rust-bin: use linker to set rpath

Patchelf should be reserved for when the ELF cannot be generated
correctly in the first place. This is not the case here because we have
control over the linker flags. The limitation is that -C link-args can
only be specified once, so consolidate the generation of link-args. Also
introduce some new intermediate variables in link-args generation for
customization.

Patchelf was running only in ${PKGD} because patching the ELF in ${D}
would cause objcopy to fail when splitting the debug sections. This is
not a problem when setting it correctly in the linker. The benefit is
that the rpath is correct in the sysroot as well.

This also switches the rpaths to be relative so that they work in both
the sysroot and the target in the same way.

Signed-off-by: Tyler Hall <tyler.hall@lexmark.com>
Signed-off-by: Steven Walter <swalter@lexmark.com>
This commit is contained in:
Tyler Hall
2017-03-13 22:33:31 -04:00
committed by Steven Walter
parent 172a226259
commit 463622c0c6
+52 -16
View File
@@ -1,6 +1,5 @@
inherit rust inherit rust
DEPENDS_append = " patchelf-native"
RDEPENDS_${PN} += "${RUSTLIB_DEP}" RDEPENDS_${PN} += "${RUSTLIB_DEP}"
RUSTC_ARCHFLAGS += "-C opt-level=3 -g -L ${STAGING_DIR_HOST}/${rustlibdir} -C linker=${RUST_TARGET_CCLD}" RUSTC_ARCHFLAGS += "-C opt-level=3 -g -L ${STAGING_DIR_HOST}/${rustlibdir} -C linker=${RUST_TARGET_CCLD}"
@@ -37,6 +36,44 @@ CRATE_TYPE ?= "dylib"
BIN_SRC ?= "${S}/src/main.rs" BIN_SRC ?= "${S}/src/main.rs"
LIB_SRC ?= "${S}/src/lib.rs" LIB_SRC ?= "${S}/src/lib.rs"
rustbindest ?= "${bindir}"
rustlibdest ?= "${rustlibdir}"
RUST_RPATH_ABS ?= "${rustlibdir}:${rustlib}"
def relative_rpaths(paths, base):
relpaths = set()
for p in paths.split(':'):
if p == base:
relpaths.add('$ORIGIN')
continue
relpaths.add(os.path.join('$ORIGIN', os.path.relpath(p, base)))
return '-rpath=' + ':'.join(relpaths) if len(relpaths) else ''
RUST_LIB_RPATH_FLAGS ?= "${@relative_rpaths(d.getVar('RUST_RPATH_ABS', True), d.getVar('rustlibdest', True))}"
RUST_BIN_RPATH_FLAGS ?= "${@relative_rpaths(d.getVar('RUST_RPATH_ABS', True), d.getVar('rustbindest', True))}"
def libfilename(d):
if d.getVar('CRATE_TYPE', True) == 'dylib':
return d.getVar('LIBNAME', True) + '.so'
else:
return d.getVar('LIBNAME', True) + '.rlib'
def link_args(d, bin):
linkargs = []
if bin:
rpaths = d.getVar('RUST_BIN_RPATH_FLAGS', False)
else:
rpaths = d.getVar('RUST_LIB_RPATH_FLAGS', False)
if d.getVar('CRATE_TYPE', True) == 'dylib':
linkargs.append('-soname')
linkargs.append(libfilename(d))
if len(rpaths):
linkargs.append(rpaths)
if len(linkargs):
return ' '.join(['-Wl,' + arg for arg in linkargs])
else:
return ''
get_overlap_externs () { get_overlap_externs () {
externs= externs=
for dep in ${OVERLAP_DEPS}; do for dep in ${OVERLAP_DEPS}; do
@@ -62,17 +99,16 @@ oe_runrustc () {
} }
oe_compile_rust_lib () { oe_compile_rust_lib () {
[ "${CRATE_TYPE}" == "dylib" ] && suffix=so || suffix=rlib
rm -rf ${LIBNAME}.{rlib,so} rm -rf ${LIBNAME}.{rlib,so}
local -a link_args local -a link_args
if [ "${CRATE_TYPE}" == "dylib" ]; then if [ -n '${@link_args(d, False)}' ]; then
link_args[0]="-C" link_args[0]='-C'
link_args[1]="link-args=-Wl,-soname -Wl,${LIBNAME}.$suffix" link_args[1]='link-args=${@link_args(d, False)}'
fi fi
oe_runrustc $(get_overlap_externs) \ oe_runrustc $(get_overlap_externs) \
"${link_args[@]}" \ "${link_args[@]}" \
${LIB_SRC} \ ${LIB_SRC} \
-o ${LIBNAME}.$suffix \ -o ${@libfilename(d)} \
--crate-name=${CRATE_NAME} --crate-type=${CRATE_TYPE} \ --crate-name=${CRATE_NAME} --crate-type=${CRATE_TYPE} \
"$@" "$@"
} }
@@ -80,20 +116,27 @@ oe_compile_rust_lib[vardeps] += "get_overlap_externs"
oe_compile_rust_bin () { oe_compile_rust_bin () {
rm -rf ${BINNAME} rm -rf ${BINNAME}
oe_runrustc $(get_overlap_externs) ${BIN_SRC} -o ${BINNAME} "$@" local -a link_args
if [ -n '${@link_args(d, True)}' ]; then
link_args[0]='-C'
link_args[1]='link-args=${@link_args(d, True)}'
fi
oe_runrustc $(get_overlap_externs) \
"${link_args[@]}" \
${BIN_SRC} -o ${BINNAME} "$@"
} }
oe_compile_rust_bin[vardeps] += "get_overlap_externs" oe_compile_rust_bin[vardeps] += "get_overlap_externs"
oe_install_rust_lib () { oe_install_rust_lib () {
for lib in $(ls ${LIBNAME}.{so,rlib} 2>/dev/null); do for lib in $(ls ${LIBNAME}.{so,rlib} 2>/dev/null); do
echo Installing $lib echo Installing $lib
install -D -m 755 $lib ${D}/${rustlibdir}/$lib install -D -m 755 $lib ${D}/${rustlibdest}/$lib
done done
} }
oe_install_rust_bin () { oe_install_rust_bin () {
echo Installing ${BINNAME} echo Installing ${BINNAME}
install -D -m 755 ${BINNAME} ${D}/${bindir}/${BINNAME} install -D -m 755 ${BINNAME} ${D}/${rustbindest}/${BINNAME}
} }
do_rust_bin_fixups() { do_rust_bin_fixups() {
@@ -101,13 +144,6 @@ do_rust_bin_fixups() {
echo "Strip rust note: $f" echo "Strip rust note: $f"
${OBJCOPY} -R .note.rustc $f $f ${OBJCOPY} -R .note.rustc $f $f
done done
for f in `find ${PKGD}`; do
file "$f" | grep -q ELF || continue
readelf -d "$f" | grep RUNPATH | grep -q rustlib || continue
echo "Set rpath:" "$f"
patchelf --set-rpath '$ORIGIN:'${rustlibdir}:${rustlib} "$f"
done
} }
PACKAGE_PREPROCESS_FUNCS += "do_rust_bin_fixups" PACKAGE_PREPROCESS_FUNCS += "do_rust_bin_fixups"