我在调查 CMake 文件时发现了一个奇怪的行
cmake_minimum_required(VERSION 3.11)
project(Project1)
set(SRC_FILES ${SRC_FILES} ./file1.cpp)
set(SRC_FILES ${SRC_FILES} ./file2.cpp) # sets the same variable
add_library(lib_name ${SRC_FILES})
为什么我们要设置变量
SRC_FILES
两次?是bug吗?
我正在检查变量的值
message(SOURCES="${SRC_FILES}")
它打印
SOURCES="./file1.cpp./file2.cpp
它是有效的 CMake 文件吗?
第二个“集合”分配
SRC_FILES
${SRC_FILES} ./file2.cpp
的组合值。所以它有效地appends变量。因此,最终结果是 SRC_FILES
同时包含 file1 和 file2.
这是一个完全有效的 CMake 文件。当然,在这个具体示例中,像这样将两者分配在一起会更简单:
set(SRC_FILES
${SRC_FILES} # This can be dropped if SRC_FILES doesn't contain previous value
./file1.cpp
./file2.cpp
)
注意:在现代 CMake 中,像这样使用
list(APPEND <list> new_value)
是一种更优雅的方式:
list(APPEND SRC_FILES ./file2.cpp)
是的,在cmake中重新赋值一个变量是完美的。请注意,尽管您可以(并且恕我直言)使用任一个
list(APPEND SRC_FILES ./file1.cpp ./file2.cpp)
或
set(SRC_FILES ./file1.cpp ./file2.cpp)
取而代之的是更容易阅读/更短的逻辑。
如果您希望
SRC_FILES
变量在您的逻辑之前为空,请使用后者。在 99% 的情况下,您不会从父 cmake 目录传递预先存在的变量,因此通常采用第二种方法。否则,您最终可能会在 lib 的源文件中找到来自其他目标的源代码。
记住当你开始编码时看到这样一行:
x = x + 1
你发现的是 CMake 对这种模式的看法。
set
命令将创建一个列表,如果使用两个以上的参数调用。
所以第一个
set
创建一个包含nothing的字符串变量
SRC_FILES
(默认情况下CMake将未设置的变量评估为nothing)和"./file1.cpp"
,第二个set
从SRC_FILES
内容创建一个字符串列表和"./file2.cpp"
.
其他答案已经指出了将
SRC_FILES
设置为相同值的其他方法。他们没有说清楚的是SRC_FILES
完全是多余的。它甚至被认为是现代 CMake 中的反模式。请参阅项目Avoid custom variables in the arguments of project commands.
旁注:路径是相对于当前 CMake 文件的,因此也不需要
./
。
所以干净、可读和惯用的代码将是
add_library(library_name file1.cpp file2.cpp)
它说“从 file1.cpp 和 file2.cpp 创建一个库 library_name”,这就是所有需要说的。