From f3154c9b4a9d177374e408be3c794a681bee7742 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 12 Jun 2025 12:06:39 -0700 Subject: [PATCH] build: introduce `SWIFTPM_BUILD_ONLY_TESTS` support This adds support for an environment variable to exclude all dependencies from being built. We can externally pass in the appropriate include and library search paths allowing us to control the build and share the artifacts from the previous build reducing overall cost in CI. --- Package.swift | 875 ++++++++++++++++++++++++++------------------------ 1 file changed, 459 insertions(+), 416 deletions(-) diff --git a/Package.swift b/Package.swift index ea1fef7cb88..1c6f3dc6206 100644 --- a/Package.swift +++ b/Package.swift @@ -15,141 +15,151 @@ import class Foundation.ProcessInfo import PackageDescription -// When building the toolchain on the CI for ELF platforms, remove the CI's -// stdlib absolute runpath and add ELF's $ORIGIN relative paths before installing. -let swiftpmLinkSettings: [LinkerSetting] -let packageLibraryLinkSettings: [LinkerSetting] -if let resourceDirPath = ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RPATH_OS"] { - swiftpmLinkSettings = [.unsafeFlags([ - "-no-toolchain-stdlib-rpath", - "-Xlinker", "-rpath", - "-Xlinker", "$ORIGIN/../lib/swift/\(resourceDirPath)", - ])] - packageLibraryLinkSettings = [.unsafeFlags([ - "-no-toolchain-stdlib-rpath", - "-Xlinker", "-rpath", - "-Xlinker", "$ORIGIN/../../\(resourceDirPath)", - ])] -} else { - swiftpmLinkSettings = [] - packageLibraryLinkSettings = [] +func defined(_ variable: String) -> Bool { + ProcessInfo.processInfo.environment[variable] != nil } -// Common experimental flags to be added to all targets. -let commonExperimentalFeatures: [SwiftSetting] = [ - .enableExperimentalFeature("MemberImportVisibility"), -] - -// Certain targets fail to compile with MemberImportVisibility enabled on 6.0.3 -// but work with >=6.1. These targets opt in to using `swift6CompatibleExperimentalFeatures`. -#if swift(>=6.1) -let swift6CompatibleExperimentalFeatures = commonExperimentalFeatures -#else -let swift6CompatibleExperimentalFeatures: [SwiftSetting] = [] -#endif +var buildOnlyTests: Bool { + defined("SWIFTPM_BUILD_ONLY_TESTS") +} -/** SwiftPMDataModel is the subset of SwiftPM product that includes just its data model. - This allows some clients (such as IDEs) that use SwiftPM's data model but not its build system - to not have to depend on SwiftDriver, SwiftLLBuild, etc. We should probably have better names here, - though that could break some clients. - */ -let swiftPMDataModelProduct = ( - name: "SwiftPMDataModel", - targets: [ - "PackageCollections", - "PackageCollectionsModel", - "PackageGraph", - "PackageLoading", - "PackageMetadata", - "PackageModel", - "PackageModelSyntax", - "SourceControl", - "Workspace", - ] -) +var useLocalDependencies: Bool { + defined("SWIFTCI_USE_LOCAL_DEPS") +} -/** The `libSwiftPM` set of interfaces to programmatically work with Swift - packages. `libSwiftPM` includes all of the SwiftPM code except the - command line tools, while `libSwiftPMDataModel` includes only the data model. +var useLLBuildFramework: Bool { + defined("SWIFTPM_LLBUILD_FWK") +} - NOTE: This API is *unstable* and may change at any time. - */ -let swiftPMProduct = ( - name: "SwiftPM", - targets: swiftPMDataModelProduct.targets + [ - "Build", - "LLBuildManifest", - "SourceKitLSPAPI", - "SPMLLBuild", - "SwiftBuildSupport", - ] -) +var useSwiftBuildFramework: Bool { + defined("SWIFTPM_SWBUILD_FRAMEWORK") +} +var includeDynamicLibrary: Bool { #if os(Windows) -let includeDynamicLibrary: Bool = false -let systemSQLitePkgConfig: String? = nil + false #else -let includeDynamicLibrary: Bool = true -var systemSQLitePkgConfig: String? = "sqlite3" -if ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RPATH_OS"] == "android" { - systemSQLitePkgConfig = nil -} + true #endif +} -/** An array of products which have two versions listed: one dynamically linked, the other with the - automatic linking type with `-auto` suffix appended to product's name. - */ -let autoProducts = [swiftPMProduct, swiftPMDataModelProduct] +@MainActor +func LLBuildDependency(_ dependencies: [T] = []) -> [T] { + if useLLBuildFramework { return [] } + return dependencies +} + +@MainActor +func SwiftBuildDependency(_ dependencies: [T] = []) -> [T] { + if useSwiftBuildFramework { return [] } + return dependencies +} -let shoudUseSwiftBuildFramework = (ProcessInfo.processInfo.environment["SWIFTPM_SWBUILD_FRAMEWORK"] != nil) +// MARK: - Dependencies + +var dependencies: [Package.Dependency] { + if buildOnlyTests { return [] } + + if useLocalDependencies { + return [ + .package(path: "../swift-argument-parser"), + .package(path: "../swift-crypto"), + .package(path: "../swift-syntax"), + .package(path: "../swift-system"), + .package(path: "../swift-collections"), + .package(path: "../swift-certificates"), + .package(path: "../swift-toolchain-sqlite"), + ] + LLBuildDependency([ + .package(name: "swift-llbuild", path: "../llbuild"), + ]) + SwiftBuildDependency([ + .package(path: "../swift-build"), + .package(path: "../swift-tools-support-core"), + .package(path: "../swift-driver"), + ]) + } -let swiftDriverDeps: [Target.Dependency] -let swiftTSCBasicsDeps: [Target.Dependency] -let swiftToolsCoreSupportAutoDeps: [Target.Dependency] -let swiftTSCTestSupportDeps: [Target.Dependency] + /// When not using local dependencies, the branch to use for llbuild and TSC + /// repositories. + let relatedDependenciesBranch = "main" -if shoudUseSwiftBuildFramework { - swiftDriverDeps = [] - swiftTSCBasicsDeps = [] - swiftToolsCoreSupportAutoDeps = [] - swiftTSCTestSupportDeps = [] -} else { - swiftDriverDeps = [ - .product(name: "SwiftDriver", package: "swift-driver") - ] - swiftTSCBasicsDeps = [ - .product(name: "TSCBasic", package: "swift-tools-support-core"), - ] - swiftToolsCoreSupportAutoDeps = [ - .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core") - ] - swiftTSCTestSupportDeps = [ - .product(name: "TSCTestSupport", package: "swift-tools-support-core"), - ] + return [ + // The 'swift-argument-parser' version declared here must match that + // used by 'swift-driver' and 'sourcekit-lsp'. Please coordinate + // dependency version changes here with those projects. + .package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.5.1")), + .package(url: "https://github.com/apple/swift-crypto.git", .upToNextMinor(from: "3.0.0")), + .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: relatedDependenciesBranch), + .package(url: "https://github.com/apple/swift-system.git", from: "1.1.1"), + .package(url: "https://github.com/apple/swift-collections.git", "1.0.1" ..< "1.2.0"), + .package(url: "https://github.com/apple/swift-certificates.git", "1.0.1" ..< "1.6.0"), + .package(url: "https://github.com/swiftlang/swift-toolchain-sqlite.git", from: "1.0.0"), + + // For use in previewing documentation + .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0"), + ] + LLBuildDependency([ + .package(url: "https://github.com/swiftlang/swift-llbuild.git", branch: relatedDependenciesBranch), + ]) + SwiftBuildDependency([ + .package(url: "https://github.com/swiftlang/swift-build.git", branch: relatedDependenciesBranch), + .package(url: "https://github.com/swiftlang/swift-tools-support-core.git", branch: relatedDependenciesBranch), + .package(url: "https://github.com/swiftlang/swift-driver.git", branch: relatedDependenciesBranch), + ]) } -let package = Package( - name: "SwiftPM", - platforms: [ - .macOS(.v13), - .iOS(.v17), - .macCatalyst(.v17), - ], - products: - autoProducts.flatMap { - (includeDynamicLibrary ? [ + +// MARK: - Products + +var products: [Product] { + if buildOnlyTests { return [] } + + /** + SwiftPMDataModel is the subset of SwiftPM product that includes just its data + model. This allows some clients (such as IDEs) that use SwiftPM's data model + but not its build system to not have to depend on SwiftDriver, SwiftLLBuild, + etc. We should probably have better names here, though that could break some + clients. + **/ + let swiftPMDataModelProduct = ( + name: "SwiftPMDataModel", + targets: [ + "PackageCollections", + "PackageCollectionsModel", + "PackageGraph", + "PackageLoading", + "PackageMetadata", + "PackageModel", + "PackageModelSyntax", + "SourceControl", + "Workspace", + ] + ) + + /** + The `libSwiftPM` set of interfaces to programmatically work with Swift + packages. `libSwiftPM` includes all of the SwiftPM code except the command + line tools, while `libSwiftPMDataModel` includes only the data model. + + NOTE: This API is *unstable* and may change at any time. + **/ + let swiftPMProduct = ( + name: "SwiftPM", + targets: swiftPMDataModelProduct.targets + [ + "Build", + "LLBuildManifest", + "SourceKitLSPAPI", + "SPMLLBuild", + "SwiftBuildSupport", + ] + ) + + return [swiftPMDataModelProduct, swiftPMProduct].flatMap { + [ + .library(name: "\($0.name)-auto", targets: $0.targets), + ] + (includeDynamicLibrary ? [ .library( name: $0.name, type: .dynamic, targets: $0.targets ), ] : []) - + - [ - .library( - name: "\($0.name)-auto", - targets: $0.targets - ), - ] } + [ .library( name: "XCBuildSupport", @@ -184,8 +194,13 @@ let package = Package( "PackageModel", ] ), - ], - targets: [ + ] +} + +// MARK: - Targets + +var targets: [Target] { + var _targets: [Target] = [ // The `PackageDescription` target provides the API that is available // to `Package.swift` manifests. Here we build a debug version of the // library; the bootstrap scripts build the deployable version. @@ -199,6 +214,10 @@ let package = Package( ], linkerSettings: packageLibraryLinkSettings ), + .testTarget( + name: "PackageDescriptionTests", + dependencies: ["PackageDescription"] + ), // The `AppleProductTypes` target provides additional product types // to `Package.swift` manifests. Here we build a debug version of the @@ -227,6 +246,10 @@ let package = Package( ], linkerSettings: packageLibraryLinkSettings ), + .testTarget( + name: "PackagePluginAPITests", + dependencies: ["PackagePlugin", "_InternalTestSupport"] + ), .target( name: "SourceKitLSPAPI", @@ -244,6 +267,13 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "SourceKitLSPAPITests", + dependencies: [ + "SourceKitLSPAPI", + "_InternalTestSupport", + ] + ), // MARK: SwiftPM specific support libraries @@ -262,6 +292,13 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "_AsyncFileSystemTests", + dependencies: [ + "_AsyncFileSystem", + "_InternalTestSupport", + ] + ), .target( name: "Basics", @@ -272,7 +309,9 @@ let package = Package( .product(name: "DequeModule", package: "swift-collections"), .product(name: "OrderedCollections", package: "swift-collections"), .product(name: "SystemPackage", package: "swift-system"), - ] + swiftToolsCoreSupportAutoDeps, + ] + SwiftBuildDependency([ + .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core") + ]), exclude: ["CMakeLists.txt", "Vendor/README.md"], swiftSettings: swift6CompatibleExperimentalFeatures + [ .enableExperimentalFeature("StrictConcurrency"), @@ -280,6 +319,33 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "BasicsTests", + dependencies: [ + "Basics", + "_InternalTestSupport", + "tsan_utils", + ], + exclude: [ + "Archiver/Inputs/archive.tar.gz", + "Archiver/Inputs/archive.zip", + "Archiver/Inputs/invalid_archive.tar.gz", + "Archiver/Inputs/invalid_archive.zip", + "processInputs/long-stdout-stderr", + "processInputs/long-stdout-stderr.bat", + "processInputs/exit4", + "processInputs/exit4.bat", + "processInputs/simple-stdout-stderr", + "processInputs/simple-stdout-stderr.bat", + "processInputs/deadlock-if-blocking-io", + "processInputs/deadlock-if-blocking-io.bat", + "processInputs/echo", + "processInputs/echo.bat", + "processInputs/in-to-out", + "processInputs/in-to-out.bat", + ] + ), + .target( /** The llbuild manifest model */ @@ -290,6 +356,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "LLBuildManifestTests", + dependencies: ["Basics", "LLBuildManifest", "_InternalTestSupport"] + ), .target( /** Package registry support */ @@ -306,6 +376,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageRegistryTests", + dependencies: ["_InternalTestSupport", "PackageRegistry"] + ), .target( /** Source control operations */ @@ -319,11 +393,18 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "SourceControlTests", + dependencies: ["SourceControl", "_InternalTestSupport"], + exclude: ["Inputs/TestRepo.tgz"] + ), .target( /** Shim for llbuild library */ name: "SPMLLBuild", - dependencies: ["Basics"], + dependencies: ["Basics"] + LLBuildDependency([ + .product(name: "llbuildSwift", package: "swift-llbuild"), + ]), exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ .unsafeFlags(["-static"]), @@ -335,7 +416,9 @@ let package = Package( name: "SwiftFixIt", dependencies: [ "Basics", - ] + swiftTSCBasicsDeps + swiftSyntaxDependencies( + ] + SwiftBuildDependency([ + .product(name: "TSCBasic", package: "swift-tools-support-core"), + ]) + swiftSyntaxDependencies( ["SwiftDiagnostics", "SwiftIDEUtils", "SwiftParser", "SwiftSyntax"] ), exclude: ["CMakeLists.txt"], @@ -343,18 +426,28 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "SwiftFixItTests", + dependencies: ["SwiftFixIt", "_InternalTestSupport"] + ), .target( /** API for inspecting symbols defined in binaries */ name: "BinarySymbols", dependencies: [ "Basics", - ] + swiftTSCBasicsDeps, + ] + SwiftBuildDependency([ + .product(name: "TSCBasic", package: "swift-tools-support-core"), + ]), exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "BinarySymbolsTests", + dependencies: ["BinarySymbols", "_InternalTestSupport"] + ), // MARK: Project Model @@ -367,6 +460,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageModelTests", + dependencies: ["PackageModel", "_InternalTestSupport"] + ), .target( /** Primary Package model objects relationship to SwiftSyntax */ @@ -381,6 +478,13 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageModelSyntaxTests", + dependencies: [ + "PackageModelSyntax", + "_InternalTestSupport", + ] + swiftSyntaxDependencies(["SwiftIDEUtils"]) + ), .target( /** Package model conventions and loading support */ @@ -395,6 +499,11 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageLoadingTests", + dependencies: ["PackageLoading", "_InternalTestSupport"], + exclude: ["Inputs", "pkgconfigInputs"] + ), // MARK: Package Dependency Resolution @@ -412,6 +521,11 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageGraphTests", + dependencies: ["PackageGraph", "_InternalTestSupport"], + swiftSettings: commonExperimentalFeatures + ), // MARK: Package Collections @@ -427,6 +541,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageCollectionsModelTests", + dependencies: ["PackageCollectionsModel", "_InternalTestSupport"] + ), .target( /** Data structures and support for package collections */ @@ -443,6 +561,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageCollectionsTests", + dependencies: ["PackageCollections", "_InternalTestSupport", "tsan_utils"] + ), .target( name: "PackageCollectionsSigning", @@ -457,6 +579,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageCollectionsSigningTests", + dependencies: ["PackageCollectionsSigning", "_InternalTestSupport"] + ), .target( name: "PackageFingerprint", @@ -469,6 +595,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageFingerprintTests", + dependencies: ["PackageFingerprint", "_InternalTestSupport"] + ), .target( name: "PackageSigning", @@ -483,6 +613,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "PackageSigningTests", + dependencies: ["_InternalTestSupport", "PackageSigning"] + ), // MARK: Documentation @@ -506,6 +640,11 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "SPMBuildCoreTests", + dependencies: ["SPMBuildCore", "_InternalTestSupport"] + ), + .target( /** Builds Modules and Products */ name: "Build", @@ -517,23 +656,33 @@ let package = Package( "SPMLLBuild", .product(name: "OrderedCollections", package: "swift-collections"), "DriverSupport", - ] + swiftDriverDeps, + ] + SwiftBuildDependency([ + .product(name: "SwiftDriver", package: "swift-driver") + ]), exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "BuildTests", + dependencies: ["Build", "PackageModel", "Commands", "_InternalTestSupport", "_InternalBuildTestSupport"] + ), + .target( name: "DriverSupport", dependencies: [ "Basics", "PackageModel", - ] + swiftDriverDeps, + ] + SwiftBuildDependency([ + .product(name: "SwiftDriver", package: "swift-driver") + ]), exclude: ["CMakeLists.txt"], swiftSettings: commonExperimentalFeatures + [ .unsafeFlags(["-static"]), ] ), + .target( /** Support for building using Xcode's build system */ name: "XCBuildSupport", @@ -547,15 +696,26 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "XCBuildSupportTests", + dependencies: ["XCBuildSupport", "_InternalTestSupport", "_InternalBuildTestSupport"], + exclude: ["Inputs/Foo.pc"] + ), + .target( name: "SwiftBuildSupport", dependencies: [ "SPMBuildCore", "PackageGraph", - ], + ] + SwiftBuildDependency([ + .product(name: "SwiftBuild", package: "swift-build"), + // This is here to statically link the build service in the same executable as SwiftPM + .product(name: "SWBBuildService", package: "swift-build"), + ]), exclude: ["CMakeLists.txt", "README.md"], swiftSettings: commonExperimentalFeatures ), + .target( /** High level functionality */ name: "Workspace", @@ -575,6 +735,11 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "WorkspaceTests", + dependencies: ["Workspace", "_InternalTestSupport"] + ), + .target( // ** High level interface for package discovery */ name: "PackageMetadata", @@ -704,6 +869,10 @@ let package = Package( .unsafeFlags(["-static"]), ] ), + .testTarget( + name: "QueryEngineTests", + dependencies: ["QueryEngine", "_InternalTestSupport"] + ), .executableTarget( /** The main executable provided by SwiftPM */ @@ -711,12 +880,14 @@ let package = Package( dependencies: ["Basics", "Commands"], exclude: ["CMakeLists.txt"] ), + .executableTarget( /** Builds packages */ name: "swift-build", dependencies: ["Commands"], exclude: ["CMakeLists.txt"] ), + .executableTarget( /** Builds SwiftPM itself for bootstrapping (minimal version of `swift-build`) */ name: "swift-bootstrap", @@ -733,35 +904,41 @@ let package = Package( ], exclude: ["CMakeLists.txt"] ), + .executableTarget( /** Interacts with Swift SDKs used for cross-compilation */ name: "swift-sdk", dependencies: ["Commands", "SwiftSDKCommand"], exclude: ["CMakeLists.txt"] ), + .executableTarget( /** Deprecated command superseded by `swift-sdk` */ name: "swift-experimental-sdk", dependencies: ["Commands", "SwiftSDKCommand"], exclude: ["CMakeLists.txt"] ), + .executableTarget( /** Runs package tests */ name: "swift-test", dependencies: ["Commands"], exclude: ["CMakeLists.txt"] ), + .executableTarget( /** Runs an executable product */ name: "swift-run", dependencies: ["Commands"], exclude: ["CMakeLists.txt"] ), + .executableTarget( /** Interacts with package collections */ name: "swift-package-collection", dependencies: ["Commands", "PackageCollectionsCommand"] ), + .executableTarget( /** Multi-command entry point for SwiftPM. */ name: "swift-package-manager", @@ -774,11 +951,13 @@ let package = Package( ], linkerSettings: swiftpmLinkSettings ), + .executableTarget( /** Interact with package registry */ name: "swift-package-registry", dependencies: ["Commands", "PackageRegistryCommand"] ), + .executableTarget( /** Utility to produce the artifacts for prebuilts */ name: "swift-build-prebuilts", @@ -803,19 +982,19 @@ let package = Package( // MARK: Additional Test Dependencies - .target( - /** SwiftPM internal build test suite support library */ - name: "_InternalBuildTestSupport", - dependencies: [ - "Build", - "XCBuildSupport", - "SwiftBuildSupport", - "_InternalTestSupport" - ], - swiftSettings: [ - .unsafeFlags(["-static"]), - ] - ), + .target( + /** SwiftPM internal build test suite support library */ + name: "_InternalBuildTestSupport", + dependencies: [ + "Build", + "XCBuildSupport", + "SwiftBuildSupport", + "_InternalTestSupport" + ], + swiftSettings: [ + .unsafeFlags(["-static"]), + ] + ), .target( /** SwiftPM internal test suite support library */ @@ -830,7 +1009,9 @@ let package = Package( "SourceControl", .product(name: "OrderedCollections", package: "swift-collections"), "Workspace", - ] + swiftTSCTestSupportDeps, + ] + SwiftBuildDependency([ + .product(name: "TSCTestSupport", package: "swift-tools-support-core"), + ]), swiftSettings: [ .unsafeFlags(["-static"]), ] @@ -855,89 +1036,6 @@ let package = Package( // MARK: SwiftPM tests - .testTarget( - name: "_AsyncFileSystemTests", - dependencies: [ - "_AsyncFileSystem", - "_InternalTestSupport", - ] - ), - - .testTarget( - name: "SourceKitLSPAPITests", - dependencies: [ - "SourceKitLSPAPI", - "_InternalTestSupport", - ] - ), - - .testTarget( - name: "BasicsTests", - dependencies: [ - "Basics", - "_InternalTestSupport", - "tsan_utils", - ], - exclude: [ - "Archiver/Inputs/archive.tar.gz", - "Archiver/Inputs/archive.zip", - "Archiver/Inputs/invalid_archive.tar.gz", - "Archiver/Inputs/invalid_archive.zip", - "processInputs/long-stdout-stderr", - "processInputs/long-stdout-stderr.bat", - "processInputs/exit4", - "processInputs/exit4.bat", - "processInputs/simple-stdout-stderr", - "processInputs/simple-stdout-stderr.bat", - "processInputs/deadlock-if-blocking-io", - "processInputs/deadlock-if-blocking-io.bat", - "processInputs/echo", - "processInputs/echo.bat", - "processInputs/in-to-out", - "processInputs/in-to-out.bat", - ] - ), - .testTarget( - name: "BuildTests", - dependencies: ["Build", "PackageModel", "Commands", "_InternalTestSupport", "_InternalBuildTestSupport"] - ), - .testTarget( - name: "LLBuildManifestTests", - dependencies: ["Basics", "LLBuildManifest", "_InternalTestSupport"] - ), - .testTarget( - name: "WorkspaceTests", - dependencies: ["Workspace", "_InternalTestSupport"] - ), - .testTarget( - name: "PackageDescriptionTests", - dependencies: ["PackageDescription"] - ), - .testTarget( - name: "SPMBuildCoreTests", - dependencies: ["SPMBuildCore", "_InternalTestSupport"] - ), - .testTarget( - name: "PackageLoadingTests", - dependencies: ["PackageLoading", "_InternalTestSupport"], - exclude: ["Inputs", "pkgconfigInputs"] - ), - .testTarget( - name: "PackageModelTests", - dependencies: ["PackageModel", "_InternalTestSupport"] - ), - .testTarget( - name: "PackageModelSyntaxTests", - dependencies: [ - "PackageModelSyntax", - "_InternalTestSupport", - ] + swiftSyntaxDependencies(["SwiftIDEUtils"]) - ), - .testTarget( - name: "PackageGraphTests", - dependencies: ["PackageGraph", "_InternalTestSupport"], - swiftSettings: commonExperimentalFeatures - ), .testTarget( name: "PackageGraphPerformanceTests", dependencies: ["PackageGraph", "_InternalTestSupport"], @@ -948,56 +1046,7 @@ let package = Package( "Inputs/kitura.json", ] ), - .testTarget( - name: "PackageCollectionsModelTests", - dependencies: ["PackageCollectionsModel", "_InternalTestSupport"] - ), - .testTarget( - name: "PackageCollectionsSigningTests", - dependencies: ["PackageCollectionsSigning", "_InternalTestSupport"] - ), - .testTarget( - name: "PackageCollectionsTests", - dependencies: ["PackageCollections", "_InternalTestSupport", "tsan_utils"] - ), - .testTarget( - name: "PackageFingerprintTests", - dependencies: ["PackageFingerprint", "_InternalTestSupport"] - ), - .testTarget( - name: "PackagePluginAPITests", - dependencies: ["PackagePlugin", "_InternalTestSupport"] - ), - .testTarget( - name: "PackageRegistryTests", - dependencies: ["_InternalTestSupport", "PackageRegistry"] - ), - .testTarget( - name: "PackageSigningTests", - dependencies: ["_InternalTestSupport", "PackageSigning"] - ), - .testTarget( - name: "QueryEngineTests", - dependencies: ["QueryEngine", "_InternalTestSupport"] - ), - .testTarget( - name: "SourceControlTests", - dependencies: ["SourceControl", "_InternalTestSupport"], - exclude: ["Inputs/TestRepo.tgz"] - ), - .testTarget( - name: "SwiftFixItTests", - dependencies: ["SwiftFixIt", "_InternalTestSupport"] - ), - .testTarget( - name: "BinarySymbolsTests", - dependencies: ["BinarySymbols", "_InternalTestSupport"] - ), - .testTarget( - name: "XCBuildSupportTests", - dependencies: ["XCBuildSupport", "_InternalTestSupport", "_InternalBuildTestSupport"], - exclude: ["Inputs/Foo.pc"] - ), + .testTarget( name: "FunctionalPerformanceTests", dependencies: [ @@ -1005,13 +1054,151 @@ let package = Package( "_InternalTestSupport", ] ), + // Examples (These are built to ensure they stay up to date with the API.) .executableTarget( name: "package-info", dependencies: ["Workspace"], path: "Examples/package-info/Sources/package-info" ) + ] + + // rdar://101868275 "error: cannot find 'XCTAssertEqual' in scope" can + // affect almost any functional test, so we flat out disable them all until + // we know what is going on + if !defined("SWIFTCI_DISABLE_SDK_DEPENDENT_TESTS") { + _targets.append(contentsOf: [ + .testTarget( + name: "FunctionalTests", + dependencies: [ + "swift-package-manager", + "PackageModel", + "_InternalTestSupport", + ] + ), + .executableTarget( + name: "dummy-swiftc", + dependencies: [ + "Basics", + ] + ), + .testTarget( + name: "_InternalTestSupportTests", + dependencies: [ + "_InternalTestSupport" + ] + ), + .testTarget( + name: "IntegrationTests", + dependencies: [ + "_IntegrationTestSupport", + "_InternalTestSupport", + .product(name: "TSCTestSupport", package: "swift-tools-support-core"), + .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"), + ], + ), + .testTarget( + name: "CommandsTests", + dependencies: [ + "swift-package-manager", + "Basics", + "Build", + "Commands", + "PackageModel", + "PackageModelSyntax", + "PackageRegistryCommand", + "SourceControl", + "_InternalTestSupport", + "Workspace", + "dummy-swiftc", + ] + ), + ]) + } + + if buildOnlyTests { + return _targets.compactMap { target in + guard target.isTest || target.name.contains("TestSupport") else { + return nil + } + + // X509 needs to be built for testable import + if target.name == "PackageSigningTests" || + // this seems to be causing hangs on Windows + target.name == "PackageRegistryTests" { + return nil + } + + target.dependencies = target.dependencies.filter { dependency in + if case .byNameItem(name: let name, _) = dependency, + name.contains("TestSupport") { + return true + } + return false + } + + return target + } + } + return _targets +} + + +// When building the toolchain on the CI for ELF platforms, remove the CI's != +// nil +// stdlib absolute runpath and add ELF's $ORIGIN relative paths before installing. +let swiftpmLinkSettings: [LinkerSetting] +let packageLibraryLinkSettings: [LinkerSetting] +if let resourceDirPath = ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RPATH_OS"] { + swiftpmLinkSettings = [.unsafeFlags([ + "-no-toolchain-stdlib-rpath", + "-Xlinker", "-rpath", + "-Xlinker", "$ORIGIN/../lib/swift/\(resourceDirPath)", + ])] + packageLibraryLinkSettings = [.unsafeFlags([ + "-no-toolchain-stdlib-rpath", + "-Xlinker", "-rpath", + "-Xlinker", "$ORIGIN/../../\(resourceDirPath)", + ])] +} else { + swiftpmLinkSettings = [] + packageLibraryLinkSettings = [] +} + +// Common experimental flags to be added to all targets. +let commonExperimentalFeatures: [SwiftSetting] = [ + .enableExperimentalFeature("MemberImportVisibility"), +] + +// Certain targets fail to compile with MemberImportVisibility enabled on 6.0.3 +// but work with >=6.1. These targets opt in to using `swift6CompatibleExperimentalFeatures`. +#if swift(>=6.1) +let swift6CompatibleExperimentalFeatures = commonExperimentalFeatures +#else +let swift6CompatibleExperimentalFeatures: [SwiftSetting] = [] +#endif + + + +#if os(Windows) +let systemSQLitePkgConfig: String? = nil +#else +var systemSQLitePkgConfig: String? = "sqlite3" +if ProcessInfo.processInfo.environment["SWIFTCI_INSTALL_RPATH_OS"] == "android" { + systemSQLitePkgConfig = nil +} +#endif + +let package = Package( + name: "SwiftPM", + platforms: [ + .macOS(.v13), + .iOS(.v17), + .macCatalyst(.v17), ], + products: products, + dependencies: dependencies, + targets: targets, swiftLanguageModes: [.v5] ) @@ -1023,58 +1210,6 @@ package.targets.append(contentsOf: [ ]) #endif -// rdar://101868275 "error: cannot find 'XCTAssertEqual' in scope" can affect almost any functional test, so we flat out -// disable them all until we know what is going on -if ProcessInfo.processInfo.environment["SWIFTCI_DISABLE_SDK_DEPENDENT_TESTS"] == nil { - package.targets.append(contentsOf: [ - .testTarget( - name: "FunctionalTests", - dependencies: [ - "swift-package-manager", - "PackageModel", - "_InternalTestSupport", - ] - ), - .executableTarget( - name: "dummy-swiftc", - dependencies: [ - "Basics", - ] - ), - .testTarget( - name: "_InternalTestSupportTests", - dependencies: [ - "_InternalTestSupport" - ] - ), - .testTarget( - name: "IntegrationTests", - dependencies: [ - "_IntegrationTestSupport", - "_InternalTestSupport", - .product(name: "TSCTestSupport", package: "swift-tools-support-core"), - .product(name: "SwiftToolsSupport-auto", package: "swift-tools-support-core"), - ], - ), - .testTarget( - name: "CommandsTests", - dependencies: [ - "swift-package-manager", - "Basics", - "Build", - "Commands", - "PackageModel", - "PackageModelSyntax", - "PackageRegistryCommand", - "SourceControl", - "_InternalTestSupport", - "Workspace", - "dummy-swiftc", - ] - ), - ]) -} - func swiftSyntaxDependencies(_ names: [String]) -> [Target.Dependency] { /// Whether swift-syntax is being built as a single dynamic library instead of as a separate library per module. @@ -1082,7 +1217,7 @@ func swiftSyntaxDependencies(_ names: [String]) -> [Target.Dependency] { /// This means that the swift-syntax symbols don't need to be statically linked, which allows us to stay below the /// maximum number of exported symbols on Windows, in turn allowing us to build sourcekit-lsp using SwiftPM on Windows /// and run its tests. - let buildDynamicSwiftSyntaxLibrary = ProcessInfo.processInfo.environment["SWIFTSYNTAX_BUILD_DYNAMIC_LIBRARY"] != nil + let buildDynamicSwiftSyntaxLibrary = defined("SWIFTSYNTAX_BUILD_DYNAMIC_LIBRARY") if buildDynamicSwiftSyntaxLibrary { return [.product(name: "_SwiftSyntaxDynamic", package: "swift-syntax")] } else { @@ -1090,101 +1225,9 @@ func swiftSyntaxDependencies(_ names: [String]) -> [Target.Dependency] { } } -// Add package dependency on llbuild when not bootstrapping. -// -// When bootstrapping SwiftPM, we can't use llbuild as a package dependency it -// will provided by whatever build system (SwiftCI, bootstrap script) is driving -// the build process. So, we only add these dependencies if SwiftPM is being -// built directly using SwiftPM. It is a bit unfortunate that we've add the -// package dependency like this but there is no other good way of expressing -// this right now. - -/// When not using local dependencies, the branch to use for llbuild and TSC repositories. -let relatedDependenciesBranch = "main" - -if ProcessInfo.processInfo.environment["SWIFTPM_LLBUILD_FWK"] == nil { - if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { - package.dependencies += [ - .package(url: "https://github.com/swiftlang/swift-llbuild.git", branch: relatedDependenciesBranch), - ] - } else { - // In Swift CI, use a local path to llbuild to interoperate with tools - // like `update-checkout`, which control the sources externally. - package.dependencies += [ - .package(name: "swift-llbuild", path: "../llbuild"), - ] - } - package.targets.first(where: { $0.name == "SPMLLBuild" })!.dependencies += [ - .product(name: "llbuildSwift", package: "swift-llbuild"), - ] -} - -if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { - package.dependencies += [ - // The 'swift-argument-parser' version declared here must match that - // used by 'swift-driver' and 'sourcekit-lsp'. Please coordinate - // dependency version changes here with those projects. - .package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.5.1")), - .package(url: "https://github.com/apple/swift-crypto.git", .upToNextMinor(from: "3.0.0")), - .package(url: "https://github.com/swiftlang/swift-syntax.git", branch: relatedDependenciesBranch), - .package(url: "https://github.com/apple/swift-system.git", from: "1.1.1"), - .package(url: "https://github.com/apple/swift-collections.git", "1.0.1" ..< "1.2.0"), - .package(url: "https://github.com/apple/swift-certificates.git", "1.0.1" ..< "1.6.0"), - .package(url: "https://github.com/swiftlang/swift-toolchain-sqlite.git", from: "1.0.0"), - // For use in previewing documentation - .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0"), - ] - if !swiftDriverDeps.isEmpty { - package.dependencies += [ - .package(url: "https://github.com/swiftlang/swift-tools-support-core.git", branch: relatedDependenciesBranch), - .package(url: "https://github.com/swiftlang/swift-driver.git", branch: relatedDependenciesBranch), - ] - } -} else { - package.dependencies += [ - .package(path: "../swift-argument-parser"), - .package(path: "../swift-crypto"), - .package(path: "../swift-syntax"), - .package(path: "../swift-system"), - .package(path: "../swift-collections"), - .package(path: "../swift-certificates"), - .package(path: "../swift-toolchain-sqlite"), - ] - if !swiftDriverDeps.isEmpty { - package.dependencies += [ - .package(path: "../swift-tools-support-core"), - .package(path: "../swift-driver"), - ] - } - -} - /// If ENABLE_APPLE_PRODUCT_TYPES is set in the environment, then also define ENABLE_APPLE_PRODUCT_TYPES in each of the regular targets and test targets. if ProcessInfo.processInfo.environment["ENABLE_APPLE_PRODUCT_TYPES"] == "1" { for target in package.targets.filter({ $0.type == .regular || $0.type == .test }) { target.swiftSettings = (target.swiftSettings ?? []) + [ .define("ENABLE_APPLE_PRODUCT_TYPES") ] } } - -if !shoudUseSwiftBuildFramework { - - let swiftbuildsupport: Target = package.targets.first(where: { $0.name == "SwiftBuildSupport" } )! - swiftbuildsupport.dependencies += [ - .product(name: "SwiftBuild", package: "swift-build"), - ] - - swiftbuildsupport.dependencies += [ - // This is here to statically link the build service in the same executable as SwiftPM - .product(name: "SWBBuildService", package: "swift-build"), - ] - - if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil { - package.dependencies += [ - .package(url: "https://github.com/swiftlang/swift-build.git", branch: relatedDependenciesBranch), - ] - } else { - package.dependencies += [ - .package(path: "../swift-build"), - ] - } -}