Skip to content

Commit 26203af

Browse files
committed
Proper beam compilation and .app file generation
1 parent 08b2a54 commit 26203af

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

309309
defp do_gleam(%Mix.Dep{opts: opts} = dep, config) do
310310
Mix.Gleam.require!()
311+
Mix.Project.ensure_structure()
311312

312313
lib = Path.join(Mix.Project.build_path(), "lib")
313314
out = opts[:build]
314315
package = opts[:dest]
315316

316317
command =
317318
{"gleam",
318-
["compile-package", "--target", "erlang", "--package", package, "--out", out, "--lib", lib]}
319+
[
320+
"compile-package",
321+
"--no-beam",
322+
"--target",
323+
"erlang",
324+
"--package",
325+
package,
326+
"--out",
327+
out,
328+
"--lib",
329+
lib
330+
]}
319331

320332
shell_cmd!(dep, config, command)
321333

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

326-
if create_app_file do
327-
generate_gleam_app_file(opts)
328-
end
329-
330-
Code.prepend_path(ebin, cache: true)
337+
Code.prepend_path(Path.join(out, "ebin"), cache: true)
331338
end
332339

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

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