33import Foundation
44import PackageDescription
55
6- func envEnable( _ key: String , default defaultValue: Bool = false ) -> Bool {
7- guard let value = Context . environment [ key] else {
8- return defaultValue
6+ // MARK: - Env Manager
7+
8+ /* GENERATED BY SPMManifestTool BEGIN */
9+ /* DO NOT EDIT */
10+
11+ public protocol EnvironmentProvider {
12+ func value( forKey key: String ) -> String ?
13+ }
14+
15+ import PackageDescription
16+ public struct PackageContextEnvironmentProvider : EnvironmentProvider {
17+ public init ( ) { }
18+
19+ public func value( forKey key: String ) -> String ? {
20+ Context . environment [ key]
921 }
10- if value == " 1 " {
11- return true
12- } else if value == " 0 " {
13- return false
14- } else {
22+ }
23+
24+ // MARK: - Env Manager
25+
26+ public final class EnvManager {
27+ nonisolated ( unsafe) public static let shared = EnvManager ( )
28+
29+ private var domains : [ String ] = [ ]
30+ private var environmentProvider : EnvironmentProvider
31+
32+ /// When true, append raw key as fallback when searching in domains
33+ public var includeFallbackToRawKey : Bool = false
34+
35+ private init ( ) {
36+ self . environmentProvider = PackageContextEnvironmentProvider ( )
37+ }
38+
39+ /// Set a custom environment provider (useful for testing)
40+ public func setEnvironmentProvider( _ provider: EnvironmentProvider ) {
41+ self . environmentProvider = provider
42+ }
43+
44+ /// Reset domains and environment provider (useful for testing)
45+ public func reset( ) {
46+ domains. removeAll ( )
47+ includeFallbackToRawKey = false
48+ self . environmentProvider = PackageContextEnvironmentProvider ( )
49+ }
50+
51+ public func register( domain: String ) {
52+ domains. append ( domain)
53+ }
54+
55+ public func withDomain< T> ( _ domain: String , perform: ( ) throws -> T ) rethrows -> T {
56+ domains. append ( domain)
57+ defer { domains. removeAll { $0 == domain } }
58+ return try perform ( )
59+ }
60+
61+ private func envValue< T> ( rawKey: String , default defaultValue: T ? , searchInDomain: Bool , parser: ( String ) -> T ? ) -> T ? {
62+ func parseEnvValue( _ key: String ) -> ( String , T ) ? {
63+ guard let value = environmentProvider. value ( forKey: key) ,
64+ let result = parser ( value) else { return nil }
65+ return ( value, result)
66+ }
67+ var keys : [ String ] = searchInDomain ? domains. map { " \( $0. uppercased ( ) ) _ \( rawKey) " } : [ ]
68+ if !searchInDomain || includeFallbackToRawKey {
69+ keys. append ( rawKey)
70+ }
71+ for key in keys {
72+ if let ( value, result) = parseEnvValue ( key) {
73+ print ( " [Env] \( key) = \( value) -> \( result) " )
74+ return result
75+ }
76+ }
77+ let primaryKey = keys. first ?? rawKey
78+ if let defaultValue {
79+ print ( " [Env] \( primaryKey) not set -> \( defaultValue) (default) " )
80+ }
1581 return defaultValue
1682 }
83+
84+ public func envBoolValue( rawKey: String , default defaultValue: Bool ? = nil , searchInDomain: Bool ) -> Bool ? {
85+ envValue ( rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { value in
86+ switch value {
87+ case " 1 " : true
88+ case " 0 " : false
89+ default : nil
90+ }
91+ }
92+ }
93+
94+ public func envIntValue( rawKey: String , default defaultValue: Int ? = nil , searchInDomain: Bool ) -> Int ? {
95+ envValue ( rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { Int ( $0) }
96+ }
97+
98+ public func envStringValue( rawKey: String , default defaultValue: String ? = nil , searchInDomain: Bool ) -> String ? {
99+ envValue ( rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { $0 }
100+ }
101+ }
102+
103+ public func envBoolValue( _ key: String , default defaultValue: Bool = false , searchInDomain: Bool = true ) -> Bool {
104+ EnvManager . shared. envBoolValue ( rawKey: key, default: defaultValue, searchInDomain: searchInDomain) !
105+ }
106+
107+ public func envIntValue( _ key: String , default defaultValue: Int = 0 , searchInDomain: Bool = true ) -> Int {
108+ EnvManager . shared. envIntValue ( rawKey: key, default: defaultValue, searchInDomain: searchInDomain) !
109+ }
110+
111+ public func envStringValue( _ key: String , default defaultValue: String , searchInDomain: Bool = true ) -> String {
112+ EnvManager . shared. envStringValue ( rawKey: key, default: defaultValue, searchInDomain: searchInDomain) !
113+ }
114+
115+ public func envStringValue( _ key: String , searchInDomain: Bool = true ) -> String ? {
116+ EnvManager . shared. envStringValue ( rawKey: key, searchInDomain: searchInDomain)
17117}
18118
119+ /* GENERATED BY SPMManifestTool END */
120+ EnvManager . shared. register ( domain: " OpenRenderBox " )
121+ EnvManager . shared. register ( domain: " OpenSwiftUI " )
122+
123+ // MARK: - Env and config
124+
19125#if os(macOS)
20126// 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.
21- let buildForDarwinPlatform = envEnable ( " OPENSWIFTUI_BUILD_FOR_DARWIN_PLATFORM " , default: true )
127+ let buildForDarwinPlatform = envBoolValue ( " BUILD_FOR_DARWIN_PLATFORM " , default: true )
22128#else
23- let buildForDarwinPlatform = envEnable ( " OPENSWIFTUI_BUILD_FOR_DARWIN_PLATFORM " )
129+ let buildForDarwinPlatform = envBoolValue ( " BUILD_FOR_DARWIN_PLATFORM " )
24130#endif
25131
26132// https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/3061#issuecomment-2118821061
27133// By-pass https://github.com/swiftlang/swift-package-manager/issues/7580
28- let isSPIDocGenerationBuild = envEnable ( " SPI_GENERATE_DOCS " , default : false )
29- let isSPIBuild = envEnable ( " SPI_BUILD " )
134+ let isSPIDocGenerationBuild = envBoolValue ( " SPI_GENERATE_DOCS " , searchInDomain : false )
135+ let isSPIBuild = envBoolValue ( " SPI_BUILD " , searchInDomain : false )
30136
31- // MARK: - Env and Config
137+ let isXcodeEnv = envStringValue ( " __CFBundleIdentifier " , searchInDomain: false ) == " com.apple.dt.Xcode "
138+ let development = envBoolValue ( " DEVELOPMENT " , default: false )
32139
33- let isXcodeEnv = Context . environment [ " __CFBundleIdentifier " ] == " com.apple.dt.Xcode "
34- let development = envEnable ( " OPENRENDERBOX_DEVELOPMENT " )
140+ let releaseVersion = envIntValue ( " TARGET_RELEASE " , default: 2024 )
141+
142+ let libSwiftPath = {
143+ // From Swift toolchain being installed or from Swift SDK.
144+ guard let libSwiftPath = envStringValue ( " LIB_SWIFT_PATH " ) else {
145+ // Fallback when LIB_SWIFT_PATH is not set
146+ let swiftBinPath = envStringValue ( " BIN_SWIFT_PATH " ) ?? envStringValue ( " _ " , searchInDomain: false ) ?? " /usr/bin/swift "
147+ let swiftBinURL = URL ( fileURLWithPath: swiftBinPath)
148+ let SDKPath = swiftBinURL. deletingLastPathComponent ( ) . deletingLastPathComponent ( ) . deletingLastPathComponent ( ) . path
149+ return SDKPath . appending ( " /usr/lib/swift " )
150+ }
151+ return libSwiftPath
152+ } ( )
35153
36- let releaseVersion = Context . environment [ " OPENRENDERBOX_TARGET_RELEASE " ] . flatMap { Int ( $0) } ?? 2024
154+ let libraryEvolutionCondition = envBoolValue ( " LIBRARY_EVOLUTION " , default: buildForDarwinPlatform)
155+ let compatibilityTestCondition = envBoolValue ( " COMPATIBILITY_TEST " , default: false )
37156
38- let swiftBinPath = Context . environment [ " _ " ] ?? " /usr/bin/swift "
39- let swiftBinURL = URL ( fileURLWithPath: swiftBinPath)
40- let SDKPath = swiftBinURL. deletingLastPathComponent ( ) . deletingLastPathComponent ( ) . deletingLastPathComponent ( ) . path
41- let includePath = SDKPath . appending ( " /usr/lib/swift " )
157+ let useLocalDeps = envBoolValue ( " USE_LOCAL_DEPS " )
158+ let renderBoxCondtion = envBoolValue ( " RENDERBOX " , default: buildForDarwinPlatform && !isSPIBuild)
42159
43- let sharedCSettings : [ CSetting ] = [
44- . unsafeFlags( [ " -I " , includePath] , . when( platforms: . nonDarwinPlatforms) ) ,
160+ // MARK: - Shared Settings
161+
162+ var sharedCSettings : [ CSetting ] = [
163+ . unsafeFlags( [ " -I " , libSwiftPath] , . when( platforms: . nonDarwinPlatforms) ) ,
45164 . unsafeFlags( [ " -fmodules " ] ) ,
46165 . define( " __COREFOUNDATION_FORSWIFTFOUNDATIONONLY__ " , to: " 1 " , . when( platforms: . nonDarwinPlatforms) ) ,
47166]
48- let sharedCxxSettings : [ CXXSetting ] = [
49- . unsafeFlags( [ " -I " , includePath ] , . when( platforms: . nonDarwinPlatforms) ) ,
167+ var sharedCxxSettings : [ CXXSetting ] = [
168+ . unsafeFlags( [ " -I " , libSwiftPath ] , . when( platforms: . nonDarwinPlatforms) ) ,
50169 . unsafeFlags( [ " -fcxx-modules " ] ) ,
51170 . define( " __COREFOUNDATION_FORSWIFTFOUNDATIONONLY__ " , to: " 1 " , . when( platforms: . nonDarwinPlatforms) ) ,
52171]
53172var sharedSwiftSettings : [ SwiftSetting ] = [
54173 . swiftLanguageMode( . v5) ,
55174]
56-
57- // MARK: - [env] OPENRENDERBOX_LIBRARY_EVOLUTION
58-
59- let libraryEvolutionCondition = envEnable ( " OPENRENDERBOX_LIBRARY_EVOLUTION " , default: buildForDarwinPlatform)
60-
61175if libraryEvolutionCondition {
62176 // NOTE: -enable-library-evolution will cause module verify failure for `swift build`.
63- // Either set OPENRENDERBOX_LIBRARY_EVOLUTION =0 or add `-Xswiftc -no-verify-emitted-module-interface` after `swift build`
177+ // Either set LIBRARY_EVOLUTION =0 or add `-Xswiftc -no-verify-emitted-module-interface` after `swift build`
64178 sharedSwiftSettings. append ( . unsafeFlags( [ " -enable-library-evolution " , " -no-verify-emitted-module-interface " ] ) )
65179}
66180
181+ // MARK: - Extension
182+
183+ extension Target {
184+ func addRBSettings( ) {
185+ dependencies. append (
186+ . product( name: " RenderBox " , package : " DarwinPrivateFrameworks " )
187+ )
188+ var swiftSettings = swiftSettings ?? [ ]
189+ swiftSettings. append ( . define( " OPENRENDERBOX_RENDERBOX " ) )
190+ self . swiftSettings = swiftSettings
191+ }
192+ }
193+
194+ extension [ Platform ] {
195+ static var nonDarwinPlatforms : [ Platform ] {
196+ [ . linux, . android, . wasi, . openbsd, . windows]
197+ }
198+ }
199+
67200// MARK: - Targets
68201
69202let openRenderBoxTarget = Target . target (
@@ -96,7 +229,7 @@ let openRenderBoxCompatibilityTestTarget = Target.testTarget(
96229// MARK: - Package
97230
98231let libraryType : Product . Library . LibraryType ?
99- switch Context . environment [ " OPENRENDERBOX_LIBRARY_TYPE " ] {
232+ switch envStringValue ( " LIBRARY_TYPE " ) {
100233case " dynamic " :
101234 libraryType = . dynamic
102235case " static " :
@@ -123,10 +256,6 @@ let package = Package(
123256 cxxLanguageStandard: . cxx20
124257)
125258
126- let useLocalDeps = envEnable ( " OPENRENDERBOX_USE_LOCAL_DEPS " )
127-
128- let renderBoxCondtion = envEnable ( " OPENRENDERBOX_RENDERBOX " , default: buildForDarwinPlatform && !isSPIBuild )
129-
130259if renderBoxCondtion {
131260 let privateFrameworkRepo : Package . Dependency
132261 if useLocalDeps {
@@ -135,13 +264,11 @@ if renderBoxCondtion {
135264 privateFrameworkRepo = Package . Dependency. package ( url: " https://github.com/OpenSwiftUIProject/DarwinPrivateFrameworks.git " , branch: " main " )
136265 }
137266 package . dependencies. append ( privateFrameworkRepo)
138- var swiftSettings : [ SwiftSetting ] = ( openRenderBoxShimsTarget. swiftSettings ?? [ ] )
139- swiftSettings. append ( . define( " OPENRENDERBOX_RENDERBOX " ) )
140- openRenderBoxShimsTarget. swiftSettings = swiftSettings
141- openRenderBoxShimsTarget. dependencies. append (
142- . product( name: " RenderBox " , package : " DarwinPrivateFrameworks " )
143- )
144- let rbVersion = Context . environment [ " DARWIN_PRIVATE_FRAMEWORKS_TARGET_RELEASE " ] . flatMap { Int ( $0) } ?? 2024
267+ openRenderBoxShimsTarget. addRBSettings ( )
268+
269+ let rbVersion = EnvManager . shared. withDomain ( " DARWIN_PRIVATE_FRAMEWORKS " ) {
270+ envIntValue ( " TARGET_RELEASE " , default: 2024 )
271+ }
145272 package . platforms = switch rbVersion {
146273 case 2024 : [ . iOS( . v18) , . macOS( . v15) , . macCatalyst( . v18) , . tvOS( . v18) , . watchOS( . v10) , . visionOS( . v2) ]
147274 case 2021 : [ . iOS( . v15) , . macOS( . v12) , . macCatalyst( . v15) , . tvOS( . v15) , . watchOS( . v7) ]
@@ -151,20 +278,11 @@ if renderBoxCondtion {
151278 openRenderBoxShimsTarget. dependencies. append ( " OpenRenderBox " )
152279}
153280
154- let compatibilityTestCondition = envEnable ( " OPENRENDERBOX_COMPATIBILITY_TEST " )
155281if compatibilityTestCondition && renderBoxCondtion {
156- openRenderBoxCompatibilityTestTarget. dependencies. append (
157- . product( name: " RenderBox " , package : " DarwinPrivateFrameworks " )
158- )
282+ openRenderBoxCompatibilityTestTarget. addRBSettings ( )
159283 var swiftSettings : [ SwiftSetting ] = ( openRenderBoxCompatibilityTestTarget. swiftSettings ?? [ ] )
160284 swiftSettings. append ( . define( " OPENRENDERBOX_COMPATIBILITY_TEST " ) )
161285 openRenderBoxCompatibilityTestTarget. swiftSettings = swiftSettings
162286} else {
163287 openRenderBoxCompatibilityTestTarget. dependencies. append ( " OpenRenderBox " )
164288}
165-
166- extension [ Platform ] {
167- static var nonDarwinPlatforms : [ Platform ] {
168- [ . linux, . android, . wasi, . openbsd, . windows]
169- }
170- }
0 commit comments