summaryrefslogtreecommitdiff
path: root/src/rebar_port_compiler.erl
diff options
context:
space:
mode:
authorDave Smith <dizzyd@dizzyd.com>2010-02-16 07:05:29 -0700
committerDave Smith <dizzyd@dizzyd.com>2010-02-16 07:05:29 -0700
commit1f6d861ababc5bead8cf75e0d0ee63f33798f42a (patch)
treefa1da08058bf141171c37b1a9559b759e527aa63 /src/rebar_port_compiler.erl
parent51133313a6eb44171a0eb4e3a087febf06bd8622 (diff)
Overhaul env expansion so that rebar fully expands env refs prior to invoking the shell script. Also now using DRV_* env vars for compilation/linking of files found in c_src; this frees up "normal" CFLAGS/LDFLAGS for usage in sub build scripts.
Diffstat (limited to 'src/rebar_port_compiler.erl')
-rw-r--r--src/rebar_port_compiler.erl100
1 files changed, 78 insertions, 22 deletions
diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl
index b08a046..fcce72b 100644
--- a/src/rebar_port_compiler.erl
+++ b/src/rebar_port_compiler.erl
@@ -47,8 +47,10 @@
%% CFLAGS - C compiler
%% CXXFLAGS - C++ compiler
%% LDFLAGS - Link flags
-%% DRIVER_CFLAGS - default -I paths for erts and ei
-%% DRIVER_LDFLAGS - default -L and -lerl_interface -lei
+%% ERL_CFLAGS - default -I paths for erts and ei
+%% ERL_LDFLAGS - default -L and -lerl_interface -lei
+%% DRV_CFLAGS - flags that will be used for compiling the driver
+%% DRV_LDFLAGS - flags that will be used for linking the driver
%%
%% Note that if you wish to extend (vs. replace) these variables, you MUST
%% include a shell-style reference in your definition. E.g. to extend CFLAGS,
@@ -80,7 +82,7 @@ compile(Config, AppFile) ->
%% default for this operating system. This enables max flexibility for users.
DefaultEnvs = filter_envs(default_env(), []),
OverrideEnvs = filter_envs(rebar_config:get_list(Config, port_envs, []), []),
- Env = merge_envs(OverrideEnvs, DefaultEnvs),
+ Env = expand_vars_loop(merge_each_var(os_env() ++ DefaultEnvs ++ OverrideEnvs, [])),
%% One or more files are available for building. Run the pre-compile hook, if
%% necessary.
@@ -97,7 +99,8 @@ compile(Config, AppFile) ->
case needs_link(SoName, NewBins) of
true ->
AllBins = string:join(NewBins ++ ExistingBins, " "),
- rebar_utils:sh_failfast(?FMT("$CC ~s $LDFLAGS $DRIVER_LDFLAGS -o ~s", [AllBins, SoName]), Env);
+ rebar_utils:sh_failfast(?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s",
+ [AllBins, SoName]), Env);
false ->
?INFO("Skipping relink of ~s\n", [SoName]),
ok
@@ -162,9 +165,11 @@ compile_each([Source | Rest], Config, Env, NewBins, ExistingBins) ->
?CONSOLE("Compiling ~s\n", [Source]),
case compiler(Ext) of
"$CC" ->
- rebar_utils:sh_failfast(?FMT("$CC -c $CFLAGS $DRIVER_CFLAGS ~s -o ~s", [Source, Bin]), Env);
+ rebar_utils:sh_failfast(?FMT("$CC -c $CFLAGS $DRV_CFLAGS ~s -o ~s",
+ [Source, Bin]), Env);
"$CXX" ->
- rebar_utils:sh_failfast(?FMT("$CXX -c $CXXFLAGS $DRIVER_CFLAGS ~s -o ~s", [Source, Bin]), Env)
+ rebar_utils:sh_failfast(?FMT("$CXX -c $CXXFLAGS $DRV_CFLAGS ~s -o ~s",
+ [Source, Bin]), Env)
end,
compile_each(Rest, Config, Env, [Bin | NewBins], ExistingBins);
@@ -192,13 +197,6 @@ needs_link(SoName, NewBins) ->
MaxLastMod >= Other
end.
-merge_envs(OverrideEnvs, DefaultEnvs) ->
- orddict:merge(fun(Key, Override, Default) ->
- expand_env_variable(Override, Key, Default)
- end,
- orddict:from_list(OverrideEnvs),
- orddict:from_list(DefaultEnvs)).
-
%%
%% Choose a compiler variable, based on a provided extension
@@ -214,6 +212,62 @@ compiler(_) -> "$CC".
%%
+%% Given a list of {Key, Value} environment variables, where Key may be defined
+%% multiple times, walk the list and expand each self-reference so that we
+%% end with a list of each variable singly-defined.
+%%
+merge_each_var([], Vars) ->
+ Vars;
+merge_each_var([{Key, Value} | Rest], Vars) ->
+ case orddict:find(Key, Vars) of
+ error ->
+ %% Nothing yet defined for this key/value. Expand any self-references
+ %% as blank.
+ Evalue = expand_env_variable(Value, Key, "");
+ {ok, Value0} ->
+ %% Use previous definition in expansion
+ Evalue = expand_env_variable(Value, Key, Value0)
+ end,
+ merge_each_var(Rest, orddict:store(Key, Evalue, Vars)).
+
+%%
+%% Give a unique list of {Key, Value} environment variables, expand each one
+%% for every other key until no further expansions are possible.
+%%
+expand_vars_loop(Vars) ->
+ expand_vars_loop(Vars, 10).
+
+expand_vars_loop(Vars0, 0) ->
+ ?ABORT("Max. expansion reached for ENV vars!\n", []);
+expand_vars_loop(Vars0, Count) ->
+ Vars = lists:foldl(fun({Key, Value}, Acc) ->
+ expand_vars(Key, Value, Acc)
+ end,
+ Vars0, Vars0),
+ case orddict:from_list(Vars) of
+ Vars0 ->
+ Vars0;
+ Vars ->
+ expand_vars_loop(Vars, Count-1)
+ end.
+
+%%
+%% Expand all OTHER references to a given K/V pair
+%%
+expand_vars(Key, Value, Vars) ->
+ lists:foldl(fun({AKey, AValue}, Acc) ->
+ case AKey of
+ Key ->
+ NewValue = AValue;
+ _ ->
+ NewValue = expand_env_variable(AValue, Key, Value)
+ end,
+ [{AKey, NewValue} | Acc]
+ end,
+ [], Vars).
+
+
+%%
%% Given env. variable FOO we want to expand all references to
%% it in InStr. References can have two forms: $FOO and ${FOO}
%%
@@ -242,18 +296,20 @@ filter_envs([{Key, Value} | Rest], Acc) ->
erts_dir() ->
lists:concat([code:root_dir(), "/erts-", erlang:system_info(version)]).
+os_env() ->
+ [list_to_tuple(re:split(S, "=", [{return, list}])) || S <- os:getenv()].
+
default_env() ->
[{"CC", "gcc"},
{"CXX", "g++"},
- {"CFLAGS", "-g -Wall -fPIC"},
- {"CXXFLAGS", "-g -Wall -fPIC"},
- {"LDFLAGS", "-shared"},
- {"darwin", "LDFLAGS", "-bundle -flat_namespace -undefined suppress"},
- {"DRIVER_CFLAGS", lists:concat([" -I", code:lib_dir(erl_interface, include),
- " -I", filename:join(erts_dir(), include),
- " "])},
- {"DRIVER_LDFLAGS", lists:concat([" -L", code:lib_dir(erl_interface, lib),
- " -lerl_interface -lei"])},
+ {"ERL_CFLAGS", lists:concat([" -I", code:lib_dir(erl_interface, include),
+ " -I", filename:join(erts_dir(), include),
+ " "])},
+ {"ERL_LDFLAGS", lists:concat([" -L", code:lib_dir(erl_interface, lib),
+ " -lerl_interface -lei"])},
+ {"DRV_CFLAGS", "-g -Wall -fPIC $ERL_CFLAGS"},
+ {"DRV_LDFLAGS", "-shared $ERL_LDFLAGS"},
+ {"darwin", "DRV_LDFLAGS", "-bundle -flat_namespace -undefined suppress $ERL_LDFLAGS"},
{"ERLANG_ARCH", integer_to_list(8 * erlang:system_info(wordsize))},
{"ERLANG_TARGET", rebar_utils:get_arch()}].