1{
2 pkgs,
3 lib,
4 stdenv,
5 fetchFromGitHub,
6 erlang,
7 makeWrapper,
8 coreutils,
9 curl,
10 bash,
11 debugInfo ? false,
12}@inputs:
13
14{
15 baseName ? "elixir",
16 version,
17 erlang ? inputs.erlang,
18 minimumOTPVersion,
19 maximumOTPVersion ? null,
20 sha256 ? null,
21 rev ? "v${version}",
22 src ? fetchFromGitHub {
23 inherit rev sha256;
24 owner = "elixir-lang";
25 repo = "elixir";
26 },
27 escriptPath ? "lib/elixir/generate_app.escript",
28}@args:
29
30let
31 inherit (lib)
32 assertMsg
33 concatStringsSep
34 getVersion
35 optional
36 optionalString
37 toInt
38 versions
39 versionAtLeast
40 versionOlder
41 ;
42
43 compatibilityMsg = ''
44 Unsupported elixir and erlang OTP combination.
45
46 elixir ${version}
47 erlang OTP ${getVersion erlang} is not >= ${minimumOTPVersion} ${
48 optionalString (maximumOTPVersion != null) "and <= ${maximumOTPVersion}"
49 }
50
51 See https://hexdocs.pm/elixir/${version}/compatibility-and-deprecations.html
52 '';
53
54 maxShiftMajor = builtins.toString ((toInt (versions.major maximumOTPVersion)) + 1);
55 maxAssert =
56 if (maximumOTPVersion == null) then
57 true
58 else
59 versionOlder (versions.major (getVersion erlang)) maxShiftMajor;
60
61 elixirShebang =
62 if stdenv.hostPlatform.isDarwin then
63 # Darwin disallows shebang scripts from using other scripts as their
64 # command. Use env as an intermediary instead of calling elixir directly
65 # (another shebang script).
66 # See https://github.com/NixOS/nixpkgs/pull/9671
67 "${coreutils}/bin/env $out/bin/elixir"
68 else
69 "$out/bin/elixir";
70in
71assert assertMsg (versionAtLeast (getVersion erlang) minimumOTPVersion) compatibilityMsg;
72assert assertMsg maxAssert compatibilityMsg;
73
74stdenv.mkDerivation ({
75 pname = "${baseName}";
76
77 inherit src version debugInfo;
78
79 nativeBuildInputs = [ makeWrapper ];
80 buildInputs = [ erlang ];
81
82 LANG = "C.UTF-8";
83 LC_TYPE = "C.UTF-8";
84
85 ERLC_OPTS =
86 let
87 erlc_opts = [ "deterministic" ] ++ optional debugInfo "debug_info";
88 in
89 "[${concatStringsSep "," erlc_opts}]";
90
91 preBuild = ''
92 patchShebangs ${escriptPath} || true
93
94 substituteInPlace Makefile \
95 --replace "/usr/local" $out
96 '';
97
98 postFixup = ''
99 # Elixir binaries are shell scripts which run erl. Add some stuff
100 # to PATH so the scripts can run without problems.
101
102 for f in $out/bin/*; do
103 b=$(basename $f)
104 if [ "$b" = mix ]; then continue; fi
105 wrapProgram $f \
106 --prefix PATH ":" "${
107 lib.makeBinPath [
108 erlang
109 coreutils
110 curl
111 bash
112 ]
113 }"
114 done
115
116 substituteInPlace $out/bin/mix \
117 --replace "/usr/bin/env elixir" "${elixirShebang}"
118 '';
119
120 pos = builtins.unsafeGetAttrPos "sha256" args;
121 meta = with lib; {
122 homepage = "https://elixir-lang.org/";
123 description = "Functional, meta-programming aware language built on top of the Erlang VM";
124
125 longDescription = ''
126 Elixir is a functional, meta-programming aware language built on
127 top of the Erlang VM. It is a dynamic language with flexible
128 syntax and macro support that leverages Erlang's abilities to
129 build concurrent, distributed and fault-tolerant applications
130 with hot code upgrades.
131 '';
132
133 license = licenses.asl20;
134 platforms = platforms.unix;
135 teams = [ teams.beam ];
136 };
137})