Makefile, Compiling and Linking

32,505

You should revise the structure a little:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o

all: sysstatd

sysstatd: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd

server.o: server.c
    $(CC) $(CFLAGS) -c server.c

rio.o: rio.c rio.h
    $(CC) $(CFLAGS) -c rio.c

clean:
    rm -f *~ *.o sysstatd

The difference is that the phoney rule all depends on sysstatd being up to date, and sysstatd is up to date when it is up to date w.r.t the object files.

Now it is just rather verbose, writing the compilation actions explicitly. It would be sufficient to use:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o

all: sysstatd

sysstatd: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd

server.o: server.c
rio.o: rio.c rio.h

clean:
    rm -f *~ *.o sysstatd

You could also debate: does server.c not use rio.h? If it does, the dependency should be listed. If not, why does rio.h exist? make will assume that server.o depends on server.c, so you don't have to specify that (but it won't make assumptions about the headers). You could also use a macro to prevent repetition of the program name:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd

all: $(PROG)

$(PROG): $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $@

server.o: rio.h
rio.o: rio.h

clean:
    rm -f *~ *.o $(PROG) core a.out

If you needed other libraries, then you might use:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd
LOCALLIBDIR = /usr/local/lib
LDFLAGS = -L$(LOCALLIBDIR)
LDLIBS  = -lone -ltwo

all: $(PROG)

$(PROG): $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS) $(LDLIBS)

server.o: rio.h
rio.o: rio.h

clean:
    rm -f *~ *.o $(PROG) core a.out
Share:
32,505
darksky
Author by

darksky

C, C++, Linux, x86, Python Low latency systems Also: iOS (Objective-C, Cocoa Touch), Ruby, Ruby on Rails, Django, Flask, JavaScript, Java, Bash.

Updated on August 07, 2022

Comments

  • darksky
    darksky almost 2 years

    I have a question regarding compiling and linking in Makefile (and perhaps in general).

    I have a server.c file which consists of the main program which has a main() function. server.c includes rio.c. I have a module called rio which consists of rio.c and rio.h. It has no main() function.

    I have two questions, how to actually write the Makefile, and the best practice for doing such a thing.

    Q1: How to write the Makefile

    I have the following Makefile:

    CC = gcc
    CFLAGS = -Wall -Werror -Wmissing-prototypes
    OBJS = server.o rio.o
    
    all: $(OBJS)
        $(CC) $(CFLAGS) $(OBJS) -o sysstatd
    
    server.o: server.c
        $(CC) $(CFLAGS) -c server.c
    
    rio.o: rio.c rio.h
        $(CC) $(CFLAGS) -c rio.c
    
    clean:
        rm -f *~ *.o sysstatd
    

    I am having linking issues with this. It says that I have multiple definitions of all the functions used in C. I'm not sure how this is possible since server.c is compiled with the -c flag so nothing is actually linked. It should know that some functions exist but not actually link them until the all rule compiles both object files together and produces a single object file which has everything linked.

    What is the issue here?

    Q2: Best practice Since I have a module and then another file which contains the main program, should I compile the main program, server.c, as a separate module and then compile both together in all, or compile server.c in all and add the rio.o module there? Note that this still produces the same linking problem I have above so I'm pretty sure I have my issue lies somewhere else.

  • Engineer
    Engineer almost 9 years
    Hugely beneficial seeing it improved step by step like this. Thank you.