GCC: separation of language frontends and the -print-prog-name option

Backgrounds: coreboot uses its cross-toolchain for i386-elf, arm-eabi, etc. built from source, including the Ada frontend (GNAT). GNAT itself is written in Ada, so an Ada non-cross compiler is required to make the cross-toolchain.

The build system of coreboot contains a sequence of commands that is equivalent to the following one to check if Ada support is usable:

 [ -x "$(${CC} -print-prog-name=gnat1)" ] &&
    command -v gnatbind 2>/dev/null &&
    [ "$(cat /dev/null |
         gnatbind --version 2>&1 |
         grep -c 'Free Software Foundation')" -gt 0 ]

[ -x "$(${CC} -print-prog-name=gnat1)" ] checks if the toolchain supports Ada and it recognizes the frontend of the language. It may detect some situations triggering strange bugs where the environment provides a potentially incompatible combination of gcc and gnat.
For instance, the system administrator may install a full set of GCC 5 provided by the distribution in /usr/bin while a developer builds C and C++ frontends of GCC 11, installs to ~/tools and adds PATH="$HOME/tools/bin:$PATH" to their .profile.

While the command works with typical systems where cc1, cc1plus, gnat1, and so on are installed to the same directory, the implication does not hold on nixpkgs because frontends are built separately and installed in different places.

The -print-prog-name (and -x <language>) options are documented interfaces of GCC, but it does not fit well with nixpkgs in the current form. An overhaul of toolchain-related packages would be needed, but is it feasible?
How could the packages be built and split to work correctly without wasting everyone’s disk space too much?

Related issue on GitHub:
https://github.com/NixOS/nixpkgs/issues/24708

I am still a fan of keeping things separate, and just patching things like this. I would break GCC up further (separate libraries and compiler itself) if I had the time.

1 Like

Thank you for sharing your opinion, @Ericson2314!

I strongly agree with you on split components in GCC and another issue on bootstrapping a toolchain. On the other hand, I, as you probably do, prefer less duplication both in builds (wastes resources on build clusters) and in results (wastes resources on distribution sites and deployed systems).

I want a solution to my problem, the behavior of -print-prog-name with GNAT, of course. However, toolchain packages are essential for distributions so the solution should not become a dirty and fragile piece of such components. Will such patching increase maintainance cost noticeably?

Yeah I would think there would be like a PROG_AC (Ada compiler?) from coreutils or similar configure mechanism this stuff should use instead.

${CC} -print-prog-name=gnat1 just seems like the wrong way to do things — say GNAT is being built with a different Ada compiler?

Current configure.ac of GCC requires GNAT to build GNAT, so we don’t need to care non-GNAT Ada compilers.
Moreover, to build GNAT, object files compiled from C (actually C++ nowadays) sources and ones from Ada sources must be compatible enough to link together, which means that the C(++) and Ada compilers to be used are required to match ABIs.

Thus, it makes sense to check if the C compiler recognizes gnat1. While Autotools-like try-to-compile-and-execute style detection will work if implemented correctly, it is not trivial. It might be acceptable to let users use GNAT whatever they provide and hope it will fail during builds, though.