diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1d8c056c..8fa3e307 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,4 +2,4 @@ _[Put a one line description of your change into the PR title, please be specifi _[Explain the context, and why you're making that change. What is the problem you're trying to solve.]_ -_[Tests can be run by commenting `@swift-ci` test on the pull request, for more information see [this](https://github.com/swiftlang/swift-build/blob/main/README.md)]_ +_[Tests can be run by commenting `@swift-ci test` on the pull request, for more information see [this](https://github.com/swiftlang/swift-build/blob/main/README.md)]_ diff --git a/Package.swift b/Package.swift index ad2569d2..be86c92b 100644 --- a/Package.swift +++ b/Package.swift @@ -31,16 +31,20 @@ func swiftSettings(languageMode: SwiftLanguageMode) -> [SwiftSetting] { .enableUpcomingFeature("ConciseMagicFile"), .enableUpcomingFeature("DeprecateApplicationMain"), .enableUpcomingFeature("DisableOutwardActorInference"), + //.enableUpcomingFeature("DynamicActorIsolation"), .enableUpcomingFeature("ForwardTrailingClosures"), + .enableUpcomingFeature("GlobalActorIsolatedTypesUsability"), .enableUpcomingFeature("GlobalConcurrency"), .enableUpcomingFeature("ImplicitOpenExistentials"), .enableUpcomingFeature("ImportObjcForwardDeclarations"), .enableUpcomingFeature("InferSendableFromCaptures"), .enableUpcomingFeature("IsolatedDefaultValues"), + .enableUpcomingFeature("NonfrozenEnumExhaustivity"), //.enableUpcomingFeature("RegionBasedIsolation"), // rdar://137809703 // Future Swift features .enableUpcomingFeature("ExistentialAny"), + .enableUpcomingFeature("MemberImportVisibility"), .enableUpcomingFeature("InternalImportsByDefault"), .swiftLanguageMode(.v5), @@ -51,6 +55,7 @@ func swiftSettings(languageMode: SwiftLanguageMode) -> [SwiftSetting] { return [ // Future Swift features .enableUpcomingFeature("ExistentialAny"), + .enableUpcomingFeature("MemberImportVisibility"), .enableUpcomingFeature("InternalImportsByDefault"), .swiftLanguageMode(.v6), @@ -195,7 +200,6 @@ let package = Package( "SWBCSupport", "SWBLibc", .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "Crypto", package: "swift-crypto", condition: .when(platforms: [.linux, .openbsd, .android])), .product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .android, .windows])), ], exclude: ["CMakeLists.txt"], @@ -232,7 +236,14 @@ let package = Package( swiftSettings: swiftSettings(languageMode: .v6)), .target( name: "SWBUniversalPlatform", - dependencies: ["SWBCore", "SWBMacro", "SWBUtil"], + dependencies: [ + "SWBCore", + "SWBMacro", + "SWBUtil", + "SWBTaskConstruction", + "SWBTaskExecution", + .product(name: "ArgumentParser", package: "swift-argument-parser"), + ], exclude: ["CMakeLists.txt"], resources: [.process("Specs")], swiftSettings: swiftSettings(languageMode: .v6)), @@ -427,7 +438,6 @@ for target in package.targets { // `SWIFTCI_USE_LOCAL_DEPS` configures if dependencies are locally available to build if useLocalDependencies { package.dependencies += [ - .package(path: "../swift-crypto"), .package(path: "../swift-driver"), .package(path: "../swift-system"), .package(path: "../swift-argument-parser"), @@ -437,7 +447,6 @@ if useLocalDependencies { } } else { package.dependencies += [ - .package(url: "https://github.com/apple/swift-crypto.git", "2.0.0"..<"4.0.0"), .package(url: "https://github.com/swiftlang/swift-driver.git", branch: "release/6.2"), .package(url: "https://github.com/apple/swift-system.git", .upToNextMajor(from: "1.4.1")), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.3"), diff --git a/Plugins/cmake-smoke-test/cmake-smoke-test.swift b/Plugins/cmake-smoke-test/cmake-smoke-test.swift index 7c59f0fc..4cd00782 100644 --- a/Plugins/cmake-smoke-test/cmake-smoke-test.swift +++ b/Plugins/cmake-smoke-test/cmake-smoke-test.swift @@ -41,12 +41,6 @@ struct CMakeSmokeTest: CommandPlugin { let swiftSystemURL = try findSiblingRepository("swift-system", swiftBuildURL: swiftBuildURL) let swiftSystemBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-system") - let swiftAsn1URL = try findSiblingRepository("swift-asn1", swiftBuildURL: swiftBuildURL) - let swiftAsn1BuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-asn1") - - let swiftCryptoURL = try findSiblingRepository("swift-crypto", swiftBuildURL: swiftBuildURL) - let swiftCryptoBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-crypto") - let llbuildURL = try findSiblingRepository("llbuild", swiftBuildURL: swiftBuildURL) let llbuildBuildURL = context.pluginWorkDirectoryURL.appending(component: "llbuild") @@ -56,7 +50,7 @@ struct CMakeSmokeTest: CommandPlugin { let swiftDriverURL = try findSiblingRepository("swift-driver", swiftBuildURL: swiftBuildURL) let swiftDriverBuildURL = context.pluginWorkDirectoryURL.appending(component: "swift-driver") - for url in [swiftToolsSupportCoreBuildURL, swiftAsn1BuildURL, swiftCryptoBuildURL, swiftSystemBuildURL, llbuildBuildURL, swiftArgumentParserBuildURL, swiftDriverBuildURL, swiftBuildBuildURL] { + for url in [swiftToolsSupportCoreBuildURL, swiftSystemBuildURL, llbuildBuildURL, swiftArgumentParserBuildURL, swiftDriverBuildURL, swiftBuildBuildURL] { try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) } @@ -69,8 +63,6 @@ struct CMakeSmokeTest: CommandPlugin { "-DArgumentParser_DIR=\(swiftArgumentParserBuildURL.appending(components: "cmake", "modules").path())", "-DLLBuild_DIR=\(llbuildBuildURL.appending(components: "cmake", "modules").path())", "-DTSC_DIR=\(swiftToolsSupportCoreBuildURL.appending(components: "cmake", "modules").path())", - "-DSwiftASN1_DIR=\(swiftAsn1BuildURL.appending(components: "cmake", "modules").path())", - "-DSwiftCrypto_DIR=\(swiftCryptoBuildURL.appending(components: "cmake", "modules").path())", "-DSwiftDriver_DIR=\(swiftDriverBuildURL.appending(components: "cmake", "modules").path())", "-DSwiftSystem_DIR=\(swiftSystemBuildURL.appending(components: "cmake", "modules").path())" ] @@ -87,18 +79,6 @@ struct CMakeSmokeTest: CommandPlugin { try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftToolsSupportCoreBuildURL) print("Built swift-tools-support-core") - if hostOS != .macOS && hostOS != .windows { - print("Building swift-asn1") - try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftAsn1URL.path()], workingDirectory: swiftAsn1BuildURL) - try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftAsn1BuildURL) - print("Built swift-asn1") - - print("Building swift-crypto") - try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftCryptoURL.path()], workingDirectory: swiftCryptoBuildURL) - try await Process.checkNonZeroExit(url: ninjaURL, arguments: [], workingDirectory: swiftCryptoBuildURL) - print("Built swift-crypto") - } - if hostOS != .macOS { print("Building swift-system") try await Process.checkNonZeroExit(url: cmakeURL, arguments: sharedCMakeArgs + [swiftSystemURL.path()], workingDirectory: swiftSystemBuildURL) diff --git a/Sources/SWBApplePlatform/ActoolInputFileGroupingStrategy.swift b/Sources/SWBApplePlatform/ActoolInputFileGroupingStrategy.swift index dede8866..97410e4c 100644 --- a/Sources/SWBApplePlatform/ActoolInputFileGroupingStrategy.swift +++ b/Sources/SWBApplePlatform/ActoolInputFileGroupingStrategy.swift @@ -12,6 +12,7 @@ public import SWBCore import SWBUtil +import Foundation /// A grouping strategy that groups all asset catalogs and all strings files that match sticker packs inside those asset catalogs. @_spi(Testing) public final class ActoolInputFileGroupingStrategy: InputFileGroupingStrategy { diff --git a/Sources/SWBApplePlatform/AppIntentsMetadataTaskProducer.swift b/Sources/SWBApplePlatform/AppIntentsMetadataTaskProducer.swift index 937ecc1a..cf8b9a03 100644 --- a/Sources/SWBApplePlatform/AppIntentsMetadataTaskProducer.swift +++ b/Sources/SWBApplePlatform/AppIntentsMetadataTaskProducer.swift @@ -13,6 +13,7 @@ import SWBCore import SWBUtil import SWBTaskConstruction +import SWBMacro final class AppIntentsMetadataTaskProducer: PhasedTaskProducer, TaskProducer { diff --git a/Sources/SWBApplePlatform/CoreDataCompiler.swift b/Sources/SWBApplePlatform/CoreDataCompiler.swift index af46c91d..1a324cf8 100644 --- a/Sources/SWBApplePlatform/CoreDataCompiler.swift +++ b/Sources/SWBApplePlatform/CoreDataCompiler.swift @@ -12,6 +12,7 @@ import SWBUtil public import SWBCore +import SWBMacro public final class CoreDataModelCompilerSpec : GenericCompilerSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.compilers.model.coredata" diff --git a/Sources/SWBApplePlatform/CoreMLCompiler.swift b/Sources/SWBApplePlatform/CoreMLCompiler.swift index 3f9a37bd..dfa14648 100644 --- a/Sources/SWBApplePlatform/CoreMLCompiler.swift +++ b/Sources/SWBApplePlatform/CoreMLCompiler.swift @@ -13,6 +13,7 @@ public import SWBUtil public import SWBCore public import SWBMacro +import SWBProtocol public struct DiscoveredCoreMLToolSpecInfo: DiscoveredCommandLineToolSpecInfo { public let toolPath: Path @@ -151,7 +152,7 @@ public final class CoreMLCompilerSpec : GenericCompilerSpec, SpecIdentifierType, // When the build setting is empty or is set to Automatic, then use an appropriate string based on the predominant source code language for the target. if languageSettingValue.isEmpty || languageSettingValue == "Automatic" { // Note that it would be pretty weird here to not have a configured target, or to have a target which is not a StandardTarget. - let predominantSourceCodeLanguage = (cbc.producer.configuredTarget?.target as? StandardTarget)?.predominantSourceCodeLanguage ?? .undefined + let predominantSourceCodeLanguage = (cbc.producer.configuredTarget?.target as? SWBCore.StandardTarget)?.predominantSourceCodeLanguage ?? .undefined switch predominantSourceCodeLanguage { case .swift: codegenLanguage = "Swift" @@ -289,7 +290,7 @@ public final class CoreMLCompilerSpec : GenericCompilerSpec, SpecIdentifierType, } guard - let target = cbc.producer.configuredTarget?.target as? BuildPhaseTarget, + let target = cbc.producer.configuredTarget?.target as? SWBCore.BuildPhaseTarget, let outputPath = headerOutputPath, target.headersBuildPhase != nil else { continue } diff --git a/Sources/SWBApplePlatform/DevelopmentAssetsTaskProducer.swift b/Sources/SWBApplePlatform/DevelopmentAssetsTaskProducer.swift index 6e0b6299..1dffb25a 100644 --- a/Sources/SWBApplePlatform/DevelopmentAssetsTaskProducer.swift +++ b/Sources/SWBApplePlatform/DevelopmentAssetsTaskProducer.swift @@ -13,6 +13,7 @@ import SWBCore import SWBUtil import SWBTaskConstruction +import SWBMacro final class DevelopmentAssetsTaskProducer: StandardTaskProducer, TaskProducer { func generateTasks() async -> [any PlannedTask] { diff --git a/Sources/SWBApplePlatform/InstrumentsPackageBuilderSpec.swift b/Sources/SWBApplePlatform/InstrumentsPackageBuilderSpec.swift index fc4fd231..cc0d38c9 100644 --- a/Sources/SWBApplePlatform/InstrumentsPackageBuilderSpec.swift +++ b/Sources/SWBApplePlatform/InstrumentsPackageBuilderSpec.swift @@ -12,6 +12,7 @@ import SWBUtil public import SWBCore +import SWBMacro public final class InstrumentsPackageBuilderSpec: GenericCompilerSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.compilers.instruments-package-builder" diff --git a/Sources/SWBApplePlatform/IntentsCompiler.swift b/Sources/SWBApplePlatform/IntentsCompiler.swift index 2a7564e6..e31cf5a4 100644 --- a/Sources/SWBApplePlatform/IntentsCompiler.swift +++ b/Sources/SWBApplePlatform/IntentsCompiler.swift @@ -12,6 +12,8 @@ import SWBUtil public import SWBCore +import SWBProtocol +import SWBMacro /// Payload information for Intents tasks. fileprivate struct IntentsTaskPayload: TaskPayload, Encodable { @@ -122,7 +124,7 @@ public final class IntentsCompilerSpec : GenericCompilerSpec, SpecIdentifierType let outputDir = cbc.scope.evaluate(BuiltinMacros.DERIVED_FILE_DIR).join("IntentDefinitionGenerated").join(modelName).normalize() guard - let target = cbc.producer.configuredTarget?.target as? BuildPhaseTarget, + let target = cbc.producer.configuredTarget?.target as? SWBCore.BuildPhaseTarget, target.sourcesBuildPhase != nil, let intentsCodegenVisibility = input.intentsCodegenVisibility else { return } @@ -136,7 +138,7 @@ public final class IntentsCompilerSpec : GenericCompilerSpec, SpecIdentifierType // When the build setting is empty or is set to Automatic, then use an appropriate string based on the predominant source code language for the target. if languageSettingValue.isEmpty || languageSettingValue == "Automatic" { // Note that it would be pretty weird here to not have a configured target, or to have a target which is not a StandardTarget. - let predominantSourceCodeLanguage = (cbc.producer.configuredTarget?.target as? StandardTarget)?.predominantSourceCodeLanguage ?? .undefined + let predominantSourceCodeLanguage = (cbc.producer.configuredTarget?.target as? SWBCore.StandardTarget)?.predominantSourceCodeLanguage ?? .undefined switch predominantSourceCodeLanguage { case .swift: codegenLanguage = "Swift" @@ -236,7 +238,7 @@ public final class IntentsCompilerSpec : GenericCompilerSpec, SpecIdentifierType } guard - let target = cbc.producer.configuredTarget?.target as? BuildPhaseTarget, + let target = cbc.producer.configuredTarget?.target as? SWBCore.BuildPhaseTarget, let outputPath = headerOutputPath, target.headersBuildPhase != nil else { continue } diff --git a/Sources/SWBApplePlatform/MiGCompiler.swift b/Sources/SWBApplePlatform/MiGCompiler.swift index 25f07a88..1f9c9ceb 100644 --- a/Sources/SWBApplePlatform/MiGCompiler.swift +++ b/Sources/SWBApplePlatform/MiGCompiler.swift @@ -13,6 +13,7 @@ public import SWBUtil public import SWBCore public import SWBMacro +import SWBProtocol public struct DiscoveredMiGToolSpecInfo: DiscoveredCommandLineToolSpecInfo { public let toolPath: Path diff --git a/Sources/SWBApplePlatform/Plugin.swift b/Sources/SWBApplePlatform/Plugin.swift index 60ade7a3..50ae32d4 100644 --- a/Sources/SWBApplePlatform/Plugin.swift +++ b/Sources/SWBApplePlatform/Plugin.swift @@ -18,6 +18,7 @@ import Foundation import SWBTaskConstruction @PluginExtensionSystemActor public func initializePlugin(_ manager: PluginManager) { + manager.register(AppleDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(ApplePlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(ActoolInputFileGroupingStrategyExtension(), type: InputFileGroupingStrategyExtensionPoint.self) manager.register(ImageScaleFactorsInputFileGroupingStrategyExtension(), type: InputFileGroupingStrategyExtensionPoint.self) @@ -29,6 +30,12 @@ import SWBTaskConstruction manager.register(AppleSettingsBuilderExtension(), type: SettingsBuilderExtensionPoint.self) } +struct AppleDeveloperDirectoryExtension: DeveloperDirectoryExtension { + func fallbackDeveloperDirectory(hostOperatingSystem: OperatingSystem) async throws -> Path? { + try await hostOperatingSystem == .macOS ? Xcode.getActiveDeveloperDirectoryPath() : nil + } +} + struct TaskProducersExtension: TaskProducerExtension { func createPreSetupTaskProducers(_ context: TaskProducerContext) -> [any TaskProducer] { @@ -148,6 +155,10 @@ struct ActoolInputFileGroupingStrategyExtension: InputFileGroupingStrategyExtens } return ["actool": Factory()] } + + func fileTypesCompilingToSwiftSources() -> [String] { + return ["folder.abstractassetcatalog"] + } } struct ImageScaleFactorsInputFileGroupingStrategyExtension: InputFileGroupingStrategyExtension { @@ -159,6 +170,10 @@ struct ImageScaleFactorsInputFileGroupingStrategyExtension: InputFileGroupingStr } return ["image-scale-factors": Factory()] } + + func fileTypesCompilingToSwiftSources() -> [String] { + return [] + } } struct LocalizationInputFileGroupingStrategyExtension: InputFileGroupingStrategyExtension { @@ -170,6 +185,10 @@ struct LocalizationInputFileGroupingStrategyExtension: InputFileGroupingStrategy } return ["region": Factory()] } + + func fileTypesCompilingToSwiftSources() -> [String] { + return [] + } } struct XCStringsInputFileGroupingStrategyExtension: InputFileGroupingStrategyExtension { @@ -181,6 +200,10 @@ struct XCStringsInputFileGroupingStrategyExtension: InputFileGroupingStrategyExt } return ["xcstrings": Factory()] } + + func fileTypesCompilingToSwiftSources() -> [String] { + return [] + } } struct ApplePlatformInfoExtension: PlatformInfoExtension { diff --git a/Sources/SWBApplePlatform/RealityAssetsCompilerSpec.swift b/Sources/SWBApplePlatform/RealityAssetsCompilerSpec.swift index 54bdd6ad..e41cd491 100644 --- a/Sources/SWBApplePlatform/RealityAssetsCompilerSpec.swift +++ b/Sources/SWBApplePlatform/RealityAssetsCompilerSpec.swift @@ -13,6 +13,7 @@ import Foundation package import SWBCore import SWBUtil +import SWBMacro //--------------------- // diff --git a/Sources/SWBApplePlatform/ResMergerLinkerSpec.swift b/Sources/SWBApplePlatform/ResMergerLinkerSpec.swift index 0e2beae6..1380e2cd 100644 --- a/Sources/SWBApplePlatform/ResMergerLinkerSpec.swift +++ b/Sources/SWBApplePlatform/ResMergerLinkerSpec.swift @@ -12,6 +12,7 @@ import SWBUtil public import SWBCore +import SWBMacro public final class ResMergerLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.pbx.linkers.resmerger" diff --git a/Sources/SWBApplePlatform/Specs/Darwin Package Types.xcspec b/Sources/SWBApplePlatform/Specs/Darwin Package Types.xcspec index dc43c009..2f6e800c 100644 --- a/Sources/SWBApplePlatform/Specs/Darwin Package Types.xcspec +++ b/Sources/SWBApplePlatform/Specs/Darwin Package Types.xcspec @@ -58,7 +58,6 @@ Description = "OCUnit Test Bundle"; DefaultBuildSettings = { WRAPPER_SUFFIX = "octest"; - ENABLE_BITCODE = NO; }; ProductReference = { FileType = wrapper.cfbundle; diff --git a/Sources/SWBApplePlatform/Specs/Darwin Product Types.xcspec b/Sources/SWBApplePlatform/Specs/Darwin Product Types.xcspec index 5b52c4b6..e1bc5a17 100644 --- a/Sources/SWBApplePlatform/Specs/Darwin Product Types.xcspec +++ b/Sources/SWBApplePlatform/Specs/Darwin Product Types.xcspec @@ -155,7 +155,6 @@ Description = "OCUnit Test Bundle"; DefaultBuildProperties = { WRAPPER_EXTENSION = "octest"; - ENABLE_BITCODE = NO; ENTITLEMENTS_REQUIRED = NO; }; PackageTypes = ( diff --git a/Sources/SWBApplePlatform/Specs/Embedded-Shared.xcspec b/Sources/SWBApplePlatform/Specs/Embedded-Shared.xcspec index c92e24f6..be8c42ef 100644 --- a/Sources/SWBApplePlatform/Specs/Embedded-Shared.xcspec +++ b/Sources/SWBApplePlatform/Specs/Embedded-Shared.xcspec @@ -28,11 +28,6 @@ Identifier = com.apple.build-system.native; BasedOn = "default:com.apple.build-system.native"; Properties = ( - { - Name = "ENABLE_BITCODE"; - Type = Boolean; - DefaultValue = NO; - }, ); }, ) diff --git a/Sources/SWBApplePlatform/Specs/watchOS Shared.xcspec b/Sources/SWBApplePlatform/Specs/watchOS Shared.xcspec index 674ac246..c8205424 100644 --- a/Sources/SWBApplePlatform/Specs/watchOS Shared.xcspec +++ b/Sources/SWBApplePlatform/Specs/watchOS Shared.xcspec @@ -117,50 +117,6 @@ BasedOn = "com.apple.product-type.app-extension"; }, - // --- LLVM Compiler - { - _Domain = watchos-shared; - Type = Compiler; - Identifier = "com.apple.compilers.llvm.clang.1_0.compiler"; - BasedOn = "default:com.apple.compilers.llvm.clang.1_0.compiler"; - InputFileTypes = ( - "sourcecode.c.c", - "sourcecode.c.objc", - "sourcecode.cpp.cpp", - "sourcecode.cpp.objcpp", - { - "FileType" = "sourcecode.asm"; - "Condition" = "! $(ENABLE_BITCODE)"; - "ErrorMessage" = "$(InputFileName): Assembly files are not supported for the $(PLATFORM_DISPLAY_NAME) platform (arch $(CURRENT_ARCH))."; - }, - ); - Options = ( - // Generate bitcode options - not visible in the build settings. - { - Name = "CLANG_BITCODE_GENERATION_MODE"; - Type = Enumeration; - Values = ( - none, - marker, - bitcode, - ); - DefaultValue = "$(BITCODE_GENERATION_MODE)"; - Condition = "$(ENABLE_BITCODE)"; - CommandLineArgs = { - none = (); - marker = ( - "-fembed-bitcode-marker", - "-fno-gnu-inline-asm", - ); - bitcode = ( - "-fembed-bitcode", - "-fno-gnu-inline-asm", - ); - }; - }, - ); - }, - // Actool ATV specific bits { _Domain = watchos-shared; diff --git a/Sources/SWBApplePlatform/XCStringsCompiler.swift b/Sources/SWBApplePlatform/XCStringsCompiler.swift index e8107a78..07f6dd8b 100644 --- a/Sources/SWBApplePlatform/XCStringsCompiler.swift +++ b/Sources/SWBApplePlatform/XCStringsCompiler.swift @@ -12,6 +12,7 @@ import SWBUtil public import SWBCore +import Foundation public final class XCStringsCompilerSpec: GenericCompilerSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.compilers.xcstrings" diff --git a/Sources/SWBApplePlatform/XCStringsInputFileGroupingStrategy.swift b/Sources/SWBApplePlatform/XCStringsInputFileGroupingStrategy.swift index 5a8755f0..8532692d 100644 --- a/Sources/SWBApplePlatform/XCStringsInputFileGroupingStrategy.swift +++ b/Sources/SWBApplePlatform/XCStringsInputFileGroupingStrategy.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBCore +import SWBUtil /// A grouping strategy that places each xcstrings table in its own group, along with any other .strings or .stringsdicts with the same basename. /// diff --git a/Sources/SWBBuildService/BuildDependencyInfo.swift b/Sources/SWBBuildService/BuildDependencyInfo.swift index ee2791bc..fd6ca8ff 100644 --- a/Sources/SWBBuildService/BuildDependencyInfo.swift +++ b/Sources/SWBBuildService/BuildDependencyInfo.swift @@ -403,12 +403,18 @@ extension BuildDependencyInfo { let filename = resolvedBuildFile.absolutePath.basename + // TODO: all of the below are using linkType: .searchPath, we aren't reporting .absolutePath + if resolvedBuildFile.fileType.conformsTo(identifier: "wrapper.framework") { + // TODO: static frameworks? await inputs.addInput(TargetDependencyInfo.Input(inputType: .framework, name: .name(filename), linkType: .searchPath, libraryType: .dynamic)) } else if resolvedBuildFile.fileType.conformsTo(identifier: "compiled.mach-o.dylib") { await inputs.addInput(TargetDependencyInfo.Input(inputType: .library, name: .name(filename), linkType: .searchPath, libraryType: .dynamic)) } + else if resolvedBuildFile.fileType.conformsTo(identifier: "sourcecode.text-based-dylib-definition") { + await inputs.addInput(TargetDependencyInfo.Input(inputType: .library, name: .name(filename), linkType: .searchPath, libraryType: .dynamic)) + } else if resolvedBuildFile.fileType.conformsTo(identifier: "archive.ar") { await inputs.addInput(TargetDependencyInfo.Input(inputType: .library, name: .name(filename), linkType: .searchPath, libraryType: .static)) } diff --git a/Sources/SWBBuildService/BuildOperationMessages.swift b/Sources/SWBBuildService/BuildOperationMessages.swift index 39a79df8..c17616f5 100644 --- a/Sources/SWBBuildService/BuildOperationMessages.swift +++ b/Sources/SWBBuildService/BuildOperationMessages.swift @@ -21,6 +21,7 @@ import SWBTaskConstruction import SWBTaskExecution package import SWBUtil import SWBMacro +import Synchronization // FIXME: Workaround: Unable to prefer my own type over NS renamed types import class SWBTaskExecution.Task diff --git a/Sources/SWBBuildService/BuildService.swift b/Sources/SWBBuildService/BuildService.swift index 17b16996..e1219955 100644 --- a/Sources/SWBBuildService/BuildService.swift +++ b/Sources/SWBBuildService/BuildService.swift @@ -34,7 +34,7 @@ public struct MsgHandlingError: Swift.Error { private struct CoreCacheKey: Equatable, Hashable { /// The path of the developer directory. - let developerPath: Path? + let developerPath: SWBProtocol.DeveloperPath? /// The inferior build products path, if defined. let inferiorProducts: Path? @@ -146,7 +146,7 @@ open class BuildService: Service, @unchecked Sendable { } /// Convenience overload which throws if the Core had initialization errors. - func sharedCore(developerPath: Path?, inferiorProducts: Path? = nil, environment: [String: String] = [:]) async throws -> Core { + func sharedCore(developerPath: SWBProtocol.DeveloperPath?, inferiorProducts: Path? = nil, environment: [String: String] = [:]) async throws -> Core { let (c, diagnostics) = await sharedCore(developerPath: developerPath, inferiorProducts: inferiorProducts, environment: environment) guard let core = c else { throw ServiceError.unableToInitializeCore(errors: diagnostics.map { $0.formatLocalizedDescription(.debug) }) @@ -157,7 +157,7 @@ open class BuildService: Service, @unchecked Sendable { /// Get a shared core instance. /// /// We use an explicit cache so that we can minimize the number of cores we load while still keeping a flexible public interface that doesn't require all clients to provide all possible required parameters for core initialization (which is useful for testing and debug purposes). - func sharedCore(developerPath: Path?, resourceSearchPaths: [Path] = [], inferiorProducts: Path? = nil, environment: [String: String] = [:]) async -> (Core?, [Diagnostic]) { + func sharedCore(developerPath: SWBProtocol.DeveloperPath?, resourceSearchPaths: [Path] = [], inferiorProducts: Path? = nil, environment: [String: String] = [:]) async -> (Core?, [Diagnostic]) { let key = CoreCacheKey(developerPath: developerPath, inferiorProducts: inferiorProducts, environment: environment) return await sharedCoreCacheLock.withLock { if let existing = sharedCoreCache[key] { @@ -191,7 +191,17 @@ open class BuildService: Service, @unchecked Sendable { } } let delegate = Delegate() - let (core, diagnostics) = await (Core.getInitializedCore(delegate, pluginManager: pluginManager, developerPath: developerPath, resourceSearchPaths: resourceSearchPaths, inferiorProductsPath: inferiorProducts, environment: environment, buildServiceModTime: buildServiceModTime, connectionMode: connectionMode), delegate.diagnostics) + let coreDeveloperPath: Core.DeveloperPath? + switch developerPath { + case .xcode(let path): + coreDeveloperPath = .xcode(path) + case .swiftToolchain(let path): + let xcodeDeveloperPath = try? await Xcode.getActiveDeveloperDirectoryPath() + coreDeveloperPath = .swiftToolchain(path, xcodeDeveloperPath: xcodeDeveloperPath) + case nil: + coreDeveloperPath = nil + } + let (core, diagnostics) = await (Core.getInitializedCore(delegate, pluginManager: pluginManager, developerPath: coreDeveloperPath, resourceSearchPaths: resourceSearchPaths, inferiorProductsPath: inferiorProducts, environment: environment, buildServiceModTime: buildServiceModTime, connectionMode: connectionMode), delegate.diagnostics) delegate.freeze() sharedCoreCache[key] = (core, diagnostics) return (core, diagnostics) diff --git a/Sources/SWBBuildService/BuildServiceEntryPoint.swift b/Sources/SWBBuildService/BuildServiceEntryPoint.swift index c333751f..1a66fff2 100644 --- a/Sources/SWBBuildService/BuildServiceEntryPoint.swift +++ b/Sources/SWBBuildService/BuildServiceEntryPoint.swift @@ -110,6 +110,7 @@ extension BuildService { pluginManager.registerExtensionPoint(EnvironmentExtensionPoint()) pluginManager.registerExtensionPoint(InputFileGroupingStrategyExtensionPoint()) pluginManager.registerExtensionPoint(TaskProducerExtensionPoint()) + pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) pluginManager.registerExtensionPoint(DiagnosticToolingExtensionPoint()) pluginManager.registerExtensionPoint(SDKVariantInfoExtensionPoint()) pluginManager.registerExtensionPoint(FeatureAvailabilityExtensionPoint()) diff --git a/Sources/SWBBuildService/Messages.swift b/Sources/SWBBuildService/Messages.swift index a4267a1e..11159c04 100644 --- a/Sources/SWBBuildService/Messages.swift +++ b/Sources/SWBBuildService/Messages.swift @@ -77,7 +77,7 @@ private struct CreateXCFrameworkHandler: MessageHandler { guard let buildService = request.service as? BuildService else { throw StubError.error("service object is not of type BuildService") } - let (result, output) = try await XCFramework.createXCFramework(commandLine: message.commandLine, currentWorkingDirectory: message.currentWorkingDirectory, infoLookup: buildService.sharedCore(developerPath: message.effectiveDeveloperPath)) + let (result, output) = try await XCFramework.createXCFramework(commandLine: message.commandLine, currentWorkingDirectory: message.currentWorkingDirectory, infoLookup: buildService.sharedCore(developerPath: message.effectiveDeveloperPath.map { .xcode($0) })) if !result { throw StubError.error(output) } @@ -113,7 +113,7 @@ private struct ProductTypeSupportsMacCatalystHandler: MessageHandler { guard let buildService = request.service as? BuildService else { throw StubError.error("service object is not of type BuildService") } - return try await BoolResponse(buildService.sharedCore(developerPath: message.effectiveDeveloperPath).productTypeSupportsMacCatalyst(productTypeIdentifier: message.productTypeIdentifier)) + return try await BoolResponse(buildService.sharedCore(developerPath: message.effectiveDeveloperPath.map { .xcode($0) }).productTypeSupportsMacCatalyst(productTypeIdentifier: message.productTypeIdentifier)) } } @@ -122,8 +122,16 @@ private struct ProductTypeSupportsMacCatalystHandler: MessageHandler { private struct CreateSessionHandler: MessageHandler { func handle(request: Request, message: CreateSessionRequest) async throws -> CreateSessionResponse { let service = request.buildService + let developerPath: DeveloperPath? + if let devPath = message.developerPath2 { + developerPath = devPath + } else if let devPath = message.effectiveDeveloperPath { + developerPath = .xcode(devPath) + } else { + developerPath = nil + } let (core, diagnostics) = await service.sharedCore( - developerPath: message.effectiveDeveloperPath, + developerPath: developerPath, resourceSearchPaths: message.resourceSearchPaths ?? [], inferiorProducts: message.inferiorProductsPath, environment: message.environment ?? [:] @@ -184,7 +192,7 @@ extension SetSessionWorkspaceContainerPathRequest: PIFProvidingRequest { try fs.createDirectory(dir, recursive: true) let pifPath = dir.join(Foundation.UUID().description + ".json") let argument = isProject ? "-project" : "-workspace" - let result = try await Process.getOutput(url: URL(fileURLWithPath: "/usr/bin/xcrun"), arguments: ["xcodebuild", "-dumpPIF", pifPath.str, argument, path.str], currentDirectoryURL: URL(fileURLWithPath: containerPath.dirname.str, isDirectory: true), environment: Environment.current.addingContents(of: [.developerDir: session.core.developerPath.str])) + let result = try await Process.getOutput(url: URL(fileURLWithPath: "/usr/bin/xcrun"), arguments: ["xcodebuild", "-dumpPIF", pifPath.str, argument, path.str], currentDirectoryURL: URL(fileURLWithPath: containerPath.dirname.str, isDirectory: true), environment: Environment.current.addingContents(of: [.developerDir: session.core.developerPath.path.str])) if !result.exitStatus.isSuccess { throw StubError.error("Could not dump PIF for '\(path.str)': \(String(decoding: result.stderr, as: UTF8.self))") } @@ -1200,7 +1208,7 @@ private struct ClientExchangeResponseMsg StringResponse { let session = try request.session(for: message) - return StringResponse(session.core.developerPath.str) + return StringResponse(session.core.developerPath.path.str) } } @@ -1469,7 +1477,7 @@ private struct ExecuteCommandLineToolMsg: MessageHandler { request.service.send(message.replyChannel, BoolResponse(false)) return } - let (core, diagnostics) = await buildService.sharedCore(developerPath: message.developerPath) + let (core, diagnostics) = await buildService.sharedCore(developerPath: message.developerPath.map { .xcode($0) }) guard let core else { for diagnostic in diagnostics where diagnostic.behavior == .error { request.service.send(message.replyChannel, ErrorResponse(diagnostic.formatLocalizedDescription(.messageOnly))) diff --git a/Sources/SWBBuildService/PreviewInfo.swift b/Sources/SWBBuildService/PreviewInfo.swift index 02425472..49221da5 100644 --- a/Sources/SWBBuildService/PreviewInfo.swift +++ b/Sources/SWBBuildService/PreviewInfo.swift @@ -15,6 +15,7 @@ package import SWBCore import SWBTaskConstruction package import SWBTaskExecution package import SWBUtil +import SWBMacro enum PreviewInfoErrors: Error { case noBuildDescription(any Error) diff --git a/Sources/SWBBuildService/Session.swift b/Sources/SWBBuildService/Session.swift index 7a8adbc8..56f06a01 100644 --- a/Sources/SWBBuildService/Session.swift +++ b/Sources/SWBBuildService/Session.swift @@ -17,6 +17,7 @@ public import SWBServiceCore package import SWBTaskExecution import SWBUtil import struct Foundation.UUID +import Synchronization enum SessionError: Error { case noSettings(String) diff --git a/Sources/SWBBuildSystem/BuildOperation.swift b/Sources/SWBBuildSystem/BuildOperation.swift index 35655805..934b78d2 100644 --- a/Sources/SWBBuildSystem/BuildOperation.swift +++ b/Sources/SWBBuildSystem/BuildOperation.swift @@ -666,22 +666,24 @@ package final class BuildOperation: BuildSystemOperation { let aggregatedCounters = await adaptor.getAggregatedCounters() let aggregatedTaskCounters = await adaptor.getAggregatedTaskCounters() do { - let swiftCacheHits = aggregatedCounters[.swiftCacheHits, default: 0] - let swiftCacheMisses = aggregatedCounters[.swiftCacheMisses, default: 0] - let clangCacheHits = aggregatedCounters[.clangCacheHits, default: 0] - let clangCacheMisses = aggregatedCounters[.clangCacheMisses, default: 0] - if swiftCacheHits + swiftCacheMisses > 0 || clangCacheHits + clangCacheMisses > 0 { - adaptor.withActivity(ruleInfo: "CompilationCacheMetrics", executionDescription: "Report compilation cache metrics", signature: "compilation_cache_metrics", target: nil, parentActivity: nil) { activity in + let cacheHits: Int + let cacheMisses: Int + do { + let swiftCacheHits = aggregatedCounters[.swiftCacheHits, default: 0] + let swiftCacheMisses = aggregatedCounters[.swiftCacheMisses, default: 0] + let clangCacheHits = aggregatedCounters[.clangCacheHits, default: 0] + let clangCacheMisses = aggregatedCounters[.clangCacheMisses, default: 0] + cacheHits = swiftCacheHits + clangCacheHits + cacheMisses = swiftCacheMisses + clangCacheMisses + } + if cacheHits + cacheMisses > 0 { + let signature = ByteString(encodingAsUTF8: "compilation_cache_metrics") + 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")" } - if swiftCacheHits + swiftCacheMisses > 0 { - delegate.emit(data: ByteString(encodingAsUTF8: "Swift compiler: \(getSummary(hits: swiftCacheHits, misses: swiftCacheMisses))").bytes, for: activity, signature: "compilation_cache_metrics") - } - if clangCacheHits + clangCacheMisses > 0 { - delegate.emit(data: ByteString(encodingAsUTF8: "Clang compiler: \(getSummary(hits: clangCacheHits, misses: clangCacheMisses))").bytes, for: activity, signature: "compilation_cache_metrics") - } + delegate.emit(diagnostic: Diagnostic(behavior: .note, location: .unknown, data: DiagnosticData(getSummary(hits: cacheHits, misses: cacheMisses))), for: activity, signature: signature) return .succeeded } @@ -879,8 +881,15 @@ package final class BuildOperation: BuildSystemOperation { } package func taskDiscoveredRequiredTargetDependency(target: ConfiguredTarget, antecedent: ConfiguredTarget, reason: RequiredTargetDependencyReason, warningLevel: BooleanWarningLevel) { - if !transitiveDependencyExists(target: target, antecedent: antecedent) { + 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) @@ -898,14 +907,8 @@ package final class BuildOperation: BuildSystemOperation { } else { message = DiagnosticData("'\(target.target.name)' is missing a dependency on '\(antecedent.target.name)' because \(reason)") } - 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 - } + + targetDiagnosticsEngine.emit(Diagnostic(behavior: diagnosticBehavior, location: .unknown, data: message)) } } } @@ -1530,7 +1533,7 @@ internal final class OperationSystemAdaptor: SWBLLBuild.BuildSystemDelegate, Act return } - let signatureCtx = MD5Context() + let signatureCtx = InsecureHashContext() signatureCtx.add(string: "CleanupCompileCache") signatureCtx.add(string: cachePath.str) let signature = signatureCtx.signature diff --git a/Sources/SWBBuildSystem/CleanOperation.swift b/Sources/SWBBuildSystem/CleanOperation.swift index d797c680..fce5fa8b 100644 --- a/Sources/SWBBuildSystem/CleanOperation.swift +++ b/Sources/SWBBuildSystem/CleanOperation.swift @@ -22,6 +22,7 @@ package import var Foundation.NSLocalizedDescriptionKey package import class Foundation.NSError package import struct Foundation.URL package import struct Foundation.UUID +import SWBMacro package final class CleanOperation: BuildSystemOperation, TargetDependencyResolverDelegate { package var diagnosticContext: DiagnosticContextData { diff --git a/Sources/SWBBuildSystem/DependencyCycleFormatter.swift b/Sources/SWBBuildSystem/DependencyCycleFormatter.swift index bdbe027d..b0d7f6fa 100644 --- a/Sources/SWBBuildSystem/DependencyCycleFormatter.swift +++ b/Sources/SWBBuildSystem/DependencyCycleFormatter.swift @@ -15,6 +15,7 @@ import SWBTaskExecution import SWBUtil import Foundation private import SWBLLBuild +import SWBTaskConstruction /// Convenience enum to encode whether a task is the beginning or end of a target, or something else. /// "End of a target" in this case is a task which tasks in other targets may be directly depending on, and so can mark the point at which we cross a target boundary. diff --git a/Sources/SWBCore/BuildFileResolution.swift b/Sources/SWBCore/BuildFileResolution.swift index 29d99478..8c4ab089 100644 --- a/Sources/SWBCore/BuildFileResolution.swift +++ b/Sources/SWBCore/BuildFileResolution.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBMacro /// Protocol to support getting resolved information about a `BuildFile` within a `ConfiguredTarget`. public protocol BuildFileResolution: SpecLookupContext { diff --git a/Sources/SWBCore/BuildRequest.swift b/Sources/SWBCore/BuildRequest.swift index c5624d3b..38f22129 100644 --- a/Sources/SWBCore/BuildRequest.swift +++ b/Sources/SWBCore/BuildRequest.swift @@ -323,7 +323,7 @@ extension BuildRequest { case .buildRequest: dependencyScope = .buildRequest } - try self.init(parameters: parameters, buildTargets: payload.configuredTargets.map{ try BuildRequest.BuildTargetInfo(from: $0, defaultParameters: parameters, workspace: workspace) }, dependencyScope: dependencyScope, continueBuildingAfterErrors: payload.continueBuildingAfterErrors, hideShellScriptEnvironment: payload.hideShellScriptEnvironment, useParallelTargets: payload.useParallelTargets, useImplicitDependencies: payload.useImplicitDependencies, useDryRun: payload.useDryRun, showNonLoggedProgress: payload.showNonLoggedProgress, recordBuildBacktraces: payload.recordBuildBacktraces, generatePrecompiledModulesReport: payload.generatePrecompiledModulesReport, buildDescriptionID: payload.buildDescriptionID.map(BuildDescriptionID.init), qos: qos, buildPlanDiagnosticsDirPath: payload.buildPlanDiagnosticsDirPath, buildCommand: buildCommand, schemeCommand: payload.schemeCommand?.coreRepresentation, containerPath: payload.containerPath, jsonRepresentation: payload.jsonRepresentation) + try self.init(parameters: parameters, buildTargets: payload.configuredTargets.map{ try BuildRequest.BuildTargetInfo(from: $0, defaultParameters: parameters, workspace: workspace) }, dependencyScope: dependencyScope, continueBuildingAfterErrors: payload.continueBuildingAfterErrors, hideShellScriptEnvironment: payload.hideShellScriptEnvironment, useParallelTargets: payload.useParallelTargets, useImplicitDependencies: payload.useImplicitDependencies, useDryRun: payload.useDryRun, enableStaleFileRemoval: nil, showNonLoggedProgress: payload.showNonLoggedProgress, recordBuildBacktraces: payload.recordBuildBacktraces, generatePrecompiledModulesReport: payload.generatePrecompiledModulesReport, buildDescriptionID: payload.buildDescriptionID.map(BuildDescriptionID.init), qos: qos, buildPlanDiagnosticsDirPath: payload.buildPlanDiagnosticsDirPath, buildCommand: buildCommand, schemeCommand: payload.schemeCommand?.coreRepresentation, containerPath: payload.containerPath, jsonRepresentation: payload.jsonRepresentation) } /// Whether the build request _explicitly_ contains the specified `target`. diff --git a/Sources/SWBCore/CMakeLists.txt b/Sources/SWBCore/CMakeLists.txt index fb2eb82c..467c8aa8 100644 --- a/Sources/SWBCore/CMakeLists.txt +++ b/Sources/SWBCore/CMakeLists.txt @@ -59,6 +59,7 @@ add_library(SWBCore DiagnosticSupport.swift EnvironmentBindings.swift ExecutableTask.swift + Extensions/DeveloperDirectoryExtension.swift Extensions/DiagnosticToolingExtension.swift Extensions/EnvironmentExtension.swift Extensions/FeatureAvailabilityExtension.swift @@ -71,7 +72,6 @@ add_library(SWBCore Extensions/ToolchainRegistryExtension.swift FileSystemSignatureBasedCache.swift FileToBuild.swift - KnownFolders.swift LibclangVendored/ArrayExtensions.swift LibclangVendored/CStringArray.swift LibclangVendored/Libclang.swift diff --git a/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierFramework.swift b/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierFramework.swift index 51a4b9f5..614c3939 100644 --- a/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierFramework.swift +++ b/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierFramework.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import Foundation public struct ModuleVerifierFramework { @_spi(Testing) public let directory: Path diff --git a/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierHeader.swift b/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierHeader.swift index 4ef43ee6..9bb47f05 100644 --- a/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierHeader.swift +++ b/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierHeader.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import Foundation enum HeaderKind: String { case publicHeader = "public" diff --git a/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierTarget.swift b/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierTarget.swift index 69d64420..d8e5bbe0 100644 --- a/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierTarget.swift +++ b/Sources/SWBCore/ClangModuleVerifier/ModuleVerifierTarget.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import Foundation public struct ModuleVerifierTarget: Equatable { public let value: String diff --git a/Sources/SWBCore/ConfiguredTarget.swift b/Sources/SWBCore/ConfiguredTarget.swift index 561a1156..4f93f80e 100644 --- a/Sources/SWBCore/ConfiguredTarget.swift +++ b/Sources/SWBCore/ConfiguredTarget.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBProtocol public final class ConfiguredTarget: Hashable, CustomStringConvertible, Serializable, Comparable, Sendable, Encodable { /// The build parameters to use for this target. diff --git a/Sources/SWBCore/Core.swift b/Sources/SWBCore/Core.swift index e5927969..00643fe9 100644 --- a/Sources/SWBCore/Core.swift +++ b/Sources/SWBCore/Core.swift @@ -40,7 +40,7 @@ public final class Core: Sendable { /// Get a configured instance of the core. /// /// - returns: An initialized Core instance on which all discovery and loading will have been completed. If there are errors during that process, they will be logged to `stderr` and no instance will be returned. Otherwise, the initialized object is returned. - public static func getInitializedCore(_ delegate: any CoreDelegate, pluginManager: PluginManager, developerPath: Path? = nil, resourceSearchPaths: [Path] = [], inferiorProductsPath: Path? = nil, extraPluginRegistration: @PluginExtensionSystemActor (_ pluginPaths: [Path]) -> Void = { _ in }, additionalContentPaths: [Path] = [], environment: [String:String] = [:], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async -> Core? { + public static func getInitializedCore(_ delegate: any CoreDelegate, pluginManager: PluginManager, developerPath: DeveloperPath? = nil, resourceSearchPaths: [Path] = [], inferiorProductsPath: Path? = nil, extraPluginRegistration: @PluginExtensionSystemActor (_ pluginPaths: [Path]) -> Void = { _ in }, additionalContentPaths: [Path] = [], environment: [String:String] = [:], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async -> Core? { // Enable macro expression interning during loading. return await MacroNamespace.withExpressionInterningEnabled { let hostOperatingSystem: OperatingSystem @@ -51,20 +51,35 @@ public final class Core: Sendable { return nil } - let resolvedDeveloperPath: String + #if USE_STATIC_PLUGIN_INITIALIZATION + // In a package context, plugins are statically linked into the build system. + // Load specs from service plugins if requested since we don't have a Service in certain tests + // Here we don't have access to `core.pluginPaths` like we do in the call below, + // but it doesn't matter because it will return an empty array when USE_STATIC_PLUGIN_INITIALIZATION is defined. + await extraPluginRegistration([]) + #endif + + let resolvedDeveloperPath: DeveloperPath do { - if let resolved = developerPath?.nilIfEmpty?.str { + if let resolved = developerPath { resolvedDeveloperPath = resolved - } else if hostOperatingSystem == .macOS { - resolvedDeveloperPath = try await Xcode.getActiveDeveloperDirectoryPath().str - } else if hostOperatingSystem == .windows { - guard let userProgramFiles = URL.userProgramFiles, let swiftPath = try? userProgramFiles.appending(component: "Swift").filePath else { - delegate.error("Could not determine path to user program files") + } else { + let values = try await Set(pluginManager.extensions(of: DeveloperDirectoryExtensionPoint.self).asyncMap { try await $0.fallbackDeveloperDirectory(hostOperatingSystem: hostOperatingSystem) }).compactMap { $0 } + switch values.count { + case 0: + delegate.error("Could not determine path to developer directory because no extensions provided a fallback value") + return nil + case 1: + let path = values[0] + if path.str.hasSuffix(".app/Contents/Developer") { + resolvedDeveloperPath = .xcode(path) + } else { + resolvedDeveloperPath = .fallback(values[0]) + } + default: + delegate.error("Could not determine path to developer directory because multiple extensions provided conflicting fallback values: \(values.sorted().map { $0.str }.joined(separator: ", "))") return nil } - resolvedDeveloperPath = swiftPath.str - } else { - resolvedDeveloperPath = "/" } } catch { delegate.error("Could not determine path to developer directory: \(error)") @@ -93,8 +108,11 @@ public final class Core: Sendable { } } + #if !USE_STATIC_PLUGIN_INITIALIZATION + // In a package context, plugins are statically linked into the build system. // Load specs from service plugins if requested since we don't have a Service in certain tests await extraPluginRegistration(core.pluginPaths) + #endif await core.initializeSpecRegistry() @@ -156,8 +174,26 @@ public final class Core: Sendable { public let pluginManager: PluginManager + public enum DeveloperPath: Sendable, Hashable { + // A path to an Xcode install's "/Contents/Developer" directory + case xcode(Path) + + // A path to the root of a Swift toolchain, optionally paired with the developer path of an installed Xcode + case swiftToolchain(Path, xcodeDeveloperPath: Path?) + + // A fallback resolved path. + case fallback(Path) + + public var path: Path { + switch self { + case .xcode(let path), .swiftToolchain(let path, xcodeDeveloperPath: _), .fallback(let path): + return path + } + } + } + /// The path to the "Developer" directory. - public let developerPath: Path + public let developerPath: DeveloperPath /// Additional search paths to be used when looking up resource bundles. public let resourceSearchPaths: [Path] @@ -192,11 +228,11 @@ public final class Core: Sendable { public let connectionMode: ServiceHostConnectionMode - @_spi(Testing) public init(delegate: any CoreDelegate, hostOperatingSystem: OperatingSystem, pluginManager: PluginManager, developerPath: String, resourceSearchPaths: [Path], inferiorProductsPath: Path?, additionalContentPaths: [Path], environment: [String:String], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async throws { + @_spi(Testing) public init(delegate: any CoreDelegate, hostOperatingSystem: OperatingSystem, pluginManager: PluginManager, developerPath: DeveloperPath, resourceSearchPaths: [Path], inferiorProductsPath: Path?, additionalContentPaths: [Path], environment: [String:String], buildServiceModTime: Date, connectionMode: ServiceHostConnectionMode) async throws { self.delegate = delegate self.hostOperatingSystem = hostOperatingSystem self.pluginManager = pluginManager - self.developerPath = Path(developerPath) + self.developerPath = developerPath self.resourceSearchPaths = resourceSearchPaths self.inferiorProductsPath = inferiorProductsPath self.additionalContentPaths = additionalContentPaths @@ -204,19 +240,27 @@ public final class Core: Sendable { self.connectionMode = connectionMode self.environment = environment - let versionPath = self.developerPath.dirname.join("version.plist") + switch developerPath { + case .xcode(let path): + let versionPath = path.dirname.join("version.plist") - // Load the containing app (Xcode or Playgrounds) version information, if available. - // - // We make this optional so tests do not need to provide it. - if let info = try XcodeVersionInfo.versionInfo(versionPath: versionPath) { - self.xcodeVersion = info.shortVersion + // Load the containing app (Xcode or Playgrounds) version information, if available. + // + // We make this optional so tests do not need to provide it. + if let info = try XcodeVersionInfo.versionInfo(versionPath: versionPath) { + self.xcodeVersion = info.shortVersion - // If the ProductBuildVersion key is missing, we use "UNKNOWN" as the value. - self.xcodeProductBuildVersion = info.productBuildVersion ?? ProductBuildVersion(major: 0, train: "A", build: 0, buildSuffix: "") - self.xcodeProductBuildVersionString = info.productBuildVersion?.description ?? "UNKNOWN" - } else { - // Set an arbitrary version for testing purposes. + // If the ProductBuildVersion key is missing, we use "UNKNOWN" as the value. + self.xcodeProductBuildVersion = info.productBuildVersion ?? ProductBuildVersion(major: 0, train: "A", build: 0, buildSuffix: "") + self.xcodeProductBuildVersionString = info.productBuildVersion?.description ?? "UNKNOWN" + } else { + // Set an arbitrary version for testing purposes. + self.xcodeVersion = Version(99, 99, 99) + self.xcodeProductBuildVersion = ProductBuildVersion(major: 99, train: "T", build: 999) + self.xcodeProductBuildVersionString = xcodeProductBuildVersion.description + } + case .swiftToolchain, .fallback: + // FIXME: Eliminate this requirment for Swift toolchains self.xcodeVersion = Version(99, 99, 99) self.xcodeProductBuildVersion = ProductBuildVersion(major: 99, train: "T", build: 999) self.xcodeProductBuildVersionString = xcodeProductBuildVersion.description @@ -229,7 +273,17 @@ public final class Core: Sendable { self.toolchainPaths = { var toolchainPaths = [(Path, strict: Bool)]() - toolchainPaths.append((Path(developerPath).join("Toolchains"), strict: developerPath.hasSuffix(".app/Contents/Developer"))) + switch developerPath { + case .xcode(let path): + toolchainPaths.append((path.join("Toolchains"), strict: path.str.hasSuffix(".app/Contents/Developer"))) + case .swiftToolchain(let path, xcodeDeveloperPath: let xcodeDeveloperPath): + toolchainPaths.append((path, strict: true)) + if let xcodeDeveloperPath { + toolchainPaths.append((xcodeDeveloperPath.join("Toolchains"), strict: xcodeDeveloperPath.str.hasSuffix(".app/Contents/Developer"))) + } + case .fallback(let path): + toolchainPaths.append((path.join("Toolchains"), strict: false)) + } // FIXME: We should support building the toolchain locally (for `inferiorProductsPath`). @@ -359,12 +413,14 @@ public final class Core: Sendable { public func lookupCASPlugin() -> ToolchainCASPlugin? { return casPlugin.withLock { casPlugin in if casPlugin == nil { - if hostOperatingSystem == .macOS { - let pluginPath = developerPath.join("usr/lib/libToolchainCASPlugin.dylib") + switch developerPath { + case .xcode(let path): + let pluginPath = path.join("usr/lib/libToolchainCASPlugin.dylib") let plugin = try? ToolchainCASPlugin(dylib: pluginPath) casPlugin = plugin - } else { + case .swiftToolchain, .fallback: // Unimplemented + break } } return casPlugin @@ -388,8 +444,19 @@ public final class Core: Sendable { if let onlySearchAdditionalPlatformPaths = getEnvironmentVariable("XCODE_ONLY_EXTRA_PLATFORM_FOLDERS"), onlySearchAdditionalPlatformPaths.boolValue { searchPaths = [] } else { - let platformsDir = self.developerPath.join("Platforms") - searchPaths = [platformsDir] + switch developerPath { + case .xcode(let path): + let platformsDir = path.join("Platforms") + searchPaths = [platformsDir] + case .swiftToolchain(_, let xcodeDeveloperDirectoryPath): + if let xcodeDeveloperDirectoryPath { + searchPaths = [xcodeDeveloperDirectoryPath.join("Platforms")] + } else { + searchPaths = [] + } + case .fallback: + searchPaths = [] + } } if let additionalPlatformSearchPaths = getEnvironmentVariable("XCODE_EXTRA_PLATFORM_FOLDERS") { for searchPath in additionalPlatformSearchPaths.split(separator: Path.pathEnvironmentSeparator) { @@ -677,7 +744,7 @@ struct CoreRegistryDelegate : PlatformRegistryDelegate, SDKRegistryDelegate, Spe core.pluginManager } - var developerPath: Path { + var developerPath: Core.DeveloperPath { core.developerPath } } diff --git a/Sources/SWBCore/EnvironmentBindings.swift b/Sources/SWBCore/EnvironmentBindings.swift index fce15432..ad20efef 100644 --- a/Sources/SWBCore/EnvironmentBindings.swift +++ b/Sources/SWBCore/EnvironmentBindings.swift @@ -41,7 +41,7 @@ public struct EnvironmentBindings: Sendable { } /// Add a signature of the bindings into the given context. - public func computeSignature(into ctx: MD5Context) { + public func computeSignature(into ctx: InsecureHashContext) { for (variable, val) in bindings { // The signature computation should record the variable name and value data, and the positions which divide them. ctx.add(string: variable) diff --git a/Sources/SWBCore/Extensions/DeveloperDirectoryExtension.swift b/Sources/SWBCore/Extensions/DeveloperDirectoryExtension.swift new file mode 100644 index 00000000..9dc0db37 --- /dev/null +++ b/Sources/SWBCore/Extensions/DeveloperDirectoryExtension.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +public import SWBUtil + +public struct DeveloperDirectoryExtensionPoint: ExtensionPoint { + public typealias ExtensionProtocol = DeveloperDirectoryExtension + + public static let name = "DeveloperDirectoryExtensionPoint" + + public init() {} +} + +public protocol DeveloperDirectoryExtension: Sendable { + func fallbackDeveloperDirectory(hostOperatingSystem: OperatingSystem) async throws -> Path? +} diff --git a/Sources/SWBCore/Extensions/InputFileGroupingStrategyExtension.swift b/Sources/SWBCore/Extensions/InputFileGroupingStrategyExtension.swift index 08328020..2fb9a95f 100644 --- a/Sources/SWBCore/Extensions/InputFileGroupingStrategyExtension.swift +++ b/Sources/SWBCore/Extensions/InputFileGroupingStrategyExtension.swift @@ -22,4 +22,5 @@ public struct InputFileGroupingStrategyExtensionPoint: ExtensionPoint, Sendable public protocol InputFileGroupingStrategyExtension: Sendable { func groupingStrategies() -> [String: any InputFileGroupingStrategyFactory] + func fileTypesCompilingToSwiftSources() -> [String] } diff --git a/Sources/SWBCore/Extensions/PlatformInfoExtension.swift b/Sources/SWBCore/Extensions/PlatformInfoExtension.swift index 584d4cbc..a0b8ac35 100644 --- a/Sources/SWBCore/Extensions/PlatformInfoExtension.swift +++ b/Sources/SWBCore/Extensions/PlatformInfoExtension.swift @@ -74,6 +74,6 @@ extension PlatformInfoExtension { public protocol PlatformInfoExtensionAdditionalPlatformsContext: Sendable { var hostOperatingSystem: OperatingSystem { get } - var developerPath: Path { get } + var developerPath: Core.DeveloperPath { get } var fs: any FSProxy { get } } diff --git a/Sources/SWBCore/KnownFolders.swift b/Sources/SWBCore/KnownFolders.swift deleted file mode 100644 index e9e7dbe9..00000000 --- a/Sources/SWBCore/KnownFolders.swift +++ /dev/null @@ -1,60 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -import SWBUtil -import Foundation - -#if os(Windows) -import WinSDK - -private var KF_FLAG_DEFAULT: DWORD { - DWORD(WinSDK.KF_FLAG_DEFAULT.rawValue) -} - -private func SUCCEEDED(_ hr: HRESULT) -> Bool { - hr >= 0 -} - -private func _url(for id: KNOWNFOLDERID) -> URL? { - var pszPath: PWSTR? - let hr: HRESULT = withUnsafePointer(to: id) { id in - SHGetKnownFolderPath(id, KF_FLAG_DEFAULT, nil, &pszPath) - } - guard SUCCEEDED(hr) else { return nil } - defer { CoTaskMemFree(pszPath) } - return URL(filePath: String(decodingCString: pszPath!, as: UTF16.self), directoryHint: .isDirectory) -} -#endif - -extension URL { - /// Maps to the environment variable `%LOCALAPPDATA%\Programs` - /// - /// An example of a concrete path is `C:\Users\User\AppData\Local\Programs` - static var userProgramFiles: URL? { -#if os(Windows) - _url(for: FOLDERID_UserProgramFiles) -#else - nil -#endif - } - - /// Maps to the environment variable `%ProgramFiles(x86)%` - /// - /// An example of a concrete path is `C:\Program Files (x86)` - static var programFilesX86: URL? { -#if os(Windows) - _url(for: FOLDERID_ProgramFilesX86) -#else - nil -#endif - } -} diff --git a/Sources/SWBCore/LibSwiftDriver/LibSwiftDriver.swift b/Sources/SWBCore/LibSwiftDriver/LibSwiftDriver.swift index cd9257b0..fa323660 100644 --- a/Sources/SWBCore/LibSwiftDriver/LibSwiftDriver.swift +++ b/Sources/SWBCore/LibSwiftDriver/LibSwiftDriver.swift @@ -177,7 +177,7 @@ public final class SwiftModuleDependencyGraph: SwiftGlobalExplicitDependencyGrap } } - public func queryPlanningDependencies(for key: String) throws -> [String] { + public func querySwiftmodulesNeedingRegistrationForDebugging(for key: String) throws -> [String] { let graph = try registryQueue.blocking_sync { guard let driver = registry[key] else { throw StubError.error("Unable to find jobs for key \(key). Be sure to plan the build ahead of fetching results.") @@ -185,13 +185,40 @@ public final class SwiftModuleDependencyGraph: SwiftGlobalExplicitDependencyGrap return driver.intermoduleDependencyGraph } guard let graph else { return [] } - let directDependencies = graph.mainModule.directDependencies ?? [] - let transitiveDependencies = Set(directDependencies + SWBUtil.transitiveClosure(directDependencies, successors: { moduleID in graph.modules[moduleID]?.directDependencies ?? [] }).0) + var swiftmodulePaths: [String] = [] + swiftmodulePaths.reserveCapacity(graph.modules.values.count) + for (_, moduleInfo) in graph.modules.sorted(byKey: { $0.moduleName < $1.moduleName }) { + guard moduleInfo != graph.mainModule else { + continue + } + switch moduleInfo.details { + case .swift: + if let modulePath = VirtualPath.lookup(moduleInfo.modulePath.path).absolutePath { + swiftmodulePaths.append(modulePath.pathString) + } + case .swiftPrebuiltExternal(let details): + if let modulePath = VirtualPath.lookup(details.compiledModulePath.path).absolutePath { + swiftmodulePaths.append(modulePath.pathString) + } + case .clang, .swiftPlaceholder: + break + } + } + return swiftmodulePaths + } + public func queryPlanningDependencies(for key: String) throws -> [String] { + let graph = try registryQueue.blocking_sync { + guard let driver = registry[key] else { + throw StubError.error("Unable to find jobs for key \(key). Be sure to plan the build ahead of fetching results.") + } + return driver.intermoduleDependencyGraph + } + guard let graph else { return [] } var fileDependencies: [String] = [] - fileDependencies.reserveCapacity(transitiveDependencies.count * 10) - for dependencyID in transitiveDependencies { - guard let moduleInfo = graph.modules[dependencyID] else { + fileDependencies.reserveCapacity(graph.modules.values.count * 10) + for (_, moduleInfo) in graph.modules.sorted(byKey: { $0.moduleName < $1.moduleName }) { + guard moduleInfo != graph.mainModule else { continue } fileDependencies.append(contentsOf: moduleInfo.sourceFiles ?? []) @@ -461,6 +488,15 @@ public final class LibSwiftDriver { case path(Path) case library(libSwiftScanPath: Path) + public var compilerOrLibraryPath: Path { + switch self { + case .path(let path): + return path + case .library(let path): + return path + } + } + public var description: String { switch self { case .path(let path): @@ -753,6 +789,14 @@ public final class SwiftCASDatabases { self.cas = cas } + public var supportsSizeManagement: Bool { cas.supportsSizeManagement } + + public func getStorageSize() throws -> Int64? { try cas.getStorageSize() } + + public func setSizeLimit(_ size: Int64) throws { try cas.setSizeLimit(size) } + + public func prune() throws { try cas.prune() } + public func queryCacheKey(_ key: String, globally: Bool) async throws -> SwiftCachedCompilation? { guard let comp = try await cas.queryCacheKey(key, globally: globally) else { return nil } return SwiftCachedCompilation(comp, key: key) diff --git a/Sources/SWBCore/LibSwiftDriver/PlannedBuild.swift b/Sources/SWBCore/LibSwiftDriver/PlannedBuild.swift index 81694020..55a889b9 100644 --- a/Sources/SWBCore/LibSwiftDriver/PlannedBuild.swift +++ b/Sources/SWBCore/LibSwiftDriver/PlannedBuild.swift @@ -103,7 +103,7 @@ public struct SwiftDriverJob: Serializable, CustomDebugStringConvertible { self.cacheKeys = job.outputCacheKeys.reduce(into: [String]()) { result, key in result.append(key.value) }.sorted() - let md5 = MD5Context() + let md5 = InsecureHashContext() for arg in commandLine { md5.add(bytes: arg) } diff --git a/Sources/SWBCore/MacroConfigFileLoader.swift b/Sources/SWBCore/MacroConfigFileLoader.swift index d532f768..224e5e9f 100644 --- a/Sources/SWBCore/MacroConfigFileLoader.swift +++ b/Sources/SWBCore/MacroConfigFileLoader.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBMacro +import Foundation /// Information on a macro config file. @_spi(Testing) public struct MacroConfigInfo: Sendable { @@ -118,7 +119,7 @@ final class MacroConfigFileLoader: Sendable { let nestedConfigurations: NestedConfigurations /// A collection of included xcconfig files leading to the one currently being parsed. The element currently being parsed is the last one in the array. let ancestorIncludes: AncestorIncludes - let developerPath: Path + let developerPath: Core.DeveloperPath /// If a #include(?) directive has been found then this method creates and returns a parser to parse that file. The delegate of the subparser will share the macro value assignment table and diagnostics object of this delegate, so that the include file's information will be added to that of the file that included it. /// - parameter fileName: The file to be included. If this is not an absolute path, then it will be searched for in the base path of the file included it, and any defined search paths. @@ -131,7 +132,10 @@ final class MacroConfigFileLoader: Sendable { // // FIXME: Move this to its proper home, and support the other special cases Xcode has (PLATFORM_DIR and SDK_DIR). This should move to using a generic facility, e.g., source trees: Add search paths for .xcconfig macros to match what Xcode has if path.str.hasPrefix("") { - path = Path(path.str.replacingOccurrences(of: "", with: developerPath.str)) + switch developerPath { + case .xcode(let developerPath), .swiftToolchain(let developerPath, _), .fallback(let developerPath): + path = Path(path.str.replacingOccurrences(of: "", with: developerPath.str)) + } } let allSearchPaths: [Path] = basePath != nil ? [basePath!] + searchPaths : searchPaths diff --git a/Sources/SWBCore/MacroEvaluationExtensions.swift b/Sources/SWBCore/MacroEvaluationExtensions.swift index 57fc5441..2522d300 100644 --- a/Sources/SWBCore/MacroEvaluationExtensions.swift +++ b/Sources/SWBCore/MacroEvaluationExtensions.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBMacro +import Foundation public extension PropertyListItem { diff --git a/Sources/SWBCore/MacroExpressionSourceExtensions.swift b/Sources/SWBCore/MacroExpressionSourceExtensions.swift index 18c2cef5..bfabdc89 100644 --- a/Sources/SWBCore/MacroExpressionSourceExtensions.swift +++ b/Sources/SWBCore/MacroExpressionSourceExtensions.swift @@ -12,6 +12,7 @@ public import SWBMacro public import SWBProtocol +import SWBUtil extension MacroNamespace { /// Parses `strings` as a macro expression string list, returning a MacroExpression object to represent it. The returned macro expression contains a copy of the input string and a compiled representation that can be used to evaluate the expression in a particular context. The diagnostics handler is invoked once for every issue found during the parsing. Even in the presence of errors, this method always returns an expression that’s as parsed as possible. diff --git a/Sources/SWBCore/PlannedTask.swift b/Sources/SWBCore/PlannedTask.swift index 1feea1e5..6cc3b1aa 100644 --- a/Sources/SWBCore/PlannedTask.swift +++ b/Sources/SWBCore/PlannedTask.swift @@ -28,7 +28,7 @@ public struct TaskIdentifier: Comparable, Hashable, Serializable, CustomStringCo } public var sandboxProfileSentinel: String { - let taskIdentifierChecksumContext = MD5Context() + let taskIdentifierChecksumContext = InsecureHashContext() taskIdentifierChecksumContext.add(string: self.rawValue) return taskIdentifierChecksumContext.signature.asString } @@ -45,7 +45,7 @@ extension TaskIdentifier { } public init(forTarget: ConfiguredTarget?, dynamicTaskPayload: ByteString, priority: TaskPriority) { - let ctx = MD5Context() + let ctx = InsecureHashContext() ctx.add(bytes: dynamicTaskPayload) self.rawValue = "P\(priority.rawValue):\(forTarget?.guid.stringValue ?? ""):\(forTarget?.parameters.configuration ?? ""):\(ctx.signature.asString)" } diff --git a/Sources/SWBCore/PlatformFiltering.swift b/Sources/SWBCore/PlatformFiltering.swift index d3397bdb..630fd835 100644 --- a/Sources/SWBCore/PlatformFiltering.swift +++ b/Sources/SWBCore/PlatformFiltering.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBMacro +import SWBUtil extension PlatformFilter { public convenience init?(_ scope: MacroEvaluationScope) { diff --git a/Sources/SWBCore/PlatformRegistry.swift b/Sources/SWBCore/PlatformRegistry.swift index ae9edb6c..ec7b126b 100644 --- a/Sources/SWBCore/PlatformRegistry.swift +++ b/Sources/SWBCore/PlatformRegistry.swift @@ -21,7 +21,7 @@ public import SWBMacro @_spi(Testing) public protocol PlatformRegistryDelegate: DiagnosticProducingDelegate, SpecRegistryProvider { var pluginManager: PluginManager { get } - var developerPath: Path { get } + var developerPath: Core.DeveloperPath { get } } public final class Platform: Sendable { @@ -337,7 +337,7 @@ public final class PlatformRegistry { struct Context: PlatformInfoExtensionAdditionalPlatformsContext { var hostOperatingSystem: OperatingSystem - var developerPath: Path + var developerPath: Core.DeveloperPath var fs: any FSProxy } diff --git a/Sources/SWBCore/ProjectModel/BuildPhase.swift b/Sources/SWBCore/ProjectModel/BuildPhase.swift index 12c8be43..c533ffd6 100644 --- a/Sources/SWBCore/ProjectModel/BuildPhase.swift +++ b/Sources/SWBCore/ProjectModel/BuildPhase.swift @@ -124,7 +124,7 @@ public class BuildPhaseWithBuildFiles: BuildPhase, @unchecked Sendable /// Returns a string that can be used as a suffix for the base name of a derived file in order to make its filename unique. This is based on the file's path but contains only characters that have no special meaning in filenames. For example, the string will never contain a path separator character. public static func filenameUniquefierSuffixFor(path: Path) -> String { - let digester = MD5Context.init() + let digester = InsecureHashContext.init() digester.add(string: path.normalize().str) return digester.signature.asString } diff --git a/Sources/SWBCore/ProjectModel/FilePathResolver.swift b/Sources/SWBCore/ProjectModel/FilePathResolver.swift index 1dab8cfd..49834473 100644 --- a/Sources/SWBCore/ProjectModel/FilePathResolver.swift +++ b/Sources/SWBCore/ProjectModel/FilePathResolver.swift @@ -12,7 +12,7 @@ public import SWBUtil public import SWBMacro - +import SWBProtocol /// A FilePathResolver is used to resolve the absolute paths for Reference objects. public final class FilePathResolver: Sendable diff --git a/Sources/SWBCore/ProjectModel/FileTextEncoding.swift b/Sources/SWBCore/ProjectModel/FileTextEncoding.swift index 35089c8b..ee43d556 100644 --- a/Sources/SWBCore/ProjectModel/FileTextEncoding.swift +++ b/Sources/SWBCore/ProjectModel/FileTextEncoding.swift @@ -19,7 +19,7 @@ public import struct Foundation.Data public import class Foundation.NSNumber public import class Foundation.NSString -#if canImport(CoreFoundation) +#if canImport(Darwin) import class CoreFoundation.CFString import var CoreFoundation.kCFStringEncodingInvalidId import func CoreFoundation.CFStringConvertEncodingToNSStringEncoding @@ -38,7 +38,7 @@ public import struct Foundation.StringEncodingDetectionOptionsKey // encodings (except UTF-8) DO add a BOM based on the host byte order. Be aware. public extension FileTextEncoding { init?(stringEncoding: String.Encoding) { - #if canImport(CoreFoundation) + #if canImport(Darwin) let cfencoding = CFStringConvertNSStringEncodingToEncoding(stringEncoding.rawValue) if cfencoding != kCFStringEncodingInvalidId, let name = CFStringConvertEncodingToIANACharSetName(cfencoding).map(String.init) { self.init(name) @@ -50,7 +50,7 @@ public extension FileTextEncoding { /// Convert the given encoding to an `NSStringEncoding`. var stringEncoding: String.Encoding? { - #if canImport(CoreFoundation) + #if canImport(Darwin) let cfencoding = CFStringConvertIANACharSetNameToEncoding(rawValue.asCFString) if cfencoding != kCFStringEncodingInvalidId { return String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(cfencoding)) diff --git a/Sources/SWBCore/ProjectModel/PIFLoader.swift b/Sources/SWBCore/ProjectModel/PIFLoader.swift index 3aeb0168..dc167904 100644 --- a/Sources/SWBCore/ProjectModel/PIFLoader.swift +++ b/Sources/SWBCore/ProjectModel/PIFLoader.swift @@ -13,6 +13,7 @@ public import SWBUtil public import SWBProtocol public import SWBMacro +import Foundation enum PIFLoadingError: Error { /// Indicates a general PIF object decoding error. diff --git a/Sources/SWBCore/ProjectModel/PlatformFilter.swift b/Sources/SWBCore/ProjectModel/PlatformFilter.swift index 02bbf3a9..16d089ce 100644 --- a/Sources/SWBCore/ProjectModel/PlatformFilter.swift +++ b/Sources/SWBCore/ProjectModel/PlatformFilter.swift @@ -12,6 +12,7 @@ import SWBUtil import SWBProtocol +import Foundation /// Provides a generic mechanism to provide project model items to be filterable for a given platform. public final class PlatformFilter: ProjectModelItem, Hashable, Codable { diff --git a/Sources/SWBCore/ProjectModel/Workspace.swift b/Sources/SWBCore/ProjectModel/Workspace.swift index 13b3cea4..d1c8af8b 100644 --- a/Sources/SWBCore/ProjectModel/Workspace.swift +++ b/Sources/SWBCore/ProjectModel/Workspace.swift @@ -13,6 +13,7 @@ import SWBProtocol public import SWBUtil public import SWBMacro +import Foundation public enum DuplicatedIdentifierObjectType: String, Sendable { case project diff --git a/Sources/SWBCore/Settings/BuildRuleFile.swift b/Sources/SWBCore/Settings/BuildRuleFile.swift index e7361d66..0eb4d746 100644 --- a/Sources/SWBCore/Settings/BuildRuleFile.swift +++ b/Sources/SWBCore/Settings/BuildRuleFile.swift @@ -12,6 +12,7 @@ import Foundation import SWBMacro +import SWBUtil /// Decodable representation of a .xcbuildrules file's on-disk format. struct BuildRuleFile: Codable { diff --git a/Sources/SWBCore/Settings/BuiltinMacros.swift b/Sources/SWBCore/Settings/BuiltinMacros.swift index af043a83..00979bd3 100644 --- a/Sources/SWBCore/Settings/BuiltinMacros.swift +++ b/Sources/SWBCore/Settings/BuiltinMacros.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBMacro +import Synchronization /// The builtin macro declarations for things which are used directly by the build system. public final class BuiltinMacros { @@ -224,11 +225,9 @@ public final class BuiltinMacros { public static let ACTION = BuiltinMacros.declareStringMacro("ACTION") public static let ARCHS = BuiltinMacros.declareStringListMacro("ARCHS") - public static let BITCODE_GENERATION_MODE = BuiltinMacros.declareStringMacro("BITCODE_GENERATION_MODE") public static let BUILD_COMPONENTS = BuiltinMacros.declareStringListMacro("BUILD_COMPONENTS") public static let DEPLOYMENT_LOCATION = BuiltinMacros.declareBooleanMacro("DEPLOYMENT_LOCATION") public static let DEPLOYMENT_POSTPROCESSING = BuiltinMacros.declareBooleanMacro("DEPLOYMENT_POSTPROCESSING") - public static let ENABLE_BITCODE = BuiltinMacros.declareBooleanMacro("ENABLE_BITCODE") public static let ENABLE_TESTABILITY = BuiltinMacros.declareBooleanMacro("ENABLE_TESTABILITY") public static let ENABLE_TESTING_SEARCH_PATHS = BuiltinMacros.declareBooleanMacro("ENABLE_TESTING_SEARCH_PATHS") public static let ENABLE_PRIVATE_TESTING_SEARCH_PATHS = BuiltinMacros.declareBooleanMacro("ENABLE_PRIVATE_TESTING_SEARCH_PATHS") @@ -508,7 +507,7 @@ public final class BuiltinMacros { public static let CLANG_EXPLICIT_MODULES_IGNORE_LIBCLANG_VERSION_MISMATCH = BuiltinMacros.declareBooleanMacro("CLANG_EXPLICIT_MODULES_IGNORE_LIBCLANG_VERSION_MISMATCH") public static let CLANG_EXPLICIT_MODULES_OUTPUT_PATH = BuiltinMacros.declareStringMacro("CLANG_EXPLICIT_MODULES_OUTPUT_PATH") public static let SWIFT_EXPLICIT_MODULES_OUTPUT_PATH = BuiltinMacros.declareStringMacro("SWIFT_EXPLICIT_MODULES_OUTPUT_PATH") - public static let CLANG_ENABLE_COMPILE_CACHE = BuiltinMacros.declareEnumMacro("CLANG_ENABLE_COMPILE_CACHE") as EnumMacroDeclaration + public static let CLANG_ENABLE_COMPILE_CACHE = BuiltinMacros.declareBooleanMacro("CLANG_ENABLE_COMPILE_CACHE") public static let CLANG_CACHE_FINE_GRAINED_OUTPUTS = BuiltinMacros.declareEnumMacro("CLANG_CACHE_FINE_GRAINED_OUTPUTS") as EnumMacroDeclaration public static let CLANG_CACHE_FINE_GRAINED_OUTPUTS_VERIFICATION = BuiltinMacros.declareEnumMacro("CLANG_CACHE_FINE_GRAINED_OUTPUTS_VERIFICATION") as EnumMacroDeclaration public static let CLANG_DISABLE_DEPENDENCY_INFO_FILE = BuiltinMacros.declareBooleanMacro("CLANG_DISABLE_DEPENDENCY_INFO_FILE") @@ -721,6 +720,8 @@ public final class BuiltinMacros { public static let GENERATE_MASTER_OBJECT_FILE = BuiltinMacros.declareBooleanMacro("GENERATE_MASTER_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") + public static let GENERATED_TEST_ENTRY_POINT_PATH = BuiltinMacros.declarePathMacro("GENERATED_TEST_ENTRY_POINT_PATH") public static let GENERATE_TEXT_BASED_STUBS = BuiltinMacros.declareBooleanMacro("GENERATE_TEXT_BASED_STUBS") public static let GENERATE_INTERMEDIATE_TEXT_BASED_STUBS = BuiltinMacros.declareBooleanMacro("GENERATE_INTERMEDIATE_TEXT_BASED_STUBS") public static let GLOBAL_API_NOTES_PATH = BuiltinMacros.declareStringMacro("GLOBAL_API_NOTES_PATH") @@ -800,7 +801,6 @@ public final class BuiltinMacros { public static let __KNOWN_SPI_INSTALL_PATHS = BuiltinMacros.declareStringListMacro("__KNOWN_SPI_INSTALL_PATHS") public static let LD = BuiltinMacros.declareStringMacro("LD") public static let LDPLUSPLUS = BuiltinMacros.declareStringMacro("LDPLUSPLUS") - public static let LD_BITCODE_GENERATION_MODE = BuiltinMacros.declareStringMacro("LD_BITCODE_GENERATION_MODE") public static let LD_CLIENT_NAME = BuiltinMacros.declareStringMacro("LD_CLIENT_NAME") public static let LD_DEPENDENCY_INFO_FILE = BuiltinMacros.declarePathMacro("LD_DEPENDENCY_INFO_FILE") public static let LD_DYLIB_INSTALL_NAME = BuiltinMacros.declareStringMacro("LD_DYLIB_INSTALL_NAME") @@ -1066,7 +1066,7 @@ public final class BuiltinMacros { public static let SWIFT_VERSION = BuiltinMacros.declareStringMacro("SWIFT_VERSION") public static let EFFECTIVE_SWIFT_VERSION = BuiltinMacros.declareStringMacro("EFFECTIVE_SWIFT_VERSION") public static let SWIFT_WHOLE_MODULE_OPTIMIZATION = BuiltinMacros.declareBooleanMacro("SWIFT_WHOLE_MODULE_OPTIMIZATION") - public static let SWIFT_ENABLE_COMPILE_CACHE = BuiltinMacros.declareEnumMacro("SWIFT_ENABLE_COMPILE_CACHE") as EnumMacroDeclaration + public static let SWIFT_ENABLE_COMPILE_CACHE = BuiltinMacros.declareBooleanMacro("SWIFT_ENABLE_COMPILE_CACHE") public static let SWIFT_ENABLE_PREFIX_MAPPING = BuiltinMacros.declareBooleanMacro("SWIFT_ENABLE_PREFIX_MAPPING") public static let SWIFT_OTHER_PREFIX_MAPPINGS = BuiltinMacros.declareStringListMacro("SWIFT_OTHER_PREFIX_MAPPINGS") public static let SYMBOL_GRAPH_EXTRACTOR_OUTPUT_DIR = BuiltinMacros.declareStringMacro("SYMBOL_GRAPH_EXTRACTOR_OUTPUT_DIR") @@ -1424,7 +1424,6 @@ public final class BuiltinMacros { AdditionalCommandLineArguments, AppIdentifierPrefix, BLOCKLISTS_PATH, - BITCODE_GENERATION_MODE, BUILD_COMPONENTS, BUILD_DESCRIPTION_CACHE_DIR, BUILD_DIR, @@ -1665,7 +1664,6 @@ public final class BuiltinMacros { ENABLE_DEFAULT_SEARCH_PATHS_IN_LIBRARY_SEARCH_PATHS, ENABLE_DEFAULT_SEARCH_PATHS_IN_REZ_SEARCH_PATHS, ENABLE_DEFAULT_SEARCH_PATHS_IN_SWIFT_INCLUDE_PATHS, - ENABLE_BITCODE, ENABLE_CLOUD_SIGNING, ENABLE_GENERIC_TASK_CACHING, GENERIC_TASK_CACHE_ENABLE_DIAGNOSTIC_REMARKS, @@ -1757,6 +1755,8 @@ public final class BuiltinMacros { GENERATE_MASTER_OBJECT_FILE, GENERATE_PKGINFO_FILE, GENERATE_RESOURCE_ACCESSORS, + GENERATE_TEST_ENTRY_POINT, + GENERATED_TEST_ENTRY_POINT_PATH, GENERATE_TEXT_BASED_STUBS, GENERATE_INTERMEDIATE_TEXT_BASED_STUBS, GID, @@ -1859,7 +1859,6 @@ public final class BuiltinMacros { LAUNCH_CONSTRAINT_SELF, LD, LDPLUSPLUS, - LD_BITCODE_GENERATION_MODE, LD_CLIENT_NAME, LD_DEPENDENCY_INFO_FILE, LD_DYLIB_INSTALL_NAME, @@ -2632,15 +2631,6 @@ public enum SwiftDependencyRegistrationMode: String, Equatable, Hashable, Enumer case verifySwiftDependencyScanner = "verify-swift-dependency-scanner" } -/// Enumeration macro type for tri-state boolean value of whether the user has enabled compilation caching builds, disabled, or not set. -public enum CompilationCachingSetting: String, Equatable, Hashable, EnumerationMacroType { - public static let defaultValue = CompilationCachingSetting.notset - - case notset = "NOT_SET" - case enabled = "YES" - case disabled = "NO" -} - public enum FineGrainedCachingSetting: String, Equatable, Hashable, EnumerationMacroType { public static let defaultValue = FineGrainedCachingSetting.notset diff --git a/Sources/SWBCore/Settings/Settings.swift b/Sources/SWBCore/Settings/Settings.swift index d75b48de..f74c0119 100644 --- a/Sources/SWBCore/Settings/Settings.swift +++ b/Sources/SWBCore/Settings/Settings.swift @@ -156,9 +156,15 @@ fileprivate struct PreOverridesSettings { // NOTE: All of these settings must depend only on the core, and be immutable, as these values are cached in the universal defaults table. // FIXME: These need to translate to "fake-VFS" paths, for the pseudo-SWB testing. - let developerPath = core.developerPath + let developerPath = core.developerPath.path - let legacyDeveloperPath = core.developerPath.dirname.join("PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer") + switch core.developerPath { + case .xcode(let path): + let legacyDeveloperPath = path.dirname.join("PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer") + table.push(BuiltinMacros.LEGACY_DEVELOPER_DIR, literal: legacyDeveloperPath.str) + default: + break + } let developerToolsPath = developerPath.join("Tools") let developerAppsPath = developerPath.join("Applications") @@ -185,7 +191,6 @@ fileprivate struct PreOverridesSettings { // FIXME: We should see if any of these can be deprecated, once we support that. table.push(BuiltinMacros.SYSTEM_DEVELOPER_DIR, literal: developerPath.str) table.push(BuiltinMacros.DEVELOPER_DIR, literal: developerPath.str) - table.push(BuiltinMacros.LEGACY_DEVELOPER_DIR, literal: legacyDeveloperPath.str) table.push(BuiltinMacros.SYSTEM_DEVELOPER_APPS_DIR, literal: developerAppsPath.str) table.push(BuiltinMacros.DEVELOPER_APPLICATIONS_DIR, literal: developerAppsPath.str) table.push(BuiltinMacros.DEVELOPER_LIBRARY_DIR, literal: developerLibPath.str) @@ -576,11 +581,11 @@ final class WorkspaceSettings: Sendable { } if SWBFeatureFlag.enableClangCachingByDefault.value { - table.push(BuiltinMacros.CLANG_ENABLE_COMPILE_CACHE, literal: .enabled) + table.push(BuiltinMacros.CLANG_ENABLE_COMPILE_CACHE, literal: true) } if SWBFeatureFlag.enableSwiftCachingByDefault.value { - table.push(BuiltinMacros.SWIFT_ENABLE_COMPILE_CACHE, literal: .enabled) + table.push(BuiltinMacros.SWIFT_ENABLE_COMPILE_CACHE, literal: true) } return table @@ -1020,8 +1025,18 @@ extension WorkspaceContext { } // Add the standard search paths. - paths.append(core.developerPath.join("usr").join("bin")) - paths.append(core.developerPath.join("usr").join("local").join("bin")) + switch core.developerPath { + case .xcode(let path), .fallback(let path): + paths.append(path.join("usr").join("bin")) + paths.append(path.join("usr").join("local").join("bin")) + case .swiftToolchain(let path, let xcodeDeveloperPath): + paths.append(path.join("usr").join("bin")) + paths.append(path.join("usr").join("local").join("bin")) + if let xcodeDeveloperPath { + paths.append(xcodeDeveloperPath.join("usr").join("bin")) + paths.append(xcodeDeveloperPath.join("usr").join("local").join("bin")) + } + } // Add the entries from PATH. if let value = userInfo?.buildSystemEnvironment["PATH"] { @@ -1857,6 +1872,15 @@ private class SettingsBuilder { // FIXME: We need to report an error here if the toolchain couldn't be found. return core.toolchainRegistry.lookup(name) } + + // If the build system was initialized as part of a swift toolchain, push that toolchain ahead of the default toolchain, if they are not the same (e.g. when on macOS where an Xcode install exists). + if case .swiftToolchain(let path, xcodeDeveloperPath: _) = core.developerPath { + if let developerPathToolchain = core.toolchainRegistry.toolchains.first(where: { $0.path.normalize() == path.normalize() }), + developerPathToolchain != coreSettings.defaultToolchain { + toolchains.append(developerPathToolchain) + } + } + // Add the default toolchain at the end, if not present. if let defaultToolchain = coreSettings.defaultToolchain, toolchains.firstIndex(of: defaultToolchain) == nil { toolchains.append(defaultToolchain) @@ -2593,7 +2617,7 @@ private class SettingsBuilder { // FIXME: Why is this logic not part of loading the SDK in SDKRegistry.registerSDK()? I think all of the information currently used by this method should be available there. func addPlatformSDKSettings(_ platform: Platform?, _ sdk: SDK, _ sdkVariant: SDKVariant?) { pushTable(.exported) { table in - // bitcode + // Bitcode is no longer supported, so we want to continue to strip bitcode from non-simulator embedded platforms as we always have. if let platform, !platform.isSimulator, platform.correspondingSimulatorPlatformName != nil { table.push(BuiltinMacros.STRIP_BITCODE_FROM_COPIED_FILES, literal: true) } @@ -3791,6 +3815,11 @@ private class SettingsBuilder { table.push(BuiltinMacros.EFFECTIVE_PLATFORM_NAME, literal: MacCatalystInfo.publicSDKBuiltProductsDirSuffix) } + table.push(BuiltinMacros.SWIFT_ENABLE_EXPLICIT_MODULES, literal: .disabled) + table.push(BuiltinMacros._EXPERIMENTAL_SWIFT_EXPLICIT_MODULES, literal: .disabled) + table.push(BuiltinMacros.CLANG_ENABLE_EXPLICIT_MODULES, literal: false) + table.push(BuiltinMacros._EXPERIMENTAL_CLANG_EXPLICIT_MODULES, literal: false) + push(table, .exported) } @@ -4069,12 +4098,6 @@ private class SettingsBuilder { // Determine a preferred architecture for indexing, single-file actions, and the static analyzer. self.preferredArch = getPreferredArch(effectiveArchs) - // For installation and deployment, we need to generate proper bitcode: -fembed-bitcode/-embed-bitcode. - // NOTE! Do not simply check DEPLOYMENT_POSTPROCESSING as it may not be in-scope yet. - if parameters.action.isInstallAction || scope.evaluate(BuiltinMacros.DEPLOYMENT_POSTPROCESSING) { - table.push(BuiltinMacros.BITCODE_GENERATION_MODE, literal: "bitcode") - } - // Set `ARCHS` to the list of architectures we ended up with, and save the original value. table.push(BuiltinMacros.__ARCHS__, literal: originalArchs) table.push(BuiltinMacros.ARCHS, literal: effectiveArchs.removingDuplicates()) @@ -4093,10 +4116,6 @@ private class SettingsBuilder { table.push(BuiltinMacros.__SWIFT_MODULE_ONLY_ARCHS__, literal: originalModuleOnlyArchs) table.push(BuiltinMacros.SWIFT_MODULE_ONLY_ARCHS, literal: moduleOnlyArchs) - if (scope.evaluate(BuiltinMacros.ENABLE_TESTING_SEARCH_PATHS) && project?.isPackage != true) || !["iphoneos", "appletvos", "watchos"].contains(specLookupContext.platform?.name) { - table.push(BuiltinMacros.ENABLE_BITCODE, literal: false) - } - // FIXME: There is a more random, but questionable stuff here. To be added in a test case driven fashion. // Resolve some of the key path settings to be absolute. @@ -4176,21 +4195,6 @@ private class SettingsBuilder { })) } - // Bitcode support was deprecated in Xcode 14 and is being turned off by default in Xcode 15, but there is a user default which can enable it. - if scope.evaluate(BuiltinMacros.ENABLE_BITCODE) { - if UserDefaults.enableBitcodeSupport { - // If we're going to generate bitcode, then symbol editing must be done by the linker, not by a separate nmedit invocation. - table.push(BuiltinMacros.SEPARATE_SYMBOL_EDIT, literal: false) - - self.targetDiagnostics.append(Diagnostic(behavior: .warning, location: .buildSetting(BuiltinMacros.ENABLE_BITCODE), data: DiagnosticData("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode."))) - } - else { - table.push(BuiltinMacros.ENABLE_BITCODE, literal: false) - - self.targetDiagnostics.append(Diagnostic(behavior: .warning, location: .buildSetting(BuiltinMacros.ENABLE_BITCODE), data: DiagnosticData("Ignoring ENABLE_BITCODE because building with bitcode is no longer supported."))) - } - } - // If testability is enabled, then that overrides certain other settings, and in a way that the user cannot override: They're either using testability, or they're not. if scope.evaluate(BuiltinMacros.ENABLE_TESTABILITY) { table.push(BuiltinMacros.GCC_SYMBOLS_PRIVATE_EXTERN, literal: false) diff --git a/Sources/SWBCore/ShellScript.swift b/Sources/SWBCore/ShellScript.swift index bd98d388..e6845d96 100644 --- a/Sources/SWBCore/ShellScript.swift +++ b/Sources/SWBCore/ShellScript.swift @@ -216,7 +216,7 @@ public func computeScriptEnvironment(_ type: ScriptType, scope: MacroEvaluationS // Ensure that BUILD_DESCRIPTION_CACHE_DIR is never exported as it is *not* something we want customers to use. result.removeValue(forKey: BuiltinMacros.BUILD_DESCRIPTION_CACHE_DIR.name) - if scope.evaluate(BuiltinMacros.CLANG_ENABLE_COMPILE_CACHE) == .enabled { + if scope.evaluate(BuiltinMacros.CLANG_ENABLE_COMPILE_CACHE) { // Make sure the cache directory is not going to be deleted via an `xcodebuild` invocation from the script. result["COMPILATION_CACHE_KEEP_CAS_DIRECTORY"] = "YES" } diff --git a/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift b/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift index 0286c0e7..5757442a 100644 --- a/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift +++ b/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift @@ -14,6 +14,7 @@ public import SWBUtil public import struct Foundation.Data public import class Foundation.JSONDecoder public import SWBMacro +import SWBProtocol /// Describes the type and other characteristics of a single kind of input file accepted by a build tool. struct InputFileTypeDescriptor: Encodable, Sendable { diff --git a/Sources/SWBCore/SpecImplementations/SpecRegistry.swift b/Sources/SWBCore/SpecImplementations/SpecRegistry.swift index af4a15c8..06ee3a20 100644 --- a/Sources/SWBCore/SpecImplementations/SpecRegistry.swift +++ b/Sources/SWBCore/SpecImplementations/SpecRegistry.swift @@ -13,6 +13,8 @@ import SWBLibc public import SWBUtil public import SWBMacro +import Foundation +import Synchronization /// Delegate protocol used by the registry to report diagnostics. @_spi(Testing) public protocol SpecRegistryDelegate: DiagnosticProducingDelegate {} diff --git a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift index 8e12cfe1..313eba1e 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBMacro +import Foundation /// Abstract C Compiler. This is not a concrete implementation, but rather it uses various information in the command build context to choose a specific compiler and to call `constructTasks()` on that compiler. This provides a level of indirection for projects that just want their source files compiled using the default C compiler. Depending on the context, the default C compiler for any particular combination of platform, architecture, and other factors may be Clang, ICC, GCC, or some other compiler. @@ -690,7 +691,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible previousArg = argAsByteString } - let ctx = MD5Context() + let ctx = InsecureHashContext() ctx.add(string: inputFileType.identifier) ctx.add(string: self.identifier) @@ -846,7 +847,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible return false } - let buildSettingEnabled = cbc.scope.evaluate(BuiltinMacros.CLANG_ENABLE_COMPILE_CACHE) == .enabled + let buildSettingEnabled = cbc.scope.evaluate(BuiltinMacros.CLANG_ENABLE_COMPILE_CACHE) // If a blocklist is provided in the toolchain, use it to determine the default for the current project guard let blocklist = clangInfo?.clangCachingBlocklist else { @@ -1412,7 +1413,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible return nil } - let md5 = MD5Context() + let md5 = InsecureHashContext() md5.add(string: prefixHeader.str) let sharingIdentHashValue = md5.signature let baseCachePath = scope.evaluate(BuiltinMacros.SHARED_PRECOMPS_DIR) diff --git a/Sources/SWBCore/SpecImplementations/Tools/ClangStatCache.swift b/Sources/SWBCore/SpecImplementations/Tools/ClangStatCache.swift index 70d0fc73..76c69149 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/ClangStatCache.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/ClangStatCache.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import SWBUtil + final public class ClangStatCacheSpec: GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.compilers.clang-stat-cache" diff --git a/Sources/SWBCore/SpecImplementations/Tools/CodeSign.swift b/Sources/SWBCore/SpecImplementations/Tools/CodeSign.swift index 33710aa1..d8d7ead2 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CodeSign.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CodeSign.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBMacro +import Foundation public final class CodesignToolSpec : CommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.build-tools.codesign" diff --git a/Sources/SWBCore/SpecImplementations/Tools/ConcatenateTool.swift b/Sources/SWBCore/SpecImplementations/Tools/ConcatenateTool.swift index 02efc3e4..024d6db6 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/ConcatenateTool.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/ConcatenateTool.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBMacro public final class ConcatenateToolSpec : CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { public static let identifier = "com.apple.build-tools.concatenate" diff --git a/Sources/SWBCore/SpecImplementations/Tools/CopyTool.swift b/Sources/SWBCore/SpecImplementations/Tools/CopyTool.swift index 1443a29a..9df6d6d5 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CopyTool.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CopyTool.swift @@ -42,8 +42,6 @@ public final class CopyToolSpec : CompilerSpec, SpecIdentifierType, @unchecked S let outputPath = cbc.output // Lookup function for computing the command line. - let enableBitcode = cbc.scope.evaluate(BuiltinMacros.ENABLE_BITCODE) - let bitcodeGenerationMode = cbc.scope.evaluate(BuiltinMacros.BITCODE_GENERATION_MODE) func lookup(_ macro: MacroDeclaration) -> MacroExpression? { switch macro { case BuiltinMacros.COPY_PHASE_STRIP, BuiltinMacros.PBXCP_STRIP_UNSIGNED_BINARIES: @@ -63,41 +61,22 @@ public final class CopyToolSpec : CompilerSpec, SpecIdentifierType, @unchecked S guard stripBitcode else { return nil } - // If we have been directed to strip bitcode, and bitcode is either disabled or is turned to a level less than 'bitcode' (i.e., less than full bitcode), then we should strip bitcode from binaries we copy. - if !enableBitcode || bitcodeGenerationMode != "bitcode" { - return Static { cbc.scope.namespace.parseLiteralString("YES") } as MacroStringExpression - } - return nil + // Always strip all bitcode. + return Static { cbc.scope.namespace.parseLiteralString("YES") } as MacroStringExpression case BuiltinMacros.PBXCP_BITCODE_STRIP_MODE: guard stripBitcode else { return nil } - if !enableBitcode { - // If bitcode is not enabled then strip all bitcode. - return Static { cbc.scope.namespace.parseLiteralString("all") } as MacroStringExpression - } - else if bitcodeGenerationMode != "bitcode" { - // If bitcode level is less than full, then strip bitcode. - if bitcodeGenerationMode == "marker" { - // If bitcode is enabled but to generate the marker, then strip down to a marker. - return Static { cbc.scope.namespace.parseLiteralString("replace-with-marker") } as MacroStringExpression - } - else { - // Otherwise strip all bitcode. - return Static { cbc.scope.namespace.parseLiteralString("all") } as MacroStringExpression - } - } - return nil + // Always strip all bitcode. + return Static { cbc.scope.namespace.parseLiteralString("all") } as MacroStringExpression case BuiltinMacros.PBXCP_BITCODE_STRIP_TOOL: guard stripBitcode else { return nil } // FIXME: We should change the .xcspec file to make this setting conditional on $(PBXCP_STRIP_BITCODE). Then we can just always generate this value. - if !enableBitcode || bitcodeGenerationMode != "bitcode" { - // Find bitcode_strip in our effective toolchains. - if let bitcodeStripPath = cbc.producer.toolchains.lazy.compactMap({ $0.executableSearchPaths.lookup(Path("bitcode_strip")) }).first { - return cbc.scope.namespace.parseLiteralString(bitcodeStripPath.str) as MacroStringExpression - } + // Find bitcode_strip in our effective toolchains. + if let bitcodeStripPath = cbc.producer.toolchains.lazy.compactMap({ $0.executableSearchPaths.lookup(Path("bitcode_strip")) }).first { + return cbc.scope.namespace.parseLiteralString(bitcodeStripPath.str) as MacroStringExpression } return nil case BuiltinMacros.PBXCP_EXCLUDE_SUBPATHS: diff --git a/Sources/SWBCore/SpecImplementations/Tools/CreateBuildDirectory.swift b/Sources/SWBCore/SpecImplementations/Tools/CreateBuildDirectory.swift index 2e389e18..4ea707da 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CreateBuildDirectory.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CreateBuildDirectory.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import SWBUtil +import SWBMacro public final class CreateBuildDirectorySpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { public static let identifier = "com.apple.tools.create-build-directory" diff --git a/Sources/SWBCore/SpecImplementations/Tools/InfoPlistTool.swift b/Sources/SWBCore/SpecImplementations/Tools/InfoPlistTool.swift index de3b5214..d0683f6f 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/InfoPlistTool.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/InfoPlistTool.swift @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBMacro +import Foundation public final class InfoPlistToolSpec : GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.tools.info-plist-utility" diff --git a/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift b/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift index ae49d2d8..8dd603b1 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift @@ -970,14 +970,14 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec let argPrefix = "-Xlinker" // Args without parameters - for arg in ["-dynamiclib", "-bundle", "-r", "-fembed-bitcode-marker", "-dead_strip", "-nostdlib", "-rdynamic"] { + for arg in ["-dynamiclib", "-bundle", "-r", "-dead_strip", "-nostdlib", "-rdynamic"] { while let index = commandLine.firstIndex(of: arg) { commandLine.remove(at: index) } } // Args without parameters (-Xlinker-prefixed, e.g. -Xlinker) - for arg in ["-bitcode_verify", "-export_dynamic", "-sdk_imports_each_object"] { + for arg in ["-export_dynamic", "-sdk_imports_each_object"] { while let index = commandLine.firstIndex(of: arg) { guard index > 0, commandLine[index - 1] == argPrefix else { break } commandLine.removeSubrange(index - 1 ... index) @@ -996,7 +996,7 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec } // Args with a parameter (-Xlinker-prefixed, e.g. -Xlinker arg -Xlinker param) - for arg in ["-object_path_lto", "-add_ast_path", "-dependency_info", "-map", "-order_file", "-bitcode_symbol_map", "-final_output", "-allowable_client", "-sdk_imports"] { + for arg in ["-object_path_lto", "-add_ast_path", "-dependency_info", "-map", "-order_file", "-final_output", "-allowable_client", "-sdk_imports"] { while let index = commandLine.firstIndex(of: arg) { guard index > 0, index + 2 < commandLine.count, @@ -1122,6 +1122,13 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec } } + override public func environmentFromSpec(_ cbc: CommandBuildContext, _ delegate: any DiagnosticProducingDelegate, lookup: ((MacroDeclaration) -> MacroExpression?)? = nil) -> [(String, String)] { + var env: [(String, String)] = super.environmentFromSpec(cbc, delegate, lookup: lookup) + // The linker driver and linker may not be adjacent, so set PATH so the former can find the latter. + env.append(("PATH", cbc.producer.executableSearchPaths.environmentRepresentation)) + return env + } + /// Compute the list of command line arguments and inputs to pass to the linker, given a list of library specifiers. /// /// Note that `inputs` will only contain values for libraries which are being directly linked by absolute path rather than by using search paths. diff --git a/Sources/SWBCore/SpecImplementations/Tools/Lipo.swift b/Sources/SWBCore/SpecImplementations/Tools/Lipo.swift index 58e12a5f..9f3bd92d 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/Lipo.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/Lipo.swift @@ -12,6 +12,7 @@ import SWBProtocol import SWBUtil +import SWBMacro public final class LipoToolSpec: GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { diff --git a/Sources/SWBCore/SpecImplementations/Tools/MasterObjectLink.swift b/Sources/SWBCore/SpecImplementations/Tools/MasterObjectLink.swift index c2a947b0..ade7bd11 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/MasterObjectLink.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/MasterObjectLink.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// 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 { @@ -34,18 +35,6 @@ final class MasterObjectLinkSpec: CommandLineToolSpec, SpecImplementationType, @ var commandLine = [toolSpecInfo.toolPath.str] commandLine += ["-r", "-arch", arch] - let supportsBitcode = await !cbc.producer.ldLinkerSpec.commandLineFromMacroDeclaration(cbc, delegate, optionContext: toolSpecInfo, BuiltinMacros.LD_BITCODE_GENERATION_MODE).isEmpty - - if cbc.scope.evaluate(BuiltinMacros.ENABLE_BITCODE) && supportsBitcode { - // LD_BITCODE_GENERATION_MODE is the linker setting which controls passing bitcode options to the linker; but since we're invoking the linker directly here, rather than the compiler driver, we pass -bitcode_bundle rather than -fembed-bitcode*. - commandLine += ["-bitcode_bundle"] - - // If we're generating full bitcode, then we also want to pass -bitcode_verify to make sure all the objects it links against also contain full bitcode. - if cbc.scope.evaluate(BuiltinMacros.BITCODE_GENERATION_MODE) == "bitcode" { - commandLine += ["-bitcode_verify"] - } - } - // We do not pass the deployment target to the linker here. Instead the linker infers the platform and deployment target from the .o files being collected. We did briefly pass it to the linker to silence a linker warning - if we ever see issues here we should confer with the linker folks to make sure we do the right thing. See for more about the history here. let sysroot = cbc.scope.evaluate(BuiltinMacros.SDK_DIR) diff --git a/Sources/SWBCore/SpecImplementations/Tools/MergeInfoPlist.swift b/Sources/SWBCore/SpecImplementations/Tools/MergeInfoPlist.swift index 656faa51..4a5e70fe 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/MergeInfoPlist.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/MergeInfoPlist.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBMacro public final class MergeInfoPlistSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { public static func construct(registry: SpecRegistry, proxy: SpecProxy) -> Spec { diff --git a/Sources/SWBCore/SpecImplementations/Tools/MkdirTool.swift b/Sources/SWBCore/SpecImplementations/Tools/MkdirTool.swift index 8cacc8e5..88617ce2 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/MkdirTool.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/MkdirTool.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import SWBUtil + public final class MkdirToolSpec : CommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.tools.mkdir" diff --git a/Sources/SWBCore/SpecImplementations/Tools/ProcessSDKImports.swift b/Sources/SWBCore/SpecImplementations/Tools/ProcessSDKImports.swift index 3830a095..9a92892b 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/ProcessSDKImports.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/ProcessSDKImports.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBMacro public final class ProcessSDKImportsSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { public static let identifier = "com.apple.tools.process-sdk-imports" diff --git a/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift b/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift index c0bca1f0..f8f7eb58 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/ProductPackaging.swift @@ -12,6 +12,7 @@ public import SWBUtil import SWBMacro +import Foundation public final class ProductPackagingToolSpec : GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.tools.product-pkg-utility" diff --git a/Sources/SWBCore/SpecImplementations/Tools/SetAttributes.swift b/Sources/SWBCore/SpecImplementations/Tools/SetAttributes.swift index c9d2baf0..38d6534b 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/SetAttributes.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/SetAttributes.swift @@ -10,6 +10,9 @@ // //===----------------------------------------------------------------------===// +import SWBUtil +import SWBMacro + public final class SetAttributesSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { public static let identifier = "com.apple.build-tools.set-attributes" diff --git a/Sources/SWBCore/SpecImplementations/Tools/StripTool.swift b/Sources/SWBCore/SpecImplementations/Tools/StripTool.swift index 612362a9..0f4a556d 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/StripTool.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/StripTool.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import SWBMacro +import SWBUtil public final class StripToolSpec : GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.build-tools.strip" diff --git a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift index a95fc4ee..cec5bb91 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift @@ -951,7 +951,7 @@ public final class SwiftCommandOutputParser: TaskOutputParser { ruleInfo = "\(ruleInfo) \(path.str.quotedDescription)" } let signature: ByteString = { - let md5 = MD5Context() + let md5 = InsecureHashContext() md5.add(string: ruleInfo) return md5.signature }() @@ -1412,7 +1412,7 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi private func swiftCachingEnabled(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, _ moduleName: String, _ useIntegratedDriver: Bool, _ explicitModuleBuildEnabled: Bool, _ disabledPCHCompile: Bool) async -> Bool { guard cbc.producer.supportsCompilationCaching else { return false } - guard cbc.scope.evaluate(BuiltinMacros.SWIFT_ENABLE_COMPILE_CACHE) == .enabled else { + guard cbc.scope.evaluate(BuiltinMacros.SWIFT_ENABLE_COMPILE_CACHE) else { return false } if cbc.scope.evaluate(BuiltinMacros.INDEX_ENABLE_BUILD_ARENA) { @@ -1490,7 +1490,7 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi switch feature.level { case .warn: - delegate.warning("Enabling the Swift language feature '\(identifier)' is recommended; \(supplementaryMessage)") + delegate.warning("Enabling the Swift language feature '\(identifier)' will become a requirement in the future; \(supplementaryMessage)") case .error: delegate.error("Enabling the Swift language feature '\(identifier)' is required; \(supplementaryMessage)") case .ignore: @@ -3061,12 +3061,6 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi fileMapEntry.indexUnitOutputPath = indexObjectPath.str } } - let objectFilePrefix = objectFilePath.basenameWithoutSuffix - // The bitcode file. - if compilationMode.compileSources { - let bitcodeFilePath = objectFileDir.join(objectFilePrefix + ".bc") - fileMapEntry.llvmBitcode = bitcodeFilePath.str - } return (objectFilePath, fileMapEntry) } @@ -3309,10 +3303,6 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi "-O", "-Osize", - // _Very_ deprecated, but continuing to strip for backwards compatibility - "-embed-bitcode", - "-embed-bitcode-marker", - // Previews does not use compiler output "-parseable-output", "-use-frontend-parseable-output", @@ -3584,7 +3574,7 @@ extension SwiftCompilerSpec { static public func computeRuleInfoAndSignatureForPerFileVirtualBatchSubtask(variant: String, arch: String, path: Path) -> ([String], ByteString) { let ruleInfo = ["SwiftCompile", variant, arch, path.str.quotedDescription] let signature: ByteString = { - let md5 = MD5Context() + let md5 = InsecureHashContext() md5.add(string: ruleInfo.joined(separator: " ")) return md5.signature }() @@ -3784,7 +3774,6 @@ struct SwiftOutputFileMap: Codable { struct Entry: Codable { var object: String? var indexUnitOutputPath: String? - var llvmBitcode: String? var remap: String? var diagnostics: String? var emitModuleDiagnostics: String? @@ -3798,7 +3787,6 @@ 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/Sources/SWBCore/SpecImplementations/Tools/SwiftStdLibTool.swift b/Sources/SWBCore/SpecImplementations/Tools/SwiftStdLibTool.swift index 67618493..ce7edc49 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/SwiftStdLibTool.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/SwiftStdLibTool.swift @@ -52,6 +52,7 @@ public final class SwiftStdLibToolSpec : GenericCommandLineToolSpec, SpecIdentif // Compute the command line. var commandLine = await commandLineFromTemplate(cbc, delegate, optionContext: discoveredCommandLineToolSpecInfo(cbc.producer, cbc.scope, delegate), lookup: lookup).map(\.asString) + // Bitcode is no longer supported, but some old libraries may contain bitcode, so we continue to strip it when directed. if commandLine.contains("--strip-bitcode") { if let bitcodeStripToolPath = cbc.producer.toolchains.lazy.compactMap({ $0.executableSearchPaths.lookup(Path("bitcode_strip")) }).first { commandLine.append(contentsOf: ["--strip-bitcode-tool", bitcodeStripToolPath.str]) diff --git a/Sources/SWBCore/SpecImplementations/Tools/TAPISymbolExtractor.swift b/Sources/SWBCore/SpecImplementations/Tools/TAPISymbolExtractor.swift index e45594e0..dfbeb75e 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/TAPISymbolExtractor.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/TAPISymbolExtractor.swift @@ -13,6 +13,7 @@ import Foundation public import SWBUtil public import SWBMacro +import SWBProtocol final public class TAPISymbolExtractor: GenericCompilerSpec, GCCCompatibleCompilerCommandLineBuilder, SpecIdentifierType, @unchecked Sendable { public static let identifier = "com.apple.compilers.documentation.objc-symbol-extract" diff --git a/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift b/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift index e3cf5869..818147fb 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBMacro +import Foundation public struct DiscoveredTAPIToolSpecInfo: DiscoveredCommandLineToolSpecInfo { public let toolPath: Path diff --git a/Sources/SWBCore/SpecImplementations/Tools/UnifdefTool.swift b/Sources/SWBCore/SpecImplementations/Tools/UnifdefTool.swift index 5719b766..08091d21 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/UnifdefTool.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/UnifdefTool.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBMacro public final class UnifdefToolSpec : CommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { public static let identifier = "public.build-task.unifdef" diff --git a/Sources/SWBCore/SpecImplementations/Tools/ValidateDevelopmentAssets.swift b/Sources/SWBCore/SpecImplementations/Tools/ValidateDevelopmentAssets.swift index 7418c883..5d130ef7 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/ValidateDevelopmentAssets.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/ValidateDevelopmentAssets.swift @@ -12,6 +12,7 @@ import SWBProtocol import SWBUtil +import SWBMacro public final class ValidateDevelopmentAssets: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { public static let identifier = "com.apple.tools.validate-development-assets" diff --git a/Sources/SWBCore/SpecImplementations/Tools/WriteFile.swift b/Sources/SWBCore/SpecImplementations/Tools/WriteFile.swift index 614728a7..eccf5cf1 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/WriteFile.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/WriteFile.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import SWBMacro public final class WriteFileSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { public static let identifier = "com.apple.build-tools.write-file" diff --git a/Sources/SWBCore/Specs/CoreBuildSystem.xcspec b/Sources/SWBCore/Specs/CoreBuildSystem.xcspec index 07d123de..d48771f6 100644 --- a/Sources/SWBCore/Specs/CoreBuildSystem.xcspec +++ b/Sources/SWBCore/Specs/CoreBuildSystem.xcspec @@ -280,25 +280,6 @@ Type = bool; DefaultValue = NO; }, - { - Name = "ENABLE_BITCODE"; - Type = bool; - DefaultValue = NO; - }, - { - Name = "HIDE_BITCODE_SYMBOLS"; - Type = bool; - DefaultValue = YES; - }, - { - Name = "BITCODE_GENERATION_MODE"; - Type = enum; - Values = ( - "marker", - "bitcode", - ); - DefaultValue = marker; - }, { Name = "STRIP_BITCODE_FROM_COPIED_FILES"; Type = bool; @@ -1339,29 +1320,6 @@ When `GENERATE_INFOPLIST_FILE` is enabled, sets the value of the [CFBundleIdenti Category = BuildOptions; DefaultValue = NO; }, - { - Name = "ENABLE_BITCODE"; - Type = Boolean; - DefaultValue = NO; - }, - { - Name = "BITCODE_GENERATION_MODE"; - Type = Enumeration; - Values = ( - { - Value = "marker"; - }, - { - Value = "bitcode"; - }, - ); - DefaultValue = marker; - }, - { - Name = "HIDE_BITCODE_SYMBOLS"; - Type = Boolean; - DefaultValue = YES; - }, { Name = "STRIP_BITCODE_FROM_COPIED_FILES"; Type = Boolean; @@ -1790,6 +1748,22 @@ For more information on mergeable libraries, see [Configuring your project to us DefaultValue = NO; }, + { + Name = "COMPILATION_CACHE_ENABLE_CACHING"; + Type = Boolean; + Category = "Compilation Caching"; + DefaultValue = "$(COMPILATION_CACHE_ENABLE_CACHING_DEFAULT)"; + DisplayName = "Enable Compilation Caching"; + Description = "Caches the results of compilations for a particular set of inputs."; + }, + { + Name = "COMPILATION_CACHE_ENABLE_DIAGNOSTIC_REMARKS"; + Type = Boolean; + Category = "Compilation Caching"; + DisplayName = "Compilation Caching Diagnostic Info"; + Description = "Emits diagnostic information for cached compilation tasks."; + }, + // FIXME: The TAPI settings should not need to be here in order to have them appear in the project editor UI. { Name = "SUPPORTS_TEXT_BASED_API"; diff --git a/Sources/SWBCore/SwiftSDK.swift b/Sources/SWBCore/SwiftSDK.swift index 0e43edfc..eb443381 100644 --- a/Sources/SWBCore/SwiftSDK.swift +++ b/Sources/SWBCore/SwiftSDK.swift @@ -69,20 +69,24 @@ public struct SwiftSDK: Sendable { } /// The default location storing Swift SDKs installed by SwiftPM. - static var defaultSwiftSDKsDirectory: Path { - get throws { - try FileManager.default.url( + static func defaultSwiftSDKsDirectory(hostOperatingSystem: OperatingSystem) throws -> Path { + let spmURL: URL + if hostOperatingSystem == .macOS { + spmURL = try FileManager.default.url( for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: false - ).appendingPathComponent("org.swift.swiftpm").appendingPathComponent("swift-sdks").filePath + ).appendingPathComponent("org.swift.swiftpm") + } else { + spmURL = URL.homeDirectory.appendingPathComponent(".swiftpm") } + return try spmURL.appendingPathComponent("swift-sdks").filePath } /// Find Swift SDKs installed by SwiftPM. - public static func findSDKs(targetTriples: [String], fs: any FSProxy) throws -> [SwiftSDK] { - return try findSDKs(swiftSDKsDirectory: defaultSwiftSDKsDirectory, targetTriples: targetTriples, fs: fs) + public static func findSDKs(targetTriples: [String], fs: any FSProxy, hostOperatingSystem: OperatingSystem) throws -> [SwiftSDK] { + return try findSDKs(swiftSDKsDirectory: defaultSwiftSDKsDirectory(hostOperatingSystem: hostOperatingSystem), targetTriples: targetTriples, fs: fs) } private static func findSDKs(swiftSDKsDirectory: Path, targetTriples: [String], fs: any FSProxy) throws -> [SwiftSDK] { diff --git a/Sources/SWBCore/ToolInfo/ClangToolInfo.swift b/Sources/SWBCore/ToolInfo/ClangToolInfo.swift index dad597b3..dcc80ccc 100644 --- a/Sources/SWBCore/ToolInfo/ClangToolInfo.swift +++ b/Sources/SWBCore/ToolInfo/ClangToolInfo.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import Foundation public struct DiscoveredClangToolSpecInfo: DiscoveredCommandLineToolSpecInfo { public let toolPath: Path diff --git a/Sources/SWBCore/ToolchainRegistry.swift b/Sources/SWBCore/ToolchainRegistry.swift index fdca83d4..2515b184 100644 --- a/Sources/SWBCore/ToolchainRegistry.swift +++ b/Sources/SWBCore/ToolchainRegistry.swift @@ -14,6 +14,7 @@ public import SWBUtil import struct Foundation.CharacterSet import Foundation +import SWBMacro /// Delegate protocol used to report diagnostics. @_spi(Testing) public protocol ToolchainRegistryDelegate: DiagnosticProducingDelegate { diff --git a/Sources/SWBCore/WorkspaceContext.swift b/Sources/SWBCore/WorkspaceContext.swift index e7db7ae0..1b61e537 100644 --- a/Sources/SWBCore/WorkspaceContext.swift +++ b/Sources/SWBCore/WorkspaceContext.swift @@ -15,6 +15,7 @@ import Foundation public import SWBUtil public import struct SWBProtocol.RunDestinationInfo public import SWBMacro +import Synchronization /// Wrapper for user context information. public struct UserInfo: Codable, Hashable, Sendable { diff --git a/Sources/SWBCore/XCFramework.swift b/Sources/SWBCore/XCFramework.swift index 5615f75d..1326f5fe 100644 --- a/Sources/SWBCore/XCFramework.swift +++ b/Sources/SWBCore/XCFramework.swift @@ -17,6 +17,7 @@ public import class Foundation.PropertyListDecoder public import class Foundation.PropertyListEncoder public import protocol Foundation.LocalizedError public import SWBMacro +import Synchronization /// Represents the various types of error cases possible when constructing an `XCFramework` type. /// @@ -46,9 +47,6 @@ public enum XCFrameworkValidationError: Error, Equatable { /// The debug symbols path is empty. case debugSymbolsPathEmpty(libraryIdentifier: String) - /// The bitcode symbol maps path is empty. - case bitcodeSymbolMapsPathEmpty(libraryIdentifier: String) - /// The platform variant is empty. case platformVariantEmpty(libraryIdentifier: String) @@ -111,9 +109,6 @@ extension XCFrameworkValidationError: LocalizedError { case let .debugSymbolsPathEmpty(libraryIdentifier): return libraryErrorMessage("The '\(XCFrameworkInfoPlist_V1.Library.CodingKeys.debugSymbolsPath.stringValue)' is empty", libraryIdentifier: libraryIdentifier) - case let .bitcodeSymbolMapsPathEmpty(libraryIdentifier): - return libraryErrorMessage("The '\(XCFrameworkInfoPlist_V1.Library.CodingKeys.bitcodeSymbolMapsPath.stringValue)' is empty", libraryIdentifier: libraryIdentifier) - case let .platformVariantEmpty(libraryIdentifier): return libraryErrorMessage("The '\(XCFrameworkInfoPlist_V1.Library.CodingKeys.platformVariant.stringValue)' is empty", libraryIdentifier: libraryIdentifier) @@ -291,13 +286,10 @@ public struct XCFramework: Hashable, Sendable { /// - remark: XCFrameworks which declare this property can only be used by Xcodes which support v1.1 or later. public let mergeableMetadata: Bool - /// The relative path to the bitcode symbol maps. Typically 'BCSymbolMaps'. - public let bitcodeSymbolMapsPath: Path? - /// The library type for the given `Library`. public let libraryType: LibraryType - public init(libraryIdentifier: String, supportedPlatform: String, supportedArchitectures: OrderedSet, platformVariant: String?, libraryPath: Path, binaryPath: Path?, headersPath: Path?, debugSymbolsPath: Path? = nil, mergeableMetadata: Bool = false, bitcodeSymbolMapsPath: Path? = nil) { + public init(libraryIdentifier: String, supportedPlatform: String, supportedArchitectures: OrderedSet, platformVariant: String?, libraryPath: Path, binaryPath: Path?, headersPath: Path?, debugSymbolsPath: Path? = nil, mergeableMetadata: Bool = false) { self.libraryIdentifier = libraryIdentifier self.supportedPlatform = supportedPlatform self.supportedArchitectures = supportedArchitectures @@ -306,7 +298,6 @@ public struct XCFramework: Hashable, Sendable { self.binaryPath = binaryPath self.headersPath = headersPath self.debugSymbolsPath = debugSymbolsPath - self.bitcodeSymbolMapsPath = bitcodeSymbolMapsPath self.mergeableMetadata = mergeableMetadata self.libraryType = XCFramework.LibraryType(fileExtension: libraryPath.fileExtension) @@ -450,12 +441,6 @@ extension XCFramework { } } - if let bitcodeSymbolMapsPath = library.bitcodeSymbolMapsPath { - guard !bitcodeSymbolMapsPath.isEmpty else { - throw XCFrameworkValidationError.bitcodeSymbolMapsPathEmpty(libraryIdentifier: library.libraryIdentifier) - } - } - if let platformVariant = library.platformVariant { guard !platformVariant.isEmpty else { throw XCFrameworkValidationError.platformVariantEmpty(libraryIdentifier: library.libraryIdentifier) @@ -522,7 +507,6 @@ extension XCFramework.Library: Hashable { let debugSymbolsPath: String? // This is optional because we only want to encode it if the XCFramework is at least of the version which supports it, but this struct doesn't know what that is, so we capture that characteristic in XCFramework.serialize() where the version is available. let mergeableMetadata: Bool? - let bitcodeSymbolMapsPath: String? enum CodingKeys: String, CodingKey { case libraryIdentifier = "LibraryIdentifier" @@ -534,10 +518,11 @@ extension XCFramework.Library: Hashable { case headersPath = "HeadersPath" case debugSymbolsPath = "DebugSymbolsPath" case mergeableMetadata = "MergeableMetadata" + // Bitcode is no longer supported, but we still recognize the key for older XCFrameworks which define it. case bitcodeSymbolMapsPath = "BitcodeSymbolMapsPath" } - init(libraryIdentifier: String, supportedPlatform: String, supportedArchitectures: [String], platformVariant: String?, libraryPath: String, binaryPath: String?, headersPath: String?, debugSymbolsPath: String?, mergeableMetadata: Bool?, bitcodeSymbolMapsPath: String?) { + init(libraryIdentifier: String, supportedPlatform: String, supportedArchitectures: [String], platformVariant: String?, libraryPath: String, binaryPath: String?, headersPath: String?, debugSymbolsPath: String?, mergeableMetadata: Bool?) { self.libraryIdentifier = libraryIdentifier self.supportedPlatform = supportedPlatform self.supportedArchitectures = supportedArchitectures @@ -547,7 +532,6 @@ extension XCFramework.Library: Hashable { self.headersPath = headersPath self.debugSymbolsPath = debugSymbolsPath self.mergeableMetadata = mergeableMetadata - self.bitcodeSymbolMapsPath = bitcodeSymbolMapsPath } // NOTE: The mappings for maccatalyst are so that "macabi" is used as that is what is directly matched in the LC_BUILD_VERSION info. @@ -570,7 +554,6 @@ extension XCFramework.Library: Hashable { try container.encodeIfPresent(headersPath, forKey: .headersPath) try container.encodeIfPresent(debugSymbolsPath, forKey: .debugSymbolsPath) try container.encodeIfPresent(mergeableMetadata, forKey: .mergeableMetadata) - try container.encodeIfPresent(bitcodeSymbolMapsPath, forKey: .bitcodeSymbolMapsPath) } init(from decoder: any Decoder) throws { @@ -589,7 +572,8 @@ extension XCFramework.Library: Hashable { self.headersPath = try container.decodeIfPresent(String.self, forKey: .headersPath) self.debugSymbolsPath = try container.decodeIfPresent(String.self, forKey: .debugSymbolsPath) self.mergeableMetadata = try container.decodeIfPresent(Bool.self, forKey: .mergeableMetadata) - self.bitcodeSymbolMapsPath = try container.decodeIfPresent(String.self, forKey: .bitcodeSymbolMapsPath) + // Bitcode is no longer supported, but we still recognize the key for older XCFrameworks which define it. + let _ = try container.decodeIfPresent(String.self, forKey: .bitcodeSymbolMapsPath) } } @@ -651,7 +635,7 @@ extension XCFramework { let libraries = self.libraries.map { lib in // We only archive the mergeableMetadata property if we're the version which supports it or higher, so we set it to nil if we're a lower version. let mergeableMetadata: Bool? = (version >= type(of: self).mergeableMetadataVersion) ? lib.mergeableMetadata : nil - return XCFrameworkInfoPlist_V1.Library(libraryIdentifier: lib.libraryIdentifier, supportedPlatform: lib.supportedPlatform, supportedArchitectures: lib.supportedArchitectures.elements, platformVariant: lib.platformVariant, libraryPath: lib.libraryPath.str, binaryPath: lib.binaryPath?.str, headersPath: lib.headersPath?.str, debugSymbolsPath: lib.debugSymbolsPath?.str, mergeableMetadata: mergeableMetadata, bitcodeSymbolMapsPath: lib.bitcodeSymbolMapsPath?.str) + return XCFrameworkInfoPlist_V1.Library(libraryIdentifier: lib.libraryIdentifier, supportedPlatform: lib.supportedPlatform, supportedArchitectures: lib.supportedArchitectures.elements, platformVariant: lib.platformVariant, libraryPath: lib.libraryPath.str, binaryPath: lib.binaryPath?.str, headersPath: lib.headersPath?.str, debugSymbolsPath: lib.debugSymbolsPath?.str, mergeableMetadata: mergeableMetadata) } let xcframeworkV1 = XCFrameworkInfoPlist_V1(version: version.description, libraries: libraries) @@ -674,9 +658,8 @@ extension XCFramework.Library { let headersPath = other.headersPath.flatMap { Path($0) } let debugSymbolsPath = other.debugSymbolsPath.flatMap { Path($0) } let mergeableMetadata = other.mergeableMetadata ?? false - let bitcodeSymbolMapsPath = other.bitcodeSymbolMapsPath.flatMap { Path($0) } - self.init(libraryIdentifier: libraryIdentifier, supportedPlatform: supportedPlatform, supportedArchitectures: supportedArchitectures, platformVariant: platformVariant, libraryPath: libraryPath, binaryPath: binaryPath, headersPath: headersPath, debugSymbolsPath: debugSymbolsPath, mergeableMetadata: mergeableMetadata, bitcodeSymbolMapsPath: bitcodeSymbolMapsPath) + self.init(libraryIdentifier: libraryIdentifier, supportedPlatform: supportedPlatform, supportedArchitectures: supportedArchitectures, platformVariant: platformVariant, libraryPath: libraryPath, binaryPath: binaryPath, headersPath: headersPath, debugSymbolsPath: debugSymbolsPath, mergeableMetadata: mergeableMetadata) } } @@ -768,12 +751,6 @@ extension XCFramework { newCommandLine.append("-debug-symbols") newCommandLine.append(dsym.str) } - - let bcsymbolmap = archiveRoot.join("BCSymbolMaps").join("\(name).bcsymbolmap") - if fs.exists(bcsymbolmap) { - newCommandLine.append("-debug-symbols") - newCommandLine.append(bcsymbolmap.str) - } } @@ -1088,9 +1065,8 @@ extension XCFramework { // There are two types of debugging symbols to concern ourselves with: dSYMs and BCSymbolMaps. Both are passed in via the commandline using the -debug-symbols flag. However, within the XCFramework itself, we store these in the same way that an xcarchive does, in a dSYMs and BCSymbolMaps folders. let debugSymbolsPath = debugSymbolPaths.contains { $0.fileExtension == "dSYM" } ? Path("dSYMs") : nil - let bitcodeSymbolMapsPath = debugSymbolPaths.contains { $0.fileExtension == "bcsymbolmap" } ? Path("BCSymbolMaps") : nil - return .success(XCFramework.Library(libraryIdentifier: libraryIdentifier, supportedPlatform: resolvedSupportedPlatform, supportedArchitectures: supportedArchs, platformVariant: supportedEnvironment, libraryPath: Path(libPath.basename), binaryPath: relativeBinaryPath, headersPath: headersPath, debugSymbolsPath: debugSymbolsPath, mergeableMetadata: containsMergeableMetadata, bitcodeSymbolMapsPath: bitcodeSymbolMapsPath)) + return .success(XCFramework.Library(libraryIdentifier: libraryIdentifier, supportedPlatform: resolvedSupportedPlatform, supportedArchitectures: supportedArchs, platformVariant: supportedEnvironment, libraryPath: Path(libPath.basename), binaryPath: relativeBinaryPath, headersPath: headersPath, debugSymbolsPath: debugSymbolsPath, mergeableMetadata: containsMergeableMetadata)) } /// A key that holds the primary paths for xcframework contents. @@ -1215,15 +1191,6 @@ extension XCFramework { } } - // Process the bitcode symbol maps, if any. - if let bitcodeSymbolMapsPath = library.bitcodeSymbolMapsPath { - for pathToBitcodeSymbolMap in path.debugSymbolPaths.filter({ $0.fileExtension == "bcsymbolmap" }) { - let destinationPath = libraryIdentifierPath.join(bitcodeSymbolMapsPath).join(pathToBitcodeSymbolMap.basename) - try fs.createDirectory(destinationPath.dirname, recursive: true) - try fs.copy(pathToBitcodeSymbolMap, to: destinationPath) - } - } - // If there are any of the special Swift files, pick these up to. let libraryName = library.libraryPath.basenameWithoutSuffix let baseLibraryName = libraryName.hasPrefix("lib") ? libraryName.withoutPrefix("lib") : libraryName @@ -1347,19 +1314,6 @@ extension XCFramework { } } - // Copy over any bitcode symbols that may exist. - if let bitcodeSymbolMapsPath = library.bitcodeSymbolMapsPath { - let copyBitcodeSymbolMapsFromPath = rootPathToLibrary.join(bitcodeSymbolMapsPath) - guard fs.exists(copyBitcodeSymbolMapsFromPath) else { - throw XCFrameworkValidationError.missingPathEntry(xcframeworkPath: xcframeworkPath, libraryIdentifier: library.libraryIdentifier, plistKey: XCFrameworkInfoPlist_V1.Library.CodingKeys.bitcodeSymbolMapsPath.stringValue, plistValue: library.bitcodeSymbolMapsPath?.str ?? "") - } - - let copyBitcodeSymbolMapsToPath = copyLibraryToPath - for file in try fs.listdir(copyBitcodeSymbolMapsFromPath) { - try copy(copyBitcodeSymbolMapsFromPath.join(file), to: copyBitcodeSymbolMapsToPath.join(file)) - } - } - // If the library has headers, we need to create a task to copy those over as well. if let headersPath = library.headersPath, library.libraryType.canHaveHeaders { let copyHeadersFromPath = rootPathToLibrary.join(headersPath) diff --git a/Sources/SWBGenericUnixPlatform/Plugin.swift b/Sources/SWBGenericUnixPlatform/Plugin.swift index c9ee96d7..e4679961 100644 --- a/Sources/SWBGenericUnixPlatform/Plugin.swift +++ b/Sources/SWBGenericUnixPlatform/Plugin.swift @@ -15,12 +15,24 @@ import SWBCore import Foundation @PluginExtensionSystemActor public func initializePlugin(_ manager: PluginManager) { + manager.register(GenericUnixDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(GenericUnixPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(GenericUnixPlatformInfoExtension(), type: PlatformInfoExtensionPoint.self) manager.register(GenericUnixSDKRegistryExtension(), type: SDKRegistryExtensionPoint.self) manager.register(GenericUnixToolchainRegistryExtension(), type: ToolchainRegistryExtensionPoint.self) } +struct GenericUnixDeveloperDirectoryExtension: DeveloperDirectoryExtension { + func fallbackDeveloperDirectory(hostOperatingSystem: OperatingSystem) async throws -> Path? { + if hostOperatingSystem == .windows || hostOperatingSystem == .macOS { + // Handled by the Windows and Apple plugins + return nil + } + + return .root + } +} + struct GenericUnixPlatformSpecsExtension: SpecificationsExtension { func specificationFiles(resourceSearchPaths: [Path]) -> Bundle? { findResourceBundle(nameWhenInstalledInToolchain: "SwiftBuild_SWBGenericUnixPlatform", resourceSearchPaths: resourceSearchPaths, defaultBundle: Bundle.module) diff --git a/Sources/SWBGenericUnixPlatform/Specs/Unix.xcspec b/Sources/SWBGenericUnixPlatform/Specs/Unix.xcspec index 484b04ea..eb72ba9c 100644 --- a/Sources/SWBGenericUnixPlatform/Specs/Unix.xcspec +++ b/Sources/SWBGenericUnixPlatform/Specs/Unix.xcspec @@ -53,6 +53,8 @@ SWIFT_FORCE_STATIC_LINK_STDLIB = NO; // Avoid warning for executable types ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + GENERATE_TEST_ENTRY_POINT = YES; + GENERATED_TEST_ENTRY_POINT_PATH = "$(DERIVED_SOURCES_DIR)/test_entry_point.swift"; }; PackageTypes = ( com.apple.package-type.mach-o-executable // default diff --git a/Sources/SWBGenericUnixPlatform/Specs/UnixLd.xcspec b/Sources/SWBGenericUnixPlatform/Specs/UnixLd.xcspec index d5c723cd..e773b048 100644 --- a/Sources/SWBGenericUnixPlatform/Specs/UnixLd.xcspec +++ b/Sources/SWBGenericUnixPlatform/Specs/UnixLd.xcspec @@ -138,6 +138,12 @@ Type = Path; Condition = "NO"; }, + { + // Unsupported + Name = "LD_WARN_DUPLICATE_LIBRARIES"; + Type = Boolean; + Condition = "NO"; + }, { // Don't deduplicate is broken in gold Name = "LD_DONT_RUN_DEDUPLICATION"; diff --git a/Sources/SWBMacro/MacroConfigFileParser.swift b/Sources/SWBMacro/MacroConfigFileParser.swift index a465ac27..a1fa7ebf 100644 --- a/Sources/SWBMacro/MacroConfigFileParser.swift +++ b/Sources/SWBMacro/MacroConfigFileParser.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import Foundation private extension UInt8 { var isASCIISpace: Bool { diff --git a/Sources/SWBMacro/MacroEvaluationScope.swift b/Sources/SWBMacro/MacroEvaluationScope.swift index ab31749f..98d6e692 100644 --- a/Sources/SWBMacro/MacroEvaluationScope.swift +++ b/Sources/SWBMacro/MacroEvaluationScope.swift @@ -345,16 +345,20 @@ final class MacroEvaluationContext { /// Returns the next value for `macro` (this works correctly if even `macro` is the same as the macro declaration associated with the context, i.e. the inherited-value case — in this case the result is exactly the same as invoking `nextInheritedValue()`). Returns nil if there is no next value. func nextValueForMacro(_ macro: MacroDeclaration) -> MacroValueAssignment? { - // If it’s the same macro as ours, it’s really just an inheritance lookup. - if macro === self.macro { - return nextInheritedValue() - } - // Otherwise, if we have a parent context, we defer the question to it. - if let parent = self.parent { - return parent.nextValueForMacro(macro) + var currentContext: MacroEvaluationContext = self + while true { + // If it’s the same macro as ours, it’s really just an inheritance lookup. + if macro === currentContext.macro { + return currentContext.nextInheritedValue() + } + // Otherwise, if we have a parent context, we defer the question to it. + if let parent = currentContext.parent { + currentContext = parent + } else { + // If we get this far, we need to look up in our scope’s table. We might or might not find it. + return currentContext.scope.table.lookupMacro(macro, overrideLookup: currentContext.lookup)?.firstMatchingCondition(currentContext.scope.conditionParameterValues) + } } - // If we get this far, we need to look up in our scope’s table. We might or might not find it. - return scope.table.lookupMacro(macro, overrideLookup: lookup)?.firstMatchingCondition(scope.conditionParameterValues) } } diff --git a/Sources/SWBMacro/MacroNamespace.swift b/Sources/SWBMacro/MacroNamespace.swift index ca351f92..eb42c54b 100644 --- a/Sources/SWBMacro/MacroNamespace.swift +++ b/Sources/SWBMacro/MacroNamespace.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import Synchronization /// A namespace represents a set of named macro declarations and (in the future) a set of named macro conditions. MacroNamespace is the starting point for many of the APIs of the macro evaluation subsystem: declaring macros and conditions, parsing macro expressions as strings or string lists, etc. A namespace can reference an underlying namespace — this can be used to share, for example, built-in macro declarations among various projects, while still allowing each project to declare custom macros that don’t interfere with each other. /// diff --git a/Sources/SWBProjectModel/PIFGenerationModel.swift b/Sources/SWBProjectModel/PIFGenerationModel.swift index 8fe09730..975fc22b 100644 --- a/Sources/SWBProjectModel/PIFGenerationModel.swift +++ b/Sources/SWBProjectModel/PIFGenerationModel.swift @@ -980,7 +980,9 @@ public enum PIF { public var IS_ZIPPERED: String? public var KEEP_PRIVATE_EXTERNS: String? public var LD_RUNPATH_SEARCH_PATHS: [String]? + public var LD_WARN_DUPLICATE_LIBRARIES: String? public var LIBRARY_SEARCH_PATHS: [String]? + public var LINKER_DRIVER: String? public var CLANG_COVERAGE_MAPPING_LINKER_ARGS: String? public var CURRENT_PROJECT_VERSION: String? public var MACH_O_TYPE: String? diff --git a/Sources/SWBProtocol/AsyncSequence.swift b/Sources/SWBProtocol/AsyncSequence.swift index 67eea99d..55ac8e6c 100644 --- a/Sources/SWBProtocol/AsyncSequence.swift +++ b/Sources/SWBProtocol/AsyncSequence.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import SWBUtil + extension FixedWidthInteger { public init(protocolEndian value: Self) { self.init(littleEndian: value) diff --git a/Sources/SWBProtocol/Message.swift b/Sources/SWBProtocol/Message.swift index 0b7a406f..c32a01ad 100644 --- a/Sources/SWBProtocol/Message.swift +++ b/Sources/SWBProtocol/Message.swift @@ -416,6 +416,11 @@ public struct ProductTypeSupportsMacCatalystRequest: RequestMessage, Equatable, // MARK: Session Management +public enum DeveloperPath: Sendable, Hashable, Codable { + case xcode(Path) + case swiftToolchain(Path) +} + public struct CreateSessionRequest: RequestMessage, Equatable, SerializableCodable { public typealias ResponseMessage = CreateSessionResponse @@ -423,6 +428,7 @@ public struct CreateSessionRequest: RequestMessage, Equatable, SerializableCodab public let name: String public let developerPath: Path? + public let developerPath2: DeveloperPath? public let resourceSearchPaths: [Path]? public let appPath: Path? public let cachePath: Path? @@ -437,9 +443,10 @@ public struct CreateSessionRequest: RequestMessage, Equatable, SerializableCodab self.init(name: name, developerPath: developerPath, resourceSearchPaths: [], cachePath: cachePath, inferiorProductsPath: inferiorProductsPath, environment: environment) } - public init(name: String, developerPath: Path?, resourceSearchPaths: [Path], cachePath: Path?, inferiorProductsPath: Path?, environment: [String:String]?) { + public init(name: String, developerPath: Path?, resourceSearchPaths: [Path], cachePath: Path?, inferiorProductsPath: Path?, environment: [String:String]?) { // API/ABI compatibility self.name = name self.developerPath = developerPath + self.developerPath2 = nil self.resourceSearchPaths = resourceSearchPaths self.appPath = developerPath?.dirname.dirname self.cachePath = cachePath @@ -447,11 +454,28 @@ public struct CreateSessionRequest: RequestMessage, Equatable, SerializableCodab self.environment = environment } + public init(name: String, developerPath: DeveloperPath?, resourceSearchPaths: [Path], cachePath: Path?, inferiorProductsPath: Path?, environment: [String:String]?) { + self.name = name + self.developerPath2 = developerPath + switch developerPath { + case .xcode(let path), .swiftToolchain(let path): + self.developerPath = path + case nil: + self.developerPath = nil + } + self.resourceSearchPaths = resourceSearchPaths + self.appPath = self.developerPath?.dirname.dirname + self.cachePath = cachePath + self.inferiorProductsPath = inferiorProductsPath + self.environment = environment + } + public init(fromLegacy deserializer: any Deserializer) throws { let count = try deserializer.beginAggregate(4...5) self.name = try deserializer.deserialize() self.appPath = try deserializer.deserialize() self.developerPath = count >= 5 ? try deserializer.deserialize() : appPath?.join("Contents").join("Developer") + self.developerPath2 = nil self.resourceSearchPaths = [] self.cachePath = try deserializer.deserialize() self.inferiorProductsPath = try deserializer.deserialize() diff --git a/Sources/SWBProtocol/PlanningOperationMessages.swift b/Sources/SWBProtocol/PlanningOperationMessages.swift index e9fb3fed..80f3fa91 100644 --- a/Sources/SWBProtocol/PlanningOperationMessages.swift +++ b/Sources/SWBProtocol/PlanningOperationMessages.swift @@ -11,7 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil - +import Foundation // MARK: General planning operation messages diff --git a/Sources/SWBProtocol/ProjectDescriptorTypes.swift b/Sources/SWBProtocol/ProjectDescriptorTypes.swift index 1730cd3a..8b1b51b8 100644 --- a/Sources/SWBProtocol/ProjectDescriptorTypes.swift +++ b/Sources/SWBProtocol/ProjectDescriptorTypes.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// public import SWBUtil +import Foundation public struct SchemeInput: Equatable, Hashable, Serializable, Sendable { public let name: String @@ -448,7 +449,7 @@ public struct ProductDescription: Equatable, Hashable, Serializable, Sendable { /// CLI tools might not have one. public let buildVersion: String? - /// Bitcode + /// Bitcode - no longer supported public let enableBitcode: Bool /// Codesigning @@ -520,7 +521,6 @@ public struct ProductDescription: Equatable, Hashable, Serializable, Sendable { deploymentTarget: Version, marketingVersion: String?, buildVersion: String?, - enableBitcode: Bool, codesign: CodesignMode?, team: String?, infoPlistPath: String?, @@ -536,7 +536,7 @@ public struct ProductDescription: Equatable, Hashable, Serializable, Sendable { self.deploymentTarget = deploymentTarget self.marketingVersion = marketingVersion self.buildVersion = buildVersion - self.enableBitcode = enableBitcode + self.enableBitcode = false self.codesign = codesign self.team = team self.infoPlistPath = infoPlistPath @@ -544,7 +544,7 @@ public struct ProductDescription: Equatable, Hashable, Serializable, Sendable { } public init(from deserializer: any Deserializer) throws { - try deserializer.beginAggregate(15) + try deserializer.beginAggregate(14) self.displayName = try deserializer.deserialize() self.productName = try deserializer.deserialize() self.identifier = try deserializer.deserialize() @@ -557,7 +557,7 @@ public struct ProductDescription: Equatable, Hashable, Serializable, Sendable { self.deploymentTarget = try Version(deploymentTarget) self.marketingVersion = try deserializer.deserialize() self.buildVersion = try deserializer.deserialize() - self.enableBitcode = try deserializer.deserialize() + self.enableBitcode = false let codesign: String? = try deserializer.deserialize() self.codesign = codesign.map { CodesignMode.fromString($0) } self.team = try deserializer.deserialize() @@ -566,7 +566,7 @@ public struct ProductDescription: Equatable, Hashable, Serializable, Sendable { } public func serialize(to serializer: T) { - serializer.beginAggregate(15) + serializer.beginAggregate(14) serializer.serialize(self.displayName) serializer.serialize(self.productName) serializer.serialize(self.identifier) @@ -577,7 +577,6 @@ public struct ProductDescription: Equatable, Hashable, Serializable, Sendable { serializer.serialize(self.deploymentTarget.description) serializer.serialize(self.marketingVersion) serializer.serialize(self.buildVersion) - serializer.serialize(self.enableBitcode) serializer.serialize(self.codesign?.asString()) serializer.serialize(self.team) serializer.serialize(self.infoPlistPath) diff --git a/Sources/SWBQNXPlatform/QNXSDP.swift b/Sources/SWBQNXPlatform/QNXSDP.swift index 1bcddf4e..67a71c49 100644 --- a/Sources/SWBQNXPlatform/QNXSDP.swift +++ b/Sources/SWBQNXPlatform/QNXSDP.swift @@ -39,7 +39,7 @@ struct QNXSDP: Sendable { self.version = try await { if let compilerPath = hostPath?.join("usr").join("bin").join(host.imageFormat.executableName(basename: "qcc")) { - let output = try await Process.getMergedOutput(url: URL(fileURLWithPath: compilerPath.str), arguments: ["-dM", "E", "-x", "c", "-c", Path.null.str], environment: environment) + let output = try await Process.getMergedOutput(url: URL(fileURLWithPath: compilerPath.str), arguments: ["-dM", "E", "-x", "c", "-c", Path.null.str, "-o", Path.null.str], environment: environment) if output.exitStatus.isSuccess, !output.output.isEmpty { let prefix = "#define __QNX__ " if let versionString = String(decoding: output.output, as: UTF8.self).split(separator: "\n").map(String.init).first(where: { $0.hasPrefix(prefix) })?.dropFirst(prefix.count), let version = Int(versionString) { diff --git a/Sources/SWBQNXPlatform/Specs/QNXLd.xcspec b/Sources/SWBQNXPlatform/Specs/QNXLd.xcspec index ec19fdf0..30f9c24b 100644 --- a/Sources/SWBQNXPlatform/Specs/QNXLd.xcspec +++ b/Sources/SWBQNXPlatform/Specs/QNXLd.xcspec @@ -132,6 +132,12 @@ Type = Path; Condition = "NO"; }, + { + // Unsupported + Name = "LD_WARN_DUPLICATE_LIBRARIES"; + Type = Boolean; + Condition = "NO"; + }, { // Don't deduplicate is broken in gold Name = "LD_DONT_RUN_DEDUPLICATION"; diff --git a/Sources/SWBServiceCore/Request.swift b/Sources/SWBServiceCore/Request.swift index 948451ed..25f6725c 100644 --- a/Sources/SWBServiceCore/Request.swift +++ b/Sources/SWBServiceCore/Request.swift @@ -12,6 +12,7 @@ public import SWBProtocol import SWBUtil +import Synchronization /// An individual request made by a service client. /// diff --git a/Sources/SWBTaskConstruction/BuildDirectoryContext.swift b/Sources/SWBTaskConstruction/BuildDirectoryContext.swift index 9cf0821a..6a29ce38 100644 --- a/Sources/SWBTaskConstruction/BuildDirectoryContext.swift +++ b/Sources/SWBTaskConstruction/BuildDirectoryContext.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import SWBUtil +import Synchronization /// Tracks the build directory creation usage across the build plan. This allows the usage information to be cached during task planning. final class BuildDirectoryContext: Sendable { diff --git a/Sources/SWBTaskConstruction/ProductPlanning/BuildPlanDumping.swift b/Sources/SWBTaskConstruction/ProductPlanning/BuildPlanDumping.swift index b60e0b79..a321ccc9 100644 --- a/Sources/SWBTaskConstruction/ProductPlanning/BuildPlanDumping.swift +++ b/Sources/SWBTaskConstruction/ProductPlanning/BuildPlanDumping.swift @@ -12,6 +12,8 @@ package import SWBUtil import SWBCore +import SWBMacro +import Foundation /// Ability to dump the contents of a build plan for diagnostic purposes. package extension BuildPlan { diff --git a/Sources/SWBTaskConstruction/ProductPlanning/ProductPlan.swift b/Sources/SWBTaskConstruction/ProductPlanning/ProductPlan.swift index e52138f1..88d2edfe 100644 --- a/Sources/SWBTaskConstruction/ProductPlanning/ProductPlan.swift +++ b/Sources/SWBTaskConstruction/ProductPlanning/ProductPlan.swift @@ -13,6 +13,8 @@ package import SWBUtil package import SWBCore import SWBMacro +import SWBProtocol +import Foundation /// The `GlobalProductPlanDelegate` is a subset of the more ubiquitous `TaskPlanningDelegate` which provides functionality only needed by a `GlobalProductPlan`, even if it exists outside the context of a build. package protocol GlobalProductPlanDelegate: CoreClientTargetDiagnosticProducingDelegate { @@ -38,7 +40,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider /// /// The array of imparted build properties is ordered so that direct dependencies come first, followed by their direct /// transitive dependencies and so forth. - private var impartedBuildPropertiesByTarget: [ConfiguredTarget: [ImpartedBuildProperties]] + private var impartedBuildPropertiesByTarget: [ConfiguredTarget: [SWBCore.ImpartedBuildProperties]] /// The set of shared intermediate nodes that have been created, keyed by their sharing identifier. /// @@ -48,7 +50,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider let delegate: any GlobalProductPlanDelegate struct VFSContentsKey: Hashable { - let project: Project + let project: SWBCore.Project let effectivePlatformName: String } @@ -118,15 +120,15 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider } /// The mapping of original targets to dynamically building targets because of diamond-style linkage. - private var dynamicallyBuildingTargetsWithDiamondLinkage = [Target:Target]() + private var dynamicallyBuildingTargetsWithDiamondLinkage = [SWBCore.Target: SWBCore.Target]() /// Reverse mapping which allows looking up the corresponding dynamically building target for a static one. - private var staticallyBuildingTargetsWithDiamondLinkage = [Target:Target]() + private var staticallyBuildingTargetsWithDiamondLinkage = [SWBCore.Target: SWBCore.Target]() /// All targets in the product plan which are building dynamically because of diamond-style linkage or because of the client's build request. /// /// Note: currently this will only be package product targets. - package var dynamicallyBuildingTargets: Set { + package var dynamicallyBuildingTargets: Set { return Set(planRequest.buildGraph.dynamicallyBuildingTargets + Array(dynamicallyBuildingTargetsWithDiamondLinkage.keys)) } @@ -213,7 +215,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider self.clientsOfBundlesByTarget = clientsOfBundlesByTarget var directlyLinkedDependenciesByTarget = [ConfiguredTarget:OrderedSet]() - var impartedBuildPropertiesByTarget = [ConfiguredTarget:[ImpartedBuildProperties]]() + var impartedBuildPropertiesByTarget = [ConfiguredTarget:[SWBCore.ImpartedBuildProperties]]() // We can skip computing contributing properties entirely if no target declares any and if there are no package products in the graph. let targetsContributingProperties = planRequest.buildGraph.allTargets.filter { !$0.target.hasImpartedBuildProperties || $0.target.type == .packageProduct } @@ -303,7 +305,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider } // Record the target's products using both TARGET_BUILD_DIR and BUILT_PRODUCTS_DIR. - if let standardTarget = configuredTarget.target as? StandardTarget { + if let standardTarget = configuredTarget.target as? SWBCore.StandardTarget { productPathsToProducingTargets[settings.globalScope.evaluate(BuiltinMacros.TARGET_BUILD_DIR).join(standardTarget.productReference.name).normalize()] = configuredTarget productPathsToProducingTargets[settings.globalScope.evaluate(BuiltinMacros.BUILT_PRODUCTS_DIR).join(standardTarget.productReference.name).normalize()] = configuredTarget } @@ -465,7 +467,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider targetsByCommandLineToolProductPath[executablePath] = configuredTarget } - for scriptPhase in (configuredTarget.target as? BuildPhaseTarget)?.buildPhases.compactMap({ $0 as? ShellScriptBuildPhase }) ?? [] { + for scriptPhase in (configuredTarget.target as? SWBCore.BuildPhaseTarget)?.buildPhases.compactMap({ $0 as? SWBCore.ShellScriptBuildPhase }) ?? [] { for scriptPhaseInput in scriptPhase.inputFilePaths.map({ Path(targetSettings.globalScope.evaluate($0)).normalize() }) { if let producingTarget = targetsByCommandLineToolProductPath[scriptPhaseInput] { targetsRequiredToBuildForIndexing.insert(producingTarget) @@ -699,7 +701,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider continue } - var packageTargetsToSkip = [Target]() + var packageTargetsToSkip = [SWBCore.Target]() // Find all statically linked package products. let linkedPackageProducts = dependencies.filter { @@ -785,7 +787,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider // If we have already emitted an error about a package product, don't emit an error about its targets. var packageTargetsToIgnore = [ConfiguredTarget]() - let updateConfiguration = { (configuredTarget: ConfiguredTarget, dynamicTarget: Target) in + let updateConfiguration = { (configuredTarget: ConfiguredTarget, dynamicTarget: SWBCore.Target) in // If the `targetTaskInfo` for the static target isn't present, we already made the decision to make this target dynamic. if self.targetTaskInfos[configuredTarget] == nil { return } @@ -822,7 +824,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider packageTargetsToIgnore.append(contentsOf: dependenciesByTarget[product]?.map { $0.target } ?? []) let workspaceContext = self.planRequest.workspaceContext - if let packageProductTarget = product.target as? PackageProductTarget, let guid = packageProductTarget.dynamicTargetVariantGuid, let dynamicTarget = workspaceContext.workspace.target(for: guid) { + if let packageProductTarget = product.target as? SWBCore.PackageProductTarget, let guid = packageProductTarget.dynamicTargetVariantGuid, let dynamicTarget = workspaceContext.workspace.target(for: guid) { updateConfiguration(product, dynamicTarget) self.dynamicallyBuildingTargetsWithDiamondLinkage[packageProductTarget] = dynamicTarget } else { @@ -839,7 +841,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider let name = "target '\(target.target.name)'" if let andOther = checkLinkage(for: name, topLevelTargets: topLevelTargets, kind: .target) { let workspaceContext = self.planRequest.workspaceContext - if let standardTarget = target.target as? StandardTarget, let guid = standardTarget.dynamicTargetVariantGuid, let dynamicTarget = workspaceContext.workspace.target(for: guid) { + if let standardTarget = target.target as? SWBCore.StandardTarget, let guid = standardTarget.dynamicTargetVariantGuid, let dynamicTarget = workspaceContext.workspace.target(for: guid) { updateConfiguration(target, dynamicTarget) self.dynamicallyBuildingTargetsWithDiamondLinkage[standardTarget] = dynamicTarget } else { @@ -874,7 +876,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider /// Get the settings to use for an unconfigured target. /// /// This method is intended for use when querying cross-target information where the configuration parameters are not known. In this case, we will use the "best" configured target that we know of, ideally one for the current build. If no configured target is available, we will use one that is configured "as if" the target was building. - func getUnconfiguredTargetSettings(_ target: Target, viewedFrom: ConfiguredTarget) -> Settings { + func getUnconfiguredTargetSettings(_ target: SWBCore.Target, viewedFrom: ConfiguredTarget) -> Settings { // FIXME: Find the "best" configured target. // // FIXME: Make efficient. @@ -951,7 +953,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider /// Construct the module info, if used, for a target. // // FIXME: We should just merge the ModuleInfo with the ProductPlan: [Swift Build] Merge ModuleInfo with ProductPlan - static func computeModuleInfo(workspaceContext: WorkspaceContext, target: Target, settings: Settings, diagnosticHandler: (_ message: String, _ location: Diagnostic.Location, _ component: Component, _ essential: Bool) -> Void) -> ModuleInfo? { + static func computeModuleInfo(workspaceContext: WorkspaceContext, target: SWBCore.Target, settings: Settings, diagnosticHandler: (_ message: String, _ location: Diagnostic.Location, _ component: Component, _ essential: Bool) -> Void) -> ModuleInfo? { let scope = settings.globalScope // If this product type doesn't support modules, do nothing. @@ -977,7 +979,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider // Determine if the target includes Swift, which might contribute to the module definition. let specLookupContext = SpecLookupCtxt(specRegistry: workspaceContext.core.specRegistry, platform: settings.platform) - let buildingAnySwiftSourceFiles = (target as? BuildPhaseTarget)?.sourcesBuildPhase?.containsSwiftSources(workspaceContext.workspace, specLookupContext, scope, settings.filePathResolver) ?? false + let buildingAnySwiftSourceFiles = (target as? SWBCore.BuildPhaseTarget)?.sourcesBuildPhase?.containsSwiftSources(workspaceContext.workspace, specLookupContext, scope, settings.filePathResolver) ?? false // Determine if the target exports its Swift ObjC API. let exportsSwiftObjCAPI = buildingAnySwiftSourceFiles && scope.evaluate(BuiltinMacros.SWIFT_INSTALL_OBJC_HEADER) && !scope.evaluate(BuiltinMacros.SWIFT_OBJC_INTERFACE_HEADER_NAME).isEmpty @@ -1080,7 +1082,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider } /// Determine if `configuredTarget` will generate a module map, and which umbrella header to use. - private static func generatesModuleMap(workspaceContext: WorkspaceContext, target: Target, settings: Settings) -> (Bool, String) { + private static func generatesModuleMap(workspaceContext: WorkspaceContext, target: SWBCore.Target, settings: Settings) -> (Bool, String) { let scope = settings.globalScope // A target generates a module map if DEFINES_MODULE is true, and it has an explicit module map (or contents), or it has an umbrella header. @@ -1092,7 +1094,7 @@ package final class GlobalProductPlan: GlobalTargetInfoProvider if !scope.evaluate(BuiltinMacros.MODULEMAP_FILE).isEmpty { return (true, "") } // Look for an umbrella header to use in a generated module map. - if let buildPhaseTarget = target as? BuildPhaseTarget, let headersBuildPhase = buildPhaseTarget.headersBuildPhase { + if let buildPhaseTarget = target as? SWBCore.BuildPhaseTarget, let headersBuildPhase = buildPhaseTarget.headersBuildPhase { let workspace = workspaceContext.workspace let headerFileTypes = workspaceContext.core.specRegistry.headerFileTypes let moduleName = scope.evaluate(BuiltinMacros.PRODUCT_MODULE_NAME) @@ -1246,7 +1248,7 @@ package final class ProductPlan } private extension ConfiguredTarget { - func getImpartedBuildProperties(using planRequest: BuildPlanRequest) -> ImpartedBuildProperties? { + func getImpartedBuildProperties(using planRequest: BuildPlanRequest) -> SWBCore.ImpartedBuildProperties? { let settings = planRequest.buildRequestContext.getCachedSettings(self.parameters, target: self.target) let defaultConfigurationName = planRequest.workspaceContext.workspace.project(for: self.target).defaultConfigurationName let buildConfiguration = self.target.getEffectiveConfiguration(settings.globalScope.evaluate(BuiltinMacros.CONFIGURATION), defaultConfigurationName: defaultConfigurationName) diff --git a/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift b/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift index 4f63753b..7dd6ef5b 100644 --- a/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift +++ b/Sources/SWBTaskConstruction/ProductPlanning/ProductPlanner.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro @PluginExtensionSystemActor private func taskProducerExtensions(_ workspaceContext: WorkspaceContext) -> [any TaskProducerExtension] { let extensions = workspaceContext.core.pluginManager.extensions(of: TaskProducerExtensionPoint.self) diff --git a/Sources/SWBTaskConstruction/StaleFileRemovalContext.swift b/Sources/SWBTaskConstruction/StaleFileRemovalContext.swift index 7eb5cf6b..3c742681 100644 --- a/Sources/SWBTaskConstruction/StaleFileRemovalContext.swift +++ b/Sources/SWBTaskConstruction/StaleFileRemovalContext.swift @@ -12,6 +12,8 @@ package import SWBCore import SWBUtil +import SWBMacro +import SWBProtocol /// Context of immutable data used to compute stale file removal identifiers for configured targets. package protocol StaleFileRemovalContext { diff --git a/Sources/SWBTaskConstruction/TaskProducerSandboxing.swift b/Sources/SWBTaskConstruction/TaskProducerSandboxing.swift index 9d085f15..802b7c98 100644 --- a/Sources/SWBTaskConstruction/TaskProducerSandboxing.swift +++ b/Sources/SWBTaskConstruction/TaskProducerSandboxing.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro extension TaskProducerContext { func sandbox(builder: inout PlannedTaskBuilder, delegate: any TaskGenerationDelegate) { diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/BuildRuleTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/BuildRuleTaskProducer.swift index 4027b4f9..7874ced4 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/BuildRuleTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/BuildRuleTaskProducer.swift @@ -13,14 +13,15 @@ import SWBUtil import SWBCore import SWBMacro +import SWBProtocol final class BuildRuleTaskProducer: StandardTaskProducer, TaskProducer, ShellBasedTaskProducer { private unowned let action: BuildRuleScriptAction private let cbc: CommandBuildContext private unowned let delegate: any TaskGenerationDelegate - private unowned let buildPhase: BuildPhase + private unowned let buildPhase: SWBCore.BuildPhase - init(_ context: TaskProducerContext, action: BuildRuleScriptAction, cbc: CommandBuildContext, delegate: any TaskGenerationDelegate, buildPhase: BuildPhase) { + init(_ context: TaskProducerContext, action: BuildRuleScriptAction, cbc: CommandBuildContext, delegate: any TaskGenerationDelegate, buildPhase: SWBCore.BuildPhase) { self.action = action self.cbc = cbc self.delegate = delegate @@ -122,7 +123,7 @@ final class BuildRuleTaskProducer: StandardTaskProducer, TaskProducer, ShellBase // If we are in a headers build phase, expose visibility and output dir // information to the script and set the HEADER_OUTPUT_DIR macro value // for output path resolution. - if buildPhase is HeadersBuildPhase { + if buildPhase is SWBCore.HeadersBuildPhase { if let headerVisibility = input.headerVisibility, let outputDir = TargetHeaderInfo.outputPath(for: input.absolutePath, visibility: headerVisibility, scope: cbc.scope)?.dirname { environment["SCRIPT_HEADER_VISIBILITY"] = headerVisibility.rawValue inputVariables[BuiltinMacros.HEADER_OUTPUT_DIR] = outputDir.str diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/CopyFilesTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/CopyFilesTaskProducer.swift index 01364f9c..04b6f569 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/CopyFilesTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/CopyFilesTaskProducer.swift @@ -13,12 +13,14 @@ import SWBCore import SWBUtil import SWBMacro +import SWBProtocol +import Foundation /// Produces tasks for files in a Copy Files build phase in an Xcode target. /// /// Also subclassed by ``SwiftPackageCopyFilesTaskProducer``. class CopyFilesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBasedBuildPhaseTaskProducer { - typealias ManagedBuildPhase = CopyFilesBuildPhase + typealias ManagedBuildPhase = SWBCore.CopyFilesBuildPhase func prepare() { let scope = context.settings.globalScope @@ -237,7 +239,8 @@ class CopyFilesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBasedBui // Determine whether we should re-sign on copy. This is only done if the file-to-build wants it, *and* the file type supports it. let codeSignAfterCopying = ftb.codeSignOnCopy && ftb.fileType.codeSignOnCopy - // Determine whether we should strip bitcode during copying. The default value of STRIP_BITCODE_FROM_COPIED_FILES is set on a per-SDK basis. + // Determine whether we should strip bitcode during copying. + // STRIP_BITCODE_FROM_COPIED_FILES is set to YES for non-simulator embedded platforms, so we don't need to spend time stripping it for other platforms. let stripBitcode = scope.evaluate(BuiltinMacros.STRIP_BITCODE_FROM_COPIED_FILES) && codeSignAfterCopying // SUPPORT FOR MERGEABLE LIBRARIES @@ -323,7 +326,7 @@ class CopyFilesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBasedBui for cTarget in [configuredTarget] + context.globalProductPlan.dependencies(of: configuredTarget) { // FIXME: Perhaps knowing "does this target link this XCFramework" is something that the GlobalProductPlan or XCFrameworkContext should know. var didFindBuildFile = false - if let frameworksBuildPhase = (cTarget.target as? BuildPhaseTarget)?.frameworksBuildPhase { + if let frameworksBuildPhase = (cTarget.target as? SWBCore.BuildPhaseTarget)?.frameworksBuildPhase { for linkedBuildFile in frameworksBuildPhase.buildFiles { // FIXME: This is sketchy: It's using the current context to evaluate a build file in potentially a different target. This might rarely matter since this code only applies to XCFrameworks, but it feels wrong. if let resolvedLinkedBuildFile = try? context.resolveBuildFileReference(linkedBuildFile), resolvedLinkedBuildFile.fileType.identifier == "wrapper.xcframework", resolvedBuildFile.absolutePath == resolvedLinkedBuildFile.absolutePath { diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift index 8a204889..85fdeaa0 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift @@ -14,6 +14,8 @@ public import SWBCore import SWBLibc public import SWBUtil package import SWBMacro +import SWBProtocol +import Foundation /// Convenience initializers for FileToBuild. extension FileToBuild { @@ -40,7 +42,7 @@ extension TaskProducerContext: InputFileGroupingStrategyContext { package final class BuildFilesProcessingContext: BuildFileFilteringContext { package let excludedSourceFileNames: [String] package let includedSourceFileNames: [String] - package let currentPlatformFilter: PlatformFilter? + package let currentPlatformFilter: SWBCore.PlatformFilter? // FIXME: It would be better to have simple heuristics for ordering these groups, but this logic was how the old build system worked. // @@ -273,7 +275,7 @@ final class BuildPhaseFileWarningContext { } // Warn the user if this build phase contains a file reference with a path which is being handled by a build setting. - func emitBuildPhaseFileWarningDiagnostics(buildPhase: BuildPhase, buildFile: BuildFile?, path: Path) { + func emitBuildPhaseFileWarningDiagnostics(buildPhase: SWBCore.BuildPhase, buildFile: SWBCore.BuildFile?, path: Path) { for (settingFilePath, kind) in paths where path == settingFilePath { context.emitBuildPhaseFileWarning(buildPhase: buildPhase, buildFile: buildFile, message: "The \(buildPhase.name) build phase contains this target's \(kind) file '\(settingFilePath.str)'.") } @@ -281,7 +283,7 @@ final class BuildPhaseFileWarningContext { } extension TaskProducerContext { - func emitBuildPhaseFileWarning(buildPhase: BuildPhase, buildFile: BuildFile?, message: String) { + func emitBuildPhaseFileWarning(buildPhase: SWBCore.BuildPhase, buildFile: SWBCore.BuildFile?, message: String) { let diagnosticLocation: Diagnostic.Location if let buildFile, let target = configuredTarget?.target { diagnosticLocation = .buildFile(buildFileGUID: buildFile.guid, buildPhaseGUID: buildPhase.guid, targetGUID: target.guid) @@ -299,10 +301,10 @@ extension TaskProducerContext { /// Protocol for build phase tasks producers which are based around processing file references. protocol FilesBasedBuildPhaseTaskProducer: AnyObject, TaskProducer { /// The type of build phase managed by this producer. - associatedtype ManagedBuildPhase: BuildPhaseWithBuildFiles + associatedtype ManagedBuildPhase: SWBCore.BuildPhaseWithBuildFiles /// The build phase managed by the producer. - var buildPhase: BuildPhaseWithBuildFiles { get } + var buildPhase: SWBCore.BuildPhaseWithBuildFiles { get } /// The managed build phase instance (equivalent to the buildPhase but with the appropriate type). var managedBuildPhase: ManagedBuildPhase { get } @@ -332,7 +334,7 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { } /// The build phase managed by this producer. - unowned let buildPhase: BuildPhaseWithBuildFiles + unowned let buildPhase: SWBCore.BuildPhaseWithBuildFiles /// The map of compilers used during file processing, and the file types they processed. var usedTools = [CommandLineToolSpec: Set]() @@ -344,13 +346,13 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { /// /// - phaseStartNode: A virtual node which should be used as an input for all tasks produced by the phase. /// - phaseEndNode: A virtual node which should be have as inputs all tasks produced by the phase. - init(_ context: TargetTaskProducerContext, buildPhase: BuildPhaseWithBuildFiles, phaseStartNodes: [any PlannedNode], phaseEndNode: any PlannedNode, phaseEndTask: any PlannedTask) { + init(_ context: TargetTaskProducerContext, buildPhase: SWBCore.BuildPhaseWithBuildFiles, phaseStartNodes: [any PlannedNode], phaseEndNode: any PlannedNode, phaseEndTask: any PlannedTask) { self.buildPhase = buildPhase super.init(context, phaseStartNodes: phaseStartNodes, phaseEndNode: phaseEndNode, phaseEndTask: phaseEndTask) } /// Allows subclasses to contribute additional build files. - func additionalBuildFiles(_ scope: MacroEvaluationScope) -> [BuildFile] { + func additionalBuildFiles(_ scope: MacroEvaluationScope) -> [SWBCore.BuildFile] { return [] } @@ -369,13 +371,13 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { // FIXME: We should cache this, for phases which iterate over the build files multiple times. var seenBases = Set() var nonUniqueBases = Set() - typealias ResolvedBuildFile = (buildFile: BuildFile?, buildableReference: Reference?, path: Path, basename: String, fileTypeSpec: FileTypeSpec, shouldUsePrefixHeader: Bool) + typealias ResolvedBuildFile = (buildFile: SWBCore.BuildFile?, buildableReference: SWBCore.Reference?, path: Path, basename: String, fileTypeSpec: FileTypeSpec, shouldUsePrefixHeader: Bool) var resolvedBuildFiles: [ResolvedBuildFile] = [] let buildPhaseFileWarningContext = BuildPhaseFileWarningContext(context, scope) // Helper function for adding a resolved item. The build file can be nil here if the client wants to add a file divorced from any build file (e.g., because the build file contains context which shouldn't be applied to this file). - func addResolvedItem(buildFile: BuildFile?, path: Path, reference: Reference?, fileType: FileTypeSpec, shouldUsePrefixHeader: Bool = true) { + func addResolvedItem(buildFile: SWBCore.BuildFile?, path: Path, reference: SWBCore.Reference?, fileType: FileTypeSpec, shouldUsePrefixHeader: Bool = true) { let base = path.basenameWithoutSuffix.lowercased() if seenBases.contains(base) { nonUniqueBases.insert(base) @@ -403,10 +405,10 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { do { let (reference, path, fileType) = try context.resolveBuildFileReference(buildFile) - let sourceFiles = (self.targetContext.configuredTarget?.target as? StandardTarget)?.sourcesBuildPhase?.buildFiles.count ?? 0 + let sourceFiles = (self.targetContext.configuredTarget?.target as? SWBCore.StandardTarget)?.sourcesBuildPhase?.buildFiles.count ?? 0 if scope.evaluate(BuiltinMacros.ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS) && (sourceFiles > 0) { // Ignore xcassets in Resource Copy Phase since they're now added to the Compile Sources phase for codegen. - if producer.buildPhase is ResourcesBuildPhase && fileType.conformsTo(identifier: "folder.abstractassetcatalog") { + if producer.buildPhase is SWBCore.ResourcesBuildPhase && fileType.conformsTo(identifier: "folder.abstractassetcatalog") { continue } } @@ -418,7 +420,7 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { guard !fileType.conformsTo(identifier: "folder.rkassets") else { continue } // Utility function to unwrap a variant group and add each child as a separate item. - func unwrapResolveAndAdd(variantGroup: VariantGroup, for buildFile: BuildFile) throws { + func unwrapResolveAndAdd(variantGroup: SWBCore.VariantGroup, for buildFile: SWBCore.BuildFile) throws { for childReference in variantGroup.children { let (reference, path, fileType) = try context.resolveBuildFileReference(buildFile, reference: childReference) addResolvedItem(buildFile: buildFile, path: path, reference: reference, fileType: fileType) @@ -431,7 +433,7 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { // If this is a variant group and the file type doesn't expect to be grouped, expand it. // // FIXME: This is a very invasive way of handling the problem that variant groups can be built both as a single item (XIB + resources) or as an exploded list. We should push this higher into the model, or lower down into the actual rule. Or we might be able to just always unwrap if ibtool doesn't need combined compilation anymore. - if let asVariantGroup = reference as? VariantGroup { + if let asVariantGroup = reference as? SWBCore.VariantGroup { // If we're processing a single language for installLoc, then unwrap the variant group into a separate item for each of its child references. if installlocSpecificLanguages { try unwrapResolveAndAdd(variantGroup: asVariantGroup, for: buildFile) @@ -439,8 +441,8 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { else { // If the first item in the variant group is an IB document with Base localization, then we need to handle it specially, since it may contain a mix of IB documents and strings files. // An exception to this is when String Catalogs are in play. - if let baseReference = asVariantGroup.children.first as? FileReference, SpecRegistry.interfaceBuilderDocumentFileTypeIdentifiers.contains(baseReference.fileTypeIdentifier), baseReference.regionVariantName == "Base" { - var ibDocRefs = [FileReference]() // These are specifically override nibs, not including Base. + if let baseReference = asVariantGroup.children.first as? SWBCore.FileReference, SpecRegistry.interfaceBuilderDocumentFileTypeIdentifiers.contains(baseReference.fileTypeIdentifier), baseReference.regionVariantName == "Base" { + var ibDocRefs = [SWBCore.FileReference]() // These are specifically override nibs, not including Base. var hasStringCatalog = false // Iterate over the children of the group - skipping the first reference - to put them into buckets. @@ -449,7 +451,7 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { continue } // FIXME: It's only valid to have a single item in the variant group for any given localization, and we should emit an issue (an error?) about that. (It seems hard to get into that situation other than an SCM merge conflict.) Also maybe emit an issue if there's an item in the group with no localization. - if let fileRef = ref as? FileReference { + if let fileRef = ref as? SWBCore.FileReference { if SpecRegistry.interfaceBuilderDocumentFileTypeIdentifiers.contains(fileRef.fileTypeIdentifier) { // If it's an IB document, then remember it. ibDocRefs.append(fileRef) @@ -568,21 +570,23 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { } } - let sourceFiles = (self.targetContext.configuredTarget?.target as? StandardTarget)?.sourcesBuildPhase?.buildFiles.count ?? 0 - if scope.evaluate(BuiltinMacros.ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS) && (sourceFiles > 0) { - // Process asset catalogs first to workaround issue where generated sources aren't added to main source code group. - // rdar://102834701 (File grouping for 'collection groups' is sensitive to ordering of build phase members) - var assetCatalogBuildFiles = [ResolvedBuildFile]() - var otherBuildFiles = [ResolvedBuildFile]() - for resolvedBuildFile in resolvedBuildFiles { - if resolvedBuildFile.fileTypeSpec.conformsTo(identifier: "folder.abstractassetcatalog") { - assetCatalogBuildFiles.append(resolvedBuildFile) - } - else { - otherBuildFiles.append(resolvedBuildFile) - } + var compileToSwiftFileTypes : [String] = [] + for groupingStragegyExtensions in await context.workspaceContext.core.pluginManager.extensions(of: InputFileGroupingStrategyExtensionPoint.self) { + compileToSwiftFileTypes.append(contentsOf: groupingStragegyExtensions.fileTypesCompilingToSwiftSources()) + } + + // Reorder resolvedBuildFiles so that file types which compile to Swift appear first in the list and so are processed first. + // This is needed because generated sources aren't added to the the main source code list. + // rdar://102834701 (File grouping for 'collection groups' is sensitive to ordering of build phase members) + var compileToSwiftFiles = [ResolvedBuildFile]() + var otherBuildFiles = [ResolvedBuildFile]() + for resolvedBuildFile in resolvedBuildFiles { + if compileToSwiftFileTypes.contains (where: { identifier in resolvedBuildFile.fileTypeSpec.conformsTo(identifier: identifier)}) { + compileToSwiftFiles.append(resolvedBuildFile) + } else { + otherBuildFiles.append(resolvedBuildFile) } - resolvedBuildFiles = assetCatalogBuildFiles + otherBuildFiles + resolvedBuildFiles = compileToSwiftFiles + otherBuildFiles } // Allow subclasses to provide additional content diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ResourcesTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ResourcesTaskProducer.swift index 63369026..222a0ea4 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ResourcesTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ResourcesTaskProducer.swift @@ -13,6 +13,7 @@ import SWBCore import SWBUtil import SWBMacro +import Foundation /// Produces tasks for files in a Copy Resources build phase in an Xcode target. final class ResourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBasedBuildPhaseTaskProducer { diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellBasedTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellBasedTaskProducer.swift index 59949d4d..0bb632e7 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellBasedTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellBasedTaskProducer.swift @@ -13,6 +13,7 @@ import SWBUtil import SWBCore import SWBMacro +import Foundation protocol ShellBasedTaskProducer { func handleFileLists(_ tasks: inout [any PlannedTask], _ inputs: inout [any PlannedNode], _ outputs: inout [any PlannedNode], _ environment: inout [String: String] , _ scope: MacroEvaluationScope, _ inputFileLists: [any PlannedNode], _ outputFileLists: [any PlannedNode], lookup: @escaping ((MacroDeclaration) -> MacroExpression?)) async diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellScriptTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellScriptTaskProducer.swift index c38f4390..c3a86d90 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellScriptTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/ShellScriptTaskProducer.swift @@ -13,12 +13,13 @@ import SWBUtil import SWBCore import SWBMacro +import SWBProtocol final class ShellScriptTaskProducer: PhasedTaskProducer, TaskProducer, ShellBasedTaskProducer { /// The shell script build phase this task producer is working with. - unowned let shellScriptBuildPhase: ShellScriptBuildPhase + unowned let shellScriptBuildPhase: SWBCore.ShellScriptBuildPhase - init(_ context: TargetTaskProducerContext, shellScriptBuildPhase: ShellScriptBuildPhase, phaseStartNodes: [any PlannedNode], phaseEndNode: any PlannedNode, phaseEndTask: any PlannedTask) { + init(_ context: TargetTaskProducerContext, shellScriptBuildPhase: SWBCore.ShellScriptBuildPhase, phaseStartNodes: [any PlannedNode], phaseEndNode: any PlannedNode, phaseEndTask: any PlannedTask) { self.shellScriptBuildPhase = shellScriptBuildPhase super.init(context, phaseStartNodes: phaseStartNodes, phaseEndNode: phaseEndNode, phaseEndTask: phaseEndTask) } @@ -307,7 +308,7 @@ final class ShellScriptTaskProducer: PhasedTaskProducer, TaskProducer, ShellBase /// Construct the tasks for an individual shell-script build rule. /// /// NOTE: External targets are basically shell scripts. It lives here because the behavior shares some significant logical pieces with the behavior of shell script build phases. - static func constructTasksForExternalTarget(_ target: ExternalTarget, _ context: TaskProducerContext, cbc: CommandBuildContext, delegate: any TaskGenerationDelegate) { + static func constructTasksForExternalTarget(_ target: SWBCore.ExternalTarget, _ context: TaskProducerContext, cbc: CommandBuildContext, delegate: any TaskGenerationDelegate) { let action = cbc.scope.evaluate(BuiltinMacros.ACTION) let (executable, arguments, workingDirectory, environment) = constructCommandLine(for: target, action: action, settings: context.settings, workspaceContext: context.workspaceContext, scope: cbc.scope) diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift index f53e8aff..89ecceaa 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SourcesTaskProducer.swift @@ -838,6 +838,10 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase result.append((embedInCodeAccessorResult.fileToBuild, embedInCodeAccessorResult.fileToBuildFileType, /* shouldUsePrefixHeader */ false)) } + if scope.evaluate(BuiltinMacros.GENERATE_TEST_ENTRY_POINT) { + result.append((scope.evaluate(BuiltinMacros.GENERATED_TEST_ENTRY_POINT_PATH), context.lookupFileType(fileName: "sourcecode.swift")!, /* shouldUsePrefixHeader */ false)) + } + return result }()) @@ -1185,7 +1189,7 @@ final class SourcesTaskProducer: FilesBasedBuildPhaseTaskProducerBase, FilesBase let productBinaryPath = scope.evaluate(BuiltinMacros.TARGET_BUILD_DIR).join(scope.evaluate(BuiltinMacros.EXECUTABLE_PATH)) if singleArchBinaryPath != productBinaryPath { await appendGeneratedTasks(&tasks, options: [.linking, .linkingRequirement, .unsignedProductRequirement]) { delegate in - await context.copySpec.constructCopyTasks(CommandBuildContext(producer: context, scope: scope, inputs: [FileToBuild(context: context, absolutePath: singleArchBinaryPath)], output: productBinaryPath, commandOrderingOutputs: [linkedBinaryNode]), delegate, executionDescription: "Copy binary to product", stripUnsignedBinaries: false, stripBitcode: false) + await context.copySpec.constructCopyTasks(CommandBuildContext(producer: context, scope: scope, inputs: [FileToBuild(context: context, absolutePath: singleArchBinaryPath)], output: productBinaryPath, commandOrderingOutputs: [linkedBinaryNode]), delegate, executionDescription: "Copy binary to product", stripUnsignedBinaries: false) } } } diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SwiftPackageCopyFilesTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SwiftPackageCopyFilesTaskProducer.swift index 66e015eb..814cb269 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SwiftPackageCopyFilesTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/SwiftPackageCopyFilesTaskProducer.swift @@ -15,6 +15,7 @@ import class Foundation.FileHandle import SWBCore import SWBUtil +import SWBMacro /// Produces tasks for a runtime-synthesized build phase includes linked frameworks produced by package targets, into non-package targets. final class SwiftPackageCopyFilesTaskProducer: CopyFilesTaskProducer { diff --git a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CopySwiftPackageResourcesTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CopySwiftPackageResourcesTaskProducer.swift index 58ed86aa..1a7938e7 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CopySwiftPackageResourcesTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CopySwiftPackageResourcesTaskProducer.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro /// Task producer for embedding the Swift package resource bundles into an app or framework. final class CopySwiftPackageResourcesTaskProducer: PhasedTaskProducer, TaskProducer { diff --git a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CustomTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CustomTaskProducer.swift index 2d52b24e..57b15e66 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CustomTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/CustomTaskProducer.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro /// A task producer responsible for adding custom tasks specified in the project model to the graph. final class CustomTaskProducer: PhasedTaskProducer, TaskProducer { @@ -37,7 +38,7 @@ final class CustomTaskProducer: PhasedTaskProducer, TaskProducer { if outputs.isEmpty { // If there are no outputs, create a virtual output that can be wired up to gates - let md5Context = MD5Context() + let md5Context = InsecureHashContext() for arg in commandLine { md5Context.add(string: arg) } diff --git a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/DevelopmentAssetsTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/DevelopmentAssetsTaskProducer.swift index e5c0f407..ad2105da 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/DevelopmentAssetsTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/DevelopmentAssetsTaskProducer.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro final class DevelopmentAssetsTaskProducer: StandardTaskProducer, TaskProducer { func generateTasks() async -> [any PlannedTask] { diff --git a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/InfoPlistTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/InfoPlistTaskProducer.swift index d50d3e02..1f740497 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/InfoPlistTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/InfoPlistTaskProducer.swift @@ -13,6 +13,7 @@ import SWBCore import SWBUtil import SWBMacro +import Foundation /// This task producer is responsible for creating tasks which result in the Info.plist file being produced in its final form and location. /// diff --git a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/ProductPostprocessingTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/ProductPostprocessingTaskProducer.swift index bdff7889..d8d82ac0 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/ProductPostprocessingTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/ProductPostprocessingTaskProducer.swift @@ -13,6 +13,8 @@ import SWBCore import SWBUtil import SWBMacro +import SWBProtocol +import Foundation /// Returns an array of build variant-macro evaluation scope pairs for the given scope for a list of build variants. /// - parameter scope: The base scope for which to return the varianted subscopes. @@ -369,10 +371,6 @@ final class ProductPostprocessingTaskProducer: PhasedTaskProducer, TaskProducer // If multiple targets in the build share a product name, they may compute clashing tbd paths in EagerLinkingTBDs. This is rare, so for now we just skip the optimization if it happens. return } - guard !scope.evaluate(BuiltinMacros.ENABLE_BITCODE) || scope.evaluate(BuiltinMacros.BITCODE_GENERATION_MODE) != "bitcode" else { - // If building with full bitcode, the linker will not allow linking against a target's stub, because it doesn't have any. - return - } } context.settings.productType?.addStubAPITasks(self, scope, destination: destination, &tasks) } @@ -774,7 +772,7 @@ private extension ProductTypeSpec { struct FilteringContext: PathResolvingBuildFileFilteringContext { let excludedSourceFileNames: [String] let includedSourceFileNames: [String] - let currentPlatformFilter: PlatformFilter? + let currentPlatformFilter: SWBCore.PlatformFilter? let filePathResolver: FilePathResolver } let filteringContext = FilteringContext( diff --git a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TAPISymbolExtractorTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TAPISymbolExtractorTaskProducer.swift index fe378d01..95b8bf0e 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TAPISymbolExtractorTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TAPISymbolExtractorTaskProducer.swift @@ -14,6 +14,8 @@ import SWBCore import SWBUtil import class SWBCore.DocumentationCompilerSpec import SWBMacro +import SWBProtocol +import Foundation /// A task producer that constructs TAPI Symbol Extraction tasks. /// @@ -181,7 +183,7 @@ final class TAPISymbolExtractorTaskProducer: PhasedTaskProducer, TaskProducer { var headerList: [TAPIFileList.HeaderInfo] = { [headerBuildFiles = documentationHeaderInfo.headerBuildFiles] in let buildFilesContext = BuildFilesProcessingContext(scope) - func computeProductHeader(for fileRef: FileReference, isFramework: Bool, visibility: TAPIFileList.HeaderVisibility, inputNodes: inout [any PlannedNode]) -> TAPIFileList.HeaderInfo? { + func computeProductHeader(for fileRef: SWBCore.FileReference, isFramework: Bool, visibility: TAPIFileList.HeaderVisibility, inputNodes: inout [any PlannedNode]) -> TAPIFileList.HeaderInfo? { // The JSON file should have the product headers, not the source headers, so we need to compute the output path. // FIXME: We should be able to get this info from - or at least share it with - the HeadersTaskProducer. let path = producer.context.settings.filePathResolver.resolveAbsolutePath(fileRef) diff --git a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TargetOrderTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TargetOrderTaskProducer.swift index 5423a898..73850277 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TargetOrderTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/TargetOrderTaskProducer.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro /// Wrapper for capturing the task information needed for the `TargetOrderTaskProducer`. /// diff --git a/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift index 90359ae0..d4c2cd5f 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/TaskProducer.swift @@ -1308,7 +1308,6 @@ extension TaskProducerContext: CommandProducer { scope.evaluate(BuiltinMacros.SWIFT_USE_INTEGRATED_DRIVER) && // Prerequisite for eager linking !SwiftCompilerSpec.shouldUseWholeModuleOptimization(for: scope).result && // off for WMO scope.evaluate(BuiltinMacros.EAGER_LINKING) && // Optimization is currently opt-in via this build setting - scope.evaluate(BuiltinMacros.BITCODE_GENERATION_MODE) != "bitcode" && // Using this optimization is currently unsupported with full bitcode settings.productType?.supportsEagerLinking == true && // The optimization is only valid for supported product types compileSourcesExportOnlySwiftSymbols(scope: scope) && // All exported symbols from compile sources must be from Swift sources !linkedLibrariesMayIntroduceExportedSymbols(scope: scope) // We must not be linking anything that introduces exported symbols diff --git a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/CreateBuildDirectoryTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/CreateBuildDirectoryTaskProducer.swift index 5f3a7676..12cd9961 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/CreateBuildDirectoryTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/CreateBuildDirectoryTaskProducer.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro /// This produces the tasks which create the build directories which are conceptually not part of any target, such as the `SYMROOT`, `OBJROOT` and `DSTROOT`. final class CreateBuildDirectoryTaskProducer: StandardTaskProducer, TaskProducer { diff --git a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/HeadermapVFSTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/HeadermapVFSTaskProducer.swift index 614a4aac..f719ff12 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/HeadermapVFSTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/HeadermapVFSTaskProducer.swift @@ -12,6 +12,9 @@ import SWBCore import SWBUtil +import SWBMacro +import Foundation +import SWBProtocol final class HeadermapVFSTaskProducer: StandardTaskProducer, TaskProducer { @@ -33,7 +36,7 @@ final class HeadermapVFSTaskProducer: StandardTaskProducer, TaskProducer { let vfsContentsByPath = try Dictionary(try await targetContexts.concurrentMap(maximumParallelism: 100) { (targetContext: TaskProducerContext) async throws -> (Path, ByteString)? in let targetScope = targetContext.settings.globalScope let vfsSetting = targetScope.evaluate(BuiltinMacros.CPP_HEADERMAP_PRODUCT_HEADERS_VFS_FILE) - guard targetContext.configuredTarget?.target is StandardTarget, targetScope.evaluate(BuiltinMacros.USE_HEADERMAP), !vfsSetting.isEmpty else { + guard targetContext.configuredTarget?.target is SWBCore.StandardTarget, targetScope.evaluate(BuiltinMacros.USE_HEADERMAP), !vfsSetting.isEmpty else { return nil } let vfsPath = self.context.makeAbsolute(vfsSetting) @@ -80,7 +83,7 @@ extension TaskProducerContext { return try PropertyListItem(vfs.toVFSOverlay()).asJSONFragment() } - func forEachBuildProductToSourceMapping(mapToTempFilesOnly: Bool, _ body: ((target: Target, isActiveTarget: Bool, builtFile: Path, originalSource: Path)) throws -> Void) async rethrows { + func forEachBuildProductToSourceMapping(mapToTempFilesOnly: Bool, _ body: ((target: SWBCore.Target, isActiveTarget: Bool, builtFile: Path, originalSource: Path)) throws -> Void) async rethrows { let index = await workspaceContext.headerIndex @@ -96,7 +99,7 @@ extension TaskProducerContext { let hasEnabledIndexBuildArena = settings.globalScope.evaluate(BuiltinMacros.INDEX_ENABLE_BUILD_ARENA) let effectivePlatformName = settings.globalScope.evaluate(BuiltinMacros.EFFECTIVE_PLATFORM_NAME) - var settingsByTarget: [Target: Settings] = [:] + var settingsByTarget: [SWBCore.Target: Settings] = [:] for configuredTarget in globalProductPlan.allTargets { guard workspaceContext.workspace.project(for: configuredTarget.target) == project else { continue } let settings = globalProductPlan.getTargetSettings(configuredTarget) @@ -147,7 +150,7 @@ extension TaskProducerContext { let privateHeadersFolderPseudoPath = headerDestPaths.privatePath // Add the public and private headers. - func addEntry(_ fileRef: FileReference, installDir: Path) throws { + func addEntry(_ fileRef: SWBCore.FileReference, installDir: Path) throws { // Compute the header path. // // FIXME: This isn't the correct file resolver to use. diff --git a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/IndexBuildVFSDirectoryRemapTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/IndexBuildVFSDirectoryRemapTaskProducer.swift index 31a80a2c..e66b3234 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/IndexBuildVFSDirectoryRemapTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/IndexBuildVFSDirectoryRemapTaskProducer.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import SWBMacro final class IndexBuildVFSDirectoryRemapTaskProducer: StandardTaskProducer, TaskProducer { diff --git a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/PCHModuleMapTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/PCHModuleMapTaskProducer.swift index 53637db0..0a608fe6 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/PCHModuleMapTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/PCHModuleMapTaskProducer.swift @@ -12,6 +12,8 @@ import SWBCore import SWBUtil +import Foundation +import SWBMacro final class PCHModuleMapTaskProducer: StandardTaskProducer, TaskProducer { diff --git a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/XCFrameworkTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/XCFrameworkTaskProducer.swift index e082c7f4..a855ddae 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/XCFrameworkTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/WorkspaceTaskProducers/XCFrameworkTaskProducer.swift @@ -15,6 +15,7 @@ import SWBUtil import struct Foundation.Data import class Foundation.PropertyListDecoder +import SWBMacro /// The XCFrameworkTaskProducer needs to look at a various number of build phases to determine what work actually needs to be done. As part of this, the XCFramework itself needs to be inspected. The matching library within the XCFramework will be copied into the build destination root for later processing by the other build phases, such as the `SourcesBuildPhase`, to handle the linking of the library. final class XCFrameworkTaskProducer: StandardTaskProducer, TaskProducer { diff --git a/Sources/SWBTaskConstruction/XCFrameworkContext.swift b/Sources/SWBTaskConstruction/XCFrameworkContext.swift index a1a34482..bb276ae9 100644 --- a/Sources/SWBTaskConstruction/XCFrameworkContext.swift +++ b/Sources/SWBTaskConstruction/XCFrameworkContext.swift @@ -12,6 +12,7 @@ import SWBCore import SWBUtil +import Synchronization /// Tracks the XCFramework usage across the build plan. This allows the usage information to be cached during task planning. final class XCFrameworkContext: Sendable { diff --git a/Sources/SWBTaskExecution/BuildDescription.swift b/Sources/SWBTaskExecution/BuildDescription.swift index c1b0aa4b..a7de2774 100644 --- a/Sources/SWBTaskExecution/BuildDescription.swift +++ b/Sources/SWBTaskExecution/BuildDescription.swift @@ -18,6 +18,7 @@ package import struct SWBProtocol.BuildOperationTaskEnded package import struct SWBProtocol.TargetDependencyRelationship import class SWBTaskConstruction.ProductPlan package import SWBMacro +import Synchronization /// The delegate for constructing a build description. package protocol BuildDescriptionConstructionDelegate: ActivityReporter { @@ -928,7 +929,7 @@ package final class BuildDescriptionBuilder { } package static func computeShellToolSignature(args: [ByteString], environment: EnvironmentBindings?, dependencyData: DependencyDataStyle?, isUnsafeToInterrupt: Bool, additionalSignatureData: String) -> ByteString { - let ctx = MD5Context() + let ctx = InsecureHashContext() for arg in args { ctx.add(bytes: arg) } diff --git a/Sources/SWBTaskExecution/BuildDescriptionManager.swift b/Sources/SWBTaskExecution/BuildDescriptionManager.swift index 8bd487ec..6dc77926 100644 --- a/Sources/SWBTaskExecution/BuildDescriptionManager.swift +++ b/Sources/SWBTaskExecution/BuildDescriptionManager.swift @@ -20,6 +20,7 @@ package import SWBUtil package import struct SWBProtocol.BuildDescriptionID package import struct SWBProtocol.BuildOperationTaskEnded import SWBMacro +import Synchronization /// An enum describing from where the build description was retrieved, for testing purposes. package enum BuildDescriptionRetrievalSource { @@ -57,7 +58,7 @@ package struct BuildDescriptionRetrievalInfo { } /// Controls the non-deterministic eviction policy of the cache. Note that this is distinct from deterministic _pruning_ (due to TTL or size limits). -package enum BuildDescriptionMemoryCacheEvictionPolicy: Sendable { +package enum BuildDescriptionMemoryCacheEvictionPolicy: Sendable, Hashable { /// Never evict due to memory pressure. case never @@ -104,20 +105,22 @@ package final class BuildDescriptionManager: Sendable { package init(fs: any FSProxy, buildDescriptionMemoryCacheEvictionPolicy: BuildDescriptionMemoryCacheEvictionPolicy, maxCacheSize: (inMemory: Int, onDisk: Int) = (4, 4)) { self.fs = fs - self.inMemoryCachedBuildDescriptions = HeavyCache(maximumSize: maxCacheSize.inMemory, evictionPolicy: { - switch buildDescriptionMemoryCacheEvictionPolicy { - case .never: - .never - case .default(let totalCostLimit): - .default(totalCostLimit: totalCostLimit, willEvictCallback: { buildDescription in - // Capture the path to a local variable so that the buildDescription instance isn't retained by OSLog's autoclosure message parameter. - let packagePath = buildDescription.packagePath - #if canImport(os) - OSLog.log("Evicted cached build description at '\(packagePath.str)'") - #endif - }) - } - }()) + self.inMemoryCachedBuildDescriptions = withHeavyCacheGlobalState(isolated: buildDescriptionMemoryCacheEvictionPolicy == .never) { + HeavyCache(maximumSize: maxCacheSize.inMemory, evictionPolicy: { + switch buildDescriptionMemoryCacheEvictionPolicy { + case .never: + .never + case .default(let totalCostLimit): + .default(totalCostLimit: totalCostLimit, willEvictCallback: { buildDescription in + // Capture the path to a local variable so that the buildDescription instance isn't retained by OSLog's autoclosure message parameter. + let packagePath = buildDescription.packagePath + #if canImport(os) + OSLog.log("Evicted cached build description at '\(packagePath.str)'") + #endif + }) + } + }()) + } self.maxCacheSize = maxCacheSize } @@ -728,7 +731,7 @@ private final class BuildSystemTaskPlanningDelegate: TaskPlanningDelegate { } package func recordAttachment(contents: SWBUtil.ByteString) -> SWBUtil.Path { - let digester = MD5Context() + let digester = InsecureHashContext() digester.add(bytes: contents) let path = descriptionPath.join("attachments").join(digester.signature.asString) do { diff --git a/Sources/SWBTaskExecution/BuildDescriptionSignature.swift b/Sources/SWBTaskExecution/BuildDescriptionSignature.swift index 0a967bfe..c711afae 100644 --- a/Sources/SWBTaskExecution/BuildDescriptionSignature.swift +++ b/Sources/SWBTaskExecution/BuildDescriptionSignature.swift @@ -94,7 +94,7 @@ package struct BuildDescriptionSignatureComponents: Codable, Hashable, Sendable } systemInfo = request.workspaceContext.systemInfo userInfo = request.workspaceContext.userInfo - developerPath = request.workspaceContext.core.developerPath + developerPath = request.workspaceContext.core.developerPath.path xcodeVersionString = request.workspaceContext.core.xcodeVersionString xcodeProductBuildVersionString = request.workspaceContext.core.xcodeProductBuildVersionString buildServiceModTime = request.workspaceContext.core.buildServiceModTime @@ -114,7 +114,7 @@ extension BuildDescriptionSignatureComponents { } func signatureStringValue(humanReadableString: ByteString) -> BuildDescriptionSignature { - let hashContext = MD5Context() + let hashContext = InsecureHashContext() hashContext.add(bytes: humanReadableString) return hashContext.signature } diff --git a/Sources/SWBTaskExecution/DynamicTaskSpecs/ClangModuleDependencyGraph.swift b/Sources/SWBTaskExecution/DynamicTaskSpecs/ClangModuleDependencyGraph.swift index 96217dcd..8cb06e21 100644 --- a/Sources/SWBTaskExecution/DynamicTaskSpecs/ClangModuleDependencyGraph.swift +++ b/Sources/SWBTaskExecution/DynamicTaskSpecs/ClangModuleDependencyGraph.swift @@ -106,7 +106,7 @@ package final class ClangModuleDependencyGraph { /// For example, for a source file, it contains the original command line plus the arguments that configure the /// compilation with explicit modules. For module dependencies, it contains the command line arguments to build /// the pcm file. There may be multiple command lines if a single clang driver invocation expands to multiple jobs - /// for example, when using `-save-temps` or `-fembed-bitcode`. + /// for example, when using `-save-temps`. package let commands: [CompileCommand] package let transitiveIncludeTreeIDs: OrderedSet diff --git a/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingDataPruner.swift b/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingDataPruner.swift index 510a61a9..cd6c44da 100644 --- a/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingDataPruner.swift +++ b/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingDataPruner.swift @@ -14,6 +14,7 @@ package import SWBCore import SWBProtocol package import SWBUtil package import SWBCAS +import Foundation package struct ClangCachingPruneDataTaskKey: Hashable, Serializable, CustomDebugStringConvertible, Sendable { let path: Path @@ -90,7 +91,7 @@ package final class CompilationCachingDataPruner: Sendable { startedAction() let serializer = MsgPackSerializer() key.serialize(to: serializer) - let signatureCtx = MD5Context() + let signatureCtx = InsecureHashContext() signatureCtx.add(string: "ClangCachingPruneData") signatureCtx.add(bytes: serializer.byteString) let signature = signatureCtx.signature @@ -113,12 +114,12 @@ package final class CompilationCachingDataPruner: Sendable { do { let dbSize = try casDBs.getOndiskSize() let sizeLimit = try computeCASSizeLimit(casOptions: casOpts, dbSize: dbSize, fileSystem: fs) - if casOpts.enableDiagnosticRemarks, let dbSize, let sizeLimit, sizeLimit < dbSize { + if let dbSize, let sizeLimit, sizeLimit < dbSize { activityReporter.emit( diagnostic: Diagnostic( - behavior: .remark, + behavior: .note, location: .unknown, - data: DiagnosticData("cache size (\(dbSize)) larger than size limit (\(sizeLimit)") + data: DiagnosticData("cache size (\(dbSize)) larger than size limit (\(sizeLimit))") ), for: activityID, signature: signature @@ -141,6 +142,75 @@ package final class CompilationCachingDataPruner: Sendable { } } + package func pruneCAS( + _ casDBs: SwiftCASDatabases, + key: ClangCachingPruneDataTaskKey, + activityReporter: any ActivityReporter, + fileSystem fs: any FSProxy + ) { + let casOpts = key.casOptions + guard casOpts.limitingStrategy != .discarded else { + return // No need to prune, CAS directory is getting deleted. + } + let inserted = state.withLock { $0.prunedCASes.insert(key).inserted } + guard inserted else { + return // already pruned + } + + startedAction() + let serializer = MsgPackSerializer() + key.serialize(to: serializer) + let signatureCtx = InsecureHashContext() + signatureCtx.add(string: "SwiftCachingPruneData") + signatureCtx.add(bytes: serializer.byteString) + let signature = signatureCtx.signature + + let casPath = casOpts.casPath.str + let swiftscanPath = key.path.str + + // Avoiding the swift concurrency variant because it may lead to starvation when `waitForCompletion()` + // blocks on such tasks. Before using a swift concurrency task here make sure there's no deadlock + // when setting `LIBDISPATCH_COOPERATIVE_POOL_STRICT`. + queue.async { + activityReporter.withActivity( + ruleInfo: "SwiftCachingPruneData \(casPath) \(swiftscanPath)", + executionDescription: "Swift caching pruning \(casPath) using \(swiftscanPath)", + signature: signature, + target: nil, + parentActivity: nil) + { activityID in + let status: BuildOperationTaskEnded.Status + do { + let dbSize = try casDBs.getStorageSize() + let sizeLimit = try computeCASSizeLimit(casOptions: casOpts, dbSize: dbSize.map{Int($0)}, fileSystem: fs) + if let dbSize, let sizeLimit, sizeLimit < dbSize { + activityReporter.emit( + diagnostic: Diagnostic( + behavior: .note, + location: .unknown, + data: DiagnosticData("cache size (\(dbSize)) larger than size limit (\(sizeLimit))") + ), + for: activityID, + signature: signature + ) + } + try casDBs.setSizeLimit(Int64(sizeLimit ?? 0)) + try casDBs.prune() + status = .succeeded + } catch { + activityReporter.emit( + diagnostic: Diagnostic(behavior: .error, location: .unknown, data: DiagnosticData(error.localizedDescription)), + for: activityID, + signature: signature + ) + status = .failed + } + return status + } + self.finishedAction() + } + } + package func pruneCAS( _ toolchainCAS: ToolchainCAS, key: ClangCachingPruneDataTaskKey, @@ -159,7 +229,7 @@ package final class CompilationCachingDataPruner: Sendable { startedAction() let serializer = MsgPackSerializer() key.serialize(to: serializer) - let signatureCtx = MD5Context() + let signatureCtx = InsecureHashContext() signatureCtx.add(string: "ClangCachingPruneData") signatureCtx.add(bytes: serializer.byteString) let signature = signatureCtx.signature @@ -182,12 +252,12 @@ package final class CompilationCachingDataPruner: Sendable { do { let dbSize = (try? toolchainCAS.getOnDiskSize()).map { Int($0) } let sizeLimit = try computeCASSizeLimit(casOptions: casOpts, dbSize: dbSize, fileSystem: fs).map { Int64($0) } - if casOpts.enableDiagnosticRemarks, let dbSize, let sizeLimit, sizeLimit < dbSize { + if let dbSize, let sizeLimit, sizeLimit < dbSize { activityReporter.emit( diagnostic: Diagnostic( - behavior: .remark, + behavior: .note, location: .unknown, - data: DiagnosticData("cache size (\(dbSize)) larger than size limit (\(sizeLimit)") + data: DiagnosticData("cache size (\(dbSize)) larger than size limit (\(sizeLimit))") ), for: activityID, signature: signature diff --git a/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingUploader.swift b/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingUploader.swift index 41d28587..b159d23c 100644 --- a/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingUploader.swift +++ b/Sources/SWBTaskExecution/DynamicTaskSpecs/CompilationCachingUploader.swift @@ -13,6 +13,11 @@ package import SWBCore import SWBProtocol import SWBUtil +import Foundation + +#if canImport(os) +import os +#endif /// Manages uploading compilation caching outputs in the background, when a remote cache is enabled. /// The network tasks are managed using Swift concurrency, without blocking execution lanes @@ -62,7 +67,7 @@ package final class CompilationCachingUploader { } startedUpload() - let signatureCtx = MD5Context() + let signatureCtx = InsecureHashContext() signatureCtx.add(string: "ClangCachingUpload") signatureCtx.add(string: cacheKey) let signature = signatureCtx.signature @@ -77,7 +82,7 @@ package final class CompilationCachingUploader { if enableDiagnosticRemarks { for output in clangCompilation.getOutputs() { activityReporter.emit( - diagnostic: Diagnostic(behavior: .remark, location: .unknown, data: DiagnosticData("uploaded CAS output \(output.name): \(output.casID)")), + diagnostic: Diagnostic(behavior: .note, location: .unknown, data: DiagnosticData("uploaded CAS output \(output.name): \(output.casID)")), for: activityID, signature: signature ) @@ -122,7 +127,7 @@ package final class CompilationCachingUploader { } startedUpload() - let signatureCtx = MD5Context() + let signatureCtx = InsecureHashContext() signatureCtx.add(string: "SwiftCachingUpload") signatureCtx.add(string: cacheKey) let signature = signatureCtx.signature @@ -139,7 +144,7 @@ package final class CompilationCachingUploader { if enableDiagnosticRemarks { for output in try swiftCompilation.getOutputs() { activityReporter.emit( - diagnostic: Diagnostic(behavior: .remark, + diagnostic: Diagnostic(behavior: .note, location: .unknown, data: DiagnosticData("uploaded CAS output \(output.kindName): \(output.casID)")), for: activityID, diff --git a/Sources/SWBTaskExecution/DynamicTaskSpecs/SwiftDriverJobDynamicTaskSpec.swift b/Sources/SWBTaskExecution/DynamicTaskSpecs/SwiftDriverJobDynamicTaskSpec.swift index 605787fe..e01273bc 100644 --- a/Sources/SWBTaskExecution/DynamicTaskSpecs/SwiftDriverJobDynamicTaskSpec.swift +++ b/Sources/SWBTaskExecution/DynamicTaskSpecs/SwiftDriverJobDynamicTaskSpec.swift @@ -242,7 +242,7 @@ final class SwiftDriverJobDynamicTaskSpec: DynamicTaskSpec { // rdar://91295617 (Swift produces empty serialized diagnostics if there are none which is not parseable by clang_loadDiagnostics) return expectedDiagnostics.filter { filePath in do { - let shouldAdd = try fs.exists(filePath) && (try fs.getFileInfo(filePath)).statBuf.st_size > 0 + let shouldAdd = try fs.exists(filePath) && (try fs.getFileSize(filePath)) > 0 return shouldAdd } catch { return false diff --git a/Sources/SWBTaskExecution/ProjectPlanner.swift b/Sources/SWBTaskExecution/ProjectPlanner.swift index 5605b60b..287c35b7 100644 --- a/Sources/SWBTaskExecution/ProjectPlanner.swift +++ b/Sources/SWBTaskExecution/ProjectPlanner.swift @@ -13,6 +13,7 @@ package import SWBCore package import SWBProtocol import SWBUtil +import SWBMacro package struct ProjectPlanner { private let workspaceContext: WorkspaceContext @@ -75,7 +76,7 @@ package struct ProjectPlanner { guard let target = workspaceContext.workspace.target(for: targetIdentifier) else { return nil } let settings = buildRequestContext.getCachedSettings(parameters, target: target) let productName = settings.globalScope.evaluate(BuiltinMacros.PRODUCT_NAME) - return try! ProductDescription(displayName: productName, productName: productName, identifier: productName, productType: .app, dependencies: nil, bundleIdentifier: nil, targetedDeviceFamilies: nil, deploymentTarget: Version("10.10"), marketingVersion: nil, buildVersion: nil, enableBitcode: false, codesign: nil, team: nil, infoPlistPath: nil, iconPath: nil) + return try! ProductDescription(displayName: productName, productName: productName, identifier: productName, productType: .app, dependencies: nil, bundleIdentifier: nil, targetedDeviceFamilies: nil, deploymentTarget: Version("10.10"), marketingVersion: nil, buildVersion: nil, codesign: nil, team: nil, infoPlistPath: nil, iconPath: nil) } } diff --git a/Sources/SWBTaskExecution/TaskActions/AuxiliaryFileTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/AuxiliaryFileTaskAction.swift index d0b4bdb7..72797811 100644 --- a/Sources/SWBTaskExecution/TaskActions/AuxiliaryFileTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/AuxiliaryFileTaskAction.swift @@ -13,6 +13,7 @@ public import SWBUtil import SWBLibc public import SWBCore +import Foundation public final class AuxiliaryFileTaskAction: TaskAction { public override class var toolIdentifier: String { @@ -117,7 +118,7 @@ public final class AuxiliaryFileTaskAction: TaskAction { serializer.serialize(context.logContents) super.serialize(to: serializer) } - let md5 = MD5Context() + let md5 = InsecureHashContext() md5.add(bytes: serializer.byteString) return md5.signature } diff --git a/Sources/SWBTaskExecution/TaskActions/ClangCachingKeyQueryTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ClangCachingKeyQueryTaskAction.swift index be5f3183..40d5ecd5 100644 --- a/Sources/SWBTaskExecution/TaskActions/ClangCachingKeyQueryTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ClangCachingKeyQueryTaskAction.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBCore +import Foundation /// Used only when remote caching is enabled, for remote cache key querying. /// After the task completes, if the remote key is found, the local CAS will @@ -63,7 +64,7 @@ public final class ClangCachingKeyQueryTaskAction: TaskAction { cachedComp = nil } if key.casOptions.enableDiagnosticRemarks { - outputDelegate.remark("cache \(cachedComp != nil ? "hit" : "miss")") + outputDelegate.note("cache \(cachedComp != nil ? "hit" : "miss")") } return .succeeded } catch { diff --git a/Sources/SWBTaskExecution/TaskActions/ClangCachingMaterializeKeyTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ClangCachingMaterializeKeyTaskAction.swift index 1177be3d..8192aa71 100644 --- a/Sources/SWBTaskExecution/TaskActions/ClangCachingMaterializeKeyTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ClangCachingMaterializeKeyTaskAction.swift @@ -13,6 +13,7 @@ public import SWBUtil public import SWBCore public import SWBLLBuild +import Foundation /// Used only when remote caching is enabled, to manage tasks for remote key /// querying and compilation output downloading as dependency tasks. diff --git a/Sources/SWBTaskExecution/TaskActions/ClangCachingOutputMaterializerTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ClangCachingOutputMaterializerTaskAction.swift index 1c66ad7e..b7388e0d 100644 --- a/Sources/SWBTaskExecution/TaskActions/ClangCachingOutputMaterializerTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ClangCachingOutputMaterializerTaskAction.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBCore +import Foundation /// Used only when remote caching is enabled for downloading a compilation output, /// using its ID, into the local CAS. @@ -58,7 +59,7 @@ public final class ClangCachingOutputMaterializerTaskAction: TaskAction { } if obj == nil { if key.casOptions.enableDiagnosticRemarks { - outputDelegate.remark("missing CAS object: \(key.casID)") + outputDelegate.note("missing CAS object: \(key.casID)") } } return .succeeded diff --git a/Sources/SWBTaskExecution/TaskActions/ClangCompileTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ClangCompileTaskAction.swift index d64cc404..5f26bde7 100644 --- a/Sources/SWBTaskExecution/TaskActions/ClangCompileTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ClangCompileTaskAction.swift @@ -14,6 +14,8 @@ import SWBUtil import SWBLibc public import SWBCore public import SWBLLBuild +import Foundation +import SWBProtocol public final class ClangCompileTaskAction: TaskAction, BuildValueValidatingTaskAction { public override class var toolIdentifier: String { @@ -367,10 +369,11 @@ public final class ClangCompileTaskAction: TaskAction, BuildValueValidatingTaskA } guard let cachedComp = try casDBs.getLocalCachedCompilation(cacheKey: cacheKey) else { if enableDiagnosticRemarks { - outputDelegate.remark("cache miss: \(cacheKey)") + outputDelegate.note("cache miss: \(cacheKey)") } outputDelegate.incrementClangCacheMiss() outputDelegate.incrementTaskCounter(.cacheMisses) + outputDelegate.emitOutput("Cache miss\n") return false } @@ -378,23 +381,25 @@ public final class ClangCompileTaskAction: TaskAction, BuildValueValidatingTaskA for output in outputs { guard cachedComp.isOutputMaterialized(output) else { if enableDiagnosticRemarks { - outputDelegate.remark("missing CAS output \(output.name): \(output.casID)") - outputDelegate.remark("cache miss: \(cacheKey)") + outputDelegate.note("missing CAS output \(output.name): \(output.casID)") + outputDelegate.note("cache miss: \(cacheKey)") } outputDelegate.incrementClangCacheMiss() outputDelegate.incrementTaskCounter(.cacheMisses) + outputDelegate.emitOutput("Cache miss\n") return false } } let diagnosticText = try cachedComp.replay(commandLine: command.arguments, workingDirectory: workingDirectory.str) if enableDiagnosticRemarks { - outputDelegate.remark("replayed cache hit: \(cacheKey)") + outputDelegate.note("replayed cache hit: \(cacheKey)") for output in outputs { - outputDelegate.remark("using CAS output \(output.name): \(output.casID)") + outputDelegate.note("using CAS output \(output.name): \(output.casID)") } } outputDelegate.incrementClangCacheHit() outputDelegate.incrementTaskCounter(.cacheHits) + outputDelegate.emitOutput("Cache hit\n") outputDelegate.emitOutput(ByteString(encodingAsUTF8: diagnosticText)) return true } @@ -413,7 +418,7 @@ public final class ClangCompileTaskAction: TaskAction, BuildValueValidatingTaskA guard let cachedComp = try casDBs.getLocalCachedCompilation(cacheKey: cacheKey) else { // This can happen if caching an invocation is skipped due to using date/time macros which makes the output non-deterministic. if enableDiagnosticRemarks { - outputDelegate.remark("compilation was not cached for key: \(cacheKey)") + outputDelegate.note("compilation was not cached for key: \(cacheKey)") } return } diff --git a/Sources/SWBTaskExecution/TaskActions/ClangScanTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ClangScanTaskAction.swift index 5ee3c0e8..d9d7e053 100644 --- a/Sources/SWBTaskExecution/TaskActions/ClangScanTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ClangScanTaskAction.swift @@ -14,6 +14,7 @@ import SWBUtil import SWBLibc public import SWBCore public import enum SWBLLBuild.BuildValueKind +import Foundation public final class ClangScanTaskAction: TaskAction, BuildValueValidatingTaskAction { public override class var toolIdentifier: String { diff --git a/Sources/SWBTaskExecution/TaskActions/ConcatenateTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ConcatenateTaskAction.swift index 3acef5b8..a3669c7f 100644 --- a/Sources/SWBTaskExecution/TaskActions/ConcatenateTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ConcatenateTaskAction.swift @@ -12,6 +12,7 @@ public import SWBCore import SWBUtil +import Foundation public final class ConcatenateTaskAction: TaskAction { public override class var toolIdentifier: String { diff --git a/Sources/SWBTaskExecution/TaskActions/ConstructStubExecutorInputFileListTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ConstructStubExecutorInputFileListTaskAction.swift index 4baef637..ebb79347 100644 --- a/Sources/SWBTaskExecution/TaskActions/ConstructStubExecutorInputFileListTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ConstructStubExecutorInputFileListTaskAction.swift @@ -14,6 +14,7 @@ public import SWBCore import SWBLibc import SWBUtil public import SWBLLBuild +import Foundation /// rdar://125894897 (🚨 fetchOperationServiceEndpoint seems completely broken for app extensions implemented in Swift (SwiftUI: Swift entry point data not found.)) /// diff --git a/Sources/SWBTaskExecution/TaskActions/CopyPlistTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/CopyPlistTaskAction.swift index 470bee7b..3e8f06ea 100644 --- a/Sources/SWBTaskExecution/TaskActions/CopyPlistTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/CopyPlistTaskAction.swift @@ -14,6 +14,7 @@ public import SWBCore import SWBLibc public import SWBUtil import SWBMacro +import Foundation /// Concrete implementation of task for copying a property list file. public final class CopyPlistTaskAction: TaskAction { diff --git a/Sources/SWBTaskExecution/TaskActions/CopyStringsFileTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/CopyStringsFileTaskAction.swift index d85c2ebb..002b2a22 100644 --- a/Sources/SWBTaskExecution/TaskActions/CopyStringsFileTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/CopyStringsFileTaskAction.swift @@ -15,6 +15,7 @@ import Foundation public import SWBCore import SWBLibc public import SWBUtil +import SWBProtocol /// Concrete implementation of task for copying a strings file. public final class CopyStringsFileTaskAction: TaskAction { diff --git a/Sources/SWBTaskExecution/TaskActions/CopyTiffTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/CopyTiffTaskAction.swift index aa1dfa22..cac4975e 100644 --- a/Sources/SWBTaskExecution/TaskActions/CopyTiffTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/CopyTiffTaskAction.swift @@ -13,6 +13,7 @@ public import SWBUtil import SWBLibc public import SWBCore +import Foundation /// Concrete implementation of task for copying a property list file. public final class CopyTiffTaskAction: TaskAction { diff --git a/Sources/SWBTaskExecution/TaskActions/CreateBuildDirectoryTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/CreateBuildDirectoryTaskAction.swift index 72461bf9..10cc6af5 100644 --- a/Sources/SWBTaskExecution/TaskActions/CreateBuildDirectoryTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/CreateBuildDirectoryTaskAction.swift @@ -13,6 +13,7 @@ public import SWBCore import SWBLibc public import SWBUtil +import Foundation public final class CreateBuildDirectoryTaskAction: TaskAction { public override class var toolIdentifier: String { diff --git a/Sources/SWBTaskExecution/TaskActions/DeferredExecutionTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/DeferredExecutionTaskAction.swift index e5fe682c..a0307227 100644 --- a/Sources/SWBTaskExecution/TaskActions/DeferredExecutionTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/DeferredExecutionTaskAction.swift @@ -13,6 +13,8 @@ public import SWBCore import SWBUtil public import SWBLLBuild +import Foundation +import SWBProtocol public final class DeferredExecutionTaskAction: TaskAction { public override class var toolIdentifier: String { diff --git a/Sources/SWBTaskExecution/TaskActions/EmbedSwiftStdLibTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/EmbedSwiftStdLibTaskAction.swift index 1552d691..f2ded2fd 100644 --- a/Sources/SWBTaskExecution/TaskActions/EmbedSwiftStdLibTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/EmbedSwiftStdLibTaskAction.swift @@ -15,7 +15,7 @@ import SWBLibc import SWBUtil import Foundation import struct SWBProtocol.BuildOperationMetrics - +import Synchronization fileprivate func executableFileNameMatchesSwiftRuntimeLibPattern(_ fileName: String) -> Bool { return fileName.hasPrefix("libswift") && fileName.hasSuffix(".dylib") @@ -140,6 +140,7 @@ public final class EmbedSwiftStdLibTaskAction: TaskAction { var shouldPrint = false var shouldCopy = false + // Bitcode is no longer supported, but some old libraries may contain bitcode, so we continue to strip it when directed. var shouldStripBitcode = false var bitcodeStripPath: Path? = nil diff --git a/Sources/SWBTaskExecution/TaskActions/LSRegisterURLTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/LSRegisterURLTaskAction.swift index 80fbae02..93f1d0c4 100644 --- a/Sources/SWBTaskExecution/TaskActions/LSRegisterURLTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/LSRegisterURLTaskAction.swift @@ -12,6 +12,7 @@ import SWBUtil public import SWBCore +import Foundation /// Concrete implementation of task for registering a built app. public final class LSRegisterURLTaskAction: TaskAction { diff --git a/Sources/SWBTaskExecution/TaskActions/ODRAssetPackManifestTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ODRAssetPackManifestTaskAction.swift index 6fcd3ba6..72f1cfb3 100644 --- a/Sources/SWBTaskExecution/TaskActions/ODRAssetPackManifestTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ODRAssetPackManifestTaskAction.swift @@ -17,6 +17,7 @@ import struct Foundation.CharacterSet import struct Foundation.Date import class Foundation.DateFormatter import typealias Foundation.TimeInterval +import SWBMacro public final class ODRAssetPackManifestTaskAction: TaskAction { public override class var toolIdentifier: String { diff --git a/Sources/SWBTaskExecution/TaskActions/ProcessXCFrameworkTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ProcessXCFrameworkTaskAction.swift index 56167f9f..aacfd3fb 100644 --- a/Sources/SWBTaskExecution/TaskActions/ProcessXCFrameworkTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ProcessXCFrameworkTaskAction.swift @@ -13,6 +13,7 @@ public import SWBCore import SWBLibc import SWBUtil +import Foundation /// Performs the processing of a given XCFramework, doing the work to process an individual slice and outputting into a location that can be used during the build. public final class ProcessXCFrameworkTaskAction: TaskAction { diff --git a/Sources/SWBTaskExecution/TaskActions/SwiftCachingKeyQueryTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/SwiftCachingKeyQueryTaskAction.swift index 42fc9a7a..abe3c70f 100644 --- a/Sources/SWBTaskExecution/TaskActions/SwiftCachingKeyQueryTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/SwiftCachingKeyQueryTaskAction.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBCore +import Foundation /// Used only when remote caching is enabled, for remote cache key querying. public final class SwiftCachingKeyQueryTaskAction: TaskAction { @@ -48,7 +49,7 @@ public final class SwiftCachingKeyQueryTaskAction: TaskAction { for cacheKey in key.cacheKeys { let cacheHit = try await cas.queryCacheKey(cacheKey, globally: true) != nil if key.casOptions.enableDiagnosticRemarks { - outputDelegate.remark("cache key query \(cacheHit ? "hit" : "miss")") + outputDelegate.note("cache key query \(cacheHit ? "hit" : "miss")") } guard cacheHit else { // return on first failure. @@ -59,7 +60,7 @@ public final class SwiftCachingKeyQueryTaskAction: TaskAction { guard !key.casOptions.enableStrictCASErrors else { throw error } outputDelegate.warning(error.localizedDescription) if key.casOptions.enableDiagnosticRemarks { - outputDelegate.remark("cache key query failed") + outputDelegate.note("cache key query failed") } } return .succeeded diff --git a/Sources/SWBTaskExecution/TaskActions/SwiftCachingMaterializeKeyTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/SwiftCachingMaterializeKeyTaskAction.swift index ba0ee56e..0883b6f4 100644 --- a/Sources/SWBTaskExecution/TaskActions/SwiftCachingMaterializeKeyTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/SwiftCachingMaterializeKeyTaskAction.swift @@ -13,6 +13,7 @@ public import SWBUtil public import SWBCore public import SWBLLBuild +import Foundation /// Used only when remote caching is enabled, to manage tasks for remote key /// querying and compilation output downloading as dependency tasks. diff --git a/Sources/SWBTaskExecution/TaskActions/SwiftCachingOutputMaterializerTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/SwiftCachingOutputMaterializerTaskAction.swift index 3ed88acd..fd917d34 100644 --- a/Sources/SWBTaskExecution/TaskActions/SwiftCachingOutputMaterializerTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/SwiftCachingOutputMaterializerTaskAction.swift @@ -12,6 +12,7 @@ public import SWBUtil public import SWBCore +import Foundation /// Used only when remote caching is enabled for downloading a compilation output, /// using its ID, into the local CAS. @@ -48,13 +49,13 @@ public final class SwiftCachingOutputMaterializerTaskAction: TaskAction { do { let loaded = try await cas.download(with: key.casID) if !loaded && key.casOptions.enableDiagnosticRemarks { - outputDelegate.remark("cached output \(key.casID) not found") + outputDelegate.note("cached output \(key.casID) not found") } } catch { guard !key.casOptions.enableStrictCASErrors else { throw error } outputDelegate.warning(error.localizedDescription) if key.casOptions.enableDiagnosticRemarks { - outputDelegate.remark("cached output \(key.casID) downloading failed") + outputDelegate.note("cached output \(key.casID) downloading failed") } } return .succeeded diff --git a/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobSchedulingTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobSchedulingTaskAction.swift index cc8c3249..d75cbca8 100644 --- a/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobSchedulingTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobSchedulingTaskAction.swift @@ -14,6 +14,8 @@ import SWBUtil import SWBLibc public import SWBCore public import enum SWBLLBuild.BuildValueKind +import Foundation +import SWBProtocol open class SwiftDriverJobSchedulingTaskAction: TaskAction { public override class var toolIdentifier: String { @@ -137,7 +139,7 @@ open class SwiftDriverJobSchedulingTaskAction: TaskAction { return } - let signatureCtx = MD5Context() + let signatureCtx = InsecureHashContext() signatureCtx.add(string: task.identifier.rawValue) signatureCtx.add(string: "swiftdriverjobdiscoveryactivity") signatureCtx.add(number: dependencyID) diff --git a/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobTaskAction.swift index 5662720d..db56f501 100644 --- a/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/SwiftDriverJobTaskAction.swift @@ -15,6 +15,7 @@ import Foundation public import SWBCore public import SWBUtil public import SWBLLBuild +import SWBProtocol public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTaskAction { public override class var toolIdentifier: String { @@ -164,7 +165,7 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas private var state = State() public override func getSignature(_ task: any ExecutableTask, executionDelegate: any TaskExecutionDelegate) -> ByteString { - let md5 = MD5Context() + let md5 = InsecureHashContext() // We intentionally do not integrate the superclass signature here, because the driver job's signature captures the same information without requiring expensive serialization. md5.add(bytes: driverJob.driverJob.signature) task.environment.computeSignature(into: md5) @@ -493,6 +494,17 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas if let casOpts = payload.casOptions, casOpts.enableIntegratedCacheQueries { let swiftModuleDependencyGraph = dynamicExecutionDelegate.operationContext.swiftModuleDependencyGraph cas = try swiftModuleDependencyGraph.getCASDatabases(casOptions: casOpts, compilerLocation: payload.compilerLocation) + + let casKey = ClangCachingPruneDataTaskKey( + path: payload.compilerLocation.compilerOrLibraryPath, + casOptions: casOpts + ) + dynamicExecutionDelegate.operationContext.compilationCachingDataPruner.pruneCAS( + cas!, + key: casKey, + activityReporter: dynamicExecutionDelegate, + fileSystem: executionDelegate.fs + ) } else { cas = nil } @@ -587,24 +599,24 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas // If any of the key misses, return cache miss. guard let comp = try cas.queryLocalCacheKey(cacheKey) else { if enableDiagnosticRemarks { - outputDelegate.remark("local cache miss for key: \(cacheKey)") + outputDelegate.note("local cache miss for key: \(cacheKey)") } return false } if enableDiagnosticRemarks { - outputDelegate.remark("local cache found for key: \(cacheKey)") + outputDelegate.note("local cache found for key: \(cacheKey)") } // Check all outputs are materialized. // Doing the check immediately after the key allows associating the output remarks with the right key. for output in try comp.getOutputs() { if !output.isMaterialized { if enableDiagnosticRemarks { - outputDelegate.remark("cached output \(output.kindName) not available locally: \(output.casID)") + outputDelegate.note("cached output \(output.kindName) not available locally: \(output.casID)") } return false } if enableDiagnosticRemarks { - outputDelegate.remark("using CAS output \(output.kindName): \(output.casID)") + outputDelegate.note("using CAS output \(output.kindName): \(output.casID)") } } comps.append(comp) @@ -630,14 +642,16 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas let result = try await replayCachedCommandImpl() if enableDiagnosticRemarks { - outputDelegate.remark("replay cache \(result ? "hit" : "miss")") + outputDelegate.note("replay cache \(result ? "hit" : "miss")") } if result { outputDelegate.incrementSwiftCacheHit() outputDelegate.incrementTaskCounter(.cacheHits) + outputDelegate.emitOutput("Cache hit\n") } else { outputDelegate.incrementSwiftCacheMiss() outputDelegate.incrementTaskCounter(.cacheMisses) + outputDelegate.emitOutput("Cache miss\n") } return result } diff --git a/Sources/SWBTaskExecution/TaskActions/SwiftDriverTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/SwiftDriverTaskAction.swift index 171f9fce..864b1f72 100644 --- a/Sources/SWBTaskExecution/TaskActions/SwiftDriverTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/SwiftDriverTaskAction.swift @@ -109,14 +109,9 @@ final public class SwiftDriverTaskAction: TaskAction, BuildValueValidatingTaskAc if let linkerResponseFilePath = driverPayload.linkerResponseFilePath { var responseFileCommandLine: [String] = [] - let plannedBuild = try dependencyGraph.queryPlannedBuild(for: driverPayload.uniqueID) if driverPayload.explicitModulesEnabled { - for job in plannedBuild.explicitModulesPlannedDriverJobs() { - for output in job.driverJob.outputs { - if output.fileExtension == "swiftmodule" { - responseFileCommandLine.append(contentsOf: ["-Wl,-add_ast_path", "-Wl,\(output.str)"]) - } - } + for swiftmodulePath in try dependencyGraph.querySwiftmodulesNeedingRegistrationForDebugging(for: driverPayload.uniqueID) { + responseFileCommandLine.append(contentsOf: ["-Xlinker", "-add_ast_path", "-Xlinker", "\(swiftmodulePath)"]) } } let contents = ByteString(encodingAsUTF8: ResponseFiles.responseFileContents(args: responseFileCommandLine)) diff --git a/Sources/SWBTaskExecution/TaskActions/TaskAction.swift b/Sources/SWBTaskExecution/TaskActions/TaskAction.swift index d18775ff..3fb585d7 100644 --- a/Sources/SWBTaskExecution/TaskActions/TaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/TaskAction.swift @@ -52,7 +52,7 @@ open class TaskAction: PlannedTaskAction, PolymorphicSerializable // FIXME: This is quite inefficient as practically used by the build system, because we end up serializing every task action twice, effectively. We could do a lot better if we were willing to lift this signature out somewhere else, but this is simply and ensures that by default we tend to capture every interesting piece of information in the signature. let sz = MsgPackSerializer() serialize(to: sz) - let md5 = MD5Context() + let md5 = InsecureHashContext() md5.add(bytes: sz.byteString) return md5.signature } @@ -67,7 +67,7 @@ open class TaskAction: PlannedTaskAction, PolymorphicSerializable /// This is checked to determine if the command needs to rebuild versus the last time it was run. open func getSignature(_ task: any ExecutableTask, executionDelegate: any TaskExecutionDelegate) -> ByteString { - let md5 = MD5Context() + let md5 = InsecureHashContext() md5.add(bytes: serializedRepresentationSignature!) for arg in task.commandLine { md5.add(bytes: arg.asByteString) diff --git a/Sources/SWBTaskExecution/TaskActions/ValidateDevelopmentAssetsTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ValidateDevelopmentAssetsTaskAction.swift index 31ae6031..40c7a91c 100644 --- a/Sources/SWBTaskExecution/TaskActions/ValidateDevelopmentAssetsTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ValidateDevelopmentAssetsTaskAction.swift @@ -12,6 +12,7 @@ public import SWBCore import SWBUtil +import SWBMacro public final class ValidateDevelopmentAssetsTaskAction: TaskAction { public override class var toolIdentifier: String { diff --git a/Sources/SWBTaskExecution/TaskActions/ValidateProductTaskAction.swift b/Sources/SWBTaskExecution/TaskActions/ValidateProductTaskAction.swift index 8e7fff22..398f01ee 100644 --- a/Sources/SWBTaskExecution/TaskActions/ValidateProductTaskAction.swift +++ b/Sources/SWBTaskExecution/TaskActions/ValidateProductTaskAction.swift @@ -13,6 +13,8 @@ public import SWBCore import SWBLibc public import SWBUtil +import SWBProtocol +import Foundation /// Concrete implementation of task for validating a a product. public final class ValidateProductTaskAction: TaskAction { diff --git a/Sources/SWBTaskExecution/TaskStore.swift b/Sources/SWBTaskExecution/TaskStore.swift index 615f10df..dc9ff3a2 100644 --- a/Sources/SWBTaskExecution/TaskStore.swift +++ b/Sources/SWBTaskExecution/TaskStore.swift @@ -12,6 +12,7 @@ package import SWBCore package import SWBUtil +import Synchronization package final class TaskStore { package enum Error: Swift.Error { diff --git a/Sources/SWBTestSupport/AssertMatch.swift b/Sources/SWBTestSupport/AssertMatch.swift index f6935eee..f7118634 100644 --- a/Sources/SWBTestSupport/AssertMatch.swift +++ b/Sources/SWBTestSupport/AssertMatch.swift @@ -12,6 +12,7 @@ package import SWBUtil package import Testing +import Synchronization package indirect enum StringPattern: Sendable { /// Matches only the start, when matching a list of inputs. diff --git a/Sources/SWBTestSupport/BuildOperationTester.swift b/Sources/SWBTestSupport/BuildOperationTester.swift index 14d5d249..df0f3878 100644 --- a/Sources/SWBTestSupport/BuildOperationTester.swift +++ b/Sources/SWBTestSupport/BuildOperationTester.swift @@ -19,7 +19,7 @@ package import SWBBuildSystem @_spi(Testing) package import SWBCore package import SWBTaskConstruction package import SWBTaskExecution -package import SWBUtil +@_spi(Testing) package import SWBUtil private import class SWBLLBuild.BuildDB private import class SWBLLBuild.BuildKey @@ -36,6 +36,7 @@ package import struct SWBProtocol.BuildOperationMetrics // FIXME: Workaround: Unable to prefer my own type over NS renamed types package import class SWBTaskExecution.Task +import SWBMacro extension BuildRequest { func with(parameters: BuildParameters, buildTargets: [BuildTargetInfo]) -> BuildRequest { @@ -50,6 +51,8 @@ extension BuildRequest { useDryRun: useDryRun, enableStaleFileRemoval: enableStaleFileRemoval, showNonLoggedProgress: showNonLoggedProgress, + recordBuildBacktraces: recordBuildBacktraces, + generatePrecompiledModulesReport: generatePrecompiledModulesReport, buildDescriptionID: buildDescriptionID, qos: qos, buildPlanDiagnosticsDirPath: buildPlanDiagnosticsDirPath, @@ -628,6 +631,25 @@ package final class BuildOperationTester { return nil } + package func getDiagnosticMessageForTask(_ pattern: StringPattern, kind: DiagnosticKind, task: Task) -> String? { + for (index, event) in self.events.enumerated() { + switch event { + case .taskHadEvent(let eventTask, event: .hadDiagnostic(let diagnostic)) where diagnostic.behavior == kind: + guard eventTask == task else { + continue + } + let message = diagnostic.formatLocalizedDescription(.debugWithoutBehavior, task: eventTask) + if pattern ~= message { + _eventList.remove(at: index) + return message + } + default: + continue + } + } + return nil + } + package func check(_ pattern: StringPattern, kind: BuildOperationTester.DiagnosticKind, failIfNotFound: Bool, sourceLocation: SourceLocation, checkDiagnostic: (Diagnostic) -> Bool) -> Bool { let found = (getDiagnosticMessage(pattern, kind: kind, checkDiagnostic: checkDiagnostic) != nil) if !found, failIfNotFound { @@ -713,6 +735,18 @@ package final class BuildOperationTester { } + package func checkNoTaskWithBacktraces(_ conditions: TaskCondition..., sourceLocation: SourceLocation = #_sourceLocation) { + for matchedTask in findMatchingTasks(conditions) { + Issue.record("found unexpected task matching conditions '\(conditions)', found: \(matchedTask)", sourceLocation: sourceLocation) + + if let frameID = getBacktraceID(matchedTask, sourceLocation: sourceLocation) { + enumerateBacktraces(frameID) { _, category, description in + Issue.record("...", sourceLocation: sourceLocation) + } + } + } + } + /// Check whether the results contains a dependency cycle error. If so, then consume the error and create a `CycleChecking` object and pass it to the block. Otherwise fail. package func checkDependencyCycle(_ pattern: StringPattern, kind: DiagnosticKind = .error, failIfNotFound: Bool = true, sourceLocation: SourceLocation = #_sourceLocation, body: (CycleChecker) async throws -> Void) async throws { guard let message = getDiagnosticMessage(pattern, kind: kind, checkDiagnostic: { _ in true }) else { @@ -1011,8 +1045,21 @@ package final class BuildOperationTester { startedTasks.remove(task) } - package func checkBacktrace(_ identifier: BuildOperationBacktraceFrameEmitted.Identifier, _ patterns: [StringPattern], sourceLocation: SourceLocation = #_sourceLocation) { - var frameDescriptions: [String] = [] + private func getBacktraceID(_ task: Task, sourceLocation: SourceLocation = #_sourceLocation) -> BuildOperationBacktraceFrameEmitted.Identifier? { + guard let frameID: BuildOperationBacktraceFrameEmitted.Identifier = events.compactMap ({ (event) -> BuildOperationBacktraceFrameEmitted.Identifier? in + guard case .emittedBuildBacktraceFrame(identifier: let identifier, previousFrameIdentifier: _, category: _, description: _) = event, case .task(let signature) = identifier, BuildOperationTaskSignature.taskIdentifier(ByteString(encodingAsUTF8: task.identifier.rawValue)) == signature else { + return nil + } + return identifier + // Iff the task is a dynamic task, there may be more than one corresponding frame if it was requested multiple times, in which case we choose the first. Non-dynamic tasks always have a 1-1 relationship with frames. + }).sorted().first else { + Issue.record("Did not find a single build backtrace frame for task: \(task.identifier)", sourceLocation: sourceLocation) + return nil + } + return frameID + } + + private func enumerateBacktraces(_ identifier: BuildOperationBacktraceFrameEmitted.Identifier, _ handleFrameInfo: (_ identifier: BuildOperationBacktraceFrameEmitted.Identifier?, _ category: BuildOperationBacktraceFrameEmitted.Category, _ description: String) -> ()) { var currentFrameID: BuildOperationBacktraceFrameEmitted.Identifier? = identifier while let id = currentFrameID { if let frameInfo: (BuildOperationBacktraceFrameEmitted.Identifier?, BuildOperationBacktraceFrameEmitted.Category, String) = events.compactMap({ (event) -> (BuildOperationBacktraceFrameEmitted.Identifier?, BuildOperationBacktraceFrameEmitted.Category, String)? in @@ -1022,28 +1069,29 @@ package final class BuildOperationTester { return (previousFrameIdentifier, category, description) // Iff the task is a dynamic task, there may be more than one corresponding frame if it was requested multiple times, in which case we choose the first. Non-dynamic tasks always have a 1-1 relationship with frames. }).sorted(by: { $0.0 }).first { - frameDescriptions.append("") + handleFrameInfo(frameInfo.0, frameInfo.1, frameInfo.2) currentFrameID = frameInfo.0 } else { currentFrameID = nil } } + } + + package func checkBacktrace(_ identifier: BuildOperationBacktraceFrameEmitted.Identifier, _ patterns: [StringPattern], sourceLocation: SourceLocation = #_sourceLocation) { + var frameDescriptions: [String] = [] + enumerateBacktraces(identifier) { (_, category, description) in + frameDescriptions.append("") + } XCTAssertMatch(frameDescriptions, patterns, sourceLocation: sourceLocation) } package func checkBacktrace(_ task: Task, _ patterns: [StringPattern], sourceLocation: SourceLocation = #_sourceLocation) { - guard let frameID: BuildOperationBacktraceFrameEmitted.Identifier = events.compactMap ({ (event) -> BuildOperationBacktraceFrameEmitted.Identifier? in - guard case .emittedBuildBacktraceFrame(identifier: let identifier, previousFrameIdentifier: _, category: _, description: _) = event, case .task(let signature) = identifier, BuildOperationTaskSignature.taskIdentifier(ByteString(encodingAsUTF8: task.identifier.rawValue)) == signature else { - return nil - } - return identifier - // Iff the task is a dynamic task, there may be more than one corresponding frame if it was requested multiple times, in which case we choose the first. Non-dynamic tasks always have a 1-1 relationship with frames. - }).sorted().first else { - Issue.record("Did not find a single build backtrace frame for task: \(task.identifier)", sourceLocation: sourceLocation) - return + if let frameID = getBacktraceID(task, sourceLocation: sourceLocation) { + checkBacktrace(frameID, patterns, sourceLocation: sourceLocation) + } else { + // already recorded an issue } - checkBacktrace(frameID, patterns, sourceLocation: sourceLocation) } private class TaskDependencyResolver { @@ -1520,7 +1568,7 @@ package final class BuildOperationTester { func body(results: BuildResults) throws -> Void { results.consumeTasksMatchingRuleTypes(excludedTasks) - results.checkNoTask(sourceLocation: sourceLocation) + results.checkNoTaskWithBacktraces(sourceLocation: sourceLocation) results.checkNote(.equal("Building targets in dependency order"), failIfNotFound: false) results.checkNote(.prefix("Target dependency graph"), failIfNotFound: false) @@ -1546,7 +1594,9 @@ package final class BuildOperationTester { } } - try await checkBuild(name, parameters: parameters, runDestination: runDestination, buildRequest: inputBuildRequest, buildCommand: buildCommand, schemeCommand: schemeCommand, persistent: persistent, serial: serial, buildOutputMap: buildOutputMap, signableTargets: signableTargets, signableTargetInputs: signableTargetInputs, clientDelegate: clientDelegate, sourceLocation: sourceLocation, body: body) + try await UserDefaults.withEnvironment(["EnableBuildBacktraceRecording": "true"]) { + try await checkBuild(name, parameters: parameters, runDestination: runDestination, buildRequest: inputBuildRequest, buildCommand: buildCommand, schemeCommand: schemeCommand, persistent: persistent, serial: serial, buildOutputMap: buildOutputMap, signableTargets: signableTargets, signableTargetInputs: signableTargetInputs, clientDelegate: clientDelegate, sourceLocation: sourceLocation, body: body) + } } package static func buildRequestForIndexOperation( diff --git a/Sources/SWBTestSupport/CoreBasedTests.swift b/Sources/SWBTestSupport/CoreBasedTests.swift index 93d8b80f..2ab4fe1d 100644 --- a/Sources/SWBTestSupport/CoreBasedTests.swift +++ b/Sources/SWBTestSupport/CoreBasedTests.swift @@ -183,13 +183,13 @@ extension CoreBasedTests { package var actoolPath: Path { get async throws { - try await getCore().developerPath.join("usr/bin/actool") + try await getCore().developerPath.path.join("usr/bin/actool") } } package var ibtoolPath: Path { get async throws { - try await getCore().developerPath.join("usr/bin/ibtool") + try await getCore().developerPath.path.join("usr/bin/ibtool") } } diff --git a/Sources/SWBTestSupport/CoreTestSupport.swift b/Sources/SWBTestSupport/CoreTestSupport.swift index 6621beb1..356345fa 100644 --- a/Sources/SWBTestSupport/CoreTestSupport.swift +++ b/Sources/SWBTestSupport/CoreTestSupport.swift @@ -15,6 +15,7 @@ private import Foundation package import SWBUtil import SWBTaskConstruction import SWBTaskExecution +import SWBServiceCore #if USE_STATIC_PLUGIN_INITIALIZATION private import SWBAndroidPlatform @@ -33,11 +34,11 @@ extension Core { /// This core is uninitialized, and is not expected to be suitable for general use. It is useful for performance testing specific parts of the Core loading mechanisms. static func createTestingCore() async throws -> (Core, [Diagnostic]) { let hostOperatingSystem = try ProcessInfo.processInfo.hostOperatingSystem() - let developerPath: String + let developerPath: Core.DeveloperPath if hostOperatingSystem == .macOS { - developerPath = try await Xcode.getActiveDeveloperDirectoryPath().str + developerPath = .xcode(try await Xcode.getActiveDeveloperDirectoryPath()) } else { - developerPath = "/" + developerPath = .fallback(Path.root) } let delegate = TestingCoreDelegate() return await (try Core(delegate: delegate, hostOperatingSystem: hostOperatingSystem, pluginManager: PluginManager(skipLoadingPluginIdentifiers: []), developerPath: developerPath, resourceSearchPaths: [], inferiorProductsPath: nil, additionalContentPaths: [], environment: [:], buildServiceModTime: Date(), connectionMode: .inProcess), delegate.diagnostics) @@ -50,15 +51,15 @@ extension Core { // When this code is being loaded directly via unit tests, find the running Xcode path. // // This is a "well known" launch parameter set in Xcode's schemes. - let developerPath: Path? + let developerPath: DeveloperPath? if let xcodeDeveloperDirPath = getEnvironmentVariable("XCODE_DEVELOPER_DIR_PATH").map(Path.init) { - developerPath = xcodeDeveloperDirPath + developerPath = .xcode(xcodeDeveloperDirPath) } else { // In the context of auto-generated package schemes, try to infer the active Xcode. let potentialDeveloperPath = getEnvironmentVariable("PATH")?.components(separatedBy: String(Path.pathEnvironmentSeparator)).first.map(Path.init)?.dirname.dirname let versionInfo = potentialDeveloperPath?.dirname.join("version.plist") if let versionInfo = versionInfo, (try? PropertyList.fromPath(versionInfo, fs: localFS))?.dictValue?["ProjectName"] == "IDEApplication" { - developerPath = potentialDeveloperPath + developerPath = potentialDeveloperPath.map { .xcode($0) } } else { developerPath = nil } @@ -89,6 +90,7 @@ extension Core { pluginManager.registerExtensionPoint(EnvironmentExtensionPoint()) pluginManager.registerExtensionPoint(InputFileGroupingStrategyExtensionPoint()) pluginManager.registerExtensionPoint(TaskProducerExtensionPoint()) + pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) pluginManager.registerExtensionPoint(DiagnosticToolingExtensionPoint()) pluginManager.registerExtensionPoint(SDKVariantInfoExtensionPoint()) pluginManager.registerExtensionPoint(FeatureAvailabilityExtensionPoint()) diff --git a/Sources/SWBTestSupport/DiagnosticsCheckingResult.swift b/Sources/SWBTestSupport/DiagnosticsCheckingResult.swift index 57aadbd9..07cb6501 100644 --- a/Sources/SWBTestSupport/DiagnosticsCheckingResult.swift +++ b/Sources/SWBTestSupport/DiagnosticsCheckingResult.swift @@ -202,7 +202,7 @@ package func _filterDiagnostic(message: String) -> String? { return nil } - if message.hasPrefix("Enabling the Swift language feature 'MemberImportVisibility' is recommended") { + if message.hasPrefix("Enabling the Swift language feature 'MemberImportVisibility' will become a requirement in the future") { return nil } diff --git a/Sources/SWBTestSupport/DummyCommandProducer.swift b/Sources/SWBTestSupport/DummyCommandProducer.swift index fa378654..de335df2 100644 --- a/Sources/SWBTestSupport/DummyCommandProducer.swift +++ b/Sources/SWBTestSupport/DummyCommandProducer.swift @@ -59,8 +59,18 @@ package struct MockCommandProducer: CommandProducer, Sendable { for path in platform?.executableSearchPaths.paths ?? [] { paths.append(path) } - paths.append(core.developerPath.join("usr").join("bin")) - paths.append(core.developerPath.join("usr").join("local").join("bin")) + switch core.developerPath { + case .xcode(let path), .fallback(let path): + paths.append(path.join("usr").join("bin")) + paths.append(path.join("usr").join("local").join("bin")) + case .swiftToolchain(let path, xcodeDeveloperPath: let xcodeDeveloperPath): + paths.append(path.join("usr").join("bin")) + paths.append(path.join("usr").join("local").join("bin")) + if let xcodeDeveloperPath { + paths.append(xcodeDeveloperPath.join("usr").join("bin")) + paths.append(xcodeDeveloperPath.join("usr").join("local").join("bin")) + } + } } self.executableSearchPaths = StackedSearchPath(paths: [Path](paths), fs: fs) self.toolchains = toolchain.map { [$0] } ?? [] diff --git a/Sources/SWBTestSupport/LibraryGeneration.swift b/Sources/SWBTestSupport/LibraryGeneration.swift index 69a6e758..02cc269d 100644 --- a/Sources/SWBTestSupport/LibraryGeneration.swift +++ b/Sources/SWBTestSupport/LibraryGeneration.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// package import SWBUtil +import Foundation /// Helpers for creating frameworks and libraries for use in unit tests. extension InstalledXcode { diff --git a/Sources/SWBTestSupport/Misc.swift b/Sources/SWBTestSupport/Misc.swift index 40f39073..85394475 100644 --- a/Sources/SWBTestSupport/Misc.swift +++ b/Sources/SWBTestSupport/Misc.swift @@ -196,36 +196,6 @@ extension ProcessInfo { return false } - /// Whether the process is running translated, e.g. using Rosetta on macOS, or Prism on Windows. - package var isTranslated: Bool { - #if os(Windows) - var pProcessMachine = USHORT(IMAGE_FILE_MACHINE_UNKNOWN) - var pNativeMachine = USHORT(IMAGE_FILE_MACHINE_UNKNOWN) - guard IsWow64Process2(GetCurrentProcess(), &pProcessMachine, &pNativeMachine) else { - return false - } - // Checking of specific architectures is a bit fragile, but we only support AMD64 and ARM64 on Windows for now. - guard pNativeMachine == IMAGE_FILE_MACHINE_ARM64 else { - return false - } - var systemInfo = SYSTEM_INFO() - GetNativeSystemInfo(&systemInfo) - return systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 - #elseif canImport(Darwin) - let sysctl_proc_translated = "sysctl.proc_translated" - var len: Int = 0 - if sysctlbyname(sysctl_proc_translated, nil, &len, nil, 0) == 0 { - var p = [CChar](repeating: 0, count: len) - if len > 0 && sysctlbyname(sysctl_proc_translated, &p, &len, nil, 0) == 0 { - return p[0] == 1 - } - } - return false - #else - return false - #endif - } - // Get memory usage of current process in bytes package var memoryUsage: UInt64 { #if canImport(Darwin) diff --git a/Sources/SWBTestSupport/SkippedTestSupport.swift b/Sources/SWBTestSupport/SkippedTestSupport.swift index 3634c891..d6ee26e5 100644 --- a/Sources/SWBTestSupport/SkippedTestSupport.swift +++ b/Sources/SWBTestSupport/SkippedTestSupport.swift @@ -115,15 +115,17 @@ extension Trait where Self == Testing.ConditionTrait { package static func requireSDKs(_ knownSDKs: KnownSDK..., comment: Comment? = nil) -> Self { enabled(comment != nil ? "required SDKs are not installed: \(comment?.description ?? "")" : "required SDKs are not installed.", { let sdkRegistry = try await ConditionTraitContext.shared.getCore().sdkRegistry - let missingSDKs = await knownSDKs.asyncFilter { sdkRegistry.lookup($0.sdkName) == nil }.sorted() + let missingSDKs = await knownSDKs.asyncFilter { knownSDK in + sdkRegistry.lookup(knownSDK.sdkName) == nil && sdkRegistry.allSDKs.count(where: { $0.aliases.contains(knownSDK.sdkName) }) == 0 + }.sorted() return missingSDKs.isEmpty }) } /// Constructs a condition trait that causes a test to be disabled if not running on the specified host OS. /// - parameter when: An additional constraint to apply such that the host OS requirement is only applied if this parameter is _also_ true. Defaults to true. - package static func requireHostOS(_ os: OperatingSystem, when condition: Bool = true) -> Self { - enabled("This test requires a \(os) host OS.", { try ProcessInfo.processInfo.hostOperatingSystem() == os && condition }) + package static func requireHostOS(_ os: OperatingSystem..., when condition: Bool = true) -> Self { + enabled("This test requires a \(os) host OS.", { os.contains(try ProcessInfo.processInfo.hostOperatingSystem()) && condition }) } /// Constructs a condition trait that causes a test to be disabled if running on the specified host OS. @@ -136,6 +138,13 @@ extension Trait where Self == Testing.ConditionTrait { disabled("Process spawning is unavailable.", { try ProcessInfo.processInfo.hostOperatingSystem().isAppleEmbedded || ProcessInfo.processInfo.isMacCatalystApp }) } + /// Constructs a condition trait that causes a test to be disabled if the developer directory is pointing at an Xcode developer directory. + package static var skipXcodeToolchain: Self { + disabled("This test is incompatible with Xcode toolchains.", { + try await ConditionTraitContext.shared.getCore().developerPath.path.str.contains(".app/Contents/Developer") + }) + } + /// Constructs a condition trait that causes a test to be disabled if the Foundation process spawning implementation is not using `posix_spawn_file_actions_addchdir`. package static var requireThreadSafeWorkingDirectory: Self { disabled("Thread-safe process working directory support is unavailable.", { @@ -321,7 +330,7 @@ extension Trait where Self == Testing.ConditionTrait { extension Trait where Self == Testing.ConditionTrait { package static var skipDeveloperDirectoryWithEqualSign: Self { disabled { - try await ConditionTraitContext.shared.getCore().developerPath.str.contains("=") + try await ConditionTraitContext.shared.getCore().developerPath.path.str.contains("=") } } @@ -399,7 +408,7 @@ extension Trait where Self == Testing.ConditionTrait { package func casOptions() async throws -> (canUseCASPlugin: Bool, canUseCASPruning: Bool, canCheckCASUpToDate: Bool) { let libclang = try #require(try await ConditionTraitContext.shared.libclang) let core = try await ConditionTraitContext.shared.getCore() - let canUseCASPlugin = libclang.supportsCASPlugin && localFS.exists(core.developerPath.join("usr/lib/libToolchainCASPlugin.dylib")) + let canUseCASPlugin = libclang.supportsCASPlugin && localFS.exists(core.developerPath.path.join("usr/lib/libToolchainCASPlugin.dylib")) let canUseCASPruning = libclang.supportsCASPruning let canCheckCASUpToDate = libclang.supportsCASUpToDateChecks return (canUseCASPlugin, canUseCASPruning, canCheckCASUpToDate) diff --git a/Sources/SWBTestSupport/TaskConstructionTester.swift b/Sources/SWBTestSupport/TaskConstructionTester.swift index b65cc9e7..48816c10 100644 --- a/Sources/SWBTestSupport/TaskConstructionTester.swift +++ b/Sources/SWBTestSupport/TaskConstructionTester.swift @@ -17,6 +17,8 @@ package import struct SWBProtocol.RunDestinationInfo package import SWBTaskConstruction import SWBTaskExecution package import Testing +import SWBMacro +import Foundation /// Helper class for testing task construction. package final class TaskConstructionTester { diff --git a/Sources/SWBTestSupport/TaskExecutionTestSupport.swift b/Sources/SWBTestSupport/TaskExecutionTestSupport.swift index 73a1a011..0fc3b973 100644 --- a/Sources/SWBTestSupport/TaskExecutionTestSupport.swift +++ b/Sources/SWBTestSupport/TaskExecutionTestSupport.swift @@ -17,6 +17,7 @@ package import SWBUtil package import struct SWBProtocol.BuildDescriptionID package import struct SWBProtocol.BuildOperationTaskEnded package import struct SWBProtocol.TargetDependencyRelationship +import Synchronization /// An empty delegate implementation. package final class MockTestBuildDescriptionConstructionDelegate: BuildDescriptionConstructionDelegate, Sendable { diff --git a/Sources/SWBTestSupport/TaskPlanningTestSupport.swift b/Sources/SWBTestSupport/TaskPlanningTestSupport.swift index 806593ef..ae67ca1c 100644 --- a/Sources/SWBTestSupport/TaskPlanningTestSupport.swift +++ b/Sources/SWBTestSupport/TaskPlanningTestSupport.swift @@ -18,6 +18,8 @@ import SWBTaskExecution package import SWBUtil import Testing package import SWBMacro +import Foundation +import Synchronization extension PlannedTask { package var dependencyData: DependencyDataStyle? { @@ -316,7 +318,7 @@ package class TestTaskPlanningDelegate: TaskPlanningDelegate, @unchecked Sendabl } package func recordAttachment(contents: SWBUtil.ByteString) -> SWBUtil.Path { - let digester = MD5Context() + let digester = InsecureHashContext() digester.add(bytes: contents) if let path = tmpDir?.path.join(digester.signature.asString) { do { diff --git a/Sources/SWBTestSupport/TestWorkspaces.swift b/Sources/SWBTestSupport/TestWorkspaces.swift index dbafde17..c225eb2c 100644 --- a/Sources/SWBTestSupport/TestWorkspaces.swift +++ b/Sources/SWBTestSupport/TestWorkspaces.swift @@ -273,6 +273,8 @@ package final class TestFile: TestInternalStructureItem, CustomStringConvertible return "text.json.xcstrings" case ".swift": return "sourcecode.swift" + case ".tbd": + return "sourcecode.text-based-dylib-definition" case ".tif", ".tiff": return "image.tiff" case ".txt": diff --git a/Sources/SWBTestSupport/XCFrameworkTestSupport.swift b/Sources/SWBTestSupport/XCFrameworkTestSupport.swift index 81df4b61..6b0e9267 100644 --- a/Sources/SWBTestSupport/XCFrameworkTestSupport.swift +++ b/Sources/SWBTestSupport/XCFrameworkTestSupport.swift @@ -81,13 +81,6 @@ package enum XCFrameworkTestSupport: Sendable { try fs.createDirectory(targetPath, recursive: true) try fs.write(targetPath.join(lib.libraryPath.str + ".dSYM"), contents: "fake dsym!") } - - // Just create some fake bitcode symbol maps for when the library has them. - if let bitcodeSymbolMapsPath = lib.bitcodeSymbolMapsPath { - let targetPath = libRoot.join(bitcodeSymbolMapsPath) - try fs.createDirectory(targetPath, recursive: true) - try fs.write(targetPath.join(lib.libraryPath.str + ".bcsymbolmap"), contents: "fake symbol map!") - } } } diff --git a/Sources/SWBUniversalPlatform/CMakeLists.txt b/Sources/SWBUniversalPlatform/CMakeLists.txt index 0ca2f13c..f331ab96 100644 --- a/Sources/SWBUniversalPlatform/CMakeLists.txt +++ b/Sources/SWBUniversalPlatform/CMakeLists.txt @@ -34,11 +34,17 @@ add_library(SWBUniversalPlatform STATIC CppTool.swift DiffTool.swift LexCompiler.swift + TestEntryPointGenerationTaskAction.swift + TestEntryPointGenerationTool.swift + TestEntryPointTaskProducer.swift YaccCompiler.swift Plugin.swift) target_link_libraries(SWBUniversalPlatform PUBLIC SWBCore SWBMacro - SWBUtil) + SWBUtil + SWBTaskConstruction + SWBTaskExecution + ArgumentParser) target_sources(SWBUniversalPlatform PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource_bundle_accessor.swift") diff --git a/Sources/SWBUniversalPlatform/CopyPlistFile.swift b/Sources/SWBUniversalPlatform/CopyPlistFile.swift index c0aa9322..506cf6e3 100644 --- a/Sources/SWBUniversalPlatform/CopyPlistFile.swift +++ b/Sources/SWBUniversalPlatform/CopyPlistFile.swift @@ -12,6 +12,7 @@ import SWBMacro import SWBCore +import SWBUtil final class CopyPlistFileSpec: GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { static let identifier = "com.apple.build-tasks.copy-plist-file" diff --git a/Sources/SWBUniversalPlatform/CopyStringsFile.swift b/Sources/SWBUniversalPlatform/CopyStringsFile.swift index e05bd4a9..21fbbdc2 100644 --- a/Sources/SWBUniversalPlatform/CopyStringsFile.swift +++ b/Sources/SWBUniversalPlatform/CopyStringsFile.swift @@ -13,6 +13,7 @@ import SWBUtil import SWBMacro import SWBCore +import Foundation final class CopyStringsFileSpec: GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { static let identifier = "com.apple.build-tasks.copy-strings-file" diff --git a/Sources/SWBUniversalPlatform/DiffTool.swift b/Sources/SWBUniversalPlatform/DiffTool.swift index c5c1b90f..18122950 100644 --- a/Sources/SWBUniversalPlatform/DiffTool.swift +++ b/Sources/SWBUniversalPlatform/DiffTool.swift @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// import SWBCore +import SWBMacro +import SWBUtil final class DiffToolSpec: CommandLineToolSpec, SpecImplementationType, @unchecked Sendable { static let identifier = "com.apple.build-tools.diff" diff --git a/Sources/SWBUniversalPlatform/LexCompiler.swift b/Sources/SWBUniversalPlatform/LexCompiler.swift index 27190482..2c1cb199 100644 --- a/Sources/SWBUniversalPlatform/LexCompiler.swift +++ b/Sources/SWBUniversalPlatform/LexCompiler.swift @@ -12,6 +12,7 @@ import SWBUtil import SWBCore +import SWBMacro final class LexCompilerSpec : CompilerSpec, SpecIdentifierType, @unchecked Sendable { static let identifier = "com.apple.compilers.lex" diff --git a/Sources/SWBUniversalPlatform/Plugin.swift b/Sources/SWBUniversalPlatform/Plugin.swift index bd278de3..b50a687c 100644 --- a/Sources/SWBUniversalPlatform/Plugin.swift +++ b/Sources/SWBUniversalPlatform/Plugin.swift @@ -13,9 +13,13 @@ public import SWBUtil import SWBCore import Foundation +import SWBTaskConstruction +import SWBTaskExecution @PluginExtensionSystemActor public func initializePlugin(_ manager: PluginManager) { manager.register(UniversalPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) + manager.register(UniversalPlatformTaskProducerExtension(), type: TaskProducerExtensionPoint.self) + manager.register(UniversalPlatformTaskActionExtension(), type: TaskActionExtensionPoint.self) } struct UniversalPlatformSpecsExtension: SpecificationsExtension { @@ -26,6 +30,7 @@ struct UniversalPlatformSpecsExtension: SpecificationsExtension { CppToolSpec.self, LexCompilerSpec.self, YaccCompilerSpec.self, + TestEntryPointGenerationToolSpec.self, ] } @@ -44,3 +49,35 @@ struct UniversalPlatformSpecsExtension: SpecificationsExtension { findResourceBundle(nameWhenInstalledInToolchain: "SwiftBuild_SWBUniversalPlatform", resourceSearchPaths: resourceSearchPaths, defaultBundle: Bundle.module)?.resourceURL.map { [$0] } ?? [] } } + +struct UniversalPlatformTaskProducerExtension: TaskProducerExtension { + func createPreSetupTaskProducers(_ context: SWBTaskConstruction.TaskProducerContext) -> [any SWBTaskConstruction.TaskProducer] { + [] + } + + struct TestEntryPointTaskProducerFactory: TaskProducerFactory { + var name: String { + "TestEntryPointTaskProducerFactory" + } + + func createTaskProducer(_ context: SWBTaskConstruction.TargetTaskProducerContext, startPhaseNodes: [SWBCore.PlannedVirtualNode], endPhaseNode: SWBCore.PlannedVirtualNode) -> any SWBTaskConstruction.TaskProducer { + TestEntryPointTaskProducer(context, phaseStartNodes: startPhaseNodes, phaseEndNode: endPhaseNode) + } + } + + var setupTaskProducers: [any SWBTaskConstruction.TaskProducerFactory] { + [TestEntryPointTaskProducerFactory()] + } + + var unorderedPostSetupTaskProducers: [any SWBTaskConstruction.TaskProducerFactory] { [] } + + var unorderedPostBuildPhasesTaskProducers: [any SWBTaskConstruction.TaskProducerFactory] { [] } + + var globalTaskProducers: [any SWBTaskConstruction.GlobalTaskProducerFactory] { [] } +} + +struct UniversalPlatformTaskActionExtension: TaskActionExtension { + var taskActionImplementations: [SWBUtil.SerializableTypeCode : any SWBUtil.PolymorphicSerializable.Type] { + [41: TestEntryPointGenerationTaskAction.self] + } +} diff --git a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec index 28ee0ac2..fcdfeda1 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang LLVM 1.0.xcspec @@ -2708,28 +2708,6 @@ }; }, - // Generate bitcode options - not visible in the build settings. - { - Name = "CLANG_BITCODE_GENERATION_MODE"; - Type = Enumeration; - Values = ( - none, - marker, - bitcode, - ); - DefaultValue = "$(BITCODE_GENERATION_MODE)"; - Architectures = ( arm64, arm64e, armv7, armv7s, armv7k, arm64_32 ); - Condition = "$(ENABLE_BITCODE)"; - CommandLineArgs = { - marker = ( - "-fembed-bitcode-marker", - ); - bitcode = ( - "-fembed-bitcode", - ); - }; - }, - // Address Sanitizer options. { Name = "CLANG_ADDRESS_SANITIZER"; @@ -2970,6 +2948,12 @@ }; }, + { + Name = "CLANG_ENABLE_COMPILE_CACHE"; + Type = Boolean; + DefaultValue = "$(COMPILATION_CACHE_ENABLE_CACHING)"; + }, + // Thread Sanitizer options. { Name = "CLANG_THREAD_SANITIZER"; diff --git a/Sources/SWBUniversalPlatform/Specs/Ld.xcspec b/Sources/SWBUniversalPlatform/Specs/Ld.xcspec index b3acd33c..d30e08ad 100644 --- a/Sources/SWBUniversalPlatform/Specs/Ld.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Ld.xcspec @@ -400,9 +400,9 @@ CommandLineArgs = { "" = (); "<>" = ( - "-Xlinker", - "-dylib_install_name", - "-Xlinker", + "-Xclang-linker", + "-install_name", + "-Xclang-linker", "$(value)", ); }; @@ -501,6 +501,24 @@ Name = "LD_EXPORT_GLOBAL_SYMBOLS"; Type = Boolean; DefaultValue = NO; + }, + { + Name = "SWIFTC_LD_EXPORT_GLOBAL_SYMBOLS"; + Type = Boolean; + DefaultValue = "$(LD_EXPORT_GLOBAL_SYMBOLS)"; + Condition = "$(LINKER_DRIVER) == swiftc"; + CommandLineArgs = { + YES = ( + "-Xclang-linker", "-rdynamic" + ); + NO = (); + }; + }, + { + Name = "CLANG_LD_EXPORT_GLOBAL_SYMBOLS"; + Type = Boolean; + DefaultValue = "$(LD_EXPORT_GLOBAL_SYMBOLS)"; + Condition = "$(LINKER_DRIVER) == clang"; CommandLineArgs = { YES = ( "-rdynamic", @@ -545,99 +563,6 @@ DefaultValue = YES; }, - // Bitcode options - { - Name = "LD_BITCODE_GENERATION_MODE"; - Type = Enumeration; - Values = ( - marker, - bitcode, - ); - DefaultValue = "$(BITCODE_GENERATION_MODE)"; - Architectures = ( - arm64e, - arm64, - arm64_32, - armv7, - armv7s, - armv7k, - ); - Condition = "$(ENABLE_BITCODE)"; - CommandLineArgs = { - marker = ( - "-fembed-bitcode-marker", - ); - bitcode = ( - "-fembed-bitcode", - ); - }; - }, - { - Name = "LD_VERIFY_BITCODE"; - Type = Boolean; - DefaultValue = YES; - Architectures = ( - arm64e, - arm64, - arm64_32, - armv7, - armv7s, - armv7k, - ); - Condition = "$(ENABLE_BITCODE) && $(BITCODE_GENERATION_MODE) == bitcode"; - CommandLineArgs = { - YES = ( - "-Xlinker", - "-bitcode_verify", - ); - NO = (); - }; - }, - { - Name = "LD_HIDE_BITCODE_SYMBOLS"; - Type = Boolean; - DefaultValue = "$(HIDE_BITCODE_SYMBOLS)"; - Architectures = ( - arm64, - arm64e, - arm64_32, - armv7, - armv7s, - armv7k, - ); - Condition = "$(ENABLE_BITCODE) && $(BITCODE_GENERATION_MODE) == bitcode && $(MACH_O_TYPE) != mh_object"; - CommandLineArgs = { - YES = ( - "-Xlinker", - "-bitcode_hide_symbols", - ); - NO = (); - }; - }, - { - Name = "LD_GENERATE_BITCODE_SYMBOL_MAP"; - Type = Boolean; - DefaultValue = "$(HIDE_BITCODE_SYMBOLS)"; - Architectures = ( - arm64, - arm64e, - arm64_32, - armv7, - armv7s, - armv7k, - ); - Condition = "$(ENABLE_BITCODE) && $(BITCODE_GENERATION_MODE) == bitcode && $(MACH_O_TYPE) != mh_object"; - CommandLineArgs = { - YES = ( - "-Xlinker", - "-bitcode_symbol_map", - "-Xlinker", - "$(BUILT_PRODUCTS_DIR)", - ); - NO = (); - }; - }, - // Thread Sanitizer options { Name = "LD_THREAD_SANITIZER"; diff --git a/Sources/SWBUniversalPlatform/Specs/PackageTypes.xcspec b/Sources/SWBUniversalPlatform/Specs/PackageTypes.xcspec index 028bf5c1..2a4dd1fe 100644 --- a/Sources/SWBUniversalPlatform/Specs/PackageTypes.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/PackageTypes.xcspec @@ -217,7 +217,6 @@ Description = "Unit Test Bundle"; DefaultBuildSettings = { WRAPPER_SUFFIX = "xctest"; - ENABLE_BITCODE = NO; }; ProductReference = { FileType = wrapper.cfbundle; @@ -234,7 +233,6 @@ Description = "External Test Bundle"; DefaultBuildSettings = { WRAPPER_SUFFIX = "externaltest"; - ENABLE_BITCODE = NO; }; ProductReference = { FileType = wrapper.cfbundle; diff --git a/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec b/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec index 68dab9bb..0067050f 100644 --- a/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/ProductTypes.xcspec @@ -290,7 +290,7 @@ DefaultBuildProperties = { WRAPPER_EXTENSION = "xctest"; ENABLE_TESTING_SEARCH_PATHS = YES; - PRODUCT_SPECIFIC_LDFLAGS = "-framework XCTest -lXCTestSwiftSupport"; + PRODUCT_SPECIFIC_LDFLAGS = "-Xlinker -needed_framework -Xlinker XCTest -framework XCTest -Xlinker -needed-lXCTestSwiftSupport -lXCTestSwiftSupport"; PRODUCT_TYPE_SWIFT_STDLIB_TOOL_FLAGS = "--scan-executable \"$(PLATFORM_DIR)/Developer/usr/lib/libXCTestSwiftSupport.dylib\""; XCTRUNNER_PATH = "$(XCTRUNNER_PATH$(TEST_BUILD_STYLE))"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(LD_RUNPATH_SEARCH_PATHS_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))"; @@ -300,7 +300,6 @@ INSTALL_PATH_XCTRUNNER_YES = "$(DEFAULT_TEST_RUNNER_APP_INSTALL_PATH)"; INSTALL_PATH_XCTRUNNER_NO = "$(DEFAULT_TEST_BUNDLE_INSTALL_PATH)"; - ENABLE_BITCODE = NO; ENTITLEMENTS_REQUIRED = NO; PROVISIONING_PROFILE_SUPPORTED = YES; diff --git a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec index 846b1e6c..4f04b3e2 100644 --- a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec @@ -930,6 +930,11 @@ Category = "General"; Description = "Coordinates the build of the main module's modular dependencies via explicit tasks scheduled by the build system."; }, + { + Name = "SWIFT_ENABLE_COMPILE_CACHE"; + Type = Boolean; + DefaultValue = "$(COMPILATION_CACHE_ENABLE_CACHING)"; + }, { Name = "SWIFT_GENERATE_ADDITIONAL_LINKER_ARGS"; Type = Boolean; @@ -1031,28 +1036,6 @@ DisplayName = "Reflection Metadata Level"; }, - // Generate bitcode options - { - Name = "SWIFT_BITCODE_GENERATION_MODE"; - Type = Enumeration; - Values = ( - marker, - bitcode, - ); - DefaultValue = "$(BITCODE_GENERATION_MODE)"; - Architectures = ( arm64, arm64e, armv7, armv7s, armv7k, arm64_32 ); - Condition = "$(ENABLE_BITCODE)"; - CommandLineArgs = { - marker = ( - "-embed-bitcode-marker", - ); - bitcode = ( - "-embed-bitcode", - ); - }; - // Not visible in the build settings editor - }, - // Fuzzer option. { Name = "SWIFT_LIBFUZZER"; diff --git a/Sources/SWBUniversalPlatform/Specs/TestEntryPointGenerator.xcspec b/Sources/SWBUniversalPlatform/Specs/TestEntryPointGenerator.xcspec new file mode 100644 index 00000000..103d4f00 --- /dev/null +++ b/Sources/SWBUniversalPlatform/Specs/TestEntryPointGenerator.xcspec @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +( + { Identifier = "org.swift.test-entry-point-generator"; + Type = Compiler; + Name = "Generate Test Entry Point"; + Description = "Generates the entry point for a test target."; + CommandLine = "builtin-generateTestEntryPoint [options] --output $(OutputPath)"; + RuleName = "GenerateTestEntryPoint $(OutputPath)"; + ExecDescription = "Generate entry point for $(PRODUCT_NAME)"; + Outputs = ( + "$(OutputPath)" + ); + Options = ( + ); + } +) diff --git a/Sources/SWBUniversalPlatform/TestEntryPointGenerationTaskAction.swift b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTaskAction.swift new file mode 100644 index 00000000..57dff473 --- /dev/null +++ b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTaskAction.swift @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +import SWBUtil +import SWBCore +import SWBTaskExecution +import ArgumentParser + +class TestEntryPointGenerationTaskAction: TaskAction { + override class var toolIdentifier: String { + "TestEntryPointGenerationTaskAction" + } + + override func performTaskAction(_ task: any ExecutableTask, dynamicExecutionDelegate: any DynamicTaskExecutionDelegate, executionDelegate: any TaskExecutionDelegate, clientDelegate: any TaskExecutionClientDelegate, outputDelegate: any TaskOutputDelegate) async -> CommandResult { + do { + let options = try Options.parse(Array(task.commandLineAsStrings.dropFirst())) + try executionDelegate.fs.write(options.output, contents: #""" + #if canImport(Testing) + import Testing + #endif + + @main + @available(macOS 10.15, iOS 11, watchOS 4, tvOS 11, visionOS 1, *) + @available(*, deprecated, message: "Not actually deprecated. Marked as deprecated to allow inclusion of deprecated tests (which test deprecated functionality) without warnings") + struct Runner { + private static func testingLibrary() -> String { + var iterator = CommandLine.arguments.makeIterator() + while let argument = iterator.next() { + if argument == "--testing-library", let libraryName = iterator.next() { + return libraryName.lowercased() + } + } + + // Fallback if not specified: run XCTest (legacy behavior) + return "xctest" + } + + #if os(Linux) + @_silgen_name("$ss13_runAsyncMainyyyyYaKcF") + private static func _runAsyncMain(_ asyncFun: @Sendable @escaping () async throws -> ()) + + static func main() { + let testingLibrary = Self.testingLibrary() + #if canImport(Testing) + if testingLibrary == "swift-testing" { + _runAsyncMain { + await Testing.__swiftPMEntryPoint() as Never + } + } + #endif + } + #else + static func main() async { + let testingLibrary = Self.testingLibrary() + #if canImport(Testing) + if testingLibrary == "swift-testing" { + await Testing.__swiftPMEntryPoint() as Never + } + #endif + } + #endif + } + """#) + return .succeeded + } catch { + outputDelegate.emitError("\(error)") + return .failed + } + } +} + +private struct Options: ParsableArguments { + @Option var output: Path +} diff --git a/Sources/SWBUniversalPlatform/TestEntryPointGenerationTool.swift b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTool.swift new file mode 100644 index 00000000..007611ad --- /dev/null +++ b/Sources/SWBUniversalPlatform/TestEntryPointGenerationTool.swift @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +import SWBUtil +import SWBMacro +import SWBCore + +final class TestEntryPointGenerationToolSpec: GenericCommandLineToolSpec, SpecIdentifierType, @unchecked Sendable { + static let identifier = "org.swift.test-entry-point-generator" + + override func createTaskAction(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) -> (any PlannedTaskAction)? { + TestEntryPointGenerationTaskAction() + } +} diff --git a/Sources/SWBUniversalPlatform/TestEntryPointTaskProducer.swift b/Sources/SWBUniversalPlatform/TestEntryPointTaskProducer.swift new file mode 100644 index 00000000..fe4b56ef --- /dev/null +++ b/Sources/SWBUniversalPlatform/TestEntryPointTaskProducer.swift @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +import SWBCore +import SWBTaskConstruction +import SWBMacro + +class TestEntryPointTaskProducer: PhasedTaskProducer, TaskProducer { + func generateTasks() async -> [any PlannedTask] { + var tasks: [any PlannedTask] = [] + if context.settings.globalScope.evaluate(BuiltinMacros.GENERATE_TEST_ENTRY_POINT) { + await self.appendGeneratedTasks(&tasks) { delegate in + let scope = context.settings.globalScope + let outputPath = scope.evaluate(BuiltinMacros.GENERATED_TEST_ENTRY_POINT_PATH) + let cbc = CommandBuildContext(producer: context, scope: scope, inputs: [], outputs: [outputPath]) + await context.testEntryPointGenerationToolSpec.constructTasks(cbc, delegate) + } + } + return tasks + } +} + +extension TaskProducerContext { + var testEntryPointGenerationToolSpec: TestEntryPointGenerationToolSpec { + return workspaceContext.core.specRegistry.getSpec(TestEntryPointGenerationToolSpec.identifier, domain: domain) as! TestEntryPointGenerationToolSpec + } +} diff --git a/Sources/SWBUniversalPlatform/YaccCompiler.swift b/Sources/SWBUniversalPlatform/YaccCompiler.swift index e4755ce7..82a0641e 100644 --- a/Sources/SWBUniversalPlatform/YaccCompiler.swift +++ b/Sources/SWBUniversalPlatform/YaccCompiler.swift @@ -12,6 +12,7 @@ import SWBUtil import SWBCore +import SWBMacro final class YaccCompilerSpec : CompilerSpec, SpecIdentifierType, @unchecked Sendable { static let identifier = "com.apple.compilers.yacc" diff --git a/Sources/SWBUtil/CMakeLists.txt b/Sources/SWBUtil/CMakeLists.txt index d73490cc..0be8ed58 100644 --- a/Sources/SWBUtil/CMakeLists.txt +++ b/Sources/SWBUtil/CMakeLists.txt @@ -68,6 +68,7 @@ add_library(SWBUtil OutputByteStream.swift Pair.swift Path.swift + PathWindows.swift PbxCp.swift PluginManager.swift PluginManagerCommon.swift @@ -100,6 +101,7 @@ add_library(SWBUtil VFS.swift WaitCondition.swift WeakRef.swift + Win32Error.swift XCBuildDataArchive.swift Xcode.swift) set_target_properties(SWBUtil PROPERTIES @@ -108,5 +110,4 @@ target_link_libraries(SWBUtil PUBLIC SWBCSupport SWBLibc ArgumentParser - $<$>,$>>:Crypto::Crypto> $<$>:SwiftSystem::SystemPackage>) diff --git a/Sources/SWBUtil/DependencyInfo.swift b/Sources/SWBUtil/DependencyInfo.swift index c7e7a149..a39141fe 100644 --- a/Sources/SWBUtil/DependencyInfo.swift +++ b/Sources/SWBUtil/DependencyInfo.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import SWBLibc +import Foundation public enum DependencyInfoEncodingError: Error { case emptyString diff --git a/Sources/SWBUtil/DiagnosticsEngine.swift b/Sources/SWBUtil/DiagnosticsEngine.swift index 254b0424..db52c9cc 100644 --- a/Sources/SWBUtil/DiagnosticsEngine.swift +++ b/Sources/SWBUtil/DiagnosticsEngine.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import Synchronization + /// The component of a diagnostic. public enum Component: Serializable, Equatable, Hashable, Sendable, Codable { case `default` diff --git a/Sources/SWBUtil/FSProxy.swift b/Sources/SWBUtil/FSProxy.swift index a8959df3..ae89474c 100644 --- a/Sources/SWBUtil/FSProxy.swift +++ b/Sources/SWBUtil/FSProxy.swift @@ -71,6 +71,8 @@ public struct FileInfo: Equatable, Sendable { public var isExecutable: Bool { #if os(Windows) + // Per https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions, "user execute bits are set according to the filename extension". + // Don't use FileManager.isExecutableFile due to https://github.com/swiftlang/swift-foundation/issues/860 return (statBuf.st_mode & UInt16(_S_IEXEC)) != 0 #else return (statBuf.st_mode & S_IXUSR) != 0 @@ -148,6 +150,7 @@ public protocol FSProxy: AnyObject, Sendable { // FIXME: Need to document behavior w.r.t. error handling. func isDirectory(_ path: Path) -> Bool + /// Checks whether the given path has the execute bit (which on Windows is determined by the file extension). func isExecutable(_ path: Path) throws -> Bool /// Checks whether the given path is a symlink, also returning whether the linked file exists. @@ -292,6 +295,10 @@ public extension FSProxy { var exists: Bool = false return isSymlink(path, &exists) } + + func getFileSize(_ path: Path) throws -> Int64 { + try Int64(getFileInfo(path).statBuf.st_size) + } } fileprivate extension FSProxy { @@ -614,7 +621,7 @@ class LocalFS: FSProxy, @unchecked Sendable { DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil) } if handle == INVALID_HANDLE_VALUE { - throw StubError.error("Failed to update file time") + throw Win32Error(GetLastError()) } try handle.closeAfter { var ft = FILETIME() @@ -622,7 +629,7 @@ class LocalFS: FSProxy, @unchecked Sendable { GetSystemTime(&st) SystemTimeToFileTime(&st, &ft) if !SetFileTime(handle, nil, &ft, &ft) { - throw StubError.error("Failed to update file time") + Win32Error(GetLastError()) } } #else @@ -641,7 +648,7 @@ class LocalFS: FSProxy, @unchecked Sendable { DWORD(OPEN_EXISTING), DWORD(FILE_FLAG_BACKUP_SEMANTICS), nil) } if handle == INVALID_HANDLE_VALUE { - throw StubError.error("Failed to update file time") + throw Win32Error(GetLastError()) } try handle.closeAfter { // Number of 100ns intervals between 1601 and 1970 epochs @@ -656,7 +663,7 @@ class LocalFS: FSProxy, @unchecked Sendable { ft.dwLowDateTime = timeInt.LowPart ft.dwHighDateTime = timeInt.HighPart if !SetFileTime(handle, nil, &ft, &ft) { - throw StubError.error("Failed to update file time") + throw Win32Error(GetLastError()) } } #else @@ -880,7 +887,7 @@ class LocalFS: FSProxy, @unchecked Sendable { 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 StubError.error("GetFinalPathNameByHandleW failed") + throw Win32Error(GetLastError()) } let path = String(platformString: $0.baseAddress!) // Drop UNC prefix if present @@ -1636,13 +1643,6 @@ extension HANDLE { } } } - -fileprivate struct Win32Error: Error { - let error: DWORD - init(_ error: DWORD) { - self.error = error - } -} #endif extension FileDescriptor { diff --git a/Sources/SWBUtil/FilesSignature.swift b/Sources/SWBUtil/FilesSignature.swift index a3ebd185..8cbc25c7 100644 --- a/Sources/SWBUtil/FilesSignature.swift +++ b/Sources/SWBUtil/FilesSignature.swift @@ -71,7 +71,7 @@ fileprivate extension FSProxy { /// Returns the signature of a list of files. func filesSignature(_ statInfos: [(Path, stat?)]) -> ByteString { - let md5Context = MD5Context() + let md5Context = InsecureHashContext() for (path, statInfo) in statInfos { md5Context.add(string: path.str) if let statInfo { diff --git a/Sources/SWBUtil/HashContext.swift b/Sources/SWBUtil/HashContext.swift index 40e2841a..4465820c 100644 --- a/Sources/SWBUtil/HashContext.swift +++ b/Sources/SWBUtil/HashContext.swift @@ -14,8 +14,6 @@ import WinSDK #elseif canImport(CryptoKit) private import CryptoKit -#else -private import Crypto #endif public import Foundation @@ -104,7 +102,7 @@ fileprivate final class BCryptHashContext: HashContext { @available(*, unavailable) extension BCryptHashContext: Sendable { } -#else +#elseif canImport(CryptoKit) fileprivate final class SwiftCryptoHashContext: HashContext { @usableFromInline internal var hash = HF() @@ -147,6 +145,199 @@ fileprivate final class SwiftCryptoHashContext: HashContext { extension SwiftCryptoHashContext: Sendable { } #endif +fileprivate final class VendoredSHA256HashContext: HashContext { + /// The length of the output digest (in bits). + private static let digestLength = 256 + + /// The size of each blocks (in bits). + private static let blockBitSize = 512 + + /// The initial hash value. + private static let initalHashValue: [UInt32] = [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 + ] + + /// The constants in the algorithm (K). + private static let konstants: [UInt32] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + ] + + private var bytes: OutputByteStream + + init() { + self.bytes = .init() + } + + func add(bytes: D) where D : DataProtocol { + self.bytes.write(bytes) + } + + var signature: ByteString { + let digest = self.hash(self.bytes.bytes) + var result = [UInt8](repeating: 0, count: Int(digest.count) * 2) + + digest.bytes.withUnsafeBufferPointer { ptr in + for i in 0..> 4) + result[i*2 + 1] = hexchar(value & 0x0F) + } + } + + return ByteString(result) + } + + private func hash(_ bytes: ByteString) -> ByteString { + var input = bytes.bytes + + // Pad the input. + pad(&input) + + // Break the input into N 512-bit blocks. + let messageBlocks = input.blocks(size: Self.blockBitSize / 8) + + /// The hash that is being computed. + var hash = Self.initalHashValue + + // Process each block. + for block in messageBlocks { + process(block, hash: &hash) + } + + // Finally, compute the result. + var result = [UInt8](repeating: 0, count: Self.digestLength / 8) + for (idx, element) in hash.enumerated() { + let pos = idx * 4 + result[pos + 0] = UInt8((element >> 24) & 0xff) + result[pos + 1] = UInt8((element >> 16) & 0xff) + result[pos + 2] = UInt8((element >> 8) & 0xff) + result[pos + 3] = UInt8(element & 0xff) + } + + return ByteString(result) + } + + /// Process and compute hash from a block. + private func process(_ block: ArraySlice, hash: inout [UInt32]) { + + // Compute message schedule. + var W = [UInt32](repeating: 0, count: Self.konstants.count) + for t in 0..> 10) + let σ0 = W[t-15].rotateRight(by: 7) ^ W[t-15].rotateRight(by: 18) ^ (W[t-15] >> 3) + W[t] = σ1 &+ W[t-7] &+ σ0 &+ W[t-16] + } + } + + var a = hash[0] + var b = hash[1] + var c = hash[2] + var d = hash[3] + var e = hash[4] + var f = hash[5] + var g = hash[6] + var h = hash[7] + + // Run the main algorithm. + for t in 0.. [UInt8] { + var value = self.littleEndian + return withUnsafeBytes(of: &value, Array.init) + } +} + +private extension UInt32 { + /// Rotates self by given amount. + func rotateRight(by amount: UInt32) -> UInt32 { + return (self >> amount) | (self << (32 - amount)) + } +} + +private extension Array { + /// Breaks the array into the given size. + func blocks(size: Int) -> AnyIterator> { + var currentIndex = startIndex + return AnyIterator { + if let nextIndex = self.index(currentIndex, offsetBy: size, limitedBy: self.endIndex) { + defer { currentIndex = nextIndex } + return self[currentIndex.. UInt8 { assert(value >= 0 && value < 16) @@ -173,25 +364,29 @@ public class DelegatedHashContext: HashContext { } } -public final class MD5Context: DelegatedHashContext { +public final class InsecureHashContext: DelegatedHashContext { public init() { #if os(Windows) super.init(impl: BCryptHashContext(algorithm: "MD5", digestLength: 16)) - #else + #elseif canImport(CryptoKit) super.init(impl: SwiftCryptoHashContext()) + #else + super.init(impl: VendoredSHA256HashContext()) #endif } } @available(*, unavailable) -extension MD5Context: Sendable { } +extension InsecureHashContext: Sendable { } public final class SHA256Context: DelegatedHashContext { public init() { #if os(Windows) super.init(impl: BCryptHashContext(algorithm: "SHA256", digestLength: 32)) - #else + #elseif canImport(CryptoKit) super.init(impl: SwiftCryptoHashContext()) + #else + super.init(impl: VendoredSHA256HashContext()) #endif } } diff --git a/Sources/SWBUtil/HeavyCache.swift b/Sources/SWBUtil/HeavyCache.swift index 83c35b6f..190457e2 100644 --- a/Sources/SWBUtil/HeavyCache.swift +++ b/Sources/SWBUtil/HeavyCache.swift @@ -10,6 +10,10 @@ // //===----------------------------------------------------------------------===// +#if canImport(os) +import os +#endif + /// Base protocol used for global operations over generic type. private protocol _HeavyCacheBase: AnyObject { /// Clear the cache. @@ -33,8 +37,22 @@ public func clearAllHeavyCaches() { } } -@_spi(Testing) public func withHeavyCacheGlobalState(_ body: () async throws -> T) async rethrows -> T { - try await $allHeavyCaches.withValue(.init([])) { +public func withHeavyCacheGlobalState(isolated: Bool = true, _ body: () throws -> T) rethrows -> T { + if isolated { + try $allHeavyCaches.withValue(.init([])) { + try body() + } + } else { + try body() + } +} + +@_spi(Testing) public func withHeavyCacheGlobalState(isolated: Bool = true, _ body: () async throws -> T) async rethrows -> T { + if isolated { + try await $allHeavyCaches.withValue(.init([])) { + try await body() + } + } else { try await body() } } diff --git a/Sources/SWBUtil/Int.swift b/Sources/SWBUtil/Int.swift index 83dfeae2..d8196006 100644 --- a/Sources/SWBUtil/Int.swift +++ b/Sources/SWBUtil/Int.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import Foundation + extension Int { // FIXME: Figure out what the best API for this is. Having a more explicit (non-format string based) API is easier to make efficient, but it ends up taking so many arguments just to get the same flexibility. public func toString(format: String = "%d") -> String { diff --git a/Sources/SWBUtil/LazyCache.swift b/Sources/SWBUtil/LazyCache.swift index ce8605f9..292d38b4 100644 --- a/Sources/SWBUtil/LazyCache.swift +++ b/Sources/SWBUtil/LazyCache.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import SWBLibc +import Synchronization // Workaround compiler crash: rdar://138854389 (Compiler crashes when compiling code using a Mutex with an Optional) #if os(Windows) diff --git a/Sources/SWBUtil/Library.swift b/Sources/SWBUtil/Library.swift index e7f016f5..c8079482 100644 --- a/Sources/SWBUtil/Library.swift +++ b/Sources/SWBUtil/Library.swift @@ -33,8 +33,8 @@ public enum Library: Sendable { @_alwaysEmitIntoClient public static func open(_ path: Path) throws -> LibraryHandle { #if os(Windows) - guard let handle = path.withPlatformString(LoadLibraryW) else { - throw LibraryOpenError(message: "LoadLibraryW returned \(GetLastError())") + guard let handle = try path.withPlatformString({ p in try p.withCanonicalPathRepresentation({ LoadLibraryW($0) }) }) else { + throw LibraryOpenError(message: Win32Error(GetLastError()).description) } return LibraryHandle(rawValue: handle) #else @@ -64,15 +64,18 @@ public enum Library: Sendable { } public static func locate(_ pointer: T.Type) -> Path { - let outPointer: UnsafeMutablePointer #if os(Windows) var handle: HMODULE? - GetModuleHandleExW(DWORD(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), unsafeBitCast(pointer, to: LPCWSTR?.self), &handle) - let capacity = 260 - outPointer = .allocate(capacity: capacity) - defer { outPointer.deallocate() } - GetModuleFileNameW(handle, outPointer, DWORD(capacity)) + guard GetModuleHandleExW(DWORD(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), unsafeBitCast(pointer, to: LPCWSTR?.self), &handle) else { + return Path("") + } + do { + return try Path(SWB_GetModuleFileNameW(handle)) + } catch { + return Path("") + } #else + let outPointer: UnsafeMutablePointer var info = Dl_info() #if os(Android) dladdr(unsafeBitCast(pointer, to: UnsafeMutableRawPointer.self), &info) @@ -81,8 +84,8 @@ public enum Library: Sendable { dladdr(unsafeBitCast(pointer, to: UnsafeMutableRawPointer?.self), &info) outPointer = UnsafeMutablePointer(mutating: info.dli_fname) #endif - #endif return Path(platformString: outPointer) + #endif } } @@ -114,3 +117,32 @@ public struct LibraryHandle: @unchecked Sendable { self.rawValue = rawValue } } + +#if os(Windows) +@_spi(Testing) public func SWB_GetModuleFileNameW(_ hModule: HMODULE?) throws -> String { +#if DEBUG + var bufferCount = Int(1) // force looping +#else + var bufferCount = Int(MAX_PATH) +#endif + while true { + if let result = try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: bufferCount, { buffer in + switch (GetModuleFileNameW(hModule, buffer.baseAddress!, DWORD(buffer.count)), GetLastError()) { + case (1..(_ body: (Self) throws -> Result) throws -> Result { + // 1. Normalize the path first. + // Contrary to the documentation, this works on long paths independently + // of the registry or process setting to enable long paths (but it will also + // not add the \\?\ prefix required by other functions under these conditions). + let dwLength: DWORD = GetFullPathNameW(self, 0, nil, nil) + return try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) { pwszFullPath in + guard (1.. DWORD { + DWORD(hr) & 0xffff +} + +@inline(__always) +fileprivate func HRESULT_FACILITY(_ hr: HRESULT) -> DWORD { + DWORD(hr << 16) & 0x1fff +} + +@inline(__always) +fileprivate func SUCCEEDED(_ hr: HRESULT) -> Bool { + hr >= 0 +} + +// This is a non-standard extension to the Windows SDK that allows us to convert +// an HRESULT to a Win32 error code. +@inline(__always) +fileprivate func WIN32_FROM_HRESULT(_ hr: HRESULT) -> DWORD { + if SUCCEEDED(hr) { return DWORD(ERROR_SUCCESS) } + if HRESULT_FACILITY(hr) == FACILITY_WIN32 { + return HRESULT_CODE(hr) + } + return DWORD(hr) +} +#endif diff --git a/Sources/SWBUtil/PbxCp.swift b/Sources/SWBUtil/PbxCp.swift index d7b157c0..e372db81 100644 --- a/Sources/SWBUtil/PbxCp.swift +++ b/Sources/SWBUtil/PbxCp.swift @@ -569,9 +569,8 @@ public func pbxcp(_ argv: [String], cwd: Path) async -> (success: Bool, output: } if let bitcodeStripFlag = options.bitcodeStripFlag { - if bitcodeStripFlag == "replace-with-marker" { - options.bitcodeStripFlag = "-m" - } else if bitcodeStripFlag == "all" { + // Always strip all bitcode if we were passed a valid option. + if bitcodeStripFlag == "replace-with-marker" || bitcodeStripFlag == "all" { options.bitcodeStripFlag = "-r" } else { return (false, CopyOptions.helpMessage()) diff --git a/Sources/SWBUtil/Process.swift b/Sources/SWBUtil/Process.swift index 62af985a..634c3f0d 100644 --- a/Sources/SWBUtil/Process.swift +++ b/Sources/SWBUtil/Process.swift @@ -129,7 +129,7 @@ extension Process { throw StubError.error("\(url) is not an absolute file URL") } let executableFilePath = try url.standardizedFileURL.filePath - if !FileManager.default.isExecutableFile(atPath: executableFilePath.str) { + if try !localFS.isExecutable(executableFilePath) { throw StubError.error("\(executableFilePath.str) is not an executable file") } let process = Process() diff --git a/Sources/SWBUtil/ProcessInfo.swift b/Sources/SWBUtil/ProcessInfo.swift index 7202bfdd..85b4ef2c 100644 --- a/Sources/SWBUtil/ProcessInfo.swift +++ b/Sources/SWBUtil/ProcessInfo.swift @@ -62,8 +62,10 @@ extension ProcessInfo { var capacity = UNLEN + 1 let pointer = UnsafeMutablePointer.allocate(capacity: Int(capacity)) defer { pointer.deallocate() } - GetUserNameW(pointer, &capacity) - return String(platformString: pointer) + if GetUserNameW(pointer, &capacity) { + return String(platformString: pointer) + } + return "" #else let uid = geteuid().orIfZero(getuid()) return (getpwuid(uid)?.pointee.pw_name).map { String(cString: $0) } ?? String(uid) diff --git a/Sources/SWBUtil/PropertyList.swift b/Sources/SWBUtil/PropertyList.swift index 4f34adc9..71cd3cb0 100644 --- a/Sources/SWBUtil/PropertyList.swift +++ b/Sources/SWBUtil/PropertyList.swift @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#if canImport(CoreFoundation) +#if canImport(Darwin) import class CoreFoundation.CFBoolean import func CoreFoundation.CFBooleanGetTypeID import func CoreFoundation.CFBooleanGetValue @@ -68,7 +68,7 @@ extension PropertyListConversionError: CustomStringConvertible { } public struct OpaquePropertyListItem: Equatable, Hashable, @unchecked Sendable { -#if canImport(CoreFoundation) +#if canImport(Darwin) fileprivate var wrappedValue: CFTypeRef fileprivate init(_ wrappedValue: CFTypeRef) { @@ -639,7 +639,7 @@ extension PropertyListItem: Equatable { private func convertToPropertyListItem(_ item: Any) -> PropertyListItem { switch(item) { -#if canImport(CoreFoundation) +#if canImport(Darwin) case let asBool as CFBoolean where CFGetTypeID(asBool) == CFBooleanGetTypeID(): return .plBool(CFBooleanGetValue(asBool)) @@ -683,7 +683,7 @@ private func convertToPropertyListItem(_ item: Any) -> PropertyListItem { } return .plDict(result) -#if canImport(CoreFoundation) +#if canImport(Darwin) case let asCFType as CFTypeRef: return .plOpaque(.init(asCFType)) #else diff --git a/Sources/SWBUtil/ScopedKeepAliveCache.swift b/Sources/SWBUtil/ScopedKeepAliveCache.swift index 1c5059d9..06a5b344 100644 --- a/Sources/SWBUtil/ScopedKeepAliveCache.swift +++ b/Sources/SWBUtil/ScopedKeepAliveCache.swift @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +import Synchronization + /// Supports using an evicting base cache but temporarily preventing eviction during `cache.keepAlive { ... }`. /// /// - It doesn't prevent the base cache from evicting, but instead temporarily uses an additional non-evicting store diff --git a/Sources/SWBUtil/Static.swift b/Sources/SWBUtil/Static.swift index 89f8e9a7..28aa6a66 100644 --- a/Sources/SWBUtil/Static.swift +++ b/Sources/SWBUtil/Static.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import SWBLibc +import Synchronization // This is a workaround for Swift's lack of local-static (rdar://problem/17662275) or in // generics (rdar://problem/22882266). diff --git a/Sources/SWBUtil/String.swift b/Sources/SWBUtil/String.swift index 6069c5ef..24b53d54 100644 --- a/Sources/SWBUtil/String.swift +++ b/Sources/SWBUtil/String.swift @@ -694,7 +694,7 @@ public func ==(lhs: T, rhs: String) -> Bool where T.Iterator.Elem extension String { /// Returns MD5 hex string representation. public func md5() -> String { - let context = MD5Context() + let context = InsecureHashContext() context.add(string: self) return context.signature.asString } @@ -768,7 +768,7 @@ fileprivate struct BinaryDataIterator } } -#if canImport(CoreFoundation) +#if canImport(Darwin) public import class CoreFoundation.CFString public import enum CoreFoundation.CFStringBuiltInEncodings public import func CoreFoundation.CFStringCreateWithCString diff --git a/Sources/SWBUtil/UserDefaults.swift b/Sources/SWBUtil/UserDefaults.swift index 7e9033bd..452ca333 100644 --- a/Sources/SWBUtil/UserDefaults.swift +++ b/Sources/SWBUtil/UserDefaults.swift @@ -203,10 +203,6 @@ public enum UserDefaults: Sendable { return hasValue(forKey: "EnableSDKStatCaching") ? bool(forKey: "EnableSDKStatCaching") : true } - public static var enableBitcodeSupport: Bool { - return hasValue(forKey: "EnableBitcodeSupport") ? bool(forKey: "EnableBitcodeSupport") : false - } - public static var useTargetDependenciesForImpartedBuildSettings: Bool { return bool(forKey: "UseTargetDependenciesForImpartedBuildSettings") } @@ -350,7 +346,6 @@ public let xcodeUserDefaultsToExportToSwiftBuild = [ "AttemptDependencyCycleResolution", "IgnoreFileSystemDeviceInodeChanges", "FileSystemMode", - "EnableBitcodeSupport", "DVTExtraPlatformFolders", // Legacy build system defaults also supported by Swift Build. diff --git a/Sources/SWBUtil/Win32Error.swift b/Sources/SWBUtil/Win32Error.swift new file mode 100644 index 00000000..35de1fef --- /dev/null +++ b/Sources/SWBUtil/Win32Error.swift @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#if os(Windows) +public import WinSDK +import Foundation + +public struct Win32Error: Error, CustomStringConvertible { + public let error: DWORD + + public init(_ error: DWORD) { + self.error = error + } + + public var description: String { + let flags: DWORD = DWORD(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS) + var buffer: UnsafeMutablePointer? + let length: DWORD = withUnsafeMutablePointer(to: &buffer) { + $0.withMemoryRebound(to: WCHAR.self, capacity: 2) { + FormatMessageW(flags, nil, error, 0, $0, 0, nil) + } + } + guard let buffer, length > 0 else { + return "Win32 Error Code \(error)" + } + defer { LocalFree(buffer) } + return String(decodingCString: buffer, as: UTF16.self).trimmingCharacters(in: .whitespacesAndNewlines) + } +} +#endif diff --git a/Sources/SWBWebAssemblyPlatform/Plugin.swift b/Sources/SWBWebAssemblyPlatform/Plugin.swift index 40bbdf9e..c3c16659 100644 --- a/Sources/SWBWebAssemblyPlatform/Plugin.swift +++ b/Sources/SWBWebAssemblyPlatform/Plugin.swift @@ -25,6 +25,10 @@ struct WebAssemblyPlatformSpecsExtension: SpecificationsExtension { func specificationFiles(resourceSearchPaths: [Path]) -> Bundle? { findResourceBundle(nameWhenInstalledInToolchain: "SwiftBuild_SWBWebAssemblyPlatform", resourceSearchPaths: resourceSearchPaths, defaultBundle: Bundle.module) } + + func specificationDomains() -> [String: [String]] { + ["webassembly": ["generic-unix"]] + } } struct WebAssemblyPlatformExtension: PlatformInfoExtension { @@ -76,7 +80,8 @@ struct WebAssemblySDKRegistryExtension: SDKRegistryExtension { let wasmSwiftSDKs = (try? SwiftSDK.findSDKs( targetTriples: Array(supportedTriples.keys), - fs: context.fs + fs: context.fs, + hostOperatingSystem: context.hostOperatingSystem )) ?? [] var wasmSDKs: [(path: Path, platform: SWBCore.Platform?, data: [String: PropertyListItem])] = [] @@ -94,6 +99,7 @@ struct WebAssemblySDKRegistryExtension: SDKRegistryExtension { "Type": .plString("SDK"), "Version": .plString("1.0.0"), "CanonicalName": .plString(wasmSDK.identifier), + "Aliases": ["webassembly", "wasi"], "IsBaseSDK": .plBool(true), "DefaultProperties": .plDict([ "PLATFORM_NAME": .plString("webassembly"), diff --git a/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec b/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec index 0e7af4c7..4b246b98 100644 --- a/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec +++ b/Sources/SWBWebAssemblyPlatform/Specs/WasmLd.xcspec @@ -15,7 +15,7 @@ Domain = webassembly; Identifier = "com.apple.pbx.linkers.ld"; Type = Linker; - BasedOn = "default:com.apple.pbx.linkers.ld"; + BasedOn = "generic-unix:com.apple.pbx.linkers.ld"; Name = Ld; Description = "Link executable using alternate linker"; IsAbstract = Yes; @@ -39,12 +39,6 @@ }, ); }, - { - Name = SDKROOT; - Type = Path; - CommandLineFlag = "--sysroot"; - IsInputDependency = Yes; - }, { // wasm-ld is always deterministic Name = LD_DETERMINISTIC_MODE; @@ -113,6 +107,12 @@ DefaultValue = YES; Condition = "NO"; }, + { + // Unsupported + Name = "LD_WARN_DUPLICATE_LIBRARIES"; + Type = Boolean; + Condition = "NO"; + }, { // wasm-ld doesn't support dependency info Name = "LD_DEPENDENCY_INFO_FILE"; @@ -129,14 +129,14 @@ IsInputDependency = Yes; }, { - Name = "LD_EXPORT_GLOBAL_SYMBOLS"; - Type = Boolean; - DefaultValue = NO; - CommandLineArgs = { - YES = ("-Xlinker", "--export-dynamic"); - NO = (); - }; - Condition = "$(MACH_O_TYPE) == mh_dylib"; + Name = "CLANG__INPUT_FILE_LIST_PATH__"; + Type = Path; + Condition = "NO"; // wasm-ld does not support -filelist + }, + { + Name = "SWIFTC__INPUT_FILE_LIST_PATH__"; + Type = Path; + Condition = "NO"; // wasm-ld does not support -filelist }, ); }, diff --git a/Sources/SWBWindowsPlatform/Plugin.swift b/Sources/SWBWindowsPlatform/Plugin.swift index 9ddfdf17..34037862 100644 --- a/Sources/SWBWindowsPlatform/Plugin.swift +++ b/Sources/SWBWindowsPlatform/Plugin.swift @@ -16,6 +16,7 @@ import Foundation @PluginExtensionSystemActor public func initializePlugin(_ manager: PluginManager) { let plugin = WindowsPlugin() + manager.register(WindowsDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self) manager.register(WindowsPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self) manager.register(WindowsEnvironmentExtension(plugin: plugin), type: EnvironmentExtensionPoint.self) manager.register(WindowsPlatformExtension(plugin: plugin), type: PlatformInfoExtensionPoint.self) @@ -51,6 +52,18 @@ public final class WindowsPlugin: Sendable { } } +struct WindowsDeveloperDirectoryExtension: DeveloperDirectoryExtension { + func fallbackDeveloperDirectory(hostOperatingSystem: OperatingSystem) async throws -> Path? { + guard hostOperatingSystem == .windows else { + return nil + } + guard let userProgramFiles = URL.userProgramFiles, let swiftPath = try? userProgramFiles.appending(component: "Swift").filePath else { + throw StubError.error("Could not determine path to user program files") + } + return swiftPath + } +} + struct WindowsPlatformSpecsExtension: SpecificationsExtension { func specificationFiles(resourceSearchPaths: [Path]) -> Bundle? { findResourceBundle(nameWhenInstalledInToolchain: "SwiftBuild_SWBWindowsPlatform", resourceSearchPaths: resourceSearchPaths, defaultBundle: Bundle.module) @@ -81,7 +94,15 @@ struct WindowsPlatformExtension: PlatformInfoExtension { return [] } - let platformsPath = context.developerPath.join("Platforms") + let platformsPath: Path + switch context.developerPath { + case .xcode(let path): + platformsPath = path.join("Platforms") + case .swiftToolchain(let path, _): + platformsPath = path.join("Platforms") + case .fallback(let path): + platformsPath = path.join("Platforms") + } return try context.fs.listdir(platformsPath).compactMap { version in let versionedPlatformsPath = platformsPath.join(version) guard context.fs.isDirectory(versionedPlatformsPath) else { diff --git a/Sources/SWBWindowsPlatform/Specs/WindowsLd.xcspec b/Sources/SWBWindowsPlatform/Specs/WindowsLd.xcspec index 8e2d588f..39f50000 100644 --- a/Sources/SWBWindowsPlatform/Specs/WindowsLd.xcspec +++ b/Sources/SWBWindowsPlatform/Specs/WindowsLd.xcspec @@ -153,6 +153,12 @@ Type = Path; Condition = "NO"; }, + { + // Unsupported + Name = "LD_WARN_DUPLICATE_LIBRARIES"; + Type = Boolean; + Condition = "NO"; + }, { // Don't deduplicate is broken in gold Name = "LD_DONT_RUN_DEDUPLICATION"; diff --git a/Sources/SwiftBuild/ConsoleCommands/SWBServiceConsoleSessionCommands.swift b/Sources/SwiftBuild/ConsoleCommands/SWBServiceConsoleSessionCommands.swift index 76f064c4..abad7e59 100644 --- a/Sources/SwiftBuild/ConsoleCommands/SWBServiceConsoleSessionCommands.swift +++ b/Sources/SwiftBuild/ConsoleCommands/SWBServiceConsoleSessionCommands.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import SWBProtocol +import SWBUtil class SWBServiceConsoleCreateSessionCommand: SWBServiceConsoleCommand { static let name = "createSession" diff --git a/Sources/SwiftBuild/ProjectModel/BuildSettings.swift b/Sources/SwiftBuild/ProjectModel/BuildSettings.swift index 54a97cf4..33e50e9f 100644 --- a/Sources/SwiftBuild/ProjectModel/BuildSettings.swift +++ b/Sources/SwiftBuild/ProjectModel/BuildSettings.swift @@ -104,6 +104,8 @@ extension ProjectModel { case SWIFT_USER_MODULE_VERSION case TAPI_DYLIB_INSTALL_NAME case TARGETED_DEVICE_FAMILY + case LINKER_DRIVER + case LD_WARN_DUPLICATE_LIBRARIES } public enum MultipleValueSetting: String, CaseIterable, Sendable, Hashable, Codable { @@ -162,6 +164,7 @@ extension ProjectModel { case windows case wasi case openbsd + case freebsd public var asConditionStrings: [String] { let filters = self.toPlatformFilter().map { (filter: ProjectModel.PlatformFilter) -> String in @@ -262,6 +265,9 @@ public extension ProjectModel.BuildSettings.Platform { case .openbsd: result.append(.init(platform: "openbsd")) + + case .freebsd: + result.append(.init(platform: "freebsd")) } return result } diff --git a/Sources/SwiftBuild/SWBBuildService.swift b/Sources/SwiftBuild/SWBBuildService.swift index a70e9631..5403d4c8 100644 --- a/Sources/SwiftBuild/SWBBuildService.swift +++ b/Sources/SwiftBuild/SWBBuildService.swift @@ -221,6 +221,20 @@ public final class SWBBuildService: Sendable { } } + public func createSession(name: String, swiftToolchainPath: String, resourceSearchPaths: [String], cachePath: String?, inferiorProductsPath: String?, environment: [String:String]?) async -> (Result, [SwiftBuildMessage.DiagnosticInfo]) { + do { + let response = try await send(request: CreateSessionRequest(name: name, developerPath: .swiftToolchain(Path(swiftToolchainPath)), resourceSearchPaths: resourceSearchPaths.map(Path.init), cachePath: cachePath.map(Path.init), inferiorProductsPath: inferiorProductsPath.map(Path.init), environment: environment)) + let diagnostics = response.diagnostics.map { SwiftBuildMessage.DiagnosticInfo(.init($0, .global)) } + if let sessionID = response.sessionID { + return (.success(SWBBuildServiceSession(name: name, uid: sessionID, service: self)), diagnostics) + } else { + return (.failure(SwiftBuildError.requestError(description: "Could not initialize build system")), diagnostics) + } + } catch { + return (.failure(error), []) + } + } + /// List the active session UIDs and info. /// /// - returns: A map of session UIDs to info. diff --git a/Sources/SwiftBuild/SWBBuildServiceConnection.swift b/Sources/SwiftBuild/SWBBuildServiceConnection.swift index 5daa6d9a..60547066 100644 --- a/Sources/SwiftBuild/SWBBuildServiceConnection.swift +++ b/Sources/SwiftBuild/SWBBuildServiceConnection.swift @@ -16,6 +16,12 @@ import SWBUtil public import Foundation +#if canImport(System) +import System +#else +import SystemPackage +#endif + typealias swb_build_service_connection_message_handler_t = @Sendable (UInt64, SWBDispatchData) -> Void /// Represents and manages a connection to an Swift Build service subprocess. Clients do not normally talk directly to the connection; instead, they almost always go through a SWBBuildService object, which provides higher-level operations. The connection doesn’t know about the service-specific semantics, but instead provides general machinery for sending synchronous and asynchronous messages over one or more muxed communication “channels”, and for controlling the subprocess. diff --git a/Sources/SwiftBuild/SWBProductPlannerSupport.swift b/Sources/SwiftBuild/SWBProductPlannerSupport.swift index 84f8c5de..bc52a222 100644 --- a/Sources/SwiftBuild/SWBProductPlannerSupport.swift +++ b/Sources/SwiftBuild/SWBProductPlannerSupport.swift @@ -233,7 +233,7 @@ public struct SWBProductDescription: Equatable, Sendable { /// CLI tools might not have one. public let buildVersion: String? - /// Bitcode + /// Bitcode - no longer used, but preserved for compatibility with Xcode. public let enableBitcode: Bool /// Codesigning @@ -294,7 +294,7 @@ public struct SWBProductDescription: Equatable, Sendable { self.deploymentTarget = deploymentTarget self.marketingVersion = marketingVersion self.buildVersion = buildVersion - self.enableBitcode = enableBitcode + self.enableBitcode = false self.codesign = codesign self.team = team self.infoPlistPath = infoPlistPath diff --git a/Sources/SwiftBuild/SWBProvisioningTaskInputs.swift b/Sources/SwiftBuild/SWBProvisioningTaskInputs.swift index 94175b0c..6012ec1a 100644 --- a/Sources/SwiftBuild/SWBProvisioningTaskInputs.swift +++ b/Sources/SwiftBuild/SWBProvisioningTaskInputs.swift @@ -12,6 +12,7 @@ import SWBProtocol import SWBUtil +import Foundation @frozen public enum SWBProvisioningStyle: Sendable { case automatic diff --git a/Tests/SWBAndroidPlatformTests/SWBAndroidPlatformTests.swift b/Tests/SWBAndroidPlatformTests/SWBAndroidPlatformTests.swift index 91d7fc6a..2299add3 100644 --- a/Tests/SWBAndroidPlatformTests/SWBAndroidPlatformTests.swift +++ b/Tests/SWBAndroidPlatformTests/SWBAndroidPlatformTests.swift @@ -15,6 +15,7 @@ import SWBProtocol import SWBTestSupport import SWBTaskExecution import SWBUtil +import SWBCore @Suite fileprivate struct AndroidBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBApplePlatformTests/AppleCommandLineToolSpecDiscoveredInfoTests.swift b/Tests/SWBApplePlatformTests/AppleCommandLineToolSpecDiscoveredInfoTests.swift index dfa1da2d..97b45760 100644 --- a/Tests/SWBApplePlatformTests/AppleCommandLineToolSpecDiscoveredInfoTests.swift +++ b/Tests/SWBApplePlatformTests/AppleCommandLineToolSpecDiscoveredInfoTests.swift @@ -16,6 +16,7 @@ import Testing import SWBCore import SWBTestSupport import SWBUtil +import SWBProtocol @Suite fileprivate struct AppleCommandLineToolSpecDiscoveredInfoTests: CoreBasedTests { diff --git a/Tests/SWBBuildServiceTests/BuildDependencyInfoTests.swift b/Tests/SWBBuildServiceTests/BuildDependencyInfoTests.swift index 5f89ec46..8d83baf6 100644 --- a/Tests/SWBBuildServiceTests/BuildDependencyInfoTests.swift +++ b/Tests/SWBBuildServiceTests/BuildDependencyInfoTests.swift @@ -41,6 +41,7 @@ import Foundation TestFile("libFoo.dylib"), TestFile("libBar.a"), TestFile("libBaz.a"), + TestFile("libQux.tbd"), ]), buildConfigurations: [ TestBuildConfiguration( @@ -124,6 +125,7 @@ import Foundation TestFrameworksBuildPhase([ "Foundation.framework", "libBar.a", + "libQux.tbd", ]) ] ), @@ -221,6 +223,10 @@ import Foundation #expect(input.inputType == .library) #expect(input.linkType == .searchPath) } + results.checkTargetInputName(target, .name("libQux.tbd")) { input in + #expect(input.inputType == .library) + #expect(input.linkType == .searchPath) + } results.checkNoMoreTargetInputs(target) results.checkTargetOutputPath(target, "/usr/local/lib/libDylibTarget.dylib") @@ -325,6 +331,8 @@ import Foundation "-Xlinker -reexport-lXlinkerLib", "-Wl,-reexport-lQuoteLib", + + // TODO: we should support positional arguments as well but that requires a complete understanding of all possible linker args, will come back to this ].joined(separator: " ") ]), ], diff --git a/Tests/SWBBuildSystemPerfTests/ModulesVerifierPerfTests.swift b/Tests/SWBBuildSystemPerfTests/ModulesVerifierPerfTests.swift index 48499215..dd248926 100644 --- a/Tests/SWBBuildSystemPerfTests/ModulesVerifierPerfTests.swift +++ b/Tests/SWBBuildSystemPerfTests/ModulesVerifierPerfTests.swift @@ -15,6 +15,7 @@ import Testing import SWBCore import SWBTestSupport import SWBUtil +import SWBProtocol @Suite(.performance) fileprivate struct ModulesVerifierPerfTests: CoreBasedTests, PerfTests { diff --git a/Tests/SWBBuildSystemTests/AppIntentsNLTrainingTests.swift b/Tests/SWBBuildSystemTests/AppIntentsNLTrainingTests.swift index 5a1ea702..da54a2b7 100644 --- a/Tests/SWBBuildSystemTests/AppIntentsNLTrainingTests.swift +++ b/Tests/SWBBuildSystemTests/AppIntentsNLTrainingTests.swift @@ -17,6 +17,7 @@ import SWBCore import SWBTestSupport import SWBTaskExecution import SWBUtil +import SWBProtocol @Suite(.requireXcode16()) fileprivate struct AppIntentsNLTrainingTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/AppShortcutsStringsValidationTests.swift b/Tests/SWBBuildSystemTests/AppShortcutsStringsValidationTests.swift index 5e94299e..94b0a9a6 100644 --- a/Tests/SWBBuildSystemTests/AppShortcutsStringsValidationTests.swift +++ b/Tests/SWBBuildSystemTests/AppShortcutsStringsValidationTests.swift @@ -17,6 +17,7 @@ import SWBCore import SWBTestSupport import SWBTaskExecution import SWBUtil +import SWBProtocol @Suite(.requireXcode16()) fileprivate struct AppShortcutsStringsValidationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/BuildCommandTests.swift b/Tests/SWBBuildSystemTests/BuildCommandTests.swift index 8c50a544..995e8a43 100644 --- a/Tests/SWBBuildSystemTests/BuildCommandTests.swift +++ b/Tests/SWBBuildSystemTests/BuildCommandTests.swift @@ -16,6 +16,7 @@ import SWBTestSupport import SwiftBuildTestSupport import SWBUtil import Testing +import Foundation /// Tests the behavior of various alternative build commands of a build request, including single-file compiles. @Suite diff --git a/Tests/SWBBuildSystemTests/BuildOperationTests.swift b/Tests/SWBBuildSystemTests/BuildOperationTests.swift index d6984796..31466ea4 100644 --- a/Tests/SWBBuildSystemTests/BuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/BuildOperationTests.swift @@ -397,6 +397,103 @@ fileprivate struct BuildOperationTests: CoreBasedTests { } } + @Test(.skipHostOS(.macOS), .skipHostOS(.windows, "cannot find testing library"), .requireThreadSafeWorkingDirectory) + func unitTestWithGeneratedEntryPoint() async throws { + try await withTemporaryDirectory { (tmpDir: Path) in + let testProject = try await TestProject( + "TestProject", + sourceRoot: tmpDir, + groupTree: TestGroup( + "SomeFiles", + children: [ + TestFile("library.swift"), + TestFile("test.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "ARCHS": "$(ARCHS_STANDARD)", + "CODE_SIGNING_ALLOWED": "NO", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "$(HOST_PLATFORM)", + "SUPPORTED_PLATFORMS": "$(HOST_PLATFORM)", + "SWIFT_VERSION": swiftVersion, + ]) + ], + targets: [ + TestStandardTarget( + "test", + type: .unitTest, + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "LD_RUNPATH_SEARCH_PATHS": "@loader_path/", + ]) + ], + buildPhases: [ + TestSourcesBuildPhase(["test.swift"]), + TestFrameworksBuildPhase([ + TestBuildFile(.target("library")), + ]) + ], + dependencies: [ + "library" + ] + ), + TestStandardTarget( + "library", + type: .dynamicLibrary, + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "DYLIB_INSTALL_NAME_BASE": "$ORIGIN", + + // FIXME: Find a way to make these default + "EXECUTABLE_PREFIX": "lib", + "EXECUTABLE_PREFIX[sdk=windows*]": "", + ]) + ], + buildPhases: [ + TestSourcesBuildPhase(["library.swift"]), + ], + ), + ]) + let core = try await getCore() + let tester = try await BuildOperationTester(core, testProject, simulated: false) + + let projectDir = tester.workspace.projects[0].sourceRoot + + try await tester.fs.writeFileContents(projectDir.join("library.swift")) { stream in + stream <<< "public func foo() -> Int { 42 }\n" + } + + try await tester.fs.writeFileContents(projectDir.join("test.swift")) { stream in + stream <<< """ + import Testing + import library + @Suite struct MySuite { + @Test func myTest() async throws { + #expect(foo() == 42) + } + } + """ + } + + let destination: RunDestinationInfo = .host + try await tester.checkBuild(runDestination: destination, persistent: true) { results in + results.checkNoErrors() + + let toolchain = try #require(try await getCore().toolchainRegistry.defaultToolchain) + let environment: Environment + if destination.platform == "linux" { + environment = ["LD_LIBRARY_PATH": toolchain.path.join("usr/lib/swift/linux").str] + } else { + environment = .init() + } + + let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: projectDir.join("build").join("Debug\(destination.builtProductsDirSuffix)").join(core.hostOperatingSystem.imageFormat.executableName(basename: "test.xctest")).str), arguments: ["--testing-library", "swift-testing"], environment: environment) + #expect(String(decoding: executionResult.stderr, as: UTF8.self).contains("Test run started")) + } + } + } + /// Check that environment variables are propagated from the user environment correctly. @Test(.requireSDKs(.host), .skipHostOS(.windows), .requireSystemPackages(apt: "yacc", yum: "byacc")) func userEnvironment() async throws { @@ -2773,7 +2870,6 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script "GENERATE_INFOPLIST_FILE": "YES", "FRAMEWORK_SEARCH_PATHS": "$(inherited) \(tmpDirPath.str)", "COPY_PHASE_STRIP": "NO", - "STRIP_BITCODE_FROM_COPIED_FILES": "NO", "SDKROOT": "macosx", "INSTALLLOC_LANGUAGE": "ja", "DSTROOT": tmpDirPath.join("DSTROOT").str @@ -2912,6 +3008,7 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script "GENERATE_INFOPLIST_FILE": "YES", "FRAMEWORK_SEARCH_PATHS": "$(inherited) \(tmpDirPath.str)", "COPY_PHASE_STRIP": "NO", + // Stripping bitcode varies by platform, and since it's not what we're testing here, we just turn it off. "STRIP_BITCODE_FROM_COPIED_FILES": "NO", "SDKROOT": runDestination.sdk, "SUPPORTS_MACCATALYST": runDestination.sdkVariant == MacCatalystInfo.sdkVariantName ? "YES" : "NO" @@ -3792,8 +3889,8 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script } if !shouldFilterSwiftLibs { - #expect(dependencyInfo.inputs.contains(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftCore.dylib").str)) - #expect(dependencyInfo.inputs.contains(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftFoundation.dylib").str)) + #expect(dependencyInfo.inputs.contains(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftCore.dylib").str)) + #expect(dependencyInfo.inputs.contains(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftFoundation.dylib").str)) #expect(dependencyInfo.outputs.sorted().contains(expectedDependencyInfo.outputs.sorted())) #expect(dependencyInfo.outputs.contains(buildDir.join("App.app/Contents/Frameworks/libswiftCore.dylib").str)) #expect(dependencyInfo.outputs.contains(buildDir.join("App.app/Contents/Frameworks/libswiftFoundation.dylib").str)) @@ -3801,8 +3898,8 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script if shouldBackDeploySwiftConcurrency { // Note all toolchains have this yet... - if tester.fs.exists(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib")) { - #expect(dependencyInfo.inputs.contains(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib").str)) + if tester.fs.exists(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib")) { + #expect(dependencyInfo.inputs.contains(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib").str)) #expect(dependencyInfo.outputs.contains(buildDir.join("App.app/Contents/Frameworks/libswift_Concurrency.dylib").str)) } } @@ -3821,7 +3918,7 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script let unitTestsExpectedDependencyInfo = DependencyInfo( version: "swift-stdlib-tool", inputs: ([ - core.developerPath.join("Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib").str, + core.developerPath.path.join("Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib").str, buildDir.join("UnitTests.xctest/Contents/MacOS/UnitTests").str, ]).sorted(), missing: [], @@ -3838,8 +3935,8 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script if !shouldFilterSwiftLibs { if (try Version(core.loadSDK(.macOS).defaultDeploymentTarget)) < Version(10, 15) { - #expect(unitTestsDependencyInfo.inputs.contains(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftCore.dylib").str)) - #expect(unitTestsDependencyInfo.inputs.contains(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftFoundation.dylib").str)) + #expect(unitTestsDependencyInfo.inputs.contains(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftCore.dylib").str)) + #expect(unitTestsDependencyInfo.inputs.contains(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/macosx/libswiftFoundation.dylib").str)) } #expect(unitTestsDependencyInfo.outputs.sorted().contains(unitTestsExpectedDependencyInfo.outputs.sorted())) if (try Version(core.loadSDK(.macOS).defaultDeploymentTarget)) < Version(10, 15) { @@ -3852,8 +3949,8 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script // NOTE: Tests have their deployment target overridden. if (try Version(core.loadSDK(.macOS).defaultDeploymentTarget)) < Version(10, 15) { // Note all toolchains have this yet... - if tester.fs.exists(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib")) { - #expect(unitTestsDependencyInfo.inputs.contains(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib").str)) + if tester.fs.exists(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib")) { + #expect(unitTestsDependencyInfo.inputs.contains(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib").str)) #expect(unitTestsDependencyInfo.outputs.contains(buildDir.join("SwiftlessApp.app/Contents/Frameworks/libswift_Concurrency.dylib").str)) } } @@ -3867,8 +3964,8 @@ That command depends on command in Target 'agg2' (project \'aProject\'): script if shouldBackDeploySwiftConcurrency { // Note all toolchains have this yet... - if tester.fs.exists(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib")) { - #expect(dependencyInfo.inputs.contains(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib").str)) + if tester.fs.exists(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib")) { + #expect(dependencyInfo.inputs.contains(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/libswift_Concurrency.dylib").str)) #expect(dependencyInfo.outputs.contains(buildDir.join("SwiftlessSysExApp.app/Contents/Frameworks/libswift_Concurrency.dylib").str)) } } diff --git a/Tests/SWBBuildSystemTests/BuildTaskBehaviorTests.swift b/Tests/SWBBuildSystemTests/BuildTaskBehaviorTests.swift index 9c4bf773..8c9b69f8 100644 --- a/Tests/SWBBuildSystemTests/BuildTaskBehaviorTests.swift +++ b/Tests/SWBBuildSystemTests/BuildTaskBehaviorTests.swift @@ -21,6 +21,7 @@ import SWBLibc import class SWBBuildSystem.BuildOperation import class SWBTaskExecution.Task +import SWBProtocol private final class MockTaskTypeDescription: TaskTypeDescription { init(isUnsafeToInterrupt: Bool = false) { @@ -206,7 +207,7 @@ fileprivate struct BuildTaskBehaviorTests: CoreBasedTests { /// Stress concurrent access to the build system cache during rapid cancel /// then build scenarios. - @Test(.requireSDKs(.host), .skipHostOS(.windows, "no /usr/bin/true"), + @Test(.requireSDKs(.host), .skipHostOS(.windows, "no /usr/bin/true"), .requireThreadSafeWorkingDirectory, // To aid in establishing the subtle concurrent // timing required to trigger chaos, we disable early build operation // cancellation. diff --git a/Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift b/Tests/SWBBuildSystemTests/ClangCompilationCachingTests.swift index cde5771d..20192674 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.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Clang compiler: 0 hits (0%), 1 miss").bytes)) + results.checkNote("0 hits (0%), 1 miss") 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.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Clang compiler: 1 hit (100%), 0 misses").bytes)) + results.checkNote("1 hit (100%), 0 misses") results.checkCompileCacheHit(compileTask) } results.checkNoDiagnostics() @@ -1672,7 +1672,7 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests { results.check(contains: .activityStarted(ruleInfo: "ClangCachingPruneData \(path.str)/builtin \(libClangPath.str)")) results.check(contains: .activityEnded(ruleInfo: "ClangCachingPruneData \(path.str)/builtin \(libClangPath.str)", status: .succeeded)) - results.checkRemark(.contains("cache miss: ")) + results.checkNote(.contains("cache miss: ")) results.checkNoRemarks() } @@ -1686,7 +1686,7 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests { results.check(notContains: .activityEnded(ruleInfo: "CleanupCompileCache \(path.str)", status: .succeeded)) if canUseCASPruning { - results.checkRemark(.regex(try Regex("cache size \\(.*\\) larger than size limit"))) + results.checkNote(.regex(try Regex("cache size \\(.*\\) larger than size limit"))) } } @@ -1708,7 +1708,7 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests { results.check(contains: .activityStarted(ruleInfo: "ClangCachingPruneData \(path.str)/builtin \(libClangPath.str)")) results.check(contains: .activityEnded(ruleInfo: "ClangCachingPruneData \(path.str)/builtin \(libClangPath.str)", status: .succeeded)) - results.checkRemark(.contains("cache miss: ")) + results.checkNote(.contains("cache miss: ")) results.checkNoRemarks() } } @@ -1836,12 +1836,22 @@ fileprivate struct ClangCompilationCachingTests: CoreBasedTests { } extension BuildOperationTester.BuildResults { - fileprivate func checkCompileCacheMiss(_ task: Task, file: StaticString = #file, line: UInt = #line) { - checkRemark(.contains("cache miss: ")) + fileprivate func checkCompileCacheMiss(_ task: Task, sourceLocation: SourceLocation = #_sourceLocation) { + let found = (getDiagnosticMessageForTask(.contains("cache miss: "), kind: .note, task: task) != nil) + guard found else { + Issue.record("Unable to find cache miss diagnostic for task \(task)", sourceLocation: sourceLocation) + return + } + check(contains: .taskHadEvent(task, event: .hadOutput(contents: "Cache miss\n")), sourceLocation: sourceLocation) } - fileprivate func checkCompileCacheHit(_ task: Task, file: StaticString = #file, line: UInt = #line) { - checkRemark(.contains("cache hit: ")) - while checkRemark(.contains("using CAS output"), failIfNotFound: false) {} + fileprivate func checkCompileCacheHit(_ task: Task, sourceLocation: SourceLocation = #_sourceLocation) { + let found = (getDiagnosticMessageForTask(.contains("cache hit: "), kind: .note, task: task) != nil) + guard found else { + Issue.record("Unable to find cache hit diagnostic for task \(task)", sourceLocation: sourceLocation) + return + } + while getDiagnosticMessageForTask(.contains("using CAS output"), kind: .note, task: task) != nil {} + check(contains: .taskHadEvent(task, event: .hadOutput(contents: "Cache hit\n")), sourceLocation: sourceLocation) } } diff --git a/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift b/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift index 9580afef..95d636b7 100644 --- a/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift +++ b/Tests/SWBBuildSystemTests/ClangExplicitModulesTests.swift @@ -617,7 +617,7 @@ fileprivate struct ClangExplicitModulesTests: CoreBasedTests { "CLANG_ENABLE_MODULES": "YES", "_EXPERIMENTAL_CLANG_EXPLICIT_MODULES": "YES", // This makes the Clang driver invocation expand into multiple -cc1 invocations. - "OTHER_CFLAGS": "-fembed-bitcode -save-temps=obj", + "OTHER_CFLAGS": "-save-temps=obj", ])], targets: [ TestStandardTarget( @@ -668,7 +668,6 @@ fileprivate struct ClangExplicitModulesTests: CoreBasedTests { // From -save-times=obj outputs.append(Path(obj.withoutSuffix + ".i")) - outputs.append(Path(obj.withoutSuffix + ".bc")) outputs.append(Path(obj.withoutSuffix + ".s")) for path in outputs { @@ -2970,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'") + 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')") case .yesError: - results.checkError("'Framework2' is missing a dependency on 'Framework1' because dependency scan of 'file_2.c' discovered a dependency on 'Framework1'") + 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')") default: break } diff --git a/Tests/SWBBuildSystemTests/CleanOperationTests.swift b/Tests/SWBBuildSystemTests/CleanOperationTests.swift index 0b4fabaf..549d1d5c 100644 --- a/Tests/SWBBuildSystemTests/CleanOperationTests.swift +++ b/Tests/SWBBuildSystemTests/CleanOperationTests.swift @@ -292,7 +292,7 @@ fileprivate struct CleanOperationTests: CoreBasedTests { groupTree: TestGroup("Sources", children: []), buildConfigurations: [TestBuildConfiguration("Debug", buildSettings: [:])], targets: [ - TestExternalTarget("external", toolPath: "\(try await getCore().developerPath.str)/usr/bin/make", arguments: "$(ACTION)", workingDirectory: sourceRoot.str, buildConfigurations: [TestBuildConfiguration("Debug", buildSettings: [:])], dependencies: [], passBuildSettingsInEnvironment: true) + TestExternalTarget("external", toolPath: "\(try await getCore().developerPath.path.str)/usr/bin/make", arguments: "$(ACTION)", workingDirectory: sourceRoot.str, buildConfigurations: [TestBuildConfiguration("Debug", buildSettings: [:])], dependencies: [], passBuildSettingsInEnvironment: true) ]) ]) let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false) @@ -318,7 +318,7 @@ fileprivate struct CleanOperationTests: CoreBasedTests { #expect(try tester.fs.read(sourceRoot.join("out.txt")) == "external\n") try await tester.checkBuild(runDestination: .macOS, buildCommand: .cleanBuildFolder(style: type), persistent: true) { results in - results.checkTask(.matchRule(["\(try await getCore().developerPath.str)/usr/bin/make", "clean"])) { _ in } + results.checkTask(.matchRule(["\(try await getCore().developerPath.path.str)/usr/bin/make", "clean"])) { _ in } results.checkNoTask() results.checkNoDiagnostics() } @@ -342,7 +342,7 @@ fileprivate struct CleanOperationTests: CoreBasedTests { try await withBasedProjectHarness { tester, _, _ in try await tester.checkBuild(runDestination: .macOS, buildCommand: .cleanBuildFolder(style: .legacy), persistent: false) { results in // CleanOperation.cleanExternalTarget() captures all of the output of the inferior tool - stdout and stderr - as part of the error message, which can include unrelated garbage (e.g. ObjC runtime reports of symbol collisions, reports of xcodebuild being relaunched under ASan), some of which might be expected, so we just check that there's an error which contains the expected string content to be robust to those scenarios. - results.checkError(.and(.prefix("Failed to clean target \'external\': "), .contains("make: *** No rule to make target `clean\'. Stop.\n (for task: [\"\(try await getCore().developerPath.str)/usr/bin/make\", \"clean\"])"))) + results.checkError(.and(.prefix("Failed to clean target \'external\': "), .contains("make: *** No rule to make target `clean\'. Stop.\n (for task: [\"\(try await getCore().developerPath.path.str)/usr/bin/make\", \"clean\"])"))) results.checkNoDiagnostics() } } diff --git a/Tests/SWBBuildSystemTests/CodeGenerationToolTests.swift b/Tests/SWBBuildSystemTests/CodeGenerationToolTests.swift index 22c74308..cb46d95a 100644 --- a/Tests/SWBBuildSystemTests/CodeGenerationToolTests.swift +++ b/Tests/SWBBuildSystemTests/CodeGenerationToolTests.swift @@ -17,6 +17,7 @@ import SWBTaskExecution import SWBTestSupport import SWBUtil import Testing +import SWBProtocol @Suite fileprivate struct CodeGenerationToolTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/DependencyValidationTests.swift b/Tests/SWBBuildSystemTests/DependencyValidationTests.swift index 7780a36a..3eb2afc8 100644 --- a/Tests/SWBBuildSystemTests/DependencyValidationTests.swift +++ b/Tests/SWBBuildSystemTests/DependencyValidationTests.swift @@ -14,6 +14,7 @@ import SWBCore import SWBTestSupport import SWBUtil import Testing +import SWBProtocol @Suite fileprivate struct DependencyValidationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/DevelopmentAssetsDiagnosticTests.swift b/Tests/SWBBuildSystemTests/DevelopmentAssetsDiagnosticTests.swift index e4e285ef..5f97c1e4 100644 --- a/Tests/SWBBuildSystemTests/DevelopmentAssetsDiagnosticTests.swift +++ b/Tests/SWBBuildSystemTests/DevelopmentAssetsDiagnosticTests.swift @@ -15,6 +15,8 @@ import Testing import SWBCore import SWBUtil import SWBTestSupport +import SWBTaskExecution +import SWBProtocol @Suite fileprivate struct DevelopmentAssetsDiagnosticTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/DriverKitBuildOperationTests.swift b/Tests/SWBBuildSystemTests/DriverKitBuildOperationTests.swift index d2b1c646..72c897e8 100644 --- a/Tests/SWBBuildSystemTests/DriverKitBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/DriverKitBuildOperationTests.swift @@ -15,6 +15,7 @@ import Testing import SWBCore import SWBUtil import SWBTestSupport +import Foundation @Suite fileprivate struct DriverKitBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/DsymGenerationBuildOperationTests.swift b/Tests/SWBBuildSystemTests/DsymGenerationBuildOperationTests.swift index b2013ac1..db117150 100644 --- a/Tests/SWBBuildSystemTests/DsymGenerationBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/DsymGenerationBuildOperationTests.swift @@ -15,6 +15,8 @@ import Testing import SWBCore import SWBTestSupport import SWBUtil +import SWBMacro +import SWBProtocol @Suite fileprivate struct DsymGenerationBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift b/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift index 12327b3d..2f77cc1a 100644 --- a/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/EntitlementsBuildOperationTests.swift @@ -20,6 +20,7 @@ import struct SWBProtocol.TargetDependencyRelationship import SWBTestSupport import SWBTaskExecution import SWBUtil +import SwiftBuildTestSupport @Suite fileprivate struct EntitlementsBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/ExportLocBuildOperationTests.swift b/Tests/SWBBuildSystemTests/ExportLocBuildOperationTests.swift index 1bad334b..2f9b9e5a 100644 --- a/Tests/SWBBuildSystemTests/ExportLocBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/ExportLocBuildOperationTests.swift @@ -16,6 +16,7 @@ import SWBCore import SWBTaskExecution import SWBTestSupport import SWBUtil +import SWBProtocol @Suite fileprivate struct ExportLocBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/IndexBuildOperationTests.swift b/Tests/SWBBuildSystemTests/IndexBuildOperationTests.swift index 8a6ce13c..70ce2ea7 100644 --- a/Tests/SWBBuildSystemTests/IndexBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/IndexBuildOperationTests.swift @@ -22,6 +22,7 @@ import class SWBTaskConstruction.ProductPlan import SWBTestSupport import SWBTaskExecution import SWBUtil +import SWBMacro @Suite fileprivate struct IndexBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/InfoPlistBuildOperationTests.swift b/Tests/SWBBuildSystemTests/InfoPlistBuildOperationTests.swift index 9d4b9ce8..64720f25 100644 --- a/Tests/SWBBuildSystemTests/InfoPlistBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/InfoPlistBuildOperationTests.swift @@ -14,6 +14,8 @@ import SWBCore import SWBTestSupport import SWBUtil import Testing +import SWBProtocol +import SWBTaskExecution @Suite fileprivate struct InfoPlistBuildOperationTests: CoreBasedTests { @@ -116,14 +118,14 @@ fileprivate struct InfoPlistBuildOperationTests: CoreBasedTests { for arch in ["arm64", "x86_64"] { // There should be an Info.plist processing task, and associated Preprocess (we explicitly enable it). results.checkTask(.matchTargetName("Tool"), .matchRule(["Preprocess", "\(SRCROOT)/build/aProject.build/Release/Tool.build/normal/\(arch)/Preprocessed-Info.plist", "\(SRCROOT)/Tool.plist"])) { task in - task.checkCommandLine(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc", "-E", "-P", "-x", "c", "-Wno-trigraphs", "\(SRCROOT)/Tool.plist", "-F\(SRCROOT)/build/Release", "-target", "\(arch)-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", core.loadSDK(.macOS).path.str, "-o", "\(SRCROOT)/build/aProject.build/Release/Tool.build/normal/\(arch)/Preprocessed-Info.plist"]) + task.checkCommandLine(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc", "-E", "-P", "-x", "c", "-Wno-trigraphs", "\(SRCROOT)/Tool.plist", "-F\(SRCROOT)/build/Release", "-target", "\(arch)-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", core.loadSDK(.macOS).path.str, "-o", "\(SRCROOT)/build/aProject.build/Release/Tool.build/normal/\(arch)/Preprocessed-Info.plist"]) } } for arch in ["arm64", "x86_64"] { // There should be an Info.plist processing task, and associated Preprocess (we explicitly enable it). results.checkTask(.matchTargetName("App"), .matchRule(["Preprocess", "\(SRCROOT)/build/aProject.build/Release/App.build/normal/\(arch)/Preprocessed-Info.plist", "\(SRCROOT)/Tool.plist"])) { task in - task.checkCommandLine(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc", "-E", "-P", "-x", "c", "-Wno-trigraphs", "\(SRCROOT)/Tool.plist", "-F\(SRCROOT)/build/Release", "-target", "\(arch)-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", core.loadSDK(.macOS).path.str, "-o", "\(SRCROOT)/build/aProject.build/Release/App.build/normal/\(arch)/Preprocessed-Info.plist"]) + task.checkCommandLine(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc", "-E", "-P", "-x", "c", "-Wno-trigraphs", "\(SRCROOT)/Tool.plist", "-F\(SRCROOT)/build/Release", "-target", "\(arch)-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", core.loadSDK(.macOS).path.str, "-o", "\(SRCROOT)/build/aProject.build/Release/App.build/normal/\(arch)/Preprocessed-Info.plist"]) } } diff --git a/Tests/SWBBuildSystemTests/InstrumentsPackageBuildOperationTests.swift b/Tests/SWBBuildSystemTests/InstrumentsPackageBuildOperationTests.swift index 936900b5..1dc85f60 100644 --- a/Tests/SWBBuildSystemTests/InstrumentsPackageBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/InstrumentsPackageBuildOperationTests.swift @@ -13,7 +13,8 @@ import SWBCore import SWBTestSupport import SWBUtil -import Testing +import SWBProtocol +import SwiftBuildTestSupport import Testing diff --git a/Tests/SWBBuildSystemTests/LinkerTests.swift b/Tests/SWBBuildSystemTests/LinkerTests.swift index 8352a7fc..184f51d2 100644 --- a/Tests/SWBBuildSystemTests/LinkerTests.swift +++ b/Tests/SWBBuildSystemTests/LinkerTests.swift @@ -16,6 +16,8 @@ import Testing import SWBBuildSystem import SWBCore import SWBProtocol +import Foundation +import SWBTaskExecution @Suite fileprivate struct LinkerTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/MergeableLibrariesBuildOperationTests.swift b/Tests/SWBBuildSystemTests/MergeableLibrariesBuildOperationTests.swift index 1021cc20..ce5ed097 100644 --- a/Tests/SWBBuildSystemTests/MergeableLibrariesBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/MergeableLibrariesBuildOperationTests.swift @@ -18,6 +18,11 @@ import SwiftBuildTestSupport import struct SWBProtocol.RunDestinationInfo import SWBCore import class SwiftBuild.SWBBuildService +import SWBTaskExecution + +#if canImport(Darwin) +import MachO +#endif @Suite(.requireXcode16()) fileprivate struct MergeableLibrariesBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/PackageBuildOperationTests.swift b/Tests/SWBBuildSystemTests/PackageBuildOperationTests.swift index 3ab12806..d854664c 100644 --- a/Tests/SWBBuildSystemTests/PackageBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/PackageBuildOperationTests.swift @@ -247,7 +247,7 @@ fileprivate struct PackageBuildOperationTests: CoreBasedTests { try results.checkTask(.matchRuleType("RealityAssetsCompile")) { task in task.checkCommandLineContainsUninterrupted([ - core.developerPath.join("usr/bin/realitytool").str, "compile", "--platform", "xros", "--deployment-target", results.runDestinationSDK.defaultDeploymentTarget, + core.developerPath.path.join("usr/bin/realitytool").str, "compile", "--platform", "xros", "--deployment-target", results.runDestinationSDK.defaultDeploymentTarget, "-o", "\(workspace.sourceRoot.str)/aProject/build/Debug-xros/PackageLib.bundle/test.reality", "\(packageRKAssetsFile.str)", "--schema-file", @@ -275,7 +275,7 @@ fileprivate struct PackageBuildOperationTests: CoreBasedTests { try results.checkTask(.matchRuleType("RealityAssetsCompile")) { task in task.checkCommandLineContainsUninterrupted([ - core.developerPath.join("usr/bin/realitytool").str, "compile", "--platform", "xros", "--deployment-target", results.runDestinationSDK.defaultDeploymentTarget, + core.developerPath.path.join("usr/bin/realitytool").str, "compile", "--platform", "xros", "--deployment-target", results.runDestinationSDK.defaultDeploymentTarget, "-o", "\(workspace.sourceRoot.str)/aProject/build/Debug-xros/PackageLib.bundle/test.reality", "\(packageRKAssetsFile.str)", "--schema-file", diff --git a/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift b/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift index 2ea40bce..7df199bf 100644 --- a/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/PreviewsBuildOperationTests.swift @@ -18,6 +18,8 @@ import SWBTestSupport import SWBProtocol import SWBCore @_spi(Testing) import SWBBuildService +import SWBTaskExecution +import SwiftBuildTestSupport @Suite(.requireXcode16()) fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { @@ -125,7 +127,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { // For the regular build we should expect to run the thinned asset catalog task results.checkTask(.matchRuleType("CompileAssetCatalogVariant")) { task in task.checkRuleInfo(["CompileAssetCatalogVariant", "thinned", "\(srcRoot.str)/build/Debug-iphonesimulator/AppTarget.app", "\(srcRoot.str)/Sources/Assets.xcassets"]) - task.checkCommandLine(["\(core.developerPath.str)/usr/bin/actool", "\(srcRoot.str)/Sources/Assets.xcassets", "--compile", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_output/thinned", "--output-format", "human-readable-text", "--notices", "--warnings", "--export-dependency-info", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_dependencies_thinned", "--output-partial-info-plist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_generated_info.plist_thinned", "--app-icon", "AppIcon", "--compress-pngs", "--enable-on-demand-resources", "YES", "--filter-for-thinning-device-configuration", "iPhone15,2", "--filter-for-device-os-version", core.loadSDK(.iOSSimulator).defaultDeploymentTarget, "--development-region", "English", "--target-device", "iphone", "--minimum-deployment-target", core.loadSDK(.iOSSimulator).defaultDeploymentTarget, "--platform", "iphonesimulator"]) + task.checkCommandLine(["\(core.developerPath.path.str)/usr/bin/actool", "\(srcRoot.str)/Sources/Assets.xcassets", "--compile", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_output/thinned", "--output-format", "human-readable-text", "--notices", "--warnings", "--export-dependency-info", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_dependencies_thinned", "--output-partial-info-plist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_generated_info.plist_thinned", "--app-icon", "AppIcon", "--compress-pngs", "--enable-on-demand-resources", "YES", "--filter-for-thinning-device-configuration", "iPhone15,2", "--filter-for-device-os-version", core.loadSDK(.iOSSimulator).defaultDeploymentTarget, "--development-region", "English", "--target-device", "iphone", "--minimum-deployment-target", core.loadSDK(.iOSSimulator).defaultDeploymentTarget, "--platform", "iphonesimulator"]) } results.checkTask(.matchRuleType("LinkAssetCatalog")) { task in @@ -143,7 +145,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { results.checkTask(.matchRule(["Ld", "\(srcRoot.str)/build/Debug-iphonesimulator/AppTarget.app/AppTarget", "normal"])) { task in task.checkCommandLine( [ - "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", + "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-Xlinker", "-reproducible", "-target", "\(results.runDestinationTargetArchitecture)-apple-ios\(core.loadSDK(.iOSSimulator).defaultDeploymentTarget)-simulator", "-isysroot", core.loadSDK(.iOSSimulator).path.str, @@ -209,7 +211,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { XCTAssertEqualSequences( compileCommandLine, [ - "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend", + "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend", "-frontend", "-c", "-primary-file", @@ -306,7 +308,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { linkerCommandLine.remove(at: idx) } } - XCTAssertEqualSequences(linkerCommandLine, ["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-Xlinker", "-reproducible", "-target", "\(results.runDestinationTargetArchitecture)-apple-ios\(core.loadSDK(.iOSSimulator).defaultDeploymentTarget)-simulator", "-dynamiclib", "-isysroot", core.loadSDK(.iOSSimulator).path.str, "-Os", "-Xlinker", "-warn_unused_dylibs", "-L\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-L\(srcRoot.str)/build/Debug-iphonesimulator", "-F\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-F\(srcRoot.str)/build/Debug-iphonesimulator", "-filelist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.LinkFileList", "-install_name", "@rpath/AppTarget.debug.dylib", "-dead_strip", "-Xlinker", "-object_path_lto", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_lto.o", "-Xlinker", "-objc_abi_version", "-Xlinker", "2", "-Xlinker", "-dependency_info", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_dependency_info.dat", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.swiftmodule", "-Xlinker", "-alias", "-Xlinker", "_main", "-Xlinker", "___debug_main_executable_dylib_entry_point", "-Xlinker", "-no_adhoc_codesign", "-o", "\(srcRoot.str)/build/Debug-iphonesimulator/AppTarget.app/AppTarget.debug.dylib"]) + XCTAssertEqualSequences(linkerCommandLine, ["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-Xlinker", "-reproducible", "-target", "\(results.runDestinationTargetArchitecture)-apple-ios\(core.loadSDK(.iOSSimulator).defaultDeploymentTarget)-simulator", "-dynamiclib", "-isysroot", core.loadSDK(.iOSSimulator).path.str, "-Os", "-Xlinker", "-warn_unused_dylibs", "-L\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-L\(srcRoot.str)/build/Debug-iphonesimulator", "-F\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-F\(srcRoot.str)/build/Debug-iphonesimulator", "-filelist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.LinkFileList", "-install_name", "@rpath/AppTarget.debug.dylib", "-dead_strip", "-Xlinker", "-object_path_lto", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_lto.o", "-Xlinker", "-objc_abi_version", "-Xlinker", "2", "-Xlinker", "-dependency_info", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_dependency_info.dat", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.swiftmodule", "-Xlinker", "-alias", "-Xlinker", "_main", "-Xlinker", "___debug_main_executable_dylib_entry_point", "-Xlinker", "-no_adhoc_codesign", "-o", "\(srcRoot.str)/build/Debug-iphonesimulator/AppTarget.app/AppTarget.debug.dylib"]) } } @@ -338,7 +340,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { // For the preview build we should expect to run the unthinned asset catalog task results.checkTask(.matchRuleType("CompileAssetCatalogVariant")) { task in task.checkRuleInfo(["CompileAssetCatalogVariant", "unthinned", "\(srcRoot.str)/build/Debug-iphonesimulator/AppTarget.app", "\(srcRoot.str)/Sources/Assets.xcassets"]) - task.checkCommandLine(["\(core.developerPath.str)/usr/bin/actool", "\(srcRoot.str)/Sources/Assets.xcassets", "--compile", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_output/unthinned", "--output-format", "human-readable-text", "--notices", "--warnings", "--export-dependency-info", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_dependencies_unthinned", "--output-partial-info-plist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_generated_info.plist_unthinned", "--app-icon", "AppIcon", "--compress-pngs", "--enable-on-demand-resources", "YES", "--development-region", "English", "--target-device", "iphone", "--minimum-deployment-target", core.loadSDK(.iOSSimulator).defaultDeploymentTarget, "--platform", "iphonesimulator"]) + task.checkCommandLine(["\(core.developerPath.path.str)/usr/bin/actool", "\(srcRoot.str)/Sources/Assets.xcassets", "--compile", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_output/unthinned", "--output-format", "human-readable-text", "--notices", "--warnings", "--export-dependency-info", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_dependencies_unthinned", "--output-partial-info-plist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/assetcatalog_generated_info.plist_unthinned", "--app-icon", "AppIcon", "--compress-pngs", "--enable-on-demand-resources", "YES", "--development-region", "English", "--target-device", "iphone", "--minimum-deployment-target", core.loadSDK(.iOSSimulator).defaultDeploymentTarget, "--platform", "iphonesimulator"]) } // And we should link into place again, because the inputs (e.g. the unthinned catalog) changed @@ -510,7 +512,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { XCTAssertEqualSequences( compileCommandLine, [ - "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend", + "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend", "-frontend", "-c", "\(srcRoot.str)/Sources/main.swift", @@ -613,7 +615,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { linkerCommandLine.remove(at: idx) } } - XCTAssertEqualSequences(linkerCommandLine, ["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-Xlinker", "-reproducible", "-target", "\(results.runDestinationTargetArchitecture)-apple-ios\(core.loadSDK(.iOSSimulator).defaultDeploymentTarget)-simulator", "-dynamiclib", "-isysroot", core.loadSDK(.iOSSimulator).path.str, "-Os", "-L\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-L\(srcRoot.str)/build/Debug-iphonesimulator", "-F\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-F\(srcRoot.str)/build/Debug-iphonesimulator", "-filelist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.LinkFileList", "-install_name", "@rpath/AppTarget.debug.dylib", "-dead_strip", "-Xlinker", "-object_path_lto", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_lto.o", "-Xlinker", "-objc_abi_version", "-Xlinker", "2", "-Xlinker", "-dependency_info", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.swiftmodule", "-Xlinker", "-alias", "-Xlinker", "_main", "-Xlinker", "___debug_main_executable_dylib_entry_point", "-Xlinker", "-no_adhoc_codesign", "-o", "\(srcRoot.str)/build/Debug-iphonesimulator/AppTarget.app/AppTarget.debug.dylib"]) + XCTAssertEqualSequences(linkerCommandLine, ["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-Xlinker", "-reproducible", "-target", "\(results.runDestinationTargetArchitecture)-apple-ios\(core.loadSDK(.iOSSimulator).defaultDeploymentTarget)-simulator", "-dynamiclib", "-isysroot", core.loadSDK(.iOSSimulator).path.str, "-Os", "-L\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-L\(srcRoot.str)/build/Debug-iphonesimulator", "-F\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphonesimulator", "-F\(srcRoot.str)/build/Debug-iphonesimulator", "-filelist", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.LinkFileList", "-install_name", "@rpath/AppTarget.debug.dylib", "-dead_strip", "-Xlinker", "-object_path_lto", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_lto.o", "-Xlinker", "-objc_abi_version", "-Xlinker", "2", "-Xlinker", "-dependency_info", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(srcRoot.str)/build/ProjectName.build/Debug-iphonesimulator/AppTarget.build/Objects-normal/\(results.runDestinationTargetArchitecture)/AppTarget.swiftmodule", "-Xlinker", "-alias", "-Xlinker", "_main", "-Xlinker", "___debug_main_executable_dylib_entry_point", "-Xlinker", "-no_adhoc_codesign", "-o", "\(srcRoot.str)/build/Debug-iphonesimulator/AppTarget.app/AppTarget.debug.dylib"]) } } } @@ -762,7 +764,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { results.checkTask(.matchRule(["Ld", "\(srcRoot.str)/build/Debug-iphonesimulator/AppExTarget.appex/AppExTarget", "normal"])) { task in task.checkCommandLine( [ - "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", + "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-Xlinker", "-reproducible", "-target", "\(results.runDestinationTargetArchitecture)-apple-ios\(core.loadSDK(.iOSSimulator).defaultDeploymentTarget)-simulator", "-isysroot", core.loadSDK(.iOSSimulator).path.str, @@ -1114,7 +1116,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { } XCTAssertEqualSequences(compileCommandLine, [[ - "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", + "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-enforce-exclusivity=checked", "-enable-experimental-feature", "DebugDescriptionMacro", "-sdk", sdkPath.str, @@ -1168,7 +1170,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { } XCTAssertEqualSequences(linkerCommandLine, [[ - "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", + "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-Xlinker", "-reproducible", "-target", "\(arch)-apple-ios\(core.loadSDK(.iOS).defaultDeploymentTarget)", "-isysroot", sdkPath.str, @@ -1178,7 +1180,7 @@ fileprivate struct PreviewsBuildOperationTests: CoreBasedTests { "-F\(srcRoot.str)/build/EagerLinkingTBDs/Debug-iphoneos", "-F\(srcRoot.str)/build/Debug-iphoneos", "-fobjc-link-runtime", - "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos", + "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos", "-L/usr/lib/swift", ], linkStyleArgs, [ "\(srcRoot.str)/build/ProjectName.build/Debug-iphoneos/\(targetName).build/Objects-normal/\(arch)/main.selection.preview-thunk.o", diff --git a/Tests/SWBBuildSystemTests/RebuildTests.swift b/Tests/SWBBuildSystemTests/RebuildTests.swift index 55521896..1ed9fb98 100644 --- a/Tests/SWBBuildSystemTests/RebuildTests.swift +++ b/Tests/SWBBuildSystemTests/RebuildTests.swift @@ -15,6 +15,7 @@ import Testing import SWBCore import SWBTestSupport import SWBUtil +import SWBProtocol /// Test suite for tests specifically examining rebuilding projects in interesting scenarios. @Suite diff --git a/Tests/SWBBuildSystemTests/SceneKitBuildOperationTests.swift b/Tests/SWBBuildSystemTests/SceneKitBuildOperationTests.swift index cd65b3d3..918f1936 100644 --- a/Tests/SWBBuildSystemTests/SceneKitBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/SceneKitBuildOperationTests.swift @@ -14,6 +14,7 @@ import Testing import SWBTestSupport import SWBUtil +import SWBCore @Suite fileprivate struct SceneKitBuildOperationTests: CoreBasedTests { @@ -74,28 +75,28 @@ fileprivate struct SceneKitBuildOperationTests: CoreBasedTests { try await tester.checkBuild(runDestination: .macOS) { results in results.checkTask(.matchRuleType("Process"), .matchRuleItemBasename("A.dae")) { task in task.checkRuleInfo(["Process", "SceneKit", "document", "\(SRCROOT)/Sources/A.dae"]) - task.checkCommandLineContains([core.developerPath.join("usr").join("bin").join("scntool").str, "--compress", "\(SRCROOT)/Sources/A.dae"]) + task.checkCommandLineContains([core.developerPath.path.join("usr").join("bin").join("scntool").str, "--compress", "\(SRCROOT)/Sources/A.dae"]) task.checkEnvironment([:], exact: true) } results.checkTask(.matchRuleType("Process"), .matchRuleItemBasename("B.dae")) { task in task.checkRuleInfo(["Process", "SceneKit", "document", "\(SRCROOT)/Sources/B.dae"]) - task.checkCommandLineContains([core.developerPath.join("usr").join("bin").join("scntool").str, "--decompress", "\(SRCROOT)/Sources/B.dae"]) + task.checkCommandLineContains([core.developerPath.path.join("usr").join("bin").join("scntool").str, "--decompress", "\(SRCROOT)/Sources/B.dae"]) task.checkEnvironment([:], exact: true) } results.checkTask(.matchRuleType("Process"), .matchRuleItemBasename("C.DAE")) { task in task.checkRuleInfo(["Process", "SceneKit", "document", "\(SRCROOT)/Sources/C.DAE"]) - task.checkCommandLineContains([core.developerPath.join("usr").join("bin").join("scntool").str, "--compress", "\(SRCROOT)/Sources/C.DAE", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/Resources/C.dae"]) + task.checkCommandLineContains([core.developerPath.path.join("usr").join("bin").join("scntool").str, "--compress", "\(SRCROOT)/Sources/C.DAE", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/Resources/C.dae"]) task.checkEnvironment([:], exact: true) } results.checkTask(.matchRuleType("Copy"), .matchRuleItemBasename("D.scnassets")) { task in task.checkRuleInfo(["Copy", "SceneKit", "assets", "\(SRCROOT)/Sources/D.scnassets"]) - task.checkCommandLineContainsUninterrupted(["\(core.developerPath.str)/usr/bin/copySceneKitAssets", "\(SRCROOT)/Sources/D.scnassets", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/Resources/D.scnassets", "--target-platform=macosx", "--target-version=\(core.loadSDK(.macOS).defaultDeploymentTarget)"]) + task.checkCommandLineContainsUninterrupted(["\(core.developerPath.path.str)/usr/bin/copySceneKitAssets", "\(SRCROOT)/Sources/D.scnassets", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/Resources/D.scnassets", "--target-platform=macosx", "--target-version=\(core.loadSDK(.macOS).defaultDeploymentTarget)"]) task.checkCommandLineContainsUninterrupted([ "--target-build-dir=\(SRCROOT)/build/Debug", "--resources-folder-path=App.app/Contents/Resources"]) task.checkEnvironment([:], exact: true) } results.checkTask(.matchRuleType("Compile"), .matchRuleItemBasename("E.scncache")) { task in task.checkRuleInfo(["Compile", "SceneKit", "Shaders", "\(SRCROOT)/Sources/E.scncache"]) - task.checkCommandLineContainsUninterrupted(["\(core.developerPath.str)/usr/bin/compileSceneKitShaders", "\(SRCROOT)/Sources/E.scncache", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/Resources/scenekit.metallib", "--target-platform=macosx", "--target-version=\(core.loadSDK(.macOS).defaultDeploymentTarget)"]) + task.checkCommandLineContainsUninterrupted(["\(core.developerPath.path.str)/usr/bin/compileSceneKitShaders", "\(SRCROOT)/Sources/E.scncache", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/Resources/scenekit.metallib", "--target-platform=macosx", "--target-version=\(core.loadSDK(.macOS).defaultDeploymentTarget)"]) task.checkCommandLineContainsUninterrupted(["--target-build-dir=\(SRCROOT)/build/Debug", "--resources-folder-path=App.app/Contents/Resources", "--intermediate-dir=\(SRCROOT)/build/aProject.build/Debug/App.build"]) task.checkEnvironment([:], exact: true) } diff --git a/Tests/SWBBuildSystemTests/SpriteKitBuildOperationTests.swift b/Tests/SWBBuildSystemTests/SpriteKitBuildOperationTests.swift index dd6bbe81..45b6735d 100644 --- a/Tests/SWBBuildSystemTests/SpriteKitBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/SpriteKitBuildOperationTests.swift @@ -16,6 +16,8 @@ import SWBTestSupport import SWBUtil import Testing +import SwiftBuildTestSupport +import SWBCore @Suite fileprivate struct SpriteKitBuildOperationTests: CoreBasedTests { @@ -58,7 +60,7 @@ fileprivate struct SpriteKitBuildOperationTests: CoreBasedTests { try await tester.checkBuild(runDestination: .macOS) { results in try results.checkTask(.matchRuleType("GenerateTextureAtlas")) { task in task.checkRuleInfo(["GenerateTextureAtlas", "\(SRCROOT)/build/Debug/App.app/Contents/Resources/assets.atlasc", "\(SRCROOT)/Sources/assets.atlas"]) - task.checkCommandLine(["\(core.developerPath.str)/usr/bin/TextureAtlas", "\(SRCROOT)/Sources/assets.atlas", "\(SRCROOT)/build/Debug/App.app/Contents/Resources"]) + task.checkCommandLine(["\(core.developerPath.path.str)/usr/bin/TextureAtlas", "\(SRCROOT)/Sources/assets.atlas", "\(SRCROOT)/build/Debug/App.app/Contents/Resources"]) task.checkEnvironment([:], exact: true) try results.checkPropertyListContents(Path("\(SRCROOT)/build/Debug/App.app/Contents/Resources/assets.atlasc/assets.plist")) { plist in diff --git a/Tests/SWBBuildSystemTests/StaleFileRemovalTests.swift b/Tests/SWBBuildSystemTests/StaleFileRemovalTests.swift index 1588691c..e927e72c 100644 --- a/Tests/SWBBuildSystemTests/StaleFileRemovalTests.swift +++ b/Tests/SWBBuildSystemTests/StaleFileRemovalTests.swift @@ -19,6 +19,7 @@ import SWBTestSupport import SWBUtil import SWBTaskExecution +import SWBProtocol @Suite fileprivate struct StaleFileRemovalTests: CoreBasedTests { diff --git a/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift b/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift index 2a4f3d05..4a82aacd 100644 --- a/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift +++ b/Tests/SWBBuildSystemTests/SwiftCompilationCachingTests.swift @@ -96,6 +96,7 @@ fileprivate struct SwiftCompilationCachingTests: CoreBasedTests { results.checkTask(.matchTargetName("Application"), .matchRule(["SwiftCompile", "normal", "arm64", "Compiling App.swift", "\(tmpDirPath.str)/Test/aProject/App.swift"])) { task in task.checkCommandLineMatches([.suffix("swift-frontend"), .anySequence, "-cache-compile-job", .anySequence]) numCompile += 1 + results.checkKeyQueryCacheMiss(task) } results.checkTask(.matchTargetName("Application"), .matchRule(["SwiftEmitModule", "normal", "arm64", "Emitting module for Application"])) { _ in } @@ -109,7 +110,7 @@ fileprivate struct SwiftCompilationCachingTests: CoreBasedTests { numCompile += tasks.count } - results.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Swift compiler: 0 hits (0%), 4 misses").bytes)) + results.checkNote("0 hits (0%), 4 misses") results.checkNoTask() } @@ -121,19 +122,104 @@ fileprivate struct SwiftCompilationCachingTests: CoreBasedTests { tester.userInfo = rawUserInfo.withAdditionalEnvironment(environment: metricsEnv("two")) try await tester.checkBuild(runDestination: .anyiOSDevice, persistent: true) { results in - results.check(contains: .activityEmittedData(ruleInfo: "CompilationCacheMetrics", ByteString(encodingAsUTF8: "Swift compiler: 4 hits (100%), 0 misses").bytes)) + results.checkTask(.matchRule(["SwiftCompile", "normal", "arm64", "Compiling App.swift", "\(tmpDirPath.str)/Test/aProject/App.swift"])) { task in + results.checkKeyQueryCacheHit(task) + } + + results.checkNote("4 hits (100%), 0 misses") } #expect(try readMetrics("two").contains("\"swiftCacheHits\":\(numCompile),\"swiftCacheMisses\":0")) } } + + @Test(.requireSDKs(.macOS)) + func swiftCASLimiting() async throws { + try await withTemporaryDirectory { (tmpDirPath: Path) async throws -> Void in + let testWorkspace = try await TestWorkspace( + "Test", + sourceRoot: tmpDirPath.join("Test"), + projects: [ + TestProject( + "aProject", + groupTree: TestGroup( + "Sources", + children: [ + TestFile("main.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "macosx", + "SWIFT_VERSION": swiftVersion, + "SWIFT_ENABLE_EXPLICIT_MODULES": "YES", + "SWIFT_ENABLE_COMPILE_CACHE": "YES", + "COMPILATION_CACHE_ENABLE_DIAGNOSTIC_REMARKS": "YES", + "COMPILATION_CACHE_LIMIT_SIZE": "1", + "COMPILATION_CACHE_CAS_PATH": tmpDirPath.join("CompilationCache").str, + "DSTROOT": tmpDirPath.join("dstroot").str, + ]), + ], + targets: [ + TestStandardTarget( + "tool", + type: .framework, + buildPhases: [ + TestSourcesBuildPhase([ + "main.swift", + ]), + ] + ) + ]) + ]) + let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false) + + try await tester.fs.writeFileContents(tmpDirPath.join("Test/aProject/main.swift")) { + $0 <<< "let x = 1\n" + } + + try await tester.checkBuild(runDestination: .macOS, persistent: true) { results in + results.checkTask(.matchRuleType("SwiftCompile")) { results.checkKeyQueryCacheMiss($0) } + } + try await tester.checkBuild(runDestination: .macOS, buildCommand: .cleanBuildFolder(style: .regular), body: { _ in }) + + // Update the source file and rebuild. + try await tester.fs.writeFileContents(tmpDirPath.join("Test/aProject/main.swift")) { + $0 <<< "let x = 2\n" + } + try await tester.checkBuild(runDestination: .macOS, persistent: true) { results in + results.checkTask(.matchRuleType("SwiftCompile")) { results.checkKeyQueryCacheMiss($0) } + } + try await tester.checkBuild(runDestination: .macOS, buildCommand: .cleanBuildFolder(style: .regular), body: { _ in }) + + // Revert the source change and rebuild. It should still be a cache miss because of CAS size limiting. + try await tester.fs.writeFileContents(tmpDirPath.join("Test/aProject/main.swift")) { + $0 <<< "let x = 1\n" + } + try await tester.checkBuild(runDestination: .macOS, persistent: true) { results in + results.checkTask(.matchRuleType("SwiftCompile")) { results.checkKeyQueryCacheMiss($0) } + } + } + } } extension BuildOperationTester.BuildResults { - fileprivate func checkKeyQueryCacheMiss(_ task: Task, file: StaticString = #file, line: UInt = #line) { - checkRemark(.contains("cache key query miss")) + fileprivate func checkKeyQueryCacheMiss(_ task: Task, sourceLocation: SourceLocation = #_sourceLocation) { + let found = (getDiagnosticMessageForTask(.contains("cache miss"), kind: .note, task: task) != nil) + guard found else { + Issue.record("Unable to find cache miss diagnostic for task \(task)", sourceLocation: sourceLocation) + return + } + check(contains: .taskHadEvent(task, event: .hadOutput(contents: "Cache miss\n")), sourceLocation: sourceLocation) } - fileprivate func checkKeyQueryCacheHit(_ task: Task, file: StaticString = #file, line: UInt = #line) { - checkRemark(.contains("cache key query hit")) + fileprivate func checkKeyQueryCacheHit(_ task: Task, sourceLocation: SourceLocation = #_sourceLocation) { + let found = (getDiagnosticMessageForTask(.contains("cache found for key"), kind: .note, task: task) != nil) + guard found else { + Issue.record("Unable to find cache hit diagnostic for task \(task)", sourceLocation: sourceLocation) + return + } + check(contains: .taskHadEvent(task, event: .hadOutput(contents: "Cache hit\n")), sourceLocation: sourceLocation) } } diff --git a/Tests/SWBBuildSystemTests/SwiftDriverTests.swift b/Tests/SWBBuildSystemTests/SwiftDriverTests.swift index f6e8a409..ed5d3f05 100644 --- a/Tests/SWBBuildSystemTests/SwiftDriverTests.swift +++ b/Tests/SWBBuildSystemTests/SwiftDriverTests.swift @@ -19,6 +19,7 @@ import SWBTestSupport import SWBLLBuild import SWBCore +import SWBTaskExecution @Suite(.requireLLBuild(apiVersion: 12), .requireXcode16()) fileprivate struct SwiftDriverTests: CoreBasedTests { @@ -3162,8 +3163,6 @@ fileprivate struct SwiftDriverTests: CoreBasedTests { "ARCHS": "arm64e", "SWIFT_WHOLE_MODULE_OPTIMIZATION": "YES", "SWIFT_ENABLE_LIBRARY_EVOLUTION": "YES", - "ENABLE_BITCODE": "YES", - "BITCODE_GENERATION_MODE": "bitcode", "SDKROOT": "iphoneos", "SWIFT_USE_INTEGRATED_DRIVER": "YES", ]) @@ -3229,15 +3228,6 @@ fileprivate struct SwiftDriverTests: CoreBasedTests { // Check that subtasks progress events are reported as expected. try await tester.checkBuild(runDestination: .anyiOSDevice, buildRequest: buildRequest, persistent: true) { results in - if UserDefaults.enableBitcodeSupport { - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'TargetA' from project 'aProject')")) - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'TargetB' from project 'aProject')")) - } - else { - results.checkWarning(.equal("Ignoring ENABLE_BITCODE because building with bitcode is no longer supported. (in target 'TargetA' from project 'aProject')")) - results.checkWarning(.equal("Ignoring ENABLE_BITCODE because building with bitcode is no longer supported. (in target 'TargetB' from project 'aProject')")) - } - results.checkNoErrors() let compilationRequirementA = try #require(results.getTask(.matchTargetName("TargetA"), .matchRuleType("SwiftDriver Compilation Requirements"))) @@ -3273,16 +3263,10 @@ fileprivate struct SwiftDriverTests: CoreBasedTests { #expect(compilationTask.execDescription == "Compile \(targetName) (arm64e)") results.checkTaskRequested(compilationTask, .matchTargetName(targetName), .matchRuleType("SwiftCompile"), .matchRuleItem(SRCROOT.join("Sources/file\(targetNameSuffix)1.swift").str), .matchRuleItem(SRCROOT.join("Sources/file\(targetNameSuffix)2.swift").str)) - - if UserDefaults.enableBitcodeSupport { - results.checkTaskRequested(compilationTask, .matchTargetName(targetName), .matchRuleType("SwiftBackend"), .matchRuleItemPattern(.suffix("file\(targetNameSuffix)1.bc"))) - results.checkTaskRequested(compilationTask, .matchTargetName(targetName), .matchRuleType("SwiftBackend"), .matchRuleItemPattern(.suffix("file\(targetNameSuffix)2.bc"))) - } } results.checkTask(.matchTargetName(targetName), .matchRulePattern(["SwiftCompile", "normal", "arm64e", "Compiling file\(targetNameSuffix)1.swift, file\(targetNameSuffix)2.swift", .equal(SRCROOT.join("Sources/file\(targetNameSuffix)1.swift").str), .equal(SRCROOT.join("Sources/file\(targetNameSuffix)2.swift").str)])) { compileFileTask in - let fileSuffix = UserDefaults.enableBitcodeSupport ? "bc" : "o" - compileFileTask.checkCommandLineMatches([.suffix("swift-frontend"), .anySequence, .equal(SRCROOT.join("Sources/file\(targetNameSuffix)1.swift").str), .anySequence, "-o", .suffix("file\(targetNameSuffix)1.\(fileSuffix)"), "-o", .suffix("file\(targetNameSuffix)2.\(fileSuffix)")]) + compileFileTask.checkCommandLineMatches([.suffix("swift-frontend"), .anySequence, .equal(SRCROOT.join("Sources/file\(targetNameSuffix)1.swift").str), .anySequence, "-o", .suffix("file\(targetNameSuffix)1.o"), "-o", .suffix("file\(targetNameSuffix)2.o")]) } } } @@ -4613,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'") - results.checkWarning("'Framework3' is missing a dependency on 'Framework2' because dependency scan of Swift module 'Framework3' discovered a dependency on 'Framework2'") + 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')") case .yesError: - 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'") + 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')") default: break } @@ -4895,7 +4879,7 @@ fileprivate struct SwiftDriverTests: CoreBasedTests { do { let params = BuildParameters(configuration: "Debug") try await tester.checkBuild(runDestination: .macOS, buildRequest: parameterizedBuildRequest(params)) { results in - results.checkWarnings([.contains("Enabling the Swift language feature 'DeprecateApplicationMain' is recommended; set 'SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES'")], failIfNotFound: true) + results.checkWarnings([.contains("Enabling the Swift language feature 'DeprecateApplicationMain' will become a requirement in the future; set 'SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES'")], failIfNotFound: true) results.checkNotes([.contains("Learn more about 'DeprecateApplicationMain' by visiting https://www.swift.org/swift-evolution/")]) results.checkNoErrors() } @@ -5057,4 +5041,106 @@ fileprivate struct SwiftDriverTests: CoreBasedTests { } } } + + @Test(.requireSDKs(.macOS)) + func incrementalExplicitModulesLinkerSwiftmoduleRegistration() async throws { + try await withTemporaryDirectory { tmpDirPath async throws -> Void in + let testWorkspace = try await TestWorkspace( + "Test", + sourceRoot: tmpDirPath.join("Test"), + projects: [ + TestProject( + "aProject", + groupTree: TestGroup( + "Sources", + path: "Sources", + children: [ + TestFile("fileA1.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "PRODUCT_NAME": "$(TARGET_NAME)", + "SWIFT_VERSION": swiftVersion, + "BUILD_VARIANTS": "normal", + "SWIFT_USE_INTEGRATED_DRIVER": "YES", + "SWIFT_ENABLE_EXPLICIT_MODULES": "YES", + ]) + ], + targets: [ + TestStandardTarget( + "TargetA", + type: .framework, + buildPhases: [ + TestSourcesBuildPhase([ + "fileA1.swift", + ]), + ]), + ]) + ]) + + let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false) + tester.userInfo = tester.userInfo.withAdditionalEnvironment(environment: ["SWIFT_FORCE_MODULE_LOADING": "only-interface"]) + let parameters = BuildParameters(configuration: "Debug", overrides: [ + // Redirect the prebuilt cache so we always build modules from source + "SWIFT_OVERLOAD_PREBUILT_MODULE_CACHE_PATH": tmpDirPath.str + ]) + let buildRequest = BuildRequest(parameters: parameters, buildTargets: tester.workspace.projects[0].targets.map({ BuildRequest.BuildTargetInfo(parameters: parameters, target: $0) }), continueBuildingAfterErrors: false, useParallelTargets: true, useImplicitDependencies: false, useDryRun: false) + let SRCROOT = testWorkspace.sourceRoot.join("aProject") + + // Create the source files. + try await tester.fs.writeFileContents(SRCROOT.join("Sources/fileA1.swift")) { file in + file <<< + """ + public struct A { + public init() { } + } + """ + } + + var cleanResponseFileContents: ByteString? = nil + try await tester.checkBuild(runDestination: .macOS, buildRequest: buildRequest, persistent: true) { results in + var responseFile: Path? = nil + results.checkTask(.matchRuleType("SwiftDriver Compilation Requirements")) { driverTask in + responseFile = driverTask.outputPaths.filter { $0.str.hasSuffix("-linker-args.resp") }.only + } + try results.checkTask(.matchRuleType("Ld")) { linkTask in + linkTask.checkCommandLineContains("@\(try #require(responseFile).str)") + } + let responseFileContents = try tester.fs.read(try #require(responseFile)) + #expect(!responseFileContents.isEmpty) + cleanResponseFileContents = responseFileContents + } + + try await tester.fs.writeFileContents(SRCROOT.join("Sources/fileA1.swift")) { file in + file <<< + """ + public struct A { + public init() { } + } + + public func foo() { } + """ + } + + var incrementalResponseFileContents: ByteString? = nil + try await tester.checkBuild(runDestination: .macOS, buildRequest: buildRequest, persistent: true) { results in + var responseFile: Path? = nil + results.checkTask(.matchRuleType("SwiftDriver Compilation Requirements")) { driverTask in + responseFile = driverTask.outputPaths.filter { $0.str.hasSuffix("-linker-args.resp") }.only + } + try results.checkTask(.matchRuleType("Ld")) { linkTask in + linkTask.checkCommandLineContains("@\(try #require(responseFile).str)") + } + let responseFileContents = try tester.fs.read(try #require(responseFile)) + #expect(!responseFileContents.isEmpty) + incrementalResponseFileContents = responseFileContents + } + + let cleanContents = try #require(cleanResponseFileContents) + let incrementalContents = try #require(incrementalResponseFileContents) + #expect(cleanContents == incrementalContents) + } + } } diff --git a/Tests/SWBBuildSystemTests/UnitTestBuildOperationTests.swift b/Tests/SWBBuildSystemTests/UnitTestBuildOperationTests.swift index 107a8bbb..fba9edb1 100644 --- a/Tests/SWBBuildSystemTests/UnitTestBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/UnitTestBuildOperationTests.swift @@ -17,6 +17,7 @@ import SWBTestSupport import SWBCore import SWBProtocol import SWBUtil +import SWBTaskExecution @Suite @@ -1270,63 +1271,4 @@ fileprivate struct UnitTestBuildOperationTests: CoreBasedTests { } } } - - /// Validates that a project building for a platform which uses bitcode is able to build successfully when linking to XCTest. - /// Testing frameworks like XCTest are not built with bitcode because they aren't intended to be shipped, and so dependencies of these targets should have bitcode disabled. - /// This is especially important for packages, which cannot disable bitcode. - @Test(.requireSDKs(.iOS)) - func testingFrameworksWithBitcode() async throws { - try await withTemporaryDirectory { tmpDir in - let testWorkspace = TestWorkspace( - "Test", - sourceRoot: tmpDir.join("Test"), - projects: [ - TestProject( - "aProject", - groupTree: TestGroup( - "Framework", - children: [ - TestFile("Test.swift"), - TestFile("XCTest.framework") - ]), - buildConfigurations: [ - TestBuildConfiguration( - "Debug", - buildSettings: [:]), - ], - targets: [ - TestStandardTarget( - "Framework", - type: .framework, - buildConfigurations: [ - TestBuildConfiguration( - "Debug", - buildSettings: [ - "ENABLE_BITCODE": "YES", - "PRODUCT_NAME": "$(TARGET_NAME)", - "SDKROOT": "iphoneos", - "SWIFT_VERSION": "5.0", - ]), - ], - buildPhases: [ - TestSourcesBuildPhase([ - "Test.swift", - ]), - TestFrameworksBuildPhase([ - "XCTest.framework" - ]) - ] - ) - ]) - ]) - let tester = try await BuildOperationTester(getCore(), testWorkspace, simulated: false) - - try tester.fs.createDirectory(testWorkspace.sourceRoot.join("aProject"), recursive: true) - try tester.fs.write(testWorkspace.sourceRoot.join("aProject").join("Test.swift"), contents: "import XCTest") - - try await tester.checkBuild(runDestination: .iOS) { results in - results.checkNoDiagnostics() - } - } - } } diff --git a/Tests/SWBBuildSystemTests/WatchBuildOperationTests.swift b/Tests/SWBBuildSystemTests/WatchBuildOperationTests.swift index d133646a..be5d8045 100644 --- a/Tests/SWBBuildSystemTests/WatchBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/WatchBuildOperationTests.swift @@ -13,6 +13,7 @@ import SWBTestSupport import SWBUtil import Testing +import SWBCore @Suite fileprivate struct WatchBuildOperationTests: CoreBasedTests { @@ -132,9 +133,9 @@ fileprivate struct WatchBuildOperationTests: CoreBasedTests { // Create files in the filesystem so they're known to exist. let fs = tester.fs - try fs.createDirectory(core.developerPath.join("usr/bin"), recursive: true) - try await fs.writeFileContents(core.developerPath.join("usr/bin/actool")) { $0 <<< "binary" } - try await fs.writeFileContents(core.developerPath.join("usr/bin/ibtool")) { $0 <<< "binary" } + try fs.createDirectory(core.developerPath.path.join("usr/bin"), recursive: true) + try await fs.writeFileContents(core.developerPath.path.join("usr/bin/actool")) { $0 <<< "binary" } + try await fs.writeFileContents(core.developerPath.path.join("usr/bin/ibtool")) { $0 <<< "binary" } try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } try fs.createDirectory(Path("/Users/whoever/Library/MobileDevice/Provisioning Profiles"), recursive: true) diff --git a/Tests/SWBBuildSystemTests/XCFrameworkBuildOperationTests.swift b/Tests/SWBBuildSystemTests/XCFrameworkBuildOperationTests.swift index 74701f0b..2d0bcaac 100644 --- a/Tests/SWBBuildSystemTests/XCFrameworkBuildOperationTests.swift +++ b/Tests/SWBBuildSystemTests/XCFrameworkBuildOperationTests.swift @@ -18,6 +18,7 @@ import SWBCore import SWBTestSupport import SWBTaskExecution import SWBUtil +import SWBProtocol @Suite fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { @@ -473,7 +474,7 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { try await fs.writeFileContents(Path(SRCROOT).join("file.c"), body: { $0 <<< "int main() { return 0; }" }) let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), ]) let supportXCFrameworkPath = Path(SRCROOT).join("libsample.xcframework") @@ -481,7 +482,7 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { try await XCFrameworkTestSupport.writeXCFramework(supportXCFramework, fs: fs, path: supportXCFrameworkPath, infoLookup: infoLookup) let otherXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libother.a"), binaryPath: Path("libother.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libother.a"), binaryPath: Path("libother.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libother.a"), binaryPath: Path("libother.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), ]) let otherXCFrameworkPath = Path(SRCROOT).join("libother.xcframework") @@ -555,10 +556,6 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { { return $0.headersPath }, { return "Missing path (\($0.join("Headers").str)) from XCFramework 'libsample.xcframework' as defined by 'HeadersPath' in its `Info.plist` file (in target \'App\' from project \'aProject\')" } ), - ( - { return $0.bitcodeSymbolMapsPath }, - { return "Missing path (\($0.join("symbolmaps").str)) from XCFramework 'libsample.xcframework' as defined by 'BitcodeSymbolMapsPath' in its `Info.plist` file (in target \'App\' from project \'aProject\')" } - ), ] for scenario in scenarios { @@ -574,8 +571,8 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { let supportXCFrameworkPath = Path(SRCROOT).join("libsample.xcframework") let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), - XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), + XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), ]) try fs.createDirectory(supportXCFrameworkPath, recursive: true) @@ -654,8 +651,8 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { let supportXCFrameworkPath = Path(SRCROOT).join("libsample.xcframework") let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), - XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), + XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), ]) try fs.createDirectory(supportXCFrameworkPath, recursive: true) @@ -718,8 +715,8 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { let supportXCFrameworkPath = Path(SRCROOT).join("libsample.xcframework") let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), - XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), + XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), ]) try fs.createDirectory(supportXCFrameworkPath, recursive: true) @@ -887,8 +884,8 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { let supportXCFrameworkPath = Path(SRCROOT).join("sample.xcframework") let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos\(infoLookup.loadSDK(.iOS).defaultDeploymentTarget)", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("sample.framework"), binaryPath: Path("sample.framework/sample"), headersPath: nil, debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), - XCFramework.Library(libraryIdentifier: "arm64-apple-watchos\(infoLookup.loadSDK(.watchOS).defaultDeploymentTarget)", supportedPlatform: "watchos", supportedArchitectures: ["arm64", "arm64_32"], platformVariant: nil, libraryPath: Path("sample.framework"), binaryPath: Path("sample.framework/sample"), headersPath: nil, debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos\(infoLookup.loadSDK(.iOS).defaultDeploymentTarget)", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("sample.framework"), binaryPath: Path("sample.framework/sample"), headersPath: nil, debugSymbolsPath: Path("dSYMs")), + XCFramework.Library(libraryIdentifier: "arm64-apple-watchos\(infoLookup.loadSDK(.watchOS).defaultDeploymentTarget)", supportedPlatform: "watchos", supportedArchitectures: ["arm64", "arm64_32"], platformVariant: nil, libraryPath: Path("sample.framework"), binaryPath: Path("sample.framework/sample"), headersPath: nil, debugSymbolsPath: Path("dSYMs")), ]) try fs.createDirectory(supportXCFrameworkPath, recursive: true) @@ -896,8 +893,8 @@ fileprivate struct XCFrameworkBuildOperationTests: CoreBasedTests { let staticSupportXCFrameworkPath = Path(SRCROOT).join("libsample.xcframework") let staticSupportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos\(infoLookup.loadSDK(.iOS).defaultDeploymentTarget)", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: nil, debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), - XCFramework.Library(libraryIdentifier: "arm64-apple-watchos\(infoLookup.loadSDK(.watchOS).defaultDeploymentTarget)", supportedPlatform: "watchos", supportedArchitectures: ["arm64", "arm64_32"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: nil, debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos\(infoLookup.loadSDK(.iOS).defaultDeploymentTarget)", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: nil, debugSymbolsPath: Path("dSYMs")), + XCFramework.Library(libraryIdentifier: "arm64-apple-watchos\(infoLookup.loadSDK(.watchOS).defaultDeploymentTarget)", supportedPlatform: "watchos", supportedArchitectures: ["arm64", "arm64_32"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: nil, debugSymbolsPath: Path("dSYMs")), ]) try fs.createDirectory(staticSupportXCFrameworkPath, recursive: true) diff --git a/Tests/SWBCorePerfTests/SerializationPerfTests.swift b/Tests/SWBCorePerfTests/SerializationPerfTests.swift index d440ad09..53952652 100644 --- a/Tests/SWBCorePerfTests/SerializationPerfTests.swift +++ b/Tests/SWBCorePerfTests/SerializationPerfTests.swift @@ -15,6 +15,7 @@ import SWBUtil import SWBCore import SWBMacro import SWBTestSupport +import Synchronization @Suite(.performance) fileprivate struct SerializationPerfTests: CoreBasedTests, PerfTests { diff --git a/Tests/SWBCorePerfTests/SettingsPerfTests.swift b/Tests/SWBCorePerfTests/SettingsPerfTests.swift index 1cab098d..255abf63 100644 --- a/Tests/SWBCorePerfTests/SettingsPerfTests.swift +++ b/Tests/SWBCorePerfTests/SettingsPerfTests.swift @@ -15,6 +15,7 @@ import SWBUtil import SWBCore import SWBTestSupport +import SWBProtocol @Suite(.performance) fileprivate struct SettingsPerfTests: CoreBasedTests, PerfTests { diff --git a/Tests/SWBCoreTests/BuildParametersTests.swift b/Tests/SWBCoreTests/BuildParametersTests.swift index 71a752ac..139d8a67 100644 --- a/Tests/SWBCoreTests/BuildParametersTests.swift +++ b/Tests/SWBCoreTests/BuildParametersTests.swift @@ -15,6 +15,7 @@ import Testing import SWBUtil import SWBCore import SWBProtocol +import SWBTestSupport @Suite fileprivate struct BuildParametersTests { @Test diff --git a/Tests/SWBCoreTests/CommandLineSpecTests.swift b/Tests/SWBCoreTests/CommandLineSpecTests.swift index a71986f3..69419765 100644 --- a/Tests/SWBCoreTests/CommandLineSpecTests.swift +++ b/Tests/SWBCoreTests/CommandLineSpecTests.swift @@ -1848,14 +1848,14 @@ import SWBMacro let core = try await getCore() let clangSpec = try core.specRegistry.getSpec("com.apple.compilers.llvm.clang.1_0") as CommandLineToolSpec let mockFileType = try core.specRegistry.getSpec("sourcecode.cpp.cpp") as FileTypeSpec - let enableCompileCache = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("CLANG_ENABLE_COMPILE_CACHE") as? EnumMacroDeclaration) + let enableCompileCache = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("CLANG_ENABLE_COMPILE_CACHE") as? BooleanMacroDeclaration) let enablePrefixMap = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("CLANG_ENABLE_PREFIX_MAPPING") as? BooleanMacroDeclaration) let prefixMaps = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("CLANG_OTHER_PREFIX_MAPPINGS") as? StringListMacroDeclaration) let devDir = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("DEVELOPER_DIR") as? PathMacroDeclaration) func test(caching: Bool, prefixMapping: Bool, extraMaps: [String], completion: ([String]) throws -> Void) async throws { var table = MacroValueAssignmentTable(namespace: core.specRegistry.internalMacroNamespace) - table.push(enableCompileCache, literal: caching ? .enabled : .disabled) + table.push(enableCompileCache, literal: caching) table.push(enablePrefixMap, literal: prefixMapping) table.push(prefixMaps, literal: extraMaps) table.push(devDir, literal: "/Xcode.app/Contents/Developer") @@ -1902,7 +1902,7 @@ import SWBMacro let swiftSpec = try core.specRegistry.getSpec("com.apple.xcode.tools.swift.compiler") as CompilerSpec let mockFileType = try core.specRegistry.getSpec("sourcecode.swift") as FileTypeSpec - let enableCompileCache = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("SWIFT_ENABLE_COMPILE_CACHE") as? EnumMacroDeclaration) + let enableCompileCache = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("SWIFT_ENABLE_COMPILE_CACHE") as? BooleanMacroDeclaration) let enablePrefixMap = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("SWIFT_ENABLE_PREFIX_MAPPING") as? BooleanMacroDeclaration) let prefixMaps = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("SWIFT_OTHER_PREFIX_MAPPINGS") as? StringListMacroDeclaration) let devDir = try #require(core.specRegistry.internalMacroNamespace.lookupMacroDeclaration("DEVELOPER_DIR") as? PathMacroDeclaration) @@ -1922,7 +1922,7 @@ import SWBMacro // remove in rdar://53000820 table.push(BuiltinMacros.USE_SWIFT_RESPONSE_FILE, literal: true) - table.push(enableCompileCache, literal: caching ? .enabled : .disabled) + table.push(enableCompileCache, literal: caching) table.push(enablePrefixMap, literal: prefixMapping) table.push(prefixMaps, literal: extraMaps) table.push(devDir, literal: "/Xcode.app/Contents/Developer") diff --git a/Tests/SWBCoreTests/CoreTests.swift b/Tests/SWBCoreTests/CoreTests.swift index 9483d02d..b19b7a33 100644 --- a/Tests/SWBCoreTests/CoreTests.swift +++ b/Tests/SWBCoreTests/CoreTests.swift @@ -18,6 +18,7 @@ import SWBTestSupport import Foundation @_spi(Testing) import SWBCore +import SWBServiceCore @Suite fileprivate struct CoreTests: CoreBasedTests { @Test @@ -25,11 +26,11 @@ import Foundation let core = try await getCore() switch try ProcessInfo.processInfo.hostOperatingSystem() { case .macOS: - XCTAssertMatch(core.developerPath.str, .suffix(".app/Contents/Developer")) + XCTAssertMatch(core.developerPath.path.str, .suffix(".app/Contents/Developer")) case .windows: - XCTAssertMatch(core.developerPath.str, .suffix("\\AppData\\Local\\Programs\\Swift")) + XCTAssertMatch(core.developerPath.path.str, .suffix("\\AppData\\Local\\Programs\\Swift")) default: - #expect(core.developerPath.str == "/") + #expect(core.developerPath.path.str == "/") } } @@ -333,7 +334,7 @@ import Foundation let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.register(BuiltinSpecsExtension(), type: SpecificationsExtensionPoint.self) - let core = await Core.getInitializedCore(delegate, pluginManager: pluginManager, developerPath: tmpDirPath, buildServiceModTime: Date(), connectionMode: .inProcess) + let core = await Core.getInitializedCore(delegate, pluginManager: pluginManager, developerPath: .fallback(tmpDirPath), buildServiceModTime: Date(), connectionMode: .inProcess) #expect(core == nil) let results = CoreDelegateResults(delegate.diagnostics) @@ -378,9 +379,15 @@ import Foundation func toolchainPathsCount() async throws -> Int { let delegate = Delegate() let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + await pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.registerExtensionPoint(ToolchainRegistryExtensionPoint()) await pluginManager.register(BuiltinSpecsExtension(), type: SpecificationsExtensionPoint.self) + struct MockDeveloperDirectoryExtensionPoint: DeveloperDirectoryExtension { + func fallbackDeveloperDirectory(hostOperatingSystem: OperatingSystem) async throws -> Path? { + .root + } + } struct MockToolchainExtension: ToolchainRegistryExtension { func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] { guard context.toolchainRegistry.lookup(ToolchainRegistry.defaultToolchainIdentifier) == nil else { @@ -389,6 +396,7 @@ import Foundation return [Toolchain(identifier: ToolchainRegistry.defaultToolchainIdentifier, displayName: "Mock", version: Version(), aliases: ["default"], path: .root, frameworkPaths: [], libraryPaths: [], defaultSettings: [:], overrideSettings: [:], defaultSettingsWhenPrimary: [:], executableSearchPaths: [], testingLibraryPlatformNames: [], fs: context.fs)] } } + await pluginManager.register(MockDeveloperDirectoryExtensionPoint(), type: DeveloperDirectoryExtensionPoint.self) await pluginManager.register(MockToolchainExtension(), type: ToolchainRegistryExtensionPoint.self) let core = await Core.getInitializedCore(delegate, pluginManager: pluginManager, inferiorProductsPath: Path.root.join("invalid"), environment: [:], buildServiceModTime: Date(), connectionMode: .inProcess) for diagnostic in delegate.diagnostics { @@ -416,9 +424,15 @@ import Foundation func testExternalToolchainPath(environmentOverrides: [String:String], expecting expectedPathStrings: [String], _ originalToolchainCount: Int) async throws { let delegate = Delegate() let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + await pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.registerExtensionPoint(ToolchainRegistryExtensionPoint()) await pluginManager.register(BuiltinSpecsExtension(), type: SpecificationsExtensionPoint.self) + struct MockDeveloperDirectoryExtensionPoint: DeveloperDirectoryExtension { + func fallbackDeveloperDirectory(hostOperatingSystem: OperatingSystem) async throws -> Path? { + .root + } + } struct MockToolchainExtension: ToolchainRegistryExtension { func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] { guard context.toolchainRegistry.lookup(ToolchainRegistry.defaultToolchainIdentifier) == nil else { @@ -427,6 +441,7 @@ import Foundation return [Toolchain(identifier: ToolchainRegistry.defaultToolchainIdentifier, displayName: "Mock", version: Version(), aliases: ["default"], path: .root, frameworkPaths: [], libraryPaths: [], defaultSettings: [:], overrideSettings: [:], defaultSettingsWhenPrimary: [:], executableSearchPaths: [], testingLibraryPlatformNames: [], fs: context.fs)] } } + await pluginManager.register(MockDeveloperDirectoryExtensionPoint(), type: DeveloperDirectoryExtensionPoint.self) await pluginManager.register(MockToolchainExtension(), type: ToolchainRegistryExtensionPoint.self) let core = await Core.getInitializedCore(delegate, pluginManager: pluginManager, inferiorProductsPath: Path.root.join("invalid"), environment: environmentOverrides, buildServiceModTime: Date(), connectionMode: .inProcess) for diagnostic in delegate.diagnostics { diff --git a/Tests/SWBCoreTests/FileTextEncodingTests.swift b/Tests/SWBCoreTests/FileTextEncodingTests.swift index a5efbe99..190dca66 100644 --- a/Tests/SWBCoreTests/FileTextEncodingTests.swift +++ b/Tests/SWBCoreTests/FileTextEncodingTests.swift @@ -13,6 +13,9 @@ import Foundation import Testing import SWBCore +import SWBProtocol +import SWBUtil +import SWBTestSupport @Suite fileprivate struct FileTextEncodingTests { @Test @@ -23,7 +26,8 @@ import SWBCore #expect(FileTextEncoding("utf8") != FileTextEncoding.utf8) } - @Test(.skipHostOS(.windows, "feature not available on Windows due to missing CF APIs")) + @Test(.skipHostOS(.windows, "feature not available on Windows due to missing CF APIs"), + .skipHostOS(.linux, "feature not available on Linux due to missing CF APIs")) func encoding() throws { #expect(FileTextEncoding.utf8.stringEncoding == String.Encoding.utf8) #expect(FileTextEncoding.utf16.stringEncoding == String.Encoding.utf16) diff --git a/Tests/SWBCoreTests/IncrementalPIFLoadingTests.swift b/Tests/SWBCoreTests/IncrementalPIFLoadingTests.swift index b0e817bb..03a5a101 100644 --- a/Tests/SWBCoreTests/IncrementalPIFLoadingTests.swift +++ b/Tests/SWBCoreTests/IncrementalPIFLoadingTests.swift @@ -16,6 +16,7 @@ import SWBCore import SWBUtil import SWBTestSupport @_spi(Testing) import SWBCore +import SWBProtocol /// Test of the incremental PIF loading mechanisms. @Suite(.serialized) fileprivate struct IncrementalPIFLoadingTests { @@ -340,12 +341,12 @@ import SWBTestSupport #expect(IncrementalPIFLoader.objectsTransferred.value == 3) // Validate that the file references are consistent. - var knownReferences = Set() - func visit(_ ref: Reference) { + var knownReferences = Set() + func visit(_ ref: SWBCore.Reference) { switch ref { - case let asGroup as FileGroup: + case let asGroup as SWBCore.FileGroup: asGroup.children.forEach(visit) - case let asFile as FileReference: + case let asFile as SWBCore.FileReference: knownReferences.insert(asFile) default: fatalError("unexpected reference: \(ref)") @@ -354,12 +355,12 @@ import SWBTestSupport for project in workspace.projects { knownReferences.removeAll() visit(project.groupTree) - for case let target as BuildPhaseTarget in project.targets { - for case let phase as BuildPhaseWithBuildFiles in target.buildPhases { + for case let target as SWBCore.BuildPhaseTarget in project.targets { + for case let phase as SWBCore.BuildPhaseWithBuildFiles in target.buildPhases { for buildFile in phase.buildFiles { switch buildFile.buildableItem { case .reference(let guid): - let ref = try #require(workspace.lookupReference(for: guid) as? FileReference) + let ref = try #require(workspace.lookupReference(for: guid) as? SWBCore.FileReference) #expect(knownReferences.contains(ref), "unexpected target reference: \(ref)") case .targetProduct(_): continue diff --git a/Tests/SWBCoreTests/ModuleVerifierFilenameMapTests.swift b/Tests/SWBCoreTests/ModuleVerifierFilenameMapTests.swift index 81006913..604b8311 100644 --- a/Tests/SWBCoreTests/ModuleVerifierFilenameMapTests.swift +++ b/Tests/SWBCoreTests/ModuleVerifierFilenameMapTests.swift @@ -14,6 +14,7 @@ import Foundation import SWBCore import SWBUtil import Testing +import SWBTestSupport @Suite fileprivate struct ModuleVerifierFilenameMapTests { @Test diff --git a/Tests/SWBCoreTests/PIFLoadingTests.swift b/Tests/SWBCoreTests/PIFLoadingTests.swift index 1f518fbe..f79bf378 100644 --- a/Tests/SWBCoreTests/PIFLoadingTests.swift +++ b/Tests/SWBCoreTests/PIFLoadingTests.swift @@ -15,6 +15,8 @@ import SWBTestSupport import SWBUtil @_spi(Testing) import SWBCore +import SWBMacro +import SWBProtocol // MARK: - Test cases for ProjectModelItem class static methods @@ -253,7 +255,7 @@ private final class ProjectModelItemClass: ProjectModelItem { } // Test the required version. - let requiredValue: [Reference] = try Reference.parseValueForKeyAsArrayOfProjectModelItems("arrayOfItemsKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try Reference(fromDictionary: $0, withPIFLoader: pifLoader) }) + let requiredValue: [SWBCore.Reference] = try Reference.parseValueForKeyAsArrayOfProjectModelItems("arrayOfItemsKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try Reference(fromDictionary: $0, withPIFLoader: pifLoader) }) #expect(requiredValue.count == 3) #expect(requiredValue[0].guid == "xib-fileReference-guid") #expect(requiredValue[1].guid == "fr-strings-fileReference-guid") @@ -293,13 +295,13 @@ private final class ProjectModelItemClass: ProjectModelItem { } // Test the optional version. - let presentValue: [Reference]? = try ProjectModelItemClass.parseOptionalValueForKeyAsArrayOfProjectModelItems("arrayOfItemsKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try Reference(fromDictionary: $0, withPIFLoader: pifLoader) }) + let presentValue: [SWBCore.Reference]? = try ProjectModelItemClass.parseOptionalValueForKeyAsArrayOfProjectModelItems("arrayOfItemsKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try Reference(fromDictionary: $0, withPIFLoader: pifLoader) }) #expect(presentValue?.count == 3) #expect(presentValue?[0].guid == "xib-fileReference-guid") #expect(presentValue?[1].guid == "fr-strings-fileReference-guid") #expect(presentValue?[2].guid == "some-fileGroup-guid") - let absentValue: [Reference]? = try ProjectModelItemClass.parseOptionalValueForKeyAsArrayOfProjectModelItems("missingKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try Reference(fromDictionary: $0, withPIFLoader: pifLoader) }) + let absentValue: [SWBCore.Reference]? = try ProjectModelItemClass.parseOptionalValueForKeyAsArrayOfProjectModelItems("missingKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try Reference(fromDictionary: $0, withPIFLoader: pifLoader) }) #expect(absentValue == nil) // Test failure cases. @@ -450,10 +452,10 @@ private final class ProjectModelItemClass: ProjectModelItem { } // Test the optional version. - let presentValue: FileGroup? = try FileGroup.parseOptionalValueForKeyAsProjectModelItem("fileGroupKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try FileGroup(fromDictionary: $0, withPIFLoader: pifLoader, isRoot: false) }) + let presentValue: SWBCore.FileGroup? = try FileGroup.parseOptionalValueForKeyAsProjectModelItem("fileGroupKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try FileGroup(fromDictionary: $0, withPIFLoader: pifLoader, isRoot: false) }) #expect(presentValue != nil) - let absentValue: FileGroup? = try FileGroup.parseOptionalValueForKeyAsProjectModelItem("missingKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try FileGroup(fromDictionary: $0, withPIFLoader: pifLoader, isRoot: false) }) + let absentValue: SWBCore.FileGroup? = try FileGroup.parseOptionalValueForKeyAsProjectModelItem("missingKey", pifDict: pifDict, pifLoader: pifLoader, construct: { try FileGroup(fromDictionary: $0, withPIFLoader: pifLoader, isRoot: false) }) #expect(absentValue == nil) // Test failure cases. @@ -630,7 +632,7 @@ private final class ProjectModelItemClass: ProjectModelItem { Issue.record("property list is not a dictionary") return } - let fileRef = try #require(GroupTreeReference.parsePIFDictAsReference(fileRefPIF, pifLoader: pifLoader, isRoot: true) as? FileReference) + let fileRef = try #require(GroupTreeReference.parsePIFDictAsReference(fileRefPIF, pifLoader: pifLoader, isRoot: true) as? SWBCore.FileReference) // Examine the file reference. #expect(fileRef.guid == "some-fileReference-guid") @@ -673,7 +675,7 @@ private final class ProjectModelItemClass: ProjectModelItem { Issue.record("property list is not a dictionary") return } - let fileGroup = try #require(GroupTreeReference.parsePIFDictAsReference(fileGroupPIF, pifLoader: pifLoader, isRoot: true) as? FileGroup) + let fileGroup = try #require(GroupTreeReference.parsePIFDictAsReference(fileGroupPIF, pifLoader: pifLoader, isRoot: true) as? SWBCore.FileGroup) // Examine the file group. #expect(fileGroup.guid == "some-fileGroup-guid") @@ -683,14 +685,14 @@ private final class ProjectModelItemClass: ProjectModelItem { #expect(fileGroup.children.count == 2) // Examine its children - if let fileRef = try? #require(fileGroup.children.first as? FileReference) { + if let fileRef = try? #require(fileGroup.children.first as? SWBCore.FileReference) { #expect(fileRef.guid == "first-fileReference-guid") #expect(fileRef.sourceTree == SourceTree.groupRelative) #expect(fileRef.path.stringRep == "ClassOne.m") #expect(fileRef.fileTypeIdentifier == "sourcecode.c.objc") #expect(fileRef.regionVariantName == nil) } - if let fileRef = try? #require(fileGroup.children[1] as? FileReference) { + if let fileRef = try? #require(fileGroup.children[1] as? SWBCore.FileReference) { #expect(fileRef.guid == "second-fileReference-guid") #expect(fileRef.sourceTree == SourceTree.groupRelative) #expect(fileRef.path.stringRep == "ClassOne.h") @@ -731,7 +733,7 @@ private final class ProjectModelItemClass: ProjectModelItem { Issue.record("property list is not a dictionary") return } - let versionGroup = try #require(try GroupTreeReference.parsePIFDictAsReference(versionGroupPIF, pifLoader: pifLoader, isRoot: true) as? VersionGroup) + let versionGroup = try #require(try GroupTreeReference.parsePIFDictAsReference(versionGroupPIF, pifLoader: pifLoader, isRoot: true) as? SWBCore.VersionGroup) // Examine the file group. #expect(versionGroup.guid == "some-versionGroup-guid") @@ -740,14 +742,14 @@ private final class ProjectModelItemClass: ProjectModelItem { #expect(versionGroup.children.count == 2) // Examine its children - if let fileRef = try? #require(versionGroup.children[0] as? FileReference) { + if let fileRef = try? #require(versionGroup.children[0] as? SWBCore.FileReference) { #expect(fileRef.guid == "first-versionedFile-guid") #expect(fileRef.sourceTree == SourceTree.groupRelative) #expect(fileRef.path.stringRep == "CoreData-1.xcdatamodel") #expect(fileRef.fileTypeIdentifier == "wrapper.xcdatamodel") #expect(fileRef.regionVariantName == nil) } - if let fileRef = try? #require(versionGroup.children[1] as? FileReference) { + if let fileRef = try? #require(versionGroup.children[1] as? SWBCore.FileReference) { #expect(fileRef.guid == "second-versionedFile-guid") #expect(fileRef.sourceTree == SourceTree.groupRelative) #expect(fileRef.path.stringRep == "CoreData-2.xcdatamodel") @@ -769,7 +771,7 @@ private final class ProjectModelItemClass: ProjectModelItem { // Convert the test data into a property list, then read the file group from it. let versionGroupPlist = PropertyListItem(testVersionGroupData) let versionGroupPIF = try #require(versionGroupPlist.dictValue, "property list is not a dictionary") - let versionGroup = try #require(GroupTreeReference.parsePIFDictAsReference(versionGroupPIF, pifLoader: pifLoader, isRoot: true) as? VersionGroup) + let versionGroup = try #require(GroupTreeReference.parsePIFDictAsReference(versionGroupPIF, pifLoader: pifLoader, isRoot: true) as? SWBCore.VersionGroup) // Examine the file group. #expect(versionGroup.guid == "some-versionGroup-guid") @@ -814,28 +816,28 @@ private final class ProjectModelItemClass: ProjectModelItem { ] // Convert the test data into a property list, then read the variant group from it. - let variantGroup = try #require(GroupTreeReference.parsePIFDictAsReference( variantGroupPIF, pifLoader: pifLoader, isRoot: true) as? VariantGroup) + let variantGroup = try #require(GroupTreeReference.parsePIFDictAsReference( variantGroupPIF, pifLoader: pifLoader, isRoot: true) as? SWBCore.VariantGroup) // Examine the variant group. #expect(variantGroup.guid == "some-variantGroup-guid") #expect(variantGroup.name == "Thingy.xib") // Examine its children, the xib and its localized strings files - if let fileRef = try? #require(variantGroup.children[0] as? FileReference) { + if let fileRef = try? #require(variantGroup.children[0] as? SWBCore.FileReference) { #expect(fileRef.guid == "xib-fileReference-guid") #expect(fileRef.sourceTree == SourceTree.groupRelative) #expect(fileRef.path.stringRep == "Thingy.xib") #expect(fileRef.fileTypeIdentifier == "file.xib") #expect(fileRef.regionVariantName == nil) } - if let fileRef = try? #require(variantGroup.children[1] as? FileReference) { + if let fileRef = try? #require(variantGroup.children[1] as? SWBCore.FileReference) { #expect(fileRef.guid == "fr-strings-fileReference-guid") #expect(fileRef.sourceTree == SourceTree.groupRelative) #expect(fileRef.path.stringRep == "Thingy.strings") #expect(fileRef.fileTypeIdentifier == "text.plist.strings") #expect(fileRef.regionVariantName == "fr") } - if let fileRef = try? #require(variantGroup.children[2] as? FileReference) { + if let fileRef = try? #require(variantGroup.children[2] as? SWBCore.FileReference) { #expect(fileRef.guid == "de-strings-fileReference-guid") #expect(fileRef.sourceTree == SourceTree.groupRelative) #expect(fileRef.path.stringRep == "Thingy.strings") @@ -941,7 +943,7 @@ private final class ProjectModelItemClass: ProjectModelItem { ] // Convert the test data into a property list, then read the build phase from it. - if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? SourcesBuildPhase) { + if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? SWBCore.SourcesBuildPhase) { // Examine the build phase. #expect(buildPhase.buildFiles.count == 1) } @@ -962,7 +964,7 @@ private final class ProjectModelItemClass: ProjectModelItem { ] // Convert the test data into a property list, then read the build phase from it. - if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? HeadersBuildPhase) { + if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? SWBCore.HeadersBuildPhase) { // Examine the build phase. #expect(buildPhase.buildFiles.count == 1) } @@ -983,7 +985,7 @@ private final class ProjectModelItemClass: ProjectModelItem { ] // Convert the test data into a property list, then read the build phase from it. - if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? ResourcesBuildPhase) { + if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? SWBCore.ResourcesBuildPhase) { // Examine the build phase. #expect(buildPhase.buildFiles.count == 1) } @@ -1007,7 +1009,7 @@ private final class ProjectModelItemClass: ProjectModelItem { ] // Convert the test data into a property list, then read the build phase from it. - if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? CopyFilesBuildPhase) { + if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? SWBCore.CopyFilesBuildPhase) { // Examine the build phase. #expect(buildPhase.destinationSubfolder.stringRep == "Resources") #expect(buildPhase.destinationSubpath.stringRep == "Subpath") @@ -1036,7 +1038,7 @@ private final class ProjectModelItemClass: ProjectModelItem { ] // Convert the test data into a property list, then read the build phase from it. - if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? ShellScriptBuildPhase) { + if let buildPhase = try? #require(BuildPhase.parsePIFDictAsBuildPhase(buildPhasePIF, pifLoader: pifLoader) as? SWBCore.ShellScriptBuildPhase) { // Examine the build phase. #expect(buildPhase.guid == "some-shellScriptBuildPhase-guid") #expect(buildPhase.name == "A Shell Script Phase") @@ -1129,7 +1131,7 @@ private final class ProjectModelItemClass: ProjectModelItem { @Test func loadingStandardTarget() throws { // These file ref classes are only used for their GUIDs in this test, but the other data may be useful if the model changes in the future. - let classOneFileRef: FileReference = try { + let classOneFileRef: SWBCore.FileReference = try { let fileRefPIF: [String: PropertyListItem] = [ "guid": "framework-source-fileReference-guid", "type": "file", @@ -1141,7 +1143,7 @@ private final class ProjectModelItemClass: ProjectModelItem { // Convert the test data into a property list, then read the file reference from it. return try FileReference(fromDictionary: fileRefPIF, withPIFLoader: pifLoader, isRoot: true) }() - let classTwoFileRef: FileReference = try { + let classTwoFileRef: SWBCore.FileReference = try { let fileRefPIF: [String: PropertyListItem] = [ "guid": "app-source-fileReference-guid", "type": "file", @@ -1153,7 +1155,7 @@ private final class ProjectModelItemClass: ProjectModelItem { // Convert the test data into a property list, then read the file reference from it. return try FileReference(fromDictionary: fileRefPIF, withPIFLoader: pifLoader, isRoot: true) }() - let cocoaFwkFileRef: FileReference = try { + let cocoaFwkFileRef: SWBCore.FileReference = try { let fileRefPIF: [String: PropertyListItem] = [ "guid": "cocoa-framework-fileReference-guid", "type": "file", @@ -1167,7 +1169,7 @@ private final class ProjectModelItemClass: ProjectModelItem { }() // Load a framework target. - let frameworkTarget: StandardTarget = try { + let frameworkTarget: SWBCore.StandardTarget = try { let testBuildConfigurationData: [String: PropertyListItem] = [ "guid": "framework-buildConfiguration-guid", "name": "Debug", @@ -1244,7 +1246,7 @@ private final class ProjectModelItemClass: ProjectModelItem { } // Load an app target which depends on the framework target. - let appTarget: StandardTarget = try { + let appTarget: SWBCore.StandardTarget = try { let testBuildConfigurationData: [String: PropertyListItem] = [ "guid": "app-buildConfiguration-guid", "name": "Debug", @@ -1343,13 +1345,13 @@ private final class ProjectModelItemClass: ProjectModelItem { try #require(appTarget.buildPhases.count == 2) try #require(frameworkTarget.buildPhases.count == 2) - let appSourcesBuildPhase = try #require(appTarget.buildPhases[0] as? SourcesBuildPhase) - let appFrameworksBuildPhase = try #require(appTarget.buildPhases[1] as? FrameworksBuildPhase) - let frameworkSourcesBuildPhase = try #require(frameworkTarget.buildPhases[0] as? SourcesBuildPhase) - let frameworkFrameworksBuildPhase = try #require(frameworkTarget.buildPhases[1] as? FrameworksBuildPhase) + let appSourcesBuildPhase = try #require(appTarget.buildPhases[0] as? SWBCore.SourcesBuildPhase) + let appFrameworksBuildPhase = try #require(appTarget.buildPhases[1] as? SWBCore.FrameworksBuildPhase) + let frameworkSourcesBuildPhase = try #require(frameworkTarget.buildPhases[0] as? SWBCore.SourcesBuildPhase) + let frameworkFrameworksBuildPhase = try #require(frameworkTarget.buildPhases[1] as? SWBCore.FrameworksBuildPhase) // Because of the way reference resolution of a BuildFile.BuildableItem works, we don't have a context to resolve the build file's references to real references, so all we can do is check that the GUID is what we expect. - func checkBuildFileRef(of buildPhase: BuildPhaseWithBuildFiles, fileRef: FileReference) throws { + func checkBuildFileRef(of buildPhase: SWBCore.BuildPhaseWithBuildFiles, fileRef: SWBCore.FileReference) throws { guard let buildFileRef = try? #require(buildPhase.buildFiles.first) else { return } @@ -1374,7 +1376,7 @@ private final class ProjectModelItemClass: ProjectModelItem { @Test func loadingAggregateTarget() throws { - let target: AggregateTarget = try { + let target: SWBCore.AggregateTarget = try { let testBuildConfigurationData: [String: PropertyListItem] = [ "guid": "aggregate-target-guid", "name": "Debug", @@ -1405,7 +1407,7 @@ private final class ProjectModelItemClass: ProjectModelItem { @Test func loadingExternalTarget() throws { - let target: ExternalTarget = try { + let target: SWBCore.ExternalTarget = try { let testBuildConfigurationData: [String: PropertyListItem] = [ "guid": "external-buildConfiguration-guid", "name": "Debug", @@ -1564,33 +1566,33 @@ private final class ProjectModelItemClass: ProjectModelItem { XCTAssertMatch(rootGroup.guid, .prefix("G")) #expect(rootGroup.parent == nil) #expect(rootGroup.children.count == 5) - let sourceFileRef1 = try #require(rootGroup.children[0] as? FileReference) + let sourceFileRef1 = try #require(rootGroup.children[0] as? SWBCore.FileReference) XCTAssertMatch(sourceFileRef1.guid, .prefix("FR")) #expect(sourceFileRef1.parent === rootGroup) - let headerFileRef1 = try #require(rootGroup.children[1] as? FileReference) + let headerFileRef1 = try #require(rootGroup.children[1] as? SWBCore.FileReference) XCTAssertMatch(headerFileRef1.guid, .prefix("FR")) #expect(headerFileRef1.parent === rootGroup) - let sourceFileRef2 = try #require(rootGroup.children[2] as? FileReference) + let sourceFileRef2 = try #require(rootGroup.children[2] as? SWBCore.FileReference) XCTAssertMatch(sourceFileRef2.guid, .prefix("FR")) #expect(sourceFileRef2.parent === rootGroup) - let headerFileRef2 = try #require(rootGroup.children[3] as? FileReference) + let headerFileRef2 = try #require(rootGroup.children[3] as? SWBCore.FileReference) XCTAssertMatch(headerFileRef2.guid, .prefix("FR")) #expect(headerFileRef2.parent === rootGroup) - let xibVariantGroup = try #require(rootGroup.children[4] as? VariantGroup) + let xibVariantGroup = try #require(rootGroup.children[4] as? SWBCore.VariantGroup) XCTAssertMatch(xibVariantGroup.guid, .prefix("VG")) #expect(xibVariantGroup.parent === rootGroup) #expect(xibVariantGroup.children.count == 3) - let xibFile = try #require(xibVariantGroup.children[0] as? FileReference) + let xibFile = try #require(xibVariantGroup.children[0] as? SWBCore.FileReference) XCTAssertMatch(xibFile.guid, .prefix("FR")) #expect(xibFile.parent === xibVariantGroup) - let stringsFile = try #require(xibVariantGroup.children[1] as? FileReference) + let stringsFile = try #require(xibVariantGroup.children[1] as? SWBCore.FileReference) XCTAssertMatch(stringsFile.guid, .prefix("FR")) #expect(stringsFile.parent === xibVariantGroup) // Check the targets. - let aggregateTarget = try #require(project.targets[0] as? AggregateTarget) - let appTarget = try #require(project.targets[2] as? StandardTarget) - let externalTarget = try #require(project.targets[3] as? ExternalTarget) + let aggregateTarget = try #require(project.targets[0] as? SWBCore.AggregateTarget) + let appTarget = try #require(project.targets[2] as? SWBCore.StandardTarget) + let externalTarget = try #require(project.targets[3] as? SWBCore.ExternalTarget) XCTAssertMatch(aggregateTarget.guid, .prefix("AT")) #expect(aggregateTarget.name == "AggregateTarget") @@ -1598,7 +1600,7 @@ private final class ProjectModelItemClass: ProjectModelItem { #expect(aggregateTarget.buildConfigurations.count == 2) #expect(aggregateTarget.dependencies.map { $0.guid } == [appTarget.guid, externalTarget.guid]) - let fwkTarget = try #require(project.targets[1] as? StandardTarget) + let fwkTarget = try #require(project.targets[1] as? SWBCore.StandardTarget) XCTAssertMatch(fwkTarget.guid, .prefix("T")) #expect(fwkTarget.name == "FwkTarget") #expect(fwkTarget.buildPhases.count == 3) @@ -1623,39 +1625,39 @@ private final class ProjectModelItemClass: ProjectModelItem { #expect(externalTarget.workingDirectory.stringRep == "$(PROJECT_DIR)") #expect(externalTarget.passBuildSettingsInEnvironment) - #expect([Target](workspace.allTargets) == [aggregateTarget, fwkTarget, appTarget, externalTarget]) + #expect([SWBCore.Target](workspace.allTargets) == [aggregateTarget, fwkTarget, appTarget, externalTarget]) // Check the build phases of the framework target. - let headersBuildPhase = try #require(fwkTarget.buildPhases[0] as? HeadersBuildPhase) + let headersBuildPhase = try #require(fwkTarget.buildPhases[0] as? SWBCore.HeadersBuildPhase) let headerBuildFile = headersBuildPhase.buildFiles[0] XCTAssertMatch(headerBuildFile.guid, .prefix("BF")) #expect(headerBuildFile.buildableItem == .reference(guid: headerFileRef1.guid)) - let fwkSourcesBuildPhase = try #require(fwkTarget.buildPhases[1] as? SourcesBuildPhase) + let fwkSourcesBuildPhase = try #require(fwkTarget.buildPhases[1] as? SWBCore.SourcesBuildPhase) let fwkSourceBuildFile = fwkSourcesBuildPhase.buildFiles[0] XCTAssertMatch(fwkSourceBuildFile.guid, .prefix("BF")) #expect(fwkSourceBuildFile.buildableItem == .reference(guid: sourceFileRef1.guid)) - let fwkFrameworksBuildPhase = try #require(fwkTarget.buildPhases[2] as? FrameworksBuildPhase) + let fwkFrameworksBuildPhase = try #require(fwkTarget.buildPhases[2] as? SWBCore.FrameworksBuildPhase) #expect(fwkFrameworksBuildPhase.buildFiles.count == 0) // Check the build phases of the app target. - let appSourcesBuildPhase = try #require(appTarget.buildPhases[0] as? SourcesBuildPhase) + let appSourcesBuildPhase = try #require(appTarget.buildPhases[0] as? SWBCore.SourcesBuildPhase) let appSourceBuildFile = appSourcesBuildPhase.buildFiles[0] XCTAssertMatch(appSourceBuildFile.guid, .prefix("BF")) #expect(appSourceBuildFile.buildableItem == .reference(guid: sourceFileRef2.guid)) - let appFrameworksBuildPhase = try #require(appTarget.buildPhases[1] as? FrameworksBuildPhase) + let appFrameworksBuildPhase = try #require(appTarget.buildPhases[1] as? SWBCore.FrameworksBuildPhase) let appFrameworkBuildFile = appFrameworksBuildPhase.buildFiles[0] XCTAssertMatch(appFrameworkBuildFile.guid, .prefix("BF")) #expect(appFrameworkBuildFile.buildableItem == .targetProduct(guid: fwkProductReference.target!.guid)) - let resourcesBuildPhase = try #require(appTarget.buildPhases[2] as? ResourcesBuildPhase) + let resourcesBuildPhase = try #require(appTarget.buildPhases[2] as? SWBCore.ResourcesBuildPhase) let resourceBuildFile = resourcesBuildPhase.buildFiles[0] XCTAssertMatch(resourceBuildFile.guid, .prefix("BF")) #expect(resourceBuildFile.buildableItem == .reference(guid: xibVariantGroup.guid)) - let copyFilesBuildPhase = try #require(appTarget.buildPhases[3] as? CopyFilesBuildPhase) + let copyFilesBuildPhase = try #require(appTarget.buildPhases[3] as? SWBCore.CopyFilesBuildPhase) let copyFilesBuildFile = copyFilesBuildPhase.buildFiles[0] #expect(copyFilesBuildPhase.destinationSubfolder.stringRep == "$(FRAMEWORKS_FOLDER_PATH)") #expect(copyFilesBuildPhase.destinationSubpath.stringRep == "") diff --git a/Tests/SWBCoreTests/PlatformRegistryTests.swift b/Tests/SWBCoreTests/PlatformRegistryTests.swift index cacb5178..4831eb55 100644 --- a/Tests/SWBCoreTests/PlatformRegistryTests.swift +++ b/Tests/SWBCoreTests/PlatformRegistryTests.swift @@ -48,8 +48,8 @@ import SWBMacro return _diagnosticsEngine.diagnostics.filter { $0.behavior == .error }.map { $0.formatLocalizedDescription(.debugWithoutBehavior) } } - var developerPath: Path { - Path.temporaryDirectory + var developerPath: Core.DeveloperPath { + .fallback(Path.temporaryDirectory) } } diff --git a/Tests/SWBCoreTests/ProductTypesTests.swift b/Tests/SWBCoreTests/ProductTypesTests.swift index 96f79320..3baeb0ef 100644 --- a/Tests/SWBCoreTests/ProductTypesTests.swift +++ b/Tests/SWBCoreTests/ProductTypesTests.swift @@ -10,6 +10,7 @@ import Testing @_spi(Testing) import SWBCore import SWBTestSupport import SWBUtil +import SWBProtocol @Suite fileprivate struct ProductTypesTests: CoreBasedTests { diff --git a/Tests/SWBCoreTests/ProvisioningTests.swift b/Tests/SWBCoreTests/ProvisioningTests.swift index dac7ac4d..38edbadf 100644 --- a/Tests/SWBCoreTests/ProvisioningTests.swift +++ b/Tests/SWBCoreTests/ProvisioningTests.swift @@ -16,8 +16,9 @@ import Testing import SWBTestSupport import SWBUtil import SWBMacro +import SWBProtocol -private func createMockProject() throws -> Project { +private func createMockProject() throws -> SWBCore.Project { let projectPIF: [String: PropertyListItem] = [ "guid": "some-project-guid", "path": "/tmp/SomeProject/aProject.xcodeproj", @@ -190,7 +191,7 @@ private func setupMacroEvaluationScope(_ settings: [MacroDeclaration:String] = [ let workspaceContext = WorkspaceContext(core: core, workspace: testWorkspace, processExecutionCache: .sharedForTesting) let buildRequestContext = BuildRequestContext(workspaceContext: workspaceContext) - guard let target = testWorkspace.projects.first?.targets.first as? StandardTarget else { + guard let target = testWorkspace.projects.first?.targets.first as? SWBCore.StandardTarget else { Issue.record("unable to find target in test workspace") return } diff --git a/Tests/SWBCoreTests/SettingsTests.swift b/Tests/SWBCoreTests/SettingsTests.swift index 0f406d2c..df822c5f 100644 --- a/Tests/SWBCoreTests/SettingsTests.swift +++ b/Tests/SWBCoreTests/SettingsTests.swift @@ -90,7 +90,7 @@ import SWBMacro #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.OutputPath) === nil) // Verify that the computed path defaults were added. - #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.DEVELOPER_DIR)?.expression.stringRep == core.developerPath.str) + #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.DEVELOPER_DIR)?.expression.stringRep == core.developerPath.path.str) #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.AVAILABLE_PLATFORMS)?.expression.stringRep.contains("macosx") == true) // Verify that the CACHE_ROOT was added. @@ -263,16 +263,14 @@ import SWBMacro "USER_TARGET_SETTING": "USER_TARGET_VALUE"])], buildPhases: [TestSourcesBuildPhase(["Mock.cpp"])])])]).load(core) let context = try await contextForTestData(testWorkspace, - environment: [ - "ENABLE_BITCODE": "YES", - ], - files: [ - core.loadSDK(.macOS).path.join("Cocoa.pch"): "", - core.loadSDK(.macOS).path.join("System/Library/Frameworks/mock.txt"): "", - core.loadSDK(.macOS).path.join("usr/include/mock.txt"): "", - additionalSDKPath.join("Applications/Xcode.app/mock.txt"): "", - additionalSDKPath.join("usr/mock.txt"): "", - ]) + files: [ + core.loadSDK(.macOS).path.join("Cocoa.pch"): "", + core.loadSDK(.macOS).path.join("System/Library/Frameworks/mock.txt"): "", + core.loadSDK(.macOS).path.join("usr/include/mock.txt"): "", + additionalSDKPath.join("Applications/Xcode.app/mock.txt"): "", + additionalSDKPath.join("usr/mock.txt"): "", + ] + ) let buildRequestContext = BuildRequestContext(workspaceContext: context) let testProject = context.workspace.projects[0] let testTarget = testProject.targets[0] @@ -591,7 +589,7 @@ import SWBMacro // Aggregate targets' settings are substantially similar to standard targets, but it is common for certain values to not be defined for aggregate targets. #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.TARGET_NAME)?.expression.stringRep == "AggregateTarget1") - #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.SDKROOT)?.expression.stringRep.hasPrefix(try context.fs.realpath(core.developerPath).str) == true) + #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.SDKROOT)?.expression.stringRep.hasPrefix(try context.fs.realpath(core.developerPath.path).str) == true) #expect(settings.tableForTesting.lookupMacro(BuiltinMacros.TARGET_BUILD_DIR)?.expression.stringRep == "$(UNINSTALLED_PRODUCTS_DIR)$(TARGET_BUILD_SUBPATH)") // Subsequent definitions will have overwritten the previous definition. @@ -631,17 +629,17 @@ import SWBMacro } // Check we can find clang in the toolchain. - #expect(settings.executableSearchPaths.lookup(Path("clang")) == core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/bin/clang")) + #expect(settings.executableSearchPaths.lookup(Path("clang")) == core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/bin/clang")) // Check that we find ibtool outside the toolchain. - #expect(settings.executableSearchPaths.lookup(Path("ibtool")) == core.developerPath.join("usr/bin/ibtool")) + #expect(settings.executableSearchPaths.lookup(Path("ibtool")) == core.developerPath.path.join("usr/bin/ibtool")) // Check the paths directly. let paths = settings.executableSearchPaths.paths - let toolchainPathIndex = paths.firstIndex(of: core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/bin")) ?? Int.max - let platformPathIndex = paths.firstIndex(of: core.developerPath.join("Platforms/MacOSX.platform/usr/bin")) ?? Int.max - let developerLocalBinIndex = paths.firstIndex(of: core.developerPath.join("usr/local/bin")) ?? Int.max - let developerBinIndex = paths.firstIndex(of: core.developerPath.join("usr/bin")) ?? Int.max + let toolchainPathIndex = paths.firstIndex(of: core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/bin")) ?? Int.max + let platformPathIndex = paths.firstIndex(of: core.developerPath.path.join("Platforms/MacOSX.platform/usr/bin")) ?? Int.max + let developerLocalBinIndex = paths.firstIndex(of: core.developerPath.path.join("usr/local/bin")) ?? Int.max + let developerBinIndex = paths.firstIndex(of: core.developerPath.path.join("usr/bin")) ?? Int.max #expect(toolchainPathIndex < platformPathIndex) #expect(platformPathIndex < developerBinIndex) #expect(developerBinIndex < developerLocalBinIndex) @@ -3133,11 +3131,11 @@ import SWBMacro "USER_TARGET_SETTING": "USER_TARGET_VALUE"])], buildPhases: [TestSourcesBuildPhase(["Mock.cpp"])])])]).load(getCore()) let context = try await contextForTestData(testWorkspace, - environment: [ - "ENABLE_BITCODE": "YES", - "RC_ARCHS": "x86_64 x86_64h", - ], - files: [:]) + environment: [ + "RC_ARCHS": "x86_64 x86_64h", + ], + files: [:] + ) let buildRequestContext = BuildRequestContext(workspaceContext: context) let testProject = context.workspace.projects[0] let testTarget = testProject.targets[0] @@ -4997,34 +4995,6 @@ import SWBMacro #expect(settings.globalScope.evaluate(BuiltinMacros.OTHER_CFLAGS) == ["-best"]) } - @Test - func packagesAllowTestingSearchPathsAndBitcodeSimultaneously() async throws { - let testWorkspace = try await TestWorkspace("Test", projects: [ - TestPackageProject("aPackageProject", groupTree: TestGroup("Sources", path: "Sources", children: [TestFile("best.swift"), TestFile("Info.plist"),]), targets: [ - TestStandardTarget("Target", - type: .application, - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "ENABLE_TESTING_SEARCH_PATHS": "YES", - "INFOPLIST_FILE": "Sources/Info.plist", - "SUPPORTED_PLATFORMS": "$(AVAILABLE_PLATFORMS)", - ]) - ]) - ]) - ]).load(getCore()) - - let context = try await contextForTestData(testWorkspace) - let buildRequestContext = BuildRequestContext(workspaceContext: context) - let testProject = context.workspace.projects[0] - let testTarget = testProject.targets[0] - - let parameters = BuildParameters(configuration: "Debug", activeRunDestination: .iOS) - let settings = Settings(workspaceContext: context, buildRequestContext: buildRequestContext, parameters: parameters, project: testProject, target: testTarget) - - #expect(!settings.globalScope.evaluate(BuiltinMacros.ENABLE_BITCODE)) - #expect(settings.globalScope.evaluate(BuiltinMacros.ENABLE_TESTING_SEARCH_PATHS)) - } - @Test(.requireSDKs(.macOS)) func catalystDoesNotBreakOnlyActiveArch() async throws { let testWorkspace = TestWorkspace("Test", projects: [ diff --git a/Tests/SWBCoreTests/ShellScriptEnvironmentTests.swift b/Tests/SWBCoreTests/ShellScriptEnvironmentTests.swift index f363d0c5..16100daf 100644 --- a/Tests/SWBCoreTests/ShellScriptEnvironmentTests.swift +++ b/Tests/SWBCoreTests/ShellScriptEnvironmentTests.swift @@ -15,6 +15,7 @@ import Testing import SWBUtil import SWBCore import SWBTestSupport +import SWBProtocol @Suite fileprivate struct ShellScriptEnvironmentTests: CoreBasedTests { @Test(.requireHostOS(.macOS)) @@ -72,7 +73,6 @@ import SWBTestSupport "DERIVED_SOURCES_DIR": srcroot.join("build/aProject.build/Debug/Target1.build/DerivedSources").str, "DOCUMENTATION_FOLDER_PATH": "Target1.app/Contents/Resources/English.lproj/Documentation", "DWARF_DSYM_FILE_NAME": "Target1.app.dSYM", - "ENABLE_BITCODE": "NO", "ENABLE_ON_DEMAND_RESOURCES": "NO", "ENABLE_TESTABILITY": "NO", "EXECUTABLES_FOLDER_PATH": "Target1.app/Contents/Executables", diff --git a/Tests/SWBCoreTests/SwiftCompilerTests.swift b/Tests/SWBCoreTests/SwiftCompilerTests.swift index 637fa1c2..0fb08d09 100644 --- a/Tests/SWBCoreTests/SwiftCompilerTests.swift +++ b/Tests/SWBCoreTests/SwiftCompilerTests.swift @@ -19,6 +19,7 @@ import SWBProtocol import SWBTestSupport import SWBMacro @_spi(Testing) import SWBCore +import Synchronization fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Sendable { let buildOperationIdentifier: BuildSystemOperationIdentifier @@ -412,7 +413,7 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda #expect(delegate.events[safe: 1]?.0 == "skippedSubtask") let expectedSignature: ByteString = { - let md5 = MD5Context() + let md5 = InsecureHashContext() md5.add(string: "CompileSwift VARIANT ARCH bar.swift") return md5.signature }() diff --git a/Tests/SWBCoreTests/TargetDependencyResolverTests.swift b/Tests/SWBCoreTests/TargetDependencyResolverTests.swift index ebce0b99..69a6a6ae 100644 --- a/Tests/SWBCoreTests/TargetDependencyResolverTests.swift +++ b/Tests/SWBCoreTests/TargetDependencyResolverTests.swift @@ -16,6 +16,7 @@ import SWBProtocol import SWBTestSupport @_spi(Testing) import SWBUtil import Foundation +import SWBMacro fileprivate enum TargetPlatformSpecializationMode { /// The v1 support of target platform specialization that uses SDKROOT=auto and SDK_VARIANT=auto to opt-in. diff --git a/Tests/SWBCoreTests/ToolchainRegistryTests.swift b/Tests/SWBCoreTests/ToolchainRegistryTests.swift index 12cad775..e8f8753d 100644 --- a/Tests/SWBCoreTests/ToolchainRegistryTests.swift +++ b/Tests/SWBCoreTests/ToolchainRegistryTests.swift @@ -16,6 +16,7 @@ import SWBTestSupport import SWBUtil @_spi(Testing) import SWBCore +import SWBServiceCore @Suite fileprivate struct ToolchainRegistryTests: CoreBasedTests { let fs: any FSProxy = localFS @@ -70,9 +71,15 @@ import SWBUtil } let pluginManager = await PluginManager(skipLoadingPluginIdentifiers: []) + await pluginManager.registerExtensionPoint(DeveloperDirectoryExtensionPoint()) await pluginManager.registerExtensionPoint(SpecificationsExtensionPoint()) await pluginManager.registerExtensionPoint(ToolchainRegistryExtensionPoint()) await pluginManager.register(BuiltinSpecsExtension(), type: SpecificationsExtensionPoint.self) + struct MockDeveloperDirectoryExtensionPoint: DeveloperDirectoryExtension { + func fallbackDeveloperDirectory(hostOperatingSystem: OperatingSystem) async throws -> Path? { + .root + } + } struct MockToolchainExtension: ToolchainRegistryExtension { func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] { guard context.toolchainRegistry.lookup(ToolchainRegistry.defaultToolchainIdentifier) == nil else { @@ -81,8 +88,20 @@ import SWBUtil return [Toolchain(identifier: ToolchainRegistry.defaultToolchainIdentifier, displayName: "Mock", version: Version(), aliases: ["default"], path: .root, frameworkPaths: [], libraryPaths: [], defaultSettings: [:], overrideSettings: [:], defaultSettingsWhenPrimary: [:], executableSearchPaths: [], testingLibraryPlatformNames: [], fs: context.fs)] } } + await pluginManager.register(MockDeveloperDirectoryExtensionPoint(), type: DeveloperDirectoryExtensionPoint.self) await pluginManager.register(MockToolchainExtension(), type: ToolchainRegistryExtensionPoint.self) - let core = try #require(await Core.getInitializedCore(TestingCoreDelegate(), pluginManager: pluginManager, inferiorProductsPath: Path.root.join("invalid"), environment: [:], buildServiceModTime: Date(), connectionMode: .inProcess)) + let coreDelegate = TestingCoreDelegate() + let core = await Core.getInitializedCore(coreDelegate, pluginManager: pluginManager, inferiorProductsPath: Path.root.join("invalid"), environment: [:], buildServiceModTime: Date(), connectionMode: .inProcess) + guard let core else { + let errors = coreDelegate.diagnostics.filter { $0.behavior == .error } + for error in errors { + Issue.record(Comment(rawValue: error.formatLocalizedDescription(.debugWithoutBehavior))) + } + if errors.isEmpty { + Issue.record("Failed to initialize core but no errors were provided") + } + return + } let delegate = TestDataDelegate(pluginManager: core.pluginManager) let registry = await ToolchainRegistry(delegate: delegate, searchPaths: [(tmpDirPath, strict: strict)], fs: fs, hostOperatingSystem: core.hostOperatingSystem) try perform(registry, delegate.warnings, delegate.errors) diff --git a/Tests/SWBCoreTests/WorkspaceHeaderIndexTests.swift b/Tests/SWBCoreTests/WorkspaceHeaderIndexTests.swift index 7dd23268..16176dfb 100644 --- a/Tests/SWBCoreTests/WorkspaceHeaderIndexTests.swift +++ b/Tests/SWBCoreTests/WorkspaceHeaderIndexTests.swift @@ -14,6 +14,7 @@ import Foundation import Testing import SWBTestSupport @_spi(Testing) import SWBCore +import SWBMacro @Suite fileprivate struct WorkspaceHeaderIndexTests: CoreBasedTests { @Test diff --git a/Tests/SWBCoreTests/XCFrameworkTests.swift b/Tests/SWBCoreTests/XCFrameworkTests.swift index 37abdf1b..d90f4414 100644 --- a/Tests/SWBCoreTests/XCFrameworkTests.swift +++ b/Tests/SWBCoreTests/XCFrameworkTests.swift @@ -14,6 +14,7 @@ import Foundation import Testing import SWBTestSupport import SWBUtil +import SWBMacro @_spi(Testing) import SWBCore @@ -321,7 +322,6 @@ import SWBUtil "LibraryPath": .plString("XCSample.dylib"), "BinaryPath": .plString("XCSample.dylib"), "HeadersPath": .plString("Headers"), - "BitcodeSymbolMapsPath": .plString("BCSymbolMaps"), ]), .plDict([ "LibraryIdentifier": .plString("x86_64-apple-iphonesimulator13.0"), @@ -330,7 +330,6 @@ import SWBUtil "LibraryPath": .plString("XCSample.dylib"), // Missing BinaryPath to exercise this case "HeadersPath": .plString("Headers"), - "BitcodeSymbolMapsPath": .plString("BCSymbolMaps"), ]), ]) ]) @@ -364,7 +363,6 @@ import SWBUtil #expect(library.libraryPath.str == "XCSample.dylib") #expect(library.binaryPath?.str == "XCSample.dylib") #expect(library.headersPath?.str == "Headers") - #expect(library.bitcodeSymbolMapsPath?.str == "BCSymbolMaps") } do { @@ -374,7 +372,6 @@ import SWBUtil #expect(library.libraryPath.str == "XCSample.dylib") #expect(library.binaryPath == nil) #expect(library.headersPath?.str == "Headers") - #expect(library.bitcodeSymbolMapsPath?.str == "BCSymbolMaps") } } @@ -998,7 +995,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { else { #expect(library.debugSymbolsPath == nil) } - #expect(library.bitcodeSymbolMapsPath == nil) #expect(library.libraryType == .framework) } } @@ -1152,12 +1148,12 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { } @Test - func iOSFrameworkWithDebugSymbolsAndBitCodeMaps_swift() async throws { + func iOSFrameworkWithDebugSymbols_swift() async throws { try await _testiOSFramework(useSwift: true, withDebugSymbols: true) } @Test - func iOSFrameworkWithDebugSymbolsAndBitCodeMaps_nonswift() async throws { + func iOSFrameworkWithDebugSymbols_nonswift() async throws { try await _testiOSFramework(useSwift: false, withDebugSymbols: true) } @@ -1170,7 +1166,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { if withDebugSymbols { debugSymbolPaths = [ tmpDir.join(path.basenameWithoutSuffix + ".framework.dSYM"), - tmpDir.join(path.basenameWithoutSuffix + ".bcsymbolmap") ] } else { @@ -1192,11 +1187,9 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { #expect(library.headersPath == nil) if withDebugSymbols { #expect(library.debugSymbolsPath?.str == "dSYMs") - #expect(library.bitcodeSymbolMapsPath?.str == "BCSymbolMaps") } else { #expect(library.debugSymbolsPath == nil) - #expect(library.bitcodeSymbolMapsPath == nil) } #expect(library.libraryType == .framework) } @@ -1518,11 +1511,9 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { } let dsymPath1 = try createFakeDebugFile(at: path1, bundle: true) let dsymPath3 = try createFakeDebugFile(at: path3) - let bcsymPath3a = try createFakeDebugFile(at: path3, basename: "bitcode1", fileExtension: "bcsymbolmap") - let bcsymPath3b = try createFakeDebugFile(at: path3, basename: "bitcode2", fileExtension: "bcsymbolmap") let commandLine: [String] - commandLine = ["createXCFramework", "-library", path1.str, "-debug-symbols", dsymPath1.str, "-headers", path1.dirname.join("include").str, "-library", path2.str, "-headers", path2.dirname.join("include").str, "-library", path3.str, "-headers", path3.dirname.join("include").str, "-debug-symbols", dsymPath3.str, "-debug-symbols", bcsymPath3a.str, "-debug-symbols", bcsymPath3b.str, "-output", outputPath.str] + (allowInternalDistribution ? ["-allow-internal-distribution"] : []) + commandLine = ["createXCFramework", "-library", path1.str, "-debug-symbols", dsymPath1.str, "-headers", path1.dirname.join("include").str, "-library", path2.str, "-headers", path2.dirname.join("include").str, "-library", path3.str, "-headers", path3.dirname.join("include").str, "-debug-symbols", dsymPath3.str, "-output", outputPath.str] + (allowInternalDistribution ? ["-allow-internal-distribution"] : []) // Validate that the output is correct. let (passed, output) = XCFramework.createXCFramework(commandLine: commandLine, currentWorkingDirectory: tmpDir, infoLookup: infoLookup) @@ -1556,7 +1547,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { #expect(macos.supportedArchitectures == ["x86_64"]) #expect(macos.headersPath?.str == expectedHeadersPath) #expect(macos.debugSymbolsPath?.str == "dSYMs") - #expect(macos.bitcodeSymbolMapsPath == nil) #expect(macos.platformVariant == nil) #expect(iphoneos.libraryPath.str == "libsample.dylib") @@ -1566,7 +1556,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { #expect(iphoneos.supportedArchitectures == ["arm64", "arm64e"]) #expect(iphoneos.headersPath?.str == expectedHeadersPath) #expect(iphoneos.debugSymbolsPath == nil) - #expect(iphoneos.bitcodeSymbolMapsPath == nil) #expect(iphoneos.platformVariant == nil) #expect(iphonesimulator.libraryPath.str == "libsample.dylib") @@ -1577,7 +1566,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { #expect(iphonesimulator.platformVariant == "simulator") #expect(iphonesimulator.headersPath?.str == expectedHeadersPath) #expect(iphonesimulator.debugSymbolsPath?.str == "dSYMs") - #expect(iphonesimulator.bitcodeSymbolMapsPath?.str == "BCSymbolMaps") // Validate that there are actually files on disk in the correct location. #expect(localFS.exists(outputPath.join(macos.libraryIdentifier).join(macos.libraryPath))) @@ -1594,8 +1582,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { // Validate the bcsymbolmaps are in place. #expect(!localFS.exists(outputPath.join(macos.libraryIdentifier).join("BCSymbolMaps"))) #expect(!localFS.exists(outputPath.join(iphoneos.libraryIdentifier).join("BCSymbolMaps"))) - #expect(localFS.exists(outputPath.join(iphonesimulator.libraryIdentifier).join("BCSymbolMaps").join("bitcode1.bcsymbolmap"))) - #expect(localFS.exists(outputPath.join(iphonesimulator.libraryIdentifier).join("BCSymbolMaps").join("bitcode2.bcsymbolmap"))) if useSwift { let macosSwiftModuleDir = outputPath.join(macos.libraryIdentifier).join(macos.headersPath!).join("sample.swiftmodule") @@ -1646,9 +1632,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { try fs.createDirectory(Path("/var/tmp/hi.xcarchive/dSYMs/libhi.a.dSYM"), recursive: true) // explicitly missing dSYM for 'hi.dylib' try fs.createDirectory(Path("/var/tmp/hi.xcarchive/BCSymbolMaps"), recursive: true) - try fs.write(Path("/var/tmp/hi.xcarchive/BCSymbolMaps/hi.framework.bcsymbolmap"), contents: "symbols!") - // explicitly missing bcsymbolmap for 'libhi.a' - try fs.write(Path("/var/tmp/hi.xcarchive/BCSymbolMaps/hi.dylib.bcsymbolmap"), contents: "symbols!") try fs.createDirectory(Path("/var/tmp/bye.xcarchive/Products/Library/Frameworks/bye.framework"), recursive: true) try fs.createDirectory(Path("/var/tmp/bye.xcarchive/Products/usr/local/lib"), recursive: true) @@ -1657,7 +1640,6 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { try fs.createDirectory(Path("/var/tmp/bye.xcarchive/dSYMs/bye.framework.dSYM"), recursive: true) // explicitly missing dSYM try fs.createDirectory(Path("/var/tmp/bye.xcarchive/BCSymbolMaps"), recursive: true) - try fs.write(Path("/var/tmp/bye.xcarchive/BCSymbolMaps/bye.framework.bcsymbolmap"), contents: "symbols!") try testCommandLineRewrite([ "-create-xcframework", @@ -1680,8 +1662,8 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { ], expected: [ "-create-xcframework", - "-framework", "/var/tmp/hi.xcarchive/Products/Library/Frameworks/hi.framework", "-debug-symbols", "/var/tmp/hi.xcarchive/dSYMs/hi.framework.dSYM", "-debug-symbols", "/var/tmp/hi.xcarchive/BCSymbolMaps/hi.framework.bcsymbolmap", - "-framework", "/var/tmp/bye.xcarchive/Products/Library/Frameworks/bye.framework", "-debug-symbols", "/var/tmp/bye.xcarchive/dSYMs/bye.framework.dSYM", "-debug-symbols", "/var/tmp/bye.xcarchive/BCSymbolMaps/bye.framework.bcsymbolmap", + "-framework", "/var/tmp/hi.xcarchive/Products/Library/Frameworks/hi.framework", "-debug-symbols", "/var/tmp/hi.xcarchive/dSYMs/hi.framework.dSYM", + "-framework", "/var/tmp/bye.xcarchive/Products/Library/Frameworks/bye.framework", "-debug-symbols", "/var/tmp/bye.xcarchive/dSYMs/bye.framework.dSYM", "-output", "/var/tmp/my.xcframework", ]) @@ -1695,7 +1677,7 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { expected: [ "-create-xcframework", "-library", "/var/tmp/hi.xcarchive/Products/usr/local/lib/libhi.a", "-headers", "/var/tmp/hi.xcarchive/Products/usr/local/include", "-debug-symbols", "/var/tmp/hi.xcarchive/dSYMs/libhi.a.dSYM", - "-library", "/var/tmp/hi.xcarchive/Products/usr/local/lib/hi.dylib", "-headers", "/var/tmp/hi.xcarchive/Products/usr/local/include", "-debug-symbols", "/var/tmp/hi.xcarchive/BCSymbolMaps/hi.dylib.bcsymbolmap", + "-library", "/var/tmp/hi.xcarchive/Products/usr/local/lib/hi.dylib", "-headers", "/var/tmp/hi.xcarchive/Products/usr/local/include", "-library", "/var/tmp/bye.xcarchive/Products/usr/local/lib/libbye.a", "-output", "/var/tmp/my.xcframework", ]) @@ -1710,7 +1692,7 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { expected: [ "-create-xcframework", "-library", "/var/tmp/hi.xcarchive/Products/usr/local/lib/libhi.a", "-headers", "/var/tmp/hi.xcarchive/Products/usr/local/include", "-debug-symbols", "/var/tmp/hi.xcarchive/dSYMs/libhi.a.dSYM", - "-library", "/var/tmp/hi.xcarchive/Products/usr/local/lib/hi.dylib", "-headers", "/var/tmp/hi.xcarchive/Products/usr/local/include", "-debug-symbols", "/var/tmp/hi.xcarchive/BCSymbolMaps/hi.dylib.bcsymbolmap", + "-library", "/var/tmp/hi.xcarchive/Products/usr/local/lib/hi.dylib", "-headers", "/var/tmp/hi.xcarchive/Products/usr/local/include", "-library", "/var/tmp/bye.xcarchive/Products/usr/local/lib/libbye.a", "-output", "/var/tmp/my.xcframework", ]) @@ -1718,7 +1700,7 @@ fileprivate struct XCFrameworkCreationCommandTests: CoreBasedTests { // This will create an invalid command-line, but the only test consideration here is that the rewriting happens appropriately. let expectedCommandLine = [ "-create-xcframework", - "-framework", "/var/tmp/hi.xcarchive/Products/Library/Frameworks/hi.framework", "-debug-symbols", "/var/tmp/hi.xcarchive/dSYMs/hi.framework.dSYM", "-debug-symbols", "/var/tmp/hi.xcarchive/BCSymbolMaps/hi.framework.bcsymbolmap", + "-framework", "/var/tmp/hi.xcarchive/Products/Library/Frameworks/hi.framework", "-debug-symbols", "/var/tmp/hi.xcarchive/dSYMs/hi.framework.dSYM", "-library", "/var/tmp/hi.xcarchive/Products/usr/local/lib/-allow-internal-distribution", "-headers", "/var/tmp/hi.xcarchive/Products/usr/local/include", "-output", "/var/tmp/my.xcframework", ] diff --git a/Tests/SWBProtocolTests/MessageSerializationTests.swift b/Tests/SWBProtocolTests/MessageSerializationTests.swift index 6352388c..53dcc2c4 100644 --- a/Tests/SWBProtocolTests/MessageSerializationTests.swift +++ b/Tests/SWBProtocolTests/MessageSerializationTests.swift @@ -245,7 +245,7 @@ import Testing let schemeDescription = SchemeDescription(name: "best", disambiguatedName: "best", isShared: true, isAutogenerated: true, actions: ActionsInfo(analyze: actionInfo, archive: actionInfo, profile: actionInfo, run: actionInfo, test: actionInfo)) #expect(try schemeDescription == serializationRoundTrip(schemeDescription)) - let productDescription = try ProductDescription(displayName: "Product", productName: "product", identifier: "123456", productType: .app, dependencies: nil, bundleIdentifier: "com.apple.product", targetedDeviceFamilies: [.appleTV, .iPad], deploymentTarget: Version("13.0"), marketingVersion: "1.0", buildVersion: "1.0", enableBitcode: false, codesign: .manual, team: "best-team", infoPlistPath: "/Info.plist", iconPath: "/Icon.png") + let productDescription = try ProductDescription(displayName: "Product", productName: "product", identifier: "123456", productType: .app, dependencies: nil, bundleIdentifier: "com.apple.product", targetedDeviceFamilies: [.appleTV, .iPad], deploymentTarget: Version("13.0"), marketingVersion: "1.0", buildVersion: "1.0", codesign: .manual, team: "best-team", infoPlistPath: "/Info.plist", iconPath: "/Icon.png") #expect(try productDescription == serializationRoundTrip(productDescription)) let productTupleDescription = ProductTupleDescription(displayName: "Product", productName: "product", productType: .app, identifier: "123456", team: nil, bundleIdentifier: "com.apple.product", destination: destinationInfo, containingSchemes: ["a", "b", "c"], iconPath: "/Icon.png") diff --git a/Tests/SWBQNXPlatformTests/SWBQNXPlatformTests.swift b/Tests/SWBQNXPlatformTests/SWBQNXPlatformTests.swift index 2109448e..3d9b9b92 100644 --- a/Tests/SWBQNXPlatformTests/SWBQNXPlatformTests.swift +++ b/Tests/SWBQNXPlatformTests/SWBQNXPlatformTests.swift @@ -15,6 +15,7 @@ import SWBProtocol import SWBTestSupport import SWBTaskExecution import SWBUtil +import SWBCore @Suite fileprivate struct QNXBuildOperationTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/AppClipTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/AppClipTaskConstructionTests.swift index 0c565321..6aed1c34 100644 --- a/Tests/SWBTaskConstructionTests/AppClipTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/AppClipTaskConstructionTests.swift @@ -15,6 +15,7 @@ import SWBTestSupport import SWBCore import SWBUtil +import SWBProtocol @Suite fileprivate struct AppClipTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/AppExtensionTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/AppExtensionTaskConstructionTests.swift index 414315b4..5832096a 100644 --- a/Tests/SWBTaskConstructionTests/AppExtensionTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/AppExtensionTaskConstructionTests.swift @@ -15,6 +15,7 @@ import SWBTestSupport import SWBCore import SWBUtil +import SWBProtocol @Suite fileprivate struct AppExtensionTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/AppIntentsMetadataTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/AppIntentsMetadataTaskConstructionTests.swift index d62ff168..afd64f3c 100644 --- a/Tests/SWBTaskConstructionTests/AppIntentsMetadataTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/AppIntentsMetadataTaskConstructionTests.swift @@ -17,6 +17,8 @@ import SWBProtocol import SWBTaskConstruction import SWBTestSupport import SWBUtil +import Foundation +import SWBTaskExecution @Suite(.requireXcode16()) fileprivate struct AppIntentsMetadataTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/BitcodeTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/BitcodeTaskConstructionTests.swift deleted file mode 100644 index a8e543e0..00000000 --- a/Tests/SWBTaskConstructionTests/BitcodeTaskConstructionTests.swift +++ /dev/null @@ -1,494 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -import Testing -import SWBTestSupport - -import SWBCore -import SWBUtil - -/// Test task construction involving bitcode. -/// -/// Bitcode has a complicated set of rules including multiple generation modes (off, marker, full), and affects compiling, linking, and copying. -@Suite(.userDefaults(["EnableBitcodeSupport": "1"])) -fileprivate struct BitcodeTaskConstructionTests: CoreBasedTests { - /// Test the logic to strip bitcode when copying items in a copy files build phase. - @Test(.requireSDKs(.iOS)) - func bitcodeStripWhileCopying() async throws { - let testProject = TestProject( - "aProject", - groupTree: TestGroup( - "SomeFiles", - children: [ - TestFile("AppSource.m"), - TestFile("FwkSource.m"), - TestFile("Info.plist"), - TestFile("Mock.txt"), - ]), - buildConfigurations: [ - TestBuildConfiguration( "Debug", buildSettings: [ - "INFOPLIST_FILE": "Info.plist", - "PRODUCT_NAME": "$(TARGET_NAME)", - "CODE_SIGN_IDENTITY": "-", - "AD_HOC_CODE_SIGNING_ALLOWED": "YES", - // Using the public iOS SDK defaults both ENABLE_BITCODE and STRIP_BITCODE_FROM_COPIED_FILES to YES. - "SDKROOT": "iphoneos", - ]), - ], - targets: [ - TestStandardTarget( - "AppTarget", - type: .application, - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "INFOPLIST_FILE": "Info.plist", - ]), - ], - buildPhases: [ - TestSourcesBuildPhase([ - "AppSource.m", - ]), - TestFrameworksBuildPhase([]), - TestCopyFilesBuildPhase([ - TestBuildFile("FwkTarget.framework", codeSignOnCopy: true), - ], destinationSubfolder: .frameworks, onlyForDeployment: false), - TestCopyFilesBuildPhase([ - TestBuildFile("Mock.txt", codeSignOnCopy: true), - ], destinationSubfolder: .resources, onlyForDeployment: false), - ], - dependencies: ["FwkTarget"] - ), - TestStandardTarget( - "FwkTarget", - type: .framework, - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "INFOPLIST_FILE": "Info.plist", - ]), - ], - buildPhases: [ - TestSourcesBuildPhase([ - "FwkSource.m", - ]), - TestFrameworksBuildPhase([]), - ] - ), - ] - ) - - let core = try await getCore() - let tester = try TaskConstructionTester(core, testProject) - let SRCROOT = tester.workspace.projects[0].sourceRoot.str - - // Test building without bitcode. - await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["ENABLE_BITCODE": "NO", "BITCODE_GENERATION_MODE": "bitcode"]), runDestination: .iOS) { results in - results.checkTasks(.matchRuleType("Gate")) { _ in } - results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in } - - // There shouldn't be any diagnostics. - results.checkNoDiagnostics() - - // Check that none of the bitcode options are in the compile and link tasks' command lines. - results.checkTasks(.matchRuleType("CompileC")) { tasks in - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - task.checkCommandLineDoesNotContain("-fembed-bitcode") - } - } - results.checkTasks(.matchRuleType("Ld")) { tasks in - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - task.checkCommandLineDoesNotContain("-fembed-bitcode") - task.checkCommandLineDoesNotContain("-bitcode_verify") - task.checkCommandLineDoesNotContain("-bitcode_hide_symbols") - task.checkCommandLineDoesNotContain("-bitcode_symbol_map") - } - } - - // Check that the copying of the framework is stripping bitcode fully. - results.checkTask(.matchTargetName("AppTarget"), .matchRuleType("Copy"), .matchRuleItemBasename("FwkTarget.framework")) { task in - task.checkCommandLineContainsUninterrupted(["-bitcode-strip", "all", "-bitcode-strip-tool", "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/bitcode_strip"]) - task.checkCommandLineContainsUninterrupted(["\(SRCROOT)/build/Debug-iphoneos/FwkTarget.framework", "\(SRCROOT)/build/Debug-iphoneos/AppTarget.app/Frameworks"]) - } - // Check that the copying of the text file is NOT stripping bitcode (because this file is not code signed and so should never be stripped). - results.checkTask(.matchTargetName("AppTarget"), .matchRuleType("Copy"), .matchRuleItemBasename("Mock.txt")) { task in - task.checkCommandLineDoesNotContain("-bitcode-strip") - task.checkCommandLineDoesNotContain("-bitcode-strip-tool") - task.checkCommandLineContainsUninterrupted(["\(SRCROOT)/Mock.txt", "\(SRCROOT)/build/Debug-iphoneos/AppTarget.app"]) - } - } - - // Test building with the bitcode marker. - await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["ENABLE_BITCODE": "YES", "BITCODE_GENERATION_MODE": "marker"]), runDestination: .iOS) { results in - results.checkTasks(.matchRuleType("Gate")) { _ in } - results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in } - - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'AppTarget' from project 'aProject')")) - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'FwkTarget' from project 'aProject')")) - - // There shouldn't be any diagnostics. - results.checkNoDiagnostics() - - // Check that none of the bitcode options are in the compile and link tasks' command lines. - results.checkTasks(.matchRuleType("CompileC")) { tasks in - for task in tasks { - task.checkCommandLineContains(["-fembed-bitcode-marker"]) - task.checkCommandLineDoesNotContain("-fembed-bitcode") - } - } - results.checkTasks(.matchRuleType("Ld")) { tasks in - for task in tasks { - task.checkCommandLineContains(["-fembed-bitcode-marker"]) - task.checkCommandLineDoesNotContain("-fembed-bitcode") - task.checkCommandLineDoesNotContain("-bitcode_verify") - task.checkCommandLineDoesNotContain("-bitcode_hide_symbols") - task.checkCommandLineDoesNotContain("-bitcode_symbol_map") - } - } - - // Check that the copying of the framework is stripping bitcode to marker level. - results.checkTask(.matchTargetName("AppTarget"), .matchRuleType("Copy"), .matchRuleItemBasename("FwkTarget.framework")) { task in - task.checkCommandLineContainsUninterrupted(["-bitcode-strip", "replace-with-marker", "-bitcode-strip-tool", "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/bitcode_strip"]) - task.checkCommandLineContainsUninterrupted(["\(SRCROOT)/build/Debug-iphoneos/FwkTarget.framework", "\(SRCROOT)/build/Debug-iphoneos/AppTarget.app/Frameworks"]) - } - // Check that the copying of the text file is NOT stripping bitcode (because this file is not code signed and so should never be stripped). - results.checkTask(.matchTargetName("AppTarget"), .matchRuleType("Copy"), .matchRuleItemBasename("Mock.txt")) { task in - task.checkCommandLineDoesNotContain("-bitcode-strip") - task.checkCommandLineDoesNotContain("-bitcode-strip-tool") - task.checkCommandLineContainsUninterrupted(["\(SRCROOT)/Mock.txt", "\(SRCROOT)/build/Debug-iphoneos/AppTarget.app"]) - } - } - - // Test building with full bitcode. - await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["ENABLE_BITCODE": "YES", "BITCODE_GENERATION_MODE": "bitcode"]), runDestination: .iOS) { results in - results.checkTasks(.matchRuleType("Gate")) { _ in } - results.checkTasks(.matchRuleType("CreateBuildDirectory")) { _ in } - - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'AppTarget' from project 'aProject')")) - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'FwkTarget' from project 'aProject')")) - - // There shouldn't be any diagnostics. - results.checkNoDiagnostics() - - // Check that none of the bitcode options are in the compile and link tasks' command lines. - results.checkTasks(.matchRuleType("CompileC")) { tasks in - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - task.checkCommandLineContains(["-fembed-bitcode"]) - } - } - results.checkTasks(.matchRuleType("Ld")) { tasks in - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - task.checkCommandLineContains(["-fembed-bitcode"]) - task.checkCommandLineContains(["-bitcode_verify", "-bitcode_hide_symbols", "-bitcode_symbol_map"]) - } - } - - // Check that the copying of the framework is NOT stripping bitcode (because we're building for full bitcode). - results.checkTask(.matchTargetName("AppTarget"), .matchRuleType("Copy"), .matchRuleItemBasename("FwkTarget.framework")) { task in - task.checkCommandLineDoesNotContain("-bitcode-strip") - task.checkCommandLineDoesNotContain("-bitcode-strip-tool") - task.checkCommandLineContainsUninterrupted(["\(SRCROOT)/build/Debug-iphoneos/FwkTarget.framework", "\(SRCROOT)/build/Debug-iphoneos/AppTarget.app/Frameworks"]) - } - // Check that the copying of the text file is NOT stripping bitcode (because this file is not code signed and so should never be stripped). - results.checkTask(.matchTargetName("AppTarget"), .matchRuleType("Copy"), .matchRuleItemBasename("Mock.txt")) { task in - task.checkCommandLineDoesNotContain("-bitcode-strip") - task.checkCommandLineDoesNotContain("-bitcode-strip-tool") - task.checkCommandLineContainsUninterrupted(["\(SRCROOT)/Mock.txt", "\(SRCROOT)/build/Debug-iphoneos/AppTarget.app"]) - } - } - } - - @Test(.requireSDKs(.iOS)) - func bitcodeSymbolsAreNotHiddenInMHObjectProducts() async throws { - let testProject = TestProject( - "aProject", - groupTree: TestGroup( - "SomeFiles", - children: [ - TestFile("AppSource.m"), - TestFile("LibSource.m"), - TestFile("Info.plist"), - ]), - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "CODE_SIGN_IDENTITY": "-", - "AD_HOC_CODE_SIGNING_ALLOWED": "YES", - // Using the public iOS SDK defaults both ENABLE_BITCODE and STRIP_BITCODE_FROM_COPIED_FILES to YES. - "SDKROOT": "iphoneos", - "ENABLE_BITCODE": "YES", - "BITCODE_GENERATION_MODE": "bitcode", - ]), - ], - targets: [ - TestStandardTarget( - "App", - type: .application, - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "INFOPLIST_FILE": "Info.plist", - "PRODUCT_NAME": "App", - ]), - ], - buildPhases: [ - TestSourcesBuildPhase([ - "AppSource.m", - ]), - TestFrameworksBuildPhase([ - "Lib.o" - ]), - ], - dependencies: ["Lib"] - ), - TestStandardTarget( - "Lib", - type: .objectFile, - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "PRODUCT_NAME": "Lib", - ]), - ], - buildPhases: [ - TestSourcesBuildPhase([ - "LibSource.m", - ]), - TestFrameworksBuildPhase([]), - ] - ), - ] - ) - - let tester = try await TaskConstructionTester(getCore(), testProject) - - await tester.checkBuild(runDestination: .iOS) { results in - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'App' from project 'aProject')")) - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'Lib' from project 'aProject')")) - - // There shouldn't be any diagnostics. - results.checkNoDiagnostics() - - // Check that none of the bitcode options are in the compile and link tasks' command lines. - results.checkTasks(.matchRuleType("CompileC")) { tasks in - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - task.checkCommandLineContains(["-fembed-bitcode"]) - } - } - results.checkTasks(.matchTargetName("Lib"), .matchRuleType("Ld")) { tasks in - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - task.checkCommandLineContains(["-fembed-bitcode"]) - task.checkCommandLineContains(["-bitcode_verify"]) - task.checkCommandLineDoesNotContain("-bitcode_hide_symbols") - task.checkCommandLineDoesNotContain("-bitcode_symbol_map") - } - } - results.checkTasks(.matchTargetName("App"), .matchRuleType("Ld")) { tasks in - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - task.checkCommandLineContains(["-fembed-bitcode"]) - task.checkCommandLineContains(["-bitcode_verify"]) - task.checkCommandLineContains(["-bitcode_hide_symbols"]) - task.checkCommandLineContains(["-bitcode_symbol_map"]) - } - } - } - } - - func _testBitcodeFlags(sdkroot: String, expectBitcode: Bool) async throws { - let testProject = try await TestProject( - "aProject", - groupTree: TestGroup( - "SomeFiles", - children: [ - TestFile("FwkSource.m"), - TestFile("FwkSource.swift"), - ]), - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "CODE_SIGNING_ALLOWED": "NO", - "GENERATE_INFOPLIST_FILE": "YES", - "PRODUCT_NAME": "$(TARGET_NAME)", - "SDKROOT": sdkroot, - "SWIFT_EXEC": swiftCompilerPath.str, - "SWIFT_VERSION": swiftVersion, - "EXCLUDED_SOURCE_FILE_NAMES[sdk=driverkit*]": "*.swift", - ]), - ], - targets: [ - TestStandardTarget( - "FwkTarget", - type: .framework, - buildPhases: [ - TestSourcesBuildPhase([ - "FwkSource.m", - "FwkSource.swift", - ]), - ] - ), - ] - ) - let tester = try await TaskConstructionTester(getCore(), testProject) - - // Test building with the bitcode marker. - await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["ENABLE_BITCODE": "YES", "BITCODE_GENERATION_MODE": "marker"]), runDestination: nil) { results in - if expectBitcode { - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'FwkTarget' from project 'aProject')")) - } - - results.checkNoDiagnostics() - - results.checkTasks(.matchRuleType("SwiftDriver Compilation")) { tasks in - if sdkroot != "driverkit" { - #expect(tasks.count > 0) - } - for task in tasks { - let arch = task.ruleInfo[safe: task.ruleInfo.count - 2] - if expectBitcode && arch != "i386" && arch != "x86_64" { - task.checkCommandLineContains(["-embed-bitcode-marker"]) - } else { - task.checkCommandLineDoesNotContain("-embed-bitcode-marker") - } - task.checkCommandLineDoesNotContain("-embed-bitcode") - } - } - results.checkTasks(.matchRuleType("CompileC")) { tasks in - #expect(tasks.count > 0) - for task in tasks { - let arch = task.ruleInfo[safe: 4] - if expectBitcode && arch != "i386" && arch != "x86_64" { - task.checkCommandLineContains(["-fembed-bitcode-marker"]) - } else { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - } - task.checkCommandLineDoesNotContain("-fembed-bitcode") - } - } - results.checkTasks(.matchRuleType("Ld")) { tasks in - #expect(tasks.count > 0) - for task in tasks { - if expectBitcode { - task.checkCommandLineContains(["-fembed-bitcode-marker"]) - } else { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - } - task.checkCommandLineDoesNotContain("-fembed-bitcode") - task.checkCommandLineDoesNotContain("-bitcode_verify") - task.checkCommandLineDoesNotContain("-bitcode_hide_symbols") - task.checkCommandLineDoesNotContain("-bitcode_symbol_map") - } - } - } - - // Test building with full bitcode. - await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["ENABLE_BITCODE": "YES", "BITCODE_GENERATION_MODE": "bitcode"]), runDestination: nil) { results in - if expectBitcode { - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'FwkTarget' from project 'aProject')")) - } - - results.checkNoDiagnostics() - - results.checkTasks(.matchRuleType("SwiftDriver Compilation")) { tasks in - if sdkroot != "driverkit" { - #expect(tasks.count > 0) - } - for task in tasks { - let arch = task.ruleInfo[safe: task.ruleInfo.count - 2] - if expectBitcode && arch != "i386" && arch != "x86_64" { - task.checkCommandLineContains(["-embed-bitcode"]) - } else { - task.checkCommandLineDoesNotContain("-embed-bitcode") - } - task.checkCommandLineDoesNotContain("-embed-bitcode-marker") - } - } - results.checkTasks(.matchRuleType("CompileC")) { tasks in - #expect(tasks.count > 0) - for task in tasks { - let arch = task.ruleInfo[safe: 4] - if expectBitcode && arch != "i386" && arch != "x86_64" { - task.checkCommandLineContains(["-fembed-bitcode"]) - } else { - task.checkCommandLineDoesNotContain("-fembed-bitcode") - } - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - } - } - results.checkTasks(.matchRuleType("Ld")) { tasks in - #expect(tasks.count > 0) - for task in tasks { - task.checkCommandLineDoesNotContain("-fembed-bitcode-marker") - if expectBitcode { - task.checkCommandLineContains(["-fembed-bitcode"]) - task.checkCommandLineContains(["-bitcode_verify", "-bitcode_hide_symbols", "-bitcode_symbol_map"]) - } else { - task.checkCommandLineDoesNotContain("-fembed-bitcode") - task.checkCommandLineDoesNotContain("-bitcode_verify") - task.checkCommandLineDoesNotContain("-bitcode_hide_symbols") - task.checkCommandLineDoesNotContain("-bitcode_symbol_map") - } - } - } - } - } - - @Test(.requireSDKs(.macOS)) - func bitcodeUnsupportedPlatformsIgnored_macOS() async throws { - try await _testBitcodeFlags(sdkroot: "macosx", expectBitcode: false) - } - - @Test(.requireSDKs(.driverKit)) - func bitcodeUnsupportedPlatformsIgnored_DriverKit() async throws { - try await _testBitcodeFlags(sdkroot: "driverkit", expectBitcode: false) - } - - @Test(.requireSDKs(.iOS)) - func bitcodeUnsupportedPlatformsIgnored_iOSSimulator() async throws { - try await _testBitcodeFlags(sdkroot: "iphonesimulator", expectBitcode: false) - } - - @Test(.requireSDKs(.tvOS)) - func bitcodeUnsupportedPlatformsIgnored_tvOSSimulator() async throws { - try await _testBitcodeFlags(sdkroot: "appletvsimulator", expectBitcode: false) - } - - @Test(.requireSDKs(.watchOS)) - func bitcodeUnsupportedPlatformsIgnored_watchOSSimulator() async throws { - try await _testBitcodeFlags(sdkroot: "watchsimulator", expectBitcode: false) - } - - @Test(.requireSDKs(.xrOS)) - func bitcodeUnsupportedPlatformsIgnored_visionOSSimulator() async throws { - try await _testBitcodeFlags(sdkroot: "xrsimulator", expectBitcode: false) - } - - @Test(.requireSDKs(.iOS)) - func bitcodeSupportedPlatforms_iOS() async throws { - try await _testBitcodeFlags(sdkroot: "iphoneos", expectBitcode: true) - } - - @Test(.requireSDKs(.tvOS)) - func bitcodeSupportedPlatforms_tvOS() async throws { - try await _testBitcodeFlags(sdkroot: "appletvos", expectBitcode: true) - } - - @Test(.requireSDKs(.watchOS)) - func bitcodeSupportedPlatforms_watchOS() async throws { - try await _testBitcodeFlags(sdkroot: "watchos", expectBitcode: true) - } - - @Test(.requireSDKs(.xrOS)) - func bitcodeSupportedPlatforms_visionOS() async throws { - try await _testBitcodeFlags(sdkroot: "xros", expectBitcode: false) // bitcode was never supported on visionOS - } -} diff --git a/Tests/SWBTaskConstructionTests/BuildActionTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/BuildActionTaskConstructionTests.swift index 1d130ec7..20913228 100644 --- a/Tests/SWBTaskConstructionTests/BuildActionTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/BuildActionTaskConstructionTests.swift @@ -15,6 +15,7 @@ import SWBUtil import SWBCore import SWBTestSupport +import SWBProtocol @Suite(.requireXcode16()) fileprivate struct BuildActionTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/ClangResponseFileTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/ClangResponseFileTaskConstructionTests.swift index a99d446c..08cdc80a 100644 --- a/Tests/SWBTaskConstructionTests/ClangResponseFileTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/ClangResponseFileTaskConstructionTests.swift @@ -58,7 +58,7 @@ fileprivate struct ClangResponseFileTaskConstructionTests: CoreBasedTests { let core = try await getCore() let tester = try TaskConstructionTester(core, testProject) try await tester.checkBuild(runDestination: .host) { results in - try results.checkWriteAuxiliaryFileTask(.matchRuleItemPattern(.suffix("7187679823f38a2a940e0043cdf9d637-common-args.resp"))) { task, contents in + try results.checkWriteAuxiliaryFileTask(.matchRuleItemPattern(.suffix("-common-args.resp"))) { task, contents in let responseFilePath = try #require(task.outputs.only) // The command arguments in the response file vary vastly between different platforms, so just check for some basics present in the content. @@ -165,7 +165,7 @@ fileprivate struct ClangResponseFileTaskConstructionTests: CoreBasedTests { let core = try await getCore() let tester = try TaskConstructionTester(core, testProject) await tester.checkBuild(runDestination: .host) { results in - results.checkWriteAuxiliaryFileTask(.matchRuleItemPattern(.suffix("7187679823f38a2a940e0043cdf9d637-common-args.resp"))) { task, contents in + results.checkWriteAuxiliaryFileTask(.matchRuleItemPattern(.suffix("-common-args.resp"))) { task, contents in let stringContents = contents.asString #expect(stringContents.contains("-target")) let blocksFlag = switch runDestination { @@ -348,7 +348,7 @@ fileprivate struct ClangResponseFileTaskConstructionTests: CoreBasedTests { let core = try await getCore() let tester = try TaskConstructionTester(core, testProject) await tester.checkBuild(runDestination: .host) { results in - results.checkWriteAuxiliaryFileTask(.matchRuleItemPattern(.suffix("7187679823f38a2a940e0043cdf9d637-common-args.resp"))) { task, contents in + results.checkWriteAuxiliaryFileTask(.matchRuleItemPattern(.suffix("-common-args.resp"))) { task, contents in let stringContents = contents.asString #expect(stringContents.contains("-Xclang -Wno-shorten-64-to-32")) results.checkTask(.matchRuleType("CompileC"), .matchRuleItemPattern(.suffix("a.c"))) { compileTask in diff --git a/Tests/SWBTaskConstructionTests/ClangTests.swift b/Tests/SWBTaskConstructionTests/ClangTests.swift index 06beb9ad..39cb40df 100644 --- a/Tests/SWBTaskConstructionTests/ClangTests.swift +++ b/Tests/SWBTaskConstructionTests/ClangTests.swift @@ -216,7 +216,7 @@ fileprivate struct ClangTests: CoreBasedTests { do { let fs = PseudoFS() try await fs.writeFileContents(Path(mockClangPath)) { $0 <<< "binary" } - try await fs.writeFileContents(core.developerPath.join(clangCachePath)) { $0 <<< "binary" } + try await fs.writeFileContents(core.developerPath.path.join(clangCachePath)) { $0 <<< "binary" } let tester = try TaskConstructionTester(core, getTestProject(["CC" : Path(mockClangPath).str])) await tester.checkBuild(runDestination: .host, fs: fs, clientDelegate: ClientDelegate(mockClangPath)) { results in @@ -241,7 +241,7 @@ fileprivate struct ClangTests: CoreBasedTests { do { let fs = PseudoFS() try await fs.writeFileContents(Path(mockClangPath)) { $0 <<< "binary" } - try await fs.writeFileContents(core.developerPath.join(clangCachePath)) { $0 <<< "binary" } + try await fs.writeFileContents(core.developerPath.path.join(clangCachePath)) { $0 <<< "binary" } let tester = try TaskConstructionTester(core, getTestProject([ "CC" : Path(mockClangPath).str, "CLANG_CACHE_FALLBACK_IF_UNAVAILABLE" : "YES", @@ -260,7 +260,7 @@ fileprivate struct ClangTests: CoreBasedTests { do { let fs = PseudoFS() try await fs.writeFileContents(clangCompilerPath) { $0 <<< "binary" } - try await fs.writeFileContents(core.developerPath.join(clangCachePath)) { $0 <<< "binary" } + try await fs.writeFileContents(core.developerPath.path.join(clangCachePath)) { $0 <<< "binary" } let tester = try TaskConstructionTester(core, getTestProject()) await tester.checkBuild(runDestination: .host, fs: fs) { results in diff --git a/Tests/SWBTaskConstructionTests/DebugInformationTests.swift b/Tests/SWBTaskConstructionTests/DebugInformationTests.swift index 1747a43b..6ae8abba 100644 --- a/Tests/SWBTaskConstructionTests/DebugInformationTests.swift +++ b/Tests/SWBTaskConstructionTests/DebugInformationTests.swift @@ -14,6 +14,8 @@ import Testing import SWBCore import SWBTestSupport +import SWBProtocol +import SWBUtil /// Tests of debug formats and dSYM generation. @Suite diff --git a/Tests/SWBTaskConstructionTests/DocumentationTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/DocumentationTaskConstructionTests.swift index a82d8360..cbd38481 100644 --- a/Tests/SWBTaskConstructionTests/DocumentationTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/DocumentationTaskConstructionTests.swift @@ -900,7 +900,7 @@ fileprivate struct DocumentationTaskConstructionTests: CoreBasedTests { "SYSTEM_FRAMEWORK_SEARCH_PATHS": "system_framework_search_paths1 system_framework_search_paths2", "HEADER_SEARCH_PATHS": "header_search_paths1 header_search_paths2", "SYSTEM_HEADER_SEARCH_PATHS": "system_header_search_paths1 system_header_search_paths2", - "TOOLCHAIN_DIR": core.developerPath.join("Toolchains/XcodeDefault.xctoolchain").str, + "TOOLCHAIN_DIR": core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain").str, "EXCLUDED_SOURCE_FILE_NAMES": "Excluded*", "DOCC_EXTRACT_SWIFT_INFO_FOR_OBJC_SYMBOLS": "NO", "TAPI_EXTRACT_API_ENABLE_MODULES": "YES", @@ -1426,7 +1426,7 @@ fileprivate struct DocumentationTaskConstructionTests: CoreBasedTests { task in task.checkCommandLine([ - core.developerPath.dirname.join("SharedFrameworks/CoreDocumentation.framework/Resources/sdkdb_to_symgraph").str, + core.developerPath.path.dirname.join("SharedFrameworks/CoreDocumentation.framework/Resources/sdkdb_to_symgraph").str, sdkdbOutputPath, "Framework", symbolGraphPath diff --git a/Tests/SWBTaskConstructionTests/DriverKitTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/DriverKitTaskConstructionTests.swift index a2887563..ee338491 100644 --- a/Tests/SWBTaskConstructionTests/DriverKitTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/DriverKitTaskConstructionTests.swift @@ -17,6 +17,7 @@ import SWBCore import SWBTaskConstruction import SWBTestSupport @_spi(Testing) import SWBUtil +import SWBProtocol @Suite fileprivate struct DriverKitTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/EagerCompilationTests.swift b/Tests/SWBTaskConstructionTests/EagerCompilationTests.swift index 77673f75..af9a6cc6 100644 --- a/Tests/SWBTaskConstructionTests/EagerCompilationTests.swift +++ b/Tests/SWBTaskConstructionTests/EagerCompilationTests.swift @@ -541,7 +541,7 @@ fileprivate struct EagerCompilationTests: CoreBasedTests { // Create files in the filesystem so they're known to exist. let fs = PseudoFS() for frameworkSubpath in unitTestFrameworkSubpaths { - let frameworkPath = core.developerPath.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) + let frameworkPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) try fs.createDirectory(frameworkPath.dirname, recursive: true) try fs.write(frameworkPath, contents: ByteString(encodingAsUTF8: frameworkPath.basename)) } diff --git a/Tests/SWBTaskConstructionTests/EagerLinkingTests.swift b/Tests/SWBTaskConstructionTests/EagerLinkingTests.swift index 4ffddfe7..ae159fe4 100644 --- a/Tests/SWBTaskConstructionTests/EagerLinkingTests.swift +++ b/Tests/SWBTaskConstructionTests/EagerLinkingTests.swift @@ -420,17 +420,6 @@ fileprivate struct EagerLinkingTests: CoreBasedTests { } } - // If archiving with full bitcode, don't emit a tbd. - await tester.checkBuild(BuildParameters(action: .archive, configuration: "Debug", overrides: ["ENABLE_BITCODE": "YES"]), runDestination: .macOS, targetName: "Fwk") { results in - results.checkTarget("Fwk") { target in - results.checkNoDiagnostics() - results.checkTask(.matchRuleType("SwiftDriver Compilation Requirements"), .matchTarget(target)) { task in - task.checkCommandLineDoesNotContain("-emit-tbd") - task.checkCommandLineDoesNotContain("-emit-tbd-path") - } - } - } - // An all-Swift app target should not emit a TBD, but the framework it links should. await tester.checkBuild(BuildParameters(action: .build, configuration: "Debug"), runDestination: .macOS, targetName: "App") { results in results.checkTarget("App") { target in diff --git a/Tests/SWBTaskConstructionTests/GenerateAppPlaygroundAssetCatalogTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/GenerateAppPlaygroundAssetCatalogTaskConstructionTests.swift index 0d661c37..10e657f9 100644 --- a/Tests/SWBTaskConstructionTests/GenerateAppPlaygroundAssetCatalogTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/GenerateAppPlaygroundAssetCatalogTaskConstructionTests.swift @@ -18,6 +18,7 @@ import SWBCore import SWBUtil import SWBTaskConstruction +import SWBProtocol @Suite fileprivate struct GenerateAppPlaygroundAssetCatalogTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/InAppPurchaseContentTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/InAppPurchaseContentTaskConstructionTests.swift index daf22e49..6b338d2a 100644 --- a/Tests/SWBTaskConstructionTests/InAppPurchaseContentTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/InAppPurchaseContentTaskConstructionTests.swift @@ -14,6 +14,7 @@ import Testing import SWBTaskConstruction import SWBTestSupport import SWBUtil +import SWBCore @Suite fileprivate struct InAppPurchaseContentTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift index e831750f..c5a7234f 100644 --- a/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/IndexBuildTaskConstructionTests.swift @@ -546,6 +546,10 @@ fileprivate struct IndexBuildTaskConstructionTests: CoreBasedTests { try results.checkTask(.matchTargetName("AppTarget"), .matchRuleItem("SwiftDriver Compilation Requirements")) { task in task.checkRuleInfo(["SwiftDriver Compilation Requirements", "AppTarget", "normal", "x86_64", "com.apple.xcode.tools.swift.compiler"]) + // Explicit modules are disabled for semantic functionality currently, make sure it is also disabled + // for preparation in general. + task.checkCommandLineDoesNotContain("-explicit-module-build") + let skipFlag = swiftFeatures.has(.experimentalSkipAllFunctionBodies) ? "-experimental-skip-all-function-bodies" : "-experimental-skip-non-inlinable-function-bodies" task.checkCommandLineContains(["-module-name", "AppTarget", "-Onone", "-Xfrontend", skipFlag, "-emit-dependencies", "-emit-module", "-emit-module-path", "-emit-objc-header", "-emit-objc-header-path"]) if swiftFeatures.has(.experimentalAllowModuleWithCompilerErrors) { @@ -793,8 +797,11 @@ fileprivate struct IndexBuildTaskConstructionTests: CoreBasedTests { results.checkNoTask(.matchCommandLineArgument("clang-stat-cache")) - try results.checkTask(.matchTargetName("AppTarget"), .matchRuleItem("CompileC")) { task in + // Explicit modules are disabled for semantic functionality currently, make sure it is also disabled + // for preparation in general. + results.checkNoTask(.matchRuleItem("ScanDependencies")) + try results.checkTask(.matchTargetName("AppTarget"), .matchRuleItem("CompileC")) { task in if clangFeatures.has(.allowPcmWithCompilerErrors) { task.checkCommandLineContains(["-Xclang", "-fallow-pcm-with-compiler-errors"]) } else { diff --git a/Tests/SWBTaskConstructionTests/InfoPlistTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/InfoPlistTaskConstructionTests.swift index d42ec873..2021613d 100644 --- a/Tests/SWBTaskConstructionTests/InfoPlistTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/InfoPlistTaskConstructionTests.swift @@ -17,6 +17,7 @@ import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol @Suite fileprivate struct InfoPlistTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/InstallLocTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/InstallLocTaskConstructionTests.swift index d70151b5..1ace97f1 100644 --- a/Tests/SWBTaskConstructionTests/InstallLocTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/InstallLocTaskConstructionTests.swift @@ -17,6 +17,7 @@ import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol @Suite fileprivate struct InstallLocTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/InstallTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/InstallTaskConstructionTests.swift index 9d55f8bd..c0a1113f 100644 --- a/Tests/SWBTaskConstructionTests/InstallTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/InstallTaskConstructionTests.swift @@ -15,6 +15,8 @@ import Testing import SWBCore import SWBTestSupport +import SWBUtil +import SWBProtocol /// Test interesting characteristics of install builds. @Suite diff --git a/Tests/SWBTaskConstructionTests/IntermediateStubTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/IntermediateStubTaskConstructionTests.swift index c6d6e103..d4010c7d 100644 --- a/Tests/SWBTaskConstructionTests/IntermediateStubTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/IntermediateStubTaskConstructionTests.swift @@ -16,6 +16,7 @@ import SWBCore import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol @Suite fileprivate struct IntermediateStubTaskConstructionTests: CoreBasedTests { @@ -127,41 +128,6 @@ fileprivate struct IntermediateStubTaskConstructionTests: CoreBasedTests { } } - @Test(.requireSDKs(.iOS), .userDefaults(["EnableBitcodeSupport": "1"])) - func targetWithFullBitcodeGeneratesNoStubs() async throws { - let testProject = try await TestProject( - "aProject", - groupTree: TestGroup( - "SomeFiles", path: "Sources", - children: [ - TestFile("Fwk.swift"), - ]), - buildConfigurations: [ - TestBuildConfiguration("Debug", buildSettings: [ - "CODE_SIGN_IDENTITY": "", - "PRODUCT_NAME": "$(TARGET_NAME)", - "SDKROOT": "iphoneos", - "SWIFT_EXEC": swiftCompilerPath.str, - "SWIFT_VERSION": swiftVersion, - "TAPI_EXEC": tapiToolPath.str, - "ENABLE_BITCODE": "YES", - "BITCODE_GENERATION_MODE": "bitcode" - ])], - targets: [ - TestStandardTarget( - "Fwk", - type: .framework, - buildPhases: [ - TestSourcesBuildPhase(["Fwk.swift"]) - ]), - ]) - let tester = try await TaskConstructionTester(getCore(), testProject) - await tester.checkBuild(BuildParameters(action: .build, configuration: "Debug"), runDestination: .iOS) { results in - results.checkNoTask(.matchRuleType("GenerateTAPI")) - results.checkWarning(.contains("Building with bitcode is deprecated")) - } - } - @Test(.requireSDKs(.macOS)) func targetInstallingStubsGeneratesNoIntermediateStubs() async throws { let testProject = try await TestProject( diff --git a/Tests/SWBTaskConstructionTests/KernelExtensionTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/KernelExtensionTaskConstructionTests.swift index 40d6da97..806c0084 100644 --- a/Tests/SWBTaskConstructionTests/KernelExtensionTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/KernelExtensionTaskConstructionTests.swift @@ -14,6 +14,8 @@ import Testing import SWBCore import SWBTaskConstruction import SWBTestSupport +import SWBUtil +import SWBProtocol @Suite fileprivate struct KernelExtensionTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/LibtoolTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/LibtoolTaskConstructionTests.swift index adbad16e..e2fb0236 100644 --- a/Tests/SWBTaskConstructionTests/LibtoolTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/LibtoolTaskConstructionTests.swift @@ -15,6 +15,7 @@ import Testing import SWBCore import SWBTaskConstruction import SWBTestSupport +import SWBUtil @Suite fileprivate struct LibtoolTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/MasterObjectFileTests.swift b/Tests/SWBTaskConstructionTests/MasterObjectFileTests.swift index 6bfa7e47..dea36b88 100644 --- a/Tests/SWBTaskConstructionTests/MasterObjectFileTests.swift +++ b/Tests/SWBTaskConstructionTests/MasterObjectFileTests.swift @@ -15,6 +15,7 @@ import SWBCore import SWBTestSupport import SWBTaskConstruction import SWBUtil +import SWBProtocol @Suite fileprivate struct MasterObjectFileTests: CoreBasedTests { @@ -165,7 +166,6 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { TestBuildConfiguration( "Debug", buildSettings: [ - "ENABLE_BITCODE": "YES", "PRODUCT_NAME": "$(TARGET_NAME)", "IPHONEOS_DEPLOYMENT_TARGET": core.loadSDK(.iOS).defaultDeploymentTarget, "SDKROOT": "iphoneos", @@ -206,7 +206,7 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { 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")]) } 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.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", "-L\(core.developerPath.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")]) + 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")]) } } @@ -235,7 +235,6 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { TestBuildConfiguration( "Debug", buildSettings: [ - "ENABLE_BITCODE": "YES", "PRODUCT_NAME": "$(TARGET_NAME)", "IPHONEOS_DEPLOYMENT_TARGET": core.loadSDK(.iOS).defaultDeploymentTarget, "SDKROOT": "iphoneos", @@ -273,12 +272,7 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { 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 - if UserDefaults.enableBitcodeSupport { - task.checkCommandLineMatches([.suffix("ld"), "-r", "-arch", "arm64", "-bitcode_bundle", "-syslibroot", .equal(results.runDestinationSDK.path.str), "-o", .equal("\(SRCROOT)/build/aProject.build/Debug-iphoneos/AllLibraries.build/Objects-normal/libAllLibraries.a-arm64-master.o")]) - } - else { - 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")]) - } + 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")]) } 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")]) @@ -288,13 +282,6 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { // There should be no other tasks. results.checkNoTask() - if UserDefaults.enableBitcodeSupport { - results.checkWarning(.equal("Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode. (in target 'AllLibraries' from project 'aProject')")) - } - else { - results.checkWarning(.equal("Ignoring ENABLE_BITCODE because building with bitcode is no longer supported. (in target \'AllLibraries\' from project \'aProject\')")) - } - // There shouldn't be any diagnostics. results.checkNoDiagnostics() @@ -316,7 +303,6 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { TestBuildConfiguration( "Debug", buildSettings: [ - "ENABLE_BITCODE": "YES", "PRODUCT_NAME": "$(TARGET_NAME)", "IPHONEOS_DEPLOYMENT_TARGET": core.loadSDK(.iOS).defaultDeploymentTarget, "SDKROOT": "iphonesimulator", @@ -354,7 +340,6 @@ fileprivate struct MasterObjectFileTests: CoreBasedTests { 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 - // -bitcode_bundle shouldn't be passed here since Intel architectures do not support it 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")]) } results.checkTask(.matchTarget(target), .matchRuleType("Libtool")) { task in diff --git a/Tests/SWBTaskConstructionTests/MultiPlatformTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/MultiPlatformTaskConstructionTests.swift index d855cffa..2d59a358 100644 --- a/Tests/SWBTaskConstructionTests/MultiPlatformTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/MultiPlatformTaskConstructionTests.swift @@ -369,9 +369,9 @@ fileprivate struct MultiPlatformTaskConstructionTests: CoreBasedTests { ] ) - try fs.createDirectory(core.developerPath.join("usr/bin"), recursive: true) - try await fs.writeFileContents(core.developerPath.join("usr/bin/actool")) { $0 <<< "binary" } - try await fs.writeFileContents(core.developerPath.join("usr/bin/ibtool")) { $0 <<< "binary" } + try fs.createDirectory(core.developerPath.path.join("usr/bin"), recursive: true) + try await fs.writeFileContents(core.developerPath.path.join("usr/bin/actool")) { $0 <<< "binary" } + try await fs.writeFileContents(core.developerPath.path.join("usr/bin/ibtool")) { $0 <<< "binary" } // Create files in the filesystem so they're known to exist. try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } diff --git a/Tests/SWBTaskConstructionTests/ObjectiveCSymbolExtractorTests.swift b/Tests/SWBTaskConstructionTests/ObjectiveCSymbolExtractorTests.swift index 84678cc1..0222dd1a 100644 --- a/Tests/SWBTaskConstructionTests/ObjectiveCSymbolExtractorTests.swift +++ b/Tests/SWBTaskConstructionTests/ObjectiveCSymbolExtractorTests.swift @@ -17,6 +17,7 @@ import SWBTestSupport import SWBCore @_spi(Testing) import SWBTaskConstruction +import SWBProtocol @Suite fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { @@ -61,7 +62,7 @@ fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { buildPhases.insert(TestHeadersBuildPhase(headerBuildPhaseFiles), at: 0) } - let toolchainPath = core.developerPath.join("Toolchains/XcodeDefault.xctoolchain") + let toolchainPath = core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain") let testProject = try await TestProject( "aProject", groupTree: TestGroup( @@ -241,7 +242,7 @@ fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { "PRODUCT_NAME": "$(TARGET_NAME)", "PRODUCT_BUNDLE_IDENTIFIER": "test.bundle.identifier", "CURRENT_PROJECT_VERSION": "0.0.1", - "TOOLCHAIN_DIR": core.developerPath.join("Toolchains/XcodeDefault.xctoolchain").str, + "TOOLCHAIN_DIR": core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain").str, ].merging(extraBuildSettings, uniquingKeysWith: { _, new in new }).compactMapValues({ $0 }) ) ], @@ -374,7 +375,7 @@ fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { "PRODUCT_NAME": "$(TARGET_NAME)", "PRODUCT_BUNDLE_IDENTIFIER": "test.bundle.identifier", "CURRENT_PROJECT_VERSION": "0.0.1", - "TOOLCHAIN_DIR": core.developerPath.join("Toolchains/XcodeDefault.xctoolchain").str, + "TOOLCHAIN_DIR": core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain").str, ] ) ], @@ -406,7 +407,7 @@ fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { "PRODUCT_NAME": "$(TARGET_NAME)", "PRODUCT_BUNDLE_IDENTIFIER": "test.bundle.identifier", "CURRENT_PROJECT_VERSION": "0.0.1", - "TOOLCHAIN_DIR": core.developerPath.join("Toolchains/XcodeDefault.xctoolchain").str, + "TOOLCHAIN_DIR": core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain").str, ] ) ], @@ -621,7 +622,7 @@ fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { "PRODUCT_NAME": "$(TARGET_NAME)", "PRODUCT_BUNDLE_IDENTIFIER": "test.bundle.sub-dependency", "CURRENT_PROJECT_VERSION": "0.0.1", - "TOOLCHAIN_DIR": core.developerPath.join("Toolchains/XcodeDefault.xctoolchain").str, + "TOOLCHAIN_DIR": core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain").str, ] ) ], @@ -651,7 +652,7 @@ fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { "PRODUCT_NAME": "$(TARGET_NAME)", "PRODUCT_BUNDLE_IDENTIFIER": "test.bundle.dependency", "CURRENT_PROJECT_VERSION": "0.0.1", - "TOOLCHAIN_DIR": core.developerPath.join("Toolchains/XcodeDefault.xctoolchain").str, + "TOOLCHAIN_DIR": core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain").str, ] ) ], @@ -680,7 +681,7 @@ fileprivate struct ObjectiveCSymbolExtractorTests: CoreBasedTests { "PRODUCT_NAME": "$(TARGET_NAME)", "PRODUCT_BUNDLE_IDENTIFIER": "test.bundle.app", "CURRENT_PROJECT_VERSION": "0.0.1", - "TOOLCHAIN_DIR": core.developerPath.join("Toolchains/XcodeDefault.xctoolchain").str, + "TOOLCHAIN_DIR": core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain").str, // Set the real swift compiler path so we can determine the location of compatibility headers ignores file "SWIFT_EXEC": swiftCompilerPath.str, // Set the real clang tool path so that we can check it's features.json file diff --git a/Tests/SWBTaskConstructionTests/OnDemandResourcesTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/OnDemandResourcesTaskConstructionTests.swift index f23f9fed..5695b3e5 100644 --- a/Tests/SWBTaskConstructionTests/OnDemandResourcesTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/OnDemandResourcesTaskConstructionTests.swift @@ -17,6 +17,7 @@ import SWBProtocol import SWBTaskConstruction import SWBTestSupport import SWBUtil +import SWBCore @Suite fileprivate struct OnDemandResourcesTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/PlatformTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/PlatformTaskConstructionTests.swift index 7efb815c..f2e561d3 100644 --- a/Tests/SWBTaskConstructionTests/PlatformTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/PlatformTaskConstructionTests.swift @@ -20,6 +20,7 @@ import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBMacro @Suite fileprivate struct PlatformTaskConstructionTests: CoreBasedTests { @@ -542,9 +543,9 @@ fileprivate struct PlatformTaskConstructionTests: CoreBasedTests { // Create files in the filesystem so they're known to exist. let fs = PseudoFS() - try fs.createDirectory(core.developerPath.join("usr/bin"), recursive: true) - try await fs.writeFileContents(core.developerPath.join("usr/bin/actool")) { $0 <<< "binary" } - try await fs.writeFileContents(core.developerPath.join("usr/bin/ibtool")) { $0 <<< "binary" } + try fs.createDirectory(core.developerPath.path.join("usr/bin"), recursive: true) + try await fs.writeFileContents(core.developerPath.path.join("usr/bin/actool")) { $0 <<< "binary" } + try await fs.writeFileContents(core.developerPath.path.join("usr/bin/ibtool")) { $0 <<< "binary" } try fs.createDirectory(Path("/Users/whoever/Library/MobileDevice/Provisioning Profiles"), recursive: true) try fs.write(Path("/Users/whoever/Library/MobileDevice/Provisioning Profiles/8db0e92c-592c-4f06-bfed-9d945841b78d.mobileprovision"), contents: "profile") @@ -599,7 +600,7 @@ fileprivate struct PlatformTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRule(["CopyAndPreserveArchs", "/tmp/Test/aProject/build/Debug-iphoneos/StickerTarget.appex/StickerTarget"])) { task in task.checkCommandLineMatches([ "lipo", - "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Library/Application Support/MessagesApplicationExtensionStub/MessagesApplicationExtensionStub", + "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Library/Application Support/MessagesApplicationExtensionStub/MessagesApplicationExtensionStub", "-output", "/tmp/Test/aProject/build/Debug-iphoneos/StickerTarget.appex/StickerTarget", "-extract", @@ -744,7 +745,7 @@ fileprivate struct PlatformTaskConstructionTests: CoreBasedTests { "-target", "\(arch)-apple-ios\(IPHONEOS_DEPLOYMENT_TARGET)-macabi", "-isysroot", core.loadSDK(.macOS).path.str, "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", - "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", + "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks", "-o", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/\(arch)/Binary/AppTarget", ] @@ -923,7 +924,7 @@ fileprivate struct PlatformTaskConstructionTests: CoreBasedTests { "-isysroot", core.loadSDK(.macOS).path.str, "-L/usr/local/lib", "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", - "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", + "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-iframework", "/Library/Frameworks", "-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks", "-o", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/MacOS/AppTarget", diff --git a/Tests/SWBTaskConstructionTests/PostprocessingTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/PostprocessingTaskConstructionTests.swift index 11221dbb..85fd06e1 100644 --- a/Tests/SWBTaskConstructionTests/PostprocessingTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/PostprocessingTaskConstructionTests.swift @@ -17,6 +17,7 @@ import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol @Suite fileprivate struct PostprocessingTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/ResourceTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/ResourceTaskConstructionTests.swift index a7b97818..2dac3859 100644 --- a/Tests/SWBTaskConstructionTests/ResourceTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/ResourceTaskConstructionTests.swift @@ -17,6 +17,7 @@ import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol /// Task construction tests related to resource processing. @Suite @@ -64,7 +65,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { let SRCROOT = tester.workspace.projects[0].sourceRoot.str let fs = PseudoFS() - let rezPath = core.developerPath.join("usr/bin/Rez") + let rezPath = core.developerPath.path.join("usr/bin/Rez") try fs.createDirectory(rezPath.dirname, recursive: true) try await fs.writeFileContents(rezPath) { _ in } @@ -568,7 +569,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { .path("\(SRCROOT)/build/aProject.build/Debug/App.build/foo-PartialInfo.plist"),]) task.checkEnvironment([ - "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.str)/usr/bin/.."), + "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.path.str)/usr/bin/.."), ], exact: true) } @@ -709,7 +710,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { .path("\(SRCROOT)/build/aProject.build/Debug/App.build/foo-PartialInfo.plist"),]) task.checkEnvironment([ - "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.str)/usr/bin/.."), + "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.path.str)/usr/bin/.."), ], exact: true) } @@ -850,7 +851,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { .path("\(SRCROOT)/build/aProject.build/Debug/App.build/Base.lproj/foo-PartialInfo.plist"),]) task.checkEnvironment([ - "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.str)/usr/bin/.."), + "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.path.str)/usr/bin/.."), ], exact: true) } @@ -1010,7 +1011,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { ]) task.checkEnvironment([ - "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.str)/usr/bin/.."), + "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.path.str)/usr/bin/.."), ], exact: true) } @@ -1033,7 +1034,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { ]) task.checkEnvironment([ - "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.str)/usr/bin/.."), + "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.path.str)/usr/bin/.."), ], exact: true) } @@ -1074,7 +1075,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { ]) task.checkEnvironment([ - "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.str)/usr/bin/.."), + "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.path.str)/usr/bin/.."), ], exact: true) } @@ -1229,7 +1230,7 @@ fileprivate struct ResourcesTaskConstructionTests: CoreBasedTests { .path("\(SRCROOT)/build/aProject.build/Debug/App.build/\(region).lproj/foo-PartialInfo.plist"),]) task.checkEnvironment([ - "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.str)/usr/bin/.."), + "XCODE_DEVELOPER_USR_PATH": .equal("\(core.developerPath.path.str)/usr/bin/.."), ], exact: true) } } diff --git a/Tests/SWBTaskConstructionTests/ShellScriptTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/ShellScriptTaskConstructionTests.swift index 38060e64..ed758671 100644 --- a/Tests/SWBTaskConstructionTests/ShellScriptTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/ShellScriptTaskConstructionTests.swift @@ -14,6 +14,7 @@ import Testing import SWBTaskConstruction import SWBTestSupport import SWBUtil +import SWBCore @Suite fileprivate struct ShellScriptTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/SwiftABICheckerTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/SwiftABICheckerTaskConstructionTests.swift index fa6a1e04..75c6b9c7 100644 --- a/Tests/SWBTaskConstructionTests/SwiftABICheckerTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/SwiftABICheckerTaskConstructionTests.swift @@ -17,6 +17,7 @@ import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol @Suite fileprivate struct SwiftABICheckerTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/SwiftModuleOnlyTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/SwiftModuleOnlyTaskConstructionTests.swift index d50a67c2..91a026e0 100644 --- a/Tests/SWBTaskConstructionTests/SwiftModuleOnlyTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/SwiftModuleOnlyTaskConstructionTests.swift @@ -701,7 +701,6 @@ fileprivate struct SwiftModuleOnlyTaskConstructionTests: CoreBasedTests { } #expect(fileDict["object"] == nil) - #expect(fileDict["llvm-bc"] == nil) #expect(fileDict.count == 4) #expect(fileDict["diagnostics"]?.stringValue == archBuildDir.join("\(basename)\(platformSuffix).dia").str) diff --git a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift index cdc34ef7..997e5fec 100644 --- a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift @@ -18,6 +18,7 @@ import SWBTestSupport @_spi(Testing) import SWBUtil import SWBTaskConstruction +import Foundation /// Task construction tests related to Swift compilation. @Suite @@ -173,7 +174,7 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { // Create a fake codesign_allocate tool so it can be found in the executable search paths. let fs = PseudoFS() try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } - try await fs.writeFileContents(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate")) { $0 <<< "binary" } + try await fs.writeFileContents(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate")) { $0 <<< "binary" } // NOTE: The toolchain cannot be set normally and must be passed in as an override. var overrides = ["TOOLCHAINS": toolchainIdentifier] @@ -325,11 +326,10 @@ 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 == 8) + #expect(fileDict.count == 7) } else { #expect(fileDict.count == 6) } @@ -379,7 +379,7 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { task.checkCommandLine(([ ["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-isysroot", core.loadSDK(.macOS).path.str, "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList"], shouldEmitSwiftRPath ? ["-Xlinker", "-rpath", "-Xlinker", "/usr/lib/swift"] : [], - ["-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/\(toolchain).xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-framework", "FwkTarget", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget"] + ["-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/\(toolchain).xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-framework", "FwkTarget", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget"] ] as [[String]]).reduce([], +)) task.checkInputs([ @@ -397,9 +397,6 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { .namePattern(.prefix("Linked Binary \(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget")), .path("\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat"), ]) - - // We used to pass the deployment target to the linker in the environment, but this is supposedly no longer necessary. - task.checkEnvironment([:], exact: true) } // There should be a task to embed the Swift standard libraries. @@ -418,8 +415,8 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { .name("CopySwiftStdlib \(SRCROOT)/build/Debug/AppTarget.app"),]) task.checkEnvironment([ - "CODESIGN_ALLOCATE": .equal(core.developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate").str), - "DEVELOPER_DIR": .equal(core.developerPath.str), + "CODESIGN_ALLOCATE": .equal(core.developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate").str), + "DEVELOPER_DIR": .equal(core.developerPath.path.str), "SDKROOT": .equal(core.loadSDK(.macOS).path.str), // This is coming from our overrides in unit test infrastructure. "TOOLCHAINS": .equal(toolchainIdentifier), @@ -1266,11 +1263,9 @@ 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 @@ -1280,11 +1275,9 @@ 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]) } @@ -2874,7 +2867,7 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { await tester.checkBuild(BuildParameters(action: .build, configuration: "Debug"), runDestination: .macOS) { results in results.checkTask(.matchRuleType("Ld")) { task in - task.checkCommandLine(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget"]) + task.checkCommandLine(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget"]) } results.checkNoDiagnostics() } @@ -2887,11 +2880,11 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { results.checkTask(.matchRuleType("Ld")) { task in let containsSubFrameworksPath = task.commandLineAsStrings.contains("\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/SubFrameworks") let expectedCommandLine: [String] = [ - ["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-ios\(catalystVersion.description)-macabi", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-L\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-F\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks"], + ["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-ios\(catalystVersion.description)-macabi", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-L\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-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", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-F\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks"], (containsSubFrameworksPath ? ["-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/SubFrameworks"] : []), ["-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks"], (containsSubFrameworksPath ? ["-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/SubFrameworks"] : []), - ["-filelist", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/System/iOSSupport/usr/lib/swift", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/MacOS/AppTarget"], + ["-filelist", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/System/iOSSupport/usr/lib/swift", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/MacOS/AppTarget"], ].reduce([], +) task.checkCommandLine(expectedCommandLine) } @@ -2900,7 +2893,7 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { await tester.checkBuild(BuildParameters(action: .build, configuration: "Debug", overrides: ["IS_ZIPPERED": "YES"]), runDestination: .macOS) { results in results.checkTask(.matchRuleType("Ld")) { task in - task.checkCommandLine(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget"]) + task.checkCommandLine(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget"]) } results.checkNoDiagnostics() } @@ -2909,11 +2902,11 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { results.checkTask(.matchRuleType("Ld")) { task in let containsSubFrameworksPath = task.commandLineAsStrings.contains("\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/SubFrameworks") let expectedCommandLine: [String] = [ - ["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-ios\(catalystVersion.description)-macabi", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-L\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-L\(core.loadSDK(.macOS).path.str)/System/iOSSupport/usr/lib", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/maccatalyst", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-F\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks"], + ["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-ios\(catalystVersion.description)-macabi", "-isysroot", "\(core.loadSDK(.macOS).path.str)", "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-L\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-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", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug-maccatalyst", "-F\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)", "-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks"], (containsSubFrameworksPath ? ["-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/SubFrameworks"] : []), ["-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/Frameworks"], (containsSubFrameworksPath ? ["-iframework", "\(core.loadSDK(.macOS).path.str)/System/iOSSupport/System/Library/SubFrameworks"] : []), - ["-filelist", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/MacOS/AppTarget"], + ["-filelist", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.build/Objects-normal/x86_64/AppTarget.swiftmodule", "@\(SRCROOT)/build/aProject.build/Debug-maccatalyst/AppTarget.build/Objects-normal/x86_64/AppTarget-linker-args.resp", "-o", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/MacOS/AppTarget"], ].reduce([], +) task.checkCommandLine(expectedCommandLine) } diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index 2deea788..4511d270 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -21,6 +21,8 @@ import SWBUtil import SWBTaskConstruction +import class SWBMacro.StringMacroDeclaration + @Suite fileprivate struct TaskConstructionTests: CoreBasedTests { @Test(.requireSDKs(.macOS)) @@ -518,9 +520,6 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { .path("\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_lto.o"), .path("\(SRCROOT)/build/aProject.build/Debug/AppTarget.build/Objects-normal/x86_64/AppTarget_dependency_info.dat"), ]) - - // We used to pass the deployment target to the linker in the environment, but this is supposedly no longer necessary. - task.checkEnvironment([:], exact: true) } // There should be two CpHeader tasks. @@ -659,7 +658,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { "SCRIPT_INPUT_FILE_1": .equal(""), "SCRIPT_INPUT_FILE_COUNT": .equal("2"), "SCRIPT_OUTPUT_FILE_COUNT": .equal("0"), - "TOOLCHAIN_DIR": .equal("\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain"), + "TOOLCHAIN_DIR": .equal("\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain"), ] // Validate that MACOSX_DEPLOYMENT_TARGET is present in the environment, but deployment targets for other platforms are not. scriptVariables["MACOSX_DEPLOYMENT_TARGET"] = StringPattern.equal(MACOSX_DEPLOYMENT_TARGET) @@ -1340,9 +1339,6 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { ["-dynamiclib", "-isysroot", core.loadSDK(.macOS).path.str, "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/FrameworkTarget.build/Objects-normal/x86_64/FrameworkTarget.LinkFileList", "-install_name", "/Library/Frameworks/FrameworkTarget.framework/Versions/A/FrameworkTarget"], ["-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/FrameworkTarget.build/Objects-normal/x86_64/FrameworkTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/FrameworkTarget.build/Objects-normal/x86_64/FrameworkTarget_dependency_info.dat", "-fobjc-link-runtime", "-lstatic", "-ldynamic", "-Xlinker", "-no_adhoc_codesign", "-o", "\(SRCROOT)/build/Debug/FrameworkTarget.framework/Versions/A/FrameworkTarget"] ].reduce([], +)) - - // We used to pass the deployment target to the linker in the environment, but this is supposedly no longer necessary. - task.checkEnvironment([:], exact: true) } // There should be three CpHeader tasks. @@ -1485,9 +1481,6 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { .path("\(SRCROOT)/build/aProject.build/Release/FrameworkTarget.build/Objects-normal/x86_64/FrameworkTarget_lto.o"), .path("\(SRCROOT)/build/aProject.build/Release/FrameworkTarget.build/Objects-normal/x86_64/FrameworkTarget_dependency_info.dat"), ]) - - // We used to pass the deployment target to the linker in the environment, but this is supposedly no longer necessary. - task.checkEnvironment([:], exact: true) } results.checkTask(.matchTarget(target), .matchRuleType("GenerateTAPI")) { task in @@ -2339,21 +2332,21 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { switch runDestination.platform { case "macosx": platformSearchPaths = [ - developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/bin"), - developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/local/bin"), - developerPath.join("Toolchains/XcodeDefault.xctoolchain/usr/libexec"), - developerPath.join("Platforms/MacOSX.platform/usr/bin"), - developerPath.join("Platforms/MacOSX.platform/usr/local/bin"), - developerPath.join("Platforms/MacOSX.platform/Developer/usr/bin"), - developerPath.join("Platforms/MacOSX.platform/Developer/usr/local/bin"), + developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/bin"), + developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/local/bin"), + developerPath.path.join("Toolchains/XcodeDefault.xctoolchain/usr/libexec"), + developerPath.path.join("Platforms/MacOSX.platform/usr/bin"), + developerPath.path.join("Platforms/MacOSX.platform/usr/local/bin"), + developerPath.path.join("Platforms/MacOSX.platform/Developer/usr/bin"), + developerPath.path.join("Platforms/MacOSX.platform/Developer/usr/local/bin"), ] default: platformSearchPaths = [] } for path in searchPaths + platformSearchPaths.map(\.str) + [ - developerPath.join("usr/bin").str, - developerPath.join("usr/local/bin").str, + developerPath.path.join("usr/bin").str, + developerPath.path.join("usr/local/bin").str, "/usr/local/bin" ] { #expect(task.environment.bindingsDictionary["PATH"]?.contains(path) == true, "PATH environment variable did not contain entry: \(path)") @@ -4052,7 +4045,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } } // Note that system framework search paths are presently not deduplicated for the linker args. - #expect(searchPaths == ["-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L/Local/Library/Libs", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-F/Local/Library/Frameworks", "-F/Local/Library/Frameworks", "-iframework", "/System/Library/PrivateFrameworks", "-iframework", "/Local/Library/Frameworks", "-iframework", "/Local/Library/Frameworks", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift"]) + #expect(searchPaths == ["-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L/Local/Library/Libs", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-F/Local/Library/Frameworks", "-F/Local/Library/Frameworks", "-iframework", "/System/Library/PrivateFrameworks", "-iframework", "/Local/Library/Frameworks", "-iframework", "/Local/Library/Frameworks", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift"]) // FIXME: [Swift Build] Extra "//" in framework search path for Ld command } } @@ -4110,7 +4103,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { try fs.write(Path(SRCROOT).join("Info.plist"), contents: "") - let clangTool = try await discoveredClangToolInfo(toolPath: Path("\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"), arch: RunDestinationInfo.macOS.targetArchitecture, sysroot: nil) + let clangTool = try await discoveredClangToolInfo(toolPath: Path("\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"), arch: RunDestinationInfo.macOS.targetArchitecture, sysroot: nil) guard let clangLibDarwinPath = clangTool.getLibDarwinPath() else { Issue.record("Could not get lib darwin path") return @@ -4122,12 +4115,12 @@ 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.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-fsanitize=address", "-fsanitize-stable-abi", "\(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", "-fsanitize-stable-abi", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/SourceFile.o"]) } //There should be no task to copy dylib. While testing for -fsanitize-stable-abi is a temporary test. This test should remain. results.checkNoTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename("libclang_rt.asan_osx_dynamic.dylib")) results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-sanitize=address", "-sanitize-stable-abi", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/\(targetName)-OutputFileMap.json"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-sanitize=address", "-sanitize-stable-abi", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/\(targetName)-OutputFileMap.json"]) } results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkCommandLineContains( @@ -4142,18 +4135,18 @@ 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.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", "\(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. results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-sanitize=address", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/\(targetName)-OutputFileMap.json"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-sanitize=address", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-asan/x86_64/\(targetName)-OutputFileMap.json"]) } // There should be one Ld task. results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkRuleInfo([.equal("Ld"), .equal("\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"), .any]) - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"]) } // There should be one task to copy the Asan library into the product. @@ -4276,18 +4269,18 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { // There should be one CompileC task, which includes the TSan option, and which puts its output in a -tsan directory. results.checkTask(.matchTarget(target), .matchRuleType("CompileC")) { task in task.checkRuleInfo([.equal("CompileC"), .equal("\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-tsan/x86_64/SourceFile.o"), .suffix("SourceFile.m"), .any, .any, .any, .any]) - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-fsanitize=thread", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-tsan/x86_64/SourceFile.o"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-fsanitize=thread", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-tsan/x86_64/SourceFile.o"]) } // There should be one CompileSwiftSources task, which includes the TSan option, and which puts its output in a -tsan directory. results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-sanitize=thread", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-tsan/x86_64/\(targetName)-OutputFileMap.json"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "-sanitize=thread", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-tsan/x86_64/\(targetName)-OutputFileMap.json"]) } // There should be one Ld task. results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkRuleInfo([.equal("Ld"), .equal("\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"), .any]) - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"]) } // There should be one task to copy the TSan library into the product. @@ -4331,18 +4324,18 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { // There should be one CompileC task, which includes the UBSan option, and which puts its output in a -ubsan directory. results.checkTask(.matchTarget(target), .matchRuleType("CompileC")) { task in task.checkRuleInfo([.equal("CompileC"), .equal("\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-ubsan/x86_64/SourceFile.o"), .suffix("SourceFile.m"), .any, .any, .any, .any]) - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-fsanitize=undefined", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-ubsan/x86_64/SourceFile.o"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "-fsanitize=undefined", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-ubsan/x86_64/SourceFile.o"]) } // There should be one CompileSwiftSources task, which puts its output in a -ubsan directory. But the UBSan option is not passed for swift. results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-ubsan/x86_64/\(targetName)-OutputFileMap.json"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", "\(SRCROOT)/build/aProject.build/Debug/\(targetName).build/Objects-normal-ubsan/x86_64/\(targetName)-OutputFileMap.json"]) } // There should be one Ld task. results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkRuleInfo([.equal("Ld"), .equal("\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"), .any]) - task.checkCommandLineContains(["\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"]) + task.checkCommandLineContains(["\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)"]) } // There should be one task to copy the UBSan library into the product. @@ -6953,7 +6946,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { "SCRIPT_OUTPUT_FILE_LIST_1": .equal("\(SRCROOT)/build/aProject.build/Debug/App.build/OutputFileList-FileList-output2-49b85065e1ab5f8726dafd7606a852ce-resolved.xcfilelist"), "SCRIPT_OUTPUT_FILE_LIST_COUNT": .equal("2"), - "TOOLCHAIN_DIR": .equal("\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain"), + "TOOLCHAIN_DIR": .equal("\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain"), ] task.checkEnvironment(scriptVariables) } @@ -7020,7 +7013,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { "SCRIPT_OUTPUT_FILE_LIST_1": .equal("\(SRCROOT)/build/aProject.build/Debug/App.build/OutputFileList-FileList-output2-49b85065e1ab5f8726dafd7606a852ce-resolved.xcfilelist"), "SCRIPT_OUTPUT_FILE_LIST_COUNT": .equal("2"), - "TOOLCHAIN_DIR": .equal("\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain"), + "TOOLCHAIN_DIR": .equal("\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain"), ] task.checkEnvironment(scriptVariables) } diff --git a/Tests/SWBTaskConstructionTests/TaskOrderingTests.swift b/Tests/SWBTaskConstructionTests/TaskOrderingTests.swift index 5f39b3cb..7ec04ecd 100644 --- a/Tests/SWBTaskConstructionTests/TaskOrderingTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskOrderingTests.swift @@ -16,6 +16,7 @@ import SWBCore import SWBTaskConstruction import SWBTestSupport +import SWBProtocol @Suite fileprivate struct TaskOrderingTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/TrackedDomainTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TrackedDomainTaskConstructionTests.swift index ad6aeb95..950f8855 100644 --- a/Tests/SWBTaskConstructionTests/TrackedDomainTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TrackedDomainTaskConstructionTests.swift @@ -18,6 +18,7 @@ import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol @Suite(.requireXcode16()) fileprivate struct TrackedDomainTaskConstructionTests: CoreBasedTests { diff --git a/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift index 2d169fad..d40bc363 100644 --- a/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/UnitTestTaskConstructionTests.swift @@ -15,6 +15,7 @@ import SWBCore import SWBProtocol import SWBTestSupport import SWBUtil +import Foundation @Suite(.requireXcode16()) fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { @@ -133,7 +134,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation Requirements")) { task in task.checkRuleInfo(["SwiftDriver Compilation Requirements", "UnitTestTarget", "normal", "x86_64", "com.apple.xcode.tools.swift.compiler"]) - task.checkCommandLineContains([[swiftCompilerPath.str, "-module-name", "UnitTestTarget", "-O", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-Swift.h", "-working-directory", SRCROOT]].reduce([], +)) + task.checkCommandLineContains([[swiftCompilerPath.str, "-module-name", "UnitTestTarget", "-O", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-Swift.h", "-working-directory", SRCROOT]].reduce([], +)) task.checkInputs([ .path("\(SRCROOT)/TestOne.swift"), @@ -164,7 +165,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in task.checkRuleInfo(["SwiftDriver Compilation", "UnitTestTarget", "normal", "x86_64", "com.apple.xcode.tools.swift.compiler"]) - task.checkCommandLineContains([[swiftCompilerPath.str, "-module-name", "UnitTestTarget", "-O", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-Swift.h", "-working-directory", SRCROOT]].reduce([], +)) + task.checkCommandLineContains([[swiftCompilerPath.str, "-module-name", "UnitTestTarget", "-O", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/UnitTestTarget-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget-Swift.h", "-working-directory", SRCROOT]].reduce([], +)) task.checkInputs([ .path("\(SRCROOT)/TestOne.swift"), @@ -227,10 +228,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRule(["WriteAuxiliaryFile", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.LinkFileList"])) { _ in } results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkRuleInfo(["Ld", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/MacOS/UnitTestTarget", "normal"]) - task.checkCommandLineMatches(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-bundle", "-isysroot", .equal(core.loadSDK(.macOS).path.str), "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/usr/lib", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-iframework", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", .anySequence, "-filelist", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.swiftmodule", "-framework", "XCTest", "-lXCTestSwiftSupport", "-framework", "FrameworkTarget", "-o", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/MacOS/UnitTestTarget"]) - - // We used to pass the deployment target to the linker in the environment, but this is supposedly no longer necessary. - task.checkEnvironment([:], exact: true) + task.checkCommandLineMatches(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-bundle", "-isysroot", .equal(core.loadSDK(.macOS).path.str), "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/usr/lib", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-iframework", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", .anySequence, "-filelist", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/Objects-normal/x86_64/UnitTestTarget.swiftmodule", "-Xlinker", "-needed_framework", "-Xlinker", "XCTest", "-framework", "XCTest", "-Xlinker", "-needed-lXCTestSwiftSupport", "-lXCTestSwiftSupport", "-framework", "FrameworkTarget", "-o", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/MacOS/UnitTestTarget"]) } // There should be a 'Copy' of the generated header. @@ -283,7 +281,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { // There should be a 'CopySwiftLibs' task. results.checkTask(.matchTarget(target), .matchRuleType("CopySwiftLibs")) { task in task.checkRuleInfo(["CopySwiftLibs", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest"]) - task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--scan-executable", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/MacOS/UnitTestTarget", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Library/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Extensions", "--scan-folder", "\(SRCROOT)/build/Debug/FrameworkTarget.framework", "--platform", "macosx", "--toolchain", defaultToolchain.path.str, "--destination", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/SwiftStdLibToolInputDependencies.dep", "--filter-for-swift-os"]) + task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--scan-executable", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/MacOS/UnitTestTarget", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Library/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Extensions", "--scan-folder", "\(SRCROOT)/build/Debug/FrameworkTarget.framework", "--platform", "macosx", "--toolchain", defaultToolchain.path.str, "--destination", "\(SRCROOT)/build/Debug/UnitTestTarget.xctest/Contents/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTarget.build/SwiftStdLibToolInputDependencies.dep", "--filter-for-swift-os"]) } // There should be a 'Touch' task. @@ -301,6 +299,67 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { } } + @Test(.requireSDKs(.linux)) + func unitTestTarget_linux() async throws { + let swiftCompilerPath = try await self.swiftCompilerPath + let swiftVersion = try await self.swiftVersion + let testProject = TestProject( + "aProject", + groupTree: TestGroup( + "SomeFiles", + children: [ + TestFile("TestOne.swift"), + TestFile("TestTwo.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "CODE_SIGN_IDENTITY": "", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "linux", + "SWIFT_VERSION": swiftVersion, + ]), + ], + targets: [ + TestStandardTarget( + "UnitTestTarget", + type: .unitTest, + buildConfigurations: [ + TestBuildConfiguration("Debug", + buildSettings: [:]), + ], + buildPhases: [ + TestSourcesBuildPhase([ + "TestOne.swift", + "TestTwo.swift", + ]), + ], + dependencies: [] + ), + ]) + let core = try await getCore() + let tester = try TaskConstructionTester(core, testProject) + + let fs = PseudoFS() + + try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } + + await tester.checkBuild(runDestination: .linux, fs: fs) { results in + results.checkTarget("UnitTestTarget") { target in + results.checkTask(.matchTarget(target), .matchRuleType("GenerateTestEntryPoint")) { task in + task.checkCommandLineMatches([.suffix("builtin-generateTestEntryPoint"), "--output", .suffix("test_entry_point.swift")]) + task.checkOutputs([.pathPattern(.suffix("test_entry_point.swift"))]) + } + results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in + task.checkInputs(contain: [.pathPattern(.suffix("test_entry_point.swift"))]) + } + } + + results.checkNoDiagnostics() + } + } + // MARK: Application test target using TEST_HOST @@ -416,7 +475,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { let testFrameworkSubpaths = await testFrameworkSubpaths(includeXCUIAutomation: false) for frameworkSubpath in testFrameworkSubpaths { - let frameworkPath = core.developerPath.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) + let frameworkPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) try fs.createDirectory(frameworkPath.dirname, recursive: true) try fs.write(frameworkPath, contents: ByteString(encodingAsUTF8: frameworkPath.basename)) } @@ -444,7 +503,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation Requirements")) { task in task.checkRuleInfo(["SwiftDriver Compilation Requirements", "UnitTestTargetOne", "normal", "x86_64", "com.apple.xcode.tools.swift.compiler"]) - task.checkCommandLineContains(([[swiftCompilerPath.str, "-module-name", "UnitTestTargetOne", "-O", "@\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.SwiftFileList", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-parse-as-library", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-Swift.h", "-working-directory", SRCROOT]] as [[String]]).reduce([], +)) + task.checkCommandLineContains(([[swiftCompilerPath.str, "-module-name", "UnitTestTargetOne", "-O", "@\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.SwiftFileList", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-parse-as-library", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-Swift.h", "-working-directory", SRCROOT]] as [[String]]).reduce([], +)) task.checkInputs([ .path("\(SRCROOT)/TestOne.swift"), @@ -475,7 +534,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in task.checkRuleInfo(["SwiftDriver Compilation", "UnitTestTargetOne", "normal", "x86_64", "com.apple.xcode.tools.swift.compiler"]) - task.checkCommandLineContains(([[swiftCompilerPath.str, "-module-name", "UnitTestTargetOne", "-O", "@\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.SwiftFileList", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-parse-as-library", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-Swift.h", "-working-directory", SRCROOT]] as [[String]]).reduce([], +)) + task.checkCommandLineContains(([[swiftCompilerPath.str, "-module-name", "UnitTestTargetOne", "-O", "@\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.SwiftFileList", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-parse-as-library", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/UnitTestTargetOne-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne-Swift.h", "-working-directory", SRCROOT]] as [[String]]).reduce([], +)) task.checkInputs([ .path("\(SRCROOT)/TestOne.swift"), @@ -519,10 +578,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRule(["WriteAuxiliaryFile", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.LinkFileList"])) { _ in } results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkRuleInfo(["Ld", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/MacOS/UnitTestTargetOne", "normal"]) - task.checkCommandLineMatches(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-bundle", "-isysroot", .equal(core.loadSDK(.macOS).path.str), "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/usr/lib", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-iframework", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", .anySequence, "-filelist", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-rpath", "-Xlinker", "@executable_path/../Frameworks", "-bundle_loader", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.swiftmodule", "-framework", "XCTest", "-lXCTestSwiftSupport", "-Xlinker", "-no_adhoc_codesign", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/MacOS/UnitTestTargetOne"]) - - // We used to pass the deployment target to the linker in the environment, but this is supposedly no longer necessary. - task.checkEnvironment([:], exact: true) + task.checkCommandLineMatches(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-bundle", "-isysroot", .equal(core.loadSDK(.macOS).path.str), "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/usr/lib", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-iframework", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", .anySequence, "-filelist", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-rpath", "-Xlinker", "@executable_path/../Frameworks", "-bundle_loader", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/MacOS/AppTarget", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/Objects-normal/x86_64/UnitTestTargetOne.swiftmodule", "-Xlinker", "-needed_framework", "-Xlinker", "XCTest", "-framework", "XCTest", "-Xlinker", "-needed-lXCTestSwiftSupport", "-lXCTestSwiftSupport", "-Xlinker", "-no_adhoc_codesign", "-o", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/MacOS/UnitTestTargetOne"]) testTargetLinkTasks.append(task) } @@ -570,7 +626,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { // There should be a 'CopySwiftLibs' task. results.checkTask(.matchTarget(target), .matchRuleType("CopySwiftLibs")) { task in task.checkRuleInfo(["CopySwiftLibs", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest"]) - task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--sign", "-", "--scan-executable", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/MacOS/UnitTestTargetOne", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Library/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Extensions", "--platform", "macosx", "--toolchain", defaultToolchain.path.str, "--destination", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/SwiftStdLibToolInputDependencies.dep", "--filter-for-swift-os"]) + task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--sign", "-", "--scan-executable", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/MacOS/UnitTestTargetOne", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Library/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Extensions", "--platform", "macosx", "--toolchain", defaultToolchain.path.str, "--destination", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/PlugIns/UnitTestTargetOne.xctest/Contents/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug/UnitTestTargetOne.build/SwiftStdLibToolInputDependencies.dep", "--filter-for-swift-os"]) } // There should be a task to sign the test bundle, and one to generate entitlements for it. @@ -683,9 +739,9 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename(frameworkName)) { task in - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug/AppTarget.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) task.checkInputs([ - .path("\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"), + .path("\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"), .any, .any, ]) @@ -937,11 +993,11 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { try await fs.writePlist(Path("/tmp/Test/aProject/Entitlements.plist"), .plDict([:])) try await fs.writeFileContents(self.swiftCompilerPath) { $0 <<< "binary" } for frameworkSubpath in await testFrameworkSubpaths() { - let watchosframeworkPath = core.developerPath.join("Platforms/WatchOS.platform/Developer").join(frameworkSubpath) + let watchosframeworkPath = core.developerPath.path.join("Platforms/WatchOS.platform/Developer").join(frameworkSubpath) try fs.createDirectory(watchosframeworkPath.dirname, recursive: true) try fs.write(watchosframeworkPath, contents: ByteString(encodingAsUTF8: watchosframeworkPath.basename)) - let watchsimframeworkPath = core.developerPath.join("Platforms/WatchSimulator.platform/Developer").join(frameworkSubpath) + let watchsimframeworkPath = core.developerPath.path.join("Platforms/WatchSimulator.platform/Developer").join(frameworkSubpath) try fs.createDirectory(watchsimframeworkPath.dirname, recursive: true) try fs.write(watchsimframeworkPath, contents: ByteString(encodingAsUTF8: watchosframeworkPath.basename)) } @@ -987,7 +1043,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { var copyTask: (any PlannedTask)? = nil results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename(frameworkName)) { task in copyTask = task - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchos/AppTarget.app/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/WatchOS.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchos/AppTarget.app/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/WatchOS.platform/Developer/\(frameworkPath.str)"]) } results.checkTask(.matchTarget(target), .matchRuleType("CodeSign"), .matchRuleItemBasename(frameworkName)) { task in task.checkRuleInfo(["CodeSign", "\(SRCROOT)/build/Debug-watchos/AppTarget.app/Frameworks/\(frameworkName)"]) @@ -1117,7 +1173,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename(frameworkName)) { task in - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchsimulator/AppTarget.app/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/WatchSimulator.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchsimulator/AppTarget.app/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/WatchSimulator.platform/Developer/\(frameworkPath.str)"]) } results.checkNoTask(.matchTarget(target), .matchRuleType("CodeSign"), .matchRuleItemBasename(frameworkName)) } @@ -1224,11 +1280,11 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { try await fs.writePlist(Path("/tmp/Test/aProject/Entitlements.plist"), .plDict([:])) try await fs.writeFileContents(self.swiftCompilerPath) { $0 <<< "binary" } for frameworkSubpath in await testFrameworkSubpaths() { - let watchosframeworkPath = core.developerPath.join("Platforms/WatchOS.platform/Developer").join(frameworkSubpath) + let watchosframeworkPath = core.developerPath.path.join("Platforms/WatchOS.platform/Developer").join(frameworkSubpath) try fs.createDirectory(watchosframeworkPath.dirname, recursive: true) try fs.write(watchosframeworkPath, contents: ByteString(encodingAsUTF8: watchosframeworkPath.basename)) - let watchsimframeworkPath = core.developerPath.join("Platforms/WatchSimulator.platform/Developer").join(frameworkSubpath) + let watchsimframeworkPath = core.developerPath.path.join("Platforms/WatchSimulator.platform/Developer").join(frameworkSubpath) try fs.createDirectory(watchsimframeworkPath.dirname, recursive: true) try fs.write(watchsimframeworkPath, contents: ByteString(encodingAsUTF8: watchosframeworkPath.basename)) } @@ -1291,7 +1347,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { var copyTask: (any PlannedTask)? = nil results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename(frameworkName)) { task in copyTask = task - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchos/\(productName)/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/WatchOS.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchos/\(productName)/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/WatchOS.platform/Developer/\(frameworkPath.str)"]) copyFrameworksTasks.append(task) } results.checkTask(.matchTarget(target), .matchRuleType("CodeSign"), .matchRuleItemBasename(frameworkName)) { task in @@ -1479,7 +1535,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename(frameworkName)) { task in - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchsimulator/\(productName)/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/WatchSimulator.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug-watchsimulator/\(productName)/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/WatchSimulator.platform/Developer/\(frameworkPath.str)"]) copyFrameworksTasks.append(task) } results.checkNoTask(.matchTarget(target), .matchRuleType("CodeSign"), .matchRuleItemBasename(frameworkName)) @@ -1597,7 +1653,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { try await fs.writePlist(Path("/tmp/Test/aProject/Entitlements.plist"), .plDict([:])) try await fs.writeFileContents(self.swiftCompilerPath) { $0 <<< "binary" } for frameworkSubpath in await testFrameworkSubpaths() { - let frameworkPath = core.developerPath.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) + let frameworkPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) try fs.createDirectory(frameworkPath.dirname, recursive: true) try fs.write(frameworkPath, contents: ByteString(encodingAsUTF8: frameworkPath.basename)) } @@ -1625,7 +1681,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename(frameworkName)) { task in - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) } results.checkTask(.matchTarget(target), .matchRuleType("CodeSign"), .matchRuleItemBasename(frameworkName)) { task in task.checkRuleInfo(["CodeSign", "\(SRCROOT)/build/Debug\(MacCatalystInfo.publicSDKBuiltProductsDirSuffix)/AppTarget.app/Contents/Frameworks/\(frameworkName)"]) @@ -1752,12 +1808,12 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } for frameworkSubpath in await testFrameworkSubpaths() { - let frameworkPath = core.developerPath.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) + let frameworkPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) try fs.createDirectory(frameworkPath.dirname, recursive: true) try fs.write(frameworkPath, contents: ByteString(encodingAsUTF8: frameworkPath.basename)) } - let xctrunnerPath = core.developerPath.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") + let xctrunnerPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") try await fs.writeXCTRunnerApp(xctrunnerPath, archs: ["arm64", "arm64e", "x86_64"], platform: .macOS, infoLookup: core) // Perform a build which has a specific target order in the top-level targets, and which has Parallelize Build turned off. Specifically we insert the framework test target *after* the app target, but *before* the hosted test targets. @@ -1979,12 +2035,12 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } for frameworkSubpath in await testFrameworkSubpaths() { - let frameworkPath = core.developerPath.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) + let frameworkPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) try fs.createDirectory(frameworkPath.dirname, recursive: true) try fs.write(frameworkPath, contents: ByteString(encodingAsUTF8: frameworkPath.basename)) } - let xctrunnerPath = core.developerPath.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") + let xctrunnerPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") try await fs.writeXCTRunnerApp(xctrunnerPath, archs: ["arm64", "arm64e", "x86_64"], platform: .macOS, infoLookup: core) // Perform a build where only the app and test targets are top-level targets, and which has Parallelize Build turned off. @@ -2191,13 +2247,13 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } for frameworkSubpath in await testFrameworkSubpaths(variantSubpath: "") { - let frameworkPath = core.developerPath.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) + let frameworkPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer").join(frameworkSubpath) try fs.createDirectory(frameworkPath.dirname, recursive: true) try fs.write(frameworkPath, contents: ByteString(encodingAsUTF8: frameworkPath.basename)) } // Create the XCTRunner.app source to copy. - let xctrunnerPath = core.developerPath.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") + let xctrunnerPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") try await fs.writeXCTRunnerApp(xctrunnerPath, archs: ["arm64", "arm64e", "x86_64"], platform: .macOS, infoLookup: core) // Check a debug build. @@ -2225,7 +2281,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { // There should be one Swift compile phase, and a task to generate its output file map. results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in task.checkRuleInfo(["SwiftDriver Compilation", "UITestTarget", "normal", "x86_64", "com.apple.xcode.tools.swift.compiler"]) - task.checkCommandLineContains(([[swiftCompilerPath.str, "-module-name", "UITestTarget", "-O", "@\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.SwiftFileList", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget-Swift.h", "-working-directory", SRCROOT]] as [[String]]).reduce([], +)) + task.checkCommandLineContains(([[swiftCompilerPath.str, "-module-name", "UITestTarget", "-O", "@\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.SwiftFileList", "-sdk", core.loadSDK(.macOS).path.str, "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-g", /* options from the xcspec which sometimes change appear here */ "-swift-version", swiftVersion, "-I", "\(SRCROOT)/build/Debug", "-F", "\(SRCROOT)/build/Debug", "-F", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", "-c", "-j\(compilerParallelismLevel)", "-incremental", "-output-file-map", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget-OutputFileMap.json", "-serialize-diagnostics", "-emit-dependencies", "-emit-module", "-emit-module-path", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.swiftmodule", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/swift-overrides.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-generated-files.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-own-target-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-all-target-headers.hmap", "-Xcc", "-iquote", "-Xcc", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/UITestTarget-project-headers.hmap", "-Xcc", "-I\(SRCROOT)/build/Debug/include", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/DerivedSources-normal/x86_64", "-Xcc", "-I\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/DerivedSources", "-emit-objc-header", "-emit-objc-header-path", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget-Swift.h", "-working-directory", SRCROOT]] as [[String]]).reduce([], +)) task.checkInputs([ .path("\(SRCROOT)/TestOne.swift"), .path("\(SRCROOT)/TestTwo.swift"), @@ -2312,10 +2368,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRule(["WriteAuxiliaryFile", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.LinkFileList"])) { _ in } results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkRuleInfo(["Ld", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/MacOS/UITestTarget", "normal"]) - task.checkCommandLineMatches(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-bundle", "-isysroot", .equal(core.loadSDK(.macOS).path.str), "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/usr/lib", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-iframework", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", .anySequence, "-filelist", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.swiftmodule", "-framework", "XCTest", "-lXCTestSwiftSupport", "-Xlinker", "-no_adhoc_codesign", "-o", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/MacOS/UITestTarget"]) - - // We used to pass the deployment target to the linker in the environment, but this is supposedly no longer necessary. - task.checkEnvironment([:], exact: true) + task.checkCommandLineMatches(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(MACOSX_DEPLOYMENT_TARGET)", "-bundle", "-isysroot", .equal(core.loadSDK(.macOS).path.str), "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-L\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/usr/lib", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-iframework", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Frameworks", .anySequence, "-filelist", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.LinkFileList", "-Xlinker", "-rpath", "-Xlinker", "@loader_path/../Frameworks", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/Objects-normal/x86_64/UITestTarget.swiftmodule", "-Xlinker", "-needed_framework", "-Xlinker", "XCTest", "-framework", "XCTest", "-Xlinker", "-needed-lXCTestSwiftSupport", "-lXCTestSwiftSupport", "-Xlinker", "-no_adhoc_codesign", "-o", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/MacOS/UITestTarget"]) } // There should be a 'Copy' of the generated header. @@ -2368,28 +2421,28 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { // There should be a 'CopySwiftLibs' task. results.checkTask(.matchTarget(target), .matchRuleType("CopySwiftLibs")) { task in task.checkRuleInfo(["CopySwiftLibs", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest"]) - task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--sign", "-", "--scan-executable", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/MacOS/UITestTarget", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Library/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Extensions", "--platform", "macosx", "--toolchain", "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain", "--destination", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/SwiftStdLibToolInputDependencies.dep", "--filter-for-swift-os"]) + task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--sign", "-", "--scan-executable", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/MacOS/UITestTarget", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Library/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Extensions", "--platform", "macosx", "--toolchain", "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain", "--destination", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug/UITestTarget.build/SwiftStdLibToolInputDependencies.dep", "--filter-for-swift-os"]) } // Check selected tasks to copy the XCTRunner.app. results.checkTask(.matchTarget(target), .matchRule(["CopyAndPreserveArchs", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/MacOS/UITestTarget-Runner"])) { task in - task.checkCommandLine(["lipo", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/MacOS/XCTRunner", "-output", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/MacOS/UITestTarget-Runner", "-extract", "x86_64"]) + task.checkCommandLine(["lipo", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/MacOS/XCTRunner", "-output", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/MacOS/UITestTarget-Runner", "-extract", "x86_64"]) task.checkOutputs([ .path("\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/MacOS/UITestTarget-Runner"), .name("Copy \(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/MacOS/UITestTarget-Runner"), ]) } - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PkgInfo", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/PkgInfo"])) { task in + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PkgInfo", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/PkgInfo"])) { task in task.checkOutputs([ .path("\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PkgInfo"), .name("Copy \(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PkgInfo"), ]) } - results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/Info.plist", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"])) { task in - task.checkCommandLine(["builtin-copyPlist", "--validate", "--convert", "xml1", "--macro-expansion", "WRAPPEDPRODUCTNAME", "UITestTarget-Runner", "--macro-expansion", "WRAPPEDPRODUCTBUNDLEIDENTIFIER", "com.dev.UITestTarget.xctrunner", "--macro-expansion", "TESTPRODUCTNAME", "UITestTarget", "--macro-expansion", "TESTPRODUCTBUNDLEIDENTIFIER", "com.dev.UITestTarget", "--copy-value", "UIDeviceFamily", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Info.plist", "--outdir", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents", "--", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"]) + results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/Info.plist", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"])) { task in + task.checkCommandLine(["builtin-copyPlist", "--validate", "--convert", "xml1", "--macro-expansion", "WRAPPEDPRODUCTNAME", "UITestTarget-Runner", "--macro-expansion", "WRAPPEDPRODUCTBUNDLEIDENTIFIER", "com.dev.UITestTarget.xctrunner", "--macro-expansion", "TESTPRODUCTNAME", "UITestTarget", "--macro-expansion", "TESTPRODUCTBUNDLEIDENTIFIER", "com.dev.UITestTarget", "--copy-value", "UIDeviceFamily", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Info.plist", "--outdir", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents", "--", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"]) task.checkInputs(contain: [ .path("\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Info.plist"), - .path("\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"), + .path("\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-ProductPostprocessingTaskProducer"))), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-entry"))), ]) @@ -2406,9 +2459,9 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename("\(frameworkName)")) { task in - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/Debug/UITestTarget-Runner.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) task.checkInputs(contain: [ - .path("\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"), + .path("\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-ProductPostprocessingTaskProducer"))), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-entry"))), ]) @@ -2577,16 +2630,16 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { .name("Copy \(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/MacOS/UITestTarget-Runner"), ]) } - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/PkgInfo", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/PkgInfo"])) { task in + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/PkgInfo", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/PkgInfo"])) { task in task.checkOutputs([ .path("\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/PkgInfo"), .name("Copy \(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/PkgInfo"), ]) } - results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/Info.plist", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"])) { task in + results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/Info.plist", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"])) { task in task.checkInputs(contain: [ .path("\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/PlugIns/UITestTarget.xctest/Contents/Info.plist"), - .path("\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"), + .path("\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Contents/Info.plist"), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-ProductPostprocessingTaskProducer"))), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-entry"))), ]) @@ -2603,9 +2656,9 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename results.checkTask(.matchTarget(target), .matchRuleType("Copy"), .matchRuleItemBasename("\(frameworkName)")) { task in - task.checkRuleInfo(["Copy", "\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) + task.checkRuleInfo(["Copy", "\(SRCROOT)/build/UninstalledProducts/macosx/UITestTarget-Runner.app/Contents/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"]) task.checkInputs(contain: [ - .path("\(core.developerPath.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"), + .path("\(core.developerPath.path.str)/Platforms/MacOSX.platform/Developer/\(frameworkPath.str)"), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-ProductPostprocessingTaskProducer"))), .namePattern(.and(.prefix("target-UITestTarget-"), .suffix("-entry"))), ]) @@ -2793,20 +2846,20 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { try fs.createDirectory(Path("/Users/whoever/Library/MobileDevice/Provisioning Profiles"), recursive: true) try fs.write(Path("/Users/whoever/Library/MobileDevice/Provisioning Profiles/8db0e92c-592c-4f06-bfed-9d945841b78d.mobileprovision"), contents: "profile") for frameworkSubpath in await testFrameworkSubpaths() { - let iosframeworkPath = core.developerPath.join("Platforms/iPhoneOS.platform/Developer").join(frameworkSubpath) + let iosframeworkPath = core.developerPath.path.join("Platforms/iPhoneOS.platform/Developer").join(frameworkSubpath) try fs.createDirectory(iosframeworkPath.dirname, recursive: true) try fs.write(iosframeworkPath, contents: ByteString(encodingAsUTF8: iosframeworkPath.basename)) - let isimframeworkPath = core.developerPath.join("Platforms/iPhoneSimulator.platform/Developer").join(frameworkSubpath) + let isimframeworkPath = core.developerPath.path.join("Platforms/iPhoneSimulator.platform/Developer").join(frameworkSubpath) try fs.createDirectory(isimframeworkPath.dirname, recursive: true) try fs.write(isimframeworkPath, contents: ByteString(encodingAsUTF8: iosframeworkPath.basename)) } // Create the XCTRunner.app source to copy. - let deviceXctrunnerPath = core.developerPath.join("Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app") + let deviceXctrunnerPath = core.developerPath.path.join("Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app") try await fs.writeXCTRunnerApp(deviceXctrunnerPath, archs: ["arm64", "arm64e"], platform: .iOS, infoLookup: core) - let simXctrunnerPath = core.developerPath.join("Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app") + let simXctrunnerPath = core.developerPath.path.join("Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app") try await fs.writeXCTRunnerApp(simXctrunnerPath, archs: ["x86_64"], platform: .iOSSimulator, infoLookup: core) // Check a debug build for the device. @@ -2833,15 +2886,15 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { // There should be two tasks to copy the XCTRunner.app, and one to preprocess its Info.plist results.checkTask(.matchTarget(target), .matchRule(["CopyAndPreserveArchs", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/UITestTarget-Runner"])) { _ in } - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PkgInfo", "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/PkgInfo"])) { _ in } - results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/Info.plist", "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Info.plist"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PkgInfo", "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/PkgInfo"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/Info.plist", "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Info.plist"])) { _ in } // There should be tasks to copy the test frameworks and re-sign them. var nestedSigningTasks = [any PlannedTask]() for framework in await testFrameworkSubpaths() { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Developer/\(frameworkPath.str)"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Developer/\(frameworkPath.str)"])) { _ in } results.checkTask(.matchTarget(target), .matchRule(["CodeSign", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/Frameworks/\(frameworkName)"])) { task in nestedSigningTasks.append(task) } @@ -2922,15 +2975,15 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { // There should be two tasks to copy the XCTRunner.app, and one to preprocess its Info.plist results.checkTask(.matchTarget(target), .matchRule(["CopyAndPreserveArchs", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/UITestTarget-Runner"])) { _ in } - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/PkgInfo", "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/PkgInfo"])) { _ in } - results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/Info.plist", "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Info.plist"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/PkgInfo", "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/PkgInfo"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/Info.plist", "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Info.plist"])) { _ in } // There should be tasks to copy the test frameworks and re-sign them. var nestedSigningTasks = [any PlannedTask]() for framework in await testFrameworkSubpaths() { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Developer/\(frameworkPath.str)"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Developer/\(frameworkPath.str)"])) { _ in } results.checkTask(.matchTarget(target), .matchRule(["CodeSign", "\(SRCROOT)/build/UninstalledProducts/iphoneos/UITestTarget-Runner.app/Frameworks/\(frameworkName)"])) { task in nestedSigningTasks.append(task) } @@ -3015,16 +3068,16 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { results.checkTask(.matchTarget(target), .matchRule(["MkDir", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest"])) { _ in } // There should be two tasks to copy the XCTRunner.app, and one to preprocess its Info.plist - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/UITestTarget-Runner", "\(core.developerPath.str)/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app/XCTRunner"])) { _ in } - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/PkgInfo", "\(core.developerPath.str)/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app/PkgInfo"])) { _ in } - results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/Info.plist", "\(core.developerPath.str)/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Info.plist"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/UITestTarget-Runner", "\(core.developerPath.path.str)/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app/XCTRunner"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/PkgInfo", "\(core.developerPath.path.str)/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app/PkgInfo"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["CopyPlistFile", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/Info.plist", "\(core.developerPath.path.str)/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/XCTRunner.app/Info.plist"])) { _ in } // There should be tasks to copy the test frameworks. But the test frameworks are not signed for the simulator. var nestedSigningTasks = [any PlannedTask]() for framework in await testFrameworkSubpaths() { let frameworkPath = Path(framework) let frameworkName = frameworkPath.basename - results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/Frameworks/\(frameworkName)", "\(core.developerPath.str)/Platforms/iPhoneSimulator.platform/Developer/\(frameworkPath.str)"])) { _ in } + results.checkTask(.matchTarget(target), .matchRule(["Copy", "\(SRCROOT)/build/Debug-iphonesimulator/UITestTarget-Runner.app/Frameworks/\(frameworkName)", "\(core.developerPath.path.str)/Platforms/iPhoneSimulator.platform/Developer/\(frameworkPath.str)"])) { _ in } } // There should be a task to generate a dSYM file for the target. This is placed in the PlugIns directory alongside the .xctest bundle. @@ -3085,7 +3138,7 @@ fileprivate struct UnitTestTaskConstructionTests: CoreBasedTests { // There should be a 'CopySwiftLibs' task that includes a reference to the libXCTestSwiftSupport.dylib executable. results.checkTask(.matchTarget(target), .matchRuleType("CopySwiftLibs")) { task in task.checkRuleInfo(["CopySwiftLibs", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest"]) - task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--sign", "105DE4E702E4", "--scan-executable", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/UITestTarget", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/Extensions", "--platform", "iphoneos", "--toolchain", "\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain", "--destination", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.str)/Platforms/iPhoneOS.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug-iphoneos/UITestTarget.build/SwiftStdLibToolInputDependencies.dep", "--back-deploy-swift-concurrency"]) + task.checkCommandLine(["builtin-swiftStdLibTool", "--copy", "--verbose", "--sign", "105DE4E702E4", "--scan-executable", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/UITestTarget", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/Frameworks", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/PlugIns", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/SystemExtensions", "--scan-folder", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/Extensions", "--platform", "iphoneos", "--toolchain", "\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain", "--destination", "\(SRCROOT)/build/Debug-iphoneos/UITestTarget-Runner.app/PlugIns/UITestTarget.xctest/Frameworks", "--strip-bitcode", "--scan-executable", "\(core.developerPath.path.str)/Platforms/iPhoneOS.platform/Developer/usr/lib/libXCTestSwiftSupport.dylib", "--strip-bitcode-tool", "\(defaultToolchain.path.str)/usr/bin/bitcode_strip", "--emit-dependency-info", "\(SRCROOT)/build/aProject.build/Debug-iphoneos/UITestTarget.build/SwiftStdLibToolInputDependencies.dep", "--back-deploy-swift-concurrency"]) } } diff --git a/Tests/SWBTaskConstructionTests/UnsupportedBehaviorTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/UnsupportedBehaviorTaskConstructionTests.swift index 7960e547..85630110 100644 --- a/Tests/SWBTaskConstructionTests/UnsupportedBehaviorTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/UnsupportedBehaviorTaskConstructionTests.swift @@ -121,7 +121,7 @@ fileprivate struct UnsupportedBehaviorTaskConstructionTests: CoreBasedTests { try await fs.writeFileContents(swiftCompilerPath) { $0 <<< "binary" } for platform in ["iPhoneOS", "iPhoneSimulator"] { for frameworkSubpath in unitTestFrameworkSubpaths { - let frameworkPath = core.developerPath.join("Platforms/\(platform).platform/Developer").join(frameworkSubpath) + let frameworkPath = core.developerPath.path.join("Platforms/\(platform).platform/Developer").join(frameworkSubpath) try fs.createDirectory(frameworkPath.dirname, recursive: true) try fs.write(frameworkPath, contents: ByteString(encodingAsUTF8: frameworkPath.basename)) } diff --git a/Tests/SWBTaskConstructionTests/WatchTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/WatchTaskConstructionTests.swift index 81d46ff6..db2a64f1 100644 --- a/Tests/SWBTaskConstructionTests/WatchTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/WatchTaskConstructionTests.swift @@ -378,7 +378,7 @@ fileprivate struct WatchTaskConstructionTests: CoreBasedTests { // There should be a task to embed the Swift standard libraries. results.checkTask(.matchTarget(target), .matchRuleType("CopySwiftLibs"), .matchRuleItemBasename("Watchable WatchKit App.app")) { task in - task.checkCommandLineContains(["builtin-swiftStdLibTool", "--scan-executable", "\(builtWatchAppPath)/Watchable WatchKit App", "--scan-folder", "\(builtWatchAppPath)/Frameworks", "--scan-folder", "\(builtWatchAppPath)/PlugIns", "--platform", "watchos", "--destination", "\(builtWatchAppPath)/Frameworks", "--strip-bitcode"]) + task.checkCommandLineContains(["builtin-swiftStdLibTool", "--scan-executable", "\(builtWatchAppPath)/Watchable WatchKit App", "--scan-folder", "\(builtWatchAppPath)/Frameworks", "--scan-folder", "\(builtWatchAppPath)/PlugIns", "--platform", "watchos", "--destination", "\(builtWatchAppPath)/Frameworks"]) } // There should be one codesign task. @@ -484,7 +484,7 @@ fileprivate struct WatchTaskConstructionTests: CoreBasedTests { // There should be a task to embed the Swift standard libraries. results.checkTask(.matchTarget(target), .matchRuleType("CopySwiftLibs"), .matchRuleItemBasename("Watchable.app")) { task in - task.checkCommandLineContains(["builtin-swiftStdLibTool", "--scan-executable", "\(builtHostIOSAppPath)/Watchable", "--scan-folder", "\(builtHostIOSAppPath)/Frameworks", "--scan-folder", "\(builtHostIOSAppPath)/PlugIns", "--platform", "iphoneos", "--destination", "\(builtHostIOSAppPath)/Frameworks", "--strip-bitcode"]) + task.checkCommandLineContains(["builtin-swiftStdLibTool", "--scan-executable", "\(builtHostIOSAppPath)/Watchable", "--scan-folder", "\(builtHostIOSAppPath)/Frameworks", "--scan-folder", "\(builtHostIOSAppPath)/PlugIns", "--platform", "iphoneos", "--destination", "\(builtHostIOSAppPath)/Frameworks"]) } // There should be one codesign task. @@ -539,15 +539,11 @@ fileprivate struct WatchTaskConstructionTests: CoreBasedTests { ["-o", "\(SRCROOT)/build/aProject.build/Debug-watchsimulator/Watchable WatchKit Extension.build/Objects-\(variant)/\(arch)/Controller.o"] ].reduce([], +) task.checkCommandLineContains(expectedCommandLine) - #expect(!task.commandLine.contains("-fembed-bitcode-marker")) - #expect(!task.commandLine.contains("-fembed-bitcode")) } results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in task.checkRuleInfo(["SwiftDriver Compilation", "Watchable WatchKit Extension", .equal(variant), .equal(arch), .equal("com.apple.xcode.tools.swift.compiler")]) let responseFilePath = "@\(SRCROOT)/build/aProject.build/Debug-watchsimulator/\(target.target.name).build/Objects-\(variant)/\(arch)/\(target.target.name).SwiftFileList" task.checkCommandLineContains([swiftCompilerPath.str, responseFilePath, "-sdk", core.loadSDK(.watchOSSimulator).path.str, "-target", "x86_64-apple-watchos\(core.loadSDK(.watchOS).defaultDeploymentTarget)-simulator"]) - #expect(!task.commandLine.contains("-embed-bitcode-marker")) - #expect(!task.commandLine.contains("-embed-bitcode")) } results.checkTaskExists(.matchTarget(target), .matchRuleType("SwiftDriver Compilation Requirements")) @@ -561,8 +557,6 @@ fileprivate struct WatchTaskConstructionTests: CoreBasedTests { ["-fapplication-extension", "\(SRCROOT)/build/Debug-watchsimulator/Watchable WatchKit Extension.appex/Watchable WatchKit Extension"] ].reduce([], +) task.checkCommandLineContains(expectedCommandLine) - #expect(!task.commandLine.contains("-fembed-bitcode-marker")) - #expect(!task.commandLine.contains("-fembed-bitcode")) } // There should be tasks to copy the associated Swift files. @@ -704,24 +698,18 @@ fileprivate struct WatchTaskConstructionTests: CoreBasedTests { ["-o", "\(SRCROOT)/build/aProject.build/Debug-iphonesimulator/Watchable.build/Objects-normal/\(arch)/main.o"] ].reduce([], +) task.checkCommandLineContains(expectedCommandLine) - #expect(!task.commandLine.contains("-fembed-bitcode-marker")) - #expect(!task.commandLine.contains("-fembed-bitcode")) } // SwiftDriver results.checkTask(.matchTarget(target), .matchRuleType("SwiftDriver Compilation")) { task in task.checkRuleInfo(["SwiftDriver Compilation", "Watchable", .equal("normal"), .equal(arch), .equal("com.apple.xcode.tools.swift.compiler")]) let responseFilePath = "@\(SRCROOT)/build/aProject.build/Debug-iphonesimulator/\(target.target.name).build/Objects-normal/\(arch)/\(target.target.name).SwiftFileList" task.checkCommandLineContains([swiftCompilerPath.str, responseFilePath, "-sdk", core.loadSDK(.iOSSimulator).path.str, "-target", "\(arch)-apple-ios\(core.loadSDK(.iOSSimulator).defaultDeploymentTarget)-simulator"]) - #expect(!task.commandLine.contains("-embed-bitcode-marker")) - #expect(!task.commandLine.contains("-embed-bitcode")) } results.checkTaskExists(.matchTarget(target), .matchRuleType("SwiftDriver Compilation Requirements")) // Ld results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in - #expect(!task.commandLine.contains("-fembed-bitcode-marker")) - #expect(!task.commandLine.contains("-fembed-bitcode")) } } @@ -803,7 +791,7 @@ fileprivate struct WatchTaskConstructionTests: CoreBasedTests { } // Check an install build for the device. - let installParameters = BuildParameters(action: .install, configuration: "Debug", overrides: ["BITCODE_GENERATION_MODE": "bitcode"]) + let installParameters = BuildParameters(action: .install, configuration: "Debug") await tester.checkBuild(installParameters, runDestination: .macOS, fs: fs) { results in // Ignore certain classes of tasks. results.checkTasks(.matchRuleType("Gate")) { _ in } diff --git a/Tests/SWBTaskConstructionTests/XCFrameworkTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/XCFrameworkTaskConstructionTests.swift index 70b232c6..0e5b09a0 100644 --- a/Tests/SWBTaskConstructionTests/XCFrameworkTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/XCFrameworkTaskConstructionTests.swift @@ -15,6 +15,8 @@ import Testing import SWBTestSupport import SWBUtil import SWBTaskConstruction +import SWBProtocol +import Foundation @Suite fileprivate struct XCFrameworkTaskConstructionTests: CoreBasedTests { @@ -450,7 +452,7 @@ fileprivate struct XCFrameworkTaskConstructionTests: CoreBasedTests { // There needs to be a strong dependency on the XCFramework processing. results.checkTaskFollows(task, antecedent: try #require(processSupportXCFrameworkTask)) - task.checkCommandLine(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", core.loadSDK(.macOS).path.str, "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App.LinkFileList", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App.swiftmodule", "-framework", "Support", "-Xlinker", "-no_adhoc_codesign", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/MacOS/App"]) + task.checkCommandLine(["clang", "-Xlinker", "-reproducible", "-target", "x86_64-apple-macos\(core.loadSDK(.macOS).defaultDeploymentTarget)", "-isysroot", core.loadSDK(.macOS).path.str, "-Os", "-L\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-L\(SRCROOT)/build/Debug", "-F\(SRCROOT)/build/EagerLinkingTBDs/Debug", "-F\(SRCROOT)/build/Debug", "-filelist", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App.LinkFileList", "-Xlinker", "-object_path_lto", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App_lto.o", "-Xlinker", "-dependency_info", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App_dependency_info.dat", "-fobjc-link-runtime", "-L\(core.developerPath.path.str)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", "-L/usr/lib/swift", "-Xlinker", "-add_ast_path", "-Xlinker", "\(SRCROOT)/build/aProject.build/Debug/App.build/Objects-normal/x86_64/App.swiftmodule", "-framework", "Support", "-Xlinker", "-no_adhoc_codesign", "-o", "\(SRCROOT)/build/Debug/App.app/Contents/MacOS/App"]) } } } @@ -538,7 +540,7 @@ fileprivate struct XCFrameworkTaskConstructionTests: CoreBasedTests { try fs.createDirectory(Path(SRCROOT), recursive: true) try fs.write(Path(SRCROOT).join("file.c"), contents: "int f() { return 0; }") - let xctrunnerPath = core.developerPath.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") + let xctrunnerPath = core.developerPath.path.join("Platforms/MacOSX.platform/Developer/Library/Xcode/Agents/XCTRunner.app") try await fs.writeXCTRunnerApp(xctrunnerPath, archs: ["arm64", "arm64e", "x86_64"], platform: .macOS, infoLookup: core) let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ diff --git a/Tests/SWBTaskExecutionTests/BuildDescriptionTests.swift b/Tests/SWBTaskExecutionTests/BuildDescriptionTests.swift index 9f02963a..28eb3598 100644 --- a/Tests/SWBTaskExecutionTests/BuildDescriptionTests.swift +++ b/Tests/SWBTaskExecutionTests/BuildDescriptionTests.swift @@ -30,13 +30,7 @@ fileprivate struct BuildDescriptionTests: CoreBasedTests { func fullManifest(fileSystem: String) -> String { let tmp = Path.root.join("tmp").strWithPosixSlashes let deps = Path.root.join("tmp").join("foo.d") - let signature: String - #if os(Windows) - // non-constant on Windows because Path.root may evaluate to any drive letter - signature = BuildDescriptionBuilder.computeShellToolSignature(args: ["true"], environment: EnvironmentBindings(), dependencyData: .makefile(deps), isUnsafeToInterrupt: false, additionalSignatureData: "").unsafeStringValue - #else - signature = "aca37e3650838b65a98c26816eed1031" - #endif + let signature = BuildDescriptionBuilder.computeShellToolSignature(args: ["true"], environment: EnvironmentBindings(), dependencyData: .makefile(deps), isUnsafeToInterrupt: false, additionalSignatureData: "").unsafeStringValue return """ {"client":{"name":"basic","version":0,"file-system":"\(fileSystem)","perform-ownership-analysis":"\(SWBFeatureFlag.performOwnershipAnalysis.value ? "yes" : "no")"},"targets":{"":[""]},"nodes":{"\(tmp)/filtered/":{"content-exclusion-patterns":["_CodeSignature","*.gitignore"]}},"commands":{"":{"tool":"phony","inputs":[],"outputs":[""]},"P0:::Foo":{"tool":"shell","description":"Foo","inputs":["\(tmp)/all/","\(tmp)/filtered/"],"outputs":[],"args":["true"],"env":{},"working-directory":"\(Path.pathSeparatorString.escapedForJSON)","deps":["\(deps.str.escapedForJSON)"],"deps-style":"makefile","signature":"\(signature)"}}} """ diff --git a/Tests/SWBTaskExecutionTests/FileCopyTaskTests.swift b/Tests/SWBTaskExecutionTests/FileCopyTaskTests.swift index 4443ab5f..da70238e 100644 --- a/Tests/SWBTaskExecutionTests/FileCopyTaskTests.swift +++ b/Tests/SWBTaskExecutionTests/FileCopyTaskTests.swift @@ -15,6 +15,7 @@ import Testing import SWBTestSupport import SWBUtil import SWBTaskExecution +import SWBCore @Suite fileprivate struct FileCopyTaskTests { diff --git a/Tests/SWBTaskExecutionTests/InProcessTaskTestSupport.swift b/Tests/SWBTaskExecutionTests/InProcessTaskTestSupport.swift index aecbf67b..ac43422e 100644 --- a/Tests/SWBTaskExecutionTests/InProcessTaskTestSupport.swift +++ b/Tests/SWBTaskExecutionTests/InProcessTaskTestSupport.swift @@ -21,6 +21,7 @@ import SWBUtil import enum SWBProtocol.ExternalToolResult import struct SWBProtocol.BuildOperationMetrics import SWBMacro +import Synchronization struct MockExecutionDelegate: TaskExecutionDelegate { struct Lookup: PlatformInfoLookup { diff --git a/Tests/SWBTaskExecutionTests/PBXCpTests.swift b/Tests/SWBTaskExecutionTests/PBXCpTests.swift index 6dd7504f..c4b0237f 100644 --- a/Tests/SWBTaskExecutionTests/PBXCpTests.swift +++ b/Tests/SWBTaskExecutionTests/PBXCpTests.swift @@ -14,6 +14,13 @@ import Foundation import Testing import SWBUtil import SWBTestSupport +import SWBCore + +#if canImport(System) +import System +#else +import SystemPackage +#endif @Suite fileprivate struct PBXCpTests: CoreBasedTests { @@ -470,7 +477,7 @@ fileprivate struct PBXCpTests: CoreBasedTests { } - /// Check that we can invoke bitcode_strip. + /// Check that we can invoke `bitcode_strip`. @Test func bitcodeStrip() async throws { try await withTemporaryDirectory { tmp in @@ -487,11 +494,12 @@ fileprivate struct PBXCpTests: CoreBasedTests { // Check that we run the bitcode_strip tool and capture its output. Note that bitcode_strip is in the default toolchain, so we need to pass the path to it there. let defaultToolchain = try #require(try await getCore().toolchainRegistry.defaultToolchain) let bitcodeStripPath = defaultToolchain.path.join("usr/bin/bitcode_strip") + // Note that we always strip all bitcode (-r), even if 'replace-with-marker' is passed. let result = await pbxcp(["builtin-copy", "-dry-run", "-bitcode-strip", "replace-with-marker", "-bitcode-strip-tool", bitcodeStripPath.str, src.str + Path.pathSeparatorString, dst.str], cwd: Path("/")) #expect(result.success == true) #expect(result.output == ( bitcodeStripPath.str + - " \(src.join("fake-bin").str) -m -o \(dst.join("fake-bin").str)\n")) + " \(src.join("fake-bin").str) -r -o \(dst.join("fake-bin").str)\n")) } } @@ -511,11 +519,12 @@ fileprivate struct PBXCpTests: CoreBasedTests { // Check that we run the bitcode_strip tool and capture its output. Note that bitcode_strip is in the default toolchain, so we need to pass the path to it there. let defaultToolchain = try #require(try await getCore().toolchainRegistry.defaultToolchain) let bitcodeStripPath = defaultToolchain.path.join("usr/bin/bitcode_strip") + // Note that we always strip all bitcode (-r), even if 'replace-with-marker' is passed. let result = await pbxcp(["builtin-copy", "-dry-run", "-strip-unsigned-binaries", "-bitcode-strip", "replace-with-marker", "-bitcode-strip-tool", bitcodeStripPath.str, src.str + Path.pathSeparatorString, dst.str], cwd: Path("/")) #expect(result.success == true) #expect(result.output.contains( bitcodeStripPath.str + - " \(dst.join("fake-bin").str) -m -o \(dst.join("fake-bin").str)\n")) + " \(dst.join("fake-bin").str) -r -o \(dst.join("fake-bin").str)\n")) } } diff --git a/Tests/SWBTaskExecutionTests/ProcessProductEntitlementsTaskActionTests.swift b/Tests/SWBTaskExecutionTests/ProcessProductEntitlementsTaskActionTests.swift index 46e1d58a..0ff0f27f 100644 --- a/Tests/SWBTaskExecutionTests/ProcessProductEntitlementsTaskActionTests.swift +++ b/Tests/SWBTaskExecutionTests/ProcessProductEntitlementsTaskActionTests.swift @@ -16,6 +16,7 @@ import SWBCore import SWBUtil import SWBTaskExecution import SWBMacro +import SWBTestSupport @Suite fileprivate struct ProcessProductEntitlementsTaskActionTests { diff --git a/Tests/SWBTaskExecutionTests/ProcessXCFrameworkLibraryTaskActionTests.swift b/Tests/SWBTaskExecutionTests/ProcessXCFrameworkLibraryTaskActionTests.swift index 86306784..9e7570aa 100644 --- a/Tests/SWBTaskExecutionTests/ProcessXCFrameworkLibraryTaskActionTests.swift +++ b/Tests/SWBTaskExecutionTests/ProcessXCFrameworkLibraryTaskActionTests.swift @@ -38,7 +38,7 @@ fileprivate struct ProcessXCFrameworkLibraryTaskActionTests: CoreBasedTests { try fs.createDirectory(Path(SRCROOT), recursive: true) let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("Support.framework"), binaryPath: Path("Support.framework/Versions/A/Support"), headersPath: nil, debugSymbolsPath: Path("debugSymbols"), bitcodeSymbolMapsPath: Path("BCSymbolMaps")), + XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("Support.framework"), binaryPath: Path("Support.framework/Versions/A/Support"), headersPath: nil, debugSymbolsPath: Path("debugSymbols")), XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("Support.framework"), binaryPath: Path("Support.framework"), headersPath: nil, debugSymbolsPath: Path("debugSymbols")), ]) let supportXCFrameworkPath = Path(SRCROOT).join("Support.xcframework") @@ -67,7 +67,6 @@ fileprivate struct ProcessXCFrameworkLibraryTaskActionTests: CoreBasedTests { // Verify that the debug symbols are in place. #expect(try fs.read(Path(DSTROOT).join("Support.framework.dSYM")) == "fake dsym!") - #expect(try fs.read(Path(DSTROOT).join("Support.framework.bcsymbolmap")) == "fake symbol map!") } } @@ -84,7 +83,7 @@ fileprivate struct ProcessXCFrameworkLibraryTaskActionTests: CoreBasedTests { try fs.createDirectory(Path(SRCROOT), recursive: true) let supportXCFramework = try XCFramework(version: Version(1, 0), libraries: [ - XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs"), bitcodeSymbolMapsPath: Path("symbolmaps")), + XCFramework.Library(libraryIdentifier: "x86_64-apple-macos10.15", supportedPlatform: "macos", supportedArchitectures: ["x86_64"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), XCFramework.Library(libraryIdentifier: "arm64-apple-iphoneos13.0", supportedPlatform: "ios", supportedArchitectures: ["arm64", "arm64e"], platformVariant: nil, libraryPath: Path("libsample.a"), binaryPath: Path("libsample.a"), headersPath: Path("Headers"), debugSymbolsPath: Path("dSYMs")), ]) let supportXCFrameworkPath = Path(SRCROOT).join("libsample.xcframework") @@ -109,7 +108,6 @@ fileprivate struct ProcessXCFrameworkLibraryTaskActionTests: CoreBasedTests { // Verify that the debug symbols are in place. #expect(try fs.read(Path(DSTROOT).join("libsample.a.dSYM")) == "fake dsym!") - #expect(try fs.read(Path(DSTROOT).join("libsample.a.bcsymbolmap")) == "fake symbol map!") // Verify that the headers are in place. #expect(try fs.read(Path(DSTROOT).join("include").join("header1.h")) == "// header 1") diff --git a/Tests/SWBUtilTests/CacheTests.swift b/Tests/SWBUtilTests/CacheTests.swift index 2cdc24fe..7c584010 100644 --- a/Tests/SWBUtilTests/CacheTests.swift +++ b/Tests/SWBUtilTests/CacheTests.swift @@ -13,6 +13,7 @@ import Foundation import Testing import SWBUtil +import Synchronization @Suite fileprivate struct CacheTests { @Test diff --git a/Tests/SWBUtilTests/HashContextTests.swift b/Tests/SWBUtilTests/HashContextTests.swift index 541b9adc..3160b3b4 100644 --- a/Tests/SWBUtilTests/HashContextTests.swift +++ b/Tests/SWBUtilTests/HashContextTests.swift @@ -13,23 +13,24 @@ import Foundation import Testing import SWBUtil +import SWBTestSupport @Suite fileprivate struct HashContextTests { @Test func basics() { - let first = MD5Context() + let first = InsecureHashContext() first.add(string: "first") let firstSignature = first.signature #expect(!firstSignature.isEmpty) - let second = MD5Context() + let second = InsecureHashContext() second.add(string: "first") second.add(string: "second") let secondSignature = second.signature #expect(!secondSignature.isEmpty) #expect(firstSignature != secondSignature) - let third = MD5Context() + let third = InsecureHashContext() third.add(bytes: ByteString("first")) third.add(bytes: ByteString("second")) let thirdSignature = third.signature @@ -39,39 +40,39 @@ import SWBUtil } /// Check against a known hash value. - @Test + @Test(.requireHostOS(.macOS, .windows)) func value() { - #expect(MD5Context().signature == "d41d8cd98f00b204e9800998ecf8427e") + #expect(InsecureHashContext().signature == "d41d8cd98f00b204e9800998ecf8427e") } @Test func variations() { - let first = MD5Context() + let first = InsecureHashContext() first.add(string: "first") - let second = MD5Context() + let second = InsecureHashContext() second.add(bytes: ByteString(encodingAsUTF8: "first")) #expect(first.signature == second.signature) } - @Test + @Test(.requireHostOS(.macOS, .windows)) func numbers() { do { - let ctx = MD5Context() + let ctx = InsecureHashContext() ctx.add(number: 0x01 as UInt8) #expect(ctx.signature == "55a54008ad1ba589aa210d2629c1df41") } do { - let ctx = MD5Context() + let ctx = InsecureHashContext() ctx.add(number: 0x0102 as UInt16) #expect(ctx.signature == "050d144172d916d0846f839e0412e929") } do { - let ctx = MD5Context() + let ctx = InsecureHashContext() ctx.add(number: 0x01020304 as UInt32) #expect(ctx.signature == "c73cabeb6558aba030bba9ca49dcdd75") } do { - let ctx = MD5Context() + let ctx = InsecureHashContext() ctx.add(number: 0x0102030405060708 as UInt64) #expect(ctx.signature == "8a7334bacf760ff26b99fad472ded851") } diff --git a/Tests/SWBUtilTests/HeavyCacheTests.swift b/Tests/SWBUtilTests/HeavyCacheTests.swift index a34d5412..49c496b4 100644 --- a/Tests/SWBUtilTests/HeavyCacheTests.swift +++ b/Tests/SWBUtilTests/HeavyCacheTests.swift @@ -13,6 +13,7 @@ import Foundation import Testing @_spi(Testing) import SWBUtil +import Synchronization @Suite fileprivate struct HeavyCacheTests { @@ -188,16 +189,7 @@ fileprivate struct HeavyCacheTests { /// Provides a HeavyCache suitable for use in tests (eviction policy disabled to prevent memory pressure interference). fileprivate func withHeavyCache(isolatedGlobalState: Bool = true, maximumSize: Int? = nil, timeToLive: Duration? = nil, _ block: (HeavyCache) async throws -> Void) async rethrows { - func withIsolatedGlobalState(block: () async throws -> Void) async rethrows { - if isolatedGlobalState { - try await withHeavyCacheGlobalState { - try await block() - } - } else { - try await block() - } - } - try await withIsolatedGlobalState { + try await withHeavyCacheGlobalState(isolated: isolatedGlobalState) { try await block(HeavyCache(maximumSize: maximumSize, timeToLive: timeToLive, evictionPolicy: .never)) } } diff --git a/Tests/SWBUtilTests/LazyCacheTests.swift b/Tests/SWBUtilTests/LazyCacheTests.swift index d06b2586..5b54da13 100644 --- a/Tests/SWBUtilTests/LazyCacheTests.swift +++ b/Tests/SWBUtilTests/LazyCacheTests.swift @@ -13,6 +13,7 @@ import Foundation import SWBUtil import Testing +import Synchronization @Suite fileprivate struct LazyCacheTests { @Test diff --git a/Tests/SWBUtilTests/PathTests.swift b/Tests/SWBUtilTests/PathTests.swift index 8500774e..3d704983 100644 --- a/Tests/SWBUtilTests/PathTests.swift +++ b/Tests/SWBUtilTests/PathTests.swift @@ -14,6 +14,7 @@ import Foundation import Testing import SWBTestSupport import SWBUtil +import SWBCore @Suite(.skipHostOS(.windows, "path tests need a big overhaul for Windows")) fileprivate struct PathTests { diff --git a/Tests/SWBUtilTests/PathWindowsTests.swift b/Tests/SWBUtilTests/PathWindowsTests.swift new file mode 100644 index 00000000..f81f7afb --- /dev/null +++ b/Tests/SWBUtilTests/PathWindowsTests.swift @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +import Testing +import SWBTestSupport +import SWBUtil + +@Suite(.requireHostOS(.windows)) +fileprivate struct PathWindowsTests { + @Test func testCanonicalPathRepresentation_deviceFiles() throws { + #expect(try "NUL".canonicalPathRepresentation == "\\\\.\\NUL") + #expect(try Path("NUL").canonicalPathRepresentation == "\\\\.\\NUL") + + #expect(try "\\\\.\\NUL".canonicalPathRepresentation == "\\\\.\\NUL") + + // System.FilePath appends a trailing slash to fully qualified device file names + withKnownIssue { () throws -> () in + #expect(try Path("\\\\.\\NUL").canonicalPathRepresentation == "\\\\.\\NUL") + } + } + + @Test func testCanonicalPathRepresentation_driveLetters() throws { + #expect(try Path("C:/").canonicalPathRepresentation == "C:\\") + #expect(try Path("c:/").canonicalPathRepresentation == "c:\\") + + #expect(try Path("\\\\?\\C:/").canonicalPathRepresentation == "C:\\") + #expect(try Path("\\\\?\\c:/").canonicalPathRepresentation == "c:\\") + } + + @Test func testCanonicalPathRepresentation_absolute() throws { + #expect(try Path("C:" + String(repeating: "/foo/bar/baz", count: 21)).canonicalPathRepresentation == "C:" + String(repeating: "\\foo\\bar\\baz", count: 21)) + #expect(try Path("C:" + String(repeating: "/foo/bar/baz", count: 22)).canonicalPathRepresentation == "\\\\?\\C:" + String(repeating: "\\foo\\bar\\baz", count: 22)) + } + + @Test func testCanonicalPathRepresentation_relative() throws { + let root = Path.root.str.dropLast() + #expect(try Path(String(repeating: "/foo/bar/baz", count: 21)).canonicalPathRepresentation == root + String(repeating: "\\foo\\bar\\baz", count: 21)) + #expect(try Path(String(repeating: "/foo/bar/baz", count: 22)).canonicalPathRepresentation == "\\\\?\\" + root + String(repeating: "\\foo\\bar\\baz", count: 22)) + } + + @Test func testCanonicalPathRepresentation_driveRelative() throws { + let current = Path.currentDirectory + + // Ensure the output path will be < 260 characters so we can assert it's not prefixed with \\?\ + let chunks = (260 - current.str.count) / "foo/bar/baz/".count + #expect(current.str.count < 248 && chunks > 0, "The current directory is too long for this test.") + + #expect(try Path(current.str.prefix(2) + String(repeating: "foo/bar/baz/", count: chunks)).canonicalPathRepresentation == current.join(String(repeating: "\\foo\\bar\\baz", count: chunks)).str) + #expect(try Path(current.str.prefix(2) + String(repeating: "foo/bar/baz/", count: 22)).canonicalPathRepresentation == "\\\\?\\" + current.join(String(repeating: "\\foo\\bar\\baz", count: 22)).str) + } +} + +fileprivate extension String { + var canonicalPathRepresentation: String { + get throws { + #if os(Windows) + return try withCString(encodedAs: UTF16.self) { platformPath in + return try platformPath.withCanonicalPathRepresentation { canonicalPath in + return String(decodingCString: canonicalPath, as: UTF16.self) + } + } + #else + return self + #endif + } + } +} + +fileprivate extension Path { + var canonicalPathRepresentation: String { + get throws { + #if os(Windows) + return try withPlatformString { platformPath in + return try platformPath.withCanonicalPathRepresentation { canonicalPath in + return String(decodingCString: canonicalPath, as: UTF16.self) + } + } + #else + return str + #endif + } + } +} diff --git a/Tests/SWBUtilTests/ProcessTests.swift b/Tests/SWBUtilTests/ProcessTests.swift index d4020300..b70660cc 100644 --- a/Tests/SWBUtilTests/ProcessTests.swift +++ b/Tests/SWBUtilTests/ProcessTests.swift @@ -226,13 +226,7 @@ extension SWBUtil.Process { let hostOS = try ProcessInfo.processInfo.hostOperatingSystem() let scriptString = try await script(hostOS) if hostOS == .windows { - // https://github.com/apple/swift-foundation/issues/860 - if ProcessInfo.processInfo.isTranslated { - let systemRoot = try #require(getEnvironmentVariable("SystemRoot"), "Can't determine path to cmd.exe because the SystemRoot environment variable is not set") - commandShellPath = "\(systemRoot)\\SysWOW64\\cmd.exe" - } else { - commandShellPath = try #require(getEnvironmentVariable("ComSpec"), "Can't determine path to cmd.exe because the ComSpec environment variable is not set") - } + commandShellPath = try #require(getEnvironmentVariable("ComSpec"), "Can't determine path to cmd.exe because the ComSpec environment variable is not set") arguments = ["/c", scriptString] } else { commandShellPath = "/bin/sh" diff --git a/Tests/SWBUtilTests/SignaturesTests.swift b/Tests/SWBUtilTests/SignaturesTests.swift index 300cbf7f..ca93d8fd 100644 --- a/Tests/SWBUtilTests/SignaturesTests.swift +++ b/Tests/SWBUtilTests/SignaturesTests.swift @@ -13,6 +13,7 @@ import Foundation import Testing import SWBUtil +import SWBTestSupport @Suite(.requireHostOS(.macOS), .requireSDKs(.macOS)) fileprivate struct SignaturesTests { diff --git a/Tests/SWBUtilTests/VersionTests.swift b/Tests/SWBUtilTests/VersionTests.swift index 7ef9d123..96c46f88 100644 --- a/Tests/SWBUtilTests/VersionTests.swift +++ b/Tests/SWBUtilTests/VersionTests.swift @@ -13,6 +13,7 @@ import Foundation import Testing import SWBUtil +import SWBTestSupport @Suite fileprivate struct VersionTests { func checkEq(_ a: Version, _ b: Version) { diff --git a/Tests/SWBWebAssemblyPlatformTests/SWBWebAssemblyPlatformTests.swift b/Tests/SWBWebAssemblyPlatformTests/SWBWebAssemblyPlatformTests.swift index 274667cc..fcef5cb9 100644 --- a/Tests/SWBWebAssemblyPlatformTests/SWBWebAssemblyPlatformTests.swift +++ b/Tests/SWBWebAssemblyPlatformTests/SWBWebAssemblyPlatformTests.swift @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// import Testing +import SWBCore import SWBProtocol import SWBTestSupport import SWBTaskExecution @@ -19,13 +20,13 @@ import SWBUtil @Suite fileprivate struct SWBWebAssemblyPlatformTests: CoreBasedTests { @Test( + .requireSDKs(.wasi), .requireThreadSafeWorkingDirectory, - .enabled(if: getEnvironmentVariable("WASM_SDKROOT") != nil), + .skipXcodeToolchain, arguments: ["wasm32"], [true, false] ) func wasiCommandWithSwift(arch: String, enableTestability: Bool) async throws { - guard let sdkroot = getEnvironmentVariable("WASM_SDKROOT") else { return } - guard let toolchain = getEnvironmentVariable("WASM_TOOLCHAINS") else { return } + let sdkroot = try await #require(getCore().loadSDK(llvmTargetTripleSys: "wasi")).path.str try await withTemporaryDirectory { (tmpDir: Path) in let testProject = TestProject( @@ -46,7 +47,6 @@ fileprivate struct SWBWebAssemblyPlatformTests: CoreBasedTests { "SDKROOT": sdkroot, "SWIFT_VERSION": "6.0", "SUPPORTED_PLATFORMS": "webassembly", - "TOOLCHAINS": toolchain, "ENABLE_TESTABILITY": enableTestability ? "YES" : "NO" ]) ], @@ -132,10 +132,9 @@ fileprivate struct SWBWebAssemblyPlatformTests: CoreBasedTests { } } - @Test(.requireThreadSafeWorkingDirectory, .enabled(if: getEnvironmentVariable("WASM_SDKROOT") != nil), arguments: ["wasm32"]) + @Test(.requireSDKs(.wasi), .requireThreadSafeWorkingDirectory, .skipXcodeToolchain, arguments: ["wasm32"]) func wasiCommandWithCAndCxx(arch: String) async throws { - guard let sdkroot = getEnvironmentVariable("WASM_SDKROOT") else { return } - guard let toolchain = getEnvironmentVariable("WASM_TOOLCHAINS") else { return } + let sdkroot = try await #require(getCore().loadSDK(llvmTargetTripleSys: "wasi")).path.str try await withTemporaryDirectory { (tmpDir: Path) in let testProject = TestProject( @@ -157,7 +156,6 @@ fileprivate struct SWBWebAssemblyPlatformTests: CoreBasedTests { "SDKROOT": sdkroot, "SWIFT_VERSION": "6.0", "SUPPORTED_PLATFORMS": "webassembly", - "TOOLCHAINS": toolchain, ]) ], targets: [ @@ -252,3 +250,9 @@ fileprivate struct SWBWebAssemblyPlatformTests: CoreBasedTests { } } } + +fileprivate extension Core { + func loadSDK(llvmTargetTripleSys: String) -> SDK? { + sdkRegistry.allSDKs.filter { $0.defaultVariant?.llvmTargetTripleSys == llvmTargetTripleSys }.only + } +} diff --git a/Tests/SWBWindowsPlatformTests/WindowsTestSupport.swift b/Tests/SWBWindowsPlatformTests/WindowsTestSupport.swift index c90ccfed..95226ce5 100644 --- a/Tests/SWBWindowsPlatformTests/WindowsTestSupport.swift +++ b/Tests/SWBWindowsPlatformTests/WindowsTestSupport.swift @@ -12,6 +12,7 @@ import SWBCore @_spi(Testing) import SWBWindowsPlatform +import SWBUtil extension VSInstallation.Component.ID { static let visualCppBuildTools_x86_x64 = Self("Microsoft.VisualStudio.Component.VC.Tools.x86.x64") diff --git a/Tests/SwiftBuildTests/ConsoleCommands/BuildCommandTests.swift b/Tests/SwiftBuildTests/ConsoleCommands/BuildCommandTests.swift index d85a137a..7bb4e1f5 100644 --- a/Tests/SwiftBuildTests/ConsoleCommands/BuildCommandTests.swift +++ b/Tests/SwiftBuildTests/ConsoleCommands/BuildCommandTests.swift @@ -15,6 +15,7 @@ import SWBTestSupport import SwiftBuild import SWBUtil import Testing +import SwiftBuildTestSupport @Suite(.skipHostOS(.windows)) fileprivate struct BuildCommandTests { diff --git a/Tests/SwiftBuildTests/ConsoleCommands/CLIConnection.swift b/Tests/SwiftBuildTests/ConsoleCommands/CLIConnection.swift index c107ba89..5624e529 100644 --- a/Tests/SwiftBuildTests/ConsoleCommands/CLIConnection.swift +++ b/Tests/SwiftBuildTests/ConsoleCommands/CLIConnection.swift @@ -12,7 +12,7 @@ import Foundation import SWBTestSupport -import SWBUtil +@_spi(Testing) import SWBUtil import SWBCore import SWBLibc import SwiftBuild @@ -151,6 +151,10 @@ final class CLIConnection { _ = try? await exitStatus } + // Consume the rest of the output before closing the handle to ensure the dispatch IO is closed + while let _ = try? await outputStreamIterator.next() { + } + try? monitorHandle.close() } @@ -161,11 +165,11 @@ final class CLIConnection { static func terminate(processIdentifier: Int32) throws { #if os(Windows) guard let proc = OpenProcess(DWORD(PROCESS_TERMINATE), false, DWORD(processIdentifier)) else { - throw StubError.error("OpenProcess failed with error \(GetLastError())") + throw Win32Error(GetLastError()) } defer { CloseHandle(proc) } if !TerminateProcess(proc, UINT(0xC0000000 | DWORD(9))) { - throw StubError.error("TerminateProcess returned \(GetLastError())") + throw Win32Error(GetLastError()) } #else if SWBLibc.kill(processIdentifier, SIGKILL) != 0 { @@ -313,27 +317,9 @@ fileprivate func swiftRuntimePath() throws -> Path? { let name = "swiftCore.dll" return try name.withCString(encodedAs: CInterop.PlatformUnicodeEncoding.self) { wName in guard let handle = GetModuleHandleW(wName) else { - throw POSIXError(errno, context: "GetModuleHandleW", name) - } - - var capacity = MAX_PATH - var path = "" - while path.isEmpty { - try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(capacity)) { - let dwLength = GetModuleFileNameW(handle, $0.baseAddress!, DWORD($0.count)) - switch dwLength { - case 0: - throw POSIXError(errno, context: "GetModuleFileNameW", String(dwLength)) - default: - if GetLastError() == ERROR_INSUFFICIENT_BUFFER { - capacity *= 2 - } else { - path = String(decodingCString: $0.baseAddress!, as: CInterop.PlatformUnicodeEncoding.self) - } - } - } + throw Win32Error(GetLastError()) } - return Path(path).dirname + return try Path(SWB_GetModuleFileNameW(handle)).dirname } #else return nil @@ -344,14 +330,16 @@ fileprivate func systemRoot() throws -> Path? { #if os(Windows) let dwLength: DWORD = GetWindowsDirectoryW(nil, 0) if dwLength == 0 { - throw POSIXError(errno, context: "GetWindowsDirectoryW") + throw Win32Error(GetLastError()) } return try withUnsafeTemporaryAllocation(of: WCHAR.self, capacity: Int(dwLength)) { switch GetWindowsDirectoryW($0.baseAddress!, DWORD($0.count)) { + case 1..() #if os(Windows) guard let proc: HANDLE = OpenProcess(SYNCHRONIZE, false, DWORD(pid)) else { - throw StubError.error("OpenProcess failed with error \(GetLastError())") + throw Win32Error(GetLastError()) } defer { CloseHandle(proc) } Thread.detachNewThread { if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED { - promise.fail(throwing: StubError.error("WaitForSingleObject failed with error \(GetLastError())")) + promise.fail(throwing: Win32Error(GetLastError())) return } promise.fulfill(with: ()) diff --git a/Tests/SwiftBuildTests/ConsoleCommands/SessionCommandsTests.swift b/Tests/SwiftBuildTests/ConsoleCommands/SessionCommandsTests.swift index 1e5438f1..6dc5fece 100644 --- a/Tests/SwiftBuildTests/ConsoleCommands/SessionCommandsTests.swift +++ b/Tests/SwiftBuildTests/ConsoleCommands/SessionCommandsTests.swift @@ -12,6 +12,7 @@ import SWBTestSupport import Testing +import SWBUtil @Suite fileprivate struct SessionCommandsTests { diff --git a/Tests/SwiftBuildTests/ConsoleCommands/XcodeCommandsTests.swift b/Tests/SwiftBuildTests/ConsoleCommands/XcodeCommandsTests.swift index e504cf0c..78173376 100644 --- a/Tests/SwiftBuildTests/ConsoleCommands/XcodeCommandsTests.swift +++ b/Tests/SwiftBuildTests/ConsoleCommands/XcodeCommandsTests.swift @@ -12,6 +12,7 @@ import SWBTestSupport import Testing +import SWBUtil @Suite fileprivate struct XcodeCommandsTests { diff --git a/Tests/SwiftBuildTests/IndexingInfoTests.swift b/Tests/SwiftBuildTests/IndexingInfoTests.swift index 1180255f..575ca27a 100644 --- a/Tests/SwiftBuildTests/IndexingInfoTests.swift +++ b/Tests/SwiftBuildTests/IndexingInfoTests.swift @@ -16,6 +16,8 @@ import SwiftBuild import SwiftBuildTestSupport import SWBTestSupport @_spi(Testing) import SWBUtil +import SWBProtocol +import SWBCore // These tests use the old model, ie. the index build arena is disabled. @Suite(.requireHostOS(.macOS)) diff --git a/Utilities/SwiftPM+SwiftBuild.xcworkspace/contents.xcworkspacedata b/Utilities/SwiftPM+SwiftBuild.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..06dfbdf6 --- /dev/null +++ b/Utilities/SwiftPM+SwiftBuild.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + +