【问题标题】:CMake one build directory for multiple projectsC为多个项目创建一个构建目录
【发布时间】:2016-03-30 01:07:09
【问题描述】:

我是 CMake 的初学者。我的环境有几个项目,例如:

project
  |------ CMakeLists.txt (The main Cmake)
  |------ ProjectA
  |          |----- .cpp files
  |          |----- .hpp files
  |          |----- CMakeList.txt
  |------ ProjectB
  |          |----- .cpp files
  |          |----- .hpp files
  |          |----- CMakeList.txt
  | 
  |------ build
  |         |-----  CMakeStuff
  |------ bin
  |        |---- executables
  |------ lib
  |        |---- libwhatever.a
  |------ db 
           |---- Database stuff

我想为每个项目使用一个构建目录,如上所示。最好它可以分成多个子项目,比如build/projectAbuild/ProjectB,这样如果我需要重建一个项目,我可以删除整个build/Project文件,一切都消失了,一个新的Cmake将构建它再次。

我在配置 CMAKE 时遇到了困难。

我在项目文件夹上的原始 CMakeList.txt:

cmake_minimum_required(VERSION 3.2.2.)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../bin)

project(projectA)
set(CMAKE_BUILD_TYPE Debug)

file(GLOB SOURCES "*.cpp")

add_library(commonmessage SHARED ${SOURCES})

install(TARGETS commonmessage DESTINATION ../lib)

我的问题是:

A) 如果我在单个构建目录上运行 cmake 会发生什么 - 这可能吗?正确的 CMAKE 配置是什么?

B) 我对 ProjectA 的编译需要包含来自 ProjectB 的文件 - 我如何在 CMakeLists.txt 中为每个单独的项目设置它?

C) 最后,我需要一个 makefile 来构建所有项目,以及单独构建每个项目的选项。单个构建目录可以实现吗?

感谢您的帮助。

【问题讨论】:

    标签: c++ makefile cmake


    【解决方案1】:

    首先,您发布的 CMake 代码看起来不属于顶部 CMakeList.txt 文件,因为它直接引用 .cpp 文件和“projectA”。 还有一些不是惯用的:

    cmake_minimum_required(VERSION 3.2.2.)
    

    为什么是尾随点?不确定cmake是否会抱怨,但无论如何都没用。

    set(CMAKE_BUILD_TYPE Debug)
    

    不要那样做。而是使用 -DCMAKE_BUILD_TYPE=Debug 命令行标志调用 cmake,或使用 ccmake,或 GUI,或编辑 CMakeCache.txt 文件。

    file(GLOB SOURCES "*.cpp")
    

    也不要那样做。在 CMake 中明确列出源文件是一种很好的做法,因为通配不会使 cmake 自动检测新添加或删除的文件。不过有些人可能不同意。

    现在是主题的核心,以下是通常的处理方式:

    顶部 CMakeLists.txt 文件:

    cmake_minimum_required(VERSION 3.2.2)
    project(globalProject)
    
    add_subdirectory(projectA)
    add_subdirectory(projectB)
    

    ProjectA CMakeLists.txt 文件(假设 projectA 是可执行文件):

    add_executable(projectA file1.cpp file2.cpp ... )
    include_directories(${CMAKE_SOURCE_DIR}/projectB) # include files from ProjectB
    target_link_libraries(projectA projectB)
    
    install(TARGETS projectA RUNTIME DESTINATION bin)
    

    ProjectB CMakeLists.txt 文件(假设 projectB 是一个库):

    add_library(projectB file1.cpp file2.cpp ... )
    
    install(TARGETS projectB
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)
    

    请注意,此设置需要 make install 步骤在您选择的位置创建 bin 和 lib,如命令行调用 cmake -DCMAKE_INSTALL_PREFIX=.. 中给出的(假设 make 从构建目录运行)。

    此外,此设置允许您选择是要构建静态库还是共享库,方法是使用:-DBUILD_SHARED_LIBS=ON。要同时构建两者,您需要使用两个不同的名称进行两个 add_library 调用,一个是 STATIC,另一个是 SHARED。

    总结完成这项工作所需的步骤:

    $ mkdir build && cd build
    $ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=.. -DBUILD_SHARED_LIBS=ON
    $ make
    $ make install
    

    您可以将这些命令放在脚本中以实现可重用性。

    现在,您的问题可以得到解答:

    A) 可以并且推荐,参见上面的代码,只需要一个构建目录。

    B) 查看项目A/CMakeLists.txt的代码,你必须调用include_directories()

    C) 是的,这是可能的。可以使用 make 和目标名称从构建目录中单独构建项目中的每个目标:make projectBmake projectA

    【讨论】:

    • 先生,感谢您的帮助...如果我需要在目标文件夹中生成 lib 和 bin 文件而不需要 make install 怎么办?
    • 虽然可以使用CMAKE_*_OUTPUT_DIRECTORY 变量,但我不建议这样做,因为您可能有多个具有多种配置的构建目录(调试与发布、不同的编译器等)和在编译时能够在不覆盖文件的情况下并行测试它们总是好的。为什么在项目的根目录下需要 bin/lib?
    • 好点。 bin 是所有可执行文件的安装位置。 `lib' 将保存所有库。
    • install (TARGETS projectA, projectB... 正在发出 install TARGETS given target "projectA" which does not exist in this directory... 由于子目录而无法正常工作
    • 在声明目标后立即在两个特定的 CMakeLists.txt 文件中分别放置一个 install 调用是否有效?
    【解决方案2】:

    A) 您可以为 N 个项目执行 1 个 CMakeLists.txt。当你定义一个库时,你可以在cmake中定义的可执行文件中使用它(add_executable和target_link_libraries看)。

    B) 查看 target_include_directories

    C) 看来您可以调用cmake --target target 来仅为您的 cmakelists.txt 文件的目标之一生成 Makefile。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多