2012-04-18 30 views
9

Quiero registrar los argumentos pasados ​​a cmake en mis scripts generados. Por ejemplo, "my-config.in" será procesada por cmake, no tiene definición así:Cómo capturar los argumentos de línea de comandos de CMake?

config = "@ CMAKE_ARGS @"

Después cmake, my-config contendrá una línea como la esto:

config = "- DLINUX -DUSE_FOO = y -DCMAKE_INSTALL_PREFIX =/usr"

probé CMAKE_ARGS, CMAKE_OPTIONS, pero falló. Ningún documento menciona esto. :-(

Respuesta

16

No sé de cualquier variable que proporciona esta información, pero se puede generar por sí mismo (con algunas salvedades).

Cualquier -D argumentos pasados ​​a CMake se añaden al archivo de caché CMakeCache.txt en el directorio de construcción y se vuelve a aplicar durante las invocaciones posteriores sin tener que estar especificado en la línea de comandos de nuevo.

Así que en tu ejemplo, si primero ejecutar CMake como

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

continuación, se quiere encontrar que posteriormente se ejecuta simplemente

cmake . 

todavía tendrá CMAKE_INSTALL_PREFIX conjunto de /usr


Si lo que estás buscando de CMAKE_ARGS es la lista completa de las variables definidas en la línea de comandos de cada invocación de CMake a continuación, el siguiente debe hacer el truco:

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}") 

Esto es un poco frágil, ya que depende del hecho de que cada variable que tiene ser en set a través de la línea de comando tiene la frase "No help, variable specified on the command line." especificada como su propiedad HELPSTRING. Si CMake cambia este valor predeterminado HELPSTRING, deberá actualizar la declaración if según corresponda.


Si esto no es lo que quiere CMAKE_ARGS para mostrar, pero en cambio sólo los argumentos de la ejecución actual, entonces no creo que hay una manera de hacerlo por debajo de la piratería código fuente de CMake! Sin embargo, espero que esto no sea lo que desea, ya que todos los argumentos anteriores de la línea de comando se vuelven a aplicar de manera efectiva cada vez.

+0

Funcionó por un tiempo pero luego dejó de funcionar. Sé que esto parece muy extraño, pero literalmente copié/pegué el script anterior y funcionó. Y luego dejó de funcionar, sin ningún cambio en el script en absoluto. Tal vez me estoy volviendo loco, pero esto me trae recuerdos de los archivos 'bat' y su comportamiento incoherente ... – Samaursa

+0

Me tomó un tiempo averiguar por qué. Para futuros SOers, esto no funcionará con las variables de CMake. – Samaursa

1

Una forma de almacenar CRealice argumentos de línea de comandos, es tener un guión envoltorio llamada ~/bin/cmake (*** 1), que hace 2 cosas:

  • crear ./cmake_call.sh que almacena los argumentos de línea de comandos
  • llamada la verdadera cmake ejecutable con los argumentos de línea de comandos

~/bin/cmake # código se muestra a continuación

#!/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]" 

Uso:

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

Esto creará cmake_call.sh con el siguiente contenido:

#!/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" 

La tercera última línea almacena los argumentos cmake. Ahora puede volver a invocar la línea de comandos exacta que utilizó simplemente llamando:

./cmake_call.sh 

Notas al pie:

(*** 1) ~/bin/cmake es por lo general en el camino porque de ~/.profile. Al crear ~/bin/cmake la primera vez, es posible que sea necesario cerrar la sesión y volver a iniciarla, de modo que .profile vea ~/bin.

Cuestiones relacionadas