Skip to content
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

Add --pkg-config-path to LocationOptions #5949

Merged
merged 10 commits into from
Dec 19, 2022
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ Note: This is in reverse chronological order, so newer entries are added to the
Swift 5.8
-----------

* [#5949]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should sort these

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already in reverse chronological order, or would you like to see some other sorting?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the rest of the document has is non-reverse chronological order?


New `--pkg-config-path` option on `build`, `test`, and `run` commands has been
introduced as an alternative to passing `PKG_CONFIG_PATH` environment variable.
It allows specifying alternative path to search for `.pc` files used by
`pkg-config`. Use the option multiple times to specify more than one path.

* [#5874]

In packages using tools version 5.8 or later, Foundation is no longer implicitly imported into package manifests. If Foundation APIs are used, the module needs to be imported explicitly.
Expand Down
12 changes: 9 additions & 3 deletions Sources/Build/BuildOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
/// The output stream for the build delegate.
private let outputStream: OutputByteStream

/// The verbosity level to print out at
/// The verbosity level to use for diagnostics.
private let logLevel: Basics.Diagnostic.Severity

/// File system to operate on
/// File system to operate on.
private let fileSystem: TSCBasic.FileSystem

/// ObservabilityScope with which to emit diagnostics
/// ObservabilityScope with which to emit diagnostics.
private let observabilityScope: ObservabilityScope

public var builtTestProducts: [BuiltTestProduct] {
Expand All @@ -95,6 +95,9 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
/// File rules to determine resource handling behavior.
private let additionalFileRules: [FileRuleDescription]

/// Alternative path to search for pkg-config `.pc` files.
private let pkgConfigDirectories: [AbsolutePath]

public init(
buildParameters: BuildParameters,
cacheBuildManifest: Bool,
Expand All @@ -103,6 +106,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
pluginScriptRunner: PluginScriptRunner,
pluginWorkDirectory: AbsolutePath,
disableSandboxForPluginCommands: Bool,
pkgConfigDirectories: [AbsolutePath],
outputStream: OutputByteStream,
logLevel: Basics.Diagnostic.Severity,
fileSystem: TSCBasic.FileSystem,
Expand All @@ -118,6 +122,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
self.additionalFileRules = additionalFileRules
self.pluginScriptRunner = pluginScriptRunner
self.pluginWorkDirectory = pluginWorkDirectory
self.pkgConfigDirectories = pkgConfigDirectories
self.disableSandboxForPluginCommands = disableSandboxForPluginCommands
self.outputStream = outputStream
self.logLevel = logLevel
Expand Down Expand Up @@ -399,6 +404,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
builtToolsDir: self.buildParameters.buildPath,
buildEnvironment: self.buildParameters.buildEnvironment,
toolSearchDirectories: [self.buildParameters.toolchain.swiftCompilerPath.parentDirectory],
pkgConfigDirectories: self.pkgConfigDirectories,
pluginScriptRunner: self.pluginScriptRunner,
observabilityScope: self.observabilityScope,
fileSystem: self.fileSystem
Expand Down
7 changes: 6 additions & 1 deletion Sources/Build/BuildPlan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2416,7 +2416,12 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
else {
pkgConfigCache[target] = ([], [])
}
let results = try pkgConfigArgs(for: target, fileSystem: self.fileSystem, observabilityScope: self.observabilityScope)
let results = try pkgConfigArgs(
for: target,
pkgConfigDirectories: buildParameters.pkgConfigDirectories,
fileSystem: fileSystem,
observabilityScope: observabilityScope
)
var ret: [(cFlags: [String], libs: [String])] = []
for result in results {
ret.append((result.cFlags, result.libs))
Expand Down
1 change: 1 addition & 0 deletions Sources/Commands/PackageTools/PluginCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ struct PluginCommand: SwiftCommand {
toolNamesToTriples: toolNamesToTriples,
writableDirectories: writableDirectories,
readOnlyDirectories: readOnlyDirectories,
pkgConfigDirectories: swiftTool.options.locations.pkgConfigDirectories,
fileSystem: swiftTool.fileSystem,
observabilityScope: swiftTool.observabilityScope,
callbackQueue: delegateQueue,
Expand Down
1 change: 1 addition & 0 deletions Sources/CoreCommands/BuildSystemSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extension SwiftTool {
pluginScriptRunner: self.getPluginScriptRunner(),
pluginWorkDirectory: try self.getActiveWorkspace().location.pluginWorkingDirectory,
disableSandboxForPluginCommands: self.options.security.shouldDisableSandbox,
pkgConfigDirectories: self.options.locations.pkgConfigDirectories,
outputStream: customOutputStream ?? self.outputStream,
logLevel: customLogLevel ?? self.logLevel,
fileSystem: self.fileSystem,
Expand Down
10 changes: 10 additions & 0 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ public struct LocationOptions: ParsableArguments {

@Option(name: .customLong("experimental-destinations-path"), help: .hidden, completion: .directory)
public var crossCompilationDestinationsDirectory: AbsolutePath?

@Option(
name: .customLong("pkg-config-path"),
help:
"""
Specify alternative path to search for pkg-config `.pc` files. Use the option multiple times to
specify more than one path.
""",
completion: .directory)
public var pkgConfigDirectories: [AbsolutePath] = []
}

public struct CachingOptions: ParsableArguments {
Expand Down
9 changes: 5 additions & 4 deletions Sources/CoreCommands/SwiftTool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,11 @@ public final class SwiftTool {
(packageRoot ?? cwd).appending(component: ".build")

// make sure common directories are created
self.sharedSecurityDirectory = try getSharedSecurityDirectory(options: self.options, fileSystem: fileSystem)
self.sharedConfigurationDirectory = try getSharedConfigurationDirectory(options: self.options, fileSystem: fileSystem)
self.sharedCacheDirectory = try getSharedCacheDirectory(options: self.options, fileSystem: fileSystem)
self.sharedSecurityDirectory = try getSharedSecurityDirectory(options: options, fileSystem: fileSystem)
self.sharedConfigurationDirectory = try getSharedConfigurationDirectory(options: options, fileSystem: fileSystem)
self.sharedCacheDirectory = try getSharedCacheDirectory(options: options, fileSystem: fileSystem)
self.sharedCrossCompilationDestinationsDirectory = try fileSystem.getSharedCrossCompilationDestinationsDirectory(
explicitDirectory: self.options.locations.crossCompilationDestinationsDirectory
explicitDirectory: options.locations.crossCompilationDestinationsDirectory
)

// set global process logging handler
Expand Down Expand Up @@ -593,6 +593,7 @@ public final class SwiftTool {
archs: options.build.archs,
flags: options.build.buildFlags,
xcbuildFlags: options.build.xcbuildFlags,
pkgConfigDirectories: options.locations.pkgConfigDirectories,
jobs: options.build.jobs ?? UInt32(ProcessInfo.processInfo.activeProcessorCount),
shouldLinkStaticSwiftStdlib: options.linker.shouldLinkStaticSwiftStdlib,
canRenameEntrypointFunctionName: DriverSupport.checkSupportedFrontendFlags(
Expand Down
33 changes: 24 additions & 9 deletions Sources/PackageLoading/Target+PkgConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,28 @@ public struct PkgConfigResult {
}

/// Get pkgConfig result for a system library target.
public func pkgConfigArgs(for target: SystemLibraryTarget, brewPrefix: AbsolutePath? = .none, fileSystem: FileSystem, observabilityScope: ObservabilityScope) throws -> [PkgConfigResult] {
public func pkgConfigArgs(
for target: SystemLibraryTarget,
pkgConfigDirectories: [AbsolutePath],
brewPrefix: AbsolutePath? = .none,
fileSystem: FileSystem,
observabilityScope: ObservabilityScope
) throws -> [PkgConfigResult] {
// If there is no pkg config name defined, we're done.
guard let pkgConfigNames = target.pkgConfig else { return [] }

// Compute additional search paths for the provider, if any.
let provider = target.providers?.first { $0.isAvailable }
let additionalSearchPaths = try provider?.pkgConfigSearchPath(brewPrefixOverride: brewPrefix) ?? []

var ret: [PkgConfigResult] = []
let additionalSearchPaths: [AbsolutePath]
// Give priority to `pkgConfigDirectories` passed as an argument to this function.
if let providerSearchPaths = try provider?.pkgConfigSearchPath(brewPrefixOverride: brewPrefix) {
additionalSearchPaths = pkgConfigDirectories + providerSearchPaths
} else {
additionalSearchPaths = pkgConfigDirectories
}

var ret: [PkgConfigResult] = []
// Get the pkg config flags.
for pkgConfigName in pkgConfigNames.components(separatedBy: " ") {
let result: PkgConfigResult
Expand All @@ -92,19 +105,21 @@ public func pkgConfigArgs(for target: SystemLibraryTarget, brewPrefix: AbsoluteP
}

result = PkgConfigResult(
pkgConfigName: pkgConfigName,
cFlags: cFlags,
libs: libs,
error: error,
provider: provider
pkgConfigName: pkgConfigName,
cFlags: cFlags,
libs: libs,
error: error,
provider: provider
)
MaxDesiatov marked this conversation as resolved.
Show resolved Hide resolved
} catch {
result = PkgConfigResult(pkgConfigName: pkgConfigName, error: error, provider: provider)
}

// If there is no pc file on system and we have an available provider, emit a warning.
if let provider = result.provider, result.couldNotFindConfigFile {
observabilityScope.emit(warning: "you may be able to install \(result.pkgConfigName) using your system-packager:\n\(provider.installText)")
observabilityScope.emit(
warning: "you may be able to install \(result.pkgConfigName) using your system-packager:\n\(provider.installText)"
)
} else if let error = result.error {
observabilityScope.emit(
warning: "\(error)",
Expand Down
2 changes: 1 addition & 1 deletion Sources/PackageModel/BuildEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//

/// A build environment with which to evaluation conditions.
/// A build environment with which to evaluate conditions.
public struct BuildEnvironment: Codable {
public let platform: Platform
public let configuration: BuildConfiguration?
Expand Down
11 changes: 8 additions & 3 deletions Sources/SPMBuildCore/BuildParameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ public struct BuildParameters: Encodable {
/// Extra build flags.
public var flags: BuildFlags

/// An array of paths to search for pkg-config `.pc` files.
public var pkgConfigDirectories: [AbsolutePath]

/// How many jobs should llbuild and the Swift compiler spawn
public var jobs: UInt32

Expand All @@ -155,7 +158,7 @@ public struct BuildParameters: Encodable {
/// Whether to enable code coverage.
public var enableCodeCoverage: Bool

/// Whether to enable generation of `.swiftinterface` files alongside
/// Whether to enable generation of `.swiftinterface` files alongside.
/// `.swiftmodule`s.
public var enableParseableModuleInterfaces: Bool

Expand All @@ -168,10 +171,10 @@ public struct BuildParameters: Encodable {
/// to a separate process.
public var useIntegratedSwiftDriver: Bool

/// Whether to use the explicit module build flow (with the integrated driver)
/// Whether to use the explicit module build flow (with the integrated driver).
public var useExplicitModuleBuild: Bool

/// A flag that inidcates this build should check whether targets only import
/// A flag that inidcates this build should check whether targets only import.
/// their explicitly-declared dependencies
public var explicitTargetDependencyImportCheckingMode: TargetDependencyImportCheckingMode

Expand Down Expand Up @@ -231,6 +234,7 @@ public struct BuildParameters: Encodable {
archs: [String] = [],
flags: BuildFlags,
xcbuildFlags: [String] = [],
pkgConfigDirectories: [AbsolutePath] = [],
jobs: UInt32 = UInt32(ProcessInfo.processInfo.activeProcessorCount),
shouldLinkStaticSwiftStdlib: Bool = false,
shouldEnableManifestCaching: Bool = false,
Expand Down Expand Up @@ -261,6 +265,7 @@ public struct BuildParameters: Encodable {
self.triple = triple
self.archs = archs
self.flags = flags
self.pkgConfigDirectories = pkgConfigDirectories
self.xcbuildFlags = xcbuildFlags
self.jobs = jobs
self.shouldLinkStaticSwiftStdlib = shouldLinkStaticSwiftStdlib
Expand Down
8 changes: 7 additions & 1 deletion Sources/SPMBuildCore/PluginContextSerializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typealias WireInput = HostToPluginMessage.InputContext
internal struct PluginContextSerializer {
let fileSystem: FileSystem
let buildEnvironment: BuildEnvironment
let pkgConfigDirectories: [AbsolutePath]
var paths: [WireInput.Path] = []
var pathsToIds: [AbsolutePath: WireInput.Path.Id] = [:]
var targets: [WireInput.Target] = []
Expand Down Expand Up @@ -105,7 +106,12 @@ internal struct PluginContextSerializer {
var ldFlags: [String] = []
// FIXME: What do we do with any diagnostics here?
let observabilityScope = ObservabilitySystem({ _, _ in }).topScope
for result in try pkgConfigArgs(for: target, fileSystem: self.fileSystem, observabilityScope: observabilityScope) {
for result in try pkgConfigArgs(
for: target,
pkgConfigDirectories: pkgConfigDirectories,
fileSystem: fileSystem,
observabilityScope: observabilityScope
) {
if let error = result.error {
observabilityScope.emit(
warning: "\(error)",
Expand Down
10 changes: 9 additions & 1 deletion Sources/SPMBuildCore/PluginInvocation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extension PluginTarget {
/// - workingDirectory: The initial working directory of the invoked plugin.
/// - outputDirectory: A directory under which the plugin can write anything it wants to.
/// - toolNamesToPaths: A mapping from name of tools available to the plugin to the corresponding absolute paths.
/// - pkgConfigDirectory: A directory for searching `pkg-config` `.pc` files in it.
/// - fileSystem: The file system to which all of the paths refers.
///
/// - Returns: A PluginInvocationResult that contains the results of invoking the plugin.
Expand All @@ -58,6 +59,7 @@ extension PluginTarget {
toolNamesToTriples: [String: [String]],
writableDirectories: [AbsolutePath],
readOnlyDirectories: [AbsolutePath],
pkgConfigDirectories: [AbsolutePath],
fileSystem: FileSystem,
observabilityScope: ObservabilityScope,
callbackQueue: DispatchQueue,
Expand All @@ -75,7 +77,11 @@ extension PluginTarget {
// Serialize the plugin action to send as the initial message.
let initialMessage: Data
do {
var serializer = PluginContextSerializer(fileSystem: fileSystem, buildEnvironment: buildEnvironment)
var serializer = PluginContextSerializer(
fileSystem: fileSystem,
buildEnvironment: buildEnvironment,
pkgConfigDirectories: pkgConfigDirectories
)
let pluginWorkDirId = try serializer.serialize(path: outputDirectory)
let toolSearchDirIds = try toolSearchDirectories.map{ try serializer.serialize(path: $0) }
let toolNamesToPathIds = try toolNamesToPaths.mapValues{ try serializer.serialize(path: $0) }
Expand Down Expand Up @@ -325,6 +331,7 @@ extension PackageGraph {
builtToolsDir: AbsolutePath,
buildEnvironment: BuildEnvironment,
toolSearchDirectories: [AbsolutePath],
pkgConfigDirectories: [AbsolutePath],
pluginScriptRunner: PluginScriptRunner,
observabilityScope: ObservabilityScope,
fileSystem: FileSystem
Expand Down Expand Up @@ -466,6 +473,7 @@ extension PackageGraph {
toolNamesToTriples: toolNamesToTriples,
writableDirectories: writableDirectories,
readOnlyDirectories: readOnlyDirectories,
pkgConfigDirectories: pkgConfigDirectories,
fileSystem: fileSystem,
observabilityScope: observabilityScope,
callbackQueue: delegateQueue,
Expand Down
24 changes: 11 additions & 13 deletions Sources/XCBuildSupport/PIFBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,16 @@ import SPMBuildCore
struct PIFBuilderParameters {

/// Whether or not build for testability is enabled.
public let enableTestability: Bool
let enableTestability: Bool

/// Whether to create dylibs for dynamic library products.
public let shouldCreateDylibForDynamicProducts: Bool
let shouldCreateDylibForDynamicProducts: Bool

/// The path to the library directory of the active toolchain.
public let toolchainLibDir: AbsolutePath
let toolchainLibDir: AbsolutePath

/// Creates a `PIFBuilderParameters` instance.
/// - Parameters:
/// - enableTestability: Whether or not build for testability is enabled.
/// - shouldCreateDylibForDynamicProducts: Whether to create dylibs for dynamic library products.
public init(enableTestability: Bool, shouldCreateDylibForDynamicProducts: Bool, toolchainLibDir: AbsolutePath) {
self.enableTestability = enableTestability
self.shouldCreateDylibForDynamicProducts = shouldCreateDylibForDynamicProducts
self.toolchainLibDir = toolchainLibDir
}
/// An array of paths to search for pkg-config `.pc` files.
let pkgConfigDirectories: [AbsolutePath]
}

/// PIF object builder for a package graph.
Expand Down Expand Up @@ -708,7 +701,12 @@ final class PackagePIFProjectBuilder: PIFProjectBuilder {
var impartedSettings = PIF.BuildSettings()

var cFlags: [String] = []
for result in try pkgConfigArgs(for: systemTarget, fileSystem: fileSystem, observabilityScope: self.observabilityScope) {
for result in try pkgConfigArgs(
for: systemTarget,
pkgConfigDirectories: parameters.pkgConfigDirectories,
fileSystem: fileSystem,
observabilityScope: observabilityScope
) {
if let error = result.error {
self.observabilityScope.emit(
warning: "\(error)",
Expand Down
3 changes: 2 additions & 1 deletion Sources/XCBuildSupport/XcodeBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ extension PIFBuilderParameters {
self.init(
enableTestability: buildParameters.enableTestability,
shouldCreateDylibForDynamicProducts: buildParameters.shouldCreateDylibForDynamicProducts,
toolchainLibDir: (try? buildParameters.toolchain.toolchainLibDir) ?? .root
toolchainLibDir: (try? buildParameters.toolchain.toolchainLibDir) ?? .root,
pkgConfigDirectories: buildParameters.pkgConfigDirectories
)
}
}
Expand Down
1 change: 1 addition & 0 deletions Tests/BuildTests/MockBuildTestHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func mockBuildParameters(
hostTriple: hostTriple,
destinationTriple: destinationTriple,
flags: flags,
pkgConfigDirectories: [],
jobs: 3,
shouldLinkStaticSwiftStdlib: shouldLinkStaticSwiftStdlib,
canRenameEntrypointFunctionName: canRenameEntrypointFunctionName,
Expand Down
Loading