Force rebuild.
4 * by the AMX Mod X Development Team
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * In addition, as a special exception, the author gives permission to
22 * link the code of this program with the Half-Life Game Engine ("HL
23 * Engine") and Modified Game Libraries ("MODs") developed by Valve,
24 * L.L.C ("Valve"). You must obey the GNU General Public License in all
25 * respects for all of the code used other than the HL Engine and MODs
26 * from Valve. If you modify this file, you may extend this exception
27 * to your version of the file, but you are not obligated to do so. If
28 * you do not wish to do so, delete this exception statement from your
37 Windows, SysUtils, Classes, Math, IniFiles;
40 COMPILER_EXE = 'spcomp.exe';
43 procedure CompilePlugin(const Name, OutputDir: String);
44 function GetAgeFromDat(const FileName: String): Integer;
45 procedure SetAgeToDat(const FileName: String; const Age: Integer);
46 function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
53 Write('Press enter to exit ...');
58 procedure CompilePlugin(const Name, OutputDir: String);
62 cStart,cEnd: Longword;
63 FileName, FilePath, Compiled: String;
65 FileName := ExtractFileName(Name);
66 FilePath := ExtractFilePath(Name);
67 if (OutputDir = '') then
68 Compiled := FilePath+'compiled\'+ChangeFileExt(Filename,'.smx')
70 Compiled := OutputDir+ChangeFileExt(Filename,'.smx');
73 FilePath := ExtractFilePath(ParamStr(0));
76 WriteLn('//// '+ExtractFileName(FileName));
78 if FileExists(Compiled) and ( GetAgeFromDat(Name)=FileAge(Name) ) then
80 WriteLn('// Already compiled.');
81 WriteLn('// ----------------------------------------');
85 Output := TStringList.Create;
88 cStart := GetTickCount;
89 if not GetConsoleOutput(ExtractFilePath(ParamStr(0))+COMPILER_EXE+' "'+Name+'" "-o'+Compiled+'"',Output) then
91 WriteLn('// Internal error.');
96 for i := 3 to (Output.Count-1) do
98 WriteLn('// '+Output.Strings[i]);
102 WriteLn('// Compilation Time: '+FloatToStr(SimpleRoundTo((cEnd-cStart) / 1000,-2))+' sec');
103 WriteLn('// ----------------------------------------');
106 WriteLn('// Internal error.');
110 SetAgeToDat(Name,FileAge(Name));
113 function GetAgeFromDat(const FileName: String): Integer;
117 Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
118 Result := Ini.ReadInteger(FileName,'Age',-1);
122 procedure SetAgeToDat(const FileName: String; const Age: Integer);
126 Ini := TIniFile.Create(ExtractFilePath(ParamStr(0))+'compile.dat');
127 Ini.WriteInteger(FileName,'Age',Age);
130 SetFileAttributes(PChar(ExtractFilePath(ParamStr(0))+'compile.dat'), faHidden);
133 function GetConsoleOutput(const Command: String; var Output: TStringList): Boolean;
135 StartupInfo: TStartupInfo;
136 ProcessInfo: TProcessInformation;
137 SecurityAttr: TSecurityAttributes;
138 PipeOutputRead: THandle;
139 PipeOutputWrite: THandle;
140 PipeErrorsRead: THandle;
141 PipeErrorsWrite: THandle;
143 Buffer: array [0..255] of Char;
144 NumberOfBytesRead: DWORD;
145 Stream: TMemoryStream;
148 FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
149 FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
151 SecurityAttr.nLength := SizeOf(SecurityAttr);
152 SecurityAttr.bInheritHandle := True;
153 SecurityAttr.lpSecurityDescriptor := nil;
155 CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
156 CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);
158 FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
159 StartupInfo.cb:=SizeOf(StartupInfo);
160 StartupInfo.hStdInput := 0;
161 StartupInfo.hStdOutput := PipeOutputWrite;
162 StartupInfo.hStdError := PipeErrorsWrite;
163 StartupInfo.wShowWindow := SW_HIDE;
164 StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
166 if CreateProcess(nil, PChar(command), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInfo) then begin
168 CloseHandle(PipeOutputWrite);
169 CloseHandle(PipeErrorsWrite);
171 Stream := TMemoryStream.Create;
174 Succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
175 if not Succeed then Break;
176 Stream.Write(Buffer, NumberOfBytesRead);
181 Stream.Position := 0;
182 Output.LoadFromStream(Stream);
184 CloseHandle(PipeOutputRead);
190 Succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
191 if not Succeed then Break;
192 Errors := Errors + Copy(Buffer, 1, NumberOfBytesRead);
197 CloseHandle(PipeErrorsRead);
199 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
200 CloseHandle(ProcessInfo.hProcess);
205 CloseHandle(PipeOutputRead);
206 CloseHandle(PipeOutputWrite);
207 CloseHandle(PipeErrorsRead);
208 CloseHandle(PipeErrorsWrite);
211 if (Errors <> '') then begin
212 if (Output.Count > 1) then begin
213 if (Trim(Output[Output.Count -2]) = '') then
214 Output.Strings[Output.Count -2] := TrimRight(Errors)
216 Output.Insert(Output.Count -1, TrimRight(Errors));
220 Output.Text := Output.Text; // pseudo-rearrangement