2012-04-18 22 views
9

Tôi muốn ghi lại các đối số được chuyển đến cmake trong các tập lệnh được tạo của tôi. Ví dụ, "my-config.in" sẽ được xử lý bởi cmake, nó có nghĩa như thế này:Làm thế nào để nắm bắt các đối số dòng lệnh CMake?

config = "@ CMAKE_ARGS @"

Sau cmake, my-config sẽ chứa một dòng cái gì đó như này:

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

tôi đã cố gắng 01., CMAKE_OPTIONS, nhưng không thành công. Không có tài liệu nào đề cập đến điều này. :-(

Trả lời

16

Tôi không biết về bất kỳ biến cung cấp thông tin này, nhưng bạn có thể tạo ra nó cho mình (với một vài provisos).

Bất kỳ -D đối số truyền cho CMake được thêm vào tập tin bộ nhớ cache CMakeCache.txt trong thư mục xây dựng và được reapplied trong lời gọi tiếp theo mà không cần phải được xác định trên dòng lệnh một lần nữa.

vì vậy, trong ví dụ của bạn, nếu bạn lần đầu tiên thực hiện CMake như

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

sau đó bạn sẽ thấy rằng sau đó chạy đơn giản

cmake . 

vẫn sẽ có CMAKE_INSTALL_PREFIX thiết lập để /usr


Nếu những gì bạn đang tìm kiếm từ CMAKE_ARGS là danh sách đầy đủ của các biến được xác định trên dòng lệnh từ mọi gọi của CMake thì những điều sau đây nên thực hiện thủ thuật:

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

Đây là một chút mong manh tùy thuộc vào thực tế là mỗi biến số vi được thiết lập thông qua dòng lệnh có cụm từ "Không có trợ giúp, biến được chỉ định trên dòng lệnh." được chỉ định làm thuộc tính HELPSTRING của nó. Nếu CMake thay đổi mặc định HELPSTRING này, bạn phải cập nhật câu lệnh if tương ứng.


Nếu đây không phải là những gì bạn muốn CMAKE_ARGS để hiển thị, nhưng thay vì chỉ các đối số từ thực thi hiện tại thì tôi không nghĩ rằng có cách để làm điều đó thiếu mã nguồn của CMake! Tuy nhiên, tôi hy vọng đây không phải là những gì bạn muốn vì tất cả các đối số dòng lệnh trước đó được áp dụng lại hiệu quả mọi lúc.

+0

Nó hoạt động được một lúc nhưng sau đó nó ngừng hoạt động. Tôi biết điều này có vẻ rất lạ, nhưng tôi theo nghĩa đen sao chép/dán kịch bản trên và nó hoạt động. Và sau đó nó ngừng hoạt động, không có bất kỳ thay đổi nào đối với kịch bản. Có lẽ tôi sẽ phát điên nhưng điều này mang lại những kỷ niệm về các tập tin “bat” và hành vi không nhất quán của họ ... – Samaursa

+0

Hãy cho tôi một thời gian để tìm ra lý do. Đối với các SOers trong tương lai, điều này sẽ không hoạt động với các biến CMake. – Samaursa

1

Một cách để lưu trữ CMake đối số dòng lệnh, là phải có một kịch bản wrapper gọi ~/bin/cmake (*** 1), mà không 2 điều:

  • tạo ./cmake_call.sh lưu trữ các đối số dòng lệnh
  • gọi thực cmake thực thi với các đối số dòng lệnh

~/bin/cmake # mã được hiển thị bên dưới

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

Cách sử dụng:

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

này sẽ tạo cmake_call.sh với nội dung sau:

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

Dòng cuối cùng 3rd lưu trữ các đối số cmake. Bây giờ bạn có thể reinvoke dòng lệnh chính xác mà bạn sử dụng bằng cách đơn giản gọi:

./cmake_call.sh 

Chú thích:

(*** 1) ~/bin/cmake thường là trong PATH vì ~/.profile. Khi tạo ~/bin/cmake lần đầu tiên, có thể cần phải đăng xuất và đăng nhập lại để .profile thấy ~/bin.

Các vấn đề liên quan