mirror of
https://github.com/yonaskolb/XcodeGen.git
synced 2024-08-17 00:30:29 +03:00
Support for multiple deployment targets with xcode 14 (#1336)
* platformFilters on Dependecies * platformFilters on sources * fixed current unit tests * renamed enum to SupportedPlatforms * supportedPlatforms field for target * errors * renamed errors * inferPlatformFiltersByPath flag * changed priority to generate filter * fixed parsing * fixed init * unit test supportedPlatforms * unit tests for errors * fixing build settings and unit tests * added new settingsPresets * new check errors and unit tests * case insensitive match * fixed skipping cross platform target * json decode * unit tests inferPlatformFiltersByPath and platformFilters for sources * mocked files * fixing unit tests * first test on dependecies * unit tests completed * fixed unit tests * changelog * doc changes * doc changes * doc changes * doc changes * doc changes * doc changes * doc changes * doc changes * fixed doc * fixed unti tests style * fixed regex * fixed doc * addressing comments * Added TestProject, moved unit tests resources in another folder * Raising error if platform is an array * unit test on new error * fixed error enum * Integrated in TestProject * committed TestProject * unit test error * fixing spm deps in test project * pushed testProject * pushed testProject * pushed testProject fix * comment on isResolved property * renameing supportedPlatforms to supportedDestinations * renameing supportedPlatforms to supportedDestinations * renameing test app * checked out old file * fixing test app * working on auto baseSDK * fixed deploymentTarget * renamed errors * fixed presets * remamed index to priority * small comments * removed isResolved in target and fixed error check * added unit tests * fixed doc * fixed doc * fixed doc * fixed doc * fixed test app * add visionOS and more error check and testing * fixed supported destinations priority and tests * fixed doc * solved conflicts * fixed conflicts * renamed everything --------- Co-authored-by: Giovanni Amati <giovanni.amati@sky.uk>
This commit is contained in:
parent
ec050cd5cb
commit
97d36fd1d2
@ -2,6 +2,15 @@
|
||||
|
||||
## Next Version
|
||||
|
||||
### Feature support for multiple deployment targets with xcode 14
|
||||
|
||||
- Added `supportedDestinations` for target
|
||||
- Added a new platform value `auto` that we can use only with `supportedDestinations`
|
||||
- Added the possiblity to avoid the definition of plaform, only when we use `supportedDestinations`, that fallbacks to 'auto'
|
||||
- Added `destinationFilters` for sources and dependecies
|
||||
- Added `inferDestinationFiltersByPath`, a convenience filter for sources
|
||||
- Added visionOS support
|
||||
|
||||
### Added
|
||||
|
||||
- `.mlpackage` files now default to being a source type #1398 @aaron-foreflight
|
||||
|
@ -22,6 +22,7 @@ You can also use environment variables in your configuration file, by using `${S
|
||||
- [Target](#target)
|
||||
- [Product Type](#product-type)
|
||||
- [Platform](#platform)
|
||||
- [Supported Destinations](#supported-destinations)
|
||||
- [Sources](#sources)
|
||||
- [Target Source](#target-source)
|
||||
- [Dependency](#dependency)
|
||||
@ -356,6 +357,7 @@ Settings are merged in the following order: `groups`, `base`, `configs` (simple
|
||||
|
||||
- [x] **type**: **[Product Type](#product-type)** - Product type of the target
|
||||
- [x] **platform**: **[Platform](#platform)** - Platform of the target
|
||||
- [ ] **supportedDestinations**: **[[Supported Destinations](#supported-destinations)]** - List of supported platform destinations for the target.
|
||||
- [ ] **deploymentTarget**: **String** - The deployment target (eg `9.2`). If this is not specified the value from the project set in [Options](#options)`.deploymentTarget.PLATFORM` will be used.
|
||||
- [ ] **sources**: **[Sources](#sources)** - Source directories of the target
|
||||
- [ ] **configFiles**: **[Config Files](#config-files)** - `.xcconfig` files per config
|
||||
@ -433,12 +435,15 @@ This will provide default build settings for a certain product type. It can be a
|
||||
|
||||
This will provide default build settings for a certain platform. It can be any of the following:
|
||||
|
||||
- `auto` (available only when we use `supportedDestinations`)
|
||||
- `iOS`
|
||||
- `macOS`
|
||||
- `tvOS`
|
||||
- `macOS`
|
||||
- `watchOS`
|
||||
- `visionOS` (`visionOS` doesn't support Carthage usage)
|
||||
|
||||
Note that when we use supported destinations with Xcode 14+ we can avoid the definition of platform that fallbacks to the `auto` value.
|
||||
|
||||
**Multi Platform targets**
|
||||
|
||||
You can also specify an array of platforms. This will generate a target for each platform.
|
||||
@ -469,6 +474,33 @@ targets:
|
||||
|
||||
The above will generate 2 targets named `MyFramework_iOS` and `MyFramework_tvOS`, with all the relevant platform build settings. They will both have a `PRODUCT_NAME` of `MyFramework`
|
||||
|
||||
### Supported Destinations
|
||||
|
||||
This will provide a mix of default build settings for the chosen platform destinations. It can be any of the following:
|
||||
|
||||
- `iOS`
|
||||
- `tvOS`
|
||||
- `macOS`
|
||||
- `macCatalyst`
|
||||
- `visionOS`
|
||||
|
||||
```yaml
|
||||
targets:
|
||||
MyFramework:
|
||||
type: framework
|
||||
supportedDestinations: [iOS, tvOS]
|
||||
deploymentTarget:
|
||||
iOS: 9.0
|
||||
tvOS: 10.0
|
||||
sources:
|
||||
- path: MySources
|
||||
inferDestinationFiltersByPath: true
|
||||
- path: OtherSources
|
||||
destinationFilters: [iOS]
|
||||
```
|
||||
|
||||
Note that the definition of supported destinations can be applied to every type of bundle making everything more easy to manage (app targets, unit tests, UI tests etc).
|
||||
|
||||
### Sources
|
||||
|
||||
Specifies the source directories for a target. This can either be a single source or a list of sources. Applicable source files, resources, headers, and `.lproj` files will be parsed appropriately.
|
||||
@ -483,7 +515,9 @@ A source can be provided via a string (the path) or an object of the form:
|
||||
- [ ] **compilerFlags**: **[String]** or **String** - A list of compilerFlags to add to files under this specific path provided as a list or a space delimited string. Defaults to empty.
|
||||
- [ ] **excludes**: **[String]** - A list of [global patterns](https://en.wikipedia.org/wiki/Glob_(programming)) representing the files to exclude. These rules are relative to `path` and _not the directory where `project.yml` resides_. XcodeGen uses Bash 4's Glob behaviors where globstar (**) is enabled.
|
||||
- [ ] **includes**: **[String]** - A list of global patterns in the same format as `excludes` representing the files to include. These rules are relative to `path` and _not the directory where `project.yml` resides_. If **excludes** is present and file conflicts with **includes**, **excludes** will override the **includes** behavior.
|
||||
- [ ] **createIntermediateGroups**: **Bool** - This overrides the value in [Options](#options)
|
||||
- [ ] **destinationFilters**: **[[Supported Destinations](#supported-destinations)]** - List of supported platform destinations the files should filter to. Defaults to all supported destinations.
|
||||
- [ ] **inferDestinationFiltersByPath**: **Bool** - This is a convenience filter that helps you to filter the files if their paths match these patterns `**/<supportedDestination>/*` or `*_<supportedDestination>.swift`. Note, if you use `destinationFilters` this flag will be ignored.
|
||||
- [ ] **createIntermediateGroups**: **Bool** - This overrides the value in [Options](#options).
|
||||
- [ ] **optional**: **Bool** - Disable missing path check. Defaults to false.
|
||||
- [ ] **buildPhase**: **String** - This manually sets the build phase this file or files in this directory will be added to, otherwise XcodeGen will guess based on the file extension. Note that `Info.plist` files will never be added to any build phases, no matter what this setting is. Possible values are:
|
||||
- `sources` - Compile Sources phase
|
||||
@ -519,9 +553,11 @@ targets:
|
||||
MyTarget:
|
||||
sources: MyTargetSource
|
||||
MyOtherTarget:
|
||||
supportedDestinations: [iOS, tvOS]
|
||||
sources:
|
||||
- MyOtherTargetSource1
|
||||
- path: MyOtherTargetSource2
|
||||
inferDestinationFiltersByPath: true
|
||||
name: MyNewName
|
||||
excludes:
|
||||
- "ios/*.[mh]"
|
||||
@ -533,6 +569,7 @@ targets:
|
||||
- "-Werror"
|
||||
- "-Wextra"
|
||||
- path: MyOtherTargetSource3
|
||||
destinationFilters: [iOS]
|
||||
compilerFlags: "-Werror -Wextra"
|
||||
- path: ModuleMaps
|
||||
buildPhase:
|
||||
@ -560,10 +597,11 @@ A dependency can be one of a 6 types:
|
||||
|
||||
- [ ] **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).
|
||||
- [ ] **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
|
||||
- [ ] **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**
|
||||
- [ ] **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.
|
||||
- [ ] **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**.
|
||||
- [ ] **destinationFilters**: **[[Supported Destinations](#supported-destinations)]** - List of supported platform destinations this dependency should filter to. Defaults to all supported destinations.
|
||||
- [ ] **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:
|
||||
@ -613,13 +651,17 @@ projectReferences:
|
||||
path: path/to/FooLib.xcodeproj
|
||||
targets:
|
||||
MyTarget:
|
||||
supportedDestinations: [iOS, tvOS]
|
||||
dependencies:
|
||||
- target: MyFramework
|
||||
destinationFilters: [iOS]
|
||||
- target: FooLib/FooTarget
|
||||
- framework: path/to/framework.framework
|
||||
destinationFilters: [tvOS]
|
||||
- carthage: Result
|
||||
findFrameworks: false
|
||||
linkType: static
|
||||
destinationFilters: [iOS]
|
||||
- sdk: Contacts.framework
|
||||
- sdk: libc++.tbd
|
||||
- sdk: libz.dylib
|
||||
|
@ -1,3 +1,3 @@
|
||||
TARGETED_DEVICE_FAMILY: 3
|
||||
LD_RUNPATH_SEARCH_PATHS: ["$(inherited)", "@executable_path/Frameworks"]
|
||||
SDKROOT: appletvos
|
||||
TARGETED_DEVICE_FAMILY: 3
|
||||
|
5
SettingPresets/SupportedDestinations/iOS.yml
Normal file
5
SettingPresets/SupportedDestinations/iOS.yml
Normal file
@ -0,0 +1,5 @@
|
||||
SUPPORTED_PLATFORMS: iphoneos iphonesimulator
|
||||
TARGETED_DEVICE_FAMILY: '1,2'
|
||||
SUPPORTS_MACCATALYST: NO
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: YES
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD: YES
|
2
SettingPresets/SupportedDestinations/macCatalyst.yml
Normal file
2
SettingPresets/SupportedDestinations/macCatalyst.yml
Normal file
@ -0,0 +1,2 @@
|
||||
SUPPORTS_MACCATALYST: YES
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: NO
|
3
SettingPresets/SupportedDestinations/macOS.yml
Normal file
3
SettingPresets/SupportedDestinations/macOS.yml
Normal file
@ -0,0 +1,3 @@
|
||||
SUPPORTED_PLATFORMS: macosx
|
||||
SUPPORTS_MACCATALYST: NO
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: NO
|
2
SettingPresets/SupportedDestinations/tvOS.yml
Normal file
2
SettingPresets/SupportedDestinations/tvOS.yml
Normal file
@ -0,0 +1,2 @@
|
||||
SUPPORTED_PLATFORMS: appletvos appletvsimulator
|
||||
TARGETED_DEVICE_FAMILY: '3'
|
3
SettingPresets/SupportedDestinations/visionOS.yml
Normal file
3
SettingPresets/SupportedDestinations/visionOS.yml
Normal file
@ -0,0 +1,3 @@
|
||||
SUPPORTED_PLATFORMS: xros xrsimulator
|
||||
TARGETED_DEVICE_FAMILY: '7'
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD: NO
|
@ -16,6 +16,7 @@ public struct Dependency: Equatable {
|
||||
public var implicit: Bool = implicitDefault
|
||||
public var weakLink: Bool = weakLinkDefault
|
||||
public var platformFilter: PlatformFilter = platformFilterDefault
|
||||
public var destinationFilters: [SupportedDestination]?
|
||||
public var platforms: Set<Platform>?
|
||||
public var copyPhase: BuildPhaseSpec.CopyFilesSettings?
|
||||
|
||||
@ -28,6 +29,7 @@ public struct Dependency: Equatable {
|
||||
implicit: Bool = implicitDefault,
|
||||
weakLink: Bool = weakLinkDefault,
|
||||
platformFilter: PlatformFilter = platformFilterDefault,
|
||||
destinationFilters: [SupportedDestination]? = nil,
|
||||
platforms: Set<Platform>? = nil,
|
||||
copyPhase: BuildPhaseSpec.CopyFilesSettings? = nil
|
||||
) {
|
||||
@ -39,6 +41,7 @@ public struct Dependency: Equatable {
|
||||
self.implicit = implicit
|
||||
self.weakLink = weakLink
|
||||
self.platformFilter = platformFilter
|
||||
self.destinationFilters = destinationFilters
|
||||
self.platforms = platforms
|
||||
self.copyPhase = copyPhase
|
||||
}
|
||||
@ -48,7 +51,7 @@ public struct Dependency: Equatable {
|
||||
case iOS
|
||||
case macOS
|
||||
}
|
||||
|
||||
|
||||
public enum CarthageLinkType: String {
|
||||
case dynamic
|
||||
case `static`
|
||||
@ -142,7 +145,11 @@ extension Dependency: JSONObjectConvertible {
|
||||
} else {
|
||||
self.platformFilter = .all
|
||||
}
|
||||
|
||||
|
||||
if let destinationFilters: [SupportedDestination] = jsonDictionary.json(atKeyPath: "destinationFilters") {
|
||||
self.destinationFilters = destinationFilters
|
||||
}
|
||||
|
||||
if let platforms: [ProjectSpec.Platform] = jsonDictionary.json(atKeyPath: "platforms") {
|
||||
self.platforms = Set(platforms)
|
||||
}
|
||||
@ -161,6 +168,7 @@ extension Dependency: JSONEncodable {
|
||||
"link": link,
|
||||
"platforms": platforms?.map(\.rawValue).sorted(),
|
||||
"copy": copyPhase?.toJSONValue(),
|
||||
"destinationFilters": destinationFilters?.map { $0.rawValue },
|
||||
]
|
||||
|
||||
if removeHeaders != Dependency.removeHeadersDefault {
|
||||
|
@ -26,6 +26,7 @@ public struct DeploymentTarget: Equatable {
|
||||
|
||||
public func version(for platform: Platform) -> Version? {
|
||||
switch platform {
|
||||
case .auto: return nil
|
||||
case .iOS: return iOS
|
||||
case .tvOS: return tvOS
|
||||
case .watchOS: return watchOS
|
||||
@ -39,6 +40,7 @@ extension Platform {
|
||||
|
||||
public var deploymentTargetSetting: String {
|
||||
switch self {
|
||||
case .auto: return ""
|
||||
case .iOS: return "IPHONEOS_DEPLOYMENT_TARGET"
|
||||
case .tvOS: return "TVOS_DEPLOYMENT_TARGET"
|
||||
case .watchOS: return "WATCHOS_DEPLOYMENT_TARGET"
|
||||
@ -49,6 +51,7 @@ extension Platform {
|
||||
|
||||
public var sdkRoot: String {
|
||||
switch self {
|
||||
case .auto: return "auto"
|
||||
case .iOS: return "iphoneos"
|
||||
case .tvOS: return "appletvos"
|
||||
case .watchOS: return "watchos"
|
||||
|
@ -1,9 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
public enum Platform: String, Hashable, CaseIterable {
|
||||
case auto
|
||||
case iOS
|
||||
case watchOS
|
||||
case tvOS
|
||||
case macOS
|
||||
case watchOS
|
||||
case visionOS
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ extension Plist: JSONEncodable {
|
||||
[
|
||||
"path": path,
|
||||
"properties": properties,
|
||||
]
|
||||
] as [String : Any]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ extension Settings: JSONEncodable {
|
||||
"base": buildSettings,
|
||||
"groups": groups,
|
||||
"configs": configSettings.mapValues { $0.toJSONValue() },
|
||||
]
|
||||
] as [String : Any]
|
||||
}
|
||||
return buildSettings
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ public enum SpecParsingError: Error, CustomStringConvertible {
|
||||
case unknownPackageRequirement([String: Any])
|
||||
case invalidSourceBuildPhase(String)
|
||||
case invalidTargetReference(String)
|
||||
case invalidTargetPlatformAsArray
|
||||
case invalidVersion(String)
|
||||
case unknownBreakpointType(String)
|
||||
case unknownBreakpointScope(String)
|
||||
@ -27,6 +28,8 @@ public enum SpecParsingError: Error, CustomStringConvertible {
|
||||
return "Invalid Source Build Phase: \(error)"
|
||||
case let .invalidTargetReference(targetReference):
|
||||
return "Invalid Target Reference Syntax: \(targetReference)"
|
||||
case .invalidTargetPlatformAsArray:
|
||||
return "Invalid Target platform: Array not allowed with supported destinations"
|
||||
case let .invalidVersion(version):
|
||||
return "Invalid version: \(version)"
|
||||
case let .unknownPackageRequirement(package):
|
||||
|
@ -180,6 +180,29 @@ extension Project {
|
||||
errors.append(.invalidTargetSource(target: target.name, source: sourcePath.string))
|
||||
}
|
||||
}
|
||||
|
||||
if target.supportedDestinations != nil, target.platform == .watchOS {
|
||||
errors.append(.unexpectedTargetPlatformForSupportedDestinations(target: target.name, platform: target.platform))
|
||||
}
|
||||
|
||||
if target.supportedDestinations?.contains(.macOS) == true,
|
||||
target.supportedDestinations?.contains(.macCatalyst) == true {
|
||||
|
||||
errors.append(.multipleMacPlatformsInSupportedDestinations(target: target.name))
|
||||
}
|
||||
|
||||
if target.supportedDestinations?.contains(.macCatalyst) == true,
|
||||
target.platform != .iOS, target.platform != .auto {
|
||||
|
||||
errors.append(.invalidTargetPlatformForSupportedDestinations(target: target.name))
|
||||
}
|
||||
|
||||
if target.platform != .auto, target.platform != .watchOS,
|
||||
let supportedDestination = SupportedDestination(rawValue: target.platform.rawValue),
|
||||
target.supportedDestinations?.contains(supportedDestination) == false {
|
||||
|
||||
errors.append(.missingTargetPlatformInSupportedDestinations(target: target.name, platform: target.platform))
|
||||
}
|
||||
}
|
||||
|
||||
for projectReference in projectReferences {
|
||||
|
@ -17,6 +17,10 @@ public struct SpecValidationError: Error, CustomStringConvertible {
|
||||
case invalidTargetConfigFile(target: String, configFile: String, config: String)
|
||||
case invalidTargetSchemeConfigVariant(target: String, configVariant: String, configType: ConfigType)
|
||||
case invalidTargetSchemeTest(target: String, testTarget: String)
|
||||
case invalidTargetPlatformForSupportedDestinations(target: String)
|
||||
case unexpectedTargetPlatformForSupportedDestinations(target: String, platform: Platform)
|
||||
case multipleMacPlatformsInSupportedDestinations(target: String)
|
||||
case missingTargetPlatformInSupportedDestinations(target: String, platform: Platform)
|
||||
case invalidSchemeTarget(scheme: String, target: String, action: String)
|
||||
case invalidSchemeConfig(scheme: String, config: String)
|
||||
case invalidSwiftPackage(name: String, target: String)
|
||||
@ -54,6 +58,14 @@ public struct SpecValidationError: Error, CustomStringConvertible {
|
||||
return "Target \(target.quoted) has an invalid scheme config variant which requires a config that has a \(configType.rawValue.quoted) type and contains the name \(configVariant.quoted)"
|
||||
case let .invalidTargetSchemeTest(target, test):
|
||||
return "Target \(target.quoted) scheme has invalid test \(test.quoted)"
|
||||
case let .invalidTargetPlatformForSupportedDestinations(target):
|
||||
return "Target \(target.quoted) has supported destinations that require a target platform iOS or auto"
|
||||
case let .unexpectedTargetPlatformForSupportedDestinations(target, platform):
|
||||
return "Target \(target.quoted) has platform \(platform.rawValue.quoted) that does not expect supported destinations"
|
||||
case let .multipleMacPlatformsInSupportedDestinations(target):
|
||||
return "Target \(target.quoted) has multiple definitions of mac platforms in supported destinations"
|
||||
case let .missingTargetPlatformInSupportedDestinations(target, platform):
|
||||
return "Target \(target.quoted) has platform \(platform.rawValue.quoted) that is missing in supported destinations"
|
||||
case let .invalidConfigFile(configFile, config):
|
||||
return "Invalid config file \(configFile.quoted) for config \(config.quoted)"
|
||||
case let .invalidSchemeTarget(scheme, target, action):
|
||||
|
45
Sources/ProjectSpec/SupportedDestination.swift
Normal file
45
Sources/ProjectSpec/SupportedDestination.swift
Normal file
@ -0,0 +1,45 @@
|
||||
import Foundation
|
||||
|
||||
public enum SupportedDestination: String, CaseIterable {
|
||||
case iOS
|
||||
case tvOS
|
||||
case macOS
|
||||
case macCatalyst
|
||||
case visionOS
|
||||
}
|
||||
|
||||
extension SupportedDestination {
|
||||
|
||||
public var string: String {
|
||||
switch self {
|
||||
case .iOS:
|
||||
return "ios"
|
||||
case .tvOS:
|
||||
return "tvos"
|
||||
case .macOS:
|
||||
return "macos"
|
||||
case .macCatalyst:
|
||||
return "maccatalyst"
|
||||
case .visionOS:
|
||||
return "xros"
|
||||
}
|
||||
}
|
||||
|
||||
// This is used to:
|
||||
// 1. Get the first one and apply SettingPresets 'Platforms' and 'Product_Platform' if the platform is 'auto'
|
||||
// 2. Sort, loop and merge together SettingPresets 'SupportedDestinations'
|
||||
public var priority: Int {
|
||||
switch self {
|
||||
case .iOS:
|
||||
return 0
|
||||
case .tvOS:
|
||||
return 1
|
||||
case .visionOS:
|
||||
return 2
|
||||
case .macOS:
|
||||
return 3
|
||||
case .macCatalyst:
|
||||
return 4
|
||||
}
|
||||
}
|
||||
}
|
@ -37,6 +37,7 @@ public struct Target: ProjectTarget {
|
||||
public var name: String
|
||||
public var type: PBXProductType
|
||||
public var platform: Platform
|
||||
public var supportedDestinations: [SupportedDestination]?
|
||||
public var settings: Settings
|
||||
public var sources: [TargetSource]
|
||||
public var dependencies: [Dependency]
|
||||
@ -58,7 +59,7 @@ public struct Target: ProjectTarget {
|
||||
public var productName: String
|
||||
public var onlyCopyFilesOnInstall: Bool
|
||||
public var putResourcesBeforeSourcesBuildPhase: Bool
|
||||
|
||||
|
||||
public var isLegacy: Bool {
|
||||
legacy != nil
|
||||
}
|
||||
@ -78,6 +79,7 @@ public struct Target: ProjectTarget {
|
||||
name: String,
|
||||
type: PBXProductType,
|
||||
platform: Platform,
|
||||
supportedDestinations: [SupportedDestination]? = nil,
|
||||
productName: String? = nil,
|
||||
deploymentTarget: Version? = nil,
|
||||
settings: Settings = .empty,
|
||||
@ -103,6 +105,7 @@ public struct Target: ProjectTarget {
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.platform = platform
|
||||
self.supportedDestinations = supportedDestinations
|
||||
self.deploymentTarget = deploymentTarget
|
||||
self.productName = productName ?? name
|
||||
self.settings = settings
|
||||
@ -162,15 +165,17 @@ extension Target {
|
||||
guard let targetsDictionary: [String: JSONDictionary] = jsonDictionary["targets"] as? [String: JSONDictionary] else {
|
||||
return jsonDictionary
|
||||
}
|
||||
|
||||
|
||||
var crossPlatformTargets: [String: JSONDictionary] = [:]
|
||||
|
||||
for (targetName, target) in targetsDictionary {
|
||||
|
||||
if let platforms = target["platform"] as? [String] {
|
||||
|
||||
for platform in platforms {
|
||||
var platformTarget = target
|
||||
|
||||
/// This value is set to help us to check, in Target init, that there are no conflicts in the definition of the platforms. We want to ensure that the user didn't define, at the same time,
|
||||
/// the new Xcode 14 supported destinations and the XcodeGen generation of Multiple Platform Targets (when you define the platform field as an array).
|
||||
platformTarget["isMultiPlatformTarget"] = true
|
||||
|
||||
platformTarget = platformTarget.expand(variables: ["platform": platform])
|
||||
|
||||
@ -202,8 +207,8 @@ extension Target {
|
||||
crossPlatformTargets[targetName] = target
|
||||
}
|
||||
}
|
||||
|
||||
var merged = jsonDictionary
|
||||
|
||||
merged["targets"] = crossPlatformTargets
|
||||
return merged
|
||||
}
|
||||
@ -268,19 +273,41 @@ extension Target: NamedJSONDictionaryConvertible {
|
||||
let resolvedName: String = jsonDictionary.json(atKeyPath: "name") ?? name
|
||||
self.name = resolvedName
|
||||
productName = jsonDictionary.json(atKeyPath: "productName") ?? resolvedName
|
||||
let typeString: String = try jsonDictionary.json(atKeyPath: "type")
|
||||
|
||||
let typeString: String = jsonDictionary.json(atKeyPath: "type") ?? ""
|
||||
if let type = PBXProductType(string: typeString) {
|
||||
self.type = type
|
||||
} else {
|
||||
throw SpecParsingError.unknownTargetType(typeString)
|
||||
}
|
||||
let platformString: String = try jsonDictionary.json(atKeyPath: "platform")
|
||||
|
||||
if let supportedDestinations: [SupportedDestination] = jsonDictionary.json(atKeyPath: "supportedDestinations") {
|
||||
self.supportedDestinations = supportedDestinations
|
||||
}
|
||||
|
||||
let isResolved = jsonDictionary.json(atKeyPath: "isMultiPlatformTarget") ?? false
|
||||
if isResolved, supportedDestinations != nil {
|
||||
throw SpecParsingError.invalidTargetPlatformAsArray
|
||||
}
|
||||
|
||||
var platformString: String = jsonDictionary.json(atKeyPath: "platform") ?? ""
|
||||
// platform defaults to 'auto' if it is empty and we are using supported destinations
|
||||
if supportedDestinations != nil, platformString.isEmpty {
|
||||
platformString = Platform.auto.rawValue
|
||||
}
|
||||
// we add 'iOS' in supported destinations if it contains only 'macCatalyst'
|
||||
if supportedDestinations?.contains(.macCatalyst) == true,
|
||||
supportedDestinations?.contains(.iOS) == false {
|
||||
|
||||
supportedDestinations?.append(.iOS)
|
||||
}
|
||||
|
||||
if let platform = Platform(rawValue: platformString) {
|
||||
self.platform = platform
|
||||
} else {
|
||||
throw SpecParsingError.unknownTargetPlatform(platformString)
|
||||
}
|
||||
|
||||
|
||||
if let string: String = jsonDictionary.json(atKeyPath: "deploymentTarget") {
|
||||
deploymentTarget = try Version.parse(string)
|
||||
} else if let double: Double = jsonDictionary.json(atKeyPath: "deploymentTarget") {
|
||||
@ -351,6 +378,7 @@ extension Target: JSONEncodable {
|
||||
var dict: [String: Any?] = [
|
||||
"type": type.name,
|
||||
"platform": platform.rawValue,
|
||||
"supportedDestinations": supportedDestinations?.map { $0.rawValue },
|
||||
"settings": settings.toJSONValue(),
|
||||
"configFiles": configFiles,
|
||||
"attributes": attributes,
|
||||
|
@ -23,6 +23,8 @@ public struct TargetSource: Equatable {
|
||||
public var createIntermediateGroups: Bool?
|
||||
public var attributes: [String]
|
||||
public var resourceTags: [String]
|
||||
public var inferDestinationFiltersByPath: Bool?
|
||||
public var destinationFilters: [SupportedDestination]?
|
||||
|
||||
public enum HeaderVisibility: String {
|
||||
case `public`
|
||||
@ -51,7 +53,9 @@ public struct TargetSource: Equatable {
|
||||
headerVisibility: HeaderVisibility? = nil,
|
||||
createIntermediateGroups: Bool? = nil,
|
||||
attributes: [String] = [],
|
||||
resourceTags: [String] = []
|
||||
resourceTags: [String] = [],
|
||||
inferDestinationFiltersByPath: Bool? = nil,
|
||||
destinationFilters: [SupportedDestination]? = nil
|
||||
) {
|
||||
self.path = (path as NSString).standardizingPath
|
||||
self.name = name
|
||||
@ -66,6 +70,8 @@ public struct TargetSource: Equatable {
|
||||
self.createIntermediateGroups = createIntermediateGroups
|
||||
self.attributes = attributes
|
||||
self.resourceTags = resourceTags
|
||||
self.inferDestinationFiltersByPath = inferDestinationFiltersByPath
|
||||
self.destinationFilters = destinationFilters
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +118,12 @@ extension TargetSource: JSONObjectConvertible {
|
||||
createIntermediateGroups = jsonDictionary.json(atKeyPath: "createIntermediateGroups")
|
||||
attributes = jsonDictionary.json(atKeyPath: "attributes") ?? []
|
||||
resourceTags = jsonDictionary.json(atKeyPath: "resourceTags") ?? []
|
||||
|
||||
inferDestinationFiltersByPath = jsonDictionary.json(atKeyPath: "inferDestinationFiltersByPath")
|
||||
|
||||
if let destinationFilters: [SupportedDestination] = jsonDictionary.json(atKeyPath: "destinationFilters") {
|
||||
self.destinationFilters = destinationFilters
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,6 +141,8 @@ extension TargetSource: JSONEncodable {
|
||||
"createIntermediateGroups": createIntermediateGroups,
|
||||
"resourceTags": resourceTags,
|
||||
"path": path,
|
||||
"inferDestinationFiltersByPath": inferDestinationFiltersByPath,
|
||||
"destinationFilters": destinationFilters?.map { $0.rawValue },
|
||||
]
|
||||
|
||||
if optional != TargetSource.optionalDefault {
|
||||
|
@ -25,7 +25,7 @@ extension TestPlan: JSONEncodable {
|
||||
[
|
||||
"path": path,
|
||||
"defaultPlan": defaultPlan,
|
||||
]
|
||||
] as [String : Any]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@ extension Platform {
|
||||
|
||||
public var emoji: String {
|
||||
switch self {
|
||||
case .auto: return "🤖"
|
||||
case .iOS: return "📱"
|
||||
case .watchOS: return "⌚️"
|
||||
case .tvOS: return "📺"
|
||||
|
@ -151,6 +151,9 @@ extension Platform {
|
||||
|
||||
public var carthageName: String {
|
||||
switch self {
|
||||
case .auto:
|
||||
// This is a dummy value
|
||||
return "auto"
|
||||
case .iOS:
|
||||
return "iOS"
|
||||
case .tvOS:
|
||||
|
@ -340,7 +340,7 @@ public class PBXProjGenerator {
|
||||
return addObject(buildConfig)
|
||||
}
|
||||
|
||||
var dependencies = target.targets.map { generateTargetDependency(from: target.name, to: $0, platform: nil) }
|
||||
var dependencies = target.targets.map { generateTargetDependency(from: target.name, to: $0, platform: nil, platforms: nil) }
|
||||
|
||||
let defaultConfigurationName = project.options.defaultConfig ?? project.configs.first?.name ?? ""
|
||||
let buildConfigList = addObject(XCConfigurationList(
|
||||
@ -359,7 +359,7 @@ public class PBXProjGenerator {
|
||||
aggregateTarget.dependencies = dependencies
|
||||
}
|
||||
|
||||
func generateTargetDependency(from: String, to target: String, platform: String?) -> PBXTargetDependency {
|
||||
func generateTargetDependency(from: String, to target: String, platform: String?, platforms: [String]?) -> PBXTargetDependency {
|
||||
guard let targetObject = targetObjects[target] ?? targetAggregateObjects[target] else {
|
||||
fatalError("Target dependency not found: from ( \(from) ) to ( \(target) )")
|
||||
}
|
||||
@ -376,6 +376,7 @@ public class PBXProjGenerator {
|
||||
let targetDependency = addObject(
|
||||
PBXTargetDependency(
|
||||
platformFilter: platform,
|
||||
platformFilters: platforms,
|
||||
target: targetObject,
|
||||
targetProxy: targetProxy
|
||||
)
|
||||
@ -727,7 +728,7 @@ public class PBXProjGenerator {
|
||||
return !linkingAttributes.isEmpty ? ["ATTRIBUTES": linkingAttributes] : nil
|
||||
}
|
||||
|
||||
func processTargetDependency(_ dependency: Dependency, dependencyTarget: Target, embedFileReference: PBXFileElement?, platform: String?) {
|
||||
func processTargetDependency(_ dependency: Dependency, dependencyTarget: Target, embedFileReference: PBXFileElement?, platform: String?, platforms: [String]?) {
|
||||
let dependencyLinkage = dependencyTarget.defaultLinkage
|
||||
let link = dependency.link ??
|
||||
((dependencyLinkage == .dynamic && target.type != .staticLibrary) ||
|
||||
@ -736,6 +737,7 @@ public class PBXProjGenerator {
|
||||
if link, let dependencyFile = embedFileReference {
|
||||
let pbxBuildFile = PBXBuildFile(file: dependencyFile, settings: getDependencyFrameworkSettings(dependency: dependency))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let buildFile = addObject(pbxBuildFile)
|
||||
targetFrameworkBuildFiles.append(buildFile)
|
||||
|
||||
@ -752,6 +754,7 @@ public class PBXProjGenerator {
|
||||
settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? !dependencyTarget.type.isExecutable)
|
||||
)
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
|
||||
if dependency.copyPhase != nil {
|
||||
@ -787,6 +790,7 @@ public class PBXProjGenerator {
|
||||
|
||||
let embed = dependency.embed ?? target.shouldEmbedDependencies
|
||||
let platform = makePlatformFilter(for: dependency.platformFilter)
|
||||
let platforms = makeDestinationFilters(for: dependency.destinationFilters)
|
||||
|
||||
switch dependency.type {
|
||||
case .target:
|
||||
@ -795,15 +799,15 @@ public class PBXProjGenerator {
|
||||
switch dependencyTargetReference.location {
|
||||
case .local:
|
||||
let dependencyTargetName = dependency.reference
|
||||
let targetDependency = generateTargetDependency(from: target.name, to: dependencyTargetName, platform: platform)
|
||||
let targetDependency = generateTargetDependency(from: target.name, to: dependencyTargetName, platform: platform, platforms: platforms)
|
||||
dependencies.append(targetDependency)
|
||||
guard let dependencyTarget = project.getTarget(dependencyTargetName) else { continue }
|
||||
processTargetDependency(dependency, dependencyTarget: dependencyTarget, embedFileReference: targetFileReferences[dependencyTarget.name], platform: platform)
|
||||
processTargetDependency(dependency, dependencyTarget: dependencyTarget, embedFileReference: targetFileReferences[dependencyTarget.name], platform: platform, platforms: platforms)
|
||||
case .project(let dependencyProjectName):
|
||||
let dependencyTargetName = dependencyTargetReference.name
|
||||
let (targetDependency, dependencyTarget, dependencyProductProxy) = try generateExternalTargetDependency(from: target.name, to: dependencyTargetName, in: dependencyProjectName, platform: target.platform)
|
||||
dependencies.append(targetDependency)
|
||||
processTargetDependency(dependency, dependencyTarget: dependencyTarget, embedFileReference: dependencyProductProxy, platform: platform)
|
||||
processTargetDependency(dependency, dependencyTarget: dependencyTarget, embedFileReference: dependencyProductProxy, platform: platform, platforms: platforms)
|
||||
}
|
||||
|
||||
case .framework:
|
||||
@ -829,6 +833,7 @@ public class PBXProjGenerator {
|
||||
if dependency.link ?? (target.type != .staticLibrary) {
|
||||
let pbxBuildFile = PBXBuildFile(file: fileReference, settings: getDependencyFrameworkSettings(dependency: dependency))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let buildFile = addObject(pbxBuildFile)
|
||||
|
||||
targetFrameworkBuildFiles.append(buildFile)
|
||||
@ -841,6 +846,7 @@ public class PBXProjGenerator {
|
||||
if embed {
|
||||
let pbxBuildFile = PBXBuildFile(file: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
|
||||
if dependency.copyPhase != nil {
|
||||
@ -891,12 +897,14 @@ public class PBXProjGenerator {
|
||||
settings: getDependencyFrameworkSettings(dependency: dependency)
|
||||
)
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let buildFile = addObject(pbxBuildFile)
|
||||
targetFrameworkBuildFiles.append(buildFile)
|
||||
|
||||
if dependency.embed == true {
|
||||
let pbxBuildFile = PBXBuildFile(file: fileReference, settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
|
||||
if dependency.copyPhase != nil {
|
||||
@ -926,6 +934,7 @@ public class PBXProjGenerator {
|
||||
if dependency.link ?? (!isStaticLibrary && !isCarthageStaticLink) {
|
||||
let pbxBuildFile = PBXBuildFile(file: fileReference, settings: getDependencyFrameworkSettings(dependency: dependency))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let buildFile = addObject(pbxBuildFile)
|
||||
targetFrameworkBuildFiles.append(buildFile)
|
||||
}
|
||||
@ -954,11 +963,12 @@ public class PBXProjGenerator {
|
||||
if link {
|
||||
let file = PBXBuildFile(product: packageDependency, settings: getDependencyFrameworkSettings(dependency: dependency))
|
||||
file.platformFilter = platform
|
||||
file.platformFilters = platforms
|
||||
let buildFile = addObject(file)
|
||||
targetFrameworkBuildFiles.append(buildFile)
|
||||
} else {
|
||||
let targetDependency = addObject(
|
||||
PBXTargetDependency(platformFilter: platform, product: packageDependency)
|
||||
PBXTargetDependency(platformFilter: platform, platformFilters: platforms, product: packageDependency)
|
||||
)
|
||||
dependencies.append(targetDependency)
|
||||
}
|
||||
@ -967,6 +977,7 @@ public class PBXProjGenerator {
|
||||
let pbxBuildFile = PBXBuildFile(product: packageDependency,
|
||||
settings: getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true))
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let embedFile = addObject(pbxBuildFile)
|
||||
|
||||
if dependency.copyPhase != nil {
|
||||
@ -999,6 +1010,7 @@ public class PBXProjGenerator {
|
||||
settings: embed ? getEmbedSettings(dependency: dependency, codeSign: dependency.codeSign ?? true) : nil
|
||||
)
|
||||
pbxBuildFile.platformFilter = platform
|
||||
pbxBuildFile.platformFilters = platforms
|
||||
let buildFile = addObject(pbxBuildFile)
|
||||
copyBundlesReferences.append(buildFile)
|
||||
|
||||
@ -1445,7 +1457,12 @@ public class PBXProjGenerator {
|
||||
return "ios"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func makeDestinationFilters(for filters: [SupportedDestination]?) -> [String]? {
|
||||
guard let filters = filters, !filters.isEmpty else { return nil }
|
||||
return filters.map { $0.string }
|
||||
}
|
||||
|
||||
/// Make `Build Tools Plug-ins` as a dependency to the target
|
||||
/// - Parameter target: ProjectTarget
|
||||
/// - Returns: Elements for referencing other targets through content proxies.
|
||||
@ -1466,7 +1483,7 @@ public class PBXProjGenerator {
|
||||
return targetDependency
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func getInfoPlists(for target: Target) -> [Config: String] {
|
||||
var searchForDefaultInfoPlist: Bool = true
|
||||
var defaultInfoPlist: String?
|
||||
@ -1600,7 +1617,7 @@ extension Platform {
|
||||
/// - returns: `true` for platforms that the app store requires simulator slices to be stripped.
|
||||
public var requiresSimulatorStripping: Bool {
|
||||
switch self {
|
||||
case .iOS, .tvOS, .watchOS, .visionOS:
|
||||
case .auto, .iOS, .tvOS, .watchOS, .visionOS:
|
||||
return true
|
||||
case .macOS:
|
||||
return false
|
||||
|
@ -41,16 +41,63 @@ extension Project {
|
||||
|
||||
public func getTargetBuildSettings(target: Target, config: Config) -> BuildSettings {
|
||||
var buildSettings = BuildSettings()
|
||||
|
||||
|
||||
// list of supported destination sorted by priority
|
||||
let specSupportedDestinations = target.supportedDestinations?.sorted(by: { $0.priority < $1.priority }) ?? []
|
||||
|
||||
if options.settingPresets.applyTarget {
|
||||
buildSettings += SettingsPresetFile.platform(target.platform).getBuildSettings()
|
||||
let platform: Platform
|
||||
|
||||
if target.platform == .auto,
|
||||
let firstDestination = specSupportedDestinations.first,
|
||||
let firstDestinationPlatform = Platform(rawValue: firstDestination.rawValue) {
|
||||
|
||||
platform = firstDestinationPlatform
|
||||
} else {
|
||||
platform = target.platform
|
||||
}
|
||||
|
||||
buildSettings += SettingsPresetFile.platform(platform).getBuildSettings()
|
||||
buildSettings += SettingsPresetFile.product(target.type).getBuildSettings()
|
||||
buildSettings += SettingsPresetFile.productPlatform(target.type, target.platform).getBuildSettings()
|
||||
buildSettings += SettingsPresetFile.productPlatform(target.type, platform).getBuildSettings()
|
||||
|
||||
if target.platform == .auto {
|
||||
// this fix is necessary because the platform preset overrides the original value
|
||||
buildSettings["SDKROOT"] = Platform.auto.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if !specSupportedDestinations.isEmpty {
|
||||
var supportedPlatforms: [String] = []
|
||||
var targetedDeviceFamily: [String] = []
|
||||
|
||||
for supportedDestination in specSupportedDestinations {
|
||||
let supportedPlatformBuildSettings = SettingsPresetFile.supportedDestination(supportedDestination).getBuildSettings()
|
||||
buildSettings += supportedPlatformBuildSettings
|
||||
|
||||
if let value = supportedPlatformBuildSettings?["SUPPORTED_PLATFORMS"] as? String {
|
||||
supportedPlatforms += value.components(separatedBy: " ")
|
||||
}
|
||||
if let value = supportedPlatformBuildSettings?["TARGETED_DEVICE_FAMILY"] as? String {
|
||||
targetedDeviceFamily += value.components(separatedBy: ",")
|
||||
}
|
||||
}
|
||||
|
||||
buildSettings["SUPPORTED_PLATFORMS"] = supportedPlatforms.joined(separator: " ")
|
||||
buildSettings["TARGETED_DEVICE_FAMILY"] = targetedDeviceFamily.joined(separator: ",")
|
||||
}
|
||||
|
||||
// apply custom platform version
|
||||
if let version = target.deploymentTarget {
|
||||
buildSettings[target.platform.deploymentTargetSetting] = version.deploymentTarget
|
||||
if !specSupportedDestinations.isEmpty {
|
||||
for supportedDestination in specSupportedDestinations {
|
||||
if let platform = Platform(rawValue: supportedDestination.rawValue) {
|
||||
buildSettings[platform.deploymentTargetSetting] = version.deploymentTarget
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buildSettings[target.platform.deploymentTargetSetting] = version.deploymentTarget
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent setting presets from overrwriting settings in target xcconfig files
|
||||
@ -205,7 +252,7 @@ extension SettingsPresetFile {
|
||||
|
||||
guard let settingsPath = possibleSettingsPaths.first(where: { $0.exists }) else {
|
||||
switch self {
|
||||
case .base, .config, .platform:
|
||||
case .base, .config, .platform, .supportedDestination:
|
||||
print("No \"\(name)\" settings found")
|
||||
case .product, .productPlatform:
|
||||
break
|
||||
|
@ -5,6 +5,7 @@ import XcodeProj
|
||||
public enum SettingsPresetFile {
|
||||
case config(ConfigType)
|
||||
case platform(Platform)
|
||||
case supportedDestination(SupportedDestination)
|
||||
case product(PBXProductType)
|
||||
case productPlatform(PBXProductType, Platform)
|
||||
case base
|
||||
@ -13,6 +14,7 @@ public enum SettingsPresetFile {
|
||||
switch self {
|
||||
case let .config(config): return "Configs/\(config.rawValue)"
|
||||
case let .platform(platform): return "Platforms/\(platform.rawValue)"
|
||||
case let .supportedDestination(supportedDestination): return "SupportedDestinations/\(supportedDestination.rawValue)"
|
||||
case let .product(product): return "Products/\(product.name)"
|
||||
case let .productPlatform(product, platform): return "Product_Platform/\(product.name)_\(platform.rawValue)"
|
||||
case .base: return "base"
|
||||
@ -23,6 +25,7 @@ public enum SettingsPresetFile {
|
||||
switch self {
|
||||
case let .config(config): return "\(config.rawValue) config"
|
||||
case let .platform(platform): return platform.rawValue
|
||||
case let .supportedDestination(supportedDestination): return supportedDestination.rawValue
|
||||
case let .product(product): return product.name
|
||||
case let .productPlatform(product, platform): return "\(platform) \(product)"
|
||||
case .base: return "base"
|
||||
|
@ -109,7 +109,23 @@ class SourceGenerator {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func makeDestinationFilters(for path: Path, with filters: [SupportedDestination]?, or inferDestinationFiltersByPath: Bool?) -> [String]? {
|
||||
if let filters = filters, !filters.isEmpty {
|
||||
return filters.map { $0.string }
|
||||
} else if inferDestinationFiltersByPath == true {
|
||||
for supportedDestination in SupportedDestination.allCases {
|
||||
let regex1 = try? NSRegularExpression(pattern: "\\/\(supportedDestination)\\/", options: .caseInsensitive)
|
||||
let regex2 = try? NSRegularExpression(pattern: "\\_\(supportedDestination)\\.swift$", options: .caseInsensitive)
|
||||
|
||||
if regex1?.isMatch(to: path.string) == true || regex2?.isMatch(to: path.string) == true {
|
||||
return [supportedDestination.string]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateSourceFile(targetType: PBXProductType, targetSource: TargetSource, path: Path, fileReference: PBXFileElement? = nil, buildPhases: [Path: BuildPhaseSpec]) -> SourceFile {
|
||||
let fileReference = fileReference ?? fileReferencesByPath[path.string.lowercased()]!
|
||||
var settings: [String: Any] = [:]
|
||||
@ -174,8 +190,10 @@ class SourceGenerator {
|
||||
if chosenBuildPhase == .resources && !assetTags.isEmpty {
|
||||
settings["ASSET_TAGS"] = assetTags
|
||||
}
|
||||
|
||||
let buildFile = PBXBuildFile(file: fileReference, settings: settings.isEmpty ? nil : settings)
|
||||
|
||||
let platforms = makeDestinationFilters(for: path, with: targetSource.destinationFilters, or: targetSource.inferDestinationFiltersByPath)
|
||||
|
||||
let buildFile = PBXBuildFile(file: fileReference, settings: settings.isEmpty ? nil : settings, platformFilters: platforms)
|
||||
return SourceFile(
|
||||
path: path,
|
||||
fileReference: fileReference,
|
||||
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>TestApp</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,10 @@
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct MyAppApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
Image(systemName: "globe")
|
||||
.imageScale(.large)
|
||||
.foregroundColor(.accentColor)
|
||||
Text("Hello, world! on iOS")
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
Image(systemName: "house")
|
||||
.imageScale(.large)
|
||||
.foregroundColor(.accentColor)
|
||||
Text("Hello, world! tvOS")
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -0,0 +1 @@
|
||||
import Foundation
|
@ -41,6 +41,7 @@
|
||||
0F99AECCB4691803C791CDCE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2FC2A8A829CE71B1CF415FF7 /* Main.storyboard */; };
|
||||
15129B8D9ED000BDA1FEEC27 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23A2F16890ECF2EE3FED72AE /* AppDelegate.swift */; };
|
||||
1551370B0ACAC632E15C853B /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF47010E7368583405AA50CB /* SwiftyJSON.framework */; };
|
||||
1B485D6584C3B47AC58831C6 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18722C61B05FFF4CC63D5755 /* ContentView.swift */; platformFilters = (tvos, ); };
|
||||
1BC891D89980D82738D963F3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74FBDFA5CB063F6001AD8ACD /* Main.storyboard */; };
|
||||
1E03FC7312293997599C6435 /* Empty.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 068EDF47F0B087F6A4052AC0 /* Empty.h */; };
|
||||
1E2A4D61E96521FF7123D7B0 /* XPC Service.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = 22237B8EBD9E6BE8EBC8735F /* XPC Service.xpc */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@ -56,6 +57,7 @@
|
||||
21CA04F29CD0DEB0DD27B808 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C5AC2545AE4D4F7F44E2E9B /* Result.framework */; };
|
||||
262891CCD5F74316610437FA /* Framework2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EF21DF245F66BEF5446AAEF /* Framework2.framework */; platformFilter = ios; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
265B6A05C0198FD2EB485173 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93C033648A37D95027845BD3 /* main.swift */; };
|
||||
2698ED273D0A5820B28CAD20 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D52EC9AA9FFD3B690C355068 /* LaunchScreen.storyboard */; platformFilters = (ios, ); };
|
||||
2730C6D0A35AED4ADD6EDF17 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0704B6CAFBB53E0EBB08F6B3 /* ViewController.swift */; settings = {COMPILER_FLAGS = "-Werror"; }; };
|
||||
28A96EBC76D53817AABDA91C /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 8AF20308873AEEEC4D8C45D1 /* Settings.bundle */; };
|
||||
2A5356FCC03EE312F1738C61 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09B82F603D981398F38D762E /* AppDelegate.swift */; };
|
||||
@ -70,6 +72,7 @@
|
||||
339578307B9266AB3D7722D9 /* File2.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC56891DA7446EAC8C2F27EB /* File2.swift */; };
|
||||
3535891EC86283BB5064E7E1 /* Headers in Headers */ = {isa = PBXBuildFile; fileRef = 2E1E747C7BC434ADB80CC269 /* Headers */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3788E1382B38DF4ACE3D2BB1 /* MyFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A58A16491CDDF968B0D56DE /* MyFramework.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3A3BA9F91994D8B472C71F04 /* Swinject in Frameworks */ = {isa = PBXBuildFile; platformFilters = (tvos, ); productRef = C7F9B7EDE85527EFEA85D46D /* Swinject */; };
|
||||
3BBCA6F76E5F212E9C55FB78 /* BundleX.bundle in Copy Bundle Resources */ = {isa = PBXBuildFile; fileRef = 45C12576F5AA694DD0CE2132 /* BundleX.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
3C5134EE524310ACF7B7CD6E /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CAF6C55B555E3E1352645B6 /* ExtensionDelegate.swift */; };
|
||||
3DF22C477446669094AC7C8C /* ExternalTarget.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F6ADE654A3459AFDA2CC0CD3 /* ExternalTarget.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@ -148,6 +151,7 @@
|
||||
B18C121B0A4D43ED8149D8E2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 79325B44B19B83EC6CEDBCC5 /* LaunchScreen.storyboard */; };
|
||||
B20617116B230DED1F7AF5E5 /* libStaticLibrary_ObjC.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B221F5A689AD7D3AD52F56B8 /* libStaticLibrary_ObjC.a */; };
|
||||
B2D43A31C184E34EF9CB743C /* Framework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8A9274BE42A03DC5DA1FAD04 /* Framework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
B358AB913543E62237FCC4E3 /* MyAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15A4363D659A58DA835DE8BA /* MyAppApp.swift */; };
|
||||
B47F2629BFE5853767C8BB5E /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FDB2B6A77D39CD5602F2125F /* Contacts.framework */; };
|
||||
B49D3A51787E362DE4D0E78A /* SomeXPCService.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = 70A8E15C81E454DC950C59F0 /* SomeXPCService.xpc */; };
|
||||
B502EF8F7605CBD038298F23 /* CrossOverlayFramework.swiftcrossimport in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8DD7A61B07AD2F91BDECC255 /* CrossOverlayFramework.swiftcrossimport */; };
|
||||
@ -163,6 +167,7 @@
|
||||
C836F09B677937EFF69B1FCE /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C934C1F7A68CCD0AB6B38478 /* NotificationController.swift */; };
|
||||
C88598A49087A212990F4E8B /* ResourceFolder in Resources */ = {isa = PBXBuildFile; fileRef = 6B1603BA83AA0C7B94E45168 /* ResourceFolder */; };
|
||||
CAE18A2194B57C830A297F83 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6680EFE4E908CDBDCE405C8 /* main.swift */; };
|
||||
CAF8470C7F1BF207DBE6AEE3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEEFDE76B5FEC833403C0869 /* ContentView.swift */; platformFilters = (ios, ); };
|
||||
CCA17097382757012B58C17C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1BC32A813B80A53962A1F365 /* Assets.xcassets */; };
|
||||
D058D241BDF5FB0C919BBECA /* CrossOverlayFramework.swiftcrossimport in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8DD7A61B07AD2F91BDECC255 /* CrossOverlayFramework.swiftcrossimport */; };
|
||||
D5458D67C3596943114C3205 /* Standalone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F5BD97AF0F94A15A5B7DDB7 /* Standalone.swift */; };
|
||||
@ -738,8 +743,10 @@
|
||||
108BB29172D27BE3BD1E7F35 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
13EEAB58665D79C15184D9D0 /* App_iOS_UITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = App_iOS_UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
148B7C933698BCC4F1DBA979 /* XPC_Service.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPC_Service.m; sourceTree = "<group>"; };
|
||||
15A4363D659A58DA835DE8BA /* MyAppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAppApp.swift; sourceTree = "<group>"; };
|
||||
16AA52945B70B1BF9E246350 /* FilterDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDataProvider.swift; sourceTree = "<group>"; };
|
||||
16D662EE577E4CD6AFF39D66 /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = config.xcconfig; sourceTree = "<group>"; };
|
||||
18722C61B05FFF4CC63D5755 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
187E665975BB5611AF0F27E1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
1BC32A813B80A53962A1F365 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
1D0C79A8C750EC0DE748C463 /* StaticLibrary_ObjC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StaticLibrary_ObjC.m; sourceTree = "<group>"; };
|
||||
@ -766,6 +773,7 @@
|
||||
3ED831531AA349CCC19B258B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
3EF21DF245F66BEF5446AAEF /* Framework2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework2.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3FC04772130400920D68A167 /* App_Clip_Tests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = App_Clip_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
407C3F0009FDCE5B1B7DC2A8 /* App_supportedDestinations.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = App_supportedDestinations.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
40863AE6202CFCD0529D8438 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
41FC82ED1C4C3B7B3D7B2FB7 /* Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
432E2C071A4B6B3757BEA13E /* Driver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Driver.cpp; sourceTree = "<group>"; };
|
||||
@ -830,6 +838,7 @@
|
||||
AAA49985DFFE797EE8416887 /* inputList.xcfilelist */ = {isa = PBXFileReference; lastKnownFileType = text.xcfilelist; path = inputList.xcfilelist; sourceTree = "<group>"; };
|
||||
AB055761199DF36DB0C629A6 /* Framework2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Framework2.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
AEBCA8CFF769189C0D52031E /* App_iOS.xctestplan */ = {isa = PBXFileReference; path = App_iOS.xctestplan; sourceTree = "<group>"; };
|
||||
AEEFDE76B5FEC833403C0869 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
B17B8D9C9B391332CD176A35 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LocalizedStoryboard.storyboard; sourceTree = "<group>"; };
|
||||
B198242976C3395E31FE000A /* MessagesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesViewController.swift; sourceTree = "<group>"; };
|
||||
B1C33BB070583BE3B0EC0E68 /* App_iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = App_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@ -855,6 +864,7 @@
|
||||
D21BB1B6FA5A025305B223BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
D296BB7355994040E197A1EE /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = "<group>"; };
|
||||
D51CC8BCCBD68A90E90A3207 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D52EC9AA9FFD3B690C355068 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
D629E142AB87C681D4EC90F7 /* iMessageExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = iMessageExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D6C89D80B5458D8929F5C127 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
D70BE0C05E5779A077793BE6 /* Model 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Model 2.xcdatamodel"; sourceTree = "<group>"; };
|
||||
@ -909,6 +919,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
36418B6CABA06BA9B206556E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3A3BA9F91994D8B472C71F04 /* Swinject in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
5EFF61D0A49AA8EABD72DF44 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -1102,6 +1120,7 @@
|
||||
0D039F2E62354C7C8E283BE6 /* App_iOS_UITests */,
|
||||
EE78B4FBD0137D1975C47D76 /* App_macOS */,
|
||||
6DE1C805DC13547F27FD86C6 /* App_macOS_Tests */,
|
||||
D27117FBA2920408002F0B4C /* App_supportedDestinations */,
|
||||
BAE6C12745737019DC9E98BF /* App_watchOS */,
|
||||
795B8D70B674C850B57DD39D /* App_watchOS Extension */,
|
||||
6DBE0EE90642BB3F6E58AD43 /* Configs */,
|
||||
@ -1194,6 +1213,23 @@
|
||||
path = UnderFileGroup;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
69C61547C081D04364A5DE42 /* Storyboards */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D52EC9AA9FFD3B690C355068 /* LaunchScreen.storyboard */,
|
||||
);
|
||||
name = Storyboards;
|
||||
path = Storyboards;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6A90AFD865B13D26DA108CAB /* tvOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
18722C61B05FFF4CC63D5755 /* ContentView.swift */,
|
||||
);
|
||||
path = tvOS;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6BD8F0932CCAD4BBE752866B /* App_Clip_UITests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1266,6 +1302,17 @@
|
||||
path = "XPC Service";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
85FEBB7D2103B020423407A2 /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9E5249A284275B0CDF4E5DDA /* iOS */,
|
||||
6A90AFD865B13D26DA108CAB /* tvOS */,
|
||||
15A4363D659A58DA835DE8BA /* MyAppApp.swift */,
|
||||
);
|
||||
name = Sources;
|
||||
path = Sources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8CFD8AD4820FAB9265663F92 /* Tool */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1301,6 +1348,14 @@
|
||||
path = StandaloneFiles;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9E5249A284275B0CDF4E5DDA /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
AEEFDE76B5FEC833403C0869 /* ContentView.swift */,
|
||||
);
|
||||
path = iOS;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9EDF27BB8A57733E6639D36D /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1343,6 +1398,7 @@
|
||||
B1C33BB070583BE3B0EC0E68 /* App_iOS.app */,
|
||||
0B9D98D935F2C69A1F5BA539 /* App_macOS_Tests.xctest */,
|
||||
33F6DCDC37D2E66543D4965D /* App_macOS.app */,
|
||||
407C3F0009FDCE5B1B7DC2A8 /* App_supportedDestinations.app */,
|
||||
0D09D243DBCF9D32E239F1E8 /* App_watchOS Extension.appex */,
|
||||
A680BE9F68A255B0FB291AE6 /* App_watchOS.app */,
|
||||
84317819C92F78425870E483 /* BundleX.bundle */,
|
||||
@ -1432,6 +1488,15 @@
|
||||
path = StaticLibrary_Swift;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D27117FBA2920408002F0B4C /* App_supportedDestinations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
85FEBB7D2103B020423407A2 /* Sources */,
|
||||
69C61547C081D04364A5DE42 /* Storyboards */,
|
||||
);
|
||||
path = App_supportedDestinations;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D557819B1EE5B42A0A3DD4D1 /* tvOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2205,6 +2270,26 @@
|
||||
productReference = 7D700FA699849D2F95216883 /* EntitledApp.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
C0570E2FB50D830D8D423396 /* App_supportedDestinations */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 5EC789CCE1928A4CDA00DD1E /* Build configuration list for PBXNativeTarget "App_supportedDestinations" */;
|
||||
buildPhases = (
|
||||
CF8BAE171BAAFB2E5DDB9C19 /* Sources */,
|
||||
97119CD9F01D9A9522EF3526 /* Resources */,
|
||||
36418B6CABA06BA9B206556E /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = App_supportedDestinations;
|
||||
packageProductDependencies = (
|
||||
C7F9B7EDE85527EFEA85D46D /* Swinject */,
|
||||
);
|
||||
productName = App_supportedDestinations;
|
||||
productReference = 407C3F0009FDCE5B1B7DC2A8 /* App_supportedDestinations.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
C7F90FD0FAAF232B3E015D38 /* CrossOverlayFramework_watchOS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C483BD5456B09C276DE6EFC1 /* Build configuration list for PBXNativeTarget "CrossOverlayFramework_watchOS" */;
|
||||
@ -2415,6 +2500,7 @@
|
||||
F674B2CFC4738EEC49BAD0DA /* App_iOS_UITests */,
|
||||
020A320BB3736FCDE6CC4E70 /* App_macOS */,
|
||||
71E2BDAC4B8E8FC2BBF75C55 /* App_macOS_Tests */,
|
||||
C0570E2FB50D830D8D423396 /* App_supportedDestinations */,
|
||||
208179651927D1138D19B5AD /* App_watchOS */,
|
||||
307AE3FA155FFD09B74AE351 /* App_watchOS Extension */,
|
||||
DA40AB367B606CCE2FDD398D /* BundleX */,
|
||||
@ -2520,6 +2606,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97119CD9F01D9A9522EF3526 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2698ED273D0A5820B28CAD20 /* LaunchScreen.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
AA12B5909FEE45016F469C78 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -3000,6 +3094,16 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CF8BAE171BAAFB2E5DDB9C19 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CAF8470C7F1BF207DBE6AEE3 /* ContentView.swift in Sources */,
|
||||
1B485D6584C3B47AC58831C6 /* ContentView.swift in Sources */,
|
||||
B358AB913543E62237FCC4E3 /* MyAppApp.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D1F422E9C4DD531AA88418C9 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -4108,6 +4212,26 @@
|
||||
};
|
||||
name = "Staging Debug";
|
||||
};
|
||||
24CFBB3ABB9E14E85035B892 /* Production Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = App_supportedDestinations/Info.generated.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.test.TestApp;
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
};
|
||||
name = "Production Debug";
|
||||
};
|
||||
2569D399CA3C4828EF87AD78 /* Test Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -4815,6 +4939,26 @@
|
||||
};
|
||||
name = "Production Release";
|
||||
};
|
||||
4C11A3E7EA48B5FB556D4614 /* Staging Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = App_supportedDestinations/Info.generated.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.test.TestApp;
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
};
|
||||
name = "Staging Debug";
|
||||
};
|
||||
4D5DC2028DC046B8AF0B9B83 /* Test Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -5558,6 +5702,26 @@
|
||||
};
|
||||
name = "Staging Debug";
|
||||
};
|
||||
75B3C83C754AA9C12ABF5E54 /* Staging Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = App_supportedDestinations/Info.generated.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.test.TestApp;
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
};
|
||||
name = "Staging Release";
|
||||
};
|
||||
77B8B41EBA5D778EB3AF89DC /* Production Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -5757,6 +5921,26 @@
|
||||
};
|
||||
name = "Production Release";
|
||||
};
|
||||
7F3F6A813F8B126258780E8D /* Production Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = App_supportedDestinations/Info.generated.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.test.TestApp;
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
};
|
||||
name = "Production Release";
|
||||
};
|
||||
7F86E00770E76CA3412A03BD /* Staging Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -6288,6 +6472,26 @@
|
||||
};
|
||||
name = "Staging Debug";
|
||||
};
|
||||
98EE00BF46FAE62F16C25E9C /* Test Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = App_supportedDestinations/Info.generated.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.test.TestApp;
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
};
|
||||
name = "Test Release";
|
||||
};
|
||||
9A891313A139893990989BDD /* Test Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -6469,6 +6673,26 @@
|
||||
};
|
||||
name = "Production Debug";
|
||||
};
|
||||
A4015127D0A01FE60CF5621B /* Test Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = App_supportedDestinations/Info.generated.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.test.TestApp;
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator appletvos appletvsimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
||||
};
|
||||
name = "Test Debug";
|
||||
};
|
||||
A59DDFBFCF18C44A993CFB00 /* Test Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@ -8721,6 +8945,19 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "Production Debug";
|
||||
};
|
||||
5EC789CCE1928A4CDA00DD1E /* Build configuration list for PBXNativeTarget "App_supportedDestinations" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
24CFBB3ABB9E14E85035B892 /* Production Debug */,
|
||||
7F3F6A813F8B126258780E8D /* Production Release */,
|
||||
4C11A3E7EA48B5FB556D4614 /* Staging Debug */,
|
||||
75B3C83C754AA9C12ABF5E54 /* Staging Release */,
|
||||
A4015127D0A01FE60CF5621B /* Test Debug */,
|
||||
98EE00BF46FAE62F16C25E9C /* Test Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = "Production Debug";
|
||||
};
|
||||
62C52A55CB8D3BD9A055FD14 /* Build configuration list for PBXNativeTarget "App_macOS_Tests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
@ -9125,6 +9362,11 @@
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
C7F9B7EDE85527EFEA85D46D /* Swinject */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 4EDA79334592CBBA0E507AD2 /* XCRemoteSwiftPackageReference "Swinject" */;
|
||||
productName = Swinject;
|
||||
};
|
||||
D7917D10F77DA9D69937D493 /* Swinject */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 4EDA79334592CBBA0E507AD2 /* XCRemoteSwiftPackageReference "Swinject" */;
|
||||
|
@ -232,6 +232,29 @@ targets:
|
||||
properties:
|
||||
com.apple.security.application-groups: group.com.app
|
||||
|
||||
App_supportedDestinations:
|
||||
type: application
|
||||
supportedDestinations: [iOS, tvOS]
|
||||
info:
|
||||
path: App_supportedDestinations/Info.generated.plist
|
||||
properties:
|
||||
CFBundleDisplayName: "TestApp"
|
||||
CFBundleVersion: "1.0.0"
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.test.TestApp
|
||||
sources:
|
||||
- path: App_supportedDestinations/Sources
|
||||
group: App_supportedDestinations
|
||||
inferDestinationFiltersByPath: true
|
||||
- path: App_supportedDestinations/Storyboards
|
||||
group: App_supportedDestinations
|
||||
destinationFilters: [iOS]
|
||||
dependencies:
|
||||
- package: Swinject
|
||||
product: Swinject
|
||||
destinationFilters: [tvOS]
|
||||
|
||||
App_watchOS:
|
||||
type: application.watchapp2
|
||||
platform: watchOS
|
||||
@ -482,7 +505,7 @@ schemes:
|
||||
enableGPUFrameCaptureMode: "disabled"
|
||||
enableGPUValidationMode: "disabled"
|
||||
storeKitConfiguration: "App_iOS/Configuration.storekit"
|
||||
macroExpansion: App_iOS
|
||||
macroExpansion: App_iOS
|
||||
test:
|
||||
gatherCoverageData: true
|
||||
targets:
|
||||
|
@ -73,12 +73,23 @@ class ProjectSpecTests: XCTestCase {
|
||||
describe {
|
||||
|
||||
$0.it("has correct build setting") {
|
||||
try expect(Platform.auto.deploymentTargetSetting) == ""
|
||||
try expect(Platform.iOS.deploymentTargetSetting) == "IPHONEOS_DEPLOYMENT_TARGET"
|
||||
try expect(Platform.tvOS.deploymentTargetSetting) == "TVOS_DEPLOYMENT_TARGET"
|
||||
try expect(Platform.watchOS.deploymentTargetSetting) == "WATCHOS_DEPLOYMENT_TARGET"
|
||||
try expect(Platform.macOS.deploymentTargetSetting) == "MACOSX_DEPLOYMENT_TARGET"
|
||||
try expect(Platform.visionOS.deploymentTargetSetting) == "XROS_DEPLOYMENT_TARGET"
|
||||
}
|
||||
|
||||
$0.it("has correct sdk root") {
|
||||
try expect(Platform.auto.sdkRoot) == "auto"
|
||||
try expect(Platform.iOS.sdkRoot) == "iphoneos"
|
||||
try expect(Platform.tvOS.sdkRoot) == "appletvos"
|
||||
try expect(Platform.watchOS.sdkRoot) == "watchos"
|
||||
try expect(Platform.macOS.sdkRoot) == "macosx"
|
||||
try expect(Platform.visionOS.sdkRoot) == "xros"
|
||||
}
|
||||
|
||||
$0.it("parses version correctly") {
|
||||
try expect(Version.parse("2").deploymentTarget) == "2.0"
|
||||
try expect(Version.parse("2.0").deploymentTarget) == "2.0"
|
||||
@ -178,7 +189,59 @@ class ProjectSpecTests: XCTestCase {
|
||||
|
||||
try expectNoValidationError(project, .duplicateDependencies(target: "target1", dependencyReference: "package1"))
|
||||
}
|
||||
|
||||
|
||||
$0.it("unexpected supported destinations for watch app") {
|
||||
var project = baseProject
|
||||
project.targets = [
|
||||
Target(
|
||||
name: "target1",
|
||||
type: .application,
|
||||
platform: .watchOS,
|
||||
supportedDestinations: [.macOS]
|
||||
)
|
||||
]
|
||||
try expectValidationError(project, .unexpectedTargetPlatformForSupportedDestinations(target: "target1", platform: .watchOS))
|
||||
}
|
||||
|
||||
$0.it("multiple definitions of mac platform in supported destinations") {
|
||||
var project = baseProject
|
||||
project.targets = [
|
||||
Target(
|
||||
name: "target1",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
supportedDestinations: [.macOS, .macCatalyst]
|
||||
)
|
||||
]
|
||||
try expectValidationError(project, .multipleMacPlatformsInSupportedDestinations(target: "target1"))
|
||||
}
|
||||
|
||||
$0.it("invalid target platform for macCatalyst supported destinations") {
|
||||
var project = baseProject
|
||||
project.targets = [
|
||||
Target(
|
||||
name: "target1",
|
||||
type: .application,
|
||||
platform: .tvOS,
|
||||
supportedDestinations: [.tvOS, .macCatalyst]
|
||||
)
|
||||
]
|
||||
try expectValidationError(project, .invalidTargetPlatformForSupportedDestinations(target: "target1"))
|
||||
}
|
||||
|
||||
$0.it("missing target platform in supported destinations") {
|
||||
var project = baseProject
|
||||
project.targets = [
|
||||
Target(
|
||||
name: "target1",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
supportedDestinations: [.tvOS]
|
||||
)
|
||||
]
|
||||
try expectValidationError(project, .missingTargetPlatformInSupportedDestinations(target: "target1", platform: .iOS))
|
||||
}
|
||||
|
||||
$0.it("allows non-existent configurations") {
|
||||
var project = baseProject
|
||||
project.options = SpecOptions(disabledValidations: [.missingConfigs])
|
||||
|
@ -604,10 +604,66 @@ class SpecLoadingTests: XCTestCase {
|
||||
target_iOS.deploymentTarget = Version(major: 9, minor: 0, patch: 0)
|
||||
target_tvOS.deploymentTarget = Version(major: 10, minor: 0, patch: 0)
|
||||
|
||||
try expect(project.targets.count) == 2
|
||||
try expect(project.targets) == [target_iOS, target_tvOS]
|
||||
}
|
||||
|
||||
$0.it("parses no platform fallbacks to auto if we are using supported destinations") {
|
||||
let targetDictionary: [String: Any] = [
|
||||
"type": "framework",
|
||||
"supportedDestinations": ["iOS", "tvOS"]
|
||||
]
|
||||
|
||||
let project = try getProjectSpec(["targets": ["Framework": targetDictionary]])
|
||||
let target = Target(name: "Framework", type: .framework, platform: .auto)
|
||||
|
||||
try expect(project.targets) == [target]
|
||||
}
|
||||
|
||||
$0.it("parses no platform fails if we are not using supported destinations") {
|
||||
let expectedError = SpecParsingError.unknownTargetPlatform("")
|
||||
|
||||
let projectDictionary: [String: Any] = [
|
||||
"name": "test",
|
||||
"targets": ["target1": [
|
||||
"type": "application"
|
||||
] as [String : Any]]
|
||||
]
|
||||
|
||||
try expectError(expectedError) {
|
||||
_ = try Project(jsonDictionary: projectDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
$0.it("parses supported destinations with macCatalyst but not iOS, we add iOS") {
|
||||
let targetDictionary: [String: Any] = [
|
||||
"type": "framework",
|
||||
"supportedDestinations": ["macCatalyst"]
|
||||
]
|
||||
|
||||
let project = try getProjectSpec(["targets": ["Framework": targetDictionary]])
|
||||
let target = Target(name: "Framework", type: .framework, platform: .auto)
|
||||
|
||||
try expect(project.targets) == [target]
|
||||
try expect(project.targets.first?.supportedDestinations) == [.macCatalyst, .iOS]
|
||||
}
|
||||
|
||||
$0.it("invalid target platform because platform is an array and supported destinations is in use") {
|
||||
let expectedError = SpecParsingError.invalidTargetPlatformAsArray
|
||||
|
||||
let projectDictionary: [String: Any] = [
|
||||
"name": "test",
|
||||
"targets": ["target1": [
|
||||
"type": "application",
|
||||
"platform": ["iOS", "tvOS"],
|
||||
"supportedDestinations": ["iOS", "tvOS"]
|
||||
] as [String : Any]]
|
||||
]
|
||||
|
||||
try expectError(expectedError) {
|
||||
_ = try Project(jsonDictionary: projectDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
$0.it("parses target templates") {
|
||||
|
||||
let targetDictionary: [String: Any] = [
|
||||
|
@ -335,7 +335,156 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
try expect(targetConfig.buildSettings["WATCHOS_DEPLOYMENT_TARGET"] as? String) == "2.0"
|
||||
try expect(targetConfig.buildSettings["TVOS_DEPLOYMENT_TARGET"]).beNil()
|
||||
}
|
||||
|
||||
|
||||
$0.it("supportedPlaforms merges settings - iOS, tvOS") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.tvOS, .iOS])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "iphoneos iphonesimulator appletvos appletvsimulator"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "1,2,3"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == true
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == true
|
||||
|
||||
try expect(targetConfig1.buildSettings["LD_RUNPATH_SEARCH_PATHS"] as? [String]) == ["$(inherited)", "@executable_path/Frameworks"]
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "AppIcon"
|
||||
try expect(targetConfig1.buildSettings["CODE_SIGN_IDENTITY"] as? String) == "iPhone Developer"
|
||||
}
|
||||
|
||||
$0.it("supportedPlaforms merges settings - iOS, visionOS") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.visionOS, .iOS])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "iphoneos iphonesimulator xros xrsimulator"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "1,2,7"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == true
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
|
||||
try expect(targetConfig1.buildSettings["LD_RUNPATH_SEARCH_PATHS"] as? [String]) == ["$(inherited)", "@executable_path/Frameworks"]
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "AppIcon"
|
||||
try expect(targetConfig1.buildSettings["CODE_SIGN_IDENTITY"] as? String) == "iPhone Developer"
|
||||
}
|
||||
|
||||
$0.it("supportedPlaforms merges settings - iOS, tvOS, macOS") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.iOS, .tvOS, .macOS])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "iphoneos iphonesimulator appletvos appletvsimulator macosx"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "1,2,3"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == true
|
||||
|
||||
try expect(targetConfig1.buildSettings["LD_RUNPATH_SEARCH_PATHS"] as? [String]) == ["$(inherited)", "@executable_path/Frameworks"]
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "AppIcon"
|
||||
try expect(targetConfig1.buildSettings["CODE_SIGN_IDENTITY"] as? String) == "iPhone Developer"
|
||||
}
|
||||
|
||||
$0.it("supportedPlaforms merges settings - iOS, tvOS, macCatalyst") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.iOS, .tvOS, .macCatalyst])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "iphoneos iphonesimulator appletvos appletvsimulator"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "1,2,3"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == true
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == true
|
||||
|
||||
try expect(targetConfig1.buildSettings["LD_RUNPATH_SEARCH_PATHS"] as? [String]) == ["$(inherited)", "@executable_path/Frameworks"]
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "AppIcon"
|
||||
try expect(targetConfig1.buildSettings["CODE_SIGN_IDENTITY"] as? String) == "iPhone Developer"
|
||||
}
|
||||
|
||||
$0.it("supportedPlaforms merges settings - iOS, macOS") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.iOS, .macOS])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "iphoneos iphonesimulator macosx"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "1,2"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == true
|
||||
|
||||
try expect(targetConfig1.buildSettings["LD_RUNPATH_SEARCH_PATHS"] as? [String]) == ["$(inherited)", "@executable_path/Frameworks"]
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "AppIcon"
|
||||
try expect(targetConfig1.buildSettings["CODE_SIGN_IDENTITY"] as? String) == "iPhone Developer"
|
||||
}
|
||||
|
||||
$0.it("supportedPlaforms merges settings - tvOS, macOS") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.tvOS, .macOS])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "appletvos appletvsimulator macosx"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "3"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
|
||||
try expect(targetConfig1.buildSettings["LD_RUNPATH_SEARCH_PATHS"] as? [String]) == ["$(inherited)", "@executable_path/Frameworks"]
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "App Icon & Top Shelf Image"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME"] as? String) == "LaunchImage"
|
||||
}
|
||||
|
||||
$0.it("supportedPlaforms merges settings - visionOS, macOS") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.visionOS, .macOS])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "xros xrsimulator macosx"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "7"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "AppIcon"
|
||||
}
|
||||
|
||||
$0.it("supportedPlaforms merges settings - iOS, macCatalyst") {
|
||||
let target = Target(name: "Target", type: .application, platform: .auto, supportedDestinations: [.iOS, .macCatalyst])
|
||||
let project = Project(name: "", targets: [target])
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let targetConfig1 = try unwrap(pbxProject.nativeTargets.first?.buildConfigurationList?.buildConfigurations.first)
|
||||
|
||||
try expect(targetConfig1.buildSettings["SUPPORTED_PLATFORMS"] as? String) == "iphoneos iphonesimulator"
|
||||
try expect(targetConfig1.buildSettings["TARGETED_DEVICE_FAMILY"] as? String) == "1,2"
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MACCATALYST"] as? Bool) == true
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == false
|
||||
try expect(targetConfig1.buildSettings["SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD"] as? Bool) == true
|
||||
|
||||
try expect(targetConfig1.buildSettings["LD_RUNPATH_SEARCH_PATHS"] as? [String]) == ["$(inherited)", "@executable_path/Frameworks"]
|
||||
try expect(targetConfig1.buildSettings["SDKROOT"] as? String) == "auto"
|
||||
try expect(targetConfig1.buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] as? String) == "AppIcon"
|
||||
try expect(targetConfig1.buildSettings["CODE_SIGN_IDENTITY"] as? String) == "iPhone Developer"
|
||||
}
|
||||
|
||||
$0.it("generates dependencies") {
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
|
||||
@ -1066,7 +1215,108 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
try expect(app2OtherLinkerSettings.contains("-ObjC")) == false
|
||||
try expect(app3OtherLinkerSettings.contains("-ObjC")) == true
|
||||
}
|
||||
|
||||
|
||||
$0.it("filter sources with inferDestinationFiltersByPath") {
|
||||
let sourceFiles = TargetSource(path: "App_supportedDestinations/TestResources", inferDestinationFiltersByPath: true)
|
||||
|
||||
let target = Target(
|
||||
name: "test",
|
||||
type: .application,
|
||||
platform: .auto,
|
||||
sources: [sourceFiles],
|
||||
dependencies: []
|
||||
)
|
||||
|
||||
let project = Project(
|
||||
basePath: fixturePath + "TestProject",
|
||||
name: "test",
|
||||
targets: [target]
|
||||
)
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let buildFiles = pbxProject.buildFiles
|
||||
|
||||
try expect(buildFiles.count) == 8
|
||||
|
||||
for buildFile in buildFiles {
|
||||
let name = buildFile.file?.nameOrPath
|
||||
|
||||
if buildFile.platformFilters == [SupportedDestination.iOS.string] &&
|
||||
(name == "File_ios.swift" || name == "File_A.swift") {
|
||||
continue
|
||||
} else if buildFile.platformFilters == [SupportedDestination.tvOS.string] &&
|
||||
(name == "File_tvOs.swift" || name == "File_B.swift") {
|
||||
continue
|
||||
} else if buildFile.platformFilters == [SupportedDestination.macOS.string] &&
|
||||
(name == "File_macOS.swift" || name == "File_C.swift") {
|
||||
continue
|
||||
} else if buildFile.platformFilters == [SupportedDestination.macCatalyst.string] &&
|
||||
(name == "File_MACCATALYST.swift" || name == "File_D.swift") {
|
||||
continue
|
||||
}
|
||||
|
||||
throw failure("Unexpected source file / destinationFilters")
|
||||
}
|
||||
}
|
||||
|
||||
$0.it("filter sources with destinationFilters") {
|
||||
let sourceFile1 = TargetSource(path: "App_supportedDestinations/TestResources/iOs",
|
||||
destinationFilters: [.iOS])
|
||||
let sourceFile2 = TargetSource(path: "App_supportedDestinations/TestResources/TVOS",
|
||||
destinationFilters: [.tvOS])
|
||||
let sourceFile3 = TargetSource(path: "App_supportedDestinations/TestResources/macos",
|
||||
destinationFilters: [.macOS, .macCatalyst])
|
||||
let sourceFile4 = TargetSource(path: "App_supportedDestinations/TestResources/macCatalyst",
|
||||
destinationFilters: [.macOS, .macCatalyst])
|
||||
let sourceFile5 = TargetSource(path: "App_supportedDestinations/TestResources/File_ios.swift",
|
||||
destinationFilters: [.iOS])
|
||||
let sourceFile6 = TargetSource(path: "App_supportedDestinations/TestResources/File_tvOs.swift",
|
||||
destinationFilters: [.tvOS])
|
||||
let sourceFile7 = TargetSource(path: "App_supportedDestinations/TestResources/File_macOS.swift",
|
||||
destinationFilters: [.macOS, .macCatalyst])
|
||||
let sourceFile8 = TargetSource(path: "App_supportedDestinations/TestResources/File_MACCATALYST.swift",
|
||||
destinationFilters: [.macOS, .macCatalyst])
|
||||
|
||||
let target = Target(
|
||||
name: "test",
|
||||
type: .application,
|
||||
platform: .auto,
|
||||
sources: [sourceFile1, sourceFile2, sourceFile3, sourceFile4, sourceFile5, sourceFile6, sourceFile7, sourceFile8],
|
||||
dependencies: []
|
||||
)
|
||||
|
||||
let project = Project(
|
||||
basePath: fixturePath + "TestProject",
|
||||
name: "test",
|
||||
targets: [target]
|
||||
)
|
||||
|
||||
let pbxProject = try project.generatePbxProj()
|
||||
let buildFiles = pbxProject.buildFiles
|
||||
|
||||
try expect(buildFiles.count) == 8
|
||||
|
||||
for buildFile in buildFiles {
|
||||
let name = buildFile.file?.nameOrPath
|
||||
|
||||
if buildFile.platformFilters == [SupportedDestination.iOS.string] &&
|
||||
(name == "File_ios.swift" || name == "File_A.swift") {
|
||||
continue
|
||||
} else if buildFile.platformFilters == [SupportedDestination.tvOS.string] &&
|
||||
(name == "File_tvOs.swift" || name == "File_B.swift") {
|
||||
continue
|
||||
} else if buildFile.platformFilters == [SupportedDestination.macOS.string, SupportedDestination.macCatalyst.string] &&
|
||||
(name == "File_C.swift" || name == "File_D.swift") {
|
||||
continue
|
||||
} else if buildFile.platformFilters == [SupportedDestination.macOS.string, SupportedDestination.macCatalyst.string] &&
|
||||
(name == "File_macOS.swift" || name == "File_MACCATALYST.swift") {
|
||||
continue
|
||||
}
|
||||
|
||||
throw failure("Unexpected source file / destinationFilters")
|
||||
}
|
||||
}
|
||||
|
||||
$0.it("copies Swift Objective-C Interface Header") {
|
||||
let swiftStaticLibraryWithHeader = Target(
|
||||
name: "swiftStaticLibraryWithHeader",
|
||||
@ -1645,7 +1895,197 @@ class ProjectGeneratorTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGenerateXcodeProjectWithPlatformFilteredDependencies() throws {
|
||||
|
||||
describe("generateXcodeProject with destinationFilters") {
|
||||
|
||||
func generateProjectForApp(withDependencies: [Dependency], targets: [Target], packages: [String: SwiftPackage] = [:]) throws -> PBXProj {
|
||||
|
||||
let app = Target(
|
||||
name: "App",
|
||||
type: .application,
|
||||
platform: .iOS,
|
||||
dependencies: withDependencies
|
||||
)
|
||||
|
||||
let project = Project(
|
||||
name: "test",
|
||||
targets: targets + [app],
|
||||
packages: packages
|
||||
)
|
||||
|
||||
return try project.generatePbxProj()
|
||||
}
|
||||
|
||||
func expectLinkedDependecies(_ expectedLinkedFiles: [String: [String]], in project: PBXProj) throws {
|
||||
let buildPhases = project.buildPhases
|
||||
let frameworkPhases = project.frameworksBuildPhases.filter { buildPhases.contains($0) }
|
||||
|
||||
var linkedFiles: [String: [String]] = [:]
|
||||
|
||||
for link in frameworkPhases[0].files ?? [] {
|
||||
if let name = link.file?.nameOrPath ?? link.product?.productName {
|
||||
linkedFiles[name] = link.platformFilters
|
||||
}
|
||||
}
|
||||
|
||||
try expect(linkedFiles) == expectedLinkedFiles
|
||||
}
|
||||
|
||||
func expectCopiedBundles(_ expectedCopiedBundleFiles: [String: [String]], in project: PBXProj) throws {
|
||||
let buildPhases = project.buildPhases
|
||||
let copyBundlesPhase = project.copyFilesBuildPhases.filter { buildPhases.contains($0) }
|
||||
|
||||
var copiedFiles: [String: [String]] = [:]
|
||||
|
||||
for copy in copyBundlesPhase[0].files ?? [] {
|
||||
if let name = copy.file?.nameOrPath {
|
||||
copiedFiles[name] = copy.platformFilters
|
||||
}
|
||||
}
|
||||
|
||||
try expect(copiedFiles) == expectedCopiedBundleFiles
|
||||
}
|
||||
|
||||
$0.it("target dependencies") {
|
||||
|
||||
let frameworkA = Target(
|
||||
name: "frameworkA",
|
||||
type: .framework,
|
||||
platform: .iOS
|
||||
)
|
||||
|
||||
let frameworkB = Target(
|
||||
name: "frameworkB",
|
||||
type: .framework,
|
||||
platform: .iOS
|
||||
)
|
||||
|
||||
let expectedLinkedFiles = [
|
||||
"frameworkA.framework": [SupportedDestination.iOS.string],
|
||||
"frameworkB.framework": [SupportedDestination.iOS.string, SupportedDestination.tvOS.string]
|
||||
]
|
||||
|
||||
// given
|
||||
let dependencies = [
|
||||
Dependency(type: .target, reference: frameworkA.name, destinationFilters: [.iOS]),
|
||||
Dependency(type: .target, reference: frameworkB.name, destinationFilters: [.iOS, .tvOS]),
|
||||
]
|
||||
|
||||
// when
|
||||
let pbxProject = try generateProjectForApp(withDependencies: dependencies, targets: [frameworkA, frameworkB])
|
||||
|
||||
// then ensure that everything is linked
|
||||
try expectLinkedDependecies(expectedLinkedFiles, in: pbxProject)
|
||||
}
|
||||
|
||||
$0.it("framework dependencies") {
|
||||
|
||||
let expectedLinkedFiles = [
|
||||
"frameworkA.framework": [SupportedDestination.iOS.string],
|
||||
"frameworkB.framework": [SupportedDestination.iOS.string, SupportedDestination.tvOS.string]
|
||||
]
|
||||
|
||||
// given
|
||||
let dependencies = [
|
||||
Dependency(type: .framework, reference: "frameworkA.framework", destinationFilters: [.iOS]),
|
||||
Dependency(type: .framework, reference: "frameworkB.framework", destinationFilters: [.iOS, .tvOS]),
|
||||
]
|
||||
|
||||
// when
|
||||
let pbxProject = try generateProjectForApp(withDependencies: dependencies, targets: [])
|
||||
|
||||
// then ensure that everything is linked
|
||||
try expectLinkedDependecies(expectedLinkedFiles, in: pbxProject)
|
||||
}
|
||||
|
||||
$0.it("carthage dependencies") {
|
||||
|
||||
let expectedLinkedFiles = [
|
||||
"frameworkA.framework": [SupportedDestination.iOS.string],
|
||||
"frameworkB.framework": [SupportedDestination.iOS.string, SupportedDestination.tvOS.string]
|
||||
]
|
||||
|
||||
// given
|
||||
let dependencies = [
|
||||
Dependency(type: .carthage(findFrameworks: false, linkType: .dynamic), reference: "frameworkA.framework", destinationFilters: [.iOS]),
|
||||
Dependency(type: .carthage(findFrameworks: false, linkType: .dynamic), reference: "frameworkB.framework", destinationFilters: [.iOS, .tvOS]),
|
||||
]
|
||||
|
||||
// when
|
||||
let pbxProject = try generateProjectForApp(withDependencies: dependencies, targets: [])
|
||||
|
||||
// then ensure that everything is linked
|
||||
try expectLinkedDependecies(expectedLinkedFiles, in: pbxProject)
|
||||
}
|
||||
|
||||
$0.it("sdk dependencies") {
|
||||
|
||||
let expectedLinkedFiles = [
|
||||
"sdkA.framework": [SupportedDestination.iOS.string],
|
||||
"sdkB.framework": [SupportedDestination.iOS.string, SupportedDestination.tvOS.string]
|
||||
]
|
||||
|
||||
// given
|
||||
let dependencies = [
|
||||
Dependency(type: .sdk(root: nil), reference: "sdkA.framework", destinationFilters: [.iOS]),
|
||||
Dependency(type: .sdk(root: nil), reference: "sdkB.framework", destinationFilters: [.iOS, .tvOS]),
|
||||
]
|
||||
|
||||
// when
|
||||
let pbxProject = try generateProjectForApp(withDependencies: dependencies, targets: [])
|
||||
|
||||
// then ensure that everything is linked
|
||||
try expectLinkedDependecies(expectedLinkedFiles, in: pbxProject)
|
||||
}
|
||||
|
||||
$0.it("package dependencies") {
|
||||
|
||||
let packages: [String: SwiftPackage] = [
|
||||
"RxSwift": .remote(url: "https://github.com/ReactiveX/RxSwift", versionRequirement: .upToNextMajorVersion("5.1.1")),
|
||||
]
|
||||
|
||||
let expectedLinkedFiles = [
|
||||
"RxSwift": [SupportedDestination.iOS.string],
|
||||
"RxCocoa": [SupportedDestination.iOS.string, SupportedDestination.tvOS.string]
|
||||
]
|
||||
|
||||
// given
|
||||
let dependencies = [
|
||||
Dependency(type: .package(products: ["RxSwift"]), reference: "RxSwift", destinationFilters: [.iOS]),
|
||||
Dependency(type: .package(products: ["RxCocoa"]), reference: "RxSwift", destinationFilters: [.iOS, .tvOS]),
|
||||
]
|
||||
|
||||
// when
|
||||
let pbxProject = try generateProjectForApp(withDependencies: dependencies, targets: [], packages: packages)
|
||||
|
||||
// then ensure that everything is linked
|
||||
try expectLinkedDependecies(expectedLinkedFiles, in: pbxProject)
|
||||
}
|
||||
|
||||
$0.it("bundle dependencies") {
|
||||
|
||||
let expectedCopiedBundleFiles = [
|
||||
"bundleA.bundle": [SupportedDestination.iOS.string],
|
||||
"bundleB.bundle": [SupportedDestination.iOS.string, SupportedDestination.tvOS.string]
|
||||
]
|
||||
|
||||
// given
|
||||
let dependencies = [
|
||||
Dependency(type: .bundle, reference: "bundleA.bundle", destinationFilters: [.iOS]),
|
||||
Dependency(type: .bundle, reference: "bundleB.bundle", destinationFilters: [.iOS, .tvOS]),
|
||||
]
|
||||
|
||||
// when
|
||||
let pbxProject = try generateProjectForApp(withDependencies: dependencies, targets: [])
|
||||
|
||||
// then ensure that everything is linked
|
||||
try expectCopiedBundles(expectedCopiedBundleFiles, in: pbxProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGenerateXcodeProjectWithCustomDependencyDestinations() throws {
|
||||
|
||||
describe("generateXcodeProject") {
|
||||
|
Loading…
Reference in New Issue
Block a user