PDFium-komponentti löytää natiivikirjastonsa kiinteän, järjestetyn hakuketjun kautta sen jättämisen sijaan käyttöjärjestelmän lataajalle, koska eksplisiittinen jakelupuu on jakelupuu, jonka voit debugata. Windowsilla kyseinen ketju etsii Win32- tai Win64-alikansiota, jonka asennusohjelma jo toimittaa. Muilla kohteilla se rakentaa alikansion nimen Free Pascal -kohtemakroista muodossa <cpu>-<os>, joten jakelupuu lukee täsmälleen kuten käännettyjen yksiköiden puu. Tuo viimeinen päätös toi vian, joka on koko artikkelin arvoinen, koska syy oli iso kirjain ja oire oli hiljaisuus
Ketju järjestyksessä
Neljä sijaintia, kokeillaan järjestyksessä, sitten alustan lataaja viimeisenä keinona. Ensiksi ensisijainen asettelu, DLLs-kansio suoritettavan vieressä, joka sisältää yhden alikansion per kohde. Toiseksi vaihtoehtoinen asettelu, jossa kohdealikansio on suoraan suoritettavan vieressä. Kolmanneksi tasainen perinneasettelu, kirjasto suoritettavan vieressä ilman alikansiota lainkaan. Neljänneksi, vain Windowsilla, järjestelmäkansio, joka vaatii huolellisuutta, koska 32-bittisen prosessin on katsottava kohteeseen SysWOW64 ja 64-bittisen prosessin kohteeseen System32, eikä 32-bittisellä Windowsilla entistä ole olemassa, joten haku on palattava taaksepäin. Vasta kaiken tämän jälkeen lataajalta pyydetään hakemaan omatoimisesti
Järjestelmäkansiovaihetta ei ole tarkoituksella Windowsin ulkopuolella. Alustan lataajan oma hakupolku, jota ajaa ajonaikaisen linkittäjän konfiguraatio ja kirjastopolkuympäristö, kattaa jo kyseisen maaston, ja sen monistaminen Pascalilla tarkoittaisi sääntöjen uudelleentoteuttamista, jotka vaihtelevat jakelun mukaan. Windows-ketjun vikojen diagnosointi käsitellään erikseen artikkelissa PDFium DLL:n käyttöönotto ja latausvikojen diagnosointi
Mistä alikansion nimi tulee
Windowsilla se on Win32 tai Win64, ja sen päättää käynnissä olevan prosessin bittisyys eikä käyttöjärjestelmän, koska juuri se päättää, minkä binäärin voi ladata. Kaikkialla muualla nimi rakennetaan kääntäjän kohdemakroista niin, että kone, joka kääntää kahdelle arkkitehtuurille, tuottaa kaksi selkeästi erotettua puuta, ja niin, että natiivikirjaston kantava kansio istuu käännettyjen yksiköiden kantavan kansion vieressä samalla nimellä
function BuildDllSubDir(UseV8: Boolean): string;
begin
{$IFDEF MSWINDOWS}
if IsWin64 then
Result := 'Win64'
else
Result := 'Win32';
{$ELSE}
// Kääntäjän makrot kirjoittavat käyttöjärjestelmän isolla alkukirjaimella
// (”Linux”, ”Darwin”), mutta paketin yksikkötulostuskansio ei, joten
// ne sopivat yhteen vasta taittamisen jälkeen. Isolla ja pienellä
// kirjaimella erottelevalla tiedostojärjestelmällä tuo ero on koko haku
Result := LowerCase({$I %FPCTARGETCPU%} + '-' + {$I %FPCTARGETOS%});
{$ENDIF}
end;
Miksi iso kirjain rikkoi koko ketjun
Kääntäjän makro kirjoittaa kohdekäyttöjärjestelmän isolla alkukirjaimella: Win64, Linux, Darwin. Lazarus-paketti kirjoittaa yksikkötulosteensa kansioon, joka on nimetty sen omasta kohdemuuttujasta, joka on pienellä kirjaimella: win64, linux, darwin. Kaksi kirjoitusasua samasta asiasta, eikä mitään tapaa huomata sitä Windowsilla, jossa tiedostojärjestelmä ei erota niitä
Linuxilla ne ovat kaksi eri kansiota. Jakelu, joka laittaa jaetun objektin kohteeseen DLLs/x86_64-linux, on näkymätön lataajalle, joka etsii kohdetta DLLs/x86_64-Linux, joten kaikki ketjun neljä eksplisiittistä vaihetta ohitetaan ja koodi putoaa alustan lataajan hakemiselle. Joskus se toimii, jos kirjasto sattuu olemaan asennettuna järjestelmänlaajuisesti, ja joskus ei, ja kummassakin tapauksessa huolella järjestetty jakelupuu ei osallistu mitenkään. Vikalla ei ole virheviestiä, koska mikään ei epäonnistunut: jokainen vaihe raportoi oikein, ettei tiedosto ollut siellä, missä se katsoi
Koetusohjelma, käännettynä ja ajettuna
Tätä virheluokkaa ei voi löytää lukemalla, eikä sitä voi löytää kääntämälläkään. Tavallinen tekniikka alustahaaran varmentamiseen, joka ei koskaan käänny kehityskoneella, on kopioida yksikkö väliaikaiseen kansioon, nimetä se uudelleen, korvata alustaehdollinen symbolilla, jota ei koskaan määritellä, ja kääntää kopio; jos se kääntyy, uses-lause ja kutsusignatuurit kyseisellä polulla ovat ainakin itsensä kanssa yhdenmukaisia. Se toimii hyvin itsenäiselle yksikölle
Se ei toimi tässä. Pääsidontayksikkö on hyvin suuri ja se vetää LCL:n mukaan, joten sitä ei voi yksinkertaisesti kopioida ja kääntää Windows-symbolin ollessa pois päältä. Sen sijaan muutama funktio, joita muutos kosketti, transkriboitiin sanatarkasti pieneen itsenäiseen ohjelmaan, ja kyseinen ohjelma ajettiin. Se tulosti arvon x86_64-Win64, ja erimielisyys oli näkyvissä yhdellä tulosterivillä. Saman ohjelman kääntäminen ei olisi kertonut mitään, koska merkkijono on täysin pätevä; vain sen arvo on väärä
program ProbeSubDir;
{$MODE DELPHI}
uses
SysUtils;
begin
// Tulosta, älä assertoi. Pointtina on katsoa arvo, johon makro
// oikeasti laajenee tällä työkaluketjulla
Writeln('raw: ', {$I %FPCTARGETCPU%}, '-', {$I %FPCTARGETOS%});
Writeln('folded: ', LowerCase({$I %FPCTARGETCPU%} + '-' +
{$I %FPCTARGETOS%}));
end.
Yleinen opetus: kun alustojen välinen muutos koskee jonkin asian arvoa eikä sen tyyppiä, vain kääntävä varmennus ei ole varmennus. Tulosta se. Laajempi joukko Delphin ja Free Pascalin välisiä ristikääntäjieroja on koottu artikkeliin Delphi- ja FPC-ristikääntäjäkuilut
Anna alustan selittää omat latausvikansa
Lataajan Windows-haara luettaa käsin ne syyt, joilla lataus voi epäonnistua, koska hyödylliset erot siellä, arkkitehtuurin täsmäämättömyys, puuttuva siirtymäriippuvuus, polku, joka ei ratkea, kartoittuvat virhekoodeiksi, jotka kannattaa nimetä erikseen. Windowsin ulkopuolella kannettava lataajayksikkö palauttaa jo kuvaavan merkkijonon, joka kattaa saman maaston, joten ei-Windows-haara käyttää sitä suoraan sen sijaan että johtaisi kategoriat uudelleen virhenumerosta, joka tarkoittaa eri asioita eri järjestelmissä
Kiusauksen vastustaminen normalisoida nuo kaksi yhdeksi viestiksi on tahallista. Latausvika on jakeluongelma, ja viestiä lukevan henkilön tarvitsee alustan omaa sanastoa löytääkseen sen
Nimitörmäys, joka rekursioituu
Vielä yksi ansa, pieni ja terävä. Kannettava lataajayksikkö vie proseduurin nimeltä UnloadLibrary, ja sidontayksiköllä on samanniminen proseduuri, joka tekee oman kirjanpitonsa ennen kahvan vapauttamista. Kyseisen proseduurin sisällä kutsu ilman yksikköetuliitettä funktioon UnloadLibrary ratkeaa nykyisen yksikön versioon, joka kutsuu itseään. Korjaus on pätevöittää kutsu yksikkönimellä
Tämä on sama muoto kuin tunnisteen varjostusongelmat, jotka hallitsevat Free Pascal -porttauksia yleisesti: Windows-yksikkö vie kokonaislukutyyppiset minimi- ja maksimifunktiot, jotka varjostavat liukulukuversiot, ja synkronointityypin, joka varjostaa samannimisen luokan, ja jokaisessa tapauksessa ratkaisu riippuu uses-lauseen järjestyksestä. Kutsupaikan pätevöittäminen on korjaus, joka ei riipu siitä, että joku säilyttäisi kyseisen järjestyksen myöhemmin
Käyttöönoton tarkistusluettelo
Kolme asiaa selittävät useimmat latausviat, kun polkuaritmetiikka on oikein. Arkkitehtuurin on täsmättävä prosessiin, ei koneeseen, joten 32-bittinen sovellus 64-bittisellä Windowsilla tarvitsee 32-bittisen binäärin. V8 käytössä olevalla käännöksellä on eri tiedostonimi, joten jakelu, joka sekoittaa ne, näyttää oikealta eikä lataa mitään. Ja vain yksi variantti voi asua järjestelmäkansiossa kerrallaan, mikä on hyvä syy suosia eksplisiittistä alikansioasettelua minkään asentamiseen järjestelmänlaajuisesti
Lazaruksen osalta erityisesti: laita natiivikirjasto kohteeseen DLLs/<cpu>-<os> pienellä kirjaimella, suoritettavan vieressä, ja se löytyy ketjun ensimmäisellä vaiheella jokaisella kohteella. Lazarus-esimerkkikatselin, joka harjoittaa tätä, on kuvattu artikkelissa Lazarus- ja FPC-katselin, ja nykyinen alustatuki on lueteltu PDFium Delphi -komponentin tuotesivulla