[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
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. # Nuke objects built from OCaml. Useful when changing the OCaml compiler, for instance.
.PHONY: ocaml_clean .PHONY: ocaml_clean
ocaml_clean: ocaml_clean:

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

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

@ -43,7 +43,7 @@ eval $(opam env)
touch .release touch .release
./autogen.sh ./autogen.sh
./configure --prefix="/$RELEASE_NAME" ./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 popd
if [ "$DRYRUN" = "no" ]; then 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