%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1997-2009. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% %% To be used from makefiles on the unix side executing things on the NT-side -module(ntbuild). -export([nmake/1, omake/1, waitnode/1, restart/1, setdir/1, run_tests/1, run_command/1]). -export([serv_nmake/2, serv_omake/2, serv_restart/0, serv_run_tests/2, serv_run_command/1]). waitnode([NtNode]) -> % First, wait for node to disappear. case wait_disappear(NtNode, 0) of ok -> case wait_appear(NtNode, 0) of ok -> halt(0); fail -> halt(1) end; fail -> halt(1) end. % Wait for nt node to appear within 5 minutes. wait_appear(_NtNode, 300) -> fail; wait_appear(NtNode, N) -> receive after 1000 -> ok end, case nt_node_alive(NtNode, quiet) of no -> wait_appear(NtNode, N+1); yes -> ok end. % Waits for nt node to disappear within 3 minutes. wait_disappear(NtNode, 300) -> fail; wait_disappear(NtNode, N) -> receive after 1000 -> ok end, case nt_node_alive(NtNode, quiet) of yes -> wait_disappear(NtNode, N+1); no -> ok end. restart([NtNode]) -> case nt_node_alive(NtNode) of yes -> case rpc:call(NtNode, ntbuild, serv_restart, []) of ok -> io:format("halt(0)~n"), halt(); Error -> io:format("halt(1)~n"), halt(1) end; no -> halt(1) end. setdir([NtNode, Dir0]) -> Dir = atom_to_list(Dir0), case nt_node_alive(NtNode) of yes -> case rpc:call(NtNode, file, set_cwd, [Dir]) of ok -> io:format("halt(0)~n"), halt(); Error -> io:format("halt(1) (Error: ~p) (~p not found) ~n", [Error, Dir]), halt(1) end; no -> halt(1) end. run_tests([NtNode, Vsn0, Logdir]) -> Vsn = atom_to_list(Vsn0), case nt_node_alive(NtNode) of yes -> case rpc:call(NtNode, ntbuild, serv_run_tests, [Vsn, Logdir]) of ok -> io:format("halt(0)~n"), halt(); Error -> io:format("RPC To Windows Node Failed: ~p~n", [Error]), io:format("halt(1)~n"), halt(1) end; no -> halt(1) end. run_command([NtNode, Cmd]) -> case nt_node_alive(NtNode) of yes -> case rpc:call(NtNode, ntbuild, serv_run_command, [Cmd]) of ok -> io:format("halt(0)~n"), halt(); Error -> io:format("RPC To Windows Node Failed: ~p~n", [Error]), io:format("halt(1)~n"), halt(1) end; no -> halt(1) end. nmake([NtNode, Path, Options]) -> % io:format("nmake2(~w,~w)~n",[Path, Options]), Dir=atom_to_list(Path), Opt=atom_to_list(Options), case nt_node_alive(NtNode) of yes -> case rpc:call(NtNode, ntbuild, serv_nmake, [Dir, Opt]) of ok -> io:format("halt(0)~n"), halt(); Error -> io:format("Error: ~n", [Error]), halt(1) end; no -> halt(1) end. omake([NtNode, Path, Options]) -> Dir=atom_to_list(Path), Opt=atom_to_list(Options), case nt_node_alive(NtNode) of yes -> case rpc:call(NtNode, ntbuild, serv_omake, [Dir, Opt]) of ok -> io:format("halt(0)~n"), halt(); Error -> io:format("RPC To Windows Node Failed: ~p~n", [Error]), io:format("~p ~p~n", [Dir, Opt]), io:format("halt(1)~n"), halt(1) end; no -> halt(1) end. nt_node_alive(NtNode) -> case net:ping(NtNode) of pong -> yes; pang -> io:format("The NT node (~p) is not up. ~n",[NtNode]), no end. nt_node_alive(NtNode, quiet) -> case net:ping(NtNode) of pong -> yes; pang -> no end. %%% %%% The 'serv_' functions. Theese are the routines run on the WinNT node. %%% %%----------------------- %% serv_run_tests() %% Runs the tests. serv_run_tests(Vsn, Logdir) -> {ok, Cwd}=file:get_cwd(), io:format("serv_run_tests ~p ~p ~n", [Vsn, Logdir]), Cmd0= "set central_log_dir=" ++ Logdir, Erl = "C:/progra~1/erl"++Vsn++"/bin/erl", Cmd1 = Erl++" -sname a -setcookie a -noshell -noinput -s ts install -s ts run -s ts save -s erlang halt", %% Dir = "C:/temp/test_suite/test_server", Cmd= Cmd0 ++ "/r/n" ++ Cmd1, Dir = "C:/temp/test_server/p7a/test_server", file:set_cwd(Dir), Res=run_make_bat(Dir, Cmd), file:set_cwd(Cwd), Res. %%----------------------- %% serv_run_command() %% Runs a command. serv_run_command(Cmd) -> {ok, Cwd}=file:get_cwd(), Res=run_make_bat("", Cmd), file:set_cwd(Cwd), Res. %%----------------------- %% serv_restart() %% Reboots the NT machine. serv_restart() -> Exe="\\erts\\install_nt\\reboot.exe", open_port({spawn, Exe}, [stream, eof, in]), ok. %%----------------------- %% serv_nmake(Path, Options) %% Runs `nmake' in the given directory. %% Result: ok | error serv_nmake(Path, Options) -> {ok, Cwd}=file:get_cwd(), Command="nmake -e -f Makefile.win32 " ++ Options ++ " 2>&1", Res=run_make_bat(Path, Command), file:set_cwd(Cwd), Res. %%----------------------- %% serv_omake(Path, Options) %% Runs `omake' in the given directory. %% Result: ok | error serv_omake(Path, Options) -> {ok, Cwd}=file:get_cwd(), Command="omake -W -E -EN -f Makefile.win32 " ++ Options ++ " 2>&1", Res=run_make_bat(Path, Command), file:set_cwd(Cwd), Res. read_output(Port, SoFar) -> % io:format("(read_output)~n"), case get_data_from_port(Port) of eof -> io:format("*** eof ***~n"), io:format("Never reached a real message"), halt(1); {ok, Data} -> case print_line([SoFar|Data]) of {ok, Rest} -> read_output(Port, Rest); {done, Res} -> Res end end. print_line(Data) -> print_line(Data, []). print_line([], Acc) -> {ok, lists:reverse(Acc)}; print_line([$*,$o,$k,$*|Rest], _Acc) -> io:format("*ok*~n"), {done, ok}; print_line([$*,$e,$r,$r,$o,$r|Rest], _Acc) -> io:format("*error*~n"), {done, error}; print_line([$\r,$\n|Rest], Acc) -> io:format("~s~n", [lists:reverse(Acc)]), print_line(Rest, []); print_line([Chr|Rest], Acc) -> print_line(Rest, [Chr|Acc]). get_data_from_port(Port) -> receive {Port, {data, Bytes}} -> {ok, Bytes}; {Port, eof} -> unlink(Port), exit(Port, die), eof; Other -> io:format("Strange message received: ~p~n", [Other]), get_data_from_port(Port) end. run_make_bat(Dir, Make) -> {Name, Exe, Script}=create_make_script(Dir, Make), io:format("Exe:~p Cwd:~p Script:~p ~n",[Exe, Dir, Script]), case file:write_file(Name, Script) of ok -> case catch open_port({spawn, Exe}, [stderr_to_stdout, stream, hide, eof, in]) of Port when port(Port) -> read_output(Port, []); Other -> io:format("Error, open_port failed: ~p~n", [Other]), {open_port, Other, Exe} end; Error -> {write_file, Error, Name} end. create_make_script(Dir, Make) when atom(Make) -> create_make_script(Dir, atom_to_list(Make)); create_make_script(Dir, Make) -> {"run_make_bs.bat", "run_make_bs 2>&1", ["@echo off\r\n", "@cd ", Dir, "\r\n", Make++"\r\n", "if errorlevel 1 echo *run_make_bs error*\r\n", "if not errorlevel 1 echo *ok*\r\n"]}.