2017-08-25 124 views
0

我们正在苦于在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_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

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

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" 
+0

Thanks @vre。让我试试吧。不幸的是,我没有用于测试的MinGW机器,所以我必须要求其他人来执行测试。但我可以在其他平台上测试更改。 – jww

+0

另一个问题(如果你不介意):是否应该分别引用参数?即,'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

+0

看起来文档问题已存在多年。下面是一个从2011年开始的问题的例子:[cmake execute_process()总是失败,当我打电话给git时,没有这样的文件或目录](https://stackoverflow.com/q/6797395/608639)。当一个项目不能修复它的文档时,它让我感到困惑。年复一年让用户一次又一次地犯同样的错误有什么意义? – jww

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是否正确。其不幸的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")