2017-08-25 85 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")