docs/5 - Using the toolchain.txt
author "Yann E. MORIN" <yann.morin.1998@free.fr>
Sun May 05 18:34:20 2013 +0200 (2013-05-05)
changeset 3212 4c0d4394d0b0
parent 2764 986e90e1ca27
permissions -rw-r--r--
scripts: help debugging missing directories

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