@@ -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.
108117public 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+
0 commit comments