r223753 - [modules] Add experimental -fmodule-map-file-home-is-cwd flag to -cc1.

Richard Smith richard-llvm at metafoo.co.uk
Mon Dec 8 19:20:05 PST 2014


Author: rsmith
Date: Mon Dec  8 21:20:04 2014
New Revision: 223753

URL: http://llvm.org/viewvc/llvm-project?rev=223753&view=rev
Log:
[modules] Add experimental -fmodule-map-file-home-is-cwd flag to -cc1.

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).

Added:
    cfe/trunk/test/Modules/Inputs/modular_maps-moduleb-cwd.map
    cfe/trunk/test/Modules/Inputs/modular_maps/modulea-cwd.map
    cfe/trunk/test/Modules/Inputs/modular_maps/modulec-cwd.map
    cfe/trunk/test/Modules/Inputs/relative-dep-gen-cwd.modulemap
Modified:
    cfe/trunk/include/clang/Driver/CC1Options.td
    cfe/trunk/include/clang/Lex/HeaderSearch.h
    cfe/trunk/include/clang/Lex/HeaderSearchOptions.h
    cfe/trunk/include/clang/Lex/ModuleMap.h
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Lex/HeaderSearch.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/test/Modules/modular_maps.cpp
    cfe/trunk/test/Modules/relative-dep-gen.cpp

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Mon Dec  8 21:20:04 2014
@@ -337,6 +337,9 @@ def fno_modules_error_recovery : Flag<["
 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 {
 

Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Mon Dec  8 21:20:04 2014
@@ -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.
   ///

Modified: cfe/trunk/include/clang/Lex/HeaderSearchOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearchOptions.h?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearchOptions.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearchOptions.h Mon Dec  8 21:20:04 2014
@@ -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),

Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Mon Dec  8 21:20:04 2014
@@ -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();

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Mon Dec  8 21:20:04 2014
@@ -1003,6 +1003,7 @@ static void ParseHeaderSearchArgs(Header
   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 =

Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Mon Dec  8 21:20:04 2014
@@ -1113,11 +1113,10 @@ HeaderSearch::findModuleForHeader(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 *getPrivateModule
 }
 
 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(con
 }
 
 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(cons
   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 Di
     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

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Dec  8 21:20:04 2014
@@ -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(StringRe
           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::parseExternModuleD
     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
   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,

Added: cfe/trunk/test/Modules/Inputs/modular_maps-moduleb-cwd.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modular_maps-moduleb-cwd.map?rev=223753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modular_maps-moduleb-cwd.map (added)
+++ cfe/trunk/test/Modules/Inputs/modular_maps-moduleb-cwd.map Mon Dec  8 21:20:04 2014
@@ -0,0 +1,4 @@
+module B {
+  header "Inputs/modular_maps/common.h"
+  private header "Inputs/modular_maps/b.h"
+}

Added: cfe/trunk/test/Modules/Inputs/modular_maps/modulea-cwd.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modular_maps/modulea-cwd.map?rev=223753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modular_maps/modulea-cwd.map (added)
+++ cfe/trunk/test/Modules/Inputs/modular_maps/modulea-cwd.map Mon Dec  8 21:20:04 2014
@@ -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"
+

Added: cfe/trunk/test/Modules/Inputs/modular_maps/modulec-cwd.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/modular_maps/modulec-cwd.map?rev=223753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/modular_maps/modulec-cwd.map (added)
+++ cfe/trunk/test/Modules/Inputs/modular_maps/modulec-cwd.map Mon Dec  8 21:20:04 2014
@@ -0,0 +1,3 @@
+module C {
+  header "Inputs/modular_maps/c.h"
+}

Added: cfe/trunk/test/Modules/Inputs/relative-dep-gen-cwd.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/relative-dep-gen-cwd.modulemap?rev=223753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/relative-dep-gen-cwd.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/relative-dep-gen-cwd.modulemap Mon Dec  8 21:20:04 2014
@@ -0,0 +1,4 @@
+module "relative-dep-gen" {
+  header "Inputs/relative-dep-gen-1.h"
+  header "Inputs/relative-dep-gen-2.h"
+}

Modified: cfe/trunk/test/Modules/modular_maps.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/modular_maps.cpp?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/test/Modules/modular_maps.cpp (original)
+++ cfe/trunk/test/Modules/modular_maps.cpp Mon Dec  8 21:20:04 2014
@@ -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"

Modified: cfe/trunk/test/Modules/relative-dep-gen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/relative-dep-gen.cpp?rev=223753&r1=223752&r2=223753&view=diff
==============================================================================
--- cfe/trunk/test/Modules/relative-dep-gen.cpp (original)
+++ cfe/trunk/test/Modules/relative-dep-gen.cpp Mon Dec  8 21:20:04 2014
@@ -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
@@ -10,6 +11,14 @@
 // 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"
 





More information about the cfe-commits mailing list