Merge pull request #568 from tritao/rpaths

Use rpaths & soname/install_name to link sibling shared libraries on OS X and Linux
This commit is contained in:
Tom van Dijck 2016-08-17 09:36:44 -07:00 committed by GitHub
commit fd4b937449
9 changed files with 115 additions and 11 deletions

View File

@ -786,6 +786,13 @@
}
}
api.register {
name = "runpathdirs",
scope = "config",
kind = "list:path",
tokens = true,
}
api.register {
name = "runtime",
scope = "config",

View File

@ -178,9 +178,21 @@
-- Format a list of values to be safely written as part of a variable assignment.
--
function make.list(value)
function make.list(value, quoted)
quoted = false
if #value > 0 then
return " " .. table.concat(value, " ")
if quoted then
local result = ""
for _, v in ipairs (value) do
if #result then
result = result .. " "
end
result = result .. premake.quoted(v)
end
return result
else
return " " .. table.concat(value, " ")
end
else
return ""
end

View File

@ -429,14 +429,14 @@
function make.ldFlags(cfg, toolset)
local flags = table.join(toolset.getLibraryDirectories(cfg), toolset.getldflags(cfg), cfg.linkoptions)
local flags = table.join(toolset.getLibraryDirectories(cfg), toolset.getrunpathdirs(cfg, cfg.runpathdirs), toolset.getldflags(cfg), cfg.linkoptions)
_p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(flags))
end
function make.libs(cfg, toolset)
local flags = toolset.getlinks(cfg)
_p(' LIBS +=%s', make.list(flags))
_p(' LIBS +=%s', make.list(flags, true))
end

View File

@ -165,6 +165,7 @@
end
clang.getrunpathdirs = gcc.getrunpathdirs
--
-- Build a list of linker flags corresponding to the settings in
@ -189,6 +190,10 @@
local r = { iif(cfg.system == premake.MACOSX, "-dynamiclib", "-shared") }
if cfg.system == "windows" and not cfg.flags.NoImportLib then
table.insert(r, '-Wl,--out-implib="' .. cfg.linktarget.relpath .. '"')
elseif cfg.system == premake.LINUX then
table.insert(r, '-Wl,-soname=' .. premake.quoted(cfg.linktarget.name))
elseif cfg.system == premake.MACOSX then
table.insert(r, '-Wl,-install_name,' .. premake.quoted('@rpath/' .. cfg.linktarget.name))
end
return r
end,

View File

@ -191,6 +191,52 @@
return result
end
--
-- Return a list of decorated rpaths
--
function gcc.getrunpathdirs(cfg, dirs)
local result = {}
if not ((cfg.system == premake.MACOSX)
or (cfg.system == premake.LINUX)) then
return result
end
local rpaths = {}
-- User defined runpath search paths
for _, fullpath in ipairs(cfg.runpathdirs) do
local rpath = path.getrelative(cfg.buildtarget.directory, fullpath)
if not (table.contains(rpaths, rpath)) then
table.insert(rpaths, rpath)
end
end
-- Automatically add linked shared libraries path relative to target directory
for _, sibling in ipairs(config.getlinks(cfg, "siblings", "object")) do
if (sibling.kind == premake.SHAREDLIB) then
local fullpath = sibling.linktarget.directory
local rpath = path.getrelative(cfg.buildtarget.directory, fullpath)
if not (table.contains(rpaths, rpath)) then
table.insert(rpaths, rpath)
end
end
end
for _, rpath in ipairs(rpaths) do
if (cfg.system == premake.MACOSX) then
rpath = "@loader_path/" .. rpath
elseif (cfg.system == premake.LINUX) then
rpath = iif(rpath == ".", "", "/" .. rpath)
rpath = "$$ORIGIN" .. rpath
end
table.insert(result, "-Wl,-rpath,'" .. rpath .. "'")
end
return result
end
--
-- Return a list of LDFLAGS for a specific configuration.
@ -212,8 +258,12 @@
kind = {
SharedLib = function(cfg)
local r = { iif(cfg.system == premake.MACOSX, "-dynamiclib", "-shared") }
if cfg.system == "windows" and not cfg.flags.NoImportLib then
if cfg.system == premake.WINDOWS and not cfg.flags.NoImportLib then
table.insert(r, '-Wl,--out-implib="' .. cfg.linktarget.relpath .. '"')
elseif cfg.system == premake.LINUX then
table.insert(r, '-Wl,-soname=' .. premake.quoted(cfg.linktarget.name))
elseif cfg.system == premake.MACOSX then
table.insert(r, '-Wl,-install_name,' .. premake.quoted('@rpath/' .. cfg.linktarget.name))
end
return r
end,
@ -313,7 +363,8 @@
local links = config.getlinks(cfg, "system", "fullpath")
for _, link in ipairs(links) do
if path.isframework(link) then
table.insert(result, "-framework " .. path.getbasename(link))
table.insert(result, "-framework")
table.insert(result, path.getbasename(link))
elseif path.isobjectfile(link) then
table.insert(result, link)
else

View File

@ -187,7 +187,9 @@
return result
end
function msc.getrunpathdirs()
return {}
end
--
-- Decorate include file search paths for the MSVC command line.

View File

@ -102,6 +102,7 @@
snc.getcppflags = gcc.getcppflags
snc.getdefines = gcc.getdefines
snc.getincludedirs = gcc.getincludedirs
snc.getrunpathdirs = gcc.getrunpathdirs
snc.getLibraryDirectories = gcc.getLibraryDirectories
snc.getlinks = gcc.getlinks

View File

@ -35,11 +35,20 @@
kind "SharedLib"
prepare { "ldFlags", "linkCmd" }
test.capture [[
ALL_LDFLAGS += $(LDFLAGS) -shared -s
ALL_LDFLAGS += $(LDFLAGS) -shared -Wl,-soname=libMyProject.so -s
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
]]
end
function suite.links_onMacOSXCppSharedLib()
_OS = "macosx"
kind "SharedLib"
prepare { "ldFlags", "linkCmd" }
test.capture [[
ALL_LDFLAGS += $(LDFLAGS) -dynamiclib -Wl,-install_name,@rpath/libMyProject.dylib -Wl,-x
LINKCMD = $(CXX) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
]]
end
--
-- Check link command for a shared C library.
@ -50,7 +59,7 @@
kind "SharedLib"
prepare { "ldFlags", "linkCmd" }
test.capture [[
ALL_LDFLAGS += $(LDFLAGS) -shared -s
ALL_LDFLAGS += $(LDFLAGS) -shared -Wl,-soname=libMyProject.so -s
LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)
]]
end
@ -153,12 +162,29 @@
prepare { "ldFlags", "libs", "ldDeps" }
test.capture [[
ALL_LDFLAGS += $(LDFLAGS) -Lbuild/bin/Debug -s
ALL_LDFLAGS += $(LDFLAGS) -Lbuild/bin/Debug -Wl,-rpath,'$$ORIGIN/../../build/bin/Debug' -s
LIBS += -lMyProject2
LDDEPS += build/bin/Debug/libMyProject2.so
]]
end
function suite.links_onMacOSXSiblingSharedLib()
_OS = "macosx"
links "MyProject2"
flags { "RelativeLinks" }
test.createproject(wks)
kind "SharedLib"
location "build"
prepare { "ldFlags", "libs", "ldDeps" }
test.capture [[
ALL_LDFLAGS += $(LDFLAGS) -Lbuild/bin/Debug -Wl,-rpath,'@loader_path/../../build/bin/Debug' -Wl,-x
LIBS += -lMyProject2
LDDEPS += build/bin/Debug/libMyProject2.dylib
]]
end
--
-- Check a linking multiple siblings.
--

View File

@ -347,7 +347,7 @@
function suite.links_onFramework()
links { "Cocoa.framework" }
prepare()
test.contains({ "-framework Cocoa" }, gcc.getlinks(cfg))
test.contains({ "-framework Cocoa" }, {table.implode (gcc.getlinks(cfg), '', '', ' ')})
end
function suite.links_onSystemLibs_onWindows()