summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCliff Moon <cliff@moonpolysoft.com>2010-04-28 16:27:54 -0700
committerCliff Moon <cliff@moonpolysoft.com>2010-04-28 16:27:54 -0700
commitc3fe43a0ba1af0ee9172239be0a44662fa392984 (patch)
tree05e56feb06b2cac2eeee19a37c8d457120f51f95 /src
parent87bca27644d4429add86dd274148dda9ae52eed4 (diff)
add new configuration option so_specs which allows multiple drivers to be built in the same project.
Diffstat (limited to 'src')
-rw-r--r--src/rebar_port_compiler.erl44
1 files changed, 26 insertions, 18 deletions
diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl
index dace112..1a72d16 100644
--- a/src/rebar_port_compiler.erl
+++ b/src/rebar_port_compiler.erl
@@ -39,6 +39,9 @@
%%
%% * port_sources - Erlang list of files and/or wildcard strings to be compiled
%%
+%% * so_specs - Erlang list of tuples of the form {"priv/so_name.so", ["c_src/object_file_name.o"]} useful for
+%% building multiple *.so files.
+%%
%% * port_envs - Erlang list of key/value pairs which will control the environment when
%% running the compiler and linker. By default, the following variables
%% are defined:
@@ -92,19 +95,21 @@ compile(Config, AppFile) ->
{NewBins, ExistingBins} = compile_each(Sources, Config, Env, [], []),
%% Construct the driver name and make sure priv/ exists
- SoName = so_name(Config, AppFile),
- ok = filelib:ensure_dir(SoName),
+ SoSpecs = so_specs(Config, AppFile, NewBins ++ ExistingBins),
+ ?INFO("Using specs ~p\n", [SoSpecs]),
+ lists:foreach(fun({SoName,_}) -> ok = filelib:ensure_dir(SoName) end, SoSpecs),
%% Only relink if necessary, given the SoName and list of new binaries
- case needs_link(SoName, NewBins) of
- true ->
- AllBins = string:join(NewBins ++ ExistingBins, " "),
+ lists:foreach(fun({SoName,Bins}) ->
+ case needs_link(SoName, sets:to_list(sets:intersection([sets:from_list(Bins),sets:from_list(NewBins)]))) of
+ true ->
rebar_utils:sh_failfast(?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s",
- [AllBins, SoName]), Env);
- false ->
+ [string:join(Bins, " "), SoName]), Env);
+ false ->
?INFO("Skipping relink of ~s\n", [SoName]),
ok
- end
+ end
+ end, SoSpecs)
end.
clean(Config, AppFile) ->
@@ -113,7 +118,7 @@ clean(Config, AppFile) ->
rebar_file_utils:delete_each([source_to_bin(S) || S <- Sources]),
%% Delete the .so file
- rebar_file_utils:delete_each([so_name(Config, AppFile)]),
+ rebar_file_utils:delete_each(lists:map(fun({SoName,_}) -> SoName end, so_specs(Config, AppFile, expand_objects(Sources)))),
%% Run the cleanup script, if it exists
run_cleanup_hook(Config).
@@ -130,6 +135,11 @@ expand_sources([], Acc) ->
expand_sources([Spec | Rest], Acc) ->
Acc2 = filelib:wildcard(Spec) ++ Acc,
expand_sources(Rest, Acc2).
+
+expand_objects(Sources) ->
+ lists:map(fun(File) ->
+ filename:join([filename:dirname(File),filename:basename(File) ++ ".o"])
+ end, Sources).
run_precompile_hook(Config, Env) ->
case rebar_config:get(Config, port_pre_script, undefined) of
@@ -319,21 +329,19 @@ source_to_bin(Source) ->
Ext = filename:extension(Source),
filename:rootname(Source, Ext) ++ ".o".
-so_name(Config, AppFile) ->
+so_specs(Config, AppFile, Bins) ->
%% Check config to see if a custom so_name has been specified
- PortName = case rebar_config:get(Config, so_name, undefined) of
+ ?INFO("config ~p\n", [Config]),
+ case rebar_config:get(Config, so_specs, undefined) of
undefined ->
%% Get the app name, which we'll use to
%% generate the linked port driver name
case rebar_app_utils:load_app_file(AppFile) of
{ok, AppName, _} ->
- lists:concat([AppName, "_drv.so"]);
+ SoName = ?FMT("priv/~s", [lists:concat([AppName, "_drv.so"])]),
+ [{SoName, Bins}];
error ->
?FAIL
end;
- Soname ->
- Soname
- end,
-
- %% Construct the driver name
- ?FMT("priv/~s", [PortName]).
+ SoSpecs -> SoSpecs
+ end.