Apply the same compilation command to several source files - makefile

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?

Related

How to copy target file to a sub folder in Makefile?

In this Makefile- I want to copy the $(TGT) binary file after compiled to a sub folder(test) in the same directory. How can I include the copy command of the compiled target file in the Makefile?
CC = g++
CFLAGS = -ansi -std=c++11
LIBS = -L/usr/lib -lstdc++
DEPS = foo.cpp
OBJ = foo.o
TGT+=foo
%.o: %.cc $(DEPS)
$(CC) -c $< $(CFLAGS) -o $#
all: $(TGT)
$(TGT): $(OBJ)
$(CC) $^ $(CFLAGS) $(LIBS) -o $#
# TODO: Need to include the copy command for copying TGT to test folder.
clean:
rm -f *.o $(TGT)
Currently the folder structure is-
<foo>
Makefile
foo.cpp
foo.h
<test>
<..Need "foo" inside this folder>
Is there some reason you can't just change the recipe to copy the file?
Change:
$(TGT): $(OBJ)
$(CC) $^ $(CFLAGS) $(LIBS) -o $#
To:
$(TGT): $(OBJ)
$(CC) $^ $(CFLAGS) $(LIBS) -o $#
cp $# test
You can easily add a rule to copy a file:
all: test/$(TGT)
test/$(TGT): $(TGT)
cp $< $#

Makefile multiple sources ouputs variable expansion

suppose CC variable is a compiling command and we don't need any additional flags. Simple part of makefile compiling main.c and next.c to main.o and next.o:
all: main.o next.o
%.o : %.c
$(CC) $< -o $#
Now suppose I would like to have output files in variable:
all: $(OBJ)
OBJ = main.o next.o
%.o : %.c
$(CC) $< -o $#
Of course it won't work. I understand why but I can't find solution. Can you help me?

How to move .o on project folder?

I wrote this Makefile to move all .o of the project inside a directory 'obj' in the main folder.
Directories
.:
actor/ lib/ Controller.cpp Controller.h Controller.o doc.txt main.cpp main.o Makefile uno VRP*
./actor:
Customer.cpp Customer.h Customer.o Depot.cpp Depot.h Depot.o Route.cpp Route.h Route.o Vehicle.cpp Vehicle.h Vehicle.o
./lib:
Search.cpp Search.h Search.o Utils.cpp Utils.h Utils.o VRP.cpp VRP.h VRP.o
Makefile
CXX=g++
RM=rm -rf
BIN_NAME=VRP
CPPFLAGS=-s -O2 -std=gnu++11 -Wall
SRCS=$(wildcard *.cpp actor/*.cpp lib/*.cpp)
OBJS=$(subst .cpp,.o,$(SRCS))
all: $(OBJS_DIR) $(BIN_NAME)
$(OBJS_DIR):
mkdir $(OBJS_DIR)
$OBJS_DIR)/%.o : $(SRCS)
$(CXX) $(CPPFLAGS) -c $< -o $#
$(BIN_NAME) : $(OBJS)
$(CXX) -o $# $^
debug:
$(CXX) -g $(CPPFLAGS) -o $(BIN_NAME) $(OBJS)
.PHONY : all clean
clean:
$(RM) $(OBJS) $(OBJS_DIR)
dist-clean: clean
$(RM) $(BIN_NAME)
How can I make it works?
This line $OBJS_DIR)/%.o : $(SRCS) sets the prerequisites of every file that matches $OBJS_DIR)/%.o to all the files in $(SRCS) that's not even close to what you want. (It is also a typo. You are missing the opening ().
You can't write a single rule for what you are trying to do here you need three pattern rules (or one with a vpath/VPATH setup).
$(OBJS_DIR)/%.o: %.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
$(OBJS_DIR)/%.o: actor/%.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
$(OBJS_DIR)/%.o: lib/%.cpp
$(CXX) $(CPPFLAGS) -c $< -o $#
That being said you don't actually have any targets that match $(OBJS_DIR)/%.o since the value of $(OBJS) is Controller.o ... actor/Customer.o ... lib/Search.o. To fix that you also need:
OBJS=$(addprefix $(OBJS_DIR)/,$(patsubst %.cpp,%.o,$(notdir $(SRCS))))
$(notdir) to get just the filename from the source files.
$(patsubst) instead of $(subst) just for correctness (subst would have modified a Bar.cpp.cpp file to Bar.o.o).
$(addprefix) to add the $(OBJS_DIR) prefix to the bare object file names.

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 $#

Resources