summaryrefslogtreecommitdiffstats
path: root/Source/cmMakefileTargetGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmMakefileTargetGenerator.cxx')
-rw-r--r--Source/cmMakefileTargetGenerator.cxx214
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