LINUX.ORG.RU

Линковка статических библиотек .a

 , ,


0

1

Привет! Пытаюсь собрать программку с несколькими статическими библиотеками (.а). Код следующий:

include_directories("${CMAKE_SOURCE_DIR}/program/example")
find_library(CORE libcore.a PATHS ${CMAKE_SOURCE_DIR}/program/example REQUIRED)
find_library(V libv.a PATHS ${CMAKE_SOURCE_DIR}/program/example REQUIRED)
add_executable(example example.c exmpl.h)
target_link_libraries(example PUBLIC ${CORE} ${V})
install(TARGETS example
        RUNTIME DESTINATION ${OUTBIN})

Причем find_library все находит, тк при обращении к CORE и V выводятся правильные пути. У каждой либы есть свой заголовочный файл (core.h и v.h, соответственно), все они подключаются в exmpl.h.

Ошибка: undefined reference to ‘func’. Происходит если функции из libcore.a пытаются обратится к функциям из libv.a и наоборот, т.е. либы не видят эти заголовочные файлы.

Подскажите, что можно сделать.



Последнее исправление: wolfram18 (всего исправлений: 2)

Происходит если функции из libcore.a пытаются обратится к функциям из libv.a и наоборот

Для статических недобиблиотек важен порядок линковки, попробуй другой:

target_link_libraries(example PUBLIC ${V} ${CORE})

В более сложных случаях (кольцевые зависимости) приходилось указывать библиотеки два раза два раза. Ещё посмотри https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc или похожие вопросы, может там есть более правальные решения.

т.е. либы не видят эти заголовочные файлы

Это не имеет отношения к заголовочным файлам, иначе были бы ошибки компилятора а не линкера.

anonymous
()
Ответ на: комментарий от anonymous

Вы правы, после того как поменяла местами, часть ‘undefined reference’ ушла. Остались проблемы в example.c.obj: In function `_main’ буквально со всеми функциями из этих библиотек.

wolfram18
() автор топика
Ответ на: комментарий от MKuznetsov

Попыталась скомпилировать следующим образом: ''' gcc -o example example.c exmpl.h ''' Да, и на этом этапе возникают ошибки: undefined reference, ко всем тем функциям которые по идее описываются в exmpl.h. exmpl.h рядом с example.c, указан как #include «exmpl.h»

wolfram18
() автор топика

Вы собираете бинарник программы с помощью статических либ. Вот когда надо было собирать статические либы — на этом этапе надо было бы предусмотреть, чтобы они друг о друге знали. Иначе они могут общаться не между собой, а только через вашу программу.

Infra_HDC ★★★★★
()
Ответ на: комментарий от PRN

К сожалению не могу показать, библиотеки на самом деле не так называются. nm работает, выдает список всех объектных файлов в архивах библиотек.

anonymous
()
Ответ на: комментарий от Infra_HDC

Библиотека не моя и распространяется именно так: набор статических либ .а и заголовочных файлов. Но я нашла, что можно все это распаковать и запаковать в одну либу. Не знаю, насколько это здраво, ведь функции не просто так раскидали отдельно.

wolfram18
() автор топика

сначала убедись, что это собирается вручную.

$ gcc example.c -lcore -lv ...

Если собирается, то открой Makefile, build.ninja, или что там у тебя cmake выдает, и посмотри как оно (не) собирается там.

Lrrr ★★★★★
()
Ответ на: комментарий от MKuznetsov

Да, так собралось.

$ gcc -Wall -c example.c

$ gcc -o example example.o -L. -lcore -lv -lcore -lm -lpthread

Почему в таком виде не надо указывать заголовочный файл?

Попыталась сделать такую же последовательность в cmake - не срабатывает:

add_executable(example example.c exmpl.h)

target_link_libraries(example PUBLIC ${CORE} ${V} ${CORE} m pthread)

wolfram18
() автор топика
Ответ на: комментарий от wolfram18

Почему в таком виде не надо указывать заголовочный файл?

Заголовочный файл при линковке не нужен.

Заголовочный файл это просто кусок кода на Си, который подставляется в компилируемый исходник.

Допустим, у тебя в заголовочном файле написано extern void foo(int a);. Компилятор запоминает, что foo — это функция, которая находится где-то снаружи, и идёт дальше.

Когда компилятор создаёт объектный файл, у тебя там в машинном коде будет, например, вызов к внешней функции foo. Теперь задача линковщика – соединить объектные файлы. Если на этапе линковки не будет найдено, откуда взять foo, то будет ошибка линковки.

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wolfram18

Почему в таком виде не надо указывать заголовочный файл?

И еще в дополнение к этому. Передавать заголовочные файлы параметрами компилятору – не надо.

У тебя в файле .c есть строки вида #include "что-то.h".

Когда компилятор видит такую строку, он ищет указанный заголовочный файл и просто подставляет его содержимое вместо строки.

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

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wolfram18

Да, так собралось.
$ gcc -Wall -c example.c
$ gcc -o example example.o -L. -lcore -lv -lcore -lm -lpthread

Подозреваю, что все дело во флаге -L. который подсказал линкеру искать библиотеки в текущем каталоге кроме стандартных путей. Как компилятору надо подсказывать, где лежат h-файлы (флаг -I), так и линкеру надо указывать путь до нестандартных библиотек (флаг -L).

Надо смотреть какую команду для линкера сгенерировал CMake, тогда будет ясно почему он не может найти функции внутри стат.библиотек. Сделай

cmake ../
make VERBOSE=1

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

sigurd ★★★★★
()
Последнее исправление: sigurd (всего исправлений: 1)
Ответ на: комментарий от sigurd

Я наконец-то смогла локализовать проблему: когда я пытаюсь собрать программу через cmake, вылезают ошибки типа "undefined reference to ‘_core_Malloc’, но просмотрев либу через nm libcore.a, обнаружила, что там все названия без нижнего подчеркивания ‘core_Malloc’ и т.д.

Вроде бы так отражаются различия между С/С++, т.е. моя программа и CMakeLists написаны под С, либы собраны под С++. Видимо, когда я собираю вручную, компилятор это понимает и ищет и с подчеркиванием и без (какая-то опция компиляции?).

Можно ли как то учесть это через CMakeLists?

wolfram18
() автор топика
Ответ на: комментарий от wolfram18

но просмотрев либу через nm libcore.a, обнаружила, что там все названия без нижнего подчеркивания ‘core_Malloc’

У тебя есть либы сторонние на Си, есть твоя С++ софтина их юзающая. Верно? Попробуй:

extern "C" {
#include <your_external_c_library.h>
}

Возможно автор не учел возможность компиляции плюсовым компилятором

kvpfs_2
()
Ответ на: комментарий от kvpfs_2

Как ни парадоксально, но наоборот: программа на Си, либы предположительно на С++. Попробовала использовать extern «C++» { #include exmpl.h }, но в таком виде ругается: error: expected identifier or ‘(’: extern «C++» {… Видимо в Си подключение выглядит другим образом. Есть ли оно вообще ?

wolfram18
() автор топика