mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2024-09-20 09:08:46 +03:00
add target templates
This commit is contained in:
parent
a43a96075a
commit
c50d1dd157
@ -38,6 +38,7 @@ Required properties are marked with checkbox. Some of the YAML examples don't sh
|
||||
- [ ] **targets**: **[String: [Target](#target)]** - The list of targets in the project mapped by name
|
||||
- [ ] **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](#target)]** - 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`.
|
||||
|
||||
### Include
|
||||
|
||||
@ -163,6 +164,7 @@ Settings are merged in the following order: groups, base, configs.
|
||||
- `INFOPLIST_FILE`: If it doesn't exist your sources will be searched for `Info.plist` files and the first one found will be used for this setting
|
||||
- `FRAMEWORK_SEARCH_PATHS`: If carthage dependencies are used, the platform build path will be added to this setting
|
||||
- [ ] **dependencies**: **[[Dependency](#dependency)]** - Dependencies for the target
|
||||
- [ ] **templates**: **[String]** - A list of target templates that will be merged in order
|
||||
- [ ] **transitivelyLinkDependencies**: **Bool** - If this is not specified the value from the project set in [Options](#options)`.transitivelyLinkDependencies` will be used.
|
||||
- [ ] **prebuildScripts**: **[[Build Script](#build-script)]** - Build scripts that run *before* any other build phases
|
||||
- [ ] **postbuildScripts**: **[[Build Script](#build-script)]** - Build scripts that run *after* any other build phases
|
||||
|
@ -128,6 +128,6 @@ extension Project {
|
||||
}
|
||||
|
||||
static func filterJSON(jsonDictionary: JSONDictionary) throws -> JSONDictionary {
|
||||
return try Target.generateCrossPlaformTargets(jsonDictionary: jsonDictionary)
|
||||
return try Target.resolveTargets(jsonDictionary: jsonDictionary)
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,24 @@ extension Dictionary where Key == String, Value: Any {
|
||||
}
|
||||
}
|
||||
|
||||
func merge(dictionary: JSONDictionary, onto base: JSONDictionary) -> JSONDictionary {
|
||||
var merged = base
|
||||
|
||||
for (key, value) in dictionary {
|
||||
if key.hasSuffix(":REPLACE") {
|
||||
let newKey = key.replacingOccurrences(of: ":REPLACE", with: "")
|
||||
merged[newKey] = value
|
||||
} else if let dictionary = value as? JSONDictionary, let base = merged[key] as? JSONDictionary {
|
||||
merged[key] = merge(dictionary: dictionary, onto: base)
|
||||
} else if let array = value as? [Any], let base = merged[key] as? [Any] {
|
||||
merged[key] = base + array
|
||||
} else {
|
||||
merged[key] = value
|
||||
}
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
public func += (lhs: inout BuildSettings, rhs: BuildSettings?) {
|
||||
guard let rhs = rhs else { return }
|
||||
lhs.merge(rhs)
|
||||
|
@ -45,22 +45,4 @@ extension Project {
|
||||
}
|
||||
return json
|
||||
}
|
||||
|
||||
private static func merge(dictionary: JSONDictionary, onto base: JSONDictionary) -> JSONDictionary {
|
||||
var merged = base
|
||||
|
||||
for (key, value) in dictionary {
|
||||
if key.hasSuffix(":REPLACE") {
|
||||
let newKey = key.replacingOccurrences(of: ":REPLACE", with: "")
|
||||
merged[newKey] = value
|
||||
} else if let dictionary = value as? JSONDictionary, let base = merged[key] as? JSONDictionary {
|
||||
merged[key] = merge(dictionary: dictionary, onto: base)
|
||||
} else if let array = value as? [Any], let base = merged[key] as? [Any] {
|
||||
merged[key] = base + array
|
||||
} else {
|
||||
merged[key] = value
|
||||
}
|
||||
}
|
||||
return merged
|
||||
}
|
||||
}
|
||||
|
@ -95,11 +95,27 @@ extension Target: CustomStringConvertible {
|
||||
|
||||
extension Target {
|
||||
|
||||
static func generateCrossPlaformTargets(jsonDictionary: JSONDictionary) throws -> JSONDictionary {
|
||||
guard let targetsDictionary: [String: JSONDictionary] = jsonDictionary["targets"] as? [String: JSONDictionary] else {
|
||||
static func resolveTargets(jsonDictionary: JSONDictionary) throws -> JSONDictionary {
|
||||
guard var targetsDictionary: [String: JSONDictionary] = jsonDictionary["targets"] as? [String: JSONDictionary] else {
|
||||
return jsonDictionary
|
||||
}
|
||||
|
||||
let targetTemplatesDictionary: [String: JSONDictionary] = jsonDictionary["targetTemplates"] as? [String: JSONDictionary] ?? [:]
|
||||
|
||||
for (targetName, var target) in targetsDictionary {
|
||||
|
||||
if let templates = target["templates"] as? [String] {
|
||||
var mergedDictionary: JSONDictionary = [:]
|
||||
for template in templates {
|
||||
if let templateDictionary = targetTemplatesDictionary[template] {
|
||||
mergedDictionary = merge(dictionary: templateDictionary, onto: mergedDictionary)
|
||||
}
|
||||
}
|
||||
target = merge(dictionary: mergedDictionary, onto: target)
|
||||
}
|
||||
targetsDictionary[targetName] = target
|
||||
}
|
||||
|
||||
let platformReplacement = "$platform"
|
||||
var crossPlatformTargets: [String: JSONDictionary] = [:]
|
||||
|
||||
@ -156,6 +172,7 @@ extension Target {
|
||||
}
|
||||
}
|
||||
var merged = jsonDictionary
|
||||
|
||||
merged["targets"] = crossPlatformTargets
|
||||
return merged
|
||||
}
|
||||
|
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "NT_324671077936"
|
||||
BuildableName = "App_watchOS.app"
|
||||
BlueprintName = "App_watchOS"
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Production Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "NT_324671077936"
|
||||
BuildableName = "App_watchOS.app"
|
||||
BlueprintName = "App_watchOS"
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Production Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "NT_324671077936"
|
||||
BuildableName = "App_watchOS.app"
|
||||
BlueprintName = "App_watchOS"
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Production Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "NT_324671077936"
|
||||
BuildableName = "App_watchOS.app"
|
||||
BlueprintName = "App_watchOS"
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Production Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Production Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -80,6 +80,7 @@ targets:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.project.app.watch
|
||||
dependencies:
|
||||
- target: App_watchOS Extension
|
||||
templates: [MyTemplate]
|
||||
|
||||
App_watchOS Extension:
|
||||
type: watchkit2-extension
|
||||
@ -148,3 +149,6 @@ schemes:
|
||||
commandLineArguments:
|
||||
argument: YES
|
||||
argument.with.dot: YES
|
||||
targetTemplates:
|
||||
MyTemplate:
|
||||
scheme: {}
|
||||
|
@ -12,6 +12,9 @@ targets:
|
||||
NewTarget:
|
||||
type: application
|
||||
platform: iOS
|
||||
templates: [IncludedTemplate]
|
||||
sources:
|
||||
- folder1
|
||||
IncludedTarget:
|
||||
name: IncludedTargetNew
|
||||
platform: tvOS
|
||||
|
@ -11,3 +11,7 @@ targets:
|
||||
platform: iOS
|
||||
sources:
|
||||
- Target
|
||||
targetTemplates:
|
||||
IncludedTemplate:
|
||||
sources:
|
||||
- folder2
|
||||
|
@ -22,7 +22,7 @@ class SpecLoadingTests: XCTestCase {
|
||||
]
|
||||
try expect(project.targets) == [
|
||||
Target(name: "IncludedTargetNew", type: .application, platform: .tvOS, sources: ["NewSource"]),
|
||||
Target(name: "NewTarget", type: .application, platform: .iOS),
|
||||
Target(name: "NewTarget", type: .application, platform: .iOS, sources: ["folder1", "folder2"]),
|
||||
]
|
||||
}
|
||||
|
||||
@ -176,6 +176,26 @@ class SpecLoadingTests: XCTestCase {
|
||||
try expect(project.targets) == [target_iOS, target_tvOS]
|
||||
}
|
||||
|
||||
$0.it("parses target templates") {
|
||||
|
||||
let targetDictionary: [String: Any] = [
|
||||
"type": "framework",
|
||||
"templates": ["temp2", "temp"]
|
||||
]
|
||||
|
||||
let project = try getProjectSpec([
|
||||
"targets": ["Framework": targetDictionary],
|
||||
"targetTemplates": [
|
||||
"temp": ["platform": "iOS"],
|
||||
"temp2": ["platform": "tvOS"],
|
||||
]
|
||||
])
|
||||
|
||||
let target = Target(name: "Framework", type: .framework, platform: .iOS)
|
||||
|
||||
try expect(project.targets.first) == target
|
||||
}
|
||||
|
||||
$0.it("parses target schemes") {
|
||||
var targetDictionary = validTarget
|
||||
targetDictionary["scheme"] = [
|
||||
|
Loading…
Reference in New Issue
Block a user