diff --git a/pkgs/build-support/gcc-wrapper/builder.sh b/pkgs/build-support/gcc-wrapper/builder.sh new file mode 100755 index 000000000000..d3b1f433559c --- /dev/null +++ b/pkgs/build-support/gcc-wrapper/builder.sh @@ -0,0 +1,62 @@ +#! /bin/sh -e + +. $stdenv/setup + +if test -z "$isNative"; then + cflagsCompile="-B$out/bin -B$glibc/lib -isystem $glibc/include" + ldflags="-L$glibc/lib -L$gcc/lib " \ + "-dynamic-linker $glibc/lib/ld-linux.so.2" \ + "-rpath $glibc/lib -rpath $gcc/lib" +else + cflagsCompile="-B$out/bin" +fi + +mkdir $out +mkdir $out/bin + + +mkGccWrapper () { + local dst=$1 + local src=$2 + + if ! test -f "$src"; then + echo "$src does not exist (skipping)" + return + fi + + sed \ + -e "s^@cflagsCompile@^$cflagsCompile^g" \ + -e "s^@cflagsLink@^$cflagsLink^g" \ + -e "s^@ldflags@^$ldflags^g" \ + -e "s^@gcc@^$src^g" \ + < $gccWrapper > $dst + chmod +x $dst + +} + +mkGccWrapper $out/bin/gcc $gcc/bin/gcc +ln -s gcc $out/bin/cc + +mkGccWrapper $out/bin/g++ $gcc/bin/g++ +ln -s g++ $out/bin/c++ + +mkGccWrapper $out/bin/g77 $gcc/bin/g77 +ln -s g77 $out/bin/f77 + + +sed \ + -e "s^@ldflags@^$ldflags^g" \ + -e "s^@ld@^$gcc/bin/ld^g" \ + < $ldWrapper > $out/bin/ld +chmod +x $out/bin/ld + + +mkdir $out/nix-support +test -z "$isNative" && echo $gcc > $out/nix-support/orig-gcc +test -z "$isNative" && echo $glibc > $out/nix-support/orig-glibc + +sed \ + -e "s^@isNative@^$isNative^g" \ + -e "s^@gcc@^$gcc^g" \ + -e "s^@glibc@^$glibc^g" \ + < $setupHook > $out/nix-support/setup-hook diff --git a/pkgs/build-support/gcc-wrapper/default.nix b/pkgs/build-support/gcc-wrapper/default.nix new file mode 100644 index 000000000000..da1896611645 --- /dev/null +++ b/pkgs/build-support/gcc-wrapper/default.nix @@ -0,0 +1,23 @@ +# The Nix `gcc' derivation 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 +# derivation provides a wrapper that sets up the right environment +# variables so that the compiler and the linker just "work". + +{name, stdenv, isNative, gcc ? null, glibc ? null, binutils ? null}: + +assert isNative -> gcc != ""; +assert !isNative -> gcc != null && glibc != null && binutils != null; + +derivation { + system = stdenv.system; + builder = ./builder.sh; + setupHook = ./setup-hook.sh; + gccWrapper = ./gcc-wrapper.sh; + ldWrapper = ./ld-wrapper.sh; + inherit name stdenv isNative gcc glibc binutils; + langC = if isNative then true else gcc.langC; + langCC = if isNative then true else gcc.langCC; + langF77 = if isNative then false else gcc.langF77; +} diff --git a/pkgs/build-support/gcc-wrapper/gcc-wrapper.sh b/pkgs/build-support/gcc-wrapper/gcc-wrapper.sh new file mode 100644 index 000000000000..59f38086f325 --- /dev/null +++ b/pkgs/build-support/gcc-wrapper/gcc-wrapper.sh @@ -0,0 +1,74 @@ +#! /bin/sh + +if test -n "$NIX_GCC_WRAPPER_START_HOOK"; then + . "$NIX_GCC_WRAPPER_START_HOOK" +fi + +if test -z "$NIX_GLIBC_FLAGS_SET"; then + NIX_CFLAGS_COMPILE="@cflagsCompile@ $NIX_CFLAGS_COMPILE" + NIX_CFLAGS_LINK="@cflagsLink@ $NIX_CFLAGS_LINK" + NIX_LDFLAGS="@ldflags@ $NIX_LDFLAGS" +fi + +# Figure out if linker flags should be passed. GCC prints annoying +# warnings when they are not needed. +dontLink=0 +if test "$*" = "-v"; 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 + +# Add the flags for the C compiler proper. +extra=($NIX_CFLAGS_COMPILE) + +if test "$dontLink" != "1"; then + + # Add the flags that should only be passed to the compiler when + # linking. + extra=(${extra[@]} $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; do + extra=(${extra[@]} "-Wl,$i") + done + export NIX_LDFLAGS_SET=1 + + if test "$NIX_STRIP_DEBUG" = "1"; then + # Add executable-stripping flags. + extra=(${extra[@]} $NIX_CFLAGS_STRIP) + fi +fi + +# Optionally print debug info. +if test "$NIX_DEBUG" = "1"; then + echo "original flags to @gcc@:" >&2 + for i in "$@"; do + echo " $i" >&2 + done + echo "extra flags to @gcc@:" >&2 + for i in ${extra[@]}; do + echo " $i" >&2 + done +fi + +if test -n "$NIX_GCC_WRAPPER_EXEC_HOOK"; then + . "$NIX_GCC_WRAPPER_EXEC_HOOK" +fi + +exec @gcc@ "$@" ${extra[@]} diff --git a/pkgs/build-support/gcc-wrapper/ld-wrapper.sh b/pkgs/build-support/gcc-wrapper/ld-wrapper.sh new file mode 100644 index 000000000000..2201bbe19d23 --- /dev/null +++ b/pkgs/build-support/gcc-wrapper/ld-wrapper.sh @@ -0,0 +1,28 @@ +#! /bin/sh + +if test -n "$NIX_LD_WRAPPER_START_HOOK"; then + . "$NIX_LD_WRAPPER_START_HOOK" +fi + +extra=() + +if test -z "$NIX_LDFLAGS_SET"; then + extra=(${extra[@]} $NIX_LDFLAGS) +fi + +if test "$NIX_DEBUG" = "1"; then + echo "original flags to @ld@:" >&2 + for i in "$@"; 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@ "$@" ${extra[@]} diff --git a/pkgs/build-support/gcc-wrapper/setup-hook.sh b/pkgs/build-support/gcc-wrapper/setup-hook.sh new file mode 100644 index 000000000000..a4c52ba803d7 --- /dev/null +++ b/pkgs/build-support/gcc-wrapper/setup-hook.sh @@ -0,0 +1,15 @@ +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 -rpath $1/lib" + fi +} + +envHooks=(${envHooks[@]} addCVars) + +if test -z "@isNative@"; then + PATH=$PATH:@gcc@/bin:@glibc@/bin +fi diff --git a/pkgs/development/compilers/gcc-wrapper/builder.sh b/pkgs/development/compilers/gcc-wrapper/builder.sh deleted file mode 100755 index fda971e9462c..000000000000 --- a/pkgs/development/compilers/gcc-wrapper/builder.sh +++ /dev/null @@ -1,65 +0,0 @@ -#! /bin/sh -e - -. $stdenv/setup - -mkdir $out -mkdir $out/bin -for i in $(cd $gcc/bin && ls); do - cat > $out/bin/$i <&2 - for i in \${extra[@]}; do - echo " \$i" >&2 - done -fi - -IFS= - -exec $gcc/bin/$i \$@ \${extra[@]} -EOF - chmod +x $out/bin/$i -done - -echo $gcc > $out/orig-gcc -echo $glibc > $out/orig-glibc diff --git a/pkgs/development/compilers/gcc-wrapper/default.nix b/pkgs/development/compilers/gcc-wrapper/default.nix deleted file mode 100644 index 33c82a6c2f7d..000000000000 --- a/pkgs/development/compilers/gcc-wrapper/default.nix +++ /dev/null @@ -1,17 +0,0 @@ -# The Nix `gcc' derivation 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 -# derivation provides a wrapper that sets up the right environment -# variables so that the compiler and the linker just "work". - -{stdenv, gcc}: - -derivation { - name = gcc.name; # maybe a bad idea - system = stdenv.system; - builder = ./builder.sh; - glibc = stdenv.param4; # !!! hack - inherit stdenv gcc; - inherit (gcc) langC langCC langF77; -} diff --git a/pkgs/stdenv/generic/builder.sh b/pkgs/stdenv/generic/builder.sh index ad788118492c..ac9851607733 100755 --- a/pkgs/stdenv/generic/builder.sh +++ b/pkgs/stdenv/generic/builder.sh @@ -1,41 +1,17 @@ #! /bin/sh -# Set up the initial path. -for i in $initialPath; do - PATH=$PATH:$i/bin -done +. $stdenv/setup -# Make output directories. mkdir $out || exit 1 -mkdir $out/bin || exit 1 -# Create the setup script. sed \ - -e "s^@OUT@^$out^g" \ - -e "s^@PREHOOK@^$prehook^g" \ - -e "s^@POSTHOOK@^$posthook^g" \ - -e "s^@INITIALPATH@^$initialPath^g" \ - -e "s^@PARAM1@^$param1^g" \ - -e "s^@PARAM2@^$param2^g" \ - -e "s^@PARAM3@^$param3^g" \ - -e "s^@PARAM4@^$param4^g" \ - -e "s^@PARAM5@^$param5^g" \ + -e "s^@preHook@^$preHook^g" \ + -e "s^@postHook@^$postHook^g" \ + -e "s^@initialPath@^$initialPath^g" \ + -e "s^@gcc@^$gcc^g" \ + -e "s^@param1@^$param1^g" \ + -e "s^@param2@^$param2^g" \ + -e "s^@param3@^$param3^g" \ + -e "s^@param4@^$param4^g" \ + -e "s^@param5@^$param5^g" \ < $setup > $out/setup || exit 1 - -# Create the gcc wrapper. -sed \ - -e 's^@GCC\@^$NIX_CC^g' \ - < $gccwrapper > $out/bin/gcc || exit 1 -chmod +x $out/bin/gcc || exit 1 -ln -s gcc $out/bin/cc || exit 1 - -# Create the g++ wrapper. -sed \ - -e 's^@GCC\@^$NIX_CXX^g' \ - < $gccwrapper > $out/bin/g++ || exit 1 -chmod +x $out/bin/g++ || exit 1 -ln -s g++ $out/bin/c++ || exit 1 - -# Create the ld wrapper. -cp $ldwrapper $out/bin/ld || exit 1 -chmod +x $out/bin/ld || exit 1 diff --git a/pkgs/stdenv/generic/default.nix b/pkgs/stdenv/generic/default.nix index 6778b4d131cc..c816e5888080 100644 --- a/pkgs/stdenv/generic/default.nix +++ b/pkgs/stdenv/generic/default.nix @@ -1,23 +1,17 @@ -{system, name, noSysDirs, prehook, posthook, initialPath, - param1, param2, param3, param4, param5}: +{ stdenv, name, preHook, postHook, initialPath, gcc +, param1 ? "", param2 ? "", param3 ? "", param4 ? "", param5 ? "" +}: + derivation { - name = name; - system = system; + inherit stdenv name; + system = stdenv.system; + builder = ./builder.sh; - noSysDirs = noSysDirs; setup = ./setup.sh; - gccwrapper = ./gcc-wrapper.sh; - ldwrapper = ./ld-wrapper.sh; - prehook = prehook; - posthook = posthook; + inherit preHook postHook initialPath gcc; - initialPath = initialPath; # TODO: make this more elegant. - param1 = param1; - param2 = param2; - param3 = param3; - param4 = param4; - param5 = param5; + inherit param1 param2 param3 param4 param5; } diff --git a/pkgs/stdenv/generic/gcc-wrapper.sh b/pkgs/stdenv/generic/gcc-wrapper.sh deleted file mode 100644 index f68612d2c1e7..000000000000 --- a/pkgs/stdenv/generic/gcc-wrapper.sh +++ /dev/null @@ -1,42 +0,0 @@ -#! /bin/sh - -IFS= - -justcompile=0 -for i in $@; do - if test "$i" == "-c"; then - justcompile=1 - elif test "$i" == "-S"; then - justcompile=1 - elif test "$i" == "-E"; then - justcompile=1 - elif test "$i" == "-E"; then - justcompile=1 - elif test "$i" == "-M"; then - justcompile=1 - elif test "$i" == "-MM"; then - justcompile=1 - fi -done - -IFS=" " -extra=($NIX_CFLAGS_COMPILE) -if test "$justcompile" != "1"; then - extra=(${extra[@]} $NIX_CFLAGS_LINK) - for i in $NIX_LDFLAGS; do - extra=(${extra[@]} "-Wl,$i") - done - if test "$NIX_STRIP_DEBUG" == "1"; then - extra=(${extra[@]} -g0 -Wl,-s) - fi -fi - -if test "$NIX_DEBUG" == "1"; then - echo "extra flags to @GCC@:" >&2 - for i in ${extra[@]}; do - echo " $i" >&2 - done -fi - -IFS= -exec @GCC@ $@ ${extra[@]} diff --git a/pkgs/stdenv/generic/ld-wrapper.sh b/pkgs/stdenv/generic/ld-wrapper.sh deleted file mode 100644 index e6a2fe74c5e8..000000000000 --- a/pkgs/stdenv/generic/ld-wrapper.sh +++ /dev/null @@ -1,17 +0,0 @@ -#! /bin/sh - -IFS=" " -extra=($NIX_CFLAGS_LINK $NIX_LDFLAGS) -if test "$NIX_STRIP_DEBUG" == "1"; then - extra=(${extra[@]} -s) -fi - -if test "$NIX_DEBUG" == "1"; then - echo "extra flags to @LD@:" >&2 - for i in ${extra[@]}; do - echo " $i" >&2 - done -fi - -IFS= -exec $NIX_LD $@ ${extra[@]} diff --git a/pkgs/stdenv/generic/setup.sh b/pkgs/stdenv/generic/setup.sh index 25b84bb5edcc..c163c04cb517 100644 --- a/pkgs/stdenv/generic/setup.sh +++ b/pkgs/stdenv/generic/setup.sh @@ -1,67 +1,85 @@ +set -e + + # Set up the initial path. -for i in @INITIALPATH@; do - PATH=$PATH:$i/bin +PATH= +for i in @gcc@ @initialPath@; do + PATH=$PATH${PATH:+:}$i/bin done -echo $PATH + +if test "$NIX_DEBUG" = "1"; then + echo "Initial path: $PATH" +fi + # Execute the pre-hook. -param1=@PARAM1@ -param2=@PARAM2@ -param3=@PARAM3@ -param4=@PARAM4@ -param5=@PARAM5@ -. @PREHOOK@ +param1=@param1@ +param2=@param2@ +param3=@param3@ +param4=@param4@ +param5=@param5@ +. @preHook@ -# Add the directory containing the GCC wrappers to the PATH. -export PATH=@OUT@/bin:$PATH -# Recursively add all buildinputs to the relevant environment variables. -addtoenv() +# Recursively find all build inputs. +findInputs() { - pkgs="$buildinputs $1" + local pkg=$1 + pkgs=(${pkgs[@]} $pkg) - if test -d $1/bin; then - export PATH=$1/bin:$PATH + if test -f $pkg/nix-support/setup-hook; then + . $pkg/nix-support/setup-hook fi - - if test -d $1/lib; then - export NIX_CFLAGS_LINK="-L$1/lib $NIX_CFLAGS_LINK" - export NIX_LDFLAGS="-rpath $1/lib $NIX_LDFLAGS" - fi - - if test -d $1/lib/pkgconfig; then - export PKG_CONFIG_PATH=$1/lib/pkgconfig:$PKG_CONFIG_PATH - fi - - if test -d $1/include; then - export NIX_CFLAGS_COMPILE="-I$1/include $NIX_CFLAGS_COMPILE" - fi - - if test -f $1/propagated-build-inputs; then - for i in $(cat $1/propagated-build-inputs); do - addtoenv $i + + if test -f $pkg/nix-support/propagated-build-inputs; then + for i in $(cat $pkg/nix-support/propagated-build-inputs); do + addToEnv $pkg done fi } -oldbuildinputs=$buildinputs -buildinputs= - -for i in $oldbuildinputs; do - addtoenv $i +pkgs=() +envHooks=() +for i in $buildinputs; do + findInputs $i done + +# Set the relevant environment variables to point to the build inputs +# found above. +addToEnv() +{ + local pkg=$1 + + if test -d $1/bin; then + export _PATH=$_PATH:$1/bin + fi + + for i in "${envHooks[@]}"; do + $i $pkg + done +} + +for i in "${pkgs[@]}"; do + addToEnv $i +done + + # Add the output as an rpath. if test "$NIX_NO_SELF_RPATH" != "1"; then export NIX_LDFLAGS="-rpath $out/lib $NIX_LDFLAGS" fi + # Strip debug information by default. export NIX_STRIP_DEBUG=1 +export NIX_CFLAGS_STRIP="-g0 -Wl,-s" + # Execute the post-hook. -. @POSTHOOK@ +. @postHook@ -if test "$NIX_DEBUG" == "1"; then - echo "Setup: PATH=$PATH" +PATH=$_PATH${_PATH}$PATH +if test "$NIX_DEBUG" = "1"; then + echo "Final path: $PATH" fi diff --git a/pkgs/stdenv/initial/builder.sh b/pkgs/stdenv/initial/builder.sh new file mode 100755 index 000000000000..8a9f7ab49188 --- /dev/null +++ b/pkgs/stdenv/initial/builder.sh @@ -0,0 +1,9 @@ +#! /bin/sh -e + +export PATH=/usr/bin:/bin + +mkdir $out +cat > $out/setup < hello.c < + +int main(int argc, char * * argv) +{ + printf("Hello World!\n"); + return 0; +} +EOF + +gcc hello.c -o $out/bin/hello + +$out/bin/hello + +cat > hello2.cc < + +int main(int argc, char * * argv) +{ + std::cout << "Hello World!\n"; + std::cout << VALUE << std::endl; + return 0; +} +EOF + +g++ hello2.cc -o $out/bin/hello2 -DVALUE="1 + 2 * 3" + +$out/bin/hello2 + +ld -v \ No newline at end of file diff --git a/pkgs/test/simple/default.nix b/pkgs/test/simple/default.nix new file mode 100644 index 000000000000..2d582f03a511 --- /dev/null +++ b/pkgs/test/simple/default.nix @@ -0,0 +1,18 @@ +let { + system = "i686-linux"; + + stdenvInitial = (import ../../stdenv/initial) { + name = "stdenv-initial"; + inherit system; + }; + + stdenv = (import ../../stdenv/native) {stdenv = stdenvInitial;}; + + test = derivation { + name = "simple-test"; + inherit system stdenv; + builder = ./builder.sh; + }; + + body = test; +}