Skip to content

Commit 9062760

Browse files
authored
Merge branch 'master' into project-format
2 parents 67a25a0 + 167d119 commit 9062760

30 files changed

Lines changed: 684 additions & 284 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
name: Xcode ${{ matrix.xcode }}
99
strategy:
1010
matrix:
11-
xcode: ["16.0", "16.3"]
11+
xcode: ["16.4", "26.2"]
1212
env:
1313
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
1414
steps:

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Next Version
44

5+
- Adds an `explicitFolders` property to `TargetSource` that is passed through to `PBXFileSystemSynchronizedRootGroup`, to turn entire subfolders into Resources. #1596 @macguru
6+
- Allow synced folders to be sorted using `groupOrdering`. #1596 @macguru
7+
- Fixed synced folders ignoring `createIntermediateGroups=YES` and always beging created at the root level. #1596 @macguru
8+
- Fix membership exceptions not working for nested synced folders with intermediate groups enabled. #1596 @macguru
9+
510
## 2.44.1
611

712
### Fixed

Docs/ProjectSpec.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ A source can be provided via a string (the path) or an object of the form:
527527
- [ ] **compilerFlags**: **[String]** or **String** - A list of compilerFlags to add to files under this specific path provided as a list or a space delimited string. Defaults to empty.
528528
- [ ] **excludes**: **[String]** - A list of [global patterns](https://en.wikipedia.org/wiki/Glob_(programming)) representing the files to exclude. These rules are relative to `path` and _not the directory where `project.yml` resides_. XcodeGen uses Bash 4's Glob behaviors where globstar (**) is enabled.
529529
- [ ] **includes**: **[String]** - A list of global patterns in the same format as `excludes` representing the files to include. These rules are relative to `path` and _not the directory where `project.yml` resides_. If **excludes** is present and file conflicts with **includes**, **excludes** will override the **includes** behavior.
530+
- [ ] **explicitFolders**: **[String]** - Only valid for `syncedFolder` type. A list of global patterns in the same format as `excludes` to child folders that Xcode should treat as folder references.
530531
- [ ] **destinationFilters**: **[[Supported Destinations](#supported-destinations)]** - List of supported platform destinations the files should filter to. Defaults to all supported destinations.
531532
- [ ] **inferDestinationFiltersByPath**: **Bool** - This is a convenience filter that helps you to filter the files if their paths match these patterns `**/<supportedDestination>/*` or `*_<supportedDestination>.swift`. Note, if you use `destinationFilters` this flag will be ignored.
532533
- [ ] **createIntermediateGroups**: **Bool** - This overrides the value in [Options](#options).

Package.resolved

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import PackageDescription
44

55
let package = Package(
66
name: "XcodeGen",
7-
platforms: [.macOS(.v10_13)],
7+
platforms: [.macOS(.v11)],
88
products: [
99
.executable(name: "xcodegen", targets: ["XcodeGen"]),
1010
.library(name: "XcodeGenKit", targets: ["XcodeGenKit"]),
@@ -16,10 +16,10 @@ let package = Package(
1616
.package(url: "https://github.com/yonaskolb/JSONUtilities.git", from: "4.2.0"),
1717
.package(url: "https://github.com/kylef/Spectre.git", from: "0.9.2"),
1818
.package(url: "https://github.com/onevcat/Rainbow.git", from: "4.0.0"),
19-
.package(url: "https://github.com/tuist/XcodeProj.git", exact: "8.27.7"),
19+
.package(url: "https://github.com/tuist/XcodeProj.git", exact: "9.10.1"),
2020
.package(url: "https://github.com/jakeheis/SwiftCLI.git", from: "6.0.3"),
2121
.package(url: "https://github.com/mxcl/Version", from: "2.0.0"),
22-
.package(url: "https://github.com/freddi-kit/ArtifactBundleGen", exact: "0.0.6")
22+
.package(url: "https://github.com/freddi-kit/ArtifactBundleGen", exact: "0.0.8")
2323
],
2424
targets: [
2525
.executableTarget(name: "XcodeGen", dependencies: [

Sources/ProjectSpec/Linkage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ extension Target {
5656
private extension BuildSettings {
5757

5858
var machOType: String? {
59-
self["MACH_O_TYPE"] as? String
59+
self["MACH_O_TYPE"]?.stringValue
6060
}
6161
}

Sources/ProjectSpec/Settings.swift

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,17 @@ public struct Settings: Equatable, JSONObjectConvertible, CustomStringConvertibl
1515
self.groups = groups
1616
}
1717

18-
public init(dictionary: [String: Any]) {
19-
buildSettings = dictionary
20-
configSettings = [:]
21-
groups = []
22-
}
23-
24-
public static let empty: Settings = Settings(dictionary: [:])
18+
public static let empty: Settings = Settings(buildSettings: [:])
2519

2620
public init(jsonDictionary: JSONDictionary) throws {
2721
if jsonDictionary["configs"] != nil || jsonDictionary["groups"] != nil || jsonDictionary["base"] != nil {
2822
groups = jsonDictionary.json(atKeyPath: "groups") ?? jsonDictionary.json(atKeyPath: "presets") ?? []
2923
let buildSettingsDictionary: JSONDictionary = jsonDictionary.json(atKeyPath: "base") ?? [:]
30-
buildSettings = buildSettingsDictionary
24+
buildSettings = buildSettingsDictionary.mapValues { BuildSetting(any: $0) }
3125

3226
self.configSettings = try Self.extractValidConfigs(from: jsonDictionary)
3327
} else {
34-
buildSettings = jsonDictionary
28+
buildSettings = jsonDictionary.mapValues { BuildSetting(any: $0) }
3529
configSettings = [:]
3630
groups = []
3731
}
@@ -58,7 +52,7 @@ public struct Settings: Equatable, JSONObjectConvertible, CustomStringConvertibl
5852
}
5953

6054
public static func == (lhs: Settings, rhs: Settings) -> Bool {
61-
NSDictionary(dictionary: lhs.buildSettings).isEqual(to: rhs.buildSettings) &&
55+
lhs.buildSettings == rhs.buildSettings &&
6256
lhs.configSettings == rhs.configSettings &&
6357
lhs.groups == rhs.groups
6458
}
@@ -96,14 +90,14 @@ public struct Settings: Equatable, JSONObjectConvertible, CustomStringConvertibl
9690

9791
extension Settings: ExpressibleByDictionaryLiteral {
9892

99-
public init(dictionaryLiteral elements: (String, Any)...) {
100-
var dictionary: [String: Any] = [:]
101-
elements.forEach { dictionary[$0.0] = $0.1 }
102-
self.init(dictionary: dictionary)
93+
public init(dictionaryLiteral elements: (String, BuildSetting)...) {
94+
var buildSettings: BuildSettings = [:]
95+
elements.forEach { buildSettings[$0.0] = $0.1 }
96+
self.init(buildSettings: buildSettings)
10397
}
10498
}
10599

106-
extension Dictionary where Key == String, Value: Any {
100+
extension Dictionary where Key == String {
107101

108102
public func merged(_ dictionary: [Key: Value]) -> [Key: Value] {
109103
var mergedDictionary = self
@@ -116,26 +110,56 @@ extension Dictionary where Key == String, Value: Any {
116110
self[key] = value
117111
}
118112
}
119-
120-
public func equals(_ dictionary: BuildSettings) -> Bool {
121-
NSDictionary(dictionary: self).isEqual(to: dictionary)
122-
}
123113
}
124114

125115
public func += (lhs: inout BuildSettings, rhs: BuildSettings?) {
126116
guard let rhs = rhs else { return }
127117
lhs.merge(rhs)
128118
}
129119

120+
extension BuildSetting {
121+
122+
public init(any value: Any) {
123+
if let array = value as? [String] {
124+
self = .array(array)
125+
} else if let bool = value as? Bool {
126+
self = .init(booleanLiteral: bool)
127+
} else {
128+
self = .string("\(value)")
129+
}
130+
}
131+
132+
public func toAny() -> Any {
133+
switch self {
134+
case let .string(value): return value
135+
case let .array(value): return value
136+
}
137+
}
138+
}
139+
140+
extension ProjectAttribute {
141+
142+
public init(any value: Any) {
143+
if let array = value as? [String] {
144+
self = .array(array)
145+
} else if let object = value as? PBXObject {
146+
self = .targetReference(object)
147+
} else {
148+
self = .string("\(value)")
149+
}
150+
}
151+
}
152+
130153
extension Settings: JSONEncodable {
131154
public func toJSONValue() -> Any {
155+
let anySettings = buildSettings.mapValues { $0.toAny() }
132156
if groups.count > 0 || configSettings.count > 0 {
133157
return [
134-
"base": buildSettings,
158+
"base": anySettings,
135159
"groups": groups,
136160
"configs": configSettings.mapValues { $0.toJSONValue() },
137161
] as [String : Any]
138162
}
139-
return buildSettings
163+
return anySettings
140164
}
141165
}

Sources/ProjectSpec/TargetSource.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public struct TargetSource: Equatable {
1616
public var compilerFlags: [String]
1717
public var excludes: [String]
1818
public var includes: [String]
19+
public var explicitFolders: [String]
1920
public var type: SourceType?
2021
public var optional: Bool
2122
public var buildPhase: BuildPhaseSpec?
@@ -47,6 +48,7 @@ public struct TargetSource: Equatable {
4748
compilerFlags: [String] = [],
4849
excludes: [String] = [],
4950
includes: [String] = [],
51+
explicitFolders: [String] = [],
5052
type: SourceType? = nil,
5153
optional: Bool = optionalDefault,
5254
buildPhase: BuildPhaseSpec? = nil,
@@ -63,6 +65,7 @@ public struct TargetSource: Equatable {
6365
self.compilerFlags = compilerFlags
6466
self.excludes = excludes
6567
self.includes = includes
68+
self.explicitFolders = explicitFolders
6669
self.type = type
6770
self.optional = optional
6871
self.buildPhase = buildPhase
@@ -106,6 +109,7 @@ extension TargetSource: JSONObjectConvertible {
106109
headerVisibility = jsonDictionary.json(atKeyPath: "headerVisibility")
107110
excludes = jsonDictionary.json(atKeyPath: "excludes") ?? []
108111
includes = jsonDictionary.json(atKeyPath: "includes") ?? []
112+
explicitFolders = jsonDictionary.json(atKeyPath: "explicitFolders") ?? []
109113
type = jsonDictionary.json(atKeyPath: "type")
110114
optional = jsonDictionary.json(atKeyPath: "optional") ?? TargetSource.optionalDefault
111115

@@ -133,6 +137,7 @@ extension TargetSource: JSONEncodable {
133137
"compilerFlags": compilerFlags,
134138
"excludes": excludes,
135139
"includes": includes,
140+
"explicitFolders": explicitFolders,
136141
"name": name,
137142
"group": group,
138143
"headerVisibility": headerVisibility?.rawValue,

0 commit comments

Comments
 (0)