Kennisbank

Het upgraden van Delphi software op een slimme manier

Dit jaar (2020) viert Delphi zijn 25e verjaardag. In die 25 jaar is er een enorme hoeveelheid code geschreven. Veel van deze toepassingen worden nog steeds volop gebruikt door bedrijven en particulieren. Dit toont de kracht van Delphi: code die tientallen jaren geleden is geschreven werkt nog steeds, zelfs in de laatste Delphi versies.

Toch zijn er hierbij nog enkele opmerkingen te maken. Helaas zien we dat er ook veel applicaties zijn die nog steeds in oude Delphi versies worden ontwikkeld. Dat is jammer, want de nieuwe versies van Delphi hebben echt veel voordelen. Niet alleen is de IDE veel prettiger in gebruik, ook de nieuwe taalverbeteringen zijn een echte verbetering.

Er zijn een aantal terugkerende problemen bij het converteren van oudere Delphi applicaties naar de nieuwste Delphi versie. Zo moet je vanaf Delphi 2009 rekening houden met Unicode. Daarnaast kunnen er componenten zijn die niet meer ontwikkeld worden, of die aanzienlijk zijn aangepast. Dit betekent dat er nog steeds bedrijven zijn die met Delphi 5, Delphi 7 of enkele andere oude versies werken. Nu is het converteren van de broncode niet altijd even gemakkelijk. Bij GDK Software hebben we veel projecten en klanten gehad die met oudere Delphi software naar ons toe kwamen. Omdat we vaak dezelfde problemen tegenkomen, hebben we een tool ontwikkeld die de conversie veel gemakkelijker maakt; de GDK Compiler Helper. In deze post leg ik kort uit hoe de GDK Compiler Helper ons helpt bij de conversieprojecten en hoe GDK Software ook kan helpen bij de upgrade van jullie Delphi project.

GDK Compiler Helper

 

De GDK Compiler Helper gebruikt de Delphi compiler om automatisch programma’s te compileren, fouten te zoeken en code te wijzigen om deze fouten te herstellen. Omdat alle wijzigingen via acties worden uitgevoerd, kun je gewoon de laatste codebase pakken en de conversie elke keer opnieuw starten. Bij de ontwikkeling van de GDK Compiler Helper hebben we er altijd aan gedacht om de conversie zoveel mogelijk te automatiseren.

Ik begin met een korte introductie in de mechanica van de GDK Compiler Helper. Daarna zal ik enkele voorbeelden geven van de verschillende acties die de tool kan uitvoeren.

Pre-compilatie

We voeren een aantal stappen automatisch uit voordat we met het compilatieproces beginnen. Eerst doen we een pre-compileer actie op alle broncode. Deze bestaat uit de volgende acties:

  1. Converteer alle formbestanden (.dfm-bestanden) naar tekstbestanden
  2. Voer alle pre-process acties uit die zijn gedefinieerd

Om te beginnen met het eerste punt; met Delphi is het mogelijk om formulierbestanden op te slaan als binaire bestanden. Aangezien het mogelijk is om componenten te vervangen door de compiler helper, moeten de formbestanden worden opgeslagen als leesbare tekstbestanden.

Vervolgens voeren we alle pre-proces acties uit. Stel dat we weten dat er in elk pascal-bestand bepaalde wijzigingen moeten worden aangebracht, dan kunnen we deze in de actielijst specificeren. De compiler helper zal deze acties eerst uitvoeren op alle broncode, alvorens de eigenlijke compilatie te starten.

Compilatie

Vervolgens gebruiken we de Delphi compiler om het project te compileren en fouten te herstellen.

Voor het oplossen van fouten, waarschuwingen en hints hebben we een database met acties opgezet, die de compilerhelper gebruikt om automatisch codewijzigingen uit te voeren en de broncode opnieuw te compileren. Een actie kan bestaan uit:

  • Voeg een unit toe aan de uses
  • Verwijderen of hernoemen van units
  • Wijzig de code met behulp van een eenvoudige replace
  • Wijzig de code met behulp van Reguliere expressies
  • Voeg een prefix toe aan een identifier of variabele
  • Wijzig het type van een variabele
  • Vervang een (design time) component
  • Vervang alle code via een replace of een Reguliere expressie over een volledig pascal-bestand

Voorbeelden van acties

Omdat we bij GDK Software veel conversies hebben uitgevoerd, hebben we een vrij uitgebreide database van deze acties samengesteld. Via de GDK Compiler Helper kunnen we deze acties eenvoudig toevoegen en bewerken:

Enkele voorbeelden van compilatiefouten en de bijbehorende acties zijn:

error E2003: Undeclared identifier: 'CurrencyString'

De oplossing is de actie AddPrefixToIdentifier en het voorvoegsel of de oplossing is FormatSetting.. Hier werkt de GDK Compiler Helper de code automatisch bij naar FormatSettings.CurrencyString. Hetzelfde geldt voor de volgende fouten:

error E2003: Undeclared identifier: 'CurrencyFormat'
error E2003: Undeclared identifier: 'CurrencyDecimals'
error E2003: Undeclared identifier: 'DateSeparator'
error E2003: Undeclared identifier: 'TimeSeparator'
[...enz]

Een ander voorbeeld:

error E2003: Undeclared identifier: 'VarArrayOf'

In dit geval moet een unit worden toegevoegd aan de uses. Dit wordt gedaan door gebruik te maken van de actie AddUnitToInterface waar de unit System.Variants is toegevoegd.

Een voorbeeld van een meer complexe actie is de oplossing voor het volgende probleem:

error E1050: WideChar reduced to byte char in set expressions. Consider using 'CharInSet' function in 'SysUtils' unit.

In dit voorbeeld hebben we de Delphi-waarschuwingen geïdentificeerd als fouten. De oplossing voor dit probleem is de actie ReplaceByRegEx. Voor een vervangingsactie (zowel de reguliere actie als de Regular Expressions actie) moeten we twee parameters specificeren; de zoekstring, en het resultaat. In dit specifieke geval was de zoekstring een vrij complexe Regular Expressions functie.

([\w\^]+[[]?[\w\+\.\-\s]+[]]?)\s+[Ii][Nn]\s+([a-zA-Z0-9[\s]*[Cc][Hh][Rr][(][\d]+[)]*[a-zA-Z0-9'?,\s(\]]*[Cc][Hh][Rr][(][\d]+[)]*[]\)]?)

en het resultaat

CharInSet(\1, \2)

De Compiler Helper zal deze oplossing toepassen op de specifieke regel van de code, waarna het compilatieproces wordt voortgezet met de rest van de broncode.

Toevoegen acties

Tijdens het werken aan een conversie wil je uiteraard zo eenvoudig mogelijk nieuwe acties toevoegen. Hoewel de GDK Compiler Helper nogal wat zaken automatisch kan oplossen, zijn er altijd specifieke problemen die voor een project opgelost moeten worden. Daarom kun je eenvoudig je eigen oplossingen en acties toevoegen.

Ter illustratie laat ik een voorbeeld zien van een deel van de conversie van de (open source) MPEG Audio Collection Library. Een van de Delphi projecten geeft de volgende foutmelding:
error E2003: Undeclared identifier: 'ReadLn'

De corresponderende coderegel is:

Str := TCP.ReadLn;

Door het analyseren van de broncode weet ik dat de ReadLn functie van de Indy Libraries nu in de unit TCP.IOHandler zit in plaats van in de unit TCP. Dus we hebben de actie ReplaceIdentifier nodig en vervangen TCP. door TCP.IOHandler. Het toevoegen van deze actie is nu zeer eenvoudig:

Het belangrijkste voordeel van het wijzigen van uw broncode op deze manier is dat deze herbruikbaar is. Als deze specifieke code ergens anders weer voorkomt, zal de GDK Compiler Helper deze oplossing daar automatisch toepassen en verder compileren.

Zoals je hebt gezien is het ongelooflijk eenvoudig om bestaande Delphi projecten te updaten naar de laatste Delphi versie met de GDK Compiler Helper. Je kunt ook de bestaande ontwikkeling van de oude versie van de software voortzetten tijdens het conversieproject. Omdat alle wijzigingen worden opgeslagen in acties kun je gewoon de laatste codebase pakken en de conversie elke keer opnieuw starten

Hoe kunnen we helpen

Bij GDK Software willen we onze kennis delen met andere ontwikkelaars en we willen bedrijven helpen om hun Delphi-software up-to-date te krijgen en te houden. Daarom hebben we interessante mogelijkheden om de GDK Compiler Helper ook voor jouw softwareproject te gebruiken.

Ben je geïnteresseerd in een persoonlijke demo van de GDK Compiler Helper, of ben je op zoek naar hulp bij het omzetten van een Delphi project? Neem dan contact met mij op via info@gdksoftware.com

Geschreven door Marco Geuze
Directeur

Contact

Laat ons helpen jouw ambities concreet te maken.