Order of the lines on makefile - makefile

I have main.cpp (including main function) and func1.cpp, and I want to link these files with a makefile. Classic form would be:
main: main.o func1.o
g++ main.o func1.o -o main
main.o: main.cpp
g++ -c main.cpp
func1.o: func1.cpp
g++ -c func1.cpp
or one can write
main: func1.o main.o
g++ main.o func1.o -o main
func1.o: func1.cpp
g++ -c func1.cpp
main.o: main.cpp
g++ -c main.cpp
or
main: main.o func1.o
g++ main.o func1.o -o main
func1.o: func1.cpp
g++ -c func1.cpp
main.o: main.cpp
g++ -c main.cpp
Do the last two differ from the classic one ? Does one have some advantages over the other?

No, the only time the order of the rules comes into play is when you just enter make, in which case it can choose the first rule as the default.
Beyond that, make is intelligent enough to execute dependent rules no matter where they are in the file.

There is no difference between the three sets of ruls. However, make knows how build .cpp files into object files, so all you really need is:
main: main.o func1.o
g++ main.o func1.o -o $#

Related

Makefile Not Recognizing Object Make Directive

I am having issues getting my Makefile to compile a very simple main function, and I can't seem to find the issue. Here is my Makefile:
main: main.o Recursion.o
gcc -Wall -o main main.o Recursion.o
main.o: main.c Recursion.c
gcc -Wall -c main.c
Recursion.o: Recursion.c Recursion.h
gcc -Wall -c Recursion.c
clean:
rm main *.o
When I enter the make command in the UNIX terminal, this is the result I get:
-bash-4.2$ make
cc -c -o main.o main.c
cc -c -o Recursion.o Recursion.c
gcc -Wall -o main main.o Recursion.o
main.o: main.c Recursion.c
make: main.o:: Command not found
make: *** [Makefile:3: main] Error 127
-bash-4.2$
I cannot figure out what's wrong. It is generating the executable main, but I'm not sure what exactly the issue is on the command line. Any suggestions?
Makefiles are indentation-sensitive.
Try this:
main: main.o Recursion.o
gcc -Wall -o main main.o Recursion.o
main.o: main.c Recursion.c
gcc -Wall -c main.c
Recursion.o: Recursion.c Recursion.h
gcc -Wall -c Recursion.c
clean:
rm main *.o

Generate objects individually from variables

I'm doing a Makefile to make objects with the same gcc command. This file looks like this:
SRCLIB = main.c srv.c
OBJLIB = main.o srv.o
CC = gcc
CCFLAGS = -Wall -Werror
$(OBJLIB) : $(SRCLIB)
$(CC) $(CCFLAGS) -c $^ -o $#
The objetive is to execute this like:
gcc -Wall -c read_line.c -o read_line.o
gcc -Wall -c client.c -o client.o
But I don't know how to do it, and everything I tested is not working. Is it even possible to do this in a Makefile?
Your makefile expands to this, after the variables are expanded:
main.o srv.o : main.c srv.c
$(CC) $(CCFLAGS) -c $^ -o $#
In make, using multiple targets in explicit rules like this is the same as writing the rule multiple times, once for each target. So, this is the same as this:
main.o : main.c srv.c
$(CC) $(CCFLAGS) -c $^ -o $#
srv.o : main.c srv.c
$(CC) $(CCFLAGS) -c $^ -o $#
This means that if either of the source files changes, BOTH object files will be recreated (since each object depends on both sources, not just their own source file).
Further, in your compile line you use the variable $^ which expands to all the prerequisites. So your compile lines will expand to:
gcc -Wall -Werror -c main.c srv.c -o main.o
gcc -Wall -Werror -c main.c srv.c -o srv.o
which is illegal: if you use -c with the -o option you can only compile one source file.
Make has built-in rules that already know how to compile files, so there's no need to write your own. You can just write this:
SRCLIB = main.c srv.c
OBJLIB = main.o srv.o
CC = gcc
CCFLAGS = -Wall -Werror
.PHONY: all
all: $(OBJLIB)
and that's all you need.

GNU Make seems to skip prerequisites

I've got a basic, minimal makefile to compile C++ source; a stripped-down version looks like this:
TARGET = main
OBJ = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
CPPFLAGS = -std=c++11 -Wall
build: $(TARGET)
$(TARGET): $(OBJ)
#echo "$? --> $#"
g++ $(CPPFLAGS) -o $# $?
#echo
%.o: %.cpp
#echo "$< --> $#"
g++ $(CPPFLAGS) -c $<
#echo
When building from scratch, everything works as expected:
clock.cpp --> clock.o
g++ -std=c++11 -Wall -c clock.cpp
main.cpp --> main.o
g++ -std=c++11 -Wall -c main.cpp
clock.o main.o --> main
g++ -std=c++11 -Wall -o main clock.o main.o
After a change in one of the source files, make rebuilds the corresponding object file, but for some reason skips the existing (unchanged) object file when trying to link (clock.o --> main instead of clock.o main.o --> main):
clock.cpp --> clock.o
g++ -std=c++11 -Wall -c clock.cpp
clock.o --> main
g++ -std=c++11 -Wall -o main clock.o
When running make again, without changing any file, the linking works as expected:
clock.o main.o --> main
g++ -std=c++11 -Wall -o main clock.o main.o
What's the reason for this behavior, and how could it be prevented?
I'm running GNU Make 4.1 on i686 Linux 4.4
You use wrong automatic variable in g++ $(CPPFLAGS) -o $# $? recipe.
https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html:
$?
The names of all the prerequisites that are newer than the target,
with spaces between them.
So Make does exactly what you ask it to do: link main target from all updated prerequisites and skip untouched prerequisites.
g++ $(CPPFLAGS) -o $# $^ recipe will fix the problem.

How to get g++ to ignore warnings from included projects

I'm making a new project that is dependent on two other projects (written by others). While I'm developing my code I would like to use g++ options such as -Wall -pedantic -Werror but when I use these options I get a flood of warnings by including files from the other two projects.
Is there any way I can ignore the warnings from those two projects but still see the warnings from my own project?
If you're compiling their source directly via a makefile, you can make optional CPPFLAGSwhich you can use for conditional compilation parameters. For example:
CPPFLAGS=-Wall -pedantic -Werror for your project and CPPFLAGS=-g for their project files (or something).
Take the following sample makefile. Assume you wrote factorial.cpp and hello.cpp and they wrote main.cpp:
CPPFLAGS+=-Wall -pedantic -Werror
all: hello
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello
main.o: main.cpp
g++ -c main.cpp
factorial.o: factorial.cpp
g++ -c $(CPPFLAGS) factorial.cpp
hello.o: hello.cpp
g++ -c $(CPPFLAGS) hello.cpp
clean:
rm -rf *o hello
Try something like that and get back to me.

How dependencies works on gnu Makefile?

How dependencies works on gnu Makefile ?
I want to create a Makefile which:
- will apply some patches (in our exmaple, apply main.patch on main.c)
- create a programm called toto from patched main.c file
my_patch=./main.patch
all: toto
patch: $(my_patch)
echo "apply patch"
main.o: main.c
gcc -o main.o -c main.c -Wall
toto: patch main.o $(my_patch)
echo "build"
gcc -o toto main.o
but, the patch are always applied ... which leads me on my question:
"How dependencies works on gnu Makefile ?"
How can I tell to gnu make that it's useless to apply main.patch if the date of main.patch is smaller than the binary toto
thanks for any help :)
The phony target (patch) is confusing things. The patch rule modifies main.c, so let that be the target:
my_patch=./main.patch
all: toto
main.c: $(my_patch)
echo "apply patch"
main.o: main.c
gcc -o main.o -c main.c -Wall
toto: main.o # no need to specify $(my_patch) here
echo "build"
gcc -o toto main.o
P.S. while you're at it, you may as well introduce automatic variables; the makefile is cleaner and easier to maintain that way:
main.o: main.c
gcc -o $# -c $< -Wall
toto: main.o # no need to specify $(my_patch) here
echo "build"
gcc -o $# $^

Resources