Skip to content

Commit

Permalink
Make sure to use old dtags on Linux to get RPATH.
Browse files Browse the repository at this point in the history
The comment in the code explains why.

Signed-off-by: Chris Lalancette <[email protected]>
  • Loading branch information
clalancette committed Dec 18, 2017
1 parent 7f24fa3 commit bf3bad0
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 23 deletions.
2 changes: 2 additions & 0 deletions bindings/pydrake/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ drake_py_test(
drake_py_test(
name = "common_install_test",
size = "medium",
# Increase the timeout so that debug builds are successful.
timeout = "long",
srcs = ["test/common_install_test.py"],
data = ["//:install"],
main = "test/common_install_test.py",
Expand Down
1 change: 1 addition & 0 deletions setup/ubuntu/16.04/install_prereqs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ lldb-4.0
make
mesa-common-dev
openjdk-8-jdk
patchelf
patchutils
pkg-config
protobuf-compiler
Expand Down
42 changes: 20 additions & 22 deletions tools/install/install.py.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python

import argparse
import collections
import filecmp
import os
import re
Expand Down Expand Up @@ -159,25 +160,12 @@ def macos_fix_rpaths(basename, dst_full):


def linux_fix_rpaths(dst_full):
# Check that file has an rpath or a runpath tag
try:
check_output(["chrpath", "-l", dst_full])
except OSError as ex:
if ex.errno == 2 and ex.strerror == "No such file or directory":
print("`chrpath` not found. Please run install_prereqs.sh.")
raise ex
except CalledProcessError as ex:
if ex.returncode == 2 and \
ex.output.strip().endswith('no rpath or runpath tag found.'):
# Cannot be modified with `chrpath`, so we skip it.
return
raise ex
# Check if file dependencies are found and not in install prefix.
# The found libraries outside of the install prefix are system
# libraries and we do not worry about these. We only make sure that
# drake libraries will be found.
file_output = check_output(["ldd", dst_full])
rpath = set()
rpath = []
for line in file_output.splitlines():
ldd_result = line.strip().split(' => ')
# If library found and not in install prefix, then skip.
Expand All @@ -195,18 +183,28 @@ def linux_fix_rpaths(dst_full):
diff_path = os.path.dirname(
os.path.relpath(libs[soname][0], lib_dirname)
)
rpath.add('$ORIGIN' + '/' + diff_path)
rpath.append('$ORIGIN' + '/' + diff_path)

# Ensure that system libraries get loaded instead of those bundled with
# MATLAB that are added to the LD_LIBRARY_PATH.
rpath.append('/usr/lib/x86_64-linux-gnu/')

# The above may have duplicated some items into the list. Uniquify it
# here, preserving order. Note that we do not just use a set() above,
# since order matters.
rpath = collections.OrderedDict.fromkeys(rpath).keys()

# Replace build tree RPATH with computed install tree RPATH. Build tree
# RPATH are automatically removed by this call. RPATH will contain the
# necessary relative paths to find the libraries that are needed. RPATH
# will typically be set to `$ORIGIN` or `$ORIGIN/../../..` .
if rpath:
str_rpath = ":".join(x for x in rpath)
check_output(
['chrpath',
"-r", str_rpath,
dst_full]
)
str_rpath = ":".join(x for x in rpath)
check_output(
["patchelf",
"--force-rpath", # We need to override LD_LIBRARY_PATH.
"--set-rpath", str_rpath,
dst_full]
)


def create_java_launcher(filename, classpath, main_class):
Expand Down
3 changes: 2 additions & 1 deletion tools/install/libdrake/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ load(
"HAS_MOVED_6996",
)
load(":build_components.bzl", "LIBDRAKE_COMPONENTS")
load("//tools:drake.bzl", "drake_cc_binary")

LIBDRAKE_COMPONENTS = adjust_labels_for_drake_hoist(LIBDRAKE_COMPONENTS)

Expand All @@ -36,7 +37,7 @@ install_cmake_config(
# LIBDRAKE_COMPONENTS and all the Drake externals. We use linkstatic=1 so
# that the binary package will not contain any references to shared libraries
# inside the build tree.
cc_binary(
drake_cc_binary(
name = "libdrake.so",
linkshared = 1,
linkstatic = 1,
Expand Down
19 changes: 19 additions & 0 deletions tools/skylark/drake_cc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,9 @@ def drake_cc_binary(
data = [],
deps = [],
copts = [],
linkopts = [],
gcc_copts = [],
linkshared = 0,
linkstatic = 1,
testonly = 0,
add_test_rule = 0,
Expand Down Expand Up @@ -385,14 +387,31 @@ def drake_cc_binary(
copts = new_copts,
testonly = testonly,
**kwargs)
if linkshared == 1:
# On Linux, we need to disable "new" dtags in the linker so that we use
# RPATH instead of RUNPATH. When doing runtime linking, RPATH is
# checked *before* LD_LIBRARY_PATH, which is important to avoid using
# the MATLAB versions of certain libraries (protobuf). macOS doesn't
# understand this flag, so it is conditional on Linux only. Note that
# the string we use for rpath here doesn't actually matter; it will be
# replaced during installation later.
linkopts = select({
"//tools/cc_toolchain:apple": linkopts,
"//conditions:default": linkopts + [
"-Wl,-rpath=/usr/lib/x86_64-linux-gnu -Wl,--disable-new-dtags",
],
})

native.cc_binary(
name = name,
srcs = new_srcs,
data = data,
deps = new_deps,
copts = new_copts,
testonly = testonly,
linkshared = linkshared,
linkstatic = linkstatic,
linkopts = linkopts,
**kwargs)

# Also generate the OS X debug symbol file for this binary.
Expand Down

0 comments on commit bf3bad0

Please sign in to comment.