Commit 1e4bb358 authored by Zsolt Parragi's avatar Zsolt Parragi Committed by Brad King
Browse files

Add generator expression support to per-source COMPILE_FLAGS

This allows users to specify different genex-based compile flags for
each file in a target, e.g. compiling just a single file with `Od/Ox` in
release builds on Visual Studio.
parent ee0f2d23
Pipeline #32979 passed with stage
......@@ -6,3 +6,10 @@ Additional flags to be added when compiling this source file.
These flags will be added to the list of compile flags when this
source file builds. Use :prop_sf:`COMPILE_DEFINITIONS` to pass
additional preprocessor definitions.
Contents of ``COMPILE_FLAGS`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. However, :generator:`Xcode`
does not support per-config per-source settings, so expressions
that depend on the build configuration are not allowed with that
generator.
src-COMPILE_FLAGS-genex
-----------------------
* The :prop_sf:`COMPILE_FLAGS` source file property learned to support
:manual:`generator expressions <cmake-generator-expressions(7)>`.
......@@ -341,7 +341,11 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
}
// Add source file specific flags.
lg->AppendFlags(flags, source->GetProperty("COMPILE_FLAGS"));
if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
const char* processed = ge.Parse(cflags)->Evaluate(lg, config);
lg->AppendFlags(flags, processed);
}
return flags;
}
......
......@@ -675,7 +675,24 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
default:
break;
}
lg->AppendFlags(flags, sf->GetProperty("COMPILE_FLAGS"));
if (const char* cflags = sf->GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
std::string configName = "NO-PER-CONFIG-SUPPORT-IN-XCODE";
CM_AUTO_PTR<cmCompiledGeneratorExpression> compiledExpr = ge.Parse(cflags);
const char* processed = compiledExpr->Evaluate(lg, configName);
if (compiledExpr->GetHadContextSensitiveCondition()) {
std::ostringstream e;
/* clang-format off */
e <<
"Xcode does not support per-config per-source COMPILE_FLAGS:\n"
" " << cflags << "\n"
"specified for source:\n"
" " << sf->GetFullPath() << "\n";
/* clang-format on */
lg->IssueMessage(cmake::FATAL_ERROR, e.str());
}
lg->AppendFlags(flags, processed);
}
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
......
......@@ -1464,7 +1464,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
needfc = true;
}
if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
fc.CompileFlags = cflags;
cmGeneratorExpression ge;
CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
fc.CompileFlags = cge->Evaluate(lg, *i);
needfc = true;
}
if (lg->FortranProject) {
......
......@@ -437,8 +437,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
langFlags += "_FLAGS)";
this->LocalGenerator->AppendFlags(flags, langFlags);
std::string configUpper =
cmSystemTools::UpperCase(this->LocalGenerator->GetConfigName());
std::string config = this->LocalGenerator->GetConfigName();
std::string configUpper = cmSystemTools::UpperCase(config);
// Add Fortran format flags.
if (lang == "Fortran") {
......@@ -446,12 +446,14 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
}
// Add flags from source file properties.
if (source.GetProperty("COMPILE_FLAGS")) {
this->LocalGenerator->AppendFlags(flags,
source.GetProperty("COMPILE_FLAGS"));
if (const char* cflags = source.GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
false, this->GeneratorTarget);
this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
*this->FlagFileStream << "# Custom flags: " << relativeObj
<< "_FLAGS = " << source.GetProperty("COMPILE_FLAGS")
<< "\n"
<< "_FLAGS = " << evaluatedFlags << "\n"
<< "\n";
}
......
......@@ -132,8 +132,14 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
// Add source file specific flags.
this->LocalGenerator->AppendFlags(flags,
source->GetProperty("COMPILE_FLAGS"));
if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpression ge;
CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
false, this->GeneratorTarget);
this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
}
return flags;
}
......
......@@ -686,7 +686,12 @@ static Json::Value DumpSourceFilesList(
cmLocalGenerator* lg = target->GetLocalGenerator();
std::string compileFlags = ld.Flags;
lg->AppendFlags(compileFlags, file->GetProperty("COMPILE_FLAGS"));
if (const char* cflags = file->GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
const char* processed =
ge.Parse(cflags)->Evaluate(target->GetLocalGenerator(), config);
lg->AppendFlags(compileFlags, processed);
}
fileData.Flags = compileFlags;
fileData.IncludePathList = ld.IncludePathList;
......
......@@ -1355,8 +1355,13 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
objectName = this->GeneratorTarget->GetObjectName(&sf);
}
std::string flags;
bool configDependentFlags = false;
std::string defines;
if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
if (cmGeneratorExpression::Find(cflags) != std::string::npos) {
configDependentFlags = true;
}
flags += cflags;
}
if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
......@@ -1412,7 +1417,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
// if we have flags or defines for this config then
// use them
if (!flags.empty() || !configDefines.empty() || compileAs || noWinRT) {
if (!flags.empty() || configDependentFlags || !configDefines.empty() ||
compileAs || noWinRT) {
(*this->BuildFileStream) << firstString;
firstString = ""; // only do firstString once
hasFlags = true;
......@@ -1427,7 +1433,15 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
if (noWinRT) {
clOptions.AddFlag("CompileAsWinRT", "false");
}
clOptions.Parse(flags.c_str());
if (configDependentFlags) {
cmGeneratorExpression ge;
CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(flags);
std::string evaluatedFlags =
cge->Evaluate(this->LocalGenerator, *config);
clOptions.Parse(evaluatedFlags.c_str());
} else {
clOptions.Parse(flags.c_str());
}
if (clOptions.HasFlag("AdditionalIncludeDirectories")) {
clOptions.AppendFlag("AdditionalIncludeDirectories",
"%(AdditionalIncludeDirectories)");
......
......@@ -257,6 +257,7 @@ add_custom_target(check-part4 ALL
# Cover test properties with generator expressions.
add_executable(echo echo.c)
add_executable(pwd pwd.c)
set_property(SOURCE echo.c PROPERTY COMPILE_FLAGS $<1:-DSRC_GENEX_WORKS>)
add_test(NAME echo-configuration COMMAND echo $<CONFIGURATION>)
set_property(TEST echo-configuration PROPERTY
......
......@@ -3,6 +3,9 @@
int main(int argc, char* argv[])
{
#ifndef SRC_GENEX_WORKS
#error SRC_GENEX_WORKS not defined
#endif
printf("%s\n", argv[1]);
return EXIT_SUCCESS;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment