Inno-Setup-issrc/Projects/Src/Compiler.Compile.pas

192 lines
5.8 KiB
ObjectPascal

unit Compiler.Compile;
{
Inno Setup
Copyright (C) 1997-2024 Jordan Russell
Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT.
Compiler DLL interface functions which wrap TSetupCompiler
}
interface
uses
Shared.CompilerInt.Struct;
function ISCompileScript(const Params: TCompileScriptParamsEx;
const PropagateExceptions: Boolean): Integer;
function ISGetVersion: PCompilerVersionInfo;
implementation
uses
Windows, SysUtils, Classes, PathFunc,
Shared.Struct, Shared.CommonFunc, Compiler.SetupCompiler;
function GetSelfFilename: String;
{ Returns Filename of the calling DLL or application. (ParamStr(0) can only
return the filename of the calling application.) }
var
Buf: array[0..MAX_PATH-1] of Char;
begin
SetString(Result, Buf, GetModuleFileName(HInstance, Buf, SizeOf(Buf)))
end;
function ISCompileScript(const Params: TCompileScriptParamsEx;
const PropagateExceptions: Boolean): Integer;
function CheckParams(const Params: TCompileScriptParamsEx): Boolean;
begin
Result := ((Params.Size = SizeOf(Params)) or
(Params.Size = SizeOf(TCompileScriptParams))) and
Assigned(Params.CallbackProc);
end;
procedure InitializeSetupCompiler(const SetupCompiler: TSetupCompiler;
const Params: TCompileScriptParamsEx);
begin
SetupCompiler.AppData := Params.AppData;
SetupCompiler.CallbackProc := Params.CallbackProc;
if Assigned(Params.CompilerPath) then
SetupCompiler.CompilerDir := Params.CompilerPath
else
SetupCompiler.CompilerDir := PathExtractPath(GetSelfFilename);
SetupCompiler.SourceDir := Params.SourcePath;
end;
function EncodeIncludedFilenames(const IncludedFilenames: TStringList): String;
var
S: String;
I: Integer;
begin
S := '';
for I := 0 to IncludedFilenames.Count-1 do
S := S + IncludedFilenames[I] + #0;
Result := S;
end;
procedure NotifyPreproc(const SetupCompiler: TSetupCompiler);
var
Data: TCompilerCallbackData;
S: String;
begin
Data.PreprocessedScript := PChar(SetupCompiler.GetPreprocOutput);
S := EncodeIncludedFilenames(SetupCompiler.GetPreprocIncludedFilenames);
Data.IncludedFilenames := PChar(S);
Params.CallbackProc(iscbNotifyPreproc, Data, Params.AppData);
end;
procedure NotifySuccess(const SetupCompiler: TSetupCompiler);
var
Data: TCompilerCallbackData;
begin
Data.OutputExeFilename := PChar(SetupCompiler.GetExeFilename);
var DebugInfo := SetupCompiler.GetDebugInfo;
Data.DebugInfo := DebugInfo.Memory;
Data.DebugInfoSize := DebugInfo.Size;
Params.CallbackProc(iscbNotifySuccess, Data, Params.AppData);
end;
procedure NotifyError(const SetupCompiler: TSetupCompiler);
var
Data: TCompilerCallbackData;
S: String;
begin
Data.ErrorMsg := nil;
Data.ErrorFilename := nil;
Data.ErrorLine := 0;
if not(ExceptObject is EAbort) then begin
S := GetExceptMessage;
Data.ErrorMsg := PChar(S);
{ use a Pointer cast instead of PChar so that we'll get a null
pointer if the string is empty }
Data.ErrorFilename := Pointer(SetupCompiler.GetLineFilename);
Data.ErrorLine := SetupCompiler.GetLineNumber;
end;
Params.CallbackProc(iscbNotifyError, Data, Params.AppData);
end;
var
SetupCompiler: TSetupCompiler;
P: PChar;
P2: Integer;
begin
if not CheckParams(Params) then begin
Result := isceInvalidParam;
Exit;
end;
SetupCompiler := TSetupCompiler.Create(nil);
try
InitializeSetupCompiler(SetupCompiler, Params);
{ Parse Options (only present in TCompileScriptParamsEx) }
if (Params.Size <> SizeOf(TCompileScriptParams)) and Assigned(Params.Options) then begin
P := Params.Options;
while P^ <> #0 do begin
if StrLIComp(P, 'Output=', Length('Output=')) = 0 then begin
Inc(P, Length('Output='));
var Output: Boolean;
if TryStrToBoolean(P, Output) then
SetupCompiler.SetOutput(Output)
else begin
{ Bad option }
Result := isceInvalidParam;
Exit;
end;
end else if StrLIComp(P, 'OutputDir=', Length('OutputDir=')) = 0 then begin
Inc(P, Length('OutputDir='));
SetupCompiler.SetOutputDir(P);
end else if StrLIComp(P, 'OutputBaseFilename=', Length('OutputBaseFilename=')) = 0 then begin
Inc(P, Length('OutputBaseFilename='));
SetupCompiler.SetOutputBaseFilename(P);
end else if StrLIComp(P, 'SignTool-', Length('SignTool-')) = 0 then begin
Inc(P, Length('SignTool-'));
P2 := Pos('=', P);
if (P2 <> 0) then
SetupCompiler.AddSignTool(Copy(P, 1, P2-1), Copy(P, P2+1, MaxInt))
else begin
{ Bad option }
Result := isceInvalidParam;
Exit;
end;
end else if StrLIComp(P, 'ISPP:', Length('ISPP:')) = 0 then
SetupCompiler.AddPreprocOption(P)
else begin
{ Unknown option }
Result := isceInvalidParam;
Exit;
end;
Inc(P, StrLen(P) + 1);
end;
end;
try
try
SetupCompiler.Compile;
finally
NotifyPreproc(SetupCompiler);
end;
Result := isceNoError;
NotifySuccess(SetupCompiler);
except
Result := isceCompileFailure;
NotifyError(SetupCompiler);
if PropagateExceptions then
raise;
end;
finally
SetupCompiler.Free;
end;
end;
function ISGetVersion: PCompilerVersionInfo;
const
Ver: TCompilerVersionInfo =
(Title: SetupTitle; Version: SetupVersion; BinVersion: SetupBinVersion);
begin
Result := @Ver;
end;
end.