创建一个无需 gnat-tools 即可链接的静态 Ada-Library

Create a static Ada-Library which can be linked without gnat-tools

我想从 Ada-Code 创建静态库并将其部署到没有 GNAT-Toolchain 的开发人员(对于 C/C++ 代码)。

当我尝试使用 C 程序 Link Ada-Library ('.a') 时,我会遇到以下 Linker-Errors:

undefined reference to `__gnat_rcheck_CE_Overflow_Check'
undefined reference to `ada__text_io__put_line__2'

我怎样才能做到这一点?它接缝我应该 link 反对运行时库,但如何?


测试代码:

main.c:

#include <stdio.h>

extern void adaTest();
extern int add5(int);

int main(){
  adaTest();
  int b = add5(2);
  printf("--> %d \ndone.\n", b);
  return 0;
}

ada_lib_project.gpr:

library project ada_lib_project is
    for Languages use ("Ada");
    for Library_Name use "My_Ada_Lib";
    for Library_Dir use "my_generated_lib";
    for Library_Kind use "Static";
end ada_lib_project;

adatestpacket.ads:

with Interfaces.C; use Interfaces.C;
package adatestpacket is
  procedure adatest with
    Export, Convention => C, External_Name => "adaTest";

  function add5(x: in int) return int with
    Export, Convention => C, External_Name => "add5";
end adatestpacket;

adatestpacket.adb:

with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C; use Interfaces.C;
package body adatestpacket is
  procedure adatest is
  begin
    Put_Line("This is executed ADA/SPARK-Code...");
    null;
  end adatest;

  function add5(x: in int) return int is
  begin
    return x + 5;
  end add5;
end adatestpacket;

正在编译:

gcc -c main.c -o main.o           # .c -> .o
gprbuild -P ada_lib_project.gpr   # .ad[sb] -> .a
gcc main.o -L my_generated_lib -l My_Ada_Lib -o a.out # Linking -- with undefined References

可能最简单的方法是简单地也用 gprbuild 编译 C 源代码(即使你不能在你的目标场景中这样做,你可以做测试并用 -v GPRbuild 是如何让它工作的):

with "ada_lib_project";

project My_Executable is
   for Languages use ("C");
   for Main use ("main.c");
end My_Executable;

您还需要调用 adainitadafinal 来初始化/完成 Ada 包:

#include <stdio.h>

extern void adainit();
extern void adafinal();
extern void adaTest();
extern int add5(int);

int main(){
  adainit();
  adaTest();
  int b = add5(2);
  printf("--> %d \ndone.\n", b);
  adafinal();
  return 0;
}

adainitadafinalgnatbind 为独立库生成。当看到您使用 C 可执行文件中的 Ada 库时,我不完全确定 GPRBuild 是否会处理这个问题;如果没有,你需要

package Binder is
   for Default_Switches ("Ada") use ("-n");
end Binder;

在你的图书馆。这样做之后,你应该可以做到

gprbuild my_executable.gpr

如果你想在没有 GPRbuild 的情况下完成它,-n/adainit/adafinal 部分仍然适用,你需要 link 你的可执行文件

-l<your-gnat-lib>

其中 是您的 GNAT 版本的 Ada 标准库;上次我这样做时,它类似于 gnat-2021。您可能需要添加一个 -L<directory-containing-that-lib>,具体取决于它所在的位置。

(这个答案可能有错误,因为我在M1上目前无法测试它)

编辑:如果您真的想为开发人员提供无法访问 GNAT 的权限,您需要构建一个 encapsulated,即动态库。 This answer 涵盖了该过程。如果需要提供静态库,您必须至少提供 GNAT 标准库文件。

我已经用 -static 生成了静态二进制文件。我不知道在生成您的库时是否可以使用类似的东西,或者您还需要 GNAT 运行时才能与 C/C++ 工具链接。

对于任何对工作实施感兴趣的人,这些是我的问题的变化:

main.c:

#include <stdio.h>

extern void adainit();
extern void adafinal();
extern void adaTest();
extern int add5(int);

int main(){
  adainit();
  adaTest();
  int b = add5(2);
  printf("--> %d \ndone.\n", b);
  adafinal();
  return 0;
}

ada_lib_project.gpr:

library project ada_lib_project is
    for Languages use ("Ada");
    for Library_Name use "My_Ada_Lib";
    for Library_Dir use "my_generated_lib";
    for Library_Kind use "static-pic";
    for Library_Interface use ("adatestpacket");

    package Binder is
      -- "-Lada" set "ada" as Prefix for "init" and "final" Function
      for Default_Switches ("Ada") use ("-n","-Lada");
    end Binder;

end ada_lib_project;

正在编译:

gprbuild -P ada_lib_project.gpr # .adb -> .a
gcc main.c -L my_generated_lib -l My_Ada_Lib -l gnat_pic -ldl

对于最后一个命令,我只需要将库 (My_Ada_Lib) 和运行时 (libgnat_pic.a) 从 GNAT/2021/lib/gcc/x86_64-pc-linux-gnu/10.3.1/rts-native/adalib 传输到远程机器。