ccc: Implement support clang PTH using gcc PCH style interface.
This requires some hackery, as gcc's PCH mechanism changes behavior,
whereas while PTH is simply a cache. Notably:
- Automatically cause clang to load a .pth file if we find one that
matches a command line -include argument (similar to how gcc
looks for .gch files).
- When generating precompiled headers, translate the suffix from .gch
to .pth (so we do not conflict with actual gcc PCH files).
- When generating precompiled headers, copy the input header to the
same location as the output PTH file. This is necessary because gcc
supports -include xxx.h even if xxx.h doesn't exist, but for clang
we need to actually have the contents of this file available.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62246 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/ccc/ccclib/Arguments.py b/tools/ccc/ccclib/Arguments.py
index 9756455..a3c25f1 100644
--- a/tools/ccc/ccclib/Arguments.py
+++ b/tools/ccc/ccclib/Arguments.py
@@ -556,7 +556,7 @@
self.addOption(JoinedOrSeparateOption('-idirafter', self.iGroup))
self.addOption(JoinedOrSeparateOption('-iquote', self.iGroup))
self.isysrootOption = self.addOption(JoinedOrSeparateOption('-isysroot', self.iGroup))
- self.addOption(JoinedOrSeparateOption('-include', self.iGroup))
+ self.includeOption = self.addOption(JoinedOrSeparateOption('-include', self.iGroup))
self.addOption(JoinedOption('-i', self.iGroup))
self.keep_private_externsOption = self.addOption(JoinedOrSeparateOption('-keep_private_externs'))
diff --git a/tools/ccc/ccclib/ToolChain.py b/tools/ccc/ccclib/ToolChain.py
index 083ce38..8511328 100644
--- a/tools/ccc/ccclib/ToolChain.py
+++ b/tools/ccc/ccclib/ToolChain.py
@@ -76,12 +76,15 @@
def selectTool(self, action):
assert isinstance(action, Phases.JobAction)
- if (self.driver.cccClang and
- self.archName == 'i386' and
- action.inputs[0].type in (Types.CType, Types.CTypeNoPP,
- Types.ObjCType, Types.ObjCTypeNoPP) and
- isinstance(action.phase, Phases.CompilePhase)):
- return self.clangTool
+ if self.driver.cccClang and self.archName == 'i386':
+ if (action.inputs[0].type in (Types.CType, Types.CTypeNoPP,
+ Types.ObjCType, Types.ObjCTypeNoPP) and
+ isinstance(action.phase, Phases.CompilePhase)):
+ return self.clangTool
+ elif (action.inputs[0].type in (Types.CHeaderType, Types.CHeaderNoPPType,
+ Types.ObjCHeaderType, Types.ObjCHeaderNoPPType) and
+ isinstance(action.phase, Phases.PrecompilePhase)):
+ return self.clangTool
return self.toolMap[action.phase.__class__]
diff --git a/tools/ccc/ccclib/Tools.py b/tools/ccc/ccclib/Tools.py
index 3341287..a12c84a 100644
--- a/tools/ccc/ccclib/Tools.py
+++ b/tools/ccc/ccclib/Tools.py
@@ -183,10 +183,28 @@
output, outputType, arglist):
cmd_args = []
+ patchOutputNameForPTH = False
if output is None:
cmd_args.append('-fsyntax-only')
elif outputType is Types.AsmTypeNoPP:
cmd_args.append('-S')
+ elif outputType is Types.PCHType:
+ # No special option needed, driven by -x. However, we
+ # patch the output name to try and not conflict with gcc.
+ patchOutputNameForPTH = True
+
+ # FIXME: This is a total hack. Copy the input header file
+ # to the output, so that it can be -include'd by clang.
+ assert len(inputs) == 1
+ assert not isinstance(output, Jobs.PipedJob)
+ assert not isinstance(inputs[0].source, Jobs.PipedJob)
+ inputPath = arglist.getValue(inputs[0].source)
+ outputPath = os.path.join(os.path.dirname(arglist.getValue(output)),
+ os.path.basename(inputPath))
+ # Only do copy when the output doesn't exist.
+ if not os.path.exists(outputPath):
+ import shutil
+ shutil.copyfile(inputPath, outputPath)
else:
raise ValueError,"Unexpected output type for clang tool."
@@ -205,6 +223,13 @@
# FIXME: Clang isn't going to accept just anything here.
arglist.addAllArgs(cmd_args, arglist.parser.iGroup)
+ # Automatically load .pth files which match -include options.
+ for arg in arglist.getArgs(arglist.parser.includeOption):
+ pthPath = arglist.getValue(arg) + '.pth'
+ if os.path.exists(pthPath):
+ cmd_args.append('-token-cache')
+ cmd_args.append(pthPath)
+
# FIXME: Dehardcode this.
cmd_args.append('-fblocks')
@@ -228,7 +253,17 @@
if arch is not None:
cmd_args.extend(arglist.render(arch))
- cmd_args.extend(arglist.render(output))
+ if isinstance(output, Jobs.PipedJob):
+ cmd_args.extend(['-o', '-'])
+ else:
+ if patchOutputNameForPTH:
+ base,suffix = os.path.splitext(arglist.getValue(output))
+ if suffix == '.gch':
+ suffix = '.pth'
+ cmd_args.append('-o')
+ cmd_args.append(base + suffix)
+ else:
+ cmd_args.extend(arglist.render(output))
for input in inputs:
cmd_args.append('-x')