Зависимости подмодулей CMake

#cmake

#cmake

Вопрос:

У меня есть проект CMake с двумя подмодулями A и B . B зависит от A . В подмодуле B я хотел бы выполнить поиск A с помощью find_package(A CONFIG) . Мой минимальный (не) рабочий пример был бы:

 CMakeLists.txt
   cmake_minimum_required(VERSION 3.13)
   project(AB)
   add_subdirectory(B)
   add_subdirectory(A)
A/CMakeLists.txt:
   message(STATUS "CMake: A")
   add_library(A SHARED A.hpp A.cpp)
   target_include_directories(A PUBLIC "${CURRENT_SOURCE_DIR}")
   install(TARGETS A EXPORT AA LIBRARY DESTINATION lib/)
   export(TARGETS A NAMESPACE AA:: FILE ${CMAKE_BINARY_DIR}/A/AConfig.cmake)
   export(PACKAGE AA)
A/A.hpp (some non-sense code)
A/A.cpp
B/CMakeLists.txt
   find_package(A CONFIG)
   message(STATUS "---> ${A_FOUND}")
   add_library(B B.hpp B.cpp)
   target_link_libraries(B AA::A)
B/B.hpp (some non-sense code)
B/B.cpp
  

A/CMakeList.txt корректно выдает AConfig.cmake . Но, насколько я понимаю, это происходит после того, как (!) find_package(A CONFIG) вызывается и, следовательно AConfig.cmake , не найдено.
Есть идеи, как заставить find_package() запускаться после A выполнения?

Конечно, я знаю, что в этом примере find_package это не имеет никакого смысла. В моем реальном проекте подмодули являются внешним программным обеспечением, которое я не хочу изменять (в моем случае parallelSTL и TBB).

Комментарии:

1.Вам необходимо установить или, по крайней мере, собрать проект A перед использованием find_package(A) . Поскольку сборка выполняется после завершения этапа конфигурирования, когда CMakeLists.txt обрабатываются скрипты, вы не можете включить оба проекта в add_subdirectory и ожидать, что все будет работать. Для A немедленной сборки проекта вы можете использовать execute_process command.

2. Я не совсем понял, что вы имеете в виду, можете ли вы поменять порядок add_subdirectory(B) и add_subdirectory(A) ?

Ответ №1:

Действительно, cmake в настоящее время должным образом не поддерживает это. Обсуждение планов на будущее можно найти здесь. Вот мой уродливый обходной путь:

 A/CMakeLists.txt:
   message(STATUS "CMake: A")
   add_library(A SHARED A.hpp A.cpp)
   target_include_directories(A PUBLIC "${CURRENT_SOURCE_DIR}")
   install(TARGETS A EXPORT AA LIBRARY DESTINATION lib/)
   export(TARGETS A NAMESPACE AA:: FILE ${CMAKE_BINARY_DIR}/A/AConfig.cmake)
   export(PACKAGE AA)

   add_library(AA::A ALIAS A)
   file(WRITE ${CMAKE_BINARY_DIR}/A/AConfig.cmake "")
   # include(CMakePackageConfigHelpers)
   # write_basic_package_version_file(
   #   ${CMAKE_BINARY_DIR}/A/AConfigVersion.cmake
   #   VERSION 1.0.0
   #   COMPATIBILITY AnyNewerVersion)
  

Итак, идея состоит в том, чтобы создать фиктивный файл AConfig.cmake . Это перезаписывается позже, но это гарантирует, что find_package() не произойдет сбой до его фактического создания. Затем нам нужно переименовать цель A в имя после импорта AA::A . В случае, если существует требование к версии A , также необходимо создать файл AConfigVersion.cmake .
Я создал MWE на github.