For C, unfortunately, the situation is made more complex by the problem of claiming. Since header files may participate in many compilations, indexing them directly would result in a lot of duplicate indexer output. To work around this, the C++ indexer uses a dynamic "claiming" mechanism to ensure the header is only indexed once for each of its variations (e.g., how it is expanded under the preprocessor in different files). The claiming mechanism makes the outputs not directly cacheable, since the claim assignment is not easily recoverable after the fact.
For languages without this issue, for example Java and Go, indexer outputs can be cached and reused.
Updating the graph takes a bit more than simply "adding in" the updated data, since the new data may have removed entries that were previously there. Also, a simple change to one compilation unit may require large changes to the rest of the graph, so updating it completely generally requires scanning the whole graph. (Consider, for example, a change that adds a new overload that will be preferred by calls from existing code that has not otherwise changed).
So: Caching doesn't eliminate the need to rebuild the graph, but it can (where applicable) reduce the amount of indexing you have to do for a build.
–M