Я работаю над перемещением базы кода в cmake, где в зависимости от того, какой исполняемый файл создается, требуются разные реализации конкретной библиотеки.В некоторых случаях это происходит из-за того, что полученные исполняемые файлы имеют разные требования / возможности, но во многих случаях мы можем использовать реализации, которыми можно управлять с помощью модульных тестов, которые не используются в рабочей среде.
Поскольку библиотеки нуждаются вЧтобы зависеть от интерфейсов, а не от реализаций, в некоторых случаях cmake не может правильно построить дерево зависимостей, что приводит к сбою шага компоновки (проблема описана здесь ).
Например, рассмотримследующий надуманный пример.Существует 2 библиотеки a & b, где b зависит от a, а a имеет две реализации.Я определил цели следующим образом в CMakeLists.txt
:
add_library(lib-a-intf INTERFACE)
target_include_directories(lib-a-intf INTERFACE lib-a)
add_library(lib-a-impl-a impl-a/impl-a.cpp)
target_link_libraries(lib-a-impl-a PUBLIC lib-a-intf)
add_library(lib-a-impl-b impl-b/impl-b.cpp)
target_link_libraries(lib-a-impl-b PUBLIC lib-a-intf)
add_library(lib-b lib-b.cpp)
target_link_libraries(lib-b PRIVATE lib-a-intf)
target_include_directories(lib-b PUBLIC lib-b)
А затем исполняемый файл извлекает нужную ему версию в соответствии с его требованиями
add_executable(main main.cpp)
target_link_libraries(main lib-a-impl-b lib-b)
Поскольку cmake не может установитьдо правильного порядка ссылок, это не может сделать ссылку на неопределенную ссылку для функций, определенных в библиотеке a.
Я знаю несколько обходных путей, но они не оптимальны.Определение библиотеки a реализации как библиотеки объектов работает, но не хорошо масштабируется, так как эти реализации будут перекомпилированы для каждого исполняемого файла.Использование флага компоновщика --whole-archive
также работает, но также плохо масштабируется, так как приводит к тому, что исполняемые файлы больше, чем необходимо, поскольку невостребованные символы в библиотеке a не будут собирать мусор.
Есть ли способ в cmakeуказать, что библиотека реализует интерфейсную библиотеку, так что порядок ссылок правильный?Кроме того, есть ли способ изменить способ определения библиотек для решения этой проблемы?