如何使用CMake收集源文件而不使用globbing?

时间:2012-06-06 12:52:42

标签: build cmake

CMake documentation明确指出file(GLOB ...)不是 建议收集构建的源文件,但事实并非如此 提到实际推荐的方法是什么。

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

4 个答案:

答案 0 :(得分:18)

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

  

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

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

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

答案 1 :(得分:15)

我完全使用GLOB,每次添加运行的文件

touch ../src/CMakeLists.txt

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

“CMake无法生成一个知道何时添加新源文件的构建系统”真的吗?好的,所以告诉它

这不是100%自动,但比手动添加文件更容易。

答案 2 :(得分:1)

我使用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及其他用法,请阅读the article from the author

答案 3 :(得分:0)

我使用传统的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
)        
...