4

I'm reading a big Makefile, part of which I don't understand:

$(IREJECTION): $(IREJECTION:%$(MACH64).o=%.cpp)
        $(CPP) $(CPPDLIBOPTS) -c $(@:%$(MACH64).o=%.cpp) -o $@

In this script (note that I removed unnecessary variables to avoid verbosity), what does the following mean

  • $(IREJECTION:%$(MACH64).o=%.cpp) (on the first line)
  • $(@:%$(MACH64).o=%.cpp) ? (on the second line)

Also, what does this form A: B mean? As in :

 $(IREJECTION): $(IREJECTION:%$(MACH64).o=%.cpp)   #on the first line
 <---- A ---->  <------------ B --------------->   #first instance of A: B
                <--- A ----> <-------- B ------>   #second instance of A: B

As you see, there are two instances of the form A:B — the second one is inside B itself. I see similar thing here as well:

$(@:%$(MACH64).o=%.cpp)   #on the second line
 <A> <---------B------->

Please help me understand this.

6
  • these are substitituoin/rewrite rules: gnu.org/software/make/manual/make.html#Substitution-Refs. basically $(var:%.foo=%.bar) means replace .foo extensions of all elements of var with .bar Commented May 8, 2014 at 6:55
  • 1
    @Anycorn: I think you meant : replace .bar extensions of all elements of var with .foo? Commented May 8, 2014 at 7:01
  • I see why it would be confusion, but no, it is in that form Commented May 8, 2014 at 7:03
  • @Anycorn: So you mean, in %$(MACH64).o=%.cpp, .cpp files are being generated from .o files? Commented May 8, 2014 at 7:06
  • the dependencies are being generated from the target (.o) files. I'll write a detailed answer. Commented May 8, 2014 at 7:06

3 Answers 3

4

You got quite complex example I think. It has many things in it.

Rule / Recipe

A: B
    <command>
  • A - target
  • B - dependency
  • <command> - command to be executed to build A ("Recipe")

target: dependency is called a 'rule'. So all in all, above example is 'rule' with appropriate 'recipe'.

(to make A, which depends on B, one needs to execute <command>)

make compares modifications dates of B and A. If B is newer, then it executes <command>


Variables

$(IREJECTION) is make's variable (it should be defined somewhere before in the file, like IREJECTION:=somefile.o)

During make execution $(IREJECTION) is replaced to actual value of the variable.



Variable substitution

From link below:

$(var:a=b) <..> take the value of the variable var, replace every 'a' at the end of a word with 'b' in that value, and substitute the resulting string.

And:

For example:

 foo := a.o b.o c.o
 bar := $(foo:%.o=%.c)

sets bar to a.c b.c c.c.

In your case $(IREJECTION:%$(MACH64).o=%.cpp), it takes variable named IREJECTION, tries to find $(MACH64).o (which also references variable MACH64) at the end of the word and replace it with .cpp.



Automatic variable

$@ is called automatic variable. It is reference to the 'target'.



Futher reading

http://www.gnu.org/software/make/manual/make.html

Sign up to request clarification or add additional context in comments.

1 Comment

Actually, the target/dependency part is the Rule, and the shell commands are the Recipe. A target can appear in more than one Rule, but at most one of those Rules can have a Recipe.
2

A: B meant that you add a make target A that depends on B. That means when B was changed, it has to be run before A is done. You can use the target A by calling make A.

Comments

1

I'll go tep by step:

lets say you have some object file irejection.mach64.o and the source file irejection.cpp

to generate object from source you typically write a rule smth like

irejection.mach64.o : irejection.cpp # means target : dependencies
    $(CC) irejection.cpp -o $@ # $@ is a special variable - the target (output)

Now lets say $(MACH64) is .mach64 and $(IREJECTION) is irejection$(MACH64).o, ie irejection.mach64.o

$(IREJECTION:%$(MACH64).o=%.cpp) will expand to irejection.cpp

$(@:%$(MACH64).o=%.cpp) will expand to the same, since $@ is $(IREJECTION)

In essence, given object file target with a architecture extensions, rewrite the file name to its source file counterpart.

Seems unncessearily convoluted to me tho. Cleaner way would be smth like:

%$(MACH64).o : %.cpp
    $(CC) -c $@ $<

% are "wildcards", $< is the first dependency, $@ is the output

see: http://www.gnu.org/software/make/manual/make.html#Automatic-Variables

http://www.gnu.org/software/make/manual/make.html#Pattern-Rules

3 Comments

Now I understand the replace thingy. It is in reverse direction which is a bit weird, because after replacement, the cpp file generated might not be the actual file (on disk) to be compiled. Anyway, in order for this to work, the object files should have exactly same prefix as the source files.
@Nawaz replace thingy is more of transform foo to bar rather than bar is foo`. more generally some common root needs to exist for pattern rules to work
@Nawaz btw, when writing rule commands, always always always use TAB or you'll get strange errors.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.