diff --git a/Makefile b/Makefile index eb41e0aba..821b23345 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/Makefile.autoconf.in b/Makefile.autoconf.in index 3b5823d51..e21c9af3d 100644 --- a/Makefile.autoconf.in +++ b/Makefile.autoconf.in @@ -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@ diff --git a/configure.ac b/configure.ac index 6c88f821e..2073aa6bd 100644 --- a/configure.ac +++ b/configure.ac @@ -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() diff --git a/scripts/create_binary_release.sh b/scripts/create_binary_release.sh index 423e882c0..b68d1c4d4 100755 --- a/scripts/create_binary_release.sh +++ b/scripts/create_binary_release.sh @@ -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 diff --git a/scripts/set_libso_path.sh b/scripts/set_libso_path.sh new file mode 100755 index 000000000..e39f28496 --- /dev/null +++ b/scripts/set_libso_path.sh @@ -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"