Skip to content

Commit

Permalink
Add support for target-specific port options
Browse files Browse the repository at this point in the history
{port_specs, [{".*", "priv/foo.so", ["c_src/foo.c"], [{env, []}]}]}.
  • Loading branch information
Tuncer Ayaz committed Apr 16, 2012
1 parent 2ae73cc commit 7c418ed
Show file tree
Hide file tree
Showing 4 changed files with 268 additions and 217 deletions.
6 changes: 4 additions & 2 deletions rebar.config.sample
Original file line number Diff line number Diff line change
Expand Up @@ -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 ==

Expand Down
25 changes: 20 additions & 5 deletions src/rebar_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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]).
Expand All @@ -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
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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
%% ===================================================================
Expand Down
78 changes: 44 additions & 34 deletions src/rebar_core.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
Expand Down Expand Up @@ -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),
Expand All @@ -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,
Expand Down Expand Up @@ -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, []),
Expand Down
Loading

0 comments on commit 7c418ed

Please sign in to comment.