Skip to content

Commit 9e218ee

Browse files
committed
Proper beam compilation and .app file generation
1 parent 700def0 commit 9e218ee

File tree

5 files changed

+63
-57
lines changed

5 files changed

+63
-57
lines changed

lib/mix/lib/mix/dep/loader.ex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ defmodule Mix.Dep.Loader do
107107
make_dep(dep)
108108

109109
gleam?(dep) ->
110-
gleam_dep(dep, children, locked?)
110+
gleam_dep(dep, children, manager, locked?)
111111

112112
true ->
113113
{dep, []}
@@ -367,18 +367,18 @@ defmodule Mix.Dep.Loader do
367367
{dep, []}
368368
end
369369

370-
defp gleam_dep(%Mix.Dep{opts: opts} = dep, _children = nil, locked?) do
370+
defp gleam_dep(%Mix.Dep{opts: opts} = dep, _children = nil, manager, locked?) do
371371
Mix.Gleam.require!()
372372

373373
config = File.cd!(opts[:dest], fn -> Mix.Gleam.load_config(".") end)
374374
from = Path.join(opts[:dest], "gleam.toml")
375-
deps = Enum.map(config[:deps], &to_dep(&1, from, _manager = nil, locked?))
375+
deps = Enum.map(config[:deps], &to_dep(&1, from, manager, locked?))
376376

377377
{dep, deps}
378378
end
379379

380-
defp gleam_dep(%Mix.Dep{opts: opts} = dep, children, locked?) do
381-
{dep, Enum.map(children, &to_dep(&1, opts[:dest], _manager = nil, locked?))}
380+
defp gleam_dep(%Mix.Dep{opts: opts} = dep, children, manager, locked?) do
381+
{dep, Enum.map(children, &to_dep(&1, opts[:dest], manager, locked?))}
382382
end
383383

384384
defp mix_children(config, locked?, opts) do

lib/mix/lib/mix/tasks/deps.compile.ex

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -298,65 +298,59 @@ defmodule Mix.Tasks.Deps.Compile do
298298

299299
defp do_gleam(%Mix.Dep{opts: opts} = dep, config) do
300300
Mix.Gleam.require!()
301+
Mix.Project.ensure_structure()
301302

302303
lib = Path.join(Mix.Project.build_path(), "lib")
303304
out = opts[:build]
304305
package = opts[:dest]
305306

306307
command =
307308
{"gleam",
308-
["compile-package", "--target", "erlang", "--package", package, "--out", out, "--lib", lib]}
309+
[
310+
"compile-package",
311+
"--no-beam",
312+
"--target",
313+
"erlang",
314+
"--package",
315+
package,
316+
"--out",
317+
out,
318+
"--lib",
319+
lib
320+
]}
309321

310322
shell_cmd!(dep, config, command)
311323

312-
ebin = Path.join(out, "ebin")
313-
app_file_path = Keyword.get(opts, :app, Path.join(ebin, "#{dep.app}.app"))
314-
create_app_file = app_file_path && !File.exists?(app_file_path)
324+
File.cd!(package, fn -> Mix.Gleam.load_config(".") end)
325+
|> push_gleam_project(dep, Keyword.fetch!(config, :deps_path))
315326

316-
if create_app_file do
317-
generate_gleam_app_file(opts)
318-
end
319-
320-
Code.prepend_path(ebin, cache: true)
327+
Code.prepend_path(Path.join(out, "ebin"), cache: true)
321328
end
322329

323-
defp gleam_extra_applications(config) do
324-
config
325-
|> Map.get(:extra_applications, [])
326-
|> Enum.map(&String.to_atom/1)
327-
end
328-
329-
defp gleam_mod(config) do
330-
case config[:mod] do
331-
nil -> []
332-
mod -> {String.to_atom(mod), []}
333-
end
334-
end
335-
336-
defp generate_gleam_app_file(opts) do
337-
toml = File.cd!(opts[:dest], fn -> Mix.Gleam.load_config(".") end)
338-
339-
module =
340-
quote do
341-
def project do
342-
[
343-
app: unquote(toml.name) |> String.to_atom(),
344-
version: "#{unquote(toml.version)}"
345-
]
346-
end
347-
348-
def application do
349-
[
350-
mod: unquote(gleam_mod(toml)),
351-
extra_applications: unquote(gleam_extra_applications(toml))
352-
]
353-
end
354-
end
355-
356-
module_name = String.to_atom("Gleam.#{toml.name}")
357-
Module.create(module_name, module, Macro.Env.location(__ENV__))
358-
Mix.Project.push(module_name)
359-
Mix.Tasks.Compile.App.run([])
330+
defp push_gleam_project(toml, dep, deps_path) do
331+
build = Path.expand(dep.opts[:build])
332+
src = Path.join(build, "_gleam_artefacts")
333+
File.mkdir(Path.join(build, "ebin"))
334+
335+
config =
336+
[
337+
app: dep.app,
338+
version: toml.version,
339+
deps: toml.deps,
340+
build_per_environment: true,
341+
lockfile: "mix.lock",
342+
# Remove per-environment segment from the path since ProjectStack.push below will append it
343+
build_path: Mix.Project.build_path() |> Path.split() |> Enum.drop(-1) |> Path.join(),
344+
deps_path: deps_path,
345+
erlc_paths: [src],
346+
erlc_include_path: Path.join(build, "include")
347+
]
348+
349+
Mix.ProjectStack.pop()
350+
Mix.ProjectStack.push(dep.app, config, "nofile")
351+
# Somehow running just `compile` task won't work (doesn't compile the .erl files)
352+
Mix.Task.run("compile.erlang", ["--force"])
353+
Mix.Task.run("compile.app")
360354
end
361355

362356
defp make_command(dep) do
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-module(collocated_erlang).
2+
-export([hello/0]).
3+
4+
hello() ->
5+
"Hello from Collocated Erlang!".
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
pub fn main() {
22
True
33
}
4+
5+
@external(erlang, "collocated_erlang", "hello")
6+
pub fn erl() -> String

lib/mix/test/mix/gleam_test.exs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ defmodule Mix.GleamTest do
6868
{:my_other_project, path: "../my_other_project"},
6969
{:gleeunit, ">= 1.0.0 and < 2.0.0", only: :dev}
7070
],
71-
mod: "some@application"
71+
application: [
72+
mod: {:some@application, []}
73+
]
7274
}
7375
end
7476
end
@@ -81,10 +83,10 @@ defmodule Mix.GleamTest do
8183
Mix.Tasks.Deps.Get.run([])
8284
assert_received {:mix_shell, :info, ["* Getting gleam_stdlib " <> _]}
8385
assert_received {:mix_shell, :info, ["* Getting gleam_otp " <> _]}
84-
assert_received {:mix_shell, :info, ["* Getting gleeunit " <> _]}
8586

8687
Mix.Tasks.Deps.Compile.run([])
8788
assert :gleam_dep.main()
89+
assert :gleam_dep.erl() == ~c'Hello from Collocated Erlang!'
8890
assert :gleam@int.to_string(1) == "1"
8991

9092
{:ok, content} = :file.consult("_build/dev/lib/gleam_dep/ebin/gleam_dep.app")
@@ -94,13 +96,15 @@ defmodule Mix.GleamTest do
9496
:application,
9597
:gleam_dep,
9698
[
97-
{:modules, [:gleam_dep]},
99+
{:modules, [:collocated_erlang, :gleam_dep]},
98100
{:optional_applications, []},
99-
{:applications, [:kernel, :stdlib, :elixir, :ssl]},
101+
{:applications,
102+
[:kernel, :stdlib, :elixir, :gleam_otp, :gleam_stdlib, :gleeunit]},
100103
{:description, ~c"gleam_dep"},
101104
{:registered, []},
102-
{:vsn, ~c"1.0.0"},
103-
{:mod, {:gleam_dep@somemodule, []}}
105+
{:vsn, ~c"1.0.0"}
106+
# Need to add support for :application option in Compile.App
107+
# {:mod, {:gleam_dep@somemodule, []}}
104108
]
105109
}
106110
]

0 commit comments

Comments
 (0)