mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2024-09-11 12:56:03 +03:00
wrap long lines
This commit is contained in:
parent
e75b1c1e89
commit
75e0644b99
4
Makefile
4
Makefile
@ -25,8 +25,8 @@ uninstall:
|
||||
rm -rf $(SHARE_PATH)
|
||||
|
||||
format_code:
|
||||
swiftformat Tests --stripunusedargs closure-only --header strip
|
||||
swiftformat Sources --stripunusedargs closure-only --header strip
|
||||
swiftformat Tests --wraparguments beforefirst --stripunusedargs closure-only --header strip
|
||||
swiftformat Sources --wraparguments beforefirst --stripunusedargs closure-only --header strip
|
||||
|
||||
update_brew:
|
||||
sed -i '' 's|\(url ".*/archive/\)\(.*\)\(.tar\)|\1$(VERSION)\3|' Formula/xcodegen.rb
|
||||
|
@ -23,7 +23,14 @@ public struct BuildScript: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public init(script: ScriptType, name: String? = nil, inputFiles: [String] = [], outputFiles: [String] = [], shell: String? = nil, runOnlyWhenInstalling: Bool = false) {
|
||||
public init(
|
||||
script: ScriptType,
|
||||
name: String? = nil,
|
||||
inputFiles: [String] = [],
|
||||
outputFiles: [String] = [],
|
||||
shell: String? = nil,
|
||||
runOnlyWhenInstalling: Bool = false
|
||||
) {
|
||||
self.script = script
|
||||
self.name = name
|
||||
self.inputFiles = inputFiles
|
||||
|
@ -12,7 +12,13 @@ public struct Dependency: Equatable {
|
||||
public var link: Bool = true
|
||||
public var implicit: Bool = false
|
||||
|
||||
public init(type: DependencyType, reference: String, embed: Bool? = nil, link: Bool = true, implicit: Bool = false) {
|
||||
public init(
|
||||
type: DependencyType,
|
||||
reference: String,
|
||||
embed: Bool? = nil,
|
||||
link: Bool = true,
|
||||
implicit: Bool = false
|
||||
) {
|
||||
self.type = type
|
||||
self.reference = reference
|
||||
self.embed = embed
|
||||
|
@ -9,7 +9,12 @@ public struct DeploymentTarget: Equatable {
|
||||
public var watchOS: Version?
|
||||
public var macOS: Version?
|
||||
|
||||
public init(iOS: Version? = nil, tvOS: Version? = nil, watchOS: Version? = nil, macOS: Version? = nil) {
|
||||
public init(
|
||||
iOS: Version? = nil,
|
||||
tvOS: Version? = nil,
|
||||
watchOS: Version? = nil,
|
||||
macOS: Version? = nil
|
||||
) {
|
||||
self.iOS = iOS
|
||||
self.tvOS = tvOS
|
||||
self.watchOS = watchOS
|
||||
|
@ -52,7 +52,18 @@ public struct ProjectSpec {
|
||||
}
|
||||
}
|
||||
|
||||
public init(carthageBuildPath: String? = nil, createIntermediateGroups: Bool = false, bundleIdPrefix: String? = nil, settingPresets: SettingPresets = .all, developmentLanguage: String? = nil, indentWidth: Int? = nil, tabWidth: Int? = nil, usesTabs: Bool? = nil, xcodeVersion: String? = nil, deploymentTarget: DeploymentTarget = .init()) {
|
||||
public init(
|
||||
carthageBuildPath: String? = nil,
|
||||
createIntermediateGroups: Bool = false,
|
||||
bundleIdPrefix: String? = nil,
|
||||
settingPresets: SettingPresets = .all,
|
||||
developmentLanguage: String? = nil,
|
||||
indentWidth: Int? = nil,
|
||||
tabWidth: Int? = nil,
|
||||
usesTabs: Bool? = nil,
|
||||
xcodeVersion: String? = nil,
|
||||
deploymentTarget: DeploymentTarget = .init()
|
||||
) {
|
||||
self.carthageBuildPath = carthageBuildPath
|
||||
self.createIntermediateGroups = createIntermediateGroups
|
||||
self.bundleIdPrefix = bundleIdPrefix
|
||||
@ -79,7 +90,19 @@ public struct ProjectSpec {
|
||||
}
|
||||
}
|
||||
|
||||
public init(basePath: Path, name: String, configs: [Config] = Config.defaultConfigs, targets: [Target] = [], settings: Settings = .empty, settingGroups: [String: Settings] = [:], schemes: [Scheme] = [], options: Options = Options(), fileGroups: [String] = [], configFiles: [String: String] = [:], attributes: [String: Any] = [:]) {
|
||||
public init(
|
||||
basePath: Path,
|
||||
name: String,
|
||||
configs: [Config] = Config.defaultConfigs,
|
||||
targets: [Target] = [],
|
||||
settings: Settings = .empty,
|
||||
settingGroups: [String: Settings] = [:],
|
||||
schemes: [Scheme] = [],
|
||||
options: Options = Options(),
|
||||
fileGroups: [String] = [],
|
||||
configFiles: [String: String] = [:],
|
||||
attributes: [String: Any] = [:]
|
||||
) {
|
||||
self.basePath = basePath
|
||||
self.name = name
|
||||
self.targets = targets
|
||||
@ -112,7 +135,10 @@ extension ProjectSpec: CustomDebugStringConvertible {
|
||||
}
|
||||
|
||||
if !settingGroups.isEmpty {
|
||||
string += "\nSetting Groups:\n\(indent)" + settingGroups.keys.sorted().map { "⚙️ \($0)" }.joined(separator: "\n\(indent)")
|
||||
string += "\nSetting Groups:\n\(indent)" + settingGroups.keys
|
||||
.sorted()
|
||||
.map { "⚙️ \($0)" }
|
||||
.joined(separator: "\n\(indent)")
|
||||
}
|
||||
|
||||
if !targets.isEmpty {
|
||||
@ -146,9 +172,11 @@ extension ProjectSpec {
|
||||
let jsonDictionary = try ProjectSpec.filterJSON(jsonDictionary: jsonDictionary)
|
||||
name = try jsonDictionary.json(atKeyPath: "name")
|
||||
settings = jsonDictionary.json(atKeyPath: "settings") ?? .empty
|
||||
settingGroups = jsonDictionary.json(atKeyPath: "settingGroups") ?? jsonDictionary.json(atKeyPath: "settingPresets") ?? [:]
|
||||
settingGroups = jsonDictionary.json(atKeyPath: "settingGroups")
|
||||
?? jsonDictionary.json(atKeyPath: "settingPresets") ?? [:]
|
||||
let configs: [String: String] = jsonDictionary.json(atKeyPath: "configs") ?? [:]
|
||||
self.configs = configs.isEmpty ? Config.defaultConfigs : configs.map { Config(name: $0, type: ConfigType(rawValue: $1)) }.sorted { $0.name < $1.name }
|
||||
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 }
|
||||
schemes = try jsonDictionary.json(atKeyPath: "schemes")
|
||||
fileGroups = jsonDictionary.json(atKeyPath: "fileGroups") ?? []
|
||||
|
@ -14,7 +14,15 @@ public struct Scheme: Equatable {
|
||||
public var test: Test?
|
||||
public var profile: Profile?
|
||||
|
||||
public init(name: String, build: Build, run: Run? = nil, test: Test? = nil, profile: Profile? = nil, analyze: Analyze? = nil, archive: Archive? = nil) {
|
||||
public init(
|
||||
name: String,
|
||||
build: Build,
|
||||
run: Run? = nil,
|
||||
test: Test? = nil,
|
||||
profile: Profile? = nil,
|
||||
analyze: Analyze? = nil,
|
||||
archive: Archive? = nil
|
||||
) {
|
||||
self.name = name
|
||||
self.build = build
|
||||
self.run = run
|
||||
@ -55,7 +63,12 @@ public struct Scheme: Equatable {
|
||||
public var commandLineArguments: [String: Bool]
|
||||
public var targets: [String]
|
||||
|
||||
public init(config: String, gatherCoverageData: Bool = false, commandLineArguments: [String: Bool] = [:], targets: [String] = []) {
|
||||
public init(
|
||||
config: String,
|
||||
gatherCoverageData: Bool = false,
|
||||
commandLineArguments: [String: Bool] = [:],
|
||||
targets: [String] = []
|
||||
) {
|
||||
self.config = config
|
||||
self.gatherCoverageData = gatherCoverageData
|
||||
self.commandLineArguments = commandLineArguments
|
||||
|
@ -9,11 +9,16 @@ public enum SpecParsingError: Error, CustomStringConvertible {
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case let .unknownTargetType(type): return "Unknown Target type: \(type)"
|
||||
case let .unknownTargetPlatform(platform): return "Unknown Target platform: \(platform)"
|
||||
case let .invalidDependency(dependency): return "Unknown Target dependency: \(dependency)"
|
||||
case let .unknownSourceBuildPhase(buildPhase): return "Unknown Source Build Phase: \(buildPhase)"
|
||||
case let .invalidVersion(version): return "Invalid version: \(version)"
|
||||
case let .unknownTargetType(type):
|
||||
return "Unknown Target type: \(type)"
|
||||
case let .unknownTargetPlatform(platform):
|
||||
return "Unknown Target platform: \(platform)"
|
||||
case let .invalidDependency(dependency):
|
||||
return "Unknown Target dependency: \(dependency)"
|
||||
case let .unknownSourceBuildPhase(buildPhase):
|
||||
return "Unknown Source Build Phase: \(buildPhase)"
|
||||
case let .invalidVersion(version):
|
||||
return "Invalid version: \(version)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,10 +72,18 @@ extension ProjectSpec {
|
||||
|
||||
for configVariant in scheme.configVariants {
|
||||
if !configs.contains(where: { $0.name.contains(configVariant) && $0.type == .debug }) {
|
||||
errors.append(.invalidTargetSchemeConfigVariant(target: target.name, configVariant: configVariant, configType: .debug))
|
||||
errors.append(.invalidTargetSchemeConfigVariant(
|
||||
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))
|
||||
errors.append(.invalidTargetSchemeConfigVariant(
|
||||
target: target.name,
|
||||
configVariant: configVariant,
|
||||
configType: .release
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,20 +22,34 @@ public struct SpecValidationError: Error, CustomStringConvertible {
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case let .invalidTargetDependency(target, dependency): return "Target \(target.quoted) has invalid dependency: \(dependency.quoted)"
|
||||
case let .invalidTargetConfigFile(target, configFile, config): return "Target \(target.quoted) has invalid config file \(configFile.quoted) for config \(config.quoted)"
|
||||
case let .invalidTargetSource(target, source): return "Target \(target.quoted) has a missing source directory \(source.quoted)"
|
||||
case let .invalidTargetSchemeConfigVariant(target, configVariant, configType): return "Target \(target.quoted) has an invalid scheme config variant which requires a config that has a \(configType.rawValue.quoted) type and contains the name \(configVariant.quoted)"
|
||||
case let .invalidTargetSchemeTest(target, test): return "Target \(target.quoted) scheme has invalid test \(test.quoted)"
|
||||
case let .invalidConfigFile(configFile, config): return "Invalid config file \(configFile.quoted) for config \(config.quoted)"
|
||||
case let .invalidSchemeTarget(scheme, target): return "Scheme \(scheme.quoted) has invalid build target \(target.quoted)"
|
||||
case let .invalidSchemeConfig(scheme, config): return "Scheme \(scheme.quoted) has invalid build configuration \(config.quoted)"
|
||||
case let .invalidBuildSettingConfig(config): return "Build setting has invalid build configuration \(config.quoted)"
|
||||
case let .invalidSettingsGroup(group): return "Invalid settings group \(group.quoted)"
|
||||
case let .invalidBuildScriptPath(target, name, path): return "Target \(target.quoted) has a script \(name != nil ? "\(name!.quoted) which has a " : "")path that doesn't exist \(path.quoted)"
|
||||
case let .invalidFileGroup(group): return "Invalid file group \(group.quoted)"
|
||||
case let .invalidConfigFileConfig(config): return "Config file has invalid config \(config.quoted)"
|
||||
case let .missingConfigTypeForGeneratedTargetScheme(target, configType): return "Target \(target.quoted) is missing a config of type \(configType.rawValue) to generate its scheme"
|
||||
case let .invalidTargetDependency(target, dependency):
|
||||
return "Target \(target.quoted) has invalid dependency: \(dependency.quoted)"
|
||||
case let .invalidTargetConfigFile(target, configFile, config):
|
||||
return "Target \(target.quoted) has invalid config file \(configFile.quoted) for config \(config.quoted)"
|
||||
case let .invalidTargetSource(target, source):
|
||||
return "Target \(target.quoted) has a missing source directory \(source.quoted)"
|
||||
case let .invalidTargetSchemeConfigVariant(target, configVariant, configType):
|
||||
return "Target \(target.quoted) has an invalid scheme config variant which requires a config that has a \(configType.rawValue.quoted) type and contains the name \(configVariant.quoted)"
|
||||
case let .invalidTargetSchemeTest(target, test):
|
||||
return "Target \(target.quoted) scheme has invalid test \(test.quoted)"
|
||||
case let .invalidConfigFile(configFile, config):
|
||||
return "Invalid config file \(configFile.quoted) for config \(config.quoted)"
|
||||
case let .invalidSchemeTarget(scheme, target):
|
||||
return "Scheme \(scheme.quoted) has invalid build target \(target.quoted)"
|
||||
case let .invalidSchemeConfig(scheme, config):
|
||||
return "Scheme \(scheme.quoted) has invalid build configuration \(config.quoted)"
|
||||
case let .invalidBuildSettingConfig(config):
|
||||
return "Build setting has invalid build configuration \(config.quoted)"
|
||||
case let .invalidSettingsGroup(group):
|
||||
return "Invalid settings group \(group.quoted)"
|
||||
case let .invalidBuildScriptPath(target, name, path):
|
||||
return "Target \(target.quoted) has a script \(name != nil ? "\(name!.quoted) which has a " : "")path that doesn't exist \(path.quoted)"
|
||||
case let .invalidFileGroup(group):
|
||||
return "Invalid file group \(group.quoted)"
|
||||
case let .invalidConfigFileConfig(config):
|
||||
return "Config file has invalid config \(config.quoted)"
|
||||
case let .missingConfigTypeForGeneratedTargetScheme(target, configType):
|
||||
return "Target \(target.quoted) is missing a config of type \(configType.rawValue) to generate its scheme"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,20 @@ public struct Target {
|
||||
return name
|
||||
}
|
||||
|
||||
public init(name: String, type: PBXProductType, platform: Platform, deploymentTarget: Version? = nil, settings: Settings = .empty, configFiles: [String: String] = [:], sources: [TargetSource] = [], dependencies: [Dependency] = [], prebuildScripts: [BuildScript] = [], postbuildScripts: [BuildScript] = [], scheme: TargetScheme? = nil, legacy: LegacyTarget? = nil) {
|
||||
public init(
|
||||
name: String,
|
||||
type: PBXProductType,
|
||||
platform: Platform,
|
||||
deploymentTarget: Version? = nil,
|
||||
settings: Settings = .empty,
|
||||
configFiles: [String: String] = [:],
|
||||
sources: [TargetSource] = [],
|
||||
dependencies: [Dependency] = [],
|
||||
prebuildScripts: [BuildScript] = [],
|
||||
postbuildScripts: [BuildScript] = [],
|
||||
scheme: TargetScheme? = nil,
|
||||
legacy: LegacyTarget? = nil
|
||||
) {
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.platform = platform
|
||||
@ -158,7 +171,12 @@ public struct TargetScheme {
|
||||
public var gatherCoverageData: Bool
|
||||
public var commandLineArguments: [String: Bool]
|
||||
|
||||
public init(testTargets: [String] = [], configVariants: [String] = [], gatherCoverageData: Bool = false, commandLineArguments: [String: Bool] = [:]) {
|
||||
public init(
|
||||
testTargets: [String] = [],
|
||||
configVariants: [String] = [],
|
||||
gatherCoverageData: Bool = false,
|
||||
commandLineArguments: [String: Bool] = [:]
|
||||
) {
|
||||
self.testTargets = testTargets
|
||||
self.configVariants = configVariants
|
||||
self.gatherCoverageData = gatherCoverageData
|
||||
|
@ -35,7 +35,15 @@ public struct TargetSource {
|
||||
case folder
|
||||
}
|
||||
|
||||
public init(path: String, name: String? = nil, compilerFlags: [String] = [], excludes: [String] = [], type: SourceType? = nil, optional: Bool = false, buildPhase: BuildPhase? = nil) {
|
||||
public init(
|
||||
path: String,
|
||||
name: String? = nil,
|
||||
compilerFlags: [String] = [],
|
||||
excludes: [String] = [],
|
||||
type: SourceType? = nil,
|
||||
optional: Bool = false,
|
||||
buildPhase: BuildPhase? = nil
|
||||
) {
|
||||
self.path = path
|
||||
self.name = name
|
||||
self.compilerFlags = compilerFlags
|
||||
|
@ -55,9 +55,29 @@ func generate(spec: String, project: String, isQuiet: Bool, justVersion: Bool) {
|
||||
}
|
||||
|
||||
command(
|
||||
Option<String>("spec", default: "project.yml", flag: "s", description: "The path to the spec file"),
|
||||
Option<String>("project", default: "", flag: "p", description: "The path to the folder where the project should be generated"),
|
||||
Flag("quiet", default: false, flag: "q", description: "Suppress printing of informational and success messages"),
|
||||
Flag("version", default: false, flag: "v", description: "Show XcodeGen version"),
|
||||
Option<String>(
|
||||
"spec",
|
||||
default: "project.yml",
|
||||
flag: "s",
|
||||
description: "The path to the spec file"
|
||||
),
|
||||
Option<String>(
|
||||
"project",
|
||||
default: "",
|
||||
flag: "p",
|
||||
description: "The path to the folder where the project should be generated"
|
||||
),
|
||||
Flag(
|
||||
"quiet",
|
||||
default: false,
|
||||
flag: "q",
|
||||
description: "Suppress printing of informational and success messages"
|
||||
),
|
||||
Flag(
|
||||
"version",
|
||||
default: false,
|
||||
flag: "v",
|
||||
description: "Show XcodeGen version"
|
||||
),
|
||||
generate
|
||||
).run(version)
|
||||
|
@ -54,10 +54,20 @@ public class PBXProjGenerator {
|
||||
if let configPath = spec.configFiles[config.name] {
|
||||
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: spec.basePath + configPath)
|
||||
}
|
||||
return XCBuildConfiguration(reference: referenceGenerator.generate(XCBuildConfiguration.self, config.name), name: config.name, baseConfigurationReference: baseConfigurationReference, buildSettings: buildSettings)
|
||||
return XCBuildConfiguration(
|
||||
reference: referenceGenerator.generate(XCBuildConfiguration.self, config.name),
|
||||
name: config.name,
|
||||
baseConfigurationReference: baseConfigurationReference,
|
||||
buildSettings: buildSettings
|
||||
)
|
||||
}
|
||||
|
||||
let buildConfigList = XCConfigurationList(reference: referenceGenerator.generate(XCConfigurationList.self, spec.name), buildConfigurations: buildConfigs.references, defaultConfigurationName: buildConfigs.first?.name ?? "", defaultConfigurationIsVisible: 0)
|
||||
let buildConfigList = XCConfigurationList(
|
||||
reference: referenceGenerator.generate(XCConfigurationList.self, spec.name),
|
||||
buildConfigurations: buildConfigs.references,
|
||||
defaultConfigurationName: buildConfigs.first?.name ?? "",
|
||||
defaultConfigurationIsVisible: 0
|
||||
)
|
||||
|
||||
buildConfigs.forEach(addObject)
|
||||
addObject(buildConfigList)
|
||||
@ -65,37 +75,70 @@ public class PBXProjGenerator {
|
||||
for target in spec.targets {
|
||||
targetNativeReferences[target.name] =
|
||||
referenceGenerator.generate(
|
||||
target.isLegacy ? PBXLegacyTarget.self : PBXNativeTarget.self, target.name)
|
||||
target.isLegacy ? PBXLegacyTarget.self : PBXNativeTarget.self,
|
||||
target.name
|
||||
)
|
||||
|
||||
let fileReference = PBXFileReference(reference: referenceGenerator.generate(PBXFileReference.self, target.name), sourceTree: .buildProductsDir, explicitFileType: target.type.fileExtension, path: target.filename, includeInIndex: 0)
|
||||
let fileReference = PBXFileReference(
|
||||
reference: referenceGenerator.generate(PBXFileReference.self, target.name),
|
||||
sourceTree: .buildProductsDir,
|
||||
explicitFileType: target.type.fileExtension,
|
||||
path: target.filename,
|
||||
includeInIndex: 0
|
||||
)
|
||||
addObject(fileReference)
|
||||
targetFileReferences[target.name] = fileReference.reference
|
||||
|
||||
let buildFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, fileReference.reference), fileRef: fileReference.reference)
|
||||
let buildFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, fileReference.reference),
|
||||
fileRef: fileReference.reference
|
||||
)
|
||||
addObject(buildFile)
|
||||
targetBuildFiles[target.name] = buildFile
|
||||
}
|
||||
|
||||
let targets = try spec.targets.map(generateTarget)
|
||||
|
||||
let productGroup = PBXGroup(reference: referenceGenerator.generate(PBXGroup.self, "Products"), children: Array(targetFileReferences.values), sourceTree: .group, name: "Products")
|
||||
let productGroup = PBXGroup(
|
||||
reference: referenceGenerator.generate(PBXGroup.self, "Products"),
|
||||
children: Array(targetFileReferences.values),
|
||||
sourceTree: .group,
|
||||
name: "Products"
|
||||
)
|
||||
addObject(productGroup)
|
||||
topLevelGroups.insert(productGroup.reference)
|
||||
|
||||
if !carthageFrameworksByPlatform.isEmpty {
|
||||
var platforms: [PBXGroup] = []
|
||||
for (platform, fileReferences) in carthageFrameworksByPlatform {
|
||||
let platformGroup = PBXGroup(reference: referenceGenerator.generate(PBXGroup.self, "Carthage" + platform), children: fileReferences.sorted(), sourceTree: .group, name: platform, path: platform)
|
||||
let platformGroup = PBXGroup(
|
||||
reference: referenceGenerator.generate(PBXGroup.self, "Carthage" + platform),
|
||||
children: fileReferences.sorted(),
|
||||
sourceTree: .group,
|
||||
name: platform,
|
||||
path: platform
|
||||
)
|
||||
addObject(platformGroup)
|
||||
platforms.append(platformGroup)
|
||||
}
|
||||
let carthageGroup = PBXGroup(reference: referenceGenerator.generate(PBXGroup.self, "Carthage"), children: platforms.references.sorted(), sourceTree: .group, name: "Carthage", path: carthageBuildPath)
|
||||
let carthageGroup = PBXGroup(
|
||||
reference: referenceGenerator.generate(PBXGroup.self, "Carthage"),
|
||||
children: platforms.references.sorted(),
|
||||
sourceTree: .group,
|
||||
name: "Carthage",
|
||||
path: carthageBuildPath
|
||||
)
|
||||
addObject(carthageGroup)
|
||||
frameworkFiles.append(carthageGroup.reference)
|
||||
}
|
||||
|
||||
if !frameworkFiles.isEmpty {
|
||||
let group = PBXGroup(reference: referenceGenerator.generate(PBXGroup.self, "Frameworks"), children: frameworkFiles, sourceTree: .group, name: "Frameworks")
|
||||
let group = PBXGroup(
|
||||
reference: referenceGenerator.generate(PBXGroup.self, "Frameworks"),
|
||||
children: frameworkFiles,
|
||||
sourceTree: .group,
|
||||
name: "Frameworks"
|
||||
)
|
||||
addObject(group)
|
||||
topLevelGroups.insert(group.reference)
|
||||
}
|
||||
@ -104,21 +147,30 @@ public class PBXProjGenerator {
|
||||
topLevelGroups.insert(rootGroup)
|
||||
}
|
||||
|
||||
let mainGroup = PBXGroup(reference: referenceGenerator.generate(PBXGroup.self, "Project"), children: Array(topLevelGroups), sourceTree: .group, usesTabs: spec.options.usesTabs.map { $0 ? 1 : 0 }, indentWidth: spec.options.indentWidth, tabWidth: spec.options.tabWidth)
|
||||
let mainGroup = PBXGroup(
|
||||
reference: referenceGenerator.generate(PBXGroup.self, "Project"),
|
||||
children: Array(topLevelGroups),
|
||||
sourceTree: .group,
|
||||
usesTabs: spec.options.usesTabs.map { $0 ? 1 : 0 },
|
||||
indentWidth: spec.options.indentWidth,
|
||||
tabWidth: spec.options.tabWidth
|
||||
)
|
||||
addObject(mainGroup)
|
||||
|
||||
sortGroups(group: mainGroup)
|
||||
|
||||
let projectAttributes: [String: Any] = ["LastUpgradeCheck": spec.xcodeVersion].merged(spec.attributes)
|
||||
let root = PBXProject(name: spec.name,
|
||||
reference: proj.rootObject,
|
||||
buildConfigurationList: buildConfigList.reference,
|
||||
compatibilityVersion: "Xcode 3.2",
|
||||
mainGroup: mainGroup.reference,
|
||||
developmentRegion: spec.options.developmentLanguage ?? "en",
|
||||
knownRegions: sourceGenerator.knownRegions.sorted(),
|
||||
targets: targets.references,
|
||||
attributes: projectAttributes)
|
||||
let root = PBXProject(
|
||||
name: spec.name,
|
||||
reference: proj.rootObject,
|
||||
buildConfigurationList: buildConfigList.reference,
|
||||
compatibilityVersion: "Xcode 3.2",
|
||||
mainGroup: mainGroup.reference,
|
||||
developmentRegion: spec.options.developmentLanguage ?? "en",
|
||||
knownRegions: sourceGenerator.knownRegions.sorted(),
|
||||
targets: targets.references,
|
||||
attributes: projectAttributes
|
||||
)
|
||||
proj.objects.projects.append(root)
|
||||
|
||||
return proj
|
||||
@ -170,7 +222,10 @@ public class PBXProjGenerator {
|
||||
if let bundleIdPrefix = spec.options.bundleIdPrefix,
|
||||
!spec.targetHasBuildSetting("PRODUCT_BUNDLE_IDENTIFIER", basePath: spec.basePath, target: target, config: config) {
|
||||
let characterSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-.")).inverted
|
||||
let escapedTargetName = target.name.replacingOccurrences(of: "_", with: "-").components(separatedBy: characterSet).joined(separator: "")
|
||||
let escapedTargetName = target.name
|
||||
.replacingOccurrences(of: "_", with: "-")
|
||||
.components(separatedBy: characterSet)
|
||||
.joined(separator: "")
|
||||
buildSettings["PRODUCT_BUNDLE_IDENTIFIER"] = bundleIdPrefix + "." + escapedTargetName
|
||||
}
|
||||
|
||||
@ -206,10 +261,19 @@ public class PBXProjGenerator {
|
||||
if let configPath = target.configFiles[config.name] {
|
||||
baseConfigurationReference = sourceGenerator.getContainedFileReference(path: spec.basePath + configPath)
|
||||
}
|
||||
return XCBuildConfiguration(reference: referenceGenerator.generate(XCBuildConfiguration.self, config.name + target.name), name: config.name, baseConfigurationReference: baseConfigurationReference, buildSettings: buildSettings)
|
||||
return XCBuildConfiguration(
|
||||
reference: referenceGenerator.generate(XCBuildConfiguration.self, config.name + target.name),
|
||||
name: config.name,
|
||||
baseConfigurationReference: baseConfigurationReference,
|
||||
buildSettings: buildSettings
|
||||
)
|
||||
}
|
||||
configs.forEach(addObject)
|
||||
let buildConfigList = XCConfigurationList(reference: referenceGenerator.generate(XCConfigurationList.self, target.name), buildConfigurations: configs.references, defaultConfigurationName: "")
|
||||
let buildConfigList = XCConfigurationList(
|
||||
reference: referenceGenerator.generate(XCConfigurationList.self, target.name),
|
||||
buildConfigurations: configs.references,
|
||||
defaultConfigurationName: ""
|
||||
)
|
||||
addObject(buildConfigList)
|
||||
|
||||
var dependencies: [String] = []
|
||||
@ -228,8 +292,18 @@ public class PBXProjGenerator {
|
||||
guard let dependencyTarget = spec.getTarget(dependencyTargetName) else { continue }
|
||||
let dependencyFileReference = targetFileReferences[dependencyTargetName]!
|
||||
|
||||
let targetProxy = PBXContainerItemProxy(reference: referenceGenerator.generate(PBXContainerItemProxy.self, target.name), containerPortal: proj.rootObject, remoteGlobalIDString: targetNativeReferences[dependencyTargetName]!, proxyType: .nativeTarget, remoteInfo: dependencyTargetName)
|
||||
let targetDependency = PBXTargetDependency(reference: referenceGenerator.generate(PBXTargetDependency.self, dependencyTargetName + target.name), target: targetNativeReferences[dependencyTargetName]!, targetProxy: targetProxy.reference)
|
||||
let targetProxy = PBXContainerItemProxy(
|
||||
reference: referenceGenerator.generate(PBXContainerItemProxy.self, target.name),
|
||||
containerPortal: proj.rootObject,
|
||||
remoteGlobalIDString: targetNativeReferences[dependencyTargetName]!,
|
||||
proxyType: .nativeTarget,
|
||||
remoteInfo: dependencyTargetName
|
||||
)
|
||||
let targetDependency = PBXTargetDependency(
|
||||
reference: referenceGenerator.generate(PBXTargetDependency.self, dependencyTargetName + target.name),
|
||||
target: targetNativeReferences[dependencyTargetName]!,
|
||||
targetProxy: targetProxy.reference
|
||||
)
|
||||
|
||||
addObject(targetProxy)
|
||||
addObject(targetDependency)
|
||||
@ -237,7 +311,10 @@ public class PBXProjGenerator {
|
||||
|
||||
if (dependencyTarget.type.isLibrary || dependencyTarget.type.isFramework) && dependency.link {
|
||||
let dependencyBuildFile = targetBuildFiles[dependencyTargetName]!
|
||||
let buildFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, dependencyBuildFile.reference + target.name), fileRef: dependencyBuildFile.fileRef!)
|
||||
let buildFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, dependencyBuildFile.reference + target.name),
|
||||
fileRef: dependencyBuildFile.fileRef!
|
||||
)
|
||||
addObject(buildFile)
|
||||
targetFrameworkBuildFiles.append(buildFile.reference)
|
||||
}
|
||||
@ -245,7 +322,11 @@ public class PBXProjGenerator {
|
||||
if embed && !dependencyTarget.type.isLibrary {
|
||||
|
||||
let embedSettings = dependency.buildSettings
|
||||
let embedFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, dependencyFileReference + target.name), fileRef: dependencyFileReference, settings: embedSettings)
|
||||
let embedFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, dependencyFileReference + target.name),
|
||||
fileRef: dependencyFileReference,
|
||||
settings: embedSettings
|
||||
)
|
||||
addObject(embedFile)
|
||||
|
||||
if dependencyTarget.type.isExtension {
|
||||
@ -263,12 +344,22 @@ public class PBXProjGenerator {
|
||||
case .framework:
|
||||
let fileReference: String
|
||||
if dependency.implicit {
|
||||
fileReference = sourceGenerator.getFileReference(path: Path(dependency.reference), inPath: spec.basePath, sourceTree: .buildProductsDir)
|
||||
fileReference = sourceGenerator.getFileReference(
|
||||
path: Path(dependency.reference),
|
||||
inPath: spec.basePath,
|
||||
sourceTree: .buildProductsDir
|
||||
)
|
||||
} else {
|
||||
fileReference = sourceGenerator.getFileReference(path: Path(dependency.reference), inPath: spec.basePath)
|
||||
fileReference = sourceGenerator.getFileReference(
|
||||
path: Path(dependency.reference),
|
||||
inPath: spec.basePath
|
||||
)
|
||||
}
|
||||
|
||||
let buildFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name), fileRef: fileReference)
|
||||
let buildFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name),
|
||||
fileRef: fileReference
|
||||
)
|
||||
addObject(buildFile)
|
||||
|
||||
targetFrameworkBuildFiles.append(buildFile.reference)
|
||||
@ -277,7 +368,11 @@ public class PBXProjGenerator {
|
||||
}
|
||||
|
||||
if embed {
|
||||
let embedFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name), fileRef: fileReference, settings: dependency.buildSettings)
|
||||
let embedFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name),
|
||||
fileRef: fileReference,
|
||||
settings: dependency.buildSettings
|
||||
)
|
||||
addObject(embedFile)
|
||||
copyFrameworksReferences.append(embedFile.reference)
|
||||
}
|
||||
@ -289,13 +384,20 @@ public class PBXProjGenerator {
|
||||
}
|
||||
let fileReference = sourceGenerator.getFileReference(path: frameworkPath, inPath: platformPath)
|
||||
|
||||
let buildFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name), fileRef: fileReference)
|
||||
let buildFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name),
|
||||
fileRef: fileReference
|
||||
)
|
||||
addObject(buildFile)
|
||||
carthageFrameworksByPlatform[target.platform.carthageDirectoryName, default: []].insert(fileReference)
|
||||
|
||||
targetFrameworkBuildFiles.append(buildFile.reference)
|
||||
if target.platform == .macOS && target.type.isApp {
|
||||
let embedFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name), fileRef: fileReference, settings: dependency.buildSettings)
|
||||
let embedFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + target.name),
|
||||
fileRef: fileReference,
|
||||
settings: dependency.buildSettings
|
||||
)
|
||||
addObject(embedFile)
|
||||
copyFrameworksReferences.append(embedFile.reference)
|
||||
}
|
||||
@ -330,7 +432,8 @@ public class PBXProjGenerator {
|
||||
inputPaths: buildScript.inputFiles,
|
||||
outputPaths: buildScript.outputFiles,
|
||||
shellPath: buildScript.shell ?? "/bin/sh",
|
||||
shellScript: shellScript)
|
||||
shellScript: shellScript
|
||||
)
|
||||
shellScriptPhase.runOnlyForDeploymentPostprocessing = buildScript.runOnlyWhenInstalling ? 1 : 0
|
||||
addObject(shellScriptPhase)
|
||||
buildPhases.append(shellScriptPhase.reference)
|
||||
@ -365,7 +468,8 @@ public class PBXProjGenerator {
|
||||
let frameworkBuildPhase = PBXFrameworksBuildPhase(
|
||||
reference: referenceGenerator.generate(PBXFrameworksBuildPhase.self, target.name),
|
||||
files: targetFrameworkBuildFiles,
|
||||
runOnlyForDeploymentPostprocessing: 0)
|
||||
runOnlyForDeploymentPostprocessing: 0
|
||||
)
|
||||
|
||||
addObject(frameworkBuildPhase)
|
||||
buildPhases.append(frameworkBuildPhase.reference)
|
||||
@ -377,7 +481,8 @@ public class PBXProjGenerator {
|
||||
reference: referenceGenerator.generate(PBXCopyFilesBuildPhase.self, "embed app extensions" + target.name),
|
||||
dstPath: "",
|
||||
dstSubfolderSpec: .plugins,
|
||||
files: extensions)
|
||||
files: extensions
|
||||
)
|
||||
|
||||
addObject(copyFilesPhase)
|
||||
buildPhases.append(copyFilesPhase.reference)
|
||||
@ -389,7 +494,8 @@ public class PBXProjGenerator {
|
||||
reference: referenceGenerator.generate(PBXCopyFilesBuildPhase.self, "embed frameworks" + target.name),
|
||||
dstPath: "",
|
||||
dstSubfolderSpec: .frameworks,
|
||||
files: copyFrameworksReferences)
|
||||
files: copyFrameworksReferences
|
||||
)
|
||||
|
||||
addObject(copyFilesPhase)
|
||||
buildPhases.append(copyFilesPhase.reference)
|
||||
@ -401,23 +507,36 @@ public class PBXProjGenerator {
|
||||
reference: referenceGenerator.generate(PBXCopyFilesBuildPhase.self, "embed watch content" + target.name),
|
||||
dstPath: "$(CONTENTS_FOLDER_PATH)/Watch",
|
||||
dstSubfolderSpec: .productsDirectory,
|
||||
files: copyWatchReferences)
|
||||
files: copyWatchReferences
|
||||
)
|
||||
|
||||
addObject(copyFilesPhase)
|
||||
buildPhases.append(copyFilesPhase.reference)
|
||||
}
|
||||
|
||||
let carthageFrameworksToEmbed = Array(Set(carthageDependencies
|
||||
let carthageFrameworksToEmbed = Array(Set(
|
||||
carthageDependencies
|
||||
.filter { $0.embed ?? true }
|
||||
.map { $0.reference }))
|
||||
.map { $0.reference }
|
||||
))
|
||||
.sorted()
|
||||
|
||||
if !carthageFrameworksToEmbed.isEmpty {
|
||||
|
||||
if target.type.isApp && target.platform != .macOS {
|
||||
let inputPaths = carthageFrameworksToEmbed.map { "$(SRCROOT)/\(carthageBuildPath)/\(target.platform)/\($0)\($0.contains(".") ? "" : ".framework")" }
|
||||
let outputPaths = carthageFrameworksToEmbed.map { "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/\($0)\($0.contains(".") ? "" : ".framework")" }
|
||||
let carthageScript = PBXShellScriptBuildPhase(reference: referenceGenerator.generate(PBXShellScriptBuildPhase.self, "Carthage" + target.name), files: [], name: "Carthage", inputPaths: inputPaths, outputPaths: outputPaths, shellPath: "/bin/sh", shellScript: "/usr/local/bin/carthage copy-frameworks\n")
|
||||
let inputPaths = carthageFrameworksToEmbed
|
||||
.map { "$(SRCROOT)/\(carthageBuildPath)/\(target.platform)/\($0)\($0.contains(".") ? "" : ".framework")" }
|
||||
let outputPaths = carthageFrameworksToEmbed
|
||||
.map { "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/\($0)\($0.contains(".") ? "" : ".framework")" }
|
||||
let carthageScript = PBXShellScriptBuildPhase(
|
||||
reference: referenceGenerator.generate(PBXShellScriptBuildPhase.self, "Carthage" + target.name),
|
||||
files: [],
|
||||
name: "Carthage",
|
||||
inputPaths: inputPaths,
|
||||
outputPaths: outputPaths,
|
||||
shellPath: "/bin/sh",
|
||||
shellScript: "/usr/local/bin/carthage copy-frameworks\n"
|
||||
)
|
||||
addObject(carthageScript)
|
||||
buildPhases.append(carthageScript.reference)
|
||||
}
|
||||
@ -450,7 +569,8 @@ public class PBXProjGenerator {
|
||||
buildRules: [],
|
||||
dependencies: dependencies,
|
||||
productReference: fileReference,
|
||||
productType: target.type)
|
||||
productType: target.type
|
||||
)
|
||||
}
|
||||
addObject(pbxtarget)
|
||||
return pbxtarget
|
||||
|
@ -41,9 +41,16 @@ public class ProjectGenerator {
|
||||
func getBuildEntry(_ buildTarget: Scheme.BuildTarget) -> XCScheme.BuildAction.Entry {
|
||||
|
||||
let predicate: (PBXTarget) -> Bool = { $0.name == buildTarget.target }
|
||||
let targetReference = pbxProject.objects.nativeTargets.referenceValues.first { predicate($0 as PBXTarget) } ?? pbxProject.objects.legacyTargets.referenceValues.first { predicate($0 as PBXTarget) }!
|
||||
let targetReference =
|
||||
pbxProject.objects.nativeTargets.referenceValues.first { predicate($0 as PBXTarget) } ??
|
||||
pbxProject.objects.legacyTargets.referenceValues.first { predicate($0 as PBXTarget) }!
|
||||
|
||||
let buildableReference = XCScheme.BuildableReference(referencedContainer: "container:\(spec.name).xcodeproj", blueprintIdentifier: targetReference.reference, buildableName: buildTarget.target + (targetReference.productType?.fileExtension.map { ".\($0)" } ?? ""), blueprintName: scheme.name)
|
||||
let buildableReference = XCScheme.BuildableReference(
|
||||
referencedContainer: "container:\(spec.name).xcodeproj",
|
||||
blueprintIdentifier: targetReference.reference,
|
||||
buildableName: buildTarget.target + (targetReference.productType?.fileExtension.map { ".\($0)" } ?? ""),
|
||||
blueprintName: scheme.name
|
||||
)
|
||||
|
||||
return XCScheme.BuildAction.Entry(buildableReference: buildableReference, buildFor: buildTarget.buildTypes)
|
||||
}
|
||||
@ -60,43 +67,60 @@ public class ProjectGenerator {
|
||||
let buildableReference = buildActionEntries.first!.buildableReference
|
||||
let productRunable = XCScheme.BuildableProductRunnable(buildableReference: buildableReference)
|
||||
|
||||
let buildAction = XCScheme.BuildAction(buildActionEntries: buildActionEntries, parallelizeBuild: true, buildImplicitDependencies: true)
|
||||
let buildAction = XCScheme.BuildAction(
|
||||
buildActionEntries: buildActionEntries,
|
||||
parallelizeBuild: true,
|
||||
buildImplicitDependencies: true
|
||||
)
|
||||
|
||||
let testables = testBuildTargetEntries.map { XCScheme.TestableReference(skipped: false, buildableReference: $0.buildableReference) }
|
||||
let testables = testBuildTargetEntries.map {
|
||||
XCScheme.TestableReference(skipped: false, buildableReference: $0.buildableReference)
|
||||
}
|
||||
|
||||
let testCommandLineArgs = scheme.test.map { XCScheme.CommandLineArguments($0.commandLineArguments) }
|
||||
let launchCommandLineArgs = scheme.run.map { XCScheme.CommandLineArguments($0.commandLineArguments) }
|
||||
let profileCommandLineArgs = scheme.profile.map { XCScheme.CommandLineArguments($0.commandLineArguments) }
|
||||
|
||||
let testAction = XCScheme.TestAction(buildConfiguration: scheme.test?.config ?? defaultDebugConfig.name,
|
||||
macroExpansion: buildableReference,
|
||||
testables: testables,
|
||||
shouldUseLaunchSchemeArgsEnv: scheme.test?.commandLineArguments.isEmpty ?? true,
|
||||
codeCoverageEnabled: scheme.test?.gatherCoverageData ?? false,
|
||||
commandlineArguments: testCommandLineArgs)
|
||||
let testAction = XCScheme.TestAction(
|
||||
buildConfiguration: scheme.test?.config ?? defaultDebugConfig.name,
|
||||
macroExpansion: buildableReference,
|
||||
testables: testables,
|
||||
shouldUseLaunchSchemeArgsEnv: scheme.test?.commandLineArguments.isEmpty ?? true,
|
||||
codeCoverageEnabled: scheme.test?.gatherCoverageData ?? false,
|
||||
commandlineArguments: testCommandLineArgs
|
||||
)
|
||||
|
||||
let launchAction = XCScheme.LaunchAction(buildableProductRunnable: productRunable,
|
||||
buildConfiguration: scheme.run?.config ?? defaultDebugConfig.name,
|
||||
commandlineArguments: launchCommandLineArgs)
|
||||
let launchAction = XCScheme.LaunchAction(
|
||||
buildableProductRunnable: productRunable,
|
||||
buildConfiguration: scheme.run?.config ?? defaultDebugConfig.name,
|
||||
commandlineArguments: launchCommandLineArgs
|
||||
)
|
||||
|
||||
let profileAction = XCScheme.ProfileAction(buildableProductRunnable: productRunable,
|
||||
buildConfiguration: scheme.profile?.config ?? defaultReleaseConfig.name,
|
||||
shouldUseLaunchSchemeArgsEnv: scheme.profile?.commandLineArguments.isEmpty ?? true,
|
||||
commandlineArguments: profileCommandLineArgs)
|
||||
let profileAction = XCScheme.ProfileAction(
|
||||
buildableProductRunnable: productRunable,
|
||||
buildConfiguration: scheme.profile?.config ?? defaultReleaseConfig.name,
|
||||
shouldUseLaunchSchemeArgsEnv: scheme.profile?.commandLineArguments.isEmpty ?? true,
|
||||
commandlineArguments: profileCommandLineArgs
|
||||
)
|
||||
|
||||
let analyzeAction = XCScheme.AnalyzeAction(buildConfiguration: scheme.analyze?.config ?? defaultDebugConfig.name)
|
||||
|
||||
let archiveAction = XCScheme.ArchiveAction(buildConfiguration: scheme.archive?.config ?? defaultReleaseConfig.name, revealArchiveInOrganizer: true)
|
||||
let archiveAction = XCScheme.ArchiveAction(
|
||||
buildConfiguration: scheme.archive?.config ?? defaultReleaseConfig.name,
|
||||
revealArchiveInOrganizer: true
|
||||
)
|
||||
|
||||
return XCScheme(name: scheme.name,
|
||||
lastUpgradeVersion: spec.xcodeVersion,
|
||||
version: "1.3",
|
||||
buildAction: buildAction,
|
||||
testAction: testAction,
|
||||
launchAction: launchAction,
|
||||
profileAction: profileAction,
|
||||
analyzeAction: analyzeAction,
|
||||
archiveAction: archiveAction)
|
||||
return XCScheme(
|
||||
name: scheme.name,
|
||||
lastUpgradeVersion: spec.xcodeVersion,
|
||||
version: "1.3",
|
||||
buildAction: buildAction,
|
||||
testAction: testAction,
|
||||
launchAction: launchAction,
|
||||
profileAction: profileAction,
|
||||
analyzeAction: analyzeAction,
|
||||
archiveAction: archiveAction
|
||||
)
|
||||
}
|
||||
|
||||
func generateSharedData(pbxProject: PBXProj) throws -> XCSharedData {
|
||||
@ -116,7 +140,13 @@ public class ProjectGenerator {
|
||||
let debugConfig = spec.configs.first { $0.type == .debug }!
|
||||
let releaseConfig = spec.configs.first { $0.type == .release }!
|
||||
|
||||
let scheme = Scheme(name: schemeName, target: target, targetScheme: targetScheme, debugConfig: debugConfig.name, releaseConfig: releaseConfig.name)
|
||||
let scheme = Scheme(
|
||||
name: schemeName,
|
||||
target: target,
|
||||
targetScheme: targetScheme,
|
||||
debugConfig: debugConfig.name,
|
||||
releaseConfig: releaseConfig.name
|
||||
)
|
||||
let xcscheme = try generateScheme(scheme, pbxProject: pbxProject)
|
||||
xcschemes.append(xcscheme)
|
||||
} else {
|
||||
@ -124,10 +154,18 @@ public class ProjectGenerator {
|
||||
|
||||
let schemeName = "\(target.name) \(configVariant)"
|
||||
|
||||
let debugConfig = spec.configs.first { $0.type == .debug && $0.name.contains(configVariant) }!
|
||||
let releaseConfig = spec.configs.first { $0.type == .release && $0.name.contains(configVariant) }!
|
||||
let debugConfig = spec.configs
|
||||
.first { $0.type == .debug && $0.name.contains(configVariant) }!
|
||||
let releaseConfig = spec.configs
|
||||
.first { $0.type == .release && $0.name.contains(configVariant) }!
|
||||
|
||||
let scheme = Scheme(name: schemeName, target: target, targetScheme: targetScheme, debugConfig: debugConfig.name, releaseConfig: releaseConfig.name)
|
||||
let scheme = Scheme(
|
||||
name: schemeName,
|
||||
target: target,
|
||||
targetScheme: targetScheme,
|
||||
debugConfig: debugConfig.name,
|
||||
releaseConfig: releaseConfig.name
|
||||
)
|
||||
let xcscheme = try generateScheme(scheme, pbxProject: pbxProject)
|
||||
xcschemes.append(xcscheme)
|
||||
}
|
||||
@ -144,9 +182,20 @@ extension Scheme {
|
||||
self.init(
|
||||
name: name,
|
||||
build: .init(targets: [Scheme.BuildTarget(target: target.name)]),
|
||||
run: .init(config: debugConfig, commandLineArguments: targetScheme.commandLineArguments),
|
||||
test: .init(config: debugConfig, gatherCoverageData: targetScheme.gatherCoverageData, commandLineArguments: targetScheme.commandLineArguments, targets: targetScheme.testTargets),
|
||||
profile: .init(config: releaseConfig, commandLineArguments: targetScheme.commandLineArguments),
|
||||
run: .init(
|
||||
config: debugConfig,
|
||||
commandLineArguments: targetScheme.commandLineArguments
|
||||
),
|
||||
test: .init(
|
||||
config: debugConfig,
|
||||
gatherCoverageData: targetScheme.gatherCoverageData,
|
||||
commandLineArguments: targetScheme.commandLineArguments,
|
||||
targets: targetScheme.testTargets
|
||||
),
|
||||
profile: .init(
|
||||
config: releaseConfig,
|
||||
commandLineArguments: targetScheme.commandLineArguments
|
||||
),
|
||||
analyze: .init(config: debugConfig),
|
||||
archive: .init(config: releaseConfig)
|
||||
)
|
||||
|
@ -81,7 +81,12 @@ extension ProjectSpec {
|
||||
}
|
||||
|
||||
// combines all levels of a target's settings: target, target config, project, project config
|
||||
public func getCombinedBuildSettings(basePath: Path, target: Target, config: Config, includeProject: Bool = true) -> BuildSettings {
|
||||
public func getCombinedBuildSettings(
|
||||
basePath: Path,
|
||||
target: Target,
|
||||
config: Config,
|
||||
includeProject: Bool = true
|
||||
) -> BuildSettings {
|
||||
var buildSettings: BuildSettings = [:]
|
||||
if includeProject {
|
||||
if let configFilePath = configFiles[config.name] {
|
||||
@ -96,8 +101,19 @@ extension ProjectSpec {
|
||||
return buildSettings
|
||||
}
|
||||
|
||||
public func targetHasBuildSetting(_ setting: String, basePath: Path, target: Target, config: Config, includeProject: Bool = true) -> Bool {
|
||||
let buildSettings = getCombinedBuildSettings(basePath: basePath, target: target, config: config, includeProject: includeProject)
|
||||
public func targetHasBuildSetting(
|
||||
_ setting: String,
|
||||
basePath: Path,
|
||||
target: Target,
|
||||
config: Config,
|
||||
includeProject: Bool = true
|
||||
) -> Bool {
|
||||
let buildSettings = getCombinedBuildSettings(
|
||||
basePath: basePath,
|
||||
target: target,
|
||||
config: config,
|
||||
includeProject: includeProject
|
||||
)
|
||||
return buildSettings[setting] != nil
|
||||
}
|
||||
|
||||
|
@ -61,9 +61,19 @@ class SourceGenerator {
|
||||
settings["COMPILER_FLAGS"] = targetSource.compilerFlags.joined(separator: " ")
|
||||
}
|
||||
|
||||
// TODO: add the target name to the reference generator string so shared files don't have same reference (that will be escaped by appending a number)
|
||||
let buildFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + targetName), fileRef: fileReference, settings: settings.isEmpty ? nil : settings)
|
||||
return SourceFile(path: path, fileReference: fileReference, buildFile: buildFile, buildPhase: chosenBuildPhase)
|
||||
// TODO: add the target name to the reference generator string so shared files don't have same reference
|
||||
// (that will be escaped by appending a number)
|
||||
let buildFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + targetName),
|
||||
fileRef: fileReference,
|
||||
settings: settings.isEmpty ? nil : settings
|
||||
)
|
||||
return SourceFile(
|
||||
path: path,
|
||||
fileReference: fileReference,
|
||||
buildFile: buildFile,
|
||||
buildPhase: chosenBuildPhase
|
||||
)
|
||||
}
|
||||
|
||||
func getContainedFileReference(path: Path) -> String {
|
||||
@ -71,7 +81,12 @@ class SourceGenerator {
|
||||
|
||||
let parentPath = path.parent()
|
||||
let fileReference = getFileReference(path: path, inPath: parentPath)
|
||||
let parentGroup = getGroup(path: parentPath, mergingChildren: [fileReference], createIntermediateGroups: createIntermediateGroups, isBaseGroup: true)
|
||||
let parentGroup = getGroup(
|
||||
path: parentPath,
|
||||
mergingChildren: [fileReference],
|
||||
createIntermediateGroups: createIntermediateGroups,
|
||||
isBaseGroup: true
|
||||
)
|
||||
|
||||
if createIntermediateGroups {
|
||||
createIntermediaGroups(for: parentGroup.reference, at: parentPath)
|
||||
@ -83,7 +98,12 @@ class SourceGenerator {
|
||||
if let fileReference = fileReferencesByPath[path] {
|
||||
return fileReference
|
||||
} else {
|
||||
let fileReference = PBXFileReference(reference: referenceGenerator.generate(PBXFileReference.self, path.byRemovingBase(path: spec.basePath).string), sourceTree: sourceTree, name: name, path: path.byRemovingBase(path: inPath).string)
|
||||
let fileReference = PBXFileReference(
|
||||
reference: referenceGenerator.generate(PBXFileReference.self, path.byRemovingBase(path: spec.basePath).string),
|
||||
sourceTree: sourceTree,
|
||||
name: name,
|
||||
path: path.byRemovingBase(path: inPath).string
|
||||
)
|
||||
addObject(fileReference)
|
||||
fileReferencesByPath[path] = fileReference.reference
|
||||
return fileReference.reference
|
||||
@ -147,10 +167,12 @@ class SourceGenerator {
|
||||
if let cachedGroup = variantGroupsByPath[path] {
|
||||
variantGroup = cachedGroup
|
||||
} else {
|
||||
variantGroup = PBXVariantGroup(reference: referenceGenerator.generate(PBXVariantGroup.self, path.byRemovingBase(path: spec.basePath).string),
|
||||
children: [],
|
||||
name: path.lastComponent,
|
||||
sourceTree: .group)
|
||||
variantGroup = PBXVariantGroup(
|
||||
reference: referenceGenerator.generate(PBXVariantGroup.self, path.byRemovingBase(path: spec.basePath).string),
|
||||
children: [],
|
||||
name: path.lastComponent,
|
||||
sourceTree: .group
|
||||
)
|
||||
addObject(variantGroup)
|
||||
variantGroupsByPath[path] = variantGroup
|
||||
}
|
||||
@ -184,8 +206,10 @@ class SourceGenerator {
|
||||
+ Pre-defined Excluded files
|
||||
*/
|
||||
|
||||
let sourceExcludeFilePaths: Set<Path> = Set(getSourceExcludes(dirPath: rootSourcePath)
|
||||
+ defaultExcludedFiles)
|
||||
let sourceExcludeFilePaths: Set<Path> = Set(
|
||||
getSourceExcludes(dirPath: rootSourcePath)
|
||||
+ defaultExcludedFiles
|
||||
)
|
||||
|
||||
return try dirPath.children()
|
||||
.filter {
|
||||
@ -204,7 +228,11 @@ class SourceGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private func getGroupSources(targetSource: TargetSource, path: Path, isBaseGroup: Bool) throws -> (sourceFiles: [SourceFile], groups: [PBXGroup]) {
|
||||
private func getGroupSources(
|
||||
targetSource: TargetSource,
|
||||
path: Path,
|
||||
isBaseGroup: Bool
|
||||
) throws -> (sourceFiles: [SourceFile], groups: [PBXGroup]) {
|
||||
|
||||
let children = try getSourceChildren(targetSource: targetSource, dirPath: path)
|
||||
|
||||
@ -263,8 +291,18 @@ class SourceGenerator {
|
||||
groupChildren.append(variantGroup.reference)
|
||||
baseLocalisationVariantGroups.append(variantGroup)
|
||||
|
||||
let buildFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, variantGroup.reference + targetName), fileRef: variantGroup.reference, settings: nil)
|
||||
allSourceFiles.append(SourceFile(path: filePath, fileReference: variantGroup.reference, buildFile: buildFile, buildPhase: .resources))
|
||||
let buildFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, variantGroup.reference + targetName),
|
||||
fileRef: variantGroup.reference,
|
||||
settings: nil
|
||||
)
|
||||
let sourceFile = SourceFile(
|
||||
path: filePath,
|
||||
fileReference: variantGroup.reference,
|
||||
buildFile: buildFile,
|
||||
buildPhase: .resources
|
||||
)
|
||||
allSourceFiles.append(sourceFile)
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,10 +312,19 @@ class SourceGenerator {
|
||||
for filePath in try localisedDirectory.children().sorted { $0.lastComponent < $1.lastComponent } {
|
||||
// find base localisation variant group
|
||||
// ex: Foo.strings will be added to Foo.strings or Foo.storyboard variant group
|
||||
let variantGroup = baseLocalisationVariantGroups.first { Path($0.name!).lastComponent == filePath.lastComponent } ??
|
||||
baseLocalisationVariantGroups.first { Path($0.name!).lastComponentWithoutExtension == filePath.lastComponentWithoutExtension }
|
||||
let variantGroup = baseLocalisationVariantGroups
|
||||
.first {
|
||||
Path($0.name!).lastComponent == filePath.lastComponent
|
||||
|
||||
let fileReference = getFileReference(path: filePath, inPath: path, name: variantGroup != nil ? localisationName : filePath.lastComponent)
|
||||
} ?? baseLocalisationVariantGroups.first {
|
||||
Path($0.name!).lastComponentWithoutExtension == filePath.lastComponentWithoutExtension
|
||||
}
|
||||
|
||||
let fileReference = getFileReference(
|
||||
path: filePath,
|
||||
inPath: path,
|
||||
name: variantGroup != nil ? localisationName : filePath.lastComponent
|
||||
)
|
||||
|
||||
if let variantGroup = variantGroup {
|
||||
if !variantGroup.children.contains(fileReference) {
|
||||
@ -285,16 +332,28 @@ class SourceGenerator {
|
||||
}
|
||||
} else {
|
||||
// add SourceFile to group if there is no Base.lproj directory
|
||||
let buildFile = PBXBuildFile(reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + targetName),
|
||||
fileRef: fileReference,
|
||||
settings: nil)
|
||||
allSourceFiles.append(SourceFile(path: filePath, fileReference: fileReference, buildFile: buildFile, buildPhase: .resources))
|
||||
let buildFile = PBXBuildFile(
|
||||
reference: referenceGenerator.generate(PBXBuildFile.self, fileReference + targetName),
|
||||
fileRef: fileReference,
|
||||
settings: nil
|
||||
)
|
||||
allSourceFiles.append(SourceFile(
|
||||
path: filePath,
|
||||
fileReference: fileReference,
|
||||
buildFile: buildFile,
|
||||
buildPhase: .resources
|
||||
))
|
||||
groupChildren.append(fileReference)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let group = getGroup(path: path, mergingChildren: groupChildren, createIntermediateGroups: spec.options.createIntermediateGroups, isBaseGroup: isBaseGroup)
|
||||
let group = getGroup(
|
||||
path: path,
|
||||
mergingChildren: groupChildren,
|
||||
createIntermediateGroups: spec.options.createIntermediateGroups,
|
||||
isBaseGroup: isBaseGroup
|
||||
)
|
||||
if spec.options.createIntermediateGroups {
|
||||
createIntermediaGroups(for: group.reference, at: path)
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ extension PBXFileElement {
|
||||
extension PBXProj {
|
||||
|
||||
public func printGroups() -> String {
|
||||
guard let project = objects.projects.first?.value, let mainGroup = objects.groups.getReference(project.mainGroup) else {
|
||||
guard let project = objects.projects.first?.value,
|
||||
let mainGroup = objects.groups.getReference(project.mainGroup) else {
|
||||
return ""
|
||||
}
|
||||
return printGroup(group: mainGroup)
|
||||
|
@ -20,12 +20,20 @@ func projectGeneratorTests() {
|
||||
|
||||
describe("Project Generator") {
|
||||
|
||||
let application = Target(name: "MyApp", type: .application, platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_1": "VALUE"]),
|
||||
dependencies: [Dependency(type: .target, reference: "MyFramework")])
|
||||
let application = Target(
|
||||
name: "MyApp",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_1": "VALUE"]),
|
||||
dependencies: [Dependency(type: .target, reference: "MyFramework")]
|
||||
)
|
||||
|
||||
let framework = Target(name: "MyFramework", type: .framework, platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"]))
|
||||
let framework = Target(
|
||||
name: "MyFramework",
|
||||
type: .framework,
|
||||
platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"])
|
||||
)
|
||||
|
||||
let targets = [application, framework]
|
||||
|
||||
@ -94,7 +102,11 @@ func projectGeneratorTests() {
|
||||
}
|
||||
|
||||
$0.it("generates configs") {
|
||||
let spec = ProjectSpec(basePath: "", name: "test", configs: [Config(name: "config1"), Config(name: "config2")])
|
||||
let spec = ProjectSpec(
|
||||
basePath: "",
|
||||
name: "test",
|
||||
configs: [Config(name: "config1"), Config(name: "config2")]
|
||||
)
|
||||
let project = try getProject(spec)
|
||||
let configs = project.pbxproj.objects.buildConfigurations.referenceValues
|
||||
try expect(configs.count) == 2
|
||||
@ -103,7 +115,11 @@ func projectGeneratorTests() {
|
||||
}
|
||||
|
||||
$0.it("clears config settings when missing type") {
|
||||
let spec = ProjectSpec(basePath: "", name: "test", configs: [Config(name: "config")])
|
||||
let spec = ProjectSpec(
|
||||
basePath: "",
|
||||
name: "test",
|
||||
configs: [Config(name: "config")]
|
||||
)
|
||||
let project = try getProject(spec)
|
||||
guard let config = project.pbxproj.objects.buildConfigurations.first?.value else {
|
||||
throw failure("configuration not found")
|
||||
@ -140,11 +156,15 @@ func projectGeneratorTests() {
|
||||
}
|
||||
|
||||
$0.it("applies partial config settings") {
|
||||
let spec = ProjectSpec(basePath: "", name: "test", configs: [
|
||||
Config(name: "Staging Debug", type: .debug),
|
||||
Config(name: "Staging Release", type: .release),
|
||||
],
|
||||
settings: Settings(configSettings: ["staging": ["SETTING1": "VALUE1"], "debug": ["SETTING2": "VALUE2"]]))
|
||||
let spec = ProjectSpec(
|
||||
basePath: "",
|
||||
name: "test",
|
||||
configs: [
|
||||
Config(name: "Staging Debug", type: .debug),
|
||||
Config(name: "Staging Release", type: .release),
|
||||
],
|
||||
settings: Settings(configSettings: ["staging": ["SETTING1": "VALUE1"], "debug": ["SETTING2": "VALUE2"]])
|
||||
)
|
||||
|
||||
var buildSettings = spec.getProjectBuildSettings(config: spec.configs.first!)
|
||||
try expect(buildSettings["SETTING1"] as? String) == "VALUE1"
|
||||
@ -207,7 +227,8 @@ func projectGeneratorTests() {
|
||||
scriptSpec.targets[0].postbuildScripts = [BuildScript(script: .script("script2"))]
|
||||
let pbxProject = try getPbxProj(scriptSpec)
|
||||
|
||||
guard let nativeTarget = pbxProject.objects.nativeTargets.referenceValues.first(where: { !$0.buildPhases.isEmpty }) else {
|
||||
guard let nativeTarget = pbxProject.objects.nativeTargets.referenceValues
|
||||
.first(where: { !$0.buildPhases.isEmpty }) else {
|
||||
throw failure("Target with build phases not found")
|
||||
}
|
||||
let buildPhases = nativeTarget.buildPhases
|
||||
@ -224,9 +245,23 @@ func projectGeneratorTests() {
|
||||
}
|
||||
|
||||
$0.it("generates targets with cylical dependencies") {
|
||||
let target1 = Target(name: "target1", type: .framework, platform: .iOS, dependencies: [Dependency(type: .target, reference: "target2")])
|
||||
let target2 = Target(name: "target2", type: .framework, platform: .iOS, dependencies: [Dependency(type: .target, reference: "target1")])
|
||||
let spec = ProjectSpec(basePath: "", name: "test", targets: [target1, target2])
|
||||
let target1 = Target(
|
||||
name: "target1",
|
||||
type: .framework,
|
||||
platform: .iOS,
|
||||
dependencies: [Dependency(type: .target, reference: "target2")]
|
||||
)
|
||||
let target2 = Target(
|
||||
name: "target2",
|
||||
type: .framework,
|
||||
platform: .iOS,
|
||||
dependencies: [Dependency(type: .target, reference: "target1")]
|
||||
)
|
||||
let spec = ProjectSpec(
|
||||
basePath: "",
|
||||
name: "test",
|
||||
targets: [target1, target2]
|
||||
)
|
||||
|
||||
_ = try getPbxProj(spec)
|
||||
}
|
||||
@ -236,13 +271,28 @@ func projectGeneratorTests() {
|
||||
|
||||
let buildTarget = Scheme.BuildTarget(target: application.name)
|
||||
$0.it("generates scheme") {
|
||||
let scheme = Scheme(name: "MyScheme", build: Scheme.Build(targets: [buildTarget]))
|
||||
let spec = ProjectSpec(basePath: "", name: "test", targets: [application, framework], schemes: [scheme])
|
||||
let scheme = Scheme(
|
||||
name: "MyScheme",
|
||||
build: Scheme.Build(targets: [buildTarget])
|
||||
)
|
||||
let spec = ProjectSpec(
|
||||
basePath: "",
|
||||
name: "test",
|
||||
targets: [application, framework],
|
||||
schemes: [scheme]
|
||||
)
|
||||
let project = try getProject(spec)
|
||||
guard let target = project.pbxproj.objects.nativeTargets.referenceValues.first(where: { $0.name == application.name }) else { throw failure("Target not found") }
|
||||
guard let xcscheme = project.sharedData?.schemes.first else { throw failure("Scheme not found") }
|
||||
guard let target = project.pbxproj.objects.nativeTargets.referenceValues
|
||||
.first(where: { $0.name == application.name }) else {
|
||||
throw failure("Target not found")
|
||||
}
|
||||
guard let xcscheme = project.sharedData?.schemes.first else {
|
||||
throw failure("Scheme not found")
|
||||
}
|
||||
try expect(scheme.name) == "MyScheme"
|
||||
guard let buildActionEntry = xcscheme.buildAction?.buildActionEntries.first else { throw failure("Build Action entry not found") }
|
||||
guard let buildActionEntry = xcscheme.buildAction?.buildActionEntries.first else {
|
||||
throw failure("Build Action entry not found")
|
||||
}
|
||||
try expect(buildActionEntry.buildFor) == BuildType.all
|
||||
|
||||
let buildableReferences: [XCScheme.BuildableReference] = [
|
||||
@ -281,9 +331,17 @@ func projectGeneratorTests() {
|
||||
|
||||
try expect(project.sharedData?.schemes.count) == 2
|
||||
|
||||
guard let nativeTarget = project.pbxproj.objects.nativeTargets.referenceValues.first(where: { $0.name == application.name }) else { throw failure("Target not found") }
|
||||
guard let xcscheme = project.sharedData?.schemes.first(where: { $0.name == "\(target.name) Test" }) else { throw failure("Scheme not found") }
|
||||
guard let buildActionEntry = xcscheme.buildAction?.buildActionEntries.first else { throw failure("Build Action entry not found") }
|
||||
guard let nativeTarget = project.pbxproj.objects.nativeTargets.referenceValues
|
||||
.first(where: { $0.name == application.name }) else {
|
||||
throw failure("Target not found")
|
||||
}
|
||||
guard let xcscheme = project.sharedData?.schemes
|
||||
.first(where: { $0.name == "\(target.name) Test" }) else {
|
||||
throw failure("Scheme not found")
|
||||
}
|
||||
guard let buildActionEntry = xcscheme.buildAction?.buildActionEntries.first else {
|
||||
throw failure("Build Action entry not found")
|
||||
}
|
||||
try expect(buildActionEntry.buildableReference.blueprintIdentifier) == nativeTarget.reference
|
||||
|
||||
try expect(xcscheme.launchAction?.buildConfiguration) == "Test Debug"
|
||||
@ -397,7 +455,12 @@ func projectGeneratorTests() {
|
||||
try createDirectories(directories)
|
||||
|
||||
let target = Target(name: "Test", type: .application, platform: .iOS, sources: ["Sources"])
|
||||
let spec = ProjectSpec(basePath: directoryPath, name: "Test", targets: [target], fileGroups: ["Sources"])
|
||||
let spec = ProjectSpec(
|
||||
basePath: directoryPath,
|
||||
name: "Test",
|
||||
targets: [target],
|
||||
fileGroups: ["Sources"]
|
||||
)
|
||||
|
||||
let project = try getPbxProj(spec)
|
||||
try project.expectFile(paths: ["Sources", "a.swift"], buildPhase: .sources)
|
||||
@ -720,8 +783,10 @@ extension PBXProj {
|
||||
}
|
||||
|
||||
if let buildPhase = buildPhase {
|
||||
let buildFile = objects.buildFiles.referenceValues.first(where: { $0.fileRef == fileReference.reference })
|
||||
let actualBuildPhase = buildFile.flatMap { buildFile in objects.buildPhases.referenceValues.first { $0.files.contains(buildFile.reference) } }?.buildPhase
|
||||
let buildFile = objects.buildFiles.referenceValues
|
||||
.first(where: { $0.fileRef == fileReference.reference })
|
||||
let actualBuildPhase = buildFile
|
||||
.flatMap { buildFile in objects.buildPhases.referenceValues.first { $0.files.contains(buildFile.reference) } }?.buildPhase
|
||||
|
||||
var error: String?
|
||||
if let buildPhase = buildPhase.buildPhase {
|
||||
|
@ -7,18 +7,31 @@ func projectSpecTests() {
|
||||
|
||||
describe("ProjectSpec") {
|
||||
|
||||
let framework = Target(name: "MyFramework", type: .framework, platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"]))
|
||||
let staticLibrary = Target(name: "MyStaticLibrary", type: .staticLibrary, platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"]))
|
||||
let dynamicLibrary = Target(name: "MyDynamicLibrary", type: .dynamicLibrary, platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"]))
|
||||
let framework = Target(
|
||||
name: "MyFramework",
|
||||
type: .framework,
|
||||
platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"])
|
||||
)
|
||||
let staticLibrary = Target(
|
||||
name: "MyStaticLibrary",
|
||||
type: .staticLibrary,
|
||||
platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"])
|
||||
)
|
||||
let dynamicLibrary = Target(
|
||||
name: "MyDynamicLibrary",
|
||||
type: .dynamicLibrary,
|
||||
platform: .iOS,
|
||||
settings: Settings(buildSettings: ["SETTING_2": "VALUE"])
|
||||
)
|
||||
|
||||
func expectValidationError(_ spec: ProjectSpec, _ expectedError: SpecValidationError.ValidationError) throws {
|
||||
do {
|
||||
try spec.validate()
|
||||
} catch let error as SpecValidationError {
|
||||
if !error.errors.contains(where: { $0.description == expectedError.description }) {
|
||||
if !error.errors
|
||||
.contains(where: { $0.description == expectedError.description }) {
|
||||
throw failure("Supposed to fail with:\n\(expectedError)\nbut got:\n\(error.errors.map { $0.description }.joined(separator: "\n"))")
|
||||
}
|
||||
return
|
||||
@ -65,14 +78,19 @@ func projectSpecTests() {
|
||||
$0.describe("Validation") {
|
||||
|
||||
let baseSpec = ProjectSpec(basePath: "", name: "", configs: [Config(name: "invalid")])
|
||||
let invalidSettings = Settings(configSettings: ["invalidConfig": [:]],
|
||||
groups: ["invalidSettingGroup"])
|
||||
let invalidSettings = Settings(
|
||||
configSettings: ["invalidConfig": [:]],
|
||||
groups: ["invalidSettingGroup"]
|
||||
)
|
||||
$0.it("fails with invalid project") {
|
||||
var spec = baseSpec
|
||||
spec.settings = invalidSettings
|
||||
spec.configFiles = ["invalidConfig": "invalidConfigFile"]
|
||||
spec.fileGroups = ["invalidFileGroup"]
|
||||
spec.settingGroups = ["settingGroup1": Settings(configSettings: ["invalidSettingGroupConfig": [:]], groups: ["invalidSettingGroupSettingGroup"])]
|
||||
spec.settingGroups = ["settingGroup1": Settings(
|
||||
configSettings: ["invalidSettingGroupConfig": [:]],
|
||||
groups: ["invalidSettingGroupSettingGroup"]
|
||||
)]
|
||||
|
||||
try expectValidationError(spec, .invalidConfigFileConfig("invalidConfig"))
|
||||
try expectValidationError(spec, .invalidBuildSettingConfig("invalidConfig"))
|
||||
@ -85,16 +103,17 @@ func projectSpecTests() {
|
||||
|
||||
$0.it("fails with invalid target") {
|
||||
var spec = baseSpec
|
||||
spec.targets = [Target(name: "target1",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
settings: invalidSettings,
|
||||
configFiles: ["invalidConfig": "invalidConfigFile"],
|
||||
sources: ["invalidSource"],
|
||||
dependencies: [Dependency(type: .target, reference: "invalidDependency")],
|
||||
prebuildScripts: [BuildScript(script: .path("invalidPrebuildScript"), name: "prebuildScript1")],
|
||||
postbuildScripts: [BuildScript(script: .path("invalidPostbuildScript"))],
|
||||
scheme: TargetScheme(testTargets: ["invalidTarget"])
|
||||
spec.targets = [Target(
|
||||
name: "target1",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
settings: invalidSettings,
|
||||
configFiles: ["invalidConfig": "invalidConfigFile"],
|
||||
sources: ["invalidSource"],
|
||||
dependencies: [Dependency(type: .target, reference: "invalidDependency")],
|
||||
prebuildScripts: [BuildScript(script: .path("invalidPrebuildScript"), name: "prebuildScript1")],
|
||||
postbuildScripts: [BuildScript(script: .path("invalidPostbuildScript"))],
|
||||
scheme: TargetScheme(testTargets: ["invalidTarget"])
|
||||
)]
|
||||
|
||||
try expectValidationError(spec, .invalidTargetDependency(target: "target1", dependency: "invalidDependency"))
|
||||
@ -115,10 +134,11 @@ func projectSpecTests() {
|
||||
|
||||
$0.it("fails with invalid scheme") {
|
||||
var spec = baseSpec
|
||||
spec.schemes = [Scheme(name: "scheme1",
|
||||
build: .init(targets: [.init(target: "invalidTarget")]),
|
||||
run: .init(config: "debugInvalid"),
|
||||
archive: .init(config: "releaseInvalid")
|
||||
spec.schemes = [Scheme(
|
||||
name: "scheme1",
|
||||
build: .init(targets: [.init(target: "invalidTarget")]),
|
||||
run: .init(config: "debugInvalid"),
|
||||
archive: .init(config: "releaseInvalid")
|
||||
)]
|
||||
|
||||
try expectValidationError(spec, .invalidSchemeTarget(scheme: "scheme1", target: "invalidTarget"))
|
||||
@ -128,10 +148,11 @@ func projectSpecTests() {
|
||||
|
||||
$0.it("allows missing optional file") {
|
||||
var spec = baseSpec
|
||||
spec.targets = [Target(name: "target1",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
sources: [.init(path: "generated.swift", optional: true)]
|
||||
spec.targets = [Target(
|
||||
name: "target1",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
sources: [.init(path: "generated.swift", optional: true)]
|
||||
)]
|
||||
try spec.validate()
|
||||
}
|
||||
|
@ -224,15 +224,18 @@ func specLoadingTests() {
|
||||
}
|
||||
|
||||
$0.it("parses options") {
|
||||
let options = ProjectSpec.Options(carthageBuildPath: "../Carthage/Build",
|
||||
createIntermediateGroups: true,
|
||||
bundleIdPrefix: "com.test",
|
||||
developmentLanguage: "ja",
|
||||
deploymentTarget: DeploymentTarget(
|
||||
iOS: "11.1",
|
||||
tvOS: "10.0",
|
||||
watchOS: "3.0",
|
||||
macOS: "10.12.1"))
|
||||
let options = ProjectSpec.Options(
|
||||
carthageBuildPath: "../Carthage/Build",
|
||||
createIntermediateGroups: true,
|
||||
bundleIdPrefix: "com.test",
|
||||
developmentLanguage: "ja",
|
||||
deploymentTarget: DeploymentTarget(
|
||||
iOS: "11.1",
|
||||
tvOS: "10.0",
|
||||
watchOS: "3.0",
|
||||
macOS: "10.12.1"
|
||||
)
|
||||
)
|
||||
let expected = ProjectSpec(basePath: "", name: "test", options: options)
|
||||
let dictionary: [String: Any] = ["options": [
|
||||
"carthageBuildPath": "../Carthage/Build",
|
||||
|
Loading…
Reference in New Issue
Block a user