2

Subversion のリビジョン番号を C++ プロジェクトに埋め込もうとしていますが、そのための GNU make の設定に問題があります。私のメイクファイルは現在、次のようになっています。

check-svnversion:
  ../shared/update-svnversion-h.pl

../shared/svnversion.h: check-svnversion

shared/svnversion.o: ../shared/svnversion.h

.PHONY: check-svnversion

svnversion.osvnversion.cpp(パターン ルールを介して) および(何らかの理由で依存svnversion.h関係チェックが検出されないため、明示的にリストされています) に依存します。 svnversion.hスクリプトによって作成および維持されupdate-svnversion-h.plます (基本的にはsvnversion、出力を実行して C++ ファイルに変更するだけです)。

現在、makeファイルを最新の状態にするには、2 回実行する必要があります。初回はmake実行されますがupdate-svnversion-h.pl(前提条件としてリストされているため)、その後のタイムスタンプをチェックしsvnversion.hて によって変更されたことを確認update-svnversion-h.plしないため、 をリメイクしませんsvnversion.o。2回目は、タイムスタンプをチェックし、update-svnversion-h.plとにかく実行し(今回svnversion.hは最新なので何もしません)、再コンパイルsvnversion.cppして make にしsvnversion.oます。

GNU make に単一の前提条件を 2 回評価するか、前提条件のコマンドが終了するまで前提条件のタイムスタンプのチェックを遅らせるように指示する方法はありますか?

または、ソース コードにリビジョン番号を埋め込むより良い方法はありますか? (速度を上げるために、ビルドごとに再コンパイルが必要なソリューションは避けようとしています。)

4

4 に答える 4

2

これは、 autotoolsがconfig.hヘッダーに対して行うことと似ているようです。

automakeのremake-hdr.amショーをざっと見てみると、それがどのようにトリックを行うかがわかります。

%CONFIG_H%: %STAMP%
## Recover from removal of CONFIG_HEADER
    @if test ! -f $@; then \
      rm -f %STAMP%; \
      $(MAKE) $(AM_MAKEFLAGS) %STAMP%; \
    else :; fi


%STAMP%: %CONFIG_H_DEPS% $(top_builddir)/config.status
    @rm -f %STAMP%
    cd $(top_builddir) && $(SHELL) ./config.status %CONFIG_H_PATH%

そしてconfig.status、スタンプファイルを作成します。

このautomakeの例とあなたの例の主な違いは、automakeがスタンプファイルに触れることですが、あなたの例では実際のファイルではありません。

于 2008-12-02T01:20:24.273 に答える
2

これが私がmakeファイルに入れたターゲットです。さまざまなビルドテレメトリを文字列として返すいくつかの関数を作成します。良い点は、テレメトリが、オブジェクトが作成されたときではなく、最後にリンクされた時間を表すことです。

##
## on every build, record the working copy revision string
##
svn_version.c: $(C_SRC:.c=.o) Makefile
    @echo -n 'const char* build_date(void);\n'  > $@
    @echo -n 'const char* build_date(void)\n{ static const char* build_date = __DATE__ ; '  >> $@
    @echo 'return build_date; }\n'                                                          >> $@
    @echo -n 'const char* build_time(void);\n'                                              >> $@
    @echo -n 'const char* build_time(void)\n{ static const char* build_time = __TIME__ ; '  >> $@
    @echo 'return build_time; }\n'                                                          >> $@
    @echo -n 'const char* svnid_build(void);\n'                                             >> $@
    @echo -n 'const char* svnid_build(void)\n{ static const char* SVN_Version = "\\n<SVN_PID>'    >> $@
    @svnversion -cn .                                                                       >> $@
    @echo '</svn_pid>\\n"; return SVN_Version; }\n'                                         >> $@
    @echo -n 'const char* svnid_build_str_only(void);\n'                                    >> $@
    @echo -n 'const char* svnid_build_str_only(void)\n{ static const char* SVN_Version = "' >> $@
    @svnversion -cn .                                                                       >> $@
    @echo '"; return SVN_Version; }\n'                                                      >> $@
    @$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $(@:.c=.o) $@

最終ターゲットのオブジェクトファイルへの依存関係を、単に「svn_version.c」に置き換えてください。元。

final-target: svn_version.c
    $(CC) $(C_SRC:.c=.o) $(<:.c=.o) -o $@
于 2009-09-28T14:47:07.640 に答える
1

Subversion のキーワード置換を使用して、バージョン番号をコードに入れることができます。

詳細は[本に]記載されていますが、要するに、svn:keywords含めるファイルのプロパティを設定してから、コードのどこかにRev配置する必要があります。$Rev$SVN はこれを自動的に に置き換えます。$Rev: #$ここ#で、 はリビジョン番号です。実際の数値を取得するには、結果の文字列を解析する必要がありますが、簡単に解析できるはずです (最初の 6 文字と最後の文字を削除するだけです)。

これは、リポジトリの最後に変更されたリビジョンではなく、そのファイルの最後に変更されたリビジョンであることに注意してください。それはもう少し複雑で、本のページで詳しく説明されています.

于 2008-12-01T20:58:37.033 に答える
1

check-svnversion ルールで svnversion.o を削除して、必要に応じて強制的に再コンパイルすることで、これを解決しました。これは正確にはエレガントではありませんが、機能します。CesarB's answerで説明されている autotools ソリューションに似ています。

../shared/svnversion.h: check-svnversion

check-svnversion:
    ../shared/update-svnversion-h.pl
    @#Force recreation of svnversion.o.  Otherwise, make won't notice that
    @#svnversion.h has changed until the next time it's invoked.
    @if [ ../shared/svnversion.h -nt shared/svnversion.o ] ; then rm shared/svnversion.o ; fi

shared/svnversion.o: ../shared/svnversion.h

.PHONY: check-svnversion
于 2008-12-02T20:03:52.947 に答える