Как проверить, вызывается ли include(CPack) ранее или нет в CMake?

#cmake #cpack

Вопрос:

Я работаю над проектом, в котором в качестве подмодуля используется сторонний источник. В стороннем источнике CMakeLists.txt они имеют include(CPack) в своем CMakeLists.txt, и это вызывает проблемы, потому что, когда я пишу свое собственное include(CPack) в CMakeLists.txt в моем проекте я получаю предупреждения конфигурации cmake, такие как

 CPack.cmake has already been included!!
 

и все переменные CPack, которые я написал, перезаписаны сторонним источником, что вызывает ошибки при запуске make package

Я попытался add_subdirectory(third-party-source EXCLUDE_FROM_ALL) , который игнорирует все install вызовы в стороннем источнике, но, к сожалению, он не игнорировал вызовы CPack.

Есть ли способ для меня добавить что-то вроде

 if(CPACK_ALREADY_INCLUDED)
  include(CPack)
endif()
 

в стороннем источнике, чтобы обойти эту проблему?

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

1. EXCLUDE_FROM_ALL применяется только к целям, созданным в этом каталоге и ниже, поэтому нет абсолютно никаких причин, по которым он игнорировал include() бы директиву.

Ответ №1:

Преодолеть неправильное поведение третьих лиц никогда не бывает легко. Вот почему я лично не одобряю add_subdirectory и предпочитаю использовать vcpkg или другой инструмент оркестровки сборки (например, Conan) вместо этого.

Однако следующий фрагмент кода должен работать:

 function (add_third_party)
  # Write an empty CPack module
  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/override/CPack.cmake" "")
  set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_BINARY_DIR}/override;${CMAKE_MODULE_PATH}")
  add_subdirectory(third-party-source)
endfunction ()

add_third_party()
 

Это создаст пустой модуль CPack и заставит сторонний код включить его вместо стандартного модуля. Функция существует для того, чтобы убедиться, что это переопределяющее поведение не может просочиться в остальную часть вашей сборки.


Я неправильно истолковал ваш вопрос. Я думал, что вы контролируете проект, который включает CPack в себя .

Да, переменная имеет имя CPack_CMake_INCLUDED . Тем не менее, лучше проверить, являетесь ли вы проектом верхнего уровня, и условно включить свои правила упаковки, как это:

 string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" is_top_level)
option(MyProj_INCLUDE_PACKAGING "Include packaging rules for MyProj" "${is_top_level}")

if (MyProj_INCLUDE_PACKAGING)
    # ...
    include(CPack)
endif ()
 

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

1. CPack_CMake_INCLUDED на самом деле работает. Интересно, почему это не упоминается в cmake.org/cmake/help/latest/module/CPack.html

2. Не уверен. Хотя это было в источниках целую вечность.