How to convert a source c files to corresponding .o files using suffix rule in makefile? - makefile

Suppose we have a.c b.c c.c .So the make file will like this
app: a.o b.o c.o
gcc -o app.o a.o b.o c.o
a.o: a.c
gcc -c a.c
b.o: b.c
gcc -c b.c
c.o: c.c
gcc -c c.c
In the future more C files may be added. So do I need to make target of .o extensions for each .c file. I got to know about suffix rules which uses the .source-extension.target-extension. But I could understand how to use this suffix rule in the make file. Please provide me the command to be included in make file and please describe the syntax.I am newbie to makefile.

You can use the below makefile.
app: a.o b.o c.o
gcc -o $# $^
a.o : a.h
b.o : b.h
c.o : c.h
%.o: %.c
gcc -c $<
Where $# is the target(app), $^ is the list of dependencies and $< is the corresponding c file to compile to object file

Below is the sample makefile for compiling c code.
TARGET = a.out
SRCS = a.c b.c c.c
OBJS = $(SRCS:.c=.o)
CFLAGS = -g -ggdb -O2 -Wall -Werror
CC = gcc
RM = rm
.PHONY: all clean
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
$(TARGET) : $(OBJS)
$(CC) $^ -o $#
clean:
$(RM) *.o
$(RM) $(TARGET)

Related

What would be the minimal Makefile for a C project?

I find plenty of answers such as this one that doesn't use the implicit rules.
The minimum I can write is this:
SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
EXEC=a.exe
all: $(EXEC)
$(EXEC): $(OBJ)
$(CC) $^ -o $#
clean:
$(RM) $(OBJ)
$(RM) $(EXEC)
But I am sure I can remove the linking part as well.
Is it possible to reduce this Makefile a bit more?
EDIT
With the help of Maxim Egorushkin I wrote this:
#Makefile
OBJS=$(patsubst %.c,%.o,$(wildcard *.c))
EXEC=a
$(EXEC): $(OBJS)
all : $(EXEC)
clean :
rm -f $(OBJS)
.PHONY: all clean
It does build my files, but it doesn't link anything:
$ make
cc -c -o bar.o bar.c
cc -c -o cow.o cow.c
cc -c -o foo.o foo.c
What should I change?
The dummy source files are created as follow:
echo "int main() {return 0;}" > cow.c
touch foo.c bar.c cow.c
The bare minimum would be:
all : a
a : a.o b.o c.o
clean :
rm -f a a.o
.PHONY: all clean
It expects source files a.c, b.c and c.c to produce executable a:
$ touch a.c b.c c.c
$ make
cc -c -o a.o a.c
cc -c -o b.o b.c
cc -c -o c.o c.c
cc a.o b.o c.o -o a
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'a' failed
make: *** [a] Error 1
However, you do not get automatic header dependency generation with the built-in GNU make rules. Extra 5 lines would be required for that.

Generate makefile targets from a list of source files

I'm trying to create a build system using make and would like to do the following:
have a list of source files specified in the makefile, e.g.
SOURCES = a.cpp b.cpp c.cpp
Automatically create build targets that depend on each file separately
I.e a single rule that would automatically expand into:
a.o: a.cpp
$(CC) $(CFLAGS) -c a.cpp -o a.o
b.o: b.cpp
$(CC) $(CFLAGS) -c b.cpp -o b.o
c.o: c.cpp
$(CC) $(CFLAGS) -c c.cpp -o c.o
I've tried the following:
SOURCES = a.cpp b.cpp c.cpp
OBJECTS = $(SOURCES:.cpp=.o)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $< -o $#
However, this seems to expand into the following
a.o: a.cpp b.cpp c.cpp
$(CC) $(CFLAGS) -c a.cpp -o a.o
b.o: b.cpp b.cpp c.cpp
$(CC) $(CFLAGS) -c a.cpp -o b.o
c.o: c.cpp b.cpp c.cpp
$(CC) $(CFLAGS) -c a.cpp -o c.o
Which is not right
Is there a simple way to achieve the result that i wrote earlier?
Make already has built-in rules that convert a .cpp file to a .o file. Just write:
SOURCES = a.cpp b.cpp c.cpp
all: $(SOURCES:.cpp=.o)
and it will work. If you want to know how to write your own rules, read about implicit rules, in particular pattern rules.

how to expand variables to multiple rules in makefile?

Say that I have two variables in Makefile
CXXFILES = a.cpp b.cpp
OBJFILES = a.o b.o
I would like to write a rule that will expand to
a.cpp : a.o
g++ -o a.o a.cpp
b.cpp : b.o
g++ -o b.o b.cpp
Note that I'm not looking for
%.o : %.cpp
g++ -o $# $<
because I don't want to match all .cpp files -- I only want those files specified by a variable.
Sounds like a job for a Static Pattern Rule:
Here is an example, which compiles each of foo.o and bar.o from the
corresponding .c file:
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $#

A simple Makefile that doesn't create the executable file

I have the following Makefile:
CC = gcc
OBJS = a.o b.o c.o
EXEC = prog
DEBUG = #-g for debug
CFLAGS = -std=c99 -Wall -Werror $(DEBUG)
$(EXEC) : $(OBJS)
a.o : a.c a.h b.h
b.o : b.c b.h
c.o : c.c c.h b.h
clean:
rm -f $(OBJS) $(EXEC)
It creates the object files but it doesn't create the executable file - prog.
How do I fix it?
Thanks!
$(EXEC): $(OBJS)
$(CC) -o $# $(CFLAGS) $(OBJS)
Basically, when you list multiple objects as dependencies, the implicit rules can't be used, so you have to write the command to execute yourself. The $# is a shorthand for $(EXEC) in this case; it is the target being created.

How to define rules in the Makefile to compile only that *.cpp files which was modified (and their dependencies), not all *.cpp files

Lets say I have files:
Libs:
one.cpp, one.h
two.cpp, two.h
three.cpp, three.h
Program:
program.cpp
Is there way, to create Makefile which will compile only that *.cpp which were modified from last compilation?
Currently I have something like that:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: $(OBJS) program
.cpp.o:
g++ -Wall -c $<
program:
g++ -Wall $(OBJS) program.cpp -o program
clean:
rm -f $(OBJS) program
I works fine, but when I compile my program and then change two.cpp or two.h I need to run "make clean" first, because when I secondly run "make" I get:
Nothing to be done for 'all'.
I would like to change my Makefile in that way, it would recognize my changes and recompile that file and its dependencies (if one.cpp uses code from two.cpp which was modified, both files should be recompiled).
So if I modify two.cpp, make should do:
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
But if one.cpp uses code from two.cpp which was modified, make shold do:
g++ -Wall -c one.cpp
g++ -Wall -c two.cpp
g++ -Wall $(OBJS) program.cpp -o program
First we make the object files prerequisites of the executable. Once this is done, Make will rebuild program whenever one of the SRCS changes, so we don't need OBJS as an explicit target:
all: program
program: $(OBJS)
g++ -Wall $(OBJS) program.cpp -o program
Then we make the header files prerequisites of the objects, so that if we change three.h, Make will rebuild three.o:
$(OBJS): %.o : %.h
And finally since one.cpp uses code from two.cpp by means of two.h (I hope), we make two.h a prerequisite of one.o:
one.o: two.h
And to make things cleaner and easier to maintain we use automatic variables:
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
Put it all together and we get:
SRCS = one.cpp two.cpp three.cpp
OBJS = $(SRCS:.cpp=.o)
all: program
$(OBJS): %.o : %.h
one.o: two.h
.cpp.o:
g++ -Wall -c $<
program: $(OBJS)
g++ -Wall $^ program.cpp -o $#
clean:
rm -f $(OBJS) program
There are a few more things we could do (like adding program.o to OBJS), but this is enough for today.
Add the files a command depends upon to run to the right of the target name.
Example:
default: hello.c
gcc -o hello.bin hello.c
install: hello.bin
cp hello.bin ../
All you need to do is tell make that the .o file depends on the .cpp file:
%.cpp.o: %.cpp
g++ -Wall -c -o $# $<

Resources