Komponenta PDFium najde svojo domorodno knjižnico skozi fiksno, urejeno verigo iskanja namesto da bi jo prepustila nalagalniku operacijskega sistema, ker je drevo namestitve, ki je izrecno, drevo namestitve, ki ga lahko razhroščujete. Na Windows ta veriga išče podmapo Win32 ali Win64, ki jo namestitveni program že pošilja. Na drugih ciljih zgradi ime podmape iz makrojev cilja Free Pascal, kot <cpu>-<os>, tako da drevo namestitve bere natanko kot drevo prevedenih enot. Ta zadnja odločitev je uvedla hrošča, vrednega celega članka, ker je bil vzrok velika črka in simptom tišina
Veriga, po vrstnem redu
Štiri lokacije, poskušane v zaporedju, nato nalagalnik platforme kot zadnja rešitev. Najprej prednostna razporeditev, mapa DLLs poleg izvedljive datoteke, ki vsebuje eno podmapo na cilj. Drugo alternativna razporeditev s podmapo cilja naravnost poleg izvedljive datoteke. Tretje ravna podedovana razporeditev, knjižnica sedi poleg izvedljive datoteke brez sploh nobene podmape. Četrto, samo na Windows, sistemska mapa, ki potrebuje skrb, ker mora 32-bitni proces gledati v SysWOW64 in 64-bitni proces v System32, in na 32-bitnem Windows prvi ne obstaja, tako da mora iskanje pasti nazaj. Šele po vsem tem je nalagalnik vprašan, naj išče sam
Namensko ni koraka sistemske mape zunaj Windows. Lastna iskalna pot nalagalnika platforme, gnana s strani konfiguracije izvajalnega povezovalnika in okolja poti knjižnic, že pokriva to področje, podvajanje nje v Pascalu bi pomenilo ponovno implementiranje pravil, ki se razlikujejo po distribuciji. Diagnosticiranje odpovedi v verigi Windows je pokrito ločeno v namestitvi DLL PDFium in diagnosticiranju odpovedi nalaganja
Od kod pride ime podmape
Na Windows je Win32 ali Win64, odločeno z bitnostjo tekočega procesa in ne operacijskega sistema, ker je to tisto, kar določa, katera binarna datoteka se lahko naloži. Povsod drugje je ime zgrajeno iz makrojev cilja prevajalnika, tako da stroj, ki gradi za dve arhitekturi, proizvede dve jasno ločeni drevesi, in tako, da mapa, ki drži domorodno knjižnico, sedi poleg mape, ki drži prevedene enote, z istim imenom
function BuildDllSubDir(UseV8: Boolean): string;
begin
{$IFDEF MSWINDOWS}
if IsWin64 then
Result := 'Win64'
else
Result := 'Win32';
{$ELSE}
// Makroji prevajalnika velikajočajo OS (»Linux«, »Darwin«), izhodna
// mapa enot paketa pa ne, tako da se ti dve ujemata šele po zlaganju.
// Na sistemu datotek, občutljivem na velike in male črke, je ta
// razlika celotno iskanje
Result := LowerCase({$I %FPCTARGETCPU%} + '-' + {$I %FPCTARGETOS%});
{$ENDIF}
end;
Zakaj je velika črka polomila celo verigo
Makro prevajalnika črkuje ciljni operacijski sistem z začetnico veliko: Win64, Linux, Darwin. Paket Lazarus zapiše svoj izhod enot v mapo, poimenovano iz svoje lastne spremenljivke cilja, ki je mala: win64, linux, darwin. Dve črkovanji iste stvari in noben način opažanja na Windows, kjer sistem datotek ne razlikuje njiju
Na Linuxu sta dve različni mapi. Namestitev, ki da skupni objekt v DLLs/x86_64-linux, je nevidna nalagalniku, ki išče DLLs/x86_64-Linux, tako da vsi štirje izrecni koraki verige zgrešijo in koda pade skozi na pustiti nalagalniku platforme iskati. Včasih to deluje, če je knjižnica slučajno nameščena po celem sistemu, včasih pa ne, in v obeh primerih skrbno urejeno drevo namestitve ne prispeva ničesar. Odpoved nima sporočila napake, ker nič ni odpovedalo: vsak korak je pravilno poročal, da datoteka ni bila tam, kjer je gledal
Program sonde, preveden in pognan
Ta razred hroščev ni mogoče najti z branjem in ga ni mogoče najti niti s prevajanjem. Običajna tehnika za preverjanje veje platforme, ki se nikoli ne prevede na razvojnem stroju, je kopirati enoto v začasno mapo, jo preimenovati, zamenjati pogoj platforme s simbolom, ki ni nikoli definiran, in prevesti kopijo; če se prevede, so razdelek uses in podpisi klicev na tej poti vsaj samoskladni. To deluje dobro za samozadostno enoto
Tukaj ne deluje. Glavna vezalna enota je zelo velika in vleče LCL noter, zato je ne more preprosto kopirati in prevesti z izklopljenim simbolom Windows. Namesto tega je bila peščica funkcij, ki jih je sprememba dotaknila, prepisana dobesedno v majhen samozadosten program in ta program je bil pognan. Natisnil je x86_64-Win64 in neskladje je bilo vidno v eni vrstici izhoda. Prevajanje istega programa vam ne bi reklo ničesar, ker je niz popolnoma veljaven; samo njegova vrednost je napačna
program ProbeSubDir;
{$MODE DELPHI}
uses
SysUtils;
begin
// Natisnite, ne trdite. Točka je pogledati vrednost, v katero se
// makro dejansko razširi na tej orodjarni
Writeln('raw: ', {$I %FPCTARGETCPU%}, '-', {$I %FPCTARGETOS%});
Writeln('folded: ', LowerCase({$I %FPCTARGETCPU%} + '-' +
{$I %FPCTARGETOS%}));
end.
Splošna lekcija: ko zadeva sprememba čez platforme vrednost česa in ne njenega tipa, je preverjanje samo-prevajanje ni preverjanje. Natisnite jo. Širši nabor razlik čez prevajalnike med Delphi in Free Pascal je zbran v članku o pasteh čez prevajalnike Delphi in FPC
Pustite platformi razložiti svoje odpovedi nalaganja
Veja Windows nalagalnika ročno oštevilči razloge, ki jih nalaganje lahko odpove, ker se uporabne razlike tam — neskladje arhitektur, manjkajoča tranzitivna odvisnost, pot, ki se ne razreši — preslikajo v kode napak, vredne posameznega poimenovanja. Zunaj Windows prenosljiva enota nalagalnika že vrne opisni niz, ki pokriva isto področje, tako da veja ne-Windows uporabi njega neposredno namesto ponovnega izpeljevanja kategorij iz številke napake, ki pomeni različne stvari na različnih sistemih
Upiranje nagibu, da se ti dve normalizirata v eno sporočilo, je namerno. Odpoved nalaganja je težava namestitve in oseba, ki bere sporočilo, potrebuje lastni besednjak platforme za iskanje njega
Trčenje imen, ki se rekurzira
Še ena past, majhna in ostra. Prenosljiva enota nalagalnika izvozi proceduro, imenovano UnloadLibrary, vezalna enota pa ima proceduro istega imena, ki počne svoje lastno knjigovodstvo pred sprostitvijo ročaja. Znotraj te procedure se nekvalificiran klic UnloadLibrary razreši v tisto v trenutni enoti, ki kliče samo sebe. Popravek je kvalificirati klic z imenom enote
To je ista oblika kot težave sencenja identifikatorjev, ki prevladujejo na prenosih Free Pascal na splošno: enota Windows izvozi funkciji minimum in maksimum celoštevilskega tipa, ki senčita plavajoče-vejične različice, in tip sinhronizacije, ki senči razred istega imena, in v vsakem primeru je razrešitev odvisna od vrstnega reda razdelka uses. Kvalificiranje mesta klica je popravek, ki ni odvisen od tega, da nekdo ohrani ta vrstni red kasneje
Kontrolni seznam namestitve
Trije stvari pojasnijo večino odpovedi nalaganja, ko je aritmetika poti prava. Arhitektura se mora ujemati s procesom in ne s strojem, zato 32-bitna aplikacija na 64-bitnem Windows potrebuje 32-bitno binarno datoteko. Gradnja z omogočenim V8 ima drugo ime datoteke, zato namestitev, ki jih zmeša, bo izgledala pravilno in naložila ničesar. In samo ena različica lahko živi v sistemski mapi naenkrat, kar je dober razlog, da dajete prednost izrecni razporeditvi podmap pred nameščanjem česar koli po celem sistemu
Za Lazarus posebej dajte domorodno knjižnico pod DLLs/<cpu>-<os> z malimi črkami, poleg izvedljive datoteke, in bo najdena s strani prvega koraka verige na vsakem cilju. Vzorčni pregledovalnik, ki to vadi na Lazarusu, je opisan v članku o pregledovalniku Lazarus in FPC, trenutna podpora platformam pa je navedena na strani produkta PDFium Delphi component