Commit aaa16732 authored by David's avatar David Committed by Raphael Megzari
Browse files

rebar3: add rebar3WithPlugins

parent ac5ef3c5
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -24,6 +24,10 @@ Many Erlang/OTP distributions available in `beam.interpreters` have versions wit

We provide a version of Rebar3, under `rebar3`. We also provide a helper to fetch Rebar3 dependencies from a lockfile under `fetchRebar3Deps`.

We also provide a version on Rebar3 with plugins included, under `rebar3WithPlugins`. This package is a function which takes two arguments: `plugins`, a list of nix derivations to include as plugins (loaded only when specified in `rebar.config`), and `globalPlugins`, which should always be loaded by rebar3. Example: `rebar3WithPlugins { globalPlugins = [beamPackages.pc]; }`.

When adding a new plugin it is important that the `packageName` attribute is the same as the atom used by rebar3 to refer to the plugin.

### Mix & Erlang.mk {#build-tools-other}

Erlang.mk works exactly as expected. There is a bootstrap process that needs to be run, which is supported by the `buildErlangMk` derivation.
+1 −1
Original line number Diff line number Diff line
@@ -18,8 +18,8 @@ let
      inherit callPackage erlang;
      beamPackages = self;

      inherit (callPackage ../tools/build-managers/rebar3 { }) rebar3 rebar3WithPlugins;
      rebar = callPackage ../tools/build-managers/rebar { };
      rebar3 = callPackage ../tools/build-managers/rebar3 { };

      # rebar3 port compiler plugin is required by buildRebar3
      pc = callPackage ./pc { };
+96 −63
Original line number Diff line number Diff line
{ lib, stdenv, fetchFromGitHub,
  fetchHex, erlang,
  tree }:
  fetchHex, erlang, makeWrapper }:

let
  version = "3.15.1";

  # Dependencies should match the ones in:
  # https://github.com/erlang/rebar3/blob/${version}/rebar.lock
  # `sha256` could also be taken from https://hex.pm - Checksum
  deps = import ./rebar-deps.nix { inherit fetchHex; };
in
stdenv.mkDerivation rec {
  owner = "erlang";
  deps = import ./rebar-deps.nix { inherit fetchHex fetchFromGitHub; };
  rebar3 = stdenv.mkDerivation rec {
    pname = "rebar3";
    inherit version erlang;

    # How to obtain `sha256`:
    # nix-prefetch-url --unpack https://github.com/erlang/rebar3/archive/${version}.tar.gz
    src = fetchFromGitHub {
    owner = "erlang";
      inherit owner;
      repo = pname;
      rev = version;
      sha256 = "1pcy5m79g0l9l3d8lkbx6cq1w87z1g3sa6wwvgbgraj2v3wkyy5g";
@@ -25,11 +20,10 @@ stdenv.mkDerivation rec {

    bootstrapper = ./rebar3-nix-bootstrap;

  buildInputs = [ erlang tree ];
    buildInputs = [ erlang ];

    postPatch = ''
    mkdir -p _checkouts
    mkdir -p _build/default/lib/
      mkdir -p _checkouts _build/default/lib/

      ${toString (lib.mapAttrsToList (k: v: ''
        cp -R --no-preserve=mode ${v} _checkouts/${k}
@@ -68,4 +62,43 @@ stdenv.mkDerivation rec {
      maintainers = lib.teams.beam.members;
      license = lib.licenses.asl20;
    };
}

  };
  rebar3WithPlugins = { plugins ? [ ], globalPlugins ? [ ] }:
    let
      pluginLibDirs = map (p: "${p}/lib/erlang/lib") (lib.unique (plugins ++ globalPlugins));
      globalPluginNames = lib.unique (map (p: p.packageName) globalPlugins);
      rebar3Patched = (rebar3.overrideAttrs (old: {

        # skip-plugins.patch is necessary because otherwise rebar3 will always
        # try to fetch plugins if they are not already present in _build.
        #
        # global-deps.patch makes it possible to use REBAR_GLOBAL_PLUGINS to
        # instruct rebar3 to always load a certain plugin. It is necessary since
        # REBAR_GLOBAL_CONFIG_DIR doesn't seem to work for this.
        patches = [ ./skip-plugins.patch ./global-plugins.patch ];
      }));
    in stdenv.mkDerivation {
      pname = "rebar3-with-plugins";
      inherit (rebar3) version bootstrapper;
      nativeBuildInputs = [ erlang makeWrapper ];
      unpackPhase = "true";

      # Here we extract the rebar3 escript (like `rebar3_prv_local_install.erl`) and
      # add plugins to the code path.

      installPhase = ''
        erl -noshell -eval '
          {ok, Escript} = escript:extract("${rebar3Patched}/bin/rebar3", []),
          {archive, Archive} = lists:keyfind(archive, 1, Escript),
          {ok, _} = zip:extract(Archive, [{cwd, "'$out/lib'"}]),
          init:stop(0)
        '
        mkdir -p $out/bin
        makeWrapper ${erlang}/bin/erl $out/bin/rebar3 \
          --set REBAR_GLOBAL_PLUGINS "${toString globalPluginNames}" \
          --suffix-each ERL_LIBS ":" "$out/lib ${toString pluginLibDirs}" \
          --add-flags "+sbtu +A1 -noshell -boot start_clean -s rebar3 main -extra"
      '';
    };
in { inherit rebar3 rebar3WithPlugins; }
+14 −0
Original line number Diff line number Diff line
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl
index f2d22233..bee2cf18 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -30,7 +30,8 @@ project_plugins_install(State) ->
 top_level_install(State) ->
     Profiles = rebar_state:current_profiles(State),
     lists:foldl(fun(Profile, StateAcc) ->
-                        Plugins = rebar_state:get(State, {plugins, Profile}, []),
+                        Plugins = rebar_state:get(State, {plugins, Profile}, [])
+                            ++ [list_to_atom(P) || P <- string:lexemes(os:getenv("REBAR_GLOBAL_PLUGINS", ""), " ")],
                         handle_plugins(Profile, Plugins, StateAcc)
                 end, State, Profiles).
 
+54 −0
Original line number Diff line number Diff line
diff --git a/src/rebar_plugins.erl b/src/rebar_plugins.erl
index f2d22233..c61fa553 100644
--- a/src/rebar_plugins.erl
+++ b/src/rebar_plugins.erl
@@ -106,31 +106,9 @@ handle_plugins(Profile, Plugins, State, Upgrade) ->
     State3 = rebar_state:set(State2, deps_dir, DepsDir),
     rebar_state:lock(State3, Locks).
 
-handle_plugin(Profile, Plugin, State, Upgrade) ->
+handle_plugin(_Profile, Plugin, State, _Upgrade) ->
     try
-        {Apps, State2} = rebar_prv_install_deps:handle_deps_as_profile(Profile, State, [Plugin], Upgrade),
-        {no_cycle, Sorted} = rebar_prv_install_deps:find_cycles(Apps),
-        ToBuild = rebar_prv_install_deps:cull_compile(Sorted, []),
-
-        %% Add already built plugin deps to the code path
-        ToBuildPaths = [rebar_app_info:ebin_dir(A) || A <- ToBuild],
-        PreBuiltPaths = [Ebin || A <- Apps,
-                                 Ebin <- [rebar_app_info:ebin_dir(A)],
-                                 not lists:member(Ebin, ToBuildPaths)],
-        code:add_pathsa(PreBuiltPaths),
-
-        %% Build plugin and its deps
-        build_plugins(ToBuild, Apps, State2),
-
-        %% Add newly built deps and plugin to code path
-        State3 = rebar_state:update_all_plugin_deps(State2, Apps),
-        NewCodePaths = [rebar_app_info:ebin_dir(A) || A <- ToBuild],
-
-        %% Store plugin code paths so we can remove them when compiling project apps
-        State4 = rebar_state:update_code_paths(State3, all_plugin_deps, PreBuiltPaths++NewCodePaths),
-        rebar_paths:set_paths([plugins], State4),
-
-        {plugin_providers(Plugin), State4}
+        {plugin_providers(Plugin), State}
     catch
         ?WITH_STACKTRACE(C,T,S)
             ?DEBUG("~p ~p ~p", [C, T, S]),
@@ -138,15 +116,6 @@ handle_plugin(Profile, Plugin, State, Upgrade) ->
             {[], State}
     end.
 
-build_plugins(MustBuildApps, AllApps, State) ->
-    State1 = rebar_state:deps_to_build(State, MustBuildApps),
-    State2 = rebar_state:all_deps(State1, AllApps),
-    State3 = rebar_state:set(State2, deps_dir, ?DEFAULT_PLUGINS_DIR),
-    {Args, Extra} = rebar_state:command_parsed_args(State),
-    State4 = rebar_state:command_parsed_args(State3, {[{deps_only, true}|Args], Extra}),
-    rebar_prv_compile:do(State4),
-    ok.
-
 plugin_providers({Plugin, _, _, _}) when is_atom(Plugin) ->
     validate_plugin(Plugin);
 plugin_providers({Plugin, _, _}) when is_atom(Plugin) ->
Loading