CMake 文档明确指出不建议为构建收集file(GLOB ...)
源文件,但没有提及推荐的方法实际上是什么。
手动指定每个源文件对我来说听起来有点太手动了。那么,如果不是,那么收集源文件的正确方法是什么
file(GLOB ...)
?
手动确实是推荐的方法。通过建议不要使用 GLOB,该文档只是对依赖于现有文件的构建系统发出警告。例如,您想添加一个测试可执行文件,因此您创建了 mytest.cpp。哎呀。现在你的库编译中断了。AUX_SOURCE_DIRECTORY 的文档(类似于源文件的通配符)给出以下警告:
使用此命令来避免为库或可执行目标编写源文件列表是很有诱惑力的。虽然这似乎可行,但 CMake 无法生成一个知道何时添加新源文件的构建系统。通常生成的构建系统知道何时需要重新运行 CMake,因为修改了 CMakeLists.txt 文件以添加新源。当源只是添加到目录而不修改此文件时,必须手动重新运行 CMake 以生成包含新文件的构建系统。
如果您确定想要目录的所有内容,并且不打算添加新内容,那么请务必使用 GLOB。
此外,不要忘记手动列出文件不必输入所有文件名。例如,您可以这样做,ls *.cpp >> CMakeLists.txt
然后使用您的编辑器将文件列表移动到文件中的正确位置。
我正是为此使用 GLOB,每次添加文件时我都会运行
touch ../src/CMakeLists.txt
下一个make
命令将重新扫描目录。
“CMake 无法生成一个知道何时添加新源文件的构建系统”真的吗?好吧,那就说吧!
它不是 100% 自动的,但比手动添加文件要容易得多。
我使用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安装方法及其他使用方法请阅读作者的文章。
我使用传统的 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
)
...
按照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