Makefile sometimes ignores variable in recipe - makefile

I have the following Makefile
CXX = g++
CXXFLAGS = -g -Wall
COMPILE = ${CXX} ${CXXFLAGS} -c
LINK = ${CXX} -lpthread
LIB_INC = -Ilib -Iwrappers -Iprocesses
src := $(wildcard lib/*.cpp) $(wildcard wrappers/*.cpp)
obj = $(src:.cpp=.o)
src_1 := processnetwork_part001.cpp sc_application_1.cpp
obj_1 = $(src_1:.cpp=.o)
src_2 := processnetwork_part002.cpp sc_application_2.cpp
obj_2 = $(src_2:.cpp=.o)
all : sc_application_1 sc_application_2
.PHONY : all
sc_application_1 : ${obj} ${obj_1}
${LINK} -o sc_application_1 $(obj) ${obj_1}
sc_application_2 : ${obj} ${obj_2}
${LINK} -o sc_application_2 $(obj) ${obj_2}
%.o : %.cpp %.h
${COMPILE} -o $# $< $(LIB_INC)
clean :
rm sc_application_1 sc_application_2 ${obj} ${obj_1} ${obj_2}
Where lib, wrappers and processes are subdirectories of the directory where the Makefile and the two main applications sc_application_1 and sc_application_2 are stored. When I run make, I get the following output (only the last few lines w/o compiler warnings).
g++ -g -Wall -c -o lib/Scheduler.o lib/Scheduler.cpp -Ilib -Iwrappers -Iprocesses
g++ -g -Wall -c -o wrappers/consumer_wrapper.o wrappers/consumer_wrapper.cpp -Ilib -Iwrappers -Iprocesses
g++ -g -Wall -c -o wrappers/generator_wrapper.o wrappers/generator_wrapper.cpp -Ilib -Iwrappers -Iprocesses
g++ -g -Wall -c -o wrappers/square_wrapper.o wrappers/square_wrapper.cpp -Ilib -Iwrappers -Iprocesses
g++ -g -Wall -c -o processnetwork_part001.o processnetwork_part001.cpp -Ilib -Iwrappers -Iprocesses
g++ -g -Wall -c -o sc_application_1.o sc_application_1.cpp
In file included from wrappers/wrappers.h:4:0,
from sc_application_1.cpp:10:
wrappers/generator_wrapper.h:4:28: fatal error: ProcessWrapper.h: No such file or directory
compilation terminated.
make: *** [sc_application_1.o] Error 1
Compilation fails because for some reason that I don't understand, the variable LIB_INC isn't added anymore to
g++ -g -Wall -c -o sc_application_1.o sc_application_1.cpp
But it is (as I intended) on all previous lines. Can anyone explain me this behaviour? Thank you.
edit: The error doesn't occur when I ommit the "%.h" in the "%.o" target.

I'm going to go out on a limb, and guess that there is no sc_application_1.h, but there is a header file for every previous source (e.g. Scheduler.h, consumer_wrapper.h ...).
Your %.o: %.cpp %.h rule doesn't apply if there is no %.h, so Make falls back on its default rule, which does not use LIB_INC. The simplest way to fix this is to add another %.o rule:
%.o : %.cpp %.h
${COMPILE} -o $# $< $(LIB_INC)
%.o : %.cpp
${COMPILE} -o $# $< $(LIB_INC)

Related

How to get prerequisites with respect to the target in Makefile (GNU Make)?

Is there a way to get the prerequisite corresponding to a target in the Makefile (GNU Make)?
For instance, consider the following Makefile:
CXX = g++
CFLAGS = -Wall
MODULE_NAME = myRenderer
BUILD_DIR = bin
SOURCE_FILES = renderer/tracer.cpp renderer/lights/DiffuseLight.cpp renderer/materials/ScatterUtils.cpp
OBJECT_FILES = $(patsubst %,$(BUILD_DIR)/%, $(notdir $(SOURCE_FILES:.cpp=.o)))
$(BUILD_DIR)/$(MODULE_NAME): $(OBJECT_FILES)
$(CXX) -o $# $^
$(OBJECT_FILES): $(SOURCE_FILES)
#mkdir -p "$(BUILD_DIR)"
$(CXX) $(CFLAGS) -I. -c $< -o $#
when I run make, I can see that the following commands get executed:
g++ -Wall -I. -c renderer/tracer.cpp -o bin/tracer.o
g++ -Wall -I. -c renderer/tracer.cpp -o bin/DiffuseLight.o
g++ -Wall -I. -c renderer/tracer.cpp -o bin/ScatterUtils.o
g++ -o bin/myRenderer bin/tracer.o bin/DiffuseLight.o bin/ScatterUtils.o
And obviously, this fails to build the executable as it's using only the first prerequisite i.e. renderer/tracer.cpp to generate all the object files because I am using the $< automatic variable in the recipe command for the $(OBJECT_FILES) target.
I wish to know how to fix my Makefile to be able to execute these commands:
g++ -Wall -I. -c renderer/tracer.cpp -o bin/tracer.o
g++ -Wall -I. -c renderer/lights/DiffuseLight.cpp -o bin/DiffuseLight.o
g++ -Wall -I. -c renderer/materials/ScatterUtils.cpp -o bin/ScatterUtils.o
g++ -o bin/myRenderer bin/tracer.o bin/DiffuseLight.o bin/ScatterUtils.o
I cannot seem to find the right automatic variable or a way to fetch the right source file to build a given object file.
As suggested by Matt you have (at least) two options:
A compilation rule:
# $(1): source file
define MY_RULE
$$(patsubst %.cpp,$$(BUILD_DIR)/%.o,$$(notdir $(1))): $(1)
#mkdir -p "$$(BUILD_DIR)"
$$(CXX) $$(CFLAGS) -I. -c $$< -o $$#
endef
$(foreach f,$(SOURCE_FILES),$(eval $(call MY_RULE,$(f))))
Note the $$ used to escape the first expansion (see The eval Function for a detailed explanation).
The vpath directive:
vpath %.cpp $(dir $(SOURCE_FILES))
$(BUILD_DIR)/%.o: %.cpp
#mkdir -p "$(BUILD_DIR)"
$(CXX) $(CFLAGS) -I. -c $< -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.

Whats worng with the make file format

I wrote a makefile for my mini-project with gedit.
when I run "make", all *.o and executable created.
once I change one of my file (without make clean or make -B)
it's show it compile the chaneged file again and link all object again.
But the executable file works like nothing change.
(after "make -B" the executable file run ok)
CC = g++
CFLAGS = -Wall
OBJS = pawn.o knight.o bishop.o rook.o queen.o king.o board.o
movement.o game.o
all: ex1
ex1: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o ex1
pawn.o: chess/tools/pawn.cpp chess/tools/tool.hpp
$(CC) $(CFLAGS) -c chess/tools/pawn.cpp
knight.o: chess/tools/knight.cpp chess/tools/tool.hpp
$(CC) $(CFLAGS) -c chess/tools/knight.cpp
bishop.o: chess/tools/bishop.cpp chess/tools/tool.hpp
$(CC) $(CFLAGS) -c chess/tools/bishop.cpp
rook.o: chess/tools/rook.cpp chess/tools/tool.hpp
$(CC) $(CFLAGS) -c chess/tools/rook.cpp
queen.o: chess/tools/queen.cpp chess/tools/tool.hpp
$(CC) $(CFLAGS) -c chess/tools/queen.cpp
king.o: chess/tools/king.cpp chess/tools/tool.hpp
$(CC) $(CFLAGS) -c chess/tools/king.cpp
board.o: chess/board.cpp chess/board.hpp
$(CC) $(CFLAGS) -c chess/board.cpp
movement.o: chess/movement.cpp
$(CC) $(CFLAGS) -c chess/movement.cpp
game.o: chess/game.cpp
$(CC) $(CFLAGS) -c chess/game.cpp
clean:
rm *.o
If there is another problem or suggestion with the design of the make file, I will be glad to hear about it.
Edit
1)The program is not print nothing to the screen.
2)The change is in king.cpp file (located in another folder) print Print Change to screen
[av#ArchlinuxAvichai chess]$ ls
chess ex1 Makefile
[av#ArchlinuxAvichai chess]$ ls chess
board.cpp board.hpp game.cpp movement.cpp tools
[av#ArchlinuxAvichai chess]$ ls chess/tools
bishop.cpp king.cpp knight.cpp pawn.cpp queen.cpp rook.cpp tool.hpp
[av#ArchlinuxAvichai chess]$ make
g++ -Wall -c chess/tools/pawn.cpp
g++ -Wall -c chess/tools/knight.cpp
g++ -Wall -c chess/tools/bishop.cpp
g++ -Wall -c chess/tools/rook.cpp
g++ -Wall -c chess/tools/queen.cpp
g++ -Wall -c chess/tools/king.cpp
g++ -Wall -c chess/board.cpp
g++ -Wall -c chess/movement.cpp
g++ -Wall -c chess/game.cpp
g++ -Wall pawn.o knight.o bishop.o rook.o queen.o king.o board.o movement.o game.o -o ex1
[av#ArchlinuxAvichai chess]$ ./ex1
[av#ArchlinuxAvichai chess]$ *** AT this stage i change the file
[av#ArchlinuxAvichai chess]$
[av#ArchlinuxAvichai chess]$ make
g++ -Wall -c chess/tools/king.cpp
g++ -Wall pawn.o knight.o bishop.o rook.o queen.o king.o board.o movement.o game.o -o ex1
[av#ArchlinuxAvichai chess]$ ./ex1
[av#ArchlinuxAvichai chess]$
[av#ArchlinuxAvichai chess]$ make -B
g++ -Wall -c chess/tools/pawn.cpp
g++ -Wall -c chess/tools/knight.cpp
g++ -Wall -c chess/tools/bishop.cpp
g++ -Wall -c chess/tools/rook.cpp
g++ -Wall -c chess/tools/queen.cpp
g++ -Wall -c chess/tools/king.cpp
g++ -Wall -c chess/board.cpp
g++ -Wall -c chess/movement.cpp
g++ -Wall -c chess/game.cpp
g++ -Wall pawn.o knight.o bishop.o rook.o queen.o king.o board.o movement.o game.o -o ex1
[av#ArchlinuxAvichai chess]$ ./ex1
Print Change
[av#ArchlinuxAvichai chess]$
Try the following makefile:
CXX := g++
CXXFLAGS := -Wall
OBJS := pawn.o knight.o bishop.o rook.o queen.o king.o board.o movement.o game.o
COMPILE_CMD = ${CXX} -c -o $# ${CXXFLAGS} -MD -MP $<
LINK_CMD = ${CXX} -o $# ${LDFLAGS} $^
all: ex1
ex1: ${OBJS}
${LINK_CMD}
%.o : chess/tools/%.cpp
${COMPILE_CMD}
%.o : chess/%.cpp
${COMPILE_CMD}
-include $(OBJS:%.o=%.d)
clean:
rm -f *.o *.d
.PHONY: clean all
Changes:
Use ${CXX} for C++ code.
Auto-generate header dependencies.
Use pattern rules to avoid repetition.
Specify .o output files.
Mark targets clean and all as .PHONY.
Use LDFLAGS for linking.

Loop through list of files in Makefile

I compiling my C source files with this code:
CC=clang -std=c11
CFLAGS=-Wall -g
ASSEMBLY=-S -masm=intel
OPTIMIZE=-Ofast
FOLDER_SRC=./src/
FOLDER_BIN=./bin/
FOLDER_ASSEMBLY=./ass/
clean:
rm -f \
$(FOLDER_BIN)1.1-hello $(FOLDER_ASSEMBLY)1.1-hello \
$(FOLDER_BIN)1.2-fahrenheit $(FOLDER_ASSEMBLY)1.2-fahrenheit \
$(FOLDER_BIN)1.2-fahrenheit-floating $(FOLDER_ASSEMBLY)1.2-fahrenheit-floating
all:
$(CC) $(CFLAGS) $(OPTIMIZE) $(FOLDER_SRC)1.1-hello.c -o $(FOLDER_BIN)1.1-hello
$(CC) $(CFLAGS) $(OPTIMIZE) $(FOLDER_SRC)1.2-fahrenheit.c -o $(FOLDER_BIN)1.2-fahrenheit
$(CC) $(CFLAGS) $(OPTIMIZE) $(FOLDER_SRC)1.2-fahrenheit-floating.c -o $(FOLDER_BIN)1.2-fahrenheit-floating
assembly:
$(CC) $(ASSEMBLY) $(OPTIMIZE) $(FOLDER_SRC)1.1-hello.c -o $(FOLDER_ASSEMBLY)1.1-hello
$(CC) $(ASSEMBLY) $(OPTIMIZE) $(FOLDER_SRC)1.2-fahrenheit.c -o $(FOLDER_ASSEMBLY)1.2-fahrenheit
$(CC) $(ASSEMBLY) $(OPTIMIZE) $(FOLDER_SRC)1.2-fahrenheit-floating.c -o $(FOLDER_ASSEMBLY)1.2-fahrenheit-floating
I try to implement some kind of loop to write less. I added this code, but it just generating errors:
FILENAME_SRC := $(wildcard $(FOLDER_SRC)*.c)
FILENAME_BUILD := $(patsubst $(FOLDER_SRC)%.c,%,$(FILENAME_SRC))
echo : $(FILENAME_SRC)
#echo $^
#echo $(FILENAME_BUILD)
build : $(FILENAME_SRC)
$(CC) $(CFLAGS) $(OPTIMIZE) $^ -o $(FILENAME_BUILD)
make echo printing this to the console:
$ make echo
src/1.2-fahrenheit.c src/1.1-hello.c src/1.2-fahrenheit-floating.c
1.2-fahrenheit 1.1-hello 1.2-fahrenheit-floating
make build command generating this error:
$ make build
clang -std=c11 -Wall -g -Ofast src/1.2-fahrenheit.c src/1.1-hello.c src/1.2-fahrenheit-floating.c -o 1.2-fahrenheit 1.1-hello 1.2-fahrenheit-floating
clang.exe: error: no such file or directory: '1.1-hello'
clang.exe: error: no such file or directory: '1.2-fahrenheit-floating'
make: *** [Makefile:21: build] Error 1
I want the expected output to look like when I do make all:
$ make all
clang -std=c11 -Wall -g -Ofast ./src/1.1-hello.c -o ./bin/1.1-hello
clang -std=c11 -Wall -g -Ofast ./src/1.2-fahrenheit.c -o ./bin/1.2-fahrenheit
clang -std=c11 -Wall -g -Ofast ./src/1.2-fahrenheit-floating.c -o ./bin/1.2-fahrenheit-floating
Final solution
CC := clang -std=c11
GCC := gcc -std=c11
CFLAGS := -Wall -g
ASSEMBLY := -Wall -S -masm=intel
OPTIMIZE := -O3 -march=native
SRC := $(wildcard src/*.c)
BIN := $(patsubst src/%.c,bin/%,$(SRC))
ASS := $(patsubst src/%.c,ass/%,$(SRC))
clean:
rm -f bin/* ass/*
build: $(BIN)
$(BIN): bin/%: src/%.c
$(CC) $(CFLAGS) $(OPTIMIZE) $^ -o $#
assembly: $(ASS)
$(ASS): ass/%: src/%.c
$(CC) $(ASSEMBLY) $(OPTIMIZE) $^ -o $#
Really sorry for the clean ass/* though, it cannot be called assembly because the similar folder name in the project.
Your all rule needs to look something like
CC := clang
CFLAGS := -std=c11 -Wall -g -Ofast
targets := bin/1.1-hello bin/1.2-fahrenheit bin/1.2-fahrenheit-floating
.PHONY: all
all: $(targets)
$(targets): bin/%: src/%.c
$(LINK.c) $^ $(LDLIBS) -o $#

CFLAGS are ignored in Makefile

I am using the following makefile to build my project:
CC = /usr/bin/g++
CFLAGS = -Wall -pedantic -std=c++0x
LDFLAGS =
OBJ = main.o pnmhandler.o pixmap.o color.o
pnm: $(OBJ)
$(CC) $(CFLAGS) -o pnm $(OBJ) $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $<
As I run make I get the following error:
/usr/include/c++/4.9.1/bits/c++0x_warning.h:32:2: error: #error This
file requires compiler and library support for the ISO C++ 2011
standard. This support is currently experimental, and must be enabled
with the -std=c++11 or -std=gnu++11 compiler options.
As I can read from the following line, the CFLAGS are not properly included, but I have no idea what I am doing wrong:
g++ -c -o main.o main.cpp
Also tried -std=c++11 and -std=gnu++11, without any results. Any ideas?
If I run make -Bn, I get:
g++ -c -o main.o main.cpp
g++ -c -o pnmhandler.o pnmhandler.cpp
g++ -c -o pixmap.o pixmap.cpp
g++ -c -o color.o color.cpp
/usr/bin/g++ -Wall -pedantic -std=c++0x -o pnm main.o pnmhandler.o pixmap.o color.o
EDIT: Replacing the rule %.o: %.c with %.o: %.cpp fixes my problem.
The reason you see
g++ -c -o main.o main.cpp
is that Make is invoking its standard rule to create the object file:
%.o: %.cpp
# recipe to execute (built-in):
$(COMPILE.cpp) $(OUTPUT_OPTION) $<
The command expands to
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $# $<
Instead of setting CC and CFLAGS in your makefile, you should set CXX and CXXFLAGS, which are meant for C++ rather than C. That allows the built-in rule above to work for you, and then you just need to make sure the right linker is used, e.g. with
pnm: LINK.o=$(LINK.cc)
pnm: $(OBJ)
You also don't need the %.o: %.c rule, as you have no C sources.
Complete Makefile:
CXX = /usr/bin/g++
CXXFLAGS = -Wall -pedantic -std=c++0x
OBJ = main.o pnmhandler.o pixmap.o color.o
pnm: LINK.o=$(LINK.cc)
pnm: $(OBJ)
clean::
$(RM) pnm
.PHONY: clean

Resources