Search code examples
cmakefileautomationrefactoring

C, Refactoring Makefile


My makefile works however if I erase debutliste.o lecturefichier.o statistiques.o tri.o from the target compile, it still works I imagine bc they are done in the other .o targets.

Make:    link

compile: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o

listechainee.o: listechainee.c listechainee.h debutliste.o 
    gcc -g -Wall -Wextra -std=c11 -c listechainee.c
debutliste.o: debutliste.c debutliste.h lecturefichier.o
    gcc -g -Wall -Wextra -std=c11 -c debutliste.c
lecturefichier.o: lecturefichier.c lecturefichier.h statistiques.o
    gcc -g -Wall -Wextra -std=c11 -c lecturefichier.c
statistiques.o: statistiques.c statistiques.h tri.o
    gcc -g -Wall -Wextra -std=c11 -c statistiques.c
tri.o: tri.c  
    gcc -g -Wall -Wextra -std=c11 -c tri.c

clean:
    rm -rf *.o 

link: compile
    gcc *.o -o tri

If I understand correctly I should delete the debutliste.o lecturefichier.o statistiques.o tri.o that are inside the .o targets bc they will be executed as dependencies from the target compile and it should look like this?

Make:    link

compile: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o

listechainee.o: listechainee.c listechainee.h 
    gcc -g -Wall -Wextra -std=c11 -c listechainee.c
debutliste.o: debutliste.c debutliste.h 
    gcc -g -Wall -Wextra -std=c11 -c debutliste.c
lecturefichier.o: lecturefichier.c lecturefichier.h 
    gcc -g -Wall -Wextra -std=c11 -c lecturefichier.c
statistiques.o: statistiques.c statistiques.h 
    gcc -g -Wall -Wextra -std=c11 -c statistiques.c
tri.o: tri.c  
    gcc -g -Wall -Wextra -std=c11 -c tri.c

clean:
    rm -rf *.o 

link: compile
    gcc *.o -o tri


Solution

  • Yes. If you are using GNU Make, you can simplify your makefile (per above) by relying on the fact it already has a catalog of rules. Those rules tells make how to compile c files into object files and how to link object files into a binary. The recursive flag -r for rm makes me nervous so I removed it. You probably don't need a separate link step so I use the standard all target instead of compile:

    .PHONY: all clean
    CFLAGS:=-g -Wall -Wextra -std=c11
    
    all: tri
    
    clean:
        rm -f *.o ./tri
    
    tri: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
    
    debutliste.o: debutliste.c debutliste.h
    
    lecturefichier.o: lecturefichier.c lecturefichier.h
    
    listechainee.o: listechainee.c listechainee.h
    
    statistiques.o: statistiques.c statistiques.h
    

    If you want to be fancy you can use a pattern rule %.o: %.c %h that says a given file .o depends on it's corresponding .c and .h files which makes the makefile quite compact:

    .PHONY: all clean
    CFLAGS:=-g -Wall -Wextra -std=c11
    
    all: tri
    
    clean:
        rm -f *.o ./tri
    
    tri: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
    
    %.o: %.c %h
         $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
    

    The list of object files is probably just all your c files with a different name. You can write that as:

    OBJECTS:=$(patsubst %.c,%.o,$(wildcard *.c))
    
    tri: $(OBJECTS)
    

    However, I don't usually do that step in my projects as the build now become sensitive to temporary .c files that I often create while working.