add sdk dependency type

This commit is contained in:
Yonas Kolb 2018-11-02 17:55:24 +11:00
parent e96c91eecf
commit 7e92db5346
11 changed files with 97 additions and 7 deletions

View File

@ -6,6 +6,7 @@
- Added `weak` linking setting for dependencies [#411](https://github.com/yonaskolb/XcodeGen/pull/411) @alvarhansen
- Added `info` to targets for generating an `Info.plist` [#415](https://github.com/yonaskolb/XcodeGen/pull/415) @yonaskolb
- Added `entitlements` to targets for generating an `.entitlement` file [#415](https://github.com/yonaskolb/XcodeGen/pull/415) @yonaskolb
- Added `sdk` dependency type for linking system frameworks within the SDK [#430](https://github.com/yonaskolb/XcodeGen/pull/430) @yonaskolb
- Added `parallelizable` and `randomExecutionOrder` to `Scheme` test targets in an expanded form [#434](https://github.com/yonaskolb/XcodeGen/pull/434) @yonaskolb
- Validate incorrect config setting definitions [#431](https://github.com/yonaskolb/XcodeGen/pull/431) @yonaskolb
- Automatically set project `SDKROOT` if there is only a single platform within the project [#433](https://github.com/yonaskolb/XcodeGen/pull/433) @yonaskolb

View File

@ -329,10 +329,9 @@ A dependency can be one of a 3 types:
- `target: name` - links to another target
- `framework: path` - links to a framework
- `carthage: name` - helper for linking to a Carthage framework
- `sdk: name` - links to a dependency with the SDK. This can either be a relative path within the sdk root or a single filename that references a framework (.framework) or lib (.tbd)
**Embed options**:
These only applied to `target` and `framework` dependencies.
**Linking options**:
- [ ] **embed**: **Bool** - Whether to embed the dependency. Defaults to true for application target and false for non application targets.
- [ ] **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).
@ -363,6 +362,8 @@ targets:
- target: MyFramework
- framework: path/to/framework.framework
- carthage: Result
- sdk: Contacts.framework
- sdk: libc++.tbd
MyFramework:
type: framework
```

View File

@ -34,6 +34,7 @@ public struct Dependency: Equatable {
case target
case framework
case carthage
case sdk
}
}
@ -49,6 +50,9 @@ extension Dependency: JSONObjectConvertible {
} else if let carthage: String = jsonDictionary.json(atKeyPath: "carthage") {
type = .carthage
reference = carthage
} else if let sdk: String = jsonDictionary.json(atKeyPath: "sdk") {
type = .sdk
reference = sdk
} else {
throw SpecParsingError.invalidDependency(jsonDictionary)
}

View File

@ -138,9 +138,25 @@ extension Project {
for target in targets {
for dependency in target.dependencies {
if dependency.type == .target, getProjectTarget(dependency.reference) == nil {
errors.append(.invalidTargetDependency(target: target.name, dependency: dependency.reference))
switch dependency.type {
case .target:
if getProjectTarget(dependency.reference) == nil {
errors.append(.invalidTargetDependency(target: target.name, dependency: dependency.reference))
}
case .sdk:
let path = Path(dependency.reference)
if !dependency.reference.contains("/") {
switch path.extension {
case "framework"?,
"tbd"?:
break
default:
errors.append(.invalidSDKDependency(target: target.name, dependency: dependency.reference))
}
}
default: break
}
}
for source in target.sources {

View File

@ -6,6 +6,7 @@ public struct SpecValidationError: Error, CustomStringConvertible {
public enum ValidationError: Error, CustomStringConvertible {
case invalidXcodeGenVersion(minimumVersion: Version, version: Version)
case invalidSDKDependency(target: String, dependency: String)
case invalidTargetDependency(target: String, dependency: String)
case invalidTargetSource(target: String, source: String)
case invalidTargetConfigFile(target: String, configFile: String, config: String)
@ -27,6 +28,8 @@ public struct SpecValidationError: Error, CustomStringConvertible {
switch self {
case let .invalidXcodeGenVersion(minimumVersion, version):
return "XcodeGen version is \(version), but minimum required version specified as \(minimumVersion)"
case let .invalidSDKDependency(target, dependency):
return "Target \(target.quoted) has invalid sdk dependency: \(dependency.quoted). It must be a full path or have the following extensions: .framework, .dylib, .tbd"
case let .invalidTargetDependency(target, dependency):
return "Target \(target.quoted) has invalid dependency: \(dependency.quoted)"
case let .invalidTargetConfigFile(target, configFile, config):

View File

@ -14,6 +14,7 @@ public class PBXProjGenerator {
var targetObjects: [String: PBXTarget] = [:]
var targetAggregateObjects: [String: PBXAggregateTarget] = [:]
var targetFileReferences: [String: PBXFileReference] = [:]
var sdkFileReferences: [String: PBXFileReference] = [:]
var carthageFrameworksByPlatform: [String: Set<PBXFileElement>] = [:]
var frameworkFiles: [PBXFileElement] = []
@ -522,6 +523,38 @@ public class PBXProjGenerator {
let buildPath = Path(dependency.reference).parent().string.quoted
frameworkBuildPaths.insert(buildPath)
case .sdk:
var dependencyPath = Path(dependency.reference)
if !dependency.reference.contains("/") {
switch dependencyPath.extension ?? "" {
case "framework":
dependencyPath = Path("System/Library/Frameworks") + dependencyPath
case "tbd":
dependencyPath = Path("usr/lib") + dependencyPath
default: break
}
}
let fileReference: PBXFileReference
if let existingFileReferences = sdkFileReferences[dependency.reference] {
fileReference = existingFileReferences
} else {
fileReference = addObject(
PBXFileReference(sourceTree: .sdkRoot,
name: dependencyPath.lastComponent,
lastKnownFileType: Xcode.fileType(path: dependencyPath),
path: dependencyPath.string)
)
sdkFileReferences[dependency.reference] = fileReference
frameworkFiles.append(fileReference)
}
let buildFile = addObject(
PBXBuildFile(file: fileReference,
settings: getDependencyFrameworkSettings(dependency: dependency))
)
targetFrameworkBuildFiles.append(buildFile)
case .carthage:
guard target.type != .staticLibrary else { break }
@ -943,6 +976,8 @@ public class PBXProjGenerator {
// don't want a dependency if it's going to be embedded or statically linked in a non-top level target
// in .target check we filter out targets that will embed all of their dependencies
switch dependency.type {
case .sdk:
dependencies[dependency.reference] = dependency
case .framework, .carthage:
if isTopLevel || dependency.embed == nil {
dependencies[dependency.reference] = dependency

View File

@ -1,10 +1,11 @@
import UIKit
import Contacts
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
_ = CNContact()
}
override func didReceiveMemoryWarning() {

View File

@ -45,6 +45,7 @@
BF_47A75C8A7EF15658238E254C846C5C6B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = VG_30676EBEE9BE54AA26CAE69BE744CAE8 /* Main.storyboard */; };
BF_47FBEFEA08B9642C1F711EDA77FC8C89 /* LocalizedStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = VG_FE6D89DA2D7E7F58340D566590FF221C /* LocalizedStoryboard.storyboard */; };
BF_47FF83A37355E90F93C0F5B2CFBCE317 /* Standalone.swift in Sources */ = {isa = PBXBuildFile; fileRef = FR_82E3C6C060C4487B5177509917C3FAE3 /* Standalone.swift */; };
BF_486398284252AEE9001DD72E5E710D93 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = FR_6A3D8067EBC18CB321826EB21FEBD094 /* libc++.tbd */; };
BF_4D56F3F4D081A77C11325B96DD34D8E1 /* FrameworkFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = FR_261C31660333EF514356EFCBDB368EAB /* FrameworkFile.swift */; };
BF_4EBBAD70FA73DDC89BD933866B90DD08 /* MyFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = FR_A957DAE2193BE1E970F452BFEFF3EBF6 /* MyFramework.h */; settings = {ATTRIBUTES = (Public, ); }; };
BF_51D370314B5DA8E002A908021E459F50 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FR_A55A35F549FD72775C37ED05342812AA /* Assets.xcassets */; };
@ -70,6 +71,7 @@
BF_90F0E9253F2768C312B65530931CD55A /* Empty.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = FR_DBD29CA78CDBBEF69B2C39C6D23BBDA1 /* Empty.h */; };
BF_910C2D6055BD22643F042545CD21AA78 /* StaticLibrary_ObjC.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = FR_D0BE69522DB875ADB041E9135E0767CA /* StaticLibrary_ObjC.h */; };
BF_93A4E1A93C7DB4289E526466D547E55E /* SomeFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FR_2F56FD7A1F7782467AC9F315B6133468 /* SomeFramework.framework */; };
BF_9743BCF98E3EF021AB384652DA126416 /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FR_9A09F93850576AF57455BE58FD53C42F /* Contacts.framework */; };
BF_9830FFD35765AACD86D1B619E22830D6 /* Headers in Headers */ = {isa = PBXBuildFile; fileRef = FR_3DD4DE355C21662A9169EE41C44F73E3 /* Headers */; settings = {ATTRIBUTES = (Public, ); }; };
BF_98DEE7FD578AA439550E0023A2ECE8D0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FR_25BDF725104C5E280D45CBF33F54C72C /* ViewController.swift */; };
BF_9A74AED05E2F61530BFA0F7D23AF0112 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = VG_EB676136B9F946373D4796800CC00AD4 /* Model.xcdatamodeld */; settings = {COMPILER_FLAGS = "-Werror"; }; };
@ -91,6 +93,7 @@
BF_CD062A97959629BD672893FDAE89A1E9 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FR_BB49B398F9291781A60DA963A0BF168C /* NotificationController.swift */; };
BF_D0676C98017B6FDD96A733CB851645DE /* StaticLibrary_ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = FR_C2A280C4FA602E6610BCFB820602B69E /* StaticLibrary_ObjC.m */; };
BF_D0D1D142403C75D11757CB7092E8D035 /* XPC Service.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = FR_1FA381C639CE4923ED6845790A5DF9D2 /* XPC Service.xpc */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
BF_D2532BE2FA7D664875AD6E29A22269C0 /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FR_9A09F93850576AF57455BE58FD53C42F /* Contacts.framework */; };
BF_D3D64E2595369BBDEF03E07543AE2779 /* FrameworkFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = FR_261C31660333EF514356EFCBDB368EAB /* FrameworkFile.swift */; };
BF_D6588CD7B83034816FFD3A7DB10DAD78 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FR_16B791CFA2095097A17CC216977DF6EF /* Assets.xcassets */; };
BF_D7E271A6820E0A908736F44F99341DE1 /* Framework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FR_EFD283107EDF836BF0D9F4EB3F9A0016 /* Framework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -440,6 +443,7 @@
FR_640ADF15D2B92FDC35556B2E0934C21C /* App_macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App_macOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
FR_654475F320EF1630562C841CA8B6938A /* Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FR_6643E0FE8DD9AAC71691A739070C6833 /* Model 3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Model 3.xcdatamodel"; sourceTree = "<group>"; };
FR_6A3D8067EBC18CB321826EB21FEBD094 /* libc++.tbd */ = {isa = PBXFileReference; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
FR_752FB5DFFBC490CFB9742549A0C48527 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
FR_7532DD7B78451A5040048474AC4FBCCC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
FR_7C782E8FBF41DE8BB1E3789DF2C8C1F7 /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = "<group>"; };
@ -451,6 +455,7 @@
FR_8B770F475242D91FC20289A3B35CD165 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = "<group>"; };
FR_96127F4D9D804B89024AB846F0961621 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.module; path = module.modulemap; sourceTree = "<group>"; };
FR_98BB4C8D33EB0E666C136ACD08B21EB3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
FR_9A09F93850576AF57455BE58FD53C42F /* Contacts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Contacts.framework; path = System/Library/Frameworks/Contacts.framework; sourceTree = SDKROOT; };
FR_9B4B00A3CDADD50167B2393562AEBAB2 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.module; path = module.modulemap; sourceTree = "<group>"; };
FR_A0867B127ACF3ED382EB2FD5133D3EA8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
FR_A0DA89632C14F8DF99F15196E6EBB7D5 /* Framework2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework2.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -495,6 +500,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
BF_D2532BE2FA7D664875AD6E29A22269C0 /* Contacts.framework in Frameworks */,
BF_F8D73622DA7CFF30DB9AD17C08C63655 /* Framework2.framework in Frameworks */,
BF_0378AD9857D61219363F74B2FA308B5A /* Framework.framework in Frameworks */,
BF_B8E824A58BFE0B81E16BB26087FDC8B4 /* Result.framework in Frameworks */,
@ -515,9 +521,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
BF_9743BCF98E3EF021AB384652DA126416 /* Contacts.framework in Frameworks */,
BF_6E2D4086A22C12D516A06AE66DC48D16 /* Framework.framework in Frameworks */,
BF_230439786C4C6849F488A5FADC6A42A5 /* Result.framework in Frameworks */,
BF_36BCFE51A59D5EAE19684491C9F5427F /* StaticLibrary_ObjC.a in Frameworks */,
BF_486398284252AEE9001DD72E5E710D93 /* libc++.tbd in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -658,6 +666,8 @@
isa = PBXGroup;
children = (
G_A1CE8BFBEAC6AFDC64D7068C3CE11421 /* Carthage */,
FR_9A09F93850576AF57455BE58FD53C42F /* Contacts.framework */,
FR_6A3D8067EBC18CB321826EB21FEBD094 /* libc++.tbd */,
FR_2F56FD7A1F7782467AC9F315B6133468 /* SomeFramework.framework */,
);
name = Frameworks;

View File

@ -43,6 +43,8 @@ targets:
dependencies:
- target: Framework_macOS
- target: XPC Service
- sdk: Contacts.framework
- sdk: libc++.tbd
App_iOS:
type: application
@ -90,6 +92,7 @@ targets:
- target: App_watchOS
- target: iMessageApp
- framework: Vendor/SomeFramework.framework
- sdk: Contacts.framework
scheme:
testTargets:
- App_iOS_Tests

View File

@ -174,6 +174,20 @@ class ProjectSpecTests: XCTestCase {
try expectValidationError(project, .invalidTargetSchemeConfigVariant(target: "target1", configVariant: "invalidVariant", configType: .debug))
}
$0.it("fails with invalid sdk dependency") {
var project = baseProject
project.targets = [Target(
name: "target1",
type: .application,
platform: .iOS,
dependencies: [Dependency(type: .sdk, reference: "invalidDependency")]
)
]
try expectValidationError(project, .invalidSDKDependency(target: "target1", dependency: "invalidDependency"))
}
$0.it("fails with invalid scheme") {
var project = baseProject
project.schemes = [Scheme(

View File

@ -147,12 +147,14 @@ class SpecLoadingTests: XCTestCase {
["target": "name", "embed": false],
["carthage": "name"],
["framework": "path", "weak": true],
["sdk": "Contacts.framework"],
]
let target = try Target(name: "test", jsonDictionary: targetDictionary)
try expect(target.dependencies.count) == 3
try expect(target.dependencies.count) == 4
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", weakLink: true)
try expect(target.dependencies[3]) == Dependency(type: .sdk, reference: "Contacts.framework")
}
$0.it("parses info plist") {