Tell me about makefiles

  • Thread starter Tomás Ó hÉilidhe
  • Start date
T

Tomás Ó hÉilidhe

I already understand how program compilation works (i.e. the
preprocessor produces individual translation units which get compiled
separately, and then the linker links the object files together), but
I don't know anything about makefiles.

If I had the following program:

/* main.c */

extern void Func(void);

int main(void)
{
Func();
return 0;
}

/* func.c */

#include <stdio.h>

void Func(void) { puts("Hello World!"); }

/* End of code */

, then I would compile it as follows with gcc:

gcc a.c b.c -ansi -pedantic -s -O3 -D NDEBUG -o prog.exe

What would my makefile for this look like?
 
E

Eric Sosman

Tomás Ó hÉilidhe said:
I already understand how program compilation works (i.e. the
preprocessor produces individual translation units which get compiled
separately, and then the linker links the object files together), but
I don't know anything about makefiles.

If I had the following program:
[...]
What would my makefile for this look like?

It would look like something better discussed on
comp.unix.programmer than here.
 
R

Richard Heathfield

Tomás Ó hÉilidhe said:

gcc a.c b.c -ansi -pedantic -s -O3 -D NDEBUG -o prog.exe

What would my makefile for this look like?

I don't know, but mine would look like this:

CC=gcc
CFLAGS=-W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-ffloat-store -O2
DFLAGS=-g -pg
a: a.o b.o
$(CC) $(CFLAGS) $(DFLAGS) -o prog.exe a.o b.o
a.o: a.c
$(CC) $(CFLAGS) $(DFLAGS) -c -o a.o a.c
b.o: b.c
$(CC) $(CFLAGS) $(DFLAGS) -c -o b.o b.c

clean:
rm a.o
rm b.o
rm prog.exe

install:
cp prog.exe /usr/local/bin


Note that, in a "real" makefile, the indented lines start with a HARD TAB
(ASCII 9) character.
 
S

santosh

Tomás Ó hÉilidhe said:
I already understand how program compilation works (i.e. the
preprocessor produces individual translation units which get compiled
separately, and then the linker links the object files together), but
I don't know anything about makefiles.

If I had the following program:

/* main.c */

extern void Func(void);

This is not related to your question, but isn't the above declaration
unnecessary seeing as functions have external linkage unless specified
otherwise?
 
I

Ian Collins

santosh said:
This is not related to your question, but isn't the above declaration
unnecessary seeing as functions have external linkage unless specified
otherwise?

No, if you look again, he's defining the function in another compilation
unit.
 
H

Harald van Dijk

This is not related to your question, but isn't the above declaration
unnecessary seeing as functions have external linkage unless specified
otherwise?

The declaration is necessary. The extern keyword in the declaration is
unnecessary. (I'm sure that's what you meant.)

However, some coding styles do use the extern keyword to declare functions
that are defined in a different unit, in the same way that the keyword is
used to declare objects that are defined in a different unit. It's not
required, but it's perfectly valid C, and no less readable than its
shortened equivalent.
 
S

santosh

Harald said:
The declaration is necessary. The extern keyword in the declaration is
unnecessary. (I'm sure that's what you meant.)

Yes, sorry, that's what I meant. It's very late here.
However, some coding styles do use the extern keyword to declare
functions that are defined in a different unit, in the same way that
the keyword is used to declare objects that are defined in a different
unit. It's not required, but it's perfectly valid C, and no less
readable than its shortened equivalent.

I see. Thanks.
 
J

John Bode

I already understand how program compilation works (i.e. the
preprocessor produces individual translation units which get compiled
separately, and then the linker links the object files together), but
I don't know anything about makefiles.

If I had the following program:

/* main.c */

extern void Func(void);

int main(void)
{
Func();
return 0;

}

/* func.c */

#include <stdio.h>

void Func(void) { puts("Hello World!"); }

/* End of code */

, then I would compile it as follows with gcc:

gcc a.c b.c -ansi -pedantic -s -O3 -D NDEBUG -o prog.exe

What would my makefile for this look like?

The make utility and makefiles are not part of C, and are technically
off-topic for c.l.c.

The gnu make user guide is online at http://www.cs.utah.edu/dept/old/texinfo/make/make_toc.html.

As for what it would look like, that kind of depends on what you're
trying to accomplish. You can have one as simple as

prog.exe:
gcc a.c b.c -ansi -pedantic -s -O3 -DNDEBUG -o $@

although that's not terribly flexible, and will build both a.c and b.c
regardless of whether or not they're up to date with respect to the
target.

This is a little more sophisticated, and more typical (assumes gnu
make):

CC=gcc
CFLAGS=-ansi -pedantic -c # compilation flags
OFLAGS=-O3 # optimization flags
AFLAGS=-DNDEBUG # assert flags

SOURCE=a.c b.c
OBJECTS=${SOURCE:.c=.o}
TARGET=prog.exe

#
# Compile an individual .c file, creating an object (.o) file
#
%.o : %.c
${CC} -c ${CFLAGS} ${AFLAGS} ${OFLAGS} $<

#
# Link all the objects into the target
#
${TARGET} : ${OBJECTS}
${CC} -o $@ ${OBJECTS}

Remember that the command lines *must* start with a tab character,
otherwise you'll get a less-then-helpful error message.
 
A

Antoninus Twink

Tomás Ó hÉilidhe said:



I don't know, but mine would look like this:

CC=gcc
CFLAGS=-W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-ffloat-store -O2
DFLAGS=-g -pg
a: a.o b.o
$(CC) $(CFLAGS) $(DFLAGS) -o prog.exe a.o b.o
a.o: a.c
$(CC) $(CFLAGS) $(DFLAGS) -c -o a.o a.c
b.o: b.c
$(CC) $(CFLAGS) $(DFLAGS) -c -o b.o b.c

clean:
rm a.o
rm b.o
rm prog.exe

install:
cp prog.exe /usr/local/bin

Is this a joke? That's one of the most amateurish makefiles I've ever
seen.
 
R

Robbie Hatley

Tomás Ó hÉilidhe said:
I don't know anything about makefiles ...
... What would my makefile for this look like? ...

Off-topic here; ask this question in the following newsgroup:

gnu.utils.help

Also read the O'Reilly book "Managing Projects with Gnu Make"
(available at computer stores, bookstores, and amazon.com).

Also try these googles:

gnu make
makefile
 
I

Ian Collins

Robbie said:
Off-topic here; ask this question in the following newsgroup:

gnu.utils.help
Why do you assume the OP wants to use the GNU dialect of make?
 
A

Antoninus Twink

Is it now? I'm willing to have my mind illuminated. Do tell,
why is it "most amateruish"? Don't just make snarky comments,
explain yourself.

To take the most trivial points:
1) doesn't take advantage of built-in rules
2) highly non-extensible - should define, say, $(OBJECTS) instead of
listing all the object files in more than one place.
3) should rm -f so that "make clean" doesn't return a non-zero value
when called with no built files present
4) "make install" fails to set permissions sensibly (most likely 755
will be wanted for a program in /usr/local/bin) - and it would be nice
to have a $(PREFIX) variable instead of hard-coding the path
5) WTF is "DFLAGS"? A non-standard variable name, with no comment
explaining what it's for.
 
C

CBFalconer

Richard said:
Is it now? I'm willing to have my mind illuminated. Do tell,
why is it "most amateruish"? Don't just make snarky comments,
explain yourself.

You realize you are talking to a prime troll?

At any rate, it is a fine example. The only criticism I would make
is that the dependencies for a.o and b.o do not include a.h and
b.h.
 
R

Robbie Hatley

Ian said:
Why do you assume the OP wants to use the GNU dialect of make?

Why did you finally stop beating your wife after all these years?

In other words, "Mu.".

In still further words, it's best to avoid including (usually
false) statements as part of questions.

The GNU dialect of Make is close enough to the Unix dialect
that a good knowledge of one will be of great help in using
the other. (Yes, yes, there's differences. Deal with it.)

I'd send the person to the following group:

unix.utils.help

except for one very minor technical difficulty. (Namely, no
such group exists.)

I probably should have mentioned these, though:

comp.os.unix.misc
comp.unix.misc
comp.unix.programmer
 
R

Richard Tobin

Why do you assume the OP wants to use the GNU dialect of make?
[/QUOTE]
The GNU dialect of Make is close enough to the Unix dialect
that a good knowledge of one will be of great help in using
the other.

Just as well no-one in other newsgroups uses that kind of reasoning
to send people here!

-- Richard
 
R

Robbie Hatley

The GNU dialect of Make is close enough to the Unix dialect
that a good knowledge of one will be of great help in using
the other.

Just as well no-one in other newsgroups uses that kind of reasoning
to send people here![/QUOTE]

Sure they do. Notice that we don't have 3 different newsgroups for
original-K&R-C, C90, and C99. There's just "comp.lang.c".
Yes, there's differences; but we deal with them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top