在 MinGW 和 MinGW-64 上执行命令后变量为空?

Variable is empty after executing command on MinGW and MinGW-64?

本文关键字:变量 命令 执行 MinGW MinGW-64      更新时间:2023-10-16

我们正在为在MinGW和MinGW-64上失败的CMake构建而苦苦挣扎。我们的项目是一个C++库。我们的CMakeLists.txt有一个如下所示的块。该块通过编译器识别目标平台(其他方法太不可靠,尤其是在 ARM、MIPS 和 PPC 上(:

set(SHELL_CMD sh -c)
set(GREP_CMD egrep -i -c)
execute_process(COMMAND ${SHELL_CMD} "${CMAKE_CXX_COMPILER} -dumpmachine 2>&1"
COMMAND ${GREP_CMD} "amd64"
OUTPUT_VARIABLE CRYPTOPP_AMD64
OUTPUT_STRIP_TRAILING_WHITESPACE)
...
# http://github.com/weidai11/cryptopp/issues/466
execute_process(COMMAND ${SHELL_CMD} "${CMAKE_CXX_COMPILER} -dumpmachine 2>&1"
COMMAND ${GREP_CMD} "mingw32"
OUTPUT_VARIABLE CRYPTOPP_MINGW32
OUTPUT_STRIP_TRAILING_WHITESPACE)
# http://github.com/weidai11/cryptopp/issues/466
execute_process(COMMAND ${SHELL_CMD} "${CMAKE_CXX_COMPILER} -dumpmachine 2>&1"
COMMAND ${GREP_CMD} "w64-mingw32"
OUTPUT_VARIABLE CRYPTOPP_MINGW64
OUTPUT_STRIP_TRAILING_WHITESPACE)

它在11个平台中的9个平台上成功,但在MinGW和MinGW-64上失败。从我们跟踪该问题的错误报告中,MinGW-64 上的以下内容:

execute_process(COMMAND ${SHELL_CMD} "${CMAKE_CXX_COMPILER} -dumpmachine 2>&1"
COMMAND ${GREP_CMD} "w64-mingw32"
OUTPUT_VARIABLE CRYPTOPP_MINGW64
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS ${CRYPTOPP_MINGW64})
execute_process(COMMAND ${SHELL_CMD} "${CMAKE_CXX_COMPILER} -dumpmachine 2>&1"
COMMAND ${GREP_CMD} "mingw32"
OUTPUT_VARIABLE CRYPTOPP_MINGW32
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS ${CRYPTOPP_MINGW32})

这些语句生成一条空消息。删除OUTPUT_STRIP_TRAILING_WHITESPACE不会影响问题。从MinGW终端运行c++ -dumpmachine | egrep -i -c w64-mingw32会产生预期的结果。

我们发现CMAKE_COMPILER_IS_GNUCXX和CMAKE_CXX_COMPILER_ID是空的,但它似乎不适用,因为编译器在我们的例子中设置。(这是我们找到的唯一另一个"cmake 空变量 mingw"(。

不幸的是,我不知道正在使用哪个版本的Cmake。我们的错误报告包括 CMake 输出,但 CMake 无法打印其版本号。

为什么CMake无法在MinGW和MinGW-64上设置变量CRYPTOPP_MINGW64CRYPTOPP_MINGW32


下面是配置时 CMake 的典型输出。

=== Building cryptopp ===
mkdir -p deps/cryptopp/build/
cd deps/cryptopp/build/ && cmake -G 'MSYS Makefiles' -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTING=OFF -D BUILD_SHARED=OFF -DCMAKE_CXX_FLAGS="-march=native" ../ && make
-- The C compiler identification is GNU 6.2.0
-- The CXX compiler identification is GNU 6.2.0
-- Check for working C compiler: C:/msys32/mingw32/bin/gcc.exe
-- Check for working C compiler: C:/msys32/mingw32/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/msys32/mingw32/bin/g++.exe
-- Check for working CXX compiler: C:/msys32/mingw32/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE  
-- Compiler: 
-- Flags: -march=native
-- Build type: Release
-- 
-- The following OPTIONAL packages have been found:
* Threads
-- Configuring done
CMake Warning (dev) at CMakeLists.txt:503 (add_dependencies):
Policy CMP0046 is not set: Error on non-existent dependency in
add_dependencies.  Run "cmake --help-policy CMP0046" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
The dependency target "clean" of target "distclean" does not exist.
This warning is for project developers.  Use -Wno-dev to suppress it.
-- Generating done
-- Build files have been written to: C:/msys32/home/buildbot/slave/kovri-all-win32/build/deps/cryptopp/build

您需要将参数与命令分开。

set(SHELL_CMD sh)
set(SHELL_CMD_ARGS "-c")
set(GREP_CMD egrep)
set(GREP_CMD_ARGS "-i -c")
execute_process(COMMAND ${SHELL_CMD} "${SHELL_CMD_ARGS} ${CMAKE_CXX_COMPILER} -dumpmachine 2>&1"

问题原来是使用SHELL_CMDsh -c和位置参数。首先,SHELL_CMD只需要sh。其次,-c参数需要单独遵循命令。第三,我们需要引用整个字符串。相关,请参阅为什么回显不调用/bin/sh -c echo foo 输出任何内容?在Unix和Linux Stack Exchange上。

我们不知道这样的sh从何而来。我们猜测它是在很久以前拼凑在一起的,直到它引起问题为止。它可能应该在所有平台上都失败。我们仍然不知道2>&1是否正确。它不幸的 CMake 文档execute_process没有得到很好的解释,也没有提供任何示例。

我们将目标计算机检测代码更改为以下内容。代码现在引用参数进行sh以避免参数传递问题。

function(DumpMachine output pattern)
execute_process(
COMMAND sh -c "${CMAKE_CXX_COMPILER} -dumpmachine 2>&1"
COMMAND egrep -i -c "${pattern}"
OUTPUT_VARIABLE ${output}
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(${output} "${${output}}" PARENT_SCOPE)
endfunction(DumpMachine)
DumpMachine(CRYPTOPP_AMD64 "amd64|x86_64")
DumpMachine(CRYPTOPP_I386 "i.86")
DumpMachine(CRYPTOPP_MINGW32 "\<mingw32\>")
DumpMachine(CRYPTOPP_MINGW64 "w64-mingw32|mingw64")
DumpMachine(CRYPTOPP_X32 "x32")
DumpMachine(CRYPTOPP_AARCH32 "Aarch32")
DumpMachine(CRYPTOPP_AARCH64 "Aarch64")
DumpMachine(CRYPTOPP_ARM "\<arm\>|armhf|arm7l")