add support for localPackages

This commit is contained in:
yonaskolb
2019-09-27 21:36:07 +10:00
parent 41453595cc
commit e9193cfb29
12 changed files with 138 additions and 3 deletions
+2 -1
View File
@@ -47,7 +47,8 @@ You can also use environment variables in your configuration file, by using `${S
- [ ] **fileGroups**: **[String]** - A list of paths to add to the root of the project. These aren't files that will be included in your targets, but that you'd like to include in the project hierachy anyway. For example a folder of xcconfig files that aren't already added by any target sources, or a Readme file.
- [ ] **schemes**: **[Scheme](#scheme)** - A list of schemes by name. This allows more control over what is found in [Target Scheme](#target-scheme)
- [ ] **targetTemplates**: **[String: [Target Template](#target-template)]** - a list of targets that can be used as templates for actual targets which reference them via a `template` property. They can be used to extract common target settings. Works great in combination with `include`.
- [ ] **packages**: **[String: [Swift Package](#swift-package)]** -
- [ ] **packages**: **[String: [Swift Package](#swift-package)]** - a map of Swift packages by name
- [ ] **localPackages**: **[String]** - A list of paths to local Swift Packages. The paths must be directories with a `Package.swift` file in them. This is used to override `packages` with a local version for development purposes.
### Include
+9
View File
@@ -178,6 +178,15 @@ If you want to check in the `Package.resolved` file so that everyone is on the s
> Note that Swift Packages don't work in projects with configurations other than `Debug` and `Release`. That limitation is tracked here bugs.swift.org/browse/SR-10927
You can also include local Swift Packages by referencing them by paths in `localPackages`. When these have the same name as `packages` they will be used instead of the remote repos. This is useful for local development.
```yml
localPackages:
- ../../Yams
- ~/Developer/MyPackage
```
> For now local packages that don't mirror remote packages aren't able to be linked to
### SDK
System frameworks and libs can be linked by using the `sdk` dependency type. You can either specify frameworks or libs by using a `.framework`, `.tbd` or `dylib` filename, respectively
+7
View File
@@ -20,6 +20,7 @@ public struct Project: BuildSettingsContainer {
}
public var packages: [String: SwiftPackage]
public var localPackages: [String]
public var settings: Settings
public var settingGroups: [String: Settings]
@@ -44,6 +45,7 @@ public struct Project: BuildSettingsContainer {
settingGroups: [String: Settings] = [:],
schemes: [Scheme] = [],
packages: [String: SwiftPackage] = [:],
localPackages: [String] = [],
options: SpecOptions = SpecOptions(),
fileGroups: [String] = [],
configFiles: [String: String] = [:],
@@ -60,6 +62,7 @@ public struct Project: BuildSettingsContainer {
self.settingGroups = settingGroups
self.schemes = schemes
self.packages = packages
self.localPackages = localPackages
self.options = options
self.fileGroups = fileGroups
self.configFiles = configFiles
@@ -131,6 +134,7 @@ extension Project: Equatable {
lhs.configFiles == rhs.configFiles &&
lhs.options == rhs.options &&
lhs.packages == rhs.packages &&
lhs.localPackages == rhs.localPackages &&
NSDictionary(dictionary: lhs.attributes).isEqual(to: rhs.attributes)
}
}
@@ -170,6 +174,7 @@ extension Project {
} else {
packages = [:]
}
localPackages = jsonDictionary.json(atKeyPath: "localPackages") ?? []
if jsonDictionary["options"] != nil {
options = try jsonDictionary.json(atKeyPath: "options")
} else {
@@ -197,6 +202,7 @@ extension Project: PathContainer {
static var pathProperties: [PathProperty] {
return [
.string("configFiles"),
.string("localPackages"),
.object("options", SpecOptions.pathProperties),
.object("targets", Target.pathProperties),
.object("targetTemplates", Target.pathProperties),
@@ -261,6 +267,7 @@ extension Project: JSONEncodable {
dictionary["include"] = include
dictionary["attributes"] = attributes
dictionary["packages"] = packages.mapValues { $0.toJSONValue() }
dictionary["localPackages"] = localPackages
dictionary["targets"] = Dictionary(uniqueKeysWithValues: targetPairs)
dictionary["configs"] = Dictionary(uniqueKeysWithValues: configsPairs)
dictionary["aggregateTargets"] = Dictionary(uniqueKeysWithValues: aggregateTargetsPairs)
+6
View File
@@ -52,6 +52,12 @@ extension Project {
}
}
for package in localPackages {
if !(basePath + Path(package).normalize()).exists {
errors.append(.invalidLocalPackage(package))
}
}
for (config, configFile) in configFiles {
if !options.disabledValidations.contains(.missingConfigFiles) && !(basePath + configFile).exists {
errors.append(.invalidConfigFile(configFile: configFile, config: config))
@@ -19,6 +19,7 @@ public struct SpecValidationError: Error, CustomStringConvertible {
case invalidSchemeTarget(scheme: String, target: String)
case invalidSchemeConfig(scheme: String, config: String)
case invalidSwiftPackage(name: String, target: String)
case invalidLocalPackage(String)
case invalidConfigFile(configFile: String, config: String)
case invalidBuildSettingConfig(String)
case invalidSettingsGroup(String)
@@ -64,6 +65,8 @@ public struct SpecValidationError: Error, CustomStringConvertible {
return "Config file has invalid config \(config.quoted)"
case let .invalidSwiftPackage(name, target):
return "Target \(target.quoted) has an invalid package dependency \(name.quoted)"
case let .invalidLocalPackage(path):
return "Invalid local package \(path.quoted)"
case let .missingConfigForTargetScheme(target, configType):
return "Target \(target.quoted) is missing a config of type \(configType.rawValue) to generate its scheme"
case let .missingDefaultConfig(name):
@@ -48,6 +48,12 @@ public class PBXProjGenerator {
try sourceGenerator.getFileGroups(path: group)
}
let localPackages = Set(project.localPackages)
for package in localPackages {
let path = project.basePath + Path(package).normalize()
sourceGenerator.createLocalPackage(path: path)
}
let buildConfigs: [XCBuildConfiguration] = project.configs.map { config in
let buildSettings = project.getProjectBuildSettings(config: config)
var baseConfiguration: PBXFileReference?
+12
View File
@@ -41,6 +41,18 @@ class SourceGenerator {
return object
}
func createLocalPackage(path: Path) {
let fileReference = addObject(
PBXFileReference(
sourceTree: .absolute,
name: path.lastComponent,
lastKnownFileType: "folder",
path: path.string
)
)
rootGroups.insert(fileReference)
}
func getAllSourceFiles(targetType: PBXProductType, sources: [TargetSource]) throws -> [SourceFile] {
return try sources.flatMap { try getSourceFiles(targetType: targetType, targetSource: $0, path: project.basePath + $0.path) }
}
@@ -31,6 +31,7 @@
464ACF8D8F2D9F219BCFD3E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4E22B8BCC18A29EFE1DE3BE4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
61C17B77601A9D1B7895AB42 /* StaticLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticLibrary.swift; sourceTree = "<group>"; };
EA6A9C2D515205854C4FC36F /* XcodeGen */ = {isa = PBXFileReference; lastKnownFileType = folder; name = XcodeGen; path = /Users/Yonas/Developer/XcodeGen; sourceTree = "<absolute>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -67,6 +68,7 @@
218F6C96DF9E182F526258CF = {
isa = PBXGroup;
children = (
EA6A9C2D515205854C4FC36F /* XcodeGen */,
17DD374CC81D710476AFF41C /* SPM */,
1FA59BFD192FB5A68D5F587C /* StaticLibrary */,
5D68FDDE55EE935627A1B376 /* Products */,
@@ -1,6 +1,15 @@
{
"object": {
"pins": [
{
"package": "AEXML",
"repositoryURL": "https://github.com/tadija/AEXML",
"state": {
"branch": null,
"revision": "e4d517844dd03dac557e35d77a8e9ab438de91a6",
"version": "4.4.0"
}
},
{
"package": "Codability",
"repositoryURL": "https://github.com/yonaskolb/Codability",
@@ -9,6 +18,78 @@
"revision": "eb5bac78e0679f521c3f058c1eb9be0dd657dadd",
"version": "0.2.1"
}
},
{
"package": "JSONUtilities",
"repositoryURL": "https://github.com/yonaskolb/JSONUtilities.git",
"state": {
"branch": null,
"revision": "128d2ffc22467f69569ef8ff971683e2393191a0",
"version": "4.2.0"
}
},
{
"package": "PathKit",
"repositoryURL": "https://github.com/kylef/PathKit.git",
"state": {
"branch": null,
"revision": "73f8e9dca9b7a3078cb79128217dc8f2e585a511",
"version": "1.0.0"
}
},
{
"package": "Rainbow",
"repositoryURL": "https://github.com/onevcat/Rainbow.git",
"state": {
"branch": null,
"revision": "9c52c1952e9b2305d4507cf473392ac2d7c9b155",
"version": "3.1.5"
}
},
{
"package": "Shell",
"repositoryURL": "https://github.com/tuist/Shell",
"state": {
"branch": null,
"revision": "d38121f89401db902b0d0bfc30b987e2c84c254e",
"version": "2.0.3"
}
},
{
"package": "Spectre",
"repositoryURL": "https://github.com/kylef/Spectre.git",
"state": {
"branch": null,
"revision": "f14ff47f45642aa5703900980b014c2e9394b6e5",
"version": "0.9.0"
}
},
{
"package": "SwiftCLI",
"repositoryURL": "https://github.com/jakeheis/SwiftCLI.git",
"state": {
"branch": null,
"revision": "5318c37d3cacc8780f50b87a8840a6774320ebdf",
"version": "5.2.2"
}
},
{
"package": "XcodeProj",
"repositoryURL": "https://github.com/tuist/xcodeproj.git",
"state": {
"branch": null,
"revision": "aefcbf59cea5b0831837ed2f385e6dfd80d82cc9",
"version": "7.1.0"
}
},
{
"package": "Yams",
"repositoryURL": "https://github.com/jpsim/Yams.git",
"state": {
"branch": null,
"revision": "c947a306d2e80ecb2c0859047b35c73b8e1ca27f",
"version": "2.0.0"
}
}
]
},
+2
View File
@@ -3,6 +3,8 @@ packages:
Codability:
url: https://github.com/yonaskolb/Codability
majorVersion: 0.2.1
localPackages:
- ../../.. #XcodeGen itself
targets:
App:
type: application
@@ -96,6 +96,7 @@ class ProjectSpecTests: XCTestCase {
project.settings = invalidSettings
project.configFiles = ["invalidConfig": "invalidConfigFile"]
project.fileGroups = ["invalidFileGroup"]
project.localPackages = ["invalidLocalPackage"]
project.settingGroups = ["settingGroup1": Settings(
configSettings: ["invalidSettingGroupConfig": [:]],
groups: ["invalidSettingGroupSettingGroup"]
@@ -106,6 +107,7 @@ class ProjectSpecTests: XCTestCase {
try expectValidationError(project, .invalidConfigFile(configFile: "invalidConfigFile", config: "invalidConfig"))
try expectValidationError(project, .invalidSettingsGroup("invalidSettingGroup"))
try expectValidationError(project, .invalidFileGroup("invalidFileGroup"))
try expectValidationError(project, .invalidLocalPackage("invalidLocalPackage"))
try expectValidationError(project, .invalidSettingsGroup("invalidSettingGroupSettingGroup"))
try expectValidationError(project, .invalidBuildSettingConfig("invalidSettingGroupConfig"))
}
@@ -467,6 +469,7 @@ class ProjectSpecTests: XCTestCase {
url: "https://github.com/jpsim/Yams",
versionRequirement: .upToNextMajorVersion("2.0.0"))
],
localPackages: ["../../Package"],
options: SpecOptions(minimumXcodeGenVersion: Version(major: 3, minor: 4, patch: 5),
carthageBuildPath: "carthageBuildPath",
carthageExecutablePath: "carthageExecutablePath",
@@ -969,7 +969,8 @@ class SpecLoadingTests: XCTestCase {
"package4": SwiftPackage(url: "package.git", versionRequirement: .branch("master")),
"package5": SwiftPackage(url: "package.git", versionRequirement: .revision("x")),
"package6": SwiftPackage(url: "package.git", versionRequirement: .range(from: "1.2.0", to: "1.2.5")),
])
],
localPackages: ["../../Package"])
let dictionary: [String: Any] = [
"name": "spm",
@@ -980,7 +981,9 @@ class SpecLoadingTests: XCTestCase {
"package4": ["url": "package.git", "branch": "master"],
"package5": ["url": "package.git", "revision": "x"],
"package6": ["url": "package.git", "minVersion": "1.2.0", "maxVersion": "1.2.5"],
]]
],
"localPackages": ["../../Package"]
]
let parsedSpec = try getProjectSpec(dictionary)
try expect(parsedSpec) == project
}