summary refs log tree commit diff
path: root/maintainers
diff options
context:
space:
mode:
authorArmijn Hemel <armijn@gpl-violations.org>2005-12-06 18:05:20 +0000
committerArmijn Hemel <armijn@gpl-violations.org>2005-12-06 18:05:20 +0000
commit5138d6dc10e9a240f6b5f5e02768c23589f8ced7 (patch)
tree66a6bd744bee9963f686ad972b2cb30cf8dbd2f9 /maintainers
parent5c461f8e7b32b4a393d60f3eaa8a8934e6a0a751 (diff)
downloadnixpkgs-5138d6dc10e9a240f6b5f5e02768c23589f8ced7.tar
nixpkgs-5138d6dc10e9a240f6b5f5e02768c23589f8ced7.tar.gz
nixpkgs-5138d6dc10e9a240f6b5f5e02768c23589f8ced7.tar.bz2
nixpkgs-5138d6dc10e9a240f6b5f5e02768c23589f8ced7.tar.lz
nixpkgs-5138d6dc10e9a240f6b5f5e02768c23589f8ced7.tar.xz
nixpkgs-5138d6dc10e9a240f6b5f5e02768c23589f8ced7.tar.zst
nixpkgs-5138d6dc10e9a240f6b5f5e02768c23589f8ced7.zip
first version of the Nix cross compilation HOWTO (easy stuff is done), more to follow
svn path=/nixpkgs/trunk/; revision=4342
Diffstat (limited to 'maintainers')
-rw-r--r--maintainers/docs/cross.txt265
1 files changed, 265 insertions, 0 deletions
diff --git a/maintainers/docs/cross.txt b/maintainers/docs/cross.txt
new file mode 100644
index 00000000000..f4c128bad4c
--- /dev/null
+++ b/maintainers/docs/cross.txt
@@ -0,0 +1,265 @@
+Setting up a cross compiler with Nix
+
+"Cross compilation" means compiling a program on one machine for another
+type of machine. A typical use of cross compilation is to compile programs
+for embedded devices. These devices often don't have the computing power
+and memory to compile programs natively.
+
+For a fully working cross compiler the following are needed:
+
+* cross binutils: assembler, archiver, linker, etcetera that understand
+the format of the target system
+
+* cross compiler: a compiler that can generate binary code and object files
+for the target platform
+
+* cross C library: a library to link object files with to create fully
+functional programs
+
+Cross compilers are difficult to set up. A lot of people report that they
+cannot succeed in building a cross toolchain successfully. The answers
+usually consist of "download this pre-built toolchain", which is equally
+unhelpful.
+
+A toolchain is set up in five steps:
+
+1. build binutils to that can run on the host platform, but generate code
+for the target platform
+
+2. build Linux kernel headers for the target platform
+
+3. build a minimal C only version of GCC, that can run on the host platform
+and generate code for the target platform
+
+4. build a C library for the target platform. This includes the dynamic
+linker, C library, etc.
+
+5. build a full GCC
+
+****
+NB:
+
+Keep in mind that many programs are not very well suited for cross
+compilation. Either they are not intended to run on other platforms,
+because the code is highly platform specific, or the configuration proces
+is not written with cross compilation in mind.
+
+Nix will not solve these problems for you!
+***
+
+This document describes to set up a cross compiler to generate code for
+arm-linux with uClibc and runs on i686-linux. The "stdenv" used is the
+default from the standard Nix packages collection.
+
+Step 1: build binutils for arm-linux in the stdenv for i686-linux
+
+---
+{stdenv, fetchurl, noSysDirs}:
+
+stdenv.mkDerivation {
+  name = "binutils-2.16.1-arm";
+  builder = ./builder.sh;
+  src = fetchurl {
+    url = http://ftp.nluug.nl/gnu/binutils/binutils-2.16.1.tar.bz2;
+    md5 = "6a9d529efb285071dad10e1f3d2b2967";
+  };
+  inherit noSysDirs;
+  configureFlags = "--target=arm-linux";
+}
+---
+
+This will compile binutils that will run on i686-linux, but knows the
+format used by arm-linux.
+
+Step 2: build kernel headers for the target architecture
+
+  default.nix for kernel-headers-arm:
+
+---
+{stdenv, fetchurl}:
+
+assert stdenv.system == "i686-linux";
+
+stdenv.mkDerivation {
+  name = "linux-headers-2.6.13.4-arm";
+  builder = ./builder.sh;
+  src = fetchurl {
+    url = http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.13.4.tar.bz2;
+    md5 = "94768d7eef90a9d8174639b2a7d3f58d";
+  };
+}
+---
+
+  builder.sh for kernel-headers-arm:
+
+---
+source $stdenv/setup
+
+
+buildPhase() {
+    make include/linux/version.h
+}
+
+buildPhase=buildPhase
+
+
+installPhase() {
+    mkdir $out
+    mkdir $out/include
+    #cd $out/include
+    #ln -s asm-arm asm
+    make include/asm ARCH=arm
+    cp -prvd include/linux include/asm include/asm-arm include/asm-generic $out/include
+    echo -n > $out/include/linux/autoconf.h
+}
+
+installPhase=installPhase
+
+
+genericBuild
+---
+
+Step 3: build a minimal GCC
+
+Extra/different parameters include the target platform and the kernel
+headers argument (this needs a major cleanup, as well as the name, it
+needs to be different!). Profiled compilers are disabled. The tarball
+used here is just gcc-core. For some reason it doesn't install nicely
+if the whole tarball is used (or is this some braino on my side? -- AH).
+
+Only C is used, because for other languages (such as C++) extra libraries
+need to be compiled, for which libraries compiled for the target system
+are needed.
+
+---
+{ stdenv, fetchurl, noSysDirs
+, langC ? true, langCC ? true, langF77 ? false
+, profiledCompiler ? false
+, binutilsArm
+, kernelHeadersArm
+}:
+
+assert langC;
+
+stdenv.mkDerivation {
+  name = "gcc-4.0.2-arm";
+  builder = ./builder.sh;
+  src = fetchurl {
+    url = ftp://ftp.nluug.nl/pub/gnu/gcc/gcc-4.0.2/gcc-core-4.0.2.tar.bz2;
+    md5 = "f7781398ada62ba255486673e6274b26";
+    #url = ftp://ftp.nluug.nl/pub/gnu/gcc/gcc-4.0.2/gcc-4.0.2.tar.bz2;
+    #md5 = "a659b8388cac9db2b13e056e574ceeb0";
+  };
+  # !!! apply only if noSysDirs is set
+  patches = [./no-sys-dirs.patch ./gcc-inhibit.patch];
+  inherit noSysDirs langC langCC langF77 profiledCompiler;
+  buildInputs = [binutilsArm];
+  inherit kernelHeadersArm binutilsArm;
+  platform = "arm-linux";
+}
+---
+
+
+---
+source $stdenv/setup
+
+
+export NIX_FIXINC_DUMMY=$NIX_BUILD_TOP/dummy
+mkdir $NIX_FIXINC_DUMMY
+
+
+if test "$noSysDirs" = "1"; then
+
+    if test "$noSysDirs" = "1"; then
+        # Figure out what extra flags to pass to the gcc compilers
+        # being generated to make sure that they use our glibc.
+        if test -e $NIX_GCC/nix-support/orig-glibc; then
+            glibc=$(cat $NIX_GCC/nix-support/orig-glibc)
+            # Ugh.  Copied from gcc-wrapper/builder.sh.  We can't just
+            # source in $NIX_GCC/nix-support/add-flags, since that
+            # would cause *this* GCC to be linked against the
+            # *previous* GCC.  Need some more modularity there.
+            extraCFlags="-B$glibc/lib -isystem $glibc/include"
+            extraLDFlags="-B$glibc/lib -L$glibc/lib -Wl,-s \
+              -Wl,-dynamic-linker,$glibc/lib/ld-linux.so.2"
+
+            # Oh, what a hack.  I should be shot for this.
+            # In stage 1, we should link against the previous GCC, but
+            # not afterwards.  Otherwise we retain a dependency.
+            # However, ld-wrapper, which adds the linker flags for the
+            # previous GCC, is also used in stage 2/3.  We can prevent
+            # it from adding them by NIX_GLIBC_FLAGS_SET, but then
+            # gcc-wrapper will also not add them, thereby causing
+            # stage 1 to fail.  So we use a trick to only set the
+            # flags in gcc-wrapper.
+            hook=$(pwd)/ld-wrapper-hook
+            echo "NIX_GLIBC_FLAGS_SET=1" > $hook
+            export NIX_LD_WRAPPER_START_HOOK=$hook
+        fi
+
+        export NIX_EXTRA_CFLAGS=$extraCFlags
+        export NIX_EXTRA_LDFLAGS=$extraLDFlags
+        export CFLAGS=$extraCFlags
+        export CXXFLAGS=$extraCFlags
+        export LDFLAGS=$extraLDFlags
+    fi
+
+else
+    patches=""
+fi
+
+
+preConfigure=preConfigure
+preConfigure() {
+    
+    # Determine the frontends to build.
+    langs="c"
+    if test -n "$langCC"; then
+        langs="$langs,c++"
+    fi
+    if test -n "$langF77"; then
+        langs="$langs,f77"
+    fi
+
+    # Cross compiler evilness
+    ensureDir $out
+    ensureDir $out/arm-linux
+    ensureDir $out/arm-linux/bin
+    ln -s $binutilsArm/arm-linux/bin/as $out/arm-linux/bin/as
+    ln -s $binutilsArm/arm-linux/bin/ld $out/arm-linux/bin/ld
+    ln -s $binutilsArm/arm-linux/bin/ar $out/arm-linux/bin/ar
+    ln -s $binutilsArm/arm-linux/bin/ranlib $out/arm-linux/bin/ranlib
+
+    # Perform the build in a different directory.
+    mkdir ../build
+    cd ../build
+
+    configureScript=../$sourceRoot/configure
+    configureFlags="--enable-languages=$langs --target=$platform --disable-threads --disable-libmudflap --disable-shared --with-headers=$kernelHeadersArm/include --disable-multilib"
+}
+
+
+postInstall=postInstall
+postInstall() {
+    # Remove precompiled headers for now.  They are very big and
+    # probably not very useful yet.
+    find $out/include -name "*.gch" -exec rm -rf {} \; -prune
+
+    # Remove `fixincl' to prevent a retained dependency on the
+    # previous gcc.
+    rm -rf $out/libexec/gcc/*/*/install-tools
+}
+
+
+#if test -z "$profiledCompiler"; then
+    #makeFlags="bootstrap"
+#else    
+    #makeFlags="profiledbootstrap"
+#fi
+
+genericBuild
+---
+
+This is enough to compile a C library. In our case we take uClibc. It's
+intended to be a small sized replacement for glibc. It is widely used in
+embedded environments.