diff options
Diffstat (limited to 'Source/cmNinjaTargetGenerator.cxx')
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 191 |
1 files changed, 118 insertions, 73 deletions
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 3220fba..816e6d8 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -91,26 +91,26 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const return this->LocalGenerator->GetGlobalNinjaGenerator(); } -const char* cmNinjaTargetGenerator::GetConfigName() const +std::string const& cmNinjaTargetGenerator::GetConfigName() const { return this->LocalGenerator->GetConfigName(); } // TODO: Picked up from cmMakefileTargetGenerator. Refactor it. -const char* cmNinjaTargetGenerator::GetFeature(const char* feature) +const char* cmNinjaTargetGenerator::GetFeature(const std::string& feature) { return this->Target->GetFeature(feature, this->GetConfigName()); } // TODO: Picked up from cmMakefileTargetGenerator. Refactor it. -bool cmNinjaTargetGenerator::GetFeatureAsBool(const char* feature) +bool cmNinjaTargetGenerator::GetFeatureAsBool(const std::string& feature) { - return cmSystemTools::IsOn(this->GetFeature(feature)); + return this->Target->GetFeatureAsBool(feature, this->GetConfigName()); } // TODO: Picked up from cmMakefileTargetGenerator. Refactor it. void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags, - const char* lang) + const std::string& lang) { // Add language-specific flags. this->LocalGenerator->AddLanguageFlags(flags, lang, this->GetConfigName()); @@ -121,12 +121,18 @@ void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags, } } +std::string +cmNinjaTargetGenerator::OrderDependsTargetForTarget() +{ + return "cmake_order_depends_target_" + this->GetTargetName(); +} + // TODO: Most of the code is picked up from // void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink), // void cmMakefileTargetGenerator::WriteTargetLanguageFlags() // Refactor it. std::string -cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, +cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile const* source, const std::string& language) { // TODO: Fortran support. @@ -140,11 +146,11 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, std::string& languageFlags = this->LanguageFlags[language]; if(!hasLangCached) { - this->AddFeatureFlags(languageFlags, language.c_str()); + this->AddFeatureFlags(languageFlags, language); this->GetLocalGenerator()->AddArchitectureFlags(languageFlags, this->GeneratorTarget, - language.c_str(), + language, this->GetConfigName()); // Add shared-library flags if needed. @@ -153,23 +159,23 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, this->GetConfigName()); this->LocalGenerator->AddVisibilityPresetFlags(languageFlags, this->Target, - language.c_str()); + language); std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, - language.c_str(), + language, this->GetConfigName()); // Add include directory flags. std::string includeFlags = this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget, - language.c_str(), + language, language == "RC" ? true : false); // full include paths for RC // needed by cmcldeps if(cmGlobalNinjaGenerator::IsMinGW()) cmSystemTools::ReplaceString(includeFlags, "\\", "/"); - this->LocalGenerator->AppendFlags(languageFlags, includeFlags.c_str()); + this->LocalGenerator->AppendFlags(languageFlags, includeFlags); // Append old-style preprocessor definition flags. this->LocalGenerator->AppendFlags(languageFlags, @@ -177,7 +183,7 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source, // Add target-specific flags. this->LocalGenerator->AddCompileOptions(languageFlags, this->Target, - language.c_str(), + language, this->GetConfigName()); } @@ -211,7 +217,7 @@ bool cmNinjaTargetGenerator::needsDepFile(const std::string& lang) // void cmMakefileTargetGenerator::WriteTargetLanguageFlags(). std::string cmNinjaTargetGenerator:: -ComputeDefines(cmSourceFile *source, const std::string& language) +ComputeDefines(cmSourceFile const* source, const std::string& language) { std::set<std::string> defines; @@ -232,12 +238,12 @@ ComputeDefines(cmSourceFile *source, const std::string& language) defPropName += cmSystemTools::UpperCase(this->GetConfigName()); this->LocalGenerator->AppendDefines (defines, - source->GetProperty(defPropName.c_str())); + source->GetProperty(defPropName)); } std::string definesString; this->LocalGenerator->JoinDefines(defines, definesString, - language.c_str()); + language); return definesString; } @@ -269,14 +275,14 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const std::string cmNinjaTargetGenerator -::GetSourceFilePath(cmSourceFile* source) const +::GetSourceFilePath(cmSourceFile const* source) const { return ConvertToNinjaPath(source->GetFullPath().c_str()); } std::string cmNinjaTargetGenerator -::GetObjectFilePath(cmSourceFile* source) const +::GetObjectFilePath(cmSourceFile const* source) const { std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if(!path.empty()) @@ -320,6 +326,7 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID")) { std::string pdbPath; + std::string compilePdbPath; if(this->Target->GetType() == cmTarget::EXECUTABLE || this->Target->GetType() == cmTarget::STATIC_LIBRARY || this->Target->GetType() == cmTarget::SHARED_LIBRARY || @@ -329,11 +336,25 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const pdbPath += "/"; pdbPath += this->Target->GetPDBName(this->GetConfigName()); } + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) + { + compilePdbPath = this->Target->GetCompilePDBPath(this->GetConfigName()); + if(compilePdbPath.empty()) + { + compilePdbPath = this->Target->GetSupportDirectory() + "/"; + } + } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( - ConvertToNinjaPath(pdbPath.c_str()).c_str(), + ConvertToNinjaPath(pdbPath.c_str()), cmLocalGenerator::SHELL); + vars["TARGET_COMPILE_PDB"] = + this->GetLocalGenerator()->ConvertToOutputFormat( + ConvertToNinjaPath(compilePdbPath.c_str()), + cmLocalGenerator::SHELL); + EnsureParentDirectoryExists(pdbPath); + EnsureParentDirectoryExists(compilePdbPath); return true; } return false; @@ -362,7 +383,9 @@ cmNinjaTargetGenerator vars.Object = "$out"; vars.Defines = "$DEFINES"; vars.TargetPDB = "$TARGET_PDB"; + vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; + vars.ObjectFileDir = "$OBJECT_FILE_DIR"; cmMakefile* mf = this->GetMakefile(); @@ -404,9 +427,14 @@ cmNinjaTargetGenerator else { deptype = "gcc"; + const char* langdeptype = mf->GetDefinition("CMAKE_NINJA_DEPTYPE_" + lang); + if (langdeptype) + { + deptype = langdeptype; + } depfile = "$DEP_FILE"; const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang; - std::string depfileFlags = mf->GetSafeDefinition(flagsName.c_str()); + std::string depfileFlags = mf->GetSafeDefinition(flagsName); if (!depfileFlags.empty()) { cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE"); @@ -422,7 +450,7 @@ cmNinjaTargetGenerator // Rule for compiling object file. const std::string cmdVar = std::string("CMAKE_") + lang + "_COMPILE_OBJECT"; - std::string compileCmd = mf->GetRequiredDefinition(cmdVar.c_str()); + std::string compileCmd = mf->GetRequiredDefinition(cmdVar); std::vector<std::string> compileCmds; cmSystemTools::ExpandListArgument(compileCmd, compileCmds); @@ -466,63 +494,86 @@ cmNinjaTargetGenerator << this->GetTargetName() << "\n\n"; - std::vector<cmSourceFile*> customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands); - for(std::vector<cmSourceFile*>::const_iterator + std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + std::vector<cmSourceFile const*> customCommands; + this->GeneratorTarget->GetCustomCommands(customCommands, config); + for(std::vector<cmSourceFile const*>::const_iterator si = customCommands.begin(); si != customCommands.end(); ++si) { cmCustomCommand const* cc = (*si)->GetCustomCommand(); this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget()); + // Record the custom commands for this target. The container is used + // in WriteObjectBuildStatement when called in a loop below. + this->CustomCommands.push_back(cc); } - std::vector<cmSourceFile*> headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources); + std::vector<cmSourceFile const*> headerSources; + this->GeneratorTarget->GetHeaderSources(headerSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( headerSources, this->MacOSXContentGenerator); - std::vector<cmSourceFile*> extraSources; - this->GeneratorTarget->GetExtraSources(extraSources); + std::vector<cmSourceFile const*> extraSources; + this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator); - std::vector<cmSourceFile*> externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects); - for(std::vector<cmSourceFile*>::const_iterator + std::vector<cmSourceFile const*> externalObjects; + this->GeneratorTarget->GetExternalObjects(externalObjects, config); + for(std::vector<cmSourceFile const*>::const_iterator si = externalObjects.begin(); si != externalObjects.end(); ++si) { this->Objects.push_back(this->GetSourceFilePath(*si)); } - std::vector<cmSourceFile*> objectSources; - this->GeneratorTarget->GetObjectSources(objectSources); - for(std::vector<cmSourceFile*>::const_iterator - si = objectSources.begin(); si != objectSources.end(); ++si) + + cmNinjaDeps orderOnlyDeps; + this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps); + + // Add order-only dependencies on custom command outputs. + for(std::vector<cmCustomCommand const*>::const_iterator + cci = this->CustomCommands.begin(); + cci != this->CustomCommands.end(); ++cci) + { + cmCustomCommand const* cc = *cci; + cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), + this->GetMakefile()); + const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); + std::transform(ccoutputs.begin(), ccoutputs.end(), + std::back_inserter(orderOnlyDeps), MapToNinjaPath()); + } + + if (!orderOnlyDeps.empty()) { - this->WriteObjectBuildStatement(*si); + cmNinjaDeps orderOnlyTarget; + orderOnlyTarget.push_back(this->OrderDependsTargetForTarget()); + this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(), + "Order-only phony target for " + + this->GetTargetName(), + orderOnlyTarget, + cmNinjaDeps(), + cmNinjaDeps(), + orderOnlyDeps); } - if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) + std::vector<cmSourceFile const*> objectSources; + this->GeneratorTarget->GetObjectSources(objectSources, config); + for(std::vector<cmSourceFile const*>::const_iterator + si = objectSources.begin(); si != objectSources.end(); ++si) { - this->ModuleDefinitionFile = this->ConvertToNinjaPath( - this->GeneratorTarget->ModuleDefinitionFile.c_str()); + this->WriteObjectBuildStatement(*si, !orderOnlyDeps.empty()); } - - { - // Add object library contents as external objects. - std::vector<std::string> objs; - this->GeneratorTarget->UseObjectLibraries(objs); - for(std::vector<std::string>::iterator oi = objs.begin(); - oi != objs.end(); ++oi) + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(config); + if(!def.empty()) { - this->Objects.push_back(ConvertToNinjaPath(oi->c_str())); + this->ModuleDefinitionFile = this->ConvertToNinjaPath(def.c_str()); } - } this->GetBuildFileStream() << "\n"; } void cmNinjaTargetGenerator -::WriteObjectBuildStatement(cmSourceFile* source) +::WriteObjectBuildStatement( + cmSourceFile const* source, bool writeOrderDependsTargetForTarget) { std::string comment; const std::string language = source->GetLanguage(); @@ -542,11 +593,6 @@ cmNinjaTargetGenerator sourceFileName = this->GetSourceFilePath(source); explicitDeps.push_back(sourceFileName); - // Ensure that the target dependencies are built before any source file in - // the target, using order-only dependencies. - cmNinjaDeps orderOnlyDeps; - this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps); - cmNinjaDeps implicitDeps; if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) { std::vector<std::string> depList; @@ -555,17 +601,10 @@ cmNinjaTargetGenerator std::back_inserter(implicitDeps), MapToNinjaPath()); } - // Add order-only dependencies on custom command outputs. - std::vector<cmSourceFile*> customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands); - for(std::vector<cmSourceFile*>::const_iterator - si = customCommands.begin(); - si != customCommands.end(); ++si) + cmNinjaDeps orderOnlyDeps; + if (writeOrderDependsTargetForTarget) { - cmCustomCommand const* cc = (*si)->GetCustomCommand(); - const std::vector<std::string>& ccoutputs = cc->GetOutputs(); - std::transform(ccoutputs.begin(), ccoutputs.end(), - std::back_inserter(orderOnlyDeps), MapToNinjaPath()); + orderOnlyDeps.push_back(this->OrderDependsTargetForTarget()); } // If the source file is GENERATED and does not have a custom command @@ -589,8 +628,12 @@ cmNinjaTargetGenerator std::string objectDir = this->Target->GetSupportDirectory(); vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( - ConvertToNinjaPath(objectDir.c_str()).c_str(), + ConvertToNinjaPath(objectDir.c_str()), cmLocalGenerator::SHELL); + std::string objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); + vars["OBJECT_FILE_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat( + ConvertToNinjaPath(objectFileDir.c_str()), + cmLocalGenerator::SHELL); this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetTarget(), vars); @@ -614,11 +657,12 @@ cmNinjaTargetGenerator escapedSourceFileName = this->LocalGenerator->ConvertToOutputFormat( - escapedSourceFileName.c_str(), cmLocalGenerator::SHELL); + escapedSourceFileName, cmLocalGenerator::SHELL); compileObjectVars.Source = escapedSourceFileName.c_str(); compileObjectVars.Object = objectFileName.c_str(); compileObjectVars.ObjectDir = objectDir.c_str(); + compileObjectVars.ObjectFileDir = objectFileDir.c_str(); compileObjectVars.Flags = vars["FLAGS"].c_str(); compileObjectVars.Defines = vars["DEFINES"].c_str(); @@ -627,7 +671,7 @@ cmNinjaTargetGenerator compileCmdVar += language; compileCmdVar += "_COMPILE_OBJECT"; std::string compileCmd = - this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str()); + this->GetMakefile()->GetRequiredDefinition(compileCmdVar); std::vector<std::string> compileCmds; cmSystemTools::ExpandListArgument(compileCmd, compileCmds); @@ -685,8 +729,8 @@ cmNinjaTargetGenerator // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; flag += (this->LocalGenerator->ConvertToLinkReference( - this->ModuleDefinitionFile.c_str())); - this->LocalGenerator->AppendFlags(flags, flag.c_str()); + this->ModuleDefinitionFile)); + this->LocalGenerator->AppendFlags(flags, flag); } void @@ -717,7 +761,7 @@ cmNinjaTargetGenerator //---------------------------------------------------------------------------- void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( - cmSourceFile& source, const char* pkgloc) + cmSourceFile const& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. if(!this->Generator->GetTarget()->IsBundleOnApple()) @@ -748,9 +792,10 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( this->Generator->GetGlobalGenerator()->AddDependencyToAll(output); } -void cmNinjaTargetGenerator::addPoolNinjaVariable(const char* pool_property, - cmTarget* target, - cmNinjaVars& vars) +void cmNinjaTargetGenerator::addPoolNinjaVariable( + const std::string& pool_property, + cmTarget* target, + cmNinjaVars& vars) { const char* pool = target->GetProperty(pool_property); if (pool) |