Macros ($#, $< , $*) in Makefile? - makefile

I am learning the Makefile Language for Unix.
In the following code:
hello: main.cpp hello.cpp factorial.cpp
$(CC) $(CFLAGS) $? $(LDFLAGS) -o $#
Alternatively:
hello: main.cpp hello.cpp factorial.cpp
$(CC) $(CFLAGS) $#.cpp $(LDFLAGS) -o $#
I am not able to understand what $# and $#.cpp do? (I don't understand the terms 'dependent files' and 'changed dependent files' ). Also if you could explain what is $< and $* via a simple example, it would be helpful. Thank you.
(Sorry for the many questions - they are slightly related and I didn't want to ask them as separate posts)

Related

GNU make pattern rule when .c files in different directory

I can write pattern rules like that to compile .cfiles to .ofiles.
%.o:%.c
$(CC) -c $< $(CFLAGS) -o $#
But it seems that this method will only work when all the c file are in the same directory.
If my project's struct is like this
|-folder1
|----a.c
|----b.c
|-folder2
|----c.c
|----d.c
|Makefile
I have to change my Makefile to this
%.o:folder1/%.c
$(CC) -c $< $(CFLAGS) -o $#
%.o:folder2/%.c
$(CC) -c $< $(CFLAGS) -o $#
If i have a lot of folders, I think repeating code like this is not the correct way to solve the problem.
Anyone has better solutions?

Makefile : No rule to make target (automatic variables)

I am having trouble with my makefile, i have been reading somme tutoriels on how to make a more re-usable makefile but i am facing this error, and i have been searching for a while now, especially on the GNU make manual and here.
Here is my makefile :
SRC_DIR=./src
BUILD_DIR=./build
OBJS= $(BUILD_DIR)/main.o $(BUILD_DIR)/hamming.o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
I am having the error :
make: No rule to make target build/main.o', needed bybuild/main'. Stop.
It seems to me that the objects in the variable OBJS are not associated with the %.o pattern rule, but i don't know why.
In my working directory there is : my makefile and the two directories 'src' and 'build'.
Thank you.
I'll go out on a limb and guess that there is no src/main.h. If that's the case, you could fix things this way:
$(BUILD_DIR)/hamming.o: $(BUILD_DIR)/%.o : $(SRC_DIR)/%.h
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) -c $< $(CFLAGS) -o $#
EDIT:
Now I'm puzzled. Please try this (it is crude, but if it works we can refine it):
SRC_DIR=./src
BUILD_DIR=./build
OBJS= $(BUILD_DIR)/main.o $(BUILD_DIR)/hamming.o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main.o: $(SRC_DIR)/main.c
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
Here is a little documentation I put together for NMake a while back I hope it helps. Are you sure there are only tabs before the commands. You can't have spaces that is the number one error I have seen in the past.

Questions about makefile

Here is an easy makefile.
I have 2 questions.
all: $(SOURCES) $(EXECUTABLE)
Why put the SOURCE in the dependency.
".cpp.o:"
Why not write ".o: .cpp"
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
The dependency of all on $(SOURCES) is not necessary or even useful. The dependency information should be such that the executable depends on the object files, and the object files depend on the source files.
The notation:
.cpp.o:
was the way the original (7th Edition UNIX™) version of make handled compilation rules. GNU Make (and Sun Make) used the % notation to allow:
%.o: %.cpp
Basically, it was a design decision that made sense at the time and maybe less sense in retrospect. It was not the most egregious problem (that would be tabs at the start of command lines).

How to make this Makefile more concise?

I know there are ways to remove duplicates $(CC) $(CFLAGS) $# $^ in Makefile. Can you tell me how to make the Makefile below more concise?
CC=gcc
CFLAGS=-pthread -g -o
all: p1 p2
p1: p1.c
$(CC) $(CFLAGS) $# $^
p2: p2.c
$(CC) $(CFLAGS) $# $^
To make your Makefile more concise, you can write it as follows.
CC=gcc
CFLAGS=-pthread -g -o
all: p1 p2
%: %.c
$(CC) $(CFLAGS) $# $^
Then you can add as many p's as you want on the all: line. As long as you provide pN.c, make will compile them into the corresponding pN.
Yes, you can combine commands "by prerequisite". For example:
CC=gcc
CFLAGS=-O3
INCLS=-I$(BASEDIR)/include
LIBS=$(BASEDIR)/lib/thread.a
OBJS = dotprod_mutex.o dotprod_serial.o
EXEC = dotprod
$(EXEC): $(OBJS)
$(CC) -o $(EXEC) $(OBJS) $(LIBS)
$(OBJS): dotprod.h
$(CC) $(CFLAGS) $(INCLS) -c $*.c
or somesuch -- you'll need to go through the details and make sure those libraries and so on actually make sense.
Note that the phrase $(OBJS): dotprod.h means that $(OBJS): depends on the presence of dotprod.h.
You will want to read the manual to get all the gory details, in particular:
Letting Make deduce commands
Combine by prerequisite
As for tools to automate this stuff, you want automake and autoconf: http://sourceware.org/autobook/

What do $< and $# represent in a Makefile?

Can anybody please explain the meaning of $< and $# in a Makefile?
$< evaluates to the first "prerequisite" in the make rule, and $# evaluates to the "target" in the make rule.
Here's an example:
file.o : file.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
In this case, $< will be replaced with file.c and $# will be file.o.
These are more useful in generic rules like this:
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
See this manual for more info.
$# is the target of the current rule.
$< is the name of the first prerequisite ("source") of the current rule.
So for example:
.c.o:
$(CC) -c $(CFLAGS) -o $# $<
This will expand to a command something like:
gcc -c -Wall -o foo.o foo.c
See also the GNU make manual § 10.5.3, "Automatic Variables".

Resources