1{
2 stdenv,
3 writeText,
4 elixir,
5 erlang,
6 hex,
7 lib,
8}:
9
10{
11 name,
12 version,
13 src,
14 buildInputs ? [ ],
15 nativeBuildInputs ? [ ],
16 erlangCompilerOptions ? [ ],
17 # Deterministic Erlang builds remove full system paths from debug information
18 # among other things to keep builds more reproducible. See their docs for more:
19 # https://www.erlang.org/doc/man/compile
20 erlangDeterministicBuilds ? true,
21 beamDeps ? [ ],
22 propagatedBuildInputs ? [ ],
23 postPatch ? "",
24 compilePorts ? false,
25 meta ? { },
26 enableDebugInfo ? false,
27 mixEnv ? "prod",
28 mixTarget ? "host",
29 removeConfig ? true,
30 # A config directory that is considered for all the dependencies of an app, typically in $src/config/
31 # This was initially added, as some of Mobilizon's dependencies need to access the config at build time.
32 appConfigPath ? null,
33 ...
34}@attrs:
35
36assert appConfigPath != null -> removeConfig;
37
38let
39 shell =
40 drv:
41 stdenv.mkDerivation {
42 name = "interactive-shell-${drv.name}";
43 buildInputs = [ drv ];
44 };
45
46 pkg =
47 self:
48 stdenv.mkDerivation (
49 attrs
50 // {
51 name = "${name}-${version}";
52 inherit version src;
53
54 MIX_ENV = mixEnv;
55 MIX_TARGET = mixTarget;
56 MIX_BUILD_PREFIX = (if mixTarget == "host" then "" else "${mixTarget}_") + "${mixEnv}";
57 MIX_DEBUG = if enableDebugInfo then 1 else 0;
58 HEX_OFFLINE = 1;
59
60 ERL_COMPILER_OPTIONS =
61 let
62 options = erlangCompilerOptions ++ lib.optionals erlangDeterministicBuilds [ "deterministic" ];
63 in
64 "[${lib.concatStringsSep "," options}]";
65
66 LANG = if stdenv.hostPlatform.isLinux then "C.UTF-8" else "C";
67 LC_CTYPE = if stdenv.hostPlatform.isLinux then "C.UTF-8" else "UTF-8";
68
69 # add to ERL_LIBS so other modules can find at runtime.
70 # http://erlang.org/doc/man/code.html#code-path
71 # Mix also searches the code path when compiling with the --no-deps-check flag
72 setupHook = attrs.setupHook or writeText "setupHook.sh" ''
73 addToSearchPath ERL_LIBS "$1/lib/erlang/lib"
74 '';
75
76 buildInputs = buildInputs ++ [ ];
77 nativeBuildInputs = nativeBuildInputs ++ [
78 elixir
79 hex
80 ];
81 propagatedBuildInputs = propagatedBuildInputs ++ beamDeps;
82
83 configurePhase =
84 attrs.configurePhase or ''
85 runHook preConfigure
86
87 ${./mix-configure-hook.sh}
88 ${lib.optionalString (removeConfig && isNull appConfigPath)
89 # By default, we don't want to include whatever config a dependency brings; per
90 # https://hexdocs.pm/elixir/main/Config.html, config is application specific.
91 ''
92 rm -rf config
93 mkdir config
94 ''
95 }
96 ${lib.optionalString (!isNull appConfigPath)
97 # Some more tightly-coupled dependencies do depend on the config of the application
98 # they're being built for.
99 ''
100 rm -rf config
101 cp -r ${appConfigPath} config
102 ''
103 }
104
105 runHook postConfigure
106 '';
107
108 buildPhase =
109 attrs.buildPhase or ''
110 runHook preBuild
111 export HEX_HOME="$TEMPDIR/hex"
112 export MIX_HOME="$TEMPDIR/mix"
113 mix compile --no-deps-check
114 runHook postBuild
115 '';
116
117 installPhase =
118 attrs.installPhase or ''
119 runHook preInstall
120
121 # This uses the install path convention established by nixpkgs maintainers
122 # for all beam packages. Changing this will break compatibility with other
123 # builder functions like buildRebar3 and buildErlangMk.
124 mkdir -p "$out/lib/erlang/lib/${name}-${version}"
125
126 # Some packages like db_connection will use _build/shared instead of
127 # honoring the $MIX_ENV variable.
128 for reldir in _build/{$MIX_BUILD_PREFIX,shared}/lib/${name}/{src,ebin,priv,include} ; do
129 if test -d $reldir ; then
130 # Some builds produce symlinks (eg: phoenix priv dircetory). They must
131 # be followed with -H flag.
132 cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$reldir"
133 fi
134 done
135
136 # Copy the source so it can be used by dependent packages. For example,
137 # phoenix applications need the source of phoenix and phoenix_html to
138 # build javascript and css assets.
139 mkdir -p $out/src
140 cp -r "$src/." "$out/src"
141
142 runHook postInstall
143 '';
144
145 # stripping does not have any effect on beam files
146 # it is however needed for dependencies with NIFs like bcrypt for example
147 dontStrip = false;
148
149 passthru = {
150 packageName = name;
151 env = shell self;
152 inherit beamDeps;
153 };
154 }
155 );
156in
157lib.fix pkg