Skip to content

Commit 22a1188

Browse files
committed
[PackageDescription] Restore the old product API
This API was removed when implementing the product proposal but is being restored to keep compatibility with current Swift 3 packages. The new API will be introduced in the PackageDescription4 module.
1 parent baa42a7 commit 22a1188

File tree

12 files changed

+168
-288
lines changed

12 files changed

+168
-288
lines changed
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import PackageDescription
22

33
let package = Package(
4-
name: "packageName",
5-
products: [
6-
.Library(name: "ProductName", type: .dynamic, targets: ["packageName"]),
7-
]
4+
name: "packageName"
85
)
6+
7+
products.append(Product(name: "ProductName", type: .Library(.Dynamic), modules: ["packageName"]))
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import PackageDescription
22

33
let package = Package(
4-
name: "PackageName",
5-
products: [
6-
.Library(name: "ProductName", type: .static, targets: ["PackageName"]),
7-
]
4+
name: "PackageName"
85
)
6+
7+
products.append(Product(name: "ProductName", type: .Library(.Static), modules: ["PackageName"]))

Package.swift

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,32 @@ let package = Package(
170170
name: "XcodeprojTests",
171171
dependencies: ["Xcodeproj", "TestSupport"]),
172172
],
173-
products: [
174-
// Runtime Library: contains the package description API itself.
175-
.Library(
176-
name: "PackageDescription",
177-
type: .dynamic,
178-
targets: ["PackageDescription"]),
179-
180-
// SwiftPM Library: provides package management functionality to clients.
181-
.Library(
182-
name: "SwiftPM",
183-
type: .dynamic,
184-
targets: ["libc", "POSIX", "Basic", "Utility", "SourceControl", "PackageDescription", "PackageModel", "PackageLoading", "Get", "PackageGraph", "Build", "Xcodeproj", "Workspace"]),
185-
],
186173
exclude: [
187174
"Tests/PackageLoadingTests/Inputs",
188175
]
189176
)
177+
178+
179+
// The executable products are automatically determined by SwiftPM; any module
180+
// that contains a `main.swift` source file results in an implicit executable
181+
// product.
182+
183+
184+
// Runtime Library -- contains the package description API itself
185+
products.append(
186+
Product(
187+
name: "PackageDescription",
188+
type: .Library(.Dynamic),
189+
modules: ["PackageDescription"]
190+
)
191+
)
192+
193+
194+
// SwiftPM Library -- provides package management functionality to clients
195+
products.append(
196+
Product(
197+
name: "SwiftPM",
198+
type: .Library(.Dynamic),
199+
modules: ["libc", "POSIX", "Basic", "Utility", "SourceControl", "PackageDescription", "PackageModel", "PackageLoading", "Get", "PackageGraph", "Build", "Xcodeproj", "Workspace"]
200+
)
201+
)

Sources/PackageDescription/Package.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ public final class Package {
6060
/// The list of targets.
6161
public var targets: [Target]
6262

63-
/// The list of products vended by this package.
64-
public var products: [Product]
65-
6663
/// The list of dependencies.
6764
public var dependencies: [Dependency]
6865

@@ -75,15 +72,13 @@ public final class Package {
7572
pkgConfig: String? = nil,
7673
providers: [SystemPackageProvider]? = nil,
7774
targets: [Target] = [],
78-
products: [Product] = [],
7975
dependencies: [Dependency] = [],
8076
exclude: [String] = []
8177
) {
8278
self.name = name
8379
self.pkgConfig = pkgConfig
8480
self.providers = providers
8581
self.targets = targets
86-
self.products = products
8782
self.dependencies = dependencies
8883
self.exclude = exclude
8984

@@ -167,7 +162,6 @@ extension Package {
167162
dict["dependencies"] = .array(dependencies.map { $0.toJSON() })
168163
dict["exclude"] = .array(exclude.map { .string($0) })
169164
dict["targets"] = .array(targets.map { $0.toJSON() })
170-
dict["products"] = .array(products.map { $0.toJSON() })
171165
if let providers = self.providers {
172166
dict["providers"] = .array(providers.map { $0.toJSON() })
173167
}
@@ -215,6 +209,7 @@ struct Errors {
215209
func manifestToJSON(_ package: Package) -> String {
216210
var dict: [String: JSON] = [:]
217211
dict["package"] = package.toJSON()
212+
dict["products"] = .array(products.map { $0.toJSON() })
218213
dict["errors"] = errors.toJSON()
219214
return JSON.dictionary(dict).toString()
220215
}

Sources/PackageDescription/Product.swift

Lines changed: 55 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -8,125 +8,83 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
/// Defines a product in the package.
12-
public enum Product {
11+
public struct Product {
12+
public let name: String
13+
public let type: ProductType
14+
public let modules: [String]
1315

14-
/// An exectuable product.
15-
public struct ExecutableProduct {
16-
17-
/// The name of the executable product.
18-
public let name: String
19-
20-
/// The names of targets in the product.
21-
public let targets: [String]
22-
}
23-
24-
/// A library product.
25-
public struct LibraryProduct {
26-
27-
/// The type of library products.
28-
public enum LibraryType: String {
29-
case `static`
30-
case `dynamic`
31-
}
32-
33-
/// The name of the library product.
34-
public let name: String
35-
36-
/// The type of the library.
37-
///
38-
/// If the type is unspecified, package manager will automatically choose a type.
39-
public let type: LibraryType?
40-
41-
/// The names of targets in the product.
42-
public let targets: [String]
16+
public init(name: String, type: ProductType, modules: String...) {
17+
self.init(name: name, type: type, modules: modules)
4318
}
4419

45-
/// Executable product.
46-
case exe(ExecutableProduct)
47-
48-
/// Library product.
49-
case lib(LibraryProduct)
50-
51-
/// Create an executable product.
52-
public static func Executable(name: String, targets: [String]) -> Product {
53-
return .exe(ExecutableProduct(name: name, targets: targets))
54-
}
55-
56-
/// Create a library product.
57-
public static func Library(name: String, type: LibraryProduct.LibraryType? = nil, targets: [String]) -> Product {
58-
return .lib(LibraryProduct(name: name, type: type, targets: targets))
20+
public init(name: String, type: ProductType, modules: [String]) {
21+
self.name = name
22+
self.type = type
23+
self.modules = modules
5924
}
25+
}
6026

61-
/// Name of the product.
62-
public var name: String {
63-
switch self {
64-
case .exe(let p): return p.name
65-
case .lib(let p): return p.name
66-
}
67-
}
27+
public enum LibraryType {
28+
case Static
29+
case Dynamic
6830
}
6931

70-
extension Product.ExecutableProduct {
71-
func toJSON() -> [String: JSON] {
72-
return [
73-
"name": .string(name),
74-
"targets": .array(targets.map(JSON.string)),
75-
]
76-
}
32+
public enum ProductType {
33+
case Test
34+
case Executable
35+
case Library(LibraryType)
7736
}
7837

79-
extension Product.LibraryProduct {
80-
func toJSON() -> [String: JSON] {
81-
return [
82-
"name": .string(name),
83-
"type": type.map{ JSON.string($0.rawValue) } ?? .null,
84-
"targets": .array(targets.map(JSON.string)),
85-
]
38+
extension ProductType: CustomStringConvertible {
39+
public var description: String {
40+
switch self {
41+
case .Test:
42+
return "test"
43+
case .Executable:
44+
return "exe"
45+
case .Library(.Static):
46+
return "a"
47+
case .Library(.Dynamic):
48+
return "dylib"
49+
}
8650
}
8751
}
8852

8953
extension Product {
9054
func toJSON() -> JSON {
91-
switch self {
92-
case .exe(let product):
93-
var dict = product.toJSON()
94-
dict["product_type"] = .string("exe")
95-
return .dictionary(dict)
96-
case .lib(let product):
97-
var dict = product.toJSON()
98-
dict["product_type"] = .string("lib")
99-
return .dictionary(dict)
100-
}
55+
var dict: [String: JSON] = [:]
56+
dict["name"] = .string(name)
57+
dict["type"] = .string(type.description)
58+
dict["modules"] = .array(modules.map(JSON.string))
59+
return .dictionary(dict)
10160
}
10261
}
10362

104-
extension Product.ExecutableProduct: Equatable {
105-
public static func ==(lhs: Product.ExecutableProduct, rhs: Product.ExecutableProduct) -> Bool {
106-
return lhs.name == rhs.name &&
107-
lhs.targets == rhs.targets
63+
extension ProductType: Equatable {
64+
public static func ==(lhs: ProductType, rhs: ProductType) -> Bool {
65+
switch (lhs, rhs) {
66+
case (.Executable, .Executable):
67+
return true
68+
case (.Executable, _):
69+
return false
70+
case (.Test, .Test):
71+
return true
72+
case (.Test, _):
73+
return false
74+
case (.Library(let lhsType), .Library(let rhsType)):
75+
return lhsType == rhsType
76+
case (.Library, _):
77+
return false
78+
}
10879
}
10980
}
11081

111-
extension Product.LibraryProduct: Equatable {
112-
public static func ==(lhs: Product.LibraryProduct, rhs: Product.LibraryProduct) -> Bool {
82+
extension Product: Equatable {
83+
public static func ==(lhs: PackageDescription.Product, rhs: PackageDescription.Product) -> Bool {
11384
return lhs.name == rhs.name &&
11485
lhs.type == rhs.type &&
115-
lhs.targets == rhs.targets
86+
lhs.modules == rhs.modules
11687
}
11788
}
11889

119-
extension Product: Equatable {
120-
public static func ==(lhs: Product, rhs: Product) -> Bool {
121-
switch (lhs, rhs) {
122-
case (.exe(let a), .exe(let b)):
123-
return a == b
124-
case (.exe, _):
125-
return false
126-
case (.lib(let a), .lib(let b)):
127-
return a == b
128-
case (.lib, _):
129-
return false
130-
}
131-
}
132-
}
90+
public var products = [Product]()

Sources/PackageLoading/ManifestLoader.swift

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,14 @@ public final class ManifestLoader: ManifestLoaderProtocol {
142142
}
143143
let json = try JSON(string: jsonString)
144144
let package = PackageDescription.Package.fromJSON(json, baseURL: baseURL)
145+
let products = PackageDescription.Product.fromJSON(json)
145146
let errors = parseErrors(json)
146147

147148
guard errors.isEmpty else {
148149
throw ManifestParseError.runtimeManifestErrors(errors)
149150
}
150151

151-
return Manifest(path: path, url: baseURL, package: package, version: version)
152+
return Manifest(path: path, url: baseURL, package: package, legacyProducts: products, version: version)
152153
}
153154

154155
/// Parse the manifest at the given path to JSON.
@@ -236,12 +237,6 @@ extension PackageDescription.Package {
236237
targets = array.map(PackageDescription.Target.fromJSON)
237238
}
238239

239-
// Parse the products.
240-
var products: [PackageDescription.Product] = []
241-
if case .array(let array)? = package["products"] {
242-
products = array.map(PackageDescription.Product.fromJSON)
243-
}
244-
245240
var providers: [PackageDescription.SystemPackageProvider]? = nil
246241
if case .array(let array)? = package["providers"] {
247242
providers = array.map(PackageDescription.SystemPackageProvider.fromJSON)
@@ -262,7 +257,7 @@ extension PackageDescription.Package {
262257
}
263258
}
264259

265-
return PackageDescription.Package(name: name, pkgConfig: pkgConfig, providers: providers, targets: targets, products: products, dependencies: dependencies, exclude: exclude)
260+
return PackageDescription.Package(name: name, pkgConfig: pkgConfig, providers: providers, targets: targets, dependencies: dependencies, exclude: exclude)
266261
}
267262
}
268263

@@ -330,34 +325,40 @@ extension PackageDescription.Target.Dependency {
330325
}
331326

332327
extension PackageDescription.Product {
333-
fileprivate static func fromJSON(_ json: JSON) -> PackageDescription.Product {
328+
329+
fileprivate static func fromJSON(_ json: JSON) -> [PackageDescription.Product] {
330+
guard case .dictionary(let topLevelDict) = json else { fatalError("unexpected item") }
331+
guard case .array(let array)? = topLevelDict["products"] else { fatalError("unexpected item") }
332+
return array.map(Product.init)
333+
}
334+
335+
private init(_ json: JSON) {
334336
guard case .dictionary(let dict) = json else { fatalError("unexpected item") }
335337
guard case .string(let name)? = dict["name"] else { fatalError("missing item") }
336-
guard case .string(let productType)? = dict["product_type"] else { fatalError("missing item") }
337-
guard case .array(let targetsJSON)? = dict["targets"] else { fatalError("missing item") }
338+
guard case .string(let productType)? = dict["type"] else { fatalError("missing item") }
339+
guard case .array(let targetsJSON)? = dict["modules"] else { fatalError("missing item") }
338340

339341
let targets: [String] = targetsJSON.map {
340342
guard case JSON.string(let string) = $0 else { fatalError("invalid item") }
341343
return string
342344
}
345+
self.init(name: name, type: ProductType(productType), modules: targets)
346+
}
347+
}
343348

344-
switch productType {
349+
extension PackageDescription.ProductType {
350+
fileprivate init(_ string: String) {
351+
switch string {
345352
case "exe":
346-
return PackageDescription.Product.Executable(name: name, targets: targets)
347-
case "lib":
348-
let type: PackageDescription.Product.LibraryProduct.LibraryType?
349-
switch dict["type"] {
350-
case .string("static")?:
351-
type = .static
352-
case .string("dynamic")?:
353-
type = .dynamic
354-
case .null?:
355-
type = nil
356-
default: fatalError("unexpected item")
357-
}
358-
return PackageDescription.Product.Library(name: name, type: type, targets: targets)
353+
self = .Executable
354+
case "a":
355+
self = .Library(.Static)
356+
case "dylib":
357+
self = .Library(.Dynamic)
358+
case "test":
359+
self = .Test
359360
default:
360-
fatalError("unexpected item")
361+
fatalError("invalid string \(string)")
361362
}
362363
}
363364
}

0 commit comments

Comments
 (0)