2012-04-18 156 views
9

我想在我生成的腳本中記錄傳遞給cmake的參數。例如, 「my-config.in」 將被cmake的處理,它的定義是這樣的:如何捕獲CMake命令行參數?

配置= 「@ CMAKE_ARGS @」

cmake後,my-config將包含行像此:

配置= 「 - DLINUX -DUSE_FOO = Y -DCMAKE_INSTALL_PREFIX =/USR」

我試圖CMAKE_ARGS,CMAKE_OPTIONS,但失敗。沒有文件提到這一點。 :-(

回答

16

我不知道它提供該信息的任何變量,但你可以自己生成它(有一些附加條件)。

任何-D參數傳遞給CMake的被添加到緩存文件CMakeCache.txt在構建目錄,並在隨後的調用,而不必再在命令行上指定的在你的榜樣重新應用。

所以,如果你先執行的CMake作爲

cmake ../.. -DCMAKE_INSTALL_PREFIX:PATH=/usr 

,那麼你將發現,隨後只需運行

cmake . 

仍會有CMAKE_INSTALL_PREFIX設置爲/usr


如果你正在尋找從CMAKE_ARGS是從CMake的每一個調用的命令行上定義的變量的完整列表是什麼那麼下面應該做的伎倆:

get_cmake_property(CACHE_VARS CACHE_VARIABLES) 
foreach(CACHE_VAR ${CACHE_VARS}) 
    get_property(CACHE_VAR_HELPSTRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING) 
    if(CACHE_VAR_HELPSTRING STREQUAL "No help, variable specified on the command line.") 
    get_property(CACHE_VAR_TYPE CACHE ${CACHE_VAR} PROPERTY TYPE) 
    if(CACHE_VAR_TYPE STREQUAL "UNINITIALIZED") 
     set(CACHE_VAR_TYPE) 
    else() 
     set(CACHE_VAR_TYPE :${CACHE_VAR_TYPE}) 
    endif() 
    set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR}${CACHE_VAR_TYPE}=\"${${CACHE_VAR}}\"") 
    endif() 
endforeach() 
message("CMAKE_ARGS: ${CMAKE_ARGS}") 

這是有點脆弱,因爲它取決於事實,每個變量是通過命令行設置的短語「無幫助,在命令行上指定的變量」指定爲其HELPSTRING屬性。如果CMake更改此默認HELPSTRING,則必須相應地更新if語句。


如果這不是你想要的CMAKE_ARGS顯示,而是隻從當前執行的論據,那麼我不認爲有辦法做到這一點短黑客的CMake的源代碼!但是,我期望這不是你想要的,因爲所有以前的命令行參數都有效地重新應用。存儲CMake的命令行參數

+0

它工作了一段時間,但後來停止工作。我知道這似乎很奇怪,但我從字面上複製/粘貼上面的腳本,它的工作。然後它停止工作,不管腳本如何變化。也許我會瘋了,但這帶來了「蝙蝠」文件的記憶和他們的不一致的行爲... – Samaursa 2018-01-29 00:34:05

+0

花了我一會兒,弄清楚爲什麼。對於未來的SOers,這不適用於CMake變量。 – Samaursa 2018-01-29 00:55:38

1

的一種方式,是有所謂的包裝腳本~/bin/cmake(*** 1),它不兩兩件事:

  • 創建./cmake_call.sh存儲命令行參數
  • 調用真正的cmake可執行文件,命令行參數

~/bin/cmake#代碼如下所示

#!/usr/bin/env bash 

# 
# Place this file into this location: ~/bin/cmake 
# (with executable rights) 
# 
# This is a wrapper for cmake! 
# * It calls cmake -- see last line of the script 
# It also: 
# * Creates a file cmake_call.sh in the current directory (build-directory) 
# which stores the cmake-call with all it's cmake-flags etc. 
# (It also stores successive calls to cmake, so that you have a trace of all your cmake calls) 
# 
# You can simply reinvoke the last cmake commandline with: ./cmake_call.sh !!!!!!!!!! 
# 
# cmake_call.sh is not created 
# when cmake is called without any flags, 
# or when it is called with flags such as --help, -E, -P, etc. (refer to NON_STORE_ARGUMENTS -- you might need to modify it to suit your needs) 

SCRIPT_PATH=$(readlink -f "$BASH_SOURCE") 
SCRIPT_DIR=$(dirname "$SCRIPT_PATH") 

#http://stackoverflow.com/a/13864829 
if [ -z ${SUDO_USER+x} ]; then 
    # var SUDO_USER is unset 
    user=$USER 
else 
    user=$SUDO_USER 
fi 


#http://stackoverflow.com/a/34621068 
path_append() { path_remove $1 $2; export $1="${!1}:$2"; } 
path_prepend() { path_remove $1 $2; export $1="$2:${!1}"; } 
path_remove() { export $1="`echo -n ${!1} | awk -v RS=: -v ORS=: '$1 != "'$2'"' | sed 's/:$//'`"; } 

path_remove PATH ~/bin # when calling cmake (at the bottom of this script), do not invoke this script again! 




# when called with no arguments, don't create cmake_call.sh 
if [[ -z "[email protected]" ]]; then 
    cmake "[email protected]" 
    exit 
fi 


# variable NON_STORE_ARGUMENTS stores flags which, if any are present, cause cmake_call.sh to NOT be created 
read -r -d '' NON_STORE_ARGUMENTS <<'EOF' 
-E 
--build 
#-N 
-P 
--graphviz 
--system-information 
--debug-trycompile 
#--debug-output 
--help 
-help 
-usage 
-h 
-H 
--version 
-version 
/V 
--help-full 
--help-manual 
--help-manual-list 
--help-command 
--help-command-list 
--help-commands 
--help-module 
--help-module-list 
--help-modules 
--help-policy 
--help-policy-list 
--help-policies 
--help-property 
--help-property-list 
--help-properties 
--help-variable 
--help-variable-list 
--help-variables 
EOF 

NON_STORE_ARGUMENTS=$(echo "$NON_STORE_ARGUMENTS" | head -c -1 `# remove last newline` | sed "s/^/^/g" `#begin every line with ^` | tr '\n' '|') 

#echo "$NON_STORE_ARGUMENTS" ## for debug purposes 

## store all the args 
ARGS_STR= 
for arg in "[email protected]"; do 
    if cat <<< "$arg" | grep -E -- "$NON_STORE_ARGUMENTS" &> /dev/null; then # don't use echo "$arg" .... 
                       # since echo "-E" does not do what you want here, 
                       # but cat <<< "-E" does what you want (print minus E) 
     # do not create cmake_call.sh 
     cmake "[email protected]" 
     exit 
    fi 

    # concatenate to ARGS_STR 
    ARGS_STR="${ARGS_STR}$(echo -n " \"$arg\"" | sed "s,\($(pwd)\)\(\([/ \t,:;'\"].*\)\?\)$,\$(pwd)\2,g")" 
    #            replace $(pwd) followed by 
    #                /   or 
    #                 whitespace or 
    #                  ,   or 
    #                  :  or 
    #                  ;  or 
    #                   '  or 
    #                   " 
    #                 or nothing 
    #            with \$(pwd) 
done 









if [[ ! -e $(pwd)/cmake_call.sh ]]; then 
echo "#!/usr/bin/env bash" > $(pwd)/cmake_call.sh 

# escaping: 
# note in the HEREDOC below, \\ means \ in the output!! 
#       \$ means $ in the output!! 
#       \` means ` in the output!! 
cat <<EOF      >> $(pwd)/cmake_call.sh 


#http://stackoverflow.com/a/34621068 
path_remove() { export \$1="\`echo -n \${!1} | awk -v RS=: -v ORS=: '\$1 != "'\$2'"' | sed 's/:\$//'\`"; } 

path_remove PATH ~/bin # when calling cmake (at the bottom of this script), do not invoke ~/bin/cmake but real cmake! 


EOF 
else 
    # remove bottom 2 lines from cmake_call.sh 
    sed -i '$ d' $(pwd)/cmake_call.sh 
    sed -i '$ d' $(pwd)/cmake_call.sh 
fi 


echo "ARGS='${ARGS_STR}'" >> $(pwd)/cmake_call.sh 
echo "echo cmake \"\$ARGS\"" >> $(pwd)/cmake_call.sh 
echo "eval cmake \"\$ARGS\"" >> $(pwd)/cmake_call.sh 
#echo "eval which cmake"  >> $(pwd)/cmake_call.sh 

chmod +x  $(pwd)/cmake_call.sh 
chown $user: $(pwd)/cmake_call.sh 

cmake "[email protected]" 

用法:

mkdir build 
cd build 
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$(pwd)/install .. 

這將創建cmake_call.sh具有以下內容:

#!/usr/bin/env bash 


#http://stackoverflow.com/a/34621068 
path_remove() { export $1="`echo -n ${!1} | awk -v RS=: -v ORS=: '$1 != "'$2'"' | sed 's/:$//'`"; } 

path_remove PATH ~/bin # when calling cmake (at the bottom of this script), do not invoke ~/bin/cmake but real cmake! 


ARGS=' "-DCMAKE_BUILD_TYPE=Debug" "-DCMAKE_INSTALL_PREFIX=$(pwd)/install" ".."' 
echo cmake "$ARGS" 
eval cmake "$ARGS" 

第三屆最後一行存儲cmake的論點。 現在,您可以重新調用,您使用簡單的調用的確切命令行:

./cmake_call.sh 

腳註:

(*** 1)~/bin/cmake通常是因爲~/.profile的路徑。在第一次創建~/bin/cmake時,可能需要註銷並重新登錄,以使.profile顯示~/bin