Visual Studio 2017的CMake多项目设置

3

首先,我对CMake还不熟悉。

我想做的是从在VS 2017中直接编译我的解决方案切换到CMake,以便在其他平台上(如Linux)轻松构建项目。

文件夹结构:

project
  |─── CMakeLists.txt
  |─── bin
  |     | ─── intermediates
  |     |       |─── Win32
  |     |       |      |─── Debug
  |     |       |      └─── Release
  |     |       └─── Linux
  |     |              |─── Debug
  |     |              └─── Release
  |     |─── Win32
  |     |      |─── Debug
  |     |      └─── Release
  |     └─── Linux
  |            |─── Debug
  |            └─── Release
  |─── include
  |─── Project 1
  |      |─── CMakeLists.txt
  |      |─── src
  |      |─── res
  |      └─── header
  └─── Project 2
         |─── CMakeLists.txt
         |─── src
         |─── res
         └─── header

CMake文件

这里是我的CMakeLists,第一个用于根项目,第二个则是为第一个和第二个项目编写的:

# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2)

# Project's name
project(Project X)

# Set the C++ Version
message("!REQUIRED! -- Supported features = ${cxx_std_14}")
message("Supported features = ${cxx_std_17}")

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Set the output folder where the program will be created

set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

# Add the modules
add_subdirectory(Project 1)
add_subdirectory(Project 2) # depends on Project 1

第一和第二个项目的CMakeLists.txt内容相同:
# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.8.2)

project(Project 1)

# In order to find all cpp files automatically for compilation
file(GLOB CPP_FILES src/*.cpp)
file(GLOB CPP_FILES header/*.h)

# Set the version number of the project here
set(VERSION_MAJOR "0")
set(VERSION_MINOR "1")
set(VERSION_PATCH "0")
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})

这是我的VS设置:

Output Directory:       $(SolutionDir)bin\$(Platform)\$(Configuration)\
Intermediate Directory: $(SolutionDir)bin\intermediates\$(Platform)\$(Configuration)\

在这种情况下,项目B是可执行文件,而项目A只是一个库,必须链接到项目B中,以便使项目B编译。

问题:

  • 我如何将Visual Studio 2017的设置应用于CMake?(我需要如何配置CMAKE_BINARY_DIR等设置)
  • 项目2依赖于项目1,CMake会自动处理还是我需要在CMakeLists.txt中添加一些内容?
1个回答

2

需要解决多个问题:

  1. CMAKE_BINARY_DIR is, for all intents and purposes, a read-only variable, and should definitely be treated as such. The way to specify the binary directory is to run CMake in that directory (when running from the command line), or set that directory as the binary/output directory (when using a CMake GUI). So in your case, to achieve the setup you claim you want, you'd do this:

    > cd project/bin
    > cmake .. -G "Visual Studio whatever" ...
    

    ("whatever" is, of course, a placeholder)

    However, I strongly suggest you do not use a layout like this. A much better layout would a purely out-of-source-build, like this:

    project
    project/source/CMakeLists.txt
    project/source/include
    project/source/...
    project/build/Win32
    project/build/Linux
    

    With this setup, you'd then run like this:

    > cd project/build/Win32
    > cmake ../../source -G "Visual Studio whatever" ...
    
  2. There is a conflict between how you're setting your binary output paths in CMake, and what you've presented as your "VS settings." I do not know which is your inteded state, but in case you want to set up CMake so that your binaries end up in the output directory you've listed in the VS settings, you'd do it like this:

    set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR})
    

    Ditto for LIBRARY_OUTPUT_PATH.

  3. As far as setting the intermediate directory goes, this is something CMake manages itself and you cannot really affect this. The question is why you'd want to, though.

  4. Regarding project dependencies: you haven't shown the CMake commands which actually create the binaries (add_library()/add_executable()) or commands which set up their properties. However, if you specify that the executable created by Project 2 links against the library created by Project 1, CMake will track the dependency correctly. You'd specify it like this:

    target_link_libraries(targetNameOfProject2executable targetNameOfProject1library)
    
  5. Please note that using file(GLOB) to construct a list of source files is a bad idea and is discouraged by CMake. The reason is simple: adding a source file will not cause the buildsystem to be regenerated, meaning the source file will not be picked up. If you instead list source files explicitly, adding the file will mean you must add it to the list in the CMakeList (or in a file included by it), which will trigger a re-generation of the buildsystem.

  6. A note for Linux: unlike Visual Studio, the Makefile generator (and in fact most of CMake's generators) are single-configuration, which means you must generate a buildsystem for each configuration. In the out-of-souce setup, you'd do it like this:

    > cd project/build/Linux/Debug
    > cmake ../../../../source -DCMAKE_BUILD_TYPE=Debug ...
    > cd project/build/Linux/Release
    > cmake ../../../../source -DCMAKE_BUILD_TYPE=Release ...
    

对1: 你能说一下为什么“纯外部源代码构建”会更好吗? 对2: 我希望CMake设置与VS中的设置相同。 对5: 我该如何实现编译所有源文件,因为我不想手动编写数百个文件。 - ShadowDragon
1
@ShadowDragon 1 这并不是严格必要的,但这是首选的CMake操作模式。“CMake out-of-source”应该可以在谷歌上找到。但你最初的想法,即目录至少是不同的,也是可以的。 2 这个答案展示了它的工作原理,它实际上也适用于你的“under-source”设置。 5 您可以将列表(set()调用)移动到一个单独的文件中,您将使用include()导入它,并使用脚本或其他工具为第一次生成它。然后只需手动更新它。 - Angew is no longer proud of SO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接