fpmkunit.pp 183 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318
  1. {
  2. This file is part of the Free Pascal Makefile Package
  3. Implementation of fpmake classes and functions
  4. Copyright (c) 2007 by the freepascal team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpmkunit;
  12. {$Mode objfpc}
  13. {$H+}
  14. {$inline on}
  15. { For target or cpu dependent dependencies add also an overload were you
  16. can pass only a set of cpus. This is disabled for now because it creates
  17. an error in the compiler with overload choosing }
  18. { define cpu_only_overloads}
  19. Interface
  20. {$IFDEF OS2}
  21. {$DEFINE NO_UNIT_PROCESS}
  22. {$ENDIF OS2}
  23. {$IFDEF GO32V2}
  24. {$DEFINE NO_UNIT_PROCESS}
  25. {$ENDIF GO32V2}
  26. {$ifndef NO_UNIT_PROCESS}
  27. {$define HAS_UNIT_PROCESS}
  28. {$endif NO_UNIT_PROCESS}
  29. {$ifndef NO_UNIT_ZIPPER}
  30. {$define HAS_UNIT_ZIPPER}
  31. {$endif NO_UNIT_ZIPPER}
  32. uses
  33. SysUtils, Classes, StrUtils
  34. {$ifdef HAS_UNIT_PROCESS}
  35. ,process
  36. {$endif HAS_UNIT_PROCESS}
  37. {$ifdef HAS_UNIT_ZIPPER}
  38. ,zipper
  39. {$endif HAS_UNIT_ZIPPER}
  40. ;
  41. Type
  42. TFileType = (ftSource,ftUnit,ftObject,ftResource,ftExecutable,ftStaticLibrary,
  43. ftSharedLibrary);
  44. TFileTypes = set of TFileType;
  45. // Please keep this order, see OSCPUSupported below
  46. TCpu=(cpuNone,
  47. i386,m68k,powerpc,sparc,x86_64,arm,powerpc64,avr,armeb
  48. );
  49. TCPUS = Set of TCPU;
  50. // Please keep this order, see OSCPUSupported below
  51. TOS=(osNone,
  52. linux,go32v2,win32,os2,freebsd,beos,netbsd,
  53. amiga,atari, solaris, qnx, netware, openbsd,wdosx,
  54. palmos,macos,darwin,emx,watcom,morphos,netwlibc,
  55. win64,wince,gba,nds,embedded,symbian,haiku,iphonesim
  56. );
  57. TOSes = Set of TOS;
  58. TCompilerMode = (cmFPC,cmTP,cmObjFPC,cmDelphi,cmMacPas);
  59. TCompilerModes = Set of TCompilerMode;
  60. TTargetType = (ttProgram,ttUnit,ttImplicitUnit,ttCleanOnlyUnit,ttExampleUnit,ttExampleProgram,ttFPDoc);
  61. TTargetTypes = set of TTargetType;
  62. TFPDocFormat = (ffHtml, ffHtm, ffXHtml, ffLaTex, ffXMLStruct, ffChm);
  63. TFPDocFormats = set of TFPDocFormat;
  64. TTargetState = (tsNeutral,tsConsidering,tsNoCompile,tsCompiled,tsInstalled,tsNotFound);
  65. TTargetStates = Set of TTargetState;
  66. TSourceType = (stDoc,stSrc,stExample,stTest);
  67. TSourceTypes = set of TSourceType;
  68. TVerboseLevel = (vlError,vlWarning,vlInfo,vldebug,vlCommand);
  69. TVerboseLevels = Set of TVerboseLevel;
  70. TCommandAt = (caBeforeCompile,caAfterCompile,
  71. caBeforeInstall,caAfterInstall,
  72. caBeforeArchive,caAfterArchive,
  73. caBeforeClean,caAfterClean,
  74. caBeforeDownload,caAfterDownload);
  75. TDependencyType = (depPackage,depImplicitPackage,depUnit,depInclude);
  76. TDependencyTypes = set of TDependencyType;
  77. TLogEvent = Procedure (Level : TVerboseLevel; Const Msg : String) of Object;
  78. TNotifyProcEvent = procedure(Sender: TObject);
  79. TRunMode = (rmCompile,rmBuild,rmInstall,rmArchive,rmClean,rmDistClean,rmManifest);
  80. TBuildMode = (bmOneByOne, bmBuildUnit{, bmSkipImplicitUnits});
  81. TBuildModes = set of TBuildMode;
  82. Const
  83. // Aliases
  84. Amd64 = X86_64;
  85. PPC = PowerPC;
  86. PPC64 = PowerPC64;
  87. DOS = Go32v2;
  88. MacOSX = Darwin;
  89. AllOSes = [Low(TOS)..High(TOS)];
  90. AllCPUs = [Low(TCPU)..High(TCPU)];
  91. AllUnixOSes = [Linux,FreeBSD,NetBSD,OpenBSD,Darwin,QNX,BeOS,Solaris,Haiku,iphonesim];
  92. AllBSDOSes = [FreeBSD,NetBSD,OpenBSD,Darwin,iphonesim];
  93. AllWindowsOSes = [Win32,Win64,WinCE];
  94. AllLimit83fsOses= [go32v2,os2,emx,watcom];
  95. AllSmartLinkLibraryOSes = [Linux]; // OSes that use .a library files for smart-linking
  96. { This table is kept OS,Cpu because it is easier to maintain (PFV) }
  97. OSCPUSupported : array[TOS,TCpu] of boolean = (
  98. { os none i386 m68k ppc sparc x86_64 arm ppc64 avr armeb}
  99. { none } ( false, false, false, false, false, false, false, false, false, false),
  100. { linux } ( false, true, true, true, true, true, true, true, false, true ),
  101. { go32v2 } ( false, true, false, false, false, false, false, false, false, false),
  102. { win32 } ( false, true, false, false, false, false, false, false, false, false),
  103. { os2 } ( false, true, false, false, false, false, false, false, false, false),
  104. { freebsd } ( false, true, true, false, false, true, false, false, false, false),
  105. { beos } ( false, true, false, false, false, false, false, false, false, false),
  106. { netbsd } ( false, true, true, true, true, false, false, false, false, false),
  107. { amiga } ( false, false, true, true, false, false, false, false, false, false),
  108. { atari } ( false, false, true, false, false, false, false, false, false, false),
  109. { solaris } ( false, true, false, false, true, false, false, false, false, false),
  110. { qnx } ( false, true, false, false, false, false, false, false, false, false),
  111. { netware } ( false, true, false, false, false, false, false, false, false, false),
  112. { openbsd } ( false, true, true, false, false, false, false, false, false, false),
  113. { wdosx } ( false, true, false, false, false, false, false, false, false, false),
  114. { palmos } ( false, false, true, false, false, false, true, false, false, false),
  115. { macos } ( false, false, false, true, false, false, false, false, false, false),
  116. { darwin } ( false, true, false, true, false, true, true, true, false, false),
  117. { emx } ( false, true, false, false, false, false, false, false, false, false),
  118. { watcom } ( false, true, false, false, false ,false, false, false, false, false),
  119. { morphos } ( false, false, false, true, false ,false, false, false, false, false),
  120. { netwlibc }( false, true, false, false, false, false, false, false, false, false),
  121. { win64 } ( false, false, false, false, false, true, false, false, false, false),
  122. { wince }( false, true, false, false, false, false, true, false, false, false),
  123. { gba } ( false, false, false, false, false, false, true, false, false, false),
  124. { nds } ( false, false, false, false, false, false, true, false, false, false),
  125. { embedded }( false, true, true, true, true, true, true, true, true, true ),
  126. { symbian } ( false, true, false, false, false, false, true, false, false, false),
  127. { haiku } ( false, true, false, false, false, false, false, false, false, false),
  128. { iphonesim}( false, true, false, false, false, false, false, false, false, false)
  129. );
  130. // Useful
  131. UnitExt = '.ppu';
  132. PPUExt = UnitExt;
  133. PasExt = '.pas';
  134. PPExt = '.pp';
  135. IncExt = '.inc';
  136. ObjExt = '.o';
  137. RstExt = '.rst';
  138. LibExt = '.a';
  139. SharedLibExt = '.so';
  140. DLLExt = '.dll';
  141. ExeExt = '.exe';
  142. ZipExt = '.zip';
  143. FPMakePPFile = 'fpmake.pp';
  144. ManifestFile = 'manifest.xml';
  145. UnitConfigFile = 'fpunits.conf';
  146. DirNotFound = '<dirnotfound>';
  147. UnitTargets = [ttUnit,ttImplicitUnit,ttCleanOnlyUnit,ttExampleUnit];
  148. ProgramTargets = [ttProgram,ttExampleProgram];
  149. DefaultMessages = [vlError,vlWarning,vlCommand];
  150. AllMessages = [vlError,vlWarning,vlCommand,vlInfo];
  151. Type
  152. { TNamedItem }
  153. TNamedItem = Class(TCollectionItem)
  154. private
  155. FName: String;
  156. procedure SetName(const AValue: String);virtual;
  157. Public
  158. property Name : String Read FName Write SetName;
  159. end;
  160. { TNamedCollection }
  161. TNamedCollection = Class(TCollection)
  162. private
  163. FUniqueNames: Boolean;
  164. Public
  165. Function IndexOfName(const AName : String) : Integer;
  166. Function ItemByName(const AName : String) : TNamedItem;
  167. Property UniqueNames : Boolean Read FUniqueNames;
  168. end;
  169. { TNamedItemList }
  170. TNamedItemList = Class(TFPList)
  171. private
  172. function GetNamedItem(Index : Integer): TNamedItem;
  173. procedure SetNamedItem(Index : Integer; const AValue: TNamedItem);
  174. public
  175. Function IndexOfName(const AName : String) : Integer;
  176. Function ItemByName(const ANAme : String) : TNamedItem;
  177. Property NamedItems[Index : Integer] : TNamedItem Read GetNamedItem Write SetNamedItem; default;
  178. end;
  179. { TCommand }
  180. TCommand = Class(TNamedItem)
  181. private
  182. FAfterCommand: TNotifyEvent;
  183. FBeforeCommand: TNotifyEvent;
  184. FCommand: String;
  185. FCommandAt: TCommandAt;
  186. FDestFile: String;
  187. FIgnoreResult: Boolean;
  188. FOptions: TStrings;
  189. FSourceFile: String;
  190. Function GetOptions : TStrings;
  191. Procedure SetOptions(Const Value : TStrings);
  192. Public
  193. Destructor Destroy; override;
  194. Function HaveOptions : Boolean;
  195. Function CmdLineOptions : String;
  196. Procedure ParseOptions(S : String);
  197. Property SourceFile : String Read FSourceFile Write FSourceFile;
  198. Property DestFile : String Read FDestFile Write FDestFile;
  199. Property Command : String Read FCommand Write FCommand;
  200. Property Options : TStrings Read GetOptions Write SetOptions;
  201. Property At : TCommandAt Read FCommandAt Write FCommandAt;
  202. Property IgnoreResult : Boolean Read FIgnoreResult Write FIgnoreResult;
  203. Property BeforeCommand : TNotifyEvent Read FBeforeCommand Write FBeforeCommand;
  204. Property AfterCommand : TNotifyEvent Read FAfterCommand Write FAfterCommand;
  205. end;
  206. { TCommands }
  207. TCommands = Class(TNamedCollection)
  208. private
  209. FDefaultAt: TCommandAt;
  210. function GetCommand(const Dest : String): TCommand;
  211. function GetCommandItem(Index : Integer): TCommand;
  212. procedure SetCommandItem(Index : Integer; const AValue: TCommand);
  213. Public
  214. Function AddCommand(Const Cmd : String) : TCommand;
  215. Function AddCommand(Const Cmd,Options : String) : TCommand;
  216. Function AddCommand(Const Cmd,Options,Dest,Source : String) : TCommand;
  217. Function AddCommand(At : TCommandAt; Const Cmd : String) : TCommand;
  218. Function AddCommand(At : TCommandAt; Const Cmd,Options : String) : TCommand;
  219. Function AddCommand(At : TCommandAt; Const Cmd,Options, Dest,Source : String) : TCommand;
  220. Property CommandItems[Index : Integer] : TCommand Read GetCommandItem Write SetCommandItem;
  221. Property Commands[Dest : String] : TCommand Read GetCommand; default;
  222. Property DefaultAt : TCommandAt Read FDefaultAt Write FDefaultAt;
  223. end;
  224. { TFPVersion }
  225. TFPVersion = Class(TPersistent)
  226. private
  227. FMajor,
  228. FMinor,
  229. FMicro,
  230. FBuild : Integer;
  231. function GetAsString: String;
  232. function GetEmpty: Boolean;
  233. procedure SetAsString(const AValue: String);
  234. Public
  235. Procedure Clear;
  236. Procedure Assign(Source : TPersistent); override;
  237. Function CompareVersion(AVersion : TFPVersion) : Integer;
  238. Function SameVersion(AVersion : TFPVersion) : Boolean;
  239. Property AsString : String Read GetAsString Write SetAsString;
  240. Property Empty : Boolean Read GetEmpty;
  241. Published
  242. Property Major : Integer Read FMajor Write FMajor;
  243. Property Minor : Integer Read FMinor Write FMinor;
  244. Property Micro : Integer Read FMicro Write FMicro;
  245. Property Build : Integer Read FBuild Write FBuild;
  246. end;
  247. { TConditionalString }
  248. TConditionalString = Class
  249. private
  250. FOSes : TOSes;
  251. FCPUs : TCPUs;
  252. FValue : String;
  253. Public
  254. Constructor Create;virtual;
  255. Property Value : String Read FValue Write FValue;
  256. Property OSes : TOSes Read FOSes Write FOSes;
  257. Property CPUs : TCPUs Read FCPUS Write FCPUs;
  258. end;
  259. TConditionalStringClass = class of TConditionalString;
  260. { TConditionalStrings }
  261. TConditionalStrings = Class(TFPList)
  262. private
  263. FCSClass : TConditionalStringClass;
  264. function GetConditionalString(Index : Integer): TConditionalString;
  265. procedure SetConditionalString(Index : Integer; const AValue: TConditionalString);
  266. Public
  267. Constructor Create(AClass:TConditionalStringClass);
  268. Function Add(Const Value : String) : TConditionalString;inline;
  269. Function Add(Const Value : String;const OSes:TOSes) : TConditionalString;inline;
  270. {$ifdef cpu_only_overloads}
  271. Function Add(Const Value : String;const CPUs:TCPUs) : TConditionalString;inline;
  272. {$endif cpu_only_overloads}
  273. Function Add(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TConditionalString;
  274. Property ConditionalStrings[Index : Integer] : TConditionalString Read GetConditionalString Write SetConditionalString; default;
  275. end;
  276. { TDependency }
  277. TDependency = Class(TConditionalString)
  278. private
  279. FDependencyType : TDependencyType;
  280. // Package, Unit
  281. FTarget : TObject;
  282. FVersion : TFPVersion;
  283. FRequireChecksum : Cardinal;
  284. // Filenames, Includes
  285. FTargetFileName : String;
  286. Function GetVersion : string;
  287. Procedure SetVersion(const V : string);
  288. Public
  289. Constructor Create;override;
  290. Destructor Destroy;override;
  291. Property Target : TObject Read FTarget Write FTarget;
  292. Property DependencyType : TDependencyType Read FDependencyType;
  293. Property TargetFileName : String Read FTargetFileName Write FTargetFileName;
  294. Property Version : String Read GetVersion Write SetVersion;
  295. Property RequireChecksum : Cardinal Read FRequireChecksum Write FRequireChecksum;
  296. end;
  297. TDependencies = Class(TConditionalStrings)
  298. function GetDependency(Index : Integer): TDependency;
  299. procedure SetDependency(Index : Integer; const AValue: TDependency);
  300. Public
  301. Function Add(Const Value : String) : TDependency;inline;
  302. Function Add(Const Value : String;const OSes:TOSes) : TDependency;inline;
  303. {$ifdef cpu_only_overloads}
  304. Function Add(Const Value : String;const CPUs:TCPUs) : TDependency;inline;
  305. {$endif cpu_only_overloads}
  306. Function Add(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TDependency;
  307. Function AddUnit(Const Value : String) : TDependency;inline;
  308. Function AddUnit(Const Value : String;const OSes:TOSes) : TDependency;inline;
  309. {$ifdef cpu_only_overloads}
  310. Function AddUnit(Const Value : String;const CPUs:TCPUs) : TDependency;inline;
  311. {$endif cpu_only_overloads}
  312. Function AddUnit(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TDependency;
  313. Function AddInclude(Const Value : String) : TDependency;inline;
  314. Function AddInclude(Const Value : String;const OSes:TOSes) : TDependency;inline;
  315. {$ifdef cpu_only_overloads}
  316. Function AddInclude(Const Value : String;const CPUs:TCPUs) : TDependency;inline;
  317. {$endif cpu_only_overloads}
  318. Function AddInclude(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TDependency;
  319. Property Dependencies[Index : Integer] : TDependency Read GetDependency Write SetDependency; default;
  320. end;
  321. { TTarget }
  322. TTarget = Class(TNamedItem)
  323. private
  324. FInstall : Boolean;
  325. FAfterClean: TNotifyEvent;
  326. FAfterCompile: TNotifyEvent;
  327. FBeforeClean: TNotifyEvent;
  328. FBeforeCompile: TNotifyEvent;
  329. FCPUs: TCPUs;
  330. FOSes: TOSes;
  331. FMode: TCompilerMode;
  332. FResourceStrings: Boolean;
  333. FObjectPath,
  334. FUnitPath,
  335. FIncludePath : TConditionalStrings;
  336. FDependencies : TDependencies;
  337. FCommands : TCommands;
  338. FDirectory: String;
  339. FExtension: String;
  340. FTargetSourceFileName : String;
  341. FFileType: TFileType;
  342. FOptions: TStrings;
  343. FFPCTarget: String;
  344. FTargetState: TTargetState;
  345. FTargetType: TTargetType;
  346. FXML: string;
  347. function GetOptions: TStrings;
  348. procedure SetOptions(const AValue: TStrings);
  349. Protected
  350. Function GetSourceFileName : String; virtual;
  351. Function GetUnitFileName : String; virtual;
  352. function GetUnitLibFileName: String; virtual;
  353. Function GetObjectFileName : String; virtual;
  354. Function GetRSTFileName : String; Virtual;
  355. Function GetProgramFileName(AOS : TOS) : String; Virtual;
  356. Public
  357. Constructor Create(ACollection : TCollection); override;
  358. Destructor Destroy; override;
  359. Function GetOutputFileName (AOs : TOS) : String; Virtual;
  360. Function HaveOptions : Boolean;
  361. procedure SetName(const AValue: String);override;
  362. procedure SetXML(const AValue: string);
  363. Procedure GetCleanFiles(List : TStrings; const APrefixU, APrefixB : String; ACPU:TCPU; AOS : TOS); virtual;
  364. Procedure GetInstallFiles(List : TStrings; const APrefixU, APrefixB: String; ACPU:TCPU; AOS : TOS); virtual;
  365. Procedure GetArchiveFiles(List : TStrings; ACPU:TCPU; AOS : TOS); virtual;
  366. Property Dependencies : TDependencies Read FDependencies;
  367. Property Commands : TCommands Read FCommands;
  368. Property State : TTargetState Read FTargetState;
  369. Property TargetType : TTargetType Read FTargetType Write FTargetType;
  370. Property OSes : TOSes Read FOSes Write FOSes;
  371. Property CPUs : TCPUs Read FCPUs Write FCPUs;
  372. Property Mode : TCompilerMode Read FMode Write FMode;
  373. Property Options : TStrings Read GetOptions Write SetOptions;
  374. Property SourceFileName: String Read GetSourceFileName ;
  375. Property UnitFileName : String Read GetUnitFileName;
  376. Property UnitLibFileName : String Read GetUnitLibFileName;
  377. Property ObjectFileName : String Read GetObjectFileName;
  378. Property RSTFileName : String Read GetRSTFileName;
  379. Property FPCTarget : String Read FFPCTarget Write FFPCTarget;
  380. Property Extension : String Read FExtension Write FExtension;
  381. Property FileType : TFileType Read FFileType Write FFileType;
  382. Property Directory : String Read FDirectory Write FDirectory;
  383. Property ResourceStrings : Boolean Read FResourceStrings Write FResourceStrings;
  384. Property Install : Boolean Read FInstall Write FInstall;
  385. Property TargetSourceFileName: String Read FTargetSourceFileName;
  386. Property ObjectPath : TConditionalStrings Read FObjectPath;
  387. Property UnitPath : TConditionalStrings Read FUnitPath;
  388. Property IncludePath : TConditionalStrings Read FIncludePath;
  389. Property XML: string Read FXML Write SetXML;
  390. // Events.
  391. Property BeforeCompile : TNotifyEvent Read FBeforeCompile Write FBeforeCompile;
  392. Property AfterCompile : TNotifyEvent Read FAfterCompile Write FAfterCompile;
  393. Property BeforeClean : TNotifyEvent Read FBeforeClean Write FBeforeClean;
  394. Property AfterClean : TNotifyEvent Read FAfterClean Write FAfterClean;
  395. end;
  396. { TTargets }
  397. TTargets = Class(TNamedCollection)
  398. private
  399. function GetTargetItem(Index : Integer): TTarget;
  400. function GetTarget(const AName : String): TTarget;
  401. procedure SetTargetItem(Index : Integer; const AValue: TTarget);
  402. Public
  403. Function AddFPDoc(Const AUnitName, AXMLName : String) : TTarget;inline;
  404. Function AddUnit(Const AUnitName : String) : TTarget;inline;
  405. Function AddUnit(Const AUnitName : String;const OSes:TOSes) : TTarget;inline;
  406. {$ifdef cpu_only_overloads}
  407. Function AddUnit(Const AUnitName : String;const CPUs:TCPUs) : TTarget;inline;
  408. {$endif cpu_only_overloads}
  409. Function AddUnit(Const AUnitName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  410. Function AddImplicitUnit(Const AUnitName : String;InstallUnit:boolean=true) : TTarget;inline;
  411. Function AddImplicitUnit(Const AUnitName : String;const OSes:TOSes;InstallUnit:boolean=true) : TTarget;inline;
  412. Function AddImplicitUnit(Const AUnitName : String;const CPUs:TCPUs;InstallUnit:boolean=true) : TTarget;inline;
  413. Function AddImplicitUnit(Const AUnitName : String;const CPUs:TCPUs;const OSes:TOSes;InstallUnit:boolean=true) : TTarget;
  414. Function AddProgram(Const AProgramName : String) : TTarget;inline;
  415. Function AddProgram(Const AProgramName : String;const OSes:TOSes) : TTarget;inline;
  416. {$ifdef cpu_only_overloads}
  417. Function AddProgram(Const AProgramName : String;const CPUs:TCPUs) : TTarget;inline;
  418. {$endif cpu_only_overloads}
  419. Function AddProgram(Const AProgramName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  420. Function AddExampleUnit(Const AUnitName : String) : TTarget;inline;
  421. Function AddExampleUnit(Const AUnitName : String;const OSes:TOSes) : TTarget;inline;
  422. {$ifdef cpu_only_overloads}
  423. Function AddExampleUnit(Const AUnitName : String;const CPUs:TCPUs) : TTarget;inline;
  424. {$endif cpu_only_overloads}
  425. Function AddExampleUnit(Const AUnitName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  426. Function AddExampleProgram(Const AProgramName : String) : TTarget;inline;
  427. Function AddExampleProgram(Const AProgramName : String;const OSes:TOSes) : TTarget;inline;
  428. {$ifdef cpu_only_overloads}
  429. Function AddExampleProgram(Const AProgramName : String;const CPUs:TCPUs) : TTarget;inline;
  430. {$endif cpu_only_overloads}
  431. Function AddExampleProgram(Const AProgramName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  432. Property Targets[AName : String] : TTarget Read GetTarget; default;
  433. Property TargetItems[Index : Integer] : TTarget Read GetTargetItem Write SetTargetItem;
  434. end;
  435. { TSource }
  436. TSource = Class(TNamedItem)
  437. private
  438. FSourceType : TSourceType;
  439. FInstallSourcePath : string;
  440. function GetInstallSourcePath: string;
  441. Public
  442. Constructor Create(ACollection : TCollection); override;
  443. Destructor Destroy; override;
  444. Procedure GetInstallFiles(List : TStrings); virtual;
  445. property SourceType : TSourceType read FSourceType;
  446. property InstallSourcePath : string read GetInstallSourcePath;
  447. end;
  448. { TSources }
  449. TSources = Class(TNamedCollection)
  450. private
  451. function GetSourceItem(Index : Integer): TSource;
  452. procedure SetSourceItem(Index : Integer; const AValue: TSource);
  453. public
  454. Function AddDoc(const AFiles : String) : TSource;
  455. Function AddDoc(const AFiles : String; AInstallSourcePath : String) : TSource;
  456. Function AddSrc(const AFiles : String) : TSource;
  457. Function AddExample(const AFiles : String) : TSource;
  458. Function AddExample(const AFiles : String; AInstallSourcePath : String) : TSource;
  459. Function AddTest(const AFiles : String) : TSource;
  460. procedure AddDocFiles(const AFileMask: string; Recursive: boolean = False; AInstallSourcePath : String = '');
  461. procedure AddSrcFiles(const AFileMask: string; Recursive: boolean = False);
  462. procedure AddExampleFiles(const AFileMask: string; Recursive: boolean = False; AInstallSourcePath : String = '');
  463. procedure AddTestFiles(const AFileMask: string; Recursive: boolean = False);
  464. Property SourceItems[Index : Integer] : TSource Read GetSourceItem Write SetSourceItem;default;
  465. end;
  466. { TPackage }
  467. TPackage = Class(TNamedItem)
  468. private
  469. FAfterArchive: TNotifyEvent;
  470. FAfterArchiveProc: TNotifyProcEvent;
  471. FAfterClean: TNotifyEvent;
  472. FAfterCleanProc: TNotifyProcEvent;
  473. FAfterCompile: TNotifyEvent;
  474. FAfterCompileProc: TNotifyProcEvent;
  475. FAfterInstall: TNotifyEvent;
  476. FAfterInstallProc: TNotifyProcEvent;
  477. FAfterManifest: TNotifyEvent;
  478. FAfterManifestProc: TNotifyProcEvent;
  479. FBeforeArchive: TNotifyEvent;
  480. FBeforeArchiveProc: TNotifyProcEvent;
  481. FBeforeClean: TNotifyEvent;
  482. FBeforeCleanProc: TNotifyProcEvent;
  483. FBeforeCompile: TNotifyEvent;
  484. FBeforeCompileProc: TNotifyProcEvent;
  485. FBeforeInstall: TNotifyEvent;
  486. FBeforeInstallProc: TNotifyProcEvent;
  487. FBeforeManifest: TNotifyEvent;
  488. FBeforeManifestProc: TNotifyProcEvent;
  489. FBuildMode: TBuildMode;
  490. FFPDocFormat: TFPDocFormats;
  491. FIsFPMakeAddIn: boolean;
  492. FSupportBuildModes: TBuildModes;
  493. FUnitPath,
  494. FObjectPath,
  495. FIncludePath,
  496. FSourcePath,
  497. FExamplePath,
  498. FTestPath,
  499. FCleanFiles,
  500. FInstallFiles : TConditionalStrings;
  501. FDependencies : TDependencies;
  502. FCPUs: TCPUs;
  503. FOSes: TOSes;
  504. FTargetState: TTargetState;
  505. FTargets: TTargets;
  506. FSources: TSources;
  507. FDirectory: String;
  508. FOptions: TStrings;
  509. FFileName: String;
  510. FAuthor: String;
  511. FLicense: String;
  512. FHomepageURL: String;
  513. FDownloadURL: String;
  514. FVersion: TFPVersion;
  515. FEmail : String;
  516. FNeedLibC : Boolean;
  517. FCommands : TCommands;
  518. FDescriptionFile : String;
  519. FDescription : String;
  520. FInstalledChecksum : Cardinal;
  521. // Cached directory of installed packages
  522. FUnitDir : String;
  523. FBUTargets: TTargets;
  524. FBUTarget: TTarget;
  525. Function GetDescription : string;
  526. Function GetFileName : string;
  527. function GetOptions: TStrings;
  528. Function GetVersion : string;
  529. procedure SetOptions(const AValue: TStrings);
  530. Procedure SetVersion(const V : string);
  531. Protected
  532. procedure SetName(const AValue: String);override;
  533. procedure LoadUnitConfigFromFile(Const AFileName: String);
  534. procedure SaveUnitConfigToStringList(Const AStringList: TStrings;ACPU:TCPU;AOS:TOS); virtual;
  535. procedure SaveUnitConfigToFile(Const AFileName: String;ACPU:TCPU;AOS:TOS);
  536. Public
  537. constructor Create(ACollection: TCollection); override;
  538. destructor destroy; override;
  539. Function HaveOptions : Boolean;
  540. Function GetUnitsOutputDir(ACPU:TCPU; AOS : TOS):String;
  541. Function GetBinOutputDir(ACPU:TCPU; AOS : TOS) : String;
  542. Procedure GetCleanFiles(List : TStrings; ACPU:TCPU; AOS : TOS); virtual;
  543. procedure GetInstallFiles(List: TStrings;Types : TTargetTypes;ACPU:TCPU; AOS : TOS); virtual;
  544. procedure GetInstallSourceFiles(List: TStrings; SourceTypes : TSourceTypes; TargetTypes : TTargetTypes); virtual;
  545. Procedure GetArchiveFiles(List : TStrings; ACPU:TCPU; AOS : TOS); virtual;
  546. Procedure GetArchiveSourceFiles(List : TStrings); virtual;
  547. Procedure GetManifest(Manifest : TStrings);
  548. Property Version : String Read GetVersion Write SetVersion;
  549. Property FileName : String Read GetFileName Write FFileName;
  550. Property HomepageURL : String Read FHomepageURL Write FHomepageURL;
  551. Property DownloadURL : String Read FDownloadURL Write FDownloadURL;
  552. Property Email : String Read FEmail Write FEmail;
  553. Property Author : String Read FAuthor Write FAuthor;
  554. Property License : String Read FLicense Write FLicense;
  555. Property Directory : String Read FDirectory Write FDirectory;
  556. Property Description : String Read GetDescription Write FDescription;
  557. Property DescriptionFile : String Read FDescriptionFile Write FDescriptionFile;
  558. Property InstalledChecksum : Cardinal Read FInstalledChecksum Write FInstalledChecksum;
  559. Property IsFPMakeAddIn: boolean read FIsFPMakeAddIn write FIsFPMakeAddIn;
  560. Property SupportBuildModes: TBuildModes read FSupportBuildModes write FSupportBuildModes;
  561. Property BuildMode: TBuildMode read FBuildMode;
  562. // Compiler options.
  563. Property OSes : TOSes Read FOSes Write FOSes;
  564. Property CPUs : TCPUs Read FCPUs Write FCPUs;
  565. Property NeedLibC : Boolean Read FNeedLibC Write FNeedLibC;
  566. Property Options: TStrings Read GetOptions Write SetOptions;
  567. Property UnitPath : TConditionalStrings Read FUnitPath;
  568. Property ObjectPath : TConditionalStrings Read FObjectPath;
  569. Property IncludePath : TConditionalStrings Read FIncludePath;
  570. Property SourcePath : TConditionalStrings Read FSourcePath;
  571. Property ExamplePath : TConditionalStrings Read FExamplePath;
  572. Property TestPath : TConditionalStrings Read FTestPath;
  573. Property FPDocFormat: TFPDocFormats read FFPDocFormat write FFPDocFormat;
  574. // Targets and dependencies
  575. Property InstallFiles : TConditionalStrings Read FInstallFiles;
  576. Property CleanFiles : TConditionalStrings Read FCleanFiles;
  577. Property Dependencies : TDependencies Read FDependencies;
  578. Property Commands : TCommands Read FCommands;
  579. Property State : TTargetState Read FTargetState;
  580. Property Targets : TTargets Read FTargets;
  581. Property Sources : TSources Read FSources;
  582. Property UnitDir : String Read FUnitDir Write FUnitDir;
  583. // events
  584. Property BeforeCompile : TNotifyEvent Read FBeforeCompile Write FBeforeCompile;
  585. Property BeforeCompileProc : TNotifyProcEvent Read FBeforeCompileProc write FBeforeCompileProc;
  586. Property AfterCompile : TNotifyEvent Read FAfterCompile Write FAfterCompile;
  587. Property AfterCompileProc : TNotifyProcEvent Read FAfterCompileProc Write FAfterCompileProc;
  588. Property BeforeInstall : TNotifyEvent Read FBeforeInstall Write FBeforeInstall;
  589. Property BeforeInstallProc : TNotifyProcEvent Read FBeforeInstallProc Write FBeforeInstallProc;
  590. Property AfterInstall : TNotifyEvent Read FAfterInstall Write FAfterInstall;
  591. Property AfterInstallProc : TNotifyProcEvent Read FAfterInstallProc Write FAfterInstallProc;
  592. Property BeforeClean : TNotifyEvent Read FBeforeClean Write FBeforeClean;
  593. Property BeforeCleanProc : TNotifyProcEvent Read FBeforeCleanProc Write FBeforeCleanProc;
  594. Property AfterClean : TNotifyEvent Read FAfterClean Write FAfterClean;
  595. Property AfterCleanProc : TNotifyProcEvent Read FAfterCleanProc Write FAfterCleanProc;
  596. Property BeforeArchive : TNotifyEvent Read FBeforeArchive Write FBeforeArchive;
  597. Property BeforeArchiveProc : TNotifyProcEvent Read FBeforeArchiveProc Write FBeforeArchiveProc;
  598. Property AfterArchive : TNotifyEvent Read FAfterArchive Write FAfterArchive;
  599. Property AfterArchiveProc : TNotifyProcEvent Read FAfterArchiveProc Write FAfterArchiveProc;
  600. Property BeforeManifest : TNotifyEvent Read FBeforeManifest Write FBeforeManifest;
  601. Property BeforeManifestProc : TNotifyProcEvent Read FBeforeManifestProc Write FBeforeManifestProc;
  602. Property AfterManifest : TNotifyEvent Read FAfterManifest Write FAfterManifest;
  603. Property AfterManifestProc : TNotifyProcEvent Read FAfterManifestProc Write FAfterManifestProc;
  604. end;
  605. { TPackages }
  606. TPackages = Class(TNamedCollection)
  607. private
  608. function GetPackage(const AName : String): TPackage;
  609. function GetPackageItem(AIndex : Integer): TPackage;
  610. procedure SetPackageItem(AIndex : Integer; const AValue: TPackage);
  611. Public
  612. Function AddPackage(Const AName : String) : TPackage;
  613. Property Packages[AName : String] : TPackage Read GetPackage ; Default;
  614. Property PackageItems[AIndex : Integer] : TPackage Read GetPackageItem Write SetPackageItem;
  615. end;
  616. { TCustomDefaults }
  617. TCustomDefaults = Class(TPersistent)
  618. Private
  619. FArchive: String;
  620. FBuildMode: TBuildMode;
  621. FCompiler: String;
  622. FCopy: String;
  623. FFPDocOutputDir: String;
  624. FIgnoreInvalidOptions: Boolean;
  625. FInstallExamples: Boolean;
  626. FMkDir: String;
  627. FMove: String;
  628. FOptions: TStrings;
  629. FCPU: TCPU;
  630. FOS: TOS;
  631. FMode : TCompilerMode;
  632. FCompilerVersion : String;
  633. FPrefix: String;
  634. FLocalUnitDir,
  635. FGlobalUnitDir,
  636. FBaseInstallDir,
  637. FUnitInstallDir,
  638. FBinInstallDir,
  639. FDocInstallDir,
  640. FExamplesInstallDir : String;
  641. FRemoveTree: String;
  642. FRemoveDir: String;
  643. FRemove: String;
  644. FTarget: String;
  645. FUnixPaths: Boolean;
  646. FNoFPCCfg: Boolean;
  647. FUseEnvironment: Boolean;
  648. function GetFPDocOutputDir: String;
  649. function GetLocalUnitDir: String;
  650. function GetGlobalUnitDir: String;
  651. function GetBaseInstallDir: String;
  652. function GetBinInstallDir: String;
  653. function GetCompiler: String;
  654. function GetDocInstallDir: String;
  655. function GetExamplesInstallDir: String;
  656. function GetOptions: TStrings;
  657. function GetUnitInstallDir: String;
  658. procedure SetLocalUnitDir(const AValue: String);
  659. procedure SetGlobalUnitDir(const AValue: String);
  660. procedure SetBaseInstallDir(const AValue: String);
  661. procedure SetCPU(const AValue: TCPU);
  662. procedure SetOptions(const AValue: TStrings);
  663. procedure SetOS(const AValue: TOS);
  664. procedure SetPrefix(const AValue: String);
  665. procedure SetTarget(const AValue: String);
  666. procedure SetUnitInstallDir(const AValue: String);
  667. Protected
  668. procedure RecalcTarget;
  669. Function CmdLineOptions : String;
  670. Public
  671. Constructor Create;
  672. Procedure InitDefaults;
  673. Function HaveOptions: Boolean;
  674. procedure CompilerDefaults; virtual;
  675. Procedure LocalInit(Const AFileName : String);
  676. Procedure LoadFromFile(Const AFileName : String);
  677. Procedure SaveToFile(Const AFileName : String);
  678. procedure SaveToStream(S : TStream);virtual;
  679. procedure LoadFromStream(S : TStream);virtual;
  680. // Compile Information
  681. Property Target : String Read FTarget Write SetTarget;
  682. Property OS : TOS Read FOS Write SetOS;
  683. Property CPU : TCPU Read FCPU Write SetCPU;
  684. Property Mode : TCompilerMode Read FMode Write FMode;
  685. Property UnixPaths : Boolean Read FUnixPaths Write FUnixPaths;
  686. Property Options : TStrings Read GetOptions Write SetOptions; // Default compiler options.
  687. Property NoFPCCfg : Boolean Read FNoFPCCfg Write FNoFPCCfg;
  688. // paths etc.
  689. Property LocalUnitDir : String Read GetLocalUnitDir Write SetLocalUnitDir;
  690. Property GlobalUnitDir : String Read GetGlobalUnitDir Write SetGlobalUnitDir;
  691. Property Prefix : String Read FPrefix Write SetPrefix;
  692. Property BaseInstallDir : String Read GetBaseInstallDir Write SetBaseInstallDir;
  693. Property UnitInstallDir : String Read GetUnitInstallDir Write SetUnitInstallDir;
  694. Property BinInstallDir : String Read GetBinInstallDir Write FBinInstallDir;
  695. Property DocInstallDir : String Read GetDocInstallDir Write FDocInstallDir;
  696. Property ExamplesInstallDir : String Read GetExamplesInstallDir Write FExamplesInstallDir;
  697. Property FPDocOutputDir : String Read GetFPDocOutputDir Write FFPDocOutputDir;
  698. // Command tools. If not set, internal commands will be used.
  699. Property Compiler : String Read GetCompiler Write FCompiler; // Compiler. Defaults to fpc
  700. Property Copy : String Read FCopy Write FCopy; // copy $(FILES) to $(DEST)
  701. Property Move : String Read FMove Write FMove; // Move $(FILES) to $(DEST)
  702. Property Remove : String Read FRemove Write FRemove; // Delete $(FILES)
  703. Property RemoveDir : String Read FRemoveDir Write FRemoveDir; // Delete $(FILES)
  704. Property RemoveTree : String Read FRemoveTree Write FRemoveTree; // removes $(DIRECTORY)
  705. Property MkDir : String Read FMkDir write FMkDir; // Make $(DIRECTORY)
  706. Property Archive : String Read FArchive Write FArchive; // zip $(ARCHIVE) $(FILESORDIRS)
  707. // Misc
  708. Property UseEnvironment : Boolean read FUseEnvironment write FUseEnvironment;
  709. Property IgnoreInvalidOptions: Boolean read FIgnoreInvalidOptions write FIgnoreInvalidOptions;
  710. Property BuildMode: TBuildMode read FBuildMode write FBuildMode;
  711. // Installation optioms
  712. Property InstallExamples: Boolean read FInstallExamples write FInstallExamples;
  713. end;
  714. { TBasicDefaults }
  715. TBasicDefaults = Class(TCustomDefaults)
  716. end;
  717. { TFPCDefaults }
  718. TFPCDefaults = Class(TCustomDefaults)
  719. public
  720. procedure CompilerDefaults; override;
  721. end;
  722. { TBuildEngine }
  723. TBuildEngine = Class(TComponent)
  724. private
  725. // general variables
  726. FCompiler : String;
  727. FStartDir : String;
  728. FForceCompile : Boolean;
  729. FListMode : Boolean;
  730. FVerbose : boolean;
  731. {$ifdef HAS_UNIT_ZIPPER}
  732. FZipFile: TZipper;
  733. {$endif HAS_UNIT_ZIPPER}
  734. FExternalPackages : TPackages;
  735. // Logging
  736. FLogPrefix : String;
  737. // Events
  738. FOnLog: TLogEvent;
  739. FAfterArchive: TNotifyEvent;
  740. FAfterClean: TNotifyEvent;
  741. FAfterCompile: TNotifyEvent;
  742. FAfterInstall: TNotifyEvent;
  743. FAfterManifest: TNotifyEvent;
  744. FBeforeArchive: TNotifyEvent;
  745. FBeforeClean: TNotifyEvent;
  746. FBeforeCompile: TNotifyEvent;
  747. FBeforeInstall: TNotifyEvent;
  748. FBeforeManifest: TNotifyEvent;
  749. Protected
  750. Procedure Error(const Msg : String);
  751. Procedure Error(const Fmt : String; const Args : Array of const);
  752. // Internal copy/delete/move/archive/mkdir files
  753. Function SysDirectoryExists(const ADir:string):Boolean;
  754. Function SysFileExists(const AFileName:string):Boolean;
  755. Procedure SysCopyFile(Const Src,Dest : String); virtual;
  756. Procedure SysMoveFile(Const Src,Dest : String); virtual;
  757. Procedure SysDeleteFile(Const AFileName : String); virtual;
  758. Procedure SysDeleteDirectory(Const ADirectoryName : String); virtual;
  759. Procedure SysDeleteTree(Const ADirectoryName : String); virtual;
  760. Procedure SysArchiveFiles(List : TStrings; Const AFileName : String); virtual;
  761. procedure LogIndent;
  762. procedure LogUnIndent;
  763. Procedure EnterDir(ADir : String);
  764. Function GetCompiler : String;
  765. Function InstallPackageFiles(APAckage : TPackage; tt : TTargetType; Const Dest : String):Boolean;
  766. Procedure InstallUnitConfigFile(APAckage : TPackage; Const Dest : String);
  767. Function InstallPackageSourceFiles(APAckage : TPackage; stt : TSourceTypes; ttt : TTargetTypes; Const Dest : String):Boolean;
  768. Function FileNewer(const Src,Dest : String) : Boolean;
  769. Procedure LogSearchPath(const ASearchPathName:string;Path:TConditionalStrings; ACPU:TCPU;AOS:TOS);
  770. Function FindFileInPath(Path:TConditionalStrings; AFileName:String; var FoundPath:String;ACPU:TCPU;AOS:TOS):Boolean;
  771. procedure GetDirectoriesFromFilelist(const AFileList, ADirectoryList: TStringList);
  772. //package commands
  773. function GetUnitDir(APackage:TPackage):String;
  774. procedure AddDependencyPaths(L: TStrings; DependencyType: TDependencyType; ATarget: TTarget);
  775. procedure AddDependencyUnitPaths(L:TStrings;APackage: TPackage);
  776. Public
  777. Constructor Create(AOwner : TComponent); override;
  778. destructor Destroy;override;
  779. property Verbose : boolean read FVerbose write FVerbose;
  780. Procedure ResolveFileNames(APackage : TPackage; ACPU:TCPU;AOS:TOS;DoChangeDir:boolean=true);
  781. // Public Copy/delete/Move/Archive/Mkdir Commands.
  782. Procedure ExecuteCommand(const Cmd,Args : String; const Env: TStrings = nil; IgnoreError : Boolean = False); virtual;
  783. Procedure CmdCopyFiles(List : TStrings; Const DestDir : String);
  784. Procedure CmdCreateDir(const DestDir : String);
  785. Procedure CmdMoveFiles(List : TStrings; Const DestDir : String);
  786. Procedure CmdDeleteFiles(List : TStrings);
  787. Procedure CmdArchiveFiles(List : TStrings; Const ArchiveFile : String);
  788. Procedure CmdRenameFile(SourceName, DestName : String);
  789. Procedure CmdRemoveDirs(List: TStrings);
  790. Procedure CmdRemoveTrees(List: TStrings);
  791. Procedure ExecuteCommands(Commands : TCommands; At : TCommandAt);
  792. // Dependency commands
  793. Function DependencyOK(ADependency : TDependency) : Boolean;
  794. // Target commands
  795. Function GetCompilerCommand(APackage : TPackage; ATarget : TTarget; Env: TStrings) : String;
  796. Function TargetOK(ATarget : TTarget) : Boolean;
  797. Function NeedsCompile(APackage:TPackage; ATarget : TTarget) : Boolean;
  798. Procedure Compile(APackage:TPackage; ATarget : TTarget); virtual;
  799. Procedure MaybeCompile(APackage:TPackage; ATarget: TTarget);
  800. Procedure CompileDependencies(APackage:TPackage; ATarget: TTarget);
  801. // Package commands
  802. { Function GetPackageDir(APackage : TPackage; AbsolutePath : Boolean = False) : String;
  803. Function GetUnitsOutputDir(APackage : TPackage; AbsolutePath : Boolean = False) : String;
  804. Function GetBinOutputDir(APackage : TPackage; AbsolutePath : Boolean = False) : String; }
  805. Function PackageOK(APackage : TPackage) : Boolean; virtual;
  806. Procedure DoBeforeCompile(APackage : TPackage);virtual;
  807. Procedure DoAfterCompile(APackage : TPackage);virtual;
  808. Procedure DoBeforeInstall(APackage : TPackage);virtual;
  809. Procedure DoAfterInstall(APackage : TPackage);virtual;
  810. Procedure DoBeforeArchive(APackage : TPackage);virtual;
  811. Procedure DoAfterArchive(APackage : TPackage);virtual;
  812. Procedure DoBeforeClean(APackage : TPackage);virtual;
  813. Procedure DoAfterClean(APackage : TPackage);virtual;
  814. Function NeedsCompile(APackage : TPackage) : Boolean; virtual;
  815. Procedure Compile(APackage : TPackage);
  816. Procedure MaybeCompile(APackage:TPackage);
  817. Procedure Install(APackage : TPackage);
  818. Procedure Archive(APackage : TPackage);
  819. Procedure Manifest(APackage : TPackage);
  820. Procedure Clean(APackage : TPackage; AllTargets: boolean);
  821. Procedure Clean(APackage : TPackage; ACPU:TCPU; AOS : TOS);
  822. Procedure CompileDependencies(APackage : TPackage);
  823. Function CheckExternalPackage(Const APackageName : String):TPackage;
  824. procedure CreateOutputDir(APackage: TPackage);
  825. // Packages commands
  826. Procedure Compile(Packages : TPackages);
  827. Procedure Install(Packages : TPackages);
  828. Procedure Archive(Packages : TPackages);
  829. procedure Manifest(Packages: TPackages);
  830. Procedure Clean(Packages : TPackages; AllTargets: boolean);
  831. Procedure Log(Level : TVerboseLevel; Const Msg : String);
  832. Procedure Log(Level : TVerboseLevel; Const Fmt : String; const Args : Array Of Const);
  833. Property ListMode : Boolean Read FListMode Write FListMode;
  834. Property ForceCompile : Boolean Read FForceCompile Write FForceCompile;
  835. Property ExternalPackages: TPackages Read FExternalPackages;
  836. Property StartDir: String Read FStartDir;
  837. // Events
  838. Property BeforeCompile : TNotifyEvent Read FBeforeCompile Write FBeforeCompile;
  839. Property AfterCompile : TNotifyEvent Read FAfterCompile Write FAfterCompile;
  840. Property BeforeInstall : TNotifyEvent Read FBeforeInstall Write FBeforeInstall;
  841. Property AfterInstall : TNotifyEvent Read FAfterInstall Write FAfterInstall;
  842. Property BeforeClean : TNotifyEvent Read FBeforeClean Write FBeforeClean;
  843. Property AfterClean : TNotifyEvent Read FAfterClean Write FAfterClean;
  844. Property BeforeArchive : TNotifyEvent Read FBeforeArchive Write FBeforeArchive;
  845. Property AfterArchive : TNotifyEvent Read FAfterArchive Write FAfterArchive;
  846. Property BeforeManifest : TNotifyEvent Read FBeforeManifest Write FBeforeManifest;
  847. Property AfterManifest : TNotifyEvent Read FAfterManifest Write FAfterManifest;
  848. Property OnLog : TLogEvent Read FOnLog Write FOnlog;
  849. end;
  850. { TCustomInstaller }
  851. TCustomInstaller = Class(TComponent)
  852. private
  853. FBuildEngine: TBuildEngine;
  854. FPackages: TPackages;
  855. FRunMode: TRunMode;
  856. FListMode : Boolean;
  857. FLogLevels : TVerboseLevels;
  858. FFPMakeOptionsString: string;
  859. Protected
  860. Procedure Log(Level : TVerboseLevel; Const Msg : String);
  861. Procedure CreatePackages; virtual;
  862. Procedure FreePackages; virtual;
  863. function GetPackages: TPackages; virtual;
  864. Procedure CheckPackages; virtual;
  865. Procedure CreateBuildEngine; virtual;
  866. Procedure Error(const Msg : String);
  867. Procedure Error(const Fmt : String; Args : Array of const);
  868. Procedure AnalyzeOptions;
  869. Procedure Usage(const FMT : String; Args : Array of const);
  870. Procedure Compile(Force : Boolean); virtual;
  871. Procedure Clean(AllTargets: boolean); virtual;
  872. Procedure Install; virtual;
  873. Procedure Archive; virtual;
  874. Procedure Manifest; virtual;
  875. Public
  876. Constructor Create(AOwner : TComponent); virtual;
  877. Destructor destroy; override;
  878. Function AddPackage(Const AName : String) : TPackage;
  879. Function Run : Boolean;
  880. Property FPMakeOptionsString: string read FFPMakeOptionsString;
  881. Property BuildEngine : TBuildEngine Read FBuildEngine;
  882. //files in package
  883. Property Packages : TPackages Read GetPackages;
  884. Property RunMode : TRunMode Read FRunMode;
  885. Property ListMode : Boolean Read FListMode;
  886. end;
  887. { TFPCInstaller }
  888. TFPCInstaller = class(TCustomInstaller)
  889. public
  890. Constructor Create(AOwner : TComponent); override;
  891. end;
  892. { TBasicInstaller }
  893. TBasicInstaller = class(TCustomInstaller)
  894. Constructor Create(AOwner : TComponent); override;
  895. end;
  896. TReplaceFunction = Function (Const AName,Args : String) : String of Object;
  897. { TValueItem }
  898. TValueItem = Class(TObject)
  899. FValue : String;
  900. Constructor Create(AValue : String);
  901. end;
  902. { TFunctionItem }
  903. TFunctionItem = Class(TObject)
  904. FFunc : TReplaceFunction;
  905. Constructor Create(AFunc : TReplaceFunction);
  906. end;
  907. { TDictionary }
  908. TDictionary = Class(TComponent)
  909. FList : TStringList;
  910. Public
  911. Constructor Create(AOwner : TComponent); override;
  912. Destructor Destroy;override;
  913. Procedure AddVariable(Const AName,Value : String);
  914. Procedure AddFunction(Const AName : String; FReplacement : TReplaceFunction);
  915. Procedure RemoveItem(Const AName : String);
  916. Function GetValue(Const AName : String) : String;
  917. Function GetValue(Const AName,Args : String) : String; virtual;
  918. Function ReplaceStrings(Const ASource : String) : String; virtual;
  919. end;
  920. ECollectionError = Class(Exception);
  921. EDictionaryError = Class(Exception);
  922. EInstallerError = Class(Exception);
  923. TInstallerClass = Class of TCustomInstaller;
  924. TDictionaryClass = Class of TDictionary;
  925. Type
  926. TArchiveEvent = Procedure (Const AFileName : String; List : TStrings) of Object;
  927. TArchiveProc = Procedure (Const AFileName : String; List : TStrings);
  928. Var
  929. DictionaryClass : TDictionaryClass = TDictionary;
  930. OnArchiveFiles : TArchiveEvent = Nil;
  931. ArchiveFilesProc : TArchiveProc = Nil;
  932. Defaults : TCustomDefaults; // Set by installer.
  933. Dictionary : TDictionary;
  934. Function CurrentOS : String;
  935. Function CurrentCPU : String;
  936. Function Installer(InstallerClass: TInstallerClass) : TCustomInstaller; overload;
  937. Function Installer : TCustomInstaller; overload;
  938. Function OSToString(OS: TOS) : String;
  939. Function OSesToString(OSes: TOSes) : String;
  940. Function CPUToString(CPU: TCPU) : String;
  941. Function CPUSToString(CPUS: TCPUS) : String;
  942. Function StringToOS(const S : String) : TOS;
  943. Function OSesToString(const S : String) : TOSes;
  944. Function StringToCPU(const S : String) : TCPU;
  945. Function StringToCPUS(const S : String) : TCPUS;
  946. Function ModeToString(Mode: TCompilerMode) : String;
  947. Function StringToMode(const S : String) : TCompilerMode;
  948. Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
  949. Procedure StringToCPUOS(const S : String; Var CPU : TCPU; Var OS: TOS);
  950. Function FixPath (const APath : String) : String;
  951. Function IsRelativePath(const APath : String) : boolean;
  952. Procedure ChangeDir(const APath : String);
  953. Function Substitute(Const Source : String; Macros : Array of string) : String;
  954. Procedure SplitCommand(Const Cmd : String; Var Exe,Options : String);
  955. Procedure AddCustomFpmakeCommandlineOption(const ACommandLineOption, HelpMessage : string);
  956. Function GetCustomFpmakeCommandlineOptionValue(const ACommandLineOption : string) : string;
  957. procedure SearchFiles(const AFileName: string; Recursive: boolean; var List: TStrings);
  958. Implementation
  959. uses typinfo, rtlconsts;
  960. type
  961. TUnsortedDuplicatesStringList = class(TStringList)
  962. public
  963. function Add(const S: string): Integer; override;
  964. end;
  965. var
  966. CustomFpmakeCommandlineOptions: TStrings;
  967. CustomFpMakeCommandlineValues: TStrings;
  968. ResourceString
  969. SErrInvalidCPU = 'Invalid CPU name "%s"';
  970. SErrInvalidOS = 'Invalid OS name "%s"';
  971. SErrInvalidMode = 'Invalid compiler mode "%s"';
  972. SErrInvalidTarget = 'Invalid compiler target "%s"';
  973. SErrNameExists = 'Name "%s" already exists in the collection.';
  974. SErrNoSuchName = 'Could not find item with name "%s" in the collection.';
  975. SErrInValidArgument = 'Invalid command-line argument at position %d: %s';
  976. SErrNeedArgument = 'Option at position %d (%s) needs an argument';
  977. SErrNoPackagesDefined = 'No action possible: No packages were defined.';
  978. SErrInstaller = 'The installer encountered the following error:';
  979. SErrDepUnknownTarget = 'Unknown target for unit "%s" in dependencies for %s in package %s';
  980. SErrExternalCommandFailed = 'External command "%s" failed with exit code %d. Console output:'+LineEnding+'%s';
  981. SErrCreatingDirectory = 'Failed to create directory "%s"';
  982. SErrDeletingFile = 'Failed to delete file "%s"';
  983. SErrRemovingDirectory = 'Failed to remove directory "%s"';
  984. SErrMovingFile = 'Failed to move file "%s" to "%s"';
  985. SErrCopyingFile = 'Failed to copy file "%s" to "%s"';
  986. SErrChangeDirFailed = 'Failed to enter directory "%s"';
  987. SErrInvalidArgumentToSubstitute = 'Invalid number of arguments to Substitute';
  988. SErrNoArchiveSupport = 'This binary contains no archive support. Please recompile with archive support';
  989. SErrNoDictionaryItem = 'No item called "%s" in the dictionary';
  990. SErrNoDictionaryValue = 'The item "%s" in the dictionary is not a value';
  991. SErrNoDictionaryFunc = 'The item "%s" in the dictionary is not a function';
  992. SErrInvalidFPCInfo = 'Compiler returns invalid information, check if fpc -iV works';
  993. SErrDependencyNotFound = 'Could not find unit directory for dependency package "%s"';
  994. SErrAlreadyInitialized = 'Installer can only be initialized once';
  995. SErrInvalidState = 'Invalid state for target %s';
  996. SErrCouldNotCompile = 'Could not compile target %s from package %s';
  997. SErrUnsupportedBuildmode = 'Package does not support this buildmode';
  998. SWarnCircularTargetDependency = 'Warning: Circular dependency detected when compiling target %s with target %s';
  999. SWarnCircularPackageDependency = 'Warning: Circular dependency detected when compiling package %s with package %s';
  1000. SWarnFailedToSetTime = 'Warning: Failed to set timestamp on file "%s"';
  1001. SWarnFailedToGetTime = 'Warning: Failed to get timestamp from file "%s"';
  1002. SWarnAttemptingToCompileNonNeutralTarget = 'Warning: Attempting to compile non-neutral target %s';
  1003. SWarnSourceFileNotFound = 'Warning: Source file "%s" from package %s not found for %s';
  1004. SWarnIncludeFileNotFound = 'Warning: Include file "%s" from package %s not found for %s';
  1005. SWarnDepUnitNotFound = 'Warning: Dependency on unit %s is not supported for %s';
  1006. SWarnTargetDependsOnPackage = 'Warning: Target %s of package %s depends on another package (%s). These kind of dependencies are not processed';
  1007. SWarnDependOnOtherPlatformPackage = 'Warning: Package %s depends on package %s which is not available for the %s platform';
  1008. SWarnStartBuildingPackage = 'Start building package %s for target %s.';
  1009. SWarnBuildingPackagecomplete = '[%3.0f%%] Built target %s';
  1010. SWarnInstallationPackagecomplete = 'Installation package %s for target %s succeeded';
  1011. SWarnCleanPackagecomplete = 'Clean of package %s completed';
  1012. SInfoCompilingPackage = 'Compiling package %s';
  1013. SInfoPackageAlreadyProcessed = 'Package %s is already processed';
  1014. SInfoCompilingTarget = 'Compiling target %s';
  1015. SInfoExecutingCommand = 'Executing command "%s %s"';
  1016. SInfoCreatingOutputDir = 'Creating output dir "%s"';
  1017. SInfoInstallingPackage = 'Installing package %s';
  1018. SInfoArchivingPackage = 'Archiving package %s in "%s"';
  1019. SInfoCleaningPackage = 'Cleaning package %s';
  1020. SInfoManifestPackage = 'Creating manifest for package %s';
  1021. SInfoCopyingFile = 'Copying file "%s" to "%s"';
  1022. SInfoSourceNewerDest = 'Source file "%s" (%s) is newer than destination "%s" (%s).';
  1023. SInfoFallbackBuildmode = 'Buildmode not spported by package, falling back to one by one unit compilation';
  1024. SDbgComparingFileTimes = 'Comparing file "%s" time "%s" to "%s" time "%s".';
  1025. SDbgCompilingDependenciesOfTarget = 'Compiling dependencies of target %s';
  1026. SDbgResolvingSourcesOfTarget = 'Resolving filenames of target %s for %s';
  1027. SDbgResolvedSourceFile = 'Resolved source file %s to "%s"';
  1028. SDbgResolvedIncludeFile = 'Resolved include file %s to "%s"';
  1029. SDbgOutputNotYetAvailable = 'Output file %s not available';
  1030. SDbgDependencyOnUnit = 'Dependency of %s on unit %s';
  1031. SDbgDependencyUnitRecompiled = 'Dependent unit %s is being recompiled';
  1032. SDbgMustCompile = 'Must compile %s';
  1033. SDbgSkippingTargetWrongCPU = 'Skipping target %s, different CPU (%s)';
  1034. SDbgSkippingTargetWrongOS = 'Skipping target %s, different OS (%s)';
  1035. SDbgTargetIsNotAUnitOrProgram = 'Skipping Target %s, not an unit or program';
  1036. SDbgConsideringTarget = 'Considering target %s';
  1037. SDbgConsideringPackage = 'Considering package %s';
  1038. SDbgExternalDependency = 'External dependency %s found in "%s"';
  1039. SDbgBuildEngineArchiving = 'Build engine archiving';
  1040. SDbgBuildEngineGenerateManifests = 'Build engine generating manifests';
  1041. SDbgBuildEngineCleaning = 'Build engine cleaning';
  1042. SDbgGenerating = 'Generating "%s"';
  1043. SDbgLoading = 'Loading "%s"';
  1044. SDbgFound = 'Found';
  1045. SDbgNotFound = 'Not Found';
  1046. SDbgDirectoryExists = 'Directory "%s" %s';
  1047. SDbgFileExists = 'File "%s" %s';
  1048. SDbgArchivingFile = 'Archiving "%s"';
  1049. SDbgSearchPath = 'Using %s path "%s"';
  1050. SDbgEnterDir = 'Entering directory "%s"';
  1051. SDbgPackageChecksumChanged = 'Dependent package %s is modified';
  1052. SDbgFileDoesNotExist = 'File "%s" does not exist';
  1053. SDbgDirectoryDoesNotExist = 'Directory "%s" does not exist';
  1054. SDbgDirectoryNotEmpty = 'Directory "%s" is not empty. Will not remove';
  1055. SDbgGenerateBuildUnit = 'Generate build-unit %s';
  1056. // Help messages for usage
  1057. SValue = 'Value';
  1058. SHelpUsage = 'Usage: %s command [options]';
  1059. SHelpCommand = 'Where command is one of the following:';
  1060. SHelpCompile = 'Compile all units in the package(s).';
  1061. SHelpBuild = 'Build all units in the package(s).';
  1062. SHelpInstall = 'Install all units in the package(s).';
  1063. SHelpClean = 'Clean (remove) all units in the package(s).';
  1064. SHelpArchive = 'Create archive (zip) with all units in the package(s).';
  1065. SHelpHelp = 'This message.';
  1066. SHelpManifest = 'Create a manifest suitable for import in repository.';
  1067. SHelpCmdOptions = 'Where options is one or more of the following:';
  1068. SHelpCPU = 'Compile for indicated CPU.';
  1069. SHelpOS = 'Compile for indicated OS';
  1070. SHelpTarget = 'Compile for indicated target';
  1071. SHelpList = 'list commands instead of actually executing them.';
  1072. SHelpPrefix = 'Use indicated prefix directory for all commands.';
  1073. SHelpNoFPCCfg = 'Compiler will not use fpc.cfg';
  1074. SHelpBaseInstallDir = 'Use indicated directory as base install dir.';
  1075. SHelpLocalUnitDir = 'Use indicated directory as local (user) unit dir.';
  1076. SHelpGlobalUnitDir = 'Use indicated directory as global unit dir.';
  1077. SHelpUnitInstallDir = 'Use indicated directory to install units into.';
  1078. SHelpCompiler = 'Use indicated binary as compiler';
  1079. SHelpConfig = 'Use indicated config file when compiling.';
  1080. SHelpOptions = 'Pass extra options to the compiler.';
  1081. SHelpVerbose = 'Be verbose when working.';
  1082. SHelpInstExamples = 'Install the example-sources.';
  1083. SHelpIgnoreInvOpt = 'Ignore further invalid options.';
  1084. sHelpFpdocOutputDir = 'Use indicated directory as fpdoc output folder.';
  1085. sHelpUseEnvironment = 'Use environment to pass options to compiler.';
  1086. SHelpUseBuildUnit = 'Compile package in Build-unit mode.';
  1087. Const
  1088. // Keys for Defaults file. Do not localize.
  1089. KeyCompiler = 'Compiler';
  1090. KeyArchive = 'Archive';
  1091. KeyCopy = 'Copy';
  1092. KeyMkDir = 'MkDir';
  1093. KeyMove = 'Move';
  1094. KeyRemove = 'Remove';
  1095. KeyRemoveDir= 'RemoveDir';
  1096. KeyRemoveTree= 'RemoveTree';
  1097. KeyOptions = 'Options';
  1098. KeyCPU = 'CPU';
  1099. KeyOS = 'OS';
  1100. KeyMode = 'Mode';
  1101. KeyPrefix = 'Prefix';
  1102. KeyTarget = 'Target';
  1103. KeyNoFPCCfg = 'NoFPCCfg';
  1104. KeyUseEnv = 'UseEnv';
  1105. KeyLocalUnitDir = 'LocalUnitDir';
  1106. KeyGlobalUnitDir = 'GlobalUnitDir';
  1107. KeyBaseInstallDir = 'BaseInstallDir';
  1108. KeyUnitInstallDir = 'UnitInstallDir';
  1109. KeyBinInstallDir = 'BinInstallDir';
  1110. KeyDocInstallDir = 'DocInstallDir';
  1111. KeyExamplesInstallDir = 'ExamplesInstallDir';
  1112. KeyInstallExamples = 'InstallExamples';
  1113. // Keys for unit config
  1114. KeyName = 'Name';
  1115. KeyVersion = 'Version';
  1116. KeyChecksum = 'Checksum';
  1117. KeyNeedLibC = 'NeedLibC';
  1118. KeyDepends = 'Depends';
  1119. KeyAddIn = 'FPMakeAddIn';
  1120. KeySourcePath = 'SourcePath';
  1121. KeyFPMakeOptions = 'FPMakeOptions';
  1122. {****************************************************************************
  1123. Helpers
  1124. ****************************************************************************}
  1125. {$ifdef HAS_UNIT_PROCESS}
  1126. function ExecuteFPC(Verbose: boolean; const Path: string; const ComLine: string; const Env: TStrings; ConsoleOutput: TMemoryStream): integer;
  1127. var
  1128. P: TProcess;
  1129. BytesRead: longint;
  1130. function ReadFromStream: longint;
  1131. const
  1132. READ_BYTES = 2048;
  1133. type
  1134. TMessages = (mCompiling, mLinking);
  1135. var
  1136. //ifdef the MsgNum so it contains the correct message numbers for each compiler version.
  1137. MsgNum : array [TMessages] of integer = (3104, 9015);
  1138. n: longint;
  1139. BuffPos: longint;
  1140. sLine: string;
  1141. ch: char;
  1142. msg: TMessages;
  1143. ipos: integer;
  1144. snum: string;
  1145. begin
  1146. // make sure we have room
  1147. ConsoleOutput.SetSize(BytesRead + READ_BYTES);
  1148. // try reading it
  1149. n := P.Output.Read((ConsoleOutput.Memory + BytesRead)^, READ_BYTES);
  1150. if n > 0 then
  1151. begin
  1152. Inc(BytesRead, n);
  1153. sLine := '';
  1154. BuffPos := ConsoleOutput.Position;
  1155. //read lines from the stream
  1156. repeat
  1157. ConsoleOutput.Read(ch,1);
  1158. if ch in [#10, #13] then
  1159. begin
  1160. if Verbose then
  1161. writeln(sLine)
  1162. else
  1163. begin
  1164. for msg := Low(TMessages) to High(TMessages) do
  1165. begin
  1166. snum := Format('(%d)', [MsgNum[msg]]);
  1167. ipos := Pos(snum, sLine);
  1168. if ipos = 1 then
  1169. writeln(' ', Copy(sLine, ipos + Length(snum), Length(sLine) - ipos - Length(snum) + 1));
  1170. end;
  1171. end;
  1172. sLine := '';
  1173. BuffPos := ConsoleOutput.Position;
  1174. end
  1175. else
  1176. sLine := sLine + ch;
  1177. until ConsoleOutput.Position >= BytesRead;
  1178. ConsoleOutput.Position := BuffPos;
  1179. end
  1180. else
  1181. begin
  1182. // no data, wait 100 ms
  1183. Sleep(100);
  1184. end;
  1185. Result := n;
  1186. end;
  1187. begin
  1188. result := -1;
  1189. BytesRead := 0;
  1190. P := TProcess.Create(nil);
  1191. try
  1192. P.CommandLine := Path + ' ' + ComLine;
  1193. if assigned(Env) then
  1194. P.Environment.Assign(Env);
  1195. P.Options := [poUsePipes];
  1196. P.Execute;
  1197. while P.Running do
  1198. ReadFromStream;
  1199. // read last part
  1200. repeat
  1201. until ReadFromStream = 0;
  1202. ConsoleOutput.SetSize(BytesRead);
  1203. result := P.ExitStatus;
  1204. finally
  1205. P.Free;
  1206. end;
  1207. end;
  1208. {$endif HAS_UNIT_PROCESS}
  1209. function IsDirectoryEmpty(const directory : string) : boolean;
  1210. var
  1211. searchRec: TSearchRec;
  1212. SearchResult: longint;
  1213. begin
  1214. result := true;
  1215. SearchResult := FindFirst(IncludeTrailingPathDelimiter(directory)+AllFilesMask, faAnyFile+faSymLink, searchRec);
  1216. try
  1217. while SearchResult=0 do
  1218. begin
  1219. if (searchRec.Name<>'.') and (searchRec.Name<>'..') then
  1220. begin
  1221. result := false;
  1222. break;
  1223. end;
  1224. SearchResult := FindNext(searchRec);
  1225. end;
  1226. finally
  1227. FindClose(searchRec);
  1228. end;
  1229. end;
  1230. function ParsecompilerOutput(M: TMemoryStream; Verbose: boolean): string;
  1231. type
  1232. TParseCompilerOutputState = (cosBeginOfLine, cosSearchColon, cosParseNumber, cosOther);
  1233. var
  1234. presult: pchar;
  1235. state: TParseCompilerOutputState;
  1236. ch: char;
  1237. eolchar: char;
  1238. begin
  1239. m.Seek(0, soBeginning);
  1240. setlength(Result,M.Size);
  1241. if verbose then
  1242. begin
  1243. m.Read(Result[1],M.Size);
  1244. Exit;
  1245. end;
  1246. presult := @Result[1];
  1247. eolchar := RightStr(LineEnding,1)[1];
  1248. m.Seek(0,soBeginning);
  1249. state := cosBeginOfLine;
  1250. while m.Position<m.Size do
  1251. begin
  1252. ch := char(m.ReadByte);
  1253. case state of
  1254. cosBeginOfLine:
  1255. begin
  1256. if ch='(' then
  1257. state := cosParseNumber
  1258. else if ch=' ' then
  1259. begin
  1260. presult^ := ch;
  1261. inc(presult);
  1262. end
  1263. else
  1264. begin
  1265. presult^ := ch;
  1266. inc(presult);
  1267. state := cosSearchColon;
  1268. end;
  1269. end;
  1270. cosParseNumber:
  1271. begin
  1272. if ch=')' then
  1273. begin
  1274. state := cosOther;
  1275. // Omit the space behind the number
  1276. ch := char(m.ReadByte);
  1277. assert(ch=' ');
  1278. end;
  1279. end;
  1280. cosOther:
  1281. begin
  1282. presult^ := ch;
  1283. inc(presult);
  1284. if ch=eolchar then
  1285. state := cosBeginOfLine;
  1286. end;
  1287. cosSearchColon:
  1288. begin
  1289. presult^ := ch;
  1290. inc(presult);
  1291. if (ch=':') or (ch=eolchar) then
  1292. state := cosBeginOfLine;
  1293. end;
  1294. end;
  1295. end;
  1296. setlength(Result,presult-@result[1]);
  1297. end;
  1298. Function QuoteXML(S : String) : string;
  1299. Procedure W(Var J : Integer; Var R : String; T : String);
  1300. Var
  1301. I: integer;
  1302. begin
  1303. If J+Length(T)>Length(R) then
  1304. SetLength(R,J+Length(T));
  1305. For I:=1 to Length(t) do
  1306. begin
  1307. R[J]:=T[i];
  1308. If I<Length(T) then
  1309. Inc(J);
  1310. end;
  1311. end;
  1312. const
  1313. QuotStr = '&quot;';
  1314. AmpStr = '&amp;';
  1315. ltStr = '&lt;';
  1316. gtStr = '&gt;';
  1317. Var
  1318. I,J : Integer;
  1319. begin
  1320. SetLength(Result,Length(S));
  1321. J:=0;
  1322. For I:=1 to Length(S) do
  1323. begin
  1324. Inc(J);
  1325. case S[i] of
  1326. '"': W(j,Result,QuotStr);
  1327. '&': W(J,Result,AmpStr);
  1328. '<': W(J,Result,ltStr);
  1329. '>': W(J,Result,gtStr);
  1330. // Escape whitespace using CharRefs to be consistent with W3 spec X 3.3.3
  1331. #9: w(J,Result,'&#x9;');
  1332. { #10: wrtStr('&#xA;');
  1333. #13: wrtStr('&#xD;');}
  1334. else
  1335. Result[J]:=S[i];
  1336. end;
  1337. If (J=Length(Result)) and (I<Length(S)) then
  1338. SetLength(Result,J+Length(S)-I);
  1339. end;
  1340. If J<>Length(Result) then
  1341. SetLength(Result,J);
  1342. end;
  1343. function maybequoted(const s:string):string;
  1344. const
  1345. {$IFDEF MSWINDOWS}
  1346. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  1347. '{', '}', '''', '`', '~'];
  1348. {$ELSE}
  1349. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  1350. '{', '}', '''', ':', '\', '`', '~'];
  1351. {$ENDIF}
  1352. var
  1353. s1 : string;
  1354. i : integer;
  1355. quoted : boolean;
  1356. begin
  1357. quoted:=false;
  1358. s1:='"';
  1359. for i:=1 to length(s) do
  1360. begin
  1361. case s[i] of
  1362. '"' :
  1363. begin
  1364. quoted:=true;
  1365. s1:=s1+'\"';
  1366. end;
  1367. ' ',
  1368. #128..#255 :
  1369. begin
  1370. quoted:=true;
  1371. s1:=s1+s[i];
  1372. end;
  1373. else begin
  1374. if s[i] in FORBIDDEN_CHARS then
  1375. quoted:=True;
  1376. s1:=s1+s[i];
  1377. end;
  1378. end;
  1379. end;
  1380. if quoted then
  1381. maybequoted:=s1+'"'
  1382. else
  1383. maybequoted:=s;
  1384. end;
  1385. procedure ReadIniFile(Const AFileName: String;L:TStrings);
  1386. Var
  1387. F : TFileStream;
  1388. Line : String;
  1389. I,P,PC : Integer;
  1390. begin
  1391. F:=TFileStream.Create(AFileName,fmOpenRead);
  1392. Try
  1393. L.LoadFromStream(F);
  1394. // Fix lines.
  1395. For I:=L.Count-1 downto 0 do
  1396. begin
  1397. Line:=L[I];
  1398. P:=Pos('=',Line);
  1399. PC:=Pos(';',Line); // Comment line.
  1400. If (P=0) or ((PC<>0) and (PC<P)) then
  1401. L.Delete(I)
  1402. else
  1403. L[i]:=Trim(System.Copy(Line,1,P-1)+'='+Trim(System.Copy(Line,P+1,Length(Line)-P)));
  1404. end;
  1405. Finally
  1406. F.Free;
  1407. end;
  1408. end;
  1409. // Callback for Sysutils getapplicationname.
  1410. Function GetFPMakeName : String;
  1411. begin
  1412. Result:='fpmake';
  1413. end;
  1414. Function CurrentOS : String;
  1415. begin
  1416. Result:=OSToString(Defaults.OS);
  1417. end;
  1418. Function CurrentCPU : String;
  1419. begin
  1420. Result:=CPUToString(Defaults.CPU);
  1421. end;
  1422. Function OSToString(OS: TOS) : String;
  1423. begin
  1424. Result:=LowerCase(GetenumName(TypeInfo(TOS),Ord(OS)));
  1425. end;
  1426. Function OSesToString(OSes: TOSes) : String;
  1427. begin
  1428. Result:=LowerCase(SetToString(PtypeInfo(TypeInfo(TOSes)),Integer(OSes),False));
  1429. end;
  1430. Function CPUToString(CPU: TCPU) : String;
  1431. begin
  1432. Result:=LowerCase(GetenumName(TypeInfo(TCPU),Ord(CPU)));
  1433. end;
  1434. Function CPUSToString(CPUS: TCPUS) : String;
  1435. begin
  1436. Result:=LowerCase(SetToString(PTypeInfo(TypeInfo(TCPUS)),Integer(CPUS),False));
  1437. end;
  1438. Function StringToOS(const S : String) : TOS;
  1439. Var
  1440. I : Integer;
  1441. begin
  1442. I:=GetEnumValue(TypeInfo(TOS),S);
  1443. if (I=-1) then
  1444. Raise EInstallerError.CreateFmt(SErrInvalidOS,[S]);
  1445. Result:=TOS(I);
  1446. end;
  1447. Function OSesToString(const S : String) : TOSes;
  1448. begin
  1449. Result:=TOSes(StringToSet(PTypeInfo(TypeInfo(TOSes)),S));
  1450. end;
  1451. Function StringToCPU(const S : String) : TCPU;
  1452. Var
  1453. I : Integer;
  1454. begin
  1455. I:=GetEnumValue(TypeInfo(TCPU),S);
  1456. if (I=-1) then
  1457. Raise EInstallerError.CreateFmt(SErrInvalidCPU,[S]);
  1458. Result:=TCPU(I);
  1459. end;
  1460. Function StringToCPUS(const S : String) : TCPUS;
  1461. begin
  1462. Result:=TCPUS(StringToSet(PTypeInfo(TypeInfo(TCPUS)),S));
  1463. end;
  1464. Function ModeToString(Mode: TCompilerMode) : String;
  1465. begin
  1466. Result:=LowerCase(GetenumName(TypeInfo(TCompilerMode),Ord(Mode)));
  1467. Delete(Result,1,2);
  1468. end;
  1469. Function StringToMode(const S : String) : TCompilerMode;
  1470. Var
  1471. I : Integer;
  1472. begin
  1473. I:=GetEnumValue(TypeInfo(TCompilerMode),S);
  1474. if (I=-1) then
  1475. Raise EInstallerError.CreateFmt(SErrInvalidMode,[S]);
  1476. Result:=TCompilerMode(I);
  1477. end;
  1478. Function MakeTargetString(CPU : TCPU;OS: TOS) : String;
  1479. begin
  1480. if OS in AllLimit83fsOses then
  1481. Result := OSToString(OS)
  1482. else
  1483. Result:=CPUToString(CPU)+'-'+OSToString(OS);
  1484. end;
  1485. Procedure StringToCPUOS(const S : String; Var CPU : TCPU; Var OS: TOS);
  1486. Var
  1487. P : integer;
  1488. begin
  1489. P:=Pos('-',S);
  1490. If (P=0) then
  1491. Raise EInstallerError.CreateFmt(SErrInvalidTarget,[S]);
  1492. CPU:=StringToCPU(Copy(S,1,P-1));
  1493. OS:=StringToOs(Copy(S,P+1,Length(S)-P));
  1494. end;
  1495. Procedure ResolveDependencies(L : TDependencies; P : TNamedCollection);
  1496. Var
  1497. I,J : Integer;
  1498. C : TDependency;
  1499. begin
  1500. If Assigned(L) then
  1501. For I:=0 to L.Count-1 do
  1502. begin
  1503. C:=L[i];
  1504. if C.DependencyType in [depPackage,depUnit] then
  1505. begin
  1506. J:=P.IndexOfName(C.Value);
  1507. If J<>-1 then
  1508. C.Target:=P.Items[J];
  1509. end;
  1510. end;
  1511. end;
  1512. function AddConditionalStrings(Dest : TStrings; Src : TConditionalStrings;ACPU:TCPU;AOS:TOS; Const APrefix : String='') : Integer ;
  1513. Var
  1514. I : Integer;
  1515. C : TConditionalString;
  1516. S : String;
  1517. begin
  1518. Result:=0;
  1519. Dictionary.AddVariable('CPU',CPUToString(ACPU));
  1520. Dictionary.AddVariable('OS',OSToString(AOS));
  1521. For I:=0 to Src.Count-1 do
  1522. begin
  1523. C:=Src[I];
  1524. if (ACPU in C.CPUs) and (AOS in C.OSes) then
  1525. begin
  1526. If (APrefix<>'') then
  1527. S:=APrefix+C.Value
  1528. else
  1529. S:=C.Value;
  1530. Dest.Add(Dictionary.ReplaceStrings(S));
  1531. Inc(Result);
  1532. end;
  1533. end;
  1534. end;
  1535. function FileListToString(List : TStrings; const APrefix : String) : String;
  1536. Var
  1537. I : integer;
  1538. S : String;
  1539. begin
  1540. Result:='';
  1541. For I:=0 to List.Count-1 do
  1542. begin
  1543. If (I>0) then
  1544. Result:=Result+' ';
  1545. S:=APrefix+List[i];
  1546. If (Pos(' ',S)<>0) then
  1547. S:='"'+S+'"';
  1548. Result:=Result+S;
  1549. end;
  1550. end;
  1551. function FixPath (const APath : String) : String;
  1552. Var
  1553. P : PChar;
  1554. begin
  1555. Result:=APath;
  1556. If (result<>'') then
  1557. begin
  1558. P:=PChar(Result);
  1559. While (P^<>#0) do
  1560. begin
  1561. If P^ in ['/','\'] then
  1562. P^:=PathDelim;
  1563. Inc(P);
  1564. end;
  1565. end;
  1566. end;
  1567. function IsRelativePath(const APath: String): boolean;
  1568. begin
  1569. if APath='' then
  1570. result := true
  1571. {$ifdef unix}
  1572. else if APath[1] in AllowDirectorySeparators then
  1573. result := false
  1574. {$else}
  1575. else if ExtractFileDrive(APath)<>'' then
  1576. result := false
  1577. {$endif}
  1578. else
  1579. result := true;
  1580. end;
  1581. procedure ChangeDir(const APath : String);
  1582. begin
  1583. if Not SetCurrentDir(APath) then
  1584. Raise EInstallerError.CreateFmt(SErrChangeDirFailed,[APath]);
  1585. end;
  1586. procedure SearchFiles(const AFileName: string; Recursive: boolean; var List: TStrings);
  1587. procedure AddRecursiveFiles(const SearchDir, FileMask: string; Recursive: boolean);
  1588. const
  1589. IgnoreCase = {$ifdef UNIX}False{$else}True{$endif};
  1590. var
  1591. Info : TSearchRec;
  1592. begin
  1593. if FindFirst(SearchDir+'*',faAnyFile and faDirectory,Info)=0 then
  1594. begin
  1595. repeat
  1596. if ((Info.Attr and faDirectory) = faDirectory) and (Info.Name <> '.') and (Info.Name <> '..') and (Recursive) then
  1597. AddRecursiveFiles(SearchDir + Info.Name + PathDelim, FileMask, Recursive);
  1598. if ((Info.Attr and faDirectory) <> faDirectory) and IsWild(Info.Name, FileMask, IgnoreCase) then
  1599. List.Add(SearchDir + Info.Name);
  1600. until FindNext(Info)<>0;
  1601. end;
  1602. FindClose(Info);
  1603. end;
  1604. var
  1605. CurrDir,
  1606. BasePath: string;
  1607. i: integer;
  1608. begin
  1609. BasePath := ExtractFilePath(ExpandFileName(AFileName));
  1610. AddRecursiveFiles(BasePath, ExtractFileName(AFileName), Recursive);
  1611. CurrDir:=GetCurrentDir;
  1612. for i := 0 to Pred(List.Count) do
  1613. List[i] := ExtractRelativepath(IncludeTrailingPathDelimiter(CurrDir), List[i]);
  1614. end;
  1615. Const
  1616. WhiteSpace = [#9,#10,#13,' '];
  1617. QuoteChars = ['''','"'];
  1618. procedure SplitCommand(const Cmd : String; var Exe, Options : String);
  1619. Var
  1620. I : Integer;
  1621. InQuote : Boolean;
  1622. LastQuote : Char;
  1623. S : String;
  1624. begin
  1625. S:=Trim(Cmd);
  1626. InQuote:=False;
  1627. LastQuote:=#0;
  1628. I:=1;
  1629. While (I<=Length(S)) and (Inquote or not (S[I] in whiteSpace)) do
  1630. begin
  1631. If S[i] in QuoteChars then
  1632. begin
  1633. InQuote:=Not (S[i]=LastQuote);
  1634. If InQuote then
  1635. LastQuote:=S[i]
  1636. else
  1637. LastQuote:=#0;
  1638. end;
  1639. Inc(I);
  1640. end;
  1641. Exe:=Copy(S,1,I-1);
  1642. Delete(S,1,I);
  1643. Options:=Trim(S);
  1644. end;
  1645. procedure AddCustomFpmakeCommandlineOption(const ACommandLineOption, HelpMessage : string);
  1646. begin
  1647. if not assigned(CustomFpmakeCommandlineOptions) then
  1648. CustomFpmakeCommandlineOptions := TStringList.Create;
  1649. CustomFpmakeCommandlineOptions.Values[ACommandLineOption]:=HelpMessage;
  1650. end;
  1651. function GetCustomFpmakeCommandlineOptionValue(const ACommandLineOption: string): string;
  1652. begin
  1653. if not assigned(CustomFpMakeCommandlineValues) then
  1654. result := ''
  1655. else
  1656. result := CustomFpMakeCommandlineValues.Values[ACommandLineOption];
  1657. end;
  1658. Function OptionListToString(L : TStrings) : String;
  1659. var
  1660. I : Integer;
  1661. S : String;
  1662. begin
  1663. Result:='';
  1664. For I:=0 to L.Count-1 do
  1665. begin
  1666. If (Result<>'') then
  1667. Result:=Result+' ';
  1668. S:=L[I];
  1669. If (Pos(' ',S)<>0) or (S='') then
  1670. Result:='"'+S+'"';
  1671. end;
  1672. end;
  1673. Function OptionsToStringList(S : String) : TStrings;
  1674. Var
  1675. P : Integer;
  1676. begin
  1677. Result:=Nil;
  1678. If (S='') then
  1679. Exit;
  1680. Result:=TStringList.Create;
  1681. Repeat
  1682. P:=Pos(' ',S);
  1683. If P=0 then
  1684. P:=Length(S)+1;
  1685. Result.Add(Copy(S,1,P-1));
  1686. Delete(S,1,P);
  1687. S:=Trim(S);
  1688. Until Length(S)=0;
  1689. If Result.Count=0 then
  1690. FreeAndNil(Result);
  1691. end;
  1692. {$ifdef HAS_UNIT_PROCESS}
  1693. function GetCompilerInfo(const ACompiler,AOptions:string):string;
  1694. const
  1695. BufSize = 1024;
  1696. var
  1697. S: TProcess;
  1698. Buf: array [0..BufSize - 1] of char;
  1699. Count: longint;
  1700. begin
  1701. S:=TProcess.Create(Nil);
  1702. S.Commandline:=ACompiler+' '+AOptions;
  1703. S.Options:=[poUsePipes];
  1704. S.execute;
  1705. Count:=s.output.read(buf,BufSize);
  1706. S.Free;
  1707. SetLength(Result,Count);
  1708. Move(Buf,Result[1],Count);
  1709. end;
  1710. {$endif HAS_UNIT_PROCESS}
  1711. {****************************************************************************
  1712. TUnsortedDuplicatesStringList
  1713. ****************************************************************************}
  1714. function TUnsortedDuplicatesStringList.Add(const S: string): Integer;
  1715. begin
  1716. result := IndexOf(S);
  1717. If result > -1 then
  1718. Case DUplicates of
  1719. DupIgnore : Exit;
  1720. DupError : Error(SDuplicateString,0)
  1721. end;
  1722. inherited Add(S);
  1723. end;
  1724. {****************************************************************************
  1725. TNamedItem
  1726. ****************************************************************************}
  1727. procedure TNamedItem.SetName(const AValue: String);
  1728. begin
  1729. if FName=AValue then exit;
  1730. With TNamedCollection(Collection) do
  1731. If UniqueNames then
  1732. If (IndexOfName(AVAlue)<>-1) then
  1733. Raise ECollectionError.CreateFmt(SErrNameExists,[AValue]);
  1734. FName:=AValue;
  1735. end;
  1736. {****************************************************************************
  1737. TNamedCollection
  1738. ****************************************************************************}
  1739. function TNamedCollection.IndexOfName(const AName: String): Integer;
  1740. begin
  1741. Result:=Count-1;
  1742. While (Result>=0) and (CompareText(TNamedItem(Items[Result]).FName,AName)<>0) do
  1743. Dec(Result);
  1744. end;
  1745. function TNamedCollection.ItemByName(const AName: String): TNamedItem;
  1746. Var
  1747. I : Integer;
  1748. begin
  1749. I:=IndexOfName(AName);
  1750. If (I=-1) Then
  1751. Raise ECollectionError.CreateFmt(SErrNoSuchName,[AName]);
  1752. Result:=TNamedItem(Items[i]);
  1753. end;
  1754. {****************************************************************************
  1755. TNamedItemList
  1756. ****************************************************************************}
  1757. function TNamedItemList.GetNamedItem(Index : Integer): TNamedItem;
  1758. begin
  1759. Result:=TNamedItem(Items[Index]);
  1760. end;
  1761. procedure TNamedItemList.SetNamedItem(Index : Integer; const AValue: TNamedItem);
  1762. begin
  1763. Items[Index]:=AValue;
  1764. end;
  1765. function TNamedItemList.IndexOfName(const AName: String): Integer;
  1766. begin
  1767. Result:=Count-1;
  1768. While (Result>=0) and (CompareText(GetNamedItem(Result).Name,AName)<>0) do
  1769. Dec(Result);
  1770. end;
  1771. function TNamedItemList.ItemByName(const ANAme: String): TNamedItem;
  1772. Var
  1773. I : Integer;
  1774. begin
  1775. I:=IndexOfName(AName);
  1776. If (I=-1) Then
  1777. Raise ECollectionError.CreateFmt(SErrNoSuchName,[AName]);
  1778. Result:=TNamedItem(Items[i]);
  1779. end;
  1780. {****************************************************************************
  1781. TTargets
  1782. ****************************************************************************}
  1783. function TTargets.GetTargetItem(Index : Integer): TTarget;
  1784. begin
  1785. Result:=TTarget(Items[Index]);
  1786. end;
  1787. function TTargets.GetTarget(const AName : String): TTarget;
  1788. begin
  1789. Result:=TTarget(ItemByName(AName));
  1790. end;
  1791. procedure TTargets.SetTargetItem(Index : Integer; const AValue: TTarget);
  1792. begin
  1793. Items[Index]:=AValue;
  1794. end;
  1795. function TTargets.AddFPDoc(const AUnitName, AXMLName: String): TTarget;
  1796. begin
  1797. Result:=Add as TTarget;
  1798. Result.Name:=AUnitName;
  1799. Result.XML:=AXMLName;
  1800. Result.TargetType:=ttFPDoc;
  1801. end;
  1802. Function TTargets.AddUnit(Const AUnitName : String) : TTarget;
  1803. begin
  1804. Result:=AddUnit(AUnitName,AllCPUs,AllOSes);
  1805. end;
  1806. Function TTargets.AddUnit(Const AUnitName : String;const OSes:TOSes) : TTarget;
  1807. begin
  1808. Result:=AddUnit(AUnitName,AllCPUs,OSes);
  1809. end;
  1810. {$ifdef cpu_only_overloads}
  1811. Function TTargets.AddUnit(Const AUnitName : String;const CPUs:TCPUs) : TTarget;
  1812. begin
  1813. Result:=AddUnit(AUnitName,CPUs,AllOSes);
  1814. end;
  1815. {$endif cpu_only_overloads}
  1816. Function TTargets.AddUnit(Const AUnitName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  1817. begin
  1818. Result:=Add as TTarget;
  1819. Result.Name:=AUnitName;
  1820. Result.TargetType:=TTUnit;
  1821. Result.CPUs:=CPUs;
  1822. Result.OSes:=OSes;
  1823. end;
  1824. Function TTargets.AddImplicitUnit(Const AUnitName : String;InstallUnit:boolean=true) : TTarget;
  1825. begin
  1826. Result:=AddImplicitUnit(AUnitName,AllCPUs,AllOSes,InstallUnit);
  1827. end;
  1828. Function TTargets.AddImplicitUnit(Const AUnitName : String;const OSes:TOSes;InstallUnit:boolean=true) : TTarget;
  1829. begin
  1830. Result:=AddImplicitUnit(AUnitName,AllCPUs,OSes,InstallUnit);
  1831. end;
  1832. Function TTargets.AddImplicitUnit(Const AUnitName : String;const CPUs:TCPUs;InstallUnit:boolean=true) : TTarget;
  1833. begin
  1834. Result:=AddImplicitUnit(AUnitName,CPUs,AllOSes,InstallUnit);
  1835. end;
  1836. Function TTargets.AddImplicitUnit(Const AUnitName : String;const CPUs:TCPUs;const OSes:TOSes;InstallUnit:boolean=true) : TTarget;
  1837. begin
  1838. Result:=Add as TTarget;
  1839. Result.Name:=AUnitName;
  1840. Result.CPUs:=CPUs;
  1841. Result.OSes:=OSes;
  1842. if InstallUnit then
  1843. Result.TargetType:=TTImplicitUnit
  1844. else
  1845. Result.TargetType:=TTCleanOnlyUnit;
  1846. end;
  1847. Function TTargets.AddProgram(Const AProgramName : String) : TTarget;
  1848. begin
  1849. Result:=AddProgram(AProgramName,AllCPUs,AllOSes);
  1850. end;
  1851. Function TTargets.AddProgram(Const AProgramName : String;const OSes:TOSes) : TTarget;
  1852. begin
  1853. Result:=AddProgram(AProgramName,AllCPUs,OSes);
  1854. end;
  1855. {$ifdef cpu_only_overloads}
  1856. Function TTargets.AddProgram(Const AProgramName : String;const CPUs:TCPUs) : TTarget;
  1857. begin
  1858. Result:=AddProgram(AProgramName,CPUs,AllOSes);
  1859. end;
  1860. {$endif cpu_only_overloads}
  1861. Function TTargets.AddProgram(Const AProgramName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  1862. begin
  1863. Result:=Add as TTarget;
  1864. Result.Name:=AProgramName;
  1865. Result.CPUs:=CPUs;
  1866. Result.OSes:=OSes;
  1867. Result.TargetType:=ttProgram;
  1868. end;
  1869. Function TTargets.AddExampleUnit(Const AUnitName : String) : TTarget;
  1870. begin
  1871. Result:=AddExampleUnit(AUnitName,AllCPUs,AllOSes);
  1872. end;
  1873. Function TTargets.AddExampleUnit(Const AUnitName : String;const OSes:TOSes) : TTarget;
  1874. begin
  1875. Result:=AddExampleUnit(AUnitName,AllCPUs,OSes);
  1876. end;
  1877. {$ifdef cpu_only_overloads}
  1878. Function TTargets.AddExampleUnit(Const AUnitName : String;const CPUs:TCPUs) : TTarget;
  1879. begin
  1880. Result:=AddExampleUnit(AUnitName,CPUs,AllOSes);
  1881. end;
  1882. {$endif cpu_only_overloads}
  1883. Function TTargets.AddExampleUnit(Const AUnitName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  1884. begin
  1885. Result:=Add as TTarget;
  1886. Result.Name:=AUnitName;
  1887. Result.CPUs:=CPUs;
  1888. Result.OSes:=OSes;
  1889. Result.TargetType:=ttExampleUnit;
  1890. end;
  1891. Function TTargets.AddExampleProgram(Const AProgramName : String) : TTarget;
  1892. begin
  1893. Result:=AddExampleProgram(AProgramName,AllCPUs,AllOSes);
  1894. end;
  1895. Function TTargets.AddExampleProgram(Const AProgramName : String;const OSes:TOSes) : TTarget;
  1896. begin
  1897. Result:=AddExampleProgram(AProgramName,AllCPUs,OSes);
  1898. end;
  1899. {$ifdef cpu_only_overloads}
  1900. Function TTargets.AddExampleProgram(Const AProgramName : String;const CPUs:TCPUs) : TTarget;
  1901. begin
  1902. Result:=AddExampleProgram(AProgramName,CPUs,AllOSes);
  1903. end;
  1904. {$endif cpu_only_overloads}
  1905. Function TTargets.AddExampleProgram(Const AProgramName : String;const CPUs:TCPUs;const OSes:TOSes) : TTarget;
  1906. begin
  1907. Result:=Add as TTarget;
  1908. Result.Name:=AProgramName;
  1909. Result.CPUs:=CPUs;
  1910. Result.OSes:=OSes;
  1911. Result.TargetType:=ttExampleProgram;
  1912. end;
  1913. {****************************************************************************
  1914. TSources
  1915. ****************************************************************************}
  1916. function TSources.GetSourceItem(Index : Integer): TSource;
  1917. begin
  1918. Result:=TSource(Items[Index]);
  1919. end;
  1920. procedure TSources.SetSourceItem(Index : Integer; const AValue: TSource);
  1921. begin
  1922. Items[Index]:=AValue;
  1923. end;
  1924. function TSources.AddDoc (const AFiles : String) : TSource;
  1925. begin
  1926. Result:=Add as TSource;
  1927. Result.Name:=AFiles;
  1928. Result.FSourceType:=stDoc;
  1929. end;
  1930. function TSources.AddDoc(const AFiles: String; AInstallSourcePath: String): TSource;
  1931. begin
  1932. Result:=Add as TSource;
  1933. Result.Name:=AFiles;
  1934. Result.FInstallSourcePath:=AInstallSourcePath;
  1935. Result.FSourceType:=stDoc;
  1936. end;
  1937. function TSources.AddSrc(const AFiles : String) : TSource;
  1938. begin
  1939. Result:=Add as TSource;
  1940. Result.Name:=AFiles;
  1941. Result.FSourceType:=stSrc;
  1942. end;
  1943. function TSources.AddExample(const AFiles : String) : TSource;
  1944. begin
  1945. Result:=Add as TSource;
  1946. Result.Name:=AFiles;
  1947. Result.FSourceType:=stExample;
  1948. end;
  1949. function TSources.AddExample(const AFiles: String; AInstallSourcePath: String): TSource;
  1950. begin
  1951. Result:=Add as TSource;
  1952. Result.Name:=AFiles;
  1953. Result.FInstallSourcePath:=AInstallSourcePath;
  1954. Result.FSourceType:=stExample;
  1955. end;
  1956. function TSources.AddTest(const AFiles : String) : TSource;
  1957. begin
  1958. Result:=Add as TSource;
  1959. Result.Name:=AFiles;
  1960. Result.FSourceType:=stTest;
  1961. end;
  1962. procedure TSources.AddDocFiles(const AFileMask: string; Recursive: boolean; AInstallSourcePath : String = '');
  1963. var
  1964. List : TStrings;
  1965. i: integer;
  1966. begin
  1967. List := TStringList.Create;
  1968. SearchFiles(AFileMask, Recursive, List);
  1969. for i:= 0 to Pred(List.Count) do
  1970. AddDoc(List[i], AInstallSourcePath);
  1971. List.Free;
  1972. end;
  1973. procedure TSources.AddSrcFiles(const AFileMask: string; Recursive: boolean);
  1974. var
  1975. List : TStrings;
  1976. i: integer;
  1977. begin
  1978. List := TStringList.Create;
  1979. SearchFiles(AFileMask, Recursive, List);
  1980. for i:= 0 to Pred(List.Count) do
  1981. AddSrc(List[i]);
  1982. List.Free;
  1983. end;
  1984. procedure TSources.AddExampleFiles(const AFileMask: string; Recursive: boolean; AInstallSourcePath : String = '');
  1985. var
  1986. List : TStrings;
  1987. i: integer;
  1988. begin
  1989. List := TStringList.Create;
  1990. SearchFiles(AFileMask, Recursive, List);
  1991. for i:= 0 to Pred(List.Count) do
  1992. AddExample(List[i], AInstallSourcePath);
  1993. List.Free;
  1994. end;
  1995. procedure TSources.AddTestFiles(const AFileMask: string; Recursive: boolean);
  1996. var
  1997. List : TStrings;
  1998. i: integer;
  1999. begin
  2000. List := TStringList.Create;
  2001. SearchFiles(AFileMask, Recursive, List);
  2002. for i:= 0 to Pred(List.Count) do
  2003. AddTest(List[i]);
  2004. List.Free;
  2005. end;
  2006. {****************************************************************************
  2007. TPackage
  2008. ****************************************************************************}
  2009. constructor TPackage.Create(ACollection: TCollection);
  2010. begin
  2011. inherited Create(ACollection);
  2012. FVersion:=TFPVersion.Create;
  2013. FTargets:=TTargets.Create(TTarget);
  2014. FSources:=TSources.Create(TSource);
  2015. FDependencies:=TDependencies.Create(TDependency);
  2016. FInstallFiles:=TConditionalStrings.Create(TConditionalString);
  2017. FCleanFiles:=TConditionalStrings.Create(TConditionalString);
  2018. FUnitPath:=TConditionalStrings.Create(TConditionalString);
  2019. FObjectPath:=TConditionalStrings.Create(TConditionalString);
  2020. FIncludePath:=TConditionalStrings.Create(TConditionalString);
  2021. FSourcePath:=TConditionalStrings.Create(TConditionalString);
  2022. FExamplePath:=TConditionalStrings.Create(TConditionalString);
  2023. FTestPath:=TConditionalStrings.Create(TConditionalString);
  2024. FCommands:=TCommands.Create(TCommand);
  2025. FCPUs:=AllCPUs;
  2026. FOSes:=AllOSes;
  2027. FInstalledChecksum:=$ffffffff;
  2028. // Implicit dependency on RTL
  2029. FDependencies.Add('rtl');
  2030. FSupportBuildModes:=[bmBuildUnit, bmOneByOne];
  2031. end;
  2032. destructor TPackage.destroy;
  2033. begin
  2034. FreeAndNil(FDependencies);
  2035. FreeAndNil(FInstallFiles);
  2036. FreeAndNil(FCleanFiles);
  2037. FreeAndNil(FIncludePath);
  2038. FreeAndNil(FSourcePath);
  2039. FreeAndNil(FExamplePath);
  2040. FreeAndNil(FTestPath);
  2041. FreeAndNil(FObjectPath);
  2042. FreeAndNil(FUnitPath);
  2043. FreeAndNil(FSources);
  2044. FreeAndNil(FTargets);
  2045. FreeAndNil(FVersion);
  2046. FreeAndNil(FOptions);
  2047. inherited destroy;
  2048. end;
  2049. function TPackage.HaveOptions: Boolean;
  2050. begin
  2051. Result:=(FOptions<>Nil);
  2052. end;
  2053. procedure TPackage.SetName(const AValue: String);
  2054. begin
  2055. inherited SetName(AValue);
  2056. // RTL should not have any dependencies
  2057. if AValue='rtl' then
  2058. FDependencies.Clear;
  2059. end;
  2060. Function TPackage.GetUnitsOutputDir(ACPU:TCPU; AOS : TOS):String;
  2061. begin
  2062. Result:='units'+PathDelim+MakeTargetString(ACPU,AOS);
  2063. end;
  2064. Function TPackage.GetBinOutputDir(ACPU:TCPU; AOS : TOS) : String;
  2065. begin
  2066. Result:='bin'+PathDelim+MakeTargetString(ACPU,AOS);
  2067. end;
  2068. procedure TPackage.GetCleanFiles(List: TStrings; ACPU:TCPU; AOS : TOS);
  2069. Var
  2070. OB,OU : String;
  2071. I : Integer;
  2072. begin
  2073. OB:=IncludeTrailingPathDelimiter(GetBinOutputDir(ACPU,AOS));
  2074. OU:=IncludeTrailingPathDelimiter(GetUnitsOutputDir(ACPU,AOS));
  2075. AddConditionalStrings(List,CleanFiles,ACPU,AOS);
  2076. For I:=0 to FTargets.Count-1 do
  2077. FTargets.TargetItems[I].GetCleanFiles(List, OU, OB, ACPU, AOS);
  2078. end;
  2079. procedure TPackage.GetInstallFiles(List: TStrings;Types : TTargetTypes;ACPU:TCPU; AOS : TOS);
  2080. Var
  2081. OB,OU : String;
  2082. I : Integer;
  2083. T : TTarget;
  2084. begin
  2085. OB:=IncludeTrailingPathDelimiter(GetBinOutputDir(Defaults.CPU,Defaults.OS));
  2086. OU:=IncludeTrailingPathDelimiter(GetUnitsOutputDir(Defaults.CPU,Defaults.OS));
  2087. AddConditionalStrings(List,InstallFiles,ACPU,AOS);
  2088. For I:=0 to FTargets.Count-1 do
  2089. begin
  2090. T:=FTargets.TargetItems[I];
  2091. if (T.TargetType in Types) and (T.Install) then
  2092. T.GetInstallFiles(List, OU, OB, ACPU, AOS);
  2093. end;
  2094. end;
  2095. procedure TPackage.GetInstallSourceFiles(List: TStrings; SourceTypes : TSourceTypes; TargetTypes : TTargetTypes);
  2096. Var
  2097. I : Integer;
  2098. S : TSource;
  2099. T : TTarget;
  2100. begin
  2101. For I:=0 to FSources.Count-1 do
  2102. begin
  2103. S:=FSources.SourceItems[I];
  2104. if (S.SourceType in SourceTypes) then
  2105. S.GetInstallFiles(List);
  2106. end;
  2107. For I:=0 to FTargets.Count-1 do
  2108. begin
  2109. T:=FTargets.TargetItems[I];
  2110. if (T.TargetType in TargetTypes) then
  2111. T.GetArchiveFiles(List,Defaults.CPU,Defaults.OS);
  2112. end;
  2113. end;
  2114. procedure TPackage.GetArchiveFiles(List: TStrings; ACPU:TCPU; AOS : TOS);
  2115. Var
  2116. I : Integer;
  2117. begin
  2118. // Targets only
  2119. For I:=0 to FTargets.Count-1 do
  2120. FTargets.TargetItems[I].GetArchiveFiles(List,ACPU,AOS);
  2121. end;
  2122. procedure TPackage.GetArchiveSourceFiles(List: TStrings);
  2123. var
  2124. i : integer;
  2125. begin
  2126. for i := 0 to Sources.Count-1 do
  2127. List.Add(Sources[i].Name);
  2128. end;
  2129. Function TPackage.GetDescription : string;
  2130. Var
  2131. FN : String;
  2132. L : TStringList;
  2133. begin
  2134. If (FDescription<>'') then
  2135. Result:=FDescription
  2136. else
  2137. If (FDescriptionFile<>'') then
  2138. begin
  2139. // Always relative to binary name.
  2140. FN:=ExtractFilePath(ParamStr(0));
  2141. FN:=FN+FDescriptionFile;
  2142. If FileExists(FN) then
  2143. begin
  2144. L:=TStringList.Create;
  2145. Try
  2146. L.LoadFromFile(FN);
  2147. Result:=L.Text;
  2148. Finally
  2149. L.Free;
  2150. end;
  2151. end;
  2152. end;
  2153. end;
  2154. Function TPackage.GetVersion : string;
  2155. begin
  2156. result:=FVersion.AsString;
  2157. end;
  2158. procedure TPackage.SetOptions(const AValue: TStrings);
  2159. begin
  2160. If (AValue=Nil) or (AValue.Count=0) then
  2161. FreeAndNil(Foptions)
  2162. else
  2163. Options.Assign(AValue);
  2164. end;
  2165. Procedure TPackage.SetVersion(const V : string);
  2166. begin
  2167. FVersion.AsString:=V;
  2168. end;
  2169. Function TPackage.GetFileName : string;
  2170. begin
  2171. If (FFileName<>'') then
  2172. Result:=FFileName
  2173. else
  2174. if not FVersion.Empty then
  2175. Result := Name + '-' + FVersion.AsString
  2176. else
  2177. Result := Name;
  2178. end;
  2179. function TPackage.GetOptions: TStrings;
  2180. begin
  2181. If (FOptions=Nil) then
  2182. FOptions:=TStringList.Create;
  2183. Result:=FOptions;
  2184. end;
  2185. Procedure TPackage.GetManifest(Manifest : TStrings);
  2186. procedure AddOSes(const AIndent:string;AOSes:TOSes);
  2187. var
  2188. IOS : TOS;
  2189. begin
  2190. if (AOSes=AllOSes) then
  2191. exit;
  2192. Manifest.Add(AIndent+'<oses>');
  2193. for IOS:=low(TOSes) to high(TOSes) do
  2194. if IOS in AOSes then
  2195. Manifest.Add(Format(AIndent+' <os name="%s"/>',[OSToString(IOS)]));
  2196. Manifest.Add(AIndent+'</oses>');
  2197. end;
  2198. procedure AddCPUs(const AIndent:string;ACPUs:TCPUs);
  2199. var
  2200. ICPU : TCPU;
  2201. begin
  2202. if (ACPUs=AllCPUs) then
  2203. exit;
  2204. Manifest.Add(AIndent+'<cpus>');
  2205. for ICPU:=low(TCPUs) to high(TCPUs) do
  2206. if ICPU in ACPUs then
  2207. Manifest.Add(Format(AIndent+' <cpu name="%s"/>',[CPUToString(ICPU)]));
  2208. Manifest.Add(AIndent+'</cpus>');
  2209. end;
  2210. function GetXMLVersionString(sMajor, sMinor, sMicro, sBuild: integer): string;
  2211. begin
  2212. Result := '<version';
  2213. if sMajor <> -1 then
  2214. Result := Result + ' major="' + IntToStr(sMajor) + '"';
  2215. if sMinor <> -1 then
  2216. Result := Result + ' minor="' + IntToStr(sMinor) + '"';
  2217. if sMicro <> -1 then
  2218. Result := Result + ' micro="' + IntToStr(sMicro) + '"';
  2219. if sBuild <> -1 then
  2220. Result := Result + ' build="' + IntToStr(sBuild) + '"';
  2221. Result := Result + '/>';
  2222. end;
  2223. Var
  2224. S : String;
  2225. i : Integer;
  2226. D : TDependency;
  2227. begin
  2228. With Manifest do
  2229. begin
  2230. Add(Format('<package name="%s">',[QuoteXml(Name)]));
  2231. Add(' ' + GetXMLVersionString(FVersion.Major,FVersion.Minor,FVersion.Micro,FVersion.Build));
  2232. AddOSes(' ',OSes);
  2233. AddCPUs(' ',CPUs);
  2234. Add(Format(' <filename>%s</filename>',[QuoteXml(FileName + ZipExt)]));
  2235. Add(Format(' <author>%s</author>',[QuoteXml(Author)]));
  2236. Add(Format(' <license>%s</license>',[QuoteXml(License)]));
  2237. if HomepageURL<>'' then
  2238. Add(Format(' <homepageurl>%s</homepageurl>',[QuoteXml(HomepageURL)]));
  2239. if DownloadURL<>'' then
  2240. Add(Format(' <downloadurl>%s</downloadurl>',[QuoteXml(DownloadURL)]));
  2241. Add(Format(' <email>%s</email>',[QuoteXMl(Email)]));
  2242. S:=Description;
  2243. If (S<>'') then
  2244. Add(Format(' <description>%s</description>',[QuoteXML(S)]));
  2245. If (Dependencies.Count>0) then
  2246. begin
  2247. Add(' <dependencies>');
  2248. for I:=0 to Dependencies.Count-1 do
  2249. begin
  2250. D:=Dependencies[i];
  2251. Add(' <dependency>');
  2252. Add(Format(' <package packagename="%s"/>',[QuoteXML(D.Value)]));
  2253. if not D.FVersion.Empty then
  2254. Add(' ' + GetXMLVersionString(D.FVersion.Major,D.FVersion.Minor,D.FVersion.Micro,D.FVersion.Build));
  2255. AddOSes(' ',D.OSes);
  2256. AddCPUs(' ',D.CPUs);
  2257. Add(' </dependency>');
  2258. end;
  2259. Add(' </dependencies>');
  2260. end;
  2261. Add('</package>');
  2262. end;
  2263. end;
  2264. procedure TPackage.LoadUnitConfigFromFile(Const AFileName: String);
  2265. var
  2266. L,L2 : TStrings;
  2267. VOS : TOS;
  2268. VCPU : TCPU;
  2269. i,k : Integer;
  2270. DepChecksum : Cardinal;
  2271. DepName : String;
  2272. D : TDependency;
  2273. begin
  2274. L:=TStringList.Create;
  2275. Try
  2276. ReadIniFile(AFileName,L);
  2277. With L do
  2278. begin
  2279. Version:=Values[KeyVersion];
  2280. InstalledChecksum:=Cardinal(StrToInt64Def(Values[KeyChecksum],$ffffffff));
  2281. VCPU:=StringToCPU(Values[KeyCPU]);
  2282. VOS:=StringToOS(Values[KeyOS]);
  2283. OSes:=[VOS];
  2284. CPUs:=[VCPU];
  2285. L2:=TStringList.Create;
  2286. L2.CommaText:=Values[KeyDepends];
  2287. for i:=0 to L2.Count-1 do
  2288. begin
  2289. DepName:=L2[i];
  2290. k:=Pos('|',DepName);
  2291. if k>0 then
  2292. begin
  2293. DepChecksum:=StrToInt(Copy(DepName,k+1,Length(DepName)-k));
  2294. DepName:=Copy(DepName,1,k-1);
  2295. end
  2296. else
  2297. DepChecksum:=$ffffffff;
  2298. D:=Dependencies.Add(DepName,CPUs,OSes);
  2299. D.RequireChecksum:=DepChecksum;
  2300. end;
  2301. FreeAndNil(L2);
  2302. NeedLibC:=Upcase(Values[KeyNeedLibC])='Y';
  2303. IsFPMakeAddIn:=Upcase(Values[KeyAddIn])='Y';
  2304. end;
  2305. Finally
  2306. L.Free;
  2307. end;
  2308. end;
  2309. procedure TPackage.SaveUnitConfigToStringList(const AStringList: TStrings; ACPU: TCPU; AOS: TOS);
  2310. Var
  2311. Deps : String;
  2312. i : integer;
  2313. D : TDependency;
  2314. p : TPackage;
  2315. begin
  2316. with AStringList do
  2317. begin
  2318. Values[KeyName]:=Name;
  2319. Values[KeyVersion]:=Version;
  2320. // TODO Generate checksum based on PPUs
  2321. Values[KeyChecksum]:=IntToStr(DateTimeToFileDate(Now));
  2322. Values[KeyCPU]:=CPUToString(ACPU);
  2323. Values[KeyOS]:=OSToString(AOS);
  2324. //Installer;
  2325. Values[KeySourcePath]:=IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(Installer.BuildEngine.FStartDir)+Directory);
  2326. Values[KeyFPMakeOptions]:=trim(Installer.FPMakeOptionsString);
  2327. Deps:='';
  2328. for i:=0 to Dependencies.Count-1 do
  2329. begin
  2330. D:=Dependencies[i];
  2331. if (ACPU in D.CPUs) and (AOS in D.OSes) then
  2332. begin
  2333. if Deps<>'' then
  2334. Deps:=Deps+',';
  2335. Deps:=Deps+D.Value;
  2336. P:=TPackage(D.Target);
  2337. if assigned(P) and (P.InstalledChecksum<>$ffffffff) then
  2338. Deps:=Deps+'|'+IntToStr(P.InstalledChecksum);
  2339. end;
  2340. end;
  2341. Values[KeyDepends]:=Deps;
  2342. if NeedLibC then
  2343. Values[KeyNeedLibC]:='Y'
  2344. else
  2345. Values[KeyNeedLibC]:='N';
  2346. if IsFPMakeAddIn then
  2347. Values[KeyAddIn]:='Y'
  2348. else
  2349. Values[KeyAddIn]:='N';
  2350. end;
  2351. end;
  2352. procedure TPackage.SaveUnitConfigToFile(Const AFileName: String;ACPU:TCPU;AOS:TOS);
  2353. Var
  2354. F : TFileStream;
  2355. L : TStringList;
  2356. begin
  2357. F:=TFileStream.Create(AFileName,fmCreate);
  2358. L:=TStringList.Create;
  2359. try
  2360. SaveUnitConfigToStringList(L,ACPU,AOS);
  2361. L.SaveToStream(F);
  2362. Finally
  2363. L.Free;
  2364. F.Free;
  2365. end;
  2366. end;
  2367. {****************************************************************************
  2368. TPackages
  2369. ****************************************************************************}
  2370. function TPackages.GetPackage(const AName : String): TPackage;
  2371. begin
  2372. Result:=TPackage(ItemByName(AName))
  2373. end;
  2374. function TPackages.GetPackageItem(AIndex : Integer): TPackage;
  2375. begin
  2376. Result:=TPackage(Items[AIndex]);
  2377. end;
  2378. procedure TPackages.SetPackageItem(AIndex : Integer; const AValue: TPackage);
  2379. begin
  2380. Items[AIndex]:=AValue;
  2381. end;
  2382. function TPackages.AddPackage(const AName: String): TPackage;
  2383. begin
  2384. Result:=Add as TPackage;
  2385. Result.Name:=AName;
  2386. end;
  2387. {****************************************************************************
  2388. TCustomDefaults
  2389. ****************************************************************************}
  2390. procedure TCustomDefaults.SetCPU(const AValue: TCPU);
  2391. begin
  2392. FCPU:=AValue;
  2393. RecalcTarget;
  2394. end;
  2395. procedure TCustomDefaults.SetOptions(const AValue: TStrings);
  2396. begin
  2397. If (AValue=Nil) or (AValue.Count=0) then
  2398. FreeAndNil(Foptions)
  2399. else
  2400. Options.Assign(AValue)
  2401. end;
  2402. function TCustomDefaults.GetBaseInstallDir: String;
  2403. begin
  2404. If (FBaseInstallDir<>'') then
  2405. Result:=FBaseInstallDir
  2406. else
  2407. if UnixPaths then
  2408. Result:=Prefix +'lib' + PathDelim + 'fpc' + PathDelim + FCompilerVersion + PathDelim
  2409. else
  2410. Result:=Prefix;
  2411. end;
  2412. function TCustomDefaults.GetBinInstallDir: String;
  2413. begin
  2414. If (FBinInstallDir<>'') then
  2415. Result:=FBinInstallDir
  2416. else
  2417. If UnixPaths then
  2418. Result:=Prefix+'bin'
  2419. else
  2420. Result:=BaseInstallDir+'bin';
  2421. end;
  2422. function TCustomDefaults.GetCompiler: String;
  2423. begin
  2424. If (FCompiler<>'') then
  2425. Result:=FCompiler
  2426. else
  2427. Result:='fpc';
  2428. end;
  2429. function TCustomDefaults.GetDocInstallDir: String;
  2430. begin
  2431. If (FDocInstallDir<>'') then
  2432. Result:=FDocInstallDir
  2433. else
  2434. If UnixPaths then
  2435. Result:=Prefix+'share'+PathDelim+'doc'
  2436. else
  2437. Result:=BaseInstallDir+'docs';
  2438. end;
  2439. function TCustomDefaults.GetExamplesInstallDir: String;
  2440. begin
  2441. If (FExamplesInstallDir<>'') then
  2442. Result:=FExamplesInstallDir
  2443. else
  2444. If UnixPaths then
  2445. Result:=Prefix+'share'+PathDelim+'doc'
  2446. else
  2447. Result:=BaseInstallDir+'examples';
  2448. end;
  2449. function TCustomDefaults.GetOptions: TStrings;
  2450. begin
  2451. If (FOptions=Nil) then
  2452. FOptions:=TStringList.Create;
  2453. Result:=FOptions;
  2454. end;
  2455. function TCustomDefaults.GetUnitInstallDir: String;
  2456. begin
  2457. Dictionary.AddVariable('target',Target);
  2458. Dictionary.AddVariable('BaseInstallDir',BaseInstallDir);
  2459. result := FixPath(Dictionary.ReplaceStrings(FUnitInstallDir));
  2460. end;
  2461. function TCustomDefaults.GetLocalUnitDir: String;
  2462. begin
  2463. Result:=FLocalUnitDir;
  2464. end;
  2465. function TCustomDefaults.GetFPDocOutputDir: String;
  2466. begin
  2467. If (FFPDocOutputDir<>'') then
  2468. Result:=IncludeTrailingPathDelimiter(FixPath(FFPDocOutputDir))
  2469. else
  2470. Result:=IncludeTrailingPathDelimiter(FixPath('.'+PathDelim+'docs'));
  2471. end;
  2472. function TCustomDefaults.GetGlobalUnitDir: String;
  2473. begin
  2474. If (FGlobalUnitDir<>'') then
  2475. Result:=FGlobalUnitDir
  2476. else
  2477. Result:=UnitInstallDir;
  2478. end;
  2479. procedure TCustomDefaults.SetLocalUnitDir(const AValue: String);
  2480. begin
  2481. // Use ExpandFileName to support ~/ expansion
  2482. if AValue<>'' then
  2483. FLocalUnitDir:=IncludeTrailingPathDelimiter(ExpandFileName(AValue))
  2484. else
  2485. FLocalUnitDir:='';
  2486. end;
  2487. procedure TCustomDefaults.SetGlobalUnitDir(const AValue: String);
  2488. begin
  2489. // Use ExpandFileName to support ~/ expansion
  2490. if AValue<>'' then
  2491. FGlobalUnitDir:=IncludeTrailingPathDelimiter(ExpandFileName(AValue))
  2492. else
  2493. FGlobalUnitDir:='';
  2494. end;
  2495. procedure TCustomDefaults.SetBaseInstallDir(const AValue: String);
  2496. begin
  2497. // Use ExpandFileName to support ~/ expansion
  2498. if AValue<>'' then
  2499. FBaseInstallDir:=IncludeTrailingPathDelimiter(ExpandFileName(AValue))
  2500. else
  2501. FBaseInstallDir:='';
  2502. BinInstallDir:='';
  2503. ExamplesInstallDir:='';
  2504. end;
  2505. procedure TCustomDefaults.SetOS(const AValue: TOS);
  2506. begin
  2507. FOS:=AValue;
  2508. Recalctarget;
  2509. end;
  2510. procedure TCustomDefaults.SetPrefix(const AValue: String);
  2511. begin
  2512. if FPrefix=AValue then exit;
  2513. FPrefix:=IncludeTrailingPathDelimiter(AValue);
  2514. BaseInstallDir:='';
  2515. end;
  2516. procedure TCustomDefaults.SetTarget(const AValue: String);
  2517. Var
  2518. P : Integer;
  2519. begin
  2520. if FTarget<>AValue then
  2521. begin
  2522. P:=Pos('-',AValue);
  2523. If (P<>0) then
  2524. begin
  2525. FOS:=StringToOS(System.Copy(Avalue,P+1,Length(AValue)-P));
  2526. FCPU:=StringToCPU(System.Copy(Avalue,1,P-1));
  2527. end
  2528. else
  2529. FOS:=StringToOS(AValue);
  2530. FTarget:=AValue;
  2531. end;
  2532. end;
  2533. procedure TCustomDefaults.SetUnitInstallDir(const AValue: String);
  2534. begin
  2535. if AValue<>'' then
  2536. FUnitInstallDir:=IncludeTrailingPathDelimiter(AValue)
  2537. else
  2538. FUnitInstallDir:='';
  2539. end;
  2540. procedure TCustomDefaults.RecalcTarget;
  2541. begin
  2542. Ftarget:=CPUToString(FCPU)+'-'+OStoString(FOS);
  2543. end;
  2544. function TCustomDefaults.CmdLineOptions: String;
  2545. begin
  2546. If Haveoptions then
  2547. Result:=OptionListToString(FOptions);
  2548. end;
  2549. constructor TCustomDefaults.Create;
  2550. begin
  2551. InitDefaults;
  2552. end;
  2553. procedure TCustomDefaults.InitDefaults;
  2554. begin
  2555. {$ifdef unix}
  2556. UnixPaths:=True;
  2557. {$else}
  2558. UnixPaths:=False;
  2559. {$endif}
  2560. FNoFPCCfg:=False;
  2561. FCPU:=cpuNone;
  2562. FOS:=osNone;
  2563. FUnitInstallDir:='$(BaseInstallDir)units/$(target)/$(packagename)';
  2564. FBuildMode:=bmOneByOne;
  2565. end;
  2566. function TCustomDefaults.HaveOptions: Boolean;
  2567. begin
  2568. Result:=Assigned(FOptions);
  2569. end;
  2570. procedure TCustomDefaults.LocalInit(Const AFileName : String);
  2571. Var
  2572. FN : String;
  2573. begin
  2574. FN:=AFileName;
  2575. If (FN='') then
  2576. begin
  2577. // Environment variable.
  2578. FN:=GetEnvironmentVariable('FPMAKECFG');
  2579. If (FN<>'') then
  2580. If not FileExists(FN) then
  2581. FN:='';
  2582. // User config file fpmake.cfg
  2583. If (FN='') then
  2584. begin
  2585. FN:=GetAppConfigFile(False);
  2586. If Not FileExists(FN) then
  2587. FN:='';
  2588. end;
  2589. // Global config file fpmake.cfg
  2590. If (FN='') then
  2591. begin
  2592. FN:=GetAppConfigFile(True);
  2593. If Not FileExists(FN) then
  2594. FN:='';
  2595. end;
  2596. end;
  2597. If (FN<>'') and FileExists(FN) then
  2598. LoadFromFile(FN);
  2599. end;
  2600. procedure TCustomDefaults.CompilerDefaults;
  2601. {$ifdef HAS_UNIT_PROCESS}
  2602. var
  2603. infoSL : TStringList;
  2604. {$endif HAS_UNIT_PROCESS}
  2605. begin
  2606. if (CPU=cpuNone) or (OS=osNone) or (FCompilerVersion='') then
  2607. begin
  2608. {$ifdef HAS_UNIT_PROCESS}
  2609. // Detect compiler version/target from -i option
  2610. infosl:=TStringList.Create;
  2611. infosl.Delimiter:=' ';
  2612. infosl.DelimitedText:=GetCompilerInfo(GetCompiler,'-iVTPTO');
  2613. if infosl.Count<>3 then
  2614. Raise EInstallerError.Create(SErrInvalidFPCInfo);
  2615. if FCompilerVersion='' then
  2616. FCompilerVersion:=infosl[0];
  2617. if CPU=cpuNone then
  2618. CPU:=StringToCPU(infosl[1]);
  2619. if OS=osNone then
  2620. OS:=StringToOS(infosl[2]);
  2621. {$else HAS_UNIT_PROCESS}
  2622. // Defaults taken from compiler used to build fpmake
  2623. if CPU=cpuNone then
  2624. CPU:=StringToCPU({$I %FPCTARGETCPU%});
  2625. if OS=osNone then
  2626. OS:=StringToOS({$I %FPCTARGETOS%});
  2627. if FCompilerVersion='' then
  2628. FCompilerVersion:={$I %FPCVERSION%};
  2629. {$endif HAS_UNIT_PROCESS}
  2630. end;
  2631. end;
  2632. procedure TCustomDefaults.LoadFromFile(Const AFileName: String);
  2633. Var
  2634. F : TFileStream;
  2635. begin
  2636. F:=TFileStream.Create(AFileName,fmOpenRead);
  2637. Try
  2638. LoadFromStream(F);
  2639. Finally
  2640. F.Free;
  2641. end;
  2642. end;
  2643. procedure TCustomDefaults.SaveToFile(Const AFileName: String);
  2644. Var
  2645. F : TFileStream;
  2646. begin
  2647. F:=TFileStream.Create(AFileName,fmCreate);
  2648. Try
  2649. SaveToStream(F);
  2650. Finally
  2651. F.Free;
  2652. end;
  2653. end;
  2654. procedure TCustomDefaults.SaveToStream(S : TStream);
  2655. Var
  2656. L : TStringList;
  2657. begin
  2658. L:=TStringList.Create;
  2659. try
  2660. With L do
  2661. begin
  2662. Values[KeyArchive]:=FArchive;
  2663. Values[KeyCompiler]:=FCompiler;
  2664. Values[KeyCopy]:=FCopy;
  2665. Values[KeyMkDir]:=FMkDir;
  2666. Values[KeyMove]:=FMove;
  2667. Values[KeyOptions]:=CmdLineOptions;
  2668. Values[KeyCPU]:=CPUToString(FCPU);
  2669. Values[KeyOS]:=OSToString(FOS);
  2670. Values[KeyMode]:=ModeToString(FMode);
  2671. Values[KeyLocalUnitDir]:=FLocalUnitDir;
  2672. Values[KeyGlobalUnitDir]:=FGlobalUnitDir;
  2673. Values[KeyPrefix]:=FPrefix;
  2674. Values[KeyBaseInstallDir]:=FBaseInstallDir;
  2675. Values[KeyUnitInstallDir]:=FUnitInstallDir;
  2676. Values[KeyBinInstallDir]:=FBinInstallDir;
  2677. Values[KeyDocInstallDir]:=FDocInstallDir;
  2678. Values[KeyExamplesInstallDir]:=FExamplesInstallDir;
  2679. Values[KeyRemove]:=FRemove;
  2680. Values[KeyRemoveDir]:=FRemoveDir;
  2681. Values[KeyRemoveTree]:=FRemoveTree;
  2682. Values[KeyTarget]:=FTarget;
  2683. if FNoFPCCfg then
  2684. Values[KeyNoFPCCfg]:='Y';
  2685. if FUseEnvironment then
  2686. Values[KeyUseEnv]:='Y';
  2687. if FInstallExamples then
  2688. Values[KeyInstallExamples]:='Y';
  2689. end;
  2690. L.SaveToStream(S);
  2691. Finally
  2692. L.Free;
  2693. end;
  2694. end;
  2695. procedure TCustomDefaults.LoadFromStream(S: TStream);
  2696. Var
  2697. L : TStrings;
  2698. Line : String;
  2699. I,P,PC : Integer;
  2700. begin
  2701. L:=TStringList.Create;
  2702. Try
  2703. L.LoadFromStream(S);
  2704. // Fix lines.
  2705. For I:=L.Count-1 downto 0 do
  2706. begin
  2707. Line:=L[I];
  2708. P:=Pos('=',Line);
  2709. PC:=Pos(';',Line); // Comment line.
  2710. If (P=0) or ((PC<>0) and (PC<P)) then
  2711. L.Delete(I)
  2712. else
  2713. L[i]:=Trim(System.Copy(Line,1,P-1)+'='+Trim(System.Copy(Line,P+1,Length(Line)-P)));
  2714. end;
  2715. With L do
  2716. begin
  2717. FArchive:=Values[KeyArchive];
  2718. FCompiler:=Values[KeyCompiler];
  2719. FCopy:=Values[KeyCopy];
  2720. FMkDir:=Values[KeyMkDir];
  2721. FMove:=Values[KeyMove];
  2722. FRemove:=Values[KeyRemove];
  2723. FRemoveDir:=Values[KeyRemoveDir];
  2724. FRemoveTree:=Values[KeyRemoveTree];
  2725. Options:=OptionsToStringList(Values[KeyOptions]);
  2726. Line:=Values[KeyCPU];
  2727. If (Line<>'') then
  2728. FCPU:=StringToCPU(Line);
  2729. Line:=Values[KeyOS];
  2730. If (Line<>'') then
  2731. FOS:=StringToOS(Line);
  2732. Line:=Values[KeyMode];
  2733. If (Line<>'') then
  2734. FMode:=StringToMode(Line);
  2735. FTarget:=Values[KeyTarget];
  2736. FLocalUnitDir:=Values[KeyLocalUnitDir];
  2737. FGlobalUnitDir:=Values[KeyGlobalUnitDir];
  2738. FPrefix:=Values[KeyPrefix];
  2739. FBaseInstallDir:=Values[KeyBaseInstallDir];
  2740. FUnitInstallDir:=Values[KeyUnitInstallDir];
  2741. FBinInstallDir:=Values[KeyBinInstallDir];
  2742. FDocInstallDir:=Values[KeyDocInstallDir];
  2743. FExamplesInstallDir:=Values[KeyExamplesInstallDir];
  2744. FInstallExamples:=(Upcase(Values[KeyInstallExamples])='Y');
  2745. FNoFPCCfg:=(Upcase(Values[KeyNoFPCCfg])='Y');
  2746. FUseEnvironment:=(Upcase(Values[KeyUseEnv])='Y');
  2747. end;
  2748. Finally
  2749. L.Free;
  2750. end;
  2751. end;
  2752. {****************************************************************************
  2753. TFPCDefaults
  2754. ****************************************************************************}
  2755. procedure TFPCDefaults.CompilerDefaults;
  2756. var
  2757. BD : String;
  2758. begin
  2759. inherited CompilerDefaults;
  2760. // Use the same algorithm as the compiler, see options.pas
  2761. {$ifdef Unix}
  2762. BD:=FixPath(GetEnvironmentVariable('FPCDIR'));
  2763. if BD='' then
  2764. begin
  2765. BD:='/usr/local/lib/fpc/'+FCompilerVersion;
  2766. if not DirectoryExists(BD) and
  2767. DirectoryExists('/usr/lib/fpc/'+FCompilerVersion) then
  2768. BD:='/usr/lib/fpc/'+FCompilerVersion;
  2769. end;
  2770. {$else unix}
  2771. BD:=FixPath(GetEnvironmentVariable('FPCDIR'));
  2772. if BD='' then
  2773. begin
  2774. BD:=ExtractFilePath(FCompiler)+'..';
  2775. if not(DirectoryExists(BD+'/units')) and
  2776. not(DirectoryExists(BD+'/rtl')) then
  2777. BD:=FBaseInstallDir+'..';
  2778. end;
  2779. {$endif unix}
  2780. // Where to install by default
  2781. if (FBaseInstallDir='') and (FPrefix='') then
  2782. BaseInstallDir:=BD;
  2783. // Where to find the units by default
  2784. if (FGlobalUnitDir='') then
  2785. GlobalUnitDir:=IncludeTrailingPathDelimiter(BD)+'units'+PathDelim+Target;
  2786. end;
  2787. {****************************************************************************
  2788. TCustomInstaller
  2789. ****************************************************************************}
  2790. constructor TCustomInstaller.Create(AOwner: TComponent);
  2791. begin
  2792. Dictionary:=DictionaryClass.Create(Nil);
  2793. AnalyzeOptions;
  2794. CreatePackages;
  2795. end;
  2796. destructor TCustomInstaller.Destroy;
  2797. begin
  2798. FreePackages;
  2799. FreeAndNil(Defaults);
  2800. FreeAndNil(Dictionary);
  2801. inherited destroy;
  2802. end;
  2803. function TCustomInstaller.GetPackages: TPackages;
  2804. begin
  2805. result := FPackages;
  2806. end;
  2807. procedure TCustomInstaller.Log(Level: TVerboseLevel; const Msg: String);
  2808. begin
  2809. If Level in FLogLevels then
  2810. Writeln(StdOut,Msg);
  2811. end;
  2812. procedure TCustomInstaller.CreatePackages;
  2813. begin
  2814. FPackages:=TPackages.Create(TPackage);
  2815. end;
  2816. procedure TCustomInstaller.FreePackages;
  2817. begin
  2818. FreeAndNil(FPackages);
  2819. end;
  2820. procedure TCustomInstaller.CreateBuildEngine;
  2821. begin
  2822. FBuildEngine:=TBuildEngine.Create(Self);
  2823. // FBuildEngine.Defaults:=Defaults;
  2824. FBuildEngine.ListMode:=FListMode;
  2825. FBuildEngine.Verbose := (FLogLevels = AllMessages);
  2826. FBuildEngine.OnLog:[email protected];
  2827. end;
  2828. procedure TCustomInstaller.Error(const Msg: String);
  2829. begin
  2830. Raise EInstallerError.Create(Msg);
  2831. end;
  2832. procedure TCustomInstaller.Error(const Fmt: String; Args: array of const);
  2833. begin
  2834. Raise EInstallerError.CreateFmt(Fmt,Args);
  2835. end;
  2836. Function TCustomInstaller.AddPackage(const AName: String) : TPackage;
  2837. begin
  2838. result:=Packages.AddPackage(AName);
  2839. end;
  2840. procedure TCustomInstaller.AnalyzeOptions;
  2841. Function CheckOption(Index : Integer;const Short,Long : String; AddToOptionString: boolean = true): Boolean;
  2842. var
  2843. O : String;
  2844. begin
  2845. O:=Paramstr(Index);
  2846. Result:=(O='-'+short) or (O='--'+long) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
  2847. if AddToOptionString and Result then FFPMakeOptionsString := FFPMakeOptionsString+' '+O;
  2848. end;
  2849. Function CheckCustomOption(Index : Integer; out CustOptName: string): Boolean;
  2850. var
  2851. O : String;
  2852. i : integer;
  2853. begin
  2854. result := false;
  2855. CustOptName:='';
  2856. O:=Paramstr(Index);
  2857. if copy(O,1,2)<>'--' then
  2858. Exit;
  2859. i := pos('=',O);
  2860. if i=0 then
  2861. Exit;
  2862. O:=copy(O,3,i-3);
  2863. CustOptName:=O;
  2864. Result:=CustomFpmakeCommandlineOptions.IndexOfName(O)>-1;
  2865. if Result then FFPMakeOptionsString := FFPMakeOptionsString+' '+Paramstr(Index);
  2866. end;
  2867. Function CheckCommand(Index : Integer;const Short,Long : String): Boolean;
  2868. var
  2869. O : String;
  2870. begin
  2871. O:=Paramstr(Index);
  2872. Result:=(O='-'+short) or (O=long);
  2873. end;
  2874. Function OptionArg(Var Index : Integer) : String;
  2875. Var
  2876. P : Integer;
  2877. begin
  2878. if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
  2879. begin
  2880. If Index<ParamCount then
  2881. begin
  2882. Inc(Index);
  2883. Result:=Paramstr(Index);
  2884. end
  2885. else
  2886. Error(SErrNeedArgument,[Index,ParamStr(Index)]);
  2887. end
  2888. else If length(ParamStr(Index))>2 then
  2889. begin
  2890. P:=Pos('=',Paramstr(Index));
  2891. If (P=0) then
  2892. Error(SErrNeedArgument,[Index,ParamStr(Index)])
  2893. else
  2894. begin
  2895. Result:=Paramstr(Index);
  2896. Delete(Result,1,P);
  2897. end;
  2898. end;
  2899. end;
  2900. function SplitSpaces(var SplitString: string) : string;
  2901. var i : integer;
  2902. begin
  2903. i := pos(' ',SplitString);
  2904. if i > 0 then
  2905. begin
  2906. result := copy(SplitString,1,i-1);
  2907. delete(SplitString,1,i);
  2908. end
  2909. else
  2910. begin
  2911. result := SplitString;
  2912. SplitString:='';
  2913. end;
  2914. end;
  2915. Var
  2916. I : Integer;
  2917. DefaultsFileName : string;
  2918. OptString : string;
  2919. CustOptName : string;
  2920. begin
  2921. I:=0;
  2922. FListMode:=False;
  2923. FLogLevels:=DefaultMessages;
  2924. While (I<ParamCount) do
  2925. begin
  2926. Inc(I);
  2927. if CheckOption(I,'v','verbose',false) then
  2928. FLogLevels:=AllMessages
  2929. else if CheckOption(I,'d','debug',false) then
  2930. FLogLevels:=AllMessages+[vlDebug]
  2931. else if CheckCommand(I,'m','compile') then
  2932. FRunMode:=rmCompile
  2933. else if CheckCommand(I,'b','build') then
  2934. FRunMode:=rmBuild
  2935. else if CheckCommand(I,'i','install') then
  2936. FRunMode:=rmInstall
  2937. else if CheckCommand(I,'c','clean') then
  2938. FRunMode:=rmClean
  2939. else if CheckCommand(I,'dc','distclean') then
  2940. FRunMode:=rmDistClean
  2941. else if CheckCommand(I,'a','archive') then
  2942. FRunMode:=rmarchive
  2943. else if CheckCommand(I,'M','manifest') then
  2944. FRunMode:=rmManifest
  2945. else if CheckOption(I,'h','help') then
  2946. Usage('',[])
  2947. else if Checkoption(I,'C','cpu') then
  2948. Defaults.CPU:=StringToCPU(OptionArg(I))
  2949. else if Checkoption(I,'O','os') then
  2950. Defaults.OS:=StringToOS(OptionArg(I))
  2951. else if Checkoption(I,'t','target') then
  2952. Defaults.Target:=OptionArg(I)
  2953. else if CheckOption(I,'l','list-commands') then
  2954. FListMode:=True
  2955. else if Checkoption(I,'P','prefix') then
  2956. Defaults.Prefix:=OptionArg(I)
  2957. else if Checkoption(I,'n','nofpccfg') then
  2958. Defaults.NoFPCCfg:=true
  2959. {$ifdef HAS_UNIT_PROCESS}
  2960. else if Checkoption(I,'e','useenv') then
  2961. Defaults.UseEnvironment:=true
  2962. {$endif}
  2963. else if CheckOption(I,'B','baseinstalldir') then
  2964. Defaults.BaseInstallDir:=OptionArg(I)
  2965. else if CheckOption(I,'U','unitinstalldir') then
  2966. Defaults.UnitInstallDir:=OptionArg(I)
  2967. else if CheckOption(I,'UL','localunitdir') then
  2968. Defaults.LocalUnitDir:=OptionArg(I)
  2969. else if CheckOption(I,'UG','globalunitdir') then
  2970. Defaults.GlobalUnitDir:=OptionArg(I)
  2971. else if CheckOption(I,'o','options') then
  2972. begin
  2973. OptString := OptionArg(I);
  2974. while OptString <> '' do
  2975. Defaults.Options.Add(SplitSpaces(OptString));
  2976. end
  2977. else if CheckOption(I,'r','compiler') then
  2978. Defaults.Compiler:=OptionArg(I)
  2979. else if CheckOption(I,'f','config') then
  2980. DefaultsFileName:=OptionArg(I)
  2981. else if CheckOption(I,'ie','installexamples') then
  2982. Defaults.InstallExamples:=true
  2983. else if CheckOption(I,'bu','buildunit') then
  2984. Defaults.BuildMode:=bmBuildUnit
  2985. else if CheckOption(I,'io','ignoreinvalidoption') then
  2986. Defaults.IgnoreInvalidOptions:=true
  2987. else if CheckOption(I,'d','doc-folder') then
  2988. Defaults.FPDocOutputDir:=OptionArg(I)
  2989. else if assigned(CustomFpmakeCommandlineOptions) and CheckCustomOption(I,CustOptName) then
  2990. begin
  2991. if not assigned(CustomFpMakeCommandlineValues) then
  2992. CustomFpMakeCommandlineValues := TStringList.Create;
  2993. CustomFpMakeCommandlineValues.Values[CustOptName]:=OptionArg(I)
  2994. end
  2995. else if not Defaults.IgnoreInvalidOptions then
  2996. begin
  2997. Usage(SErrInValidArgument,[I,ParamStr(I)]);
  2998. end;
  2999. end;
  3000. If DefaultsFileName<>'' then
  3001. Defaults.LocalInit(DefaultsFileName);
  3002. Defaults.CompilerDefaults;
  3003. end;
  3004. procedure TCustomInstaller.Usage(const FMT: String; Args: array of const);
  3005. Procedure LogCmd(const LC,Msg : String);
  3006. begin
  3007. Log(vlInfo,Format(' %-12s %s',[LC,MSG]));
  3008. end;
  3009. Procedure LogOption(const C,LC,Msg : String);
  3010. begin
  3011. Log(vlInfo,Format(' -%s --%-16s %s',[C,LC,MSG]));
  3012. end;
  3013. Procedure LogArgOption(const C,LC,Msg : String);
  3014. begin
  3015. Log(vlInfo,Format(' -%s --%-20s %s',[C,LC+'='+SValue,MSG]));
  3016. end;
  3017. var
  3018. i: Integer;
  3019. begin
  3020. // Force the Usage to be displayed
  3021. Include(FLogLevels,vlInfo);
  3022. If (FMT<>'') then
  3023. Log(vlInfo,Format(Fmt,Args));
  3024. Log(vlInfo,Format(SHelpUsage,[Paramstr(0)]));
  3025. Log(vlInfo,SHelpCommand);
  3026. LogCmd('compile',SHelpCompile);
  3027. LogCmd('build',SHelpBuild);
  3028. LogCmd('install',SHelpInstall);
  3029. LogCmd('clean',SHelpClean);
  3030. LogCmd('archive',SHelpArchive);
  3031. LogCmd('manifest',SHelpManifest);
  3032. Log(vlInfo,SHelpCmdOptions);
  3033. LogOption('h','help',SHelpHelp);
  3034. LogOption('l','list-commands',SHelpList);
  3035. LogOption('n','nofpccfg',SHelpNoFPCCfg);
  3036. LogOption('v','verbose',SHelpVerbose);
  3037. {$ifdef HAS_UNIT_PROCESS}
  3038. LogOption('e', 'useenv', sHelpUseEnvironment);
  3039. {$endif}
  3040. LogOption('ie','installexamples',SHelpInstExamples);
  3041. LogOption('bu','buildunit',SHelpUseBuildUnit);
  3042. LogArgOption('C','cpu',SHelpCPU);
  3043. LogArgOption('O','os',SHelpOS);
  3044. LogArgOption('t','target',SHelpTarget);
  3045. LogArgOption('P','prefix',SHelpPrefix);
  3046. LogArgOption('B','baseinstalldir',SHelpBaseInstalldir);
  3047. LogArgOption('UL','localunitdir',SHelpLocalUnitdir);
  3048. LogArgOption('UG','globalunitdir',SHelpGlobalUnitdir);
  3049. LogArgOption('U','unitinstalldir',SHelpUnitInstallDir);
  3050. LogArgOption('r','compiler',SHelpCompiler);
  3051. LogArgOption('f','config',SHelpConfig);
  3052. LogArgOption('o','options',SHelpOptions);
  3053. LogArgOption('io','ignoreinvalidoption',SHelpIgnoreInvOpt);
  3054. LogArgOption('d', 'doc-folder', sHelpFpdocOutputDir);
  3055. if assigned(CustomFpmakeCommandlineOptions) then for i := 0 to CustomFpmakeCommandlineOptions.Count-1 do
  3056. LogArgOption(' ',CustomFpmakeCommandlineOptions.Names[i],CustomFpmakeCommandlineOptions.ValueFromIndex[i]);
  3057. Log(vlInfo,'');
  3058. If (FMT<>'') then
  3059. halt(1)
  3060. else
  3061. halt(0);
  3062. end;
  3063. procedure TCustomInstaller.Compile(Force: Boolean);
  3064. begin
  3065. FBuildEngine.ForceCompile:=Force;
  3066. FBuildEngine.Compile(Packages);
  3067. end;
  3068. procedure TCustomInstaller.Clean(AllTargets: boolean);
  3069. begin
  3070. BuildEngine.Clean(Packages, AllTargets);
  3071. end;
  3072. procedure TCustomInstaller.Install;
  3073. begin
  3074. BuildEngine.Install(Packages);
  3075. end;
  3076. procedure TCustomInstaller.Archive;
  3077. begin
  3078. // Force generation of manifest.xml, this is required for the repository
  3079. BuildEngine.Manifest(Packages);
  3080. BuildEngine.Archive(Packages);
  3081. end;
  3082. procedure TCustomInstaller.Manifest;
  3083. begin
  3084. BuildEngine.Manifest(Packages);
  3085. end;
  3086. procedure TCustomInstaller.CheckPackages;
  3087. begin
  3088. If (Packages.Count=0) then
  3089. Error(SErrNoPackagesDefined);
  3090. // Check for other obvious errors ?
  3091. end;
  3092. Function TCustomInstaller.Run : Boolean;
  3093. begin
  3094. Result:=True;
  3095. try
  3096. CheckPackages;
  3097. CreateBuildEngine;
  3098. Case RunMode of
  3099. rmCompile : Compile(False);
  3100. rmBuild : Compile(True);
  3101. rmInstall : Install;
  3102. rmArchive : Archive;
  3103. rmClean : Clean(False);
  3104. rmDistClean: Clean(True);
  3105. rmManifest : Manifest;
  3106. end;
  3107. except
  3108. On E : Exception do
  3109. begin
  3110. Log(vlError,SErrInstaller);
  3111. Log(vlError,E.Message);
  3112. Result:=False;
  3113. end;
  3114. end;
  3115. // Force returning an exitcode to the shell
  3116. if not Result then
  3117. ExitCode:=1;
  3118. end;
  3119. {****************************************************************************
  3120. TFPCInstaller
  3121. ****************************************************************************}
  3122. constructor TFPCInstaller.Create(AOwner: TComponent);
  3123. begin
  3124. if assigned(Defaults) then
  3125. Error(SErrAlreadyInitialized);
  3126. Defaults:=TFPCDefaults.Create;
  3127. inherited Create(AOwner);
  3128. end;
  3129. {****************************************************************************
  3130. TBasicInstaller
  3131. ****************************************************************************}
  3132. constructor TBasicInstaller.Create(AOwner: TComponent);
  3133. begin
  3134. if assigned(Defaults) then
  3135. Error(SErrAlreadyInitialized);
  3136. Defaults:=TBasicDefaults.Create;
  3137. inherited Create(AOwner);
  3138. end;
  3139. {****************************************************************************
  3140. TBuildEngine
  3141. ****************************************************************************}
  3142. constructor TBuildEngine.Create(AOwner: TComponent);
  3143. begin
  3144. inherited Create(AOwner);
  3145. // Maybe this should be the current directory ?
  3146. // Or have it as a command-line option.
  3147. // Would allow to put all 'installers' in one dir and call them
  3148. // With --start-dir=/path/to/sources.
  3149. FStartDir:=includeTrailingPathDelimiter(GetCurrentDir);
  3150. FExternalPackages:=TPackages.Create(TPackage);
  3151. end;
  3152. destructor TBuildEngine.Destroy;
  3153. begin
  3154. FreeAndNil(FExternalPackages);
  3155. inherited Destroy;
  3156. end;
  3157. procedure TBuildEngine.Error(const Msg: String);
  3158. begin
  3159. Raise EInstallerError.Create(Msg);
  3160. end;
  3161. procedure TBuildEngine.Error(const Fmt: String; const Args: array of const);
  3162. begin
  3163. Raise EInstallerError.CreateFmt(Fmt,Args);
  3164. end;
  3165. procedure TBuildEngine.ExecuteCommand(const Cmd,Args : String; const Env: TStrings = nil; IgnoreError : Boolean = False);
  3166. Var
  3167. E : Integer;
  3168. cmdLine: string;
  3169. ConsoleOutput: TMemoryStream;
  3170. s: string;
  3171. begin
  3172. Log(vlInfo,SInfoExecutingCommand,[Cmd,Args]);
  3173. if ListMode then
  3174. Log(vlCommand,'%s %s',[Cmd,Args])
  3175. else
  3176. begin
  3177. // We should check cmd for spaces, and move all after first space to args.
  3178. ConsoleOutput := TMemoryStream.Create;
  3179. try
  3180. {$ifdef HAS_UNIT_PROCESS}
  3181. E:=ExecuteFPC(Verbose, cmd, args, env, ConsoleOutput);
  3182. {$else}
  3183. E:=ExecuteProcess(cmd,args);
  3184. {$endif}
  3185. If (E<>0) and (not IgnoreError) then
  3186. begin
  3187. if trim(Args)<>'' then
  3188. cmdLine := cmd + ' ' + trim(args)
  3189. else
  3190. cmdline := cmd;
  3191. s := ParsecompilerOutput(ConsoleOutput,Verbose);
  3192. Error(SErrExternalCommandFailed,[cmdLine,E,s]);
  3193. end;
  3194. finally
  3195. ConsoleOutput.Free;
  3196. end;
  3197. end;
  3198. end;
  3199. Function TBuildEngine.SysDirectoryExists(const ADir:string):Boolean;
  3200. begin
  3201. result:=SysUtils.DirectoryExists(ADir);
  3202. if result then
  3203. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgFound])
  3204. else
  3205. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgNotFound]);
  3206. end;
  3207. Function TBuildEngine.SysFileExists(const AFileName:string):Boolean;
  3208. begin
  3209. result:=SysUtils.FileExists(AFileName);
  3210. if result then
  3211. Log(vlDebug,SDbgFileExists,[AFileName,SDbgFound])
  3212. else
  3213. Log(vlDebug,SDbgFileExists,[AFileName,SDbgNotFound]);
  3214. end;
  3215. procedure TBuildEngine.SysCopyFile(Const Src,Dest : String);
  3216. Var
  3217. D,S : String;
  3218. Fin,FOut : TFileStream;
  3219. Count : Int64;
  3220. A : Integer;
  3221. begin
  3222. Log(vlInfo,SInfoCopyingFile,[Src,Dest]);
  3223. FIn:=TFileStream.Create(Src,fmopenRead);
  3224. Try
  3225. D:=IncludeTrailingPathDelimiter(Dest);
  3226. If DirectoryExists(D) then
  3227. S:=D+ExtractFileName(Src)
  3228. else
  3229. S:=Dest;
  3230. FOut:=TFileStream.Create(S,fmCreate);
  3231. Try
  3232. Count:=Fout.CopyFrom(FIn,0);
  3233. If (Count<>Fin.Size) then
  3234. Error(SErrCopyingFile,[Src,S]);
  3235. Finally
  3236. FreeAndNil(Fout);
  3237. end;
  3238. A:=FileGetDate(FIn.Handle);
  3239. If (A=-1) then
  3240. log(vlWarning,SWarnFailedToGetTime,[Src])
  3241. else
  3242. if FileSetDate(S,A)<>0 then
  3243. Log(vlWarning,SWarnFailedToSetTime,[S]);
  3244. finally
  3245. FreeAndNil(Fin);
  3246. end;
  3247. end;
  3248. procedure TBuildEngine.SysMoveFile(Const Src,Dest : String);
  3249. Var
  3250. S : String;
  3251. begin
  3252. If DirectoryExists(IncludeTrailingPathDelimiter(Dest)) then
  3253. S:=IncludeTrailingPathDelimiter(Dest)+ExtractFileName(Src)
  3254. else
  3255. S:=Dest;
  3256. If Not RenameFile(Src,S) then
  3257. begin
  3258. Try
  3259. SysCopyFile(Src,S);
  3260. SysDeleteFile(Src);
  3261. Except
  3262. On E : Exception Do
  3263. Error(SErrMovingFile,[Src,S]);
  3264. end;
  3265. end;
  3266. end;
  3267. procedure TBuildEngine.SysDeleteFile(Const AFileName : String);
  3268. begin
  3269. if not FileExists(AFileName) then
  3270. Log(vldebug,SDbgFileDoesNotExist,[AFileName])
  3271. else If Not DeleteFile(AFileName) then
  3272. Error(SErrDeletingFile,[AFileName]);
  3273. end;
  3274. procedure TBuildEngine.SysDeleteDirectory(const ADirectoryName: String);
  3275. begin
  3276. if not DirectoryExists(ADirectoryName) then
  3277. Log(vldebug,SDbgDirectoryDoesNotExist,[ADirectoryName])
  3278. else if not IsDirectoryEmpty(ADirectoryName) then
  3279. Log(vldebug,SDbgDirectoryNotEmpty,[ADirectoryName])
  3280. else If Not RemoveDir(ADirectoryName) then
  3281. Error(SErrRemovingDirectory,[ADirectoryName]);
  3282. end;
  3283. procedure TBuildEngine.SysDeleteTree(const ADirectoryName: String);
  3284. function IntRemoveTree(const ADirectoryName: String) : boolean;
  3285. var
  3286. searchRec: TSearchRec;
  3287. SearchResult: longint;
  3288. begin
  3289. result := true;
  3290. SearchResult := FindFirst(IncludeTrailingPathDelimiter(ADirectoryName)+AllFilesMask, faAnyFile+faSymLink, searchRec);
  3291. try
  3292. while SearchResult=0 do
  3293. begin
  3294. if (searchRec.Name<>'.') and (searchRec.Name<>'..') then
  3295. begin
  3296. if (searchRec.Attr and faDirectory)=faDirectory then
  3297. begin
  3298. if not IntRemoveTree(IncludeTrailingPathDelimiter(ADirectoryName)+searchRec.Name) then
  3299. result := false;
  3300. end
  3301. else if not DeleteFile(IncludeTrailingPathDelimiter(ADirectoryName)+searchRec.Name) then
  3302. result := False;
  3303. end;
  3304. SearchResult := FindNext(searchRec);
  3305. end;
  3306. finally
  3307. FindClose(searchRec);
  3308. end;
  3309. if not RemoveDir(ADirectoryName) then
  3310. result := false;
  3311. end;
  3312. begin
  3313. if not DirectoryExists(ADirectoryName) then
  3314. Log(vldebug,SDbgDirectoryDoesNotExist,[ADirectoryName])
  3315. else If Not IntRemoveTree(ADirectoryName) then
  3316. Error(SErrRemovingDirectory,[ADirectoryName]);
  3317. end;
  3318. procedure TBuildEngine.SysArchiveFiles(List: TStrings;Const AFileName: String);
  3319. begin
  3320. If Not (Assigned(OnArchivefiles) or Assigned(ArchiveFilesProc)) then
  3321. Raise EInstallerError.Create(SErrNoArchiveSupport);
  3322. If Assigned(ArchiveFilesProc) then
  3323. ArchiveFilesProc(AFileName,List)
  3324. else
  3325. OnArchiveFiles(AFileName,List);
  3326. end;
  3327. procedure TBuildEngine.LogIndent;
  3328. begin
  3329. FLogPrefix:=FLogPrefix+' ';
  3330. end;
  3331. procedure TBuildEngine.LogUnIndent;
  3332. begin
  3333. Delete(FLogPrefix,1,2);
  3334. end;
  3335. procedure TBuildEngine.Log(Level: TVerboseLevel; const Msg: String);
  3336. begin
  3337. If Assigned(FOnLog) then
  3338. begin
  3339. if Level in [vlInfo,vlDebug] then
  3340. FOnLog(Level,FLogPrefix+Msg)
  3341. else
  3342. FOnLog(Level,Msg);
  3343. end;
  3344. end;
  3345. procedure TBuildEngine.Log(Level: TVerboseLevel; const Fmt: String;const Args: array of const);
  3346. begin
  3347. Log(Level,Format(Fmt,Args));
  3348. end;
  3349. procedure TBuildEngine.EnterDir(ADir: String);
  3350. Var
  3351. D : String;
  3352. begin
  3353. D:=FStartDir;
  3354. D:=D+ADir;
  3355. Log(vlDebug,SDbgEnterDir,[D]);
  3356. If Not SetCurrentDir(D) then
  3357. Error(SErrChangeDirFailed,[D]);
  3358. end;
  3359. procedure TBuildEngine.CmdCopyFiles(List: TStrings; Const DestDir: String);
  3360. Var
  3361. Args : String;
  3362. I : Integer;
  3363. DestFileName : String;
  3364. begin
  3365. CmdCreateDir(DestDir);
  3366. If (Defaults.Copy<>'') then
  3367. begin
  3368. Args:=FileListToString(List,'');
  3369. Args:=Args+' '+DestDir;
  3370. ExecuteCommand(Defaults.Copy,Args);
  3371. end
  3372. else
  3373. For I:=0 to List.Count-1 do
  3374. if List.Names[i]<>'' then
  3375. begin
  3376. if IsRelativePath(list.ValueFromIndex[i]) then
  3377. DestFileName:=DestDir+list.ValueFromIndex[i]
  3378. else
  3379. DestFileName:=list.ValueFromIndex[i];
  3380. CmdCreateDir(ExtractFilePath(DestFileName));
  3381. SysCopyFile(List.names[i],DestFileName)
  3382. end
  3383. else
  3384. SysCopyFile(List[i],DestDir);
  3385. end;
  3386. procedure TBuildEngine.CmdCreateDir(const DestDir: String);
  3387. begin
  3388. If (Defaults.MkDir<>'') then
  3389. ExecuteCommand(Defaults.MkDir,DestDir)
  3390. else
  3391. If not ForceDirectories(DestDir) then
  3392. Error(SErrCreatingDirectory,[DestDir]);
  3393. end;
  3394. procedure TBuildEngine.CmdMoveFiles(List: TStrings; Const DestDir: String);
  3395. Var
  3396. Args : String;
  3397. I : Integer;
  3398. begin
  3399. CmdCreateDir(DestDir);
  3400. If (Defaults.Move<>'') then
  3401. begin
  3402. Args:=FileListToString(List,'');
  3403. Args:=Args+' '+DestDir;
  3404. ExecuteCommand(Defaults.Move,Args);
  3405. end
  3406. else
  3407. For I:=0 to List.Count-1 do
  3408. SysMoveFile(List[i],DestDir);
  3409. end;
  3410. procedure TBuildEngine.CmdDeleteFiles(List: TStrings);
  3411. Var
  3412. Args : String;
  3413. I : Integer;
  3414. begin
  3415. If (Defaults.Remove<>'') then
  3416. begin
  3417. Args:=FileListToString(List,'');
  3418. ExecuteCommand(Defaults.Remove,Args);
  3419. end
  3420. else
  3421. For I:=0 to List.Count-1 do
  3422. SysDeleteFile(List[i]);
  3423. end;
  3424. procedure TBuildEngine.CmdArchiveFiles(List: TStrings; Const ArchiveFile: String);
  3425. Var
  3426. S,C,O : String;
  3427. begin
  3428. If (Defaults.Archive='') then
  3429. SysArchiveFiles(List,ArchiveFile)
  3430. else
  3431. begin
  3432. S:=FileListToString(List,'');
  3433. SplitCommand(Defaults.Archive,C,O);
  3434. If (O='') then
  3435. O:=ArchiveFile+' '+S
  3436. else
  3437. O:=Substitute(O,['ARCHIVE',ArchiveFile,'FILESORDIRS']);
  3438. ExecuteCommand(C,O);
  3439. end;
  3440. end;
  3441. procedure TBuildEngine.CmdRenameFile(SourceName, DestName: String);
  3442. var
  3443. Args: string;
  3444. begin
  3445. If (Defaults.Move<>'') then
  3446. begin
  3447. Args:=SourceName;
  3448. Args:=Args+' '+DestName;
  3449. ExecuteCommand(Defaults.Move,Args);
  3450. end
  3451. else
  3452. SysMoveFile(SourceName,DestName);
  3453. end;
  3454. procedure TBuildEngine.CmdRemoveDirs(List: TStrings);
  3455. Var
  3456. Args : String;
  3457. I : Integer;
  3458. begin
  3459. If (Defaults.RemoveDir<>'') then
  3460. begin
  3461. Args:=FileListToString(List,'');
  3462. ExecuteCommand(Defaults.RemoveDir,Args);
  3463. end
  3464. else
  3465. For I:=0 to List.Count-1 do
  3466. SysDeleteDirectory(List[i]);
  3467. end;
  3468. procedure TBuildEngine.CmdRemoveTrees(List: TStrings);
  3469. Var
  3470. Args : String;
  3471. I : Integer;
  3472. begin
  3473. If (Defaults.RemoveTree<>'') then
  3474. begin
  3475. Args:=FileListToString(List,'');
  3476. ExecuteCommand(Defaults.RemoveTree,Args);
  3477. end
  3478. else
  3479. For I:=0 to List.Count-1 do
  3480. SysDeleteTree(List[i]);
  3481. end;
  3482. Function TBuildEngine.FileNewer(const Src,Dest : String) : Boolean;
  3483. Var
  3484. DS,DD : Longint;
  3485. D1,D2 : TDateTime;
  3486. begin
  3487. DS:=FileAge(Src);
  3488. DD:=FileAge(Dest);
  3489. D1:=FileDateToDateTime(DS);
  3490. D2:=FileDateToDateTime(DD);
  3491. Log(vlDebug,SDbgComparingFileTimes,[Src,DateTimeToStr(D1),Dest,DateTimeToStr(D2)]);
  3492. Result:=D1>=D2;
  3493. If Result then
  3494. Log(vlInfo,SInfoSourceNewerDest,[Src,DateTimeToStr(D1),Dest,DateTimeToStr(D2)]);
  3495. end;
  3496. procedure TBuildEngine.ExecuteCommands(Commands: TCommands; At: TCommandAt);
  3497. Var
  3498. C : TCommand;
  3499. I : Integer;
  3500. Cmd,O : String;
  3501. E : Boolean;
  3502. begin
  3503. For I:=0 to Commands.Count-1 do
  3504. begin
  3505. C:=Commands.CommandItems[i];
  3506. if (C.At=At) then
  3507. begin
  3508. E:=True;
  3509. If (C.SourceFile<>'') and (C.DestFile<>'') then
  3510. E:=FileNewer(C.SourceFile,IncludeTrailingPathDelimiter(Dictionary.GetValue('OUTPUTDIR'))+C.DestFile);
  3511. If E then
  3512. begin
  3513. If Assigned(C.BeforeCommand) then
  3514. C.BeforeCommand(C);
  3515. O:=Substitute(C.CmdLineOptions,['SOURCE',C.SourceFile,'DEST',C.DestFile]);
  3516. Cmd:=C.Command;
  3517. If (ExtractFilePath(Cmd)='') then
  3518. Cmd:=ExeSearch(Cmd,GetEnvironmentvariable('PATH'));
  3519. ExecuteCommand(Cmd,O,nil,C.IgnoreResult);
  3520. If Assigned(C.AfterCommand) then
  3521. C.AfterCommand(C);
  3522. end;
  3523. end;
  3524. end;
  3525. end;
  3526. Procedure TBuildEngine.LogSearchPath(const ASearchPathName:string;Path:TConditionalStrings; ACPU:TCPU;AOS:TOS);
  3527. var
  3528. S : String;
  3529. I : Integer;
  3530. C : TConditionalString;
  3531. begin
  3532. S:='';
  3533. for i:=0 to Path.Count-1 do
  3534. begin
  3535. C:=Path[I];
  3536. if (ACPU in C.CPUs) and (AOS in C.OSes) then
  3537. begin
  3538. if S<>'' then
  3539. S:=S+PathSeparator;
  3540. S:=S+Dictionary.ReplaceStrings(C.Value)
  3541. end;
  3542. end;
  3543. if S<>'' then
  3544. Log(vlDebug,SDbgSearchPath,[ASearchPathName,S]);
  3545. end;
  3546. Function TBuildEngine.FindFileInPath(Path:TConditionalStrings; AFileName:String; var FoundPath:String;ACPU:TCPU;AOS:TOS):Boolean;
  3547. var
  3548. I : Integer;
  3549. C : TConditionalString;
  3550. begin
  3551. Result:=false;
  3552. for i:=0 to Path.Count-1 do
  3553. begin
  3554. C:=Path[I];
  3555. if (ACPU in C.CPUs) and (AOS in C.OSes) then
  3556. begin
  3557. FoundPath:=IncludeTrailingPathDelimiter(Dictionary.ReplaceStrings(C.Value));
  3558. if FileExists(FoundPath+AFileName) then
  3559. begin
  3560. result:=true;
  3561. exit;
  3562. end;
  3563. end;
  3564. end;
  3565. FoundPath:='';
  3566. end;
  3567. procedure TBuildEngine.GetDirectoriesFromFilelist(const AFileList, ADirectoryList: TStringList);
  3568. var
  3569. i: integer;
  3570. begin
  3571. ADirectoryList.Sorted:=true;
  3572. ADirectoryList.Duplicates:=dupIgnore;
  3573. for i := 0 to AFileList.Count-1 do
  3574. ADirectoryList.Add(ExtractFileDir(AFileList.Strings[i]));
  3575. end;
  3576. Procedure TBuildEngine.ResolveFileNames(APackage : TPackage; ACPU:TCPU;AOS:TOS;DoChangeDir:boolean=true);
  3577. procedure FindMainSource(T:TTarget);
  3578. var
  3579. SD,SF : String;
  3580. begin
  3581. LogSearchPath('package source',APackage.SourcePath,ACPU,AOS);
  3582. SD:=Dictionary.ReplaceStrings(T.Directory);
  3583. SF:=Dictionary.ReplaceStrings(T.SourceFileName);
  3584. if SD='' then
  3585. FindFileInPath(APackage.SourcePath,SF,SD,ACPU,AOS);
  3586. if SD<>'' then
  3587. SD:=IncludeTrailingPathDelimiter(SD);
  3588. T.FTargetSourceFileName:=SD+SF;
  3589. if FileExists(T.TargetSourceFileName) then
  3590. Log(vlDebug,SDbgResolvedSourceFile,[T.SourceFileName,T.TargetSourceFileName])
  3591. else
  3592. begin
  3593. Log(vlWarning,SWarnSourceFileNotFound,[T.SourceFileName,APackage.Name,MakeTargetString(ACPU,AOS)]);
  3594. T.FTargetSourceFileName:='';
  3595. end;
  3596. end;
  3597. procedure FindIncludeSources(T:TTarget);
  3598. var
  3599. SD,SF : String;
  3600. D : TDependency;
  3601. j : integer;
  3602. begin
  3603. LogSearchPath('target include',T.IncludePath,ACPU,AOS);
  3604. LogSearchPath('package include',APackage.IncludePath,ACPU,AOS);
  3605. for j:=0 to T.Dependencies.Count-1 do
  3606. begin
  3607. D:=T.Dependencies[j];
  3608. if (D.DependencyType=depInclude) then
  3609. begin
  3610. D.TargetFileName:='';
  3611. if (ACPU in D.CPUs) and (AOS in D.OSes) then
  3612. begin
  3613. if ExtractFilePath(D.Value)='' then
  3614. begin
  3615. SF:=Dictionary.ReplaceStrings(D.Value);
  3616. SD:='';
  3617. // first check the target specific path
  3618. if not FindFileInPath(T.IncludePath,SF,SD,ACPU,AOS) then
  3619. FindFileInPath(APackage.IncludePath,SF,SD,ACPU,AOS);
  3620. if SD<>'' then
  3621. SD:=IncludeTrailingPathDelimiter(SD);
  3622. D.TargetFileName:=SD+SF;
  3623. end
  3624. else
  3625. D.TargetFileName:=D.Value;
  3626. if FileExists(D.TargetFileName) then
  3627. Log(vlDebug,SDbgResolvedIncludeFile,[D.Value,D.TargetFileName])
  3628. else
  3629. begin
  3630. Log(vlWarning,SWarnIncludeFileNotFound,[D.Value, APackage.Name, MakeTargetString(ACPU,AOS)]);
  3631. D.TargetFileName:='';
  3632. end;
  3633. end;
  3634. end;
  3635. end;
  3636. end;
  3637. procedure FindExampleSource(T:TTarget);
  3638. var
  3639. SD,SF : String;
  3640. begin
  3641. LogSearchPath('package example',APackage.ExamplePath,ACPU,AOS);
  3642. SD:=Dictionary.ReplaceStrings(T.Directory);
  3643. SF:=Dictionary.ReplaceStrings(T.SourceFileName);
  3644. if SD='' then
  3645. FindFileInPath(APackage.ExamplePath,SF,SD,ACPU,AOS);
  3646. if SD<>'' then
  3647. SD:=IncludeTrailingPathDelimiter(SD);
  3648. T.FTargetSourceFileName:=SD+SF;
  3649. if FileExists(T.TargetSourceFileName) then
  3650. Log(vlDebug,SDbgResolvedSourceFile,[T.SourceFileName,T.TargetSourceFileName])
  3651. else
  3652. begin
  3653. Log(vlWarning,SWarnSourceFileNotFound,[T.SourceFileName, APackage.Name, MakeTargetString(ACPU,AOS)]);
  3654. T.FTargetSourceFileName:='';
  3655. end;
  3656. end;
  3657. var
  3658. T : TTarget;
  3659. i : Integer;
  3660. begin
  3661. if not((ACPU in APackage.CPUs) and (AOS in APackage.OSes)) then
  3662. exit;
  3663. try
  3664. if DoChangeDir and (APackage.Directory<>'') then
  3665. EnterDir(APackage.Directory);
  3666. Dictionary.AddVariable('CPU',CPUToString(ACPU));
  3667. Dictionary.AddVariable('OS',OSToString(AOS));
  3668. For I:=0 to APackage.Targets.Count-1 do
  3669. begin
  3670. T:=APackage.FTargets.TargetItems[I];
  3671. if (ACPU in T.CPUs) and (AOS in T.OSes) then
  3672. begin
  3673. // Debug information
  3674. Log(vlDebug,SDbgResolvingSourcesOfTarget,[T.Name,MakeTargetString(ACPU,AOS)]);
  3675. LogIndent;
  3676. case T.TargetType of
  3677. ttProgram,
  3678. ttUnit,
  3679. ttImplicitUnit :
  3680. begin
  3681. FindMainSource(T);
  3682. if T.Dependencies.Count>0 then
  3683. FindIncludeSources(T);
  3684. end;
  3685. ttExampleUnit,
  3686. ttExampleProgram :
  3687. begin
  3688. FindExampleSource(T);
  3689. end;
  3690. end;
  3691. LogUnIndent;
  3692. end;
  3693. end;
  3694. finally
  3695. If DoChangeDir and (APackage.Directory<>'') then
  3696. EnterDir('');
  3697. end;
  3698. end;
  3699. function TBuildEngine.GetUnitDir(APackage:TPackage):String;
  3700. begin
  3701. if APackage.UnitDir='' then
  3702. begin
  3703. // Retrieve Full directory name where to find the units.
  3704. // The search order is:
  3705. // - Package in this fpmake.pp
  3706. // - LocalUnitDir
  3707. // - GlobalUnitDir
  3708. if (APackage.State in [tsCompiled, tsNoCompile]) then
  3709. begin
  3710. APackage.UnitDir:=IncludeTrailingPathDelimiter(FStartDir)+IncludeTrailingPathDelimiter(APackage.Directory)+APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS);
  3711. end;
  3712. if (APackage.UnitDir='') and
  3713. (Defaults.LocalUnitDir<>'') then
  3714. begin
  3715. APackage.UnitDir:=IncludeTrailingPathDelimiter(Defaults.LocalUnitDir)+APackage.Name;
  3716. if not SysDirectoryExists(APackage.UnitDir) then
  3717. APackage.UnitDir:='';
  3718. end;
  3719. if APackage.UnitDir='' then
  3720. begin
  3721. APackage.UnitDir:=IncludeTrailingPathDelimiter(Defaults.GlobalUnitDir)+APackage.Name;
  3722. if not SysDirectoryExists(APackage.UnitDir) then
  3723. APackage.UnitDir:=DirNotFound;
  3724. end;
  3725. if (APackage.UnitDir<>DirNotFound) then
  3726. begin
  3727. if FileExists(IncludeTrailingPathDelimiter(APackage.UnitDir)+FPMakePPFile) then
  3728. begin
  3729. // The package is not installed, but the source-path is detected.
  3730. // It is an external package so it is impossible to compile it, so
  3731. // assume that it has been compiled earlier.
  3732. APackage.UnitDir := IncludeTrailingPathDelimiter(APackage.UnitDir) + APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS);
  3733. // If the unit-directory does not exist, you know for sure that
  3734. // the package is not compiled
  3735. if not SysDirectoryExists(APackage.UnitDir) then
  3736. APackage.UnitDir:=DirNotFound
  3737. else
  3738. APackage.FTargetState:=tsCompiled;
  3739. end
  3740. else if not (APackage.FTargetState in [tsCompiled, tsNoCompile]) then
  3741. begin
  3742. APackage.FTargetState:=tsInstalled;
  3743. end;
  3744. end;
  3745. end;
  3746. // Special error marker to prevent searches in case of error
  3747. if APackage.UnitDir=DirNotFound then
  3748. Result:=''
  3749. else
  3750. Result:=APackage.UnitDir;
  3751. end;
  3752. procedure TBuildEngine.AddDependencyPaths(L: TStrings; DependencyType: TDependencyType; ATarget: TTarget);
  3753. Var
  3754. I : Integer;
  3755. D : TDependency;
  3756. SD : String;
  3757. begin
  3758. For I:=0 to ATarget.Dependencies.Count-1 do
  3759. begin
  3760. D:=ATarget.Dependencies[i];
  3761. if (D.DependencyType=DependencyType) and
  3762. (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
  3763. begin
  3764. SD:=ExcludeTrailingPathDelimiter(ExtractFilePath(D.TargetFileName));
  3765. if SD<>'' then
  3766. L.Add(SD);
  3767. end;
  3768. end;
  3769. end;
  3770. procedure TBuildEngine.AddDependencyUnitPaths(L:TStrings;APackage: TPackage);
  3771. Var
  3772. I : Integer;
  3773. P : TPackage;
  3774. D : TDependency;
  3775. S : String;
  3776. begin
  3777. For I:=0 to APackage.Dependencies.Count-1 do
  3778. begin
  3779. D:=APackage.Dependencies[i];
  3780. if (D.DependencyType=depPackage) and
  3781. (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
  3782. begin
  3783. P:=TPackage(D.Target);
  3784. If Assigned(P) then
  3785. begin
  3786. // Already processed?
  3787. S:=GetUnitDir(P);
  3788. if L.IndexOf(S)=-1 then
  3789. begin
  3790. // Add this package and then dependencies
  3791. L.Add(S);
  3792. AddDependencyUnitPaths(L,P);
  3793. end;
  3794. end;
  3795. end;
  3796. end;
  3797. end;
  3798. Function TBuildEngine.GetCompilerCommand(APackage : TPackage; ATarget : TTarget; Env: TStrings) : String;
  3799. Var
  3800. L : TUnsortedDuplicatesStringList;
  3801. Args : TStringList;
  3802. s : string;
  3803. i : Integer;
  3804. begin
  3805. if ATarget.TargetSourceFileName = '' then
  3806. Error(SErrCouldNotCompile,[ATarget.Name, APackage.Name]);
  3807. Args:=TStringList.Create;
  3808. Args.Duplicates:=dupIgnore;
  3809. Result := '';
  3810. //compiler configuration
  3811. if Defaults.NoFPCCfg then
  3812. Args.Add('-n');
  3813. // Target OS
  3814. Args.Add('-T'+OSToString(Defaults.OS));
  3815. // Compile mode
  3816. If ATarget.Mode<>cmFPC then
  3817. Args.Add('-M'+ModeToString(ATarget.Mode))
  3818. else If Defaults.Mode<>cmFPC then
  3819. Args.Add('-M'+ModeToString(Defaults.Mode));
  3820. // Output file paths
  3821. If ATarget.TargetType in ProgramTargets then
  3822. Args.Add('-FE'+APackage.GetBinOutputDir(Defaults.CPU,Defaults.OS));
  3823. Args.Add('-FU'+APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS));
  3824. // Object Path
  3825. L:=TUnsortedDuplicatesStringList.Create;
  3826. L.Duplicates:=dupIgnore;
  3827. AddConditionalStrings(L,APackage.ObjectPath,Defaults.CPU,Defaults.OS);
  3828. AddConditionalStrings(L,ATarget.ObjectPath,Defaults.CPU,Defaults.OS);
  3829. for i:=0 to L.Count-1 do
  3830. Args.Add('-Fo'+L[i]);
  3831. FreeAndNil(L);
  3832. // Unit Dirs
  3833. L:=TUnsortedDuplicatesStringList.Create;
  3834. L.Duplicates:=dupIgnore;
  3835. AddDependencyUnitPaths(L,APackage);
  3836. AddDependencyPaths(L,depUnit,ATarget);
  3837. AddConditionalStrings(L,APackage.UnitPath,Defaults.CPU,Defaults.OS);
  3838. AddConditionalStrings(L,ATarget.UnitPath,Defaults.CPU,Defaults.OS);
  3839. for i:=0 to L.Count-1 do
  3840. Args.Add('-Fu'+L[i]);
  3841. FreeAndNil(L);
  3842. // Include Path
  3843. L:=TUnsortedDuplicatesStringList.Create;
  3844. L.Duplicates:=dupIgnore;
  3845. AddDependencyPaths(L,depInclude,ATarget);
  3846. AddConditionalStrings(L,APackage.IncludePath,Defaults.CPU,Defaults.OS);
  3847. AddConditionalStrings(L,ATarget.IncludePath,Defaults.CPU,Defaults.OS);
  3848. for i:=0 to L.Count-1 do
  3849. Args.Add('-Fi'+L[i]);
  3850. FreeAndNil(L);
  3851. // Custom Options
  3852. If (Defaults.HaveOptions) then
  3853. Args.AddStrings(Defaults.Options);
  3854. If (APackage.HaveOptions) then
  3855. Args.AddStrings(APackage.Options);
  3856. If (ATarget.HaveOptions) then
  3857. Args.AddStrings(ATarget.Options);
  3858. {$ifdef HAS_UNIT_PROCESS}
  3859. // Force the compiler-output to be easy parseable
  3860. if not Verbose then
  3861. args.Add('-viq');
  3862. {$endif}
  3863. // Add Filename to compile
  3864. Args.Add(ATarget.TargetSourceFileName);
  3865. // Convert to string
  3866. Result:='';
  3867. for i:=0 to Args.Count-1 do
  3868. Result:=Result+' '+maybequoted(Args[i]);
  3869. Delete(result,1,1);
  3870. if Defaults.UseEnvironment and assigned(Env) then
  3871. begin
  3872. env.Values['FPCEXTCMD'] := Result;
  3873. result := '!FPCEXTCMD';
  3874. // Make sure that this process' environment variables are passed to the
  3875. // compiler's environment
  3876. for i := 0 to GetEnvironmentVariableCount-1 do
  3877. env.Add(GetEnvironmentString(i));
  3878. end;
  3879. // Add Filename to compile
  3880. result := result + ' ' + ATarget.TargetSourceFileName;
  3881. Args.Free;
  3882. end;
  3883. Function TBuildEngine.GetCompiler : String;
  3884. Var
  3885. S : String;
  3886. begin
  3887. // Cache in FCompiler for speed.
  3888. If (FCompiler='') then
  3889. begin
  3890. FCompiler:=Defaults.Compiler;
  3891. If (ExtractFilePath(FCompiler)='') then
  3892. begin
  3893. S:=ExeSearch(FCompiler,GetEnvironmentVariable('PATH'));
  3894. If (S<>'') then
  3895. FCompiler:=S;
  3896. end;
  3897. end;
  3898. Result:=FCompiler;
  3899. end;
  3900. procedure TBuildEngine.CreateOutputDir(APackage: TPackage);
  3901. Var
  3902. D : String;
  3903. i: integer;
  3904. begin
  3905. //create a units directory
  3906. D:=APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS);
  3907. If not SysDirectoryExists(D) then
  3908. begin
  3909. Log(vlInfo,SInfoCreatingOutputDir,[D]);
  3910. CmdCreateDir(D);
  3911. end;
  3912. //also create a bin directory for programtargets
  3913. For i := 0 to Pred(APackage.Targets.Count) do
  3914. begin
  3915. if APackage.Targets.TargetItems[i].TargetType in ProgramTargets then
  3916. begin
  3917. D:=APackage.GetBinOutputDir(Defaults.CPU,Defaults.OS);
  3918. If not SysDirectoryExists(D) then
  3919. begin
  3920. Log(vlInfo,SInfoCreatingOutputDir,[D]);
  3921. CmdCreateDir(D);
  3922. end;
  3923. //do not continue loop, directory is made anyway
  3924. break;
  3925. end;
  3926. end;
  3927. end;
  3928. Function TBuildEngine.DependencyOK(ADependency : TDependency) : Boolean;
  3929. begin
  3930. Result:=(Defaults.CPU in ADependency.CPUs) and (Defaults.OS in ADependency.OSes);
  3931. end;
  3932. Function TBuildEngine.TargetOK(ATarget : TTarget) : Boolean;
  3933. begin
  3934. Result:=(Defaults.CPU in ATarget.CPUs) and (Defaults.OS in ATarget.OSes);
  3935. end;
  3936. Function TBuildEngine.PackageOK(APackage : TPackage) : Boolean;
  3937. begin
  3938. Result:=(Defaults.CPU in APackage.CPUs) and (Defaults.OS in APackage.OSes);
  3939. end;
  3940. procedure TBuildEngine.DoBeforeCompile(APackage: TPackage);
  3941. begin
  3942. ExecuteCommands(APackage.Commands,caBeforeCompile);
  3943. If Assigned(APackage.BeforeCompile) then
  3944. APackage.BeforeCompile(APackage);
  3945. If Assigned(APackage.BeforeCompileProc) then
  3946. APackage.BeforeCompileProc(APackage);
  3947. end;
  3948. procedure TBuildEngine.DoAfterCompile(APackage: TPackage);
  3949. begin
  3950. If Assigned(APackage.AfterCompile) then
  3951. APackage.AfterCompile(APackage);
  3952. If Assigned(APackage.AfterCompileProc) then
  3953. APackage.AfterCompileProc(APackage);
  3954. ExecuteCommands(APackage.Commands,caAfterCompile);
  3955. end;
  3956. Function TBuildEngine.NeedsCompile(APackage:TPackage;ATarget: TTarget): Boolean;
  3957. Var
  3958. I : Integer;
  3959. D : TDependency;
  3960. T : TTarget;
  3961. OD,OFN : String;
  3962. begin
  3963. Result:=False;
  3964. // Forced recompile?
  3965. if FForceCompile then
  3966. Result:=true;
  3967. // Check output file
  3968. if not result then
  3969. begin
  3970. if ATarget.TargetType in ProgramTargets then
  3971. OD:=APackage.GetBinOutputDir(Defaults.CPU,Defaults.OS)
  3972. else
  3973. OD:=APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS);
  3974. If (OD<>'') then
  3975. OD:=IncludeTrailingPathDelimiter(OD);
  3976. OFN:=OD+ATarget.GetOutPutFileName(Defaults.OS);
  3977. Result:=Not FileExists(OFN);
  3978. if Result then
  3979. Log(vlDebug,SDbgOutputNotYetAvailable,[OFN]);
  3980. end;
  3981. // Check main source
  3982. If not Result then
  3983. begin
  3984. if FileExists(ATarget.TargetSourceFileName) then
  3985. Result:=FileNewer(ATarget.TargetSourceFileName,OFN)
  3986. end;
  3987. // Check unit and include dependencies
  3988. If not Result then
  3989. begin
  3990. ResolveDependencies(ATarget.Dependencies,ATarget.Collection as TTargets);
  3991. I:=0;
  3992. for i:=0 to ATarget.Dependencies.Count-1 do
  3993. begin
  3994. D:=ATarget.Dependencies[i];
  3995. if (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
  3996. begin
  3997. case D.DependencyType of
  3998. depUnit :
  3999. begin
  4000. T:=TTarget(D.Target);
  4001. If (T=Nil) then
  4002. Error(SErrDepUnknownTarget,[D.Value, ATarget.Name, APackage.Name]);
  4003. // If a dependent package is compiled we always need to recompile
  4004. Log(vldebug, SDbgDependencyOnUnit, [ATarget.Name,T.Name]);
  4005. Result:=(T.State=tsCompiled);
  4006. if Result then
  4007. Log(vldebug, SDbgDependencyUnitRecompiled, [T.Name]);
  4008. end;
  4009. depInclude :
  4010. begin
  4011. if D.TargetFileName<>'' then
  4012. Result:=FileNewer(D.TargetFileName,OFN)
  4013. end;
  4014. depPackage :
  4015. begin
  4016. log(vlWarning,SWarnTargetDependsOnPackage,[ATarget.Name, APackage.Name, d.Value]);
  4017. end;
  4018. end;
  4019. if result then
  4020. break;
  4021. end;
  4022. end;
  4023. end;
  4024. if result then
  4025. Log(vlDebug,SDbgMustCompile,[ATarget.Name]);
  4026. end;
  4027. procedure TBuildEngine.Compile(APackage: TPackage; ATarget: TTarget);
  4028. Var
  4029. S : String;
  4030. Env : TStrings;
  4031. begin
  4032. Log(vlInfo,SInfoCompilingTarget,[ATarget.Name]);
  4033. LogIndent;
  4034. ExecuteCommands(ATarget.Commands,caBeforeCompile);
  4035. If Assigned(ATarget.BeforeCompile) then
  4036. ATarget.BeforeCompile(ATarget);
  4037. if APackage.BuildMode=bmBuildUnit then
  4038. begin
  4039. APackage.FBUTarget.Dependencies.AddUnit(ATarget.Name).FTargetFileName:=ATarget.TargetSourceFileName;
  4040. end
  4041. else
  4042. begin
  4043. if Defaults.UseEnvironment then
  4044. begin
  4045. Env := TStringList.Create;
  4046. try
  4047. S:=GetCompilerCommand(APackage,ATarget,Env);
  4048. ExecuteCommand(GetCompiler,S,Env);
  4049. finally
  4050. Env.Free;
  4051. end;
  4052. end
  4053. else
  4054. begin
  4055. S:=GetCompilerCommand(APackage,ATarget,Env);
  4056. ExecuteCommand(GetCompiler,S,nil);
  4057. end;
  4058. If Assigned(ATarget.AfterCompile) then
  4059. ATarget.AfterCompile(ATarget);
  4060. ExecuteCommands(ATarget.Commands,caAfterCompile);
  4061. end;
  4062. LogUnIndent;
  4063. end;
  4064. procedure TBuildEngine.CompileDependencies(APackage:TPackage; ATarget: TTarget);
  4065. Var
  4066. I : Integer;
  4067. T : TTarget;
  4068. D : TDependency;
  4069. begin
  4070. Log(vlDebug, Format(SDbgCompilingDependenciesOfTarget, [ATarget.Name]));
  4071. LogIndent;
  4072. For I:=0 to ATarget.Dependencies.Count-1 do
  4073. begin
  4074. D:=ATarget.Dependencies[i];
  4075. if (D.DependencyType=depPackage) then
  4076. log(vlWarning,SWarnTargetDependsOnPackage,[ATarget.Name, APackage.Name, d.Value])
  4077. else if (D.DependencyType=depUnit) and
  4078. (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
  4079. begin
  4080. T:=TTarget(D.Target);
  4081. if Assigned(T) and (T<>ATarget) then
  4082. begin
  4083. if TargetOK(T) then
  4084. begin
  4085. // We don't need to compile implicit units, they are only
  4086. // used for dependency checking
  4087. if (T.TargetType<>ttImplicitUnit) then
  4088. begin
  4089. case T.State of
  4090. tsNeutral :
  4091. MaybeCompile(APackage,T);
  4092. tsConsidering :
  4093. Log(vlWarning,SWarnCircularTargetDependency,[ATarget.Name,T.Name]);
  4094. end;
  4095. end;
  4096. end
  4097. else
  4098. Log(vlWarning, Format(SWarnDepUnitNotFound, [T.Name, MakeTargetString(Defaults.CPU,Defaults.OS)]));
  4099. end
  4100. else
  4101. Error(SErrDepUnknownTarget,[D.Value, ATarget.Name, APackage.Name]);
  4102. end;
  4103. end;
  4104. LogUnIndent;
  4105. end;
  4106. procedure TBuildEngine.MaybeCompile(APackage: TPackage; ATarget: TTarget);
  4107. begin
  4108. if ATarget.State<>tsNeutral then
  4109. Error(SErrInvalidState,[ATarget.Name]);
  4110. Log(vlDebug, Format(SDbgConsideringTarget, [ATarget.Name]));
  4111. LogIndent;
  4112. ATarget.FTargetState:=tsConsidering;
  4113. ResolveDependencies(ATarget.Dependencies,ATarget.Collection as TTargets);
  4114. CompileDependencies(APackage, ATarget);
  4115. if NeedsCompile(APackage, ATarget) then
  4116. begin
  4117. Compile(APackage,ATarget);
  4118. ATarget.FTargetState:=tsCompiled;
  4119. end
  4120. else
  4121. ATarget.FTargetState:=tsNoCompile;
  4122. LogUnIndent;
  4123. end;
  4124. function TBuildEngine.NeedsCompile(APackage: TPackage): Boolean;
  4125. Var
  4126. I : Integer;
  4127. P : TPackage;
  4128. D : TDependency;
  4129. begin
  4130. Result:=False;
  4131. // Forced recompile?
  4132. if FForceCompile then
  4133. Result:=true;
  4134. // Recompile because of Package Dependencies?
  4135. if not Result then
  4136. begin
  4137. I:=0;
  4138. For I:=0 to APackage.Dependencies.Count-1 do
  4139. begin
  4140. D:=APackage.Dependencies[i];
  4141. if (D.DependencyType=depPackage) and
  4142. (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
  4143. begin
  4144. P:=TPackage(D.Target);
  4145. if Assigned(P) then
  4146. begin
  4147. Result:=(P.State=tsCompiled);
  4148. if Result then
  4149. break;
  4150. end;
  4151. end;
  4152. end;
  4153. end;
  4154. // Recompile a Target of this package?
  4155. If Not Result then
  4156. begin
  4157. try
  4158. If (APackage.Directory<>'') then
  4159. EnterDir(APackage.Directory);
  4160. for i:=0 to APackage.Targets.Count-1 do
  4161. begin
  4162. Result:=NeedsCompile(APackage,APackage.Targets.TargetItems[i]);
  4163. if Result then
  4164. break;
  4165. end;
  4166. Finally
  4167. If (APackage.Directory<>'') then
  4168. EnterDir('');
  4169. end;
  4170. end;
  4171. if result then
  4172. Log(vlDebug,SDbgMustCompile,[APackage.Name]);
  4173. end;
  4174. function TBuildEngine.CheckExternalPackage(Const APackageName : String):TPackage;
  4175. var
  4176. S : String;
  4177. F : String;
  4178. I : Integer;
  4179. begin
  4180. // Already checked?
  4181. I:=ExternalPackages.IndexOfName(APackageName);
  4182. if I<>-1 then
  4183. begin
  4184. result:=ExternalPackages.PackageItems[I];
  4185. exit;
  4186. end;
  4187. // Create new external package
  4188. Result:=ExternalPackages.AddPackage(APackageName);
  4189. Result.FTargetState:=tsNotFound;
  4190. // Load unit config
  4191. S:=GetUnitDir(Result);
  4192. if S<>'' then
  4193. begin
  4194. Log(vldebug, SDbgExternalDependency, [APackageName,S]);
  4195. // Load unit config if it exists
  4196. F:=IncludeTrailingPathDelimiter(S)+UnitConfigFile;
  4197. if FileExists(F) then
  4198. begin
  4199. Log(vlDebug, Format(SDbgLoading, [F]));
  4200. Result.LoadUnitConfigFromFile(F);
  4201. end;
  4202. // Check recursive implicit dependencies
  4203. CompileDependencies(Result);
  4204. end
  4205. else
  4206. Error(SErrDependencyNotFound,[APackageName]);
  4207. end;
  4208. procedure TBuildEngine.CompileDependencies(APackage: TPackage);
  4209. Var
  4210. I : Integer;
  4211. P : TPackage;
  4212. D : TDependency;
  4213. begin
  4214. For I:=0 to APackage.Dependencies.Count-1 do
  4215. begin
  4216. D:=APackage.Dependencies[i];
  4217. if (D.DependencyType=depPackage) and
  4218. (Defaults.CPU in D.CPUs) and (Defaults.OS in D.OSes) then
  4219. begin
  4220. P:=TPackage(D.Target);
  4221. If Assigned(P) then
  4222. begin
  4223. if (Defaults.CPU in P.CPUs) and (Defaults.OS in P.OSes) then
  4224. begin
  4225. case P.State of
  4226. tsNeutral :
  4227. MaybeCompile(P);
  4228. tsConsidering :
  4229. Log(vlWarning,SWarnCircularPackageDependency,[APackage.Name,P.Name]);
  4230. end;
  4231. end
  4232. else
  4233. Log(vlWarning,SWarnDependOnOtherPlatformPackage,[APackage.Name, D.Value, MakeTargetString(Defaults.CPU, Defaults.OS)]);
  4234. end
  4235. else
  4236. begin
  4237. D.Target:=CheckExternalPackage(D.Value);
  4238. P:=TPackage(D.Target);
  4239. end;
  4240. if (D.RequireChecksum<>$ffffffff) and
  4241. (P.InstalledChecksum<>$ffffffff) and
  4242. (P.InstalledChecksum<>D.RequireChecksum) then
  4243. Log(vlDebug,SDbgPackageChecksumChanged,[P.Name]);
  4244. end;
  4245. end;
  4246. end;
  4247. procedure TBuildEngine.Compile(APackage: TPackage);
  4248. Var
  4249. T : TTarget;
  4250. I : Integer;
  4251. Cmd: string;
  4252. cmdOpts: string;
  4253. sFPDocFormat: string;
  4254. IFPDocFormat: TFPDocFormat;
  4255. d: integer;
  4256. UC: string;
  4257. dep: TDependency;
  4258. RegenerateUnitconfigFile: boolean;
  4259. BUName: string;
  4260. procedure CompileBuildUnit;
  4261. var
  4262. I: Integer;
  4263. T: TTarget;
  4264. L: TStrings;
  4265. F: Text;
  4266. begin
  4267. if (APackage.FBUTarget.Dependencies.Count>0) then
  4268. begin
  4269. Log(vldebug, Format(SDbgGenerateBuildUnit, [APackage.FBUTarget.Name]));
  4270. system.Assign(F,APackage.FBUTarget.FTargetSourceFileName);
  4271. Rewrite(F);
  4272. writeln(F,'unit ' + APackage.FBUTarget.Name +';');
  4273. writeln(F,'interface');
  4274. writeln(F,'uses');
  4275. for i := 0 to APackage.FBUTarget.Dependencies.Count-1 do
  4276. begin
  4277. if i<>0 then
  4278. write(F,',');
  4279. writeln(F,APackage.FBUTarget.Dependencies.Dependencies[i].Value);
  4280. end;
  4281. writeln(F,';');
  4282. writeln(F,'implementation');
  4283. writeln(F,'end.');
  4284. system.close(F);
  4285. APackage.FBuildMode:=bmOneByOne;
  4286. try
  4287. Compile(APackage,APackage.FBUTarget);
  4288. finally
  4289. // Delete temporary build-unit files
  4290. L := TStringList.Create;
  4291. try
  4292. APackage.FBUTarget.GetCleanFiles(L,IncludeTrailingPathDelimiter(APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS)),'',Defaults.CPU,Defaults.OS);
  4293. L.Add(APackage.FBUTarget.SourceFileName);
  4294. CmdDeleteFiles(L);
  4295. finally
  4296. L.Free;
  4297. end;
  4298. end;
  4299. end;
  4300. For I:=0 to APackage.Targets.Count-1 do
  4301. begin
  4302. T:=APackage.Targets.TargetItems[i];
  4303. if (T.TargetType = ttUnit) and (TargetOK(T)) then
  4304. begin
  4305. If Assigned(T.AfterCompile) then
  4306. T.AfterCompile(T);
  4307. ExecuteCommands(T.Commands,caAfterCompile);
  4308. end
  4309. end;
  4310. end;
  4311. procedure ProcessCompileTarget;
  4312. begin
  4313. if TargetOK(T) then
  4314. begin
  4315. if T.State=tsNeutral then
  4316. MaybeCompile(APackage,T);
  4317. // If a target is compiled, re-generate the UnitConfigFile
  4318. if T.FTargetState<>tsNoCompile then
  4319. RegenerateUnitconfigFile:= True;
  4320. end
  4321. else
  4322. begin
  4323. if not(Defaults.CPU in T.CPUs) then
  4324. Log(vldebug, Format(SDbgSkippingTargetWrongCPU, [T.Name, CPUsToString(T.CPUs)]));
  4325. if not(Defaults.OS in T.OSes) then
  4326. Log(vldebug, Format(SDbgSkippingTargetWrongOS, [T.Name, OSesToString(T.OSes)]));
  4327. end;
  4328. end;
  4329. begin
  4330. cmdOpts := '';
  4331. Log(vlInfo,SInfoCompilingPackage,[APackage.Name]);
  4332. case Defaults.BuildMode of
  4333. bmOneByOne: begin
  4334. if bmOneByOne in APackage.SupportBuildModes then
  4335. APackage.FBuildMode:=bmOneByOne
  4336. else
  4337. raise exception.create(SErrUnsupportedBuildmode);
  4338. end;
  4339. bmBuildUnit: begin
  4340. // When bmBuildUnit is supported by the package use a buildunit.
  4341. // Unless there is only one target and bmOneByOne is also supported
  4342. if (bmBuildUnit in APackage.SupportBuildModes) and
  4343. not ((APackage.Targets.Count=1) and (bmOneByOne in APackage.SupportBuildModes)) then
  4344. APackage.FBuildMode:=bmBuildUnit
  4345. else if bmOneByOne in APackage.SupportBuildModes then
  4346. begin
  4347. log(vlInfo,SInfoFallbackBuildmode);
  4348. APackage.FBuildMode:=bmOneByOne
  4349. end
  4350. else
  4351. raise exception.create(SErrUnsupportedBuildmode);
  4352. end;
  4353. end;
  4354. Try
  4355. If (APackage.Directory<>'') then
  4356. EnterDir(APackage.Directory);
  4357. CreateOutputDir(APackage);
  4358. Dictionary.AddVariable('UNITSOUTPUTDIR',APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS));
  4359. Dictionary.AddVariable('BINOUTPUTDIR',APackage.GetBinOutputDir(Defaults.CPU,Defaults.OS));
  4360. DoBeforeCompile(APackage);
  4361. RegenerateUnitconfigFile:=False;
  4362. if APackage.BuildMode=bmBuildUnit then
  4363. begin
  4364. APackage.FBUTargets := TTargets.Create(TTarget);
  4365. if Defaults.OS in AllLimit83fsOses then
  4366. BUName := 'BUnit.pp'
  4367. else
  4368. BUName := 'BuildUnit_'+StringReplace(APackage.Name,'-','_',[rfReplaceAll])+'.pp';
  4369. APackage.FBUTarget := APackage.FBUTargets.AddUnit(BUName);
  4370. APackage.FBUTarget.FTargetSourceFileName := APackage.FBUTarget.SourceFileName;
  4371. end;
  4372. For I:=0 to APackage.Targets.Count-1 do
  4373. begin
  4374. T:=APackage.Targets.TargetItems[i];
  4375. case T.TargetType of
  4376. ttUnit:
  4377. begin
  4378. ProcessCompileTarget;
  4379. end;
  4380. ttProgram:
  4381. begin // do nothing, are compiled later
  4382. end;
  4383. ttFPDoc:
  4384. begin
  4385. for d := 0 to T.Dependencies.Count - 1 do
  4386. begin
  4387. dep := TDependency(T.Dependencies[d]);
  4388. //add unit dependencies
  4389. if dep.DependencyType = depUnit then
  4390. cmdOpts := cmdOpts + ' --input=' + dep.Value;
  4391. end;
  4392. //check if a documentation target is given
  4393. cmdOpts := cmdOpts + ' --input=' + T.Directory + T.Name + T.Extension + ' --descr='+ T.XML;
  4394. end
  4395. else
  4396. log(vldebug, SDbgTargetIsNotAUnitOrProgram,[T.Name]);
  4397. end;
  4398. end;
  4399. if APackage.BuildMode=bmBuildUnit then
  4400. CompileBuildUnit;
  4401. FreeAndNil(APackage.FBUTarget);
  4402. For I:=0 to APackage.Targets.Count-1 do
  4403. begin
  4404. T:=APackage.Targets.TargetItems[i];
  4405. if T.TargetType=ttProgram then
  4406. begin
  4407. ProcessCompileTarget;
  4408. end;
  4409. end;
  4410. if RegenerateUnitconfigFile then
  4411. begin
  4412. UC:=IncludeTrailingPathDelimiter(APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS))+UnitConfigFile;
  4413. Log(vlInfo, Format(SDbgGenerating, [UC]));
  4414. APackage.SaveUnitConfigToFile(UC,Defaults.CPU,Defaults.OS);
  4415. end;
  4416. //compile documentation, because options were found
  4417. if cmdOpts <> '' then
  4418. begin
  4419. //append package name
  4420. cmdOpts := cmdOpts + ' --package=' + APackage.Name;
  4421. for IFPDocFormat:=Low(TFPDocFormat) to High(TFPDocFormat) do
  4422. begin
  4423. if IFPDocFormat in APackage.FPDocFormat then
  4424. begin
  4425. //prepend output format
  4426. case IFPDocFormat of
  4427. ffHtml: sFPDocFormat := '--format=html --output=' + Defaults.FPDocOutputDir;
  4428. ffHtm: sFPDocFormat := '--format=htm --output=' + Defaults.FPDocOutputDir;
  4429. ffXHtml: sFPDocFormat := '--format=xhtml --output=' + Defaults.FPDocOutputDir;
  4430. ffLaTex: sFPDocFormat := '--format=latex --output=' + Defaults.FPDocOutputDir + APackage.Name + '.tex';
  4431. ffXMLStruct: sFPDocFormat := '--format=xml-struct --output=' + Defaults.FPDocOutputDir;
  4432. ffChm: sFPDocFormat := '--format=chm --output=' + Defaults.FPDocOutputDir + APackage.Name + '.chm';
  4433. end;
  4434. //execute fpdoc
  4435. Cmd:=ExeSearch('fpdoc',GetEnvironmentvariable('PATH'));
  4436. if Cmd = '' then Cmd := 'fpdoc';
  4437. ExecuteProcess(Cmd, sFPDocFormat + cmdOpts);
  4438. end;
  4439. end;
  4440. end;
  4441. DoAfterCompile(APackage);
  4442. Finally
  4443. If (APackage.Directory<>'') then
  4444. EnterDir('');
  4445. end;
  4446. end;
  4447. procedure TBuildEngine.MaybeCompile(APackage: TPackage);
  4448. begin
  4449. if APackage.State in [tsCompiled, tsNoCompile] then
  4450. begin
  4451. Log(vlInfo,SInfoPackageAlreadyProcessed,[APackage.Name]);
  4452. Exit;
  4453. end;
  4454. if APackage.State<>tsNeutral then
  4455. Error(SErrInvalidState,[APackage.Name]);
  4456. Log(vlDebug,SDbgConsideringPackage,[APackage.Name]);
  4457. LogIndent;
  4458. APackage.FTargetState:=tsConsidering;
  4459. ResolveDependencies(APackage.Dependencies,(APackage.Collection as TPackages));
  4460. CompileDependencies(APackage);
  4461. ResolveFileNames(APackage,Defaults.CPU,Defaults.OS);
  4462. If NeedsCompile(APackage) then
  4463. begin
  4464. Compile(APackage);
  4465. APackage.FTargetState:=tsCompiled;
  4466. end
  4467. else
  4468. APackage.FTargetState:=tsNoCompile;
  4469. LogUnIndent;
  4470. end;
  4471. Function TBuildEngine.InstallPackageFiles(APAckage : TPackage; tt : TTargetType; Const Dest : String):Boolean;
  4472. Var
  4473. List : TStringList;
  4474. begin
  4475. Result:=False;
  4476. List:=TStringList.Create;
  4477. Try
  4478. APackage.GetInstallFiles(List,[tt],Defaults.CPU, Defaults.OS);
  4479. if (List.Count>0) then
  4480. begin
  4481. Result:=True;
  4482. CmdCopyFiles(List,Dest);
  4483. end;
  4484. Finally
  4485. List.Free;
  4486. end;
  4487. end;
  4488. procedure TBuildEngine.InstallUnitConfigFile(APAckage: TPackage; const Dest: String);
  4489. Var
  4490. List : TStringList;
  4491. begin
  4492. List:=TStringList.Create;
  4493. Try
  4494. List.add(IncludeTrailingPathDelimiter(APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS))+UnitConfigFile);
  4495. CmdCopyFiles(List,Dest);
  4496. Finally
  4497. List.Free;
  4498. end;
  4499. end;
  4500. function TBuildEngine.InstallPackageSourceFiles(APAckage : TPackage; stt : TSourceTypes; ttt : TTargetTypes; Const Dest : String): Boolean;
  4501. Var
  4502. List : TStringList;
  4503. begin
  4504. Result:=False;
  4505. List:=TStringList.Create;
  4506. Try
  4507. APackage.GetInstallSourceFiles(List,stt,ttt);
  4508. if (List.Count>0) then
  4509. begin
  4510. Result:=True;
  4511. CmdCopyFiles(List,Dest);
  4512. end;
  4513. Finally
  4514. List.Free;
  4515. end;
  4516. end;
  4517. procedure TBuildEngine.DoBeforeInstall(APackage: TPackage);
  4518. begin
  4519. ExecuteCommands(APackage.Commands,caBeforeInstall);
  4520. If Assigned(APackage.BeforeInstall) then
  4521. APackage.BeforeInstall(APackage);
  4522. If Assigned(APackage.BeforeInstallProc) then
  4523. APackage.BeforeInstallProc(APackage);
  4524. end;
  4525. procedure TBuildEngine.DoAfterInstall(APackage: TPackage);
  4526. begin
  4527. If Assigned(APackage.AfterInstall) then
  4528. APackage.AfterInstall(APackage);
  4529. If Assigned(APackage.AfterInstallProc) then
  4530. APackage.AfterInstallProc(APackage);
  4531. ExecuteCommands(APackage.Commands,caAfterInstall);
  4532. end;
  4533. procedure TBuildEngine.Install(APackage: TPackage);
  4534. Var
  4535. UC,D : String;
  4536. B : Boolean;
  4537. begin
  4538. If (Apackage.State<>tsCompiled) then
  4539. MaybeCompile(APackage);
  4540. try
  4541. Log(vlInfo,SInfoInstallingPackage,[APackage.Name]);
  4542. If (APackage.Directory<>'') then
  4543. EnterDir(APackage.Directory);
  4544. DoBeforeInstall(APackage);
  4545. // units
  4546. B:=false;
  4547. Dictionary.AddVariable('PackageName',APackage.Name);
  4548. D:=IncludeTrailingPathDelimiter(Defaults.UnitInstallDir);
  4549. if InstallPackageFiles(APAckage,ttUnit,D) then
  4550. B:=true;
  4551. if InstallPackageFiles(APAckage,ttImplicitUnit,D) then
  4552. B:=true;
  4553. // By default do not install the examples. Maybe add an option for this later
  4554. //if InstallPackageFiles(APAckage,ttExampleUnit,D) then
  4555. // B:=true;
  4556. // Unit (dependency) configuration if there were units installed
  4557. if B then
  4558. InstallUnitConfigFile(APackage,D);
  4559. // Programs
  4560. D:=IncludeTrailingPathDelimiter(Defaults.BinInstallDir);
  4561. InstallPackageFiles(APAckage,ttProgram,D);
  4562. //InstallPackageFiles(APAckage,ttExampleProgram,D);
  4563. // Documentation
  4564. D:=IncludeTrailingPathDelimiter(Defaults.DocInstallDir)+'fpc-'+APackage.FileName+PathDelim;
  4565. InstallPackageSourceFiles(APackage,[stDoc],[],D);
  4566. // Examples
  4567. if Defaults.InstallExamples then
  4568. begin
  4569. D:=IncludeTrailingPathDelimiter(Defaults.ExamplesInstallDir)+'fpc-'+APackage.FileName+PathDelim+'examples'+PathDelim;
  4570. InstallPackageSourceFiles(APackage,[stExample],[ttExampleProgram,ttExampleUnit],D);
  4571. end;
  4572. // Done.
  4573. APackage.FTargetState:=tsInstalled;
  4574. DoAfterInstall(APackage);
  4575. Finally
  4576. If (APackage.Directory<>'') then
  4577. EnterDir('');
  4578. end;
  4579. end;
  4580. procedure TBuildEngine.DoBeforeArchive(APackage: TPackage);
  4581. begin
  4582. ExecuteCommands(APackage.Commands,caBeforeArchive);
  4583. If Assigned(APackage.BeforeArchive) then
  4584. APackage.BeforeArchive(APackage);
  4585. If Assigned(APackage.BeforeArchiveProc) then
  4586. APackage.BeforeArchiveProc(APackage);
  4587. end;
  4588. procedure TBuildEngine.DoAfterArchive(APackage: TPackage);
  4589. begin
  4590. If Assigned(APackage.AfterArchive) then
  4591. APackage.AfterArchive(APackage);
  4592. If Assigned(APackage.AfterArchiveProc) then
  4593. APackage.AfterArchiveProc(APackage);
  4594. ExecuteCommands(APackage.Commands,caAfterArchive);
  4595. end;
  4596. procedure TBuildEngine.Archive(APackage: TPackage);
  4597. Var
  4598. L : TStringList;
  4599. A : String;
  4600. i: integer;
  4601. ICPU : TCPU;
  4602. IOS : TOS;
  4603. begin
  4604. A:=FStartDir+ APackage.FileName + ZipExt;
  4605. Log(vlInfo,SInfoArchivingPackage,[APackage.Name,A]);
  4606. try
  4607. If (APackage.Directory<>'') then
  4608. EnterDir(APackage.Directory);
  4609. DoBeforeArchive(Apackage);
  4610. L:=TStringList.Create;
  4611. L.Sorted:=true;
  4612. L.Duplicates:=dupIgnore;
  4613. Try
  4614. // Add fpmake.pp & manifest.xml always
  4615. L.Add(FPMakePPFile);
  4616. L.Add(ManifestFile);
  4617. //get all files from all targets
  4618. for ICPU:=Low(TCPU) to high(TCPU) do
  4619. for IOS:=Low(TOS) to high(TOS) do
  4620. if OSCPUSupported[IOS,ICPU] then
  4621. begin
  4622. ResolveFileNames(APackage,ICPU,IOS,false);
  4623. APackage.GetArchiveFiles(L, ICPU, IOS);
  4624. end;
  4625. //from sources
  4626. APackage.GetArchiveSourceFiles(L);
  4627. //show all files
  4628. for i := 0 to L.Count-1 do
  4629. Log(vlDebug, Format(SDbgArchivingFile, [L[i]]));
  4630. {$ifdef HAS_UNIT_ZIPPER}
  4631. if not Assigned(ArchiveFilesProc) then
  4632. begin
  4633. FZipFile := TZipper.Create;
  4634. FZipFile.ZipFiles(A, L);
  4635. end
  4636. else
  4637. {$endif HAS_UNIT_ZIPPER}
  4638. CmdArchiveFiles(L,A);
  4639. Finally
  4640. L.Free;
  4641. {$ifdef HAS_UNIT_ZIPPER}
  4642. if not Assigned(ArchiveFilesProc) then
  4643. FreeAndNil(FZipFile);
  4644. {$endif HAS_UNIT_ZIPPER}
  4645. end;
  4646. DoAfterArchive(Apackage);
  4647. Finally
  4648. If (APackage.Directory<>'') then
  4649. EnterDir('');
  4650. end;
  4651. end;
  4652. procedure TBuildEngine.DoBeforeClean(APackage: TPackage);
  4653. begin
  4654. ExecuteCommands(APackage.Commands,caBeforeClean);
  4655. If Assigned(APackage.BeforeClean) then
  4656. APackage.BeforeClean(APackage);
  4657. If Assigned(APackage.BeforeCleanProc) then
  4658. APackage.BeforeCleanProc(APackage);
  4659. end;
  4660. procedure TBuildEngine.DoAfterClean(APackage: TPackage);
  4661. begin
  4662. If Assigned(APackage.AfterClean) then
  4663. APackage.AfterClean(APackage);
  4664. If Assigned(APackage.AfterInstallProc) then
  4665. APackage.AfterCleanProc(APackage);
  4666. ExecuteCommands(APackage.Commands,caAfterClean);
  4667. end;
  4668. procedure TBuildEngine.Clean(APackage: TPackage; AllTargets: boolean);
  4669. var
  4670. // ACPU: TCpu;
  4671. // AOS: TOS;
  4672. DirectoryList : TStringList;
  4673. begin
  4674. Log(vlInfo,SInfoCleaningPackage,[APackage.Name]);
  4675. try
  4676. If (APackage.Directory<>'') then
  4677. EnterDir(APackage.Directory);
  4678. DoBeforeClean(Apackage);
  4679. if AllTargets then
  4680. begin
  4681. // Remove the unit-directory completely. This is safer in case of files
  4682. // being renamed and such. See also bug 19655
  4683. DirectoryList := TStringList.Create;
  4684. try
  4685. DirectoryList.Add(ExtractFileDir(APackage.GetUnitsOutputDir(Defaults.CPU,Defaults.OS)));
  4686. CmdRemoveTrees(DirectoryList);
  4687. finally
  4688. DirectoryList.Free;
  4689. end;
  4690. { for ACPU:=low(TCpu) to high(TCpu) do
  4691. for AOS:=low(TOS) to high(TOS) do
  4692. begin
  4693. if FileExists(APackage.GetUnitsOutputDir(ACPU,AOS)) or
  4694. FileExists(APackage.GetBinOutputDir(ACPU,AOS)) then
  4695. Clean(APackage,ACPU,AOS);
  4696. end;}
  4697. end
  4698. else
  4699. Clean(APackage, Defaults.CPU, Defaults.OS);
  4700. DoAfterClean(Apackage);
  4701. Finally
  4702. If (APackage.Directory<>'') then
  4703. EnterDir('');
  4704. end;
  4705. end;
  4706. procedure TBuildEngine.Clean(APackage: TPackage; ACPU: TCPU; AOS: TOS);
  4707. Var
  4708. List : TStringList;
  4709. DirectoryList : TStringList;
  4710. begin
  4711. List:=TStringList.Create;
  4712. try
  4713. List.Add(APackage.GetUnitsOutputDir(ACPU,AOS) + PathDelim + UnitConfigFile);
  4714. APackage.GetCleanFiles(List,ACPU,AOS);
  4715. if (List.Count>0) then
  4716. begin
  4717. CmdDeleteFiles(List);
  4718. DirectoryList := TStringList.Create;
  4719. try
  4720. GetDirectoriesFromFilelist(List,DirectoryList);
  4721. CmdRemoveDirs(DirectoryList);
  4722. DirectoryList.Clear;
  4723. if DirectoryExists(APackage.GetBinOutputDir(ACPU,AOS)) then
  4724. DirectoryList.Add(APackage.GetBinOutputDir(ACPU,AOS));
  4725. if DirectoryExists(APackage.GetUnitsOutputDir(ACPU,AOS)) then
  4726. DirectoryList.Add(APackage.GetUnitsOutputDir(ACPU,AOS));
  4727. CmdRemoveDirs(DirectoryList);
  4728. DirectoryList.Clear;
  4729. if DirectoryExists(ExtractFileDir(APackage.GetBinOutputDir(ACPU,AOS))) then
  4730. DirectoryList.Add(ExtractFileDir(APackage.GetBinOutputDir(ACPU,AOS)));
  4731. if DirectoryExists(ExtractFileDir(APackage.GetUnitsOutputDir(ACPU,AOS))) then
  4732. DirectoryList.Add(ExtractFileDir(APackage.GetUnitsOutputDir(ACPU,AOS)));
  4733. CmdRemoveDirs(DirectoryList);
  4734. finally
  4735. DirectoryList.Free;
  4736. end;
  4737. end;
  4738. Finally
  4739. List.Free;
  4740. end;
  4741. end;
  4742. Procedure TBuildEngine.Manifest(APackage : TPackage);
  4743. Var
  4744. L : TStrings;
  4745. PD,
  4746. MF : String;
  4747. begin
  4748. L:=TStringList.Create;
  4749. Try
  4750. Log(vlInfo, Format(SInfoManifestPackage,[APackage.Name]));
  4751. PD:=APackage.Directory;
  4752. if PD<>'' then
  4753. PD:=IncludeTrailingPathDelimiter(PD);
  4754. MF:=PD+ManifestFile;
  4755. Log(vlDebug, Format(SDbgGenerating, [MF]));
  4756. L.Add('<?xml version="1.0"?>');
  4757. L.Add('<packages>');
  4758. APackage.GetManifest(L);
  4759. L.Add('</packages>');
  4760. L.SaveToFile(MF);
  4761. Finally
  4762. L.Free;
  4763. end;
  4764. end;
  4765. procedure TBuildEngine.Compile(Packages: TPackages);
  4766. Var
  4767. I : Integer;
  4768. P : TPackage;
  4769. begin
  4770. If Assigned(BeforeCompile) then
  4771. BeforeCompile(Self);
  4772. For I:=0 to Packages.Count-1 do
  4773. begin
  4774. P:=Packages.PackageItems[i];
  4775. log(vlWarning,SWarnStartBuildingPackage,[P.Name, Defaults.Target]);
  4776. If PackageOK(P) then
  4777. MaybeCompile(P);
  4778. //show compile progress
  4779. log(vlWarning,SWarnBuildingPackagecomplete,[(I + 1)/Packages.Count * 100, P.Name]);
  4780. end;
  4781. If Assigned(AfterCompile) then
  4782. AfterCompile(Self);
  4783. end;
  4784. procedure TBuildEngine.Install(Packages: TPackages);
  4785. Var
  4786. I : Integer;
  4787. P : TPackage;
  4788. begin
  4789. If Assigned(BeforeInstall) then
  4790. BeforeInstall(Self);
  4791. For I:=0 to Packages.Count-1 do
  4792. begin
  4793. P:=Packages.PackageItems[i];
  4794. If PackageOK(P) then
  4795. Install(P);
  4796. log(vlWarning, SWarnInstallationPackagecomplete, [P.Name, Defaults.Target]);
  4797. end;
  4798. If Assigned(AfterInstall) then
  4799. AfterInstall(Self);
  4800. end;
  4801. procedure TBuildEngine.Archive(Packages: TPackages);
  4802. Var
  4803. I : Integer;
  4804. P : TPackage;
  4805. begin
  4806. If Assigned(BeforeArchive) then
  4807. BeforeArchive(Self);
  4808. Log(vlDebug, SDbgBuildEngineArchiving);
  4809. For I:=0 to Packages.Count-1 do
  4810. begin
  4811. P:=Packages.PackageItems[i];
  4812. Archive(P);
  4813. end;
  4814. If Assigned(AfterArchive) then
  4815. AfterArchive(Self);
  4816. end;
  4817. procedure TBuildEngine.Manifest(Packages: TPackages);
  4818. Var
  4819. I : Integer;
  4820. P : TPackage;
  4821. begin
  4822. If Assigned(BeforeManifest) then
  4823. BeforeManifest(Self);
  4824. Log(vlDebug, SDbgBuildEngineGenerateManifests);
  4825. For I:=0 to Packages.Count-1 do
  4826. begin
  4827. P:=Packages.PackageItems[i];
  4828. Manifest(P);
  4829. end;
  4830. If Assigned(AfterManifest) then
  4831. AfterManifest(Self);
  4832. end;
  4833. procedure TBuildEngine.Clean(Packages: TPackages; AllTargets: boolean);
  4834. Var
  4835. I : Integer;
  4836. P : TPackage;
  4837. begin
  4838. If Assigned(BeforeClean) then
  4839. BeforeClean(Self);
  4840. Log(vldebug, SDbgBuildEngineCleaning);
  4841. For I:=0 to Packages.Count-1 do
  4842. begin
  4843. P:=Packages.PackageItems[i];
  4844. If AllTargets or PackageOK(P) then
  4845. Clean(P, AllTargets);
  4846. log(vlWarning, SWarnCleanPackagecomplete, [P.Name]);
  4847. end;
  4848. If Assigned(AfterClean) then
  4849. AfterClean(Self);
  4850. end;
  4851. {****************************************************************************
  4852. TFPVersion
  4853. ****************************************************************************}
  4854. function TFPVersion.GetAsString: String;
  4855. begin
  4856. if Empty then
  4857. Result:='<none>'
  4858. else
  4859. begin
  4860. Result := '';
  4861. if Major <> -1 then
  4862. Result := Result + IntToStr(Major);
  4863. if Minor <> -1 then
  4864. Result := Result + '.' + IntToStr(Minor);
  4865. if Micro <> -1 then
  4866. Result := Result + '.' + IntToStr(Micro);
  4867. if Build <> -1 then
  4868. Result := Result + '-' + IntToStr(Build);
  4869. end;
  4870. end;
  4871. function TFPVersion.GetEmpty: Boolean;
  4872. begin
  4873. Result:=(Major=0) and (Minor=0) and (Micro=0) and (Build=0);
  4874. end;
  4875. procedure TFPVersion.SetAsString(const AValue: String);
  4876. Function NextDigit(sep : Char; var V : string) : integer;
  4877. Var
  4878. P : Integer;
  4879. begin
  4880. P:=Pos(Sep,V);
  4881. If (P=0) then
  4882. P:=Length(V)+1;
  4883. Result:=StrToIntDef(Copy(V,1,P-1),-1);
  4884. If Result<>-1 then
  4885. Delete(V,1,P);
  4886. end;
  4887. Var
  4888. V : String;
  4889. begin
  4890. Clear;
  4891. // Special support for empty version string
  4892. if (AValue='') or (AValue='<none>') then
  4893. exit;
  4894. V:=AValue;
  4895. Major:=NextDigit('.',V);
  4896. Minor:=NextDigit('.',V);
  4897. Micro:=NextDigit('-',V);
  4898. Build:=NextDigit(#0,V);
  4899. end;
  4900. procedure TFPVersion.Clear;
  4901. begin
  4902. Micro:=-1;
  4903. Major:=-1;
  4904. Minor:=-1;
  4905. Build:=-1;
  4906. end;
  4907. procedure TFPVersion.Assign(Source: TPersistent);
  4908. Var
  4909. V : TFPVersion;
  4910. begin
  4911. if Source is TFPVersion then
  4912. begin
  4913. V:=Source as TFPVersion;
  4914. Major:=V.Major;
  4915. Minor:=V.Minor;
  4916. Micro:=V.Micro;
  4917. Build:=V.Build;
  4918. end
  4919. else
  4920. inherited Assign(Source);
  4921. end;
  4922. function TFPVersion.CompareVersion(AVersion: TFPVersion): Integer;
  4923. begin
  4924. Result:=Major-AVersion.Major;
  4925. If (Result=0) then
  4926. begin
  4927. Result:=Minor-AVersion.Minor;
  4928. if (Result=0) then
  4929. begin
  4930. Result:=Micro-AVersion.Micro;
  4931. If (Result=0) then
  4932. Result:=Build-AVersion.Build;
  4933. end;
  4934. end;
  4935. end;
  4936. function TFPVersion.SameVersion(AVersion: TFPVersion): Boolean;
  4937. begin
  4938. Result:=CompareVersion(AVersion)=0;
  4939. end;
  4940. {****************************************************************************
  4941. TTarget
  4942. ****************************************************************************}
  4943. constructor TTarget.Create(ACollection: TCollection);
  4944. begin
  4945. inherited Create(ACollection);
  4946. FInstall:=True;
  4947. FCPUs:=AllCPUs;
  4948. FOSes:=AllOSes;
  4949. FUnitPath:=TConditionalStrings.Create(TConditionalString);
  4950. FIncludePath:=TConditionalStrings.Create(TConditionalString);
  4951. FObjectPath:=TConditionalStrings.Create(TConditionalString);
  4952. FDependencies:=TDependencies.Create(TDependency);
  4953. FCommands:=TCOmmands.Create(TCommand);
  4954. end;
  4955. destructor TTarget.Destroy;
  4956. begin
  4957. FreeAndNil(FUnitPath);
  4958. FreeAndNil(FObjectPath);
  4959. FreeAndNil(FIncludePath);
  4960. FreeAndNil(FDependencies);
  4961. FreeAndNil(FCommands);
  4962. FreeAndNil(Foptions);
  4963. inherited Destroy;
  4964. end;
  4965. function TTarget.GetOptions: TStrings;
  4966. begin
  4967. If Foptions=Nil then
  4968. FOptions:=TStringList.Create;
  4969. Result:=FOptions;
  4970. end;
  4971. function TTarget.GetUnitLibFileName: String;
  4972. begin
  4973. Result:='libp'+Name+LibExt;
  4974. end;
  4975. procedure TTarget.SetOptions(const AValue: TStrings);
  4976. begin
  4977. If (AValue=Nil) or (AValue.Count=0) then
  4978. FreeAndNil(FOptions)
  4979. else
  4980. Options.Assign(AValue);
  4981. end;
  4982. function TTarget.GetSourceFileName: String;
  4983. begin
  4984. Result:=Name+FExtension;
  4985. end;
  4986. function TTarget.GetUnitFileName: String;
  4987. begin
  4988. Result:=Name+UnitExt;
  4989. end;
  4990. function TTarget.GetObjectFileName: String;
  4991. begin
  4992. Result:=Name+ObjExt;
  4993. end;
  4994. function TTarget.GetRSTFileName: String;
  4995. begin
  4996. Result:=Name+RSText;
  4997. end;
  4998. function TTarget.GetProgramFileName(AOS : TOS): String;
  4999. begin
  5000. if AOS in [Go32v2,Win32,Win64,OS2] then
  5001. Result:=Name+ExeExt
  5002. else
  5003. Result:=Name;
  5004. end;
  5005. function TTarget.GetOutputFileName(AOs: TOS): String;
  5006. begin
  5007. if TargetType in UnitTargets then
  5008. Result:=GetUnitFileName
  5009. else
  5010. Result:=GetProgramFileName(AOs);
  5011. end;
  5012. function TTarget.HaveOptions: Boolean;
  5013. begin
  5014. Result:=(FOptions<>Nil);
  5015. end;
  5016. procedure TTarget.SetName(const AValue: String);
  5017. Var
  5018. D,N,E : String;
  5019. begin
  5020. N:=FixPath(AValue);
  5021. D:=ExtractFilePath(N);
  5022. E:=ExtractFileExt(N);
  5023. N:=ExtractFileName(N);
  5024. inherited SetName(Copy(N,1,Length(N)-Length(E)));
  5025. FExtension:=E;
  5026. FDirectory:=D;
  5027. end;
  5028. procedure TTarget.SetXML(const AValue: string);
  5029. begin
  5030. FXML:=FixPath(AValue);
  5031. end;
  5032. procedure TTarget.GetCleanFiles(List: TStrings; const APrefixU, APrefixB : String; ACPU: TCPU; AOS : TOS);
  5033. begin
  5034. If not(ACPU in CPUs) or not(AOS in OSes) then
  5035. exit;
  5036. List.Add(APrefixU + ObjectFileName);
  5037. If (TargetType in [ttUnit,ttImplicitUnit,ttExampleUnit, ttCleanOnlyUnit]) then
  5038. begin
  5039. List.Add(APrefixU + UnitFileName);
  5040. if (AOS in AllSmartLinkLibraryOSes) and FileExists(APrefixU + UnitLibFileName) then
  5041. List.Add(APrefixU + UnitLibFileName);
  5042. end
  5043. else If (TargetType in [ttProgram,ttExampleProgram]) then
  5044. List.Add(APrefixB + GetProgramFileName(AOS));
  5045. If ResourceStrings then
  5046. List.Add(APrefixU + RSTFileName);
  5047. // Maybe add later ? AddConditionalStrings(List,CleanFiles);
  5048. end;
  5049. procedure TTarget.GetInstallFiles(List: TStrings; const APrefixU, APrefixB: String; ACPU: TCPU; AOS : TOS);
  5050. begin
  5051. If not(ACPU in CPUs) or not(AOS in OSes) then
  5052. exit;
  5053. If Not (TargetType in [ttProgram,ttExampleProgram]) then
  5054. List.Add(APrefixU + ObjectFileName);
  5055. If (TargetType in [ttUnit,ttImplicitUnit,ttExampleUnit]) then
  5056. begin
  5057. List.Add(APrefixU + UnitFileName);
  5058. if (AOS in AllSmartLinkLibraryOSes) and FileExists(APrefixU + UnitLibFileName) then
  5059. List.Add(APrefixU + UnitLibFileName);
  5060. end
  5061. else If (TargetType in [ttProgram,ttExampleProgram]) then
  5062. List.Add(APrefixB + GetProgramFileName(AOS));
  5063. If ResourceStrings then
  5064. List.Add(APrefixU + RSTFileName);
  5065. // Maybe add later ? AddConditionalStrings(List,InstallFiles);
  5066. end;
  5067. procedure TTarget.GetArchiveFiles(List: TStrings; ACPU: TCPU; AOS : TOS);
  5068. var
  5069. i : integer;
  5070. D : TDependency;
  5071. begin
  5072. If not(ACPU in CPUs) or not(AOS in OSes) then
  5073. exit;
  5074. // Main source
  5075. if TargetSourceFileName<>'' then
  5076. List.Add(TargetSourceFileName);
  5077. // Includes
  5078. for i:=0 to Dependencies.Count-1 do
  5079. begin
  5080. D:=Dependencies[i];
  5081. if (D.DependencyType=depInclude) and
  5082. (D.TargetFileName<>'') then
  5083. List.Add(D.TargetFileName);
  5084. end;
  5085. // FPDoc files
  5086. if XML <> '' then
  5087. begin
  5088. List.Add(Directory + Name + Extension);
  5089. List.Add(XML);
  5090. end;
  5091. end;
  5092. {****************************************************************************
  5093. TSource
  5094. ****************************************************************************}
  5095. function TSource.GetInstallSourcePath: string;
  5096. begin
  5097. if FInstallSourcePath<>'' then
  5098. result := FInstallSourcePath
  5099. else if SourceType=stExample then
  5100. result := 'examples'
  5101. else
  5102. result := '';
  5103. end;
  5104. constructor TSource.Create(ACollection: TCollection);
  5105. begin
  5106. inherited Create(ACollection);
  5107. end;
  5108. destructor TSource.Destroy;
  5109. begin
  5110. inherited Destroy;
  5111. end;
  5112. procedure TSource.GetInstallFiles(List: TStrings);
  5113. begin
  5114. if InstallSourcePath<>'' then
  5115. list.Values[name] := (IncludeTrailingPathDelimiter(InstallSourcePath)+ExtractFileName(Name))
  5116. else
  5117. list.add(Name);
  5118. end;
  5119. {****************************************************************************
  5120. TCommands
  5121. ****************************************************************************}
  5122. function TCommands.GetCommand(const Dest : String): TCommand;
  5123. begin
  5124. Result:=TCommand(ItemByName(Dest));
  5125. end;
  5126. function TCommands.GetCommandItem(Index : Integer): TCommand;
  5127. begin
  5128. Result:=TCommand(Items[Index]);
  5129. end;
  5130. procedure TCommands.SetCommandItem(Index : Integer; const AValue: TCommand);
  5131. begin
  5132. Items[Index]:=AValue;
  5133. end;
  5134. Function TCommands.AddCommand(const Cmd: String) : TCommand;
  5135. begin
  5136. Result:=AddCommand(fdefaultAt,Cmd,'','','');
  5137. end;
  5138. function TCommands.AddCommand(const Cmd, Options: String): TCommand;
  5139. begin
  5140. Result:=AddCommand(fdefaultAt,Cmd,Options,'','');
  5141. end;
  5142. function TCommands.AddCommand(const Cmd, Options, Dest, Source: String ): TCommand;
  5143. begin
  5144. Result:=AddCommand(fdefaultAt,Cmd,options,Dest,Source);
  5145. end;
  5146. Function TCommands.AddCommand(At: TCommandAt; const Cmd: String) : TCommand;
  5147. begin
  5148. Result:=AddCommand(At,Cmd,'','','');
  5149. end;
  5150. function TCommands.AddCommand(At: TCommandAt; const Cmd, Options: String ): TCommand;
  5151. begin
  5152. Result:=AddCommand(At,Cmd,Options,'','');
  5153. end;
  5154. function TCommands.AddCommand(At: TCommandAt; const Cmd, Options, Dest, Source: String): TCommand;
  5155. begin
  5156. Result:=Add as TCommand;
  5157. Result.Command:=Cmd;
  5158. If (Options<>'') then
  5159. Result.ParseOptions(Options);
  5160. Result.At:=At;
  5161. Result.SourceFile:=Source;
  5162. Result.DestFile:=Dest;
  5163. end;
  5164. {****************************************************************************
  5165. TConditionalString
  5166. ****************************************************************************}
  5167. Constructor TConditionalString.Create;
  5168. begin
  5169. inherited Create;
  5170. end;
  5171. {****************************************************************************
  5172. TConditionalStrings
  5173. ****************************************************************************}
  5174. Constructor TConditionalStrings.Create(AClass:TConditionalStringClass);
  5175. begin
  5176. inherited Create;
  5177. FCSClass:=AClass;
  5178. end;
  5179. function TConditionalStrings.GetConditionalString(Index : Integer): TConditionalString;
  5180. begin
  5181. Result:=TConditionalString(Items[Index]);
  5182. end;
  5183. procedure TConditionalStrings.SetConditionalString(Index : Integer; const AValue: TConditionalString);
  5184. begin
  5185. Items[Index]:=AValue;
  5186. end;
  5187. Function TConditionalStrings.Add(Const Value : String) : TConditionalString;
  5188. begin
  5189. result:=Add(Value,AllCPUs,AllOSes);
  5190. end;
  5191. {$ifdef cpu_only_overloads}
  5192. Function TConditionalStrings.Add(Const Value : String;const CPUs:TCPUs) : TConditionalString;
  5193. begin
  5194. result:=Add(Value,CPUs,AllOSes);
  5195. end;
  5196. {$endif cpu_only_overloads}
  5197. Function TConditionalStrings.Add(Const Value : String;const OSes:TOSes) : TConditionalString;
  5198. begin
  5199. result:=Add(Value,AllCPUs,OSes);
  5200. end;
  5201. Function TConditionalStrings.Add(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TConditionalString;
  5202. begin
  5203. Result:=FCSClass.Create;
  5204. Result.Value:=Value;
  5205. Result.OSes:=OSes;
  5206. Result.CPUs:=CPUs;
  5207. inherited Add(Result);
  5208. end;
  5209. {****************************************************************************
  5210. TDependency
  5211. ****************************************************************************}
  5212. Constructor TDependency.Create;
  5213. begin
  5214. inherited Create;
  5215. FVersion:=TFPVersion.Create;
  5216. end;
  5217. Destructor TDependency.Destroy;
  5218. begin
  5219. FreeAndNil(FVersion);
  5220. end;
  5221. Function TDependency.GetVersion : string;
  5222. begin
  5223. result:=FVersion.AsString;
  5224. end;
  5225. Procedure TDependency.SetVersion(const V : string);
  5226. begin
  5227. FVersion.AsString:=V;
  5228. end;
  5229. {****************************************************************************
  5230. TDependencies
  5231. ****************************************************************************}
  5232. function TDependencies.GetDependency(Index : Integer): TDependency;
  5233. begin
  5234. Result:=TDependency(Items[Index]);
  5235. end;
  5236. procedure TDependencies.SetDependency(Index : Integer; const AValue: TDependency);
  5237. begin
  5238. Items[Index]:=AValue;
  5239. end;
  5240. Function TDependencies.Add(Const Value : String) : TDependency;
  5241. begin
  5242. result:=Add(Value,AllCPUs,AllOSes);
  5243. end;
  5244. {$ifdef cpu_only_overloads}
  5245. Function TDependencies.Add(Const Value : String;const CPUs:TCPUs) : TDependency;
  5246. begin
  5247. result:=Add(Value,CPUs,AllOSes);
  5248. end;
  5249. {$endif cpu_only_overloads}
  5250. Function TDependencies.Add(Const Value : String;const OSes:TOSes) : TDependency;
  5251. begin
  5252. result:=Add(Value,AllCPUs,OSes);
  5253. end;
  5254. Function TDependencies.Add(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TDependency;
  5255. begin
  5256. Result:=inherited Add(Value,CPUs,OSes) as TDependency;
  5257. Result.Target:=nil;
  5258. Result.FDependencyType:=depPackage;
  5259. end;
  5260. Function TDependencies.AddUnit(Const Value : String) : TDependency;
  5261. begin
  5262. result:=AddUnit(Value,AllCPUs,AllOSes);
  5263. end;
  5264. {$ifdef cpu_only_overloads}
  5265. Function TDependencies.AddUnit(Const Value : String;const CPUs:TCPUs) : TDependency;
  5266. begin
  5267. result:=AddUnit(Value,CPUs,AllOSes);
  5268. end;
  5269. {$endif cpu_only_overloads}
  5270. Function TDependencies.AddUnit(Const Value : String;const OSes:TOSes) : TDependency;
  5271. begin
  5272. result:=AddUnit(Value,AllCPUs,OSes);
  5273. end;
  5274. Function TDependencies.AddUnit(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TDependency;
  5275. begin
  5276. Result:=inherited Add(Value,CPUs,OSes) as TDependency;
  5277. Result.Target:=nil;
  5278. Result.FDependencyType:=depUnit;
  5279. end;
  5280. Function TDependencies.AddInclude(Const Value : String) : TDependency;
  5281. begin
  5282. result:=AddInclude(Value,AllCPUs,AllOSes);
  5283. end;
  5284. {$ifdef cpu_only_overloads}
  5285. Function TDependencies.AddInclude(Const Value : String;const CPUs:TCPUs) : TDependency;
  5286. begin
  5287. result:=AddInclude(Value,CPUs,AllOSes);
  5288. end;
  5289. {$endif cpu_only_overloads}
  5290. Function TDependencies.AddInclude(Const Value : String;const OSes:TOSes) : TDependency;
  5291. begin
  5292. result:=AddInclude(Value,AllCPUs,OSes);
  5293. end;
  5294. Function TDependencies.AddInclude(Const Value : String;const CPUs:TCPUs;const OSes:TOSes) : TDependency;
  5295. Var
  5296. N : String;
  5297. begin
  5298. N:=FixPath(Value);
  5299. if ExtractFileExt(N)='' then
  5300. ChangeFileExt(N,IncExt);
  5301. Result:=inherited Add(N,CPUs,OSes) as TDependency;
  5302. Result.FDependencyType:=depInclude;
  5303. end;
  5304. {****************************************************************************
  5305. TValueItem
  5306. ****************************************************************************}
  5307. constructor TValueItem.Create(AValue: String);
  5308. begin
  5309. FValue:=AValue;
  5310. end;
  5311. {****************************************************************************
  5312. TFunctionItem
  5313. ****************************************************************************}
  5314. constructor TFunctionItem.Create(AFunc: TReplaceFunction);
  5315. begin
  5316. FFunc:=AFunc;
  5317. end;
  5318. {****************************************************************************
  5319. TDictionary
  5320. ****************************************************************************}
  5321. constructor TDictionary.Create(AOwner: TComponent);
  5322. begin
  5323. inherited Create(AOwner);
  5324. FList:=TStringList.Create;
  5325. FList.Sorted:=True;
  5326. FList.Duplicates:=dupError;
  5327. end;
  5328. destructor TDictionary.Destroy;
  5329. Var
  5330. I : Integer;
  5331. begin
  5332. For I:=0 to Flist.Count-1 do
  5333. FList.Objects[i].Free;
  5334. FreeAndNil(FList);
  5335. inherited Destroy;
  5336. end;
  5337. procedure TDictionary.AddVariable(const AName, Value: String);
  5338. Var
  5339. I : Integer;
  5340. begin
  5341. I:=Flist.IndexOf(AName);
  5342. If I=-1 then
  5343. I:=FList.Add(Aname)
  5344. else
  5345. Flist.Objects[i].Free;
  5346. Flist.Objects[i]:=TValueItem.Create(Value);
  5347. end;
  5348. procedure TDictionary.AddFunction(const AName: String; FReplacement: TReplaceFunction);
  5349. Var
  5350. I : Integer;
  5351. begin
  5352. I:=Flist.IndexOf(AName);
  5353. If I=-1 then
  5354. I:=Flist.Add(AName)
  5355. else
  5356. Flist.Objects[i].Free;
  5357. Flist.Objects[i]:=TFunctionItem.Create(FReplacement);
  5358. end;
  5359. procedure TDictionary.RemoveItem(const AName: String);
  5360. Var
  5361. I : Integer;
  5362. begin
  5363. I:=Flist.IndexOf(AName);
  5364. If (I<>-1) then
  5365. begin
  5366. FList.Objects[i].Free;
  5367. FList.Delete(I);
  5368. end;
  5369. end;
  5370. function TDictionary.GetValue(const AName: String): String;
  5371. begin
  5372. Result:=GetValue(AName,'');
  5373. end;
  5374. function TDictionary.GetValue(const AName,Args: String): String;
  5375. Var
  5376. O : TObject;
  5377. I : Integer;
  5378. begin
  5379. I:=Flist.IndexOf(AName);
  5380. If (I=-1) then
  5381. Raise EDictionaryError.CreateFmt(SErrNoDictionaryItem,[AName]);
  5382. O:=Flist.Objects[I];
  5383. If O is TValueItem then
  5384. Result:=TValueItem(O).FValue
  5385. else
  5386. Result:=TFunctionItem(O).FFunc(AName,Args);
  5387. end;
  5388. function TDictionary.ReplaceStrings(Const ASource: String): String;
  5389. Var
  5390. S,FN,FV : String;
  5391. P: Integer;
  5392. begin
  5393. Result:='';
  5394. S:=ASource;
  5395. P:=Pos('$(',S);
  5396. While (P<>0) do
  5397. begin
  5398. Result:=Result+Copy(S,1,P-1);
  5399. Delete(S,1,P+1);
  5400. P:=Pos(')',S);
  5401. FN:=Copy(S,1,P-1);
  5402. Delete(S,1,P);
  5403. P:=Pos(' ',FN);
  5404. If (P<>0) then // function arguments ?
  5405. begin
  5406. FV:=FN;
  5407. FN:=Copy(FN,1,P);
  5408. System.Delete(FV,1,P);
  5409. end
  5410. else
  5411. FV:='';
  5412. Result:=Result+GetValue(FN,FV);
  5413. P:=Pos('$(',S);
  5414. end;
  5415. Result:=Result+S;
  5416. end;
  5417. Function Substitute(Const Source : String; Macros : Array of string) : String;
  5418. Var
  5419. I : Integer;
  5420. begin
  5421. I:=0;
  5422. While I<High(Macros) do
  5423. begin
  5424. Dictionary.AddVariable(Macros[i],Macros[I+1]);
  5425. Inc(I,2);
  5426. end;
  5427. Result:=Dictionary.ReplaceStrings(Source);
  5428. While I<High(Macros) do
  5429. begin
  5430. Dictionary.RemoveItem(Macros[i]);
  5431. Inc(I,2);
  5432. end;
  5433. end;
  5434. {****************************************************************************
  5435. Default Instances
  5436. ****************************************************************************}
  5437. var
  5438. DefInstaller : TCustomInstaller;
  5439. Function Installer(InstallerClass: TInstallerClass): TCustomInstaller;
  5440. begin
  5441. If Not Assigned(DefInstaller) then
  5442. DefInstaller:=InstallerClass.Create(Nil);
  5443. Result:=DefInstaller;
  5444. end;
  5445. Function Installer: TCustomInstaller;
  5446. begin
  5447. Result := Installer(TFPCInstaller);
  5448. end;
  5449. { TCommand }
  5450. function TCommand.GetOptions: TStrings;
  5451. begin
  5452. If (FOptions=Nil) then
  5453. FOptions:=TStringList.Create;
  5454. Result:=FOptions;
  5455. end;
  5456. procedure TCommand.SetOptions(const Value: TStrings);
  5457. begin
  5458. If (Value=Nil) or (Value.Count=0) then
  5459. FreeAndNil(FOptions)
  5460. else
  5461. Options.Assign(Value);
  5462. end;
  5463. destructor TCommand.Destroy;
  5464. begin
  5465. FreeAndNil(FOptions);
  5466. inherited Destroy;
  5467. end;
  5468. function TCommand.HaveOptions: Boolean;
  5469. begin
  5470. Result:=(FOptions<>Nil);
  5471. end;
  5472. function TCommand.CmdLineOptions: String;
  5473. begin
  5474. If HaveOptions then
  5475. Result:=OptionListToString(Options);
  5476. end;
  5477. procedure TCommand.ParseOptions(S: String);
  5478. begin
  5479. Options:=OptionsToStringList(S);
  5480. end;
  5481. Initialization
  5482. OnGetApplicationName:=@GetFPMakeName;
  5483. CustomFpmakeCommandlineOptions:=nil;
  5484. CustomFpMakeCommandlineValues:=nil;
  5485. Finalization
  5486. FreeAndNil(CustomFpMakeCommandlineValues);
  5487. FreeAndNil(CustomFpmakeCommandlineOptions);
  5488. FreeAndNil(DefInstaller);
  5489. FreeAndNil(Dictionary);
  5490. FreeAndNil(Defaults);
  5491. end.