Может ли в Linux статическая библиотека использовать динамическую?

Пытаюсь сделать приложение и статическую библиотеку, которая использует ffmpeg. Фрагмент CMakeLists.txt для статической библиотеки:

find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
find_library(AVCODEC_LIBRARY avcodec)

find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
find_library(AVFORMAT_LIBRARY avformat)

find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
find_library(AVUTIL_LIBRARY avutil)

find_path(AVDEVICE_INCLUDE_DIR libavdevice/avdevice.h)
find_library(AVDEVICE_LIBRARY avdevice)

add_library(prj STATIC ${SOURCE_LIB})
target_include_directories(prj  PRIVATE ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR} ${AVDEVICE_INCLUDE_DIR})
target_link_libraries(prj  ${AVCODEC_LIBRARY} ${AVFORMAT_LIBRARY} ${AVUTIL_LIBRARY} ${AVDEVICE_LIBRARY})

Всё собирается, nm показывает нужные мне функции:

U avformat_close_input
U avformat_find_stream_info
U avformat_free_context
U avformat_network_init

В CMakeLists.txt приложения:

add_library( libprj STATIC IMPORTED )
set_property( TARGET libprj PROPERTY IMPORTED_LOCATION /tmp/libprj.a )
add_executable(app ${SOURCE_EXE})
target_link_libraries(app libprj)

При сборке приложения множество сообщений о статической библиотеке, типа

ошибка: /tmp/libprj.a(prj.c.o): in function `st':
ошибка: undefined reference to `avformat_close_input'

Задумался. А так, вообще, можно делать? Или, искать ошибку в конфиге сборки?


Ответы (3 шт):

Автор решения: Sergey Chernov

В общем, абсолютно чёткого понимания нет, но есть предположение. Если указать библиотеки ffmpeg при компоновке приложения, то всё нормально. Похоже на то, что, таки, статически прилинкованная библиотека никак не участвует в подгрузке динамической, просто ссылаясь на функции из неё. Собственно, учитывая, что статическая библиотека становится частью приложения, то, в принципе, логично, что именно оно и ответственнено за загрузку нужных .so.

→ Ссылка
Автор решения: knzsoft

Проблема в том, что библиотечные файлы ffmpeg реализованы средствами компилятора C, а не C++, а значит, в них отсутствует mangling. Отсюда и проблема поиска сигнатур C++ там где этих сигнатур нет.

Чтобы решить эту проблему достаточно включение заголовков ffmpeg, в коде программы, заключить в extern "C" { }.

→ Ссылка
Автор решения: user7860670

Статические библиотеки представляют собой архив из собранных объектных файлов. Шаг линковки для них не выполняется. Он и не может выполняться, так как не известно, какие символы будут использоваться - это становится известно после того, как библиотека прилинкуется к бинарю. Соответственно и динамические библиотеки необходимо линковать к конечному бинарю. Причем на линукс есть проблема с порядком линковки - библиотеки, которые содержат недостающие символы, должны линковаться строго после единиц трансляции и библиотек, использующих эти символы.

→ Ссылка