[Picolibc] Integrating Picolibc into a GCC toolchain

Keith Packard keithp at keithp.com
Mon Jan 24 13:53:57 PST 2022


"R. Diez" <rdiezmail-newlib at yahoo.de> writes:

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

I cannot fault your goals here, and picolibc should be up to the
task. If not, we'll figure out how to make it work.

> 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.

Yes, crosstool-ng is an adventure; I pointed to that not to suggest that
you use it but as an example of a toolchain construction mechanism that
generates the meson cross-compilation file from values defined in its
own configuration.

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

It does, but not using command line options. All of those settings land
in the cross compilation definitions file.

> 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.

It's certainly different, which means it's more work for you right now.

>
> 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.

crosstool-ng creates this from the following template:

	cat << EOF > picolibc-cross.txt
[binaries]
c = '${CT_TARGET}-gcc'
ar = '${CT_TARGET}-ar'
as = '${CT_TARGET}-as'
strip = '${CT_TARGET}-strip'

[host_machine]
system = '${CT_TARGET_VENDOR}'
cpu_family = '${CT_TARGET_ARCH}'
cpu = '${CT_TARGET_ARCH}'
endian = '${CT_ARCH_ENDIAN}'

[properties]
c_args = [ ${meson_cflags} '-nostdlib', '-fno-common', '-ftls-model=local-exec' ]
needs_exe_wrapper = true
skip_sanity_check = true
EOF

> "skip_sanity_check = true" may well fall in that category,

That one is required for any toolchain building step as the meson sanity
checks try to link a simple program with a simplistic command line,
which requires libc.

> If a simulator is available, "exe_wrapper" should probably be passed
> (or generated) from outside too.

Yes, if you want to run tests during the build (something newlib can't
do at all). And, the whole 'exe_wrapper' adventure is something I've
been working to improve with meson upstream. They're completely on-board
with cross-compilation, and the support is amazing. But, embedded
development remains a bit of a mystery to them.

> 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).

No, these values come from your toolchain and would be set by you, just
as they are when building with autotools. The only difference with
autotools is that you set the triplet and the build system figures out
the tool names from that. You can see from the fragment above that
crosstool-ng sets CT_TARGET and that is used to create names for all of
the tools in the script.

> 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.

These names aren't picolibc specific; they're meson specific, and yes,
meson could start using some other tool, but it hasn't ever done so.

> 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).

I don't think that's necessary; the build system for picolibc has been
pretty stable once I got things sorted out a couple of years ago. In
fact, looking at the commit history for cross-arm-none-eabi.txt shows a
single change that would have affected how your files would be
generated, and that was to add the 'nm' tool which is used to verify
that picolibc doesn't insert duplicate definitions of any symbol into
the library.

> 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?

I'm hoping to convince you that it *is* possible, just that instead of
passing command line arguments, you need to generate a cross-compilation
configuration file to pass the toolchain-specific values to meson.

> 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 .

I haven't even been bothering with this second pass -- the only piece of
gcc which uses libc is libstdc++, so I only build that library after
building libc, instead of re-building the whole compiler.

> 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?

You should be able to make this work; realize that you'll need a newer
version of gcc that includes the '--enable-stdio=stdio_pure'
configuration option (gcc 10 or newer, I think).

I've just built a full toolchain using crosstool-ng with only picolibc
support and then built and ran the hello-world and hello-worldpp
examples found in picolibc to demonstrate that this can be done, at
least using that mechanism.

-- 
-keith
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://keithp.com/pipermail/picolibc/attachments/20220124/e16e6036/attachment.sig>


More information about the Picolibc mailing list