#!/bin/bash ######################################################################### # # # OCaml # # # # Damien Doligez, Jane Street Capital # # # # Copyright 2014 Institut National de Recherche en Informatique et # # en Automatique. All rights reserved. This file is distributed # # under the terms of the Q Public License version 1.0. # # # ######################################################################### [ -z "$Tdebug" ] || set -x Pwith_byte=true Pwith_opt=true while : ; do case $1 in -no-byte) Pwith_byte=false; shift;; -no-opt) Pwith_opt=false; shift;; *) break;; esac done Pfile=$1 Pdir=$(dirname $1) base=$(basename $1 .t) byte_exec=$base.byt opt_exec=$base.exe Pocamlrun="$TOPDIR/boot/ocamlrun$EXE" Pflags="-nostdlib -I $OTOPDIR/stdlib -I $OTOPDIR/testsuite/lib" Pocamlc="$Pocamlrun $OTOPDIR/ocamlc $Pflags" Pocamlopt="$Pocamlrun $OTOPDIR/ocamlopt $Pflags" Pocaml="$Pocamlrun $OTOPDIR/ocaml $Pflags \ -init $OTOPDIR/testsuite/scripts/empty" Pocamldoc="$Pocamlrun $OTOPDIR/ocamldoc/ocamldoc" Plex="$Pocamlrun $OTOPDIR/lex/ocamllex" Pyacc="$TOPDIR/yacc/ocamlyacc$EXE" Pocamlmklib="$Pocamlrun $OTOPDIR/tools/ocamlmklib \ -ocamlc '$OTOPDIR/boot/ocamlrun$EXE $OTOPDIR/ocamlc $Pflags' \ -ocamlopt '$OTOPDIR/boot/ocamlrun$EXE $OTOPDIR/ocamlopt $Pflags'" if [ "$ARCH" = none -o "$ASM" = none ]; then Pwith_opt=false fi # Pcustomflag is set to "-custom" (at several places in this file) # as soon as a custom runtime is needed. if $SUPPORTS_SHARED_LIBRARIES; then Pcustomflag= else Pcustomflag=-custom fi sources="$base.ml" kinds="byte opt" compflags= byteflags= custom=false optflags= lexflags=-q yaccflags=-q topflags= cflags= fortranflags= exec_env= args= exit=0 compexit=0 postprocess=false postexit=0 # Print the error message to stderr and exit with an error code. error () { echo ERROR: $* >&2 exit 5 } # Log the command given as argument(s) and execute it, saving the outputs launch () { echo "$*" >&2 Ltmpexit=0 Lstg=${Pstage:+-$Pstage} eval "$*" >_tmp/$base-$kind$Lstg.refout \ 2>>_tmp/$base-$kind$Lstg.referr \ || Ltmpexit=$? eval "P${Pstage}exit=$Ltmpexit" } # Log the command given as argument(s) and execute it, leaving the outputs alone log () { echo "$*" >&2 eval "$*" } # Compile mlyacc, mllex and C files, and build a list of files for the # OCaml compiler to compile and link. # Two arguments: the extensions to use for library objects (cmo/cmx) and # libs (cma/cmxa). precompile () { cmoext=$1 cmaext=$2 Pocamlfiles= for f in $sources; do case $f in *.ml|*.mli) Pocamlfiles="$Pocamlfiles $f";; *.mly) launch $Pyacc $yaccflags $f Pocamlfiles="$Pocamlfiles ${f%.mly}.mli ${f%.mly}.ml" ;; *.mll) launch $Plex $lexflags $f Pocamlfiles="$Pocamlfiles ${f%.mll}.ml" ;; *.c) launch $NATIVECC $NATIVECCCOMPOPTS $cflags \ -I $CTOPDIR/byterun -c $f Pcustomflag=-custom Pocamlfiles="$Pocamlfiles ${f%.c}.$O" ;; *.f) launch $FORTRAN_COMPILER $fortranflags -c $f Pcustomflag=-custom Pocamlfiles="$Pocamlfiles ${f%.f}.$O" ;; *.cmo) Pocamlfiles="$Pocamlfiles ${f%.cmo}.$cmoext";; *.cma) Pocamlfiles="$Pocamlfiles ${f%.cma}.$cmaext";; *.$O) Pcustomflag=-custom Pocamlfiles="$Pocamlfiles $f" ;; *) error "unexpected source file extension: $f";; esac done } opt_comp () { preprocess precompile cmx cmxa launch $Pocamlopt $compflags $optflags $Pocamlfiles -o $opt_exec } byte_comp () { preprocess precompile cmo cma if $custom; then Pcustomflag=-custom; fi launch $Pocamlc $compflags $Pcustomflag $byteflags $Pocamlfiles \ -o $byte_exec } top_comp () { launch : no compilation step needed } top_principal_comp () { launch : no compilation step needed } opt_run () { launch $SET_LD_PATH $exec_env ./$opt_exec $args } byte_run () { case $Pcustomflag in "") Luseruntime=$Pocamlrun;; -custom) Luseruntime=;; *) error "internal error (bad value for Pcustomflag)";; esac launch $SET_LD_PATH $exec_env $Luseruntime ./$byte_exec $args } top_run () { launch "cat $sources | TERM=dumb $Pocaml $topflags 2>&1 \ | grep -v '^ OCaml version'" } top_principal_run () { launch "cat $sources | TERM=dumb $Pocaml $topflags -principal 2>&1 \ | grep -v '^ OCaml version'" } postprocess_sort () { log "sort $1 >$1.post" } postprocess_sort_uniq () { log "sort $1 | uniq >$1.post" } Pcompare_files () { ref="$1" act="$2" if [ ! -f "$ref" ]; then ref=/dev/null; fi log $DIFF $ref $act } Pcheck () { if $postprocess; then post=.post else post= fi case $kind in *_*) variant=-${kind#*_};; *) variant=;; esac ( set -e for suff in -comp.referr -comp.refout .referr$post .refout$post; do Pcompare_files $base$variant$suff _tmp/$base-$kind$suff done [ "$Pcompexit" -eq "$compexit" ] || { error "compilation exit code $Pcompexit is different" \ "from expected $compexit" false } [ "$Pexit" -eq "$exit" ] || { error "program exit code $Pexit is different from expected $exit" false } ) } Pcheck_kind () { case $kind/$Pwith_opt/$Pwith_byte in opt/false/*) false;; byte/*/false) false;; top*/*/false) false;; # top is a subset of byte *) true;; esac } preprocess () { : } precheck () { case "$sources " in *'.f '*) test -n "$FORTRAN_COMPILER";; esac } opt_precheck () { precheck } byte_precheck () { precheck } top_precheck () { precheck } Pexport_variables () { export OCAMLYACC="$Pyacc" export OCAMLLEX="$Plex" export OCAMLC="$Pocamlc" export OCAMLOPT="$Pocamlopt" export OCAMLRUN="$Pocamlrun" } Pstart_test () { printf "Testing %-4s %s ... " "$kind" "$Pfile" >&3 printf "#################################################" printf "\nTesting %-4s %s ...\n" "$kind" "$Pfile" } Pskip_test () { printf "skip\n" >&3 printf "skip\n\n" exit 0 } Pfail_test () { printf "FAIL\n" >&3 printf "FAIL\n\n" } Ppass_test () { printf "pass\n" >&3 printf "pass\n\n" } cd "$Pdir" ###################################################### # read the user's definitions . ./$base.t ###################################################### Pexport_variables mkdir -p _tmp for kind in $kinds; do Pstart_test ( # Skip test if kind=opt and configured without native code # or if user disabled the current kind Pcheck_kind || Pskip_test # Run user-defined pre-check ${kind}_precheck || Pskip_test rm -f _tmp/$base*.ref{out,err} ( Pstage=comp ${kind}_comp Pstage= ${kind}_run if $postprocess; then Pstage=post (cd _tmp; ${kind}_postprocess_out $base-$kind.refout) (cd _tmp; ${kind}_postprocess_err $base-$kind.referr) fi Pcheck ) case $? in 0) Ppass_test;; *) Pfail_test;; esac ) done