File: BuildSettings.swift

package info (click to toggle)
swiftlang 6.2.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,856,264 kB
  • sloc: cpp: 9,995,718; ansic: 2,234,019; asm: 1,092,167; python: 313,940; objc: 82,726; f90: 80,126; lisp: 38,373; pascal: 25,580; sh: 20,378; ml: 5,058; perl: 4,751; makefile: 4,725; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (350 lines) | stat: -rw-r--r-- 12,727 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
//===----------------------------------------------------------------------===//
//
// 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 Foundation
import SWBProtocol
import SWBUtil

extension ProjectModel {
    public struct BuildSettings: Sendable, Hashable {
        public enum SingleValueSetting: String, CaseIterable, Sendable, Equatable, Codable {
            case APPLICATION_EXTENSION_API_ONLY
            case BUILT_PRODUCTS_DIR
            case CLANG_CXX_LANGUAGE_STANDARD
            case CLANG_ENABLE_MODULES
            case CLANG_DISABLE_CXX_MODULES
            case CLANG_ENABLE_OBJC_ARC
            case CODE_SIGNING_REQUIRED
            case CODE_SIGN_IDENTITY
            case COMBINE_HIDPI_IMAGES
            case COPY_PHASE_STRIP
            case DEBUG_INFORMATION_FORMAT
            case DEFINES_MODULE
            case DRIVERKIT_DEPLOYMENT_TARGET
            case DYLIB_INSTALL_NAME_BASE
            case EMBEDDED_CONTENT_CONTAINS_SWIFT
            case ENABLE_NS_ASSERTIONS
            case ENABLE_TESTABILITY
            case ENABLE_TESTING_SEARCH_PATHS
            case ENTITLEMENTS_REQUIRED
            case EXECUTABLE_PREFIX
            case GENERATE_INFOPLIST_FILE
            case GCC_C_LANGUAGE_STANDARD
            case GCC_OPTIMIZATION_LEVEL
            case GENERATE_PRELINK_OBJECT_FILE
            case INFOPLIST_FILE
            case IPHONEOS_DEPLOYMENT_TARGET
            case KEEP_PRIVATE_EXTERNS
            case CLANG_COVERAGE_MAPPING_LINKER_ARGS
            case MACH_O_TYPE
            case MACOSX_DEPLOYMENT_TARGET
            case MODULEMAP_FILE
            case MODULEMAP_FILE_CONTENTS
            case MODULEMAP_PATH
            case MODULE_CACHE_DIR
            case ONLY_ACTIVE_ARCH
            case PACKAGE_RESOURCE_BUNDLE_NAME
            case PACKAGE_RESOURCE_TARGET_KIND
            case PRODUCT_BUNDLE_IDENTIFIER
            case PRODUCT_MODULE_NAME
            case PRODUCT_NAME
            case PROJECT_NAME
            case SDKROOT
            case SDK_VARIANT
            case SKIP_INSTALL
            case INSTALL_PATH
            case SUPPORTS_MACCATALYST
            case SWIFT_SERIALIZE_DEBUGGING_OPTIONS
            case SWIFT_INSTALL_OBJC_HEADER
            case SWIFT_OBJC_INTERFACE_HEADER_NAME
            case SWIFT_OBJC_INTERFACE_HEADER_DIR
            case SWIFT_OPTIMIZATION_LEVEL
            case SWIFT_VERSION
            case TARGET_NAME
            case TARGET_BUILD_DIR
            case TVOS_DEPLOYMENT_TARGET
            case USE_HEADERMAP
            case USES_SWIFTPM_UNSAFE_FLAGS
            case WATCHOS_DEPLOYMENT_TARGET
            case XROS_DEPLOYMENT_TARGET
            case _IOS_DEPLOYMENT_TARGET
            case MARKETING_VERSION
            case CURRENT_PROJECT_VERSION
            case SWIFT_EMIT_MODULE_INTERFACE
            case GENERATE_RESOURCE_ACCESSORS
            case BUILD_LIBRARY_FOR_DISTRIBUTION
            case BUILD_PACKAGE_FOR_DISTRIBUTION
            case COMPILER_WORKING_DIRECTORY
            case COREML_CODEGEN_LANGUAGE
            case COREML_COMPILER_CONTAINER
            case EXECUTABLE_NAME
            case GENERATE_EMBED_IN_CODE_ACCESSORS
            case INSTALLAPI_COPY_PHASE
            case INSTALLHDRS_COPY_PHASE
            case IS_ZIPPERED
            case PACKAGE_REGISTRY_SIGNATURE
            case PACKAGE_TARGET_NAME_CONFLICTS_WITH_PRODUCT_NAME
            case SKIP_BUILDING_DOCUMENTATION
            case SKIP_CLANG_STATIC_ANALYZER
            case STRIP_INSTALLED_PRODUCT
            case SUPPORTS_TEXT_BASED_API
            case SUPPRESS_WARNINGS
            case SWIFT_ENABLE_BARE_SLASH_REGEX
            case SWIFT_INSTALL_MODULE
            case SWIFT_PACKAGE_NAME
            case SWIFT_USER_MODULE_VERSION
            case TAPI_DYLIB_INSTALL_NAME
            case TARGETED_DEVICE_FAMILY
            case LINKER_DRIVER
            case LD_WARN_DUPLICATE_LIBRARIES

            // @available(*, deprecated, renamed: "GENERATE_PRELINK_OBJECT_FILE") // can't add @available because it breaks CaseIterable
            case GENERATE_MASTER_OBJECT_FILE // ignore-unacceptable-language
        }

        public enum MultipleValueSetting: String, CaseIterable, Sendable, Hashable, Codable {
            case EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES
            case FRAMEWORK_SEARCH_PATHS
            case GCC_PREPROCESSOR_DEFINITIONS
            case HEADER_SEARCH_PATHS
            case LD_RUNPATH_SEARCH_PATHS
            case LIBRARY_SEARCH_PATHS
            case OTHER_CFLAGS
            case OTHER_CPLUSPLUSFLAGS
            case OTHER_LDFLAGS
            case OTHER_LDRFLAGS
            case OTHER_SWIFT_FLAGS
            case PRELINK_FLAGS
            case SPECIALIZATION_SDK_OPTIONS
            case SUPPORTED_PLATFORMS
            case SWIFT_ACTIVE_COMPILATION_CONDITIONS
            case SWIFT_IMPLEMENTS_MACROS_FOR_MODULE_NAMES
            case SWIFT_MODULE_ALIASES
            case SWIFT_WARNINGS_AS_WARNINGS_GROUPS
            case SWIFT_WARNINGS_AS_ERRORS_GROUPS
        }

        public enum Declaration: String, Hashable, CaseIterable, Sendable {
            case ARCHS
            case GCC_PREPROCESSOR_DEFINITIONS
            case FRAMEWORK_SEARCH_PATHS
            case HEADER_SEARCH_PATHS
            case IPHONEOS_DEPLOYMENT_TARGET
            case OTHER_CFLAGS
            case OTHER_CPLUSPLUSFLAGS
            case OTHER_LDFLAGS
            case OTHER_SWIFT_FLAGS
            case SPECIALIZATION_SDK_OPTIONS
            case SWIFT_VERSION
            case SWIFT_ACTIVE_COMPILATION_CONDITIONS
        }

        public enum Platform: Hashable, CaseIterable, Sendable {
            case macOS
            case macCatalyst
            case iOS

            // Special case to support arm64e-only iOS app builds with SwiftPM dependencies. Don't use it for anything else!
            case _iOSDevice

            case tvOS
            case watchOS
            case xrOS

            case driverKit

            case linux
            case android
            case windows
            case wasi
            case openbsd
            case freebsd

            public var asConditionStrings: [String] {
                let filters = self.toPlatformFilter().map { (filter: ProjectModel.PlatformFilter) -> String in
                    if filter.environment.isEmpty {
                        return filter.platform
                    } else {
                        return "\(filter.platform)-\(filter.environment)"
                    }
                }.sorted()
                return ["__platform_filter=\(filters.joined(separator: ";"))"]
            }
        }

        public var platformSpecificSettings = [Platform: [Declaration: [String]]]()

        public init() {
            var settings: [Declaration: [String]] = [:]
            for declaration in Declaration.allCases {
                settings[declaration] = ["$(inherited)"]
            }

            for platform in Platform.allCases {
                platformSpecificSettings[platform] = settings
            }
        }

        private(set) var singleValueSettings: OrderedDictionary<String, String> = [:]
        private(set) var multipleValueSettings: OrderedDictionary<String, [String]> = [:]

        public subscript(_ setting: SingleValueSetting) -> String? {
            get { singleValueSettings[setting.rawValue] }
            set { singleValueSettings[setting.rawValue] = newValue }
        }

        public subscript(single setting: String) -> String? {
            get { singleValueSettings[setting] }
            set { singleValueSettings[setting] = newValue }
        }

        public subscript(_ setting: MultipleValueSetting) -> [String]? {
            get { multipleValueSettings[setting.rawValue] }
            set { multipleValueSettings[setting.rawValue] = newValue }
        }

        public subscript(multiple setting: String) -> [String]? {
            get { multipleValueSettings[setting] }
            set { multipleValueSettings[setting] = newValue }
        }
    }
}


public extension ProjectModel.BuildSettings.Platform {
    func toPlatformFilter() -> [ProjectModel.PlatformFilter] {
        var result: [ProjectModel.PlatformFilter] = []

        switch self {
        case .macOS:
            result.append(.init(platform: "macos"))

        case .macCatalyst:
            result.append(.init(platform: "ios", environment: "maccatalyst"))

        case .iOS:
            result.append(.init(platform: "ios"))
            result.append(.init(platform: "ios", environment: "simulator"))

        case ._iOSDevice:
            result.append(.init(platform: "ios"))

        case .tvOS:
            result.append(.init(platform: "tvos"))
            result.append(.init(platform: "tvos", environment: "simulator"))

        case .watchOS:
            result.append(.init(platform: "watchos"))
            result.append(.init(platform: "watchos", environment: "simulator"))

        case .xrOS:
            result.append(.init(platform: "xros"))
            result.append(.init(platform: "xros", environment: "simulator"))

        case .driverKit:
            result.append(.init(platform: "driverkit"))

        case .linux:
            result.append(.init(platform: "linux", environment: "gnu"))

        case .android:
            result.append(.init(platform: "linux", environment: "android"))
            result.append(.init(platform: "linux", environment: "androideabi"))

        case .windows:
            result.append(.init(platform: "windows", environment: "msvc"))

        case .wasi:
            result.append(.init(platform: "wasi"))

        case .openbsd:
            result.append(.init(platform: "openbsd"))

        case .freebsd:
            result.append(.init(platform: "freebsd"))
        }
        return result
    }
}

extension ProjectModel.BuildSettings: Codable {
    private struct StringKey: CodingKey {
        var stringValue: String
        var intValue: Int?

        init(stringValue value: String) {
            self.stringValue = value
        }

        init(_ value: String) {
            self.stringValue = value
        }

        init?(intValue: Int) {
            assertionFailure("does not support integer keys")
            return nil
        }
    }

    public init(from decoder: any Decoder) throws {
        self.init()

        let container = try decoder.container(keyedBy: StringKey.self)

        // NOTE: unknown settings will be lost during decoding, as there is no way to tell
        // if they are a single or multiple value setting.

        for key in SingleValueSetting.allCases {
            if let value = try container.decodeIfPresent(String.self, forKey: StringKey(key.rawValue)) {
                self[key] = value
            }
        }
        for key in MultipleValueSetting.allCases {
            if let value = try container.decodeIfPresent([String].self, forKey: StringKey(key.rawValue)) {
                self[key] = value
            }
        }
        for platform in Platform.allCases {
            for condition in platform.asConditionStrings {
                for declaration in Declaration.allCases {
                    if let value = try container.decodeIfPresent([String].self, forKey: StringKey("\(declaration.rawValue)[\(condition)]")) {
                        self.platformSpecificSettings[platform, default: [:]][declaration] = value
                    }
                }
            }
        }
    }

    public func encode(to encoder: any Encoder) throws {
        var container = encoder.container(keyedBy: StringKey.self)

        for (key, value) in singleValueSettings {
            try container.encode(value, forKey: StringKey(key))
        }

        for (key, value) in multipleValueSettings {
            try container.encode(value, forKey: StringKey(key))
        }

        for (platformCondition, values) in platformSpecificSettings {
            for condition in platformCondition.asConditionStrings {
                for (key, value) in values {
                    // If `$(inherited)` is the only value, do not emit anything to the PIF.
                    if value == ["$(inherited)"] {
                        continue
                    }
                    try container.encode(value, forKey: StringKey("\(key.rawValue)[\(condition)]"))
                }
            }
        }
    }
}