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)
This commit is contained in:
commit
070f09f91e
|
@ -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.
|
||||
|
|
|
@ -709,6 +709,15 @@ cmXCodeObject* cmGlobalXCodeGenerator
|
|||
return obj;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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",
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue