mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2026-03-18 20:02:25 +00:00
add aggregate targets
This commit is contained in:
@@ -23,6 +23,7 @@ Required properties are marked with checkbox. Some of the YAML examples don't sh
|
||||
- [Dependency](#dependency)
|
||||
- [Target Scheme](#target-scheme)
|
||||
- [Legacy Target](#legacy-target)
|
||||
- [Aggregate Target](#aggregate-target)
|
||||
- [Scheme](#scheme)
|
||||
|
||||
## Project
|
||||
@@ -449,6 +450,16 @@ By providing a legacy target, you are opting in to the "Legacy Target" mode. Thi
|
||||
- [ ] ***passSettings***: Bool - Whether or not to pass build settings down to the build tool in the legacy target.
|
||||
- [ ] ***workingDirectory***: String - The working directory under which the build tool will be invoked in the legacy target.
|
||||
|
||||
## Aggregate Target
|
||||
|
||||
This is used to override settings or run build scripts in specific targets
|
||||
|
||||
- [x] **targets**: **[String]** - The list of target names to include as target dependencies
|
||||
- [ ] **configFiles**: **[Config Files](#config-files)** - `.xcconfig` files per config
|
||||
- [ ] **settings**: **[Settings](#settings)** - Target specific build settings.
|
||||
- [ ] **buildScripts**: **[[Build Script](#build-script)]** - Build scripts to run
|
||||
- [ ] **scheme**: **[Target Scheme](#target-scheme)** - Generated scheme
|
||||
|
||||
## Scheme
|
||||
|
||||
Schemes allows for more control than the convenience [Target Scheme](#target-scheme) on [Target](#target)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import Foundation
|
||||
import JSONUtilities
|
||||
|
||||
public struct AggregateTarget: ProjectTarget, Equatable {
|
||||
public var name: String
|
||||
public var targets: [String]
|
||||
public var settings: Settings
|
||||
public var buildScripts: [BuildScript]
|
||||
public var configFiles: [String: String]
|
||||
public var scheme: TargetScheme?
|
||||
|
||||
public init(
|
||||
name: String,
|
||||
targets: [String],
|
||||
settings: Settings = .empty,
|
||||
configFiles: [String: String] = [:],
|
||||
buildScripts: [BuildScript] = [],
|
||||
scheme: TargetScheme? = nil
|
||||
) {
|
||||
self.name = name
|
||||
self.targets = targets
|
||||
self.settings = settings
|
||||
self.configFiles = configFiles
|
||||
self.buildScripts = buildScripts
|
||||
self.scheme = scheme
|
||||
}
|
||||
}
|
||||
|
||||
extension AggregateTarget: CustomStringConvertible {
|
||||
|
||||
public var description: String {
|
||||
return "\(name): \(targets.joined(separator: ", "))"
|
||||
}
|
||||
}
|
||||
|
||||
extension AggregateTarget: NamedJSONDictionaryConvertible {
|
||||
|
||||
public init(name: String, jsonDictionary: JSONDictionary) throws {
|
||||
self.name = jsonDictionary.json(atKeyPath: "name") ?? name
|
||||
targets = jsonDictionary.json(atKeyPath: "targets") ?? []
|
||||
settings = jsonDictionary.json(atKeyPath: "settings") ?? .empty
|
||||
configFiles = jsonDictionary.json(atKeyPath: "configFiles") ?? [:]
|
||||
buildScripts = jsonDictionary.json(atKeyPath: "buildScripts") ?? []
|
||||
scheme = jsonDictionary.json(atKeyPath: "scheme")
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ public struct Project {
|
||||
targetsMap = Dictionary(uniqueKeysWithValues: targets.map { ($0.name, $0) })
|
||||
}
|
||||
}
|
||||
public var aggregateTargets: [AggregateTarget]
|
||||
|
||||
public var settings: Settings
|
||||
public var settingGroups: [String: Settings]
|
||||
@@ -30,6 +31,7 @@ public struct Project {
|
||||
name: String,
|
||||
configs: [Config] = Config.defaultConfigs,
|
||||
targets: [Target] = [],
|
||||
aggregateTargets: [AggregateTarget] = [],
|
||||
settings: Settings = .empty,
|
||||
settingGroups: [String: Settings] = [:],
|
||||
schemes: [Scheme] = [],
|
||||
@@ -42,6 +44,7 @@ public struct Project {
|
||||
self.name = name
|
||||
self.targets = targets
|
||||
targetsMap = Dictionary(uniqueKeysWithValues: self.targets.map { ($0.name, $0) })
|
||||
self.aggregateTargets = aggregateTargets
|
||||
self.configs = configs
|
||||
self.settings = settings
|
||||
self.settingGroups = settingGroups
|
||||
@@ -80,6 +83,9 @@ extension Project: CustomDebugStringConvertible {
|
||||
if !targets.isEmpty {
|
||||
string += "\nTargets:\n\(indent)" + targets.map { $0.description }.joined(separator: "\n\(indent)")
|
||||
}
|
||||
if !aggregateTargets.isEmpty {
|
||||
string += "\nAggregate Targets:\n\(indent)" + aggregateTargets.map { $0.description }.joined(separator: "\n\(indent)")
|
||||
}
|
||||
|
||||
return string
|
||||
}
|
||||
@@ -90,6 +96,7 @@ extension Project: Equatable {
|
||||
public static func == (lhs: Project, rhs: Project) -> Bool {
|
||||
return lhs.name == rhs.name &&
|
||||
lhs.targets == rhs.targets &&
|
||||
lhs.aggregateTargets == rhs.aggregateTargets &&
|
||||
lhs.settings == rhs.settings &&
|
||||
lhs.settingGroups == rhs.settingGroups &&
|
||||
lhs.configs == rhs.configs &&
|
||||
@@ -114,6 +121,7 @@ extension Project {
|
||||
self.configs = configs.isEmpty ? Config.defaultConfigs :
|
||||
configs.map { Config(name: $0, type: ConfigType(rawValue: $1)) }.sorted { $0.name < $1.name }
|
||||
targets = try jsonDictionary.json(atKeyPath: "targets").sorted { $0.name < $1.name }
|
||||
aggregateTargets = try jsonDictionary.json(atKeyPath: "aggregateTargets").sorted { $0.name < $1.name }
|
||||
schemes = try jsonDictionary.json(atKeyPath: "schemes")
|
||||
fileGroups = jsonDictionary.json(atKeyPath: "fileGroups") ?? []
|
||||
configFiles = jsonDictionary.json(atKeyPath: "configFiles") ?? [:]
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// ProjectTarget.swift
|
||||
// ProjectSpec
|
||||
//
|
||||
// Created by Yonas Kolb on 22/7/18.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol ProjectTarget {
|
||||
|
||||
var name: String { get }
|
||||
var settings: Settings { get }
|
||||
var buildScripts: [BuildScript] { get }
|
||||
var configFiles: [String: String] { get }
|
||||
var scheme: TargetScheme? { get }
|
||||
}
|
||||
|
||||
extension Target {
|
||||
|
||||
var buildScripts: [BuildScript] {
|
||||
return prebuildScripts + postbuildScripts
|
||||
}
|
||||
}
|
||||
@@ -53,12 +53,9 @@ extension Project {
|
||||
errors += validateSettings(settings)
|
||||
}
|
||||
|
||||
for target in targets {
|
||||
for dependency in target.dependencies {
|
||||
if dependency.type == .target, getTarget(dependency.reference) == nil {
|
||||
errors.append(.invalidTargetDependency(target: target.name, dependency: dependency.reference))
|
||||
}
|
||||
}
|
||||
let projectTargets: [ProjectTarget] = targets.map { $0 as ProjectTarget } + aggregateTargets.map { $0 as ProjectTarget }
|
||||
|
||||
for target in projectTargets {
|
||||
|
||||
for (config, configFile) in target.configFiles {
|
||||
if !(basePath + configFile).exists {
|
||||
@@ -69,13 +66,6 @@ extension Project {
|
||||
}
|
||||
}
|
||||
|
||||
for source in target.sources {
|
||||
let sourcePath = basePath + source.path
|
||||
if !source.optional && !sourcePath.exists {
|
||||
errors.append(.invalidTargetSource(target: target.name, source: sourcePath.string))
|
||||
}
|
||||
}
|
||||
|
||||
if let scheme = target.scheme {
|
||||
|
||||
for configVariant in scheme.configVariants {
|
||||
@@ -84,14 +74,14 @@ extension Project {
|
||||
target: target.name,
|
||||
configVariant: configVariant,
|
||||
configType: .debug
|
||||
))
|
||||
))
|
||||
}
|
||||
if !configs.contains(where: { $0.name.contains(configVariant) && $0.type == .release }) {
|
||||
errors.append(.invalidTargetSchemeConfigVariant(
|
||||
target: target.name,
|
||||
configVariant: configVariant,
|
||||
configType: .release
|
||||
))
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +101,7 @@ extension Project {
|
||||
}
|
||||
}
|
||||
|
||||
let scripts = target.prebuildScripts + target.postbuildScripts
|
||||
for script in scripts {
|
||||
for script in target.buildScripts {
|
||||
if case let .path(pathString) = script.script {
|
||||
let scriptPath = basePath + pathString
|
||||
if !scriptPath.exists {
|
||||
@@ -124,6 +113,29 @@ extension Project {
|
||||
errors += validateSettings(target.settings)
|
||||
}
|
||||
|
||||
for target in aggregateTargets {
|
||||
for dependency in target.targets {
|
||||
if getTarget(dependency) == nil {
|
||||
errors.append(.invalidTargetDependency(target: target.name, dependency: dependency))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for target in targets {
|
||||
for dependency in target.dependencies {
|
||||
if dependency.type == .target, getTarget(dependency.reference) == nil {
|
||||
errors.append(.invalidTargetDependency(target: target.name, dependency: dependency.reference))
|
||||
}
|
||||
}
|
||||
|
||||
for source in target.sources {
|
||||
let sourcePath = basePath + source.path
|
||||
if !source.optional && !sourcePath.exists {
|
||||
errors.append(.invalidTargetSource(target: target.name, source: sourcePath.string))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for scheme in schemes {
|
||||
for buildTarget in scheme.build.targets {
|
||||
if getTarget(buildTarget.target) == nil {
|
||||
|
||||
@@ -21,7 +21,7 @@ public struct LegacyTarget: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct Target {
|
||||
public struct Target: ProjectTarget {
|
||||
public var name: String
|
||||
public var type: PBXProductType
|
||||
public var platform: Platform
|
||||
@@ -209,47 +209,6 @@ extension Target: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct TargetScheme: Equatable {
|
||||
public var testTargets: [String]
|
||||
public var configVariants: [String]
|
||||
public var gatherCoverageData: Bool
|
||||
public var commandLineArguments: [String: Bool]
|
||||
public var environmentVariables: [XCScheme.EnvironmentVariable]
|
||||
public var preActions: [Scheme.ExecutionAction]
|
||||
public var postActions: [Scheme.ExecutionAction]
|
||||
|
||||
public init(
|
||||
testTargets: [String] = [],
|
||||
configVariants: [String] = [],
|
||||
gatherCoverageData: Bool = false,
|
||||
commandLineArguments: [String: Bool] = [:],
|
||||
environmentVariables: [XCScheme.EnvironmentVariable] = [],
|
||||
preActions: [Scheme.ExecutionAction] = [],
|
||||
postActions: [Scheme.ExecutionAction] = []
|
||||
) {
|
||||
self.testTargets = testTargets
|
||||
self.configVariants = configVariants
|
||||
self.gatherCoverageData = gatherCoverageData
|
||||
self.commandLineArguments = commandLineArguments
|
||||
self.environmentVariables = environmentVariables
|
||||
self.preActions = preActions
|
||||
self.postActions = postActions
|
||||
}
|
||||
}
|
||||
|
||||
extension TargetScheme: JSONObjectConvertible {
|
||||
|
||||
public init(jsonDictionary: JSONDictionary) throws {
|
||||
testTargets = jsonDictionary.json(atKeyPath: "testTargets") ?? []
|
||||
configVariants = jsonDictionary.json(atKeyPath: "configVariants") ?? []
|
||||
gatherCoverageData = jsonDictionary.json(atKeyPath: "gatherCoverageData") ?? false
|
||||
commandLineArguments = jsonDictionary.json(atKeyPath: "commandLineArguments") ?? [:]
|
||||
environmentVariables = try XCScheme.EnvironmentVariable.parseAll(jsonDictionary: jsonDictionary)
|
||||
preActions = jsonDictionary.json(atKeyPath: "preActions") ?? []
|
||||
postActions = jsonDictionary.json(atKeyPath: "postActions") ?? []
|
||||
}
|
||||
}
|
||||
|
||||
extension LegacyTarget: JSONObjectConvertible {
|
||||
|
||||
public init(jsonDictionary: JSONDictionary) throws {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import Foundation
|
||||
import JSONUtilities
|
||||
import xcproj
|
||||
|
||||
public struct TargetScheme: Equatable {
|
||||
public var testTargets: [String]
|
||||
public var configVariants: [String]
|
||||
public var gatherCoverageData: Bool
|
||||
public var commandLineArguments: [String: Bool]
|
||||
public var environmentVariables: [XCScheme.EnvironmentVariable]
|
||||
public var preActions: [Scheme.ExecutionAction]
|
||||
public var postActions: [Scheme.ExecutionAction]
|
||||
|
||||
public init(
|
||||
testTargets: [String] = [],
|
||||
configVariants: [String] = [],
|
||||
gatherCoverageData: Bool = false,
|
||||
commandLineArguments: [String: Bool] = [:],
|
||||
environmentVariables: [XCScheme.EnvironmentVariable] = [],
|
||||
preActions: [Scheme.ExecutionAction] = [],
|
||||
postActions: [Scheme.ExecutionAction] = []
|
||||
) {
|
||||
self.testTargets = testTargets
|
||||
self.configVariants = configVariants
|
||||
self.gatherCoverageData = gatherCoverageData
|
||||
self.commandLineArguments = commandLineArguments
|
||||
self.environmentVariables = environmentVariables
|
||||
self.preActions = preActions
|
||||
self.postActions = postActions
|
||||
}
|
||||
}
|
||||
|
||||
extension TargetScheme: JSONObjectConvertible {
|
||||
|
||||
public init(jsonDictionary: JSONDictionary) throws {
|
||||
testTargets = jsonDictionary.json(atKeyPath: "testTargets") ?? []
|
||||
configVariants = jsonDictionary.json(atKeyPath: "configVariants") ?? []
|
||||
gatherCoverageData = jsonDictionary.json(atKeyPath: "gatherCoverageData") ?? false
|
||||
commandLineArguments = jsonDictionary.json(atKeyPath: "commandLineArguments") ?? [:]
|
||||
environmentVariables = try XCScheme.EnvironmentVariable.parseAll(jsonDictionary: jsonDictionary)
|
||||
preActions = jsonDictionary.json(atKeyPath: "preActions") ?? []
|
||||
postActions = jsonDictionary.json(atKeyPath: "postActions") ?? []
|
||||
}
|
||||
}
|
||||
@@ -150,6 +150,7 @@ public class PBXProjGenerator {
|
||||
}
|
||||
|
||||
try project.targets.forEach(generateTarget)
|
||||
try project.aggregateTargets.forEach(generateAggregateTarget)
|
||||
|
||||
let productGroup = createObject(
|
||||
id: "Products",
|
||||
@@ -218,6 +219,92 @@ public class PBXProjGenerator {
|
||||
return pbxProj
|
||||
}
|
||||
|
||||
func generateAggregateTarget(_ target: AggregateTarget) throws {
|
||||
|
||||
let configs: [ObjectReference<XCBuildConfiguration>] = project.configs.map { config in
|
||||
|
||||
let buildSettings = project.getBuildSettings(settings: target.settings, config: config)
|
||||
|
||||
var baseConfigurationReference: String?
|
||||
if let configPath = target.configFiles[config.name] {
|
||||
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: project.basePath + configPath)
|
||||
}
|
||||
let buildConfig = XCBuildConfiguration(
|
||||
name: config.name,
|
||||
baseConfigurationReference: baseConfigurationReference,
|
||||
buildSettings: buildSettings
|
||||
)
|
||||
return createObject(id: config.name + target.name, buildConfig)
|
||||
}
|
||||
|
||||
let dependencies: [String] = target.targets.map { generateTargetDependency(from: target.name, to: $0).reference }
|
||||
|
||||
let buildConfigList = createObject(id: target.name, XCConfigurationList(
|
||||
buildConfigurations: configs.map { $0.reference },
|
||||
defaultConfigurationName: ""
|
||||
))
|
||||
|
||||
var buildPhases: [String] = []
|
||||
buildPhases += try target.buildScripts.map { try generateBuildScript(targetName: target.name, buildScript: $0) }
|
||||
|
||||
let aggregateTarget = PBXAggregateTarget(name: target.name,
|
||||
buildConfigurationList:
|
||||
buildConfigList.reference,
|
||||
buildPhases: buildPhases,
|
||||
buildRules: [],
|
||||
dependencies: dependencies,
|
||||
productName: target.name,
|
||||
productReference: nil,
|
||||
productType: nil
|
||||
)
|
||||
_ = addObject(id: target.name, aggregateTarget)
|
||||
}
|
||||
|
||||
func generateTargetDependency(from: String, to target: String) -> ObjectReference<PBXTargetDependency> {
|
||||
|
||||
let targetProxy = createObject(
|
||||
id: "\(from)-\(target)",
|
||||
PBXContainerItemProxy(
|
||||
containerPortal: pbxProj.rootObject,
|
||||
remoteGlobalIDString: targetObjects[target]!.reference,
|
||||
proxyType: .nativeTarget,
|
||||
remoteInfo: target
|
||||
)
|
||||
)
|
||||
|
||||
let targetDependency = createObject(
|
||||
id: "\(from)-\(target)",
|
||||
PBXTargetDependency(
|
||||
target: targetObjects[target]!.reference,
|
||||
targetProxy: targetProxy.reference
|
||||
)
|
||||
)
|
||||
return targetDependency
|
||||
}
|
||||
|
||||
func generateBuildScript(targetName: String, buildScript: BuildScript) throws -> String {
|
||||
|
||||
let shellScript: String
|
||||
switch buildScript.script {
|
||||
case let .path(path):
|
||||
shellScript = try (project.basePath + path).read()
|
||||
case let .script(script):
|
||||
shellScript = script
|
||||
}
|
||||
|
||||
let shellScriptPhase = PBXShellScriptBuildPhase(
|
||||
files: [],
|
||||
name: buildScript.name ?? "Run Script",
|
||||
inputPaths: buildScript.inputFiles,
|
||||
outputPaths: buildScript.outputFiles,
|
||||
shellPath: buildScript.shell ?? "/bin/sh",
|
||||
shellScript: shellScript
|
||||
)
|
||||
shellScriptPhase.runOnlyForDeploymentPostprocessing = buildScript.runOnlyWhenInstalling
|
||||
shellScriptPhase.showEnvVarsInLog = buildScript.showEnvVars
|
||||
return createObject(id: String(describing: buildScript.name) + shellScript + targetName, shellScriptPhase).reference
|
||||
}
|
||||
|
||||
func generateTargetAttributes() -> [String: Any]? {
|
||||
|
||||
var targetAttributes: [String: [String: Any]] = [:]
|
||||
@@ -415,23 +502,7 @@ public class PBXProjGenerator {
|
||||
guard let dependencyTarget = project.getTarget(dependencyTargetName) else { continue }
|
||||
let dependencyFileReference = targetFileReferences[dependencyTargetName]!
|
||||
|
||||
let targetProxy = createObject(
|
||||
id: "\(target.name)-\(dependency.reference)",
|
||||
PBXContainerItemProxy(
|
||||
containerPortal: pbxProj.rootObject,
|
||||
remoteGlobalIDString: targetObjects[dependencyTargetName]!.reference,
|
||||
proxyType: .nativeTarget,
|
||||
remoteInfo: dependencyTargetName
|
||||
)
|
||||
)
|
||||
|
||||
let targetDependency = createObject(
|
||||
id: dependencyTargetName + target.name,
|
||||
PBXTargetDependency(
|
||||
target: targetObjects[dependencyTargetName]!.reference,
|
||||
targetProxy: targetProxy.reference
|
||||
)
|
||||
)
|
||||
let targetDependency = generateTargetDependency(from: target.name, to: dependencyTargetName)
|
||||
|
||||
dependencies.append(targetDependency.reference)
|
||||
|
||||
@@ -549,31 +620,7 @@ public class PBXProjGenerator {
|
||||
.map { $0.reference }
|
||||
}
|
||||
|
||||
func generateBuildScript(buildScript: BuildScript) throws {
|
||||
|
||||
let shellScript: String
|
||||
switch buildScript.script {
|
||||
case let .path(path):
|
||||
shellScript = try (project.basePath + path).read()
|
||||
case let .script(script):
|
||||
shellScript = script
|
||||
}
|
||||
|
||||
let shellScriptPhase = PBXShellScriptBuildPhase(
|
||||
files: [],
|
||||
name: buildScript.name ?? "Run Script",
|
||||
inputPaths: buildScript.inputFiles,
|
||||
outputPaths: buildScript.outputFiles,
|
||||
shellPath: buildScript.shell ?? "/bin/sh",
|
||||
shellScript: shellScript
|
||||
)
|
||||
shellScriptPhase.runOnlyForDeploymentPostprocessing = buildScript.runOnlyWhenInstalling
|
||||
shellScriptPhase.showEnvVarsInLog = buildScript.showEnvVars
|
||||
let shellScriptPhaseReference = createObject(id: String(describing: buildScript.name) + shellScript + target.name, shellScriptPhase)
|
||||
buildPhases.append(shellScriptPhaseReference.reference)
|
||||
}
|
||||
|
||||
try target.prebuildScripts.forEach(generateBuildScript)
|
||||
buildPhases += try target.prebuildScripts.map { try generateBuildScript(targetName: target.name, buildScript: $0) }
|
||||
|
||||
let sourcesBuildPhaseFiles = getBuildFilesForPhase(.sources)
|
||||
let sourcesBuildPhase = createObject(id: target.name, PBXSourcesBuildPhase(files: sourcesBuildPhaseFiles))
|
||||
@@ -687,7 +734,7 @@ public class PBXProjGenerator {
|
||||
).reference
|
||||
}
|
||||
|
||||
try target.postbuildScripts.forEach(generateBuildScript)
|
||||
buildPhases += try target.postbuildScripts.map { try generateBuildScript(targetName: target.name, buildScript: $0) }
|
||||
|
||||
let targetObject = targetObjects[target.name]!.object
|
||||
|
||||
|
||||
@@ -6,6 +6,22 @@
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
AT_445731917037 /* SuperTarget */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = CL_445731917037 /* Build configuration list for PBXAggregateTarget "SuperTarget" */;
|
||||
buildPhases = (
|
||||
SSBP_8280041834 /* MyScript */,
|
||||
);
|
||||
dependencies = (
|
||||
TD_208010900457 /* PBXTargetDependency */,
|
||||
TD_747418473860 /* PBXTargetDependency */,
|
||||
);
|
||||
name = SuperTarget;
|
||||
productName = SuperTarget;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
BF_130062884703 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FR_257516580010 /* Alamofire.framework */; };
|
||||
BF_138356261076 /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FR_363921640403 /* InterfaceController.swift */; };
|
||||
@@ -90,6 +106,13 @@
|
||||
remoteGlobalIDString = NT_507023492251;
|
||||
remoteInfo = "App_watchOS Extension";
|
||||
};
|
||||
CIP_20801090045 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = P_8448771205358 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = NT_825232110500;
|
||||
remoteInfo = App_iOS;
|
||||
};
|
||||
CIP_28856087625 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = P_8448771205358 /* Project object */;
|
||||
@@ -132,6 +155,13 @@
|
||||
remoteGlobalIDString = NT_399755008402;
|
||||
remoteInfo = StaticLibrary_ObjC;
|
||||
};
|
||||
CIP_74741847386 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = P_8448771205358 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = NT_472296042419;
|
||||
remoteInfo = Framework_iOS;
|
||||
};
|
||||
CIP_78441234790 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = P_8448771205358 /* Project object */;
|
||||
@@ -642,7 +672,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_432517223942 /* PBXTargetDependency */,
|
||||
TD_676191581124 /* PBXTargetDependency */,
|
||||
);
|
||||
name = App_iOS_UITests;
|
||||
productName = App_iOS_UITests;
|
||||
@@ -662,7 +692,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_249869083204 /* PBXTargetDependency */,
|
||||
TD_193291182921 /* PBXTargetDependency */,
|
||||
);
|
||||
name = App_watchOS;
|
||||
productName = App_watchOS;
|
||||
@@ -696,7 +726,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_562366646359 /* PBXTargetDependency */,
|
||||
TD_784412347908 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Framework_watchOS;
|
||||
productName = Framework_watchOS;
|
||||
@@ -715,7 +745,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_202479103763 /* PBXTargetDependency */,
|
||||
TD_667455552356 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Framework_iOS;
|
||||
productName = Framework_iOS;
|
||||
@@ -751,7 +781,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_698828390883 /* PBXTargetDependency */,
|
||||
TD_337103940101 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Framework_macOS;
|
||||
productName = Framework_macOS;
|
||||
@@ -786,7 +816,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_883611297273 /* PBXTargetDependency */,
|
||||
TD_957476409477 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Framework_tvOS;
|
||||
productName = Framework_tvOS;
|
||||
@@ -803,7 +833,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_436638162860 /* PBXTargetDependency */,
|
||||
TD_887143865471 /* PBXTargetDependency */,
|
||||
);
|
||||
name = App_iOS_Tests;
|
||||
productName = App_iOS_Tests;
|
||||
@@ -826,10 +856,10 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_257389546865 /* PBXTargetDependency */,
|
||||
TD_354342487294 /* PBXTargetDependency */,
|
||||
TD_490183489588 /* PBXTargetDependency */,
|
||||
TD_669996692733 /* PBXTargetDependency */,
|
||||
TD_824101787753 /* PBXTargetDependency */,
|
||||
TD_109724965966 /* PBXTargetDependency */,
|
||||
TD_721522128177 /* PBXTargetDependency */,
|
||||
TD_288560876254 /* PBXTargetDependency */,
|
||||
);
|
||||
name = App_iOS;
|
||||
productName = App_iOS;
|
||||
@@ -847,7 +877,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
TD_762620471828 /* PBXTargetDependency */,
|
||||
TD_317921131342 /* PBXTargetDependency */,
|
||||
);
|
||||
name = iMessageApp;
|
||||
productName = iMessageApp;
|
||||
@@ -1088,6 +1118,20 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"You ran a script\"\n";
|
||||
};
|
||||
SSBP_8280041834 /* MyScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = MyScript;
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"do the thing\"";
|
||||
};
|
||||
SSBP_8706434794 /* MyScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1215,62 +1259,72 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
TD_202479103763 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_66745555235 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_249869083204 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_507023492251 /* App_watchOS Extension */;
|
||||
targetProxy = CIP_19329118292 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_257389546865 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_324671077936 /* App_watchOS */;
|
||||
targetProxy = CIP_82410178775 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_354342487294 /* PBXTargetDependency */ = {
|
||||
TD_109724965966 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_472296042419 /* Framework_iOS */;
|
||||
targetProxy = CIP_10972496596 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_432517223942 /* PBXTargetDependency */ = {
|
||||
TD_193291182921 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_507023492251 /* App_watchOS Extension */;
|
||||
targetProxy = CIP_19329118292 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_208010900457 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_825232110500 /* App_iOS */;
|
||||
targetProxy = CIP_67619158112 /* PBXContainerItemProxy */;
|
||||
targetProxy = CIP_20801090045 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_436638162860 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_825232110500 /* App_iOS */;
|
||||
targetProxy = CIP_88714386547 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_490183489588 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_72152212817 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_562366646359 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_78441234790 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_669996692733 /* PBXTargetDependency */ = {
|
||||
TD_288560876254 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_935153865209 /* iMessageApp */;
|
||||
targetProxy = CIP_28856087625 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_698828390883 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_33710394010 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_762620471828 /* PBXTargetDependency */ = {
|
||||
TD_317921131342 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_618687462494 /* iMessageExtension */;
|
||||
targetProxy = CIP_31792113134 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_883611297273 /* PBXTargetDependency */ = {
|
||||
TD_337103940101 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_33710394010 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_667455552356 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_66745555235 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_676191581124 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_825232110500 /* App_iOS */;
|
||||
targetProxy = CIP_67619158112 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_721522128177 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_72152212817 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_747418473860 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_472296042419 /* Framework_iOS */;
|
||||
targetProxy = CIP_74741847386 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_784412347908 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_78441234790 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_824101787753 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_324671077936 /* App_watchOS */;
|
||||
targetProxy = CIP_82410178775 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_887143865471 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_825232110500 /* App_iOS */;
|
||||
targetProxy = CIP_88714386547 /* PBXContainerItemProxy */;
|
||||
};
|
||||
TD_957476409477 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = NT_399755008402 /* StaticLibrary_ObjC */;
|
||||
targetProxy = CIP_95747640947 /* PBXContainerItemProxy */;
|
||||
@@ -1365,6 +1419,13 @@
|
||||
};
|
||||
name = "Test Debug";
|
||||
};
|
||||
BC_122527152613 /* Test Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
MY_SETTING = hello;
|
||||
};
|
||||
name = "Test Release";
|
||||
};
|
||||
BC_128103534773 /* Production Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -1719,6 +1780,13 @@
|
||||
};
|
||||
name = "Staging Debug";
|
||||
};
|
||||
BC_334821934458 /* Production Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
MY_SETTING = hello;
|
||||
};
|
||||
name = "Production Release";
|
||||
};
|
||||
BC_351179072988 /* Test Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -1777,6 +1845,13 @@
|
||||
};
|
||||
name = "Production Release";
|
||||
};
|
||||
BC_370290618113 /* Production Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
MY_SETTING = hello;
|
||||
};
|
||||
name = "Production Debug";
|
||||
};
|
||||
BC_380703106572 /* Test Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -1903,6 +1978,13 @@
|
||||
};
|
||||
name = "Production Release";
|
||||
};
|
||||
BC_439666751882 /* Staging Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
MY_SETTING = hello;
|
||||
};
|
||||
name = "Staging Debug";
|
||||
};
|
||||
BC_444705348320 /* Staging Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -1936,6 +2018,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.project.StaticLibrary-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = "Test Release";
|
||||
@@ -2291,6 +2374,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.project.StaticLibrary-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = "Production Release";
|
||||
@@ -2343,6 +2427,13 @@
|
||||
};
|
||||
name = "Production Release";
|
||||
};
|
||||
BC_612244244384 /* Test Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
MY_SETTING = hello;
|
||||
};
|
||||
name = "Test Debug";
|
||||
};
|
||||
BC_622471558373 /* Production Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -2374,6 +2465,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.project.StaticLibrary-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = "Production Debug";
|
||||
@@ -2605,6 +2697,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.project.StaticLibrary-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = "Staging Debug";
|
||||
@@ -2789,6 +2882,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.project.StaticLibrary-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = "Staging Release";
|
||||
@@ -2985,6 +3079,13 @@
|
||||
};
|
||||
name = "Test Debug";
|
||||
};
|
||||
BC_851086512031 /* Staging Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
MY_SETTING = hello;
|
||||
};
|
||||
name = "Staging Release";
|
||||
};
|
||||
BC_864485046941 /* Staging Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -3008,6 +3109,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.project.StaticLibrary-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = "Test Debug";
|
||||
@@ -3092,6 +3194,19 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "";
|
||||
};
|
||||
CL_445731917037 /* Build configuration list for PBXAggregateTarget "SuperTarget" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
BC_370290618113 /* Production Debug */,
|
||||
BC_334821934458 /* Production Release */,
|
||||
BC_439666751882 /* Staging Debug */,
|
||||
BC_851086512031 /* Staging Release */,
|
||||
BC_612244244384 /* Test Debug */,
|
||||
BC_122527152613 /* Test Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "";
|
||||
};
|
||||
CL_472296042419 /* Build configuration list for PBXNativeTarget "Framework_iOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -158,3 +158,13 @@ schemes:
|
||||
targetTemplates:
|
||||
MyTemplate:
|
||||
scheme: {}
|
||||
aggregateTargets:
|
||||
SuperTarget:
|
||||
targets:
|
||||
- App_iOS
|
||||
- Framework_iOS
|
||||
settings:
|
||||
MY_SETTING: hello
|
||||
buildScripts:
|
||||
- name: MyScript
|
||||
script: echo "do the thing"
|
||||
|
||||
@@ -187,6 +187,29 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
func testAggregateTargets() {
|
||||
describe {
|
||||
|
||||
let aggregateTarget = AggregateTarget(name: "AggregateTarget", targets: ["MyApp", "MyFramework"] )
|
||||
let project = Project(basePath: "", name: "test", targets: targets, aggregateTargets: [aggregateTarget])
|
||||
|
||||
$0.it("generates aggregate targets") {
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let aggregateTargets = pbxProject.objects.aggregateTargets.referenceValues
|
||||
try expect(aggregateTargets.count) == 1
|
||||
guard let pbxAggregateTarget = aggregateTargets.first else {
|
||||
throw failure("Couldn't find AggregateTarget")
|
||||
}
|
||||
|
||||
try expect(pbxAggregateTarget.name) == "AggregateTarget"
|
||||
try expect(pbxAggregateTarget.dependencies.count) == 2
|
||||
|
||||
let targetDependencies = pbxProject.objects.targetDependencies.referenceValues
|
||||
try expect(targetDependencies.count) == 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testTargets() {
|
||||
describe {
|
||||
|
||||
|
||||
@@ -132,6 +132,31 @@ class ProjectSpecTests: XCTestCase {
|
||||
try expectValidationError(project, .invalidTargetSchemeConfigVariant(target: "target1", configVariant: "invalidVariant", configType: .debug))
|
||||
}
|
||||
|
||||
$0.it("fails with invalid aggregate target") {
|
||||
var project = baseProject
|
||||
project.aggregateTargets = [AggregateTarget(
|
||||
name: "target1",
|
||||
targets: ["invalidDependency"],
|
||||
settings: invalidSettings,
|
||||
configFiles: ["invalidConfig": "invalidConfigFile"],
|
||||
buildScripts: [BuildScript(script: .path("invalidPrebuildScript"), name: "buildScript1")],
|
||||
scheme: TargetScheme(testTargets: ["invalidTarget"])
|
||||
)]
|
||||
|
||||
try expectValidationError(project, .invalidTargetDependency(target: "target1", dependency: "invalidDependency"))
|
||||
try expectValidationError(project, .invalidTargetConfigFile(target: "target1", configFile: "invalidConfigFile", config: "invalidConfig"))
|
||||
try expectValidationError(project, .invalidTargetSchemeTest(target: "target1", testTarget: "invalidTarget"))
|
||||
try expectValidationError(project, .invalidBuildSettingConfig("invalidConfig"))
|
||||
try expectValidationError(project, .invalidSettingsGroup("invalidSettingGroup"))
|
||||
try expectValidationError(project, .invalidBuildScriptPath(target: "target1", name: "buildScript1", path: "invalidPrebuildScript"))
|
||||
|
||||
try expectValidationError(project, .missingConfigForTargetScheme(target: "target1", configType: .debug))
|
||||
try expectValidationError(project, .missingConfigForTargetScheme(target: "target1", configType: .release))
|
||||
|
||||
project.aggregateTargets[0].scheme?.configVariants = ["invalidVariant"]
|
||||
try expectValidationError(project, .invalidTargetSchemeConfigVariant(target: "target1", configVariant: "invalidVariant", configType: .debug))
|
||||
}
|
||||
|
||||
$0.it("fails with invalid scheme") {
|
||||
var project = baseProject
|
||||
project.schemes = [Scheme(
|
||||
|
||||
@@ -206,6 +206,18 @@ class SpecLoadingTests: XCTestCase {
|
||||
try expect(target.sources) == ["templateSource", "targetSource"] // merges array in order
|
||||
}
|
||||
|
||||
$0.it("parses aggregate targets") {
|
||||
let dictionary: [String: Any] = [
|
||||
"targets": ["target_1", "target_2"],
|
||||
"settings": ["SETTING": "VALUE"],
|
||||
"configFiles": ["debug": "file.xcconfig"],
|
||||
]
|
||||
|
||||
let project = try getProjectSpec(["aggregateTargets": ["AggregateTarget": dictionary]])
|
||||
let expectedTarget = AggregateTarget(name: "AggregateTarget", targets: ["target_1", "target_2"], settings: ["SETTING": "VALUE"], configFiles: ["debug": "file.xcconfig"])
|
||||
try expect(project.aggregateTargets) == [expectedTarget]
|
||||
}
|
||||
|
||||
$0.it("parses target schemes") {
|
||||
var targetDictionary = validTarget
|
||||
targetDictionary["scheme"] = [
|
||||
|
||||
Reference in New Issue
Block a user