我们正在努力解决在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_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
答案 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_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
是否正确。其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")