diff --git a/Package.resolved b/Package.resolved index b1bbb869b..c2b699d7c 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "2c64b45620932621276e50344e6c5fe6c9d3f5504944717f976fdeef05f66bc5", + "originHash" : "5e56f5e0102d16fcc8dac2f347eeb346b445dfb32ffd8468e54aaa3bc8afc236", "pins" : [ { "identity" : "darwinprivateframeworks", @@ -16,7 +16,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenAttributeGraph", "state" : { "branch" : "main", - "revision" : "6f398f0238e498ce60f98b90e99efdc27b0f0c78" + "revision" : "7c516532e7a11785e383fbee88af834d89cdb981" } }, { @@ -25,7 +25,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenCoreGraphics", "state" : { "branch" : "main", - "revision" : "706d964f419ce293fe1c7afa9b784de0d91f7e9a" + "revision" : "cd89c292c4ed4c25d9468a12d9490cc18304ff37" } }, { @@ -43,7 +43,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenRenderBox", "state" : { "branch" : "main", - "revision" : "a288f586e9ecac85b259d433a795d4104cb929a5" + "revision" : "1e9139ba6f5521e7fc879e410dfc4a67136fea15" } }, { diff --git a/Package.swift b/Package.swift index 7c82eb87c..24e3fc43c 100644 --- a/Package.swift +++ b/Package.swift @@ -1,56 +1,209 @@ // swift-tools-version: 6.1 -// The swift-tools-version declares the minimum version of Swift required to build this package. import CompilerPluginSupport import Foundation import PackageDescription -func envEnable(_ key: String, default defaultValue: Bool = false) -> Bool { - guard let value = Context.environment[key] else { - return defaultValue +// MARK: - EnvManager + +/* GENERATED BY SPMManifestTool BEGIN */ +/* DO NOT EDIT */ + +public protocol EnvironmentProvider { + func value(forKey key: String) -> String? +} + +import PackageDescription +public struct PackageContextEnvironmentProvider: EnvironmentProvider { + public init() {} + + public func value(forKey key: String) -> String? { + Context.environment[key] + } +} + +public final class EnvManager { + nonisolated(unsafe) public static let shared = EnvManager() + + private var domains: [String] = [] + private var environmentProvider: EnvironmentProvider + + /// When true, append raw key as fallback when searching in domains + public var includeFallbackToRawKey: Bool = false + + private init() { + self.environmentProvider = PackageContextEnvironmentProvider() + } + + /// Set a custom environment provider (useful for testing) + public func setEnvironmentProvider(_ provider: EnvironmentProvider) { + self.environmentProvider = provider + } + + /// Reset domains and environment provider (useful for testing) + public func reset() { + domains.removeAll() + includeFallbackToRawKey = false + self.environmentProvider = PackageContextEnvironmentProvider() + } + + public func register(domain: String) { + domains.append(domain) + } + + public func withDomain(_ domain: String, perform: () throws -> T) rethrows -> T { + domains.append(domain) + defer { domains.removeAll { $0 == domain } } + return try perform() } - if value == "1" { - return true - } else if value == "0" { - return false - } else { + + private func envValue(rawKey: String, default defaultValue: T?, searchInDomain: Bool, parser: (String) -> T?) -> T? { + func parseEnvValue(_ key: String) -> (String, T)? { + guard let value = environmentProvider.value(forKey: key), + let result = parser(value) else { return nil } + return (value, result) + } + var keys: [String] = searchInDomain ? domains.map { "\($0.uppercased())_\(rawKey)" } : [] + if !searchInDomain || includeFallbackToRawKey { + keys.append(rawKey) + } + for key in keys { + if let (value, result) = parseEnvValue(key) { + print("[Env] \(key)=\(value) -> \(result)") + return result + } + } + let primaryKey = keys.first ?? rawKey + if let defaultValue { + print("[Env] \(primaryKey) not set -> \(defaultValue)(default)") + } return defaultValue } + + public func envBoolValue(rawKey: String, default defaultValue: Bool? = nil, searchInDomain: Bool) -> Bool? { + envValue(rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { value in + switch value { + case "1": true + case "0": false + default: nil + } + } + } + + public func envIntValue(rawKey: String, default defaultValue: Int? = nil, searchInDomain: Bool) -> Int? { + envValue(rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { Int($0) } + } + + public func envStringValue(rawKey: String, default defaultValue: String? = nil, searchInDomain: Bool) -> String? { + envValue(rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { $0 } + } +} + +public func envBoolValue(_ key: String, default defaultValue: Bool = false, searchInDomain: Bool = true) -> Bool { + EnvManager.shared.envBoolValue(rawKey: key, default: defaultValue, searchInDomain: searchInDomain)! +} + +public func envIntValue(_ key: String, default defaultValue: Int = 0, searchInDomain: Bool = true) -> Int { + EnvManager.shared.envIntValue(rawKey: key, default: defaultValue, searchInDomain: searchInDomain)! } +public func envStringValue(_ key: String, default defaultValue: String, searchInDomain: Bool = true) -> String { + EnvManager.shared.envStringValue(rawKey: key, default: defaultValue, searchInDomain: searchInDomain)! +} + +public func envStringValue(_ key: String, searchInDomain: Bool = true) -> String? { + EnvManager.shared.envStringValue(rawKey: key, searchInDomain: searchInDomain) +} + +/* GENERATED BY SPMManifestTool END */ +EnvManager.shared.register(domain: "OpenSwiftUI") + +// MARK: - Env and config + #if os(macOS) // NOTE: #if os(macOS) check is not accurate if we are cross compiling for Linux platform. So we add an env key to specify it. -let buildForDarwinPlatform = envEnable("OPENSWIFTUI_BUILD_FOR_DARWIN_PLATFORM", default: true) +let buildForDarwinPlatform = envBoolValue("BUILD_FOR_DARWIN_PLATFORM", default: true) #else -let buildForDarwinPlatform = envEnable("OPENSWIFTUI_BUILD_FOR_DARWIN_PLATFORM") +let buildForDarwinPlatform = envBoolValue("BUILD_FOR_DARWIN_PLATFORM") #endif // https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/3061#issuecomment-2118821061 // By-pass https://github.com/swiftlang/swift-package-manager/issues/7580 -let isSPIDocGenerationBuild = envEnable("SPI_GENERATE_DOCS") -let isSPIBuild = envEnable("SPI_BUILD") - -// MARK: - Env and Config - -let isXcodeEnv = Context.environment["__CFBundleIdentifier"] == "com.apple.dt.Xcode" +let isSPIDocGenerationBuild = envBoolValue("SPI_GENERATE_DOCS", searchInDomain: false) +let isSPIBuild = envBoolValue("SPI_BUILD", searchInDomain: false) // Xcode use clang as linker which supports "-iframework" while SwiftPM use swiftc as linker which supports "-Fsystem" let systemFrameworkSearchFlag = isXcodeEnv ? "-iframework" : "-Fsystem" +let isXcodeEnv = envStringValue("__CFBundleIdentifier", searchInDomain: false) == "com.apple.dt.Xcode" +let development = envBoolValue("DEVELOPMENT", default: false) +let warningsAsErrorsCondition = envBoolValue("WERROR", default: isXcodeEnv && development) + +let libSwiftPath = { + // From Swift toolchain being installed or from Swift SDK. + guard let libSwiftPath = envStringValue("LIB_SWIFT_PATH") else { + // Fallback when LIB_SWIFT_PATH is not set + let swiftBinPath = envStringValue("BIN_SWIFT_PATH") ?? envStringValue("_", searchInDomain: false) ?? "/usr/bin/swift" + let swiftBinURL = URL(fileURLWithPath: swiftBinPath) + let SDKPath = swiftBinURL.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent().path + return SDKPath.appending("/usr/lib/swift") + } + return libSwiftPath +}() + +let swiftToolchainPath = envStringValue("SWIFT_TOOLCHAIN_PATH") ?? (development ? "/Volumes/BuildMachine/swift-project" : "") +let swiftToolchainVersion = envStringValue("SWIFT_TOOLCHAIN_VERSION") ?? (development ? "6.0.2" : "") +let swiftToolchainSupported = envBoolValue("SWIFT_TOOLCHAIN_SUPPORTED", default: !swiftToolchainVersion.isEmpty) -let swiftBinPath = Context.environment["_"] ?? "/usr/bin/swift" -let swiftBinURL = URL(fileURLWithPath: swiftBinPath) -let SDKPath = swiftBinURL.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent().path -let includePath = SDKPath.appending("/usr/lib/swift") +let releaseVersion = envIntValue("TARGET_RELEASE", default: 2024) + +let libraryEvolutionCondition = envBoolValue("LIBRARY_EVOLUTION", default: buildForDarwinPlatform) +let compatibilityTestCondition = envBoolValue("COMPATIBILITY_TEST") + +let useLocalDeps = envBoolValue("USE_LOCAL_DEPS") +let attributeGraphCondition = envBoolValue("ATTRIBUTEGRAPH", default: buildForDarwinPlatform && !isSPIBuild) +let renderBoxCondition = envBoolValue("OPENRENDERBOX_RENDERBOX", default: buildForDarwinPlatform && !isSPIBuild) + +// For #39 +let anyAttributeFix = envBoolValue("ANY_ATTRIBUTE_FIX", default: !buildForDarwinPlatform) + +let linkCoreUI = envBoolValue("LINK_COREUI", default: buildForDarwinPlatform && !isSPIBuild) +let linkBacklightServices = envBoolValue("LINK_BACKLIGHTSERVICES", default: buildForDarwinPlatform && !isSPIBuild) +// This should be disabled for UI test target due to link issue of Testing. +// Only enable for non-UI test targets. +let linkTesting = envBoolValue("LINK_TESTING") + +let symbolLocatorCondition = envBoolValue("SYMBOL_LOCATOR", default: buildForDarwinPlatform) +let openCombineCondition = envBoolValue("OPENCOMBINE", default: !buildForDarwinPlatform) +let swiftLogCondition = envBoolValue("SWIFT_LOG", default: !buildForDarwinPlatform) +let swiftCryptoCondition = envBoolValue("SWIFT_CRYPTO", default: !buildForDarwinPlatform) +let renderGTKCondition = envBoolValue("RENDER_GTK", default: !buildForDarwinPlatform) + +let swiftUIRenderCondition = envBoolValue("SWIFTUI_RENDER", default: buildForDarwinPlatform) + +let ignoreAvailability = envBoolValue("IGNORE_AVAILABILITY", default: !isSPIDocGenerationBuild && !compatibilityTestCondition) + +// Run @OpenSwiftUIProject/DarwinPrivateFrameworks repo's Scripts/install_internal_sdk.sh XRSimulator to install internal XRSimulator SDK +let internalXRSDK = envBoolValue("INTERNAL_XR_SDK") +let enablePrivateImports = envBoolValue("ENABLE_PRIVATE_IMPORTS", default: true) +let enableRuntimeConcurrencyCheck = envBoolValue("ENABLE_RUNTIME_CONCURRENCY_CHECK") + +let bridgeFramework = envStringValue("OPENSWIFTUI_BRIDGE_FRAMEWORK", default: "SwiftUI") + +// Workaround iOS CI build issue (We need to disable this on iOS CI) +let supportMultiProducts: Bool = envBoolValue("SUPPORT_MULTI_PRODUCTS", default: true) + +// MARK: - Shared Settings var sharedCSettings: [CSetting] = [ - .unsafeFlags(["-I", includePath], .when(platforms: .nonDarwinPlatforms)), + .unsafeFlags(["-I", libSwiftPath], .when(platforms: .nonDarwinPlatforms)), + .define("NDEBUG", .when(configuration: .release)), .unsafeFlags(["-fmodules"]), .define("__COREFOUNDATION_FORSWIFTFOUNDATIONONLY__", to: "1", .when(platforms: .nonDarwinPlatforms)), .define("_WASI_EMULATED_SIGNAL", .when(platforms: [.wasi])), ] var sharedCxxSettings: [CXXSetting] = [ - .unsafeFlags(["-I", includePath], .when(platforms: .nonDarwinPlatforms)), + .unsafeFlags(["-I", libSwiftPath], .when(platforms: .nonDarwinPlatforms)), .unsafeFlags(["-fcxx-modules"]), .define("__COREFOUNDATION_FORSWIFTFOUNDATIONONLY__", to: "1", .when(platforms: .nonDarwinPlatforms)), .define("_WASI_EMULATED_SIGNAL", .when(platforms: [.wasi])), @@ -60,50 +213,89 @@ var sharedSwiftSettings: [SwiftSetting] = [ .enableUpcomingFeature("BareSlashRegexLiterals"), .enableUpcomingFeature("InternalImportsByDefault"), .enableUpcomingFeature("InferSendableFromCaptures"), + .enableExperimentalFeature("Extern"), // FIXME: -unavailable-decl-optimization=stub is not working somehow (eg. Color.vibrancy). Dig into this later .unsafeFlags(["-unavailable-decl-optimization=stub"]), .swiftLanguageMode(.v5), -] -// MARK: - [env] OPENSWIFTUI_ANY_ATTRIBUTE_FIX + .define("OPENSWIFTUI_RELEASE_\(releaseVersion)"), +] -// For #39 -let anyAttributeFix = envEnable("OPENSWIFTUI_ANY_ATTRIBUTE_FIX", default: !buildForDarwinPlatform) -if anyAttributeFix { - sharedSwiftSettings.append(.define("OPENSWIFTUI_ANY_ATTRIBUTE_FIX")) +// Modified from: https://github.com/swiftlang/swift/blob/main/SwiftCompilerSources/Package.swift +// +// Create a couple of symlinks to an existing Ninja build: +// +// ```shell +// cd $OPENSWIFTUI_SWIFT_TOOLCHAIN_PATH +// mkdir -p build/Default +// ln -s build//llvm- build/Default/llvm +// ln -s build//swift- build/Default/swift +// ``` +// +// where <$OPENSWIFTUI_SWIFT_TOOLCHAIN_PATH> is the parent directory of the swift repository. + +if !swiftToolchainPath.isEmpty { + sharedCSettings.append( + .unsafeFlags( + [ + "-static", + "-DCOMPILED_WITH_SWIFT", + "-DPURE_BRIDGING_MODE", + "-UIBOutlet", "-UIBAction", "-UIBInspectable", + "-I\(swiftToolchainPath)/swift/include", + "-I\(swiftToolchainPath)/swift/stdlib/public/SwiftShims", + "-I\(swiftToolchainPath)/llvm-project/llvm/include", + "-I\(swiftToolchainPath)/llvm-project/clang/include", + "-I\(swiftToolchainPath)/build/Default/swift/include", + "-I\(swiftToolchainPath)/build/Default/llvm/include", + "-I\(swiftToolchainPath)/build/Default/llvm/tools/clang/include", + "-DLLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING", // Required to fix LLVM link issue + ] + ) + ) } - -// MARK: - [env] OPENSWIFTUI_TARGET_RELEASE - -let releaseVersion = Context.environment["OPENSWIFTUI_TARGET_RELEASE"].flatMap { Int($0) } ?? 2024 -sharedCSettings.append(.define("OPENSWIFTUI_RELEASE", to: "\(releaseVersion)")) -sharedSwiftSettings.append(.define("OPENSWIFTUI_RELEASE_\(releaseVersion)")) -if releaseVersion >= 2024 { - for year in 2024 ... releaseVersion { +if !swiftToolchainVersion.isEmpty { + sharedCSettings.append( + .define("OPENSWIFTUI_SWIFT_TOOLCHAIN_VERSION", to: swiftToolchainVersion) + ) +} +if swiftToolchainSupported { + sharedCSettings.append(.define("OPENSWIFTUI_SWIFT_TOOLCHAIN_SUPPORTED")) + sharedSwiftSettings.append(.define("OPENSWIFTUI_SWIFT_TOOLCHAIN_SUPPORTED")) +} +if releaseVersion >= 2021 { + for year in 2021 ... releaseVersion { sharedSwiftSettings.append(.define("OPENSWIFTUI_SUPPORT_\(year)_API")) } } +if warningsAsErrorsCondition { + sharedSwiftSettings.append(.unsafeFlags(["-warnings-as-errors"])) +} +if libraryEvolutionCondition { + // NOTE: -enable-library-evolution will cause module verify failure for `swift build`. + // Either set OPENSWIFTUI_LIBRARY_EVOLUTION=0 or add `-Xswiftc -no-verify-emitted-module-interface` after `swift build` + sharedSwiftSettings.append(.unsafeFlags(["-enable-library-evolution", "-no-verify-emitted-module-interface"])) +} +if !compatibilityTestCondition { + sharedCSettings.append(.define("OPENSWIFTUI")) + sharedCxxSettings.append(.define("OPENSWIFTUI")) + sharedSwiftSettings.append(.define("OPENSWIFTUI")) +} -// MARK: - [env] OPENSWIFTUI_DEVELOPMENT - -let development = envEnable("OPENSWIFTUI_DEVELOPMENT") +if anyAttributeFix { + sharedSwiftSettings.append(.define("OPENSWIFTUI_ANY_ATTRIBUTE_FIX")) +} if development { sharedSwiftSettings.append(.define("OPENSWIFTUI_DEVELOPMENT")) } -// MARK: - [env] OPENSWIFTUI_LINK_COREUI - -let linkCoreUI = envEnable("OPENSWIFTUI_LINK_COREUI", default: buildForDarwinPlatform && !isSPIBuild) sharedCSettings.append(.define("OPENSWIFTUI_LINK_COREUI", to: linkCoreUI ? "1" : "0")) sharedCxxSettings.append(.define("OPENSWIFTUI_LINK_COREUI", to: linkCoreUI ? "1" : "0")) if linkCoreUI { sharedSwiftSettings.append(.define("OPENSWIFTUI_LINK_COREUI")) } -// MARK: - [env] OPENSWIFTUI_LINK_BACKLIGHTSERVICES - -let linkBacklightServices = envEnable("OPENSWIFTUI_LINK_BACKLIGHTSERVICES", default: buildForDarwinPlatform && !isSPIBuild) sharedCSettings.append( .define( "OPENSWIFTUI_LINK_BACKLIGHTSERVICES", @@ -127,56 +319,16 @@ if linkBacklightServices { ) } -// MARK: - [env] OPENGSWIFTUI_SYMBOL_LOCATOR - -let symbolLocatorCondition = envEnable("OPENGSWIFTUI_SYMBOL_LOCATOR", default: buildForDarwinPlatform) - -// MARK: - [env] OPENSWIFTUI_OPENCOMBINE - -let openCombineCondition = envEnable("OPENSWIFTUI_OPENCOMBINE", default: !buildForDarwinPlatform) - -// MARK: - [env] OPENSWIFTUI_SWIFT_LOG - -let swiftLogCondition = envEnable("OPENSWIFTUI_SWIFT_LOG", default: !buildForDarwinPlatform) - -// MARK: - [env] OPENSWIFTUI_SWIFT_CRYPTO - -let swiftCryptoCondition = envEnable("OPENSWIFTUI_SWIFT_CRYPTO", default: !buildForDarwinPlatform) - -// MARK: - [env] OPENSWIFTUI_RENDER_GTK - -let renderGTKCondition = envEnable("OPENSWIFTUI_RENDER_GTK", default: !buildForDarwinPlatform) - -let cgtkTarget = Target.systemLibrary( - name: "CGTK", - pkgConfig: "gtk4", - providers: [ - .brew(["gtk4"]), - .apt(["libgtk-4-dev clang"]), - ] -) - -// MARK: - [env] OPENGSWIFTUI_SWIFTUI_RENDER - -let swiftUIRenderCondition = envEnable("OPENSWIFTUI_SWIFTUI_RENDER", default: buildForDarwinPlatform) if swiftUIRenderCondition { sharedCSettings.append(.define("_OPENSWIFTUI_SWIFTUI_RENDER")) sharedCxxSettings.append(.define("_OPENSWIFTUI_SWIFTUI_RENDER")) sharedSwiftSettings.append(.define("_OPENSWIFTUI_SWIFTUI_RENDER")) } -// MARK: - [env] OPENSWIFTUI_LINK_TESTING - -// This should be disabled for UI test target due to link issue of Testing. -// Only enable for non-UI test targets. -let linkTesting = envEnable("OPENSWIFTUI_LINK_TESTING") if linkTesting { sharedSwiftSettings.append(.define("OPENSWIFTUI_LINK_TESTING")) } -// MARK: - [env] OPENSWIFTUI_WERROR - -let warningsAsErrorsCondition = envEnable("OPENSWIFTUI_WERROR", default: isXcodeEnv && development) if warningsAsErrorsCondition { // Hold off the werror feature as we can't avoid the concurrency warning. // Since there is no such group for diagnostic we want to ignore, we enable werror for all known groups instead. @@ -197,54 +349,148 @@ if warningsAsErrorsCondition { sharedSwiftSettings.append(.unsafeFlags(["-Wwarning", "DeprecatedDeclaration"])) // We want to use deprecated APIs in test targets) } -// MARK: - [env] OPENSWIFTUI_LIBRARY_EVOLUTION - -let libraryEvolutionCondition = envEnable("OPENSWIFTUI_LIBRARY_EVOLUTION", default: buildForDarwinPlatform) if libraryEvolutionCondition && !openCombineCondition && !swiftLogCondition { // NOTE: -enable-library-evolution will cause module verify failure for `swift build`. // Either set OPENSWIFTUI_LIBRARY_EVOLUTION=0 or add `-Xswiftc -no-verify-emitted-module-interface` after `swift build` sharedSwiftSettings.append(.unsafeFlags(["-enable-library-evolution", "-no-verify-emitted-module-interface"])) } -// MARK: - [env] OPENSWIFTUI_COMPATIBILITY_TEST - -let compatibilityTestCondition = envEnable("OPENSWIFTUI_COMPATIBILITY_TEST") -sharedCSettings.append(.define("OPENSWIFTUI", to: compatibilityTestCondition ? "1" : "0")) -sharedCxxSettings.append(.define("OPENSWIFTUI", to: compatibilityTestCondition ? "1" : "0")) if !compatibilityTestCondition { sharedSwiftSettings.append(.define("OPENSWIFTUI")) } -// MARK: - [env] OPENSWIFTUI_IGNORE_AVAILABILITY - -let ignoreAvailability = envEnable("OPENSWIFTUI_IGNORE_AVAILABILITY", default: !isSPIDocGenerationBuild && !compatibilityTestCondition) sharedSwiftSettings.append(contentsOf: [SwiftSetting].availabilityMacroSettings(ignoreAvailability: ignoreAvailability)) -// MARK: - [env] OPENSWIFTUI_INTERNAL_XR_SDK - -// Run @OpenSwiftUIProject/DarwinPrivateFrameworks repo's Scripts/install_internal_sdk.sh XRSimulator to install internal XRSimulator SDK -let internalXRSDK = envEnable("OPENSWIFTUI_INTERNAL_XR_SDK") sharedCSettings.append(.define("OPENSWIFTUI_INTERNAL_XR_SDK", to: internalXRSDK ? "1" : "0")) sharedCxxSettings.append(.define("OPENSWIFTUI_INTERNAL_XR_SDK", to: internalXRSDK ? "1" : "0")) if internalXRSDK { sharedSwiftSettings.append(.define("OPENSWIFTUI_INTERNAL_XR_SDK")) } -// MARK: - [env] OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS - -let enablePrivateImports = envEnable("OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS", default: true) if enablePrivateImports { sharedSwiftSettings.append(.define("OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS")) sharedSwiftSettings.append(.unsafeFlags(["-Xfrontend", "-enable-private-imports"])) } -// MARK: - [env] OPENSWIFTUI_ENABLE_RUNTIME_CONCURRENCY_CHECK - -let enableRuntimeConcurrencyCheck = envEnable("OPENSWIFTUI_ENABLE_RUNTIME_CONCURRENCY_CHECK", default: false) if enableRuntimeConcurrencyCheck { sharedSwiftSettings.append(.define("OPENSWIFTUI_ENABLE_RUNTIME_CONCURRENCY_CHECK")) } +// MARK: - Extension + +extension Target { + func addAGSettings() { + // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message + // "could not determine executable path for bundle 'AttributeGraph.framework'" + dependencies.append(.product(name: "AttributeGraph", package: "DarwinPrivateFrameworks")) + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH")) + self.swiftSettings = swiftSettings + } + + func addRBSettings() { + // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message + // "could not determine executable path for bundle 'RenderBox.framework'" + dependencies.append(.product(name: "RenderBox", package: "DarwinPrivateFrameworks")) + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENRENDERBOX_RENDERBOX")) + self.swiftSettings = swiftSettings + } + + func addCoreUISettings() { + // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message + // "could not determine executable path for bundle 'CoreUI.framework'" + dependencies.append(.product(name: "CoreUI", package: "DarwinPrivateFrameworks")) + } + + func addBacklightServicesSettings() { + // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message + // "could not determine executable path for bundle 'BacklightServices.framework'" + dependencies.append( + .product( + name: "BacklightServices", + package: "DarwinPrivateFrameworks", + condition: .when(platforms: [.iOS, .visionOS]) + ) + ) + } + + func addOpenCombineSettings() { + dependencies.append(.product(name: "OpenCombine", package: "OpenCombine")) + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENSWIFTUI_OPENCOMBINE")) + self.swiftSettings = swiftSettings + } + + func addSwiftLogSettings() { + dependencies.append(.product(name: "Logging", package: "swift-log")) + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENSWIFTUI_SWIFT_LOG")) + self.swiftSettings = swiftSettings + } + + func addSwiftCryptoSettings() { + dependencies.append(.product(name: "Crypto", package: "swift-crypto")) + var swiftSettings = swiftSettings ?? [] + swiftSettings.append(.define("OPENSWIFTUI_SWIFT_CRYPTO")) + self.swiftSettings = swiftSettings + } +} + +extension [Platform] { + static var darwinPlatforms: [Platform] { + [.macOS, .iOS, .macCatalyst, .tvOS, .watchOS, .visionOS] + } + + static var nonDarwinPlatforms: [Platform] { + [.linux, .android, .wasi, .openbsd, .windows] + } +} + +extension [SwiftSetting] { + /// Settings which define commonly-used OS availability macros. + /// + /// These leverage a pseudo-experimental feature in the Swift compiler for + /// setting availability definitions, which was added in + /// [swift#65218](https://github.com/swiftlang/swift/pull/65218). + fileprivate static func availabilityMacroSettings(ignoreAvailability: Bool) -> Self { + let minimumVersion = "iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, visionOS 1.0" + return [ + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v1_0:\(ignoreAvailability ? minimumVersion : "iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v1_4:\(ignoreAvailability ? minimumVersion : "iOS 13.4, macOS 10.15.4, tvOS 13.4, watchOS 6.2")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_0:\(ignoreAvailability ? minimumVersion : "iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_1:\(ignoreAvailability ? minimumVersion : "iOS 14.2, macOS 11.0, tvOS 14.1, watchOS 7.1")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_3:\(ignoreAvailability ? minimumVersion : "iOS 14.5, macOS 11.3, tvOS 14.5, watchOS 7.4")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_0:\(ignoreAvailability ? minimumVersion : "iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_2:\(ignoreAvailability ? minimumVersion : "iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_4:\(ignoreAvailability ? minimumVersion : "iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_0:\(ignoreAvailability ? minimumVersion : "iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_1:\(ignoreAvailability ? minimumVersion : "iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_4:\(ignoreAvailability ? minimumVersion : "iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_0:\(ignoreAvailability ? minimumVersion : "iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_1:\(ignoreAvailability ? minimumVersion : "iOS 17.1, macOS 14.1, tvOS 17.1, watchOS 10.1, visionOS 1.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_2:\(ignoreAvailability ? minimumVersion : "iOS 17.2, macOS 14.2, tvOS 17.2, watchOS 10.2, visionOS 1.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_4:\(ignoreAvailability ? minimumVersion : "iOS 17.4, macOS 14.4, tvOS 17.4, watchOS 10.4, visionOS 1.1")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v6_0:\(ignoreAvailability ? minimumVersion : "iOS 18.0, macOS 15.0, tvOS 18.0, watchOS 11.0, visionOS 2.0")"), + .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v7_0:\(ignoreAvailability ? minimumVersion : "iOS 19.0, macOS 16.0, tvOS 19.0, watchOS 12.0, visionOS 3.0")"), + .enableExperimentalFeature("AvailabilityMacro=_distantFuture:iOS 99.0, macOS 99.0, tvOS 99.0, watchOS 99.0, visionOS 99.0"), + ] + } +} + +// MARK: - Targets + +// MARK: - CGTK Target + +let cgtkTarget = Target.systemLibrary( + name: "CGTK", + pkgConfig: "gtk4", + providers: [ + .brew(["gtk4"]), + .apt(["libgtk-4-dev clang"]), + ] +) + // MARK: - OpenSwiftUISPI Target let openSwiftUISPITarget = Target.target( @@ -397,10 +643,6 @@ let openSwiftUICompatibilityTestTarget = Target.testTarget( swiftSettings: sharedSwiftSettings ) -// MARK: - [env] OPENSWIFTUI_BRIDGE_FRAMEWORK - -let bridgeFramework = Context.environment["OPENSWIFTUI_BRIDGE_FRAMEWORK"] ?? "SwiftUI" - // MARK: - OpenSwiftUIBridge Target let openSwiftUIBridgeTarget = Target.target( @@ -456,11 +698,10 @@ let openSwiftUISymbolDualTestsTarget = Target.testTarget( swiftSettings: sharedSwiftSettings ) -// Workaround iOS CI build issue (We need to disable this on iOS CI) -let supportMultiProducts: Bool = envEnable("OPENSWIFTUI_SUPPORT_MULTI_PRODUCTS", default: true) +// MARK: - Products let libraryType: Product.Library.LibraryType? -switch Context.environment["OPENSWIFTUI_LIBRARY_TYPE"] { +switch envStringValue("LIBRARY_TYPE") { case "dynamic": libraryType = .dynamic case "static": @@ -481,6 +722,8 @@ if supportMultiProducts { ] } +// MARK: - Package + let package = Package( name: "OpenSwiftUI", products: products, @@ -518,8 +761,6 @@ if buildForDarwinPlatform { package.targets.append(openSwiftUICompatibilityTestTarget) } -// MARK: - SymbolLocator - if symbolLocatorCondition { package.dependencies.append( .package(url: "https://github.com/OpenSwiftUIProject/SymbolLocator.git", from: "0.2.0") @@ -532,68 +773,6 @@ if symbolLocatorCondition { } } -extension Target { - func addAGSettings() { - // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message - // "could not determine executable path for bundle 'AttributeGraph.framework'" - dependencies.append(.product(name: "AttributeGraph", package: "DarwinPrivateFrameworks")) - var swiftSettings = swiftSettings ?? [] - swiftSettings.append(.define("OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH")) - self.swiftSettings = swiftSettings - } - - func addRBSettings() { - // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message - // "could not determine executable path for bundle 'RenderBox.framework'" - dependencies.append(.product(name: "RenderBox", package: "DarwinPrivateFrameworks")) - var swiftSettings = swiftSettings ?? [] - swiftSettings.append(.define("OPENRENDERBOX_RENDERBOX")) - self.swiftSettings = swiftSettings - } - - func addCoreUISettings() { - // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message - // "could not determine executable path for bundle 'CoreUI.framework'" - dependencies.append(.product(name: "CoreUI", package: "DarwinPrivateFrameworks")) - } - - func addBacklightServicesSettings() { - // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message - // "could not determine executable path for bundle 'BacklightServices.framework'" - dependencies.append( - .product( - name: "BacklightServices", - package: "DarwinPrivateFrameworks", - condition: .when(platforms: [.iOS, .visionOS]) - ) - ) - } - - func addOpenCombineSettings() { - dependencies.append(.product(name: "OpenCombine", package: "OpenCombine")) - var swiftSettings = swiftSettings ?? [] - swiftSettings.append(.define("OPENSWIFTUI_OPENCOMBINE")) - self.swiftSettings = swiftSettings - } - - func addSwiftLogSettings() { - dependencies.append(.product(name: "Logging", package: "swift-log")) - var swiftSettings = swiftSettings ?? [] - swiftSettings.append(.define("OPENSWIFTUI_SWIFT_LOG")) - self.swiftSettings = swiftSettings - } - - func addSwiftCryptoSettings() { - dependencies.append(.product(name: "Crypto", package: "swift-crypto")) - var swiftSettings = swiftSettings ?? [] - swiftSettings.append(.define("OPENSWIFTUI_SWIFT_CRYPTO")) - self.swiftSettings = swiftSettings - } -} - -let useLocalDeps = envEnable("OPENSWIFTUI_USE_LOCAL_DEPS") - -let attributeGraphCondition = envEnable("OPENATTRIBUTEGRAPH_ATTRIBUTEGRAPH", default: buildForDarwinPlatform && !isSPIBuild) if attributeGraphCondition { openSwiftUICoreTarget.addAGSettings() openSwiftUITarget.addAGSettings() @@ -605,7 +784,6 @@ if attributeGraphCondition { openSwiftUIBridgeTestTarget.addAGSettings() } -let renderBoxCondition = envEnable("OPENRENDERBOX_RENDERBOX", default: buildForDarwinPlatform && !isSPIBuild) if renderBoxCondition { openSwiftUICoreTarget.addRBSettings() openSwiftUITarget.addRBSettings() @@ -686,44 +864,3 @@ if swiftCryptoCondition { openSwiftUICoreTarget.addSwiftCryptoSettings() openSwiftUITarget.addSwiftCryptoSettings() } - -extension [Platform] { - static var darwinPlatforms: [Platform] { - [.macOS, .iOS, .macCatalyst, .tvOS, .watchOS, .visionOS] - } - - static var nonDarwinPlatforms: [Platform] { - [.linux, .android, .wasi, .openbsd, .windows] - } -} - -extension [SwiftSetting] { - /// Settings which define commonly-used OS availability macros. - /// - /// These leverage a pseudo-experimental feature in the Swift compiler for - /// setting availability definitions, which was added in - /// [swift#65218](https://github.com/swiftlang/swift/pull/65218). - fileprivate static func availabilityMacroSettings(ignoreAvailability: Bool) -> Self { - let minimumVersion = "iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, visionOS 1.0" - return [ - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v1_0:\(ignoreAvailability ? minimumVersion : "iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v1_4:\(ignoreAvailability ? minimumVersion : "iOS 13.4, macOS 10.15.4, tvOS 13.4, watchOS 6.2")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_0:\(ignoreAvailability ? minimumVersion : "iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_1:\(ignoreAvailability ? minimumVersion : "iOS 14.2, macOS 11.0, tvOS 14.1, watchOS 7.1")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_3:\(ignoreAvailability ? minimumVersion : "iOS 14.5, macOS 11.3, tvOS 14.5, watchOS 7.4")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_0:\(ignoreAvailability ? minimumVersion : "iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_2:\(ignoreAvailability ? minimumVersion : "iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_4:\(ignoreAvailability ? minimumVersion : "iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_0:\(ignoreAvailability ? minimumVersion : "iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_1:\(ignoreAvailability ? minimumVersion : "iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_4:\(ignoreAvailability ? minimumVersion : "iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_0:\(ignoreAvailability ? minimumVersion : "iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_1:\(ignoreAvailability ? minimumVersion : "iOS 17.1, macOS 14.1, tvOS 17.1, watchOS 10.1, visionOS 1.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_2:\(ignoreAvailability ? minimumVersion : "iOS 17.2, macOS 14.2, tvOS 17.2, watchOS 10.2, visionOS 1.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_4:\(ignoreAvailability ? minimumVersion : "iOS 17.4, macOS 14.4, tvOS 17.4, watchOS 10.4, visionOS 1.1")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v6_0:\(ignoreAvailability ? minimumVersion : "iOS 18.0, macOS 15.0, tvOS 18.0, watchOS 11.0, visionOS 2.0")"), - .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v7_0:\(ignoreAvailability ? minimumVersion : "iOS 19.0, macOS 16.0, tvOS 19.0, watchOS 12.0, visionOS 3.0")"), - .enableExperimentalFeature("AvailabilityMacro=_distantFuture:iOS 99.0, macOS 99.0, tvOS 99.0, watchOS 99.0, visionOS 99.0"), - ] - } -}