2016-04-13 17 views
0

私はうまく動作する "C"/C++ CMakeプロジェクトを持っています。しかし、私は時々(時間)が少し異なるリモートクラスタを構築することがあります。このマシンはLinuxを実行しており、私はmakeを使用してビルドしています。私はファイルの変更がどのように検出されたかを変更するいくつかのmake/CMakeの方法があるかどうか疑問に思っています。タイムスタンプを使用するのではなく、MD5またはdiffに設定します。それ以外の場合は、私は定数make clean/make -jのサイクルに耐えなければならないか、その特定のサーバーで作業するたびに現地時間を変更する必要があると思います。CMakeはどのように変更されたファイルを検出しますか

私はこれらの設定を変更するフラグが存在するかどうかを確認するためにCMakeのドキュメントを突き止めていましたが、何も見つかりませんでした。 RTCのないプラットフォーム(Raspberryなど)ではどのように動作しますか?

+3

CMakeは変更されたファイルを検出しません。**全くの**。 CMakeはビルドファイルを生成します。 'make '、またはKDevelop、またはNinjaのために。 *これらのツールは、それぞれ独自の方法で変更されたファイルを検出します。関連するツールのドキュメントを確認してください。システム管理者に確認してください。関連するすべてのシステムが適切にNTP同期されているかどうかは関係ありません。 – DevSolar

+0

@DevSolar権利、私はそれがより低いレベルに行きました。タイムスタンプを使わないようにする方法を考えていますか?それは国家のスーパーコンピューティングセンターで、私は時間を変えるように彼らを説得するのは難しいと思う。 –

+0

さて、タイムスタンプをチェックするのは 'make 'が* for *です。再構築が必要なものを検出する方法なしに、部分的な再構築をどのように期待しますか? – DevSolar

答えて

0

右は、そうCMakeの/ makeは私がやりたいことはありませんし、私がターゲットに私のマシンの時間を同期させる手間を望んでいないことを知って、私は次のを思い付いた:

#!/bin/bash 

touch src_hash.md5 

echo -n make "[email protected]" > mymake.sh 

find `pwd`/../src `pwd`/../include -print0 | 
    while IFS= read -r -d $'\0' f; do 
     if [[ ! -d "$f" ]]; then 
      MD5=`md5sum "$f" | awk -v fn="$f" '{ print "\"" fn "\" " $1; }'` 
      echo $MD5 >> src_hash.md5.new 

      OLDMD5=`grep -e "^\"$f\"" src_hash.md5` 
      if [[ "$OLDMD5" == "" ]]; then 
       echo "$MD5 -- [a new file]" 
       continue # a new file, make can handle that well on its own 
      fi 

      HASH=`echo $MD5 | awk '{ print $2; }'` 
      OLDHASH=`echo $OLDMD5 | awk '{ print $2; }'` 
      if [[ "$HASH" != "$OLDHASH" ]]; then 
       echo "$MD5 -- changed from $OLDHASH" 
       echo -n " \"--what-if=${f}\"" >> mymake.sh 
       # this is running elsewhere, can't pass stuff via variables 
      fi 
     fi 
    done 

touch src_hash.md5.new 
mv src_hash.md5.new src_hash.md5 

echo using: `cat mymake.sh` 
echo >> mymake.sh # add a newline 
chmod +x mymake.sh 
./mymake.sh 
rm -f mymake.sh 

これは、ソースファイルのハッシュのリストをsrc_hash.md5に保存し、実行するたびに、現在のファイルとそれらのハッシュを比較し、それに応じてリストを更新します。

最後に、makeを呼び出し、スクリプトに指定した引数をすべて渡します(など)。これは--what-if=スイッチを利用して、makeに与えられたファイルが変更されたように動作するようにします。つまり、ビルドターゲットのソース/ヘッダーへの依存をエレガントに処理します。

ソース/インクルードファイルへのパスを引数として渡し、内部でハードコーディングされないようにすることもできます。 makeは何かを再構築しませ程度頑固な余分なときの状況のた​​め、ファイルのタイムスタンプを変更して復元するtouchを使用して

または上記のスクリプトの1回の以上の繰り返し、:

#!/bin/bash 

if [[ ! -d ../src ]]; then 
    >&2 echo "error: ../src is not a directory or does not exist" 
    exit -1 
fi 
if [[ ! -d ../include ]]; then 
    >&2 echo "error: ../include is not a directory or does not exist" 
    exit -1 
fi 

echo "Scanning for changed files in ../src and ../include" 

touch src_hash.md5 # in case this runs for the first time 

rm -f mymaketouch.sh 
rm -f mymakerestore.sh 
touch mymaketouch.sh 
touch mymakerestore.sh 

echo -n make "[email protected]" > mymake.sh 

CWD="`pwd`" 
find ../src ../include -print0 | 
    while IFS= read -r -d $'\0' f; do 
     if [[ ! -d "$f" ]]; then 
      fl=`readlink -f "$CWD/$f"` 

      MD5=`md5sum "$fl" | awk -v fn="$fl" '{ print "\"" fn "\" " $1; }'` 
      HASH=`echo $MD5 | awk '{ print $2; }'` 
      echo $MD5 >> src_hash.md5.new 

      OLDMD5=`grep -e "^\"$fl\"" src_hash.md5` 
      OLDHASH=`echo $OLDMD5 | awk '{ print $2; }'` 
      if [[ "$OLDMD5" == "" ]]; then 
       echo "$f $HASH -- [a new file]" 
       continue # a new file, make can handle that well on its own 
      fi 

      if [[ "$HASH" != "$OLDHASH" ]]; then 
       echo "$f $HASH -- changed from $OLDHASH" 

       echo "touch -m \"$fl\"" >> mymaketouch.sh # will touch it and change modification time 
       stat "$fl" -c "touch -m -d \"%y\" \"%n\"" >> mymakerestore.sh # will restore it later on so that we do not run into problems when copying newer from a different system 

       echo -n " \"--what-if=$fl\"" >> mymake.sh 
       # this is running elsewhere, can't pass stuff via variables 
      fi 
     fi 
    done 

echo using: `cat mymake.sh` 
echo >> mymake.sh # add a newline 
echo 'exit $?' >> mymake.sh 

chmod +x mymaketouch.sh 
chmod +x mymakerestore.sh 
chmod +x mymake.sh 

control_c() # run if user hits control-c 
{ 
    echo -en "\nrestoring modification times\n" 
    ./mymakerestore.sh 
    rm -f mymaketouch.sh 
    rm -f mymakerestore.sh 
    rm -f mymake.sh 
    rm -f src_hash.md5.new 
    exit -1 
} 

trap control_c SIGINT 

./mymaketouch.sh 
./mymake.sh 
RETVAL=$? 
./mymakerestore.sh 
rm -f mymaketouch.sh 
rm -f mymakerestore.sh 
rm -f mymake.sh 

touch src_hash.md5.new # in case there was nothing new 
mv src_hash.md5.new src_hash.md5 
# do it now in case someone hits ctrl+c mid-build and not all files are built 

exit $RETVAL 

、あるいは場合には、並列にあなたをハッシュ実行

#!/bin/bash 

if [[ ! -d ../src ]]; then 
    >&2 echo "error: ../src is not a directory or does not exist" 
    exit -1 
fi 
if [[ ! -d ../include ]]; then 
    >&2 echo "error: ../include is not a directory or does not exist" 
    exit -1 
fi 

echo "Scanning for changed files in ../src and ../include" 

touch src_hash.md5 # in case this runs for the first time 

rm -f mymaketouch.sh 
rm -f mymakerestore.sh 
touch mymaketouch.sh 
touch mymakerestore.sh 

echo -n make "[email protected]" > mymake.sh 

CWD="`pwd`" 
rm -f src_hash.md5.new # will use ">>", make sure to remove the file 
find ../src ../include -print0 | 
    while IFS= read -r -d $'\0' f; do 
     if [[ ! -d "$f" ]]; then 
      fl="$CWD/$f" 
      (echo `md5sum "$f" | awk -v fn="$fl" '{ print "\"" fn "\" " $1; }'`) & # parallel, echo is atomic (http://stackoverflow.com/questions/9926616/is-echo-atomic-when-writing-single-lines) 
      # run in parallel (remove the ampersand if you run into trouble) 
     fi 
    done >> src_hash.md5.new # >> is atomic but > wouldn't be 
# this is fast 

cat src_hash.md5 > src_hash.md5.diff 
echo separator >> src_hash.md5.diff 
cat src_hash.md5.new >> src_hash.md5.diff 
# make a compound file for awk (could also read the other file in awk but this seems simpler right now) 

cat src_hash.md5.diff | awk 'BEGIN { FS="\""; had_sep = 0; } 
    { 
     if(!had_sep && $1 == "separator") 
      had_sep = 1; 
     else { 
      sub(/[[:space:]]/, "", $3); 
      if(!had_sep) 
       old_hashes[$2] = $3; 
      else { 
       f = $2; 
       if((idx = index(f, "../")) != 0) 
        f = substr(f, idx, length(f) - idx + 1); 
       if($2 in old_hashes) { 
        if(old_hashes[$2] != $3) 
         print "\"" f "\" " $3 " -- changed from " old_hashes[$2]; 
       } else 
        print "\"" f "\" -- a new file " $3; 
      } 
     } 
    }' 
# print verbose for the user only 

cat src_hash.md5.diff | awk 'BEGIN { FS="\""; had_sep = 0; } 
    { 
     if(!had_sep && $1 == "separator") 
      had_sep = 1; 
     else { 
      sub(/[[:space:]]/, "", $3); 
      if(!had_sep) 
       old_hashes[$2] = $3; 
      else { 
       if($2 in old_hashes) { 
        if(old_hashes[$2] != $3) 
         printf($2 "\0"); /* use \0 as a line separator for the below loop */ 
       } 
      } 
     } 
    }' | 
    while IFS= read -r -d $'\0' fl; do 
     echo "touch -m \"$fl\"" >> mymaketouch.sh # will touch it and change modification time 
     stat "$fl" -c "touch -m -d \"%y\" \"%n\"" >> mymakerestore.sh # will restore it later on so that we do not run into problems when copying newer from a different system 

     echo -n " \"--what-if=$fl\"" >> mymake.sh 
     # this is running elsewhere, can't pass stuff via variables 
    done 
# run again, handle files that require change 

rm -f src_hash.md5.diff 

echo using: `cat mymake.sh` 
echo >> mymake.sh # add a newline 
echo 'exit $?' >> mymake.sh 

chmod +x mymaketouch.sh 
chmod +x mymakerestore.sh 
chmod +x mymake.sh 

control_c() # run if user hits control-c 
{ 
    echo -en "\nrestoring modification times\n" 
    ./mymakerestore.sh 
    rm -f mymaketouch.sh 
    rm -f mymakerestore.sh 
    rm -f mymake.sh 
    rm -f src_hash.md5.new 
    exit -1 
} 

trap control_c SIGINT 

./mymaketouch.sh 
./mymake.sh 
RETVAL=$? 
./mymakerestore.sh 
rm -f mymaketouch.sh 
rm -f mymakerestore.sh 
rm -f mymake.sh 

touch src_hash.md5.new # in case there was nothing new 
mv src_hash.md5.new src_hash.md5 
# do it now in case someone hits ctrl+c mid-build and not all files are built 

exit $RETVAL 
+0

@ComicSansMS修正のおかげで、bashがそのようにサポートされていたかどうかは分かりませんでした。私は、 "将来のSOハイライター"の後ろに '.sh'を残していたのがもっともです。 –

関連する問題