1

I'm trying to understand why some Makefiles have prerequisites with %.txt and others have *.txt.

I've created this folder layout.

$ tree .
.
├── hi1.txt
├── hi2.txt
├── hi3.txt
└── Makefile

First, I tried this.

foo.txt: *.txt
    echo $^

And it does what I expect.

$ make
echo hi1.txt hi2.txt hi3.txt
hi1.txt hi2.txt hi3.txt

But, then I've seen some Makefiles use %.txt was a wildcard. So I tried that next.

foo.txt: %.txt
    echo $^

However, this results in an error.

$ make
make: *** No rule to make target '%.txt', needed by 'foo.txt'.  Stop.

Can someone explain why this is happening?

GNU Make 4.3

  • Your understanding is correct, %.go is the prerequisite. But if it doesn't exist, make will look for a rule to make it. I have no idea why it doesn't understand %. – Oskar Skog Apr 11 at 6:06
  • 1
    The percent sing is a SunPro Make feature from January 1986. So called pattern matching rules only apply in case of default rules and that require a percent on the left hand side as well. – schily Apr 11 at 7:17
  • Ah, okay. What is %.png: %.svg doing in this example? learnxinyminutes.com/docs/make – 425nesp Apr 11 at 7:26
1

In make, the percent sign is used for pattern matching, and it requires one in the target as well as (at least) one in the prerequisites:

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

With this makefile, we specify that in order to build something whose file name ends with .o, you need to have a file that has the same prefix, but then ends with .c rather than .o

In order to be able to construct those rules, you obviously need to be able to refer to the target as well as the prerequisites; this is where the$@ and $< variables come in. $@ means 'the target of this rule', and $< means 'this rule's first listed prerequisite'. If you need to construct a command that uses all prerequisites (e.g., to link an executable), then you can use the variable $^:

%: %.o lib.o
        $(CC) $(LDFLAGS) -o $@ $^

If you combine the above two example makefile snippets in one makefile, and you have a file 'lib.c' with some common code that you want to use in a number of C programs in that same directory, then you can add any random .c file, say foo.c, and compile it into a program foo that also links in the code in lib.c, without requiring any changes to your makefile.

Note that it is also possible to have patterns with the same target, as long as the prerequisites are different; e.g., the following will work:

%.o: %.c
        $(CC).....
%.o: %.cpp
        $(CXX).....

that is, it will work as expected as long as you don't have any C++ source files in this directory that happen to have the same name (sans extension) as a C source file. If that does happen to be the case, the C++ version will be ignored and the C source will be compiled instead (because the C rule is listed first in the makefile)

For more info, see the relevant section in the GNU make manual.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.