CMake:如何在参数中用双引号调用execute_process?aka使用来自CMake的查找来计数与字符串匹配的行

Ant*_*nio 6 windows cmake find findstr

我会想调用命令find从内execute_process

find命令的格式为:

find [/v] [/c] [/n] [/i] [/off[line]] "<String>" [[<Drive>:][<Path>]<FileName>[...]]
Run Code Online (Sandbox Code Playgroud)

因此,字符串必须用双引号引起来。但是,如果在cmake中,我会这样做:

execute_process(COMMAND <firstCommandPipingSomethingToFind> 
                COMMAND find "<myString>" /c
                OUTPUT_VARIABLE MY_COUNT
                OUTPUT_STRIP_TRAILING_WHITESPACE)
Run Code Online (Sandbox Code Playgroud)

我得到一个错误FIND: Parameter format not correct
如果我使用双引号转义\,则会出现错误Access denied - \
同样,使用双转义\\或双双引号""也无济于事。

所以我的问题是:
有没有办法在调用时转义双引号execute_processfind正确接收其参数?

我可以使用findstr,不需要双引号;但是它不提供计数功能。我可以find通过致电使用find /v /c "",但同样,我需要双引号!我想计算cmake以外的输出行,并将结果直接存储在MY_COUNT变量中。

注意:我正在使用CMake 3.4.1


要重现该问题,您可以使用以下代码,其中的代码cmake -E echo用于将字符串提供给findstrfind

#This works
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND findstr ell OUTPUT_VARIABLE DUMMY)
message (STATUS "0) DUMMY=${DUMMY}")

#All of the following don't work
set(MyCommand "find \"ell\" /c")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND "${MyCommand}" OUTPUT_VARIABLE DUMMY)
message (STATUS MyCommand=${MyCommand})
message (STATUS "1) DUMMY=${DUMMY}")

execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND ${MyCommand} OUTPUT_VARIABLE DUMMY)
message (STATUS "2) DUMMY=${DUMMY}")

execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND MyCommand OUTPUT_VARIABLE DUMMY)
message (STATUS "3) DUMMY=${DUMMY}")

execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND "find \"ell\" /c" OUTPUT_VARIABLE DUMMY)
message (STATUS "4) DUMMY=${DUMMY}")
Run Code Online (Sandbox Code Playgroud)

哪个输出:

0) DUMMY=hello

MyCommand=find "ell" /c
1) DUMMY=
2) DUMMY=
3) DUMMY=
4) DUMMY=
Run Code Online (Sandbox Code Playgroud)

我也试过

set(MyArgument "\"ell\" /c")
message (STATUS MyArgument=${MyArgument})
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find "${MyArgument}" OUTPUT_VARIABLE DUMMY)
message (STATUS "1) DUMMY=${DUMMY}")

execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find ${MyArgument} OUTPUT_VARIABLE DUMMY)
message (STATUS "2) DUMMY=${DUMMY}")

set(MyArgument "\"ell\"")
message (STATUS MyArgument=${MyArgument})
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find "${MyArgument}" /c OUTPUT_VARIABLE DUMMY)
message (STATUS "1) DUMMY=${DUMMY}")

execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find ${MyArgument} /c OUTPUT_VARIABLE DUMMY)
message (STATUS "2) DUMMY=${DUMMY}")
Run Code Online (Sandbox Code Playgroud)

哪个输出:

MyArgument="ell" /c
File not found - \ELL\

1) DUMMY=
File not found - \ELL\

2) DUMMY=
MyArgument="ell"
Access denied - \

1) DUMMY=
Access denied - \

2) DUMMY=
CMake Error at CMakeRules.cmake:404 (execute_process):
  execute_process given COMMAND argument with no value.
Call Stack (most recent call first):
  CMakeLists.txt:24 (include)
Run Code Online (Sandbox Code Playgroud)

如果删除该/c选件,问题仍然存在。


这个:

execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find \"ell\" OUTPUT_VARIABLE DUMMY)
message (STATUS "DUMMY=${DUMMY}")
Run Code Online (Sandbox Code Playgroud)

输出此:

Access denied - \

DUMMY=
Run Code Online (Sandbox Code Playgroud)

在Tsyvarev建议检索哪个字符串有效地传递给命令行之后,这是:

execute_process(COMMAND cmd /c echo \"ell\")
execute_process(COMMAND cmd /c echo "ell")
execute_process(COMMAND cmd /c echo ""ell"")
Run Code Online (Sandbox Code Playgroud)

输出此:

\"ell\"

ell

"" ell\"\"
Run Code Online (Sandbox Code Playgroud)

带有第三条命令的警告:

Argument not separated from preceding token by whitespace.
This warning is for project developers.  Use -Wno-dev to suppress it.
Run Code Online (Sandbox Code Playgroud)

Ant*_*nio 0

根据 CMake 开发人员的说法,由于 CreateProcess API 和解析参数的非标准方式的限制,
Windows不能直接由 cmake 从内部find调用。execute_processfind

不过,可以通过创建临时批处理脚本来间接调用它。

我在 Windows 中计算程序输出中字符串出现次数的问题是通过以下方式解决的:

file(WRITE ${CMAKE_BINARY_DIR}/countLines.bat [[@find /v /c "" %1]])
execute_process(COMMAND <firstCommandPipingSomethingToFind> COMMAND findstr <regular expression> COMMAND countLines.bat WORKING_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE N_MATCHES OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "N_MATCHES=${N_MATCHES}")
file(REMOVE ${CMAKE_BINARY_DIR}/countLines.bat)
Run Code Online (Sandbox Code Playgroud)

in Between的优点findstr是支持正则表达式。find仅用于计算匹配行数

@前面的内容find是为了防止脚本内的命令调用最终出现在输出变量中。