在MinGW和MinGW-64上执行命令后变量为空?
我们正在苦于在MinGW和MinGW-64上发生故障的CMake。我们的项目是一个C++库。我们的CMakeLists.txt
有一个如下所示的块。块标识通过编译目标平台(其它方法是太不可靠,尤其是在ARM,MIPS和PPC):在MinGW和MinGW-64上执行命令后变量为空?
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。从我们跟踪bug report问题上的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 and CMAKE_CXX_COMPILER_ID are empty但它似乎不适用,因为我们的情况下编译器已设置。 (这是我们发现的唯一的另一个“cmake空变量mingw”)。
不幸的是,我不知道正在使用什么版本的Cmake。我们的bug report包含CMake输出,但CMake未能打印其版本号。
为什么CMake未能在MinGW和MinGW-64上设置变量CRYPTOPP_MINGW64
和CRYPTOPP_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_CMD
,sh -c
和位置参数。首先,SHELL_CMD
只需要sh
。其次,-c
论点需要单独遵循命令。第三,我们需要引用整个字符串。相关信息,请参阅Why doesn't echo called as /bin/sh -c echo foo output anything?,地址为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")
Thanks @vre。让我试试吧。不幸的是,我没有用于测试的MinGW机器,所以我必须要求其他人来执行测试。但我可以在其他平台上测试更改。 – jww
另一个问题(如果你不介意):是否应该分别引用参数?即,'execute_process(COMMAND“$ {SHELL_CMD}”“$ {SHELL_CMD_ARGS}”“$ {CMAKE_CXX_COMPILER}”“-dumpmachine”“2>&1”'?CMake文件为[execute_process](https://cmake.org /cmake/help/v3.0/command/execute_process.html)不能很好地解释,并且不提供示例(* qv *)。 – jww
看起来文档问题已存在多年。下面是一个从2011年开始的问题的例子:[cmake execute_process()总是失败,当我打电话给git时,没有这样的文件或目录](https://*.com/q/6797395/608639)。当一个项目不能修复它的文档时,它让我感到困惑。年复一年让用户一次又一次地犯同样的错误有什么意义? – jww