#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.