Skip to content

Update Erlang.mk (MERGE IF GREEN) (backport #13580) #13832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 235 additions & 0 deletions erlang.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
ERLANG_MK_FILENAME := $(realpath $(lastword $(MAKEFILE_LIST)))
export ERLANG_MK_FILENAME

<<<<<<< HEAD
ERLANG_MK_VERSION = 2022.05.31-72-gb8a27ab-dirty
=======
ERLANG_MK_VERSION = e13b4c7
>>>>>>> b34a7227b (Update Erlang.mk)
ERLANG_MK_WITHOUT =

# Make 3.81 and 3.82 are deprecated.
Expand Down Expand Up @@ -3774,6 +3778,7 @@ endif

# Deps related targets.

<<<<<<< HEAD
# @todo rename GNUmakefile and makefile into Makefile first, if they exist
# While Makefile file could be GNUmakefile or makefile,
# in practice only Makefile is needed so far.
Expand All @@ -3783,6 +3788,26 @@ define dep_autopatch
$(call erlang,$(call dep_autopatch_appsrc.erl,$(1))); \
$(call dep_autopatch_erlang_mk,$(1)); \
elif [ -f $(DEPS_DIR)/$(1)/Makefile ]; then \
=======
autopatch_verbose_0 = @echo " PATCH " $(subst autopatch-,,$@) "(method: $(AUTOPATCH_METHOD))";
autopatch_verbose_2 = set -x;
autopatch_verbose = $(autopatch_verbose_$(V))

define dep_autopatch_detect
if [ -f $(DEPS_DIR)/$1/erlang.mk ]; then \
echo erlang.mk; \
elif [ -f $(DEPS_DIR)/$1/mix.exs -a -d $(DEPS_DIR)/$1/lib ]; then \
if [ "$(ELIXIR)" != "disable" ]; then \
echo mix; \
elif [ -f $(DEPS_DIR)/$1/rebar.lock -o -f $(DEPS_DIR)/$1/rebar.config ]; then \
echo rebar3; \
elif [ -f $(DEPS_DIR)/$1/Makefile ]; then \
echo noop; \
else \
exit 99; \
fi \
elif [ -f $(DEPS_DIR)/$1/Makefile ]; then \
>>>>>>> b34a7227b (Update Erlang.mk)
if [ -f $(DEPS_DIR)/$1/rebar.lock ]; then \
$(call dep_autopatch2,$1); \
elif [ 0 != `grep -c "include ../\w*\.mk" $(DEPS_DIR)/$(1)/Makefile` ]; then \
Expand Down Expand Up @@ -4839,6 +4864,216 @@ clean-app:

endif

<<<<<<< HEAD
=======
# Copyright (c) 2024, Tyler Hughes <[email protected]>
# Copyright (c) 2024, Loïc Hoguin <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.

# Elixir is automatically enabled in all cases except when
# an Erlang project uses an Elixir dependency. In that case
# $(ELIXIR) must be set explicitly.
ELIXIR ?= $(if $(filter elixir,$(BUILD_DEPS) $(DEPS)),dep,$(if $(EX_FILES),system,disable))
export ELIXIR

ifeq ($(ELIXIR),system)
# We expect 'elixir' to be on the path.
ELIXIR_BIN ?= $(shell readlink -f `which elixir`)
ELIXIR_LIBS ?= $(abspath $(dir $(ELIXIR_BIN))/../lib)
# Fallback in case 'elixir' is a shim.
ifeq ($(wildcard $(ELIXIR_LIBS)/elixir/),)
ELIXIR_LIBS = $(abspath $(shell elixir -e 'IO.puts(:code.lib_dir(:elixir))')/../)
endif
ELIXIR_LIBS := $(ELIXIR_LIBS)
export ELIXIR_LIBS
ERL_LIBS := $(ERL_LIBS):$(ELIXIR_LIBS)
else
ifeq ($(ELIXIR),dep)
ERL_LIBS := $(ERL_LIBS):$(DEPS_DIR)/elixir/lib/
endif
endif

elixirc_verbose_0 = @echo " EXC $(words $(EX_FILES)) files";
elixirc_verbose_2 = set -x;
elixirc_verbose = $(elixirc_verbose_$(V))

# Unfortunately this currently requires Elixir.
# https://github.com/jelly-beam/verl is a good choice
# for an Erlang implementation, but we already have to
# pull hex_core and Rebar3 so adding yet another pull
# is annoying, especially one that would be necessary
# every time we autopatch Rebar projects. Wait and see.
define hex_version_resolver.erl
HexVersionResolve = fun(Name, Req) ->
application:ensure_all_started(ssl),
application:ensure_all_started(inets),
Config = $(hex_config.erl),
case hex_repo:get_package(Config, atom_to_binary(Name)) of
{ok, {200, _RespHeaders, Package}} ->
#{releases := List} = Package,
{value, #{version := Version}} = lists:search(fun(#{version := Vsn}) ->
M = list_to_atom("Elixir.Version"),
F = list_to_atom("match?"),
M:F(Vsn, Req)
end, List),
{ok, Version};
{ok, {Status, _, Errors}} ->
{error, Status, Errors}
end
end,
HexVersionResolveAndPrint = fun(Name, Req) ->
case HexVersionResolve(Name, Req) of
{ok, Version} ->
io:format("~s", [Version]),
halt(0);
{error, Status, Errors} ->
io:format("Error ~b: ~0p~n", [Status, Errors]),
halt(77)
end
end
endef

define dep_autopatch_mix.erl
$(call hex_version_resolver.erl),
{ok, _} = application:ensure_all_started(elixir),
{ok, _} = application:ensure_all_started(mix),
MixFile = <<"$(call core_native_path,$(DEPS_DIR)/$1/mix.exs)">>,
{Mod, Bin} =
case elixir_compiler:file(MixFile, fun(_File, _LexerPid) -> ok end) of
[{T = {_, _}, _CheckerPid}] -> T;
[T = {_, _}] -> T
end,
{module, Mod} = code:load_binary(Mod, binary_to_list(MixFile), Bin),
Project = Mod:project(),
Application = try Mod:application() catch error:undef -> [] end,
StartMod = case lists:keyfind(mod, 1, Application) of
{mod, {StartMod0, _StartArgs}} ->
atom_to_list(StartMod0);
_ ->
""
end,
Write = fun (Text) ->
file:write_file("$(call core_native_path,$(DEPS_DIR)/$1/Makefile)", Text, [append])
end,
Write([
"PROJECT = ", atom_to_list(proplists:get_value(app, Project)), "\n"
"PROJECT_DESCRIPTION = ", proplists:get_value(description, Project, ""), "\n"
"PROJECT_VERSION = ", proplists:get_value(version, Project, ""), "\n"
"PROJECT_MOD = ", StartMod, "\n"
"define PROJECT_ENV\n",
io_lib:format("~p", [proplists:get_value(env, Application, [])]), "\n"
"endef\n\n"]),
ExtraApps = lists:usort([eex, elixir, logger, mix] ++ proplists:get_value(extra_applications, Application, [])),
Write(["LOCAL_DEPS += ", lists:join(" ", [atom_to_list(App) || App <- ExtraApps]), "\n\n"]),
Deps = proplists:get_value(deps, Project, []) -- [elixir_make],
IsRequiredProdDep = fun(Opts) ->
(proplists:get_value(optional, Opts) =/= true)
andalso
case proplists:get_value(only, Opts, prod) of
prod -> true;
L when is_list(L) -> lists:member(prod, L);
_ -> false
end
end,
lists:foreach(fun
({Name, Req}) when is_binary(Req) ->
{ok, Vsn} = HexVersionResolve(Name, Req),
Write(["DEPS += ", atom_to_list(Name), "\n"]),
Write(["dep_", atom_to_list(Name), " = hex ", Vsn, " ", atom_to_list(Name), "\n"]);
({Name, Opts}) when is_list(Opts) ->
Path = proplists:get_value(path, Opts),
case IsRequiredProdDep(Opts) of
true when Path =/= undefined ->
Write(["DEPS += ", atom_to_list(Name), "\n"]),
Write(["dep_", atom_to_list(Name), " = ln ", Path, "\n"]);
true when Path =:= undefined ->
Write(["DEPS += ", atom_to_list(Name), "\n"]),
io:format(standard_error, "Warning: No version given for ~p.", [Name]);
false ->
ok
end;
({Name, Req, Opts}) ->
case IsRequiredProdDep(Opts) of
true ->
{ok, Vsn} = HexVersionResolve(Name, Req),
Write(["DEPS += ", atom_to_list(Name), "\n"]),
Write(["dep_", atom_to_list(Name), " = hex ", Vsn, " ", atom_to_list(Name), "\n"]);
false ->
ok
end;
(_) ->
ok
end, Deps),
case lists:member(elixir_make, proplists:get_value(compilers, Project, [])) of
false ->
ok;
true ->
Write("# https://hexdocs.pm/elixir_make/Mix.Tasks.Compile.ElixirMake.html\n"),
MakeVal = fun(Key, Proplist, DefaultVal, DefaultReplacement) ->
case proplists:get_value(Key, Proplist, DefaultVal) of
DefaultVal -> DefaultReplacement;
Value -> Value
end
end,
MakeMakefile = binary_to_list(MakeVal(make_makefile, Project, default, <<"Makefile">>)),
MakeExe = MakeVal(make_executable, Project, default, "$$\(MAKE)"),
MakeCwd = MakeVal(make_cwd, Project, undefined, <<".">>),
MakeTargets = MakeVal(make_targets, Project, [], []),
MakeArgs = MakeVal(make_args, Project, undefined, []),
case file:rename("$(DEPS_DIR)/$1/" ++ MakeMakefile, "$(DEPS_DIR)/$1/elixir_make.mk") of
ok -> ok;
Err = {error, _} ->
io:format(standard_error, "Failed to copy Makefile with error ~p~n", [Err]),
halt(90)
end,
Write(["app::\n"
"\t", MakeExe, " -C ", MakeCwd, " -f $(DEPS_DIR)/$1/elixir_make.mk",
lists:join(" ", MakeTargets),
lists:join(" ", MakeArgs),
"\n\n"]),
case MakeVal(make_clean, Project, nil, undefined) of
undefined ->
ok;
Clean ->
Write(["clean::\n\t", Clean, "\n\n"])
end
end,
Write("ERLC_OPTS = +debug_info\n\n"),
Write("include $$\(if $$\(ERLANG_MK_FILENAME),$$\(ERLANG_MK_FILENAME),erlang.mk)"),
halt()
endef

define dep_autopatch_mix
sed 's|\(defmodule.*do\)|\1\n try do\n Code.compiler_options(on_undefined_variable: :warn)\n rescue _ -> :ok\n end\n|g' -i $(DEPS_DIR)/$(1)/mix.exs; \
$(MAKE) $(DEPS_DIR)/hex_core/ebin/dep_built; \
MIX_ENV="$(if $(MIX_ENV),$(strip $(MIX_ENV)),prod)" \
$(call erlang,$(call dep_autopatch_mix.erl,$1))
endef

# We change the group leader so the Elixir io:format output
# isn't captured as we need to either print the modules on
# success, or print _ERROR_ on failure.
define compile_ex.erl
{ok, _} = application:ensure_all_started(elixir),
{ok, _} = application:ensure_all_started(mix),
ModCode = list_to_atom("Elixir.Code"),
ModCode:put_compiler_option(ignore_module_conflict, true),
ModComp = list_to_atom("Elixir.Kernel.ParallelCompiler"),
ModMixProject = list_to_atom("Elixir.Mix.Project"),
erlang:group_leader(whereis(standard_error), self()),
ModMixProject:in_project($(PROJECT), ".", [], fun(_MixFile) ->
case ModComp:compile_to_path([$(call comma_list,$(patsubst %,<<"%">>,$1))], <<"ebin/">>) of
{ok, Modules, _} ->
lists:foreach(fun(E) -> io:format(user, "~p ", [E]) end, Modules),
halt(0);
{error, _ErroredModules, _WarnedModules} ->
io:format(user, "_ERROR_", []),
halt(1)
end
end)
endef

>>>>>>> b34a7227b (Update Erlang.mk)
# Copyright (c) 2016, Loïc Hoguin <[email protected]>
# Copyright (c) 2015, Viktor Söderqvist <[email protected]>
# This file is part of erlang.mk and subject to the terms of the ISC License.
Expand Down
Loading