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.

155 lines
5.0 KiB

11 years ago
10 years ago
  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. case lists:member("--help", Args) of
  6. true ->
  7. usage(),
  8. halt(0);
  9. false ->
  10. ok
  11. end,
  12. %% Get a string repr of build time
  13. Built = build_time(),
  14. %% Get a string repr of first matching VCS changeset
  15. VcsInfo = vcs_info([{hg, ".hg", "hg identify -i", "hg status"},
  16. {git, ".git", "git describe --always --tags",
  17. "git status -s"}]),
  18. %% Check for force=1 flag to force a rebuild
  19. case lists:member("force=1", Args) of
  20. true ->
  21. rm("ebin/*.beam");
  22. false ->
  23. rm("ebin/rebar.beam")
  24. end,
  25. %% Add check for debug flag
  26. DebugFlag = case lists:member("debug", Args) of
  27. true -> debug_info;
  28. false -> undefined
  29. end,
  30. %% Extract the system info of the version of OTP we use to compile rebar
  31. OtpInfo = string:strip(erlang:system_info(otp_release), both, $\n),
  32. %% Types dict:dict() and digraph:digraph() have been introduced in
  33. %% Erlang 17.
  34. %% At the same time, their counterparts dict() and digraph() are to be
  35. %% deprecated in Erlang 18. namespaced_types option is used to select
  36. %% proper type name depending on the OTP version used.
  37. NamespacedTypes = case is_otp(OtpInfo, "^[0-9]+") of
  38. true -> {d, namespaced_types};
  39. false -> undefined
  40. end,
  41. os:cmd("./bootstrap/rebar get-deps compile"),
  42. %% Compile all src/*.erl to ebin
  43. %% To not accidentally try to compile files like Mac OS X resource forks,
  44. %% we only look for rebar source files that start with a letter.
  45. case make:files(filelib:wildcard("src/[a-zA-Z]*.erl"),
  46. [{outdir, "ebin"}, {i, "include"},
  47. DebugFlag,
  48. NamespacedTypes,
  49. {d, 'BUILD_TIME', Built},
  50. {d, 'VCS_INFO', VcsInfo},
  51. {d, 'OTP_INFO', OtpInfo}]) of
  52. up_to_date ->
  53. ok;
  54. error ->
  55. io:format("Failed to compile rebar files!\n"),
  56. halt(1)
  57. end,
  58. %% Make sure file:consult can parse the .app file
  59. case file:consult("ebin/rebar.app") of
  60. {ok, _} ->
  61. ok;
  62. {error, Reason} ->
  63. io:format("Invalid syntax in ebin/rebar.app: ~p\n", [Reason]),
  64. halt(1)
  65. end,
  66. %% Add ebin/ to our path
  67. true = code:add_path("ebin"),
  68. %% Run rebar compile to do proper .app validation etc.
  69. %% and rebar escriptize to create the rebar script
  70. %RebarArgs = Args -- ["debug"], %% Avoid trying to run 'debug' command
  71. %rebar:main(["compile", "escriptize"] ++ RebarArgs),
  72. os:cmd("./bootstrap/rebar compile escriptize"),
  73. %% Finally, update executable perms for our script on *nix,
  74. %% or write out script files on win32.
  75. case os:type() of
  76. {unix,_} ->
  77. [] = os:cmd("chmod u+x rebar3"),
  78. ok;
  79. {win32,_} ->
  80. write_windows_scripts(),
  81. ok;
  82. _ ->
  83. ok
  84. end,
  85. %% Add a helpful message
  86. io:format("Congratulations! You now have a self-contained script called"
  87. " \"rebar3\" in\n"
  88. "your current working directory. "
  89. "Place this script anywhere in your path\n"
  90. "and you can use rebar to build OTP-compliant apps.\n").
  91. usage() ->
  92. io:format("Usage: bootstrap [OPTION]...~n"),
  93. io:format(" force=1 unconditional build~n"),
  94. io:format(" debug add debug information~n").
  95. is_otp(OtpInfo, Regex) ->
  96. case re:run(OtpInfo, Regex, [{capture, none}]) of
  97. match -> true;
  98. nomatch -> false
  99. end.
  100. rm(Path) ->
  101. NativePath = filename:nativename(Path),
  102. Cmd = case os:type() of
  103. {unix,_} -> "rm -f ";
  104. {win32,_} -> "del /q "
  105. end,
  106. [] = os:cmd(Cmd ++ NativePath),
  107. ok.
  108. build_time() ->
  109. {{Y, M, D}, {H, Min, S}} = calendar:now_to_universal_time(now()),
  110. lists:flatten(io_lib:format("~4..0w~2..0w~2..0w_~2..0w~2..0w~2..0w",
  111. [Y, M, D, H, Min, S])).
  112. vcs_info([]) ->
  113. "No VCS info available.";
  114. vcs_info([{Id, Dir, VsnCmd, StatusCmd} | Rest]) ->
  115. case filelib:is_dir(Dir) of
  116. true ->
  117. Vsn = string:strip(os:cmd(VsnCmd), both, $\n),
  118. Status = case string:strip(os:cmd(StatusCmd), both, $\n) of
  119. [] ->
  120. "";
  121. _ ->
  122. "-dirty"
  123. end,
  124. lists:concat([Id, " ", Vsn, Status]);
  125. false ->
  126. vcs_info(Rest)
  127. end.
  128. write_windows_scripts() ->
  129. CmdScript=
  130. "@echo off\r\n"
  131. "setlocal\r\n"
  132. "set rebarscript=%~f0\r\n"
  133. "escript.exe \"%rebarscript:.cmd=%\" %*\r\n",
  134. ok = file:write_file("rebar.cmd", CmdScript).