add new configuration option so_specs which allows multiple drivers to be built in the same project.

This commit is contained in:
Cliff Moon 2010-04-28 16:27:54 -07:00
parent 87bca27644
commit c3fe43a0ba

View file

@ -39,6 +39,9 @@
%% %%
%% * port_sources - Erlang list of files and/or wildcard strings to be compiled %% * 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 %% * port_envs - Erlang list of key/value pairs which will control the environment when
%% running the compiler and linker. By default, the following variables %% running the compiler and linker. By default, the following variables
%% are defined: %% are defined:
@ -92,19 +95,21 @@ compile(Config, AppFile) ->
{NewBins, ExistingBins} = compile_each(Sources, Config, Env, [], []), {NewBins, ExistingBins} = compile_each(Sources, Config, Env, [], []),
%% Construct the driver name and make sure priv/ exists %% Construct the driver name and make sure priv/ exists
SoName = so_name(Config, AppFile), SoSpecs = so_specs(Config, AppFile, NewBins ++ ExistingBins),
ok = filelib:ensure_dir(SoName), ?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 %% Only relink if necessary, given the SoName and list of new binaries
case needs_link(SoName, NewBins) of lists:foreach(fun({SoName,Bins}) ->
true -> case needs_link(SoName, sets:to_list(sets:intersection([sets:from_list(Bins),sets:from_list(NewBins)]))) of
AllBins = string:join(NewBins ++ ExistingBins, " "), true ->
rebar_utils:sh_failfast(?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s", rebar_utils:sh_failfast(?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s",
[AllBins, SoName]), Env); [string:join(Bins, " "), SoName]), Env);
false -> false ->
?INFO("Skipping relink of ~s\n", [SoName]), ?INFO("Skipping relink of ~s\n", [SoName]),
ok ok
end end
end, SoSpecs)
end. end.
clean(Config, AppFile) -> clean(Config, AppFile) ->
@ -113,7 +118,7 @@ clean(Config, AppFile) ->
rebar_file_utils:delete_each([source_to_bin(S) || S <- Sources]), rebar_file_utils:delete_each([source_to_bin(S) || S <- Sources]),
%% Delete the .so file %% 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 the cleanup script, if it exists
run_cleanup_hook(Config). run_cleanup_hook(Config).
@ -131,6 +136,11 @@ expand_sources([Spec | Rest], Acc) ->
Acc2 = filelib:wildcard(Spec) ++ Acc, Acc2 = filelib:wildcard(Spec) ++ Acc,
expand_sources(Rest, Acc2). 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) -> run_precompile_hook(Config, Env) ->
case rebar_config:get(Config, port_pre_script, undefined) of case rebar_config:get(Config, port_pre_script, undefined) of
undefined -> undefined ->
@ -319,21 +329,19 @@ source_to_bin(Source) ->
Ext = filename:extension(Source), Ext = filename:extension(Source),
filename:rootname(Source, Ext) ++ ".o". 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 %% 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 -> undefined ->
%% Get the app name, which we'll use to %% Get the app name, which we'll use to
%% generate the linked port driver name %% generate the linked port driver name
case rebar_app_utils:load_app_file(AppFile) of case rebar_app_utils:load_app_file(AppFile) of
{ok, AppName, _} -> {ok, AppName, _} ->
lists:concat([AppName, "_drv.so"]); SoName = ?FMT("priv/~s", [lists:concat([AppName, "_drv.so"])]),
[{SoName, Bins}];
error -> error ->
?FAIL ?FAIL
end; end;
Soname -> SoSpecs -> SoSpecs
Soname end.
end,
%% Construct the driver name
?FMT("priv/~s", [PortName]).