Skip to content

Commit 2954e55

Browse files
authored
Merge pull request #184 from Dadoum/main
[PkgConfig] Add checks for circular dependencies
2 parents 207f9c6 + 4183919 commit 2954e55

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

Diff for: Sources/TSCUtility/PkgConfig.swift

+23-3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ public struct PCFileFinder {
104104
}
105105
}
106106

107+
/// Informations to track circular dependencies and other PkgConfig issues
108+
public class LoadingContext {
109+
public init() {
110+
pkgConfigStack = [String]()
111+
}
112+
113+
public var pkgConfigStack: [String]
114+
}
115+
107116
/// Information on an individual `pkg-config` supported package.
108117
public struct PkgConfig {
109118
/// The name of the package.
@@ -138,8 +147,10 @@ public struct PkgConfig {
138147
additionalSearchPaths: [AbsolutePath] = [],
139148
diagnostics: DiagnosticsEngine,
140149
fileSystem: FileSystem = localFileSystem,
141-
brewPrefix: AbsolutePath?
150+
brewPrefix: AbsolutePath?,
151+
loadingContext: LoadingContext = LoadingContext()
142152
) throws {
153+
loadingContext.pkgConfigStack.append(name)
143154

144155
if let path = try? AbsolutePath(validating: name) {
145156
guard fileSystem.isFile(path) else { throw PkgConfigError.couldNotFindConfigFile(name: name) }
@@ -163,13 +174,19 @@ public struct PkgConfig {
163174
var libs = [String]()
164175

165176
for dep in dependencies {
177+
if let index = loadingContext.pkgConfigStack.firstIndex(of: dep) {
178+
diagnostics.emit(warning: "circular dependency detected while parsing \(loadingContext.pkgConfigStack[0]): \(loadingContext.pkgConfigStack[index..<loadingContext.pkgConfigStack.count].joined(separator: " -> ")) -> \(dep)")
179+
continue
180+
}
181+
166182
// FIXME: This is wasteful, we should be caching the PkgConfig result.
167183
let pkg = try PkgConfig(
168-
name: dep,
184+
name: dep,
169185
additionalSearchPaths: additionalSearchPaths,
170186
diagnostics: diagnostics,
171187
fileSystem: fileSystem,
172-
brewPrefix: brewPrefix
188+
brewPrefix: brewPrefix,
189+
loadingContext: loadingContext
173190
)
174191

175192
cFlags += pkg.cFlags
@@ -184,6 +201,8 @@ public struct PkgConfig {
184201

185202
self.cFlags = parser.cFlags + dependencyFlags.cFlags + privateDependencyFlags.cFlags
186203
self.libs = parser.libs + dependencyFlags.libs
204+
205+
loadingContext.pkgConfigStack.removeLast();
187206
}
188207

189208
private static var envSearchPaths: [AbsolutePath] {
@@ -408,3 +427,4 @@ public struct PkgConfigParser {
408427
return splits
409428
}
410429
}
430+

Diff for: Tests/TSCUtilityTests/PkgConfigParserTests.swift

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ import TSCTestSupport
1515
@testable import TSCUtility
1616

1717
final class PkgConfigParserTests: XCTestCase {
18+
func testCircularPCFile() throws {
19+
XCTAssertTrue(try PkgConfig(name: "harfbuzz", additionalSearchPaths: [AbsolutePath(#file).parentDirectory.appending(components: "pkgconfigInputs")], diagnostics: DiagnosticsEngine(), brewPrefix: nil).diagnostics.diagnostics.contains { diagnostic in
20+
diagnostic.message.text == "circular dependency detected while parsing harfbuzz: harfbuzz -> freetype2 -> harfbuzz"
21+
})
22+
}
1823

1924
func testGTK3PCFile() {
2025
try! loadPCFile("gtk+-3.0.pc") { parser in

Diff for: Tests/TSCUtilityTests/pkgconfigInputs/freetype2.pc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
prefix=/usr
2+
exec_prefix=/usr
3+
libdir=/usr/lib
4+
includedir=/usr/include
5+
6+
Name: FreeType 2
7+
URL: https://freetype.org
8+
Description: A free, high-quality, and portable font engine.
9+
Version: 23.4.17
10+
Requires:
11+
Requires.private: harfbuzz
12+
Libs: -L${libdir} -lfreetype
13+
Libs.private: -lbz2
14+
Cflags: -I${includedir}/freetype2

Diff for: Tests/TSCUtilityTests/pkgconfigInputs/harfbuzz.pc

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
prefix=/usr
2+
libdir=${prefix}/lib
3+
includedir=${prefix}/include
4+
5+
Name: harfbuzz
6+
Description: HarfBuzz text shaping library
7+
Version: 2.7.4
8+
Requires.private: freetype2
9+
Libs: -L${libdir} -lharfbuzz
10+
Libs.private: -pthread -lm
11+
Cflags: -I${includedir}/harfbuzz

0 commit comments

Comments
 (0)