CMake和Visual Studio - 指定解决方案文件目录

9
我为我的项目定义了一个CMakeLists.txt文件,并且它可以正常工作。我使用CMake GUI来生成Visual Studio项目,并指定将二进制文件(CMake缓存和其他内容)构建到与CMakeLists.txt相同的Build文件夹中。我已经能够指定可执行文件和库文件的创建位置,但有没有方法指定Visual Studio解决方案文件的创建位置呢?我希望它在根目录中,但同时我不想在Build目录中也包含CMake创建的所有其他文件。
CMake会创建我在CMakeLists.txt中定义的项目,但还会创建两个其他项目:ALL_BUILDZERO_CHECK。它们有什么用途?我使用命令set_property(GLOBAL PROPERTY USE_FOLDERS On)避免创建ZERO_CHECK,但有没有方法避免创建ALL_BUILD
2个回答

9

看起来你最近才开始使用CMake,当我第一次开始使用CMake时也会有这些问题。让我们按照你发布的顺序来解决这些问题:

我使用CMake GUI生成Visual Studio项目,并要求在与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解决方案感觉不同。这需要一些时间来适应,但最终体验比人们所担心的要少痛苦得多。

如果它们的外观确实让你很烦,考虑将它们移动到解决方案内部的文件夹,这样你就不必一直看着它们了。


2
感谢您提供完整的答案。我理解了大部分您的观点,并且同意它们。源外构建的想法非常强大。我希望将解决方案文件与项目文件(每种类型 *.vcxproj 和 *.vcxproj.filter 都有 3 个)放在不同的文件夹中的唯一原因是,最终您必须打开解决方案才能使用它。而且最好将此文件与项目文件和 CMake 文件分开...但可能可以通过软链接解决此问题。 - Maverik
3
+1,只想补充一点,将解决方案文件保存在临时文件夹中可以再次提醒您,生成cmake -> *.sln是单向过程,所有*.sln的修改都会在重新生成后丢失。 - user2288008
虽然源外编译很好并且有它们的应用,但源内编译也可以很方便。关于使用源外编译进行版本控制更容易的评论,我不太同意。你总是可以将源内编译目录添加到.gitignore中,从而避免意外添加其中的内容。 - rbaleksandar

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,但我没有尝试得太努力,因为这会添加一堆我不想要的额外杂乱无章的东西——所以也许这可以被弄好。

这段代码非常棒,完全满足了我的需求,谢谢! - autonomy

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