beamPackages: Add support for Mix and Erlang.mk

This commit is contained in:
Eric Merritt
2016-03-28 14:14:13 -07:00
parent 3b7aee2e5a
commit 8dbcb4e35e
16 changed files with 43953 additions and 3053 deletions

View File

@@ -0,0 +1,86 @@
{ stdenv, writeText, erlang, perl, which, gitMinimal, wget }:
{ name, version
, src
, setupHook ? null
, buildInputs ? []
, beamDeps ? []
, postPatch ? ""
, compilePorts ? false
, installPhase ? null
, meta ? {}
, ... }@attrs:
with stdenv.lib;
let
shell = drv: stdenv.mkDerivation {
name = "interactive-shell-${drv.name}";
buildInputs = [ drv ];
};
pkg = self: stdenv.mkDerivation ( attrs // {
app_name = "${name}";
name = "${name}-${version}";
inherit version;
dontStrip = true;
inherit src;
setupHook = if setupHook == null
then writeText "setupHook.sh" ''
addToSearchPath ERL_LIBS "$1/lib/erlang/lib"
''
else setupHook;
buildInputs = [ erlang perl which gitMinimal wget ];
propagatedBuildInputs = beamDeps;
configurePhase = ''
runHook preConfigure
# We shouldnt need to do this, but it seems at times there is a *.app in
# the repo/package. This ensures we start from a clean slate
make SKIP_DEPS=1 clean
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
make SKIP_DEPS=1
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/lib/erlang/lib/${name}
cp -r ebin $out/lib/erlang/lib/${name}/
cp -r src $out/lib/erlang/lib/${name}/
if [ -d include ]; then
cp -r include $out/lib/erlang/lib/${name}/
fi
if [ -d priv ]; then
cp -r priv $out/lib/erlang/lib/${name}/
fi
if [ -d doc ]; then
cp -r doc $out/lib/erlang/lib/${name}/
fi
runHook postInstall
'';
passthru = {
packageName = name;
env = shell self;
inherit beamDeps;
};
});
in fix pkg

View File

@@ -0,0 +1,19 @@
{ stdenv, buildRebar3, fetchHex }:
{ name, version, sha256
, hexPkg ? name
, ... }@attrs:
with stdenv.lib;
let
pkg = self: buildRebar3 (attrs // {
src = fetchHex {
pkg = hexPkg;
inherit version;
inherit sha256;
};
});
in
fix pkg

View File

@@ -0,0 +1,86 @@
{ stdenv, writeText, elixir, erlang, hexRegistrySnapshot, hex }:
{ name
, version
, src
, setupHook ? null
, buildInputs ? []
, beamDeps ? []
, postPatch ? ""
, compilePorts ? false
, installPhase ? null
, meta ? {}
, ... }@attrs:
with stdenv.lib;
let
shell = drv: stdenv.mkDerivation {
name = "interactive-shell-${drv.name}";
buildInputs = [ drv ];
};
bootstrapper = ./mix-bootstrap;
pkg = self: stdenv.mkDerivation ( attrs // {
name = "${name}-${version}";
inherit version;
dontStrip = true;
inherit src;
setupHook = if setupHook == null
then writeText "setupHook.sh" ''
addToSearchPath ERL_LIBS "$1/lib/erlang/lib"
''
else setupHook;
inherit buildInputs;
propagatedBuildInputs = [ hexRegistrySnapshot hex elixir ] ++ beamDeps;
configurePhase = ''
runHook preConfigure
${erlang}/bin/escript ${bootstrapper}
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
export HEX_OFFLINE=1
export HEX_HOME=`pwd`
export MIX_ENV=prod
MIX_ENV=prod mix compile --debug-info --no-deps-check
runHook postBuild
'';
installPhase = ''
runHook preInstall
MIXENV=prod
if [ -d "_build/shared" ]; then
MIXENV=shared
fi
mkdir -p "$out/lib/erlang/lib/${name}-${version}"
for reldir in src ebin priv include; do
fd="_build/$MIXENV/lib/${name}/$reldir"
[ -d "$fd" ] || continue
cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$fd"
success=1
done
runHook postInstall
'';
passthru = {
packageName = name;
env = shell self;
inherit beamDeps;
};
});
in fix pkg

View File

@@ -0,0 +1,89 @@
{ stdenv, writeText, erlang, rebar3, openssl, libyaml,
pc, buildEnv }:
{ name, version
, src
, setupHook ? null
, buildInputs ? [], beamDeps ? [], buildPlugins ? []
, postPatch ? ""
, compilePorts ? false
, installPhase ? null
, meta ? {}
, ... }@attrs:
with stdenv.lib;
let
ownPlugins = buildPlugins ++ (if compilePorts then [pc] else []);
shell = drv: stdenv.mkDerivation {
name = "interactive-shell-${drv.name}";
buildInputs = [ drv ];
};
pkg = self: stdenv.mkDerivation (attrs // {
name = "${name}-${version}";
inherit version;
buildInputs = buildInputs ++ [ erlang rebar3 openssl libyaml ];
propagatedBuildInputs = unique (beamDeps ++ ownPlugins);
dontStrip = true;
# The following are used by rebar3-nix-bootstrap
inherit compilePorts;
buildPlugins = ownPlugins;
inherit src;
setupHook = if setupHook == null
then writeText "setupHook.sh" ''
addToSearchPath ERL_LIBS "$1/lib/erlang/lib/"
''
else setupHook;
postPatch = ''
rm -f rebar rebar3
'';
configurePhase = ''
runHook preConfigure
rebar3-nix-bootstrap
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
HOME=. rebar3 compile
${if compilePorts then ''
HOME=. rebar3 pc compile
'' else ''''}
runHook postBuild
'';
installPhase = if installPhase == null
then ''
runHook preInstall
mkdir -p "$out/lib/erlang/lib/${name}-${version}"
for reldir in src ebin priv include; do
fd="_build/default/lib/${name}/$reldir"
[ -d "$fd" ] || continue
cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$fd"
success=1
done
runHook postInstall
''
else installPhase;
meta = {
inherit (erlang.meta) platforms;
} // meta;
passthru = {
packageName = name;
env = shell self;
inherit beamDeps;
};
});
in
fix pkg

View File

@@ -0,0 +1,17 @@
{ stdenv, pkgs }: #? import <nixpkgs> {} }:
let
self = rec {
hexPackages = import ./hex-packages.nix { stdenv = stdenv; callPackage = self.callPackage; };
callPackage = pkgs.lib.callPackageWith (pkgs // self // hexPackages);
buildRebar3 = callPackage ./build-rebar3.nix {};
buildHex = callPackage ./build-hex.nix {};
buildErlangMk = callPackage ./build-erlang-mk.nix {};
buildMix = callPackage ./build-mix.nix {};
## Non hex packages
hex = callPackage ./hex {};
webdriver = callPackage ./webdriver {};
elli = callPackage ./elli {};
};
in self // self.hexPackages

View File

@@ -0,0 +1,34 @@
{ stdenv, fetchurl }:
{ pkg, version, sha256
, meta ? {}
}:
with stdenv.lib;
stdenv.mkDerivation ({
name = "hex-source-${pkg}-${version}";
src = fetchurl {
url = "https://s3.amazonaws.com/s3.hex.pm/tarballs/${pkg}-${version}.tar";
inherit sha256;
};
phases = [ "unpackPhase" "installPhase" ];
unpackCmd = ''
tar -xf $curSrc contents.tar.gz
mkdir contents
tar -C contents -xzf contents.tar.gz
'';
installPhase = ''
runHook preInstall
mkdir "$out"
cp -Hrt "$out" .
success=1
runHook postInstall
'';
inherit meta;
})

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
{stdenv, writeText, fetchFromGitHub }:
stdenv.mkDerivation rec {
name = "hex-registry";
rev = "329ae2b";
version = "0.0.0+build.${rev}";
src = fetchFromGitHub {
owner = "erlang-nix";
repo = "hex-pm-registry-snapshots";
inherit rev;
sha256 = "1rs3z8psfvy10mzlfvkdzbflgikcnq08r38kfi0f8p5wvi8f8hmh";
};
installPhase = ''
mkdir -p "$out/var/hex"
zcat "registry.ets.gz" > "$out/var/hex/registry.ets"
'';
setupHook = writeText "setupHook.sh" ''
export HEX_REGISTRY_SNAPSHOT="$1/var/hex/registry.ets"
'';
}

View File

@@ -0,0 +1,58 @@
{stdenv, fetchFromGitHub, writeText, elixir }:
let
shell = drv: stdenv.mkDerivation {
name = "interactive-shell-${drv.name}";
buildInputs = [ drv ];
};
pkg = self: stdenv.mkDerivation rec {
name = "hex";
version = "v0.11.3";
src = fetchFromGitHub {
owner = "hexpm";
repo = "hex";
rev = "f5e200ad95f030f0a7ab88a86545dd0dde1ee521";
sha256 = "0n4cgmnbmglarydls9pmxznbzp49pv85ncbd4f2lp1fm7qr08xfw";
};
setupHook = writeText "setupHook.sh" ''
addToSearchPath ERL_LIBS "$1/lib/erlang/lib/"
'';
dontStrip = true;
buildInputs = [ elixir ];
buildPhase = ''
runHook preBuild
export HEX_OFFLINE=1
export HEX_HOME=./
export MIX_ENV=prod
mix compile
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/lib/erlang/lib
cp -r ./_build/prod/lib/hex $out/lib/erlang/lib/
runHook postInstall
'';
meta = {
description = "Package manager for the Erlang VM https://hex.pm";
license = stdenv.lib.licenses.mit;
homepage = "https://github.com/hexpm/hex";
maintainers = with stdenv.lib.maintainers; [ ericbmerritt ];
};
passthru = {
env = shell self;
};
};
in stdenv.lib.fix pkg

View File

@@ -0,0 +1,112 @@
#!/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
, erl_libs
, root
, name
, registry_snapshot}).
-define(LOCAL_HEX_REGISTRY, "registry.ets").
main(Args) ->
{ok, RequiredData} = gather_required_data_from_the_environment(Args),
ok = bootstrap_libs(RequiredData).
%% @doc
%% This takes an app name in the standard OTP <name>-<version> format
%% and returns just the app name. Why? because rebar is doesn't
%% respect OTP conventions in some cases.
-spec fixup_app_name(file:name()) -> string().
fixup_app_name(Path) ->
BaseName = filename:basename(Path),
case string:tokens(BaseName, "-") of
[Name, _Version] -> Name;
Name -> Name
end.
-spec gather_required_data_from_the_environment([string()]) -> {ok, #data{}}.
gather_required_data_from_the_environment(_) ->
{ok, #data{ version = guard_env("version")
, erl_libs = os:getenv("ERL_LIBS", [])
, root = code:root_dir()
, name = guard_env("name")
, registry_snapshot = guard_env("HEX_REGISTRY_SNAPSHOT")}}.
-spec guard_env(string()) -> string().
guard_env(Name) ->
case os:getenv(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.
-spec bootstrap_libs(#data{}) -> ok.
bootstrap_libs(#data{erl_libs = ErlLibs}) ->
io:format("Bootstrapping dependent libraries~n"),
Target = "_build/prod/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_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),
ok = 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
%% 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)).

View File

@@ -0,0 +1,34 @@
{stdenv, fetchFromGitHub, buildRebar3 }:
let
shell = drv: stdenv.mkDerivation {
name = "interactive-shell-${drv.name}";
buildInputs = [ drv ];
};
pkg = self: buildRebar3 rec {
name = "pgsql";
version = "25+beta.2";
src = fetchFromGitHub {
owner = "semiocast";
repo = "pgsql";
rev = "14f632bc89e464d82ce3ef12a67ed8c2adb5b60c";
sha256 = "17dcahiwlw61zhy8aq9rn46lwb35fb9q3372s4wmz01czm8c348w";
};
dontStrip = true;
meta = {
description = "Erlang PostgreSQL Driver";
license = stdenv.lib.licenses.mit;
homepage = "https://github.com/semiocast/pgsql";
maintainers = with stdenv.lib.maintainers; [ ericbmerritt ];
};
passthru = {
env = shell self;
};
};
in stdenv.lib.fix pkg

View File

@@ -0,0 +1,40 @@
{stdenv, fetchFromGitHub, writeText, erlang }:
let
shell = drv: stdenv.mkDerivation {
name = "interactive-shell-${drv.name}";
buildInputs = [ drv ];
};
pkg = self: stdenv.mkDerivation rec {
name = "webdriver";
version = "0.0.0+build.18.7ceaf1f";
src = fetchFromGitHub {
owner = "Quviq";
repo = "webdrv";
rev = "7ceaf1f67d834e841ca0133b4bf899a9fa2db6bb";
sha256 = "1pq6pmlr6xb4hv2fvmlrvzd8c70kdcidlgjv4p8n9pwvkif0cb87";
};
setupHook = writeText "setupHook.sh" ''
addToSearchPath ERL_LIBS "$1/lib/erlang/lib/"
'';
buildInputs = [ erlang ];
installFlags = "PREFIX=$(out)/lib/erlang/lib";
meta = {
description = "WebDriver implementation in Erlang";
license = stdenv.lib.licenses.mit;
homepage = "https://github.com/Quviq/webdrv";
maintainers = with stdenv.lib.maintainers; [ ericbmerritt ];
};
passthru = {
env = shell self;
};
};
in stdenv.lib.fix pkg