@@ -32,6 +32,382 @@ available.
3232C/C++ toolchains
3333----------------
3434
35+ Before delving into the details, some definitions are necessary. The basement layer
36+ uses the same terms that were establisdhed by the autoconf project. In principle, three
37+ different systems are distinguished:
38+
39+ The *build * system
40+ This is the system where the build is executed, i.e. where Bob and the
41+ compiler is running. The ``AUTOCONF_BUILD `` variable describes the build
42+ system and is always defined.
43+
44+ The *host * system
45+ The host system is where the compiled binaries are meant to be executed.
46+ For embedded build systems, this is sometimes called the "target" system.
47+ The ``AUTOCONF_HOST `` variable represents this system. If set and different
48+ than ``AUTOCONF_BUILD ``, the package is cross compiled.
49+
50+ The *target * system
51+ This system is only applicable to compilers and their related tools. It is
52+ stored in the ``AUTOCONF_TARGET `` variable. It describes the system for
53+ which the compiler produces the object code. For a cross-compiler, the
54+ *target * system is different from the *host * system where the compiler is
55+ executed. Of *build * and *target * system are identical, it is called a
56+ native compiler.
57+
58+ The different systems are described as a so-called *target triplet *. Even
59+ though it is used ubiquitously, it is only loosely defined. In fact, it may not
60+ even have exactly three fields as the name suggests. It generally has the
61+ format of ``arch-vendor-system `` where ``system `` may either be the ``os ``
62+ (operating system) or ``kernel-os ``. See the `autoconf documentation
63+ <https://autotools.info/autoconf/canonical.html> `_.
64+
65+ In almost all cases, projects will use cross compilation. This is even the case
66+ where the build system and the host system have the same architecture and
67+ operating system. The rationale is to be as independent from the build system
68+ as possible. Using native compiler always has the drawback that the result
69+ relies at least on the libc of the build system and is thus not portable across
70+ machines.
71+
72+ Selecting a C/C++-toolchain
73+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
74+
75+ To select the desired toolchain, add a dependency in the following format early
76+ in your project dependency list::
77+
78+ depends:
79+ - name: <toolchain name here>
80+ use: [tools, environment]
81+ forward: True
82+
83+ The following toolchains are predefined for commonly used target systems:
84+
85+ * ``devel::cross-toolchain-aarch64-linux-gnu ``: ARMv8-A AArch64 Linux with glibc.
86+ * ``devel::cross-toolchain-aarch64-none-elf ``: ARMv8-A/R AArch64 bare metal
87+ toolchain with newlib libc.
88+ * ``devel::cross-toolchain-arm-linux-gnueabihf ``: ARMv7-A Linux with glibc. Hard
89+ floating point ABI.
90+ * ``devel::cross-toolchain-arm-none-eabi ``: ARMv7 bare metal toolchain with
91+ newlib libc.
92+ * ``devel::cross-toolchain-x86_64-linux-gnu ``: x86_64 toolchain for Linux with glibc.
93+ * ``devel::cross-toolchain-riscv64-linux-gnu ``: RISC-V toolchain targeting the GC
94+ profile.
95+
96+ Read on to learn how to switch to different toolchains for selected
97+ dependencies or how to define your own if the standard ones are not sufficient.
98+
99+ All toolchains compile for a reasonable default architecture model that is
100+ supposed to be widely supported. To tweak the standard compile flags, the
101+ following variables may be optionally set when pulling in the toolchain.
102+
103+ ``BASEMENT_OPTIMIZE ``
104+ Compiler optimization level (``-O ``). Defaults to ``s `` to optimize for
105+ small binaries.
106+
107+ ``BASEMENT_DEBUG ``
108+ May be ``0 `` or ``1 `` and controls the generation of debugging information.
109+ Defaults to ``1 ``.
110+
111+ ``CROSS_TOOLCHAIN_CPU ``
112+ If set, adds an ``-mcpu= `` option to the compiler flags with the value. It
113+ overrides the default CPU selection of the toolchain.
114+
115+ ``CROSS_TOOLCHAIN_ARCH ``
116+ If set, adds an ``-march= `` option to the compiler flags with the value. It
117+ overrides the default architecture selection of the toolchain.
118+
119+ Standard tools
120+ ~~~~~~~~~~~~~~
121+
122+ There are two tools that are meant to be used by recipes that compile C/C++
123+ code.
124+
125+ ``target-toolchain ``
126+ This is the main toolchain. Every C/C++ package uses it. It represents the
127+ compiler that builds for the target system where the package should run in
128+ the end. Usually, but not necessarily, this is a cross compiler even on the
129+ same architecture.
130+
131+ A recipe should make no assumption about which compiler this is and for
132+ which architecture or operating system it compiles. This is the key
133+ ingredient for making Bob projects flexible because the
134+ ``target-toolchain `` may be replaced anywhere in the dependency tree and
135+ all dependencies beneath it will automatically be compiled for the
136+ configured target.
137+
138+ ``host-toolchain ``
139+ This toolchain represents the native host machine compiler. Even though it
140+ builds host executables, it does never :external:ref: `fingerprint
141+ <configuration-principle-fingerprinting>` the results. Instead, it is
142+ intended to be used in the ``buildScript `` if the package *also * needs the
143+ host compiler during build time where none of the host build object code is
144+ part of the result. Points to the host gcc or the gcc of the sandbox. Only
145+ selected packages need it when being built in the sandbox.
146+
147+ Given the above definitions, practically all recipes that build C/C++ code will do
148+ a::
149+
150+ buildTool: [target-toolchain]
151+
152+ to use the currently selected C/C++ compiler. Only if the build requires the
153+ native compiler too (e.g. to build some intermediate build tool),
154+ ``host-toolchain `` may be added to ``buildTool ``.
155+
156+ There are two other tools that are always defined. They are intended to be used
157+ at special places where they replace the ``target-toolchain `` for selected
158+ dependencies.
159+
160+ ``host-compat-toolchain ``
161+ A toolchain that builds portable host executables that should be able to
162+ run on the oldest supported Ubuntu LTS. Even though it builds for the host
163+ architecture and operating system, it is a cross compiler with a backwards
164+ compatible glibc version. When using the ``basement::rootrecipe `` class,
165+ this is the default ``target-toolchain ``. It is defined as a dedicated name
166+ to be able to compile specifically for the host when needed::
167+
168+ depends:
169+ - ...
170+ - name: some::package
171+ tools:
172+ target-toolchain: host-compat-toolchain
173+
174+ This will build ``some::package `` for the host regardless of the currently
175+ defined target toolchain. It comes in handy if some special tool is needed
176+ to compile a package.
177+
178+ ``host-native-toolchain ``
179+ This toolchain represents the native host machine compiler. In contrast to
180+ ``host-toolchain `` it *does * fingerprint the system. This implies that
181+ binary artifacts of such packages are not exchangeable between systems! It
182+ is used if a package needs to be compiled natively and the object code is
183+ part of the package result. Like in the ``host-compat-toolchain `` example
184+ above, it is usually supplied as ``target-toolchain `` for selected
185+ dependencies.
186+
187+ An example for the necessity of the ``host-native-toolchain `` is for
188+ example Python. To cross-compile python, the same version is required on
189+ the build system. Therefore, Python needs to be first compiled natively.
190+ Then Python can be cross compiled by whatever ``target-toolchain `` is
191+ configured. See the following excerpt from the ``basement::rootrecipe ``
192+ class where this is already done for you::
193+
194+ depends:
195+ - name: python::python3-minimal
196+ use: [tools]
197+ forward: True
198+ tools:
199+ # To build python3 a working python interpreter is required. Build
200+ # a bootstrap python3 interpreter with the native host toolchain.
201+ # The real interpreter is then built with the
202+ # host-compat-toolchain.
203+ target-toolchain: host-native-toolchain
204+
205+ - python::python3
206+
207+ Switching cross-compilers
208+ ~~~~~~~~~~~~~~~~~~~~~~~~~
209+
210+ Once a cross-compiling toolchain has been selected, all following dependencies
211+ are built by this compiler. As this applies to all packages, selecting a
212+ different cross compiler requires some special care. Suppose a root recipe has
213+ the following (intentionally incorrect!) dependency list::
214+
215+ inherit: ["basement::rootrecipe"]
216+ depends:
217+ - name: devel::cross-toolchain-aarch64-linux-gnu
218+ use: [tools, environment]
219+ forward: True
220+
221+ - utils::bash
222+
223+ - name: devel::cross-toolchain-arm-none-eabi
224+ use: [tools, environment]
225+ forward: True
226+
227+ - some::firmware
228+
229+ .. warning ::
230+ The example above does *not * work but is used as an illustration what needs
231+ to be considered.
232+
233+ The above example will unfortunately not work as expected. The reason is that after
234+ the ``devel::cross-toolchain-aarch64-linux-gnu `` dependency, *everything * will be
235+ compiled for Linux AArch64. This includes the ``devel::cross-toolchain-arm-none-eabi ``
236+ dependency too! But this compiler needs to be executed on the build system. Therefore,
237+ the ``target-toolchain `` used for the compiler needs to be replaced with the
238+ ``host-compat-toolchain ``::
239+
240+ depends:
241+ ...
242+ - name: devel::cross-toolchain-arm-none-eabi
243+ use: [tools, environment]
244+ forward: True
245+ tools:
246+ target-toolchain: host-compat-toolchain
247+
248+ - some::firmware
249+
250+ As you can see, the ``devel::cross-toolchain-arm-none-eabi `` is built
251+ explicitly with the ``host-compat-toolchain ``, regardless of which other
252+ toolchain is configured at this point.
253+
254+ Installing a compiler in the target system
255+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
256+
257+ Sometimes, the toolchain should be installed on the target system. This works
258+ like for any other package. The only difference is that the ``use `` list does
259+ not have the ``tools `` key because the compiler should be installed rather than
260+ used at build time::
261+
262+ inherit: ["basement::rootrecipe"]
263+ depends:
264+ # The toolchain for the target system
265+ - name: devel::cross-toolchain-aarch64-linux-gnu
266+ use: [tools, environment]
267+ forward: True
268+
269+ # The native compiler and binutils for the target system
270+ - devel::binutils
271+ - devel::gcc-native
272+
273+ The above example installs a native compiler into the target system. That is, this compiler
274+ will produce binaries for the same system. Similarly, a cross-compiler could be installed
275+ as well::
276+
277+ inherit: ["basement::rootrecipe"]
278+ depends:
279+ # The toolchain for the target system
280+ - name: devel::cross-toolchain-aarch64-linux-gnu
281+ use: [tools, environment]
282+ forward: True
283+
284+ - devel::cross-toolchain-arm-none-eabi
285+
286+ The toolchain will be compiled for the AArch64 Linux system and will produce
287+ object code for AArch32 bare-metal systems. Note the absence of the ``use:
288+ [tools, environment] `` and ``forward: True `` lines from the
289+ ``devel::cross-toolchain-arm-none-eabi `` dependency.
290+
291+ Advanced toolchain selection
292+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
293+
294+ If the pre-configured toolchains are not sufficient, it is possible to compile
295+ almost any custom GNU gcc/binutils based Linux toolchain. Starting point is
296+ the generic ``devel::cross-toolchain `` recipe. This unconfigured cross-compilation
297+ toolchain needs to be configured. At least the following variables need to be
298+ defined for it:
299+
300+ ``ARCH ``
301+ The target architecture. This is based on the architectures as defined by
302+ the Linux kernel. Valid choices are, among others, ``arm ``, ``arm64 ``,
303+ ``i386 ``, ``x86_64 `` or ``riscv ``. See the Linux kernel documentation for
304+ all possible values.
305+
306+ ``AUTOCONF_TARGET ``
307+ The autoconf target triplet that describes the system. This is the primary
308+ variable that affects the toolchain and needs to be aligned with the other
309+ switches. See below for some rough guidelines.
310+
311+ ``GCC_LIBC ``
312+ The C-library that should be used by the toolchain. Valid choices are
313+ ``glibc ``, ``newlib `` and ``uclibc-ng ``.
314+
315+ The following, additional variables are available to tweak the toolchain:
316+
317+ ``GCC_TARGET_ARCH ``
318+ This is passed as ``--with-arch= `` to the gcc configure script and provides
319+ the default value for the ``-march= `` gcc option. As such, it sets the
320+ default target architecture that the compiler is using. It is recommended
321+ to pass this switch to choose the right architectural features. See the
322+ `GCC machine dependent options
323+ <https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Submodel-Options.html> `_ for
324+ the supported values of the ``-march= `` option.
325+
326+ ``GCC_TARGET_ABI ``
327+ Passed as ``--with-abi= `` to the gcc configure script and provides the
328+ default value for the ``-mabi= `` option. This is used for example for
329+ RISC-V to choose between the different possible ABIs.
330+
331+ ``GCC_TARGET_FLOAT_ABI ``
332+ May be either ``hard `` or ``soft ``.
333+
334+ ``GCC_TARGET_FPU ``
335+ Passed as ``--with-fpu= `` to the gcc configure script and provides the
336+ default value for the ``-mfpu= `` option. Again, the acceptable values
337+ depend on the chosen target.
338+
339+ ``GCC_MULTILIB ``
340+ If set, provides the comma separated set of multilibs to build. The
341+ permissible values depend on the target architecture. Currently, the
342+ basement layer only supports ``m32,m64 `` on ``x86_64 ``.
343+
344+ ``GCC_ENABLE_LANGUAGES ``
345+ Comma separated list of languages that gcc should support. Defaults to
346+ ``c,c++ ``.
347+
348+ ``GCC_EXTRA_OPTIONS ``
349+ If set, it is passed verbatim to the gcc configure script.
350+
351+ TODO: Explain target triplet choices.
352+
353+ Standard variables for C/C++ packages
354+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
355+
356+ When using the ``target-toolchain ``, the following variables are available. The
357+ variables have the same name as the executable that is normally available on
358+ the build system.
359+
360+ * ``AR ``: The archiver to create/modify static libraries.
361+ * ``AS ``: The assembler.
362+ * ``CC ``: The C-compiler.
363+ * ``CPP ``: The C preprocessor.
364+ * ``CXX ``: The C++-compiler.
365+ * ``LD ``: The linker.
366+ * ``NM ``: Tool to inspect object symbol tables.
367+ * ``OBJCOPY ``: Tool to copy and translate object files.
368+ * ``OBJDUMP ``: Print object file contents.
369+ * ``RANLIB ``: Tool to (re-)generate symbol index of a static library.
370+ * ``READELF ``: Display information about ELF files.
371+ * ``STRIP ``: Tool for stripping unneeded sections and symbols from object files.
372+
373+ Other meta information variables that are not directly linked to a particular
374+ executable are:
375+
376+ * ``AUTOCONF_HOST ``: Set for cross-compiler to the *host * system target triplet.
377+ * ``CROSS_COMPILE ``: Cross compile prefix for standard tool of a
378+ cross-compiling toolchain, e.g., ``riscv64-linux-gnu- `` for a RISC-V Linux
379+ cross toolchain. Some build systems use this method to find the right tools
380+ instead of the individual variables above (``AR ``, ...).
381+
382+ .. attention ::
383+ The above variables are defined by ``target-toolchain `` only. If it is
384+ missing from ``buildTools ``, they will be undefined!
385+
386+ The following variables are not defined by ``target-toolchain `` but are part of
387+ the normal environment variables. The reason is that recipes should be able to
388+ amend or replace them at any place.
389+
390+ * ``CPPFLAGS ``: Preprocessor options, e.g., ``-DMACRO=definition ``.
391+ * ``CFLAGS ``: Compiler options that are used when compiling C-code.
392+ * ``CXXFLAGS ``: Compiler options that are used when compiling C++-code.
393+ * ``LDFLAGS ``: Options used when linking. Note that they are passed to the
394+ compiler driver (e.g., ``gcc `` or ``clang ``) and therefore need to be wrapped
395+ appropriately (e.g., ``-Wl,<option> `` in case of ``gcc `` or ``clang ``).
396+
397+ Feature variables
398+ ~~~~~~~~~~~~~~~~~
399+
400+ For some architectures, the cross compilation toolchains provide variables that
401+ indicate the available features of the selected target architecture. This
402+ information is derived from the toolchain defaults and any
403+ ``CROSS_TOOLCHAIN_ARCH `` and ``CROSS_TOOLCHAIN_CPU `` settings made.
404+
405+ * Arm: ``CPU_HAS_VFPV2 ``, ``CPU_HAS_VFPV3 ``, ``CPU_HAS_VFPV4 ``, ``CPU_HAS_NEON ``
406+ * Arm64: ``CPU_HAS_SVE ``, ``CPU_HAS_SVE2 ``, ``CPU_HAS_SME ``
407+ * x86_64: ``CPU_HAS_SSE3 ``, ``CPU_HAS_SSSE3 ``, ``CPU_HAS_SSE41 ``,
408+ ``CPU_HAS_SSE42 ``, ``CPU_HAS_AVX ``, ``CPU_HAS_AVX2 ``, ``CPU_HAS_AVX512 ``. All
409+ CPU features before and including SSE2 are implicitly assumed to be present.
410+
35411Standard build systems
36412----------------------
37413
0 commit comments