Makefile
author Simon MacMullen <simon@rabbitmq.com>
Fri Feb 03 15:59:12 2012 +0000 (3 months ago)
changeset 8922 4f87837a40be
parent 8670 02476613ae59
parent 8671 8b4c4598afd6
child 8829 4157b5c86aec
child 8850 24c00697df46
child 8855 a9c2c098fc44
child 9000 5e31ba01360c
permissions -rw-r--r--
Merge bug24702
     1 TMPDIR ?= /tmp
     2 
     3 RABBITMQ_NODENAME ?= rabbit
     4 RABBITMQ_SERVER_START_ARGS ?=
     5 RABBITMQ_MNESIA_DIR ?= $(TMPDIR)/rabbitmq-$(RABBITMQ_NODENAME)-mnesia
     6 RABBITMQ_PLUGINS_EXPAND_DIR ?= $(TMPDIR)/rabbitmq-$(RABBITMQ_NODENAME)-plugins-scratch
     7 RABBITMQ_LOG_BASE ?= $(TMPDIR)
     8 
     9 DEPS_FILE=deps.mk
    10 SOURCE_DIR=src
    11 EBIN_DIR=ebin
    12 INCLUDE_DIR=include
    13 DOCS_DIR=docs
    14 INCLUDES=$(wildcard $(INCLUDE_DIR)/*.hrl) $(INCLUDE_DIR)/rabbit_framing.hrl
    15 SOURCES=$(wildcard $(SOURCE_DIR)/*.erl) $(SOURCE_DIR)/rabbit_framing_amqp_0_9_1.erl $(SOURCE_DIR)/rabbit_framing_amqp_0_8.erl $(USAGES_ERL)
    16 BEAM_TARGETS=$(patsubst $(SOURCE_DIR)/%.erl, $(EBIN_DIR)/%.beam, $(SOURCES))
    17 TARGETS=$(EBIN_DIR)/rabbit.app $(INCLUDE_DIR)/rabbit_framing.hrl $(BEAM_TARGETS) plugins
    18 WEB_URL=http://www.rabbitmq.com/
    19 MANPAGES=$(patsubst %.xml, %.gz, $(wildcard $(DOCS_DIR)/*.[0-9].xml))
    20 WEB_MANPAGES=$(patsubst %.xml, %.man.xml, $(wildcard $(DOCS_DIR)/*.[0-9].xml) $(DOCS_DIR)/rabbitmq-service.xml)
    21 USAGES_XML=$(DOCS_DIR)/rabbitmqctl.1.xml $(DOCS_DIR)/rabbitmq-plugins.1.xml
    22 USAGES_ERL=$(foreach XML, $(USAGES_XML), $(call usage_xml_to_erl, $(XML)))
    23 QC_MODULES := rabbit_backing_queue_qc
    24 QC_TRIALS ?= 100
    25 
    26 ifeq ($(shell python -c 'import simplejson' 2>/dev/null && echo yes),yes)
    27 PYTHON=python
    28 else
    29 ifeq ($(shell python2.6 -c 'import simplejson' 2>/dev/null && echo yes),yes)
    30 PYTHON=python2.6
    31 else
    32 ifeq ($(shell python2.5 -c 'import simplejson' 2>/dev/null && echo yes),yes)
    33 PYTHON=python2.5
    34 else
    35 # Hmm. Missing simplejson?
    36 PYTHON=python
    37 endif
    38 endif
    39 endif
    40 
    41 BASIC_PLT=basic.plt
    42 RABBIT_PLT=rabbit.plt
    43 
    44 ifndef USE_SPECS
    45 # our type specs rely on features and bug fixes in dialyzer that are
    46 # only available in R14B03 upwards (R14B03 is erts 5.8.4)
    47 USE_SPECS:=$(shell erl -noshell -eval 'io:format([list_to_integer(X) || X <- string:tokens(erlang:system_info(version), ".")] >= [5,8,4]), halt().')
    48 endif
    49 
    50 ifndef USE_PROPER_QC
    51 # PropEr needs to be installed for property checking
    52 # http://proper.softlab.ntua.gr/
    53 USE_PROPER_QC:=$(shell erl -noshell -eval 'io:format({module, proper} =:= code:ensure_loaded(proper)), halt().')
    54 endif
    55 
    56 #other args: +native +"{hipe,[o3,verbose]}" -Ddebug=true +debug_info +no_strict_record_tests
    57 ERLC_OPTS=-I $(INCLUDE_DIR) -o $(EBIN_DIR) -Wall -v +debug_info $(call boolean_macro,$(USE_SPECS),use_specs) $(call boolean_macro,$(USE_PROPER_QC),use_proper_qc)
    58 
    59 VERSION?=0.0.0
    60 PLUGINS_SRC_DIR?=$(shell [ -d "plugins-src" ] && echo "plugins-src" || echo )
    61 PLUGINS_DIR=plugins
    62 TARBALL_NAME=rabbitmq-server-$(VERSION)
    63 TARGET_SRC_DIR=dist/$(TARBALL_NAME)
    64 
    65 SIBLING_CODEGEN_DIR=../rabbitmq-codegen/
    66 AMQP_CODEGEN_DIR=$(shell [ -d $(SIBLING_CODEGEN_DIR) ] && echo $(SIBLING_CODEGEN_DIR) || echo codegen)
    67 AMQP_SPEC_JSON_FILES_0_9_1=$(AMQP_CODEGEN_DIR)/amqp-rabbitmq-0.9.1.json
    68 AMQP_SPEC_JSON_FILES_0_8=$(AMQP_CODEGEN_DIR)/amqp-rabbitmq-0.8.json
    69 
    70 ERL_CALL=erl_call -sname $(RABBITMQ_NODENAME) -e
    71 
    72 ERL_EBIN=erl -noinput -pa $(EBIN_DIR)
    73 
    74 define usage_xml_to_erl
    75   $(subst __,_,$(patsubst $(DOCS_DIR)/rabbitmq%.1.xml, $(SOURCE_DIR)/rabbit_%_usage.erl, $(subst -,_,$(1))))
    76 endef
    77 
    78 define usage_dep
    79   $(call usage_xml_to_erl, $(1)): $(1) $(DOCS_DIR)/usage.xsl
    80 endef
    81 
    82 define boolean_macro
    83 $(if $(filter true,$(1)),-D$(2))
    84 endef
    85 
    86 ifneq "$(SBIN_DIR)" ""
    87 ifneq "$(TARGET_DIR)" ""
    88 SCRIPTS_REL_PATH=$(shell ./calculate-relative $(TARGET_DIR)/sbin $(SBIN_DIR))
    89 endif
    90 endif
    91 
    92 # Versions prior to this are not supported
    93 NEED_MAKE := 3.80
    94 ifneq "$(NEED_MAKE)" "$(firstword $(sort $(NEED_MAKE) $(MAKE_VERSION)))"
    95 $(error Versions of make prior to $(NEED_MAKE) are not supported)
    96 endif
    97 
    98 # .DEFAULT_GOAL introduced in 3.81
    99 DEFAULT_GOAL_MAKE := 3.81
   100 ifneq "$(DEFAULT_GOAL_MAKE)" "$(firstword $(sort $(DEFAULT_GOAL_MAKE) $(MAKE_VERSION)))"
   101 .DEFAULT_GOAL=all
   102 endif
   103 
   104 all: $(TARGETS)
   105 
   106 .PHONY: plugins
   107 ifneq "$(PLUGINS_SRC_DIR)" ""
   108 plugins:
   109 	[ -d "$(PLUGINS_SRC_DIR)/rabbitmq-server" ] || ln -s "$(CURDIR)" "$(PLUGINS_SRC_DIR)/rabbitmq-server"
   110 	mkdir -p $(PLUGINS_DIR)
   111 	PLUGINS_SRC_DIR="" $(MAKE) -C "$(PLUGINS_SRC_DIR)" plugins-dist PLUGINS_DIST_DIR="$(CURDIR)/$(PLUGINS_DIR)" VERSION=$(VERSION)
   112 	echo "Put your EZs here and use rabbitmq-plugins to enable them." > $(PLUGINS_DIR)/README
   113 	rm -f $(PLUGINS_DIR)/rabbit_common*.ez
   114 else
   115 plugins:
   116 # Not building plugins
   117 endif
   118 
   119 $(DEPS_FILE): $(SOURCES) $(INCLUDES)
   120 	rm -f $@
   121 	echo $(subst : ,:,$(foreach FILE,$^,$(FILE):)) | escript generate_deps $@ $(EBIN_DIR)
   122 
   123 $(EBIN_DIR)/rabbit.app: $(EBIN_DIR)/rabbit_app.in $(SOURCES) generate_app
   124 	escript generate_app $< $@ $(SOURCE_DIR)
   125 
   126 $(EBIN_DIR)/%.beam: $(SOURCE_DIR)/%.erl | $(DEPS_FILE)
   127 	erlc $(ERLC_OPTS) -pa $(EBIN_DIR) $<
   128 
   129 $(INCLUDE_DIR)/rabbit_framing.hrl: codegen.py $(AMQP_CODEGEN_DIR)/amqp_codegen.py $(AMQP_SPEC_JSON_FILES_0_9_1) $(AMQP_SPEC_JSON_FILES_0_8)
   130 	$(PYTHON) codegen.py --ignore-conflicts header $(AMQP_SPEC_JSON_FILES_0_9_1) $(AMQP_SPEC_JSON_FILES_0_8) $@
   131 
   132 $(SOURCE_DIR)/rabbit_framing_amqp_0_9_1.erl: codegen.py $(AMQP_CODEGEN_DIR)/amqp_codegen.py $(AMQP_SPEC_JSON_FILES_0_9_1)
   133 	$(PYTHON) codegen.py body $(AMQP_SPEC_JSON_FILES_0_9_1) $@
   134 
   135 $(SOURCE_DIR)/rabbit_framing_amqp_0_8.erl: codegen.py $(AMQP_CODEGEN_DIR)/amqp_codegen.py $(AMQP_SPEC_JSON_FILES_0_8)
   136 	$(PYTHON) codegen.py body $(AMQP_SPEC_JSON_FILES_0_8) $@
   137 
   138 dialyze: $(BEAM_TARGETS) $(BASIC_PLT)
   139 	dialyzer --plt $(BASIC_PLT) --no_native --fullpath \
   140 	  -Wrace_conditions $(BEAM_TARGETS)
   141 
   142 # rabbit.plt is used by rabbitmq-erlang-client's dialyze make target
   143 create-plt: $(RABBIT_PLT)
   144 
   145 $(RABBIT_PLT): $(BEAM_TARGETS) $(BASIC_PLT)
   146 	dialyzer --plt $(BASIC_PLT) --output_plt $@ --no_native \
   147 	  --add_to_plt $(BEAM_TARGETS)
   148 
   149 $(BASIC_PLT): $(BEAM_TARGETS)
   150 	if [ -f $@ ]; then \
   151 	    touch $@; \
   152 	else \
   153 	    dialyzer --output_plt $@ --build_plt \
   154 		--apps erts kernel stdlib compiler sasl os_mon mnesia tools \
   155 		  public_key crypto ssl; \
   156 	fi
   157 
   158 clean:
   159 	rm -f $(EBIN_DIR)/*.beam
   160 	rm -f $(EBIN_DIR)/rabbit.app $(EBIN_DIR)/rabbit.boot $(EBIN_DIR)/rabbit.script $(EBIN_DIR)/rabbit.rel
   161 	rm -f $(PLUGINS_DIR)/*.ez
   162 	[ -d "$(PLUGINS_SRC_DIR)" ] && PLUGINS_SRC_DIR="" PRESERVE_CLONE_DIR=1 make -C $(PLUGINS_SRC_DIR) clean || true
   163 	rm -f $(INCLUDE_DIR)/rabbit_framing.hrl $(SOURCE_DIR)/rabbit_framing_amqp_*.erl codegen.pyc
   164 	rm -f $(DOCS_DIR)/*.[0-9].gz $(DOCS_DIR)/*.man.xml $(DOCS_DIR)/*.erl $(USAGES_ERL)
   165 	rm -f $(RABBIT_PLT)
   166 	rm -f $(DEPS_FILE)
   167 
   168 cleandb:
   169 	rm -rf $(RABBITMQ_MNESIA_DIR)/*
   170 
   171 ############ various tasks to interact with RabbitMQ ###################
   172 
   173 BASIC_SCRIPT_ENVIRONMENT_SETTINGS=\
   174 	RABBITMQ_NODE_IP_ADDRESS="$(RABBITMQ_NODE_IP_ADDRESS)" \
   175 	RABBITMQ_NODE_PORT="$(RABBITMQ_NODE_PORT)" \
   176 	RABBITMQ_LOG_BASE="$(RABBITMQ_LOG_BASE)" \
   177 	RABBITMQ_MNESIA_DIR="$(RABBITMQ_MNESIA_DIR)" \
   178 	RABBITMQ_PLUGINS_EXPAND_DIR="$(RABBITMQ_PLUGINS_EXPAND_DIR)"
   179 
   180 run: all
   181 	$(BASIC_SCRIPT_ENVIRONMENT_SETTINGS) \
   182 		RABBITMQ_ALLOW_INPUT=true \
   183 		RABBITMQ_SERVER_START_ARGS="$(RABBITMQ_SERVER_START_ARGS)" \
   184 		./scripts/rabbitmq-server
   185 
   186 run-node: all
   187 	$(BASIC_SCRIPT_ENVIRONMENT_SETTINGS) \
   188 		RABBITMQ_NODE_ONLY=true \
   189 		RABBITMQ_ALLOW_INPUT=true \
   190 		RABBITMQ_SERVER_START_ARGS="$(RABBITMQ_SERVER_START_ARGS)" \
   191 		./scripts/rabbitmq-server
   192 
   193 run-background-node: all
   194 	$(BASIC_SCRIPT_ENVIRONMENT_SETTINGS) \
   195 		RABBITMQ_NODE_ONLY=true \
   196 		RABBITMQ_SERVER_START_ARGS="$(RABBITMQ_SERVER_START_ARGS)" \
   197 		./scripts/rabbitmq-server
   198 
   199 run-tests: all
   200 	OUT=$$(echo "rabbit_tests:all_tests()." | $(ERL_CALL)) ; \
   201 	  echo $$OUT ; echo $$OUT | grep '^{ok, passed}$$' > /dev/null
   202 
   203 run-qc: all
   204 	$(foreach MOD,$(QC_MODULES),./quickcheck $(RABBITMQ_NODENAME) $(MOD) $(QC_TRIALS))
   205 
   206 start-background-node: all
   207 	-rm -f $(RABBITMQ_MNESIA_DIR).pid
   208 	mkdir -p $(RABBITMQ_MNESIA_DIR)
   209 	setsid sh -c "$(MAKE) run-background-node > $(RABBITMQ_MNESIA_DIR)/startup_log 2> $(RABBITMQ_MNESIA_DIR)/startup_err" &
   210 	sleep 1
   211 
   212 start-rabbit-on-node: all
   213 	echo "rabbit:start()." | $(ERL_CALL)
   214 	./scripts/rabbitmqctl -n $(RABBITMQ_NODENAME) wait $(RABBITMQ_MNESIA_DIR).pid
   215 
   216 stop-rabbit-on-node: all
   217 	echo "rabbit:stop()." | $(ERL_CALL)
   218 
   219 set-memory-alarm: all
   220 	echo "alarm_handler:set_alarm({{vm_memory_high_watermark, node()}, []})." | \
   221 	$(ERL_CALL)
   222 
   223 clear-memory-alarm: all
   224 	echo "alarm_handler:clear_alarm({vm_memory_high_watermark, node()})." | \
   225 	$(ERL_CALL)
   226 
   227 stop-node:
   228 	-$(ERL_CALL) -q
   229 
   230 # code coverage will be created for subdirectory "ebin" of COVER_DIR
   231 COVER_DIR=.
   232 
   233 start-cover: all
   234 	echo "rabbit_misc:start_cover([\"rabbit\", \"hare\"])." | $(ERL_CALL)
   235 	echo "rabbit_misc:enable_cover([\"$(COVER_DIR)\"])." | $(ERL_CALL)
   236 
   237 start-secondary-cover: all
   238 	echo "rabbit_misc:start_cover([\"hare\"])." | $(ERL_CALL)
   239 
   240 stop-cover: all
   241 	echo "rabbit_misc:report_cover(), cover:stop()." | $(ERL_CALL)
   242 	cat cover/summary.txt
   243 
   244 ########################################################################
   245 
   246 srcdist: distclean
   247 	mkdir -p $(TARGET_SRC_DIR)/codegen
   248 	cp -r ebin src include LICENSE LICENSE-MPL-RabbitMQ INSTALL README $(TARGET_SRC_DIR)
   249 	sed 's/%%VSN%%/$(VERSION)/' $(TARGET_SRC_DIR)/ebin/rabbit_app.in > $(TARGET_SRC_DIR)/ebin/rabbit_app.in.tmp && \
   250 		mv $(TARGET_SRC_DIR)/ebin/rabbit_app.in.tmp $(TARGET_SRC_DIR)/ebin/rabbit_app.in
   251 
   252 	cp -r $(AMQP_CODEGEN_DIR)/* $(TARGET_SRC_DIR)/codegen/
   253 	cp codegen.py Makefile generate_app generate_deps calculate-relative $(TARGET_SRC_DIR)
   254 
   255 	cp -r scripts $(TARGET_SRC_DIR)
   256 	cp -r $(DOCS_DIR) $(TARGET_SRC_DIR)
   257 	chmod 0755 $(TARGET_SRC_DIR)/scripts/*
   258 
   259 ifneq "$(PLUGINS_SRC_DIR)" ""
   260 	cp -r $(PLUGINS_SRC_DIR) $(TARGET_SRC_DIR)/plugins-src
   261 	rm $(TARGET_SRC_DIR)/LICENSE
   262 	cat packaging/common/LICENSE.head >> $(TARGET_SRC_DIR)/LICENSE
   263 	cat $(AMQP_CODEGEN_DIR)/license_info >> $(TARGET_SRC_DIR)/LICENSE
   264 	find $(PLUGINS_SRC_DIR)/licensing -name "license_info_*" -exec cat '{}' >> $(TARGET_SRC_DIR)/LICENSE \;
   265 	cat packaging/common/LICENSE.tail >> $(TARGET_SRC_DIR)/LICENSE
   266 	find $(PLUGINS_SRC_DIR)/licensing -name "LICENSE-*" -exec cp '{}' $(TARGET_SRC_DIR) \;
   267 	rm -rf $(TARGET_SRC_DIR)/licensing
   268 else
   269 	@echo No plugins source distribution found
   270 endif
   271 
   272 	(cd dist; tar -zchf $(TARBALL_NAME).tar.gz $(TARBALL_NAME))
   273 	(cd dist; zip -q -r $(TARBALL_NAME).zip $(TARBALL_NAME))
   274 	rm -rf $(TARGET_SRC_DIR)
   275 
   276 distclean: clean
   277 	$(MAKE) -C $(AMQP_CODEGEN_DIR) distclean
   278 	rm -rf dist
   279 	find . -regex '.*\(~\|#\|\.swp\|\.dump\)' -exec rm {} \;
   280 
   281 # xmlto can not read from standard input, so we mess with a tmp file.
   282 %.gz: %.xml $(DOCS_DIR)/examples-to-end.xsl
   283 	xmlto --version | grep -E '^xmlto version 0\.0\.([0-9]|1[1-8])$$' >/dev/null || opt='--stringparam man.indent.verbatims=0' ; \
   284 	    xsltproc --novalid $(DOCS_DIR)/examples-to-end.xsl $< > $<.tmp && \
   285 	    xmlto -o $(DOCS_DIR) $$opt man $<.tmp && \
   286 	    gzip -f $(DOCS_DIR)/`basename $< .xml`
   287 	rm -f $<.tmp
   288 
   289 # Use tmp files rather than a pipeline so that we get meaningful errors
   290 # Do not fold the cp into previous line, it's there to stop the file being
   291 # generated but empty if we fail
   292 $(SOURCE_DIR)/%_usage.erl:
   293 	xsltproc --novalid --stringparam modulename "`basename $@ .erl`" \
   294 		$(DOCS_DIR)/usage.xsl $< > $@.tmp
   295 	sed -e 's/"/\\"/g' -e 's/%QUOTE%/"/g' $@.tmp > $@.tmp2
   296 	fold -s $@.tmp2 > $@.tmp3
   297 	mv $@.tmp3 $@
   298 	rm $@.tmp $@.tmp2
   299 
   300 # We rename the file before xmlto sees it since xmlto will use the name of
   301 # the file to make internal links.
   302 %.man.xml: %.xml $(DOCS_DIR)/html-to-website-xml.xsl
   303 	cp $< `basename $< .xml`.xml && \
   304 		xmlto xhtml-nochunks `basename $< .xml`.xml ; rm `basename $< .xml`.xml
   305 	cat `basename $< .xml`.html | \
   306 	    xsltproc --novalid $(DOCS_DIR)/remove-namespaces.xsl - | \
   307 		xsltproc --novalid --stringparam original `basename $<` $(DOCS_DIR)/html-to-website-xml.xsl - | \
   308 		xmllint --format - > $@
   309 	rm `basename $< .xml`.html
   310 
   311 docs_all: $(MANPAGES) $(WEB_MANPAGES)
   312 
   313 install: install_bin install_docs
   314 
   315 install_bin: all install_dirs
   316 	cp -r ebin include LICENSE* INSTALL $(TARGET_DIR)
   317 
   318 	chmod 0755 scripts/*
   319 	for script in rabbitmq-env rabbitmq-server rabbitmqctl rabbitmq-plugins; do \
   320 		cp scripts/$$script $(TARGET_DIR)/sbin; \
   321 		[ -e $(SBIN_DIR)/$$script ] || ln -s $(SCRIPTS_REL_PATH)/$$script $(SBIN_DIR)/$$script; \
   322 	done
   323 
   324 	mkdir -p $(TARGET_DIR)/$(PLUGINS_DIR)
   325 	[ -d "$(PLUGINS_DIR)" ] && cp $(PLUGINS_DIR)/*.ez $(PLUGINS_DIR)/README $(TARGET_DIR)/$(PLUGINS_DIR) || true
   326 
   327 install_docs: docs_all install_dirs
   328 	for section in 1 5; do \
   329 		mkdir -p $(MAN_DIR)/man$$section; \
   330 		for manpage in $(DOCS_DIR)/*.$$section.gz; do \
   331 			cp $$manpage $(MAN_DIR)/man$$section; \
   332 		done; \
   333 	done
   334 
   335 install_dirs:
   336 	@ OK=true && \
   337 	  { [ -n "$(TARGET_DIR)" ] || { echo "Please set TARGET_DIR."; OK=false; }; } && \
   338 	  { [ -n "$(SBIN_DIR)" ] || { echo "Please set SBIN_DIR."; OK=false; }; } && \
   339 	  { [ -n "$(MAN_DIR)" ] || { echo "Please set MAN_DIR."; OK=false; }; } && $$OK
   340 
   341 	mkdir -p $(TARGET_DIR)/sbin
   342 	mkdir -p $(SBIN_DIR)
   343 	mkdir -p $(MAN_DIR)
   344 
   345 $(foreach XML,$(USAGES_XML),$(eval $(call usage_dep, $(XML))))
   346 
   347 # Note that all targets which depend on clean must have clean in their
   348 # name.  Also any target that doesn't depend on clean should not have
   349 # clean in its name, unless you know that you don't need any of the
   350 # automatic dependency generation for that target (eg cleandb).
   351 
   352 # We want to load the dep file if *any* target *doesn't* contain
   353 # "clean" - i.e. if removing all clean-like targets leaves something
   354 
   355 ifeq "$(MAKECMDGOALS)" ""
   356 TESTABLEGOALS:=$(.DEFAULT_GOAL)
   357 else
   358 TESTABLEGOALS:=$(MAKECMDGOALS)
   359 endif
   360 
   361 ifneq "$(strip $(patsubst clean%,,$(patsubst %clean,,$(TESTABLEGOALS))))" ""
   362 -include $(DEPS_FILE)
   363 endif
   364 
   365 .PHONY: run-qc