Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XCConfig files #64

Merged
merged 11 commits into from
Sep 24, 2017
2 changes: 2 additions & 0 deletions Fixtures/TestProject/Configs/base.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BASE_SETTING = baseSetting
OVERWRITTEN_SETTING = base
4 changes: 4 additions & 0 deletions Fixtures/TestProject/Configs/config.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#include "base.xcconfig"

CONFIG_SETTING = configSetting
OVERWRITTEN_SETTING = new
14 changes: 14 additions & 0 deletions Fixtures/TestProject/GeneratedProject.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@
FR1345298503 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
FR2653659501 /* TestProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = xctest; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = TestProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
FR2993497801 /* MyFramework.framework */ = {isa = PBXFileReference; explicitFileType = framework; includeInIndex = 0; lastKnownFileType = wrapper.framework; path = MyFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FR3546283901 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = "<group>"; };
FR3676338401 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
FR3676338402 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
FR5980633301 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
FR6218091901 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
FR6334256101 /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = config.xcconfig; sourceTree = "<group>"; };
FR6523263101 /* TestProject.app */ = {isa = PBXFileReference; explicitFileType = app; includeInIndex = 0; lastKnownFileType = wrapper.application; path = TestProject.app; sourceTree = BUILT_PRODUCTS_DIR; };
FR6877173101 /* TestProjectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProjectTests.swift; sourceTree = "<group>"; };
FR7078510801 /* FrameworkFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameworkFile.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -104,9 +106,20 @@
path = TestProject;
sourceTree = "<group>";
};
G83406189501 /* Configs */ = {
isa = PBXGroup;
children = (
FR3546283901 /* base.xcconfig */,
FR6334256101 /* config.xcconfig */,
);
name = Configs;
path = Configs;
sourceTree = "<group>";
};
G84487712001 = {
isa = PBXGroup;
children = (
G83406189501 /* Configs */,
G29934978701 /* MyFramework */,
G65232631501 /* TestProject */,
G26536595301 /* TestProjectTests */,
Expand Down Expand Up @@ -386,6 +399,7 @@
};
XCBC37128501 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = FR6334256101 /* config.xcconfig */;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
Expand Down
15 changes: 15 additions & 0 deletions Fixtures/TestProject/TestProject.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
CC2A0EBF1F33D50E00C324B9 /* TestProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
CC2A0EC11F33D50E00C324B9 /* TestProjectTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProjectTests.swift; sourceTree = "<group>"; };
CC2A0EC31F33D50E00C324B9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CC9392651F76EDF800C1934A /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = base.xcconfig; path = Configs/base.xcconfig; sourceTree = SOURCE_ROOT; };
CC9392661F76EDF800C1934A /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = Configs/config.xcconfig; sourceTree = SOURCE_ROOT; };
CCA4B60A1F1FC00500DF34A1 /* TestProject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestProject.app; sourceTree = BUILT_PRODUCTS_DIR; };
CCA4B60D1F1FC00500DF34A1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
CCA4B60F1F1FC00500DF34A1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -102,9 +104,20 @@
path = TestProjectTests;
sourceTree = "<group>";
};
CC9392641F76EDE600C1934A /* Configs */ = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you create this TestProject.xcodeproj/project.pbxproj ?
On Xcode, Configs group is missing reference (appears red).

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TestProject.xcodeproj was created and edited in Xcode. GeneratedProject.xcodeproj is the one generated by XcodeGen.

I'm not sure what you mean by missing configs group. Both projects appear fine for me

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just saw what you mean by the red group, I've fixed this in master. This project isn't really used in any tests and is more just for a comparison between a project created in xcode versus created in XcodeGen

isa = PBXGroup;
children = (
CC9392651F76EDF800C1934A /* base.xcconfig */,
CC9392661F76EDF800C1934A /* config.xcconfig */,
);
name = Configs;
path = "New Group";
sourceTree = "<group>";
};
CCA4B6011F1FC00500DF34A1 = {
isa = PBXGroup;
children = (
CC9392641F76EDE600C1934A /* Configs */,
CCA4B60C1F1FC00500DF34A1 /* TestProject */,
CCA71FE91F225E4C00F772C1 /* MyFramework */,
CC2A0EC01F33D50E00C324B9 /* TestProjectTests */,
Expand Down Expand Up @@ -509,6 +522,7 @@
};
CCA4B61D1F1FC00500DF34A1 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = CC9392661F76EDF800C1934A /* config.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
Expand Down Expand Up @@ -592,6 +606,7 @@
CC2A0EC71F33D50E00C324B9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
CCA4B6051F1FC00500DF34A1 /* Build configuration list for PBXProject "TestProject" */ = {
isa = XCConfigurationList;
Expand Down
4 changes: 4 additions & 0 deletions Fixtures/TestProject/spec.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
name: GeneratedProject
groups:
- Configs
targets:
TestProject:
type: application
Expand All @@ -23,6 +25,8 @@ targets:
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
configFiles:
Debug: Configs/config.xcconfig
MyFramework:
type: framework
platform: iOS
Expand Down
10 changes: 9 additions & 1 deletion Sources/ProjectSpec/ProjectSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public struct ProjectSpec {
public var schemes: [Scheme]
public var options: Options
public var attributes: [String: Any]
public var groups: [String]
public var configFiles: [String: String]

public struct Options {
public var carthageBuildPath: String?
Expand All @@ -31,14 +33,16 @@ public struct ProjectSpec {
}
}

public init(name: String, configs: [Config] = [], targets: [Target] = [], settings: Settings = .empty, settingGroups: [String: Settings] = [:], schemes: [Scheme] = [], options: Options = Options(), attributes: [String: Any] = [:]) {
public init(name: String, configs: [Config] = [], targets: [Target] = [], settings: Settings = .empty, settingGroups: [String: Settings] = [:], schemes: [Scheme] = [], options: Options = Options(), groups: [String] = [], configFiles: [String: String] = [:], attributes: [String: Any] = [:]) {
self.name = name
self.targets = targets
self.configs = configs
self.settings = settings
self.settingGroups = settingGroups
self.schemes = schemes
self.options = options
self.groups = groups
self.configFiles = configFiles
self.attributes = attributes
}

Expand All @@ -60,6 +64,8 @@ extension ProjectSpec: Equatable {
lhs.settingGroups == rhs.settingGroups &&
lhs.configs == rhs.configs &&
lhs.schemes == rhs.schemes &&
lhs.groups == rhs.groups &&
lhs.configFiles == rhs.configFiles &&
lhs.options == rhs.options
}
}
Expand All @@ -82,6 +88,8 @@ extension ProjectSpec: JSONObjectConvertible {
self.configs = configs.map { Config(name: $0, type: ConfigType(rawValue: $1)) }
targets = try jsonDictionary.json(atKeyPath: "targets").sorted { $0.name < $1.name }
schemes = try jsonDictionary.json(atKeyPath: "schemes")
groups = jsonDictionary.json(atKeyPath: "groups") ?? []
configFiles = jsonDictionary.json(atKeyPath: "configFiles") ?? [:]
attributes = jsonDictionary.json(atKeyPath: "attributes") ?? [:]
if jsonDictionary["options"] != nil {
options = try jsonDictionary.json(atKeyPath: "options")
Expand Down
13 changes: 10 additions & 3 deletions Sources/XcodeGenKit/PBXProjGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,17 @@ public class PBXProjGenerator {
uuids = []
project = PBXProj(archiveVersion: 1, objectVersion: 46, rootObject: generateUUID(PBXProject.self, spec.name))

for group in spec.groups {
_ = try getGroups(path: basePath + group)
}

let buildConfigs: [XCBuildConfiguration] = spec.configs.map { config in
let buildSettings = spec.getProjectBuildSettings(config: config)
return XCBuildConfiguration(reference: generateUUID(XCBuildConfiguration.self, config.name), name: config.name, baseConfigurationReference: nil, buildSettings: buildSettings)
var baseConfigurationReference: String?
if let configPath = spec.configFiles[config.name] {
baseConfigurationReference = getFileReference(path: basePath + configPath, inPath: basePath)
}
return XCBuildConfiguration(reference: generateUUID(XCBuildConfiguration.self, config.name), name: config.name, baseConfigurationReference: baseConfigurationReference, buildSettings: buildSettings)
}

let buildConfigList = XCConfigurationList(reference: generateUUID(XCConfigurationList.self, spec.name), buildConfigurations: buildConfigs.references, defaultConfigurationName: buildConfigs.first?.name ?? "", defaultConfigurationIsVisible: 0)
Expand Down Expand Up @@ -189,8 +197,7 @@ public class PBXProjGenerator {

var baseConfigurationReference: String?
if let configPath = target.configFiles[config.name] {
let path = basePath + configPath
baseConfigurationReference = fileReferencesByPath[path]
baseConfigurationReference = getFileReference(path: basePath + configPath, inPath: basePath)
}
return XCBuildConfiguration(reference: generateUUID(XCBuildConfiguration.self, config.name + target.name), name: config.name, baseConfigurationReference: baseConfigurationReference, buildSettings: buildSettings)
}
Expand Down
10 changes: 7 additions & 3 deletions Sources/XcodeGenKit/SettingsBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,19 @@ extension ProjectSpec {
return buildSettings
}

// combines all levels of a target's settings
// 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) -> BuildSettings {
var buildSettings: BuildSettings = [:]
if includeProject {
if let configFilePath = configFiles[config.name] {
if let configFile = try? XCConfig(path: basePath + configFilePath) {
buildSettings += configFile.flattenedBuildSettings()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe including xcconfig should just #include the included xcconfig, not adding to buildSettings section.🤔
What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh and what if included xcconfig #include other xcconfigs?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean by the first point? Maybe these will answer your question.

  • this function is just use for getting all the combined settings for the purposes of checking what build settings will be applied - similar to Xcode's combined settings view
  • xcconfigs aren't added using #include they are just set as a baseconfiguration for the target or project. The rest of the build settings are applied directly on the build setting or project and don't use an xcconfig

For the second point configFile. flattenedBuildSettings() goes through all #include files and merges them 👍

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I'm going to take a look at the details.👌

Copy link
Collaborator

@toshi0383 toshi0383 Sep 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the second point configFile. flattenedBuildSettings() goes through all #include files and merges them 👍

What I meant was XcodeGen:Include.
I see XcodeGen:Include just ignores XcodeGen:Included spec's configFile.

TestProject $ head spec.yml
include: included.yml
name: GeneratedProject
groups:
  - Configs
targets:
  TestProject:
    type: application
    platform: iOS
    sources: TestProject
    settings:
TestProject $ head included.yml
configFiles:
  Debug: Included/Configs/included.xcconfig  # This is completely ignored when `XcodeGen:included`.

This behavior is perfectly 🙆‍♂️ to me. Maybe it worth it to warn user when XcodeGen:included spec has configFile attribute, because it's ignored.

Maybe we should really rename XcodeGen:include to something else to avoid confusion. 🙄

Copy link
Owner Author

@yonaskolb yonaskolb Sep 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because include is a list not just a string. I should change this though to allow a simple string for a single value, just like a target's sources:

include: [included.yml] #works, using json style
include:
  - included.yml #works, using yaml style
include: included.yml #doesn't work (yet, will change)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include can now be a single string 39c8af3

}
}
buildSettings += getProjectBuildSettings(config: config)
}
if let configFilePath = target.configFiles[config.name] {
let path = basePath + configFilePath
if let configFile = try? XCConfig(path: path) {
if let configFile = try? XCConfig(path: basePath + configFilePath) {
buildSettings += configFile.flattenedBuildSettings()
}
}
Expand Down
2 changes: 2 additions & 0 deletions docs/ProjectSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ Required properties are marked 🔵 and optional properties with ⚪️.
- ⚪️ **options**: [Options](#options) - Various options to override default behaviour
- ⚪️ **attributes**: `map` - The PBXProject attributes. This is for advanced use. Defaults to ``{"LastUpgradeCheck": "0900"}``
- ⚪️ **configs**: [Configs](#configs) - Project build configurations. Defaults to `Debug` and `Release` configs
- ⚪️ **configFiles**: [Config Files](#config-files) - `.xcconfig` files per config
- ⚪️ **settings**: [Settings](#settings) - Project specific settings. Default base and config type settings will be applied first before any settings defined here
- ⚪️ **settingGroups**: [Setting Groups](#setting-groups) - Setting groups mapped by name
- ⚪️ **targets**: [Target](#target) - The list of targets in the project mapped by name
- ⚪️ **groups**: `[String]` - A list of paths to add to the top level groups. These are files that aren't build files but that you'd like in the project heirachy. For example a folder xcconfig files that aren't already added by any target sources.

### Options
- ⚪️ **carthageBuildPath**: `String` - The path to the carthage build directory. Defaults to `Carthage/Build`. This is used when specifying target carthage dependencies
Expand Down