ezwiebel
ezwiebel

Reputation: 31

How to link an externally built C library to Ada default runtime math services (sin, cos, etc.)?

I need to use an externally built C library doing some calculation with trigonometric services to my Ada program. I do it well using an stm32 bb runtime (SFP) but when trying to do the same in a native environment using the default Ada runtime, I end up with linking problems. Hope I can find some help here.

I tried several configurations of project files (gpr) solutions and I always end up with the same kind of linking error:

Memory region         Used Size  Region Size  %age Used/opt/gnat/gnat_native/bin/../libexec/gcc/x86_64-pc-linux-gnu/7.3.1/ld: /home/pulsar/repos/pulsar-software/something/lib_c/libC.a(something.o): in function `compute':
(.text+0xa5): undefined reference to `sin'
collect2: error: ld returned 1 exit status

Here is what I've got so far.

The C library build sequence is as follows (confirmed by the library provider):

$ gcc -c something.c -o something.o
$ ar -r libsomethingLib.a something.o

The C library gpr file something_lib_c.gpr:

library project Something_Lib_C is
   for Languages        use ("C");
   for Externally_Built use "true";
   for Source_Dirs      use ("src_c");
   for Library_Dir      use "lib_c";
   for Library_Name     use "somethingLib";
   for Library_Kind     use "static";
end Geocaging_Lib_C;

In the lib_c directory, I have the actual library libsomethingLib.a

In the src_c directory, I have the header API to use the C library (something.h):

#ifndef _GEOCAGING_H
#define _GEOCAGING_H

typedef struct something_s something_t;

extern void compute(something_t* const self);

#endif // _GEOCAGING_H

Then here is the Ada project file that wraps the C library something_lib.gpr:

with "something_lib_c.gpr";

project Something_Lib extends "../settings.gpr" is

   for Languages   use ("Ada");
   for Source_Dirs use ("./src_ada");
   for Object_Dir  use "obj" & "/" & Target & "/" & Build;

end Geocaging_Lib;

In the directory src_ada, I have the Ada API wrapper (something_api.ads):

with Interfaces;   use Interfaces;
with Interfaces.C; use Interfaces.C;

package Something_API is

   type T_Something is null record;

   procedure Compute (Something : access T_Something);
   with Import => True,
        Convention => C,
        External_Name => "compute";

end Something_API;

And finally, I call the compute service from my Ada program by with-ing the Ada API wrapper.

Once again, when building/linking the whole thing for an arm-eabi target, using an stm32-full or stm32-sfp Ada runtime, everything runs well and the behavior of the library is validated.

The whole point is I'd like to do the thing in a native environment in order to run CI tests on it and I can't find a way to pass the link stage.

Last thing, in the Settings.gpr generic project file contains some common Ada build/bind/build switches that I can provide if necessary. But I can't see how this could work in arm and not in native with the same options. This HAS to be linked to the default Ada runtime thing...

Any idea?

Upvotes: 2

Views: 857

Answers (2)

ezwiebel
ezwiebel

Reputation: 31

OK, my HUGE apologies to all of you who tried to help... The solution was more obvious than I thought, I was just too obsessed with the thing working in arm and not in native.

BUT, the solution was simply to add the -lm switch to the global linker switches. Hence:

   Ada_Switches_Linker_Native := (
        "-Wl,--gc-sections"
        ,"-Wl,--verbose"
        ,"-Wl,-lm"
      );

   package Linker is
      case Target is
         when "native" =>
            for Switches ("Ada") use Ada_Switches_Linker_Native;

      ...

      end case;
   end Linker;

In case it could be of interest for someone else, the fact that it works straightforward in arm environment and not in native is because the default runtime does not embed a specific mathematical library and you are supposed to use the C one provided by gcc, linking through the -lm switch.

In the contrary, when using a target specific runtime like arm (for stm32f4 for example), the correct mathematical libraries are provided, selected and automatically linked depending on your compilation options (-mhard-float, -msoft-float, etc.).

Sorry again and thank you very much for your time.

Upvotes: 1

Simon Wright
Simon Wright

Reputation: 25511

If you were building with a C main program, what would you have to do to bring in the maths libraries at link time? ... possibly something like

gcc foo.c -l somethingLib -lm

What you need to do is to arrange for the -lm to be included whenever you call in something_lib_c.gpr.

I think that what you need to do is to modify library project Something_Lib_C to include the line

for Library_Options use ("-lm");

Upvotes: 3

Related Questions