我需要构建一个静态库,其中包含一堆用Ada编写的代码,可以用C / C ++编写的代码调用。
我已经通过互联网搜索了一些关于gnatmake
,gnatbind
和gnatlink
的知识,但仍然无法正确完成工作。
另外,我读过有些工具依赖于某种项目文件。
我对这些不感兴趣,我只需要在Makefile
中写一堆命令。
答案 0 :(得分:10)
这个答案假设你正在使用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
答案 1 :(得分:2)
谢谢你的帮助! 实际上,它使用以下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)
除此之外,我必须将我的功能声明为extern&#34; C&#34;在我的C ++文件中。
非常感谢,我几乎在那里但在链接时错过了包含ada运行时库(-lgnat -lgnarl)。