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