How to use qmake file with google test and shared library - c++

I started with a makefile that would generate the dependencies of my C++ files. It was a C++ project using google test. Later, I started a Qt project which uses qmake and links to a shared library which the old makefile builds. Needless to say, the old makefile is really complicated now.
I would like to make a qmake file which can do the following:
Build a shared library for a list a sources
Build google test (optionally, I would accept a separate makefile for this)
Build my Qt executable with a different list of sources linking to the first shared library
All builds should have debug and release versions which will output to different directories
Can someone point me in the right direction for making a *.pro file which will do that? I'm really not clear on how to do things like multiple targets in qmake.
Here is the current makefile I am using (clearly a mess):
GTEST_DIR = /home/matt/lib/gtest-1.5.0
GMOCK_DIR = /home/matt/lib/gmock-1.5.0
SRC_DIR = /home/matt/Documents/myproject
QTINC := -I/usr/share/qt4/mkspecs/linux-g++ -I/usr/include/qt4/QtCore \
-I/usr/include/qt4/QtGui -I/usr/include/qt4
TEST_SRCS = test/TestRunner.cpp test/CellTest.cpp test/PuzzleTest.cpp \
test/SingleCandidateMethodTest.cpp test/ExclusionMethodTest.cpp \
test/BlockIntersectionMethodTest.cpp test/CoveringSetMethodTest.cpp \
test/SimpleValidatorTest.cpp test/PuzzleMarkerTest.cpp \
test/PlayerValidatorTest.cpp test/SolverHelperTest.cpp \
test/GuessCommandTest.cpp test/MarkCommandTest.cpp \
test/UnmarkCommandTest.cpp test/MethodSolverTest.cpp \
test/SimplePuzzleImporterTest.cpp test/SolvedPuzzleImporterTest.cpp \
test/AddHintMarksCommandTest.cpp test/CellControllerTest.cpp \
test/PuzzleControllerTest.cpp
QT_SRCS =
LIB_SRCS = Puzzle.cpp Cell.cpp SingleCandidateMethod.cpp ExclusionMethod.cpp \
BlockIntersectionMethod.cpp CoveringSetMethod.cpp SimpleValidator.cpp \
PuzzleMarker.cpp PlayerValidator.cpp SolverHelper.cpp GuessCommand.cpp \
MarkCommand.cpp UnmarkCommand.cpp MethodSolver.cpp \
SimplePuzzleImporter.cpp SolvedPuzzleImporter.cpp GameManager.cpp \
CellController.cpp AddHintMarksCommand.cpp GameController.cpp \
PuzzleController.cpp
DEPDIR = .deps
df = $(DEPDIR)/$(#F)
# preprocessor
CPPFLAGS += -I$(GTEST_DIR)/include -I$(GMOCK_DIR)/include -I$(SRC_DIR) $(QTINC)
# C++ compiler
CXXFLAGS = -Wall -std=c++0x
# qt defines
QTDEF = -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
# stuff to link for Qt
QTFLAGS = -L/usr/lib -lQtCore -lQtGui -lpthread
# gtest headers, don't need to change
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
# gmock stuff, don't need to change
GMOCK_HEADERS = $(GMOCK_DIR)/include/gmock/*.h \
$(GMOCK_DIR)/include/gmock/internal/*.h \
$(GTEST_HEADERS)
MAKEDEPEND = $(CXX) $(CPPFLAGS) -MM -o $(df).d $<
MAKEDEPEND_TEST = $(CXX) $(CPPFLAGS) -MM -o $(df).d -MT $(basename $<).o $<
MAKEDEPEND_QT = $(CXX) $(CPPFLAGS) -MM -o $(df).d -MT $(basename $<).o $<
SRCS := main.cpp $(LIB_SRCS)
OBJS := $(SRCS:%.cpp=%.o)
LIB_OBJS := $(LIB_SRCS:%.cpp=%.o)
QT_OBJS := $(QT_SRCS:%.cpp=%.o)
TEST_OBJS := $(TEST_SRCS:%.cpp=%.o)
# targets:
debug : CXXFLAGS += -g -O0
# removed this warning because it sucks: -Wconversion (int to size_t!)
debug_warn : CXXFLAGS += -pedantic -Wextra
debug_warn : debug
debug : all
release : CXXFLAGS += -O2
release : all
lib : CXXFLAGS += -fPIC
lib : libSudokuLib.so
libSudokuLib.so : $(LIB_OBJS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -shared -o libSudokuLib.so $(LIB_OBJS)
all : sudoku run_tests
sudoku : $(OBJS) $(QT_OBJS)
$(CXX) $(CPPFLAGS) $(QTDEF) $(CXXFLAGS) $(QTFLAGS) $^ -o $#
run_tests : $(LIB_OBJS) $(TEST_OBJS) gtest.a gmock.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $#
# dependency stuff
.D_TARGET:
mkdir -p $(DEPDIR)
touch $#
.PRECIOUS: .D_TARGET
# GTEST building stuff don't touch me
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
GMOCK_SRCS_ = $(GMOCK_DIR)/src/*.cc $(GMOCK_HEADERS)
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc
gmock-all.o : $(GMOCK_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
-c $(GMOCK_DIR)/src/gmock-all.cc
gmock_main.o : $(GMOCK_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
-c $(GMOCK_DIR)/src/gmock_main.cc
gmock.a : gmock-all.o gtest-all.o
$(AR) $(ARFLAGS) $# $^
gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc
gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $# $^
gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $# $^
# QT stuff
%Qt.o : %Qt.o .D_TARGET
$(MAKEDEPEND_QT);
#cp $(df).d $(df).P;
# sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
# -e '/^$$/ d' -e 's/$$/ :/' < $(df).d >> $(df).P;
#rm -f $(df).d
$(CXX) $(CPPFLAGS) $(QTDEF) $(CXXFLAGS) -o $# -c $<
# tests
%Test.o : %Test.cpp .D_TARGET $(GMOCK_HEADERS)
$(MAKEDEPEND_TEST);
#cp $(df).d $(df).P;
# sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
# -e '/^$$/ d' -e 's/$$/ :/' < $(df).d >> $(df).P;
#rm -f $(df).d
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
# objects from sources
%.o : %.cpp .D_TARGET
$(MAKEDEPEND);
#cp $(df).d $(df).P; \
# sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
# -e '/^$$/ d' -e 's/$$/ :/' < $(df).d >> $(df).P;
#rm -f $(df).d
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
-include $(QT_SRCS:%.cpp=$(DEPDIR)/%.o.P)
-include $(TEST_SRCS:test/%.cpp=$(DEPDIR)/%.o.P)
-include $(SRCS:%.cpp=$(DEPDIR)/%.o.P)
clean:
$(RM) $(OBJS) $(TEST_OBJS) $(QT_OBJS) \
gtest.a gtest_main.a gtest-all.o gtest_main.o \
.D_TARGET sudoku run_tests
rm -rf $(DEPDIR)
And here is the project.pro file for qmake (which relies on that first makefile instead of building the library itself)
TEMPLATE = app
TARGET = qtsudoku
DEPENDPATH += .
INCLUDEPATH += . ../myproject
CONFIG += qt warn_on debug
QMAKE_CXXFLAGS += -std=c++0x
LIBS += -L/home/matt/Documents/myproject -lSudokuLib
# Input
HEADERS += QtPuzzleModel.h QtPuzzleView.h QtGameApplication.h QtDirector.h \
QtMainWindow.h QtFactory.h
SOURCES += main.cpp QtPuzzleModel.cpp QtGameApplication.cpp QtDirector.cpp \
QtMainWindow.cpp QtFactory.cpp

In general, a good way to do something like this is with the SUBDIRS qmake template. You would make a qmake file for each of the items you want to build (shared library, google test, and the executable), then make a SUBDIRS template to do those in order. I think the subdirs template will provide the debug/release flags to each underlying make file.
For the shared library, the qmake library template should be fine.
I don't know about google test, I assume you could generate a qmake file for it if desired, or you could continue with the makefile.
For linking the two, you could make a qmake file that has a main.cpp, specifies the others as libraries, and builds an executable.
You can use DESTDIR, MOC_DIR, OBJECTS_DIR, and UI_DIR to change where generated files go.

Related

Extend C++ project with CMakeList.txt

I'm trying to transform old project with Makefile to a modern one with CMakeLists.txt and GoogleTest framework but i can't handle the dependencies.
This is my Project structure
Project-LG
src/
app/
main.cpp
A.cpp
A.hpp
B.cpp
B.hpp
C.cpp
C.hpp
...
cpp-utils/
D.cpp
D.hpp
E.hpp
F.hpp
json/
json.hpp
hiredis/ /*Makefile project*/
orane2/ /*Makefile project*/
rmr/ /*Makefile project*/
spdlog/ /*Headers project with nested directories*/
Makefile
And this is the "Project-LG" Makefile
CC=gcc
CPP=g++
SRCDIR = .
APPDIR = $(SRCDIR)/app
UTILSDIR = $(SRCDIR)/cpp-utils
TARGETDIR =./../out
OBJDIR =./../out/obj
APP_OBJDIR =$(OBJDIR)/app
UTILS_OBJDIR =$(OBJDIR)/cpp-utils
LIBSDIR = ./../libs
INCLUDE_FILE = \
-Iapp \
-Icpp-utils \
-Irmr/si \
-Irmr/si/si95 \
-Irmr/common \
-Ijson \
-Iorane2 \
-I. \
-Ihiredis
SUBDIRS := \
$(SRCDIR)/rmr \
$(SRCDIR)/orane2 \
$(SRCDIR)/hiredis
LFLAGS =
LIBS += -pthread -static-libstdc++ \
-L$(LIBSDIR) -l:librmr.a -l:liborane2.a -l:hiredis.a
XAPP_NAME_STR := '"app-lg"'
CFLAGS += -Wall -g -O2 -DXAPP_NAME=$(XAPP_NAME_STR) $(INCLUDE_FILE)
CPPFLAGS = $(CFLAGS) -fPIC -std=c++17
APP_EXE ?= xapp
APP_SOURCES := $(shell find $(APPDIR) -maxdepth 1 -name '*.cpp' -printf '%f\n')
UTILS_SOURCES := $(shell find $(UTILSDIR) -maxdepth 1 -name '*.cpp' -printf '%f\n')
APP_OBJS := $(addprefix $(APP_OBJDIR)/, $(APP_SOURCES:%.cpp=%.o))
UTILS_OBJS := $(addprefix $(UTILS_OBJDIR)/, $(UTILS_SOURCES:%.cpp=%.o))
.SUFFIXES: .c~.o
.PHONY: all $(SUBDIRS) clean
all: $(SUBDIRS) $(APP_EXE)
$(APP_EXE): $(APP_OBJS) $(UTILS_OBJS)
#mkdir -p $(TARGETDIR)
#mkdir -p $(OBJDIR)
$(CPP) $(CFLAGS) $(LFLAGS) $(APP_OBJS) $(UTILS_OBJS) $(LIBS) -o $(TARGETDIR)/$#
$(APP_OBJDIR)/%.o : $(APPDIR)/%.cpp
#mkdir -p $(OBJDIR)
#mkdir -p $(APP_OBJDIR)
$(CPP) -c $(CPPFLAGS) $(LFLAGS) $< -o $#
$(UTILS_OBJDIR)/%.o : $(UTILSDIR)/%.cpp
#mkdir -p $(OBJDIR)
#mkdir -p $(UTILS_OBJDIR)
$(CPP) -c $(CPPFLAGS) $(LFLAGS) $< -o $#
$(SUBDIRS):
$(MAKE) -C $#
clean:
rm -rf $(TARGETDIR)
It was difficult to figure out how to call the Makefile from CMake and how to add the GoogleTest framework with all its dependencies
Please accept my thanks for your time.

Header file dependancy not working

I have written below Makefile and as per answer to this question added rules for header file dependencies but it is not working. I did a clean and then build. After that I modified Parse.h using touch command and ran "make all" it says Test.exe is up to date. I got same output with just "make" command too.
Can anyone please let me know where am I gone wrong.
RM := rm -rf
MKDIR := mkdir -p
FIND := find
CPIO := cpio
CD := cd
MV := mv
# Set compiler flags
ifeq ($(BUILD_TYPE),DEBUG)
COMPILE_FLAGS= -c -fpic -DDBG=1 -g -DUSE_UTLPATMAT=1 -Wall
else ifeq ($(BUILD_TYPE),RELEASE)
COMPILE_FLAGS= -c -fpic -O3 -DUSE_UTLPATMAT=1 -Wall
else ifeq ($(BUILD_TYPE),PERF)
COMPILE_FLAGS= -c -fpic -O3 -DUSE_UTLPATMAT=1 -DPERF_COMPONENT -Wall
else
COMPILE_FLAGS= -c -fpic -O3 -DUSE_UTLPATMAT=1 -Wall
endif
export STFP_HOME = $(shell cd "$(CURDIR)/.."; pwd)
STFP_LIB = $(STFP_HOME)/lib
STFP_BIN = $(STFP_HOME)/bin
$(shell mkdir -p ${STFP_LIB})
$(shell mkdir -p ${STFP_BIN})
STFP_INC = $(CURDIR)/SP
SPTEST_SRC = $(CURDIR)/SPTest
SPTEST_INC = $(CURDIR)/SPTest
STFP_SRC = $(CURDIR)/SP
STFP_INC = $(CURDIR)/SP
UTILITIES_SRC_DIR = $(CURDIR)/../utilities
LIBS= -L${CLIENT_LIB}
INCS_DIRS= -I${CLIENT_INC}
#Subdivision Publisher Test
SPTESTSRCS=\
$(SPTEST_SRC)/Parse.cpp \
$(SPTEST_SRC)/Main.cpp
SPTESTOBJS=$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SPTESTSRCS)))
all := $(STFP_BIN)/Test.exe
#################### Main targets #####################################
all:$(all)
clean:
find $(STFP_SRC)/ -name "*.o" | xargs rm -rf
find $(SPTEST_SRC)/ -name "*.o" | xargs rm -rf
rm -rf $(STFP_LIB)
rm -rf $(STFP_BIN)
#######################################################################
$(STFP_BIN)/Test.exe: $(SPTESTOBJS)
$(CXX) -g $(INCS_DIRS) \
$(SPTESTOBJS) -o $# \
$(LIBS) -lmodpbase64 -lboost_regex -lboost_filesystem -lboost_system -lboost_serialization \
-lutility
%.o : %.cpp
$(CXX) -DPROVIDE_LOG_UTILITIES $(COMPILE_FLAGS) $(INCS_DIRS) -o $# $<
%.o : %.c
$(CC) -DPROVIDE_LOG_UTILITIES $(COMPILE_FLAGS) $(INCS_DIRS) -o $# $<
################# Dependencies #########################
depend: .depend
.depend: $(SPTESTSRCS)
rm -f .depend
$(CXX) -DPROVIDE_LOG_UTILITIES $(COMPILE_FLAGS) $(INCS_DIRS) -MM -$(SPTESTSRCS) > .depend
-include .depend
########################################################
Thanks
You seem to expect .o files in SPTest. You could do so by using:
SPTest/%.o: SPTest/%.cpp
$(CXX) -DPROVIDE_LOG_UTILITIES $(COMPILE_FLAGS) $(INCS_DIRS) -o $# $<
OR by using (where #D is directory and #F is filename):
%.o : %.cpp
$(CXX) -DPROVIDE_LOG_UTILITIES $(COMPILE_FLAGS) $(INCS_DIRS) -o $(#D)/$(#F) $<
Let me know if you still get errors.

How to write make files with auto dependancy generator

In expansion to my previous question how to write a makefile for structured file system:
The file structure:
.
├── Headers
│   ├── function.h
│   └── test.h
├── makefile
├── README.md
└── Sources
├── function.c
├── main.c
└── test.c
I'm trying to write a makefile that reads the #include<...> on any given source file and compile as required.
Originally I used to have a make file that looked like this:
INC_DIR = Headers
SRC_DIR = Sources
OBJ_DIR = Objects
#CXXFLAGS = -c -Wall -I. -IHeaders
CXXFLAGS = -c -Wall -I. -IHeaders
CC = gcc
SRCS = $(SRC_DIR)/*.c
OBJS = $(OBJ_DIR)/*.o
#The wildcard and patsubt commads will come handy
DEPS = $(INC_DIR)/*.h
#need to use an automatic dependency generator
output: $(OBJ_DIR)/main.o $(OBJ_DIR)/function.o
$(CC) $^ -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEPS)
$(CC) $(CXXFLAGS) $< -o $#
run: output
./output
clean:
rm $(OBJ_DIR)/*.o
rm output
-#echo "Clean completed"
That meant that for every source file that output was dependent on i had to add that object to this line.
output: $(OBJ_DIR)/main.o $(OBJ_DIR)/function.o $(OBJ_DIR)/test.o
$(CC) $^ -o $#
And is any other source file was dependent on one or more sources additional rules had to be added.
To solve this:
here is what I have gathered from Auto-Dependency Generation and 4.14 Generating Prerequisites Automatically
As mentioned by the community members, I have a mixed understanding of dependency generation and how to make use of the files generated.
DEP_DIR = .d
$(shell mkdir -p $(DEP_DIR) >/dev/null)
DEPFLAGS = -MT $# -MMD -MP -MF $(DEP_DIR)/$*.Td
INC_DIR = Headers
SRC_DIR = Sources
OBJ_DIR = Objects
$(shell mkdir -p $(OBJ_DIR) >/dev/null)
CXXFLAGS = -c -Wall -I. -IHeaders
CC = gcc
SRCS = $(SRC_DIR)/*.c
OBJS = $(OBJ_DIR)/*.o
#The wildcard and patsubt commads will come handy
#DEPS = $(INC_DIR)/*.h
MAKEDEPEND = $(CC) $(CXXFLAGS) $< \
| sed -n 's/^\# *[0-9][0-9]* *"\([^"]*\)".*/$*.o: \1/p' \
| sort | uniq > $*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CXXFLAGS)
#need to use an automatic dependency generator
#%.d: %.c
# #set -e; rm -f $#; \
# $(CC) -MP -MD $(CXXFLAGS) $< > $#.$$$$; \
# sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
# rm -f $#.$$$$
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEP_DIR)/%.d
#$(MAKEDEPEND); \
cp $*.Td $*.d; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.Td >> $*.d; \
rm -f $*.Td
#$(COMPILE.c) -o $# $<
$(CC) $(CXXFLAGS) $(DEPFLAGS) $< -o $#
-include $(SRCS:.c=.d)
$(DEP_DIR)/%.d: ;
.PRECIOUS: $(DEP_DIR)/%.d
output: $(OBJS)
$(CC) $^ -o $#
run: output
./output
clean:
rm -r $(OBJ_DIR)
rm -r $(DEP_DIR)
rm output
-#echo "Clean completed"
The error when make is executed is:
$ make
gcc -c -Wall -I. -IHeaders -MT Objects/*.o -MMD -MP -MF .d/*.Td Sources/function.c -o Objects/*.o
gcc Objects/*.o -o output
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
makefile:48: recipe for target 'output' failed
make: *** [output] Error 1
So, I'm hoping to achieve the auto dependency detection and compilation. I think the error is in the way that the dependencies are detected and the way they are generated for a given source file.
It looks to me like you're trying to combine multiple different ways of generating dependency info, and that can't work. The advanced post talks about multiple ways to solve the problem: you need to pick one not try to use them all together.
If you want to use the advanced method then use it as described in the "TL;DR" section at the top, or else in the "Combining Compilation and Dependency Generation" section at the bottom. If you're using GCC there's no need for MAKEDEPEND, sed, etc.
The advanced post says that your rule should look like this:
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
%.o : %.c
%.o : %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
That's it.

Secondary expansion in make prereqs with patsubst

I have the following make file:
.SECONDEXPANSION:
CXX = g++
CXXFLAGS = -Wall -W -ansi -I. -I../Include
BUILD_DIR = obj
OUT = bin/EngineTests
SRC = LiveTestReporterStdout.cpp \
EngineTests.cpp \
IntegratorValidationTest.cpp \
PRIVATE_SRC = Private/Unit/BlockTests/AlertBlockTest.cpp \
Private/Unit/BlockTests/CapBlockTest.cpp \
Private/TestHelpers.cpp
OBJS = $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(SRC))
all: $(OUT)
private: SRC += $(PRIVATE_SRC)
private: $(OUT)
$(BUILD_DIR)/%.o : %.cpp
#echo $(CXX) $(CXXFLAGS) $<
#mkdir -p $(dir $#)
#$(CXX) $(CXXFLAGS) -c $< -o $#
$(OUT): $(OBJS)
#echo Linking $# ...
# blah
The goal being able to do make to build all from just $(SRC) and make private to build from $(SRC) + $(PRIVATE_SRC). But it doesnt work - I'm aware that target specific variables cant be used for pre-reqs and the solution somehow involves secondary expansion, but cant get it to work.
I have tried OBJS = $$(patsubst %.cpp, $(BUILD_DIR)/%.o, $$(SRC)) and various things like that.
Many thanks

How to implement cleanall in when a common make file is used

Hi I am using common makefile.inc for my project. For my src folders, I define a makefile which sets some variables and includes makefile.inc. I can also define DIRS= variable (sample #2) which will call make -C on each one of the directories specified there. This all works. However, I cannot get a "clean" or "cleanall" to work properly. If DIRS= is defined, I need a way to go through all the directories listed and call "make -C xxx clean". Any ideas?
Sample makefile #1
TYPE = exe
SOURCES = test.cpp
INCLUDES = -I. -I/usr/local/include -I../src
LIBS = -lpcre
OUT = test
include ../../makefile.inc
Sample makefile #2
DIRS = src test
include ../makefile.inc
makefile.inc
OBJS = $(SOURCES:.cpp=.o)
ifeq ($(CFG),)
CFG=debug
endif
ifeq ($(CFG),debug)
CXXFLAGS += -g -Wall -DNDEBUG
else
CXXFLAGS += -O2 -Wall
endif
all: dirs cfgcheck $(OUT)
.PHONY: clean cleanall all
cfgcheck:
ifneq ($(CFG),release)
ifneq ($(CFG),debug)
#echo "Error: Invalid CFG '$(CFG)'' (options: debug,release)"
#exit 1
endif
endif
#echo "Making '$(CURDIR)' CFG="$(CFG)
$(OUT): $(OBJS)
ifeq ($(TYPE),lib)
$(AR) rcs $(OUT) $(OBJS)
endif
ifeq ($(TYPE),exe)
$(CXX) -o $# $^ ${LDFLAGS} $(LIBS)
endif
-include $(OBJS:.o=.d)
%.o: %.cpp
$(CXX) -c $(INCLUDES) $(CXXFLAGS) $*.cpp -o $*.o
$(CXX) -MM $(CXXFLAGS) $*.cpp > $*.d
#cp -f $*.d $*.d.tmp
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
#rm -f $*.d.tmp
dirs: $(DIRS)
$(DIRS):
$(MAKE) -C $#
clean:
rm -f $(OUT) *.o *.d
I'd do something like this:
DIRS = src test
clean: TARG:=clean
clean: $(DIRS)
.PHONY: $(DIRS)
$(DIRS):
#$(MAKE) -C $# $(TARG)
If you don't like using the names of directories as phony targets, there are alternatives that are slightly more complicated...