Skip to content

Commit b3c0adb

Browse files
authored
Merge pull request #2779 from mliberman/fix/pkgconfig-dependencies
Fix Absolute Path Dependencies in `.pc` Files
2 parents 8a4f2ee + 731764b commit b3c0adb

File tree

5 files changed

+81
-16
lines changed

5 files changed

+81
-16
lines changed

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1460,7 +1460,7 @@ final class BuildPlanTests: XCTestCase {
14601460

14611461
let diagnostic = diagnostics.diagnostics.last!
14621462

1463-
XCTAssertEqual(diagnostic.message.text, "couldn't find pc file")
1463+
XCTAssertEqual(diagnostic.message.text, "couldn't find pc file for BTarget")
14641464
XCTAssertEqual(diagnostic.message.behavior, .warning)
14651465
XCTAssertEqual(diagnostic.location.description, "'BTarget' BTarget.pc")
14661466
}

swift-tools-support-core/Sources/TSCUtility/PkgConfig.swift

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ import TSCBasic
1212
import Foundation
1313

1414
public enum PkgConfigError: Swift.Error, CustomStringConvertible {
15-
case couldNotFindConfigFile
15+
case couldNotFindConfigFile(name: String)
1616
case parsingError(String)
1717
case nonWhitelistedFlags(String)
1818

1919
public var description: String {
2020
switch self {
21-
case .couldNotFindConfigFile:
22-
return "couldn't find pc file"
21+
case .couldNotFindConfigFile(let name):
22+
return "couldn't find pc file for \(name)"
2323
case .parsingError(let error):
2424
return "parsing error(s): \(error)"
2525
case .nonWhitelistedFlags(let flags):
@@ -89,7 +89,7 @@ public struct PCFileFinder {
8989
PCFileFinder.shouldEmitPkgConfigPathsDiagnostic = false
9090
diagnostics.emit(warning: "failed to retrieve search paths with pkg-config; maybe pkg-config is not installed")
9191
}
92-
throw PkgConfigError.couldNotFindConfigFile
92+
throw PkgConfigError.couldNotFindConfigFile(name: name)
9393
}
9494
}
9595

@@ -110,9 +110,6 @@ public struct PkgConfig {
110110
/// DiagnosticsEngine to emit diagnostics
111111
let diagnostics: DiagnosticsEngine
112112

113-
/// Helper to query `pkg-config` for library locations
114-
private let pkgFileFinder: PCFileFinder
115-
116113
/// Load the information for the named package.
117114
///
118115
/// It will search `fileSystem` for the pkg config file in the following order:
@@ -132,12 +129,19 @@ public struct PkgConfig {
132129
fileSystem: FileSystem = localFileSystem,
133130
brewPrefix: AbsolutePath?
134131
) throws {
135-
self.name = name
136-
self.pkgFileFinder = PCFileFinder(diagnostics: diagnostics, brewPrefix: brewPrefix)
137-
self.pcFile = try pkgFileFinder.locatePCFile(
138-
name: name,
139-
customSearchPaths: PkgConfig.envSearchPaths + additionalSearchPaths,
140-
fileSystem: fileSystem)
132+
133+
if let path = try? AbsolutePath(validating: name) {
134+
guard fileSystem.isFile(path) else { throw PkgConfigError.couldNotFindConfigFile(name: name) }
135+
self.name = path.basenameWithoutExt
136+
self.pcFile = path
137+
} else {
138+
self.name = name
139+
let pkgFileFinder = PCFileFinder(diagnostics: diagnostics, brewPrefix: brewPrefix)
140+
self.pcFile = try pkgFileFinder.locatePCFile(
141+
name: name,
142+
customSearchPaths: PkgConfig.envSearchPaths + additionalSearchPaths,
143+
fileSystem: fileSystem)
144+
}
141145

142146
self.diagnostics = diagnostics
143147
var parser = PkgConfigParser(pcFile: pcFile, fileSystem: fileSystem)
@@ -153,6 +157,7 @@ public struct PkgConfig {
153157
name: dep,
154158
additionalSearchPaths: additionalSearchPaths,
155159
diagnostics: diagnostics,
160+
fileSystem: fileSystem,
156161
brewPrefix: brewPrefix
157162
)
158163

swift-tools-support-core/Tests/TSCUtilityTests/PkgConfigParserTests.swift

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,36 @@ final class PkgConfigParserTests: XCTestCase {
129129
XCTAssertEqual(PCFileFinder.pkgConfigPaths, [AbsolutePath("/Volumes/BestDrive/pkgconfig")])
130130
}
131131

132+
func testAbsolutePathDependency() throws {
133+
134+
let libffiPath = "/usr/local/opt/libffi/lib/pkgconfig/libffi.pc"
135+
136+
try loadPCFile("gobject-2.0.pc") { parser in
137+
XCTAssert(parser.dependencies.isEmpty)
138+
XCTAssertEqual(parser.privateDependencies, [libffiPath])
139+
}
140+
141+
try loadPCFile("libffi.pc") { parser in
142+
XCTAssert(parser.dependencies.isEmpty)
143+
XCTAssert(parser.privateDependencies.isEmpty)
144+
}
145+
146+
let fileSystem = try InMemoryFileSystem(
147+
files: [
148+
"/usr/local/opt/glib/lib/pkgconfig/gobject-2.0.pc": pcFileByteString("gobject-2.0.pc"),
149+
libffiPath: pcFileByteString("libffi.pc")
150+
]
151+
)
152+
153+
XCTAssertNoThrow(
154+
try PkgConfig(
155+
name: "gobject-2.0",
156+
additionalSearchPaths: [AbsolutePath("/usr/local/opt/glib/lib/pkgconfig")],
157+
diagnostics: DiagnosticsEngine(),
158+
fileSystem: fileSystem,
159+
brewPrefix: AbsolutePath("/usr/local")))
160+
}
161+
132162
func testUnevenQuotes() throws {
133163
do {
134164
try loadPCFile("quotes_failure.pc")
@@ -138,10 +168,17 @@ final class PkgConfigParserTests: XCTestCase {
138168
}
139169
}
140170

171+
private func pcFilePath(_ inputName: String) -> AbsolutePath {
172+
return AbsolutePath(#file).parentDirectory.appending(components: "pkgconfigInputs", inputName)
173+
}
174+
141175
private func loadPCFile(_ inputName: String, body: ((PkgConfigParser) -> Void)? = nil) throws {
142-
let input = AbsolutePath(#file).parentDirectory.appending(components: "pkgconfigInputs", inputName)
143-
var parser = PkgConfigParser(pcFile: input, fileSystem: localFileSystem)
176+
var parser = PkgConfigParser(pcFile: pcFilePath(inputName), fileSystem: localFileSystem)
144177
try parser.parse()
145178
body?(parser)
146179
}
180+
181+
private func pcFileByteString(_ inputName: String) throws -> ByteString {
182+
return try localFileSystem.readFileContents(pcFilePath(inputName))
183+
}
147184
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
prefix=/usr/local/Cellar/glib/2.64.3
2+
libdir=${prefix}/lib
3+
includedir=${prefix}/include
4+
5+
Name: GObject
6+
Description: GLib Type, Object, Parameter and Signal Library
7+
Version: 2.64.3
8+
# Requires: glib-2.0
9+
Requires.private: /usr/local/opt/libffi/lib/pkgconfig/libffi.pc >= 3.0.0
10+
Libs: -L${libdir} -lgobject-2.0
11+
Libs.private: -lintl
12+
Cflags:-I${includedir}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
prefix=/usr/local/Cellar/libffi/3.3
2+
exec_prefix=${prefix}
3+
libdir=${exec_prefix}/lib
4+
toolexeclibdir=${libdir}
5+
includedir=${prefix}/include
6+
7+
Name: libffi
8+
Description: Library supporting Foreign Function Interfaces
9+
Version: 3.3
10+
Libs: -L${toolexeclibdir} -lffi
11+
Cflags: -I${includedir}

0 commit comments

Comments
 (0)