1-module(rebar_env).
2
3-export([create_env/1,
4         create_env/2]).
5
6-include("rebar.hrl").
7
8%% @doc The following environment variables are exported when running
9%% a hook (absolute paths):
10%%
11%% REBAR_DEPS_DIR          = rebar_dir:deps_dir/1
12%% REBAR_BUILD_DIR         = rebar_dir:base_dir/1
13%% REBAR_ROOT_DIR          = rebar_dir:root_dir/1
14%% REBAR_CHECKOUTS_DIR     = rebar_dir:checkouts_dir/1
15%% REBAR_CHECKOUTS_OUT_DIR = rebar_dir:checkouts_out_dir/1
16%% REBAR_PLUGINS_DIR       = rebar_dir:plugins_dir/1
17%% REBAR_GLOBAL_CONFIG_DIR = rebar_dir:global_config_dir/1
18%% REBAR_GLOBAL_CACHE_DIR  = rebar_dir:global_cache_dir/1
19%% REBAR_TEMPLATE_DIR      = rebar_dir:template_dir/1
20%% REBAR_APP_DIRS          = rebar_dir:lib_dirs/1
21%% REBAR_SRC_DIRS          = rebar_dir:src_dirs/1
22%%
23%% autoconf compatible variables
24%% (see: http://www.gnu.org/software/autoconf/manual/autoconf.html#Erlang-Libraries):
25%% ERLANG_ERTS_VER              = erlang:system_info(version)
26%% ERLANG_ROOT_DIR              = code:root_dir/0
27%% ERLANG_LIB_DIR_erl_interface = code:lib_dir(erl_interface)
28%% ERLANG_LIB_VER_erl_interface = version part of path returned by code:lib_dir(erl_interface)
29%% ERL                          = ERLANG_ROOT_DIR/bin/erl
30%% ERLC                         = ERLANG_ROOT_DIR/bin/erl
31%%
32
33-spec create_env(rebar_state:t()) -> proplists:proplist().
34create_env(State) ->
35    Opts = rebar_state:opts(State),
36    create_env(State, Opts).
37
38-spec create_env(rebar_state:t(), rebar_dict()) -> proplists:proplist().
39create_env(State, Opts) ->
40    BaseDir = rebar_dir:base_dir(State),
41    EnvVars = [
42        {"REBAR_DEPS_DIR",          filename:absname(rebar_dir:deps_dir(State))},
43        {"REBAR_BUILD_DIR",         filename:absname(rebar_dir:base_dir(State))},
44        {"REBAR_ROOT_DIR",          filename:absname(rebar_dir:root_dir(State))},
45        {"REBAR_CHECKOUTS_DIR",     filename:absname(rebar_dir:checkouts_dir(State))},
46        {"REBAR_CHECKOUTS_OUT_DIR", filename:absname(rebar_dir:checkouts_out_dir(State))},
47        {"REBAR_PLUGINS_DIR",       filename:absname(rebar_dir:plugins_dir(State))},
48        {"REBAR_GLOBAL_CONFIG_DIR", filename:absname(rebar_dir:global_config_dir(State))},
49        {"REBAR_GLOBAL_CACHE_DIR",  filename:absname(rebar_dir:global_cache_dir(Opts))},
50        {"REBAR_TEMPLATE_DIR",      filename:absname(rebar_dir:template_dir(State))},
51        {"REBAR_APP_DIRS",          join_dirs(BaseDir, rebar_dir:lib_dirs(State))},
52        {"REBAR_SRC_DIRS",          join_dirs(BaseDir, rebar_dir:all_src_dirs(Opts))},
53        {"ERLANG_ERTS_VER",         erlang:system_info(version)},
54        {"ERLANG_ROOT_DIR",         code:root_dir()},
55        {"ERL",                     filename:join([code:root_dir(), "bin", "erl"])},
56        {"ERLC",                    filename:join([code:root_dir(), "bin", "erlc"])},
57        {"ERLANG_ARCH"  ,           rebar_api:wordsize()},
58        {"ERLANG_TARGET",           rebar_api:get_arch()}
59    ],
60    EInterfaceVars = create_erl_interface_env(),
61    lists:append([EnvVars, EInterfaceVars]).
62
63-spec create_erl_interface_env() -> list().
64create_erl_interface_env() ->
65    case code:lib_dir(erl_interface) of
66        {error, bad_name} ->
67            ?WARN("erl_interface is missing. ERLANG_LIB_DIR_erl_interface and "
68            "ERLANG_LIB_VER_erl_interface will not be added to the environment.", []),
69            [];
70        Dir ->
71            [
72             {"ERLANG_LIB_DIR_erl_interface", Dir},
73             {"ERLANG_LIB_VER_erl_interface", re_version(Dir)}
74            ]
75    end.
76
77%% ====================================================================
78%% Internal functions
79%% ====================================================================
80
81join_dirs(BaseDir, Dirs) ->
82    rebar_string:join([filename:join(BaseDir, Dir) || Dir <- Dirs], ":").
83
84re_version(Path) ->
85    case re:run(Path, "^.*-(?<VER>[^/-]*)$", [{capture,[1],list}, unicode]) of
86        nomatch -> "";
87        {match, [Ver]} -> Ver
88    end.
89