Skip to content

Commit 83db533

Browse files
author
José Valim
committed
Merge pull request #1872 from elixir-lang/jv-_build
Compile projects to _build
2 parents f6a2046 + 49fe9b0 commit 83db533

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1294
-807
lines changed

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ define APP_TEMPLATE
2020
$(1): lib/$(1)/ebin/Elixir.$(2).beam lib/$(1)/ebin/$(1).app
2121

2222
lib/$(1)/ebin/$(1).app: lib/$(1)/mix.exs
23-
$(Q) cd lib/$(1) && ../../bin/elixir -e "Mix.Server.start_link(:dev)" -r mix.exs -e "Mix.Task.run('compile.app')"
23+
$(Q) cd lib/$(1) && ../../bin/elixir -e "Mix.Sup.start_link()" -r mix.exs -e "Mix.Task.run('compile.app')"
24+
$(Q) cp lib/$(1)/_build/shared/lib/$(1)/ebin/$(1).app lib/$(1)/ebin/$(1).app
25+
$(Q) rm -rf lib/$(1)/_build
2426

2527
lib/$(1)/ebin/Elixir.$(2).beam: $(wildcard lib/$(1)/lib/*.ex) $(wildcard lib/$(1)/lib/*/*.ex) $(wildcard lib/$(1)/lib/*/*/*.ex)
2628
@ echo "==> $(1) (compile)"

lib/mix/lib/mix.ex

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,30 @@ defmodule Mix do
2323
# Application behaviour callback
2424
@doc false
2525
def start(_, []) do
26-
resp = Mix.Sup.start_link get_env
27-
Mix.SCM.register_builtin
28-
resp
26+
res = Mix.Sup.start_link
27+
if env = System.get_env("MIX_ENV") do
28+
env(binary_to_atom env)
29+
end
30+
res
2931
end
3032

3133
@doc """
3234
Returns the mix environment.
3335
"""
3436
def env do
35-
Mix.Server.call(:env)
37+
# env is not available on bootstraping
38+
case :application.get_env(:mix, :env) do
39+
{ :ok, env } -> env
40+
:undefined -> :dev
41+
end
3642
end
3743

3844
@doc """
3945
Changes the current mix env. Project configuration loaded
4046
per environment will not be reloaded.
4147
"""
4248
def env(env) when is_atom(env) do
43-
Mix.Server.cast({ :env, env })
44-
end
45-
46-
defp get_env do
47-
if env = System.get_env("MIX_ENV") do
48-
binary_to_atom env
49-
else
50-
:dev
51-
end
49+
:application.set_env(:mix, :env, env)
5250
end
5351

5452
@doc """
@@ -69,14 +67,17 @@ defmodule Mix do
6967
messages to the current process.
7068
"""
7169
def shell do
72-
Mix.Server.call(:shell)
70+
case :application.get_env(:mix, :shell) do
71+
{ :ok, shell } -> shell
72+
:undefined -> Mix.Shell.IO
73+
end
7374
end
7475

7576
@doc """
7677
Sets the current shell.
7778
"""
7879
def shell(shell) do
79-
Mix.Server.cast({ :shell, shell })
80+
:application.set_env(:mix, :shell, shell)
8081
end
8182

8283
@doc """

lib/mix/lib/mix/cli.ex

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,7 @@ defmodule Mix.CLI do
4949

5050
defp run_task(name, args) do
5151
try do
52-
# We need to skip loading the paths for the project and
53-
# its dependencies because the dependencies may be setting
54-
# up or getting updated and we don't want to load their
55-
# config until the process is done.
56-
if not deps_task?(name) && Mix.Project.get do
52+
if Mix.Project.get do
5753
Mix.Task.run "loadpaths", ["--no-deps-check", "--no-elixir-version-check"]
5854
Mix.Task.reenable "loadpaths"
5955
Mix.Task.reenable "deps.loadpaths"
@@ -78,7 +74,7 @@ defmodule Mix.CLI do
7874
defp change_env(task) do
7975
if nil?(System.get_env("MIX_ENV")) && (env = Mix.project[:preferred_cli_env][task]) do
8076
Mix.env(env)
81-
{ project, file } = Mix.Project.pop
77+
{ project, _config, file } = Mix.Project.pop
8278
Mix.Project.push project, file
8379
end
8480
end
@@ -91,10 +87,6 @@ defmodule Mix.CLI do
9187
IO.puts "Elixir #{System.version}"
9288
end
9389

94-
defp deps_task?("deps.update"), do: true
95-
defp deps_task?("deps.get"), do: true
96-
defp deps_task?(_), do: false
97-
9890
# Check for --help or --version in the args
9991
defp check_for_shortcuts([first_arg|_]) when first_arg in
10092
["--help", "-h", "-help"], do: :help

lib/mix/lib/mix/deps.ex

Lines changed: 74 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ defmodule Mix.Deps do
3535
3636
Inside Mix, those dependencies are converted to a `Mix.Dep` record.
3737
This module provides conveniences to work with those dependencies
38-
and the dependencies are usually in two specific states: fetched and
39-
unfetched.
38+
and the dependencies are usually in two specific states: loaded and
39+
unloaded.
4040
41-
When a dependency is unfetched, it means Mix only parsed its specification
42-
and made no attempt to actually fetch the dependency or validate its
43-
status. When the dependency is fetched, it means Mix attempted to fetch
44-
and validate it, the status is set in the status field.
41+
When a dependency is unloaded, it means Mix only parsed its specification
42+
and made no attempt to actually load the dependency or validate its
43+
status. When the dependency is loaded, it means Mix attempted to fetch,
44+
load and validate it, the status is set in the status field.
4545
4646
## Mix options
4747
@@ -80,7 +80,7 @@ defmodule Mix.Deps do
8080
Returns all children dependencies for the current project,
8181
as well as the defined apps in case of umbrella projects.
8282
The children dependencies returned by this function were
83-
not fetched yet.
83+
not loaded yet.
8484

8585
## Exceptions
8686

@@ -90,28 +90,28 @@ defmodule Mix.Deps do
9090
defdelegate children(), to: Mix.Deps.Retriever
9191
9292
@doc """
93-
Returns fetched dependencies recursively as a `Mix.Dep` record.
93+
Returns loaded dependencies recursively as a `Mix.Dep` record.
9494

9595
## Exceptions
9696

9797
This function raises an exception if any of the dependencies
9898
provided in the project are in the wrong format.
9999
"""
100-
def fetched do
100+
def loaded do
101101
{ deps, _ } = Mix.Deps.Converger.all(nil, fn(dep, acc) -> { dep, acc } end)
102102
Mix.Deps.Converger.topsort(deps)
103103
end
104104
105105
@doc """
106-
Receives a list of dependency names and returns fetched dependency
106+
Receives a list of dependency names and returns loaded dependency
107107
records. Logs a message if the dependency could not be found.
108108

109109
## Exceptions
110110

111111
This function raises an exception if any of the dependencies
112112
provided in the project are in the wrong format.
113113
"""
114-
def fetched_by_name(given, all_deps // fetched) do
114+
def loaded_by_name(given, all_deps // loaded) do
115115
# Ensure all apps are atoms
116116
apps = to_app_names(given)
117117
@@ -130,7 +130,7 @@ defmodule Mix.Deps do
130130
end
131131

132132
@doc """
133-
Maps and reduces over all unfetched dependencies, one by one.
133+
Maps and reduces over all unloaded dependencies, one by one.
134134
135135
This is useful in case you want to retrieve the dependency
136136
tree for a project but process and change them along the way.
@@ -145,7 +145,7 @@ defmodule Mix.Deps do
145145
This function raises an exception if any of the dependencies
146146
provided in the project are in the wrong format.
147147
"""
148-
def unfetched(acc, callback) do
148+
def unloaded(acc, callback) do
149149
{ deps, acc } = Mix.Deps.Converger.all(acc, callback)
150150
{ Mix.Deps.Converger.topsort(deps), acc }
151151
end
@@ -159,10 +159,10 @@ defmodule Mix.Deps do
159159
This function raises an exception if any of the dependencies
160160
provided in the project are in the wrong format.
161161
"""
162-
def unfetched_by_name(given, acc, callback) do
162+
def unloaded_by_name(given, acc, callback) do
163163
names = to_app_names(given)
164164

165-
unfetched(acc, fn(dep, acc) ->
165+
unloaded(acc, fn(dep, acc) ->
166166
if dep.app in names do
167167
callback.(dep, acc)
168168
else
@@ -176,8 +176,7 @@ defmodule Mix.Deps do
176176
changing the current working directory and loading the given
177177
project onto the project stack.
178178
179-
This function only works for mix dependencies.
180-
It is expected a fetched dependency as argument.
179+
It is expected a loaded dependency as argument.
181180
"""
182181
def in_dependency(dep, post_config // [], fun)
183182

@@ -252,7 +251,7 @@ defmodule Mix.Deps do
252251
do: "the dependency requires Elixir #{req} but you are running on v#{System.version}"
253252
254253
defp dep_status(Mix.Dep[app: app, requirement: req, opts: opts, from: from]) do
255-
info = { app, req, Dict.drop(opts, [:dest, :lock, :env, :drop]) }
254+
info = { app, req, Dict.drop(opts, [:dest, :lock, :env, :build]) }
256255
"\n > In #{Path.relative_to_cwd(from)}:\n #{inspect info}\n"
257256
end
258257

@@ -270,22 +269,26 @@ defmodule Mix.Deps do
270269
:outdated ->
271270
dep.status :lockoutdated
272271
:ok ->
273-
dep
272+
if vsn = old_elixir_lock(dep) do
273+
dep.status({ :elixirlock, vsn })
274+
else
275+
dep
276+
end
274277
end
275278
else
276279
dep
277280
end
278281
end
279282

280283
@doc """
281-
Check if a dependency is ok.
284+
Checks if a dependency is ok.
282285
"""
283286
def ok?(Mix.Dep[status: { :ok, _ }]), do: true
284287
def ok?(Mix.Dep[]), do: false
285288

286289
@doc """
287-
Check if a dependency is available. Available dependencies
288-
are the ones that can be compiled, loaded, etc.
290+
Checks if a dependency is available. Available dependencies
291+
are the ones that can be loaded.
289292
"""
290293
def available?(Mix.Dep[status: { :overriden, _ }]), do: false
291294
def available?(Mix.Dep[status: { :diverged, _ }]), do: false
@@ -295,13 +298,23 @@ defmodule Mix.Deps do
295298
def available?(Mix.Dep[]), do: true
296299

297300
@doc """
298-
Check if a dependency can be updated.
301+
Checks if a dependency can be compiled.
302+
303+
All available dependencies can be compiled except for
304+
umbrella applications.
305+
"""
306+
def compilable?(Mix.Dep[manager: manager, extra: extra] = dep) do
307+
available?(dep) and (manager != :mix or !extra[:umbrella?])
308+
end
309+
310+
@doc """
311+
Checks if a dependency can be updated.
299312
"""
300313
def updatable?(Mix.Dep[status: { :elixirreq, _ }]), do: true
301314
def updatable?(dep), do: available?(dep)
302315
303316
@doc """
304-
Check if a dependency is out of date, also considering its
317+
Checks if a dependency is out of date, also considering its
305318
lock status. Therefore, be sure to call `check_lock` before
306319
invoking this function.
307320

@@ -328,44 +341,36 @@ defmodule Mix.Deps do
328341
end
329342

330343
@doc """
331-
Returns all compile paths for the dependency.
332-
Expects a fetched dependency.
344+
Returns all load paths for the given dependency. Automatically
345+
derived from source paths.
333346
"""
334-
def compile_path(Mix.Dep[app: app, opts: opts, manager: manager]) do
335-
if manager == :mix do
336-
Mix.Project.in_project app, opts[:dest], fn _ ->
337-
Mix.Project.compile_path
338-
end
339-
else
340-
Path.join(opts[:dest], "ebin")
347+
def load_paths(Mix.Dep[opts: opts] = dep) do
348+
build_path = Path.dirname(opts[:build])
349+
Enum.map source_paths(dep), fn path ->
350+
Path.join [build_path, Path.basename(path), "ebin"]
341351
end
342352
end
343353
344354
@doc """
345-
Returns all load paths for the dependency.
346-
Expects a fetched dependency.
347-
"""
348-
def load_paths(Mix.Dep[manager: :mix, app: app, opts: opts]) do
349-
Mix.Project.in_project(app, opts[:dest], fn _ ->
350-
Mix.Project.load_paths
351-
end) |> Enum.uniq
352-
end
355+
Returns all source paths.
353356

354-
def load_paths(Mix.Dep[manager: :rebar, opts: opts, extra: extra]) do
357+
Source paths are the directories that contains ebin files for a given
358+
dependency. All managers, except rebar, have only one source path.
359+
"""
360+
def source_paths(Mix.Dep[manager: :rebar, opts: opts, extra: extra]) do
355361
# Add root dir and all sub dirs with ebin/ directory
356362
sub_dirs = Enum.map(extra[:sub_dirs] || [], fn path ->
357363
Path.join(opts[:dest], path)
358364
end)
359365
360-
[ opts[:dest] | sub_dirs ]
361-
|> Enum.map(&Path.wildcard(&1))
362-
|> Enum.concat
363-
|> Enum.map(&Path.join(&1, "ebin"))
364-
|> Enum.filter(&File.dir?(&1))
366+
[opts[:dest] | sub_dirs]
367+
|> Enum.map(&Path.wildcard(&1))
368+
|> Enum.concat
369+
|> Enum.filter(fn p -> p |> Path.join("ebin") |> File.dir? end)
365370
end
366371
367-
def load_paths(Mix.Dep[manager: manager, opts: opts]) when manager in [:make] do
368-
[ Path.join(opts[:dest], "ebin") ]
372+
def source_paths(Mix.Dep[opts: opts]) do
373+
[opts[:dest]]
369374
end
370375
371376
@doc """
@@ -394,7 +399,7 @@ defmodule Mix.Deps do
394399
@doc false
395400
# Called by deps.get and deps.update
396401
def finalize(all_deps, apps, lock, opts) do
397-
deps = fetched_by_name(apps, all_deps)
402+
deps = loaded_by_name(apps, all_deps)
398403
399404
# Do not attempt to compile dependencies that are not available.
400405
# mix deps.check at the end will emit proper status in case they failed.
@@ -404,22 +409,24 @@ defmodule Mix.Deps do
404409
# deps if all dependencies are available. This is because if a
405410
# dependency is missing, it could be a children of the parent
406411
# (aka a sibling) which would make parent compilation fail.
412+
#
413+
# If there is any other dependency that is not ok, we include
414+
# it for compilation too, this is our best to try to solve the
415+
# maximum we can at each deps.get and deps.update.
407416
if Enum.all?(all_deps, &available?/1) do
408-
deps = with_depending(deps, all_deps)
417+
deps = with_depending(deps, all_deps) ++
418+
Enum.filter(all_deps, fn dep -> not ok?(dep) end)
409419
end
410420
411-
apps = Enum.map(deps, &(&1.app))
421+
apps = Enum.map(deps, &(&1.app)) |> Enum.uniq
412422
Mix.Deps.Lock.write(lock)
413423
414424
unless opts[:no_compile] do
415-
# TODO: This is a temporary workaround to the fact
416-
# we do not loadpaths for deps.get and deps.update tasks
417-
# in the CLI.
418-
Mix.Task.run("deps.loadpaths", ["--no-deps-check"])
419-
Mix.Task.reenable("deps.loadpaths")
420-
421-
args = if opts[:quiet], do: ["--quiet"|apps], else: apps
422-
Mix.Task.run("deps.compile", args)
425+
if apps != [] do
426+
args = if opts[:quiet], do: ["--quiet"|apps], else: apps
427+
Mix.Task.run("deps.compile", args)
428+
end
429+
423430
unless opts[:no_deps_check] do
424431
Mix.Task.run("deps.check", [])
425432
end
@@ -449,4 +456,11 @@ defmodule Mix.Deps do
449456
if is_binary(app), do: binary_to_atom(app), else: app
450457
end
451458
end
459+
460+
defp old_elixir_lock(Mix.Dep[opts: opts]) do
461+
old_vsn = Mix.Deps.Lock.elixir_vsn(opts[:build])
462+
if old_vsn && old_vsn != System.version do
463+
old_vsn
464+
end
465+
end
452466
end

0 commit comments

Comments
 (0)