Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for defining PRODUCT_NAME in the manifest #435

Merged
merged 15 commits into from Jul 5, 2019
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/

### Added
- `tuist graph` command https://github.com/tuist/tuist/pull/427 by @pepibumur.
- Allow customisation of `productName` in the project Manifest https://github.com/tuist/tuist/pull/435 by @ollieatkinson

### Fixed

Expand Down
8 changes: 8 additions & 0 deletions Sources/ProjectDescription/Target.swift
Expand Up @@ -15,6 +15,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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Sources/TuistGenerator/Generator/BuildPhaseGenerator.swift
Expand Up @@ -245,7 +245,7 @@ final class BuildPhaseGenerator: BuildPhaseGenerating {
resourcesBuildPhase: PBXResourcesBuildPhase) {
let bundles = graph.resourceBundleDependencies(path: path, name: target.name)
let sortedBundles = bundles.sorted { $0.target.name < $1.target.name }
let refs = sortedBundles.compactMap { fileElements.product(name: $0.target.productNameWithExtension) }
let refs = sortedBundles.compactMap { fileElements.product(target: $0.target.name) }

refs.forEach {
let pbxBuildFile = PBXBuildFile(file: $0)
Expand Down
6 changes: 4 additions & 2 deletions Sources/TuistGenerator/Generator/ConfigGenerator.swift
Expand Up @@ -175,16 +175,18 @@ final class ConfigGenerator: ConfigGenerating {
settings["MACH_O_TYPE"] = "staticlib"
}

settings["PRODUCT_NAME"] = target.productName
ollieatkinson marked this conversation as resolved.
Show resolved Hide resolved

if target.product.testsBundle {
let appDependency = graph.targetDependencies(path: sourceRootPath, name: target.name).first { targetNode in
targetNode.target.product == .app
}

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)"
}
}
Expand Down
16 changes: 8 additions & 8 deletions Sources/TuistGenerator/Generator/LinkGenerator.swift
Expand Up @@ -78,7 +78,7 @@ final class LinkGenerator: LinkGenerating {
let headersSearchPaths = graph.librariesPublicHeadersFolders(path: path, name: target.name)
let librarySearchPaths = graph.librariesSearchPaths(path: path, name: target.name)
let swiftIncludePaths = graph.librariesSwiftIncludePaths(path: path, name: target.name)
let linkableModules = try graph.linkableDependencies(path: path, name: target.name)
let linkableModules = try graph.linkableDependencies(path: path, name: target.name, system: system)

try generateEmbedPhase(dependencies: embeddableFrameworks,
pbxTarget: pbxTarget,
Expand Down Expand Up @@ -139,8 +139,8 @@ final class LinkGenerator: LinkGenerating {
precompiledEmbedPhase.inputPaths.append(relativePath)
precompiledEmbedPhase.outputPaths.append("$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/\(path.components.last!)")

} else if case let DependencyReference.product(name) = dependency {
guard let fileRef = fileElements.product(name: name) else {
} else if case let DependencyReference.product(target, name) = dependency {
guard let fileRef = fileElements.product(target: target) else {
throw LinkGeneratorError.missingProduct(name: name)
}
let buildFile = PBXBuildFile(file: fileRef, settings: ["ATTRIBUTES": ["CodeSignOnCopy"]])
Expand Down Expand Up @@ -234,8 +234,8 @@ final class LinkGenerator: LinkGenerating {
let buildFile = PBXBuildFile(file: fileRef)
pbxproj.add(object: buildFile)
buildPhase.files?.append(buildFile)
case let .product(name):
guard let fileRef = fileElements.product(name: name) else {
case let .product(target, name):
guard let fileRef = fileElements.product(target: target) else {
throw LinkGeneratorError.missingProduct(name: name)
}
let buildFile = PBXBuildFile(file: fileRef)
Expand Down Expand Up @@ -280,7 +280,7 @@ final class LinkGenerator: LinkGenerating {

dependencies.append(contentsOf:
graph.resourceBundleDependencies(path: path, name: target.name)
.map { .product($0.target.productNameWithExtension) })
.map { .product(target: $0.target.name, name: $0.target.productNameWithExtension) })

if !dependencies.isEmpty {
try generateDependenciesBuildPhase(
Expand All @@ -298,8 +298,8 @@ final class LinkGenerator: LinkGenerating {
fileElements: ProjectFileElements) throws {
var files: [PBXBuildFile] = []

for case let .product(name) in dependencies.sorted() {
guard let fileRef = fileElements.product(name: name) else {
for case let .product(target, name) in dependencies.sorted() {
guard let fileRef = fileElements.product(target: target) else {
throw LinkGeneratorError.missingProduct(name: name)
}

Expand Down
20 changes: 10 additions & 10 deletions Sources/TuistGenerator/Generator/ProjectFileElements.swift
Expand Up @@ -189,36 +189,36 @@ class ProjectFileElements {
groups: ProjectGroups,
pbxproj: PBXProj) throws {
try prepareProductsFileReferences(project: project, dependencies: dependencies).forEach { pair in
guard self.products[pair.productName] == nil else { return }
guard self.products[pair.targetName] == nil else { return }
pbxproj.add(object: pair.fileReference)
groups.products.children.append(pair.fileReference)
self.products[pair.productName] = pair.fileReference
self.products[pair.targetName] = pair.fileReference
}
}

func prepareProductsFileReferences(project: Project, dependencies: Set<GraphNode>)
throws -> [(productName: String, fileReference: PBXFileReference)] {
throws -> [(targetName: String, fileReference: PBXFileReference)] {
let targetsProducts = project.targets
.map { ($0.productNameWithExtension, $0.product) }
.map { ($0, $0.product) }
let dependenciesProducts = dependencies
.compactMap { $0 as? TargetNode }
.map { $0.target }
.map { ($0.productNameWithExtension, $0.product) }
.map { ($0, $0.product) }
let mergeStrategy: (Product, Product) -> Product = { first, _ in first }
let sortByName: ((String, Product), (String, Product)) -> Bool = { first, second in first.0 < second.0 }
let sortByName: ((Target, Product), (Target, Product)) -> Bool = { first, second in first.0.productNameWithExtension < second.0.productNameWithExtension }

let targetsProductsDictionary = Dictionary(targetsProducts, uniquingKeysWith: mergeStrategy)
let dependenciesProductsDictionary = Dictionary(dependenciesProducts, uniquingKeysWith: mergeStrategy)
let productsDictionary = targetsProductsDictionary.merging(dependenciesProductsDictionary,
uniquingKeysWith: mergeStrategy)
return productsDictionary
.sorted(by: sortByName)
.map { productName, product in
.map { target, product in
let fileType = Xcode.filetype(extension: product.xcodeValue.fileExtension!)
return (productName: productName,
return (targetName: target.name,
fileReference: PBXFileReference(sourceTree: .buildProductsDir,
explicitFileType: fileType,
path: productName,
path: target.productNameWithExtension,
includeInIndex: false))
}
}
Expand Down Expand Up @@ -484,7 +484,7 @@ class ProjectFileElements {
return elements[path] as? PBXGroup
}

func product(name: String) -> PBXFileReference? {
func product(target name: String) -> PBXFileReference? {
return products[name]
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/TuistGenerator/Generator/SchemesGenerator.swift
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions Sources/TuistGenerator/Generator/TargetGenerator.swift
Expand Up @@ -56,7 +56,7 @@ final class TargetGenerator: TargetGenerating {
graph: Graphing,
system: Systeming = System()) throws -> PBXNativeTarget {
/// Products reference.
let productFileReference = fileElements.products[target.productNameWithExtension]!
let productFileReference = fileElements.products[target.name]!

/// Target
let pbxTarget = PBXNativeTarget(name: target.name,
Expand All @@ -65,7 +65,7 @@ final class TargetGenerator: TargetGenerating {
buildRules: [],
dependencies: [],
productInstallPath: nil,
productName: target.name,
productName: target.productName,
product: productFileReference,
productType: target.product.xcodeValue)
pbxproj.add(object: pbxTarget)
Expand Down