8

我已经CMakeLists.txt为我的项目定义了一个可以正常工作的文件。

我使用 CMake GUI 生成 Visual Studio 项目,并要求Build在位于同一文件夹中的文件夹中构建二进制文件(CMAke 缓存和其他东西) CMakeLists.txt

我能够指定必须在哪里创建可执行文件和库。有没有办法指定必须在哪里创建 Visual Studio 解决方案文件?我想将它放在根目录中,但同时我不希望 CMake 在 Build 目录中创建所有其他文件。

CMake 创建了我在其中定义的项目以及CMakeLists.txt另外两个项目:ALL_BUILDZERO_CHECK. 它们的用途是什么?我能够ZERO_CHECK通过使用命令来避免创建set_property(GLOBAL PROPERTY USE_FOLDERS On)。有没有办法避免创建ALL_BUILD

4

2 回答 2

10

看来您最近才切换到 CMake,因为当我第一次开始使用 CMake 时,这些问题也突然出现在我的脑海中。让我们按照您发布它们的顺序来解决它们:

我使用 CMake GUI 生成 Visual Studio 项目,并要求在 Build 文件夹中构建二进制文件(CMAke 缓存和其他内容),该文件夹位于 CMakeLists.txt 所在的同一文件夹中。

不。始终使用 CMake进行源外构建。我知道,当你第一次这样做时感觉很奇怪,但相信我:一旦你习惯了,你就再也不想回去了。

当代码和构建文件正确分离时,使用源代码控制变得更加方便,这使得它成为 CMake 的杀手级功能。

有没有办法指定必须在哪里创建 Visual Studio 解决方案文件?

你真的不应该在意。

我明白为什么您确实觉得您需要完全控制解决方案和项目文件的创建方式,但您确实不需要。只需将解决方案的目标指定为源外构建的来源,然后忘记生成的所有其他文件。你不需要担心,你也不想担心——这正是 CMake 应该为你处理的事情

问问自己:如果您可以手动选择每个项目文件的位置,您将获得什么?没什么,因为很有可能,你无论如何都不会碰它们。CMake 现在是你唯一的主人......

CMake 创建了我在 CMakeLists.txt 中定义的项目,还创建了另外两个项目:ALL_BUILD 和 ZERO_CHECK。它们的用途是什么?通过使用命令 set_property(GLOBAL PROPERTY USE_FOLDERS On),我能够避免创建 ZERO_CHECK。有没有办法避免创建 ALL_BUILD?

再说一次,你真的不应该关心。CMake 定义了几个虚拟项目,它们对于您不想担心的某些内部巫术非常有用。一开始它们看起来很奇怪,但你会比你想象的更快地适应它们的视线。只是不要试图把它们扔掉,因为它不能正常工作。如果他们的视线真的让您非常恼火,请考虑将它们移动到解决方案内的文件夹中,这样您就不必一直看着它们。

底线:CMake 在几个方面与手工制作的 VS 解决方案不同。这需要一些时间来适应,但最终是一种比人们可能担心的痛苦少得多的经历。

于 2013-11-08T19:32:34.983 回答
1

您并不总是可以选择您的环境需要什么。Visual Studio 的 GitHub 集成要求解决方案文件存在于源代码管理中并且位于源代码树的根目录中。这是一个记录在案的限制。

我能想到的最好的方法是将这一点添加到 CMakeList.txt 中:

# The solution file isn't generated until after this script finishes, 
# which means that:
#   - it might not exist (if this is the first run)
#   - you need to run cmake twice to ensure any new solution was copied
set(sln_binpath ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.sln)
if(EXISTS ${sln_binpath})
    # Load solution file from bin-dir and change the relative references to 
    # project files so that the in memory copy is as if it had been built in 
    # the source dir.
    file(RELATIVE_PATH prefix 
        ${CMAKE_CURRENT_SOURCE_DIR} 
        ${CMAKE_CURRENT_BINARY_DIR})
    file(READ ${sln_binpath} sln_content)
    string(REGEX REPLACE 
        "\"([^\"]+).vcxproj\""
        "\"${prefix}/\\1.vcxproj\"" 
        sln_content
        "${sln_content}")

    # Compare the updated contents with the existing source path sln, if it
    # exists and is the same we don't want to disturb VS by touching it.
    set(sln_srcpath ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.sln)
    set(old_content "")
    if(EXISTS ${sln_srcpath})
        file(READ ${sln_srcpath} old_content)
    endif()
    if(NOT old_content STREQUAL sln_content)
        file(WRITE ${sln_srcpath} ${sln_content})
    endif()
endif()

如果 cmake 有办法运行后期生成脚本,但我找不到,这会有所帮助。

其他没有成功的想法:

  1. 将 cmake 包装在执行相同操作的脚本中,但是:
    • 告诉用户运行单独的脚本并不比说运行 cmake 两次简单。特别是因为需要运行两次 cmake 并不是一个陌生的概念。
  2. 把它放在预构建步骤中,但是
    • 构建是常见的,而改变构建是罕见的
    • 从 IDE 内部的构建中更改解决方案使其能够...
  3. 使用 add_subdirectory 因为那应该先完成
    • 它似乎立即制作了 vcxproj,但直到后来才制作了 sln,但我没有那么努力,因为这增加了一堆我不想要的额外混乱 - 所以也许这可以工作
于 2016-10-09T22:35:23.807 回答