Reputation: 31
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
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
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