Makefile rule using the automatic variable $^ without dependencies - variables

I learnt from the GNU Make manual that the sign $^ is an automatic variable which represents the names of all the prerequisites. However I fell upon a makefile like this one:
SVR_OBJECT_FILES = server.o\
server_func.o
CLT_OBJECT_FILES = client.o
CFLAGS = -Wall -Werror -W
CC = gcc
all: client/client server/serveur
client/client: $(CLT_OBJECT_FILES)
server/serveur: $(SVR_OBJECT_FILES)
client/client server/serveur:
#mkdir -p $(dir $#)
$(CC) $(CFLAGS) $^ -o $#
%.o: %.c
$(CC) -c $<
clean:
rm -f client/client server/serveur *.o
Which works fine so my question is :
How can the command below can link the right object files while the $^ variable is refering no preprerequisites at all. (the rule has no prerequisites)
$(CC) $(CFLAGS) $^ -o $#

$^ contains all the prerequisites of the target, not just the ones that are mentioned with the rule itself. The same file can appear as a target several times in rules with no commands:
sometarget: dependency1
…
sometarget: dependency2
assemble -o $# $^
…
sometarget: dependency3
The dependencies of sometarget are dependency1, dependency2 and dependency3, and when the assemble command is invoked by make sometarget, it will receive all three as arguments.
Here, $^ will contain all $(CLT_OBJECT_FILES) or $(SRV_OBJECT_FILES) depending on which target the command is executed for.

Related

makefile with debug option

I am kinda rookie in makefile field but trying to write makefile that would go in two modes: normal mode make outputing executable file called say bingo depending on some files and a mode make debug outputing executable file called bingo.debug that shall be compiled with debug option. I'm trying to use target variable with the following result:
PROGRAM = bingo
SUFIX = .debug
CC = gcc
CFLAGS = -Wall -O2
DEBUG = -g -D DEBUG
all: $(PROGRAM)
debug: CFLAGS += $(DEBUG)
debug: PROGRAM += $(SUFIX)
debug: all
file1.o: file1.c file1.h
$(CC) -c $(CFLAGS) -o $# $<
file2.o: file2.c file2.h
$(CC) -c $(CFLAGS) -o $# $<
$(PROGRAM).o: $(PROGRAM).c
$(CC) -c $(CFLAGS) -o $# $<
$(PROGRAM): file1.o file2.o ($PROGRAM).o
$(CC) -o $# $^
.PHONY: all clean
clean:
rm -rf $(PROGRAM) *.o
It looks like make debug correctly compiles the file with debug flags but it does not change the file name (i.e. both modes outputs the same bingo file). Any help much appriciated!
You cannot use target-specific variables in targets. The documentation is very clear that they are available only in recipes.
In general it's problematic to do things this way, because make has no idea which objects were built with debug and which weren't. If you forget to do a complete clean and/or run make the wrong way then you'll get a mix of different object files: some compiled with debug and some not.
Instead, you should put your debug object files in a different directory from your non-debug object files so you don't have to worry about that.

specifying a make variable in a rule

I would like to set a variable $(CFLAGS2) to hold different values depending on the target i make. Specifically, i want to have a target which compiles my project with "-g -Wall", and another one which compiles with "-O3"
I tried it like this:
CC=gcc
COPT=-c $< -o $# $(CADD) $(CFLAGS) $(CFLAGS2)
.PHONY: opti
.PHONY: debi
opti: seto
make hammingtest
debi: setd
make hammingtest
.PHONY: seto
seto:
$(eval CFLAGS2 := -O3)
.PHONY: setd
setd:
$(eval CFLAGS2 :=-g -Wall)
hamming.o: hamming.cpp hamming.h
$(CC) $(COPT) $(DEFS) $(CFLAGS2)
hammingtest.o: hammingtest.cpp hamming.h
$(CC) $(COPT) $(DEFS) $(CFLAGS2)
hammingtest: hammingtest.o hamming.o
$(CC) -o hammingtest hammingtest.o hamming.o
But when i do "make debi" it acts as if $(CFLAGS") was not set at all (the same with "make opti")
How can i achieve this?
Do not use $(eval ...) in shell lines. That is usually just plain wrong.
There is a number of ways to do what you want. Since you already have recursive make set up, you could use command-line variables:
opti:
${MAKE} COPTS2='-O3' hammingtest
debi:
${MAKE} COPTS2='-g -Wall' hammingtest
A better style is to eschew the recursive make, maybe in favour of target specific variables:
CC=gcc
COPT=-c $< -o $# $(CADD) $(CFLAGS) $(CFLAGS2)
CFLAGS2 = $(error Someone tried to deref CFLAGS2!)
opti: CFLAGS2 := -O3
debi: CFLAGS2 := -g -Wall
.PHONY: all
all:
#echo 'What do you want to make?'
.PHONY: opti debi
opti debi: hammingtest
opti debi: ; #echo $# Success
.
.
.
This looks likely to work at a cursory glance.
The way this is set up though is problematic. For example, the following sequence of shell commands will give you an optimised build, with no warnings.
$ make opti
$ make debi

gcc Makefile: Variable Substitution error with %

My make file has worked, up until I tried some variable substitution. %.o is not recognized.
I get make: * No rule to make target `%.o', needed by `parser'. Stop.
CC=gcc
CFLAGS=-ansi -pedantic -Wall -ggdb3
PROJECT=project.c project.h
PARSER=parser.c parser.h
OBJ=project.o parser.o
#CFILE=project.c parser.c
#1 no problem
#parser: project.o parser.o
# $(CC) $(CFLAGS) -o $# $^
#2 no problem
#parser: $(OBJ)
# $(CC) $(CFLAGS) -o $# $^
#3 this fails
parser: %.o
$(CC) $(CFLAGS) -o $# $^
#parser: project.o parser.o
# gcc -ansi -pedantic -Wall -ggdb -o parser project.o parser.o
project.o: $(PROJECT)
$(CC) $(CFLAGS) -c $^
parser.o: $(PARSER)
$(CC) $(CFLAGS) -c $^
clean:
rm -f $(OBJ) parser
You're not creating a pattern rule, since there is no % in the target name. As a result the % has no special meaning in the list of dependencies. It's seen as a literal part of a file name; you can't use it as a regular wildcard.

Prepending a path on make

In my makefile I have an object variable. I need to prepend obj/ to every .o file. How would I do this?
CC=g++
CFLAGS=-C -Wall
LDFLAGS=-lsqlite3 -lpthread -ldl
SOURCES=main.cpp Database.cpp actionInit.cpp TileSet.cpp Player.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=mahjong-counter
all: bin $(OBJECTS) $(EXECUTABLE)
bin:
mkdir -p bin
%.o: %.cpp
$(CC) $(LDFLAGS) $< -c -o $#
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $(EXECUTABLE)
clean:
rm $(OBJECTS)
You want CXX, not CC. CC is for C compiler, not the C++ compiler
In any case, I believe the following should work:
CXX=g++
CXXFLAGS=-C -Wall
LDFLAGS=-lsqlite3 -lpthread -ldl
OBJ_DIR = obj
BIN_DIR = bin
EXECUTABLE=mahjong-counter
SOURCES= main.cpp Database.cpp actionInit.cpp TileSet.cpp Player.cpp
OBJECTS= $(SOURCES:%.cpp=$(OBJ_DIR)/%.o)
all: dirs $(OBJECTS) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $(EXECUTABLE)
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
dirs:
mkdir -p $(BIN_DIR)
mkdir -p $(OBJ_DIR)
.PHONY: dirs all
You could use more expressive version of substitution you employed when assigning OBJECTS
OBJECTS=$(SOURCES:%.cpp=obj/%.o)
or use a standard text transformation function
OBJECTS=$(addprefix obj/,$(SOURCES:.cpp=.o))

How to write a shell script to compile multiple embedded sql in C files (.sqc)?

I have written 3 .sqc files i.e. embedded sql in host language C. I need to make a (Unix) shell script to simply compile all 3 sqc files in a row. How can I do that? Right now, I can individually run each .sqc file using a Makefile that basically converts the .sqc file to a c file and then compiles it. Can I make 3 individual Makefiles and run all of them through a shell script? If so, then how? Can I make one Makefile that can compile all 3 .sqc independently and compile them thereafter through a shell script? If so, then how? Any other options?
Here is the Makefile that can only compile a single .sqc file:
NAME=sample
DB2PATH = /sqllib
CC=gcc
CFLAGS=-I$(DB2PATH)/include
LIBS=-L$(DB2PATH)/lib -R$(DB2PATH)/lib -ldb2
all: $(NAME)
$(NAME): $(NAME).sqc util.o
db2 connect to sampleDB
db2 prep $(NAME).sqc bindfile
db2 bind $(NAME).bnd
db2 connect reset
$(CC) $(CFLAGS) -c $(NAME).c
$(CC) $(CFLAGS) -o $(NAME) $(NAME).o util.o $(LIBS)
clean:
rm -f $(NAME) $(NAME).c $(NAME).o $(NAME).bnd
util.o : util.c
$(CC) -c util.c $(CFLAGS)
A possible (Unix) shell script and Makefile example would suffice to help.
Thank you.
This Makefile should do all three in one step, just type "make". Note that you'll have to change the second line to reflect the names of your real .sqc files.
Also note that I'm not familiar with sqc and I haven't tested this, I'm just working from your Makefile.
# THIS IS THE ONLY LINE YOU'LL HAVE TO CHANGE:
NAMES = file1 file2 file3
DB2PATH = /sqllib
CC=gcc
CFLAGS=-I$(DB2PATH)/include
LIBS=-L$(DB2PATH)/lib -R$(DB2PATH)/lib -ldb2
all: $(NAMES)
# This will convert .sqc into .c
%.c: %.sqc
db2 connect to sampleDB
db2 prep $< bindfile
db2 bind $*.bnd
db2 connect reset
# This will compile .c into .o, whether it's fileN.c or util.c
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
# This will link fileN.o and util.o into fileN
$(NAMES): % : %.o util.o
$(CC) $(CFLAGS) -o $# $^ $(LIBS)
# This is just to assure Make that that isn't really a file called "clean"
.PHONY: clean
clean:
rm -f $(NAMES) $(NAMES:=.c) $(NAMES:=.o) $(NAMES:=.bnd)
DB2PATH = /sqllib
CC=gcc
CFLAGS=-I$(DB2PATH)/include
LIBS=-L$(DB2PATH)/lib -R$(DB2PATH)/lib -ldb2
all: $(NAME)
$(NAME): $(NAME).sqc util.o
db2 connect to sampleDB
db2 prep $(NAME).sqc bindfile
db2 bind $(NAME).bnd
db2 connect reset
$(CC) $(CFLAGS) -c $(NAME).c
$(CC) $(CFLAGS) -o $(NAME) $(NAME).o util.o $(LIBS)
clean:
rm -f $(NAME) $(NAME).c $(NAME).o $(NAME).bnd
util.o : util.c
$(CC) -c util.c $(CFLAGS)
suppose you have three files: file1.sqc file2.sqc file3.sqc, and your makefile is saved as mksqc.mk
Script:
make -f mksqc.mk NAME=file1
make -f mksqc.mk NAME=file2
make -f mksqc.mk NAME=file3