Compare commits

...

5 Commits

Author SHA1 Message Date
Yonas Kolb
1993e6caad
Merge e7ee5f3f63 into 45151c2882 2024-07-11 10:31:42 +09:00
Ernesto Cambuston
45151c2882
Allow changing macro expansions on test actions. (#1468)
* Allow to override test macroExpansions

* update doc

* style

* Address feedback from PR

* fix build

* add toJSONValue encoding
2024-07-10 12:19:30 +10:00
Ernesto Cambuston
f8842228c5
Test action macroExpansion allows unavailable buildable reference. (#1471)
* fix buildable ref

* fix test

* add test
2024-07-03 21:41:03 +10:00
Kohki Miki
7eb5e9bd06
Remove GraphViz feature (#1485)
* Remove GraphViz to pass build on Xcode 16

* Update documentations
2024-07-02 17:06:02 +10:00
yonaskolb
e7ee5f3f63 use carthage xcframeworks 2021-05-01 14:32:56 +10:00
16 changed files with 178 additions and 243 deletions

View File

@ -2,6 +2,8 @@
## Next Version
- Removed `xcodegen dump --type graphviz` feature. @giginet
## 2.41.0
### Added

View File

@ -1039,7 +1039,7 @@ The different actions share some properties:
- [ ] **askForAppToLaunch**: **Bool** - `run` and `profile` actions can define the executable set to ask to launch. This defaults to false.
- [ ] **launchAutomaticallySubstyle**: **String** - `run` action can define the launch automatically substyle ('2' for extensions).
- [ ] **storeKitConfiguration**: **String** - `run` action can specify a storekit configuration. See [Options](#options).
- [ ] **macroExpansion**: **String** - `run` action can define the macro expansion from other target. This defaults to nil.
- [ ] **macroExpansion**: **String** - `run` and `test` action can define the macro expansion from other target. This defaults to nil.
### Execution Action

View File

@ -18,15 +18,6 @@
"version" : "0.0.6"
}
},
{
"identity" : "graphviz",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SwiftDocOrg/GraphViz.git",
"state" : {
"revision" : "70bebcf4597b9ce33e19816d6bbd4ba9b7bdf038",
"version" : "0.2.0"
}
},
{
"identity" : "jsonutilities",
"kind" : "remoteSourceControl",

View File

@ -19,7 +19,6 @@ let package = Package(
.package(url: "https://github.com/tuist/XcodeProj.git", exact: "8.13.0"),
.package(url: "https://github.com/jakeheis/SwiftCLI.git", from: "6.0.3"),
.package(url: "https://github.com/mxcl/Version", from: "2.0.0"),
.package(url: "https://github.com/SwiftDocOrg/GraphViz.git", exact: "0.2.0"),
.package(url: "https://github.com/freddi-kit/ArtifactBundleGen", exact: "0.0.6")
],
targets: [
@ -41,7 +40,6 @@ let package = Package(
"XcodeProj",
"PathKit",
"XcodeGenCore",
"GraphViz",
], resources: [
.copy("SettingPresets")
]),

View File

@ -35,7 +35,6 @@ The project spec is a YAML or JSON file that defines your targets, configuration
- ✅ Distribute your spec amongst multiple files for easy **sharing** and overriding
- ✅ Easily create **multi-platform** frameworks
- ✅ Integrate **Carthage** frameworks without any work
- ✅ Export **Dependency Diagrams** to view in [Graphviz](https://www.graphviz.org)
Given an example project spec:
@ -138,27 +137,6 @@ Options:
There are other commands as well such as `xcodegen dump` which lets one output the resolved spec in many different formats, or write it to a file. Use `xcodegen help` to see more detailed usage information.
## Dependency Diagrams
<details>
<summary>Click to expand!</summary>
#### How to export dependency diagrams:
To stdout:
```
xcodegen dump --type graphviz
```
To a file:
```
xcodegen dump --type graphviz --file Graph.viz
```
During implementation, `graphviz` formatting was validated using [GraphvizOnline](https://dreampuf.github.io/GraphvizOnline/), [WebGraphviz](http://www.webgraphviz.com), and [Graphviz on MacOS](https://graphviz.org).
</details>
## Editing
```shell
git clone https://github.com/yonaskolb/XcodeGen.git

View File

@ -220,6 +220,7 @@ public struct Scheme: Equatable {
public var captureScreenshotsAutomatically: Bool
public var deleteScreenshotsWhenEachTestSucceeds: Bool
public var testPlans: [TestPlan]
public var macroExpansion: String?
public struct TestTarget: Equatable, ExpressibleByStringLiteral {
@ -286,7 +287,8 @@ public struct Scheme: Equatable {
debugEnabled: Bool = debugEnabledDefault,
customLLDBInit: String? = nil,
captureScreenshotsAutomatically: Bool = captureScreenshotsAutomaticallyDefault,
deleteScreenshotsWhenEachTestSucceeds: Bool = deleteScreenshotsWhenEachTestSucceedsDefault
deleteScreenshotsWhenEachTestSucceeds: Bool = deleteScreenshotsWhenEachTestSucceedsDefault,
macroExpansion: String? = nil
) {
self.config = config
self.gatherCoverageData = gatherCoverageData
@ -304,6 +306,7 @@ public struct Scheme: Equatable {
self.customLLDBInit = customLLDBInit
self.captureScreenshotsAutomatically = captureScreenshotsAutomatically
self.deleteScreenshotsWhenEachTestSucceeds = deleteScreenshotsWhenEachTestSucceeds
self.macroExpansion = macroExpansion
}
public var shouldUseLaunchSchemeArgsEnv: Bool {
@ -620,6 +623,7 @@ extension Scheme.Test: JSONObjectConvertible {
customLLDBInit = jsonDictionary.json(atKeyPath: "customLLDBInit")
captureScreenshotsAutomatically = jsonDictionary.json(atKeyPath: "captureScreenshotsAutomatically") ?? Scheme.Test.captureScreenshotsAutomaticallyDefault
deleteScreenshotsWhenEachTestSucceeds = jsonDictionary.json(atKeyPath: "deleteScreenshotsWhenEachTestSucceeds") ?? Scheme.Test.deleteScreenshotsWhenEachTestSucceedsDefault
macroExpansion = jsonDictionary.json(atKeyPath: "macroExpansion")
}
}
@ -636,6 +640,7 @@ extension Scheme.Test: JSONEncodable {
"language": language,
"region": region,
"coverageTargets": coverageTargets.map { $0.reference },
"macroExpansion": macroExpansion
]
if gatherCoverageData != Scheme.Test.gatherCoverageDataDefault {

View File

@ -10,9 +10,11 @@ public struct SpecOptions: Equatable {
public static let generateEmptyDirectoriesDefault = false
public static let findCarthageFrameworksDefault = false
public static let useBaseInternationalizationDefault = true
public static let carthageXCFrameworksDefault = false
public static let schemePathPrefixDefault = "../../"
public var minimumXcodeGenVersion: Version?
public var carthageXCFrameworks: Bool
public var carthageBuildPath: String?
public var carthageExecutablePath: String?
public var createIntermediateGroups: Bool
@ -77,6 +79,7 @@ public struct SpecOptions: Equatable {
public init(
minimumXcodeGenVersion: Version? = nil,
carthageXCFrameworks: Bool = carthageXCFrameworksDefault,
carthageBuildPath: String? = nil,
carthageExecutablePath: String? = nil,
createIntermediateGroups: Bool = createIntermediateGroupsDefault,
@ -103,6 +106,7 @@ public struct SpecOptions: Equatable {
schemePathPrefix: String = schemePathPrefixDefault
) {
self.minimumXcodeGenVersion = minimumXcodeGenVersion
self.carthageXCFrameworks = carthageXCFrameworks
self.carthageBuildPath = carthageBuildPath
self.carthageExecutablePath = carthageExecutablePath
self.createIntermediateGroups = createIntermediateGroups
@ -137,6 +141,7 @@ extension SpecOptions: JSONObjectConvertible {
minimumXcodeGenVersion = try Version.parse(string)
}
carthageXCFrameworks = jsonDictionary.json(atKeyPath: "carthageXCFrameworks") ?? SpecOptions.carthageXCFrameworksDefault
carthageBuildPath = jsonDictionary.json(atKeyPath: "carthageBuildPath")
carthageExecutablePath = jsonDictionary.json(atKeyPath: "carthageExecutablePath")
bundleIdPrefix = jsonDictionary.json(atKeyPath: "bundleIdPrefix")
@ -206,6 +211,9 @@ extension SpecOptions: JSONEncodable {
if useBaseInternationalization != SpecOptions.useBaseInternationalizationDefault {
dict["useBaseInternationalization"] = useBaseInternationalization
}
if carthageXCFrameworks != SpecOptions.carthageXCFrameworksDefault {
dict["carthageXCFrameworks"] = carthageXCFrameworks
}
if schemePathPrefix != SpecOptions.schemePathPrefixDefault {
dict["schemePathPrefix"] = schemePathPrefix
}

View File

@ -41,8 +41,6 @@ class DumpCommand: ProjectCommand {
output = try Yams.dump(object: project.toJSONDictionary())
case .summary:
output = project.debugDescription
case .graphviz:
output = GraphVizGenerator().generateModuleGraphViz(targets: project.targets)
}
if let file = file {
@ -61,7 +59,6 @@ private enum DumpType: String, ConvertibleFromString, CaseIterable {
case parsedJSON = "parsed-json"
case parsedYaml = "parsed-yaml"
case summary
case graphviz
static var defaultValue: DumpType { .yaml }
}

View File

@ -39,14 +39,43 @@ public class CarthageDependencyResolver {
versionLoader = CarthageVersionLoader(buildPath: project.basePath + CarthageDependencyResolver.getBuildPath(project))
}
func frameworkPath(for name: String, platform: Platform, linkType: Dependency.CarthageLinkType) -> Path {
var file = Path(name)
var xcFramework = project.options.carthageXCFrameworks
switch file.extension {
case "xcframework":
xcFramework = true
case "framework":
xcFramework = false
case .none:
let fileExtension: String
if xcFramework {
fileExtension = "xcframework"
} else {
fileExtension = "framework"
}
file = Path(file.string + ".\(fileExtension)")
default:
break
}
let parentPath = Path(buildPath(for: platform, linkType: linkType, xcFramework: xcFramework))
return parentPath + file
}
/// Carthage's build path for the given platform
func buildPath(for platform: Platform, linkType: Dependency.CarthageLinkType) -> String {
func buildPath(for platform: Platform, linkType: Dependency.CarthageLinkType, xcFramework: Bool) -> String {
var path = buildPath
if !xcFramework {
path += "/\(platform.carthageName)"
}
switch linkType {
case .static:
return "\(buildPath)/\(platform.carthageName)/Static"
path += "/Static"
case .dynamic:
return "\(buildPath)/\(platform.carthageName)"
break
}
return path
}
/// Fetches all carthage dependencies for a given target

View File

@ -57,8 +57,13 @@ class CarthageVersionLoader {
struct CarthageVersionFile: Decodable {
private struct Reference: Decodable, Equatable {
public let name: String
public let hash: String
let name: String
let hash: String
let container: String?
var frameworkFilename: String {
container ?? "\(name).framework"
}
}
private let data: [Platform: [String]]
@ -67,7 +72,7 @@ struct CarthageVersionFile: Decodable {
let container = try decoder.container(keyedBy: Platform.self)
data = try Platform.allCases.reduce(into: [:]) { data, platform in
let references = try container.decodeIfPresent([Reference].self, forKey: platform) ?? []
let frameworks = Set(references.map { $0.name }).sorted()
let frameworks = Set(references.map { $0.frameworkFilename }).sorted()
data[platform] = frameworks
}
}

View File

@ -1,66 +0,0 @@
import DOT
import Foundation
import GraphViz
import ProjectSpec
extension Dependency {
var graphVizName: String {
switch self.type {
case .bundle, .package, .sdk, .framework, .carthage:
return "[\(self.type)]\\n\(reference)"
case .target:
return reference
}
}
}
extension Dependency.DependencyType: CustomStringConvertible {
public var description: String {
switch self {
case .bundle: return "bundle"
case .package: return "package"
case .framework: return "framework"
case .carthage: return "carthage"
case .sdk: return "sdk"
case .target: return "target"
}
}
}
extension Node {
init(target: Target) {
self.init(target.name)
self.shape = .box
}
init(dependency: Dependency) {
self.init(dependency.reference)
self.shape = .box
self.label = dependency.graphVizName
}
}
public class GraphVizGenerator {
public init() {}
public func generateModuleGraphViz(targets: [Target]) -> String {
return DOTEncoder().encode(generateGraph(targets: targets))
}
func generateGraph(targets: [Target]) -> Graph {
var graph = Graph(directed: true)
targets.forEach { target in
target.dependencies.forEach { dependency in
let from = Node(target: target)
graph.append(from)
let to = Node(dependency: dependency)
graph.append(to)
var edge = Edge(from: from, to: to)
edge.style = .dashed
graph.append(edge)
}
}
return graph
}
}

View File

@ -24,6 +24,7 @@ public class PBXProjGenerator {
var packageReferences: [String: XCRemoteSwiftPackageReference] = [:]
var carthageFrameworksByPlatform: [String: Set<PBXFileElement>] = [:]
var carthageXCFrameworks: Set<PBXFileElement> = []
var frameworkFiles: [PBXFileElement] = []
var bundleFiles: [PBXFileElement] = []
@ -226,8 +227,8 @@ public class PBXProjGenerator {
try project.targets.forEach(generateTarget)
try project.aggregateTargets.forEach(generateAggregateTarget)
if !carthageFrameworksByPlatform.isEmpty {
var platforms: [PBXGroup] = []
if !carthageFrameworksByPlatform.isEmpty || !carthageXCFrameworks.isEmpty {
var children: [PBXFileElement] = []
for (platform, files) in carthageFrameworksByPlatform {
let platformGroup: PBXGroup = addObject(
PBXGroup(
@ -236,11 +237,14 @@ public class PBXProjGenerator {
path: platform
)
)
platforms.append(platformGroup)
children.append(platformGroup)
}
if !carthageXCFrameworks.isEmpty {
children += Array(carthageXCFrameworks)
}
let carthageGroup = addObject(
PBXGroup(
children: platforms,
children: children,
sourceTree: .group,
name: "Carthage",
path: carthageResolver.buildPath
@ -703,7 +707,7 @@ public class PBXProjGenerator {
let targetSupportsDirectEmbed = !(target.platform.requiresSimulatorStripping &&
(target.type.isApp || target.type == .watch2Extension))
let directlyEmbedCarthage = target.directlyEmbedCarthageDependencies ?? targetSupportsDirectEmbed
let directlyEmbedCarthage = target.directlyEmbedCarthageDependencies ?? project.options.carthageXCFrameworks || targetSupportsDirectEmbed
func getEmbedSettings(dependency: Dependency, codeSign: Bool) -> [String: Any] {
var embedAttributes: [String] = []
@ -920,14 +924,14 @@ public class PBXProjGenerator {
? carthageResolver.relatedDependencies(for: dependency, in: target.platform) : [dependency]
allDependencies.forEach { dependency in
let platformPath = Path(carthageResolver.buildPath(for: target.platform, linkType: linkType))
var frameworkPath = platformPath + dependency.reference
if frameworkPath.extension == nil {
frameworkPath = Path(frameworkPath.string + ".framework")
}
let fileReference = self.sourceGenerator.getFileReference(path: frameworkPath, inPath: platformPath)
let frameworkPath = carthageResolver.frameworkPath(for: dependency.reference, platform: target.platform, linkType: linkType)
let fileReference = self.sourceGenerator.getFileReference(path: frameworkPath, inPath: frameworkPath.parent())
if frameworkPath.extension == "xcframework" {
self.carthageXCFrameworks.insert(fileReference)
} else {
self.carthageFrameworksByPlatform[target.platform.carthageName, default: []].insert(fileReference)
}
let isStaticLibrary = target.type == .staticLibrary
let isCarthageStaticLink = dependency.carthageLinkType == .static
@ -1025,12 +1029,8 @@ public class PBXProjGenerator {
let isFromTopLevelTarget = carthageDependency.isFromTopLevelTarget
let embed = dependency.embed ?? target.shouldEmbedCarthageDependencies
let platformPath = Path(carthageResolver.buildPath(for: target.platform, linkType: dependency.carthageLinkType ?? .default))
var frameworkPath = platformPath + dependency.reference
if frameworkPath.extension == nil {
frameworkPath = Path(frameworkPath.string + ".framework")
}
let fileReference = sourceGenerator.getFileReference(path: frameworkPath, inPath: platformPath)
let frameworkPath = carthageResolver.frameworkPath(for: dependency.reference, platform: target.platform, linkType: dependency.carthageLinkType ?? .default)
let fileReference = self.sourceGenerator.getFileReference(path: frameworkPath, inPath: frameworkPath.parent())
if dependency.carthageLinkType == .static {
guard isFromTopLevelTarget else { continue } // ignore transitive dependencies if static
@ -1182,7 +1182,7 @@ public class PBXProjGenerator {
if !carthageFrameworksToEmbed.isEmpty {
let inputPaths = carthageFrameworksToEmbed
.map { "$(SRCROOT)/\(carthageResolver.buildPath(for: target.platform, linkType: .dynamic))/\($0)\($0.contains(".") ? "" : ".framework")" }
.map { "$(SRCROOT)/\(carthageResolver.frameworkPath(for: $0, platform: target.platform, linkType: .dynamic))" }
let outputPaths = carthageFrameworksToEmbed
.map { "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/\($0)\($0.contains(".") ? "" : ".framework")" }
let carthageExecutable = carthageResolver.executable
@ -1385,15 +1385,21 @@ public class PBXProjGenerator {
let configFrameworkBuildPaths: [String]
if !carthageDependencies.isEmpty {
var carthagePlatformBuildPaths: Set<String> = []
if carthageDependencies.contains(where: { $0.dependency.carthageLinkType == .static }) {
let carthagePlatformBuildPath = "$(PROJECT_DIR)/" + carthageResolver.buildPath(for: target.platform, linkType: .static)
carthagePlatformBuildPaths.insert(carthagePlatformBuildPath)
func getCarthageBuildPaths(linkType: Dependency.CarthageLinkType) -> Set<String> {
var paths: Set<String> = []
if carthageDependencies.contains(where: { $0.dependency.carthageLinkType == linkType }) {
let path = "$(PROJECT_DIR)/\(carthageResolver.buildPath(for: target.platform, linkType: linkType, xcFramework: false))"
paths.insert(path)
if project.options.carthageXCFrameworks {
let path = "$(PROJECT_DIR)/\(carthageResolver.buildPath(for: target.platform, linkType: linkType, xcFramework: true))/**"
paths.insert(path)
}
if carthageDependencies.contains(where: { $0.dependency.carthageLinkType == .dynamic }) {
let carthagePlatformBuildPath = "$(PROJECT_DIR)/" + carthageResolver.buildPath(for: target.platform, linkType: .dynamic)
carthagePlatformBuildPaths.insert(carthagePlatformBuildPath)
}
configFrameworkBuildPaths = carthagePlatformBuildPaths.sorted() + frameworkBuildPaths.sorted()
return paths
}
carthagePlatformBuildPaths = carthagePlatformBuildPaths.union(getCarthageBuildPaths(linkType: .static))
carthagePlatformBuildPaths = carthagePlatformBuildPaths.union(getCarthageBuildPaths(linkType: .dynamic))
configFrameworkBuildPaths = carthagePlatformBuildPaths.union(frameworkBuildPaths).sorted()
} else {
configFrameworkBuildPaths = frameworkBuildPaths.sorted()
}

View File

@ -286,10 +286,21 @@ public class SchemeGenerator {
let testPlans = scheme.test?.testPlans.enumerated().map { index, testPlan in
XCScheme.TestPlanReference(reference: "container:\(testPlan.path)", default: defaultTestPlanIndex == index)
} ?? []
let testBuildableEntries = buildActionEntries.filter({ $0.buildFor.contains(.testing) }) + testBuildTargetEntries
let testMacroExpansionBuildableRef = testBuildableEntries.map(\.buildableReference).contains(buildableReference) ? buildableReference : testBuildableEntries.first?.buildableReference
let testMacroExpansion: XCScheme.BuildableReference = buildActionEntries.first(
where: { value in
if let macroExpansion = scheme.test?.macroExpansion {
return value.buildableReference.blueprintName == macroExpansion
}
return false
}
)?.buildableReference ?? testMacroExpansionBuildableRef ?? buildableReference
let testAction = XCScheme.TestAction(
buildConfiguration: scheme.test?.config ?? defaultDebugConfig.name,
macroExpansion: buildableReference,
macroExpansion: testMacroExpansion,
testables: testables,
testPlans: testPlans.isEmpty ? nil : testPlans,
preActions: scheme.test?.preActions.map(getExecutionAction) ?? [],

View File

@ -55,7 +55,7 @@ class CarthageDependencyResolverTests: XCTestCase {
}
try allPlatforms.forEach { platform in
try expect(expectedByPlatform[platform]) == resolver.buildPath(for: platform, linkType: .dynamic)
try expect(expectedByPlatform[platform]) == resolver.buildPath(for: platform, linkType: .dynamic, xcFramework: false)
}
}
}

View File

@ -1,104 +0,0 @@
import ProjectSpec
import Spectre
@testable import XcodeGenKit
import XCTest
private let app = Target(
name: "MyApp",
type: .application,
platform: .iOS,
settings: Settings(buildSettings: ["SETTING_1": "VALUE"]),
dependencies: [
Dependency(type: .target, reference: "MyInternalFramework"),
Dependency(type: .bundle, reference: "Resources"),
Dependency(type: .carthage(findFrameworks: true, linkType: .static), reference: "MyStaticFramework"),
Dependency(type: .carthage(findFrameworks: true, linkType: .dynamic), reference: "MyDynamicFramework"),
Dependency(type: .framework, reference: "MyExternalFramework"),
Dependency(type: .package(products: ["MyPackage"]), reference: "MyPackage"),
Dependency(type: .sdk(root: "MySDK"), reference: "MySDK"),
]
)
private let framework = Target(
name: "MyFramework",
type: .framework,
platform: .iOS,
settings: Settings(buildSettings: ["SETTING_2": "VALUE"])
)
private let uiTest = Target(
name: "MyAppUITests",
type: .uiTestBundle,
platform: .iOS,
settings: Settings(buildSettings: ["SETTING_3": "VALUE"]),
dependencies: [Dependency(type: .target, reference: "MyApp")]
)
private let targets = [app, framework, uiTest]
class GraphVizGeneratorTests: XCTestCase {
func testGraphOutput() throws {
describe {
let graph = GraphVizGenerator().generateGraph(targets: targets)
$0.it("generates the expected number of nodes") {
try expect(graph.nodes.count) == 16
}
$0.it("generates box nodes") {
try expect(graph.nodes.filter { $0.shape == .box }.count) == 16
}
$0.it("generates the expected carthage nodes") {
try expect(graph.nodes.filter { $0.label?.contains("[carthage]") ?? false }.count) == 2
}
$0.it("generates the expected sdk nodes") {
try expect(graph.nodes.filter { $0.label?.contains("[sdk]") ?? false }.count) == 1
}
$0.it("generates the expected Framework nodes") {
try expect(graph.nodes.filter { $0.label?.contains("[framework]") ?? false }.count) == 1
}
$0.it("generates the expected package nodes") {
try expect(graph.nodes.filter { $0.label?.contains("[package]") ?? false }.count) == 1
}
$0.it("generates the expected bundle nodes") {
try expect(graph.nodes.filter { $0.label?.contains("[bundle]") ?? false }.count) == 1
}
$0.it("generates the expected edges") {
try expect(graph.edges.count) == 8
}
$0.it("generates dashed edges") {
try expect(graph.edges.filter { $0.style == .dashed }.count) == 8
}
$0.it("generates the expected output") {
let output = GraphVizGenerator().generateModuleGraphViz(targets: targets)
try expect(output) == """
digraph {
MyApp [shape=box]
MyInternalFramework [label=MyInternalFramework shape=box]
MyApp [shape=box]
Resources [label="[bundle]\\nResources" shape=box]
MyApp [shape=box]
MyStaticFramework [label="[carthage]\\nMyStaticFramework" shape=box]
MyApp [shape=box]
MyDynamicFramework [label="[carthage]\\nMyDynamicFramework" shape=box]
MyApp [shape=box]
MyExternalFramework [label="[framework]\\nMyExternalFramework" shape=box]
MyApp [shape=box]
MyPackage [label="[package]\\nMyPackage" shape=box]
MyApp [shape=box]
MySDK [label="[sdk]\\nMySDK" shape=box]
MyAppUITests [shape=box]
MyApp [label=MyApp shape=box]
MyApp -> MyInternalFramework [style=dashed]
MyApp -> Resources [style=dashed]
MyApp -> MyStaticFramework [style=dashed]
MyApp -> MyDynamicFramework [style=dashed]
MyApp -> MyExternalFramework [style=dashed]
MyApp -> MyPackage [style=dashed]
MyApp -> MySDK [style=dashed]
MyAppUITests -> MyApp [style=dashed]
}
"""
}
}
}
}

View File

@ -476,9 +476,84 @@ class SchemeGeneratorTests: XCTestCase {
let xcodeProject = try project.generateXcodeProject()
let xcscheme = try unwrap(xcodeProject.sharedData?.schemes.first)
try expect(xcscheme.testAction?.macroExpansion?.buildableName) == "MyApp.app"
try expect(xcscheme.launchAction?.macroExpansion?.buildableName) == "MyApp.app"
}
$0.it("allows to override test macroExpansion") {
let app = Target(
name: "MyApp",
type: .application,
platform: .iOS,
dependencies: [Dependency(type: .target, reference: "MyAppExtension", embed: false)]
)
let `extension` = Target(
name: "MyAppExtension",
type: .appExtension,
platform: .iOS
)
let appTarget = Scheme.BuildTarget(target: .local(app.name), buildTypes: [.running])
let extensionTarget = Scheme.BuildTarget(target: .local(`extension`.name), buildTypes: [.running])
let scheme = Scheme(
name: "TestScheme",
build: Scheme.Build(targets: [appTarget, extensionTarget]),
run: Scheme.Run(config: "Debug", macroExpansion: "MyApp"),
test: .init(macroExpansion: "MyAppExtension")
)
let project = Project(
name: "test",
targets: [app, `extension`],
schemes: [scheme]
)
let xcodeProject = try project.generateXcodeProject()
let xcscheme = try unwrap(xcodeProject.sharedData?.schemes.first)
try expect(xcscheme.testAction?.macroExpansion?.buildableName) == "MyAppExtension.appex"
try expect(xcscheme.launchAction?.macroExpansion?.buildableName) == "MyApp.app"
}
$0.it("generates scheme with macroExpansion from tests when the main target is not part of the scheme") {
let app = Target(
name: "MyApp",
type: .application,
platform: .iOS,
dependencies: []
)
let mockApp = Target(
name: "MockApp",
type: .application,
platform: .iOS,
dependencies: []
)
let testBundle = Target(
name: "TestBundle",
type: .unitTestBundle,
platform: .iOS
)
let appTarget = Scheme.BuildTarget(target: .local(app.name), buildTypes: [.running])
let mockAppTarget = Scheme.BuildTarget(target: .local(mockApp.name), buildTypes: [.testing])
let testBundleTarget = Scheme.BuildTarget(target: .local(testBundle.name), buildTypes: [.testing])
let scheme = Scheme(
name: "TestScheme",
build: Scheme.Build(targets: [appTarget, mockAppTarget, testBundleTarget]),
run: Scheme.Run(config: "Debug", macroExpansion: "MyApp")
)
let project = Project(
name: "test",
targets: [app, mockApp, testBundle],
schemes: [scheme]
)
let xcodeProject = try project.generateXcodeProject()
let xcscheme = try unwrap(xcodeProject.sharedData?.schemes.first)
try expect(xcscheme.testAction?.macroExpansion?.buildableName) == "MockApp.app"
}
$0.it("generates scheme with test target of local swift package") {
let targetScheme = TargetScheme(
testTargets: [Scheme.Test.TestTarget(targetReference: TestableTargetReference(name: "XcodeGenKitTests", location: .package("XcodeGen")))])