如何从可从C++代码调用的 Ada 源代码构建静态库?
How to build a static library from Ada source that's callable from C++ code?
我需要构建一个静态库,其中包含一堆用ADA编写的代码,可以从C/C 编写的代码中调用。
我已经通过Internet进行了搜索,并了解了gnatmake
,gnatbind
和gnatlink
,但仍然无法正确完成工作。
另外,我已经阅读了一些工具,这些工具依赖于某种项目文件。我对这些不感兴趣,我只需要一堆命令即可在Makefile
中写入。
此答案假定您正在使用GCC工具链。
最大的障碍是ADA代码需要详细说明(大致相当于在C 中调用文件级构造函数)。 gnatbind 是这样做的工具,您使用标志-L
:
-Lxyz Library build: adainit/final renamed to xyzinit/final, implies -n
[...]
-n No Ada main program (foreign main routine)
为例,请考虑ADA源foo.ads
,
package Foo is
procedure Impl
with
Convention => C,
Export,
External_Name => "foo";
end Foo;
或,如果在ADA2012之前使用ADA,
package Foo is
procedure Impl;
pragma Export (Convention => C, Entity => Impl, External_Name => "foo");
end Foo;
和 foo.adb
,
with Ada.Text_IO;
package body Foo is
procedure Impl is
begin
Ada.Text_IO.Put_Line ("I am foo");
end Impl;
begin
Ada.Text_IO.Put_Line ("foo is elaborated");
end Foo;
和类似的文件bar.ads
,bar.adb
(s/foo/bar/g
)。
编译以下内容:
gnatmake foo bar
绑定:
gnatbind -Lck -o ck.adb foo.ali bar.ali
(这实际上将生成ck.ads
以及命名的ck.adb
;这些是执行详细说明的代码)。
编译详细代码:
gnatmake ck.adb
生成库:
ar cr libck.a ck.o foo.o bar.o
您快要准备好滚动了。
C主程序看起来像
#include <stdio.h>
void ckinit(void);
void ckfinal(void);
void foo(void);
void bar(void);
int main()
{
ckinit();
printf("calling foo:n");
foo();
printf("calling bar:n");
bar();
ckfinal();
return 0;
}
(您的主要位于C ,因此您需要extern "C" {
...当然)。
您会认为
gcc main.c libck.a
会解决问题。但是,libck
在ADA运行时呼叫。这里(macos),这意味着我说
gcc main.c libck.a /opt/gnat-gpl-2016/lib/gcc/x86_64-apple-darwin14.5.0/4.9.4/adalib/libgnat.a
(您可以使用gcc --print-libgcc-file-name
找到该路径)
最终可执行的运行:
$ ./a.out
bar is elaborated
foo is elaborated
calling foo:
I am foo
calling bar:
I am bar
谢谢您的巨大帮助!实际上,它可以与以下makefile一起使用:
ada_libs := -lgnat -lgnarl
cpp_src := ...
ada_src := ...
library.so : $(cpp_src:.cc=.o) adalib.a
g++ -o $@ $^ $(ada_libs)
$(cpp_src:.cc=.o) : %.o : %.cc
g++ -c -o $@ $<
$(cpp_src:.cc=.d) : %.d : %.cc
g++ -MM -MF $@ $^
$(addprefix objects/,$(ada_src:.adb=.o)) : objects/%.o : %.adb
gnatmake -c -D objects $^
adabind.adb : $(addprefix objects/,$(ada_src:.adb=.o))
gnatbind -n -o $@ $(^:.o=.ali)
adabind.ali : adabind.adb
gnatmake -c -D objects $^
adalib.a : adabind.ali
ar cur $@ $(^:.ali=.o) objects/*.o
include $(cpp_src:.cc=.d)
除此之外,我必须在我的C 文件中声明自己的功能为外部" C"。
非常感谢,我几乎在那里,但错过了链接时包括ADA运行时库(-lgnat -lgnarl)。
相关文章:
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 更改命令行 qt5 源代码构建配置的正确/快速方法
- 从源代码构建 gRPC C++
- 如何使用我构建的库,而不会从源代码出错,但不为我自己的项目编译?
- 为什么Qt必须从源代码构建以进行交叉编译?
- 尝试使用 MSVC 从源代码构建 qt 创建器:无法打开包含文件:"stddef.h":没有这样的文件或目录
- 从源代码构建 pcl 1.7.2
- 使用 bazel 构建的二进制文件在 pprof 中查看源代码
- 在构建时从源代码编译 OpenCV 3
- SQLite - 从源代码构建库或将源代码直接包含在我的项目中
- 从源代码构建 openCV 之前的步骤
- 在 OSX 上从源代码构建 GIMP 2.10 在"gimp-debug-tool-2.0"失败
- 如果构建是源代码外的,CMake 无法确定标头依赖项?
- 我如何只构建 TensorFlow lite,而不是从源代码构建所有 TensorFlow
- 使用 bazel 从源代码构建张量流服务遇到错误:C++规则'@org_tensorflow//…'编译失败(出口 4)
- Qt 5 中源代码外构建的链接器错误
- CMake configure_file没有源代码构建
- 如何使用 cmake 在构建源代码之前检查某些库是否存在
- 为什么这个简单的makefile不能在更改时重新构建源代码
- 如何构建源代码以检入需要很长时间构建的二进制文件