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
+32 -11
View File
@@ -2387,7 +2387,20 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
gtgt->GetName()); gtgt->GetName());
return; 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)) { if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue = const char* ltoValue =
@@ -2404,13 +2417,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// Add preprocessor definitions for this target and configuration. // Add preprocessor definitions for this target and configuration.
BuildObjectListOrString ppDefs(this, true); BuildObjectListOrString ppDefs(this, true);
if (languages.count("Swift")) { this->AppendDefines(
// FIXME: Xcode warns that Swift does not support definition values. ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
// C/CXX sources mixed in Swift targets will not see CMAKE_INTDIR.
} else {
this->AppendDefines(
ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
}
if (const std::string* exportMacro = gtgt->GetExportMacro()) { if (const std::string* exportMacro = gtgt->GetExportMacro()) {
// Add the export symbol definition for shared library objects. // Add the export symbol definition for shared library objects.
this->AppendDefines(ppDefs, exportMacro->c_str()); this->AppendDefines(ppDefs, exportMacro->c_str());
@@ -2424,15 +2432,28 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS", buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
ppDefs.CreateList()); ppDefs.CreateList());
if (languages.count("Swift")) { 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) { if (this->XcodeVersion < 80) {
std::string defineString; std::string defineString;
std::set<std::string> defines(targetDefines.begin(), std::set<std::string> defines(targetSwiftDefines.begin(),
targetDefines.end()); targetSwiftDefines.end());
this->CurrentLocalGenerator->JoinDefines(defines, defineString, "Swift"); this->CurrentLocalGenerator->JoinDefines(defines, defineString, "Swift");
cflags["Swift"] += " " + defineString; cflags["Swift"] += " " + defineString;
} else { } else {
BuildObjectListOrString swiftDefs(this, true);
this->AppendDefines(swiftDefs, targetSwiftDefines);
buildSettings->AddAttribute("SWIFT_ACTIVE_COMPILATION_CONDITIONS", buildSettings->AddAttribute("SWIFT_ACTIVE_COMPILATION_CONDITIONS",
ppDefs.CreateList()); swiftDefs.CreateList());
} }
} }
+13
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); extern int ObjCMain(void);
int main(void) int main(void)
{ {
+1
View File
@@ -4,3 +4,4 @@ project(SwiftMix C Swift)
add_executable(SwiftMix CMain.c ObjCMain.m SwiftMain.swift ObjC-Swift.h) 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") 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_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)
+20
View File
@@ -3,6 +3,26 @@ import Foundation
@objc class SwiftMainClass : NSObject { @objc class SwiftMainClass : NSObject {
@objc class func SwiftMain() -> Int32 { @objc class func SwiftMain() -> Int32 {
dump("Hello World!"); 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; return 0;
} }
} }