Skip to content

Commit 98e1b4c

Browse files
author
José Valim
committed
Ensure we tag the destination when compiling through mix
Closes #2533
1 parent ae19491 commit 98e1b4c

File tree

3 files changed

+44
-36
lines changed

3 files changed

+44
-36
lines changed

lib/elixir/lib/kernel/parallel_compiler.ex

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,44 @@ defmodule Kernel.ParallelCompiler do
1515
is set to `true` and there is a warning, this function will fail
1616
with an exception.
1717
18-
This function receives a set of callbacks as options:
18+
This function accepts the following options:
1919
2020
* `:each_file` - for each file compiled, invokes the callback passing the
2121
file
2222
2323
* `:each_module` - for each module compiled, invokes the callback passing
2424
the file, module and the module bytecode
2525
26-
The compiler doesn't care about the return values of the callbacks.
26+
* `:dest` - the destination directory for the beam files. When using `files/2`,
27+
this information is only used to properly annotate the beam files before
28+
they are loaded into memory. If you want a file to actually be writen to
29+
`dest`, use `files_to_path/3` instead.
30+
2731
Returns the modules generated by each compiled file.
2832
"""
29-
def files(files, callbacks \\ [])
33+
def files(files, options \\ [])
3034

31-
def files(files, callbacks) when is_list(callbacks) do
32-
spawn_compilers(files, nil, callbacks)
35+
def files(files, options) when is_list(options) do
36+
spawn_compilers(files, nil, options)
3337
end
3438

3539
@doc """
3640
Compiles the given files to the given path.
3741
Read `files/2` for more information.
3842
"""
39-
def files_to_path(files, path, callbacks \\ [])
43+
def files_to_path(files, path, options \\ [])
4044

41-
def files_to_path(files, path, callbacks) when is_binary(path) and is_list(callbacks) do
42-
spawn_compilers(files, path, callbacks)
45+
def files_to_path(files, path, options) when is_binary(path) and is_list(options) do
46+
spawn_compilers(files, path, options)
4347
end
4448

45-
defp spawn_compilers(files, path, callbacks) do
49+
defp spawn_compilers(files, path, options) do
4650
true = Code.ensure_loaded?(Kernel.ErrorHandler)
4751
compiler_pid = self()
4852
:elixir_code_server.cast({:reset_warnings, compiler_pid})
4953
schedulers = max(:erlang.system_info(:schedulers_online), 2)
5054

51-
result = spawn_compilers(files, files, path, callbacks, [], [], schedulers, [])
55+
result = spawn_compilers(files, files, path, options, [], [], schedulers, [])
5256

5357
# In case --warning-as-errors is enabled and there was a warning,
5458
# compilation status will be set to error and we fail with CompileError
@@ -59,21 +63,21 @@ defmodule Kernel.ParallelCompiler do
5963
end
6064

6165
# We already have 4 currently running, don't spawn new ones
62-
defp spawn_compilers(entries, original, output, callbacks, waiting, queued, schedulers, result) when
66+
defp spawn_compilers(entries, original, output, options, waiting, queued, schedulers, result) when
6367
length(queued) - length(waiting) >= schedulers do
64-
wait_for_messages(entries, original, output, callbacks, waiting, queued, schedulers, result)
68+
wait_for_messages(entries, original, output, options, waiting, queued, schedulers, result)
6569
end
6670

6771
# Release waiting processes
68-
defp spawn_compilers([h|t], original, output, callbacks, waiting, queued, schedulers, result) when is_pid(h) do
72+
defp spawn_compilers([h|t], original, output, options, waiting, queued, schedulers, result) when is_pid(h) do
6973
{_kind, ^h, ref, _module} = List.keyfind(waiting, h, 1)
7074
send h, {ref, :ready}
7175
waiting = List.keydelete(waiting, h, 1)
72-
spawn_compilers(t, original, output, callbacks, waiting, queued, schedulers, result)
76+
spawn_compilers(t, original, output, options, waiting, queued, schedulers, result)
7377
end
7478

7579
# Spawn a compiler for each file in the list until we reach the limit
76-
defp spawn_compilers([h|t], original, output, callbacks, waiting, queued, schedulers, result) do
80+
defp spawn_compilers([h|t], original, output, options, waiting, queued, schedulers, result) do
7781
parent = self()
7882

7983
{pid, ref} =
@@ -90,7 +94,7 @@ defmodule Kernel.ParallelCompiler do
9094
_ = if output do
9195
:elixir_compiler.file_to_path(h, output)
9296
else
93-
:elixir_compiler.file(h)
97+
:elixir_compiler.file(h, Keyword.get(options, :dest))
9498
end
9599
{:compiled, h}
96100
catch
@@ -99,43 +103,43 @@ defmodule Kernel.ParallelCompiler do
99103
end)
100104
end
101105

102-
spawn_compilers(t, original, output, callbacks, waiting,
106+
spawn_compilers(t, original, output, options, waiting,
103107
[{pid, ref, h}|queued], schedulers, result)
104108
end
105109

106110
# No more files, nothing waiting, queue is empty, we are done
107-
defp spawn_compilers([], _original, _output, _callbacks, [], [], _schedulers, result) do
111+
defp spawn_compilers([], _original, _output, _options, [], [], _schedulers, result) do
108112
for {:module, mod} <- result, do: mod
109113
end
110114

111115
# Queued x, waiting for x: POSSIBLE ERROR! Release processes so we get the failures
112-
defp spawn_compilers([], original, output, callbacks, waiting, queued, schedulers, result) when length(waiting) == length(queued) do
116+
defp spawn_compilers([], original, output, options, waiting, queued, schedulers, result) when length(waiting) == length(queued) do
113117
Enum.each queued, fn {child, _, _} ->
114118
{_kind, ^child, ref, _module} = List.keyfind(waiting, child, 1)
115119
send child, {ref, :release}
116120
end
117-
wait_for_messages([], original, output, callbacks, waiting, queued, schedulers, result)
121+
wait_for_messages([], original, output, options, waiting, queued, schedulers, result)
118122
end
119123

120124
# No more files, but queue and waiting are not full or do not match
121-
defp spawn_compilers([], original, output, callbacks, waiting, queued, schedulers, result) do
122-
wait_for_messages([], original, output, callbacks, waiting, queued, schedulers, result)
125+
defp spawn_compilers([], original, output, options, waiting, queued, schedulers, result) do
126+
wait_for_messages([], original, output, options, waiting, queued, schedulers, result)
123127
end
124128

125129
# Wait for messages from child processes
126-
defp wait_for_messages(entries, original, output, callbacks, waiting, queued, schedulers, result) do
130+
defp wait_for_messages(entries, original, output, options, waiting, queued, schedulers, result) do
127131
receive do
128132
{:struct_available, module} ->
129133
available = for {:struct, pid, _, waiting_module} <- waiting,
130134
module == waiting_module,
131135
not pid in entries,
132136
do: pid
133137

134-
spawn_compilers(available ++ entries, original, output, callbacks,
138+
spawn_compilers(available ++ entries, original, output, options,
135139
waiting, queued, schedulers, [{:struct, module}|result])
136140

137141
{:module_available, child, ref, file, module, binary} ->
138-
if callback = Keyword.get(callbacks, :each_module) do
142+
if callback = Keyword.get(options, :each_module) do
139143
callback.(file, module, binary)
140144
end
141145

@@ -147,7 +151,7 @@ defmodule Kernel.ParallelCompiler do
147151
not pid in entries,
148152
do: pid
149153

150-
spawn_compilers(available ++ entries, original, output, callbacks,
154+
spawn_compilers(available ++ entries, original, output, options,
151155
waiting, queued, schedulers, [{:module, module}|result])
152156

153157
{:waiting, kind, child, ref, on} ->
@@ -160,10 +164,10 @@ defmodule Kernel.ParallelCompiler do
160164
waiting = [{kind, child, ref, on}|waiting]
161165
end
162166

163-
spawn_compilers(entries, original, output, callbacks, waiting, queued, schedulers, result)
167+
spawn_compilers(entries, original, output, options, waiting, queued, schedulers, result)
164168

165169
{:DOWN, _down_ref, :process, down_pid, {:compiled, file}} ->
166-
if callback = Keyword.get(callbacks, :each_file) do
170+
if callback = Keyword.get(options, :each_file) do
167171
callback.(file)
168172
end
169173

@@ -172,11 +176,11 @@ defmodule Kernel.ParallelCompiler do
172176
new_entries = List.delete(entries, down_pid)
173177
new_queued = List.keydelete(queued, down_pid, 0)
174178
new_waiting = List.keydelete(waiting, down_pid, 1)
175-
spawn_compilers(new_entries, original, output, callbacks, new_waiting, new_queued, schedulers, result)
179+
spawn_compilers(new_entries, original, output, options, new_waiting, new_queued, schedulers, result)
176180

177181
{:DOWN, down_ref, :process, _down_pid, reason} ->
178182
handle_failure(down_ref, reason, entries, waiting, queued)
179-
wait_for_messages(entries, original, output, callbacks, waiting, queued, schedulers, result)
183+
wait_for_messages(entries, original, output, options, waiting, queued, schedulers, result)
180184
end
181185
end
182186

lib/elixir/src/elixir_compiler.erl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-module(elixir_compiler).
2-
-export([get_opt/1, string/2, quoted/2, file/1, file_to_path/2]).
2+
-export([get_opt/1, string/2, quoted/2, file/1, file/2, file_to_path/2]).
33
-export([core/0, module/4, eval_forms/3]).
44
-include("elixir.hrl").
55

@@ -42,12 +42,15 @@ file(Relative) when is_binary(Relative) ->
4242
file(Relative, Dest) ->
4343
File = filename:absname(Relative),
4444
{ok, Bin} = file:read_file(File),
45-
string(elixir_utils:characters_to_list(Bin), File, Dest).
45+
string(elixir_utils:characters_to_list(Bin), File, case Dest of
46+
nil -> Dest;
47+
_ -> filename:absname(Dest)
48+
end).
4649

47-
file_to_path(File, Path) when is_binary(File), is_binary(Path) ->
48-
Dest = filename:absname(Path),
50+
file_to_path(File, Dest) when is_binary(File), is_binary(Dest) ->
4951
Comp = file(File, Dest),
50-
_ = [binary_to_path(X, Dest) || X <- Comp],
52+
Abs = filename:absname(Dest),
53+
_ = [binary_to_path(X, Abs) || X <- Comp],
5154
Comp.
5255

5356
%% Evaluation

lib/mix/lib/mix/compilers/elixir.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ defmodule Mix.Compilers.Elixir do
9696
try do
9797
_ = Kernel.ParallelCompiler.files :lists.usort(stale),
9898
each_module: &each_module(pid, dest, cwd, &1, &2, &3),
99-
each_file: &each_file(&1)
99+
each_file: &each_file(&1),
100+
dest: dest
100101
Agent.cast pid, fn entries ->
101102
write_manifest(manifest, entries)
102103
entries

0 commit comments

Comments
 (0)