如何创建ada lib.a并链接到C [英] How to create an ada lib.a and link to C

查看:149
本文介绍了如何创建ada lib.a并链接到C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个ada库,并尝试了一些不同的方法。
我尝试使用makefiles编译项目,并尝试从所有.o文件创建一个库。
这似乎无法正常工作。
然后我向adacore寻求支持,他们指出了我在ada和c项目中都使用.gpr文件的方向,并指出应该创建一个库的ada.gpr。这几乎可以用,但是当它尝试编译ada时,我得到了未定义的引用。

I am trying to create an ada library and have tried a few different things. I have tried compiling the project using makefiles and trying to create a library from all the .o files This seemed to not work as expected. I then asked adacore support and they pointed me in the direction of using .gpr files for both the ada and c projects and withing in the ada.gpr that should create a library. This almost worked but when it tries to compile the ada I get undefined references.

我尝试过的操作:
命令行:

What I have tried: Command line:

ar rc libmy_lib.a *.o

,当我尝试读取lib中的内容时

and when I try to read what is in the lib

ld libmy_lib.a

我收到此错误
ld:警告:找不到条目符号_start;未设置起始地址

I get this error ld: warning: cannot find entry symbol _start; not setting start address

项目文件:
我的ada项目文件prj.gpr

Project Files: My ada project file 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;

我的c项目文件c_main.gpr

My c project file c_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;

当我运行命令
gprbuild c_main.gpr

When i run the command gprbuild c_main.gpr

我遇到2个不同的错误:
首先是未定义的对某些程序包的引用,这些程序包是我的ada代码的一部分,而在gnat .adb文件中我不知道存在。我觉得图书馆很破。
其次,即使代码可以正常编译并运行,某些包的字段也无法找到/不存在。

I got 2 different errors: First being undefined references to some packages that are part of my ada code and come that at gnat .adb files I didnt know existed. So broken library I figure. Second being that fields of certain packages cant be found/dont exist even though the code compiles fine and runs. It gives me errors stating that the fields dont exist in the ada code.

TLDR:
我有一个错误,指出该字段不存在于ada代码中。我在3个不同的目录中有一个ada项目,我想创建他们的图书馆。然后链接到C测试程序。最终,我只需要交付库文件。命令行是最好的。我不想处理项目文件。

TLDR: I have an ada project in 3 different directories and I want to create a library from them. Then link to a C testing program. Ultimately I just have to deliver the library file. Command line would be best. I do not want to deal with project files.

推荐答案

创建静态库存在很大问题libtest.a

首先,Ada代码极有可能在Ada运行时系统(RTS)中调用。如果创建静态库,则无论您是否使用 gprbuild ,您(或您的用户)都需要显式调用Ada RTS。因此,

First, the Ada code is extremely likely to call in the Ada runtime system (RTS). If you create a static library, you (or your users) will need to call in the Ada RTS explicitly, whether or not you use gprbuild. So neither

gcc main_c.c -ltest

nor

gprbuild -P c_main

就足够了;您会遇到这样的失败(甚至更糟):

will be enough; you'll get failures like this (and worse):

$ 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

第二,Ada代码可能(将要!)需要详细说明,在程序启动时完成。在 gprbuild 创建库时,它会添加函数 testinit(),您的C代码必须在调用该库的任何接口之前先调用,然后在所有使用该库后调用 testfinal()(大多数人都不会打扰)。

Secondly, Ada code might (will!) require elaboration, done at program start. When gprbuild creates the library it adds functions testinit(), which your C code must call before calling any interface of the library, and testfinal() to be called after all uses of the library (most people don't bother).

第一个问题的解决方法是创建动态库(在Windows上是 .dll ,在 .so ,在Mac OS X上为 .dylib )。为此,您说对于Library_Kind使用 dynamic; (注意,尽管动态库知道它还需要其他哪些库,但它可能不知道在哪里可以找到它们,因此您必须安排它们位于加载程序的库搜索路径上。)

A way round the first problem is to create a dynamic library (.dll on Windows, .so on Linux and other Unix systems, .dylib on Mac OS X). To do this, you say for Library_Kind use "dynamic";. (Note, although the dynamic library knows what other libraries it needs, it may not know where to find them, so you'll have to arrange for them to be on the loader's library search path).

解决第二个问题的方法是创建AdaCore所谓的独立动态库,并使其自动初始化。

A way round the second problem is to create what AdaCore call a standalone dynamic library, and to get it to initialize itself automatically.

要执行此操作需要添加两个属性:

To do this you need to add two attributes:


  • 供Library_Interface使用(...); 指定希望在库外显示的单位名称的列表。效果是在库中仅包含命名单位的源文件和 .ali 文件;

  • for Library_Auto_Init请使用 true; -我认为这实际上是默认设置。

  • for Library_Interface use (...); specifies a list of the names of the units you wish to be visible outside the library. The effect is to include only the named units' source and .ali files in the library; if the only callers are to be from C you probably only need to name one.
  • for Library_Auto_Init use "true"; - I think this is actually the default.

我举了一个小例子(在Mac OS X上,GNAT GPL 2014)。

I set up a little example (on Mac OS X, GNAT GPL 2014).

子目录 ada

Subdirectory ada

项目文件,

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;

hello.ads,

hello.ads,

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

hello.adb,

hello.adb,

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

number.ads,

number.ads,

package Number is
   pragma Elaborate_Body;
   Value : Integer := 0;   -- before elaboration
end Number;

和number.adb

and number.adb

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;

和main.c

#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.






要将库分发给另一台计算机上的C用户,而未安装Ada运行时,则需要打包 libtest.so (或 .dylib .dll )和Ada需要共享库。


To distribute your library to C users on another computer, without the Ada runtime already installed, you’d need to package up libtest.so (or .dylib, or .dll) and the Ada shared libraries required.

在Unix系统上,您可以使用 ldd libtest.so 找到它。您正在寻找 libgnat * .so libgnarl * .so 。您应该在编译器的对象搜索路径中找到它们(通常是 gnatls -v 输出的对象搜索路径部分的最后一行)。通常会有符号链接:

On a Unix system, you’d find this out using ldd libtest.so You’re looking for libgnat*.so and libgnarl*.so. You should find these in the compiler’s object search path (usually the last line of the Object Search Path section of the output of gnatls -v). Typically there will be symbolic links:

libgnat.so       ->      libgnat.1.so
libgnat.1.so     ->      libgnat.1.0.0.so
libgnat.1.0.0.so         (the real thing)

将共享库和符号链接放在带有 libtest.so 的目录中,例如 product / ,那么您的用户应该能够与

Put the shared libraries and symlinks in a directory with libtest.so, say product/, then your users should be able to link with

gcc main.c -o main -Lproduct -ltest

或者也许

gcc main.c -o main -Lproduct -ltest -lgnat -lgnarl

根据您的操作系统,生成的可执行文件可能不是能够在运行时找到共享库。

Depending on your OS, the resulting executable may not be able to find the shared libraries at runtime.

一种解决方法是将库放置在加载程序已经看起来的位置,例如 / usr /本地/ lib (在这种情况下,您不需要 -Lproduct )。

One way round this is to put the libraries where the loader already looks, for example /usr/local/lib (in which case you wouldn’t need the -Lproduct).

另一种方法是通过设置环境变量(在Linux上是 LD_LIBRARY_PATH ,在 DYLD_LIBRARY_PATH Mac OS X)。

Another way is to tell the loader where to look by setting an environment variable (LD_LIBRARY_PATH on Linux, DYLD_LIBRARY_PATH on Mac OS X).

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

A third way is to tell the linker to save the path in the executable:

gcc main.c -o main -Lproduct -ltest -lgnat -lgnarl -Wl,-rpath,$PWD/product

可以在Mac OS X上运行,也许可以在Linux上运行。

works on Mac OS X, probably will on Linux.

这篇关于如何创建ada lib.a并链接到C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆