1

(Pythonスクリプトを介して)作成foo.hdbおよび作成することになっている次のMakefile.amがあります。foo.cdbfoo.h

TESTS = check_foo

check_PROGRAMS = check_foo

check_foo_SOURCES = check_foo.c $(top_builddir)/src/isti.h \
    foo.cdb foo.h foo.hdb
check_foo_CFLAGS = @CHECK_CFLAGS@ $(all_includes) -I../../clib/src/
check_foo_LDADD = $(top_builddir)/src/libcorm.la @CHECK_LIBS@ -lsqlite3

%.hdb %.cdb: %.h
    PYTHONPATH=$(top_builddir)/cgen/src python $(top_builddir)/cgen/src/isti/cgen/run.py $<

clean-local:
    rm -f *.hdb *.cdb

ただし、make foo.hdbandmake foo.cdbは機能しますが(Pythonコードを呼び出してfoo.hdbfoo.cdbファイルをから生成しますfoo.h)、make clean check(または2つを別々に)機能しません(欠落しているfoo.hdb-そのようなファイルはありません)-から生成するためにパターンルールは呼び出されませfoo.hdbfoo.h

つまり、check_foo_SOURCESにリストされているファイルに対してパターンルールが呼び出されていません

どうすればこれを機能させることができますか?残りのautotoolsインフラストラクチャは正常に機能しています。Makefileを見ると、autotoolsがチェックソースを拡張する方法に問題があるのではないかと思います。

これはすべてLinuxでGnumakeを使用しています。これがMakefileです。

[MadScientistの助けを反映するために少し更新されました]。

後で更新

次のMakefile(autotoolsではなくmakeだけ)は正常に機能するため、この問題はautotoolsとchecksupportに関連しているようです。

all: check_foo

CFLAGS=-I../../clib/src
LDFLAGS=-L../../clib/src/.libs

check_foo: check_foo.c foo.h corm_foo.h corm_foo.c
    gcc $(CFLAGS) $(LDFLAGS) $^ -o $@ -lcorm -lsqlite3

corm_%.h corm_%.c: %.h
    PYTHONPATH=../../cgen/src python ../../cgen/src/isti/cgen/run.py $<

clean:
    rm -f corm_*.h corm_*.c
    rm -f *.o

(ファイル拡張子がOKのままになるように、xxx.hdbからcorm_xxx.hなどに切り替えたことに注意してください)。

詳細

CHECKマクロに関連しているように見えるので、これはconfigure.acです。

AC_INIT([corm], [0.1], [a.cooke@isti.com])
AC_CONFIG_MACRO_DIR([m4])
PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) 
AM_INIT_AUTOMAKE([-Wall foreign -Werror])
AC_PROG_CC_C99
AM_PROG_CC_C_O
LT_INIT
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile clib/Makefile clib/src/Makefile clib/tests/Makefile clib/docs/Makefile cgen/Makefile cgen/docs/Makefile example/Makefile example/src/Makefile])
AC_CHECK_PROGS([DOXYGEN], [doxygen], AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]))
AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([clib/docs/Doxyfile cgen/docs/Doxyfile])])

解決

さて、以下のさまざまなことを要約すると、2つの重要な問題がありました(ファイル拡張子を修正したら、「プレーンな」makefileとfcellerの回答を参照してください)。どちらも機能させるのに十分でした。

  1. (処理)ヘッダーファイルは複雑です。自動依存関係のため、プログラムで生成されたヘッダーファイルは問題を解決します。解決策は、 BUILT_SOURCESを使用することです

  2. ただし、.cファイル(の処理)は複雑ではありません。したがって、corm_foo.cをcheck_foo.cの前に置くと、そのファイルの生成がトリガーされます。これもcorm_foo.hを生成するため、すべてが機能します(check_foo.cにcorm_foo.hを含めることができるようになったため)。

また、fcellerには、整頓されたmakefileに関するいくつかの優れた一般的なポイントがあり、「プレーンな」makefileが機能する理由を説明しています。

4

4 に答える 4

2

この線

%.cdb: %.hdb

何もしません。GNU makeマニュアルを確認すると、コマンドラインのないパターンルールが、同じパターンで以前に定義されたルールを削除するために使用されていることがわかります。以前のルールがないため、これは基本的にノーオペレーションです。

ルールを1回呼び出すだけで2つの出力ファイルを作成するコマンドがある場合は、次のように両方のパターンを同じルールに配置する必要があります。

%.cdb %.hdb: %.h
        PYTHONPATH=$(top_builddir)/cgen/src python $(top_builddir)/cgen/src/isti/cgen/run.py $<

これにより、GNU makeは、両方のターゲットがルールの1回の呼び出しから生成されることを通知します。注意してください!この構文は、パターンルールに対してのみこの動作をします。複数のターゲットを持つ明示的なルールは、まったく異なることを行います(紛らわしいほどです)。

振る舞いについてmake cleanはよくわかりません。automakeによって生成されたmakefileは複雑すぎて、私はそれを読むことができません。デバッグが必要になります(実行して何が起こるかを追跡します)。cleanただし、ターゲットとビルドターゲットの両方を同じmakeの呼び出しで実行できるように、そこにあるルールが適切に設計されていないのではないかと思います。2つのコマンドを別々に実行し、それがより適切に機能するかどうかを確認します。

make clean
make check
于 2013-02-19T22:51:30.673 に答える
2

まず第一に、*_SOURCESに「*.h」を含める必要はありません。automakeは、依存関係を生成するためのコードを生成します。マニュアルから:_SOURCES定義にリストされているヘッダーファイルはディストリビューションに含まれますが、それ以外の場合は無視されます

プレーンなMakefileで行った変更(「ファイル拡張子がOKのままになるように、xxx.hdbからcorm_xxx.hなどに切り替えたことに注意してください」)は不可欠です。automakeは、何を呼び出すか(CC、CXX、F77)を確認するために、ファイル名拡張子を使用して*_SOURCESリストをフィルタリングします。

次のMakefile.amが機能します。

TEST = check_foo

check_PROGRAMS = check_foo

check_foo_SOURCES = check_foo.c foo.db.c
check_foo_CFLAGS = 
check_foo_LDADD = 

%.db.c %.db.h: %.h
    echo "int i = 1;" > foo.db.c
    echo "int j;" > foo.db.h

clean-local:
    rm -f *.db.h *.db.c
于 2013-02-22T18:44:20.830 に答える
1

foo.hdb構築されるソースファイルであるautomakeに指示する必要があります。以下をMakefile.amに追加します。

BUILT_SOURCES = foo.hdb
于 2013-02-23T21:01:12.680 に答える
0

既存の直接的なものに間接的な答え/議論を追加してみましょう。

私は最近、あなたが経験したのと同じ種類の理由で離れましmakeた。それは非常に強力ですが、物事が期待どおりに進まない場合はデバッグが少し難しい場合があります。

私は最近、makeのデバッグ可能な代替ビルドツールとして非常に有望なpydoitを発見しました。「パターンルール」の概念が含まれていなかったので、私はその仕事をするための独立したパッケージfprulesを提案しました。

doitこれは、投稿で言及したのと同じタスクを実行する方法ですfprules

from fprules import file_pattern

# all: check_foo
DOIT_CONFIG = {'default_tasks': ['check_foo']}

CFLAGS = '-I../../clib/src'
LDFLAGS = '-L../../clib/src/.libs'

# check_foo: check_foo.c foo.h corm_foo.h corm_foo.c
#     gcc $(CFLAGS) $(LDFLAGS) $^ -o $@ -lcorm -lsqlite3
def task_check_foo():
    """
    Compiles the `check_foo` executable
    """
    src_files = ('check_foo.c', 'foo.h', 'corm_foo.h', 'corm_foo.c')
    dst_file = 'check_foo'
    return {

        'file_dep': src_files,
        'actions': ["gcc %s %s %s -o %s -lcorm -lsqlite3" % (CFLAGS, LDFLAGS, ' '.join(src_files), dst_file)],
        'verbosity': 2,
        'targets': [dst_file],
        'clean': True
    }

# corm_%.h corm_%.c: %.h
#     PYTHONPATH=../../cgen/src python ../../cgen/src/isti/cgen/run.py $<
def task_gen_corm():
    """
    Generates files `corm_%.h` and `corm_%.c`
    for each header file `%.h`.
    """
    for data in file_pattern('./*.h', dict(h_file='./corm_%.h', c_file='./corm_%.c')):
        yield {
            'name': data.name,
            'file_dep': [data.src_path],
            'actions': ["PYTHONPATH=../../cgen/src python ../../cgen/src/isti/cgen/run.py %s" % data.src_path],
            'verbosity': 2,
            'targets': [data.h_file, data.c_file],
            'clean': True
        }

# clean:
#     rm -f corm_*.h corm_*.c
#     rm -f *.o
# No need to create tasks for this: 
# with 'clean': True, `doit clean` will clean all target files

次にdoit、フォルダ内で実行します。

必要に応じて、プロジェクトページにフィードバックを提供することを躊躇しないでください。たとえば、複数行のコマンドはサポートされていません。不足していると感じた場合は、投票できます:https ://github.com/pydoit/doit/issues/314

于 2019-08-01T16:58:02.147 に答える