This question already has answers here:
What do the makefile symbols $# and $< mean?
(6 answers)
Closed 7 years ago.
Here's my sample makefile content:
CC=g++
CFLAGS=-c -Wall
...
$(CC) $(CFLAGS) $< -o $#
What does the $< mean here?
Read the documentation of GNU make. It is explained in the automatic variable section.
$<
The name of the first prerequisite. If the target got its recipe from an implicit rule, this will be the first prerequisite added by the implicit rule
Related
This question already has answers here:
In gnu make, can the prerequisites in a static pattern rule have different suffixes
(3 answers)
Closed 4 years ago.
Suppose I have three source files: file3.c, file2.c, file3.s which are all not of the same extension. I want to compile it into object files: file1.o, file2.o, file3.o which are of the same pattern.
OBJ = file1.o file2.o file3.o
all: $(OBJ)
#Here I am in the stuck
$(OBJ) : %.o : %.c #or %.s
$(CC) $(CFLAGS) -c $< -o $#
How to do this using pattern rules in GNU make?
The recipe for generating .o files can be made common for both .c and .s files this way:
OBJ = file1.o file2.o file3.o
.PHONY: all
all: $(OBJ)
.SECONDEXPANSION:
%.o: $$(wildcard $$*.c) $$(wildcard $$*.s)
$(CC) $(CFLAGS) -c $< -o $#
The prerequisite, which may end with .c or .s, is determined by secondary expanding the stem (i.e.: $*) and the wildcard built-in function for the filenames resulting from concatenating the stem with the corresponding "extensions" .c and .s.
The "or" is implemented by taking advantage of the fact that the wildcard built-in function is expanded to nothing (as opposed to be expanded to the provided pattern, like the Bash shell does) if the pattern is not matched (i.e.: if there is no filename that matched the pattern provided to wildcard).
This question already has answers here:
Create rule in makefile for just a set of files
(2 answers)
Closed 5 years ago.
I'm working on a project using makefile. Some of the make rules have the following format:
a.o b.o c.o : %.o : %.c
gcc -c $< -o $#
What's the meaning of such a rule? I'm unable to find explanation in the official manual, but I guess it's used for applying pattern-matching on only the *.o files listed as targets. Is that correct?
Quoting from the GNU Make,
Static Pattern Rules.
Static pattern rules are rules which specify multiple targets and
construct the prerequisite names for each target based on the target
name. They are more general than ordinary rules with multiple targets
because the targets do not have to have identical prerequisites. Their
prerequisites must be analogous, but not necessarily identical.
The syntax for static pattern rules:
targets : target-pattern: prereq-patterns …
recipe
…
Pattern rule is mentioned as % in the target. It matches any target ends with .o here a.o, b.o and c.o.
Here ‘$<’ is the automatic variable that holds the name of the prerequisite and ‘$#’ is the automatic variable that holds the name of the target.
a.o b.o c.o : %.o : %.c
gcc -c $< -o $#
This question already has answers here:
What do the makefile symbols $# and $< mean?
(6 answers)
Closed 6 years ago.
In some .mak files I see lines like:
$(CC) $[# $(CFLAGS) $(OFLAGS) $(DFLAGS)
I know that the $ sign means the value of the variable... But what is $[# (where there is no variable)?
Other examples: $[* , $^#
And $# $< in this answer, in the lines:
$(ODIR)/%.o: $(SDIR)/%.cpp
$(CC) -c $(INC) -o $# $< $(CFLAGS)
Now I know that the last two lines mean to create the .o files in ODIR directory and the .c files in SDIR directory. But what's the essential meaning of $# $<?
I couldn't find anything except these apache-related results as examples, with no explanation.
These are automatic variables as described here : GNU make : Automatic variables
Also see this thread : What do the makefile symbols $# and $< mean?
I need a file to have a dedicated rule for use special flags.
Now I use
$(OBJDIR)/%.$(OE): special_file.c
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(CFLAGS_SPECIAL) $(DEFINES) $(INCLUDE) $< -o $#
$(OBJDIR)/%.$(OE): %.c $(OBJDIR)
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDE) $< -o $#
But isn't working for special_file.c. It seems the path is not known, but when I comment my special rule and let make all files, file is compiling fine.
How to divert make to a rule just for one file?
Thanks very much in advance,
You should use Target-specific Variable Values:
$(OBJDIR)/special_file.$(OE): CFLAGS += --specific_flags
$(OBJDIR)/special_file.$(OE): special_file.c
$(OBJDIR)/%.$(OE): %.c $(OBJDIR)
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDE) $< -o $#
If you want to do it this way, you'll have to write it as a static rule:
$(OBJDIR)/special_file.$(OE): special_file.c
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(CFLAGS_SPECIAL) $(DEFINES) $(INCLUDE) $< -o $#
However, much simpler and more flexible is to use recursive variable naming. Do something like this:
special_file_FLAGS = $(CFLAGS_SPECIAL)
$(OBJDIR)/%.$(OE): %.c
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $($*_FLAGS) $(DEFINES) $(INCLUDE) $< -o $#
The automatic variable $* expands to the stem (the part that matches %). Now when you build anything other than special_file.c, say other_file.c, make will expand $(other_file_FLAGS) which is empty. When you build special_file.c, make will expand $(special_file_FLAGS).
BTW, you should (almost) never list a directory as a prerequisite of a target. Search for other answers to find out why not and the right way to ensure the target directory is created.
ETA:
Target-specific variables are definitely a cool feature. I tend to not use them, though. Why? Because I prefer to separate my data from my rules.
If you use target-specific variables, you are mixing together the rule syntax (the target) with the data syntax (the variable assignment). Using the recursive variable name method, I keep the rule syntax and the data assignment separate. What if I decide I need to change my pattern rule so that the target name changes? With target-specific variables I have to go through all my files and change the target names. With recursive variable naming, I just change the pattern rule and it Just Works.
In my build environments I typically have makefiles containing only data (variable assignments), plus an include of a common makefile that declares all my rules. Avoiding the need to leak target formatting syntax all over my general data-driven makefiles, escaping from my uber-magical common rule definitions, keeps me from doing much with target-specific variables.
This question already has answers here:
What do $< and $# represent in a Makefile?
(2 answers)
Closed 7 years ago.
For example in
$(CC) $(CFLAGS) -c -o $# $<
what do they mean?
$# The file name of the target.
$< The name of the first dependency.
For more details: Makefile symbol reference
$# is the name of the target being built - the program or object file being created.
$< is the name of the file that caused it to be rebuilt is the name of the file 'whose existence allowed the inference rule to be chose for the target'.
In the example, you might have:
program.o: program.c
${CC} ${CFLAGS} -c -o $# $<
In this case, $# is 'program.o' and $< is 'program.c'. (The rule must be generating an object file because of the '-c' option.)
Beware '$<'; if there was a header that was more recent than the program, '$<' would match that instead - and then the compile line wouldn't work. As shown, it is safe enough, though.
Beta comments about '$<'...
The POSIX definition of 'make' says:
$<
In an inference rule, the $< macro shall evaluate to the filename whose existence allowed the inference rule to be chosen for the target. In the .DEFAULT rule, the $< macro shall evaluate to the current target name. The meaning of the $< macro shall be otherwise unspecified.
For example, in the .c.a inference rule, $< represents the prerequisite .c file.
So, in the example I gave, '$<' is technically 'unspecified'. And, in the correct context,
which would be:
.c.o:
${CC} ${CFLAGS} -c -o $# $<
Then '$<' is unconditionally 'progname.c' when 'progname.o' is being built.
Some versions of 'make' used to do weird things with it; both GNU Make (3.81) and Solaris 10 make seem to behave sanely. I'm caught in a time-warp, I suspect. I used the following makefile:
all: x.o
x.o: x.c
${CC} ${CFLAGS} -c -o $# $<
x.o: x.h
I used 'echo "int main(){return 0;}" > x.c' and 'echo > x.h' to create the code. It didn't matter which file was touched out of 'x.c' and 'x.h'; either way, the compilation was 'correct'. I have an old make-derivative which was, circa 1992, compatible with Sun MAKE of the time in most respects, that mishandles it.
The 7th Edition UNIX Programmer's Manual says:
The rule to create a file with suffix s2 that depends on a similarly named file with suffix s1 is specified
as an entry for the ‘target’ s1s2. In such an entry, the special macro $* stands for the target name with
suffix deleted, $# for the full target name, $< for the complete list of prerequisites, and $? for the list
of prerequisites that are out of date.
It doesn't say anything about what it means outside that context. I note that 7th Edition 'make' would list both 'x.c' and 'x.h' for '$<' - but POSIX says that is incorrect.
The SUN "make User's Guide" (Revision A of 16 March 1987) says:
$< The name of the dependency file, as if selected by make for use with an implicit rule.
That more or less conforms to what you now see.
Oh well, such is life; things change around you. Sometimes you spot it happening; sometimes you don't.