diff --git a/README.asciidoc b/README.asciidoc index a0f4259f..d9c85280 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -86,10 +86,11 @@ CLCACHE_NODIRECT:: key. Use this if you experience problems with direct mode or if you need built-in macroses like \__TIME__ to work correctly. CLCACHE_BASEDIR:: - Has effect only when direct mode is on. Set this to path to root directory - of your project. This allows clcache to cache relative paths, so if you - move your project to different directory, clcache will produce cache hits as - before. + Set this to path to root directory of your project. In direct mode, this allows + clcache to cache relative paths, so if you move your project to different directory, + clcache will produce cache hits as before. When direct mode is disabled, clcache will + translate any absolute paths in the preprocessor output into relative paths before + computing the hash. CLCACHE_OBJECT_CACHE_TIMEOUT_MS:: Overrides the default ObjectCacheLock timeout (Default is 10 * 1000 ms). The ObjectCacheLock is used to give exclusive access to the cache, which is diff --git a/clcache/__main__.py b/clcache/__main__.py index 94af73f1..db5f095e 100644 --- a/clcache/__main__.py +++ b/clcache/__main__.py @@ -469,6 +469,11 @@ def computeKeyNodirect(compilerBinary, commandLine, environment): compilerHash = getCompilerHash(compilerBinary) normalizedCmdLine = CompilerArtifactsRepository._normalizedCommandLine(commandLine) + if "CLCACHE_BASEDIR" in os.environ: + baseDir = normalizeBaseDir(os.environ["CLCACHE_BASEDIR"]).replace("\\", "\\\\").encode("UTF-8") + newBaseDir = BASEDIR_REPLACEMENT.encode("UTF-8") + preprocessedSourceCode = re.sub(re.escape(baseDir), newBaseDir, preprocessedSourceCode, flags=re.IGNORECASE) + h = HashAlgorithm() h.update(compilerHash.encode("UTF-8")) h.update(' '.join(normalizedCmdLine).encode("UTF-8")) @@ -495,7 +500,7 @@ def _normalizedCommandLine(cmdline): argsToStrip += ("MP",) return [arg for arg in cmdline - if not (arg[0] in "/-" and arg[1:].startswith(argsToStrip))] + if arg[0] in "/-" and not arg[1:].startswith(argsToStrip)] class CacheFileStrategy: def __init__(self, cacheDirectory=None): diff --git a/tests/integrationtests/basedir/filemacro.cpp b/tests/integrationtests/basedir/filemacro.cpp new file mode 100644 index 00000000..4d2c53a3 --- /dev/null +++ b/tests/integrationtests/basedir/filemacro.cpp @@ -0,0 +1,8 @@ +#include + +int main() +{ + std::cout << __FILE__ << '\n'; +} + + diff --git a/tests/test_integration.py b/tests/test_integration.py index ced806ec..2c9af431 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1069,12 +1069,14 @@ def tearDown(self): os.chdir(self.savedCwd) self.tempDir.cleanup() - def _runCompiler(self, cppFile, extraArgs=None): + def _runCompiler(self, cppFile, extraArgs=None, direct=True): cmd = CLCACHE_CMD + ["/nologo", "/EHsc", "/c"] if extraArgs: cmd.extend(extraArgs) cmd.append(cppFile) env = dict(os.environ, CLCACHE_DIR=self.clcacheDir, CLCACHE_BASEDIR=os.getcwd()) + if not direct: + env["CLCACHE_NODIRECT"] = "1" self.assertEqual(subprocess.call(cmd, env=env), 0) def expectHit(self, runCompiler): @@ -1140,6 +1142,16 @@ def runCompiler(): self._runCompiler("main.cpp", ["/DRESOURCES_DIR={}".format(os.getcwd())]) self.expectMiss([runCompiler, runCompiler]) + def testBasedirNoDirectAbsolutePath(self): + def runCompiler(): + self._runCompiler(os.path.join(os.getcwd(), "main.cpp"), direct=False) + self.expectHit([runCompiler, runCompiler]) + + def testBasedirNoDirectFileMacro(self): + def runCompiler(): + self._runCompiler(os.path.join(os.getcwd(), "filemacro.cpp"), direct=False) + self.expectHit([runCompiler, runCompiler]) + def testBasedirRelativeIncludeArg(self): basedir = os.getcwd()