Nehmen wir an, ich habe die Includedatei in einem Archiv, das zu Zeiten von XE veröffentlicht wurde. Wenn jemand, das jetzt mit Rio übersetzt, ist Rio doch nicht bekannt, und auch nicht die speziellen nötigen Anpassungen (ich denke zB an Auslesen des DecimalSeparator).
Ich habe die besten Erfahrungen gemacht, wenn ich die bedingten Abschnitte auf die alten Versionen beziehe. Z.B. gibt es die function
GetProductVersion in
System.Sysutils.pas erst ab Delphi 10 Seattle. Damit der Code auch in älteren Versionen funktioniert, gibt es an geeigneter Stelle folgende Sequenz:
Delphi-Quellcode:
{$IF RTLVersion < 30.0 Seattle}
function GetProductVersion(const AFileName: string; var AMajor, AMinor, ABuild: Cardinal): Boolean;
var
FileName: string;
InfoSize, Wnd: DWORD;
VerBuf: Pointer;
FI: PVSFixedFileInfo;
VerSize: DWORD;
begin
Result := False;
// GetFileVersionInfo modifies the filename parameter data while parsing.
// Copy the string const into a local variable to create a writeable copy.
FileName := AFileName;
UniqueString(FileName);
InfoSize := GetFileVersionInfoSize(PChar(FileName), Wnd);
if InfoSize <> 0 then
begin
GetMem(VerBuf, InfoSize);
try
if GetFileVersionInfo(PChar(FileName), Wnd, InfoSize, VerBuf) then
if VerQueryValue(VerBuf, '\', Pointer(FI), VerSize) then
begin
AMajor := HiWord(FI.dwProductVersionMS);
AMinor := LoWord(FI.dwProductVersionMS);
ABuild := HiWord(FI.dwProductVersionLS);
Result:= True;
end;
finally
FreeMem(VerBuf);
end;
end;
end;
{$IFEND}
Ein anderes Beispiel aus
PngComponents. Die Klasse
TPngImage gibt es erst seit Delphi 2009 (vorher hieß es
TPNGObject) und der Code läuft nur unter Delphi 7 und höher. Daher gibt es dort folgende Sequenz:
Delphi-Quellcode:
{$IF RTLVersion < 20.0 D2009 }
{$IF RTLVersion < 15.0 D7 }
PngComponents are only compatible with Delphi 7 and higher!
{$IFEND}
type
TPngImage = TPNGObject;
{$IFEND}
Hier noch ein paar Auszüge aus dem
Project Magician:
Delphi-Quellcode:
function CompareNatural(const Key1, Key2: string): Integer;
{$IF RTLVersion < 27.0 XE6}
function CheckCfg(const Key: string; out idx: Integer): Boolean;
const
cCfg = 'Cfg_';
begin
Result := StartsStr(cCfg, Key) and TryStrToInt(Copy(Key, 5), idx);
end;
var
idx1: Integer;
idx2: Integer;
{$IFEND}
begin
{$IF RTLVersion < 27.0 XE6 }
if CheckCfg(key1, idx1) and CheckCfg(key2, idx2) then begin
Result := CompareValue(idx1, idx2);
end
else begin
result := CompareText(key1, key2);
end;
{$ELSE}
Result := string.Compare(Key1, Key2, [coDigitAsNumbers, coIgnoreCase]);
{$IFEND}
end;
Delphi-Quellcode:
class function TCustomProjFile.GetKnownPlatforms: TArray<
string>;
begin
if FKnownPlatforms =
nil then begin
FKnownPlatforms := TArray<
string>.Create(
'
Win32', '
Win64', '
OSX32', '
iOSSimulator', '
Android'
{$IF RTLVersion < 29.0 XE8 }
, '
iOSDevice'
{$ELSE}
, '
iOSDevice32', '
Linux64', '
iOSDevice64'
{$ENDIF}
);
end;
result := FKnownPlatforms;
end;
Delphi-Quellcode:
if not moduleIsPackage and AConfig.ClearChildAppSettings then begin
{ only base platform configurations have app settings and must keep them }
if Arg.Parent.Key = buildConfiguration.Key then Exit;
Arg.Remove(sOutputExt);
Arg.Remove(sIcon_MainIcon);
Arg.Remove(sIcns_MainIcns);
Arg.Remove(sManifest_File);
{$IF RTLVersion >= 30.0 Seattle}
Arg.Remove(sAppEnableRuntimeThemes);
Arg.Remove(sAppEnableHighDPI);
Arg.Remove(sAppEnableAdministrator);
Arg.Remove(sCustom_Styles);
{$ENDIF}
end;
Alle diese Konstrukte benötigen nicht die tatsächlichen VERxxx Bedingungen und compilieren in der Regel ohne Änderungen auf einer neuen Delphi Version. Deswegen kommen die Projekte auch ohne sowas wie die
JEDI.inc oder COMPILERS.inc oder wie sie alle heißen aus.
Wenn irgendwas mit einer neuen Version nicht compiliert, wird die aktuelle Version des betreffenden Codes in ein passendes $IF-Konstrukt eingepackt, das den neuen Compiler und alle zukünftigen ausschließt und der verbleibende Code wird für den neuen Compiler angepasst, gegebenenfalls im ELSE Teil. Damit habe ich wieder für die nächsten Jahre Ruhe.