如何 link 外部构建的 C 库到 Ada 默认运行时数学服务(sin、cos 等)?

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

我需要使用外部构建的 C 库对我的 Ada 程序进行三角函数计算。我使用 stm32 bb 运行time (SFP) 做得很好,但是当尝试在本地环境中使用默认的 Ada 运行time 做同样的事情时,我最终遇到了 linking 问题.希望我能在这里找到一些帮助。

我尝试了几种项目文件配置 (gpr) 解决方案,但我总是以相同类型的 linking 错误结束:

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

这是我目前所知道的。

C库构建顺序如下(由库提供者确认):

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

C 库 gpr 文件 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;

在 lib_c 目录中,我有实际的库 libsomethingLib.a

src_c 目录中,我有 header API 来使用 C 库 (something.h):

#ifndef _GEOCAGING_H
#define _GEOCAGING_H

typedef struct something_s something_t;

extern void compute(something_t* const self);

#endif // _GEOCAGING_H

然后这里是封装了C库的Ada工程文件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;

在目录 src_ada 中,我有 Ada API 包装器 (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;

最后,我通过 with-ing Ada API 包装器从我的 Ada 程序调用计算服务。

再一次,当building/linking整个事情针对一个arm-eabi目标,使用stm32-fullstm32-sfp阿达运行时,一切运行很好,库的行为得到了验证。

重点是我想在本地环境中做这件事以便对其进行 运行 CI 测试,但我找不到通过 link阶段。

最后,在 Settings.gpr 通用项目文件中包含一些常见的 Ada build/bind/build 开关,必要时我可以提供这些开关。但我看不出这如何在 arm 中工作,而不是在具有相同选项的 native 中工作。这必须 linked 到默认的 Ada 运行time 东西...

有什么想法吗?

如果您使用 C 主程序进行构建,您需要做什么才能在 link 时引入数学库? ...可能像

gcc foo.c -l somethingLib -lm

您需要做的是安排在您每次调用 something_lib_c.gpr 时包含 -lm

我认为您需要做的是修改 library project Something_Lib_C 以包含行

for Library_Options use ("-lm");

好的,我向所有试图提供帮助的人深表歉意... 解决方案比我想象的更明显,我只是太痴迷于在 arm 中而不是在 native 中工作的东西。

但是,解决方案只是将 -lm 开关添加到全局链接器开关。因此:

   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;

如果其他人可能会对它感兴趣,它在 arm 环境中直接工作而不是在本机环境中的事实是因为 default 运行时没有嵌入特定的数学库,你应该使用 gcc 提供的 C 语言,通过 -lm 开关链接。

相反,当使用像 arm 这样的目标特定运行时(例如 stm32f4)时,会根据您的编译选项提供、选择和自动链接正确的数学库(-mhard-float , -msoft-float, 等等).

再次抱歉,非常感谢您抽出宝贵时间。