如何创建一个ada lib.a并链接到c

问题描述 投票:0回答:1
ar rc libmy_lib.a *.o

当我尝试阅读lib

中的内容时

ld libmy_lib.a
我得到这个错误
LD:警告:找不到条目符号_start;未设置开始地址

项目文件: 我的ada项目文件prj.gpr
project Prj is
for Source_Dirs use ("source1/", "source2", ....);
for Object_Dir use ".";

for Languages use ("Ada");
for Library_Name use "test";
for Library_Dir use "lib";
for Library_Interface use (
 --All my ada packages
        );

package Naming is
      for Spec_Suffix ("ada") use ".1.ada";
      for Body_Suffix ("ada") use ".2.ada";
      for Separate_Suffix use ".2.ada";
      for Dot_Replacement use ".";
   end Naming;

   package Compiler is
      for Default_Switches ("ada") use ("-v", "-g", "-gnato", "-gnatwa", "-gnatQ", "-gnat05");
   end Compiler;

   package Builder is
      for Global_Compilation_Switches ("Ada") use ("-gnat95");
   end Builder;

   package Ide is
  end Ide;

end Prj;

MyC Project FileC_Main.gpr

with "prj.gpr"; project C_Main is for Source_Dirs use ("source_c_1/", "source_c_2/"); for Languages use ("C"); for Main use ("source_c_1/main.c"); end C_Main;
当我运行命令时
gprbuildc_main.gpr

我有2个不同的错误: 首先是对我ADA代码一部分的某些软件包的不确定引用,然后在我不知道存在的GNAT .ADB文件中。我想的库是如此破库。 其次是即使代码良好并运行,也无法找到某些软件包的字段。它给了我错误,指出该字段不存在ADA代码中。 tldr: 我在3个不同的目录中有一个ADA项目,我想从它们创建一个库。然后链接到C测试程序。最终,我只需要交付库文件即可。命令行最好。我不想处理项目文件。
	

创建静态库的问题很大。 首先,ADA代码极有可能在ADA运行时系统(RTS)中调用。如果您创建静态库,则您(或您的用户)将需要明确拨打ADA RTS,无论您是否使用

libtest.a

。所以都不是

gprbuild

nor
c ada gnat gnat-gps
1个回答
12
投票
gcc main_c.c -ltest

将足够;您会得到这样的失败(而且更糟):

gprbuild -P c_main

第二,ADA代码可能(Will!)需要详细说明,在程序启动时完成。当创建库时,添加了函数
$ gcc main.c -Lada/lib -ltest Undefined symbols for architecture x86_64: "_ada__calendar__delays__delay_for", referenced from: _Hello in libtest.a(hello.o) ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status

) 第一个问题是创建动态库(在Windows上,Linux和其他Unix系统上的动态库,Mac OS X上的其他UNIX系统)。为此,你说
gprbuild

(请注意,尽管动态库知道它需要哪些其他库,但它可能不知道在哪里可以找到它们,因此您必须安排它们在加载程序的库搜索路径上)。 第二个问题是创建Adacore称为

standalOnedynamic库
的方法,并使其自动初始化。
要做到这一点,您需要添加两个属性:

testinit()

指定您希望在图书馆外看到的单位的名称列表。效果是仅在库中包含命名单元的源和

testfinal()
文件;如果唯一的呼叫者来自C,则可能只需要命名一个。
.dll-我认为这实际上是默认值。

I设置了一个示例(在Mac OS X上,GNAT GPL 2014)。

subdirectory

.so

项目文件,
.dylib
hello.ads,
for Library_Kind use "dynamic";

hello.adb, for Library_Interface use (...);

number.ads,

    .ali
  • 和数字
    
    for Library_Auto_Init use "true";
  • 传统目录
  • 项目文件,
ada

和main.c

library project Prj is for Languages use ("ada"); for Library_Name use "test"; for Library_Kind use "dynamic"; for Library_Interface use ("hello"); for Library_Auto_Init use "true"; for Library_Src_Dir use "include"; for Library_Dir use "lib"; for Source_Dirs use ("."); for Object_Dir use ".build"; end Prj;

构建

function Hello return Integer; pragma Export (C, Hello, "Hello");

执行:
with Number;
function Hello return Integer is 
begin
   delay 0.001;            -- so the tasking runtime gets called in
   return Number.Value;
end Hello;

要在另一台计算机上向C用户分发库,而没有已经安装的ADA运行时,您需要包装
package Number is pragma Elaborate_Body; Value : Integer := 0; -- before elaboration end Number;

(或

package body Number is begin Value := 42; -- after elaboration end Number;
with "ada/prj"; project C_Main is for Source_Dirs use ("."); for Languages use ("c"); for Main use ("main.c"); for Exec_Dir use "."; for Object_Dir use ".build"; end C_Main;

),以及所需的ADA共享库。

在一个Unix系统中,您会发现这是您正在寻找的
#include <stdio.h>

extern int Hello(void);

int main() {
  int hello = Hello();
  printf("Hello returned %d.\n", hello);
  return 0;
}

$ gprbuild -p -P c_main gcc -c main.c gcc -c -fPIC number.adb gcc -c -fPIC hello.adb gprlib test.lexch gnatbind -n -o b__test.adb -Ltest -a /Users/simon/tmp/crychair/ada/.build/number.ali ... gcc -c -x ada -gnatA -gnatws b__test.adb -o b__test.o ... gcc -dynamiclib -shared-libgcc -o /Users/simon/tmp/crychair/ada/lib/libtest.dylib ... /Users/simon/tmp/crychair/ada/.build/number.o ... ar cr libc_main.a ... ranlib -c libc_main.a gcc main.o -o main

。您应该在编译器的对象搜索路径(通常是
$ ./main
Hello returned 42.
输出的对象搜索路径部分的最后一行)中找到这些。通常会有符号链接:

libtest.so

.dylib

表示共享库和符号链接在目录中,例如,您的用户应该能够与
链接
.dll

或可能
ldd libtest.so

在操作系统上,可执行的可执行文件可能无法在运行时找到共享库。 绕这是一种方式,就是将装载机已经看起来的库放置在库中,例如(在这种情况下,您不需要libgnat*.so

)。 Another方法是通过设置环境变量来告诉加载程序在哪里看(linux上,Mac OS X上的
libgnarl*.so
)。

第三种方法是告诉链接器以将路径保存在可执行文件中:

gnatls -v
Mac OS X上的工作,可能会在Linux上。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.