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