我问这个是下次我使用CMake的时候提醒自己的.它永远不会坚持,谷歌的结果也不是很好.
在CMake中设置和使用变量的语法是什么?
我正在尝试编写一个宏,它通过给定的库列表.但是,宏中的消息调用仅打印列表的第一项.我在这做错了什么?
码:
macro( FindLibs LIBRARY_NAMES_LIST )
message( "inside ${LIBRARY_NAMES_LIST}" )
endmacro()
set( LIBRARY_NAMES_LIST lib1 lib2 lib3)
message( "outside ${LIBRARY_NAMES_LIST}" )
FindLibs(${LIBRARY_NAMES_LIST})
Run Code Online (Sandbox Code Playgroud)
输出:
message( "outside lib1 lib2 lib3" )
message( "inside lib1" )
Run Code Online (Sandbox Code Playgroud) 我一直认为,如果你想比较两个字符串(但不是变量),你需要做的就是引用它:
if("${A}" STREQUAL "some string")
Run Code Online (Sandbox Code Playgroud)
但现在我发现这段代码有时打印出来oops:
cmake_minimum_required(VERSION 2.8)
if("d" STREQUAL "")
message("oops...")
endif()
Run Code Online (Sandbox Code Playgroud)
可能是它的错误(因为它用Xcode打印,但不是用make打印)?还是有一些特殊的变量?
更新
有没有描述问题的命令字符串:
string(COMPARE EQUAL "${A}" "" result)
if(result)
message("...")
endif()
Run Code Online (Sandbox Code Playgroud)
更新2
我期望从CMake 3.1.0开始实现的行为(参见CMP0054).
3.0.2 测试的输出:
CMake version: 3.0.2
Quoted test
Surprise!
Unquoted test
Surprise!
Run Code Online (Sandbox Code Playgroud)
3.1.0 测试的输出:
CMake version: 3.1.0
Quoted test
OK
Unquoted test
Surprise!
Run Code Online (Sandbox Code Playgroud) 我想循环遍历字符串中给出的项目列表.根据CMake的要求,项目以分号分隔.下列
cmake_minimum_required(VERSION 2.8)
FOREACH(LETTER "a;b;c")
MESSAGE("<<${LETTER}>>")
ENDFOREACH()
Run Code Online (Sandbox Code Playgroud)
将字符串解释"a;b;c"为字符串文字.相反,当首先分配"a;b;c"变量时,所有变量都按预期进行.
cmake_minimum_required(VERSION 2.8)
SET(MYLIST "a;b;c")
FOREACH(LETTER ${MYLIST})
MESSAGE("<<${LETTER}>>")
ENDFOREACH()
Run Code Online (Sandbox Code Playgroud)
这是循环列表的推荐方法还是有更优雅的解决方案?
在cmake中,有什么区别:
set(any_new_var ${old_var})
Run Code Online (Sandbox Code Playgroud)
和
set(any_new_var "${old_var}")
Run Code Online (Sandbox Code Playgroud)
有什么重要区别?我何时使用其中一种形式?
例如,我尝试下一个迷你测试
# test.cmake
# Variable 'a' isn't defined.
set(hola "${a}")
# message(${hola})
message("${hola}")
Run Code Online (Sandbox Code Playgroud)
这个迷你测试(cmake -P test.cmake)的输出是一个空行(因为'a'没有定义).如果我取消注释第一条消息,cmake会抛出一条消息错误:
CMake Error at prueba.cmake:6 (message):
message called with incorrect number of arguments
Run Code Online (Sandbox Code Playgroud)
为什么在第二种情况下它不会抛出错误但是空行?
我正在尝试创建一个与某些环境变量一起运行的自定义命令,例如LDFLAGS,如果它包含空格,则需要引用它的值:
LDFLAGS="-Lmydir -Lmyotherdir"
Run Code Online (Sandbox Code Playgroud)
由于CMake的转义规则,我无法找到将此参数包含在CMake自定义命令中的方法.这是我到目前为止所尝试的:
COMMAND LDFLAGS="-Ldir -Ldir2" echo blah VERBATIM)
Run Code Online (Sandbox Code Playgroud)
产量 "LDFLAGS=\"-Ldir -Ldir2\"" echo blah
COMMAND LDFLAGS=\"-Ldir -Ldir2\" echo blah VERBATIM)
Run Code Online (Sandbox Code Playgroud)
产量 LDFLAGS=\"-Ldir -Ldir2\" echo blah
似乎我要么引用整个字符串,要么在作为命令的一部分使用时,转义的引号不会解析.
我希望既可以包含文字双引号,也可以作为为命令设置环境变量的更好方法.请注意,我仍然使用CMake 2.8,因此我没有在3.2中使用新的"env"命令.
CMake从以下行发出错误
if(NOT ($ENV{TnCfg} STREQUAL Linux_Build_Speech))
Run Code Online (Sandbox Code Playgroud)
错误是
CMakeLists.txt的CMake错误:37(如果):
如果给出论点:
Run Code Online (Sandbox Code Playgroud)"NOT" "(" "STREQUAL" "Linux_Build_Speech" ")"指定了未知参数
有什么问题?该行是有效代码.
我对一个非常简单的例子感到困惑.我有一个标准列表,所以基本上它的字符串表示使用分号作为分隔符.我想用另一个替换它:
set(L1 "A" "B" "C")
message("L1: ${L1}")
string(REPLACE ";" "<->" L2 ${L1})
message("L2: ${L2}")
Run Code Online (Sandbox Code Playgroud)
这个片段打印:
L1: A;B;C
L2: ABC
Run Code Online (Sandbox Code Playgroud)
而且我不明白为什么.根据其他一些SO答案,我的字符串替换似乎有效.我究竟做错了什么 ?有没有办法将值存储A<->B<->C在我的第二个变量中?
注意:我使用CMake 3.7.2
在我的 CMake 项目中,我有 2 个共享相同源代码文件的目标(静态库和共享库),如下所示:
add_library("${PROJECT_NAME}" STATIC
"${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.h"
"${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.cpp"
"${PROJECT_SOURCE_DIR}/include/calculator/core/Calculator.h"
"${PROJECT_SOURCE_DIR}/src/calculator/core/Calculator.cpp"
)
add_library("${PROJECT_NAME}-shared" SHARED
"${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.h"
"${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.cpp"
"${PROJECT_SOURCE_DIR}/include/calculator/core/Calculator.h"
"${PROJECT_SOURCE_DIR}/src/calculator/core/Calculator.cpp"
)
Run Code Online (Sandbox Code Playgroud)
显然,这里存在一个问题:源定义是重复的。它很难维护并且也容易出错。
为了避免这种情况,我想创建一个 CMake 列表变量,以便源定义可以在两个目标中重用。
我已经尝试过这个但它不起作用:
set(CALCULATOR_CORE_SOURCES_LIST
"${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.h"
"${PROJECT_SOURCE_DIR}/src/calculator/core/ShuntingYard.cpp"
"${PROJECT_SOURCE_DIR}/include/calculator/core/Calculator.h"
"${PROJECT_SOURCE_DIR}/src/calculator/core/Calculator.cpp"
)
string(REPLACE ";" " " CALCULATOR_CORE_SOURCES "${CALCULATOR_CORE_SOURCES_LIST}")
add_library("${PROJECT_NAME}" STATIC ${CALCULATOR_CORE_SOURCES})
add_library("${PROJECT_NAME}-shared" SHARED ${CALCULATOR_CORE_SOURCES})
Run Code Online (Sandbox Code Playgroud)
它失败并出现错误:Cannot find source file.
那么...如何在目标之间重用源文件定义而不进行这种重复?是否可以使用列表来做到这一点,或者是否有更好的方法来解决这个问题?
PS:我使用的是CMake 3.15
我想有选择地在我的CMakeLists文件中添加一些库路径,并且要做到这一点的方法是将变量设置为:
set(MYLIBDIR "DEFAULT")
Run Code Online (Sandbox Code Playgroud)
如果用户要指定自定义目录,则将其更改为:
set(MYLIBDIR /path/to/dir1
/path/to/dir2)
Run Code Online (Sandbox Code Playgroud)
因此,为了检查用户是否确实提供了额外的目录,我检查了:
if(NOT ${MYLIBDIR} STREQUAL "DEFAULT")
link_directories(${MYLIBDIR})
endif()
Run Code Online (Sandbox Code Playgroud)
当我尝试这样做时,我从cmake中得到一个错误。有没有办法在字符串比较之前连接变量的所有元素?
假设我们有一个 CMake 函数func,它接受命名参数,比如NAMED1和NAMED2。第一个参数是强制性的,第二个是可选的。例如
func(NAMED1 foo NAMED2 optional)
Run Code Online (Sandbox Code Playgroud)
现在我有一个循环需要func在每次迭代时调用这个函数,但根据当前的迭代,我有时需要提供可选值,有时不需要。所以在每次迭代时,我都会构建一个参数列表,比如
list(APPEND args "NAMED1" "foo")
if (...something...)
list(APPEND args "NAMED2" "optional")
endif()
Run Code Online (Sandbox Code Playgroud)
所以我args现在有了清单。作为一个字符串,它可能看起来像
NAMED1;foo
Run Code Online (Sandbox Code Playgroud)
或者它可能看起来像
NAMED1;foo;NAMED2;optional
Run Code Online (Sandbox Code Playgroud)
所以我想用字符串替换整个列表
string(REPLACE ";" " " args "${args}")
Run Code Online (Sandbox Code Playgroud)
然后结果args看起来像
NAMED1 foo NAMED2 optional
Run Code Online (Sandbox Code Playgroud)
所以我想把这个字符串传递给函数func,用
func("${args}")
Run Code Online (Sandbox Code Playgroud)
但现在的问题是 CMake 认为这是一个大字符串,而它应该将其解释为单独的字符串。我怎样才能做到这一点?
我正在创建一个导入目标,该目标希望公开两个接口包含目录:
list(APPEND LIB_INCLUDE_DIRS "dir1")
list(APPEND LIB_INCLUDE_DIRS "dir2")
add_library(lib SHARED IMPORTED GLOBAL)
set_target_properties(
lib
PROPERTIES
IMPORTED_LOCATION "something"
INTERFACE_INCLUDE_DIRECTORIES ${LIB_INCLUDE_DIRS}
)
Run Code Online (Sandbox Code Playgroud)
不幸的是,这是一个错误:set_target_properties的参数数目错误。
如果我尝试仅设置第一个目录,它将起作用。有办法设置两者吗?还是INTERFACE_INCLUDE_DIRECTORIES的复数形式具有讽刺意味?