it-swarm-id.com

Bagaimana cara membuat Makefile untuk mengkompilasi ulang hanya file yang diubah?

Saya telah berjuang sedikit untuk membuat kompilasi hanya file yang telah diedit. Namun saya tidak terlalu sukses dan semua file dikompilasi ulang. Adakah yang bisa menjelaskan mengapa?

File saya adalah:

main.c
a_functions.c

di mana main.c mencakup main.h dan a_functions.c include ah

Ini makefile saya:

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)

Mengubah makefile sesuai saran tampaknya memiliki masalah yang sama ::

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

Masalah khusus yang Anda bicarakan - Buat kembali program1 (Dengan menautkan kembali objek) bahkan ketika tidak ada yang berubah - ada dalam aturan ini:

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

Target aturan ini adalah program, dan Make berasumsi bahwa itu adalah file. Tetapi karena tidak ada file seperti itu, setiap kali Anda menjalankan Make, Make berpikir bahwa file ini perlu dibangun kembali, dan menjalankan aturan. Saya menyarankan ini:

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

Atau lebih baik, ini:

program1: a_functions.o main.o
    gcc $^ -o [email protected]

Atau lebih baik lagi ini:

$(EXEC_FILE): a_functions.o main.o
    $(CC) $^ -o [email protected]

(Dan jangan lupa untuk mengubah aturan all agar sesuai.)

Beberapa poin lain:

  1. Seperti @paxdiablo tunjukkan,

    a_functions.o: a_functions.c a.h
    main.o: main.c main.h
    
  2. Tidak masuk akal untuk menautkan objek-objek ini bersama-sama kecuali sesuatu dalam satu (mungkin main.o) Memanggil sesuatu di yang lain (mungkin a_functions.o), Jadi saya akan berharap untuk melihat ketergantungan seperti ini:

    main.o: a.h
    

    Jadi saya menduga Anda memiliki beberapa deklarasi yang salah tempat.

  3. Anda mendeklarasikan aturan objects, tetapi tidak pernah merujuknya. Jadi, Anda tidak pernah benar-benar menggunakannya; Jadikan menggunakan aturan default untuk %.o: %.c. Saya menyarankan ini:

    OBJECTS = a_functions.o main.o
    $(OBJECTS): %: %.c
        $(CC) $< $(CFLAGS) -o [email protected]
    

    (Dalam hal ini Anda dapat mengubah $(EXEC_FILE): a_functions.o main.o menjadi $(EXEC_FILE): $(OBJECTS).) Atau hanya ini:

    %.o: %.c
        $(CC) $< $(CFLAGS) -o [email protected]
    
75
Beta

Tidak yakin apakah ini menyebabkan masalah spesifik Anda tetapi dua baris:

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

pasti salah, karena umumnya tidak ada perintah untuk membuat kembali file C berdasarkan header yang disertakan.

File C tidak bergantung pada file header mereka, objek dibuat oleh file C itu.

Misalnya, sebuah main.c dari:

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

akan di makefile sebagai sesuatu seperti:

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

Perubahan:

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

untuk:

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

(berasumsi bahwa a_functions.c termasuk a.h dan main.c termasuk main.h) dan coba lagi.

Jika asumsi di atas salah, Anda harus memberi tahu kami file C apa yang menyertakan header apa sehingga kami dapat memberi tahu Anda aturan yang benar.


Jika Anda berpendapat bahwa makefile masih membangun segalanya bahkan setelah perubahan itu, Anda perlu melihat dua hal.

Yang pertama adalah output dari ls -l pada semua file yang relevan sehingga Anda dapat melihat tanggal dan waktu apa yang mereka miliki.

Yang kedua adalah output aktual dari make. Output dari make -d akan sangat membantu karena itu menunjukkan file dan tanggal apa yang digunakan make untuk mencari tahu apa yang harus dilakukan.


Dalam hal penyelidikan, make tampaknya berfungsi dengan baik sesuai transkrip berikut:

=====
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