CMake: как создавать двоичные файлы "как можно более статичными"
Я хотел бы иметь контроль над типом библиотек, которые обнаруживаются/связаны с моими двоичными файлами в CMake. Конечной целью является создание двоичных файлов "как можно более статических", чтобы связать статически с каждой библиотекой, которая имеет статическую версию. Это важно, так как позволит переносить двоичные файлы в разных системах во время тестирования.
Банкомат это, кажется, довольно сложно достичь, поскольку пакеты FindXXX.cmake, или, точнее, команда find_library всегда подбирает динамические библиотеки, когда доступны как статические, так и динамические.
Подсказки о том, как реализовать эту функциональность - желательно элегантным способом, - очень приветствуются!
Ответы
Ответ 1
Я провел некоторое расследование, и хотя я не мог найти удовлетворительного решения проблемы, я нашел половину решения.
Проблема статических построений сводится к 3 вещам:
-
Создание и связывание внутренних библиотек проекта.
Довольно просто, просто нужно перевернуть переключатель BUILD_SHARED_LIBS
OFF
.
-
Поиск статических версий внешних библиотек.
Единственный способ, по-видимому, установить CMAKE_FIND_LIBRARY_SUFFIXES
, чтобы содержать нужный суффикс файла (его список приоритетов).
Это решение довольно "грязное" и очень похоже на кросс-платформенное стремление CMake. IMHO это должно быть обработано за кулисами CMake, но, насколько я понял, из-за путаницы ".lib" в Windows кажется, что разработчики CMake предпочитают текущую реализацию.
-
Связывание статически с системными библиотеками.
CMake предоставляет опцию LINK_SEARCH_END_STATIC
, которая основана на документации: "Завершите линию ссылок, чтобы использовать статические системные библиотеки".
Казалось бы, вот и все, проблема решена. Однако, похоже, что текущая реализация не соответствует задаче. Если опция включена, CMake генерирует неявный вызов компоновщика с списком аргументов, который заканчивается параметрами, переданными компоновщику, включая -Wl,-Bstatic
. Однако этого недостаточно. Только указание компоновщика связывать статически приводит к ошибке, в моем случае: /usr/bin/ld: cannot find -lgcc_s
. То, что не хватает, говорит gcc, что нам нужна статическая привязка через аргумент -static
, который не генерируется вызовом компоновщика с помощью CMake. Я думаю, что это ошибка, но мне пока не удалось получить подтверждение от разработчиков.
Наконец, я думаю, что все это могло и должно быть сделано CMake за кулисами, ведь это не так сложно, за исключением того, что это невозможно в Windows - если это считается сложным...
Ответ 2
Хорошо сделанный файл FindXXX.cmake будет содержать что-то для этого. Если вы посмотрите в FindBoost.cmake, вы можете установить переменную Boost_USE_STATIC_LIBS, чтобы контролировать, обнаруживает ли она статические или разделяемые библиотеки. К сожалению, большинство пакетов не реализуют это.
Если модуль использует команду find_library (чаще всего), вы можете изменить поведение CMake с помощью переменной CMAKE_FIND_LIBRARY_SUFFIXES. Здесь соответствующий код CMake из FindBoost.cmake, чтобы использовать это:
IF(WIN32)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ELSE(WIN32)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
ENDIF(WIN32)
Вы можете либо поставить это перед вызовом find_package, либо, лучше, сами изменить файлы .cmake и внести свой вклад в сообщество.
Для файлов .cmake, которые я использую в своем проекте, я сохраняю их все в своей папке в исходном элементе управления. Я сделал это, потому что обнаружил, что наличие правильного файла .cmake для некоторых библиотек противоречиво и сохранение моей собственной копии позволило мне внести изменения и гарантировать, что все, кто проверил код, будут иметь одинаковые системные файлы сборки.