Merge pull request #411 from alvarhansen/weak-link

Add framework weak linking setting
This commit is contained in:
Yonas Kolb
2018-10-02 20:47:50 +10:00
committed by GitHub
8 changed files with 810 additions and 14 deletions
+6
View File
@@ -1,5 +1,11 @@
# Change Log
## Master
#### Added
- Added `weak` Weak linking setting for dependencies [411](https://github.com/yonaskolb/XcodeGen/pull/411) @alvarhansen
## 1.11.2
If XcodeGen is compiled with Swift 4.2, then UUID's in the generated project will not be deterministic. This will be fixed in an upcoming release with an update to xcodeproj 6.0
+1
View File
@@ -328,6 +328,7 @@ These only applied to `target` and `framework` dependencies.
- [ ] **link**: **Bool** - Whether to link the dependency. Defaults to `true` depending on the type of the dependency and the type of the target (e.g. static libraries will only link to executables by default).
- [ ] **codeSign**: **Bool** - Whether the `codeSignOnCopy` setting is applied when embedding framework. Defaults to true
- [ ] **removeHeaders**: **Bool** - Whether the `removeHeadersOnCopy` setting is applied when embedding the framework. Defaults to true
- [ ] **weak**: **Bool** - Whether the `Weak` setting is applied when linking the framework. Defaults to false
**Implicit Framework options**:
+7 -1
View File
@@ -11,6 +11,7 @@ public struct Dependency: Equatable {
public var removeHeaders: Bool = true
public var link: Bool?
public var implicit: Bool = false
public var weakLink: Bool = false
public init(
type: DependencyType,
@@ -18,7 +19,8 @@ public struct Dependency: Equatable {
embed: Bool? = nil,
codeSign: Bool? = nil,
link: Bool? = nil,
implicit: Bool = false
implicit: Bool = false,
weakLink: Bool = false
) {
self.type = type
self.reference = reference
@@ -26,6 +28,7 @@ public struct Dependency: Equatable {
self.codeSign = codeSign
self.link = link
self.implicit = implicit
self.weakLink = weakLink
}
public enum DependencyType {
@@ -61,5 +64,8 @@ extension Dependency: JSONObjectConvertible {
if let bool: Bool = jsonDictionary.json(atKeyPath: "implicit") {
implicit = bool
}
if let bool: Bool = jsonDictionary.json(atKeyPath: "weak") {
weakLink = bool
}
}
}
+20 -3
View File
@@ -459,6 +459,14 @@ public class PBXProjGenerator {
return ["ATTRIBUTES": embedAttributes]
}
func getDependencyFrameworkSettings(dependency: Dependency) -> [String: Any]? {
var linkingAttributes: [String] = []
if dependency.weakLink {
linkingAttributes.append("Weak")
}
return !linkingAttributes.isEmpty ? ["ATTRIBUTES": linkingAttributes] : nil
}
for dependency in targetDependencies {
let embed = dependency.embed ?? target.shouldEmbedDependencies
@@ -482,7 +490,10 @@ public class PBXProjGenerator {
let dependencyBuildFile = targetBuildFiles[dependencyTargetName]!
let buildFile = createObject(
id: dependencyBuildFile.reference + target.name,
PBXBuildFile(fileRef: dependencyBuildFile.object.fileRef!)
PBXBuildFile(
fileRef: dependencyBuildFile.object.fileRef!,
settings: getDependencyFrameworkSettings(dependency: dependency)
)
)
targetFrameworkBuildFiles.append(buildFile.reference)
@@ -538,7 +549,10 @@ public class PBXProjGenerator {
let buildFile = createObject(
id: "framework" + fileReference + target.name,
PBXBuildFile(fileRef: fileReference)
PBXBuildFile(
fileRef: fileReference,
settings: getDependencyFrameworkSettings(dependency: dependency)
)
)
targetFrameworkBuildFiles.append(buildFile.reference)
@@ -569,7 +583,10 @@ public class PBXProjGenerator {
let buildFile = createObject(
id: "carthage" + fileReference + target.name,
PBXBuildFile(fileRef: fileReference)
PBXBuildFile(
fileRef: fileReference,
settings: getDependencyFrameworkSettings(dependency: dependency)
)
)
carthageFrameworksByPlatform[target.platform.carthageDirectoryName, default: []].insert(fileReference)
File diff suppressed because it is too large Load Diff
+11
View File
@@ -73,6 +73,8 @@ targets:
- target: Framework_iOS
- target: StaticLibrary_ObjC_iOS
- carthage: Result
- target: Framework2_iOS
weak: true
- target: App_watchOS
- target: iMessageApp
- framework: Vendor/SomeFramework.framework
@@ -160,6 +162,15 @@ targets:
dependencies:
- carthage: Result
- target: StaticLibrary_ObjC_$platform
Framework2:
type: framework
platform: [iOS, tvOS, watchOS, macOS]
sources:
- path: Framework
excludes:
- "*.xcodeproj"
App_iOS_Tests:
type: bundle.unit-test
platform: iOS
@@ -21,6 +21,12 @@ fileprivate let framework = Target(
settings: Settings(buildSettings: ["SETTING_2": "VALUE"])
)
fileprivate let optionalFramework = Target(
name: "MyOptionalFramework",
type: .framework,
platform: .iOS
)
fileprivate let uiTest = Target(
name: "MyAppUITests",
type: .uiTestBundle,
@@ -29,7 +35,7 @@ fileprivate let uiTest = Target(
dependencies: [Dependency(type: .target, reference: "MyApp")]
)
fileprivate let targets = [app, framework, uiTest]
fileprivate let targets = [app, framework, optionalFramework, uiTest]
class ProjectGeneratorTests: XCTestCase {
@@ -230,10 +236,11 @@ class ProjectGeneratorTests: XCTestCase {
$0.it("generates targets") {
let pbxProject = try project.generatePbxProj()
let nativeTargets = pbxProject.objects.nativeTargets.referenceValues
try expect(nativeTargets.count) == 3
try expect(nativeTargets.count) == 4
try expect(nativeTargets.contains { $0.name == app.name }).beTrue()
try expect(nativeTargets.contains { $0.name == framework.name }).beTrue()
try expect(nativeTargets.contains { $0.name == uiTest.name }).beTrue()
try expect(nativeTargets.contains { $0.name == optionalFramework.name }).beTrue()
}
$0.it("generates target attributes") {
@@ -243,7 +250,7 @@ class ProjectGeneratorTests: XCTestCase {
var testTargetWithAttributes = uiTest
testTargetWithAttributes.settings.buildSettings["CODE_SIGN_STYLE"] = "Manual"
let project = Project(basePath: "", name: "test", targets: [appTargetWithAttributes, framework, testTargetWithAttributes])
let project = Project(basePath: "", name: "test", targets: [appTargetWithAttributes, framework, optionalFramework, testTargetWithAttributes])
let pbxProject = try project.generatePbxProj()
guard let targetAttributes = pbxProject.objects.projects.referenceValues.first?.attributes["TargetAttributes"] as? [String: [String: Any]] else {
@@ -804,6 +811,35 @@ class ProjectGeneratorTests: XCTestCase {
try expect(second.outputFiles) == []
try expect(second.outputFilesCompilerFlags) == []
}
$0.it("generates dependency build file settings") {
let app = Target(
name: "MyApp",
type: .application,
platform: .iOS,
dependencies: [
Dependency(type: .target, reference: "MyFramework"),
Dependency(type: .target, reference: "MyOptionalFramework", weakLink: true)
]
)
let project = Project(basePath: "", name: "test", targets: [app, framework, optionalFramework, uiTest])
let pbxProject = try project.generatePbxProj()
guard let nativeTarget = pbxProject.objects.nativeTargets.referenceValues.first(where: { $0.name == app.name }) else {
throw failure("PBXNativeTarget for \(app.name) not found")
}
let buildPhases = nativeTarget.buildPhases
let frameworkPhases = pbxProject.objects.frameworksBuildPhases.objectReferences.filter { buildPhases.contains($0.reference) }
let frameworkBuildFiles = frameworkPhases[0].object.files.compactMap { pbxProject.objects.buildFiles[$0] }
let buildFileSettings = frameworkBuildFiles.map { $0.settings }
try expect(frameworkBuildFiles.count) == 2
try expect(buildFileSettings.compactMap({ $0 }).count) == 1
try expect(buildFileSettings.compactMap({ $0?["ATTRIBUTES"] }).count) == 1
try expect(buildFileSettings.compactMap({ $0?["ATTRIBUTES"] as? [String] }).first) == ["Weak"]
}
}
}
@@ -146,13 +146,13 @@ class SpecLoadingTests: XCTestCase {
targetDictionary["dependencies"] = [
["target": "name", "embed": false],
["carthage": "name"],
["framework": "path"],
["framework": "path", "weak": true],
]
let target = try Target(name: "test", jsonDictionary: targetDictionary)
try expect(target.dependencies.count) == 3
try expect(target.dependencies[0]) == Dependency(type: .target, reference: "name", embed: false)
try expect(target.dependencies[1]) == Dependency(type: .carthage, reference: "name")
try expect(target.dependencies[2]) == Dependency(type: .framework, reference: "path")
try expect(target.dependencies[2]) == Dependency(type: .framework, reference: "path", weakLink: true)
}
$0.it("parses cross platform targets") {