summaryrefslogtreecommitdiff
path: root/deps/rabbit_common/mk
diff options
context:
space:
mode:
authordcorbacho <dparracorbacho@piotal.io>2020-11-18 14:27:41 +0000
committerdcorbacho <dparracorbacho@piotal.io>2020-11-18 14:27:41 +0000
commitf23a51261d9502ec39df0f8db47ba6b22aa7659f (patch)
tree53dcdf46e7dc2c14e81ee960bce8793879b488d3 /deps/rabbit_common/mk
parentafa2c2bf6c7e0e9b63f4fb53dc931c70388e1c82 (diff)
parent9f6d64ec4a4b1eeac24d7846c5c64fd96798d892 (diff)
downloadrabbitmq-server-git-stream-timestamp-offset.tar.gz
Merge remote-tracking branch 'origin/master' into stream-timestamp-offsetstream-timestamp-offset
Diffstat (limited to 'deps/rabbit_common/mk')
-rw-r--r--deps/rabbit_common/mk/rabbitmq-build.mk42
-rw-r--r--deps/rabbit_common/mk/rabbitmq-components.hexpm.mk36
-rw-r--r--deps/rabbit_common/mk/rabbitmq-components.mk359
-rw-r--r--deps/rabbit_common/mk/rabbitmq-dist.mk365
-rw-r--r--deps/rabbit_common/mk/rabbitmq-early-plugin.mk3
-rw-r--r--deps/rabbit_common/mk/rabbitmq-early-test.mk130
-rw-r--r--deps/rabbit_common/mk/rabbitmq-hexpm.mk67
-rw-r--r--deps/rabbit_common/mk/rabbitmq-macros.mk22
-rw-r--r--deps/rabbit_common/mk/rabbitmq-plugin.mk23
-rw-r--r--deps/rabbit_common/mk/rabbitmq-run.mk428
-rw-r--r--deps/rabbit_common/mk/rabbitmq-test.mk80
-rw-r--r--deps/rabbit_common/mk/rabbitmq-tools.mk429
-rwxr-xr-xdeps/rabbit_common/mk/xrefr338
13 files changed, 2322 insertions, 0 deletions
diff --git a/deps/rabbit_common/mk/rabbitmq-build.mk b/deps/rabbit_common/mk/rabbitmq-build.mk
new file mode 100644
index 0000000000..2fedcf629b
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-build.mk
@@ -0,0 +1,42 @@
+# --------------------------------------------------------------------
+# Compiler flags.
+# --------------------------------------------------------------------
+
+ifeq ($(filter rabbitmq-macros.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-macros.mk
+endif
+
+# NOTE: This plugin is loaded twice because Erlang.mk recurses. That's
+# why ERL_LIBS may contain twice the path to Elixir libraries or
+# ERLC_OPTS may contain duplicated flags.
+
+TEST_ERLC_OPTS += +nowarn_export_all
+
+ifneq ($(filter-out rabbit_common amqp_client,$(PROJECT)),)
+# Add the CLI ebin directory to the code path for the compiler: plugin
+# CLI extensions may access behaviour modules defined in this directory.
+RMQ_ERLC_OPTS += -pa $(DEPS_DIR)/rabbitmq_cli/_build/dev/lib/rabbitmqctl/ebin
+endif
+
+# Add Lager parse_transform module and our default Lager extra sinks.
+LAGER_EXTRA_SINKS += rabbit_log \
+ rabbit_log_channel \
+ rabbit_log_connection \
+ rabbit_log_feature_flags \
+ rabbit_log_federation \
+ rabbit_log_ldap \
+ rabbit_log_mirroring \
+ rabbit_log_osiris \
+ rabbit_log_prelaunch \
+ rabbit_log_queue \
+ rabbit_log_ra \
+ rabbit_log_shovel \
+ rabbit_log_upgrade
+lager_extra_sinks = $(subst $(space),$(comma),$(LAGER_EXTRA_SINKS))
+
+RMQ_ERLC_OPTS += +'{parse_transform,lager_transform}' \
+ +'{lager_extra_sinks,[$(lager_extra_sinks)]}'
+
+# Push our compilation options to both the normal and test ERLC_OPTS.
+ERLC_OPTS += $(RMQ_ERLC_OPTS)
+TEST_ERLC_OPTS += $(RMQ_ERLC_OPTS)
diff --git a/deps/rabbit_common/mk/rabbitmq-components.hexpm.mk b/deps/rabbit_common/mk/rabbitmq-components.hexpm.mk
new file mode 100644
index 0000000000..4b110176a7
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-components.hexpm.mk
@@ -0,0 +1,36 @@
+ifeq ($(.DEFAULT_GOAL),)
+# Define default goal to `all` because this file defines some targets
+# before the inclusion of erlang.mk leading to the wrong target becoming
+# the default.
+.DEFAULT_GOAL = all
+endif
+
+# PROJECT_VERSION defaults to:
+# 1. the version exported by rabbitmq-server-release;
+# 2. the version stored in `git-revisions.txt`, if it exists;
+# 3. a version based on git-describe(1), if it is a Git clone;
+# 4. 0.0.0
+
+PROJECT_VERSION := $(RABBITMQ_VERSION)
+
+ifeq ($(PROJECT_VERSION),)
+PROJECT_VERSION := $(shell \
+if test -f git-revisions.txt; then \
+ head -n1 git-revisions.txt | \
+ awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \
+else \
+ (git describe --dirty --abbrev=7 --tags --always --first-parent \
+ 2>/dev/null || echo rabbitmq_v0_0_0) | \
+ sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \
+ -e 's/-/./g'; \
+fi)
+endif
+
+# --------------------------------------------------------------------
+# RabbitMQ components.
+# --------------------------------------------------------------------
+
+dep_amqp_client = hex $(PROJECT_VERSION)
+dep_rabbit_common = hex $(PROJECT_VERSION)
+
+# Third-party dependencies version pinning.
diff --git a/deps/rabbit_common/mk/rabbitmq-components.mk b/deps/rabbit_common/mk/rabbitmq-components.mk
new file mode 100644
index 0000000000..b2a3be8b35
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-components.mk
@@ -0,0 +1,359 @@
+ifeq ($(.DEFAULT_GOAL),)
+# Define default goal to `all` because this file defines some targets
+# before the inclusion of erlang.mk leading to the wrong target becoming
+# the default.
+.DEFAULT_GOAL = all
+endif
+
+# PROJECT_VERSION defaults to:
+# 1. the version exported by rabbitmq-server-release;
+# 2. the version stored in `git-revisions.txt`, if it exists;
+# 3. a version based on git-describe(1), if it is a Git clone;
+# 4. 0.0.0
+
+PROJECT_VERSION := $(RABBITMQ_VERSION)
+
+ifeq ($(PROJECT_VERSION),)
+PROJECT_VERSION := $(shell \
+if test -f git-revisions.txt; then \
+ head -n1 git-revisions.txt | \
+ awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \
+else \
+ (git describe --dirty --abbrev=7 --tags --always --first-parent \
+ 2>/dev/null || echo rabbitmq_v0_0_0) | \
+ sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \
+ -e 's/-/./g'; \
+fi)
+endif
+
+# --------------------------------------------------------------------
+# RabbitMQ components.
+# --------------------------------------------------------------------
+
+# For RabbitMQ repositories, we want to checkout branches which match
+# the parent project. For instance, if the parent project is on a
+# release tag, dependencies must be on the same release tag. If the
+# parent project is on a topic branch, dependencies must be on the same
+# topic branch or fallback to `stable` or `master` whichever was the
+# base of the topic branch.
+
+dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master
+dep_amqp10_client = git_rmq rabbitmq-amqp1.0-client $(current_rmq_ref) $(base_rmq_ref) master
+dep_amqp10_common = git_rmq rabbitmq-amqp1.0-common $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_auth_backend_oauth2 = git_rmq rabbitmq-auth-backend-oauth2 $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_aws = git_rmq rabbitmq-aws $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_boot_steps_visualiser = git_rmq rabbitmq-boot-steps-visualiser $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_cli = git_rmq rabbitmq-cli $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_codegen = git_rmq rabbitmq-codegen $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_consistent_hash_exchange = git_rmq rabbitmq-consistent-hash-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_ct_client_helpers = git_rmq rabbitmq-ct-client-helpers $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_ct_helpers = git_rmq rabbitmq-ct-helpers $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_delayed_message_exchange = git_rmq rabbitmq-delayed-message-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_dotnet_client = git_rmq rabbitmq-dotnet-client $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_event_exchange = git_rmq rabbitmq-event-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_lvc_exchange = git_rmq rabbitmq-lvc-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_management_agent = git_rmq rabbitmq-management-agent $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_management_exchange = git_rmq rabbitmq-management-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_management_themes = git_rmq rabbitmq-management-themes $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_message_timestamp = git_rmq rabbitmq-message-timestamp $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_metronome = git_rmq rabbitmq-metronome $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_mqtt = git_rmq rabbitmq-mqtt $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_objc_client = git_rmq rabbitmq-objc-client $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_peer_discovery_aws = git_rmq rabbitmq-peer-discovery-aws $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_peer_discovery_common = git_rmq rabbitmq-peer-discovery-common $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_peer_discovery_consul = git_rmq rabbitmq-peer-discovery-consul $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_peer_discovery_etcd = git_rmq rabbitmq-peer-discovery-etcd $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_peer_discovery_k8s = git_rmq rabbitmq-peer-discovery-k8s $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_prometheus = git_rmq rabbitmq-prometheus $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_random_exchange = git_rmq rabbitmq-random-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_recent_history_exchange = git_rmq rabbitmq-recent-history-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_routing_node_stamp = git_rmq rabbitmq-routing-node-stamp $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_rtopic_exchange = git_rmq rabbitmq-rtopic-exchange $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_server_release = git_rmq rabbitmq-server-release $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_sharding = git_rmq rabbitmq-sharding $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_stream = git_rmq rabbitmq-stream $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_trust_store = git_rmq rabbitmq-trust-store $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_test = git_rmq rabbitmq-test $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_web_dispatch = git_rmq rabbitmq-web-dispatch $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_web_stomp = git_rmq rabbitmq-web-stomp $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_web_stomp_examples = git_rmq rabbitmq-web-stomp-examples $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master
+dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master
+dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master
+
+dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master
+
+# Third-party dependencies version pinning.
+#
+# We do that in this file, which is copied in all projects, to ensure
+# all projects use the same versions. It avoids conflicts and makes it
+# possible to work with rabbitmq-public-umbrella.
+
+dep_accept = hex 0.3.5
+dep_cowboy = hex 2.8.0
+dep_cowlib = hex 2.9.1
+dep_jsx = hex 2.11.0
+dep_lager = hex 3.8.0
+dep_prometheus = git https://github.com/deadtrickster/prometheus.erl.git master
+dep_ra = git https://github.com/rabbitmq/ra.git master
+dep_ranch = hex 1.7.1
+dep_recon = hex 2.5.1
+dep_observer_cli = hex 1.5.4
+dep_stdout_formatter = hex 0.2.4
+dep_sysmon_handler = hex 1.3.0
+
+RABBITMQ_COMPONENTS = amqp_client \
+ amqp10_common \
+ amqp10_client \
+ rabbit \
+ rabbit_common \
+ rabbitmq_amqp1_0 \
+ rabbitmq_auth_backend_amqp \
+ rabbitmq_auth_backend_cache \
+ rabbitmq_auth_backend_http \
+ rabbitmq_auth_backend_ldap \
+ rabbitmq_auth_backend_oauth2 \
+ rabbitmq_auth_mechanism_ssl \
+ rabbitmq_aws \
+ rabbitmq_boot_steps_visualiser \
+ rabbitmq_cli \
+ rabbitmq_codegen \
+ rabbitmq_consistent_hash_exchange \
+ rabbitmq_ct_client_helpers \
+ rabbitmq_ct_helpers \
+ rabbitmq_delayed_message_exchange \
+ rabbitmq_dotnet_client \
+ rabbitmq_event_exchange \
+ rabbitmq_federation \
+ rabbitmq_federation_management \
+ rabbitmq_java_client \
+ rabbitmq_jms_client \
+ rabbitmq_jms_cts \
+ rabbitmq_jms_topic_exchange \
+ rabbitmq_lvc_exchange \
+ rabbitmq_management \
+ rabbitmq_management_agent \
+ rabbitmq_management_exchange \
+ rabbitmq_management_themes \
+ rabbitmq_message_timestamp \
+ rabbitmq_metronome \
+ rabbitmq_mqtt \
+ rabbitmq_objc_client \
+ rabbitmq_peer_discovery_aws \
+ rabbitmq_peer_discovery_common \
+ rabbitmq_peer_discovery_consul \
+ rabbitmq_peer_discovery_etcd \
+ rabbitmq_peer_discovery_k8s \
+ rabbitmq_prometheus \
+ rabbitmq_random_exchange \
+ rabbitmq_recent_history_exchange \
+ rabbitmq_routing_node_stamp \
+ rabbitmq_rtopic_exchange \
+ rabbitmq_server_release \
+ rabbitmq_sharding \
+ rabbitmq_shovel \
+ rabbitmq_shovel_management \
+ rabbitmq_stomp \
+ rabbitmq_stream \
+ rabbitmq_toke \
+ rabbitmq_top \
+ rabbitmq_tracing \
+ rabbitmq_trust_store \
+ rabbitmq_web_dispatch \
+ rabbitmq_web_mqtt \
+ rabbitmq_web_mqtt_examples \
+ rabbitmq_web_stomp \
+ rabbitmq_web_stomp_examples \
+ rabbitmq_website
+
+# Erlang.mk does not rebuild dependencies by default, once they were
+# compiled once, except for those listed in the `$(FORCE_REBUILD)`
+# variable.
+#
+# We want all RabbitMQ components to always be rebuilt: this eases
+# the work on several components at the same time.
+
+FORCE_REBUILD = $(RABBITMQ_COMPONENTS)
+
+# Several components have a custom erlang.mk/build.config, mainly
+# to disable eunit. Therefore, we can't use the top-level project's
+# erlang.mk copy.
+NO_AUTOPATCH += $(RABBITMQ_COMPONENTS)
+
+ifeq ($(origin current_rmq_ref),undefined)
+ifneq ($(wildcard .git),)
+current_rmq_ref := $(shell (\
+ ref=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}');\
+ if test "$$(git rev-parse --short HEAD)" != "$$ref"; then echo "$$ref"; fi))
+else
+current_rmq_ref := master
+endif
+endif
+export current_rmq_ref
+
+ifeq ($(origin base_rmq_ref),undefined)
+ifneq ($(wildcard .git),)
+possible_base_rmq_ref := master
+ifeq ($(possible_base_rmq_ref),$(current_rmq_ref))
+base_rmq_ref := $(current_rmq_ref)
+else
+base_rmq_ref := $(shell \
+ (git rev-parse --verify -q master >/dev/null && \
+ git rev-parse --verify -q $(possible_base_rmq_ref) >/dev/null && \
+ git merge-base --is-ancestor $$(git merge-base master HEAD) $(possible_base_rmq_ref) && \
+ echo $(possible_base_rmq_ref)) || \
+ echo master)
+endif
+else
+base_rmq_ref := master
+endif
+endif
+export base_rmq_ref
+
+# Repository URL selection.
+#
+# First, we infer other components' location from the current project
+# repository URL, if it's a Git repository:
+# - We take the "origin" remote URL as the base
+# - The current project name and repository name is replaced by the
+# target's properties:
+# eg. rabbitmq-common is replaced by rabbitmq-codegen
+# eg. rabbit_common is replaced by rabbitmq_codegen
+#
+# If cloning from this computed location fails, we fallback to RabbitMQ
+# upstream which is GitHub.
+
+# Macro to transform eg. "rabbit_common" to "rabbitmq-common".
+rmq_cmp_repo_name = $(word 2,$(dep_$(1)))
+
+# Upstream URL for the current project.
+RABBITMQ_COMPONENT_REPO_NAME := $(call rmq_cmp_repo_name,$(PROJECT))
+RABBITMQ_UPSTREAM_FETCH_URL ?= https://github.com/rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
+RABBITMQ_UPSTREAM_PUSH_URL ?= git@github.com:rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
+
+# Current URL for the current project. If this is not a Git clone,
+# default to the upstream Git repository.
+ifneq ($(wildcard .git),)
+git_origin_fetch_url := $(shell git config remote.origin.url)
+git_origin_push_url := $(shell git config remote.origin.pushurl || git config remote.origin.url)
+RABBITMQ_CURRENT_FETCH_URL ?= $(git_origin_fetch_url)
+RABBITMQ_CURRENT_PUSH_URL ?= $(git_origin_push_url)
+else
+RABBITMQ_CURRENT_FETCH_URL ?= $(RABBITMQ_UPSTREAM_FETCH_URL)
+RABBITMQ_CURRENT_PUSH_URL ?= $(RABBITMQ_UPSTREAM_PUSH_URL)
+endif
+
+# Macro to replace the following pattern:
+# 1. /foo.git -> /bar.git
+# 2. /foo -> /bar
+# 3. /foo/ -> /bar/
+subst_repo_name = $(patsubst %/$(1)/%,%/$(2)/%,$(patsubst %/$(1),%/$(2),$(patsubst %/$(1).git,%/$(2).git,$(3))))
+
+# Macro to replace both the project's name (eg. "rabbit_common") and
+# repository name (eg. "rabbitmq-common") by the target's equivalent.
+#
+# This macro is kept on one line because we don't want whitespaces in
+# the returned value, as it's used in $(dep_fetch_git_rmq) in a shell
+# single-quoted string.
+dep_rmq_repo = $(if $(dep_$(2)),$(call subst_repo_name,$(PROJECT),$(2),$(call subst_repo_name,$(RABBITMQ_COMPONENT_REPO_NAME),$(call rmq_cmp_repo_name,$(2)),$(1))),$(pkg_$(1)_repo))
+
+dep_rmq_commits = $(if $(dep_$(1)), \
+ $(wordlist 3,$(words $(dep_$(1))),$(dep_$(1))), \
+ $(pkg_$(1)_commit))
+
+define dep_fetch_git_rmq
+ fetch_url1='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(1))'; \
+ fetch_url2='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_FETCH_URL),$(1))'; \
+ if test "$$$$fetch_url1" != '$(RABBITMQ_CURRENT_FETCH_URL)' && \
+ git clone -q -n -- "$$$$fetch_url1" $(DEPS_DIR)/$(call dep_name,$(1)); then \
+ fetch_url="$$$$fetch_url1"; \
+ push_url='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(1))'; \
+ elif git clone -q -n -- "$$$$fetch_url2" $(DEPS_DIR)/$(call dep_name,$(1)); then \
+ fetch_url="$$$$fetch_url2"; \
+ push_url='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_PUSH_URL),$(1))'; \
+ fi; \
+ cd $(DEPS_DIR)/$(call dep_name,$(1)) && ( \
+ $(foreach ref,$(call dep_rmq_commits,$(1)), \
+ git checkout -q $(ref) >/dev/null 2>&1 || \
+ ) \
+ (echo "error: no valid pathspec among: $(call dep_rmq_commits,$(1))" \
+ 1>&2 && false) ) && \
+ (test "$$$$fetch_url" = "$$$$push_url" || \
+ git remote set-url --push origin "$$$$push_url")
+endef
+
+# --------------------------------------------------------------------
+# Component distribution.
+# --------------------------------------------------------------------
+
+list-dist-deps::
+ @:
+
+prepare-dist::
+ @:
+
+# --------------------------------------------------------------------
+# Umbrella-specific settings.
+# --------------------------------------------------------------------
+
+# If the top-level project is a RabbitMQ component, we override
+# $(DEPS_DIR) for this project to point to the top-level's one.
+#
+# We also verify that the guessed DEPS_DIR is actually named `deps`,
+# to rule out any situation where it is a coincidence that we found a
+# `rabbitmq-components.mk` up upper directories.
+
+possible_deps_dir_1 = $(abspath ..)
+possible_deps_dir_2 = $(abspath ../../..)
+
+ifeq ($(notdir $(possible_deps_dir_1)),deps)
+ifneq ($(wildcard $(possible_deps_dir_1)/../rabbitmq-components.mk),)
+deps_dir_overriden = 1
+DEPS_DIR ?= $(possible_deps_dir_1)
+DISABLE_DISTCLEAN = 1
+endif
+endif
+
+ifeq ($(deps_dir_overriden),)
+ifeq ($(notdir $(possible_deps_dir_2)),deps)
+ifneq ($(wildcard $(possible_deps_dir_2)/../rabbitmq-components.mk),)
+deps_dir_overriden = 1
+DEPS_DIR ?= $(possible_deps_dir_2)
+DISABLE_DISTCLEAN = 1
+endif
+endif
+endif
+
+ifneq ($(wildcard UMBRELLA.md),)
+DISABLE_DISTCLEAN = 1
+endif
+
+# We disable `make distclean` so $(DEPS_DIR) is not accidentally removed.
+
+ifeq ($(DISABLE_DISTCLEAN),1)
+ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),)
+SKIP_DEPS = 1
+endif
+endif
diff --git a/deps/rabbit_common/mk/rabbitmq-dist.mk b/deps/rabbit_common/mk/rabbitmq-dist.mk
new file mode 100644
index 0000000000..3e17a27939
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-dist.mk
@@ -0,0 +1,365 @@
+.PHONY: dist test-dist do-dist cli-scripts cli-escripts clean-dist
+
+DIST_DIR = plugins
+CLI_SCRIPTS_DIR = sbin
+CLI_ESCRIPTS_DIR = escript
+MIX = echo y | mix
+
+# Set $(DIST_AS_EZS) to a non-empty value to enable the packaging of
+# plugins as .ez archives.
+ifeq ($(USE_RABBIT_BOOT_SCRIPT),)
+DIST_AS_EZS ?=
+else
+DIST_AS_EZS =
+endif
+
+dist_verbose_0 = @echo " DIST " $@;
+dist_verbose_2 = set -x;
+dist_verbose = $(dist_verbose_$(V))
+
+MIX_ARCHIVES ?= $(HOME)/.mix/archives
+
+MIX_TASK_ARCHIVE_DEPS_VERSION = 0.5.0
+mix_task_archive_deps = $(MIX_ARCHIVES)/mix_task_archive_deps-$(MIX_TASK_ARCHIVE_DEPS_VERSION)
+
+# We take the version of an Erlang application from the .app file. This
+# macro is called like this:
+#
+# $(call get_app_version,/path/to/name.app.src)
+
+ifeq ($(PLATFORM),msys2)
+core_unix_path = $(shell cygpath $1)
+else
+core_unix_path = $1
+endif
+
+define get_app_version
+$(shell awk '
+/{ *vsn *, *"/ {
+ vsn=$$0;
+ sub(/.*{ *vsn, *"/, "", vsn);
+ sub(/".*/, "", vsn);
+ print vsn;
+ exit;
+}' $(1))
+endef
+
+define get_mix_project_version
+$(shell cd $(1) && \
+ $(MIX) do deps.get, deps.compile, compile >/dev/null && \
+ $(MIX) run --no-start -e "IO.puts(Mix.Project.config[:version])")
+endef
+
+# Define the target to create an .ez plugin archive for an
+# Erlang.mk-based project. This macro is called like this:
+#
+# $(call do_ez_target_erlangmk,app_name,app_version,app_dir)
+
+define do_ez_target_erlangmk
+dist_$(1)_ez_dir = $$(if $(2),$(DIST_DIR)/$(1)-$(2), \
+ $$(if $$(VERSION),$(DIST_DIR)/$(1)-$$(VERSION),$(DIST_DIR)/$(1)))
+ifeq ($(DIST_AS_EZS),)
+dist_$(1)_ez = $$(dist_$(1)_ez_dir)
+else
+dist_$(1)_ez = $$(dist_$(1)_ez_dir).ez
+endif
+
+$$(dist_$(1)_ez): APP = $(1)
+$$(dist_$(1)_ez): VSN = $(2)
+$$(dist_$(1)_ez): SRC_DIR = $(3)
+$$(dist_$(1)_ez): EZ_DIR = $$(abspath $$(dist_$(1)_ez_dir))
+$$(dist_$(1)_ez): EZ = $$(dist_$(1)_ez)
+$$(dist_$(1)_ez): $$(if $$(wildcard $(3)/ebin $(3)/include $(3)/priv),\
+ $$(filter-out %/dep_built %/ebin/test,$$(call core_find,$$(wildcard $(3)/ebin $(3)/include $(3)/priv),*)),)
+
+# If the application's Makefile defines a `list-dist-deps` target, we
+# use it to populate the dependencies list. This is useful when the
+# application has also a `prepare-dist` target to modify the created
+# tree before we make an archive out of it.
+
+ifeq ($$(shell test -f $(3)/rabbitmq-components.mk \
+ && grep -q '^list-dist-deps::' $(3)/Makefile && echo yes),yes)
+$$(dist_$(1)_ez): $$(patsubst %,$(3)/%, \
+ $$(shell $(MAKE) --no-print-directory -C $(3) list-dist-deps \
+ APP=$(1) VSN=$(2) EZ_DIR=$$(abspath $$(dist_$(1)_ez_dir))))
+endif
+
+ERLANGMK_DIST_APPS += $(1)
+
+ERLANGMK_DIST_EZS += $$(dist_$(1)_ez)
+
+endef
+
+# Define the target to create an .ez plugin archive for a Mix-based
+# project. This macro is called like this:
+#
+# $(call do_ez_target_mix,app_name,app_version,app_dir)
+
+define get_mix_project_dep_ezs
+$(shell cd $(1) && \
+ $(MIX) do deps.get, deps.compile, compile >/dev/null && \
+ $(MIX) archive.build.all.list -e -o $(DIST_DIR) --skip "rabbit $(ERLANGMK_DIST_APPS)")
+endef
+
+define do_ez_target_mix
+dist_$(1)_ez_dir = $$(if $(2),$(DIST_DIR)/$(1)-$(2), \
+ $$(if $$(VERSION),$(DIST_DIR)/$(1)-$$(VERSION),$(DIST_DIR)/$(1)))
+dist_$(1)_ez = $$(dist_$(1)_ez_dir).ez
+
+$$(dist_$(1)_ez): APP = $(1)
+$$(dist_$(1)_ez): VSN = $(2)
+$$(dist_$(1)_ez): SRC_DIR = $(3)
+$$(dist_$(1)_ez): EZ_DIR = $$(abspath $$(dist_$(1)_ez_dir))
+$$(dist_$(1)_ez): EZ = $$(dist_$(1)_ez)
+$$(dist_$(1)_ez): $$(if $$(wildcard _build/dev/lib/$(1)/ebin $(3)/priv),\
+ $$(filter-out %/dep_built,$$(call core_find,$$(wildcard _build/dev/lib/$(1)/ebin $(3)/priv),*)),)
+
+MIX_DIST_EZS += $$(dist_$(1)_ez)
+EXTRA_DIST_EZS += $$(call get_mix_project_dep_ezs,$(3))
+
+endef
+
+# Real entry point: it tests the existence of an .app file to determine
+# if it is an Erlang application (and therefore if it should be provided
+# as an .ez plugin archive) and calls do_ez_target_erlangmk. If instead
+# it finds a Mix configuration file, it calls do_ez_target_mix. It
+# should be called as:
+#
+# $(call ez_target,path_to_app)
+
+define ez_target
+dist_$(1)_appdir = $(2)
+dist_$(1)_appfile = $$(dist_$(1)_appdir)/ebin/$(1).app
+dist_$(1)_mixfile = $$(dist_$(1)_appdir)/mix.exs
+
+$$(if $$(shell test -f $$(dist_$(1)_appfile) && echo OK), \
+ $$(eval $$(call do_ez_target_erlangmk,$(1),$$(call get_app_version,$$(dist_$(1)_appfile)),$$(dist_$(1)_appdir))), \
+ $$(if $$(shell test -f $$(dist_$(1)_mixfile) && [ "x$(1)" != "xrabbitmqctl" ] && [ "x$(1)" != "xrabbitmq_cli" ] && echo OK), \
+ $$(eval $$(call do_ez_target_mix,$(1),$$(call get_mix_project_version,$$(dist_$(1)_appdir)),$$(dist_$(1)_appdir)))))
+
+endef
+
+ifneq ($(filter do-dist,$(MAKECMDGOALS)),)
+# The following code is evaluated only when running "make do-dist",
+# otherwise it would trigger an infinite loop, as this code calls "make
+# list-dist-deps" (see do_ez_target_erlangmk).
+ifdef DIST_PLUGINS_LIST
+# Now, try to create an .ez target for the top-level project and all
+# dependencies.
+
+ifeq ($(wildcard $(DIST_PLUGINS_LIST)),)
+$(error DIST_PLUGINS_LIST ($(DIST_PLUGINS_LIST)) is missing)
+endif
+
+$(eval $(foreach path, \
+ $(filter-out %/looking_glass %/lz4, \
+ $(sort $(shell cat $(DIST_PLUGINS_LIST))) $(CURDIR)), \
+ $(call ez_target,$(if $(filter $(path),$(CURDIR)),$(PROJECT),$(notdir $(path))),$(path))))
+endif
+endif
+
+# The actual recipe to create the .ez plugin archive. Some variables
+# are defined in the do_ez_target_erlangmk and do_ez_target_mix macros
+# above. All .ez archives are also listed in this do_ez_target_erlangmk
+# and do_ez_target_mix macros.
+
+RSYNC ?= rsync
+RSYNC_V_0 =
+RSYNC_V_1 = -v
+RSYNC_V = $(RSYNC_V_$(V))
+
+ZIP ?= zip
+ZIP_V_0 = -q
+ZIP_V_1 =
+ZIP_V = $(ZIP_V_$(V))
+
+$(ERLANGMK_DIST_EZS):
+ $(verbose) rm -rf $(EZ_DIR) $(EZ)
+ $(verbose) mkdir -p $(EZ_DIR)
+ $(dist_verbose) $(RSYNC) -a $(RSYNC_V) \
+ --exclude '/ebin/dep_built' \
+ --exclude '/ebin/test' \
+ --include '/ebin/***' \
+ --include '/include/***' \
+ --include '/priv/***' \
+ --exclude '*' \
+ $(call core_unix_path,$(SRC_DIR))/ $(call core_unix_path,$(EZ_DIR))/
+ @# Give a chance to the application to make any modification it
+ @# wants to the tree before we make an archive.
+ $(verbose) ! (test -f $(SRC_DIR)/rabbitmq-components.mk \
+ && grep -q '^prepare-dist::' $(SRC_DIR)/Makefile) || \
+ $(MAKE) --no-print-directory -C $(SRC_DIR) prepare-dist \
+ APP=$(APP) VSN=$(VSN) EZ_DIR=$(EZ_DIR)
+ifneq ($(DIST_AS_EZS),)
+ $(verbose) (cd $(DIST_DIR) && \
+ find "$(basename $(notdir $@))" | LC_COLLATE=C sort \
+ > "$(basename $(notdir $@)).manifest" && \
+ $(ZIP) $(ZIP_V) --names-stdin "$(notdir $@)" \
+ < "$(basename $(notdir $@)).manifest")
+ $(verbose) rm -rf $(EZ_DIR) $(EZ_DIR).manifest
+endif
+
+$(MIX_DIST_EZS): $(mix_task_archive_deps)
+ $(verbose) cd $(SRC_DIR) && \
+ $(MIX) do deps.get, deps.compile, compile, archive.build.all \
+ -e -o $(abspath $(DIST_DIR)) --skip "rabbit $(ERLANGMK_DIST_APPS)"
+
+MIX_TASK_ARCHIVE_DEPS_URL = https://github.com/rabbitmq/mix_task_archive_deps/releases/download/$(MIX_TASK_ARCHIVE_DEPS_VERSION)/mix_task_archive_deps-$(MIX_TASK_ARCHIVE_DEPS_VERSION).ez
+
+$(mix_task_archive_deps):
+ $(gen_verbose) mix archive.install --force $(MIX_TASK_ARCHIVE_DEPS_URL)
+
+# We need to recurse because the top-level make instance is evaluated
+# before dependencies are downloaded.
+
+MAYBE_APPS_LIST = $(if $(shell test -f $(ERLANG_MK_TMP)/apps.log && echo OK), \
+ $(ERLANG_MK_TMP)/apps.log)
+DIST_LOCK = $(DIST_DIR).lock
+
+dist:: $(ERLANG_MK_RECURSIVE_DEPS_LIST) all
+ $(gen_verbose) \
+ if command -v flock >/dev/null; then \
+ flock $(DIST_LOCK) \
+ sh -c '$(MAKE) do-dist \
+ DIST_PLUGINS_LIST="$(ERLANG_MK_RECURSIVE_DEPS_LIST) \
+ $(MAYBE_APPS_LIST)"'; \
+ elif command -v lockf >/dev/null; then \
+ lockf $(DIST_LOCK) \
+ sh -c '$(MAKE) do-dist \
+ DIST_PLUGINS_LIST="$(ERLANG_MK_RECURSIVE_DEPS_LIST) \
+ $(MAYBE_APPS_LIST)"'; \
+ else \
+ $(MAKE) do-dist \
+ DIST_PLUGINS_LIST="$(ERLANG_MK_RECURSIVE_DEPS_LIST) \
+ $(MAYBE_APPS_LIST)"; \
+ fi
+
+test-dist:: export TEST_DIR=NON-EXISTENT
+test-dist:: $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) test-build
+ $(gen_verbose) \
+ if command -v flock >/dev/null; then \
+ flock $(DIST_LOCK) \
+ sh -c '$(MAKE) do-dist \
+ DIST_PLUGINS_LIST="$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \
+ $(MAYBE_APPS_LIST)"'; \
+ elif command -v lockf >/dev/null; then \
+ lockf $(DIST_LOCK) \
+ sh -c '$(MAKE) do-dist \
+ DIST_PLUGINS_LIST="$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \
+ $(MAYBE_APPS_LIST)"'; \
+ else \
+ $(MAKE) do-dist \
+ DIST_PLUGINS_LIST="$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) \
+ $(MAYBE_APPS_LIST)"; \
+ fi
+
+DIST_EZS = $(ERLANGMK_DIST_EZS) $(MIX_DIST_EZS)
+
+do-dist:: $(DIST_EZS)
+ $(verbose) unwanted='$(filter-out $(DIST_EZS) $(EXTRA_DIST_EZS), \
+ $(wildcard $(DIST_DIR)/*))'; \
+ test -z "$$unwanted" || (echo " RM $$unwanted" && rm -rf $$unwanted)
+
+CLI_SCRIPTS_LOCK = $(CLI_SCRIPTS_DIR).lock
+CLI_ESCRIPTS_LOCK = $(CLI_ESCRIPTS_DIR).lock
+
+ifneq ($(filter-out rabbit_common amqp10_common,$(PROJECT)),)
+dist:: install-cli
+test-build:: install-cli
+endif
+
+install-cli: install-cli-scripts install-cli-escripts
+ @:
+
+ifeq ($(PROJECT),rabbit)
+install-cli-scripts:
+ $(gen_verbose) \
+ if command -v flock >/dev/null; then \
+ flock $(CLI_SCRIPTS_LOCK) \
+ sh -c 'mkdir -p "$(CLI_SCRIPTS_DIR)" && \
+ for file in scripts/*; do \
+ cmp -s "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")" || \
+ cp -a "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")"; \
+ done'; \
+ elif command -v lockf >/dev/null; then \
+ lockf $(CLI_SCRIPTS_LOCK) \
+ sh -c 'mkdir -p "$(CLI_SCRIPTS_DIR)" && \
+ for file in scripts/*; do \
+ cmp -s "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")" || \
+ cp -a "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")"; \
+ done'; \
+ else \
+ mkdir -p "$(CLI_SCRIPTS_DIR)" && \
+ for file in scripts/*; do \
+ cmp -s "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")" || \
+ cp -a "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")"; \
+ done; \
+ fi
+else
+
+install-cli-scripts:
+ $(gen_verbose) \
+ set -e; \
+ if test -d "$(DEPS_DIR)/rabbit/scripts"; then \
+ rabbit_scripts_dir='$(DEPS_DIR)/rabbit/scripts'; \
+ elif test -d "$(DEPS_DIR)/../scripts"; then \
+ rabbit_scripts_dir='$(DEPS_DIR)/../scripts'; \
+ else \
+ echo 'rabbit/scripts directory not found' 1>&2; \
+ exit 1; \
+ fi; \
+ test -d "$$rabbit_scripts_dir"; \
+ if command -v flock >/dev/null; then \
+ flock $(CLI_SCRIPTS_LOCK) \
+ sh -e -c 'mkdir -p "$(CLI_SCRIPTS_DIR)" && \
+ for file in "'$$rabbit_scripts_dir'"/*; do \
+ test -f "$$file"; \
+ cmp -s "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")" || \
+ cp -a "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")"; \
+ done'; \
+ elif command -v lockf >/dev/null; then \
+ lockf $(CLI_SCRIPTS_LOCK) \
+ sh -e -c 'mkdir -p "$(CLI_SCRIPTS_DIR)" && \
+ for file in "'$$rabbit_scripts_dir'"/*; do \
+ test -f "$$file"; \
+ cmp -s "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")" || \
+ cp -a "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")"; \
+ done'; \
+ else \
+ mkdir -p "$(CLI_SCRIPTS_DIR)" && \
+ for file in "$$rabbit_scripts_dir"/*; do \
+ test -f "$$file"; \
+ cmp -s "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")" || \
+ cp -a "$$file" "$(CLI_SCRIPTS_DIR)/$$(basename "$$file")"; \
+ done; \
+ fi
+endif
+
+install-cli-escripts:
+ $(gen_verbose) \
+ if command -v flock >/dev/null; then \
+ flock $(CLI_ESCRIPTS_LOCK) \
+ sh -c 'mkdir -p "$(CLI_ESCRIPTS_DIR)" && \
+ $(MAKE) -C "$(DEPS_DIR)/rabbitmq_cli" install \
+ PREFIX="$(abspath $(CLI_ESCRIPTS_DIR))" \
+ DESTDIR='; \
+ elif command -v lockf >/dev/null; then \
+ lockf $(CLI_ESCRIPTS_LOCK) \
+ sh -c 'mkdir -p "$(CLI_ESCRIPTS_DIR)" && \
+ $(MAKE) -C "$(DEPS_DIR)/rabbitmq_cli" install \
+ PREFIX="$(abspath $(CLI_ESCRIPTS_DIR))" \
+ DESTDIR='; \
+ else \
+ mkdir -p "$(CLI_ESCRIPTS_DIR)" && \
+ $(MAKE) -C "$(DEPS_DIR)/rabbitmq_cli" install \
+ PREFIX="$(abspath $(CLI_ESCRIPTS_DIR))" \
+ DESTDIR= ; \
+ fi
+
+clean-dist::
+ $(gen_verbose) rm -rf \
+ "$(DIST_DIR)" \
+ "$(CLI_SCRIPTS_DIR)" \
+ "$(CLI_ESCRIPTS_DIR)"
+
+clean:: clean-dist
diff --git a/deps/rabbit_common/mk/rabbitmq-early-plugin.mk b/deps/rabbit_common/mk/rabbitmq-early-plugin.mk
new file mode 100644
index 0000000000..7b5f14b8f9
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-early-plugin.mk
@@ -0,0 +1,3 @@
+ifeq ($(filter rabbitmq-early-test.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-early-test.mk
+endif
diff --git a/deps/rabbit_common/mk/rabbitmq-early-test.mk b/deps/rabbit_common/mk/rabbitmq-early-test.mk
new file mode 100644
index 0000000000..f4f00173b3
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-early-test.mk
@@ -0,0 +1,130 @@
+# --------------------------------------------------------------------
+# xref
+# --------------------------------------------------------------------
+
+ifeq ($(filter distclean distclean-xref,$(MAKECMDGOALS)),)
+ifneq ($(PROJECT),rabbit_common)
+XREFR := $(DEPS_DIR)/rabbit_common/mk/xrefr
+else
+XREFR := mk/xrefr
+endif
+endif
+
+# --------------------------------------------------------------------
+# dialyzer
+# --------------------------------------------------------------------
+
+DIALYZER_OPTS ?= -Werror_handling -Wrace_conditions
+
+# --------------------------------------------------------------------
+# %-on-concourse dependencies.
+# --------------------------------------------------------------------
+
+ifneq ($(words $(filter %-on-concourse,$(MAKECMDGOALS))),0)
+TEST_DEPS += ci $(RMQ_CI_CT_HOOKS)
+NO_AUTOPATCH += ci $(RMQ_CI_CT_HOOKS)
+dep_ci = git git@github.com:rabbitmq/rabbitmq-ci master
+endif
+
+# --------------------------------------------------------------------
+# Common Test flags.
+# --------------------------------------------------------------------
+
+# We start the common_test node as a hidden Erlang node. The benefit
+# is that other Erlang nodes won't try to connect to each other after
+# discovering the common_test node if they are not meant to.
+#
+# This helps when several unrelated RabbitMQ clusters are started in
+# parallel.
+
+CT_OPTS += -hidden
+
+# Enable the following common_test hooks on Travis and Concourse:
+#
+# cth_fail_fast
+# This hook will make sure the first failure puts an end to the
+# testsuites; ie. all remaining tests are skipped.
+#
+# cth_styledout
+# This hook will change the output of common_test to something more
+# concise and colored.
+#
+# On Jenkins, in addition to those common_test hooks, enable JUnit-like
+# report. Jenkins parses those reports so the results can be browsed
+# from its UI. Furthermore, it displays a graph showing evolution of the
+# results over time.
+
+ifndef TRAVIS
+CT_HOOKS ?= cth_styledout
+TEST_DEPS += cth_styledout
+endif
+
+ifdef TRAVIS
+FAIL_FAST = 1
+SKIP_AS_ERROR = 1
+endif
+
+ifdef CONCOURSE
+FAIL_FAST = 1
+SKIP_AS_ERROR = 1
+endif
+
+RMQ_CI_CT_HOOKS = cth_fail_fast
+ifeq ($(FAIL_FAST),1)
+CT_HOOKS += $(RMQ_CI_CT_HOOKS)
+TEST_DEPS += $(RMQ_CI_CT_HOOKS)
+endif
+
+dep_cth_fail_fast = git https://github.com/rabbitmq/cth_fail_fast.git master
+dep_cth_styledout = git https://github.com/rabbitmq/cth_styledout.git master
+
+CT_HOOKS_PARAM_VALUE = $(patsubst %,and %,$(CT_HOOKS))
+CT_OPTS += -ct_hooks $(wordlist 2,$(words $(CT_HOOKS_PARAM_VALUE)),$(CT_HOOKS_PARAM_VALUE))
+
+# Disable most messages on Travis because it might exceed the limit
+# set by Travis.
+#
+# CAUTION: All arguments after -erl_args are passed to the emulator and
+# common_test doesn't interpret them! Therefore, all common_test flags
+# *MUST* appear before.
+
+CT_QUIET_FLAGS = -verbosity 50 \
+ -erl_args \
+ -kernel error_logger silent
+
+ifdef TRAVIS
+CT_OPTS += $(CT_QUIET_FLAGS)
+endif
+
+# On CI, set $RABBITMQ_CT_SKIP_AS_ERROR so that any skipped
+# testsuite/testgroup/testcase is considered an error.
+
+ifeq ($(SKIP_AS_ERROR),1)
+export RABBITMQ_CT_SKIP_AS_ERROR = true
+endif
+
+# --------------------------------------------------------------------
+# Looking Glass rules.
+# --------------------------------------------------------------------
+
+ifneq ("$(RABBITMQ_TRACER)","")
+BUILD_DEPS += looking_glass
+dep_looking_glass = git https://github.com/rabbitmq/looking-glass master
+ERL_LIBS := "$(ERL_LIBS):../looking_glass:../lz4"
+export RABBITMQ_TRACER
+endif
+
+define lg_callgrind.erl
+lg_callgrind:profile_many("traces.lz4.*", "callgrind.out", #{running => true}),
+halt().
+endef
+
+.PHONY: profile clean-profile
+
+profile:
+ $(gen_verbose) $(call erlang,$(call lg_callgrind.erl))
+
+clean:: clean-profile
+
+clean-profile:
+ $(gen_verbose) rm -f traces.lz4.* callgrind.out.*
diff --git a/deps/rabbit_common/mk/rabbitmq-hexpm.mk b/deps/rabbit_common/mk/rabbitmq-hexpm.mk
new file mode 100644
index 0000000000..24281b1321
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-hexpm.mk
@@ -0,0 +1,67 @@
+# --------------------------------------------------------------------
+# Hex.pm.
+# --------------------------------------------------------------------
+
+.PHONY: hex-publish hex-publish-docs
+
+HEXPM_URL = https://github.com/rabbitmq/hexpm-cli/releases/latest/download/hexpm
+HEXPM_CLI = $(ERLANG_MK_TMP)/hexpm
+
+$(HEXPM_CLI):
+ $(verbose) mkdir -p $(ERLANG_MK_TMP)
+ $(gen_verbose) $(call core_http_get,$@,$(HEXPM_URL))
+ $(verbose) chmod +x $@
+
+RABBIT_COMMON_HEXPM_VERSION = $(PROJECT_VERSION)
+AMQP_CLIENT_HEXPM_VERSION = $(PROJECT_VERSION)
+
+rebar.config: dep_rabbit_common = hex $(RABBIT_COMMON_HEXPM_VERSION)
+rebar.config: dep_amqp_client = hex $(AMQP_CLIENT_HEXPM_VERSION)
+
+define RABBITMQ_HEXPM_DEFAULT_FILES
+ "erlang.mk",
+ "git-revisions.txt",
+ "include",
+ "LICENSE*",
+ "Makefile",
+ "rabbitmq-components.mk",
+ "README",
+ "README.md",
+ "src"
+endef
+
+ifeq ($(PROJECT),rabbit_common)
+RMQ_COMPONENTS_PREFIX = mk
+RMQ_COMPONENTS_HEXPM = mk/rabbitmq-components.hexpm.mk
+else
+RMQ_COMPONENTS_PREFIX = .
+RMQ_COMPONENTS_HEXPM = $(DEPS_DIR)/rabbit_common/mk/rabbitmq-components.hexpm.mk
+endif
+
+hex-publish: $(HEXPM_CLI) app rebar.config
+ $(gen_verbose) echo "$(PROJECT_DESCRIPTION) $(PROJECT_VERSION)" \
+ > git-revisions.txt
+ $(verbose) mv \
+ $(RMQ_COMPONENTS_PREFIX)/rabbitmq-components.mk \
+ rabbitmq-components.mk.not-hexpm
+ $(verbose) cp \
+ $(RMQ_COMPONENTS_HEXPM) \
+ $(RMQ_COMPONENTS_PREFIX)/rabbitmq-components.mk
+ $(verbose) grep -E '^dep.* = hex' \
+ rabbitmq-components.mk.not-hexpm \
+ >> $(RMQ_COMPONENTS_PREFIX)/rabbitmq-components.mk
+ $(verbose) touch -r \
+ rabbitmq-components.mk.not-hexpm \
+ $(RMQ_COMPONENTS_PREFIX)/rabbitmq-components.mk
+ $(verbose) trap '\
+ rm -f git-revisions.txt rebar.lock; \
+ if test -f rabbitmq-components.mk.not-hexpm; then \
+ mv \
+ rabbitmq-components.mk.not-hexpm \
+ $(RMQ_COMPONENTS_PREFIX)/rabbitmq-components.mk; \
+ fi' EXIT INT; \
+ $(HEXPM_CLI) publish
+
+hex-publish-docs: $(HEXPM_CLI) app docs
+ $(gen_verbose) trap 'rm -f rebar.lock' EXIT INT; \
+ $(HEXPM_CLI) docs
diff --git a/deps/rabbit_common/mk/rabbitmq-macros.mk b/deps/rabbit_common/mk/rabbitmq-macros.mk
new file mode 100644
index 0000000000..048745a7f0
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-macros.mk
@@ -0,0 +1,22 @@
+# Macro to compare two x.y.z versions.
+#
+# Usage:
+# ifeq ($(call compare_version,$(ERTS_VER),$(MAX_ERTS_VER),<),true)
+# # Only evaluated if $(ERTS_VER) < $(MAX_ERTS_VER)
+# endif
+
+define compare_version
+$(shell awk 'BEGIN {
+ split("$(1)", v1, ".");
+ version1 = v1[1] * 1000000 + v1[2] * 10000 + v1[3] * 100 + v1[4];
+
+ split("$(2)", v2, ".");
+ version2 = v2[1] * 1000000 + v2[2] * 10000 + v2[3] * 100 + v2[4];
+
+ if (version1 $(3) version2) {
+ print "true";
+ } else {
+ print "false";
+ }
+}')
+endef
diff --git a/deps/rabbit_common/mk/rabbitmq-plugin.mk b/deps/rabbit_common/mk/rabbitmq-plugin.mk
new file mode 100644
index 0000000000..29064a9a4f
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-plugin.mk
@@ -0,0 +1,23 @@
+ifeq ($(filter rabbitmq-build.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-build.mk
+endif
+
+ifeq ($(filter rabbitmq-hexpm.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-hexpm.mk
+endif
+
+ifeq ($(filter rabbitmq-dist.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-dist.mk
+endif
+
+ifeq ($(filter rabbitmq-run.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-run.mk
+endif
+
+ifeq ($(filter rabbitmq-test.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-test.mk
+endif
+
+ifeq ($(filter rabbitmq-tools.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-tools.mk
+endif
diff --git a/deps/rabbit_common/mk/rabbitmq-run.mk b/deps/rabbit_common/mk/rabbitmq-run.mk
new file mode 100644
index 0000000000..bef62c03f7
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-run.mk
@@ -0,0 +1,428 @@
+.PHONY: run-broker run-background-broker run-node run-background-node \
+ start-background-node start-rabbit-on-node \
+ stop-rabbit-on-node set-resource-alarm clear-resource-alarm \
+ stop-node
+
+ifeq ($(filter rabbitmq-dist.mk,$(notdir $(MAKEFILE_LIST))),)
+include $(dir $(lastword $(MAKEFILE_LIST)))rabbitmq-dist.mk
+endif
+
+exec_verbose_0 = @echo " EXEC " $@;
+exec_verbose_2 = set -x;
+exec_verbose = $(exec_verbose_$(V))
+
+ifeq ($(PLATFORM),msys2)
+TEST_TMPDIR ?= $(TEMP)/rabbitmq-test-instances
+else
+TMPDIR ?= /tmp
+TEST_TMPDIR ?= $(TMPDIR)/rabbitmq-test-instances
+endif
+
+# Location of the scripts controlling the broker.
+RABBITMQ_SCRIPTS_DIR ?= $(CURDIR)/sbin
+
+ifeq ($(PLATFORM),msys2)
+RABBITMQ_PLUGINS ?= $(RABBITMQ_SCRIPTS_DIR)/rabbitmq-plugins.bat
+RABBITMQ_SERVER ?= $(RABBITMQ_SCRIPTS_DIR)/rabbitmq-server.bat
+RABBITMQCTL ?= $(RABBITMQ_SCRIPTS_DIR)/rabbitmqctl.bat
+else
+RABBITMQ_PLUGINS ?= $(RABBITMQ_SCRIPTS_DIR)/rabbitmq-plugins
+RABBITMQ_SERVER ?= $(RABBITMQ_SCRIPTS_DIR)/rabbitmq-server
+RABBITMQCTL ?= $(RABBITMQ_SCRIPTS_DIR)/rabbitmqctl
+endif
+
+export RABBITMQ_SCRIPTS_DIR RABBITMQCTL RABBITMQ_PLUGINS RABBITMQ_SERVER
+
+# We export MAKE to be sure scripts and tests use the proper command.
+export MAKE
+
+# We need to pass the location of codegen to the Java client ant
+# process.
+CODEGEN_DIR = $(DEPS_DIR)/rabbitmq_codegen
+PYTHONPATH = $(CODEGEN_DIR)
+export PYTHONPATH
+
+ANT ?= ant
+ANT_FLAGS += -Dmake.bin=$(MAKE) \
+ -DUMBRELLA_AVAILABLE=true \
+ -Drabbitmqctl.bin=$(RABBITMQCTL) \
+ -Dsibling.codegen.dir=$(CODEGEN_DIR)
+ifeq ($(PROJECT),rabbitmq_test)
+ANT_FLAGS += -Dsibling.rabbitmq_test.dir=$(CURDIR)
+else
+ANT_FLAGS += -Dsibling.rabbitmq_test.dir=$(DEPS_DIR)/rabbitmq_test
+endif
+export ANT ANT_FLAGS
+
+node_tmpdir = $(TEST_TMPDIR)/$(1)
+node_pid_file = $(call node_tmpdir,$(1))/$(1).pid
+node_log_base = $(call node_tmpdir,$(1))/log
+node_mnesia_base = $(call node_tmpdir,$(1))/mnesia
+node_mnesia_dir = $(call node_mnesia_base,$(1))/$(1)
+node_quorum_dir = $(call node_mnesia_dir,$(1))/quorum
+node_stream_dir = $(call node_mnesia_dir,$(1))/stream
+node_plugins_expand_dir = $(call node_tmpdir,$(1))/plugins
+node_feature_flags_file = $(call node_tmpdir,$(1))/feature_flags
+node_enabled_plugins_file = $(call node_tmpdir,$(1))/enabled_plugins
+
+# Broker startup variables for the test environment.
+ifeq ($(PLATFORM),msys2)
+HOSTNAME := $(COMPUTERNAME)
+else
+HOSTNAME := $(shell hostname -s)
+endif
+
+RABBITMQ_NODENAME ?= rabbit@$(HOSTNAME)
+RABBITMQ_NODENAME_FOR_PATHS ?= $(RABBITMQ_NODENAME)
+NODE_TMPDIR ?= $(call node_tmpdir,$(RABBITMQ_NODENAME_FOR_PATHS))
+
+RABBITMQ_BASE ?= $(NODE_TMPDIR)
+RABBITMQ_PID_FILE ?= $(call node_pid_file,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_LOG_BASE ?= $(call node_log_base,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_MNESIA_BASE ?= $(call node_mnesia_base,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_MNESIA_DIR ?= $(call node_mnesia_dir,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_QUORUM_DIR ?= $(call node_quorum_dir,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_STREAM_DIR ?= $(call node_stream_dir,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_PLUGINS_EXPAND_DIR ?= $(call node_plugins_expand_dir,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_FEATURE_FLAGS_FILE ?= $(call node_feature_flags_file,$(RABBITMQ_NODENAME_FOR_PATHS))
+RABBITMQ_ENABLED_PLUGINS_FILE ?= $(call node_enabled_plugins_file,$(RABBITMQ_NODENAME_FOR_PATHS))
+
+# Enable colourful debug logging by default
+# To change this, set RABBITMQ_LOG to info, notice, warning etc.
+RABBITMQ_LOG ?= debug,+color
+export RABBITMQ_LOG
+
+# erlang.mk adds dependencies' ebin directory to ERL_LIBS. This is
+# a sane default, but we prefer to rely on the .ez archives in the
+# `plugins` directory so the plugin code is executed. The `plugins`
+# directory is added to ERL_LIBS by rabbitmq-env.
+DIST_ERL_LIBS = $(patsubst :%,%,$(patsubst %:,%,$(subst :$(APPS_DIR):,:,$(subst :$(DEPS_DIR):,:,:$(ERL_LIBS):))))
+
+ifdef PLUGINS_FROM_DEPS_DIR
+RMQ_PLUGINS_DIR=$(DEPS_DIR)
+else
+RMQ_PLUGINS_DIR=$(CURDIR)/$(DIST_DIR)
+endif
+
+define basic_script_env_settings
+MAKE="$(MAKE)" \
+ERL_LIBS="$(DIST_ERL_LIBS)" \
+RABBITMQ_NODENAME="$(1)" \
+RABBITMQ_NODE_IP_ADDRESS="$(RABBITMQ_NODE_IP_ADDRESS)" \
+RABBITMQ_NODE_PORT="$(3)" \
+RABBITMQ_BASE="$(call node_tmpdir,$(2))" \
+RABBITMQ_PID_FILE="$(call node_pid_file,$(2))" \
+RABBITMQ_LOG_BASE="$(call node_log_base,$(2))" \
+RABBITMQ_MNESIA_BASE="$(call node_mnesia_base,$(2))" \
+RABBITMQ_MNESIA_DIR="$(call node_mnesia_dir,$(2))" \
+RABBITMQ_QUORUM_DIR="$(call node_quorum_dir,$(2))" \
+RABBITMQ_STREAM_DIR="$(call node_stream_dir,$(2))" \
+RABBITMQ_FEATURE_FLAGS_FILE="$(call node_feature_flags_file,$(2))" \
+RABBITMQ_PLUGINS_DIR="$(if $(RABBITMQ_PLUGINS_DIR),$(RABBITMQ_PLUGINS_DIR),$(RMQ_PLUGINS_DIR))" \
+RABBITMQ_PLUGINS_EXPAND_DIR="$(call node_plugins_expand_dir,$(2))" \
+RABBITMQ_SERVER_START_ARGS="-ra wal_sync_method sync $(RABBITMQ_SERVER_START_ARGS)" \
+RABBITMQ_ENABLED_PLUGINS="$(RABBITMQ_ENABLED_PLUGINS)"
+endef
+
+BASIC_SCRIPT_ENV_SETTINGS = \
+ $(call basic_script_env_settings,$(RABBITMQ_NODENAME),$(RABBITMQ_NODENAME_FOR_PATHS),$(RABBITMQ_NODE_PORT)) \
+ RABBITMQ_ENABLED_PLUGINS_FILE="$(RABBITMQ_ENABLED_PLUGINS_FILE)"
+
+test-tmpdir:
+ $(verbose) mkdir -p $(TEST_TMPDIR)
+
+virgin-test-tmpdir:
+ $(gen_verbose) rm -rf $(TEST_TMPDIR)
+ $(verbose) mkdir -p $(TEST_TMPDIR)
+
+node-tmpdir:
+ $(verbose) mkdir -p $(RABBITMQ_LOG_BASE) \
+ $(RABBITMQ_MNESIA_BASE) \
+ $(RABBITMQ_PLUGINS_EXPAND_DIR)
+
+virgin-node-tmpdir:
+ $(gen_verbose) rm -rf $(NODE_TMPDIR)
+ $(verbose) mkdir -p $(RABBITMQ_LOG_BASE) \
+ $(RABBITMQ_MNESIA_BASE) \
+ $(RABBITMQ_PLUGINS_EXPAND_DIR)
+
+.PHONY: test-tmpdir virgin-test-tmpdir node-tmpdir virgin-node-tmpdir
+
+ifdef LEAVE_PLUGINS_DISABLED
+RABBITMQ_ENABLED_PLUGINS ?=
+else
+RABBITMQ_ENABLED_PLUGINS ?= ALL
+endif
+
+# --------------------------------------------------------------------
+# Run a full RabbitMQ.
+# --------------------------------------------------------------------
+
+define test_rabbitmq_config
+%% vim:ft=erlang:
+
+[
+ {rabbit, [
+$(if $(RABBITMQ_NODE_PORT), {tcp_listeners$(comma) [$(RABBITMQ_NODE_PORT)]}$(comma),)
+ {loopback_users, []},
+ {log, [{file, [{level, debug}]},
+ {console, [{level, debug}]}]}
+ ]},
+ {rabbitmq_management, [
+$(if $(RABBITMQ_NODE_PORT), {listener$(comma) [{port$(comma) $(shell echo "$$(($(RABBITMQ_NODE_PORT) + 10000))")}]},)
+ ]},
+ {rabbitmq_mqtt, [
+$(if $(RABBITMQ_NODE_PORT), {tcp_listeners$(comma) [$(shell echo "$$((1883 + $(RABBITMQ_NODE_PORT) - 5672))")]},)
+ ]},
+ {rabbitmq_stomp, [
+$(if $(RABBITMQ_NODE_PORT), {tcp_listeners$(comma) [$(shell echo "$$((61613 + $(RABBITMQ_NODE_PORT) - 5672))")]},)
+ ]},
+ {ra, [
+ {data_dir, "$(RABBITMQ_QUORUM_DIR)"},
+ {wal_sync_method, sync}
+ ]},
+ {lager, [
+ {colors, [
+ %% https://misc.flogisoft.com/bash/tip_colors_and_formatting
+ {debug, "\\\e[0;34m" },
+ {info, "\\\e[1;37m" },
+ {notice, "\\\e[1;36m" },
+ {warning, "\\\e[1;33m" },
+ {error, "\\\e[1;31m" },
+ {critical, "\\\e[1;35m" },
+ {alert, "\\\e[1;44m" },
+ {emergency, "\\\e[1;41m" }
+ ]}
+ ]},
+ {osiris, [
+ {data_dir, "$(RABBITMQ_STREAM_DIR)"}
+ ]}
+].
+endef
+
+define test_rabbitmq_config_with_tls
+%% vim:ft=erlang:
+
+[
+ {rabbit, [
+ {loopback_users, []},
+ {log, [{file, [{level, debug}]},
+ {console, [{level, debug}]}]},
+ {ssl_listeners, [5671]},
+ {ssl_options, [
+ {cacertfile, "$(TEST_TLS_CERTS_DIR_in_config)/testca/cacert.pem"},
+ {certfile, "$(TEST_TLS_CERTS_DIR_in_config)/server/cert.pem"},
+ {keyfile, "$(TEST_TLS_CERTS_DIR_in_config)/server/key.pem"},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, false},
+ {honor_cipher_order, true}]}
+ ]},
+ {rabbitmq_management, [
+ {listener, [
+ {port, 15671},
+ {ssl, true},
+ {ssl_opts, [
+ {cacertfile, "$(TEST_TLS_CERTS_DIR_in_config)/testca/cacert.pem"},
+ {certfile, "$(TEST_TLS_CERTS_DIR_in_config)/server/cert.pem"},
+ {keyfile, "$(TEST_TLS_CERTS_DIR_in_config)/server/key.pem"},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, false},
+ {honor_cipher_order, true}]}
+ ]}
+ ]},
+ {ra, [
+ {data_dir, "$(RABBITMQ_QUORUM_DIR)"},
+ {wal_sync_method, sync}
+ ]},
+ {lager, [
+ {colors, [
+ %% https://misc.flogisoft.com/bash/tip_colors_and_formatting
+ {debug, "\\\e[0;34m" },
+ {info, "\\\e[1;37m" },
+ {notice, "\\\e[1;36m" },
+ {warning, "\\\e[1;33m" },
+ {error, "\\\e[1;31m" },
+ {critical, "\\\e[1;35m" },
+ {alert, "\\\e[1;44m" },
+ {emergency, "\\\e[1;41m" }
+ ]}
+ ]},
+ {osiris, [
+ {data_dir, "$(RABBITMQ_STREAM_DIR)"}
+ ]}
+].
+endef
+
+TEST_CONFIG_FILE ?= $(TEST_TMPDIR)/test.config
+TEST_TLS_CERTS_DIR := $(TEST_TMPDIR)/tls-certs
+ifeq ($(origin TEST_TLS_CERTS_DIR_in_config),undefined)
+ifeq ($(PLATFORM),msys2)
+TEST_TLS_CERTS_DIR_in_config := $(shell echo $(TEST_TLS_CERTS_DIR) | sed -E "s,^/([^/]+),\1:,")
+else
+TEST_TLS_CERTS_DIR_in_config := $(TEST_TLS_CERTS_DIR)
+endif
+export TEST_TLS_CERTS_DIR_in_config
+endif
+
+.PHONY: $(TEST_CONFIG_FILE)
+$(TEST_CONFIG_FILE): node-tmpdir
+ $(gen_verbose) printf "$(subst $(newline),\n,$(subst ",\",$(config)))" > $@
+
+$(TEST_TLS_CERTS_DIR): node-tmpdir
+ $(gen_verbose) $(MAKE) -C $(DEPS_DIR)/rabbitmq_ct_helpers/tools/tls-certs \
+ DIR=$(TEST_TLS_CERTS_DIR) all
+
+show-test-tls-certs-dir: $(TEST_TLS_CERTS_DIR)
+ @echo $(TEST_TLS_CERTS_DIR)
+
+ifdef NOBUILD
+DIST_TARGET ?=
+else
+ifeq ($(wildcard ebin/test),)
+DIST_TARGET ?= dist
+else
+DIST_TARGET ?= test-dist
+endif
+endif
+
+run-broker run-tls-broker: RABBITMQ_CONFIG_FILE := $(basename $(TEST_CONFIG_FILE))
+run-broker: config := $(test_rabbitmq_config)
+run-tls-broker: config := $(test_rabbitmq_config_with_tls)
+run-tls-broker: $(TEST_TLS_CERTS_DIR)
+
+run-broker run-tls-broker: node-tmpdir $(DIST_TARGET) $(TEST_CONFIG_FILE)
+ $(BASIC_SCRIPT_ENV_SETTINGS) \
+ RABBITMQ_ALLOW_INPUT=true \
+ RABBITMQ_CONFIG_FILE=$(RABBITMQ_CONFIG_FILE) \
+ $(RABBITMQ_SERVER)
+
+run-background-broker: node-tmpdir $(DIST_TARGET)
+ $(BASIC_SCRIPT_ENV_SETTINGS) \
+ $(RABBITMQ_SERVER) -detached
+
+# --------------------------------------------------------------------
+# Run a bare Erlang node.
+# --------------------------------------------------------------------
+
+run-node: node-tmpdir $(DIST_TARGET)
+ $(BASIC_SCRIPT_ENV_SETTINGS) \
+ RABBITMQ_NODE_ONLY=true \
+ RABBITMQ_ALLOW_INPUT=true \
+ $(RABBITMQ_SERVER)
+
+run-background-node: virgin-node-tmpdir $(DIST_TARGET)
+ $(BASIC_SCRIPT_ENV_SETTINGS) \
+ RABBITMQ_NODE_ONLY=true \
+ $(RABBITMQ_SERVER) -detached
+
+# --------------------------------------------------------------------
+# Start RabbitMQ in the background.
+# --------------------------------------------------------------------
+
+ifneq ($(LOG_TO_STDIO),yes)
+REDIRECT_STDIO = > $(RABBITMQ_LOG_BASE)/startup_log \
+ 2> $(RABBITMQ_LOG_BASE)/startup_err
+endif
+
+RMQCTL_WAIT_TIMEOUT ?= 60
+
+define rmq_started
+true = rpc:call('$(1)', rabbit, is_running, []),
+halt().
+endef
+
+start-background-node: node-tmpdir $(DIST_TARGET)
+ $(BASIC_SCRIPT_ENV_SETTINGS) \
+ RABBITMQ_NODE_ONLY=true \
+ $(RABBITMQ_SERVER) \
+ $(REDIRECT_STDIO) &
+ ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n $(RABBITMQ_NODENAME) wait --timeout $(RMQCTL_WAIT_TIMEOUT) $(RABBITMQ_PID_FILE) kernel
+
+start-background-broker: node-tmpdir $(DIST_TARGET)
+ $(BASIC_SCRIPT_ENV_SETTINGS) \
+ $(RABBITMQ_SERVER) \
+ $(REDIRECT_STDIO) &
+ ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n $(RABBITMQ_NODENAME) wait --timeout $(RMQCTL_WAIT_TIMEOUT) $(RABBITMQ_PID_FILE) && \
+ ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(call erlang,$(call rmq_started,$(RABBITMQ_NODENAME)),-sname sbb-$$$$ -hidden)
+
+start-rabbit-on-node:
+ $(exec_verbose) ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n $(RABBITMQ_NODENAME) \
+ eval 'rabbit:start().' | \
+ sed -E -e '/^ completed with .* plugins\.$$/d' -e '/^ok$$/d'
+ $(verbose) ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n $(RABBITMQ_NODENAME) wait --timeout $(RMQCTL_WAIT_TIMEOUT) $(RABBITMQ_PID_FILE)
+
+stop-rabbit-on-node:
+ $(exec_verbose) ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n $(RABBITMQ_NODENAME) \
+ eval 'rabbit:stop().' | \
+ sed -E -e '/^ok$$/d'
+
+stop-node:
+ $(exec_verbose) ( \
+ pid=$$(test -f $(RABBITMQ_PID_FILE) && cat $(RABBITMQ_PID_FILE)); \
+ test "$$pid" && \
+ kill -TERM "$$pid" && \
+ echo waiting for process to exit && \
+ while ps -p "$$pid" >/dev/null 2>&1; do sleep 1; done \
+ ) || :
+
+# " <-- To please Vim syntax hilighting.
+
+# --------------------------------------------------------------------
+# Start a RabbitMQ cluster in the background.
+# --------------------------------------------------------------------
+
+NODES ?= 2
+
+start-brokers start-cluster: $(DIST_TARGET)
+ @for n in $$(seq $(NODES)); do \
+ nodename="rabbit-$$n@$(HOSTNAME)"; \
+ $(MAKE) start-background-broker \
+ NOBUILD=1 \
+ RABBITMQ_NODENAME="$$nodename" \
+ RABBITMQ_NODE_PORT="$$((5672 + $$n - 1))" \
+ RABBITMQ_SERVER_START_ARGS=" \
+ -rabbit loopback_users [] \
+ -rabbitmq_management listener [{port,$$((15672 + $$n - 1))}] \
+ -rabbitmq_mqtt tcp_listeners [$$((1883 + $$n - 1))] \
+ -rabbitmq_stomp tcp_listeners [$$((61613 + $$n - 1))] \
+ -rabbitmq_prometheus tcp_config [{port,$$((15692 + $$n - 1))}] \
+ -rabbitmq_stream tcp_listeners [$$((5555 + $$n - 1))] \
+ "; \
+ if test '$@' = 'start-cluster' && test "$$nodename1"; then \
+ ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n "$$nodename" stop_app; \
+ ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n "$$nodename" join_cluster "$$nodename1"; \
+ ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n "$$nodename" start_app; \
+ else \
+ nodename1=$$nodename; \
+ fi; \
+ done
+
+stop-brokers stop-cluster:
+ @for n in $$(seq $(NODES) -1 1); do \
+ nodename="rabbit-$$n@$(HOSTNAME)"; \
+ $(MAKE) stop-node \
+ RABBITMQ_NODENAME="$$nodename"; \
+ done
+
+# --------------------------------------------------------------------
+# Used by testsuites.
+# --------------------------------------------------------------------
+
+set-resource-alarm:
+ $(exec_verbose) ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n $(RABBITMQ_NODENAME) \
+ eval 'rabbit_alarm:set_alarm({{resource_limit, $(SOURCE), node()}, []}).'
+
+clear-resource-alarm:
+ $(exec_verbose) ERL_LIBS="$(DIST_ERL_LIBS)" \
+ $(RABBITMQCTL) -n $(RABBITMQ_NODENAME) \
+ eval 'rabbit_alarm:clear_alarm({resource_limit, $(SOURCE), node()}).'
diff --git a/deps/rabbit_common/mk/rabbitmq-test.mk b/deps/rabbit_common/mk/rabbitmq-test.mk
new file mode 100644
index 0000000000..931f072125
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-test.mk
@@ -0,0 +1,80 @@
+.PHONY: ct-slow ct-fast
+
+ct-slow ct-fast:
+ $(MAKE) ct CT_SUITES='$(CT_SUITES)'
+
+# --------------------------------------------------------------------
+# xref
+# --------------------------------------------------------------------
+
+# We need the list of dependencies of the current project. We use it in
+# xrefr(1) to scan for Elixir-based projects. For those, we need to add
+# the path inside `_build` to the xref code path.
+
+ifneq ($(filter xref,$(MAKECMDGOALS)),)
+export ERLANG_MK_RECURSIVE_DEPS_LIST
+endif
+
+xref: $(ERLANG_MK_RECURSIVE_DEPS_LIST)
+
+# --------------------------------------------------------------------
+# Helpers to run Make targets on Concourse.
+# --------------------------------------------------------------------
+
+FLY ?= fly
+FLY_TARGET ?= $(shell $(FLY) targets | awk '/ci\.rabbitmq\.com/ { print $$1; }')
+
+CONCOURSE_TASK = $(ERLANG_MK_TMP)/concourse-task.yaml
+
+CI_DIR ?= $(DEPS_DIR)/ci
+PIPELINE_DIR = $(CI_DIR)/server-release
+BRANCH_RELEASE = $(shell "$(PIPELINE_DIR)/scripts/map-branch-to-release.sh" "$(base_rmq_ref)")
+PIPELINE_DATA = $(PIPELINE_DIR)/release-data-$(BRANCH_RELEASE).yaml
+REPOSITORY_NAME = $(shell "$(PIPELINE_DIR)/scripts/map-erlang-app-and-repository-name.sh" "$(PIPELINE_DATA)" "$(PROJECT)")
+
+CONCOURSE_PLATFORM ?= linux
+ERLANG_VERSION ?= $(shell "$(PIPELINE_DIR)/scripts/list-erlang-versions.sh" "$(PIPELINE_DATA)" | head -n 1)
+TASK_INPUTS = $(shell "$(PIPELINE_DIR)/scripts/list-task-inputs.sh" "$(CONCOURSE_TASK)")
+
+.PHONY: $(CONCOURSE_TASK)
+$(CONCOURSE_TASK): $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST)
+ $(gen_verbose) echo 'platform: $(CONCOURSE_PLATFORM)' > "$@"
+ $(verbose) echo 'inputs:' >> "$@"
+ $(verbose) echo ' - name: $(PROJECT)' >> "$@"
+ $(verbose) cat $(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) | while read -r file; do \
+ echo " - name: $$(basename "$$file")" >> "$@"; \
+ done
+ $(verbose) echo 'outputs:' >> "$@"
+ $(verbose) echo ' - name: test-output' >> "$@"
+ifeq ($(CONCOURSE_PLATFORM),linux)
+ $(verbose) echo 'image_resource:' >> "$@"
+ $(verbose) echo ' type: docker-image' >> "$@"
+ $(verbose) echo ' source:' >> "$@"
+ $(verbose) echo ' repository: pivotalrabbitmq/rabbitmq-server-buildenv' >> "$@"
+ $(verbose) echo ' tag: linux-erlang-$(ERLANG_VERSION)' >> "$@"
+endif
+ $(verbose) echo 'run:' >> "$@"
+ $(verbose) echo ' path: ci/server-release/scripts/test-erlang-app.sh' >> "$@"
+ $(verbose) echo ' args:' >> "$@"
+ $(verbose) echo " - $(PROJECT)" >> "$@"
+# This section must be the last because the `%-on-concourse` target
+# appends other variables.
+ $(verbose) echo 'params:' >> "$@"
+ifdef V
+ $(verbose) echo ' V: "$(V)"' >> "$@"
+endif
+ifdef t
+ $(verbose) echo ' t: "$(t)"' >> "$@"
+endif
+
+%-on-concourse: $(CONCOURSE_TASK)
+ $(verbose) test -d "$(PIPELINE_DIR)"
+ $(verbose) echo ' MAKE_TARGET: "$*"' >> "$(CONCOURSE_TASK)"
+ $(FLY) -t $(FLY_TARGET) execute \
+ --config="$(CONCOURSE_TASK)" \
+ $(foreach input,$(TASK_INPUTS), \
+ $(if $(filter $(PROJECT),$(input)), \
+ --input="$(input)=.", \
+ --input="$(input)=$(DEPS_DIR)/$(input)")) \
+ --output="test-output=$(CT_LOGS_DIR)/on-concourse"
+ $(verbose) rm -f "$(CT_LOGS_DIR)/on-concourse/filename"
diff --git a/deps/rabbit_common/mk/rabbitmq-tools.mk b/deps/rabbit_common/mk/rabbitmq-tools.mk
new file mode 100644
index 0000000000..6672153cb0
--- /dev/null
+++ b/deps/rabbit_common/mk/rabbitmq-tools.mk
@@ -0,0 +1,429 @@
+ifeq ($(PLATFORM),msys2)
+HOSTNAME := $(COMPUTERNAME)
+else
+HOSTNAME := $(shell hostname -s)
+endif
+
+READY_DEPS = $(foreach DEP,\
+ $(filter $(RABBITMQ_COMPONENTS),$(DEPS) $(BUILD_DEPS) $(TEST_DEPS)), \
+ $(if $(wildcard $(DEPS_DIR)/$(DEP)),$(DEP),))
+
+RELEASED_RMQ_DEPS = $(filter $(RABBITMQ_COMPONENTS),$(DEPS) $(BUILD_DEPS))
+
+.PHONY: show-upstream-git-fetch-url show-upstream-git-push-url \
+ show-current-git-fetch-url show-current-git-push-url
+
+show-upstream-git-fetch-url:
+ @echo $(RABBITMQ_UPSTREAM_FETCH_URL)
+
+show-upstream-git-push-url:
+ @echo $(RABBITMQ_UPSTREAM_PUSH_URL)
+
+show-current-git-fetch-url:
+ @echo $(RABBITMQ_CURRENT_FETCH_URL)
+
+show-current-git-push-url:
+ @echo $(RABBITMQ_CURRENT_PUSH_URL)
+
+.PHONY: update-erlang-mk update-rabbitmq-components.mk
+
+update-erlang-mk: erlang-mk
+ $(verbose) if test "$(DO_COMMIT)" = 'yes'; then \
+ git diff --quiet -- erlang.mk \
+ || git commit -m 'Update erlang.mk' -- erlang.mk; \
+ fi
+ $(verbose) for repo in $(READY_DEPS:%=$(DEPS_DIR)/%); do \
+ ! test -f $$repo/erlang.mk \
+ || $(MAKE) -C $$repo erlang-mk; \
+ if test "$(DO_COMMIT)" = 'yes'; then \
+ (cd $$repo; \
+ git diff --quiet -- erlang.mk \
+ || git commit -m 'Update erlang.mk' -- erlang.mk); \
+ fi; \
+ done
+
+# --------------------------------------------------------------------
+# rabbitmq-components.mk checks.
+# --------------------------------------------------------------------
+
+UPSTREAM_RMQ_COMPONENTS_MK = $(DEPS_DIR)/rabbit_common/mk/rabbitmq-components.mk
+
+ifeq ($(PROJECT),rabbit_common)
+check-rabbitmq-components.mk:
+ @:
+else
+check-rabbitmq-components.mk:
+ $(verbose) cmp -s rabbitmq-components.mk \
+ $(UPSTREAM_RMQ_COMPONENTS_MK) || \
+ (echo "error: rabbitmq-components.mk must be updated!" 1>&2; \
+ false)
+endif
+
+ifeq ($(PROJECT),rabbit_common)
+rabbitmq-components-mk:
+ @:
+else
+rabbitmq-components-mk:
+ifeq ($(FORCE),yes)
+ $(gen_verbose) cp -a $(UPSTREAM_RMQ_COMPONENTS_MK) .
+else
+ $(gen_verbose) if test -d .git && test -d $(DEPS_DIR)/rabbit_common/.git; then \
+ upstream_branch=$$(LANG=C git -C $(DEPS_DIR)/rabbit_common branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}'); \
+ local_branch=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}'); \
+ test "$$local_branch" = "$$upstream_branch" || exit 0; \
+ fi; \
+ cp -a $(UPSTREAM_RMQ_COMPONENTS_MK) .
+endif
+ifeq ($(DO_COMMIT),yes)
+ $(verbose) git diff --quiet rabbitmq-components.mk \
+ || git commit -m 'Update rabbitmq-components.mk' rabbitmq-components.mk
+endif
+endif
+
+update-rabbitmq-components-mk: rabbitmq-components-mk
+ $(verbose) for repo in $(READY_DEPS:%=$(DEPS_DIR)/%); do \
+ ! test -f $$repo/rabbitmq-components.mk \
+ || $(MAKE) -C $$repo rabbitmq-components-mk; \
+ done
+
+update-contributor-code-of-conduct:
+ $(verbose) for repo in $(READY_DEPS:%=$(DEPS_DIR)/%); do \
+ cp $(DEPS_DIR)/rabbit_common/CODE_OF_CONDUCT.md $$repo/CODE_OF_CONDUCT.md; \
+ cp $(DEPS_DIR)/rabbit_common/CONTRIBUTING.md $$repo/CONTRIBUTING.md; \
+ done
+
+ifdef CREDS
+define replace_aws_creds
+ set -e; \
+ if test -f "$(CREDS)"; then \
+ key_id=$(shell travis encrypt --no-interactive \
+ "AWS_ACCESS_KEY_ID=$$(awk '/^rabbitmq-s3-access-key-id/ { print $$2; }' < "$(CREDS)")"); \
+ access_key=$(shell travis encrypt --no-interactive \
+ "AWS_SECRET_ACCESS_KEY=$$(awk '/^rabbitmq-s3-secret-access-key/ { print $$2; }' < "$(CREDS)")"); \
+ mv .travis.yml .travis.yml.orig; \
+ awk "\
+ /^ global:/ { \
+ print; \
+ print \" - secure: $$key_id\"; \
+ print \" - secure: $$access_key\"; \
+ next; \
+ } \
+ /- secure:/ { next; } \
+ { print; }" < .travis.yml.orig > .travis.yml; \
+ rm -f .travis.yml.orig; \
+ else \
+ echo " INFO: CREDS file missing; not setting/updating AWS credentials"; \
+ fi
+endef
+else
+define replace_aws_creds
+ echo " INFO: CREDS not set; not setting/updating AWS credentials"
+endef
+endif
+
+ifeq ($(PROJECT),rabbit_common)
+travis-yml:
+ $(gen_verbose) $(replace_aws_creds)
+else
+travis-yml:
+ $(gen_verbose) \
+ set -e; \
+ if test -d .git && test -d $(DEPS_DIR)/rabbit_common/.git; then \
+ upstream_branch=$$(LANG=C git -C $(DEPS_DIR)/rabbit_common branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}'); \
+ local_branch=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}'); \
+ test "$$local_branch" = "$$upstream_branch" || exit 0; \
+ fi; \
+ test -f .travis.yml || exit 0; \
+ (grep -E -- '- secure:' .travis.yml || :) > .travis.yml.creds; \
+ cp -a $(DEPS_DIR)/rabbit_common/.travis.yml .travis.yml.orig; \
+ awk ' \
+ /^ global:/ { \
+ print; \
+ system("test -f .travis.yml.creds && cat .travis.yml.creds"); \
+ next; \
+ } \
+ /- secure:/ { next; } \
+ { print; } \
+ ' < .travis.yml.orig > .travis.yml; \
+ rm -f .travis.yml.orig .travis.yml.creds; \
+ if test -f .travis.yml.patch; then \
+ patch -p0 < .travis.yml.patch; \
+ rm -f .travis.yml.orig; \
+ fi; \
+ $(replace_aws_creds)
+ifeq ($(DO_COMMIT),yes)
+ $(verbose) ! test -f .travis.yml || \
+ git diff --quiet .travis.yml \
+ || git commit -m 'Travis CI: Update config from rabbitmq-common' .travis.yml
+endif
+endif
+
+update-travis-yml: travis-yml
+ $(verbose) for repo in $(READY_DEPS:%=$(DEPS_DIR)/%); do \
+ ! test -f $$repo/rabbitmq-components.mk \
+ || $(MAKE) -C $$repo travis-yml; \
+ done
+
+ifneq ($(wildcard .git),)
+
+.PHONY: sync-gitremote sync-gituser
+
+sync-gitremote: $(READY_DEPS:%=$(DEPS_DIR)/%+sync-gitremote)
+ @:
+
+%+sync-gitremote:
+ $(exec_verbose) cd $* && \
+ git remote set-url origin \
+ '$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(notdir $*))'
+ $(verbose) cd $* && \
+ git remote set-url --push origin \
+ '$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(notdir $*))'
+
+ifeq ($(origin, RMQ_GIT_GLOBAL_USER_NAME),undefined)
+RMQ_GIT_GLOBAL_USER_NAME := $(shell git config --global user.name)
+export RMQ_GIT_GLOBAL_USER_NAME
+endif
+ifeq ($(origin RMQ_GIT_GLOBAL_USER_EMAIL),undefined)
+RMQ_GIT_GLOBAL_USER_EMAIL := $(shell git config --global user.email)
+export RMQ_GIT_GLOBAL_USER_EMAIL
+endif
+ifeq ($(origin RMQ_GIT_USER_NAME),undefined)
+RMQ_GIT_USER_NAME := $(shell git config user.name)
+export RMQ_GIT_USER_NAME
+endif
+ifeq ($(origin RMQ_GIT_USER_EMAIL),undefined)
+RMQ_GIT_USER_EMAIL := $(shell git config user.email)
+export RMQ_GIT_USER_EMAIL
+endif
+
+sync-gituser: $(READY_DEPS:%=$(DEPS_DIR)/%+sync-gituser)
+ @:
+
+%+sync-gituser:
+ifeq ($(RMQ_GIT_USER_NAME),$(RMQ_GIT_GLOBAL_USER_NAME))
+ $(exec_verbose) cd $* && git config --unset user.name || :
+else
+ $(exec_verbose) cd $* && git config user.name "$(RMQ_GIT_USER_NAME)"
+endif
+ifeq ($(RMQ_GIT_USER_EMAIL),$(RMQ_GIT_GLOBAL_USER_EMAIL))
+ $(verbose) cd $* && git config --unset user.email || :
+else
+ $(verbose) cd $* && git config user.email "$(RMQ_GIT_USER_EMAIL)"
+endif
+
+.PHONY: sync-gitignore-from-master
+sync-gitignore-from-master: $(READY_DEPS:%=$(DEPS_DIR)/%+sync-gitignore-from-master)
+
+%+sync-gitignore-from-master:
+ $(gen_verbose) cd $* && \
+ if test -d .git; then \
+ branch=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}'); \
+ ! test "$$branch" = 'master' || exit 0; \
+ git show origin/master:.gitignore > .gitignore; \
+ fi
+ifeq ($(DO_COMMIT),yes)
+ $(verbose) cd $* && \
+ if test -d .git; then \
+ git diff --quiet .gitignore \
+ || git commit -m 'Git: Sync .gitignore from master' .gitignore; \
+ fi
+endif
+
+.PHONY: show-branch
+
+show-branch: $(READY_DEPS:%=$(DEPS_DIR)/%+show-branch)
+ $(verbose) printf '%-34s %s\n' $(PROJECT): "$$(git symbolic-ref -q --short HEAD || git describe --tags --exact-match)"
+
+%+show-branch:
+ $(verbose) printf '%-34s %s\n' $(notdir $*): "$$(cd $* && (git symbolic-ref -q --short HEAD || git describe --tags --exact-match))"
+
+SINCE_TAG ?= last-release
+COMMITS_LOG_OPTS ?= --oneline --decorate --no-merges
+MARKDOWN ?= no
+
+define show_commits_since_tag
+set -e; \
+if test "$1"; then \
+ erlang_app=$(notdir $1); \
+ repository=$(call rmq_cmp_repo_name,$(notdir $1)); \
+ git_dir=-C\ "$1"; \
+else \
+ erlang_app=$(PROJECT); \
+ repository=$(call rmq_cmp_repo_name,$(PROJECT)); \
+fi; \
+case "$(SINCE_TAG)" in \
+last-release) \
+ tags_count=$$(git $$git_dir tag -l 2>/dev/null | grep -E -v '(-beta|_milestone|[-_]rc)' | wc -l); \
+ ;; \
+*) \
+ tags_count=$$(git $$git_dir tag -l 2>/dev/null | wc -l); \
+ ;; \
+esac; \
+if test "$$tags_count" -gt 0; then \
+ case "$(SINCE_TAG)" in \
+ last-release) \
+ ref=$$(git $$git_dir describe --abbrev=0 --tags \
+ --exclude "*-beta*" \
+ --exclude "*_milestone*" \
+ --exclude "*[-_]rc*"); \
+ ;; \
+ last-prerelease) \
+ ref=$$(git $$git_dir describe --abbrev=0 --tags); \
+ ;; \
+ *) \
+ git $$git_dir rev-parse "$(SINCE_TAG)" -- >/dev/null; \
+ ref=$(SINCE_TAG); \
+ ;; \
+ esac; \
+ commits_count=$$(git $$git_dir log --oneline "$$ref.." | wc -l); \
+ if test "$$commits_count" -gt 0; then \
+ if test "$(MARKDOWN)" = yes; then \
+ printf "\n## [\`$$repository\`](https://github.com/rabbitmq/$$repository)\n\nCommits since \`$$ref\`:\n\n"; \
+ git $$git_dir --no-pager log $(COMMITS_LOG_OPTS) \
+ --format="format:* %s ([\`%h\`](https://github.com/rabbitmq/$$repository/commit/%H))" \
+ "$$ref.."; \
+ echo; \
+ else \
+ echo; \
+ echo "# $$repository - Commits since $$ref"; \
+ git $$git_dir log $(COMMITS_LOG_OPTS) "$$ref.."; \
+ fi; \
+ fi; \
+else \
+ if test "$(MARKDOWN)" = yes; then \
+ printf "\n## [\`$$repository\`](https://github.com/rabbitmq/$$repository)\n\n**New** since the last release!\n"; \
+ else \
+ echo; \
+ echo "# $$repository - New since the last release!"; \
+ fi; \
+fi
+endef
+
+.PHONY: commits-since-release
+
+commits-since-release: commits-since-release-title \
+ $(RELEASED_RMQ_DEPS:%=$(DEPS_DIR)/%+commits-since-release)
+ $(verbose) $(call show_commits_since_tag)
+
+commits-since-release-title:
+ $(verbose) set -e; \
+ case "$(SINCE_TAG)" in \
+ last-release) \
+ tags_count=$$(git $$git_dir tag -l 2>/dev/null | grep -E -v '(-beta|_milestone|[-_]rc)' | wc -l); \
+ ;; \
+ *) \
+ tags_count=$$(git $$git_dir tag -l 2>/dev/null | wc -l); \
+ ;; \
+ esac; \
+ if test "$$tags_count" -gt 0; then \
+ case "$(SINCE_TAG)" in \
+ last-release) \
+ ref=$$(git $$git_dir describe --abbrev=0 --tags \
+ --exclude "*-beta*" \
+ --exclude "*_milestone*" \
+ --exclude "*[-_]rc*"); \
+ ;; \
+ last-prerelease) \
+ ref=$$(git $$git_dir describe --abbrev=0 --tags); \
+ ;; \
+ *) \
+ ref=$(SINCE_TAG); \
+ ;; \
+ esac; \
+ version=$$(echo "$$ref" | sed -E \
+ -e 's/rabbitmq_v([0-9]+)_([0-9]+)_([0-9]+)/v\1.\2.\3/' \
+ -e 's/_milestone/-beta./' \
+ -e 's/_rc/-rc./' \
+ -e 's/^v//'); \
+ echo "# Changes since RabbitMQ $$version"; \
+ else \
+ echo "# Changes since the beginning of time"; \
+ fi
+
+%+commits-since-release:
+ $(verbose) $(call show_commits_since_tag,$*)
+
+endif # ($(wildcard .git),)
+
+# --------------------------------------------------------------------
+# erlang.mk query-deps* formatting.
+# --------------------------------------------------------------------
+
+# We need to provide a repo mapping for deps resolved via git_rmq fetch method
+query_repo_git_rmq = https://github.com/rabbitmq/$(call rmq_cmp_repo_name,$(1))
+
+# --------------------------------------------------------------------
+# Common test logs compression.
+# --------------------------------------------------------------------
+
+.PHONY: ct-logs-archive clean-ct-logs-archive
+
+ifneq ($(wildcard logs/*),)
+TAR := tar
+ifeq ($(PLATFORM),freebsd)
+TAR := gtar
+endif
+ifeq ($(PLATFORM),darwin)
+TAR := gtar
+endif
+
+CT_LOGS_ARCHIVE ?= $(PROJECT)-ct-logs-$(subst _,-,$(subst -,,$(subst .,,$(patsubst ct_run.ct_$(PROJECT)@$(HOSTNAME).%,%,$(notdir $(lastword $(wildcard logs/ct_run.*))))))).tar.xz
+
+ifeq ($(patsubst %.tar.xz,%,$(CT_LOGS_ARCHIVE)),$(CT_LOGS_ARCHIVE))
+$(error CT_LOGS_ARCHIVE file must use '.tar.xz' as its filename extension)
+endif
+
+ct-logs-archive: $(CT_LOGS_ARCHIVE)
+ @:
+
+$(CT_LOGS_ARCHIVE):
+ $(gen_verbose) \
+ for file in logs/*; do \
+ ! test -L "$$file" || rm "$$file"; \
+ done
+ $(verbose) \
+ $(TAR) -c \
+ --exclude "*/mnesia" \
+ --transform "s/^logs/$(patsubst %.tar.xz,%,$(notdir $(CT_LOGS_ARCHIVE)))/" \
+ -f - logs | \
+ xz > "$@"
+else
+ct-logs-archive:
+ @:
+endif
+
+clean-ct-logs-archive::
+ $(gen_verbose) rm -f $(PROJECT)-ct-logs-*.tar.xz
+
+clean:: clean-ct-logs-archive
+
+# --------------------------------------------------------------------
+# Generate a file listing RabbitMQ component dependencies and their
+# Git commit hash.
+# --------------------------------------------------------------------
+
+.PHONY: rabbitmq-deps.mk clean-rabbitmq-deps.mk
+
+rabbitmq-deps.mk: $(PROJECT)-rabbitmq-deps.mk
+ @:
+
+closing_paren := )
+
+define rmq_deps_mk_line
+dep_$(1) := git $(dir $(RABBITMQ_UPSTREAM_FETCH_URL))$(call rmq_cmp_repo_name,$(1)).git $$(git -C "$(2)" rev-parse HEAD)
+endef
+
+$(PROJECT)-rabbitmq-deps.mk: $(ERLANG_MK_RECURSIVE_DEPS_LIST)
+ $(gen_verbose) echo "# In $(PROJECT) - commit $$(git rev-parse HEAD)" > $@
+ $(verbose) cat $(ERLANG_MK_RECURSIVE_DEPS_LIST) | \
+ while read -r dir; do \
+ component=$$(basename "$$dir"); \
+ case "$$component" in \
+ $(foreach component,$(RABBITMQ_COMPONENTS),$(component)$(closing_paren) echo "$(call rmq_deps_mk_line,$(component),$$dir)" ;;) \
+ esac; \
+ done >> $@
+
+clean:: clean-rabbitmq-deps.mk
+
+clean-rabbitmq-deps.mk:
+ $(gen_verbose) rm -f $(PROJECT)-rabbitmq-deps.mk
diff --git a/deps/rabbit_common/mk/xrefr b/deps/rabbit_common/mk/xrefr
new file mode 100755
index 0000000000..03c408fcb4
--- /dev/null
+++ b/deps/rabbit_common/mk/xrefr
@@ -0,0 +1,338 @@
+#!/usr/bin/env escript
+%% vim:ft=erlang:
+
+%% The code is copied from xref_runner.
+%% https://github.com/inaka/xref_runner
+%%
+%% The only change is the support of our erlang_version_support
+%% attribute: we don't want any warnings about functions which will be
+%% dropped at load time.
+%%
+%% It's also a plain text escript instead of a compiled one because we
+%% want to support Erlang R16B03 and the version of xref_runner uses
+%% maps and is built with something like Erlang 18.
+
+%% This mode allows us to reference local function. For instance:
+%% lists:map(fun generate_comment/1, Comments)
+-mode(compile).
+
+-define(DIRS, ["ebin", "test"]).
+
+-define(CHECKS, [undefined_function_calls,
+ undefined_functions,
+ locals_not_used]).
+
+main(_) ->
+ Checks = ?CHECKS,
+ ElixirDeps = get_elixir_deps_paths(),
+ [true = code:add_path(P) || P <- ElixirDeps],
+ XrefWarnings = lists:append([check(Check) || Check <- Checks]),
+ warnings_prn(XrefWarnings),
+ case XrefWarnings of
+ [] -> ok;
+ _ -> halt(1)
+ end.
+
+get_elixir_deps_paths() ->
+ case os:getenv("ERLANG_MK_RECURSIVE_DEPS_LIST") of
+ false ->
+ [];
+ Filename ->
+ {ok, Fd} = file:open(Filename, [read]),
+ get_elixir_deps_paths1(Fd, [])
+ end.
+
+get_elixir_deps_paths1(Fd, Paths) ->
+ case file:read_line(Fd) of
+ {ok, Line0} ->
+ Line = Line0 -- [$\r, $\n],
+ RootPath = case os:type() of
+ {unix, _} ->
+ Line;
+ {win32, _} ->
+ case os:find_executable("cygpath.exe") of
+ false ->
+ Line;
+ Cygpath ->
+ os:cmd(
+ io_lib:format("~s --windows \"~s\"",
+ [Cygpath, Line]))
+ -- [$\r, $\n]
+ end
+ end,
+ Glob = filename:join([RootPath, "_build", "dev", "lib", "*", "ebin"]),
+ NewPaths = filelib:wildcard(Glob),
+ get_elixir_deps_paths1(Fd, Paths ++ NewPaths);
+ eof ->
+ add_elixir_stdlib_path(Paths)
+ end.
+
+add_elixir_stdlib_path(Paths) ->
+ case find_elixir_home() of
+ false -> Paths;
+ ElixirLibDir -> [ElixirLibDir | Paths]
+ end.
+
+find_elixir_home() ->
+ ElixirExe = case os:type() of
+ {unix, _} -> "elixir";
+ {win32, _} -> "elixir.bat"
+ end,
+ case os:find_executable(ElixirExe) of
+ false -> false;
+ ExePath -> resolve_symlink(ExePath)
+ end.
+
+resolve_symlink(ExePath) ->
+ case file:read_link_all(ExePath) of
+ {error, einval} ->
+ determine_elixir_home(ExePath);
+ {ok, ResolvedLink} ->
+ ExePath1 = filename:absname(ResolvedLink,
+ filename:dirname(ExePath)),
+ resolve_symlink(ExePath1);
+ {error, _} ->
+ false
+ end.
+
+determine_elixir_home(ExePath) ->
+ LibPath = filename:join([filename:dirname(filename:dirname(ExePath)),
+ "lib",
+ "elixir",
+ "ebin"]),
+ case filelib:is_dir(LibPath) of
+ true -> LibPath;
+ false -> {skip, "Failed to locate Elixir lib dir"}
+ end.
+check(Check) ->
+ Dirs = ?DIRS,
+ lists:foreach(fun code:add_path/1, Dirs),
+
+ {ok, Xref} = xref:start([]),
+ try
+ ok = xref:set_library_path(Xref, code:get_path()),
+
+ lists:foreach(
+ fun(Dir) ->
+ case filelib:is_dir(Dir) of
+ true -> {ok, _} = xref:add_directory(Xref, Dir);
+ false -> ok
+ end
+ end, Dirs),
+
+ {ok, Results} = xref:analyze(Xref, Check),
+
+ FilteredResults = filter_xref_results(Check, Results),
+
+ [result_to_warning(Check, Result) || Result <- FilteredResults]
+ after
+ stopped = xref:stop(Xref)
+ end.
+
+%% -------------------------------------------------------------------
+%% Filtering results.
+%% -------------------------------------------------------------------
+
+filter_xref_results(Check, Results) ->
+ SourceModules =
+ lists:usort([source_module(Result) || Result <- Results]),
+
+ Ignores = lists:flatmap(
+ fun(Module) -> get_ignorelist(Module, Check) end, SourceModules),
+
+ UnusedFunctions = lists:flatmap(
+ fun(Mod) -> get_unused_compat_functions(Mod) end,
+ SourceModules),
+
+ ToIgnore = case get(results_to_ignore) of
+ undefined -> [];
+ RTI -> RTI
+ end,
+ NewToIgnore = [parse_xref_target(Result)
+ || Result <- Results,
+ lists:member(parse_xref_source(Result), UnusedFunctions)],
+ AllToIgnore = ToIgnore ++ NewToIgnore ++ [mfa(M, {F, A})
+ || {_, {M, F, A}} <- Ignores],
+ put(results_to_ignore, AllToIgnore),
+
+ [Result || Result <- Results,
+ not lists:member(parse_xref_result(Result), Ignores) andalso
+ not lists:member(parse_xref_result(Result), AllToIgnore) andalso
+ not lists:member(parse_xref_source(Result), UnusedFunctions)].
+
+source_module({Mt, _Ft, _At}) -> Mt;
+source_module({{Ms, _Fs, _As}, _Target}) -> Ms.
+
+%%
+%% Ignore behaviour functions, and explicitly marked functions
+%%
+%% Functions can be ignored by using
+%% -ignore_xref([{F, A}, {M, F, A}...]).
+get_ignorelist(Mod, Check) ->
+ %% Get ignore_xref attribute and combine them in one list
+ Attributes =
+ try
+ Mod:module_info(attributes)
+ catch
+ _Class:_Error -> []
+ end,
+
+ IgnoreXref =
+ [mfa(Mod, Value) || {ignore_xref, Values} <- Attributes, Value <- Values],
+
+ BehaviourCallbacks = get_behaviour_callbacks(Check, Mod, Attributes),
+
+ %% And create a flat {M, F, A} list
+ IgnoreXref ++ BehaviourCallbacks.
+
+get_behaviour_callbacks(exports_not_used, Mod, Attributes) ->
+ Behaviours = [Value || {behaviour, Values} <- Attributes, Value <- Values],
+ [{Mod, {Mod, F, A}}
+ || B <- Behaviours, {F, A} <- B:behaviour_info(callbacks)];
+get_behaviour_callbacks(_Check, _Mod, _Attributes) ->
+ [].
+
+get_unused_compat_functions(Module) ->
+ OTPVersion = code_version:get_otp_version(),
+ Attributes = try
+ Module:module_info(attributes)
+ catch
+ _Class:_Error -> []
+ end,
+ CompatTuples = [Tuple
+ || {erlang_version_support, Tuples} <- Attributes,
+ Tuple <- Tuples],
+ get_unused_compat_functions(Module, OTPVersion, CompatTuples, []).
+
+get_unused_compat_functions(_, _, [], Result) ->
+ Result;
+get_unused_compat_functions(Module,
+ OTPVersion,
+ [{MinOTPVersion, Choices} | Rest],
+ Result) ->
+ Functions = lists:map(
+ fun({_, Arity, Pre, Post}) ->
+ if
+ OTPVersion >= MinOTPVersion ->
+ %% We ignore the "pre" function.
+ mfa(Module, {Pre, Arity});
+ true ->
+ %% We ignore the "post" function.
+ mfa(Module, {Post, Arity})
+ end
+ end, Choices),
+ get_unused_compat_functions(Module, OTPVersion, Rest,
+ Result ++ Functions).
+
+mfa(M, {F, A}) -> {M, {M, F, A}};
+mfa(M, MFA) -> {M, MFA}.
+
+parse_xref_result({{SM, _, _}, MFAt}) -> {SM, MFAt};
+parse_xref_result({TM, _, _} = MFAt) -> {TM, MFAt}.
+
+parse_xref_source({{SM, _, _} = MFAt, _}) -> {SM, MFAt};
+parse_xref_source({TM, _, _} = MFAt) -> {TM, MFAt}.
+
+parse_xref_target({_, {TM, _, _} = MFAt}) -> {TM, MFAt};
+parse_xref_target({TM, _, _} = MFAt) -> {TM, MFAt}.
+
+%% -------------------------------------------------------------------
+%% Preparing results.
+%% -------------------------------------------------------------------
+
+result_to_warning(Check, {MFASource, MFATarget}) ->
+ {Filename, Line} = get_source(MFASource),
+ [{filename, Filename},
+ {line, Line},
+ {source, MFASource},
+ {target, MFATarget},
+ {check, Check}];
+result_to_warning(Check, MFA) ->
+ {Filename, Line} = get_source(MFA),
+ [{filename, Filename},
+ {line, Line},
+ {source, MFA},
+ {check, Check}].
+
+%%
+%% Given a MFA, find the file and LOC where it's defined. Note that
+%% xref doesn't work if there is no abstract_code, so we can avoid
+%% being too paranoid here.
+%%
+get_source({M, F, A}) ->
+ case code:get_object_code(M) of
+ error -> {"", 0};
+ {M, Bin, _} -> find_function_source(M, F, A, Bin)
+ end.
+
+find_function_source(M, F, A, Bin) ->
+ AbstractCode = beam_lib:chunks(Bin, [abstract_code]),
+ {ok, {M, [{abstract_code, {raw_abstract_v1, Code}}]}} = AbstractCode,
+
+ %% Extract the original source filename from the abstract code
+ [Source|_] = [S || {attribute, _, file, {S, _}} <- Code],
+
+ %% Extract the line number for a given function def
+ Fn = [E || E <- Code,
+ element(1, E) == function,
+ element(3, E) == F,
+ element(4, E) == A],
+
+ case Fn of
+ [{function, Line, F, _, _}] when is_integer(Line) ->
+ {Source, Line};
+ [{function, Line, F, _, _}] ->
+ {Source, erl_anno:line(Line)};
+ %% do not crash if functions are exported, even though they
+ %% are not in the source.
+ %% parameterized modules add new/1 and instance/1 for example.
+ [] -> {Source, 0}
+ end.
+
+%% -------------------------------------------------------------------
+%% Reporting results.
+%% -------------------------------------------------------------------
+
+warnings_prn([]) ->
+ ok;
+warnings_prn(Comments) ->
+ Messages = lists:map(fun generate_comment/1, Comments),
+ lists:foreach(fun warning_prn/1, Messages).
+
+warning_prn(Message) ->
+ FullMessage = Message ++ "~n",
+ io:format(FullMessage, []).
+
+generate_comment(XrefWarning) ->
+ Filename = proplists:get_value(filename, XrefWarning),
+ Line = proplists:get_value(line, XrefWarning),
+ Source = proplists:get_value(source, XrefWarning),
+ Check = proplists:get_value(check, XrefWarning),
+ Target = proplists:get_value(target, XrefWarning),
+ Position = case {Filename, Line} of
+ {"", _} -> "";
+ {Filename, 0} -> [Filename, " "];
+ {Filename, Line} -> [Filename, ":",
+ integer_to_list(Line), " "]
+ end,
+ [Position, generate_comment_text(Check, Source, Target)].
+
+generate_comment_text(Check, {SM, SF, SA}, TMFA) ->
+ SMFA = io_lib:format("`~p:~p/~p`", [SM, SF, SA]),
+ generate_comment_text(Check, SMFA, TMFA);
+generate_comment_text(Check, SMFA, {TM, TF, TA}) ->
+ TMFA = io_lib:format("`~p:~p/~p`", [TM, TF, TA]),
+ generate_comment_text(Check, SMFA, TMFA);
+
+generate_comment_text(undefined_function_calls, SMFA, TMFA) ->
+ io_lib:format("~s calls undefined function ~s", [SMFA, TMFA]);
+generate_comment_text(undefined_functions, SMFA, _TMFA) ->
+ io_lib:format("~s is not defined as a function", [SMFA]);
+generate_comment_text(locals_not_used, SMFA, _TMFA) ->
+ io_lib:format("~s is an unused local function", [SMFA]);
+generate_comment_text(exports_not_used, SMFA, _TMFA) ->
+ io_lib:format("~s is an unused export", [SMFA]);
+generate_comment_text(deprecated_function_calls, SMFA, TMFA) ->
+ io_lib:format("~s calls deprecated function ~s", [SMFA, TMFA]);
+generate_comment_text(deprecated_functions, SMFA, _TMFA) ->
+ io_lib:format("~s is deprecated", [SMFA]).