Skip to content

Commit 357fcff

Browse files
committed
Proper beam compilation and .app file generation
1 parent 160b669 commit 357fcff

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
@@ -324,65 +324,59 @@ defmodule Mix.Tasks.Deps.Compile do
324324

325325
defp do_gleam(%Mix.Dep{opts: opts} = dep, config) do
326326
Mix.Gleam.require!()
327+
Mix.Project.ensure_structure()
327328

328329
lib = Path.join(Mix.Project.build_path(), "lib")
329330
out = opts[:build]
330331
package = opts[:dest]
331332

332333
command =
333334
{"gleam",
334-
["compile-package", "--target", "erlang", "--package", package, "--out", out, "--lib", lib]}
335+
[
336+
"compile-package",
337+
"--no-beam",
338+
"--target",
339+
"erlang",
340+
"--package",
341+
package,
342+
"--out",
343+
out,
344+
"--lib",
345+
lib
346+
]}
335347

336348
shell_cmd!(dep, config, command)
337349

338-
ebin = Path.join(out, "ebin")
339-
app_file_path = Keyword.get(opts, :app, Path.join(ebin, "#{dep.app}.app"))
340-
create_app_file = app_file_path && !File.exists?(app_file_path)
350+
File.cd!(package, fn -> Mix.Gleam.load_config(".") end)
351+
|> push_gleam_project(dep, Keyword.fetch!(config, :deps_path))
341352

342-
if create_app_file do
343-
generate_gleam_app_file(opts)
344-
end
345-
346-
Code.prepend_path(ebin, cache: true)
353+
Code.prepend_path(Path.join(out, "ebin"), cache: true)
347354
end
348355

349-
defp gleam_extra_applications(config) do
350-
config
351-
|> Map.get(:extra_applications, [])
352-
|> Enum.map(&String.to_atom/1)
353-
end
354-
355-
defp gleam_mod(config) do
356-
case config[:mod] do
357-
nil -> []
358-
mod -> {String.to_atom(mod), []}
359-
end
360-
end
361-
362-
defp generate_gleam_app_file(opts) do
363-
toml = File.cd!(opts[:dest], fn -> Mix.Gleam.load_config(".") end)
364-
365-
module =
366-
quote do
367-
def project do
368-
[
369-
app: unquote(toml.name) |> String.to_atom(),
370-
version: "#{unquote(toml.version)}"
371-
]
372-
end
373-
374-
def application do
375-
[
376-
mod: unquote(gleam_mod(toml)),
377-
extra_applications: unquote(gleam_extra_applications(toml))
378-
]
379-
end
380-
end
381-
382-
module_name = String.to_atom("Gleam.#{toml.name}")
383-
Module.create(module_name, module, Macro.Env.location(__ENV__))
384-
Mix.Project.push(module_name)
385-
Mix.Tasks.Compile.App.run([])
356+
defp push_gleam_project(toml, dep, deps_path) do
357+
build = Path.expand(dep.opts[:build])
358+
src = Path.join(build, "_gleam_artefacts")
359+
File.mkdir(Path.join(build, "ebin"))
360+
361+
config =
362+
[
363+
app: dep.app,
364+
version: toml.version,
365+
deps: toml.deps,
366+
build_per_environment: true,
367+
lockfile: "mix.lock",
368+
# Remove per-environment segment from the path since ProjectStack.push below will append it
369+
build_path: Mix.Project.build_path() |> Path.split() |> Enum.drop(-1) |> Path.join(),
370+
deps_path: deps_path,
371+
erlc_paths: [src],
372+
erlc_include_path: Path.join(build, "include")
373+
]
374+
375+
Mix.ProjectStack.pop()
376+
Mix.ProjectStack.push(dep.app, config, "nofile")
377+
# Somehow running just `compile` task won't work (doesn't compile the .erl files)
378+
Mix.Task.run("compile.erlang", ["--force"])
379+
Mix.Task.run("compile.app")
386380
end
387381

388382
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)