summaryrefslogtreecommitdiffstats
path: root/Source/cmLocalGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmLocalGenerator.cxx')
-rw-r--r--Source/cmLocalGenerator.cxx281
1 files changed, 178 insertions, 103 deletions
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index f6962d1..fe5c8af 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -6,6 +6,7 @@
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -34,6 +35,7 @@
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <assert.h>
+#include <initializer_list>
#include <iterator>
#include <sstream>
#include <stdio.h>
@@ -51,25 +53,23 @@
// replaced in the form <var> with GetSafeDefinition(var).
// ${LANG} is replaced in the variable first with all enabled
// languages.
-static const char* ruleReplaceVars[] = {
- "CMAKE_${LANG}_COMPILER",
- "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
- "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
- "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
- "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
- "CMAKE_${LANG}_LINK_FLAGS",
- "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
- "CMAKE_${LANG}_ARCHIVE",
- "CMAKE_AR",
- "CMAKE_CURRENT_SOURCE_DIR",
- "CMAKE_CURRENT_BINARY_DIR",
- "CMAKE_RANLIB",
- "CMAKE_LINKER",
- "CMAKE_MT",
- "CMAKE_CUDA_HOST_COMPILER",
- "CMAKE_CUDA_HOST_LINK_LAUNCHER",
- "CMAKE_CL_SHOWINCLUDES_PREFIX"
-};
+static auto ruleReplaceVars = { "CMAKE_${LANG}_COMPILER",
+ "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS",
+ "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS",
+ "CMAKE_SHARED_MODULE_${LANG}_FLAGS",
+ "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS",
+ "CMAKE_${LANG}_LINK_FLAGS",
+ "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG",
+ "CMAKE_${LANG}_ARCHIVE",
+ "CMAKE_AR",
+ "CMAKE_CURRENT_SOURCE_DIR",
+ "CMAKE_CURRENT_BINARY_DIR",
+ "CMAKE_RANLIB",
+ "CMAKE_LINKER",
+ "CMAKE_MT",
+ "CMAKE_CUDA_HOST_COMPILER",
+ "CMAKE_CUDA_HOST_LINK_LAUNCHER",
+ "CMAKE_CL_SHOWINCLUDES_PREFIX" };
cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
: cmOutputConverter(makefile->GetStateSnapshot())
@@ -151,15 +151,13 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
this->VariableMappings[compilerOptionSysroot] =
this->Makefile->GetSafeDefinition(compilerOptionSysroot);
- for (const char* const* replaceIter = cm::cbegin(ruleReplaceVars);
- replaceIter != cm::cend(ruleReplaceVars); ++replaceIter) {
- std::string actualReplace = *replaceIter;
- if (actualReplace.find("${LANG}") != std::string::npos) {
- cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
+ for (std::string replaceVar : ruleReplaceVars) {
+ if (replaceVar.find("${LANG}") != std::string::npos) {
+ cmSystemTools::ReplaceString(replaceVar, "${LANG}", lang);
}
- this->VariableMappings[actualReplace] =
- this->Makefile->GetSafeDefinition(actualReplace);
+ this->VariableMappings[replaceVar] =
+ this->Makefile->GetSafeDefinition(replaceVar);
}
}
}
@@ -366,9 +364,8 @@ void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config)
void cmLocalGenerator::ProcessEvaluationFiles(
std::vector<std::string>& generatedFiles)
{
- std::vector<cmGeneratorExpressionEvaluationFile*> ef =
- this->Makefile->GetEvaluationFiles();
- for (cmGeneratorExpressionEvaluationFile* geef : ef) {
+ for (cmGeneratorExpressionEvaluationFile* geef :
+ this->Makefile->GetEvaluationFiles()) {
geef->Generate(this);
if (cmSystemTools::GetFatalErrorOccured()) {
return;
@@ -382,15 +379,15 @@ void cmLocalGenerator::ProcessEvaluationFiles(
std::back_inserter(intersection));
if (!intersection.empty()) {
cmSystemTools::Error("Files to be generated by multiple different "
- "commands: ",
- cmWrap('"', intersection, '"', " ").c_str());
+ "commands: " +
+ cmWrap('"', intersection, '"', " "));
return;
}
- generatedFiles.insert(generatedFiles.end(), files.begin(), files.end());
- std::vector<std::string>::iterator newIt =
- generatedFiles.end() - files.size();
- std::inplace_merge(generatedFiles.begin(), newIt, generatedFiles.end());
+ cmAppend(generatedFiles, files);
+ std::inplace_merge(generatedFiles.begin(),
+ generatedFiles.end() - files.size(),
+ generatedFiles.end());
}
}
@@ -473,7 +470,7 @@ void cmLocalGenerator::GenerateInstallRules()
<< "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl
<< " set(CMAKE_INSTALL_PREFIX \"" << prefix << "\")" << std::endl
<< "endif()" << std::endl
- << "string(REGEX REPLACE \"/$\" \"\" CMAKE_INSTALL_PREFIX "
+ << R"(string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX )"
<< "\"${CMAKE_INSTALL_PREFIX}\")" << std::endl
<< std::endl;
@@ -792,7 +789,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
#endif
for (std::string const& i : includes) {
if (fwSearchFlag && *fwSearchFlag && this->Makefile->IsOn("APPLE") &&
- cmSystemTools::IsPathToFramework(i.c_str())) {
+ cmSystemTools::IsPathToFramework(i)) {
std::string frameworkDir = i;
frameworkDir += "/../";
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
@@ -892,6 +889,32 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags,
}
}
this->AddCompilerRequirementFlag(flags, target, lang);
+
+ // Add compile flag for the MSVC compiler only.
+ cmMakefile* mf = this->GetMakefile();
+ if (const char* jmc =
+ mf->GetDefinition("CMAKE_" + lang + "_COMPILE_OPTIONS_JMC")) {
+
+ // Handle Just My Code debugging flags, /JMC.
+ // If the target is a Managed C++ one, /JMC is not compatible.
+ if (target->GetManagedType(config) !=
+ cmGeneratorTarget::ManagedType::Managed) {
+ // add /JMC flags if target property VS_JUST_MY_CODE_DEBUGGING is set
+ // to ON
+ if (char const* jmcExprGen =
+ target->GetProperty("VS_JUST_MY_CODE_DEBUGGING")) {
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(jmcExprGen);
+ std::string isJMCEnabled = cge->Evaluate(this, config);
+ if (cmSystemTools::IsOn(isJMCEnabled)) {
+ std::vector<std::string> optVec;
+ cmSystemTools::ExpandListArgument(jmc, optVec);
+ this->AppendCompileOptions(flags, optVec);
+ }
+ }
+ }
+ }
}
std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
@@ -1146,30 +1169,34 @@ void cmLocalGenerator::GetTargetFlags(
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
CM_FALLTHROUGH;
case cmStateEnums::SHARED_LIBRARY: {
- linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
- linkFlags += " ";
- if (!buildType.empty()) {
- std::string build = libraryLinkVariable;
- build += "_";
- build += buildType;
- linkFlags += this->Makefile->GetSafeDefinition(build);
+ if (linkLanguage != "Swift") {
+ linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
linkFlags += " ";
- }
- if (this->Makefile->IsOn("WIN32") &&
- !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW"))) {
- std::vector<cmSourceFile*> sources;
- target->GetSourceFiles(sources, buildType);
- std::string defFlag =
- this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
- for (cmSourceFile* sf : sources) {
- if (sf->GetExtension() == "def") {
- linkFlags += defFlag;
- linkFlags += this->ConvertToOutputFormat(
- cmSystemTools::CollapseFullPath(sf->GetFullPath()), SHELL);
- linkFlags += " ";
+ if (!buildType.empty()) {
+ std::string build = libraryLinkVariable;
+ build += "_";
+ build += buildType;
+ linkFlags += this->Makefile->GetSafeDefinition(build);
+ linkFlags += " ";
+ }
+ if (this->Makefile->IsOn("WIN32") &&
+ !(this->Makefile->IsOn("CYGWIN") ||
+ this->Makefile->IsOn("MINGW"))) {
+ std::vector<cmSourceFile*> sources;
+ target->GetSourceFiles(sources, buildType);
+ std::string defFlag =
+ this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
+ for (cmSourceFile* sf : sources) {
+ if (sf->GetExtension() == "def") {
+ linkFlags += defFlag;
+ linkFlags += this->ConvertToOutputFormat(
+ cmSystemTools::CollapseFullPath(sf->GetFullPath()), SHELL);
+ linkFlags += " ";
+ }
}
}
}
+
const char* targetLinkFlags = target->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
linkFlags += targetLinkFlags;
@@ -1184,6 +1211,7 @@ void cmLocalGenerator::GetTargetFlags(
linkFlags += " ";
}
}
+
std::vector<std::string> opts;
target->GetLinkOptions(opts, config, linkLanguage);
// LINK_OPTIONS are escaped.
@@ -1194,25 +1222,49 @@ void cmLocalGenerator::GetTargetFlags(
}
} break;
case cmStateEnums::EXECUTABLE: {
- linkFlags += this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
- linkFlags += " ";
- if (!buildType.empty()) {
- std::string build = "CMAKE_EXE_LINKER_FLAGS_";
- build += buildType;
- linkFlags += this->Makefile->GetSafeDefinition(build);
+ if (linkLanguage != "Swift") {
+ linkFlags +=
+ this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
linkFlags += " ";
+ if (!buildType.empty()) {
+ std::string build = "CMAKE_EXE_LINKER_FLAGS_";
+ build += buildType;
+ linkFlags += this->Makefile->GetSafeDefinition(build);
+ linkFlags += " ";
+ }
+ if (linkLanguage.empty()) {
+ cmSystemTools::Error(
+ "CMake can not determine linker language for target: " +
+ target->GetName());
+ return;
+ }
+
+ if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
+ linkFlags +=
+ this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
+ linkFlags += " ";
+ } else {
+ linkFlags +=
+ this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
+ linkFlags += " ";
+ }
+
+ if (target->IsExecutableWithExports()) {
+ std::string exportFlagVar = "CMAKE_EXE_EXPORTS_";
+ exportFlagVar += linkLanguage;
+ exportFlagVar += "_FLAG";
+
+ linkFlags += this->Makefile->GetSafeDefinition(exportFlagVar);
+ linkFlags += " ";
+ }
}
- if (linkLanguage.empty()) {
- cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- target->GetName().c_str());
- return;
- }
+
this->AddLanguageFlagsForLinking(flags, target, linkLanguage, buildType);
if (pcli) {
this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
}
+
if (cmSystemTools::IsOn(
this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") +
@@ -1220,23 +1272,6 @@ void cmLocalGenerator::GetTargetFlags(
linkFlags += this->Makefile->GetSafeDefinition(sFlagVar);
linkFlags += " ";
}
- if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) {
- linkFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE");
- linkFlags += " ";
- } else {
- linkFlags +=
- this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
- linkFlags += " ";
- }
- if (target->IsExecutableWithExports()) {
- std::string exportFlagVar = "CMAKE_EXE_EXPORTS_";
- exportFlagVar += linkLanguage;
- exportFlagVar += "_FLAG";
-
- linkFlags += this->Makefile->GetSafeDefinition(exportFlagVar);
- linkFlags += " ";
- }
std::string cmp0065Flags =
this->GetLinkLibsCMP0065(linkLanguage, *target);
@@ -1259,6 +1294,7 @@ void cmLocalGenerator::GetTargetFlags(
linkFlags += " ";
}
}
+
std::vector<std::string> opts;
target->GetLinkOptions(opts, config, linkLanguage);
// LINK_OPTIONS are escaped.
@@ -1283,6 +1319,10 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
// Add language-specific flags.
this->AddLanguageFlags(flags, target, lang, config);
+ if (target->IsIPOEnabled(lang, config)) {
+ this->AppendFeatureOptions(flags, lang, "IPO");
+ }
+
this->AddArchitectureFlags(flags, target, lang, config);
if (lang == "Fortran") {
@@ -1404,9 +1444,9 @@ void cmLocalGenerator::OutputLinkLibraries(
std::string linkLanguage = cli.GetLinkLanguage();
- std::string libPathFlag =
+ const std::string& libPathFlag =
this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
- std::string libPathTerminator =
+ const std::string& libPathTerminator =
this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
// Add standard libraries for this language.
@@ -1540,8 +1580,39 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
flagsVar += "_FLAGS";
this->AddConfigVariableFlags(flags, flagsVar, config);
- if (target->IsIPOEnabled(lang, config)) {
- this->AppendFeatureOptions(flags, lang, "IPO");
+ // Add MSVC runtime library flags. This is activated by the presence
+ // of a default selection whether or not it is overridden by a property.
+ const char* msvcRuntimeLibraryDefault =
+ this->Makefile->GetDefinition("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT");
+ if (msvcRuntimeLibraryDefault && *msvcRuntimeLibraryDefault) {
+ const char* msvcRuntimeLibraryValue =
+ target->GetProperty("MSVC_RUNTIME_LIBRARY");
+ if (!msvcRuntimeLibraryValue) {
+ msvcRuntimeLibraryValue = msvcRuntimeLibraryDefault;
+ }
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(msvcRuntimeLibraryValue);
+ std::string const msvcRuntimeLibrary =
+ cge->Evaluate(this, config, false, target);
+ if (!msvcRuntimeLibrary.empty()) {
+ if (const char* msvcRuntimeLibraryOptions =
+ this->Makefile->GetDefinition(
+ "CMAKE_" + lang + "_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_" +
+ msvcRuntimeLibrary)) {
+ this->AppendCompileOptions(flags, msvcRuntimeLibraryOptions);
+ } else if ((this->Makefile->GetSafeDefinition(
+ "CMAKE_" + lang + "_COMPILER_ID") == "MSVC" ||
+ this->Makefile->GetSafeDefinition(
+ "CMAKE_" + lang + "_SIMULATE_ID") == "MSVC") &&
+ !cmSystemTools::GetErrorOccuredFlag()) {
+ // The compiler uses the MSVC ABI so it needs a known runtime library.
+ this->IssueMessage(MessageType::FATAL_ERROR,
+ "MSVC_RUNTIME_LIBRARY value '" +
+ msvcRuntimeLibrary + "' not known for this " +
+ lang + " compiler.");
+ }
+ }
}
}
@@ -1559,6 +1630,10 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
}
this->AddLanguageFlags(flags, target, lang, config);
+
+ if (target->IsIPOEnabled(lang, config)) {
+ this->AppendFeatureOptions(flags, lang, "IPO");
+ }
}
cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse(
@@ -1852,7 +1927,9 @@ static void AddVisibilityCompileOption(std::string& flags,
strcmp(prop, "protected") != 0 && strcmp(prop, "internal") != 0) {
std::ostringstream e;
e << "Target " << target->GetName() << " uses unsupported value \"" << prop
- << "\" for " << flagDefine << ".";
+ << "\" for " << flagDefine << "."
+ << " The supported values are: default, hidden, protected, and "
+ "internal.";
cmSystemTools::Error(e.str());
return;
}
@@ -2263,11 +2340,8 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
dflag = df;
}
}
-
- std::set<std::string>::const_iterator defineIt = defines.begin();
- const std::set<std::string>::const_iterator defineEnd = defines.end();
const char* itemSeparator = definesString.empty() ? "" : " ";
- for (; defineIt != defineEnd; ++defineIt) {
+ for (std::string const& define : defines) {
// Append the definition with proper escaping.
std::string def = dflag;
if (this->GetState()->UseWatcomWMake()) {
@@ -2281,7 +2355,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
// command line without any escapes. However we still have to
// get the '$' and '#' characters through WMake as '$$' and
// '$#'.
- for (const char* c = defineIt->c_str(); *c; ++c) {
+ for (const char* c = define.c_str(); *c; ++c) {
if (*c == '$' || *c == '#') {
def += '$';
}
@@ -2290,11 +2364,11 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
} else {
// Make the definition appear properly on the command line. Use
// -DNAME="value" instead of -D"NAME=value" for historical reasons.
- std::string::size_type eq = defineIt->find("=");
- def += defineIt->substr(0, eq);
+ std::string::size_type eq = define.find('=');
+ def += define.substr(0, eq);
if (eq != std::string::npos) {
def += "=";
- def += this->EscapeForShell(defineIt->c_str() + eq + 1, true);
+ def += this->EscapeForShell(define.substr(eq + 1), true);
}
}
definesString += itemSeparator;
@@ -2851,7 +2925,7 @@ static void cmLGInfoProp(cmMakefile* mf, cmGeneratorTarget* target,
void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
const std::string& targetName,
- const char* fname)
+ const std::string& fname)
{
// Find the Info.plist template.
const char* in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST");
@@ -2885,11 +2959,12 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_BUNDLE_VERSION");
cmLGInfoProp(mf, target, "MACOSX_BUNDLE_COPYRIGHT");
- mf->ConfigureFile(inFile.c_str(), fname, false, false, false);
+ mf->ConfigureFile(inFile, fname, false, false, false);
}
void cmLocalGenerator::GenerateFrameworkInfoPList(
- cmGeneratorTarget* target, const std::string& targetName, const char* fname)
+ cmGeneratorTarget* target, const std::string& targetName,
+ const std::string& fname)
{
// Find the Info.plist template.
const char* in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST");
@@ -2919,5 +2994,5 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING");
cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_BUNDLE_VERSION");
- mf->ConfigureFile(inFile.c_str(), fname, false, false, false);
+ mf->ConfigureFile(inFile, fname, false, false, false);
}