Skip to content

Commit 6ed5fe7

Browse files
committed
Proper beam compilation and .app file generation
1 parent 3ba141b commit 6ed5fe7

File tree

5 files changed

+63
-57
lines changed

5 files changed

+63
-57
lines changed

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

+5-5
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

+40-46
Original file line numberDiff line numberDiff line change
@@ -326,65 +326,59 @@ defmodule Mix.Tasks.Deps.Compile do
326326

327327
defp do_gleam(%Mix.Dep{opts: opts} = dep, config) do
328328
Mix.Gleam.require!()
329+
Mix.Project.ensure_structure()
329330

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

334335
command =
335336
{"gleam",
336-
["compile-package", "--target", "erlang", "--package", package, "--out", out, "--lib", lib]}
337+
[
338+
"compile-package",
339+
"--no-beam",
340+
"--target",
341+
"erlang",
342+
"--package",
343+
package,
344+
"--out",
345+
out,
346+
"--lib",
347+
lib
348+
]}
337349

338350
shell_cmd!(dep, config, command)
339351

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

344-
if create_app_file do
345-
generate_gleam_app_file(opts)
346-
end
347-
348-
Code.prepend_path(ebin, cache: true)
355+
Code.prepend_path(Path.join(out, "ebin"), cache: true)
349356
end
350357

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

390384
defp make_command(dep) do
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!".
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

+10-6
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)