I am trying to understand how exactly the concept of toolchain for embedded Linux systems is used/being practiced in the Yocto project but find myself confused.
To start with, what I DO understand about toolchains in embedded systems in general (not necessarily in Yocto project's context), is that a toolchain, high level speaking, is a set of tools (utilities), libraries, configurations, etc... that are used to build at the "first phase", the required "system" software that will be deployed and used on the target machine i.e.- the Linux kernel, relevant/required kernel modules (in source-tree), glibc
(or some other C library) - which acts as an interface between the kernel and user space applications, while also, and perhaps at a later stage, i.e. - at the "second phase", the toolchain will be used to build all sort of other packages (3rd party or proprietary) and some user space applications (for example, some proprietary C/C++ user space application that runs and display to the console "Hello World!"
). The separation for these two phases allows to have several teams to work on the embedded system in parallel (i.e. - the first phase is typically done by some BSP/OS team and the application development that are hosted on the OS, are done, typically, by another team, during the second phase).
Typical tools of a toolchain are usually (not limited to): gcc/g++
, binutils
, and some other "build related" utilities. In addition there are also the kernel headers and glibc
.
When dealing with toolchains, there is the concept of cross-compilation off course, for example, host is X86_64
architecture based and target is ARM architecture based.
In my case, I perform cross-compilation by having the host machine as an X86_64
machine with Ubuntu 20.04 (with gcc
9.4.0 and glibc
2.31) and the target machine ALSO being an X86_64
with some other Linux flavor that will be used (Debian based, but not Ubuntu).
In my Yocto version (mickledore) I use, under the layers/oe-core/meta/recipes-devtools/gcc/
folder, there are (in addition to others that are not mentioned) the following recipes:
gcc-cross-canadian.inc gcc-crosssdk.inc gcc_12.3.bb gcc-12.3.inc gcc-cross-canadian_12.3.bb gcc-crosssdk_12.3.bb gcc-common.inc gcc-cross.inc gcc-configure-common.inc gcc-cross_12.3.bb
My intuition tells me these recipes are divided as follows:
gcc-12.3*
- are responsible for building thegcc
that will be deployed and hosted on the target machine (if it is relevant of course, because many, if not all embedded system are not meant to act as a host/build machine).gcc-cross*
- are responsible for building thegcc
that will be used for cross compilation, just like in my case (in which the host and target machine even though are both X86_64, are not the same machine - so the cross compiler is needed)gcc-cross-canadian*
- are responsible for building thegcc
that will be used for cross compilation in the case of cross-canadian buildgcc-cross-sdk*
- are responsible for building thegcc
that will be used for cross compilation for other applications that will be built using the SDK that Yocto can provide (i.e. - when I will build my image as follows:bitbake <my_image> -c populate_sdk
)
One of the features (advantages) of the Yocto project as an holistic "build system" is that during the build of some image, Yocto first builds its own toolchain that will be used tobuild (mainly compile) the packages that will be installed on the image's root file system.
When examining the BitBake logs during the build, and grep
-ing for do_compile
, indeed the first packages I see that are being built are packages that are related/part of a toolchain, such as: gcc
, glibc
, autoconf
, kern-tools
, pkconfig
, patch
and many more, while only at a later stage, other "concrete" packages (i.e. - that are running on the target system, for example, openssh
) and proprietary applications are being built.
This of course, make sense due to the above feature of Yocto project that was mentioned earlier.
Taking into account the following, my questions are:
Are my assumptions about the role of the different
gcc-xxx
recipes is correct? If not, what is wrong?When further examining the BitBake logs during the build, and
grep
-ing fordo_compile
, I noticed that when I build the image itself, i.e. - when I run the command:bitbake <my_image>
, I see BitBake tasks for thegcc
andgcc-cross
recipes. However, when I do the same for the SDK for this image, i.e. - when I run the command:bitbake <my_image> -c populate_sdk
- I see BitBake tasks for thegcc-crosssdk
,gcc-cross-canadian
andgcc-cross
recipes.
If the gcc-cross
is being built during the actual image creation, why is it ALSO being built for the SDK? What is the difference between the gcc-cross
and gcc-crosssdk
? I would expect that during the SDK creation only the gcc-cross-canadian
and gcc-crosssdk
will be built.
For the
binutils
, which is also a mandatory package for the build procedure, I also see recipes forcross
,crosssdk
andcross-canadian
, like for thegcc
tool. However, when looking at the BitBake build logs, for both the actual image and the SDK, in both cases I see tasks that are related only for thebinutils-cross
andbinutils
BUT NOT of thebinutils-crosssdk
- why is it different from thegcc
case?If I do not wish to have the
gcc
executable (and other related "artifacts" of thegcc
recipe) to be part of my final image, how do I remove it? When I simply triedIMAGE_INSTALL_REMOVE += "gcc"
--> did not have any impact (i.e., thegcc
executable and the other related files are still present on my image root file system).