【问题标题】:How to link an externally built C library to Ada default runtime math services (sin, cos, etc.)?如何将外部构建的 C 库链接到 Ada 默认运行时数学服务(sin、cos 等)?
【发布时间】:2020-02-04 21:52:23
【问题描述】:

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

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

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 目录中,我有头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库something_lib.gpr的Ada工程文件:

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;

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

再一次,当为 arm-eabi 目标构建/链接整个事物时,使用 stm32-fullstm32-sfp Ada 运行时,一切运行良好并且库的行为得到验证。

关键是我想在本地环境中做这件事以便在其上运行 CI 测试,但我找不到通过链接阶段的方法。

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

有什么想法吗?

【问题讨论】:

标签: c linker cross-compiling ada


【解决方案1】:

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

gcc foo.c -l somethingLib -lm

您需要做的是安排在您拨打something_lib_c.gpr 时包含-lm

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

for Library_Options use ("-lm");

【讨论】:

  • 既然 OP 似乎有一些复杂的构建系统,并且仅在构建本机时才会出现错误,可能会根据目标将其包裹在 switch case 周围? case target is when "xxx" => null; when "native" => for Library_Options use ("-lm"); end case; 或类似的味道
  • @LoneWanderer,你是对的,一旦问题得到解决,我就是这样处理的。但目前我需要弄清楚原生方面发生了什么......
  • @Simon Wright,感谢您的回答,但它似乎不起作用......我得到了完全相同的错误。真正让我烦恼的是它在 arm 环境中工作。
  • @ezwiebel 您的数学库是否可能不提供sin
  • @JL2210,会喜欢它这么简单。我使用了 sin 示例,但实际上在实际程序中使用了许多其他数学服务并且“缺少”链接器(cos、asin、atan2、...)。我目前正在尝试查看从本机运行时获取的确切库,我可能已经找到与 libc 相关的内容...我会及时通知您。
【解决方案2】:

好的,我向所有试图提供帮助的人深表歉意... 解决方案比我想象的更明显,我只是太着迷于在 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 运行时没有嵌入特定的数学库,您应该使用 C 的由gcc 提供,通过-lm 开关链接。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 2015-04-05
    相关资源
    最近更新 更多