From 2842c27680863fd7cccf931c29edc9ca16578033 Mon Sep 17 00:00:00 2001 From: usama Date: Wed, 23 Apr 2025 15:16:20 -0700 Subject: [PATCH 01/30] Pass -ftyped-cxx-new-delete as a linker arg. The motivation here is to make back deployment easier by conditionally linking in a shim layer in the clang driver. rdar://149709799 --- Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec index fcdfeda1..e2405751 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec @@ -2927,6 +2927,11 @@ YES = ("-ftyped-cxx-new-delete"); NO = ("-fno-typed-cxx-new-delete"); }; + AdditionalLinkerArgs = { + compiler-default = (); + YES = ("-ftyped-cxx-new-delete"); + NO = (); + }; }, // Index-while-building options, not visible in build settings. { From 8515f09263ad4f3c3c8cb0dc22ec345dc4a31625 Mon Sep 17 00:00:00 2001 From: baujla Date: Thu, 24 Apr 2025 10:03:42 -0700 Subject: [PATCH 02/30] App Sandbox build setting ends up in iOS signed app (#432) --- Sources/SWBCore/SigningSupport.swift | 9 +++ .../Tools/ProductPackaging.swift | 5 +- .../EntitlementsBuildOperationTests.swift | 67 ++++--------------- 3 files changed, 23 insertions(+), 58 deletions(-) diff --git a/Sources/SWBCore/SigningSupport.swift b/Sources/SWBCore/SigningSupport.swift index 9f874ab2..7d398c55 100644 --- a/Sources/SWBCore/SigningSupport.swift +++ b/Sources/SWBCore/SigningSupport.swift @@ -30,6 +30,8 @@ public protocol PlatformSigningContext func shouldPassEntitlementsFileContentToCodeSign() -> Bool func requiresEntitlements(_ scope: MacroEvaluationScope, hasProfile: Bool, productFileType: FileTypeSpec) -> Bool + + func supportsAppSandboxAndHardenedRuntime() -> Bool } extension PlatformSigningContext @@ -58,12 +60,19 @@ extension PlatformSigningContext { return hasProfile || scope.evaluate(BuiltinMacros.ENTITLEMENTS_REQUIRED) } + + @_spi(Testing) public func supportsAppSandboxAndHardenedRuntime() -> Bool { + return false + } } /// Provides behavior for code signing for the macOS platform. @_spi(Testing) public struct MacSigningContext: PlatformSigningContext { + @_spi(Testing) public func supportsAppSandboxAndHardenedRuntime() -> Bool { + return true + } } diff --git a/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift b/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift index f8f7eb58..0c095dbf 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift @@ -114,15 +114,12 @@ public final class ProductPackagingToolSpec : GenericCommandLineToolSpec, SpecId entitlementsDictionary["com.apple.security.get-task-allow"] = nil } - let isAppSandboxEnabled = cbc.scope.evaluate(BuiltinMacros.ENABLE_APP_SANDBOX) - let isHardenedRuntimeEnabled = cbc.scope.evaluate(BuiltinMacros.ENABLE_HARDENED_RUNTIME) - // rdar://142845111 (Turn on `AppSandboxConflictingValuesEmitsWarning` by default) if SWBFeatureFlag.enableAppSandboxConflictingValuesEmitsWarning.value { EntitlementConflictDiagnosticEmitter.checkForConflicts(cbc, delegate, entitlementsDictionary: entitlementsDictionary, entitlementsPath: codeSignEntitlementsInput?.absolutePath) } - if isAppSandboxEnabled || isHardenedRuntimeEnabled { + if cbc.producer.platform?.signingContext.supportsAppSandboxAndHardenedRuntime() == true { // Inject entitlements that are settable via build settings. // This is only supported when App Sandbox or Hardened Runtime is enabled. for (buildSetting, entitlementPrefix) in Self.sandboxFileAccessSettingsAndEntitlements { diff --git a/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift b/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift index 2f77cc1a..b3e808f0 100644 --- a/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift @@ -238,24 +238,24 @@ fileprivate struct EntitlementsBuildOperationTests: CoreBasedTests { } } - /// Test that the `ProcessProductEntitlementsTaskAction` does not embed build settings based entitlements that are dependent on App Sandbox being enabled, when App Sandbox is disabled. - @Test(.requireSDKs(.macOS)) - func macOSAppSandboxEnabledEntitlementsWithSandboxDisabled() async throws { + /// Test that the `ProcessProductEntitlementsTaskAction` does not embed build settings that only apply to macOS. + @Test(.requireSDKs(.iOS)) + func iOSAppSandboxAndHardnedRuntimeBuildSettingEnabled() async throws { try await withTemporaryDirectory { tmpDirPath async throws -> Void in let testWorkspace = entitlementsTestWorkspace( sourceRoot: tmpDirPath, buildSettings: [ "PRODUCT_NAME": "$(TARGET_NAME)", "INFOPLIST_FILE": "Info.plist", - "CODE_SIGN_IDENTITY": "-", - "RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES": "NO", - "RUNTIME_EXCEPTION_ALLOW_JIT": "NO", - "RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY": "NO", - "AUTOMATION_APPLE_EVENTS": "NO", - "RUNTIME_EXCEPTION_DEBUGGING_TOOL": "NO", - "RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION": "NO", - "RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION": "NO", - "ENABLE_APP_SANDBOX": "NO", + "AD_HOC_CODE_SIGNING_ALLOWED": "YES", + "RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES": "YES", + "RUNTIME_EXCEPTION_ALLOW_JIT": "YES", + "RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY": "YES", + "AUTOMATION_APPLE_EVENTS": "YES", + "RUNTIME_EXCEPTION_DEBUGGING_TOOL": "YES", + "RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION": "YES", + "RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION": "YES", + "ENABLE_APP_SANDBOX": "YES", "ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER": "readwrite", "ENABLE_FILE_ACCESS_PICTURE_FOLDER": "readonly", "ENABLE_FILE_ACCESS_MUSIC_FOLDER": "readwrite", @@ -271,7 +271,7 @@ fileprivate struct EntitlementsBuildOperationTests: CoreBasedTests { "ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY": "YES", "ENABLE_RESOURCE_ACCESS_USB": "YES", "ENABLE_RESOURCE_ACCESS_PRINTING": "YES", - "SDKROOT": "macosx" + "SDKROOT": "iphoneos" ] ) @@ -481,47 +481,6 @@ fileprivate struct EntitlementsBuildOperationTests: CoreBasedTests { } } - /// Test that the `ProcessProductEntitlementsTaskAction` does not embed build settings based entitlements that are dependent on Hardened Runtime being enabled, when Hardened Runtime is disabled. - @Test(.requireSDKs(.macOS)) - func macOSHardenedRuntimeEnabledEntitlementsWithHardenedRuntimeDisabled() async throws { - try await withTemporaryDirectory { tmpDirPath async throws -> Void in - let testWorkspace = entitlementsTestWorkspace( - sourceRoot: tmpDirPath, - buildSettings: [ - "PRODUCT_NAME": "$(TARGET_NAME)", - "INFOPLIST_FILE": "Info.plist", - "CODE_SIGN_IDENTITY": "-", - "ENABLE_HARDENED_RUNTIME": "NO", - "RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES": "YES", - "RUNTIME_EXCEPTION_ALLOW_JIT": "YES", - "RUNTIME_EXCEPTION_ALLOW_UNSIGNED_EXECUTABLE_MEMORY": "YES", - "AUTOMATION_APPLE_EVENTS": "YES", - "RUNTIME_EXCEPTION_DEBUGGING_TOOL": "YES", - "RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION": "YES", - "RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION": "YES", - "ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER": "readwrite", - "ENABLE_FILE_ACCESS_PICTURE_FOLDER": "readonly", - "ENABLE_FILE_ACCESS_MUSIC_FOLDER": "readwrite", - "ENABLE_FILE_ACCESS_MOVIES_FOLDER": "readonly", - "ENABLE_INCOMING_NETWORK_CONNECTIONS": "YES", - "ENABLE_OUTGOING_NETWORK_CONNECTIONS": "YES", - "ENABLE_RESOURCE_ACCESS_AUDIO_INPUT": "YES", - "ENABLE_RESOURCE_ACCESS_BLUETOOTH": "YES", - "ENABLE_RESOURCE_ACCESS_CALENDARS": "YES", - "ENABLE_RESOURCE_ACCESS_CAMERA": "YES", - "ENABLE_RESOURCE_ACCESS_CONTACTS": "YES", - "ENABLE_RESOURCE_ACCESS_LOCATION": "YES", - "ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY": "YES", - "SDKROOT": "macosx" - ] - ) - - try await buildTestBinaryAndValidateEntitlements(testWorkspace: testWorkspace, expectedEntitlements: [ - "com.apple.application-identifier": "$(AppIdentifierPrefix)$(CFBundleIdentifier)", - ]) - } - } - @Test(.requireSDKs(.iOS)) func simulatorEntitlementsSections() async throws { try await withTemporaryDirectory { tmpDirPath in From d4fe8535a289e7433746a9eac1d59f2a37d6d90d Mon Sep 17 00:00:00 2001 From: Mirza Garibovic Date: Thu, 24 Apr 2025 12:56:52 -0700 Subject: [PATCH 03/30] Revert "Annotate "$targetA is missing a dependency on $targetB" diagnostics with target location (rdar://149397709)" This reverts commit f97263c5681eea0c5a6591ff8ed06de7c44abb22. This seems to trigger conflicting target info in client events. Reverting while I investigate. --- Sources/SWBBuildSystem/BuildOperation.swift | 19 +++++++++---------- .../ClangExplicitModulesTests.swift | 4 ++-- .../SwiftDriverTests.swift | 8 ++++---- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/Sources/SWBBuildSystem/BuildOperation.swift b/Sources/SWBBuildSystem/BuildOperation.swift index 934b78d2..de2bdeba 100644 --- a/Sources/SWBBuildSystem/BuildOperation.swift +++ b/Sources/SWBBuildSystem/BuildOperation.swift @@ -881,15 +881,8 @@ package final class BuildOperation: BuildSystemOperation { } package func taskDiscoveredRequiredTargetDependency(target: ConfiguredTarget, antecedent: ConfiguredTarget, reason: RequiredTargetDependencyReason, warningLevel: BooleanWarningLevel) { - let diagnosticBehavior: SWBUtil.Diagnostic.Behavior - switch warningLevel { - case .yesError: diagnosticBehavior = .error - case .yes: diagnosticBehavior = .warning - case .no: return - } - let targetDiagnosticsEngine = buildOutputDelegate.diagnosticsEngine(for: target) - if !transitiveDependencyExists(target: target, antecedent: antecedent) { + // Ensure we only diagnose missing dependencies when platform and SDK variant match. We perform this check as late as possible since computing settings can be expensive. let targetSettings = requestContext.getCachedSettings(target.parameters, target: target.target) let antecedentSettings = requestContext.getCachedSettings(antecedent.parameters, target: antecedent.target) @@ -907,8 +900,14 @@ package final class BuildOperation: BuildSystemOperation { } else { message = DiagnosticData("'\(target.target.name)' is missing a dependency on '\(antecedent.target.name)' because \(reason)") } - - targetDiagnosticsEngine.emit(Diagnostic(behavior: diagnosticBehavior, location: .unknown, data: message)) + switch warningLevel { + case .yes: + buildOutputDelegate.emit(Diagnostic(behavior: .warning, location: .unknown, data: message)) + case .yesError: + buildOutputDelegate.emit(Diagnostic(behavior: .error, location: .unknown, data: message)) + default: + break + } } } } diff --git a/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift b/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift index 95d636b7..70d31af9 100644 --- a/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift +++ b/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift @@ -2969,9 +2969,9 @@ fileprivate struct ClangExplicitModulesTests: CoreBasedTests { try await tester.checkBuild(runDestination: destination, buildRequest: buildRequest, persistent: true) { results in switch warningLevel { case .yes: - results.checkWarning("'Framework2' is missing a dependency on 'Framework1' because dependency scan of 'file_2.c' discovered a dependency on 'Framework1' (in target 'Framework2' from project 'aProject')") + results.checkWarning("'Framework2' is missing a dependency on 'Framework1' because dependency scan of 'file_2.c' discovered a dependency on 'Framework1'") case .yesError: - results.checkError("'Framework2' is missing a dependency on 'Framework1' because dependency scan of 'file_2.c' discovered a dependency on 'Framework1' (in target 'Framework2' from project 'aProject')") + results.checkError("'Framework2' is missing a dependency on 'Framework1' because dependency scan of 'file_2.c' discovered a dependency on 'Framework1'") default: break } diff --git a/Tests/SWBBuildSystemTests/SwiftDriverTests.swift b/Tests/SWBBuildSystemTests/SwiftDriverTests.swift index ed5d3f05..6be300a1 100644 --- a/Tests/SWBBuildSystemTests/SwiftDriverTests.swift +++ b/Tests/SWBBuildSystemTests/SwiftDriverTests.swift @@ -4597,11 +4597,11 @@ fileprivate struct SwiftDriverTests: CoreBasedTests { try await tester.checkBuild(runDestination: .macOS, buildRequest: buildRequest, persistent: true) { results in switch warningLevel { case .yes: - results.checkWarning("'Framework3' is missing a dependency on 'Framework1' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework1' (in target 'Framework3' from project 'aProject')") - results.checkWarning("'Framework3' is missing a dependency on 'Framework2' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework2' (in target 'Framework3' from project 'aProject')") + results.checkWarning("'Framework3' is missing a dependency on 'Framework1' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework1'") + results.checkWarning("'Framework3' is missing a dependency on 'Framework2' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework2'") case .yesError: - results.checkError("'Framework3' is missing a dependency on 'Framework1' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework1' (in target 'Framework3' from project 'aProject')") - results.checkError("'Framework3' is missing a dependency on 'Framework2' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework2' (in target 'Framework3' from project 'aProject')") + results.checkError("'Framework3' is missing a dependency on 'Framework1' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework1'") + results.checkError("'Framework3' is missing a dependency on 'Framework2' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework2'") default: break } From e2f55064ffee9c3be3c42a460bcc751d6320b5e7 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 21 Apr 2025 15:07:08 -0700 Subject: [PATCH 04/30] Simplify a few API calls in FSProxy These now go through Foundation rather than Win32 APIs directly. This simplifies Unicode and long path handling in particular. For realpath I left the POSIX implementation in place for non-Windows for now since it's not clear that has equivalent behavior. touch/setFileTimestamp now differ in that they no longer set atime, but virtually nothing uses atime. --- Sources/SWBUtil/FSProxy.swift | 86 +++-------------------------------- 1 file changed, 7 insertions(+), 79 deletions(-) diff --git a/Sources/SWBUtil/FSProxy.swift b/Sources/SWBUtil/FSProxy.swift index ae89474c..974bc667 100644 --- a/Sources/SWBUtil/FSProxy.swift +++ b/Sources/SWBUtil/FSProxy.swift @@ -615,69 +615,15 @@ class LocalFS: FSProxy, @unchecked Sendable { } func touch(_ path: Path) throws { - #if os(Windows) - let handle: HANDLE = path.withPlatformString { - CreateFileW($0, DWORD(GENERIC_WRITE), DWORD(FILE_SHARE_READ), nil, - DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil) - } - if handle == INVALID_HANDLE_VALUE { - throw Win32Error(GetLastError()) - } - try handle.closeAfter { - var ft = FILETIME() - var st = SYSTEMTIME() - GetSystemTime(&st) - SystemTimeToFileTime(&st, &ft) - if !SetFileTime(handle, nil, &ft, &ft) { - Win32Error(GetLastError()) - } - } - #else - try eintrLoop { - guard utimensat(AT_FDCWD, path.str, nil, 0) == 0 else { - throw POSIXError(errno, context: "utimensat", "AT_FDCWD", path.str) - } - } - #endif + try _setFileTimestamp(path, timestamp: Date()) } func setFileTimestamp(_ path: Path, timestamp: Int) throws { - #if os(Windows) - let handle: HANDLE = path.withPlatformString { - CreateFileW($0, DWORD(GENERIC_WRITE), DWORD(FILE_SHARE_READ), nil, - DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil) - } - if handle == INVALID_HANDLE_VALUE { - throw Win32Error(GetLastError()) - } - try handle.closeAfter { - // Number of 100ns intervals between 1601 and 1970 epochs - let delta = 116444736000000000 - - let ll = UInt64((timestamp * 10000000) + delta) - - var timeInt = ULARGE_INTEGER() - timeInt.QuadPart = ll + try _setFileTimestamp(path, timestamp: Date(timeIntervalSince1970: Double(timestamp))) + } - var ft = FILETIME() - ft.dwLowDateTime = timeInt.LowPart - ft.dwHighDateTime = timeInt.HighPart - if !SetFileTime(handle, nil, &ft, &ft) { - throw Win32Error(GetLastError()) - } - } - #else - try eintrLoop { - #if os(Linux) || os(Android) - let UTIME_OMIT = 1073741822 - #endif - let atime = timespec(tv_sec: 0, tv_nsec: Int(UTIME_OMIT)) - let mtime = timespec(tv_sec: time_t(timestamp), tv_nsec: 0) - guard utimensat(AT_FDCWD, path.str, [atime, mtime], 0) == 0 else { - throw POSIXError(errno, context: "utimensat", "AT_FDCWD", path.str, String(timestamp)) - } - } - #endif + private func _setFileTimestamp(_ path: Path, timestamp: Date) throws { + try fileManager.setAttributes([.modificationDate: timestamp], ofItemAtPath: path.str) } func getFileInfo(_ path: Path) throws -> FileInfo { @@ -875,28 +821,10 @@ class LocalFS: FSProxy, @unchecked Sendable { func realpath(_ path: Path) throws -> Path { #if os(Windows) - let handle: HANDLE = path.withPlatformString { - CreateFileW($0, GENERIC_READ, DWORD(FILE_SHARE_READ), nil, - DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil) - } - if handle == INVALID_HANDLE_VALUE { + guard exists(path) else { throw POSIXError(ENOENT, context: "realpath", path.str) } - return try handle.closeAfter { - let dwLength: DWORD = GetFinalPathNameByHandleW(handle, nil, 0, DWORD(FILE_NAME_NORMALIZED)) - return try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) { - guard GetFinalPathNameByHandleW(handle, $0.baseAddress!, DWORD($0.count), - DWORD(FILE_NAME_NORMALIZED)) == dwLength - 1 else { - throw Win32Error(GetLastError()) - } - let path = String(platformString: $0.baseAddress!) - // Drop UNC prefix if present - if path.hasPrefix(#"\\?\"#) { - return Path(path.dropFirst(4)) - } - return Path(path) - } - } + return Path(path.str.standardizingPath) #else guard let result = SWBLibc.realpath(path.str, nil) else { throw POSIXError(errno, context: "realpath", path.str) } defer { free(result) } From 382cc20bd73302e6c7fd672a033d3bbcb6391e78 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Thu, 24 Apr 2025 13:21:44 -0700 Subject: [PATCH 05/30] Remove confusing SWBDispatchQueue.async overload This overload was only meant to be used in one place, and its behavior was a little confusing, since it does not actually run the work on the queue. Over time, this overload got used in a few other places due to overload resolution picking it up, and turning formerly synchronous work asynchronous. Remove it to restore the intended behavior. --- Sources/SWBServiceCore/ServiceHostConnection.swift | 6 +----- Sources/SWBUtil/SWBDispatch.swift | 13 ++----------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/Sources/SWBServiceCore/ServiceHostConnection.swift b/Sources/SWBServiceCore/ServiceHostConnection.swift index 34001138..a3af56e5 100644 --- a/Sources/SWBServiceCore/ServiceHostConnection.swift +++ b/Sources/SWBServiceCore/ServiceHostConnection.swift @@ -46,9 +46,6 @@ final class ServiceHostConnection: @unchecked Sendable { /// Whether the queue is suspended. private let isSuspended = LockedValue(true) - /// The queue used to read incoming messages. - private let receiveQueue: SWBQueue - /// The queue used to send outgoing messages. private let sendQueue: SWBQueue @@ -69,7 +66,6 @@ final class ServiceHostConnection: @unchecked Sendable { self.inputFD = inputFD self.outputFD = outputFD // The queues for the service host connection are given .userInitiated QOS (not .utility, which most queues in Swift Build have) because we don't know whether we're servicing a user interaction request. Most requests should be shunted to a background thread unless there's a reason to send a quick response at high priority. - self.receiveQueue = SWBQueue(label: "SWBBuildService.ServiceHostConnection.receiveQueue", qos: .userInitiated, autoreleaseFrequency: .workItem) self.sendQueue = SWBQueue(label: "SWBBuildService.ServiceHostConnection.sendQueue", qos: .userInitiated, autoreleaseFrequency: .workItem) } @@ -136,7 +132,7 @@ final class ServiceHostConnection: @unchecked Sendable { // Otherwise, launch the receive pump. isSuspended.withLock { $0 = false } - receiveQueue.async { + Task(priority: .userInitiated) { // Read data forever. var data: [UInt8] = [] let tmpBufferSize = 4096 diff --git a/Sources/SWBUtil/SWBDispatch.swift b/Sources/SWBUtil/SWBDispatch.swift index ecbd2506..089bd2e9 100644 --- a/Sources/SWBUtil/SWBDispatch.swift +++ b/Sources/SWBUtil/SWBDispatch.swift @@ -282,17 +282,8 @@ public final class SWBQueue: Sendable { } } - public func async(group: SWBDispatchGroup? = nil, execute body: @escaping @Sendable () -> Void) { - return queue.async(group: group?.group, execute: body) - } - - // Temporary hack until rdar://98401196 (Use Swift Concurrency for low-level IO in ServiceHostConnection) lands. This should be safe because we only ever call `async` once in the place we use this. - public func async(qos: SWBQoS = .unspecified, execute work: @Sendable @escaping () async -> Void) { - queue.async(group: nil, qos: qos.dispatchQoS, flags: []) { - Task { - await work() - } - } + public func async(group: SWBDispatchGroup? = nil, qos: SWBQoS = .unspecified, execute body: @escaping @Sendable () -> Void) { + return queue.async(group: group?.group, qos: qos.dispatchQoS, execute: body) } public static func global() -> Self { From c704557b4280f8ec7229f5ffc7ec37ec8cac4080 Mon Sep 17 00:00:00 2001 From: thetruestblue Date: Thu, 24 Apr 2025 15:36:53 -0700 Subject: [PATCH 06/30] Add new libcxx flag for disabling container overflow checks libcxx changed the name of the macro used to include sanitizer container annotations. We should add the new flag name to maintain current behavior. Sanitizer container overflow checks are prone to false positives, so we default to disabling these on xcode projects. rdar://149350723 --- Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec | 1 + Tests/SWBTaskConstructionTests/TaskConstructionTests.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec index fcdfeda1..aeee0c18 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec @@ -2736,6 +2736,7 @@ YES = (); NO = ( "-D_LIBCPP_HAS_NO_ASAN", + "-D_LIBCPP_HAS_ASAN=0", ); }; Condition = "$(CLANG_ADDRESS_SANITIZER)"; diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index 4511d270..570aed47 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -4135,7 +4135,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { // There should be one CompileC task, which includes the ASan option, and which puts its output in a -asan directory. results.checkTask(.matchTarget(target), .matchRuleType("CompileC")) { task in task.checkRuleInfo([.equal("CompileC"), .equal("\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/SourceFile.o"), .suffix("SourceFile.m"), .any, .any, .any, .any]) - task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-fsanitize=address", "-D_LIBCPP_HAS_NO_ASAN", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/SourceFile.o"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-fsanitize=address", "-D_LIBCPP_HAS_NO_ASAN", "-D_LIBCPP_HAS_ASAN=0", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/SourceFile.o"]) } // There should be one CompileSwiftSources task, which includes the ASan option, and which puts its output in a -asan directory. From 9ad44f1a0bd5a504381c1ccda38b41b5fc42ece0 Mon Sep 17 00:00:00 2001 From: baujla Date: Thu, 24 Apr 2025 17:55:32 -0700 Subject: [PATCH 07/30] Test targets emit incorrect 'The ENABLE_APP_SANDBOX build setting is set to NO, but is set to YES in your entitlements file.' warning (#433) --- Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec b/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec index 0067050f..38336aec 100644 --- a/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec @@ -299,6 +299,8 @@ INSTALL_PATH = "$(INSTALL_PATH_XCTRUNNER_$(USES_XCTRUNNER:default=NO))"; INSTALL_PATH_XCTRUNNER_YES = "$(DEFAULT_TEST_RUNNER_APP_INSTALL_PATH)"; INSTALL_PATH_XCTRUNNER_NO = "$(DEFAULT_TEST_BUNDLE_INSTALL_PATH)"; + ENABLE_APP_SANDBOX = "$(USES_XCTRUNNER)"; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = "$(USES_XCTRUNNER)"; ENTITLEMENTS_REQUIRED = NO; From 622ebc73599d643d98ca119fb431e3b36ee5c5f0 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 24 Apr 2025 11:03:31 -0700 Subject: [PATCH 08/30] [Explicit Module Builds] Enable incremental dependency scanning\nWith an opt-out build setting SWIFT_DISABLE_INCREMENTAL_SCAN in case early adoption shows any troubles --- Sources/SWBCore/Settings/BuiltinMacros.swift | 2 + .../Tools/SwiftCompiler.swift | 8 +++ .../PreviewsBuildOperationTests.swift | 1 + .../SwiftDriverTests.swift | 1 + .../SwiftTaskConstructionTests.swift | 60 +++++++++++++++++++ 5 files changed, 72 insertions(+) diff --git a/Sources/SWBCore/Settings/BuiltinMacros.swift b/Sources/SWBCore/Settings/BuiltinMacros.swift index 00979bd3..13bec632 100644 --- a/Sources/SWBCore/Settings/BuiltinMacros.swift +++ b/Sources/SWBCore/Settings/BuiltinMacros.swift @@ -1003,6 +1003,7 @@ public final class BuiltinMacros { public static let SWIFT_EMIT_MODULE_INTERFACE = BuiltinMacros.declareBooleanMacro("SWIFT_EMIT_MODULE_INTERFACE") public static let SWIFT_ENABLE_BATCH_MODE = BuiltinMacros.declareBooleanMacro("SWIFT_ENABLE_BATCH_MODE") public static let SWIFT_ENABLE_INCREMENTAL_COMPILATION = BuiltinMacros.declareBooleanMacro("SWIFT_ENABLE_INCREMENTAL_COMPILATION") + public static let SWIFT_DISABLE_INCREMENTAL_SCAN = BuiltinMacros.declareBooleanMacro("SWIFT_DISABLE_INCREMENTAL_SCAN") public static let SWIFT_ENABLE_LAYOUT_STRING_VALUE_WITNESSES = BuiltinMacros.declareBooleanMacro("SWIFT_ENABLE_LAYOUT_STRING_VALUE_WITNESSES") public static let SWIFT_ENABLE_LIBRARY_EVOLUTION = BuiltinMacros.declareBooleanMacro("SWIFT_ENABLE_LIBRARY_EVOLUTION") public static let SWIFT_ENABLE_BARE_SLASH_REGEX = BuiltinMacros.declareBooleanMacro("SWIFT_ENABLE_BARE_SLASH_REGEX") @@ -2164,6 +2165,7 @@ public final class BuiltinMacros { SWIFT_EMIT_MODULE_INTERFACE, SWIFT_ENABLE_BATCH_MODE, SWIFT_ENABLE_INCREMENTAL_COMPILATION, + SWIFT_DISABLE_INCREMENTAL_SCAN, SWIFT_ENABLE_LAYOUT_STRING_VALUE_WITNESSES, SWIFT_ENABLE_LIBRARY_EVOLUTION, SWIFT_USE_INTEGRATED_DRIVER, diff --git a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift index cec5bb91..5a448c46 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift @@ -119,6 +119,7 @@ public struct SwiftSourceFileIndexingInfo: SourceFileIndexingInfo { "-emit-dependencies", "-serialize-diagnostics", "-incremental", + "-incremental-dependency-scan", "-parseable-output", "-use-frontend-parseable-output", "-whole-module-optimization", @@ -153,6 +154,7 @@ public struct SwiftSourceFileIndexingInfo: SourceFileIndexingInfo { // can be removed after we use the new driver instead (rdar://75851402). private static let newDriverFlags: Set = [ "-driver-print-graphviz", + "-incremental-dependency-scan", "-explicit-module-build", "-experimental-explicit-module-build", "-nonlib-dependency-scanner", @@ -1743,6 +1745,10 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi if cbc.scope.evaluate(BuiltinMacros.SWIFT_ENABLE_INCREMENTAL_COMPILATION) { args.append("-incremental") + if LibSwiftDriver.supportsDriverFlag(spelled: "-incremental-dependency-scan"), + !cbc.scope.evaluate(BuiltinMacros.SWIFT_DISABLE_INCREMENTAL_SCAN) { + args.append("-incremental-dependency-scan") + } } } @@ -3279,6 +3285,8 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi for arg in [ // Should strip this because it saves some work and avoids writing a useless incremental build record "-incremental", + // Same as above + "-incremental-dependency-scan", // Stripped because we want to end up in single file mode "-enable-batch-mode", diff --git a/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift b/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift index 7df199bf..0911fb0c 100644 --- a/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift @@ -831,6 +831,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { "ENABLE_PREVIEWS": "YES", "CLANG_ENABLE_MODULES": "YES", "SDK_STAT_CACHE_ENABLE": "NO", + "SWIFT_DISABLE_INCREMENTAL_SCAN": "YES", "SWIFT_ENABLE_EXPLICIT_MODULES": explicitModules ? "YES" : "NO", diff --git a/Tests/SWBBuildSystemTests/SwiftDriverTests.swift b/Tests/SWBBuildSystemTests/SwiftDriverTests.swift index ed5d3f05..bb360d56 100644 --- a/Tests/SWBBuildSystemTests/SwiftDriverTests.swift +++ b/Tests/SWBBuildSystemTests/SwiftDriverTests.swift @@ -3616,6 +3616,7 @@ fileprivate struct SwiftDriverTests: CoreBasedTests { "ENABLE_PREVIEWS": "YES", "SWIFT_USE_INTEGRATED_DRIVER": useIntegratedDriver ? "YES" : "NO", "SWIFT_ENABLE_EXPLICIT_MODULES": useIntegratedDriver ? "YES" : "NO", + "SWIFT_DISABLE_INCREMENTAL_SCAN": "YES", "_EXPERIMENTAL_SWIFT_EXPLICIT_MODULES": useIntegratedDriver ? "YES" : "NO", // Eager linking is not supported when using the driver binary. "EAGER_LINKING": "NO", diff --git a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift index 997e5fec..9f5473c8 100644 --- a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift @@ -645,6 +645,7 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { "SWIFT_PACKAGE_NAME": "FooPkg", "SWIFT_EMIT_MODULE_INTERFACE": "YES", "SWIFT_ENABLE_EXPLICIT_MODULES": "YES", + "SWIFT_DISABLE_INCREMENTAL_SCAN": "YES", ]), ], buildPhases: [ @@ -830,6 +831,7 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { "DEFINES_MODULE": "YES", "SWIFT_VERSION": swiftVersion, "SWIFT_EMIT_MODULE_INTERFACE": "YES", + "SWIFT_DISABLE_INCREMENTAL_SCAN": "YES", ]), ], buildPhases: [ @@ -1530,6 +1532,64 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { } } + @Test(.requireSDKs(.macOS), .enabled(if: LibSwiftDriver.supportsDriverFlag(spelled: "-incremental-dependency-scan"))) + func optOutIncrementalScanning() async throws { + let testProject = try await TestProject( + "aProject", + groupTree: TestGroup( + "SomeFiles", path: "Sources", + children: [ + TestFile("main.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "PRODUCT_NAME": "$(TARGET_NAME)", + "SWIFT_ENABLE_EXPLICIT_MODULES": "YES", + ]), + ], + targets: [ + TestStandardTarget( + "Exec", type: .commandLineTool, + buildConfigurations: [ + TestBuildConfiguration("Debug", + buildSettings: [ + "SWIFT_EXEC": swiftCompilerPath.str, + "SWIFT_VERSION": swiftVersion, + ]), + ], + buildPhases: [ + TestSourcesBuildPhase([ + "main.swift", + ]), + ]) + ]) + let tester = try await TaskConstructionTester(getCore(), testProject) + + await tester.checkBuild(runDestination: .macOS) { results in + results.checkTarget("Exec") { target in + results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation Requirements")) { task in + task.checkCommandLineContains(["-explicit-module-build"]) + task.checkCommandLineContains(["-incremental"]) + task.checkCommandLineContains(["-incremental-dependency-scan"]) + } + } + results.checkNoDiagnostics() + } + + await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["SWIFT_DISABLE_INCREMENTAL_SCAN": "YES"]), runDestination: .macOS) { results in + results.checkTarget("Exec") { target in + results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation Requirements")) { task in + task.checkCommandLineContains(["-explicit-module-build"]) + task.checkCommandLineContains(["-incremental"]) + task.checkCommandLineDoesNotContain("-incremental-dependency-scan") + } + } + results.checkNoDiagnostics() + } + } + @Test(.requireSDKs(.macOS)) func swift4DisablesExplicitModules() async throws { let testProject = try await TestProject( From 0d54cb46838ea21334a7d7979215e2a7a192caf3 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 25 Apr 2025 15:09:33 -0700 Subject: [PATCH 09/30] [SE-0466] Add SWIFT_DEFAULT_ACTOR_ISOLATION build setting This setting controls default actor isolation for unannotated code. Resolves: rdar://145751834 --- .../SWBUniversalPlatform/Specs/Swift.xcspec | 17 +++- .../SwiftTaskConstructionTests.swift | 88 +++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec index 4f04b3e2..b8434e0c 100644 --- a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec @@ -569,7 +569,22 @@ Category = "Upcoming Features"; Description = "Enables strict concurrency checking to produce warnings for possible data races. This is always 'complete' when in the Swift 6 language mode and produces errors instead of warnings."; }, - + { + Name = "SWIFT_DEFAULT_ACTOR_ISOLATION"; + Type = Enumeration; + Values = ( + nonisolated, + MainActor + ); + DefaultValue = "nonisolated"; + CommandLineArgs = { + nonisolated = (); + MainActor = ( "-default-isolation=MainActor" ); + }; + DisplayName = "Default Actor Isolation"; + Category = "Language"; + Description = "Controls default actor isolation for unannotated code. When set to 'MainActor', `@MainActor` isolation will be inferred by default to mitigate false-positive data-race safety errors in sequential code."; + }, { Name = "SWIFT_STRICT_MEMORY_SAFETY"; Type = Boolean; diff --git a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift index 997e5fec..bf208bf6 100644 --- a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift @@ -3468,6 +3468,94 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { } } + @Test(.requireSDKs(.macOS)) + func defaultIsolationFlag() async throws { + try await withTemporaryDirectory { tmpDir in + let srcRoot = tmpDir.join("srcroot") + let testProject = try await TestProject( + "ProjectName", + sourceRoot: srcRoot, + groupTree: TestGroup( + "SomeFiles", path: "Sources", + children: [ + TestFile("File1.swift"), + TestFile("File2.swift"), + TestFile("File3.swift"), + ]), + targets: [ + TestStandardTarget( + "Default", + type: .framework, + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "GENERATE_INFOPLIST_FILE": "YES", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SWIFT_EXEC": swiftCompilerPath.str, + "SWIFT_VERSION": "5.0", + ]), + ], + buildPhases: [ + TestSourcesBuildPhase([ + TestBuildFile("File1.swift"), + ]), + ], dependencies: ["Nonisolated", "MainActor"]), + TestStandardTarget( + "Nonisolated", + type: .framework, + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "GENERATE_INFOPLIST_FILE": "YES", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SWIFT_EXEC": swiftCompilerPath.str, + "SWIFT_VERSION": "5.0", + "SWIFT_DEFAULT_ACTOR_ISOLATION": "nonisolated", + ]), + ], + buildPhases: [ + TestSourcesBuildPhase([ + TestBuildFile("File2.swift"), + ]), + ]), + TestStandardTarget( + "MainActor", + type: .framework, + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "GENERATE_INFOPLIST_FILE": "YES", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SWIFT_EXEC": swiftCompilerPath.str, + "SWIFT_VERSION": "5.0", + "SWIFT_DEFAULT_ACTOR_ISOLATION": "MainActor", + ]), + ], + buildPhases: [ + TestSourcesBuildPhase([ + TestBuildFile("File3.swift"), + ]), + ]), + ]) + + let tester = try await TaskConstructionTester(getCore(), testProject) + await tester.checkBuild(BuildParameters(action: .install, configuration: "Debug"), runDestination: .macOS) { results in + results.checkTarget("Default") { target in + results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in + task.checkCommandLineNoMatch([.prefix("-default-isolation")]) + } + } + results.checkTarget("Nonisolated") { target in + results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in + task.checkCommandLineNoMatch([.prefix("-default-isolation")]) + } + } + results.checkTarget("MainActor") { target in + results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in + task.checkCommandLineContains(["-default-isolation=MainActor"]) + } + } + } + } + } + // Test frontend flag -library-level inference from the INSTALL_PATH. @Test(.requireSDKs(.macOS)) func libraryLevel() async throws { From cb6dfa20d8846eaeebcefe6ff539c244764b06b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20B=C3=BCgling?= Date: Fri, 25 Apr 2025 16:59:22 -0700 Subject: [PATCH 10/30] `compatibleConfiguredTarget` should consider toolchains (#439) --- Sources/SWBCore/DependencyResolution.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Sources/SWBCore/DependencyResolution.swift b/Sources/SWBCore/DependencyResolution.swift index fd716988..c7cad902 100644 --- a/Sources/SWBCore/DependencyResolution.swift +++ b/Sources/SWBCore/DependencyResolution.swift @@ -694,10 +694,11 @@ extension SpecializationParameters { let dependencySettings = buildRequestContext.getCachedSettings(ct.parameters, target: ct.target) let dependencyPlatform = dependencySettings.platform let dependencySdkVariant = dependencySettings.sdkVariant?.name + let dependencyToolchains = dependencySettings.toolchains guard Ref(dependencyPlatform) == platform && dependencySdkVariant == sdkVariant else { return false } // For dependencies with 'auto' SDKROOT, they get their SDK 'imposed', including if it is internal vs public SDK, not just what platform it is. // For such dependencies also confirm that the existing configured dependency matches 'internal vs public' for the SDK. - if dependencyHasAutoSDKRoot, let dependencySDK = dependencySettings.sdk, let dependentSDK = sdk, dependencySDK !== dependentSDK { + if dependencyHasAutoSDKRoot, let dependencySDK = dependencySettings.sdk, let dependentSDK = sdk, dependencySDK !== dependentSDK || settings.toolchains != dependencyToolchains { return false } return true @@ -742,8 +743,9 @@ extension SpecializationParameters { continue } + let behavior: Diagnostic.Behavior = buildRequest.enableIndexBuildArena ? .warning : .error let data = DiagnosticData("multiple configured targets of '\(target.name)' are being created for \(currentSettings.platform?.displayName ?? "")") - delegate.emit(Diagnostic(behavior: .error, location: .unknown, data: data)) + delegate.emit(Diagnostic(behavior: behavior, location: .unknown, data: data)) hasMultipleTargets = true } } From 49938222f3782ee5bdfab577127b072d11d643dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20B=C3=BCgling?= Date: Fri, 25 Apr 2025 16:59:37 -0700 Subject: [PATCH 11/30] Fix typo in `isCompatible` (#440) --- Sources/SWBCore/DependencyResolution.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SWBCore/DependencyResolution.swift b/Sources/SWBCore/DependencyResolution.swift index c7cad902..6726b02e 100644 --- a/Sources/SWBCore/DependencyResolution.swift +++ b/Sources/SWBCore/DependencyResolution.swift @@ -190,7 +190,7 @@ struct SpecializationParameters: Hashable, CustomStringConvertible { let toolchain = effectiveToolchainOverride(originalParameters: configuredTarget.parameters, workspaceContext: workspaceContext) return (platform == nil || platform === settings.platform) && (sdkVariant == nil || sdkVariant?.name == settings.sdkVariant?.name) && - (toolchain == nil || toolchain == settings.globalScope.evaluate(BuiltinMacros.EFFECTIVE_TOOLCHAINS_DIRS)) && + (toolchain == nil || toolchain == settings.globalScope.evaluate(BuiltinMacros.TOOLCHAINS)) && (canonicalNameSuffix == nil || canonicalNameSuffix?.nilIfEmpty == settings.sdk?.canonicalNameSuffix) } From 52578ea6ff1b779196dffefa68fdb1da5efa8bff Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sun, 27 Apr 2025 22:12:54 -0700 Subject: [PATCH 12/30] Fix shellcheck issue in perf tests script (#448) --- Utilities/swift-ci-perf-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/swift-ci-perf-tests.sh b/Utilities/swift-ci-perf-tests.sh index 255c7e09..dbef917e 100755 --- a/Utilities/swift-ci-perf-tests.sh +++ b/Utilities/swift-ci-perf-tests.sh @@ -3,6 +3,6 @@ set -euo pipefail __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd ${__dir}/.. +cd "${__dir}"/.. swift test -c release --filter Perf From bd5f6733ca2e8803ad99914cb5f7c1b59aeba881 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sun, 27 Apr 2025 22:13:11 -0700 Subject: [PATCH 13/30] Remove a trailing comma to restore 6.0 compatibility (#447) --- Tests/SWBBuildSystemTests/BuildOperationTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SWBBuildSystemTests/BuildOperationTests.swift b/Tests/SWBBuildSystemTests/BuildOperationTests.swift index 31466ea4..e7eec6c1 100644 --- a/Tests/SWBBuildSystemTests/BuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/BuildOperationTests.swift @@ -453,7 +453,7 @@ fileprivate struct BuildOperationTests: CoreBasedTests { buildPhases: [ TestSourcesBuildPhase(["library.swift"]), ], - ), + ) ]) let core = try await getCore() let tester = try await BuildOperationTester(core, testProject, simulated: false) From b82da06d726f29c4e64e41ad77343b372bfa5323 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sun, 27 Apr 2025 22:15:22 -0700 Subject: [PATCH 14/30] Improve cmake-smoke-test command plugin - Make --sysroot-path optional - Fail early if --disable-sandbox is not passed - Use SwiftPM's checkouts of dependencies instead of assuming the update-checkout layout --- .../cmake-smoke-test/cmake-smoke-test.swift | 55 ++++++++++++++----- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/Plugins/cmake-smoke-test/cmake-smoke-test.swift b/Plugins/cmake-smoke-test/cmake-smoke-test.swift index 4cd00782..f1cdba50 100644 --- a/Plugins/cmake-smoke-test/cmake-smoke-test.swift +++ b/Plugins/cmake-smoke-test/cmake-smoke-test.swift @@ -17,17 +17,22 @@ import Foundation struct CMakeSmokeTest: CommandPlugin { func performCommand(context: PluginContext, arguments: [String]) async throws { var args = ArgumentExtractor(arguments) - let hostOS = try OS.host() + guard args.extractFlag(named: "disable-sandbox") > 0 else { + throw Errors.missingRequiredOption("--disable-sandbox") + } + guard let cmakePath = args.extractOption(named: "cmake-path").last else { throw Errors.missingRequiredOption("--cmake-path") } print("using cmake at \(cmakePath)") let cmakeURL = URL(filePath: cmakePath) guard let ninjaPath = args.extractOption(named: "ninja-path").last else { throw Errors.missingRequiredOption("--ninja-path") } print("using ninja at \(ninjaPath)") let ninjaURL = URL(filePath: ninjaPath) - guard let sysrootPath = args.extractOption(named: "sysroot-path").last else { throw Errors.missingRequiredOption("--sysroot-path") } - print("using sysroot at \(sysrootPath)") + let sysrootPath = args.extractOption(named: "sysroot-path").last + if let sysrootPath { + print("using sysroot at \(sysrootPath)") + } let moduleCachePath = context.pluginWorkDirectoryURL.appending(component: "module-cache").path() @@ -35,30 +40,33 @@ struct CMakeSmokeTest: CommandPlugin { let swiftBuildBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-build") print("swift-build: \(swiftBuildURL.path())") - let swiftToolsSupportCoreURL = try findSiblingRepository("swift-tools-support-core", swiftBuildURL: swiftBuildURL) + let swiftToolsSupportCoreURL = try findDependency("swift-tools-support-core", pluginContext: context) let swiftToolsSupportCoreBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-tools-support-core") - let swiftSystemURL = try findSiblingRepository("swift-system", swiftBuildURL: swiftBuildURL) + let swiftSystemURL = try findDependency("swift-system", pluginContext: context) let swiftSystemBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-system") - let llbuildURL = try findSiblingRepository("llbuild", swiftBuildURL: swiftBuildURL) + let llbuildURL = try findDependency("swift-llbuild", pluginContext: context) let llbuildBuildURL = context.pluginWorkDirectoryURL.appending(component: "llbuild") - let swiftArgumentParserURL = try findSiblingRepository("swift-argument-parser", swiftBuildURL: swiftBuildURL) + let swiftArgumentParserURL = try findDependency("swift-argument-parser", pluginContext: context) let swiftArgumentParserBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-argument-parser") - let swiftDriverURL = try findSiblingRepository("swift-driver", swiftBuildURL: swiftBuildURL) + let swiftDriverURL = try findDependency("swift-driver", pluginContext: context) let swiftDriverBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-driver") for url in [swiftToolsSupportCoreBuildURL, swiftSystemBuildURL, llbuildBuildURL, swiftArgumentParserBuildURL, swiftDriverBuildURL, swiftBuildBuildURL] { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) } - let sharedSwiftFlags = [ - "-sdk", sysrootPath, + var sharedSwiftFlags = [ "-module-cache-path", moduleCachePath ] + if let sysrootPath { + sharedSwiftFlags += ["-sdk", sysrootPath] + } + let cMakeProjectArgs = [ "-DArgumentParser_DIR=\(swiftArgumentParserBuildURL.appending(components: "cmake", "modules").path())", "-DLLBuild_DIR=\(llbuildBuildURL.appending(components: "cmake", "modules").path())", @@ -107,11 +115,28 @@ struct CMakeSmokeTest: CommandPlugin { print("Built swift-build") } - func findSiblingRepository(_ name: String, swiftBuildURL: URL) throws -> URL { - let url = swiftBuildURL.deletingLastPathComponent().appending(component: name) - print("\(name): \(url.path())") - guard FileManager.default.fileExists(atPath: url.path()) else { throw Errors.missingRepository(url.path()) } - return url + func findDependency(_ name: String, pluginContext: PluginContext) throws -> URL { + var stack: [Package] = pluginContext.package.dependencies.map { $0.package } + var visited = Set(stack.map { $0.id }) + var transitiveDependencies = pluginContext.package.dependencies.map { $0.package } + while let current = stack.popLast() { + for dependency in current.dependencies { + guard visited.insert(dependency.package.id).inserted else { + continue + } + transitiveDependencies.append(dependency.package) + stack.append(dependency.package) + } + } + guard let dependency = transitiveDependencies.first(where: { $0.id == name }) else { + throw Errors.missingRepository(name) + } + let dependencyURL = dependency.directoryURL + print("\(name): \(dependencyURL.path())") + guard FileManager.default.fileExists(atPath: dependencyURL.path()) else { + throw Errors.missingRepository(dependencyURL.path()) + } + return dependencyURL } } From 0e2c7816df00ee1ae9066aac9bb9b1d3a77635e1 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Sun, 27 Apr 2025 09:41:23 -0700 Subject: [PATCH 15/30] [CAS] Adjust the caching report text to not mention 'miss' The text now reads "2 hits / 4 cacheable tasks (50%)". The intention of the change is to avoid "miss" which can have negative associations. --- Sources/SWBBuildSystem/BuildOperation.swift | 3 ++- Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift | 4 ++-- Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Sources/SWBBuildSystem/BuildOperation.swift b/Sources/SWBBuildSystem/BuildOperation.swift index de2bdeba..5542c89e 100644 --- a/Sources/SWBBuildSystem/BuildOperation.swift +++ b/Sources/SWBBuildSystem/BuildOperation.swift @@ -681,7 +681,8 @@ package final class BuildOperation: BuildSystemOperation { adaptor.withActivity(ruleInfo: "CompilationCacheMetrics", executionDescription: "Report compilation cache metrics", signature: signature, target: nil, parentActivity: nil) { activity in func getSummary(hits: Int, misses: Int) -> String { let hitPercent = Int((Double(hits) / Double(hits + misses) * 100).rounded()) - return "\(hits) hit\(hits == 1 ? "" : "s") (\(hitPercent)%), \(misses) miss\(misses == 1 ? "" : "es")" + let total = hits + misses + return "\(hits) hit\(hits == 1 ? "" : "s") / \(total) cacheable task\(total == 1 ? "" : "s") (\(hitPercent)%)" } delegate.emit(diagnostic: Diagnostic(behavior: .note, location: .unknown, data: DiagnosticData(getSummary(hits: cacheHits, misses: cacheMisses))), for: activity, signature: signature) return .succeeded diff --git a/Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift b/Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift index 20192674..e8b436e0 100644 --- a/Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift +++ b/Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift @@ -234,7 +234,7 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests { // Make sure scanning happens before compilation... results.check(event: .taskHadEvent(scanTask, event: .completed), precedes: .taskHadEvent(compileTask, event: .started)) - results.checkNote("0 hits (0%), 1 miss") + results.checkNote("0 hits / 1 cacheable task (0%)") results.checkCompileCacheMiss(compileTask) results.checkNoDiagnostics() } @@ -262,7 +262,7 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests { // Make sure scanning happens before compilation. results.check(event: .taskHadEvent(scanTask, event: .completed), precedes: .taskHadEvent(compileTask, event: .started)) - results.checkNote("1 hit (100%), 0 misses") + results.checkNote("1 hit / 1 cacheable task (100%)") results.checkCompileCacheHit(compileTask) } results.checkNoDiagnostics() diff --git a/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift b/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift index 4a82aacd..c01277a9 100644 --- a/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift +++ b/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift @@ -110,7 +110,7 @@ fileprivate struct SwiftCompilationCachingTests: CoreBasedTests { numCompile += tasks.count } - results.checkNote("0 hits (0%), 4 misses") + results.checkNote("0 hits / 4 cacheable tasks (0%)") results.checkNoTask() } @@ -126,7 +126,7 @@ fileprivate struct SwiftCompilationCachingTests: CoreBasedTests { results.checkKeyQueryCacheHit(task) } - results.checkNote("4 hits (100%), 0 misses") + results.checkNote("4 hits / 4 cacheable tasks (100%)") } #expect(try readMetrics("two").contains("\"swiftCacheHits\":\(numCompile),\"swiftCacheMisses\":0")) } From d7751e2d6a7fe3d73075d6076b0981626093f098 Mon Sep 17 00:00:00 2001 From: baujla Date: Mon, 28 Apr 2025 10:10:40 -0700 Subject: [PATCH 16/30] =?UTF-8?q?Added=20needed=20dependency=20to=20iOSApp?= =?UTF-8?q?SandboxAndHardnedRuntimeBuildSetting=E2=80=A6=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SWBBuildSystemTests/EntitlementsBuildOperationTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift b/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift index b3e808f0..683395e7 100644 --- a/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift @@ -239,8 +239,8 @@ fileprivate struct EntitlementsBuildOperationTests: CoreBasedTests { } /// Test that the `ProcessProductEntitlementsTaskAction` does not embed build settings that only apply to macOS. - @Test(.requireSDKs(.iOS)) - func iOSAppSandboxAndHardnedRuntimeBuildSettingEnabled() async throws { + @Test(.requireSDKs(.macOS, .iOS)) + func iOSAppSandboxAndHardenedRuntimeBuildSettingEnabled() async throws { try await withTemporaryDirectory { tmpDirPath async throws -> Void in let testWorkspace = entitlementsTestWorkspace( sourceRoot: tmpDirPath, From 097165755d1ca42ae40ce1da13524c1ca7f9385b Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 28 Apr 2025 09:22:17 -0700 Subject: [PATCH 17/30] Force git to check out text files with Unix newlines Our xcspecs in particular expect to exist with Unix newlines, and some tests may fail depending on git's autocrlf settings on Windows. Just standardize the newlines to keep everything consistent. --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6313b56c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf From 1beb6eaae30282c4c0469aa97fc9f95a72000f18 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Mon, 28 Apr 2025 11:46:25 -0700 Subject: [PATCH 18/30] Skip large file copy test in GitHub actions (#451) --- Sources/SWBTestSupport/SkippedTestSupport.swift | 8 ++++++-- Tests/SWBTaskExecutionTests/PBXCpTests.swift | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Sources/SWBTestSupport/SkippedTestSupport.swift b/Sources/SWBTestSupport/SkippedTestSupport.swift index d6ee26e5..7ba31ee9 100644 --- a/Sources/SWBTestSupport/SkippedTestSupport.swift +++ b/Sources/SWBTestSupport/SkippedTestSupport.swift @@ -172,6 +172,10 @@ extension Trait where Self == Testing.ConditionTrait { #endif } + package static func skipInGitHubActions(_ comment: Comment? = nil) -> Self { + return .skipIfEnvironmentVariableSet(key: "GITHUB_ACTIONS") + } + package static func requireClangFeatures(_ requiredFeatures: DiscoveredClangToolSpecInfo.FeatureFlag...) -> Self { enabled("Clang compiler does not support features: \(requiredFeatures)") { let features = try await ConditionTraitContext.shared.clangFeatures @@ -235,8 +239,8 @@ extension Trait where Self == Testing.ConditionTrait { } } - package static func skipIfEnvironmentVariableSet(key: EnvironmentKey) -> Self { - disabled("environment sets '\(key)'") { + package static func skipIfEnvironmentVariableSet(key: EnvironmentKey, _ comment: Comment? = nil) -> Self { + disabled(comment ?? "environment sets '\(key)'") { getEnvironmentVariable(key) != nil } } diff --git a/Tests/SWBTaskExecutionTests/PBXCpTests.swift b/Tests/SWBTaskExecutionTests/PBXCpTests.swift index c4b0237f..109bba4d 100644 --- a/Tests/SWBTaskExecutionTests/PBXCpTests.swift +++ b/Tests/SWBTaskExecutionTests/PBXCpTests.swift @@ -442,7 +442,8 @@ fileprivate struct PBXCpTests: CoreBasedTests { fileprivate let buffer0 = [UInt8](repeating: 0xAA, count: 1024 * 513) fileprivate let buffer1 = [UInt8](repeating: 0x55, count: 1024 * 513) - @Test(.skipHostOS(.windows, "LocalFS needs to use stat64 on windows....")) + @Test(.skipHostOS(.windows, "LocalFS needs to use stat64 on windows...."), + .skipInGitHubActions("GitHub action runners do not have enough storage space for this test")) func largerFile() async throws { try await withTemporaryDirectory { tmp in // Test copying a large file. From 3038e01d6e93db50d13d066a832467507a6bd159 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Mon, 28 Apr 2025 12:39:43 -0700 Subject: [PATCH 19/30] Add missing host SDK requirement to test rdar://149411160 --- Tests/SWBBuildSystemTests/BuildOperationTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SWBBuildSystemTests/BuildOperationTests.swift b/Tests/SWBBuildSystemTests/BuildOperationTests.swift index e7eec6c1..70778e4a 100644 --- a/Tests/SWBBuildSystemTests/BuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/BuildOperationTests.swift @@ -397,7 +397,7 @@ fileprivate struct BuildOperationTests: CoreBasedTests { } } - @Test(.skipHostOS(.macOS), .skipHostOS(.windows, "cannot find testing library"), .requireThreadSafeWorkingDirectory) + @Test(.requireSDKs(.host), .skipHostOS(.macOS), .skipHostOS(.windows, "cannot find testing library"), .requireThreadSafeWorkingDirectory) func unitTestWithGeneratedEntryPoint() async throws { try await withTemporaryDirectory { (tmpDir: Path) in let testProject = try await TestProject( From 0b4a664136ef8e1a239beb8047e08ab8bcecadb4 Mon Sep 17 00:00:00 2001 From: Ben Barham Date: Wed, 23 Apr 2025 15:49:26 -0700 Subject: [PATCH 20/30] Check for the index workspace description rather than index arena There's various paths that should be specific to the index workspace description rather than if the index arena is enabled. Specifically the recent change to replace parameters for host tools (https://github.com/swiftlang/swift-build/pull/345) broke the *package* description as it uses the passed in run destination rather than configuring for all platforms. This replacement would then create two configured targets for macOS for the same target (one for the given run destination and one for the macOS platform that the index uses). This also changes the *target* description to only build for the run destination, which makes sense given its entire purpose is to be a replacement for the workspace description if it hasn't built yet (ie. it should be as fast as possible). Resolves rdar://149896775. --- Sources/SWBCore/BuildRequest.swift | 9 + Sources/SWBCore/DependencyResolution.swift | 16 +- .../BuildDescriptionManager.swift | 2 +- .../HostBuildToolBuildOperationTests.swift | 175 ++++++++++++++++++ .../IndexSelectConfiguredTargetTests.swift | 2 +- .../IndexTargetDependencyResolverTests.swift | 24 +-- .../IndexBuildTaskConstructionTests.swift | 2 +- 7 files changed, 204 insertions(+), 26 deletions(-) diff --git a/Sources/SWBCore/BuildRequest.swift b/Sources/SWBCore/BuildRequest.swift index 38f22129..c7720567 100644 --- a/Sources/SWBCore/BuildRequest.swift +++ b/Sources/SWBCore/BuildRequest.swift @@ -248,6 +248,15 @@ public final class BuildRequest: CustomStringConvertible, Sendable { return parameters.action == .indexBuild } + /// Whether or not this request is for building the index workspace description (as opposed to the target or + /// package description). + /// + /// Note that this is only valid when *building* the description, subsequent requests that use it will have a run + /// destination set (and thus return false). + public var buildsIndexWorkspaceDescription: Bool { + return enableIndexBuildArena && parameters.activeRunDestination == nil + } + /// The quality-of-service to use for this request. public let qos: SWBQoS diff --git a/Sources/SWBCore/DependencyResolution.swift b/Sources/SWBCore/DependencyResolution.swift index 6726b02e..dcf70e52 100644 --- a/Sources/SWBCore/DependencyResolution.swift +++ b/Sources/SWBCore/DependencyResolution.swift @@ -493,7 +493,7 @@ extension SpecializationParameters { self.workspaceContext = workspaceContext self.delegate = delegate - if buildRequest.enableIndexBuildArena { + if buildRequest.buildsIndexWorkspaceDescription { // For the index build, multiple build parameters are applied during configuration of a target (to configure for multiple platforms) and the build parameters for each target in the build request is not relevant. // Keep this dictionary empty so that `LinkageDependencyResolver` fallbacks to using the build parameters of the configured targets, which are the relevant ones. self.buildParametersByTarget = [:] @@ -507,7 +507,7 @@ extension SpecializationParameters { self.defaultImposedParameters = SpecializationParameters.default(workspaceContext: workspaceContext, buildRequestContext: buildRequestContext, parameters: buildRequest.parameters) - if buildRequest.enableIndexBuildArena { + if buildRequest.buildsIndexWorkspaceDescription { let hostOS = (try? workspaceContext.core.hostOperatingSystem.xcodePlatformName) ?? "unknown" // Create the build parameters for each available platform. @@ -577,7 +577,7 @@ extension SpecializationParameters { func lookupTopLevelConfiguredTarget(_ targetInfo: BuildRequest.BuildTargetInfo) -> [ConfiguredTarget] { guard !Task.isCancelled else { return [] } let (target, parameters) = (targetInfo.target, targetInfo.parameters) - if !buildRequest.enableIndexBuildArena { + if !buildRequest.buildsIndexWorkspaceDescription { // Top-level targets get defaults imposed, in case that they are themselves using "auto" anywhere. return [lookupConfiguredTarget(target, parameters: parameters, imposedParameters: defaultImposedParameters, isTopLevelLookup: true)] } @@ -585,12 +585,6 @@ extension SpecializationParameters { // Aggregate targets are only configured as dependencies. guard target.type != .aggregate else { return [] } - let isFromPackage = workspaceContext.workspace.project(for: target).isPackage - if isFromPackage { - // Configure top-level package targets using the run-destination of the build request. - return [lookupConfiguredTarget(target, parameters: parameters, imposedParameters: defaultImposedParameters, isTopLevelLookup: true)] - } - var configuredTargets: [ConfiguredTarget] = [] let unconfiguredSettings = buildRequestContext.getCachedSettings(targetInfo.parameters, target: target) let unconfiguredSupportedPlatforms = unconfiguredSettings.globalScope.evaluate(BuiltinMacros.SUPPORTED_PLATFORMS) @@ -759,7 +753,7 @@ extension SpecializationParameters { } // At this point we know there is not a configured target for this target and parameters in our cache, so create one and return it. - let configuredTarget = ConfiguredTarget(parameters: parameters, target: target, specializeGuidForActiveRunDestination: buildRequest.enableIndexBuildArena) + let configuredTarget = ConfiguredTarget(parameters: parameters, target: target, specializeGuidForActiveRunDestination: buildRequest.buildsIndexWorkspaceDescription) configuredTargetsByTarget[configuredTarget.target, default: []].insert(configuredTarget) addSuperimposedProperties(for: configuredTarget, superimposedProperties: superimposedProperties) return configuredTarget @@ -774,7 +768,7 @@ extension SpecializationParameters { } var parameters = parameters - if buildRequest.enableIndexBuildArena { + if buildRequest.buildsIndexWorkspaceDescription { // Avoid forced propagation of "auto" overrides to targets that don't need them. If this is a host tool, // force its parameters to the host platform to avoid creating duplicate configured targets after it has // been specialized. diff --git a/Sources/SWBTaskExecution/BuildDescriptionManager.swift b/Sources/SWBTaskExecution/BuildDescriptionManager.swift index 6dc77926..ae355c56 100644 --- a/Sources/SWBTaskExecution/BuildDescriptionManager.swift +++ b/Sources/SWBTaskExecution/BuildDescriptionManager.swift @@ -285,7 +285,7 @@ package final class BuildDescriptionManager: Sendable { } var isIndexWorkspaceDescription: Bool { - return isForIndex && buildRequest.parameters.activeRunDestination == nil + return buildRequest.buildsIndexWorkspaceDescription } func signature(cacheDir: Path) throws -> BuildDescriptionSignature { diff --git a/Tests/SWBBuildSystemTests/HostBuildToolBuildOperationTests.swift b/Tests/SWBBuildSystemTests/HostBuildToolBuildOperationTests.swift index e872af3f..1e4748d3 100644 --- a/Tests/SWBBuildSystemTests/HostBuildToolBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/HostBuildToolBuildOperationTests.swift @@ -439,6 +439,181 @@ fileprivate struct HostBuildToolBuildOperationTests: CoreBasedTests { } } + @Test(.requireSDKs(.macOS)) + func testHostToolsAndDependenciesAreBuiltDuringIndexingPreparationForPackage() async throws { + try await withTemporaryDirectory { tmpDirPath async throws -> Void in + let depPackage = try await TestPackageProject( + "DepPackage", + groupTree: TestGroup("Foo", children: [ + TestFile("transitivedep.swift"), + TestFile("dep.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SWIFT_VERSION": swiftVersion, + "GENERATE_INFOPLIST_FILE": "YES", + "PRODUCT_NAME": "$(TARGET_NAME)", + "CODE_SIGNING_ALLOWED": "NO", + ]), + ], + targets: [ + TestStandardTarget("TransitivePackageDep", type: .objectFile, buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SDKROOT": "auto", + "SUPPORTED_PLATFORMS": "macosx iphoneos iphonesimulator", + ], + impartedBuildProperties: + TestImpartedBuildProperties( + buildSettings: [ + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": "IMPARTED_SETTINGS" + ]) + ), + ], buildPhases: [ + TestSourcesBuildPhase(["transitivedep.swift"]) + ]), + TestStandardTarget("PackageDep", type: .staticLibrary, buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SDKROOT": "auto", + "SUPPORTED_PLATFORMS": "macosx iphoneos iphonesimulator", + ]), + ], buildPhases: [ + TestSourcesBuildPhase(["dep.swift"]), + TestFrameworksBuildPhase([ + TestBuildFile(.target("TransitivePackageDep")) + ]) + ], dependencies: [ + "TransitivePackageDep" + ]), + TestPackageProductTarget("PackageDepProduct", frameworksBuildPhase: + TestFrameworksBuildPhase([ + TestBuildFile(.target("PackageDep")), + ] + ), buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SDKROOT": "auto", + "SUPPORTED_PLATFORMS": "macosx iphoneos iphonesimulator", + ]), + ], dependencies: [ + "PackageDep" + ]), + ]) + + let hostToolsPackage = try await TestPackageProject( + "HostToolsPackage", + groupTree: TestGroup("Foo", children: [ + TestFile("tool.swift"), + TestFile("lib.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SWIFT_VERSION": swiftVersion, + "GENERATE_INFOPLIST_FILE": "YES", + "PRODUCT_NAME": "$(TARGET_NAME)", + "CODE_SIGNING_ALLOWED": "NO", + ]), + ], + targets: [ + TestStandardTarget("HostTool", type: .hostBuildTool, buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SDKROOT": "auto", + ]) + ], buildPhases: [ + TestSourcesBuildPhase(["tool.swift"]), + TestFrameworksBuildPhase([TestBuildFile(.target("PackageDepProduct"))]) + ], dependencies: [ + "PackageDepProduct" + ]), + TestStandardTarget("HostToolClientLib", type: .objectFile, buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SDKROOT": "auto", + "SUPPORTED_PLATFORMS": "macosx iphoneos iphonesimulator", + ]), + ], buildPhases: [ + TestSourcesBuildPhase(["lib.swift"]), + ], dependencies: [ + "HostTool" + ]), + TestPackageProductTarget("HostToolClientLibProduct", frameworksBuildPhase: + TestFrameworksBuildPhase([TestBuildFile(.target("HostToolClientLib"))] + ), buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SDKROOT": "auto", + "SUPPORTED_PLATFORMS": "macosx iphoneos iphonesimulator", + ]), + ], dependencies: [ + "HostToolClientLib" + ]), + ]) + + let testWorkspace = TestWorkspace("aWorkspace", sourceRoot: tmpDirPath.join("Test"), projects: [depPackage, hostToolsPackage]) + let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false, systemInfo: .init(operatingSystemVersion: Version(99, 98, 97), productBuildVersion: "99A98", nativeArchitecture: Architecture.host.stringValue ?? "undefined_arch")) + + try await tester.fs.writeFileContents(testWorkspace.sourceRoot.join("DepPackage/transitivedep.swift")) { stream in + stream <<< + """ + public let transitiveDependencyMessage = "Hello from host tool transitive dependency!" + """ + } + + try await tester.fs.writeFileContents(testWorkspace.sourceRoot.join("DepPackage/dep.swift")) { stream in + stream <<< + """ + import TransitivePackageDep + + public let dependencyMessage = "Hello from host tool dependency! " + transitiveDependencyMessage + #if !IMPARTED_SETTINGS + #error("settings not imparted") + #endif + """ + } + + try await tester.fs.writeFileContents(testWorkspace.sourceRoot.join("HostToolsPackage/tool.swift")) { stream in + stream <<< + """ + import PackageDep + + @main struct Foo { + static func main() { + print("Hello from host tool! " + dependencyMessage) + } + } + """ + } + + try await tester.fs.writeFileContents(testWorkspace.sourceRoot.join("HostToolsPackage/lib.swift")) { stream in + stream <<< + """ + public class MyClass {} + """ + } + + try await tester.checkIndexBuild(prepareTargets: hostToolsPackage.targets.map(\.guid), workspaceOperation: false, runDestination: .anyMac, persistent: true) { results in + results.checkNoDiagnostics() + + results.checkTaskExists(.matchTargetName("HostTool"), .matchRuleType("Ld")) + try results.checkTask(.matchTargetName("HostTool"), .matchRuleType(ProductPlan.preparedForIndexPreCompilationRuleName)) { task in + try results.checkTaskFollows(task, .matchTargetName("PackageDep"), .matchRuleType("Libtool")) + } + } + } + } + @Test(.requireSDKs(.macOS)) func hostToolsAreSkippedDuringIndexingPreparationWhenUnapproved() async throws { try await withTemporaryDirectory { tmpDirPath async throws -> Void in diff --git a/Tests/SWBCoreTests/IndexSelectConfiguredTargetTests.swift b/Tests/SWBCoreTests/IndexSelectConfiguredTargetTests.swift index 7484e43f..99951832 100644 --- a/Tests/SWBCoreTests/IndexSelectConfiguredTargetTests.swift +++ b/Tests/SWBCoreTests/IndexSelectConfiguredTargetTests.swift @@ -58,7 +58,7 @@ import SWBUtil ])]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [appTarget]) { results in + try await tester.checkIndexBuildGraph(targets: [appTarget], workspaceOperation: true) { results in try results.checkSelectedPlatform(of: appTarget, "macos", "iphoneos", .macOS, expectedPlatform: "macos") try results.checkSelectedPlatform(of: appTarget, "iosmac", "macos", .macOS, expectedPlatform: "macos") try results.checkSelectedPlatform(of: appTarget, "macos", "iosmac", .watchOS, expectedPlatform: "macos") diff --git a/Tests/SWBCoreTests/IndexTargetDependencyResolverTests.swift b/Tests/SWBCoreTests/IndexTargetDependencyResolverTests.swift index 40756fd9..c787f3f7 100644 --- a/Tests/SWBCoreTests/IndexTargetDependencyResolverTests.swift +++ b/Tests/SWBCoreTests/IndexTargetDependencyResolverTests.swift @@ -134,7 +134,7 @@ import SWBUtil ])]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [macApp, macApp2, iosApp, iosApp2, fwkTarget_mac, fwkTarget_ios]) { results in + try await tester.checkIndexBuildGraph(targets: [macApp, macApp2, iosApp, iosApp2, fwkTarget_mac, fwkTarget_ios], workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "FwkTarget_mac-macos", "macApp-macos", "macApp2-macos", "FwkTarget_ios-iphoneos", "iosApp-iphoneos", "FwkTarget_ios-iphonesimulator", "iosApp-iphonesimulator", "iosApp2-iphoneos", "iosApp2-iphonesimulator", @@ -260,7 +260,7 @@ import SWBUtil ])]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [macApp, iosApp, watchKitApp, watchKitExt]) { results in + try await tester.checkIndexBuildGraph(targets: [macApp, iosApp, watchKitApp, watchKitExt], workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "macApp-macos", "iosApp-iphoneos", "iosApp-iphonesimulator", "Watchable WatchKit Extension-watchos", "Watchable WatchKit App-watchos", "Watchable WatchKit Extension-watchsimulator", "Watchable WatchKit App-watchsimulator", @@ -364,7 +364,7 @@ import SWBUtil ])]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [iosApp, watchApp, hostTool, hostToolDep]) { results in + try await tester.checkIndexBuildGraph(targets: [iosApp, watchApp, hostTool, hostToolDep], workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "hostToolDep-macos", "hostTool-macos", "iosApp-iphoneos", "iosApp-iphonesimulator", @@ -452,7 +452,7 @@ import SWBUtil ])]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [iosApp, hostTool, commonDep]) { results in + try await tester.checkIndexBuildGraph(targets: [iosApp, hostTool, commonDep], workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "commonDep-macos", "hostTool-macos", "commonDep-iphoneos", "iosApp-iphoneos", "commonDep-iphonesimulator", "iosApp-iphonesimulator", "commonDep-iosmac" ]) @@ -573,7 +573,7 @@ import SWBUtil var iosApp2_iosConfTarget: ConfiguredTarget! let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: targetsToCheck) { results in + try await tester.checkIndexBuildGraph(targets: targetsToCheck, workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "macApp2-macos", "Aggregate-macos", @@ -593,7 +593,7 @@ import SWBUtil } // Same request but with reversed order of top-level targets. Make sure the graph is same. - try await tester.checkIndexBuildGraph(targets: targetsToCheck.reversed()) { results in + try await tester.checkIndexBuildGraph(targets: targetsToCheck.reversed(), workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "iosApp2-iphoneos", "iosApp2-iphonesimulator", @@ -608,11 +608,11 @@ import SWBUtil try checkDependencies(results) } - try await tester.checkIndexBuildGraph(targets: [macApp]) { results throws in + try await tester.checkIndexBuildGraph(targets: [macApp], workspaceOperation: true) { results throws in #expect(try results.target(.init(macApp2, "macos")).guid == macApp2_macosConfTarget.guid) } - try await tester.checkIndexBuildGraph(targets: [iosApp]) { results throws in + try await tester.checkIndexBuildGraph(targets: [iosApp], workspaceOperation: true) { results throws in #expect(try results.target(.init(iosApp2, "iphoneos")).guid == iosApp2_iosConfTarget.guid) } } @@ -755,7 +755,7 @@ import SWBUtil ])]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [catalystAppTarget1, catalystAppTarget2, catalystAppTarget3, osxAppTarget, osxAppTarget_iosmac, fwkTarget, fwkTarget_osx]) { results in + try await tester.checkIndexBuildGraph(targets: [catalystAppTarget1, catalystAppTarget2, catalystAppTarget3, osxAppTarget, osxAppTarget_iosmac, fwkTarget, fwkTarget_osx], workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "FwkTarget-iphoneos", "catalystApp1-iphoneos", "FwkTarget-iphonesimulator", "catalystApp1-iphonesimulator", "FwkTarget-iosmac", "catalystApp1-iosmac", "catalystApp2-iphoneos", "catalystApp2-iphonesimulator", "catalystApp2-iosmac", "catalystApp3-iphoneos", "catalystApp3-iphonesimulator", "catalystApp3-iosmac", "FwkTarget_osx-macos", "catalystApp3-macos", "osxApp-macos", "osxApp_iosmac-iosmac", "FwkTarget_osx-iosmac", ]) @@ -912,7 +912,7 @@ import SWBUtil ]), package]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [macAppTarget, iosAppTarget]) { results in + try await tester.checkIndexBuildGraph(targets: [macAppTarget, iosAppTarget], workspaceOperation: true) { results in #expect(results.targets(macAppTarget).map { results.targetNameAndPlatform($0) } == [ "macAppTarget-macos", ]) @@ -993,7 +993,7 @@ import SWBUtil ])]) let tester = try await BuildOperationTester(core, workspace, simulated: false) - try await tester.checkIndexBuildGraph(targets: [iosApp]) { results in + try await tester.checkIndexBuildGraph(targets: [iosApp], workspaceOperation: true) { results in #expect(results.targets().map { results.targetNameAndPlatform($0) } == [ "iosApp-iphoneos", "iosApp-iphonesimulator", ]) @@ -1048,7 +1048,7 @@ import SWBUtil func checkTargetArch(_ arch: String, expected: [String: String], sourceLocation: SourceLocation = #_sourceLocation) async throws { let tester = try await BuildOperationTester(core, workspace, simulated: false) tester.systemInfo = SystemInfo(operatingSystemVersion: Version(99, 98, 97), productBuildVersion: "99A98", nativeArchitecture: arch) - try await tester.checkIndexBuildGraph(targets: [macosApp, iosApp, driver]) { results in + try await tester.checkIndexBuildGraph(targets: [macosApp, iosApp, driver], workspaceOperation: true) { results in var actual: [String: String] = [:] for target in results.targets() { actual[target.nameAndPlatform] = target.parameters.activeArchitecture diff --git a/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift index c5a7234f..fd95be85 100644 --- a/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift @@ -366,7 +366,7 @@ fileprivate struct IndexBuildTaskConstructionTests: CoreBasedTests { results.checkNoDiagnostics() } - try await tester.checkIndexBuild(targets: [fwkTarget1]) { results in + try await tester.checkIndexBuild(targets: [fwkTarget1], workspaceOperation: true) { results in results.checkWriteAuxiliaryFileTask(.matchRulePattern(["WriteAuxiliaryFile", .suffix("VFS-iphonesimulator/all-product-headers.yaml")])) { task, contents in #expect(contents == vfs_sim) } From bb19f0dc92d90efcf1147e5d64c1a178e1c146ce Mon Sep 17 00:00:00 2001 From: usama Date: Mon, 28 Apr 2025 13:06:32 -0700 Subject: [PATCH 21/30] Add -ftyped-cxx-delete to CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORT rdar://150337166 --- .../SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec | 6 +++--- .../TaskConstructionTests.swift | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec index 5b3326ac..f7ce248e 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec @@ -2925,12 +2925,12 @@ DefaultValue = compiler-default; CommandLineArgs = { compiler-default = (); - YES = ("-ftyped-cxx-new-delete"); - NO = ("-fno-typed-cxx-new-delete"); + YES = ("-ftyped-cxx-new-delete", "-ftyped-cxx-delete"); + NO = ("-fno-typed-cxx-new-delete", "-fno-typed-cxx-delete"); }; AdditionalLinkerArgs = { compiler-default = (); - YES = ("-ftyped-cxx-new-delete"); + YES = ("-ftyped-cxx-new-delete", "-ftyped-cxx-delete"); NO = (); }; }, diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index 570aed47..5a0603cc 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -8478,12 +8478,14 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } } else if let val = overrides[typedMemoryOperationsCXX] { if val == "YES" { - task.checkCommandLineContains(["-ftyped-cxx-new-delete"]) + task.checkCommandLineContains(["-ftyped-cxx-new-delete", "-ftyped-cxx-delete"]) } else if val == "NO" { - task.checkCommandLineContains(["-fno-typed-cxx-new-delete"]) + task.checkCommandLineContains(["-fno-typed-cxx-new-delete", "-fno-typed-cxx-delete"]) } else if val == "compiler-default" { task.checkCommandLineDoesNotContain("-ftyped-cxx-new-delete") + task.checkCommandLineDoesNotContain("-ftyped-cxx-delete") task.checkCommandLineDoesNotContain("-fno-typed-cxx-new-delete") + task.checkCommandLineDoesNotContain("-fno-typed-cxx-delete") } } } @@ -8501,6 +8503,11 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: override), runDestination: .macOS, fs: fs) { results -> Void in results.checkTarget("AppTarget") { target -> Void in results.checkTask(.matchTarget(target), .matchRuleType("CompileC"), body: {task in test(task: task, overrides: override)}) + if let val = override[typedMemoryOperationsCXX], val == "YES" { + results.checkTask(.matchTarget(target), .matchRuleType("Ld"), body: {task in + task.checkCommandLineContains(["-ftyped-cxx-new-delete", "-ftyped-cxx-delete"]) + }) + } } } } From adcc695753cb4149da800941d58b137d2a80452b Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Wed, 2 Apr 2025 15:10:26 -0700 Subject: [PATCH 22/30] Export CMake targets for use by SwiftPM --- CMakeLists.txt | 41 +++++++- Package.swift | 1 + Sources/SWBAndroidPlatform/CMakeLists.txt | 10 +- Sources/SWBApplePlatform/CMakeLists.txt | 10 +- Sources/SWBBuildService/CMakeLists.txt | 8 ++ Sources/SWBBuildServiceBundle/CMakeLists.txt | 2 + Sources/SWBBuildSystem/CMakeLists.txt | 8 ++ Sources/SWBCAS/CMakeLists.txt | 8 ++ Sources/SWBCLibc/CMakeLists.txt | 8 ++ Sources/SWBCSupport/CLibRemarksHelper.h | 4 +- Sources/SWBCSupport/CLibclang.h | 98 ++++++++++--------- Sources/SWBCSupport/CMakeLists.txt | 20 +++- Sources/SWBCSupport/CSupportDefines.h | 17 ++++ Sources/SWBCSupport/empty.swift | 16 +++ Sources/SWBCore/CMakeLists.txt | 8 ++ Sources/SWBGenericUnixPlatform/CMakeLists.txt | 10 +- Sources/SWBLLBuild/CMakeLists.txt | 9 +- Sources/SWBLibc/CMakeLists.txt | 8 ++ Sources/SWBMacro/CMakeLists.txt | 9 +- Sources/SWBProjectModel/CMakeLists.txt | 8 ++ Sources/SWBProtocol/CMakeLists.txt | 8 ++ Sources/SWBQNXPlatform/CMakeLists.txt | 10 +- Sources/SWBServiceCore/CMakeLists.txt | 8 ++ Sources/SWBTaskConstruction/CMakeLists.txt | 8 ++ Sources/SWBTaskExecution/CMakeLists.txt | 8 ++ Sources/SWBUniversalPlatform/CMakeLists.txt | 10 +- Sources/SWBUtil/CMakeLists.txt | 8 ++ Sources/SWBWebAssemblyPlatform/CMakeLists.txt | 10 +- Sources/SWBWindowsPlatform/CMakeLists.txt | 10 +- Sources/SwiftBuild/CMakeLists.txt | 8 ++ cmake/modules/CMakeLists.txt | 9 ++ cmake/modules/SwiftBuildConfig.cmake.in | 3 + 32 files changed, 340 insertions(+), 63 deletions(-) create mode 100644 Sources/SWBCSupport/CSupportDefines.h create mode 100644 Sources/SWBCSupport/empty.swift create mode 100644 cmake/modules/CMakeLists.txt create mode 100644 cmake/modules/SwiftBuildConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 00f40cf7..ed60c850 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,18 @@ cmake_minimum_required(VERSION 3.26...3.29) project(SwiftBuild LANGUAGES C CXX Swift) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +set(CMAKE_INSTALL_RPATH "$,@loader_path/..,$ORIGIN>") +set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH YES) + +set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL) +set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift) + +option(BUILD_SHARED_LIBS "Build shared libraries by default" YES) + set(CMAKE_C_VISIBILITY hidden) set(CMAKE_CXX_VISIBILITY hidden) set(CMAKE_CXX_STANDARD 17) @@ -35,7 +47,33 @@ add_compile_options("$<$:SHELL:-package-name SwiftBuild> # rdar://137809703 # "$<$:SHELL:-enable-upcoming-feature RegionBasedIsolation>" "$<$:SHELL:-enable-upcoming-feature ExistentialAny>" - "$<$:SHELL:-enable-upcoming-feature InternalImportsByDefault>") + "$<$:SHELL:-enable-upcoming-feature InternalImportsByDefault>" + "$<$:SHELL:-no-toolchain-stdlib-rpath>" + # Turn off autolinking within this project to reduce linker overhead. + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBLibc>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBAndroidPlatform>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBApplePlatform>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBBuildService>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBCLibc>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBGenericUnixPlatform>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBTaskConstruction>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBUtil>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBUniversalPlatform>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBWindowsPlatform>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SwiftBuild>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBWebAssemblyPlatform>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBCSupport>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBMacro>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBProjectModel>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBTaskExecution>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBServiceCore>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBQNXPlatform>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBProtocol>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBLLBuild>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBCore>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBCAS>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBBuildSystem>" + "$<$:SHELL:-Xfrontend -disable-autolink-library -Xfrontend SWBCore>") # Prefer the static initialization for the plugins. add_compile_definitions(USE_STATIC_PLUGIN_INITIALIZATION) @@ -50,3 +88,4 @@ find_package(Threads) find_package(SQLite3) add_subdirectory(Sources) +add_subdirectory(cmake/modules) diff --git a/Package.swift b/Package.swift index dcee18be..baef8b0a 100644 --- a/Package.swift +++ b/Package.swift @@ -135,6 +135,7 @@ let package = Package( swiftSettings: swiftSettings(languageMode: .v5)), .target( name: "SWBCSupport", + exclude: ["empty.swift"], publicHeadersPath: ".", cSettings: [ .define("_CRT_SECURE_NO_WARNINGS", .when(platforms: [.windows])), diff --git a/Sources/SWBAndroidPlatform/CMakeLists.txt b/Sources/SWBAndroidPlatform/CMakeLists.txt index e2f2faae..9cf4c2c4 100644 --- a/Sources/SWBAndroidPlatform/CMakeLists.txt +++ b/Sources/SWBAndroidPlatform/CMakeLists.txt @@ -28,7 +28,7 @@ file(CONFIGURE ]] ESCAPE_QUOTES @ONLY NEWLINE_STYLE LF) -add_library(SWBAndroidPlatform STATIC +add_library(SWBAndroidPlatform AndroidSDK.swift Plugin.swift) target_link_libraries(SWBAndroidPlatform PUBLIC @@ -37,3 +37,11 @@ target_link_libraries(SWBAndroidPlatform PUBLIC SWBUtil) target_sources(SWBAndroidPlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBAndroidPlatform PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBAndroidPlatform) + +install(TARGETS SWBAndroidPlatform + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBApplePlatform/CMakeLists.txt b/Sources/SWBApplePlatform/CMakeLists.txt index c636817e..fb516d7b 100644 --- a/Sources/SWBApplePlatform/CMakeLists.txt +++ b/Sources/SWBApplePlatform/CMakeLists.txt @@ -28,7 +28,7 @@ file(CONFIGURE ]] ESCAPE_QUOTES @ONLY NEWLINE_STYLE LF) -add_library(SWBApplePlatform STATIC +add_library(SWBApplePlatform AppIntentsMetadataCompiler.swift AppIntentsMetadataTaskProducer.swift AppIntentsSSUTrainingCompiler.swift @@ -75,3 +75,11 @@ target_link_libraries(SWBApplePlatform PUBLIC SWBTaskConstruction) target_sources(SWBApplePlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBApplePlatform PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBApplePlatform) + +install(TARGETS SWBApplePlatform + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBBuildService/CMakeLists.txt b/Sources/SWBBuildService/CMakeLists.txt index 00971369..ac623f70 100644 --- a/Sources/SWBBuildService/CMakeLists.txt +++ b/Sources/SWBBuildService/CMakeLists.txt @@ -37,3 +37,11 @@ target_link_libraries(SWBBuildService PUBLIC SWBWebAssemblyPlatform SWBWindowsPlatform $<$>:SwiftSystem::SystemPackage>) + +set_target_properties(SWBBuildService PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBBuildService) + +install(TARGETS SWBBuildService + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBBuildServiceBundle/CMakeLists.txt b/Sources/SWBBuildServiceBundle/CMakeLists.txt index dcae6b91..f4a03757 100644 --- a/Sources/SWBBuildServiceBundle/CMakeLists.txt +++ b/Sources/SWBBuildServiceBundle/CMakeLists.txt @@ -20,3 +20,5 @@ target_link_libraries(SWBBuildServiceBundle PRIVATE SWBCore) install(TARGETS SWBBuildServiceBundle) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBBuildServiceBundle) diff --git a/Sources/SWBBuildSystem/CMakeLists.txt b/Sources/SWBBuildSystem/CMakeLists.txt index 7bef4f58..9095c4fd 100644 --- a/Sources/SWBBuildSystem/CMakeLists.txt +++ b/Sources/SWBBuildSystem/CMakeLists.txt @@ -22,3 +22,11 @@ target_link_libraries(SWBBuildSystem PUBLIC SWBCore SWBTaskConstruction SWBTaskExecution) + +set_target_properties(SWBBuildSystem PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBBuildSystem) + +install(TARGETS SWBBuildSystem + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBCAS/CMakeLists.txt b/Sources/SWBCAS/CMakeLists.txt index b35d440e..a2909820 100644 --- a/Sources/SWBCAS/CMakeLists.txt +++ b/Sources/SWBCAS/CMakeLists.txt @@ -19,3 +19,11 @@ set_target_properties(SWBCAS PROPERTIES target_link_libraries(SWBCAS PUBLIC SWBUtil SWBCSupport) + +set_target_properties(SWBCAS PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBCAS) + +install(TARGETS SWBCAS + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBCLibc/CMakeLists.txt b/Sources/SWBCLibc/CMakeLists.txt index a5d690b0..26c4f41b 100644 --- a/Sources/SWBCLibc/CMakeLists.txt +++ b/Sources/SWBCLibc/CMakeLists.txt @@ -12,3 +12,11 @@ add_library(SWBCLibc libc.c) target_include_directories(SWBCLibc INTERFACE include) + +target_include_directories(SWBCLibc PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBCLibc) + +install(TARGETS SWBCLibc + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBCSupport/CLibRemarksHelper.h b/Sources/SWBCSupport/CLibRemarksHelper.h index d22bb643..7f2104b8 100644 --- a/Sources/SWBCSupport/CLibRemarksHelper.h +++ b/Sources/SWBCSupport/CLibRemarksHelper.h @@ -15,8 +15,10 @@ #include +#include "CSupportDefines.h" + // Swift has no way of checking if a weak_import symbol is available. // This function checks if LLVMRemarkVersion from libRemarks.dylib is available, which should be enough to assert the whole library is available as well. -bool isLibRemarksAvailable(void); +CSUPPORT_EXPORT bool isLibRemarksAvailable(void); #endif /* CLibRemarksHelper_h */ diff --git a/Sources/SWBCSupport/CLibclang.h b/Sources/SWBCSupport/CLibclang.h index 04701ae2..438c4c45 100644 --- a/Sources/SWBCSupport/CLibclang.h +++ b/Sources/SWBCSupport/CLibclang.h @@ -19,6 +19,8 @@ #include #include +#include "CSupportDefines.h" + #ifdef __cplusplus extern "C" { #endif @@ -85,85 +87,85 @@ typedef enum { /// Open an interface to libclang, from a given path. /// /// \returns nullptr on error. -libclang_t libclang_open(const char* path); +CSUPPORT_EXPORT libclang_t libclang_open(const char* path); /// Intentionally leak libclang interface. -void libclang_leak(libclang_t lib); +CSUPPORT_EXPORT void libclang_leak(libclang_t lib); /// Close an open libclang interface. -void libclang_close(libclang_t lib); +CSUPPORT_EXPORT void libclang_close(libclang_t lib); /// Get the clang version string. -void libclang_get_clang_version(libclang_t lib, void (^callback)(const char*)); +CSUPPORT_EXPORT void libclang_get_clang_version(libclang_t lib, void (^callback)(const char*)); /// Whether the libclang has the minimal set of required API. -bool libclang_has_required_api(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_required_api(libclang_t lib); /// Whether the libclang has dependency scanning support. -bool libclang_has_scanner(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_scanner(libclang_t lib); /// Whether libclang supports reporting structured scanning diagnostics. -bool libclang_has_structured_scanner_diagnostics(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_structured_scanner_diagnostics(libclang_t lib); /// Create a new scanner instance with optional CAS databases. -libclang_scanner_t libclang_scanner_create(libclang_t lib, libclang_casdatabases_t, libclang_casoptions_t); +CSUPPORT_EXPORT libclang_scanner_t libclang_scanner_create(libclang_t lib, libclang_casdatabases_t, libclang_casoptions_t); /// Dispose of a scanner. -void libclang_scanner_dispose(libclang_scanner_t scanner); +CSUPPORT_EXPORT void libclang_scanner_dispose(libclang_scanner_t scanner); /// Whether the libclang has CAS support. -bool libclang_has_cas(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_cas(libclang_t lib); /// Whether the libclang has CAS plugin support. -bool libclang_has_cas_plugin_feature(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_cas_plugin_feature(libclang_t lib); /// Whether the libclang has CAS pruning support. -bool libclang_has_cas_pruning_feature(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_cas_pruning_feature(libclang_t lib); /// Whether the libclang has CAS up-to-date checking support. -bool libclang_has_cas_up_to_date_checks_feature(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_cas_up_to_date_checks_feature(libclang_t lib); /// Whether the libclang has current working directory optimization support. -bool libclang_has_current_working_directory_optimization(libclang_t lib); +CSUPPORT_EXPORT bool libclang_has_current_working_directory_optimization(libclang_t lib); /// Create the CAS options object. -libclang_casoptions_t libclang_casoptions_create(libclang_t lib); +CSUPPORT_EXPORT libclang_casoptions_t libclang_casoptions_create(libclang_t lib); /// Dispose of the CAS options object. -void libclang_casoptions_dispose(libclang_casoptions_t); +CSUPPORT_EXPORT void libclang_casoptions_dispose(libclang_casoptions_t); /// Set the on-disk path to be used for the CAS database instances. -void libclang_casoptions_setondiskpath(libclang_casoptions_t, const char *path); +CSUPPORT_EXPORT void libclang_casoptions_setondiskpath(libclang_casoptions_t, const char *path); /// Set the plugin library path to be used for the CAS database instances. -void libclang_casoptions_setpluginpath(libclang_casoptions_t, const char *path); +CSUPPORT_EXPORT void libclang_casoptions_setpluginpath(libclang_casoptions_t, const char *path); /// Set a value for a named option that the CAS plugin supports. -void libclang_casoptions_setpluginoption(libclang_casoptions_t, const char *name, const char *value); +CSUPPORT_EXPORT void libclang_casoptions_setpluginoption(libclang_casoptions_t, const char *name, const char *value); /// Create the CAS database instances. -libclang_casdatabases_t libclang_casdatabases_create(libclang_casoptions_t, void (^error_callback)(const char *)); +CSUPPORT_EXPORT libclang_casdatabases_t libclang_casdatabases_create(libclang_casoptions_t, void (^error_callback)(const char *)); /// Dispose of the CAS databases instances. -void libclang_casdatabases_dispose(libclang_casdatabases_t); +CSUPPORT_EXPORT void libclang_casdatabases_dispose(libclang_casdatabases_t); /// Get the local storage size of the CAS/cache data in bytes. /// /// \returns the local storage size, or -1 if the implementation does not support /// reporting such size, or -2 if an error occurred. -int64_t libclang_casdatabases_get_ondisk_size(libclang_casdatabases_t, void (^error_callback)(const char *)); +CSUPPORT_EXPORT int64_t libclang_casdatabases_get_ondisk_size(libclang_casdatabases_t, void (^error_callback)(const char *)); /// Set the size for limiting disk storage growth. /// /// \param size_limit the maximum size limit in bytes. 0 means no limit. Negative values are invalid. /// \returns true if there was an error, false otherwise. -bool libclang_casdatabases_set_ondisk_size_limit(libclang_casdatabases_t, int64_t size_limit, void (^error_callback)(const char *)); +CSUPPORT_EXPORT bool libclang_casdatabases_set_ondisk_size_limit(libclang_casdatabases_t, int64_t size_limit, void (^error_callback)(const char *)); /// Prune local storage to reduce its size according to the desired size limit. /// Pruning can happen concurrently with other operations. /// /// \returns true if there was an error, false otherwise. -bool libclang_casdatabases_prune_ondisk_data(libclang_casdatabases_t, void (^error_callback)(const char *)); +CSUPPORT_EXPORT bool libclang_casdatabases_prune_ondisk_data(libclang_casdatabases_t, void (^error_callback)(const char *)); /// A callback to get the name of a given output. /// @@ -193,7 +195,7 @@ typedef size_t (^module_lookup_output_t)( /// \param callback - A block to invoke for each discovered dependency. /// \param error_callback - A block to invoke on an error. /// \returns True on success, false if the scanner failed. -bool libclang_scanner_scan_dependencies( +CSUPPORT_EXPORT bool libclang_scanner_scan_dependencies( libclang_scanner_t scanner, int argc, char *const *argv, const char *workingDirectory, __attribute__((noescape)) module_lookup_output_t module_lookup_output, __attribute__((noescape)) void (^modules_callback)(clang_module_dependency_set_t, bool), @@ -210,13 +212,13 @@ bool libclang_scanner_scan_dependencies( /// \param envp - A null terminated array of KEY=VALUE pairs (`envp`-style). /// \returns True on success, false on failure (including if the libclang cannot /// support). -bool libclang_driver_get_actions(libclang_t wrapped_lib, - int argc, - char* const* argv, - char* const* envp, - const char* working_directory, - void (^callback)(int argc, const char** argv), - void (^error_callback)(const char*)); +CSUPPORT_EXPORT bool libclang_driver_get_actions(libclang_t wrapped_lib, + int argc, + char* const* argv, + char* const* envp, + const char* working_directory, + void (^callback)(int argc, const char** argv), + void (^error_callback)(const char*)); struct libclang_diagnostic_t_ { char *file_name; @@ -255,31 +257,31 @@ struct libclang_diagnostic_set_t_ { libclang_diagnostic_t *diagnostics; }; -libclang_diagnostic_set_t libclang_read_diagnostics(libclang_t wrapped_lib, - const char* path, - const char** error_string); +CSUPPORT_EXPORT libclang_diagnostic_set_t libclang_read_diagnostics(libclang_t wrapped_lib, + const char* path, + const char** error_string); -void libclang_diagnostic_set_dispose(libclang_diagnostic_set_t diagnostic_set); +CSUPPORT_EXPORT void libclang_diagnostic_set_dispose(libclang_diagnostic_set_t diagnostic_set); -void libclang_cas_load_object_async(libclang_casdatabases_t, const char *casid, void (^callback)(libclang_cas_casobject_t, const char *error)); -void libclang_cas_casobject_dispose(libclang_cas_casobject_t); +CSUPPORT_EXPORT void libclang_cas_load_object_async(libclang_casdatabases_t, const char *casid, void (^callback)(libclang_cas_casobject_t, const char *error)); +CSUPPORT_EXPORT void libclang_cas_casobject_dispose(libclang_cas_casobject_t); -bool libclang_cas_casobject_is_materialized(libclang_casdatabases_t, const char *casid, void (^error_callback)(const char *)); +CSUPPORT_EXPORT bool libclang_cas_casobject_is_materialized(libclang_casdatabases_t, const char *casid, void (^error_callback)(const char *)); -libclang_cas_cached_compilation_t libclang_cas_get_cached_compilation(libclang_casdatabases_t, const char *cache_key, bool globally, void (^error_callback)(const char *)); -void libclang_cas_get_cached_compilation_async(libclang_casdatabases_t, const char *cache_key, bool globally, void (^callback)(libclang_cas_cached_compilation_t, const char *error)); +CSUPPORT_EXPORT libclang_cas_cached_compilation_t libclang_cas_get_cached_compilation(libclang_casdatabases_t, const char *cache_key, bool globally, void (^error_callback)(const char *)); +CSUPPORT_EXPORT void libclang_cas_get_cached_compilation_async(libclang_casdatabases_t, const char *cache_key, bool globally, void (^callback)(libclang_cas_cached_compilation_t, const char *error)); -void libclang_cas_cached_compilation_dispose(libclang_cas_cached_compilation_t); +CSUPPORT_EXPORT void libclang_cas_cached_compilation_dispose(libclang_cas_cached_compilation_t); -size_t libclang_cas_cached_compilation_get_num_outputs(libclang_cas_cached_compilation_t); -void libclang_cas_cached_compilation_get_output_name(libclang_cas_cached_compilation_t, size_t output_idx, void (^callback)(const char*)); -void libclang_cas_cached_compilation_get_output_casid(libclang_cas_cached_compilation_t, size_t output_idx, void (^callback)(const char*)); -bool libclang_cas_cached_compilation_is_output_materialized(libclang_cas_cached_compilation_t, size_t output_idx); -void libclang_cas_cached_compilation_make_global_async(libclang_cas_cached_compilation_t, void (^callback)(const char *error)); +CSUPPORT_EXPORT size_t libclang_cas_cached_compilation_get_num_outputs(libclang_cas_cached_compilation_t); +CSUPPORT_EXPORT void libclang_cas_cached_compilation_get_output_name(libclang_cas_cached_compilation_t, size_t output_idx, void (^callback)(const char*)); +CSUPPORT_EXPORT void libclang_cas_cached_compilation_get_output_casid(libclang_cas_cached_compilation_t, size_t output_idx, void (^callback)(const char*)); +CSUPPORT_EXPORT bool libclang_cas_cached_compilation_is_output_materialized(libclang_cas_cached_compilation_t, size_t output_idx); +CSUPPORT_EXPORT void libclang_cas_cached_compilation_make_global_async(libclang_cas_cached_compilation_t, void (^callback)(const char *error)); /// Synchronous call. /// \returns True on success, false on failure. -bool libclang_cas_replay_compilation(libclang_cas_cached_compilation_t, int argc, char *const *argv, const char *workingDirectory, void (^callback)(const char* diagnostic_text, const char *error)); +CSUPPORT_EXPORT bool libclang_cas_replay_compilation(libclang_cas_cached_compilation_t, int argc, char *const *argv, const char *workingDirectory, void (^callback)(const char* diagnostic_text, const char *error)); #ifdef __cplusplus } diff --git a/Sources/SWBCSupport/CMakeLists.txt b/Sources/SWBCSupport/CMakeLists.txt index 07903eae..c5c09de2 100644 --- a/Sources/SWBCSupport/CMakeLists.txt +++ b/Sources/SWBCSupport/CMakeLists.txt @@ -8,16 +8,30 @@ See http://swift.org/LICENSE.txt for license information See http://swift.org/CONTRIBUTORS.txt for Swift project authors ]] -add_library(SWBCSupport STATIC +add_library(SWBCSupport CLibclang.cpp - CLibRemarksHelper.c) + CLibRemarksHelper.c + empty.swift) +# Use swiftc as the linker so we pick up search paths for the blocks runtime, +# and enable C++ interop so it delegates to clang++. +set_target_properties(SWBCSupport PROPERTIES + LINKER_LANGUAGE Swift) +set_target_properties(SWBCSupport PROPERTIES + Swift_MODULE_NAME __SWBCSupport_Empty) +target_link_options(SWBCSupport PRIVATE + -cxx-interoperability-mode=default) target_compile_definitions(SWBCSupport PRIVATE $<$:_CRT_SECURE_NO_WARNINGS> $<$:_CRT_NONSTDC_NO_WARNINGS>) target_compile_options(SWBCSupport PRIVATE - -fblocks) + "$<$:SHELL:-fblocks>") target_include_directories(SWBCSupport PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # TODO(compnerd) wire this up with `find_package` target_link_libraries(SWBCSupport PRIVATE $<$>:BlocksRuntime>) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBCSupport) + +install(TARGETS SWBCSupport + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBCSupport/CSupportDefines.h b/Sources/SWBCSupport/CSupportDefines.h new file mode 100644 index 00000000..49da425f --- /dev/null +++ b/Sources/SWBCSupport/CSupportDefines.h @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#ifdef _WIN32 +#define CSUPPORT_EXPORT __declspec(dllexport) +#else +#define CSUPPORT_EXPORT +#endif diff --git a/Sources/SWBCSupport/empty.swift b/Sources/SWBCSupport/empty.swift new file mode 100644 index 00000000..8898982c --- /dev/null +++ b/Sources/SWBCSupport/empty.swift @@ -0,0 +1,16 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +// This file is intentionally left blank. When built with CMake, +// SWBCSupport sets the link language to Swift w/ C++ interop +// to find libblocksruntime, and requires at least one Swift +// source file to avoid downstream issues. diff --git a/Sources/SWBCore/CMakeLists.txt b/Sources/SWBCore/CMakeLists.txt index 467c8aa8..10a5077a 100644 --- a/Sources/SWBCore/CMakeLists.txt +++ b/Sources/SWBCore/CMakeLists.txt @@ -207,3 +207,11 @@ target_link_libraries(SWBCore PUBLIC SwiftDriver) target_sources(SWBCore PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBCore PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBCore) + +install(TARGETS SWBCore + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBGenericUnixPlatform/CMakeLists.txt b/Sources/SWBGenericUnixPlatform/CMakeLists.txt index 8e5213b8..4a7550cf 100644 --- a/Sources/SWBGenericUnixPlatform/CMakeLists.txt +++ b/Sources/SWBGenericUnixPlatform/CMakeLists.txt @@ -28,10 +28,18 @@ file(CONFIGURE ]] ESCAPE_QUOTES @ONLY NEWLINE_STYLE LF) -add_library(SWBGenericUnixPlatform STATIC +add_library(SWBGenericUnixPlatform Plugin.swift) target_link_libraries(SWBGenericUnixPlatform PUBLIC SWBCore SWBUtil) target_sources(SWBGenericUnixPlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBGenericUnixPlatform PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBGenericUnixPlatform) + +install(TARGETS SWBGenericUnixPlatform + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBLLBuild/CMakeLists.txt b/Sources/SWBLLBuild/CMakeLists.txt index 3f36654b..353db118 100644 --- a/Sources/SWBLLBuild/CMakeLists.txt +++ b/Sources/SWBLLBuild/CMakeLists.txt @@ -14,5 +14,12 @@ set_target_properties(SWBLLBuild PROPERTIES Swift_LANGUAGE_VERSION 6) target_link_libraries(SWBLLBuild PUBLIC SWBUtil - $<$>:libllbuild> $<$>:llbuildSwift>) + +set_target_properties(SWBLLBuild PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBLLBuild) + +install(TARGETS SWBLLBuild + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBLibc/CMakeLists.txt b/Sources/SWBLibc/CMakeLists.txt index 8e5daf61..3e9917c6 100644 --- a/Sources/SWBLibc/CMakeLists.txt +++ b/Sources/SWBLibc/CMakeLists.txt @@ -19,3 +19,11 @@ target_link_libraries(SWBLibc PUBLIC # without this explicit configuration. target_include_directories(SWBLibc PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) + +set_target_properties(SWBLibc PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBLibc) + +install(TARGETS SWBLibc + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBMacro/CMakeLists.txt b/Sources/SWBMacro/CMakeLists.txt index 4abeddf1..aaa68d49 100644 --- a/Sources/SWBMacro/CMakeLists.txt +++ b/Sources/SWBMacro/CMakeLists.txt @@ -31,5 +31,10 @@ target_link_libraries(SWBMacro PUBLIC SwiftDriver TSCBasic) -target_include_directories(SWBMacro PUBLIC - ${CMAKE_CURRENT_BINARY_DIR}) +set_target_properties(SWBMacro PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBMacro) + +install(TARGETS SWBMacro + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBProjectModel/CMakeLists.txt b/Sources/SWBProjectModel/CMakeLists.txt index 3a98c919..721ae581 100644 --- a/Sources/SWBProjectModel/CMakeLists.txt +++ b/Sources/SWBProjectModel/CMakeLists.txt @@ -20,3 +20,11 @@ set_target_properties(SWBProjectModel PROPERTIES Swift_LANGUAGE_VERSION 6) target_link_libraries(SWBProjectModel PUBLIC SWBProtocol) + +set_target_properties(SWBProjectModel PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBProjectModel) + +install(TARGETS SWBProjectModel + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBProtocol/CMakeLists.txt b/Sources/SWBProtocol/CMakeLists.txt index d00c636b..9208d4b2 100644 --- a/Sources/SWBProtocol/CMakeLists.txt +++ b/Sources/SWBProtocol/CMakeLists.txt @@ -48,3 +48,11 @@ set_target_properties(SWBProtocol PROPERTIES Swift_LANGUAGE_VERSION 6) target_link_libraries(SWBProtocol PUBLIC SWBUtil) + +set_target_properties(SWBProtocol PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBProtocol) + +install(TARGETS SWBProtocol + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBQNXPlatform/CMakeLists.txt b/Sources/SWBQNXPlatform/CMakeLists.txt index b458f8ce..23249e86 100644 --- a/Sources/SWBQNXPlatform/CMakeLists.txt +++ b/Sources/SWBQNXPlatform/CMakeLists.txt @@ -28,7 +28,7 @@ file(CONFIGURE ]] ESCAPE_QUOTES @ONLY NEWLINE_STYLE LF) -add_library(SWBQNXPlatform STATIC +add_library(SWBQNXPlatform Plugin.swift QNXSDP.swift) target_link_libraries(SWBQNXPlatform PUBLIC @@ -37,3 +37,11 @@ target_link_libraries(SWBQNXPlatform PUBLIC SWBUtil) target_sources(SWBQNXPlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBQNXPlatform PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBQNXPlatform) + +install(TARGETS SWBQNXPlatform + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBServiceCore/CMakeLists.txt b/Sources/SWBServiceCore/CMakeLists.txt index 673eec1e..9d39ed50 100644 --- a/Sources/SWBServiceCore/CMakeLists.txt +++ b/Sources/SWBServiceCore/CMakeLists.txt @@ -18,3 +18,11 @@ set_target_properties(SWBServiceCore PROPERTIES Swift_LANGUAGE_VERSION 6) target_link_libraries(SWBServiceCore PUBLIC SWBProtocol) + +set_target_properties(SWBServiceCore PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBServiceCore) + +install(TARGETS SWBServiceCore + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBTaskConstruction/CMakeLists.txt b/Sources/SWBTaskConstruction/CMakeLists.txt index 7657836a..b792f9dc 100644 --- a/Sources/SWBTaskConstruction/CMakeLists.txt +++ b/Sources/SWBTaskConstruction/CMakeLists.txt @@ -63,3 +63,11 @@ set_target_properties(SWBTaskConstruction PROPERTIES target_link_libraries(SWBTaskConstruction PUBLIC SWBCore SWBUtil) + +set_target_properties(SWBTaskConstruction PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBTaskConstruction) + +install(TARGETS SWBTaskConstruction + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBTaskExecution/CMakeLists.txt b/Sources/SWBTaskExecution/CMakeLists.txt index c5bab209..6c7cba03 100644 --- a/Sources/SWBTaskExecution/CMakeLists.txt +++ b/Sources/SWBTaskExecution/CMakeLists.txt @@ -82,3 +82,11 @@ target_link_libraries(SWBTaskExecution PUBLIC SWBLLBuild SWBTaskConstruction SWBUtil) + +set_target_properties(SWBTaskExecution PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBTaskExecution) + +install(TARGETS SWBTaskExecution + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBUniversalPlatform/CMakeLists.txt b/Sources/SWBUniversalPlatform/CMakeLists.txt index f331ab96..7b0fffd7 100644 --- a/Sources/SWBUniversalPlatform/CMakeLists.txt +++ b/Sources/SWBUniversalPlatform/CMakeLists.txt @@ -28,7 +28,7 @@ file(CONFIGURE ]] ESCAPE_QUOTES @ONLY NEWLINE_STYLE LF) -add_library(SWBUniversalPlatform STATIC +add_library(SWBUniversalPlatform CopyPlistFile.swift CopyStringsFile.swift CppTool.swift @@ -48,3 +48,11 @@ target_link_libraries(SWBUniversalPlatform PUBLIC ArgumentParser) target_sources(SWBUniversalPlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBUniversalPlatform PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBUniversalPlatform) + +install(TARGETS SWBUniversalPlatform + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBUtil/CMakeLists.txt b/Sources/SWBUtil/CMakeLists.txt index 0be8ed58..eae57b98 100644 --- a/Sources/SWBUtil/CMakeLists.txt +++ b/Sources/SWBUtil/CMakeLists.txt @@ -111,3 +111,11 @@ target_link_libraries(SWBUtil PUBLIC SWBLibc ArgumentParser $<$>:SwiftSystem::SystemPackage>) + +set_target_properties(SWBUtil PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBUtil) + +install(TARGETS SWBUtil + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBWebAssemblyPlatform/CMakeLists.txt b/Sources/SWBWebAssemblyPlatform/CMakeLists.txt index 8953a5aa..0c12e39a 100644 --- a/Sources/SWBWebAssemblyPlatform/CMakeLists.txt +++ b/Sources/SWBWebAssemblyPlatform/CMakeLists.txt @@ -28,7 +28,7 @@ file(CONFIGURE ]] ESCAPE_QUOTES @ONLY NEWLINE_STYLE LF) -add_library(SWBWebAssemblyPlatform STATIC +add_library(SWBWebAssemblyPlatform Plugin.swift) target_link_libraries(SWBWebAssemblyPlatform PUBLIC SWBCore @@ -36,3 +36,11 @@ target_link_libraries(SWBWebAssemblyPlatform PUBLIC SWBUtil) target_sources(SWBWebAssemblyPlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBWebAssemblyPlatform PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBWebAssemblyPlatform) + +install(TARGETS SWBWebAssemblyPlatform + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SWBWindowsPlatform/CMakeLists.txt b/Sources/SWBWindowsPlatform/CMakeLists.txt index 79e016d4..8f40d3c5 100644 --- a/Sources/SWBWindowsPlatform/CMakeLists.txt +++ b/Sources/SWBWindowsPlatform/CMakeLists.txt @@ -28,7 +28,7 @@ file(CONFIGURE ]] ESCAPE_QUOTES @ONLY NEWLINE_STYLE LF) -add_library(SWBWindowsPlatform STATIC +add_library(SWBWindowsPlatform KnownFolders.swift Plugin.swift VSInstallation.swift) @@ -38,3 +38,11 @@ target_link_libraries(SWBWindowsPlatform PUBLIC SWBUtil) target_sources(SWBWindowsPlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") + +set_target_properties(SWBWindowsPlatform PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SWBWindowsPlatform) + +install(TARGETS SWBWindowsPlatform + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/Sources/SwiftBuild/CMakeLists.txt b/Sources/SwiftBuild/CMakeLists.txt index 8d1343bc..45970977 100644 --- a/Sources/SwiftBuild/CMakeLists.txt +++ b/Sources/SwiftBuild/CMakeLists.txt @@ -66,3 +66,11 @@ target_link_libraries(SwiftBuild PUBLIC SWBProtocol SWBUtil SWBProjectModel) + +set_target_properties(SwiftBuild PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY}) + +set_property(GLOBAL APPEND PROPERTY SWIFTBUILD_EXPORTS SwiftBuild) + +install(TARGETS SwiftBuild + ARCHIVE DESTINATION "${SwiftBuild_INSTALL_LIBDIR}") diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt new file mode 100644 index 00000000..1f05107b --- /dev/null +++ b/cmake/modules/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SWIFTBUILD_EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/SwiftBuildExports.cmake) + +configure_file(SwiftBuildConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/SwiftBuildConfig.cmake) + +get_property(SWIFTBUILD_EXPORTS GLOBAL PROPERTY SWIFTBUILD_EXPORTS) +export(TARGETS ${SWIFTBUILD_EXPORTS} + NAMESPACE SwiftBuild:: + FILE ${SWIFTBUILD_EXPORTS_FILE}) diff --git a/cmake/modules/SwiftBuildConfig.cmake.in b/cmake/modules/SwiftBuildConfig.cmake.in new file mode 100644 index 00000000..74cb8f0f --- /dev/null +++ b/cmake/modules/SwiftBuildConfig.cmake.in @@ -0,0 +1,3 @@ +if(NOT TARGET SwiftBuild::SwiftBuild) + include(@SWIFTBUILD_EXPORTS_FILE@) +endif() From ea8d61926f4b0e3b23035af2e4e907f20178bcac Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 28 Apr 2025 11:46:25 -0700 Subject: [PATCH 23/30] Inclusive language: rename master object file to prelinked object file This renames occurrences of "master" in relation to this feature to "prelink" or "prelinked". There are 3 remaining exceptions, which is to default the GENERATE_PRELINK_OBJECT_FILE build setting to GENERATE_MASTER_OBJECT_FILE for backwards compatibility. --- Sources/SWBCore/CMakeLists.txt | 2 +- Sources/SWBCore/Settings/BuiltinMacros.swift | 4 +- .../SpecImplementations/RegisterSpecs.swift | 2 +- ...ctLink.swift => PrelinkedObjectLink.swift} | 16 ++--- Sources/SWBCore/Specs/CoreBuildSystem.xcspec | 8 +-- .../Specs/en.lproj/CoreBuildSystem.strings | 4 +- .../SWBProjectModel/PIFGenerationModel.swift | 5 +- .../SourcesTaskProducer.swift | 12 ++-- .../TaskProducers/TaskProducer.swift | 10 ++-- .../ProjectModel/BuildSettings.swift | 2 +- ...s.swift => PrelinkedObjectFileTests.swift} | 58 +++++++++---------- .../TaskConstructionTests.swift | 12 ++-- 12 files changed, 69 insertions(+), 66 deletions(-) rename Sources/SWBCore/SpecImplementations/Tools/{MasterObjectLink.swift => PrelinkedObjectLink.swift} (77%) rename Tests/SWBTaskConstructionTests/{MasterObjectFileTests.swift => PrelinkedObjectFileTests.swift} (90%) diff --git a/Sources/SWBCore/CMakeLists.txt b/Sources/SWBCore/CMakeLists.txt index 467c8aa8..f0be7c8d 100644 --- a/Sources/SWBCore/CMakeLists.txt +++ b/Sources/SWBCore/CMakeLists.txt @@ -155,11 +155,11 @@ add_library(SWBCore SpecImplementations/Tools/LaunchServicesRegisterTool.swift SpecImplementations/Tools/LinkerTools.swift SpecImplementations/Tools/Lipo.swift - SpecImplementations/Tools/MasterObjectLink.swift SpecImplementations/Tools/MergeInfoPlist.swift SpecImplementations/Tools/MkdirTool.swift SpecImplementations/Tools/ModulesVerifierTool.swift SpecImplementations/Tools/PLUtilTool.swift + SpecImplementations/Tools/PrelinkedObjectLink.swift SpecImplementations/Tools/ProcessSDKImports.swift SpecImplementations/Tools/ProcessXCFrameworkLibrary.swift SpecImplementations/Tools/ProductPackaging.swift diff --git a/Sources/SWBCore/Settings/BuiltinMacros.swift b/Sources/SWBCore/Settings/BuiltinMacros.swift index 13bec632..1ca2ea8e 100644 --- a/Sources/SWBCore/Settings/BuiltinMacros.swift +++ b/Sources/SWBCore/Settings/BuiltinMacros.swift @@ -717,7 +717,7 @@ public final class BuiltinMacros { public static let GENERATE_EMBED_IN_CODE_ACCESSORS = BuiltinMacros.declareBooleanMacro("GENERATE_EMBED_IN_CODE_ACCESSORS") public static let GENERATE_INFOPLIST_FILE = BuiltinMacros.declareBooleanMacro("GENERATE_INFOPLIST_FILE") public static let GENERATE_KERNEL_MODULE_INFO_FILE = BuiltinMacros.declareBooleanMacro("GENERATE_KERNEL_MODULE_INFO_FILE") - public static let GENERATE_MASTER_OBJECT_FILE = BuiltinMacros.declareBooleanMacro("GENERATE_MASTER_OBJECT_FILE") + public static let GENERATE_PRELINK_OBJECT_FILE = BuiltinMacros.declareBooleanMacro("GENERATE_PRELINK_OBJECT_FILE") public static let GENERATE_PKGINFO_FILE = BuiltinMacros.declareBooleanMacro("GENERATE_PKGINFO_FILE") public static let GENERATE_RESOURCE_ACCESSORS = BuiltinMacros.declareBooleanMacro("GENERATE_RESOURCE_ACCESSORS") public static let GENERATE_TEST_ENTRY_POINT = BuiltinMacros.declareBooleanMacro("GENERATE_TEST_ENTRY_POINT") @@ -1753,7 +1753,7 @@ public final class BuiltinMacros { GENERATE_EMBED_IN_CODE_ACCESSORS, GENERATE_INFOPLIST_FILE, GENERATE_KERNEL_MODULE_INFO_FILE, - GENERATE_MASTER_OBJECT_FILE, + GENERATE_PRELINK_OBJECT_FILE, GENERATE_PKGINFO_FILE, GENERATE_RESOURCE_ACCESSORS, GENERATE_TEST_ENTRY_POINT, diff --git a/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift b/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift index 115a9b73..4bf7277f 100644 --- a/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift +++ b/Sources/SWBCore/SpecImplementations/RegisterSpecs.swift @@ -129,7 +129,7 @@ public struct BuiltinSpecsExtension: SpecificationsExtension { ValidateDevelopmentAssets.self, ConstructStubExecutorFileListToolSpec.self, GateSpec.self, - MasterObjectLinkSpec.self, + PrelinkedObjectLinkSpec.self, SetAttributesSpec.self, WriteFileSpec.self, SignatureCollectionSpec.self, diff --git a/Sources/SWBCore/SpecImplementations/Tools/MasterObjectLink.swift b/Sources/SWBCore/SpecImplementations/Tools/PrelinkedObjectLink.swift similarity index 77% rename from Sources/SWBCore/SpecImplementations/Tools/MasterObjectLink.swift rename to Sources/SWBCore/SpecImplementations/Tools/PrelinkedObjectLink.swift index ade7bd11..d651edfb 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/MasterObjectLink.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/PrelinkedObjectLink.swift @@ -13,15 +13,15 @@ import SWBUtil import SWBMacro -/// Spec to use the linker to run `ld -r` to create a prelinked object file (a.k.a. "master object file"). -final class MasterObjectLinkSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { - static let identifier = "com.apple.build-tools.master-object-link" +/// Spec to use the linker to run `ld -r` to create a prelinked object file. +public final class PrelinkedObjectLinkSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { + public static let identifier = "com.apple.build-tools.prelinked-object-link" - class func construct(registry: SpecRegistry, proxy: SpecProxy) -> Spec { - return MasterObjectLinkSpec(registry, proxy, ruleInfoTemplate: [], commandLineTemplate: []) + public class func construct(registry: SpecRegistry, proxy: SpecProxy) -> Spec { + return PrelinkedObjectLinkSpec(registry, proxy, ruleInfoTemplate: [], commandLineTemplate: []) } - override func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) async { + public override func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) async { guard let toolSpecInfo = await cbc.producer.ldLinkerSpec.discoveredCommandLineToolSpecInfo(cbc.producer, cbc.scope, delegate) as? DiscoveredLdLinkerToolSpecInfo else { delegate.error("Could not find path to ld binary") return @@ -62,7 +62,7 @@ final class MasterObjectLinkSpec: CommandLineToolSpec, SpecImplementationType, @ commandLine += cbc.scope.evaluate(BuiltinMacros.PRELINK_FLAGS) let warningLdFlags = cbc.scope.evaluate(BuiltinMacros.WARNING_LDFLAGS) if !warningLdFlags.isEmpty { - // WARNING_LDFLAGS for some reason is only used for creating the master object file. + // WARNING_LDFLAGS for some reason is only used for creating the prelinked object file. delegate.warning("WARNING_LDFLAGS is deprecated; use OTHER_LDFLAGS instead.", location: .buildSetting(BuiltinMacros.WARNING_LDFLAGS)) commandLine += warningLdFlags } @@ -70,6 +70,6 @@ final class MasterObjectLinkSpec: CommandLineToolSpec, SpecImplementationType, @ commandLine += cbc.scope.evaluate(BuiltinMacros.PRELINK_LIBS) commandLine += ["-o", outputPath.str] - delegate.createTask(type: self, ruleInfo: ["MasterObjectLink", outputPath.str], commandLine: commandLine, environment: EnvironmentBindings(), workingDirectory: cbc.producer.defaultWorkingDirectory, inputs: cbc.inputs.map({ $0.absolutePath }), outputs: [outputPath], action: nil, execDescription: "Link \(outputPath.basename)", enableSandboxing: enableSandboxing) + delegate.createTask(type: self, ruleInfo: ["PrelinkedObjectLink", outputPath.str], commandLine: commandLine, environment: EnvironmentBindings(), workingDirectory: cbc.producer.defaultWorkingDirectory, inputs: cbc.inputs.map({ $0.absolutePath }), outputs: [outputPath], action: nil, execDescription: "Link \(outputPath.basename)", enableSandboxing: enableSandboxing) } } diff --git a/Sources/SWBCore/Specs/CoreBuildSystem.xcspec b/Sources/SWBCore/Specs/CoreBuildSystem.xcspec index d48771f6..d89f2142 100644 --- a/Sources/SWBCore/Specs/CoreBuildSystem.xcspec +++ b/Sources/SWBCore/Specs/CoreBuildSystem.xcspec @@ -442,9 +442,9 @@ }; }, { - Name = "GENERATE_MASTER_OBJECT_FILE"; + Name = "GENERATE_PRELINK_OBJECT_FILE"; Type = bool; - DefaultValue = NO; + DefaultValue = "$(GENERATE_MASTER_OBJECT_FILE:default=NO)"; // ignore-unacceptable-language; kept for compatibility }, { Name = "PRELINK_LIBS"; @@ -1598,10 +1598,10 @@ When `GENERATE_INFOPLIST_FILE` is enabled, sets the value of the [CFBundleIdenti ); }, { - Name = "GENERATE_MASTER_OBJECT_FILE"; + Name = "GENERATE_PRELINK_OBJECT_FILE"; Type = Boolean; Category = "Linking - General"; - DefaultValue = NO; + DefaultValue = "$(GENERATE_MASTER_OBJECT_FILE:default=NO)"; // ignore-unacceptable-language; kept for compatibility ConditionFlavors = ( arch, sdk, diff --git a/Sources/SWBCore/Specs/en.lproj/CoreBuildSystem.strings b/Sources/SWBCore/Specs/en.lproj/CoreBuildSystem.strings index 455318c8..a33cfc4a 100644 --- a/Sources/SWBCore/Specs/en.lproj/CoreBuildSystem.strings +++ b/Sources/SWBCore/Specs/en.lproj/CoreBuildSystem.strings @@ -409,8 +409,8 @@ Generally you should not specify an order file in Debug or Development configura "[LINKER_DISPLAYS_MANGLED_NAMES]-name" = "Display Mangled Names"; "[LINKER_DISPLAYS_MANGLED_NAMES]-description" = "Activating this setting causes the linker to display mangled names for C++ symbols. Normally, this is not recommended, but turning it on can help to diagnose and solve C++ link errors."; -"[GENERATE_MASTER_OBJECT_FILE]-name" = "Perform Single-Object Prelink"; -"[GENERATE_MASTER_OBJECT_FILE]-description" = "Activating this setting will cause the object files built by a target to be prelinked using `ld -r` into a single object file, and that object file will then be linked into the final product. This is useful to force the linker to resolve symbols and link the object files into a single module before building a static library. Also, a separate set of link flags can be applied to the prelink allowing additional control over, for instance, exported symbols."; +"[GENERATE_PRELINK_OBJECT_FILE]-name" = "Perform Single-Object Prelink"; +"[GENERATE_PRELINK_OBJECT_FILE]-description" = "Activating this setting will cause the object files built by a target to be prelinked using `ld -r` into a single object file, and that object file will then be linked into the final product. This is useful to force the linker to resolve symbols and link the object files into a single module before building a static library. Also, a separate set of link flags can be applied to the prelink allowing additional control over, for instance, exported symbols."; "[PRELINK_LIBS]-name" = "Prelink libraries"; "[PRELINK_LIBS]-description" = "Additional libraries to pass when performing a single-object prelink."; diff --git a/Sources/SWBProjectModel/PIFGenerationModel.swift b/Sources/SWBProjectModel/PIFGenerationModel.swift index 975fc22b..698a7343 100644 --- a/Sources/SWBProjectModel/PIFGenerationModel.swift +++ b/Sources/SWBProjectModel/PIFGenerationModel.swift @@ -963,7 +963,7 @@ public enum PIF { public var GCC_OPTIMIZATION_LEVEL: String? public var GCC_PREPROCESSOR_DEFINITIONS: [String]? public var GENERATE_EMBED_IN_CODE_ACCESSORS: String? - public var GENERATE_MASTER_OBJECT_FILE: String? + public var GENERATE_PRELINK_OBJECT_FILE: String? public var GENERATE_RESOURCE_ACCESSORS: String? public var HEADER_SEARCH_PATHS: [String]? public var INFOPLIST_FILE: String? @@ -1045,6 +1045,9 @@ public enum PIF { public var USE_HEADERMAP: String? public var USES_SWIFTPM_UNSAFE_FLAGS: String? public var WATCHOS_DEPLOYMENT_TARGET: String? + + @available(*, deprecated, renamed: "GENERATE_PRELINK_OBJECT_FILE") + public var GENERATE_MASTER_OBJECT_FILE: String? // ignore-unacceptable-language } } diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift index 89ecceaa..b2ab7c3e 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift @@ -865,14 +865,14 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase } } - // Handle linking master objects. Presently we always do this if GENERATE_MASTER_OBJECT_FILE even if there are no other tasks, since PRELINK_LIBS or PRELINK_FLAGS might be set to values which will cause a master object file to be generated. - // FIXME: The implicitly means that if GENERATE_MASTER_OBJECT_FILE is enabled then we will always try to link. That's arguably not correct. - if !isForAPI && scope.evaluate(BuiltinMacros.GENERATE_MASTER_OBJECT_FILE) { - let executableName = scope.evaluate(BuiltinMacros.EXECUTABLE_NAME) + "-" + arch + "-master.o" + // Handle linking prelinked objects. Presently we always do this if GENERATE_PRELINK_OBJECT_FILE even if there are no other tasks, since PRELINK_LIBS or PRELINK_FLAGS might be set to values which will cause a prelinked object file to be generated. + // FIXME: The implicitly means that if GENERATE_PRELINK_OBJECT_FILE is enabled then we will always try to link. That's arguably not correct. + if !isForAPI && scope.evaluate(BuiltinMacros.GENERATE_PRELINK_OBJECT_FILE) { + let executableName = scope.evaluate(BuiltinMacros.EXECUTABLE_NAME) + "-" + arch + "-prelink.o" // FIXME: It would be more consistent to put this in the per-arch directory. let output = Path(scope.evaluate(BuiltinMacros.PER_VARIANT_OBJECT_FILE_DIR)).join(executableName) await appendGeneratedTasks(&perArchTasks, options: [.linking, .linkingRequirement, .unsignedProductRequirement]) { delegate in - await context.masterObjectLinkSpec.constructTasks(CommandBuildContext(producer: context, scope: scope, inputs: linkerInputNodes.map { FileToBuild(context: context, absolutePath: $0.path) }, output: output), delegate) + await context.prelinkedObjectLinkSpec.constructTasks(CommandBuildContext(producer: context, scope: scope, inputs: linkerInputNodes.map { FileToBuild(context: context, absolutePath: $0.path) }, output: output), delegate) } linkerInputNodes = [context.createNode(output)] } @@ -912,7 +912,7 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase continue } - // Create the linker task. If we have no input files but decide to create the task anyway, then this task will rely on gate tasks to be properly ordered (which is what happens for the master object file task above if there are no input files). + // Create the linker task. If we have no input files but decide to create the task anyway, then this task will rely on gate tasks to be properly ordered (which is what happens for the prelinked object file task above if there are no input files). if !linkerInputNodes.isEmpty || (components.contains("build") && scope.evaluate(BuiltinMacros.MERGE_LINKED_LIBRARIES)) { // Compute the output path. let output: Path diff --git a/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift index d4c2cd5f..bc5e5a7b 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift @@ -228,7 +228,7 @@ public class TaskProducerContext: StaleFileRemovalContext, BuildFileResolution public let ldLinkerSpec: LdLinkerSpec public let libtoolLinkerSpec: LibtoolLinkerSpec public let lipoSpec: LipoToolSpec - let masterObjectLinkSpec: CommandLineToolSpec + let prelinkedObjectLinkSpec: CommandLineToolSpec public let mkdirSpec: MkdirToolSpec let modulesVerifierSpec: ModulesVerifierToolSpec let clangModuleVerifierInputGeneratorSpec: ClangModuleVerifierInputGeneratorSpec @@ -354,7 +354,7 @@ public class TaskProducerContext: StaleFileRemovalContext, BuildFileResolution self.ldLinkerSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as LdLinkerSpec self.libtoolLinkerSpec = try! workspaceContext.core.specRegistry.getSpec(domain: domain) as LibtoolLinkerSpec self.lipoSpec = workspaceContext.core.specRegistry.getSpec("com.apple.xcode.linkers.lipo", domain: domain) as! LipoToolSpec - self.masterObjectLinkSpec = workspaceContext.core.specRegistry.getSpec("com.apple.build-tools.master-object-link", domain: domain) as! CommandLineToolSpec + self.prelinkedObjectLinkSpec = workspaceContext.core.specRegistry.getSpec(PrelinkedObjectLinkSpec.identifier, domain: domain) as! CommandLineToolSpec self.mkdirSpec = workspaceContext.core.specRegistry.getSpec("com.apple.tools.mkdir", domain: domain) as! MkdirToolSpec self.modulesVerifierSpec = workspaceContext.core.specRegistry.getSpec("com.apple.build-tools.modules-verifier", domain: domain) as! ModulesVerifierToolSpec self.clangModuleVerifierInputGeneratorSpec = workspaceContext.core.specRegistry.getSpec("com.apple.build-tools.module-verifier-input-generator", domain: domain) as! ClangModuleVerifierInputGeneratorSpec @@ -724,9 +724,9 @@ public class TaskProducerContext: StaleFileRemovalContext, BuildFileResolution return false } - // If this target is generating a master object file, then we assume it will produce a binary. - // FIXME: This is nasty. See SourcesTaskProducer.generateTasks() for handling of GENERATE_MASTER_OBJECT_FILE. - guard !scope.evaluate(BuiltinMacros.GENERATE_MASTER_OBJECT_FILE) else { + // If this target is generating a prelinked object file, then we assume it will produce a binary. + // FIXME: This is nasty. See SourcesTaskProducer.generateTasks() for handling of GENERATE_PRELINK_OBJECT_FILE. + guard !scope.evaluate(BuiltinMacros.GENERATE_PRELINK_OBJECT_FILE) else { return true } diff --git a/Sources/SwiftBuild/ProjectModel/BuildSettings.swift b/Sources/SwiftBuild/ProjectModel/BuildSettings.swift index 33e50e9f..3d3ff3c4 100644 --- a/Sources/SwiftBuild/ProjectModel/BuildSettings.swift +++ b/Sources/SwiftBuild/ProjectModel/BuildSettings.swift @@ -40,7 +40,7 @@ extension ProjectModel { case GENERATE_INFOPLIST_FILE case GCC_C_LANGUAGE_STANDARD case GCC_OPTIMIZATION_LEVEL - case GENERATE_MASTER_OBJECT_FILE + case GENERATE_PRELINK_OBJECT_FILE case INFOPLIST_FILE case IPHONEOS_DEPLOYMENT_TARGET case KEEP_PRIVATE_EXTERNS diff --git a/Tests/SWBTaskConstructionTests/MasterObjectFileTests.swift b/Tests/SWBTaskConstructionTests/PrelinkedObjectFileTests.swift similarity index 90% rename from Tests/SWBTaskConstructionTests/MasterObjectFileTests.swift rename to Tests/SWBTaskConstructionTests/PrelinkedObjectFileTests.swift index dea36b88..3c805622 100644 --- a/Tests/SWBTaskConstructionTests/MasterObjectFileTests.swift +++ b/Tests/SWBTaskConstructionTests/PrelinkedObjectFileTests.swift @@ -18,10 +18,10 @@ import SWBUtil import SWBProtocol @Suite -fileprivate struct MasterObjectFileTests: CoreBasedTests { - // Test interesting permutations of generating a master object file. +fileprivate struct PrelinkedObjectFileTests: CoreBasedTests { + // Test interesting permutations of generating a prelinked object file. @Test(.requireSDKs(.macOS)) - func masterObjectFileGeneration() async throws { + func prelinkedObjectFileGeneration() async throws { let core = try await getCore() let testProject = TestProject( "aProject", @@ -46,7 +46,7 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { TestBuildConfiguration( "Debug", buildSettings: [ - "GENERATE_MASTER_OBJECT_FILE": "YES", + "GENERATE_PRELINK_OBJECT_FILE": "YES", "WARNING_LDFLAGS": "-lWarningLibrary", "PRELINK_LIBS": "-lSomeLibrary -lAnotherLibrary", "PRELINK_FLAGS": "-exported_symbols_list Exports.exp", @@ -71,9 +71,9 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { results.checkTasks(.matchRuleType("RegisterExecutionPolicyException")) { _ in } results.checkTarget("AllLibraries") { target in - // There should be tasks to create the master object file and then the static library. - results.checkTask(.matchTarget(target), .matchRuleType("MasterObjectLink")) { task in - task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), "-exported_symbols_list", "Exports.exp", "-lWarningLibrary", "-lSomeLibrary", "-lAnotherLibrary", "-o", .equal("\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-master.o")]) + // There should be tasks to create the prelinked object file and then the static library. + results.checkTask(.matchTarget(target), .matchRuleType("PrelinkedObjectLink")) { task in + task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), "-exported_symbols_list", "Exports.exp", "-lWarningLibrary", "-lSomeLibrary", "-lAnotherLibrary", "-o", .equal("\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-prelink.o")]) } results.checkTask(.matchTarget(target), .matchRuleType("Libtool")) { task in task.checkCommandLineMatches([.suffix("libtool"), "-static", "-arch_only", "x86_64", "-D", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), .equal("-L\(SRCROOT)/build/Debug"), "-filelist", .equal("\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/x86_64/AllLibraries.LinkFileList"), "-dependency_info", "\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/x86_64/AllLibraries_libtool_dependency_info.dat", "-o", .equal("\(SRCROOT)/build/Debug/libAllLibraries.a")]) @@ -100,9 +100,9 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { results.checkTasks(.matchRuleType("RegisterExecutionPolicyException")) { _ in } results.checkTarget("AllLibraries") { target in - // There should be tasks to create the master object file and then the static library. - results.checkTask(.matchTarget(target), .matchRuleType("MasterObjectLink")) { task in - task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), "-exported_symbols_list", "Exports.exp", "-lWarningLibrary", "-lSomeLibrary", "-lAnotherLibrary", "-o", .equal("\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-master.o")]) + // There should be tasks to create the prelinked object file and then the static library. + results.checkTask(.matchTarget(target), .matchRuleType("PrelinkedObjectLink")) { task in + task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), "-exported_symbols_list", "Exports.exp", "-lWarningLibrary", "-lSomeLibrary", "-lAnotherLibrary", "-o", .equal("\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-prelink.o")]) } results.checkTask(.matchTarget(target), .matchRuleType("Libtool")) { task in task.checkCommandLineMatches([.suffix("libtool"), "-static", "-arch_only", "x86_64", "-D", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), .equal("-L\(SRCROOT)/build/Debug/BuiltProducts"), "-filelist", .equal("\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/x86_64/AllLibraries.LinkFileList"), "-dependency_info", "\(SRCROOT)/build/aProject.build/Debug/AllLibraries.build/Objects-normal/x86_64/AllLibraries_libtool_dependency_info.dat", "-o", "/tmp/aProject.dst/usr/local/lib/libAllLibraries.a"]) @@ -137,8 +137,8 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in } results.checkTarget("AllLibraries") { target in - // There should be tasks to create the master object file and then the static library. - results.checkNoTask(.matchTarget(target), .matchRuleType("MasterObjectLink")) + // There should be tasks to create the prelinked object file and then the static library. + results.checkNoTask(.matchTarget(target), .matchRuleType("PrelinkedObjectLink")) } // There should be no other tasks. @@ -153,9 +153,9 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { } @Test(.requireSDKs(.macOS, .iOS)) - func masterObjectFileGenerationVariant_macCatalyst() async throws { + func prelinkedObjectFileGenerationVariant_macCatalyst() async throws { let core = try await getCore() - // Test that a master object file gets generated even if the target contains no sources or libraries in its build phases. + // Test that a prelinked object file gets generated even if the target contains no sources or libraries in its build phases. let testProject = TestProject( "aProject", groupTree: TestGroup( @@ -179,7 +179,7 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { TestBuildConfiguration( "Debug", buildSettings: [ - "GENERATE_MASTER_OBJECT_FILE": "YES", + "GENERATE_PRELINK_OBJECT_FILE": "YES", ]), ], buildPhases: [ @@ -201,9 +201,9 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { results.checkTasks(.matchRuleType("RegisterExecutionPolicyException")) { _ in } results.checkTarget("AllLibraries") { target in - // There should be tasks to create the master object file and then the static library. - results.checkTask(.matchTarget(target), .matchRuleType("MasterObjectLink")) { task in - task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), "-o", .equal("\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-master.o")]) + // There should be tasks to create the prelinked object file and then the static library. + results.checkTask(.matchTarget(target), .matchRuleType("PrelinkedObjectLink")) { task in + task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), "-o", .equal("\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-prelink.o")]) } results.checkTask(.matchTarget(target), .matchRuleType("Libtool")) { task in task.checkCommandLineMatches([.suffix("libtool"), "-static", "-arch_only", "x86_64", "-D", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), .equal("-L\(SRCROOT)/build/Debug-maccatalyst"), "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-filelist", .equal("\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AllLibraries.build/Objects-normal/x86_64/AllLibraries.LinkFileList"), "-dependency_info", "\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AllLibraries.build/Objects-normal/x86_64/AllLibraries_libtool_dependency_info.dat", "-o", .equal("\(SRCROOT)/build/Debug-maccatalyst/libAllLibraries.a")]) @@ -222,9 +222,9 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { } @Test(.requireSDKs(.iOS)) - func masterObjectFileGenerationVariant_ios() async throws { + func prelinkedObjectFileGenerationVariant_ios() async throws { let core = try await getCore() - // Test that a master object file gets generated even if the target contains no sources or libraries in its build phases. + // Test that a prelinked object file gets generated even if the target contains no sources or libraries in its build phases. let testProject = TestProject( "aProject", groupTree: TestGroup( @@ -248,7 +248,7 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { TestBuildConfiguration( "Debug", buildSettings: [ - "GENERATE_MASTER_OBJECT_FILE": "YES", + "GENERATE_PRELINK_OBJECT_FILE": "YES", ]), ], buildPhases: [ @@ -270,9 +270,9 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { results.checkTasks(.matchRuleType("RegisterExecutionPolicyException")) { _ in } results.checkTarget("AllLibraries") { target in - // There should be tasks to create the master object file and then the static library. - results.checkTask(.matchTarget(target), .matchRuleType("MasterObjectLink")) { task in - task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "arm64", "-syslibroot", .equal(results.runDestinationSDK.path.str), "-o", .equal("\(SRCROOT)/build/aProject.build/Debug-iphoneos/AllLibraries.build/Objects-normal/libAllLibraries.a-arm64-master.o")]) + // There should be tasks to create the prelinked object file and then the static library. + results.checkTask(.matchTarget(target), .matchRuleType("PrelinkedObjectLink")) { task in + task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "arm64", "-syslibroot", .equal(results.runDestinationSDK.path.str), "-o", .equal("\(SRCROOT)/build/aProject.build/Debug-iphoneos/AllLibraries.build/Objects-normal/libAllLibraries.a-arm64-prelink.o")]) } results.checkTask(.matchTarget(target), .matchRuleType("Libtool")) { task in task.checkCommandLineMatches([.suffix("libtool"), "-static", "-arch_only", "arm64", "-D", "-syslibroot", .equal(results.runDestinationSDK.path.str), .equal("-L\(SRCROOT)/build/Debug-iphoneos"), "-filelist", .equal("\(SRCROOT)/build/aProject.build/Debug-iphoneos/AllLibraries.build/Objects-normal/arm64/AllLibraries.LinkFileList"), "-dependency_info", "\(SRCROOT)/build/aProject.build/Debug-iphoneos/AllLibraries.build/Objects-normal/arm64/AllLibraries_libtool_dependency_info.dat", "-o", .equal("\(SRCROOT)/build/Debug-iphoneos/libAllLibraries.a")]) @@ -291,7 +291,7 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { } @Test(.requireSDKs(.iOS)) - func masterObjectFileGenerationVariant_ios_simulator() async throws { + func prelinkedObjectFileGenerationVariant_ios_simulator() async throws { let core = try await getCore() let testProject = TestProject( "aProject", @@ -316,7 +316,7 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { TestBuildConfiguration( "Debug", buildSettings: [ - "GENERATE_MASTER_OBJECT_FILE": "YES", + "GENERATE_PRELINK_OBJECT_FILE": "YES", ]), ], buildPhases: [ @@ -338,9 +338,9 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { results.checkTasks(.matchRuleType("RegisterExecutionPolicyException")) { _ in } results.checkTarget("AllLibraries") { target in - // There should be tasks to create the master object file and then the static library. - results.checkTask(.matchTarget(target), .matchRuleType("MasterObjectLink")) { task in - task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(results.runDestinationSDK.path.str), "-o", .equal("\(SRCROOT)/build/aProject.build/Debug-iphonesimulator/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-master.o")]) + // There should be tasks to create the prelinked object file and then the static library. + results.checkTask(.matchTarget(target), .matchRuleType("PrelinkedObjectLink")) { task in + task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(results.runDestinationSDK.path.str), "-o", .equal("\(SRCROOT)/build/aProject.build/Debug-iphonesimulator/AllLibraries.build/Objects-normal/libAllLibraries.a-x86_64-prelink.o")]) } results.checkTask(.matchTarget(target), .matchRuleType("Libtool")) { task in task.checkCommandLineMatches([.suffix("libtool"), "-static", "-arch_only", "x86_64", "-D", "-syslibroot", .equal(results.runDestinationSDK.path.str), .equal("-L\(SRCROOT)/build/Debug-iphonesimulator"), "-filelist", .equal("\(SRCROOT)/build/aProject.build/Debug-iphonesimulator/AllLibraries.build/Objects-normal/x86_64/AllLibraries.LinkFileList"), "-dependency_info", "\(SRCROOT)/build/aProject.build/Debug-iphonesimulator/AllLibraries.build/Objects-normal/x86_64/AllLibraries_libtool_dependency_info.dat", "-o", .equal("\(SRCROOT)/build/Debug-iphonesimulator/libAllLibraries.a")]) diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index 570aed47..fec36d64 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -97,7 +97,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { "ALTERNATE_OWNER": "fooOwner", "ALTERNATE_GROUP": "", "ALTERNATE_MODE": "", - "GENERATE_MASTER_OBJECT_FILE": "YES", + "GENERATE_PRELINK_OBJECT_FILE": "YES", ]), ], targets: [ @@ -885,9 +885,9 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } results.checkNoTask(.matchTarget(target), .matchRuleType("Copy")) - // There should be one master object link task. - results.checkTask(.matchTarget(target), .matchRuleType("MasterObjectLink")) { task in - task.checkRuleInfo(["MasterObjectLink", "\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/AppTarget-x86_64-master.o"]) + // There should be one prelinked object link task. + results.checkTask(.matchTarget(target), .matchRuleType("PrelinkedObjectLink")) { task in + task.checkRuleInfo(["PrelinkedObjectLink", "\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/AppTarget-x86_64-prelink.o"]) let nonUniqueObjs = task.commandLineAsStrings.filter { $0.contains("NonUnique") } if nonUniqueObjs.count != 2 { #expect(nonUniqueObjs.count == 2) @@ -895,7 +895,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } #expect(nonUniqueObjs[0] != nonUniqueObjs[1]) - task.checkCommandLineMatches([StringPattern.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile-Matched-Excluded.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile-Matched-Included.o"), .equal(nonUniqueObjs[0]), .equal(nonUniqueObjs[1]), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile_MRR.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/Lex.yy.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/y.tab.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/Script-Output-Custom-SourceFile.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/Script-Output-Standard-SourceFile.o"), "-o", .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/AppTarget-x86_64-master.o")]) + task.checkCommandLineMatches([StringPattern.suffix("ld"), "-r", "-arch", "x86_64", "-syslibroot", .equal(core.loadSDK(.macOS).path.str), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile-Matched-Excluded.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile-Matched-Included.o"), .equal(nonUniqueObjs[0]), .equal(nonUniqueObjs[1]), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile_MRR.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/Lex.yy.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/y.tab.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/Script-Output-Custom-SourceFile.o"), .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/Script-Output-Standard-SourceFile.o"), "-o", .equal("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/AppTarget-x86_64-prelink.o")]) task.checkInputs([ .path("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/x86_64/SourceFile.o"), @@ -915,7 +915,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { .namePattern(.prefix("target-"))]) task.checkOutputs([ - .path("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/AppTarget-x86_64-master.o"),]) + .path("\(SRCROOT)/build/aProject.build/Release/AppTarget.build/Objects-normal/AppTarget-x86_64-prelink.o"),]) } From 056d2e30c57c3f8703a05f8b0ca91e7e3e4dddfc Mon Sep 17 00:00:00 2001 From: Michael Rawdon Date: Mon, 28 Apr 2025 16:14:11 -0700 Subject: [PATCH 24/30] Restore support for the llvm-bc (bitcode) field in the Swift file map. This is still used by, e.g., Swift LTO. rdar://150188689 --- .../SWBCore/SpecImplementations/Tools/SwiftCompiler.swift | 8 ++++++++ .../SwiftTaskConstructionTests.swift | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift index 5a448c46..2e616d51 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift @@ -3067,6 +3067,12 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi fileMapEntry.indexUnitOutputPath = indexObjectPath.str } } + let objectFilePrefix = objectFilePath.basenameWithoutSuffix + // The path to the bitcode file. This is used, for example, by LTO. + if compilationMode.compileSources { + let bitcodeFilePath = objectFileDir.join(objectFilePrefix + ".bc") + fileMapEntry.llvmBitcode = bitcodeFilePath.str + } return (objectFilePath, fileMapEntry) } @@ -3782,6 +3788,7 @@ struct SwiftOutputFileMap: Codable { struct Entry: Codable { var object: String? var indexUnitOutputPath: String? + var llvmBitcode: String? var remap: String? var diagnostics: String? var emitModuleDiagnostics: String? @@ -3795,6 +3802,7 @@ struct SwiftOutputFileMap: Codable { enum CodingKeys: String, CodingKey { case object case indexUnitOutputPath = "index-unit-output-path" + case llvmBitcode = "llvm-bc" case remap case diagnostics case emitModuleDiagnostics = "emit-module-diagnostics" diff --git a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift index 7959ab49..f68b8ef3 100644 --- a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift @@ -326,10 +326,11 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { #expect(fileDict["dependencies"]?.stringValue == "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/\(filename).d") #expect(fileDict["swift-dependencies"]?.stringValue == "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/\(filename).swiftdeps") #expect(fileDict["swiftmodule"]?.stringValue == "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/\(filename)~partial.swiftmodule") + #expect(fileDict["llvm-bc"]?.stringValue == "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/\(filename).bc") #expect(fileDict["const-values"]?.stringValue == "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/\(filename).swiftconstvalues") if swiftFeatures.has(.indexUnitOutputPathWithoutWarning) { #expect(fileDict["index-unit-output-path"]?.stringValue == "/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/\(filename).o") - #expect(fileDict.count == 7) + #expect(fileDict.count == 8) } else { #expect(fileDict.count == 6) } @@ -1265,9 +1266,11 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { } else { compileTask.checkCommandLineContains(["-lto=llvm-thin"]) } + compileTask.checkOutputs(contain: [.namePattern(.suffix("Bar.bc"))]) } results.checkTask(.matchTarget(target), .matchRuleType("Libtool")) { archiverTask in results.checkTaskFollows(archiverTask, .matchTarget(target), .matchRuleType("SwiftDriver Compilation")) + archiverTask.checkInputs(contain: [.namePattern(.suffix("Bar.bc"))]) } } results.checkTarget("CoreFoo") { target in @@ -1277,9 +1280,11 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { } else { compileTask.checkCommandLineContains(["-lto=llvm-thin"]) } + compileTask.checkOutputs(contain: [.namePattern(.suffix("Foo.bc"))]) } results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { linkerTask in results.checkTaskFollows(linkerTask, .matchTarget(target), .matchRuleType("SwiftDriver Compilation")) + linkerTask.checkInputs(contain: [.namePattern(.suffix("Foo.bc"))]) if ltoSetting == "YES_THIN" { linkerTask.checkCommandLineMatches([.anySequence, "-Xlinker", "-cache_path_lto", "-Xlinker", .suffix("/LTOCache"), .anySequence]) } From e97614b0b510c97f1fd6491280d6d81925a41e4b Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Tue, 29 Apr 2025 01:51:02 -0700 Subject: [PATCH 25/30] [CI] Add support for GitHub Actions (#446) * [CI] Add support for GitHub Actions * Update the license headers --- .github/workflows/pull_request.yml | 29 +++++++++++++++++++ .license_header_template | 11 +++++++ .licenseignore | 9 ++++++ Tests/SWBCoreTests/ProductTypesTests.swift | 11 +++++-- .../CommandLineTool/CommandLineTool/main.c | 12 ++++++++ .../Sources/CommandLineToolPackage/main.swift | 12 ++++++++ Utilities/swift-ci-perf-tests.sh | 13 ++++++++- 7 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/pull_request.yml create mode 100644 .license_header_template create mode 100644 .licenseignore diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 00000000..efc6d05e --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,29 @@ +name: Pull request + +on: + pull_request: + types: [opened, reopened, synchronize] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + tests: + name: Test + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + with: + linux_os_versions: '["noble", "jammy", "focal", "rhel-ubi9"]' + linux_pre_build_command: command -v apt >/dev/null 2>&1 && apt update && apt install -y libsqlite3-dev libncurses-dev || (command -v yum >/dev/null 2>&1 && yum update -y && yum install -y sqlite-devel ncurses-devel) + linux_build_command: 'swift build' + linux_swift_versions: '["nightly-main", "nightly-6.2"]' + windows_swift_versions: '["nightly-main"]' + windows_build_command: 'swift build' + soundness: + name: Soundness + uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main + with: + license_header_check_project_name: "Swift" + api_breakage_check_enabled: false + unacceptable_language_check_enabled: false + format_check_enabled: false diff --git a/.license_header_template b/.license_header_template new file mode 100644 index 00000000..52d6f278 --- /dev/null +++ b/.license_header_template @@ -0,0 +1,11 @@ +@@===----------------------------------------------------------------------===@@ +@@ +@@ This source file is part of the Swift open source project +@@ +@@ Copyright (c) YEARS Apple Inc. and the Swift project authors +@@ Licensed under Apache License v2.0 with Runtime Library Exception +@@ +@@ See http://swift.org/LICENSE.txt for license information +@@ See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +@@ +@@===----------------------------------------------------------------------===@@ diff --git a/.licenseignore b/.licenseignore new file mode 100644 index 00000000..21fbce89 --- /dev/null +++ b/.licenseignore @@ -0,0 +1,9 @@ +**/*.mlmodel +**/*.pbxproj +**/*.png +**/*.xcworkspacedata +**/Package.swift +.dir-locals.el +.editorconfig +CODEOWNERS +Package.swift diff --git a/Tests/SWBCoreTests/ProductTypesTests.swift b/Tests/SWBCoreTests/ProductTypesTests.swift index 3baeb0ef..5bc412bb 100644 --- a/Tests/SWBCoreTests/ProductTypesTests.swift +++ b/Tests/SWBCoreTests/ProductTypesTests.swift @@ -1,9 +1,14 @@ +//===----------------------------------------------------------------------===// // -// ProductTypesTests.swift -// SWBCoreTests +// This source file is part of the Swift open source project // -// Copyright © 2024 Apple Inc. All rights reserved. +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception // +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// import Testing diff --git a/Tests/SwiftBuildTests/TestData/CommandLineTool/CommandLineTool/main.c b/Tests/SwiftBuildTests/TestData/CommandLineTool/CommandLineTool/main.c index 33c14ce1..cdee1235 100644 --- a/Tests/SwiftBuildTests/TestData/CommandLineTool/CommandLineTool/main.c +++ b/Tests/SwiftBuildTests/TestData/CommandLineTool/CommandLineTool/main.c @@ -1,3 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + int main() { return 0; } diff --git a/Tests/SwiftBuildTests/TestData/CommandLineToolPackage/Sources/CommandLineToolPackage/main.swift b/Tests/SwiftBuildTests/TestData/CommandLineToolPackage/Sources/CommandLineToolPackage/main.swift index e69de29b..380508dc 100644 --- a/Tests/SwiftBuildTests/TestData/CommandLineToolPackage/Sources/CommandLineToolPackage/main.swift +++ b/Tests/SwiftBuildTests/TestData/CommandLineToolPackage/Sources/CommandLineToolPackage/main.swift @@ -0,0 +1,12 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + diff --git a/Utilities/swift-ci-perf-tests.sh b/Utilities/swift-ci-perf-tests.sh index dbef917e..f8787e78 100755 --- a/Utilities/swift-ci-perf-tests.sh +++ b/Utilities/swift-ci-perf-tests.sh @@ -1,4 +1,15 @@ -#!/usr/bin/env bash +#!/bin/bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift open source project +## +## Copyright (c) 2025 Apple Inc. and the Swift project authors +## Licensed under Apache License v2.0 with Runtime Library Exception +## +## See http://swift.org/LICENSE.txt for license information +## See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +## +##===----------------------------------------------------------------------===## set -euo pipefail From d42d61dbd650171a82892dd3a3fedff4574aa050 Mon Sep 17 00:00:00 2001 From: Ankit Aggarwal Date: Tue, 29 Apr 2025 06:56:41 -0700 Subject: [PATCH 26/30] Update CODEOWNERS --- CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 4ffcd609..96347c4f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,4 @@ -* @jakepetroules @mirza-garibovic @mhrawdon @neonichu @owenv +* @aciidgh @jakepetroules @mirza-garibovic @mhrawdon @neonichu @owenv *XCStrings* @matthewseaman @kulpreetchilana @jakepetroules @mirza-garibovic @mhrawdon @neonichu @owenv *StringCatalog* @matthewseaman @kulpreetchilana @jakepetroules @mirza-garibovic @mhrawdon @neonichu @owenv -*Preview* @jonathanpenn @jakepetroules @mirza-garibovic @mhrawdon @neonichu @owenv \ No newline at end of file +*Preview* @jonathanpenn @jakepetroules @mirza-garibovic @mhrawdon @neonichu @owenv From 392cca662cc242df280092151f5d46fad96a69cf Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Tue, 29 Apr 2025 14:04:29 -0700 Subject: [PATCH 27/30] Add missing license header to CMake filewq --- cmake/modules/SwiftBuildConfig.cmake.in | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cmake/modules/SwiftBuildConfig.cmake.in b/cmake/modules/SwiftBuildConfig.cmake.in index 74cb8f0f..b996ae36 100644 --- a/cmake/modules/SwiftBuildConfig.cmake.in +++ b/cmake/modules/SwiftBuildConfig.cmake.in @@ -1,3 +1,14 @@ +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift open source project +## +## Copyright (c) YEARS Apple Inc. and the Swift project authors +## Licensed under Apache License v2.0 with Runtime Library Exception +## +## See http://swift.org/LICENSE.txt for license information +## See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +## +##===----------------------------------------------------------------------===## if(NOT TARGET SwiftBuild::SwiftBuild) include(@SWIFTBUILD_EXPORTS_FILE@) endif() From 08e7bfeadc00349e55570d608a0ba925654cfca9 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Wed, 30 Apr 2025 09:10:35 -0700 Subject: [PATCH 28/30] Add automerge action for scheduled updates to release branch --- .github/workflows/automerge.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/automerge.yml diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 00000000..7d8af0d3 --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,17 @@ +name: Create PR to merge main into release branch +# In the first period after branching the release branch, we typically want to include many changes from `main` in the release branch. This workflow automatically creates a PR every Monday to merge main into the release branch. +# Later in the release cycle we should stop this practice to avoid landing risky changes by disabling this workflow. To do so, disable the workflow as described in https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/disabling-and-enabling-a-workflow +on: + schedule: + - cron: '0 9 * * MON' + workflow_dispatch: +jobs: + create_merge_pr: + name: Create PR to merge main into release branch + uses: swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml@main + with: + base_branch: release/6.2 + permissions: + contents: write + pull-requests: write + if: (github.event_name == 'schedule' && github.repository == 'swiftlang/swift-build') || (github.event_name != 'schedule') # Ensure that we don't run this on a schedule in a fork From e6ed315b32b666cf5f6f478439827f5187f2e697 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Tue, 29 Apr 2025 16:26:22 -0700 Subject: [PATCH 29/30] Remove blocking_sync usages from SWBLLBuildTests These just need simple synchronization; use a mutex instead. --- Tests/SWBLLBuildTests/LLBuildTests.swift | 113 +++++++++++++---------- 1 file changed, 65 insertions(+), 48 deletions(-) diff --git a/Tests/SWBLLBuildTests/LLBuildTests.swift b/Tests/SWBLLBuildTests/LLBuildTests.swift index 19d3186f..6f50c9d7 100644 --- a/Tests/SWBLLBuildTests/LLBuildTests.swift +++ b/Tests/SWBLLBuildTests/LLBuildTests.swift @@ -17,137 +17,154 @@ import SWBUtil import struct SWBLLBuild.Diagnostic import Foundation +import Synchronization fileprivate class LoggingDelegate: BuildSystemDelegate { - let queue = SWBQueue(label: "LLBuildTests.LoggingDelegate.queue", qos: UserDefaults.defaultRequestQoS) var buildSystem: BuildSystem? = nil let fs: (any SWBLLBuild.FileSystem)? let fsProxy: any FSProxy - var log: [String] = [] - var errors: [String] = [] + private struct Output: Sendable { + var log: [String] = [] + var errors: [String] = [] + } + private let output = SWBMutex(.init()) let ignoreStatusChanges: Bool + var log: [String] { + output.withLock { $0.log } + } + + var errors: [String] { + output.withLock { $0.errors } + } + init(fs: any FSProxy, ignoreStatusChanges: Bool = false) { self.fs = SWBLLBuild.FileSystemImpl(fs) self.fsProxy = fs self.ignoreStatusChanges = ignoreStatusChanges } + func append(log: String) { + output.withLock { output in + output.log.append(log) + } + } + func lookupTool(_ name: String) -> (any Tool)? { return nil } func hadCommandFailure() { - queue.blocking_sync { - self.log.append("had-command-failure") + output.withLock { output in + output.log.append("had-command-failure") } buildSystem?.cancel() } func handleDiagnostic(_ diagnostic: Diagnostic) { - queue.blocking_sync { - self.log.append("\(diagnostic.kind): \(diagnostic.message)") - self.errors.append("\(diagnostic.kind): \(diagnostic.message)") + output.withLock { output in + output.log.append("\(diagnostic.kind): \(diagnostic.message)") + output.errors.append("\(diagnostic.kind): \(diagnostic.message)") } } func commandStatusChanged(_ command: Command, kind: CommandStatusKind) { if !ignoreStatusChanges { - queue.blocking_sync { - self.log.append("command-status-changed: \(command.name), to: \(kind)") + output.withLock { output in + output.log.append("command-status-changed: \(command.name), to: \(kind)") } } } func commandPreparing(_ command: Command) { - queue.blocking_sync { - self.log.append("command-preparing: \(command.name)") + output.withLock { output in + output.log.append("command-preparing: \(command.name)") } } func commandStarted(_ command: Command) { - queue.blocking_sync { - self.log.append("command-started: \(command.name)") + output.withLock { output in + output.log.append("command-started: \(command.name)") } } func shouldCommandStart(_ command: Command) -> Bool { - queue.blocking_sync { - self.log.append("should-command-start: \(command.name)") + output.withLock { output in + output.log.append("should-command-start: \(command.name)") } return true } func commandFinished(_ command: Command, result: CommandResult) { - queue.blocking_sync { - self.log.append("command-finished: \(command.name)") + output.withLock { output in + output.log.append("command-finished: \(command.name)") } } func commandFoundDiscoveredDependency(_ command: Command, path: String, kind: DiscoveredDependencyKind) { - queue.blocking_sync { - self.log.append("command-found-discovered-dependency: \(path) \(kind)") + output.withLock { output in + output.log.append("command-found-discovered-dependency: \(path) \(kind)") } } func commandHadError(_ command: Command, message: String) { - queue.blocking_sync { - self.log.append("command-had-error: \(command.name): \(message)") - self.errors.append("command-had-error: \(command.name): \(message)") + output.withLock { output in + output.log.append("command-had-error: \(command.name): \(message)") + output.errors.append("command-had-error: \(command.name): \(message)") } } func commandHadNote(_ command: Command, message: String) { - queue.blocking_sync { - self.log.append("command-had-note: \(command.name): \(message)") + output.withLock { output in + output.log.append("command-had-note: \(command.name): \(message)") } } func commandHadWarning(_ command: Command, message: String) { - queue.blocking_sync { - self.log.append("command-had-warning: \(command.name): \(message)") + output.withLock { output in + output.log.append("command-had-warning: \(command.name): \(message)") } } func commandProcessStarted(_ command: Command, process: ProcessHandle) { - queue.blocking_sync { - self.log.append("command-process-started: \(command.name) -- \(command.description)") + output.withLock { output in + output.log.append("command-process-started: \(command.name) -- \(command.description)") } } func commandProcessHadError(_ command: Command, process: ProcessHandle, message: String) { - queue.blocking_sync { - self.log.append("command-process-error: \(message)") + output.withLock { output in + output.log.append("command-process-error: \(message)") } } func commandProcessHadOutput(_ command: Command, process: ProcessHandle, data: [UInt8]) { - queue.blocking_sync { - self.log.append("command-process-output: \(command.name): \(ByteString(data).bytes.asReadableString().debugDescription)") + output.withLock { output in + output.log.append("command-process-output: \(command.name): \(ByteString(data).bytes.asReadableString().debugDescription)") } } func commandProcessFinished(_ command: Command, process: ProcessHandle, result: CommandExtendedResult) { - queue.blocking_sync { - self.log.append("command-process-finished: \(command.name)") + output.withLock { output in + output.log.append("command-process-finished: \(command.name)") } } func determinedRuleNeedsToRun(_ rule: BuildKey, reason: RuleRunReason, inputRule: BuildKey?) { - queue.blocking_sync { - self.log.append("determined-rule-needs-to-run: \(rule.description)") + output.withLock { output in + output.log.append("determined-rule-needs-to-run: \(rule.description)") } } func cycleDetected(rules: [BuildKey]) { - queue.blocking_sync { - self.log.append("cycle-detected: \(rules.map{ $0.key })") + output.withLock { output in + output.log.append("cycle-detected: \(rules.map{ $0.key })") } } func commandCannotBuildOutputDueToMissingInputs(_ command: Command, output: BuildKey, inputs: [BuildKey]) { - queue.blocking_sync { + self.output.withLock { outputBox in let msg = "commandCannotBuildOutputDueToMissingInputs: \(command.name) \(output.key) \(inputs.map { $0.key })" - self.log.append(msg) - self.errors.append(msg) + outputBox.log.append(msg) + outputBox.errors.append(msg) } } func cannotBuildNodeDueToMultipleProducers(output: BuildKey, commands: [Command]) { - queue.blocking_sync { + self.output.withLock { outputBox in let msg = "cannotBuildNodeDueToMultipleProducers: \(output.key) \(commands.map { $0.name })" - self.log.append(msg) - self.errors.append(msg) + outputBox.log.append(msg) + outputBox.errors.append(msg) } } func shouldResolveCycle(rules: [BuildKey], candidate: BuildKey, action: CycleAction) -> Bool { - queue.blocking_sync { - self.log.append("should-resolve-cycle: \(rules.map{ $0.key })") + output.withLock { output in + output.log.append("should-resolve-cycle: \(rules.map{ $0.key })") } return false; } @@ -521,7 +538,7 @@ fileprivate class LoggingDelegate: BuildSystemDelegate { } func execute(_ command: Command, _ commandInterface: BuildSystemCommandInterface) -> Bool { - delegate.log.append("write-command: execute") + delegate.append(log: "write-command: execute") do { try delegate.fsProxy.write(Static.outputPath, contents: []) return true From 276a25a6b5d6e008884db710c5bf95b0ff844b0a Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Tue, 29 Apr 2025 16:26:22 -0700 Subject: [PATCH 30/30] Avoid blocking a Swift Task in the read() syscall Add a DispatchIO-based helper which returns the data asynchronously. --- .../ServiceHostConnection.swift | 11 ++++++---- Sources/SWBUtil/Dispatch+Async.swift | 20 ++++++++++++++++++- Sources/SWBUtil/SWBDispatch.swift | 15 +++++++++++++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Sources/SWBServiceCore/ServiceHostConnection.swift b/Sources/SWBServiceCore/ServiceHostConnection.swift index a3af56e5..59d1a172 100644 --- a/Sources/SWBServiceCore/ServiceHostConnection.swift +++ b/Sources/SWBServiceCore/ServiceHostConnection.swift @@ -148,10 +148,13 @@ final class ServiceHostConnection: @unchecked Sendable { #endif // Read data. - let result = read(self.inputFD.rawValue, tmp.baseAddress, numericCast(tmpBufferSize)) - if result < 0 { - if errno == EINTR { continue } - error = ServiceHostIOError(message: "read from client failed", cause: SWBUtil.POSIXError(errno, context: "read")) + let result: Int + do { + let buf = try await DispatchFD(fileDescriptor: self.inputFD).readChunk(upToLength: tmpBufferSize) + result = buf.count + buf.copyBytes(to: tmp) + } catch let readError { + error = ServiceHostIOError(message: "read from client failed", cause: readError) break } if result == 0 { diff --git a/Sources/SWBUtil/Dispatch+Async.swift b/Sources/SWBUtil/Dispatch+Async.swift index cde7d4c1..bf70a86d 100644 --- a/Sources/SWBUtil/Dispatch+Async.swift +++ b/Sources/SWBUtil/Dispatch+Async.swift @@ -13,7 +13,7 @@ // This file contains helpers used to bridge GCD and Swift Concurrency. // In the long term, these ideally all go away. -private import Foundation +import Foundation /// Runs an async function and synchronously waits for the response. /// - warning: This function is extremely dangerous because it blocks the calling thread and may lead to deadlock, and should only be used as a temporary transitional aid. @@ -41,6 +41,24 @@ public func runAsyncAndBlock(_ block: @Sendable @escaping () asy return try result.value!.get() } +extension DispatchFD { + public func readChunk(upToLength maxLength: Int) async throws -> SWBDispatchData { + return try await withCheckedThrowingContinuation { continuation in + SWBDispatchIO.read( + fromFileDescriptor: self, + maxLength: maxLength, + runningHandlerOn: .global() + ) { data, error in + if error != 0 { + continuation.resume(throwing: POSIXError(error)) + return + } + continuation.resume(returning: data) + } + } + } +} + extension AsyncThrowingStream where Element == UInt8, Failure == any Error { /// Returns an async stream which reads bytes from the specified file descriptor. Unlike `FileHandle.bytes`, it does not block the caller. @available(macOS, deprecated: 15.0, message: "Use the AsyncSequence-returning overload.") diff --git a/Sources/SWBUtil/SWBDispatch.swift b/Sources/SWBUtil/SWBDispatch.swift index 089bd2e9..4845461f 100644 --- a/Sources/SWBUtil/SWBDispatch.swift +++ b/Sources/SWBUtil/SWBDispatch.swift @@ -15,7 +15,7 @@ private import Dispatch public import SWBLibc -import Foundation +public import Foundation #if canImport(System) public import System @@ -123,6 +123,12 @@ extension SWBDispatchData: RandomAccessCollection { } } +extension SWBDispatchData: DataProtocol { + public var regions: DispatchData.Regions { + dispatchData.regions + } +} + /// Thin wrapper for `DispatchSemaphore` to isolate it from the rest of the codebase and help migration away from it. internal final class SWBDispatchSemaphore: Sendable { private let semaphore: DispatchSemaphore @@ -183,6 +189,13 @@ public final class SWBDispatchIO: Sendable { io = DispatchIO(type: .stream, fileDescriptor: numericCast(fileDescriptor), queue: queue.queue, cleanupHandler: cleanupHandler) } + public static func read(fromFileDescriptor fileDescriptor: DispatchFD, maxLength: Int, runningHandlerOn queue: SWBQueue, handler: @escaping (SWBDispatchData, Int32) -> Void) { + // Most of the dispatch APIs take a parameter called "fileDescriptor". On Windows (except makeReadSource and makeWriteSource) it is actually a HANDLE, so convert it accordingly. + DispatchIO.read(fromFileDescriptor: numericCast(fileDescriptor.rawValue), maxLength: maxLength, runningHandlerOn: queue.queue) { data, error in + handler(SWBDispatchData(data), error) + } + } + public static func stream(fileDescriptor: DispatchFD, queue: SWBQueue, cleanupHandler: @escaping (Int32) -> Void) -> SWBDispatchIO { // Most of the dispatch APIs take a parameter called "fileDescriptor". On Windows (except makeReadSource and makeWriteSource) it is actually a HANDLE, so convert it accordingly. SWBDispatchIO(fileDescriptor: numericCast(fileDescriptor.rawValue), queue: queue, cleanupHandler: cleanupHandler)