summary refs log tree commit diff
path: root/pkgs/stdenv/generic
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2004-03-19 16:53:04 +0000
committerEelco Dolstra <eelco.dolstra@logicblox.com>2004-03-19 16:53:04 +0000
commit5941f66f0e76cadbda30b3240ba00b30ea365ac7 (patch)
tree35ecc8fde93aa1dd9b5705fe5302cae77ead3860 /pkgs/stdenv/generic
parent0fd59fd7a41a47478f241b4a27c39d39f42914b9 (diff)
downloadnixlib-5941f66f0e76cadbda30b3240ba00b30ea365ac7.tar
nixlib-5941f66f0e76cadbda30b3240ba00b30ea365ac7.tar.gz
nixlib-5941f66f0e76cadbda30b3240ba00b30ea365ac7.tar.bz2
nixlib-5941f66f0e76cadbda30b3240ba00b30ea365ac7.tar.lz
nixlib-5941f66f0e76cadbda30b3240ba00b30ea365ac7.tar.xz
nixlib-5941f66f0e76cadbda30b3240ba00b30ea365ac7.tar.zst
nixlib-5941f66f0e76cadbda30b3240ba00b30ea365ac7.zip
* The stdenv setup script now defines a generic builder that allows
  builders for typical Autoconf-style to be much shorten, e.g.,

    . $stdenv/setup
    genericBuild

  The generic builder does lots of stuff automatically:

  - Unpacks source archives specified by $src or $srcs (it knows about
    gzip, bzip2, tar, zip, and unpacked source trees).
  - Determines the source tree.
  - Applies patches specified by $patches.
  - Fixes libtool not to search for libraries in /lib etc.
  - Runs `configure'.
  - Runs `make'.
  - Runs `make install'.
  - Strips debug information from static libraries.
  - Writes nested log information (in the format accepted by
    `log2xml').

  There are also lots of hooks and variables to customise the generic
  builder.  See `stdenv/generic/docs.txt'.

* Adapted the base packages (i.e., the ones used by stdenv) to use the
  generic builder.

* We now use `curl' instead of `wget' to download files in `fetchurl'.

* Neither `curl' nor `wget' are part of stdenv.  We shouldn't
  encourage people to download stuff in builders (impure!).

* Updated some packages.

* `buildinputs' is now `buildInputs' (but the old name also works).

* `findInputs' in the setup script now prevents inputs from being
  processed multiple times (which could happen, e.g., if an input was
  a propagated input of several other inputs; this caused the size
  variables like $PATH to blow up exponentially in the worst case).

* Patched GNU Make to write nested log information in the format
  accepted by `log2xml'.  Also, prior to writing the build command,
  Make now writes a line `building X' to indicate what is being
  built.  This is unfortunately often obscured by the gigantic tool
  invocations in many Makefiles.  The actual build commands are marked
  `unimportant' so that they don't clutter pages generated by
  `log2html'.


svn path=/nixpkgs/trunk/; revision=845
Diffstat (limited to 'pkgs/stdenv/generic')
-rw-r--r--pkgs/stdenv/generic/docs.txt93
-rw-r--r--pkgs/stdenv/generic/setup.sh302
2 files changed, 390 insertions, 5 deletions
diff --git a/pkgs/stdenv/generic/docs.txt b/pkgs/stdenv/generic/docs.txt
new file mode 100644
index 000000000000..060f3cd154b9
--- /dev/null
+++ b/pkgs/stdenv/generic/docs.txt
@@ -0,0 +1,93 @@
+* genericBuild performs a generic build of (typically) autotool-style
+  packages
+
+  
+* unpack phase
+
+** may be overriden by setting $unpackPhase to point at a function that
+   unpacks the source (which should set $sourceRoot)
+
+** the generic unpacker unpacks all sources specified by $srcs, or
+   $src if $srcs is empty
+
+** supports tar, bzipped tar, gzipped tar, compressed tar, zip
+
+** zip must be in scope (in $buildinputs)
+
+** additional file types may be supported by setting $findUnpacker,
+   which is called with a single argument specifying the file to be
+   unpacked
+
+** $findUnpacker should set $unpackCmd, specifying the full command to
+   unpack the file (must include the file name)
+
+** alternatively, $unpackCmd can be set before calling the generic
+   builder (e.g., 'unpackCmd="unrar x $src"'); this only works if
+   there is a single source file
+
+** the generic unpacker then sets $sourceRoot to the name of the
+   directory created by unpacking the source archives
+
+** the source archives should produce only one directory
+
+** alternatively, $setSourceRoot may be set to a function that sets
+   $sourceRoot
+
+
+* the generic builder then chdirs to $sourceRoot
+
+
+* patch phase (skipped if neither $patchPhase nor $patches are set)
+
+** may be overriden by setting $patchPhase to point at a function that
+   unpacks the source (which should set $sourceRoot)
+
+** if the $patches variable is set, it runs `patch -p1 < ...' in
+   $sourceRoot for each element in $patches (the `patch' command
+   should be in $PATH; note that it isn't in the standard environment)
+
+
+* configuration phase
+
+** may be overriden by setting $configurePhase to point at a function
+
+** calls $preConfigurer first, if set (useful for running
+   autoconf/automake)
+
+** the configure script is specified by $configureScript, which
+   defaults to ./configure
+   
+** if no executable file exists at $configureScript, does nothing
+
+** if a file ./ltmain.sh exists and $dontFixLibtool is not set, calls
+   function fixLibtool to remove its default search path (/usr etc.)
+
+** adds "--prefix=$out" to $configureFlags unless $dontAddPrefix is
+   set
+
+** calls $configureScript with $configureFlags
+
+** calls $postConfigurer, if set (useful for any last-minute patches
+   prior to building)
+
+
+* build phase
+
+** may be overriden by setting $buildPhase to point at a function
+
+** runs make with flags $makeFlags
+
+
+* install phase
+
+** may be overriden by setting $installPhase to point at a function
+
+** runs make with flags $installFlags
+
+** unless $dontStrip is set or $NIX_STRIP_DEBUG is not 1, finds all *.a
+   files in $out and runs "strip -S" on them (executables and dynamic
+   libraries can be stripped automatically by setting NIX_STRIP_DEBUG
+   to 1 (default))
+
+** if $propagatedBuildInputs is set, its contents are written to
+   $out/nix-support/propagated-build-inputs
diff --git a/pkgs/stdenv/generic/setup.sh b/pkgs/stdenv/generic/setup.sh
index 2dedf46ac2b3..f64260f490ae 100644
--- a/pkgs/stdenv/generic/setup.sh
+++ b/pkgs/stdenv/generic/setup.sh
@@ -40,7 +40,14 @@ fi
 findInputs()
 {
     local pkg=$1
-    pkgs=(${pkgs[@]} $pkg)
+
+    case $pkgs in
+        *\ $pkg\ *)
+            return 0
+            ;;
+    esac
+    
+    pkgs="$pkgs $pkg "
 
     if test -f $pkg/nix-support/setup-hook; then
         . $pkg/nix-support/setup-hook
@@ -53,8 +60,11 @@ findInputs()
     fi
 }
 
-pkgs=()
-for i in $buildinputs; do
+pkgs=""
+if test -n "$buildinputs"; then
+    buildInputs="$buildinputs" # compatibility
+fi
+for i in $buildInputs; do
     findInputs $i
 done
 
@@ -66,7 +76,7 @@ addToEnv()
     local pkg=$1
 
     if test -d $1/bin; then
-        export _PATH=$_PATH:$1/bin
+        export _PATH=$_PATH${_PATH:+:}$1/bin
     fi
 
     for i in "${envHooks[@]}"; do
@@ -74,7 +84,7 @@ addToEnv()
     done
 }
 
-for i in "${pkgs[@]}"; do
+for i in $pkgs; do
     addToEnv $i
 done
 
@@ -121,3 +131,285 @@ PATH=$_PATH${_PATH:+:}$PATH
 if test "$NIX_DEBUG" = "1"; then
     echo "Final path: $PATH"
 fi
+
+
+######################################################################
+# What follows is the generic builder.
+
+
+nestingLevel=0
+
+startNest() {
+    nestingLevel=$(($nestingLevel + 1))
+    echo -en "\e[$1p"
+}
+
+stopNest() {
+    nestingLevel=$(($nestingLevel - 1))
+    echo -en "\e[q"
+}
+
+header() {
+    startNest "$2"
+    echo "$1"
+}
+
+# Make sure that even when we exit abnormally, the original nesting
+# level is properly restored.
+closeNest() {
+    while test $nestingLevel -gt 0; do
+        stopNest
+    done
+}
+
+trap "closeNest" EXIT
+
+
+# Utility function: return the base name of the given path, with the
+# prefix `HASH-' removed, if present.
+stripHash() {
+    strippedName=$(basename $1);
+    if echo "$strippedName" | grep -q '^[a-f0-9]\{32\}-'; then
+        strippedName=$(echo "$strippedName" | cut -c34-)
+    fi
+}
+
+
+unpackFile() {
+    local file=$1
+    local cmd
+
+    case $file in
+        *.tar) cmd="tar xvf $file";;
+        *.tar.gz | *.tgz | *.tar.Z) cmd="tar xvfz $file";;
+        *.tar.bz2 | *.tbz2) cmd="tar xvfj $file";;
+        *.zip) cmd="unzip $file";;
+        *)
+            if test -d "$file"; then
+                stripHash $file
+                cmd="cp -prvd $file $strippedName"
+            else
+                if test -n "$findUnpacker"; then
+                    $findUnpacker $1;
+                fi
+                if test -z "$unpackCmd"; then
+                    echo "source archive $file has unknown type"
+                    exit 1
+                fi
+                cmd=$unpackCmd
+            fi
+            ;;
+    esac
+
+    header "unpacking source archive $file (using $cmd)" 3
+    $cmd
+    stopNest
+}
+
+
+unpackW() {
+    if test -n "$unpackPhase"; then
+        $unpackPhase
+        return
+    fi
+
+    if test -z "$srcs"; then
+        if test -z "$src"; then
+            echo 'variable $src or $srcs should point to the source'
+            exit 1
+        fi
+        srcs="$src"
+    fi
+
+    # To determine the source directory created by unpacking the
+    # source archives, we record the contents of the current
+    # directory, then look below which directory got added.  Yeah,
+    # it's rather hacky.
+    local dirsBefore=""
+    for i in *; do
+        if test -d "$i"; then
+            dirsBefore="$dirsBefore $i "
+        fi
+    done
+
+    # Unpack all source archives.
+    for i in $srcs; do
+        unpackFile $i
+    done
+
+    # Find the source directory.
+    if test -n "$setSourceRoot"; then
+        $setSourceRoot
+    else
+        sourceRoot=
+        for i in *; do
+            if test -d "$i"; then
+                case $dirsBefore in
+                    *\ $i\ *)
+                        ;;
+                    *)
+                        if test -n "$sourceRoot"; then
+                            echo "unpacker produced multiple directories"
+                            exit 1
+                        fi
+                        sourceRoot=$i
+                        ;;
+                esac
+            fi
+        done
+    fi
+
+    if test -z "$sourceRoot"; then
+        echo "unpacker appears to have produced no directories"
+        exit 1
+    fi
+
+    echo "source root is $sourceRoot"
+
+    if test -n "$postUnpack"; then
+        $postUnpack
+    fi
+}
+
+
+unpackPhase() {
+    header "unpacking sources"
+    unpackW
+    stopNest
+}
+
+
+patchW() {
+    if test -n "$patchPhase"; then
+        $patchPhase
+        return
+    fi
+
+    for i in $patches; do
+        header "applying patch $i" 3
+        patch -p1 < $i
+        stopNest
+    done
+}
+
+
+patchPhase() {
+    if test -z "$patchPhase" -a -z "$patches"; then return; fi
+    header "patching sources"
+    patchW
+    stopNest
+}
+
+
+fixLibtool () {
+    sed 's^eval sys_lib_.*search_path=.*^^' < $1 > $1.tmp
+    mv $1.tmp $1
+}
+
+
+configureW() {
+    if test -n "$configurePhase"; then
+        $configurePhase
+        stopNest
+        return
+    fi
+
+    if test -n "$preConfigure"; then
+        $preConfigure
+    fi
+
+    if test -z "$configureScript"; then
+        configureScript=./configure
+    fi
+    
+    if ! test -x $configureScript; then
+        echo "no configure script, doing nothing"
+        return
+    fi
+
+    if test -z "$dontFixLibtool" -a -f ./ltmain.sh; then
+        fixLibtool ./ltmain.sh
+    fi
+
+    if test -z "$dontAddPrefix"; then
+        configureFlags="--prefix=$out $configureFlags"
+    fi
+
+    echo "configure flags: $configureFlags"
+    $configureScript $configureFlags
+
+    if test -n "$postConfigure"; then
+        $postConfigure
+    fi
+}
+
+
+configurePhase() {
+    header "configuring"
+    configureW
+    stopNest
+}
+
+
+buildW() {
+    if test -n "$buildPhase"; then
+        $buildPhase
+        return
+    fi
+
+    echo "make flags: $makeFlags"
+    make $makeFlags
+}
+
+
+buildPhase() {
+    header "building"
+    buildW
+    stopNest
+}
+
+
+installW() {
+    if test -n "$installPhase"; then
+        $installPhase
+        return
+    fi
+    
+    if test -n "$preInstall"; then
+        $preInstall
+    fi
+    
+    make install $installFlags
+
+    if test -z "$dontStrip" -a "$NIX_STRIP_DEBUG" = 1; then
+        find $out -name "*.a" -exec echo stripping {} \; -exec strip -S {} \;
+    fi
+
+    if test -n "$propagatedBuildInputs"; then
+        mkdir -f $out/nix-support
+        echo "$propagatedBuildInputs" > $out/nix-support/propagated-build-inputs
+    fi
+
+    if test -n "$postInstall"; then
+        $postInstall
+    fi
+}
+
+
+installPhase() {
+    header "installing"
+    installW
+    stopNest
+}
+
+
+genericBuild () {
+    header "building $out"
+    unpackPhase
+    cd $sourceRoot
+    patchPhase
+    configurePhase
+    buildPhase
+    installPhase
+    stopNest
+}