From 5b73823775fb99eb220595c954e44783108fcc00 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sun, 16 Nov 2025 11:32:08 -0800 Subject: [PATCH] Correct linker file list escaping depending on the LINKER_DRIVER used --- Sources/SWBCore/Settings/BuiltinMacros.swift | 3 +++ .../SpecImplementations/LinkerSpec.swift | 5 ++-- .../PropertyDomainSpec.swift | 2 ++ .../Tools/LinkerTools.swift | 7 +++++- .../Specs/UnixLibtool.xcspec | 3 ++- Sources/SWBUniversalPlatform/Specs/Ld.xcspec | 24 ++++++++++++++++++- .../SWBUniversalPlatform/Specs/Libtool.xcspec | 11 +++++++++ .../Specs/WindowsLibtool.xcspec | 2 +- .../BuildOperationTests.swift | 12 +++++----- 9 files changed, 57 insertions(+), 12 deletions(-) diff --git a/Sources/SWBCore/Settings/BuiltinMacros.swift b/Sources/SWBCore/Settings/BuiltinMacros.swift index b32c08df..5570cc92 100644 --- a/Sources/SWBCore/Settings/BuiltinMacros.swift +++ b/Sources/SWBCore/Settings/BuiltinMacros.swift @@ -1198,6 +1198,8 @@ public final class BuiltinMacros { public static let _WRAPPER_RESOURCES_DIR = BuiltinMacros.declareStringMacro("_WRAPPER_RESOURCES_DIR") public static let __INPUT_FILE_LIST_PATH__ = BuiltinMacros.declarePathMacro("__INPUT_FILE_LIST_PATH__") public static let LINKER_FILE_LIST_FORMAT = BuiltinMacros.declareEnumMacro("LINKER_FILE_LIST_FORMAT") as EnumMacroDeclaration + public static let LIBTOOL_FILE_LIST_FORMAT = BuiltinMacros.declareEnumMacro("LIBTOOL_FILE_LIST_FORMAT") as EnumMacroDeclaration + public static let LINKER_RESPONSE_FILE_FORMAT = BuiltinMacros.declareEnumMacro("LINKER_RESPONSE_FILE_FORMAT") as EnumMacroDeclaration public static let SWIFT_RESPONSE_FILE_PATH = BuiltinMacros.declarePathMacro("SWIFT_RESPONSE_FILE_PATH") public static let __ARCHS__ = BuiltinMacros.declareStringListMacro("__ARCHS__") @@ -2459,6 +2461,7 @@ public final class BuiltinMacros { _WRAPPER_RESOURCES_DIR, __INPUT_FILE_LIST_PATH__, LINKER_FILE_LIST_FORMAT, + LIBTOOL_FILE_LIST_FORMAT, LINKER_RESPONSE_FILE_FORMAT, __ARCHS__, __SWIFT_MODULE_ONLY_ARCHS__, diff --git a/Sources/SWBCore/SpecImplementations/LinkerSpec.swift b/Sources/SWBCore/SpecImplementations/LinkerSpec.swift index 5d728619..6149d4c4 100644 --- a/Sources/SWBCore/SpecImplementations/LinkerSpec.swift +++ b/Sources/SWBCore/SpecImplementations/LinkerSpec.swift @@ -138,8 +138,9 @@ open class LinkerSpec : CommandLineToolSpec, @unchecked Sendable { return ruleInfo } - public func inputFileListContents(_ cbc: CommandBuildContext) -> ByteString { - return ByteString(encodingAsUTF8: ResponseFiles.responseFileContents(args: cbc.inputs.map { $0.absolutePath.strWithPosixSlashes }, format: cbc.scope.evaluate(BuiltinMacros.LINKER_FILE_LIST_FORMAT))) + public func inputFileListContents(_ cbc: CommandBuildContext, lookup: ((MacroDeclaration) -> MacroExpression?)? = nil) -> ByteString { + let format = cbc.scope.evaluate(BuiltinMacros.LINKER_FILE_LIST_FORMAT, lookup: lookup) + return ByteString(encodingAsUTF8: ResponseFiles.responseFileContents(args: cbc.inputs.map { $0.absolutePath.strWithPosixSlashes }, format: format)) } open override func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) async { diff --git a/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift b/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift index af2f0063..e237aecc 100644 --- a/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift +++ b/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift @@ -118,6 +118,8 @@ private final class EnumBuildOptionType : BuildOptionType { return try namespace.declareEnumMacro(name) as EnumMacroDeclaration case "LINKER_FILE_LIST_FORMAT": return try namespace.declareEnumMacro(name) as EnumMacroDeclaration + case "LIBTOOL_FILE_LIST_FORMAT": + return try namespace.declareEnumMacro(name) as EnumMacroDeclaration case "LINKER_RESPONSE_FILE_FORMAT": return try namespace.declareEnumMacro(name) as EnumMacroDeclaration case "DOCC_MINIMUM_ACCESS_LEVEL": diff --git a/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift b/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift index 8c8e6bc3..414ec486 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift @@ -461,7 +461,7 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec let fileListPath = cbc.scope.evaluate(BuiltinMacros.__INPUT_FILE_LIST_PATH__, lookup: linkerDriverLookup) if !fileListPath.isEmpty { let fileListPath = fileListPath - cbc.producer.writeFileSpec.constructFileTasks(CommandBuildContext(producer: cbc.producer, scope: cbc.scope, inputs: [], output: fileListPath), delegate, contents: inputFileListContents(cbc), permissions: nil, preparesForIndexing: false, additionalTaskOrderingOptions: [.immediate, .ignorePhaseOrdering]) + cbc.producer.writeFileSpec.constructFileTasks(CommandBuildContext(producer: cbc.producer, scope: cbc.scope, inputs: [], output: fileListPath), delegate, contents: inputFileListContents(cbc, lookup: linkerDriverLookup), permissions: nil, preparesForIndexing: false, additionalTaskOrderingOptions: [.immediate, .ignorePhaseOrdering]) inputPaths.append(fileListPath) } @@ -1655,6 +1655,11 @@ public final class LibtoolLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @u return resolveExecutablePath(producer, lookupPath) } + public override func inputFileListContents(_ cbc: CommandBuildContext, lookup: ((MacroDeclaration) -> MacroExpression?)? = nil) -> ByteString { + let format = cbc.scope.evaluate(BuiltinMacros.LIBTOOL_FILE_LIST_FORMAT, lookup: lookup) + return ByteString(encodingAsUTF8: ResponseFiles.responseFileContents(args: cbc.inputs.map { $0.absolutePath.strWithPosixSlashes }, format: format)) + } + static func discoveredCommandLineToolSpecInfo(_ producer: any CommandProducer, _ delegate: any CoreClientTargetDiagnosticProducingDelegate, toolPath: Path) async throws -> DiscoveredLibtoolLinkerToolSpecInfo { if toolPath.basenameWithoutSuffix == "llvm-lib" || toolPath.basenameWithoutSuffix == "ar" || toolPath.basenameWithoutSuffix.hasSuffix("-ar") { return DiscoveredLibtoolLinkerToolSpecInfo(toolPath: toolPath, toolVersion: nil) diff --git a/Sources/SWBGenericUnixPlatform/Specs/UnixLibtool.xcspec b/Sources/SWBGenericUnixPlatform/Specs/UnixLibtool.xcspec index 7d08dcb2..9d2f6a94 100644 --- a/Sources/SWBGenericUnixPlatform/Specs/UnixLibtool.xcspec +++ b/Sources/SWBGenericUnixPlatform/Specs/UnixLibtool.xcspec @@ -69,10 +69,11 @@ DefaultValue = YES; }, { - Name = "LINKER_FILE_LIST_FORMAT"; + Name = "LIBTOOL_FILE_LIST_FORMAT"; Type = Enumeration; Values = ( unescapedNewlineSeparated, + unixShellQuotedSpaceSeparated, unixShellQuotedNewlineSeparated, windowsShellQuotedNewlineSeparated, ); diff --git a/Sources/SWBUniversalPlatform/Specs/Ld.xcspec b/Sources/SWBUniversalPlatform/Specs/Ld.xcspec index 49937a83..2a31927e 100644 --- a/Sources/SWBUniversalPlatform/Specs/Ld.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Ld.xcspec @@ -831,8 +831,30 @@ unixShellQuotedNewlineSeparated, windowsShellQuotedNewlineSeparated, ); + DefaultValue = "$(LINKER_FILE_LIST_FORMAT_$(LINKER_DRIVER))"; + }, + { + Name = "LINKER_FILE_LIST_FORMAT_clang"; + Type = Enumeration; + Values = ( + unescapedNewlineSeparated, + unixShellQuotedSpaceSeparated, + unixShellQuotedNewlineSeparated, + windowsShellQuotedNewlineSeparated, + ); DefaultValue = unescapedNewlineSeparated; }, + { + Name = "LINKER_FILE_LIST_FORMAT_swiftc"; + Type = Enumeration; + Values = ( + unescapedNewlineSeparated, + unixShellQuotedSpaceSeparated, + unixShellQuotedNewlineSeparated, + windowsShellQuotedNewlineSeparated, + ); + DefaultValue = unixShellQuotedSpaceSeparated; + }, { Name = "LINKER_RESPONSE_FILE_FORMAT"; Type = Enumeration; @@ -843,7 +865,7 @@ windowsShellQuotedNewlineSeparated, ); DefaultValue = unixShellQuotedSpaceSeparated; - } + }, ); } ) diff --git a/Sources/SWBUniversalPlatform/Specs/Libtool.xcspec b/Sources/SWBUniversalPlatform/Specs/Libtool.xcspec index d146ce6c..18c5ac48 100644 --- a/Sources/SWBUniversalPlatform/Specs/Libtool.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Libtool.xcspec @@ -111,6 +111,17 @@ Type = Boolean; DefaultValue = YES; }, + { + Name = "LIBTOOL_FILE_LIST_FORMAT"; + Type = Enumeration; + Values = ( + unescapedNewlineSeparated, + unixShellQuotedSpaceSeparated, + unixShellQuotedNewlineSeparated, + windowsShellQuotedNewlineSeparated, + ); + DefaultValue = unescapedNewlineSeparated; + }, ); } ) diff --git a/Sources/SWBWindowsPlatform/Specs/WindowsLibtool.xcspec b/Sources/SWBWindowsPlatform/Specs/WindowsLibtool.xcspec index c5521e0d..5647fd0d 100644 --- a/Sources/SWBWindowsPlatform/Specs/WindowsLibtool.xcspec +++ b/Sources/SWBWindowsPlatform/Specs/WindowsLibtool.xcspec @@ -64,7 +64,7 @@ IsInputDependency = Yes; }, { - Name = "LINKER_FILE_LIST_FORMAT"; + Name = "LIBTOOL_FILE_LIST_FORMAT"; Type = Enumeration; Values = ( unescapedNewlineSeparated, diff --git a/Tests/SWBBuildSystemTests/BuildOperationTests.swift b/Tests/SWBBuildSystemTests/BuildOperationTests.swift index 19c2bbc6..25f8c854 100644 --- a/Tests/SWBBuildSystemTests/BuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/BuildOperationTests.swift @@ -40,8 +40,8 @@ fileprivate struct BuildOperationTests: CoreBasedTests { "SomeFiles", children: [ TestFile("main.swift"), - TestFile("dynamic.swift"), - TestFile("static.swift"), + TestFile("dynamic library.swift"), + TestFile("static library.swift"), ]), buildConfigurations: [ TestBuildConfiguration("Debug", buildSettings: [ @@ -93,7 +93,7 @@ fileprivate struct BuildOperationTests: CoreBasedTests { ]) ], buildPhases: [ - TestSourcesBuildPhase(["dynamic.swift"]), + TestSourcesBuildPhase(["dynamic library.swift"]), ] ), TestStandardTarget( @@ -107,7 +107,7 @@ fileprivate struct BuildOperationTests: CoreBasedTests { ]) ], buildPhases: [ - TestSourcesBuildPhase(["static.swift"]), + TestSourcesBuildPhase(["static library.swift"]), ] ), ]) @@ -125,11 +125,11 @@ fileprivate struct BuildOperationTests: CoreBasedTests { stream <<< "print(\"Hello world\")\n" } - try await tester.fs.writeFileContents(projectDir.join("dynamic.swift")) { stream in + try await tester.fs.writeFileContents(projectDir.join("dynamic library.swift")) { stream in stream <<< "public func dynamicLib() { }" } - try await tester.fs.writeFileContents(projectDir.join("static.swift")) { stream in + try await tester.fs.writeFileContents(projectDir.join("static library.swift")) { stream in stream <<< "public func staticLib() { }" }