Skip to content

Add target=name conditional for build settings #508

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Sources/SWBCore/Settings/BuiltinMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ public final class BuiltinMacros {
public static let configurationCondition = BuiltinMacros.declareConditionParameter("config")
public static let platformCondition = BuiltinMacros.declareConditionParameter("__platform_filter")
public static let sdkBuildVersionCondition = BuiltinMacros.declareConditionParameter("_sdk_build_version")
public static let targetNameCondition = BuiltinMacros.declareConditionParameter("target")

private static let allBuiltinConditionParameters = [archCondition, sdkCondition, variantCondition, configurationCondition, platformCondition, sdkBuildVersionCondition]
private static let allBuiltinConditionParameters = [archCondition, sdkCondition, variantCondition, configurationCondition, platformCondition, sdkBuildVersionCondition, targetNameCondition]

// MARK: Built-in Macro Definitions

Expand Down
26 changes: 17 additions & 9 deletions Sources/SWBCore/Settings/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1592,7 +1592,7 @@ private class SettingsBuilder {
if let sdk = boundProperties.sdk, settingsContext.purpose.bindToSDK {
for property in impartedBuildProperties ?? [] {
// Imparted build properties are always from packages, so force allow platform filter conditionals.
bindConditionParameters(property.buildSettings, sdk, forceAllowPlatformFilterCondition: true)
bindConditionParameters(bindTargetCondition(property.buildSettings), sdk, forceAllowPlatformFilterCondition: true)
}
}

Expand Down Expand Up @@ -2751,6 +2751,14 @@ private class SettingsBuilder {
}
}

func bindTargetCondition(_ table: MacroValueAssignmentTable) -> MacroValueAssignmentTable {
if let target {
return table.bindConditionParameter(BuiltinMacros.targetNameCondition, [target.name])
} else {
return table
}
}

/// Add the regular project settings.
func addProjectSettings(_ config: BuildConfiguration, _ sdk: SDK? = nil) {
guard let project else {
Expand Down Expand Up @@ -2781,11 +2789,11 @@ private class SettingsBuilder {
// Load and push a settings table from the file.
let info = buildRequestContext.getCachedMacroConfigFile(path, project: project, context: .baseConfiguration)
if let sdk = sdk, settingsContext.purpose.bindToSDK {
bindConditionParameters(info.table, sdk)
bindConditionParameters(bindTargetCondition(info.table), sdk)
}
else {
// No bound SDK, so push the project's build settings unmodified.
push(info.table, .exported)
push(bindTargetCondition(info.table), .exported)
}
self.diagnostics.append(contentsOf: info.diagnostics)
for path in info.dependencyPaths {
Expand All @@ -2810,11 +2818,11 @@ private class SettingsBuilder {

// Add the project's config settings.
if let sdk, settingsContext.purpose.bindToSDK {
bindConditionParameters(config.buildSettings, sdk)
bindConditionParameters(bindTargetCondition(config.buildSettings), sdk)
}
else {
// No bound SDK, so push the project's build settings unmodified.
push(config.buildSettings, .exported)
push(bindTargetCondition(config.buildSettings), .exported)
}

// Save the settings table as part of the construction components.
Expand Down Expand Up @@ -2996,11 +3004,11 @@ private class SettingsBuilder {
// Load and push a settings table from the file.
let info = buildRequestContext.getCachedMacroConfigFile(path, project: project, context: .baseConfiguration)
if let sdk = sdk, settingsContext.purpose.bindToSDK {
bindConditionParameters(info.table, sdk)
bindConditionParameters(bindTargetCondition(info.table), sdk)
}
else {
// No bound SDK, so push the target xcconfig's build settings unmodified.
push(info.table, .exported)
push(bindTargetCondition(info.table), .exported)
}
self.targetDiagnostics.append(contentsOf: info.diagnostics)
for path in info.dependencyPaths {
Expand All @@ -3019,11 +3027,11 @@ private class SettingsBuilder {
//
// FIXME: Cache this table, but we can only do that once we share the namespace.
if let sdk, settingsContext.purpose.bindToSDK {
bindConditionParameters(config.buildSettings, sdk)
bindConditionParameters(bindTargetCondition(config.buildSettings), sdk)
}
else {
// No bound SDK, so push the target's build settings unmodified.
push(config.buildSettings, .exported)
push(bindTargetCondition(config.buildSettings), .exported)
}

addSpecializationOverrides(sdk: sdk, usesAutomaticSDK: usesAutomaticSDK)
Expand Down
43 changes: 43 additions & 0 deletions Tests/SWBCoreTests/SettingsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4837,6 +4837,49 @@ import SWBMacro
#expect(settings.globalScope.evaluate(BuiltinMacros.SUPPORTED_PLATFORMS).contains("macosx"))
}

@Test
func targetConditionals() async throws {
let testWorkspace = try await TestWorkspace(
"Workspace",
projects: [TestPackageProject(
"aProject",
groupTree: TestGroup("SomeFiles", children: []),
buildConfigurations: [
TestBuildConfiguration(
"Debug",
buildSettings: [
"SDKROOT": "macosx",
// config=Debug is added here to ensure target conditionals still compose with existing conditionals.
"OTHER_CFLAGS[target=Target][config=Debug]": "-best",
"OTHER_LDFLAGS[target=Other]": "-other",
"SUPPORTED_PLATFORMS": "$(AVAILABLE_PLATFORMS)",
"SUPPORTS_MACCATALYST": "YES",
])
],
targets: [
TestStandardTarget("Target", type: .application),
TestStandardTarget("Other", type: .application),
])
]).load(getCore())

let context = try await contextForTestData(testWorkspace)
let buildRequestContext = BuildRequestContext(workspaceContext: context)
let testProject = context.workspace.projects[0]
let parameters = BuildParameters(action: .build, configuration: "Debug", activeRunDestination: .macOS)

do {
let settings = Settings(workspaceContext: context, buildRequestContext: buildRequestContext, parameters: parameters, project: testProject, target: testProject.targets[0])
#expect(settings.globalScope.evaluate(BuiltinMacros.OTHER_CFLAGS) == ["-best"])
#expect(settings.globalScope.evaluate(BuiltinMacros.OTHER_LDFLAGS) == [])
}

do {
let settings = Settings(workspaceContext: context, buildRequestContext: buildRequestContext, parameters: parameters, project: testProject, target: testProject.targets[1])
#expect(settings.globalScope.evaluate(BuiltinMacros.OTHER_CFLAGS) == [])
#expect(settings.globalScope.evaluate(BuiltinMacros.OTHER_LDFLAGS) == ["-other"])
}
}

@Test(.requireSDKs(.macOS, .iOS))
func platformConditionals() async throws {
let testWorkspace = try await TestWorkspace(
Expand Down