簡體   English   中英

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

[英]How to collect source files with CMake without globbing?

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

  • 上面的行將所有“*_unittest.cpp”添加到列表中
  • 您可以更改中間線以制定自己的規則,只是普通的 python。 使用正則表達式更好,但簡單的字符串搜索可以在上述情況下完成工作。
  • 注意最后一行,它需要替換 // 以更改為可用的通用分隔符。 您可以在 Windows 中生成您的 CMakeList.txt。
  • 您可以將 SRC_FILES 替換為您想要的任何內容。
  • python 命令可以在 Jenkins/TeamCity 下運行,由 svn/git commit 觸發。 然后我們可以自動添加新文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM