Generate makefile targets from a list of source files - makefile

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.

Related

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.

How to convert a source c files to corresponding .o files using suffix rule in 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)

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.

Apply the same compilation command to several source files

Let's say I have several .cpp files which are built by the same way:
main.o : main.cpp
$(CC) -c main.cpp $(COMPILATION_FLAGS)
file1.o : file1.cpp
$(CC) -c file1.cpp $(COMPILATION_FLAGS)
file2.o : file2.cpp
$(CC) -c file2.cpp $(COMPILATION_FLAGS)
How can I write this command only once, and then apply it to main, file1 and file2, to exclude code duplication?
http://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html
http://www.gnu.org/software/make/manual/html_node/Pattern-Examples.html#Pattern-Examples
Something like
%.o : %.cpp
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
should do what you want.
Why don't you use CFLAGS and CPPFLAGS rather than COMPILATION_FLAGS?

Resources