Требуемое объяснение: libtool, automake, общие библиотеки (и Fortran) - PullRequest
2 голосов
/ 07 апреля 2011

Проблема, с которой я столкнулся, решена.Я публикую это, чтобы получить объяснение, почему решение действительно работает.Я получил отличные отзывы здесь раньше.

У меня есть устаревшая кодовая база, в которой используется очень упрощенная система сборки, и мой проект состоит в том, чтобы перенести ее в Autotools для настройки и, в частности, для создания общих библиотек.Основная библиотека написана на C, но она также должна быть связана с Fortran (для унаследованных целей) и распространяется с некоторыми тестовыми кодами в F77.Авторы организовали исходный код в модули ...

src_module1/
src_module2/
...
testc/
testf77/

Они создали библиотеку lib/libmain.a, скомпилировав код в каталогах src _ * / и заархивировав объекты с помощью ranlib.

MyПервый подход состоял в том, чтобы создать общую библиотеку из каждого src _ * / отдельно и "связать" все это в одну общую библиотеку.При использовании Autotools src_module1/Makefile.am будет содержать

noinst_LTLIBRARIES = libmodule1.la
libmodule1_la_SOURCES = ...

и т. Д. Для других модулей, и, наконец, lib/Makefile.am потребуется только:

lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES =
libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la ...

Это, кажется, работает отлично,Однако, когда код в testc / был скомпилирован и связан с libmain.la, возникла ошибка «символы не найдены».

Думая, что это проблема с libtool или общими библиотеками, я попытался создать только статические, в основном изменив все .la на .a и все _LTLIBRARIES на _LIBRARIES.Та же проблема.На этот раз, однако, обратите внимание на ошибку «ranlib: warning for library: libmain.a. Содержимое пусто (ни один объектный файл в библиотеке не определяет глобальные символы)» при попытке связать сам libmain.a.

Решение, которое я нашел, похоже на взлом.Я не собирал Makefiles ни для одного из каталогов src _ * /, но вместо этого использовал только для каталога lib /, и его Makefile.am содержал строки:

lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES = [all sources from all ../src_modules/ ]

Это сработало.Скомпилированные программы в testc / связаны с libmain.la без проблем.Одним из «модулей» является набор связываний на Фортране, которые обертывают другие функции C в библиотеке.Даже фортранские коды в testf77 / правильно связаны с libmain.la.

Может кто-нибудь внимательно объяснить, что происходит, когда libtool создает общую библиотеку?Или даже при создании статической библиотеки?Почему несколько статических библиотек нельзя связать вместе, чтобы создать одну статическую библиотеку?Почему символы доступны только тогда, когда libtool / ranlib собирает библиотеку «из исходников»?А как насчет установки разделяемой / статической библиотеки, т.е. перемещения ее в / usr / local / lib --- что там происходит?Статья в Википедии о статических и общих библиотеках для меня недостаточно детальна.

Я ценю все усилия, чтобы разобраться в моем давнем вопросе.

1 Ответ

2 голосов
/ 08 апреля 2011

То, что вы впервые попробовали, должно сработать.Я использую этот вид установки все время (в контексте C ++).Это также задокументировано, и часть набора тестов Automake (хотя, возможно, и не с Fortran).

Библиотека libtool, которая не может быть установлена ​​, т. Е. Библиотека, объявленная с noinst_LTLIBRARIES, называется удобная библиотека libtool .Это noinst_ имеет большое значение в том, что построено.Даже если Libtool настроен для создания разделяемых библиотек, удобная библиотека libtool на самом деле не является разделяемой библиотекой: это просто набор объектных файлов (скомпилированных как PIC , чтобы их можно было использовать в общей папке).библиотека) хранится в архиве.Вы можете использовать удобную библиотеку libtool где угодно, используя этот набор объектов, например, для создания разделяемой библиотеки.

Когда несколько библиотек удобства libtool LIBADDed для устанавливаемой библиотеки libtool (например, libmain.la), Libtool должен распаковать архивы, содержащие объекты каждой библиотеки удобства, и связать их вфинальная библиотека.

Здесь есть одна ловушка, на которую стоит обратить внимание: при создании общей библиотеки из вспомогательных библиотек, если переменная _SOURCES пуста, Automake не знает, какой компоновщик использовать, и по умолчанию он использует компоновщик C.Если вы хотите заставить Automake использовать правило связывания для какого-то определенного языка, вы можете объявить исходный файл nodist_EXTRA_..._SOURCES, который не должен существовать.(См., Например, Libtool Convenience Libraries руководства Automake.)

Может быть, это была ваша проблема?Если у вас есть несколько файлов Fortran в источниках некоторых из ваших модулей (ваше описание предполагает, что это только файлы C), компоновщик Fortran будет использоваться для сборки libmain.la, только если файл Fortran появится в исходных файлах, объявленных для этого libtoolбиблиотека.И компоновщик C будет использоваться, когда libmain_la_SOURCES пуст.

В противном случае, я понятия не имею, почему он не работает.

В вашем примере есть небольшая ошибка:

libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la

должно быть

libmain_la_LIBADD = $(top_builddir)/src_module1/libmodule1.la

, поскольку библиотека не создается в исходном каталоге.Однако я предполагаю, что это всего лишь опечатка, и вы не увидите разницу, если не выполните сборку VPATH или не выполните make distcheck.


Вторая попытка с использованием _LIBRARIES без Libtool неожидается, что он будет работать.
_LIBRARIES может использоваться только для объявления статических архивов, и в этом случае _LIBADD может содержать только объектные файлы, но не другие статические архивы.Распаковка архива для повторного использования его объектов в другом архиве может быть непростой задачей.Ответ Automake на эту проблему всегда был таким: установите Libtool и используйте _LTLIBRARIES (Libtool можно настроить для сборки только статических библиотек).

...