I have 3 files: Source.cpp 2ndfile.cpp 2ndfile.hpp
And I'm trying to compile them with mingw32-make
makefile that doesn't work:
all: launch.exe
launch.exe: %.o
g++ -o $# $^
%.o: %.cpp
g++ -c $< -std=gnu++11
makefile that works:
all: launch.exe
launch.exe: source.o 2ndfile.o
g++ -o $# $^
source.o: source.cpp
g++ -c source.cpp -std=gnu++11
2ndfile.o: 2ndfile.cpp
g++ -c 2ndfile.cpp -std=gnu++11
My question is: why the first one doesn't work? What's my problem with '%' patterns?
The error I get: mingw32-make: *** No rule to make target '%.o', needed by 'launch.exe'. Stop.
My question is: why the first one doesn't work? What's my problem with '%' patterns?
A pattern rule matches targets to prerequisites via a common element in their names, represented by the % wildcard. You present your own example in the form of this rule:
%.o: %.cpp
g++ -c $< -std=gnu++11
On the other hand, this rule ...
launch.exe: %.o
g++ -o $# $^
... is not a pattern rule, because the target name does not contain a %. There, you seem to be trying to use % in an entirely different sense, analogous to * in a glob pattern. It does not serve that purpose, even in pattern rules. That would give pattern rules a very different (and much less useful) meaning. Instead, in your non-pattern rule, the % is treated as an ordinary character.
There are many ways to write makefiles, but a good, simple model to start from for exploring pattern rules would be a combination of your first and second examples:
all: launch.exe
launch.exe: source.o 2ndfile.o
g++ -o $# $^
%.o: %.cpp
g++ -c $< -std=gnu++11
Substitute % with *.
all: launch.exe
launch.exe: *.o
g++ -o $# $^
*.o: *.cpp
g++ -c $^ -std=gnu++11
EDIT: there's an answer below why this is a bad idea. Here's what works:
all: launch.exe
launch.exe: Source.o 2ndfile.o
g++ -o $# $^
%.o: %.cpp
g++ -c $^ -std=gnu++11
Related
I have Makefile. This runs on FreeBSD with gmake and make. In BSD Make command not output log same with gmake.
$ gmake
compile main.cpp
linking myout
$ make
c++ -O2 -pipe -c main.cpp -o main.o
linking myout
$ cat Makefile
TARGET = myout
default: $(TARGET)
SRCS = main.cpp
OBJS = $(SRCS:%.cpp=%.o)
default: $(BIN)
%.o: %.cpp
#echo compile $<
#$(CXX) -c $< -o $#
$(TARGET): $(OBJS)
#echo linking $#
#$(CXX) $(OBJS) -o $#
clean:
#rm -f $(OBJS) $(TARGET)
According to the FreeBSD make documentation, it doesn't support pattern rules. So your rule here:
%.o: %.cpp
#echo compile $<
#$(CXX) -c $< -o $#
in FreeBSD make is just an explicit rule telling make how to build the literal file %.o from the literal file %.cpp. Since you don't try to build a file named %.o (you're trying to build main.o), this rule is ignored / never used.
It looks like if you want something that will work the same way between both versions of make you'll have to restrict yourself to the POSIX standard suffix rules format, like this:
.SUFFIXES: .cpp .o
.cpp.o:
#echo compile $<
#$(CXX) -c $< -o $#
The default build utilities are different. FreeBSD uses a different implementation of make than GNU/Linux. The respective man pages outline differences.
https://forums.freebsd.org/threads/difference-gmake-gnu-and-freebsd-make.28784/
I'm trying to understand deeply how makefiles work.
For example, I've the following one:
CC = gcc
CFLAGS = -I.
DEPS = int_array.h
OBJS = int_array.o test_int_array.o
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
clean:
rm -rf *.o test_int_array *.dSYM
The part that I really don't understand fully is :
...
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
...
I know that the option -c basically indicates just to run the preprocessor, compiling and assembling steps (i.e. without producing executables, I guess).
-o means to write the output to the specified file. Which file in this case?
I understood that $# (and $^ for right) is apparently referring to a "left" side, but which one? Is it referring, in the first case, to the left side of :, that is %.o?
What does $< mean?
Could you please explain step by step how the make tool would interpret those two statements?
I think I understood this part more or less:
...
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
...
which should mean produce an executable called "test_int_array" (which basically is indicated by these options -o $# from the $(OBJS) files on the right (stated using the option $^).
Is $(CFLAGS) needed in both cases? Does the order matter?
In the example:
test_int_array: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
$# is the filename of the target for this rule: test_int_array.
$^ is the names of all prerequisites.
This would be whatever is contained in OBJS, so: int_array.o test_int_array.o
In the example:
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$< is the name of the first prerequisite: %.c
$# is the filename of the target for this rule: %.o
$(CFLAGS) is not needed for linking, since it only includes the flag -I. Also the CFLAGS indicates that the flags are used for compiling only, hence C FLAGS.
In a Makefile, each rule follows this format:
resulting_file : source_files
steps to get resulting_file from source_files
What is called respectively lefthand and righthand in a rule is the resulting_file and the source_files.
%.ext : %.ext2
is a pattern rule. It allows your Makefile to automatically create any .ext file it needs if it can find a file at the same path with .ext2.
%.c : %.o
is a pattern rule to obtain your .o files (int_array.o test_int_array.o) from their equivalent .c files (int_array.c test_int_array.c)
This is invoked when you specify that $(OBJS) is needed to build the test_int_array file.
Pattern rules automatically use certain variables, such as $(CFLAGS) so you do not need to manually add it in that rule. You can find a full list of implicitly used variables in pattern rules here: https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC96
You can find out about $#, $< and $^ and similar here: https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC101
$#: the entire lefthand
$<: the first file in the righthand
$^: the entire righthand list of files, space separated.
I have this simple rule in my Makefile:
PP=g++ -std=c++0x
%.o: $.cpp
$(PP) $< -c -o $#
When I run make parse_utils.o, the command be executed should be:
g++ -std=c++0x parse_utils.cpp -c -o parse_utils.o
But in fact it's:
>make parse_utils.o
g++ -c -o parse_utils.o parse_utils.cpp
And I got a compile error because I used C++11 syntax.
Is this wildcard rule wrong?
Your target is wrong. Change
%.o: $.cpp
to
%.o: %.cpp
My Makefile looks like this:
BIN = bin
OBJECTS = object1.o \
object2.o \
object3.o
HDR = $(OBJECTS:%.o=%.h) header1.h header2.h
MAIN = main.c
CC = gcc
CFLAGS = -Wall -g -std=c99 -fstack-protector-all
LDFLAGS = -lpthread
$(BIN): $(OBJECTS) $(MAIN)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
%.o: %.c $(HDR)
$(CC) $(CFLAGS) -c $< -o $#
It seems that the %.o: %.c $(HDR) rule is not used. When invoking with option make -r it says that there's no rule to make target object.o. The build of each object file should depend on every header file. What am I missing?
Edit: I should mention that when doing echo $(HDR) than it looks like the variable contains the right values:
object1.h object2.h object3.h header1.h header2.h
In the declaration of HDR, try $(OBJECTS:.o=.h) instead. Or, better yet, use gcc -MM or the like to generate your dependencies instead.
A pattern rule can't have auxilliary dependencies like ${HDR}.
Use:
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
${OBJECTS}: ${HDR}
Ok, the given Makefile should work, I had a typo in one of the header file names.
It's a pitty, but make doesn't warn about that. It seems that when a pattern based rule is missing a prerequisite than it's just ignored. The built-in .o creation rule is used instead.
Jonathan Leffler's proposal of ${OBJECTS}: ${HDR} brought that up, because than there's an error regarding "no rule to make target misspelled.h" - I would have expected that from my rule too.
So I can just agree to fluffy, it's better to use auto-generated dependencies instead.
Please explain $# $^ $ in the makefile below
LIBS = -lkernel32 -luser32 -lgdi32 -lopengl32
CFLAGS = -Wall
# (This should be the actual list of C files)
SRC=$(wildcard '*.c')
test: $(SRC)
gcc -o $# $^ $(CFLAGS) $(LIBS)
This is what these two symbols mean:
$# is the target i.e. test
$^ is the list of pre-requisites for the rule (which in this case is the expanded wild card list as specified in SRC=$(wildcard '*.c'))
All such variables are explained in the Automatic variables page of the GNU make manual.
SRC=$(wildcard '*.c')
This just all your source file name ending with .c ie file1.c, file2.c file3.c etc.
in
test: $(SRC)
gcc -o $# $^ $(CFLAGS) $(LIBS)
$ is a way to define variables in Makefile
$# is your target, in your case it is "test".
$^ is the list of all the prerequisites of the rule, including the names of the directories in which they were found
$< is the list of all dependencies
ref: https://www.gnu.org/software/make/manual/make.html#Automatic-Variables