Added support for dependency destination specification. (Resolves #1038) (#1039)

* 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:
Jakub Bednar
2021-07-15 12:10:34 +10:00
committed by GitHub
co-authored by Jakub Bednář Yonas Kolb
parent e2f062b6be
commit d35d22f08b
8 changed files with 1522 additions and 11 deletions
+3
View File
@@ -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
+13
View File
@@ -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**:
+10 -2
View File
@@ -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 {
+61 -6
View File
@@ -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 = (
);
+3
View File
@@ -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