37

CMake 文档明确指出不建议为构建收集file(GLOB ...)源文件,但没有提及推荐的方法实际上是什么。

手动指定每个源文件对我来说听起来有点太手动了。那么,如果不是,那么收集源文件的正确方法是什么 file(GLOB ...)

4

5 回答 5

25

手动确实是推荐的方法。通过建议不要使用 GLOB,该文档只是对依赖于现有文件的构建系统发出警告。例如,您想添加一个测试可执行文件,因此您创建了 mytest.cpp。哎呀。现在你的库编译中断了。AUX_SOURCE_DIRECTORY 的文档(类似于源文件的通配符)给出以下警告:

使用此命令来避免为库或可执行目标编写源文件列表是很有诱惑力的。虽然这似乎可行,但 CMake 无法生成一个知道何时添加新源文件的构建系统。通常生成的构建系统知道何时需要重新运行 CMake,因为修改了 CMakeLists.txt 文件以添加新源。当源只是添加到目录而不修改此文件时,必须手动重新运行 CMake 以生成包含新文件的构建系统。

如果您确定想要目录的所有内容,并且不打算添加新内容,那么请务必使用 GLOB。

此外,不要忘记手动列出文件不必输入所有文件名。例如,您可以这样做,ls *.cpp >> CMakeLists.txt然后使用您的编辑器将文件列表移动到文件中的正确位置。

于 2012-06-06T13:21:47.823 回答
18

我正是为此使用 GLOB,每次添加文件时我都会运行

touch ../src/CMakeLists.txt

下一个make命令将重新扫描目录。

“CMake 无法生成一个知道何时添加新源文件的构建系统”真的吗?好吧,那就说吧

它不是 100% 自动的,但比手动添加文件要容易得多。

于 2014-02-04T19:43:58.170 回答
5

我使用cog,一个python模块。这是一个收集 .cpp 文件的示例:

CMakeLists.txt:

set(SRC_FILES "")

# [[[cog
#    import cog, glob
#    for src in glob.glob('*.cpp'):
#       if "skeleton" in src: continue
#       cog.outl("SET(SRC_FILES ${SRC_FILES} %s)" % src)
# ]]]
# [[[end]]]

add_library(mylib STATIC  ${SRC_FILES})

然后,运行:

python -m cogapp -r CMakeLists.txt

CMakeLists.txt 文件将就地更新。

cog安装方法及其他使用方法请阅读作者的文章

于 2015-05-25T07:23:58.947 回答
2

我使用传统的 CMakeLists.txt 和 python 脚本来更新它。添加文件后,我手动运行 python 脚本。

import os
import re       

def relFiles(base, sub):
    fullSub = os.path.join(base,sub)
    abs = [os.path.join(dp, f) for dp, dn, fn in os.walk(fullSub) for f in fn]
    return [os.path.relpath(f, base) for f in abs]

def updateAddLibrary(cmakelistsDir, subs):
    cmakelists = os.path.join(cmakelistsDir, "CMakeLists.txt")
    listings = [relFiles(cmakelistsDir, sub) for sub in subs]
    files = [f for listing in listings for f in listing] #flatten
    with open(cmakelists, 'r') as file:
        text = file.read()
    sources = "".join(["    %s\n" % f.replace('\\', '/') for f in files])
    text = re.sub(r"add_library\s*\(\s*([^\s\)]+).*?\)",
           r"add_library(\1\n%s)" % sources, 
           text, 1, re.DOTALL)
    with open(cmakelists, "w") as file:
        file.write(text)

dir = os.path.dirname(os.path.abspath(__file__))
updateAddLibrary(dir, ['inc','src'])

之前的例子:

...
add_library(MyLib
    inc/a.h
) 
...

后:

...
add_library(MyLib
    inc/a.h
    inc/sub/b.h
    src/a.cpp
)        
...
于 2018-01-18T09:56:30.033 回答
0

按照douyw的回答,谢谢您的回答。

不是 Cmake 专家,不想成为专家,我花了 3 个小时来尝试处理 GLOB(禁用)和 aux_source_directory(甚至不接近 GLOB),并且 douyw 救了我的命。

我添加了递归文件遍历,它在我的项目中工作:

首先,安装 cogapp python 模块(python -m pip install cogapp)

set(SRC_FILES "")

# [[[cog
#   import cog, os
#   for root, _, files in os.walk(".", topdown=False):
#       for f in files: 
#           if not "_unittest" in f: continue
#           if not f.endswith(".cpp"): continue
#           cog.outl('SET(SRC_FILES ${SRC_FILES} "%s")' % os.path.join(root, f).replace('\\', '/'))
# ]]]
# [[[end]]]

运行:python -m cogapp -r CMakeLists.txt

  • 上面的行将所有“*_unittest.cpp”添加到列表中
  • 您可以更改中间线以制定自己的规则,只是普通的 python。使用正则表达式更好,但简单的字符串搜索可以在上述情况下完成工作。
  • 注意最后一行,它需要替换 // 以更改为可用的通用分隔符。您可以在 Windows 中生成您的 CMakeList.txt。
  • 您可以将 SRC_FILES 替换为您想要的任何内容。
  • python 命令可以在 Jenkins/TeamCity 下运行,由 svn/git commit 触发。然后我们可以自动添加新文件。
于 2022-02-08T10:40:05.360 回答