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 @@ -5609,6 +5609,10 @@ HelpText<"Use the current working directory as the home directory of " "module maps specified by -fmodule-map-file=">, MarshallingInfoFlag>; +def fmodule_file_home_is_cwd : Flag<["-"], "fmodule-file-home-is-cwd">, + HelpText<"Use the current working directory as the base directory of " + "compiled module files.">, + MarshallingInfoFlag>; def fmodule_feature : Separate<["-"], "fmodule-feature">, MetaVarName<"">, HelpText<"Enable in module map requires declarations">, diff --git a/clang/include/clang/Lex/HeaderSearchOptions.h b/clang/include/clang/Lex/HeaderSearchOptions.h --- a/clang/include/clang/Lex/HeaderSearchOptions.h +++ b/clang/include/clang/Lex/HeaderSearchOptions.h @@ -143,6 +143,12 @@ /// file. unsigned ModuleMapFileHomeIsCwd : 1; + /// Set the base path of a built module file to be the current working + /// directory. This is useful for sharing module files across machines + /// that build with different paths without having to rewrite all + /// modulemap files to have working directory relative paths. + unsigned ModuleFileHomeIsCwd : 1; + /// Also search for prebuilt implicit modules in the prebuilt module cache /// path. unsigned EnablePrebuiltImplicitModules : 1; @@ -222,9 +228,9 @@ HeaderSearchOptions(StringRef _Sysroot = "/") : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false), ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false), - EnablePrebuiltImplicitModules(false), UseBuiltinIncludes(true), - UseStandardSystemIncludes(true), UseStandardCXXIncludes(true), - UseLibcxx(false), Verbose(false), + ModuleFileHomeIsCwd(false), EnablePrebuiltImplicitModules(false), + UseBuiltinIncludes(true), UseStandardSystemIncludes(true), + UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false), ModulesValidateOncePerBuildSession(false), ModulesValidateSystemHeaders(false), ValidateASTInputFilesContent(false), UseDebugInfo(false), 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 @@ -1223,7 +1223,15 @@ Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name); } - if (WritingModule && WritingModule->Directory) { + if (WritingModule && + PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) { + // Use the current working directory as the base path for all inputs. + auto *CWD = + Context.getSourceManager().getFileManager().getDirectory(".").get(); + SmallString<128> BaseDir(CWD->getName()); + cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir); + BaseDirectory.assign(BaseDir.begin(), BaseDir.end()); + } else if (WritingModule && WritingModule->Directory) { SmallString<128> BaseDir(WritingModule->Directory->getName()); cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir); diff --git a/clang/test/Modules/module-file-home-is-cwd.m b/clang/test/Modules/module-file-home-is-cwd.m new file mode 100644 --- /dev/null +++ b/clang/test/Modules/module-file-home-is-cwd.m @@ -0,0 +1,8 @@ +// RUN: cd %S +// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-file-home-is-cwd -fmodule-name=libA -emit-module Inputs/normal-module-map/module.map -o %t/mod.pcm +// RUN: llvm-bcanalyzer --dump --disable-histogram %t/mod.pcm | FileCheck %s + +// CHECK: blob data = 'Inputs{{/|\\}}normal-module-map{{/|\\}}a1.h' +// CHECK: blob data = 'Inputs{{/|\\}}normal-module-map{{/|\\}}a2.h' +// CHECK: blob data = 'Inputs{{/|\\}}normal-module-map{{/|\\}}module.map' +// CHECK-NOT: MODULE_DIRECTORY