Динамическое связывание библиотеки в Аде вводит дополнительные зависимости

У меня проблемы с динамическим и статическим связыванием библиотеки в Аде. Я подготовил минимальный рабочий пример. Эти три файла определяют библиотеку, которая выводит «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;

Я использую GPS 19.1 GNAT Community Edition в Windows. Если helloworld_interface.gpr открыт и запускается "Build All", компилируется исполняемый файл, который работает должным образом и полностью автономен.

Если мы изменим Library_Kind с static на dynamic в helloworld_lib.gpr и соберем как раньше, exe и dll будут скомпилированы. Однако скомпилированные файлы теперь зависят от libgnat-2019.dll и libgcc_s_seh-1.dll. Программа не будет работать без этих DLL, которые можно скопировать из C:\GNAT\2019\bin.

Учитывая, что статически связанный EXE-файл может быть создан без каких-либо других зависимостей, как этот пример может быть скомпилирован в EXE и DLL без каких-либо других зависимостей? Почему теперь требуются эти две дополнительные библиотеки DLL?


person Mark MAC Clowes    schedule 12.02.2020    source источник


Ответы (1)


libgnat-2019.dll — это реализация GNAT стандартной библиотеки Ada. libgcc_s_seh-1.dll является зависимостью этой стандартной библиотеки.

Если вы скомпилируете один исполняемый файл без динамических библиотек, GNAT может статически связываться со стандартной библиотекой, поэтому вы в конечном итоге не будете зависеть от динамических библиотек.

Однако если вы подключаетесь к динамической библиотеке Ada, возникает ситуация, когда код исполняемого файла и библиотеки требуют стандартной библиотеки. Если вы попытаетесь связать стандартную библиотеку статически, вы получите стандартную библиотеку, связанную с DLL, и другую, связанную с вашим исполняемым файлом. Таким образом, у вас будут все объекты в стандартной библиотеке дважды при загрузке исполняемого файла, что запрещено семантикой языка Ада (например, весь код инициализации пакета будет вызываться дважды).

Поэтому, как только вы скомпилируете код Ada в DLL-файл, у вас не останется другого выбора, кроме как динамически связать стандартную библиотеку. Однако вы можете динамически компоновать C DLL-файлы, сохраняя при этом возможность статического включения Ada stdlib. Теоретически вы можете создать Ada DLL с -nostdlib и -nodefaultlibs, но это сильно ограничит то, что вы будете делать внутри этой библиотеки (iirc не будет исключений).

person flyx    schedule 12.02.2020