web-dev-qa-db-ja.com

Makefileを作成して、変更されたファイルのみを再コンパイルするにはどうすればよいですか?

編集されたファイルのみをコンパイルするようにmakeを取得するのに少し苦労しています。しかし、私はあまり成功せず、すべてのファイルが再コンパイルされます。誰かが私に理由を説明できますか?

私のファイルは次のとおりです。

main.c
a_functions.c

ここで、main.c includemain.hおよびa_functions.c includeah

ここに私のメイクファイルがあります:

CC=gcc
CFLAGS=-Wall -I. -c
EXEC_FILE=program1


all: program

a_functions.o: a_functions.c
a_functions.c: a.h
main.o: main.c
main.c: main.h

objects: a_functions.c main.c
    $(CC) a_functions.c main.c $(CFLAGS)

program: a_functions.o main.o
    $(CC) a_functions.o main.o -o $(EXEC_FILE)

提案に従ってメイクファイルを変更すると、同じ問題があるようです::

all: program

a_functions.o: a_functions.c a.h
    gcc a_functions.c -c

main.o: main.c main.h
    gcc main.c -c

program: a_functions.o main.o
    gcc a_functions.o main.o -o program1
55
Pithikos

あなたが話している特定の問題-何も変わっていない場合でも(オブジェクトを再リンクすることで)_program1_を再構築する-はこのルールにあります:

_program: a_functions.o main.o
    gcc a_functions.o main.o -o program1
_

このルールのターゲットはprogramであり、Makeはそれがファイルであると仮定します。ただし、そのようなファイルは存在しないため、Makeを実行するたびに、Makeはこのファイルを再構築する必要があると判断し、ルールを実行します。これをお勧めします:

_program1: a_functions.o main.o
    gcc a_functions.o main.o -o program1
_

または、これは:

_program1: a_functions.o main.o
    gcc $^ -o $@
_

それとももっといいでしょう:

_$(EXEC_FILE): a_functions.o main.o
    $(CC) $^ -o $@
_

(そして、一致するallルールを変更することを忘れないでください。)

他のいくつかのポイント:

  1. @paxdiabloが指摘したように、

    _a_functions.o: a_functions.c a.h
    main.o: main.c main.h
    _
  2. 一方の何か(おそらく_main.o_)が他方の何か(おそらく_a_functions.o_)を呼び出さない限り、これらのオブジェクトをリンクすることは意味がありません。

    _main.o: a.h
    _

    だから私はあなたがいくつかの見当違いの宣言を持っていると思う。

  3. objectsルールを宣言しますが、それを参照することはありません。したがって、実際に使用することはありません。 Makeは_%.o: %.c_のデフォルトルールを使用します。これをお勧めします:

    _OBJECTS = a_functions.o main.o
    $(OBJECTS): %: %.c
        $(CC) $< $(CFLAGS) -o $@
    _

    (この場合、$(EXEC_FILE): a_functions.o main.o$(EXEC_FILE): $(OBJECTS)に変更できます。)またはこれだけ:

    _%.o: %.c
        $(CC) $< $(CFLAGS) -o $@
    _
75
Beta

これが特定の問題の原因かどうかはわかりませんが、次の2行です。

a_functions.c: a.h
main.c: main.h

一般的に、含まれているヘッダーに基づいてCファイルを再作成するコマンドがないため、間違いです。

Cファイルはヘッダーファイルに依存しません。Cファイルによって作成されたオブジェクトです。

たとえば、次のmain.c

#include <hdr1.h>
#include <hdr2.h>
int main (void) { return 0; }

makefileには次のようになります。

main.o: main.c hdr1.h hdr2.h
    gcc -c -o main.o main.c

変化する:

a_functions.o: a_functions.c
a_functions.c: a.h
main.o: main.c
main.c: main.h

に:

a_functions.o: a_functions.c a.h
main.o: main.c main.h

a_functions.ca.hが含まれ、main.cmain.hが含まれると仮定して)、もう一度試してください。

上記の仮定が間違っている場合は、正しいCルールを伝えるために、どのCファイルにどのヘッダーが含まれているかを伝える必要があります。


makefileがこれらの変更後もすべてを構築しているという主張がある場合は、2つのことを検討する必要があります。

1つ目は、関連するすべてのファイルのls -lからの出力です。これにより、ファイルの日付と時刻を確認できます。

2番目はmakeからの実際の出力です。 make -dの出力は、showsどのファイルと日付makeが何をすべきかを判断するために使用しているため、特に役立ちます。


調査の観点では、makeは次のトランスクリプトに従って正常に機能するようです。

=====
pax$ cat qq.h
#define QQ 1
=====
pax$ cat qq.c
#include "qq.h"
int main(void) { return 0; }
=====
pax$ cat qq.mk
qq: qq.o
        gcc -o qq qq.o

qq.o: qq.c qq.h
        gcc -c -o qq.o qq.c
=====
pax$ touch qq.c qq.h
=====
pax$ make -f qq.mk
gcc -c -o qq.o qq.c
gcc -o qq qq.o
=====
pax$ make -f qq.mk
make: `qq' is up to date.
11
paxdiablo