tags:

views:

282

answers:

5

Can someone help me figure out the following make file?

BINS=file1 file2 file3

all: $(BINS)

clean: 
        rm -f $(BINS) *~ 

$*: [email protected]
        gcc -g -o $@ $?

Here are my questions:

  1. What is the -g option of gcc?
  2. What are $* and $@
  3. How does it know to execute the last target?

Thanks!

+1  A: 

The GNU Make Manual

GCC online documentation

nicerobot
RTFM is not really a helpful answer.
Jay Conrod
Teach a person to fish ...
nicerobot
Technical documentation like this can be pretty opaque. Learning the basics of make through the documentation is about the hardest way I can think of.
Jay Conrod
The benefit Chris would gain from reading the manuals to learn the answer to his few basic questions far outweighs any reason for duplicating the content from those manuals here in SO
nicerobot
This is why I hate coming to this site...It's hard to Google for special characters like $* or $@. And I don't have a lot of time to spend reading a manual.
ChrisDiRulli
@chrisdirulli but i gave you the resources and once on those pages, it's easy to search for those characters.
nicerobot
+5  A: 

From the gcc and make documentation:

  1. "-g Produce debugging information in the operating system's native format".

  2. a. "$* The stem with which an implicit rule matches (see How Patterns Match). If the target is dir/a.foo.b and the target pattern is a.%.b then the stem is dir/foo. The stem is useful for constructing names of related files. In a static pattern rule, the stem is part of the file name that matched the '%' in the target pattern."

    b. "$@ The file name of the target of the rule. If the target is an archive member, then '$@' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), '$@' is the name of whichever target caused the rule's commands to be run."

    c. "$? The names of all the prerequisites that are newer than the target, with spaces between them." (Not asked, but worth adding.)

  3. "'all' Compile the entire program. This should be the default target."

This example makefile is a bit limited, since it seems to only build C programs. The GNU make has several more extensive examples that are useful for learning how to write makefiles.

Jon Ericson
+2  A: 

1.) What is the -g option of gcc?

Generate debugging info

2.) What are $* and $@

$* is the stem of the rule. When you make rule like

%.ext: %.otherext
    ext2otherext --input $? --output $@ --logfile $*.log

, and the rule tries to make file.ext from file.otherext, then to log goes to file.log

$@ is the target filename (file.ext in the case above).

3.) How does it know to execute the last target?

This is a mystery.

$* is used for intermediary files: like, when you try to make an %.so out of %.c, you'll need an intermediary %.o which is neither target nor a source. You put:

%.so: %.c
    gcc -fPIC -g -c -o $*.o $?
    ld -shared -o $@ $*.o

In other words, in a %.extension rule, $* is everything but the .extension.

As a target, $* makes no sense.

Are you sure this rule is actually executed somewhere? When I try to reproduce it using your Makefile, it applies default rules (cc -o) instead of gcc -g -o

Rule you need seems to be:

%: %.c
    gcc -g -o $@ $?
Quassnoi
I'm curious to know if the makefile works, but I'm too lazy to actually try it. Did you?
Jon Ericson
Yes, I did, it doesn't work :) It makes actually, but uses default rules instead of gcc -g.
Quassnoi
A: 

Q1 and Q2 have been answered extensively already, so a brief explanation for Q3 only:

Make always executes the first target unless you specified a different one. This is also called the default target. Usually the default target is called "all".

bluebrother
+1  A: 

The first line does just what you'd expect by looking at it — it creates a list of names and assigns it to BIN. Next, a make target called all is defined, which is dependent on the targets listed in $BIN (all can't be built until each target in $BIN is built). all is a special build target; if you just run make rather than, say, make clean, the all target is automatically built. There are no actual commands associated with all — it simply ensures that all its dependencies are built. The last fairly straightforward command defines a build target called clean, which deletes each file listed in $BIN (note that $BIN is being used both as a list of build targets and a list of files in this makefile) and all backups.

Next, we get to a line which is, basically, magic. $* is a special build target which means "anything not specifically defined". When make tries to build all, it finds the target and starts work on its dependencies. But when it tries to build file1, there is no explicit target defined. Instead, it uses $* to build file1. Similarly, $@ gets replaced with the build target's name, and $? with its dependencies (sort of; that one you're better off checking the manual for). When make goes to build file1, then, the $* rule causes it to behave as if the following rule were defined:

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

Finally, the -g option simply enables debugging information to be compiled in.

Ben Blank
$* is not a special build target, it's not a target at all.
Quassnoi