1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(ts_make).
21
22-export([make/1,make/3,unmake/1]).
23
24-include_lib("common_test/include/ct.hrl").
25
26%% Functions to be called from make test cases.
27
28make(Config) when is_list(Config) ->
29    DataDir = proplists:get_value(data_dir, Config),
30    Makefile = proplists:get_value(makefile, Config),
31    Make = proplists:get_value(make_command, Config),
32    case make(Make, DataDir, Makefile) of
33	ok -> ok;
34	{error,Reason} -> exit({make_failed,Reason})
35    end.
36
37unmake(Config) when is_list(Config) ->
38    ok.
39
40%% Runs `make' in the given directory.
41%% Result: ok | {error, Reason}
42
43make(Make, Dir, Makefile) ->
44    {RunFile, RunCmd, Script} = run_make_script(os:type(), Make, Dir, Makefile),
45    case file:write_file(RunFile, unicode:characters_to_binary(Script)) of
46	ok ->
47	    Log = filename:join(Dir, "make.log"),
48	    file:delete(Log),
49	    Port = open_port({spawn, RunCmd}, [eof,stream,in,stderr_to_stdout]),
50	    case get_port_data(Port, [], false) of
51		"*ok*" ++ _ -> ok;
52		"*error*" ++ _ -> {error, make};
53		Other ->{error,{make,Other}}
54	    end;
55	Error -> Error
56    end.
57
58get_port_data(Port, Last0, Complete0) ->
59    receive
60	{Port,{data,Bytes}} ->
61	    {Last, Complete} = update_last(Bytes, Last0, Complete0),
62	    get_port_data(Port, Last, Complete);
63	{Port, eof} ->
64	    Result = update_last(eof, Last0, Complete0),
65	    unlink(Port),
66	    exit(Port, die),
67	    Result
68    end.
69
70update_last([C|Rest], Line, true) ->
71    try
72	%% Utf-8 list to utf-8 binary
73	%% (e.g. we assume utf-8 bytes from port)
74	io:put_chars(list_to_binary(Line))
75    catch
76	error:badarg ->
77	    %% io:put_chars/1 badarged
78	    %% this likely means we had unicode code points
79	    %% in our bytes buffer (e.g warning from gcc with åäö)
80	    io:put_chars(unicode:characters_to_binary(Line))
81    end,
82    io:nl(),
83    update_last([C|Rest], [], false);
84update_last([$\r|Rest], Result, Complete) ->
85    update_last(Rest, Result, Complete);
86update_last([$\n|Rest], Result, _Complete) ->
87    update_last(Rest, lists:reverse(Result), true);
88update_last([C|Rest], Result, Complete) ->
89    update_last(Rest, [C|Result], Complete);
90update_last([], Result, Complete) ->
91    {Result, Complete};
92update_last(eof, Result, _) ->
93    unicode:characters_to_list(list_to_binary(Result)).
94
95run_make_script({win32, _}, Make, Dir, Makefile) ->
96    {"run_make.bat",
97     ".\\run_make",
98     ["@echo off\r\n",
99      "cd \"", filename:nativename(Dir), "\"\r\n",
100      Make, " -f ", Makefile, " \r\n",
101      "if errorlevel 1 echo *error*\r\n",
102      "if not errorlevel 1 echo *ok*\r\n"]};
103run_make_script({unix, _}, Make, Dir, Makefile) ->
104    {"run_make",
105     "/bin/sh ./run_make",
106     ["#!/bin/sh\n",
107      "cd \"", Dir, "\"\n",
108      Make, " -f ", Makefile, " 2>&1\n",
109      "case $? in\n",
110      "  0) echo '*ok*';;\n",
111      "  *) echo '*error*';;\n",
112      "esac\n"]};
113run_make_script(_Other, _Make, _Dir, _Makefile) ->
114    exit(dont_know_how_to_make_script_on_this_platform).
115