Coccinelle release-1.0.0-rc11
[bpt/coccinelle.git] / configure
index 79872ca..2e46817 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 
-# Author: Yoann Padioleau 
+# Author: Yoann Padioleau
 
 ######################################################################
 # Prelude
@@ -28,24 +28,83 @@ my $projectcmdline =
 
 my $prefix="/usr/local";
 my $python=1;
-my $trac=0;
+my $pcre=1;
+my $noocamlscripting=0;
 my $opt=".opt";
 my $tarzan=1;
+my $pydir="pycaml";
+my $menhirdir="menhirlib";
+my $sexpdir="ocamlsexp";
+my $python_cmd="python";
+
+# generic ocaml libraries (set entries to 0 to disable by default)
+# 0: disabled, 1: use global library, >1: use local library
+my %libs=
+  ( "pycaml"    => 1
+  , "menhirLib" => 1
+  , "sexplib"   => 1
+  , "pcre"      => 1
+  , "dynlink"   => 0
+  , "extlib"    => 0
+  );
+
+# add additional dependencies that some of these libraries may have
+# these will then be added automatically
+# (we don't really make use of this here)
+my %deps=
+  ( # "pycaml" => ["str"]    # example
+    # "sexplib" => ["unix", "bigarray", "num"]
+  );
 
 local $_ = join ' ', @ARGV;
 
 # Parse options
-/-h/ || /--help/ and die "usage: $0 [--prefix=path] [--without-python] [--with-trac] [--no-opt]\n\n\t--no-opt\tDo not use the optimimized version of OCaml\n\t--opt\tUse the optimimized version of OCaml\n\n";
+/-h/ || /--help/ and die "usage: $0 [--prefix=path] [--without-FEATURE] [--no-opt]\n
+\t--without-python\tDisable scripting in Python
+\t--without-ocaml\t\tDisable scripting in Ocaml
+\t--without-pcre\t\tDisable regexp with PCRE
+\t--with-pyton=PATH\t\tSpecify path to python executable
+\t--no-opt\t\tDo not use the optimimized version of OCaml
+\t--opt\t\t\tUse the optimimized version of OCaml\n\n";
 /--prefix=([^ ]*)/ and $prefix = $1;
+/--without-pcre/ and $pcre = 0;
 /--without-python/ and $python = 0;
-/--without-trac/ and $trac = 0;
-/--with-trac/ and $trac = 1;
+/--without-ocaml/ and $noocamlscripting = 1;
 /--no-opt/ and $opt = "";
 /--opt/ and $opt = ".opt";
+/--with-python=([^ ]*)/ and $python_cmd = $1;
+
+# todo: also print these options as part of the help message...
+foreach my $lib (keys %libs) {
+  /--with-$lib/ and $libs{$lib} = 1;
+  /--with-local-$lib/ and $libs{$lib} = 2;
+  /--without-$lib/ and $libs{$lib} = 0;
+}
 
 #tarzan by default (used by score file parsing and now also for sexp_ast_c.ml)
 
 
+# extend the feature set based on their dependencies
+my $changedLibs = 1;
+while($changedLibs) {
+  $changedLibs = 0;
+  foreach $dep (keys %deps) {
+    if ($libs{$dep}) {
+      my $reqs = $deps{$dep};
+      foreach $req (@$reqs) {
+        if (!$libs{$req}) {
+         $libs{$req}  = 1;
+         $changedLibs = 1;
+       }
+      }
+    }
+  }
+}
+
+if (!$python) {
+  $libs{'pycaml'} = 0;
+}
+
 #if($ARGV[0] =~ "--prefix=(.*)") {
 #    $prefix = $1;
 #}
@@ -99,17 +158,26 @@ my $error = 0;
 #---------------------------------------------------------------------
 # Compilers and runtimes
 #---------------------------------------------------------------------
+
 $error +=
     check_config("echo \"1;;\\n\" | ocaml |",
-#                 "Objective(.*) 3.0[9]",
-                 "Objective(.*) 3.",
+                 "Objective(.*) 3.\(09|1[0-9]\)",
                  "OCaml (the wonderful language) is present.",
                  "The program ocaml is missing or is not a good version. We need at least 3.09",
                  );
 
+unless ($noocamlscripting) {
+$noocamlscripting = check_config("echo \"1;;\\n\" | ocaml |",
+                 "Objective(.*) 3.1[1-9]",
+                 "OCaml >= 3.11 is present. OCaml scripting activated.",
+                 "OCaml scripting disabled. We need at least OCaml 3.11",
+                 );
+}
+my $ocamlprefix = $noocamlscripting ? "no" : "yes";
+
 if ($opt eq ".opt") {
-   my $opt_check = `which ocamlc.opt 2> /dev/null`;
-   if($opt_check =~ "/ocamlc.opt\$") {
+   my $opt_check1 = `ocamlc.opt -version 2>/dev/null`;
+   if($opt_check1 =~ /[0-9\.]+/) {
        pr2 "ocamlc.opt is present.";
    }
    else {
@@ -117,8 +185,8 @@ if ($opt eq ".opt") {
        pr2 "ocamlc.opt not found";
    }
 
-   my $opt_check = `which ocamlopt.opt 2> /dev/null`;
-   if($opt_check =~ "/ocamlopt.opt\$") {
+   my $opt_check2 = `ocamlopt.opt -version 2>/dev/null`;
+   if($opt_check2 =~ /[0-9\.]+/) {
        pr2 "ocamlopt.opt is present.";
    }
    else {
@@ -126,8 +194,8 @@ if ($opt eq ".opt") {
        pr2 "ocamlopt.opt not found";
    }
 
-   my $opt_check = `which ocamldep.opt 2> /dev/null`;
-   if($opt_check =~ "/ocamldep.opt\$") {
+   my $opt_check3 = `ocamldep.opt -version 2>/dev/null`;
+   if($opt_check3 =~ /[0-9\.]+/) {
        pr2 "ocamldep.opt is present.";
    }
    else {
@@ -135,8 +203,8 @@ if ($opt eq ".opt") {
        pr2 "ocamldep.opt not found";
    }
 
-   my $opt_check = `which ocamllex.opt 2> /dev/null`;
-   if($opt_check =~ "/ocamllex.opt\$") {
+   my $opt_check4 = `ocamllex.opt -version 2>/dev/null`;
+   if($opt_check4 =~ /[0-9\.]+/) {
        pr2 "ocamllex.opt is present.";
    }
    else {
@@ -175,7 +243,6 @@ $error += check_config(
 We need  3.XX",
 );
 
-
 #---------------------------------------------------------------------
 # More developers tools
 #---------------------------------------------------------------------
@@ -184,6 +251,130 @@ We need  3.XX",
 # Librairies
 #---------------------------------------------------------------------
 
+# Python dev
+my $PY_VERSION;
+if($python) {
+    if(check_config(
+       "$python_cmd --version 2>&1 |",
+       '^Python [23]\.',
+       "$python_cmd is present",
+       "$python_cmd is missing or is not a good version."
+       ))
+    {
+       $python=0;
+    }
+    if($python) {
+       my $PY_PREFIX = `$python_cmd pycaml/getprefix.py | tr -d '\n'`;
+       $PY_VERSION = `$python_cmd pycaml/getversion.py | tr -d '\n'`;
+       my $python_hdr = "$PY_PREFIX/include/python$PY_VERSION/Python.h";
+       if(check_config(
+           "ls $python_hdr 2> /dev/null | ",
+           $python_hdr,
+           "Python.h found",
+           "Python.h missing - You need to install python-dev"
+           ))
+       {
+           $python=0
+       }
+    }
+}
+
+my $ocamlfind=!check_config(
+       "ocamlfind ocamlc -version 2> /dev/null | ",
+       '^[0-9\.]+',
+       "ocamlfind is present",
+       "ocamlfind is missing -- Switch to local library copies."
+    );
+
+# pycaml. Binding between Python and OCaml
+my $syspydir=`ocamlfind query pycaml 2> /dev/null | xargs echo -n`;
+
+if($syspydir) {
+    pr2 "'pycaml' library is present in $syspydir";
+    if ($libs{'pycaml'} > 1) {
+        pr2 "... but a local copy of 'pycaml' will be used.";
+    }
+    else {
+        $pydir=$syspydir;
+    }
+} else {
+    pr2 "'pycaml' library is not present. A local copy will be used.";
+}
+
+# menhirLib. Runtime system for the parsers generated with menhir
+my $sysmenhirdir=`ocamlfind query menhirLib 2> /dev/null | xargs echo -n`;
+
+if($sysmenhirdir) {
+    $menhirdir=$sysmenhirdir;
+    pr2 "'menhirLib' library is present in $menhirdir";
+} else {
+    pr2 "'menhirLib' library is not present. A local copy will be used.";
+}
+
+# sexplib.
+my $syssexpdir=`ocamlfind query sexplib 2> /dev/null | xargs echo -n`;
+
+if($syssexpdir) {
+    $sexpdir=$syssexpdir;
+    pr2 "'sexplib' library is present in $sexpdir";
+} else {
+    pr2 "'sexplib' library is not present. A local copy will be used.";
+}
+
+# Check if libpcre-ocaml is available
+# when pcre feature is enabled.
+my $pcredir="";
+if($pcre) {
+    $pcredir=`ocamlfind query pcre 2> /dev/null | xargs echo -n `;
+    if(check_config(
+          "echo -n $pcredir | ",
+          '^/.*$',
+          "'pcre-ocaml' library is present in $pcredir",
+          "'pcre-ocaml' library is not present - You need to install libpcre-ocaml-dev"
+       ))
+    {
+       $pcre=0
+    }
+}
+
+######################################################################
+# Printing of library selection
+######################################################################
+
+
+pr2 "----------------------------------------------------------------------";
+pr2 "Library configuration:";
+
+my %libPaths;
+foreach my $lib (keys %libs) {
+  my $isSelected = $libs{$lib};
+  if ($isSelected) {
+    my $libdir = `ocamlfind query $lib 2> /dev/null | xargs echo -n`;
+    if ($libdir && $libs{$lib} <= 1) {
+      $libs{$lib} = 1;
+      $libPaths{$lib} = $libdir;
+    }
+    else {
+      if (-d $lib) {      # test if local directory exists
+        $libs{$lib} = 2;  # use local version
+       $libPaths{$lib} = $lib;
+      } else {
+        $libs{$lib} = 0;  # disable the feature
+       $libPaths{$lib} = "";
+      }
+    }
+  }
+
+  my $choice = $libs{$lib};
+  if ($choice == 0) {
+    pr2 "$lib: disabled";
+  } elsif ($choice == 1) {
+    pr2 "$lib: global version in $libPaths{$lib}";
+  } else {
+    pr2 "$lib: local version selected";
+  }
+}
+
 ######################################################################
 # Generate config files (platform/portability issues)
 ######################################################################
@@ -197,7 +388,6 @@ We need  3.XX",
 # Diagnostic
 ######################################################################
 
-
 if($error) {
     pr2 "
 ----------------------------------------------------------------------
@@ -211,12 +401,8 @@ on the $project website. !!!!
 ";
 } else {
 
-#pad: before the message was saying (make depend); make all
-# I found this confusing so I removed it.
-
-    pr2 "
-
-----------------------------------------------------------------------
+    pr2
+"----------------------------------------------------------------------
 
 All seems fine for $project.
 
@@ -238,25 +424,24 @@ Then, to test $project simply type:
 
 ";
 
-if($python) {
-        pr2
+    if($python) {
+       pr2
 "To use the python SmPL feature you may have to set some environment variables.
+However, they are automatically set by the front-end installed in $prefix/bin.
 For bash do:
 export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:$prefix/lib
-export PYTHONPATH=\$PYTHONPATH:$src/python
-"
+export PYTHONPATH=\$PYTHONPATH:$src/python"
     }
-    pr2 "
-----------------------------------------------------------------------
-";
-}
-
 
+    pr2 "----------------------------------------------------------------------";
+}
 
 ######################################################################
 # Generating the configuration
 ######################################################################
 
+pr2 "  Compilation configuration\n";
+
 pr2 "$project target prefix: $prefix (you can use --prefix to override it)";
 pr2 "Generating Makefile.config";
 open(CONFIG, ">Makefile.config");
@@ -279,9 +464,28 @@ LIBDIR=$prefix/lib
 # Where to install the configuration files
 SHAREDIR=$src
 
+BASH_COMPLETION_DIR=/etc/bash_completion.d
+
 # Features
 FEATURE_PYTHON=$python
 FEATURE_TARZAN=$tarzan
+";
+
+if ($python) {
+print CONFIG "PYVER=$PY_VERSION\n";
+print CONFIG "PYCMD=$python_cmd\n";
+}
+
+if($pcre) {
+print CONFIG "
+PCREDIR=$pcredir"
+}
+
+print CONFIG "
+PYCAMLDIR=$pydir
+MENHIRDIR=$menhirdir
+SEXPDIR=$sexpdir
+DYNLINK=$ocamlprefix
 
 # The OPTBIN variable is here to allow to use ocamlc.opt instead of
 # ocaml, when it is available, which speeds up compilation. So
@@ -290,28 +494,133 @@ FEATURE_TARZAN=$tarzan
 OPTBIN=$opt
 ";
 
-pr2 "Modifying globals/config.ml";
-pr2 "Generating appropriate links in python/ (python=$python)";
-my $pythonprefix = $python ? "yes_" : "no_";
-`cd python; rm -f  pycocci.ml pycocci_aux.ml;`;
-`cd python; ln -s ${pythonprefix}pycocci.ml pycocci.ml; `;
-`cd python; ln -s ${pythonprefix}pycocci_aux.ml pycocci_aux.ml;`;
-`cd python; make depend`;
-
-my $command = "perl -p -e 's#Not_found.\*#Not_found->\\\"$src\\\"#' globals/config.ml.in > globals/config.ml";
-`$command`;
-
 #
-# Configuration of python with or without trac
+# Generate variables for handling the ocaml libraries
 #
-`cd python/coccilib; ln -sf output_base.py output.py;`;
-if($trac) {
-# Switch between implementation
-# in python/coccilib
-pr2 "Selecting python trac extension";
-`cd python/coccilib; ln -sf output_trac.py output.py;`;
+
+my @sellibs     = ();
+my @makelibs    = ();
+my @cleanlibs   = ();
+my @deplibs     = ();
+my @lnklibs     = ();
+my @optlnklibs  = ();
+my @inclibs     = ();
+my @flagslibs   = ();
+my @featurelibs = ();
+my @pathlibs    = ();
+
+sub strVar {
+  return "\$(" . $_[0] . "_" . $_[1] . ")";
+}
+
+foreach $lib (keys %libs) {
+  my $sel     = $libs{$lib};
+  my $path    = $libPaths{$lib};
+  my $pathvar = strVar("PATH", $lib);
+
+  if ($sel == 1) {              # global version
+    push(@lnklibs,    strVar("GLOBAL", $lib));
+    push(@optlnklibs, strVar("GLOBALOPT", $lib));
+  } elsif ($sel > 1) {         # local version
+    push(@lnklibs,    strVar("LOCAL", $lib));
+    push(@optlnklibs, strVar("LOCALOPT", $lib));
+    if (-e "$path/Makefile") {  # does it have a Makefile?
+      push(@makelibs,  $pathvar);
+      push(@cleanlibs, $pathvar);
+      push(@deplibs,   $pathvar);
+    }
+  }
+
+  if ($sel >= 1) {  # indifferent of global/local
+    push(@sellibs,     $lib);
+    push(@inclibs,     $pathvar);
+    push(@flagslibs,   strVar("FLAGS", $lib));
+    
+    push(@featurelibs, "FEATURE_$lib=1");
+    push(@pathlibs,    "PATH_$lib=$path");
+  }
+}
+
+my $strSellibs    = join(" ", @sellibs);
+my $strMakelibs   = join(" ", @makelibs);
+my $strCleanlibs  = join(" ", @cleanlibs);
+my $strDeplibs    = join(" ", @deplibs);
+my $strLnklibs    = join(" ", @lnklibs);
+my $strOptlnklibs = join(" ", @optlnklibs);
+my $strInclibs    = join(" ", @inclibs);
+my $strFlagslibs  = join(" ", @flagslibs);
+my $strFeatures   = join("\n", @featurelibs);
+my $strPaths      = join("\n", @pathlibs);
+
+print CONFIG "
+# selected libraries
+$strFeatures
+
+# library paths
+$strPaths
+
+# collected config vars
+SELLIBS=$strSellibs
+MAKELIBS=$strMakelibs
+CLEANLIBS=$strCleanlibs
+DEPLIBS=$strDeplibs
+LNKLIBS=$strLnklibs
+OPTLNKLIBS=$strOptlnklibs
+INCLIBS=$strInclibs
+FLAGSLIBS=$strFlagslibs
+
+# selected ocaml modules
+";
+
+sub repl {
+    my $src = $_[0];
+    my $dest = $_[1];
+    my $key = $_[2];
+    my $val = ucfirst($_[3]);
+    my $cmd = "sed -e 's|${key}|${val}|g' ${src} > ${dest}";
+    if (-e $dest) {
+       unlink($dest);
+    }
+    `$cmd`;
 }
 
+my $pythonprefix = $python ? "yes" : "no";
+pr2 "Support for python scripting: $pythonprefix";
+repl('python/pycocci.ml.in', 'python/pycocci.ml', '@PYCOCCI_FILE@', "${pythonprefix}_pycocci");
+print CONFIG "PYCOCCI_FILE=${pythonprefix}_pycocci.ml\n";
+# `cd python; ln -sf ${pythonprefix}_pycocci.ml pycocci.ml; `;
+`cd python; make depend`;
+
+pr2 "Support for ocaml scripting: $ocamlprefix";
+repl('ocaml/prepare_ocamlcocci.ml.in', 'ocaml/prepare_ocamlcocci.ml', '@OCAMLCOCCI_FILE@', "${ocamlprefix}_prepare_ocamlcocci");
+print CONFIG "OCAMLCOCCI_FILE=${ocamlprefix}_prepare_ocamlcocci.ml\n";
+# `cd ocaml; ln -sf ${ocamlprefix}_prepare_ocamlcocci.ml prepare_ocamlcocci.ml;`;
+`cd ocaml; make depend`;
 
+my $pcresuffix = $pcre ? "pcre" : "str";
+pr2 "Support for regexp: $pcresuffix";
+repl('globals/regexp.ml.in', 'globals/regexp.ml', '@REGEXP_FILE@', "Regexp_${pcresuffix}");
+print CONFIG "REGEXP_FILE=regexp_${pcresuffix}.ml";
+# `cd globals; ln -sf regexp_${pcresuffix}.ml regexp.ml; touch regexp.ml;`;
+`cd globals; make depend`;
 
+pr2 "Modifying globals/config.ml";
+my $version = `cat ./version | tr -d '\n'`;
+`echo -n "$version" > ./version`; # make sure that there are no newlines after version
+my $command1 = "sed -i -e 's|^let version = \".*\"\$|let version = \"$version\"|g' globals/config.ml.in"; # substitute version
+my $command2 = "perl -p -e 's#Not_found.\*#Not_found->\\\"$src\\\"#' globals/config.ml.in > globals/config.ml";
+`$command1`;
+`$command2`;
+
+pr2 "----------------------------------------------------------------------";
+pr2 "  Runtime dependency\n";
+
+if ($ocamlfind) {
+pr2 "Support for external ocaml library in ocaml scripting: yes (ocamlfind found)";
+}
+else {
+pr2 "Support for external ocaml library in ocaml scripting: no";
+pr2 "!!!!!!! WARNING !!!!!!! ocamlfind may be required at runtime";
+}
 
+pr2 "";