mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2026-03-18 20:02:25 +00:00
* Added support for dependency destination specification. (Resolves #1038) * More generic way covering more different dependency types. (#1038) * Added unit-test for each possible dependency combination. First test current embeding then the new one with custom copy spec. (#1038) * Review fixes. (#1038) * Minimized unit-test boiler-plate (#1038) * Update CHANGELOG.md Co-authored-by: Jakub Bednář <jakub.bednar@avast.com> Co-authored-by: Yonas Kolb <yonaskolb@users.noreply.github.com>
This commit is contained in:
co-authored by
Jakub Bednář
Yonas Kolb
parent
e2f062b6be
commit
d35d22f08b
@@ -2,6 +2,9 @@
|
||||
|
||||
## Next Version
|
||||
|
||||
### Added
|
||||
- Allow specifying a `copy` setting for each dependency. [#1038](https://github.com/yonaskolb/XcodeGen/pull/1039) @JakubBednar
|
||||
|
||||
## 2.24.0
|
||||
|
||||
### Added
|
||||
|
||||
@@ -432,6 +432,19 @@ A dependency can be one of a 6 types:
|
||||
- [ ] **weak**: **Bool** - Whether the `Weak` setting is applied when linking the framework. Defaults to false
|
||||
- [ ] **platformFilter**: **String** - This field is specific to Mac Catalyst. It corresponds to the "Platforms" dropdown in the Frameworks & Libraries section of Target settings in Xcode. Available options are: **iOS**, **macOS** and **all**. Defaults is **all**
|
||||
- [ ] **platforms**: **[[Platform](#platform)]** - List of platforms this dependency should apply to. Defaults to all applicable platforms.
|
||||
- **copy** - Copy Files Phase for this dependency. This only applies when `embed` is true. Must be specified as an object with the following fields:
|
||||
- [x] **destination**: **String** - Destination of the Copy Files phase. This can be one of the following values:
|
||||
- `absolutePath`
|
||||
- `productsDirectory`
|
||||
- `wrapper`
|
||||
- `executables`
|
||||
- `resources`
|
||||
- `javaResources`
|
||||
- `frameworks`
|
||||
- `sharedFrameworks`
|
||||
- `sharedSupport`
|
||||
- `plugins`
|
||||
- [ ] **subpath**: **String** - The path inside of the destination to copy the files.
|
||||
|
||||
**Implicit Framework options**:
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ public struct Dependency: Equatable {
|
||||
public var weakLink: Bool = weakLinkDefault
|
||||
public var platformFilter: PlatformFilter = platformFilterDefault
|
||||
public var platforms: Set<Platform>?
|
||||
public var copyPhase: BuildPhaseSpec.CopyFilesSettings?
|
||||
|
||||
public init(
|
||||
type: DependencyType,
|
||||
@@ -27,7 +28,8 @@ public struct Dependency: Equatable {
|
||||
implicit: Bool = implicitDefault,
|
||||
weakLink: Bool = weakLinkDefault,
|
||||
platformFilter: PlatformFilter = platformFilterDefault,
|
||||
platforms: Set<Platform>? = nil
|
||||
platforms: Set<Platform>? = nil,
|
||||
copyPhase: BuildPhaseSpec.CopyFilesSettings? = nil
|
||||
) {
|
||||
self.type = type
|
||||
self.reference = reference
|
||||
@@ -38,6 +40,7 @@ public struct Dependency: Equatable {
|
||||
self.weakLink = weakLink
|
||||
self.platformFilter = platformFilter
|
||||
self.platforms = platforms
|
||||
self.copyPhase = copyPhase
|
||||
}
|
||||
|
||||
public enum PlatformFilter: String, Equatable {
|
||||
@@ -135,6 +138,10 @@ extension Dependency: JSONObjectConvertible {
|
||||
if let platforms: [ProjectSpec.Platform] = jsonDictionary.json(atKeyPath: "platforms") {
|
||||
self.platforms = Set(platforms)
|
||||
}
|
||||
|
||||
if let object: JSONDictionary = jsonDictionary.json(atKeyPath: "copy") {
|
||||
copyPhase = try BuildPhaseSpec.CopyFilesSettings(jsonDictionary: object)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +151,8 @@ extension Dependency: JSONEncodable {
|
||||
"embed": embed,
|
||||
"codeSign": codeSign,
|
||||
"link": link,
|
||||
"platforms": platforms?.map(\.rawValue).sorted()
|
||||
"platforms": platforms?.map(\.rawValue).sorted(),
|
||||
"copy": copyPhase?.toJSONValue(),
|
||||
]
|
||||
|
||||
if removeHeaders != Dependency.removeHeadersDefault {
|
||||
|
||||
@@ -662,6 +662,7 @@ public class PBXProjGenerator {
|
||||
var dependencies: [PBXTargetDependency] = []
|
||||
var targetFrameworkBuildFiles: [PBXBuildFile] = []
|
||||
var frameworkBuildPaths = Set<String>()
|
||||
var customCopyDependenciesReferences: [PBXBuildFile] = []
|
||||
var copyFilesBuildPhasesFiles: [BuildPhaseSpec.CopyFilesSettings: [PBXBuildFile]] = [:]
|
||||
var copyFrameworksReferences: [PBXBuildFile] = []
|
||||
var copyResourcesReferences: [PBXBuildFile] = []
|
||||
@@ -689,7 +690,11 @@ public class PBXProjGenerator {
|
||||
if dependency.removeHeaders {
|
||||
embedAttributes.append("RemoveHeadersOnCopy")
|
||||
}
|
||||
return ["ATTRIBUTES": embedAttributes]
|
||||
var retval: [String:Any] = ["ATTRIBUTES": embedAttributes]
|
||||
if let copyPhase = dependency.copyPhase {
|
||||
retval["COPY_PHASE"] = copyPhase
|
||||
}
|
||||
return retval
|
||||
}
|
||||
|
||||
func getDependencyFrameworkSettings(dependency: Dependency) -> [String: Any]? {
|
||||
@@ -727,7 +732,10 @@ public class PBXProjGenerator {
|
||||
pbxBuildFile.platformFilter = platform
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
|
||||
if dependencyTarget.type.isExtension {
|
||||
if dependency.copyPhase != nil {
|
||||
// custom copy takes precedence
|
||||
customCopyDependenciesReferences.append(embedFile)
|
||||
} else if dependencyTarget.type.isExtension {
|
||||
// embed app extension
|
||||
extensions.append(embedFile)
|
||||
} else if dependencyTarget.type.isSystemExtension {
|
||||
@@ -807,7 +815,12 @@ public class PBXProjGenerator {
|
||||
let pbxBuildFile = PBXBuildFile(file: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
|
||||
if dependency.copyPhase != nil {
|
||||
customCopyDependenciesReferences.append(embedFile)
|
||||
} else {
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
}
|
||||
}
|
||||
case .sdk(let root):
|
||||
|
||||
@@ -858,7 +871,12 @@ public class PBXProjGenerator {
|
||||
let pbxBuildFile = PBXBuildFile(file: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
|
||||
if dependency.copyPhase != nil {
|
||||
customCopyDependenciesReferences.append(embedFile)
|
||||
} else {
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
}
|
||||
}
|
||||
|
||||
case .carthage(let findFrameworks, let linkType):
|
||||
@@ -923,7 +941,12 @@ public class PBXProjGenerator {
|
||||
settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
|
||||
if dependency.copyPhase != nil {
|
||||
customCopyDependenciesReferences.append(embedFile)
|
||||
} else {
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
}
|
||||
}
|
||||
case .bundle:
|
||||
// Static and dynamic libraries can't copy resources
|
||||
@@ -969,7 +992,11 @@ public class PBXProjGenerator {
|
||||
let embedFile = addObject(
|
||||
PBXBuildFile(file: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
|
||||
)
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
if dependency.copyPhase != nil {
|
||||
customCopyDependenciesReferences.append(embedFile)
|
||||
} else {
|
||||
copyFrameworksReferences.append(embedFile)
|
||||
}
|
||||
} else {
|
||||
carthageFrameworksToEmbed.append(dependency.reference)
|
||||
}
|
||||
@@ -1016,6 +1043,19 @@ public class PBXProjGenerator {
|
||||
)
|
||||
}
|
||||
|
||||
func splitCopyDepsByDestination(_ references: [PBXBuildFile]) -> [BuildPhaseSpec.CopyFilesSettings : [PBXBuildFile]] {
|
||||
|
||||
var retval = [BuildPhaseSpec.CopyFilesSettings : [PBXBuildFile]]()
|
||||
for reference in references {
|
||||
|
||||
guard let key = reference.settings?["COPY_PHASE"] as? BuildPhaseSpec.CopyFilesSettings else { continue }
|
||||
var filesWithSameDestination = retval[key] ?? [PBXBuildFile]()
|
||||
filesWithSameDestination.append(reference)
|
||||
retval[key] = filesWithSameDestination
|
||||
}
|
||||
return retval
|
||||
}
|
||||
|
||||
copyFilesBuildPhasesFiles.merge(getBuildFilesForCopyFilesPhases()) { $0 + $1 }
|
||||
|
||||
buildPhases += try target.preBuildScripts.map { try generateBuildScript(targetName: target.name, buildScript: $0) }
|
||||
@@ -1154,6 +1194,21 @@ public class PBXProjGenerator {
|
||||
buildPhases.append(copyFilesPhase)
|
||||
}
|
||||
|
||||
if !customCopyDependenciesReferences.isEmpty {
|
||||
|
||||
let splitted = splitCopyDepsByDestination(customCopyDependenciesReferences)
|
||||
for (phase, references) in splitted {
|
||||
|
||||
guard let destination = phase.destination.destination else { continue }
|
||||
|
||||
let copyFilesPhase = addObject(
|
||||
getPBXCopyFilesBuildPhase(dstSubfolderSpec: destination, dstPath:phase.subpath, name: "Embed Dependencies", files: references)
|
||||
)
|
||||
|
||||
buildPhases.append(copyFilesPhase)
|
||||
}
|
||||
}
|
||||
|
||||
if !copyWatchReferences.isEmpty {
|
||||
|
||||
let copyFilesPhase = addObject(
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
7F658343A505B824321E086B /* Headers in Headers */ = {isa = PBXBuildFile; fileRef = 2E1E747C7BC434ADB80CC269 /* Headers */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
803B7CE086CFBA409F9D1ED7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 108BB29172D27BE3BD1E7F35 /* Assets.xcassets */; };
|
||||
818D448D4DDD6649B5B26098 /* example.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 28360ECA4D727FAA58557A81 /* example.mp4 */; settings = {ASSET_TAGS = (tag1, tag2, ); }; };
|
||||
81DFAB3A7633CE97929B9B2A /* Framework.framework in Embed Dependencies */ = {isa = PBXBuildFile; fileRef = 41FC82ED1C4C3B7B3D7B2FB7 /* Framework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
8267B75289E9D6C7B38FC426 /* DriverKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0A428E67153BB40184F37BE /* DriverKit.framework */; };
|
||||
87927928A8A3460166ACB819 /* SwiftFileInDotPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F430AABE04B7499B458D9DB /* SwiftFileInDotPath.swift */; settings = {COMPILER_FLAGS = "-Werror"; }; };
|
||||
8C941A6EF08069CB3CB88FC1 /* Result.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0C5AC2545AE4D4F7F44E2E9B /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@@ -142,7 +143,6 @@
|
||||
BAA1C1E3828F5D43546AF997 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BB1B49A91B892152D68ED76 /* libc++.tbd */; };
|
||||
BB06A57E259D0D2A001EA21F /* Result.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0C5AC2545AE4D4F7F44E2E9B /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
BD1419893577E6CEDF8CBA83 /* Result.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0C5AC2545AE4D4F7F44E2E9B /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
BD95416F2005199F6B3572CF /* Framework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 41FC82ED1C4C3B7B3D7B2FB7 /* Framework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
BFCCC56337A5D9D513C1C791 /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = F2950763C4C568CC85021D18 /* module.modulemap */; };
|
||||
C093BF20B99FE892D0F06B2D /* libEndpointSecurity.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BC75409252FF15F540FBB7B /* libEndpointSecurity.tbd */; };
|
||||
C3672B561F456794151C047C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4C3FE6B986506724DAB5D0F /* ViewController.swift */; };
|
||||
@@ -578,6 +578,17 @@
|
||||
name = "Embed App Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CF6B94E7B2D2312582A526F5 /* Embed Dependencies */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = test;
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
81DFAB3A7633CE97929B9B2A /* Framework.framework in Embed Dependencies */,
|
||||
);
|
||||
name = "Embed Dependencies";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DE875E9A37F7CB9C347AEFA0 /* Embed System Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -607,7 +618,6 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
BD95416F2005199F6B3572CF /* Framework.framework in Embed Frameworks */,
|
||||
A7D1A9942302569A9515696A /* Result.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
@@ -1529,6 +1539,7 @@
|
||||
A6E1C88C073F8CC6B5B072B6 /* Frameworks */,
|
||||
DE875E9A37F7CB9C347AEFA0 /* Embed System Extensions */,
|
||||
F8CDEFED6ED131A09041F995 /* Embed Frameworks */,
|
||||
CF6B94E7B2D2312582A526F5 /* Embed Dependencies */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
||||
@@ -57,6 +57,9 @@ targets:
|
||||
optional: true
|
||||
dependencies:
|
||||
- target: Framework_macOS
|
||||
copy:
|
||||
destination: plugins
|
||||
subpath: "test"
|
||||
- target: XPC Service
|
||||
- target: NetworkSystemExtension
|
||||
- target: EndpointSecuritySystemExtension
|
||||
|
||||
@@ -398,7 +398,8 @@ class ProjectSpecTests: XCTestCase {
|
||||
codeSign: true,
|
||||
link: true,
|
||||
implicit: true,
|
||||
weakLink: true)],
|
||||
weakLink: true,
|
||||
copyPhase: BuildPhaseSpec.CopyFilesSettings(destination: .frameworks, subpath: "example", phaseOrder: .postCompile))],
|
||||
info: Plist(path: "info.plist", attributes: ["foo": "bar"]),
|
||||
entitlements: Plist(path: "entitlements.plist", attributes: ["foo": "bar"]),
|
||||
transitivelyLinkDependencies: true,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user