diff options
Diffstat (limited to 'src/rebar_port_compiler.erl')
-rw-r--r-- | src/rebar_port_compiler.erl | 228 |
1 files changed, 70 insertions, 158 deletions
diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 22acff6..91b2cac 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -86,37 +86,21 @@ %% "$CFLAGS -X86Options"}]} %% -%% TODO: reconsider keeping both sources and objects once -%% support for deprecated options has been remove. -%% remove [] as valid value for sources, objects, and opts -%% when removing deprecated options. -record(spec, {type::'drv' | 'exe', target::file:filename(), - sources = [] :: [file:filename(), ...] | [], - objects = [] :: [file:filename(), ...] | [], + sources = [] :: [file:filename(), ...], + objects = [] :: [file:filename(), ...], opts = [] ::list() | []}). -compile(Config, AppFile) -> - rebar_utils:deprecated(port_sources, port_specs, Config, "soon"), - rebar_utils:deprecated(so_name, port_specs, Config, "soon"), - rebar_utils:deprecated(so_specs, port_specs, Config, "soon"), - - %% TODO: remove SpecType and OldSources make get_specs/2 - %% return list(#spec{}) when removing deprecated options - {SpecType, {OldSources, Specs}} = get_specs(Config, AppFile), - - case {SpecType, OldSources, Specs} of - {old, [], _} -> - ok; % old specs empty - {new, [], []} -> - ok; % port_specs empty - - _ -> % have old/new specs - +compile(Config, _AppFile) -> + case get_specs(Config) of + [] -> + ok; + Specs -> SharedEnv = rebar_config:get_env(Config, ?MODULE), %% Compile each of the sources - NewBins = compile_sources(OldSources, Specs, SharedEnv), + NewBins = compile_sources(Config, Specs, SharedEnv), %% Make sure that the target directories exist ?INFO("Using specs ~p\n", [Specs]), @@ -146,24 +130,17 @@ compile(Config, AppFile) -> end, Specs) end. -clean(Config, AppFile) -> - %% TODO: remove SpecType and OldSources make get_specs/2 - %% return list(#spec{}) when removing deprecated options - {SpecType, {OldSources, Specs}} = get_specs(Config, AppFile), - - case {SpecType, OldSources, Specs} of - {old, [], _} -> - ok; % old specs empty - {new, [], []} -> - ok; % port_specs empty - - _ -> % have old/new specs - +clean(Config, _AppFile) -> + case get_specs(Config) of + [] -> + ok; + Specs -> lists:foreach(fun(#spec{target=Target, objects=Objects}) -> rebar_file_utils:delete_each([Target]), rebar_file_utils:delete_each(Objects) end, Specs) - end. + end, + ok. setup_env(Config) -> setup_env(Config, []). @@ -177,15 +154,17 @@ setup_env(Config, ExtraEnv) -> %% merge with the default for this operating system. This enables %% max flexibility for users. DefaultEnv = filter_env(default_env(), []), - PortEnv = filter_env(port_env(Config), []), - OverrideEnv = global_defines() ++ PortEnv ++ filter_env(ExtraEnv, []), + RawPortEnv = rebar_config:get_list(Config, port_env, []), + PortEnv = filter_env(RawPortEnv, []), + Defines = get_defines(Config), + OverrideEnv = Defines ++ PortEnv ++ filter_env(ExtraEnv, []), RawEnv = apply_defaults(os_env(), DefaultEnv) ++ OverrideEnv, expand_vars_loop(merge_each_var(RawEnv, [])). -global_defines() -> - Defines = rebar_config:get_global(defines, []), - Flags = string:join(["-D" ++ D || D <- Defines], " "), - [{"ERL_CFLAGS", "$ERL_CFLAGS " ++ Flags}]. +get_defines(Config) -> + RawDefines = rebar_config:get_xconf(Config, defines, []), + Defines = string:join(["-D" ++ D || D <- RawDefines], " "), + [{"ERL_CFLAGS", "$ERL_CFLAGS " ++ Defines}]. replace_extension(File, NewExt) -> OldExt = filename:extension(File), @@ -198,18 +177,16 @@ replace_extension(File, OldExt, NewExt) -> %% == compile and link == %% -compile_sources([], Specs, SharedEnv) -> % port_spec +compile_sources(Config, Specs, SharedEnv) -> lists:foldl( fun(#spec{sources=Sources, type=Type, opts=Opts}, NewBins) -> Env = proplists:get_value(env, Opts, SharedEnv), - compile_each(Sources, Type, Env, NewBins) - end, [], Specs); -compile_sources(OldSources, _Specs, SharedEnv) -> % deprecated - compile_each(OldSources, drv, SharedEnv, []). + compile_each(Config, Sources, Type, Env, NewBins) + end, [], Specs). -compile_each([], _Type, _Env, NewBins) -> +compile_each(_Config, [], _Type, _Env, NewBins) -> lists:reverse(NewBins); -compile_each([Source | Rest], Type, Env, NewBins) -> +compile_each(Config, [Source | Rest], Type, Env, NewBins) -> Ext = filename:extension(Source), Bin = replace_extension(Source, Ext, ".o"), case needs_compile(Source, Bin) of @@ -217,22 +194,27 @@ compile_each([Source | Rest], Type, Env, NewBins) -> Template = select_compile_template(Type, compiler(Ext)), Cmd = expand_command(Template, Env, Source, Bin), ShOpts = [{env, Env}, return_on_error, {use_stdout, false}], - exec_compiler(Source, Cmd, ShOpts), - compile_each(Rest, Type, Env, [Bin | NewBins]); + exec_compiler(Config, Source, Cmd, ShOpts), + compile_each(Config, Rest, Type, Env, [Bin | NewBins]); false -> ?INFO("Skipping ~s\n", [Source]), - compile_each(Rest, Type, Env, NewBins) + compile_each(Config, Rest, Type, Env, NewBins) end. -exec_compiler(Source, Cmd, ShOpts) -> +exec_compiler(Config, Source, Cmd, ShOpts) -> case rebar_utils:sh(Cmd, ShOpts) of {error, {_RC, RawError}} -> - AbsSource = filename:absname(Source), + AbsSource = case rebar_utils:processing_base_dir(Config) of + true -> + Source; + false -> + filename:absname(Source) + end, ?CONSOLE("Compiling ~s\n", [AbsSource]), Error = re:replace(RawError, Source, AbsSource, [{return, list}, global]), ?CONSOLE("~s", [Error]), - ?ABORT; + ?FAIL; {ok, Output} -> ?CONSOLE("Compiling ~s\n", [Source]), ?CONSOLE("~s", [Output]) @@ -260,19 +242,11 @@ needs_link(SoName, NewBins) -> %% == port_specs == %% -get_specs(Config, AppFile) -> - case rebar_config:get_local(Config, port_specs, undefined) of - undefined -> - %% TODO: DEPRECATED: remove support for non-port_specs syntax - {old, old_get_specs(Config, AppFile)}; - PortSpecs -> - {new, get_port_specs(Config, PortSpecs)} - end. - -get_port_specs(Config, PortSpecs) -> +get_specs(Config) -> + PortSpecs = rebar_config:get_local(Config, port_specs, []), Filtered = filter_port_specs(PortSpecs), OsType = os:type(), - {[], [get_port_spec(Config, OsType, Spec) || Spec <- Filtered]}. + [get_port_spec(Config, OsType, Spec) || Spec <- Filtered]. filter_port_specs(Specs) -> [S || S <- Specs, filter_port_spec(S)]. @@ -323,58 +297,6 @@ switch_to_dll_or_exe(Target) -> _Other -> Target end. -%% TODO: DEPRECATED: remove support for non-port_specs syntax [old_*()] -old_get_specs(Config, AppFile) -> - OsType = os:type(), - SourceFiles = old_get_sources(Config), - Specs = - case rebar_config:get_local(Config, so_specs, undefined) of - undefined -> - Objects = port_objects(SourceFiles), - %% New form of so_specs is not provided. See if the old form - %% of {so_name} is available instead - Dir = "priv", - SoName = - case rebar_config:get_local(Config, so_name, undefined) of - undefined -> - %% Ok, neither old nor new form is - %% available. Use the app name and - %% generate a sensible default. - AppName = rebar_app_utils:app_name(AppFile), - DrvName = ?FMT("~s_drv.so", [AppName]), - filename:join([Dir, DrvName]); - AName -> - %% Old form is available -- use it - filename:join(Dir, AName) - end, - [old_get_so_spec({SoName, Objects}, OsType)]; - SoSpecs -> - [old_get_so_spec(S, OsType) || S <- SoSpecs] - end, - {SourceFiles, Specs}. - -old_get_sources(Config) -> - RawSources = rebar_config:get_local(Config, port_sources, - ["c_src/*.c"]), - FilteredSources = old_filter_port_sources(RawSources), - old_expand_sources(FilteredSources). - -old_filter_port_sources(PortSources) -> - [S || S <- PortSources, old_is_arch_port_sources(S)]. - -old_is_arch_port_sources({Arch, _Sources}) -> rebar_utils:is_arch(Arch); -old_is_arch_port_sources(_Sources) -> true. - -old_expand_sources(Sources) -> - lists:flatmap(fun filelib:wildcard/1, Sources). - -old_get_so_spec({Target, Objects}, OsType) -> - #spec{type=drv, - target=maybe_switch_extension(OsType, Target), - sources=[], - objects=Objects, - opts=[]}. - %% %% == port_env == %% @@ -498,35 +420,6 @@ is_expandable(InStr) -> nomatch -> false end. -port_env(Config) -> - %% TODO: remove support for deprecated port_envs option - PortEnv = rebar_utils:get_deprecated_list(Config, port_envs, port_env, - [], "soon"), - %% TODO: remove migration of deprecated port_env DRV_-/EXE_-less vars - %% when the deprecation grace period ends - WarnAndConvertVar = fun(Var) -> - New = "DRV_" ++ Var, - rebar_utils:deprecated(Var, New, "soon"), - New - end, - ConvertVar = fun(Var="CXX_TEMPLATE") -> WarnAndConvertVar(Var); - (Var="CC_TEMPLATE") -> WarnAndConvertVar(Var); - (Var="LINK_TEMPLATE") -> WarnAndConvertVar(Var); - (Var) -> Var - end, - %% Also warn about references to deprecated vars? omitted for - %% performance reasons. - ReplaceVars = fun(Val) -> - re:replace(Val, "\\$(CXX|CC|LINK)(_TEMPLATE)", - "DRV_\\1\\2", [{return,list}, global]) - end, - Convert = fun({ArchRegex, Var, Val}) -> - {ArchRegex, ConvertVar(Var), ReplaceVars(Val)}; - ({Var, Val}) -> - {ConvertVar(Var), ReplaceVars(Val)} - end, - [Convert(EnvVar) || EnvVar <- PortEnv]. - %% %% Filter a list of env vars such that only those which match the provided %% architecture regex (or do not have a regex) are returned. @@ -626,13 +519,32 @@ default_env() -> {"darwin9.*-64$", "CXXFLAGS", "-m64 $CXXFLAGS"}, {"darwin9.*-64$", "LDFLAGS", "-arch x86_64 $LDFLAGS"}, - %% OS X Snow Leopard flags for 32-bit - {"darwin10.*-32", "CFLAGS", "-m32 $CFLAGS"}, - {"darwin10.*-32", "CXXFLAGS", "-m32 $CXXFLAGS"}, - {"darwin10.*-32", "LDFLAGS", "-arch i386 $LDFLAGS"}, - - %% OS X Lion flags for 32-bit - {"darwin11.*-32", "CFLAGS", "-m32 $CFLAGS"}, - {"darwin11.*-32", "CXXFLAGS", "-m32 $CXXFLAGS"}, - {"darwin11.*-32", "LDFLAGS", "-arch i386 $LDFLAGS"} + %% OS X Snow Leopard, Lion, and Mountain Lion flags for 32-bit + {"darwin1[0-2].*-32", "CFLAGS", "-m32 $CFLAGS"}, + {"darwin1[0-2].*-32", "CXXFLAGS", "-m32 $CXXFLAGS"}, + {"darwin1[0-2].*-32", "LDFLAGS", "-arch i386 $LDFLAGS"}, + + %% Windows specific flags + %% add MS Visual C++ support to rebar on Windows + {"win32", "CC", "cl.exe"}, + {"win32", "CXX", "cl.exe"}, + {"win32", "LINKER", "link.exe"}, + {"win32", "DRV_CXX_TEMPLATE", + %% DRV_* and EXE_* Templates are identical + "$CXX /c $CXXFLAGS $DRV_CFLAGS $PORT_IN_FILES /Fo$PORT_OUT_FILE"}, + {"win32", "DRV_CC_TEMPLATE", + "$CC /c $CFLAGS $DRV_CFLAGS $PORT_IN_FILES /Fo$PORT_OUT_FILE"}, + {"win32", "DRV_LINK_TEMPLATE", + "$LINKER $PORT_IN_FILES $LDFLAGS $DRV_LDFLAGS /OUT:$PORT_OUT_FILE"}, + %% DRV_* and EXE_* Templates are identical + {"win32", "EXE_CXX_TEMPLATE", + "$CXX /c $CXXFLAGS $EXE_CFLAGS $PORT_IN_FILES /Fo$PORT_OUT_FILE"}, + {"win32", "EXE_CC_TEMPLATE", + "$CC /c $CFLAGS $EXE_CFLAGS $PORT_IN_FILES /Fo$PORT_OUT_FILE"}, + {"win32", "EXE_LINK_TEMPLATE", + "$LINKER $PORT_IN_FILES $LDFLAGS $EXE_LDFLAGS /OUT:$PORT_OUT_FILE"}, + %% ERL_CFLAGS are ok as -I even though strictly it should be /I + {"win32", "ERL_LDFLAGS", " /LIBPATH:$ERL_EI_LIBDIR erl_interface.lib ei.lib"}, + {"win32", "DRV_CFLAGS", "/Zi /Wall $ERL_CFLAGS"}, + {"win32", "DRV_LDFLAGS", "/DLL $ERL_LDFLAGS"} ]. |