【问题标题】:How to generate CMakeLists.txt?如何生成 CMakeLists.txt?
【发布时间】:2011-10-18 09:01:20
【问题描述】:

我需要一些关于如何为 CMake 自动生成 CMakeLists.txt 文件的指针/建议。有谁知道任何现有的发电机?我检查了CMake Wiki 中列出的那些,但不幸的是它们不适合我。

我已经有一个基本的 Python 脚本,它遍历我的项目的目录结构并生成所需的文件,但它现在真的很“愚蠢”。我想对其进行扩充以考虑到例如我正在构建的不同平台、我正在使用的编译器\交叉编译器或我可能拥有的不同版本的库依赖项。我在 CMake 方面没有太多\专家经验,我可以为我的工作提供一个示例,或者一个已经工作的生成器可能会有很大帮助。

【问题讨论】:

  • 应该真的很蠢。您真的不希望执行目录遍历的代码了解平台或任何复杂的东西。在项目级配置中隔离该代码。
  • @Tom K 我没有进行平台特定的目录遍历,只是在我的项目结构中,无论平台如何,它都是相同的。我不明白为什么这会造成问题。我需要根据我正在构建的实际平台选择\取消选择一些选项,包括目录等。
  • @Nicol Bolas CMake 有自己的脚本语言。您可以在 CMake 文件中包含条件等,因此它在某种程度上是可编写脚本的。不幸的是,我无法切换到 Premake。
  • 实际上,在重构了一些构建系统之后.. 我发现最好让 CMakeLists.txt 包含所有源文件的完整、哑列表,并使源文件本身包含必要的编译守卫。因此,您的所有 Linux、Windows、ARM 等特定文件始终编译/包含在项目中,但源文件本身具有预处理器条件,将它们排除在构建之外。因此,您几乎总是可以在任何给定目录中使用“gcc -I. *.cpp”。如果那不是一个选项,您必须在 cmakelists.txt 中手动执行 if
  • 还有另一个很有帮助的提示:如果您在 earch 目录中通过愚蠢的 python 脚本生成完整的文件列表,请说“files.cmake”并让 CMakeLists.txt 随处可见,只需在顶部,您可以在 cmake 脚本中对生成的列表进行后期编辑。因此,如果您的 files.cmake 创建了一个 CMake 变量 SOURCES,只需执行 if(win32) list(remove SOURCES posix-specific-code.cpp) endif()

标签: c++ c cmake


【解决方案1】:

我认为您不需要使用自动脚本来生成 CMakeLists.Txt,因为在您了解基本过程之后,编写一个非常简单的任务。是的,我同意理解 CMake Wiki 中给出的编写过程也很困难,因为它太详细了。

显示如何编写 CMakeLists.txt 的一个非常基本的示例显示为 here,我认为这对每个人都有用,即使是第一次编写 CMakeLists.txt 的人时间。

【讨论】:

  • 网站已关闭。有cached link version
  • 无论您对程序的理解程度如何,自动生成一个总是更快更方便。这个问题值得得到一个有用的答案。
  • 该网址现在重定向...Thanks, Wayback...
  • 我正在一个项目中使用 CLion 中的数千个源文件。我不想添加其他人创建的所有新文件并在每次 git pull 后手动删除所有已删除的文件...
  • 这不仅是一个无答案,而且即使有,它也是一个仅链接帖子,现在指向一个汽车网站。这显示了这类帖子的所有问题。
【解决方案2】:

好吧,我也没有太多 Cmake 经验,但是要执行跨平台,需要编写和修改很多文件,包括 CMakeLists.txt 文件,我建议您使用这个名为 ProjectGenerator 的新工具工具,它非常酷,它可以完成所有需要的额外工作,并且可以轻松地为 3'rd 方源生成此类文件,而无需付出任何努力。 使用前请仔细阅读自述文件。

链接: http://www.ogre3d.org/forums/viewtopic.php?f=1&t=54842

【讨论】:

  • 这实际上是唯一回答这个问题的帖子。我认为它不应该仅仅因为人们个人偏好是手动做事而被否决,因为 linux。
  • @David:同意,但这不是唯一回答问题的帖子,我添加了一个!
  • 请注意,这个“ProjectGenerator 工具”显然已停产。论坛中提供的链接已损坏。
【解决方案3】:

我认为你这样做是颠倒的。

使用 CMake 时,您应该自己编写 CMakeLists.txt。通常,您不需要处理不同的编译器,因为 CMake 了解它们。但是,如果必须,您可以在 CMakeFiles 中添加代码以根据您使用的工具执行不同的操作。

【讨论】:

  • 我同意。 CMake 是我用过的最好的此类构建工具,但你必须遵守它的规则,并遵守源代码的物理设计。你可能最好看看 CMake 在其他 Python 项目中是如何使用的。
  • 通常在使用交叉编译器时,它并不像应该的那么容易。而且我自己编写了大部分 CMakeLists.txt 文件,我只需要一点帮助来以或多或少的自动化方式“维护”我需要在构建中包含的文件列表 - 我有数百个源文件和手动确保一切正常且花花公子非常容易出错且耗时。无论如何,我制作的脚本已经变得不那么愚蠢了,在@kert 的 cmets 的帮助下,我实际上有了一些几乎可以满足我要求的东西。
  • 如果没有很多愚蠢的 CMake 脚本,如 Makefiles,需要重写为 CMake20 的大量 IF 和全局变量(正确完成 (TM)),那将是真的。
【解决方案4】:

CLion是一个完全基于CMake项目文件的集成开发环境。

使用import project from source

时可以自己生成CMakeLists.txt文件

但是,随着项目的增长和添加外部依赖项,您很可能必须手动编辑此文件。

【讨论】:

    【解决方案5】:

    我正在维护一个 C++ 软件环境,该环境具有 1000 多个模块(共享、静态库、程序)并使用 20 多个第三方(boost、openCV、Qt、Qwt...)。该软件环境托管了许多程序(约 50 个),每个程序都包含一些库、程序和第三方。我使用 CMake 来生成 makefile,这真的很棒。

    但是,如果您按照推荐的方式编写 CMakeLists.txt(将模块声明为库/程序、导入源文件、添加依赖项...)。我同意 celavek:维护那些 CMakeLists.txt 文件真的很痛苦:

    • 向模块添加新文件时,需要更新其CMakeLists.txt
    • 升级第三方时,需要更新所有使用它的模块的CMakeLists.txt
    • 当您添加新的依赖项(库A 现在需要库B)时,您可能需要更新所有使用A 的程序的CMakeLists.txt
    • 当您想要更改新的全局设置(编译器设置、预定义变量、使用的 C++ 标准)时,您需要更新所有 CMakeLists.txt

    然后,我看到了解决这些问题的两种策略,很可能是 OP 提到的一种。

    1- 让CMakeLists.txt 写得很好,并且足够聪明,不会有僵硬的行为来即时更新自己。这就是我们在我们的软件环境中所拥有的。每个模块都有一个标准化的文件组织(源在src 文件夹中,包含在inc 文件夹中......)并有简单的文本文件来指定它们的依赖关系(使用我们定义的关键字,如@9​​87654335@ 来表示模块需要链接Qt)。然后,我们的CMakeLists.txt 是一个两行文件,只需调用我们编写的 cmake 宏来自动设置模块。作为一个 MCVE,应该是:

    CMakeLists.txt:

    include( utl.cmake )
    add_module( "mylib", lib )
    

    utl.cmake:

    macro( add_module name what )
        file(GLOB_RECURSE source_files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
        include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
        if ( what STREQUEL "lib" )
            add_library( ${name} SHARED ${source_files} )
        elseif ( what STREQUEL "prg" )
            add_executable( ${name} ${source_files} )
        endif()
        # TODO: Parse the simple texts files to add target_link_libraries accordingly
    endmacro()
    

    然后,对于上面暴露的所有情况,您只需要更新 utl.cmake,而不是您拥有的数千个 CMakeLists.txt...

    老实说,我们对这种方法非常满意,系统变得非常易于维护,我们可以轻松添加新的依赖项、升级第三方、更改一些构建/依赖项策略...

    但是,还有很多 CMake 脚本需要编写。并且CMake 脚本语言很烂...该工具非常强大,对,但是脚本的变量范围、缓存、痛苦且记录不充分的语法(只是为了检查列表是否为空,您必须询问它的大小和将它存储在一个变量中!),事实上它不是面向对象的……维护起来真的很痛苦。

    所以,我现在确信真正好的方法可能是:

    2- 从 Python 等更强大的语言完全生成 CMakeLists.txt。 Python 脚本会做类似于我们的 utl.cmake 所做的事情,相反它会生成一个 CMakeLists.txt 准备被传递给 CMake 工具(使用 HelloWorld 中建议的格式,没有变量,没有函数......它只会调用标准 CMake 函数)。

    我怀疑这样的通用工具是否存在,因为很难生成让每个人都开心的CMakeLists.txt 文件,你必须自己编写。请注意,gen-cmake 会这样做(生成一个 CMakeLists.txt),但是以一种非常原始的方式,它显然只支持 Linux,但它可能是一个很好的起点。

    这很可能是我们软件环境的 v2……有一天。

    注意:此外,例如,如果您想同时支持 qmake 和 cmake,编写良好的 Python 脚本可以按需生成 CMakeLists 和 pro 文件!

    【讨论】:

    【解决方案6】:

    不确定这是否是原始发帖人面临的问题,但我在上面看到很多“只写 CMakefile.txt”的答案,让我简要解释一下为什么生成 CMakefile 可能有意义:

    a) 我有另一个我相当满意的构建系统

    (其中涵盖了大型集合的大型多平台构建 互连的共享和静态库、程序、脚本 具有各种内部和外部的语言扩展和工具 依赖项、怪癖和变体)

    b) 就算换了,我也不会考虑cmake。

    我查看了 CMakefiles,但我对语法不满意 并且对语义不满意。

    c) CLion 使用 CMakefiles,并且仅使用 Cmakefiles(并且看起来有些有趣)

    所以,为了给 CLion 一个机会(我喜欢 PyCharm,所以它很诱人),但是为了继续使用我的构建系统,我很乐意使用一些工具来让我 实施 使 generate_cmake 并根据当前动态生成所有必要的 CMakefile 从我的构建系统中提取的信息。我可以很高兴地向工具/脚本提供我的应用程序包含哪些源和标头、预期构建哪些库和程序、预期为哪个组件设置哪些-I、-L、-D等信息等等

    好吧,如果 JetBrains 允许提供一些直接协议来为 IDE 提供所需的信息,我当然会更高兴 (比如说,允许我提供自己的命令来编译、运行和 发出他们真正需要的任何元数据——我想他们主要需要 incdirs 和定义来实现动态代码分析,以及 libpaths 来为调试器设置 LD_LIBRARY_PATH),而不参考 cmake。 CMakefiles 作为协议有点复杂。

    【讨论】:

      【解决方案7】:

      也许这会有所帮助:

      https://conan.io/

      作者就cmake以及如何在CPPCon中使用cmake创建模块化项目做了一些演讲。据我所知,这个工具需要 cmake,所以我想当你集成新包或创建新包时会生成它。最近我读到一些关于如何使用 YAML 文件编写 C/C++ 项目的更高级别描述的内容,但不确定它是否是柯南的一部分(我读的是柯南的作者)。我从来没有使用过,它对我来说还有待解决,所以,如果你使用它并且满足你的需求,请评论你对它的看法以及它如何适合你的场景。

      【讨论】:

        【解决方案8】:

        我一直在寻找这样的生成器,但最后我决定自己编写(部分原因是我想了解 CMake 的工作原理):

        https://github.com/Aenteas/cmake-generator

        它有几个附加功能,例如创建 python 包装器 (SWIG)。

        编写适合所有人的生成器是不可能的,但我希望它能给你一个想法,以防你想制作你的定制版本。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-01
          • 2021-08-30
          • 1970-01-01
          • 2014-09-21
          • 1970-01-01
          • 2017-12-15
          相关资源
          最近更新 更多