From 28db2268e8e36521626071a39596b9aaa87defbb Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sat, 2 Jan 2016 17:57:06 +0100 Subject: Xcode: Factor out XCODE_ATTRIBUTE_ variant filter (#14947) Move the variant= filter out to a helper function so that it can be re-used later for CMAKE_XCODE_ATTRIBUTE_*. --- Source/cmGlobalXCodeGenerator.cxx | 68 +++++++++++++++++++++++---------------- Source/cmGlobalXCodeGenerator.h | 2 ++ 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 475efa8..c9d2742 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1656,6 +1656,46 @@ std::string cmGlobalXCodeGenerator::ExtractFlagRegex(const char* exp, return retFlag; } + //---------------------------------------------------------------------------- +// This function strips off Xcode attributes that do not target the current +// configuration +void +cmGlobalXCodeGenerator +::FilterConfigurationAttribute(std::string const& configName, + std::string& attribute) +{ + // Handle [variant=] condition explicitly here. + std::string::size_type beginVariant = attribute.find("[variant="); + if (beginVariant == std::string::npos) + { + // There is no variant in this attribute. + return; + } + + std::string::size_type endVariant = attribute.find("]", beginVariant+9); + if (endVariant == std::string::npos) + { + // There is no terminating bracket. + return; + } + + // Compare the variant to the configuration. + std::string variant = + attribute.substr(beginVariant+9, endVariant-beginVariant-9); + if (variant == configName) + { + // The variant matches the configuration so use this + // attribute but drop the [variant=] condition. + attribute.erase(beginVariant, endVariant-beginVariant+1); + } + else + { + // The variant does not match the configuration so + // do not use this attribute. + attribute.clear(); + } +} + //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, @@ -2498,33 +2538,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if(i->find("XCODE_ATTRIBUTE_") == 0) { std::string attribute = i->substr(16); - // Handle [variant=] condition explicitly here. - std::string::size_type beginVariant = - attribute.find("[variant="); - if (beginVariant != std::string::npos) - { - std::string::size_type endVariant = - attribute.find("]", beginVariant+9); - if (endVariant != std::string::npos) - { - // Compare the variant to the configuration. - std::string variant = - attribute.substr(beginVariant+9, endVariant-beginVariant-9); - if (variant == configName) - { - // The variant matches the configuration so use this - // attribute but drop the [variant=] condition. - attribute.erase(beginVariant, endVariant-beginVariant+1); - } - else - { - // The variant does not match the configuration so - // do not use this attribute. - attribute.clear(); - } - } - } - + this->FilterConfigurationAttribute(configName, attribute); if (!attribute.empty()) { cmGeneratorExpression ge; diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index c8a39df..4801064 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -153,6 +153,8 @@ private: std::string ExtractFlag(const char* flag, std::string& flags); std::string ExtractFlagRegex(const char* exp, int matchIndex, std::string& flags); + void FilterConfigurationAttribute(std::string const& configName, + std::string& attribute); void SortXCodeObjects(); // delete all objects in the this->XCodeObjects vector. void ClearXCodeObjects(); -- cgit v0.12 From 28f98ceef1770fe252c0c3c1e59aca773cc64009 Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 3 Jan 2016 11:53:38 +0100 Subject: Xcode: Make CMAKE_XCODE_ATTRIBUTE calculation last step (#14947) --- Source/cmGlobalXCodeGenerator.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index c9d2742..6f192cb 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3527,6 +3527,10 @@ bool cmGlobalXCodeGenerator this->CreateString(this->GeneratorToolset.c_str())); } + std::string symroot = root->GetCurrentBinaryDirectory(); + symroot += "/build"; + buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot.c_str())); + // Put this last so it can override existing settings // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly. { @@ -3543,10 +3547,6 @@ bool cmGlobalXCodeGenerator } } - std::string symroot = root->GetCurrentBinaryDirectory(); - symroot += "/build"; - buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot.c_str())); - for( std::vector::iterator i = configs.begin(); i != configs.end(); ++i) { -- cgit v0.12 From dc0ddb9e34f885d32f0fa3bb25072ec77e4a79bb Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 3 Jan 2016 11:58:52 +0100 Subject: Xcode: Store configuration name along with XcodeObject (#14947) --- Source/cmGlobalXCodeGenerator.cxx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 6f192cb..3ac1137 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3440,18 +3440,19 @@ bool cmGlobalXCodeGenerator this->CreateObject(cmXCodeObject::XCConfigurationList); cmXCodeObject* buildConfigurations = this->CreateObject(cmXCodeObject::OBJECT_LIST); - std::vector configs; + typedef std::vector > Configs; + Configs configs; const char *defaultConfigName = "Debug"; if(this->XcodeVersion == 15) { cmXCodeObject* configDebug = this->CreateObject(cmXCodeObject::XCBuildConfiguration); configDebug->AddAttribute("name", this->CreateString("Debug")); - configs.push_back(configDebug); + configs.push_back(std::make_pair("Debug", configDebug)); cmXCodeObject* configRelease = this->CreateObject(cmXCodeObject::XCBuildConfiguration); configRelease->AddAttribute("name", this->CreateString("Release")); - configs.push_back(configRelease); + configs.push_back(std::make_pair("Release", configRelease)); } else { @@ -3465,13 +3466,12 @@ bool cmGlobalXCodeGenerator cmXCodeObject* config = this->CreateObject(cmXCodeObject::XCBuildConfiguration); config->AddAttribute("name", this->CreateString(name)); - configs.push_back(config); + configs.push_back(std::make_pair(name, config)); } } - for(std::vector::iterator c = configs.begin(); - c != configs.end(); ++c) + for(Configs::iterator c = configs.begin(); c != configs.end(); ++c) { - buildConfigurations->AddObject(*c); + buildConfigurations->AddObject(c->second); } configlist->AddAttribute("buildConfigurations", buildConfigurations); @@ -3547,10 +3547,9 @@ bool cmGlobalXCodeGenerator } } - for( std::vector::iterator i = configs.begin(); - i != configs.end(); ++i) + for(Configs::iterator i = configs.begin(); i != configs.end(); ++i) { - (*i)->AddAttribute("buildSettings", buildSettings); + i->second->AddAttribute("buildSettings", buildSettings); } this->RootObject->AddAttribute("buildConfigurationList", -- cgit v0.12 From d8bc26a065f1999698c9b499ca793f9adf740a9d Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Sun, 3 Jan 2016 11:55:50 +0100 Subject: Xcode: Parse variant and genex for CMAKE_XCODE_ATTRIBUTE (#14947) --- .../CMAKE_XCODE_ATTRIBUTE_an-attribute.rst | 6 +++ Source/cmGlobalXCodeGenerator.cxx | 49 +++++++++++++++------- Source/cmGlobalXCodeGenerator.h | 1 + .../XcodeProject/XcodeAttributeGenex-check.cmake | 48 +++++++++++++++++++++ .../XcodeProject/XcodeAttributeGenex.cmake | 14 ++++++- 5 files changed, 101 insertions(+), 17 deletions(-) diff --git a/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst b/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst index 122b9f6..be683d6 100644 --- a/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst +++ b/Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst @@ -8,3 +8,9 @@ in the generated Xcode project. Ignored on other generators. See the :prop_tgt:`XCODE_ATTRIBUTE_` target property to set attributes on a specific target. + +Contents of ``CMAKE_XCODE_ATTRIBUTE_`` may use +"generator expressions" with the syntax ``$<...>``. See the +:manual:`cmake-generator-expressions(7)` manual for available +expressions. See the :manual:`cmake-buildsystem(7)` manual +for more on defining buildsystem properties. diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 3ac1137..fa9af12 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -710,6 +710,15 @@ cmXCodeObject* cmGlobalXCodeGenerator } //---------------------------------------------------------------------------- +cmXCodeObject* cmGlobalXCodeGenerator +::CreateFlatClone(cmXCodeObject* orig) +{ + cmXCodeObject* obj = this->CreateObject(orig->GetType()); + obj->CopyAttributes(orig); + return obj; +} + +//---------------------------------------------------------------------------- std::string GetGroupMapKeyFromPath(cmGeneratorTarget* target, const std::string& fullpath) { @@ -3531,25 +3540,33 @@ bool cmGlobalXCodeGenerator symroot += "/build"; buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot.c_str())); - // Put this last so it can override existing settings - // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly. - { - std::vector vars = this->CurrentMakefile->GetDefinitions(); - for(std::vector::const_iterator i = vars.begin(); - i != vars.end(); ++i) + for(Configs::iterator i = configs.begin(); i != configs.end(); ++i) { - if(i->find("CMAKE_XCODE_ATTRIBUTE_") == 0) + cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings); + + // Put this last so it can override existing settings + // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly. + std::vector vars = this->CurrentMakefile->GetDefinitions(); + for(std::vector::const_iterator d = vars.begin(); + d != vars.end(); ++d) { - buildSettings->AddAttribute(i->substr(22).c_str(), - this->CreateString( - this->CurrentMakefile->GetDefinition(i->c_str()))); + if(d->find("CMAKE_XCODE_ATTRIBUTE_") == 0) + { + std::string attribute = d->substr(22); + this->FilterConfigurationAttribute(i->first, attribute); + if(!attribute.empty()) + { + cmGeneratorExpression ge; + std::string processed = + ge.Parse(this->CurrentMakefile->GetDefinition(*d)) + ->Evaluate(this->CurrentLocalGenerator, i->first); + buildSettingsForCfg->AddAttribute(attribute, + this->CreateString(processed)); + } + } } - } - } - - for(Configs::iterator i = configs.begin(); i != configs.end(); ++i) - { - i->second->AddAttribute("buildSettings", buildSettings); + // store per-config buildSettings into configuration object + i->second->AddAttribute("buildSettings", buildSettingsForCfg); } this->RootObject->AddAttribute("buildConfigurationList", diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 4801064..9659822 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -131,6 +131,7 @@ private: cmXCodeObject* CreateObject(cmXCodeObject::Type type); cmXCodeObject* CreateString(const std::string& s); cmXCodeObject* CreateObjectReference(cmXCodeObject*); + cmXCodeObject* CreateFlatClone(cmXCodeObject*); cmXCodeObject* CreateXCodeTarget(cmGeneratorTarget *gtgt, cmXCodeObject* buildPhases); void ForceLinkerLanguages(); diff --git a/Tests/RunCMake/XcodeProject/XcodeAttributeGenex-check.cmake b/Tests/RunCMake/XcodeProject/XcodeAttributeGenex-check.cmake index 637df0f..8a39506 100644 --- a/Tests/RunCMake/XcodeProject/XcodeAttributeGenex-check.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeAttributeGenex-check.cmake @@ -1,3 +1,5 @@ +# per target attribute with genex + set(expect "TEST_HOST = \"[^;\"]*Tests/RunCMake/XcodeProject/XcodeAttributeGenex-build/[^;\"/]*/some\"") file(STRINGS ${RunCMake_TEST_BINARY_DIR}/XcodeAttributeGenex.xcodeproj/project.pbxproj actual REGEX "TEST_HOST = .*;" LIMIT_COUNT 1) @@ -5,3 +7,49 @@ if(NOT "${actual}" MATCHES "${expect}") message(SEND_ERROR "The actual project contains the line:\n ${actual}\n" "which does not match expected regex:\n ${expect}\n") endif() + +# per target attribute with variant + +file(STRINGS ${RunCMake_TEST_BINARY_DIR}/XcodeAttributeGenex.xcodeproj/project.pbxproj actual + REGEX "CONFIG_SPECIFIC = .*;") +list(REMOVE_DUPLICATES actual) + +set(expect "CONFIG_SPECIFIC = general") +if(NOT "${actual}" MATCHES "${expect}") + message(SEND_ERROR "The actual project contains the line:\n ${actual}\n" + "which does not match expected regex:\n ${expect}\n") +endif() + +set(expect "CONFIG_SPECIFIC = release") +if(NOT "${actual}" MATCHES "${expect}") + message(SEND_ERROR "The actual project contains the line:\n ${actual}\n" + "which does not match expected regex:\n ${expect}\n") +endif() + +# global attribute with genex + +set(expect "ANOTHER_GLOBAL = \"[^;\"]*Tests/RunCMake/XcodeProject/XcodeAttributeGenex-build/[^;\"/]*/another\"") +file(STRINGS ${RunCMake_TEST_BINARY_DIR}/XcodeAttributeGenex.xcodeproj/project.pbxproj actual + REGEX "ANOTHER_GLOBAL = .*;" LIMIT_COUNT 1) +if(NOT "${actual}" MATCHES "${expect}") + message(SEND_ERROR "The actual project contains the line:\n ${actual}\n" + "which does not match expected regex:\n ${expect}\n") +endif() + +# global attribute with variant + +file(STRINGS ${RunCMake_TEST_BINARY_DIR}/XcodeAttributeGenex.xcodeproj/project.pbxproj actual + REGEX "ANOTHER_CONFIG = .*;" LIMIT_COUNT 4) +list(REMOVE_DUPLICATES actual) + +set(expect "ANOTHER_CONFIG = general") +if(NOT "${actual}" MATCHES "${expect}") + message(SEND_ERROR "The actual project contains the line:\n ${actual}\n" + "which does not match expected regex:\n ${expect}\n") +endif() + +set(expect "ANOTHER_CONFIG = debug") +if(NOT "${actual}" MATCHES "${expect}") + message(SEND_ERROR "The actual project contains the line:\n ${actual}\n" + "which does not match expected regex:\n ${expect}\n") +endif() diff --git a/Tests/RunCMake/XcodeProject/XcodeAttributeGenex.cmake b/Tests/RunCMake/XcodeProject/XcodeAttributeGenex.cmake index 760b882..d8cb3bd 100644 --- a/Tests/RunCMake/XcodeProject/XcodeAttributeGenex.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeAttributeGenex.cmake @@ -1,4 +1,16 @@ enable_language(C) add_executable(some main.c) add_executable(another main.c) -set_property(TARGET another PROPERTY XCODE_ATTRIBUTE_TEST_HOST "$") +set_target_properties(another PROPERTIES + # per target attribute with genex + XCODE_ATTRIBUTE_TEST_HOST "$" + # per target attribute with variant + XCODE_ATTRIBUTE_CONFIG_SPECIFIC[variant=Release] "release" + XCODE_ATTRIBUTE_CONFIG_SPECIFIC "general") + +# global attribute with genex +set(CMAKE_XCODE_ATTRIBUTE_ANOTHER_GLOBAL "$") + +# global attribute with variant +set(CMAKE_XCODE_ATTRIBUTE_ANOTHER_CONFIG "general") +set(CMAKE_XCODE_ATTRIBUTE_ANOTHER_CONFIG[variant=Debug] "debug") -- cgit v0.12