How to handle a transitive dependency conflict using Git submodules and CMake?

后端 未结 2 464
轻奢々
轻奢々 2020-11-30 08:33

We have a number of Git repositories, some containing our own code and some containing slightly modified third-party library code. A simplified dependency graph looks like t

相关标签:
2条回答
  • 2020-11-30 09:17

    CMake 3.10 and later now support:

    include_guard(GLOBAL)
    

    Analogous to #pragma once in c++.

    A great book on cmake that explained so much to me is "Professional CMAKE, A Practical Guide" by Craig Scott. Available online only at: [https://crascit.com/professional-cmake/][1]

    I don't Craig, but his book is a great service to cmake newcomers like myself.

    0 讨论(0)
  • 2020-11-30 09:28

    There are several approaches for detect and discard inclusion of the project, which has already be included in some other parts of the main project.

    Check project's target existence

    The simplest pattern for single inclusion of subproject is checking existence of some subproject's target:

    # When include 'C' subproject
    if(NOT TARGET library_C)
        add_subdirectory(C)
    endif()
    

    (Here we assume that project C defines target library_C.)

    After such conditional inclusion all subproject's targets and functions will be immediately available for the caller with garantee.

    It is better to use this pattern in all places (in executable_A and library_B). Such a way changing order of library_B and library_C in executable_A doesn't break correctness.

    This pattern can be reworked for use by subproject itself:

    # At the beginning of 'C' project
    cmake_minimum_required(...)
    if(TARGET library_C)
        return() # The project has already been built.
    endif()
    
    project(C)
    ...
    

    Check project existence

    When a project is created, CMake defines several variables for it, and <PROJECT-NAME>_BINARY_DIR is among them. Note, that this variable is cached, so when cmake is called the second time (e.g. if some of CMakeLists.txt has been changed), the variable exists at the very beginning.

    # When include 'C' subproject
    if(NOT C_BINARY_DIR # Check that the subproject has never been included
        OR C_BINARY_DIR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/C" # Or has been included by us.
    )
        add_subdirectory(C)
    endif()
    

    This pattern can be reworked for use by subproject itself:

    # At the beginning of 'C' project
    cmake_minimum_required(...)
    if(NOT C_BINARY_DIR # Check that the project has never been created
        OR C_BINARY_DIR STREQUAL "${CMAKE_CURRENT_BINARY_DIR}" # Or has been created by us.
        project(C)
    else()
        return() # The project has already been built
    endif()
    
    0 讨论(0)
提交回复
热议问题