CowZow
CowZow

Reputation: 1414

How do you handle headers that include headers with a makefile in C?

Suppose you have a file called file.c.

Here's what I have for the makefile:

file.x: file.o
        -gcc file.o -o file.x

file.o: file.c header1.h header2.h
        -gcc file.c header1.h header2.h

I am confused about how to handle when header2.h includes header1.h.

Is this line redundant? Or is it good style to show dependencies?

file.c header1.h header2.h

Update: I apologize for the confusion. I have reverted the edits I made to the question. The current makefile is the one I posted in the original question that Jonathan's answer refers to.

Upvotes: 1

Views: 320

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753705

The original version of the question contained the following lines in the makefile:

file.o: file.c header1.h header2.h
        -gcc file.c header1.h header2.h

My answer addresses the original version of the question, before it got fixed up.

Note that the compilation line generates the executable a.out unless the compiler objects to compiling the header files. You should have -c in the command line.


A couple of issues:

  1. In a makefile, when does the object file need rebuilding?

    Answer: when the source file or one of the headers it includes changes.

    Subsidiary Q: what does this dependency line mean:

    file.o: file.c header1.h header2.h
    

    Subsidiary A: file.o needs rebuilding if the source file or one of the headers it includes changes.

  2. If you stipulate: header1.h depends on header2.h, what's going to happen to header1.h when you change header2.h?

    Answer: nothing. You don't compile header1.h per se. It is the object files that change.

  3. If you stipulate the file.c depends on header1.h or header2.h or both, what's going to happen to file.c when you change one of the headers?

    Answer: nothing again. You don't change file.c; you recompile the object file again.

So, the dependency portion of your object file rule is fine (within limitations related to automatic dependency generation). There is no point in a rule that says the source file depends on the headers; in fact, the source file does not directly depend on the headers. (It indirectly depends on them in that if the header contents change so that what was valid code is no longer valid code, nothing will compile until the source is fixed. But that is slightly off the subject.)

Hard-coding the dependencies is problematic; they change. On the other hand, generating the dependencies automatically is fiddly. There are GCC options (like -M, -MM, -MF, -MG, -MP, -MQ, -MD, -MMD, -MT, -H — such an abundance of options tells you there are issues here!) to assist, and GNU make has 'conditional inclusion' to include dependency files if they exist and not witter if they don't. These can help. Look up makedepend, mkdep and related commands for other ways of automating that.


Ignoring automatic dependency generation, your makefile might read:

FILES.o = file.o

file.x: ${FILES.o}
        ${CC} -o $@ ${CFLAGS} ${FILES.o} 

file.o: file.c header1.h header2.h

make will provide a command to compile file.c into file.o.

When your program grows to use other.o too, you simply add other.o to the macro FILES.o (that's why it is a plural name). You might add dependency information too. If you need libraries too, then you can add options to the link line:

LDFLAGS = -L/usr/local/lib
LDLIBS  = -llocal

FILES.o = file.o other1.o other2.o

file.x: ${FILES.o}
        ${CC} -o $@ ${CFLAGS} ${FILES.o} ${LDFLAGS} ${LDLIBS}

file.o: file.c header1.h header2.h

Note that the libraries should go after the object files. Listing libraries before object files is apt to lead to link-time failures on other platforms, to the irritation of those trying to build your software.

Upvotes: 2

Related Questions