]> git.lizzy.rs Git - rust.git/blobdiff - configure
Add support for clang 4.2 (as reported by apple clang) r=graydon
[rust.git] / configure
index dd213c809ef650983bad728dfc0a04ae016f9009..9813f0ec6b6f8e56e905b0197ad72f44ee2b1630 100755 (executable)
--- a/configure
+++ b/configure
@@ -19,6 +19,12 @@ err() {
     exit 1
 }
 
+need_ok() {
+    if [ $? -ne 0 ]
+    then
+        err $1
+    fi
+}
 
 need_cmd() {
     if which $1 >/dev/null 2>&1
@@ -35,9 +41,26 @@ make_dir() {
     fi
 }
 
-copy() {
-    msg "cp $1 $2"
-    cp $1 $2
+copy_if_changed() {
+    if cmp -s $1 $2
+    then
+        msg "leaving $2 unchanged"
+    else
+        msg "cp $1 $2"
+        cp -f $1 $2
+        chmod u-w $2 # make copied artifact read-only
+    fi
+}
+
+move_if_changed() {
+    if cmp -s $1 $2
+    then
+        msg "leaving $2 unchanged"
+    else
+        msg "mv $1 $2"
+        mv -f $1 $2
+        chmod u-w $2 # make moved artifact read-only
+    fi
 }
 
 putvar() {
@@ -48,36 +71,81 @@ putvar() {
     then
         printf "configure: %-20s := %.35s ...\n" $1 "$T"
     else
-        printf "configure: %-20s := %s\n" $1 "$T"
+        printf "configure: %-20s := %s %s\n" $1 "$T" "$2"
     fi
-    printf "%-20s := %s\n" $1 "$T" >>config.mk
+    printf "%-20s := %s\n" $1 "$T" >>config.tmp
 }
 
 probe() {
     local V=$1
-    local P=$2
+    shift
+    local P
     local T
-    T=$(which $P 2>&1)
-    if [ $? -ne 0 ]
-    then
-        T=""
-    fi
+    for P
+    do
+        T=$(which $P 2>&1)
+        if [ $? -eq 0 ]
+        then
+            VER0=$($P --version 2>/dev/null | head -1 \
+                |  sed -e 's/[^0-9]*\([vV]\?[0-9.]\+[^ ]*\).*/\1/' )
+            if [ $? -eq 0 -a "x${VER0}" != "x" ]
+            then
+              VER="($VER0)"
+            else
+              VER=""
+            fi
+            break
+        else
+            VER=""
+            T=""
+        fi
+    done
     eval $V=\$T
-    putvar $V
+    putvar $V "$VER"
 }
 
 probe_need() {
     local V=$1
-    local P=$2
-    probe $V $P
+    probe $*
     eval VV=\$$V
     if [ -z "$VV" ]
     then
-        err "required program '$P' not found"
+        err "needed, but unable to find any of: $*"
     fi
 }
 
+validate_opt () {
+    for arg in $CFG_CONFIGURE_ARGS
+    do
+        isArgValid=0
+        for option in $BOOL_OPTIONS
+        do
+            if test --disable-$option = $arg
+            then
+                isArgValid=1
+            fi
+            if test --enable-$option = $arg
+            then
+                isArgValid=1
+            fi
+        done
+        for option in $VAL_OPTIONS
+        do
+            if echo "$arg" | grep -q -- "--$option="
+            then
+                isArgValid=1
+            fi
+        done
+        if test $isArgValid -eq 0
+        then
+            err "Option '$arg' is not recognized"
+        fi
+    done
+}
+
 valopt() {
+    VAL_OPTIONS="$VAL_OPTIONS $1"
+
     local OP=$1
     local DEFAULT=$2
     shift
@@ -85,7 +153,7 @@ valopt() {
     local DOC="$*"
     if [ $HELP -eq 0 ]
     then
-        local UOP=$(echo $OP | tr 'a-z-' 'A-Z_')
+        local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
         local V="CFG_${UOP}"
         eval $V="$DEFAULT"
         for arg in $CFG_CONFIGURE_ARGS
@@ -108,6 +176,8 @@ valopt() {
 }
 
 opt() {
+    BOOL_OPTIONS="$BOOL_OPTIONS $1"
+
     local OP=$1
     local DEFAULT=$2
     shift
@@ -146,9 +216,11 @@ opt() {
 }
 
 msg "looking for configure programs"
+need_cmd cmp
 need_cmd mkdir
 need_cmd printf
 need_cmd cut
+need_cmd head
 need_cmd grep
 need_cmd xargs
 need_cmd cp
@@ -158,6 +230,7 @@ need_cmd date
 need_cmd tr
 need_cmd sed
 
+
 msg "inspecting environment"
 
 CFG_OSTYPE=$(uname -s)
@@ -167,13 +240,12 @@ if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
 then
     # Darwin's `uname -s` lies and always returns i386. We have to use sysctl
     # instead.
-    if sysctl hw.optional.x86_64 | grep ': 1'
+    if sysctl hw.optional.x86_64 | grep -q ': 1'
     then
         CFG_CPUTYPE=x86_64
     fi
 fi
 
-
 # The goal here is to come up with the same triple as LLVM would,
 # at least for the subset of platforms we're willing to target.
 
@@ -211,7 +283,7 @@ case $CFG_CPUTYPE in
         CFG_CPUTYPE=arm
         ;;
 
-    x86_64 | x86-64 | x64)
+    x86_64 | x86-64 | x64 | amd64)
         CFG_CPUTYPE=x86_64
         ;;
 
@@ -219,11 +291,21 @@ case $CFG_CPUTYPE in
         err "unknown CPU type: $CFG_CPUTYPE"
 esac
 
-CFG_HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
+# Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation
+if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ]
+then
+    file -L "$SHELL" | grep -q "x86[_-]64"
+    if [ $? != 0 ]; then
+        CFG_CPUTYPE=i686
+    fi
+fi
 
-CFG_SELF=$(echo $0 | tr '\\' '/')
-CFG_SRC_DIR=${CFG_SELF%${CFG_SELF##*/}}
-CFG_BUILD_DIR=$(echo $PWD | tr '\\' '/')
+
+DEFAULT_HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
+
+CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
+CFG_BUILD_DIR="$(pwd)/"
+CFG_SELF=${CFG_SRC_DIR}$(basename $0)
 CFG_CONFIGURE_ARGS="$@"
 
 OPTIONS=""
@@ -238,21 +320,38 @@ then
     echo "Options:"
     echo ""
 else
-    msg "recreating config.mk"
-    echo '' >config.mk
+    msg "recreating config.tmp"
+    echo '' >config.tmp
 
     step_msg "processing $CFG_SELF args"
 fi
 
+BOOL_OPTIONS=""
+VAL_OPTIONS=""
+
 opt sharedstd 1 "build libstd as a shared library"
-opt valgrind 1 "run tests with valgrind"
+opt valgrind 0 "run tests with valgrind (memcheck by default)"
+opt helgrind 0 "run tests with helgrind instead of memcheck"
 opt docs     1 "build documentation"
 opt optimize 1 "build optimized rust code"
+opt optimize-cxx 1 "build optimized C++ code"
+opt optimize-llvm 1 "build optimized LLVM"
+opt debug 0 "build with extra debug fun"
+opt fast-make 0 "use .gitmodules as timestamp for submodule deps"
+opt manage-submodules 1 "let the build manage the git submodules"
 opt mingw-cross 0 "cross-compile for win32 using mingw"
-opt only-gcc 0 "prefer gcc to clang for building the runtime"
+opt clang 0 "prefer clang to gcc for building the runtime"
+opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
+opt pax-flags 0 "apply PaX flags to rustc binaries (required for GRSecurity/PaX-patched kernels)"
 valopt prefix "/usr/local" "set installation prefix"
+valopt local-rust-root "/usr/local" "set prefix for local rust binary"
 valopt llvm-root "" "set LLVM root"
-valopt target-triples "" "LLVM target triples (defaults to host if unset)"
+valopt host-triple "${DEFAULT_HOST_TRIPLE}" "LLVM host triple"
+valopt target-triples "${CFG_HOST_TRIPLE}" "LLVM target triples"
+
+# Validate Options
+step_msg "validating $CFG_SELF args"
+validate_opt
 
 if [ $HELP -eq 1 ]
 then
@@ -260,172 +359,213 @@ then
     exit 0
 fi
 
-step_msg "writing out basic parameters"
-putvar CFG_SRC_DIR
-putvar CFG_BUILD_DIR
-putvar CFG_OSTYPE
-putvar CFG_CPUTYPE
-putvar CFG_CONFIGURE_ARGS
 
 step_msg "looking for build programs"
-probe_need CFG_PERL         perl
-probe_need CFG_PYTHON       python
-probe_need CFG_CURL         curl
 
-probe CFG_GIT              git
+probe_need CFG_PERL        perl
+probe_need CFG_CURL        curl
+probe_need CFG_PYTHON      python2.7 python2.6 python2 python
+
+python_version=$($CFG_PYTHON -V 2>&1)
+if [ $(echo $python_version | grep -c '^Python 2\.[4567]') -ne 1 ]; then
+    err "Found $python_version, but LLVM requires Python 2.4-2.7"
+fi
+
+# If we have no git directory then we are probably a tarball distribution
+# and shouldn't attempt to load submodules
+if [ ! -e ${CFG_SRC_DIR}.git ]
+then
+    probe CFG_GIT          git
+    msg "git: no git directory. disabling submodules"
+    CFG_DISABLE_MANAGE_SUBMODULES=1
+else
+    probe_need CFG_GIT     git
+fi
+
 probe CFG_CLANG            clang++
 probe CFG_GCC              gcc
-probe CFG_LLVM_CONFIG      llvm-config
+probe CFG_LD               ld
 probe CFG_VALGRIND         valgrind
 probe CFG_PERF             perf
-probe CFG_MAKEINFO         makeinfo
-probe CFG_TEXI2PDF         texi2pdf
-probe CFG_TEX              tex
-probe CFG_MAKENSIS         makensis
-probe CFG_NATURALDOCS      naturaldocs
-
-if [ -z "$CFG_CLANG" -a -z "$CFG_GCC" ]
+probe CFG_ISCC             iscc
+probe CFG_LLNEXTGEN        LLnextgen
+probe CFG_PANDOC           pandoc
+probe CFG_PDFLATEX         pdflatex
+probe CFG_XETEX            xetex
+probe CFG_LUATEX           luatex
+probe CFG_NODE             nodejs node
+if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ]
 then
-    err "either clang or gcc is required"
+    probe CFG_PAXCTL           paxctl /sbin/paxctl
+    probe CFG_ZCAT             zcat
 fi
 
-if head -n 1 ${CFG_SRC_DIR}src/snapshots.txt | grep -q '^T'
+if [ ! -z "$CFG_PANDOC" ]
 then
-    CFG_IN_TRANSITION=1
-    putvar CFG_IN_TRANSITION
+    PANDOC_VER_LINE=$(pandoc --version | grep '^pandoc ')
+    PANDOC_VER=${PANDOC_VER_LINE#pandoc }
+    PV_MAJOR_MINOR=${PANDOC_VER%.[0-9]*}
+    PV_MAJOR=${PV_MAJOR_MINOR%%[.][0-9]*}
+    PV_MINOR=${PV_MAJOR_MINOR#[0-9]*[.]}
+    PV_MINOR=${PV_MINOR%%[.][0-9]*}
+    if [ "$PV_MAJOR" -lt "1" ] || [ "$PV_MINOR" -lt "8" ]
+    then
+               step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. disabling"
+               BAD_PANDOC=1
+    fi
 fi
 
-# Valgrind is only reliable on Linux. On Windows it doesn't work at all, and
-# on the Mac the dynamic linker causes Valgrind to emit a huge stream of
-# errors.
-if [ $CFG_OSTYPE != unknown-linux-gnu ] && [ $CFG_OSTYPE != apple-darwin ]
+if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ]
 then
-    CFG_BAD_VALGRIND=1
-    putvar CFG_BAD_VALGRIND
+    if [ ! -z "$CFG_ENABLE_PAX_FLAGS" -a -z "$CFG_PAXCTL" ]
+    then
+        err "enabled PaX markings but no paxctl binary found"
+    fi
+
+    if [ -z "$CFG_DISABLE_PAX_FLAGS" ]
+    then
+        # GRSecurity/PaX detection. This can be very flaky.
+        GRSEC_DETECTED=
+
+        # /dev/grsec only exists if CONFIG_GRKERNSEC_NO_RBAC is not set.
+        # /proc/sys/kernel/grsecurity is not available if Ã‡ONFIG_GRKERNSEC_SYSCTL is not set.
+        if [ -e /dev/grsec -o -d /proc/sys/kernel/grsecurity ]
+        then
+            GRSEC_DETECTED=1
+        # /proc/config.gz is normally only available to root, and only if CONFIG_IKCONFIG_PROC has been set.
+        elif [ -r /proc/config.gz -a ! -z "$CFG_ZCAT" ]
+        then
+            if "$CFG_ZCAT" /proc/config.gz | grep --quiet "CONFIG_GRKERNSEC=y"
+            then
+                GRSEC_DETECTED=1
+            fi
+        # Flaky.
+        elif grep --quiet grsec /proc/version
+        then
+            GRSEC_DETECTED=1
+        fi
+
+        if [ ! -z "$GRSEC_DETECTED" ]
+        then
+            step_msg "GRSecurity: yes"
+            if [ ! -z "$CFG_PAXCTL" ]
+            then
+                CFG_ENABLE_PAX_FLAGS=1
+            else
+                warn "GRSecurity kernel detected but no paxctl binary found: not setting CFG_ENABLE_PAX_FLAGS"
+            fi
+        else
+            step_msg "GRSecurity: no"
+        fi
+    fi
 fi
 
-if [ ! -z "$CFG_LLVM_ROOT" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ]
+if [ ! -z "$CFG_ENABLE_LOCAL_RUST" ]
 then
-    CFG_LLVM_CONFIG="$CFG_LLVM_ROOT/bin/llvm-config"
+    if [ ! -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc ]
+    then
+        err "no local rust to use"
+    else
+        LRV=`${CFG_LOCAL_RUST_ROOT}/bin/rustc --version`
+        step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: " $LRV
+    fi
 fi
 
-if [ ! -z "$CFG_LLVM_ROOT" -a -z "$CFG_LLVM_CONFIG" ]
+# Force freebsd to build with clang; gcc doesn't like us there
+if [ $CFG_OSTYPE = unknown-freebsd ]
 then
-    CFG_LLVM_INCDIR="$CFG_LLVM_ROOT/include"
-    CFG_LLVM_BINDIR="$CFG_LLVM_ROOT/bin"
-    CFG_LLVM_LIBDIR="$CFG_LLVM_ROOT/lib"
-    CFG_LLVM_CXXFLAGS="-I$CFG_LLVM_INCDIR"
-    CFG_LLVM_LDFLAGS=""
-    CFG_LLVM_LIBS=$(find "$CFG_LLVM_LIBDIR" \
-                    -name '*.lib' \
-                    -exec echo '\"{}\"' ';' \
-                    | xargs echo)
-    CFG_LLVM_VERSION=$("$CFG_LLVM_BINDIR/llc" \
-                       --version \
-                       | grep version \
-                       | cut -d ' ' -f 5-)
-    CFG_LLVM_TRIPLE=$("$CFG_LLVM_BINDIR/llc" \
-                      --version \
-                      | grep Host: \
-                      | cut -d ' ' -f 4-)
-elif [ ! -z "$CFG_LLVM_CONFIG" ]
+    step_msg "on FreeBSD, forcing use of clang"
+    CFG_ENABLE_CLANG=1
+    putvar CFG_ENABLE_CLANG
+fi
+
+
+if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
 then
-    CFG_LLVM_VERSION=$($CFG_LLVM_CONFIG --version)
-    CFG_LLVM_INCDIR=$($CFG_LLVM_CONFIG --includedir)
-    CFG_LLVM_BINDIR=$($CFG_LLVM_CONFIG --bindir)
-    CFG_LLVM_LIBDIR=$($CFG_LLVM_CONFIG --libdir)
-    CFG_LLVM_CXXFLAGS=$($CFG_LLVM_CONFIG --cxxflags)
-    CFG_LLVM_LDFLAGS=$($CFG_LLVM_CONFIG --ldflags)
-    CFG_LLVM_LIBS=$($CFG_LLVM_CONFIG --libs)
-    CFG_LLVM_TRIPLE=$($CFG_LLVM_CONFIG --host-target)
-else
-    err "no llvm-config found and no --llvm-root specified"
+    err "either clang or gcc is required"
 fi
 
-case $CFG_LLVM_VERSION in
-    (3.0svn | 3.0 | 3.1svn)
-    step_msg "found ok version of LLVM: $CFG_LLVM_VERSION"
-    ;;
-    (*)
-    err "bad LLVM version: $CFG_LLVM_VERSION, need >=3.0svn"
-    ;;
-esac
+if [ ! -z "$CFG_LLVM_ROOT" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ]
+then
+    step_msg "using custom LLVM at $CFG_LLVM_ROOT"
+
+    LLVM_CONFIG="$CFG_LLVM_ROOT/bin/llvm-config"
+    LLVM_VERSION=$($LLVM_CONFIG --version)
+
+    case $LLVM_VERSION in
+       (3.1svn|3.1|3.0svn|3.0)
+           msg "found ok version of LLVM: $LLVM_VERSION"
+           ;;
+       (*)
+           err "bad LLVM version: $LLVM_VERSION, need >=3.0svn"
+           ;;
+    esac
+fi
 
-if [ ! -z "$CFG_CLANG" -a -z "$CFG_ONLY_GCC" ]
+if [ ! -z "$CFG_ENABLE_CLANG" ]
 then
+    if [ -z "$CFG_CLANG" ]
+    then
+       err "clang requested but not found"
+    fi
     CFG_CLANG_VERSION=$("$CFG_CLANG" \
                       --version \
                       | grep version \
-                      | cut -d ' ' -f 3)
+                      | sed 's/.*\(version .*\)/\1/' \
+                      | cut -d ' ' -f 2)
 
     case $CFG_CLANG_VERSION in
-        (3.0svn | 3.0)
+        (3.0svn | 3.0 | 3.1* | 3.2* | 4.0* | 4.1* | 4.2*)
         step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
         CFG_C_COMPILER="clang"
         ;;
         (*)
-        msg "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn; disabling"
-        CFG_C_COMPILER="gcc"
+        err "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn"
         ;;
     esac
 else
     CFG_C_COMPILER="gcc"
 fi
 
-if [ -z "$CFG_PREFIX" ]
+# a little post-processing of various config values
+
+CFG_PREFIX=${CFG_PREFIX%/}
+CFG_TARGET_TRIPLES="$(echo $CFG_TARGET_TRIPLES | tr ',' ' ')"
+case $CFG_TARGET_TRIPLES in
+    (*$CFG_HOST_TRIPLE*) ;;
+    (*) err "Host triple is not among the target triples." ;;
+esac
+
+if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
 then
-    CFG_PREFIX=/usr/local
+    err "either clang or gcc is required"
 fi
 
-if [ ! -z "$CFG_LLVM_TRIPLE" ]
+if [ ! -z "$CFG_PERF" ]
 then
-    if [ $CFG_HOST_TRIPLE != $CFG_LLVM_TRIPLE ]
+    HAVE_PERF_LOGFD=`$CFG_PERF stat --log-fd 2>&1 | grep 'unknown option'`
+    if [ -z "$HAVE_PERF_LOGFD" ];
     then
-        warn "LLVM host-triple $CFG_LLVM_TRIPLE differs from"
-        warn "detected host triple $CFG_HOST_TRIPLE"
-        warn "choosing LLVM host-triple instead"
-        msg ""
-        CFG_HOST_TRIPLE=$CFG_LLVM_TRIPLE
+        CFG_PERF_WITH_LOGFD=1
+        putvar CFG_PERF_WITH_LOGFD
     fi
 fi
 
-if [ -z "$CFG_TARGET_TRIPLES" ]
-then
-    CFG_TARGET_TRIPLES="${CFG_HOST_TRIPLE}"
-fi
-
-putvar CFG_HOST_TRIPLE
-putvar CFG_TARGET_TRIPLES
-
-putvar CFG_C_COMPILER
-putvar CFG_PREFIX
-
-putvar CFG_LLVM_ROOT
-putvar CFG_LLVM_CONFIG
-putvar CFG_LLVM_INCDIR
-putvar CFG_LLVM_BINDIR
-putvar CFG_LLVM_LIBDIR
-putvar CFG_LLVM_CXXFLAGS
-putvar CFG_LLVM_LDFLAGS
-putvar CFG_LLVM_LIBS
-putvar CFG_LLVM_TRIPLE
-
-# Munge any paths that appear in config.mk back to posix-y
-perl -i.bak -p -e 's@ ([a-zA-Z]):[/\\]@ /\1/@go;' \
-               -e 's@\\@/@go;' config.mk
-rm -f config.mk.bak
-
 step_msg "making directories"
+
 for i in \
-    doc doc/std \
-    nd nd/std \
-    dl \
-    test/run-pass test/run-fail test/compile-fail \
-    test/bench test/perf test/pretty
+    doc doc/core doc/std \
+    dl tmp
 do
     make_dir $i
 done
 
+make_dir llvm
+for t in $CFG_TARGET_TRIPLES
+do
+    make_dir llvm/$t
+done
+
 make_dir rustllvm
 for t in $CFG_TARGET_TRIPLES
 do
@@ -437,31 +577,298 @@ for t in $CFG_TARGET_TRIPLES
 do
   make_dir rt/$t
   for i in                                          \
-    isaac bigint sync test arch/i386 arch/x86_64    \
+    isaac linenoise sync test arch/i386 arch/x86_64    \
     libuv libuv/src/ares libuv/src/eio libuv/src/ev
   do
     make_dir rt/$t/$i
   done
 done
 
-for t in $CFG_TARGET_TRIPLES
+# On windows we just store the libraries in the bin directory because
+# there's no rpath
+CFG_LIBDIR=lib
+if [ "$CFG_OSTYPE" = "pc-mingw32" ]
+then
+    CFG_LIBDIR=bin
+fi
+
+for h in $CFG_TARGET_TRIPLES
 do
-    for i in 0 1 2 3
+    for t in $CFG_TARGET_TRIPLES
     do
-        # host bin dir
-        make_dir stage$i/bin
+        for i in 0 1 2 3
+        do
+            # host bin dir
+            make_dir $h/stage$i/bin
 
-        # host lib dir
-        make_dir stage$i/lib
+            # host lib dir
+            make_dir $h/stage$i/$CFG_LIBDIR
 
-        # target bin dir
-        make_dir stage$i/lib/rustc/$t/bin
+            # target bin dir
+            make_dir $h/stage$i/$CFG_LIBDIR/rustc/$t/bin
 
-        # target lib dir
-        make_dir stage$i/lib/rustc/$t/lib
+            # target lib dir
+            make_dir $h/stage$i/$CFG_LIBDIR/rustc/$t/$CFG_LIBDIR
+        done
     done
+
+    make_dir $h/test/run-pass
+    make_dir $h/test/run-pass-fulldeps
+    make_dir $h/test/run-fail
+    make_dir $h/test/compile-fail
+    make_dir $h/test/bench
+    make_dir $h/test/perf
+    make_dir $h/test/pretty
+    make_dir $h/test/doc-tutorial
+    make_dir $h/test/doc-tutorial-ffi
+    make_dir $h/test/doc-tutorial-macros
+    make_dir $h/test/doc-tutorial-borrowed-ptr
+    make_dir $h/test/doc-tutorial-tasks
+    make_dir $h/test/doc-ref
+done
+
+# Configure submodules
+step_msg "configuring submodules"
+
+# Have to be in the top of src directory for this
+if [ -z $CFG_DISABLE_MANAGE_SUBMODULES ]
+then
+    cd ${CFG_SRC_DIR}
+
+    msg "git: submodule sync"
+    "${CFG_GIT}" submodule --quiet sync
+
+    msg "git: submodule update"
+    "${CFG_GIT}" submodule --quiet update --init
+    need_ok "git failed"
+
+    msg "git: submodule foreach sync"
+    "${CFG_GIT}" submodule --quiet foreach --recursive 'if test -e .gitmodules; then git submodule sync; fi'
+    need_ok "git failed"
+
+    msg "git: submodule foreach update"
+    "${CFG_GIT}" submodule --quiet update --init --recursive
+    need_ok "git failed"
+
+    # NB: this is just for the sake of getting the submodule SHA1 values
+    # and status written into the build log.
+    msg "git: submodule status"
+    "${CFG_GIT}" submodule status --recursive
+
+    msg "git: submodule clobber"
+    "${CFG_GIT}" submodule --quiet foreach --recursive git clean -dxf
+    need_ok "git failed"
+    "${CFG_GIT}" submodule --quiet foreach --recursive git checkout .
+    need_ok "git failed"
+
+    cd ${CFG_BUILD_DIR}
+fi
+
+# Configure llvm, only if necessary
+step_msg "looking at LLVM"
+CFG_LLVM_SRC_DIR=${CFG_SRC_DIR}src/llvm/
+for t in $CFG_TARGET_TRIPLES
+do
+    do_reconfigure=1
+
+    if [ -z $CFG_LLVM_ROOT ]
+    then
+        LLVM_BUILD_DIR=${CFG_BUILD_DIR}llvm/$t
+        if [ ! -z "$CFG_DISABLE_OPTIMIZE_LLVM" ]
+        then
+            LLVM_DBG_OPTS=""
+            # Just use LLVM straight from its build directory to
+            # avoid 'make install' time
+            LLVM_INST_DIR=$LLVM_BUILD_DIR/Debug+Asserts
+        else
+            LLVM_DBG_OPTS="--enable-optimized"
+            LLVM_INST_DIR=$LLVM_BUILD_DIR/Release+Asserts
+        fi
+    else
+        msg "not reconfiguring LLVM, external LLVM root"
+        # The user is using their own LLVM
+        LLVM_BUILD_DIR=
+        LLVM_INST_DIR=$CFG_LLVM_ROOT
+        do_reconfigure=0
+    fi
+
+
+    if [ ${do_reconfigure} -ne 0 ]
+    then
+    # because git is hilarious, it might have put the module index
+    # in a couple places.
+        index1="${CFG_SRC_DIR}.git/modules/src/llvm/index"
+        index2="${CFG_SRC_DIR}src/llvm/.git/index"
+        for index in ${index1} ${index2}
+        do
+            config_status="${CFG_BUILD_DIR}llvm/$t/config.status"
+            if test -e ${index} -a \
+                    -e ${config_status} -a \
+                    ${config_status} -nt ${index}
+            then
+                msg "not reconfiguring LLVM, config.status is fresh"
+                do_reconfigure=0
+            fi
+        done
+    fi
+
+    if [ ${do_reconfigure} -ne 0 ]
+    then
+        msg "configuring LLVM for $t"
+
+        LLVM_TARGETS="--enable-targets=x86,x86_64,arm"
+        LLVM_BUILD="--build=$t"
+        LLVM_HOST="--host=$t"
+        LLVM_TARGET="--target=$t"
+
+        # Disable unused LLVM features
+        LLVM_OPTS="$LLVM_DBG_OPTS --disable-docs \
+                   --enable-bindings=none --disable-threads \
+                   --disable-pthreads"
+
+        if [ "$CFG_C_COMPILER" = "clang" ]
+        then
+            LLVM_CXX_32="clang++ -m32"
+            LLVM_CC_32="clang -m32"
+
+            LLVM_CXX_64="clang++"
+            LLVM_CC_64="clang"
+        else
+            LLVM_CXX_32="g++ -m32"
+            LLVM_CC_32="gcc -m32"
+
+            LLVM_CXX_64="g++"
+            LLVM_CC_64="gcc"
+        fi
+
+        LLVM_CFLAGS_32="-m32"
+        LLVM_CXXFLAGS_32="-m32"
+        LLVM_LDFLAGS_32="-m32"
+
+        LLVM_CFLAGS_64=""
+        LLVM_CXXFLAGS_64=""
+        LLVM_LDFLAGS_64=""
+
+        if echo $t | grep -q x86_64
+        then
+            LLVM_CXX=$LLVM_CXX_64
+            LLVM_CC=$LLVM_CC_64
+            LLVM_CFLAGS=$LLVM_CFLAGS_64
+            LLVM_CXXFLAGS=$LLVM_CXXFLAGS_64
+            LLVM_LDFLAGS=$LLVM_LDFLAGS_64
+        else
+            LLVM_CXX=$LLVM_CXX_32
+            LLVM_CC=$LLVM_CC_32
+            LLVM_CFLAGS=$LLVM_CFLAGS_32
+            LLVM_CXXFLAGS=$LLVM_CXXFLAGS_32
+            LLVM_LDFLAGS=$LLVM_LDFLAGS_32
+        fi
+
+        CXX=$LLVM_CXX
+        CC=$LLVM_CC
+        CFLAGS=$LLVM_CFLAGS
+        CXXFLAGS=$LLVM_CXXFLAGS
+        LDFLAGS=$LLVM_LDFLAGS
+
+        LLVM_FLAGS="$LLVM_TARGETS $LLVM_OPTS $LLVM_BUILD \
+                        $LLVM_HOST $LLVM_TARGET"
+
+        msg "configuring LLVM with:"
+        msg "$LLVM_FLAGS"
+
+        export CXX
+        export CC
+        export CFLAGS
+        export CXXFLAGS
+        export LDFLAGS
+
+        cd $LLVM_BUILD_DIR
+        case $CFG_SRC_DIR in
+            /* | [a-z]:* | [A-Z]:*)
+                ${CFG_LLVM_SRC_DIR}configure $LLVM_FLAGS
+                ;;
+            *)
+                ${CFG_BUILD_DIR}${CFG_LLVM_SRC_DIR}configure \
+                    $LLVM_FLAGS
+                ;;
+        esac
+        need_ok "LLVM configure failed"
+        cd $CFG_BUILD_DIR
+    fi
+
+    # Construct variables for LLVM build and install directories for
+    # each target. These will be named
+    # CFG_LLVM_BUILD_DIR_${target_triple} but all the hyphens in
+    # target_triple will be converted to underscore, because bash
+    # variables can't contain hyphens. The makefile will then have to
+    # convert back.
+    CFG_LLVM_BUILD_DIR=$(echo CFG_LLVM_BUILD_DIR_${t} | tr - _)
+    CFG_LLVM_INST_DIR=$(echo CFG_LLVM_INST_DIR_${t} | tr - _)
+    eval ${CFG_LLVM_BUILD_DIR}="'$LLVM_BUILD_DIR'"
+    eval ${CFG_LLVM_INST_DIR}="'$LLVM_INST_DIR'"
+done
+
+
+step_msg "writing configuration"
+
+putvar CFG_SRC_DIR
+putvar CFG_BUILD_DIR
+putvar CFG_OSTYPE
+putvar CFG_CPUTYPE
+putvar CFG_CONFIGURE_ARGS
+putvar CFG_PREFIX
+putvar CFG_TARGET_TRIPLES
+putvar CFG_C_COMPILER
+putvar CFG_LIBDIR
+putvar CFG_DISABLE_MANAGE_SUBMODULES
+
+if [ ! -z "$CFG_ENABLE_PAX_FLAGS" ]
+then
+    putvar CFG_ENABLE_PAX_FLAGS
+    putvar CFG_PAXCTL
+fi
+
+if [ ! -z $BAD_PANDOC ]
+then
+    CFG_PANDOC=
+    putvar CFG_PANDOC
+fi
+
+if head -n 1 ${CFG_SRC_DIR}src/snapshots.txt | grep -q '^T'
+then
+    CFG_IN_TRANSITION=1
+    putvar CFG_IN_TRANSITION
+fi
+
+# Valgrind is only reliable on Linux. On Windows it doesn't work at all, and
+# on the Mac the dynamic linker causes Valgrind to emit a huge stream of
+# errors.
+if [ $CFG_OSTYPE != unknown-linux-gnu ] && [ $CFG_OSTYPE != apple-darwin ]
+then
+    CFG_BAD_VALGRIND=1
+    putvar CFG_BAD_VALGRIND
+fi
+
+putvar CFG_LLVM_ROOT
+putvar CFG_LLVM_SRC_DIR
+
+for t in $CFG_TARGET_TRIPLES
+do
+    CFG_LLVM_BUILD_DIR=$(echo CFG_LLVM_BUILD_DIR_${t} | tr - _)
+    CFG_LLVM_INST_DIR=$(echo CFG_LLVM_INST_DIR_${t} | tr - _)
+    putvar $CFG_LLVM_BUILD_DIR
+    putvar $CFG_LLVM_INST_DIR
 done
 
-copy ${CFG_SRC_DIR}Makefile.in ./Makefile
+# Munge any paths that appear in config.mk back to posix-y
+perl -i.bak -p -e 's@ ([a-zA-Z]):[/\\]@ /\1/@go;' \
+               -e 's@\\@/@go;' config.tmp
+rm -f config.tmp.bak
+
+msg
+copy_if_changed ${CFG_SRC_DIR}Makefile.in ./Makefile
+move_if_changed config.tmp config.mk
+rm -f config.tmp
+touch config.stamp
 
 step_msg "complete"