Cross-Platform, Packages, Testing & Debugging

Cross-compiling requires a cross-compiler build of FPC plus target binutils and libraries; fpcupdeluxe automates installation.

41.1 Free Pascal targets

win32, win64 i386, x86_64, aarch64 (Windows on ARM in recent versions) i386, x86_64, arm, aarch64, powerpc64, riscv64, mips,...

darwin (macOS), ios x86_64, aarch64 freebsd, openbsd, netbsd i386, x86_64, aarch64 arm, aarch64, i386, x86_64 arm (Cortex-M), avr, riscv32, xtensa (ESP32), mipsel msdos, go32v2 wasi, embedded (WebAssembly) wasm32 (development versions)

Cross-compiling requires a cross-compiler build of FPC plus target binutils and libraries; fpcupdeluxe automates installation. Example:

In Lazarus, configure build modes (*Project Options → Compiler Options → Build modes*) for Debug/Release and per-platform targets.

fpc -Tlinux -Paarch64 -XP<prefix> hello.pas      # Linux ARM64 (e.g. Raspberry Pi 4/5)
fpc -Twin64 -Px86_64 hello.pas                    # Windows 64-bit

41.2 Delphi platforms

Windows 32-bit / 64-bit macOS (Intel and Apple Silicon) Professional and up (via PAServer on a Mac) iOS (device, simulator)

Professional and up (with Xcode on a Mac) Android 32/64-bit Professional and up

Enterprise and up (console, servers; FMX via FMXLinux)

41.3 Package managers and installers

Online Package Manager (OPM) *Package → Online Package Manager*: browse/install hundreds of packages (Indy, Synapse, BGRABitmap, ZeosLib,...) Lazarus packages (.lpk)

*Package → Open Package File*, compile, install (rebuilds the IDE for design-time packages) install multiple FPC/Lazarus versions, cross-compilers, and modules GetIt Package Manager built into RAD Studio (*Tools → GetIt*): libraries, components, styles, samples Delphi (some FPC support) npm-like dependency manager: boss init, boss install <github-repo>, boss update TMS Smart Setup, Delphinus

41.4 Unit testing with FPCUnit (Free Pascal)

Lazarus also offers a GUI test runner (*File → New → FPCUnit Test Application*).

program MathTests;
{$mode objfpc}{$H+}
uses
  Classes, SysUtils, fpcunit, testregistry, consoletestrunner;

type
  TMathTest = class(TTestCase)
  protected
    procedure SetUp; override;
  published                         // published methods are discovered as tests
    procedure TestAddition;
    procedure TestStrToIntFails;
  end;

procedure TMathTest.SetUp;
begin
  // runs before each test
end;

procedure TMathTest.TestAddition;
begin
  AssertEquals('2 + 2', 4, 2 + 2);
  AssertTrue('positive', 2 + 2 > 0);
end;

procedure TMathTest.TestStrToIntFails;
var
  N: Integer;
begin
  AssertFalse(TryStrToInt('abc', N));
end;

var
  App: TTestRunner;
begin
  RegisterTest(TMathTest);
  App := TTestRunner.Create(nil);
  try
    App.Initialize;
    App.Title := 'Math tests';
    App.Run;                        // try: ./mathtests --all --format=plain
  finally
    App.Free;
  end;
end.

41.5 Unit testing with DUnitX (Delphi)

Other tools: DUnit (legacy, still bundled), TestInsight (IDE integration), Delphi-Mocks and Spring4D mocks, code coverage with DelphiCodeCoverage.

unit CalculatorTests;

interface

uses
  DUnitX.TestFramework;

type
  [TestFixture]
  TCalculatorTests = class
  public
    [Setup]
    procedure Setup;
    [Test]
    procedure AddsTwoNumbers;
    [Test]
    [TestCase('Small', '2,3,5')]
    [TestCase('Negative', '-1,1,0')]
    procedure AddCases(A, B, Expected: Integer);
  end;

implementation

procedure TCalculatorTests.Setup;
begin
end;

procedure TCalculatorTests.AddsTwoNumbers;
begin
  Assert.AreEqual(4, 2 + 2);
end;

procedure TCalculatorTests.AddCases(A, B, Expected: Integer);
begin
  Assert.AreEqual(Expected, A + B);
end;

initialization
  TDUnitX.RegisterTestFixture(TCalculatorTests);

end.

41.6 Debugging

FpDebug (native, default on Windows/Linux), GDB, LLDB (macOS) integrated debugger (Windows), LLDB-based for macOS/iOS/Android/Linux

F5; conditional, hit count, logging, data (watchpoints) F5; conditions, pass counts, actions, data breakpoints

F7 into, F8 over, Shift+F8 out, F4 run to cursor F7, F8, Shift+F8, F4

Watches, Locals, Evaluate/Modify (Ctrl+F7), Call Stack, Threads, Assembler

Watches, Local Variables, Evaluate/Modify (Ctrl+F7), Call Stack, Threads, CPU view

-g debug info (DWARF), -gl line info, -gh heaptrc, -Cr -Co -Ct checks, -O-

Debug configuration: debug info, range/overflow checking, optimization off Debugging tips:

Turn on range, overflow, and I/O checks in debug builds; turn them off (if measured) in release.

Print stack traces on exceptions: FPC DumpExceptionBackTrace(Output) with -gl; Delphi madExcept/EurekaLog/JclDebug.

Log with TEventLog (FPC), OutputDebugString (Windows), or a logging library (LoggerPro, mORMot logging).

Reproduce with the smallest possible program; use Assert to check invariants.

41.7 Code quality tools

Formatters: Lazarus JEDI Code Format (*Source → JEDI Code Format*), Delphi built-in formatter (Ctrl+D), pasfmt.

Static analysis: Pascal Analyzer (Peganza), FixInsight, Delphi Code Insight/Error Insight, FPC hints and notes (-vh -vn).

Documentation generators: PasDoc, fpdoc.