## ## Makefile for building Erlang applications ## # # default values # DEFAULT_APP_VSN=0.0.0 # # directories and files # ENV_MK=../../env.mk ALT_ENV_MK=../env.mk APP_MK=../app.mk VSN_MK=../vsn.mk SRC_DIR=. EBIN_DIR=../ebin INCLUDE_DIR=../include DOC_DIR=../doc OVERVIEW_DIR=$(SRC_DIR) DOC_INDEX=$(DOC_DIR)/index.html OVERVIEW=$(OVERVIEW_DIR)/overview.edoc # # do include # -include $(ENV_MK) -include $(ALT_ENV_MK) -include $(APP_MK) -include $(VSN_MK) # # confirm APP_NAME and APP_VSN # ifndef APP_NAME EMPTY := pwd_url = $(subst $(EMPTY) ,%20,$(subst %,%25,$(shell pwd))) this_path := $(pwd_url) parent_path := $(dir $(this_path)) parent_path_list := $(subst /, ,$(parent_path)) app_name := $(lastword $(parent_path_list)) ifdef app_name APP_NAME := $(app_name) else APP_NAME := $(error Cannot define APP_NAME) # Stop! endif # app_name endif # !APP_NAME # then, APP_NAME is defined! to_upper = \ $(subst \ a,A,$(subst \ b,B,$(subst \ c,C,$(subst \ d,D,$(subst \ e,E,$(subst \ f,F,$(subst \ g,G,$(subst \ h,H,$(subst \ i,I,$(subst \ j,J,$(subst \ k,K,$(subst \ l,L,$(subst \ m,M,$(subst \ n,N,$(subst \ o,O,$(subst \ p,P,$(subst \ q,Q,$(subst \ r,R,$(subst \ s,S,$(subst \ t,T,$(subst \ u,U,$(subst \ v,V,$(subst \ w,W,$(subst \ x,X,$(subst \ y,Y,$(subst \ z,Z,$(1))))))))))))))))))))))))))) APP_NAME_UPPER := $(call to_upper,$(APP_NAME)) ifndef APP_VSN ifdef $(APP_NAME_UPPER)_VSN APP_VSN=$($(APP_NAME_UPPER)_VSN) else APP_VSN=$(DEFAULT_APP_VSN) endif # $(APP_NAME_UPPER)_VSN endif # !APP_VSN # # debug stuffs # ifdef debug DEBUG=$(debug) endif ifdef DEBUG ERLC_DEBUG_FLAG=-Ddebug -DDEBUG +debug_info else ERLC_DEBUG_FLAG= endif # # useful constants and functions # COMMA=, escape_quote = $(subst ",\",$(1)) # # commands and flags # ERLC=erlc ERLC_INC_FLAG=-I $(INCLUDE_DIR) -I $(SRC_DIR) ERLC_FLAGS= $(ERLC_INC_FLAG) $(ERLC_DEBUG_FLAG) \ $(ERLC_EXTRA_FLAGS) -o $(EBIN_DIR) EDOC_OPTS={def,{version, "$(APP_VSN)"}}, \ {def,{app_name, "$(APP_NAME)"}}, \ {dir, "$(DOC_DIR)"}, {overview, "$(OVERVIEW)"}, private ifdef EDOC_EXTRA_OPTS ESCAPED_EDOC_OPTS_LIST := \ [$(call escape_quote,$(EDOC_OPTS)$(COMMA) $(EDOC_EXTRA_OPTS))] else ESCAPED_EDOC_OPTS_LIST := \ [$(call escape_quote,$(EDOC_OPTS))] endif # EDOC_EXTRA_OPTS # # sources and targets # -include sources.mk ifndef SOURCES SOURCES:=$(filter-out $(SRC_DIR)/tmp%,$(wildcard $(SRC_DIR)/*.erl)) -include not_sources.mk ifdef NOT_SOURCES SOURCES:=$(filter-out $(NOT_SOURCES),$(SOURCES)) endif # NOT_SOURCES endif # !SOURCES -include includes.mk ifndef INCLUDES INCLUDES:= \ $(filter-out $(INCLUDE_DIR)/tmp%,$(wildcard $(INCLUDE_DIR)/*.hrl))\ $(filter-out $(SRC_DIR)/tmp%,$(wildcard $(SRC_DIR)/*.hrl)) -include not_includes.mk ifdef NOT_INCLUDES INCLUDES:=$(filter-out $(NOT_INCLUDES),$(INCLUDES)) endif # NOT_INCLUDES endif # !INCLUDES OBJECTS=$(patsubst $(SRC_DIR)/%.erl, $(EBIN_DIR)/%.beam,$(SOURCES)) # application resource file. APP_TARGET=$(EBIN_DIR)/$(APP_NAME).app # application upgrade file APPUP_TARGET=$(EBIN_DIR)/$(APP_NAME).appup TEST_MODS=$(patsubst $(SRC_DIR)/%.erl,%,$(wildcard $(SRC_DIR)/t_*.erl)) # # main targets # .PHONY: obj doc desc all test obj: $(OBJECTS) doc: $(DOC_INDEX) desc: $(APP_TARGET) $(APPUP_TARGET) all: obj doc desc test: obj @for t in dummy $(TEST_MODS); do \ if [ "$$t" != "dummy" ] ; then \ echo "Test module: $$t"; \ erl -boot start_clean -noshell -pa $(EBIN_DIR) \ -s $$t test \ -s init stop;\ fi \ done # # rules # $(OBJECTS) : $(INCLUDES) # each objct depends on include files. $(OBJECTS) : $(EBIN_DIR)/%.beam : $(SRC_DIR)/%.erl $(ERLC) $(ERLC_FLAGS) $< $(VSN_MK) : echo "$(APP_NAME_UPPER)_VSN = $(APP_VSN)" > $@ $(APP_MK) : echo "APP_NAME = $(APP_NAME)" > $@ $(DOC_INDEX): $(SOURCES) $(OVERVIEW) $(VSN_MK) $(APP_MK) erl -boot start_clean -noshell \ -eval "edoc:application($(APP_NAME), \"$(SRC_DIR)\", \ $(ESCAPED_EDOC_OPTS_LIST))" \ -s init stop $(APP_TARGET): $(SRC_DIR)/$(APP_NAME).app.src $(VSN_MK) $(APP_MK) sed -e 's;%VSN%;$(APP_VSN);' -e 's;%NAME%;$(APP_NAME);' $< > $@ $(APPUP_TARGET): $(SRC_DIR)/$(APP_NAME).appup.src $(VSN_MK) $(APP_MK) sed -e 's;%VSN%;$(APP_VSN);' -e 's;%NAME%;$(APP_NAME);' $< > $@ # # other targets # .PHONY: clean doc_clean print_vars clean: -rm -f $(OBJECTS) $(APP_TARGET) $(APPUP_TARGET) -rm -f $(SRC_DIR)/*.beam $(SRC_DIR)/erl_crash.dump doc_clean: -rm -f $(DOC_DIR)/* print_vars: # for debugging Makefile @echo "ERLANG_HOME=$(ERLANG_HOME)" @echo "APP_NAME=$(APP_NAME)" @echo "APP_VSN=$(APP_VSN)" @echo "SRC_DIR=$(SRC_DIR)" @echo "EBIN_DIR=$(EBIN_DIR)" @echo "INCLUDE_DIR=$(INCLUDE_DIR)" @echo "DOC_DIR=$(DOC_DIR)" @echo "OVERVIEW=$(OVERVIEW)" @echo "DOC_INDEX=$(DOC_INDEX)" @echo "ERLC_FLAGS=$(ERLC_FLAGS)" @echo "SOURCES=$(SOURCES)" @echo "INCLUDES=$(INCLUDES)" @echo "APP_TARGET=$(APP_TARGET)" @echo "APPUP_TARGET=$(APPUP_TARGET)" @echo "EDOC_OPTS=$(EDOC_OPTS)" @echo "EDOC_EXTRA_OPTS=$(EDOC_EXTRA_OPTS)" @echo "TEST_MODS=$(TEST_MODS)" @echo "DEBUG=$(DEBUG)"