Search code examples
cmakecpack

How to check whether include(CPack) is already being called before or not in CMake?


I am working on a project that uses a third party source as a submodule. In the third party source of the CMakeLists.txt they have include(CPack) in their CMakeLists.txt, and this is causing problems because when I write my own include(CPack) in the CMakeLists.txt of my project, I get cmake config warnings like

CPack.cmake has already been included!!

and all the CPack variables I wrote are overwritten by the third party source, which causes errors when I run make package

I attempted add_subdirectory(third-party-source EXCLUDE_FROM_ALL), which ignores all the install calls in the third party source, but unfortunately it didn't ignore the CPack calls.

Is there a way for me to add something like

if(CPACK_ALREADY_INCLUDED)
  include(CPack)
endif()

in the third party source to work around this problem?


Solution

  • To override 3rd-party misbehavior is never easy. This is why I personally do not favor add_subdirectory and prefer to use vcpkg or another build orchestration tool (like Conan) instead.

    However, the following snippet should work:

    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()
    

    This will create a blank CPack module and trick the third party code into including it rather than the standard module. The function exists to make sure this overriding behavior can't leak out into the rest of your build.


    I had misread your question. I thought you were in control of the project that included CPack.

    Yes, the variable is named CPack_CMake_INCLUDED. However, it is better to check whether you are the top-level project and conditionally include your packaging rules, like this:

    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 ()