How to specify Ada runtime with GPRbuild

I have a runtime installed at this location:

$ ls -1 ${HOME:?}/bare_runtime
adainclude
adalib

I can build object files if I invoke GCC cross-compiler directly and specify the path to runtime:

$ ${HOME:?}/gcc-15.2.0_sparc64-unknown-elf/bin/sparc64-unknown-elf-gcc -c bit_ops.adb --RTS=${HOME:?}/bare_runtime
$ file bit_ops.o
bit_ops.o: ELF 64-bit MSB relocatable, SPARC V9, relaxed memory ordering, version 1 (SYSV), not stripped

However this does not work when using GPRbuild with a specific config file:

$ PATH="${HOME:?}/gcc-15.2.0_native/bin:${HOME:?}/gcc-15.2.0_sparc64-unknown-elf/bin" gprbuild -P libdsa.gpr --config=sparc64-unknown-elf.cgpr --RTS=${HOME:?}/bare_runtime
warning: runtimes are taken into account only in auto-configuration
libdsa.gpr:7:17: warning: there are no sources of language "C" in this project
Compile
   [Ada]          bit_ops.adb
fatal error, run-time library not installed correctly
cannot locate file system.ads
compilation abandoned
gprbuild: *** compilation phase failed

I suspect the warning is telling me if I use --config= option, then --RTS= option is ignored. I tried setting for Runtime_Dir (“Ada”) use “<path_to_runtime>” in .cgpr file but that did not seem to help.

Any ideas how to tell GPRbuild where to find this runtime?

Why do you need --config=sparc64-unknown-elf.cgpr?

Because it tells GPRbuild where and how to locate my bare metal cross-compiler. Without it GPRbuild produces these errors:

$ PATH="${HOME:?}/gcc-15.2.0_native/bin:${HOME:?}/gcc-15.2.0_sparc64-unknown-elf/bin" gprbuild -P libdsa.gpr --target=sparc64-unknown-elf --RTS=${HOME:?}/bare_runtime
gprconfig: can't find a toolchain for the following configuration:
gprconfig: language 'ada', target 'sparc64-unknown-elf', runtime '/home/user/bare_runtime'
libdsa.gpr:7:17: warning: there are no sources of language "C" in this project
libdsa.gpr:9:33: warning: libraries are not supported on this platform
libdsa.gpr:7:17: no compiler for language "Ada", cannot compile "bit_ops.ads"
gprbuild: *** compilation phase failed

The only way I managed to work around it is by copying runtime files to:

${HOME}/gcc-15.2.0_sparc64-unknown-elf/lib/gcc/sparc64-unknown-elf/15.2.0/adainclude
${HOME}/gcc-15.2.0_sparc64-unknown-elf/lib/gcc/sparc64-unknown-elf/15.2.0/adalib

these paths seem to be hardcoded to default locations when looking for a runtime. Ideally I want to find a way to specify the runtime explicitly in a different location, as I want to experiment with different runtimes.

Am I missing something or GPRbuild is just not flexible enough to locate the runtime via --RTS= command line option or the equivalent Runtime project option?

The --RTS= should be working… However, pointing the linker to the appropriate rts (libgnat.a) is also okay as seen in the Ironclad kernel build script: First filename). Third.

I hope it helps,
Fer

Anyone knows the rationale for why GPRbuild ignores --RTS= option when used with --config= option? Because if the alternative is to use Runtime_Dir in *.cgpr file, well that option also seems to be ignored.

Because configuration is provided. Otherwise, gprconfig is called by gprbuild to create configuration automatically.

If Runtime_Dir doesn’t do its work, it means there is no runtime recognized at given path.

Runtime from the gprbuild point of view is more than couple of directories.

Can you elaborate on what directory structure Ada runtime is supposed to have? As I mentioned previously, the runtime is found correctly by Ada compiler in the same adainclude and adalib sub-directories, provided they are located under ${HOME}/gcc-15.2.0_sparc64-unknown-elf/lib/gcc/sparc64-unknown-elf/15.2.0/.

If I want to change the base directory of the runtime via Runtime_Dir in *.cgpr file, the GPRbuild fails to do that. When using verbose command line option, there is no indication of why or how this happens. Are there any other options to print which runtime directories are searched by the compiler?

I suggest you to debug why gprconfig can’t find your runtime and then use gprbuild as usual without .cgpr. To do this run

gprbuild -vh --RTS=… -P project.gpr

Find gprconfig command arguments and run it with verbose options (two -v if don’t mistake). Gprconfig will print its search actions, so you will understand why it can’t find your compiler/runtime combination.

If you need custom gprconfig entries for your runtime, then you can put them in runtime.xml alongside to adalib/adaincude folders, like this

https://github.com/AdaCore/bb-runtimes/blob/c1d74b17297ecaddb72670f7d1639e1bcec3d065/arm/rm48/runtime.xml

I tried to debug it before, see this thread: https://forum.ada-lang.io/t/gprconfig-for-bare-metal-target/4409

I’m not sure how GNAT Pro build their cross-compilers, but I’m building a bare metal sparc64 cross-compiler without any Ada runtime, which is also missing a few other tools like gnatls. I think gprconfig may be missing some logic to correctly identify such cross-compilers. It finds sparc64 C and Asm compilers, but refuses to find Ada compiler. There is no indication why. The Ada compiler is definitely there, because I can use it to build sparc64 object files, i.e. when building Ada runtime. This is the reason I had to create a custom *.cgpr file to workaround these issues.

I’m not sure if this is a bug with gprconfig or if there is a different strategy for building Ada cross-compilers. Following your suggestion, below is the command invoked by gprbuild:

PATH="${HOME:?}/gcc-15.2.0_native/bin:${HOME:?}/gcc-15.2.0_sparc64-unknown-elf/bin" \
  /home/user/gcc-15.2.0_native/bin/gprconfig -vv --batch \
  -o /tmp/out --target=sparc64-unknown-elf \
  --config=c,,,, --config=ada,,/home/user/bare_runtime,,
...
gprconfig: can't find a toolchain for the following configuration:
gprconfig: language 'ada', target 'sparc64-unknown-elf', runtime '/home/user/bare_runtime'

Can you (after make all) run this?

make cross-gnattools
make ada.all.cross

It should build <prefix>-gnatls

For an experiment you could create a dummy script (sparc64-unknown-elf-gnatls) like this:

#!/bin/bash
if [ "$1" == "-v" ] ; then
  echo "GNATLS 15.2.0"
fi

Now you need to teach gprconfig about sparc64 target. You can use a dirty hack for beginning:

  • Open ~/.local/share/alire/toolchains/gprbuild_25.0.1_9a2e6cfb/share/gprconfig/compilers.xml
  • Find this and append sparc64-.* after LONG-REGEXP before )?gnatls
  <compiler_description>
    <name>GNAT</name>
    <executable prefix="1">(LONG-REGEXP|sparc64-.*)?gnatls</executable>

Now if you run gprconfig -v -v --target=sparc64-unknown-elf --config=ada,,/path-to/runtime,,

gprconfig starts iterating $PATH. You should look for a line

Foreach compiler in /tmp/bin regexp=TRUE extra_dir=FALSE

where /tmp/bin corresponds to your compiler path in $PATH

Under this line gprconfig iterates compilers. you should scroll to the line

GNAT is candidate: filename=sparc64-unknown-elf-gnatls

Where GNAT corresponds to the section in compilers.xml you have edited before.

Then gprconfig will run your compiler and gnatls and match output with regexp in compilers.xml

      target: executing "sparc64-unknown-elf-gcc -dumpmachine" output="sparc64-unknown-elf
      target: grep matched="sparc64-unknown-elf"
      version: executing "sparc64-unknown-elf-gnatls -v --version" output="GNATLS 15.2.0
      version: grep matched="15.2"
      variables: executing "sparc64-unknown-elf-gcc -v" output="gcc version 15.2.0 (GCC)
      variables: grep matched="15.2.0"
      variables: executing "sparc64-unknown-elf-gcc -v" output="gcc version 15.2.0 (GCC)
      variables: grep matched="15"
      languages: constant := Ada

If all matches gprconfig starts looking with runtime and end up with the folder provided in the command line.

I hope you understand the idea. I’ve made this output having this dummy compiler (`sparc64-unknown-elf-gcc) in the PATH:

#!/bin/bash
if [ "$1" == "-dumpmachine" ] ; then
  echo "sparc64-unknown-elf"
elif [ "$1" == "-v" ] ; then
  echo "gcc version 15.2.0 (GCC)"
else
  echo "$*"
fi

I suggest you to rebuild the ccross-compiler with https://github.com/alire-project/GNAT-FSF-builds scripts. It full of Python code byt it shouldn’t be hard to patch it with an extra cross target.

For simplest runtime construction you could take a look at GitHub - Fabien-Chouteau/bare_runtime: Minimal Ada/SPARK run-time for embedded or other restricted targets · GitHub repo. It a bit outdated however.

Thanks for the tips, I think this helped me to resolve the issues. So looks like I was missing gmake -C gcc cross-gnattools step when building my cross-compiler. This built and installed several sparc64-unknown-elf-gnat* tools which were missing previously. I did not need to change gprconfig compilers.xml file, as it already contains .*-elf-.* pattern which should match my target.

Now running:

PATH="${HOME:?}/gcc-15.2.0_native/bin:${HOME:?}/gcc-15.2.0_sparc64-unknown-elf/bin" \
  gprbuild -P libdsa.gpr --target=sparc64-unknown-elf --RTS=${HOME:?}/bare_runtime

finds the runtime and generates object files.