diff --git a/Sources/ProjectDescription/Target.swift b/Sources/ProjectDescription/Target.swift index 5eebabfa18e..4a9458e23d7 100644 --- a/Sources/ProjectDescription/Target.swift +++ b/Sources/ProjectDescription/Target.swift @@ -14,6 +14,11 @@ public class Target: Codable { /// Bundle identifier. public let bundleId: String + + /// The name of the product output by this target. + /// passing nil in the initialiser will default + /// this value to the name of the target. + public let productName: String /// Relative path to the Info.plist file. public let infoPlist: InfoPlist @@ -49,6 +54,7 @@ public class Target: Codable { case name case platform case product + case productName = "product_name" case bundleId = "bundle_id" case infoPlist = "info_plist" case entitlements @@ -82,6 +88,7 @@ public class Target: Codable { public init(name: String, platform: Platform, product: Product, + productName: String? = nil, bundleId: String, infoPlist: InfoPlist, sources: FileList? = nil, @@ -96,6 +103,7 @@ public class Target: Codable { self.name = name self.platform = platform self.bundleId = bundleId + self.productName = productName ?? name self.product = product self.infoPlist = infoPlist self.entitlements = entitlements diff --git a/Sources/TuistGenerator/Generator/ConfigGenerator.swift b/Sources/TuistGenerator/Generator/ConfigGenerator.swift index 449d25498f8..9a96d16a444 100644 --- a/Sources/TuistGenerator/Generator/ConfigGenerator.swift +++ b/Sources/TuistGenerator/Generator/ConfigGenerator.swift @@ -174,6 +174,8 @@ final class ConfigGenerator: ConfigGenerating { if target.product == .staticFramework { settings["MACH_O_TYPE"] = "staticlib" } + + settings["PRODUCT_NAME"] = target.productName if target.product.testsBundle { let appDependency = graph.targetDependencies(path: sourceRootPath, name: target.name).first { targetNode in @@ -181,10 +183,10 @@ final class ConfigGenerator: ConfigGenerating { } if let app = appDependency { - settings["TEST_TARGET_NAME"] = "\(app.target.name)" + settings["TEST_TARGET_NAME"] = "\(app.target.productName)" if target.product == .unitTests { - settings["TEST_HOST"] = "$(BUILT_PRODUCTS_DIR)/\(app.target.productNameWithExtension)/\(app.target.name)" + settings["TEST_HOST"] = "$(BUILT_PRODUCTS_DIR)/\(app.target.productNameWithExtension)/\(app.target.productName)" settings["BUNDLE_LOADER"] = "$(TEST_HOST)" } } diff --git a/Sources/TuistGenerator/Generator/SchemesGenerator.swift b/Sources/TuistGenerator/Generator/SchemesGenerator.swift index b680bec9d9f..efd11462deb 100644 --- a/Sources/TuistGenerator/Generator/SchemesGenerator.swift +++ b/Sources/TuistGenerator/Generator/SchemesGenerator.swift @@ -53,7 +53,7 @@ final class SchemesGenerator: SchemesGenerating { buildAction: BuildAction(targets: [target.name]), testAction: TestAction(targets: [target.name]), runAction: RunAction(config: .debug, - executable: target.name, + executable: target.productName, arguments: Arguments(environment: target.environment))) try generateScheme(scheme: scheme, diff --git a/Sources/TuistGenerator/Graph/GraphLoader.swift b/Sources/TuistGenerator/Graph/GraphLoader.swift index 2a06e4ebc17..be0a1971fd4 100644 --- a/Sources/TuistGenerator/Graph/GraphLoader.swift +++ b/Sources/TuistGenerator/Graph/GraphLoader.swift @@ -38,8 +38,8 @@ class GraphLoader: GraphLoading { let cache = GraphLoaderCache() let circularDetector = GraphCircularDetector() let project = try Project.at(path, cache: cache, circularDetector: circularDetector, modelLoader: modelLoader) - let entryNodes: [GraphNode] = try project.targets.map { $0.name }.map { targetName in - try TargetNode.read(name: targetName, path: path, cache: cache, circularDetector: circularDetector, modelLoader: modelLoader) + let entryNodes: [GraphNode] = try project.targets.map { target in + try TargetNode.read(name: target.name, path: path, cache: cache, circularDetector: circularDetector, modelLoader: modelLoader) } let graph = Graph(name: project.name, entryPath: path, @@ -57,8 +57,8 @@ class GraphLoader: GraphLoading { try (projectPath, Project.at(projectPath, cache: cache, circularDetector: circularDetector, modelLoader: modelLoader)) } let entryNodes = try projects.flatMap { (project) -> [TargetNode] in - try project.1.targets.map { $0.name }.map { targetName in - try TargetNode.read(name: targetName, path: project.0, cache: cache, circularDetector: circularDetector, modelLoader: modelLoader) + try project.1.targets.map { target in + try TargetNode.read(name: target.name, path: project.0, cache: cache, circularDetector: circularDetector, modelLoader: modelLoader) } } let graph = Graph(name: workspace.name, diff --git a/Sources/TuistGenerator/Models/Target.swift b/Sources/TuistGenerator/Models/Target.swift index f8a2c8ff4e7..e0b254023f6 100644 --- a/Sources/TuistGenerator/Models/Target.swift +++ b/Sources/TuistGenerator/Models/Target.swift @@ -16,6 +16,7 @@ public class Target: Equatable { public let platform: Platform public let product: Product public let bundleId: String + public let productName: String // An info.plist file is needed for (dynamic) frameworks, applications and executables // however is not needed for other products such as static libraries. @@ -36,6 +37,7 @@ public class Target: Equatable { public init(name: String, platform: Platform, product: Product, + productName: String, bundleId: String, infoPlist: InfoPlist? = nil, entitlements: AbsolutePath? = nil, @@ -52,6 +54,7 @@ public class Target: Equatable { self.product = product self.platform = platform self.bundleId = bundleId + self.productName = productName self.infoPlist = infoPlist self.entitlements = entitlements self.settings = settings @@ -79,9 +82,9 @@ public class Target: Equatable { var productNameWithExtension: String { switch product { case .staticLibrary, .dynamicLibrary: - return "lib\(name).\(product.xcodeValue.fileExtension!)" + return "lib\(productName).\(product.xcodeValue.fileExtension!)" case _: - return "\(name).\(product.xcodeValue.fileExtension!)" + return "\(productName).\(product.xcodeValue.fileExtension!)" } } @@ -125,6 +128,7 @@ public class Target: Equatable { lhs.platform == rhs.platform && lhs.product == rhs.product && lhs.bundleId == rhs.bundleId && + lhs.productName == rhs.productName && lhs.infoPlist == rhs.infoPlist && lhs.entitlements == rhs.entitlements && lhs.settings == rhs.settings && diff --git a/Sources/TuistKit/Generator/GeneratorModelLoader.swift b/Sources/TuistKit/Generator/GeneratorModelLoader.swift index 6c05ecbaa14..10a833f7603 100644 --- a/Sources/TuistKit/Generator/GeneratorModelLoader.swift +++ b/Sources/TuistKit/Generator/GeneratorModelLoader.swift @@ -203,6 +203,8 @@ extension TuistGenerator.Target { let product = TuistGenerator.Product.from(manifest: manifest.product) let bundleId = manifest.bundleId + let productName = manifest.productName + let dependencies = manifest.dependencies.map { TuistGenerator.Dependency.from(manifest: $0) } let infoPlist = TuistGenerator.InfoPlist.from(manifest: manifest.infoPlist, path: path) @@ -236,6 +238,7 @@ extension TuistGenerator.Target { return TuistGenerator.Target(name: name, platform: platform, product: product, + productName: productName, bundleId: bundleId, infoPlist: infoPlist, entitlements: entitlements, diff --git a/Sources/TuistKit/Generator/ManifestTargetGenerator.swift b/Sources/TuistKit/Generator/ManifestTargetGenerator.swift index 7854af49621..c25da3a5a3c 100644 --- a/Sources/TuistKit/Generator/ManifestTargetGenerator.swift +++ b/Sources/TuistKit/Generator/ManifestTargetGenerator.swift @@ -26,6 +26,7 @@ class ManifestTargetGenerator: ManifestTargetGenerating { return Target(name: "\(project)-Manifest", platform: .macOS, product: .staticFramework, + productName: "\(project)-Manifest", bundleId: "io.tuist.manifests.${PRODUCT_NAME:rfc1034identifier}", settings: settings, sources: [(path: manifest, compilerFlags: nil)], diff --git a/Tests/ProjectDescriptionTests/TargetTests.swift b/Tests/ProjectDescriptionTests/TargetTests.swift index 698a4a8c132..9aa76411d59 100644 --- a/Tests/ProjectDescriptionTests/TargetTests.swift +++ b/Tests/ProjectDescriptionTests/TargetTests.swift @@ -9,6 +9,7 @@ final class TargetTests: XCTestCase { let subject = Target(name: "name", platform: .iOS, product: .app, + productName: "product_name", bundleId: "bundle_id", infoPlist: "info.plist", sources: "sources/*", @@ -59,6 +60,7 @@ final class TargetTests: XCTestCase { } ], "product": "app", + "product_name": "product_name", "sources": [ { "glob": "sources\\/*" @@ -128,6 +130,7 @@ final class TargetTests: XCTestCase { let subject = Target(name: "name", platform: .iOS, product: .app, + productName: "product_name", bundleId: "bundle_id", infoPlist: "info.plist", sources: FileList(globs: ["sources/*"]), @@ -178,6 +181,7 @@ final class TargetTests: XCTestCase { } ], "product": "app", + "product_name": "product_name", "sources": [ { "glob": "sources\\/*" diff --git a/Tests/TuistGeneratorTests/Generator/BuildPhaseGeneratorTests.swift b/Tests/TuistGeneratorTests/Generator/BuildPhaseGeneratorTests.swift index ae4a5504bc9..52ce8026998 100644 --- a/Tests/TuistGeneratorTests/Generator/BuildPhaseGeneratorTests.swift +++ b/Tests/TuistGeneratorTests/Generator/BuildPhaseGeneratorTests.swift @@ -273,8 +273,8 @@ final class BuildPhaseGeneratorTests: XCTestCase { func test_generateResourceBundle() throws { // Given let path = AbsolutePath("/path") - let bundle1 = Target.test(name: "Bundle1", product: .bundle) - let bundle2 = Target.test(name: "Bundle2", product: .bundle) + let bundle1 = Target.test(name: "Bundle1", product: .bundle, productName: "Bundle1") + let bundle2 = Target.test(name: "Bundle2", product: .bundle, productName: "Bundle2") let app = Target.test(name: "App", product: .app) let graph = Graph.create(project: .test(path: path), dependencies: [ diff --git a/Tests/TuistGeneratorTests/Generator/TargetGeneratorTests.swift b/Tests/TuistGeneratorTests/Generator/TargetGeneratorTests.swift index a2baa2dd5ba..c84fe894b33 100644 --- a/Tests/TuistGeneratorTests/Generator/TargetGeneratorTests.swift +++ b/Tests/TuistGeneratorTests/Generator/TargetGeneratorTests.swift @@ -64,7 +64,7 @@ final class TargetGeneratorTests: XCTestCase { graph: graph) // Then - XCTAssertEqual(generatedTarget.productName, "MyFramework") + XCTAssertEqual(generatedTarget.name, "MyFramework") XCTAssertEqual(generatedTarget.productNameWithExtension(), "MyFramework.framework") XCTAssertEqual(generatedTarget.productType, .framework) diff --git a/Tests/TuistGeneratorTests/Models/TestData/Target+TestData.swift b/Tests/TuistGeneratorTests/Models/TestData/Target+TestData.swift index 7d795b3f21b..7c0a8eda234 100644 --- a/Tests/TuistGeneratorTests/Models/TestData/Target+TestData.swift +++ b/Tests/TuistGeneratorTests/Models/TestData/Target+TestData.swift @@ -8,6 +8,7 @@ extension Target { static func test(name: String = "Target", platform: Platform = .iOS, product: Product = .app, + productName: String? = nil, bundleId: String = "com.test.bundle_id", infoPlist: InfoPlist? = .file(path: AbsolutePath("/Info.plist")), entitlements: AbsolutePath? = AbsolutePath("/Test.entitlements"), @@ -23,6 +24,7 @@ extension Target { return Target(name: name, platform: platform, product: product, + productName: productName ?? name, bundleId: bundleId, infoPlist: infoPlist, entitlements: entitlements, @@ -41,6 +43,7 @@ extension Target { static func empty(name: String = "Target", platform: Platform = .iOS, product: Product = .app, + productName: String? = nil, bundleId: String = "com.test.bundleId", infoPlist: InfoPlist? = nil, entitlements: AbsolutePath? = nil, @@ -56,6 +59,7 @@ extension Target { return Target(name: name, platform: platform, product: product, + productName: productName ?? name, bundleId: bundleId, infoPlist: infoPlist, entitlements: entitlements, diff --git a/Tests/TuistIntegrationTests/Generator/MultipleConfigurationsIntegrationTests.swift b/Tests/TuistIntegrationTests/Generator/MultipleConfigurationsIntegrationTests.swift index ede1d95fba2..ce3072ee75a 100644 --- a/Tests/TuistIntegrationTests/Generator/MultipleConfigurationsIntegrationTests.swift +++ b/Tests/TuistIntegrationTests/Generator/MultipleConfigurationsIntegrationTests.swift @@ -336,6 +336,7 @@ final class MultipleConfigurationsIntegrationTests: XCTestCase { return Target(name: "AppTarget", platform: .iOS, product: .app, + productName: "AppTarget", bundleId: "test.bundle", settings: settings, sources: [(path: pathTo("App/Sources/AppDelegate.swift"), compilerFlags: nil)], diff --git a/Tests/TuistIntegrationTests/Generator/StableStructureIntegrationTests.swift b/Tests/TuistIntegrationTests/Generator/StableStructureIntegrationTests.swift index d405a68ac1d..e67715cc6ea 100644 --- a/Tests/TuistIntegrationTests/Generator/StableStructureIntegrationTests.swift +++ b/Tests/TuistIntegrationTests/Generator/StableStructureIntegrationTests.swift @@ -110,6 +110,7 @@ final class StableXcodeProjIntegrationTests: XCTestCase { return Target(name: "AppTarget", platform: .iOS, product: .app, + productName: "AppTarget", bundleId: "test.bundle", settings: settings, sources: createSources(), @@ -186,6 +187,7 @@ final class StableXcodeProjIntegrationTests: XCTestCase { return Target(name: name, platform: .iOS, product: .framework, + productName: name, bundleId: "test.bundle.\(name)", settings: nil, sources: [], diff --git a/Tests/TuistKitTests/Generator/Mocks/MockManifestTargetGenerator.swift b/Tests/TuistKitTests/Generator/Mocks/MockManifestTargetGenerator.swift index a0b3cf59d03..43760a511fb 100644 --- a/Tests/TuistKitTests/Generator/Mocks/MockManifestTargetGenerator.swift +++ b/Tests/TuistKitTests/Generator/Mocks/MockManifestTargetGenerator.swift @@ -14,6 +14,7 @@ final class MockManifestTargetGenerator: ManifestTargetGenerating { return Target(name: name, platform: .iOS, product: .framework, + productName: name, bundleId: "io.tuist.testing", infoPlist: nil, filesGroup: .group(name: "Manifest")) diff --git a/fixtures/ios_app_with_frameworks/App/Project.swift b/fixtures/ios_app_with_frameworks/App/Project.swift index 6c97262d61b..d7e8fee633c 100644 --- a/fixtures/ios_app_with_frameworks/App/Project.swift +++ b/fixtures/ios_app_with_frameworks/App/Project.swift @@ -13,8 +13,8 @@ let project = Project(name: "MainApp", infoPlist: "Config/App-Info.plist", sources: "Sources/**", dependencies: [ - .project(target: "Framework1", path: "../Framework1"), - .project(target: "Framework2", path: "../Framework2"), + .project(target: "Framework1-iOS", path: "../Framework1"), + .project(target: "Framework2-iOS", path: "../Framework2"), ]), Target(name: "AppTests", platform: .iOS, diff --git a/fixtures/ios_app_with_frameworks/Framework1/Project.swift b/fixtures/ios_app_with_frameworks/Framework1/Project.swift index b5ff2edefba..65a58a633c2 100644 --- a/fixtures/ios_app_with_frameworks/Framework1/Project.swift +++ b/fixtures/ios_app_with_frameworks/Framework1/Project.swift @@ -2,23 +2,34 @@ import ProjectDescription let project = Project(name: "Framework1", targets: [ - Target(name: "Framework1", + Target(name: "Framework1-iOS", platform: .iOS, product: .framework, + productName: "Framework1", bundleId: "io.tuist.Framework1", infoPlist: "Config/Framework1-Info.plist", sources: "Sources/**", dependencies: [ - .project(target: "Framework2", path: "../Framework2"), + .project(target: "Framework2-iOS", path: "../Framework2"), ]), - + Target(name: "Framework1-macOS", + platform: .macOS, + product: .framework, + productName: "Framework1", + bundleId: "io.tuist.Framework1", + infoPlist: "Config/Framework1-Info.plist", + sources: "Sources/**", + dependencies: [ + .project(target: "Framework2-macOS", path: "../Framework2"), + ]), Target(name: "Framework1Tests", platform: .iOS, product: .unitTests, + productName: "Framework1Tests", bundleId: "io.tuist.Framework1Tests", infoPlist: "Config/Framework1Tests-Info.plist", sources: "Tests/**", dependencies: [ - .target(name: "Framework1"), + .target(name: "Framework1-iOS"), ]), ]) diff --git a/fixtures/ios_app_with_frameworks/Framework2/Project.swift b/fixtures/ios_app_with_frameworks/Framework2/Project.swift index 023c72ea651..c87d2ef9a10 100644 --- a/fixtures/ios_app_with_frameworks/Framework2/Project.swift +++ b/fixtures/ios_app_with_frameworks/Framework2/Project.swift @@ -2,9 +2,10 @@ import ProjectDescription let project = Project(name: "Framework2", targets: [ - Target(name: "Framework2", + Target(name: "Framework2-iOS", platform: .iOS, product: .framework, + productName: "Framework2", bundleId: "io.tuist.Framework2", infoPlist: "Config/Framework2-Info.plist", sources: "Sources/**", @@ -12,7 +13,17 @@ let project = Project(name: "Framework2", private: "Sources/Private/**", project: "Sources/Project/**"), dependencies: []), - + Target(name: "Framework2-macOS", + platform: .macOS, + product: .framework, + productName: "Framework2", + bundleId: "io.tuist.Framework2", + infoPlist: "Config/Framework2-Info.plist", + sources: "Sources/**", + headers: Headers(public: "Sources/Public/**", + private: "Sources/Private/**", + project: "Sources/Project/**"), + dependencies: []), Target(name: "Framework2Tests", platform: .iOS, product: .unitTests, @@ -20,6 +31,6 @@ let project = Project(name: "Framework2", infoPlist: "Config/Framework2Tests-Info.plist", sources: "Tests/**", dependencies: [ - .target(name: "Framework2"), + .target(name: "Framework2-iOS"), ]), ])