Skip to content

chore(windows): Delphi 11/12 source compatibility#16043

Open
MattGyverLee wants to merge 1 commit into
keymanapp:masterfrom
MattGyverLee:chore/windows/delphi-11-12-compat
Open

chore(windows): Delphi 11/12 source compatibility#16043
MattGyverLee wants to merge 1 commit into
keymanapp:masterfrom
MattGyverLee:chore/windows/delphi-11-12-compat

Conversation

@MattGyverLee
Copy link
Copy Markdown
Contributor

@MattGyverLee MattGyverLee commented Jun 2, 2026

Summary

Lets the existing tree compile under Delphi 11 (VER350) and Delphi 12 (VER360) without breaking Delphi 10.3 (VER330). Lowers contributor friction on #4599 and makes a future build-server bump to a paid Delphi 11/12 license a drop-in if/when that's wanted. CI is unchanged: with KEYMAN_DELPHI_VERSION unset, every build script keeps defaulting to Delphi 10.3 (BDS 20.0) exactly as before.

Split off from #16039 per @mcdurdin's review — that PR bundled the 11/12 compat work with the CE-specific build-chain workarounds. This PR is the compat half; the CE half is a separate PR.

Why this is in scope for the Delphi removal roadmap

Delphi 10.3 Pro is no longer obtainable, and CE 10.3 has been removed from Embarcadero's downloads. Any future build-server bump or new contributor onboarding must go to Delphi 11/12. This PR makes that bump a pure environment change rather than a chase for compile errors in vendored third-party code.

What's in the change

1. Build-script knob (CI-safe)

File Change
resources/build/win/configure_environment.inc.sh DELPHI_VERSION reads \${KEYMAN_DELPHI_VERSION:-20.0}
resources/build/win/delphi_environment.inc.sh Same
resources/builder.inc.sh builder_describe_platform delphi-tool probe also respects KEYMAN_DELPHI_VERSION. Without this, machines with only Delphi 12 installed had all win,delphi-gated targets silently skipped

Default unchanged. CI doesn't set the var; nothing about the canonical 10.3 flow changes.

2. Delphi 11/12 source compat in Keyman-owned code

Five files under common/windows/delphi/. Every change is additive IFDEF arms for VER350 / VER360; the VER330 (10.3) paths are untouched. Each was hit by a real compile failure on Delphi 12; the patch is the minimum needed to keep the existing code shape on 10.3 while letting it compile on 11/12.

File Change Why
tools/devtools/SourceRootPath.pas Add VER350/VER360 -> '22.0'/'23.0' DelphiMajorVersion needs to know the new BDS install dirs
web/Keyman.System.HttpServer.Base.pas Extend the IFNDEF VER330 tripwire to also accept VER340/350/360 Existing comment says "may need to check this with updated versions of Delphi" — this is that check
components/FixedTrackbar.pas Same tripwire extension Same pattern
general/CleartypeDrawCharacter.pas EnumFontFamiliesEx integer-return comparison on VER340/350/360 (was VER340-only) The Win32 wrapper return type changed in 10.4+; existing guard only covered 10.4
general/JsonUtil.pas Pass [] options arg to TJSONAncestor.ToChars on VER350/360 Delphi 11+ added a required Options parameter

3. Vendored third-party patches (please look here first)

WARNING: This is the highest-risk piece of the PR. Three files under developer/src/ext/. Each hunk is annotated with a // Keyman local patch comment plus a refresh strategy noting the upstream package and what to re-apply when those projects ship Delphi 12-compatible releases.

File Change Why
jedi/jcl/jcl/source/common/JclSynch.pas Wrap Boolean args to CreateEvent / OpenEvent / CreateWaitableTimer / OpenWaitableTimer / OpenSemaphore / CreateMutex / OpenMutex in explicit BOOL(); switch JclWin32.CreateMutex -> Winapi.Windows.CreateMutex Delphi 12 tightened implicit Boolean->BOOL conversion at call sites. BOOL() is an ordinal-preserving typecast, equivalent to the implicit conversion 10.3 was doing — no runtime semantic change. The CreateMutex unit-resolution switch matches the file's existing pattern for the other Winapi calls
jedi/jvcl/jvcl/run/JvComponent.pas On VER350+, unconditionally call DoCreate Embarcadero removed the OldCreateOrder property in Delphi 11; the modern default is equivalent to OldCreateOrder=True
mbcolor/mxs.inc Add VER350/VER360 blocks defining DELPHI_5_UP ... DELPHI_10_UP Without these, HTMLColors.pas silently drops Variants from its uses clause and breaks with "Undeclared identifier: 'null'"

4. .gitignore

Add patterns for per-arch version*.res and meson wraplock files. General build-output cleanup; not tied to either Delphi tier.

Reviewer notes

  • The vendored ext patches in section 3 are the only place real behaviour potentially shifts. The intent is no runtime change — every cast is value-preserving, and OldCreateOrder=True is what Delphi 11 already does by default. That's the spot most worth a second pair of eyes.
  • Untouched on purpose: the compiler stack (kmcmplib, kmc-*, Keyman Core). Those are already Delphi-free per chore(windows): Deprecate use of Delphi #4599 progress and aren't in this PR's blast radius.

User Testing

User testing not required: build-environment / source-compat change with no runtime behaviour modification. CI will exercise the 10.3 default path.

Relates-to

Relates-to: #4599
Replaces: #16039 (split into this PR + #16044)

Lets the existing tree compile under Delphi 11 (VER350) and Delphi 12
(VER360) without breaking Delphi 10.3 (VER330). CI is unchanged: with
KEYMAN_DELPHI_VERSION unset, every build script keeps defaulting to
Delphi 10.3 (BDS 20.0) exactly as before.

This is a bridge to lower contributor friction on keymanapp#4599 (deprecate
Delphi). The 10.3 build server can also be upgraded to a paid Delphi
11/12 license on top of these patches if/when that's wanted.

Build-script knob:
* resources/build/win/configure_environment.inc.sh,
  resources/build/win/delphi_environment.inc.sh: DELPHI_VERSION now
  reads ${KEYMAN_DELPHI_VERSION:-20.0}.
* resources/builder.inc.sh: builder_describe_platform's delphi tool
  detection respects the same KEYMAN_DELPHI_VERSION default, so
  machines with only Delphi 12 installed no longer have win,delphi-
  gated targets silently skipped.

Keyman-owned source compat (additive VER350/VER360 arms; VER330 paths
untouched):
* common/windows/delphi/tools/devtools/SourceRootPath.pas: teach
  DelphiMajorVersion about BDS 22.0 / 23.0 install dirs.
* common/windows/delphi/web/Keyman.System.HttpServer.Base.pas: extend
  the IFNDEF VER330 tripwire to accept VER340/350/360.
* common/windows/delphi/components/FixedTrackbar.pas: same tripwire
  extension.
* common/windows/delphi/general/CleartypeDrawCharacter.pas:
  EnumFontFamiliesEx integer-return comparison on VER340/350/360 (was
  VER340-only).
* common/windows/delphi/general/JsonUtil.pas: pass [] options arg to
  TJSONAncestor.ToChars on VER350/360 (Delphi 11+ added the parameter).

Vendored third-party patches (each hunk annotated with a "Keyman local
patch" comment plus refresh strategy):
* developer/src/ext/jedi/jcl/jcl/source/common/JclSynch.pas: wrap
  Boolean args to CreateEvent / OpenEvent / CreateWaitableTimer /
  OpenWaitableTimer / OpenSemaphore / CreateMutex / OpenMutex in
  explicit BOOL() casts (Delphi 12 tightened implicit Boolean->BOOL at
  call sites); switch JclWin32.CreateMutex -> Winapi.Windows.CreateMutex
  to match the file's existing pattern for the other Winapi calls.
* developer/src/ext/jedi/jvcl/jvcl/run/JvComponent.pas: on VER350+,
  unconditionally call DoCreate (Embarcadero removed the
  OldCreateOrder property in Delphi 11; modern behavior is equivalent
  to OldCreateOrder=True).
* developer/src/ext/mbcolor/mxs.inc: add VER350/VER360 blocks defining
  DELPHI_5_UP through DELPHI_10_UP. Without these, HTMLColors.pas
  silently drops Variants from its uses clause and breaks with
  "Undeclared identifier: 'null'".

.gitignore: add patterns for per-arch version*.res and meson
wraplock files.

Relates-to: keymanapp#4599
@github-project-automation github-project-automation Bot moved this to Todo in Keyman Jun 2, 2026
@keymanapp-test-bot keymanapp-test-bot Bot added has-user-test user-test-missing User tests have not yet been defined for the PR labels Jun 2, 2026
@keymanapp-test-bot
Copy link
Copy Markdown

User Test Results

Test specification and instructions

ERROR: user tests have not yet been defined

@keyman-server
Copy link
Copy Markdown
Collaborator

This pull request is from an external repo and will not automatically be built. The build must still be passed before it can be merged. Ask one of the team members to make a manual build of this PR.

Copy link
Copy Markdown
Member

@mcdurdin mcdurdin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks okay apart from this one thing; I don't have source of Delphi 12 to confirm but it seems precisely backwards.

Comment on lines +126 to +129
// Keyman local patch: Delphi 11/12 compat (vendored JVCL). The
// OldCreateOrder property was removed in Delphi 11; the modern semantics
// are equivalent to OldCreateOrder=True, so always call DoCreate on
// VER350+. On JVCL refresh from upstream: re-apply if not yet upstreamed.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems wrong according to the documentation for OldCreateOrder.

Comment on lines +940 to +943
// Keyman local patch: Delphi 11/12 compat (vendored JCL). Explicit BOOL() casts
// added below to satisfy Delphi 12's stricter implicit-Boolean->BOOL conversion.
// Backwards-compatible with Delphi 10.3 (BOOL is an ordinal-preserving typecast).
// On JCL refresh from upstream: re-apply if upstream hasn't picked up the cast.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this more deeply. This seems to be total nonsense!

I even took the time to try building with an unmodified JclSynch.pas to verify this -- it is completely unnecessary.

Copy link
Copy Markdown
Member

@mcdurdin mcdurdin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks pretty but it's pretty wrong. Some of the simpler patches are okay but the patches to jedi code are just plain wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore has-user-test user-test-missing User tests have not yet been defined for the PR windows/

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants