]> granicus.if.org Git - clang/commitdiff
[modules] Add experimental -fmodule-map-file-home-is-cwd flag to -cc1.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 9 Dec 2014 03:20:04 +0000 (03:20 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 9 Dec 2014 03:20:04 +0000 (03:20 +0000)
For files named by -fmodule-map-file=, and files found by 'extern module'
directives, this flag specifies that we should resolve filenames relative to
the current working directory rather than relative to the directory in which
the module map file resides. This is aimed at fixing path handling, in
particular for relative -I paths, when building modules that represent
components of the current project (rather than libraries installed on the
current system, which the current project has as dependencies, where we'd
typically expect the module map files to be looked up implicitly).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@223753 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/clang/Driver/CC1Options.td
include/clang/Lex/HeaderSearch.h
include/clang/Lex/HeaderSearchOptions.h
include/clang/Lex/ModuleMap.h
lib/Frontend/CompilerInvocation.cpp
lib/Lex/HeaderSearch.cpp
lib/Lex/ModuleMap.cpp
test/Modules/Inputs/modular_maps-moduleb-cwd.map [new file with mode: 0644]
test/Modules/Inputs/modular_maps/modulea-cwd.map [new file with mode: 0644]
test/Modules/Inputs/modular_maps/modulec-cwd.map [new file with mode: 0644]
test/Modules/Inputs/relative-dep-gen-cwd.modulemap [new file with mode: 0644]
test/Modules/modular_maps.cpp
test/Modules/relative-dep-gen.cpp

index fbab14b51be802ec9d905951146e5162def60bb0..10bda46012dd1b5cc336008395e884744be607f6 100644 (file)
@@ -337,6 +337,9 @@ def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">,
 def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">,
   MetaVarName<"<name>">,
   HelpText<"Specify the name of the module whose implementation file this is">;
+def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">,
+  HelpText<"Use the current working directory as the home directory of "
+           "module maps specified by -fmodule-map-file=<FILE>">;
 
 let Group = Action_Group in {
 
index 190a0c9833934b8f2dad568cd143b659565ed0f8..158f67d40b494c7b9c0726dfce21a8222b7f9fec 100644 (file)
@@ -640,7 +640,8 @@ private:
   };
 
   LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
-                                            bool IsSystem);
+                                            bool IsSystem,
+                                            const DirectoryEntry *Dir);
 
   /// \brief Try to load the module map file in the given directory.
   ///
index 4e6e46939f785f70d5d415c11bd8f5ac8140ef04..775943de81698c1e576c5f38957f3e51cb7eb7ae 100644 (file)
@@ -101,6 +101,15 @@ public:
   /// \brief Interpret module maps.  This option is implied by full modules.
   unsigned ModuleMaps : 1;
 
+  /// \brief Set the 'home directory' of a module map file to the current
+  /// working directory (or the home directory of the module map file that
+  /// contained the 'extern module' directive importing this module map file
+  /// if any) rather than the directory containing the module map file.
+  //
+  /// The home directory is where we look for files named in the module map
+  /// file.
+  unsigned ModuleMapFileHomeIsCwd : 1;
+
   /// \brief The interval (in seconds) between pruning operations.
   ///
   /// This operation is expensive, because it requires Clang to walk through
@@ -158,6 +167,7 @@ public:
 public:
   HeaderSearchOptions(StringRef _Sysroot = "/")
     : Sysroot(_Sysroot), DisableModuleHash(0), ModuleMaps(0),
+      ModuleMapFileHomeIsCwd(0),
       ModuleCachePruneInterval(7*24*60*60),
       ModuleCachePruneAfter(31*24*60*60),
       BuildSessionTimestamp(0),
index aad83c1fce28b53da713ae9d8041b4364e305a4e..b31158b9d293f23ac5a36c016331b478c5fd64bf 100644 (file)
@@ -454,8 +454,12 @@ public:
   /// \param IsSystem Whether this module map file is in a system header
   /// directory, and therefore should be considered a system module.
   ///
+  /// \param HomeDir The directory in which relative paths within this module
+  ///        map file will be resolved.
+  ///
   /// \returns true if an error occurred, false otherwise.
-  bool parseModuleMapFile(const FileEntry *File, bool IsSystem);
+  bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
+                          const DirectoryEntry *HomeDir);
     
   /// \brief Dump the contents of the module map, for debugging purposes.
   void dump();
index f01663858e0a0b446af54e999cc641f6e11f6c35..59095941a83c9077bf5669317ccf742a1e0ade24 100644 (file)
@@ -1003,6 +1003,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
   Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
   // -fmodules implies -fmodule-maps
   Opts.ModuleMaps = Args.hasArg(OPT_fmodule_maps) || Args.hasArg(OPT_fmodules);
+  Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd);
   Opts.ModuleCachePruneInterval =
       getLastArgIntValue(Args, OPT_fmodules_prune_interval, 7 * 24 * 60 * 60);
   Opts.ModuleCachePruneAfter =
index a3f3737521ec686130e57421c115bf3760856bef..02fd87c8226d3f4baf2641d0531be9cb7c8e38bd 100644 (file)
@@ -1113,11 +1113,10 @@ HeaderSearch::findModuleForHeader(const FileEntry *File) const {
   return ModMap.findModuleForHeader(File);
 }
 
-static const FileEntry *getPrivateModuleMap(StringRef ModuleMapPath,
-                                            const DirectoryEntry *Directory,
+static const FileEntry *getPrivateModuleMap(const FileEntry *File,
                                             FileManager &FileMgr) {
-  StringRef Filename = llvm::sys::path::filename(ModuleMapPath);
-  SmallString<128>  PrivateFilename(Directory->getName());
+  StringRef Filename = llvm::sys::path::filename(File->getName());
+  SmallString<128>  PrivateFilename(File->getDir()->getName());
   if (Filename == "module.map")
     llvm::sys::path::append(PrivateFilename, "module_private.map");
   else if (Filename == "module.modulemap")
@@ -1128,7 +1127,25 @@ static const FileEntry *getPrivateModuleMap(StringRef ModuleMapPath,
 }
 
 bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) {
-  switch (loadModuleMapFileImpl(File, IsSystem)) {
+  // Find the directory for the module. For frameworks, that may require going
+  // up from the 'Modules' directory.
+  const DirectoryEntry *Dir = nullptr;
+  if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd)
+    Dir = FileMgr.getDirectory(".");
+  else {
+    Dir = File->getDir();
+    StringRef DirName(Dir->getName());
+    if (llvm::sys::path::filename(DirName) == "Modules") {
+      DirName = llvm::sys::path::parent_path(DirName);
+      if (DirName.endswith(".framework"))
+        Dir = FileMgr.getDirectory(DirName);
+      // FIXME: This assert can fail if there's a race between the above check
+      // and the removal of the directory.
+      assert(Dir && "parent must exist");
+    }
+  }
+
+  switch (loadModuleMapFileImpl(File, IsSystem, Dir)) {
   case LMM_AlreadyLoaded:
   case LMM_NewlyLoaded:
     return false;
@@ -1140,7 +1157,8 @@ bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem) {
 }
 
 HeaderSearch::LoadModuleMapResult
-HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) {
+HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem,
+                                    const DirectoryEntry *Dir) {
   assert(File && "expected FileEntry");
 
   // Check whether we've already loaded this module map, and mark it as being
@@ -1149,15 +1167,14 @@ HeaderSearch::loadModuleMapFileImpl(const FileEntry *File, bool IsSystem) {
   if (!AddResult.second)
     return AddResult.first->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
 
-  if (ModMap.parseModuleMapFile(File, IsSystem)) {
+  if (ModMap.parseModuleMapFile(File, IsSystem, Dir)) {
     LoadedModuleMaps[File] = false;
     return LMM_InvalidModuleMap;
   }
 
   // Try to load a corresponding private module map.
-  if (const FileEntry *PMMFile =
-          getPrivateModuleMap(File->getName(), File->getDir(), FileMgr)) {
-    if (ModMap.parseModuleMapFile(PMMFile, IsSystem)) {
+  if (const FileEntry *PMMFile = getPrivateModuleMap(File, FileMgr)) {
+    if (ModMap.parseModuleMapFile(PMMFile, IsSystem, Dir)) {
       LoadedModuleMaps[File] = false;
       return LMM_InvalidModuleMap;
     }
@@ -1231,7 +1248,8 @@ HeaderSearch::loadModuleMapFile(const DirectoryEntry *Dir, bool IsSystem,
     return KnownDir->second ? LMM_AlreadyLoaded : LMM_InvalidModuleMap;
 
   if (const FileEntry *ModuleMapFile = lookupModuleMapFile(Dir, IsFramework)) {
-    LoadModuleMapResult Result = loadModuleMapFileImpl(ModuleMapFile, IsSystem);
+    LoadModuleMapResult Result =
+        loadModuleMapFileImpl(ModuleMapFile, IsSystem, Dir);
     // Add Dir explicitly in case ModuleMapFile is in a subdirectory.
     // E.g. Foo.framework/Modules/module.modulemap
     //      ^Dir                  ^ModuleMapFile
index 9ac554ae96c3a41d010a6ec8967ab88af7d0bc38..c5e317a0ba602dc20a435162344759380b818aec 100644 (file)
@@ -19,6 +19,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/LiteralSupport.h"
@@ -648,7 +649,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
           bool IsFrameworkDir = Parent.endswith(".framework");
           if (const FileEntry *ModMapFile =
                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
-            parseModuleMapFile(ModMapFile, IsSystem);
+            parseModuleMapFile(ModMapFile, IsSystem, ParentDir);
             inferred = InferredDirectories.find(ParentDir);
           }
 
@@ -1024,7 +1025,8 @@ namespace clang {
     /// \brief The current module map file.
     const FileEntry *ModuleMapFile;
     
-    /// \brief The directory that this module map resides in.
+    /// \brief The directory that file names in this module map file should
+    /// be resolved relative to.
     const DirectoryEntry *Directory;
 
     /// \brief The directory containing Clang-supplied headers.
@@ -1591,7 +1593,11 @@ void ModuleMapParser::parseExternModuleDecl() {
     FileNameRef = ModuleMapFileName.str();
   }
   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
-    Map.parseModuleMapFile(File, /*IsSystem=*/false);
+    Map.parseModuleMapFile(
+        File, /*IsSystem=*/false,
+        Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
+            ? Directory
+            : File->getDir());
 }
 
 /// \brief Parse a requires declaration.
@@ -2333,7 +2339,8 @@ bool ModuleMapParser::parseModuleMapFile() {
   } while (true);
 }
 
-bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) {
+bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
+                                   const DirectoryEntry *Dir) {
   llvm::DenseMap<const FileEntry *, bool>::iterator Known
     = ParsedModuleMap.find(File);
   if (Known != ParsedModuleMap.end())
@@ -2346,17 +2353,6 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) {
   if (!Buffer)
     return ParsedModuleMap[File] = true;
 
-  // Find the directory for the module. For frameworks, that may require going
-  // up from the 'Modules' directory.
-  const DirectoryEntry *Dir = File->getDir();
-  StringRef DirName(Dir->getName());
-  if (llvm::sys::path::filename(DirName) == "Modules") {
-    DirName = llvm::sys::path::parent_path(DirName);
-    if (DirName.endswith(".framework"))
-      Dir = SourceMgr.getFileManager().getDirectory(DirName);
-    assert(Dir && "parent must exist");
-  }
-  
   // Parse this module map file.
   Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
diff --git a/test/Modules/Inputs/modular_maps-moduleb-cwd.map b/test/Modules/Inputs/modular_maps-moduleb-cwd.map
new file mode 100644 (file)
index 0000000..1ff307f
--- /dev/null
@@ -0,0 +1,4 @@
+module B {
+  header "Inputs/modular_maps/common.h"
+  private header "Inputs/modular_maps/b.h"
+}
diff --git a/test/Modules/Inputs/modular_maps/modulea-cwd.map b/test/Modules/Inputs/modular_maps/modulea-cwd.map
new file mode 100644 (file)
index 0000000..10be523
--- /dev/null
@@ -0,0 +1,7 @@
+module A {
+  header "Inputs/modular_maps/common.h"
+  header "Inputs/modular_maps/a.h"
+}
+
+extern module B "Inputs/modular_maps-moduleb-cwd.map"
+
diff --git a/test/Modules/Inputs/modular_maps/modulec-cwd.map b/test/Modules/Inputs/modular_maps/modulec-cwd.map
new file mode 100644 (file)
index 0000000..ca38b54
--- /dev/null
@@ -0,0 +1,3 @@
+module C {
+  header "Inputs/modular_maps/c.h"
+}
diff --git a/test/Modules/Inputs/relative-dep-gen-cwd.modulemap b/test/Modules/Inputs/relative-dep-gen-cwd.modulemap
new file mode 100644 (file)
index 0000000..b8678d3
--- /dev/null
@@ -0,0 +1,4 @@
+module "relative-dep-gen" {
+  header "Inputs/relative-dep-gen-1.h"
+  header "Inputs/relative-dep-gen-2.h"
+}
index 484e727c13e1ddff47ffe6a9f8ca18da08033fdf..3b6afc7552d6f89d518ca266c33d08cadbdf4318 100644 (file)
@@ -1,6 +1,15 @@
 // RUN: rm -rf %t
+//
 // RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=%S/Inputs/modular_maps/modulea.map -fmodule-map-file=%S/Inputs/modular_maps/modulec.map -I %S/Inputs/modular_maps %s -verify
 // RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=%S/Inputs/modular_maps/modulec.map -fmodule-map-file=%S/Inputs/modular_maps/modulea.map -I %S/Inputs/modular_maps %s -verify
+//
+// RUN: cd %S
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulea.map -fmodule-map-file=Inputs/modular_maps/modulec.map -I Inputs/modular_maps %s -verify
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulec.map -fmodule-map-file=Inputs/modular_maps/modulea.map -I Inputs/modular_maps %s -verify
+//
+// RUN: cd %S
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulea-cwd.map -fmodule-map-file=Inputs/modular_maps/modulec-cwd.map -I Inputs/modular_maps %s -verify -fmodule-map-file-home-is-cwd
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=Inputs/modular_maps/modulec-cwd.map -fmodule-map-file=Inputs/modular_maps/modulea-cwd.map -I Inputs/modular_maps %s -verify -fmodule-map-file-home-is-cwd
 
 #include "common.h"
 #include "a.h"
index 9a52f34a0166c56dec8d0681ed5125c826f5dfe9..c8171777154a80957dc21696713ec09b1a9eb432 100644 (file)
@@ -3,6 +3,7 @@
 // RUN: cd %S
 // RUN: rm -rf %t
 // RUN: mkdir %t
+//
 // RUN: %clang_cc1 -cc1 -fmodule-name=relative-dep-gen -emit-module -x c++ Inputs/relative-dep-gen.modulemap -dependency-file %t/build.d -MT mod.pcm -o %t/mod.pcm
 // RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen.modulemap -fmodule-file=%t/mod.pcm -dependency-file %t/use-explicit.d -MT use.o relative-dep-gen.cpp -fsyntax-only
 // RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen.modulemap -dependency-file %t/use-implicit.d relative-dep-gen.cpp -MT use.o -fsyntax-only
 // RUN: FileCheck --check-prefix=CHECK-BUILD %s < %t/build.d
 // RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-explicit.d
 // RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-implicit.d
+//
+// RUN: %clang_cc1 -cc1 -fmodule-name=relative-dep-gen -emit-module -x c++ Inputs/relative-dep-gen-cwd.modulemap -dependency-file %t/build-cwd.d -MT mod.pcm -o %t/mod-cwd.pcm -fmodule-map-file-home-is-cwd
+// RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen-cwd.modulemap -fmodule-file=%t/mod-cwd.pcm -dependency-file %t/use-explicit-cwd.d -MT use.o relative-dep-gen.cpp -fsyntax-only -fmodule-map-file-home-is-cwd
+// RUN: %clang_cc1 -cc1 -fmodule-map-file=Inputs/relative-dep-gen-cwd.modulemap -dependency-file %t/use-implicit-cwd.d relative-dep-gen.cpp -MT use.o -fsyntax-only -fmodule-map-file-home-is-cwd
+//
+// RUN: FileCheck --check-prefix=CHECK-BUILD %s < %t/build-cwd.d
+// RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-explicit-cwd.d
+// RUN: FileCheck --check-prefix=CHECK-USE %s < %t/use-implicit-cwd.d
 
 #include "Inputs/relative-dep-gen-1.h"