From 9432f686e62082045f53bd0ec8f8911966476df1 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 30 Nov 2017 15:06:21 +0100 Subject: Add generator expression support to per-source COMPILE_DEFINITIONS This allows users to specify different genex-based compile definitions for each file in a target. Fixes: #17508 --- Help/prop_sf/COMPILE_DEFINITIONS.rst | 10 ++++++++++ Help/release/dev/src-COMPILE_DEFINITIONS-genex.rst | 5 +++++ Source/cmExtraSublimeTextGenerator.cxx | 14 +++++++++----- Source/cmGlobalXCodeGenerator.cxx | 7 +++++-- Source/cmLocalVisualStudio7Generator.cxx | 6 +++--- Source/cmMakefileTargetGenerator.cxx | 11 ++++++----- Source/cmNinjaTargetGenerator.cxx | 21 ++++++++++++++------- Source/cmServerProtocol.cxx | 10 ++++++++-- Source/cmVisualStudio10TargetGenerator.cxx | 11 ++++++++++- Tests/GeneratorExpression/CMakeLists.txt | 9 +++++++-- Tests/GeneratorExpression/srcgenex.c | 12 ------------ Tests/GeneratorExpression/srcgenex_defs.c | 12 ++++++++++++ Tests/GeneratorExpression/srcgenex_flags.c | 12 ++++++++++++ .../PerConfigPerSourceDefinitions-result.txt | 1 + .../PerConfigPerSourceDefinitions-stderr.txt | 8 ++++++++ .../PerConfigPerSourceDefinitions.cmake | 3 +++ Tests/RunCMake/XcodeProject/RunCMakeTest.cmake | 1 + 17 files changed, 114 insertions(+), 39 deletions(-) create mode 100644 Help/release/dev/src-COMPILE_DEFINITIONS-genex.rst delete mode 100644 Tests/GeneratorExpression/srcgenex.c create mode 100644 Tests/GeneratorExpression/srcgenex_defs.c create mode 100644 Tests/GeneratorExpression/srcgenex_flags.c create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-result.txt create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-stderr.txt create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions.cmake diff --git a/Help/prop_sf/COMPILE_DEFINITIONS.rst b/Help/prop_sf/COMPILE_DEFINITIONS.rst index 1626825..8d2108c 100644 --- a/Help/prop_sf/COMPILE_DEFINITIONS.rst +++ b/Help/prop_sf/COMPILE_DEFINITIONS.rst @@ -17,3 +17,13 @@ by the native build tool. Xcode does not support per-configuration definitions on source files. .. include:: /include/COMPILE_DEFINITIONS_DISCLAIMER.txt + +Contents of ``COMPILE_DEFINITIONS`` 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. + +Generator expressions should be preferred instead of setting the alternative per-configuration +property. diff --git a/Help/release/dev/src-COMPILE_DEFINITIONS-genex.rst b/Help/release/dev/src-COMPILE_DEFINITIONS-genex.rst new file mode 100644 index 0000000..892344f --- /dev/null +++ b/Help/release/dev/src-COMPILE_DEFINITIONS-genex.rst @@ -0,0 +1,5 @@ +src-COMPILE_DEFINITIONS-genex +----------------------------- + +* The :prop_sf:`COMPILE_DEFINITIONS` source file property learned to support + :manual:`generator expressions `. diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 2443ece..bd1b6bb 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -379,6 +379,7 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( cmMakefile* makefile = lg->GetMakefile(); const std::string& language = source->GetLanguage(); const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + cmGeneratorExpressionInterpreter genexInterpreter(lg, target, config); // Add the export symbol definition for shared library objects. if (const char* exportMacro = target->GetExportMacro()) { @@ -387,11 +388,14 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( // Add preprocessor definitions for this target and configuration. lg->AddCompileDefinitions(defines, target, config, language); - lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS")); - { - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += cmSystemTools::UpperCase(config); - lg->AppendDefines(defines, source->GetProperty(defPropName)); + if (const char* compile_defs = source->GetProperty("COMPILE_DEFINITIONS")) { + lg->AppendDefines(defines, genexInterpreter.Evaluate(compile_defs)); + } + + std::string defPropName = "COMPILE_DEFINITIONS_"; + defPropName += cmSystemTools::UpperCase(config); + if (const char* config_compile_defs = source->GetProperty(defPropName)) { + lg->AppendDefines(defines, genexInterpreter.Evaluate(config_compile_defs)); } std::string definesString; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 63f708b..bbf4175 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -740,8 +740,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( // Add per-source definitions. BuildObjectListOrString flagsBuild(this, false); - this->AppendDefines(flagsBuild, sf->GetProperty("COMPILE_DEFINITIONS"), - true); + if (const char* compile_defs = sf->GetProperty("COMPILE_DEFINITIONS")) { + this->AppendDefines( + flagsBuild, + genexInterpreter.Evaluate(compile_defs, "COMPILE_DEFINITIONS"), true); + } if (!flagsBuild.IsEmpty()) { if (!flags.empty()) { flags += ' '; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index e5c8317..53966cd 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1484,13 +1484,13 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( } } if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) { - fc.CompileDefs = cdefs; + fc.CompileDefs = genexInterpreter.Evaluate(cdefs); needfc = true; } std::string defPropName = "COMPILE_DEFINITIONS_"; defPropName += configUpper; - if (const char* ccdefs = sf.GetProperty(defPropName.c_str())) { - fc.CompileDefsConfig = ccdefs; + if (const char* ccdefs = sf.GetProperty(defPropName)) { + fc.CompileDefsConfig = genexInterpreter.Evaluate(ccdefs); needfc = true; } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 85dc55e..5e0c582 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -447,18 +447,19 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( // Add source-sepcific preprocessor definitions. if (const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS")) { - this->LocalGenerator->AppendDefines(defines, compile_defs); + const char* evaluatedDefs = genexInterpreter.Evaluate(compile_defs); + this->LocalGenerator->AppendDefines(defines, evaluatedDefs); *this->FlagFileStream << "# Custom defines: " << relativeObj - << "_DEFINES = " << compile_defs << "\n" + << "_DEFINES = " << evaluatedDefs << "\n" << "\n"; } std::string defPropName = "COMPILE_DEFINITIONS_"; defPropName += configUpper; if (const char* config_compile_defs = source.GetProperty(defPropName)) { - this->LocalGenerator->AppendDefines(defines, config_compile_defs); + const char* evaluatedDefs = genexInterpreter.Evaluate(config_compile_defs); + this->LocalGenerator->AppendDefines(defines, evaluatedDefs); *this->FlagFileStream << "# Custom defines: " << relativeObj << "_DEFINES_" - << configUpper << " = " << config_compile_defs - << "\n" + << configUpper << " = " << evaluatedDefs << "\n" << "\n"; } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index bad4112..1036977 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -177,13 +177,20 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, const std::string& language) { std::set defines; - this->LocalGenerator->AppendDefines( - defines, source->GetProperty("COMPILE_DEFINITIONS")); - { - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += cmSystemTools::UpperCase(this->GetConfigName()); - this->LocalGenerator->AppendDefines(defines, - source->GetProperty(defPropName)); + const std::string config = this->LocalGenerator->GetConfigName(); + cmGeneratorExpressionInterpreter genexInterpreter( + this->LocalGenerator, this->GeneratorTarget, config); + + if (const char* compile_defs = source->GetProperty("COMPILE_DEFINITIONS")) { + this->LocalGenerator->AppendDefines( + defines, genexInterpreter.Evaluate(compile_defs)); + } + + std::string defPropName = "COMPILE_DEFINITIONS_"; + defPropName += cmSystemTools::UpperCase(config); + if (const char* config_compile_defs = source->GetProperty(defPropName)) { + this->LocalGenerator->AppendDefines( + defines, genexInterpreter.Evaluate(config_compile_defs)); } std::string definesString = this->GetDefines(language); diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 1bb07e7..da354bd 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -712,10 +712,16 @@ static Json::Value DumpSourceFilesList( fileData.IncludePathList = ld.IncludePathList; std::set defines; - lg->AppendDefines(defines, file->GetProperty("COMPILE_DEFINITIONS")); + if (const char* defs = file->GetProperty("COMPILE_DEFINITIONS")) { + lg->AppendDefines(defines, genexInterpreter.Evaluate(defs)); + } + const std::string defPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config); - lg->AppendDefines(defines, file->GetProperty(defPropName)); + if (const char* config_defs = file->GetProperty(defPropName)) { + lg->AppendDefines(defines, genexInterpreter.Evaluate(config_defs)); + } + defines.insert(ld.Defines.begin(), ld.Defines.end()); fileData.SetDefines(defines); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index badd24f..8589a96 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2066,12 +2066,15 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( std::string flags; bool configDependentFlags = false; std::string defines; + bool configDependentDefines = false; if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) { configDependentFlags = cmGeneratorExpression::Find(cflags) != std::string::npos; flags += cflags; } if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) { + configDependentDefines = + cmGeneratorExpression::Find(cdefs) != std::string::npos; defines += cdefs; } std::string lang = @@ -2121,6 +2124,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( if (!configDefines.empty()) { configDefines += ";"; } + configDependentDefines |= + cmGeneratorExpression::Find(ccdefs) != std::string::npos; configDefines += ccdefs; } // if we have flags or defines for this config then @@ -2170,7 +2175,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( clOptions.AppendFlag("DisableSpecificWarnings", "%(DisableSpecificWarnings)"); } - clOptions.AddDefines(configDefines.c_str()); + if (configDependentDefines) { + clOptions.AddDefines(genexInterpreter.Evaluate(configDefines)); + } else { + clOptions.AddDefines(configDefines.c_str()); + } clOptions.SetConfiguration((*config).c_str()); clOptions.PrependInheritedString("AdditionalOptions"); clOptions.OutputFlagMap(*this->BuildFileStream, " "); diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index 83fd11d..5165970 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -258,8 +258,13 @@ add_custom_target(check-part4 ALL VERBATIM ) -add_executable(srcgenex srcgenex.c) -set_property(SOURCE srcgenex.c PROPERTY COMPILE_FLAGS "-DNAME=$") +#----------------------------------------------------------------------------- +# Cover source file properties with generator expressions. +add_executable(srcgenex_flags srcgenex_flags.c) +set_property(SOURCE srcgenex_flags.c PROPERTY COMPILE_FLAGS "-DNAME=$") + +add_executable(srcgenex_defs srcgenex_defs.c) +set_property(SOURCE srcgenex_defs.c PROPERTY COMPILE_DEFINITIONS NAME=$) #----------------------------------------------------------------------------- # Cover test properties with generator expressions. diff --git a/Tests/GeneratorExpression/srcgenex.c b/Tests/GeneratorExpression/srcgenex.c deleted file mode 100644 index 56d3c3f..0000000 --- a/Tests/GeneratorExpression/srcgenex.c +++ /dev/null @@ -1,12 +0,0 @@ -int srcgenex(void) -{ - return 0; -} - -int main(int argc, char* argv[]) -{ -#ifndef NAME -#error NAME not defined -#endif - return NAME(); -} diff --git a/Tests/GeneratorExpression/srcgenex_defs.c b/Tests/GeneratorExpression/srcgenex_defs.c new file mode 100644 index 0000000..883e631 --- /dev/null +++ b/Tests/GeneratorExpression/srcgenex_defs.c @@ -0,0 +1,12 @@ +int srcgenex_defs(void) +{ + return 0; +} + +int main(int argc, char* argv[]) +{ +#ifndef NAME +#error NAME not defined +#endif + return NAME(); +} diff --git a/Tests/GeneratorExpression/srcgenex_flags.c b/Tests/GeneratorExpression/srcgenex_flags.c new file mode 100644 index 0000000..3de2b12 --- /dev/null +++ b/Tests/GeneratorExpression/srcgenex_flags.c @@ -0,0 +1,12 @@ +int srcgenex_flags(void) +{ + return 0; +} + +int main(int argc, char* argv[]) +{ +#ifndef NAME +#error NAME not defined +#endif + return NAME(); +} diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-result.txt b/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-stderr.txt b/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-stderr.txt new file mode 100644 index 0000000..46a294d --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions-stderr.txt @@ -0,0 +1,8 @@ +^CMake Error in CMakeLists.txt: + Xcode does not support per-config per-source COMPILE_DEFINITIONS: + + \$<\$:MYDEBUG> + + specified for source: + + .*/Tests/RunCMake/XcodeProject/main.c$ diff --git a/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions.cmake b/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions.cmake new file mode 100644 index 0000000..f9df55f --- /dev/null +++ b/Tests/RunCMake/XcodeProject/PerConfigPerSourceDefinitions.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_executable(main main.c) +set_property(SOURCE main.c PROPERTY COMPILE_DEFINITIONS "$<$:MYDEBUG>") diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index f730b83..7eb624c 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -19,6 +19,7 @@ if (NOT XCODE_VERSION VERSION_LESS 6) endif() run_cmake(PerConfigPerSourceFlags) +run_cmake(PerConfigPerSourceDefinitions) # Use a single build tree for a few tests without cleaning. -- cgit v0.12