Cross-platform
mormot2-pgvector compiles and runs on three target combinations:
| OS | Compiler | Status |
|---|---|---|
| Windows x64 | FPC 3.2.2 + Lazarus | 2 674 / 2 674 tests PASS |
| Windows x64 | Delphi 12 / 36.0 (RAD Studio Athens) | 2 656 / 2 656 tests PASS + spawn-the-binary CLI suite |
| Linux x86_64 | FPC 3.2.2 (Ubuntu 24.04 / WSL2) | 2 656 / 2 656 tests PASS |
mORMot 2 itself is the load-bearing layer: it provides the cross-OS, cross-compiler primitives (file I/O, networking, threading, JSON, ORM) and we follow its conventions everywhere. As a result, the project's own units needed only three small portability tweaks.
The three Delphi-portability fixes
tkAString is FPC-only
MapColumnType in mormot.db.pgvector.orm.pas had a case branch for
the FPC-specific tkAString TTypeKind constant. Delphi does not
declare it. Wrap with {$ifdef FPC}:
case TypeKind of
...
tkLString, // long ANSI string
tkUString,
tkWString:
Result := 'TEXT';
{$ifdef FPC}
tkAString: // FPC alias for AnsiString-with-codepage
Result := 'TEXT';
{$endif FPC}
...
end;
Variant -> Double via AnyVariantToDouble
mORMot's TDocVariantData JSON parser stores some bare-number tokens
as varOleStr on Delphi where FPC keeps them as varDouble. A
direct d := variant_value cast then raises EVariantTypeCastError
on Delphi.
TOllamaEmbeddingClient.ParseEmbeddings now goes through
mormot.core.text.AnyVariantToDouble (with a try-except direct-cast
fallback for the rare third-party variants):
if not AnyVariantToDouble(inner^.Values[j], d) then
try
d := inner^.Values[j];
except
raise EEmbeddingClient.CreateUtf8(
'Ollama: embeddings[%][%] is not a number', [i, j]);
end;
Byte-level comparison instead of RawUtf8(#$C3#$A9)
Delphi parses string literals like #$C3 as UTF-16 code units and
re-encodes them to two UTF-8 bytes when assigned to a RawUtf8. FPC
keeps #$C3 as a single raw byte. Tests that asserted on a
RawUtf8(#$C3#$A9) literal therefore failed on one compiler.
LoadFile_PreservesNonAsciiBytes in test/test.chunk.pas now uses a
PByte cast and compares each byte explicitly:
P := PByte(Pointer(content));
CheckEqual(P[0], $63); // 'c'
CheckEqual(P[1], $61); // 'a'
CheckEqual(P[2], $66); // 'f'
CheckEqual(P[3], $C3); // 'é' lead byte
CheckEqual(P[4], $A9); // 'é' continuation byte
That assertion is portable across both compilers.
Building under FPC + Lazarus
The .lpi project files reference mORMot 2 source paths via the
OtherUnitFiles and IncludeFiles settings. The exact paths are
hard-coded for the developer's machine layout and are read by
lazbuild:
lazbuild --build-mode=Default --build-all test\test_runner.lpi
lazbuild --build-mode=Default --build-all examples\01_ingest_mormot2.lpi
lazbuild --build-mode=Default --build-all examples\02_query_cli.lpi
lazbuild --build-mode=Default --build-all examples\03_chat_cli.lpi
Outputs land under build\. To redirect the FPC search paths to
your own mORMot 2 location, edit the IncludeFiles and
OtherUnitFiles lines in each .lpi, or invoke fpc directly with
the -Fu / -Fi flags as the Linux build script does.
Building under Delphi
Delphi's dcc64 does not load .lpi files. The simplest invocation
follows the test_runner cross-compile:
$rtl = "C:\dev\IDE\Embarcadero\Studio\23.0\lib\win64\release"
$m = "C:\path\to\mORMot2\src"
dcc64 -NSSystem;Winapi;System.Win `
-U$rtl -U$rtl\<lang> `
-U$m -U$m\core -U$m\db -U$m\net -U$m\crypt `
-U$m\orm -U$m\rest -U$m\soa -U$m\app -U$m\lib `
-Usrc `
-I$m `
test\test_runner.dpr
The -NS flag list resolves the modern Delphi unit namespaces
(System.SysUtils, Winapi.Windows, …) used by the mORMot 2
SysUtils and Windows aliases. The -U<lang> directory carries the
localized RTL .dcu set; substitute your install's language code (the
example uses fr for the French build).
A dproj is not required; dcc64 on the .dpr is enough for
unattended cross-compile validation.
Building under Linux (WSL or native)
The .lpi paths are Windows-specific, so on Linux the recommended
path is to invoke fpc directly. The repo ships
build-linux.sh and run-linux.sh for WSL:
# from a WSL bash shell
M=/mnt/c/path/to/mORMot2/src
P=/mnt/c/path/to/mormot2-pgvector
cd "$P"
mkdir -p build_linux
fpc -Mobjfpc -Sci \
-Fi"$M" -Fu"$M" -Fu"$P/src" \
-Fu"$M/core" -Fi"$M/core" \
-Fu"$M/orm" -Fi"$M/orm" \
-Fu"$M/db" -Fi"$M/db" \
-Fu"$M/net" -Fi"$M/net" \
-Fu"$M/crypt" -Fi"$M/crypt" \
-Fu"$M/rest" -Fi"$M/rest" \
-Fu"$M/soa" -Fi"$M/soa" \
-Fu"$M/app" -Fi"$M/app" \
-Fu"$M/lib" -Fi"$M/lib" \
-FUbuild_linux \
-obuild_linux/test_runner_linux \
test/test_runner.dpr
The Linux test_runner runs identically to its Windows counterpart,
except that the --noenter flag is silently rejected because the
post-test press-key prompt is Windows-only in mORMot's
TSynTestsLogged.RunAsConsole. Run without it on Linux:
./build_linux/test_runner_linux
Live PostgreSQL and live Ollama tests skip cleanly when the
WSL-internal localhost:5432 / localhost:11434 do not point at the
Windows host's loopback. To enable them across the WSL boundary, set
the env vars to the Windows host IP visible inside WSL (typically
172.<x>.<y>.<z> or the host's name with .local).
macOS
Not yet validated end-to-end, but expected to work via FPC + Lazarus
on the same lazbuild path used on Windows; the only macOS-specific
piece would be the libpq location, which SynDBPostgresLibrary (or
the --libpq CLI flag) lets you override.