diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6025,6 +6025,9 @@ HelpText<"Disable validation of precompiled headers">, MarshallingInfoFlag, "DisableValidationForModuleKind::None">, Normalizer<"makeFlagToValueNormalizer(DisableValidationForModuleKind::All)">; +def fpcm_output_path_independent : Flag<["-"], "fpcm-output-path-independent">, + HelpText<"Output a PCM/PCH file that does not write out information about its output path">, + MarshallingInfoFlag>; def fallow_pcm_with_errors : Flag<["-"], "fallow-pcm-with-compiler-errors">, HelpText<"Accept a PCM file that was created with compiler errors">, MarshallingInfoFlag>; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -344,6 +344,15 @@ /// When using -emit-module, treat the modulemap as a system module. unsigned IsSystemModule : 1; + /// Output a PCM/PCH file that does not write out information about its output + /// path. + /// + /// FIXME: This only controls whether \p ORIGINAL_PCH_DIR record is written + /// out or not. Consider either removing that record entirely if it's no + /// longer relevant or switching the default to not write it unless an option + /// is set to true. + unsigned OutputPathIndependentPCM : 1; + /// Output (and read) PCM files regardless of compiler errors. unsigned AllowPCMWithCompilerErrors : 1; @@ -513,7 +522,8 @@ ASTDumpLookups(false), BuildingImplicitModule(false), BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false), IncludeTimestamps(true), UseTemporary(true), - AllowPCMWithCompilerErrors(false), TimeTraceGranularity(500) {} + OutputPathIndependentPCM(false), AllowPCMWithCompilerErrors(false), + TimeTraceGranularity(500) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -573,7 +573,8 @@ ASTFileSignature WriteAST(Sema &SemaRef, StringRef OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors = false, - bool ShouldCacheASTInMemory = false); + bool ShouldCacheASTInMemory = false, + bool OutputPathIndependent = false); /// Emit a token. void AddToken(const Token &Tok, RecordDataImpl &Record); @@ -764,6 +765,7 @@ ASTWriter Writer; bool AllowASTWithErrors; bool ShouldCacheASTInMemory; + bool OutputPathIndependent; protected: ASTWriter &getWriter() { return Writer; } @@ -776,7 +778,8 @@ std::shared_ptr Buffer, ArrayRef> Extensions, bool AllowASTWithErrors = false, bool IncludeTimestamps = true, - bool ShouldCacheASTInMemory = false); + bool ShouldCacheASTInMemory = false, + bool OutputPathIndependent = false); ~PCHGenerator() override; void InitializeSema(Sema &S) override { SemaPtr = &S; } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -140,7 +140,8 @@ CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, FrontendOpts.ModuleFileExtensions, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, - FrontendOpts.IncludeTimestamps, +CI.getLangOpts().CacheGeneratedPCH)); + FrontendOpts.IncludeTimestamps, +CI.getLangOpts().CacheGeneratedPCH, + FrontendOpts.OutputPathIndependentPCM)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, std::string(InFile), OutputFile, std::move(OS), Buffer)); @@ -203,7 +204,9 @@ /*IncludeTimestamps=*/ +CI.getFrontendOpts().BuildingImplicitModule, /*ShouldCacheASTInMemory=*/ - +CI.getFrontendOpts().BuildingImplicitModule)); + +CI.getFrontendOpts().BuildingImplicitModule, + /*OutputPathIndependent=*/ + +CI.getFrontendOpts().OutputPathIndependentPCM)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, std::string(InFile), OutputFile, std::move(OS), Buffer)); return std::make_unique(std::move(Consumers)); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4483,7 +4483,8 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors, - bool ShouldCacheASTInMemory) { + bool ShouldCacheASTInMemory, + bool OutputPathIndependent) { WritingAST = true; ASTHasCompilerErrors = hasErrors; @@ -4499,8 +4500,9 @@ Context = &SemaRef.Context; PP = &SemaRef.PP; this->WritingModule = WritingModule; - ASTFileSignature Signature = - WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); + ASTFileSignature Signature = WriteASTCore( + SemaRef, isysroot, OutputPathIndependent ? StringRef() : OutputFile, + WritingModule); Context = nullptr; PP = nullptr; this->WritingModule = nullptr; diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -25,13 +25,14 @@ StringRef OutputFile, StringRef isysroot, std::shared_ptr Buffer, ArrayRef> Extensions, bool AllowASTWithErrors, bool IncludeTimestamps, - bool ShouldCacheASTInMemory) + bool ShouldCacheASTInMemory, bool OutputPathIndependent) : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()), SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data), Writer(Stream, this->Buffer->Data, ModuleCache, Extensions, IncludeTimestamps), AllowASTWithErrors(AllowASTWithErrors), - ShouldCacheASTInMemory(ShouldCacheASTInMemory) { + ShouldCacheASTInMemory(ShouldCacheASTInMemory), + OutputPathIndependent(OutputPathIndependent) { this->Buffer->IsComplete = false; } @@ -70,7 +71,7 @@ // For serialization we are lenient if the errors were // only warn-as-error kind. PP.getDiagnostics().hasUncompilableErrorOccurred(), - ShouldCacheASTInMemory); + ShouldCacheASTInMemory, OutputPathIndependent); Buffer->IsComplete = true; } diff --git a/clang/test/PCH/pch-output-path-independent.c b/clang/test/PCH/pch-output-path-independent.c new file mode 100644 --- /dev/null +++ b/clang/test/PCH/pch-output-path-independent.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t && mkdir -p %t/a %t/b + +// RUN: %clang_cc1 -triple x86_64-apple-macos11 -emit-pch %s -o %t/a/t1.pch -fpcm-output-path-independent +// RUN: %clang_cc1 -triple x86_64-apple-macos11 -emit-pch %s -o %t/b/t2.pch -fpcm-output-path-independent + +// RUN: diff %t/a/t1.pch %t/b/t2.pch