buildRebar3: use `rebar3 bare compile`
This commit is contained in:
parent
0d66d837d3
commit
aef59d8856
|
@ -1,12 +1,10 @@
|
||||||
{ stdenv, writeText, erlang, rebar3WithPlugins, openssl, libyaml,
|
{ stdenv, writeText, erlang, rebar3WithPlugins, openssl, libyaml, lib }:
|
||||||
pc, lib }:
|
|
||||||
|
|
||||||
{ name, version
|
{ name, version
|
||||||
, src
|
, src
|
||||||
, setupHook ? null
|
, setupHook ? null
|
||||||
, buildInputs ? [], beamDeps ? [], buildPlugins ? []
|
, buildInputs ? [], beamDeps ? [], buildPlugins ? []
|
||||||
, postPatch ? ""
|
, postPatch ? ""
|
||||||
, compilePorts ? false
|
|
||||||
, installPhase ? null
|
, installPhase ? null
|
||||||
, buildPhase ? null
|
, buildPhase ? null
|
||||||
, configurePhase ? null
|
, configurePhase ? null
|
||||||
|
@ -21,7 +19,6 @@ let
|
||||||
|
|
||||||
rebar3 = rebar3WithPlugins {
|
rebar3 = rebar3WithPlugins {
|
||||||
plugins = buildPlugins;
|
plugins = buildPlugins;
|
||||||
globalPlugins = (if compilePorts then [pc] else []);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
shell = drv: stdenv.mkDerivation {
|
shell = drv: stdenv.mkDerivation {
|
||||||
|
@ -52,18 +49,9 @@ let
|
||||||
rm -f rebar rebar3
|
rm -f rebar rebar3
|
||||||
'' + postPatch;
|
'' + postPatch;
|
||||||
|
|
||||||
configurePhase = ''
|
|
||||||
runHook preConfigure
|
|
||||||
${erlang}/bin/escript ${rebar3.bootstrapper} ${debugInfoFlag}
|
|
||||||
runHook postConfigure
|
|
||||||
'';
|
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
runHook preBuild
|
runHook preBuild
|
||||||
HOME=. rebar3 compile
|
HOME=. rebar3 bare compile -path ""
|
||||||
${if compilePorts then ''
|
|
||||||
HOME=. rebar3 pc compile
|
|
||||||
'' else ""}
|
|
||||||
runHook postBuild
|
runHook postBuild
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -71,10 +59,9 @@ let
|
||||||
runHook preInstall
|
runHook preInstall
|
||||||
mkdir -p "$out/lib/erlang/lib/${name}-${version}"
|
mkdir -p "$out/lib/erlang/lib/${name}-${version}"
|
||||||
for reldir in src ebin priv include; do
|
for reldir in src ebin priv include; do
|
||||||
fd="_build/default/lib/${name}/$reldir"
|
[ -d "$reldir" ] || continue
|
||||||
[ -d "$fd" ] || continue
|
# $out/lib/erlang/lib is a convention used in nixpkgs for compiled BEAM packages
|
||||||
cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$fd"
|
cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$reldir"
|
||||||
success=1
|
|
||||||
done
|
done
|
||||||
runHook postInstall
|
runHook postInstall
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -19,8 +19,6 @@ let
|
||||||
sha256 = "1pcy5m79g0l9l3d8lkbx6cq1w87z1g3sa6wwvgbgraj2v3wkyy5g";
|
sha256 = "1pcy5m79g0l9l3d8lkbx6cq1w87z1g3sa6wwvgbgraj2v3wkyy5g";
|
||||||
};
|
};
|
||||||
|
|
||||||
bootstrapper = ./rebar3-nix-bootstrap;
|
|
||||||
|
|
||||||
buildInputs = [ erlang ];
|
buildInputs = [ erlang ];
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
@ -106,7 +104,7 @@ let
|
||||||
}));
|
}));
|
||||||
in stdenv.mkDerivation {
|
in stdenv.mkDerivation {
|
||||||
pname = "rebar3-with-plugins";
|
pname = "rebar3-with-plugins";
|
||||||
inherit (rebar3) version bootstrapper;
|
inherit (rebar3) version;
|
||||||
nativeBuildInputs = [ erlang makeWrapper ];
|
nativeBuildInputs = [ erlang makeWrapper ];
|
||||||
unpackPhase = "true";
|
unpackPhase = "true";
|
||||||
|
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
#!/usr/bin/env escript
|
|
||||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
|
||||||
%%! -smp enable
|
|
||||||
%%% ---------------------------------------------------------------------------
|
|
||||||
%%% @doc
|
|
||||||
%%% The purpose of this command is to prepare a rebar3 project so that
|
|
||||||
%%% rebar3 understands that the dependencies are all already
|
|
||||||
%%% installed. If you want a hygienic build on nix then you must run
|
|
||||||
%%% this command before running rebar3. I suggest that you add a
|
|
||||||
%%% `Makefile` to your project and have the bootstrap command be a
|
|
||||||
%%% dependency of the build commands. See the nix documentation for
|
|
||||||
%%% more information.
|
|
||||||
%%%
|
|
||||||
%%% This command designed to have as few dependencies as possible so
|
|
||||||
%%% that it can be a dependency of root level packages like rebar3. To
|
|
||||||
%%% that end it does many things in a fairly simplistic way. That is
|
|
||||||
%%% by design.
|
|
||||||
%%%
|
|
||||||
%%% ### Assumptions
|
|
||||||
%%%
|
|
||||||
%%% This command makes the following assumptions:
|
|
||||||
%%%
|
|
||||||
%%% * It is run in a nix-shell or nix-build environment
|
|
||||||
%%% * that all dependencies have been added to the ERL_LIBS
|
|
||||||
%%% Environment Variable
|
|
||||||
|
|
||||||
-record(data, {version
|
|
||||||
, debug_info = false
|
|
||||||
, erl_libs
|
|
||||||
, root
|
|
||||||
, name}).
|
|
||||||
|
|
||||||
-define(HEX_REGISTRY_PATH, ".cache/rebar3/hex/default/registry").
|
|
||||||
|
|
||||||
main(Args) ->
|
|
||||||
{ok, ArgData} = parse_args(Args),
|
|
||||||
{ok, RequiredData} = gather_required_data_from_the_environment(ArgData),
|
|
||||||
do_the_bootstrap(RequiredData).
|
|
||||||
|
|
||||||
-spec do_the_bootstrap(#data{}) -> ok.
|
|
||||||
do_the_bootstrap(RequiredData) ->
|
|
||||||
ok = bootstrap_configs(RequiredData),
|
|
||||||
ok = bootstrap_libs(RequiredData).
|
|
||||||
|
|
||||||
%% @doc
|
|
||||||
%% Argument parsing is super simple only because we want to keep the
|
|
||||||
%% dependencies minimal. For now there can be one entry on the
|
|
||||||
%% command line: "debug-info"
|
|
||||||
-spec parse_args([string()]) -> #data{}.
|
|
||||||
parse_args(Args0) ->
|
|
||||||
PossibleArgs = sets:from_list(["debug-info"]),
|
|
||||||
Args1 = sets:from_list(Args0),
|
|
||||||
Result = sets:subtract(Args1, PossibleArgs),
|
|
||||||
case sets:to_list(Result) of
|
|
||||||
[] ->
|
|
||||||
{ok, #data{debug_info = sets:is_element("debug-info", Args1)}};
|
|
||||||
UnknownArgs ->
|
|
||||||
io:format("Unexpected command line arguments passed in: ~p~n",
|
|
||||||
[UnknownArgs]),
|
|
||||||
erlang:halt(120)
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
-spec bootstrap_configs(#data{}) -> ok.
|
|
||||||
bootstrap_configs(RequiredData)->
|
|
||||||
io:format("Boostrapping app and rebar configurations~n"),
|
|
||||||
ok = if_single_app_project_update_app_src_version(RequiredData),
|
|
||||||
ok = if_debug_info_add(RequiredData).
|
|
||||||
|
|
||||||
-spec bootstrap_libs(#data{}) -> ok.
|
|
||||||
bootstrap_libs(#data{erl_libs = ErlLibs}) ->
|
|
||||||
io:format("Bootstrapping dependent libraries~n"),
|
|
||||||
Target = "_build/default/lib/",
|
|
||||||
Paths = string:tokens(ErlLibs, ":"),
|
|
||||||
CopiableFiles =
|
|
||||||
lists:foldl(fun(Path, Acc) ->
|
|
||||||
gather_directory_contents(Path) ++ Acc
|
|
||||||
end, [], Paths),
|
|
||||||
lists:foreach(fun (Path) ->
|
|
||||||
ok = link_app(Path, Target)
|
|
||||||
end, CopiableFiles).
|
|
||||||
|
|
||||||
-spec gather_dependency(string()) -> [{string(), string()}].
|
|
||||||
gather_dependency(Path) ->
|
|
||||||
FullLibrary = filename:join(Path, "lib/erlang/lib/"),
|
|
||||||
case filelib:is_dir(FullLibrary) of
|
|
||||||
true ->
|
|
||||||
gather_directory_contents(FullLibrary);
|
|
||||||
false ->
|
|
||||||
[raw_hex(Path)]
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec raw_hex(string()) -> {string(), string()}.
|
|
||||||
raw_hex(Path) ->
|
|
||||||
[_, Name] = re:split(Path, "-hex-source-"),
|
|
||||||
{Path, erlang:binary_to_list(Name)}.
|
|
||||||
|
|
||||||
-spec gather_directory_contents(string()) -> [{string(), string()}].
|
|
||||||
gather_directory_contents(Path) ->
|
|
||||||
{ok, Names} = file:list_dir(Path),
|
|
||||||
lists:map(fun(AppName) ->
|
|
||||||
{filename:join(Path, AppName), fixup_app_name(AppName)}
|
|
||||||
end, Names).
|
|
||||||
|
|
||||||
%% @doc
|
|
||||||
%% Makes a symlink from the directory pointed at by Path to a
|
|
||||||
%% directory of the same name in Target. So if we had a Path of
|
|
||||||
%% {`foo/bar/baz/bash`, `baz`} and a Target of `faz/foo/foos`, the symlink
|
|
||||||
%% would be `faz/foo/foos/baz`.
|
|
||||||
-spec link_app({string(), string()}, string()) -> ok.
|
|
||||||
link_app({Path, TargetFile}, TargetDir) ->
|
|
||||||
Target = filename:join(TargetDir, TargetFile),
|
|
||||||
make_symlink(Path, Target).
|
|
||||||
|
|
||||||
-spec make_symlink(string(), string()) -> ok.
|
|
||||||
make_symlink(Path, TargetFile) ->
|
|
||||||
file:delete(TargetFile),
|
|
||||||
ok = filelib:ensure_dir(TargetFile),
|
|
||||||
io:format("Making symlink from ~s to ~s~n", [Path, TargetFile]),
|
|
||||||
ok = file:make_symlink(Path, TargetFile).
|
|
||||||
|
|
||||||
%% @doc
|
|
||||||
%% This takes an app name in the standard OTP <name>-<version> format
|
|
||||||
%% and returns just the app name. Why? Because rebar doesn't
|
|
||||||
%% respect OTP conventions in some cases.
|
|
||||||
-spec fixup_app_name(string()) -> string().
|
|
||||||
fixup_app_name(FileName) ->
|
|
||||||
case string:tokens(FileName, "-") of
|
|
||||||
[Name] -> Name;
|
|
||||||
[Name, _Version] -> Name;
|
|
||||||
[Name, _Version, _Tag] -> Name
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec gather_required_data_from_the_environment(#data{}) -> {ok, #data{}}.
|
|
||||||
gather_required_data_from_the_environment(ArgData) ->
|
|
||||||
{ok, ArgData#data{ version = guard_env("version")
|
|
||||||
, erl_libs = get_env("ERL_LIBS", [])
|
|
||||||
, root = code:root_dir()
|
|
||||||
, name = guard_env("name")
|
|
||||||
}}.
|
|
||||||
|
|
||||||
-spec nix2bool(any()) -> boolean().
|
|
||||||
nix2bool("1") ->
|
|
||||||
true;
|
|
||||||
nix2bool("") ->
|
|
||||||
false.
|
|
||||||
|
|
||||||
get_env(Name) ->
|
|
||||||
os:getenv(Name).
|
|
||||||
get_env(Name, Def) ->
|
|
||||||
case get_env(Name) of
|
|
||||||
false -> Def;
|
|
||||||
Val -> Val
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec guard_env(string()) -> string().
|
|
||||||
guard_env(Name) ->
|
|
||||||
case get_env(Name) of
|
|
||||||
false ->
|
|
||||||
stderr("Expected Environment variable ~s! Are you sure you are "
|
|
||||||
"running in a Nix environment? Either a nix-build, "
|
|
||||||
"nix-shell, etc?~n", [Name]),
|
|
||||||
erlang:halt(1);
|
|
||||||
Variable ->
|
|
||||||
Variable
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% @doc
|
|
||||||
%% If debug info is set we need to add debug info to the list of compile options
|
|
||||||
%%
|
|
||||||
-spec if_debug_info_add(#data{}) -> ok.
|
|
||||||
if_debug_info_add(#data{debug_info = true}) ->
|
|
||||||
ConfigTerms = add_debug_info(read_rebar_config()),
|
|
||||||
Text = lists:map(fun(Term) -> io_lib:format("~tp.~n", [Term]) end,
|
|
||||||
ConfigTerms),
|
|
||||||
file:write_file("rebar.config", Text);
|
|
||||||
if_debug_info_add(_) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
-spec add_debug_info([term()]) -> [term()].
|
|
||||||
add_debug_info(Config) ->
|
|
||||||
ExistingOpts = case lists:keysearch(erl_opts, 1, Config) of
|
|
||||||
{value, {erl_opts, ExistingOptsList}} -> ExistingOptsList;
|
|
||||||
_ -> []
|
|
||||||
end,
|
|
||||||
case lists:member(debug_info, ExistingOpts) of
|
|
||||||
true ->
|
|
||||||
Config;
|
|
||||||
false ->
|
|
||||||
lists:keystore(erl_opts, 1, Config,
|
|
||||||
{erl_opts, [debug_info | ExistingOpts]})
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec read_rebar_config() -> [term()].
|
|
||||||
read_rebar_config() ->
|
|
||||||
case file:consult("rebar.config") of
|
|
||||||
{ok, Terms} ->
|
|
||||||
Terms;
|
|
||||||
_ ->
|
|
||||||
stderr("Unable to read rebar config!", []),
|
|
||||||
erlang:halt(1)
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
-spec if_single_app_project_update_app_src_version(#data{}) -> ok.
|
|
||||||
if_single_app_project_update_app_src_version(#data{name = Name,
|
|
||||||
version = Version}) ->
|
|
||||||
SrcFile = filename:join("src",
|
|
||||||
lists:concat([Name, ".app.src"])),
|
|
||||||
|
|
||||||
case filelib:is_file(SrcFile) of
|
|
||||||
true ->
|
|
||||||
update_app_src_with_version(SrcFile, Version);
|
|
||||||
false ->
|
|
||||||
ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec update_app_src_with_version(string(), string()) -> ok.
|
|
||||||
update_app_src_with_version(SrcFile, Version) ->
|
|
||||||
{ok, [{application, Name, Details}]} = file:consult(SrcFile),
|
|
||||||
NewDetails = lists:keyreplace(vsn, 1, Details, {vsn, Version}),
|
|
||||||
ok = file:write_file(SrcFile, io_lib:fwrite("~p.\n", [{application, Name, NewDetails}])).
|
|
||||||
|
|
||||||
%% @doc
|
|
||||||
%% Write the result of the format string out to stderr.
|
|
||||||
-spec stderr(string(), [term()]) -> ok.
|
|
||||||
stderr(FormatStr, Args) ->
|
|
||||||
io:put_chars(standard_error, io_lib:format(FormatStr, Args)).
|
|
Loading…
Reference in New Issue