%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1997-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% %%% Purpose : Autoconf for Windows. -module(ts_autoconf_win32). -export([configure/0]). -include("ts.hrl"). configure() -> case variables() of {ok, Vars} -> ts_lib:subst_file("conf_vars.in", "conf_vars", Vars); Error -> Error end. variables() -> run_tests(tests(), []). run_tests([{Prompt, Tester}|Rest], Vars) -> io:format("checking ~s... ", [Prompt]), case catch Tester(Vars) of {'EXIT', Reason} -> io:format("FAILED~nExit status: ~p~n", [Reason]), {error, auto_conf_failed}; {Result, NewVars} -> io:format("~s~n", [lists:concat([Result])]), run_tests(Rest, NewVars) end; run_tests([], Vars) -> {ok, Vars}. %%% The tests. tests() -> [{"host system type", fun system_type/1}, {"CPU type", fun cpu/1}, {"for C compiler", fun c_compiler/1}, {"for make program", fun make/1}, {"for location of SSL libraries", fun ssl/1}, {"for location of Java compiler", fun javac/1}]. system_type(Vars) -> Os = case os:type() of {win32, nt} -> case os:version() of {4,_,_} -> "Windows NT"; {5,0,_} -> "Windows 2000"; {5,1,_} -> "Windows XP"; {5,2,_} -> "Windows 2003"; {6,0,_} -> "Windows Vista"; {6,1,_} -> "Windows 7"; {_,_,_} -> "Windows NCC-1701-D" end; {win32, windows} -> case os:version() of {4,0,_} -> "Windows 95"; {4,10,_} -> "Windows 98" end; {win32, _} -> "Windows" end, {Os, [{host_os, Os}, {host, "win32"}|Vars]}. cpu(Vars) -> Arch = os:getenv("PROCESSOR_ARCHITECTURE"), Level0 = os:getenv("PROCESSOR_Level"), Cpu = case {Arch, Level0} of {"x86", Level} when is_list(Level) -> "i" ++ Level ++ "86"; {Other, _Level} when is_list(Other) -> Other; {false, _} -> "i386" end, {Cpu, [{host_cpu, Cpu}|Vars]}. c_compiler(Vars) -> try CompTests = [{msc, fun visual_cxx/1}, {gnuc, fun mingw32/1}], %% First try to find the same compiler that the system %% was built with... UsedCompiler = case erlang:system_info(c_compiler_used) of {UsedCmplr, _} -> case lists:keysearch(UsedCmplr, 1, CompTests) of {value, {UsedCmplr, CompTest}} -> CompTest(Vars); _ -> ok end, UsedCmplr; undefined -> undefined end, %% ... then try to find a compiler... lists:foreach(fun ({Cmplr, _CmplrTst}) when Cmplr =:= UsedCompiler -> ok; % Have already checked for this one ({_Cmplr, CmplrTst}) -> CmplrTst(Vars) end, CompTests), {no, Vars} catch throw:{_Path, _NewVars} = Res -> Res end. visual_cxx(Vars) -> case os:find_executable("cl") of false -> {no, Vars}; Path when is_list(Path) -> {DEFAULT_THR_LIB, ERTS_THR_LIB, DLL, DBG_LINK, DBG_COMP, OPT} = case is_debug_build() of true -> {"-MTd ", "-MDd ", "-LDd ", "-debug -pdb:none ", "-Z7 -DDEBUG", " "}; false -> {"-MT ", "-MD ", "-LD ", " ", " ", "-Ox "} end, WIN32 = "-D__WIN32__ ", ERTS_CFLAGS = ERTS_THR_LIB ++ WIN32 ++ OPT ++ DBG_COMP, LIBS = "ws2_32.lib", CC = "cl -nologo", throw({Path, [{'CC', CC}, {'LD', CC}, {'SHLIB_LD', CC}, {'SHLIB_LDFLAGS', ERTS_THR_LIB ++ DLL}, {'SHLIB_LDLIBS', "-link " ++ DBG_LINK ++ "kernel32.lib"}, {'SHLIB_EXTRACT_ALL', ""}, {'CFLAGS', DEFAULT_THR_LIB ++ WIN32 ++ DBG_COMP}, {'EI_CFLAGS', DEFAULT_THR_LIB ++ WIN32 ++ DBG_COMP}, {'ERTS_CFLAGS', ERTS_CFLAGS}, {'SHLIB_CFLAGS', ERTS_CFLAGS++DLL}, {'CROSSLDFLAGS', ""}, {'DEFS', common_c_defs()}, {'SHLIB_SUFFIX', ".dll"}, {'ERTS_LIBS', ERTS_THR_LIB ++ LIBS}, {'LIBS', DEFAULT_THR_LIB ++ "-link " ++ DBG_LINK ++ LIBS}, {obj,".obj"}, {exe, ".exe"}, {test_c_compiler, "{msc, undefined}"} | Vars]}) end. mingw32(Vars) -> Gcc = "mingw32-gcc", case os:find_executable(Gcc) of false -> {no, Vars}; Path when is_list(Path) -> {DBG_COMP, OPT} = case is_debug_build() of true -> {"-DDEBUG", " "}; false -> {" ", "-O2 "} end, WIN32 = "-D__WIN32__ ", ERTS_CFLAGS = WIN32 ++ "-g " ++ OPT ++ DBG_COMP, LIBS = "-lws2_32", CC = Gcc, throw({Path, [{'CC', CC}, {'LD', CC}, {'SHLIB_LD', CC}, {'SHLIB_LDFLAGS', "-shared "}, {'SHLIB_LDLIBS', " -lkernel32"}, {'SHLIB_EXTRACT_ALL', ""}, {'CFLAGS', WIN32 ++ DBG_COMP}, {'EI_CFLAGS', WIN32 ++ DBG_COMP}, {'ERTS_CFLAGS', ERTS_CFLAGS}, {'SHLIB_CFLAGS', ERTS_CFLAGS}, {'CROSSLDFLAGS', ""}, {'DEFS', common_c_defs()}, {'SHLIB_SUFFIX', ".dll"}, {'ERTS_LIBS', LIBS}, {'LIBS', LIBS}, {obj,".o"}, {exe, ".exe"}, {test_c_compiler, "{gnuc, undefined}"} | Vars]}) end. common_c_defs() -> "-DHAVE_STRERROR=1". make(Vars) -> try find_make("nmake -nologo", Vars), find_make("mingw32-make", Vars) catch throw:{_Path, _NewVars} = Res -> Res end. find_make(MakeCmd, Vars) -> [Make|_] = string:tokens(MakeCmd, " \t"), case os:find_executable(Make) of false -> {no, Vars}; Path when is_list(Path) -> throw({Path, [{make_command, MakeCmd} | Vars]}) end. ssl(Vars) -> {"win32",[{'SSLEAY_ROOT',"win32"}|Vars]}. javac(Vars) -> case os:find_executable("javac") of false -> {no, Vars}; Path when is_list(Path) -> {Path, [{'JAVAC', "javac"} | Vars]} end. is_debug_build() -> case catch string:str(erlang:system_info(system_version), "debug") of Int when is_integer(Int), Int > 0 -> true; _ -> false end.