6

installcheckライブラリをビルドするときに make ターゲットを実装するにはどうすればよいですか? つまり、作成されたライブラリにリンクするテスト プログラムを作成するターゲットcheckがあり、ライブラリ コードが適切に機能するかどうかを確認するためにスクリプトによって呼び出されます。インストール済み; どうすればこれを実装できますか?

4

1 に答える 1

6

これに関するガイドが見つからないので、 GNU automake のマニュアルを読んで一般的な試行錯誤を重ねてパッチを当てた、私が思いついた方法を紹介します。醜いかもしれませんが、うまくいきます...

ライブラリを構築するためのチェック ルーチンに、ライブラリをテスト プログラムにリンクし、そのプログラムが正しく動作するかどうかを確認することが含まれる場合、ライブラリを installcheck するには、同じことを行うだけでよく、テスト プログラムをローカルに構築されたライブラリではなく、インストールされたライブラリにリンクします。図書館。

ライブラリをalphaと呼びましょう(したがって、libalpha.soおよび/またはlibalpha.aを作成します)。alpha のソース コードがsrcディレクトリのalpha.cppファイルにあると仮定すると、通常どおりsrc/Makefile.amを作成します。

# src/Makefile.am

lib_LTLIBRARIES = libalpha.la
libalpha_la_SOURCES = alpha.cpp
include_HEADERS = alpha.h

チェック ルーチンには、alphaにリンクするバイナリbetaの作成が含まれます。betaのソース コードは、ディレクトリtestsのファイルbeta.cppにあります。automake ファイルtests/Makefile.amは次のようになります。

# tests/Makefile.am

check_PROGRAMS = beta
beta_SOURCES = beta.cpp
beta_CPPFLAGS = -I$(top_srcdir)/src
beta_LDADD = $(top_builddir)/src/libalpha.la

次のように、 tests/Makefile.amに「ローカル」ターゲットを作成してcheck、ルーチンを作成します。installcheck

# tests/Makefile.am

# ...

check-local:
    # recipe to run when 'make check' is called.

installcheck-local:
    # recipe to run when 'make installcheck' is called.

checkとのinstallcheckターゲットが競合するのは、どちらかのターゲットを使用すると、もう一方のターゲットが適切に実行されなくなるためです (一方のターゲットが他方のターゲットのビルド ツリーを「汚染」します)。他のターゲットが適切に実行されるためには、ベータ版installcheckとそのオブジェクト ファイルを削除し、その性質 (インストールされたファイル、checkローカル ファイル)に応じて、ターゲットを再コンパイルして再リンクする必要があります。

make clean汚染されたビルド ツリーの問題は、両方のターゲットのレシピで実行するだけで解決できます。これにより、汚染されたビルドが明らかに削除されますが、同じターゲットを再度実行するたびに再構築する必要がないため、熱心すぎます。ビルド ツリーが汚染されるのは、他のターゲットを実行するときだけです。

この複雑さを解決するには、2 つのターゲットのどちらが以前に呼び出されたかを覚えておく必要があります。これは、中間ファイル ( taintと呼びましょう) の作成/破棄によって行うことができます。checkファイルtaintが存在するたびに、ターゲットは汚染されます。これは、 taintをクリーニング、再構築、および削除することによって解決されます。ファイルtaintが存在しない場合、installcheckターゲットは汚染されます。これは、クリーニング、再構築、およびtaintの作成によって解決されます。

ターゲットは次の形式になります。

# tests/Makefile.am

# ...

check-local:
      # First, check to see if the build tree is tainted and rebuild if so
    test ! -f taint || $(MAKE) $(AM_MAKEFLAGS) check_rebuild
      # Then, run our check tests. Substitute with your shell scripts or testsuite files as appropriate
    ./beta

installcheck-local:
      # First, check to see if the build tree is tainted and rebuild if so
    test -f taint || $(MAKE) $(AM_MAKEFLAGS) installcheck_rebuild
      # Then, run our installcheck tests. Substitute with your shell scripts or testsuite files as appropriate
    ./beta

ターゲットは、実行check_rebuild方法に従って再構築する必要がcheckあり、次のようになります。

# tests/Makefile.am

# ...

.PHONY: check_rebuild
check_rebuild:
    $(MAKE) $(AM_MAKEFLAGS) clean          # remove tainted build tree
    $(MAKE) $(AM_MAKEFLAGS) beta$(EXEEXT)  # rebuild beta
    rm -f taint                            # mark build tree as untainted

同様に、ターゲットinstallcheck_rebuildは次のようになります。

# tests/Makefile.am

# ...

.PHONY: installcheck_rebuild
installcheck_rebuild:
    $(MAKE) $(AM_MAKEFLAGS) clean          # remove tainted build tree
    $(MAKE) $(AM_MAKEFLAGS) beta$(EXEEXT) \
      beta_CPPFLAGS="-I$(DESTDIR)$(includedir)" \
      beta_LDADD="$(DESTDIR)$(libdir)/libalpha.la" \
      beta_DEPENDENCIES="$(DESTDIR)$(libdir)/libalpha.la"
    echo 1 > taint                         # mark build tree as untainted

betaを再構築installcheck_rebuildするには、インストールされたライブラリを指すように automake 変数をオーバーライドする必要があることに注意してください。

最後に、「distclean 後にビルド ディレクトリにファイルが残っています」というエラーDISTCLEANFILESで実行が失敗しないように、taint ファイルを に追加する必要があります。distcheck

そして、それはそれであるべきです。最終的なtests/Makefile.amは次のようになります:

# tests/Makefile.am

check_PROGRAMS = beta
beta_SOURCES = beta.cpp
beta_CPPFLAGS = -I$(top_srcdir)/src
beta_LDADD = $(top_builddir)/src/libalpha.la

taint_file = .taint

check-local:
    test ! -f $(taint_file) || $(MAKE) $(AM_MAKEFLAGS) check_rebuild
    ./beta # substitute with your actual test routines

installcheck-local:
    test -f $(taint_file) || $(MAKE) $(AM_MAKEFLAGS) installcheck_rebuild
    ./beta # substitute with your actual test routines

.PHONY: check_rebuild
check_rebuild:
    $(MAKE) $(AM_MAKEFLAGS) clean
    $(MAKE) $(AM_MAKEFLAGS) beta$(EXEEXT)
    rm -f $(taint_file)

.PHONY: installcheck_rebuild
installcheck_rebuild:
    $(MAKE) $(AM_MAKEFLAGS) clean
    $(MAKE) $(AM_MAKEFLAGS) beta$(EXEEXT) \
      beta_CPPFLAGS="-I$(DESTDIR)$(includedir)" \
      beta_LDADD="$(DESTDIR)$(libdir)/libalpha.la" \
      beta_DEPENDENCIES="$(DESTDIR)$(libdir)/libalpha.la"
    echo 1 > $(taint_file)

DISTCLEANFILES = $(taint_file)

免責事項

これは Linux で「標準」ビルド用にチェックされていますが、他のビルド環境や「特殊な」ことをしようとしている場合には機能しない可能性があります。うまくいけばいいのですが、わざわざチェックしたことはありません。エラーがある場合、上記のターゲットの 1 つで変数が欠落しているか誤用されている可能性があります。

たとえば、check_rebuildターゲットには次の行があります。

check_rebuild:
    # ...
    $(MAKE) $(AM_MAKEFLAGS) beta$(EXEEXT)
    # ...

変数$(AM_MAKEFLAGS)$(EXEEXT)は、automake 自体が作成する Makefile に入力するルーチンを作成する方法の一部であり、上記のターゲットでそれらを無視した場合、ビルドが失敗する (または少なくとも期待どおりに機能しない) 可能性があります。

上記で提案したターゲットが同様に正規に構築されていることを確認しようとしましたが、何かを見落としている可能性があります。ビルド エラーが発生した場合の最善の策は、ビルド中に automake 自体によって生成された Makefile を開いて、オブジェクトがどのように作成されているかを確認し、対応する Makefile.am ファイルでそれらの構成を模倣することです。

もう 1 つの可能性のある問題は、ターゲットでベータバイナリをビルドした "ハックな" 方法にある可能性があります。installcheck_rebuild繰り返しになりますが、問題を診断する最善の方法は、automake が生成する Makefile でどのように動作しているかを確認し、それを模倣しようとすることです。それ以外の場合は、automake のマニュアルを読む必要があります。それができない場合は、おそらく私より知識のある人の助けが必要になるでしょう。幸運を。

于 2013-08-14T19:38:33.320 に答える