Skip to content
This repository has been archived by the owner on Feb 4, 2020. It is now read-only.

Commit

Permalink
Support CLCACHE_BASEDIR in nodirect mode
Browse files Browse the repository at this point in the history
Do a simple case-insensitive find-and-replace to transform absolute
paths into relative paths within the preprocessor output that is used
to compute the hash. This makes CLCACHE_NODIRECT mode usable in the
presence of the __FILE__ macro.

Fixes a bug in _normalizedCommandLine that caused the source filename
to be included in the hash computation.
  • Loading branch information
oktal3700 committed Feb 21, 2019
1 parent dd7bf50 commit 33e5a0c
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 6 deletions.
9 changes: 5 additions & 4 deletions README.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 19 additions & 1 deletion clcache/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,19 @@ def normalizeBaseDir(baseDir):
return None


def caseInsensitiveReplace(data, old, new):
dataLower = data.lower()
oldLower = old.lower()
output = b''
index = 0
while True:
nextIndex = dataLower.find(oldLower, index)
if nextIndex < 0:
return output + data[index:]
output += data[index:nextIndex] + new
index = nextIndex + len(old)


def getCachedCompilerConsoleOutput(path):
try:
with open(path, 'rb') as f:
Expand Down Expand Up @@ -469,6 +482,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")
baseDirReplacement = BASEDIR_REPLACEMENT.encode("UTF-8")
preprocessedSourceCode = caseInsensitiveReplace(preprocessedSourceCode, baseDir, baseDirReplacement)

h = HashAlgorithm()
h.update(compilerHash.encode("UTF-8"))
h.update(' '.join(normalizedCmdLine).encode("UTF-8"))
Expand All @@ -495,7 +513,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):
Expand Down
8 changes: 8 additions & 0 deletions tests/integrationtests/basedir/nodirect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <iostream>

int main()
{
std::cout << __FILE__ << '\n';
}


9 changes: 8 additions & 1 deletion tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -1140,6 +1142,11 @@ def runCompiler():
self._runCompiler("main.cpp", ["/DRESOURCES_DIR={}".format(os.getcwd())])
self.expectMiss([runCompiler, runCompiler])

def testBasedirNoDirect(self):
def runCompiler():
self._runCompiler(os.path.join(os.getcwd(), "nodirect.cpp"), direct=False)
self.expectHit([runCompiler, runCompiler])

def testBasedirRelativeIncludeArg(self):
basedir = os.getcwd()

Expand Down
7 changes: 7 additions & 0 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ def testFilesBeneathRecursive(self):
self.assertIn(r".\d\4.txt", files)
self.assertIn(r".\d\e\5.txt", files)

def testCaseInsensitiveReplace(self):
replace = lambda s: clcache.caseInsensitiveReplace(s, b"PaTtErN", b"replacement")
self.assertEqual(replace(b"pattern may appear"), b"replacement may appear")
self.assertEqual(replace(b"infix paTTErn embed"), b"infix replacement embed")
self.assertEqual(replace(b"Pattern and PATTERN and pattern"), b"replacement and replacement and replacement")
self.assertEqual(replace(b"and finally PATTERN"), b"and finally replacement")


class TestExtendCommandLineFromEnvironment(unittest.TestCase):
def testEmpty(self):
Expand Down

0 comments on commit 33e5a0c

Please sign in to comment.