我觉得整个cmake社区都在拖着我。没有任何“教程”或资源对我有意义。就像我错过了一些东西。我觉得最让我感到困惑的是语言,我所看到的任何一个教程都没有给那些没有unix和体验经验的人解释cmake。“/ p>
无论如何,我正在使用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}
。
答案 0 :(得分: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”的文件选项卡,其中包含变量${GENERATED}
中的文件。
SET(SOURCES ${GENERAL} ${GENERATED})
此行将变量SOURCES设置为变量${GENERAL}
和${GENERATED}
中的任何变量。之前我们将${GENERAL}
设置为当前源目录中的cpp,h和cmake文件列表。在类似C的伪代码中,这就像“SOURCES = GENERAL + GENERATED”。作为实现的细节,值SOURCES实际上是一个列表,其内容由“;”分隔。字符。通常这样做是为了以后您可以通过使用变量${SOURCES}
创建库或可执行文件,而不是在任何地方重复其他2个变量。
答案 1 :(得分:6)
有时候,我可以理解你对cmake教程的看法。我建议查看在线文档和一些cmake项目:例如食人魔,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所在的目录)并收集ALL * .cpp,* .h和* .cmake文件。结果是文件路径的设置/列表,相对于当前源目录的resepct,存储在变量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命令,它们获得“generated”属性,这是CMake执行正确的依赖性检查所需的。
SET( SOURCES
${GENERAL}
${GENERATED}
)
所以现在我们有一组来自文件(GLOB ...)调用的源文件,存储在变量GENERAL中。我们有一组存储在变量GENERATED中的soruce文件,这些文件是在其他地方创建的。这两个集合组合成一个源文件列表并存储在变量SOURCES中。
在正常情况下我会期待一个add_library调用: add_library($ {PLUGIN_NAME} {SOURCES})
这指定Cmake要从SOURCES中的源文件创建和构建新库。