File: Module.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (323 lines) | stat: -rw-r--r-- 11,115 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
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2014-2023 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 Basics

@available(*, deprecated, renamed: "Module")
public typealias Target = Module

public class Module {
    /// Description of the module type used in `swift package describe` output. Preserved for backwards compatibility.
    public class var typeDescription: String { fatalError("implement in a subclass") }
    /// The module kind.
    public enum Kind: String {
        case executable
        case library
        case systemModule = "system-target"
        case test
        case binary
        case plugin
        case snippet
        case `macro`
    }

    /// A group a module belongs to that allows customizing access boundaries. A module is treated as
    /// a client outside of the package if `excluded`, inside the package boundary if `package`.
    public enum Group: Equatable {
        case package
        case excluded
    }

    /// A reference to a product from a module dependency.
    public struct ProductReference {
        /// The name of the product dependency.
        public let name: String

        /// The name of the package containing the product.
        public let package: String?

        /// Module aliases for targets of this product dependency. The key is an
        /// original target name and the value is a new unique name that also
        /// becomes the name of its .swiftmodule binary.
        public let moduleAliases: [String: String]?

        /// Fully qualified name for this product dependency: package ID + name of the product
        public var identity: String {
            if let package {
                return package.lowercased() + "_" + name
            } else {
                // this is hit only if this product is referenced `.byName(name)`
                // which assumes the name of this product, its package, and its module
                // all have the same name
                return name.lowercased() + "_" + name
            }
        }

        /// Creates a product reference instance.
        public init(name: String, package: String?, moduleAliases: [String: String]? = nil) {
            self.name = name
            self.package = package
            self.moduleAliases = moduleAliases
        }
    }

    /// A module dependency to a module or product.
    public enum Dependency {
        /// A dependency referencing another target, with conditions.
        case module(_ target: Module, conditions: [PackageCondition])

        /// A dependency referencing a product, with conditions.
        case product(_ product: ProductReference, conditions: [PackageCondition])


        @available(*, deprecated, renamed: "module")
        public var target: Module? { self.module }

        /// The module if the dependency is a target dependency.
        public var module: Module? {
            if case .module(let target, _) = self {
                return target
            } else {
                return nil
            }
        }

        /// The product reference if the dependency is a product dependency.
        public var product: ProductReference? {
            if case .product(let product, _) = self {
                return product
            } else {
                return nil
            }
        }

        /// The dependency conditions.
        public var conditions: [PackageCondition] {
            switch self {
            case .module(_, let conditions):
                return conditions
            case .product(_, let conditions):
                return conditions
            }
        }

        /// The name of the target or product of the dependency.
        public var name: String {
            switch self {
            case .module(let target, _):
                return target.name
            case .product(let product, _):
                return product.name
            }
        }
    }

    /// A usage of a plugin module or product. Implemented as a dependency
    /// for now and added to the `dependencies` array, since they currently
    /// have exactly the same characteristics and to avoid duplicating the
    /// implementation for now.
    public typealias PluginUsage = Dependency

    /// The name of the module.
    ///
    /// NOTE: This name is not the language-level module (i.e., the importable
    /// name) name in many cases, instead use ``Target/c99name`` if you need uniqueness.
    public private(set) var name: String

    /// Module aliases needed to build this module. The key is an original name of a
    /// dependent module and the value is a new unique name mapped to the name
    /// of its .swiftmodule binary.
    public private(set) var moduleAliases: [String: String]?
    /// Used to store pre-chained / pre-overriden module aliases
    public private(set) var prechainModuleAliases: [String: String]?
    /// Used to store aliases that should be referenced directly in source code
    public private(set) var directRefAliases: [String: [String]]?

    /// Add module aliases (if applicable) for dependencies of this module.
    ///
    /// For example, adding an alias `Bar` for a module name `Foo` will result in
    /// compiling references to `Foo` in source code of this module as `Bar.swiftmodule`.
    /// If the name argument `Foo` is the same as this module's name, this module will be
    /// renamed as `Bar` and the resulting binary will be `Bar.swiftmodule`.
    ///
    /// - Parameters:
    ///   - name: The original name of a dependent module or this module
    ///   - alias: A new unique name mapped to the resulting binary name
    public func addModuleAlias(for name: String, as alias: String) {
        if moduleAliases == nil {
            moduleAliases = [name: alias]
        } else {
            moduleAliases?[name] = alias
        }
    }

    public func removeModuleAlias(for name: String) {
        moduleAliases?.removeValue(forKey: name)
        if moduleAliases?.isEmpty ?? false {
            moduleAliases = nil
        }
    }

    public func addPrechainModuleAlias(for name: String, as alias: String) {
        if prechainModuleAliases == nil {
            prechainModuleAliases = [name: alias]
        } else {
            prechainModuleAliases?[name] = alias
        }
    }
    public func addDirectRefAliases(for name: String, as aliases: [String]) {
        if directRefAliases == nil {
            directRefAliases = [name: aliases]
        } else {
            directRefAliases?[name] = aliases
        }
    }

    @discardableResult
    public func applyAlias() -> Bool {
        // If there's an alias for this module, rename
        if let alias = moduleAliases?[name] {
            self.name = alias
            self.c99name = alias.spm_mangledToC99ExtendedIdentifier()
            return true
        }
        return false
    }

    /// The dependencies of this module.
    public let dependencies: [Dependency]

    /// The language-level module name.
    public private(set) var c99name: String

    /// The bundle name, if one is being generated.
    public var bundleName: String? {
        return resources.isEmpty ? nil : potentialBundleName
    }
    public let potentialBundleName: String?

    /// Suffix that's expected for test targets.
    public static let testModuleNameSuffix = "Tests"

    /// The kind of module.
    public let type: Kind

    /// If true, access to package declarations from other modules is allowed.
    public let packageAccess: Bool

    /// The path of the module.
    public let path: AbsolutePath

    /// The sources for the module.
    public let sources: Sources

    /// The resource files in the module.
    public let resources: [Resource]

    /// Files in the target that were marked as ignored.
    public let ignored: [AbsolutePath]

    /// Other kinds of files in the module.
    public let others: [AbsolutePath]

    /// The build settings assignments of this module.
    public let buildSettings: BuildSettings.AssignmentTable

    @_spi(SwiftPMInternal)
    public let buildSettingsDescription: [TargetBuildSettingDescription.Setting]

    /// The usages of package plugins by this module.
    public let pluginUsages: [PluginUsage]

    /// Whether or not this target uses any custom unsafe flags.
    public let usesUnsafeFlags: Bool

    init(
        name: String,
        potentialBundleName: String? = nil,
        type: Kind,
        path: AbsolutePath,
        sources: Sources,
        resources: [Resource] = [],
        ignored: [AbsolutePath] = [],
        others: [AbsolutePath] = [],
        dependencies: [Module.Dependency],
        packageAccess: Bool,
        buildSettings: BuildSettings.AssignmentTable,
        buildSettingsDescription: [TargetBuildSettingDescription.Setting],
        pluginUsages: [PluginUsage],
        usesUnsafeFlags: Bool
    ) {
        self.name = name
        self.potentialBundleName = potentialBundleName
        self.type = type
        self.path = path
        self.sources = sources
        self.resources = resources
        self.ignored = ignored
        self.others = others
        self.dependencies = dependencies
        self.c99name = self.name.spm_mangledToC99ExtendedIdentifier()
        self.packageAccess = packageAccess
        self.buildSettings = buildSettings
        self.buildSettingsDescription = buildSettingsDescription
        self.pluginUsages = pluginUsages
        self.usesUnsafeFlags = usesUnsafeFlags
    }

    @_spi(SwiftPMInternal)
    public var isEmbeddedSwiftTarget: Bool {
        for case .enableExperimentalFeature("Embedded") in self.buildSettingsDescription.swiftSettings.map(\.kind) {
            return true
        }

        return false
    }
}

extension Module: Hashable {
    public func hash(into hasher: inout Hasher) {
        hasher.combine(ObjectIdentifier(self))
    }

    public static func == (lhs: Module, rhs: Module) -> Bool {
        ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
    }
}

extension Module: CustomStringConvertible {
    public var description: String {
        return "<\(Swift.type(of: self)): \(name)>"
    }
}

public extension Sequence where Iterator.Element == Module {
    var executables: [Module] {
        return filter {
            switch $0.type {
            case .binary:
                return ($0 as? BinaryModule)?.containsExecutable == true
            case .executable, .snippet, .macro:
                return true
            default:
                return false
            }
        }
    }
}

extension [TargetBuildSettingDescription.Setting] {
    @_spi(SwiftPMInternal)
    public var swiftSettings: Self {
        self.filter { $0.tool == .swift }
    }
}