diff options
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 118 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 54 |
2 files changed, 78 insertions, 94 deletions
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 433b2cceb7..35f82174b2 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -696,20 +696,6 @@ static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) { } namespace { - struct CompileModuleData { - CompilerInstance &Instance; - GeneratePCHAction &CreateModuleAction; - }; -} - -/// \brief Helper function that executes the module-generating action under -/// a crash recovery context. -static void doCompileModule(void *UserData) { - CompileModuleData &Data = *reinterpret_cast<CompileModuleData *>(UserData); - Data.Instance.ExecuteAction(Data.CreateModuleAction); -} - -namespace { struct CompileModuleMapData { CompilerInstance &Instance; GenerateModuleAction &CreateModuleAction; @@ -1001,79 +987,60 @@ static void compileModule(CompilerInstance &ImportingInstance, llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation (new CompilerInvocation(ImportingInstance.getInvocation())); + PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); + // For any options that aren't intended to affect how a module is built, // reset them to their default values. Invocation->getLangOpts()->resetNonModularOptions(); - Invocation->getPreprocessorOpts().resetNonModularOptions(); + PPOpts.resetNonModularOptions(); // Note the name of the module we're building. Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName(); // Note that this module is part of the module build path, so that we // can detect cycles in the module graph. - 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"); + PPOpts.ModuleBuildPath.push_back(Module->getTopLevelModuleName()); + // 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()), - Module->UmbrellaHeader->getName())); + InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); - Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; + // Get or create the module map that we'll use to build this module. + llvm::SmallString<128> TempModuleMapFileName; + if (const FileEntry *ModuleMapFile + = ModMap.getContainingModuleMapFile(Module)) { + // Use the module map where this module resides. + FrontendOpts.Inputs.push_back(std::make_pair(IK, ModuleMapFile->getName())); + } else { + // Create a temporary module map file. + TempModuleMapFileName = Module->Name; + TempModuleMapFileName += "-%%%%%%%%.map"; + int FD; + if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, + TempModuleMapFileName, + /*makeAbsolute=*/false) + != llvm::errc::success) + return; + // Print the module map to this file. + llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); + Module->print(OS); + FrontendOpts.Inputs.push_back( + std::make_pair(IK, TempModuleMapFileName.str().str())); + } + // Don't free the remapped file buffers; they are owned by our caller. + PPOpts.RetainRemappedFileBuffers = true; + + Invocation->getDiagnosticOpts().VerifyDiagnostics = 0; assert(ImportingInstance.getInvocation().getModuleHash() == - Invocation->getModuleHash() && "Module hash mismatch!"); - + Invocation->getModuleHash() && "Module hash mismatch!"); + // Construct a compiler instance that will be used to actually create the // module. CompilerInstance Instance; @@ -1082,16 +1049,23 @@ static void compileModule(CompilerInstance &ImportingInstance, &ImportingInstance.getDiagnosticClient(), /*ShouldOwnClient=*/true, /*ShouldCloneClient=*/true); - + // Construct a module-generating action. - GeneratePCHAction CreateModuleAction(true); - + 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; - CompileModuleData Data = { Instance, CreateModuleAction }; - CRC.RunSafelyOnThread(&doCompileModule, &Data, ThreadStackSize); + CompileModuleMapData Data = { Instance, CreateModuleAction }; + CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize); + + // Delete the temporary module map file. + // FIXME: Even though we're executing under crash protection, it would still + // be nice to do this with RemoveFileOnSignal when we can. However, that + // doesn't make sense for all clients, so clean this up manually. + if (!TempModuleMapFileName.empty()) + llvm::sys::Path(TempModuleMapFileName).eraseFromDisk(); } ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc, diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 3cc6478acf..60c797c362 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -69,7 +69,7 @@ StringRef ModuleMap::Module::getTopLevelModuleName() const { } static void indent(llvm::raw_ostream &OS, unsigned Spaces) { - OS << std::string(' ', Spaces); + OS << std::string(Spaces, ' '); } void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const { @@ -78,7 +78,7 @@ void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const { OS << "framework "; if (IsExplicit) OS << "explicit "; - OS << Name << " {\n"; + OS << "module " << Name << " {\n"; if (UmbrellaHeader) { indent(OS, Indent + 2); @@ -586,28 +586,35 @@ void ModuleMapParser::parseUmbrellaDecl() { // Look for this file. llvm::SmallString<128> PathName; - PathName += Directory->getName(); - unsigned PathLength = PathName.size(); const FileEntry *File = 0; - if (ActiveModule->isPartOfFramework()) { - // Check whether this file is in the public headers. - llvm::sys::path::append(PathName, "Headers"); - llvm::sys::path::append(PathName, FileName); + + if (llvm::sys::path::is_absolute(FileName)) { + PathName = FileName; File = SourceMgr.getFileManager().getFile(PathName); + } else { + // Search for the header file within the search directory. + PathName += Directory->getName(); + unsigned PathLength = PathName.size(); + if (ActiveModule->isPartOfFramework()) { + // Check whether this file is in the public headers. + llvm::sys::path::append(PathName, "Headers"); + llvm::sys::path::append(PathName, FileName); + File = SourceMgr.getFileManager().getFile(PathName); - if (!File) { - // Check whether this file is in the private headers. - PathName.resize(PathLength); - llvm::sys::path::append(PathName, "PrivateHeaders"); + if (!File) { + // Check whether this file is in the private headers. + PathName.resize(PathLength); + llvm::sys::path::append(PathName, "PrivateHeaders"); + llvm::sys::path::append(PathName, FileName); + File = SourceMgr.getFileManager().getFile(PathName); + } + + // FIXME: Deal with subframeworks. + } else { + // Lookup for normal headers. llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); } - - // FIXME: Deal with subframeworks. - } else { - // Lookup for normal headers. - llvm::sys::path::append(PathName, FileName); - File = SourceMgr.getFileManager().getFile(PathName); } // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. @@ -654,11 +661,14 @@ void ModuleMapParser::parseHeaderDecl() { // Look for this file. llvm::SmallString<128> PathName; - PathName += Directory->getName(); + if (llvm::sys::path::is_relative(FileName)) { + // FIXME: Change this search to also look for private headers! + PathName += Directory->getName(); + + if (ActiveModule->isPartOfFramework()) + llvm::sys::path::append(PathName, "Headers"); + } - if (ActiveModule->isPartOfFramework()) - llvm::sys::path::append(PathName, "Headers"); - llvm::sys::path::append(PathName, FileName); // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. |