[Picolibc] Integrating Picolibc into a GCC toolchain

R. Diez rdiezmail-newlib at yahoo.de
Mon Jan 24 07:55:53 PST 2022


> [...]
> This is the preferred technique; the compiler flags set in that file are
> only those which are target-specific and not required by picolibc
> itself; anything picolibc requires would be set in the picolibc
> meson.build files instead.

Thanks for your help. Unfortunately, I find your suggested solution unsatisfactory.

The makefile I have been using for years strikes a good compromise between complexity, hackability and performance.

It downloads Binutils, GMP, MPFR, MPC, GCC, Newlib and GDB and builds a toolchain suitable for a deeply embedded (bare metal) ARM Cortex-Mx target.

It applies one patch to disable the C++ exception emergency buffer, saving quite a lot of RAM, and another one to allow fine control of the assert() code size. It allows exact control of the target compiler flags. And it is relatively easy to adjust the makefile to your needs, as most bare metal targets will probably be very similar, regarding of the actual CPU. In fact, I have used a very similar makefile for a PowerPC target.

The resulting toolchain has just 1 target and 1 libc. There are no special tricks and little room for errors.

In comparison, crosstool-ng is a monster that you have to understand first. I haven't looked much yet, but I am guessing that part of the complexity comes from supporting toolchains intended for Linux targets. If the resulting toolchain has more than 1 libc, that is asking for trouble. I find crosstool-ng yet another hurdle to do bare-metal development.

Pre-built toolchains are problematic. You do not have full control of the flags with which the libc and libstdc++ are built, and are at the mercy of the publisher. For example, if you use a Debian pre-built ARM toolchain, you are then tied to Debian.

The Newlib build system is based on the Autotools and is problematic, partly because the Autotools are a pain. But at least the interface to build Newlib is sane as far as the user is concerned:

- You set CFLAGS_FOR_TARGET (and perhaps CXXFLAGS_FOR_TARGET just in case).
- You call ./configure with the usual --prefix and --target option, along with Newlib-specific options like --disable-newlib-multithread.
- The usual "make && make install" will generate files that GCC can use directly (when building a GCC-based cross-compilation toolchain).

I do not understand how a modern build system like Meson still does not support anything as basic as CFLAGS_FOR_TARGET.

You say that scripts/cross-arm-none-eabi.txt is supposed to be just an example. But if I have to generate my own file, it is not as straightforward as passing arguments to a configuration script. It is just another hurdle.

But let's look at that file's contents:

----------8<----------8<----------8<----------

[binaries]
c = 'arm-none-eabi-gcc'
ar = 'arm-none-eabi-ar'
as = 'arm-none-eabi-as'
nm = 'arm-none-eabi-nm'
strip = 'arm-none-eabi-strip'
exe_wrapper = ['sh', '-c', 'test -z "$MESON_SOURCE_ROOT" || "$MESON_SOURCE_ROOT"/scripts/run-arm "$@"', 'run-arm']

[host_machine]
system = 'none'
cpu_family = 'arm'
cpu = 'arm'
endian = 'little'

[properties]
c_args = [ '-nostdlib', '-fno-common']
needs_exe_wrapper = true
skip_sanity_check = true

----------8<----------8<----------8<----------

You may argue that c_args and [host_machine] may be passed (or generated) from outside.

"skip_sanity_check = true" may well fall in that category, although it could be a default, because most people will not have a simulator ready when configuring a cross-compilation toolchain. If a simulator is available, "exe_wrapper" should probably be passed (or generated) from outside too.

But things like  c = 'arm-none-eabi-gcc' should be auto-detected by the Meson build, because those variables are used by the rest of the Picolibc build system (they are an implementation detail). Tomorrow, Picolibc may decide that it needs some other arm-none-eabi-xxx tool, and then my generated scripts/cross-arm-none-eabi.txt will fail (or be Picolibc version dependent). That is, I should pass "arm-none-eabi" to the Meson build system, and then it should find all such arm-none-eabi-xxx tools itself, like Autoconf's 'configure' does.

Therefore, I think it would be best to split scripts/cross-arm-none-eabi.txt into 2 parts: one part should have the standard definitions for Picolibc, and maybe some defaults for the other options, and the other part should be overridable (generated by the user, if passing command-line arguments is not enough, which it should be).


Delving into crosstool-ng is going to cost me a lot of time. Could you tell me why it is not possible to replace just Newlib with Picolibc when building a simple toolchain with a makefile like mine?

The same question in more detail: My makefile builds a first GCC cross-compiler (without any libc, only C), and then it uses it to build and install Newlib. The second GCC cross-compiler (fully featured with libc, C and C++) will then find and use those files installed by Newlib, namely arm-none-eabi/lib/libc.a, libm.a and libg.a . Can I make Picolibc build and install equivalents for those files (and the corresponding header files under include/), so that no Newlib is needed anymore?


Regards,
   rdiez


More information about the Picolibc mailing list