如何 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-full
或stm32-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
, 等等).
再次抱歉,非常感谢您抽出宝贵时间。
我需要使用外部构建的 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-full
或stm32-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
, 等等).
再次抱歉,非常感谢您抽出宝贵时间。