2012-04-18 101 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