Make, Endpoints that differ by precompiler-flag - c++

Using make, I need to produce two versions of an executable, which differ by the use of a precompiler flag DXYZ. The way I have this working so far is to produce the *.o objects for the vanilla program, and, another set *.o_xyz for the objects that make use of the -DXYZ flag.
So basically I have two two rules to produce the objects, ie: $(OBJ)/%.o: %.cpp and $(OBJ)/%.o_xyz: %.cpp.
I am wondering if this is this the best way to achieve this? Is it possible to reduce this to a single rule?
CXX=g++
OBJ=./obj
BIN=./bin
INC=-I./inc
CXXFLAGS=-std=c++11 -Wall -Wno-comment
LDFLAGS=-lpthread
CXX_SOURCES=$(wildcard *.cpp)
CXX_OBJECTS=$(patsubst %.cpp, $(OBJ)/%.o,$(notdir $(CXX_SOURCES)))
.PHONY: all
all : program_xyz program
program_xyz: $(addsuffix _xyz,$(CXX_OBJECTS))
#mkdir -p $(BIN)
$(CXX) -o $(BIN)/$# $^ $(LDFLAGS) $(INC) -DXYZ
program: $(CXX_OBJECTS)
#mkdir -p $(BIN)
$(CXX) -o $(BIN)/$# $^ $(LDFLAGS) $(INC)
##Vanilla Endpoints
$(OBJ)/%.o: %.cpp
#mkdir -p $(#D)
$(CXX) -c $< -o $# $(INC) $(CXXFLAGS)
##Endpoint with DXYZ flag
$(OBJ)/%.o_xyz: %.cpp
#mkdir -p $(#D)
$(CXX) -c $< -o $# $(INC) $(CXXFLAGS) -DXYZ

Related

How can I use different rules in Makefile for two groups of files?

I have one Makefile to build an executable and a library. Executable consists of a lot of source files and library consists of one .cpp file. The difference between compilation of executable and library is -fPIC option.
There is a compilation rule:
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
all: $(TARGET) $(TARGET_LIB)
$(TARGET): $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
$(TARGET_LIB): $(LIBOBJS)
$(CXX) $(LDFLAGS) -fPIC -shared -o $# $^
I tried to add compilation rule for library and got this:
lib.o : lib.cpp
$(CXX) -fPIC -c $(CXXFLAGS) $< -o $#
%.o : %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
all: $(TARGET) $(TARGET_LIB)
$(TARGET): $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^
$(TARGET_LIB): $(LIBOBJS)
$(CXX) $(LDFLAGS) -fPIC -shared -o $# $^
Unfortunately, only lib is compiled in this case. Second rule is omitted.
How can I use a rule for one file and different rule for group of other files?
If you just run make without a target, the first target gets built. So just put all back at the top and it should work fine.

How to compile multiple file types in the same way using Make

In a Makefile i have the following two semi-generic targets to handle compilation of any .cc and .cpp files:
$(OBJ_DIR)/%.o: %.cc
mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCDIRS) -c $< -MD -o $#
$(OBJ_DIR)/%.o: %.cpp
mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCDIRS) -c $< -MD -o $#
Seeing as they are very similar (only the file extension differs), could i merge them somehow to create one generic target for both file types?
In general, no, you cannot combine them. You have two options. The first is to use an eval statement as in the answer linked to by Amon Zilca.
The other is to just keep the recipe in a variable and re-use that:
define COMPILE
mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCDIRS) -c $< -MD -o $#
endef
$(OBJ_DIR)/%.o: %.cc
$(COMPILE)
$(OBJ_DIR)/%.o: %.cpp
$(COMPILE)
Personally I like this method better; the eval method just feels like overkill to me unless you have a LOT of extensions, or you want to make it easy to add more just by tweaking a variable.
Oh, note you can use $(#D) instead of $(dir $#), as well.

Makefile pattern rules differences

What is the difference between .cpp.o:, .o: and %.o: %.c?
Here's a simple Makefile example:
CC=g++
CFLAGS=-c -Wall
SOURCES=file1.cpp file2.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=program
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) -o $#
#.o:
#.cpp.o:
%.o: %.c
$(CC) $(CFLAGS) $< -o $#
all: $(SOURCES) $(EXECUTABLE)
clean:
rm -rf $(OBJECTS) $(EXECUTABLE)
I have noticed that the output is same, but I guess they are interpreted on a different way internally.
Is there a preferred way of doing this?
.cpp.o: # build *.o from *.cpp (old style notation)
%.o: %.c # build *.o from *.c (new style notation)
Both work but the new style is more powerful because it allows you to write more complicated constructions thanks to pattern matching:
%.uuu: %.vvv %.www

Makefile improvements: several executables & directories

I have this working Makefile and I would like to improve it:
CXX = g++
RM = rm -f
CXXFLAGS = -O2 -s -Wall -std=c++11
LDFLAGS = -Wl,-z,relro
SRCS = target1.cpp target2.cpp target3.cpp utils.cpp
OBJS = $(subst .cpp,.o,$(SRCS))
.PHONY: all target1 target2 target3 clean
all: target1 target2 target3
target1: target1.o utils.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
target2: target2.o utils.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
target3: target3.o utils.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
clean:
$(RM) $(OBJS)
My questions are:
Every target needs utils.o. Is it possible to avoid writing 3 times the same lines for target1/target2/target3?
I would like to separate sources, objects and binaries (Makefile in ./, binaries in ./, sources in src/, objects in obj/). What is the best solution in order to avoid writing target1: obj/target1.o obj/utils.o and so on?
Thanks!
1) Yes, you can use a pattern rule:
target%: target%.o utils.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
2) It really isn't that bad:
target%: obj/target%.o obj/utils.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
You can avoid those two obj/ prefixes, but it really isn't worth the trouble.

How to change my makefile to build into a separate folder

I have the following makefile:
CC=g++
CCOPTS=-Wall -Wextra -g
OBJS = manager.o tcpcon.o
TARGETS = manager
.PHONY: all clean
$(TARGETS) : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(TARGETS) $(OBJS)
clean:
rm -f $(TARGETS) $(OBJS)
%: %.cpp
$(CC) $(CCOPTS) -o $# $<
Is there a way I can make my .o and bin files be built into a directory called build? I tried going through some tutorials, but I guess I just don't fully understand makefiles..
Don't feel too bad; I'm not sure anyone fully understands makefiles.
BUILD_DIR = build
OBJS = $(BUILD_DIR)/manager.o $(BUILD_DIR)/tcpcon.o
TARGETS = $(BUILD_DIR)/manager
...
$(BUILD_DIR)/%.o: %.cpp
$(CC) -c $(CCOPTS) -o $# $<