summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2016-01-07 18:28:28 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2016-01-07 18:28:28 (GMT)
commit070f09f91ea2ea903ad503925e4870aaf541d291 (patch)
treebe2464f6559e807d0f347ff3f311b99e2fead36b
parentf7fbe0f6811dcd656f8cf772c6d57199c92f0a5e (diff)
parentd8bc26a065f1999698c9b499ca793f9adf740a9d (diff)
downloadCMake-070f09f91ea2ea903ad503925e4870aaf541d291.zip
CMake-070f09f91ea2ea903ad503925e4870aaf541d291.tar.gz
CMake-070f09f91ea2ea903ad503925e4870aaf541d291.tar.bz2
Merge topic 'xcode-global-attribute-variant'
d8bc26a0 Xcode: Parse variant and genex for CMAKE_XCODE_ATTRIBUTE (#14947) dc0ddb9e Xcode: Store configuration name along with XcodeObject (#14947) 28f98cee Xcode: Make CMAKE_XCODE_ATTRIBUTE calculation last step (#14947) 28db2268 Xcode: Factor out XCODE_ATTRIBUTE_ variant filter (#14947)
-rw-r--r--Help/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute.rst6
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx136
-rw-r--r--Source/cmGlobalXCodeGenerator.h3
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeAttributeGenex-check.cmake48
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeAttributeGenex.cmake14
5 files changed, 153 insertions, 54 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_<an-attribute>` target property
to set attributes on a specific target.
+
+Contents of ``CMAKE_XCODE_ATTRIBUTE_<an-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 3449648..526e32f 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)
{
@@ -1656,6 +1665,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=<config>] 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=<config>] 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,
@@ -2491,33 +2540,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if(i->find("XCODE_ATTRIBUTE_") == 0)
{
std::string attribute = i->substr(16);
- // Handle [variant=<config>] 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=<config>] 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;
@@ -3419,18 +3442,19 @@ bool cmGlobalXCodeGenerator
this->CreateObject(cmXCodeObject::XCConfigurationList);
cmXCodeObject* buildConfigurations =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
- std::vector<cmXCodeObject*> configs;
+ typedef std::vector<std::pair<std::string, cmXCodeObject*> > 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
{
@@ -3444,13 +3468,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<cmXCodeObject*>::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);
@@ -3506,30 +3529,37 @@ bool cmGlobalXCodeGenerator
this->CreateString(this->GeneratorToolset.c_str()));
}
- // Put this last so it can override existing settings
- // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly.
- {
- std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions();
- for(std::vector<std::string>::const_iterator i = vars.begin();
- i != vars.end(); ++i)
- {
- if(i->find("CMAKE_XCODE_ATTRIBUTE_") == 0)
- {
- buildSettings->AddAttribute(i->substr(22).c_str(),
- this->CreateString(
- this->CurrentMakefile->GetDefinition(i->c_str())));
- }
- }
- }
-
std::string symroot = root->GetCurrentBinaryDirectory();
symroot += "/build";
buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot.c_str()));
- for( std::vector<cmXCodeObject*>::iterator i = configs.begin();
- i != configs.end(); ++i)
+ for(Configs::iterator i = configs.begin(); i != configs.end(); ++i)
{
- (*i)->AddAttribute("buildSettings", buildSettings);
+ cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings);
+
+ // Put this last so it can override existing settings
+ // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly.
+ std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions();
+ for(std::vector<std::string>::const_iterator d = vars.begin();
+ d != vars.end(); ++d)
+ {
+ 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));
+ }
+ }
+ }
+ // 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 b5fd13c..862746f 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -130,6 +130,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();
@@ -152,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();
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 "$<TARGET_FILE:some>")
+set_target_properties(another PROPERTIES
+ # per target attribute with genex
+ XCODE_ATTRIBUTE_TEST_HOST "$<TARGET_FILE:some>"
+ # 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 "$<TARGET_FILE:another>")
+
+# global attribute with variant
+set(CMAKE_XCODE_ATTRIBUTE_ANOTHER_CONFIG "general")
+set(CMAKE_XCODE_ATTRIBUTE_ANOTHER_CONFIG[variant=Debug] "debug")