You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
4.6 KiB

  1. #!/usr/bin/env escript
  2. %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
  3. %% ex: ft=erlang ts=4 sw=4 et
  4. main(_Args) ->
  5. %% Fetch and build deps required to build rebar3
  6. BaseDeps = [{providers, []}
  7. ,{getopt, []}
  8. ,{erlware_commons, ["ec_dictionary.erl", "ec_vsn.erl"]}],
  9. Deps = get_deps(),
  10. [fetch_and_compile(Dep, Deps) || Dep <- BaseDeps],
  11. %% Build rebar3 modules with compile:file
  12. bootstrap_rebar3(),
  13. %% Build rebar.app from rebar.app.src
  14. {ok, App} = rebar_app_info:new(rebar, "3.0.0", filename:absname("_build/default/lib/rebar/")),
  15. rebar_otp_app:compile(rebar_state:new(), App),
  16. %% Because we are compiling files that are loaded already we want to silence
  17. %% not_purged errors in rebar_erlc_compiler:opts_changed/1
  18. error_logger:tty(false),
  19. setup_env(),
  20. os:putenv("REBAR_PROFILE", "bootstrap"),
  21. {ok, State} = rebar3:run(["compile"]),
  22. reset_env(),
  23. os:unsetenv("REBAR_PROFILE"),
  24. %% Build erlydtl files (a hook on compile in the default profile) and escript file
  25. DepsPaths = rebar_state:code_paths(State, all_deps),
  26. code:add_pathsa(DepsPaths),
  27. rebar3:run(["clean", "-a"]),
  28. rebar3:run(["escriptize"]),
  29. %% Done with compile, can turn back on error logger
  30. error_logger:tty(true),
  31. %% Finally, update executable perms for our script on *nix,
  32. %% or write out script files on win32.
  33. ec_file:copy("_build/default/bin/rebar3", "./rebar3"),
  34. case os:type() of
  35. {unix,_} ->
  36. [] = os:cmd("chmod u+x rebar3"),
  37. ok;
  38. {win32,_} ->
  39. write_windows_scripts(),
  40. ok;
  41. _ ->
  42. ok
  43. end.
  44. fetch_and_compile({Name, ErlFirstFiles}, Deps) ->
  45. {Name, _, Repo} = lists:keyfind(Name, 1, Deps),
  46. ok = fetch(Repo, Name),
  47. compile(Name, ErlFirstFiles).
  48. fetch({git, Url, Source}, App) ->
  49. Dir = filename:join([filename:absname("_build/default/lib/"), App]),
  50. case filelib:is_dir(Dir) of
  51. true ->
  52. true = code:add_path(filename:join(Dir, "ebin")),
  53. ok;
  54. false ->
  55. fetch_source(Dir, Url, Source),
  56. ok
  57. end.
  58. fetch_source(Dir, Url, {ref, Ref}) ->
  59. ok = filelib:ensure_dir(Dir),
  60. os:cmd(io_lib:format("git clone ~s ~s", [Url, Dir])),
  61. {ok, Cwd} = file:get_cwd(),
  62. file:set_cwd(Dir),
  63. os:cmd(io_lib:format("git checkout -q ~s", [Ref])),
  64. file:set_cwd(Cwd);
  65. fetch_source(Dir, Url, {_, Branch}) ->
  66. ok = filelib:ensure_dir(Dir),
  67. os:cmd(io_lib:format("git clone ~s ~s -b ~s --single-branch",
  68. [Url, Dir, Branch])).
  69. compile(App, FirstFiles) ->
  70. Dir = filename:join(filename:absname("_build/default/lib/"), App),
  71. filelib:ensure_dir(filename:join([Dir, "ebin", "dummy.beam"])),
  72. code:add_path(filename:join(Dir, "ebin")),
  73. FirstFilesPaths = [filename:join([Dir, "src", Module]) || Module <- FirstFiles],
  74. Sources = FirstFilesPaths ++ filelib:wildcard(filename:join([Dir, "src", "*.erl"])),
  75. [compile:file(X, [{i, filename:join(Dir, "include")}
  76. ,{outdir, filename:join(Dir, "ebin")}
  77. ,return]) || X <- Sources].
  78. bootstrap_rebar3() ->
  79. filelib:ensure_dir("_build/default/lib/rebar/ebin/dummy.beam"),
  80. file:make_symlink(filename:absname("src"), filename:absname("_build/default/lib/rebar/src")),
  81. Sources = filelib:wildcard("src/*.erl"),
  82. [compile:file(X, [{outdir, "_build/default/lib/rebar/ebin/"}]) || X <- Sources],
  83. code:add_path(filename:absname("_build/default/lib/rebar/ebin")).
  84. setup_env() ->
  85. %% We don't need or want erlydtl or relx providers loaded yet
  86. application:load(rebar),
  87. {ok, Providers} = application:get_env(rebar, providers),
  88. Providers1 = Providers -- [rebar_prv_erlydtl_compiler,
  89. rebar_prv_release,
  90. rebar_prv_tar],
  91. application:set_env(rebar, providers, Providers1).
  92. reset_env() ->
  93. %% Reset the env so we get all providers and can build erlydtl files
  94. application:unset_env(rebar, providers),
  95. application:unload(rebar),
  96. application:load(rebar).
  97. write_windows_scripts() ->
  98. CmdScript=
  99. "@echo off\r\n"
  100. "setlocal\r\n"
  101. "set rebarscript=%~f0\r\n"
  102. "escript.exe \"%rebarscript:.cmd=%\" %*\r\n",
  103. ok = file:write_file("rebar3.cmd", CmdScript).
  104. get_deps() ->
  105. case file:consult("rebar.lock") of
  106. {ok, [Deps]} ->
  107. [{binary_to_atom(Name, utf8), "", Source} || {Name, Source, _Level} <- Deps];
  108. _ ->
  109. {ok, Config} = file:consult("rebar.config"),
  110. proplists:get_value(deps, Config)
  111. end.