diff options
Diffstat (limited to 'src/rebar_port_compiler.erl')
-rw-r--r-- | src/rebar_port_compiler.erl | 127 |
1 files changed, 56 insertions, 71 deletions
diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 19c6f79..b9c2ea4 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -38,11 +38,11 @@ %% Supported configuration variables: %% -%% * port_sources - Erlang list of files and/or wildcard strings to be -%% compiled. Platform specific sources can be specified -%% by enclosing a string in a tuple of the form -%% {Regex, String} wherein Regex is a regular expression -%% that is checked against the system architecture. +%% * port_sources - Erlang 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 and a list of +%% filenames or wildcards to include should the expression +%% pass. %% %% * so_specs - Erlang list of tuples of the form %% {"priv/so_name.so", ["c_src/object_file_name.o"]} @@ -62,6 +62,14 @@ %% 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 +%% ERL_EI_LIBDIR - ei library directory +%% CXX_TEMPLATE - C++ command template +%% CC_TEMPLATE - C command template +%% LINK_TEMPLATE - Linker command template +%% PORT_IN_FILES - contains a space separated list of input +%% file(s), (used in command template) +%% PORT_OUT_FILE - contains the output filename (used in +%% command template) %% %% Note that if you wish to extend (vs. replace) these variables, %% you MUST include a shell-style reference in your definition. @@ -97,10 +105,6 @@ compile(Config, AppFile) -> _ -> Env = setup_env(Config), - %% One or more files are available for building. - %% Run the pre-compile hook, if necessary. - ok = run_precompile_hook(Config, Env), - %% Compile each of the sources {NewBins, ExistingBins} = compile_each(Sources, Config, Env, [], []), @@ -116,14 +120,15 @@ compile(Config, AppFile) -> %% and list of new binaries lists:foreach( fun({SoName,Bins}) -> - AllBins = [sets:from_list(Bins), sets:from_list(NewBins)], + AllBins = [sets:from_list(Bins), + sets:from_list(NewBins)], Intersection = sets:intersection(AllBins), case needs_link(SoName, sets:to_list(Intersection)) of true -> - rebar_utils:sh( - ?FMT("$CC ~s $LDFLAGS $DRV_LDFLAGS -o ~s", - [string:join(Bins, " "), SoName]), - [{env, Env}]); + Cmd = expand_command("LINK_TEMPLATE", Env, + string:join(Bins, " "), + SoName), + rebar_utils:sh(Cmd, [{env, Env}]); false -> ?INFO("Skipping relink of ~s\n", [SoName]), ok @@ -141,10 +146,7 @@ clean(Config, AppFile) -> ExtractSoName = fun({SoName, _}) -> SoName end, rebar_file_utils:delete_each([ExtractSoName(S) || S <- so_specs(Config, AppFile, - expand_objects(Sources))]), - - %% Run the cleanup script, if it exists - run_cleanup_hook(Config). + expand_objects(Sources))]). setup_env(Config) -> %% Extract environment values from the config (if specified) and @@ -165,7 +167,7 @@ expand_sources([], Acc) -> expand_sources([{ArchRegex, Spec} | Rest], Acc) -> case rebar_utils:is_arch(ArchRegex) of true -> - Acc2 = filelib:wildcard(Spec) ++ Acc, + Acc2 = expand_sources(Spec, Acc), expand_sources(Rest, Acc2); false -> expand_sources(Rest, Acc) @@ -178,39 +180,6 @@ expand_objects(Sources) -> [filename:join([filename:dirname(F), filename:basename(F) ++ ".o"]) || F <- Sources]. -run_precompile_hook(Config, Env) -> - case rebar_config:get(Config, port_pre_script, undefined) of - undefined -> - ok; - {Script, BypassFileName} -> - ?DEPRECATED(port_pre_script, - {pre_hooks, [{compile, "script"}]}, - "in a future build of rebar"), - case filelib:is_regular(BypassFileName) of - false -> - ?CONSOLE("Running ~s\n", [Script]), - {ok, _} = rebar_utils:sh(Script, [{env, Env}]), - ok; - true -> - ?INFO("~s exists; not running ~s\n", - [BypassFileName, Script]) - end - end. - -run_cleanup_hook(Config) -> - case rebar_config:get(Config, port_cleanup_script, undefined) of - undefined -> - ok; - Script -> - ?DEPRECATED(port_cleanup_script, - {post_hooks, [{clean, "script"}]}, - "in a future build of rebar"), - ?CONSOLE("Running ~s\n", [Script]), - {ok, _} = rebar_utils:sh(Script, []), - ok - end. - - compile_each([], _Config, _Env, NewBins, ExistingBins) -> {lists:reverse(NewBins), lists:reverse(ExistingBins)}; compile_each([Source | Rest], Config, Env, NewBins, ExistingBins) -> @@ -221,12 +190,13 @@ compile_each([Source | Rest], Config, Env, NewBins, ExistingBins) -> ?CONSOLE("Compiling ~s\n", [Source]), case compiler(Ext) of "$CC" -> - rebar_utils:sh(?FMT("$CC -c $CFLAGS $DRV_CFLAGS ~s -o ~s", - [Source, Bin]), [{env, Env}]); + rebar_utils:sh(expand_command("CC_TEMPLATE", Env, + Source, Bin), + [{env, Env}]); "$CXX" -> - rebar_utils:sh( - ?FMT("$CXX -c $CXXFLAGS $DRV_CFLAGS ~s -o ~s", - [Source, Bin]), [{env, Env}]) + rebar_utils:sh(expand_command("CXX_TEMPLATE", Env, + Source, Bin), + [{env, Env}]) end, compile_each(Rest, Config, Env, [Bin | NewBins], ExistingBins); @@ -274,16 +244,17 @@ compiler(_) -> "$CC". %% apply_defaults(Vars, Defaults) -> dict:to_list( - dict:merge(fun(Key, VarValue, DefaultValue) -> - case is_expandable(DefaultValue) of + dict:merge(fun(Key, VarValue, DefaultValue) -> + case is_expandable(DefaultValue) of true -> expand_env_variable(DefaultValue, Key, VarValue); false -> VarValue - end - end, - dict:from_list(Vars), - dict:from_list(Defaults))). + end + end, + dict:from_list(Vars), + dict:from_list(Defaults))). + %% %% 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 @@ -340,6 +311,11 @@ expand_vars(Key, Value, Vars) -> end, [], Vars). +expand_command(TmplName, Env, InFiles, OutFile) -> + Cmd0 = proplists:get_value(TmplName, Env), + Cmd1 = expand_env_variable(Cmd0, "PORT_IN_FILES", InFiles), + Cmd2 = expand_env_variable(Cmd1, "PORT_OUT_FILE", OutFile), + re:replace(Cmd2, "\\\$\\w+|\\\${\\w+}", "", [global, {return, list}]). %% %% Given a string, determine if it is expandable @@ -350,15 +326,17 @@ is_expandable(InStr) -> nomatch -> false end. - %% %% Given env. variable FOO we want to expand all references to %% it in InStr. References can have two forms: $FOO and ${FOO} +%% The end of form $FOO is delimited with whitespace or eol %% expand_env_variable(InStr, VarName, VarValue) -> - R1 = re:replace(InStr, "\\\$" ++ VarName, VarValue), - re:replace(R1, "\\\${" ++ VarName ++ "}", VarValue, [{return, list}]). - + R1 = re:replace(InStr, "\\\$" ++ VarName ++ "\\s", VarValue ++ " ", + [global]), + R2 = re:replace(R1, "\\\$" ++ VarName ++ "\$", VarValue), + re:replace(R2, "\\\${" ++ VarName ++ "}", VarValue, + [global, {return, list}]). %% %% Filter a list of env vars such that only those which match the provided @@ -383,22 +361,29 @@ erts_dir() -> os_env() -> Os = [list_to_tuple(re:split(S, "=", [{return, list}, {parts, 2}])) || S <- os:getenv()], - lists:keydelete([],1,Os). %% Remove Windows current disk and path + %% Drop variables without a name (win32) + [T1 || {K, _V} = T1 <- Os, K =/= []]. default_env() -> [ + {"CXX_TEMPLATE", + "$CXX -c $CXXFLAGS $DRV_CFLAGS $PORT_IN_FILES -o $PORT_OUT_FILE"}, + {"CC_TEMPLATE", + "$CC -c $CFLAGS $DRV_CFLAGS $PORT_IN_FILES -o $PORT_OUT_FILE"}, + {"LINK_TEMPLATE", + "$CC $PORT_IN_FILES $LDFLAGS $DRV_LDFLAGS -o $PORT_OUT_FILE"}, {"CC", "cc"}, {"CXX", "c++"}, {"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"])}, + {"ERL_LDFLAGS", " -L$ERL_EI_LIBDIR -lerl_interface -lei"}, {"DRV_CFLAGS", "-g -Wall -fPIC $ERL_CFLAGS"}, {"DRV_LDFLAGS", "-shared $ERL_LDFLAGS"}, + {"ERL_EI_LIBDIR", code:lib_dir(erl_interface, lib)}, {"darwin", "DRV_LDFLAGS", "-bundle -flat_namespace -undefined suppress $ERL_LDFLAGS"}, - {"ERLANG_ARCH", integer_to_list(8 * erlang:system_info(wordsize))}, + {"ERLANG_ARCH", rebar_utils:wordsize()}, {"ERLANG_TARGET", rebar_utils:get_arch()}, %% Solaris specific flags |