diff --git a/source/dub/compilers/buildsettings.d b/source/dub/compilers/buildsettings.d index cc04b84..c9d6b7d 100644 --- a/source/dub/compilers/buildsettings.d +++ b/source/dub/compilers/buildsettings.d @@ -131,6 +131,7 @@ void prependDFlags(in string[] value...) { prepend(dflags, value); } void removeDFlags(in string[] value...) { remove(dflags, value); } void addLFlags(in string[] value...) { lflags ~= value; } + void prependLFlags(in string[] value...) { prepend(lflags, value, false); } void addLibs(in string[] value...) { add(libs, value); } void addLinkerFiles(in string[] value...) { add(linkerFiles, value); } void addSourceFiles(in string[] value...) { add(sourceFiles, value); } diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index f75b1f6..998d631 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -330,6 +330,8 @@ void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { + const targetFileName = getTargetFileName(settings, platform); + final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); case TargetType.none: assert(false, "Invalid target type: none"); @@ -344,6 +346,7 @@ settings.addDFlags("-shared"); else settings.prependDFlags("-shared", "-defaultlib=libphobos2.so"); + addDynamicLibName(settings, platform, targetFileName); break; case TargetType.object: settings.addDFlags("-c"); @@ -351,7 +354,7 @@ } if (tpath is null) - tpath = (NativePath(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); + tpath = (NativePath(settings.targetPath) ~ targetFileName).toNativeString(); settings.addDFlags("-of"~tpath); } diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index 664d021..422a513 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -182,6 +182,8 @@ void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { + const targetFileName = getTargetFileName(settings, platform); + final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); case TargetType.none: assert(false, "Invalid target type: none"); @@ -194,11 +196,12 @@ break; case TargetType.dynamicLibrary: settings.addDFlags("-shared", "-fPIC"); + addDynamicLibName(settings, platform, targetFileName); break; } if (tpath is null) - tpath = (NativePath(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); + tpath = (NativePath(settings.targetPath) ~ targetFileName).toNativeString(); settings.addDFlags("-o", tpath); } diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 0737aa6..76c42e2 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -220,6 +220,8 @@ void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { + const targetFileName = getTargetFileName(settings, platform); + final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); case TargetType.none: assert(false, "Invalid target type: none"); @@ -231,6 +233,7 @@ break; case TargetType.dynamicLibrary: settings.addDFlags("-shared"); + addDynamicLibName(settings, platform, targetFileName); break; case TargetType.object: settings.addDFlags("-c"); @@ -238,7 +241,7 @@ } if (tpath is null) - tpath = (NativePath(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); + tpath = (NativePath(settings.targetPath) ~ targetFileName).toNativeString(); settings.addDFlags("-of"~tpath); } diff --git a/source/dub/compilers/utils.d b/source/dub/compilers/utils.d index 19b1419..2961001 100644 --- a/source/dub/compilers/utils.d +++ b/source/dub/compilers/utils.d @@ -118,6 +118,25 @@ /** + Adds a default DT_SONAME (ELF) / 'install name' (Mach-O) when linking a dynamic library. + This makes dependees reference their dynamic-lib deps by filename only (DT_NEEDED etc.) + instead of by the path used in the dependee linker cmdline, and enables loading the + deps from the dependee's output directory - either by setting the LD_LIBRARY_PATH + environment variable, or baking an rpath into the executable. +*/ +package void addDynamicLibName(ref BuildSettings settings, in BuildPlatform platform, string fileName) +{ + if (!platform.isWindows()) { + // *pre*pend to allow the user to override it + if (platform.platform.canFind("darwin")) + settings.prependLFlags("-install_name", "@rpath/" ~ fileName); + else + settings.prependLFlags("-soname", fileName); + } +} + + +/** Replaces each referenced import library by the appropriate linker flags. This function tries to invoke "pkg-config" if possible and falls back to diff --git a/test/2-dynLib-dep/dub.json b/test/2-dynLib-dep/dub.json index 1d3d5cf..47abf4e 100644 --- a/test/2-dynLib-dep/dub.json +++ b/test/2-dynLib-dep/dub.json @@ -3,5 +3,7 @@ "dependencies": { "dynlib-simple": { "path": "../1-dynLib-simple/" } }, + "lflags-linux": ["-rpath", "$$ORIGIN"], + "lflags-darwin": ["-rpath", "@executable_path"], "dflags-ldc": ["-link-defaultlib-shared"] } diff --git a/test/issue2258-dynLib-exe-dep/dub.json b/test/issue2258-dynLib-exe-dep/dub.json index bd99fdb..30a9f4b 100644 --- a/test/issue2258-dynLib-exe-dep/dub.json +++ b/test/issue2258-dynLib-exe-dep/dub.json @@ -4,6 +4,8 @@ "dependencies": { "dynlib-simple": { "path": "../1-dynLib-simple/" } }, + "lflags-linux": ["-rpath", "$$ORIGIN"], + "lflags-darwin": ["-rpath", "@executable_path"], "dflags-ldc": ["-link-defaultlib-shared"] }