CMake与STREQUAL的空字符串比较失败 [英] CMake compare to empty string with STREQUAL failed

查看:3365
本文介绍了CMake与STREQUAL的空字符串比较失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  if($ {A}STREQUALsome string)

我发现这个代码有时打印 oops

  cmake_minimum_required 2.8)

if(dSTREQUAL)
message(oops ...)
endif()

可能是错误(因为它输出 Xcode ,但不包含 make )?
或有一些特殊的变量?




  • cmake:2.8.12,2.8.11.2

  • xcode:4.6.2,5.0.1



更新 b

有没有描述的命令字符串问题:

  string(COMPARE EQUAL$ {A}result)
if $ b message(...)
endif()

2



自从 CMake 3.1.0 (请参阅 CMP0054 )。



3.0.2 测试的输出:

  CMake版本:3.0.2 
引用测试
惊喜!
无参考测试
惊喜!

输出3.1.0 test

  CMake版本:3.1.0 
引用测试
OK
无参考测试
惊喜!


解决方案

你碰到一个恼人的 ,它是CMake的一个功能行为。如 if命令的文档中所述:



if命令在CMake的历史上写得很早,先于$ {}
变量评估语法,为方便起见,
的参数,如上面的签名所示。

好的,这种方便是不方便的。在你的示例中,字符串d视为一个名为 d if 命令。如果变量 d 碰巧被定义为空字符串,消息语句将打印oops ...,例如:

  set(d)
if(dSTREQUAL)
# oops ...)
else()
message(fine)
endif()

这可以为

  if($ {A}STREQUAL some string)

因为如果变量 A 恰好定义为一个字符串,也是一个CMake变量的名称,例如:

  set(Ad)
set(dsome string)
if($ {A}STREQUALsome string)
#将获取
消息(oops ...)
else()
消息(fine)
endif()



可能的解决方法:



您可以在字符串后添加后缀字符 $ {} 扩展,阻止if语句执行自动计算:

  set(dsome string)
if($ {A}STREQUALsome string)
message )
else()
#这个分支将被采取
message(fine)
endif()

不要使用 $ {} 扩展:

  set(Ad)
set(dsome string)
if(A STREQUALsome string)
message ...)
else()
#这个分支将被采取
消息(罚款)
endif()
STREQUAL 的右侧使用 MATCHES / code>替换为 CMake正则表达式

  if(A MATCHES^ value $)
...
endif()

附录:CMake 3.1不再对带引号的参数进行双重扩展。请参阅新政策


I always think that if you want to compare two strings (but not variables) all you need to do is to quote it like that:

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

but now I find out that this code sometimes print oops:

cmake_minimum_required(VERSION 2.8)

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

May be it's bug (because it prints with Xcode, but not with make)? Or there is some special variables?

  • cmake: 2.8.12, 2.8.11.2
  • xcode: 4.6.2, 5.0.1

Update

There is command string without described problems:

string(COMPARE EQUAL "${A}" "" result)
if(result)
  message("...")
endif()

Update 2

The behaviour I've expected implemented since CMake 3.1.0 (see CMP0054).

Output of the 3.0.2 test:

CMake version: 3.0.2
Quoted test
Surprise!
Unquoted test
Surprise!

Output of the 3.1.0 test:

CMake version: 3.1.0
Quoted test
OK
Unquoted test
Surprise!

解决方案

You ran into a rather annoying "it's not a bug, it's a feature" behavior of CMake. As explained in the documentation of the 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.

Well, the convenience turned out to be an inconvenience. In your example the the string "d" is treated as a variable named d by the if command. If the variable d happens to be defined to the empty string, the message statement will print "oops...", e.g.:

set (d "")
if("d" STREQUAL "")
  # this branch will be taken
  message("oops...")
else()
  message("fine")
endif()

This can give surprising results for statements like

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

because there can be an unintended double expansion of the first argument if the variable A happens to be defined to a string which is also the name of a CMake variable, e.g.:

set (A "d")
set (d "some string")   
if("${A}" STREQUAL "some string")
  # this branch will be taken
  message("oops...")
else()
  message("fine")
endif()

Possible work-arounds:

You can add a suffix character to the string after the ${} expansion which prevents the if statement from doing the automatic evaluation:

set (A "d")
set (d "some string")
if("${A} " STREQUAL "some string ")
  message("oops...")
else()
  # this branch will be taken
  message("fine")
endif()

Do not use ${} expansion:

set (A "d")
set (d "some string")
if(A STREQUAL "some string")
  message("oops...")
else()
  # this branch will be taken
  message("fine")
endif()

To prevent unintended evaluation on the right side of STREQUAL use MATCHES with a CMake regular expression instead:

if(A MATCHES "^value$")
  ...
endif()

Addendum: CMake 3.1 no longer does double expansions for quoted arguments. See the new policy.

这篇关于CMake与STREQUAL的空字符串比较失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆