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