diff --git a/.gitignore b/.gitignore index 7b872195880..dd7d41d3709 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ /windows/src/**/*.identcache /windows/src/**/*.vcxproj.user /windows/src/**/version.res +/windows/src/**/version*.res /windows/src/**/*.pch /windows/src/**/*.wixobj /windows/src/**/*.sbr diff --git a/common/windows/delphi/components/FixedTrackbar.pas b/common/windows/delphi/components/FixedTrackbar.pas index 50cb444a55f..096d6340415 100644 --- a/common/windows/delphi/components/FixedTrackbar.pas +++ b/common/windows/delphi/components/FixedTrackbar.pas @@ -64,16 +64,16 @@ procedure TTntFixedDrawGrid.WMEraseBkgnd(var Message: TMessage); Tested on VER320 (10.2) Tested on VER330 (10.3) - 29 Oct 2019 - mcdurdin + TODO: Not yet fully verified against Vcl.Grids.pas in VER350 (11) or VER360 (12) } -{$IFNDEF VER340} -{$MESSAGE WARN 'Not yet checked against Delphi 10.4'} -{$IFNDEF VER330} -{$IFNDEF VER320} +{$IF Defined(VER340) or Defined(VER350) or Defined(VER360)} +{$MESSAGE WARN 'TODO: Trackbar scrolling on bottom cell not yet checked against Delphi 10.4, 11.0 or 12.0'} +{$ELSEIF Defined(VER320) or Defined(VER330)} +// Tested on Delphi 10.2 (VER320) and 10.3 (VER330) +{$ELSE} {$MESSAGE ERROR 'Check that this fix is still applicable for a new version of Delphi. Checked against Delphi 10.2, 10.3' } -{$ENDIF} -{$ENDIF} -{$ENDIF} +{$IFEND} procedure TTntFixedDrawGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); diff --git a/common/windows/delphi/general/CleartypeDrawCharacter.pas b/common/windows/delphi/general/CleartypeDrawCharacter.pas index 6d1a51976de..44562012ed2 100644 --- a/common/windows/delphi/general/CleartypeDrawCharacter.pas +++ b/common/windows/delphi/general/CleartypeDrawCharacter.pas @@ -591,11 +591,11 @@ function TestFont(FFontName: string): Boolean; StrPCopy(lf.lfFaceName, FFontName); //'Code2000'); hdc := GetDC(0); //FPlane0FontName := 'Code2000'; -{$IFDEF VER340} +{$IF Defined(VER340) or Defined(VER350) or Defined(VER360)} if EnumFontFamiliesEx(hdc, lf, @EnumFallbackFonts, 0, 0) <> 0 then {$ELSE} if EnumFontFamiliesEx(hdc, lf, @EnumFallbackFonts, 0, 0) then -{$ENDIF} +{$IFEND} begin FPlane0FontName := FFontName; Result := True; diff --git a/common/windows/delphi/general/JsonUtil.pas b/common/windows/delphi/general/JsonUtil.pas index ae2b9b0e9c6..16a90bc729d 100644 --- a/common/windows/delphi/general/JsonUtil.pas +++ b/common/windows/delphi/general/JsonUtil.pas @@ -52,7 +52,11 @@ function JSONToString(obj: TJSONAncestor; ReplaceSlashes: Boolean = False): stri begin builder := TStringBuilder.Create; try +{$IF Defined(VER350) or Defined(VER360)} + obj.ToChars(builder, []); +{$ELSE} obj.ToChars(builder); +{$IFEND} Result := builder.ToString; finally builder.Free; diff --git a/common/windows/delphi/tools/devtools/DevIncludePaths.pas b/common/windows/delphi/tools/devtools/DevIncludePaths.pas index 509045d4d17..d6df62621df 100644 --- a/common/windows/delphi/tools/devtools/DevIncludePaths.pas +++ b/common/windows/delphi/tools/devtools/DevIncludePaths.pas @@ -144,6 +144,7 @@ class function TIncludePaths.AddPathToProjectXML(const ProjectXMLFileName, Path: doc: IXMLDocument; sn, node: IXMLNode; IncludePath: string; + Condition: string; I: Integer; begin if not FileExists(ProjectXMLFileName) then @@ -159,16 +160,20 @@ class function TIncludePaths.AddPathToProjectXML(const ProjectXMLFileName, Path: for I := 0 to node.ChildNodes.Count - 1 do begin sn := node.ChildNodes[I]; + // Delphi 12 EnvOptions.proj emits an empty without a + // Condition attribute; convert defensively via VarToStrDef so a Null or + // Empty variant returns '' instead of raising EVariantTypeCastError in Pos(). + Condition := VarToStrDef(sn.Attributes['Condition'], ''); if (sn.NodeName = 'PropertyGroup') and - not VarIsNull(sn.Attributes['Condition']) and - ((Pos('Win32', sn.Attributes['Condition']) > 0) or - (Pos('Win64', sn.Attributes['Condition']) > 0)) then + ((Pos('''Win32''', Condition) > 0) or (Pos('''Win64''', Condition) > 0)) then begin - IncludePath := sn.ChildNodes['DelphiBrowsingPath'].NodeValue; + // Guard against empty child nodes (e.g. ) whose + // NodeValue is Null on Delphi 12 and can't coerce to a string directly. + IncludePath := VarToStrDef(sn.ChildNodes['DelphiBrowsingPath'].NodeValue, ''); if AddPathToIncludePath(IncludePath, Path) then sn.ChildNodes['DelphiBrowsingPath'].nodeValue := IncludePath; - IncludePath := sn.ChildNodes['DelphiLibraryPath'].NodeValue; + IncludePath := VarToStrDef(sn.ChildNodes['DelphiLibraryPath'].NodeValue, ''); if AddPathToIncludePath(IncludePath, Path) then sn.ChildNodes['DelphiLibraryPath'].nodeValue := IncludePath; end; @@ -256,6 +261,7 @@ class function TIncludePaths.Reset: Boolean; doc: IXMLDocument; node: IXMLNode; ProjectFileName: string; + Condition: string; I: Integer; sn: IXMLNode; begin @@ -296,10 +302,11 @@ class function TIncludePaths.Reset: Boolean; for I := 0 to node.ChildNodes.Count - 1 do begin sn := node.ChildNodes[I]; + // See AddPathToProjectXML: guard against Delphi 12's empty + // where Attributes['Condition'] returns a Null variant. + Condition := VarToStrDef(sn.Attributes['Condition'], ''); if (sn.NodeName = 'PropertyGroup') and - not VarIsNull(sn.Attributes['Condition']) and - ((Pos('Win32', sn.Attributes['Condition']) > 0) or - (Pos('Win64', sn.Attributes['Condition']) > 0)) then + ((Pos('''Win32''', Condition) > 0) or (Pos('''Win64''', Condition) > 0)) then begin sn.ChildNodes['DelphiBrowsingPath'].NodeValue := SDefault_DelphiBrowsingPath; sn.ChildNodes['DelphiLibraryPath'].NodeValue := SDefault_DelphiSearchPath; diff --git a/common/windows/delphi/tools/devtools/SourceRootPath.pas b/common/windows/delphi/tools/devtools/SourceRootPath.pas index 360477641e7..c8372c3c6e2 100644 --- a/common/windows/delphi/tools/devtools/SourceRootPath.pas +++ b/common/windows/delphi/tools/devtools/SourceRootPath.pas @@ -14,11 +14,19 @@ interface {$IFDEF VER340} const DelphiMajorVersion = '21.0'; {$ELSE} +{$IFDEF VER350} +const DelphiMajorVersion = '22.0'; +{$ELSE} +{$IFDEF VER360} +const DelphiMajorVersion = '23.0'; +{$ELSE} ERROR: must define Delphi version {$ENDIF} {$ENDIF} {$ENDIF} {$ENDIF} +{$ENDIF} +{$ENDIF} const DelphiBasePath = 'C:\Program Files (x86)\Embarcadero\Studio\' + DelphiMajorVersion + '\'; diff --git a/common/windows/delphi/web/Keyman.System.HttpServer.Base.pas b/common/windows/delphi/web/Keyman.System.HttpServer.Base.pas index d1daf087c39..9af0ac60e96 100644 --- a/common/windows/delphi/web/Keyman.System.HttpServer.Base.pas +++ b/common/windows/delphi/web/Keyman.System.HttpServer.Base.pas @@ -44,10 +44,15 @@ function CrackUTF8ZeroExtendedString(CommandType: THTTPCommandType; const p: str end; // Indy's UTF8 handling of URLs is *completely* broken. - // We may need to check this with updated versions of Delphi -{$IFNDEF VER330} - ERROR! Check if this is still needed with Delphi update -{$ENDIF} + // We may need to check this with updated versions of Delphi. + // VER340/VER350/VER360 (10.4/11/12): unblocked but not re-verified; workaround kept. +{$IF Defined(VER340) or Defined(VER350) or Defined(VER360)} + {$MESSAGE WARN 'TODO: Check if Indy URL UTF-8 handling is still needed with Delphi 10.4/11.0/12.0'} +{$ELSEIF Defined(VER330)} + // Verified against Delphi 10.3 (VER330) +{$ELSE} + {$MESSAGE ERROR 'Check if Indy URL UTF-8 handling is still needed with Delphi update'} +{$IFEND} SetLength(s, p.Length); for i := 1 to p.Length do diff --git a/developer/src/ext/jedi/jcl/jcl/source/common/JclSynch.pas b/developer/src/ext/jedi/jcl/jcl/source/common/JclSynch.pas index f73b1722b09..c014318f09e 100644 --- a/developer/src/ext/jedi/jcl/jcl/source/common/JclSynch.pas +++ b/developer/src/ext/jedi/jcl/jcl/source/common/JclSynch.pas @@ -1075,7 +1075,10 @@ constructor TJclMutex.Create(SecAttr: PSecurityAttributes; InitialOwner: Boolean begin inherited Create; FName := Name; - FHandle := JclWin32.CreateMutex(SecAttr, InitialOwner, PChar(Name)); + // Keyman patch (D12, source-compiled JCL): JclWin32.CreateMutex is an external + // decl with a BOOL param; D12 rejects Boolean->BOOL there (E2010). Route via the + // RTL like OpenMutex below. Only bites when JCL is built from source. + FHandle := {$IFDEF HAS_UNITSCOPE}Winapi.{$ENDIF}Windows.CreateMutex(SecAttr, BOOL(InitialOwner), PChar(Name)); if FHandle = 0 then raise EJclMutexError.CreateRes(@RsSynchCreateMutex); FExisted := GetLastError = ERROR_ALREADY_EXISTS; diff --git a/developer/src/ext/jedi/jvcl/jvcl/run/JvComponent.pas b/developer/src/ext/jedi/jvcl/jvcl/run/JvComponent.pas index 1877ee48efe..9c0cd1e9719 100644 --- a/developer/src/ext/jedi/jvcl/jvcl/run/JvComponent.pas +++ b/developer/src/ext/jedi/jvcl/jvcl/run/JvComponent.pas @@ -123,8 +123,10 @@ constructor TJvForm.Create(AOwner: TComponent); finally Exclude(FFormState, fsCreating); end; + {$IFDEF HAS_PROPERTY_OLDCREATEORDER} if OldCreateOrder then DoCreate; + {$ENDIF HAS_PROPERTY_OLDCREATEORDER} end; finally GlobalNameSpace.EndWrite; diff --git a/developer/src/ext/mbcolor/mxs.inc b/developer/src/ext/mbcolor/mxs.inc index 41b82ad96e5..358ee4b84b3 100644 --- a/developer/src/ext/mbcolor/mxs.inc +++ b/developer/src/ext/mbcolor/mxs.inc @@ -7,6 +7,26 @@ {$define DELPHI_10_UP} {$endif} + // Keyman patch (D11/12, vendored mbcolor): define DELPHI_*_UP on VER350/VER360 + // too, else HTMLColors.pas drops "uses Variants" and Null won't resolve. + {$ifdef VER350} + {$define DELPHI_5_UP} + {$define DELPHI_6_UP} + {$define DELPHI_7_UP} + {$define DELPHI_8_UP} + {$define DELPHI_9_UP} + {$define DELPHI_10_UP} + {$endif} + + {$ifdef VER360} + {$define DELPHI_5_UP} + {$define DELPHI_6_UP} + {$define DELPHI_7_UP} + {$define DELPHI_8_UP} + {$define DELPHI_9_UP} + {$define DELPHI_10_UP} + {$endif} + {$ifdef VER330} {$define DELPHI_5_UP} {$define DELPHI_6_UP} diff --git a/docs/build/windows.md b/docs/build/windows.md index edc756340ff..9e482a894cc 100644 --- a/docs/build/windows.md +++ b/docs/build/windows.md @@ -184,8 +184,8 @@ In bash, run the following commands: cd /c/Projects/keyman git clone https://github.com/emscripten-core/emsdk cd emsdk -emsdk install 3.1.58 -emsdk activate 3.1.58 +emsdk install 3.1.64 +emsdk activate 3.1.64 cd upstream/emscripten npm install ``` @@ -195,8 +195,8 @@ If you are updating an existing install of Emscripten: ```bash cd emsdk git pull -emsdk install 3.1.58 -emsdk activate 3.1.58 +emsdk install 3.1.64 +emsdk activate 3.1.64 cd upstream/emscripten npm install ``` @@ -257,6 +257,11 @@ of appropriate node versions during builds. for a short time. (We are actively working to remove Delphi dependencies given the licensing issues with using it.) + * If you have Delphi 11 or 12 with a CLI-capable license (Professional or + higher), set `KEYMAN_DELPHI_VERSION` to the Studio path — `22.0` for + Delphi 11, `23.0` for Delphi 12 — before running `build.sh`. The default + (`20.0`, Delphi 10.3) is preserved when the variable is unset. + Start Delphi IDE once after installation as it will create various environment files and take you through required registration. diff --git a/resources/build/win/configure_environment.inc.sh b/resources/build/win/configure_environment.inc.sh index d0bce72a812..1d274c67be1 100644 --- a/resources/build/win/configure_environment.inc.sh +++ b/resources/build/win/configure_environment.inc.sh @@ -65,9 +65,11 @@ _build_vs_environment() { _locate_rsvars() { # - # Delphi Compiler Configuration - Delphi 10.3.2 + # Delphi Compiler Configuration - defaults to Delphi 10.3 (BDS 20.0). + # Override via the KEYMAN_DELPHI_VERSION environment variable to build with + # a newer Delphi installation (e.g., KEYMAN_DELPHI_VERSION=23.0 for Delphi 12). # - DELPHI_VERSION=20.0 + DELPHI_VERSION="${KEYMAN_DELPHI_VERSION:-20.0}" DCC32PATH="$(cygpath -u "$ProgramFilesx86\\Embarcadero\\Studio\\$DELPHI_VERSION\\bin")" RSVars_path="$DCC32PATH/rsvars.bat" } diff --git a/resources/build/win/delphi_environment.inc.sh b/resources/build/win/delphi_environment.inc.sh index 0465bcb6930..a68b08421c4 100644 --- a/resources/build/win/delphi_environment.inc.sh +++ b/resources/build/win/delphi_environment.inc.sh @@ -13,7 +13,10 @@ DELPHIWARNINGS=(-W-MESSAGE_DIRECTIVE -W-IMPLICIT_STRING_CAST -W-IMPLICIT_STRING_CAST_LOSS -W-EXPLICIT_STRING_CAST -W-EXPLICIT_STRING_CAST_LOSS -W-CVT_WCHAR_TO_ACHAR -W-CVT_NARROWING_STRING_LOST -W-CVT_ACHAR_TO_WCHAR -W-CVT_WIDENING_STRING_LOST -W-UNICODE_TO_LOCALE -W-LOCALE_TO_UNICODE -W-IMPLICIT_VARIANTS -W-IMPLICIT_INTEGER_CAST_LOSS -W-IMPLICIT_CONVERSION_LOSS -W-COMBINING_SIGNED_UNSIGNED64 -W-COMBINING_SIGNED_UNSIGNED64) # !ENDIF -DELPHI_VERSION=20.0 +# DELPHI_VERSION defaults to Delphi 10.3 (BDS 20.0). Override via the +# KEYMAN_DELPHI_VERSION environment variable to build with a newer Delphi +# installation (e.g., KEYMAN_DELPHI_VERSION=23.0 for Delphi 12). +DELPHI_VERSION="${KEYMAN_DELPHI_VERSION:-20.0}" DCC32PATH="$(cygpath -u "$ProgramFilesx86\\Embarcadero\\Studio\\$DELPHI_VERSION\\bin")" source "$KEYMAN_ROOT/resources/build/win/delphi_environment_generated.inc.sh" diff --git a/resources/builder.inc.sh b/resources/builder.inc.sh index 6ec2fbcebff..7e9ea36a0e4 100755 --- a/resources/builder.inc.sh +++ b/resources/builder.inc.sh @@ -2323,7 +2323,8 @@ builder_describe_platform() { # Detect delphi compiler (see also delphi_environment.inc.sh) if builder_is_windows; then local ProgramFilesx86="$(cygpath -w -F 42)" - if [[ -x "$(cygpath -u "$ProgramFilesx86\\Embarcadero\\Studio\\20.0\\bin\\dcc32.exe")" ]]; then + local _delphi_version="${KEYMAN_DELPHI_VERSION:-20.0}" + if [[ -x "$(cygpath -u "$ProgramFilesx86\\Embarcadero\\Studio\\$_delphi_version\\bin\\dcc32.exe")" ]]; then builder_installed_tools+=(delphi) fi fi diff --git a/windows/src/global/delphi/cust/CustomisationStorage.pas b/windows/src/global/delphi/cust/CustomisationStorage.pas index db4e5c018fa..1af7f2a8a5e 100644 --- a/windows/src/global/delphi/cust/CustomisationStorage.pas +++ b/windows/src/global/delphi/cust/CustomisationStorage.pas @@ -157,8 +157,13 @@ function TCustomisationStorage.GetFileOfType(FileType: TCustFileType; StartIndex { TCustFileList } function TCustFileList.AddCustFile: TCustFile; +var + NewObj: TObject; begin - Result := Items[inherited Add(FObjectClass.Create)]; + // Delphi 12 dcc64 rejects the inline form with E2010 'TCustFile' and 'TObject'; + // splitting via a local TObject makes the widening explicit. + NewObj := FObjectClass.Create; + Result := Items[inherited Add(NewObj)]; end; constructor TCustFileList.Create(AObjectClass: TCustFileClass);