Add FPC-compatible CLI mode to Blaise compiler
Blaise can now act as a drop-in FPC replacement for PasBuild when invoked via `pasbuild compile --fpc /path/to/blaise`. - Detects FPC-style invocation (single-dash flags vs. native double-dash) - Handles -iV / -iTP / -iTO probe queries PasBuild uses before compiling - Maps -FE<dir>, -o<name> to output path; silently ignores -Fu, -FU, -Mobjfpc, -O<n>, -g, -gl, -CX and unknown single-dash flags - Native --source / --output / --emit-ir mode is fully preserved
This commit is contained in:
parent
25de8be212
commit
95e1ea58af
|
|
@ -27,8 +27,8 @@ begin
|
|||
WriteLn('Blaise Compiler v', Version);
|
||||
WriteLn('');
|
||||
WriteLn('Usage:');
|
||||
WriteLn(' cleanpascal --source <file.pas> --output <binary>');
|
||||
WriteLn(' cleanpascal --source <file.pas> --emit-ir');
|
||||
WriteLn(' blaise --source <file.pas> --output <binary>');
|
||||
WriteLn(' blaise --source <file.pas> --emit-ir');
|
||||
WriteLn('');
|
||||
WriteLn('Flags:');
|
||||
WriteLn(' --source <path> Pascal source file');
|
||||
|
|
@ -37,6 +37,125 @@ begin
|
|||
WriteLn(' --emit-ir Print QBE IR to stdout and exit');
|
||||
end;
|
||||
|
||||
{ Handle FPC -i query flags: -iV (version), -iTP (target processor), -iTO (target OS).
|
||||
PasBuild probes the compiler with these before invoking a full compile. }
|
||||
procedure HandleFPCInfoQuery(const AArg: string);
|
||||
var
|
||||
Query: string;
|
||||
begin
|
||||
Query := Copy(AArg, 3, MaxInt); { strip leading '-i' }
|
||||
if Query = 'V' then
|
||||
begin
|
||||
WriteLn('3.2.2');
|
||||
Halt(0);
|
||||
end
|
||||
else if Query = 'TP' then
|
||||
begin
|
||||
WriteLn('x86_64');
|
||||
Halt(0);
|
||||
end
|
||||
else if Query = 'TO' then
|
||||
begin
|
||||
WriteLn('linux');
|
||||
Halt(0);
|
||||
end;
|
||||
{ Unknown -i query — ignore silently }
|
||||
end;
|
||||
|
||||
{ Parse FPC-style arguments emitted by PasBuild when --fpc /path/to/blaise is used.
|
||||
Handles: -iV/-iTP/-iTO, -FE<dir>, -Fu<path>, -FU<path>, -o<name>,
|
||||
-Mobjfpc, -O<n>, -g, -gl, -CX, -d<define>, and the positional source file. }
|
||||
function ParseFPCArgs(
|
||||
out SourceFile: string;
|
||||
out OutputFile: string): Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
Arg: string;
|
||||
OutDir: string;
|
||||
OutName: string;
|
||||
begin
|
||||
Result := False;
|
||||
SourceFile := '';
|
||||
OutputFile := '';
|
||||
OutDir := '';
|
||||
OutName := '';
|
||||
|
||||
I := 1;
|
||||
while I <= ParamCount do
|
||||
begin
|
||||
Arg := ParamStr(I);
|
||||
|
||||
if Copy(Arg, 1, 2) = '-i' then
|
||||
HandleFPCInfoQuery(Arg)
|
||||
else if Copy(Arg, 1, 3) = '-FE' then
|
||||
OutDir := Copy(Arg, 4, MaxInt)
|
||||
else if Copy(Arg, 1, 3) = '-FU' then
|
||||
{ unit cache directory — ignored in Phase 1 }
|
||||
else if Copy(Arg, 1, 3) = '-Fu' then
|
||||
{ unit search path — ignored in Phase 1 }
|
||||
else if Copy(Arg, 1, 2) = '-o' then
|
||||
OutName := Copy(Arg, 3, MaxInt)
|
||||
else if Copy(Arg, 1, 2) = '-M' then
|
||||
{ mode switch (e.g. -Mobjfpc) — ignored }
|
||||
else if Copy(Arg, 1, 2) = '-O' then
|
||||
{ optimisation level — ignored }
|
||||
else if Copy(Arg, 1, 2) = '-d' then
|
||||
{ conditional define — ignored in Phase 1 }
|
||||
else if (Arg = '-g') or (Arg = '-gl') or (Arg = '-CX') or
|
||||
(Arg = '-XX') or (Arg = '-Xs') then
|
||||
{ debug / linking flags — ignored }
|
||||
else if (Arg = '--help') or (Arg = '-h') then
|
||||
begin
|
||||
PrintUsage;
|
||||
Halt(0);
|
||||
end
|
||||
else if (Length(Arg) > 0) and (Arg[1] <> '-') then
|
||||
begin
|
||||
{ Positional argument — the source file }
|
||||
if SourceFile = '' then
|
||||
SourceFile := Arg;
|
||||
end;
|
||||
{ Any other unrecognised -X flag is silently ignored for forward-compat }
|
||||
|
||||
Inc(I);
|
||||
end;
|
||||
|
||||
if SourceFile = '' then
|
||||
begin
|
||||
WriteLn(StdErr, 'Error: no source file specified');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
{ Build output path from -FE and -o, mirroring FPC behaviour }
|
||||
if OutName = '' then
|
||||
OutName := ChangeFileExt(ExtractFileName(SourceFile), '');
|
||||
if OutDir <> '' then
|
||||
OutputFile := IncludeTrailingPathDelimiter(OutDir) + OutName
|
||||
else
|
||||
OutputFile := OutName;
|
||||
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
{ Returns True when the argument list looks like FPC-style flags (single-dash,
|
||||
single-letter prefix) rather than Blaise native (double-dash) flags. }
|
||||
function IsFPCStyleInvocation: Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
Arg: string;
|
||||
begin
|
||||
Result := False;
|
||||
for I := 1 to ParamCount do
|
||||
begin
|
||||
Arg := ParamStr(I);
|
||||
if (Length(Arg) >= 2) and (Arg[1] = '-') and (Arg[2] <> '-') then
|
||||
begin
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ParseArgs(
|
||||
out SourceFile: string;
|
||||
out OutputFile: string;
|
||||
|
|
@ -161,10 +280,22 @@ var
|
|||
IRFile: string;
|
||||
|
||||
begin
|
||||
if not ParseArgs(SourceFile, OutputFile, EmitIR) then
|
||||
if IsFPCStyleInvocation then
|
||||
begin
|
||||
PrintUsage;
|
||||
Halt(1);
|
||||
if not ParseFPCArgs(SourceFile, OutputFile) then
|
||||
begin
|
||||
PrintUsage;
|
||||
Halt(1);
|
||||
end;
|
||||
EmitIR := False;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if not ParseArgs(SourceFile, OutputFile, EmitIR) then
|
||||
begin
|
||||
PrintUsage;
|
||||
Halt(1);
|
||||
end;
|
||||
end;
|
||||
|
||||
if not FileExists(SourceFile) then
|
||||
|
|
|
|||
Loading…
Reference in a new issue