@@ -770,6 +770,7 @@ struct ComptimeBuildObject
770
770
bool hasAnyRefs = false ;
771
771
std::string artifactsName;
772
772
std::string dynamicLibraryPath;
773
+ std::string sourceOutputName;
773
774
std::string buildObjectName;
774
775
std::vector<std::string> importLibraries;
775
776
ObjectDefinition* definition = nullptr ;
@@ -997,6 +998,7 @@ bool ComptimePrepareHeaders(EvaluatorEnvironment& environment)
997
998
{
998
999
environment.comptimeHeadersPrepared = true ;
999
1000
environment.comptimeCombinedHeaderFilename = combinedHeaderName;
1001
+ setSourceArtifactCrc (environment, combinedHeaderRelativePath, precompiledHeaderFilename);
1000
1002
return true ;
1001
1003
}
1002
1004
@@ -1203,6 +1205,7 @@ int BuildExecuteCompileTimeFunctions(EvaluatorEnvironment& environment,
1203
1205
char sourceOutputName[MAX_PATH_LENGTH] = {0 };
1204
1206
PrintfBuffer (sourceOutputName, " %s/%s.cpp" , cakelispWorkingDir,
1205
1207
buildObject.artifactsName .c_str ());
1208
+ buildObject.sourceOutputName = sourceOutputName;
1206
1209
1207
1210
char buildObjectName[MAX_PATH_LENGTH] = {0 };
1208
1211
PrintfBuffer (buildObjectName, " %s/%s.%s" , cakelispWorkingDir,
@@ -1436,6 +1439,9 @@ int BuildExecuteCompileTimeFunctions(EvaluatorEnvironment& environment,
1436
1439
if (logging.buildProcess )
1437
1440
Logf (" Linked %s successfully\n " , buildObject.definition ->name .c_str ());
1438
1441
1442
+ setSourceArtifactCrc (environment, buildObject.sourceOutputName .c_str (),
1443
+ buildObject.dynamicLibraryPath .c_str ());
1444
+
1439
1445
DynamicLibHandle builtLib = loadDynamicLibrary (buildObject.dynamicLibraryPath .c_str ());
1440
1446
if (!builtLib)
1441
1447
{
@@ -1728,7 +1734,8 @@ bool EvaluateResolveReferences(EvaluatorEnvironment& environment)
1728
1734
{
1729
1735
// We're about to start compiling comptime code; read the cache
1730
1736
// TODO: Multiple comptime configurations require different working dir
1731
- if (!buildReadCacheFile (cakelispWorkingDir, environment.comptimeCachedCommandCrcs ))
1737
+ if (!buildReadCacheFile (cakelispWorkingDir, environment.comptimeCachedCommandCrcs ,
1738
+ environment.sourceArtifactFileCrcs ))
1732
1739
return false ;
1733
1740
1734
1741
// Print state
@@ -1881,9 +1888,10 @@ bool EvaluateResolveReferences(EvaluatorEnvironment& environment)
1881
1888
1882
1889
// Only write CRCs if we did some comptime compilation. Otherwise, the tokenizer will complain
1883
1890
// about loading a completely empty file
1884
- if (!environment.comptimeNewCommandCrcs .empty ())
1885
- buildWriteCacheFile (cakelispWorkingDir, environment.comptimeCachedCommandCrcs ,
1886
- environment.comptimeNewCommandCrcs );
1891
+ if (!environment.comptimeNewCommandCrcs .empty () || !environment.sourceArtifactFileCrcs .empty ())
1892
+ buildReadMergeWriteCacheFile (cakelispWorkingDir, environment.comptimeCachedCommandCrcs ,
1893
+ environment.comptimeNewCommandCrcs ,
1894
+ environment.sourceArtifactFileCrcs );
1887
1895
1888
1896
return errors == 0 && numBuildResolveErrors == 0 ;
1889
1897
}
@@ -2038,11 +2046,92 @@ void resetGeneratorOutput(GeneratorOutput& output)
2038
2046
output.imports .clear ();
2039
2047
}
2040
2048
2049
+ uint32_t cacheUpdateFileCrc (EvaluatorEnvironment& environment, const char * filename)
2050
+ {
2051
+ uint32_t sourceCrc = getFileCrc32 (filename);
2052
+ environment.cachedIntraBuildFileCrcs [filename] = sourceCrc;
2053
+ return sourceCrc;
2054
+ }
2055
+
2056
+ uint32_t getSourceArtifactKey (const char * source,
2057
+ const char * artifact)
2058
+ {
2059
+ uint32_t artifactSourceNameCrc = 0 ;
2060
+ crc32 (artifact, strlen (artifact), &artifactSourceNameCrc);
2061
+ crc32 (source, strlen (source), &artifactSourceNameCrc);
2062
+ return artifactSourceNameCrc;
2063
+ }
2064
+
2065
+ // Call after an artifact has been built such to have source's latest changes
2066
+ void setSourceArtifactCrc (EvaluatorEnvironment& environment, const char * source,
2067
+ const char * artifact)
2068
+ {
2069
+ uint32_t sourceCrc = 0 ;
2070
+ {
2071
+ ArtifactCrcTable::iterator findIt = environment.cachedIntraBuildFileCrcs .find (source);
2072
+ if (findIt != environment.cachedIntraBuildFileCrcs .end ())
2073
+ sourceCrc = findIt->second ;
2074
+ else
2075
+ sourceCrc = cacheUpdateFileCrc (environment, source);
2076
+ }
2077
+ uint32_t artifactSourceNameCrc = getSourceArtifactKey (source, artifact);
2078
+
2079
+ // We haven't recorded this association yet, so we cannot confidently say artifact is up to
2080
+ // date with source's changes. We now record the association with the assumption that by
2081
+ // virtue of this function returning false, artifact will be updated with source's changes.
2082
+ // if (logging.buildReasons)
2083
+ // Logf("Artifact %s now has source %s changes (%u)\n", artifact, source, sourceCrc);
2084
+ environment.sourceArtifactFileCrcs [artifactSourceNameCrc] = sourceCrc;
2085
+ }
2086
+
2087
+ // If either of the files have a CRC that doesn't match what we had last build, we need to re-build
2088
+ bool crcsMatchExpectedUpdateCrcPairing (EvaluatorEnvironment& environment, const char * source,
2089
+ const char * artifact)
2090
+ {
2091
+ uint32_t artifactSourceNameCrc = getSourceArtifactKey (source, artifact);
2092
+ HashedSourceArtifactCrcTable::iterator findIt =
2093
+ environment.sourceArtifactFileCrcs .find (artifactSourceNameCrc);
2094
+ if (findIt == environment.sourceArtifactFileCrcs .end ())
2095
+ {
2096
+ if (logging.buildReasons )
2097
+ Logf (
2098
+ " Artifact %s was not associated with source %s before. There are %d associations\n " ,
2099
+ artifact, source, (int )environment.sourceArtifactFileCrcs .size ());
2100
+ // We didn't know previously that artifact depends on source
2101
+ return false ;
2102
+ }
2103
+ else
2104
+ {
2105
+ uint32_t sourceCrc = 0 ;
2106
+ {
2107
+ ArtifactCrcTable::iterator findIt = environment.cachedIntraBuildFileCrcs .find (source);
2108
+ if (findIt != environment.cachedIntraBuildFileCrcs .end ())
2109
+ sourceCrc = findIt->second ;
2110
+ else
2111
+ sourceCrc = cacheUpdateFileCrc (environment, source);
2112
+ }
2113
+ bool sourceCrcMatchesLastUse = sourceCrc == findIt->second ;
2114
+ if (logging.buildReasons )
2115
+ {
2116
+ if (sourceCrcMatchesLastUse)
2117
+ {
2118
+ // Logf("Artifact %s not rebuilding because source %s CRC is same as last time
2119
+ // (%u)\n", artifact, source, sourceCrc);
2120
+ }
2121
+ else
2122
+ Logf (" Artifact %s needs to build because source %s CRC is now %u\n " , artifact,
2123
+ source, sourceCrc);
2124
+ }
2125
+ return sourceCrcMatchesLastUse;
2126
+ }
2127
+ }
2128
+
2041
2129
bool canUseCachedFile (EvaluatorEnvironment& environment, const char * filename,
2042
2130
const char * reference)
2043
2131
{
2044
2132
if (environment.useCachedFiles )
2045
- return !fileIsMoreRecentlyModified (filename, reference);
2133
+ return !fileIsMoreRecentlyModified (filename, reference) &&
2134
+ crcsMatchExpectedUpdateCrcPairing (environment, filename, reference);
2046
2135
else
2047
2136
return false ;
2048
2137
}
0 commit comments