Search code examples
cmakefile

C Makefile - How to avoid redundant mentions of file names


For an assignment in one of my classes we need to create a makefile for our C program that's more complex than just compile: gcc whatever. I believe we're expected to do something like this:

outputname: file1.o file2.o file3.o file4.o
    gcc -o outputname file1.o file2.o file3.o file4.o

clean:
    rm -f outputname file1.o file2.o file3.o file4.o

file1.o: file1.c
    gcc -c file1.c

file2.o: file2.c
    gcc -c file2.c

file3.o: file3.c
    gcc -c file3.c

file4.o: file4.c
    gcc -c file4.c

But having to list the same file names multiple times irritates me. If I need to update a name I need to ensure I replace each instance of it in the file. Or if I add a file I have to add new lines that are practically identical to four others already in the file. I've managed to get really close to the functionality of the above makefile:

files := file1.o file2.o file3.o file4.o
output := outputname

$(output): $(files)
    gcc -o $(output) $(files)

clean: 
    rm -f $(output) $(files)

$(files): $(files:.o=.c)
    gcc -c $(@:.o=.c)

The only difference I can tell is that unlike the first example, this will recompile all of the c files if any one of them has been updated, removing one of the advantages of makefiles. Is there something else I can do that will remove the redundancy but keep all the functionality?


Solution

  • Most make utilities already have built-in implicit dependencies for things like generating a .o file from a .c file. So since you're not specifying anything special in your compile steps, you condense your file down to something like:

    OBJS = file1.o file2.o file3.o file4.o
    
    outputname: $(OBJS)
        gcc -o outputname $(OBJS)
    

    ...and it can handle the rest on its own (oh--except that you'll probably still want your clean: rule).