Permalink
Browse files

Add support for target-specific port options

{port_specs, [{".*", "priv/foo.so", ["c_src/foo.c"], [{env, []}]}]}.
  • Loading branch information...
1 parent 2ae73cc commit 7c418ed2b4a4316e4a784b83c2ffbdc1adf33dbe @tuncer tuncer committed Feb 7, 2012
Showing with 268 additions and 217 deletions.
  1. +4 −2 rebar.config.sample
  2. +20 −5 src/rebar_config.erl
  3. +44 −34 src/rebar_core.erl
  4. +200 −176 src/rebar_port_compiler.erl
View
@@ -37,14 +37,16 @@
%% Port compilation environment variables. See rebar_port_compiler.erl for
%% more info. Default is `[]'
-{port_env, []}.
+{port_env, [{"CFLAGS", "$CFLAGS -Ifoo"},
+ {"freebsd", "LDFLAGS", "$LDFLAGS -lfoo"}]}.
%% port_specs
%% List of filenames or wildcards to be compiled. May also contain a tuple
%% consisting of a regular expression to be applied against the system
%% architecture as a filter.
{port_specs, [{"priv/so_name.so", ["c_src/*.c"]},
- {"linux", "priv/hello_linux", ["c_src/hello_linux.c"]]}.
+ {"linux", "priv/hello_linux", ["c_src/hello_linux.c"]},
+ {"linux", "priv/hello_linux", ["c_src/*.c"], [{env, []}]}}.
%% == LFE Compiler ==
View
@@ -31,12 +31,17 @@
get_all/2,
set/3,
set_global/2, get_global/2,
- is_verbose/0, get_jobs/0]).
+ is_verbose/0, get_jobs/0,
+ set_env/3, get_env/2]).
-include("rebar.hrl").
-record(config, { dir :: file:filename(),
- opts :: list() }).
+ opts = [] :: list(),
+ envs = [] :: list({module(), env()}) }).
+
+-type env() :: [env_var()].
+-type env_var() :: {string(), string()}.
%% Types that can be used from other modules -- alphabetically ordered.
-export_type([config/0]).
@@ -53,8 +58,7 @@ base_config(#config{opts=Opts0}) ->
new(Opts0, ConfName).
new() ->
- #config { dir = rebar_utils:get_cwd(),
- opts = [] }.
+ #config{dir = rebar_utils:get_cwd()}.
new(ConfigFile) when is_list(ConfigFile) ->
case consult_file(ConfigFile) of
@@ -88,7 +92,7 @@ new(Opts0, ConfName) ->
?ABORT("Failed to load ~s: ~p\n", [ConfigFile, Other])
end,
- #config { dir = Dir, opts = Opts }.
+ #config{dir = Dir, opts = Opts}.
get(Config, Key, Default) ->
proplists:get_value(Key, Config#config.opts, Default).
@@ -143,6 +147,17 @@ consult_file(File) ->
end
end.
+set_env(Config, Mod, Env) ->
+ OldEnvs = Config#config.envs,
+ NewEnvs = case lists:keymember(Mod, 1, OldEnvs) of
+ true -> lists:keyreplace(Mod, 1, OldEnvs, {Mod, Env});
+ false -> [{Mod,Env}|OldEnvs]
+ end,
+ Config#config{envs=NewEnvs}.
+
+get_env(Config, Mod) ->
+ proplists:get_value(Mod, Config#config.envs, []).
+
%% ===================================================================
%% Internal functions
%% ===================================================================
View
@@ -168,7 +168,7 @@ maybe_process_dir0(AppFile, ModuleSet, Config, CurrentCodePath,
CurrentCodePath, ModuleSet)
end.
-process_dir0(Dir, Command, DirSet, Config, CurrentCodePath,
+process_dir0(Dir, Command, DirSet, Config0, CurrentCodePath,
{DirModules, ModuleSetFile}) ->
%% Get the list of modules for "any dir". This is a catch-all list
%% of modules that are processed in addition to modules associated
@@ -180,47 +180,53 @@ process_dir0(Dir, Command, DirSet, Config, CurrentCodePath,
%% Invoke 'preprocess' on the modules -- this yields a list of other
%% directories that should be processed _before_ the current one.
- Predirs = acc_modules(Modules, preprocess, Config, ModuleSetFile),
+ Predirs = acc_modules(Modules, preprocess, Config0, ModuleSetFile),
SubdirAssoc = remember_cwd_subdir(Dir, Predirs),
%% Get the list of plug-in modules from rebar.config. These
%% modules may participate in preprocess and postprocess.
- {ok, PluginModules} = plugin_modules(Config, SubdirAssoc),
+ {ok, PluginModules} = plugin_modules(Config0, SubdirAssoc),
PluginPredirs = acc_modules(PluginModules, preprocess,
- Config, ModuleSetFile),
+ Config0, ModuleSetFile),
AllPredirs = Predirs ++ PluginPredirs,
?DEBUG("Predirs: ~p\n", [AllPredirs]),
- DirSet2 = process_each(AllPredirs, Command, Config,
+ DirSet2 = process_each(AllPredirs, Command, Config0,
ModuleSetFile, DirSet),
%% Make sure the CWD is reset properly; processing the dirs may have
%% caused it to change
ok = file:set_cwd(Dir),
%% Check that this directory is not on the skip list
- case is_skip_dir(Dir) of
- true ->
- %% Do not execute the command on the directory, as some
- %% module has requested a skip on it.
- ?INFO("Skipping ~s in ~s\n", [Command, Dir]);
+ Config = case is_skip_dir(Dir) of
+ true ->
+ %% Do not execute the command on the directory, as some
+ %% module has requested a skip on it.
+ ?INFO("Skipping ~s in ~s\n", [Command, Dir]),
+ Config0;
- false ->
- %% Execute any before_command plugins on this directory
- execute_pre(Command, PluginModules,
- Config, ModuleSetFile),
+ false ->
+ %% Check for and get command specific environments
+ {Config1, Env} = setup_envs(Config0, Modules),
- %% Execute the current command on this directory
- execute(Command, Modules ++ PluginModules,
- Config, ModuleSetFile),
+ %% Execute any before_command plugins on this directory
+ execute_pre(Command, PluginModules,
+ Config1, ModuleSetFile, Env),
- %% Execute any after_command plugins on this directory
- execute_post(Command, PluginModules,
- Config, ModuleSetFile)
- end,
+ %% Execute the current command on this directory
+ execute(Command, Modules ++ PluginModules,
+ Config1, ModuleSetFile, Env),
+
+ %% Execute any after_command plugins on this directory
+ execute_post(Command, PluginModules,
+ Config1, ModuleSetFile, Env),
+
+ Config1
+ end,
%% Mark the current directory as processed
DirSet3 = sets:add_element(Dir, DirSet2),
@@ -311,22 +317,22 @@ is_dir_type(rel_dir, Dir) ->
is_dir_type(_, _) ->
false.
-execute_pre(Command, Modules, Config, ModuleFile) ->
+execute_pre(Command, Modules, Config, ModuleFile, Env) ->
execute_plugin_hook("pre_", Command, Modules,
- Config, ModuleFile).
+ Config, ModuleFile, Env).
-execute_post(Command, Modules, Config, ModuleFile) ->
+execute_post(Command, Modules, Config, ModuleFile, Env) ->
execute_plugin_hook("post_", Command, Modules,
- Config, ModuleFile).
+ Config, ModuleFile, Env).
-execute_plugin_hook(Hook, Command, Modules, Config, ModuleFile) ->
+execute_plugin_hook(Hook, Command, Modules, Config, ModuleFile, Env) ->
HookFunction = list_to_atom(Hook ++ atom_to_list(Command)),
- execute(HookFunction, Modules, Config, ModuleFile).
+ execute(HookFunction, Modules, Config, ModuleFile, Env).
%%
%% Execute a command across all applicable modules
%%
-execute(Command, Modules, Config, ModuleFile) ->
+execute(Command, Modules, Config, ModuleFile, Env) ->
case select_modules(Modules, Command, []) of
[] ->
Cmd = atom_to_list(Command),
@@ -346,9 +352,6 @@ execute(Command, Modules, Config, ModuleFile) ->
increment_operations(),
- %% Check for and get command specific environments
- Env = setup_envs(Config, Modules),
-
%% Run the available modules
apply_hooks(pre_hooks, Config, Command, Env),
case catch(run_modules(TargetModules, Command,
@@ -443,9 +446,16 @@ apply_hook({Env, {Command, Hook}}) ->
rebar_utils:sh(Hook, [{env, Env}, {abort_on_error, Msg}]).
setup_envs(Config, Modules) ->
- lists:flatten([M:setup_env(Config) ||
- M <- Modules,
- erlang:function_exported(M, setup_env, 1)]).
+ lists:foldl(fun(M, {C,E}=T) ->
+ case erlang:function_exported(M, setup_env, 1) of
+ true ->
+ Env = M:setup_env(C),
+ C1 = rebar_config:set_env(C, M, Env),
+ {C1, E++Env};
+ false ->
+ T
+ end
+ end, {Config, []}, Modules).
acc_modules(Modules, Command, Config, File) ->
acc_modules(select_modules(Modules, Command, []),
Oops, something went wrong.

0 comments on commit 7c418ed

Please sign in to comment.