1#
2#	Makefile		(C) 2006-2008, Aurélien Croc (AP²C)
3#
4# This project is under the GPL Licence
5#
6# Available MAKE options:
7#      * V sets to 1 for verbose mode
8#
9# Available variables in module.mk :
10#      * SUBDIRS
11#      * MODE = {default,debug,optimized}
12#      * CFLAGS
13#      * CXXFLAGS
14#      * LDFLAGS
15#      * DEBUG_CFLAGS
16#      * DEBUG_CXXFLAGS
17#      * OPTIMIZED_CFLAGS
18#      * OPTIMIZED_CXXFLAGS
19#      * TARGETS
20#      * GENERIC_TARGETS
21#      * PRE_GENERIC_TARGETS
22#      * directory1_directory2_file_ext_FLAGS
23#
24# Each project must be listed in the TARGETS variable. Next:
25#      * project1_SRC
26#      * project1_LIB
27#      * project1_CFLAGS
28#      * project1_LDFLAGS
29#      * project1_MODULES
30#      * project1_CXXFLAGS
31#      * ...
32#
33# This Makefile will generate:
34#      * project1_TARGET
35#      * project1_OBJ
36#
37#
38# In the file rules.mk:
39#
40# You can add your own rules
41#
42# To add a new target file support, please add the target extension in the
43# TARGET_RULES variable and define the function targetDefinition_{extension}.
44# This function will be called with one parameters: the target name
45# Like the examples above, use $(value $(1)_TARGET) or _OBJ, .. to access
46# to useful informations
47#
48#
49# /!\ = Please do your modifications in the module.mk file = /!\
50#
51
52
53# +--------------------------------------------------------------------------+
54# |   SUPPORTED LANGUAGES, DIRECTORIES ARCHI AND TOOLS LOCATIONS & FLAGS     |
55# +--------------------------------------------------------------------------+
56LANGUAGES	:= cpp c
57
58CC		:= gcc
59CXX		:= g++
60RM		:= rm -f
61AR		:= ar crs
62LEX		:= flex
63YACC		:= bison
64LINKER		:= $(CXX)
65
66DEPDIR          := .deps
67BUILDDIR        := .build
68TARGETDIR       := .
69
70
71empty           :=
72space           := $(empty) $(empty)
73comma           := ,
74
75DEBUG_CFLAGS    := -O0 -g
76DEBUG_CXXFLAGS  := -O0 -g
77OPTIM_CFLAGS	:= -O2
78OPTIM_CXXFLAGS	:= -O2
79
80ARCHI           := $(shell uname -s)
81
82ifeq ($(ARCHI),Darwin)
83PLUGIN_EXT      := bundle
84LIBRARY_EXT     := dylib
85else
86PLUGIN_EXT      := so
87LIBRARY_EXT     := so
88endif
89
90
91# +--------------------------------------------------------------------------+
92# |   DEFINITIONS VARIABLE LOADING                                           |
93# +--------------------------------------------------------------------------+
94
95MODE		:= default
96DEFFILE		:= .defs.mk
97-include $(DEFFILE)
98
99
100
101# +--------------------------------------------------------------------------+
102# |   SUBDIRS LOADING                                                        |
103# +--------------------------------------------------------------------------+
104
105include module.mk
106ifeq ($(DEFLOADED),1)
107include $(patsubst %, %/module.mk, $(_SUBDIRS))
108endif # DEFLOADED == 1
109ifeq ($(DEFDONE),1)
110
111
112
113
114# +--------------------------------------------------------------------------+
115# |   COMPILATION MODE INITIALIZATION                                        |
116# +--------------------------------------------------------------------------+
117
118ifeq ($(MAKECMDGOALS),debug)
119MODE            := debug
120endif #MAKECMDGOALS == debug
121ifeq ($(MAKECMDGOALS),optimized)
122MODE            := optimized
123endif #MAKECMDGOALS == optimized
124ifeq ($(MAKECMDGOALS),default)
125MODE            := default
126endif #MAKECMDGOALS == default
127
128ifeq ($(MODE),debug)            # DEBUG
129CFLAGS		+= $(DEBUG_CFLAGS)
130CXXFLAGS	+= $(DEBUG_CXXFLAGS)
131BUILDDIR	:= debug
132TARGETDIR	:= debug
133DEPDIR		:= debug
134else
135ifeq ($(MODE),optimized)        # OPTIMIZED
136CFLAGS		+= $(OPTIM_CFLAGS)
137CXXFLAGS	+= $(OPTIM_CXXFLAGS)
138BUILDDIR	:= optimized
139TARGETDIR	:= optimized
140DEPDIR		:= optimized
141endif # MODE == optimized
142endif # MODE == debug
143
144
145
146# +--------------------------------------------------------------------------+
147# |   VERBOSE MODE AND INITIALIZATION                                        |
148# +--------------------------------------------------------------------------+
149
150V :=
151ifeq ($(V),1)
152	Q :=
153else
154	Q := @
155endif
156
157
158
159# +--------------------------------------------------------------------------+
160# |   MAIN RULES AND TARGETS                                                 |
161# +--------------------------------------------------------------------------+
162
163_TARGETS	:= $(foreach target,$(TARGETS),$(TARGETDIR)/$(target))
164_TARGETS	:= $(PRE_GENERIC_TARGETS) $(_TARGETS) $(GENERIC_TARGETS)
165
166all: $(_TARGETS)
167debug: $(_TARGETS)
168optimized: $(_TARGETS)
169
170
171
172# +--------------------------------------------------------------------------+
173# |   MACRO DEFINITIONS                                                      |
174# +--------------------------------------------------------------------------+
175
176# Function to print smart messages
177printCmd	= $(if $(filter $(V),1),,$(shell echo "@echo \"    $(1)\""))
178
179# Get the target variable name
180targetName	= $(subst .,_,$(subst /,_,$(1)))
181
182# Specific flags definition
183flags            = $(value $(subst /,_,$(subst .,_,$(1)))_FLAGS)
184flag            = $(subst /,_,$(subst .,_,$(1)))_FLAGS
185
186
187
188# +--------------------------------------------------------------------------+
189# |   LOAD AND GENERATE DEPENDENCIES FILES                                   |
190# +--------------------------------------------------------------------------+
191
192# Get all the source files in ALLSRC
193ALLSRC          := $(foreach target,$(call targetName,$(TARGETS)),$(value \
194                        $(target)_SRC))
195
196# Get the dependencies files
197DEPENDENCIES    := $(foreach lang,$(LANGUAGES),$(patsubst %.$(lang), %.d, \
198                   $(filter %.$(lang),$(ALLSRC))))
199
200# Generate dependencies files for C++ source file
201$(DEPDIR)/%.d: %.cpp
202	@mkdir -p $(dir $@)
203	@$(CXX) $(CXXFLAGS) -MM -MP -MG -MT "\$$(DEPDIR)/$(basename $<).d \
204		\$$(BUILDDIR)/$(basename $<).o" -MG "$<" -MF $@
205
206# Load dependencies files
207-include $(foreach dep,$(DEPENDENCIES),$(DEPDIR)/$(dep))
208
209
210
211# +--------------------------------------------------------------------------+
212# |   PREVENT LOADING RULES IF DEFFILE IS NOT COMPLET                        |
213# +--------------------------------------------------------------------------+
214
215else
216TARGETS	:= $(empty)
217
218endif # DEFDONE == 1
219
220
221
222# +--------------------------------------------------------------------------+
223# |   OBJECTS AND TARGETS DEFINITIONS                                        |
224# +--------------------------------------------------------------------------+
225
226
227# Define target variables
228defineTarget	= $(call targetName,$(1))_TARGET  := $(TARGETDIR)/$(1)
229
230# Define target object variables
231define defineObject
232$(1)_OBJ	:= $(foreach obj,$(foreach lang,$(LANGUAGES),$(patsubst \
233			%.$(lang),%.o,$(filter %.$(lang),$(value $(1)_SRC)))), \
234			$(BUILDDIR)/$(obj)) \
235		   $(foreach module,$(value \
236			$(1)_MODULES),$(TARGETDIR)/$(module)) \
237		   $(foreach obj,$(patsubst %.l,%.l.o,$(filter %.l,$(value \
238			$(1)_SRC))),$(BUILDDIR)/$(obj)) \
239		   $(foreach obj,$(patsubst %.y,%.yy.o,$(filter %.y,$(value \
240			$(1)_SRC))),$(BUILDDIR)/$(obj))
241$(1)_CLEAN	:= $(foreach obj,$(patsubst %.y,%.yy.h,$(filter %.y,$(value \
242			$(1)_SRC))),$(BUILDDIR)/$(obj))
243endef
244
245# Create these definitions
246$(foreach target,$(TARGETS),$(eval $(call defineTarget,$(strip $(target)))) \
247	$(eval $(call defineObject,$(strip $(call targetName,$(target))))))
248
249
250
251# +--------------------------------------------------------------------------+
252# |   SMART MESSAGE PRINTING                                                 |
253# +--------------------------------------------------------------------------+
254
255
256# Smart messages
257cmd_ar_a_o	= AR                $@
258cmd_cc_o_c	= CC                $<
259cmd_cxx_o_cpp	= CXX               $<
260cmd_yacc_h	= YACC [H]          $<
261cmd_yacc_cpp	= YACC [CPP]        $<
262cmd_lex_cpp	= LEX               $<
263cmd_link	= LINK              $@
264cmd_ln_so_o	= LINK [M]          $@
265cmd_rm_clean	= RM                *.o
266cmd_rm_distclean = RM                $(_TARGETS) *.d $(DEFFILE)
267
268
269
270# +--------------------------------------------------------------------------+
271# |   TARGET RULES                                                           |
272# +--------------------------------------------------------------------------+
273
274TARGET_RULES    := a so bundle
275
276# Archives
277define targetDefinition_a
278$(value $(1)_TARGET): $(value $(1)_OBJ)
279	$$(call printCmd, $$(cmd_ar_a_o))
280	$$(Q)$$(AR) $$@ $$^
281endef
282-include rules.mk
283
284# Plugins (for MacOS X)
285define targetDefinition_bundle
286$(value $(1)_TARGET): $(value $(1)_OBJ) $(value $(1)_LOADER)
287	$$(call printCmd, $$(cmd_ln_so_o))
288	$$(Q)$$(LINKER) $$(MODULE_FLAGS) $$(LDFLAGS) -o $$@ $$(value $(1)_OBJ) \
289		-bundle -bundle_loader $$(value $(1)_LOADER) \
290		$$(value $(1)_LIBS) $$(value $(1)_FLAGS) $$(LIBS)
291endef
292
293# Plugins and libaries (for UNIXes)
294define targetDefinition_so
295$(value $(1)_TARGET): $(value $(1)_OBJ)
296	$$(call printCmd, $$(cmd_ln_so_o))
297	$$(Q)$$(LINKER) $$(MODULE_FLAGS) $$(LDFLAGS) -o $$@ $$(value $(1)_OBJ) \
298		-rdynamic -shared $$(value $(1)_LIBS) $$(value $(1)_FLAGS) \
299		$$(LIBS)
300endef
301
302rulesTarget	:= $(foreach rules,$(TARGET_RULES),$(filter \
303			%.$(rules),$(TARGETS)))
304$(foreach target,$(rulesTarget),$(eval $(call targetDefinition_$(subst \
305	.,,$(suffix $(target))),$(call targetName,$(target)))))
306
307
308
309# +--------------------------------------------------------------------------+
310# |   COMPILATION RULES                                                      |
311# +--------------------------------------------------------------------------+
312
313# C Files
314$(BUILDDIR)/%.o: $(BUILDDIR)/%.c
315	$(call printCmd, $(cmd_cc_o_c))
316	@mkdir -p $(dir $@)
317	$(Q)$(CC) $(CFLAGS) $(call flags,$<) -o $@ -c $<
318$(BUILDDIR)/%.o: %.c
319	$(call printCmd, $(cmd_cc_o_c))
320	@mkdir -p $(dir $@)
321	$(Q)$(CC) $(CFLAGS) $(call flags,$<) -o $@ -c $<
322
323# C++ Files
324$(BUILDDIR)/%.o: $(BUILDDIR)/%.cpp
325	$(call printCmd, $(cmd_cxx_o_cpp))
326	@mkdir -p $(dir $@)
327	$(Q)$(CXX) $(CXXFLAGS) $(call flags,$<) -o $@ -c $<
328$(BUILDDIR)/%.o: %.cpp
329	$(call printCmd, $(cmd_cxx_o_cpp))
330	@mkdir -p $(dir $@)
331	$(Q)$(CXX) $(CXXFLAGS) $(call flags,$<) -o $@ -c $<
332
333# Yacc compilation
334$(BUILDDIR)/%.yy.h: %.y
335	$(call printCmd, $(cmd_yacc_h))
336	@mkdir -p $(dir $@)
337	$(Q)$(YACC) $(call flags,$<) -d -b $(basename $(basename $@)) \
338		-p $(basename $(notdir $<)) $<
339	$(Q)rm $(basename $(basename $@)).tab.c
340	$(Q)mv $(basename $(basename $@)).tab.h $(basename $@).h
341$(BUILDDIR)/%.yy.cpp: %.y
342	$(call printCmd, $(cmd_yacc_cpp))
343	@mkdir -p $(dir $@)
344	$(Q)$(YACC) $(call flags,$<) -b $(basename $(basename $@)) \
345		-p $(basename $(notdir $<)) -o $@ $<
346
347# Lex compilation
348$(BUILDDIR)/%.l.cpp: %.l $(BUILDDIR)/%.yy.h
349	$(call printCmd, $(cmd_lex_cpp))
350	$(Q)$(LEX) $(call flags,$<) -P$(basename $(notdir $<)) -t $< > $@
351
352
353
354# +--------------------------------------------------------------------------+
355# |   CLEAN RULES                                                            |
356# +--------------------------------------------------------------------------+
357
358.PHONY: clean distclean
359clean:
360	$(call printCmd, $(cmd_rm_clean))
361	$(Q)$(RM) $(foreach target,$(TARGETS),$(value $(call \
362		targetName,$(target))_OBJ) $(value $(target)_CLEAN))
363
364distclean: clean
365	$(call printCmd, $(cmd_rm_distclean))
366	$(Q)$(RM) $(foreach dep,$(DEPENDENCIES),$(DEPDIR)/$(dep))
367	$(Q)$(RM) $(_TARGETS)
368	$(Q)$(RM) $(DEFFILE)
369
370
371
372# +--------------------------------------------------------------------------+
373# |   GET ALL SUBDIRS TO EXPLORE                                             |
374# +--------------------------------------------------------------------------+
375
376# Generate the defs.mk file which contains sub directories
377$(DEFFILE): Makefile $(patsubst %, %/module.mk, $(SUBDIRS)) module.mk
378	@echo -n "     GEN               $(DEFFILE)"
379	@echo "" > $@
380	@make -s -C ./ _depsreload
381
382.PHONY: _depsreload
383_depsreload:
384	@echo -n "."
385	@echo "DEFLOADED := 1" > $(DEFFILE)
386	@echo "_SUBDIRS := $(SUBDIRS)" >> $(DEFFILE)
387	@if [ "$(SUBDIRS)" != "$(_SUBDIRS)" ]; then make -j 1 -s -C ./ _depsreload; \
388		else echo "DEFDONE := 1" >> $(DEFFILE); echo ""; fi
389
390