Xcode: Evaluate Swift compile definitions separately

Xcode has a separate setting for Swift compile definitions, so we can
compute a dedicated value for it.  Therefore we can:

* Support the COMPILE_LANGUAGE generator expression for Swift-specific
  filters.

* Avoid passing the `=value` part of definitions, which Swift does
  not support.

This revises commit 5cb625eb2f (Xcode: Pass compile definitions to
Swift, 2022-06-19, v3.25.0-rc1~493^2) and reverts commit 12c6fec6b4
(Xcode: Drop CMAKE_INTDIR= definition in Swift targets, 2022-09-30,
v3.25.0-rc1~60^2~2), as the latter is no longer needed.

Fixes: #24086
This commit is contained in:
Brad King 2022-10-25 11:56:34 -04:00
parent 19f49a7514
commit c0dd3dd2c1
4 changed files with 66 additions and 11 deletions

View File

@ -2387,7 +2387,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
gtgt->GetName());
return;
}
std::string const& langForPreprocessor = llang;
// Choose a language to use for target-wide preprocessor definitions.
static const char* ppLangs[] = { "CXX", "C", "OBJCXX", "OBJC" };
std::string langForPreprocessor;
if (cm::contains(ppLangs, llang)) {
langForPreprocessor = llang;
} else {
for (const char* l : ppLangs) {
if (languages.count(l)) {
langForPreprocessor = l;
break;
}
}
}
if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue =
@ -2404,13 +2417,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// Add preprocessor definitions for this target and configuration.
BuildObjectListOrString ppDefs(this, true);
if (languages.count("Swift")) {
// FIXME: Xcode warns that Swift does not support definition values.
// C/CXX sources mixed in Swift targets will not see CMAKE_INTDIR.
} else {
this->AppendDefines(
ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
}
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());
@ -2424,15 +2432,28 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
ppDefs.CreateList());
if (languages.count("Swift")) {
// Swift uses a separate attribute for definitions.
std::vector<std::string> targetSwiftDefines;
gtgt->GetCompileDefinitions(targetSwiftDefines, configName, "Swift");
// Remove the '=value' parts, as Swift does not support them.
std::for_each(targetSwiftDefines.begin(), targetSwiftDefines.end(),
[](std::string& def) {
std::string::size_type pos = def.find('=');
if (pos != std::string::npos) {
def.erase(pos);
}
});
if (this->XcodeVersion < 80) {
std::string defineString;
std::set<std::string> defines(targetDefines.begin(),
targetDefines.end());
std::set<std::string> defines(targetSwiftDefines.begin(),
targetSwiftDefines.end());
this->CurrentLocalGenerator->JoinDefines(defines, defineString, "Swift");
cflags["Swift"] += " " + defineString;
} else {
BuildObjectListOrString swiftDefs(this, true);
this->AppendDefines(swiftDefs, targetSwiftDefines);
buildSettings->AddAttribute("SWIFT_ACTIVE_COMPILATION_CONDITIONS",
ppDefs.CreateList());
swiftDefs.CreateList());
}
}

View File

@ -1,3 +1,16 @@
#if !defined(FOO)
# error "FOO not defined"
#endif
#if BAR != 3
# error "FOO not defined to 3"
#endif
#if CCOND != 2
# error "CCOND not defined to 2"
#endif
#if defined(SWIFTCOND)
# error "SWIFTCOND defined"
#endif
extern int ObjCMain(void);
int main(void)
{

View File

@ -4,3 +4,4 @@ project(SwiftMix C Swift)
add_executable(SwiftMix CMain.c ObjCMain.m SwiftMain.swift ObjC-Swift.h)
set_property(TARGET SwiftMix PROPERTY XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "ObjC-Swift.h")
target_compile_options(SwiftMix PRIVATE "$<$<COMPILE_LANGUAGE:C>:-Werror=objc-method-access>")
target_compile_definitions(SwiftMix PRIVATE "$<IF:$<COMPILE_LANGUAGE:Swift>,SWIFTCOND,CCOND=2>" FOO BAR=3)

View File

@ -3,6 +3,26 @@ import Foundation
@objc class SwiftMainClass : NSObject {
@objc class func SwiftMain() -> Int32 {
dump("Hello World!");
#if FOO
dump("FOO defined");
#else
fatalError("FOO not defined");
#endif
#if BAR
dump("BAR defined");
#else
fatalError("BAR not defined");
#endif
#if CCOND
fatalError("CCOND defined");
#else
dump("CCOND not defined");
#endif
#if SWIFTCOND
dump("SWIFTCOND defined");
#else
fatalError("SWIFTCOND not defined");
#endif
return 0;
}
}