docs/5 - Using the toolchain.txt
author "Yann E. MORIN" <yann.morin.1998@free.fr>
Tue Mar 06 21:36:10 2012 +0100 (2012-03-06)
changeset 2908 dcdb309b7967
parent 2764 986e90e1ca27
permissions -rw-r--r--
docs: update my e-mail

Since anciens.enib.fr has been dead for two months now, without any
hope of recovery, update my e-mail to point to @free.fr instead.

Reported-by: "Bryan Hundven" <bryanhundven@gmail.com>
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
     1 File.........: 5 - Using the toolchain.txt
     2 Copyright....: (C) 2010 Yann E. MORIN <yann.morin.1998@free.fr>
     3 License......: Creative Commons Attribution Share Alike (CC-by-sa), v2.5
     4 
     5 
     6 Using the toolchain  /
     7 ____________________/
     8 
     9 
    10 Using the toolchain is as simple as adding the toolchain's bin directory in
    11 your PATH, such as:
    12   export PATH="${PATH}:/your/toolchain/path/bin"
    13 
    14 and then using the '--host' tuple to tell the build systems to use your
    15 toolchain (if the software package uses the autotools system you should
    16 also pass --build, for completeness):
    17   ./configure --host=your-host-tuple --build=your-build-tuple
    18 or
    19   make CC=your-host-tuple-gcc
    20 or
    21   make CROSS_COMPILE=your-host-tuple-
    22 and so on...
    23 
    24 (Note: in the above example, 'host' refers to the host of your program,
    25 not the host of the toolchain; and 'build' refers to the machine where
    26 you build your program, that is the host of the toolchain.)
    27 
    28 
    29 Assembling a root filesystem  /
    30 _____________________________/
    31 
    32 
    33 Assembling a root filesystem for a target device requires the successive
    34 building of a set of software packages for the target architecture. Building
    35 a package potentially requires artifacts which were generated as part of an
    36 earlier build. Note that not all artifacts which are installed as part of a
    37 package are desirable on a target's root filesystem (e.g. man/info files,
    38 include files, etc.). Therefore we must distinguish between a 'staging'
    39 directory and a 'rootfs' directory.
    40 
    41 A 'staging' directory is a location into which we install all the build
    42 artifacts. We can then point future builds to this location so they can find
    43 the appropriate header and library files. A 'rootfs' directory is a location
    44 into which we place only the files we want to have on our target.
    45 
    46 There are four schools of thought here:
    47 
    48 1) Install directly into the sysroot of the toolchain.
    49 
    50    By default (i.e. if you don't pass any arguments to the tools which
    51    would change this behaviour) the toolchain that is built by
    52    crosstool-NG will only look in its toolchain directories for system
    53    header and library files:
    54 
    55 #include "..." search starts here:
    56 #include <...> search starts here:
    57 <ct-ng install path>/lib/gcc/<host tuple>/4.5.2/include
    58 <ct-ng install path>/lib/gcc/<host tuple>/4.5.2/include-fixed
    59 <ct-ng install path>/lib/gcc/<host tuple>/4.5.2/../../../../<host tuple>/include
    60 <ct-ng install path>/<host tuple>/sysroot/usr/include
    61 
    62    In other words, the compiler will automagically find headers and
    63    libraries without extra flags if they are installed under the
    64    toolchain's sysroot directory.
    65 
    66    However, this is bad because the toolchain gets poluted, and can
    67    not be re-used.
    68 
    69    $ ./configure --build=<build tuple> --host=<host tuple> \
    70          --prefix=/usr --enable-foo-bar...
    71    $ make
    72    $ make DESTDIR=/<ct-ng install path>/<host tuple>/sysroot install
    73 
    74 2) Copy the toolchain's sysroot to the 'staging' area.
    75 
    76    If you start off by copying the toolchain's sysroot directory to your
    77    staging area, you can simply proceed to install all your packages'
    78    artifacts to the same staging area. You then only need to specify a
    79    '--sysroot=<staging area>' option to the compiler of any subsequent
    80    builds and all your required header and library files will be found/used.
    81 
    82    This is a viable option, but requires the user to always specify CFLAGS
    83    in order to include --sysroot=<staging area>, or requires the use of a
    84    wrapper to a few select tools (gcc, ld...) to pass this flag.
    85 
    86    Instead of polluting the toolchain's sysroot you are copying its contents
    87    to a new location and polluting the contents in that new location. By
    88    specifying the --sysroot option you're effectively abandoning the default
    89    sysroot in favour of your own.
    90 
    91    Incidentally this is what buildroot does using a wrapper, when using an
    92    external toolchain.
    93 
    94    $ cp -a $(<host tuple>-gcc --your-cflags-except-sysroot -print-sysroot) \
    95          /path/to/staging
    96    $ ./configure --build=<build tuple> --host=<host tuple>          \
    97                  --prefix=/usr --enable-foo-bar...                  \
    98                  CC="<host tuple>-gcc --syroot=/path/to/staging"    \
    99                  CXX="<host tuple>-g++ --sysroot=/path/to/staging"  \
   100                  LD="<host tuple>-ld --sysroot=/path/to/staging"    \
   101                  AND_SO_ON="tuple-andsoon --sysroot=/path/to/staging"
   102    $ make
   103    $ make DESTDIR=/path/to/staging install
   104 
   105 3) Use separate staging and sysroot directories.
   106 
   107    In this scenario you use a staging area to install programs, but you do
   108    not pre-fill that staging area with the toolchain's sysroot. In this case
   109    the compiler will find the system includes and libraries in its sysroot
   110    area but you have to pass appropriate CPPFLAGS and LDFLAGS to tell it
   111    where to find your headers and libraries from your staging area (or use
   112    a wrapper).
   113 
   114    $ ./configure --build=<build tuple> --host=<host tuple>          \
   115                  --prefix=/usr --enable-foo-bar...                  \
   116                  CPPFLAGS="-I/path/to/staging/usr/include"          \
   117                  LDFLAGS="-L/path/to/staging/lib -L/path/to/staging/usr/lib"
   118    $ make
   119    $ make DESTDIR=/path/to/staging install
   120 
   121 4) A mix of 2) and 3), using carefully crafted union mounts.
   122 
   123    The staging area is a union mount of:
   124       - the sysroot as a read-only branch
   125       - the real staging area as a read-write branch
   126    This also requires passing --sysroot to point to the union mount, but has
   127    other advantages, such as allowing per-package staging, and a few more
   128    obscure pros. It also has its disadvantages, as it potentially requires
   129    non-root users to create union mounts. Additionally, union mounts are not
   130    yet mainstream in the Linux kernel, so it requires patching. There is a
   131    FUSE-based unionfs implementation, but development is almost stalled,
   132    and there are a few gotchas...
   133 
   134    $ (good luck!)
   135 
   136 
   137 It is strongly advised not to use the toolchain sysroot directory as an
   138 install directory (i.e. option 1) for your programs/packages. If you do so,
   139 you will not be able to use your toolchain for another project. It is even
   140 strongly advised that your toolchain is chmod-ed to read-only once
   141 successfully install, so that you don't go polluting your toolchain with
   142 your programs'/packages' files. This can be achieved by selecting the
   143 "Render the toolchain read-only" from crosstool-NG's "Paths and misc options"
   144 configuration page.
   145 
   146 Thus, when you build a program/package, install it in a separate, staging,
   147 directory and let the cross-toolchain continue to use its own, pristine,
   148 sysroot directory.
   149 
   150 When you are done building and want to assemble your rootfs you could simply
   151 take the full contents of your staging directory and use the 'populate'
   152 script to add in the necessary files from the sysroot. However, the staging
   153 area you have created will include lots of build artifacts that you won't
   154 necessarily want/need on your target. For example: static libraries, header
   155 files, linking helper files, man/info pages. You'll also need to add various
   156 configuration files, scripts, and directories to the rootfs so it will boot.
   157 
   158 Therefore you'll probably end up creating a separate rootfs directory which
   159 you will populate from the staging area, necessary extras, and then use
   160 crosstool-NG's populate script to add the necessary sysroot libraries.
   161 
   162 
   163 The 'populate' script |
   164 ----------------------+
   165 
   166 When your root directory is ready, it is still missing some important bits: the
   167 toolchain's libraries. To populate your root directory with those libs, just
   168 run:
   169   your-target-tuple-populate -s /your/root -d /your/root-populated
   170 
   171 This will copy /your/root into /your/root-populated, and put the needed and only
   172 the needed libraries there. Thus you don't pollute /your/root with any cruft that
   173 would no longer be needed should you have to remove stuff. /your/root always
   174 contains only those things you install in it.
   175 
   176 You can then use /your/root-populated to build up your file system image, a
   177 tarball, or to NFS-mount it from your target, or whatever you need.
   178 
   179 The populate script accepts the following options:
   180 
   181  -s src_dir
   182     Use 'src_dir' as the un-populated root directory.
   183 
   184  -d dst_dir
   185     Put the populated root directory in 'dst_dir'.
   186 
   187  -l lib1 [...]
   188     Always add specified libraries.
   189 
   190  -L file
   191     Always add libraries listed in 'file'.
   192 
   193  -f
   194     Remove 'dst_dir' if it previously existed; continue even if any library
   195     specified with -l or -L is missing.
   196 
   197  -v
   198     Be verbose, and tell what's going on (you can see exactly where libs are
   199     coming from).
   200 
   201  -h
   202     Print the help.
   203 
   204 See 'your-target-tuple-populate -h' for more information on the options.
   205 
   206 Here is how populate works:
   207 
   208   1) performs some sanity checks:
   209      - src_dir and dst_dir are specified
   210      - src_dir exists
   211      - unless forced, dst_dir does not exist
   212      - src_dir != dst_dir
   213 
   214   2) copy src_dir to dst_dir
   215 
   216   3) add forced libraries to dst_dir
   217      - build the list from -l and -L options
   218      - get forced libraries from the sysroot (see below for heuristics)
   219        - abort on the first missing library, unless -f is specified
   220 
   221   4) add all missing libraries to dst_dir
   222      - scan dst_dir for every ELF files that are 'executable' or
   223        'shared object'
   224      - list the "NEEDED Shared library" fields
   225        - check if the library is already in dst_dir/lib or dst_dir/usr/lib
   226        - if not, get the library from the sysroot
   227          - if it's in sysroot/lib, copy it to dst_dir/lib
   228          - if it's in sysroot/usr/lib, copy it to dst_dir/usr/lib
   229          - in both cases, use the SONAME of the library to create the file
   230            in dst_dir
   231          - if it was not found in the sysroot, this is an error.