diff options
Diffstat (limited to 'Source/cmMakefileTargetGenerator.cxx')
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 214 |
1 files changed, 152 insertions, 62 deletions
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 8396fa3..e1fe0e5 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -26,10 +26,12 @@ #include "cmMakefileLibraryTargetGenerator.h" #include "cmMakefileUtilityTargetGenerator.h" #include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmProperty.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" +#include "cmSourceFileLocationKind.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" @@ -51,6 +53,17 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) if (cmProp ruleStatus = cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { this->NoRuleMessages = cmIsOff(*ruleStatus); } + switch (this->GeneratorTarget->GetPolicyStatusCMP0113()) { + case cmPolicies::WARN: + case cmPolicies::OLD: + this->CMP0113New = false; + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + this->CMP0113New = true; + break; + } MacOSXContentGenerator = cm::make_unique<MacOSXContentGeneratorType>(this); } @@ -71,6 +84,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New( case cmStateEnums::OBJECT_LIBRARY: result = cm::make_unique<cmMakefileLibraryTargetGenerator>(tgt); break; + case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UTILITY: result = cm::make_unique<cmMakefileUtilityTargetGenerator>(tgt); break; @@ -196,18 +210,32 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } + std::string currentBinDir = + this->LocalGenerator->GetCurrentBinaryDirectory(); + + // Look for ISPC extra object files generated by this target + auto ispcAdditionalObjs = + this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName()); + for (std::string const& ispcObj : ispcAdditionalObjs) { + this->CleanFiles.insert(this->LocalGenerator->MaybeConvertToRelativePath( + currentBinDir, ispcObj)); + } + // add custom commands to the clean rules? - cmProp clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM"); - bool clean = clean_no_custom ? cmIsOff(*clean_no_custom) : true; + bool clean = cmIsOff(this->Makefile->GetProperty("CLEAN_NO_CUSTOM")); // First generate the object rule files. Save a list of all object // files for this target. std::vector<cmSourceFile const*> customCommands; this->GeneratorTarget->GetCustomCommands(customCommands, this->GetConfigName()); - std::string currentBinDir = - this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmSourceFile const* sf : customCommands) { + if (this->CMP0113New && + !this->LocalGenerator->GetCommandsVisited(this->GeneratorTarget) + .insert(sf) + .second) { + continue; + } cmCustomCommandGenerator ccg(*sf->GetCustomCommand(), this->GetConfigName(), this->LocalGenerator); this->GenerateCustomRuleFile(ccg); @@ -257,17 +285,18 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName()); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator.get(), this->GetConfigName()); - const char* pchExtension = - this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); std::vector<cmSourceFile const*> externalObjects; this->GeneratorTarget->GetExternalObjects(externalObjects, this->GetConfigName()); for (cmSourceFile const* sf : externalObjects) { auto const& objectFileName = sf->GetFullPath(); - if (!cmSystemTools::StringEndsWith(objectFileName, pchExtension)) { + if (!cmSystemTools::StringEndsWith(objectFileName, + cmToCStr(pchExtension))) { this->ExternalObjects.push_back(objectFileName); } } + std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, this->GetConfigName()); @@ -525,6 +554,14 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } } + if (lang != "ISPC") { + auto const& headers = + this->GeneratorTarget->GetGeneratedISPCHeaders(config); + if (!headers.empty()) { + depends.insert(depends.end(), headers.begin(), headers.end()); + } + } + std::string relativeObj = cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj); // Write the build rule. @@ -532,6 +569,13 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Build the set of compiler flags. std::string flags; + // explicitly add the explicit language flag before any other flag + // this way backwards compatibility with user flags is maintained + if (source.GetProperty("LANGUAGE")) { + this->LocalGenerator->AppendFeatureOptions(flags, lang, + "EXPLICIT_LANGUAGE"); + } + // Add language-specific flags. std::string langFlags = cmStrCat("$(", lang, "_FLAGS", filterArch, ")"); this->LocalGenerator->AppendFlags(flags, langFlags); @@ -545,6 +589,23 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->AppendFortranPreprocessFlags(flags, source); } + std::string ispcHeaderRelative; + std::string ispcHeaderForShell; + if (lang == "ISPC") { + std::string ispcSource = + cmSystemTools::GetFilenameWithoutLastExtension(objectName); + + std::string directory = this->GeneratorTarget->GetObjectDirectory(config); + if (cmProp prop = + this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) { + directory = + cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', *prop); + } + ispcHeaderRelative = cmStrCat(directory, '/', ispcSource, ".h"); + ispcHeaderForShell = this->LocalGenerator->ConvertToOutputFormat( + ispcHeaderRelative, cmOutputConverter::SHELL); + } + // Add flags from source file properties. const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (cmProp cflags = source.GetProperty(COMPILE_FLAGS)) { @@ -710,6 +771,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmOutputConverter::SHELL); vars.ObjectFileDir = objectFileDir.c_str(); vars.Flags = flags.c_str(); + vars.ISPCHeader = ispcHeaderForShell.c_str(); std::string definesString = cmStrCat("$(", lang, "_DEFINES)"); @@ -728,7 +790,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // ability to export compile commands bool lang_has_preprocessor = ((lang == "C") || (lang == "CXX") || (lang == "OBJC") || - (lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA")); + (lang == "OBJCXX") || (lang == "Fortran") || (lang == "CUDA") || + lang == "ISPC"); bool const lang_has_assembly = lang_has_preprocessor; bool const lang_can_export_cmds = lang_has_preprocessor; @@ -779,13 +842,13 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( langIncludes.size(), this->GetIncludes(lang, this->GetConfigName())); - const char* eliminate[] = { + cmProp eliminate[] = { this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"), this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE") }; - for (const char* el : eliminate) { + for (cmProp el : eliminate) { if (el) { - cmSystemTools::ReplaceString(compileCommand, el, ""); + cmSystemTools::ReplaceString(compileCommand, *el, ""); } } @@ -797,10 +860,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string compilerLauncher; if (!compileCommands.empty() && (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA" || - lang == "OBJC" || lang == "OBJCXX")) { + lang == "ISPC" || lang == "OBJC" || lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); - if (clauncher && !clauncher->empty()) { + if (cmNonempty(clauncher)) { compilerLauncher = *clauncher; } } @@ -815,8 +878,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( cmProp cpplint = this->GeneratorTarget->GetProperty(cpplint_prop); std::string const cppcheck_prop = lang + "_CPPCHECK"; cmProp cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop); - if ((iwyu && !iwyu->empty()) || (tidy && !tidy->empty()) || - (cpplint && !cpplint->empty()) || (cppcheck && !cppcheck->empty())) { + if (cmNonempty(iwyu) || cmNonempty(tidy) || cmNonempty(cpplint) || + cmNonempty(cppcheck)) { std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile"; if (!compilerLauncher.empty()) { // In __run_co_compile case the launcher command is supplied @@ -825,30 +888,33 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher); compilerLauncher.clear(); } - if (iwyu && !iwyu->empty()) { + if (cmNonempty(iwyu)) { run_iwyu += " --iwyu="; run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); } - if (tidy && !tidy->empty()) { + if (cmNonempty(tidy)) { run_iwyu += " --tidy="; - const char* driverMode = this->Makefile->GetDefinition( - "CMAKE_" + lang + "_CLANG_TIDY_DRIVER_MODE"); - if (!(driverMode && *driverMode)) { + cmProp p = this->Makefile->GetDefinition("CMAKE_" + lang + + "_CLANG_TIDY_DRIVER_MODE"); + std::string driverMode; + if (cmNonempty(p)) { + driverMode = *p; + } else { driverMode = lang == "C" ? "gcc" : "g++"; } run_iwyu += this->LocalGenerator->EscapeForShell( cmStrCat(*tidy, ";--extra-arg-before=--driver-mode=", driverMode)); } - if (cpplint && !cpplint->empty()) { + if (cmNonempty(cpplint)) { run_iwyu += " --cpplint="; run_iwyu += this->LocalGenerator->EscapeForShell(*cpplint); } - if (cppcheck && !cppcheck->empty()) { + if (cmNonempty(cppcheck)) { run_iwyu += " --cppcheck="; run_iwyu += this->LocalGenerator->EscapeForShell(*cppcheck); } - if ((tidy && !tidy->empty()) || (cpplint && !cpplint->empty()) || - (cppcheck && !cppcheck->empty())) { + if (cmNonempty(tidy) || (cmNonempty(cpplint)) || + (cmNonempty(cppcheck))) { run_iwyu += " --source="; run_iwyu += sourceFile; } @@ -875,7 +941,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( { const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_COMPILE"); - if (val && *val) { + if (cmNonempty(val)) { launcher = cmStrCat(val, ' '); } } @@ -903,9 +969,16 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( if (!evaluated_outputs.empty()) { // Register these as extra files to clean. cmExpandList(evaluated_outputs, outputs); - this->CleanFiles.insert(outputs.begin() + 1, outputs.end()); } } + if (!ispcHeaderRelative + .empty()) { // can't move ispcHeader as vars is using it + outputs.emplace_back(ispcHeaderRelative); + } + + if (outputs.size() > 1) { + this->CleanFiles.insert(outputs.begin() + 1, outputs.end()); + } // Write the rule. this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends, @@ -935,10 +1008,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string preprocessRuleVar = cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE"); - if (const char* preprocessRule = + if (cmProp preprocessRule = this->Makefile->GetDefinition(preprocessRuleVar)) { std::vector<std::string> preprocessCommands = - cmExpandedList(preprocessRule); + cmExpandedList(*preprocessRule); std::string shellObjI = this->LocalGenerator->ConvertToOutputFormat( objI, cmOutputConverter::SHELL); @@ -980,10 +1053,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string assemblyRuleVar = cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE"); - if (const char* assemblyRule = + if (cmProp assemblyRule = this->Makefile->GetDefinition(assemblyRuleVar)) { std::vector<std::string> assemblyCommands = - cmExpandedList(assemblyRule); + cmExpandedList(*assemblyRule); std::string shellObjS = this->LocalGenerator->ConvertToOutputFormat( objS, cmOutputConverter::SHELL); @@ -1236,16 +1309,7 @@ void cmMakefileTargetGenerator::DriveCustomCommands( std::vector<std::string>& depends) { // Depend on all custom command outputs. - std::vector<cmSourceFile*> sources; - this->GeneratorTarget->GetSourceFiles( - sources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); - for (cmSourceFile* source : sources) { - if (cmCustomCommand* cc = source->GetCustomCommand()) { - cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), - this->LocalGenerator); - cm::append(depends, ccg.GetOutputs()); - } - } + cm::append(depends, this->CustomCommandOutputs); } void cmMakefileTargetGenerator::WriteObjectDependRules( @@ -1292,6 +1356,22 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends, commands); + // Symbolic inputs are not expected to exist, so add dummy rules. + if (this->CMP0113New && !depends.empty()) { + std::vector<std::string> no_depends; + std::vector<std::string> no_commands; + for (std::string const& dep : depends) { + if (cmSourceFile* dsf = + this->Makefile->GetSource(dep, cmSourceFileLocationKind::Known)) { + if (dsf->GetPropertyAsBool("SYMBOLIC")) { + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, + dep, no_depends, no_commands, + true); + } + } + } + } + // If the rule has changed make sure the output is rebuilt. if (!symbolic) { this->GlobalGenerator->AddRuleHash(ccg.GetOutputs(), content.str()); @@ -1306,6 +1386,8 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, idi.first, objFullPath, srcFullPath); } + + this->CustomCommandOutputs.insert(outputs.begin(), outputs.end()); } void cmMakefileTargetGenerator::MakeEchoProgress( @@ -1330,17 +1412,17 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( << this->GeneratorTarget->GetName() << "\n" << variableName << " ="; std::string object; - const char* lineContinue = - this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE"); - if (!lineContinue) { + std::string lineContinue; + if (cmProp p = this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE")) { + lineContinue = *p; + } else { lineContinue = "\\"; } - const char* pchExtension = - this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); for (std::string const& obj : this->Objects) { - if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) { continue; } *this->BuildFileStream << " " << lineContinue << "\n"; @@ -1435,14 +1517,13 @@ private: void cmMakefileTargetGenerator::WriteObjectsStrings( std::vector<std::string>& objStrings, std::string::size_type limit) { - const char* pchExtension = - this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); + cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION"); cmMakefileTargetGeneratorObjectStrings helper( objStrings, this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit); for (std::string const& obj : this->Objects) { - if (cmSystemTools::StringEndsWith(obj, pchExtension)) { + if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) { continue; } helper.Feed(obj); @@ -1450,6 +1531,11 @@ void cmMakefileTargetGenerator::WriteObjectsStrings( for (std::string const& obj : this->ExternalObjects) { helper.Feed(obj); } + auto ispcAdditionalObjs = + this->GeneratorTarget->GetGeneratedISPCObjects(this->GetConfigName()); + for (std::string const& obj : ispcAdditionalObjs) { + helper.Feed(obj); + } helper.Done(); } @@ -1565,8 +1651,8 @@ std::string cmMakefileTargetGenerator::GetLinkRule( cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_GNUtoMS_RULE"); - if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { - linkRule += rule; + if (cmProp rule = this->Makefile->GetDefinition(ruleVar)) { + linkRule += *rule; } } return linkRule; @@ -1615,8 +1701,8 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects( // Check for an explicit setting one way or the other. std::string const responseVar = "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS"; - if (const char* val = this->Makefile->GetDefinition(responseVar)) { - if (*val) { + if (cmProp val = this->Makefile->GetDefinition(responseVar)) { + if (!val->empty()) { return cmIsOn(val); } } @@ -1654,8 +1740,8 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries( // Check for an explicit setting one way or the other. std::string const responseVar = "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES"; - if (const char* val = this->Makefile->GetDefinition(responseVar)) { - if (*val) { + if (cmProp val = this->Makefile->GetDefinition(responseVar)) { + if (!val->empty()) { return cmIsOn(val); } } @@ -1716,8 +1802,10 @@ void cmMakefileTargetGenerator::CreateLinkLibs( cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_RESPONSE_FILE_LINK_FLAG"); - const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); - if (!responseFlag) { + std::string responseFlag; + if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) { + responseFlag = *p; + } else { responseFlag = "@"; } @@ -1754,8 +1842,10 @@ void cmMakefileTargetGenerator::CreateObjectLists( cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), "_RESPONSE_FILE_LINK_FLAG"); - const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); - if (!responseFlag) { + std::string responseFlag; + if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) { + responseFlag = *p; + } else { responseFlag = "@"; } @@ -1850,11 +1940,11 @@ void cmMakefileTargetGenerator::GenDefFile( this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetCurrentBinaryDirectory(), objlist_file), cmOutputConverter::SHELL); - const char* nm_executable = this->Makefile->GetDefinition("CMAKE_NM"); - if (nm_executable && *nm_executable) { + cmProp nm_executable = this->Makefile->GetDefinition("CMAKE_NM"); + if (cmNonempty(nm_executable)) { cmd += " --nm="; cmd += this->LocalCommonGenerator->ConvertToOutputFormat( - nm_executable, cmOutputConverter::SHELL); + *nm_executable, cmOutputConverter::SHELL); } real_link_commands.insert(real_link_commands.begin(), cmd); // create a list of obj files for the -E __create_def to read |