@@ -31,6 +31,10 @@ DISABLE_DISTCLEAN = 1
3131
3232XREF_SCOPE = app deps
3333
34+ # We add all the applications that are in non-standard paths
35+ # so they are included in the analyses as well.
36+ XREF_EXTRA_APP_DIRS = $(filter-out deps/rabbitmq_cli/_build/dev/lib/rabbit_common/,$(wildcard deps/rabbitmq_cli/_build/dev/lib/* /) ) deps/rabbitmq_prelaunch/
37+
3438# For Elixir protocols the right fix is to include the consolidated/
3539# folders in addition to ebin/. However this creates conflicts because
3640# some modules are duplicated. So instead we ignore warnings from
@@ -44,12 +48,64 @@ XREF_IGNORE = [ \
4448# Include Elixir libraries in the Xref checks.
4549xref : ERL_LIBS := $(ERL_LIBS ) :$(CURDIR ) /apps:$(CURDIR ) /deps:$(dir $(shell elixir --eval ":io.format '~s~n', [:code.lib_dir :elixir ]") )
4650
51+ ifneq ($(wildcard deps/.hex/cache.erl) ,)
52+ deps :: restore-hex-cache-ets-file
53+ endif
54+
4755include rabbitmq-components.mk
4856include erlang.mk
4957include mk/github-actions.mk
5058include mk/bazel.mk
5159include mk/topic-branches.mk
5260
61+ # --------------------------------------------------------------------
62+ # Mix Hex cache management.
63+ # --------------------------------------------------------------------
64+
65+ # We restore the initial Hex cache.ets file from an Erlang term created
66+ # at the time the source archive was prepared.
67+ #
68+ # See the `$(SOURCE_DIST)` recipe for the reason behind this step.
69+
70+ restore-hex-cache-ets-file : deps/.hex/cache.ets
71+
72+ deps/.hex/cache.ets : deps/.hex/cache.erl
73+ $(gen_verbose ) $(call erlang,$(call restore_hex_cache_from_erl_term,$< ,$@ ) )
74+
75+ define restore_hex_cache_from_erl_term
76+ In = "$(1 ) ",
77+ Out = "$(2 ) ",
78+ {ok, [Props, Entries]} = file:consult(In),
79+ Name = proplists:get_value(name, Props),
80+ Type = proplists:get_value(type, Props),
81+ Access = proplists:get_value(protection, Props),
82+ NamedTable = proplists:get_bool(named_table, Props),
83+ Keypos = proplists:get_value(keypos, Props),
84+ Heir = proplists:get_value(heir, Props),
85+ ReadConc = proplists:get_bool(read_concurrency, Props),
86+ WriteConc = proplists:get_bool(write_concurrency, Props),
87+ Compressed = proplists:get_bool(compressed, Props),
88+ Options0 = [
89+ Type,
90+ Access,
91+ {keypos, Keypos},
92+ {heir, Heir},
93+ {read_concurrency, ReadConc},
94+ {write_concurrency, WriteConc}],
95+ Options1 = case NamedTable of
96+ true -> [named_table | Options0];
97+ false -> Options0
98+ end,
99+ Options2 = case Compressed of
100+ true -> [compressed | Options0];
101+ false -> Options0
102+ end,
103+ Tab = ets:new(Name, Options2),
104+ [true = ets:insert(Tab, Entry) || Entry <- Entries],
105+ ok = ets:tab2file(Tab, Out),
106+ init:stop().
107+ endef
108+
53109# --------------------------------------------------------------------
54110# Distribution - common variables and generic functions.
55111# --------------------------------------------------------------------
@@ -192,6 +248,14 @@ $(1): $(ERLANG_MK_RECURSIVE_DEPS_LIST)
192248 sed -E -i.bak "s|^[[:blank:]]*include[[:blank:]]+\.\./.*erlang.mk$$$$|include ../../erlang.mk|" \
193249 $$@ /deps/$$$$(basename $$$$dep) /Makefile && \
194250 rm $$@ /deps/$$$$(basename $$$$dep) /Makefile.bak; \
251+ mix_exs=$$@ /deps/$$$$(basename $$$$dep) /mix.exs; \
252+ if test -f $$$$mix_exs; then \
253+ (cd $$$$(dirname "$$$$mix_exs" ) && \
254+ (test -d $$@ /deps/.hex || env DEPS_DIR=$$@ /deps MIX_HOME=$$@ /deps/.mix HEX_HOME=$$@ /deps/.hex MIX_ENV=prod FILL_HEX_CACHE=yes mix local.hex --force) && \
255+ env DEPS_DIR=$$@ /deps MIX_HOME=$$@ /deps/.mix HEX_HOME=$$@ /deps/.hex MIX_ENV=prod FILL_HEX_CACHE=yes mix deps.get --only prod && \
256+ cp $(CURDIR ) /mk/rabbitmq-mix.mk . && \
257+ rm -rf _build deps); \
258+ fi; \
195259 if test -f "$$$$dep/license_info"; then \
196260 cp "$$$$dep/license_info" "$$@ /deps/licensing/license_info_$$$$(basename $$$$dep) "; \
197261 cat "$$$$dep/license_info" >> $$@ /LICENSE; \
@@ -216,6 +280,7 @@ $(1): $(ERLANG_MK_RECURSIVE_DEPS_LIST)
216280 done
217281 $${verbose} echo "PLUGINS := $(PLUGINS ) " > $$@ /plugins.mk
218282 $${verbose} sort -r < "$$@ .git-times.txt" | head -n 1 > "$$@ .git-time.txt"
283+ $${verbose} $$(call erlang,$$(call dump_hex_cache_to_erl_term,$$(call core_native_path,$$@ ) ,$$(call core_native_path,$$@ .git-time.txt) ) )
219284 $${verbose} find $$@ -print0 | xargs -0 touch -t "$$$$(cat $$@ .git-time.txt ) "
220285 $${verbose} rm "$$@ .git-times.txt" "$$@ .git-time.txt"
221286
@@ -257,6 +322,47 @@ clean-$(1):
257322clean:: clean-$(1 )
258323endef
259324
325+ # Mix Hex component requires a cache file, otherwise it refuses to build
326+ # offline... That cache is an ETS table with all the applications we
327+ # depend on, plus some versioning informations and checksums. There
328+ # are two problems with that: the table contains a date (`last_update`
329+ # field) and `ets:tab2file()` produces a different file each time it's
330+ # called.
331+ #
332+ # To make our source archive reproducible, we fix the time of the
333+ # `last_update` field to the last Git commit and dump the content of the
334+ # table as an Erlang term to a text file.
335+ #
336+ # The ETS file must be recreated before compiling RabbitMQ. See the
337+ # `restore-hex-cache-ets-file` Make target.
338+ define dump_hex_cache_to_erl_term
339+ In = "$(1 ) /deps/.hex/cache.ets",
340+ Out = "$(1 ) /deps/.hex/cache.erl",
341+ {ok, DateStr} = file:read_file("$(2 ) "),
342+ {match, Date} = re:run(DateStr,
343+ "^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})\.([0-9]{2})",
344+ [{capture, all_but_first, list}]),
345+ [Year, Month, Day, Hour, Min, Sec] = [erlang:list_to_integer(V) || V <- Date],
346+ {ok, Tab} = ets:file2tab(In),
347+ true = ets:insert(Tab, {last_update, {{Year, Month, Day}, {Hour, Min, Sec}}}),
348+ Props = [
349+ Prop
350+ || {Key, _} = Prop <- ets:info(Tab),
351+ Key =:= name orelse
352+ Key =:= type orelse
353+ Key =:= protection orelse
354+ Key =:= named_table orelse
355+ Key =:= keypos orelse
356+ Key =:= heir orelse
357+ Key =:= read_concurrency orelse
358+ Key =:= write_concurrency orelse
359+ Key =:= compressed],
360+ Entries = ets:tab2list(Tab),
361+ ok = file:write_file(Out, io_lib:format("~w.~n~w.~n", [Props, Entries])),
362+ ok = file:delete(In),
363+ init:stop().
364+ endef
365+
260366# --------------------------------------------------------------------
261367# Distribution - public targets
262368# --------------------------------------------------------------------
0 commit comments