From b61d9a4ed56e99ea056bf66103053bd8c77f2912 Mon Sep 17 00:00:00 2001 From: Kas Date: Thu, 12 Dec 2019 17:33:41 +0000 Subject: [PATCH] Remove duplicate HEADER_SEARCH_PATHS (#787) - In the even two library dependencies shared the same `publicHeaders` path (e.g. `libcrypto.a` and `libssl.a` in OpenSSL) duplicate entries were added to the `HEADER_SEARCH_PATHS` build setting - This was regressed due to an earlier change https://github.com/tuist/tuist/pull/751 - previously the uniquing was happening in the settings helper when build settings were extended multiple times - To resolve this, we now ensure we unique paths being added - Additionally a test is included to ensure this doesn't regress in the future Test Plan: - Verify the unit tests pass A bit of a contrived manual test case update the fixture in `fixtures/ios_app_with_static_libraries/Modules/A/Project.swift` ```swift let project = Project(name: "A", targets: [ Target(name: "A", platform: .iOS, product: .staticLibrary, bundleId: "io.tuist.A", infoPlist: "Info.plist", sources: "Sources/**", dependencies: [ .project(target: "B", path: "../B"), .library(path: "../C/prebuilt/C/libC.a", publicHeaders: "../C/prebuilt/C", swiftModuleMap: "../C/prebuilt/C/C.swiftmodule"), // Add a duplicate .library(path: "../C/prebuilt/C/libC.a", publicHeaders: "../C/prebuilt/C", swiftModuleMap: "../C/prebuilt/C/C.swiftmodule") ]) ]) ``` This of course causes a duplicate binary (hence why it wasn't included) but can help illustrate a situation where two `.library` dependencies point to the same `publicHeaders` path. --- CHANGELOG.md | 1 + .../Generator/LinkGenerator.swift | 2 +- .../Generator/LinkGeneratorTests.swift | 31 ++++++++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 446081725e7..08b6f4d24c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/ ### Fixed - Ensure custom search path settings are included in generated projects https://github.com/tuist/tuist/pull/751 by @kwridan +- Remove duplicate HEADER_SEARCH_PATHS https://github.com/tuist/tuist/pull/787 by @kwridan ## 0.19.0 diff --git a/Sources/TuistGenerator/Generator/LinkGenerator.swift b/Sources/TuistGenerator/Generator/LinkGenerator.swift index 3e8778c9344..909cebf5576 100644 --- a/Sources/TuistGenerator/Generator/LinkGenerator.swift +++ b/Sources/TuistGenerator/Generator/LinkGenerator.swift @@ -256,7 +256,7 @@ final class LinkGenerator: LinkGenerating { return } let value = SettingValue - .array(["$(inherited)"] + paths.sorted() + .array(["$(inherited)"] + paths.uniqued().sorted() .map { $0.relative(to: sourceRootPath).pathString } .map { "$(SRCROOT)/\($0)" }) let newSetting = [name: value] diff --git a/Tests/TuistGeneratorTests/Generator/LinkGeneratorTests.swift b/Tests/TuistGeneratorTests/Generator/LinkGeneratorTests.swift index 71e23f17edd..1281bb751d9 100644 --- a/Tests/TuistGeneratorTests/Generator/LinkGeneratorTests.swift +++ b/Tests/TuistGeneratorTests/Generator/LinkGeneratorTests.swift @@ -88,7 +88,7 @@ final class LinkGeneratorErrorTests: XCTestCase { XCTAssertEqual($0 as? LinkGeneratorError, LinkGeneratorError.missingProduct(name: "Test")) } } - + func test_generateEmbedPhase_setupEmbedFrameworksBuildPhase_whenXCFrameworkIsPresent() throws { // Given var dependencies: [GraphDependencyReference] = [] @@ -114,9 +114,9 @@ final class LinkGeneratorErrorTests: XCTestCase { let copyBuildPhase = try XCTUnwrap(pbxTarget.embedFrameworksBuildPhases().first) XCTAssertEqual(copyBuildPhase.name, "Embed Frameworks") let buildFiles = try XCTUnwrap(copyBuildPhase.files) - XCTAssertEqual(buildFiles.map { $0.file?.path }, [ "Test.xcframework"]) + XCTAssertEqual(buildFiles.map { $0.file?.path }, ["Test.xcframework"]) XCTAssertEqual(buildFiles.map { $0.settings as? [String: [String]] }, [ - ["ATTRIBUTES": ["CodeSignOnCopy"]] + ["ATTRIBUTES": ["CodeSignOnCopy"]], ]) } @@ -200,6 +200,29 @@ final class LinkGeneratorErrorTests: XCTestCase { ]) } + func test_setupHeadersSearchPaths_mergesDuplicates() throws { + // Given + let searchPaths = [ + AbsolutePath("/path/to/libraries"), + AbsolutePath("/path/to/libraries"), + AbsolutePath("/path/to/libraries"), + ] + let sourceRootPath = AbsolutePath("/path") + let xcodeprojElements = createXcodeprojElements() + + // When + try subject.setupHeadersSearchPath(searchPaths, + pbxTarget: xcodeprojElements.pbxTarget, + sourceRootPath: sourceRootPath) + + // Then + let config = xcodeprojElements.config + XCTAssertEqual(config.buildSettings["HEADER_SEARCH_PATHS"] as? [String], [ + "$(inherited)", + "$(SRCROOT)/to/libraries", + ]) + } + func test_setupHeadersSearchPath_throws_whenTheConfigurationListIsMissing() throws { let headersFolders = [AbsolutePath("/headers")] let pbxproj = PBXProj() @@ -513,7 +536,7 @@ final class LinkGeneratorErrorTests: XCTestCase { return projectFileElements } - + private func createFileElements(fileAbsolutePath: AbsolutePath) -> ProjectFileElements { let fileElements = ProjectFileElements() fileElements.elements[fileAbsolutePath] = PBXFileReference(path: fileAbsolutePath.basename)