Updating Makefile to fit today standards - c++

I have been provided the following Makefile. I am supposed to compile a somewhat complicated project but the Makefile itself doesn't do it, even though I am trying to modify it to make it work. I am studying the GNU manual but the Makefile I have is written in a very old style and I am not able to fix it. Could someone help me translating it to today standards while maintaining functionality?
The line:
$(EXE): $(OBJS)
bla=;
for file in $(OBJS); do bla="$$bla ` $$file`"; done; \
$(CXX) $(CXXLINKFLAGS) $(CXXFLAGS) -o $# $$bla $(ADDLIBS) $(LIBS)
Is the one I am mainly interested in.
This is the complete Makefile:
# //////////////// NOMBRE DEL PROYECTO ///////////////////
#
P=project
#
EXE=$(P)
OBJS=main.o model.o param.o head.h
ADDLIBS=-D.
ADDINCFLAGS=-I.
SRCDIR=/root/projects/project
##########
CXX=g++
CXXFLAGS=-O3 -fomit-frame-pointer -pipe -DNDEBUG -pedantic-errors -Wparentheses -Wreturn-type -Wcast-qual -Wall -Wpointer-arith -Wwrite-strings -Wconversion -I$(COININCDIR)
CXXLINKFLAGS=-Wl,--rpath -Wl,/installed/CoinAll/lib
CC=gcc
CFLAGS=-03 -fomit-frame-pointer -pipe -DNDEBUG -pedantic-errors -Wimplicit -Wparentheses -Wsequence-point -Wreturn-type -Wcast-qual -Wall
COININCDIR=/installed/CoinAll/include/coin
COINLIBDIR=/installed/CoinAll/lib
LIBS=-L$(COINLIBDIR) -lCbc -lCgl -lOsiClp -lOsi -lClp -lCoinUtils -lm \
`cat $(COINLIBDIR)/cgl_addlibs.txt` \
`cat $(COINLIBDIR)/clp_addlibs.txt` \
`cat $(COINLIBDIR)/coinutils_addlibs.txt`
# LIBS=-L$(COINLIBDIR) -lClp -lCoinUtils \
# -lm `cat $(COINLIBDIR)/coinutils_addlibs.txt`
INCL=-I`$(COININCDIR)`$(ADDINCFLAGS)
all: $(EXE)
.SUFFIXES: .cpp .c .o .obj
$(EXE): $(OBJS)
bla=;
for file in $(OBJS); do bla="$$bla ` $$file`"; done; \
$(CXX) $(CXXLINKFLAGS) $(CXXFLAGS) -o $# $$bla $(ADDLIBS) $(LIBS)
.cpp.o:
$(CXX) $(CXXFLAGS) $(INCL) -c -o $# `test -f '$<' || echo '$(SRCDIR)/'`$<
.cpp.obj:
$(CXX) $(CXXFLAGS) $(INCL) -c -o $# `if test -f '$<'; then '$<'; else '$(SRCDIR)/$<'; fi`
.c.o:
$(CC) $(CFLAGS) $(INCL) -c -o $# `test -f '$<' || echo '$(SRCDIR)/'`$<
.c.obj:
$(CC) $(CFLAGS) $(INCL) -c -o $# `if test -f '$<'; then '$<'; else '$(SRCDIR)/$<'; fi`

The first question is are the entries in `$(OBJS) really commands that are intended to be run for their output and then have their output used in the link line?
Because if not then the backticks are incorrect and the entire loop can be dropped and that body replaced with:
$(CXX) $(CXXLINKFLAGS) $(CXXFLAGS) -o $# $(OBJS) $(ADDLIBS) $(LIBS)
Given that the value of $(OBJS) is main.o model.o param.o head.h (and ignoring the fact that having a .h file in a list of objects is bizarre) I think that the above is likely correct.
But, just for completeness, let us assume that it isn't and that those objects do, in fact, wish to be executed for output. In that case the body could be replaced by:
$(CXX) $(CXXLINKFLAGS) $(CXXFLAGS) -o $# $(patsubst %,`%`,$(OBJS)) $(ADDLIBS) $(LIBS)
Two last comments. There is no reason to have the space inside the backticks (assuming they are correct in the first place) and there is likely no reason to pre-declare $bla= like that.

Related

GNU Make: A better way of using both C/C++ targets with different commands

Q: Here is my Makefile fragment below:
SRCS+=$(wildcard *.c *.cpp)
OBJECTS=$(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(SRCS:.cpp=.o)))
# .....
$(OBJ_DIR)/%.o: %.cpp
$(CXX) -ggdb -Wall -Wextra -Werror $(INC) $(C_FLAGS) -c -o $# $<
$(OBJ_DIR)/%.o: %.c
$(CC) -ggdb -Wall -Wextra -Werror $(INC) $(C_FLAGS) -c -o $# $<
How can I refactor expression after "OBJECTS" and remove duplication of the similar rules for .cpp and .%c?
OBJECTS := $(patsubst %,$(OBJ_DIR)/%.o,$(basename $(SRCS)))
# Note that you may not need this variable at all.
COMPILE_ARGS = -ggdb -Wall -Wextra -Werror $(INC) $(C_FLAGS) -c -o $# $<
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(COMPILE_ARGS)
$(OBJ_DIR)/%.o: %.c
$(CC) $(COMPILE_ARGS)

C++ Makefile. .o in different subdirectories

I have some problems trying to put .o files into a separate directory (/build).
Actually, my sources (in /src) contain some subdirectories, and my Makefile only create the .o of the .cpp contained at the first "level". The other .o are just ignored, so, the target cannot be created.
In my /src directory, I have "three levels" (src/first/second/).
Here's the code of the Makefile :
CC=g++
CFLAGS=-W -Wall -ansi -pedantic -s -O3 -Os -std=c++11 -fpermissive
LDFLAGS= -lboost_system -lboost_regex
SRCDIR=src
HEADDIR=include
LIBDIR=build
BINDIR=bin
BIN=LTN
SRC = $(wildcard src/*.cpp src/*/*.cpp src/*/*/*.cpp)
OBJ = $(patsubst %.cpp,$(LIBDIR)/%.o,$(SRC))
all: $(BIN)
LTN: $(OBJ)
$(CC) -o $(BINDIR)/$# $^ $(LDFLAGS)
$(LIBDIR)/$(SRCDIR)/%.o: $(SRCDIR)/%.cpp $(HEADDIR)/%.h
$(CC) -o $# -c $< $(CFLAGS)
.PHONY = clean
You can try this:
CC=g++
CFLAGS=-W -Wall -ansi -pedantic -s -O3 -Os -std=c++11 -fpermissive
LDFLAGS= -lboost_system -lboost_regex
SRCDIR=src
HEADDIR=include
LIBDIR=build
BINDIR=bin
BIN=LTN
SRC=$(shell find . -name '*.cpp')
TMP=$(subst $(SRCDIR),$(LIBDIR), $(SRC))
OBJ=$(patsubst %.cpp,%.o,$(TMP))
all: $(BIN)
LTN: $(OBJ)
#[ ! -d $(BINDIR) ] & mkdir -p $(BINDIR)
$(CC) -o $(BINDIR)/$# $^ $(LDFLAGS)
$(LIBDIR)/%.o: $(SRCDIR)/%.cpp
#[ ! -d $(dir $#) ] & mkdir -p $(dir $#)
$(CC) -o $# -c $< $(CFLAGS)
.PHONY = clean

How to expand makefile variable in prerequisites list?

I am having an issue defining a prerequisites for my targets while using file lists in variables the problem is as follows:
in my makefile:
... some basic defines
SOURCES=HelloC.cpp \
HelloS.cpp \
HelloI.cpp \
main.cpp
SOURCES_CLIENT=Hello_Client_impl.cpp \
HelloC.cpp
OBJECTS_SERVER_DIR=obj_s/
OBJECTS_CLIENT_DIR=obj_c/
OBJECTS_SERVER=$(addprefix $(OBJECTS_SERVER_DIR),$(SOURCES:.cpp=.o))
OBJECTS_CLIENT=$(addprefix $(OBJECTS_CLIENT_DIR),$(SOURCES_CLIENT:.cpp=.o))
EXECUTABLE_SERVER=server
EXECUTABLE_CLIENT=client
all: dirs server_exe client_exe
dirs:
#echo create dirs
$(CREATE_DIR) $(OBJECTS_SERVER_DIR)
$(CREATE_DIR) $(OBJECTS_CLIENT_DIR)
server_exe: $(EXECUTABLE_SERVER)
client_exe: $(EXECUTABLE_CLIENT)
$(EXECUTABLE_SERVER): $(OBJECTS_SERVER)
$(CXX) $^ $(LFLAGS) $(LIBS) -o $#
$(EXECUTABLE_CLIENT): $(OBJECTS_CLIENT)
$(CXX) $^ $(LFLAGS) $(LIBS) -o $#
# problematic line 1
$(OBJECTS_SERVER): $(SOURCES)
$(CXX) -c $(CPPFLAGS) -o $# $<
# problematic line 2
$(OBJECTS_CLIENT): %.o : %.cpp
$(CXX) -c $(CPPFLAGS) -o $# $<
Running it (as dry run) I will get:
$ make -n
echo create dirs
mkdir -p obj_s/
mkdir -p obj_c/
g++ -c -Wall -I. -I/usr/include/ -I/usr/include/orbsvcs/ -I/usr/include/tao/ -I/usr/include/tao/PortableServer/ -o obj_s/HelloC.o HelloC.cpp
g++ -c -Wall -I. -I/usr/include/ -I/usr/include/orbsvcs/ -I/usr/include/tao/ -I/usr/include/tao/PortableServer/ -o obj_s/HelloS.o HelloC.cpp
g++ -c -Wall -I. -I/usr/include/ -I/usr/include/orbsvcs/ -I/usr/include/tao/ -I/usr/include/tao/PortableServer/ -o obj_s/HelloI.o HelloC.cpp
g++ -c -Wall -I. -I/usr/include/ -I/usr/include/orbsvcs/ -I/usr/include/tao/ -I/usr/include/tao/PortableServer/ -o obj_s/main.o HelloC.cpp
g++ obj_s/HelloC.o obj_s/HelloS.o obj_s/HelloI.o obj_s/main.o -L/usr/lib64/ -lTAO_PortableServer -lTAO_AnyTypeCode -lTAO -lACE -o server
make: *** No rule to make target `obj_c/Hello_Client_impl.cpp', needed by `obj_c/Hello_Client_impl.o'. Stop.
problematic line 1 will not expand and will always keep the first source file (HelloC.cpp) as a parameter while the second one is defined with prefix. How can I handle this so that it compiles? I would like to have source files in root dir and object files in obj_c and obj_s directories
EDIT: I originally answered the wrong question in haste, sorry about that. Anyway, the static pattern rule is the way to go, but you have to factor in the prefix. Instead of
$(OBJECTS_CLIENT): %.o : %.cpp
Use
$(OBJECTS_CLIENT): $(OBJECTS_CLIENT_DIR)%.o : %.cpp

Makefile for shared library that only compiles changed files?

I am working on a project where I am creating a .so object as my output that contains several operators for use in another program. I was given a Makefile that works just fine, except it always recompiles every file whenever I run make. Originally this was not an issue, but now that there are upwards of five or more operators in the library, running make is prohibitively slow. The trouble is that for the life of me, I can't figure out how to change this Makefile into one that behaves the way I want since I've never dealt with Makefiles in this format before:
BOOST_LOCATION=/usr/local/boost_1_54_0
CFLAGS=-pedantic -W -Wextra -Wall -Wno-strict-aliasing -Wno-long-long -Wno-unused-parameter -fPIC -D__STDC_FORMAT_MACROS -Wno-system-headers -isystem -O2 -g -DNDEBUG -ggdb3 -D__STDC_LIMIT_MACROS
INC=-I. -DPROJECT_ROOT="\"$(IN_SOURCE_DIR)\"" -I"$(IN_SOURCE_DIR)/include" -I"$(BOOST_LOCATION)"
LIBS=-L"$(IN_SOURCE_DIR)/lib" -shared -Wl,-soname,libname.so -L. -lm
all:
#if test ! -d "$(IN_SOURCE_DIR)"; then echo "Error. Try:\n\nmake IN_SOURCE_DIR=<PATH TO SOURCE TRUNK>"; exit 1; fi
$(CXX) $(CFLAGS) $(INC) -o plugin.cpp.o -c plugin.cpp
$(CXX) $(CFLAGS) $(INC) -o LogicalFile1.cpp.o -c File1/LogicalFile1.cpp
$(CXX) $(CFLAGS) $(INC) -o PhysicalFile1.cpp.o -c File1/PhysicalFile1.cpp
$(CXX) $(CFLAGS) $(INC) -o LogicalFile2.cpp.o -c File2/LogicalFile2.cpp
$(CXX) $(CFLAGS) $(INC) -o PhysicalFile2.cpp.o -c File2/PhysicalFile2.cpp
### etc.
$(CXX) $(CFLAGS) $(INC) -o libname.so \
plugin.cpp.o \
LogicalFile1.cpp.o \
PhysicalFile1.cpp.o \
LogicalFile2.cpp.o \
PhysicalFile2.cpp.o \
### etc \
$(LIBS)
clean:
rm -f *.o *.so
The biggest issue I have is that there is only one rule (all), and I cannot find an example of a Makefile that does this or how to split it into multiple rules.
In this case, it's actually pretty straightforward. Right now, you just have an all target that's doing all the building. You need to break out the compiler invocations and link step into their own rules, and you should be off to the races:
BOOST_LOCATION=/usr/local/boost_1_54_0
CFLAGS=-pedantic -W -Wextra -Wall -Wno-strict-aliasing -Wno-long-long -Wno-unused-parameter -fPIC -D__STDC_FORMAT_MACROS -Wno-system-headers -isystem -O2 -g -DNDEBUG -ggdb3 -D__STDC_LIMIT_MACROS
INC=-I. -DPROJECT_ROOT="\"$(IN_SOURCE_DIR)\"" -I"$(IN_SOURCE_DIR)/include" -I"$(BOOST_LOCATION)"
LIBS=-L"$(IN_SOURCE_DIR)/lib" -shared -Wl,-soname,libname.so -L. -lm
all: plugin.cpp.o LogicalFile1.cpp.o PhysicalFile1.cpp.o LogicalFile2.cpp.o PhysicalFile2.cpp.o
$(CXX) $(CFLAGS) $(INC) -o libname.so \
plugin.cpp.o \
LogicalFile1.cpp.o \
PhysicalFile1.cpp.o \
LogicalFile2.cpp.o \
PhysicalFile2.cpp.o \
### etc \
$(LIBS)
plugin.cpp.o: plugin.cpp | test
$(CXX) $(CFLAGS) $(INC) -o plugin.cpp.o -c plugin.cpp
LogicalFile1.cpp.o: File1/LogicalFile1.cpp | test
$(CXX) $(CFLAGS) $(INC) -o LogicalFile1.cpp.o -c File1/LogicalFile1.cpp
PhysicalFile1.cpp.o: File1/PhysicalFile1.cpp | test
$(CXX) $(CFLAGS) $(INC) -o PhysicalFile1.cpp.o -c File1/PhysicalFile1.cpp
LogicalFile2.cpp.o: File2/LogicalFile2.cpp | test
$(CXX) $(CFLAGS) $(INC) -o LogicalFile2.cpp.o -c File2/LogicalFile2.cpp
PhysicalFile2.cpp.o: File2/PhysicalFile2.cpp | test
$(CXX) $(CFLAGS) $(INC) -o PhysicalFile2.cpp.o -c File2/PhysicalFile2.cpp
test:
#if test ! -d "$(IN_SOURCE_DIR)"; then echo "Error. Try:\n\nmake IN_SOURCE_DIR=<PATH TO SOURCE TRUNK>"; exit 1; fi
clean:
rm -f *.o *.so
.PHONY: all clean test
From this point, you can simplify further, too. You could consolidate all of the compile lines into a single pattern rule, for example.
If you're willing to use the standard formats and built-in rules for make, you can write your entire makefile as easily as this:
ifeq (,$(wildcard $(IN_SOURCE_DIR)/.))
$(error Try: make IN_SOURCE_DIR=<PATH TO SOURCE TRUNK>)
endif
OBJECTS = plugin.o LogicalFile1.o PhysicalFile1.o LogicalFile2.o PhysicalFile2.o ### etc
BOOST_LOCATION = /usr/local/boost_1_54_0
CPPFLAGS = -DNDEBUG -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I. -DPROJECT_ROOT="\"$(IN_SOURCE_DIR)\"" -I"$(IN_SOURCE_DIR)/include" -I"$(BOOST_LOCATION)"
CXXFLAGS = -pedantic -W -Wextra -Wall -Wno-strict-aliasing -Wno-long-long -Wno-unused-parameter -fPIC -Wno-system-headers -isystem -O2 -g -ggdb3
LDFLAGS = -L"$(IN_SOURCE_DIR)/lib" -L.
LDLIBS = -shared -Wl,-soname,libname.so -lm
all: libname.so
libname.so: $(OBJECTS)
$(LINK.cc) $^ $(LDLIBS) -o $#
clean:
rm -f *.o *.so
.PHONY: all clean

creating a makefile for multiple targets

i have created a Makefile which i would change so, that it will generate more then one target when i run make.
In my program i use self predefined macros (e.g. TIME, REG and _DEBUG ) and i would like to have my Makefile i that way that it will generate one target with out predefined macros, one with REG and another one with REG and TIME.
I hope that what i wish is a reasonable wish from Makefile, if not, then please let me know.
P.S.:
recommendations would be gladly excepted
I am using
Here is my Makefile:
CXX = g++
SOURCES = random.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECUTABLE = random-64bit
DEBUG = -g -p -ggdb
CXXFLAGS = -Wall -ansi -pedantic -W -pipe -O3 -std=gnu++0x -march=native \
--fast-math -ftree-vectorize -ffast-math -D NDEBUG \
-D TIME -D REG -D _DEBUG
#CXXFLAGS+=$(DEBUG)
DEPS = def_type.hpp \
ls_regression.hpp \
network.hpp \
statistics.hpp \
knot.hpp \
nachbarn.hpp \
$(SOURCES:.cpp=.hpp) \
zufallszahlengenerator.hpp
INCLUDES = -I/home/phymihsa/eigen/ -I/home/phymihsa/boost_1_48_0
LIBPATH = -L/usr/local/lib64
LDFLAGS = -lm
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS) $(DEPS)
$(CXX) $(LIBPATH) $(OBJECTS) -o $#
.cpp.o: $<
$(CXX) $(LIBPATH) $(INCLUDES) $(LDFLAGS) $(CXXFLAGS) -c $<
%.o: %.cpp
$(CXX) $(LIBPATH) $(INCLUDES) $(LDFLAGS) $(CXXFLAGS) -c $<
.PHONY: clean
clean:
rm -rf $(OBJECTS) $(EXECUTABLE) *~ p1 *.o
EDIT
Based on the answer of #trojanfoe, i would to know if it is possible to use arrays
OBJECTS = $(SOURCES:.cpp=_none.o) $(SOURCES:.cpp=_reg.o) $(SOURCES:.cpp=_reg_time.o)
EXECUTABLE = $(SOURCES:.cpp=_none) $(SOURCES:.cpp=_reg) $(SOURCES:.cpp=_reg_time)
instead of each one writing each one specific?
Here is what i was searching for:
CXX = g++
OPTIONS := none reg reg_inter reg_time
none_CXXFLAGS :=
reg_CXXFLAGS := -D REG
reg_inter_CXXFLAGS := $(reg_CXXFLAGS) -D INTERMEDIATE_STEP
reg_time_CXXFLAGS := $(reg_CXXFLAGS) -D TIME
EXECUTABLES = $(addprefix random_,$(OPTIONS))
DEBUG = -g3 -p -ggdb
CXXFLAGS = -Wall -ansi -pedantic -W -pipe -O3 -std=gnu++0x -march=core2 -mtune=core2 \
--fast-math -ftree-vectorize -ffast-math -D NDEBUG
CXXFLAGS+=$(DEBUG)
DEPS = def_type.hpp \
ls_regression.hpp \
network.hpp \
statistics.hpp \
knot.hpp \
nachbarn.hpp \
zufallszahlengenerator.hpp
INCFLAGS = -I/usr/include/eigen3 -I/usr/include/boost_1_48
LIBPATH = -L/usr/lib64
LDFLAGS = -lm
.PHONY: all
all: $(EXECUTABLES)
random_%: random_%.o
$(CXX) $(LDFLAGS) $(LIBPATH) $^ -o $#
random_%.o : random.cpp $(DEPS)
$(CXX) $(INCFLAGS) $(CXXFLAGS) $($*_CXXFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJECTS) $(EXECUTABLES) *~ p1 *.o
in this solution there is a use of variables instead of writing each time the all text
regards
You'll need to generate 3 different versions of the object file from random.cpp and 3 different executables. Note $(CXXFLAGS) contains flags common across all 3 targets and I've also moved $(DEPS) to be a dependency of the object files, not the executable.
CXX = g++
SOURCES = random.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECUTABLE = random-64bit
DEBUG = -g -p -ggdb
CXXFLAGS = -Wall -ansi -pedantic -W -pipe -O3 -std=gnu++0x -march=native \
--fast-math -ftree-vectorize -ffast-math -D NDEBUG -D _DEBUG
#CXXFLAGS+=$(DEBUG)
DEPS = def_type.hpp \
ls_regression.hpp \
network.hpp \
statistics.hpp \
knot.hpp \
nachbarn.hpp \
$(SOURCES:.cpp=.hpp) \
zufallszahlengenerator.hpp
INCLUDES = -I/home/phymihsa/eigen/ -I/home/phymihsa/boost_1_48_0
LIBPATH = -L/usr/local/lib64
LDFLAGS = -lm
all: random_none random_reg random_reg_time
random_none: random_none.o
$(CXX) $(LDFLAGS) $(LIBPATH) random_none.o -o $#
random_reg: random_reg.o
$(CXX) $(LDFLAGS) $(LIBPATH) random_reg.o -o $#
random_reg_time: random_reg_time.o
$(CXX) $(LDFLAGS) $(LIBPATH) random_reg_time.o -o $#
random_none.o: random.cpp $(DEPS)
$(CXX) $(INCLUDES) $(CXXFLAGS) -c $<
random_reg.o: random.cpp $(DEPS)
$(CXX) $(INCLUDES) $(CXXFLAGS) -D REG -c $<
random_reg_time.o: random.cpp $(DEPS)
$(CXX) $(INCLUDES) $(CXXFLAGS) -D REG -D TIME -c $<
.PHONY: clean
clean:
rm -rf *.o random_none random_reg random_reg_time *~ p1
For each file, create one target per compile flag variant.
Say you have a program that depends on two files, foo.cc and bar.cc. You want to compile a debug and a release version. You'll do something like this:
DEBUG = -g -Wall -D DEBUG
RELEASE = ...
foo_debug.o: foo.cc
g++ -o foo_debug.o -c foo.cc $(DEBUG)
foo_release.o: foo.cc
g++ -o foo_release.o -c foo.cc $(RELEASE)
# Same thing for bar ...
main_debug: foo_debug.o bar_debug.o
g++ -o main_debug foo_debug.o bar_debug.o
main_release: foo_release.o bar_release.o
g++ -o main_release foo_release.o bar_release.o