8

我觉得整个 cmake 社区都在欺骗我。“教程”或资源对我来说没有任何意义。就像我错过了什么。我认为最让我困惑的是语言,而且我所见过的教程都没有接近于向几乎没有 unix 和制作经验的人解释 cmake。

无论如何,我正在使用 FireBreath,它广泛使用 cmake,我认为是时候开始弄清楚如何使用它而不是直接更改项目文件了。

根 CMakeLists.txt 文件包含以下内容:

cmake_minimum_required (VERSION 2.6)
set (CMAKE_BACKWARDS_COMPATIBILITY 2.6)

Project(${PLUGIN_NAME})

file (GLOB GENERAL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
    [^.]*.cpp
    [^.]*.h
    [^.]*.cmake
    )

include_directories(${PLUGIN_INCLUDE_DIRS})

# Generated files are stored in ${GENERATED} by the project configuration
SET_SOURCE_FILES_PROPERTIES(
    ${GENERATED}
    PROPERTIES
        GENERATED 1
    )

SOURCE_GROUP(Generated FILES
    ${GENERATED}
    )

SET( SOURCES
    ${GENERAL}
    ${GENERATED}
    )

如果有人可以向我解释每一行,将不胜感激。尤其是什么${GENERAL}${GENERATED}是。

4

2 回答 2

19

首先,cmake 语法非常简单。它由“命令”和“参数”组成。它是如此简单,以至于它需要一段时间才能沉入其中。一切都是“命令(参数)”。此外,命令名称不区分大小写。以前它们必须全部大写,但从 2.6 版开始(我认为)这并不重要。然而,参数是区分大小写的。

cmake_minimum_required (VERSION 2.6)

此命令设置项目所需的最低 cmake 版本。如果当前的cmake版本低于2.6会停止处理并报错。这避免了必须支持该工具的古老版本。

set (CMAKE_BACKWARDS_COMPATIBILITY 2.6)

将变量 CMAKE_BACKWARDS_COMPATIBILITY 设置为值 2.6。这实际上是您提供的 CMakeLists.txt 文件中的一个小错误,因为 CMAKE_BACKWARDS_COMPATIBILITY 不应该用于 2.6 及更高版本。该脚本可能应该使用cmake_policy. 这是为了指定较新版本的 cmake 在遇到以前版本的 cmake 中的不一致时应如何表现。您今天从头开始编写的任何脚本都无需担心这一点。

Project(${PLUGIN_NAME})

将项目名称设置为变量中的任何值PLUGIN_NAME。此值在某些 IDE 中显示为项目名称。要将值写入变量,您可以使用set(PLUGIN_NAME myName)和读取您使用以下${}语法的值:"${PLUGIN_NAME}". 一些命令也会写入变量,但您使用它们的方式与在set命令中相同。

file (GLOB GENERAL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
     [^.]*.cpp
     [^.]*.h
     [^.]*.cmake
     )

file是一个命令。它的第一个参数GLOB意味着“返回磁盘上名称与我将作为参数给出的模式匹配的文件”。下一个参数GENERAL是存储结果的变量,就像set将结果写入变量一样,您稍后可以使用${GENERAL}.RELATIVE并且路径意味着返回相对于该路径的文件名,而不是完整路径。因此,而不是 "C:\some\long\path\src\foo.cpp" 或 "/home/me/some/path/src/foo.cpp" 你会得到 "src\foo.cpp" 或 "src/ foo.cpp”。变量 CMAKE_CURRENT_SOURCE_DIR 是 CMake 为您填写的“魔术变量”,它指的是当前正在处理的源目录的路径,该 CMakeLists.txt 文件所在的位置。最后一个参数列表是要匹配的文件的模式。基本上,任何具有文件扩展名 cpp、h 或 cmake 的东西。

include_directories(${PLUGIN_INCLUDE_DIRS})

将目录添加${PLUGIN_INCLUDE_DIRS}到编译器搜索的包含文件的目录中。例如,如果您使用 gcc 编译,这将导致额外的“-I”参数。

# Generated files are stored in ${GENERATED} by the project configuration

以# 开头的行是注释。

SET_SOURCE_FILES_PROPERTIES(
       ${GENERATED}
       PROPERTIES
           GENERATED 1
       )

文件可以有与之关联的键/值对,这会影响它们的构建方式。在这里,变量中列出的文件${GENERATED}将属性“GENERATED”设置为值 1。这是什么意思?好吧,CMake 现在知道不要在磁盘上查找文件“${GENERATED}”,因为它们将在另一个构建步骤中创建。在发布的片段中,没有人设置变量${GENERATED}。我想它会在项目文件的其他地方设置。不要将变量${GENERATED}与属性 GENERATED 混淆!这是一个微妙的点,也许变量应该是GENERATED_FILES为了避免混淆,即SET_SOURCE_FILES_PROPERTIES(${GENERATED_FILES} PROPERTIES GENERATED 1)

 SOURCE_GROUP(Generated FILES ${GENERATED})

这将创建一个组,该组在 Visual Studio 中转换为一个名为“已生成”的文件选项卡,其中包含变量 中的文件${GENERATED}

 SET(SOURCES ${GENERAL} ${GENERATED})

此行将变量 SOURCES 设置为变量${GENERAL}和中的任何内容${GENERATED}。之前我们设置${GENERAL}为当前源目录中的 cpp、h 和 cmake 文件的列表。在类似 C 的伪代码中,这就像“SOURCES = GENERAL + GENERATED”。作为实现的细节,值 SOURCES 实际上是一个列表,其内容用“;”分隔。人物。通常这样做是为了以后您可以通过仅使用变量${SOURCES}而不是在任何地方重复其他 2 个变量来创建库或可执行文件。

于 2011-05-30T09:03:08.173 回答
6

有时,我能理解您对 cmake 教程的感受。我建议查看在线文档和一些 cmake 项目:例如 Ogre、Vtk、Kde。

从 CMakeLists.txt 的外观看来,这应该由外部 CMake 项目(带有 add_subdirectory)调用,因为它引用变量 PLUGIN_NAME、PLUGIN_INCLUDE_DIRS 和 GENERATED。

要回答您的问题:

cmake_minimum_required (VERSION 2.6)
set (CMAKE_BACKWARDS_COMPATIBILITY 2.6)
Project(${PLUGIN_NAME})

这准备了您的 cmakefile,告诉 cmake 它必须是 2.6 或更高版本,并且您正在启动一个名称与 PLUGIN_NAME 变量中指定的项目相同的项目。

file (GLOB GENERAL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
    [^.]*.cpp
    [^.]*.h
    [^.]*.cmake
    )

这部分遍历当前源目录(cmakelists.txt 所在的目录)并收集所有 *.cpp、*.h 和 *.cmake 文件。结果是文件路径的集合/列表,与当前源目录相对应,并存储在变量 GENERAL 中。

# Generated files are stored in ${GENERATED} by the project configuration
SET_SOURCE_FILES_PROPERTIES(
    ${GENERATED}
    PROPERTIES
        GENERATED 1
    )

SOURCE_GROUP(Generated FILES
    ${GENERATED}
    )

显然,将有一组源文件存储在变量 GENERATED(因此不是 GENERAL)中。对于构建生成的源文件,这些文件不一定在 CMake 的第一次构建时就存在,CMake 需要知道这些文件是生成的。使用 set_source_files_properties 命令,他们可以获得“生成”属性,这是 CMake 进行正确依赖检查所必需的。

SET( SOURCES
    ${GENERAL}
    ${GENERATED}
    )

所以现在我们有一组来自文件(GLOB ...)调用的源文件,存储在变量 GENERAL 中。我们有一组存储在变量 GENERATED 中的源文件,该变量是在其他地方创建的。这两个集合组合成一个源文件列表并存储在变量 SOURCES 中。

在正常情况下,我希望 add_library 调用: add_library( ${PLUGIN_NAME} {SOURCES} )

这向 Cmake 指定要从 SOURCES 中的源文件创建和构建一个新库。

于 2011-05-30T09:29:54.627 回答