diff options
author | Tuncer Ayaz <tuncer.ayaz@gmail.com> | 2015-07-02 13:45:35 +0200 |
---|---|---|
committer | Tuncer Ayaz <tuncer.ayaz@gmail.com> | 2015-07-02 19:50:16 +0200 |
commit | 9a64826172ade12997e8ee0ff32df52757c43025 (patch) | |
tree | 464aa2f93fd4ea611d7b6907704dbe2b9bf8140b | |
parent | 49fd99c7011191ae9fe499f03c8070faf0bb41ba (diff) | |
download | rebar-9a64826172ade12997e8ee0ff32df52757c43025.tar.gz |
cross-arch: fix up issues
* fix commit messages
* fix whitespace issues
* move internal helper functions to correct location
* unexport internal cross arch helper functions
* fix 18.0 time API compatibility
* fix Windows temp dir detection
* use correct helper function name
* use sh/2 instead of os:cmd/1
* match file:delete/1 result
* use logging macros
* fix typo
* fix Dialyzer warnings
* add Tony Rogvall to THANKS
* add missing termination clause
* os type must be win32, not windows
* match file:write_file/2 result
* document cross-arch variables
* simplify env_wordsize/1 (Thanks Fred Hebert)
-rw-r--r-- | THANKS | 1 | ||||
-rw-r--r-- | rebar.config | 3 | ||||
-rw-r--r-- | src/rebar_port_compiler.erl | 59 | ||||
-rw-r--r-- | src/rebar_utils.erl | 265 |
4 files changed, 183 insertions, 145 deletions
@@ -142,3 +142,4 @@ Derek Brown Danil Onishchenko Stavros Aronis James Fish +Tony Rogvall diff --git a/rebar.config b/rebar.config index a3849ec..bcd5368 100644 --- a/rebar.config +++ b/rebar.config @@ -29,7 +29,8 @@ - (\"gpb_compile\":\"format_error\"/\"1\") - (\"diameter_codegen\":\"from_dict\"/\"4\") - (\"diameter_dict_util\":\"format_error\"/\"1\") - - (\"diameter_dict_util\":\"parse\"/\"2\"))", + - (\"diameter_dict_util\":\"parse\"/\"2\") + - (\"erlang\":\"timestamp\"/\"0\"))", []}]}. {dialyzer, diff --git a/src/rebar_port_compiler.erl b/src/rebar_port_compiler.erl index 84cf49b..dcd8a20 100644 --- a/src/rebar_port_compiler.erl +++ b/src/rebar_port_compiler.erl @@ -165,7 +165,14 @@ info_help(Description) -> "~n" "Valid rebar.config options:~n" " ~p~n" - " ~p~n", + " ~p~n" + "Cross-arch environment variables:~n" + " REBAR_TARGET_ARCH to set the tool chain name to use~n" + " REBAR_TARGET_ARCH_WORDSIZE optional " + "(if CC fails to determine word size)~n" + " fallback word size is 32~n" + " REBAR_TARGET_ARCH_VSN optional " + "(if a special version of CC/CXX is requested)~n", [ Description, {port_env, [{"CFLAGS", "$CFLAGS -Ifoo"}, @@ -183,8 +190,10 @@ setup_env(Config, ExtraEnv) -> %% Get any port-specific envs; use port_env first and then fallback %% to port_envs for compatibility - RawPortEnv = rebar_config:get_list(Config, port_env, - rebar_config:get_list(Config, port_envs, [])), + RawPortEnv = rebar_config:get_list( + Config, + port_env, + rebar_config:get_list(Config, port_envs, [])), PortEnv = filter_env(RawPortEnv, []), Defines = get_defines(Config), @@ -571,17 +580,17 @@ default_env() -> Arch = os:getenv("REBAR_TARGET_ARCH"), Vsn = os:getenv("REBAR_TARGET_ARCH_VSN"), [ - {"CC" , get_tool(Arch,Vsn,"gcc","cc")}, - {"CXX", get_tool(Arch,Vsn,"g++","c++")}, - {"AR" , get_tool(Arch,"ar","ar")}, - {"AS" , get_tool(Arch,"as","as")}, - {"CPP" , get_tool(Arch,Vsn,"cpp","cpp")}, - {"LD" , get_tool(Arch,"ld","ld")}, - {"RANLIB" , get_tool(Arch,Vsn,"ranlib","ranlib")}, - {"STRIP" , get_tool(Arch,"strip","strip")}, - {"NM" , get_tool(Arch,"nm","nm")}, - {"OBJCOPY" , get_tool(Arch,"objcopy","objcopy")}, - {"OBJDUMP" , get_tool(Arch,"objdump","objdump")}, + {"CC", get_tool(Arch, Vsn,"gcc", "cc")}, + {"CXX", get_tool(Arch, Vsn,"g++", "c++")}, + {"AR", get_tool(Arch, "ar", "ar")}, + {"AS", get_tool(Arch, "as", "as")}, + {"CPP", get_tool(Arch, Vsn, "cpp", "cpp")}, + {"LD", get_tool(Arch, "ld", "ld")}, + {"RANLIB", get_tool(Arch, Vsn, "ranlib", "ranlib")}, + {"STRIP", get_tool(Arch, "strip", "strip")}, + {"NM", get_tool(Arch, "nm", "nm")}, + {"OBJCOPY", get_tool(Arch, "objcopy", "objcopy")}, + {"OBJDUMP", get_tool(Arch, "objdump", "objdump")}, {"DRV_CXX_TEMPLATE", "$CXX -c $CXXFLAGS $DRV_CFLAGS $PORT_IN_FILES -o $PORT_OUT_FILE"}, @@ -600,9 +609,12 @@ default_env() -> {"EXE_CFLAGS" , "-g -Wall -fPIC -MMD $ERL_CFLAGS"}, {"EXE_LDFLAGS", "$ERL_LDFLAGS"}, - {"ERL_CFLAGS", lists:concat([" -I\"", erl_interface_dir(include), - "\" -I\"", filename:join(erts_dir(), "include"), - "\" "])}, + {"ERL_CFLAGS", lists:concat( + [ + " -I\"", erl_interface_dir(include), + "\" -I\"", filename:join(erts_dir(), "include"), + "\" " + ])}, {"ERL_EI_LIBDIR", lists:concat(["\"", erl_interface_dir(lib), "\""])}, {"ERL_LDFLAGS" , " -L$ERL_EI_LIBDIR -lerl_interface -lei"}, {"ERLANG_ARCH" , rebar_utils:wordsize()}, @@ -651,20 +663,17 @@ default_env() -> {"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", "ERL_LDFLAGS", + " /LIBPATH:$ERL_EI_LIBDIR erl_interface.lib ei.lib"}, {"win32", "DRV_CFLAGS", "/Zi /Wall $ERL_CFLAGS"}, {"win32", "DRV_LDFLAGS", "/DLL $ERL_LDFLAGS"} ]. -get_tool(Arch,Tool,Default) -> - get_tool(Arch,false,Tool,Default). +get_tool(Arch, Tool, Default) -> + get_tool(Arch, false, Tool, Default). get_tool(false, _, _, Default) -> Default; -get_tool("",_,_, Default) -> Default; +get_tool("", _, _, Default) -> Default; get_tool(Arch, false, Tool, _Default) -> Arch++"-"++Tool; get_tool(Arch, "", Tool, _Default) -> Arch++"-"++Tool; get_tool(Arch, Vsn, Tool, _Default) -> Arch++"-"++Tool++"-"++Vsn. - - - - diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 31ccb3f..045e67b 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -67,12 +67,7 @@ processing_base_dir/1, processing_base_dir/2, patch_env/2, - cleanup_code_path/1, - cross_wordsize/1, - native_wordsize/0, - wordsize/1, - cross_sizeof/2, - env_wordsize/1 + cleanup_code_path/1 ]). %% for internal use only @@ -98,9 +93,9 @@ is_arch(ArchRegex) -> false end. %% -%% REBAR_TARGET_ARCH, if used, should be set to the "standard" +%% REBAR_TARGET_ARCH, if used, should be set to the "standard" %% target string. That is a prefix for binutils tools. -%% "x86_64-linux-gnu" or "arm-linux-gnueabi" are good candiates +%% "x86_64-linux-gnu" or "arm-linux-gnueabi" are good candidates %% ${REBAR_TARGET_ARCH}-gcc, ${REBAR_TARGET_ARCH}-ld ... %% get_arch() -> @@ -116,117 +111,6 @@ get_system_arch(Arch) -> wordsize() -> wordsize(os:getenv("REBAR_TARGET_ARCH")). -wordsize(Arch) when Arch =:= false; Arch =:= "" -> - native_wordsize(); -wordsize(Arch) -> - case match_wordsize(Arch, [{"i686","32"}, {"i386","32"}, - {"arm","32"}, {"aarch64", "64"}, - {"x86_64","64"}]) of - false -> - case cross_wordsize(Arch) of - "" -> - env_wordsize(os:getenv("REBAR_TARGET_ARCH_WORDSIZE")); - WordSize -> WordSize - end; - {_, Wordsize} -> - Wordsize - end. - -match_wordsize(Arch, [V={Match,_Bits}|Vs]) -> - case re:run(Arch, Match, [{capture, none}]) of - match -> V; - _ -> - match_wordsize(Arch, Vs) - end. - -env_wordsize(Wordsize) when Wordsize =:= false; - Wordsize =:= "" -> - io:format("REBAR_TARGET_ARCH_WORDSIZE not set, assuming 32\n"), - "32"; -env_wordsize(Wordsize) -> - try list_to_integer(Wordsize) of - 16 -> "16"; - 32 -> "32"; - 64 -> "64"; - _ -> - io:format("REBAR_TARGET_ARCH_WORDSIZE bad value: ~p\n", [Wordsize]), - "32" - catch - error:_ -> - io:format("REBAR_TARGET_ARCH_WORDSIZE bad value: ~p\n", [Wordsize]), - "32" - end. - -%% -%% Findout the word size of the target by using Arch-gcc -%% - -cross_wordsize(Arch) -> - cross_sizeof(Arch, "void*"). - -%% -%% Find the size of target Type using a specially crafted C file -%% that will report an error on the line of the byte size of the type. -%% - -cross_sizeof(Arch, Type) -> - Compiler = if Arch =:= "" -> "cc"; - true -> Arch ++ "-gcc" - end, - TempFile = mktemp(".c"), - file:write_file(TempFile, - <<"int t01 [1 - 2*(((long) (sizeof (TYPE))) == 1)];\n" - "int t02 [1 - 2*(((long) (sizeof (TYPE))) == 2)];\n" - "int t03 [1 - 2*(((long) (sizeof (TYPE))) == 3)];\n" - "int t04 [1 - 2*(((long) (sizeof (TYPE))) == 4)];\n" - "int t05 [1 - 2*(((long) (sizeof (TYPE))) == 5)];\n" - "int t06 [1 - 2*(((long) (sizeof (TYPE))) == 6)];\n" - "int t07 [1 - 2*(((long) (sizeof (TYPE))) == 7)];\n" - "int t08 [1 - 2*(((long) (sizeof (TYPE))) == 8)];\n" - "int t09 [1 - 2*(((long) (sizeof (TYPE))) == 9)];\n" - "int t10 [1 - 2*(((long) (sizeof (TYPE))) == 10)];\n" - "int t11 [1 - 2*(((long) (sizeof (TYPE))) == 11)];\n" - "int t12 [1 - 2*(((long) (sizeof (TYPE))) == 12)];\n" - "int t13 [1 - 2*(((long) (sizeof (TYPE))) == 13)];\n" - "int t14 [1 - 2*(((long) (sizeof (TYPE))) == 14)];\n" - "int t15 [1 - 2*(((long) (sizeof (TYPE))) == 15)];\n" - "int t16 [1 - 2*(((long) (sizeof (TYPE))) == 16)];\n" - >>), - Res = os:cmd(Compiler ++ " -DTYPE=\""++Type++"\" " ++ TempFile), - file:delete(TempFile), - case string:tokens(Res, ":") of - [_,Ln | _] -> - try list_to_integer(Ln) of - NumBytes -> integer_to_list(NumBytes*8) - catch - error:_ -> - "" - end; - _ -> - "" - end. - -mktemp(Suffix) -> - {A,B,C} = erlang:now(), - Dir = case os:type() of - {windows,_} -> "C:/WINDOWS/TEMP"; - _ -> "/tmp" - end, - File = "rebar_"++os:getpid()++ - integer_to_list(A)++"_"++ - integer_to_list(B)++"_"++ - integer_to_list(C)++Suffix, - filename:join(Dir,File). - -native_wordsize() -> - try erlang:system_info({wordsize, external}) of - Val -> - integer_to_list(8 * Val) - catch - error:badarg -> - integer_to_list(8 * erlang:system_info(wordsize)) - end. - sh_send(Command0, String, Options0) -> ?INFO("sh_send info:\n\tcwd: ~p\n\tcmd: ~s < ~s\n", [get_cwd(), Command0, String]), @@ -794,3 +678,146 @@ cleanup_code_path(OrigPath) -> _ -> code:set_path(OrigPath) end. + +wordsize(Arch) when Arch =:= false; Arch =:= "" -> + native_wordsize(); +wordsize(Arch) -> + AllArchs = [ + {"i686","32"}, + {"i386","32"}, + {"arm","32"}, + {"aarch64", "64"}, + {"x86_64","64"} + ], + case match_wordsize(Arch, AllArchs) of + false -> + case cross_wordsize(Arch) of + "" -> + env_wordsize(os:getenv("REBAR_TARGET_ARCH_WORDSIZE")); + WordSize -> + WordSize + end; + {_, Wordsize} -> + Wordsize + end. + +match_wordsize(Arch, [V={Match,_Bits}|Vs]) -> + case re:run(Arch, Match, [{capture, none}]) of + match -> + V; + nomatch -> + match_wordsize(Arch, Vs) + end; +match_wordsize(_Arch, []) -> + false. + +env_wordsize(Wordsize) when Wordsize =:= false; + Wordsize =:= "" -> + ?WARN("REBAR_TARGET_ARCH_WORDSIZE not set, assuming 32\n", []), + "32"; +env_wordsize(Wordsize) -> + case Wordsize of + "16" -> Wordsize; + "32" -> Wordsize; + "64" -> Wordsize; + _ -> + ?WARN("REBAR_TARGET_ARCH_WORDSIZE bad value: ~p\n", [Wordsize]), + "32" + end. + +%% +%% Find out the word size of the target by using Arch-gcc +%% +cross_wordsize(Arch) -> + cross_sizeof(Arch, "void*"). + +%% +%% Find the size of target Type using a specially crafted C file +%% that will report an error on the line of the byte size of the type. +%% +cross_sizeof(Arch, Type) -> + Compiler = if Arch =:= "" -> "cc"; + true -> Arch ++ "-gcc" + end, + TempFile = mktempfile(".c"), + ok = file:write_file(TempFile, + <<"int t01 [1 - 2*(((long) (sizeof (TYPE))) == 1)];\n" + "int t02 [1 - 2*(((long) (sizeof (TYPE))) == 2)];\n" + "int t03 [1 - 2*(((long) (sizeof (TYPE))) == 3)];\n" + "int t04 [1 - 2*(((long) (sizeof (TYPE))) == 4)];\n" + "int t05 [1 - 2*(((long) (sizeof (TYPE))) == 5)];\n" + "int t06 [1 - 2*(((long) (sizeof (TYPE))) == 6)];\n" + "int t07 [1 - 2*(((long) (sizeof (TYPE))) == 7)];\n" + "int t08 [1 - 2*(((long) (sizeof (TYPE))) == 8)];\n" + "int t09 [1 - 2*(((long) (sizeof (TYPE))) == 9)];\n" + "int t10 [1 - 2*(((long) (sizeof (TYPE))) == 10)];\n" + "int t11 [1 - 2*(((long) (sizeof (TYPE))) == 11)];\n" + "int t12 [1 - 2*(((long) (sizeof (TYPE))) == 12)];\n" + "int t13 [1 - 2*(((long) (sizeof (TYPE))) == 13)];\n" + "int t14 [1 - 2*(((long) (sizeof (TYPE))) == 14)];\n" + "int t15 [1 - 2*(((long) (sizeof (TYPE))) == 15)];\n" + "int t16 [1 - 2*(((long) (sizeof (TYPE))) == 16)];\n" + >>), + Cmd = Compiler ++ " -DTYPE=\""++Type++"\" " ++ TempFile, + ShOpts = [{use_stdout, false}, return_on_error], + {ok, Res} = sh(Cmd, ShOpts), + ok = file:delete(TempFile), + case string:tokens(Res, ":") of + [_, Ln | _] -> + try list_to_integer(Ln) of + NumBytes -> integer_to_list(NumBytes*8) + catch + error:_ -> + "" + end; + _ -> + "" + end. + +mktempfile(Suffix) -> + {A,B,C} = rebar_now(), + Dir = temp_dir(), + File = "rebar_"++os:getpid()++ + integer_to_list(A)++"_"++ + integer_to_list(B)++"_"++ + integer_to_list(C)++Suffix, + filename:join(Dir, File). + +temp_dir() -> + case os:type() of + {win32, _} -> windows_temp_dir(); + _ -> "/tmp" + end. + +windows_temp_dir() -> + case os:getenv("TEMP") of + false -> + case os:getenv("TMP") of + false -> "C:/WINDOWS/TEMP"; + TMP -> TMP + end; + TEMP -> TEMP + end. + +rebar_now() -> + case erlang:function_exported(erlang, timestamp, 0) of + true -> + erlang:timestamp(); + false -> + %% erlang:now/0 was deprecated in 18.0, and as the escript has to + %% pass erl_lint:module/1 (even without -mode(compile)), we would + %% see a deprecation warning for erlang:now/0. One solution is to + %% use -compile({nowarn_deprecated_function, [{erlang, now, 0}]}), + %% but that would raise a warning in versions older than 18.0. + %% Calling erlang:now/0 via apply/3 avoids that. + apply(erlang, now, []) + end. + +native_wordsize() -> + try erlang:system_info({wordsize, external}) of + Val -> + integer_to_list(8 * Val) + catch + error:badarg -> + integer_to_list(8 * erlang:system_info(wordsize)) + end. |