[make] support relocating libs at install time

Summary: Provide hooks into the autoconf configure script to define where libgmp and libmpfr may be found. Use these and opam to copy the more exotic library objects into the installation of infer on a new `make install-with-libs` target so that the binaries can be distributed usefully, i.e., without users having to install gmp, mpfr, and more importantly apron and elina (which need ocaml + opam + ..., which would defeat the point of having binaries).

Reviewed By: skcho

Differential Revision: D14065317

fbshipit-source-id: 9a2ac7200
master
Jules Villard 6 years ago committed by Facebook Github Bot
parent a3ecfdb8ad
commit ba5ad82128

@ -650,6 +650,56 @@ else
endif
endif
# install dynamic libraries
# use this if you want to distribute infer binaries
install-with-libs: install
test -d '$(DESTDIR)$(libdir)'/infer/infer/libso || \
$(MKDIR_P) '$(DESTDIR)$(libdir)'/infer/infer/libso
ifneq ($(OPAM),no)
$(INSTALL_PROGRAM) -C $(GMP_LIB_PATH) '$(DESTDIR)$(libdir)'/infer/infer/libso/
$(INSTALL_PROGRAM) -C $(MPFR_LIB_PATH) '$(DESTDIR)$(libdir)'/infer/infer/libso/
set -x; \
OPAM_SHARE=$$($(OPAM) config var share); \
APRON_LIB_PATHS="$$OPAM_SHARE/apron/lib/libapron.so $$OPAM_SHARE/apron/lib/liboctMPQ.so"; \
ELINA_LIB_PATHS="$$OPAM_SHARE/elina/lib/libelinalinearize.so $$OPAM_SHARE/elina/lib/liboptpoly.so $$OPAM_SHARE/elina/lib/libpartitions.so"; \
$(INSTALL_PROGRAM) -C $$APRON_LIB_PATHS '$(DESTDIR)$(libdir)'/infer/infer/libso/; \
$(INSTALL_PROGRAM) -C $$ELINA_LIB_PATHS '$(DESTDIR)$(libdir)'/infer/infer/libso/
# update rpath of executables
ifneq ($(PATCHELF),no)
# this sort of assumes Linux
for sofile in '$(DESTDIR)$(libdir)'/infer/infer/libso/*.so; do \
$(PATCHELF) --set-rpath '$$ORIGIN' "$$sofile"; \
done
$(PATCHELF) --set-rpath '$$ORIGIN/../libso' '$(DESTDIR)$(libdir)'/infer/infer/bin/infer
ifeq ($(IS_FACEBOOK_TREE),yes)
$(PATCHELF) --set-rpath '$$ORIGIN/../libso' '$(DESTDIR)$(libdir)'/infer/infer/bin/InferCreateTraceViewLinks
endif
else # patchelf not found
ifneq ($(OTOOL),no)
ifneq ($(INSTALL_NAME_TOOL),no)
# this sort of assumes osx
set -x; \
for sofile in '$(DESTDIR)$(libdir)'/infer/infer/libso/*.{so,dylib}; do \
$(INSTALL_NAME_TOOL) -add_rpath "@executable_path" "$$sofile" 2> /dev/null || true; \
scripts/set_libso_path.sh '$(DESTDIR)$(libdir)'/infer/infer/libso "$$sofile"; \
done
$(INSTALL_NAME_TOOL) -add_rpath '@executable_path/../libso' '$(DESTDIR)$(libdir)'/infer/infer/bin/infer 2> /dev/null || true
scripts/set_libso_path.sh '$(DESTDIR)$(libdir)'/infer/infer/libso '$(DESTDIR)$(libdir)'/infer/infer/bin/infer
ifeq ($(IS_FACEBOOK_TREE),yes)
$(INSTALL_NAME_TOOL) -add_rpath '@executable_path/../libso' '$(DESTDIR)$(libdir)'/infer/infer/bin/InferCreateTraceViewLinks 2> /dev/null || true
scripts/set_libso_path.sh '$(DESTDIR)$(libdir)'/infer/infer/libso '$(DESTDIR)$(libdir)'/infer/infer/bin/InferCreateTraceViewLinks
endif
else # install_name_tool not found
echo "ERROR: need patchelf (Linux) or otool + install_name_tool (OSX) available" >&2; exit 1
endif
else # otool not found
echo "ERROR: need patchelf (Linux) or otool + install_name_tool (OSX) available" >&2; exit 1
endif
endif # patchelf
else # opam not found
echo "ERROR: non-opam installations not supported" >&2; exit 1
endif
# Nuke objects built from OCaml. Useful when changing the OCaml compiler, for instance.
.PHONY: ocaml_clean
ocaml_clean:

@ -27,6 +27,7 @@ EMACS = @EMACS@
ENABLE_OCAMLOPT_CUSTOM_CC = @ENABLE_OCAMLOPT_CUSTOM_CC@
ENABLE_OCAML_BINANNOT = @ENABLE_OCAML_BINANNOT@
exec_prefix = @exec_prefix@
GMP_LIB_PATH = @GMP_LIB_PATH@
GNU_SED = @GNU_SED@
INFER_MAJOR = @INFER_MAJOR@
INFER_MAN_LAST_MODIFIED = @INFER_MAN_LAST_MODIFIED@
@ -34,6 +35,7 @@ INFER_MINOR = @INFER_MINOR@
INFER_PATCH = @INFER_PATCH@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_NAME_TOOL = @INSTALL_NAME_TOOL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
IS_FACEBOOK_TREE = @IS_FACEBOOK_TREE@
IS_RELEASE_TREE = @IS_RELEASE_TREE@
@ -51,6 +53,7 @@ MKDIR_P_CMD = case "@MKDIR_P@" in \
*) printf "@MKDIR_P@\n";; \
esac
MKDIR_P = $(shell $(MKDIR_P_CMD))
MPFR_LIB_PATH = @MPFR_LIB_PATH@
MVN = @MVN@
NCPU = @NCPU@
NDKBUILD = @NDKBUILD@
@ -62,6 +65,7 @@ OCAMLOPT = @OCAMLOPT@
OPAM = @OPAM@
OPAMROOT = @OPAMROOT@
OPAMSWITCH = @OPAMSWITCH@
OTOOL = @OTOOL@
PATCHELF = @PATCHELF@
PATH = @PATH@
prefix = @prefix@

@ -116,7 +116,6 @@ AS_IF([test "x$enable_c_analyzers" = "xyes"], [
])
# end if($enable_c_analyzers)
AC_CHECK_TOOL([PYTHON27], [python2.7], [no])
AC_ASSERT_PROG([python2.7], [$PYTHON27])
@ -184,6 +183,7 @@ Alternatively, you can checkout a binary release of infer:
fi
# end if($enable_c_analyzers)
# OCaml dependencies
AC_PROG_OCAML
AC_ASSERT_PROG([ocamlc], [$OCAMLC])
@ -347,26 +347,25 @@ AC_ARG_VAR([SDKROOT], [path to the OSX platform SDK used by clang])
AC_SUBST([SDKROOT])
AC_CHECK_TOOL([PATCHELF], [patchelf], [no])
# warn about broken pkg-config version for brew users
if test "$BREW" != "no"; then
if "$BREW" info pkg-config > /dev/null && \
test x"$(which pkg-config)" = x"/usr/local/bin/pkg-config"; then
AC_MSG_NOTICE([pkg-config seems to have been installed from Homebrew])
AC_MSG_CHECKING([for bad version of pkg-config brew package])
if readlink $(which pkg-config) | grep -q -e '/0.29.1_1/'; then
AC_MSG_RESULT([found 0.29.1_1])
AC_MSG_WARN([])
AC_MSG_WARN([This version of pkg-config is known to cause issues with compiling infer.])
AC_MSG_WARN([Consider running the following command to get a working version:])
AC_MSG_WARN([])
AC_MSG_WARN([ brew remove pkg-config && brew update && brew install pkg-config])
AC_MSG_WARN([])
else
AC_MSG_RESULT([no bad version found])
fi
fi
fi
AC_SUBST([PATCHELF])
AC_CHECK_TOOL([INSTALL_NAME_TOOL], [install_name_tool], [no])
AC_SUBST([INSTALL_NAME_TOOL])
AC_CHECK_TOOL([OTOOL], [otool], [no])
AC_SUBST([OTOOL])
# look for the location of various libraries, needed to create relocatable installations of infer
AC_ARG_VAR([MPFR_LIB_PATH], [path to libmpfr.so or libmpfr.dylib])
AC_MSG_CHECKING([where to find libmpfr])
AS_IF([test "x$MPFR_LIB_PATH" = "x"], [MPFR_LIB_PATH=no])
AC_MSG_RESULT([$MPFR_LIB_PATH])
AC_SUBST([MPFR_LIB_PATH])
AC_MSG_CHECKING([where to find libgmp])
AC_ARG_VAR([GMP_LIB_PATH], [path to libgmp.so or libgmp.dylib])
AS_IF([test "x$GMP_LIB_PATH" = "x"], [GMP_LIB_PATH=no])
AC_MSG_RESULT([$GMP_LIB_PATH])
AC_SUBST([GMP_LIB_PATH])
AC_CHECK_INFER_MAN_LAST_MODIFIED()

@ -43,7 +43,7 @@ eval $(opam env)
touch .release
./autogen.sh
./configure --prefix="/$RELEASE_NAME"
make -j "$JOBS" install BUILD_MODE=opt DESTDIR="$ROOT_DIR" libdir_relative_to_bindir=../lib
make -j "$JOBS" install-with-libs BUILD_MODE=opt DESTDIR="$ROOT_DIR" libdir_relative_to_bindir=../lib
popd
if [ "$DRYRUN" = "no" ]; then

@ -0,0 +1,30 @@
#!/bin/bash
# Copyright (c) 2018-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# Usage: set_libso_path.sh [LIBSO_DIR] [TARGET]
#
# This changes MacOSX's executable [TARGET] to use shared libraries in
# [LIBSO_DIR] when rpath has been set to [LIBSO_DIR].
set -e
set -o pipefail
set -u
LIBSO_DIR=$1
TARGET=$2
TMP=$( mktemp )
trap "rm $TMP" EXIT
otool -L "$TARGET" | tail -n +2 > "$TMP"
while IFS='' read -r line || [[ -n "$line" ]]; do
LIB_PATH=$( echo $line | awk '{print $1}' )
LIB_FILE=$( basename "${LIB_PATH}" )
if [ -f "${LIBSO_DIR}/${LIB_FILE}" ]; then
install_name_tool -change "${LIB_PATH}" "@rpath/${LIB_FILE}" "$TARGET"
fi
done < "$TMP"
Loading…
Cancel
Save