summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorArmijn Hemel <armijn@gpl-violations.org>2005-11-29 01:40:33 +0000
committerArmijn Hemel <armijn@gpl-violations.org>2005-11-29 01:40:33 +0000
commit508cd3a3e8e079288d2b51e29f63294888067e2b (patch)
tree7c023099c0b0293666156ca7181aee60734e62b9 /pkgs
parent0cf7a938271ffa927ac9520f098e647f20fa7a7c (diff)
downloadnixlib-508cd3a3e8e079288d2b51e29f63294888067e2b.tar
nixlib-508cd3a3e8e079288d2b51e29f63294888067e2b.tar.gz
nixlib-508cd3a3e8e079288d2b51e29f63294888067e2b.tar.bz2
nixlib-508cd3a3e8e079288d2b51e29f63294888067e2b.tar.lz
nixlib-508cd3a3e8e079288d2b51e29f63294888067e2b.tar.xz
nixlib-508cd3a3e8e079288d2b51e29f63294888067e2b.tar.zst
nixlib-508cd3a3e8e079288d2b51e29f63294888067e2b.zip
add a wrapper for cross compilers, which makes the correct link to the cross compiler. Only works for "gcc", haven't tried for g++ and the others
svn path=/nixpkgs/trunk/; revision=4317
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/build-support/gcc-cross-wrapper/add-flags5
-rw-r--r--pkgs/build-support/gcc-cross-wrapper/builder.sh94
-rw-r--r--pkgs/build-support/gcc-cross-wrapper/default.nix30
-rw-r--r--pkgs/build-support/gcc-cross-wrapper/gcc-wrapper.sh125
-rw-r--r--pkgs/build-support/gcc-cross-wrapper/ld-wrapper.sh145
-rw-r--r--pkgs/build-support/gcc-cross-wrapper/setup-hook.sh25
-rw-r--r--pkgs/build-support/gcc-cross-wrapper/utils.sh23
7 files changed, 447 insertions, 0 deletions
diff --git a/pkgs/build-support/gcc-cross-wrapper/add-flags b/pkgs/build-support/gcc-cross-wrapper/add-flags
new file mode 100644
index 000000000000..ac1e58ebb812
--- /dev/null
+++ b/pkgs/build-support/gcc-cross-wrapper/add-flags
@@ -0,0 +1,5 @@
+export NIX_CFLAGS_COMPILE="@cflagsCompile@ $NIX_CFLAGS_COMPILE"
+export NIX_CFLAGS_LINK="@cflagsLink@ $NIX_CFLAGS_LINK"
+export NIX_LDFLAGS="@ldflags@ $NIX_LDFLAGS"
+export NIX_LDFLAGS_BEFORE="@ldflagsBefore@ $NIX_LDFLAGS_BEFORE"
+export NIX_GLIBC_FLAGS_SET=1
diff --git a/pkgs/build-support/gcc-cross-wrapper/builder.sh b/pkgs/build-support/gcc-cross-wrapper/builder.sh
new file mode 100644
index 000000000000..48a29694f672
--- /dev/null
+++ b/pkgs/build-support/gcc-cross-wrapper/builder.sh
@@ -0,0 +1,94 @@
+. $stdenv/setup
+. $substitute
+
+
+# Force gcc to use ld-wrapper.sh when calling ld.
+cflagsCompile="-B$out/bin/"
+
+if test -z "$nativeGlibc"; then
+    # The "-B$glibc/lib/" flag is a quick hack to force gcc to link
+    # against the crt1.o from our own glibc, rather than the one in
+    # /usr/lib.  The real solution is of course to prevent those paths
+    # from being used by gcc in the first place.
+    # The dynamic linker is passed in `ldflagsBefore' to allow
+    # explicit overrides of the dynamic linker by callers to gcc/ld
+    # (the *last* value counts, so ours should come first).
+    cflagsCompile="$cflagsCompile -B$glibc/lib/ -isystem $glibc/include"
+    ldflags="$ldflags -L$glibc/lib"
+    ldflagsBefore="-dynamic-linker $glibc/lib/ld-linux.so.2"
+fi
+
+if test -n "$nativeTools"; then
+    gccPath="$nativePrefix/bin"
+    ldPath="$nativePrefix/bin"
+else
+    ldflags="$ldflags -L$gcc/lib"
+    gccPath="$gcc/bin"
+    ldPath="$binutils/bin"
+fi
+
+
+mkdir $out
+mkdir $out/bin
+mkdir $out/nix-support
+
+
+doSubstitute() {
+    local src=$1
+    local dst=$2
+    substitute "$src" "$dst" \
+        --subst-var "out" \
+        --subst-var "shell" \
+        --subst-var "gcc" \
+        --subst-var "gccProg" \
+        --subst-var "binutils" \
+        --subst-var "glibc" \
+        --subst-var "cflagsCompile" \
+        --subst-var "cflagsLink" \
+        --subst-var "ldflags" \
+        --subst-var "ldflagsBefore" \
+        --subst-var-by "ld" "$ldPath/ld"
+}
+
+
+# Make wrapper scripts around gcc, g++, and g77.  Also make symlinks
+# cc, c++, and f77.
+mkGccWrapper() {
+    local dst=$1
+    local src=$2
+
+    if ! test -f "$src"; then
+        echo "$src does not exist (skipping)"
+        return
+    fi
+
+    gccProg="$src"
+    doSubstitute "$gccWrapper" "$dst"
+    chmod +x "$dst"
+}
+
+mkGccWrapper $out/bin/$cross-gcc $gccPath/$cross-gcc
+#ln -s gcc $out/bin/cc
+
+mkGccWrapper $out/bin/g++ $gccPath/g++
+ln -s g++ $out/bin/c++
+
+mkGccWrapper $out/bin/g77 $gccPath/g77
+ln -s g77 $out/bin/f77
+
+
+# Make a wrapper around the linker.
+doSubstitute "$ldWrapper" "$out/bin/ld"
+chmod +x "$out/bin/ld"
+
+
+# Emit a setup hook.  Also store the path to the original GCC and
+# Glibc.
+test -n "$gcc" && echo $gcc > $out/nix-support/orig-gcc
+test -n "$glibc" && echo $glibc > $out/nix-support/orig-glibc
+
+doSubstitute "$addFlags" "$out/nix-support/add-flags"
+
+doSubstitute "$setupHook" "$out/nix-support/setup-hook"
+
+cp -p $utils $out/nix-support/utils
diff --git a/pkgs/build-support/gcc-cross-wrapper/default.nix b/pkgs/build-support/gcc-cross-wrapper/default.nix
new file mode 100644
index 000000000000..0ceab44ee27c
--- /dev/null
+++ b/pkgs/build-support/gcc-cross-wrapper/default.nix
@@ -0,0 +1,30 @@
+# The Nix `gcc' stdenv.mkDerivation is not directly usable, since it doesn't
+# know where the C library and standard header files are.  Therefore
+# the compiler produced by that package cannot be installed directly
+# in a user environment and used from the command line.  This
+# stdenv.mkDerivation provides a wrapper that sets up the right environment
+# variables so that the compiler and the linker just "work".
+
+{ name ? "", stdenv, nativeTools, nativeGlibc, nativePrefix ? ""
+, gcc ? null, glibc ? null, binutils ? null, shell ? "", cross ? ""
+}:
+
+assert nativeTools -> nativePrefix != "";
+assert !nativeTools -> gcc != null && binutils != null;
+assert !nativeGlibc -> glibc != null;
+
+stdenv.mkDerivation {
+  builder = ./builder.sh;
+  substitute = ../substitute/substitute.sh;
+  setupHook = ./setup-hook.sh;
+  gccWrapper = ./gcc-wrapper.sh;
+  ldWrapper = ./ld-wrapper.sh;
+  utils = ./utils.sh;
+  addFlags = ./add-flags;
+  inherit nativeTools nativeGlibc nativePrefix gcc glibc binutils cross;
+  name = if name == "" then gcc.name else name;
+  langC = if nativeTools then true else gcc.langC;
+  langCC = if nativeTools then true else gcc.langCC;
+  langF77 = if nativeTools then false else gcc.langF77;
+  shell = if shell == "" then stdenv.shell else shell;
+}
diff --git a/pkgs/build-support/gcc-cross-wrapper/gcc-wrapper.sh b/pkgs/build-support/gcc-cross-wrapper/gcc-wrapper.sh
new file mode 100644
index 000000000000..7de57afc3f81
--- /dev/null
+++ b/pkgs/build-support/gcc-cross-wrapper/gcc-wrapper.sh
@@ -0,0 +1,125 @@
+#! @shell@ -e
+
+if test -n "$NIX_GCC_WRAPPER_START_HOOK"; then
+    . "$NIX_GCC_WRAPPER_START_HOOK"
+fi
+
+if test -z "$NIX_GLIBC_FLAGS_SET"; then
+    . @out@/nix-support/add-flags
+fi
+
+. @out@/nix-support/utils
+
+
+# Figure out if linker flags should be passed.  GCC prints annoying
+# warnings when they are not needed.
+dontLink=0
+if test "$*" = "-v" -o -z "$*"; then
+    dontLink=1
+else
+    for i in "$@"; do
+        if test "$i" = "-c"; then
+            dontLink=1
+        elif test "$i" = "-S"; then
+            dontLink=1
+        elif test "$i" = "-E"; then
+            dontLink=1
+        elif test "$i" = "-E"; then
+            dontLink=1
+        elif test "$i" = "-M"; then
+            dontLink=1
+        elif test "$i" = "-MM"; then
+            dontLink=1
+        fi
+    done
+fi
+
+
+# Optionally filter out paths not refering to the store.
+params=("$@")
+if test "$NIX_ENFORCE_PURITY" = "1" -a -n "$NIX_STORE"; then
+    rest=()
+    n=0
+    while test $n -lt ${#params[*]}; do
+        p=${params[n]}
+        p2=${params[$((n+1))]}
+        if test "${p:0:3}" = "-L/" && badPath "${p:2}"; then
+            skip $p
+        elif test "$p" = "-L" && badPath "$p2"; then
+            n=$((n + 1)); skip $p2
+        elif test "${p:0:3}" = "-I/" && badPath "${p:2}"; then
+            skip $p
+        elif test "$p" = "-I" && badPath "$p2"; then
+            n=$((n + 1)); skip $p2
+        elif test "$p" = "-isystem" && badPath "$p2"; then
+            n=$((n + 1)); skip $p2
+        else
+            rest=("${rest[@]}" "$p")
+        fi
+        n=$((n + 1))
+    done
+    params=("${rest[@]}")
+fi
+
+
+# Add the flags for the C compiler proper.
+extraAfter=($NIX_CFLAGS_COMPILE)
+extraBefore=()
+
+if test "$dontLink" != "1"; then
+
+    # Add the flags that should only be passed to the compiler when
+    # linking.
+    extraAfter=(${extraAfter[@]} $NIX_CFLAGS_LINK)
+
+    # Add the flags that should be passed to the linker (and prevent
+    # `ld-wrapper' from adding NIX_LDFLAGS again).
+    for i in $NIX_LDFLAGS_BEFORE; do
+        extraBefore=(${extraBefore[@]} "-Wl,$i")
+    done
+    for i in $NIX_LDFLAGS; do
+	if test "${i:0:3}" = "-L/"; then
+	    extraAfter=(${extraAfter[@]} "$i")
+	else
+	    extraAfter=(${extraAfter[@]} "-Wl,$i")
+	fi
+    done
+    export NIX_LDFLAGS_SET=1
+
+    if test "$NIX_STRIP_DEBUG" = "1"; then
+        # Add executable-stripping flags.
+        extraAfter=(${extraAfter[@]} $NIX_CFLAGS_STRIP)
+    fi
+fi
+
+# Optionally print debug info.
+if test "$NIX_DEBUG" = "1"; then
+  echo "original flags to @gccProg@:" >&2
+  for i in "${params[@]}"; do
+      echo "  $i" >&2
+  done
+  echo "extraBefore flags to @gccProg@:" >&2
+  for i in ${extraBefore[@]}; do
+      echo "  $i" >&2
+  done
+  echo "extraAfter flags to @gccProg@:" >&2
+  for i in ${extraAfter[@]}; do
+      echo "  $i" >&2
+  done
+fi
+
+if test -n "$NIX_GCC_WRAPPER_EXEC_HOOK"; then
+    . "$NIX_GCC_WRAPPER_EXEC_HOOK"
+fi
+
+
+# Call the real `gcc'.  Filter out warnings from stderr about unused
+# `-B' flags, since they confuse some programs.  Deep bash magic to
+# apply grep to stderr (by swapping stdin/stderr twice).
+if test -z "$NIX_GCC_NEEDS_GREP"; then
+    @gccProg@ ${extraBefore[@]} "${params[@]}" ${extraAfter[@]}
+else
+    (@gccProg@ ${extraBefore[@]} "${params[@]}" ${extraAfter[@]} 3>&2 2>&1 1>&3- \
+        | (grep -v 'file path prefix' || true); exit ${PIPESTATUS[0]}) 3>&2 2>&1 1>&3-
+    exit $?
+fi    
diff --git a/pkgs/build-support/gcc-cross-wrapper/ld-wrapper.sh b/pkgs/build-support/gcc-cross-wrapper/ld-wrapper.sh
new file mode 100644
index 000000000000..fbf7186ad276
--- /dev/null
+++ b/pkgs/build-support/gcc-cross-wrapper/ld-wrapper.sh
@@ -0,0 +1,145 @@
+#! @shell@ -e
+
+if test -n "$NIX_LD_WRAPPER_START_HOOK"; then
+    . "$NIX_LD_WRAPPER_START_HOOK"
+fi
+
+if test -z "$NIX_GLIBC_FLAGS_SET"; then
+    . @out@/nix-support/add-flags
+fi
+
+. @out@/nix-support/utils
+
+
+# Optionally filter out paths not refering to the store.
+params=("$@")
+if test "$NIX_ENFORCE_PURITY" = "1" -a -n "$NIX_STORE" \
+        -a \( -z "$NIX_IGNORE_LD_THROUGH_GCC" -o -z "$NIX_LDFLAGS_SET" \); then
+    rest=()
+    n=0
+    while test $n -lt ${#params[*]}; do
+        p=${params[n]}
+        p2=${params[$((n+1))]}
+        if test "${p:0:3}" = "-L/" && badPath "${p:2}"; then
+            skip $p
+        elif test "$p" = "-L" && badPath "$p2"; then
+            n=$((n + 1)); skip $p2
+        elif test "$p" = "-rpath" && badPath "$p2"; then
+            n=$((n + 1)); skip $p2
+        elif test "$p" = "-dynamic-linker" && badPath "$p2"; then
+            n=$((n + 1)); skip $p2
+        elif test "${p:0:1}" = "/" && badPath "$p"; then
+            # We cannot skip this; barf.
+            echo "impure path \`$p' used in link" >&2
+            exit 1
+        else
+            rest=("${rest[@]}" "$p")
+        fi
+        n=$((n + 1))
+    done
+    params=("${rest[@]}")
+fi
+
+
+extra=()
+extraBefore=()
+
+if test -z "$NIX_LDFLAGS_SET"; then
+    extra=(${extra[@]} $NIX_LDFLAGS)
+    extraBefore=(${extraBefore[@]} $NIX_LDFLAGS_BEFORE)
+fi
+
+
+# Add all used dynamic libraries to the rpath.
+if test "$NIX_DONT_SET_RPATH" != "1"; then
+
+    # First, find all -L... switches.
+    allParams=("${params[@]}" ${extra[@]})
+    libPath=""
+    addToLibPath() {
+        local path="$1"
+        if test "${path:0:1}" != "/"; then return 0; fi
+        case "$path" in
+            *..*|*./*|*/.*|*//*)
+                local path2
+                if path2=$(readlink -f "$path"); then
+                    path="$path2"
+                fi
+                ;;
+        esac
+        case $libPath in
+            *\ $path\ *) return 0 ;;
+        esac
+        libPath="$libPath $path "
+    }
+    n=0
+    while test $n -lt ${#allParams[*]}; do
+        p=${allParams[n]}
+        p2=${allParams[$((n+1))]}
+        if test "${p:0:3}" = "-L/"; then
+            addToLibPath ${p:2}
+        elif test "$p" = "-L"; then
+            addToLibPath ${p2}
+            n=$((n + 1))
+        fi
+        n=$((n + 1))
+    done
+
+    # Second, for each -l... switch, find the directory containing the
+    # library and add it to the rpath.
+    rpath=""
+    addToRPath() {
+        # If the path is not in the store, don't add it to the rpath.
+        # This typically happens for libraries in /tmp that are later
+        # copied to $out/lib.  If not, we're screwed.
+        if test "${1:0:${#NIX_STORE}}" != "$NIX_STORE"; then return 0; fi
+        case $rpath in
+            *\ $1\ *) return 0 ;;
+        esac
+        rpath="$rpath $1 "
+    }
+    findLib() {
+        for i in $libPath; do
+            if test -f $i/lib$1.so; then
+                addToRPath $i
+            fi
+        done
+    }
+    n=0
+    while test $n -lt ${#allParams[*]}; do
+        p=${allParams[n]}
+        p2=${allParams[$((n+1))]}
+        if test "${p:0:2}" = "-l"; then
+            findLib ${p:2}
+        elif test "$p" = "-l"; then
+            # I haven't seen `-l foo', but you never know...
+            findLib ${p2}
+            n=$((n + 1))
+        fi
+        n=$((n + 1))
+    done
+
+    # Finally, add `-rpath' switches.
+    for i in $rpath; do
+        extra=(${extra[@]} -rpath $i)
+    done
+fi
+
+
+# Optionally print debug info.
+if test "$NIX_DEBUG" = "1"; then
+  echo "original flags to @ld@:" >&2
+  for i in "${params[@]}"; do
+      echo "  $i" >&2
+  done
+  echo "extra flags to @ld@:" >&2
+  for i in ${extra[@]}; do
+      echo "  $i" >&2
+  done
+fi
+
+if test -n "$NIX_LD_WRAPPER_EXEC_HOOK"; then
+    . "$NIX_LD_WRAPPER_EXEC_HOOK"
+fi
+
+exec @ld@ ${extraBefore[@]} "${params[@]}" ${extra[@]}
diff --git a/pkgs/build-support/gcc-cross-wrapper/setup-hook.sh b/pkgs/build-support/gcc-cross-wrapper/setup-hook.sh
new file mode 100644
index 000000000000..7a7ea8226919
--- /dev/null
+++ b/pkgs/build-support/gcc-cross-wrapper/setup-hook.sh
@@ -0,0 +1,25 @@
+addCVars () {
+    if test -d $1/include; then
+        export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -I$1/include"
+    fi
+
+    if test -d $1/lib; then
+        export NIX_LDFLAGS="$NIX_LDFLAGS -L$1/lib"
+    fi
+}
+
+envHooks=(${envHooks[@]} addCVars)
+
+# Note: these come *after* $out in the PATH (see setup.sh).
+
+if test -n "@gcc@"; then
+    PATH=$PATH:@gcc@/bin
+fi
+
+if test -n "@binutils@"; then
+    PATH=$PATH:@binutils@/bin
+fi
+
+if test -n "@glibc@"; then
+    PATH=$PATH:@glibc@/bin
+fi
diff --git a/pkgs/build-support/gcc-cross-wrapper/utils.sh b/pkgs/build-support/gcc-cross-wrapper/utils.sh
new file mode 100644
index 000000000000..9a664e1d1e6b
--- /dev/null
+++ b/pkgs/build-support/gcc-cross-wrapper/utils.sh
@@ -0,0 +1,23 @@
+skip () {
+    if test "$NIX_DEBUG" = "1"; then
+        echo "skipping impure path $1" >&2
+    fi
+}
+
+
+# Checks whether a path is impure.  E.g., `/lib/foo.so' is impure, but
+# `/nix/store/.../lib/foo.so' isn't.
+badPath() {
+    local p=$1
+    
+    # Relative paths are okay (since they're presumably relative to
+    # the temporary build directory).
+    if test "${p:0:1}" != "/"; then return 1; fi
+    
+    # Otherwise, the path should refer to the store or some temporary
+    # directory (including the build directory).
+    test \
+        "${p:0:${#NIX_STORE}}" != "$NIX_STORE" -a \
+        "${p:0:4}" != "/tmp" -a \
+        "${p:0:${#NIX_BUILD_TOP}}" != "$NIX_BUILD_TOP"
+}