Статическая линковка C++ рантайма к динамической библиотеке

103
25 ноября 2020, 10:30

Пытаюсь собрать приложение app, прилинковав его к динамической библиотеке library так, чтобы больше никаких dll для запуска app.exe не требовалось (кроме системных и MSVCRT.dll). Использую MinGW.

Для этого C++ runtime линкую с опцией -static, что на выходе даёт "чистую" library.dll (зависящую только от kernel32.dll и MSVCRT.dll судя по dependency walker-у):

set(LIB_NAME library)
set(LIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
add_library(${LIB_NAME} SHARED)
target_sources(${LIB_NAME} PRIVATE ${LIB_INCLUDE_DIR}/${LIB_NAME}/Some.hpp src/Some.cpp) # Some.hpp и Some.cpp -- сорсы библиотеки
target_include_directories(${LIB_NAME} PUBLIC ${LIB_INCLUDE_DIR})
if (WIN32 AND MINGW)
    target_link_options(${LIB_NAME} PUBLIC -static)
endif (WIN32 AND MINGW) 

Проблемы начинаются при линковке приложения:

set(APP_NAME app)
add_executable(${APP_NAME})
target_sources(${APP_NAME} PRIVATE src/main.cpp) # main.cpp - сорс приложения
target_link_libraries(${APP_NAME} PRIVATE ${LIB_NAME})

На этапе линковки библиотеки к приложению ld выдаёт

multiple definition of `_Unwind_SjLj_Resume'

Судя по всему, это происходит от того, что опция -static передается приложению из-за PUBLIC спецификатора, и мы получаем 2 одинаковые версии libstd++ и libgcc, встроенные как в библиотеку, так и в приложение (1 функция импортируется из main.cpp, другая из some.cpp).

Если поставить

target_link_options(${LIB_NAME} PRIVATE -static)

, то ошибок линковки не возникает, но приложение (в отличие от библиотеки) требует динамический рантайм для запуска, что не соответствует цели.

Единственный "рабочий" вариант, который я пока нашёл, линковать библиотеку к приложению следующим образом:

target_link_libraries(${APP_NAME} PRIVATE -Wl,--whole-archive ${LIB_NAME} -Wl,--no-whole-archive)

Однако не до конца понимаю смысл этого флага и правильность решения. Также почему-то dependency walker продолжает показывать зависимоть от .dll, хотя сейчас запуск возможен без неё.

Какое решение правильное?

UPD: после удаления и восстановления папки с CMake-кешем и перезапуска dependency walker-а предложение "почему-то dependency walker продолжает показывать зависимоть от .dll" стало неактуально.

READ ALSO
Вопрос про abs и решение одной задачи на С++

Вопрос про abs и решение одной задачи на С++

Решалась задача: Шахматный король ходит по горизонтали, вертикали и диагонали, но только на 1 клеткуДаны две различные клетки шахматной доски,...

92
Владение ресурсом через указатель [дубликат]

Владение ресурсом через указатель [дубликат]

Чтобы не заморачиваться с написанием класса-обертки, думаю использовать лямбда + unique_ptr, иначе говоря, пишу

111