Skip to content

Commit c5009fd

Browse files
authored
SwiftBuild: Fix executable can't find dynamic lib runtime error (#8650)
Update LD_RUNPATH_SEARCH_PATHS of executable built using the new Swift Build backend. ### Motivation: For the Swift Build backend, fix a runtime issue when building & running an executable linked against a dynamic library (from a local package dependency). That's the runtime error I get: dyld[89079]: Library not loaded: @rpath/libUtils.dylib Referenced from: /App/.build/arm64-apple-macosx/Products/Debug/App ... ### Modifications: Update the build setting LD_RUNPATH_SEARCH_PATHS for executables, appending @loader_path. This is actually an "imparted" build setting coming from dynamic libraries targets, so that's where I made the change. ### Result: Now both build configurations are capable of running the built App: $ swift run --package-path /App --build-system swiftbuild --configuration debug Hello from Lib $ swift run --package-path /App --build-system swiftbuild --configuration release Hello from Lib
1 parent e947d92 commit c5009fd

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Modules.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ extension PackagePIFProjectBuilder {
225225
case macro
226226
}
227227

228-
/// Constructs a *PIF target* for building a *module* target as a particular type.
228+
/// Constructs a *PIF target* for building a *module* as a particular type.
229229
/// An optional target identifier suffix is passed when building variants of a target.
230230
@discardableResult
231231
private mutating func buildSourceModule(
@@ -243,7 +243,8 @@ extension PackagePIFProjectBuilder {
243243

244244
switch desiredModuleType {
245245
case .dynamicLibrary:
246-
if pifBuilder.createDylibForDynamicProducts { // We are re-using this default for dynamic targets as well.
246+
// We are re-using this default for dynamic targets as well.
247+
if pifBuilder.createDylibForDynamicProducts {
247248
pifProductName = "lib\(sourceModule.name).dylib"
248249
executableName = pifProductName
249250
productType = .dynamicLibrary
@@ -760,18 +761,25 @@ extension PackagePIFProjectBuilder {
760761
}
761762
}
762763

763-
// Set the imparted settings, which are ones that clients (both direct and indirect ones) use.
764-
var debugImpartedSettings = impartedSettings
765-
debugImpartedSettings[.LD_RUNPATH_SEARCH_PATHS] =
766-
["$(BUILT_PRODUCTS_DIR)/PackageFrameworks"] +
767-
(debugImpartedSettings[.LD_RUNPATH_SEARCH_PATHS] ?? ["$(inherited)"])
764+
// Set the **imparted** settings, which are ones that clients (both direct and indirect ones) use.
765+
// For instance, given targets A, B, C with the following dependency graph:
766+
//
767+
// A (executable) -> B (dynamicLibrary) -> C (objectFile)
768+
//
769+
// An imparted build setting on C will propagate back to both B and A.
770+
impartedSettings[.LD_RUNPATH_SEARCH_PATHS] =
771+
["@loader_path"] +
772+
(impartedSettings[.LD_RUNPATH_SEARCH_PATHS] ?? ["$(inherited)"])
773+
774+
var impartedDebugSettings = impartedSettings
775+
impartedDebugSettings[.LD_RUNPATH_SEARCH_PATHS]! += ["$(BUILT_PRODUCTS_DIR)/PackageFrameworks"]
768776

769777
self.project[keyPath: sourceModuleTargetKeyPath].common.addBuildConfig { id in
770778
BuildConfig(
771779
id: id,
772780
name: "Debug",
773781
settings: debugSettings,
774-
impartedBuildSettings: debugImpartedSettings
782+
impartedBuildSettings: impartedDebugSettings
775783
)
776784
}
777785
self.project[keyPath: sourceModuleTargetKeyPath].common.addBuildConfig { id in

0 commit comments

Comments
 (0)