本文介绍了CMake并使用git-submodule进行依赖项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下三个项目。

ProjectA 没有任何依赖关系,它的 CMakeLists.txt 如下所示,

ProjectA does not have any dependencies and its CMakeLists.txt at top level is like the following,

cmake_minimum_required(VERSION 2.8.4)
project(A CXX)
add_library(a ${PROJECT_SOURCE_DIR}/liba.cpp)

ProjectB 取决于 ProjectA ,然后添加 ProjectA 作为git子模块,因此其结构如下所示:

ProjectB depend on ProjectA, and I add ProjectA as a git-submodule, so its structure will be like below,


  • ProjectB


    • CMakeLists.txt

    • libb.cpp

    • ProjectA (git子模块)


      • CMakeLists.txt

      • liba.cpp

      • ProjectB
        • CMakeLists.txt
        • libb.cpp
        • ProjectA (git submodule)
          • CMakeLists.txt
          • liba.cpp

          ProjectB CMakeLists.txt 如下所示

          cmake_minimum_required(VERSION 2.8.4)
          project(B CXX)
          add_subdirectory(ProjectA)
          add_library(b ${PROJECT_SOURCE_DIR}/libb.cpp)
          target_link_libraries(b a)
          

          到目前为止,还可以。

          现在,我们说它来自 ProjectC 。它取决于 ProjectA ProjectB 。并假设我不知道 ProjectB 已经依赖于 ProjectA (例如,我之前没有创建两者或认为 ProjectC 实际上有很多依赖关系,我不会被迫找出其中的确切依赖关系树。

          Now let's say it comes a ProjectC. It depends on both ProjectA and ProjectB. And let's assume that I am not aware that ProjectB depends on ProjectA already (e.g., I did not create the two before. Or think that ProjectC actually have many dependencies and I shall not be forced to figure out an exact dependency tree among them).

          无论如何,我将 ProjectA ProjectB 添加为 ProjectC 。因此它具有以下结构,

          Anyway, I add both ProjectA and ProjectB as git submodules in ProjectC. So it has the following structure,


          • ProjectC


            • CMakeLists.txt

            • libc.cpp

            • ProjectA (git子模块)


              • CMakeLists.txt

              • liba.cpp

              • ProjectC
                • CMakeLists.txt
                • libc.cpp
                • ProjectA (git submodule)
                  • CMakeLists.txt
                  • liba.cpp

                  • CMakeLists.txt

                  • libb.cpp

                  • ProjectA (子模块 ProjectB 的git子模块)


                    • CMakeLists.txt

                    • liba.cpp

                    • CMakeLists.txt
                    • libb.cpp
                    • ProjectA (git submodule of the submodule ProjectB)
                      • CMakeLists.txt
                      • liba.cpp

                      它具有以下 CMakeLists.txt

                      cmake_minimum_required(VERSION 2.8.4)
                      project(C CXX)
                      add_subdirectory(ProjectA)
                      add_subdirectory(ProjectB)
                      add_library(c ${PROJECT_SOURCE_DIR}/libc.cpp)
                      target_link_libraries(c a b)
                      

                      现在,如果我尝试运行 cmake 对于 ProjectC ,出现以下错误。

                      Now if I try to run cmake for ProjectC, I get the following error.

                      add_library cannot create target "a" because another target with the same
                      name already exists....
                      



                      ProjectA 两次作为子目录添加,并且 add_library 创建的所有目标都是全局。对于这种特殊情况,我可以通过删除 ProjectC / CMakeLists.txt 中的 add_subdirectory(ProjectA)来解决。但是,请考虑以下情况: ProjectC 有很多依赖项,并且它们之间可能有也可能没有依赖项。从 ProjectC 的开发人员的角度来看,他不必关心其依赖关系之间的相互依赖关系。

                      I understand the reason of this error. It is because ProjectA is added as a subdirectory twice and all targets created by add_library is Global. For this particular case, I can fix it by remove add_subdirectory(ProjectA) in the ProjectC/CMakeLists.txt. However, consider a situation that ProjectC has many dependencies, and there might or might not be dependencies among them. From point of view of the developer of ProjectC, he should not need to care about the inter-dependencies among its own dependencies.

                      在这种情况下,使 ProjectC 包括其依赖项的最佳方法是什么?必须具有 ProjectA ProjectB 作为源形式的git-submodule。我知道我可以简单地将 ProjectA ProjectB 安装在 ProjectC 只需要在某处找到已安装的文件。但是,如果可能的话,我想避免这种解决方案(例如,如果安装所使用的ABI与 ProjectC 使用的ABI不同),则会出现不兼容问题)。我希望所有三个项目都在 ProjectC 的构建树中构建。

                      In this situation, what is the best way to have ProjectC include its dependencies? Having ProjectA and ProjectB as a git-submodule in source form is a must. I am aware that I can simply install ProjectA and ProjectB somewhere, and ProjectC only need to find the installed files somewhere. However, if possible, I would like to avoid that kind of solution (for example, if the installation was built with a different ABI than the one used by ProjectC, incompatibility issues arise). I would like all three projects to be built inside the build tree of ProjectC.

                      推荐答案

                      您可以在调用 add_subdirectory 之前检查目标 a 是否已经存在:

                      You can check whether the target a already exists before calling add_subdirectory:

                      if (NOT TARGET a)
                        add_subdirectory(ProjectA)
                      endif ()
                      

                      ,因此它只为整个CMake项目添加一次子目录。

                      so that it only adds the subdirectory once for your whole CMake project.

                      这篇关于CMake并使用git-submodule进行依赖项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 08:01