diff --git a/.gitignore b/.gitignore index 9ceb3130f..88db9a552 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,13 @@ # Directories generated by Ocamlbuild _build +# autoconf-generated stuff +/acinclude.m4 +/aclocal.m4 +/autom4te.cache +/config.status +/configure + # IntelliJ files /scripts/.idea/ /infer/tests/.idea/dictionaries diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 000000000..91b81a3c6 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# Copyright (c) 2015 - present Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +set -e + +# try to pull submodules if we are in a git repo +# might fail if git is not installed (how did you even checkout the +# repo in the first place?) +if test -d '.git'; then + echo -n 'git repository detected, updating submodule... ' + if git submodule update --init > /dev/null; then + echo 'done' + else + echo 'error running git command' + fi +else + echo 'no git repository detected; not updating facebook-clang-plugins/' +fi + +ACINCLUDE="acinclude.m4" +echo -n "generating $ACINCLUDE..." +cat m4/*.m4 > "$ACINCLUDE" +echo " done" + +echo -n "generating ./configure script..." +autoreconf -fi +echo " done" + +echo "" +echo "you may now run the following commands to build Infer:" +echo "" +echo " ./configure" +echo " make -C infer clang java" +echo "" +echo 'run `./configure --help` for more options' diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..8588633de --- /dev/null +++ b/configure.ac @@ -0,0 +1,52 @@ +dnl autoconf script for Infer +dnl run ./autogen.sh to generate a configure script +dnl +dnl Copyright (c) 2015 - present Facebook, Inc. +dnl All rights reserved. +dnl +dnl This source code is licensed under the BSD style license found in the +dnl LICENSE file in the root directory of this source tree. An additional grant +dnl of patent rights can be found in the PATENTS file in the same directory. + +AC_PREREQ([2.63]) + +# TODO: use the stuff in infer/src/Makefile and version.ml.in instead +# of 0.4.0 +AC_INIT([Infer],[0.4.0],[https://github.com/facebook/infer/issues/]) + +AC_CONFIG_SRCDIR([infer/src/backend/sil.ml]) +#AC_CONFIG_HEADERS([config.h]) + +# Checks for programs. +AC_PROG_CXX +AC_PROG_AWK +AC_PROG_CC +AC_PROG_CPP +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_OBJC + +AC_PROG_OCAML +AC_ASSERT_PROG([ocamlc], [$OCAMLC]) +AC_ASSERT_PROG([ocamlopt], [$OCAMLOPT]) +AC_ASSERT_PROG([ocamlbuild], [$OCAMLBUILD]) +AC_PROG_FINDLIB +AC_ASSERT_PROG([findlib], [$FINDLIB]) +AC_PROG_OCAMLLEX +AC_ASSERT_PROG([ocamllex], [$OCAMLLEX]) +AC_PROG_OCAMLYACC +AC_ASSERT_PROG([ocamlyacc], [$OCAMLYACC]) +AC_ASSERT_OCAML_PKG([atdgen], [], [1.6.0]) +AC_ASSERT_OCAML_PKG([extlib], [], [1.5.4]) +AC_ASSERT_OCAML_PKG([javalib], [], [2.3.1]) +AC_ASSERT_OCAML_PKG([sawja], [], [1.5.1]) +AC_ASSERT_OCAML_PKG([biniou]) +AC_ASSERT_OCAML_PKG([camlzip], [zip]) +AC_ASSERT_OCAML_PKG([easy-format]) +AC_ASSERT_OCAML_PKG([ptrees]) +AC_ASSERT_OCAML_PKG([yojson]) + +# Checks for header files. +AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h locale.h malloc.h stddef.h stdint.h stdlib.h string.h sys/mount.h sys/param.h sys/socket.h sys/statfs.h sys/time.h unistd.h wchar.h wctype.h]) + +AC_OUTPUT diff --git a/m4/ac_assert_ocaml_pkg.m4 b/m4/ac_assert_ocaml_pkg.m4 new file mode 100644 index 000000000..b14fab3b8 --- /dev/null +++ b/m4/ac_assert_ocaml_pkg.m4 @@ -0,0 +1,36 @@ +dnl Copyright (c) 2015 - present Facebook, Inc. +dnl All rights reserved. +dnl +dnl This source code is licensed under the BSD style license found in the +dnl LICENSE file in the root directory of this source tree. An additional grant +dnl of patent rights can be found in the PATENTS file in the same directory. + +dnl AC_ASSERT_OCAML_PKG([pkg_name], [pkg_version]) +dnl +dnl fails if $pkg_name is not installed; also fails if it is not +dnl installed at version $pkg_version if specified +AC_DEFUN([AC_ASSERT_OCAML_PKG], +[dnl + AC_CHECK_OCAML_PKG_PATH([$1], [$2], [$3]) + + unset has_pkg + unset pkg + + has_pkg=$AS_TR_SH[OCAML_PKG_$1] + AS_IF([test "$has_pkg" = "no"], + [dnl + unset version + unset version_msg + version=".$3" + AS_IF([test "x$3" = "x"], [version=""]) + version_msg="" + AS_IF([test "x$3" != "x"], [version_msg=" version $3"]) + AC_MSG_ERROR([missing dependency: $1$version_msg. + +If you are using opam, please run + + opam install $1$version]) + ]) +]) + + diff --git a/m4/ac_assert_prog.m4 b/m4/ac_assert_prog.m4 new file mode 100644 index 000000000..1a6563922 --- /dev/null +++ b/m4/ac_assert_prog.m4 @@ -0,0 +1,18 @@ +dnl Copyright (c) 2015 - present Facebook, Inc. +dnl All rights reserved. +dnl +dnl This source code is licensed under the BSD style license found in the +dnl LICENSE file in the root directory of this source tree. An additional grant +dnl of patent rights can be found in the PATENTS file in the same directory. + +dnl AC_ASSERT_PROG([program_name], [test_variable]) +dnl +dnl fails if $test_variable is "no", which is taken to mean that +dnl $program_name is not installed +AC_DEFUN([AC_ASSERT_PROG], +[dnl + AS_IF([test "$2" = "no"], + [dnl + AC_MSG_ERROR([$1 not found.]) + ]) +]) diff --git a/m4/ac_check_ocaml_pkg_path.m4 b/m4/ac_check_ocaml_pkg_path.m4 new file mode 100644 index 000000000..9a6ae5831 --- /dev/null +++ b/m4/ac_check_ocaml_pkg_path.m4 @@ -0,0 +1,45 @@ +dnl Copyright (c) 2015 - present Facebook, Inc. +dnl All rights reserved. +dnl +dnl This source code is licensed under the BSD style license found in the +dnl LICENSE file in the root directory of this source tree. An additional grant +dnl of patent rights can be found in the PATENTS file in the same directory. + +dnl this adds the following features to AC_CHECK_OCAML_PKG: +dnl - supports an optional version argument in $3 +dnl - sets OCAML_PKG_PATH_$1 to be the path where the package is +dnl installed +AC_DEFUN([AC_CHECK_OCAML_PKG_PATH], +[dnl + AC_REQUIRE([AC_PROG_FINDLIB]) + AC_CHECK_OCAML_PKG([$1], [$2]) + + unset version_msg + version_msg="" + AS_IF([test "x$3" != "x"], [version_msg=" version $3"]) + AC_MSG_CHECKING([for OCaml findlib package $1$version_msg]) + + unset path + unset pkg + unset version + pkg=$AS_TR_SH([OCAML_PKG_$1]) + found=no + if test "x$pkg" != "xno"; then + path=`$OCAMLFIND query $pkg 2>/dev/null` + version=`$OCAMLFIND query -format '%v' $pkg 2>/dev/null` + if test "x$3" = "x" || test "x$version" = "x$3"; then + AC_MSG_RESULT([$path]) + AS_TR_SH([OCAML_PKG_$1])=$pkg + AS_TR_SH([OCAML_PKG_PATH_$1])=$path + found=yes + fi + fi + + if test "$found" = "no" ; then + AC_MSG_RESULT([not found]) + AS_TR_SH([OCAML_PKG_$1])=no + fi + + AC_SUBST(AS_TR_SH([OCAML_PKG_$1])) + AC_SUBST(AS_TR_SH([OCAML_PKG_PATH_$1])) +]) diff --git a/m4/ocaml.m4 b/m4/ocaml.m4 new file mode 100644 index 000000000..7bfdc00f7 --- /dev/null +++ b/m4/ocaml.m4 @@ -0,0 +1,281 @@ +dnl autoconf macros for OCaml +dnl +dnl Copyright © 2013 Gabriel Kerneis +dnl Copyright © 2009 Richard W.M. Jones +dnl Copyright © 2009 Stefano Zacchiroli +dnl Copyright © 2000-2005 Olivier Andrieu +dnl Copyright © 2000-2005 Jean-Christophe Filliâtre +dnl Copyright © 2000-2005 Georges Mariano +dnl +dnl +dnl Redistribution and use in source and binary forms, with or without modification, +dnl are permitted provided that the following conditions are met: +dnl +dnl * Redistributions of source code must retain the above copyright notice, this +dnl list of conditions and the following disclaimer. +dnl * Redistributions in binary form must reproduce the above copyright notice, +dnl this list of conditions and the following disclaimer in the documentation +dnl and/or other materials provided with the distribution. +dnl * The names of the contributors may not be used to endorse or promote +dnl products derived from this software without specific prior written +dnl permission. +dnl +dnl THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY +dnl EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +dnl DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +dnl DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +dnl (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +dnl LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +dnl ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +dnl SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +dnl +dnl +dnl For documentation, please read the ocaml.m4 man page. + +AC_DEFUN([AC_PROG_OCAML], +[dnl + # checking for ocamlc + AC_CHECK_TOOL([OCAMLC],[ocamlc],[no]) + + if test "$OCAMLC" != "no"; then + OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version* *\(.*\)$|\1|p'` + AC_MSG_RESULT([OCaml version is $OCAMLVERSION]) + # If OCAMLLIB is set, use it + if test "$OCAMLLIB" = ""; then + OCAMLLIB=`$OCAMLC -where 2>/dev/null | tr -d '\015' || $OCAMLC -v|tail -1|cut -d ' ' -f 4` + else + AC_MSG_RESULT([OCAMLLIB previously set; preserving it.]) + fi + AC_MSG_RESULT([OCaml library path is $OCAMLLIB]) + + AC_SUBST([OCAMLVERSION]) + AC_SUBST([OCAMLLIB]) + + # checking for ocamlopt + AC_CHECK_TOOL([OCAMLOPT],[ocamlopt],[no]) + OCAMLBEST=byte + if test "$OCAMLOPT" = "no"; then + AC_MSG_WARN([Cannot find ocamlopt; bytecode compilation only.]) + else + TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` + if test "$TMPVERSION" != "$OCAMLVERSION" ; then + AC_MSG_RESULT([versions differs from ocamlc; ocamlopt discarded.]) + OCAMLOPT=no + else + OCAMLBEST=opt + fi + fi + + AC_SUBST([OCAMLBEST]) + + # checking for ocamlc.opt + AC_CHECK_TOOL([OCAMLCDOTOPT],[ocamlc.opt],[no]) + if test "$OCAMLCDOTOPT" != "no"; then + TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` + if test "$TMPVERSION" != "$OCAMLVERSION" ; then + AC_MSG_RESULT([versions differs from ocamlc; ocamlc.opt discarded.]) + else + OCAMLC=$OCAMLCDOTOPT + fi + fi + + # checking for ocamlopt.opt + if test "$OCAMLOPT" != "no" ; then + AC_CHECK_TOOL([OCAMLOPTDOTOPT],[ocamlopt.opt],[no]) + if test "$OCAMLOPTDOTOPT" != "no"; then + TMPVERSION=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` + if test "$TMPVERSION" != "$OCAMLVERSION" ; then + AC_MSG_RESULT([version differs from ocamlc; ocamlopt.opt discarded.]) + else + OCAMLOPT=$OCAMLOPTDOTOPT + fi + fi + fi + + AC_SUBST([OCAMLOPT]) + fi + + AC_SUBST([OCAMLC]) + + # checking for native dynlink + AC_MSG_CHECKING([for dynlink.cmxa]) + if test -f "$OCAMLLIB/dynlink.cmxa" ; then + OCAMLNATDYNLINK=yes + AC_MSG_RESULT([yes]) + else + OCAMLNATDYNLINK=no + AC_MSG_RESULT([no]) + fi + + AC_SUBST([OCAMLNATDYNLINK]) + + # checking for ocaml toplevel + AC_CHECK_TOOL([OCAML],[ocaml],[no]) + + # checking for ocamldep + AC_CHECK_TOOL([OCAMLDEP],[ocamldep],[no]) + + # checking for ocamlmktop + AC_CHECK_TOOL([OCAMLMKTOP],[ocamlmktop],[no]) + + # checking for ocamlmklib + AC_CHECK_TOOL([OCAMLMKLIB],[ocamlmklib],[no]) + + # checking for ocamldoc + AC_CHECK_TOOL([OCAMLDOC],[ocamldoc],[no]) + + # checking for ocamlbuild + AC_CHECK_TOOL([OCAMLBUILD],[ocamlbuild],[no]) +]) + + +AC_DEFUN([AC_PROG_OCAMLLEX], +[dnl + # checking for ocamllex + AC_CHECK_TOOL([OCAMLLEX],[ocamllex],[no]) + if test "$OCAMLLEX" != "no"; then + AC_CHECK_TOOL([OCAMLLEXDOTOPT],[ocamllex.opt],[no]) + if test "$OCAMLLEXDOTOPT" != "no"; then + OCAMLLEX=$OCAMLLEXDOTOPT + fi + fi + AC_SUBST([OCAMLLEX]) +]) + +AC_DEFUN([AC_PROG_OCAMLYACC], +[dnl + AC_CHECK_TOOL([OCAMLYACC],[ocamlyacc],[no]) + AC_SUBST([OCAMLYACC]) +]) + + +AC_DEFUN([AC_PROG_CAMLP4], +[dnl + AC_REQUIRE([AC_PROG_OCAML])dnl + + # checking for camlp4 + AC_CHECK_TOOL([CAMLP4],[camlp4],[no]) + if test "$CAMLP4" != "no"; then + TMPVERSION=`$CAMLP4 -v 2>&1| sed -n -e 's|.*version *\(.*\)$|\1|p'` + if test "$TMPVERSION" != "$OCAMLVERSION" ; then + AC_MSG_RESULT([versions differs from ocamlc]) + CAMLP4=no + fi + fi + AC_SUBST([CAMLP4]) + + # checking for companion tools + AC_CHECK_TOOL([CAMLP4BOOT],[camlp4boot],[no]) + AC_CHECK_TOOL([CAMLP4O],[camlp4o],[no]) + AC_CHECK_TOOL([CAMLP4OF],[camlp4of],[no]) + AC_CHECK_TOOL([CAMLP4OOF],[camlp4oof],[no]) + AC_CHECK_TOOL([CAMLP4ORF],[camlp4orf],[no]) + AC_CHECK_TOOL([CAMLP4PROF],[camlp4prof],[no]) + AC_CHECK_TOOL([CAMLP4R],[camlp4r],[no]) + AC_CHECK_TOOL([CAMLP4RF],[camlp4rf],[no]) + AC_SUBST([CAMLP4BOOT]) + AC_SUBST([CAMLP4O]) + AC_SUBST([CAMLP4OF]) + AC_SUBST([CAMLP4OOF]) + AC_SUBST([CAMLP4ORF]) + AC_SUBST([CAMLP4PROF]) + AC_SUBST([CAMLP4R]) + AC_SUBST([CAMLP4RF]) +]) + + +AC_DEFUN([AC_PROG_FINDLIB], +[dnl + AC_REQUIRE([AC_PROG_OCAML])dnl + + # checking for ocamlfind + AC_CHECK_TOOL([OCAMLFIND],[ocamlfind],[no]) + AC_SUBST([OCAMLFIND]) +]) + + +dnl Thanks to Jim Meyering for working this next bit out for us. +dnl XXX We should define AS_TR_SH if it's not defined already +dnl (eg. for old autoconf). +AC_DEFUN([AC_CHECK_OCAML_PKG], +[dnl + AC_REQUIRE([AC_PROG_FINDLIB])dnl + + dnl NOTE: commented out, see ac_check_ocaml_pkg_path.m4 + dnl AC_MSG_CHECKING([for OCaml findlib package $1]) + + unset found + unset pkg + found=no + for pkg in $1 $2 ; do + if $OCAMLFIND query $pkg >/dev/null 2>/dev/null; then + dnl NOTE: commented out, see ac_check_ocaml_pkg_path.m4 + dnl AC_MSG_RESULT([found]) + AS_TR_SH([OCAML_PKG_$1])=$pkg + found=yes + break + fi + done + if test "$found" = "no" ; then + dnl NOTE: commented out, see ac_check_ocaml_pkg_path.m4 + dnl AC_MSG_RESULT([not found]) + AS_TR_SH([OCAML_PKG_$1])=no + fi + + AC_SUBST(AS_TR_SH([OCAML_PKG_$1])) +]) + + +AC_DEFUN([AC_CHECK_OCAML_MODULE], +[dnl + AC_MSG_CHECKING([for OCaml module $2]) + + cat > conftest.ml <&5 2>&5 ; then + found=yes + break + fi + done + + if test "$found" ; then + AC_MSG_RESULT([$$1]) + else + AC_MSG_RESULT([not found]) + $1=no + fi + AC_SUBST([$1]) +]) + + +dnl XXX Cross-compiling +AC_DEFUN([AC_CHECK_OCAML_WORD_SIZE], +[dnl + AC_REQUIRE([AC_PROG_OCAML])dnl + AC_MSG_CHECKING([for OCaml compiler word size]) + cat > conftest.ml < conftest.ml <