73

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

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

main.c
a_functions.c

ここで、main.cにはmain.hが含まれ 、a_functions.cにはahが含まれます

これが私のmakefileです:

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)

提案に従ってmakefileを変更すると、同じ問題が発生するようです::

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
4

3 に答える 3

99

あなたが話している特定の問題-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): %.o: %.c
        $(CC) $< $(CFLAGS) -o $@
    

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

    %.o: %.c
        $(CC) $< $(CFLAGS) -o $@
    
于 2011-10-19T02:33:53.933 に答える
13

これが特定の問題を引き起こしているかどうかはわかりませんが、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.c(を含むa.hmain.c含むと仮定してmain.h)そして再試行します。

上記の仮定が間違っている場合は、正しいルールを教えてくれるように、どのCファイルにどのヘッダーが含まれているかを教えてください。


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

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

2つ目は、からの実際の出力ですmake。の出力は、何をすべきかを理解するためにどのファイルと日付が使用されているかを示すmake -dため、特に役立ちます。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.
于 2011-10-19T00:53:47.143 に答える
1

これは事後非常に遅く、実際にはpaxdiabloの優れた回答に基づいていますが、実験中に、何か賢いことをしているのでない限り、.oファイルごとに個別のターゲットは必要ないことがわかりました。

だから私のmakefileの場合:

all: program

program: a_functions.o main.o
    gcc a_functions.o main.o -o program

clean: 
    rm -f *.o
    rm -f program

make 4.1では、.oファイルが自動的にコンパイルされます。.oファイルの名前がソースファイルと同じである場合は、何もする必要はありません。したがって、a_functions.c、a_functions.h、main.h、およびmain.cを自動的に探します。予想されるソースコード名がない場合は、次のようなエラーが発生します。

make: *** No rule to make target 'a_functions.o', needed by 'program'.  Stop.

また、「クリーンな」ターゲットを追加しました。「クリーン」は、ソフトウェアをソースコードとしてリリースする必要がある場合、またはコンパイルされたすべてのオブジェクトファイルやバイナリを削除したい場合に便利です。

そして、これはあなたがする必要があるすべてです。

これを「Makefile」に保存して実行します。

$ make

バイナリを構築します。と

$ make clean 

コード内のコンパイル済みオブジェクトとバイナリをクリーンアップします。

于 2019-11-03T02:29:10.367 に答える