Ada中的动态链接库引入了额外的依赖项

问题描述 投票:1回答:1

我在动态和静态链接Ada中的库时遇到麻烦。我准备了一个最小的工作示例。这三个文件定义了一个输出“ Hello world”的库:

helloworld_lib.gpr

project Helloworld_Lib is

   for Library_Name use "helloworld_lib";
   for Source_Files use ("helloworld_lib.adb", "helloworld_lib.ads");
   for Library_Kind use "static";
   for Library_Dir use "obj";

end Helloworld_Lib;

helloworld_lib.adb

with Ada.Text_IO;

package body helloworld_lib is

   procedure Hello is
   begin
      Ada.Text_IO.Put_Line("Hello world");
   end Hello;

end helloworld_lib;

helloworld_lib.ads

with Ada.Text_IO;
use Ada.Text_IO;

package helloworld_lib is

   procedure Hello;

end helloworld_lib;

这两个文件定义了一个导入库并运行它的项目:

helloworld_interface.gpr

with "helloworld_lib.gpr";

project Helloworld_Interface is

   for Create_Missing_Dirs use "True";
   for Main use ("helloworld_interface.adb");
   for Source_Files use ("helloworld_interface.adb");
   for Object_Dir use "obj";

end Helloworld_Interface;

helloworld_interface.adb

with helloworld_lib; use helloworld_lib;

procedure helloworld_interface is

begin

   Hello;

end helloworld_interface;

我正在Windows上使用GPS 19.1 GNAT社区版。如果打开helloworld_interface.gpr并“全部构建”运行,则将编译一个exe文件,该exe文件可以按预期运行,并且完全独立。

如果在helloworld_lib.gpr中将Library_Kindstatic更改为dynamic,并像编译exe和dll之前一样进行构建。但是,编译后的文件现在依赖于libgnat-2019.dlllibgcc_s_seh-1.dll。没有这些DLL的程序将无法运行,这些DLL可以从C:\GNAT\2019\bin复制。

鉴于可以生成一个没有其他依赖项的静态链接EXE文件,如何将此示例编译为没有其他依赖项的EXE和DLL?为什么现在需要这两个额外的DLL?

dll ada gnat gnat-gps
1个回答
0
投票

libgnat-2019.dll是ANAT标准库的GNAT实现。 libgcc_s_seh-1.dll是该标准库的依赖项。

如果编译没有动态库的单个可执行文件,则GNAT可以静态链接到标准库,因此您最终将不依赖于动态库。

但是,如果您链​​接到动态库,则会遇到可执行文件和库代码都需要标准库的情况。如果您尝试静态链接到标准库,则最终会得到一个链接到DLL的标准库和另一个链接到您的可执行文件的标准库。因此,在加载可执行文件时,您会将标准库中的所有对象两次存储,这是Ada语言语义所禁止的(例如,它将两次调用所有程序包初始化代码)。]因此,一旦将Ada代码编译为DLL文件,您别无选择,只能动态链接到标准库。但是,您可以动态链接C DLL文件,同时仍然可以静态包含Ada stdlib。从理论上讲,您可以使用-nostdlib-nodefaultlibs创建一个Ada DLL,但这将严重限制您在该库中执行的操作(iirc不会有例外)。

© www.soinside.com 2019 - 2024. All rights reserved.