in Source/cmGlobalXCodeGenerator.cxx [2315:2971]
void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
const std::string& configName)
{
if (!gtgt->IsInBuildSystem()) {
return;
}
std::string defFlags;
bool shared = ((gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) ||
(gtgt->GetType() == cmStateEnums::MODULE_LIBRARY));
bool binary = ((gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
(gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) ||
(gtgt->GetType() == cmStateEnums::EXECUTABLE) || shared);
// Compute the compilation flags for each language.
std::set<std::string> languages;
gtgt->GetLanguages(languages, configName);
std::map<std::string, std::string> cflags;
for (auto const& lang : languages) {
std::string& flags = cflags[lang];
// Add language-specific flags.
this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang,
configName);
if (gtgt->IsIPOEnabled(lang, configName)) {
this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
}
// Add shared-library flags if needed.
this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang,
configName);
this->CurrentLocalGenerator->AddVisibilityPresetFlags(flags, gtgt, lang);
this->CurrentLocalGenerator->AddCompileOptions(flags, gtgt, lang,
configName);
}
std::string llang = gtgt->GetLinkerLanguage(configName);
if (binary && llang.empty()) {
cmSystemTools::Error(
"CMake can not determine linker language for target: " +
gtgt->GetName());
return;
}
std::string const& langForPreprocessor = llang;
if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue =
this->CurrentMakefile->IsOn("_CMAKE_LTO_THIN") ? "YES_THIN" : "YES";
buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
}
// Handle PIE linker configuration
this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName);
// Add define flags
this->CurrentLocalGenerator->AppendFlags(
defFlags, this->CurrentMakefile->GetDefineFlags());
// Add preprocessor definitions for this target and configuration.
BuildObjectListOrString ppDefs(this, true);
this->AppendDefines(
ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
if (const std::string* exportMacro = gtgt->GetExportMacro()) {
// Add the export symbol definition for shared library objects.
this->AppendDefines(ppDefs, exportMacro->c_str());
}
std::vector<std::string> targetDefines;
if (!langForPreprocessor.empty()) {
gtgt->GetCompileDefinitions(targetDefines, configName,
langForPreprocessor);
}
this->AppendDefines(ppDefs, targetDefines);
buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
ppDefs.CreateList());
std::string extraLinkOptionsVar;
std::string extraLinkOptions;
if (gtgt->GetType() == cmStateEnums::EXECUTABLE) {
extraLinkOptionsVar = "CMAKE_EXE_LINKER_FLAGS";
} else if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) {
extraLinkOptionsVar = "CMAKE_SHARED_LINKER_FLAGS";
} else if (gtgt->GetType() == cmStateEnums::MODULE_LIBRARY) {
extraLinkOptionsVar = "CMAKE_MODULE_LINKER_FLAGS";
}
if (!extraLinkOptionsVar.empty()) {
this->CurrentLocalGenerator->AddConfigVariableFlags(
extraLinkOptions, extraLinkOptionsVar, configName);
}
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) {
this->CurrentLocalGenerator->GetStaticLibraryFlags(
extraLinkOptions, configName, llang, gtgt);
} else {
cmValue targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions,
*targetLinkFlags);
}
if (!configName.empty()) {
std::string linkFlagsVar =
cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName));
if (cmValue linkFlags = gtgt->GetProperty(linkFlagsVar)) {
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, *linkFlags);
}
}
std::vector<std::string> opts;
gtgt->GetLinkOptions(opts, configName, llang);
// LINK_OPTIONS are escaped.
this->CurrentLocalGenerator->AppendCompileOptions(extraLinkOptions, opts);
}
// Set target-specific architectures.
std::vector<std::string> archs;
gtgt->GetAppleArchs(configName, archs);
if (!archs.empty()) {
// Enable ARCHS attribute.
buildSettings->AddAttribute("ONLY_ACTIVE_ARCH", this->CreateString("NO"));
// Store ARCHS value.
if (archs.size() == 1) {
buildSettings->AddAttribute("ARCHS", this->CreateString(archs[0]));
} else {
cmXCodeObject* archObjects =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
for (auto& arch : archs) {
archObjects->AddObject(this->CreateString(arch));
}
buildSettings->AddAttribute("ARCHS", archObjects);
}
}
// Get the product name components.
std::string pnprefix;
std::string pnbase;
std::string pnsuffix;
gtgt->GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
cmValue version = gtgt->GetProperty("VERSION");
cmValue soversion = gtgt->GetProperty("SOVERSION");
if (!gtgt->HasSOName(configName) || gtgt->IsFrameworkOnApple()) {
version = nullptr;
soversion = nullptr;
}
if (version && !soversion) {
soversion = version;
}
if (!version && soversion) {
version = soversion;
}
std::string realName = pnbase;
std::string soName = pnbase;
if (version && soversion) {
realName += ".";
realName += *version;
soName += ".";
soName += *soversion;
}
// Set attributes to specify the proper name for the target.
std::string pndir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
if (gtgt->GetType() == cmStateEnums::STATIC_LIBRARY ||
gtgt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gtgt->GetType() == cmStateEnums::MODULE_LIBRARY ||
gtgt->GetType() == cmStateEnums::EXECUTABLE) {
if (!gtgt->UsesDefaultOutputDir(configName,
cmStateEnums::RuntimeBinaryArtifact)) {
std::string pncdir = gtgt->GetDirectory(configName);
buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
this->CreateString(pncdir));
}
if (gtgt->IsFrameworkOnApple() || gtgt->IsCFBundleOnApple()) {
pnprefix = "";
}
buildSettings->AddAttribute("EXECUTABLE_PREFIX",
this->CreateString(pnprefix));
buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
this->CreateString(pnsuffix));
} else if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
pnprefix = "lib";
pnbase = gtgt->GetName();
pnsuffix = ".a";
std::string pncdir = this->GetObjectsDirectory(
this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR);
buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
this->CreateString(pncdir));
}
// Store the product name for all target types.
buildSettings->AddAttribute("PRODUCT_NAME", this->CreateString(realName));
buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir));
// Handle settings for each target type.
switch (gtgt->GetType()) {
case cmStateEnums::STATIC_LIBRARY:
if (gtgt->GetPropertyAsBool("FRAMEWORK")) {
std::string fw_version = gtgt->GetFrameworkVersion();
buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(fw_version));
cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
}
std::string plist = this->ComputeInfoPListLocation(gtgt);
// Xcode will create the final version of Info.plist at build time,
// so let it replace the framework name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateFrameworkInfoPList(
gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
buildSettings->AddAttribute("MACH_O_TYPE",
this->CreateString("staticlib"));
} else {
buildSettings->AddAttribute("LIBRARY_STYLE",
this->CreateString("STATIC"));
}
break;
case cmStateEnums::OBJECT_LIBRARY: {
buildSettings->AddAttribute("LIBRARY_STYLE",
this->CreateString("STATIC"));
break;
}
case cmStateEnums::MODULE_LIBRARY: {
buildSettings->AddAttribute("LIBRARY_STYLE",
this->CreateString("BUNDLE"));
if (gtgt->IsCFBundleOnApple()) {
// It turns out that a BUNDLE is basically the same
// in many ways as an application bundle, as far as
// link flags go
std::string createFlags = this->LookupFlags(
"CMAKE_SHARED_MODULE_CREATE_", llang, "_FLAGS", "-bundle");
if (!createFlags.empty()) {
extraLinkOptions += " ";
extraLinkOptions += createFlags;
}
cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
}
std::string plist = this->ComputeInfoPListLocation(gtgt);
// Xcode will create the final version of Info.plist at build time,
// so let it replace the cfbundle name. This avoids creating
// a per-configuration Info.plist file. The cfbundle plist
// is very similar to the application bundle plist
this->CurrentLocalGenerator->GenerateAppleInfoPList(
gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
} else {
buildSettings->AddAttribute("MACH_O_TYPE",
this->CreateString("mh_bundle"));
buildSettings->AddAttribute("GCC_DYNAMIC_NO_PIC",
this->CreateString("NO"));
// Add the flags to create an executable.
std::string createFlags =
this->LookupFlags("CMAKE_", llang, "_LINK_FLAGS", "");
if (!createFlags.empty()) {
extraLinkOptions += " ";
extraLinkOptions += createFlags;
}
}
break;
}
case cmStateEnums::SHARED_LIBRARY: {
if (gtgt->GetPropertyAsBool("FRAMEWORK")) {
std::string fw_version = gtgt->GetFrameworkVersion();
buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(fw_version));
cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
}
std::string plist = this->ComputeInfoPListLocation(gtgt);
// Xcode will create the final version of Info.plist at build time,
// so let it replace the framework name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateFrameworkInfoPList(
gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
} else {
// Add the flags to create a shared library.
std::string createFlags = this->LookupFlags(
"CMAKE_SHARED_LIBRARY_CREATE_", llang, "_FLAGS", "-dynamiclib");
if (!createFlags.empty()) {
extraLinkOptions += " ";
extraLinkOptions += createFlags;
}
}
buildSettings->AddAttribute("LIBRARY_STYLE",
this->CreateString("DYNAMIC"));
break;
}
case cmStateEnums::EXECUTABLE: {
// Add the flags to create an executable.
std::string createFlags =
this->LookupFlags("CMAKE_", llang, "_LINK_FLAGS", "");
if (!createFlags.empty()) {
extraLinkOptions += " ";
extraLinkOptions += createFlags;
}
// Handle bundles and normal executables separately.
if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
}
std::string plist = this->ComputeInfoPListLocation(gtgt);
// Xcode will create the final version of Info.plist at build time,
// so let it replace the executable name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateAppleInfoPList(
gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
}
} break;
default:
break;
}
BuildObjectListOrString dirs(this, true);
BuildObjectListOrString fdirs(this, true);
BuildObjectListOrString sysdirs(this, true);
BuildObjectListOrString sysfdirs(this, true);
const bool emitSystemIncludes = this->XcodeVersion >= 83;
std::vector<std::string> includes;
if (!langForPreprocessor.empty()) {
this->CurrentLocalGenerator->GetIncludeDirectories(
includes, gtgt, langForPreprocessor, configName);
}
std::set<std::string> emitted;
emitted.insert("/System/Library/Frameworks");
for (auto& include : includes) {
if (this->NameResolvesToFramework(include)) {
std::string frameworkDir = cmStrCat(include, "/../");
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
if (emitted.insert(frameworkDir).second) {
std::string incpath = this->XCodeEscapePath(frameworkDir);
if (emitSystemIncludes &&
gtgt->IsSystemIncludeDirectory(frameworkDir, configName,
langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
}
}
} else {
std::string incpath = this->XCodeEscapePath(include);
if (emitSystemIncludes &&
gtgt->IsSystemIncludeDirectory(include, configName,
langForPreprocessor)) {
sysdirs.Add(incpath);
} else {
dirs.Add(incpath);
}
}
}
// Add framework search paths needed for linking.
if (cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) {
for (auto const& fwDir : cli->GetFrameworkPaths()) {
if (emitted.insert(fwDir).second) {
std::string incpath = this->XCodeEscapePath(fwDir);
if (emitSystemIncludes &&
gtgt->IsSystemIncludeDirectory(fwDir, configName,
langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
}
}
}
}
if (!fdirs.IsEmpty()) {
buildSettings->AddAttribute("FRAMEWORK_SEARCH_PATHS", fdirs.CreateList());
}
if (!dirs.IsEmpty()) {
buildSettings->AddAttribute("HEADER_SEARCH_PATHS", dirs.CreateList());
}
if (!sysfdirs.IsEmpty()) {
buildSettings->AddAttribute("SYSTEM_FRAMEWORK_SEARCH_PATHS",
sysfdirs.CreateList());
}
if (!sysdirs.IsEmpty()) {
buildSettings->AddAttribute("SYSTEM_HEADER_SEARCH_PATHS",
sysdirs.CreateList());
}
if (this->XcodeVersion >= 60 && !emitSystemIncludes) {
// Add those per-language flags in addition to HEADER_SEARCH_PATHS to gain
// system include directory awareness. We need to also keep on setting
// HEADER_SEARCH_PATHS to work around a missing compile options flag for
// GNU assembly files (#16449)
for (auto const& language : languages) {
std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags(
includes, gtgt, language, configName);
if (!includeFlags.empty()) {
cflags[language] += " " + includeFlags;
}
}
}
bool same_gflags = true;
std::map<std::string, std::string> gflags;
std::string const* last_gflag = nullptr;
std::string optLevel = "0";
// Minimal map of flags to build settings.
for (auto const& language : languages) {
std::string& flags = cflags[language];
std::string& gflag = gflags[language];
std::string oflag =
this->ExtractFlagRegex("(^| )(-Ofast|-Os|-O[0-9]*)( |$)", 2, flags);
if (oflag.size() == 2) {
optLevel = "1";
} else if (oflag.size() > 2) {
optLevel = oflag.substr(2);
}
gflag = this->ExtractFlag("-g", flags);
// put back gdwarf-2 if used since there is no way
// to represent it in the gui, but we still want debug yes
if (gflag == "-gdwarf-2") {
flags += " ";
flags += gflag;
}
if (last_gflag && *last_gflag != gflag) {
same_gflags = false;
}
last_gflag = &gflag;
}
const char* debugStr = "YES";
if (!same_gflags) {
// We can't set the Xcode flag differently depending on the language,
// so put them back in this case.
for (auto const& language : languages) {
cflags[language] += " ";
cflags[language] += gflags[language];
}
debugStr = "NO";
} else if (last_gflag && (last_gflag->empty() || *last_gflag == "-g0")) {
debugStr = "NO";
}
// extract C++ stdlib
for (auto const& language : languages) {
if (language != "CXX" && language != "OBJCXX") {
continue;
}
std::string& flags = cflags[language];
auto stdlib =
this->ExtractFlagRegex("(^| )(-stdlib=[^ ]+)( |$)", 2, flags);
if (stdlib.size() > 8) {
const auto cxxLibrary = stdlib.substr(8);
if (language == "CXX" ||
!buildSettings->GetAttribute("CLANG_CXX_LIBRARY")) {
buildSettings->AddAttribute("CLANG_CXX_LIBRARY",
this->CreateString(cxxLibrary));
}
}
}
buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES",
this->CreateString("YES"));
buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
this->CreateString(debugStr));
buildSettings->AddAttribute("GCC_OPTIMIZATION_LEVEL",
this->CreateString(optLevel));
buildSettings->AddAttribute("GCC_SYMBOLS_PRIVATE_EXTERN",
this->CreateString("NO"));
buildSettings->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
this->CreateString("NO"));
for (auto const& language : languages) {
std::string flags = cflags[language] + " " + defFlags;
if (language == "CXX" || language == "OBJCXX") {
if (language == "CXX" ||
!buildSettings->GetAttribute("OTHER_CPLUSPLUSFLAGS")) {
buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS",
this->CreateString(flags));
}
} else if (language == "Fortran") {
buildSettings->AddAttribute("IFORT_OTHER_FLAGS",
this->CreateString(flags));
} else if (language == "C" || language == "OBJC") {
if (language == "C" || !buildSettings->GetAttribute("OTHER_CFLAGS")) {
buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags));
}
} else if (language == "Swift") {
buildSettings->AddAttribute("OTHER_SWIFT_FLAGS",
this->CreateString(flags));
}
}
// Add Fortran source format attribute if property is set.
const char* format = nullptr;
std::string const& tgtfmt = gtgt->GetSafeProperty("Fortran_FORMAT");
switch (cmOutputConverter::GetFortranFormat(tgtfmt)) {
case cmOutputConverter::FortranFormatFixed:
format = "fixed";
break;
case cmOutputConverter::FortranFormatFree:
format = "free";
break;
default:
break;
}
if (format) {
buildSettings->AddAttribute("IFORT_LANG_SRCFMT",
this->CreateString(format));
}
// Create the INSTALL_PATH attribute.
std::string install_name_dir;
if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) {
// Get the install_name directory for the build tree.
install_name_dir = gtgt->GetInstallNameDirForBuildTree(configName);
// Xcode doesn't create the correct install_name in some cases.
// That is, if the INSTALL_PATH is empty, or if we have versioning
// of dylib libraries, we want to specify the install_name.
// This is done by adding a link flag to create an install_name
// with just the library soname.
std::string install_name;
if (!install_name_dir.empty()) {
// Convert to a path for the native build tool.
cmSystemTools::ConvertToUnixSlashes(install_name_dir);
install_name += install_name_dir;
install_name += "/";
}
install_name += gtgt->GetSOName(configName);
if ((realName != soName) || install_name_dir.empty()) {
install_name_dir = "";
extraLinkOptions += " -install_name ";
extraLinkOptions += XCodeEscapePath(install_name);
}
}
buildSettings->AddAttribute("INSTALL_PATH",
this->CreateString(install_name_dir));
// Create the LD_RUNPATH_SEARCH_PATHS
cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName);
if (pcli) {
std::string search_paths;
std::vector<std::string> runtimeDirs;
pcli->GetRPath(runtimeDirs, false);
// runpath dirs needs to be unique to prevent corruption
std::set<std::string> unique_dirs;
for (auto runpath : runtimeDirs) {
runpath = this->ExpandCFGIntDir(runpath, configName);
if (unique_dirs.find(runpath) == unique_dirs.end()) {
unique_dirs.insert(runpath);
if (!search_paths.empty()) {
search_paths += " ";
}
search_paths += this->XCodeEscapePath(runpath);
}
}
if (!search_paths.empty()) {
buildSettings->AddAttribute("LD_RUNPATH_SEARCH_PATHS",
this->CreateString(search_paths));
}
}
buildSettings->AddAttribute(this->GetTargetLinkFlagsVar(gtgt),
this->CreateString(extraLinkOptions));
buildSettings->AddAttribute("OTHER_REZFLAGS", this->CreateString(""));
buildSettings->AddAttribute("SECTORDER_FLAGS", this->CreateString(""));
buildSettings->AddAttribute("USE_HEADERMAP", this->CreateString("NO"));
cmXCodeObject* group = this->CreateObject(cmXCodeObject::OBJECT_LIST);
group->AddObject(this->CreateString("$(inherited)"));
buildSettings->AddAttribute("WARNING_CFLAGS", group);
// Runtime version information.
if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) {
int major;
int minor;
int patch;
// MACHO_CURRENT_VERSION or VERSION -> current_version
gtgt->GetTargetVersionFallback("MACHO_CURRENT_VERSION", "VERSION", major,
minor, patch);
std::ostringstream v;
// Xcode always wants at least 1.0.0 or nothing
if (!(major == 0 && minor == 0 && patch == 0)) {
v << major << "." << minor << "." << patch;
}
buildSettings->AddAttribute("DYLIB_CURRENT_VERSION",
this->CreateString(v.str()));
// MACHO_COMPATIBILITY_VERSION or SOVERSION -> compatibility_version
gtgt->GetTargetVersionFallback("MACHO_COMPATIBILITY_VERSION", "SOVERSION",
major, minor, patch);
std::ostringstream vso;
// Xcode always wants at least 1.0.0 or nothing
if (!(major == 0 && minor == 0 && patch == 0)) {
vso << major << "." << minor << "." << patch;
}
buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
this->CreateString(vso.str()));
}
// Precompile Headers
std::string pchHeader = gtgt->GetPchHeader(configName, llang);
if (!pchHeader.empty()) {
buildSettings->AddAttribute("GCC_PREFIX_HEADER",
this->CreateString(pchHeader));
buildSettings->AddAttribute("GCC_PRECOMPILE_PREFIX_HEADER",
this->CreateString("YES"));
}
// put this last so it can override existing settings
// Convert "XCODE_ATTRIBUTE_*" properties directly.
{
for (auto const& prop : gtgt->GetPropertyKeys()) {
if (cmHasLiteralPrefix(prop, "XCODE_ATTRIBUTE_")) {
std::string attribute = prop.substr(16);
this->FilterConfigurationAttribute(configName, attribute);
if (!attribute.empty()) {
std::string const& pr = gtgt->GetSafeProperty(prop);
std::string processed = cmGeneratorExpression::Evaluate(
pr, this->CurrentLocalGenerator, configName);
buildSettings->AddAttribute(attribute,
this->CreateString(processed));
}
}
}
}
}