2012-04-18 4 views
9

Я хочу записать аргументы, переданные cmake в мои сгенерированные скрипты. Например, "my-config.in" будут обработаны CMake, то есть определение, как это:Как захватить аргументы командной строки CMake?

конфиг = "@ CMAKE_ARGS @"

После cmake, my-config будет содержать строки что-то вроде это:

конфиг = "- DLINUX -DUSE_FOO = у -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}") 

Это немного хрупкими, как это зависит от того, что каждая переменная, которая имеет быть en, установленный через командную строку, содержит фразу «Без справки, переменная, указанная в командной строке», указанная как ее свойство HELPSTRING. Если CMake изменит это значение по умолчанию HELPSTRING, вам придется обновить заявление if соответственно.


Если это не то, что вы хотите CMAKE_ARGS, чтобы показать, но вместо этого только аргументы из текущего исполнения, то я не думаю, что есть способ сделать это короткий взлома исходного кода CMake в! Однако я ожидаю, что это не то, что вы хотите, поскольку все предыдущие аргументы командной строки эффективно повторно применяются каждый раз.

+0

Это работало некоторое время, но затем оно перестало работать. Я знаю, что это кажется очень странным, но я буквально копировал/вставлял вышеупомянутый скрипт, и это сработало. А потом он перестает работать, без каких-либо изменений в скрипте. Возможно, я схожу с ума, но это возвращает воспоминания о файлах «bat» и их непоследовательном поведении ... – Samaursa

+0

Подумал, почему. Для будущих SOers это не будет работать с переменными CMake. – Samaursa

1

Один из способов сохранить CMake аргументы командной строки, чтобы иметь сценарий оболочки под названием ~/bin/cmake (*** 1), который делает 2 вещи:

  • создать ./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" 

3-я последняя строка хранит аргументы CMake. Теперь вы можете reinvoke точную командной строки, которые вы использовали, просто позвонив:

./cmake_call.sh 

Сноски:

(*** 1) ~/bin/cmake, как правило, в PATH из-за ~/.profile. При создании ~/bin/cmake в первый раз, возможно, потребуется выйти из системы и вернуться обратно, так что .profile видит ~/bin.

Смежные вопросы