No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

381 líneas
13 KiB

hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
hace 10 años
  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. application:start(crypto),
  6. application:start(asn1),
  7. application:start(public_key),
  8. application:start(ssl),
  9. inets:start(),
  10. %% Fetch and build deps required to build rebar3
  11. BaseDeps = [{providers, []}
  12. ,{getopt, []}
  13. ,{erlware_commons, ["ec_dictionary.erl", "ec_vsn.erl"]}],
  14. Deps = get_deps(),
  15. [fetch_and_compile(Dep, Deps) || Dep <- BaseDeps],
  16. %% Build rebar3 modules with compile:file
  17. bootstrap_rebar3(),
  18. %% Build rebar.app from rebar.app.src
  19. {ok, App} = rebar_app_info:new(rebar, "3.0.0", filename:absname("_build/default/lib/rebar/")),
  20. rebar_otp_app:compile(rebar_state:new(), App),
  21. %% Because we are compiling files that are loaded already we want to silence
  22. %% not_purged errors in rebar_erlc_compiler:opts_changed/1
  23. error_logger:tty(false),
  24. setup_env(),
  25. os:putenv("REBAR_PROFILE", "bootstrap"),
  26. rebar3:run(["update"]),
  27. {ok, State} = rebar3:run(["compile"]),
  28. reset_env(),
  29. os:putenv("REBAR_PROFILE", ""),
  30. DepsPaths = rebar_state:code_paths(State, all_deps),
  31. code:add_pathsa(DepsPaths),
  32. rebar3:run(["clean", "-a"]),
  33. rebar3:run(["escriptize"]),
  34. %% Done with compile, can turn back on error logger
  35. error_logger:tty(true),
  36. %% Finally, update executable perms for our script on *nix,
  37. %% or write out script files on win32.
  38. ec_file:copy("_build/default/bin/rebar3", "./rebar3"),
  39. case os:type() of
  40. {unix,_} ->
  41. [] = os:cmd("chmod u+x rebar3"),
  42. ok;
  43. {win32,_} ->
  44. write_windows_scripts(),
  45. ok;
  46. _ ->
  47. ok
  48. end.
  49. fetch_and_compile({Name, ErlFirstFiles}, Deps) ->
  50. {Name, _, Repo} = lists:keyfind(Name, 1, Deps),
  51. ok = fetch(Repo, Name),
  52. compile(Name, ErlFirstFiles).
  53. fetch({pkg, Name, Vsn}, App) ->
  54. Dir = filename:join([filename:absname("_build/default/lib/"), App]),
  55. CDN = "https://s3.amazonaws.com/s3.hex.pm/tarballs",
  56. Package = binary_to_list(<<Name/binary, "-", Vsn/binary, ".tar">>),
  57. Url = string:join([CDN, Package], "/"),
  58. case request(Url) of
  59. {ok, Binary} ->
  60. {ok, Contents} = extract(Binary),
  61. ok = erl_tar:extract({binary, Contents}, [{cwd, Dir}, compressed]);
  62. _ ->
  63. io:format("Error: Unable to fetch package ~p ~p~n", [Name, Vsn])
  64. end.
  65. extract(Binary) ->
  66. {ok, Files} = erl_tar:extract({binary, Binary}, [memory]),
  67. {"contents.tar.gz", Contents} = lists:keyfind("contents.tar.gz", 1, Files),
  68. {ok, Contents}.
  69. request(Url) ->
  70. setHttpcOptions(),
  71. case httpc:request(get, {Url, []},
  72. [{relaxed, true}],
  73. [{body_format, binary}]) of
  74. {ok, {{_Version, 200, _Reason}, _Headers, Body}} ->
  75. {ok, Body};
  76. Error ->
  77. Error
  78. end.
  79. setHttpcOptions() ->
  80. %% Get http_proxy and https_proxy environment variables
  81. case os:getenv("http_proxy") of
  82. false ->
  83. Http = "";
  84. Http ->
  85. Http
  86. end,
  87. case os:getenv("https_proxy") of
  88. false ->
  89. Https = "";
  90. Https ->
  91. Https
  92. end,
  93. %% Parse the variables to extract host and port
  94. Opts = [],
  95. case http_uri:parse(Http) of
  96. {ok,{_, [], Host, Port, _, []}} ->
  97. Opts1 = Opts ++ [{proxy, {{Host, Port}, []}}];
  98. {error, _} ->
  99. Opts1 = Opts
  100. end,
  101. case http_uri:parse(Https) of
  102. {ok,{_, [], Host2, Port2, _, []}} ->
  103. Opts2 = Opts1 ++ [{https_proxy, {{Host2, Port2}, []}}];
  104. {error, _} ->
  105. Opts2 = Opts1
  106. end,
  107. io:format("Opts: ~p~n", [Opts2]),
  108. case Opts2 of
  109. [] ->
  110. ok;
  111. _ ->
  112. httpc:set_options(Opts2),
  113. ok
  114. end.
  115. compile(App, FirstFiles) ->
  116. Dir = filename:join(filename:absname("_build/default/lib/"), App),
  117. filelib:ensure_dir(filename:join([Dir, "ebin", "dummy.beam"])),
  118. code:add_path(filename:join(Dir, "ebin")),
  119. FirstFilesPaths = [filename:join([Dir, "src", Module]) || Module <- FirstFiles],
  120. Sources = FirstFilesPaths ++ filelib:wildcard(filename:join([Dir, "src", "*.erl"])),
  121. [compile_file(X, [{i, filename:join(Dir, "include")}
  122. ,debug_info
  123. ,{outdir, filename:join(Dir, "ebin")}
  124. ,return | additional_defines()]) || X <- Sources].
  125. compile_file(File, Opts) ->
  126. case compile:file(File, Opts) of
  127. {ok, _Mod} ->
  128. ok;
  129. {ok, _Mod, []} ->
  130. ok;
  131. {ok, _Mod, Ws} ->
  132. io:format("~s~n", [format_warnings(File, Ws)]),
  133. halt(1);
  134. {error, Es, Ws} ->
  135. io:format("~s ~s~n", [format_errors(File, Es), format_warnings(File, Ws)]),
  136. halt(1)
  137. end.
  138. bootstrap_rebar3() ->
  139. filelib:ensure_dir("_build/default/lib/rebar/ebin/dummy.beam"),
  140. code:add_path("_build/default/lib/rebar/ebin/"),
  141. ok = symlink_or_copy(filename:absname("src"),
  142. filename:absname("_build/default/lib/rebar/src")),
  143. Sources = ["src/rebar_resource.erl" | filelib:wildcard("src/*.erl")],
  144. [compile_file(X, [{outdir, "_build/default/lib/rebar/ebin/"}
  145. ,return | additional_defines()]) || X <- Sources],
  146. code:add_patha(filename:absname("_build/default/lib/rebar/ebin")).
  147. %%rebar.hrl
  148. -define(FMT(Str, Args), lists:flatten(io_lib:format(Str, Args))).
  149. %%/rebar.hrl
  150. %%rebar_file_utils
  151. symlink_or_copy(Source, Target) ->
  152. Link = case os:type() of
  153. {win32, _} ->
  154. Source;
  155. _ ->
  156. make_relative_path(Source, Target)
  157. end,
  158. case file:make_symlink(Link, Target) of
  159. ok ->
  160. ok;
  161. {error, eexist} ->
  162. ok;
  163. {error, _} ->
  164. cp_r([Source], Target)
  165. end.
  166. make_relative_path(Source, Target) ->
  167. do_make_relative_path(filename:split(Source), filename:split(Target)).
  168. do_make_relative_path([H|T1], [H|T2]) ->
  169. do_make_relative_path(T1, T2);
  170. do_make_relative_path(Source, Target) ->
  171. Base = lists:duplicate(max(length(Target) - 1, 0), ".."),
  172. filename:join(Base ++ Source).
  173. cp_r([], _Dest) ->
  174. ok;
  175. cp_r(Sources, Dest) ->
  176. case os:type() of
  177. {unix, _} ->
  178. EscSources = [escape_path(Src) || Src <- Sources],
  179. SourceStr = string:join(EscSources, " "),
  180. os:cmd(?FMT("cp -R ~s \"~s\"", [SourceStr, Dest])),
  181. ok;
  182. {win32, _} ->
  183. lists:foreach(fun(Src) -> ok = cp_r_win32(Src,Dest) end, Sources),
  184. ok
  185. end.
  186. xcopy_win32(Source,Dest)->
  187. R = os:cmd(?FMT("xcopy \"~s\" \"~s\" /q /y /e 2> nul",
  188. [filename:nativename(Source), filename:nativename(Dest)])),
  189. case length(R) > 0 of
  190. %% when xcopy fails, stdout is empty and and error message is printed
  191. %% to stderr (which is redirected to nul)
  192. true -> ok;
  193. false ->
  194. {error, lists:flatten(
  195. io_lib:format("Failed to xcopy from ~s to ~s~n",
  196. [Source, Dest]))}
  197. end.
  198. cp_r_win32({true, SourceDir}, {true, DestDir}) ->
  199. %% from directory to directory
  200. SourceBase = filename:basename(SourceDir),
  201. ok = case file:make_dir(filename:join(DestDir, SourceBase)) of
  202. {error, eexist} -> ok;
  203. Other -> Other
  204. end,
  205. ok = xcopy_win32(SourceDir, filename:join(DestDir, SourceBase));
  206. cp_r_win32({false, Source} = S,{true, DestDir}) ->
  207. %% from file to directory
  208. cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))});
  209. cp_r_win32({false, Source},{false, Dest}) ->
  210. %% from file to file
  211. {ok,_} = file:copy(Source, Dest),
  212. ok;
  213. cp_r_win32({true, SourceDir}, {false, DestDir}) ->
  214. case filelib:is_regular(DestDir) of
  215. true ->
  216. %% From directory to file? This shouldn't happen
  217. {error, lists:flatten(
  218. io_lib:format("Cannot copy dir (~p) to file (~p)\n",
  219. [SourceDir, DestDir]))};
  220. false ->
  221. %% Specifying a target directory that doesn't currently exist.
  222. %% So let's attempt to create this directory
  223. case filelib:ensure_dir(filename:join(DestDir, "dummy")) of
  224. ok ->
  225. ok = xcopy_win32(SourceDir, DestDir);
  226. {error, Reason} ->
  227. {error, lists:flatten(
  228. io_lib:format("Unable to create dir ~p: ~p\n",
  229. [DestDir, Reason]))}
  230. end
  231. end;
  232. cp_r_win32(Source,Dest) ->
  233. Dst = {filelib:is_dir(Dest), Dest},
  234. lists:foreach(fun(Src) ->
  235. ok = cp_r_win32({filelib:is_dir(Src), Src}, Dst)
  236. end, filelib:wildcard(Source)),
  237. ok.
  238. escape_path(Str) ->
  239. re:replace(Str, "([ ()?])", "\\\\&", [global, {return, list}]).
  240. %%/rebar_file_utils
  241. setup_env() ->
  242. %% We don't need or want relx providers loaded yet
  243. application:load(rebar),
  244. {ok, Providers} = application:get_env(rebar, providers),
  245. Providers1 = Providers -- [rebar_prv_release,
  246. rebar_prv_relup,
  247. rebar_prv_tar],
  248. application:set_env(rebar, providers, Providers1).
  249. reset_env() ->
  250. %% Reset the env so we get all providers
  251. application:unset_env(rebar, providers),
  252. application:unload(rebar),
  253. application:load(rebar).
  254. write_windows_scripts() ->
  255. CmdScript=
  256. "@echo off\r\n"
  257. "setlocal\r\n"
  258. "set rebarscript=%~f0\r\n"
  259. "escript.exe \"%rebarscript:.cmd=%\" %*\r\n",
  260. ok = file:write_file("rebar3.cmd", CmdScript).
  261. get_deps() ->
  262. case file:consult("rebar.lock") of
  263. {ok, [Deps]} ->
  264. [{binary_to_atom(Name, utf8), "", Source} || {Name, Source, _Level} <- Deps];
  265. _ ->
  266. {ok, Config} = file:consult("rebar.config"),
  267. proplists:get_value(deps, Config)
  268. end.
  269. format_errors(Source, Errors) ->
  270. format_errors(Source, "", Errors).
  271. format_warnings(Source, Warnings) ->
  272. format_warnings(Source, Warnings, []).
  273. format_warnings(Source, Warnings, Opts) ->
  274. Prefix = case lists:member(warnings_as_errors, Opts) of
  275. true -> "";
  276. false -> "Warning: "
  277. end,
  278. format_errors(Source, Prefix, Warnings).
  279. format_errors(_MainSource, Extra, Errors) ->
  280. [begin
  281. [format_error(Source, Extra, Desc) || Desc <- Descs]
  282. end
  283. || {Source, Descs} <- Errors].
  284. format_error(AbsSource, Extra, {{Line, Column}, Mod, Desc}) ->
  285. ErrorDesc = Mod:format_error(Desc),
  286. io_lib:format("~s:~w:~w: ~s~s~n", [AbsSource, Line, Column, Extra, ErrorDesc]);
  287. format_error(AbsSource, Extra, {Line, Mod, Desc}) ->
  288. ErrorDesc = Mod:format_error(Desc),
  289. io_lib:format("~s:~w: ~s~s~n", [AbsSource, Line, Extra, ErrorDesc]);
  290. format_error(AbsSource, Extra, {Mod, Desc}) ->
  291. ErrorDesc = Mod:format_error(Desc),
  292. io_lib:format("~s: ~s~s~n", [AbsSource, Extra, ErrorDesc]).
  293. additional_defines() ->
  294. [{d, D} || {Re, D} <- [{"^[0-9]+", namespaced_types}, {"^R1[4|5]", deprecated_crypto}], is_otp_release(Re)].
  295. is_otp_release(ArchRegex) ->
  296. case re:run(otp_release(), ArchRegex, [{capture, none}]) of
  297. match ->
  298. true;
  299. nomatch ->
  300. false
  301. end.
  302. otp_release() ->
  303. otp_release1(erlang:system_info(otp_release)).
  304. %% If OTP <= R16, otp_release is already what we want.
  305. otp_release1([$R,N|_]=Rel) when is_integer(N) ->
  306. Rel;
  307. %% If OTP >= 17.x, erlang:system_info(otp_release) returns just the
  308. %% major version number, we have to read the full version from
  309. %% a file. See http://www.erlang.org/doc/system_principles/versions.html
  310. %% Read vsn string from the 'OTP_VERSION' file and return as list without
  311. %% the "\n".
  312. otp_release1(Rel) ->
  313. File = filename:join([code:root_dir(), "releases", Rel, "OTP_VERSION"]),
  314. case file:read_file(File) of
  315. {error, _} ->
  316. Rel;
  317. {ok, Vsn} ->
  318. %% It's fine to rely on the binary module here because we can
  319. %% be sure that it's available when the otp_release string does
  320. %% not begin with $R.
  321. Size = byte_size(Vsn),
  322. %% The shortest vsn string consists of at least two digits
  323. %% followed by "\n". Therefore, it's safe to assume Size >= 3.
  324. case binary:part(Vsn, {Size, -3}) of
  325. <<"**\n">> ->
  326. %% The OTP documentation mentions that a system patched
  327. %% using the otp_patch_apply tool available to licensed
  328. %% customers will leave a '**' suffix in the version as a
  329. %% flag saying the system consists of application versions
  330. %% from multiple OTP versions. We ignore this flag and
  331. %% drop the suffix, given for all intents and purposes, we
  332. %% cannot obtain relevant information from it as far as
  333. %% tooling is concerned.
  334. binary:bin_to_list(Vsn, {0, Size - 3});
  335. _ ->
  336. binary:bin_to_list(Vsn, {0, Size - 1})
  337. end
  338. end.