Skip to content

[PkgConfig] Add checks for circular dependencies #184

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

Merged
merged 6 commits into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions Sources/TSCUtility/PkgConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ public struct PCFileFinder {
}
}

/// Informations to track circular dependencies and other PkgConfig issues
public class LoadingContext {
public init() {
pkgConfigStack = [String]()
}

public var pkgConfigStack: [String]
}

/// Information on an individual `pkg-config` supported package.
public struct PkgConfig {
/// The name of the package.
Expand Down Expand Up @@ -138,8 +147,10 @@ public struct PkgConfig {
additionalSearchPaths: [AbsolutePath] = [],
diagnostics: DiagnosticsEngine,
fileSystem: FileSystem = localFileSystem,
brewPrefix: AbsolutePath?
brewPrefix: AbsolutePath?,
loadingContext: LoadingContext = LoadingContext()
) throws {
loadingContext.pkgConfigStack.append(name)

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

for dep in dependencies {
if let index = loadingContext.pkgConfigStack.firstIndex(of: dep) {
diagnostics.emit(warning: "circular dependency detected while parsing \(loadingContext.pkgConfigStack[0]): \(loadingContext.pkgConfigStack[index..<loadingContext.pkgConfigStack.count].joined(separator: " -> ")) -> \(dep)")
continue
}

// FIXME: This is wasteful, we should be caching the PkgConfig result.
let pkg = try PkgConfig(
name: dep,
name: dep,
additionalSearchPaths: additionalSearchPaths,
diagnostics: diagnostics,
fileSystem: fileSystem,
brewPrefix: brewPrefix
brewPrefix: brewPrefix,
loadingContext: loadingContext
)

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

self.cFlags = parser.cFlags + dependencyFlags.cFlags + privateDependencyFlags.cFlags
self.libs = parser.libs + dependencyFlags.libs

loadingContext.pkgConfigStack.removeLast();
}

private static var envSearchPaths: [AbsolutePath] {
Expand Down Expand Up @@ -408,3 +427,4 @@ public struct PkgConfigParser {
return splits
}
}

5 changes: 5 additions & 0 deletions Tests/TSCUtilityTests/PkgConfigParserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import TSCTestSupport
@testable import TSCUtility

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

func testGTK3PCFile() {
try! loadPCFile("gtk+-3.0.pc") { parser in
Expand Down
14 changes: 14 additions & 0 deletions Tests/TSCUtilityTests/pkgconfigInputs/freetype2.pc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
prefix=/usr
exec_prefix=/usr
libdir=/usr/lib
includedir=/usr/include

Name: FreeType 2
URL: https://freetype.org
Description: A free, high-quality, and portable font engine.
Version: 23.4.17
Requires:
Requires.private: harfbuzz
Libs: -L${libdir} -lfreetype
Libs.private: -lbz2
Cflags: -I${includedir}/freetype2
11 changes: 11 additions & 0 deletions Tests/TSCUtilityTests/pkgconfigInputs/harfbuzz.pc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
prefix=/usr
libdir=${prefix}/lib
includedir=${prefix}/include

Name: harfbuzz
Description: HarfBuzz text shaping library
Version: 2.7.4
Requires.private: freetype2
Libs: -L${libdir} -lharfbuzz
Libs.private: -pthread -lm
Cflags: -I${includedir}/harfbuzz