Skip to content
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
2 changes: 2 additions & 0 deletions Sources/SWBCore/Settings/BuiltinMacros.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -220,6 +220,7 @@ public final class BuiltinMacros{
public static let TARGET_BUILD_DIR = BuiltinMacros.declarePathMacro("TARGET_BUILD_DIR")
public static let TARGET_BUILD_SUBPATH = BuiltinMacros.declarePathMacro("TARGET_BUILD_SUBPATH")
public static let TARGET_NAME = BuiltinMacros.declareStringMacro("TARGET_NAME")
public static let TARGET_NAME_CASE_SENSITIVITY_DISCRIMINATOR = BuiltinMacros.declareStringMacro("TARGET_NAME_CASE_SENSITIVITY_DISCRIMINATOR")
public static let TARGET_TEMP_DIR = BuiltinMacros.declarePathMacro("TARGET_TEMP_DIR")
// FIXME: This macro should be deprecated.
public static let TARGETNAME = BuiltinMacros.declareStringMacro("TARGETNAME")
Expand DownExpand Up@@ -2376,6 +2377,7 @@ public final class BuiltinMacros{
TARGET_DEVICE_OS_VERSION,
TARGET_DEVICE_PLATFORM_NAME,
TARGET_NAME,
TARGET_NAME_CASE_SENSITIVITY_DISCRIMINATOR,
TARGET_TEMP_DIR,
TEMP_DIR,
TEMP_FILES_DIR,
Expand Down
14 changes: 13 additions & 1 deletion Sources/SWBCore/Settings/Settings.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -2953,14 +2953,26 @@ private class SettingsBuilder: ProjectMatchLookup{
table.push(BuiltinMacros.PROJECT_DIR, literal: project.sourceRoot.str)
table.push(BuiltinMacros.PROJECT_TEMP_DIR, Static{BuiltinMacros.namespace.parseString("$(OBJROOT)/$(PROJECT_NAME).build") })

do{
// A fair number of Swift packages have products/targets which only differ in case. In order to avoid collisions
// of build intermediates on case-insensitive file systems, add a discriminant if we detect this.
var seenTargetNames: Set<String> = []
for target in project.targets{
if !seenTargetNames.insert(target.name.lowercased()).inserted{
table.push(BuiltinMacros.TARGET_NAME_CASE_SENSITIVITY_DISCRIMINATOR, Static{BuiltinMacros.namespace.parseString("$(TARGET_NAME:__md5)") })
break
}
}
}

if usePerConfigurationBuildLocations{
table.push(BuiltinMacros.CONFIGURATION_BUILD_DIR, Static{BuiltinMacros.namespace.parseString("$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)") })
table.push(BuiltinMacros.CONFIGURATION_TEMP_DIR, Static{BuiltinMacros.namespace.parseString("$(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)") })
} else{
table.push(BuiltinMacros.CONFIGURATION_BUILD_DIR, Static{BuiltinMacros.namespace.parseString("$(BUILD_DIR)") })
table.push(BuiltinMacros.CONFIGURATION_TEMP_DIR, Static{BuiltinMacros.namespace.parseString("$(PROJECT_TEMP_DIR)") })
}
table.push(BuiltinMacros.TARGET_TEMP_DIR, Static{BuiltinMacros.namespace.parseString("$(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME).build") })
table.push(BuiltinMacros.TARGET_TEMP_DIR, Static{BuiltinMacros.namespace.parseString("$(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME)$(TARGET_NAME_CASE_SENSITIVITY_DISCRIMINATOR).build") })
table.push(BuiltinMacros.TARGET_BUILD_DIR, Static{BuiltinMacros.namespace.parseString("$(CONFIGURATION_BUILD_DIR)$(TARGET_BUILD_SUBPATH)") })
table.push(BuiltinMacros.BUILT_PRODUCTS_DIR, Static{BuiltinMacros.namespace.parseString("$(CONFIGURATION_BUILD_DIR)") })
table.push(BuiltinMacros.DEVELOPMENT_LANGUAGE, literal: project.developmentRegion ?? "en")
Expand Down
2 changes: 1 addition & 1 deletion Sources/SWBCore/Specs/CoreBuildSystem.xcspec
Original file line numberDiff line numberDiff line change
Expand Up@@ -2987,7 +2987,7 @@ For more information on mergeable libraries, see [Configuring your project to us
{
Name = "TARGET_TEMP_DIR"
Type = Path;
DefaultValue = "$(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME).build"
DefaultValue = "$(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME)$(TARGET_NAME_CASE_SENSITIVITY_DISCRIMINATOR).build"
Description = "Identifies the directory containing the target’s intermediate build files. Run Script build phases should place intermediate files at the location indicated by `DERIVED_FILE_DIR`, not the directory identified by this build setting."
},
{
Expand Down
62 changes: 62 additions & 0 deletions Tests/SWBBuildSystemTests/PackageBuildOperationTests.swift
Original file line numberDiff line numberDiff line change
Expand Up@@ -470,6 +470,68 @@ fileprivate struct PackageBuildOperationTests: CoreBasedTests{
}
}

// Regression test which ensures we can build successfully when a project has two targets whose
// names only differ in case. Previously this would fail because the intermediate TARGET_TEMP_DIRs would
// collide.
@Test(.requireSDKs(.host))
func packageCaseInsensitiveCollisions() async throws{
try await withTemporaryDirectory{tmpDir in
let testWorkspace = try await TestWorkspace(
"Test",
sourceRoot: tmpDir.join("Test"),
projects: [
TestProject(
"aProject",
groupTree: TestGroup(
"Sources",
children: [
TestFile("file_1.swift"),
TestFile("file_2.swift"),
]),
buildConfigurations: [TestBuildConfiguration(
"Debug",
buildSettings: [
"PRODUCT_NAME": "$(TARGET_NAME)",
"SWIFT_VERSION": swiftVersion,
"DSTROOT": tmpDir.join("dstroot").str,
])],
targets: [
TestStandardTarget(
"Library",
type: .staticLibrary,
buildPhases: [
TestSourcesBuildPhase(["file_1.swift"]),
], dependencies: ["library"]),
TestStandardTarget(
"library",
type: .staticLibrary,
buildPhases: [
TestSourcesBuildPhase(["file_2.swift"]),
]),
])])

let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false)

try await tester.fs.writeFileContents(testWorkspace.sourceRoot.join("aProject/file_1.swift")){stream in
stream <<<
"""
public let x = 42
"""
}

try await tester.fs.writeFileContents(testWorkspace.sourceRoot.join("aProject/file_2.swift")){stream in
stream <<<
"""
public let y = 10
"""
}

try await tester.checkBuild(runDestination: .host){results in
results.checkNoDiagnostics()
}
}
}

@Test(.requireSDKs(.macOS))
func packageModuleAliasing() async throws{
try await withTemporaryDirectory{tmpDirPath async throws -> Void in
Expand Down
Loading