crosstool-NG Internals
Internally, crosstool-NG is script-based. To ease usage, the frontend is Makefile-based.
Makefile front-end
The entry point to crosstool-NG is the Makefile script ct-ng
. Calling
this script with an action will act exactly as if the Makefile was in
the current working directory and make was called with the action as
rule. Thus:
ct-ng menuconfig
is equivalent to having the Makefile in CWD
, and calling:
make menuconfig
Having ct-ng as it is avoids copying the Makefile everywhere, and acts as a traditional command.
ct-ng loads sub- Makefiles from the library directory $(CT_LIB_DIR)
,
as set up at configuration time with ./configure
.
ct-ng also searches for config files, sub-tools, samples, scripts and patches in that library directory.
Because of a stupid make behavior/bug I was unable to track down,
implicit make rules are disabled: installing with --local
would
trigger those rules, and mconf was unbuildable.
Kconfig parser
The kconfig language is a hacked version, vampirised from the Linux kernel, and (heavily) adapted to my needs.
The list of the most notable changes (at least the ones I remember) follows:
-
the
CONFIG_
prefix has been replaced withCT_
-
a leading
|
in prompts is skipped, and subsequent leading spaces are not trimmed; otherwise leading spaces are silently trimmed -
removed the warning about undefined environment variable
The kconfig parsers (conf and mconf) are not installed pre-built, but as source files. Thus you can have the directory where crosstool-NG is installed, exported (via NFS or whatever) and have clients with different architectures use the same crosstool-NG installation, and most notably, the same set of patches.
Architecture-specific
Note
this chapter is not really well written, and might thus be a little bit complex to understand. To get a better grasp of what an architecture is, the reader is kindly encouraged to look at the
arch/
sub-directory, and to the existing architectures to see how things are laid out.
An architecture is defined by:
-
a human-readable name, in lower case letters, with numbers as appropriate; underscore is allowed; space and special characters are not, e.g.:
arm x86_64
-
a file in
config/arch/
, named after the architecture’s name, and suffixed with.in
, e.g.:config/arch/arm.in
-
a file in
scripts/build/arch/
, named after the architecture’s name, and suffixed with.sh
, e.g.:scripts/build/arch/arm.sh
The architecture’s .in
file API
Note
Here, and in the following,
%arch%
is to be replaced with the actual architecture name.
The ARCH_%arch%
option
This config option must have neither a type, nor a prompt! Also, it can not depend on any other config option.
EXPERIMENTAL
is managed as in kernel options ?.
A (terse) help entry must be defined for this architecture, e.g.,
config ARCH_arm
help
The ARM architecture.
Adequate associated config options may be selected, e.g.,
config ARCH_arm
select ARCH_SUPPORTS_BOTH_ENDIAN
select ARCH_DEFAULT_LE
help
The ARM architecture.
Note
64-bit architectures shall select
ARCH_64
.
config ARCH_x86_64
select ARCH_64
help
The x86_64 architecture.
Other target-specific options
At your discretion. Note however that to avoid name-clashing, such
options shall be prefixed with ARCH_%arch%
.
Note
Due to historical reasons, and lack of time to clean up the code, I may have left some config options that do not completely conform to this, as the architecture name was written all upper case. However, the prefix is unique among architectures, and does not cause harm).
The architecture’s .sh
file API
-
the function
CT_DoArchTupleValues
-
parameters: none
-
environment:
-
all variables from the
.config
file, -
the two variables
target_endian_eb
andtarget_endian_el
which are the endianness suffixes
-
-
return value:
0
upon success,!0
upon failure -
provides:
-
environment variable
CT_TARGET_ARCH
(mandatory)- contains: the architecture part of the target tuple,
e.g.
armeb
for big endian ARM, ori386
for an i386
- contains: the architecture part of the target tuple,
e.g.
-
environment variable
CT_TARGET_SYS
(optional)-
contains: the system part of the target tuple, e.g.,
gnu
for glibc on most architectures, orgnueabi
for glibc on an ARM EABI -
defaults to:
-
gnu
for glibc-based toolchain -
uclibc
for uClibc-based toolchain
-
-
-
environment variables to configure the cross-gcc (defaults) (optional)
gcc ./configure switch selects default CT_ARCH_WITH_ARCH
architecture level --with-arch=${CT_ARCH_ARCH}
CT_ARCH_WITH_ABI
ABI level --with-abi=${CT_ARCH_ABI}
CT_ARCH_WITH_CPU
CPU instruction set --with-cpu=${CT_ARCH_CPU}
CT_ARCH_WITH_TUNE
scheduling --with-tune=${CT_ARCH_TUNE}
CT_ARCH_WITH_FPU
FPU type --with-fpu=${CT_ARCH_FPU}
CT_ARCH_WITH_FLOAT
floating point arithm. --with-float=soft
or [empty] -
environment variables to pass to the cross-gcc to build target binaries (defaults) (optional)
gcc ./configure switch selects default CT_ARCH_ARCH_CFLAG
architecture level -march=${CT_ARCH_ARCH}
CT_ARCH_ABI_CFLAG
ABI level -mabi=${CT_ARCH_ABI}
CT_ARCH_CPU_CFLAG
CPU instruction set -mcpu=${CT_ARCH_CPU}
CT_ARCH_TUNE_CFLAG
scheduling -mtune=${CT_ARCH_TUNE}
CT_ARCH_FPU_CFLAG
FPU type -mfpu=${CT_ARCH_FPU}
CT_ARCH_FLOAT_CFLAG
floating point arithm. -msoft-float
or [empty]CT_ARCH_ENDIAN_CFLAG
big or little endian -mbig-endian
or-mlittle-endian
-
the environment variables to configure the core and final compiler, specific to this architecture (optional):
-
CT_ARCH_CC_CORE_EXTRA_CONFIG
: additional, architecture specific coregcc ./configure
flags -
CT_ARCH_CC_EXTRA_CONFIG
: additional, architecture specific finalgcc ./configure
flags -
default to: all empty
-
-
the architecture-specific
CFLAGS
andLDFLAGS
(optional):-
CT_ARCH_TARGET_CLFAGS
-
CT_ARCH_TARGET_LDFLAGS
-
default to: all empty
-
-
-
You can have a look at config/arch/arm.in
and scripts/build/arch/arm.sh
for a quite complete example of what an actual architecture description
looks like.
Kernel specific
A kernel is defined by:
-
a human-readable name, in lower case letters, with numbers as appropriate; underscore is allowed, space and special characters are not (although they are internally replaced with underscores); e.g.:
linux bare-metal
-
a file in
config/kernel/
, named after the kernel name, and suffixed with.in
, e.g.:config/kernel/linux.in config/kernel/bare-metal.in
-
a file in
scripts/build/kernel/
, named after the kernel name, and suffixed with.sh
, e.g.:scripts/build/kernel/linux.sh scripts/build/kernel/bare-metal.sh
The kernel’s .in
file must contain:
-
an optional line containing exactly
# EXPERIMENTAL
, starting on the first column, and without any following space or other character.If this line is present, then this kernel is considered
EXPERIMENTAL
, and correct dependency onEXPERIMENTAL
will be set. -
the config option
KERNEL_%kernel_name%
(where%kernel_name%
is to be replaced with the actual kernel name, with all special characters and spaces replaced by underscores), e.g.:KERNEL_linux KERNEL_bare_metal
This config option must have neither a type, nor a prompt! Also, it can not depends on
EXPERIMENTAL
.A (terse) help entry for this kernel must be defined, e.g.:
config KERNEL_bare_metal help Build a compiler for use without any kernel.
Adequate associated config options may be selected, e.g.:
config KERNEL_bare_metal select BARE_METAL help Build a compiler for use without any kernel.
-
other kernel specific options, at your discretion. Note however that, to avoid name-clashing, such options should be prefixed with
KERNEL_%kernel_name%
, where%kernel_name%
is again to be replaced with the actual kernel name.
Note
Due to historical reasons, and lack of time to clean up the code, Yann may have left some config options that do not completely conform to this, as the kernel name was written all upper case. However, the prefix is unique among kernels, and does not cause harm).
The kernel’s .sh
file API:
-
is a bash script fragment
-
defines function
CT_DoKernelTupleValues
-
see the architecture’s
CT_DoArchTupleValues
, except for: [FIXME?] -
set the environment variable
CT_TARGET_KERNEL
, the kernel part of the target tuple -
return value: ignored
-
-
defines function
do_kernel_get
:-
parameters: none
-
environment:
- all variables from the
.config
file.
- all variables from the
-
return value:
0
for success,!0
for failure. -
behavior: download the kernel’s sources, and store the tarball into
${CT_TARBALLS_DIR}
. To this end, a function is available that abstracts downloading tarballs:-
CT_DoGet <tarball_base_name> <URL1 [URL...]>
, e.g.:CT_DoGet linux-2.6.26.5 ftp://ftp.kernel.org/pub/linux/kernel/v2.6
Note
Retrieving sources from SVN, CVS, git and the likes is not supported by
CT_DoGet
. You’ll have to do this by hand, as it is done for eglibc inscripts/build/libc/eglibc.sh
.
-
-
-
defines function
do_kernel_extract
:-
parameters: none
-
environment:
- all variables from the
.config
file,
- all variables from the
-
return value:
0
for success,!0
for failure. -
behavior: extract the kernel’s tarball into
${CT_SRC_DIR}
, and apply required patches. To this end, a function is available that abstracts extracting tarballs:-
CT_ExtractAndPatch <tarball_base_name>
, e.g.:CT_ExtractAndPatch linux-2.6.26.5
-
-
-
defines function
do_kernel_headers
:-
parameters: none
-
environment:
- all variables from the
.config
file,
- all variables from the
-
return value:
0
for success,!0
for failure. -
behavior: install the kernel headers (if any) in
${CT_SYSROOT_DIR}/usr/include
-
-
defines any kernel-specific helper functions
These functions, if any, must be prefixed with
do_kernel_%CT_KERNEL%_
, where%CT_KERNEL%
is to be replaced with the actual kernel name, to avoid any name-clashing.
You can have a look at config/kernel/linux.in
and
scripts/build/kernel/linux.sh
as an example of what a complex kernel
description looks like.
Adding a new version of a component
When a new component, such as the Linux kernel, gcc or any other is released, adding the new version to crosstool-NG is quite easy. There is a script that will do all that for you:
maintainer/manager-packages.sh
Run it with --help
to get some help.
Build scripts
[To Be Written later…]