CMake与STREQUAL的空字符串比较失败

标签 cmake

我一直认为,如果你想比较两个字符串(但不是变量),你需要做的就是像这样引用它:

if("${A}" STREQUAL "some string")

但现在我发现这段代码有时会打印 oops :
cmake_minimum_required(VERSION 2.8)

if("d" STREQUAL "")
  message("oops...")
endif()

可能是错误(因为它用 Xcode 打印,而不是用 make 打印)?
还是有一些特殊的变量?
  • cmake: 2.8.12, 2.8.11.2
  • xcode: 4.6.2, 5.0.1

  • 更新

    有命令 string没有描述的问题:
    string(COMPARE EQUAL "${A}" "" result)
    if(result)
      message("...")
    endif()
    

    更新 2

    我期望自 CMake 3.1.0 以来实现的行为(见 CMP0054)。

    3.0.2 test 的输出:
    CMake version: 3.0.2
    Quoted test
    Surprise!
    Unquoted test
    Surprise!
    

    3.1.0 的输出 test :
    CMake version: 3.1.0
    Quoted test
    OK
    Unquoted test
    Surprise!
    

    最佳答案

    您遇到了 CMake 的一个相当烦人的“这不是错误,而是一个功能”行为。如 if command 的文档中所述:

     The if command was written very early in CMake's history, predating the ${} 
     variable evaluation syntax, and for convenience evaluates variables named
     by its arguments as shown in the above signatures.
    

    好吧,结果证明方便是不方便的。在您的示例中,字符串 "d"被视为名为 d 的变量由 if命令。如果变量d恰好定义为空字符串,消息语句将打印“oops...”,例如:
    set (d "")
    if("d" STREQUAL "")
      # this branch will be taken
      message("oops...")
    else()
      message("fine")
    endif()
    

    对于像这样的语句,这可能会产生令人惊讶的结果
    if("${A}" STREQUAL "some string")
    

    因为如果变量 A,第一个参数可能会出现意外的双重扩展。恰好定义为一个字符串,该字符串也是 CMake 变量的名称,例如:
    set (A "d")
    set (d "some string")   
    if("${A}" STREQUAL "some string")
      # this branch will be taken
      message("oops...")
    else()
      message("fine")
    endif()
    

    可能的解决方法:

    您可以在 ${} 之后的字符串中添加一个后缀字符。阻止 if 语句进行自动评估的扩展:
    set (A "d")
    set (d "some string")
    if("${A} " STREQUAL "some string ")
      message("oops...")
    else()
      # this branch will be taken
      message("fine")
    endif()
    

    请勿使用 ${}扩张:
    set (A "d")
    set (d "some string")
    if(A STREQUAL "some string")
      message("oops...")
    else()
      # this branch will be taken
      message("fine")
    endif()
    

    防止对 STREQUAL 右侧的意外评估使用 MATCHESCMake regular expression反而:
    if(A MATCHES "^value$")
      ...
    endif()
    

    附录:CMake 3.1 不再对引用的参数进行双重扩展。见 new policy .

    关于CMake与STREQUAL的空字符串比较失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19982340/

    相关文章:

    list - 如何在cmake中传递一个包含一个空元素的列表?

    c - 如何修改CMakeList.txt : library found, 但是有链接错误

    CMAKE无法将.f90识别为源代码?

    c++ - 如何在我的 Qt 项目中添加 BLAS_LIB?

    c++ - 在 CMake 中检查 C 程序输出

    cmake - CMake 中 if(<string>) 中 <string> 的计算值是多少?

    c++ - RPath 不适用于从 CMake 生成的 Make Install

    c++ - 使用 Eigen 运行 CTest 时出错

    c++ - Clion(cmake)不会链接库

    c++ - OS X/Clang 不会使用 c++11 头文件