使用CMake自动将文件夹中的所有文件添加到目标吗?


162

我正在考虑将跨平台项目从Visual C ++,XCode和makefile中的单独生成管理系统切换到CMake。

我需要的一项基本功能是将目录中的所有文件自动添加到目标。尽管使用make可以轻松做到这一点,但使用Visual C ++和XCode却不容易做到(如果我做错了,请纠正我)。是否可以直接在CMake中进行?怎么样?


顺便说一句。在Visual Studio中,至少在C#项目中,项目浏览器中有一个工具栏按钮,名为“显示所有文件”。它使项目的所有子目录可见,如果它们不包含任何逻辑上包含在项目中的文件,则显示为灰色。您可以通过上下文菜单包括这些目录,该菜单递归包括其中的所有源文件:)
yeoman

Answers:


228

有可能的。例如file(GLOB

cmake_minimum_required(VERSION 2.8)

file(GLOB helloworld_SRC
    "*.h"
    "*.cpp"
)

add_executable(helloworld ${helloworld_SRC})

请注意,这需要手动重新运行cmake是否添加或删除了源文件,因为生成的构建系统不知道何时要求CMake重新生成,而在每次构建时都这样做会增加构建时间。


11
手动重新运行cmake的另一种方法是在运行make之前触摸CMakeLists.txt文件。
Seamus Connor 2015年


8
>“我们不建议您使用GLOB从源代码树中收集源文件列表。如果在添加或删除源文件时CMakeLists.txt文件没有更改,则生成的构建系统将无法确定何时要求CMake重新生成。” 由Hand1Cloud链接的CMAKE3.7文档中不再建议使用此方法

4
那么GLOB的替代方案是什么?
谢恩

13
这里建议使用自v3.1以来的更好方法:target_sources() crascit.com/2016/01/31/…–
Sheen

34

克莱斯特(Kleist)的答案确实有效,但有一个重要警告:

当您Makefile手动编写手册时,您可能会SRCS使用函数选择全部.cpp.h文件来生成变量。如果以后添加了源文件,则重新运行make将包括该文件。

但是,CMake(使用类似命令file(GLOB ...))将显式生成文件列表,并将其放置在自动生成的文件中Makefile。如果您有新的源文件,则需要Makefile通过重新运行来重新生成cmake

编辑:不需要删除Makefile。


4
无法仅简单地重新运行cmake,而是应该删除/修改过时的Makefile?
伊桑(Ethan)

24
这不是答案,而是有关@Kleist答案的评论。
Neowizard '16

3
@Neowizard不在Stackoverflow术语中。
kara deniz

1
这个评论很好,但这是“标准”,对不对?申请者已经在使用cmake,因此建议make可以“更聪明”并没有帮助。
frankliuao

那么有没有办法添加新的源文件,然后在不重新运行cmake的情况下进行构建?
artin

5

扩展@Kleist答案

从CMake 3.12开始,命令和都支持附加选项CONFIGURE_DEPENDS。使用此选项有没有需要手动添加/删除目录中的源文件后重新运行cmake - CMake的将是重新运行在未来建设项目自动。file(GLOB)file(GLOB_RECURSE)

但是,选项CONFIGURE_DEPENDS意味着每次请求构建时都会重新检查相应的目录,因此与没有CONFIGURE_DEPENDS相比,构建过程将花费更多时间

即使使用CONFIGURE_DEPENDS选项,CMake文档仍然不建议使用file(GLOB)file(GLOB_RECURSE)收集源。


-2

那么,为什么不使用Powershell为您创建源文件列表。看一下这个脚本

param (
    [Parameter(Mandatory=$True)]
    [string]$root 
)

if (-not (Test-Path  -Path $root)) {    
throw "Error directory does not exist"
}

#get the full path of the root
$rootDir = get-item -Path $root
$fp=$rootDir.FullName;


$files = Get-ChildItem -Path $root -Recurse -File | 
         Where-Object { ".cpp",".cxx",".cc",".h" -contains $_.Extension} | 
         Foreach {$_.FullName.replace("${fp}\","").replace("\","/")}

$CMakeExpr = "set(SOURCES "

foreach($file in $files){

    $CMakeExpr+= """$file"" " ;
}
$CMakeExpr+=")"
return $CMakeExpr;

假设您有一个具有这种结构的文件夹

C:\Workspace\A
--a.cpp
C:\Workspace\B 
--b.cpp

现在将此文件另存为“ generateSourceList.ps1”,然后以

~>./generateSourceList.ps1 -root "C:\Workspace" > out.txt

out.txt文件将包含

set(SOURCE "A/a.cpp" "B/b.cpp")

问题被标记为跨平台-Powershell不是跨平台。
reichhart

@reichhart PowerShell的工作在Linux和和Mac太
没有人

我知道。但是powershell没有标签,“ CMake”已经跨平台了。“ Powershell”将是一个附加的依赖项,并且很少在Windows以外的其他操作系统上使用。您可能会发现Linux上的C#开发人员比拥有Powershell的人员更多。最重要的事实是一个问题:“是否可以直接在CMake中实现?如何?”
reichhart
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.