diff --git a/Help/prop_sf/COMPILE_DEFINITIONS.rst b/Help/prop_sf/COMPILE_DEFINITIONS.rst index 1626825f1a..8d2108c48c 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 0000000000..892344f99e --- /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 2443ece243..bd1b6bbfc5 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 63f708bfad..bbf41751e8 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 e5c8317743..53966cdf3b 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 85dc55e698..5e0c5828cf 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 bad41128b7..1036977fc1 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 1bb07e7f7f..da354bdb20 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 badd24f123..8589a966ae 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 83fd11d658..5165970514 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_defs.c similarity index 82% rename from Tests/GeneratorExpression/srcgenex.c rename to Tests/GeneratorExpression/srcgenex_defs.c index 56d3c3f957..883e6317bd 100644 --- a/Tests/GeneratorExpression/srcgenex.c +++ b/Tests/GeneratorExpression/srcgenex_defs.c @@ -1,4 +1,4 @@ -int srcgenex(void) +int srcgenex_defs(void) { return 0; } diff --git a/Tests/GeneratorExpression/srcgenex_flags.c b/Tests/GeneratorExpression/srcgenex_flags.c new file mode 100644 index 0000000000..3de2b12d69 --- /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 0000000000..d00491fd7e --- /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 0000000000..46a294d92c --- /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 0000000000..f9df55fe9d --- /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 f730b835b9..7eb624c0e8 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.