fix(driver): auto-add the RTL source dir to the loader search path

After the RTL-unification move, stdlib units (classes, contnrs) explicitly
`uses runtime.arc` and friends.  The compiler driver already source-builds the
RTL from compiler/src/main/pascal at link time, but the FRONT-END unit loader
was never told where that source lives — so compiling any program that uses a
stdlib unit (or any RTL unit transitively) failed with
"Unit 'runtime.arc' not found in search paths" unless the user manually passed
--unit-path compiler/src/main/pascal.

Add the RTL source directory to the loader's search paths automatically,
resolved the same way EnsureRTLObjects resolves it for linking: --rtl-src, then
$BLAISE_RTL_SRC, then the binary/CWD-relative RTLSourceDir default.  (stdlib
itself stays an explicit --unit-path, as before — it is an opt-in library, not
implicit like the RTL.)

Regression introduced by the RTL-unification land; reported by a user.
Verified: a `uses classes` program now compiles + runs with only the stdlib
unit-path, from any CWD.  All four fixpoints green; full suite 3831.
This commit is contained in:
Graeme Geldenhuys 2026-06-26 09:12:38 +01:00
parent 18b215835c
commit a6cdba7fbe

View file

@ -31,7 +31,7 @@ uses
blaise.codegen.native.driver, blaise.codegen.native.driver,
uUnitLoader, uDebugOPDF, uDebugFacts, uUnitInterface, uSemanticExport, uSemanticImport, uUnitLoader, uDebugOPDF, uDebugFacts, uUnitInterface, uSemanticExport, uSemanticImport,
uUnitInterfaceIO, uIfaceObject, uASTDump, uUnitInterfaceIO, uIfaceObject, uASTDump,
blaise.frontend.opts, uConfig; blaise.frontend.opts, uConfig, uToolchain;
type type
{ Alias so existing signatures (ParseArgs out param, locals) read { Alias so existing signatures (ParseArgs out param, locals) read
@ -480,6 +480,7 @@ var
Front: TFrontEndOpts; { front-end-only flag bag, populated by ParseArgs } Front: TFrontEndOpts; { front-end-only flag bag, populated by ParseArgs }
ToolErr: string; { CheckToolchain result ('' on success) } ToolErr: string; { CheckToolchain result ('' on success) }
ValidErr: string; { Driver.ValidateOptions result ('' on success) } ValidErr: string; { Driver.ValidateOptions result ('' on success) }
RTLSrc: string; { RTL source dir added to the loader search path }
PendingFlags: TStringList; { deferred unknown flags (driver-private) } PendingFlags: TStringList; { deferred unknown flags (driver-private) }
PendingArgs: TStringList; { lookahead token per pending flag ('' if none) } PendingArgs: TStringList; { lookahead token per pending flag ('' if none) }
PendIdx: Integer; { drain cursor over the pending lists } PendIdx: Integer; { drain cursor over the pending lists }
@ -562,6 +563,24 @@ begin
if (UnitCacheDir <> '') and (SearchPaths.IndexOf(UnitCacheDir) < 0) then if (UnitCacheDir <> '') and (SearchPaths.IndexOf(UnitCacheDir) < 0) then
SearchPaths.Add(UnitCacheDir); SearchPaths.Add(UnitCacheDir);
{ Always make the RTL source directory discoverable to the unit loader. The
RTL units (runtime.*, rtl.platform.*, system) live in the compiler's own
source tree after the RTL-unification move; stdlib units such as `classes`
explicitly `uses runtime.arc`, so a program that uses them needs the RTL
source on the search path — without this the loader fails with
"Unit 'runtime.arc' not found". The driver already source-builds the RTL
from this same directory at link time; here we add it for the front-end
loader too. Resolution mirrors EnsureRTLObjects: --rtl-src, then
$BLAISE_RTL_SRC, then the binary/CWD-relative default. }
RTLSrc := Opts.RTLSrcDir;
if RTLSrc = '' then
RTLSrc := GetEnvironmentVariable('BLAISE_RTL_SRC');
if RTLSrc = '' then
RTLSrc := RTLSourceDir();
if (RTLSrc <> '') and DirectoryExists(RTLSrc)
and (SearchPaths.IndexOf(RTLSrc) < 0) then
SearchPaths.Add(RTLSrc);
{ Emit-mode / backend compatibility. --emit-ir prints QBE IR and { Emit-mode / backend compatibility. --emit-ir prints QBE IR and
--emit-asm prints native assembly; PickTopDriver routes each to the --emit-asm prints native assembly; PickTopDriver routes each to the
backend that produces it, ignoring --backend. That silent override is backend that produces it, ignoring --backend. That silent override is