Skip to content

Commit

Permalink
Add support for adding build tool plugins to targets (yonaskolb#1374)
Browse files Browse the repository at this point in the history
* Add support for adding build tool plugins to targets

* Added Plugin validation

* Added some tests

* Limited the minimum version to 5.7 Swift

* Update .gitignore

Co-authored-by: freddi(Yuki Aki) <[email protected]>

* Update CHANGELOG.md

Co-authored-by: freddi(Yuki Aki) <[email protected]>

* Update CHANGELOG.md

Co-authored-by: freddi(Yuki Aki) <[email protected]>

* Update Docs/ProjectSpec.md

Co-authored-by: freddi(Yuki Aki) <[email protected]>

* Added a fixture for testing plugins

* Update CHANGELOG.md

* Installed the release version of XcodeProj

---------

Co-authored-by: freddi(Yuki Aki) <[email protected]>
  • Loading branch information
BarredEwe and freddi-kit committed Aug 16, 2023
1 parent 2ef94c9 commit d8d5457
Show file tree
Hide file tree
Showing 14 changed files with 323 additions and 96 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Fixed source file `includes` not working when no paths were found #1337 @shnhrrsn

### Added

- Added support for adding `Build Tool Plug-ins` to targets #1374 @BarredEwe

## 2.36.1

### Fixed
Expand Down
33 changes: 33 additions & 0 deletions Docs/ProjectSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ You can also use environment variables in your configuration file, by using `${S
- [Dependency](#dependency)
- [Config Files](#config-files)
- [Plist](#plist)
- [Build Tool Plug-ins](#build-tool-plug-ins)
- [Build Script](#build-script)
- [Build Rule](#build-rule)
- [Target Scheme](#target-scheme)
Expand Down Expand Up @@ -381,6 +382,7 @@ Settings are merged in the following order: `groups`, `base`, `configs` (simple
- [ ] **directlyEmbedCarthageDependencies**: **Bool** - If this is `true` Carthage framework dependencies will be embedded using an `Embed Frameworks` build phase instead of the `copy-frameworks` script. Defaults to `true` for all targets except iOS/tvOS/watchOS Applications.
- [ ] **requiresObjCLinking**: **Bool** - If this is `true` any targets that link to this target will have `-ObjC` added to their `OTHER_LDFLAGS`. This is required if a static library has any categories or extensions on Objective-C code. See [this guide](https://pewpewthespells.com/blog/objc_linker_flags.html#objc) for more details. Defaults to `true` if `type` is `library.static`. If you are 100% sure you don't have categories or extensions on Objective-C code (pure Swift with no use of Foundation/UIKit) you can set this to `false`, otherwise it's best to leave it alone.
- [ ] **onlyCopyFilesOnInstall**: **Bool** – If this is `true`, the `Embed Frameworks` and `Embed App Extensions` (if available) build phases will have the "Copy only when installing" chekbox checked. Defaults to `false`.
- [ ] **buildToolPlugins**: **[[Build Tool Plug-ins](#build-tool-plug-ins)]** - Commands for the build system that run automatically *during* the build.
- [ ] **preBuildScripts**: **[[Build Script](#build-script)]** - Build scripts that run *before* any other build phases
- [ ] **postCompileScripts**: **[[Build Script](#build-script)]** - Build scripts that run after the Compile Sources phase
- [ ] **postBuildScripts**: **[[Build Script](#build-script)]** - Build scripts that run *after* any other build phases
Expand Down Expand Up @@ -695,6 +697,36 @@ targets:
com.apple.security.application-groups: group.com.app
```

### Build Tool Plug-ins

To add `Build Tool Plug-ins`, you need to add information about plugins to [Target](#target):

- **buildToolPlugins**: List of plugins to connect to the target

Each plugin includes information:

- [x] **plugin**: **String** - plugin name
- [x] **package**: **String** - the name of the package that contains the plugin

Сonnect the plugin to the desired target:

```yaml
targets:
App:
buildToolPlugins:
- plugin: MyPlugin
package: MyPackage
```

Don't forget to add a package containing the plugin we need:

```yaml
packages:
MyPackage:
url: https://github.com/MyPackage
from: 1.3.0
```

### Build Script

Run script build phases can be added at 3 different points in the build:
Expand Down Expand Up @@ -854,6 +886,7 @@ This is used to override settings or run build scripts in specific targets
- [x] **targets**: **[String]** - The list of target names to include as target dependencies
- [ ] **configFiles**: **[Config Files](#config-files)** - `.xcconfig` files per config
- [ ] **settings**: **[Settings](#settings)** - Target specific build settings.
- [ ] **buildToolPlugins**: **[[Build Tool Plug-ins](#build-tool-plug-ins)]** - Commands for the build system that run automatically *during* the build
- [ ] **buildScripts**: **[[Build Script](#build-script)]** - Build scripts to run
- [ ] **scheme**: **[Target Scheme](#target-scheme)** - Generated scheme
- [ ] **attributes**: **[String: Any]** - This sets values in the project `TargetAttributes`. It is merged with `attributes` from the project and anything automatically added by XcodeGen, with any duplicate values being override by values specified here
Expand Down
17 changes: 17 additions & 0 deletions Docs/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,20 @@ targets:
dependencies:
- framework: Vendor/MyFramework.framework
```

# Build Tool Plug-ins
XCodeGen supports working with [Swift Package Plug-ins](https://github.com/apple/swift-package-manager/blob/main/Documentation/Plugins.md#using-a-package-plugin).

To use plugins, you need to specify in your target which plugin you want to connect, and don't forget to connect the package to target.

```yaml
packages:
Prefire:
url: https://github.com/BarredEwe/Prefire
from: 1.3.0
targets:
App:
buildToolPlugins:
- plugin: PrefirePlaybookPlugin
package: Prefire
```
186 changes: 92 additions & 94 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,97 +1,95 @@
{
"object": {
"pins": [
{
"package": "AEXML",
"repositoryURL": "https://github.com/tadija/AEXML.git",
"state": {
"branch": null,
"revision": "38f7d00b23ecd891e1ee656fa6aeebd6ba04ecc3",
"version": "4.6.1"
}
},
{
"package": "GraphViz",
"repositoryURL": "https://github.com/SwiftDocOrg/GraphViz.git",
"state": {
"branch": null,
"revision": "70bebcf4597b9ce33e19816d6bbd4ba9b7bdf038",
"version": "0.2.0"
}
},
{
"package": "JSONUtilities",
"repositoryURL": "https://github.com/yonaskolb/JSONUtilities.git",
"state": {
"branch": null,
"revision": "128d2ffc22467f69569ef8ff971683e2393191a0",
"version": "4.2.0"
}
},
{
"package": "PathKit",
"repositoryURL": "https://github.com/kylef/PathKit.git",
"state": {
"branch": null,
"revision": "3bfd2737b700b9a36565a8c94f4ad2b050a5e574",
"version": "1.0.1"
}
},
{
"package": "Rainbow",
"repositoryURL": "https://github.com/onevcat/Rainbow.git",
"state": {
"branch": null,
"revision": "626c3d4b6b55354b4af3aa309f998fae9b31a3d9",
"version": "3.2.0"
}
},
{
"package": "Spectre",
"repositoryURL": "https://github.com/kylef/Spectre.git",
"state": {
"branch": null,
"revision": "26cc5e9ae0947092c7139ef7ba612e34646086c7",
"version": "0.10.1"
}
},
{
"package": "SwiftCLI",
"repositoryURL": "https://github.com/jakeheis/SwiftCLI.git",
"state": {
"branch": null,
"revision": "2e949055d9797c1a6bddcda0e58dada16cc8e970",
"version": "6.0.3"
}
},
{
"package": "Version",
"repositoryURL": "https://github.com/mxcl/Version",
"state": {
"branch": null,
"revision": "a94b48f36763c05629fc102837398505032dead9",
"version": "2.0.0"
}
},
{
"package": "XcodeProj",
"repositoryURL": "https://github.com/tuist/XcodeProj.git",
"state": {
"branch": null,
"revision": "c4d5f9d7f789dd944222be95938810947561e559",
"version": "8.12.0"
}
},
{
"package": "Yams",
"repositoryURL": "https://github.com/jpsim/Yams.git",
"state": {
"branch": null,
"revision": "01835dc202670b5bb90d07f3eae41867e9ed29f6",
"version": "5.0.1"
}
"pins" : [
{
"identity" : "aexml",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tadija/AEXML.git",
"state" : {
"revision" : "38f7d00b23ecd891e1ee656fa6aeebd6ba04ecc3",
"version" : "4.6.1"
}
]
},
"version": 1
},
{
"identity" : "graphviz",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SwiftDocOrg/GraphViz.git",
"state" : {
"revision" : "70bebcf4597b9ce33e19816d6bbd4ba9b7bdf038",
"version" : "0.2.0"
}
},
{
"identity" : "jsonutilities",
"kind" : "remoteSourceControl",
"location" : "https://github.com/yonaskolb/JSONUtilities.git",
"state" : {
"revision" : "128d2ffc22467f69569ef8ff971683e2393191a0",
"version" : "4.2.0"
}
},
{
"identity" : "pathkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kylef/PathKit.git",
"state" : {
"revision" : "3bfd2737b700b9a36565a8c94f4ad2b050a5e574",
"version" : "1.0.1"
}
},
{
"identity" : "rainbow",
"kind" : "remoteSourceControl",
"location" : "https://github.com/onevcat/Rainbow.git",
"state" : {
"revision" : "626c3d4b6b55354b4af3aa309f998fae9b31a3d9",
"version" : "3.2.0"
}
},
{
"identity" : "spectre",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kylef/Spectre.git",
"state" : {
"revision" : "26cc5e9ae0947092c7139ef7ba612e34646086c7",
"version" : "0.10.1"
}
},
{
"identity" : "swiftcli",
"kind" : "remoteSourceControl",
"location" : "https://github.com/jakeheis/SwiftCLI.git",
"state" : {
"revision" : "2e949055d9797c1a6bddcda0e58dada16cc8e970",
"version" : "6.0.3"
}
},
{
"identity" : "version",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mxcl/Version",
"state" : {
"revision" : "a94b48f36763c05629fc102837398505032dead9",
"version" : "2.0.0"
}
},
{
"identity" : "xcodeproj",
"kind" : "remoteSourceControl",
"location" : "https://github.com/tuist/XcodeProj.git",
"state" : {
"revision" : "6e60fb55271c80f83a186c9b1b4982fd991cfc0a",
"version" : "8.13.0"
}
},
{
"identity" : "yams",
"kind" : "remoteSourceControl",
"location" : "https://github.com/jpsim/Yams.git",
"state" : {
"revision" : "01835dc202670b5bb90d07f3eae41867e9ed29f6",
"version" : "5.0.1"
}
}
],
"version" : 2
}
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let package = Package(
.package(url: "https://github.com/yonaskolb/JSONUtilities.git", from: "4.2.0"),
.package(url: "https://github.com/kylef/Spectre.git", from: "0.9.2"),
.package(url: "https://github.com/onevcat/Rainbow.git", from: "3.0.0"),
.package(url: "https://github.com/tuist/XcodeProj.git", from: "8.12.0"),
.package(url: "https://github.com/tuist/XcodeProj.git", from: "8.13.0"),
.package(url: "https://github.com/jakeheis/SwiftCLI.git", from: "6.0.3"),
.package(url: "https://github.com/mxcl/Version", from: "2.0.0"),
.package(url: "https://github.com/SwiftDocOrg/GraphViz.git", exact: "0.2.0"),
Expand Down
58 changes: 58 additions & 0 deletions Sources/ProjectSpec/BuildToolPlugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Foundation
import JSONUtilities

/// Specifies the use of a plug-in product in a target.
public struct BuildToolPlugin: Equatable {

/// The name of the plug-in target.
public var plugin: String
/// The name of the package that defines the plug-in target.
public var package: String

public init(
plugin: String,
package: String
) {
self.plugin = plugin
self.package = package
}
}

extension BuildToolPlugin: JSONObjectConvertible {

public init(jsonDictionary: JSONDictionary) throws {
if let plugin: String = jsonDictionary.json(atKeyPath: "plugin") {
self.plugin = plugin
} else {
throw SpecParsingError.invalidDependency(jsonDictionary)
}

if let package: String = jsonDictionary.json(atKeyPath: "package") {
self.package = package
} else {
throw SpecParsingError.invalidDependency(jsonDictionary)
}
}
}

extension BuildToolPlugin {
public var uniqueID: String {
return "\(plugin)/\(package)"
}
}

extension BuildToolPlugin: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(plugin)
hasher.combine(package)
}
}

extension BuildToolPlugin: JSONEncodable {
public func toJSONValue() -> Any {
[
"plugin": plugin,
"package": package
]
}
}
6 changes: 6 additions & 0 deletions Sources/ProjectSpec/SpecValidation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ extension Project {
errors.append(.invalidTargetSource(target: target.name, source: sourcePath.string))
}
}

for buildToolPlugin in target.buildToolPlugins {
if packages[buildToolPlugin.package] == nil {
errors.append(.invalidPluginPackageReference(plugin: buildToolPlugin.plugin, package: buildToolPlugin.package))
}
}
}

for projectReference in projectReferences {
Expand Down
3 changes: 3 additions & 0 deletions Sources/ProjectSpec/SpecValidationError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public struct SpecValidationError: Error, CustomStringConvertible {
case invalidTestPlan(TestPlan)
case multipleDefaultTestPlans
case duplicateDependencies(target: String, dependencyReference: String)
case invalidPluginPackageReference(plugin: String, package: String)

public var description: String {
switch self {
Expand Down Expand Up @@ -91,6 +92,8 @@ public struct SpecValidationError: Error, CustomStringConvertible {
return "Your test plans contain more than one default test plan"
case let .duplicateDependencies(target, dependencyReference):
return "Target \(target.quoted) has the dependency \(dependencyReference.quoted) multiple times"
case let .invalidPluginPackageReference(plugin, package):
return "Plugin \(plugin) has invalide package reference \(package)"
}
}
}
Expand Down
Loading

0 comments on commit d8d5457

Please sign in to comment.