aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-11-29 19:06:37 +0000
committerDouglas Gregor <dgregor@apple.com>2011-11-29 19:06:37 +0000
commitf9e357d8a66c606a86a6e1aef678898b8843bd30 (patch)
tree7ab77c3935faa49ea645bd0de570bbe875e5d8c9
parent933e7a61da12400d8971890719cb03d68c1b02eb (diff)
Teach the module import mechanism how to rebuild modules expressed via
module map, rather than assuming that there is an umbrella header. This allows us to automatically build umbrella-less modules. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145415 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Lex/ModuleMap.h11
-rw-r--r--lib/Frontend/CompilerInstance.cpp72
-rw-r--r--lib/Lex/ModuleMap.cpp9
-rw-r--r--test/Modules/normal-module-map.cpp4
4 files changed, 83 insertions, 13 deletions
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index d38bbe672b..4f89f1e728 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -166,7 +166,16 @@ public:
/// framework directory.
Module *inferFrameworkModule(StringRef ModuleName,
const DirectoryEntry *FrameworkDir);
-
+
+ /// \brief Retrieve the module map file containing the definition of the given
+ /// module.
+ ///
+ /// \param Module The module whose module map file will be returned, if known.
+ ///
+ /// \returns The file entry for the module map file containing the given
+ /// module, or NULL if the module definition was inferred.
+ const FileEntry *getContainingModuleMapFile(ModuleMap::Module *Module);
+
/// \brief Parse the given module map file, and record any modules we
/// encounter.
///
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index c6a5583984..433b2cceb7 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -710,6 +710,21 @@ static void doCompileModule(void *UserData) {
}
namespace {
+ struct CompileModuleMapData {
+ CompilerInstance &Instance;
+ GenerateModuleAction &CreateModuleAction;
+ };
+}
+
+/// \brief Helper function that executes the module-generating action under
+/// a crash recovery context.
+static void doCompileMapModule(void *UserData) {
+ CompileModuleMapData &Data
+ = *reinterpret_cast<CompileModuleMapData *>(UserData);
+ Data.Instance.ExecuteAction(Data.CreateModuleAction);
+}
+
+namespace {
/// \brief Class that manages the creation of a lock file to aid
/// implicit coordination between different processes.
///
@@ -958,17 +973,11 @@ void LockFileManager::waitForUnlock() {
// Give up.
}
-/// \brief Compile a module file for the given module name with the given
-/// umbrella header, using the options provided by the importing compiler
-/// instance.
+/// \brief Compile a module file for the given module, using the options
+/// provided by the importing compiler instance.
static void compileModule(CompilerInstance &ImportingInstance,
ModuleMap::Module *Module,
StringRef ModuleFileName) {
- // FIXME: Currently, we can only handle modules that have an umbrella
- // header. That's lame.
- if (!Module->UmbrellaHeader)
- return;
-
LockFileManager Locked(ModuleFileName);
switch (Locked) {
case LockFileManager::LFS_Error:
@@ -985,6 +994,9 @@ static void compileModule(CompilerInstance &ImportingInstance,
break;
}
+ ModuleMap &ModMap
+ = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
+
// Construct a compiler invocation for creating this module.
llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation
(new CompilerInvocation(ImportingInstance.getInvocation()));
@@ -1002,6 +1014,50 @@ static void compileModule(CompilerInstance &ImportingInstance,
Invocation->getPreprocessorOpts().ModuleBuildPath
.push_back(Module->getTopLevelModuleName());
+ if (const FileEntry *ModuleMapFile
+ = ModMap.getContainingModuleMapFile(Module)) {
+ // If there is a module map file, build the module using the module map.
+ // Set up the inputs/outputs so that we build the module from its umbrella
+ // header.
+ FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
+ FrontendOpts.OutputFile = ModuleFileName.str();
+ FrontendOpts.DisableFree = false;
+ FrontendOpts.Inputs.clear();
+ FrontendOpts.Inputs.push_back(
+ std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()),
+ ModuleMapFile->getName()));
+
+ Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
+
+
+ assert(ImportingInstance.getInvocation().getModuleHash() ==
+ Invocation->getModuleHash() && "Module hash mismatch!");
+
+ // Construct a compiler instance that will be used to actually create the
+ // module.
+ CompilerInstance Instance;
+ Instance.setInvocation(&*Invocation);
+ Instance.createDiagnostics(/*argc=*/0, /*argv=*/0,
+ &ImportingInstance.getDiagnosticClient(),
+ /*ShouldOwnClient=*/true,
+ /*ShouldCloneClient=*/true);
+
+ // Construct a module-generating action.
+ GenerateModuleAction CreateModuleAction;
+
+ // Execute the action to actually build the module in-place. Use a separate
+ // thread so that we get a stack large enough.
+ const unsigned ThreadStackSize = 8 << 20;
+ llvm::CrashRecoveryContext CRC;
+ CompileModuleMapData Data = { Instance, CreateModuleAction };
+ CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize);
+ return;
+ }
+
+ // FIXME: Temporary fallback: generate the module from the umbrella header.
+ // This is currently used when we infer a module map from a framework.
+ assert(Module->UmbrellaHeader && "Inferred module map needs umbrella header");
+
// Set up the inputs/outputs so that we build the module from its umbrella
// header.
FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index a25c93bfca..3cc6478acf 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -206,6 +206,15 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
return Result;
}
+const FileEntry *
+ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) {
+ if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
+ return 0;
+
+ return SourceMgr->getFileEntryForID(
+ SourceMgr->getFileID(Module->DefinitionLoc));
+}
+
void ModuleMap::dump() {
llvm::errs() << "Modules:";
for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
diff --git a/test/Modules/normal-module-map.cpp b/test/Modules/normal-module-map.cpp
index c87657f5a9..19294950d4 100644
--- a/test/Modules/normal-module-map.cpp
+++ b/test/Modules/normal-module-map.cpp
@@ -1,8 +1,4 @@
// RUN: rm -rf %t
-// FIXME: Eventually, we should be able to remove these explicit module creation lines
-// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libA -emit-module-from-map %S/Inputs/normal-module-map/module.map
-// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libB -emit-module-from-map %S/Inputs/normal-module-map/module.map
-// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fmodule-name=libNested -emit-module-from-map %S/Inputs/normal-module-map/nested/module.map
// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -I %S/Inputs/normal-module-map %s -verify
#include "Umbrella/umbrella_sub.h"