Teknisk artikkel

Delphi-komponenter for C++Builder uten lenkefeil: Unngå uoppløste eksterne

\n

Når du vedlikeholder en VCL-komponent skrevet i Delphi, men som konsumeres av både Delphi- og C++Builder-brukere, innser du raskt at de to byggesystemene behandler avhengigheter svært ulikt. En enhet som kompileres perfekt i Delphi, kan forårsake katastrofale lenkefeil i C++Builder. Dette avviket er en hyppig felle for komponentforfattere, spesielt når de legger til nye interne enheter i et eksisterende bibliotek

Her er en oversikt over hvorfor dette skjer (ved bruk av et reelt eksempel fra HotXLS-komponenten) og hvordan du kan gjøre krysskompileringsprosessen skuddsikker

Fellen: Implisitt kompilering vs. eksplisitt inkludering

Anta at du oppretter en ny Delphi-enhet, lxXlsSummary.pas, for å håndtere dokumentmetadata, og du bruker den i din primære analyseringsenhet, lxRead.pas. Du trykker på kompiler i Delphi IDE, bygget blir grønt, og du sender utdateringen

Neste dag rapporterer C++Builder-brukerne dine om en feil under lenkingsfasen: Unresolved external 'XlsReadSummaryInformation' referenced from lxRead.obj

Hva gikk galt?

Delphi-måten (dcc32)

Når Delphi-kompilatoren behandler en pakke (.dpk), ser den på enhetene som er eksplisitt oppført i contains-klausulen. Hvis en av disse enhetene benytter (bruker) en ekstern enhet (som lxXlsSummary.pas) som ikke er i contains-listen, utfører Delphi-kompilatoren implisitt statisk lenking. Den finner ganske enkelt .pas-filen i søkestien, kompilerer den til en .dcu, og baker den inn i den resulterende .bpl. Bygget lykkes, og skjuler fullstendig utelatelsen

C++Builder-måten (MSBuild / .cbproj)

C++Builders byggesystem er mye strengere. Det genererer bare C++-objektfiler (.obj) og headere (.hpp) for Delphi-enhetene som er eksplisitt oppført i <DelphiCompile>-elementgruppen i .cbproj-filen. Fordi lxXlsSummary.pas aldri ble eksplisitt registrert i prosjektfilen, opprettes ingen lxXlsSummary.obj. Når lenkeren prøver å løse kallene gjort av lxRead.obj, mangler symbolene, noe som fører til en uoppløst ekstern feil

Å løse eksterne symboler med Pragma Link og HPPEMIT

Hvis enheten skal følge med automatisk i C++Builder, kan Delphi-kilden bruke {$HPPEMIT} til å legge inn en #pragma link-direktiv i den genererte .hpp-filen. Det gjør objektfilavhengigheten synlig for C++Builder uten at hver bruker må legge til .obj-filen manuelt

Direktivet løser koblingen, men erstatter ikke registreringen i .cbproj og .dpk. Prosjektfilene må fortsatt inneholde enheten slik at byggesystemene produserer riktige .obj- og .dcu-filer i alle konfigurasjoner

Den gyldne regelen for komponentvedlikehold

For å unngå å ødelegge C++Builder-bygg, må du ta i bruk en streng registreringspolicy. Hver gang en ny Pascal-enhet legges til i biblioteket ditt, må den registreres eksplisitt på tvers av alle tre prosjektfiltypene samtidig

1. Oppdater C++Builder-prosjektet (.cbproj)

Åpne .cbproj-filen i en teksteditor og legg den nye enheten til kompileringslisten, og sørg for at du oppgir en unik byggeordre

<DelphiCompile Include="lxXlsSummary.pas">
  <BuildOrder>101</BuildOrder>
</DelphiCompile>

2. Oppdater Delphi-pakken (.dpk)

Legg til enheten i den eksplisitte contains-klausulen. Dette sikrer at Delphi-kompilatoren ikke trenger å stole på implisitt lenking, noe som generelt anses som dårlig praksis uansett

contains
  lxRead in 'lxRead.pas',
  lxXlsSummary in 'lxXlsSummary.pas';

3. Oppdater Delphi-prosjektet (.dproj)

Mens kommandolinje-kompilatoren (dcc) er avhengig av .dpk, er Delphi IDEs prosjektinspektør avhengig av .dproj. Hold den synkronisert for visuell konsistens i IDE-en

<DCCReference Include="lxXlsSummary.pas"/>

Validering med kontinuerlig integrasjon

Det ultimate forsvaret mot denne fellen er CI/CD-validering. Stol aldri utelukkende på et vellykket Delphi-bygg før du sender en komponent med to språk. Byggeskriptene dine må påkalle MSBuild på C++Builder-prosjektene (for eksempel build-Win32-Lib-CB.cmd) og kjøre en fullstendig lenke til C++-prøveversjonen og fulle demoer. Bare når C++-lenkeren lykkes, kan du være sikker på at alle Delphi-enheter er riktig registrert og eksponerer symbolene sine for C++-kjøretidsmiljøet

Merk: Kryssplattform-kompilatorkompatibilitet opprettholdes strengt på tvers av Delphi- og C++Builder-utgavene av HotXLS VCL Component

\n
\n