Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log

## Next

### Added
- Added `options.createLocalPackageGroups` (default `true`). When set to `false`, local Swift packages are referenced only via `XCLocalSwiftPackageReference` (shown under "Package Dependencies") without an additional folder/group in the navigator. #<PR> @vahanbabayan-bloom

## 2.46.0

### Added
Expand Down
3 changes: 2 additions & 1 deletion Docs/ProjectSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ Note that target names can also be changed by adding a `name` property to a targ
- [ ] **generateEmptyDirectories**: **Bool** - If this is `true` then empty directories will be added to project too else will be missed. Defaults to `false`.
- [ ] **findCarthageFrameworks**: **Bool** - When this is set to `true`, all the individual frameworks for Carthage framework dependencies will automatically be found. This property can be overridden individually for each carthage dependency - for more details see See **findFrameworks** in the [Dependency](#dependency) section. Defaults to `false`.
- [ ] **localPackagesGroup**: **String** - The group name that local packages are put into. This defaults to `Packages`. Use `""` to specify the project root.
- [ ] **createLocalPackageGroups**: **Bool** - Whether local packages get a browsable folder/group in the project navigator in addition to the Package Dependencies entry. Defaults to `true`. Set to `false` to show local packages only under "Package Dependencies" (matching Xcode's "Add Local…" behavior).
- [ ] **fileTypes**: **[String: [FileType](#filetype)]** - A list of default file options for specific file extensions across the project. Values in [Sources](#sources) will overwrite these settings.
- [ ] **preGenCommand**: **String** - A bash command to run before the project has been generated. If the project isn't generated due to no changes when using the cache then this won't run. This is useful for running things like generating resources files before the project is regenerated.
- [ ] **postGenCommand**: **String** - A bash command to run after the project has been generated. If the project isn't generated due to no changes when using the cache then this won't run. This is useful for running things like `pod install` only if the project is actually regenerated.
Expand Down Expand Up @@ -1261,7 +1262,7 @@ Swift packages are defined at a project level, and then linked to individual tar
### Local Package

- [x] **path**: **String** - the path to the package in local. The path must be directory with a `Package.swift`.
- [ ] **group** : **String**- Optional path that specifies the location where the package will live in your xcode project. Use `""` to specify the project root.
- [ ] **group** : **String**- Optional path that specifies the location where the package will live in your xcode project. Use `""` to specify the project root. To not create any group for local packages, set [Options](#options).createLocalPackageGroups to `false`.
- [ ] **excludeFromProject** : **String**- Optional flag to exclude the package from the generated project (useful if the package is already added via xcworkspace and the project is not intended for standalone use), defaults to `false`
- [ ] **traits**: **[String]** - Optional Swift package traits to enable for this package reference. Use the top-level `packages` mapping because the legacy `localPackages` syntax cannot specify traits.

Expand Down
8 changes: 8 additions & 0 deletions Sources/ProjectSpec/SpecOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public struct SpecOptions: Equatable {
public static let generateEmptyDirectoriesDefault = false
public static let findCarthageFrameworksDefault = false
public static let useBaseInternationalizationDefault = true
public static let createLocalPackageGroupsDefault = true
public static let schemePathPrefixDefault = "../../"

public var minimumXcodeGenVersion: Version?
Expand All @@ -34,6 +35,7 @@ public struct SpecOptions: Equatable {
public var generateEmptyDirectories: Bool
public var findCarthageFrameworks: Bool
public var localPackagesGroup: String?
public var createLocalPackageGroups: Bool
public var preGenCommand: String?
public var postGenCommand: String?
public var useBaseInternationalization: Bool
Expand Down Expand Up @@ -100,6 +102,7 @@ public struct SpecOptions: Equatable {
generateEmptyDirectories: Bool = generateEmptyDirectoriesDefault,
findCarthageFrameworks: Bool = findCarthageFrameworksDefault,
localPackagesGroup: String? = nil,
createLocalPackageGroups: Bool = createLocalPackageGroupsDefault,
preGenCommand: String? = nil,
postGenCommand: String? = nil,
useBaseInternationalization: Bool = useBaseInternationalizationDefault,
Expand Down Expand Up @@ -128,6 +131,7 @@ public struct SpecOptions: Equatable {
self.generateEmptyDirectories = generateEmptyDirectories
self.findCarthageFrameworks = findCarthageFrameworks
self.localPackagesGroup = localPackagesGroup
self.createLocalPackageGroups = createLocalPackageGroups
self.preGenCommand = preGenCommand
self.postGenCommand = postGenCommand
self.useBaseInternationalization = useBaseInternationalization
Expand Down Expand Up @@ -163,6 +167,7 @@ extension SpecOptions: JSONObjectConvertible {
generateEmptyDirectories = jsonDictionary.json(atKeyPath: "generateEmptyDirectories") ?? SpecOptions.generateEmptyDirectoriesDefault
findCarthageFrameworks = jsonDictionary.json(atKeyPath: "findCarthageFrameworks") ?? SpecOptions.findCarthageFrameworksDefault
localPackagesGroup = jsonDictionary.json(atKeyPath: "localPackagesGroup")
createLocalPackageGroups = jsonDictionary.json(atKeyPath: "createLocalPackageGroups") ?? SpecOptions.createLocalPackageGroupsDefault
preGenCommand = jsonDictionary.json(atKeyPath: "preGenCommand")
postGenCommand = jsonDictionary.json(atKeyPath: "postGenCommand")
useBaseInternationalization = jsonDictionary.json(atKeyPath: "useBaseInternationalization") ?? SpecOptions.useBaseInternationalizationDefault
Expand Down Expand Up @@ -218,6 +223,9 @@ extension SpecOptions: JSONEncodable {
if schemePathPrefix != SpecOptions.schemePathPrefixDefault {
dict["schemePathPrefix"] = schemePathPrefix
}
if createLocalPackageGroups != SpecOptions.createLocalPackageGroupsDefault {
dict["createLocalPackageGroups"] = createLocalPackageGroups
}

return dict
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/XcodeGenKit/PBXProjGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ public class PBXProjGenerator {

if !excludeFromProject {
addObject(packageReference)
try sourceGenerator.createLocalPackage(path: Path(path), group: group.map { Path($0) })
if project.options.createLocalPackageGroups {
try sourceGenerator.createLocalPackage(path: Path(path), group: group.map { Path($0) })
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion Tests/ProjectSpecTests/ProjectSpecTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,8 @@ class ProjectSpecTests: XCTestCase {
transitivelyLinkDependencies: true,
groupSortPosition: .top,
generateEmptyDirectories: true,
findCarthageFrameworks: false),
findCarthageFrameworks: false,
createLocalPackageGroups: false),
fileGroups: ["foo", "bar"],
configFiles: ["configFiles": "bar"],
attributes: ["attributes": "bar"])
Expand Down
12 changes: 12 additions & 0 deletions Tests/ProjectSpecTests/SpecLoadingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,18 @@ class SpecLoadingTests: XCTestCase {
try expect(parsedSpec) == expected
}

$0.it("parses createLocalPackageGroups option") {
let defaultSpec = try getProjectSpec(["options": [String: Any]()])
try expect(defaultSpec.options.createLocalPackageGroups) == true

let expected = Project(name: "test", options: .init(createLocalPackageGroups: false))
let dictionary: [String: Any] = ["options": [
"createLocalPackageGroups": false,
]]
let parsedSpec = try getProjectSpec(dictionary)
try expect(parsedSpec) == expected
}

$0.it("parses packages") {
let project = Project(name: "spm", packages: [
"package1": .remote(url: "package.git", versionRequirement: .exact("1.2.2"), traits: ["FeatureA", "FeatureB"]),
Expand Down
43 changes: 43 additions & 0 deletions Tests/XcodeGenKitTests/PBXProjGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,49 @@ class PBXProjGeneratorTests: XCTestCase {
try expect(packages) == ["FeatureA", "FeatureB", "Common"]
}

$0.it("doesn't create groups for local packages when createLocalPackageGroups is disabled") {
var options = SpecOptions()
options.createLocalPackageGroups = false

let directories = """
Sources:
- file.swift
Packages:
- Common:
- Package.swift
- FeatureA:
- Package.swift
- FeatureB:
- Package.swift
"""
try createDirectories(directories)

let target = Target(name: "Test", type: .application, platform: .iOS, sources: ["Sources"])
let project = Project(
basePath: directoryPath,
name: "Test",
targets: [target],
packages: [
"Common": .local(path: "Packages/Common", group: nil, excludeFromProject: false),
"FeatureA": .local(path: "Packages/FeatureA", group: nil, excludeFromProject: false),
"FeatureB": .local(path: "Packages/FeatureB", group: nil, excludeFromProject: false),
],
options: options
)

let pbxProj = try project.generatePbxProj()
let group = try pbxProj.getMainGroup()

let mainGroups = group.children.map { $0.nameOrPath }
try expect(mainGroups.contains("Packages")) == false

let folderReferences = pbxProj.fileReferences.filter { $0.lastKnownFileType == "folder" }
try expect(folderReferences.isEmpty) == true

let localPackages = pbxProj.rootObject?.localPackages ?? []
try expect(localPackages.map(\.relativePath).sorted()) == ["Packages/Common", "Packages/FeatureA", "Packages/FeatureB"]
}

$0.it("sorts synced folders alongside groups") {
var options = SpecOptions()
options.groupSortPosition = .top
Expand Down
Loading