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

时间:2017-08-25 11:30:35

标签: c++ cmake mingw32 mingw-w64

我们正在努力解决在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都失败了。从我们的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_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

2 个答案:

答案 0 :(得分:2)

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

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"

答案 1 :(得分:1)

问题原来是使用SHELL_CMDsh -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是否正确。其execute_process的不幸CMake文档没有得到很好的解释,也没有提供任何示例。

我们将目标机器检测代码更改为以下内容。代码现在引用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")