【问题标题】:Compiling and linking subproject library with CMake使用 CMake 编译和链接子项目库
【发布时间】:2015-12-01 17:22:15
【问题描述】:

我有 2 个项目(prj1 和 prj2)。一个(prj2)依赖于另一个(prj1),它是一个静态库。我来用 CMake 分别编译它们。

但我需要将一个 (prj1) 集成到另一个 (prj2)。所以我希望CMake在另一个(prj2)之前编译静态库(prj1),然后链接静态库。我试过了,但 id 没有用。

在 prj2 中,externals/core 是一个 git 子模块(对于非 git 用户,您可以将此目录视为 prj1 的复制粘贴)。 我在prj2“SDL2”中尝试了(没有成功)这个CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)


if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
    "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
  set(CMAKE_CXX_FLAGS       "-Wall -Wextra -Wformat=2 -Wpedantic -D_FORTIFY_SOURCE=2")
  set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
  # TODO
endif()

set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
# if (CMAKE_VERSION VERSION_LESS "3.1")
#   if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
#       CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
#     set (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
#   endif()
# else()
#   set(CMAKE_CXX_STANDARD 11)
# endif()

project(PlanetWars2dRT-SDL2)

# Version number
set(VERSION_MAJOR "0")
set(VERSION_MINOR "0")
set(VERSION_MICRO "0")

# Configure a header file to pass some of the CMake settings
# to the source code.
configure_file (
  "src/compilation_config.h.in"
  "${PROJECT_BINARY_DIR}/compilation_config.h"
  )
# Add the binary tree to the search path for include files
# so that we will find compilation_config.h
include_directories("${PROJECT_BINARY_DIR}")

set(LIBRARY_OUTPUT_PATH    lib/${CMAKE_BUILD_TYPE})
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})

include_directories(src/)
file(
  GLOB_RECURSE
  source_files
  src/*
  )
add_executable(planet-wars-2d-rt-sdl2 ${source_files})

#include(ExternalProject)
#ExternalProject_Add(PlanetWars2dRT PREFIX externals/core/)
include_directories(externals/core/src/utils/ externals/core/src/specific/)
add_subdirectory(externals/core/)
#find_package(PlanetWars2dRT-core REQUIRED)

include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
pkg_search_module(SDL2GFX REQUIRED SDL2_gfx)
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIRS})
target_link_libraries(
  planet-wars-2d-rt-sdl2
  planet-wars-2d-rt-core
  ${SDL2_LIBRARIES} ${SDL2GFX_LIBRARIES}
  )

那是prj2树的简化版:

.
├── build (with CMake stuff generated with "cmake ..")
├── CMakeLists.txt
├── externals
│   └── core
│       ├── build (with CMake stuff generated with "cmake ..")
│       ├── CMakeLists.txt
│       ├── makefile
│       └── src
├── makefile
├── README.md
└── src
    ├── compilation_config.h.in
    └── planet-wars-2d-rt-sdl2.cpp

如何使用 CMake 编译 prj2 "SDL2" 中的 prj1 "core" 库,然后将 prj1 的库与 prj2 链接(再次使用 CMake)?

如果您的解决方案不适用于非 GNU/Linux 操作系统,那也不是什么大问题。注意:我的电脑在 Debian GNU/Linux 8 "Jessie" 上运行。

问候。

【问题讨论】:

    标签: compilation cmake subproject


    【解决方案1】:

    我无法访问您的 repo https://gitlab.com/RyDroid/PlanetWars2dRT-SDL2/,可能服务器因维护而停机。如果我正确理解您的问题,您可以创建这样的结构:

    根/

    • CMakeLists.txt // 1
    • 源/
      • CMakeLists.txt // 2
      • main.cpp
      • SDL2/
        • 一些来源
        • CMakeLists.txt // 3
      • 核心/
        • 一些来源
        • CMakeLists.txt // 4

    在 CMakeLists.txt [1] 中,您应该声明您的项目名称、所需的包、常用标志、包含路径等:

    cmake_minimum_required( VERSION 2.x )
    project(name)
    
    include_directories(inc inc/core inc/SDL2 inc/SthElse)
    
    add_subdirectory(src)
    

    在子目录 src 的 CMakeLists.txt [2] 中,您应该声明您的主要可执行文件,并使用您的 prj1 和 prj2 添加子目录

     add_subdirectory(core)
     add_subdirectory(SDL2)
     add_executable(main main.cpp)
     target_link_libraries(main core SDL2 SomeOtherLib)
    

    最后,在您的 lib 目录中的 CMakeLists.txt [3] && [4] 中,您应该声明静态库:

     add_library(core STATIC ${YourSourceFiles})
    

    这种方法一直对我有用。如果您曾经将“core”和“SDL2”作为独立的二进制文件编译和运行,那么您可能需要稍微重新组织它们。

    【讨论】:

    • 我可以毫无问题地访问 repo。我已经用文件组织更新了我的第一篇文章。它(prj2 中的 CMake)尝试编译“externals/core/src/specific/planet-wars-2d-rt-text.cpp”(这不是库的一部分,因此对 prj2“SDL2”无用),但它失败了因为找不到 LIB_PLANET_WARS_2D_RT_CORE_VERSION_MAJOR。这个宏在“externals/core/build/compilation_config.h”中定义(由“externals/core/src/specific/compilation_config.h.in”用CMake生成)。
    • 是否必须将lib(此处为SDL)放在主项目的根目录下?如果我将我的(供应商第三方)存储在我的源上方的其他地方,它仍然可能吗?似乎add_subdirectory 拒绝到顶部的相对路径。
    • @Sandburg,是的,如果你想编译这个库作为你项目的一部分,它应该在主项目的根目录下;如果你把它放在外面,这基本上意味着这个库不是你项目的一部分——那么你可以单独编译它,安装(系统或本地)并在你的项目中使用find_package(如果库提供了适当的@ 987654327@ 脚​​本,SDL2 支持)
    【解决方案2】:

    两个项目都有一个文件“compilation_config.h”。编译时,取错所以编译失败,因为使用的代码是#include "compilation_config.h",有歧义。

    所以我在两个项目中创建了一个“include/project-name”目录,并更改了包含路径:“prj1/compilation_config.h”或“prj2/compilation_config.h”。多亏了它不再有歧义,所以它现在可以工作了!

    【讨论】:

      猜你喜欢
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多