New upstream version 0.39.0+dfsg1
Víctor Cuadrado Juan
4 years ago
166 | 166 | from waflib import Scripting |
167 | 167 | Scripting.waf_entry_point(cwd, VERSION, wafdir) |
168 | 168 | |
169 | #==> | |
170 | #BZh91AY&SY9 ½´\¥ÿÿÿ³DPÿÿÿÿÿÿÿÿÿÿÿm (¬#%00e(b÷/mÐ#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%öÞúzómmkîÖZÞæ²U#.´[iÚ¾îõ¹±µú:¥'kdî7{ÛïoºµÛ¶ÖµK¹]Øvµ'ÛßO¾ö¸gv÷s½÷¶N)#.Q+Ù½íp·µÞ]/{m»<{guÒ@Ýó{§«vo;¾ø;vÎiîáÉî44lºï{ß|ûïëËßÚU9íõÝÝî·¯y½÷½x#%#%@(}ìh#%` ï²=âwfí:4§[aÓ¹½ y©³A¦¸ê»´ö4=¦öìd+Ö¨ª)íf0#6 *¢{Q$#%#6#%YJzÚV½%çÍíîæ}»j½êºaïjÚØá3TTf˦Iv×]s}6óu7¾÷z:#.ÎxûÝW_=³ÛzÖåZ;Û»ÍÝÛ}Þsy¾¯³»ß{¸ûíÖîiÉÔ÷Ëzõ¶§rç>^æû}ñ¾íóÛa zúz{x¹-ìzÍݳֲ4÷³¼ÛÞ÷fÞÏs¬ô`u¡ÒãF°Û"EE7w¼#%(J*OCÀ#%lîè=÷n{Ywº¹½»ÐdÜöï>}Ü[vÇGÐ`>ÛEmk®¥ÑMãW`×LæyÛãÚ^u½#%}÷aît;o¶û}|{mçOvpòǼÎo·*WµíÆܶ2>öí®®òÏwÖõ»]´î;ºjîí9QÚt×·Zt>÷»Ü®¨ÜÙu÷ß|}í«×ܬ&ÞíN«îq\îû½:¾Ã.ñ^ÙéyaC§¶Ó¶Û³®÷Ð¥&nCzî¤|öilöͶíÝîвë[¸÷»³Ûºû5ÖkoX«èqØnöÐlîõÞÞ/`{´ó½wÌ>ïÐê¥PJªPTT´jB¹7uÐv&i¶vÜèº]vúÝ:kÛkÔØëUUÜ{x÷)º¼»HкÚɯfw#%7ZI#%#%;Ü^êåÉÎó²û3ÊF-m½ÜözÔíÝÜì_U.us[¶õv]]ó¸|Hû,ÍqÑ»ÝÁæñ{c;úçvåJº{+¹éÔ²õ§l÷+ªWg¡»`úùÛÙ;{n#î²Ç]÷}çww»{»»xîvÛ#.¾Øú½mÝEfù"s¼ï¯¼ùÚÀ°ËlÐú$/g¬íÑx<ïÜë°VØ6EǵޮÚGxO{×>öø½ïwÞ´#%À*×Û;Fªµíí7¶;g<ÂÀëu´oSk´ÝëÓmï 9.ó®Ú×ݬ»Ý¾çwÅówwtåvë¥Þç:#.[.ëwc ÓàéÕhÁgu½Þ^ïnØu¼ÓÐ /=ÝÚ4#%c¹éî½Mö{ÜàìJ U )½{xW»´×`ï{®ñÝÊäÅÖÃV¶U[}÷IzovuÇH*í·u$ëIÒÖªîúãÞncÚ[ÓµÛ× &Æ»»}öøø½óí·³acÜ| ìÁG»îñÌͼÜ&:·»}½í6µîÐíç;ï¹ßvÛRÀîï·w}-âòó[ãnh &#%& £CBa0#.#%äPÏTzÐ#%õ§{SÔõA) B @@©©á$zzIâ é4#%#%#%#%#%#%#%D! M5TÿMoU<ÔôzTý(òÔõ)é¨mG¨#%#%Ñ£@#%#%'ªRD!4dÐODõ$ÙOF¡£õM#.ò@#.Sj#%#%#%#%#%#%$!#%&@bh&M#%M#.4SÓi4 ¢ #%h#%#%#%I¨ L#A&¦=&õmê{SIé h#%d4#%È#%ÿÓ?£Uirê\ÕQWwk¹úµZvhÊ>5Zu!LA³ ,LQ*")æ°Pcõ§óü Zü5OùÓ¦¸ üæJt¦î£Ä8WoT"¢]^SÌÆ´_3ýos2ìÀlDs4;m»qE6®ñÎÊ´ÚMíÖØ`Vd â]jíâ5o# åñ÷UI7wD¼áÌKUå¦/Ý~«oÔBäE"ªSº»U¦ÖÖ5k3khÈ 7#%H*-E Õ:¥$H& " HåP° !ß#%h¡#%ª$@dPÉ@mªfL ÍCLÓd@M$Rj6Ñ3525)FSm&Â$ÐJ2ZQ°h[Fi,i¢Z!#.F)iMF¥#.1eM£DRl¨ZSMhYi#. (ÌÌcRF£Qµ&JlBjcI@hÒËHÆRF¦"[M¶³U´iÆfLÈM&²m¦ÛM65%)-5±¦Û3fZL1f´ÄÑd¢lB!Qf´R`4TH!`ؤ©fJb0lB XhdFIR&B4±ClÍ&)BFRÊËf$@ÒYY5ccE#6dK) -)¦ ±%&ED2hhÉIF($@VAME¢fRÒ¦`ÉØ1MÍab6¤ØV$$´PRD%¤Q0EaÆIL# &RJME±£XHÒjHb iM$"H²[bË2F̲3bdE(Í&U4Ä)A³Q`,i¦Æ"5+%6(R"I&¤a³LcI¡ &¤QÔi3HÚ("h¢kP,&YA¤²2%&DÐM2*4f6)1¨6ÄÊA! "1F4,Ë Ù&TÌÕ£l¥±(#.H¦!HØСYM$QF¤É&ÉØÆJF¦h±b2²2³i¬D`¢JM52i!¢)#.1Sb5*R)#.2)´ HÅ(ÊHR"E$M)´i5DFÀh&Ti¦DÚ#.,ÒeDÈY¦ÉJbD!f k6lmd°$4Ld5EPZ XR$Ècc1 Â2RXÔY¤J&E©M(ZhII$2ɲ#)E,Ñ¥15²e"$4M¶¦¶´`Bjf¦F&RLÈ¥6À¥,Å&%TÙ¢-L¬-bCØRD#HJm~Ãk¢¦©aÍ¢lVƶ*6L¥4ÔR¤44´ ¨ØFÉ5Y¡¦c(ÉS*H¶D¦[%´QIKQµ £&D±5±acR#6e¥2eI´*Ò4TÙB+dË"©TÒTÂ63¶,YL¬S,¦ÖJ²ÙJSLlµ)¬±%¤2RÔZ ª!¨Õ£%AEVMd£jÅEHkDÑ$mhÅÔl2ѵ´0°U@iR £F2&¦±Æ¦&±di Õªµ* ÍKY4IR1!M¤lY"¶¥Y¶1Jm*R¦YaZDF¶K"e5MM¶Êk,Xl²k+, lÓ ¨ÒD bÃ4!´ -£T%¢KQY&6LJ,&Ël¤#."+,E1ÌJlÓ4AE¢Ó$&Fm6F6ÆÈS¦cE%bHÌÔ#!4LÔQ¢JdRP5BTÀ4Ó J²Bj-#636£)F̤£!HbÊkÃi4F5&Éa$YP -4)Ä4Y©²d¬a,±jE¨Õ5£4ECF¥)6b¥fQj4 2ÆA¦&Ä%I1Rcd¤Ía)ME`Û0Ù¤²lfECJ2ZfµhTÍ2Hl£0D2hªih¬ÒlÄ,LDÒRBAh´[ Q¨ÔQÆ-ÃIM#6LR#b-fC26*2%,¤©Ñ´k£TI¢Ë5E$Ô£Pdðj¡kA¥4Ë!E$¦Ih5E±JÛ"¥F±¤ÁdÑÌ¡jQHfJ$©±(j#V#.2,Y*6)4¢Ù2V-&)+)¶D¶M¡¢TR¢Âccd£dÑ&#¶HÔRLÁ¬ÉA#6)³6&"ƨ©Y¤)¤¢&RV-ÆÉ£F42JÔÑie£he¨Ñj±£i5² Q¶5%)ÐÈÌÆLÙ&kDlU%hÔ,«&´LÚ1lj £cc$UE2©¥XÚ6¶1mIÊQ f²±-F+iQµ´©QJVf*B(4X"J&ØÖ,Ê+I[M²+FbbÑIE[l¶¬R&T*&$¢1PÀ"CFi&ÔÃ%XÛØ´Í[F5¬´42ÖÊY6ÔÔÛ!mI¦¬ME26QA°ÖjMI²Ê B¢LI&RLÈÄd"Ù-¢Ñ±þn··ýÔ¥C)þB51jÄÿTqôe+(a(Æh÷!þ§ ûbåÕ LÿL$hÒlùNzí¿Îó±½9¿øºô·¦SUIPª?ë[lÈÎÿ·ÖYLâsÈ ßùë;L(0\:8À¥pÁI äd*Ãß±¢rý*¤çÿ3ÿ³ôZÑÿÊI(R×+½g,$b/Í0ÿ-npz%ZM¼íõâ8ßwB¹Á¨d~ËÕNØÆZþ,3cRR(lrrXþúݳf¤áV cÈÌ`I¥Û"lÆLhcôzçG]¼îÞ¹w§¥^¥ã\³Ë/âuçåuÍ\LëP¦"W4LªvcK@¥JAF&ÄMê×bÈÒ3(êñç]¨eñnY½74h6m`Ù(c2@sªªzoþÝ( 7pÊc#6Gv )ì,`¼rÂü®R[R}ßÒëdzçgsÅéÐN×VÄQL0¦Ð¤Y;ùd«Ïô8$ÚÍÏ£ØÐØj¤Ï(%?·râþ°ÃµºÀ¡ JÅxß÷k¶¶cÂx-2KËw%¬C°UyáyÜíÞw^Qrè»esnCQW6éçqllO²ëå5¼Z4EA¯»º?_ÆWò-ȦWÅȶÆåÈIºÕø¼u¨Û?Go*Èyùæ|m<b#4L9cuPEX°«©#.¹t@#6A!´ä#ñÆ#.¯)ÎãÂHÃz^+Ý\Ѩ8ëÞwcrË(Ë®é$s5öøZAÿhÿJrÈ.YÚlCÙ,0!MðÛtÉÈe«#6ýRÁÃ79ô,ýפ¾ìÉþFtÃÏxV¬@Gô¡d%lþ «p<kìÄ9 c£ðÐÃ|¶Ç#tE]HP0îT[æÈØÙ_#¨½zírH ȦwâÔÍW7mxþVYê?)Ärvj³oQwE¦me#.¿ÂdÔç׶b²àþN!ïe §&¢øuû/ÑÏKà`ö§nínùT)"*¤#6d9#c*w&ébÛÉðfR6z®:'ï.àûì¥k,YL#6N*}±ÆyÞ>ÇãUË"õÖUO«pi)8ªâ+ñ §Ó¬,±Èj[þv¼lQôÇôa1Kèë¯Ç×FÌ÷¿SªÄ7ÍmZ½*£N¼Pâ-#6¬AË@*{iX<ÙZøW÷»(Éðâ»EEE¼nY5ÆÕ͵þìw>ÇS6½ß«¦öøÿMfhF¨%2+zmýW!bSQIðîÜ®÷uVé(i%"÷@X'+¬¥&D§)J²å¢¶/]öï^¯"R¬k¹bÑ_·-×»±öõÆ*|ý{ü=o÷îèëØÔl|ÏÀÞ1¨4ü>õÝ>¬ýóLÖȲ"4£~"Uä¨ræPaLÖ¶jϹ$Â![ÙùzÛ²F²lWßî«âøùÑÊW=ì¼4DÁa«lAHÒPŤ'Ò'mBµ§ C×G¶éE2R]U¥"»wÕ¬ü*ÔðХ߲²ôî²Á¨ÀSE#6lÃQMZH"JuëJ»*Ã#6I¢L²íãe¥ÂS²$+b¨¬N¬<ÙkH](©É#6<*oÐçAJõÂü/;q°óap×^Ro^XjÅÄ"_gñË<TCª¼s×y¬Xq&ýqK\:05aáeF1PXäiMö÷3g{O4ÝurgúkßÙóôoÄï3Ã)#åªiÔö¢'־ʣôwr³éº8;+¹+oìÑ®Há m^L¯q#.1¼öÊIr%ÉnCMÏ}×ì6q¸v~ØÆ5.|båÙåAÅ#S<*Jtªð¡áô\äáDäÑö%*Éú9ß<}/²Á"#.L3¦ÙúÀýv½ëå+ù§T-±·,»í¶g)õïD!;SñŵaÊà=±3ÏDKA´](´¸åHvÈÍRß#v/6P½E#Ç 8qêΰâKè(q<åÅð¹ý>¼ê÷:+#%ñ²(\HÎpÊ6ç´zmï*'Ü©×1Ù»á?_k#.êV£ÊFyûeoÐæ$ê?ßjfAvß¾ÚNü£z $ !¨.fä³Ü¡Ï\iÌ©Ê#.#¥ÉE0F:E&©¯}Ù µAîg]°éÃp?X7d1á\NB=}ÙILÆ#6P#6íç;¢gäý=«»"<ú¹áïïRî:I2Éð\õq.V)gÉ ,Õ8`¬=jPûíÞèqëZ®#.þø¯,nM´B8÷8»è¸×µÛºä1il÷õm±Ï׺|5Ì=Zí鵦üLuÙ $(w0©WX uÒBdN>ù¢Ü¸I¸ì¾½iíEéËÒêwë+Õ^{å5ÁZU{)ãÉÂé¨c¼Tìí§ @^Ç¡=4´îç ÊÂZÛoý4^Û1¶Ã±öíªÆË ò-îûâû§õoÉÜn¬æU>õéºiúK|e˨J/±ßåÇ}m}w*IeQ92e@êÛíhQAA9¼CrºõÝO¡¸Ëðuu5¤&÷JÃF}w/Å¡j©jÿ} (© +þ«¯½û¿éºÚ|~þëÇTöµö°ù¥±GR{¨«E ¢úªS>,õ÷öæß»åj»çíjܱ¿Yõ¿¯õâú·+$þ.hÚ>n·ªôj£]Pê©¨Æ ×¶{âÝûïgå mk4µO§k{ÑÇÛEË£õ;ndm¥AyÑQ#6ÚäúÓ«fͲãX8T¾NL\ðôPè1 ø63Yî y²úUM3¦ùÝ#.X|è¤TWù7ìÍÇÎD^jÀER,)9Õß¹ÊÈ·)óÜÑûúuO³~¾$_¶Ï ÊsãÆ4?Zu>ì]1yÅøÚükÓEµÛX)>óOÖâm8s´ÌëéÞOz\àÚÄÚ¸;â¦R¸Á1~FS_tíÂRn(ØPñ¼b¤RfWYüÊ¡êôcì×ùúù«ÜËÎP¼B´ úY× é¤DQQe0¨x~Û{*©nf £ªwiXT¯)6-Ï;Ë£êw³$3Ê¡¶Ö}TÛÉ|-ºz²8ï5`BüéÝââêÖh¢ Ò¡¸É~¦JΤZ+¯¦9r¬èlÿV´xð¨#6h6ÀêD¶x0¥Ë)AX³£*0²¹ë¯_#.Ç·È÷zìe¥HÙÓ,¿µñïñ²5AòõÁÞ{eÔË7Súþ¡&yÖYñ¯¥³LÅS¹¾Ù?¾ÙÊ-y¯69^è}¦pàBIiK&±nÎǨþ³ éÝs»Î¹ße²ð,¼&2:LäßÏå[«¸óxHÇ®*Ø×ÒU9åé1äDL5;þ²ÏiîÐåQT nUÙ`Ò#ÍoJò41Sºëïv馫ÚÕéa離Mô4O|®I${U½órà¼0;0©*ÃzG/½7+#%Qb ]öÙK\.ª¸ÌÖ÷) I9q×ëa¾¡¼òó#.ÑýýïÞ5оä¬×w*8ÙA'<ß:¥bÊï¬2×ÂxÕQn:ú,öTl8:<ôáyï9ëCÛ¢M\¡"#.JvX¢=Êóðw¹Ô%g±CÍP´GhaÑû£ªºÅH ö)¬¾U.ÎõÛÂîA=sÈ«ÔsH]#.¤ú$¢8.\Ó³Mìòõò³Þ TÑTaÓM}ªP «½È¥>?¿½¨èØkÕborR#Rñ/Ìç*3ÔÆѦøÚ4u©ð±ocÈÞéñÇ#.vnV»pÁáã)r³Z,ª£.OêÀ·}zwîÝlnª¥.LQøy×@EHiwýÐçç=Qq§"%V2&0+Vq¬¨w=Pë¦uÁ7ºV^-Eu©QQ'çU0D}ÏéÞNi×ôñ$¤úÊ'1ÎK¯U=_lS#6´í0ã×D1zßÆǾ+âdpÚô±æZ?wéx½\`<+½fJøã×~WKËÕ¸îáÝ8n©$z«G»à<c½Ì/Yá÷Ó vfz3ó¹L´cz7kù%ûÚEÎY¥ñ¹-J`]ÞBvP\ÃÚïHm2LMßwðrÈ÷4:ðŵ¼`¡¯\Ô½u}<(ñf`¨Å³÷ôͽUQ9c:ªO+%öPiP/º°<H¬§`±È6,I<Ye"4ECØ@fzÝ«ÉbFõG¡B>q¡z<À®÷±¢Ù èì#á?}ûI¡ÓL»_KÃ'ëB¶Øÿ#É+ù¢ËÖò|Ñúåµöm±×ª©ü°áÇ7û"ònþ½bô#sh¡¶¢~¥?~´V]6k)0úô£ ¦ÙUBÕñ °U¢,õ'«@5ûÜ+ÏÕl±X6µÉ n.ö{pùèü}´:ÑÚðy¥ªbsf19%¢ØñZ³æ#Ô#6 ê,&Ñ3|#6y"ú.$#.#.æuµÅ.÷ éÙ×»*{gd¾evKfûQοí¶ÒÌð7N hÃe hP"1b±êL`ÅMm¬"ã-ÅX]#6=©Õ)«Î#.äÓ2¿+]øºtÉg:Ô00Y½UDàÆÛHIå#LÇÍ6\j¾}Þ#.Û»Æ6Ñ=U S¿ÑÏÞtÌ4såÙº"ïg³.¾t(ÄÉ:qþ²c1û¦³^¹ÙÈÕýÉn*fb¢fÛã;èXhêöÛ÷Ç1£a¼s>¬=N#.ä÷Áý(ûqÃÙfT`ÒalÚÞ~2å8Àr¥¦!:Y@àe¨Öj¡Á¥N¬Íec±;8`ij%ÉÓcW?äDM¶@0L¸¤\Þ'kK«®NºËϧcV*±FÖÒßãñð³Ô9OäÇ»éìåôÁõ*5,<:Ø|EI$¹$G4¡Õ{âS§#%beÙTö¯äìÚÈQ·Ø!ûPveòóêÞ6^ø\F´÷fX=*´nïú>Q/ãnNQ#64 ¯¦E¼×^Æ~ú`GÈ'0õÍ\PDØLÍÕ7ØKuÑohsyÛÝQ¼ã*Sçs;5XvPÍf8uÁ®[ÂÝÒS¬ÝϳÔÍ4¹²s? 'ÚÝiÎ;¾n)tYG.å¯K|íMÆ×6AâÖuü×8'¶¿UÊÒ»*se¦ÜL)e8«|ãý×W#%}O`×|AÊ>bmfò\sIÑO##y3£Bé#.â }ÏÕ¡n«r£CDb+ÂÛ`ìúÛn¨>O½Õqòh¼×59·b¢ f~~V#+bç±^Ug:^ó×ÿxºTq(Ū¿1y{TáâzÒÔ²?[좧sÔ5YÿÆgkqjûWXvã_WmMÆñuÍZ3¥Q_{=ì㳦(5#<IÛD9Ü÷3Ï^y%0IjÂÉ[J3NMíT¦nPÿG4_oñï=BÚÓK¤JÍ¿ï¹¹oÕa^ݶxe@eëªã8GHºê½ÙGÄÆÀú"ûÞ° £wñý~Sa¢v®4L§Uz°ÎÞÛß²+fy´Þ¿#./wWdË«^úPÄ´¤áYKAq:;åG2jT wÌC{¿ÚC¥k5PuÝrª0àÒs¢l+«3Û¬#Û8]ÅTò»Ó:úûâ$KÈr0Êâ(\ñ>Âæ©CÞØ ¥Î]«m9¹ÙãH X1ºÈ½7¸ÙdÉ-KOèÜû¿qÛDËâíÜ×s²ó#%$ÌØ@²%"£ÏiñÁGn¦·ÿ¦ågsáºÖÉÑosã¢Ñ+-¯m%b"¹mofÁfm{pYpÐØoÃZ̸Â4¸b³Øúxì^SÎuÜÛzVþîlbݵ Ï°POæÀ:»¾Zn(Ô#{7)×¹LùÏãÕñÁ÷YÓ¡áõ"6zXø£°ébcGë-þ7J-YSÕ#.[òw_#6}P$RFÂ/þª:üó²§HèCþCo:Të=49yz¿ÃÃÊræÄ{´R4IÖÌom¨3 ]Fm;Àuc£tÇlozÁ`(]ô¿5¨å¥÷!.º¿»ZUǤe(®¯ùÊ<V+Î3¾ÒÿÓ²uèæ:»bà-¯°F|¦WìºS·§µ]ëÑöá« Ø·M(Wù¯:ýuÊ:jÝÚÌ£H¹EÑ£8`ñÅتá¨à³ýk £Ã7c¤ü¶<ÎW=ëS¼qé4§5#.-Úß¾öÝE3ÂcÈär¨Äù§L¢^3ýÞ®§r"ßM¼}1(gËDôÑ%¯PÄI¶ôÄ`³CȲ-G%nG5lV°À(#6QEcærÚéͬ١C8z³`Cß½u.7ªY`ÞD,UGÊRÌÑvp«Oøg[\þ]EÅ@Bcvß8èÕñ]Ñ·7Bov?Uëì?ëo;2ëðÿ ¾>^R÷ FÖ\«ÈÞ¬Ãô²Ct½F«X 8,Ò;hXj¾$8ÍûYùüxpå»È6püà ·Ý¤$ÀA7ýc%#%%"A/üÕê¢cå9Xãßá]5GóÚY"E5É#ÁÛ/*9/QÉ?BuîjÑm-Ã&é;ýz|¯££Õ¨l@'ñ(¢¹*öúi|GÀS«êÓ©ÝKð!7ÕmVÐÒ×>ø³9&u È#% ûÿÕ»Ñþ-¢îÕáøÇîäévÞ»¥ #.cc¢¼¢ ÎD×Ì@?Ç4#6¡o轶j0ê**¸ÙsóîÅÃ#.¾º"M\îª"¤ò©¹#%gíÞá4yRb(Ñ>@òtÆ¡R¿Ò]eÑ·äsvÓ Én(+VpäÿE®+ü'6¹ðN°¢3¤Ä[(ZaÉ»I{Þa½x=9"1[ëJ¯lê1H#.ªñ%OÃ#%ì#%ÄcÏm¾ÿ¶çaùã¤þÑIç³ñåú#.5ðׯ_ó~µ?èÌOHÅGTUÙÀM¿ðý¶y´»õ¨5Ñ6¥Ãcjb²ø§¹$|_Cºu0^~c_ñd°"w#%°>×j>ðõER=Sþñ¶s|º5ÛåÃm¶fÕ¿.Õ4|åÝj]³¨:;£ún>ñ:ÿn@ é)ª×fËw#.·l¾¡ßþ0}÷îâ£(WÏÎüoNßÛès{G4ÆÞ|ö0t9×bbÎ?GÝ÷k_ÁÉfª "@îkòX/E÷;¥fL¡¦¿qößÕ5¼8±d¢*¡â{/Ìë¿D4áÅtÉûàûoötgS³wÓ>¬XB§<ÈIÁMmGýùu 9£>¿zsáþ¸'^Í¡c®¶7Bª+à À3ïr\«poª_PÜâÛô=TÁÖæõ§º»¶4ZMI:îäÙ³[Ê+YòÈ{QÓho³ `#67]±áÄRd1ÌU ²[d"b$#6Jk!¬gÛªLk $,¸ûÌ£Ö[ËúP&¶Ï¢U´ð¼U1#ÅË;§¿&b±A 1dy%*üüóî¨"/Z7cûÿuËBsr§¿-$ýþ~ mLÀ:z®X»U ÄDq#6Ïß©s <=U¨~L ¯R5¸}ÛVIé³íLgï ¦aóÓáåvºÿ_EF -áG8?ûmRGÒ=bSfqÖ7¶ÆAi+sèü"Ê|;O¦$÷#I±aiñÓíÁº×®[Hå[#.ºuÆƲX[È¡J×<óÙT¢ ÞºÆÕQjª@Jßü.Å#% W&û9o èîD@¾Àß#.âë cû§A,BCG:l¡úkLuÐ#6Õž?; éõæk¬©÷#.qÌvÊÐ3:^LUÈk4#6`#.~H5ðÏÙ>Ãõ÷þ}¾Ó¯[hyѺBJ2\¡~¬dâe#/¯ÿa7·§4ãYUáCÇMs÷þ{¿ÍcB'$Å;Ç©·8¦ø¦#.{,µjweß#.røâ^˾<0fxþîÍÎ5&Ī¦6P·cQÇ"5Uô÷êE7¥ãyl)pÚ7úµ!$Ó8>{K2®rãyòUçD#¯lüw¯åzã=wÊÝ#6Dn ¸}^æ¡}ªé«)D¥Ð]âuq·à¿çÛ³2±³ ®\ÚS{ûìSXãÅY%qßÀn©ÇA#°óÑUá]=@tÔ³Åj&»Æ5&fîðpK ¶Sd&vEÚ}´zGYÌ*B#6 ìÃQ>Gêp¬vþÛ m}Mææï¤É*Ý0ÞþÓpì÷Æûè|A²vB0;½k[Èé#6¦h"#_ ßzéòøÍ3ã 2&BÑ 5Â6 ܦ2,,»¹Ç|زØR¢"ÈQæY¼° ÆÒÇLkG>'ôj1* ÈéôuüiS1ëu\SdIiÆT°²O¨6ÆÚ±Ôᢻµázl_gêÿ8hxMöX0-ôî ê#ôésüKòÿ5ö¨»?#%Ýyx®)À7 y#%í2òw ÐPc± Æ#%tÀ`=!#.fîÁN¯%Ò[^v 'k³Q÷Þ´Ŗ`ÆzÆ) û¼nuí¶#ÎÃí?.ÒIpJ[¥iB¡×*,ÂÒÅ =ÕÕ`ìQ×pgc¼Iâèez«ôC,Áf{Ê2ѪRuÆú ë¹7©Óyå_æ>£vöt µÆ|ú9´VKâR;#6(<äwãC)ª((FÏv0ñ2hÊÐDÊ#0+C9°z¼]>ÄlÑJYb¦ÒT-¨¦Å¾bàèÁFrÐpõ*(~¨Ñäû£sÐÌêÊ4 u»y!jÐ#8±sy#.bn=>tzËÌhÁ¡ÈÌ\åê¦å bPõYÄËþ:¹ÂnTÝÐ`¨éÕñí±Ö½nz1»DRÅ+GèobÊØÛÑ£U$2Öå#tóëñØó^¸émÖî²½¹ªO8«,}YEÏ{^ÜIfxOÐpLÂÅG#.pßú¿¸ÊYE³>vKUÓç¼çû}gا©Ú§^ÏÜøÌÍ+#%®[a:9Þ9ÉÃd×+àB~e.wµ¼qalñwE#%{j,dº*1®íwyæ]®îëOÀFnsnZ*4xm1|F¢ ªÝ4s¡ÊýÖ{ι,äl D {#%ÓDhM´ÔD)$CTÅVƨʣ}íÁ14LT.%"¸ã#%l@'D188Ö÷#.A³èòñ®$Õ^¾0Ʊ³\´h${Þ®#.NUzJ);I?×$è±ØíJö»? v#.êÙöT«T¾î°¦ãaÆ»EÀø5vÈbãlyA}·É¹»Rò¢C÷)K.Ç( ösN\0p¨¨S"Ðo*ñ!WTðCyp2b2è/mû¬kÙÓY¢Kn9¦µJ:¸Ü³\ü{oMh]¥ÂfXn#6àÛ¯d ÓÂ/QèØ E®KNÀá®WöÙ=þ=^u¶Ã?×íÆÊ5çã+8~Ñ ZF0oÑ48Ã@òð_¾*Çc0Z4ÛþþJ°q áFÃ=tÌÐÔ%Îln¶bæ¦ÀéJÞ(BwyÉ.ÅBjÜxHÃQTÊ8¦4c#6Å|mñd@ñ#%Òå¥c6PºËÈaFÄ`]ÿw&ÅççqÕ2ü2GµÐQ˯Û1R^+¦¯LZ¾yïÛn@m2(Å£-eFK`²(euDÕ8IwN`;ª4,:$VbV66ÄPEBD 2ÙNßYö;üó6é}rÛ=ùk²#6_³S0¢³*¸B¬¥yÔy¥,ôS°X¾.9¶¤Ëuªë@+ë#%)|ðÆÔÔ@zæX"% F#%Às´õ&Á;Æzüiûç|ú¶&íïöí0t 65à1L Þ=Ùôãõ¹H9ív ¥RÜð¿4Þ{mÇnpíÔ+ãÍ=Sº!tî#6oÅgcìtn ©t,ÜluVFƱ#.Ù%Æ·©_NÃÕsËÏù*\¶µ8r&Aö²ÕÚ¨N6÷KY¾#¥öZÔÌì:w¬9§Uf Þj Íñ0ÀF+Iu,<H¿ý ÍF;ù]õ½ =ci?kÓ]w©XNÚÃC$#."oáo+wÖÓý6Ì<ärÿg·²ln{²ïé£ú/ä#%Ưۡ¬ÏªÜåô¥ázY].Lè®k¥èÐk#.Ï· g/!¡5ªJ ±R%KA¾Ç³8Ávk#.î#ßxÄEûÈ¿÷þÎÈÚìv`ÁÕåEjÜ¡øØ¢Öö%#d¶{äs1ÜQãËðÓøÉÏe·&¸r¦¶Äj¡ýÓ;¤5wÙ1#.Ä)rÁ·÷íÌiò/:'D\ÿlÌm#.¦2!1Mäñ&¬¬F)èdXUK¤@md2,ÈtëE4'ÖFÁ°5F:Ep[ÌÙRMÔ0õoïº5"HJ)#.í¤#6)$Õ¤o.Ø )Ú"0Ñ¥bÈèQѸ&bÄÌ´cu·^Øj5 ÔF=3#.MC]o/Õïâ÷~ÞaÆDbÃ'¢Yé±ÍCB&g×LF[o×QLiÂ4òìÏËGdÛ78¬Hý]Ñãg(q5ÆL¯;ÆÎEêRiü\©Dyb9iȦa<µL£Õö½w±Í£ÅBM"1¸È¥Yi]Ã\¶ Ýb»/Ì]NçúséÇp#fâzÜòëÑFßÄå .¡IÛµË#.oQævyÙxq=L°¤XÁMÀ7E+_î9x:ãOF#äøT`¡Ü³µqùCåÊjm·}#6±;¤½dJHµ!MSxLÍÁÁàé#6\³*"ÿ©©eãÂ;ßÏxý#.q#Ö§i¸>NcUGEæÿÏ^Û¤Éà4ó$Á;>)Ín$"Ëýȵ7æÍÑ ÷ÈÙf1¡ýê(v h«éC5×`ò ã{Ô R#7(HTZ'ÖcJ:7Zf6NGÌQä8@ªsIÊÛ¤ÜjìÚ#%;qÂnwjÙQ±¡3¿Áaªê©i·(Vj¡(bõëVðÖ\ÓâM´0kD>§¶UzpNzb#.ý:ë8áâJï}CñOv(ÀäO˦Ãÿ¡68H^&ì×¥±Ó³?òtÇyë°#%#ûý¶¼·6é³]Vâ¡3éeÁ×GY`IÁ´ÚÎ%® ¼ï|HsϺÛEH:uÅ) ²,Fj0ËsVºY#W6éÑ(4ÐÅ"´4YadtªÙ#6#}´Ü¶`Ø5Mõøf¤ëÀºfmjÎ(#.árµ¯V¢¿í;'\ãS´)=ǸöòÒ#%'Ü#%½zÜ\n@|ʼîmÛ¿6ôÙ ²êö¶¾7Ç¿ eÊçó)vaÒ¡ÃHFÁ XÏÛwêÖ?!¿òÑ©ÂâýjÌxOuÖwð4r }ðÛãæá7>ñ§Æ(8Ñ_Ì]`#÷úv#%HÑ=©U°Q0 þrm¾H%x; Öõý¹ .?½VI|gxûq¨[$î}PT=]#6Lk+ì Ïãý¯²K»d9r_ ¹bD³åAÍÝðü(òìù· #6#føåðÝÿ¯c»ì²BÜÖÝÕÏtê~jðêêçßlúü3~i»Ónn>ûy¾{çñ~ùë] Þn¨`"1Ø{ô°õ¯©Y.HGs$å<Æë½\G<Dºáëߧ=~ÏÕþÓCrqy!áã^H³U$ÅÕ2Änà cèúÔb3AÙîù½ùa.ÁGc@õ¼#6\Q\RÒ9¼ôUäÎ)uÛ¯ëqVÂRVÜ°¶·úûJ#%Gh¡ïÿÒ#%f÷,ÛQ¾ß·èøvKx#% è¡#6»wE·B¸cÖáÄîâ§Ï¹øj<}Åz¤4:CíÖï÷7¥dBb3Ôíh"µ%DÍ,J/Îã14i±WöÑÛv¢e»véRIKûR IXñ¥·õjý_È^ÖÒVÅ&.Ìýü²Ü2SQui¶ø]!Cû^~7²^4snë«u*ä©ó«º±5øuåw?çÔÕû%`¢åÑ©ÉãüjRD>=>ÿòu>i>ÊÊ:##69dc|Vþénmü/®~çú´J:3#Þ'$!éþÝPY]oR®m½$òZ¯&Ö¯SQUQF@ö#Ûá aøè}ÎÙCui±b)f¢y&¨D é*þn&NSìÓ°%ö$¨áTò¹^%\ ýÖwbIlI{VTeùä§îjÅçÞ¥Ô:± Ø1µ&óWR÷ñþÑùùÜ>2 ÿ#.#ú6q4¿~¿ù·X30~>êí{P?ëF(¢,Ö>_#6à3~Ú#6 ï0\îrfÁ«#6CõÃü j1T,j¥q¾#6Û6Od'@h'Á¤¢$Kð²åª¯1¶ ½ô±ùË=rÿ2·æðWÕPÅùw©1P°æ(óÚùP´îÎVåRh!0ÁVñJ@-I[ú¤\T(#6N=>$o¿ï-#ëüþoÌ}÷~?©¿SÄ>áçú}+ãäSÖyà-[O¯?8Ñ[úF©î»ÏDÐÏcÒÿ½tz/º~ùÓïá7|çé6`¶¹ðÍVúö«Ãñ˹G8©ç°híýqpä"#.ó$`{zEÂêVsãbÆG¹ÄL¯<OeпõIGá=}}ô,k±Þá<öv}²#.¹iÒåýº{ã¶+¦p±ß³0éý¹@ÒÍîÎÃ{¶uÁ#uwDa n'ª@ÆpTÏÝc#æPOR1ß@y÷^¥ïPÊí8jßeÖÑnvµåô¸aËA¸cüU&dã#6V]#ÛêG²S "Í÷ÙKÎw-ÃÑ4¾Pdé9ïÏåp.Q¯~9ra#.xR^öseH»q(â>ýºë9ÕÜ{Ϭý°±øï½áäÞQEV§ì±p2/Xu|¶]æ¢c=!U%äi?Cù CØcX¦ËìÆýýøPRv²Ä ¥24q`Þam;ÿÕÛ¾×Î_\P Wë¾ëÝ2ÒÓÄ«>îþë¤îº~¤>¶=TM@òjj*©¢³ÒB''%=-uûûHkû8ܪpÿXËؼ¡&>]°CÒp}!é8BvþZ>Ö-øÛê¶*äÄǸ$M®p9@øIHg2q#.SýuFfÑýÿ3ñyXx{Pî-ô2Ñ°oõIöO¶$¬'Ñ¿Æâ4ÊÑÅ ÂCcíÔÓ×å óí5±y¿oü|zÚ1QÈøÎóK,,$o_»Cd ÌbWά¯¥éÕáZ¿V3XÀÓÐôü¹CE.}<åÔtÖv¹W:ìN#K»aÝÙ<ïíáËXÿZ0þ:4°4n'ô)¿©cç£*(ÑZ1F ©ûÍIp[Å ]E}¹ýææzï ½ÔÈ@x#Muaͧøô÷{»þyú¾oÓé6låÕTÏG7°èôÓ6Õò}Y]ûü¤~zú)ùí`¯]$Æ×=ù\¹µYÖïS"Ëàîýßê#õoÛ}¶?=º;~ÎícvÏ\·X!kÊôCÍ~8ED´Õí«ù¿]mRáã>^Õçá&÷_#68êpbo×;ëvدµZSq§iûöÇ÷oöjíôgËÈmysrËG÷t{vÇh²à¢á`×æÒúôÏG7 m óSÜpa»£:H~ êþRöÄj9\RAï·î~^ÌîéçÇ]%="Ëùé»íxâ¦É hæ^LGëe#.·s-ëÝÑ3Ú÷ÙÌêÏæ|Û%n³¬|ðjãWuzµ}F×péÌ°çþS¶1¶¯ãLSèyµìÑ}í{ù`-¼-§z9Ðó%[¶5¡v»º½2Î;§'D?/Ã?ÀØ}öÛfª]wT¸(9=E)#.]ÙYYxôpaòÆÁ¿E3Æ£Ü0¹ÏѼF%Ì.lAÀ>2.sºUÍ?¯Öç½F6e2w?.ì·Å¿=ÛüÇn¢n;å"^¯Nù]¦ëûi=Ü[ºó´<JsCÆÉÝác!» -9ý6G£M\RD8½;ä¬Dèà¨Xhÿk¬1ÛÝîöj|G#àef®zu?|{?b죩]÷<qáóØ2óyúW»î4öùüãØìsfö_IÄdaÀíÔ2²#í·Ù#.ªú«¾û+ôçñé¾ÎïÒ-«alÙÞ¿(ô/£#.l<tìß+{t¤3.üÂó/°Ú 2´@ÎôcL|>y8bºwc|{a²rÜÞÁÐ#gwùv[ qýª$R¿Sú>]ÚwæÿÔtf¶³×ÖOåð{£<î¾ßÇKjØtcú ®ê]·yïìDZ¡¯Úÿ°Ëà F«àËÕ¤pøzì¡Aó:Ð}Ù"¼p+QÕß_«ÐÃ^/±m&îù<7;(|]oÎÇO%~Wûß2lS7µ|r¯ýæï»,èávENJÞá^[#=6{}¶uým`óùÌ~ÃýîÑÛ]nåÌ)ÖÿîËÕè¯m¶ÿ£Ïª£ò©#6ù¿GFqÂ^FÌÒìò7ðü4µ?w·ö¡(?1½è®ßçõ`¶úO·¯¯Ûï)ÍÓ["ïÆH#%õ"ÕËÆÐ2Æ P~kZ#%RE¦)#%é:³»ÿ£O2ìôý½£<Ý~¯Ïî·üs?·åõuåÚ%÷WwPì»4ô¿IÛø×~÷%IôiÓtêüÚoæòº³¢qüµiA£ªÇçÃ@ïîøgÕÓùj¸aõv{À>ÑÀu.Þ?üB Í´t¶¿®gºç*¯õhÛDAþóSöäyGÇbeÎ>Í_ÝøþÌ)Ón¢¹8h¾>#.[¿g®øÔjý ¿º;¾0v½=áÑÉñ¯ìá¡>1û4ðx÷ gP#÷h÷óñÙÀpý_Yõ¥©Ü;ü|PåVQóñ=ê?~u±ßåmAì#6`¿Ç«+¿÷¶ÔºÇ%ð#.ýìóS³÷wt÷/vÎná#Ͷ?!b¿pv ùlîâ¹ù;òêÌ/Ð|S¶9¢ ãþ?»"(H;G¾÷*t<&/»éÖûçëGK÷Dj`àõç9K#%#61ÜT'&D¯ñª¤½[-2è+`IBfH&ùÚ~;AÎwù´Åð8,È¿{#Y^ýÙátÁôMÏý®7Ü}·»,°§EÜÜpà #.±JÔÁÐúìR#ÕÃîá4¶LÜhâ+µw».©ÀXê%äqh !ô¦ÏÇ~Ièù}A7®«wèüº!À²h;ÐÁà·->ðÐB)ؼ³»¥JÒ®Ç>;ÚëZÁZ;|%9µdCPSx½ósZËËgDås£wr×+)°±¶1/1B+SéÏkÍÞ<k«ïQ}=:ÕѧBxóÃ&ýÇï"÷´¹8KÎ.óÉÞiYÉê¤kÍÍê BI×eWRÍ ÷z4åµ%fj|x¥¹êÎ0Ϩ]¸RÃbo£<±Ã<âñrgóa^ç£Ç¼;y-¾çYð&aÈI$¤í" :¶¾ 8wÔu²æ\ËÆv³i¯oM°Õ¥|Yïæ1xÑÀ{]°2Çã×^þa»Pëø-z×ã¾4-]»l¥_3T¿*|õ)8óÌõ:aÎÉ>·_!(£«F+~4sgì¶W×M«°ìÆç/Ïö´©Ý߶£Ní3¡hl3ûÝ-ÌØm=O£Ûóp>Ø#&þQ¬½0â/Sß3 þ>mM©ñw÷ì\î¢ý\}ÿ$Ùwü÷y¡ÔR$ìØú|¡ô_ÓIØÈDí'¶1ulu³L×ãÏú[=8á'x¿ôúè3úA¼#%Éé/SØC¡I%yb1ÖFÉ¥Góü*åbGѺüCª öIO4|ÿHï½cÀøò»ÚcY|u·>Sþÿæ#`ó²{ÑÊÌáþBÔfeÌ©cv²Á¨9G ?G¥F5¨4iTlT Ô¢¥nØÐæ7#6ªÒÀ¢¢,tþÍÚHÁ¶¸}=3´Ö¤On`a´Å-À¦°Aȱ¬a¦ILA«"hhn)"4±[VWcì'Ë#.Ss¬6ÐÚ]&6)":ýº[ÅÖ¡É \6öB{qZ8dÚuýÿ¶ø[Ñã"?9ÌgBPP}¨üÖÊS<¦³ =a5þrÐÍAÉ]E··cXw\1´ac0]WëøoýOSø\ýVæ#¯#±E4DCÄHèé@Öbï¡i7¨1lXT¥Q&FÈCV ±6ÆfJ¤ÿj*P´Y¶Oà9þ¬éq·ßåñãrÌÓÜïëûpìA¾öFþÞi|-'Ôl³D±çj·UuwåËu¾_ ãÉfºòöWV¯Ùãõlò:ëôeñÖ1ýèæÕ»ê(¦áLS·ñþ>ܬù±ý9Hþÿ<·jÄU±Ýmù}ZbçvùU²«&¸ê²·ü³×íú¡[GmC fj#6#Ò$pçwÔ]uGÜ<Ý~ßÓø¯Ó§Ù£O«¸¢Zxûþ#%8g#65U6ü;ܶ>®aL~ØY¿w?VPèÁwÙu~Uwö¹\ç3Ü®ÀÂÐÃÉÑkøÿ.¬&5)n|?±½¿>¯&¿án®nàM>äM¹¬ýûôwL[%û"ûBßæ<ëά#6)_@è¸à\S¼|8¿ÁéÎØÄÑ^F+rEµh[J%c§lõX*5¢gtõu¼^´yçÛÆ9ÍfRÉ¢((©[\0°Ä£#6 ÙiéÈ¢ Ôch¥b È£°µÂÂ44W VR²ÙÿÒ£FÁ÷R\æmFAKTQeBÑlB#.°QtêMæîy3wä%r(*`¥2shÙÀX;Ýg6®¶JhÇTChÆ%8Ì+:ª-!ñiÜtu,¥µÌà#.óÅ!ÚÐ@AFþ§YÙ¬uD³mé¾#.äQ¡±$I8ì~UÒI#ü,D¢Ö%\ȪrF(3*®ÔÊp#®²R1l°b¹ÓòJ®x3¸ø!U$IsJCÙõCID&é½ôAô;/ôôÆNô}Ë ´íäë-ûLH ¬^Þ@ u3ÇD>Õ÷z´ö#.QùUôhÉz°÷ýOT=¾÷góxá$g±SóPü-ÎÃáÉj»#6ý£×£LPL*øý§f¶£Ô§ü!½ëÉ3§F9û§ùj~¸îîh¨xÊìÍcÔºåøËãïÏ""'NõOU87«6«üVûúÖY´¹ÄÞÏÇñ}NO#ûjÒõ@Tõ¹â9ØsûÊvA#%_ï${Ó«ÔVì6TÖÙõ¯=óø~ç{àäm·l_/ÊÙµÇÒBÐÄ'pâqCó9Ëèæ÷¯!üyI£×<³ì©«.V|¾ÇÕ!檣#6u¬êyÄC¸î'·>Åþ¹õüܯ±öÝAe;6LèǨ4«9ÎCH¡QH2t2wT9"+1r_uLUv¹ähì¯F¬ÿÂÅêwf\F±>[î÷QâZ%T» #6ÏÕ¬ªÿM[hÅe£$#ܱ#.D¿ºÅlÅ˦ómòØÊBYQYCFF¶Ï7®_ËäÇÝã³áê_{HUuí;wùüÿ§OÉAó¬º!BAT1saèsÊ,¿] WÚh&6p¦41-6·nÑHÚ)¬1=j ±o\ËAy©Y¦=ZﶰÌ#6Ô«ÉgAèpE30ËBH¨ÁV¢À*ø¹¢hâÒñ/mM}RdCÝ7Ìy#6Ú´s¶jdßå$ 8ÛAmb{&ãìͬo*©H¥·86AU³àrYbÍZ¨¬ÛÕ§hCZ¸ÆÛ 2SSDÍ#.H#6J lXdL1a4KDã#.Gí3³u#.Ðá1¶¡×l°lôÝXÊ-m(Uz§ûÿñhÉäø1µ(UX¬0âØ©DlópÈ#.Ìi@¢OlÂÕ·åtS¼'Þ30<sÁlPt⢲o»ø¿Õæ#6 !B#6-ê»o.O6öÚº<AÿlqgºØÏwìèõfñf4ÙËÆbýÖ}æSuT044V\áÿwáîÞ:ÙìÛé{yзc(~Qïɨ<Þ O û¹ñÓÍ«ÑJtzAíÜ'ku#%ùÇ"#,,6űaiUSõÒª4ã÷]áv,ÄDjGH¸¸ÂðâÒi§O®|´°UdN¤G#"DÔÂfýV5[ÒDê*#.m4&Wç§(¡ßÅÆ_t5³ ¥3MéСÅA!ðy½ÀÐÑK¥¢#.T£¡·ÆóÌU:¼]*«EPTå·ôùdì×k»¤kmó0¦T¨J5Ël$2~ßØ?sÏêê¿g¯Ì:?.\`<<øâï«@»6ñ>\G¯øøJ½µ`CT<ʤ2+ri÷M -+A¸·Tc£´øìz^ǶòÅG=Úæ4Rë«Ùî65ÚatHǵ0 óFÞG[q·º¨ÊN𮳠þü¥Å¶<ª¢¨6Ó®Ç!#6^¹"XÞ<(²ÀÐk]o3ÆÌÀãH5KK¸´pLÊ,°¡+&°,Êp#.#Za¿*V>#%ÐÎýhÂ8pÍK§9æe¼õ².lm¬8ÁV6>d4#±C§à¶ÔAܺÉ&Fèé ᦦ¬ÒKbíV4Î Ø=ÕÝ ¸Døn$DN÷»A£PÓ+gbXÌ®çFPá2-îc¶+P¥ò)2ÉÂ2+ç*³v»öw?Ãzwò_Ûü9ô[ߣo×ûiþnþAý èyÔÆÓýb'j¼ç3Xtß1ám¦,¼3êtäzÉù~îìa#.6uqöMÛó¦q9°gì,ªÄÊ;÷ ÁÍS¹(v-ª ù`kbô»6ßV۾ϱ£)`åÈf=NÜRäòAUHtF¨ÚEë1ÕOSxWxe¶ãjh¨ô©Siyiºf6äÜR®©n1v6«DE¼ qìT'wÜÏ.gÊh#i£^ÞM¼h½óé¶3`ìQ±q&Úri3haÔ9ÙÆbX±AO}`PwÍUí«3Û¡~ÕoÒ_ÇúFÅ°¤<N=¦,Ü9}Ð'pøF_smÕA#6#.¬:M³±¸-µÉ°àzÌ! 1IË(Dâ8ìMpî@Τ2ìl+ñ"V½Üq·*t;$î§i¨Åo;n3Ù-Ïu#.põQ boyN×?u°L #.¹}#.IM¤$Á x¶ï)Ï®v¼îѱnú¼ Ë@:kï¯#.K¨iccndëÔªÞAåj«[ÉP]ÃK©)pU7UØ"wW;´ÇÁßÛÄ!ÜÔr7 JQoùŲmÛZé\¨ÂIAÆàQÞ#6:26#.]î;ñ´ïC®â¶£¨ë³º ¬ÌK%c¸Tnq°QÍ峺mñÙºâã!X ÷Ðk¶Ö·ÚåÇF=ˤV¬vNSuÕÑÆs'&vl©4µrÍb< vjN19ÆbÉÃ"°Ë0NrcZ6ßW$ãdB\ÜÖëwl#6Ó¨cÇ.Ûldå¤É6µ&Dm<Íc/³Ür±±5ß ÕoÓ:ÙD$âoµ}ä«ÅÇy溽<¸üþY·íhÕ@óμKaNâÒWGiÝ/_³ym§,qGr0÷GÂÜFDdªõçV×¾¿òÜdIÄäF6$«,© 5·\m4üb-ßöÐTM^í¶"R§".få½ÿ¾ºáwu ¹RM|an¸ê!Ô¥ÄAl©·KÆ<F°´¼)ÁF§P6ø¤,½¬-®eß4ð¡RàoNYyÉ\#6wæïÆ·¶¨ÅÎîn,ÿ ÒÛ§GtïJLL kÞ8!ÉLº÷m?oõxtîåöÅa^øñ×4@üÃe¥nÓ8¹búÇUÖµÕim;'Âyhz7,íÎ+¿öÉ«þÇyDCá÷TToÁ89I°Y¾ç´<ß\±`%dn½;,ù²BÂå68ãu6«7'}ÆôÛ^÷YtNÃWdÓ;=ä/fRͲºòc p®FiùUóísk[áü3¦¯²77Ð{¬1F.LÍÔ4éç¤<³§n#%·SáGFÓ9fài©CÓzÒ¯,6õbi#6aÝì®îÊómàò7ù¾ÅÚOf#.5Í`ùfz×¥qaôËÊǵ¦ô»u×[A(g×zÿdÅGߨrt5:Ú'à®üc´vP¢¨$ÞìÛ³FáàtxÃù]L@¢Ùù¨öVA¬^yw17sGqìAÙÉdfÒÒ_Ä£¯Ãó7n·hÓ'²8u,Ü.¤ñy¿0t¾óO`D Tò#63ɤ@ºÃjúP3<#.þFRØ/(?7óGá:ix¤ú{¹Dç#%²yþ¼#âôØ¢8=lè{ý}å¥r¸¸éñ¾áç\Íï>ïø2Ýä¹ÐiߥþCÒKíWnר>áüpbx_9³å¬×WÎ@TÛBðÑZ·¼Bìb>ß_§çcOVz|ymx#6fǼYJ ²-Ê 0#6@wßwvOóÓ®ËÒëÎ!ÞöxnpF°Q¨#%²Ýj«ÀÎÇ·e#1T´ËRV¡Ö1(3È40° cpç¯Tô沪ÎAϨ9zâ"3áÅNÇíí<·¹ycÐrv>óZªQà:¹ýí%ÖÐ~ND|²EÊÉ´à÷Ô%¸< &ÙÚq4öÁ )UyøèÌùÿ_óÆu«޼?ßàzg nõ¼;qËô;åÞÒ&LÅSå1ºúeÃyg²)IVì\.Bm0J°þ[qkdÅ°ó#´-©`®Rb]8ð3ÏcÝÇÊûO¥]ÝB$ÄKÁÇ|\ÀÈ|jÌÅg}'ò$ja±áêȵ¿<4Æ=6=&¹|§ð»®6 ]ºÔOvé¸pX»Ü=ôTÖV*yumì +¾â1e¼#µöÚgDt,DãFQiwqlÞäÀþµ#.س^O¢àô.é¤îÝϪ-ÇIÐ÷]ÔAõõ îÆQ72I8ïxLjoLk.Ë¢MDz=ýtï&½ó:o$48;!Cªpóa}j bÝ94gÖ|«¯3ß½µ4#.ÒOè%èÛÔØ¡ñÓÞ:Î<4ÅôE#.54òì3R¬úTW-Çðk¥³øyçÈcUéN-<#.'çiké;!:-D¤§ 7)%#.M;î·$®Â÷h.ØCpíJi5Ðéï¬Zñ9þ®ß#%ÿ7±CðÉêpC Ï#òÁ´ð ü¹ßrÞÓ¬Grɧå¶9¶EJ¥ÍaÕ ë¶ú`xf¤-0è´%ùkö2#¼üx#.|^:+Ð ÒÉùÌÛS9lVoazâ3!m²< ¦y©CÞo{vþ|eûüÿdQè¶F÷T½Ä½Ïá~;¬wÚjl.r<0XîÍ1`à1ß¹iê1æйºKj¶Ó§\¾¯å;ådý|:ó»OeÑ¡ÌìÉâcs§ãò²ÍcâZøô<«LÁQÖE-¿Æa Hàòµ0·Nõ3\JÜrSs t UýÒ>\}[ìäåúÞcríàXZ.ê,¥¯Ô#Îfi?ú'î¤èDÁµÊ©æÔ÷½`£Ñ@¨úã´#6oÍÇ~ÏhÊ0*Ü×ã:Ö hïÿKC¼i´Î|½_ðÍÓÃ_.¼71¼§½Âu"¹rFxôâ ç#LþÒ¹Ækyóé>Q9¬Àȳ÷#%hÍÊÈ(² ¨+fLmìßãh}ãÄuÚBN[ëR fJé{ 2ñªA·Pjפ/ñté£YÚÚ$ùyPñÖøêúë¢@ )Õ§)O~U$BO3âud¾Û1/5¿<k«æU«xdí¬½ìu¶ø¦ta>y6¡û5ÍNîQápNHèºeò¸è>·D.÷*EdÌn2,Y(è¿fñ/¥sµÒñDµÒÓôÌØЦwN¯®ÖIóíîç#.¤PBbÛV¦u]íUn=Elã·ï¿>JªE·":ÇÌ[~ÊÚÄ&ÂO¨ÁÄ)%&UrfIJNgq¾aCF¦pzPvß·SC :l#:=ɪ/¢6<ç0DU¼F9¦îÅR3}m¡ð6£y)¤8Õáà7Õ¿QúÜñeìî#$ã\¦Æ§ò^q1®J=f3£ÕÍkÆÝ$·LùÎã{¦Ö=Jìm&@×vµÑ|^m÷"Xî<ºãcèQÕ¨RHyrÕòá#6̪\hlæÏ#6Qɺ*h9·¹52g(eG=¦!B-½FäÈ= *\¨½[=Ù4³Ê ܧIm¯Ðã¹Fo%ë*¡açgþsé7s¾ð¤ß>üç:¶è$qCñntl ûÜÂ=³DOåùÅ@à}Äýó;Â_+'ç» EFÍÇD_½@Ê´Î/HÌ(¹%üñãÖÛ~!ÞʨÁõsÉMªG4E8yKåÒØÚ¾ôc6Ãä´ÜàÎû6vâv¥l½Ë#.gt>";¢ïm¼Ùu¼,ÉvõutÁ=;2hä!0ßH¿(âÞ}´s^G ap%N=¬c¥çµQ»<dZfÛêïÞWå=¾ïy±[g|̥ÿi¼å¤2ÖÉüLøÅ7¯#.¿nßF0r ðI8TÝÌ·6µD$M/#6oñ@üÑHÜ¡ÈYeV×ÛrÁD¨ïDÔ_MºpàütC¯y°ý:Ç1_G ¦h.:üzÑÓ«&~ÐbªÒqëMN6kÕmcí99º×ļkgX3sS§¶ûtc¼/+ÍìF!ä÷ø2xìåX?]¤BM#%èìùRÔöÁ3. s®)©³ù3F~~!Äi9þ×8ÁIütgHC©B³Ê @éFº×E¸éÆÉÔtÎxêýbT{ÈIZkÎérÎ[J(7ÕZÇפÒé½¥°ô4%ngW³U¡pÂzÜÆ.D c·Fó\Ïå¢ê ÑsT»f«øW#6/á9=jÑ´S¹eEØàö¹ÑãÈB#%ÈX±uÏÊÖ¬N,&6#6Bõ=p]Ù#6f§|:×D¹aêF/þ¿©+6Í|Õ,2Ø'7;5mÌ©ÙÂû]Ü`x¿2°²k\U_v¬X)æûêëò°,àµ{wï ñYÞ%åq\jµ|ßxèªÌÕ,`RWn²Æ°øÙÍËM0º <X5 UÛo6<-¨Ç)d^÷Ýb#%ûðçÚ°ò®[£±õ¾·>Iz]¸lð«°S·#6eh´³$'°´¬çíHf#6^Uî Ðt..k¤ö#.п4âî6zÛXÛPÅ¥½\9Û1mðR´t}yUQ¯}[;î¨Æûáos-÷À<¤¦TvZ§H¤sÄéïã寻Ë&?ÁßÆf}ôèÁ>WÞ³ÅøÕOÙwbe'½øëåÆqçtÕÑ_I&5q¶"æ¹Öçgõj2àE°©£½"*[WÕn¬2¾ëAá¦ÐM*aFkmö0*áe"ë²°I@.µq|%hy±gt>ûõGÌ0ÍxQ¨ZQ]~¹ LfÏ9ÖÑhjÀ®'»YtX?PØçÜôTðQäj?¬½Èo]YQµfÐ[DÔ³áGçtP?ÒóèþØÎeϤ;ûmð÷\ã4§áx§5¨íÍKèÒ@¥ÛY ü°¡³([¥uã`£"ñ%K ¢%b5j!®#TRé,Ы©ªö`A¬5w,åu1 ¶K#6¯uÌÍ+;¼òzÜÇEºâko¡.¦ùÕÏVÍßÇ>ëä(úXòV÷9Cg ôuª<²w]ÇÞ7ÆðÛþë+Þ#6~J¢ÖÞo8Ð#!õþ³PJ#%)W&8Ø9¢/ï®Îo7v°Ðv¸-õ 6âm¾æ¤C+«WAz)zÄêéVµ{Ñuå|NÉK¦Ò¥tßËòܹÆ"½E¦/séÑWaƺ\T:Ü©ÝÆðñ#%̹ÖovJ±$o¨e@¦ëtLE#.õHáÐæxizÎ@pßy¦M>úgV0P´¡ã/ïÚWFê ªÆê°ÊgR0y¹ö\÷Ü+nS×GJÊÕ^I¸ºY©}ªëÜè½BÎYC;-|CÄDfVsÖ#%Û5·\a?Æ ÖÖvs>×_Òë5Fó¨÷ypfÝuÓÊ#-/Í\¿Tz>#»¸dqÄËÍKÎ{e¿"ϽFòæÁ³Áµ@}#6#6pÂi1Ic¯1¡òª¯ÇÃ|èIm'T\&IËlgï´µp/jº~?5óÎvÝ ææܲÓ5b7fÓnºN3[al@}sÙ _XFÉÆÛß'mÂ6)k4ïÞ',Ö#6ÖKdÒUÅCÞî £¬ô#6F6¡HDp¢JÊ÷ÖÚWSä²R²sýÙí~¥axÆ«aázß5Ä7¾m.mí*E¨$CAlæ¦BIm*øÒ¡ò˳5®Ø45ÖJ·jºï9}æÖÏxôHü5Z¸Q<W÷¾»N³VDÕhU¡|ãf+ÏÆ<é¹v^-~]ðBäA`Äænð¬W éÒô>·W«¯êñB¢(P%¶ÃD7K#..mØÎÇئ+Ô,#e3m{wl4º/}úî}¼ÎYðsEÞC9H2¶±tflkA²´ÕM1C,áî `âlرëkù´OIiN}¥áù#6nÆ#%ààÍA^³(ÆÀl!Ê.±o7Bù[8fX»HíÚWzò2ÔÕså@ç¬É¯ËjÎc¯oN=,qkóPxÙ¡ÀË·qÊX8~ =Þ¡O½íÏÓ¯tÌqÁ8=þø´¼ÂûxÔE@é#%ÅmpÀONгÏaj¬ôe³ÊÈTI*xzÊÔ¢4äãlûGüGþÞtÐqͯ5K¯ìëâì·VÉxdÔÊ*W6XËSm³¾$ðH/᦯°Fì¤øSÙà<?zÌGP-;yZæOµD5Ë·gºë«iTÖêÏéÄ2 Á¿ryº~NKûôøÌGâkgÑêv|¿Wç¿êþÆú~xøLη²1«¨\8û}ÑÓ®ÌW¯Î6¼jS ;TǯOmæÜuW<ß±©38z%~çrý·ÙÄ¢3̦ۤïàåq^úðN¥gÑ'u±k//u65>Q²{Æhe!wº(¦±Ï]ºÈc!ïÂëOZÏ_ ÍÓy©1L6ðéP¾·«>ºÃezÑa¦ö_j¸ï©~Z^¢iJáÝtQaè[Â9ò-QÍïäzí$o±ýL÷æsaÕHR1ÒTÕ ×¡Áâè*aæu®|b¶µïææyÌ Ä{Sê-p5cÞ§wsÕ_LÜÂGËÖôöû©å¿¦àc}± «ûû5I³©jJ#fع¾ÎM$rÂKLîg¡sß9a--JÉ,°ã¾õ½`¤Ç|ír]xä+n/ÑÖÕELm¹Èb3ÍO]aÓ(£ì!^\CὦÕ-(r"ÇFgRÒ¸nX٠꣥ü1½+/!ÆÃ6d#6P ÕdØIáÇTÁHS{ÚÔbÿ31æ£ N¬ù\¤ë`- xf<3·¡Ù#6 gî®Þ|Ûc$âSâ¹@ág"Ä ÀÝ:9Òà»Ý.mÚ¾|×[6âjg5sÍ¢ðºàÙ½KÚ=WæÐ#%U)Aµý³MU7/Îà³E³V¶û³õb>|ÔÔsDD°#6T2À¦yÁq¢Ð²#6èü¥Òk1~6ñ,Ñå%ØâèûgûK°¶"hÔi2Kú;e#6é f¼¬T¡ÅX]Ó¦hvÍÖ°NZPqîWP¦õáÐä²I¼|Æág¬í÷i ã¢\ÒªÊaîa·Øé8ºibP» Jr¬ÑÑkLØ0óöÖë¢vÝ\ê£q!öytØ :÷Ôܵoû<£gÏ=Éo6¼IÞbì·låHÜCZýn±ù¯Ö7Fn²d»Ê¿_¦ÖVMü£cî:v¹+F;³Ü¬)&#.M'ÁÂ#.˯£¶b»ÀYÊw:$±å½À=ëZ×û°' &hhmZñX\Ë,ÊÙ9CÆçò¤!9¹0rÊÜ=Þµm©3¾¶[ ¿èZÁW©T·ÈÞÝ+(a19ÅÌáë<¥Ñéæ¡ÜvÅF³Ôè©xñè~ÅGÁB UU(;}ný½º¯àÞ¹Áµzoô]4B:Ð=.®atÏ$³ôÒeJûäí` r=q`ÉiCÂJ¿ç¼øD¡ùâÓÁ#.BY`åfYB¢òó¿Ay ±U /v¶ /C3¯¿±òÔ$¬sék:!ßr=®.ê«Y8=}«[SdÐ*¼¡÷M¹õ(ö´¯RÔxÁ5&¾GÔ¢¨)´èÉÄp¼Ió{ ã.xGtÆ¡ÿ',©iAxdÙt½×ôY»7ÓFs<dçWÙÕÈߣlõúÅ`)N}ÊèÍfK¸H}öC¡ó"qÝQ/Dq×hÞ%YNuðùËûaØÓüf6¦O}_+Ës$õÞ;öçzìm$$L·LÑáz¯bòþøË*'%$i:tÙc£yªâsQi':-'·(Þ`b6<-ã8¨ó.£uÐé¶ïËmòÚ]{¿ÜÞg·j9 ¨ ^æJª'ÎæÀo}Ò¬ÑÐñD-W8g{Èm´qnáêkÏZ9æË9òïùÖ, Cü`ÅN`[£½Ây#6Z=Ôs'´WïÏ'dë¤\¬ù¦¯ÇUÖ|MÛµÃÑé{ùËzürE÷õntwæi0²J:Ìñímã¢û åOäzã-¹|o)#XÔW·>ÅÓÐs=o¼[DØÐunÄ2¨æû`Ü1ÛNAö;ñoó$³¶¸x<¡³EüqÊíêK/¬ÙßbÐK¬/aÑt÷h$&c%n×çl#«'¬s¹â(éT¿·iاۤªËò¡^v*ø1Ö.)òFÅ<eZÝØxA)³NTÿ(ÃöAÐ?>?Ná_§X#6ãûbo1QìÐb¼DzÞÒ¸Û¾nB¬htRßM~Þ¹¼çhæ>(â= 6º6Mº1@ì|]½fÏ.×ösÛ(õ::l¬züø³jîOÁk)¾pVzקk÷û±jÔ3pV×>IÎf¥$Jý?LV2e*¤Xpå¹³nÈ(#2òY¸zk0Ö9ê<õ-w¨õ°u¡Í¶lÂnIv("`îTaÙߦ:b×däB®zíGmÚå»#6õÈyh3å³#.¡æóvÏ=ýB´Ùîïj¸+8;å>N¼Ù8dÃøݺÌu]:D£~·/Ò®*©z½pIs>ӾĶ7¢ð¾ìæ|¡Ð.ÝC×oü<©Oz¬Û5*ôÚÐ}&E§xãÑ»ó!½SbGeFI-ÉU#%¦$Ô³I ÙlM,01*Fe`÷ S~S G>»2@×ã¾~ï3¬ZÂË/ÒsÛ¤¸zµkÓÆ.xï|~ñÍD¤#%¼Ûé®u¯ÍÐ*±§Z#.ßËn¾P>¡ uxi¬ëÍÔ¨&'a¼S92)igkHÏíð|·¯`çÛÜ¡àiÖÉÛS{Æ`'+æU<:êI,öæÙ7¿_ÇVñ5îO/Iú~!®ìàZ§ºÜÁáÈR¸÷pùqyàì^Km$?«ÿr¢uà;46CR;,VÒ¤èøu'/0Î?í5¯{íÀiÎÚÞÜsü"Vîu¾ jOð3ýKÉOäýNw³ª¯ÂÛ¦/½6¨ .¡#6×XrpÑoHì~!ÑRKz¹£%dn(è)!ëßnÈrlÔ£§GÜ#DθN5çþwP$È~åtÔNBeåkµîM ÏÙènæ²1Â7_êÝóÞ¹¾?5õü;{Óº'àãÕøÏ¥¡{ùq(#%`@)ïõ(õ§áôáÔç°Ö9Mv#Õ(JL+G;I@Àðèz¼xÔ¾(H)ægëxTWÆ®òØ]÷ào»ýEkù©\ë¹lIi?K¶Wò¨ØRmcÚ-«®¯ñþ5ù³L >(2ÍÊþbFmpßgË~:×ô@ß4>$Ë_#p¼$Å"AY ä&©×z½:Û¬-&OÈÌySµgÎ]ÜlÈþÔÃfÁõ¤^¥«Û¾÷ÊAo¼?ñxüG5ý7B÷ØHÓ\ü¯íN91¤IY[Gtþ#%²©¨qHTi*7+¡þÜõÿËò?¯YCxþöaÏ(¾zÿ~[Ûá_ÚÏ]>Nt©"rNK(ö·ËçzÔöKíd¿»æïðù´!ÚEá¹tîV}ëªÚÃÞíèÝnCiü]÷ùY??Îý ªz¯nÇN¶:*F`6$´t%5®Ææó³\ª#%±|´ãÓ¹þ1ì?£¾í/ÒÊY¡°ê8KË,H|ñ"~¯Ð©¡ýj!#.K©wk|Y²äèYû=v&Sú7åí}f¥h¯P#6ªÌ· Ϩ:ý_Bý>¼s<7Ea§VNKÎõú](ú¶ÅÆQØ/ð~¶w+E@âõL0½Æ\üª"XÉBÌÜ!?_þG7LzßçmßÂÇ>¯+e§m¿Á÷¡Øf c(QÆ#6"ýu9¡Ñ#.P?KóO¹ êL¥09]#%n?øí®@¡/T¨#%½t xÎè"RµK Tg¹L°ÇJæhZ\j ¨µ+r¼ Lt#Èæ"#%o®¡òËÒ(~ª#%¾± ´é§ëãcßÁmÃfÿU#%èõ@ÝEôÿR ðºØÄxi¯ÐþëôBañ¾`Ù8ú&ØH¨Ù6óòP¿XøcÚi®àí´ÇK÷$qý4¹aß-)Á>ÏN99¨ÕÂ5v8ñ:je`a"ÅeOXï2~ZhCq yÏWiƺ(T¾¦Û¿ol|ïøH,ézþë(`L$¼{ 9gÕWR|1¿{Õ¹Ýø@Äyi<×Þÿ$ïèÇòS(òýäOgÏIëÕ¥OSIïôõ#Ñzüco*(B¢Êvæý?Ít,¡xë©TÏ[]3«X(~¤©R#6¥`UMKõ·;ã6Á¢(Ü£Øy·½?=ÆÝаì>©aI\öñ}V$øÁ4º2qÇm¿Êe#.fqpÚiÌkZÔ·ü(b§RfÌ%ݵEÔR1#µ¤Ûp2\4SywE9g+ìôÐmÒü!ô¯#Àè (&ë]Ì#%¹Öië uQºâý:vêÙ®¨ÙJË5Ií4ôýn½2×mpè«¡ön³DAñ|],Ê[#6Øy`ïÄ#6PIµoßÕwÊî,ßlN¹¬ç·Ü"c;þúY³:=±Z&W¨å#6Çf½Y¦ÈÈ`¢ÃÏÅ3×8È7K±´-T"EÃvÉFQ`¹\ÏP.Dp1C¯f¶Öoe¹_}g¶âúà«âc'K³T¢©Ö¨`¢XD$¡\æ#6P8ÌüøÀ·Ì£¾ýtbÓÎOIan0aÓÖL bBç#.° ¶ö]\ñ²òBET dØÇ(°so¾)g®Ñà#.4FÌ·e¦`1ÜL`òyJIÅG§³Â¥ô ï#?øYÖzKéÄ2÷#.ÍÔþ:·Ü7ÃßüÕaÖNQżÿiË2}}Jo£Èú¯.þ³ÊÍýÇÐïL_fs@vô#6Ä¥Í7;Î_{ÉFy"]yXºmý~,@yÆNr+(kîØ®ñ3zL;,"ì¼BN3$ü÷>åq6׿yðö]|'<@¶HZ°¦ Ýè[ï*¹süÚÍæðX¤ßï@¤U-0àe{¶Ú3ÀÂÓíTÆií7q¢I¼y»Î 'íýVç?rÕëHõ!d=1#3tÿe®ÎÝ~AN{º4N¡úÓ× I5Ù(åtD# ø uÕÜ`ÔQP+&Öá`KH³Zhð!É î¾ÉA ê(e<ýd¼þ½eý÷ímÊ5^äÞ¢)?̸Úþñç6`éØÂàäâ{î£Æák¼dVÔ2SÄ;¬7ÊN¤@`wdÃ@à¢`s¤á59_E·OR« _ªzq Ks^GlÞ<й\¡±BóBdF&!Úë\[S®~zÞd'¼¢$6ÒÙ¢½É6NX |¼¡AÀ(åøïÃrã;XËq-î¨ùöÎrI{@Î{"{íLÕźÞ5y\JEã%9×!}ÞCøI(ès=>§X.~Xp^éó{ì¨k±âøa§Ë%&âÑþWw,/òmì¥z¹Nãõ5Ç/mK¦$jìá +ÓK6L²8ª~í1o'\8¸`À- #!C<×® lá2ô×8ëõÍÙXÃN¾eÌü®R«b/!ö¥E7Â5pdp«¬BÜqÖ;»8]c5Ù½= L=«ô7#%í¾XïÃ%3#6¥,4«ã¤"»¹¼±¦ÿòuo8KÔ<׬(¸§E¤;UZÙÃoXÍ:I¬ßMejyyBþBT¥îú#6=q¨<ô,;¢ qÌ·¡Lá-á¨rjß~Ä=%³¿uû:Rcx+#.ÃVe(Jź¨C°×¦m"¯1IÃÉ2*ܼùÎÔFÆ2 ?Ù0¨k˳ßïÚ?Éðý\ðßCc£{ ±¥õ>Ôå¯p/UMóè<g;e#6,Û¡¬ (àÆz¶bâJ ü¼¢®: Öò7ã lG1Ñát¸ù|±<XÛ'M1çIñà/T½])Ïo9ìð_Urb,ÝOèL{Sá_mTܶ§ã³ZY:Tú9°Ïo¿¥ÁƳ(ul;g}m@óß¿²YµCfMjdÕó<#.x³:O)ºm÷/·ú4@[Zô;÷hÙhhP¯;wìÁÒVñ¸¥_Fm¥?ºø2_P|M9Ü©|r]¼½ko{<xrÎdLf¡,z7±¿ßg>îPxÝ,lû5=¹ËJÔé{CTjÇh÷ñbìãc°«¾DiÊî:L$eRI¦ÆÚtî×ãÄtç)¬ëÈß·ÜÑ~tÔÆãÃç£#.p²}wÍ)@))ë 2d¨ t`!.3ØYbô(%D®#%ûtdb#Ð7BÊ©'Ø«ÁYúcþõCµgïîé¬ÔMRaÿ2[þ4¤ ]gbÒ»woÕNÝ«Ï,.1D¦XËûØö¾ÛTÓ<5ÿ'Ë.¸¿¢ª×?Øä*£b¯iöÅW-«cµ@UTÙ #%AýJÌ#%î?øó>ÝÚô¯á[íê{}¾¤aªô·ï«éE aûÄEÃû(ÈõÍüÏðÝøÉöýÁä?²ÔðNxè`ß·¥"lÆPÞ·G?`lû=Úø ®j¹ËÂ\ॣ4ʤAàP(AÍ& à¾Ê0Ax2E¼«¸Mór¹Ù2I#6Q0D%9èÀ÷¯0(^Cg~ÁÛRT:F¯gw÷Ù}}v®ÄT$/d*>Q¾4C´ãÝÞ¨¦ÙÇVÍT«ÅKv#.ïÙÊ[Tú_üúl6q½Ì:ÑAéé-¾ìE.ôñ x4àÎ2²#.±ñÞ|Â¥ÀÿóääqÚ¡K¥Èj#Åìðý3© 2r·2¢ «êÈ#6Óù¬<7ÐêYÖ1Ö$âÍh>GÛTÌx~2ããéÊô@î*%Ô39hþZ[ÃÏù`tgø·Øj«Úcü© Àïð÷Ãz¾ô! °,¹f°ÇÙèd"Ô@2 v¨0é³k(!ïh[YÙR|"h/ #.(³(00Ýú¸ Mm°¶>+dʦ²ÆDTK¥ÊGE´@Å2.¨&c¯u ù8#aj¥6MIFEÜ.3+;bÁ$K*Ù³THBn|4D3¿Á#6Ù½3¡ç$ú{OôÙ«ÂÿHô³i"Q`UKÈ s;$>ª¾5ñÌP({èlpùÈ?)ã¨,ý¾rb"Zô§KA±Æ;5WÚøO´~Ë~ËýOîNâ¡{Zc#1¼¦ÌÅ P'Oä)Ï·±Î£¼M!+½E>÷TöÃßô9¶s¨ÎÞ?ä#%`cnh?½öÝ+BGG%om_}þ ¤M¼Q'ÀwG«ÏwE&h¢æÝnï%óªpmÜ"&ñõëw&©$·)¢rÛu©í³Ùí«ûÉíööñp)\uÆUüdá{KãqÚÛãE¦é]RÎ*8#.ñ6lTxÌ2i§DéÃL©Ýåj22JËïuPݹ3Tj²©ÿ:§Å¦%tCAç0Û³ô=f[ª®Û/0MksvLoTõwe1ð C¹{ ÉRâ_qýZkác>Õaü¬ûìfоáÜlJéæBBér'·;<[KåîñÛuïºä±fÈ«%3Ja1b{Ûì=G\ULj#ERXåncsÁÜrsVÓm;ÃX;MÆV ]±#.Z²·mÔ2$ g-$FÄÆñ L%ð.ª_L©§Ç6íßQSÔxÝ#.I»!¨M#.F×ϪMCêvB¶ð#%æ!qI*Øt§må´Æ¡t:CÖ\$×@0!ª#6%ÀBeV7vdÀ°ò®cÀAÖ©Fvt×FýeÐm6Û¨ëô_^qöÀ©3_éävjá:¤ö7T%â#.aû È3ÅÀã#Dõ<d!'=Ws=Ñá"{Üð±ür3»xXããÑèL#Ì{ëFÅ0ñ¹<ït²'ö(v²¢Uº¥\±ªÞËs[%k·ÁÖUÖÅZåµslUÊ®@ÁK¢¼ªÆ!E T$UhÁ^³¢eeÍq0Qj¹»6x©$ëÛAICt×M4iÁ@\!£{í!Êxt®á,ØècÄß³¡x ltH±h<ûyî̯wy£¥|®3¼¥ðìp§Õ+4ð)ÒIÍ HÂE@;Ð4['H!³¡ljÁQÎ^58uä9^çSi|£E_¬PEÜ4æÃixjRdF[ÏI)-|ÝE#.ÉBÿJÖ¢}÷Ø ÊS0+Zc8VêrØQ5TQ¨[u-¶*£guï«^2÷4¯yt£K»kvË_\h¼G}þ÷{ÇÎNÍߨV I tU¯Ìb*ÂäÚ§VKðfá,#lìÇs·©¿®üwB1óQ"¬ÝØÊN¿]S}|x×?¿ç=,%xo:!ÀI*såÑoÉ1¬J:ò¤´¡eÒB Û#.#%,þ$÷ü9g»nòyϨ7#%&êuÆ$3â6;7ØR71)¥Tð$¸¤¶§#6ø¹!ÅHTZaH$´"%;úQÒ¬ß(Z©"²(MPB0ÛËw@NÕeóñÙ{]=Üd[»ÁrÈnÀÇVoÃR@<$D DÉG׶·-"+joaÖà eSUXò'ÒòB«ÐÆ,ÚºKÔ¸g¯/7vj»ºRK]#.Ìeâ+µÿ|½xzªp®ÞERÇPig>á,üPCªÄ{Æò½½«XÜ©¦_=Þq¤¡A g6ÐO¢¦_*P!6E3Ë87Xd]ä#6æmó±2M#%áF³k#U@T¢yÂý3Ø÷o#ÖÉÐÁfÞî,Ü ;èÎm0T&â&4÷5I$Âpº~¶4Æ1rÍ/ë#6íÙj¼wüXëËh:nxfø|ñÇgXC§ÒPt/yÒ¿áìÍør#6°\ÈÆØÍ(< UTȵ\[#%^H#.}q¨ÛVFX+1á÷D¨ûºÕÓBà#..rªüm¾È½Í¡½Y]Z I¸8ÓLÓA5À×ÏN·Ó0$ÑmÅ#6æ#.Xõæa÷îÙâ.êôå\ºHÜ9T¥w_¥v¢EF`0HÊ¡E%xÜÂ+º¸öî2<õç<-#.áê}ϤÛy£¶ÙÜT[§Ï%)Ý7°40¶ãòâæÙO:§dXoY£t¢«º{{»õÆU;ªR%£D PÈÌ0ì¼Y3#%Û*VÃØq@iãAF®L`àîë´'©!ç#´ ÏAVì#º(®RÐBVcÙ3±EÊí a ¶)ÙXª`_ôÉ X¸h£Dì;£Ûe¼ô'¡4QÁJ#6Q`¹(T"@ çK¨ ®¬`²ÇînÆ´ÝïZ:uY¹í©ÆtFýðìÂ-¢RTÐfµsK>÷Bo¾Hç¼~YÅuúýsPÓÊÑ¿±ï 9:ôY&Û:öcU:çÙëBûrÎ0º>È^i [d6p;÷6¡Oð#.¿c>ëU o*&L:ÜÁÀ.$ó³ôLx㤴»§Õ~àÂïÉ9Àë'tldæ !¤1#.@Ìäu*n&H÷QT*ÖËCî.ì¡=9"E.Ô+ue×̪¤HÈA$}á{;~æJ²\¨MâÔDF`aÝGnJBPÁ=Ù#.ݱâcL¸¡B"Yáî¢ýYÏÒj@=½Ï<èq¾í!ÉùÆÞfl¹c\ü1GVø¦l.o6ÈêûlinDµÄ®ÌCÆD¬ïÁKøµÃÖ)Uf[(8?ìBª± §^fÀ] tJëM/BóC]é¯ è×»i¡^|ÇE7u[d¥g¥ÊZ;KÚ`¤ÆóÈ3;óæï`n ç¯qi8ö×OB!2ÌØCP;Èä{]¡GÊ¢¼È0QvDÝ9¼¥ºËY=s³¤íEÃBî4¶:vAèC2.û\|ÓioÝv®ZFQ4ZOí²i2e67î1kÓkð/#.§]6@³4xÊ3töÕÑøelGͲÍÑ@R ])NýþüueVL5Ú)·é.´É©ü sà7§@4/:UÛË]uC<äR\wÂ'UWÞ:çQvbª§FHRÉS©Ð,wÀ×ß=uÃYV\<wWa"ä¢wÕ÷Èߤ#ö®q¿£å.#8%vÏÏíÏIúu-?µ÷ð·8>ë2RªMÄ£8{ôíåíxÍ]z¨Bì<bc«öz:yÿfáÃçGËhäbV ©÷b ÒÖéZÙÙUð%¯óèQ>V'׿_ÝSÈ2È6½_g¸ñ¢Öåä#%Æð§:¬É©£_ÑÆxÖyßÔ#%ÒéDÙ¯~ªJó$?Ù~~é8f>îÑ=G/ Þe%A7Üüq,[Y§â¿o¹b΢oªd¡Ýãà¶4CÄÀ?Æaûý?ËÉoôÝÝãèßþ$Ý6aH*2AHe,-3ôWðþ>|ðoÃpûgrñßãjËntKç;ÓøÂß%ÂòJMY¨TßzÊüúQ÷óÌ<u`ÔáXXCWKq_æA?ÛÇoMW*ôˤ,«éý£õÿ/7ö0oöÿÛöþ±/Ý8üq¤¬I&Éêe UÕÏkôR2XIlW+YsÎC?Û äÚ¡GþeÝYg ÜÕ|ÆÚ#%$Ç¡µ¨Ãhý[<cOgöNÚk¼Mbf"\ 0íÝ{PÖõÏ?oÈGðª¡)©>p?îüy÷?=BVüsɼcýNG8(´5YyPYú¾ÎÞξ½¢jö«vÚÙÜ1¸ýË}+sk 6édص2½yÛù¯$Ü¡i)_?ï_3÷ÓÇíüûàüéC6ª?·LG÷³û_Àȯ«ï5Mu¹=!£~*+LOú¤k2¨bÄ2ðÏVÞ 7üDÏDa{ª';âû (#jº£ª%3t»¬i×¥¦AQÇ®¬2ÕYhqß´w/ùøã¦Z7¤Åö#6uÑiM«ZÎ0XL¡ë! 9¼zóüª ²zYÏ¿hnÎHr`§fá5©¯N$fá"ßæßV Þ±Æeî>¥?ë.3/«ð>KÔ6½M(Â9OÊK#6=mcÒï¾´'ª¬§J¦1Eæw³g¶ËO õR¿Õó°"ûå m"À@¦D¡È_ßØ_éú«ÕÈqè4é|`òßRì+´j`Q(âL&ÂÐK#.FM=3ÿ§úñ3£I¢Sø¦Ø¥cÒ ÈȹÄþ~î>ÜþËqU×-Ã^ËuèàH19ôêaY?¸NN·Ñ¯¨]ó#.y·Ûßù `2É/ÃDÏàê> #6m*ÕHç<\2ê=|.mcÅw~÷w§`PòMêÆ9^Þj¼=ÐXÂfulDRÀç,±þBpRHúÐÝîµ)_Å®ðߦ.üîÏÏôúýà|Iõü¸ò»ãMJîëáEO×ñ"aÚOA$ÉFï5ýéúxqçÐû¦Fwd;zçСËÓ².'gòêç©äâ|9Êlråó×ê¯l¢:vGÐi2] ³ @ñ¦®3×#M»½.À;Gâ¿9BG8ý¯ý\ý»D=®h¯^þòÖØøÉýò=kâ<RÂÐäõ©DD`_êåî"xKyy+·75¼â]*ß:Îp#%"t-8¹j°ä ®Ä»ÓëRiö4úi÷>áú¿ÀØñ<ÎzüãËçò%LÑQû>\ÿ3pÓ°êvÇ1gío¡¨ÓcjÛÚï^ÿø½\¯:³Hr!i ~ZT×°-î(ÿL½þrø'@Ù·Uì:k¶+cJ©Òò]ô8<Ãr¾É¹Ð#6ÈÔ²¤ìüØõ^cÕgqÁoTÔL#6$8=Ìò<Ë1c4+?G£âòó¿x#.âÎ\ÝZs ÜÀàF)¡Ehs.²`.z´ñòÙ0öªÞÒʹQR~m+í»0Ç._¯ÛËÑåÇC«nè5 ÏutßWv#60èªZ.0òë𷵬ËðSF§NOµN®#.ÐûEÁ¤eûøÑ3¦2J¦|;ìïMmQ³ ïºvjx¼rïJ¹¾Ý~Ðpr)c§~¢;wo«j£ïïÎö1sÑõñTh#0Ò!ãóR³UW×}Úh¥bÍ exËá"æ|PH[ǧ:àJäô/°qDC×I¦uÃGµ_z§ó8XzgüÏN×È:ÎÝÓ¿¿x£aF÷Ó¤ïÅø̺["·½ò½ejøM§ÛAéA&¶²¶®6)BÐ;XGê§('ꢵ¬IB¬×(~ a{Õpß5×.êµ55½.>#b·´Þç=ÿ©]oðÃG§Tmü#%AÁP1@zsÍnál?]ÞªzxkÝ@2 eó*+hÛ:¬¿wìÝ©ÎÜ~ TJ^9¿ Í4hB&¨ï¿#.xbðPýÀ;Ô¢^Æýú}¡¥ØKÚ}´!I+ê@=ªçÏ@-êá)"-±ñ³êaå7&#.J+Ç¢ñåÏL½pæ#.uÚ ýÏó,fò¼5à(ÌTMB³î9ál¡0á5Õ:¦sV6z=oÝür¼úÙ,åƯ÷~\Ý¿£m½ñW#úLvÅÙÏ#.{£PP·6Ú).zEËÃÂ{ï»ýÜan!Ì@ï\Nø絛*}Wÿ±þÉ3ÄÒS+ÏPhÅu·¯cãßmÙÓÚ]<ÑÒõyÅÕ'ëïztW{ÛÚ³êøÞ`Ì«í-XLm#¸Fu¢ÓZ±ä¾µïÿ9S9í¶}È8ß+äªnæÓ^ßn$ÊdE[Ó'}ìt¯íøѵK¥Q´Ûmï·ms³ñVhïU¹á _@6½oÞíöO¢êCUsªVÃú«:ÇJM,²tnOäÛä¼r'Jh±ÏªÁ¬Wè* IJTy`¸ñ´,xÂÆPèL*3(#.ÛàsÇÍ(Ç5Ã.wà~>>j;A^ZÕÂ0MÆÇ¿*vaF¸7Ï#%÷Ðg}lÌÒÌÁì-aÔz3urî#.÷?̶#6!î8P¹ò-ã¡lÕ]EïÇ®ÎZØð[¥ðRÓºÝâH53û5qµÓÝ¥¡(¨*SvAkë«Ü´iXE¦ë%qaÅn_#%ÑEò¸ÙeÑ.g}H#lkÓ>§.¿ÙÔ¯-º(2}T|pðÔ=æ ÊÓm.C:)]úÝ«ËÛyï§ÌåÝÖÇð 0«¥7§aÝçYÑóÉî®úÁÛEg'>±E®LNïzûë1Åè§âßÒ(íÓ\x¬ëµÎ©êwõÆiYئóãÊe0wóÔ%<Gz¦÷Z¿±aúÝÊéFK^Ô%zd¿M½5:îRª®cw×{Wô©hØOú¨o¯¾½löyâÍ$®¨¯zÀ0§mCÓgÀpP®¥hîÒöUA|ÊÀÝ!=yy©DzäsÎ9UI#ºêI¹#6ÉWeý¯gÍóz8V)tÇáFö®úBÜXöãfñÎþG|Âøoí.lì&)ÄpæôëøMSÓô5#.2sQ"Þw"×ju÷5ªNþº7Îåí}uKfs=}éØzÚ_C¿dlO¶¹²ªrú%§Øçß#¤¿|*¦góßsg~®ÉD\Ízw¼Ö~h鬻{xHgPî6ßÂ÷¬8¹ãß³Þt[iÖ(N ÒIÝôпÅÜSm©ÁwtîsÄ:·'³?¬g6ã ÉÄz)÷=nçЯ[JDqDQJhµ<Â^·gPáñ%mÝäú»·n·=3¼ítd2ïäËÉAíTdýúÌù^sÙoR×j=µì\å,c¾-#%¯Ã³x©©; WÍxÙzëX\µÜéó3Õ] ΰ»«K^ûÕGª1Õª÷Ä¡k{¦1Bϧñ êY±£]é~·<ëí¬«%HºîmÆ2¡´¸U\ E\¨¥D#6Ö©ýè¥=ÿEÌã¶ÛËrëïÇYòûáã%»¾f=ÞéMÞ³KÚtZÓÈ'l8¿8{ß6TF=Eò|"#.ßßUGÙVmÏiûY'.þ÷Æ ´n¤(¦Ôh³ä\jdäW¹MØ£Ç×G¦XÒ|^uS&Æ ú]^Ñ]s}§GPWé½ÉµùÛ]¹>íîæ~çÚã¯+}ß Ùî"6ÃõµÁU=c¥Ú8j~>Ï?sÓ×Òs Å"Cqv ?·åN=3 ÏDüÆs\ùÿ¤õ¤=§¤y-&*JýöãÃ[ÔÛwbÄØñéûDfNÖHZZÛóJQù«¿¯bÑÔ|¥¨Áv¼ê±¤z(ó±VÖÁtAµêq¶#.èÄø6ÔÔrÑþú#¸\ØÇÖgÞü},#6ÛNjBÅp®~ÃBYÅ7àÅË;æßO¶ïÃß« Ä* Â=µ³\Fv©êÌÁRÚMܯ©øeàE\G)×ÈLÅ<ý];8iÉúÆ££í]Ä ËĺÏY\6Çg#%U¤{Ø[»¦.I<:Øg#6¨Q.AQÁ´7漯#üá#.¬h;û!]X0ÇÏçò¸mgÝ19ÍÿèmúH¾_HGYÓ¼Ï?N××wíQ:)þ$ø/KyÎi6¡+vJ¢ÕEB¹@¸ÊÆðP¢úz ¢,¡ªÙm¿¢ÛiK»eïAxý1_®ùS4`÷³ ¿wÙ»N¶{PÔôÖ÷ÅTXPD]Î*çDïCEüYc¤ô¤ãð^FO¸ëz]ÕÏéæcpÈÚUÊUÐ@,#%ÂpHmUWùa±µ®*|ÛH¦Î}Úu÷'Ø2Ô¤æ¼ ìGC9BSu&3æÖ5ñh÷=3m"±|Ø\!XP.{ØyÝH¸¹[¹BJ+ÅGPÍS#.O2,,<Ó¿f;r÷ú½M`ª) ®¢Ñ@9b\m@ü @@]¶ÐئD #_K®cR(ä?µ#QQÄpFñ#%¨ªêªÄÄ:UÙ#%¨"ñÓmݲ#.·4맯É(¾Î^¬(üEJBë 23º ¬W¾\îp®4«ÎJê#.¬ËqÂ&zÐB/ò!<Ë9#.ølc´Àw£ôMzME×®#.CÁEEÁEà#%<så£ñhõyp³R¸øðá#6ÌÞO}¢åE§=ï½ï8Å»ðàÙø{q! ¯ÑÅ=ÜÆ¢Û©)êCöà?Ës_îì]#6êT?@-!öðó÷ÎÌ/¾¥Mþ¢Jk覱{Z-@?÷U§Õë¹üGê-Ç·Õ@{ª¼cnÎL§Q-ðÿúöòÎÿÛeÐFçÛAùk9ý3xÇx/À4¾ÔPÅHDÀÒ¯ §¼z@ìÓüUÿ¼x´#%o22iíé ¶z® kÒ$~ÇÙcÒ5õ«oÕöü}ù°RH1è¹çèÚ4£}çKêçÎL¥vJjþ©J%ÿñ ìøÐ}ÝAbArðQ1«o£Ú·X#66ÅH.>qÈ|ñ$T½"~ßÀ$ééí#.YqrA@f#%ûW°@Cë:ÑÐi&s7Ïôì¾&BOCüf+uÙòj Ù$ߺ×Ïíz³¾EêOæÚ$>ùhÕn¡át÷Hú§¸!#*1"Ú.Nç¸Û;]\xVÙöùú¤d^ wÏ|gO6ÃϺí;Jæ0&é5Ó#%}¡8Ur/$ß 3ì>Üx¿,Cq¨;@v/#%å@]¹C9P¤grÏþ¸(9Á Èvk$§9T¬Æ4h ÷~ÿm*ñ8ê»È`#%X}¹lJ^¾ü. #.JCVg5t^7!ß÷ eøÆe#%~zT)AY`ʼNµÂùíUö)>Sæ×rYXP\¨¢!Å&N0#6±zY*¥MtÛ ìtÊl,tgÎçg2jbOåN@Âq7´ñ&¿F)¶¦=(({;P'+ª×ÃwV_ðÀëá?tf¸@¢ÛnóX.3Q%x]]Ïv[ÒÉk¥×¡TÔ4¢¦ª% e^ROkl(FX8g&øwå!£?géâÊ#.#íYÍïj~âieÄ×u'³Ýe;gÂTüLìq1Ý ¯#¨(òáá#É,pçtAè5+ÙldèwäÕÒ{øÞvåÆ;ÚõmP'@î}ço=pÊ2H#6OGê_0P&ÚJ#%íËTO¦\ýæÀ¢jhDp¿ÉꡧÐy©9Sr³xêÚ-ÇhvÔd#.Y|ÓãÃPmSÀ_¶V?L_"'(PvÖR«6ã$¾Z'xõ×=÷#.A='áTP)þ%¦}ýjW¿Íþ\èô´Ò¨õÑ3Ê¡â̸|ÅZ~c¡ÞFÊ0V(·ÙÛiúÿ+Þíôüt|~!s#.Ë@Å¥ÑZÃñxä·a %»©±ªþ½GK1à*ÒpÁþ'Â=6qK½¶±/öþ®x ©®óÒ½±dRl/U¬ôdÂAÆr³#6+óÁ GÌ&IòênçôBs\g"ìé_Kâé?§èMað{4ÃCɸü¤ý³þ~öÜ ÚázNö}Ëê9)Jë³ÒïIÆf¸<Êw²Á»¤Æ=,µ¶&M!.üpVí±ðNtÞe°Ø²Ó¦p1ÐàøôzrżùXwÇ+8So£°y1Ï,ð#.0#йò½ÇÈB9:-{~Ã1[rµã[öÁå/{Ã" V«Ñ*&dÛëqì¶Y-Ï.õâÒÝpO5Æw;-¹¸ò ¦JÅff Ç»¼Á¤à°ÕçH|WÉ¡!I¥Æý1eEÖ¿Ö9AtP_ªÈåÐêkWHV#6%±¥ìå¬1^´#0Ó)åªùº°Eóg*ímŲÜëèûßÁVBo^Eæñ4ûyÖ°.éÄF±¾z4÷ö`¡(Ù§¢W'¨f鶹Jb®òÑ;¥:ZÑ;n»Íçe¤°,5÷¿_¡==:©8¼á*èçñ_ozâ|qä5v]QsÚö.2ß#6ïÓÓ~ýá*ÜEÛ"c¬|T=ù<³##6àÆ`Ñ-¶P¦#. ÀLï6 ÏÜѺ Gà¨ëÔTt6k®^m¾×¡Îu¾ír%ÄD>ÚòQMã~pÝ, ¬&»_Ag¨²Naæ{¼'##6ØÊ°àYÈ#søýø²\¿ú-´Ø~mÞÂɱ*6i¨I@¡¯PUG¶/G$YYzÑÎR0úgÏüîå¯Cæô~6·ÌSPÔ^ÎÓ¤é#.Ózý¯kHmiÛm.3ÌxK¦ÜÈÿ~®%Ä"Þ+G;L¡ïncï53áõ>¬pxq¸dê}¬=ÓÓ·UýöA¶vrv¤94>üL¸½p¯´°©gL{Ùþµt6É{<]^ÒÞÓXÈÁ\ ¸ALäo¢Ïóü¢Ôð8ºÜP6;Ak Ù#.njú«xõm©ÁäXµEÕ-">/Ñ£§5ô¦`åä[R÷6qì./Ó#%®Prö9¤¡ÏTXù8H^ôѬPòÖ~Zª¨S~§!¡<פýUîO'Uú¤0°*û¡Â!5Éåúõ `ØY³¿ÂÁà$µD£#%¡<ç A8¤y¦ç½â±F*$PIåeÉ#%úZ;d>ý{/ón\ö»A8*#vw3 *ü5`,rØ5¦#./¾ºËÜ 4WiZ¢Gé!uá&(ÒÇ_qDå®g·3$g²a:¬ï,ÕM{ÂkÌû!ÚR [#.Mßâi a½6`3"»½§ïØÈNÐ+Ùbv§êëdëZO9ª$-]»°Ûü"üfÕÃõ¸pELÂçìîiUHE¹é±e.ÂC¼âgA¬6y¢gÃë]±éwÁ÷Uîåã½}¿)¯#.A²ÌëðÀ`lAºÁ×dí9Èãjá*ÙÝ渻²§°ñ,«hïÜ£dwÌ.°»dåyr %(sãeäFzeÚXí¼#.Kó¿iCÜÚ'~Z6´#±sYJÉaLJ¦#%39F¸¨Q" ^Då6{PSS3yÝLÝ'n'´sûõ*ãz¶«cT¸#.2!r(PhPÚë37nPáF;E6#%ò-®}] âRkß ×ø°ç>Ðt©[â¾Ú²Ù¯kYëõÉ×,oÅѲZf°Øâ'Ìü¼üFæ"_êßv8í<[8¢XæË«É;ýÚru06fåÚ¹$£ìH½_¿ÅÌÖ_ÈB'ÑsÁ¾Wì$³m#6E]}Ñ#.~j4aÙ£ Mfù À\ö=°¶²ÔJqåÎ{ôÅOª÷Üþ§ÒjAéTPº¦Êæ}Ëã1¨ò%¦ÿ£Ì÷"ÛÍ¢1#6HsMÇ¡±Q¯5óßâ¬Ì½9ÆÂ>uRÂ#}ì3va¤gìvm¹ZUÀ#ª³qÆîëVØX®H2ÚÏßÙ#.ÁÖ@¨$7°íc<!"·ô2¯È.îöö!Ò5ÐÀ¡L÷³á±Ú¶æ `ÆVØäºÑb#6#6õϧë(¢Ýa'9ú#6«`4Z¢ >P4i á~q\KAÔ!nAÌ)ÁÑYÅɼLèÈÉ6Þ¼44m§3r !±ééZ-*5Þ/!*kâÔVäDK¸ù°;"Ön[z2bèé}ÚÖ½ÖJ"ÃX¢Ìvh{X£è¹Øf¬b¡Zëóè¾´ò+Au~üâOÚ°Éqm©Þ:¤·C®aïÄ,«&q\ÈA̶¿n<l4(ÉÙÛÄWÎ"oí?w©zg\.Äf¾]%kÙ¢t<æÐ#.cÊá tgßr#%s-¤ ÷çmhÅ»]§N4(ãZs´cÎ.ßx*sgi5ÃÌJI@íod/(&_ÊX·éåøC¥¿ZO¹V?0Ìd<Ö¼ÌÄË0æ;bù¶ëðzàUöKd3³ Êáh@ÙQm´c`ñíYÀíÌÀNò1ª8Ø´+n5µ#ðF¼]²"RO]WQ5#.ê/Ùªß~aêÔàí#%飵âÓê(-+GcÒÐÝ`|^D]ÿ¤¿³ÄÁ#6El\q´`!zI¡¼<)MG~©oÖxEß¿øÍF'Qn#%xTL9ó¸- 4ÜÜÜÝOÂxp8Yx¶@Øo\D÷Níu§WL7COÀ»îZ¨#6iY|ÊäVúAÓ]&[óêæ¥À_5·i>sE/#6¸¹%5ÿ/ÃN¿ÃÝìï(öþlâò9Ðs7Îåú§óh£ógTHðYg}ç_Aò0¢VÅSNÄHQ'Äá×õÀ£UGJÙB3qØ÷dZÞgÅÒÐq÷q¥¢×_aÜ8#%Iü~JÚ79ÀëÒ6ò`á|û6¯/ YÚr´hÄú§]Ù3óþKÕ⻳«Ä|3ü|cÈuyb3fïíÃøÝCx-®X3ÐPXút?QÃL#6Ô28~±s;{þ|%UVvþ,¿Æpgºÿ ÀY²Tì*Br)S0eÇûï¯Éþp>VÇù¸îü¡ü_ábÖ?©BÈrøð½C9%_ý¹$TÅIÿUP©þ·÷êYE»üZÕôAêa#°^ØXá©81#%hÿ]¡0;5gûYý¼³Ö÷vØà|ávçv ßëûîÖáþйÞcË«±_wNóx©©A3CaÚ ï:Æ]Û¸ xn4©ã×Ìê{3 ®íH¸éÍßYTBºâüT£Ca²lÀºª<ý¼;ª§`xµÍG°{ÚÀÞõ{¯aô{ý.Aô¯³í4A#.PÈû=¨íÚ+þªYÄ; ]ÃäNÁ5%Ñ î\þK¿ÞÍ59Í=¶Ïâ} F²¡®B Ötüû§ }ËÔ:Ð$A7ýß¾ºÏîû]MéÎÉã D|_÷*ØUÙý./ó,Õ!nÿP=`dÄ_¼çâÜ&\B7dªõ{ ²Aåý qÈP#%)Xu¬¯# #\>Ïæþ¯G¿å+÷[q7¡çb<*Ïw÷ý=OâGÔûôH|ï=áãøN®A ÊLª´RÅßzáóHò?yCÔàVøþí¼ ò>!0нÈ^ûÆÁ.4ñ6×å#.ý?ipvóÙ7ìj¢Ñ X %.S7pÂMÞbÀò6£4¡ÖyÂCaÎ#.Ì·¨¬Qv ´&ËPÿ<#6ÃvT«±}ûXðÒ¥WÒ`_Ýä }ÝâÄì9Åwû[wmZ?¼C`ðã tÌ{àsõÛ?OqÂöVÆȨ7RÁ°Æ.¸È(H0µp½#%o{íx-)F,=ÂÙ²"ÃÌä°íÀÚæ9Níw.i cvL0ìòÆÐ*ÚÃz}pAZsmy^®ROÅö îNÿïòðYGÔT%X|ËBáá5¦ý4¨TÎ(ÔXÐ#ýeµeþô=]Hê#%ºwZÁÀH_6£áúl¯ïwç£èÃ0%ï»=¡iìÁ'åÇ`w%#{ì;r6,#.øÖ,Ĥzdx`¿ý9p©CYÐÒTe*ÞiD¢-&¶Ö H<>Rg#65Y$î?.ÔäxRR°Áîú=T²U}ø@ú1ME~ kmmÙGåô¨ó&FØèÃefæj²~G³M¬2ëôêYAÁwYÃâÖ÷ #%yM©o®#ÌôlBÉÕ@"Ð$eæ Ä|³5:IF~¸"Ì-¨É>¤÷x¸º"#.?â#6ª[pÆñ·æ4ï* *D¨ uåsØmos¬!ÖÃfMð*fÀo5йdãÆ¿ç=1 V·ñÚÀÓömçÊkû8 6úl£\ðgbÝK!UU;¤I#6ðïlJüý¸f¶Çí86#îuï¸öoz©àÖó×Éà<è:YhÜðyfÊçñÎSlK6ÉÆd.ÕåèSøÌöü½Aô~Ã!#6ü§ù|N3ôÿ»òï;§ÔOÚy K~ô¡ ×Ä°´SêúfÄ=ºÔ#.óévdÖõò?IÆÉõáUê6üôû[~@ð@X#6Ä`ÈÃ/õ{ü>¨ #6èQÚ@Äöl²Î¦§\Ã)%±·P7À`«³¹ð× ÷C.Ðup È`güûV}¹Î|¥F1°bcC2æ²Ëæ0}"£A°o#. '#%ØÐhü÷ìÚ¹&F÷7yGÃÌ2M:ÖúD(3ü_ý}Hlû·§qE#.2+ÏM¦äûøæÖ039!×ÚFå9-Eö V#6`dêxïk #%ÔOÁ-=fq/¾Êõ¥*`k|X}yÅ^Eí!l<FDYºÓA ±¨TD â)#¢3S:i°q`wr$îï+à±">,òq$D©L#63ÎÏõkNðÍÔkÄ^!rÈÌC¹éi Ñ93C<µ½Ø2.¦#.Y$à ¸ûÙÓñoXÿËw^º#%rÿúõUvAýù+RWáóÆVoë¸q®½v¤ÞzíÛ$cÁú»eXjÿÇý1-.õXÊf]dmffµ¨Tä!Ô}§§Å´5N*näl³+¤CE×I$ª5LTËMIikm§«²Öjãzef׺:õ'«^kA«ÐÖ·¢féuG¼ÇV:ÒÄeA)2¬gøY(Î:ü¾Ù#6X#6ª4YH¹²¨éô0 AP~_bÑjTmå»2sxqnaÑXî;Ú%³ïöÞÙýµ£tGí^^ÈÂÆÛýÁ éó˼ÉI~}~ÝÕ¼QRü¾ÔúÑ÷}q§#%è!À´>Ò^¶Cwl9¨; 6ðIÝ·;¶¯¬ó·Þd]¶d>aØZjH M)ßQlЪïVY¬$ r¶PRm82d?ðÛc;ÆxézZªÎÀ«àU¶#AIE5º&W¾f^%àù§S«-5RkÓ¾]ZÍÌ¿Â19l=1IAJ~ËöêuEð4+Õ.^¿%6èßرfÆó£æg§-Ô¦ÝɽI"H±~Å÷WN3v¥7()sp*Kûû;®Î϶þÒÀû´Ûï3£ßødc_dDôvö´»~¢µQý![~Æ1mؾñ!túíÈÿ©©¿)èlHÅ3ê+ì:öK<¾¢ªQRR"äÙLÙ°LÔËsMw¶`¡º îÍieBñ@0bRòK:R¢d|~n|âWnGô ݽ}8_¨à<'¯aòV¼Qîó5¯·o\W÷Û^0'h7 2u%¸Fmîòf±0/ÍÊÀ·ió¸ò@£P.£ùbúÈ+?NÎTáõPäDs#%>!ø½Þ@Y68þçxÉ\ż.Ü?ú-¸QÙþ*°DjIôßç½a-êzÄRÏ¢*%öQ<ìr0}y,ýÂz ú>Ç[ävãò`õ#.²Â½ú&Ì2(Abã:6¿ô9v¾ðû`ç¾É±9ßÙú_¨ì>ʧ8»ÀþÉùö»6x'ã7u'{Å;H©A5twµñíPIÉ(Ö?xyX"DNþ}+»ÅÞysF±èæÆÀY3m;0#6JÊÌ#%âaAö÷D< ÉY(Ìò ¯À.pW÷Îapõ÷lòÕs½8¾?~ç3PGÌpC© :¨3yC³ÐÕ?P«¯»/id+ä?ÇGÞÙúÉõõɬ÷V7LUQX®4=áù2»Ý£¯ëø|áçð*úÄêkCÔ¦j£I'±â©æ>·Ò »ø5UÈA°4d>/ЯãH¤Wb)ÙZ]CÝZ{_\£ßö¨0G±LùrupÖÖÆZÿG}6\ÒT Éá åõú÷£°20®UöÊ°8MAÕñ#.7û;³¬{¯Ïàtc$:FÞ,!î:ìÎ:`âÁbqe¨s꾸äædQÒPÁNêËJCì2UÕZ*>RQÀÑЩüèeLæHãc;väáÁbNTm÷TÍ&tK£Pññø©tóUHª%HYÇW¯>nÛC-mur6ÑêE±½¹Þô+n}|=i³'2)E^úÏS<a$Ed@¡$´ZЫFþÎ)Ìí76,BĤJ(~¾'QvVôbJÁøN|À=ɯ»ß<OZ'Iâh<Þ°ö#%`íßÂs#.dòUî6ûcÁ-£È3#%§Mª¥¹ãïù¼_Øû«óåïè/_Çk/qcu¨²{¤·´?×?#%#49'öJ<ªJÿ¡ÄÃ5má¥8`«:m _\¸Í©RJJQ¸kúºu÷OIÝ'lòµ°~3áGbâ=hòäÒøj=ußËã$½!°ÔÃïLý®äwò!³Ý(TöCÇÙDåÄã÷~CÏ¡\ÈৠT £T¦!Sä§r>Ð2üY"æC}ÀíiòJ;).Ù¹½ð h_éç±¾üåw¼!,#6|õ»ùN}Cà=åË)BB¡háô"þã3ì kEµ,ãe'?`vðßù\à£öíç¶>ã(}M|)kì`éþ¹áaª]Ëàa½E½h#ãòF%LæV #%ÚI0%¾ Z\Baнìh%RÀ2` øÐlHvE6(¤\D½dó¸HÅH"8ERG5Ö ½Áù²AC DÖ55-~£¿Àú}ý#.>(#.ØÈðòÅÓ<³1Z*¦°°'Qb¨r#%*ãIé}¨kOH~)Û´ÑLAG§QbY()9gb4 ÁGô~×ôs¢×3Ü×fHz3J³íü`V߶PÁý+_>q°Ù#64XÌ¢3|»Í¯r«Ò¸n[]0ÙP²ÙmÝyæ]<(©hïôWóúý?fþÐ3MãʳìóAì};`%õñºéîfú#%½'¼YÍõù½HÃ[±#hqÃkóÔ6CôH&·j ªY1#(#.DB2`ëJhLé·E(Ò*XZÌO/' ;+óxBJ<ò9/;3§¨^-ûi^Cµ#6@Õ£wëÜ¢}RN5Â7ön9ÐõD#%ØpHo(ë u}J6öÄ+pòi:ºØç¡<½s¶Üíö[cÛ.Ó à49°¶¨<ïªÊ<Ïgã³ÙÛ;Âä=Åa¨]lùúÇ#.ÒÒá)#6(£ß½d©ý`~¯YíIæIRJìóî9\§ÃÞúî8ÿ#6Ù6zC¬÷|ý>4Ò~Á1Ø¡ð&IlLatɼ,#ZÅò4|kf_ѽ ´¸¹K\UÔ0½¼$ ´UO°ßÈùq¢úHhG®¬:#Y9!|úÿró=HÍ@p2¡ «B#Øë·×îüèt*KHÍÁÙ·Z<°ïC$"4ëêëç?}z¢3Ôx'îM'oÝé#%ø÷ÿ´;)âB0®ôo%dL,6f(·Öߤ¯J¼u.î¯[<r±!J´Sâ_í#6Ïíªãø ùßïÅ#%¯PC2?¢?½öýfYÌ1?I#6¯Úz³:ÃÀÉåÖh¢"V£Ìwg#6þ¬)ʲüöTÜ0¯Á=iÚ Ï Bi0ÖÂ%ö§gpõ c%ÌU!1¤1*D\?S:PzÎ ®þçæËÉHJM´RÁd¸¸1?;ÁcÀÌÝ°.<Îb§ Ö;nçÎN[»Ñê Ýõ{Cíz!RسãõÙ. S#6 ê=,è>½¾zDZN°ëÀàô·NV2KÀ.*Ð~ àGX5º!¶Å/K¬Û Ø©ÓyâzK¨*üÌ` êAnßlä¦ï/g«*|[B³¿âUBP £âÍù·4¸Åá8'Pf,Í¥dÄ1éÿkü;Ô¾Ö#ÕQÒRQñ{ùmzIIJ 0êÄ´ÃÅ ãd å1*ç0%v_η?nTÖtÎ#l1绸UgP=`*IùI²8¢º'ʨ´§F¥ëPØA¶_NáAJ`µ}ÿ¨|ýÅÓÚ/O>9X<ü|z`î7Éíö¤»ÍýVèt¹ úd¨HÁ^mQÔЯÒkKÖH¾ºëÓ.pâìDéGb\3>:ZA*à¡=^Wû<eÀ|ä 9 âp]û-³¦hêØy¡¥ÌÁÐðN£{q¤bB:8jð´AKF#6#}ë¸O`y½JÝüÑ<÷ à]ÈÈJ¬Êª%¤[9_Ôöì;#.HÂ.ÒPó÷áùOܶÕÜÌúQóμ8*eåàx_Xú(ÉA=ÐIÓíÉ\½èÖÈ,Råí <nÝÔn3Ûò'ÙÙéóøö_gùUJè â¯Wô(X¨7>àý<?ÔÕ =>Âcp`¾ÆøÏðAv}Ï°¦òO"¾<ªR{˦8r?Oësðo¶S·à~4Îj·¹£0gþð¢¢+dã(Z@·A}îlí rÔåØÞ̤]×Ý®¥éÎ#%5I#%M$ee5hPmØØ5o¢àLÝpxûÂoJ#.0I Ò,6©BÈXõZªPýÑ÷w*÷o6`>Ϲ#.¨,~è¬ð!"Æ"?» Þ`]Q{jòNo.ä˾0,bd% ¯pA°kó:Î.îz³h*;¾Ï»kõê'©uÑÔ9V/N|¢½%bªdÏ¡?*= ym+Pw!Ýd#.[*p ½ÈÁa°ln7â^öÂ9íLÀйp´4#6ú}>¿|{Vuï-¯M«¼ô©)mï¥Ývó·n°EÿQõ½Ä3t6ËnáññõÙºÈÀ®Þn]¯C9Qpë]q¾#.ãvË´[ÒQ¦ßôßõ ÌD÷F§-hja°»^¹BVͶlØÅ#%PX°V0PPÓ®¹ø:ä nî¡zgxDeñÝÚb³ÇÐ>yÊék¦ô>z{h}Ás1óAdÑäH>Ôî£éf X}Ô¾îÍÌ#¼ð8&`ÛwÐ6pÑF¾ý BBM¬#6I#6çá~Èë H7V%íü/Äÿxên=@çE¶¡ï=jÛQQEV$[jUUD:üzâ¤^*eVØ!ªú¿¨Ì&&r¶l|ôD\Üç´XÖi¡?«Xiê%x¯<íæ®ézîÒfSo[Ö¨ ¬s4üåú¿ä'÷åcyÜÕÕáPÐvSÓú0Ñ"#òÈðÍ~éº{ç´×Dª_*9äÕ¸S^t §(MÉg#ärö=§ßÆò}²)NVú¿A>?Òe ³èÎýPã/#.Yl{d+×V=µpø£µ0têÔ¹2ý0â{Qnwvï÷ê8KÎÛ¨àzÊk0Ó2¡#%óØéüú»#.qÉTÕK£ë±+WUÑù÷ÜxÉ°ý*(D¾Ý!Q4ãHÀ¢¤çæT,P@X$àY´5eHrëþ;lýÐèllWTKw{ºZĬû?ü£øN=ªg±\ļ3à1ê¢Il¸ùÝã'0´`°+Ãm÷@#.ÉYÇî½Éc÷µóy§#êúéàã/ê#%B§ôëé._0þjà%Æ/ò9Q»ür#6Wúÿ= rý¥âÀ¡(#6`1M3-ÊS¼ómÛÛËÄï)sª[!÷DTL¡Y¬ß¨èhq9"ºT"Õ#6+èAá© ¤©¥q¬©æøÚàúY¡ ûfgñ ²¤(kf:ñ£ðåØÅCù¬#. çXÑa¤Å¨klmYçqÎ3Ö~73®Ô.¦Æ%½Q²: v-°r· ê0#6ÄlÖ¯H`³}gÏ¡t¼¨Lýïä|~GôÿìÛnîv<ÁÌ!ìÊù#.ÓÕwÊ,ýðõ*U0BA_Üá÷KÒ¡(æI:§*þM?µÍ®ßÅÁ5ä=½ÖN}¼NÍ\ë׳&í?z Ф´Y- ¤*¨õÃ~#%·öµ¦ÚSõ Qk#%Z z³#%åÝÈW;Àϧm`ðÝ%#%&âUêï1ó~{ýq×ÙúùT{,eÃMÙ"bª!ÖÍÌ"qùzNº|úw¿1ÔeÉ»D@åÀy#6#°2;×â¾÷%þ÷2zTXAÄ#%28Æð*5@åï'»nÊlV#6~\bHQ^ÿ½è¿,[>G;H=iêPÈJÞ§b¨$ ¦ð¯ñLÒú.½ÕÎ`ð4Ñm°É(4^?bS*èdðpéÿ7f§Mó ÜÖñ?A£7DË$ËtÆûëÌdÞ>o#%d*6<¾Þ<Î= ͸_èyËa°aúðLfë9ßmÚíãÆxjt3û±]]î~N.5¿U4K.w¤Í ÒG Qëæìøæ°Þi}kCeúÉî.§ZÆ8=6t¸Yr#6%Ý7"sPDÖL1ܱ þ^'y·=ë;â*Slb¬l{¼*þR{\2î@¯çk·¨ªØPîᬠâðDçG½#6@<0GzÂò£|~Hø¤þzN ØûcGÿÍý]bïÓcy×÷Ò Ø!éÅ!ùÆ?í·oÙÜÙ?ÉåTQÜ)ÞQñ6ÓÒáÞú_7Ûàòà#.èðüª½ÚpÉê7?v¿~óAÞJîîç'bû,íÜz@®^í@q(M¶9T*²õÃ.Évm¶Âº9ÏY t Æ"ñÌ&÷Ä;:×ì<ÝLò0âÃñ{ü×R¬þ/$úý3Ò#6?¿>þ_Óu,6æsl»sÄlË©Å0âÕ躨sæG#ä.ñuÁgg¹mPÿk¼§l$XóüEævQ?â[òÏÞßÆIGGHNåwÒSîýçâ-¹³\Áxµ9ù¯s£{©¤`öù¤J÷ªÕ:^¶B4Ë?ÕzfêÞÿ§¥¢®¿)#.!£aû1¬KÚëõÌóê2_ã[¬{lAnµLL#6#.µ qÍ¡S'[o½ÂÓGf¬(`{JÂñwóç¦$ÛÇRu:g<®ÏðÛ]3êød¼çCpêÖ4¦8óe2övÏw]Lâ0W½k³8h[¡åÁ,¶ {ö}/l\_GH½£¤á¦#6ù^' òlæ¢å®#6ÊÙ.rw ë0Þáü~-¼ï>]¸ãÉÀswsÜ& ÑÜÝÛeìü§]È]2ý3Ë4Ù£UtÏ[mjpª¤9-ÐÁ@Ab#6£AkãÕÓlÔùúøoTq4°gÒ3,Îw<vâ/£Ã±ü3#6¤39ß \ëa7gÖâ¸<«I º×$ #%!¼|_á1wç£6ôt3kì'6¥e¶>É1~¯&#Ùî+ïUÜ¿îÌ×}.µðƳӦ³K7wMïTD_UÒr{RniÐU!Üñȸ>mòi?]Ðúsyü®ç:áéõ#6õ3Pÿ[~´ìù¯§¹OÏ.pìà?h^UÚfÞ|ð 7ä¨ DN&¥6iQ-9z-¶bêwþ{£KÝ4d@òuL:ØÝrËç}ÖÓ¶æ8\à4Ý&dOËxtð£Õ1ÕoêïSßþþt¾þßã}¿FZ÷|iwïòÃ\EÂ^ÃÑq¼.Îúyµß³Ì#F×cró°Ê1J?yU`< zôê9=(ÇV#%Û»#%øÓY]¦ÆÉNIör+Í0Õ#%)aN^/X#÷$ 2ÂOaA~eoa#%aÓÃÅNÍ¿GõðãηÁ8ÝóÎ$÷ÍKs{ütJä^ôeìQú¤ê(LÌ#.!~=.gm iijÞ]¨¦b¸MÐ6Eî@ý´Þv`waY<<ëà;% Ó3!.áé»IÕ35Ç3å·®NúÇÓ(¯§ëù6c9vòD[µ4;ÈQT4¢ÆR.²aV&¤BÓÕ¯Nh¬Fz *åQH¼Õj´$fU"Â67U<yb×b® »T#.ZdK©¨å9Ì?¼TRëøq©û߯:ÌÑÜYEzhÀO¥òúÑ'Â}ßϯú¶´ã´!hRéÿgÉ8_ú+vá4¼þxÓËDçèûý]g#.ZgùPô}ý;ñlÈ°± IôKû«ôlpýHN#öþ?bpà~á¹#%$!!ûß#%ÜUl?ÚzSøól]¸~·a¶ÄÛÉkä öjk#6vè¼]ý#.çÓHIHÿ{µ?¢ËÀ;uMÎYMQÃÈÓ[qÉ[N¹´&ÚôunµÝWx¾0óÉç±×p4-çPÖ\IÁ¸7\¶Öò¨ªñô¦Ü Béǽÿ9Á¸t<#%<3§ê#. 2¿ÛÐs½k!(Ú*]𪨰©A+hXÂÆ?Úvÿ)Èi0h~~ë[v[¹a,îÍìw ÚÌÖMN0Ï|¼Ùª<ÝÐ'Qä{jWÛö[¾¿9`±Mà®P³(yÝ9qõEXós!GWQ®Ú-ñg4'io/R á«®Pï¡ØùØk¬ÈBé;"k£s_¤}5fcfS.ê²ëÃ2 `D §ÂSI0&b1"áJ5ih¤>fRàH¢Í«N¶s8¬ Fe qWäz§d¾5àÖ !;xÀÞ>ïçeÕeB-!Øïm§0M.Î"Éô¤à7ñ¡NõbÈ>}¾X3ýä :²íäÖNÅÍ÷ü7º[Sòaéߦ#HáòÇéwo¦¢Ì³ÙÛ´!;Z-"¡øèzbS Á#6ª °ÐÕ²A±¨ÛAp¥i²e¢TA Ð@h=BµËº¿ f?´5û»q&}Ûrd^Wð?üßk{K5 Ú,_Öï{¬/+Yüt1Q!%¥*d`ü¿Ú@R¾Ä9AäF"ÕÝ·fÛPàw£|}¯ôh {·g=×·½¬HER!AÓË´Ößè,?»ßØ=ËȪÄDy_7xÿ<íî,ö+ɲ.eñÖàÈÔhXØ+VBG=«ÝÛV =¼R7Áý.ÎùrõT'(f¡Úh»V7ʤsW´Ð¦À&áõQN!ëMpqZ%·då²n¶;±'Ú%1LhUQú#6l}i à ó"e¿¦<BÈ|½3®Ü<<t¹Rð`6¸Ç&ÀvîÛvyÂ8Û`«pBº¶DÆdkOVR\:¤+;ï#¡s°îÝÈãLºÅxórÇúÝkå.ÌxÔ©¸ë4Úgu"0úË!we*ñt5æ:ÝÎ&e%ßãD¬sì·.¬é5Ĭ^r)Ãg[Äb.;a3¤ðX8:^Ó·¿¡Û&ÉëÏs^½ÛÃõwG$f>Wâw}wλw̸áŶòÕY$6ÎÖa7Åç4E#v8¹omæf¸À¯C'am²H|MÜ4!vkÿ!VBÞðÙ:Æ Å]å&@Éî[ÝÈù1àô#.sµ3/MC4XÅ#6ÅE)ënØáã´'aÚ[\£Àº½fÖ@¬næ¨|?¢©£_w³Ý¨Ï¦ÐàYÎÀlô2K?*#%a8xIéç×¾=¾øs¿AÜrøfA#6¤±á·GÃM§o#.F¾Üϵ*wQ¥íè¥Tñ`Ñö7õF4kÈAËð#.2ìª0hXøT¬ZÔß´åb µØ=H<àXoA#.!rqíg#%[:yléTËs©ÓT#q¿`Z×Í^!|´Bl¶Ç¸ò´©Ê=1#ÖÑ8ÆÎ$'`äQ.º%ì+¶&À÷{¡èzy 5 °ÔmyÁ,Tí6¾$pdø(Q13(%&ŤÂBß²°Ôla¥²HrÏ#.æcÎ<BÙɤôÏÔÞ»«[°ËZPX·wouMÁÈ̪÷LÎi]©C£0=°X¨îuà]ñ»$8dï;u!ÉÒ@0äPT®a¬xoàfvfåWl× G¿àªQp@©Öö¡MÇqG{tØ&ðºSl* z½39Ã=NùÌÌÈðØy"¥w'ÐUÒq5¶Æé¹v/¡Ëà24@·øl'âlȳ§w@'©gyÂvkÌùµÒ¢¬d¤Í4ôÎ¥ë|í#6£Ðà«5t¶õMÚ]î<#6i5À{WÓêB<á¤16;¤ ²D`ª#6ÍÉN^DYuQX¥ÚhgLm¤»2îxNKaÊ£R+q õ(Xø8LÎÎoE¤hÂ.JhÚBHN_C]àYÑÉ.Åuá-,\à@ Ø+ǯ53¢,UæeÇ2æffXÛ1¬«2ÌÉ%Xì<õcûªjñl$0nÆ&z¸íü'qÚÌQ¶*WÕÜFÞz>7³w&¥éÖû½CÂ9Û#%!zlP?V[¸·=¾Û»ÊÄsÍÑÖÒ&w·áÁ"TK¯=k9çÓäôzp¼m)ðièÖÜæÄÙ3=êFC¾hYCS8G+}9ÇÏ5®ÍGÞsÔÁÐi·d%(ô#6×nÜÉBiÄháIw°P¨¡%Õ,±h¨¢^4{ûw+Ñ#6Æ]Án³ÍÊÔJ,!25.!bÌÎ[úsHƶg6|këPå¥èÐÐɪ×eìëÁéë#.dÓC¸ÌG)¢AkotcC~[^²Ù#%D¹ÞìÎBI(×¼®Ò´U6U;â´øÀ¸}=»Ï|#%Ö«Õ¬´ÑÂ7:ðäUC#6S¥Áµ;ÈèáÎ\6Fj«U*F7Û`r¹át¯äXÈë@¾v ^µG1)ã^ï4¡N)LvàYÎò`']ÑLª5m²Ý3ã}´Y¼5ÞB@-º·¦ü¦ÏFµ&¶á®) lÐÑÛµm,¹r,±aòãH }3V%O2(öÐà£J(ÐâHk2fdçqªºDôòÚy"èN5«Û¹]Æ#.¡¬Ï7Á£0¡:þÿç06î쪻BÌÙµRÉÊ$ÇcHÃáÂûJ$ètU&WD9æÏ*Ë!çÈÜåÞb<BÑ#.#.¤E¡Fy ha½¶E· 38aú-á'/JZ*V¨i4`hRq!]#6ÐΡ«0Q¢e.ÿ_B"ûÉ¥#:+R*Fä¨ãºq=r@õ¾_ 9Û!ß/¦MHYLÓÓgq.Ôt=vü7]Xu&I¯Ù(Cy¨¼°jÏ4±K¨d;Ä¢¥Ú ©#.üJ$E1ΦÚ1dk±×´³[&ᨡÁÄrGÌXÐ!"|&4ÑIr`ô<4ÒËMkWgÅ7&»Ó6ínS./ÌçÇÚÖÞ°F2õN;@ÕDf¹â»ãUëÐûÀ%NÐn_~LÀ DH²Óf©¤ß|oR½oªó æ85IF+:5_`d{ÎuȦ¾¿\·\g#_-7èõì{èìî"æ³#YCi#.×ØÊW¬¹7R¹ÉØÎ!±E¹*.I¦#6Éw×¢½³áp$Ç$#.Îxy|FÀPLZ#.°(ÌnÛm&C¶#.F´"뼡%Ï·z9¼ÒjÄ6¦Þ0ð¾oHCøÇÇ¥7L!3 0qÄ#%Æ;{[þ@o $ÜÙVI6-Ãp%A<åO××'P£ÿ¯¹Mu#%I|E>½Êõ 8q¼D¨-ê½0ÒÆ»²ô:¢äåê=¦&-Oé¥éÏÛgÆ úîí²]+<GHk%Ù¢*>ñ¬K¿·M>i#.$×ûwã_ÜóÐѸ$ëÌgñ\W«§Ñ3nWVGM§OUªy#.ñÜY7#.ï·»·=h=BÐR´gÌß»´_t=V[(@²2N. c !áHôØ>((Q6ÿÅ7Ý* =°eHÐÿoµéÅr.#6ë\HîÚæzyðCÿ?²e³ýBÔVKÓÝò<`PA>B¢*£!>y5©÷Tõ.¥(¶fÉ(ε<Uvöú|G¼z¨lô!á×gï"ûN`´é~aõúCäD#6F [Ûº7÷«nÓ6R[êP!½ÊPE.xù®5#.+i}2AAûwR@H¡A)Ò¢+4Õ#6ÚÊ fkÙ:·oNqï$$$¥¯b¸ÎôyØöpÕ$µ@© Ò(øì¡Þ§pm`<lr°#.ú¯±òÁY±W,ï$Íø àô]CP÷À;?8¤Dv#6#bBÙ-hÐ I÷ì{ÄB"@æ|§®\¦ú¢Æ*X4GZA#.ÊÃx{i#.¤Pd ##%=ÀA`|x_äCR³¥éó4èÔ£`$kB1KºíÁ#6Xƨ1tIÅÊ»{m|®Õé¶#%¬Pº580.HÜÌö¶D[¡·¯¸ê{-Ïþ0~ðî6#.ÐÀÛuHKÓÁȬ;Æè+ù(ª°0#6AÍ£3¬%_²\$Í>&@!åÌh!7#%Ü#.[Ó]ì¸F/5û"µöi^øUÍÔdwéÖn\¶qü/ êÌpá<`bé·¤Éê5e6Û}åcj墩i,ÚAE`d;á;`þèè«UÛ4ÖÖéW¼ªÙ¬àcòz9$»u[}ÌnS(îÁG¦"uÆäMö#%²¶×/lM²`Î3 IBÅ ÆêÜ£ÉPbî0*z*RIz»·M·7©½MÍv%»´^uå»ùÞy·¦;¹ÕÍË%ewhä½#.ºEhÒÐ% Ô¦¯>6õ|,µÁ}l@$~×Ú#%Üà=Ó$.4¡°eÏEY $$gñ¸|o'¯Øÿ&_xr¤¹ße{Ú²qõøç#Øéêô/Í9xóÏsLXËüðDoÃ7æzF%A\Gvíg}¡õ¨ÄhKmBx#6I!yb°hÚùëí*×Oé¦Ïî§{hVø¶¹[sU>þ³Ö2f00$Y§ÓÄÎ+?ßó÷ãì#%OPÐ?ÂUHïjÍgy诨·«f#.¼çr£k¸,CÇs(lÈd×XT¡ #.-¡¦êTÞè`¦`0¹þf( äC.¸hïâÜ_<rµXzèý¦.[÷9WlÑþDÝÇ~++yKÜDÝèó5Û=ÇÝåóÝæ°_uZ¬ÎûÛItï½ìßi!,òîh~aÑCåð#.ïv±ß!@»#.W8Gµä´®M[q³ó'ôÿ5çcyÎèóó\sÚUÁ´ü³1,;næ)È£D£lè¢{Â#6üýEªRNÞϤ:oNEµbz©5RöónJ¯\E k}ðGp0³5+"¾N¤z¥|JNq±z©$MÅkÔÃâÁ/H çx8Sø{Qy´¶"ØØ}¹ú+<·1#k²*âªhü·ÖÐñÓãïí()de1*#úå¢#Ñ{<¤©#6B~´0úÑPPa¶ÉVd¢6jÆl¢JV++-«M²ZI[Ò[YQ¦ÌÐ @AdDõü8üúÒZ§U¾¹G]WHsÞ"zådHª2#%È õúÐú à×ùuÜßÄgõ¯"ÝV7Õ6?e¹¡ðÐØë£5hXdi½ú#.«,_Â*éiâ{ÒWÍíïBI*@<&k(}¼Ht¯MÍ#.%hkI/¤Ò²fI¯©ÓrÝw§º*(»w*R Z(íxÇÕN{Òup£&ݨ$[j]8l JÄ*ʽmî°uA}Cˬ ê##%©QM¢:ö捻*$g¸À½3ÂtBE ÁP'H¤!-EjæÜÙ+ܦl)S(ªf#.EI¤)¨¢ç÷O°h!ØÜÓ&²Ð8@#% HAdANÔUÔ£Êúø>|Çí½÷z»Õr¦7ËHdaÅÂ&ïfA=/Q ywßv) ß#%ÖH}0!ÂÓã!ì?çîÿðûoçôü6*9Ã}âHß$Áßég/b¬5B^!Õ i >ÐüÝhFD"°¢#誨d|M×½÷ÇNV2]Q5J :4¡x¡²¢(.QÒHMn]E>¶,xC6th/×áÉ»²Ô{hÍDhËþ8_£÷ùóÄõÒ+µA#.¬Zb¡ÿiÞ0"$qÝ»1ñ;£n²èÓxIx5S²ù2ûõ#.Ou *}À©9,Ê1üKûEåè')®Á²#% ÈB £Hì¶0º=IÐøõþÚ;B³q@li8"d3¿!û±Üx#.ARúì:ýØp´xÔ $¶¯SÓÖû·¿'Cµ¥ß£sì¡ßlQñ»aúpð:rS²^uÍzë³ÃéÊdT$Ö`ý²À >·D=ÕN3%c£xIîÝøµÏʼiÄ=ÏI#.-3}ûüÉr¯ÏõÉÀÃÄ#%ÿ4vvu#%ÍNvº÷n¼BqY¼ê (lÊSiLúÚ¥Äcí&b3ãOx±»#.k#6P2C+´ãLjAçXô9¢pªq¯ïf÷³®zçíblS¡-§Úá&+íXRka\¹ÙrÇ`X#% ⢡ë ò£À;x¦h}§6uò:«1[w~ÿòÑ ³?Ä7¯(iHPjÊj¨¨4£QPuQöt?_ïbɱù*îíw(QaDçéýM ªEbyf:öõ¯ìôeÕË8C8èPX{il[ÍI~#6!OLcì¾@#9OÓçVvÐøX79° #¡@úA¢V/5MP40#.»Bgð¸k7ÿß^×ο}Ò¯Êùñ(=côôþÁ~'¢!ÈD£v^ÿ#6îóÊ@²²ZÐXzñÍ}fT°Þ.Rá>çæÞ¤SÚ¶8ècs(:óÁ¿>z ,>cº¸½¾1Þt*U¶¼G¡ÔLc3úZo¥î«ÂÁÞµÑáè㥷;WeÓÇc¶¹åpçqF;jÌt,½ÇÙ¤mÖÙ*a\£·¶|kµÐ/ç¦ÅоÍh¯ËDP$S¡x7ãm£"ä[lmp`¯h8xÁÁ}7:Ù×líA¦ÕÃÃ|v#6õw;60ný1ljmß>øµ;QcµnÊ$[9µÚ5)ÜQaH$ì£h8âæfÏ{xÅlÔÝ.£Á°_+À£ÐÑðøbsaצóëÇ#%YbdSÎdÆ#.pûs{¼Il0ÜûÙR&ÌêAÇ#6ñÿBHjëP¹A골)HTøL3#%!+R¨Ï¢VAH©JÙêÄcv>8}¥hà÷·2Ö|ÊöçÛ!¿#%ùì÷;vÀ+ Ã"x%õéÑ×Ûc@¤«x@¥Ñ ºï¡8`Ŷoê¡ùÁS'+ä9Ùýâ6*êvòñ¹lØ6×ÆÛywPõ¤/ÊfïWÇ ¬ï¡ëµ#.W#Ãòú¾ ædôn;vêÝFl[Ú ÷w6%9ªMÛpZód½òK[?i`ë¿WúXAÔÓ}{n#.˹ÏeAÇ=ÎB:£ îÎhá#¯$ïR¥"Ã!ÙÙã>|÷É8f#.(¤SôܾöÒcC|¸á6RGdõLÅõý}ô=H )G¯÷&r 0Áôzs:ñwdêßË-㡧"Ö$3!~I$ß¿Ð4!#(í¿ Ó]àôöklÑü1v.ÂsϺ&®]Cj¤Jöm7ÊöÚ´õúAôöh)(r¡ÊVTu©£Ý55#hý~=Yäk©"N(Dï·Ká%OÔLzJ"À^q\øëÑX0¸°&ÃaÅ?Õ³hFE5|øeëëܼó¨_ ë'_·&µîP5' ;ûè`õVSªS¼ª*·Us²43d¶º\ÙIÝ]MÆÚ[]¾TR5 ²0¹`¨ÈX¬%JB¡i)¹d¥ÖpìnæDp¹f²áݳ ²XÒÄé½Vùµôh´55f¬ÊE$M¯ê ï!åÄ£c#6låÑ1¥gkÏ~ÓcíÝèginÿu[ÇPüúᤠ×#6Ê´é+¥dÖm¿JâÐÂO}gº#%¨#%ÆÙCÜ#6tü¥È|lûäðv+ªÁÂ"®Ý ÙS)D¨ìr«4óI£#gm±°æ´Sà¨P©Í×pã²µma·Ø¢ÏÎumwñ`W¹ ¤vëC0Ù_·«#%b n*F¢[föUÃÛ¦¸í<¶ÞNHONù'ùîHÙ¥#6¬ #.¬meQFªd°QB$J`ÈÓD©*X²R A¡iPbB>&í'5mÌSÀaõP#.3¼ù«¯Uõ_\ÊÆnëµXÚIét÷ÄAÓ¹jrir%§Ã^[õpÉ!1ßй×ÑXZÚ§TÙóYüÕfǦ³¶Kò`^üBþ:â"^%GPß:D×-nóD¿\iKÛ6ªª§£Ú!ÚE$H#%;±Ä+¦ûãÛþ:ÁÙ(gëw'`v2OA¸ºÚ¡bb$(cÕ¨Bô6HÐçªõ&:åÁ[ýBðn6LÙY¢&oáoÃa gZæ4ÅS$.vøü}^Gwxù?LD(:íÔlÚ£Ø|û»^ys*½ oèoè¡ýþ{o´Ò)4±"EÖ"ÎgÑf¯:ºJåM.î8gÕô8è$ÍI¬´e¨Ùò7Ú!ôäþF9Îòué¬ÌV°WT vg÷ÙîN^»Þ×·t) Õc=#j7®çkÏgÔKm&ðßÌåܹÁ5.SêÔÆɸk4JApN:l§eÏÛÆm2LÆ?¯]°ËYØ¡¶¯Áª¤úCÝÂûªC<sLTCvêÃA ´»Ê/>!!hl5ç©\¬ÐJ\¯×¥ dHÂdê43d=BÂÁH#¢¸pK5Qz 5ÑZt%Î^EA@@È_àæ÷e{>ñ¢ ³<Ô ²Æw+¸s, "õ5#%B «Piuô+55ÁÚ4ÍÖo.Æ#*H) BFõ®¦`È`¡âÏY¥Âz¢ØÃÉj8MË!KI} A#.``(3UÀõ¶Ô&¢M·ÊêëlUj0À%Ô¥-Ù_áç;^Q=õ\¿)I#6w¬©H¹`Íöò¨Åïå|ÙF×mÐA;8ck³èÚ{Î{44 JàÉÜÕÏ}LPCæyBM±dY¾«²ábyOÄýäµý~ɹúØàÕ#.¼C"¶I<Û;úÏÕ{FÊinlü~}|ßáñBûÅÉ{øºF¾ dìàÉ#6çîà±!!1134ã¹c÷t³Ê'HC -&Å#6°ªhvÏWqþDÈAèªt@QÙÃÇD¹Ö [!äåRÉÒs'tÃ-T#%g£èé*ªÒYKt¥ÅF"(«UV#6Ñ0&(÷&T¼Ç0}zO²Qj#Æ% N¼±¤n²(VMBòÑsýì¬ãb¨LcC@! .¤ð¥t1'?]& Õã¶ØÀÀ¨i®(D÷¨æçÌâõy¤Z¬Ý*BèÀ½ej·Mdø¨Fí¢FtHFØÑ}ÃZ0À"'¦?ÑâÊõhØÒ;ðdYC*Ï;C¿ P Ct_ À#%2Nÿµª©°¢dÔÔH<ü%ÝqHMÝI\uª´ßßÎ äLĦæêpÚMÒ<ëç#.ÚÊ8ôã%fLQÇ&ÑÅ\* å01ñxaj ;ùª{è<( pÑ®=¬¢ÿHy!wD0íµÞÇÔAc&´²b£¤Ø.5sSIý1ôj2¶EH¢¥·ÆÏ,k¬Õ=ÍñÚÍÍ2äÁE¸¨(ʽ :¡9Zkµ©´öO<שMFØÚË!Lc`0Ò3s@ï}Y÷N#6late<pÖ0÷J"DzØØÓßyCr6±Ë#%=l+§j¹0jÒOþ¯|×f>-=q¦ûÊß:Û¿עó1Èø¹¨õ ^¼P\aa£Oö¶³r@^õéu4¨ãº} xÚc4uÆÙàâ×Xgds°;îæ"ÆÖ,_ãMþºláÇtï¡ÛKV¬7LÅ¡8 9À²T(5TH ¨p_;K¦ùeÉYJ9-Uà AìXÛIò.#.áï#bìlÃIm£õU±ØdáA´Ã)jѹ ÒMF Ý4m¦¤j!6I&ͳ¦&1>ì!áÞ¦°ãm.[¼R>Ø]Ã]+ÙÒí.ì]¥ñéx·´®jñaJ¥-#.ÐÑÇ#6%±dAafÂÈ[&fVî£ãøIå.Û¹ðÇ9ÝMLÍ5#Ô#|¼[AÚæèu_kØAÆ:QB3³eÀÔ/ð°ÎÊF ws+¡-+¬pä.QS&h%mKOÖ¨fö¬¾Ò·ñßÝä:yGÈ`ÓÂ$F ½"»|hÙàP;#.aHêÅ4¦K_kà@Çip[66y3÷óxpBÿFýfÔLâ[6ãknk׫®TãÝ¥¹ÊÊÎúNº¬Ó 2I+FÂmáØÙkå>)4+.b$馬ú¨Ë¶?m ÃS>^O¹ðã³*0üÉÍhæ'£~;j0æÕº5-Nîe¶F¯Á³9HßGIÚÉr,=ä°4!{nî8nØýÐëÙë ~Æí:gg¿Ð`È-@Tùÿ/¯Þ?D/«¹ÕíاÁB °!D±¡DÐEÏ% #.&3í÷RÖâ6æ¦÷0Ü Éu*:hë$ÌM4h@I& M/WX(,¹§fh#6l°#%ÌSÎ`°£X n¦yÓzÚ¹©i¥RJùkïVr2L7käÜrE¤¼Ö¦EÇRJðÉ·ÂwXU:½c7ãweûÚ(AÓ×Lo®ÜXçû¡¸×-=®1&òXËÙL9É! Ù}Á¹IǾä\y$þÉW¦G~ÃE4ªm©ëS_ÉþßÌ G®#%£sºvYBog?~ËA%*j×Ú¹âÛ,#6ѵ¨¶¼TjæÕ¶5¨ÖÕÍmͶ-V6«¥¥ÖévCÙç.'Q÷¸ÁE5bõG9;#.¶ïY4¥(ö±Ô÷u;k®Û+¦¤ùï4Ö¿D4$S&e3JÓ,É)I¦)5E¤ÍAúΤÂZÒ1Q4Ô¡"P¢´±¯~Ü¡ZLY%[4)4ÌhEQCM½ÝDFÒY)¤PÃT%¢Ò£EL¦FhÆL¦)¬TÊ&%!MA¨ÌA¦LÚcH` 4ÑÜS¹&óg¶§äe/è#6b|[|X&Aï~lU_SBÝ×ÇøfÌþ¢;708ëY!,Ìm¯ÒfvòúsÁ©Ù9`ÄÞ¬ü8Î#.©4czKÖãj\ 0¬Î]iÙ¼¼Ú(5÷ÐzàmÚn.Ö¨,mDñs0³¥xÂxâN;Z-_ßK¡# ý}úYJÒ»0te^ÎÝfw~âÅçãîùA{*ÂïÃñbm°Çªd© ïúûZø^Ûo³_bc5 £#f²V*(i`!Faå³><9ôí0ݽò¬X #6"tXaÛô3³ÙyèNUMæçaëÔYbÂ+ÏNbC4®}û0_ê®[ç/c´yOÀôW¿¼}#êk#6xn4ëOåûÒ3Ï=GQáíPê+|ÎàÉ ÒV_£ãfåÄw&}z^Ë p{"r>Mõ£ÓG]eUY´#.q¨ E)¢AT$/rdÇ¥oKý}eÂGÝ2û¶ÛùåßXÇÆiKôô£¬Ê%x4ûmÁ÷cÇ$I*#1â8-¹¬-ߣ¼8ó#+ígÇö£dÎCìÖ÷µ« ªIm¦úõöÃ{N¹`g"âPR¨EΨ¸)µxãcB?+ç#6cguVÖˬ!çE®PÓ#6Ú+G0Âè'#66[ïG8 ápI5ö,nm_&·ÉÔè2 òí¶£·WÂc.[õ"^7L³§<1YCu-Í4î'¼Ñ¯$º41²Úîg ®Ä©OSååä½ðæ^R°öAèO?M" CòqôÂdìNIÈDBª´ÊxK'²Ùª ÕµÞ¢gd6Eõ)×FÛÀ¹m¹¼2ÙIb=OiÑ·,(Õ5X@ý\µê{w÷7g FÊHCï:ڷשÔ'®½]Æðëì±õz¼ Ãíúëïúv¢B¤xà÷Ç}IÁ\³Âw¢âvÏ·§ÓæÖ_¯¥ø? ç§ÐªX@w Üóß5Ìííá#6áí)~¿.wðzàDà ¢nGkBkjl8ògâm»]%};àf.äIG^fPså3 jÓ5'B;Cq¬ #6;ë<rÝ &\?#EC8(p+x#.jÝ_âN®ú9pÜh>?/æåüÛ>é5ú³0ù²Yþ¥7Q6È£ö0¦Ä¦aiªF»ÔÎEL¢Ö¡Âu§÷5Ú30ÞW>ØÙÓ©ê<Ô4̵¶Í<¼ØÍ3©t,Åq4hÔQSRJbã5¬D(E Æð¶ÒçVLÂWUÞŵ¬ æß´¥(%©ñ?ÕKľ$.¥âÃ1^{¶S{ÛeóL:Ø"a*cóuo\ a\MLËhz²IÆ´lÆV#6¶Â'¿S³;Ùï¬îç;WGÚv Òá8acgµ9t!éî^Ñ´åd»Ìê5+6É5#.ÂÉ,0&àbÛNJÒ:¤é°~g]øì`ɽ/Ü,7#6ÁR[Ì&*_¨ÊÐõ¡êìí§4ÍTo#.ª?02!ðnÐ6#.ÂΩª²æÑóÄï4Á&:ÏJFìÀ9]Ѥ]Ò¬ua®y:0jæó2w67¶LªL¹$ôgç}õ´n£ð@ußpBí ´ñÖ=,æYí?9@ôÓRP±áɬ@ºZßlAsø;oNñ©¦«¬qbÐ×gÉÙã6ô¯fl-&¢<ºF!ÏOB|VvÌïDDÆÇr¯/,¸Úz"VnöÍfrg£ÑñSëqHÎ:Óº¶6´=V_è-³eßÇ®ÚƱãæ·mO¸è¢õ¸t¤÷)0eÔj§=1åÎØÐàF§1ÜWVÕ£i7îæ)¬Rãw¾_<ã0Ý®È^ÏPÜd>ÃÜllg:ûà5Úã%¬GQÄî²a 3§¦è:Ó;1¢dÆ9°Ç¡n5´£Í']ºßÊßQt×\PÄ##.'yJX5Ñ\FÖ¸2L/Fò.ZX]ÔG¡(¸jS}5#6jåVͶã]*ïXTäðóqdßûªÚöFSBcÕ\llÏ^sÇ9*Në¡Ü,ß]ÌöO,ºK+çThu¿(vÎ[=e´Æ¹CAibuS"q0V^£ Zk¿kO+gX]°ÎNe6¼_y#nuÁÕÎk¦©Éct9)¯Y6ª9àZnl8\e¢±¿#¿A#M|fS®±*CP7ðvB¦EVöU;"áÖX.\[DY\('¹Ä>;Öï8óghh:yYzä×&YNÚ0,¶iQ!³é¥ØXlhÍÍÌpÑÓNVNÚ]#. ºÑH.q¼Å:¦ÌRIFÈ¡bÓ<P¹ÔÂÀµ)>Û4=¸ÍÃ#6Y¬ÛëEÎ&)Ä+æaõÆ0[3A@¡®bXßQÝëí*1¤X1qIN~.2ߩݨÛháÛá£Ô7á) ¬neïpOVêÑÙRQ9B&PÆ7ÊsiõncºÍ7Ûu³U·6vublâÂçìwÛsðüa½evâæfcy5Ù9ݬe|[Èu`z§ÛL>8¦²·¹O/¦ÅR=:%)Ç:Ó{¸ÜÖZÍQëF72Ìf2û"t[¸LLLb|¾ZÏÔáFcêEæðó8S7G´ÖQ²´ÓgórâÊܨ;ç¿©Ç1£W· i©#\Z%±pð²ÌÝUX6嵡s2úBº9H4qÆ:jn¬21ÉO)&PmVÌâë\[lÖfõ5,yULbÇ0vB ¢&¨©ÒªC¤r# SH^éi!°Ó×ÆÊ»I>ívÃ8YÙªüµWa²EZN©ØÏ+aì'gj0²ÕUÎâìrÓÖ*L¾#6$§Ê 3vðä{Á¨·É"aNû+â(0àe#6Bu öóRô`h©µÃpPI©,#. fFèã#6ëÚ°äÚ¸c¸M©_{RÆ£eé\½1åf2åR;ÎZ©a®f%ñÂb"âzÿºïÍ·9V¶ßé2#.¾¦¡#º@DE»ÎuBI@aàÞÔs¯#]Öhè Ph}èuz1Uõç tÍ®NzzOQ(¶Twqh÷Ä঴üÄõRù` »pZPLÒ;Ì7CN]"ÌÍäü#6.s׫ZÃ4ý½Ø'»õâÎ Ñä^île,Tm®t ìSR3@±0îÃt¬y\)&#.:b8ô!ËK@õ´]NÍc4ÜÓ@rÖà²e53Al2ÈbiA-µRrîvÖºS%#6#¥ÍÜ ¶ói"2ÐÀ °õ3SdÂÅtvNI-"ÚS#.ó['£2ä`éRqfàd5eëRª#.XsL%q®i¶L§¤n2éÍc*±<.Gâ(N¶çc²¥i¶m£¦TéÂ&pL*[#%X*tvmÀåÈB$I3¥/ObYÚD³»w\ñ#.»dÃíxå/ºï#.Ó\lÜêÎ#6eÊ47Uç3}Ç/ÒÙlpNZÖ)£¢Ájx#u±¡öMXNRÎÒ¬³Î ÔÁ|`5`pËî¸è²3Pòàf8¬&7PÐÖÆn°Öj;Ã'CS _¿&ÓPiIÛ+]#%ODö®÷Â,zÜÎùèe̲¤9i 7R#6tÈðS0@e°usÇùM×#6KÕ5BE¥!UAIHX.Ëb004ÚÏêÀób;àG±.NâÑÔGIF1T*©ÒNï_»;QwWm3oüòÊA8ÐTX$GaJt®ÞÁ`g£é®á N ¡}[aY¢¹I°êÒB5RÙÂ[#%l8Øq+CûÈ¡¢#.F+2fisÄØÜ l³3YÅÖ¸©Hu#.ÍîÌIawmw#6nòaæqÁÊWÃ;ÂeUô88JD61C#%CGfú1ÃgÆ$±ÆNØÃɵ#.fåî äi q¥º£ Ã0é#.(à hLÉåJII4dpjìËrÁ·i3fÕ̺ÇEÐÙ9Fm0²jJG8ÒgtÓ^Rg~V@.·uXiØl4I%ÝlK9Ã00¡Ü[Xn&uA#%0IF ÄúÈ%#6¯qCÿ$R5Á@w³;ÀiSh¦² Ê#â1Aÿ6¾*?g|z( íW¹ *I"H#$d#%|jÇØ?´È3$ä@q:áÔ:7H¤ýhuF¤@&È4¨±TC8Ì î#%»-=Ùk<÷º~¸X$*vʪL>ô ÷ó¼JÓhiÁ×/Ô'س7®RÆM߬·YEr,;Bó®_}®P«4ó¸ëá&A±´Æ\©s'M.áiR¸k5 ÜÖBh7nÂ20+aÀ7èu%¶exnX!ÑÕöõ#%c=¤×Àæ^çõµ§4pu\0RÈpBÿev#6h"J¨ÔËkñ¦[m&òRjµ*ÕáPÙR² q¶X¡1H_§D#.o=#6JAµµÍBp5ã¡\¡íö÷¬C$;×á8·SoWÇ4íUú*#%nùnR6._¡SWwUÙn»³.nºn¨-sd¯å¯5<¿Fîȵ¾*ä}î³ÓÁAáÖ<`P¡ý÷©¬ÙLv*ôrð8«#6#%|(u/¼qz0g-Z"½(à{̸°'ìò@7>GÔ»ìo?6©2.þ0Vè<²¾Ü?Ø|~rÚ=¹ÈFÙÙwE¹µÈM44¨ÈÀ,;Si#67 P¼oÆnF¿½µ°bhÐ1D)¦ õªS@£¦n0.ÖÒ.eÆùA2Ac¿´z¸äf$YÞÐQ#.cG÷±3þ!¬:?+xø Ë%êá¹A.¦9FòKPí?Vþ?_¶×äUi´&RkF±£Q[FÔIDL`Í3-lXÅ|ÿZ0Pì´Oïö¸ñÒ´TîRºÔ᳧zäK¼º:Øk5vz4D+ZÂ"kÂÑÄDFÓI0#%¬D¨í #E¶V-ÄÞ âêxÝïf§PD`@Ë[ÎIß3_Ùk̹<æÑÛÕ~«Qb*H²j}J²a_x;wÙ$l[^ÖAõ4ÑLÔdÂËpçb7úN(ÒcKi"ÈF'¸Üf5jå]*¾M½KÓoB5LâÕÙ1fR@l@ÓE`+K³D#0QÆR&lc8®åB+ Ö×ËHyÂ˱JEHÐq ²@Q¶Uú©o#.ê;eK¾ü'ô(ïéz#.sddÞí¨»¼è%Ï$¡ïÏë&ðÙ»#.PÔ HåïT¥Èõ¢®î°]Æc(i°·Ej#.^&²ÐåZHp0 8Wª.¢cc#%mÆLN¨L uÈÍY^sŲñüÞaÅ#%ò=§wKbm´lc+A)aLDHÀÆ-°5Iq0]i>â k @ /_¢Àm!* I,Ëñ ݼ;âdç¬D©_&,ŠúMõÊ6Áý{8QÌ`o¨¹U¹¾NJÚ## qöe]²gÞRrE0;>Ç/¼Ú#Ú:í¦Æ>µîÅÇmcz"4ïU#.è§2]õÈl0ÒjøáiiZµ}køw3FC®zª¶i!KábÇgØÌ:'5bCèVmÓc{^ZÖH8 ÉË¿+#%Ó¾æÖZøAËIÃ4Áùz¶^ym£Á¬ÂÉ'Gi±êØá9E$åP«%* ÀUeYNÜBº1B)#6×6¦Ô9sypYµ.ÝUfylM¥çx¸kÈDÔëi¦lïÊ]ôÁúÑ ¡C|ÐÁÅF1#6hÊ7n®ÆbC#%ktE.J ÔDbTJ¨ Q$Ø£J#.L@Àc¤#%-P$PRÄ[¼ t`luqlg¨LÍ#6Ð?Æ@ ®åB<5í¨;+Æ>ER+ýÜÉz¹M8¤Qb{(=Gø+t Ãï ~L>±ÿWTª/¢ÒkºÓÏó<1G¦A¢|A]fsÕ10#!ëGú"dFHÅ"½«bƨÚɶ¬ZÚM« "BCÒ÷©5Ï?=xT\½KJåÈû ó[ʾ§ôÀikE/³âk|t¶u+W þ n.¬ ¨ê¬ÞÔrØr$®E#.{:iÃYÞ%leäʵS0:2¥KYk8ißjÓm&ìÙ&èdñv5-zÔbºSc³AÎ##6pHÒ.KÄÓƶð¤¶Ê>-ÌÞIS1d¼ÔèËÍ<»SâKÛ¦3Û$iÈ3̸jMÙsyô@#Dmãü¼ÕÁ(Ñíju¾N&Hmr¦=fÎþWÑÇàËNÔë5ÀÈå˵ÝÀÆi>Sæ)1jnÀI®$ÌÜC#:¨y>ÖÞ*¨i½ðyXÛzMp\ÎJù}e)ãï3Ã&=¾¢¸É&B°âðÇ"í75¬´ÝÎ+c¤ØàdÌrpQ©»M=íW0arr1Æ@Æõ«t¥XEDLXÄ%ѵeÌôö²ÒBÌ´¼ËôÖkUã\§©ê^y^¦¶¼¼âƺÜÛiÖíª ,ÜÔsK¡B4ªä!_ÁhRM¢:«#ÿRDõìͤDkm^|ÝÅUÚì"hI°1<¥jÆY*dÂK èí0]#6»jí&°nÝuÝÅ&ñ\µëµÉ§®ó*òlLi[©Ãc]¦£hÒT¼e?äÐÉHà (¦Ñ³R¤me-¦U$ f±¶5¦¤S5ÔµÒ´²5¥SUF6¾^xMEª*fVÐlÒT7öy¼túccQÕ©£â`IPÀ¡Q6@bQQP´X!º+çÚD='qí°z³Äõ.kÓWéaKÞ9S@Ð×î6ýy´O;Øngq ¾ Oz³,§EÀËÂqhöëÏKS-Àº#%DFßÝOXÅ¥*jXÃɪÓm'ÓO#»;ÎLÀMÉÞ¦l1JSí"[ÕKR¥U(ÑJ01!¤Uý¨¦Ða#%¨Çj#%¨)"ìØn¢¶Í¸eµsÆòèéf´Í:ð²ÿfÂs©÷ pÝ#%H 5¦µ.Gf`#6 ò®µ2ñÞ eRD£T5ïÓ×ûûyk#.æñ#.ãÀÇ=AõÕê4\¸Twíé©Øm?2s¦O^ßnõU\«#%rãÑâuJÿo¢Æé%òÅ´AS¶(L!¯$yB`w?6Èl¨íx3Ýb ÍÁL8o\årEÎD¹S¤,`&Q¶7ühÄ´t{Î+Áon/1~»bµxÙ#%à.jßÞ¡ö ~É0Tªþ¯æƹ¾óíèlodð8YGçÙ|fQ¯ãûô0*mùʨ< h%µj6¢ùýÕ²Eâì(eQMÍmr,¡¬ÞûµkM¥c)m&Ê6-")¦Y,¦JUÅ,µgå]aM«)lÚ1&ÑFÚ¦µMÓ+"µ+ºéµ }í®Öí^Ý»*b(2#6em¥)IkjhÆ¥Wµó¹Æ¯~íl-cd¶¶ÙHen]ihÒeRMKmçáM´Úl¡3#6°ÛilÚMìêKlcãnÍó«¯;R2hkêÍRWë5x®ØĪÂFÛÂk±Ë[L7ô®ßõLUq¼ó¾TÔÇîRÈ´,£^?/Ëá>Ïw>Bmôs'`ÆèOeÅ3$SF¯<XqIFÎzTX@÷Äñ ª×æmã÷_NñW{<{1MEC=#%.b¤3ª#E À$T B 6Ø£Ç^S² ¤"-³JÙ¦Ú÷mªé¶±o²³KÍÚå5soº×ª¢#6²QdFAôR*fSJl)«iJ)Ô,¢ EÖÍFÌRÓ3ÚE E¥&©Kmi¶iY5°Ò)R|Vå(-EeQ-%£(ÓJHQ¡´Û)M"jLÑ°Ó1bÄa£+eØÙ2IdhXÔ±jª#6ÙRÉT¢©Y#jQ#.¨µM!BJLX)2 ¦I¦Jj¦Øƨ²$mE,LÚ$6Ö¥ÉFÒl²¶¤Z÷Õk»VÒ²ÛM¤²ÔÞòÚ×M6µ)ª²V¯f¯6{*¹zÍV-¶RÁmFÕ¤J*mm£ZúáÖÞcí³^ù6g]! n5Æx§{á·ç5ª÷è`fþÆpbÉzì7ùWkN-ÝðÞW ¸îmE<³¤!à#%¤yFäoDz¥ª$>Xqå×⢵åE÷Äô^éèøì\$1gÁÚa>®ìk£g]7bÙ 3meÌz4º:¶.L@ݤ¡áÈ"¥+´Ä»/ö7ñ_K3ü½©=Úßn9=½C#6?q°Å@P \cha!¼ )Ìæ]28ÐÆࡪ (ÁW_@pÄ$ûŽ -θ>õÒlÕsuæ°ÙåÈ)P;+ôø :ólPùÀ.3ôÑ¿I÷¾×ÅLFz%;8ã»m§f¸ñ¼õЫ´Ô¬ovÄÅ.yËg ØPÝM±"Ê~¤}þ b\åö2eÏàØ¥WCó|såÇéл\Lu#68TóT>µKîªtJZ~ÙVêøPvÙÂíͳÏHdÖ°éè#ÅÄØÚ =õ øs«~OØõl£qGFù¬Öû#6¤Èƺjµ¤7Ò6Wi0½«#._Èé}/[onÓ @òî#%#%lj¨Ê²N"Q@R+¥rÔ'8#6Èo(Õà "2! ÖDëê¥Ñxíb¹Õu^¬U°=³¾_vóÒ Xdé[&ya&\TCA¸!$*¨c#.ª SLÖ`O¼I.!&*x³VÏz§@â]7ù=ý«¨á×èv#.çWµ±ç]{|)LcÜÃPó fÛÊÖs²D\OúÙÀ«Îx #6((S)øbî#úÛËRdA]%Ù@ÿgìºùaZÞåe±F6ÐÊÊHFæª&cD2L#l#6Ðh{ÄC5U.mÈÁ¶ÄH)fáu'6ÑÆ¡±ÅXVFA4^Z®¨ÆÎjv©g6& b S´·»RÅF[¢ÃK#6ª@Q®IL*cð¨Râ¿JT#.t#%6:^ôtqsèÕ(ñQ jÔÎQ§×hXÔz´A;Pl|߶¨4"ÑJÔL©ªhJ¸XÌîÁò`8ŤMýà5çñæk±°÷§ÁÜæ" k;CXxj/zø/#£Pì| 4ÉL`ZhÚ-AXAKëíÚÛ[EìÔ×9b$>#%ý0¸ Ìèª=V.ná·kmÿ>sê ý¹gźÆS®i{HÔ·t0Jc*ßÁ$çL¼·Z«ùß$!þ$ëÚwËI;àtnl øÇ-i¥!I¡#.njßRY²VTÊÁ[õððl c0¶õ«ìXlA4(Fë¹ËÈ/n÷OdçèÊô½teú&YùA16ºa2e8 ÔÁõQv!h+åËbêÅó¿r@à /¥)Æ®)iQÒÆâO±¹9&íBø>ÿ|Ép©*ÚYKmji!´:I$mDVCCpP±Èc&P1èó´âÚs½s¯gÙ².Û!H #6áPªR3ÂxQȵßxÇ¥cQ¢Á:÷Tshiß5¶JÆKF¤ÉÃ'3ÔGÃyÍãsKMûé:]û`ª§ ÃÂ2UKÕJâòÌ«ÏZ§N7~R±î(: @"¡ÌȡⶶQfíf´ÄÒiDÓ´ThA´~ù~ÿNè>èëTPåúÇQpº¢óGÇpó ¥CaFE<Q#%,2ªä°®Gíâ&±û¼á9Ťð;õ1A¾¼uÈh)¹¢`ÛkNÑD=ó§#.ùüq ¹[tcv¦¢â#.iÉÆLjÆD.Ã1ìÆVí¡¶&q±"J5Òë`Ì/¸:¯lF#6¾R¯OQz#%ñ=;NÝÖo+fy*wйçF|û Å"TX¥BSM4 DB ¥×*¯rïJZÀeE¤É@òrÎf§PÜ\/èÆQø#%»¶(tWx.ǨÚP QÕ¤BÉUN#("»ðX¨2#%LâFM`'°fT(#.à2pâ§.=ZpË×v3{×raY &&´Ú²4î¤G]:\clç¹¾,u/Ëß xµî¹anGÇå¬$46×PÁDùkIt¼îÂ2v¹ÍÄÀ+¹,Òçu ñ<xϹ½eäm "#%$lá`Ü1R ü{n×z¨¢3D¦ë2Ó#.äÅêí¤¯dòêß¹nh/!Ý]ñåîî¶Øné-ü:»+~A8uëÈN35åP«Ãp¼Cmí$/R«4²¦ÆîÁ,Ã1=;ÓPp¥'#.¾>ú UGLc0õâu{2=AÑ+½ëÜ('_¹HCX=DàmÆqzEnÆÅ$ONÃ-¥¯Ë¡e¤È#6¤ÍSY}¹YîêúÑ#6I£åíª¸%Ý£HÐÍ?]$E/]jôåå˼n¤ÛìnÈHNõæ½Z½jé%»mj©RC¤@ àmQc°^:wn) «1KÙ)y#6QÒ4lß·ºw7¥´D9;¢¾âênïÕ¢ìÑê§ëÛÄtN(Àºü5îIåÖïãrBÌ©[æq_S¾®¦Rg¿s%_Æ¥àM~%Db+)'æhwJM¬0 «ö5¯YFqtªÁÏé "ïª:ʽÕ4Ñ´L¢Z®QM4jW]6èrbK$ج[FßVäbÄVkãJ*¯KÒõ-kÆ嬳oßýþñ¶Éki¶[V½*ÝrttÊ7ĸeÀ ®h'kåг)ôãK ]¬Îe´"¶JJPÉB7&®r°2ý(-Øo)<( û7Îu¡¬²h%,3al!â ¦±hv>¹3Ù]´l4}»ÒX(¸ÐÞì½qOtT5(¿åiÀ¤(º#8+!iH@ÛaSòÕ*µVzPT*édWfTp9°ÌPð5 ëÖàtïôQìêª ¨ E#5ÝvÆÓ"£I´Ul#%&°ÝíÝ+Èt00p²Fù`Åì&á,Ü}C pÀ×t,Våp¨CA2¬ ÛÑo¢|¸¾ÀÞï'´Pg=b,q¤ B=cik=A~x#6gLüqöÿË.×HÂà\h]IÕíø1 #%¨%æ¨&?¿dÒI¡ÏÊçÕ~¶ÔØ;Îáâ¨Ë#.ÃÀa aQúùhFÍpA24»Mjÿ-F?=+áÿûRâl~C~$4Kç^n«&ßByï(íê`=4ñ x(«C~¿´A@TTвÏa81#6êå{ êÒB|<Luß»¤/6ìÙýðéÙÔ;Âûîpt6øSTSbGz¿Cé¿Êw.;=#%d#%RIí #6J¥*#6¡DYX@¨©PPfôlY!x¥EdBD b[3\0ù_a»ÌË÷¡ôq¸Á+£bÓIbÁNQ²Õ~«0GqÍ9e±ìSQù~ý£Ëj±DPõ$SÒÔ£C N/P¼läV_Òþ íUAd: Câ[!Üak%ªEIH®^E¿Wcâ|s¼R¨ÄÅgßêóåÅàX!`â«r'ÈàPë;OyÜbPWGçÄ>'¯¯ï`Ãæy~6×Üß=a§,»rÞtï£ÔHÄTÌI9¨¦¤¯V¾TªSRÙÍTþËÁI¦úËúPÑj,TU#6©3û®ÜSE,#6@¼I#6e,%ìZe¡Cð@ÃQ>9yñþ_¼ïÕ-6#ÆDca]ªñË<>ÙZcm¦É\ïg:F0¶ 0#BÌ £&D®¤ÍeµÄ±¡Gf4'ÔF4ÆÒqIlb-ªÍåLQX(J¶*Ef°-H#.Ôa4J@fµ@¤ ±I2ÈPµ´Ùbb$]ÌÐLïR`MS$µZLibm-äB1ç+=B`HVZM¨F`L%¥ª¤mV>Lä±¼xa¶EXVâÄÞª²¬ ÕÖAÉF¶áÃ4gJZ¢,j¨j¥0¤ '6Ñ´®è±\·6Årܾ#.ãc^»½.4<ºí¾-¹1ç4\3¨lêApÌjÓ´K&D`:3±ók0Ó,$i¾Kµbc,P¸yA®5&Ψ hÕQ.Hº5@ák[R²°ðÕ5O<#.C:Q¨6%Üe{îË]úÓN×Ò!£ Ñ uP2Ëñ»h|úim²O:4MiãÁÖÆïØøÈxÕ,#>¸Òc!I¬ÆñÛmwºòeºÍ7YºÐ«áùqüôÂ1Ó ÍÍÓ+p8ñö¼þ#.áߣ .H(ôMTØØ?9ø Ñ0À«¢¯`1 «þ8÷A%Q#FååljT²j,ªê£TIñnª0±¬QrÕ]JƬQ¶ÜÝmÓDbd@b-eAÔn*¬Z$A$TɸúÓøC )È°íDÔ@QHXÄHE¤Ç¼ð?ÙÔX#.Gê¤@ÆYÁáõ×g¿Â¬{S(±kÙæf¹!¡çò«W²®]¦Ûnºë[ÎerZOºÂ¡.TP¤IËúìÀ&#é¹ÍuÕñVã1 Ng°þ["ALàlBêPoÕTBDWáU¼ZPø¯4²mdÛÎÝJT²«æ·¯¥VòÌ¢Ù+Xl TzÅ껪-zjö»×/]nË\Õ|×ZƯ7uY $¶¤Õ©3Jö÷í¶ØA¦@¨¢G¶2<㥩Xý|º!ÔÑòkkE{\±È5¨p¯ÊE.I#%}3@¡ËÁ±,erIcÇQ4×´Õ0NK2#.É#%½çìè¤0#qÒòMÇnXq[l'µ}Ò@a%Ç¿¯3ËÂ74Â&iGÊ<Ø!DWbUTUðËÂ[åH=TvU Äh¸¨Z7aqP×ñ0»¹aÌ°oËuÍ>¨½ ¥ECObÈ(¿|³Mî®d=` T6qÓr.À;Q$!îa^Ò¥#.-TiKJTÕcj´×¼®ØÓUk)êWQ´E%D/åÐñ9çÙê°Ä@º5]°;c{nÑ÷µJ*ÎdBdñaöü6µñ³'¤.ÿ¤ý¾víFqp£FC²êNº3ìBKQé£4Ó]®#6¤Óý#.ËÌg8¨¼±bCÖ°¡ :ëÃPó¨êÎÉ&&42i´PËZÇ0Û#%G{ª"M18=ÉÝGÜ`Â+h}ñ¡È*Mbð]þáñOC×ÝXdI"BMçQýQ¹ì<ÏÖônå¦F^Ϻú¹!}zæ±Ë`ÉûdWß#"%54I7L0µ °3'øþ|@å¹ÉY¶çA#6?KämÉ:®MÓûlp(¡©ÐÌÒ¸×V¹ "ÄëÔ§VlÃ@,×j°nÅF@$+ûRM6SHDÀB0 D¢¥Ø#P³N5X©Õ4O4D1öÍá=ü'§1ÀÁ55Ò¤{Û:ðeQÃýi`êñ×Kã;4Ï×ú´1$ÐÑеÊc£çF^Ó#¼ô=¥ØΤú¡©§A>iéTSíMZʸk2Pù|Tà¨ðÛÂ5¶PajJLi¶¦¶¤ØÖe5ù¥tA&2ÒÏØjܶ¦e©²-,Í`³LKlÛl6³Lµm$µJ"©µ3f«4M5M±UQli$1H³$#.GäiGåL"±£æÙ8î¸lƸÈéáü)D M´VµÔåV¢ÚÅ®¦µ®kvo^aQoѴצÕû»ËA'"vC¿¯#%#%ÛFÈD*TK[R]Kí´·µUøm~B²#ùKÐ=Q_fÚÈHEQ ÆGúZ#>ÕaõóØøá¼ådzApQÙ¸»h¥âB9¨!áOGk§!' %J¾ØÞ!¡ìNHlá`G´>ÒB zAm¨#%û¢Ü%íKtD©ìByìçxÆqä;ÏÓ×8Ï<Iµ#%CÁÕPÌżÐyzÔ´àµ!¶7$¹=É6Ý*ax2^³30xãèpþ#6XXPµÈ p>W·ÑëU8;¡¤gê&LxÑ;QÄ7V«ZÖKè6x#6ÅéØ¡¼¸p[1v*®@â7̨·Ý£Bò8#. Ò\Ð;¤:háÜz°p!¬a#.DV#mbL¿ê¯(Ó4tì!#6°I£± Oú;N¦ÏRbå.¡÷Ã-+?£VF0¥Vªêãì~}мáömFÂiîAÁÆQ:ïÄ#%>°Ñ#&!¦-cöðtL!/Ù¯9ãvþWà¼è¥æÔörÍù[ë9+ÁS:~râúýt&ø-tõw¼¤¦åÆåÒñL ,SÝðð4Ç]«Pø¦äºC#6(,HQXPíÇéÓ9Àóx§ï¥½#%2Oùæ&ѬHø8ÕY!D14P)#.h¤4ÉÓL*v#6HÛLMûþ¯éIJB#.üX11¾"lN9anTG§d#6ì6«Æ% `6ØÄ´wc&µi︷l¼C#.@6dÏZ«Hfh ãëU)%E`Òc JO´'ñT¨â*cm¬hæF&(}q#%çDB ;sR; SÎTyzg?~<s/T #.\/lëã:Þo\qF(P¹¨µîâð8' ¬Jô*Æ%S ×õ-ªl;w£DÃ@äàP@4ÆB¤PEÐBÈÅPe'Î#6zx¨vi=>~¼® QÐu}Þ&`]|Ñ÷N^@ÃÕUBÅfÔUЪ`EZó}MI¢#ðGðGù$=èÞ;}%¡&ZiÁ]ä4¸¸fÇfÙ«ECn¢ÉBvP§`¾Cqh\5&+&ÉWsLjFà|Ûùfwâ{àrTPÙ#6`R#.Õ!æÊ%r)(#6a<,<Ï[ÞK:MåÊd¤.óÏ!Y;0UQT»¸Y¡õñ²"½®$D0øBR0!ÔÜD½.ØboìÀ#]Ì T`ÁѱÉ".)¢èÉdrf5Âó"^¬¿îihòÝÝ%|Á#6ÓeOuB¥´àÈ©PÚW.T²¹[#.½i?îÍL#%Ez¤#6©36¶~ôâüÞ*(Âý4Ƕ¿Í»CVnÙ=è¾»VâHfmÚ¨·aYeÖje 5VWE·[Ñ$F¥¤ÂB°NÄy3ó, /¼X¼½p 8¬§gdp¨:©´>j"ìO=H£EëeäÎh ï˧ÊgؤHÞ%?^uÝF§·ÙéV§mTS±ÄºÕ+njÜBðôÕ#6´×9ÍâBröÓ,à¾81rÂsÚU:âæìbúékÿgÖË:¼µÜ|ÖƲ:#6K%$,è`#%*¨#%ADPÐÈÒ¥h#ͨ¨In1l+p<;TÈ)í ©Ù¿Ó:þ°UyónêïæÔe³#6ÔeëÇ·VÜÞQöº1ÈßÌÕ×ë2Q#%dd!CÇBbuðE!¤G³v#6Ð($«U`ѽÀsqKòÙï Ñ£Äv\5Ê ÎÐHÒ%A#%Î|É:LòOB§¯ÆSÌN¦#64 / LdM´¼íÍr¼ó¦ëÏ5wÚëm¦ÖJI¶ÒËÇBHT*F2ÀD#6üÿ_¸÷J(-!þÚnêÖwÁrPl ´ W1¢ª`Gñúnî¿«Âb£ b´Fϸ:Ä6Ö4kR&'Ó&{_¿´)·w¶õÚV7t\-2áÖ5bB<* \KlH2Ym@¡&©ª"Ó-PÒËf{½nçØé¦{ÚG.®ÊÅz¢ç±¦&#.¼zPÕ1`W¨¬PÙ²2¸ÛO!-Ý0éàÈfÙF¢D$ #fKÀ0#.`ömZhmmèØáͳX"bͲ9PÃ(¼XmÌG0Õ.à£MËì¿Ëâ§iÅLüI!1²Éb;EP DüÀSqS¿c²vwñÄä'Ñ祥ÎUñ<þÞzªßòNuØ'úû¤ÓIáÂfÊbWGq'NÄöP!×#%ÄI¾åmøÛ^efÊdÒjØÕ)}ʾÖÚL®»U?OÇkÆÛÊæ°µ0}½ÃÞ^xÇëaÎ6<îXJ.mèÚ¦Òv¨"«Om¬Õ¨}Pr)N=\wü²Ë«(ײ|J+±±òT-ªä`UíèvÙïIð{¨óÎ!WâÛoUx$§áUýÇêYÐYy¾áa©<·ØÍn6I6=Î q.ê`Â÷ývÇ]tú¦øo¹+M`sZõQ4$n@âtÂpÅ&/m ÇãîHF1×wë߸Æ,bÅè¬ÞBðì&Ù3°kÕ&72^A#% ·4ß¹çLÌÑL´K3Jj í>E/»ÛêÛçÌÚA!~ï,v7ÞÛ¯é#sµzø%ªì2t·Æ¶Bõ-úð*¨ð ¹FÇò,¬ðç" s^ÓÅC^´GÌñUGÝ!p6m=ßmÃÝ#6NÓ0¨^b!d%]±-Ê.ÛJZÊ0O¾^!¡ÖÂ0×bí-s¦µyäÕe´SZ·°òüXKï¾fsMÖï%ç8Tb»üè\²?}{Þ>%ËÂça8ðøqgêd;1Cð)æÁ ªT'çd%íBnpêá·>¡¼»f>¥óèÄyKp#ÃææG³´ÕsmGyç cQ®»·¦Û%¶Ì\U#.¡$HH0Q·KACo·UïУç»R*·µsà$.?çûõà¶KªbÓ\µ ÅaÇY2J2ÄTX (·VyÛ¹ÖîuÞªZÛ¦Û#.1A¼A(ð ¬ ^3@¤dâÑnÀÕÁ£òðt£àyÅù¿r=÷·EI&þö01ü$Õ¥³º[Ðö"û·'Ã4|·låËMÓGÎòçQÝOgC_ù´4èÓwA0Cf±eÂEÃpÑIå¨GGè öà$ëªUèt§ÝÅÈòZ¿0óhäk>1"°Õ,W%ëFþä;ùq56z{þÎ@ @qôÙ(yCScpô_{J!0£:tª4QZ$¸ê×\×v庺ͩ¦¬¦ÛNݵu&ÄÚÛ4¶«ªØÑ\¦^.^]ÚVòµ¾l²@ Å#%C@US_BÄ«ËÚ5ê)ALjºr·S9¬¹ 5öTXlzïÀÊMu>#.3ïk¤ÁÖøûí#ÂÈÉ j÷â¿«Gí#.Ã0¾Ãnº·JYUiKí:ÍËaÛp¶<h6Ú`g5!5È0°ØzùpÕH¥²!ÍíÀuþÁë¾pS-VÞM¹dmÐL¯Üá¸6uð|#.ÊäÊÉÜ@à{&ÿ}vuÄE'sj>¦þZ2nÇË׬-å®Wâæ#%ß`+ÂÞɬí'm'·õ#.|¹_úuØÑTF#6Ì5å*oµµX~ÍóÂ\èÄgi[á4Gëk®]ä9*éitQ0#6ñ'êwÉúgúÿ§îoÛ`§ñ!(RÄæY}_bû.»áÁ5Å(,DÙéPºRð¹ßSX§%DAÀµ¶&¤?3Y{ÀZ$*Áömk_ªèzÔ.¹#mäÐl¨AAì[v,aÈ$ºvÀ¥+ã'C-®H4(an~#.ÐÅ¡´ÁëX> 7¼PÅ£ãFs¼ðEÓ£pè&¦K¨ü~iÿKn<£ª{6±gTSE_çõð¾ÌÏRI'EÔ,Ìï#.ümQºC^[ò#6Èì<¶èÝPi¥ÀûqL ñ=Lo³#%{BhÙë Ҭܿ¶lÁs- ¯¢jgÎ0xAËÓ¥¶ßgLeXd¬b û`Y)0(ÏQ3I! áô®ÔùaÃý¡ø̽:ТIÅÔeÁÙ)ýÕÔ<=±®áÐÁác),·[I_òÀ3r^B8iý5³V-êWBÆCGµ÷cHgMardæ7ÝÍO1U;æf,Ý1!Èkq.ìaì£P0ëO¯võѤÈgõá§NJ±ÐèO5Ĩw¿yr²þÊçõm|µåê#%ĨÂ#%p+ÓUC'ÕG Ìñä¦j&¨ªßË ¡!ÞÀ[©#%¦B½OE«¨¶Ö+Q´Z5mdÆ©5£Y,mb¶@¢²*TEM2 Èì5WÙn¹\ê4"Ô* ARæÀá¹Uz,.ã`!i ÅòìÚp:6ßvýøg7nYÁÞúËÝ;«Üd(])5«=:C÷«7ã-\õûn}ªcâÀuÓWCÈ2ùmFmCEli î°2dS ~Õê(åíOyÖ!¤ØwF¿?´"5jùíÌ<ÁCi²RÚPl.@ä#6ê%ºéçÓ5ÊU¨ü=¹Ñ®%O×?#6\¢p`vãÇÉ@;$Ðs]_2BªPôÐöVâ¢ßÌ0`Cm¶¬×7¶Ú9FD·7|Y´&©ªVÍ,[þ}¯]tÁ(L:"W. {§¶@,ϬGüÛoÖͽ(TÐJÀÕsª¤ ó£äI/#6½y³ªîfx²&qK¨*.qß<¡¥¥LÒ®%Å#6eq}Kw4(#ÔæH ò*EZ#66°Ö-5¸éW¾`[É@DêFq#.á ̪MZ¡Pwgåõ{ö²7>Gcúìcò0Ä5µÕÔâ»×võo1kpÄ&Á|ÙôO«Y ñ¦ãQèî>#.zÞ®ùÅ'èkj©a¨²ÐÈTÊ¥ÈläÏ$ÍíB mÊ=·e×àY bø¿]ع`±#% ª£.êLãÅÓ?ɧtÐnòu#%NÐêØL8»1²üÁð¢zÏpÝ#.½ ÔêônêÌÇʪKq·t/Bª+5ÖkYf 2ÉUBÆÐÀù¾C®YIô ÙMIÀǵÜ$Á¨Ø:¤Â*ËuÖηL«w]¥#jff±PÑh×]uôÕ<®óõ§½æèQfðÀÆÀnBhT¬ci0xÈ`hpTZÔJÄ0`Ä28Ü«hãÕJ!ÁÑS£ ÉLkLD²üaÐ6Þ(ÚßpHìÃWÖû%°Dûo!H¤HI¬j¬¦ºUÍôMÌ6J´¥\é23Í×Y2¤ r»àd¨Å ¢#6&Û¤ 3PEÐî÷ZH ¨ÌÝZ@ë²Ä0ÂíV52 ¥l¥fSµ$e6,Û3$ÈÛe-/]Û˵riÝËrAfë®[sNݽåÍy¼ï"h¡RÔ3ùýw³Ùf¡å輸÷íï¼öÕæ"¢FJ°ë¦2Ù¬ËAÁ\µh@Ò4EÙcÄôõf1ºÔ6î#.j*Ócq¡¨ÑÈ0À×ÙUkH°[yÐ÷´IòãÁ¤óßQÆM¦Òp&äbÓ\3PÍÖúÀ4Õ½1ÎóEåêÞnÕ zÚéEF¾ÊËIµð[¤ö#6<qêTU¶ÓuÛ5!(£dbå´±#k7+®6½ª\®¦øµ]ï\÷¾¥Yâ²"°£i1yic$IÙi%ehCÑVc"sz(¤ÝT&0ÝÜD1§~/êÔaáenÃ)±²ái©Ä3aCwc®<¥j[J\Mb0s.#.ç¶ÖÆÖ¤2Eõ5ß`il(A£§£G½MÙ·¥2ATÍn¦©Ü]ÏDOµ3JiAÓ«Ê_¬Ý»8+ɳskhÁÇgjFV4Ò.#%ÖcKlÆöõTMX ,A(SæXôçzGí ºó2Ìÿ#FÜ4úf#.ndÇÕ|PÇí÷k#zLö1ÂfÝÖd6róo?v:WGÆ.5Fcmäå tÈWÓÇ° 1¯ÝqÆM!j´M¶Vo¥Øz¦øã5 ¤§dvÎUjhÙµ#.\"ª9lT¡µ=³C#-ÃqÓéîó}&°Æ0#.7B¬¡û÷ Bì¤]¬&Áê$åÜ,eeU»cõ ¹¸GãO8a¤)¡ ä¥P4/ººëtÖ{¯5E]5fT@Ã& Â6:é `"0lU,P]§DÂQ %Ħÿ¸ tàtë=A×n¸Ø nìÁìüô³,8¤è×æ¤EþÕiqu#%T#.Pæûqb¾e4~¹(ÄHægÞ·f='³¦ÓO¾ï×q6ø¿yÃ&ÒVý?²çª+lMHÜúõCÔÞ±\öÍ#.hÅ#3ÚÚmáîÝÔÉK#{{ºNÅËÖåyºjð=y½\ÖM\l¹ÙK*̵ðòJpð÷uÐôÐïÛjØÍ-¿kÙ»£qFb!$-ÌÌۨټ讹ãÌÛF6qÇ8hPhÂ,CöºÂ7ÌÕãµCdÌqÎám#±M¥ÙBº¯¹yÐà½ë|÷3¿y!È7稺(4Q®ÛX0wù¾,h#6?äè!¸\£Êo/£÷õgg^i¹ãíÓj#.M,=6ͪë·ê³xFpSÑ4¦ì¨FÛ,~¦JôÖ±ÝrðÓ+°iá³Ýdý_>÷ÖéM¨#6îkf©l#6Ìë¡Å)êýá{Á=óùû£{ vÜé R$T@Ð# *Ì °´%Ôl#%ú H*GåB XtL,³:jU(älFÒª®Õ`][ÖéµIµwb×r髵·6îÜÈrêñµðË%H´T©«wUÝÚ±Z¦¾+Uã[É[Iº@%rØ¡#6BKI`W(0ú6nün°££aI}ø«Jì¹X½9*ae(¡Q#P1EZÀôÉ.p»RÕ·ÓÍÆ×ZïrÐÕâ¢%&±XÑ%¨OsË}2±PBTBeEªR¤_ÂëQMZÅf&i¥E±¶5E¨¶6³+Ó5I²YLÉTÑDmLɲlklÕçjº7à¥9?ÉïÐÐ>ߺDEOjÚóÔMª+ RRËð9ì¿âÆýÝ^lxêþeËÝåEÓ¸°zÃÅ8ÓÕÝóaT9ùhì !¥ÖüíM6´ÊѾ7ѽ]Bͨûf·äV·#6µâ×OÜêêFæî¢6Ó»³®µÝ¤¥¹«Knk5]¥+ZV²½vìÖj(ÄJE¦®ÏøHf;ÙYÈIb2_l(Ñ$D@ Ä:o',ÀÕPBMÈ4p#6¡a#.§gW¶¤¡Pm+Ä4ÚÁ NκkfñÖ¶!4õ >ûµ>ÖùñkÑ6wÄäÁí0Ϻ¼è¨ Ì]hÊ°,Ó`ûO]ÿ3]¸·7µLÌf7?,lc]ÌMBbA1H¬µ4Ýid8w&ßNÓ)Äv»Æ#.Áàu?²æñçãµì! 5éá1°<¦t2b²tÙðVþ²ðæ8ÀU;¬"ǶC}åtÈÏë|w½µ^]3aÌ8fùã=ù6´ì§Í%µ ~¹åѶ»zÊW\=ÙXÛÔZh¸Ïa°Ó(±Æmå÷<H°UýÒvЬbEÈ#6NÁÛ±=ôL~+"õÈeÛ)·È~ÏðV<0T&*ž2ÊuJÚ©X¡à÷BxQG` ×Øh -TѪKo/©ZºB2$"cü\¯IÛ\â£rh¶·{:²Ulm¨Ú¹U#U#%iy?Ò3vµÇ$eù»#%b Zü¬ßàTy/o\½Õ.@Úº[%´×]§·-lfmBÑl@Eá1Á¢#DBùRÈ8$j©À\0z¦Fü¡¸ á[oZµ¾[[fIlm\ÓX¾>Ù*¼î«Ë¼UÚDFÒæ»É×>µ¹éwWÙãKÁhã*7j*A#6´¶³V¥(1Ä*ÛAÍXU¬!R#. aS#6$DQ#6#6Æ,ÊXI vUïDdÐÂ%¢¤äÄã0õázâhÌ RLcAA¬T#.9?³¿Ïïç*®·(øhyÒ]aöàsÖÐa`ªsêpÄ%X¬gÕ3n#.Ç#.³ÈÂêH9F1ÖKQ·níùîÑÛÌmµ¶¾©kU~[Â` #.Ä;@¸â@HnüÝ¡ã¦Qð!¼*ï'æ£[£Cõmþè¡/C ;¡ø&©òƽqj¯ù#%AD^G9ÐÀÓz*J#.¬¤,XcÍ#6Ç+Ìf¡z#%fθåC8>yóvoÖ¢J¹ÛïFØØé8ê¦bCDÐ#%ÅE7áÃGÐ*¨á%ÎÞÇ¢tºÄ÷Å4Èn#6½¡1*ÃM63âqMí!ý!ȵ¥ð¨W¬|TaøµX#»#hLCZ¢«xbi(6³±t\°èYl EX#%$p4b9&K`È°y~5D¼_¼ #%¡ô^3Äê;HÓ× XïYU[ï"zGEMpùCݶÍêÑ|J§NqÂIß.k6#.éï?XC߶ óð&©UMÛWJ(Õ]Ûeº»±¿ºÄB¬%ò\;é(B¢ÔÈîLgÇõÙüÞôÛWÎôNÝWu\v¶Âegd!QòBt?g>YAh7vgyÝ\º2å«uÝâòÜËÍÅfË"i$l&Ê£ÆÛ´Û&S60xÜMæÜ®UÍÜw^vo.Üu×l£ÝÛ¤W/ñäª9¦Ëy<Ëurîk2ÆnójhÈó¶Úæå®VKhԥη)³,'ÝÝݧ5wft×$RÑáÊ»eγQhÑÊÔX¥"µDh´m ¹¸#6XTbzàvAØCH#%ömõoÊ´;TÄ< 8#%îGû;¾#P ¡A;XalExýª*oN¨xþÉÂ{S´pAÀúJA¸!áE ±#%ãêw'¬+Ó}Ïu¯¥hÂ%öz3ï #6ËïÜ´æm:Ïr#%r"1 ÌÒùíêæÛVükZæ+kº¬ÿ¤¹gú£ #6Æ#%Îî6S!5²jÅjÐ¥¡·½5{Ì|1À P÷A!µ%AbÄBVçjuÝÔ²±c#.ݵêZðc^úªli¤#.÷5w!,8*àNßD l&PtI¨ÅiéÓ&I#.½Ö|ý·\{úµ¯UÑæÝÛ½(ÒDH"^b#6#.)k`ETb¤"M(0'ñn\ÄÈ)OVuç#6'÷ð=øØ 1HAcQAûj=Ôáa3¼D#%;" TÒÍÖiµJ¢¶fËMô¡!·/¤¸Y@sÑV2#Í©ZdÍQ¶Ú DüÏ&1½#.@ §ËHH"Zf0ÚÿmFkB¦km Ë7ÉLÍv¦vÓÆk±_T,£T ÂÊ$6#%þDûOPp%*¼CrW¿ªúÖó6óô÷}w~¢|ïd`B2¿¦gËñê´Cå#%aaÌHôÿ¹X4)RkU»M¶ ÈfÈOÆÑv`iñÎlDHI'2's¤Ñõ¡²y?Àáýb@cÈoSÑ5·câX¢^ü-ëpqûZÇ#%ÄÄ#.IÇY%¢iQ8ð$MÊ$4ªB£Q!.pK#.dÔþÕâòºmsWI*å^ï&ÅÄ*6VjBTBW@#6Ö#.c0LK½à1åËBá-$ok#%´Â "JM!hKEÌ©#~Nͪð»/8Áo:¶f¾$öû^à쪰pÐÖ 331(Ä`m¥ÁØx]âO,½).àdË0L\Ò²u"Áb 0«ÔÁh BXT°²+"¢7*© H4uÍit52LòêUÖRnݸ6Âhüt#ùÓw2¢H×`ôÂò*ù{Ntp~m£fE DAÙ`=aPP¬&i»PE±*Ð#6E#KT-ѺZÆ^v0ù lûa£ïÄ$µb ÉS¯t·\ªvݪÊ[§.ê¾»mµõR¶¿¶×ºØ+ìfMı f#.¨-RHE9À³ÐÂѹÑxOd#.Áyþg2Å>?åDÚñçì[Ýa3FÖAÊR±1m6¥ÒqÏ#.¾r¯©×PäqPì4`!ÄFÁDm6¬¶òÉc$¦ÖcÁ¨ñ©ÛvHEJèG+ú2LÌRØ&Ç.-S9;7¶£´3P´¹-2µ}¦ÓòxPëצè!àDûOË[m4;CìAÓA?{@~¨ìFêøÊ;gèª#. #°êÞ#6&àÍdT#%¤O]#.0UXû%Hð+Qè¨÷#6'dÑg"æØ;¾#%âßh§#%6ÕáüÓ#.¶ö!þ]ßzLÉ¿¿¯¥$ÑHX*fO'Æ"°[>PAÍ#%GÉQMAû={}á§vY¬¯ÑõÖ)Ñu©A_°d FÛϲ½¿c[Ü%oEÓ,y÷¢J2&óotÜÖ;¤¼6^o´uçA(77ü) µ¶÷Y ÄLxl+Û¨SÃù5ä4wòò$;8SVâT:<t(ñHȪ',ð³RÚÒâRgpo¤ÂÉ2"ZBÇË0/xã~æŸÇTCîûÖþIõh&"´#6béC;¾¯3¯«ÚÉÖÙ>úWûc~ÓÊqÖ'lcØÆö·0´U>L#»²8US3H¸¨wâ® B?ïkzþú&)¸Em[p´!oqÎJÐYÅ{ÙL7£LÁA¸¦ÓV0>²BG.#ÄDDJª® )æM+I¦Ík¥¦=i4b¦sì'4³>é}2ksá²HÎó|DaXéwkÎú}e°&f´RÚyiÚÎóKÛù=iæÙ°y/âu+`Çxö$ÝÀû0}]ÐJ3ñdáË-^Ýø϶Û9@Ѽ#.3]7üºÊê@óÀ¶ñXTÕ¬Fôõ{¹ë²Q 2fqLd¦ñ!»o³! ÄtÞ8<µçÂôÈ6c8Cg¥B~óQMãøÙKºËù®ÇCmª¹"9n¨¢H´<J#Öر#%×1Mn ¥ÊéÝÔxaöOÚÖNÿuQá´ÿb¨Ìñz` 74*¨9N¾tÌ Sõz¡Ö Ë8 zJãì;EøxW´±3Cd¦6JöHå¼Òa¯`&C! íó<µ,]IZðÇáÒß:}P#6f27¢ TÍ6Eún§m¯FØØáOum×êoÙºSV#6ÌÔýìÞ×éÀÔ¶I&³#ø}3 lýCÖå¿YãµÏ]Ú6·©d·jsÝ M)gV\ÕÛÒÕÞ,¯ßë'õr8ÃÒPòC5 U4v!yc:Îpôk¼¶ÿd^קÃD~»÷??[TôðE¶»wª;Àk½WÆÎÊ]!Aùp£Îrm°d+Û #L`± ´|P Hƹç_®gXo,¹i¹ªË\ XyËú)ò¦á4·§`8ÏkÆïgBC¹HÎçÕåNw3Uv0/ÏnñÑ8ª¡3'»=·1MwÉ1Ù}ûÒ2xÃER ¦§±PL¿@ã×¢LQRI5=û¼x_ZC#.eÒG§ïüØke(¤ÞàÒ F@½Ù¹uôWnqÈËÙþ/£ò貧Ù(oÒ`ÄH¿I/#% $;ÁðH|ëü!ôÿ8¬¾$DYDvâõtFþX*G²»ÏÅ^ÒÌÝ@E8*mì81P}°f>ÃÞ²âôs#.Anã"Ý3-½GCÔtä.9#¿å¼:ö´Ô>ÄÇpwÇÉÄP+m&#%f¶FÖ´ÑÛd92hÅ$ÑEy#6,:@ä¡í(:xÔwu#6©6Ïì¯T®Î®£Æ>ÞH{:¨óÚrz¨öY5zº¹[(úù³¨ågõ8Àu¢ÚO ±Ú¨¦ ¢0ôV#% FB$¯°Þå<jØÀOfçD¡Ð+ö8ÍÆ#%àA)hBÀÆ+ Ä®qk_g?ë?¯à̬¤ÝOÞS/P@JFÒQ?µªù±À2:ß·gdªH5R#£Ê;ãMç¾Á#%óëxN_¼n1¬ÙlX+¤g¹·ù_4k3>÷Vgl6éÎ×Ó©ñCq×ÐEúW9³v@ÓѨa´Nø¥7ìâ²ñvVù¦ éì?ÔTÆ'»e¿Ü»Ù;}`£9úì=§¦ò A+©/þnw®Bv>û¶çU;QUΤRtÐ:`#A'BÑ1«¾ùa+Ð1 MpAH!þO«mmCPç¢6îÐ*Á#ñÈr=ñ?£?ùûKÑTHØ?ÚáU¦7ÊIÈÛXÇrxiÞ7ÎåÆ:tà^³Í£Á!Kòó©,8AüÏzßóÄw(I ìäh·ÑQúöùw,ù.1øµZw®íb!&t4!Ç.üú2E)OkR¶Ä4³¬?eBF1³öeÑ$í8xnÕnùx-PúÉé^û,ÇãXFKPÍ<Ç+wOÞ×j¤Ñ¬E¶Ëf³MRÍbZRµMR(gfísʵ$Èu.kOU;ÏïHÝEUõÔ«@È¥~Ïíýש?£ú~dmeI£0h m¨LBLhb#M*FJ& !&Ía#6±ü$åÅögxɳ'«:û7Üo'6úÝyRMvÌ ÜÆ0Øh4MÌÝ4¢¤aKæÞ7t¶zh%*éMð·åÆ^&y}Gå1ÑÔ¦×M6`¥·m8@¨ {*E#R«5sQíøøÞ¨Ã&D¡+fCÐÄÆÛxÎ&cz\/ÓÀ[]4ª>n¨¤ôÜh#.ØL ïÖ9obkMNËÒuÕ.Âjõ!2̺ju^ëØÖ8ì3Ûë¨fèÎ[G ç_¸3ýO8°Õ Úm𦶰9ãT/èá3°ûç#6Ri¾m#%F÷"¢Ö[©¥m¦iG#%0NPÈ©-D#61u2HâëQUË;®JnVÝ®ésuu®ÈïkÎòYÛ×·7®«+lÆ4hÆ@î1A *º%*»@Âë&Mæ˪#%¦_å¬2H¢ÈAB,$ÖW¸rérÎësk$¢3ï¶*çF×2 ËLEø:UÊA-H¡K29ÇXarR×eFÉ?6¢teÌeÃÑs4Ñø© ~÷ð/c òhâÓX!Ë#6Tr!SÑ©/Þ:ãkÃz)\QÑ!TÁ`U«¢7*âÍÒll«/c\(!¡6BÒ¼«³5A«¥¨;Í·rÊ.»xÖúÇ®î×uQõíQ°i ¢I¥Âħ%4Ъ!h¨&M9Q%²ÛSM©·LÆ<DÓÄÜ$AVeCbzŪ×*:R\£³Û+µ(mUÅ¡:ÂWT7"B¡\+-£u´66RÊó Uj ¦<«5C`À5·&Á¼éånãÀnU.à»*.ÔÝTZ%ÚÔ&#.*A±Ñ©§¼Å¶eÕÞøÁÆ1'3²9Da[#.iHH7SlYe «UÆ«A@¬;)ucÔN}fÍ=,$î|ùWoÃAR<®Ó&ÂQAgÛ#©Â\\CÑz!¦©¦GK1dR0q¨²yܦ8BÙ¼1EâMjJ#.ÁBmÌKH' p¬J¼á*8Àpì#0oàÅ-ZN5FA4¨·Bæ 2+±Ðj!B SR1F/4Ìâ0Ê#.býßR ÷ØsȱTnͯ7nnø÷Xµä¢ÉʾNLâ!ILsC#&DVE¶Fi¨(a S#6Hƺ-¡2@aZM'"1AÆî<j¨í˧¥ÁlUòÃÃÛæM8K¤A³¡Ø¡)"ÞZ9fñJ6Þ ºÐÑê äd'Í4Ǹj¨ºN0üfâÆiûi©²°°(0ÓbÉQÑHD5qîeéån#.nèÀO\m Õà*%oC#.«ÊMïìu¦÷ wÀjïT¯¿&Cr@Þ±¨¨Äp6Êäøz$×&p²±@V[i¡YDæË(F )96pÒ¡&4©J¸(©0Ö\± 0¸(æ!BÐQ!bJ£"¤Á4Õ´ÈÂÓGâMI)Ǹ9pd!U!Ì[¼;îíâ+ÎòéQ×bQÁHµCTEÍIÀ;¤Úm¦Í¦l²"µj Cñ`§ë.ÿ3#6ä4êJðüû¯Ì("Å#6H°=ùÀ=Rc·.£÷e}·ª>üRÕDôÑF¿YÚ>REB#%!T£AÜBåµé{T}µ*Àì=Uí&æë§ÎÎ00Ò °W!P'Û:D¯µg<¼ÕF rO#.4P÷¨ì¬p£þÛ2FÄÙÝÛn®®[{k®;¸[ºU0Ir Y vÊk^(¦µR¡LdÁ RËuB¦æ»³qP Ù(f3Т#omB7û¾¥°·°ø\¼ÌÚÒãL6-Öý"ò»-ëÛ¹Vçt$YÐIÛâóÝkXä$Y¬Ùæj±tª/vA»>#.¬½HíÓÒ1ø¶GÛ«ÃD¯PVÑõ(þ¯à© N½¤L¯ÈÏar×($ìÝÉгàw ïRb4w^×»C¾/ ìX,^¨bK\«Ù½-!®ÓlßMvª|ºõö!üȦ7@Ï_]ßÌØuåÜ(7Ñúþ©ØÁ#%Ë·I#ú;}+¾?}n*>Û±ÏÒ[ì×{oѤvÒBÅÛ³É~¹¼È?Èùc(ñG© ÔU#6+¿æd礼콦ÐðÉßzRÊ'j[br¬#.v#%ôηUûʸT71wVfºËmEÃÒXJ§^v×# ïEC°yƱ, ìA2±AETù°áòNÊR¨QeTÎÞrá\ö9Ú5jªË#.&t0ßácZb8z¤0ÀmEþf³ÈßçH°Mq4¤9 #.þ ÃUHr¢\ªévÜV^ßÈò¼QkÚr¶Kh·²ÖìKrîêÛôK\6¼UÆnVéµ·MY#.cnm&Úæ²k-µÍÞír,mjQª+;«î-Ã#.âw²Ë»$çv÷07ü<¢Í}Zk¾zÓo´=H^Êî"Øκ!7@A"ä#6´Þ=¯íÂäD´»¿vú®_oª¾ªýQy>ð)Gä#6çøÑá"É4ÖÂ=$±òSè2w@d#%Gßèq¢1¤(IBHå%J*¨Nîòá^T#6Z\# x Ùb¡*©""(¤[u#.mt¦µø~{oF®Ü¨Rd%ÛÝäT]Ñ *½Q@Q¤ÖHѶÛ%[¿~k÷!D,#6 éB?õ@Ô#%ÿ$CÏ¥'¾ûHjÆMöFÒ¶FñÇÙ{ZPuðPç¼P#%;²f_î@O÷A$;ý&Ô¬¡Ôu`¯ª¤ª£Ù¨3`Ð: H#"&Q)òT(uqe-LÍIJ1id´i66hmIEbÆÊRRJdÚ4)µ´Eª*ØÖÔkjZVjZ52¥bÖci5³[ϺÏn·$cu¬È²#.Ç"6W"Dûne6ÛaPÊAÇ$r®tëÓ£Ò®Ï=tªò®<ìiq¨ò¤©¥D£O c!&$Ü*+hlc ¬HÉ-a"#6@£`èÁi#.H 4ECJ¤P*( B*Zë0$(¾B¡ Ô#6Y2?Íü5°Á#%ô©DØ%%¦îéÝÜ:ÓõÚô·W®ìÛVÀ(@d$f2Óȸ@M°%Ä^û³B3ã`ûÇNÙ"vÔôôm÷wc¾²³Ù QRN {ABH,O½¸VÆÈÜÐö5OÈ¡äØf2vp®§W_[,1Z%ê/-l@Ò¨±±Ü¨Mâ xFߤj¯§1pV!TÌH!PáJu0UR8Gõa£ÜµõN¦µFénãɼÖòË©R/Ú]êµsQµ±hÕZê®Á¥±ìóp9ávº?®HEÊoz¤ÑïpÛ2#6e_ìÓjÎ`»8C®+dßX{ApÂ!ê>ÿï(ü±YD©Ë³eJ[LTz÷F"Ë`ç`ÎÕRúÕ ÿùiÏJê%áMY¢ªS|²|®#6u¡àÖ½usFpÙ"}rC¼"Él³Êª<Âo×øÏMÏr§ýæØè#Æ X}¨vµºt¡;?;#'ËRùi@Ü¡ÍM¸Ôã|]?ÙÒί^¡ÔB}¨#.#%ù`ø¨ÖîAåÍã°Ï/Ñÿ|hÒl\1º**;»3Ú*¥âTþÈñÅ4¢ØìçÓ~ö3a¦)¸÷GZ³*¥zÁÑÇUƶÜ` ÂpÞ]ÎÚ£]u\ÊJãQ¢ëòUÓ3÷ðÁÆ&Òe¥ÌI#ÆåÛJ{ií'[lüÇ¿Üo5ÕÛÄîÙ¥º'Q#%ä3!O¨"e¨BG½V×ÒH#´'53×ÕîZ×#.ÃPñçRn tÈCñxm÷¦¾Ù¶Uúûïy/ãV°A<(}ZÒÙ81K²$=·E4¢Bl:EæÊSlµÉÆW_û×¹/#.ÑÛQuÔîí®:väì³G¸\§µí{KXî{îV¾¬#%¤LÒ#6Bk¬¨7â¶(/%ÀèÃà÷Ô¦Çb-¬Ä¢õÂÕÄÀÂFÅÆixå$Z³F®;ûó©vÂqÙÔ!Äg ÷7tVBZÇS¼/yÀo#ß«½Þ%&s©X½*77/²cM±ÁrøW^3Ý$"Q?:yÛ6"£éÅƺ{åøÉÐ#.ô¡¡ÌVË~ügÉgsmm9)¸®jWMöÓÃmf± è·â®8kÃÓ[éþ]»±6årXöNVRTâÌYÍZª¥;¢øùgrª³s BÄyo ,pѾa& q<£jf)ÐÙnÆÛÐÓE¥Åf5w©±ÑÄâV\º)2Æl`qÑáDë¾x¶Åf^aTûåkÄWnëh6³m<pæyßý_ZÝ>Ø[ÑÆçhNI/$ËÆf7)¤ÖôöÍGb$C¥×ÃêCC:ÚÒs/}Ñw§Êò¶DÉJnÛTóQíjP÷xÍ÷bëZ:>ì¶Êü¹9õÌW_J×°¦éyiÄÆx»uw}²×:üç´ç¼î'÷u{õõa*½^WW0ïoèÌÐâò¹ô³8ÎÜVx«¶®§|ÅtªCVo #6åUvga*Fñêòªéïlg¢/Ç=Ã5ÅéüÔÂln÷.úþöb¢</Deìóիô<¥sï>NÎ lr²¶AÅ׬Æ<EúûcÛÔÑìôþÝ! "D^æy¾8Ü£ËB6KÛ8£,g :d©D÷ÓìLíoY°¼0PÚ/iÈÚyÔsdÛ) 7°²TîÃ÷ä&ªhdrå#6%#.-í/×Cð&d«©.]ê'O8çmÃ7£UãIð,¦`W£2êçµ8ÏNÀÅî$`.èXÌ@ð=Z¢Ãì÷mRm³³£f3g#RcÀÞQä¼b3x0óð½0_$gBÈ0íÚº9¥#6¨ÜÑ)¯±Ò'¬ÏÇ keØ yc0À)Õt± (ßÛíÖ ÙdJݧÍ-®¯®AåÖǯ0É<¼^G¨&ê@1[õ c®UNÃcAÈn>Ð o#.°(ÐÈ#×LC÷ªó#%@:ó#6`FãaÀPa»ô:£L6ñÕýxõ»Æ`v¥¤`qG=æ26ð9èÖkSAC«#%6ªsÊ^æz±¿v Z3K3.ªÞ&ËsxÃ\ã#6?#6«_Dd\¨¡PʸG`{»u½§D¯OÆ.þîO'6÷ûÞ[°ìkÅÖÈ,½ÓÀý* GÄÂg ¾T©"Vsïδ##ËlºNÁƹÓkFÒéaùC·úÏòghæz¢:§çç>ýcETÚQSSNFüb((±SöÛMÄe²Ú{Að]Ák]zVÔ4o{#.Uû»ð*#%Å9ÇGÖôÚÏ6(¯Û#.oÏ϶;3\4¡³G>FÎD(ÖѽòçÇÑp²9fª7 Zæ0ÙºÞÝCë¡ãÖNÚ21Dª!.e-lZ'ÚUbÕõQÃØ¡ç~%@½vÝiVkQ-29¾ysæ83DñÅì^[)X×ÕÚÉ"Dv:e£;F#6Ç~Ù¸°ëíÓÓwÃãWoÕqÜ̲¿';¢Cs:ö#.aº:ë¶Y¹Tûè¯[ãÔÇ4v4n s©»x÷ÑÏ;èÝ2÷~öçsw~/´j¦<£\Wt·åómåG^5&Éoä wª7AÍÄ%å#¾Þ0Må8pqäñ<³~7SÛ»åßLóÎ¥mZ¡\dõQÐ{x09hRÄ¥µ¥«#%}¥ëôD4·bÍ è3¨ç®E=¸¼ó ;Hðà>.Ãx[CUZØ=íô7,Èh¨·tz=<7~O ífBñEo7ê9q À°ïLBõ«³üñ6°§«YܱY ;W¸Îå\¹Þq.ï6 )sf\=®Ë#ÕV4(êvµÐ<³Ê@Ç,,¸g ¢(Ôyzw-HÕ]B¡¡¯E´öq3¤:f,öÒ'!Ñð ì@â1HóFÔó vM\;© É3@Úõì.Úg$$VtIm-äSLÛ0w0ÈÁ'#%ÕY"aÃßôèU×]õûC#.`fá+u¸mæò?N®°Cw"³0ñ²)qOn"xX í¸NÛ&Äy~å(ä·°ÇèpÅ`\r P <ßð(;ïÍVßáL{U#.>¿ãxKf°ÂwÀõüå'y;`kàýpÃhST«CÙç2°gÏ¥_V«GªG±8v'$ODMáÀÖN}®;O[Tb,ÈÃäÒ¡E~ ¯Á°e Daì»Íml sÔ¸ª#I#6±KºÌ0ªm&@<Æ (Ó`YF91!²²"¨DÈ¢EXB!$JÆÕ½+F·5¨nZÊèZ©"(ØÁci¬¢ÅFPTÒ¢aQFR¥0ø!\Þg¬âþ&xØ µ±Î@LñÜî# # ¹vÐ á¤é$c9ÍbÕé¼mãnEɱ*µ¯¹m¶V®UQUUé¹UײóÇÐÜÍýÐçP:þ~µÑøC5÷]cÇ-§AKxæ*Æ1K+ud×/¨ÒÁí¸i¶í®oÜ#.hÇHiþc£f-+°£W ¾ù¥SáîÀkN4bJ³ÄòÖ:¸`@¥,×cÉ (2tHqbePDiòãOR;Æ]ÓxÖa%dH°!V7VÁ·Ù(&ÓicRE,%ÝEcbi¦4C®Z*=Ê[ÌgA§ÂuwL¤td½>ùlÀöL!P9lª#6@Y0ÂfL7zUàÅ3R·XQÆ6ëØËÖ¥4ÊÑÛv²ÍîFjh£MÔU¬zmkZ¦A¸Lk.<µµcÔèç9«eoLÑ$DMqP\`SZ¨X³LÐ*±cñcix12ëBÕC$Î¥¯Õ¾5©Ï9;·hÓaYÎS¼JÎ!ª#6A,ØTP2ÇcLhÇ»*ëµs½µPAôãn²U"^Ck*êæVú%+XIwÜ&]J&0ghnÀotÇßhsiH°N'a§ïiÏ]P\ªR8ÙFö0Tj?ªãÞºÓÖcSò£µ.¨CZFLàèd¬q¨Ô"Ú7*ª#6*à ѸÐá¤0m0m15+FÞn-¼,²»zça[ ¹tùÐC 2´CdT¨£]&09ÜEZÙ*å#.hFe¡±mÝF?Sã5@LãRùg%¥¶È|4k ¸Ô Úh¦ª~¬¶Æä$¼*7Ä®é@ìzi¤<D¨°]8&è .ï®r#.VFÚqÉ#B¡ZYm rm2LäÊlbWfJÌæÚ¢&n\c§F±V=¼§^1Q¼ÁèÞi®m·X9¢VßãÞßÞ= GÕyúe}#611(÷"Ñ·e0Qsâz±Xr8cMAø¹¢@=6ñalÊS!vH#.0ÕÏ ¶û0\d#3ÉÜ$d9ö¥:é¨WbTF¡£MP1#BÌðCV#6æe´Î-ͳZ"ÛhDF¤¨b0fµ8Ҹ±¶FxØ7¨Ô{ÔË ¦A¡6Á&'"Ë9#.+µU°ÍNß!UíÏ*ªÛ2s£Û1óM`ÁC!0çrc$Ûã½n翦Ì+¾îÝiL5MÓõ6¯ÚÙH$ä´¤$zO®;ÅÝóèºbCóHwÀ©ÚªwUØÖÀ4*SmÙüç U+ {}E*ûXSÔÓ^#.ñqº²±eÓ¦3~sÈ+?2CÁûàÿÐ9¯¥Ag*Î*JAFä#.o³·Ä³Bx«ÇzQ#È»û<*±¿®væA§ öÁK?~Cóyßì¨×\UbeªÁåó>\f÷={p1¼$a¦î»¹0¿{w@y9;bƪ¦['º0ÇotÜòä<×Ñ(õÈø¦k´àµÕ÷¤qÁÎHû®øü!¬í£Q:ǧ å@Hµðç©!Í5i WjKV\Õm]7hlPPH¯Ð¬»öÐÖiä#ÔD~èì9ߥ}~vý"°R(±H#%VZÛ#61´Æ&1¤D©(Z¦Uil[%¤¶¬RQ¶$¬4(¦Ê£Í¡M5#JMQ³JHIQÓhD¤KFHS4T¦È¥SFa¶lÂ%(I1«X!#%øÞ:úxôÌÔg´ê9ÉSÛº¬î¹[Ç4UyÜÐ~ðWæòs5þW$$g1$8)×ÃÂÚµâW#o®å$îVÐElO"¨>#.¶4~ ¼Hga¡hf6ؽØLKn£R&¾~§Ûzk³pCõ%ßÚ(2ÆH\Àù9q]=½haѹS(ÂBYèâ°ª¦$ã ß´ùû½ÂùïâsþCJFÃÅqy§üÚµù¯×ÑÖÇ{!Ãë: ûo?WÝjßµ¨Û&ÑXªKXÑ÷Ösi±©BQ£±õÝ«C!bR©bXK2ïÈ0'uàE$fPÉ#6>ÿ£"Ù)í¬÷ó.#.>+¡Q ¡¦b0ÜürèÕcD>n.5ª(àÉX¦¤Rb"©¢ªD.éÊf¡+@6lxËRXÐV,I.¾Þ1Ó{¯.íгöó«ÌѦ»6öå&ñsD¬ÊÜ·/׳PQÀº.a#%ÅÝÞ!`СGLÄĽG¾ôÓIà{è5OEÉ'&u1p6e¤J'LHQb`àËVAd¦¢ b¤ (ó©#.LáGô`6 kgìμÞ6ór1J¤N2,=¤4,°p¦| d<ÀÂÛ«6ìjHÚÛElm#6#%ÚÔ("3@pBh_²*ÁUYU¦#6!ìßÕºL@ ¦@¥+Å-= #%½]ô¿~7c¿#´ `>ϾÈ÷÷ò3þ¨Cft½B$#!¿ö?"dê |êÙ¾~h%¡Ð{Ñæ#.,(`ä塤|ÈØn2¦LÓÈ3ÏÐ@>ã7ïØVÆiy¼Â°÷ýÞ=ßµöR|ª2Zûf5ïðñÆUo¿[52UQJm¯ZÔÆÊJýKï*G;ó&¦¥uÊqµm¢òêg*ñ4-o^ °n2nF-tiªD§7C5Æ6Ó&TS`Ò&!*Q±A÷Ärê]uâ+NA«B/¯Ô{,¢tòOئÊúÓrµÉF¯Aï J+«)è(° Éë;øNsê>«íó]ÊMË°#.L|ÊÛéRæ!Á)Bª9£^¤ÿjfÅ<Ì;¬#6Aî0xw;ÞõHA)4gfzúqòFõcÏ áØE¡kõ|¦!»°uªMG&~逸²#%Q;ú¿Üt@d"È*¦#.>¸ô/}Râb_cóÖìT#D¥:ΣʱrÖîõý'5>ç|â²âè}.àý_Tl×=ÎÜÔ²]4X`C$0ÇVêã9'HØv'F³ñIÚj&¥gõ@>3¹Ðí#%pàJrê`{ä7s@òq{ÊA/UÒ\zge)^±²=sDþXÜÆ1×Æ£Ôå°nd[wof²X²¾çg)P6B·Þ\+ÉÚEµÜ,3âÍJS»uUtDÀý19W53ÂpTlÐÈÓ#.¤ch` ñ0pP#.@ÐnªÁ`È%ÿV TU*2ìÈ/&YÛr-Þ¨»5!PÔÊ0E#Q¤Ha¸6P";^-@âYÇ1Ìnì5Í¡#%1,½!sYÚñ¾¤flzÙ¹Ôé¥ÁciDã&Ho?/3²Ð½X2(uÇÌ°´ÃdÝzYg$äÝ&Á5åDEPÚ¥HA±è~3#% LªÀC}Yf-"¼¤}q¥£ÌàIQ%¼Ø^FZTz³µHÅKÅ"@Sp¤u^<o.ÈB3@Dmï½àâ ×jta¦lrÞX@zQfkQÁ¨À½A(Ö÷óò¯n7ÛW üï¬"ù:ÈÏÓ7Ò`ÀR7{¦BdXg&ðS¨f%¤ É0ð»,íýî¶ÜD¶uS2ºcre38ºt#%aÁ%ç»#6Lp²O§pßX9¤à»WD¢vkbÔ+LÄ#.ÜË#.»³BñC7<èD©#6H2#%ë¸ïµ!£!PÅ X#6ÉH ºÄy-_F¨é<´öÝañ¿n«ÍÛµ±So1ï[ÍVWÁ¦e 2äptc¯,ã2®i²ís¤°ð4F!ÇöR¨±AV,ñ³á$Eïæm;ÖcHo!Ó@3k9Ã_'LÁYÓB¯iè1@'*kM.³Æ£66 A»m¶ÒÁL\RE΢Fe¥%oÝ*,u`Á´¾Ñ9¥É1260ìo)¯i#.&÷Ã@V«¦Ä$ltÊvÛck¦rF)ÀKE ÙM,vLí.\º{Õ[>!m´Áiå¬Þc#4Î!äkû}avÚߤljW¸ä'7qÖ$[¬vÚÜßLU»ÆD<´ÑjlìïôH=fUÌL3aè'£>4O¬ÈÐ!ZõS5{ÓX¦¹CÎ&;±8k¦î\@r¯2n&='I©Zã¤êBÅ FÕ,¹\¬*ÍV׳p`\ñ©HfJY#%êëã¨"ßkkÌ%ñO+vv&º?grà{Þºç(äUÐä×I¤ X¬E#65³6É!ÅdhmÌóÀé^]04©qs:ÙÁÇ0@ëæE}h·¨nLeÁÃ}8 Ü^-1³ñ|2£Ãµ÷@¸p´V×;"'塱X%ôºí#%í5`+IB27©t§#.NZÐÅ©ºB¸°Aø±b+m:+¤BN\¯ mgY¬ñ[6LÎÀVælåa²DgÑ@iµDбP<ýÿB㱧4ülÔ?nMÖÎðàM$ÕY'¯BÐòtoi´\Ûñ¥Ø+~8ᥢ]-YÃ[Ôtͤp?UÿÂQm2áLØqEÍ#.qíñØåÓ<<4x¨1 (3HrÞ<9²óëktò ¦Æ r³òëz]YÒ1Íñ,ÌsÕ¦)³åÈFµ.ÉzÂy|²ÂÒ+d׳ÛFó~BÀaud¤Ö lÅÇ-Å µ¾ù3XSC´=±ùq«óëth:j=iu]p3BÀt§¯_ m}i¢2HÛ bvvÏxâ«$3@ä½Ì·gnªÕ ³ PJPÍHÆÜq!¦YÛ%j®`Þ"#I¢#P/¿=¹fgØMÁC´;,LMµM4Yp'Ò*Úúµ·ÉSìÎxÔEë¹Y¦§vMY@ôðSäÌèåå#6ݹpf#%ÊÏÚ;tíyA&w©b¥OLìO#.&Âé?8L89ÞÝM7ã%89Ê¡Ø-u#. ³/L]¯\Õ¿%Ú.cx¨b4&µ!Ò`,fÄlLMá#6Ó£p:5ÒHÄÄÌü¤dA¶¢Hø0ÌÁö4EqT¡ªk&§xÝÛ3ÅÖè)ïe£(Ã1YÃ`¢Ç6!Ý]ÛÑ.$#. àT0%DH!¹±Z¸å9Ç´ÒQ PP4wÈi8,ÑHê%Fl!6aeÈ0à\*hÛiD5Üè8hé*¢P K#6¦æÃ@ÀÀALCÄD6DáS*¸èwB]èÊ4,¨6"wA³½ò3bà"¨)ØÙÒi½ûøU«Hªå¶ÎMlEÜ 1 ÃØ#66v4#60gSP#.F¸H¶WU%0MEó& 83ÐíÄ3mÂtëÉHrºâÄ¢ BB¢ê¯3[Ò^6¼¯_#.ó±c%%¾²yyôCk£U@Ê(¨°×¦½Èn£¤±°f÷ò C°5#6,"B@MbªPê á¿öôl½Èë:½uyÑ\²íeX§ëïk°Õy+'J#.?Ö>£MÃÜ)üøx¨âÙàm&-£×B¸kMµ7âIfsQfE°ë»ºf$$#6DXÍf¿Y¯§·#%ó×W%U®ÔEüðMÑÎ^hÂò¨I#%ê¯JS°x|k0ÂJh(¨GfuaÐÆzíf?nôÓ'àÒ«¨¹*3#¼¹R'W((q#HªÕÝeiè3³%<ªÙìªJÅrØãz#ÈÄ6¹7oSñkJêF9ÌTÍ@Z¿0TV(NAqKìÍËVè+ÈämÎÜa·4}o{«;Ù¬å¦66µ²¶[[:ÁÖ®¿¢>¡DHª{hËà}*s9e¾Dʳ:¯«d{÷ÅT°3ñD#.¶CvN]GÃL@SÞ¡#%4©C»¶Çá^Wf·DîÎZ²º÷áâÔRñ7p#6ªVÚX"kÕáË»[Í$2%ñ5;Îéo7vÈ®òï^vÉåÒ¹Å×RÉ#6AÜ0@4Ð5*F ´8iQ¡øé3 iöGZK(4]-ÌUDÖ7v)<´MF¢¡ÇgV#34u*ÌÙbQ GFùèë쯷»È!ð<ýZ÷H|ÁpDäA#%¦Ï¡¦3õj¬¼dú.ÖÚ1<#P$xîam ÁVÄ®ÉÉL+ÃàÀØÁ$p ¶((7'§¨&µ9w²#6nc±ì³êlæ!ÜúìçÙ#.:ª&ª§LYUåùû¦÷×!G´È(|#%ÉÂmr,A-Ùa NKÎMN8ÓR0;»n[5'Ã)Lª×³¨^b>%¹C3é8]6±uLDÔ`X B!:©O¬iæç³n%Ú"öa\ÐØq¥ÑÃK×è£ñLôQ#.i1Ç¿0ÚÉ0µö~tm6V,V"$ú¬ásÈkÐÒʸ öò 0'º)HH2DO¢"öµZÍiHJÔߪXDVBEGEìE0cUÆe5@Àm©n\0P`M`¯8#%ì#%IîËÑ *Béøah<2½Æ¦Z\ÜìȤ°² H:¯äßbX1¿8Íõ#6 #%H*¾ß[·|4ÅO4oÕå}#9Ñth¼g#.`±Þ»´Å¸3©Õñ*\žY9)h¢#65½P4a£ePM£2Xl+%Ê«EE¨íD·LNAGUÕÂë×yåmÊ^¶²VÌÝv¬V`%QV@IÅNýWPË3:È$#.EG^2S4#%Ü¥ ¤M2,Às4µ§âPNÞ0:=G§Í,0!&*Ç·§ä=ÔÌÃaÂÖ Ð·;sHc²iÞfÍtê1ëa°SàßÚ½&ñØÒ 7!,HÈ#%5ëÃ@ä%驾EsRÏr¢Íýï_kWÏ:ó¶¶*'õÍn¥H[ïh4×·¢`wAuuÚá#.,q89 JþÏáÃ;«¯³3¯ÅO8~kÔ1 Ü$9Ê%¯«y£6ZhI¥EG!+]£fvßæoíÕ8`±Òùn¸¿¾¶^ÓötY[ÕôãBa»ÖiAà~_X>ÈH&³ìÔXb#.4Ñ©î5ë%ïë!rKïl}9úÓì='p>ýÉÔ(^7/$¤´jYiVIJ#6«bÖa´&Ä*kLmµ&ߺÑZ¸Îk¡£Y³ks¼ßÛ<ÕXªåûµ£aÞ¢þsÔæ: ÇÅ#.#.¾®¾+±;öòÃMI@\Ùô²z°/aÙ°nâ#%ÕNÑ=ǾêäKÁFzùÂFC?6ëñ(ukµÃ XE{J9&ärÔP|üi¶öÔä4Ø-J[hyªÃ´me;;ð´#.MÓIÓqAq«)\»ÄùÑe®qÄAäÒåCD8:ß 7$l·}uf¶Û6c6ZAI¡%!pj[´-ÑÅ[åÍü¬+cTdëÔçL¨Í¶§fܤ#%PYl±Ú!VYCrhM#.ÑÞîôÅN¡êÐ0LoäÅ£JÔ1ÊȲnÅF´ýJÖbÕk#.¥ø?{5²b]%OZZl}Æ0 ¸äE!òó÷ÎÙ,"÷Ég4 )@w}* uAÔ ²$ALpIF wIÏ/©tÊð¨A°O!##Æ jU6¼ãÕt±ð<4O ¢+ÙÚt÷ aÛL;ÏX#6ɨF §ßæý#%oÙ1d@Ç! Tñ{õWnÿWòmî'yüµÍó6@gö8A°ÄZ´³0?yüä<vuøl¼ôªÄfPx"%7³0Ü'´ws7uÿê"çð¾ÞöÝfÇÓ500.=Ôl×Àþê:;Xæ¾·ÞQPñã@?LSa#%G1×#6ÜÕAf˧f¡Xùè£C&3#ÅÔlDhÒKºº #.¦WÑÞaû]Û\«õæóÏ]ųÉSd5Qy7s]¼&ÆѶñs\·Æ+»·yåv¤å[yoÑ[¶Ís!ÅSõ$S`6mÙó÷þ#6*¾%|}¶<L³=AÞIYªa<Í>é#%Å<Ô®Êû>Ê,U!¬Ûf,ÚÍ´õµ¿5÷øµj÷û"Ñ-62)E4²©³jü¿tj7ßÕ~îú#. £D1SQ¶*¥)JÚüz§hµ¼'Ìx"#%Z"göBRÖÃÖ1ȸ0ÄÐ0HrHNT$è>ä#.D1¦î¹²)±¬-f¬Q¬lÈÅc+E²ÁëÎò*(@'](]ê4{qM_îòýé©çÜOsèùfa×$ðWÀ õ#%£'¸}ËeL|ó*j¹#6ý{.³æÉxv÷,!Ú°3 óÈIÀôªyæ8öÑUãoË{Ø,EE'Fñßt &ny¤ÀÞB Q¶ÄbpüÈtî"Û@ÖôTÖ¡ódHE9§¹Z¡ ½B!JSÚjh("jKNíÒkTÛRiIª[RTl@njm¯a0¨ ÿNR(+Ô\/*SÞR¬e¬Ë/n£.ÃgUPû£ãÓdtÎ=v£9é.k¯Ni`MÄÇhú([;³RÑÖ*È5õXV²Oµ8Ð"Å k°ÞÚ4ì#.y@^K?ÞÑïW-ï%ë¼lcúé#nìzK!ö¦ ¸X÷¢Ð§øþàêüûoçãvMÅ)¦%I²5¶1R`ÔFÕ&Û#6Z7æm¿+W°ÑZ(FAUdQ$ïî9ú»,ìi!`¡P* û¤6+°0rBF"EHÒ(ÄÉ )¢hlÚQ¬,#%ýhÆ}qÏzíÙ/uÝJQþÀ!"kW±mF- Ú5F«6XX«QZÊßÓ[¯3:zºüYݽ´ªË%$ÜkìÇègÍ#6Ñü5#ê1KL5VÊåF·ÓLðкùÀÆàIô÷$È«miGlý/$²ÙÛ3"*hc<jÖÓý90(8AK" Ð2Ú·Én³I©¢-ë6ÛNìµÝÙ^5æòµÕ6&·¥\ówY³2«®nÚ¹ÚKdYµywcMk»«»¤ÙRTÈØÖóº·kΨ¬$ISa!H6Ôb£cÞMi^×jÒÙMIUéZêÞuuçj¼lm(Êe¬¶R×Ü·k»tYc)&A¢a£ÑN¡àÎ#%É#6ÛÐqVm3ø{äè5H±dÜ>²øQ¶EF*dÈÇ#%ª@ S㡬þ¤Ê[Fh¥È(1P¹{äÁ5×\É&§4)DÚ7Õ¥GôØ46àYêÓäö¢ìþ3OêÁ `>¸¯pÏ?~ðøfEº#6ݧ¾÷#R÷fìfKËÇXZ¦#.Yë9¾îã~07"ß^GÏõ¤M#.UJmG/¤lír$a®îB1ßèSJë@ë#³o($QGÊ)ļ.#.õêLo.Eä`%Áæ1¢GP5¦Õñóç/ml·pB#%|²$xk(#6(iι8>J¦ç¸iß>ÔÒ9åÈt(a -Q¢Þ3oÐÕùUbÙõ`|¢B hÚ)I¨i¦×£|#.âöA¯qØÔùK5Ó"÷gëtód±BKûòVµw¬¢ö|jëP¤Ot~ÃìJ'`O8)¹A°.F´'RK`¨¤,n#¨f4äÈlƽQÁÑÔÂ!³n¶`¢úC#ØÇwƽ!ȱ|*éDÅaM ¶FÕÕWáuzC<óËû²kGG ÄêîéÕ]Üãjþ?70ÚEy£ÉZ$£Y¨Ï¨ÑÐǽÁäuMmÐ/÷Ð ÄZè8@¾?jã8ùç¯fYÁêF4dý-DEC=µvNÅ|ªÖÞm¨:´Pi\Xì"ð#.%t¢#̸ÝѨU×1Qߪ @ã[8AÀÓ Êö;÷çK¤B4Db:[nX#.édRS(´@Ír:ä|Xr×c'pdlA±ï47mà¶Ô~¤ f1ÞBG¸Ô_h½GCô"W¾s;/~D#.îfYÚÛÊÚ{aµÝ×oÊ÷}þëiäk×í¸*>ÜD-(?LþdÓ*z©Q£fÜ@ ݨþQD¢¸ß³Ñ2Tm`ô=åWì#%ÇßwïØÁ²>uLäÿl#%#%b#%?Ùÿs¿ñõÿ¿ü¿éýôÿ¹íÿóÿûýíÿóîÿ/óÿëþ_òÿHþ]º>_¿ýÙ|¾ß÷Oþÿëëÿþ?ðøÿãáÿ~#ü¿ãÿ/óþïü?ùÙÿú|åÿ/ôÿ=¸G£üúÿÓËæùGô_ôêüß_Õ¥P÷SÿLBÄ?iþ,ϳüêÈDÊy;"e\?·ûäE7¨;©sÁþ±L@ZüÄm4 þË#%öªÂ)40)*ÿþþǹÝÔI IF·ÊÙVôh #%âQ³ßÌôjB»M¢Ï¡ESY8Û,×gØ+,þûö¦C¦Òæ¨x¶æñ#.Öâ×ýÀä÷² ¢îÇ^A:Õó»0ÉæfØÝ@#Ì%*ãþUÊléÎüiÙ\¾ÅÙ»Æøyö¡ÃÉvǧ¿eÔ«jÿÝë ¥&P"ƾrÿïUËr#.ð7Ï_û«ua:XÈs+u#6Ùýþ.ÀÀ7µ*jHþ¦xiiQ]d*ieaËTÁ0ÙÿeTñhÞ¶ñïÕ¥pvîm©TYn44¼BÒÙl` ÕÁËsO6e7ª¨5mÚ8øqíMmƶ9T¨¨ëÌFdMmTIqxÝ,ØY.ä5¨mõyõx*ŧ7FÎîs¢kCºFêâ¬#y{¢ï4êÈh2ùÃáf´Øäì¹a² qS1a ïH²F#¸yíÈd¸ÐH?F:oÌÌü4ÃÃ)×Цë^EúîÞK¨ëN±£\-ÑNàS4'>:`«éßw´ÿJ±·ý4#.póÀ@ÄGßF;tk5SÞæ Ñë gà w#6Hp,#6¹^>`L³¬5¬R Eò "IEq¸Ov].fB¦æ<õÙ3PEATV*AB9wt¸¦cß·YÌÊ2 ¯kº\69¤U¥ >È!<NÁ(¿K61$@ 0P2îHqw;ó\¨xH1Mï}lı38bÿûKuÊɬÆ\¬îÙ ,F#6"`ºT70]#.úwóbs $LjÄÔJlkY¥3[FÔm¨ÌÒDÅ S_EÛWZªø|:Ö¾¸:?àE3ÿt#%¿]Tµi¸#I(¼co¦üÛªözÜíSlÖÕïéñ#%Mþ}OÒÂFA~©o;|mq>§^²æF4?ícS9öɬצåU1"ü«Ç»'_û6Ä+W] æ8uîKºxteæ߶}C3¿¾zg,r.;À}²½©½Ç0À×fÜT9P^]*zgâ_§Æ³ò8ÎQHÔ¼= #6@C&9Ò#.³QÁOª#.D'ÒáG½\áUò»µP®CGݼòö²á¾¦ÕÍ-ø¾v챯¤[êkØ´|nmcãm½(ÕìµoSEªMAj½óZåUìÞÝy»¶ë]#6.æäQ#. ©| P?ç!xnãdN2Apã'PQ±Ôí±s¼p]º¡f!OVݤ¿7áUÁbÇá*J9 ¨H{ÿî°÷cÍÔ¼(5É@$fáÌR¿æû'wØÊ=<ÑܧÛÈ_.EúØqPôÇX¡ÿ#"(]¨î;µ#D)Qb(ÁmLÍtÖêÕÙjûËf¤ÅÍh é! H¤ £þßÃ3ÏëÿÏئ¨¤"þ~áã(ø{fYr0ÛmCòNÀ.!xN¦ çå,A<?àáÿ¨ ýþ&^â|YY?÷ùB-Þ6áÍtçü¤ÿÿ&EÐý hNí'»ÿcÿ`[Óúl¿·@³¼%ËAú¼Oìÿ»æÿÜíe÷øCâ.ÃGéʽ1ÍÀê'¼waÕBÏ+Üã!Éä,yý>^#y;³9ø¾ÿѵú½gþs(?l-A!ñÿÔ¥ÝóG#%#%(ö#6CÛ¢ OùI[¥BY=+¨4ÃÔkéýÕsø]¯üB_F*ÀN#.ÿ6pñäÑÎJíâqTE3o¦« ÆYÌwÈâfÓ§m3 ÊÊÇðç,Má/-±¿Ñ8¨¼§0aw<}8fJÃ$É o§ì]aðx`H$Y@zõnÒ=®Ù iÿ~é1éÿµ^#.Jz(ÎLPÛæcèªÆ"ÿâ|xãügê?I¼Ëò~ÿð"ÿü]ÉáB@ä&öÐ | |
171 | #<== | |
172 | #-----BEGIN PGP SIGNATURE-----\n\niQIzBAABCgAdFiEEivIt5aBoIuNHTzxwSbTGfAUneqoFAl3aW3cACgkQSbTGfAUn\neqruqA//Y9oJ46ZR8W7YB/e45bfrYxGbN7NnkvkwSPNziObYur+n1QpQEOaPTn/U\n5kFtPWHXRJzaG/A9poKn7pl1Xd7Edcu1aalfoEazZbuD37VOxIp9lnrefCAeICqj\nGv0SD96Zac91CbA+b20Q4xnqxKMi3LSI4NPjfFGy62FkSk3MS4p6Rdp0/WAKwwNj\nw7WEjQCNmLb37z+FGSzXg28aljYeteBZEthsVmGJ5QqVwMBwgj2+y5FOTzFfxmqB\nrWgjFYS0l85kgYRZv9yzdNmFs5SScwafwpT8Xmdr49tFn/+0LxXyRxX+rdODgrpV\nY4EOiQz0fd6mMMnaTDXlLSXls3JyVYmbTjeNL/9gcHmnStzJ851CJQfyQg7A+JoC\nc7nz0HbiFyTgB+PUZr1OhGj3A7287o8XQ0tqR3oa7jXIOX0OynrGplMQKr++0jE1\nBgKzjLoE9CTbjkQfICLG+aUy3S1ZyDk/BcO+5+Ytbru+qXuDsIgAdVosMfNSv9jJ\nXvOINsbRMekdejYMZv8fIkn5OEjCFHVhNpobEsCb768bjB3p7alQGECBvjHCm6dy\nXZPzl9cBMWIXcBjPTS+GZj+PIXGcu76pbsx6HBHWf+uJ+4xgOsUCVu//0AV09jvA\n0MjtLWwQ8mdRH6Wt4hsp4HKtSvQrhmljf2OnuYBgaFmcdJkN1zI=\n=C0oT\n-----END PGP SIGNATURE-----\n |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,sys,errno,re,shutil,stat | |
5 | try: | |
6 | import cPickle | |
7 | except ImportError: | |
8 | import pickle as cPickle | |
9 | from waflib import Node,Runner,TaskGen,Utils,ConfigSet,Task,Logs,Options,Context,Errors | |
10 | CACHE_DIR='c4che' | |
11 | CACHE_SUFFIX='_cache.py' | |
12 | INSTALL=1337 | |
13 | UNINSTALL=-1337 | |
14 | SAVED_ATTRS='root node_sigs task_sigs imp_sigs raw_deps node_deps'.split() | |
15 | CFG_FILES='cfg_files' | |
16 | POST_AT_ONCE=0 | |
17 | POST_LAZY=1 | |
18 | PROTOCOL=-1 | |
19 | if sys.platform=='cli': | |
20 | PROTOCOL=0 | |
21 | class BuildContext(Context.Context): | |
22 | '''executes the build''' | |
23 | cmd='build' | |
24 | variant='' | |
25 | def __init__(self,**kw): | |
26 | super(BuildContext,self).__init__(**kw) | |
27 | self.is_install=0 | |
28 | self.top_dir=kw.get('top_dir',Context.top_dir) | |
29 | self.out_dir=kw.get('out_dir',Context.out_dir) | |
30 | self.run_dir=kw.get('run_dir',Context.run_dir) | |
31 | self.launch_dir=Context.launch_dir | |
32 | self.post_mode=POST_LAZY | |
33 | self.cache_dir=kw.get('cache_dir') | |
34 | if not self.cache_dir: | |
35 | self.cache_dir=os.path.join(self.out_dir,CACHE_DIR) | |
36 | self.all_envs={} | |
37 | self.node_sigs={} | |
38 | self.task_sigs={} | |
39 | self.imp_sigs={} | |
40 | self.node_deps={} | |
41 | self.raw_deps={} | |
42 | self.task_gen_cache_names={} | |
43 | self.jobs=Options.options.jobs | |
44 | self.targets=Options.options.targets | |
45 | self.keep=Options.options.keep | |
46 | self.progress_bar=Options.options.progress_bar | |
47 | self.deps_man=Utils.defaultdict(list) | |
48 | self.current_group=0 | |
49 | self.groups=[] | |
50 | self.group_names={} | |
51 | for v in SAVED_ATTRS: | |
52 | if not hasattr(self,v): | |
53 | setattr(self,v,{}) | |
54 | def get_variant_dir(self): | |
55 | if not self.variant: | |
56 | return self.out_dir | |
57 | return os.path.join(self.out_dir,os.path.normpath(self.variant)) | |
58 | variant_dir=property(get_variant_dir,None) | |
59 | def __call__(self,*k,**kw): | |
60 | kw['bld']=self | |
61 | ret=TaskGen.task_gen(*k,**kw) | |
62 | self.task_gen_cache_names={} | |
63 | self.add_to_group(ret,group=kw.get('group')) | |
64 | return ret | |
65 | def __copy__(self): | |
66 | raise Errors.WafError('build contexts cannot be copied') | |
67 | def load_envs(self): | |
68 | node=self.root.find_node(self.cache_dir) | |
69 | if not node: | |
70 | raise Errors.WafError('The project was not configured: run "waf configure" first!') | |
71 | lst=node.ant_glob('**/*%s'%CACHE_SUFFIX,quiet=True) | |
72 | if not lst: | |
73 | raise Errors.WafError('The cache directory is empty: reconfigure the project') | |
74 | for x in lst: | |
75 | name=x.path_from(node).replace(CACHE_SUFFIX,'').replace('\\','/') | |
76 | env=ConfigSet.ConfigSet(x.abspath()) | |
77 | self.all_envs[name]=env | |
78 | for f in env[CFG_FILES]: | |
79 | newnode=self.root.find_resource(f) | |
80 | if not newnode or not newnode.exists(): | |
81 | raise Errors.WafError('Missing configuration file %r, reconfigure the project!'%f) | |
82 | def init_dirs(self): | |
83 | if not(os.path.isabs(self.top_dir)and os.path.isabs(self.out_dir)): | |
84 | raise Errors.WafError('The project was not configured: run "waf configure" first!') | |
85 | self.path=self.srcnode=self.root.find_dir(self.top_dir) | |
86 | self.bldnode=self.root.make_node(self.variant_dir) | |
87 | self.bldnode.mkdir() | |
88 | def execute(self): | |
89 | self.restore() | |
90 | if not self.all_envs: | |
91 | self.load_envs() | |
92 | self.execute_build() | |
93 | def execute_build(self): | |
94 | Logs.info("Waf: Entering directory `%s'",self.variant_dir) | |
95 | self.recurse([self.run_dir]) | |
96 | self.pre_build() | |
97 | self.timer=Utils.Timer() | |
98 | try: | |
99 | self.compile() | |
100 | finally: | |
101 | if self.progress_bar==1 and sys.stderr.isatty(): | |
102 | c=self.producer.processed or 1 | |
103 | m=self.progress_line(c,c,Logs.colors.BLUE,Logs.colors.NORMAL) | |
104 | Logs.info(m,extra={'stream':sys.stderr,'c1':Logs.colors.cursor_off,'c2':Logs.colors.cursor_on}) | |
105 | Logs.info("Waf: Leaving directory `%s'",self.variant_dir) | |
106 | try: | |
107 | self.producer.bld=None | |
108 | del self.producer | |
109 | except AttributeError: | |
110 | pass | |
111 | self.post_build() | |
112 | def restore(self): | |
113 | try: | |
114 | env=ConfigSet.ConfigSet(os.path.join(self.cache_dir,'build.config.py')) | |
115 | except EnvironmentError: | |
116 | pass | |
117 | else: | |
118 | if env.version<Context.HEXVERSION: | |
119 | raise Errors.WafError('Project was configured with a different version of Waf, please reconfigure it') | |
120 | for t in env.tools: | |
121 | self.setup(**t) | |
122 | dbfn=os.path.join(self.variant_dir,Context.DBFILE) | |
123 | try: | |
124 | data=Utils.readf(dbfn,'rb') | |
125 | except(EnvironmentError,EOFError): | |
126 | Logs.debug('build: Could not load the build cache %s (missing)',dbfn) | |
127 | else: | |
128 | try: | |
129 | Node.pickle_lock.acquire() | |
130 | Node.Nod3=self.node_class | |
131 | try: | |
132 | data=cPickle.loads(data) | |
133 | except Exception as e: | |
134 | Logs.debug('build: Could not pickle the build cache %s: %r',dbfn,e) | |
135 | else: | |
136 | for x in SAVED_ATTRS: | |
137 | setattr(self,x,data.get(x,{})) | |
138 | finally: | |
139 | Node.pickle_lock.release() | |
140 | self.init_dirs() | |
141 | def store(self): | |
142 | data={} | |
143 | for x in SAVED_ATTRS: | |
144 | data[x]=getattr(self,x) | |
145 | db=os.path.join(self.variant_dir,Context.DBFILE) | |
146 | try: | |
147 | Node.pickle_lock.acquire() | |
148 | Node.Nod3=self.node_class | |
149 | x=cPickle.dumps(data,PROTOCOL) | |
150 | finally: | |
151 | Node.pickle_lock.release() | |
152 | Utils.writef(db+'.tmp',x,m='wb') | |
153 | try: | |
154 | st=os.stat(db) | |
155 | os.remove(db) | |
156 | if not Utils.is_win32: | |
157 | os.chown(db+'.tmp',st.st_uid,st.st_gid) | |
158 | except(AttributeError,OSError): | |
159 | pass | |
160 | os.rename(db+'.tmp',db) | |
161 | def compile(self): | |
162 | Logs.debug('build: compile()') | |
163 | self.producer=Runner.Parallel(self,self.jobs) | |
164 | self.producer.biter=self.get_build_iterator() | |
165 | try: | |
166 | self.producer.start() | |
167 | except KeyboardInterrupt: | |
168 | if self.is_dirty(): | |
169 | self.store() | |
170 | raise | |
171 | else: | |
172 | if self.is_dirty(): | |
173 | self.store() | |
174 | if self.producer.error: | |
175 | raise Errors.BuildError(self.producer.error) | |
176 | def is_dirty(self): | |
177 | return self.producer.dirty | |
178 | def setup(self,tool,tooldir=None,funs=None): | |
179 | if isinstance(tool,list): | |
180 | for i in tool: | |
181 | self.setup(i,tooldir) | |
182 | return | |
183 | module=Context.load_tool(tool,tooldir) | |
184 | if hasattr(module,"setup"): | |
185 | module.setup(self) | |
186 | def get_env(self): | |
187 | try: | |
188 | return self.all_envs[self.variant] | |
189 | except KeyError: | |
190 | return self.all_envs[''] | |
191 | def set_env(self,val): | |
192 | self.all_envs[self.variant]=val | |
193 | env=property(get_env,set_env) | |
194 | def add_manual_dependency(self,path,value): | |
195 | if not path: | |
196 | raise ValueError('Invalid input path %r'%path) | |
197 | if isinstance(path,Node.Node): | |
198 | node=path | |
199 | elif os.path.isabs(path): | |
200 | node=self.root.find_resource(path) | |
201 | else: | |
202 | node=self.path.find_resource(path) | |
203 | if not node: | |
204 | raise ValueError('Could not find the path %r'%path) | |
205 | if isinstance(value,list): | |
206 | self.deps_man[node].extend(value) | |
207 | else: | |
208 | self.deps_man[node].append(value) | |
209 | def launch_node(self): | |
210 | try: | |
211 | return self.p_ln | |
212 | except AttributeError: | |
213 | self.p_ln=self.root.find_dir(self.launch_dir) | |
214 | return self.p_ln | |
215 | def hash_env_vars(self,env,vars_lst): | |
216 | if not env.table: | |
217 | env=env.parent | |
218 | if not env: | |
219 | return Utils.SIG_NIL | |
220 | idx=str(id(env))+str(vars_lst) | |
221 | try: | |
222 | cache=self.cache_env | |
223 | except AttributeError: | |
224 | cache=self.cache_env={} | |
225 | else: | |
226 | try: | |
227 | return self.cache_env[idx] | |
228 | except KeyError: | |
229 | pass | |
230 | lst=[env[a]for a in vars_lst] | |
231 | cache[idx]=ret=Utils.h_list(lst) | |
232 | Logs.debug('envhash: %s %r',Utils.to_hex(ret),lst) | |
233 | return ret | |
234 | def get_tgen_by_name(self,name): | |
235 | cache=self.task_gen_cache_names | |
236 | if not cache: | |
237 | for g in self.groups: | |
238 | for tg in g: | |
239 | try: | |
240 | cache[tg.name]=tg | |
241 | except AttributeError: | |
242 | pass | |
243 | try: | |
244 | return cache[name] | |
245 | except KeyError: | |
246 | raise Errors.WafError('Could not find a task generator for the name %r'%name) | |
247 | def progress_line(self,idx,total,col1,col2): | |
248 | if not sys.stderr.isatty(): | |
249 | return'' | |
250 | n=len(str(total)) | |
251 | Utils.rot_idx+=1 | |
252 | ind=Utils.rot_chr[Utils.rot_idx%4] | |
253 | pc=(100.*idx)/total | |
254 | fs="[%%%dd/%%d][%%s%%2d%%%%%%s][%s]["%(n,ind) | |
255 | left=fs%(idx,total,col1,pc,col2) | |
256 | right='][%s%s%s]'%(col1,self.timer,col2) | |
257 | cols=Logs.get_term_cols()-len(left)-len(right)+2*len(col1)+2*len(col2) | |
258 | if cols<7: | |
259 | cols=7 | |
260 | ratio=((cols*idx)//total)-1 | |
261 | bar=('='*ratio+'>').ljust(cols) | |
262 | msg=Logs.indicator%(left,bar,right) | |
263 | return msg | |
264 | def declare_chain(self,*k,**kw): | |
265 | return TaskGen.declare_chain(*k,**kw) | |
266 | def pre_build(self): | |
267 | for m in getattr(self,'pre_funs',[]): | |
268 | m(self) | |
269 | def post_build(self): | |
270 | for m in getattr(self,'post_funs',[]): | |
271 | m(self) | |
272 | def add_pre_fun(self,meth): | |
273 | try: | |
274 | self.pre_funs.append(meth) | |
275 | except AttributeError: | |
276 | self.pre_funs=[meth] | |
277 | def add_post_fun(self,meth): | |
278 | try: | |
279 | self.post_funs.append(meth) | |
280 | except AttributeError: | |
281 | self.post_funs=[meth] | |
282 | def get_group(self,x): | |
283 | if not self.groups: | |
284 | self.add_group() | |
285 | if x is None: | |
286 | return self.groups[self.current_group] | |
287 | if x in self.group_names: | |
288 | return self.group_names[x] | |
289 | return self.groups[x] | |
290 | def add_to_group(self,tgen,group=None): | |
291 | assert(isinstance(tgen,TaskGen.task_gen)or isinstance(tgen,Task.Task)) | |
292 | tgen.bld=self | |
293 | self.get_group(group).append(tgen) | |
294 | def get_group_name(self,g): | |
295 | if not isinstance(g,list): | |
296 | g=self.groups[g] | |
297 | for x in self.group_names: | |
298 | if id(self.group_names[x])==id(g): | |
299 | return x | |
300 | return'' | |
301 | def get_group_idx(self,tg): | |
302 | se=id(tg) | |
303 | for i,tmp in enumerate(self.groups): | |
304 | for t in tmp: | |
305 | if id(t)==se: | |
306 | return i | |
307 | return None | |
308 | def add_group(self,name=None,move=True): | |
309 | if name and name in self.group_names: | |
310 | raise Errors.WafError('add_group: name %s already present',name) | |
311 | g=[] | |
312 | self.group_names[name]=g | |
313 | self.groups.append(g) | |
314 | if move: | |
315 | self.current_group=len(self.groups)-1 | |
316 | def set_group(self,idx): | |
317 | if isinstance(idx,str): | |
318 | g=self.group_names[idx] | |
319 | for i,tmp in enumerate(self.groups): | |
320 | if id(g)==id(tmp): | |
321 | self.current_group=i | |
322 | break | |
323 | else: | |
324 | self.current_group=idx | |
325 | def total(self): | |
326 | total=0 | |
327 | for group in self.groups: | |
328 | for tg in group: | |
329 | try: | |
330 | total+=len(tg.tasks) | |
331 | except AttributeError: | |
332 | total+=1 | |
333 | return total | |
334 | def get_targets(self): | |
335 | to_post=[] | |
336 | min_grp=0 | |
337 | for name in self.targets.split(','): | |
338 | tg=self.get_tgen_by_name(name) | |
339 | m=self.get_group_idx(tg) | |
340 | if m>min_grp: | |
341 | min_grp=m | |
342 | to_post=[tg] | |
343 | elif m==min_grp: | |
344 | to_post.append(tg) | |
345 | return(min_grp,to_post) | |
346 | def get_all_task_gen(self): | |
347 | lst=[] | |
348 | for g in self.groups: | |
349 | lst.extend(g) | |
350 | return lst | |
351 | def post_group(self): | |
352 | def tgpost(tg): | |
353 | try: | |
354 | f=tg.post | |
355 | except AttributeError: | |
356 | pass | |
357 | else: | |
358 | f() | |
359 | if self.targets=='*': | |
360 | for tg in self.groups[self.current_group]: | |
361 | tgpost(tg) | |
362 | elif self.targets: | |
363 | if self.current_group<self._min_grp: | |
364 | for tg in self.groups[self.current_group]: | |
365 | tgpost(tg) | |
366 | else: | |
367 | for tg in self._exact_tg: | |
368 | tg.post() | |
369 | else: | |
370 | ln=self.launch_node() | |
371 | if ln.is_child_of(self.bldnode): | |
372 | Logs.warn('Building from the build directory, forcing --targets=*') | |
373 | ln=self.srcnode | |
374 | elif not ln.is_child_of(self.srcnode): | |
375 | Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)',ln.abspath(),self.srcnode.abspath()) | |
376 | ln=self.srcnode | |
377 | def is_post(tg,ln): | |
378 | try: | |
379 | p=tg.path | |
380 | except AttributeError: | |
381 | pass | |
382 | else: | |
383 | if p.is_child_of(ln): | |
384 | return True | |
385 | def is_post_group(): | |
386 | for i,g in enumerate(self.groups): | |
387 | if i>self.current_group: | |
388 | for tg in g: | |
389 | if is_post(tg,ln): | |
390 | return True | |
391 | if self.post_mode==POST_LAZY and ln!=self.srcnode: | |
392 | if is_post_group(): | |
393 | ln=self.srcnode | |
394 | for tg in self.groups[self.current_group]: | |
395 | if is_post(tg,ln): | |
396 | tgpost(tg) | |
397 | def get_tasks_group(self,idx): | |
398 | tasks=[] | |
399 | for tg in self.groups[idx]: | |
400 | try: | |
401 | tasks.extend(tg.tasks) | |
402 | except AttributeError: | |
403 | tasks.append(tg) | |
404 | return tasks | |
405 | def get_build_iterator(self): | |
406 | if self.targets and self.targets!='*': | |
407 | (self._min_grp,self._exact_tg)=self.get_targets() | |
408 | if self.post_mode!=POST_LAZY: | |
409 | for self.current_group,_ in enumerate(self.groups): | |
410 | self.post_group() | |
411 | for self.current_group,_ in enumerate(self.groups): | |
412 | if self.post_mode!=POST_AT_ONCE: | |
413 | self.post_group() | |
414 | tasks=self.get_tasks_group(self.current_group) | |
415 | Task.set_file_constraints(tasks) | |
416 | Task.set_precedence_constraints(tasks) | |
417 | self.cur_tasks=tasks | |
418 | if tasks: | |
419 | yield tasks | |
420 | while 1: | |
421 | yield[] | |
422 | def install_files(self,dest,files,**kw): | |
423 | assert(dest) | |
424 | tg=self(features='install_task',install_to=dest,install_from=files,**kw) | |
425 | tg.dest=tg.install_to | |
426 | tg.type='install_files' | |
427 | if not kw.get('postpone',True): | |
428 | tg.post() | |
429 | return tg | |
430 | def install_as(self,dest,srcfile,**kw): | |
431 | assert(dest) | |
432 | tg=self(features='install_task',install_to=dest,install_from=srcfile,**kw) | |
433 | tg.dest=tg.install_to | |
434 | tg.type='install_as' | |
435 | if not kw.get('postpone',True): | |
436 | tg.post() | |
437 | return tg | |
438 | def symlink_as(self,dest,src,**kw): | |
439 | assert(dest) | |
440 | tg=self(features='install_task',install_to=dest,install_from=src,**kw) | |
441 | tg.dest=tg.install_to | |
442 | tg.type='symlink_as' | |
443 | tg.link=src | |
444 | if not kw.get('postpone',True): | |
445 | tg.post() | |
446 | return tg | |
447 | @TaskGen.feature('install_task') | |
448 | @TaskGen.before_method('process_rule','process_source') | |
449 | def process_install_task(self): | |
450 | self.add_install_task(**self.__dict__) | |
451 | @TaskGen.taskgen_method | |
452 | def add_install_task(self,**kw): | |
453 | if not self.bld.is_install: | |
454 | return | |
455 | if not kw['install_to']: | |
456 | return | |
457 | if kw['type']=='symlink_as'and Utils.is_win32: | |
458 | if kw.get('win32_install'): | |
459 | kw['type']='install_as' | |
460 | else: | |
461 | return | |
462 | tsk=self.install_task=self.create_task('inst') | |
463 | tsk.chmod=kw.get('chmod',Utils.O644) | |
464 | tsk.link=kw.get('link','')or kw.get('install_from','') | |
465 | tsk.relative_trick=kw.get('relative_trick',False) | |
466 | tsk.type=kw['type'] | |
467 | tsk.install_to=tsk.dest=kw['install_to'] | |
468 | tsk.install_from=kw['install_from'] | |
469 | tsk.relative_base=kw.get('cwd')or kw.get('relative_base',self.path) | |
470 | tsk.install_user=kw.get('install_user') | |
471 | tsk.install_group=kw.get('install_group') | |
472 | tsk.init_files() | |
473 | if not kw.get('postpone',True): | |
474 | tsk.run_now() | |
475 | return tsk | |
476 | @TaskGen.taskgen_method | |
477 | def add_install_files(self,**kw): | |
478 | kw['type']='install_files' | |
479 | return self.add_install_task(**kw) | |
480 | @TaskGen.taskgen_method | |
481 | def add_install_as(self,**kw): | |
482 | kw['type']='install_as' | |
483 | return self.add_install_task(**kw) | |
484 | @TaskGen.taskgen_method | |
485 | def add_symlink_as(self,**kw): | |
486 | kw['type']='symlink_as' | |
487 | return self.add_install_task(**kw) | |
488 | class inst(Task.Task): | |
489 | def __str__(self): | |
490 | return'' | |
491 | def uid(self): | |
492 | lst=self.inputs+self.outputs+[self.link,self.generator.path.abspath()] | |
493 | return Utils.h_list(lst) | |
494 | def init_files(self): | |
495 | if self.type=='symlink_as': | |
496 | inputs=[] | |
497 | else: | |
498 | inputs=self.generator.to_nodes(self.install_from) | |
499 | if self.type=='install_as': | |
500 | assert len(inputs)==1 | |
501 | self.set_inputs(inputs) | |
502 | dest=self.get_install_path() | |
503 | outputs=[] | |
504 | if self.type=='symlink_as': | |
505 | if self.relative_trick: | |
506 | self.link=os.path.relpath(self.link,os.path.dirname(dest)) | |
507 | outputs.append(self.generator.bld.root.make_node(dest)) | |
508 | elif self.type=='install_as': | |
509 | outputs.append(self.generator.bld.root.make_node(dest)) | |
510 | else: | |
511 | for y in inputs: | |
512 | if self.relative_trick: | |
513 | destfile=os.path.join(dest,y.path_from(self.relative_base)) | |
514 | else: | |
515 | destfile=os.path.join(dest,y.name) | |
516 | outputs.append(self.generator.bld.root.make_node(destfile)) | |
517 | self.set_outputs(outputs) | |
518 | def runnable_status(self): | |
519 | ret=super(inst,self).runnable_status() | |
520 | if ret==Task.SKIP_ME and self.generator.bld.is_install: | |
521 | return Task.RUN_ME | |
522 | return ret | |
523 | def post_run(self): | |
524 | pass | |
525 | def get_install_path(self,destdir=True): | |
526 | if isinstance(self.install_to,Node.Node): | |
527 | dest=self.install_to.abspath() | |
528 | else: | |
529 | dest=os.path.normpath(Utils.subst_vars(self.install_to,self.env)) | |
530 | if not os.path.isabs(dest): | |
531 | dest=os.path.join(self.env.PREFIX,dest) | |
532 | if destdir and Options.options.destdir: | |
533 | dest=os.path.join(Options.options.destdir,os.path.splitdrive(dest)[1].lstrip(os.sep)) | |
534 | return dest | |
535 | def copy_fun(self,src,tgt): | |
536 | if Utils.is_win32 and len(tgt)>259 and not tgt.startswith('\\\\?\\'): | |
537 | tgt='\\\\?\\'+tgt | |
538 | shutil.copy2(src,tgt) | |
539 | self.fix_perms(tgt) | |
540 | def rm_empty_dirs(self,tgt): | |
541 | while tgt: | |
542 | tgt=os.path.dirname(tgt) | |
543 | try: | |
544 | os.rmdir(tgt) | |
545 | except OSError: | |
546 | break | |
547 | def run(self): | |
548 | is_install=self.generator.bld.is_install | |
549 | if not is_install: | |
550 | return | |
551 | for x in self.outputs: | |
552 | if is_install==INSTALL: | |
553 | x.parent.mkdir() | |
554 | if self.type=='symlink_as': | |
555 | fun=is_install==INSTALL and self.do_link or self.do_unlink | |
556 | fun(self.link,self.outputs[0].abspath()) | |
557 | else: | |
558 | fun=is_install==INSTALL and self.do_install or self.do_uninstall | |
559 | launch_node=self.generator.bld.launch_node() | |
560 | for x,y in zip(self.inputs,self.outputs): | |
561 | fun(x.abspath(),y.abspath(),x.path_from(launch_node)) | |
562 | def run_now(self): | |
563 | status=self.runnable_status() | |
564 | if status not in(Task.RUN_ME,Task.SKIP_ME): | |
565 | raise Errors.TaskNotReady('Could not process %r: status %r'%(self,status)) | |
566 | self.run() | |
567 | self.hasrun=Task.SUCCESS | |
568 | def do_install(self,src,tgt,lbl,**kw): | |
569 | if not Options.options.force: | |
570 | try: | |
571 | st1=os.stat(tgt) | |
572 | st2=os.stat(src) | |
573 | except OSError: | |
574 | pass | |
575 | else: | |
576 | if st1.st_mtime+2>=st2.st_mtime and st1.st_size==st2.st_size: | |
577 | if not self.generator.bld.progress_bar: | |
578 | c1=Logs.colors.NORMAL | |
579 | c2=Logs.colors.BLUE | |
580 | Logs.info('%s- install %s%s%s (from %s)',c1,c2,tgt,c1,lbl) | |
581 | return False | |
582 | if not self.generator.bld.progress_bar: | |
583 | c1=Logs.colors.NORMAL | |
584 | c2=Logs.colors.BLUE | |
585 | Logs.info('%s+ install %s%s%s (from %s)',c1,c2,tgt,c1,lbl) | |
586 | try: | |
587 | os.chmod(tgt,Utils.O644|stat.S_IMODE(os.stat(tgt).st_mode)) | |
588 | except EnvironmentError: | |
589 | pass | |
590 | try: | |
591 | os.remove(tgt) | |
592 | except OSError: | |
593 | pass | |
594 | try: | |
595 | self.copy_fun(src,tgt) | |
596 | except EnvironmentError as e: | |
597 | if not os.path.exists(src): | |
598 | Logs.error('File %r does not exist',src) | |
599 | elif not os.path.isfile(src): | |
600 | Logs.error('Input %r is not a file',src) | |
601 | raise Errors.WafError('Could not install the file %r'%tgt,e) | |
602 | def fix_perms(self,tgt): | |
603 | if not Utils.is_win32: | |
604 | user=getattr(self,'install_user',None)or getattr(self.generator,'install_user',None) | |
605 | group=getattr(self,'install_group',None)or getattr(self.generator,'install_group',None) | |
606 | if user or group: | |
607 | Utils.lchown(tgt,user or-1,group or-1) | |
608 | if not os.path.islink(tgt): | |
609 | os.chmod(tgt,self.chmod) | |
610 | def do_link(self,src,tgt,**kw): | |
611 | if os.path.islink(tgt)and os.readlink(tgt)==src: | |
612 | if not self.generator.bld.progress_bar: | |
613 | c1=Logs.colors.NORMAL | |
614 | c2=Logs.colors.BLUE | |
615 | Logs.info('%s- symlink %s%s%s (to %s)',c1,c2,tgt,c1,src) | |
616 | else: | |
617 | try: | |
618 | os.remove(tgt) | |
619 | except OSError: | |
620 | pass | |
621 | if not self.generator.bld.progress_bar: | |
622 | c1=Logs.colors.NORMAL | |
623 | c2=Logs.colors.BLUE | |
624 | Logs.info('%s+ symlink %s%s%s (to %s)',c1,c2,tgt,c1,src) | |
625 | os.symlink(src,tgt) | |
626 | self.fix_perms(tgt) | |
627 | def do_uninstall(self,src,tgt,lbl,**kw): | |
628 | if not self.generator.bld.progress_bar: | |
629 | c1=Logs.colors.NORMAL | |
630 | c2=Logs.colors.BLUE | |
631 | Logs.info('%s- remove %s%s%s',c1,c2,tgt,c1) | |
632 | try: | |
633 | os.remove(tgt) | |
634 | except OSError as e: | |
635 | if e.errno!=errno.ENOENT: | |
636 | if not getattr(self,'uninstall_error',None): | |
637 | self.uninstall_error=True | |
638 | Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)') | |
639 | if Logs.verbose>1: | |
640 | Logs.warn('Could not remove %s (error code %r)',e.filename,e.errno) | |
641 | self.rm_empty_dirs(tgt) | |
642 | def do_unlink(self,src,tgt,**kw): | |
643 | try: | |
644 | if not self.generator.bld.progress_bar: | |
645 | c1=Logs.colors.NORMAL | |
646 | c2=Logs.colors.BLUE | |
647 | Logs.info('%s- remove %s%s%s',c1,c2,tgt,c1) | |
648 | os.remove(tgt) | |
649 | except OSError: | |
650 | pass | |
651 | self.rm_empty_dirs(tgt) | |
652 | class InstallContext(BuildContext): | |
653 | '''installs the targets on the system''' | |
654 | cmd='install' | |
655 | def __init__(self,**kw): | |
656 | super(InstallContext,self).__init__(**kw) | |
657 | self.is_install=INSTALL | |
658 | class UninstallContext(InstallContext): | |
659 | '''removes the targets installed''' | |
660 | cmd='uninstall' | |
661 | def __init__(self,**kw): | |
662 | super(UninstallContext,self).__init__(**kw) | |
663 | self.is_install=UNINSTALL | |
664 | class CleanContext(BuildContext): | |
665 | '''cleans the project''' | |
666 | cmd='clean' | |
667 | def execute(self): | |
668 | self.restore() | |
669 | if not self.all_envs: | |
670 | self.load_envs() | |
671 | self.recurse([self.run_dir]) | |
672 | try: | |
673 | self.clean() | |
674 | finally: | |
675 | self.store() | |
676 | def clean(self): | |
677 | Logs.debug('build: clean called') | |
678 | if hasattr(self,'clean_files'): | |
679 | for n in self.clean_files: | |
680 | n.delete() | |
681 | elif self.bldnode!=self.srcnode: | |
682 | lst=[] | |
683 | for env in self.all_envs.values(): | |
684 | lst.extend(self.root.find_or_declare(f)for f in env[CFG_FILES]) | |
685 | excluded_dirs='.lock* *conf_check_*/** config.log %s/*'%CACHE_DIR | |
686 | for n in self.bldnode.ant_glob('**/*',excl=excluded_dirs,quiet=True): | |
687 | if n in lst: | |
688 | continue | |
689 | n.delete() | |
690 | self.root.children={} | |
691 | for v in SAVED_ATTRS: | |
692 | if v=='root': | |
693 | continue | |
694 | setattr(self,v,{}) | |
695 | class ListContext(BuildContext): | |
696 | '''lists the targets to execute''' | |
697 | cmd='list' | |
698 | def execute(self): | |
699 | self.restore() | |
700 | if not self.all_envs: | |
701 | self.load_envs() | |
702 | self.recurse([self.run_dir]) | |
703 | self.pre_build() | |
704 | self.timer=Utils.Timer() | |
705 | for g in self.groups: | |
706 | for tg in g: | |
707 | try: | |
708 | f=tg.post | |
709 | except AttributeError: | |
710 | pass | |
711 | else: | |
712 | f() | |
713 | try: | |
714 | self.get_tgen_by_name('') | |
715 | except Errors.WafError: | |
716 | pass | |
717 | targets=sorted(self.task_gen_cache_names) | |
718 | line_just=max(len(t)for t in targets)if targets else 0 | |
719 | for target in targets: | |
720 | tgen=self.task_gen_cache_names[target] | |
721 | descript=getattr(tgen,'description','') | |
722 | if descript: | |
723 | target=target.ljust(line_just) | |
724 | descript=': %s'%descript | |
725 | Logs.pprint('GREEN',target,label=descript) | |
726 | class StepContext(BuildContext): | |
727 | '''executes tasks in a step-by-step fashion, for debugging''' | |
728 | cmd='step' | |
729 | def __init__(self,**kw): | |
730 | super(StepContext,self).__init__(**kw) | |
731 | self.files=Options.options.files | |
732 | def compile(self): | |
733 | if not self.files: | |
734 | Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"') | |
735 | BuildContext.compile(self) | |
736 | return | |
737 | targets=[] | |
738 | if self.targets and self.targets!='*': | |
739 | targets=self.targets.split(',') | |
740 | for g in self.groups: | |
741 | for tg in g: | |
742 | if targets and tg.name not in targets: | |
743 | continue | |
744 | try: | |
745 | f=tg.post | |
746 | except AttributeError: | |
747 | pass | |
748 | else: | |
749 | f() | |
750 | for pat in self.files.split(','): | |
751 | matcher=self.get_matcher(pat) | |
752 | for tg in g: | |
753 | if isinstance(tg,Task.Task): | |
754 | lst=[tg] | |
755 | else: | |
756 | lst=tg.tasks | |
757 | for tsk in lst: | |
758 | do_exec=False | |
759 | for node in tsk.inputs: | |
760 | if matcher(node,output=False): | |
761 | do_exec=True | |
762 | break | |
763 | for node in tsk.outputs: | |
764 | if matcher(node,output=True): | |
765 | do_exec=True | |
766 | break | |
767 | if do_exec: | |
768 | ret=tsk.run() | |
769 | Logs.info('%s -> exit %r',tsk,ret) | |
770 | def get_matcher(self,pat): | |
771 | inn=True | |
772 | out=True | |
773 | if pat.startswith('in:'): | |
774 | out=False | |
775 | pat=pat.replace('in:','') | |
776 | elif pat.startswith('out:'): | |
777 | inn=False | |
778 | pat=pat.replace('out:','') | |
779 | anode=self.root.find_node(pat) | |
780 | pattern=None | |
781 | if not anode: | |
782 | if not pat.startswith('^'): | |
783 | pat='^.+?%s'%pat | |
784 | if not pat.endswith('$'): | |
785 | pat='%s$'%pat | |
786 | pattern=re.compile(pat) | |
787 | def match(node,output): | |
788 | if output and not out: | |
789 | return False | |
790 | if not output and not inn: | |
791 | return False | |
792 | if anode: | |
793 | return anode==node | |
794 | else: | |
795 | return pattern.match(node.abspath()) | |
796 | return match | |
797 | class EnvContext(BuildContext): | |
798 | fun=cmd=None | |
799 | def execute(self): | |
800 | self.restore() | |
801 | if not self.all_envs: | |
802 | self.load_envs() | |
803 | self.recurse([self.run_dir]) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import copy,re,os | |
5 | from waflib import Logs,Utils | |
6 | re_imp=re.compile(r'^(#)*?([^#=]*?)\ =\ (.*?)$',re.M) | |
7 | class ConfigSet(object): | |
8 | __slots__=('table','parent') | |
9 | def __init__(self,filename=None): | |
10 | self.table={} | |
11 | if filename: | |
12 | self.load(filename) | |
13 | def __contains__(self,key): | |
14 | if key in self.table: | |
15 | return True | |
16 | try: | |
17 | return self.parent.__contains__(key) | |
18 | except AttributeError: | |
19 | return False | |
20 | def keys(self): | |
21 | keys=set() | |
22 | cur=self | |
23 | while cur: | |
24 | keys.update(cur.table.keys()) | |
25 | cur=getattr(cur,'parent',None) | |
26 | keys=list(keys) | |
27 | keys.sort() | |
28 | return keys | |
29 | def __iter__(self): | |
30 | return iter(self.keys()) | |
31 | def __str__(self): | |
32 | return"\n".join(["%r %r"%(x,self.__getitem__(x))for x in self.keys()]) | |
33 | def __getitem__(self,key): | |
34 | try: | |
35 | while 1: | |
36 | x=self.table.get(key) | |
37 | if not x is None: | |
38 | return x | |
39 | self=self.parent | |
40 | except AttributeError: | |
41 | return[] | |
42 | def __setitem__(self,key,value): | |
43 | self.table[key]=value | |
44 | def __delitem__(self,key): | |
45 | self[key]=[] | |
46 | def __getattr__(self,name): | |
47 | if name in self.__slots__: | |
48 | return object.__getattribute__(self,name) | |
49 | else: | |
50 | return self[name] | |
51 | def __setattr__(self,name,value): | |
52 | if name in self.__slots__: | |
53 | object.__setattr__(self,name,value) | |
54 | else: | |
55 | self[name]=value | |
56 | def __delattr__(self,name): | |
57 | if name in self.__slots__: | |
58 | object.__delattr__(self,name) | |
59 | else: | |
60 | del self[name] | |
61 | def derive(self): | |
62 | newenv=ConfigSet() | |
63 | newenv.parent=self | |
64 | return newenv | |
65 | def detach(self): | |
66 | tbl=self.get_merged_dict() | |
67 | try: | |
68 | delattr(self,'parent') | |
69 | except AttributeError: | |
70 | pass | |
71 | else: | |
72 | keys=tbl.keys() | |
73 | for x in keys: | |
74 | tbl[x]=copy.deepcopy(tbl[x]) | |
75 | self.table=tbl | |
76 | return self | |
77 | def get_flat(self,key): | |
78 | s=self[key] | |
79 | if isinstance(s,str): | |
80 | return s | |
81 | return' '.join(s) | |
82 | def _get_list_value_for_modification(self,key): | |
83 | try: | |
84 | value=self.table[key] | |
85 | except KeyError: | |
86 | try: | |
87 | value=self.parent[key] | |
88 | except AttributeError: | |
89 | value=[] | |
90 | else: | |
91 | if isinstance(value,list): | |
92 | value=value[:] | |
93 | else: | |
94 | value=[value] | |
95 | self.table[key]=value | |
96 | else: | |
97 | if not isinstance(value,list): | |
98 | self.table[key]=value=[value] | |
99 | return value | |
100 | def append_value(self,var,val): | |
101 | if isinstance(val,str): | |
102 | val=[val] | |
103 | current_value=self._get_list_value_for_modification(var) | |
104 | current_value.extend(val) | |
105 | def prepend_value(self,var,val): | |
106 | if isinstance(val,str): | |
107 | val=[val] | |
108 | self.table[var]=val+self._get_list_value_for_modification(var) | |
109 | def append_unique(self,var,val): | |
110 | if isinstance(val,str): | |
111 | val=[val] | |
112 | current_value=self._get_list_value_for_modification(var) | |
113 | for x in val: | |
114 | if x not in current_value: | |
115 | current_value.append(x) | |
116 | def get_merged_dict(self): | |
117 | table_list=[] | |
118 | env=self | |
119 | while 1: | |
120 | table_list.insert(0,env.table) | |
121 | try: | |
122 | env=env.parent | |
123 | except AttributeError: | |
124 | break | |
125 | merged_table={} | |
126 | for table in table_list: | |
127 | merged_table.update(table) | |
128 | return merged_table | |
129 | def store(self,filename): | |
130 | try: | |
131 | os.makedirs(os.path.split(filename)[0]) | |
132 | except OSError: | |
133 | pass | |
134 | buf=[] | |
135 | merged_table=self.get_merged_dict() | |
136 | keys=list(merged_table.keys()) | |
137 | keys.sort() | |
138 | try: | |
139 | fun=ascii | |
140 | except NameError: | |
141 | fun=repr | |
142 | for k in keys: | |
143 | if k!='undo_stack': | |
144 | buf.append('%s = %s\n'%(k,fun(merged_table[k]))) | |
145 | Utils.writef(filename,''.join(buf)) | |
146 | def load(self,filename): | |
147 | tbl=self.table | |
148 | code=Utils.readf(filename,m='r') | |
149 | for m in re_imp.finditer(code): | |
150 | g=m.group | |
151 | tbl[g(2)]=eval(g(3)) | |
152 | Logs.debug('env: %s',self.table) | |
153 | def update(self,d): | |
154 | self.table.update(d) | |
155 | def stash(self): | |
156 | orig=self.table | |
157 | tbl=self.table=self.table.copy() | |
158 | for x in tbl.keys(): | |
159 | tbl[x]=copy.deepcopy(tbl[x]) | |
160 | self.undo_stack=self.undo_stack+[orig] | |
161 | def commit(self): | |
162 | self.undo_stack.pop(-1) | |
163 | def revert(self): | |
164 | self.table=self.undo_stack.pop(-1) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re,shlex,shutil,sys,time,traceback | |
5 | from waflib import ConfigSet,Utils,Options,Logs,Context,Build,Errors | |
6 | WAF_CONFIG_LOG='config.log' | |
7 | autoconfig=False | |
8 | conf_template='''# project %(app)s configured on %(now)s by | |
9 | # waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s) | |
10 | # using %(args)s | |
11 | #''' | |
12 | class ConfigurationContext(Context.Context): | |
13 | '''configures the project''' | |
14 | cmd='configure' | |
15 | error_handlers=[] | |
16 | def __init__(self,**kw): | |
17 | super(ConfigurationContext,self).__init__(**kw) | |
18 | self.environ=dict(os.environ) | |
19 | self.all_envs={} | |
20 | self.top_dir=None | |
21 | self.out_dir=None | |
22 | self.tools=[] | |
23 | self.hash=0 | |
24 | self.files=[] | |
25 | self.tool_cache=[] | |
26 | self.setenv('') | |
27 | def setenv(self,name,env=None): | |
28 | if name not in self.all_envs or env: | |
29 | if not env: | |
30 | env=ConfigSet.ConfigSet() | |
31 | self.prepare_env(env) | |
32 | else: | |
33 | env=env.derive() | |
34 | self.all_envs[name]=env | |
35 | self.variant=name | |
36 | def get_env(self): | |
37 | return self.all_envs[self.variant] | |
38 | def set_env(self,val): | |
39 | self.all_envs[self.variant]=val | |
40 | env=property(get_env,set_env) | |
41 | def init_dirs(self): | |
42 | top=self.top_dir | |
43 | if not top: | |
44 | top=Options.options.top | |
45 | if not top: | |
46 | top=getattr(Context.g_module,Context.TOP,None) | |
47 | if not top: | |
48 | top=self.path.abspath() | |
49 | top=os.path.abspath(top) | |
50 | self.srcnode=(os.path.isabs(top)and self.root or self.path).find_dir(top) | |
51 | assert(self.srcnode) | |
52 | out=self.out_dir | |
53 | if not out: | |
54 | out=Options.options.out | |
55 | if not out: | |
56 | out=getattr(Context.g_module,Context.OUT,None) | |
57 | if not out: | |
58 | out=Options.lockfile.replace('.lock-waf_%s_'%sys.platform,'').replace('.lock-waf','') | |
59 | out=os.path.realpath(out) | |
60 | self.bldnode=(os.path.isabs(out)and self.root or self.path).make_node(out) | |
61 | self.bldnode.mkdir() | |
62 | if not os.path.isdir(self.bldnode.abspath()): | |
63 | self.fatal('Could not create the build directory %s'%self.bldnode.abspath()) | |
64 | def execute(self): | |
65 | self.init_dirs() | |
66 | self.cachedir=self.bldnode.make_node(Build.CACHE_DIR) | |
67 | self.cachedir.mkdir() | |
68 | path=os.path.join(self.bldnode.abspath(),WAF_CONFIG_LOG) | |
69 | self.logger=Logs.make_logger(path,'cfg') | |
70 | app=getattr(Context.g_module,'APPNAME','') | |
71 | if app: | |
72 | ver=getattr(Context.g_module,'VERSION','') | |
73 | if ver: | |
74 | app="%s (%s)"%(app,ver) | |
75 | params={'now':time.ctime(),'pyver':sys.hexversion,'systype':sys.platform,'args':" ".join(sys.argv),'wafver':Context.WAFVERSION,'abi':Context.ABI,'app':app} | |
76 | self.to_log(conf_template%params) | |
77 | self.msg('Setting top to',self.srcnode.abspath()) | |
78 | self.msg('Setting out to',self.bldnode.abspath()) | |
79 | if id(self.srcnode)==id(self.bldnode): | |
80 | Logs.warn('Setting top == out') | |
81 | elif id(self.path)!=id(self.srcnode): | |
82 | if self.srcnode.is_child_of(self.path): | |
83 | Logs.warn('Are you certain that you do not want to set top="." ?') | |
84 | super(ConfigurationContext,self).execute() | |
85 | self.store() | |
86 | Context.top_dir=self.srcnode.abspath() | |
87 | Context.out_dir=self.bldnode.abspath() | |
88 | env=ConfigSet.ConfigSet() | |
89 | env.argv=sys.argv | |
90 | env.options=Options.options.__dict__ | |
91 | env.config_cmd=self.cmd | |
92 | env.run_dir=Context.run_dir | |
93 | env.top_dir=Context.top_dir | |
94 | env.out_dir=Context.out_dir | |
95 | env.hash=self.hash | |
96 | env.files=self.files | |
97 | env.environ=dict(self.environ) | |
98 | env.launch_dir=Context.launch_dir | |
99 | if not(self.env.NO_LOCK_IN_RUN or env.environ.get('NO_LOCK_IN_RUN')or getattr(Options.options,'no_lock_in_run')): | |
100 | env.store(os.path.join(Context.run_dir,Options.lockfile)) | |
101 | if not(self.env.NO_LOCK_IN_TOP or env.environ.get('NO_LOCK_IN_TOP')or getattr(Options.options,'no_lock_in_top')): | |
102 | env.store(os.path.join(Context.top_dir,Options.lockfile)) | |
103 | if not(self.env.NO_LOCK_IN_OUT or env.environ.get('NO_LOCK_IN_OUT')or getattr(Options.options,'no_lock_in_out')): | |
104 | env.store(os.path.join(Context.out_dir,Options.lockfile)) | |
105 | def prepare_env(self,env): | |
106 | if not env.PREFIX: | |
107 | if Options.options.prefix or Utils.is_win32: | |
108 | env.PREFIX=Options.options.prefix | |
109 | else: | |
110 | env.PREFIX='/' | |
111 | if not env.BINDIR: | |
112 | if Options.options.bindir: | |
113 | env.BINDIR=Options.options.bindir | |
114 | else: | |
115 | env.BINDIR=Utils.subst_vars('${PREFIX}/bin',env) | |
116 | if not env.LIBDIR: | |
117 | if Options.options.libdir: | |
118 | env.LIBDIR=Options.options.libdir | |
119 | else: | |
120 | env.LIBDIR=Utils.subst_vars('${PREFIX}/lib%s'%Utils.lib64(),env) | |
121 | def store(self): | |
122 | n=self.cachedir.make_node('build.config.py') | |
123 | n.write('version = 0x%x\ntools = %r\n'%(Context.HEXVERSION,self.tools)) | |
124 | if not self.all_envs: | |
125 | self.fatal('nothing to store in the configuration context!') | |
126 | for key in self.all_envs: | |
127 | tmpenv=self.all_envs[key] | |
128 | tmpenv.store(os.path.join(self.cachedir.abspath(),key+Build.CACHE_SUFFIX)) | |
129 | def load(self,tool_list,tooldir=None,funs=None,with_sys_path=True,cache=False): | |
130 | tools=Utils.to_list(tool_list) | |
131 | if tooldir: | |
132 | tooldir=Utils.to_list(tooldir) | |
133 | for tool in tools: | |
134 | if cache: | |
135 | mag=(tool,id(self.env),tooldir,funs) | |
136 | if mag in self.tool_cache: | |
137 | self.to_log('(tool %s is already loaded, skipping)'%tool) | |
138 | continue | |
139 | self.tool_cache.append(mag) | |
140 | module=None | |
141 | try: | |
142 | module=Context.load_tool(tool,tooldir,ctx=self,with_sys_path=with_sys_path) | |
143 | except ImportError as e: | |
144 | self.fatal('Could not load the Waf tool %r from %r\n%s'%(tool,getattr(e,'waf_sys_path',sys.path),e)) | |
145 | except Exception as e: | |
146 | self.to_log('imp %r (%r & %r)'%(tool,tooldir,funs)) | |
147 | self.to_log(traceback.format_exc()) | |
148 | raise | |
149 | if funs is not None: | |
150 | self.eval_rules(funs) | |
151 | else: | |
152 | func=getattr(module,'configure',None) | |
153 | if func: | |
154 | if type(func)is type(Utils.readf): | |
155 | func(self) | |
156 | else: | |
157 | self.eval_rules(func) | |
158 | self.tools.append({'tool':tool,'tooldir':tooldir,'funs':funs}) | |
159 | def post_recurse(self,node): | |
160 | super(ConfigurationContext,self).post_recurse(node) | |
161 | self.hash=Utils.h_list((self.hash,node.read('rb'))) | |
162 | self.files.append(node.abspath()) | |
163 | def eval_rules(self,rules): | |
164 | self.rules=Utils.to_list(rules) | |
165 | for x in self.rules: | |
166 | f=getattr(self,x) | |
167 | if not f: | |
168 | self.fatal('No such configuration function %r'%x) | |
169 | f() | |
170 | def conf(f): | |
171 | def fun(*k,**kw): | |
172 | mandatory=kw.pop('mandatory',True) | |
173 | try: | |
174 | return f(*k,**kw) | |
175 | except Errors.ConfigurationError: | |
176 | if mandatory: | |
177 | raise | |
178 | fun.__name__=f.__name__ | |
179 | setattr(ConfigurationContext,f.__name__,fun) | |
180 | setattr(Build.BuildContext,f.__name__,fun) | |
181 | return f | |
182 | @conf | |
183 | def add_os_flags(self,var,dest=None,dup=False): | |
184 | try: | |
185 | flags=shlex.split(self.environ[var]) | |
186 | except KeyError: | |
187 | return | |
188 | if dup or''.join(flags)not in''.join(Utils.to_list(self.env[dest or var])): | |
189 | self.env.append_value(dest or var,flags) | |
190 | @conf | |
191 | def cmd_to_list(self,cmd): | |
192 | if isinstance(cmd,str): | |
193 | if os.path.isfile(cmd): | |
194 | return[cmd] | |
195 | if os.sep=='/': | |
196 | return shlex.split(cmd) | |
197 | else: | |
198 | try: | |
199 | return shlex.split(cmd,posix=False) | |
200 | except TypeError: | |
201 | return shlex.split(cmd) | |
202 | return cmd | |
203 | @conf | |
204 | def check_waf_version(self,mini='1.9.99',maxi='2.1.0',**kw): | |
205 | self.start_msg('Checking for waf version in %s-%s'%(str(mini),str(maxi)),**kw) | |
206 | ver=Context.HEXVERSION | |
207 | if Utils.num2ver(mini)>ver: | |
208 | self.fatal('waf version should be at least %r (%r found)'%(Utils.num2ver(mini),ver)) | |
209 | if Utils.num2ver(maxi)<ver: | |
210 | self.fatal('waf version should be at most %r (%r found)'%(Utils.num2ver(maxi),ver)) | |
211 | self.end_msg('ok',**kw) | |
212 | @conf | |
213 | def find_file(self,filename,path_list=[]): | |
214 | for n in Utils.to_list(filename): | |
215 | for d in Utils.to_list(path_list): | |
216 | p=os.path.expanduser(os.path.join(d,n)) | |
217 | if os.path.exists(p): | |
218 | return p | |
219 | self.fatal('Could not find %r'%filename) | |
220 | @conf | |
221 | def find_program(self,filename,**kw): | |
222 | exts=kw.get('exts',Utils.is_win32 and'.exe,.com,.bat,.cmd'or',.sh,.pl,.py') | |
223 | environ=kw.get('environ',getattr(self,'environ',os.environ)) | |
224 | ret='' | |
225 | filename=Utils.to_list(filename) | |
226 | msg=kw.get('msg',', '.join(filename)) | |
227 | var=kw.get('var','') | |
228 | if not var: | |
229 | var=re.sub(r'[-.]','_',filename[0].upper()) | |
230 | path_list=kw.get('path_list','') | |
231 | if path_list: | |
232 | path_list=Utils.to_list(path_list) | |
233 | else: | |
234 | path_list=environ.get('PATH','').split(os.pathsep) | |
235 | if kw.get('value'): | |
236 | ret=self.cmd_to_list(kw['value']) | |
237 | elif environ.get(var): | |
238 | ret=self.cmd_to_list(environ[var]) | |
239 | elif self.env[var]: | |
240 | ret=self.cmd_to_list(self.env[var]) | |
241 | else: | |
242 | if not ret: | |
243 | ret=self.find_binary(filename,exts.split(','),path_list) | |
244 | if not ret and Utils.winreg: | |
245 | ret=Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER,filename) | |
246 | if not ret and Utils.winreg: | |
247 | ret=Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE,filename) | |
248 | ret=self.cmd_to_list(ret) | |
249 | if ret: | |
250 | if len(ret)==1: | |
251 | retmsg=ret[0] | |
252 | else: | |
253 | retmsg=ret | |
254 | else: | |
255 | retmsg=False | |
256 | self.msg('Checking for program %r'%msg,retmsg,**kw) | |
257 | if not kw.get('quiet'): | |
258 | self.to_log('find program=%r paths=%r var=%r -> %r'%(filename,path_list,var,ret)) | |
259 | if not ret: | |
260 | self.fatal(kw.get('errmsg','')or'Could not find the program %r'%filename) | |
261 | interpreter=kw.get('interpreter') | |
262 | if interpreter is None: | |
263 | if not Utils.check_exe(ret[0],env=environ): | |
264 | self.fatal('Program %r is not executable'%ret) | |
265 | self.env[var]=ret | |
266 | else: | |
267 | self.env[var]=self.env[interpreter]+ret | |
268 | return ret | |
269 | @conf | |
270 | def find_binary(self,filenames,exts,paths): | |
271 | for f in filenames: | |
272 | for ext in exts: | |
273 | exe_name=f+ext | |
274 | if os.path.isabs(exe_name): | |
275 | if os.path.isfile(exe_name): | |
276 | return exe_name | |
277 | else: | |
278 | for path in paths: | |
279 | x=os.path.expanduser(os.path.join(path,exe_name)) | |
280 | if os.path.isfile(x): | |
281 | return x | |
282 | return None | |
283 | @conf | |
284 | def run_build(self,*k,**kw): | |
285 | buf=[] | |
286 | for key in sorted(kw.keys()): | |
287 | v=kw[key] | |
288 | if hasattr(v,'__call__'): | |
289 | buf.append(Utils.h_fun(v)) | |
290 | else: | |
291 | buf.append(str(v)) | |
292 | h=Utils.h_list(buf) | |
293 | dir=self.bldnode.abspath()+os.sep+(not Utils.is_win32 and'.'or'')+'conf_check_'+Utils.to_hex(h) | |
294 | cachemode=kw.get('confcache',getattr(Options.options,'confcache',None)) | |
295 | if not cachemode and os.path.exists(dir): | |
296 | shutil.rmtree(dir) | |
297 | try: | |
298 | os.makedirs(dir) | |
299 | except OSError: | |
300 | pass | |
301 | try: | |
302 | os.stat(dir) | |
303 | except OSError: | |
304 | self.fatal('cannot use the configuration test folder %r'%dir) | |
305 | if cachemode==1: | |
306 | try: | |
307 | proj=ConfigSet.ConfigSet(os.path.join(dir,'cache_run_build')) | |
308 | except EnvironmentError: | |
309 | pass | |
310 | else: | |
311 | ret=proj['cache_run_build'] | |
312 | if isinstance(ret,str)and ret.startswith('Test does not build'): | |
313 | self.fatal(ret) | |
314 | return ret | |
315 | bdir=os.path.join(dir,'testbuild') | |
316 | if not os.path.exists(bdir): | |
317 | os.makedirs(bdir) | |
318 | cls_name=kw.get('run_build_cls')or getattr(self,'run_build_cls','build') | |
319 | self.test_bld=bld=Context.create_context(cls_name,top_dir=dir,out_dir=bdir) | |
320 | bld.init_dirs() | |
321 | bld.progress_bar=0 | |
322 | bld.targets='*' | |
323 | bld.logger=self.logger | |
324 | bld.all_envs.update(self.all_envs) | |
325 | bld.env=kw['env'] | |
326 | bld.kw=kw | |
327 | bld.conf=self | |
328 | kw['build_fun'](bld) | |
329 | ret=-1 | |
330 | try: | |
331 | try: | |
332 | bld.compile() | |
333 | except Errors.WafError: | |
334 | ret='Test does not build: %s'%traceback.format_exc() | |
335 | self.fatal(ret) | |
336 | else: | |
337 | ret=getattr(bld,'retval',0) | |
338 | finally: | |
339 | if cachemode: | |
340 | proj=ConfigSet.ConfigSet() | |
341 | proj['cache_run_build']=ret | |
342 | proj.store(os.path.join(dir,'cache_run_build')) | |
343 | else: | |
344 | shutil.rmtree(dir) | |
345 | return ret | |
346 | @conf | |
347 | def ret_msg(self,msg,args): | |
348 | if isinstance(msg,str): | |
349 | return msg | |
350 | return msg(args) | |
351 | @conf | |
352 | def test(self,*k,**kw): | |
353 | if not'env'in kw: | |
354 | kw['env']=self.env.derive() | |
355 | if kw.get('validate'): | |
356 | kw['validate'](kw) | |
357 | self.start_msg(kw['msg'],**kw) | |
358 | ret=None | |
359 | try: | |
360 | ret=self.run_build(*k,**kw) | |
361 | except self.errors.ConfigurationError: | |
362 | self.end_msg(kw['errmsg'],'YELLOW',**kw) | |
363 | if Logs.verbose>1: | |
364 | raise | |
365 | else: | |
366 | self.fatal('The configuration failed') | |
367 | else: | |
368 | kw['success']=ret | |
369 | if kw.get('post_check'): | |
370 | ret=kw['post_check'](kw) | |
371 | if ret: | |
372 | self.end_msg(kw['errmsg'],'YELLOW',**kw) | |
373 | self.fatal('The configuration failed %r'%ret) | |
374 | else: | |
375 | self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw) | |
376 | return ret |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re,sys | |
5 | from waflib import Utils,Errors,Logs | |
6 | import waflib.Node | |
7 | if sys.hexversion>0x3040000: | |
8 | import types | |
9 | class imp(object): | |
10 | new_module=lambda x:types.ModuleType(x) | |
11 | else: | |
12 | import imp | |
13 | HEXVERSION=0x2001300 | |
14 | WAFVERSION="2.0.19" | |
15 | WAFREVISION="e83405712e95b47c040763fdfa468c04dfe72e4b" | |
16 | WAFNAME="waf" | |
17 | ABI=20 | |
18 | DBFILE='.wafpickle-%s-%d-%d'%(sys.platform,sys.hexversion,ABI) | |
19 | APPNAME='APPNAME' | |
20 | VERSION='VERSION' | |
21 | TOP='top' | |
22 | OUT='out' | |
23 | WSCRIPT_FILE='wscript' | |
24 | launch_dir='' | |
25 | run_dir='' | |
26 | top_dir='' | |
27 | out_dir='' | |
28 | waf_dir='' | |
29 | default_encoding=Utils.console_encoding() | |
30 | g_module=None | |
31 | STDOUT=1 | |
32 | STDERR=-1 | |
33 | BOTH=0 | |
34 | classes=[] | |
35 | def create_context(cmd_name,*k,**kw): | |
36 | for x in classes: | |
37 | if x.cmd==cmd_name: | |
38 | return x(*k,**kw) | |
39 | ctx=Context(*k,**kw) | |
40 | ctx.fun=cmd_name | |
41 | return ctx | |
42 | class store_context(type): | |
43 | def __init__(cls,name,bases,dct): | |
44 | super(store_context,cls).__init__(name,bases,dct) | |
45 | name=cls.__name__ | |
46 | if name in('ctx','Context'): | |
47 | return | |
48 | try: | |
49 | cls.cmd | |
50 | except AttributeError: | |
51 | raise Errors.WafError('Missing command for the context class %r (cmd)'%name) | |
52 | if not getattr(cls,'fun',None): | |
53 | cls.fun=cls.cmd | |
54 | classes.insert(0,cls) | |
55 | ctx=store_context('ctx',(object,),{}) | |
56 | class Context(ctx): | |
57 | errors=Errors | |
58 | tools={} | |
59 | def __init__(self,**kw): | |
60 | try: | |
61 | rd=kw['run_dir'] | |
62 | except KeyError: | |
63 | rd=run_dir | |
64 | self.node_class=type('Nod3',(waflib.Node.Node,),{}) | |
65 | self.node_class.__module__='waflib.Node' | |
66 | self.node_class.ctx=self | |
67 | self.root=self.node_class('',None) | |
68 | self.cur_script=None | |
69 | self.path=self.root.find_dir(rd) | |
70 | self.stack_path=[] | |
71 | self.exec_dict={'ctx':self,'conf':self,'bld':self,'opt':self} | |
72 | self.logger=None | |
73 | def finalize(self): | |
74 | try: | |
75 | logger=self.logger | |
76 | except AttributeError: | |
77 | pass | |
78 | else: | |
79 | Logs.free_logger(logger) | |
80 | delattr(self,'logger') | |
81 | def load(self,tool_list,*k,**kw): | |
82 | tools=Utils.to_list(tool_list) | |
83 | path=Utils.to_list(kw.get('tooldir','')) | |
84 | with_sys_path=kw.get('with_sys_path',True) | |
85 | for t in tools: | |
86 | module=load_tool(t,path,with_sys_path=with_sys_path) | |
87 | fun=getattr(module,kw.get('name',self.fun),None) | |
88 | if fun: | |
89 | fun(self) | |
90 | def execute(self): | |
91 | self.recurse([os.path.dirname(g_module.root_path)]) | |
92 | def pre_recurse(self,node): | |
93 | self.stack_path.append(self.cur_script) | |
94 | self.cur_script=node | |
95 | self.path=node.parent | |
96 | def post_recurse(self,node): | |
97 | self.cur_script=self.stack_path.pop() | |
98 | if self.cur_script: | |
99 | self.path=self.cur_script.parent | |
100 | def recurse(self,dirs,name=None,mandatory=True,once=True,encoding=None): | |
101 | try: | |
102 | cache=self.recurse_cache | |
103 | except AttributeError: | |
104 | cache=self.recurse_cache={} | |
105 | for d in Utils.to_list(dirs): | |
106 | if not os.path.isabs(d): | |
107 | d=os.path.join(self.path.abspath(),d) | |
108 | WSCRIPT=os.path.join(d,WSCRIPT_FILE) | |
109 | WSCRIPT_FUN=WSCRIPT+'_'+(name or self.fun) | |
110 | node=self.root.find_node(WSCRIPT_FUN) | |
111 | if node and(not once or node not in cache): | |
112 | cache[node]=True | |
113 | self.pre_recurse(node) | |
114 | try: | |
115 | function_code=node.read('r',encoding) | |
116 | exec(compile(function_code,node.abspath(),'exec'),self.exec_dict) | |
117 | finally: | |
118 | self.post_recurse(node) | |
119 | elif not node: | |
120 | node=self.root.find_node(WSCRIPT) | |
121 | tup=(node,name or self.fun) | |
122 | if node and(not once or tup not in cache): | |
123 | cache[tup]=True | |
124 | self.pre_recurse(node) | |
125 | try: | |
126 | wscript_module=load_module(node.abspath(),encoding=encoding) | |
127 | user_function=getattr(wscript_module,(name or self.fun),None) | |
128 | if not user_function: | |
129 | if not mandatory: | |
130 | continue | |
131 | raise Errors.WafError('No function %r defined in %s'%(name or self.fun,node.abspath())) | |
132 | user_function(self) | |
133 | finally: | |
134 | self.post_recurse(node) | |
135 | elif not node: | |
136 | if not mandatory: | |
137 | continue | |
138 | try: | |
139 | os.listdir(d) | |
140 | except OSError: | |
141 | raise Errors.WafError('Cannot read the folder %r'%d) | |
142 | raise Errors.WafError('No wscript file in directory %s'%d) | |
143 | def log_command(self,cmd,kw): | |
144 | if Logs.verbose: | |
145 | fmt=os.environ.get('WAF_CMD_FORMAT') | |
146 | if fmt=='string': | |
147 | if not isinstance(cmd,str): | |
148 | cmd=Utils.shell_escape(cmd) | |
149 | Logs.debug('runner: %r',cmd) | |
150 | Logs.debug('runner_env: kw=%s',kw) | |
151 | def exec_command(self,cmd,**kw): | |
152 | subprocess=Utils.subprocess | |
153 | kw['shell']=isinstance(cmd,str) | |
154 | self.log_command(cmd,kw) | |
155 | if self.logger: | |
156 | self.logger.info(cmd) | |
157 | if'stdout'not in kw: | |
158 | kw['stdout']=subprocess.PIPE | |
159 | if'stderr'not in kw: | |
160 | kw['stderr']=subprocess.PIPE | |
161 | if Logs.verbose and not kw['shell']and not Utils.check_exe(cmd[0]): | |
162 | raise Errors.WafError('Program %s not found!'%cmd[0]) | |
163 | cargs={} | |
164 | if'timeout'in kw: | |
165 | if sys.hexversion>=0x3030000: | |
166 | cargs['timeout']=kw['timeout'] | |
167 | if not'start_new_session'in kw: | |
168 | kw['start_new_session']=True | |
169 | del kw['timeout'] | |
170 | if'input'in kw: | |
171 | if kw['input']: | |
172 | cargs['input']=kw['input'] | |
173 | kw['stdin']=subprocess.PIPE | |
174 | del kw['input'] | |
175 | if'cwd'in kw: | |
176 | if not isinstance(kw['cwd'],str): | |
177 | kw['cwd']=kw['cwd'].abspath() | |
178 | encoding=kw.pop('decode_as',default_encoding) | |
179 | try: | |
180 | ret,out,err=Utils.run_process(cmd,kw,cargs) | |
181 | except Exception as e: | |
182 | raise Errors.WafError('Execution failure: %s'%str(e),ex=e) | |
183 | if out: | |
184 | if not isinstance(out,str): | |
185 | out=out.decode(encoding,errors='replace') | |
186 | if self.logger: | |
187 | self.logger.debug('out: %s',out) | |
188 | else: | |
189 | Logs.info(out,extra={'stream':sys.stdout,'c1':''}) | |
190 | if err: | |
191 | if not isinstance(err,str): | |
192 | err=err.decode(encoding,errors='replace') | |
193 | if self.logger: | |
194 | self.logger.error('err: %s'%err) | |
195 | else: | |
196 | Logs.info(err,extra={'stream':sys.stderr,'c1':''}) | |
197 | return ret | |
198 | def cmd_and_log(self,cmd,**kw): | |
199 | subprocess=Utils.subprocess | |
200 | kw['shell']=isinstance(cmd,str) | |
201 | self.log_command(cmd,kw) | |
202 | quiet=kw.pop('quiet',None) | |
203 | to_ret=kw.pop('output',STDOUT) | |
204 | if Logs.verbose and not kw['shell']and not Utils.check_exe(cmd[0]): | |
205 | raise Errors.WafError('Program %r not found!'%cmd[0]) | |
206 | kw['stdout']=kw['stderr']=subprocess.PIPE | |
207 | if quiet is None: | |
208 | self.to_log(cmd) | |
209 | cargs={} | |
210 | if'timeout'in kw: | |
211 | if sys.hexversion>=0x3030000: | |
212 | cargs['timeout']=kw['timeout'] | |
213 | if not'start_new_session'in kw: | |
214 | kw['start_new_session']=True | |
215 | del kw['timeout'] | |
216 | if'input'in kw: | |
217 | if kw['input']: | |
218 | cargs['input']=kw['input'] | |
219 | kw['stdin']=subprocess.PIPE | |
220 | del kw['input'] | |
221 | if'cwd'in kw: | |
222 | if not isinstance(kw['cwd'],str): | |
223 | kw['cwd']=kw['cwd'].abspath() | |
224 | encoding=kw.pop('decode_as',default_encoding) | |
225 | try: | |
226 | ret,out,err=Utils.run_process(cmd,kw,cargs) | |
227 | except Exception as e: | |
228 | raise Errors.WafError('Execution failure: %s'%str(e),ex=e) | |
229 | if not isinstance(out,str): | |
230 | out=out.decode(encoding,errors='replace') | |
231 | if not isinstance(err,str): | |
232 | err=err.decode(encoding,errors='replace') | |
233 | if out and quiet!=STDOUT and quiet!=BOTH: | |
234 | self.to_log('out: %s'%out) | |
235 | if err and quiet!=STDERR and quiet!=BOTH: | |
236 | self.to_log('err: %s'%err) | |
237 | if ret: | |
238 | e=Errors.WafError('Command %r returned %r'%(cmd,ret)) | |
239 | e.returncode=ret | |
240 | e.stderr=err | |
241 | e.stdout=out | |
242 | raise e | |
243 | if to_ret==BOTH: | |
244 | return(out,err) | |
245 | elif to_ret==STDERR: | |
246 | return err | |
247 | return out | |
248 | def fatal(self,msg,ex=None): | |
249 | if self.logger: | |
250 | self.logger.info('from %s: %s'%(self.path.abspath(),msg)) | |
251 | try: | |
252 | logfile=self.logger.handlers[0].baseFilename | |
253 | except AttributeError: | |
254 | pass | |
255 | else: | |
256 | if os.environ.get('WAF_PRINT_FAILURE_LOG'): | |
257 | msg='Log from (%s):\n%s\n'%(logfile,Utils.readf(logfile)) | |
258 | else: | |
259 | msg='%s\n(complete log in %s)'%(msg,logfile) | |
260 | raise self.errors.ConfigurationError(msg,ex=ex) | |
261 | def to_log(self,msg): | |
262 | if not msg: | |
263 | return | |
264 | if self.logger: | |
265 | self.logger.info(msg) | |
266 | else: | |
267 | sys.stderr.write(str(msg)) | |
268 | sys.stderr.flush() | |
269 | def msg(self,*k,**kw): | |
270 | try: | |
271 | msg=kw['msg'] | |
272 | except KeyError: | |
273 | msg=k[0] | |
274 | self.start_msg(msg,**kw) | |
275 | try: | |
276 | result=kw['result'] | |
277 | except KeyError: | |
278 | result=k[1] | |
279 | color=kw.get('color') | |
280 | if not isinstance(color,str): | |
281 | color=result and'GREEN'or'YELLOW' | |
282 | self.end_msg(result,color,**kw) | |
283 | def start_msg(self,*k,**kw): | |
284 | if kw.get('quiet'): | |
285 | return | |
286 | msg=kw.get('msg')or k[0] | |
287 | try: | |
288 | if self.in_msg: | |
289 | self.in_msg+=1 | |
290 | return | |
291 | except AttributeError: | |
292 | self.in_msg=0 | |
293 | self.in_msg+=1 | |
294 | try: | |
295 | self.line_just=max(self.line_just,len(msg)) | |
296 | except AttributeError: | |
297 | self.line_just=max(40,len(msg)) | |
298 | for x in(self.line_just*'-',msg): | |
299 | self.to_log(x) | |
300 | Logs.pprint('NORMAL',"%s :"%msg.ljust(self.line_just),sep='') | |
301 | def end_msg(self,*k,**kw): | |
302 | if kw.get('quiet'): | |
303 | return | |
304 | self.in_msg-=1 | |
305 | if self.in_msg: | |
306 | return | |
307 | result=kw.get('result')or k[0] | |
308 | defcolor='GREEN' | |
309 | if result is True: | |
310 | msg='ok' | |
311 | elif not result: | |
312 | msg='not found' | |
313 | defcolor='YELLOW' | |
314 | else: | |
315 | msg=str(result) | |
316 | self.to_log(msg) | |
317 | try: | |
318 | color=kw['color'] | |
319 | except KeyError: | |
320 | if len(k)>1 and k[1]in Logs.colors_lst: | |
321 | color=k[1] | |
322 | else: | |
323 | color=defcolor | |
324 | Logs.pprint(color,msg) | |
325 | def load_special_tools(self,var,ban=[]): | |
326 | if os.path.isdir(waf_dir): | |
327 | lst=self.root.find_node(waf_dir).find_node('waflib/extras').ant_glob(var) | |
328 | for x in lst: | |
329 | if not x.name in ban: | |
330 | load_tool(x.name.replace('.py','')) | |
331 | else: | |
332 | from zipfile import PyZipFile | |
333 | waflibs=PyZipFile(waf_dir) | |
334 | lst=waflibs.namelist() | |
335 | for x in lst: | |
336 | if not re.match('waflib/extras/%s'%var.replace('*','.*'),var): | |
337 | continue | |
338 | f=os.path.basename(x) | |
339 | doban=False | |
340 | for b in ban: | |
341 | r=b.replace('*','.*') | |
342 | if re.match(r,f): | |
343 | doban=True | |
344 | if not doban: | |
345 | f=f.replace('.py','') | |
346 | load_tool(f) | |
347 | cache_modules={} | |
348 | def load_module(path,encoding=None): | |
349 | try: | |
350 | return cache_modules[path] | |
351 | except KeyError: | |
352 | pass | |
353 | module=imp.new_module(WSCRIPT_FILE) | |
354 | try: | |
355 | code=Utils.readf(path,m='r',encoding=encoding) | |
356 | except EnvironmentError: | |
357 | raise Errors.WafError('Could not read the file %r'%path) | |
358 | module_dir=os.path.dirname(path) | |
359 | sys.path.insert(0,module_dir) | |
360 | try: | |
361 | exec(compile(code,path,'exec'),module.__dict__) | |
362 | finally: | |
363 | sys.path.remove(module_dir) | |
364 | cache_modules[path]=module | |
365 | return module | |
366 | def load_tool(tool,tooldir=None,ctx=None,with_sys_path=True): | |
367 | if tool=='java': | |
368 | tool='javaw' | |
369 | else: | |
370 | tool=tool.replace('++','xx') | |
371 | if not with_sys_path: | |
372 | back_path=sys.path | |
373 | sys.path=[] | |
374 | try: | |
375 | if tooldir: | |
376 | assert isinstance(tooldir,list) | |
377 | sys.path=tooldir+sys.path | |
378 | try: | |
379 | __import__(tool) | |
380 | except ImportError as e: | |
381 | e.waf_sys_path=list(sys.path) | |
382 | raise | |
383 | finally: | |
384 | for d in tooldir: | |
385 | sys.path.remove(d) | |
386 | ret=sys.modules[tool] | |
387 | Context.tools[tool]=ret | |
388 | return ret | |
389 | else: | |
390 | if not with_sys_path: | |
391 | sys.path.insert(0,waf_dir) | |
392 | try: | |
393 | for x in('waflib.Tools.%s','waflib.extras.%s','waflib.%s','%s'): | |
394 | try: | |
395 | __import__(x%tool) | |
396 | break | |
397 | except ImportError: | |
398 | x=None | |
399 | else: | |
400 | __import__(tool) | |
401 | except ImportError as e: | |
402 | e.waf_sys_path=list(sys.path) | |
403 | raise | |
404 | finally: | |
405 | if not with_sys_path: | |
406 | sys.path.remove(waf_dir) | |
407 | ret=sys.modules[x%tool] | |
408 | Context.tools[tool]=ret | |
409 | return ret | |
410 | finally: | |
411 | if not with_sys_path: | |
412 | sys.path+=back_path |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import traceback,sys | |
5 | class WafError(Exception): | |
6 | def __init__(self,msg='',ex=None): | |
7 | Exception.__init__(self) | |
8 | self.msg=msg | |
9 | assert not isinstance(msg,Exception) | |
10 | self.stack=[] | |
11 | if ex: | |
12 | if not msg: | |
13 | self.msg=str(ex) | |
14 | if isinstance(ex,WafError): | |
15 | self.stack=ex.stack | |
16 | else: | |
17 | self.stack=traceback.extract_tb(sys.exc_info()[2]) | |
18 | self.stack+=traceback.extract_stack()[:-1] | |
19 | self.verbose_msg=''.join(traceback.format_list(self.stack)) | |
20 | def __str__(self): | |
21 | return str(self.msg) | |
22 | class BuildError(WafError): | |
23 | def __init__(self,error_tasks=[]): | |
24 | self.tasks=error_tasks | |
25 | WafError.__init__(self,self.format_error()) | |
26 | def format_error(self): | |
27 | lst=['Build failed'] | |
28 | for tsk in self.tasks: | |
29 | txt=tsk.format_error() | |
30 | if txt: | |
31 | lst.append(txt) | |
32 | return'\n'.join(lst) | |
33 | class ConfigurationError(WafError): | |
34 | pass | |
35 | class TaskRescan(WafError): | |
36 | pass | |
37 | class TaskNotReady(WafError): | |
38 | pass |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re,traceback,sys | |
5 | from waflib import Utils,ansiterm | |
6 | if not os.environ.get('NOSYNC',False): | |
7 | if sys.stdout.isatty()and id(sys.stdout)==id(sys.__stdout__): | |
8 | sys.stdout=ansiterm.AnsiTerm(sys.stdout) | |
9 | if sys.stderr.isatty()and id(sys.stderr)==id(sys.__stderr__): | |
10 | sys.stderr=ansiterm.AnsiTerm(sys.stderr) | |
11 | import logging | |
12 | LOG_FORMAT=os.environ.get('WAF_LOG_FORMAT','%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s') | |
13 | HOUR_FORMAT=os.environ.get('WAF_HOUR_FORMAT','%H:%M:%S') | |
14 | zones=[] | |
15 | verbose=0 | |
16 | colors_lst={'USE':True,'BOLD':'\x1b[01;1m','RED':'\x1b[01;31m','GREEN':'\x1b[32m','YELLOW':'\x1b[33m','PINK':'\x1b[35m','BLUE':'\x1b[01;34m','CYAN':'\x1b[36m','GREY':'\x1b[37m','NORMAL':'\x1b[0m','cursor_on':'\x1b[?25h','cursor_off':'\x1b[?25l',} | |
17 | indicator='\r\x1b[K%s%s%s' | |
18 | try: | |
19 | unicode | |
20 | except NameError: | |
21 | unicode=None | |
22 | def enable_colors(use): | |
23 | if use==1: | |
24 | if not(sys.stderr.isatty()or sys.stdout.isatty()): | |
25 | use=0 | |
26 | if Utils.is_win32 and os.name!='java': | |
27 | term=os.environ.get('TERM','') | |
28 | else: | |
29 | term=os.environ.get('TERM','dumb') | |
30 | if term in('dumb','emacs'): | |
31 | use=0 | |
32 | if use>=1: | |
33 | os.environ['TERM']='vt100' | |
34 | colors_lst['USE']=use | |
35 | try: | |
36 | get_term_cols=ansiterm.get_term_cols | |
37 | except AttributeError: | |
38 | def get_term_cols(): | |
39 | return 80 | |
40 | get_term_cols.__doc__=""" | |
41 | Returns the console width in characters. | |
42 | ||
43 | :return: the number of characters per line | |
44 | :rtype: int | |
45 | """ | |
46 | def get_color(cl): | |
47 | if colors_lst['USE']: | |
48 | return colors_lst.get(cl,'') | |
49 | return'' | |
50 | class color_dict(object): | |
51 | def __getattr__(self,a): | |
52 | return get_color(a) | |
53 | def __call__(self,a): | |
54 | return get_color(a) | |
55 | colors=color_dict() | |
56 | re_log=re.compile(r'(\w+): (.*)',re.M) | |
57 | class log_filter(logging.Filter): | |
58 | def __init__(self,name=''): | |
59 | logging.Filter.__init__(self,name) | |
60 | def filter(self,rec): | |
61 | rec.zone=rec.module | |
62 | if rec.levelno>=logging.INFO: | |
63 | return True | |
64 | m=re_log.match(rec.msg) | |
65 | if m: | |
66 | rec.zone=m.group(1) | |
67 | rec.msg=m.group(2) | |
68 | if zones: | |
69 | return getattr(rec,'zone','')in zones or'*'in zones | |
70 | elif not verbose>2: | |
71 | return False | |
72 | return True | |
73 | class log_handler(logging.StreamHandler): | |
74 | def emit(self,record): | |
75 | try: | |
76 | try: | |
77 | self.stream=record.stream | |
78 | except AttributeError: | |
79 | if record.levelno>=logging.WARNING: | |
80 | record.stream=self.stream=sys.stderr | |
81 | else: | |
82 | record.stream=self.stream=sys.stdout | |
83 | self.emit_override(record) | |
84 | self.flush() | |
85 | except(KeyboardInterrupt,SystemExit): | |
86 | raise | |
87 | except: | |
88 | self.handleError(record) | |
89 | def emit_override(self,record,**kw): | |
90 | self.terminator=getattr(record,'terminator','\n') | |
91 | stream=self.stream | |
92 | if unicode: | |
93 | msg=self.formatter.format(record) | |
94 | fs='%s'+self.terminator | |
95 | try: | |
96 | if(isinstance(msg,unicode)and getattr(stream,'encoding',None)): | |
97 | fs=fs.decode(stream.encoding) | |
98 | try: | |
99 | stream.write(fs%msg) | |
100 | except UnicodeEncodeError: | |
101 | stream.write((fs%msg).encode(stream.encoding)) | |
102 | else: | |
103 | stream.write(fs%msg) | |
104 | except UnicodeError: | |
105 | stream.write((fs%msg).encode('utf-8')) | |
106 | else: | |
107 | logging.StreamHandler.emit(self,record) | |
108 | class formatter(logging.Formatter): | |
109 | def __init__(self): | |
110 | logging.Formatter.__init__(self,LOG_FORMAT,HOUR_FORMAT) | |
111 | def format(self,rec): | |
112 | try: | |
113 | msg=rec.msg.decode('utf-8') | |
114 | except Exception: | |
115 | msg=rec.msg | |
116 | use=colors_lst['USE'] | |
117 | if(use==1 and rec.stream.isatty())or use==2: | |
118 | c1=getattr(rec,'c1',None) | |
119 | if c1 is None: | |
120 | c1='' | |
121 | if rec.levelno>=logging.ERROR: | |
122 | c1=colors.RED | |
123 | elif rec.levelno>=logging.WARNING: | |
124 | c1=colors.YELLOW | |
125 | elif rec.levelno>=logging.INFO: | |
126 | c1=colors.GREEN | |
127 | c2=getattr(rec,'c2',colors.NORMAL) | |
128 | msg='%s%s%s'%(c1,msg,c2) | |
129 | else: | |
130 | msg=re.sub(r'\r(?!\n)|\x1B\[(K|.*?(m|h|l))','',msg) | |
131 | if rec.levelno>=logging.INFO: | |
132 | if rec.args: | |
133 | try: | |
134 | return msg%rec.args | |
135 | except UnicodeDecodeError: | |
136 | return msg.encode('utf-8')%rec.args | |
137 | return msg | |
138 | rec.msg=msg | |
139 | rec.c1=colors.PINK | |
140 | rec.c2=colors.NORMAL | |
141 | return logging.Formatter.format(self,rec) | |
142 | log=None | |
143 | def debug(*k,**kw): | |
144 | if verbose: | |
145 | k=list(k) | |
146 | k[0]=k[0].replace('\n',' ') | |
147 | log.debug(*k,**kw) | |
148 | def error(*k,**kw): | |
149 | log.error(*k,**kw) | |
150 | if verbose>2: | |
151 | st=traceback.extract_stack() | |
152 | if st: | |
153 | st=st[:-1] | |
154 | buf=[] | |
155 | for filename,lineno,name,line in st: | |
156 | buf.append(' File %r, line %d, in %s'%(filename,lineno,name)) | |
157 | if line: | |
158 | buf.append(' %s'%line.strip()) | |
159 | if buf: | |
160 | log.error('\n'.join(buf)) | |
161 | def warn(*k,**kw): | |
162 | log.warning(*k,**kw) | |
163 | def info(*k,**kw): | |
164 | log.info(*k,**kw) | |
165 | def init_log(): | |
166 | global log | |
167 | log=logging.getLogger('waflib') | |
168 | log.handlers=[] | |
169 | log.filters=[] | |
170 | hdlr=log_handler() | |
171 | hdlr.setFormatter(formatter()) | |
172 | log.addHandler(hdlr) | |
173 | log.addFilter(log_filter()) | |
174 | log.setLevel(logging.DEBUG) | |
175 | def make_logger(path,name): | |
176 | logger=logging.getLogger(name) | |
177 | if sys.hexversion>0x3000000: | |
178 | encoding=sys.stdout.encoding | |
179 | else: | |
180 | encoding=None | |
181 | hdlr=logging.FileHandler(path,'w',encoding=encoding) | |
182 | formatter=logging.Formatter('%(message)s') | |
183 | hdlr.setFormatter(formatter) | |
184 | logger.addHandler(hdlr) | |
185 | logger.setLevel(logging.DEBUG) | |
186 | return logger | |
187 | def make_mem_logger(name,to_log,size=8192): | |
188 | from logging.handlers import MemoryHandler | |
189 | logger=logging.getLogger(name) | |
190 | hdlr=MemoryHandler(size,target=to_log) | |
191 | formatter=logging.Formatter('%(message)s') | |
192 | hdlr.setFormatter(formatter) | |
193 | logger.addHandler(hdlr) | |
194 | logger.memhandler=hdlr | |
195 | logger.setLevel(logging.DEBUG) | |
196 | return logger | |
197 | def free_logger(logger): | |
198 | try: | |
199 | for x in logger.handlers: | |
200 | x.close() | |
201 | logger.removeHandler(x) | |
202 | except Exception: | |
203 | pass | |
204 | def pprint(col,msg,label='',sep='\n'): | |
205 | info('%s%s%s %s',colors(col),msg,colors.NORMAL,label,extra={'terminator':sep}) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re,sys,shutil | |
5 | from waflib import Utils,Errors | |
6 | exclude_regs=''' | |
7 | **/*~ | |
8 | **/#*# | |
9 | **/.#* | |
10 | **/%*% | |
11 | **/._* | |
12 | **/*.swp | |
13 | **/CVS | |
14 | **/CVS/** | |
15 | **/.cvsignore | |
16 | **/SCCS | |
17 | **/SCCS/** | |
18 | **/vssver.scc | |
19 | **/.svn | |
20 | **/.svn/** | |
21 | **/BitKeeper | |
22 | **/.git | |
23 | **/.git/** | |
24 | **/.gitignore | |
25 | **/.bzr | |
26 | **/.bzrignore | |
27 | **/.bzr/** | |
28 | **/.hg | |
29 | **/.hg/** | |
30 | **/_MTN | |
31 | **/_MTN/** | |
32 | **/.arch-ids | |
33 | **/{arch} | |
34 | **/_darcs | |
35 | **/_darcs/** | |
36 | **/.intlcache | |
37 | **/.DS_Store''' | |
38 | def ant_matcher(s,ignorecase): | |
39 | reflags=re.I if ignorecase else 0 | |
40 | ret=[] | |
41 | for x in Utils.to_list(s): | |
42 | x=x.replace('\\','/').replace('//','/') | |
43 | if x.endswith('/'): | |
44 | x+='**' | |
45 | accu=[] | |
46 | for k in x.split('/'): | |
47 | if k=='**': | |
48 | accu.append(k) | |
49 | else: | |
50 | k=k.replace('.','[.]').replace('*','.*').replace('?','.').replace('+','\\+') | |
51 | k='^%s$'%k | |
52 | try: | |
53 | exp=re.compile(k,flags=reflags) | |
54 | except Exception as e: | |
55 | raise Errors.WafError('Invalid pattern: %s'%k,e) | |
56 | else: | |
57 | accu.append(exp) | |
58 | ret.append(accu) | |
59 | return ret | |
60 | def ant_sub_filter(name,nn): | |
61 | ret=[] | |
62 | for lst in nn: | |
63 | if not lst: | |
64 | pass | |
65 | elif lst[0]=='**': | |
66 | ret.append(lst) | |
67 | if len(lst)>1: | |
68 | if lst[1].match(name): | |
69 | ret.append(lst[2:]) | |
70 | else: | |
71 | ret.append([]) | |
72 | elif lst[0].match(name): | |
73 | ret.append(lst[1:]) | |
74 | return ret | |
75 | def ant_sub_matcher(name,pats): | |
76 | nacc=ant_sub_filter(name,pats[0]) | |
77 | nrej=ant_sub_filter(name,pats[1]) | |
78 | if[]in nrej: | |
79 | nacc=[] | |
80 | return[nacc,nrej] | |
81 | class Node(object): | |
82 | dict_class=dict | |
83 | __slots__=('name','parent','children','cache_abspath','cache_isdir') | |
84 | def __init__(self,name,parent): | |
85 | self.name=name | |
86 | self.parent=parent | |
87 | if parent: | |
88 | if name in parent.children: | |
89 | raise Errors.WafError('node %s exists in the parent files %r already'%(name,parent)) | |
90 | parent.children[name]=self | |
91 | def __setstate__(self,data): | |
92 | self.name=data[0] | |
93 | self.parent=data[1] | |
94 | if data[2]is not None: | |
95 | self.children=self.dict_class(data[2]) | |
96 | def __getstate__(self): | |
97 | return(self.name,self.parent,getattr(self,'children',None)) | |
98 | def __str__(self): | |
99 | return self.abspath() | |
100 | def __repr__(self): | |
101 | return self.abspath() | |
102 | def __copy__(self): | |
103 | raise Errors.WafError('nodes are not supposed to be copied') | |
104 | def read(self,flags='r',encoding='latin-1'): | |
105 | return Utils.readf(self.abspath(),flags,encoding) | |
106 | def write(self,data,flags='w',encoding='latin-1'): | |
107 | Utils.writef(self.abspath(),data,flags,encoding) | |
108 | def read_json(self,convert=True,encoding='utf-8'): | |
109 | import json | |
110 | object_pairs_hook=None | |
111 | if convert and sys.hexversion<0x3000000: | |
112 | try: | |
113 | _type=unicode | |
114 | except NameError: | |
115 | _type=str | |
116 | def convert(value): | |
117 | if isinstance(value,list): | |
118 | return[convert(element)for element in value] | |
119 | elif isinstance(value,_type): | |
120 | return str(value) | |
121 | else: | |
122 | return value | |
123 | def object_pairs(pairs): | |
124 | return dict((str(pair[0]),convert(pair[1]))for pair in pairs) | |
125 | object_pairs_hook=object_pairs | |
126 | return json.loads(self.read(encoding=encoding),object_pairs_hook=object_pairs_hook) | |
127 | def write_json(self,data,pretty=True): | |
128 | import json | |
129 | indent=2 | |
130 | separators=(',',': ') | |
131 | sort_keys=pretty | |
132 | newline=os.linesep | |
133 | if not pretty: | |
134 | indent=None | |
135 | separators=(',',':') | |
136 | newline='' | |
137 | output=json.dumps(data,indent=indent,separators=separators,sort_keys=sort_keys)+newline | |
138 | self.write(output,encoding='utf-8') | |
139 | def exists(self): | |
140 | return os.path.exists(self.abspath()) | |
141 | def isdir(self): | |
142 | return os.path.isdir(self.abspath()) | |
143 | def chmod(self,val): | |
144 | os.chmod(self.abspath(),val) | |
145 | def delete(self,evict=True): | |
146 | try: | |
147 | try: | |
148 | if os.path.isdir(self.abspath()): | |
149 | shutil.rmtree(self.abspath()) | |
150 | else: | |
151 | os.remove(self.abspath()) | |
152 | except OSError: | |
153 | if os.path.exists(self.abspath()): | |
154 | raise | |
155 | finally: | |
156 | if evict: | |
157 | self.evict() | |
158 | def evict(self): | |
159 | del self.parent.children[self.name] | |
160 | def suffix(self): | |
161 | k=max(0,self.name.rfind('.')) | |
162 | return self.name[k:] | |
163 | def height(self): | |
164 | d=self | |
165 | val=-1 | |
166 | while d: | |
167 | d=d.parent | |
168 | val+=1 | |
169 | return val | |
170 | def listdir(self): | |
171 | lst=Utils.listdir(self.abspath()) | |
172 | lst.sort() | |
173 | return lst | |
174 | def mkdir(self): | |
175 | if self.isdir(): | |
176 | return | |
177 | try: | |
178 | self.parent.mkdir() | |
179 | except OSError: | |
180 | pass | |
181 | if self.name: | |
182 | try: | |
183 | os.makedirs(self.abspath()) | |
184 | except OSError: | |
185 | pass | |
186 | if not self.isdir(): | |
187 | raise Errors.WafError('Could not create the directory %r'%self) | |
188 | try: | |
189 | self.children | |
190 | except AttributeError: | |
191 | self.children=self.dict_class() | |
192 | def find_node(self,lst): | |
193 | if isinstance(lst,str): | |
194 | lst=[x for x in Utils.split_path(lst)if x and x!='.'] | |
195 | if lst and lst[0].startswith('\\\\')and not self.parent: | |
196 | node=self.ctx.root.make_node(lst[0]) | |
197 | node.cache_isdir=True | |
198 | return node.find_node(lst[1:]) | |
199 | cur=self | |
200 | for x in lst: | |
201 | if x=='..': | |
202 | cur=cur.parent or cur | |
203 | continue | |
204 | try: | |
205 | ch=cur.children | |
206 | except AttributeError: | |
207 | cur.children=self.dict_class() | |
208 | else: | |
209 | try: | |
210 | cur=ch[x] | |
211 | continue | |
212 | except KeyError: | |
213 | pass | |
214 | cur=self.__class__(x,cur) | |
215 | if not cur.exists(): | |
216 | cur.evict() | |
217 | return None | |
218 | if not cur.exists(): | |
219 | cur.evict() | |
220 | return None | |
221 | return cur | |
222 | def make_node(self,lst): | |
223 | if isinstance(lst,str): | |
224 | lst=[x for x in Utils.split_path(lst)if x and x!='.'] | |
225 | cur=self | |
226 | for x in lst: | |
227 | if x=='..': | |
228 | cur=cur.parent or cur | |
229 | continue | |
230 | try: | |
231 | cur=cur.children[x] | |
232 | except AttributeError: | |
233 | cur.children=self.dict_class() | |
234 | except KeyError: | |
235 | pass | |
236 | else: | |
237 | continue | |
238 | cur=self.__class__(x,cur) | |
239 | return cur | |
240 | def search_node(self,lst): | |
241 | if isinstance(lst,str): | |
242 | lst=[x for x in Utils.split_path(lst)if x and x!='.'] | |
243 | cur=self | |
244 | for x in lst: | |
245 | if x=='..': | |
246 | cur=cur.parent or cur | |
247 | else: | |
248 | try: | |
249 | cur=cur.children[x] | |
250 | except(AttributeError,KeyError): | |
251 | return None | |
252 | return cur | |
253 | def path_from(self,node): | |
254 | c1=self | |
255 | c2=node | |
256 | c1h=c1.height() | |
257 | c2h=c2.height() | |
258 | lst=[] | |
259 | up=0 | |
260 | while c1h>c2h: | |
261 | lst.append(c1.name) | |
262 | c1=c1.parent | |
263 | c1h-=1 | |
264 | while c2h>c1h: | |
265 | up+=1 | |
266 | c2=c2.parent | |
267 | c2h-=1 | |
268 | while not c1 is c2: | |
269 | lst.append(c1.name) | |
270 | up+=1 | |
271 | c1=c1.parent | |
272 | c2=c2.parent | |
273 | if c1.parent: | |
274 | lst.extend(['..']*up) | |
275 | lst.reverse() | |
276 | return os.sep.join(lst)or'.' | |
277 | else: | |
278 | return self.abspath() | |
279 | def abspath(self): | |
280 | try: | |
281 | return self.cache_abspath | |
282 | except AttributeError: | |
283 | pass | |
284 | if not self.parent: | |
285 | val=os.sep | |
286 | elif not self.parent.name: | |
287 | val=os.sep+self.name | |
288 | else: | |
289 | val=self.parent.abspath()+os.sep+self.name | |
290 | self.cache_abspath=val | |
291 | return val | |
292 | if Utils.is_win32: | |
293 | def abspath(self): | |
294 | try: | |
295 | return self.cache_abspath | |
296 | except AttributeError: | |
297 | pass | |
298 | if not self.parent: | |
299 | val='' | |
300 | elif not self.parent.name: | |
301 | val=self.name+os.sep | |
302 | else: | |
303 | val=self.parent.abspath().rstrip(os.sep)+os.sep+self.name | |
304 | self.cache_abspath=val | |
305 | return val | |
306 | def is_child_of(self,node): | |
307 | p=self | |
308 | diff=self.height()-node.height() | |
309 | while diff>0: | |
310 | diff-=1 | |
311 | p=p.parent | |
312 | return p is node | |
313 | def ant_iter(self,accept=None,maxdepth=25,pats=[],dir=False,src=True,remove=True,quiet=False): | |
314 | dircont=self.listdir() | |
315 | try: | |
316 | lst=set(self.children.keys()) | |
317 | except AttributeError: | |
318 | self.children=self.dict_class() | |
319 | else: | |
320 | if remove: | |
321 | for x in lst-set(dircont): | |
322 | self.children[x].evict() | |
323 | for name in dircont: | |
324 | npats=accept(name,pats) | |
325 | if npats and npats[0]: | |
326 | accepted=[]in npats[0] | |
327 | node=self.make_node([name]) | |
328 | isdir=node.isdir() | |
329 | if accepted: | |
330 | if isdir: | |
331 | if dir: | |
332 | yield node | |
333 | elif src: | |
334 | yield node | |
335 | if isdir: | |
336 | node.cache_isdir=True | |
337 | if maxdepth: | |
338 | for k in node.ant_iter(accept=accept,maxdepth=maxdepth-1,pats=npats,dir=dir,src=src,remove=remove,quiet=quiet): | |
339 | yield k | |
340 | def ant_glob(self,*k,**kw): | |
341 | src=kw.get('src',True) | |
342 | dir=kw.get('dir') | |
343 | excl=kw.get('excl',exclude_regs) | |
344 | incl=k and k[0]or kw.get('incl','**') | |
345 | remove=kw.get('remove',True) | |
346 | maxdepth=kw.get('maxdepth',25) | |
347 | ignorecase=kw.get('ignorecase',False) | |
348 | quiet=kw.get('quiet',False) | |
349 | pats=(ant_matcher(incl,ignorecase),ant_matcher(excl,ignorecase)) | |
350 | if kw.get('generator'): | |
351 | return Utils.lazy_generator(self.ant_iter,(ant_sub_matcher,maxdepth,pats,dir,src,remove,quiet)) | |
352 | it=self.ant_iter(ant_sub_matcher,maxdepth,pats,dir,src,remove,quiet) | |
353 | if kw.get('flat'): | |
354 | return' '.join(x.path_from(self)for x in it) | |
355 | return list(it) | |
356 | def is_src(self): | |
357 | cur=self | |
358 | x=self.ctx.srcnode | |
359 | y=self.ctx.bldnode | |
360 | while cur.parent: | |
361 | if cur is y: | |
362 | return False | |
363 | if cur is x: | |
364 | return True | |
365 | cur=cur.parent | |
366 | return False | |
367 | def is_bld(self): | |
368 | cur=self | |
369 | y=self.ctx.bldnode | |
370 | while cur.parent: | |
371 | if cur is y: | |
372 | return True | |
373 | cur=cur.parent | |
374 | return False | |
375 | def get_src(self): | |
376 | cur=self | |
377 | x=self.ctx.srcnode | |
378 | y=self.ctx.bldnode | |
379 | lst=[] | |
380 | while cur.parent: | |
381 | if cur is y: | |
382 | lst.reverse() | |
383 | return x.make_node(lst) | |
384 | if cur is x: | |
385 | return self | |
386 | lst.append(cur.name) | |
387 | cur=cur.parent | |
388 | return self | |
389 | def get_bld(self): | |
390 | cur=self | |
391 | x=self.ctx.srcnode | |
392 | y=self.ctx.bldnode | |
393 | lst=[] | |
394 | while cur.parent: | |
395 | if cur is y: | |
396 | return self | |
397 | if cur is x: | |
398 | lst.reverse() | |
399 | return self.ctx.bldnode.make_node(lst) | |
400 | lst.append(cur.name) | |
401 | cur=cur.parent | |
402 | lst.reverse() | |
403 | if lst and Utils.is_win32 and len(lst[0])==2 and lst[0].endswith(':'): | |
404 | lst[0]=lst[0][0] | |
405 | return self.ctx.bldnode.make_node(['__root__']+lst) | |
406 | def find_resource(self,lst): | |
407 | if isinstance(lst,str): | |
408 | lst=[x for x in Utils.split_path(lst)if x and x!='.'] | |
409 | node=self.get_bld().search_node(lst) | |
410 | if not node: | |
411 | node=self.get_src().find_node(lst) | |
412 | if node and node.isdir(): | |
413 | return None | |
414 | return node | |
415 | def find_or_declare(self,lst): | |
416 | if isinstance(lst,str)and os.path.isabs(lst): | |
417 | node=self.ctx.root.make_node(lst) | |
418 | else: | |
419 | node=self.get_bld().make_node(lst) | |
420 | node.parent.mkdir() | |
421 | return node | |
422 | def find_dir(self,lst): | |
423 | if isinstance(lst,str): | |
424 | lst=[x for x in Utils.split_path(lst)if x and x!='.'] | |
425 | node=self.find_node(lst) | |
426 | if node and not node.isdir(): | |
427 | return None | |
428 | return node | |
429 | def change_ext(self,ext,ext_in=None): | |
430 | name=self.name | |
431 | if ext_in is None: | |
432 | k=name.rfind('.') | |
433 | if k>=0: | |
434 | name=name[:k]+ext | |
435 | else: | |
436 | name=name+ext | |
437 | else: | |
438 | name=name[:-len(ext_in)]+ext | |
439 | return self.parent.find_or_declare([name]) | |
440 | def bldpath(self): | |
441 | return self.path_from(self.ctx.bldnode) | |
442 | def srcpath(self): | |
443 | return self.path_from(self.ctx.srcnode) | |
444 | def relpath(self): | |
445 | cur=self | |
446 | x=self.ctx.bldnode | |
447 | while cur.parent: | |
448 | if cur is x: | |
449 | return self.bldpath() | |
450 | cur=cur.parent | |
451 | return self.srcpath() | |
452 | def bld_dir(self): | |
453 | return self.parent.bldpath() | |
454 | def h_file(self): | |
455 | return Utils.h_file(self.abspath()) | |
456 | def get_bld_sig(self): | |
457 | try: | |
458 | cache=self.ctx.cache_sig | |
459 | except AttributeError: | |
460 | cache=self.ctx.cache_sig={} | |
461 | try: | |
462 | ret=cache[self] | |
463 | except KeyError: | |
464 | p=self.abspath() | |
465 | try: | |
466 | ret=cache[self]=self.h_file() | |
467 | except EnvironmentError: | |
468 | if self.isdir(): | |
469 | st=os.stat(p) | |
470 | ret=cache[self]=Utils.h_list([p,st.st_ino,st.st_mode]) | |
471 | return ret | |
472 | raise | |
473 | return ret | |
474 | pickle_lock=Utils.threading.Lock() | |
475 | class Nod3(Node): | |
476 | pass |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,tempfile,optparse,sys,re | |
5 | from waflib import Logs,Utils,Context,Errors | |
6 | options=optparse.Values() | |
7 | commands=[] | |
8 | envvars=[] | |
9 | lockfile=os.environ.get('WAFLOCK','.lock-waf_%s_build'%sys.platform) | |
10 | class opt_parser(optparse.OptionParser): | |
11 | def __init__(self,ctx,allow_unknown=False): | |
12 | optparse.OptionParser.__init__(self,conflict_handler='resolve',add_help_option=False,version='%s %s (%s)'%(Context.WAFNAME,Context.WAFVERSION,Context.WAFREVISION)) | |
13 | self.formatter.width=Logs.get_term_cols() | |
14 | self.ctx=ctx | |
15 | self.allow_unknown=allow_unknown | |
16 | def _process_args(self,largs,rargs,values): | |
17 | while rargs: | |
18 | try: | |
19 | optparse.OptionParser._process_args(self,largs,rargs,values) | |
20 | except(optparse.BadOptionError,optparse.AmbiguousOptionError)as e: | |
21 | if self.allow_unknown: | |
22 | largs.append(e.opt_str) | |
23 | else: | |
24 | self.error(str(e)) | |
25 | def print_usage(self,file=None): | |
26 | return self.print_help(file) | |
27 | def get_usage(self): | |
28 | cmds_str={} | |
29 | for cls in Context.classes: | |
30 | if not cls.cmd or cls.cmd=='options'or cls.cmd.startswith('_'): | |
31 | continue | |
32 | s=cls.__doc__ or'' | |
33 | cmds_str[cls.cmd]=s | |
34 | if Context.g_module: | |
35 | for(k,v)in Context.g_module.__dict__.items(): | |
36 | if k in('options','init','shutdown'): | |
37 | continue | |
38 | if type(v)is type(Context.create_context): | |
39 | if v.__doc__ and not k.startswith('_'): | |
40 | cmds_str[k]=v.__doc__ | |
41 | just=0 | |
42 | for k in cmds_str: | |
43 | just=max(just,len(k)) | |
44 | lst=[' %s: %s'%(k.ljust(just),v)for(k,v)in cmds_str.items()] | |
45 | lst.sort() | |
46 | ret='\n'.join(lst) | |
47 | return'''%s [commands] [options] | |
48 | ||
49 | Main commands (example: ./%s build -j4) | |
50 | %s | |
51 | '''%(Context.WAFNAME,Context.WAFNAME,ret) | |
52 | class OptionsContext(Context.Context): | |
53 | cmd='options' | |
54 | fun='options' | |
55 | def __init__(self,**kw): | |
56 | super(OptionsContext,self).__init__(**kw) | |
57 | self.parser=opt_parser(self) | |
58 | self.option_groups={} | |
59 | jobs=self.jobs() | |
60 | p=self.add_option | |
61 | color=os.environ.get('NOCOLOR','')and'no'or'auto' | |
62 | if os.environ.get('CLICOLOR','')=='0': | |
63 | color='no' | |
64 | elif os.environ.get('CLICOLOR_FORCE','')=='1': | |
65 | color='yes' | |
66 | p('-c','--color',dest='colors',default=color,action='store',help='whether to use colors (yes/no/auto) [default: auto]',choices=('yes','no','auto')) | |
67 | p('-j','--jobs',dest='jobs',default=jobs,type='int',help='amount of parallel jobs (%r)'%jobs) | |
68 | p('-k','--keep',dest='keep',default=0,action='count',help='continue despite errors (-kk to try harder)') | |
69 | p('-v','--verbose',dest='verbose',default=0,action='count',help='verbosity level -v -vv or -vvv [default: 0]') | |
70 | p('--zones',dest='zones',default='',action='store',help='debugging zones (task_gen, deps, tasks, etc)') | |
71 | p('--profile',dest='profile',default=0,action='store_true',help=optparse.SUPPRESS_HELP) | |
72 | p('--pdb',dest='pdb',default=0,action='store_true',help=optparse.SUPPRESS_HELP) | |
73 | p('-h','--help',dest='whelp',default=0,action='store_true',help="show this help message and exit") | |
74 | gr=self.add_option_group('Configuration options') | |
75 | self.option_groups['configure options']=gr | |
76 | gr.add_option('-o','--out',action='store',default='',help='build dir for the project',dest='out') | |
77 | gr.add_option('-t','--top',action='store',default='',help='src dir for the project',dest='top') | |
78 | gr.add_option('--no-lock-in-run',action='store_true',default='',help=optparse.SUPPRESS_HELP,dest='no_lock_in_run') | |
79 | gr.add_option('--no-lock-in-out',action='store_true',default='',help=optparse.SUPPRESS_HELP,dest='no_lock_in_out') | |
80 | gr.add_option('--no-lock-in-top',action='store_true',default='',help=optparse.SUPPRESS_HELP,dest='no_lock_in_top') | |
81 | default_prefix=getattr(Context.g_module,'default_prefix',os.environ.get('PREFIX')) | |
82 | if not default_prefix: | |
83 | if Utils.unversioned_sys_platform()=='win32': | |
84 | d=tempfile.gettempdir() | |
85 | default_prefix=d[0].upper()+d[1:] | |
86 | else: | |
87 | default_prefix='/usr/local/' | |
88 | gr.add_option('--prefix',dest='prefix',default=default_prefix,help='installation prefix [default: %r]'%default_prefix) | |
89 | gr.add_option('--bindir',dest='bindir',help='bindir') | |
90 | gr.add_option('--libdir',dest='libdir',help='libdir') | |
91 | gr=self.add_option_group('Build and installation options') | |
92 | self.option_groups['build and install options']=gr | |
93 | gr.add_option('-p','--progress',dest='progress_bar',default=0,action='count',help='-p: progress bar; -pp: ide output') | |
94 | gr.add_option('--targets',dest='targets',default='',action='store',help='task generators, e.g. "target1,target2"') | |
95 | gr=self.add_option_group('Step options') | |
96 | self.option_groups['step options']=gr | |
97 | gr.add_option('--files',dest='files',default='',action='store',help='files to process, by regexp, e.g. "*/main.c,*/test/main.o"') | |
98 | default_destdir=os.environ.get('DESTDIR','') | |
99 | gr=self.add_option_group('Installation and uninstallation options') | |
100 | self.option_groups['install/uninstall options']=gr | |
101 | gr.add_option('--destdir',help='installation root [default: %r]'%default_destdir,default=default_destdir,dest='destdir') | |
102 | gr.add_option('-f','--force',dest='force',default=False,action='store_true',help='force file installation') | |
103 | gr.add_option('--distcheck-args',metavar='ARGS',help='arguments to pass to distcheck',default=None,action='store') | |
104 | def jobs(self): | |
105 | count=int(os.environ.get('JOBS',0)) | |
106 | if count<1: | |
107 | if'NUMBER_OF_PROCESSORS'in os.environ: | |
108 | count=int(os.environ.get('NUMBER_OF_PROCESSORS',1)) | |
109 | else: | |
110 | if hasattr(os,'sysconf_names'): | |
111 | if'SC_NPROCESSORS_ONLN'in os.sysconf_names: | |
112 | count=int(os.sysconf('SC_NPROCESSORS_ONLN')) | |
113 | elif'SC_NPROCESSORS_CONF'in os.sysconf_names: | |
114 | count=int(os.sysconf('SC_NPROCESSORS_CONF')) | |
115 | if not count and os.name not in('nt','java'): | |
116 | try: | |
117 | tmp=self.cmd_and_log(['sysctl','-n','hw.ncpu'],quiet=0) | |
118 | except Errors.WafError: | |
119 | pass | |
120 | else: | |
121 | if re.match('^[0-9]+$',tmp): | |
122 | count=int(tmp) | |
123 | if count<1: | |
124 | count=1 | |
125 | elif count>1024: | |
126 | count=1024 | |
127 | return count | |
128 | def add_option(self,*k,**kw): | |
129 | return self.parser.add_option(*k,**kw) | |
130 | def add_option_group(self,*k,**kw): | |
131 | try: | |
132 | gr=self.option_groups[k[0]] | |
133 | except KeyError: | |
134 | gr=self.parser.add_option_group(*k,**kw) | |
135 | self.option_groups[k[0]]=gr | |
136 | return gr | |
137 | def get_option_group(self,opt_str): | |
138 | try: | |
139 | return self.option_groups[opt_str] | |
140 | except KeyError: | |
141 | for group in self.parser.option_groups: | |
142 | if group.title==opt_str: | |
143 | return group | |
144 | return None | |
145 | def sanitize_path(self,path,cwd=None): | |
146 | if not cwd: | |
147 | cwd=Context.launch_dir | |
148 | p=os.path.expanduser(path) | |
149 | p=os.path.join(cwd,p) | |
150 | p=os.path.normpath(p) | |
151 | p=os.path.abspath(p) | |
152 | return p | |
153 | def parse_cmd_args(self,_args=None,cwd=None,allow_unknown=False): | |
154 | self.parser.allow_unknown=allow_unknown | |
155 | (options,leftover_args)=self.parser.parse_args(args=_args) | |
156 | envvars=[] | |
157 | commands=[] | |
158 | for arg in leftover_args: | |
159 | if'='in arg: | |
160 | envvars.append(arg) | |
161 | elif arg!='options': | |
162 | commands.append(arg) | |
163 | if options.jobs<1: | |
164 | options.jobs=1 | |
165 | for name in'top out destdir prefix bindir libdir'.split(): | |
166 | if getattr(options,name,None): | |
167 | path=self.sanitize_path(getattr(options,name),cwd) | |
168 | setattr(options,name,path) | |
169 | return options,commands,envvars | |
170 | def init_module_vars(self,arg_options,arg_commands,arg_envvars): | |
171 | options.__dict__.clear() | |
172 | del commands[:] | |
173 | del envvars[:] | |
174 | options.__dict__.update(arg_options.__dict__) | |
175 | commands.extend(arg_commands) | |
176 | envvars.extend(arg_envvars) | |
177 | for var in envvars: | |
178 | (name,value)=var.split('=',1) | |
179 | os.environ[name.strip()]=value | |
180 | def init_logs(self,options,commands,envvars): | |
181 | Logs.verbose=options.verbose | |
182 | if options.verbose>=1: | |
183 | self.load('errcheck') | |
184 | colors={'yes':2,'auto':1,'no':0}[options.colors] | |
185 | Logs.enable_colors(colors) | |
186 | if options.zones: | |
187 | Logs.zones=options.zones.split(',') | |
188 | if not Logs.verbose: | |
189 | Logs.verbose=1 | |
190 | elif Logs.verbose>0: | |
191 | Logs.zones=['runner'] | |
192 | if Logs.verbose>2: | |
193 | Logs.zones=['*'] | |
194 | def parse_args(self,_args=None): | |
195 | options,commands,envvars=self.parse_cmd_args() | |
196 | self.init_logs(options,commands,envvars) | |
197 | self.init_module_vars(options,commands,envvars) | |
198 | def execute(self): | |
199 | super(OptionsContext,self).execute() | |
200 | self.parse_args() | |
201 | Utils.alloc_process_pool(options.jobs) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import heapq,traceback | |
5 | try: | |
6 | from queue import Queue,PriorityQueue | |
7 | except ImportError: | |
8 | from Queue import Queue | |
9 | try: | |
10 | from Queue import PriorityQueue | |
11 | except ImportError: | |
12 | class PriorityQueue(Queue): | |
13 | def _init(self,maxsize): | |
14 | self.maxsize=maxsize | |
15 | self.queue=[] | |
16 | def _put(self,item): | |
17 | heapq.heappush(self.queue,item) | |
18 | def _get(self): | |
19 | return heapq.heappop(self.queue) | |
20 | from waflib import Utils,Task,Errors,Logs | |
21 | GAP=5 | |
22 | class PriorityTasks(object): | |
23 | def __init__(self): | |
24 | self.lst=[] | |
25 | def __len__(self): | |
26 | return len(self.lst) | |
27 | def __iter__(self): | |
28 | return iter(self.lst) | |
29 | def __str__(self): | |
30 | return'PriorityTasks: [%s]'%'\n '.join(str(x)for x in self.lst) | |
31 | def clear(self): | |
32 | self.lst=[] | |
33 | def append(self,task): | |
34 | heapq.heappush(self.lst,task) | |
35 | def appendleft(self,task): | |
36 | heapq.heappush(self.lst,task) | |
37 | def pop(self): | |
38 | return heapq.heappop(self.lst) | |
39 | def extend(self,lst): | |
40 | if self.lst: | |
41 | for x in lst: | |
42 | self.append(x) | |
43 | else: | |
44 | if isinstance(lst,list): | |
45 | self.lst=lst | |
46 | heapq.heapify(lst) | |
47 | else: | |
48 | self.lst=lst.lst | |
49 | class Consumer(Utils.threading.Thread): | |
50 | def __init__(self,spawner,task): | |
51 | Utils.threading.Thread.__init__(self) | |
52 | self.task=task | |
53 | self.spawner=spawner | |
54 | self.setDaemon(1) | |
55 | self.start() | |
56 | def run(self): | |
57 | try: | |
58 | if not self.spawner.master.stop: | |
59 | self.spawner.master.process_task(self.task) | |
60 | finally: | |
61 | self.spawner.sem.release() | |
62 | self.spawner.master.out.put(self.task) | |
63 | self.task=None | |
64 | self.spawner=None | |
65 | class Spawner(Utils.threading.Thread): | |
66 | def __init__(self,master): | |
67 | Utils.threading.Thread.__init__(self) | |
68 | self.master=master | |
69 | self.sem=Utils.threading.Semaphore(master.numjobs) | |
70 | self.setDaemon(1) | |
71 | self.start() | |
72 | def run(self): | |
73 | try: | |
74 | self.loop() | |
75 | except Exception: | |
76 | pass | |
77 | def loop(self): | |
78 | master=self.master | |
79 | while 1: | |
80 | task=master.ready.get() | |
81 | self.sem.acquire() | |
82 | if not master.stop: | |
83 | task.log_display(task.generator.bld) | |
84 | Consumer(self,task) | |
85 | class Parallel(object): | |
86 | def __init__(self,bld,j=2): | |
87 | self.numjobs=j | |
88 | self.bld=bld | |
89 | self.outstanding=PriorityTasks() | |
90 | self.postponed=PriorityTasks() | |
91 | self.incomplete=set() | |
92 | self.ready=PriorityQueue(0) | |
93 | self.out=Queue(0) | |
94 | self.count=0 | |
95 | self.processed=0 | |
96 | self.stop=False | |
97 | self.error=[] | |
98 | self.biter=None | |
99 | self.dirty=False | |
100 | self.revdeps=Utils.defaultdict(set) | |
101 | self.spawner=None | |
102 | if self.numjobs>1: | |
103 | self.spawner=Spawner(self) | |
104 | def get_next_task(self): | |
105 | if not self.outstanding: | |
106 | return None | |
107 | return self.outstanding.pop() | |
108 | def postpone(self,tsk): | |
109 | self.postponed.append(tsk) | |
110 | def refill_task_list(self): | |
111 | while self.count>self.numjobs*GAP: | |
112 | self.get_out() | |
113 | while not self.outstanding: | |
114 | if self.count: | |
115 | self.get_out() | |
116 | if self.outstanding: | |
117 | break | |
118 | elif self.postponed: | |
119 | try: | |
120 | cond=self.deadlock==self.processed | |
121 | except AttributeError: | |
122 | pass | |
123 | else: | |
124 | if cond: | |
125 | lst=[] | |
126 | for tsk in self.postponed: | |
127 | deps=[id(x)for x in tsk.run_after if not x.hasrun] | |
128 | lst.append('%s\t-> %r'%(repr(tsk),deps)) | |
129 | if not deps: | |
130 | lst.append('\n task %r dependencies are done, check its *runnable_status*?'%id(tsk)) | |
131 | raise Errors.WafError('Deadlock detected: check the task build order%s'%''.join(lst)) | |
132 | self.deadlock=self.processed | |
133 | if self.postponed: | |
134 | self.outstanding.extend(self.postponed) | |
135 | self.postponed.clear() | |
136 | elif not self.count: | |
137 | if self.incomplete: | |
138 | for x in self.incomplete: | |
139 | for k in x.run_after: | |
140 | if not k.hasrun: | |
141 | break | |
142 | else: | |
143 | self.incomplete.remove(x) | |
144 | self.outstanding.append(x) | |
145 | break | |
146 | else: | |
147 | if self.stop or self.error: | |
148 | break | |
149 | raise Errors.WafError('Broken revdeps detected on %r'%self.incomplete) | |
150 | else: | |
151 | tasks=next(self.biter) | |
152 | ready,waiting=self.prio_and_split(tasks) | |
153 | self.outstanding.extend(ready) | |
154 | self.incomplete.update(waiting) | |
155 | self.total=self.bld.total() | |
156 | break | |
157 | def add_more_tasks(self,tsk): | |
158 | if getattr(tsk,'more_tasks',None): | |
159 | more=set(tsk.more_tasks) | |
160 | groups_done=set() | |
161 | def iteri(a,b): | |
162 | for x in a: | |
163 | yield x | |
164 | for x in b: | |
165 | yield x | |
166 | for x in iteri(self.outstanding,self.incomplete): | |
167 | for k in x.run_after: | |
168 | if isinstance(k,Task.TaskGroup): | |
169 | if k not in groups_done: | |
170 | groups_done.add(k) | |
171 | for j in k.prev&more: | |
172 | self.revdeps[j].add(k) | |
173 | elif k in more: | |
174 | self.revdeps[k].add(x) | |
175 | ready,waiting=self.prio_and_split(tsk.more_tasks) | |
176 | self.outstanding.extend(ready) | |
177 | self.incomplete.update(waiting) | |
178 | self.total+=len(tsk.more_tasks) | |
179 | def mark_finished(self,tsk): | |
180 | def try_unfreeze(x): | |
181 | if x in self.incomplete: | |
182 | for k in x.run_after: | |
183 | if not k.hasrun: | |
184 | break | |
185 | else: | |
186 | self.incomplete.remove(x) | |
187 | self.outstanding.append(x) | |
188 | if tsk in self.revdeps: | |
189 | for x in self.revdeps[tsk]: | |
190 | if isinstance(x,Task.TaskGroup): | |
191 | x.prev.remove(tsk) | |
192 | if not x.prev: | |
193 | for k in x.next: | |
194 | k.run_after.remove(x) | |
195 | try_unfreeze(k) | |
196 | x.next=[] | |
197 | else: | |
198 | try_unfreeze(x) | |
199 | del self.revdeps[tsk] | |
200 | if hasattr(tsk,'semaphore'): | |
201 | sem=tsk.semaphore | |
202 | try: | |
203 | sem.release(tsk) | |
204 | except KeyError: | |
205 | pass | |
206 | else: | |
207 | while sem.waiting and not sem.is_locked(): | |
208 | x=sem.waiting.pop() | |
209 | self._add_task(x) | |
210 | def get_out(self): | |
211 | tsk=self.out.get() | |
212 | if not self.stop: | |
213 | self.add_more_tasks(tsk) | |
214 | self.mark_finished(tsk) | |
215 | self.count-=1 | |
216 | self.dirty=True | |
217 | return tsk | |
218 | def add_task(self,tsk): | |
219 | self.ready.put(tsk) | |
220 | def _add_task(self,tsk): | |
221 | if hasattr(tsk,'semaphore'): | |
222 | sem=tsk.semaphore | |
223 | try: | |
224 | sem.acquire(tsk) | |
225 | except IndexError: | |
226 | sem.waiting.add(tsk) | |
227 | return | |
228 | self.count+=1 | |
229 | self.processed+=1 | |
230 | if self.numjobs==1: | |
231 | tsk.log_display(tsk.generator.bld) | |
232 | try: | |
233 | self.process_task(tsk) | |
234 | finally: | |
235 | self.out.put(tsk) | |
236 | else: | |
237 | self.add_task(tsk) | |
238 | def process_task(self,tsk): | |
239 | tsk.process() | |
240 | if tsk.hasrun!=Task.SUCCESS: | |
241 | self.error_handler(tsk) | |
242 | def skip(self,tsk): | |
243 | tsk.hasrun=Task.SKIPPED | |
244 | self.mark_finished(tsk) | |
245 | def cancel(self,tsk): | |
246 | tsk.hasrun=Task.CANCELED | |
247 | self.mark_finished(tsk) | |
248 | def error_handler(self,tsk): | |
249 | if not self.bld.keep: | |
250 | self.stop=True | |
251 | self.error.append(tsk) | |
252 | def task_status(self,tsk): | |
253 | try: | |
254 | return tsk.runnable_status() | |
255 | except Exception: | |
256 | self.processed+=1 | |
257 | tsk.err_msg=traceback.format_exc() | |
258 | if not self.stop and self.bld.keep: | |
259 | self.skip(tsk) | |
260 | if self.bld.keep==1: | |
261 | if Logs.verbose>1 or not self.error: | |
262 | self.error.append(tsk) | |
263 | self.stop=True | |
264 | else: | |
265 | if Logs.verbose>1: | |
266 | self.error.append(tsk) | |
267 | return Task.EXCEPTION | |
268 | tsk.hasrun=Task.EXCEPTION | |
269 | self.error_handler(tsk) | |
270 | return Task.EXCEPTION | |
271 | def start(self): | |
272 | self.total=self.bld.total() | |
273 | while not self.stop: | |
274 | self.refill_task_list() | |
275 | tsk=self.get_next_task() | |
276 | if not tsk: | |
277 | if self.count: | |
278 | continue | |
279 | else: | |
280 | break | |
281 | if tsk.hasrun: | |
282 | self.processed+=1 | |
283 | continue | |
284 | if self.stop: | |
285 | break | |
286 | st=self.task_status(tsk) | |
287 | if st==Task.RUN_ME: | |
288 | self._add_task(tsk) | |
289 | elif st==Task.ASK_LATER: | |
290 | self.postpone(tsk) | |
291 | elif st==Task.SKIP_ME: | |
292 | self.processed+=1 | |
293 | self.skip(tsk) | |
294 | self.add_more_tasks(tsk) | |
295 | elif st==Task.CANCEL_ME: | |
296 | if Logs.verbose>1: | |
297 | self.error.append(tsk) | |
298 | self.processed+=1 | |
299 | self.cancel(tsk) | |
300 | while self.error and self.count: | |
301 | self.get_out() | |
302 | self.ready.put(None) | |
303 | if not self.stop: | |
304 | assert not self.count | |
305 | assert not self.postponed | |
306 | assert not self.incomplete | |
307 | def prio_and_split(self,tasks): | |
308 | for x in tasks: | |
309 | x.visited=0 | |
310 | reverse=self.revdeps | |
311 | groups_done=set() | |
312 | for x in tasks: | |
313 | for k in x.run_after: | |
314 | if isinstance(k,Task.TaskGroup): | |
315 | if k not in groups_done: | |
316 | groups_done.add(k) | |
317 | for j in k.prev: | |
318 | reverse[j].add(k) | |
319 | else: | |
320 | reverse[k].add(x) | |
321 | def visit(n): | |
322 | if isinstance(n,Task.TaskGroup): | |
323 | return sum(visit(k)for k in n.next) | |
324 | if n.visited==0: | |
325 | n.visited=1 | |
326 | if n in reverse: | |
327 | rev=reverse[n] | |
328 | n.prio_order=n.tree_weight+len(rev)+sum(visit(k)for k in rev) | |
329 | else: | |
330 | n.prio_order=n.tree_weight | |
331 | n.visited=2 | |
332 | elif n.visited==1: | |
333 | raise Errors.WafError('Dependency cycle found!') | |
334 | return n.prio_order | |
335 | for x in tasks: | |
336 | if x.visited!=0: | |
337 | continue | |
338 | try: | |
339 | visit(x) | |
340 | except Errors.WafError: | |
341 | self.debug_cycles(tasks,reverse) | |
342 | ready=[] | |
343 | waiting=[] | |
344 | for x in tasks: | |
345 | for k in x.run_after: | |
346 | if not k.hasrun: | |
347 | waiting.append(x) | |
348 | break | |
349 | else: | |
350 | ready.append(x) | |
351 | return(ready,waiting) | |
352 | def debug_cycles(self,tasks,reverse): | |
353 | tmp={} | |
354 | for x in tasks: | |
355 | tmp[x]=0 | |
356 | def visit(n,acc): | |
357 | if isinstance(n,Task.TaskGroup): | |
358 | for k in n.next: | |
359 | visit(k,acc) | |
360 | return | |
361 | if tmp[n]==0: | |
362 | tmp[n]=1 | |
363 | for k in reverse.get(n,[]): | |
364 | visit(k,[n]+acc) | |
365 | tmp[n]=2 | |
366 | elif tmp[n]==1: | |
367 | lst=[] | |
368 | for tsk in acc: | |
369 | lst.append(repr(tsk)) | |
370 | if tsk is n: | |
371 | break | |
372 | raise Errors.WafError('Task dependency cycle in "run_after" constraints: %s'%''.join(lst)) | |
373 | for x in tasks: | |
374 | visit(x,[]) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from __future__ import with_statement | |
5 | import os,shlex,shutil,traceback,errno,sys,stat | |
6 | from waflib import Utils,Configure,Logs,Options,ConfigSet,Context,Errors,Build,Node | |
7 | build_dir_override=None | |
8 | no_climb_commands=['configure'] | |
9 | default_cmd="build" | |
10 | def waf_entry_point(current_directory,version,wafdir): | |
11 | Logs.init_log() | |
12 | if Context.WAFVERSION!=version: | |
13 | Logs.error('Waf script %r and library %r do not match (directory %r)',version,Context.WAFVERSION,wafdir) | |
14 | sys.exit(1) | |
15 | Context.waf_dir=wafdir | |
16 | Context.run_dir=Context.launch_dir=current_directory | |
17 | start_dir=current_directory | |
18 | no_climb=os.environ.get('NOCLIMB') | |
19 | if len(sys.argv)>1: | |
20 | potential_wscript=os.path.join(current_directory,sys.argv[1]) | |
21 | if os.path.basename(potential_wscript)==Context.WSCRIPT_FILE and os.path.isfile(potential_wscript): | |
22 | path=os.path.normpath(os.path.dirname(potential_wscript)) | |
23 | start_dir=os.path.abspath(path) | |
24 | no_climb=True | |
25 | sys.argv.pop(1) | |
26 | ctx=Context.create_context('options') | |
27 | (options,commands,env)=ctx.parse_cmd_args(allow_unknown=True) | |
28 | if options.top: | |
29 | start_dir=Context.run_dir=Context.top_dir=options.top | |
30 | no_climb=True | |
31 | if options.out: | |
32 | Context.out_dir=options.out | |
33 | if not no_climb: | |
34 | for k in no_climb_commands: | |
35 | for y in commands: | |
36 | if y.startswith(k): | |
37 | no_climb=True | |
38 | break | |
39 | cur=start_dir | |
40 | while cur: | |
41 | try: | |
42 | lst=os.listdir(cur) | |
43 | except OSError: | |
44 | lst=[] | |
45 | Logs.error('Directory %r is unreadable!',cur) | |
46 | if Options.lockfile in lst: | |
47 | env=ConfigSet.ConfigSet() | |
48 | try: | |
49 | env.load(os.path.join(cur,Options.lockfile)) | |
50 | ino=os.stat(cur)[stat.ST_INO] | |
51 | except EnvironmentError: | |
52 | pass | |
53 | else: | |
54 | for x in(env.run_dir,env.top_dir,env.out_dir): | |
55 | if not x: | |
56 | continue | |
57 | if Utils.is_win32: | |
58 | if cur==x: | |
59 | load=True | |
60 | break | |
61 | else: | |
62 | try: | |
63 | ino2=os.stat(x)[stat.ST_INO] | |
64 | except OSError: | |
65 | pass | |
66 | else: | |
67 | if ino==ino2: | |
68 | load=True | |
69 | break | |
70 | else: | |
71 | Logs.warn('invalid lock file in %s',cur) | |
72 | load=False | |
73 | if load: | |
74 | Context.run_dir=env.run_dir | |
75 | Context.top_dir=env.top_dir | |
76 | Context.out_dir=env.out_dir | |
77 | break | |
78 | if not Context.run_dir: | |
79 | if Context.WSCRIPT_FILE in lst: | |
80 | Context.run_dir=cur | |
81 | next=os.path.dirname(cur) | |
82 | if next==cur: | |
83 | break | |
84 | cur=next | |
85 | if no_climb: | |
86 | break | |
87 | wscript=os.path.normpath(os.path.join(Context.run_dir,Context.WSCRIPT_FILE)) | |
88 | if not os.path.exists(wscript): | |
89 | if options.whelp: | |
90 | Logs.warn('These are the generic options (no wscript/project found)') | |
91 | ctx.parser.print_help() | |
92 | sys.exit(0) | |
93 | Logs.error('Waf: Run from a folder containing a %r file (or try -h for the generic options)',Context.WSCRIPT_FILE) | |
94 | sys.exit(1) | |
95 | try: | |
96 | os.chdir(Context.run_dir) | |
97 | except OSError: | |
98 | Logs.error('Waf: The folder %r is unreadable',Context.run_dir) | |
99 | sys.exit(1) | |
100 | try: | |
101 | set_main_module(wscript) | |
102 | except Errors.WafError as e: | |
103 | Logs.pprint('RED',e.verbose_msg) | |
104 | Logs.error(str(e)) | |
105 | sys.exit(1) | |
106 | except Exception as e: | |
107 | Logs.error('Waf: The wscript in %r is unreadable',Context.run_dir) | |
108 | traceback.print_exc(file=sys.stdout) | |
109 | sys.exit(2) | |
110 | if options.profile: | |
111 | import cProfile,pstats | |
112 | cProfile.runctx('from waflib import Scripting; Scripting.run_commands()',{},{},'profi.txt') | |
113 | p=pstats.Stats('profi.txt') | |
114 | p.sort_stats('time').print_stats(75) | |
115 | else: | |
116 | try: | |
117 | try: | |
118 | run_commands() | |
119 | except: | |
120 | if options.pdb: | |
121 | import pdb | |
122 | type,value,tb=sys.exc_info() | |
123 | traceback.print_exc() | |
124 | pdb.post_mortem(tb) | |
125 | else: | |
126 | raise | |
127 | except Errors.WafError as e: | |
128 | if Logs.verbose>1: | |
129 | Logs.pprint('RED',e.verbose_msg) | |
130 | Logs.error(e.msg) | |
131 | sys.exit(1) | |
132 | except SystemExit: | |
133 | raise | |
134 | except Exception as e: | |
135 | traceback.print_exc(file=sys.stdout) | |
136 | sys.exit(2) | |
137 | except KeyboardInterrupt: | |
138 | Logs.pprint('RED','Interrupted') | |
139 | sys.exit(68) | |
140 | def set_main_module(file_path): | |
141 | Context.g_module=Context.load_module(file_path) | |
142 | Context.g_module.root_path=file_path | |
143 | def set_def(obj): | |
144 | name=obj.__name__ | |
145 | if not name in Context.g_module.__dict__: | |
146 | setattr(Context.g_module,name,obj) | |
147 | for k in(dist,distclean,distcheck): | |
148 | set_def(k) | |
149 | if not'init'in Context.g_module.__dict__: | |
150 | Context.g_module.init=Utils.nada | |
151 | if not'shutdown'in Context.g_module.__dict__: | |
152 | Context.g_module.shutdown=Utils.nada | |
153 | if not'options'in Context.g_module.__dict__: | |
154 | Context.g_module.options=Utils.nada | |
155 | def parse_options(): | |
156 | ctx=Context.create_context('options') | |
157 | ctx.execute() | |
158 | if not Options.commands: | |
159 | if isinstance(default_cmd,list): | |
160 | Options.commands.extend(default_cmd) | |
161 | else: | |
162 | Options.commands.append(default_cmd) | |
163 | if Options.options.whelp: | |
164 | ctx.parser.print_help() | |
165 | sys.exit(0) | |
166 | def run_command(cmd_name): | |
167 | ctx=Context.create_context(cmd_name) | |
168 | ctx.log_timer=Utils.Timer() | |
169 | ctx.options=Options.options | |
170 | ctx.cmd=cmd_name | |
171 | try: | |
172 | ctx.execute() | |
173 | finally: | |
174 | ctx.finalize() | |
175 | return ctx | |
176 | def run_commands(): | |
177 | parse_options() | |
178 | run_command('init') | |
179 | while Options.commands: | |
180 | cmd_name=Options.commands.pop(0) | |
181 | ctx=run_command(cmd_name) | |
182 | Logs.info('%r finished successfully (%s)',cmd_name,ctx.log_timer) | |
183 | run_command('shutdown') | |
184 | def distclean_dir(dirname): | |
185 | for(root,dirs,files)in os.walk(dirname): | |
186 | for f in files: | |
187 | if f.endswith(('.o','.moc','.exe')): | |
188 | fname=os.path.join(root,f) | |
189 | try: | |
190 | os.remove(fname) | |
191 | except OSError: | |
192 | Logs.warn('Could not remove %r',fname) | |
193 | for x in(Context.DBFILE,'config.log'): | |
194 | try: | |
195 | os.remove(x) | |
196 | except OSError: | |
197 | pass | |
198 | try: | |
199 | shutil.rmtree(Build.CACHE_DIR) | |
200 | except OSError: | |
201 | pass | |
202 | def distclean(ctx): | |
203 | '''removes build folders and data''' | |
204 | def remove_and_log(k,fun): | |
205 | try: | |
206 | fun(k) | |
207 | except EnvironmentError as e: | |
208 | if e.errno!=errno.ENOENT: | |
209 | Logs.warn('Could not remove %r',k) | |
210 | if not Options.commands: | |
211 | for k in os.listdir('.'): | |
212 | for x in'.waf-2 waf-2 .waf3-2 waf3-2'.split(): | |
213 | if k.startswith(x): | |
214 | remove_and_log(k,shutil.rmtree) | |
215 | cur='.' | |
216 | if ctx.options.no_lock_in_top: | |
217 | cur=ctx.options.out | |
218 | try: | |
219 | lst=os.listdir(cur) | |
220 | except OSError: | |
221 | Logs.warn('Could not read %r',cur) | |
222 | return | |
223 | if Options.lockfile in lst: | |
224 | f=os.path.join(cur,Options.lockfile) | |
225 | try: | |
226 | env=ConfigSet.ConfigSet(f) | |
227 | except EnvironmentError: | |
228 | Logs.warn('Could not read %r',f) | |
229 | return | |
230 | if not env.out_dir or not env.top_dir: | |
231 | Logs.warn('Invalid lock file %r',f) | |
232 | return | |
233 | if env.out_dir==env.top_dir: | |
234 | distclean_dir(env.out_dir) | |
235 | else: | |
236 | remove_and_log(env.out_dir,shutil.rmtree) | |
237 | env_dirs=[env.out_dir] | |
238 | if not ctx.options.no_lock_in_top: | |
239 | env_dirs.append(env.top_dir) | |
240 | if not ctx.options.no_lock_in_run: | |
241 | env_dirs.append(env.run_dir) | |
242 | for k in env_dirs: | |
243 | p=os.path.join(k,Options.lockfile) | |
244 | remove_and_log(p,os.remove) | |
245 | class Dist(Context.Context): | |
246 | '''creates an archive containing the project source code''' | |
247 | cmd='dist' | |
248 | fun='dist' | |
249 | algo='tar.bz2' | |
250 | ext_algo={} | |
251 | def execute(self): | |
252 | self.recurse([os.path.dirname(Context.g_module.root_path)]) | |
253 | self.archive() | |
254 | def archive(self): | |
255 | import tarfile | |
256 | arch_name=self.get_arch_name() | |
257 | try: | |
258 | self.base_path | |
259 | except AttributeError: | |
260 | self.base_path=self.path | |
261 | node=self.base_path.make_node(arch_name) | |
262 | try: | |
263 | node.delete() | |
264 | except OSError: | |
265 | pass | |
266 | files=self.get_files() | |
267 | if self.algo.startswith('tar.'): | |
268 | tar=tarfile.open(node.abspath(),'w:'+self.algo.replace('tar.','')) | |
269 | for x in files: | |
270 | self.add_tar_file(x,tar) | |
271 | tar.close() | |
272 | elif self.algo=='zip': | |
273 | import zipfile | |
274 | zip=zipfile.ZipFile(node.abspath(),'w',compression=zipfile.ZIP_DEFLATED) | |
275 | for x in files: | |
276 | archive_name=self.get_base_name()+'/'+x.path_from(self.base_path) | |
277 | zip.write(x.abspath(),archive_name,zipfile.ZIP_DEFLATED) | |
278 | zip.close() | |
279 | else: | |
280 | self.fatal('Valid algo types are tar.bz2, tar.gz, tar.xz or zip') | |
281 | try: | |
282 | from hashlib import sha256 | |
283 | except ImportError: | |
284 | digest='' | |
285 | else: | |
286 | digest=' (sha256=%r)'%sha256(node.read(flags='rb')).hexdigest() | |
287 | Logs.info('New archive created: %s%s',self.arch_name,digest) | |
288 | def get_tar_path(self,node): | |
289 | return node.abspath() | |
290 | def add_tar_file(self,x,tar): | |
291 | p=self.get_tar_path(x) | |
292 | tinfo=tar.gettarinfo(name=p,arcname=self.get_tar_prefix()+'/'+x.path_from(self.base_path)) | |
293 | tinfo.uid=0 | |
294 | tinfo.gid=0 | |
295 | tinfo.uname='root' | |
296 | tinfo.gname='root' | |
297 | if os.path.isfile(p): | |
298 | with open(p,'rb')as f: | |
299 | tar.addfile(tinfo,fileobj=f) | |
300 | else: | |
301 | tar.addfile(tinfo) | |
302 | def get_tar_prefix(self): | |
303 | try: | |
304 | return self.tar_prefix | |
305 | except AttributeError: | |
306 | return self.get_base_name() | |
307 | def get_arch_name(self): | |
308 | try: | |
309 | self.arch_name | |
310 | except AttributeError: | |
311 | self.arch_name=self.get_base_name()+'.'+self.ext_algo.get(self.algo,self.algo) | |
312 | return self.arch_name | |
313 | def get_base_name(self): | |
314 | try: | |
315 | self.base_name | |
316 | except AttributeError: | |
317 | appname=getattr(Context.g_module,Context.APPNAME,'noname') | |
318 | version=getattr(Context.g_module,Context.VERSION,'1.0') | |
319 | self.base_name=appname+'-'+version | |
320 | return self.base_name | |
321 | def get_excl(self): | |
322 | try: | |
323 | return self.excl | |
324 | except AttributeError: | |
325 | self.excl=Node.exclude_regs+' **/waf-2.* **/.waf-2.* **/waf3-2.* **/.waf3-2.* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' | |
326 | if Context.out_dir: | |
327 | nd=self.root.find_node(Context.out_dir) | |
328 | if nd: | |
329 | self.excl+=' '+nd.path_from(self.base_path) | |
330 | return self.excl | |
331 | def get_files(self): | |
332 | try: | |
333 | files=self.files | |
334 | except AttributeError: | |
335 | files=self.base_path.ant_glob('**/*',excl=self.get_excl()) | |
336 | return files | |
337 | def dist(ctx): | |
338 | '''makes a tarball for redistributing the sources''' | |
339 | pass | |
340 | class DistCheck(Dist): | |
341 | fun='distcheck' | |
342 | cmd='distcheck' | |
343 | def execute(self): | |
344 | self.recurse([os.path.dirname(Context.g_module.root_path)]) | |
345 | self.archive() | |
346 | self.check() | |
347 | def make_distcheck_cmd(self,tmpdir): | |
348 | cfg=[] | |
349 | if Options.options.distcheck_args: | |
350 | cfg=shlex.split(Options.options.distcheck_args) | |
351 | else: | |
352 | cfg=[x for x in sys.argv if x.startswith('-')] | |
353 | cmd=[sys.executable,sys.argv[0],'configure','build','install','uninstall','--destdir='+tmpdir]+cfg | |
354 | return cmd | |
355 | def check(self): | |
356 | import tempfile,tarfile | |
357 | with tarfile.open(self.get_arch_name())as t: | |
358 | for x in t: | |
359 | t.extract(x) | |
360 | instdir=tempfile.mkdtemp('.inst',self.get_base_name()) | |
361 | cmd=self.make_distcheck_cmd(instdir) | |
362 | ret=Utils.subprocess.Popen(cmd,cwd=self.get_base_name()).wait() | |
363 | if ret: | |
364 | raise Errors.WafError('distcheck failed with code %r'%ret) | |
365 | if os.path.exists(instdir): | |
366 | raise Errors.WafError('distcheck succeeded, but files were left in %s'%instdir) | |
367 | shutil.rmtree(self.get_base_name()) | |
368 | def distcheck(ctx): | |
369 | '''checks if the project compiles (tarball from 'dist')''' | |
370 | pass | |
371 | def autoconfigure(execute_method): | |
372 | def execute(self): | |
373 | if not Configure.autoconfig: | |
374 | return execute_method(self) | |
375 | env=ConfigSet.ConfigSet() | |
376 | do_config=False | |
377 | try: | |
378 | env.load(os.path.join(Context.top_dir,Options.lockfile)) | |
379 | except EnvironmentError: | |
380 | Logs.warn('Configuring the project') | |
381 | do_config=True | |
382 | else: | |
383 | if env.run_dir!=Context.run_dir: | |
384 | do_config=True | |
385 | else: | |
386 | h=0 | |
387 | for f in env.files: | |
388 | try: | |
389 | h=Utils.h_list((h,Utils.readf(f,'rb'))) | |
390 | except EnvironmentError: | |
391 | do_config=True | |
392 | break | |
393 | else: | |
394 | do_config=h!=env.hash | |
395 | if do_config: | |
396 | cmd=env.config_cmd or'configure' | |
397 | if Configure.autoconfig=='clobber': | |
398 | tmp=Options.options.__dict__ | |
399 | launch_dir_tmp=Context.launch_dir | |
400 | if env.options: | |
401 | Options.options.__dict__=env.options | |
402 | Context.launch_dir=env.launch_dir | |
403 | try: | |
404 | run_command(cmd) | |
405 | finally: | |
406 | Options.options.__dict__=tmp | |
407 | Context.launch_dir=launch_dir_tmp | |
408 | else: | |
409 | run_command(cmd) | |
410 | run_command(self.cmd) | |
411 | else: | |
412 | return execute_method(self) | |
413 | return execute | |
414 | Build.BuildContext.execute=autoconfigure(Build.BuildContext.execute) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re,sys,tempfile,traceback | |
5 | from waflib import Utils,Logs,Errors | |
6 | NOT_RUN=0 | |
7 | MISSING=1 | |
8 | CRASHED=2 | |
9 | EXCEPTION=3 | |
10 | CANCELED=4 | |
11 | SKIPPED=8 | |
12 | SUCCESS=9 | |
13 | ASK_LATER=-1 | |
14 | SKIP_ME=-2 | |
15 | RUN_ME=-3 | |
16 | CANCEL_ME=-4 | |
17 | COMPILE_TEMPLATE_SHELL=''' | |
18 | def f(tsk): | |
19 | env = tsk.env | |
20 | gen = tsk.generator | |
21 | bld = gen.bld | |
22 | cwdx = tsk.get_cwd() | |
23 | p = env.get_flat | |
24 | def to_list(xx): | |
25 | if isinstance(xx, str): return [xx] | |
26 | return xx | |
27 | tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s | |
28 | return tsk.exec_command(cmd, cwd=cwdx, env=env.env or None) | |
29 | ''' | |
30 | COMPILE_TEMPLATE_NOSHELL=''' | |
31 | def f(tsk): | |
32 | env = tsk.env | |
33 | gen = tsk.generator | |
34 | bld = gen.bld | |
35 | cwdx = tsk.get_cwd() | |
36 | def to_list(xx): | |
37 | if isinstance(xx, str): return [xx] | |
38 | return xx | |
39 | def merge(lst1, lst2): | |
40 | if lst1 and lst2: | |
41 | return lst1[:-1] + [lst1[-1] + lst2[0]] + lst2[1:] | |
42 | return lst1 + lst2 | |
43 | lst = [] | |
44 | %s | |
45 | if '' in lst: | |
46 | lst = [x for x in lst if x] | |
47 | tsk.last_cmd = lst | |
48 | return tsk.exec_command(lst, cwd=cwdx, env=env.env or None) | |
49 | ''' | |
50 | COMPILE_TEMPLATE_SIG_VARS=''' | |
51 | def f(tsk): | |
52 | sig = tsk.generator.bld.hash_env_vars(tsk.env, tsk.vars) | |
53 | tsk.m.update(sig) | |
54 | env = tsk.env | |
55 | gen = tsk.generator | |
56 | bld = gen.bld | |
57 | cwdx = tsk.get_cwd() | |
58 | p = env.get_flat | |
59 | buf = [] | |
60 | %s | |
61 | tsk.m.update(repr(buf).encode()) | |
62 | ''' | |
63 | classes={} | |
64 | class store_task_type(type): | |
65 | def __init__(cls,name,bases,dict): | |
66 | super(store_task_type,cls).__init__(name,bases,dict) | |
67 | name=cls.__name__ | |
68 | if name!='evil'and name!='Task': | |
69 | if getattr(cls,'run_str',None): | |
70 | (f,dvars)=compile_fun(cls.run_str,cls.shell) | |
71 | cls.hcode=Utils.h_cmd(cls.run_str) | |
72 | cls.orig_run_str=cls.run_str | |
73 | cls.run_str=None | |
74 | cls.run=f | |
75 | cls.vars=list(set(cls.vars+dvars)) | |
76 | cls.vars.sort() | |
77 | if cls.vars: | |
78 | fun=compile_sig_vars(cls.vars) | |
79 | if fun: | |
80 | cls.sig_vars=fun | |
81 | elif getattr(cls,'run',None)and not'hcode'in cls.__dict__: | |
82 | cls.hcode=Utils.h_cmd(cls.run) | |
83 | getattr(cls,'register',classes)[name]=cls | |
84 | evil=store_task_type('evil',(object,),{}) | |
85 | class Task(evil): | |
86 | vars=[] | |
87 | always_run=False | |
88 | shell=False | |
89 | color='GREEN' | |
90 | ext_in=[] | |
91 | ext_out=[] | |
92 | before=[] | |
93 | after=[] | |
94 | hcode=Utils.SIG_NIL | |
95 | keep_last_cmd=False | |
96 | weight=0 | |
97 | tree_weight=0 | |
98 | prio_order=0 | |
99 | __slots__=('hasrun','generator','env','inputs','outputs','dep_nodes','run_after') | |
100 | def __init__(self,*k,**kw): | |
101 | self.hasrun=NOT_RUN | |
102 | try: | |
103 | self.generator=kw['generator'] | |
104 | except KeyError: | |
105 | self.generator=self | |
106 | self.env=kw['env'] | |
107 | self.inputs=[] | |
108 | self.outputs=[] | |
109 | self.dep_nodes=[] | |
110 | self.run_after=set() | |
111 | def __lt__(self,other): | |
112 | return self.priority()>other.priority() | |
113 | def __le__(self,other): | |
114 | return self.priority()>=other.priority() | |
115 | def __gt__(self,other): | |
116 | return self.priority()<other.priority() | |
117 | def __ge__(self,other): | |
118 | return self.priority()<=other.priority() | |
119 | def get_cwd(self): | |
120 | bld=self.generator.bld | |
121 | ret=getattr(self,'cwd',None)or getattr(bld,'cwd',bld.bldnode) | |
122 | if isinstance(ret,str): | |
123 | if os.path.isabs(ret): | |
124 | ret=bld.root.make_node(ret) | |
125 | else: | |
126 | ret=self.generator.path.make_node(ret) | |
127 | return ret | |
128 | def quote_flag(self,x): | |
129 | old=x | |
130 | if'\\'in x: | |
131 | x=x.replace('\\','\\\\') | |
132 | if'"'in x: | |
133 | x=x.replace('"','\\"') | |
134 | if old!=x or' 'in x or'\t'in x or"'"in x: | |
135 | x='"%s"'%x | |
136 | return x | |
137 | def priority(self): | |
138 | return(self.weight+self.prio_order,-getattr(self.generator,'tg_idx_count',0)) | |
139 | def split_argfile(self,cmd): | |
140 | return([cmd[0]],[self.quote_flag(x)for x in cmd[1:]]) | |
141 | def exec_command(self,cmd,**kw): | |
142 | if not'cwd'in kw: | |
143 | kw['cwd']=self.get_cwd() | |
144 | if hasattr(self,'timeout'): | |
145 | kw['timeout']=self.timeout | |
146 | if self.env.PATH: | |
147 | env=kw['env']=dict(kw.get('env')or self.env.env or os.environ) | |
148 | env['PATH']=self.env.PATH if isinstance(self.env.PATH,str)else os.pathsep.join(self.env.PATH) | |
149 | if hasattr(self,'stdout'): | |
150 | kw['stdout']=self.stdout | |
151 | if hasattr(self,'stderr'): | |
152 | kw['stderr']=self.stderr | |
153 | if not isinstance(cmd,str): | |
154 | if Utils.is_win32: | |
155 | too_long=sum([len(arg)for arg in cmd])+len(cmd)>8192 | |
156 | else: | |
157 | too_long=len(cmd)>200000 | |
158 | if too_long and getattr(self,'allow_argsfile',True): | |
159 | cmd,args=self.split_argfile(cmd) | |
160 | try: | |
161 | (fd,tmp)=tempfile.mkstemp() | |
162 | os.write(fd,'\r\n'.join(args).encode()) | |
163 | os.close(fd) | |
164 | if Logs.verbose: | |
165 | Logs.debug('argfile: @%r -> %r',tmp,args) | |
166 | return self.generator.bld.exec_command(cmd+['@'+tmp],**kw) | |
167 | finally: | |
168 | try: | |
169 | os.remove(tmp) | |
170 | except OSError: | |
171 | pass | |
172 | return self.generator.bld.exec_command(cmd,**kw) | |
173 | def process(self): | |
174 | try: | |
175 | del self.generator.bld.task_sigs[self.uid()] | |
176 | except KeyError: | |
177 | pass | |
178 | try: | |
179 | ret=self.run() | |
180 | except Exception: | |
181 | self.err_msg=traceback.format_exc() | |
182 | self.hasrun=EXCEPTION | |
183 | else: | |
184 | if ret: | |
185 | self.err_code=ret | |
186 | self.hasrun=CRASHED | |
187 | else: | |
188 | try: | |
189 | self.post_run() | |
190 | except Errors.WafError: | |
191 | pass | |
192 | except Exception: | |
193 | self.err_msg=traceback.format_exc() | |
194 | self.hasrun=EXCEPTION | |
195 | else: | |
196 | self.hasrun=SUCCESS | |
197 | if self.hasrun!=SUCCESS and self.scan: | |
198 | try: | |
199 | del self.generator.bld.imp_sigs[self.uid()] | |
200 | except KeyError: | |
201 | pass | |
202 | def log_display(self,bld): | |
203 | if self.generator.bld.progress_bar==3: | |
204 | return | |
205 | s=self.display() | |
206 | if s: | |
207 | if bld.logger: | |
208 | logger=bld.logger | |
209 | else: | |
210 | logger=Logs | |
211 | if self.generator.bld.progress_bar==1: | |
212 | c1=Logs.colors.cursor_off | |
213 | c2=Logs.colors.cursor_on | |
214 | logger.info(s,extra={'stream':sys.stderr,'terminator':'','c1':c1,'c2':c2}) | |
215 | else: | |
216 | logger.info(s,extra={'terminator':'','c1':'','c2':''}) | |
217 | def display(self): | |
218 | col1=Logs.colors(self.color) | |
219 | col2=Logs.colors.NORMAL | |
220 | master=self.generator.bld.producer | |
221 | def cur(): | |
222 | return master.processed-master.ready.qsize() | |
223 | if self.generator.bld.progress_bar==1: | |
224 | return self.generator.bld.progress_line(cur(),master.total,col1,col2) | |
225 | if self.generator.bld.progress_bar==2: | |
226 | ela=str(self.generator.bld.timer) | |
227 | try: | |
228 | ins=','.join([n.name for n in self.inputs]) | |
229 | except AttributeError: | |
230 | ins='' | |
231 | try: | |
232 | outs=','.join([n.name for n in self.outputs]) | |
233 | except AttributeError: | |
234 | outs='' | |
235 | return'|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n'%(master.total,cur(),ins,outs,ela) | |
236 | s=str(self) | |
237 | if not s: | |
238 | return None | |
239 | total=master.total | |
240 | n=len(str(total)) | |
241 | fs='[%%%dd/%%%dd] %%s%%s%%s%%s\n'%(n,n) | |
242 | kw=self.keyword() | |
243 | if kw: | |
244 | kw+=' ' | |
245 | return fs%(cur(),total,kw,col1,s,col2) | |
246 | def hash_constraints(self): | |
247 | return(tuple(self.before),tuple(self.after),tuple(self.ext_in),tuple(self.ext_out),self.__class__.__name__,self.hcode) | |
248 | def format_error(self): | |
249 | if Logs.verbose: | |
250 | msg=': %r\n%r'%(self,getattr(self,'last_cmd','')) | |
251 | else: | |
252 | msg=' (run with -v to display more information)' | |
253 | name=getattr(self.generator,'name','') | |
254 | if getattr(self,"err_msg",None): | |
255 | return self.err_msg | |
256 | elif not self.hasrun: | |
257 | return'task in %r was not executed for some reason: %r'%(name,self) | |
258 | elif self.hasrun==CRASHED: | |
259 | try: | |
260 | return' -> task in %r failed with exit status %r%s'%(name,self.err_code,msg) | |
261 | except AttributeError: | |
262 | return' -> task in %r failed%s'%(name,msg) | |
263 | elif self.hasrun==MISSING: | |
264 | return' -> missing files in %r%s'%(name,msg) | |
265 | elif self.hasrun==CANCELED: | |
266 | return' -> %r canceled because of missing dependencies'%name | |
267 | else: | |
268 | return'invalid status for task in %r: %r'%(name,self.hasrun) | |
269 | def colon(self,var1,var2): | |
270 | tmp=self.env[var1] | |
271 | if not tmp: | |
272 | return[] | |
273 | if isinstance(var2,str): | |
274 | it=self.env[var2] | |
275 | else: | |
276 | it=var2 | |
277 | if isinstance(tmp,str): | |
278 | return[tmp%x for x in it] | |
279 | else: | |
280 | lst=[] | |
281 | for y in it: | |
282 | lst.extend(tmp) | |
283 | lst.append(y) | |
284 | return lst | |
285 | def __str__(self): | |
286 | name=self.__class__.__name__ | |
287 | if self.outputs: | |
288 | if name.endswith(('lib','program'))or not self.inputs: | |
289 | node=self.outputs[0] | |
290 | return node.path_from(node.ctx.launch_node()) | |
291 | if not(self.inputs or self.outputs): | |
292 | return self.__class__.__name__ | |
293 | if len(self.inputs)==1: | |
294 | node=self.inputs[0] | |
295 | return node.path_from(node.ctx.launch_node()) | |
296 | src_str=' '.join([a.path_from(a.ctx.launch_node())for a in self.inputs]) | |
297 | tgt_str=' '.join([a.path_from(a.ctx.launch_node())for a in self.outputs]) | |
298 | if self.outputs: | |
299 | sep=' -> ' | |
300 | else: | |
301 | sep='' | |
302 | return'%s: %s%s%s'%(self.__class__.__name__,src_str,sep,tgt_str) | |
303 | def keyword(self): | |
304 | name=self.__class__.__name__ | |
305 | if name.endswith(('lib','program')): | |
306 | return'Linking' | |
307 | if len(self.inputs)==1 and len(self.outputs)==1: | |
308 | return'Compiling' | |
309 | if not self.inputs: | |
310 | if self.outputs: | |
311 | return'Creating' | |
312 | else: | |
313 | return'Running' | |
314 | return'Processing' | |
315 | def __repr__(self): | |
316 | try: | |
317 | ins=",".join([x.name for x in self.inputs]) | |
318 | outs=",".join([x.name for x in self.outputs]) | |
319 | except AttributeError: | |
320 | ins=",".join([str(x)for x in self.inputs]) | |
321 | outs=",".join([str(x)for x in self.outputs]) | |
322 | return"".join(['\n\t{task %r: '%id(self),self.__class__.__name__," ",ins," -> ",outs,'}']) | |
323 | def uid(self): | |
324 | try: | |
325 | return self.uid_ | |
326 | except AttributeError: | |
327 | m=Utils.md5(self.__class__.__name__) | |
328 | up=m.update | |
329 | for x in self.inputs+self.outputs: | |
330 | up(x.abspath()) | |
331 | self.uid_=m.digest() | |
332 | return self.uid_ | |
333 | def set_inputs(self,inp): | |
334 | if isinstance(inp,list): | |
335 | self.inputs+=inp | |
336 | else: | |
337 | self.inputs.append(inp) | |
338 | def set_outputs(self,out): | |
339 | if isinstance(out,list): | |
340 | self.outputs+=out | |
341 | else: | |
342 | self.outputs.append(out) | |
343 | def set_run_after(self,task): | |
344 | assert isinstance(task,Task) | |
345 | self.run_after.add(task) | |
346 | def signature(self): | |
347 | try: | |
348 | return self.cache_sig | |
349 | except AttributeError: | |
350 | pass | |
351 | self.m=Utils.md5(self.hcode) | |
352 | self.sig_explicit_deps() | |
353 | self.sig_vars() | |
354 | if self.scan: | |
355 | try: | |
356 | self.sig_implicit_deps() | |
357 | except Errors.TaskRescan: | |
358 | return self.signature() | |
359 | ret=self.cache_sig=self.m.digest() | |
360 | return ret | |
361 | def runnable_status(self): | |
362 | bld=self.generator.bld | |
363 | if bld.is_install<0: | |
364 | return SKIP_ME | |
365 | for t in self.run_after: | |
366 | if not t.hasrun: | |
367 | return ASK_LATER | |
368 | elif t.hasrun<SKIPPED: | |
369 | return CANCEL_ME | |
370 | try: | |
371 | new_sig=self.signature() | |
372 | except Errors.TaskNotReady: | |
373 | return ASK_LATER | |
374 | key=self.uid() | |
375 | try: | |
376 | prev_sig=bld.task_sigs[key] | |
377 | except KeyError: | |
378 | Logs.debug('task: task %r must run: it was never run before or the task code changed',self) | |
379 | return RUN_ME | |
380 | if new_sig!=prev_sig: | |
381 | Logs.debug('task: task %r must run: the task signature changed',self) | |
382 | return RUN_ME | |
383 | for node in self.outputs: | |
384 | sig=bld.node_sigs.get(node) | |
385 | if not sig: | |
386 | Logs.debug('task: task %r must run: an output node has no signature',self) | |
387 | return RUN_ME | |
388 | if sig!=key: | |
389 | Logs.debug('task: task %r must run: an output node was produced by another task',self) | |
390 | return RUN_ME | |
391 | if not node.exists(): | |
392 | Logs.debug('task: task %r must run: an output node does not exist',self) | |
393 | return RUN_ME | |
394 | return(self.always_run and RUN_ME)or SKIP_ME | |
395 | def post_run(self): | |
396 | bld=self.generator.bld | |
397 | for node in self.outputs: | |
398 | if not node.exists(): | |
399 | self.hasrun=MISSING | |
400 | self.err_msg='-> missing file: %r'%node.abspath() | |
401 | raise Errors.WafError(self.err_msg) | |
402 | bld.node_sigs[node]=self.uid() | |
403 | bld.task_sigs[self.uid()]=self.signature() | |
404 | if not self.keep_last_cmd: | |
405 | try: | |
406 | del self.last_cmd | |
407 | except AttributeError: | |
408 | pass | |
409 | def sig_explicit_deps(self): | |
410 | bld=self.generator.bld | |
411 | upd=self.m.update | |
412 | for x in self.inputs+self.dep_nodes: | |
413 | upd(x.get_bld_sig()) | |
414 | if bld.deps_man: | |
415 | additional_deps=bld.deps_man | |
416 | for x in self.inputs+self.outputs: | |
417 | try: | |
418 | d=additional_deps[x] | |
419 | except KeyError: | |
420 | continue | |
421 | for v in d: | |
422 | try: | |
423 | v=v.get_bld_sig() | |
424 | except AttributeError: | |
425 | if hasattr(v,'__call__'): | |
426 | v=v() | |
427 | upd(v) | |
428 | def sig_deep_inputs(self): | |
429 | bld=self.generator.bld | |
430 | lst=[bld.task_sigs[bld.node_sigs[node]]for node in(self.inputs+self.dep_nodes)if node.is_bld()] | |
431 | self.m.update(Utils.h_list(lst)) | |
432 | def sig_vars(self): | |
433 | sig=self.generator.bld.hash_env_vars(self.env,self.vars) | |
434 | self.m.update(sig) | |
435 | scan=None | |
436 | def sig_implicit_deps(self): | |
437 | bld=self.generator.bld | |
438 | key=self.uid() | |
439 | prev=bld.imp_sigs.get(key,[]) | |
440 | if prev: | |
441 | try: | |
442 | if prev==self.compute_sig_implicit_deps(): | |
443 | return prev | |
444 | except Errors.TaskNotReady: | |
445 | raise | |
446 | except EnvironmentError: | |
447 | for x in bld.node_deps.get(self.uid(),[]): | |
448 | if not x.is_bld()and not x.exists(): | |
449 | try: | |
450 | del x.parent.children[x.name] | |
451 | except KeyError: | |
452 | pass | |
453 | del bld.imp_sigs[key] | |
454 | raise Errors.TaskRescan('rescan') | |
455 | (bld.node_deps[key],bld.raw_deps[key])=self.scan() | |
456 | if Logs.verbose: | |
457 | Logs.debug('deps: scanner for %s: %r; unresolved: %r',self,bld.node_deps[key],bld.raw_deps[key]) | |
458 | try: | |
459 | bld.imp_sigs[key]=self.compute_sig_implicit_deps() | |
460 | except EnvironmentError: | |
461 | for k in bld.node_deps.get(self.uid(),[]): | |
462 | if not k.exists(): | |
463 | Logs.warn('Dependency %r for %r is missing: check the task declaration and the build order!',k,self) | |
464 | raise | |
465 | def compute_sig_implicit_deps(self): | |
466 | upd=self.m.update | |
467 | self.are_implicit_nodes_ready() | |
468 | for k in self.generator.bld.node_deps.get(self.uid(),[]): | |
469 | upd(k.get_bld_sig()) | |
470 | return self.m.digest() | |
471 | def are_implicit_nodes_ready(self): | |
472 | bld=self.generator.bld | |
473 | try: | |
474 | cache=bld.dct_implicit_nodes | |
475 | except AttributeError: | |
476 | bld.dct_implicit_nodes=cache={} | |
477 | try: | |
478 | dct=cache[bld.current_group] | |
479 | except KeyError: | |
480 | dct=cache[bld.current_group]={} | |
481 | for tsk in bld.cur_tasks: | |
482 | for x in tsk.outputs: | |
483 | dct[x]=tsk | |
484 | modified=False | |
485 | for x in bld.node_deps.get(self.uid(),[]): | |
486 | if x in dct: | |
487 | self.run_after.add(dct[x]) | |
488 | modified=True | |
489 | if modified: | |
490 | for tsk in self.run_after: | |
491 | if not tsk.hasrun: | |
492 | raise Errors.TaskNotReady('not ready') | |
493 | if sys.hexversion>0x3000000: | |
494 | def uid(self): | |
495 | try: | |
496 | return self.uid_ | |
497 | except AttributeError: | |
498 | m=Utils.md5(self.__class__.__name__.encode('latin-1','xmlcharrefreplace')) | |
499 | up=m.update | |
500 | for x in self.inputs+self.outputs: | |
501 | up(x.abspath().encode('latin-1','xmlcharrefreplace')) | |
502 | self.uid_=m.digest() | |
503 | return self.uid_ | |
504 | uid.__doc__=Task.uid.__doc__ | |
505 | Task.uid=uid | |
506 | def is_before(t1,t2): | |
507 | to_list=Utils.to_list | |
508 | for k in to_list(t2.ext_in): | |
509 | if k in to_list(t1.ext_out): | |
510 | return 1 | |
511 | if t1.__class__.__name__ in to_list(t2.after): | |
512 | return 1 | |
513 | if t2.__class__.__name__ in to_list(t1.before): | |
514 | return 1 | |
515 | return 0 | |
516 | def set_file_constraints(tasks): | |
517 | ins=Utils.defaultdict(set) | |
518 | outs=Utils.defaultdict(set) | |
519 | for x in tasks: | |
520 | for a in x.inputs: | |
521 | ins[a].add(x) | |
522 | for a in x.dep_nodes: | |
523 | ins[a].add(x) | |
524 | for a in x.outputs: | |
525 | outs[a].add(x) | |
526 | links=set(ins.keys()).intersection(outs.keys()) | |
527 | for k in links: | |
528 | for a in ins[k]: | |
529 | a.run_after.update(outs[k]) | |
530 | class TaskGroup(object): | |
531 | def __init__(self,prev,next): | |
532 | self.prev=prev | |
533 | self.next=next | |
534 | self.done=False | |
535 | def get_hasrun(self): | |
536 | for k in self.prev: | |
537 | if not k.hasrun: | |
538 | return NOT_RUN | |
539 | return SUCCESS | |
540 | hasrun=property(get_hasrun,None) | |
541 | def set_precedence_constraints(tasks): | |
542 | cstr_groups=Utils.defaultdict(list) | |
543 | for x in tasks: | |
544 | h=x.hash_constraints() | |
545 | cstr_groups[h].append(x) | |
546 | keys=list(cstr_groups.keys()) | |
547 | maxi=len(keys) | |
548 | for i in range(maxi): | |
549 | t1=cstr_groups[keys[i]][0] | |
550 | for j in range(i+1,maxi): | |
551 | t2=cstr_groups[keys[j]][0] | |
552 | if is_before(t1,t2): | |
553 | a=i | |
554 | b=j | |
555 | elif is_before(t2,t1): | |
556 | a=j | |
557 | b=i | |
558 | else: | |
559 | continue | |
560 | a=cstr_groups[keys[a]] | |
561 | b=cstr_groups[keys[b]] | |
562 | if len(a)<2 or len(b)<2: | |
563 | for x in b: | |
564 | x.run_after.update(a) | |
565 | else: | |
566 | group=TaskGroup(set(a),set(b)) | |
567 | for x in b: | |
568 | x.run_after.add(group) | |
569 | def funex(c): | |
570 | dc={} | |
571 | exec(c,dc) | |
572 | return dc['f'] | |
573 | re_cond=re.compile(r'(?P<var>\w+)|(?P<or>\|)|(?P<and>&)') | |
574 | re_novar=re.compile(r'^(SRC|TGT)\W+.*?$') | |
575 | reg_act=re.compile(r'(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})',re.M) | |
576 | def compile_fun_shell(line): | |
577 | extr=[] | |
578 | def repl(match): | |
579 | g=match.group | |
580 | if g('dollar'): | |
581 | return"$" | |
582 | elif g('backslash'): | |
583 | return'\\\\' | |
584 | elif g('subst'): | |
585 | extr.append((g('var'),g('code'))) | |
586 | return"%s" | |
587 | return None | |
588 | line=reg_act.sub(repl,line)or line | |
589 | dvars=[] | |
590 | def add_dvar(x): | |
591 | if x not in dvars: | |
592 | dvars.append(x) | |
593 | def replc(m): | |
594 | if m.group('and'): | |
595 | return' and ' | |
596 | elif m.group('or'): | |
597 | return' or ' | |
598 | else: | |
599 | x=m.group('var') | |
600 | add_dvar(x) | |
601 | return'env[%r]'%x | |
602 | parm=[] | |
603 | app=parm.append | |
604 | for(var,meth)in extr: | |
605 | if var=='SRC': | |
606 | if meth: | |
607 | app('tsk.inputs%s'%meth) | |
608 | else: | |
609 | app('" ".join([a.path_from(cwdx) for a in tsk.inputs])') | |
610 | elif var=='TGT': | |
611 | if meth: | |
612 | app('tsk.outputs%s'%meth) | |
613 | else: | |
614 | app('" ".join([a.path_from(cwdx) for a in tsk.outputs])') | |
615 | elif meth: | |
616 | if meth.startswith(':'): | |
617 | add_dvar(var) | |
618 | m=meth[1:] | |
619 | if m=='SRC': | |
620 | m='[a.path_from(cwdx) for a in tsk.inputs]' | |
621 | elif m=='TGT': | |
622 | m='[a.path_from(cwdx) for a in tsk.outputs]' | |
623 | elif re_novar.match(m): | |
624 | m='[tsk.inputs%s]'%m[3:] | |
625 | elif re_novar.match(m): | |
626 | m='[tsk.outputs%s]'%m[3:] | |
627 | else: | |
628 | add_dvar(m) | |
629 | if m[:3]not in('tsk','gen','bld'): | |
630 | m='%r'%m | |
631 | app('" ".join(tsk.colon(%r, %s))'%(var,m)) | |
632 | elif meth.startswith('?'): | |
633 | expr=re_cond.sub(replc,meth[1:]) | |
634 | app('p(%r) if (%s) else ""'%(var,expr)) | |
635 | else: | |
636 | call='%s%s'%(var,meth) | |
637 | add_dvar(call) | |
638 | app(call) | |
639 | else: | |
640 | add_dvar(var) | |
641 | app("p('%s')"%var) | |
642 | if parm: | |
643 | parm="%% (%s) "%(',\n\t\t'.join(parm)) | |
644 | else: | |
645 | parm='' | |
646 | c=COMPILE_TEMPLATE_SHELL%(line,parm) | |
647 | Logs.debug('action: %s',c.strip().splitlines()) | |
648 | return(funex(c),dvars) | |
649 | reg_act_noshell=re.compile(r"(?P<space>\s+)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})|(?P<text>([^$ \t\n\r\f\v]|\$\$)+)",re.M) | |
650 | def compile_fun_noshell(line): | |
651 | buf=[] | |
652 | dvars=[] | |
653 | merge=False | |
654 | app=buf.append | |
655 | def add_dvar(x): | |
656 | if x not in dvars: | |
657 | dvars.append(x) | |
658 | def replc(m): | |
659 | if m.group('and'): | |
660 | return' and ' | |
661 | elif m.group('or'): | |
662 | return' or ' | |
663 | else: | |
664 | x=m.group('var') | |
665 | add_dvar(x) | |
666 | return'env[%r]'%x | |
667 | for m in reg_act_noshell.finditer(line): | |
668 | if m.group('space'): | |
669 | merge=False | |
670 | continue | |
671 | elif m.group('text'): | |
672 | app('[%r]'%m.group('text').replace('$$','$')) | |
673 | elif m.group('subst'): | |
674 | var=m.group('var') | |
675 | code=m.group('code') | |
676 | if var=='SRC': | |
677 | if code: | |
678 | app('[tsk.inputs%s]'%code) | |
679 | else: | |
680 | app('[a.path_from(cwdx) for a in tsk.inputs]') | |
681 | elif var=='TGT': | |
682 | if code: | |
683 | app('[tsk.outputs%s]'%code) | |
684 | else: | |
685 | app('[a.path_from(cwdx) for a in tsk.outputs]') | |
686 | elif code: | |
687 | if code.startswith(':'): | |
688 | add_dvar(var) | |
689 | m=code[1:] | |
690 | if m=='SRC': | |
691 | m='[a.path_from(cwdx) for a in tsk.inputs]' | |
692 | elif m=='TGT': | |
693 | m='[a.path_from(cwdx) for a in tsk.outputs]' | |
694 | elif re_novar.match(m): | |
695 | m='[tsk.inputs%s]'%m[3:] | |
696 | elif re_novar.match(m): | |
697 | m='[tsk.outputs%s]'%m[3:] | |
698 | else: | |
699 | add_dvar(m) | |
700 | if m[:3]not in('tsk','gen','bld'): | |
701 | m='%r'%m | |
702 | app('tsk.colon(%r, %s)'%(var,m)) | |
703 | elif code.startswith('?'): | |
704 | expr=re_cond.sub(replc,code[1:]) | |
705 | app('to_list(env[%r] if (%s) else [])'%(var,expr)) | |
706 | else: | |
707 | call='%s%s'%(var,code) | |
708 | add_dvar(call) | |
709 | app('to_list(%s)'%call) | |
710 | else: | |
711 | app('to_list(env[%r])'%var) | |
712 | add_dvar(var) | |
713 | if merge: | |
714 | tmp='merge(%s, %s)'%(buf[-2],buf[-1]) | |
715 | del buf[-1] | |
716 | buf[-1]=tmp | |
717 | merge=True | |
718 | buf=['lst.extend(%s)'%x for x in buf] | |
719 | fun=COMPILE_TEMPLATE_NOSHELL%"\n\t".join(buf) | |
720 | Logs.debug('action: %s',fun.strip().splitlines()) | |
721 | return(funex(fun),dvars) | |
722 | def compile_fun(line,shell=False): | |
723 | if isinstance(line,str): | |
724 | if line.find('<')>0 or line.find('>')>0 or line.find('&&')>0: | |
725 | shell=True | |
726 | else: | |
727 | dvars_lst=[] | |
728 | funs_lst=[] | |
729 | for x in line: | |
730 | if isinstance(x,str): | |
731 | fun,dvars=compile_fun(x,shell) | |
732 | dvars_lst+=dvars | |
733 | funs_lst.append(fun) | |
734 | else: | |
735 | funs_lst.append(x) | |
736 | def composed_fun(task): | |
737 | for x in funs_lst: | |
738 | ret=x(task) | |
739 | if ret: | |
740 | return ret | |
741 | return None | |
742 | return composed_fun,dvars_lst | |
743 | if shell: | |
744 | return compile_fun_shell(line) | |
745 | else: | |
746 | return compile_fun_noshell(line) | |
747 | def compile_sig_vars(vars): | |
748 | buf=[] | |
749 | for x in sorted(vars): | |
750 | if x[:3]in('tsk','gen','bld'): | |
751 | buf.append('buf.append(%s)'%x) | |
752 | if buf: | |
753 | return funex(COMPILE_TEMPLATE_SIG_VARS%'\n\t'.join(buf)) | |
754 | return None | |
755 | def task_factory(name,func=None,vars=None,color='GREEN',ext_in=[],ext_out=[],before=[],after=[],shell=False,scan=None): | |
756 | params={'vars':vars or[],'color':color,'name':name,'shell':shell,'scan':scan,} | |
757 | if isinstance(func,str)or isinstance(func,tuple): | |
758 | params['run_str']=func | |
759 | else: | |
760 | params['run']=func | |
761 | cls=type(Task)(name,(Task,),params) | |
762 | classes[name]=cls | |
763 | if ext_in: | |
764 | cls.ext_in=Utils.to_list(ext_in) | |
765 | if ext_out: | |
766 | cls.ext_out=Utils.to_list(ext_out) | |
767 | if before: | |
768 | cls.before=Utils.to_list(before) | |
769 | if after: | |
770 | cls.after=Utils.to_list(after) | |
771 | return cls | |
772 | def deep_inputs(cls): | |
773 | def sig_explicit_deps(self): | |
774 | Task.sig_explicit_deps(self) | |
775 | Task.sig_deep_inputs(self) | |
776 | cls.sig_explicit_deps=sig_explicit_deps | |
777 | return cls | |
778 | TaskBase=Task | |
779 | class TaskSemaphore(object): | |
780 | def __init__(self,num): | |
781 | self.num=num | |
782 | self.locking=set() | |
783 | self.waiting=set() | |
784 | def is_locked(self): | |
785 | return len(self.locking)>=self.num | |
786 | def acquire(self,tsk): | |
787 | if self.is_locked(): | |
788 | raise IndexError('Cannot lock more %r'%self.locking) | |
789 | self.locking.add(tsk) | |
790 | def release(self,tsk): | |
791 | self.locking.remove(tsk) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import copy,re,os,functools | |
5 | from waflib import Task,Utils,Logs,Errors,ConfigSet,Node | |
6 | feats=Utils.defaultdict(set) | |
7 | HEADER_EXTS=['.h','.hpp','.hxx','.hh'] | |
8 | class task_gen(object): | |
9 | mappings=Utils.ordered_iter_dict() | |
10 | prec=Utils.defaultdict(set) | |
11 | def __init__(self,*k,**kw): | |
12 | self.source=[] | |
13 | self.target='' | |
14 | self.meths=[] | |
15 | self.features=[] | |
16 | self.tasks=[] | |
17 | if not'bld'in kw: | |
18 | self.env=ConfigSet.ConfigSet() | |
19 | self.idx=0 | |
20 | self.path=None | |
21 | else: | |
22 | self.bld=kw['bld'] | |
23 | self.env=self.bld.env.derive() | |
24 | self.path=kw.get('path',self.bld.path) | |
25 | path=self.path.abspath() | |
26 | try: | |
27 | self.idx=self.bld.idx[path]=self.bld.idx.get(path,0)+1 | |
28 | except AttributeError: | |
29 | self.bld.idx={} | |
30 | self.idx=self.bld.idx[path]=1 | |
31 | try: | |
32 | self.tg_idx_count=self.bld.tg_idx_count=self.bld.tg_idx_count+1 | |
33 | except AttributeError: | |
34 | self.tg_idx_count=self.bld.tg_idx_count=1 | |
35 | for key,val in kw.items(): | |
36 | setattr(self,key,val) | |
37 | def __str__(self): | |
38 | return"<task_gen %r declared in %s>"%(self.name,self.path.abspath()) | |
39 | def __repr__(self): | |
40 | lst=[] | |
41 | for x in self.__dict__: | |
42 | if x not in('env','bld','compiled_tasks','tasks'): | |
43 | lst.append("%s=%s"%(x,repr(getattr(self,x)))) | |
44 | return"bld(%s) in %s"%(", ".join(lst),self.path.abspath()) | |
45 | def get_cwd(self): | |
46 | return self.bld.bldnode | |
47 | def get_name(self): | |
48 | try: | |
49 | return self._name | |
50 | except AttributeError: | |
51 | if isinstance(self.target,list): | |
52 | lst=[str(x)for x in self.target] | |
53 | name=self._name=','.join(lst) | |
54 | else: | |
55 | name=self._name=str(self.target) | |
56 | return name | |
57 | def set_name(self,name): | |
58 | self._name=name | |
59 | name=property(get_name,set_name) | |
60 | def to_list(self,val): | |
61 | if isinstance(val,str): | |
62 | return val.split() | |
63 | else: | |
64 | return val | |
65 | def post(self): | |
66 | if getattr(self,'posted',None): | |
67 | return False | |
68 | self.posted=True | |
69 | keys=set(self.meths) | |
70 | keys.update(feats['*']) | |
71 | self.features=Utils.to_list(self.features) | |
72 | for x in self.features: | |
73 | st=feats[x] | |
74 | if st: | |
75 | keys.update(st) | |
76 | elif not x in Task.classes: | |
77 | Logs.warn('feature %r does not exist - bind at least one method to it?',x) | |
78 | prec={} | |
79 | prec_tbl=self.prec | |
80 | for x in prec_tbl: | |
81 | if x in keys: | |
82 | prec[x]=prec_tbl[x] | |
83 | tmp=[] | |
84 | for a in keys: | |
85 | for x in prec.values(): | |
86 | if a in x: | |
87 | break | |
88 | else: | |
89 | tmp.append(a) | |
90 | tmp.sort(reverse=True) | |
91 | out=[] | |
92 | while tmp: | |
93 | e=tmp.pop() | |
94 | if e in keys: | |
95 | out.append(e) | |
96 | try: | |
97 | nlst=prec[e] | |
98 | except KeyError: | |
99 | pass | |
100 | else: | |
101 | del prec[e] | |
102 | for x in nlst: | |
103 | for y in prec: | |
104 | if x in prec[y]: | |
105 | break | |
106 | else: | |
107 | tmp.append(x) | |
108 | tmp.sort(reverse=True) | |
109 | if prec: | |
110 | buf=['Cycle detected in the method execution:'] | |
111 | for k,v in prec.items(): | |
112 | buf.append('- %s after %s'%(k,[x for x in v if x in prec])) | |
113 | raise Errors.WafError('\n'.join(buf)) | |
114 | self.meths=out | |
115 | Logs.debug('task_gen: posting %s %d',self,id(self)) | |
116 | for x in out: | |
117 | try: | |
118 | v=getattr(self,x) | |
119 | except AttributeError: | |
120 | raise Errors.WafError('%r is not a valid task generator method'%x) | |
121 | Logs.debug('task_gen: -> %s (%d)',x,id(self)) | |
122 | v() | |
123 | Logs.debug('task_gen: posted %s',self.name) | |
124 | return True | |
125 | def get_hook(self,node): | |
126 | name=node.name | |
127 | for k in self.mappings: | |
128 | try: | |
129 | if name.endswith(k): | |
130 | return self.mappings[k] | |
131 | except TypeError: | |
132 | if k.match(name): | |
133 | return self.mappings[k] | |
134 | keys=list(self.mappings.keys()) | |
135 | raise Errors.WafError("File %r has no mapping in %r (load a waf tool?)"%(node,keys)) | |
136 | def create_task(self,name,src=None,tgt=None,**kw): | |
137 | task=Task.classes[name](env=self.env.derive(),generator=self) | |
138 | if src: | |
139 | task.set_inputs(src) | |
140 | if tgt: | |
141 | task.set_outputs(tgt) | |
142 | task.__dict__.update(kw) | |
143 | self.tasks.append(task) | |
144 | return task | |
145 | def clone(self,env): | |
146 | newobj=self.bld() | |
147 | for x in self.__dict__: | |
148 | if x in('env','bld'): | |
149 | continue | |
150 | elif x in('path','features'): | |
151 | setattr(newobj,x,getattr(self,x)) | |
152 | else: | |
153 | setattr(newobj,x,copy.copy(getattr(self,x))) | |
154 | newobj.posted=False | |
155 | if isinstance(env,str): | |
156 | newobj.env=self.bld.all_envs[env].derive() | |
157 | else: | |
158 | newobj.env=env.derive() | |
159 | return newobj | |
160 | def declare_chain(name='',rule=None,reentrant=None,color='BLUE',ext_in=[],ext_out=[],before=[],after=[],decider=None,scan=None,install_path=None,shell=False): | |
161 | ext_in=Utils.to_list(ext_in) | |
162 | ext_out=Utils.to_list(ext_out) | |
163 | if not name: | |
164 | name=rule | |
165 | cls=Task.task_factory(name,rule,color=color,ext_in=ext_in,ext_out=ext_out,before=before,after=after,scan=scan,shell=shell) | |
166 | def x_file(self,node): | |
167 | if ext_in: | |
168 | _ext_in=ext_in[0] | |
169 | tsk=self.create_task(name,node) | |
170 | cnt=0 | |
171 | ext=decider(self,node)if decider else cls.ext_out | |
172 | for x in ext: | |
173 | k=node.change_ext(x,ext_in=_ext_in) | |
174 | tsk.outputs.append(k) | |
175 | if reentrant!=None: | |
176 | if cnt<int(reentrant): | |
177 | self.source.append(k) | |
178 | else: | |
179 | for y in self.mappings: | |
180 | if k.name.endswith(y): | |
181 | self.source.append(k) | |
182 | break | |
183 | cnt+=1 | |
184 | if install_path: | |
185 | self.install_task=self.add_install_files(install_to=install_path,install_from=tsk.outputs) | |
186 | return tsk | |
187 | for x in cls.ext_in: | |
188 | task_gen.mappings[x]=x_file | |
189 | return x_file | |
190 | def taskgen_method(func): | |
191 | setattr(task_gen,func.__name__,func) | |
192 | return func | |
193 | def feature(*k): | |
194 | def deco(func): | |
195 | setattr(task_gen,func.__name__,func) | |
196 | for name in k: | |
197 | feats[name].update([func.__name__]) | |
198 | return func | |
199 | return deco | |
200 | def before_method(*k): | |
201 | def deco(func): | |
202 | setattr(task_gen,func.__name__,func) | |
203 | for fun_name in k: | |
204 | task_gen.prec[func.__name__].add(fun_name) | |
205 | return func | |
206 | return deco | |
207 | before=before_method | |
208 | def after_method(*k): | |
209 | def deco(func): | |
210 | setattr(task_gen,func.__name__,func) | |
211 | for fun_name in k: | |
212 | task_gen.prec[fun_name].add(func.__name__) | |
213 | return func | |
214 | return deco | |
215 | after=after_method | |
216 | def extension(*k): | |
217 | def deco(func): | |
218 | setattr(task_gen,func.__name__,func) | |
219 | for x in k: | |
220 | task_gen.mappings[x]=func | |
221 | return func | |
222 | return deco | |
223 | @taskgen_method | |
224 | def to_nodes(self,lst,path=None): | |
225 | tmp=[] | |
226 | path=path or self.path | |
227 | find=path.find_resource | |
228 | if isinstance(lst,Node.Node): | |
229 | lst=[lst] | |
230 | for x in Utils.to_list(lst): | |
231 | if isinstance(x,str): | |
232 | node=find(x) | |
233 | elif hasattr(x,'name'): | |
234 | node=x | |
235 | else: | |
236 | tmp.extend(self.to_nodes(x)) | |
237 | continue | |
238 | if not node: | |
239 | raise Errors.WafError('source not found: %r in %r'%(x,self)) | |
240 | tmp.append(node) | |
241 | return tmp | |
242 | @feature('*') | |
243 | def process_source(self): | |
244 | self.source=self.to_nodes(getattr(self,'source',[])) | |
245 | for node in self.source: | |
246 | self.get_hook(node)(self,node) | |
247 | @feature('*') | |
248 | @before_method('process_source') | |
249 | def process_rule(self): | |
250 | if not getattr(self,'rule',None): | |
251 | return | |
252 | name=str(getattr(self,'name',None)or self.target or getattr(self.rule,'__name__',self.rule)) | |
253 | try: | |
254 | cache=self.bld.cache_rule_attr | |
255 | except AttributeError: | |
256 | cache=self.bld.cache_rule_attr={} | |
257 | chmod=getattr(self,'chmod',None) | |
258 | shell=getattr(self,'shell',True) | |
259 | color=getattr(self,'color','BLUE') | |
260 | scan=getattr(self,'scan',None) | |
261 | _vars=getattr(self,'vars',[]) | |
262 | cls_str=getattr(self,'cls_str',None) | |
263 | cls_keyword=getattr(self,'cls_keyword',None) | |
264 | use_cache=getattr(self,'cache_rule','True') | |
265 | deep_inputs=getattr(self,'deep_inputs',False) | |
266 | scan_val=has_deps=hasattr(self,'deps') | |
267 | if scan: | |
268 | scan_val=id(scan) | |
269 | key=Utils.h_list((name,self.rule,chmod,shell,color,cls_str,cls_keyword,scan_val,_vars,deep_inputs)) | |
270 | cls=None | |
271 | if use_cache: | |
272 | try: | |
273 | cls=cache[key] | |
274 | except KeyError: | |
275 | pass | |
276 | if not cls: | |
277 | rule=self.rule | |
278 | if chmod is not None: | |
279 | def chmod_fun(tsk): | |
280 | for x in tsk.outputs: | |
281 | os.chmod(x.abspath(),tsk.generator.chmod) | |
282 | if isinstance(rule,tuple): | |
283 | rule=list(rule) | |
284 | rule.append(chmod_fun) | |
285 | rule=tuple(rule) | |
286 | else: | |
287 | rule=(rule,chmod_fun) | |
288 | cls=Task.task_factory(name,rule,_vars,shell=shell,color=color) | |
289 | if cls_str: | |
290 | setattr(cls,'__str__',self.cls_str) | |
291 | if cls_keyword: | |
292 | setattr(cls,'keyword',self.cls_keyword) | |
293 | if deep_inputs: | |
294 | Task.deep_inputs(cls) | |
295 | if scan: | |
296 | cls.scan=self.scan | |
297 | elif has_deps: | |
298 | def scan(self): | |
299 | nodes=[] | |
300 | for x in self.generator.to_list(getattr(self.generator,'deps',None)): | |
301 | node=self.generator.path.find_resource(x) | |
302 | if not node: | |
303 | self.generator.bld.fatal('Could not find %r (was it declared?)'%x) | |
304 | nodes.append(node) | |
305 | return[nodes,[]] | |
306 | cls.scan=scan | |
307 | if use_cache: | |
308 | cache[key]=cls | |
309 | tsk=self.create_task(name) | |
310 | for x in('after','before','ext_in','ext_out'): | |
311 | setattr(tsk,x,getattr(self,x,[])) | |
312 | if hasattr(self,'stdout'): | |
313 | tsk.stdout=self.stdout | |
314 | if hasattr(self,'stderr'): | |
315 | tsk.stderr=self.stderr | |
316 | if getattr(self,'timeout',None): | |
317 | tsk.timeout=self.timeout | |
318 | if getattr(self,'always',None): | |
319 | tsk.always_run=True | |
320 | if getattr(self,'target',None): | |
321 | if isinstance(self.target,str): | |
322 | self.target=self.target.split() | |
323 | if not isinstance(self.target,list): | |
324 | self.target=[self.target] | |
325 | for x in self.target: | |
326 | if isinstance(x,str): | |
327 | tsk.outputs.append(self.path.find_or_declare(x)) | |
328 | else: | |
329 | x.parent.mkdir() | |
330 | tsk.outputs.append(x) | |
331 | if getattr(self,'install_path',None): | |
332 | self.install_task=self.add_install_files(install_to=self.install_path,install_from=tsk.outputs,chmod=getattr(self,'chmod',Utils.O644)) | |
333 | if getattr(self,'source',None): | |
334 | tsk.inputs=self.to_nodes(self.source) | |
335 | self.source=[] | |
336 | if getattr(self,'cwd',None): | |
337 | tsk.cwd=self.cwd | |
338 | if isinstance(tsk.run,functools.partial): | |
339 | tsk.run=functools.partial(tsk.run,tsk) | |
340 | @feature('seq') | |
341 | def sequence_order(self): | |
342 | if self.meths and self.meths[-1]!='sequence_order': | |
343 | self.meths.append('sequence_order') | |
344 | return | |
345 | if getattr(self,'seq_start',None): | |
346 | return | |
347 | if getattr(self.bld,'prev',None): | |
348 | self.bld.prev.post() | |
349 | for x in self.bld.prev.tasks: | |
350 | for y in self.tasks: | |
351 | y.set_run_after(x) | |
352 | self.bld.prev=self | |
353 | re_m4=re.compile(r'@(\w+)@',re.M) | |
354 | class subst_pc(Task.Task): | |
355 | def force_permissions(self): | |
356 | if getattr(self.generator,'chmod',None): | |
357 | for x in self.outputs: | |
358 | os.chmod(x.abspath(),self.generator.chmod) | |
359 | def run(self): | |
360 | if getattr(self.generator,'is_copy',None): | |
361 | for i,x in enumerate(self.outputs): | |
362 | x.write(self.inputs[i].read('rb'),'wb') | |
363 | stat=os.stat(self.inputs[i].abspath()) | |
364 | os.utime(self.outputs[i].abspath(),(stat.st_atime,stat.st_mtime)) | |
365 | self.force_permissions() | |
366 | return None | |
367 | if getattr(self.generator,'fun',None): | |
368 | ret=self.generator.fun(self) | |
369 | if not ret: | |
370 | self.force_permissions() | |
371 | return ret | |
372 | code=self.inputs[0].read(encoding=getattr(self.generator,'encoding','latin-1')) | |
373 | if getattr(self.generator,'subst_fun',None): | |
374 | code=self.generator.subst_fun(self,code) | |
375 | if code is not None: | |
376 | self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','latin-1')) | |
377 | self.force_permissions() | |
378 | return None | |
379 | code=code.replace('%','%%') | |
380 | lst=[] | |
381 | def repl(match): | |
382 | g=match.group | |
383 | if g(1): | |
384 | lst.append(g(1)) | |
385 | return"%%(%s)s"%g(1) | |
386 | return'' | |
387 | code=getattr(self.generator,'re_m4',re_m4).sub(repl,code) | |
388 | try: | |
389 | d=self.generator.dct | |
390 | except AttributeError: | |
391 | d={} | |
392 | for x in lst: | |
393 | tmp=getattr(self.generator,x,'')or self.env[x]or self.env[x.upper()] | |
394 | try: | |
395 | tmp=''.join(tmp) | |
396 | except TypeError: | |
397 | tmp=str(tmp) | |
398 | d[x]=tmp | |
399 | code=code%d | |
400 | self.outputs[0].write(code,encoding=getattr(self.generator,'encoding','latin-1')) | |
401 | self.generator.bld.raw_deps[self.uid()]=lst | |
402 | try: | |
403 | delattr(self,'cache_sig') | |
404 | except AttributeError: | |
405 | pass | |
406 | self.force_permissions() | |
407 | def sig_vars(self): | |
408 | bld=self.generator.bld | |
409 | env=self.env | |
410 | upd=self.m.update | |
411 | if getattr(self.generator,'fun',None): | |
412 | upd(Utils.h_fun(self.generator.fun).encode()) | |
413 | if getattr(self.generator,'subst_fun',None): | |
414 | upd(Utils.h_fun(self.generator.subst_fun).encode()) | |
415 | vars=self.generator.bld.raw_deps.get(self.uid(),[]) | |
416 | act_sig=bld.hash_env_vars(env,vars) | |
417 | upd(act_sig) | |
418 | lst=[getattr(self.generator,x,'')for x in vars] | |
419 | upd(Utils.h_list(lst)) | |
420 | return self.m.digest() | |
421 | @extension('.pc.in') | |
422 | def add_pcfile(self,node): | |
423 | tsk=self.create_task('subst_pc',node,node.change_ext('.pc','.pc.in')) | |
424 | self.install_task=self.add_install_files(install_to=getattr(self,'install_path','${LIBDIR}/pkgconfig/'),install_from=tsk.outputs) | |
425 | class subst(subst_pc): | |
426 | pass | |
427 | @feature('subst') | |
428 | @before_method('process_source','process_rule') | |
429 | def process_subst(self): | |
430 | src=Utils.to_list(getattr(self,'source',[])) | |
431 | if isinstance(src,Node.Node): | |
432 | src=[src] | |
433 | tgt=Utils.to_list(getattr(self,'target',[])) | |
434 | if isinstance(tgt,Node.Node): | |
435 | tgt=[tgt] | |
436 | if len(src)!=len(tgt): | |
437 | raise Errors.WafError('invalid number of source/target for %r'%self) | |
438 | for x,y in zip(src,tgt): | |
439 | if not x or not y: | |
440 | raise Errors.WafError('null source or target for %r'%self) | |
441 | a,b=None,None | |
442 | if isinstance(x,str)and isinstance(y,str)and x==y: | |
443 | a=self.path.find_node(x) | |
444 | b=self.path.get_bld().make_node(y) | |
445 | if not os.path.isfile(b.abspath()): | |
446 | b.parent.mkdir() | |
447 | else: | |
448 | if isinstance(x,str): | |
449 | a=self.path.find_resource(x) | |
450 | elif isinstance(x,Node.Node): | |
451 | a=x | |
452 | if isinstance(y,str): | |
453 | b=self.path.find_or_declare(y) | |
454 | elif isinstance(y,Node.Node): | |
455 | b=y | |
456 | if not a: | |
457 | raise Errors.WafError('could not find %r for %r'%(x,self)) | |
458 | tsk=self.create_task('subst',a,b) | |
459 | for k in('after','before','ext_in','ext_out'): | |
460 | val=getattr(self,k,None) | |
461 | if val: | |
462 | setattr(tsk,k,val) | |
463 | for xt in HEADER_EXTS: | |
464 | if b.name.endswith(xt): | |
465 | tsk.ext_out=tsk.ext_out+['.h'] | |
466 | break | |
467 | inst_to=getattr(self,'install_path',None) | |
468 | if inst_to: | |
469 | self.install_task=self.add_install_files(install_to=inst_to,install_from=b,chmod=getattr(self,'chmod',Utils.O644)) | |
470 | self.source=[] |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Configure import conf | |
5 | @conf | |
6 | def find_ar(conf): | |
7 | conf.load('ar') | |
8 | def configure(conf): | |
9 | conf.find_program('ar',var='AR') | |
10 | conf.add_os_flags('ARFLAGS') | |
11 | if not conf.env.ARFLAGS: | |
12 | conf.env.ARFLAGS=['rcs'] |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Errors,Logs,Task | |
6 | from waflib.Tools.ccroot import link_task,stlink_task | |
7 | from waflib.TaskGen import extension | |
8 | from waflib.Tools import c_preproc | |
9 | re_lines=re.compile('^[ \t]*(?:%)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef)[ \t]*(.*)\r*$',re.IGNORECASE|re.MULTILINE) | |
10 | class asm_parser(c_preproc.c_parser): | |
11 | def filter_comments(self,node): | |
12 | code=node.read() | |
13 | code=c_preproc.re_nl.sub('',code) | |
14 | code=c_preproc.re_cpp.sub(c_preproc.repl,code) | |
15 | return re_lines.findall(code) | |
16 | class asm(Task.Task): | |
17 | color='BLUE' | |
18 | run_str='${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' | |
19 | def scan(self): | |
20 | if self.env.ASM_NAME=='gas': | |
21 | return c_preproc.scan(self) | |
22 | Logs.warn('There is no dependency scanner for Nasm!') | |
23 | return[[],[]] | |
24 | elif self.env.ASM_NAME=='nasm': | |
25 | Logs.warn('The Nasm dependency scanner is incomplete!') | |
26 | try: | |
27 | incn=self.generator.includes_nodes | |
28 | except AttributeError: | |
29 | raise Errors.WafError('%r is missing the "asm" feature'%self.generator) | |
30 | if c_preproc.go_absolute: | |
31 | nodepaths=incn | |
32 | else: | |
33 | nodepaths=[x for x in incn if x.is_child_of(x.ctx.srcnode)or x.is_child_of(x.ctx.bldnode)] | |
34 | tmp=asm_parser(nodepaths) | |
35 | tmp.start(self.inputs[0],self.env) | |
36 | return(tmp.nodes,tmp.names) | |
37 | @extension('.s','.S','.asm','.ASM','.spp','.SPP') | |
38 | def asm_hook(self,node): | |
39 | return self.create_compiled_task('asm',node) | |
40 | class asmprogram(link_task): | |
41 | run_str='${ASLINK} ${ASLINKFLAGS} ${ASLNK_TGT_F}${TGT} ${ASLNK_SRC_F}${SRC}' | |
42 | ext_out=['.bin'] | |
43 | inst_to='${BINDIR}' | |
44 | class asmshlib(asmprogram): | |
45 | inst_to='${LIBDIR}' | |
46 | class asmstlib(stlink_task): | |
47 | pass | |
48 | def configure(conf): | |
49 | conf.env.ASMPATH_ST='-I%s' |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Task | |
5 | from waflib.TaskGen import extension | |
6 | class bison(Task.Task): | |
7 | color='BLUE' | |
8 | run_str='${BISON} ${BISONFLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}' | |
9 | ext_out=['.h'] | |
10 | @extension('.y','.yc','.yy') | |
11 | def big_bison(self,node): | |
12 | has_h='-d'in self.env.BISONFLAGS | |
13 | outs=[] | |
14 | if node.name.endswith('.yc'): | |
15 | outs.append(node.change_ext('.tab.cc')) | |
16 | if has_h: | |
17 | outs.append(node.change_ext('.tab.hh')) | |
18 | else: | |
19 | outs.append(node.change_ext('.tab.c')) | |
20 | if has_h: | |
21 | outs.append(node.change_ext('.tab.h')) | |
22 | tsk=self.create_task('bison',node,outs) | |
23 | tsk.cwd=node.parent.get_bld() | |
24 | self.source.append(outs[0]) | |
25 | def configure(conf): | |
26 | conf.find_program('bison',var='BISON') | |
27 | conf.env.BISONFLAGS=['-d'] |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import TaskGen,Task | |
5 | from waflib.Tools import c_preproc | |
6 | from waflib.Tools.ccroot import link_task,stlink_task | |
7 | @TaskGen.extension('.c') | |
8 | def c_hook(self,node): | |
9 | if not self.env.CC and self.env.CXX: | |
10 | return self.create_compiled_task('cxx',node) | |
11 | return self.create_compiled_task('c',node) | |
12 | class c(Task.Task): | |
13 | run_str='${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' | |
14 | vars=['CCDEPS'] | |
15 | ext_in=['.h'] | |
16 | scan=c_preproc.scan | |
17 | class cprogram(link_task): | |
18 | run_str='${LINK_CC} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' | |
19 | ext_out=['.bin'] | |
20 | vars=['LINKDEPS'] | |
21 | inst_to='${BINDIR}' | |
22 | class cshlib(cprogram): | |
23 | inst_to='${LIBDIR}' | |
24 | class cstlib(stlink_task): | |
25 | pass |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Utils,Errors | |
5 | from waflib.Configure import conf | |
6 | def get_extensions(lst): | |
7 | ret=[] | |
8 | for x in Utils.to_list(lst): | |
9 | if not isinstance(x,str): | |
10 | x=x.name | |
11 | ret.append(x[x.rfind('.')+1:]) | |
12 | return ret | |
13 | def sniff_features(**kw): | |
14 | exts=get_extensions(kw.get('source',[])) | |
15 | typ=kw['typ'] | |
16 | feats=[] | |
17 | for x in'cxx cpp c++ cc C'.split(): | |
18 | if x in exts: | |
19 | feats.append('cxx') | |
20 | break | |
21 | if'c'in exts or'vala'in exts or'gs'in exts: | |
22 | feats.append('c') | |
23 | if's'in exts or'S'in exts: | |
24 | feats.append('asm') | |
25 | for x in'f f90 F F90 for FOR'.split(): | |
26 | if x in exts: | |
27 | feats.append('fc') | |
28 | break | |
29 | if'd'in exts: | |
30 | feats.append('d') | |
31 | if'java'in exts: | |
32 | feats.append('java') | |
33 | return'java' | |
34 | if typ in('program','shlib','stlib'): | |
35 | will_link=False | |
36 | for x in feats: | |
37 | if x in('cxx','d','fc','c','asm'): | |
38 | feats.append(x+typ) | |
39 | will_link=True | |
40 | if not will_link and not kw.get('features',[]): | |
41 | raise Errors.WafError('Unable to determine how to link %r, try adding eg: features="c cshlib"?'%kw) | |
42 | return feats | |
43 | def set_features(kw,typ): | |
44 | kw['typ']=typ | |
45 | kw['features']=Utils.to_list(kw.get('features',[]))+Utils.to_list(sniff_features(**kw)) | |
46 | @conf | |
47 | def program(bld,*k,**kw): | |
48 | set_features(kw,'program') | |
49 | return bld(*k,**kw) | |
50 | @conf | |
51 | def shlib(bld,*k,**kw): | |
52 | set_features(kw,'shlib') | |
53 | return bld(*k,**kw) | |
54 | @conf | |
55 | def stlib(bld,*k,**kw): | |
56 | set_features(kw,'stlib') | |
57 | return bld(*k,**kw) | |
58 | @conf | |
59 | def objects(bld,*k,**kw): | |
60 | set_features(kw,'objects') | |
61 | return bld(*k,**kw) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from __future__ import with_statement | |
5 | import os,re,shlex | |
6 | from waflib import Build,Utils,Task,Options,Logs,Errors,Runner | |
7 | from waflib.TaskGen import after_method,feature | |
8 | from waflib.Configure import conf | |
9 | WAF_CONFIG_H='config.h' | |
10 | DEFKEYS='define_key' | |
11 | INCKEYS='include_key' | |
12 | SNIP_EMPTY_PROGRAM=''' | |
13 | int main(int argc, char **argv) { | |
14 | (void)argc; (void)argv; | |
15 | return 0; | |
16 | } | |
17 | ''' | |
18 | MACRO_TO_DESTOS={'__linux__':'linux','__GNU__':'gnu','__FreeBSD__':'freebsd','__NetBSD__':'netbsd','__OpenBSD__':'openbsd','__sun':'sunos','__hpux':'hpux','__sgi':'irix','_AIX':'aix','__CYGWIN__':'cygwin','__MSYS__':'cygwin','_UWIN':'uwin','_WIN64':'win32','_WIN32':'win32','__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__':'darwin','__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__':'darwin','__QNX__':'qnx','__native_client__':'nacl'} | |
19 | MACRO_TO_DEST_CPU={'__x86_64__':'x86_64','__amd64__':'x86_64','__i386__':'x86','__ia64__':'ia','__mips__':'mips','__sparc__':'sparc','__alpha__':'alpha','__aarch64__':'aarch64','__thumb__':'thumb','__arm__':'arm','__hppa__':'hppa','__powerpc__':'powerpc','__ppc__':'powerpc','__convex__':'convex','__m68k__':'m68k','__s390x__':'s390x','__s390__':'s390','__sh__':'sh','__xtensa__':'xtensa',} | |
20 | @conf | |
21 | def parse_flags(self,line,uselib_store,env=None,force_static=False,posix=None): | |
22 | assert(isinstance(line,str)) | |
23 | env=env or self.env | |
24 | if posix is None: | |
25 | posix=True | |
26 | if'\\'in line: | |
27 | posix=('\\ 'in line)or('\\\\'in line) | |
28 | lex=shlex.shlex(line,posix=posix) | |
29 | lex.whitespace_split=True | |
30 | lex.commenters='' | |
31 | lst=list(lex) | |
32 | so_re=re.compile(r"\.so(?:\.[0-9]+)*$") | |
33 | uselib=uselib_store | |
34 | def app(var,val): | |
35 | env.append_value('%s_%s'%(var,uselib),val) | |
36 | def appu(var,val): | |
37 | env.append_unique('%s_%s'%(var,uselib),val) | |
38 | static=False | |
39 | while lst: | |
40 | x=lst.pop(0) | |
41 | st=x[:2] | |
42 | ot=x[2:] | |
43 | if st=='-I'or st=='/I': | |
44 | if not ot: | |
45 | ot=lst.pop(0) | |
46 | appu('INCLUDES',ot) | |
47 | elif st=='-i': | |
48 | tmp=[x,lst.pop(0)] | |
49 | app('CFLAGS',tmp) | |
50 | app('CXXFLAGS',tmp) | |
51 | elif st=='-D'or(env.CXX_NAME=='msvc'and st=='/D'): | |
52 | if not ot: | |
53 | ot=lst.pop(0) | |
54 | app('DEFINES',ot) | |
55 | elif st=='-l': | |
56 | if not ot: | |
57 | ot=lst.pop(0) | |
58 | prefix='STLIB'if(force_static or static)else'LIB' | |
59 | app(prefix,ot) | |
60 | elif st=='-L': | |
61 | if not ot: | |
62 | ot=lst.pop(0) | |
63 | prefix='STLIBPATH'if(force_static or static)else'LIBPATH' | |
64 | appu(prefix,ot) | |
65 | elif x.startswith('/LIBPATH:'): | |
66 | prefix='STLIBPATH'if(force_static or static)else'LIBPATH' | |
67 | appu(prefix,x.replace('/LIBPATH:','')) | |
68 | elif x.startswith('-std='): | |
69 | prefix='CXXFLAGS'if'++'in x else'CFLAGS' | |
70 | app(prefix,x) | |
71 | elif x.startswith('+')or x in('-pthread','-fPIC','-fpic','-fPIE','-fpie'): | |
72 | app('CFLAGS',x) | |
73 | app('CXXFLAGS',x) | |
74 | app('LINKFLAGS',x) | |
75 | elif x=='-framework': | |
76 | appu('FRAMEWORK',lst.pop(0)) | |
77 | elif x.startswith('-F'): | |
78 | appu('FRAMEWORKPATH',x[2:]) | |
79 | elif x=='-Wl,-rpath'or x=='-Wl,-R': | |
80 | app('RPATH',lst.pop(0).lstrip('-Wl,')) | |
81 | elif x.startswith('-Wl,-R,'): | |
82 | app('RPATH',x[7:]) | |
83 | elif x.startswith('-Wl,-R'): | |
84 | app('RPATH',x[6:]) | |
85 | elif x.startswith('-Wl,-rpath,'): | |
86 | app('RPATH',x[11:]) | |
87 | elif x=='-Wl,-Bstatic'or x=='-Bstatic': | |
88 | static=True | |
89 | elif x=='-Wl,-Bdynamic'or x=='-Bdynamic': | |
90 | static=False | |
91 | elif x.startswith('-Wl')or x in('-rdynamic','-pie'): | |
92 | app('LINKFLAGS',x) | |
93 | elif x.startswith(('-m','-f','-dynamic','-O','-g')): | |
94 | app('CFLAGS',x) | |
95 | app('CXXFLAGS',x) | |
96 | elif x.startswith('-bundle'): | |
97 | app('LINKFLAGS',x) | |
98 | elif x.startswith(('-undefined','-Xlinker')): | |
99 | arg=lst.pop(0) | |
100 | app('LINKFLAGS',[x,arg]) | |
101 | elif x.startswith(('-arch','-isysroot')): | |
102 | tmp=[x,lst.pop(0)] | |
103 | app('CFLAGS',tmp) | |
104 | app('CXXFLAGS',tmp) | |
105 | app('LINKFLAGS',tmp) | |
106 | elif x.endswith(('.a','.dylib','.lib'))or so_re.search(x): | |
107 | appu('LINKFLAGS',x) | |
108 | else: | |
109 | self.to_log('Unhandled flag %r'%x) | |
110 | @conf | |
111 | def validate_cfg(self,kw): | |
112 | if not'path'in kw: | |
113 | if not self.env.PKGCONFIG: | |
114 | self.find_program('pkg-config',var='PKGCONFIG') | |
115 | kw['path']=self.env.PKGCONFIG | |
116 | s=('atleast_pkgconfig_version'in kw)+('modversion'in kw)+('package'in kw) | |
117 | if s!=1: | |
118 | raise ValueError('exactly one of atleast_pkgconfig_version, modversion and package must be set') | |
119 | if not'msg'in kw: | |
120 | if'atleast_pkgconfig_version'in kw: | |
121 | kw['msg']='Checking for pkg-config version >= %r'%kw['atleast_pkgconfig_version'] | |
122 | elif'modversion'in kw: | |
123 | kw['msg']='Checking for %r version'%kw['modversion'] | |
124 | else: | |
125 | kw['msg']='Checking for %r'%(kw['package']) | |
126 | if not'okmsg'in kw and not'modversion'in kw: | |
127 | kw['okmsg']='yes' | |
128 | if not'errmsg'in kw: | |
129 | kw['errmsg']='not found' | |
130 | if'atleast_pkgconfig_version'in kw: | |
131 | pass | |
132 | elif'modversion'in kw: | |
133 | if not'uselib_store'in kw: | |
134 | kw['uselib_store']=kw['modversion'] | |
135 | if not'define_name'in kw: | |
136 | kw['define_name']='%s_VERSION'%Utils.quote_define_name(kw['uselib_store']) | |
137 | else: | |
138 | if not'uselib_store'in kw: | |
139 | kw['uselib_store']=Utils.to_list(kw['package'])[0].upper() | |
140 | if not'define_name'in kw: | |
141 | kw['define_name']=self.have_define(kw['uselib_store']) | |
142 | @conf | |
143 | def exec_cfg(self,kw): | |
144 | path=Utils.to_list(kw['path']) | |
145 | env=self.env.env or None | |
146 | if kw.get('pkg_config_path'): | |
147 | if not env: | |
148 | env=dict(self.environ) | |
149 | env['PKG_CONFIG_PATH']=kw['pkg_config_path'] | |
150 | def define_it(): | |
151 | define_name=kw['define_name'] | |
152 | if kw.get('global_define',1): | |
153 | self.define(define_name,1,False) | |
154 | else: | |
155 | self.env.append_unique('DEFINES_%s'%kw['uselib_store'],"%s=1"%define_name) | |
156 | if kw.get('add_have_to_env',1): | |
157 | self.env[define_name]=1 | |
158 | if'atleast_pkgconfig_version'in kw: | |
159 | cmd=path+['--atleast-pkgconfig-version=%s'%kw['atleast_pkgconfig_version']] | |
160 | self.cmd_and_log(cmd,env=env) | |
161 | return | |
162 | if'modversion'in kw: | |
163 | version=self.cmd_and_log(path+['--modversion',kw['modversion']],env=env).strip() | |
164 | if not'okmsg'in kw: | |
165 | kw['okmsg']=version | |
166 | self.define(kw['define_name'],version) | |
167 | return version | |
168 | lst=[]+path | |
169 | defi=kw.get('define_variable') | |
170 | if not defi: | |
171 | defi=self.env.PKG_CONFIG_DEFINES or{} | |
172 | for key,val in defi.items(): | |
173 | lst.append('--define-variable=%s=%s'%(key,val)) | |
174 | static=kw.get('force_static',False) | |
175 | if'args'in kw: | |
176 | args=Utils.to_list(kw['args']) | |
177 | if'--static'in args or'--static-libs'in args: | |
178 | static=True | |
179 | lst+=args | |
180 | lst.extend(Utils.to_list(kw['package'])) | |
181 | if'variables'in kw: | |
182 | v_env=kw.get('env',self.env) | |
183 | vars=Utils.to_list(kw['variables']) | |
184 | for v in vars: | |
185 | val=self.cmd_and_log(lst+['--variable='+v],env=env).strip() | |
186 | var='%s_%s'%(kw['uselib_store'],v) | |
187 | v_env[var]=val | |
188 | return | |
189 | ret=self.cmd_and_log(lst,env=env) | |
190 | define_it() | |
191 | self.parse_flags(ret,kw['uselib_store'],kw.get('env',self.env),force_static=static,posix=kw.get('posix')) | |
192 | return ret | |
193 | @conf | |
194 | def check_cfg(self,*k,**kw): | |
195 | self.validate_cfg(kw) | |
196 | if'msg'in kw: | |
197 | self.start_msg(kw['msg'],**kw) | |
198 | ret=None | |
199 | try: | |
200 | ret=self.exec_cfg(kw) | |
201 | except self.errors.WafError as e: | |
202 | if'errmsg'in kw: | |
203 | self.end_msg(kw['errmsg'],'YELLOW',**kw) | |
204 | if Logs.verbose>1: | |
205 | self.to_log('Command failure: %s'%e) | |
206 | self.fatal('The configuration failed') | |
207 | else: | |
208 | if not ret: | |
209 | ret=True | |
210 | kw['success']=ret | |
211 | if'okmsg'in kw: | |
212 | self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw) | |
213 | return ret | |
214 | def build_fun(bld): | |
215 | if bld.kw['compile_filename']: | |
216 | node=bld.srcnode.make_node(bld.kw['compile_filename']) | |
217 | node.write(bld.kw['code']) | |
218 | o=bld(features=bld.kw['features'],source=bld.kw['compile_filename'],target='testprog') | |
219 | for k,v in bld.kw.items(): | |
220 | setattr(o,k,v) | |
221 | if not bld.kw.get('quiet'): | |
222 | bld.conf.to_log("==>\n%s\n<=="%bld.kw['code']) | |
223 | @conf | |
224 | def validate_c(self,kw): | |
225 | for x in('type_name','field_name','function_name'): | |
226 | if x in kw: | |
227 | Logs.warn('Invalid argument %r in test'%x) | |
228 | if not'build_fun'in kw: | |
229 | kw['build_fun']=build_fun | |
230 | if not'env'in kw: | |
231 | kw['env']=self.env.derive() | |
232 | env=kw['env'] | |
233 | if not'compiler'in kw and not'features'in kw: | |
234 | kw['compiler']='c' | |
235 | if env.CXX_NAME and Task.classes.get('cxx'): | |
236 | kw['compiler']='cxx' | |
237 | if not self.env.CXX: | |
238 | self.fatal('a c++ compiler is required') | |
239 | else: | |
240 | if not self.env.CC: | |
241 | self.fatal('a c compiler is required') | |
242 | if not'compile_mode'in kw: | |
243 | kw['compile_mode']='c' | |
244 | if'cxx'in Utils.to_list(kw.get('features',[]))or kw.get('compiler')=='cxx': | |
245 | kw['compile_mode']='cxx' | |
246 | if not'type'in kw: | |
247 | kw['type']='cprogram' | |
248 | if not'features'in kw: | |
249 | if not'header_name'in kw or kw.get('link_header_test',True): | |
250 | kw['features']=[kw['compile_mode'],kw['type']] | |
251 | else: | |
252 | kw['features']=[kw['compile_mode']] | |
253 | else: | |
254 | kw['features']=Utils.to_list(kw['features']) | |
255 | if not'compile_filename'in kw: | |
256 | kw['compile_filename']='test.c'+((kw['compile_mode']=='cxx')and'pp'or'') | |
257 | def to_header(dct): | |
258 | if'header_name'in dct: | |
259 | dct=Utils.to_list(dct['header_name']) | |
260 | return''.join(['#include <%s>\n'%x for x in dct]) | |
261 | return'' | |
262 | if'framework_name'in kw: | |
263 | fwkname=kw['framework_name'] | |
264 | if not'uselib_store'in kw: | |
265 | kw['uselib_store']=fwkname.upper() | |
266 | if not kw.get('no_header'): | |
267 | fwk='%s/%s.h'%(fwkname,fwkname) | |
268 | if kw.get('remove_dot_h'): | |
269 | fwk=fwk[:-2] | |
270 | val=kw.get('header_name',[]) | |
271 | kw['header_name']=Utils.to_list(val)+[fwk] | |
272 | kw['msg']='Checking for framework %s'%fwkname | |
273 | kw['framework']=fwkname | |
274 | elif'header_name'in kw: | |
275 | if not'msg'in kw: | |
276 | kw['msg']='Checking for header %s'%kw['header_name'] | |
277 | l=Utils.to_list(kw['header_name']) | |
278 | assert len(l),'list of headers in header_name is empty' | |
279 | kw['code']=to_header(kw)+SNIP_EMPTY_PROGRAM | |
280 | if not'uselib_store'in kw: | |
281 | kw['uselib_store']=l[0].upper() | |
282 | if not'define_name'in kw: | |
283 | kw['define_name']=self.have_define(l[0]) | |
284 | if'lib'in kw: | |
285 | if not'msg'in kw: | |
286 | kw['msg']='Checking for library %s'%kw['lib'] | |
287 | if not'uselib_store'in kw: | |
288 | kw['uselib_store']=kw['lib'].upper() | |
289 | if'stlib'in kw: | |
290 | if not'msg'in kw: | |
291 | kw['msg']='Checking for static library %s'%kw['stlib'] | |
292 | if not'uselib_store'in kw: | |
293 | kw['uselib_store']=kw['stlib'].upper() | |
294 | if'fragment'in kw: | |
295 | kw['code']=kw['fragment'] | |
296 | if not'msg'in kw: | |
297 | kw['msg']='Checking for code snippet' | |
298 | if not'errmsg'in kw: | |
299 | kw['errmsg']='no' | |
300 | for(flagsname,flagstype)in(('cxxflags','compiler'),('cflags','compiler'),('linkflags','linker')): | |
301 | if flagsname in kw: | |
302 | if not'msg'in kw: | |
303 | kw['msg']='Checking for %s flags %s'%(flagstype,kw[flagsname]) | |
304 | if not'errmsg'in kw: | |
305 | kw['errmsg']='no' | |
306 | if not'execute'in kw: | |
307 | kw['execute']=False | |
308 | if kw['execute']: | |
309 | kw['features'].append('test_exec') | |
310 | kw['chmod']=Utils.O755 | |
311 | if not'errmsg'in kw: | |
312 | kw['errmsg']='not found' | |
313 | if not'okmsg'in kw: | |
314 | kw['okmsg']='yes' | |
315 | if not'code'in kw: | |
316 | kw['code']=SNIP_EMPTY_PROGRAM | |
317 | if self.env[INCKEYS]: | |
318 | kw['code']='\n'.join(['#include <%s>'%x for x in self.env[INCKEYS]])+'\n'+kw['code'] | |
319 | if kw.get('merge_config_header')or env.merge_config_header: | |
320 | kw['code']='%s\n\n%s'%(self.get_config_header(),kw['code']) | |
321 | env.DEFINES=[] | |
322 | if not kw.get('success'): | |
323 | kw['success']=None | |
324 | if'define_name'in kw: | |
325 | self.undefine(kw['define_name']) | |
326 | if not'msg'in kw: | |
327 | self.fatal('missing "msg" in conf.check(...)') | |
328 | @conf | |
329 | def post_check(self,*k,**kw): | |
330 | is_success=0 | |
331 | if kw['execute']: | |
332 | if kw['success']is not None: | |
333 | if kw.get('define_ret'): | |
334 | is_success=kw['success'] | |
335 | else: | |
336 | is_success=(kw['success']==0) | |
337 | else: | |
338 | is_success=(kw['success']==0) | |
339 | if kw.get('define_name'): | |
340 | comment=kw.get('comment','') | |
341 | define_name=kw['define_name'] | |
342 | if kw['execute']and kw.get('define_ret')and isinstance(is_success,str): | |
343 | if kw.get('global_define',1): | |
344 | self.define(define_name,is_success,quote=kw.get('quote',1),comment=comment) | |
345 | else: | |
346 | if kw.get('quote',1): | |
347 | succ='"%s"'%is_success | |
348 | else: | |
349 | succ=int(is_success) | |
350 | val='%s=%s'%(define_name,succ) | |
351 | var='DEFINES_%s'%kw['uselib_store'] | |
352 | self.env.append_value(var,val) | |
353 | else: | |
354 | if kw.get('global_define',1): | |
355 | self.define_cond(define_name,is_success,comment=comment) | |
356 | else: | |
357 | var='DEFINES_%s'%kw['uselib_store'] | |
358 | self.env.append_value(var,'%s=%s'%(define_name,int(is_success))) | |
359 | if kw.get('add_have_to_env',1): | |
360 | if kw.get('uselib_store'): | |
361 | self.env[self.have_define(kw['uselib_store'])]=1 | |
362 | elif kw['execute']and kw.get('define_ret'): | |
363 | self.env[define_name]=is_success | |
364 | else: | |
365 | self.env[define_name]=int(is_success) | |
366 | if'header_name'in kw: | |
367 | if kw.get('auto_add_header_name'): | |
368 | self.env.append_value(INCKEYS,Utils.to_list(kw['header_name'])) | |
369 | if is_success and'uselib_store'in kw: | |
370 | from waflib.Tools import ccroot | |
371 | _vars=set() | |
372 | for x in kw['features']: | |
373 | if x in ccroot.USELIB_VARS: | |
374 | _vars|=ccroot.USELIB_VARS[x] | |
375 | for k in _vars: | |
376 | x=k.lower() | |
377 | if x in kw: | |
378 | self.env.append_value(k+'_'+kw['uselib_store'],kw[x]) | |
379 | return is_success | |
380 | @conf | |
381 | def check(self,*k,**kw): | |
382 | self.validate_c(kw) | |
383 | self.start_msg(kw['msg'],**kw) | |
384 | ret=None | |
385 | try: | |
386 | ret=self.run_build(*k,**kw) | |
387 | except self.errors.ConfigurationError: | |
388 | self.end_msg(kw['errmsg'],'YELLOW',**kw) | |
389 | if Logs.verbose>1: | |
390 | raise | |
391 | else: | |
392 | self.fatal('The configuration failed') | |
393 | else: | |
394 | kw['success']=ret | |
395 | ret=self.post_check(*k,**kw) | |
396 | if not ret: | |
397 | self.end_msg(kw['errmsg'],'YELLOW',**kw) | |
398 | self.fatal('The configuration failed %r'%ret) | |
399 | else: | |
400 | self.end_msg(self.ret_msg(kw['okmsg'],kw),**kw) | |
401 | return ret | |
402 | class test_exec(Task.Task): | |
403 | color='PINK' | |
404 | def run(self): | |
405 | cmd=[self.inputs[0].abspath()]+getattr(self.generator,'test_args',[]) | |
406 | if getattr(self.generator,'rpath',None): | |
407 | if getattr(self.generator,'define_ret',False): | |
408 | self.generator.bld.retval=self.generator.bld.cmd_and_log(cmd) | |
409 | else: | |
410 | self.generator.bld.retval=self.generator.bld.exec_command(cmd) | |
411 | else: | |
412 | env=self.env.env or{} | |
413 | env.update(dict(os.environ)) | |
414 | for var in('LD_LIBRARY_PATH','DYLD_LIBRARY_PATH','PATH'): | |
415 | env[var]=self.inputs[0].parent.abspath()+os.path.pathsep+env.get(var,'') | |
416 | if getattr(self.generator,'define_ret',False): | |
417 | self.generator.bld.retval=self.generator.bld.cmd_and_log(cmd,env=env) | |
418 | else: | |
419 | self.generator.bld.retval=self.generator.bld.exec_command(cmd,env=env) | |
420 | @feature('test_exec') | |
421 | @after_method('apply_link') | |
422 | def test_exec_fun(self): | |
423 | self.create_task('test_exec',self.link_task.outputs[0]) | |
424 | @conf | |
425 | def check_cxx(self,*k,**kw): | |
426 | kw['compiler']='cxx' | |
427 | return self.check(*k,**kw) | |
428 | @conf | |
429 | def check_cc(self,*k,**kw): | |
430 | kw['compiler']='c' | |
431 | return self.check(*k,**kw) | |
432 | @conf | |
433 | def set_define_comment(self,key,comment): | |
434 | coms=self.env.DEFINE_COMMENTS | |
435 | if not coms: | |
436 | coms=self.env.DEFINE_COMMENTS={} | |
437 | coms[key]=comment or'' | |
438 | @conf | |
439 | def get_define_comment(self,key): | |
440 | coms=self.env.DEFINE_COMMENTS or{} | |
441 | return coms.get(key,'') | |
442 | @conf | |
443 | def define(self,key,val,quote=True,comment=''): | |
444 | assert isinstance(key,str) | |
445 | if not key: | |
446 | return | |
447 | if val is True: | |
448 | val=1 | |
449 | elif val in(False,None): | |
450 | val=0 | |
451 | if isinstance(val,int)or isinstance(val,float): | |
452 | s='%s=%s' | |
453 | else: | |
454 | s=quote and'%s="%s"'or'%s=%s' | |
455 | app=s%(key,str(val)) | |
456 | ban=key+'=' | |
457 | lst=self.env.DEFINES | |
458 | for x in lst: | |
459 | if x.startswith(ban): | |
460 | lst[lst.index(x)]=app | |
461 | break | |
462 | else: | |
463 | self.env.append_value('DEFINES',app) | |
464 | self.env.append_unique(DEFKEYS,key) | |
465 | self.set_define_comment(key,comment) | |
466 | @conf | |
467 | def undefine(self,key,comment=''): | |
468 | assert isinstance(key,str) | |
469 | if not key: | |
470 | return | |
471 | ban=key+'=' | |
472 | lst=[x for x in self.env.DEFINES if not x.startswith(ban)] | |
473 | self.env.DEFINES=lst | |
474 | self.env.append_unique(DEFKEYS,key) | |
475 | self.set_define_comment(key,comment) | |
476 | @conf | |
477 | def define_cond(self,key,val,comment=''): | |
478 | assert isinstance(key,str) | |
479 | if not key: | |
480 | return | |
481 | if val: | |
482 | self.define(key,1,comment=comment) | |
483 | else: | |
484 | self.undefine(key,comment=comment) | |
485 | @conf | |
486 | def is_defined(self,key): | |
487 | assert key and isinstance(key,str) | |
488 | ban=key+'=' | |
489 | for x in self.env.DEFINES: | |
490 | if x.startswith(ban): | |
491 | return True | |
492 | return False | |
493 | @conf | |
494 | def get_define(self,key): | |
495 | assert key and isinstance(key,str) | |
496 | ban=key+'=' | |
497 | for x in self.env.DEFINES: | |
498 | if x.startswith(ban): | |
499 | return x[len(ban):] | |
500 | return None | |
501 | @conf | |
502 | def have_define(self,key): | |
503 | return(self.env.HAVE_PAT or'HAVE_%s')%Utils.quote_define_name(key) | |
504 | @conf | |
505 | def write_config_header(self,configfile='',guard='',top=False,defines=True,headers=False,remove=True,define_prefix=''): | |
506 | if not configfile: | |
507 | configfile=WAF_CONFIG_H | |
508 | waf_guard=guard or'W_%s_WAF'%Utils.quote_define_name(configfile) | |
509 | node=top and self.bldnode or self.path.get_bld() | |
510 | node=node.make_node(configfile) | |
511 | node.parent.mkdir() | |
512 | lst=['/* WARNING! All changes made to this file will be lost! */\n'] | |
513 | lst.append('#ifndef %s\n#define %s\n'%(waf_guard,waf_guard)) | |
514 | lst.append(self.get_config_header(defines,headers,define_prefix=define_prefix)) | |
515 | lst.append('\n#endif /* %s */\n'%waf_guard) | |
516 | node.write('\n'.join(lst)) | |
517 | self.env.append_unique(Build.CFG_FILES,[node.abspath()]) | |
518 | if remove: | |
519 | for key in self.env[DEFKEYS]: | |
520 | self.undefine(key) | |
521 | self.env[DEFKEYS]=[] | |
522 | @conf | |
523 | def get_config_header(self,defines=True,headers=False,define_prefix=''): | |
524 | lst=[] | |
525 | if self.env.WAF_CONFIG_H_PRELUDE: | |
526 | lst.append(self.env.WAF_CONFIG_H_PRELUDE) | |
527 | if headers: | |
528 | for x in self.env[INCKEYS]: | |
529 | lst.append('#include <%s>'%x) | |
530 | if defines: | |
531 | tbl={} | |
532 | for k in self.env.DEFINES: | |
533 | a,_,b=k.partition('=') | |
534 | tbl[a]=b | |
535 | for k in self.env[DEFKEYS]: | |
536 | caption=self.get_define_comment(k) | |
537 | if caption: | |
538 | caption=' /* %s */'%caption | |
539 | try: | |
540 | txt='#define %s%s %s%s'%(define_prefix,k,tbl[k],caption) | |
541 | except KeyError: | |
542 | txt='/* #undef %s%s */%s'%(define_prefix,k,caption) | |
543 | lst.append(txt) | |
544 | return"\n".join(lst) | |
545 | @conf | |
546 | def cc_add_flags(conf): | |
547 | conf.add_os_flags('CPPFLAGS',dup=False) | |
548 | conf.add_os_flags('CFLAGS',dup=False) | |
549 | @conf | |
550 | def cxx_add_flags(conf): | |
551 | conf.add_os_flags('CPPFLAGS',dup=False) | |
552 | conf.add_os_flags('CXXFLAGS',dup=False) | |
553 | @conf | |
554 | def link_add_flags(conf): | |
555 | conf.add_os_flags('LINKFLAGS',dup=False) | |
556 | conf.add_os_flags('LDFLAGS',dup=False) | |
557 | @conf | |
558 | def cc_load_tools(conf): | |
559 | if not conf.env.DEST_OS: | |
560 | conf.env.DEST_OS=Utils.unversioned_sys_platform() | |
561 | conf.load('c') | |
562 | @conf | |
563 | def cxx_load_tools(conf): | |
564 | if not conf.env.DEST_OS: | |
565 | conf.env.DEST_OS=Utils.unversioned_sys_platform() | |
566 | conf.load('cxx') | |
567 | @conf | |
568 | def get_cc_version(conf,cc,gcc=False,icc=False,clang=False): | |
569 | cmd=cc+['-dM','-E','-'] | |
570 | env=conf.env.env or None | |
571 | try: | |
572 | out,err=conf.cmd_and_log(cmd,output=0,input='\n'.encode(),env=env) | |
573 | except Errors.WafError: | |
574 | conf.fatal('Could not determine the compiler version %r'%cmd) | |
575 | if gcc: | |
576 | if out.find('__INTEL_COMPILER')>=0: | |
577 | conf.fatal('The intel compiler pretends to be gcc') | |
578 | if out.find('__GNUC__')<0 and out.find('__clang__')<0: | |
579 | conf.fatal('Could not determine the compiler type') | |
580 | if icc and out.find('__INTEL_COMPILER')<0: | |
581 | conf.fatal('Not icc/icpc') | |
582 | if clang and out.find('__clang__')<0: | |
583 | conf.fatal('Not clang/clang++') | |
584 | if not clang and out.find('__clang__')>=0: | |
585 | conf.fatal('Could not find gcc/g++ (only Clang), if renamed try eg: CC=gcc48 CXX=g++48 waf configure') | |
586 | k={} | |
587 | if icc or gcc or clang: | |
588 | out=out.splitlines() | |
589 | for line in out: | |
590 | lst=shlex.split(line) | |
591 | if len(lst)>2: | |
592 | key=lst[1] | |
593 | val=lst[2] | |
594 | k[key]=val | |
595 | def isD(var): | |
596 | return var in k | |
597 | if not conf.env.DEST_OS: | |
598 | conf.env.DEST_OS='' | |
599 | for i in MACRO_TO_DESTOS: | |
600 | if isD(i): | |
601 | conf.env.DEST_OS=MACRO_TO_DESTOS[i] | |
602 | break | |
603 | else: | |
604 | if isD('__APPLE__')and isD('__MACH__'): | |
605 | conf.env.DEST_OS='darwin' | |
606 | elif isD('__unix__'): | |
607 | conf.env.DEST_OS='generic' | |
608 | if isD('__ELF__'): | |
609 | conf.env.DEST_BINFMT='elf' | |
610 | elif isD('__WINNT__')or isD('__CYGWIN__')or isD('_WIN32'): | |
611 | conf.env.DEST_BINFMT='pe' | |
612 | if not conf.env.IMPLIBDIR: | |
613 | conf.env.IMPLIBDIR=conf.env.LIBDIR | |
614 | conf.env.LIBDIR=conf.env.BINDIR | |
615 | elif isD('__APPLE__'): | |
616 | conf.env.DEST_BINFMT='mac-o' | |
617 | if not conf.env.DEST_BINFMT: | |
618 | conf.env.DEST_BINFMT=Utils.destos_to_binfmt(conf.env.DEST_OS) | |
619 | for i in MACRO_TO_DEST_CPU: | |
620 | if isD(i): | |
621 | conf.env.DEST_CPU=MACRO_TO_DEST_CPU[i] | |
622 | break | |
623 | Logs.debug('ccroot: dest platform: '+' '.join([conf.env[x]or'?'for x in('DEST_OS','DEST_BINFMT','DEST_CPU')])) | |
624 | if icc: | |
625 | ver=k['__INTEL_COMPILER'] | |
626 | conf.env.CC_VERSION=(ver[:-2],ver[-2],ver[-1]) | |
627 | else: | |
628 | if isD('__clang__')and isD('__clang_major__'): | |
629 | conf.env.CC_VERSION=(k['__clang_major__'],k['__clang_minor__'],k['__clang_patchlevel__']) | |
630 | else: | |
631 | conf.env.CC_VERSION=(k['__GNUC__'],k['__GNUC_MINOR__'],k.get('__GNUC_PATCHLEVEL__','0')) | |
632 | return k | |
633 | @conf | |
634 | def get_xlc_version(conf,cc): | |
635 | cmd=cc+['-qversion'] | |
636 | try: | |
637 | out,err=conf.cmd_and_log(cmd,output=0) | |
638 | except Errors.WafError: | |
639 | conf.fatal('Could not find xlc %r'%cmd) | |
640 | for v in(r"IBM XL C/C\+\+.* V(?P<major>\d*)\.(?P<minor>\d*)",): | |
641 | version_re=re.compile(v,re.I).search | |
642 | match=version_re(out or err) | |
643 | if match: | |
644 | k=match.groupdict() | |
645 | conf.env.CC_VERSION=(k['major'],k['minor']) | |
646 | break | |
647 | else: | |
648 | conf.fatal('Could not determine the XLC version.') | |
649 | @conf | |
650 | def get_suncc_version(conf,cc): | |
651 | cmd=cc+['-V'] | |
652 | try: | |
653 | out,err=conf.cmd_and_log(cmd,output=0) | |
654 | except Errors.WafError as e: | |
655 | if not(hasattr(e,'returncode')and hasattr(e,'stdout')and hasattr(e,'stderr')): | |
656 | conf.fatal('Could not find suncc %r'%cmd) | |
657 | out=e.stdout | |
658 | err=e.stderr | |
659 | version=(out or err) | |
660 | version=version.splitlines()[0] | |
661 | version_re=re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P<major>\d*)\.(?P<minor>\d*)',re.I).search | |
662 | match=version_re(version) | |
663 | if match: | |
664 | k=match.groupdict() | |
665 | conf.env.CC_VERSION=(k['major'],k['minor']) | |
666 | else: | |
667 | conf.fatal('Could not determine the suncc version.') | |
668 | @conf | |
669 | def add_as_needed(self): | |
670 | if self.env.DEST_BINFMT=='elf'and'gcc'in(self.env.CXX_NAME,self.env.CC_NAME): | |
671 | self.env.append_unique('LINKFLAGS','-Wl,--as-needed') | |
672 | class cfgtask(Task.Task): | |
673 | def __init__(self,*k,**kw): | |
674 | Task.Task.__init__(self,*k,**kw) | |
675 | self.run_after=set() | |
676 | def display(self): | |
677 | return'' | |
678 | def runnable_status(self): | |
679 | for x in self.run_after: | |
680 | if not x.hasrun: | |
681 | return Task.ASK_LATER | |
682 | return Task.RUN_ME | |
683 | def uid(self): | |
684 | return Utils.SIG_NIL | |
685 | def signature(self): | |
686 | return Utils.SIG_NIL | |
687 | def run(self): | |
688 | conf=self.conf | |
689 | bld=Build.BuildContext(top_dir=conf.srcnode.abspath(),out_dir=conf.bldnode.abspath()) | |
690 | bld.env=conf.env | |
691 | bld.init_dirs() | |
692 | bld.in_msg=1 | |
693 | bld.logger=self.logger | |
694 | bld.multicheck_task=self | |
695 | args=self.args | |
696 | try: | |
697 | if'func'in args: | |
698 | bld.test(build_fun=args['func'],msg=args.get('msg',''),okmsg=args.get('okmsg',''),errmsg=args.get('errmsg',''),) | |
699 | else: | |
700 | args['multicheck_mandatory']=args.get('mandatory',True) | |
701 | args['mandatory']=True | |
702 | try: | |
703 | bld.check(**args) | |
704 | finally: | |
705 | args['mandatory']=args['multicheck_mandatory'] | |
706 | except Exception: | |
707 | return 1 | |
708 | def process(self): | |
709 | Task.Task.process(self) | |
710 | if'msg'in self.args: | |
711 | with self.generator.bld.multicheck_lock: | |
712 | self.conf.start_msg(self.args['msg']) | |
713 | if self.hasrun==Task.NOT_RUN: | |
714 | self.conf.end_msg('test cancelled','YELLOW') | |
715 | elif self.hasrun!=Task.SUCCESS: | |
716 | self.conf.end_msg(self.args.get('errmsg','no'),'YELLOW') | |
717 | else: | |
718 | self.conf.end_msg(self.args.get('okmsg','yes'),'GREEN') | |
719 | @conf | |
720 | def multicheck(self,*k,**kw): | |
721 | self.start_msg(kw.get('msg','Executing %d configuration tests'%len(k)),**kw) | |
722 | for var in('DEFINES',DEFKEYS): | |
723 | self.env.append_value(var,[]) | |
724 | self.env.DEFINE_COMMENTS=self.env.DEFINE_COMMENTS or{} | |
725 | class par(object): | |
726 | def __init__(self): | |
727 | self.keep=False | |
728 | self.task_sigs={} | |
729 | self.progress_bar=0 | |
730 | def total(self): | |
731 | return len(tasks) | |
732 | def to_log(self,*k,**kw): | |
733 | return | |
734 | bld=par() | |
735 | bld.keep=kw.get('run_all_tests',True) | |
736 | bld.imp_sigs={} | |
737 | tasks=[] | |
738 | id_to_task={} | |
739 | for dct in k: | |
740 | x=Task.classes['cfgtask'](bld=bld,env=None) | |
741 | tasks.append(x) | |
742 | x.args=dct | |
743 | x.bld=bld | |
744 | x.conf=self | |
745 | x.args=dct | |
746 | x.logger=Logs.make_mem_logger(str(id(x)),self.logger) | |
747 | if'id'in dct: | |
748 | id_to_task[dct['id']]=x | |
749 | for x in tasks: | |
750 | for key in Utils.to_list(x.args.get('before_tests',[])): | |
751 | tsk=id_to_task[key] | |
752 | if not tsk: | |
753 | raise ValueError('No test named %r'%key) | |
754 | tsk.run_after.add(x) | |
755 | for key in Utils.to_list(x.args.get('after_tests',[])): | |
756 | tsk=id_to_task[key] | |
757 | if not tsk: | |
758 | raise ValueError('No test named %r'%key) | |
759 | x.run_after.add(tsk) | |
760 | def it(): | |
761 | yield tasks | |
762 | while 1: | |
763 | yield[] | |
764 | bld.producer=p=Runner.Parallel(bld,Options.options.jobs) | |
765 | bld.multicheck_lock=Utils.threading.Lock() | |
766 | p.biter=it() | |
767 | self.end_msg('started') | |
768 | p.start() | |
769 | for x in tasks: | |
770 | x.logger.memhandler.flush() | |
771 | self.start_msg('-> processing test results') | |
772 | if p.error: | |
773 | for x in p.error: | |
774 | if getattr(x,'err_msg',None): | |
775 | self.to_log(x.err_msg) | |
776 | self.end_msg('fail',color='RED') | |
777 | raise Errors.WafError('There is an error in the library, read config.log for more information') | |
778 | failure_count=0 | |
779 | for x in tasks: | |
780 | if x.hasrun not in(Task.SUCCESS,Task.NOT_RUN): | |
781 | failure_count+=1 | |
782 | if failure_count: | |
783 | self.end_msg(kw.get('errmsg','%s test failed'%failure_count),color='YELLOW',**kw) | |
784 | else: | |
785 | self.end_msg('all ok',**kw) | |
786 | for x in tasks: | |
787 | if x.hasrun!=Task.SUCCESS: | |
788 | if x.args.get('mandatory',True): | |
789 | self.fatal(kw.get('fatalmsg')or'One of the tests has failed, read config.log for more information') | |
790 | @conf | |
791 | def check_gcc_o_space(self,mode='c'): | |
792 | if int(self.env.CC_VERSION[0])>4: | |
793 | return | |
794 | self.env.stash() | |
795 | if mode=='c': | |
796 | self.env.CCLNK_TGT_F=['-o',''] | |
797 | elif mode=='cxx': | |
798 | self.env.CXXLNK_TGT_F=['-o',''] | |
799 | features='%s %sshlib'%(mode,mode) | |
800 | try: | |
801 | self.check(msg='Checking if the -o link must be split from arguments',fragment=SNIP_EMPTY_PROGRAM,features=features) | |
802 | except self.errors.ConfigurationError: | |
803 | self.env.revert() | |
804 | else: | |
805 | self.env.commit() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,shutil,platform | |
5 | from waflib import Task,Utils | |
6 | from waflib.TaskGen import taskgen_method,feature,after_method,before_method | |
7 | app_info=''' | |
8 | <?xml version="1.0" encoding="UTF-8"?> | |
9 | <!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd"> | |
10 | <plist version="0.9"> | |
11 | <dict> | |
12 | <key>CFBundlePackageType</key> | |
13 | <string>APPL</string> | |
14 | <key>CFBundleGetInfoString</key> | |
15 | <string>Created by Waf</string> | |
16 | <key>CFBundleSignature</key> | |
17 | <string>????</string> | |
18 | <key>NOTE</key> | |
19 | <string>THIS IS A GENERATED FILE, DO NOT MODIFY</string> | |
20 | <key>CFBundleExecutable</key> | |
21 | <string>{app_name}</string> | |
22 | </dict> | |
23 | </plist> | |
24 | ''' | |
25 | @feature('c','cxx') | |
26 | def set_macosx_deployment_target(self): | |
27 | if self.env.MACOSX_DEPLOYMENT_TARGET: | |
28 | os.environ['MACOSX_DEPLOYMENT_TARGET']=self.env.MACOSX_DEPLOYMENT_TARGET | |
29 | elif'MACOSX_DEPLOYMENT_TARGET'not in os.environ: | |
30 | if Utils.unversioned_sys_platform()=='darwin': | |
31 | os.environ['MACOSX_DEPLOYMENT_TARGET']='.'.join(platform.mac_ver()[0].split('.')[:2]) | |
32 | @taskgen_method | |
33 | def create_bundle_dirs(self,name,out): | |
34 | dir=out.parent.find_or_declare(name) | |
35 | dir.mkdir() | |
36 | macos=dir.find_or_declare(['Contents','MacOS']) | |
37 | macos.mkdir() | |
38 | return dir | |
39 | def bundle_name_for_output(out): | |
40 | name=out.name | |
41 | k=name.rfind('.') | |
42 | if k>=0: | |
43 | name=name[:k]+'.app' | |
44 | else: | |
45 | name=name+'.app' | |
46 | return name | |
47 | @feature('cprogram','cxxprogram') | |
48 | @after_method('apply_link') | |
49 | def create_task_macapp(self): | |
50 | if self.env.MACAPP or getattr(self,'mac_app',False): | |
51 | out=self.link_task.outputs[0] | |
52 | name=bundle_name_for_output(out) | |
53 | dir=self.create_bundle_dirs(name,out) | |
54 | n1=dir.find_or_declare(['Contents','MacOS',out.name]) | |
55 | self.apptask=self.create_task('macapp',self.link_task.outputs,n1) | |
56 | inst_to=getattr(self,'install_path','/Applications')+'/%s/Contents/MacOS/'%name | |
57 | self.add_install_files(install_to=inst_to,install_from=n1,chmod=Utils.O755) | |
58 | if getattr(self,'mac_files',None): | |
59 | mac_files_root=getattr(self,'mac_files_root',None) | |
60 | if isinstance(mac_files_root,str): | |
61 | mac_files_root=self.path.find_node(mac_files_root) | |
62 | if not mac_files_root: | |
63 | self.bld.fatal('Invalid mac_files_root %r'%self.mac_files_root) | |
64 | res_dir=n1.parent.parent.make_node('Resources') | |
65 | inst_to=getattr(self,'install_path','/Applications')+'/%s/Resources'%name | |
66 | for node in self.to_nodes(self.mac_files): | |
67 | relpath=node.path_from(mac_files_root or node.parent) | |
68 | self.create_task('macapp',node,res_dir.make_node(relpath)) | |
69 | self.add_install_as(install_to=os.path.join(inst_to,relpath),install_from=node) | |
70 | if getattr(self.bld,'is_install',None): | |
71 | self.install_task.hasrun=Task.SKIP_ME | |
72 | @feature('cprogram','cxxprogram') | |
73 | @after_method('apply_link') | |
74 | def create_task_macplist(self): | |
75 | if self.env.MACAPP or getattr(self,'mac_app',False): | |
76 | out=self.link_task.outputs[0] | |
77 | name=bundle_name_for_output(out) | |
78 | dir=self.create_bundle_dirs(name,out) | |
79 | n1=dir.find_or_declare(['Contents','Info.plist']) | |
80 | self.plisttask=plisttask=self.create_task('macplist',[],n1) | |
81 | plisttask.context={'app_name':self.link_task.outputs[0].name,'env':self.env} | |
82 | plist_ctx=getattr(self,'plist_context',None) | |
83 | if(plist_ctx): | |
84 | plisttask.context.update(plist_ctx) | |
85 | if getattr(self,'mac_plist',False): | |
86 | node=self.path.find_resource(self.mac_plist) | |
87 | if node: | |
88 | plisttask.inputs.append(node) | |
89 | else: | |
90 | plisttask.code=self.mac_plist | |
91 | else: | |
92 | plisttask.code=app_info | |
93 | inst_to=getattr(self,'install_path','/Applications')+'/%s/Contents/'%name | |
94 | self.add_install_files(install_to=inst_to,install_from=n1) | |
95 | @feature('cshlib','cxxshlib') | |
96 | @before_method('apply_link','propagate_uselib_vars') | |
97 | def apply_bundle(self): | |
98 | if self.env.MACBUNDLE or getattr(self,'mac_bundle',False): | |
99 | self.env.LINKFLAGS_cshlib=self.env.LINKFLAGS_cxxshlib=[] | |
100 | self.env.cshlib_PATTERN=self.env.cxxshlib_PATTERN=self.env.macbundle_PATTERN | |
101 | use=self.use=self.to_list(getattr(self,'use',[])) | |
102 | if not'MACBUNDLE'in use: | |
103 | use.append('MACBUNDLE') | |
104 | app_dirs=['Contents','Contents/MacOS','Contents/Resources'] | |
105 | class macapp(Task.Task): | |
106 | color='PINK' | |
107 | def run(self): | |
108 | self.outputs[0].parent.mkdir() | |
109 | shutil.copy2(self.inputs[0].srcpath(),self.outputs[0].abspath()) | |
110 | class macplist(Task.Task): | |
111 | color='PINK' | |
112 | ext_in=['.bin'] | |
113 | def run(self): | |
114 | if getattr(self,'code',None): | |
115 | txt=self.code | |
116 | else: | |
117 | txt=self.inputs[0].read() | |
118 | context=getattr(self,'context',{}) | |
119 | txt=txt.format(**context) | |
120 | self.outputs[0].write(txt) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re,string,traceback | |
5 | from waflib import Logs,Utils,Errors | |
6 | class PreprocError(Errors.WafError): | |
7 | pass | |
8 | FILE_CACHE_SIZE=100000 | |
9 | LINE_CACHE_SIZE=100000 | |
10 | POPFILE='-' | |
11 | recursion_limit=150 | |
12 | go_absolute=False | |
13 | standard_includes=['/usr/local/include','/usr/include'] | |
14 | if Utils.is_win32: | |
15 | standard_includes=[] | |
16 | use_trigraphs=0 | |
17 | strict_quotes=0 | |
18 | g_optrans={'not':'!','not_eq':'!','and':'&&','and_eq':'&=','or':'||','or_eq':'|=','xor':'^','xor_eq':'^=','bitand':'&','bitor':'|','compl':'~',} | |
19 | re_lines=re.compile('^[ \t]*(?:#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$',re.IGNORECASE|re.MULTILINE) | |
20 | re_mac=re.compile(r"^[a-zA-Z_]\w*") | |
21 | re_fun=re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') | |
22 | re_pragma_once=re.compile(r'^\s*once\s*',re.IGNORECASE) | |
23 | re_nl=re.compile('\\\\\r*\n',re.MULTILINE) | |
24 | re_cpp=re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',re.DOTALL|re.MULTILINE) | |
25 | trig_def=[('??'+a,b)for a,b in zip("=-/!'()<>",r'#~\|^[]{}')] | |
26 | chr_esc={'0':0,'a':7,'b':8,'t':9,'n':10,'f':11,'v':12,'r':13,'\\':92,"'":39} | |
27 | NUM='i' | |
28 | OP='O' | |
29 | IDENT='T' | |
30 | STR='s' | |
31 | CHAR='c' | |
32 | tok_types=[NUM,STR,IDENT,OP] | |
33 | exp_types=[r"""0[xX](?P<hex>[a-fA-F0-9]+)(?P<qual1>[uUlL]*)|L*?'(?P<char>(\\.|[^\\'])+)'|(?P<n1>\d+)[Ee](?P<exp0>[+-]*?\d+)(?P<float0>[fFlL]*)|(?P<n2>\d*\.\d+)([Ee](?P<exp1>[+-]*?\d+))?(?P<float1>[fFlL]*)|(?P<n4>\d+\.\d*)([Ee](?P<exp2>[+-]*?\d+))?(?P<float2>[fFlL]*)|(?P<oct>0*)(?P<n0>\d+)(?P<qual2>[uUlL]*)""",r'L?"([^"\\]|\\.)*"',r'[a-zA-Z_]\w*',r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]',] | |
34 | re_clexer=re.compile('|'.join(["(?P<%s>%s)"%(name,part)for name,part in zip(tok_types,exp_types)]),re.M) | |
35 | accepted='a' | |
36 | ignored='i' | |
37 | undefined='u' | |
38 | skipped='s' | |
39 | def repl(m): | |
40 | s=m.group() | |
41 | if s[0]=='/': | |
42 | return' ' | |
43 | return s | |
44 | prec={} | |
45 | ops=['* / %','+ -','<< >>','< <= >= >','== !=','& | ^','&& ||',','] | |
46 | for x,syms in enumerate(ops): | |
47 | for u in syms.split(): | |
48 | prec[u]=x | |
49 | def reduce_nums(val_1,val_2,val_op): | |
50 | try: | |
51 | a=0+val_1 | |
52 | except TypeError: | |
53 | a=int(val_1) | |
54 | try: | |
55 | b=0+val_2 | |
56 | except TypeError: | |
57 | b=int(val_2) | |
58 | d=val_op | |
59 | if d=='%': | |
60 | c=a%b | |
61 | elif d=='+': | |
62 | c=a+b | |
63 | elif d=='-': | |
64 | c=a-b | |
65 | elif d=='*': | |
66 | c=a*b | |
67 | elif d=='/': | |
68 | c=a/b | |
69 | elif d=='^': | |
70 | c=a^b | |
71 | elif d=='==': | |
72 | c=int(a==b) | |
73 | elif d=='|'or d=='bitor': | |
74 | c=a|b | |
75 | elif d=='||'or d=='or': | |
76 | c=int(a or b) | |
77 | elif d=='&'or d=='bitand': | |
78 | c=a&b | |
79 | elif d=='&&'or d=='and': | |
80 | c=int(a and b) | |
81 | elif d=='!='or d=='not_eq': | |
82 | c=int(a!=b) | |
83 | elif d=='^'or d=='xor': | |
84 | c=int(a^b) | |
85 | elif d=='<=': | |
86 | c=int(a<=b) | |
87 | elif d=='<': | |
88 | c=int(a<b) | |
89 | elif d=='>': | |
90 | c=int(a>b) | |
91 | elif d=='>=': | |
92 | c=int(a>=b) | |
93 | elif d=='<<': | |
94 | c=a<<b | |
95 | elif d=='>>': | |
96 | c=a>>b | |
97 | else: | |
98 | c=0 | |
99 | return c | |
100 | def get_num(lst): | |
101 | if not lst: | |
102 | raise PreprocError('empty list for get_num') | |
103 | (p,v)=lst[0] | |
104 | if p==OP: | |
105 | if v=='(': | |
106 | count_par=1 | |
107 | i=1 | |
108 | while i<len(lst): | |
109 | (p,v)=lst[i] | |
110 | if p==OP: | |
111 | if v==')': | |
112 | count_par-=1 | |
113 | if count_par==0: | |
114 | break | |
115 | elif v=='(': | |
116 | count_par+=1 | |
117 | i+=1 | |
118 | else: | |
119 | raise PreprocError('rparen expected %r'%lst) | |
120 | (num,_)=get_term(lst[1:i]) | |
121 | return(num,lst[i+1:]) | |
122 | elif v=='+': | |
123 | return get_num(lst[1:]) | |
124 | elif v=='-': | |
125 | num,lst=get_num(lst[1:]) | |
126 | return(reduce_nums('-1',num,'*'),lst) | |
127 | elif v=='!': | |
128 | num,lst=get_num(lst[1:]) | |
129 | return(int(not int(num)),lst) | |
130 | elif v=='~': | |
131 | num,lst=get_num(lst[1:]) | |
132 | return(~int(num),lst) | |
133 | else: | |
134 | raise PreprocError('Invalid op token %r for get_num'%lst) | |
135 | elif p==NUM: | |
136 | return v,lst[1:] | |
137 | elif p==IDENT: | |
138 | return 0,lst[1:] | |
139 | else: | |
140 | raise PreprocError('Invalid token %r for get_num'%lst) | |
141 | def get_term(lst): | |
142 | if not lst: | |
143 | raise PreprocError('empty list for get_term') | |
144 | num,lst=get_num(lst) | |
145 | if not lst: | |
146 | return(num,[]) | |
147 | (p,v)=lst[0] | |
148 | if p==OP: | |
149 | if v==',': | |
150 | return get_term(lst[1:]) | |
151 | elif v=='?': | |
152 | count_par=0 | |
153 | i=1 | |
154 | while i<len(lst): | |
155 | (p,v)=lst[i] | |
156 | if p==OP: | |
157 | if v==')': | |
158 | count_par-=1 | |
159 | elif v=='(': | |
160 | count_par+=1 | |
161 | elif v==':': | |
162 | if count_par==0: | |
163 | break | |
164 | i+=1 | |
165 | else: | |
166 | raise PreprocError('rparen expected %r'%lst) | |
167 | if int(num): | |
168 | return get_term(lst[1:i]) | |
169 | else: | |
170 | return get_term(lst[i+1:]) | |
171 | else: | |
172 | num2,lst=get_num(lst[1:]) | |
173 | if not lst: | |
174 | num2=reduce_nums(num,num2,v) | |
175 | return get_term([(NUM,num2)]+lst) | |
176 | p2,v2=lst[0] | |
177 | if p2!=OP: | |
178 | raise PreprocError('op expected %r'%lst) | |
179 | if prec[v2]>=prec[v]: | |
180 | num2=reduce_nums(num,num2,v) | |
181 | return get_term([(NUM,num2)]+lst) | |
182 | else: | |
183 | num3,lst=get_num(lst[1:]) | |
184 | num3=reduce_nums(num2,num3,v2) | |
185 | return get_term([(NUM,num),(p,v),(NUM,num3)]+lst) | |
186 | raise PreprocError('cannot reduce %r'%lst) | |
187 | def reduce_eval(lst): | |
188 | num,lst=get_term(lst) | |
189 | return(NUM,num) | |
190 | def stringize(lst): | |
191 | lst=[str(v2)for(p2,v2)in lst] | |
192 | return"".join(lst) | |
193 | def paste_tokens(t1,t2): | |
194 | p1=None | |
195 | if t1[0]==OP and t2[0]==OP: | |
196 | p1=OP | |
197 | elif t1[0]==IDENT and(t2[0]==IDENT or t2[0]==NUM): | |
198 | p1=IDENT | |
199 | elif t1[0]==NUM and t2[0]==NUM: | |
200 | p1=NUM | |
201 | if not p1: | |
202 | raise PreprocError('tokens do not make a valid paste %r and %r'%(t1,t2)) | |
203 | return(p1,t1[1]+t2[1]) | |
204 | def reduce_tokens(lst,defs,ban=[]): | |
205 | i=0 | |
206 | while i<len(lst): | |
207 | (p,v)=lst[i] | |
208 | if p==IDENT and v=="defined": | |
209 | del lst[i] | |
210 | if i<len(lst): | |
211 | (p2,v2)=lst[i] | |
212 | if p2==IDENT: | |
213 | if v2 in defs: | |
214 | lst[i]=(NUM,1) | |
215 | else: | |
216 | lst[i]=(NUM,0) | |
217 | elif p2==OP and v2=='(': | |
218 | del lst[i] | |
219 | (p2,v2)=lst[i] | |
220 | del lst[i] | |
221 | if v2 in defs: | |
222 | lst[i]=(NUM,1) | |
223 | else: | |
224 | lst[i]=(NUM,0) | |
225 | else: | |
226 | raise PreprocError('Invalid define expression %r'%lst) | |
227 | elif p==IDENT and v in defs: | |
228 | if isinstance(defs[v],str): | |
229 | a,b=extract_macro(defs[v]) | |
230 | defs[v]=b | |
231 | macro_def=defs[v] | |
232 | to_add=macro_def[1] | |
233 | if isinstance(macro_def[0],list): | |
234 | del lst[i] | |
235 | accu=to_add[:] | |
236 | reduce_tokens(accu,defs,ban+[v]) | |
237 | for tmp in accu: | |
238 | lst.insert(i,tmp) | |
239 | i+=1 | |
240 | else: | |
241 | args=[] | |
242 | del lst[i] | |
243 | if i>=len(lst): | |
244 | raise PreprocError('expected ( after %r (got nothing)'%v) | |
245 | (p2,v2)=lst[i] | |
246 | if p2!=OP or v2!='(': | |
247 | raise PreprocError('expected ( after %r'%v) | |
248 | del lst[i] | |
249 | one_param=[] | |
250 | count_paren=0 | |
251 | while i<len(lst): | |
252 | p2,v2=lst[i] | |
253 | del lst[i] | |
254 | if p2==OP and count_paren==0: | |
255 | if v2=='(': | |
256 | one_param.append((p2,v2)) | |
257 | count_paren+=1 | |
258 | elif v2==')': | |
259 | if one_param: | |
260 | args.append(one_param) | |
261 | break | |
262 | elif v2==',': | |
263 | if not one_param: | |
264 | raise PreprocError('empty param in funcall %r'%v) | |
265 | args.append(one_param) | |
266 | one_param=[] | |
267 | else: | |
268 | one_param.append((p2,v2)) | |
269 | else: | |
270 | one_param.append((p2,v2)) | |
271 | if v2=='(': | |
272 | count_paren+=1 | |
273 | elif v2==')': | |
274 | count_paren-=1 | |
275 | else: | |
276 | raise PreprocError('malformed macro') | |
277 | accu=[] | |
278 | arg_table=macro_def[0] | |
279 | j=0 | |
280 | while j<len(to_add): | |
281 | (p2,v2)=to_add[j] | |
282 | if p2==OP and v2=='#': | |
283 | if j+1<len(to_add)and to_add[j+1][0]==IDENT and to_add[j+1][1]in arg_table: | |
284 | toks=args[arg_table[to_add[j+1][1]]] | |
285 | accu.append((STR,stringize(toks))) | |
286 | j+=1 | |
287 | else: | |
288 | accu.append((p2,v2)) | |
289 | elif p2==OP and v2=='##': | |
290 | if accu and j+1<len(to_add): | |
291 | t1=accu[-1] | |
292 | if to_add[j+1][0]==IDENT and to_add[j+1][1]in arg_table: | |
293 | toks=args[arg_table[to_add[j+1][1]]] | |
294 | if toks: | |
295 | accu[-1]=paste_tokens(t1,toks[0]) | |
296 | accu.extend(toks[1:]) | |
297 | else: | |
298 | accu.append((p2,v2)) | |
299 | accu.extend(toks) | |
300 | elif to_add[j+1][0]==IDENT and to_add[j+1][1]=='__VA_ARGS__': | |
301 | va_toks=[] | |
302 | st=len(macro_def[0]) | |
303 | pt=len(args) | |
304 | for x in args[pt-st+1:]: | |
305 | va_toks.extend(x) | |
306 | va_toks.append((OP,',')) | |
307 | if va_toks: | |
308 | va_toks.pop() | |
309 | if len(accu)>1: | |
310 | (p3,v3)=accu[-1] | |
311 | (p4,v4)=accu[-2] | |
312 | if v3=='##': | |
313 | accu.pop() | |
314 | if v4==','and pt<st: | |
315 | accu.pop() | |
316 | accu+=va_toks | |
317 | else: | |
318 | accu[-1]=paste_tokens(t1,to_add[j+1]) | |
319 | j+=1 | |
320 | else: | |
321 | accu.append((p2,v2)) | |
322 | elif p2==IDENT and v2 in arg_table: | |
323 | toks=args[arg_table[v2]] | |
324 | reduce_tokens(toks,defs,ban+[v]) | |
325 | accu.extend(toks) | |
326 | else: | |
327 | accu.append((p2,v2)) | |
328 | j+=1 | |
329 | reduce_tokens(accu,defs,ban+[v]) | |
330 | for x in range(len(accu)-1,-1,-1): | |
331 | lst.insert(i,accu[x]) | |
332 | i+=1 | |
333 | def eval_macro(lst,defs): | |
334 | reduce_tokens(lst,defs,[]) | |
335 | if not lst: | |
336 | raise PreprocError('missing tokens to evaluate') | |
337 | if lst: | |
338 | p,v=lst[0] | |
339 | if p==IDENT and v not in defs: | |
340 | raise PreprocError('missing macro %r'%lst) | |
341 | p,v=reduce_eval(lst) | |
342 | return int(v)!=0 | |
343 | def extract_macro(txt): | |
344 | t=tokenize(txt) | |
345 | if re_fun.search(txt): | |
346 | p,name=t[0] | |
347 | p,v=t[1] | |
348 | if p!=OP: | |
349 | raise PreprocError('expected (') | |
350 | i=1 | |
351 | pindex=0 | |
352 | params={} | |
353 | prev='(' | |
354 | while 1: | |
355 | i+=1 | |
356 | p,v=t[i] | |
357 | if prev=='(': | |
358 | if p==IDENT: | |
359 | params[v]=pindex | |
360 | pindex+=1 | |
361 | prev=p | |
362 | elif p==OP and v==')': | |
363 | break | |
364 | else: | |
365 | raise PreprocError('unexpected token (3)') | |
366 | elif prev==IDENT: | |
367 | if p==OP and v==',': | |
368 | prev=v | |
369 | elif p==OP and v==')': | |
370 | break | |
371 | else: | |
372 | raise PreprocError('comma or ... expected') | |
373 | elif prev==',': | |
374 | if p==IDENT: | |
375 | params[v]=pindex | |
376 | pindex+=1 | |
377 | prev=p | |
378 | elif p==OP and v=='...': | |
379 | raise PreprocError('not implemented (1)') | |
380 | else: | |
381 | raise PreprocError('comma or ... expected (2)') | |
382 | elif prev=='...': | |
383 | raise PreprocError('not implemented (2)') | |
384 | else: | |
385 | raise PreprocError('unexpected else') | |
386 | return(name,[params,t[i+1:]]) | |
387 | else: | |
388 | (p,v)=t[0] | |
389 | if len(t)>1: | |
390 | return(v,[[],t[1:]]) | |
391 | else: | |
392 | return(v,[[],[('T','')]]) | |
393 | re_include=re.compile(r'^\s*(<(?:.*)>|"(?:.*)")') | |
394 | def extract_include(txt,defs): | |
395 | m=re_include.search(txt) | |
396 | if m: | |
397 | txt=m.group(1) | |
398 | return txt[0],txt[1:-1] | |
399 | toks=tokenize(txt) | |
400 | reduce_tokens(toks,defs,['waf_include']) | |
401 | if not toks: | |
402 | raise PreprocError('could not parse include %r'%txt) | |
403 | if len(toks)==1: | |
404 | if toks[0][0]==STR: | |
405 | return'"',toks[0][1] | |
406 | else: | |
407 | if toks[0][1]=='<'and toks[-1][1]=='>': | |
408 | ret='<',stringize(toks).lstrip('<').rstrip('>') | |
409 | return ret | |
410 | raise PreprocError('could not parse include %r'%txt) | |
411 | def parse_char(txt): | |
412 | if not txt: | |
413 | raise PreprocError('attempted to parse a null char') | |
414 | if txt[0]!='\\': | |
415 | return ord(txt) | |
416 | c=txt[1] | |
417 | if c=='x': | |
418 | if len(txt)==4 and txt[3]in string.hexdigits: | |
419 | return int(txt[2:],16) | |
420 | return int(txt[2:],16) | |
421 | elif c.isdigit(): | |
422 | if c=='0'and len(txt)==2: | |
423 | return 0 | |
424 | for i in 3,2,1: | |
425 | if len(txt)>i and txt[1:1+i].isdigit(): | |
426 | return(1+i,int(txt[1:1+i],8)) | |
427 | else: | |
428 | try: | |
429 | return chr_esc[c] | |
430 | except KeyError: | |
431 | raise PreprocError('could not parse char literal %r'%txt) | |
432 | def tokenize(s): | |
433 | return tokenize_private(s)[:] | |
434 | def tokenize_private(s): | |
435 | ret=[] | |
436 | for match in re_clexer.finditer(s): | |
437 | m=match.group | |
438 | for name in tok_types: | |
439 | v=m(name) | |
440 | if v: | |
441 | if name==IDENT: | |
442 | if v in g_optrans: | |
443 | name=OP | |
444 | elif v.lower()=="true": | |
445 | v=1 | |
446 | name=NUM | |
447 | elif v.lower()=="false": | |
448 | v=0 | |
449 | name=NUM | |
450 | elif name==NUM: | |
451 | if m('oct'): | |
452 | v=int(v,8) | |
453 | elif m('hex'): | |
454 | v=int(m('hex'),16) | |
455 | elif m('n0'): | |
456 | v=m('n0') | |
457 | else: | |
458 | v=m('char') | |
459 | if v: | |
460 | v=parse_char(v) | |
461 | else: | |
462 | v=m('n2')or m('n4') | |
463 | elif name==OP: | |
464 | if v=='%:': | |
465 | v='#' | |
466 | elif v=='%:%:': | |
467 | v='##' | |
468 | elif name==STR: | |
469 | v=v[1:-1] | |
470 | ret.append((name,v)) | |
471 | break | |
472 | return ret | |
473 | def format_defines(lst): | |
474 | ret=[] | |
475 | for y in lst: | |
476 | if y: | |
477 | pos=y.find('=') | |
478 | if pos==-1: | |
479 | ret.append(y) | |
480 | elif pos>0: | |
481 | ret.append('%s %s'%(y[:pos],y[pos+1:])) | |
482 | else: | |
483 | raise ValueError('Invalid define expression %r'%y) | |
484 | return ret | |
485 | class c_parser(object): | |
486 | def __init__(self,nodepaths=None,defines=None): | |
487 | self.lines=[] | |
488 | if defines is None: | |
489 | self.defs={} | |
490 | else: | |
491 | self.defs=dict(defines) | |
492 | self.state=[] | |
493 | self.count_files=0 | |
494 | self.currentnode_stack=[] | |
495 | self.nodepaths=nodepaths or[] | |
496 | self.nodes=[] | |
497 | self.names=[] | |
498 | self.curfile='' | |
499 | self.ban_includes=set() | |
500 | self.listed=set() | |
501 | def cached_find_resource(self,node,filename): | |
502 | try: | |
503 | cache=node.ctx.preproc_cache_node | |
504 | except AttributeError: | |
505 | cache=node.ctx.preproc_cache_node=Utils.lru_cache(FILE_CACHE_SIZE) | |
506 | key=(node,filename) | |
507 | try: | |
508 | return cache[key] | |
509 | except KeyError: | |
510 | ret=node.find_resource(filename) | |
511 | if ret: | |
512 | if getattr(ret,'children',None): | |
513 | ret=None | |
514 | elif ret.is_child_of(node.ctx.bldnode): | |
515 | tmp=node.ctx.srcnode.search_node(ret.path_from(node.ctx.bldnode)) | |
516 | if tmp and getattr(tmp,'children',None): | |
517 | ret=None | |
518 | cache[key]=ret | |
519 | return ret | |
520 | def tryfind(self,filename,kind='"',env=None): | |
521 | if filename.endswith('.moc'): | |
522 | self.names.append(filename) | |
523 | return None | |
524 | self.curfile=filename | |
525 | found=None | |
526 | if kind=='"': | |
527 | if env.MSVC_VERSION: | |
528 | for n in reversed(self.currentnode_stack): | |
529 | found=self.cached_find_resource(n,filename) | |
530 | if found: | |
531 | break | |
532 | else: | |
533 | found=self.cached_find_resource(self.currentnode_stack[-1],filename) | |
534 | if not found: | |
535 | for n in self.nodepaths: | |
536 | found=self.cached_find_resource(n,filename) | |
537 | if found: | |
538 | break | |
539 | listed=self.listed | |
540 | if found and not found in self.ban_includes: | |
541 | if found not in listed: | |
542 | listed.add(found) | |
543 | self.nodes.append(found) | |
544 | self.addlines(found) | |
545 | else: | |
546 | if filename not in listed: | |
547 | listed.add(filename) | |
548 | self.names.append(filename) | |
549 | return found | |
550 | def filter_comments(self,node): | |
551 | code=node.read() | |
552 | if use_trigraphs: | |
553 | for(a,b)in trig_def: | |
554 | code=code.split(a).join(b) | |
555 | code=re_nl.sub('',code) | |
556 | code=re_cpp.sub(repl,code) | |
557 | return re_lines.findall(code) | |
558 | def parse_lines(self,node): | |
559 | try: | |
560 | cache=node.ctx.preproc_cache_lines | |
561 | except AttributeError: | |
562 | cache=node.ctx.preproc_cache_lines=Utils.lru_cache(LINE_CACHE_SIZE) | |
563 | try: | |
564 | return cache[node] | |
565 | except KeyError: | |
566 | cache[node]=lines=self.filter_comments(node) | |
567 | lines.append((POPFILE,'')) | |
568 | lines.reverse() | |
569 | return lines | |
570 | def addlines(self,node): | |
571 | self.currentnode_stack.append(node.parent) | |
572 | self.count_files+=1 | |
573 | if self.count_files>recursion_limit: | |
574 | raise PreprocError('recursion limit exceeded') | |
575 | if Logs.verbose: | |
576 | Logs.debug('preproc: reading file %r',node) | |
577 | try: | |
578 | lines=self.parse_lines(node) | |
579 | except EnvironmentError: | |
580 | raise PreprocError('could not read the file %r'%node) | |
581 | except Exception: | |
582 | if Logs.verbose>0: | |
583 | Logs.error('parsing %r failed %s',node,traceback.format_exc()) | |
584 | else: | |
585 | self.lines.extend(lines) | |
586 | def start(self,node,env): | |
587 | Logs.debug('preproc: scanning %s (in %s)',node.name,node.parent.name) | |
588 | self.current_file=node | |
589 | self.addlines(node) | |
590 | if env.DEFINES: | |
591 | lst=format_defines(env.DEFINES) | |
592 | lst.reverse() | |
593 | self.lines.extend([('define',x)for x in lst]) | |
594 | while self.lines: | |
595 | (token,line)=self.lines.pop() | |
596 | if token==POPFILE: | |
597 | self.count_files-=1 | |
598 | self.currentnode_stack.pop() | |
599 | continue | |
600 | try: | |
601 | state=self.state | |
602 | if token[:2]=='if': | |
603 | state.append(undefined) | |
604 | elif token=='endif': | |
605 | state.pop() | |
606 | if token[0]!='e': | |
607 | if skipped in self.state or ignored in self.state: | |
608 | continue | |
609 | if token=='if': | |
610 | ret=eval_macro(tokenize(line),self.defs) | |
611 | if ret: | |
612 | state[-1]=accepted | |
613 | else: | |
614 | state[-1]=ignored | |
615 | elif token=='ifdef': | |
616 | m=re_mac.match(line) | |
617 | if m and m.group()in self.defs: | |
618 | state[-1]=accepted | |
619 | else: | |
620 | state[-1]=ignored | |
621 | elif token=='ifndef': | |
622 | m=re_mac.match(line) | |
623 | if m and m.group()in self.defs: | |
624 | state[-1]=ignored | |
625 | else: | |
626 | state[-1]=accepted | |
627 | elif token=='include'or token=='import': | |
628 | (kind,inc)=extract_include(line,self.defs) | |
629 | self.current_file=self.tryfind(inc,kind,env) | |
630 | if token=='import': | |
631 | self.ban_includes.add(self.current_file) | |
632 | elif token=='elif': | |
633 | if state[-1]==accepted: | |
634 | state[-1]=skipped | |
635 | elif state[-1]==ignored: | |
636 | if eval_macro(tokenize(line),self.defs): | |
637 | state[-1]=accepted | |
638 | elif token=='else': | |
639 | if state[-1]==accepted: | |
640 | state[-1]=skipped | |
641 | elif state[-1]==ignored: | |
642 | state[-1]=accepted | |
643 | elif token=='define': | |
644 | try: | |
645 | self.defs[self.define_name(line)]=line | |
646 | except AttributeError: | |
647 | raise PreprocError('Invalid define line %r'%line) | |
648 | elif token=='undef': | |
649 | m=re_mac.match(line) | |
650 | if m and m.group()in self.defs: | |
651 | self.defs.__delitem__(m.group()) | |
652 | elif token=='pragma': | |
653 | if re_pragma_once.match(line.lower()): | |
654 | self.ban_includes.add(self.current_file) | |
655 | except Exception as e: | |
656 | if Logs.verbose: | |
657 | Logs.debug('preproc: line parsing failed (%s): %s %s',e,line,traceback.format_exc()) | |
658 | def define_name(self,line): | |
659 | return re_mac.match(line).group() | |
660 | def scan(task): | |
661 | try: | |
662 | incn=task.generator.includes_nodes | |
663 | except AttributeError: | |
664 | raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": '%task.generator) | |
665 | if go_absolute: | |
666 | nodepaths=incn+[task.generator.bld.root.find_dir(x)for x in standard_includes] | |
667 | else: | |
668 | nodepaths=[x for x in incn if x.is_child_of(x.ctx.srcnode)or x.is_child_of(x.ctx.bldnode)] | |
669 | tmp=c_parser(nodepaths) | |
670 | tmp.start(task.inputs[0],task.env) | |
671 | return(tmp.nodes,tmp.names) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Task | |
5 | from waflib.Configure import conf | |
6 | from waflib.TaskGen import feature,before_method,after_method | |
7 | LIB_CODE=''' | |
8 | #ifdef _MSC_VER | |
9 | #define testEXPORT __declspec(dllexport) | |
10 | #else | |
11 | #define testEXPORT | |
12 | #endif | |
13 | testEXPORT int lib_func(void) { return 9; } | |
14 | ''' | |
15 | MAIN_CODE=''' | |
16 | #ifdef _MSC_VER | |
17 | #define testEXPORT __declspec(dllimport) | |
18 | #else | |
19 | #define testEXPORT | |
20 | #endif | |
21 | testEXPORT int lib_func(void); | |
22 | int main(int argc, char **argv) { | |
23 | (void)argc; (void)argv; | |
24 | return !(lib_func() == 9); | |
25 | } | |
26 | ''' | |
27 | @feature('link_lib_test') | |
28 | @before_method('process_source') | |
29 | def link_lib_test_fun(self): | |
30 | def write_test_file(task): | |
31 | task.outputs[0].write(task.generator.code) | |
32 | rpath=[] | |
33 | if getattr(self,'add_rpath',False): | |
34 | rpath=[self.bld.path.get_bld().abspath()] | |
35 | mode=self.mode | |
36 | m='%s %s'%(mode,mode) | |
37 | ex=self.test_exec and'test_exec'or'' | |
38 | bld=self.bld | |
39 | bld(rule=write_test_file,target='test.'+mode,code=LIB_CODE) | |
40 | bld(rule=write_test_file,target='main.'+mode,code=MAIN_CODE) | |
41 | bld(features='%sshlib'%m,source='test.'+mode,target='test') | |
42 | bld(features='%sprogram %s'%(m,ex),source='main.'+mode,target='app',use='test',rpath=rpath) | |
43 | @conf | |
44 | def check_library(self,mode=None,test_exec=True): | |
45 | if not mode: | |
46 | mode='c' | |
47 | if self.env.CXX: | |
48 | mode='cxx' | |
49 | self.check(compile_filename=[],features='link_lib_test',msg='Checking for libraries',mode=mode,test_exec=test_exec) | |
50 | INLINE_CODE=''' | |
51 | typedef int foo_t; | |
52 | static %s foo_t static_foo () {return 0; } | |
53 | %s foo_t foo () { | |
54 | return 0; | |
55 | } | |
56 | ''' | |
57 | INLINE_VALUES=['inline','__inline__','__inline'] | |
58 | @conf | |
59 | def check_inline(self,**kw): | |
60 | self.start_msg('Checking for inline') | |
61 | if not'define_name'in kw: | |
62 | kw['define_name']='INLINE_MACRO' | |
63 | if not'features'in kw: | |
64 | if self.env.CXX: | |
65 | kw['features']=['cxx'] | |
66 | else: | |
67 | kw['features']=['c'] | |
68 | for x in INLINE_VALUES: | |
69 | kw['fragment']=INLINE_CODE%(x,x) | |
70 | try: | |
71 | self.check(**kw) | |
72 | except self.errors.ConfigurationError: | |
73 | continue | |
74 | else: | |
75 | self.end_msg(x) | |
76 | if x!='inline': | |
77 | self.define('inline',x,quote=False) | |
78 | return x | |
79 | self.fatal('could not use inline functions') | |
80 | LARGE_FRAGMENT='''#include <unistd.h> | |
81 | int main(int argc, char **argv) { | |
82 | (void)argc; (void)argv; | |
83 | return !(sizeof(off_t) >= 8); | |
84 | } | |
85 | ''' | |
86 | @conf | |
87 | def check_large_file(self,**kw): | |
88 | if not'define_name'in kw: | |
89 | kw['define_name']='HAVE_LARGEFILE' | |
90 | if not'execute'in kw: | |
91 | kw['execute']=True | |
92 | if not'features'in kw: | |
93 | if self.env.CXX: | |
94 | kw['features']=['cxx','cxxprogram'] | |
95 | else: | |
96 | kw['features']=['c','cprogram'] | |
97 | kw['fragment']=LARGE_FRAGMENT | |
98 | kw['msg']='Checking for large file support' | |
99 | ret=True | |
100 | try: | |
101 | if self.env.DEST_BINFMT!='pe': | |
102 | ret=self.check(**kw) | |
103 | except self.errors.ConfigurationError: | |
104 | pass | |
105 | else: | |
106 | if ret: | |
107 | return True | |
108 | kw['msg']='Checking for -D_FILE_OFFSET_BITS=64' | |
109 | kw['defines']=['_FILE_OFFSET_BITS=64'] | |
110 | try: | |
111 | ret=self.check(**kw) | |
112 | except self.errors.ConfigurationError: | |
113 | pass | |
114 | else: | |
115 | self.define('_FILE_OFFSET_BITS',64) | |
116 | return ret | |
117 | self.fatal('There is no support for large files') | |
118 | ENDIAN_FRAGMENT=''' | |
119 | #ifdef _MSC_VER | |
120 | #define testshlib_EXPORT __declspec(dllexport) | |
121 | #else | |
122 | #define testshlib_EXPORT | |
123 | #endif | |
124 | ||
125 | short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; | |
126 | short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; | |
127 | int testshlib_EXPORT use_ascii (int i) { | |
128 | return ascii_mm[i] + ascii_ii[i]; | |
129 | } | |
130 | short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; | |
131 | short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; | |
132 | int use_ebcdic (int i) { | |
133 | return ebcdic_mm[i] + ebcdic_ii[i]; | |
134 | } | |
135 | extern int foo; | |
136 | ''' | |
137 | class grep_for_endianness(Task.Task): | |
138 | color='PINK' | |
139 | def run(self): | |
140 | txt=self.inputs[0].read(flags='rb').decode('latin-1') | |
141 | if txt.find('LiTTleEnDian')>-1: | |
142 | self.generator.tmp.append('little') | |
143 | elif txt.find('BIGenDianSyS')>-1: | |
144 | self.generator.tmp.append('big') | |
145 | else: | |
146 | return-1 | |
147 | @feature('grep_for_endianness') | |
148 | @after_method('apply_link') | |
149 | def grep_for_endianness_fun(self): | |
150 | self.create_task('grep_for_endianness',self.link_task.outputs[0]) | |
151 | @conf | |
152 | def check_endianness(self): | |
153 | tmp=[] | |
154 | def check_msg(self): | |
155 | return tmp[0] | |
156 | self.check(fragment=ENDIAN_FRAGMENT,features='c cshlib grep_for_endianness',msg='Checking for endianness',define='ENDIANNESS',tmp=tmp,okmsg=check_msg,confcache=None) | |
157 | return tmp[0] |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re | |
5 | from waflib import Task,Utils,Node,Errors,Logs | |
6 | from waflib.TaskGen import after_method,before_method,feature,taskgen_method,extension | |
7 | from waflib.Tools import c_aliases,c_preproc,c_config,c_osx,c_tests | |
8 | from waflib.Configure import conf | |
9 | SYSTEM_LIB_PATHS=['/usr/lib64','/usr/lib','/usr/local/lib64','/usr/local/lib'] | |
10 | USELIB_VARS=Utils.defaultdict(set) | |
11 | USELIB_VARS['c']=set(['INCLUDES','FRAMEWORKPATH','DEFINES','CPPFLAGS','CCDEPS','CFLAGS','ARCH']) | |
12 | USELIB_VARS['cxx']=set(['INCLUDES','FRAMEWORKPATH','DEFINES','CPPFLAGS','CXXDEPS','CXXFLAGS','ARCH']) | |
13 | USELIB_VARS['d']=set(['INCLUDES','DFLAGS']) | |
14 | USELIB_VARS['includes']=set(['INCLUDES','FRAMEWORKPATH','ARCH']) | |
15 | USELIB_VARS['cprogram']=USELIB_VARS['cxxprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','FRAMEWORK','FRAMEWORKPATH','ARCH','LDFLAGS']) | |
16 | USELIB_VARS['cshlib']=USELIB_VARS['cxxshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','FRAMEWORK','FRAMEWORKPATH','ARCH','LDFLAGS']) | |
17 | USELIB_VARS['cstlib']=USELIB_VARS['cxxstlib']=set(['ARFLAGS','LINKDEPS']) | |
18 | USELIB_VARS['dprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS']) | |
19 | USELIB_VARS['dshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS']) | |
20 | USELIB_VARS['dstlib']=set(['ARFLAGS','LINKDEPS']) | |
21 | USELIB_VARS['asm']=set(['ASFLAGS']) | |
22 | @taskgen_method | |
23 | def create_compiled_task(self,name,node): | |
24 | out='%s.%d.o'%(node.name,self.idx) | |
25 | task=self.create_task(name,node,node.parent.find_or_declare(out)) | |
26 | try: | |
27 | self.compiled_tasks.append(task) | |
28 | except AttributeError: | |
29 | self.compiled_tasks=[task] | |
30 | return task | |
31 | @taskgen_method | |
32 | def to_incnodes(self,inlst): | |
33 | lst=[] | |
34 | seen=set() | |
35 | for x in self.to_list(inlst): | |
36 | if x in seen or not x: | |
37 | continue | |
38 | seen.add(x) | |
39 | if isinstance(x,Node.Node): | |
40 | lst.append(x) | |
41 | else: | |
42 | if os.path.isabs(x): | |
43 | lst.append(self.bld.root.make_node(x)or x) | |
44 | else: | |
45 | if x[0]=='#': | |
46 | p=self.bld.bldnode.make_node(x[1:]) | |
47 | v=self.bld.srcnode.make_node(x[1:]) | |
48 | else: | |
49 | p=self.path.get_bld().make_node(x) | |
50 | v=self.path.make_node(x) | |
51 | if p.is_child_of(self.bld.bldnode): | |
52 | p.mkdir() | |
53 | lst.append(p) | |
54 | lst.append(v) | |
55 | return lst | |
56 | @feature('c','cxx','d','asm','fc','includes') | |
57 | @after_method('propagate_uselib_vars','process_source') | |
58 | def apply_incpaths(self): | |
59 | lst=self.to_incnodes(self.to_list(getattr(self,'includes',[]))+self.env.INCLUDES) | |
60 | self.includes_nodes=lst | |
61 | cwd=self.get_cwd() | |
62 | self.env.INCPATHS=[x.path_from(cwd)for x in lst] | |
63 | class link_task(Task.Task): | |
64 | color='YELLOW' | |
65 | weight=3 | |
66 | inst_to=None | |
67 | chmod=Utils.O755 | |
68 | def add_target(self,target): | |
69 | if isinstance(target,str): | |
70 | base=self.generator.path | |
71 | if target.startswith('#'): | |
72 | target=target[1:] | |
73 | base=self.generator.bld.bldnode | |
74 | pattern=self.env[self.__class__.__name__+'_PATTERN'] | |
75 | if not pattern: | |
76 | pattern='%s' | |
77 | folder,name=os.path.split(target) | |
78 | if self.__class__.__name__.find('shlib')>0 and getattr(self.generator,'vnum',None): | |
79 | nums=self.generator.vnum.split('.') | |
80 | if self.env.DEST_BINFMT=='pe': | |
81 | name=name+'-'+nums[0] | |
82 | elif self.env.DEST_OS=='openbsd': | |
83 | pattern='%s.%s'%(pattern,nums[0]) | |
84 | if len(nums)>=2: | |
85 | pattern+='.%s'%nums[1] | |
86 | if folder: | |
87 | tmp=folder+os.sep+pattern%name | |
88 | else: | |
89 | tmp=pattern%name | |
90 | target=base.find_or_declare(tmp) | |
91 | self.set_outputs(target) | |
92 | def exec_command(self,*k,**kw): | |
93 | ret=super(link_task,self).exec_command(*k,**kw) | |
94 | if not ret and self.env.DO_MANIFEST: | |
95 | ret=self.exec_mf() | |
96 | return ret | |
97 | def exec_mf(self): | |
98 | if not self.env.MT: | |
99 | return 0 | |
100 | manifest=None | |
101 | for out_node in self.outputs: | |
102 | if out_node.name.endswith('.manifest'): | |
103 | manifest=out_node.abspath() | |
104 | break | |
105 | else: | |
106 | return 0 | |
107 | mode='' | |
108 | for x in Utils.to_list(self.generator.features): | |
109 | if x in('cprogram','cxxprogram','fcprogram','fcprogram_test'): | |
110 | mode=1 | |
111 | elif x in('cshlib','cxxshlib','fcshlib'): | |
112 | mode=2 | |
113 | Logs.debug('msvc: embedding manifest in mode %r',mode) | |
114 | lst=[]+self.env.MT | |
115 | lst.extend(Utils.to_list(self.env.MTFLAGS)) | |
116 | lst.extend(['-manifest',manifest]) | |
117 | lst.append('-outputresource:%s;%s'%(self.outputs[0].abspath(),mode)) | |
118 | return super(link_task,self).exec_command(lst) | |
119 | class stlink_task(link_task): | |
120 | run_str='${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' | |
121 | chmod=Utils.O644 | |
122 | def rm_tgt(cls): | |
123 | old=cls.run | |
124 | def wrap(self): | |
125 | try: | |
126 | os.remove(self.outputs[0].abspath()) | |
127 | except OSError: | |
128 | pass | |
129 | return old(self) | |
130 | setattr(cls,'run',wrap) | |
131 | rm_tgt(stlink_task) | |
132 | @feature('skip_stlib_link_deps') | |
133 | @before_method('process_use') | |
134 | def apply_skip_stlib_link_deps(self): | |
135 | self.env.SKIP_STLIB_LINK_DEPS=True | |
136 | @feature('c','cxx','d','fc','asm') | |
137 | @after_method('process_source') | |
138 | def apply_link(self): | |
139 | for x in self.features: | |
140 | if x=='cprogram'and'cxx'in self.features: | |
141 | x='cxxprogram' | |
142 | elif x=='cshlib'and'cxx'in self.features: | |
143 | x='cxxshlib' | |
144 | if x in Task.classes: | |
145 | if issubclass(Task.classes[x],link_task): | |
146 | link=x | |
147 | break | |
148 | else: | |
149 | return | |
150 | objs=[t.outputs[0]for t in getattr(self,'compiled_tasks',[])] | |
151 | self.link_task=self.create_task(link,objs) | |
152 | self.link_task.add_target(self.target) | |
153 | try: | |
154 | inst_to=self.install_path | |
155 | except AttributeError: | |
156 | inst_to=self.link_task.inst_to | |
157 | if inst_to: | |
158 | self.install_task=self.add_install_files(install_to=inst_to,install_from=self.link_task.outputs[:],chmod=self.link_task.chmod,task=self.link_task) | |
159 | @taskgen_method | |
160 | def use_rec(self,name,**kw): | |
161 | if name in self.tmp_use_not or name in self.tmp_use_seen: | |
162 | return | |
163 | try: | |
164 | y=self.bld.get_tgen_by_name(name) | |
165 | except Errors.WafError: | |
166 | self.uselib.append(name) | |
167 | self.tmp_use_not.add(name) | |
168 | return | |
169 | self.tmp_use_seen.append(name) | |
170 | y.post() | |
171 | y.tmp_use_objects=objects=kw.get('objects',True) | |
172 | y.tmp_use_stlib=stlib=kw.get('stlib',True) | |
173 | try: | |
174 | link_task=y.link_task | |
175 | except AttributeError: | |
176 | y.tmp_use_var='' | |
177 | else: | |
178 | objects=False | |
179 | if not isinstance(link_task,stlink_task): | |
180 | stlib=False | |
181 | y.tmp_use_var='LIB' | |
182 | else: | |
183 | y.tmp_use_var='STLIB' | |
184 | p=self.tmp_use_prec | |
185 | for x in self.to_list(getattr(y,'use',[])): | |
186 | if self.env["STLIB_"+x]: | |
187 | continue | |
188 | try: | |
189 | p[x].append(name) | |
190 | except KeyError: | |
191 | p[x]=[name] | |
192 | self.use_rec(x,objects=objects,stlib=stlib) | |
193 | @feature('c','cxx','d','use','fc') | |
194 | @before_method('apply_incpaths','propagate_uselib_vars') | |
195 | @after_method('apply_link','process_source') | |
196 | def process_use(self): | |
197 | use_not=self.tmp_use_not=set() | |
198 | self.tmp_use_seen=[] | |
199 | use_prec=self.tmp_use_prec={} | |
200 | self.uselib=self.to_list(getattr(self,'uselib',[])) | |
201 | self.includes=self.to_list(getattr(self,'includes',[])) | |
202 | names=self.to_list(getattr(self,'use',[])) | |
203 | for x in names: | |
204 | self.use_rec(x) | |
205 | for x in use_not: | |
206 | if x in use_prec: | |
207 | del use_prec[x] | |
208 | out=self.tmp_use_sorted=[] | |
209 | tmp=[] | |
210 | for x in self.tmp_use_seen: | |
211 | for k in use_prec.values(): | |
212 | if x in k: | |
213 | break | |
214 | else: | |
215 | tmp.append(x) | |
216 | while tmp: | |
217 | e=tmp.pop() | |
218 | out.append(e) | |
219 | try: | |
220 | nlst=use_prec[e] | |
221 | except KeyError: | |
222 | pass | |
223 | else: | |
224 | del use_prec[e] | |
225 | for x in nlst: | |
226 | for y in use_prec: | |
227 | if x in use_prec[y]: | |
228 | break | |
229 | else: | |
230 | tmp.append(x) | |
231 | if use_prec: | |
232 | raise Errors.WafError('Cycle detected in the use processing %r'%use_prec) | |
233 | out.reverse() | |
234 | link_task=getattr(self,'link_task',None) | |
235 | for x in out: | |
236 | y=self.bld.get_tgen_by_name(x) | |
237 | var=y.tmp_use_var | |
238 | if var and link_task: | |
239 | if self.env.SKIP_STLIB_LINK_DEPS and isinstance(link_task,stlink_task): | |
240 | pass | |
241 | elif var=='LIB'or y.tmp_use_stlib or x in names: | |
242 | self.env.append_value(var,[y.target[y.target.rfind(os.sep)+1:]]) | |
243 | self.link_task.dep_nodes.extend(y.link_task.outputs) | |
244 | tmp_path=y.link_task.outputs[0].parent.path_from(self.get_cwd()) | |
245 | self.env.append_unique(var+'PATH',[tmp_path]) | |
246 | else: | |
247 | if y.tmp_use_objects: | |
248 | self.add_objects_from_tgen(y) | |
249 | if getattr(y,'export_includes',None): | |
250 | self.includes=self.includes+y.to_incnodes(y.export_includes) | |
251 | if getattr(y,'export_defines',None): | |
252 | self.env.append_value('DEFINES',self.to_list(y.export_defines)) | |
253 | for x in names: | |
254 | try: | |
255 | y=self.bld.get_tgen_by_name(x) | |
256 | except Errors.WafError: | |
257 | if not self.env['STLIB_'+x]and not x in self.uselib: | |
258 | self.uselib.append(x) | |
259 | else: | |
260 | for k in self.to_list(getattr(y,'use',[])): | |
261 | if not self.env['STLIB_'+k]and not k in self.uselib: | |
262 | self.uselib.append(k) | |
263 | @taskgen_method | |
264 | def accept_node_to_link(self,node): | |
265 | return not node.name.endswith('.pdb') | |
266 | @taskgen_method | |
267 | def add_objects_from_tgen(self,tg): | |
268 | try: | |
269 | link_task=self.link_task | |
270 | except AttributeError: | |
271 | pass | |
272 | else: | |
273 | for tsk in getattr(tg,'compiled_tasks',[]): | |
274 | for x in tsk.outputs: | |
275 | if self.accept_node_to_link(x): | |
276 | link_task.inputs.append(x) | |
277 | @taskgen_method | |
278 | def get_uselib_vars(self): | |
279 | _vars=set() | |
280 | for x in self.features: | |
281 | if x in USELIB_VARS: | |
282 | _vars|=USELIB_VARS[x] | |
283 | return _vars | |
284 | @feature('c','cxx','d','fc','javac','cs','uselib','asm') | |
285 | @after_method('process_use') | |
286 | def propagate_uselib_vars(self): | |
287 | _vars=self.get_uselib_vars() | |
288 | env=self.env | |
289 | app=env.append_value | |
290 | feature_uselib=self.features+self.to_list(getattr(self,'uselib',[])) | |
291 | for var in _vars: | |
292 | y=var.lower() | |
293 | val=getattr(self,y,[]) | |
294 | if val: | |
295 | app(var,self.to_list(val)) | |
296 | for x in feature_uselib: | |
297 | val=env['%s_%s'%(var,x)] | |
298 | if val: | |
299 | app(var,val) | |
300 | @feature('cshlib','cxxshlib','fcshlib') | |
301 | @after_method('apply_link') | |
302 | def apply_implib(self): | |
303 | if not self.env.DEST_BINFMT=='pe': | |
304 | return | |
305 | dll=self.link_task.outputs[0] | |
306 | if isinstance(self.target,Node.Node): | |
307 | name=self.target.name | |
308 | else: | |
309 | name=os.path.split(self.target)[1] | |
310 | implib=self.env.implib_PATTERN%name | |
311 | implib=dll.parent.find_or_declare(implib) | |
312 | self.env.append_value('LINKFLAGS',self.env.IMPLIB_ST%implib.bldpath()) | |
313 | self.link_task.outputs.append(implib) | |
314 | if getattr(self,'defs',None)and self.env.DEST_BINFMT=='pe': | |
315 | node=self.path.find_resource(self.defs) | |
316 | if not node: | |
317 | raise Errors.WafError('invalid def file %r'%self.defs) | |
318 | if self.env.def_PATTERN: | |
319 | self.env.append_value('LINKFLAGS',self.env.def_PATTERN%node.path_from(self.get_cwd())) | |
320 | self.link_task.dep_nodes.append(node) | |
321 | else: | |
322 | self.link_task.inputs.append(node) | |
323 | if getattr(self,'install_task',None): | |
324 | try: | |
325 | inst_to=self.install_path_implib | |
326 | except AttributeError: | |
327 | try: | |
328 | inst_to=self.install_path | |
329 | except AttributeError: | |
330 | inst_to='${IMPLIBDIR}' | |
331 | self.install_task.install_to='${BINDIR}' | |
332 | if not self.env.IMPLIBDIR: | |
333 | self.env.IMPLIBDIR=self.env.LIBDIR | |
334 | self.implib_install_task=self.add_install_files(install_to=inst_to,install_from=implib,chmod=self.link_task.chmod,task=self.link_task) | |
335 | re_vnum=re.compile('^([1-9]\\d*|0)([.]([1-9]\\d*|0)){0,2}?$') | |
336 | @feature('cshlib','cxxshlib','dshlib','fcshlib','vnum') | |
337 | @after_method('apply_link','propagate_uselib_vars') | |
338 | def apply_vnum(self): | |
339 | if not getattr(self,'vnum','')or os.name!='posix'or self.env.DEST_BINFMT not in('elf','mac-o'): | |
340 | return | |
341 | link=self.link_task | |
342 | if not re_vnum.match(self.vnum): | |
343 | raise Errors.WafError('Invalid vnum %r for target %r'%(self.vnum,getattr(self,'name',self))) | |
344 | nums=self.vnum.split('.') | |
345 | node=link.outputs[0] | |
346 | cnum=getattr(self,'cnum',str(nums[0])) | |
347 | cnums=cnum.split('.') | |
348 | if len(cnums)>len(nums)or nums[0:len(cnums)]!=cnums: | |
349 | raise Errors.WafError('invalid compatibility version %s'%cnum) | |
350 | libname=node.name | |
351 | if libname.endswith('.dylib'): | |
352 | name3=libname.replace('.dylib','.%s.dylib'%self.vnum) | |
353 | name2=libname.replace('.dylib','.%s.dylib'%cnum) | |
354 | else: | |
355 | name3=libname+'.'+self.vnum | |
356 | name2=libname+'.'+cnum | |
357 | if self.env.SONAME_ST: | |
358 | v=self.env.SONAME_ST%name2 | |
359 | self.env.append_value('LINKFLAGS',v.split()) | |
360 | if self.env.DEST_OS!='openbsd': | |
361 | outs=[node.parent.make_node(name3)] | |
362 | if name2!=name3: | |
363 | outs.append(node.parent.make_node(name2)) | |
364 | self.create_task('vnum',node,outs) | |
365 | if getattr(self,'install_task',None): | |
366 | self.install_task.hasrun=Task.SKIPPED | |
367 | self.install_task.no_errcheck_out=True | |
368 | path=self.install_task.install_to | |
369 | if self.env.DEST_OS=='openbsd': | |
370 | libname=self.link_task.outputs[0].name | |
371 | t1=self.add_install_as(install_to='%s/%s'%(path,libname),install_from=node,chmod=self.link_task.chmod) | |
372 | self.vnum_install_task=(t1,) | |
373 | else: | |
374 | t1=self.add_install_as(install_to=path+os.sep+name3,install_from=node,chmod=self.link_task.chmod) | |
375 | t3=self.add_symlink_as(install_to=path+os.sep+libname,install_from=name3) | |
376 | if name2!=name3: | |
377 | t2=self.add_symlink_as(install_to=path+os.sep+name2,install_from=name3) | |
378 | self.vnum_install_task=(t1,t2,t3) | |
379 | else: | |
380 | self.vnum_install_task=(t1,t3) | |
381 | if'-dynamiclib'in self.env.LINKFLAGS: | |
382 | try: | |
383 | inst_to=self.install_path | |
384 | except AttributeError: | |
385 | inst_to=self.link_task.inst_to | |
386 | if inst_to: | |
387 | p=Utils.subst_vars(inst_to,self.env) | |
388 | path=os.path.join(p,name2) | |
389 | self.env.append_value('LINKFLAGS',['-install_name',path]) | |
390 | self.env.append_value('LINKFLAGS','-Wl,-compatibility_version,%s'%cnum) | |
391 | self.env.append_value('LINKFLAGS','-Wl,-current_version,%s'%self.vnum) | |
392 | class vnum(Task.Task): | |
393 | color='CYAN' | |
394 | ext_in=['.bin'] | |
395 | def keyword(self): | |
396 | return'Symlinking' | |
397 | def run(self): | |
398 | for x in self.outputs: | |
399 | path=x.abspath() | |
400 | try: | |
401 | os.remove(path) | |
402 | except OSError: | |
403 | pass | |
404 | try: | |
405 | os.symlink(self.inputs[0].name,path) | |
406 | except OSError: | |
407 | return 1 | |
408 | class fake_shlib(link_task): | |
409 | def runnable_status(self): | |
410 | for t in self.run_after: | |
411 | if not t.hasrun: | |
412 | return Task.ASK_LATER | |
413 | return Task.SKIP_ME | |
414 | class fake_stlib(stlink_task): | |
415 | def runnable_status(self): | |
416 | for t in self.run_after: | |
417 | if not t.hasrun: | |
418 | return Task.ASK_LATER | |
419 | return Task.SKIP_ME | |
420 | @conf | |
421 | def read_shlib(self,name,paths=[],export_includes=[],export_defines=[]): | |
422 | return self(name=name,features='fake_lib',lib_paths=paths,lib_type='shlib',export_includes=export_includes,export_defines=export_defines) | |
423 | @conf | |
424 | def read_stlib(self,name,paths=[],export_includes=[],export_defines=[]): | |
425 | return self(name=name,features='fake_lib',lib_paths=paths,lib_type='stlib',export_includes=export_includes,export_defines=export_defines) | |
426 | lib_patterns={'shlib':['lib%s.so','%s.so','lib%s.dylib','lib%s.dll','%s.dll'],'stlib':['lib%s.a','%s.a','lib%s.dll','%s.dll','lib%s.lib','%s.lib'],} | |
427 | @feature('fake_lib') | |
428 | def process_lib(self): | |
429 | node=None | |
430 | names=[x%self.name for x in lib_patterns[self.lib_type]] | |
431 | for x in self.lib_paths+[self.path]+SYSTEM_LIB_PATHS: | |
432 | if not isinstance(x,Node.Node): | |
433 | x=self.bld.root.find_node(x)or self.path.find_node(x) | |
434 | if not x: | |
435 | continue | |
436 | for y in names: | |
437 | node=x.find_node(y) | |
438 | if node: | |
439 | try: | |
440 | Utils.h_file(node.abspath()) | |
441 | except EnvironmentError: | |
442 | raise ValueError('Could not read %r'%y) | |
443 | break | |
444 | else: | |
445 | continue | |
446 | break | |
447 | else: | |
448 | raise Errors.WafError('could not find library %r'%self.name) | |
449 | self.link_task=self.create_task('fake_%s'%self.lib_type,[],[node]) | |
450 | self.target=self.name | |
451 | class fake_o(Task.Task): | |
452 | def runnable_status(self): | |
453 | return Task.SKIP_ME | |
454 | @extension('.o','.obj') | |
455 | def add_those_o_files(self,node): | |
456 | tsk=self.create_task('fake_o',[],node) | |
457 | try: | |
458 | self.compiled_tasks.append(tsk) | |
459 | except AttributeError: | |
460 | self.compiled_tasks=[tsk] | |
461 | @feature('fake_obj') | |
462 | @before_method('process_source') | |
463 | def process_objs(self): | |
464 | for node in self.to_nodes(self.source): | |
465 | self.add_those_o_files(node) | |
466 | self.source=[] | |
467 | @conf | |
468 | def read_object(self,obj): | |
469 | if not isinstance(obj,self.path.__class__): | |
470 | obj=self.path.find_resource(obj) | |
471 | return self(features='fake_obj',source=obj,name=obj.name) | |
472 | @feature('cxxprogram','cprogram') | |
473 | @after_method('apply_link','process_use') | |
474 | def set_full_paths_hpux(self): | |
475 | if self.env.DEST_OS!='hp-ux': | |
476 | return | |
477 | base=self.bld.bldnode.abspath() | |
478 | for var in['LIBPATH','STLIBPATH']: | |
479 | lst=[] | |
480 | for x in self.env[var]: | |
481 | if x.startswith('/'): | |
482 | lst.append(x) | |
483 | else: | |
484 | lst.append(os.path.normpath(os.path.join(base,x))) | |
485 | self.env[var]=lst |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ccroot,ar,gcc | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_clang(conf): | |
8 | cc=conf.find_program('clang',var='CC') | |
9 | conf.get_cc_version(cc,clang=True) | |
10 | conf.env.CC_NAME='clang' | |
11 | def configure(conf): | |
12 | conf.find_clang() | |
13 | conf.find_program(['llvm-ar','ar'],var='AR') | |
14 | conf.find_ar() | |
15 | conf.gcc_common_flags() | |
16 | conf.gcc_modifier_platform() | |
17 | conf.cc_load_tools() | |
18 | conf.cc_add_flags() | |
19 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ccroot,ar,gxx | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_clangxx(conf): | |
8 | cxx=conf.find_program('clang++',var='CXX') | |
9 | conf.get_cc_version(cxx,clang=True) | |
10 | conf.env.CXX_NAME='clang' | |
11 | def configure(conf): | |
12 | conf.find_clangxx() | |
13 | conf.find_program(['llvm-ar','ar'],var='AR') | |
14 | conf.find_ar() | |
15 | conf.gxx_common_flags() | |
16 | conf.gxx_modifier_platform() | |
17 | conf.cxx_load_tools() | |
18 | conf.cxx_add_flags() | |
19 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib.Tools import ccroot | |
6 | from waflib import Utils | |
7 | from waflib.Logs import debug | |
8 | c_compiler={'win32':['msvc','gcc','clang'],'cygwin':['gcc'],'darwin':['clang','gcc'],'aix':['xlc','gcc','clang'],'linux':['gcc','clang','icc'],'sunos':['suncc','gcc'],'irix':['gcc','irixcc'],'hpux':['gcc'],'osf1V':['gcc'],'gnu':['gcc','clang'],'java':['gcc','msvc','clang','icc'],'default':['clang','gcc'],} | |
9 | def default_compilers(): | |
10 | build_platform=Utils.unversioned_sys_platform() | |
11 | possible_compiler_list=c_compiler.get(build_platform,c_compiler['default']) | |
12 | return' '.join(possible_compiler_list) | |
13 | def configure(conf): | |
14 | try: | |
15 | test_for_compiler=conf.options.check_c_compiler or default_compilers() | |
16 | except AttributeError: | |
17 | conf.fatal("Add options(opt): opt.load('compiler_c')") | |
18 | for compiler in re.split('[ ,]+',test_for_compiler): | |
19 | conf.env.stash() | |
20 | conf.start_msg('Checking for %r (C compiler)'%compiler) | |
21 | try: | |
22 | conf.load(compiler) | |
23 | except conf.errors.ConfigurationError as e: | |
24 | conf.env.revert() | |
25 | conf.end_msg(False) | |
26 | debug('compiler_c: %r',e) | |
27 | else: | |
28 | if conf.env.CC: | |
29 | conf.end_msg(conf.env.get_flat('CC')) | |
30 | conf.env.COMPILER_CC=compiler | |
31 | conf.env.commit() | |
32 | break | |
33 | conf.env.revert() | |
34 | conf.end_msg(False) | |
35 | else: | |
36 | conf.fatal('could not configure a C compiler!') | |
37 | def options(opt): | |
38 | test_for_compiler=default_compilers() | |
39 | opt.load_special_tools('c_*.py',ban=['c_dumbpreproc.py']) | |
40 | cc_compiler_opts=opt.add_option_group('Configuration options') | |
41 | cc_compiler_opts.add_option('--check-c-compiler',default=None,help='list of C compilers to try [%s]'%test_for_compiler,dest="check_c_compiler") | |
42 | for x in test_for_compiler.split(): | |
43 | opt.load('%s'%x) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib.Tools import ccroot | |
6 | from waflib import Utils | |
7 | from waflib.Logs import debug | |
8 | cxx_compiler={'win32':['msvc','g++','clang++'],'cygwin':['g++'],'darwin':['clang++','g++'],'aix':['xlc++','g++','clang++'],'linux':['g++','clang++','icpc'],'sunos':['sunc++','g++'],'irix':['g++'],'hpux':['g++'],'osf1V':['g++'],'gnu':['g++','clang++'],'java':['g++','msvc','clang++','icpc'],'default':['clang++','g++']} | |
9 | def default_compilers(): | |
10 | build_platform=Utils.unversioned_sys_platform() | |
11 | possible_compiler_list=cxx_compiler.get(build_platform,cxx_compiler['default']) | |
12 | return' '.join(possible_compiler_list) | |
13 | def configure(conf): | |
14 | try: | |
15 | test_for_compiler=conf.options.check_cxx_compiler or default_compilers() | |
16 | except AttributeError: | |
17 | conf.fatal("Add options(opt): opt.load('compiler_cxx')") | |
18 | for compiler in re.split('[ ,]+',test_for_compiler): | |
19 | conf.env.stash() | |
20 | conf.start_msg('Checking for %r (C++ compiler)'%compiler) | |
21 | try: | |
22 | conf.load(compiler) | |
23 | except conf.errors.ConfigurationError as e: | |
24 | conf.env.revert() | |
25 | conf.end_msg(False) | |
26 | debug('compiler_cxx: %r',e) | |
27 | else: | |
28 | if conf.env.CXX: | |
29 | conf.end_msg(conf.env.get_flat('CXX')) | |
30 | conf.env.COMPILER_CXX=compiler | |
31 | conf.env.commit() | |
32 | break | |
33 | conf.env.revert() | |
34 | conf.end_msg(False) | |
35 | else: | |
36 | conf.fatal('could not configure a C++ compiler!') | |
37 | def options(opt): | |
38 | test_for_compiler=default_compilers() | |
39 | opt.load_special_tools('cxx_*.py') | |
40 | cxx_compiler_opts=opt.add_option_group('Configuration options') | |
41 | cxx_compiler_opts.add_option('--check-cxx-compiler',default=None,help='list of C++ compilers to try [%s]'%test_for_compiler,dest="check_cxx_compiler") | |
42 | for x in test_for_compiler.split(): | |
43 | opt.load('%s'%x) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Utils,Logs | |
6 | d_compiler={'default':['gdc','dmd','ldc2']} | |
7 | def default_compilers(): | |
8 | build_platform=Utils.unversioned_sys_platform() | |
9 | possible_compiler_list=d_compiler.get(build_platform,d_compiler['default']) | |
10 | return' '.join(possible_compiler_list) | |
11 | def configure(conf): | |
12 | try: | |
13 | test_for_compiler=conf.options.check_d_compiler or default_compilers() | |
14 | except AttributeError: | |
15 | conf.fatal("Add options(opt): opt.load('compiler_d')") | |
16 | for compiler in re.split('[ ,]+',test_for_compiler): | |
17 | conf.env.stash() | |
18 | conf.start_msg('Checking for %r (D compiler)'%compiler) | |
19 | try: | |
20 | conf.load(compiler) | |
21 | except conf.errors.ConfigurationError as e: | |
22 | conf.env.revert() | |
23 | conf.end_msg(False) | |
24 | Logs.debug('compiler_d: %r',e) | |
25 | else: | |
26 | if conf.env.D: | |
27 | conf.end_msg(conf.env.get_flat('D')) | |
28 | conf.env.COMPILER_D=compiler | |
29 | conf.env.commit() | |
30 | break | |
31 | conf.env.revert() | |
32 | conf.end_msg(False) | |
33 | else: | |
34 | conf.fatal('could not configure a D compiler!') | |
35 | def options(opt): | |
36 | test_for_compiler=default_compilers() | |
37 | d_compiler_opts=opt.add_option_group('Configuration options') | |
38 | d_compiler_opts.add_option('--check-d-compiler',default=None,help='list of D compilers to try [%s]'%test_for_compiler,dest='check_d_compiler') | |
39 | for x in test_for_compiler.split(): | |
40 | opt.load('%s'%x) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Utils,Logs | |
6 | from waflib.Tools import fc | |
7 | fc_compiler={'win32':['gfortran','ifort'],'darwin':['gfortran','g95','ifort'],'linux':['gfortran','g95','ifort'],'java':['gfortran','g95','ifort'],'default':['gfortran'],'aix':['gfortran']} | |
8 | def default_compilers(): | |
9 | build_platform=Utils.unversioned_sys_platform() | |
10 | possible_compiler_list=fc_compiler.get(build_platform,fc_compiler['default']) | |
11 | return' '.join(possible_compiler_list) | |
12 | def configure(conf): | |
13 | try: | |
14 | test_for_compiler=conf.options.check_fortran_compiler or default_compilers() | |
15 | except AttributeError: | |
16 | conf.fatal("Add options(opt): opt.load('compiler_fc')") | |
17 | for compiler in re.split('[ ,]+',test_for_compiler): | |
18 | conf.env.stash() | |
19 | conf.start_msg('Checking for %r (Fortran compiler)'%compiler) | |
20 | try: | |
21 | conf.load(compiler) | |
22 | except conf.errors.ConfigurationError as e: | |
23 | conf.env.revert() | |
24 | conf.end_msg(False) | |
25 | Logs.debug('compiler_fortran: %r',e) | |
26 | else: | |
27 | if conf.env.FC: | |
28 | conf.end_msg(conf.env.get_flat('FC')) | |
29 | conf.env.COMPILER_FORTRAN=compiler | |
30 | conf.env.commit() | |
31 | break | |
32 | conf.env.revert() | |
33 | conf.end_msg(False) | |
34 | else: | |
35 | conf.fatal('could not configure a Fortran compiler!') | |
36 | def options(opt): | |
37 | test_for_compiler=default_compilers() | |
38 | opt.load_special_tools('fc_*.py') | |
39 | fortran_compiler_opts=opt.add_option_group('Configuration options') | |
40 | fortran_compiler_opts.add_option('--check-fortran-compiler',default=None,help='list of Fortran compiler to try [%s]'%test_for_compiler,dest="check_fortran_compiler") | |
41 | for x in test_for_compiler.split(): | |
42 | opt.load('%s'%x) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Utils,Task,Options,Errors | |
5 | from waflib.TaskGen import before_method,after_method,feature | |
6 | from waflib.Tools import ccroot | |
7 | from waflib.Configure import conf | |
8 | ccroot.USELIB_VARS['cs']=set(['CSFLAGS','ASSEMBLIES','RESOURCES']) | |
9 | ccroot.lib_patterns['csshlib']=['%s'] | |
10 | @feature('cs') | |
11 | @before_method('process_source') | |
12 | def apply_cs(self): | |
13 | cs_nodes=[] | |
14 | no_nodes=[] | |
15 | for x in self.to_nodes(self.source): | |
16 | if x.name.endswith('.cs'): | |
17 | cs_nodes.append(x) | |
18 | else: | |
19 | no_nodes.append(x) | |
20 | self.source=no_nodes | |
21 | bintype=getattr(self,'bintype',self.gen.endswith('.dll')and'library'or'exe') | |
22 | self.cs_task=tsk=self.create_task('mcs',cs_nodes,self.path.find_or_declare(self.gen)) | |
23 | tsk.env.CSTYPE='/target:%s'%bintype | |
24 | tsk.env.OUT='/out:%s'%tsk.outputs[0].abspath() | |
25 | self.env.append_value('CSFLAGS','/platform:%s'%getattr(self,'platform','anycpu')) | |
26 | inst_to=getattr(self,'install_path',bintype=='exe'and'${BINDIR}'or'${LIBDIR}') | |
27 | if inst_to: | |
28 | mod=getattr(self,'chmod',bintype=='exe'and Utils.O755 or Utils.O644) | |
29 | self.install_task=self.add_install_files(install_to=inst_to,install_from=self.cs_task.outputs[:],chmod=mod) | |
30 | @feature('cs') | |
31 | @after_method('apply_cs') | |
32 | def use_cs(self): | |
33 | names=self.to_list(getattr(self,'use',[])) | |
34 | get=self.bld.get_tgen_by_name | |
35 | for x in names: | |
36 | try: | |
37 | y=get(x) | |
38 | except Errors.WafError: | |
39 | self.env.append_value('CSFLAGS','/reference:%s'%x) | |
40 | continue | |
41 | y.post() | |
42 | tsk=getattr(y,'cs_task',None)or getattr(y,'link_task',None) | |
43 | if not tsk: | |
44 | self.bld.fatal('cs task has no link task for use %r'%self) | |
45 | self.cs_task.dep_nodes.extend(tsk.outputs) | |
46 | self.cs_task.set_run_after(tsk) | |
47 | self.env.append_value('CSFLAGS','/reference:%s'%tsk.outputs[0].abspath()) | |
48 | @feature('cs') | |
49 | @after_method('apply_cs','use_cs') | |
50 | def debug_cs(self): | |
51 | csdebug=getattr(self,'csdebug',self.env.CSDEBUG) | |
52 | if not csdebug: | |
53 | return | |
54 | node=self.cs_task.outputs[0] | |
55 | if self.env.CS_NAME=='mono': | |
56 | out=node.parent.find_or_declare(node.name+'.mdb') | |
57 | else: | |
58 | out=node.change_ext('.pdb') | |
59 | self.cs_task.outputs.append(out) | |
60 | if getattr(self,'install_task',None): | |
61 | self.pdb_install_task=self.add_install_files(install_to=self.install_task.install_to,install_from=out) | |
62 | if csdebug=='pdbonly': | |
63 | val=['/debug+','/debug:pdbonly'] | |
64 | elif csdebug=='full': | |
65 | val=['/debug+','/debug:full'] | |
66 | else: | |
67 | val=['/debug-'] | |
68 | self.env.append_value('CSFLAGS',val) | |
69 | @feature('cs') | |
70 | @after_method('debug_cs') | |
71 | def doc_cs(self): | |
72 | csdoc=getattr(self,'csdoc',self.env.CSDOC) | |
73 | if not csdoc: | |
74 | return | |
75 | node=self.cs_task.outputs[0] | |
76 | out=node.change_ext('.xml') | |
77 | self.cs_task.outputs.append(out) | |
78 | if getattr(self,'install_task',None): | |
79 | self.doc_install_task=self.add_install_files(install_to=self.install_task.install_to,install_from=out) | |
80 | self.env.append_value('CSFLAGS','/doc:%s'%out.abspath()) | |
81 | class mcs(Task.Task): | |
82 | color='YELLOW' | |
83 | run_str='${MCS} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' | |
84 | def split_argfile(self,cmd): | |
85 | inline=[cmd[0]] | |
86 | infile=[] | |
87 | for x in cmd[1:]: | |
88 | if x.lower()=='/noconfig': | |
89 | inline.append(x) | |
90 | else: | |
91 | infile.append(self.quote_flag(x)) | |
92 | return(inline,infile) | |
93 | def configure(conf): | |
94 | csc=getattr(Options.options,'cscbinary',None) | |
95 | if csc: | |
96 | conf.env.MCS=csc | |
97 | conf.find_program(['csc','mcs','gmcs'],var='MCS') | |
98 | conf.env.ASS_ST='/r:%s' | |
99 | conf.env.RES_ST='/resource:%s' | |
100 | conf.env.CS_NAME='csc' | |
101 | if str(conf.env.MCS).lower().find('mcs')>-1: | |
102 | conf.env.CS_NAME='mono' | |
103 | def options(opt): | |
104 | opt.add_option('--with-csc-binary',type='string',dest='cscbinary') | |
105 | class fake_csshlib(Task.Task): | |
106 | color='YELLOW' | |
107 | inst_to=None | |
108 | def runnable_status(self): | |
109 | return Task.SKIP_ME | |
110 | @conf | |
111 | def read_csshlib(self,name,paths=[]): | |
112 | return self(name=name,features='fake_lib',lib_paths=paths,lib_type='csshlib') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import TaskGen,Task | |
5 | from waflib.Tools import c_preproc | |
6 | from waflib.Tools.ccroot import link_task,stlink_task | |
7 | @TaskGen.extension('.cpp','.cc','.cxx','.C','.c++') | |
8 | def cxx_hook(self,node): | |
9 | return self.create_compiled_task('cxx',node) | |
10 | if not'.c'in TaskGen.task_gen.mappings: | |
11 | TaskGen.task_gen.mappings['.c']=TaskGen.task_gen.mappings['.cpp'] | |
12 | class cxx(Task.Task): | |
13 | run_str='${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' | |
14 | vars=['CXXDEPS'] | |
15 | ext_in=['.h'] | |
16 | scan=c_preproc.scan | |
17 | class cxxprogram(link_task): | |
18 | run_str='${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' | |
19 | vars=['LINKDEPS'] | |
20 | ext_out=['.bin'] | |
21 | inst_to='${BINDIR}' | |
22 | class cxxshlib(cxxprogram): | |
23 | inst_to='${LIBDIR}' | |
24 | class cxxstlib(stlink_task): | |
25 | pass |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Utils,Task,Errors | |
5 | from waflib.TaskGen import taskgen_method,feature,extension | |
6 | from waflib.Tools import d_scan,d_config | |
7 | from waflib.Tools.ccroot import link_task,stlink_task | |
8 | class d(Task.Task): | |
9 | color='GREEN' | |
10 | run_str='${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_SRC_F:SRC} ${D_TGT_F:TGT}' | |
11 | scan=d_scan.scan | |
12 | class d_with_header(d): | |
13 | run_str='${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_HDR_F:tgt.outputs[1].bldpath()} ${D_SRC_F:SRC} ${D_TGT_F:tgt.outputs[0].bldpath()}' | |
14 | class d_header(Task.Task): | |
15 | color='BLUE' | |
16 | run_str='${D} ${D_HEADER} ${SRC}' | |
17 | class dprogram(link_task): | |
18 | run_str='${D_LINKER} ${LINKFLAGS} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F:TGT} ${RPATH_ST:RPATH} ${DSTLIB_MARKER} ${DSTLIBPATH_ST:STLIBPATH} ${DSTLIB_ST:STLIB} ${DSHLIB_MARKER} ${DLIBPATH_ST:LIBPATH} ${DSHLIB_ST:LIB}' | |
19 | inst_to='${BINDIR}' | |
20 | class dshlib(dprogram): | |
21 | inst_to='${LIBDIR}' | |
22 | class dstlib(stlink_task): | |
23 | pass | |
24 | @extension('.d','.di','.D') | |
25 | def d_hook(self,node): | |
26 | ext=Utils.destos_to_binfmt(self.env.DEST_OS)=='pe'and'obj'or'o' | |
27 | out='%s.%d.%s'%(node.name,self.idx,ext) | |
28 | def create_compiled_task(self,name,node): | |
29 | task=self.create_task(name,node,node.parent.find_or_declare(out)) | |
30 | try: | |
31 | self.compiled_tasks.append(task) | |
32 | except AttributeError: | |
33 | self.compiled_tasks=[task] | |
34 | return task | |
35 | if getattr(self,'generate_headers',None): | |
36 | tsk=create_compiled_task(self,'d_with_header',node) | |
37 | tsk.outputs.append(node.change_ext(self.env.DHEADER_ext)) | |
38 | else: | |
39 | tsk=create_compiled_task(self,'d',node) | |
40 | return tsk | |
41 | @taskgen_method | |
42 | def generate_header(self,filename): | |
43 | try: | |
44 | self.header_lst.append([filename,self.install_path]) | |
45 | except AttributeError: | |
46 | self.header_lst=[[filename,self.install_path]] | |
47 | @feature('d') | |
48 | def process_header(self): | |
49 | for i in getattr(self,'header_lst',[]): | |
50 | node=self.path.find_resource(i[0]) | |
51 | if not node: | |
52 | raise Errors.WafError('file %r not found on d obj'%i[0]) | |
53 | self.create_task('d_header',node,node.change_ext('.di')) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Utils | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def d_platform_flags(self): | |
8 | v=self.env | |
9 | if not v.DEST_OS: | |
10 | v.DEST_OS=Utils.unversioned_sys_platform() | |
11 | binfmt=Utils.destos_to_binfmt(self.env.DEST_OS) | |
12 | if binfmt=='pe': | |
13 | v.dprogram_PATTERN='%s.exe' | |
14 | v.dshlib_PATTERN='lib%s.dll' | |
15 | v.dstlib_PATTERN='lib%s.a' | |
16 | elif binfmt=='mac-o': | |
17 | v.dprogram_PATTERN='%s' | |
18 | v.dshlib_PATTERN='lib%s.dylib' | |
19 | v.dstlib_PATTERN='lib%s.a' | |
20 | else: | |
21 | v.dprogram_PATTERN='%s' | |
22 | v.dshlib_PATTERN='lib%s.so' | |
23 | v.dstlib_PATTERN='lib%s.a' | |
24 | DLIB=''' | |
25 | version(D_Version2) { | |
26 | import std.stdio; | |
27 | int main() { | |
28 | writefln("phobos2"); | |
29 | return 0; | |
30 | } | |
31 | } else { | |
32 | version(Tango) { | |
33 | import tango.stdc.stdio; | |
34 | int main() { | |
35 | printf("tango"); | |
36 | return 0; | |
37 | } | |
38 | } else { | |
39 | import std.stdio; | |
40 | int main() { | |
41 | writefln("phobos1"); | |
42 | return 0; | |
43 | } | |
44 | } | |
45 | } | |
46 | ''' | |
47 | @conf | |
48 | def check_dlibrary(self,execute=True): | |
49 | ret=self.check_cc(features='d dprogram',fragment=DLIB,compile_filename='test.d',execute=execute,define_ret=True) | |
50 | if execute: | |
51 | self.env.DLIBRARY=ret.strip() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Utils | |
6 | def filter_comments(filename): | |
7 | txt=Utils.readf(filename) | |
8 | i=0 | |
9 | buf=[] | |
10 | max=len(txt) | |
11 | begin=0 | |
12 | while i<max: | |
13 | c=txt[i] | |
14 | if c=='"'or c=="'": | |
15 | buf.append(txt[begin:i]) | |
16 | delim=c | |
17 | i+=1 | |
18 | while i<max: | |
19 | c=txt[i] | |
20 | if c==delim: | |
21 | break | |
22 | elif c=='\\': | |
23 | i+=1 | |
24 | i+=1 | |
25 | i+=1 | |
26 | begin=i | |
27 | elif c=='/': | |
28 | buf.append(txt[begin:i]) | |
29 | i+=1 | |
30 | if i==max: | |
31 | break | |
32 | c=txt[i] | |
33 | if c=='+': | |
34 | i+=1 | |
35 | nesting=1 | |
36 | c=None | |
37 | while i<max: | |
38 | prev=c | |
39 | c=txt[i] | |
40 | if prev=='/'and c=='+': | |
41 | nesting+=1 | |
42 | c=None | |
43 | elif prev=='+'and c=='/': | |
44 | nesting-=1 | |
45 | if nesting==0: | |
46 | break | |
47 | c=None | |
48 | i+=1 | |
49 | elif c=='*': | |
50 | i+=1 | |
51 | c=None | |
52 | while i<max: | |
53 | prev=c | |
54 | c=txt[i] | |
55 | if prev=='*'and c=='/': | |
56 | break | |
57 | i+=1 | |
58 | elif c=='/': | |
59 | i+=1 | |
60 | while i<max and txt[i]!='\n': | |
61 | i+=1 | |
62 | else: | |
63 | begin=i-1 | |
64 | continue | |
65 | i+=1 | |
66 | begin=i | |
67 | buf.append(' ') | |
68 | else: | |
69 | i+=1 | |
70 | buf.append(txt[begin:]) | |
71 | return buf | |
72 | class d_parser(object): | |
73 | def __init__(self,env,incpaths): | |
74 | self.allnames=[] | |
75 | self.re_module=re.compile(r"module\s+([^;]+)") | |
76 | self.re_import=re.compile(r"import\s+([^;]+)") | |
77 | self.re_import_bindings=re.compile("([^:]+):(.*)") | |
78 | self.re_import_alias=re.compile("[^=]+=(.+)") | |
79 | self.env=env | |
80 | self.nodes=[] | |
81 | self.names=[] | |
82 | self.incpaths=incpaths | |
83 | def tryfind(self,filename): | |
84 | found=0 | |
85 | for n in self.incpaths: | |
86 | found=n.find_resource(filename.replace('.','/')+'.d') | |
87 | if found: | |
88 | self.nodes.append(found) | |
89 | self.waiting.append(found) | |
90 | break | |
91 | if not found: | |
92 | if not filename in self.names: | |
93 | self.names.append(filename) | |
94 | def get_strings(self,code): | |
95 | self.module='' | |
96 | lst=[] | |
97 | mod_name=self.re_module.search(code) | |
98 | if mod_name: | |
99 | self.module=re.sub(r'\s+','',mod_name.group(1)) | |
100 | import_iterator=self.re_import.finditer(code) | |
101 | if import_iterator: | |
102 | for import_match in import_iterator: | |
103 | import_match_str=re.sub(r'\s+','',import_match.group(1)) | |
104 | bindings_match=self.re_import_bindings.match(import_match_str) | |
105 | if bindings_match: | |
106 | import_match_str=bindings_match.group(1) | |
107 | matches=import_match_str.split(',') | |
108 | for match in matches: | |
109 | alias_match=self.re_import_alias.match(match) | |
110 | if alias_match: | |
111 | match=alias_match.group(1) | |
112 | lst.append(match) | |
113 | return lst | |
114 | def start(self,node): | |
115 | self.waiting=[node] | |
116 | while self.waiting: | |
117 | nd=self.waiting.pop(0) | |
118 | self.iter(nd) | |
119 | def iter(self,node): | |
120 | path=node.abspath() | |
121 | code="".join(filter_comments(path)) | |
122 | names=self.get_strings(code) | |
123 | for x in names: | |
124 | if x in self.allnames: | |
125 | continue | |
126 | self.allnames.append(x) | |
127 | self.tryfind(x) | |
128 | def scan(self): | |
129 | env=self.env | |
130 | gruik=d_parser(env,self.generator.includes_nodes) | |
131 | node=self.inputs[0] | |
132 | gruik.start(node) | |
133 | nodes=gruik.nodes | |
134 | names=gruik.names | |
135 | return(nodes,names) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Task,Errors | |
5 | from waflib.TaskGen import taskgen_method,before_method | |
6 | @taskgen_method | |
7 | def add_dbus_file(self,filename,prefix,mode): | |
8 | if not hasattr(self,'dbus_lst'): | |
9 | self.dbus_lst=[] | |
10 | if not'process_dbus'in self.meths: | |
11 | self.meths.append('process_dbus') | |
12 | self.dbus_lst.append([filename,prefix,mode]) | |
13 | @before_method('process_source') | |
14 | def process_dbus(self): | |
15 | for filename,prefix,mode in getattr(self,'dbus_lst',[]): | |
16 | node=self.path.find_resource(filename) | |
17 | if not node: | |
18 | raise Errors.WafError('file not found '+filename) | |
19 | tsk=self.create_task('dbus_binding_tool',node,node.change_ext('.h')) | |
20 | tsk.env.DBUS_BINDING_TOOL_PREFIX=prefix | |
21 | tsk.env.DBUS_BINDING_TOOL_MODE=mode | |
22 | class dbus_binding_tool(Task.Task): | |
23 | color='BLUE' | |
24 | ext_out=['.h'] | |
25 | run_str='${DBUS_BINDING_TOOL} --prefix=${DBUS_BINDING_TOOL_PREFIX} --mode=${DBUS_BINDING_TOOL_MODE} --output=${TGT} ${SRC}' | |
26 | shell=True | |
27 | def configure(conf): | |
28 | conf.find_program('dbus-binding-tool',var='DBUS_BINDING_TOOL') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import sys | |
5 | from waflib.Tools import ar,d | |
6 | from waflib.Configure import conf | |
7 | @conf | |
8 | def find_dmd(conf): | |
9 | conf.find_program(['dmd','dmd2','ldc'],var='D') | |
10 | out=conf.cmd_and_log(conf.env.D+['--help']) | |
11 | if out.find("D Compiler v")==-1: | |
12 | out=conf.cmd_and_log(conf.env.D+['-version']) | |
13 | if out.find("based on DMD v1.")==-1: | |
14 | conf.fatal("detected compiler is not dmd/ldc") | |
15 | @conf | |
16 | def common_flags_ldc(conf): | |
17 | v=conf.env | |
18 | v.DFLAGS=['-d-version=Posix'] | |
19 | v.LINKFLAGS=[] | |
20 | v.DFLAGS_dshlib=['-relocation-model=pic'] | |
21 | @conf | |
22 | def common_flags_dmd(conf): | |
23 | v=conf.env | |
24 | v.D_SRC_F=['-c'] | |
25 | v.D_TGT_F='-of%s' | |
26 | v.D_LINKER=v.D | |
27 | v.DLNK_SRC_F='' | |
28 | v.DLNK_TGT_F='-of%s' | |
29 | v.DINC_ST='-I%s' | |
30 | v.DSHLIB_MARKER=v.DSTLIB_MARKER='' | |
31 | v.DSTLIB_ST=v.DSHLIB_ST='-L-l%s' | |
32 | v.DSTLIBPATH_ST=v.DLIBPATH_ST='-L-L%s' | |
33 | v.LINKFLAGS_dprogram=['-quiet'] | |
34 | v.DFLAGS_dshlib=['-fPIC'] | |
35 | v.LINKFLAGS_dshlib=['-L-shared'] | |
36 | v.DHEADER_ext='.di' | |
37 | v.DFLAGS_d_with_header=['-H','-Hf'] | |
38 | v.D_HDR_F='%s' | |
39 | def configure(conf): | |
40 | conf.find_dmd() | |
41 | if sys.platform=='win32': | |
42 | out=conf.cmd_and_log(conf.env.D+['--help']) | |
43 | if out.find('D Compiler v2.')>-1: | |
44 | conf.fatal('dmd2 on Windows is not supported, use gdc or ldc2 instead') | |
45 | conf.load('ar') | |
46 | conf.load('d') | |
47 | conf.common_flags_dmd() | |
48 | conf.d_platform_flags() | |
49 | if str(conf.env.D).find('ldc')>-1: | |
50 | conf.common_flags_ldc() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | typos={'feature':'features','sources':'source','targets':'target','include':'includes','export_include':'export_includes','define':'defines','importpath':'includes','installpath':'install_path','iscopy':'is_copy','uses':'use',} | |
5 | meths_typos=['__call__','program','shlib','stlib','objects'] | |
6 | import sys | |
7 | from waflib import Logs,Build,Node,Task,TaskGen,ConfigSet,Errors,Utils | |
8 | from waflib.Tools import ccroot | |
9 | def check_same_targets(self): | |
10 | mp=Utils.defaultdict(list) | |
11 | uids={} | |
12 | def check_task(tsk): | |
13 | if not isinstance(tsk,Task.Task): | |
14 | return | |
15 | if hasattr(tsk,'no_errcheck_out'): | |
16 | return | |
17 | for node in tsk.outputs: | |
18 | mp[node].append(tsk) | |
19 | try: | |
20 | uids[tsk.uid()].append(tsk) | |
21 | except KeyError: | |
22 | uids[tsk.uid()]=[tsk] | |
23 | for g in self.groups: | |
24 | for tg in g: | |
25 | try: | |
26 | for tsk in tg.tasks: | |
27 | check_task(tsk) | |
28 | except AttributeError: | |
29 | check_task(tg) | |
30 | dupe=False | |
31 | for(k,v)in mp.items(): | |
32 | if len(v)>1: | |
33 | dupe=True | |
34 | msg='* Node %r is created more than once%s. The task generators are:'%(k,Logs.verbose==1 and" (full message on 'waf -v -v')"or"") | |
35 | Logs.error(msg) | |
36 | for x in v: | |
37 | if Logs.verbose>1: | |
38 | Logs.error(' %d. %r',1+v.index(x),x.generator) | |
39 | else: | |
40 | Logs.error(' %d. %r in %r',1+v.index(x),x.generator.name,getattr(x.generator,'path',None)) | |
41 | Logs.error('If you think that this is an error, set no_errcheck_out on the task instance') | |
42 | if not dupe: | |
43 | for(k,v)in uids.items(): | |
44 | if len(v)>1: | |
45 | Logs.error('* Several tasks use the same identifier. Please check the information on\n https://waf.io/apidocs/Task.html?highlight=uid#waflib.Task.Task.uid') | |
46 | tg_details=tsk.generator.name | |
47 | if Logs.verbose>2: | |
48 | tg_details=tsk.generator | |
49 | for tsk in v: | |
50 | Logs.error(' - object %r (%r) defined in %r',tsk.__class__.__name__,tsk,tg_details) | |
51 | def check_invalid_constraints(self): | |
52 | feat=set() | |
53 | for x in list(TaskGen.feats.values()): | |
54 | feat.union(set(x)) | |
55 | for(x,y)in TaskGen.task_gen.prec.items(): | |
56 | feat.add(x) | |
57 | feat.union(set(y)) | |
58 | ext=set() | |
59 | for x in TaskGen.task_gen.mappings.values(): | |
60 | ext.add(x.__name__) | |
61 | invalid=ext&feat | |
62 | if invalid: | |
63 | Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method',list(invalid)) | |
64 | for cls in list(Task.classes.values()): | |
65 | if sys.hexversion>0x3000000 and issubclass(cls,Task.Task)and isinstance(cls.hcode,str): | |
66 | raise Errors.WafError('Class %r has hcode value %r of type <str>, expecting <bytes> (use Utils.h_cmd() ?)'%(cls,cls.hcode)) | |
67 | for x in('before','after'): | |
68 | for y in Utils.to_list(getattr(cls,x,[])): | |
69 | if not Task.classes.get(y): | |
70 | Logs.error('Erroneous order constraint %r=%r on task class %r',x,y,cls.__name__) | |
71 | if getattr(cls,'rule',None): | |
72 | Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")',cls.__name__) | |
73 | def replace(m): | |
74 | oldcall=getattr(Build.BuildContext,m) | |
75 | def call(self,*k,**kw): | |
76 | ret=oldcall(self,*k,**kw) | |
77 | for x in typos: | |
78 | if x in kw: | |
79 | if x=='iscopy'and'subst'in getattr(self,'features',''): | |
80 | continue | |
81 | Logs.error('Fix the typo %r -> %r on %r',x,typos[x],ret) | |
82 | return ret | |
83 | setattr(Build.BuildContext,m,call) | |
84 | def enhance_lib(): | |
85 | for m in meths_typos: | |
86 | replace(m) | |
87 | def ant_glob(self,*k,**kw): | |
88 | if k: | |
89 | lst=Utils.to_list(k[0]) | |
90 | for pat in lst: | |
91 | sp=pat.split('/') | |
92 | if'..'in sp: | |
93 | Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'",k[0]) | |
94 | if'.'in sp: | |
95 | Logs.error("In ant_glob pattern %r: '.' means 'one dot', not 'current directory'",k[0]) | |
96 | return self.old_ant_glob(*k,**kw) | |
97 | Node.Node.old_ant_glob=Node.Node.ant_glob | |
98 | Node.Node.ant_glob=ant_glob | |
99 | def ant_iter(self,accept=None,maxdepth=25,pats=[],dir=False,src=True,remove=True,quiet=False): | |
100 | if remove: | |
101 | try: | |
102 | if self.is_child_of(self.ctx.bldnode)and not quiet: | |
103 | quiet=True | |
104 | Logs.error('Calling ant_glob on build folders (%r) is dangerous: add quiet=True / remove=False',self) | |
105 | except AttributeError: | |
106 | pass | |
107 | return self.old_ant_iter(accept,maxdepth,pats,dir,src,remove,quiet) | |
108 | Node.Node.old_ant_iter=Node.Node.ant_iter | |
109 | Node.Node.ant_iter=ant_iter | |
110 | old=Task.is_before | |
111 | def is_before(t1,t2): | |
112 | ret=old(t1,t2) | |
113 | if ret and old(t2,t1): | |
114 | Logs.error('Contradictory order constraints in classes %r %r',t1,t2) | |
115 | return ret | |
116 | Task.is_before=is_before | |
117 | def check_err_features(self): | |
118 | lst=self.to_list(self.features) | |
119 | if'shlib'in lst: | |
120 | Logs.error('feature shlib -> cshlib, dshlib or cxxshlib') | |
121 | for x in('c','cxx','d','fc'): | |
122 | if not x in lst and lst and lst[0]in[x+y for y in('program','shlib','stlib')]: | |
123 | Logs.error('%r features is probably missing %r',self,x) | |
124 | TaskGen.feature('*')(check_err_features) | |
125 | def check_err_order(self): | |
126 | if not hasattr(self,'rule')and not'subst'in Utils.to_list(self.features): | |
127 | for x in('before','after','ext_in','ext_out'): | |
128 | if hasattr(self,x): | |
129 | Logs.warn('Erroneous order constraint %r on non-rule based task generator %r',x,self) | |
130 | else: | |
131 | for x in('before','after'): | |
132 | for y in self.to_list(getattr(self,x,[])): | |
133 | if not Task.classes.get(y): | |
134 | Logs.error('Erroneous order constraint %s=%r on %r (no such class)',x,y,self) | |
135 | TaskGen.feature('*')(check_err_order) | |
136 | def check_compile(self): | |
137 | check_invalid_constraints(self) | |
138 | try: | |
139 | ret=self.orig_compile() | |
140 | finally: | |
141 | check_same_targets(self) | |
142 | return ret | |
143 | Build.BuildContext.orig_compile=Build.BuildContext.compile | |
144 | Build.BuildContext.compile=check_compile | |
145 | def use_rec(self,name,**kw): | |
146 | try: | |
147 | y=self.bld.get_tgen_by_name(name) | |
148 | except Errors.WafError: | |
149 | pass | |
150 | else: | |
151 | idx=self.bld.get_group_idx(self) | |
152 | odx=self.bld.get_group_idx(y) | |
153 | if odx>idx: | |
154 | msg="Invalid 'use' across build groups:" | |
155 | if Logs.verbose>1: | |
156 | msg+='\n target %r\n uses:\n %r'%(self,y) | |
157 | else: | |
158 | msg+=" %r uses %r (try 'waf -v -v' for the full error)"%(self.name,name) | |
159 | raise Errors.WafError(msg) | |
160 | self.orig_use_rec(name,**kw) | |
161 | TaskGen.task_gen.orig_use_rec=TaskGen.task_gen.use_rec | |
162 | TaskGen.task_gen.use_rec=use_rec | |
163 | def _getattr(self,name,default=None): | |
164 | if name=='append'or name=='add': | |
165 | raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique') | |
166 | elif name=='prepend': | |
167 | raise Errors.WafError('env.prepend does not exist: use env.prepend_value') | |
168 | if name in self.__slots__: | |
169 | return super(ConfigSet.ConfigSet,self).__getattr__(name,default) | |
170 | else: | |
171 | return self[name] | |
172 | ConfigSet.ConfigSet.__getattr__=_getattr | |
173 | def options(opt): | |
174 | enhance_lib() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Utils,Task,Errors | |
5 | from waflib.Tools import ccroot,fc_config,fc_scan | |
6 | from waflib.TaskGen import extension | |
7 | from waflib.Configure import conf | |
8 | ccroot.USELIB_VARS['fc']=set(['FCFLAGS','DEFINES','INCLUDES','FCPPFLAGS']) | |
9 | ccroot.USELIB_VARS['fcprogram_test']=ccroot.USELIB_VARS['fcprogram']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','LDFLAGS']) | |
10 | ccroot.USELIB_VARS['fcshlib']=set(['LIB','STLIB','LIBPATH','STLIBPATH','LINKFLAGS','RPATH','LINKDEPS','LDFLAGS']) | |
11 | ccroot.USELIB_VARS['fcstlib']=set(['ARFLAGS','LINKDEPS']) | |
12 | @extension('.f','.F','.f90','.F90','.for','.FOR','.f95','.F95','.f03','.F03','.f08','.F08') | |
13 | def fc_hook(self,node): | |
14 | return self.create_compiled_task('fc',node) | |
15 | @conf | |
16 | def modfile(conf,name): | |
17 | if name.find(':')>=0: | |
18 | separator=conf.env.FC_SUBMOD_SEPARATOR or'@' | |
19 | modpath=name.split(':') | |
20 | modname=modpath[0]+separator+modpath[-1] | |
21 | suffix=conf.env.FC_SUBMOD_SUFFIX or'.smod' | |
22 | else: | |
23 | modname=name | |
24 | suffix='.mod' | |
25 | return{'lower':modname.lower()+suffix.lower(),'lower.MOD':modname.lower()+suffix.upper(),'UPPER.mod':modname.upper()+suffix.lower(),'UPPER':modname.upper()+suffix.upper()}[conf.env.FC_MOD_CAPITALIZATION or'lower'] | |
26 | def get_fortran_tasks(tsk): | |
27 | bld=tsk.generator.bld | |
28 | tasks=bld.get_tasks_group(bld.get_group_idx(tsk.generator)) | |
29 | return[x for x in tasks if isinstance(x,fc)and not getattr(x,'nomod',None)and not getattr(x,'mod_fortran_done',None)] | |
30 | class fc(Task.Task): | |
31 | color='GREEN' | |
32 | run_str='${FC} ${FCFLAGS} ${FCINCPATH_ST:INCPATHS} ${FCDEFINES_ST:DEFINES} ${_FCMODOUTFLAGS} ${FC_TGT_F}${TGT[0].abspath()} ${FC_SRC_F}${SRC[0].abspath()} ${FCPPFLAGS}' | |
33 | vars=["FORTRANMODPATHFLAG"] | |
34 | def scan(self): | |
35 | tmp=fc_scan.fortran_parser(self.generator.includes_nodes) | |
36 | tmp.task=self | |
37 | tmp.start(self.inputs[0]) | |
38 | return(tmp.nodes,tmp.names) | |
39 | def runnable_status(self): | |
40 | if getattr(self,'mod_fortran_done',None): | |
41 | return super(fc,self).runnable_status() | |
42 | bld=self.generator.bld | |
43 | lst=get_fortran_tasks(self) | |
44 | for tsk in lst: | |
45 | tsk.mod_fortran_done=True | |
46 | for tsk in lst: | |
47 | ret=tsk.runnable_status() | |
48 | if ret==Task.ASK_LATER: | |
49 | for x in lst: | |
50 | x.mod_fortran_done=None | |
51 | return Task.ASK_LATER | |
52 | ins=Utils.defaultdict(set) | |
53 | outs=Utils.defaultdict(set) | |
54 | for tsk in lst: | |
55 | key=tsk.uid() | |
56 | for x in bld.raw_deps[key]: | |
57 | if x.startswith('MOD@'): | |
58 | name=bld.modfile(x.replace('MOD@','')) | |
59 | node=bld.srcnode.find_or_declare(name) | |
60 | tsk.set_outputs(node) | |
61 | outs[node].add(tsk) | |
62 | for tsk in lst: | |
63 | key=tsk.uid() | |
64 | for x in bld.raw_deps[key]: | |
65 | if x.startswith('USE@'): | |
66 | name=bld.modfile(x.replace('USE@','')) | |
67 | node=bld.srcnode.find_resource(name) | |
68 | if node and node not in tsk.outputs: | |
69 | if not node in bld.node_deps[key]: | |
70 | bld.node_deps[key].append(node) | |
71 | ins[node].add(tsk) | |
72 | for k in ins.keys(): | |
73 | for a in ins[k]: | |
74 | a.run_after.update(outs[k]) | |
75 | for x in outs[k]: | |
76 | self.generator.bld.producer.revdeps[x].add(a) | |
77 | tmp=[] | |
78 | for t in outs[k]: | |
79 | tmp.extend(t.outputs) | |
80 | a.dep_nodes.extend(tmp) | |
81 | a.dep_nodes.sort(key=lambda x:x.abspath()) | |
82 | for tsk in lst: | |
83 | try: | |
84 | delattr(tsk,'cache_sig') | |
85 | except AttributeError: | |
86 | pass | |
87 | return super(fc,self).runnable_status() | |
88 | class fcprogram(ccroot.link_task): | |
89 | color='YELLOW' | |
90 | run_str='${FC} ${LINKFLAGS} ${FCLNK_SRC_F}${SRC} ${FCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FCSTLIB_MARKER} ${FCSTLIBPATH_ST:STLIBPATH} ${FCSTLIB_ST:STLIB} ${FCSHLIB_MARKER} ${FCLIBPATH_ST:LIBPATH} ${FCLIB_ST:LIB} ${LDFLAGS}' | |
91 | inst_to='${BINDIR}' | |
92 | class fcshlib(fcprogram): | |
93 | inst_to='${LIBDIR}' | |
94 | class fcstlib(ccroot.stlink_task): | |
95 | pass | |
96 | class fcprogram_test(fcprogram): | |
97 | def runnable_status(self): | |
98 | ret=super(fcprogram_test,self).runnable_status() | |
99 | if ret==Task.SKIP_ME: | |
100 | ret=Task.RUN_ME | |
101 | return ret | |
102 | def exec_command(self,cmd,**kw): | |
103 | bld=self.generator.bld | |
104 | kw['shell']=isinstance(cmd,str) | |
105 | kw['stdout']=kw['stderr']=Utils.subprocess.PIPE | |
106 | kw['cwd']=self.get_cwd() | |
107 | bld.out=bld.err='' | |
108 | bld.to_log('command: %s\n'%cmd) | |
109 | kw['output']=0 | |
110 | try: | |
111 | (bld.out,bld.err)=bld.cmd_and_log(cmd,**kw) | |
112 | except Errors.WafError: | |
113 | return-1 | |
114 | if bld.out: | |
115 | bld.to_log('out: %s\n'%bld.out) | |
116 | if bld.err: | |
117 | bld.to_log('err: %s\n'%bld.err) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re,os,sys,shlex | |
5 | from waflib.Configure import conf | |
6 | from waflib.TaskGen import feature,before_method | |
7 | FC_FRAGMENT=' program main\n end program main\n' | |
8 | FC_FRAGMENT2=' PROGRAM MAIN\n END\n' | |
9 | @conf | |
10 | def fc_flags(conf): | |
11 | v=conf.env | |
12 | v.FC_SRC_F=[] | |
13 | v.FC_TGT_F=['-c','-o'] | |
14 | v.FCINCPATH_ST='-I%s' | |
15 | v.FCDEFINES_ST='-D%s' | |
16 | if not v.LINK_FC: | |
17 | v.LINK_FC=v.FC | |
18 | v.FCLNK_SRC_F=[] | |
19 | v.FCLNK_TGT_F=['-o'] | |
20 | v.FCFLAGS_fcshlib=['-fpic'] | |
21 | v.LINKFLAGS_fcshlib=['-shared'] | |
22 | v.fcshlib_PATTERN='lib%s.so' | |
23 | v.fcstlib_PATTERN='lib%s.a' | |
24 | v.FCLIB_ST='-l%s' | |
25 | v.FCLIBPATH_ST='-L%s' | |
26 | v.FCSTLIB_ST='-l%s' | |
27 | v.FCSTLIBPATH_ST='-L%s' | |
28 | v.FCSTLIB_MARKER='-Wl,-Bstatic' | |
29 | v.FCSHLIB_MARKER='-Wl,-Bdynamic' | |
30 | v.SONAME_ST='-Wl,-h,%s' | |
31 | @conf | |
32 | def fc_add_flags(conf): | |
33 | conf.add_os_flags('FCPPFLAGS',dup=False) | |
34 | conf.add_os_flags('FCFLAGS',dup=False) | |
35 | conf.add_os_flags('LINKFLAGS',dup=False) | |
36 | conf.add_os_flags('LDFLAGS',dup=False) | |
37 | @conf | |
38 | def check_fortran(self,*k,**kw): | |
39 | self.check_cc(fragment=FC_FRAGMENT,compile_filename='test.f',features='fc fcprogram',msg='Compiling a simple fortran app') | |
40 | @conf | |
41 | def check_fc(self,*k,**kw): | |
42 | kw['compiler']='fc' | |
43 | if not'compile_mode'in kw: | |
44 | kw['compile_mode']='fc' | |
45 | if not'type'in kw: | |
46 | kw['type']='fcprogram' | |
47 | if not'compile_filename'in kw: | |
48 | kw['compile_filename']='test.f90' | |
49 | if not'code'in kw: | |
50 | kw['code']=FC_FRAGMENT | |
51 | return self.check(*k,**kw) | |
52 | @conf | |
53 | def fortran_modifier_darwin(conf): | |
54 | v=conf.env | |
55 | v.FCFLAGS_fcshlib=['-fPIC'] | |
56 | v.LINKFLAGS_fcshlib=['-dynamiclib'] | |
57 | v.fcshlib_PATTERN='lib%s.dylib' | |
58 | v.FRAMEWORKPATH_ST='-F%s' | |
59 | v.FRAMEWORK_ST=['-framework'] | |
60 | v.LINKFLAGS_fcstlib=[] | |
61 | v.FCSHLIB_MARKER='' | |
62 | v.FCSTLIB_MARKER='' | |
63 | v.SONAME_ST='' | |
64 | @conf | |
65 | def fortran_modifier_win32(conf): | |
66 | v=conf.env | |
67 | v.fcprogram_PATTERN=v.fcprogram_test_PATTERN='%s.exe' | |
68 | v.fcshlib_PATTERN='%s.dll' | |
69 | v.implib_PATTERN='%s.dll.a' | |
70 | v.IMPLIB_ST='-Wl,--out-implib,%s' | |
71 | v.FCFLAGS_fcshlib=[] | |
72 | v.append_value('LINKFLAGS',['-Wl,--enable-auto-import']) | |
73 | @conf | |
74 | def fortran_modifier_cygwin(conf): | |
75 | fortran_modifier_win32(conf) | |
76 | v=conf.env | |
77 | v.fcshlib_PATTERN='cyg%s.dll' | |
78 | v.append_value('LINKFLAGS_fcshlib',['-Wl,--enable-auto-image-base']) | |
79 | v.FCFLAGS_fcshlib=[] | |
80 | @conf | |
81 | def check_fortran_dummy_main(self,*k,**kw): | |
82 | if not self.env.CC: | |
83 | self.fatal('A c compiler is required for check_fortran_dummy_main') | |
84 | lst=['MAIN__','__MAIN','_MAIN','MAIN_','MAIN'] | |
85 | lst.extend([m.lower()for m in lst]) | |
86 | lst.append('') | |
87 | self.start_msg('Detecting whether we need a dummy main') | |
88 | for main in lst: | |
89 | kw['fortran_main']=main | |
90 | try: | |
91 | self.check_cc(fragment='int %s() { return 0; }\n'%(main or'test'),features='c fcprogram',mandatory=True) | |
92 | if not main: | |
93 | self.env.FC_MAIN=-1 | |
94 | self.end_msg('no') | |
95 | else: | |
96 | self.env.FC_MAIN=main | |
97 | self.end_msg('yes %s'%main) | |
98 | break | |
99 | except self.errors.ConfigurationError: | |
100 | pass | |
101 | else: | |
102 | self.end_msg('not found') | |
103 | self.fatal('could not detect whether fortran requires a dummy main, see the config.log') | |
104 | GCC_DRIVER_LINE=re.compile('^Driving:') | |
105 | POSIX_STATIC_EXT=re.compile(r'\S+\.a') | |
106 | POSIX_LIB_FLAGS=re.compile(r'-l\S+') | |
107 | @conf | |
108 | def is_link_verbose(self,txt): | |
109 | assert isinstance(txt,str) | |
110 | for line in txt.splitlines(): | |
111 | if not GCC_DRIVER_LINE.search(line): | |
112 | if POSIX_STATIC_EXT.search(line)or POSIX_LIB_FLAGS.search(line): | |
113 | return True | |
114 | return False | |
115 | @conf | |
116 | def check_fortran_verbose_flag(self,*k,**kw): | |
117 | self.start_msg('fortran link verbose flag') | |
118 | for x in('-v','--verbose','-verbose','-V'): | |
119 | try: | |
120 | self.check_cc(features='fc fcprogram_test',fragment=FC_FRAGMENT2,compile_filename='test.f',linkflags=[x],mandatory=True) | |
121 | except self.errors.ConfigurationError: | |
122 | pass | |
123 | else: | |
124 | if self.is_link_verbose(self.test_bld.err)or self.is_link_verbose(self.test_bld.out): | |
125 | self.end_msg(x) | |
126 | break | |
127 | else: | |
128 | self.end_msg('failure') | |
129 | self.fatal('Could not obtain the fortran link verbose flag (see config.log)') | |
130 | self.env.FC_VERBOSE_FLAG=x | |
131 | return x | |
132 | LINKFLAGS_IGNORED=[r'-lang*',r'-lcrt[a-zA-Z0-9\.]*\.o',r'-lc$',r'-lSystem',r'-libmil',r'-LIST:*',r'-LNO:*'] | |
133 | if os.name=='nt': | |
134 | LINKFLAGS_IGNORED.extend([r'-lfrt*',r'-luser32',r'-lkernel32',r'-ladvapi32',r'-lmsvcrt',r'-lshell32',r'-lmingw',r'-lmoldname']) | |
135 | else: | |
136 | LINKFLAGS_IGNORED.append(r'-lgcc*') | |
137 | RLINKFLAGS_IGNORED=[re.compile(f)for f in LINKFLAGS_IGNORED] | |
138 | def _match_ignore(line): | |
139 | for i in RLINKFLAGS_IGNORED: | |
140 | if i.match(line): | |
141 | return True | |
142 | return False | |
143 | def parse_fortran_link(lines): | |
144 | final_flags=[] | |
145 | for line in lines: | |
146 | if not GCC_DRIVER_LINE.match(line): | |
147 | _parse_flink_line(line,final_flags) | |
148 | return final_flags | |
149 | SPACE_OPTS=re.compile('^-[LRuYz]$') | |
150 | NOSPACE_OPTS=re.compile('^-[RL]') | |
151 | def _parse_flink_token(lexer,token,tmp_flags): | |
152 | if _match_ignore(token): | |
153 | pass | |
154 | elif token.startswith('-lkernel32')and sys.platform=='cygwin': | |
155 | tmp_flags.append(token) | |
156 | elif SPACE_OPTS.match(token): | |
157 | t=lexer.get_token() | |
158 | if t.startswith('P,'): | |
159 | t=t[2:] | |
160 | for opt in t.split(os.pathsep): | |
161 | tmp_flags.append('-L%s'%opt) | |
162 | elif NOSPACE_OPTS.match(token): | |
163 | tmp_flags.append(token) | |
164 | elif POSIX_LIB_FLAGS.match(token): | |
165 | tmp_flags.append(token) | |
166 | else: | |
167 | pass | |
168 | t=lexer.get_token() | |
169 | return t | |
170 | def _parse_flink_line(line,final_flags): | |
171 | lexer=shlex.shlex(line,posix=True) | |
172 | lexer.whitespace_split=True | |
173 | t=lexer.get_token() | |
174 | tmp_flags=[] | |
175 | while t: | |
176 | t=_parse_flink_token(lexer,t,tmp_flags) | |
177 | final_flags.extend(tmp_flags) | |
178 | return final_flags | |
179 | @conf | |
180 | def check_fortran_clib(self,autoadd=True,*k,**kw): | |
181 | if not self.env.FC_VERBOSE_FLAG: | |
182 | self.fatal('env.FC_VERBOSE_FLAG is not set: execute check_fortran_verbose_flag?') | |
183 | self.start_msg('Getting fortran runtime link flags') | |
184 | try: | |
185 | self.check_cc(fragment=FC_FRAGMENT2,compile_filename='test.f',features='fc fcprogram_test',linkflags=[self.env.FC_VERBOSE_FLAG]) | |
186 | except Exception: | |
187 | self.end_msg(False) | |
188 | if kw.get('mandatory',True): | |
189 | conf.fatal('Could not find the c library flags') | |
190 | else: | |
191 | out=self.test_bld.err | |
192 | flags=parse_fortran_link(out.splitlines()) | |
193 | self.end_msg('ok (%s)'%' '.join(flags)) | |
194 | self.env.LINKFLAGS_CLIB=flags | |
195 | return flags | |
196 | return[] | |
197 | def getoutput(conf,cmd,stdin=False): | |
198 | from waflib import Errors | |
199 | if conf.env.env: | |
200 | env=conf.env.env | |
201 | else: | |
202 | env=dict(os.environ) | |
203 | env['LANG']='C' | |
204 | input=stdin and'\n'.encode()or None | |
205 | try: | |
206 | out,err=conf.cmd_and_log(cmd,env=env,output=0,input=input) | |
207 | except Errors.WafError as e: | |
208 | if not(hasattr(e,'stderr')and hasattr(e,'stdout')): | |
209 | raise e | |
210 | else: | |
211 | out=e.stdout | |
212 | err=e.stderr | |
213 | except Exception: | |
214 | conf.fatal('could not determine the compiler version %r'%cmd) | |
215 | return(out,err) | |
216 | ROUTINES_CODE="""\ | |
217 | subroutine foobar() | |
218 | return | |
219 | end | |
220 | subroutine foo_bar() | |
221 | return | |
222 | end | |
223 | """ | |
224 | MAIN_CODE=""" | |
225 | void %(dummy_func_nounder)s(void); | |
226 | void %(dummy_func_under)s(void); | |
227 | int %(main_func_name)s() { | |
228 | %(dummy_func_nounder)s(); | |
229 | %(dummy_func_under)s(); | |
230 | return 0; | |
231 | } | |
232 | """ | |
233 | @feature('link_main_routines_func') | |
234 | @before_method('process_source') | |
235 | def link_main_routines_tg_method(self): | |
236 | def write_test_file(task): | |
237 | task.outputs[0].write(task.generator.code) | |
238 | bld=self.bld | |
239 | bld(rule=write_test_file,target='main.c',code=MAIN_CODE%self.__dict__) | |
240 | bld(rule=write_test_file,target='test.f',code=ROUTINES_CODE) | |
241 | bld(features='fc fcstlib',source='test.f',target='test') | |
242 | bld(features='c fcprogram',source='main.c',target='app',use='test') | |
243 | def mangling_schemes(): | |
244 | for u in('_',''): | |
245 | for du in('','_'): | |
246 | for c in("lower","upper"): | |
247 | yield(u,du,c) | |
248 | def mangle_name(u,du,c,name): | |
249 | return getattr(name,c)()+u+(name.find('_')!=-1 and du or'') | |
250 | @conf | |
251 | def check_fortran_mangling(self,*k,**kw): | |
252 | if not self.env.CC: | |
253 | self.fatal('A c compiler is required for link_main_routines') | |
254 | if not self.env.FC: | |
255 | self.fatal('A fortran compiler is required for link_main_routines') | |
256 | if not self.env.FC_MAIN: | |
257 | self.fatal('Checking for mangling requires self.env.FC_MAIN (execute "check_fortran_dummy_main" first?)') | |
258 | self.start_msg('Getting fortran mangling scheme') | |
259 | for(u,du,c)in mangling_schemes(): | |
260 | try: | |
261 | self.check_cc(compile_filename=[],features='link_main_routines_func',msg='nomsg',errmsg='nomsg',dummy_func_nounder=mangle_name(u,du,c,'foobar'),dummy_func_under=mangle_name(u,du,c,'foo_bar'),main_func_name=self.env.FC_MAIN) | |
262 | except self.errors.ConfigurationError: | |
263 | pass | |
264 | else: | |
265 | self.end_msg("ok ('%s', '%s', '%s-case')"%(u,du,c)) | |
266 | self.env.FORTRAN_MANGLING=(u,du,c) | |
267 | break | |
268 | else: | |
269 | self.end_msg(False) | |
270 | self.fatal('mangler not found') | |
271 | return(u,du,c) | |
272 | @feature('pyext') | |
273 | @before_method('propagate_uselib_vars','apply_link') | |
274 | def set_lib_pat(self): | |
275 | self.env.fcshlib_PATTERN=self.env.pyext_PATTERN | |
276 | @conf | |
277 | def detect_openmp(self): | |
278 | for x in('-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp'): | |
279 | try: | |
280 | self.check_fc(msg='Checking for OpenMP flag %s'%x,fragment='program main\n call omp_get_num_threads()\nend program main',fcflags=x,linkflags=x,uselib_store='OPENMP') | |
281 | except self.errors.ConfigurationError: | |
282 | pass | |
283 | else: | |
284 | break | |
285 | else: | |
286 | self.fatal('Could not find OpenMP') | |
287 | @conf | |
288 | def check_gfortran_o_space(self): | |
289 | if self.env.FC_NAME!='GFORTRAN'or int(self.env.FC_VERSION[0])>4: | |
290 | return | |
291 | self.env.stash() | |
292 | self.env.FCLNK_TGT_F=['-o',''] | |
293 | try: | |
294 | self.check_fc(msg='Checking if the -o link must be split from arguments',fragment=FC_FRAGMENT,features='fc fcshlib') | |
295 | except self.errors.ConfigurationError: | |
296 | self.env.revert() | |
297 | else: | |
298 | self.env.commit() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | INC_REGEX=r"""(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" | |
6 | USE_REGEX=r"""(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" | |
7 | MOD_REGEX=r"""(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)""" | |
8 | SMD_REGEX=r"""(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)""" | |
9 | re_inc=re.compile(INC_REGEX,re.I) | |
10 | re_use=re.compile(USE_REGEX,re.I) | |
11 | re_mod=re.compile(MOD_REGEX,re.I) | |
12 | re_smd=re.compile(SMD_REGEX,re.I) | |
13 | class fortran_parser(object): | |
14 | def __init__(self,incpaths): | |
15 | self.seen=[] | |
16 | self.nodes=[] | |
17 | self.names=[] | |
18 | self.incpaths=incpaths | |
19 | def find_deps(self,node): | |
20 | txt=node.read() | |
21 | incs=[] | |
22 | uses=[] | |
23 | mods=[] | |
24 | for line in txt.splitlines(): | |
25 | m=re_inc.search(line) | |
26 | if m: | |
27 | incs.append(m.group(1)) | |
28 | m=re_use.search(line) | |
29 | if m: | |
30 | uses.append(m.group(1)) | |
31 | m=re_mod.search(line) | |
32 | if m: | |
33 | mods.append(m.group(1)) | |
34 | m=re_smd.search(line) | |
35 | if m: | |
36 | uses.append(m.group(1)) | |
37 | mods.append('{0}:{1}'.format(m.group(1),m.group(2))) | |
38 | return(incs,uses,mods) | |
39 | def start(self,node): | |
40 | self.waiting=[node] | |
41 | while self.waiting: | |
42 | nd=self.waiting.pop(0) | |
43 | self.iter(nd) | |
44 | def iter(self,node): | |
45 | incs,uses,mods=self.find_deps(node) | |
46 | for x in incs: | |
47 | if x in self.seen: | |
48 | continue | |
49 | self.seen.append(x) | |
50 | self.tryfind_header(x) | |
51 | for x in uses: | |
52 | name="USE@%s"%x | |
53 | if not name in self.names: | |
54 | self.names.append(name) | |
55 | for x in mods: | |
56 | name="MOD@%s"%x | |
57 | if not name in self.names: | |
58 | self.names.append(name) | |
59 | def tryfind_header(self,filename): | |
60 | found=None | |
61 | for n in self.incpaths: | |
62 | found=n.find_resource(filename) | |
63 | if found: | |
64 | self.nodes.append(found) | |
65 | self.waiting.append(found) | |
66 | break | |
67 | if not found: | |
68 | if not filename in self.names: | |
69 | self.names.append(filename) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re | |
5 | from waflib import Task,TaskGen | |
6 | from waflib.Tools import ccroot | |
7 | def decide_ext(self,node): | |
8 | if'cxx'in self.features: | |
9 | return['.lex.cc'] | |
10 | return['.lex.c'] | |
11 | def flexfun(tsk): | |
12 | env=tsk.env | |
13 | bld=tsk.generator.bld | |
14 | wd=bld.variant_dir | |
15 | def to_list(xx): | |
16 | if isinstance(xx,str): | |
17 | return[xx] | |
18 | return xx | |
19 | tsk.last_cmd=lst=[] | |
20 | lst.extend(to_list(env.FLEX)) | |
21 | lst.extend(to_list(env.FLEXFLAGS)) | |
22 | inputs=[a.path_from(tsk.get_cwd())for a in tsk.inputs] | |
23 | if env.FLEX_MSYS: | |
24 | inputs=[x.replace(os.sep,'/')for x in inputs] | |
25 | lst.extend(inputs) | |
26 | lst=[x for x in lst if x] | |
27 | txt=bld.cmd_and_log(lst,cwd=wd,env=env.env or None,quiet=0) | |
28 | tsk.outputs[0].write(txt.replace('\r\n','\n').replace('\r','\n')) | |
29 | TaskGen.declare_chain(name='flex',rule=flexfun,ext_in='.l',decider=decide_ext,) | |
30 | Task.classes['flex'].vars=['FLEXFLAGS','FLEX'] | |
31 | ccroot.USELIB_VARS['c'].add('FLEXFLAGS') | |
32 | ccroot.USELIB_VARS['cxx'].add('FLEXFLAGS') | |
33 | def configure(conf): | |
34 | conf.find_program('flex',var='FLEX') | |
35 | conf.env.FLEXFLAGS=['-t'] | |
36 | if re.search(r"\\msys\\[0-9.]+\\bin\\flex.exe$",conf.env.FLEX[0]): | |
37 | conf.env.FLEX_MSYS=True |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Utils | |
6 | from waflib.Tools import fc,fc_config,fc_scan,ar | |
7 | from waflib.Configure import conf | |
8 | @conf | |
9 | def find_g95(conf): | |
10 | fc=conf.find_program('g95',var='FC') | |
11 | conf.get_g95_version(fc) | |
12 | conf.env.FC_NAME='G95' | |
13 | @conf | |
14 | def g95_flags(conf): | |
15 | v=conf.env | |
16 | v.FCFLAGS_fcshlib=['-fPIC'] | |
17 | v.FORTRANMODFLAG=['-fmod=',''] | |
18 | v.FCFLAGS_DEBUG=['-Werror'] | |
19 | @conf | |
20 | def g95_modifier_win32(conf): | |
21 | fc_config.fortran_modifier_win32(conf) | |
22 | @conf | |
23 | def g95_modifier_cygwin(conf): | |
24 | fc_config.fortran_modifier_cygwin(conf) | |
25 | @conf | |
26 | def g95_modifier_darwin(conf): | |
27 | fc_config.fortran_modifier_darwin(conf) | |
28 | @conf | |
29 | def g95_modifier_platform(conf): | |
30 | dest_os=conf.env.DEST_OS or Utils.unversioned_sys_platform() | |
31 | g95_modifier_func=getattr(conf,'g95_modifier_'+dest_os,None) | |
32 | if g95_modifier_func: | |
33 | g95_modifier_func() | |
34 | @conf | |
35 | def get_g95_version(conf,fc): | |
36 | version_re=re.compile(r"g95\s*(?P<major>\d*)\.(?P<minor>\d*)").search | |
37 | cmd=fc+['--version'] | |
38 | out,err=fc_config.getoutput(conf,cmd,stdin=False) | |
39 | if out: | |
40 | match=version_re(out) | |
41 | else: | |
42 | match=version_re(err) | |
43 | if not match: | |
44 | conf.fatal('cannot determine g95 version') | |
45 | k=match.groupdict() | |
46 | conf.env.FC_VERSION=(k['major'],k['minor']) | |
47 | def configure(conf): | |
48 | conf.find_g95() | |
49 | conf.find_ar() | |
50 | conf.fc_flags() | |
51 | conf.fc_add_flags() | |
52 | conf.g95_flags() | |
53 | conf.g95_modifier_platform() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import waflib.Tools.asm | |
5 | from waflib.Tools import ar | |
6 | def configure(conf): | |
7 | conf.find_program(['gas','gcc'],var='AS') | |
8 | conf.env.AS_TGT_F=['-c','-o'] | |
9 | conf.env.ASLNK_TGT_F=['-o'] | |
10 | conf.find_ar() | |
11 | conf.load('asm') | |
12 | conf.env.ASM_NAME='gas' |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ccroot,ar | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_gcc(conf): | |
8 | cc=conf.find_program(['gcc','cc'],var='CC') | |
9 | conf.get_cc_version(cc,gcc=True) | |
10 | conf.env.CC_NAME='gcc' | |
11 | @conf | |
12 | def gcc_common_flags(conf): | |
13 | v=conf.env | |
14 | v.CC_SRC_F=[] | |
15 | v.CC_TGT_F=['-c','-o'] | |
16 | if not v.LINK_CC: | |
17 | v.LINK_CC=v.CC | |
18 | v.CCLNK_SRC_F=[] | |
19 | v.CCLNK_TGT_F=['-o'] | |
20 | v.CPPPATH_ST='-I%s' | |
21 | v.DEFINES_ST='-D%s' | |
22 | v.LIB_ST='-l%s' | |
23 | v.LIBPATH_ST='-L%s' | |
24 | v.STLIB_ST='-l%s' | |
25 | v.STLIBPATH_ST='-L%s' | |
26 | v.RPATH_ST='-Wl,-rpath,%s' | |
27 | v.SONAME_ST='-Wl,-h,%s' | |
28 | v.SHLIB_MARKER='-Wl,-Bdynamic' | |
29 | v.STLIB_MARKER='-Wl,-Bstatic' | |
30 | v.cprogram_PATTERN='%s' | |
31 | v.CFLAGS_cshlib=['-fPIC'] | |
32 | v.LINKFLAGS_cshlib=['-shared'] | |
33 | v.cshlib_PATTERN='lib%s.so' | |
34 | v.LINKFLAGS_cstlib=['-Wl,-Bstatic'] | |
35 | v.cstlib_PATTERN='lib%s.a' | |
36 | v.LINKFLAGS_MACBUNDLE=['-bundle','-undefined','dynamic_lookup'] | |
37 | v.CFLAGS_MACBUNDLE=['-fPIC'] | |
38 | v.macbundle_PATTERN='%s.bundle' | |
39 | @conf | |
40 | def gcc_modifier_win32(conf): | |
41 | v=conf.env | |
42 | v.cprogram_PATTERN='%s.exe' | |
43 | v.cshlib_PATTERN='%s.dll' | |
44 | v.implib_PATTERN='%s.dll.a' | |
45 | v.IMPLIB_ST='-Wl,--out-implib,%s' | |
46 | v.CFLAGS_cshlib=[] | |
47 | v.append_value('LINKFLAGS',['-Wl,--enable-auto-import']) | |
48 | @conf | |
49 | def gcc_modifier_cygwin(conf): | |
50 | gcc_modifier_win32(conf) | |
51 | v=conf.env | |
52 | v.cshlib_PATTERN='cyg%s.dll' | |
53 | v.append_value('LINKFLAGS_cshlib',['-Wl,--enable-auto-image-base']) | |
54 | v.CFLAGS_cshlib=[] | |
55 | @conf | |
56 | def gcc_modifier_darwin(conf): | |
57 | v=conf.env | |
58 | v.CFLAGS_cshlib=['-fPIC'] | |
59 | v.LINKFLAGS_cshlib=['-dynamiclib'] | |
60 | v.cshlib_PATTERN='lib%s.dylib' | |
61 | v.FRAMEWORKPATH_ST='-F%s' | |
62 | v.FRAMEWORK_ST=['-framework'] | |
63 | v.ARCH_ST=['-arch'] | |
64 | v.LINKFLAGS_cstlib=[] | |
65 | v.SHLIB_MARKER=[] | |
66 | v.STLIB_MARKER=[] | |
67 | v.SONAME_ST=[] | |
68 | @conf | |
69 | def gcc_modifier_aix(conf): | |
70 | v=conf.env | |
71 | v.LINKFLAGS_cprogram=['-Wl,-brtl'] | |
72 | v.LINKFLAGS_cshlib=['-shared','-Wl,-brtl,-bexpfull'] | |
73 | v.SHLIB_MARKER=[] | |
74 | @conf | |
75 | def gcc_modifier_hpux(conf): | |
76 | v=conf.env | |
77 | v.SHLIB_MARKER=[] | |
78 | v.STLIB_MARKER=[] | |
79 | v.CFLAGS_cshlib=['-fPIC','-DPIC'] | |
80 | v.cshlib_PATTERN='lib%s.sl' | |
81 | @conf | |
82 | def gcc_modifier_openbsd(conf): | |
83 | conf.env.SONAME_ST=[] | |
84 | @conf | |
85 | def gcc_modifier_osf1V(conf): | |
86 | v=conf.env | |
87 | v.SHLIB_MARKER=[] | |
88 | v.STLIB_MARKER=[] | |
89 | v.SONAME_ST=[] | |
90 | @conf | |
91 | def gcc_modifier_platform(conf): | |
92 | gcc_modifier_func=getattr(conf,'gcc_modifier_'+conf.env.DEST_OS,None) | |
93 | if gcc_modifier_func: | |
94 | gcc_modifier_func() | |
95 | def configure(conf): | |
96 | conf.find_gcc() | |
97 | conf.find_ar() | |
98 | conf.gcc_common_flags() | |
99 | conf.gcc_modifier_platform() | |
100 | conf.cc_load_tools() | |
101 | conf.cc_add_flags() | |
102 | conf.link_add_flags() | |
103 | conf.check_gcc_o_space() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ar,d | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_gdc(conf): | |
8 | conf.find_program('gdc',var='D') | |
9 | out=conf.cmd_and_log(conf.env.D+['--version']) | |
10 | if out.find("gdc")==-1: | |
11 | conf.fatal("detected compiler is not gdc") | |
12 | @conf | |
13 | def common_flags_gdc(conf): | |
14 | v=conf.env | |
15 | v.DFLAGS=[] | |
16 | v.D_SRC_F=['-c'] | |
17 | v.D_TGT_F='-o%s' | |
18 | v.D_LINKER=v.D | |
19 | v.DLNK_SRC_F='' | |
20 | v.DLNK_TGT_F='-o%s' | |
21 | v.DINC_ST='-I%s' | |
22 | v.DSHLIB_MARKER=v.DSTLIB_MARKER='' | |
23 | v.DSTLIB_ST=v.DSHLIB_ST='-l%s' | |
24 | v.DSTLIBPATH_ST=v.DLIBPATH_ST='-L%s' | |
25 | v.LINKFLAGS_dshlib=['-shared'] | |
26 | v.DHEADER_ext='.di' | |
27 | v.DFLAGS_d_with_header='-fintfc' | |
28 | v.D_HDR_F='-fintfc-file=%s' | |
29 | def configure(conf): | |
30 | conf.find_gdc() | |
31 | conf.load('ar') | |
32 | conf.load('d') | |
33 | conf.common_flags_gdc() | |
34 | conf.d_platform_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Utils | |
6 | from waflib.Tools import fc,fc_config,fc_scan,ar | |
7 | from waflib.Configure import conf | |
8 | @conf | |
9 | def find_gfortran(conf): | |
10 | fc=conf.find_program(['gfortran','g77'],var='FC') | |
11 | conf.get_gfortran_version(fc) | |
12 | conf.env.FC_NAME='GFORTRAN' | |
13 | @conf | |
14 | def gfortran_flags(conf): | |
15 | v=conf.env | |
16 | v.FCFLAGS_fcshlib=['-fPIC'] | |
17 | v.FORTRANMODFLAG=['-J',''] | |
18 | v.FCFLAGS_DEBUG=['-Werror'] | |
19 | @conf | |
20 | def gfortran_modifier_win32(conf): | |
21 | fc_config.fortran_modifier_win32(conf) | |
22 | @conf | |
23 | def gfortran_modifier_cygwin(conf): | |
24 | fc_config.fortran_modifier_cygwin(conf) | |
25 | @conf | |
26 | def gfortran_modifier_darwin(conf): | |
27 | fc_config.fortran_modifier_darwin(conf) | |
28 | @conf | |
29 | def gfortran_modifier_platform(conf): | |
30 | dest_os=conf.env.DEST_OS or Utils.unversioned_sys_platform() | |
31 | gfortran_modifier_func=getattr(conf,'gfortran_modifier_'+dest_os,None) | |
32 | if gfortran_modifier_func: | |
33 | gfortran_modifier_func() | |
34 | @conf | |
35 | def get_gfortran_version(conf,fc): | |
36 | version_re=re.compile(r"GNU\s*Fortran",re.I).search | |
37 | cmd=fc+['--version'] | |
38 | out,err=fc_config.getoutput(conf,cmd,stdin=False) | |
39 | if out: | |
40 | match=version_re(out) | |
41 | else: | |
42 | match=version_re(err) | |
43 | if not match: | |
44 | conf.fatal('Could not determine the compiler type') | |
45 | cmd=fc+['-dM','-E','-'] | |
46 | out,err=fc_config.getoutput(conf,cmd,stdin=True) | |
47 | if out.find('__GNUC__')<0: | |
48 | conf.fatal('Could not determine the compiler type') | |
49 | k={} | |
50 | out=out.splitlines() | |
51 | import shlex | |
52 | for line in out: | |
53 | lst=shlex.split(line) | |
54 | if len(lst)>2: | |
55 | key=lst[1] | |
56 | val=lst[2] | |
57 | k[key]=val | |
58 | def isD(var): | |
59 | return var in k | |
60 | def isT(var): | |
61 | return var in k and k[var]!='0' | |
62 | conf.env.FC_VERSION=(k['__GNUC__'],k['__GNUC_MINOR__'],k['__GNUC_PATCHLEVEL__']) | |
63 | def configure(conf): | |
64 | conf.find_gfortran() | |
65 | conf.find_ar() | |
66 | conf.fc_flags() | |
67 | conf.fc_add_flags() | |
68 | conf.gfortran_flags() | |
69 | conf.gfortran_modifier_platform() | |
70 | conf.check_gfortran_o_space() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os | |
5 | import functools | |
6 | from waflib import Context,Task,Utils,Options,Errors,Logs | |
7 | from waflib.TaskGen import taskgen_method,before_method,feature,extension | |
8 | from waflib.Configure import conf | |
9 | @taskgen_method | |
10 | def add_marshal_file(self,filename,prefix): | |
11 | if not hasattr(self,'marshal_list'): | |
12 | self.marshal_list=[] | |
13 | self.meths.append('process_marshal') | |
14 | self.marshal_list.append((filename,prefix)) | |
15 | @before_method('process_source') | |
16 | def process_marshal(self): | |
17 | for f,prefix in getattr(self,'marshal_list',[]): | |
18 | node=self.path.find_resource(f) | |
19 | if not node: | |
20 | raise Errors.WafError('file not found %r'%f) | |
21 | h_node=node.change_ext('.h') | |
22 | c_node=node.change_ext('.c') | |
23 | task=self.create_task('glib_genmarshal',node,[h_node,c_node]) | |
24 | task.env.GLIB_GENMARSHAL_PREFIX=prefix | |
25 | self.source=self.to_nodes(getattr(self,'source',[])) | |
26 | self.source.append(c_node) | |
27 | class glib_genmarshal(Task.Task): | |
28 | vars=['GLIB_GENMARSHAL_PREFIX','GLIB_GENMARSHAL'] | |
29 | color='BLUE' | |
30 | ext_out=['.h'] | |
31 | def run(self): | |
32 | bld=self.generator.bld | |
33 | get=self.env.get_flat | |
34 | cmd1="%s %s --prefix=%s --header > %s"%(get('GLIB_GENMARSHAL'),self.inputs[0].srcpath(),get('GLIB_GENMARSHAL_PREFIX'),self.outputs[0].abspath()) | |
35 | ret=bld.exec_command(cmd1) | |
36 | if ret: | |
37 | return ret | |
38 | c='''#include "%s"\n'''%self.outputs[0].name | |
39 | self.outputs[1].write(c) | |
40 | cmd2="%s %s --prefix=%s --body >> %s"%(get('GLIB_GENMARSHAL'),self.inputs[0].srcpath(),get('GLIB_GENMARSHAL_PREFIX'),self.outputs[1].abspath()) | |
41 | return bld.exec_command(cmd2) | |
42 | @taskgen_method | |
43 | def add_enums_from_template(self,source='',target='',template='',comments=''): | |
44 | if not hasattr(self,'enums_list'): | |
45 | self.enums_list=[] | |
46 | self.meths.append('process_enums') | |
47 | self.enums_list.append({'source':source,'target':target,'template':template,'file-head':'','file-prod':'','file-tail':'','enum-prod':'','value-head':'','value-prod':'','value-tail':'','comments':comments}) | |
48 | @taskgen_method | |
49 | def add_enums(self,source='',target='',file_head='',file_prod='',file_tail='',enum_prod='',value_head='',value_prod='',value_tail='',comments=''): | |
50 | if not hasattr(self,'enums_list'): | |
51 | self.enums_list=[] | |
52 | self.meths.append('process_enums') | |
53 | self.enums_list.append({'source':source,'template':'','target':target,'file-head':file_head,'file-prod':file_prod,'file-tail':file_tail,'enum-prod':enum_prod,'value-head':value_head,'value-prod':value_prod,'value-tail':value_tail,'comments':comments}) | |
54 | @before_method('process_source') | |
55 | def process_enums(self): | |
56 | for enum in getattr(self,'enums_list',[]): | |
57 | task=self.create_task('glib_mkenums') | |
58 | env=task.env | |
59 | inputs=[] | |
60 | source_list=self.to_list(enum['source']) | |
61 | if not source_list: | |
62 | raise Errors.WafError('missing source '+str(enum)) | |
63 | source_list=[self.path.find_resource(k)for k in source_list] | |
64 | inputs+=source_list | |
65 | env.GLIB_MKENUMS_SOURCE=[k.abspath()for k in source_list] | |
66 | if not enum['target']: | |
67 | raise Errors.WafError('missing target '+str(enum)) | |
68 | tgt_node=self.path.find_or_declare(enum['target']) | |
69 | if tgt_node.name.endswith('.c'): | |
70 | self.source.append(tgt_node) | |
71 | env.GLIB_MKENUMS_TARGET=tgt_node.abspath() | |
72 | options=[] | |
73 | if enum['template']: | |
74 | template_node=self.path.find_resource(enum['template']) | |
75 | options.append('--template %s'%(template_node.abspath())) | |
76 | inputs.append(template_node) | |
77 | params={'file-head':'--fhead','file-prod':'--fprod','file-tail':'--ftail','enum-prod':'--eprod','value-head':'--vhead','value-prod':'--vprod','value-tail':'--vtail','comments':'--comments'} | |
78 | for param,option in params.items(): | |
79 | if enum[param]: | |
80 | options.append('%s %r'%(option,enum[param])) | |
81 | env.GLIB_MKENUMS_OPTIONS=' '.join(options) | |
82 | task.set_inputs(inputs) | |
83 | task.set_outputs(tgt_node) | |
84 | class glib_mkenums(Task.Task): | |
85 | run_str='${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}' | |
86 | color='PINK' | |
87 | ext_out=['.h'] | |
88 | @taskgen_method | |
89 | def add_settings_schemas(self,filename_list): | |
90 | if not hasattr(self,'settings_schema_files'): | |
91 | self.settings_schema_files=[] | |
92 | if not isinstance(filename_list,list): | |
93 | filename_list=[filename_list] | |
94 | self.settings_schema_files.extend(filename_list) | |
95 | @taskgen_method | |
96 | def add_settings_enums(self,namespace,filename_list): | |
97 | if hasattr(self,'settings_enum_namespace'): | |
98 | raise Errors.WafError("Tried to add gsettings enums to %r more than once"%self.name) | |
99 | self.settings_enum_namespace=namespace | |
100 | if not isinstance(filename_list,list): | |
101 | filename_list=[filename_list] | |
102 | self.settings_enum_files=filename_list | |
103 | @feature('glib2') | |
104 | def process_settings(self): | |
105 | enums_tgt_node=[] | |
106 | install_files=[] | |
107 | settings_schema_files=getattr(self,'settings_schema_files',[]) | |
108 | if settings_schema_files and not self.env.GLIB_COMPILE_SCHEMAS: | |
109 | raise Errors.WafError("Unable to process GSettings schemas - glib-compile-schemas was not found during configure") | |
110 | if hasattr(self,'settings_enum_files'): | |
111 | enums_task=self.create_task('glib_mkenums') | |
112 | source_list=self.settings_enum_files | |
113 | source_list=[self.path.find_resource(k)for k in source_list] | |
114 | enums_task.set_inputs(source_list) | |
115 | enums_task.env.GLIB_MKENUMS_SOURCE=[k.abspath()for k in source_list] | |
116 | target=self.settings_enum_namespace+'.enums.xml' | |
117 | tgt_node=self.path.find_or_declare(target) | |
118 | enums_task.set_outputs(tgt_node) | |
119 | enums_task.env.GLIB_MKENUMS_TARGET=tgt_node.abspath() | |
120 | enums_tgt_node=[tgt_node] | |
121 | install_files.append(tgt_node) | |
122 | options='--comments "<!-- @comment@ -->" --fhead "<schemalist>" --vhead " <@type@ id=\\"%s.@EnumName@\\">" --vprod " <value nick=\\"@valuenick@\\" value=\\"@valuenum@\\"/>" --vtail " </@type@>" --ftail "</schemalist>" '%(self.settings_enum_namespace) | |
123 | enums_task.env.GLIB_MKENUMS_OPTIONS=options | |
124 | for schema in settings_schema_files: | |
125 | schema_task=self.create_task('glib_validate_schema') | |
126 | schema_node=self.path.find_resource(schema) | |
127 | if not schema_node: | |
128 | raise Errors.WafError("Cannot find the schema file %r"%schema) | |
129 | install_files.append(schema_node) | |
130 | source_list=enums_tgt_node+[schema_node] | |
131 | schema_task.set_inputs(source_list) | |
132 | schema_task.env.GLIB_COMPILE_SCHEMAS_OPTIONS=[("--schema-file="+k.abspath())for k in source_list] | |
133 | target_node=schema_node.change_ext('.xml.valid') | |
134 | schema_task.set_outputs(target_node) | |
135 | schema_task.env.GLIB_VALIDATE_SCHEMA_OUTPUT=target_node.abspath() | |
136 | def compile_schemas_callback(bld): | |
137 | if not bld.is_install: | |
138 | return | |
139 | compile_schemas=Utils.to_list(bld.env.GLIB_COMPILE_SCHEMAS) | |
140 | destdir=Options.options.destdir | |
141 | paths=bld._compile_schemas_registered | |
142 | if destdir: | |
143 | paths=(os.path.join(destdir,path.lstrip(os.sep))for path in paths) | |
144 | for path in paths: | |
145 | Logs.pprint('YELLOW','Updating GSettings schema cache %r'%path) | |
146 | if self.bld.exec_command(compile_schemas+[path]): | |
147 | Logs.warn('Could not update GSettings schema cache %r'%path) | |
148 | if self.bld.is_install: | |
149 | schemadir=self.env.GSETTINGSSCHEMADIR | |
150 | if not schemadir: | |
151 | raise Errors.WafError('GSETTINGSSCHEMADIR not defined (should have been set up automatically during configure)') | |
152 | if install_files: | |
153 | self.add_install_files(install_to=schemadir,install_from=install_files) | |
154 | registered_schemas=getattr(self.bld,'_compile_schemas_registered',None) | |
155 | if not registered_schemas: | |
156 | registered_schemas=self.bld._compile_schemas_registered=set() | |
157 | self.bld.add_post_fun(compile_schemas_callback) | |
158 | registered_schemas.add(schemadir) | |
159 | class glib_validate_schema(Task.Task): | |
160 | run_str='rm -f ${GLIB_VALIDATE_SCHEMA_OUTPUT} && ${GLIB_COMPILE_SCHEMAS} --dry-run ${GLIB_COMPILE_SCHEMAS_OPTIONS} && touch ${GLIB_VALIDATE_SCHEMA_OUTPUT}' | |
161 | color='PINK' | |
162 | @extension('.gresource.xml') | |
163 | def process_gresource_source(self,node): | |
164 | if not self.env.GLIB_COMPILE_RESOURCES: | |
165 | raise Errors.WafError("Unable to process GResource file - glib-compile-resources was not found during configure") | |
166 | if'gresource'in self.features: | |
167 | return | |
168 | h_node=node.change_ext('_xml.h') | |
169 | c_node=node.change_ext('_xml.c') | |
170 | self.create_task('glib_gresource_source',node,[h_node,c_node]) | |
171 | self.source.append(c_node) | |
172 | @feature('gresource') | |
173 | def process_gresource_bundle(self): | |
174 | for i in self.to_list(self.source): | |
175 | node=self.path.find_resource(i) | |
176 | task=self.create_task('glib_gresource_bundle',node,node.change_ext('')) | |
177 | inst_to=getattr(self,'install_path',None) | |
178 | if inst_to: | |
179 | self.add_install_files(install_to=inst_to,install_from=task.outputs) | |
180 | class glib_gresource_base(Task.Task): | |
181 | color='BLUE' | |
182 | base_cmd='${GLIB_COMPILE_RESOURCES} --sourcedir=${SRC[0].parent.srcpath()} --sourcedir=${SRC[0].bld_dir()}' | |
183 | def scan(self): | |
184 | bld=self.generator.bld | |
185 | kw={} | |
186 | kw['cwd']=self.get_cwd() | |
187 | kw['quiet']=Context.BOTH | |
188 | cmd=Utils.subst_vars('${GLIB_COMPILE_RESOURCES} --sourcedir=%s --sourcedir=%s --generate-dependencies %s'%(self.inputs[0].parent.srcpath(),self.inputs[0].bld_dir(),self.inputs[0].bldpath()),self.env) | |
189 | output=bld.cmd_and_log(cmd,**kw) | |
190 | nodes=[] | |
191 | names=[] | |
192 | for dep in output.splitlines(): | |
193 | if dep: | |
194 | node=bld.bldnode.find_node(dep) | |
195 | if node: | |
196 | nodes.append(node) | |
197 | else: | |
198 | names.append(dep) | |
199 | return(nodes,names) | |
200 | class glib_gresource_source(glib_gresource_base): | |
201 | vars=['GLIB_COMPILE_RESOURCES'] | |
202 | fun_h=Task.compile_fun_shell(glib_gresource_base.base_cmd+' --target=${TGT[0].abspath()} --generate-header ${SRC}') | |
203 | fun_c=Task.compile_fun_shell(glib_gresource_base.base_cmd+' --target=${TGT[1].abspath()} --generate-source ${SRC}') | |
204 | ext_out=['.h'] | |
205 | def run(self): | |
206 | return self.fun_h[0](self)or self.fun_c[0](self) | |
207 | class glib_gresource_bundle(glib_gresource_base): | |
208 | run_str=glib_gresource_base.base_cmd+' --target=${TGT} ${SRC}' | |
209 | shell=True | |
210 | @conf | |
211 | def find_glib_genmarshal(conf): | |
212 | conf.find_program('glib-genmarshal',var='GLIB_GENMARSHAL') | |
213 | @conf | |
214 | def find_glib_mkenums(conf): | |
215 | if not conf.env.PERL: | |
216 | conf.find_program('perl',var='PERL') | |
217 | conf.find_program('glib-mkenums',interpreter='PERL',var='GLIB_MKENUMS') | |
218 | @conf | |
219 | def find_glib_compile_schemas(conf): | |
220 | conf.find_program('glib-compile-schemas',var='GLIB_COMPILE_SCHEMAS') | |
221 | def getstr(varname): | |
222 | return getattr(Options.options,varname,getattr(conf.env,varname,'')) | |
223 | gsettingsschemadir=getstr('GSETTINGSSCHEMADIR') | |
224 | if not gsettingsschemadir: | |
225 | datadir=getstr('DATADIR') | |
226 | if not datadir: | |
227 | prefix=conf.env.PREFIX | |
228 | datadir=os.path.join(prefix,'share') | |
229 | gsettingsschemadir=os.path.join(datadir,'glib-2.0','schemas') | |
230 | conf.env.GSETTINGSSCHEMADIR=gsettingsschemadir | |
231 | @conf | |
232 | def find_glib_compile_resources(conf): | |
233 | conf.find_program('glib-compile-resources',var='GLIB_COMPILE_RESOURCES') | |
234 | def configure(conf): | |
235 | conf.find_glib_genmarshal() | |
236 | conf.find_glib_mkenums() | |
237 | conf.find_glib_compile_schemas(mandatory=False) | |
238 | conf.find_glib_compile_resources(mandatory=False) | |
239 | def options(opt): | |
240 | gr=opt.add_option_group('Installation directories') | |
241 | gr.add_option('--gsettingsschemadir',help='GSettings schema location [DATADIR/glib-2.0/schemas]',default='',dest='GSETTINGSSCHEMADIR') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re | |
5 | from waflib import Utils,Options,Context | |
6 | gnuopts=''' | |
7 | bindir, user commands, ${EXEC_PREFIX}/bin | |
8 | sbindir, system binaries, ${EXEC_PREFIX}/sbin | |
9 | libexecdir, program-specific binaries, ${EXEC_PREFIX}/libexec | |
10 | sysconfdir, host-specific configuration, ${PREFIX}/etc | |
11 | sharedstatedir, architecture-independent variable data, ${PREFIX}/com | |
12 | localstatedir, variable data, ${PREFIX}/var | |
13 | libdir, object code libraries, ${EXEC_PREFIX}/lib%s | |
14 | includedir, header files, ${PREFIX}/include | |
15 | oldincludedir, header files for non-GCC compilers, /usr/include | |
16 | datarootdir, architecture-independent data root, ${PREFIX}/share | |
17 | datadir, architecture-independent data, ${DATAROOTDIR} | |
18 | infodir, GNU "info" documentation, ${DATAROOTDIR}/info | |
19 | localedir, locale-dependent data, ${DATAROOTDIR}/locale | |
20 | mandir, manual pages, ${DATAROOTDIR}/man | |
21 | docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} | |
22 | htmldir, HTML documentation, ${DOCDIR} | |
23 | dvidir, DVI documentation, ${DOCDIR} | |
24 | pdfdir, PDF documentation, ${DOCDIR} | |
25 | psdir, PostScript documentation, ${DOCDIR} | |
26 | '''%Utils.lib64() | |
27 | _options=[x.split(', ')for x in gnuopts.splitlines()if x] | |
28 | def configure(conf): | |
29 | def get_param(varname,default): | |
30 | return getattr(Options.options,varname,'')or default | |
31 | env=conf.env | |
32 | env.LIBDIR=env.BINDIR=[] | |
33 | env.EXEC_PREFIX=get_param('EXEC_PREFIX',env.PREFIX) | |
34 | env.PACKAGE=getattr(Context.g_module,'APPNAME',None)or env.PACKAGE | |
35 | complete=False | |
36 | iter=0 | |
37 | while not complete and iter<len(_options)+1: | |
38 | iter+=1 | |
39 | complete=True | |
40 | for name,help,default in _options: | |
41 | name=name.upper() | |
42 | if not env[name]: | |
43 | try: | |
44 | env[name]=Utils.subst_vars(get_param(name,default).replace('/',os.sep),env) | |
45 | except TypeError: | |
46 | complete=False | |
47 | if not complete: | |
48 | lst=[x for x,_,_ in _options if not env[x.upper()]] | |
49 | raise conf.errors.WafError('Variable substitution failure %r'%lst) | |
50 | def options(opt): | |
51 | inst_dir=opt.add_option_group('Installation prefix','By default, "waf install" will put the files in\ | |
52 | "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\ | |
53 | than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"') | |
54 | for k in('--prefix','--destdir'): | |
55 | option=opt.parser.get_option(k) | |
56 | if option: | |
57 | opt.parser.remove_option(k) | |
58 | inst_dir.add_option(option) | |
59 | inst_dir.add_option('--exec-prefix',help='installation prefix for binaries [PREFIX]',default='',dest='EXEC_PREFIX') | |
60 | dirs_options=opt.add_option_group('Installation directories') | |
61 | for name,help,default in _options: | |
62 | option_name='--'+name | |
63 | str_default=default | |
64 | str_help='%s [%s]'%(help,re.sub(r'\$\{([^}]+)\}',r'\1',str_default)) | |
65 | dirs_options.add_option(option_name,help=str_help,default='',dest=name.upper()) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ccroot,ar | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_gxx(conf): | |
8 | cxx=conf.find_program(['g++','c++'],var='CXX') | |
9 | conf.get_cc_version(cxx,gcc=True) | |
10 | conf.env.CXX_NAME='gcc' | |
11 | @conf | |
12 | def gxx_common_flags(conf): | |
13 | v=conf.env | |
14 | v.CXX_SRC_F=[] | |
15 | v.CXX_TGT_F=['-c','-o'] | |
16 | if not v.LINK_CXX: | |
17 | v.LINK_CXX=v.CXX | |
18 | v.CXXLNK_SRC_F=[] | |
19 | v.CXXLNK_TGT_F=['-o'] | |
20 | v.CPPPATH_ST='-I%s' | |
21 | v.DEFINES_ST='-D%s' | |
22 | v.LIB_ST='-l%s' | |
23 | v.LIBPATH_ST='-L%s' | |
24 | v.STLIB_ST='-l%s' | |
25 | v.STLIBPATH_ST='-L%s' | |
26 | v.RPATH_ST='-Wl,-rpath,%s' | |
27 | v.SONAME_ST='-Wl,-h,%s' | |
28 | v.SHLIB_MARKER='-Wl,-Bdynamic' | |
29 | v.STLIB_MARKER='-Wl,-Bstatic' | |
30 | v.cxxprogram_PATTERN='%s' | |
31 | v.CXXFLAGS_cxxshlib=['-fPIC'] | |
32 | v.LINKFLAGS_cxxshlib=['-shared'] | |
33 | v.cxxshlib_PATTERN='lib%s.so' | |
34 | v.LINKFLAGS_cxxstlib=['-Wl,-Bstatic'] | |
35 | v.cxxstlib_PATTERN='lib%s.a' | |
36 | v.LINKFLAGS_MACBUNDLE=['-bundle','-undefined','dynamic_lookup'] | |
37 | v.CXXFLAGS_MACBUNDLE=['-fPIC'] | |
38 | v.macbundle_PATTERN='%s.bundle' | |
39 | @conf | |
40 | def gxx_modifier_win32(conf): | |
41 | v=conf.env | |
42 | v.cxxprogram_PATTERN='%s.exe' | |
43 | v.cxxshlib_PATTERN='%s.dll' | |
44 | v.implib_PATTERN='%s.dll.a' | |
45 | v.IMPLIB_ST='-Wl,--out-implib,%s' | |
46 | v.CXXFLAGS_cxxshlib=[] | |
47 | v.append_value('LINKFLAGS',['-Wl,--enable-auto-import']) | |
48 | @conf | |
49 | def gxx_modifier_cygwin(conf): | |
50 | gxx_modifier_win32(conf) | |
51 | v=conf.env | |
52 | v.cxxshlib_PATTERN='cyg%s.dll' | |
53 | v.append_value('LINKFLAGS_cxxshlib',['-Wl,--enable-auto-image-base']) | |
54 | v.CXXFLAGS_cxxshlib=[] | |
55 | @conf | |
56 | def gxx_modifier_darwin(conf): | |
57 | v=conf.env | |
58 | v.CXXFLAGS_cxxshlib=['-fPIC'] | |
59 | v.LINKFLAGS_cxxshlib=['-dynamiclib'] | |
60 | v.cxxshlib_PATTERN='lib%s.dylib' | |
61 | v.FRAMEWORKPATH_ST='-F%s' | |
62 | v.FRAMEWORK_ST=['-framework'] | |
63 | v.ARCH_ST=['-arch'] | |
64 | v.LINKFLAGS_cxxstlib=[] | |
65 | v.SHLIB_MARKER=[] | |
66 | v.STLIB_MARKER=[] | |
67 | v.SONAME_ST=[] | |
68 | @conf | |
69 | def gxx_modifier_aix(conf): | |
70 | v=conf.env | |
71 | v.LINKFLAGS_cxxprogram=['-Wl,-brtl'] | |
72 | v.LINKFLAGS_cxxshlib=['-shared','-Wl,-brtl,-bexpfull'] | |
73 | v.SHLIB_MARKER=[] | |
74 | @conf | |
75 | def gxx_modifier_hpux(conf): | |
76 | v=conf.env | |
77 | v.SHLIB_MARKER=[] | |
78 | v.STLIB_MARKER=[] | |
79 | v.CFLAGS_cxxshlib=['-fPIC','-DPIC'] | |
80 | v.cxxshlib_PATTERN='lib%s.sl' | |
81 | @conf | |
82 | def gxx_modifier_openbsd(conf): | |
83 | conf.env.SONAME_ST=[] | |
84 | @conf | |
85 | def gcc_modifier_osf1V(conf): | |
86 | v=conf.env | |
87 | v.SHLIB_MARKER=[] | |
88 | v.STLIB_MARKER=[] | |
89 | v.SONAME_ST=[] | |
90 | @conf | |
91 | def gxx_modifier_platform(conf): | |
92 | gxx_modifier_func=getattr(conf,'gxx_modifier_'+conf.env.DEST_OS,None) | |
93 | if gxx_modifier_func: | |
94 | gxx_modifier_func() | |
95 | def configure(conf): | |
96 | conf.find_gxx() | |
97 | conf.find_ar() | |
98 | conf.gxx_common_flags() | |
99 | conf.gxx_modifier_platform() | |
100 | conf.cxx_load_tools() | |
101 | conf.cxx_add_flags() | |
102 | conf.link_add_flags() | |
103 | conf.check_gcc_o_space('cxx') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import sys | |
5 | from waflib.Tools import ccroot,ar,gcc | |
6 | from waflib.Configure import conf | |
7 | @conf | |
8 | def find_icc(conf): | |
9 | cc=conf.find_program(['icc','ICL'],var='CC') | |
10 | conf.get_cc_version(cc,icc=True) | |
11 | conf.env.CC_NAME='icc' | |
12 | def configure(conf): | |
13 | conf.find_icc() | |
14 | conf.find_ar() | |
15 | conf.gcc_common_flags() | |
16 | conf.gcc_modifier_platform() | |
17 | conf.cc_load_tools() | |
18 | conf.cc_add_flags() | |
19 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import sys | |
5 | from waflib.Tools import ccroot,ar,gxx | |
6 | from waflib.Configure import conf | |
7 | @conf | |
8 | def find_icpc(conf): | |
9 | cxx=conf.find_program('icpc',var='CXX') | |
10 | conf.get_cc_version(cxx,icc=True) | |
11 | conf.env.CXX_NAME='icc' | |
12 | def configure(conf): | |
13 | conf.find_icpc() | |
14 | conf.find_ar() | |
15 | conf.gxx_common_flags() | |
16 | conf.gxx_modifier_platform() | |
17 | conf.cxx_load_tools() | |
18 | conf.cxx_add_flags() | |
19 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re,traceback | |
5 | from waflib import Utils,Logs,Errors | |
6 | from waflib.Tools import fc,fc_config,fc_scan,ar,ccroot | |
7 | from waflib.Configure import conf | |
8 | from waflib.TaskGen import after_method,feature | |
9 | @conf | |
10 | def find_ifort(conf): | |
11 | fc=conf.find_program('ifort',var='FC') | |
12 | conf.get_ifort_version(fc) | |
13 | conf.env.FC_NAME='IFORT' | |
14 | @conf | |
15 | def ifort_modifier_win32(self): | |
16 | v=self.env | |
17 | v.IFORT_WIN32=True | |
18 | v.FCSTLIB_MARKER='' | |
19 | v.FCSHLIB_MARKER='' | |
20 | v.FCLIB_ST=v.FCSTLIB_ST='%s.lib' | |
21 | v.FCLIBPATH_ST=v.STLIBPATH_ST='/LIBPATH:%s' | |
22 | v.FCINCPATH_ST='/I%s' | |
23 | v.FCDEFINES_ST='/D%s' | |
24 | v.fcprogram_PATTERN=v.fcprogram_test_PATTERN='%s.exe' | |
25 | v.fcshlib_PATTERN='%s.dll' | |
26 | v.fcstlib_PATTERN=v.implib_PATTERN='%s.lib' | |
27 | v.FCLNK_TGT_F='/out:' | |
28 | v.FC_TGT_F=['/c','/o',''] | |
29 | v.FCFLAGS_fcshlib='' | |
30 | v.LINKFLAGS_fcshlib='/DLL' | |
31 | v.AR_TGT_F='/out:' | |
32 | v.IMPLIB_ST='/IMPLIB:%s' | |
33 | v.append_value('LINKFLAGS','/subsystem:console') | |
34 | if v.IFORT_MANIFEST: | |
35 | v.append_value('LINKFLAGS',['/MANIFEST']) | |
36 | @conf | |
37 | def ifort_modifier_darwin(conf): | |
38 | fc_config.fortran_modifier_darwin(conf) | |
39 | @conf | |
40 | def ifort_modifier_platform(conf): | |
41 | dest_os=conf.env.DEST_OS or Utils.unversioned_sys_platform() | |
42 | ifort_modifier_func=getattr(conf,'ifort_modifier_'+dest_os,None) | |
43 | if ifort_modifier_func: | |
44 | ifort_modifier_func() | |
45 | @conf | |
46 | def get_ifort_version(conf,fc): | |
47 | version_re=re.compile(r"\bIntel\b.*\bVersion\s*(?P<major>\d*)\.(?P<minor>\d*)",re.I).search | |
48 | if Utils.is_win32: | |
49 | cmd=fc | |
50 | else: | |
51 | cmd=fc+['-logo'] | |
52 | out,err=fc_config.getoutput(conf,cmd,stdin=False) | |
53 | match=version_re(out)or version_re(err) | |
54 | if not match: | |
55 | conf.fatal('cannot determine ifort version.') | |
56 | k=match.groupdict() | |
57 | conf.env.FC_VERSION=(k['major'],k['minor']) | |
58 | def configure(conf): | |
59 | if Utils.is_win32: | |
60 | compiler,version,path,includes,libdirs,arch=conf.detect_ifort() | |
61 | v=conf.env | |
62 | v.DEST_CPU=arch | |
63 | v.PATH=path | |
64 | v.INCLUDES=includes | |
65 | v.LIBPATH=libdirs | |
66 | v.MSVC_COMPILER=compiler | |
67 | try: | |
68 | v.MSVC_VERSION=float(version) | |
69 | except ValueError: | |
70 | v.MSVC_VERSION=float(version[:-3]) | |
71 | conf.find_ifort_win32() | |
72 | conf.ifort_modifier_win32() | |
73 | else: | |
74 | conf.find_ifort() | |
75 | conf.find_program('xiar',var='AR') | |
76 | conf.find_ar() | |
77 | conf.fc_flags() | |
78 | conf.fc_add_flags() | |
79 | conf.ifort_modifier_platform() | |
80 | all_ifort_platforms=[('intel64','amd64'),('em64t','amd64'),('ia32','x86'),('Itanium','ia64')] | |
81 | @conf | |
82 | def gather_ifort_versions(conf,versions): | |
83 | version_pattern=re.compile(r'^...?.?\....?.?') | |
84 | try: | |
85 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Compilers\\Fortran') | |
86 | except OSError: | |
87 | try: | |
88 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Compilers\\Fortran') | |
89 | except OSError: | |
90 | return | |
91 | index=0 | |
92 | while 1: | |
93 | try: | |
94 | version=Utils.winreg.EnumKey(all_versions,index) | |
95 | except OSError: | |
96 | break | |
97 | index+=1 | |
98 | if not version_pattern.match(version): | |
99 | continue | |
100 | targets={} | |
101 | for target,arch in all_ifort_platforms: | |
102 | if target=='intel64': | |
103 | targetDir='EM64T_NATIVE' | |
104 | else: | |
105 | targetDir=target | |
106 | try: | |
107 | Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) | |
108 | icl_version=Utils.winreg.OpenKey(all_versions,version) | |
109 | path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') | |
110 | except OSError: | |
111 | pass | |
112 | else: | |
113 | batch_file=os.path.join(path,'bin','ifortvars.bat') | |
114 | if os.path.isfile(batch_file): | |
115 | targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file) | |
116 | for target,arch in all_ifort_platforms: | |
117 | try: | |
118 | icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+target) | |
119 | path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') | |
120 | except OSError: | |
121 | continue | |
122 | else: | |
123 | batch_file=os.path.join(path,'bin','ifortvars.bat') | |
124 | if os.path.isfile(batch_file): | |
125 | targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file) | |
126 | major=version[0:2] | |
127 | versions['intel '+major]=targets | |
128 | @conf | |
129 | def setup_ifort(conf,versiondict): | |
130 | platforms=Utils.to_list(conf.env.MSVC_TARGETS)or[i for i,j in all_ifort_platforms] | |
131 | desired_versions=conf.env.MSVC_VERSIONS or list(reversed(list(versiondict.keys()))) | |
132 | for version in desired_versions: | |
133 | try: | |
134 | targets=versiondict[version] | |
135 | except KeyError: | |
136 | continue | |
137 | for arch in platforms: | |
138 | try: | |
139 | cfg=targets[arch] | |
140 | except KeyError: | |
141 | continue | |
142 | cfg.evaluate() | |
143 | if cfg.is_valid: | |
144 | compiler,revision=version.rsplit(' ',1) | |
145 | return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu | |
146 | conf.fatal('ifort: Impossible to find a valid architecture for building %r - %r'%(desired_versions,list(versiondict.keys()))) | |
147 | @conf | |
148 | def get_ifort_version_win32(conf,compiler,version,target,vcvars): | |
149 | try: | |
150 | conf.msvc_cnt+=1 | |
151 | except AttributeError: | |
152 | conf.msvc_cnt=1 | |
153 | batfile=conf.bldnode.make_node('waf-print-msvc-%d.bat'%conf.msvc_cnt) | |
154 | batfile.write("""@echo off | |
155 | set INCLUDE= | |
156 | set LIB= | |
157 | call "%s" %s | |
158 | echo PATH=%%PATH%% | |
159 | echo INCLUDE=%%INCLUDE%% | |
160 | echo LIB=%%LIB%%;%%LIBPATH%% | |
161 | """%(vcvars,target)) | |
162 | sout=conf.cmd_and_log(['cmd.exe','/E:on','/V:on','/C',batfile.abspath()]) | |
163 | batfile.delete() | |
164 | lines=sout.splitlines() | |
165 | if not lines[0]: | |
166 | lines.pop(0) | |
167 | MSVC_PATH=MSVC_INCDIR=MSVC_LIBDIR=None | |
168 | for line in lines: | |
169 | if line.startswith('PATH='): | |
170 | path=line[5:] | |
171 | MSVC_PATH=path.split(';') | |
172 | elif line.startswith('INCLUDE='): | |
173 | MSVC_INCDIR=[i for i in line[8:].split(';')if i] | |
174 | elif line.startswith('LIB='): | |
175 | MSVC_LIBDIR=[i for i in line[4:].split(';')if i] | |
176 | if None in(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR): | |
177 | conf.fatal('ifort: Could not find a valid architecture for building (get_ifort_version_win32)') | |
178 | env=dict(os.environ) | |
179 | env.update(PATH=path) | |
180 | compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler) | |
181 | fc=conf.find_program(compiler_name,path_list=MSVC_PATH) | |
182 | if'CL'in env: | |
183 | del(env['CL']) | |
184 | try: | |
185 | conf.cmd_and_log(fc+['/help'],env=env) | |
186 | except UnicodeError: | |
187 | st=traceback.format_exc() | |
188 | if conf.logger: | |
189 | conf.logger.error(st) | |
190 | conf.fatal('ifort: Unicode error - check the code page?') | |
191 | except Exception as e: | |
192 | Logs.debug('ifort: get_ifort_version: %r %r %r -> failure %s',compiler,version,target,str(e)) | |
193 | conf.fatal('ifort: cannot run the compiler in get_ifort_version (run with -v to display errors)') | |
194 | else: | |
195 | Logs.debug('ifort: get_ifort_version: %r %r %r -> OK',compiler,version,target) | |
196 | finally: | |
197 | conf.env[compiler_name]='' | |
198 | return(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR) | |
199 | class target_compiler(object): | |
200 | def __init__(self,ctx,compiler,cpu,version,bat_target,bat,callback=None): | |
201 | self.conf=ctx | |
202 | self.name=None | |
203 | self.is_valid=False | |
204 | self.is_done=False | |
205 | self.compiler=compiler | |
206 | self.cpu=cpu | |
207 | self.version=version | |
208 | self.bat_target=bat_target | |
209 | self.bat=bat | |
210 | self.callback=callback | |
211 | def evaluate(self): | |
212 | if self.is_done: | |
213 | return | |
214 | self.is_done=True | |
215 | try: | |
216 | vs=self.conf.get_ifort_version_win32(self.compiler,self.version,self.bat_target,self.bat) | |
217 | except Errors.ConfigurationError: | |
218 | self.is_valid=False | |
219 | return | |
220 | if self.callback: | |
221 | vs=self.callback(self,vs) | |
222 | self.is_valid=True | |
223 | (self.bindirs,self.incdirs,self.libdirs)=vs | |
224 | def __str__(self): | |
225 | return str((self.bindirs,self.incdirs,self.libdirs)) | |
226 | def __repr__(self): | |
227 | return repr((self.bindirs,self.incdirs,self.libdirs)) | |
228 | @conf | |
229 | def detect_ifort(self): | |
230 | return self.setup_ifort(self.get_ifort_versions(False)) | |
231 | @conf | |
232 | def get_ifort_versions(self,eval_and_save=True): | |
233 | dct={} | |
234 | self.gather_ifort_versions(dct) | |
235 | return dct | |
236 | def _get_prog_names(self,compiler): | |
237 | if compiler=='intel': | |
238 | compiler_name='ifort' | |
239 | linker_name='XILINK' | |
240 | lib_name='XILIB' | |
241 | else: | |
242 | compiler_name='CL' | |
243 | linker_name='LINK' | |
244 | lib_name='LIB' | |
245 | return compiler_name,linker_name,lib_name | |
246 | @conf | |
247 | def find_ifort_win32(conf): | |
248 | v=conf.env | |
249 | path=v.PATH | |
250 | compiler=v.MSVC_COMPILER | |
251 | version=v.MSVC_VERSION | |
252 | compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler) | |
253 | v.IFORT_MANIFEST=(compiler=='intel'and version>=11) | |
254 | fc=conf.find_program(compiler_name,var='FC',path_list=path) | |
255 | env=dict(conf.environ) | |
256 | if path: | |
257 | env.update(PATH=';'.join(path)) | |
258 | if not conf.cmd_and_log(fc+['/nologo','/help'],env=env): | |
259 | conf.fatal('not intel fortran compiler could not be identified') | |
260 | v.FC_NAME='IFORT' | |
261 | if not v.LINK_FC: | |
262 | conf.find_program(linker_name,var='LINK_FC',path_list=path,mandatory=True) | |
263 | if not v.AR: | |
264 | conf.find_program(lib_name,path_list=path,var='AR',mandatory=True) | |
265 | v.ARFLAGS=['/nologo'] | |
266 | if v.IFORT_MANIFEST: | |
267 | conf.find_program('MT',path_list=path,var='MT') | |
268 | v.MTFLAGS=['/nologo'] | |
269 | try: | |
270 | conf.load('winres') | |
271 | except Errors.WafError: | |
272 | Logs.warn('Resource compiler not found. Compiling resource file is disabled') | |
273 | @after_method('apply_link') | |
274 | @feature('fc') | |
275 | def apply_flags_ifort(self): | |
276 | if not self.env.IFORT_WIN32 or not getattr(self,'link_task',None): | |
277 | return | |
278 | is_static=isinstance(self.link_task,ccroot.stlink_task) | |
279 | subsystem=getattr(self,'subsystem','') | |
280 | if subsystem: | |
281 | subsystem='/subsystem:%s'%subsystem | |
282 | flags=is_static and'ARFLAGS'or'LINKFLAGS' | |
283 | self.env.append_value(flags,subsystem) | |
284 | if not is_static: | |
285 | for f in self.env.LINKFLAGS: | |
286 | d=f.lower() | |
287 | if d[1:]=='debug': | |
288 | pdbnode=self.link_task.outputs[0].change_ext('.pdb') | |
289 | self.link_task.outputs.append(pdbnode) | |
290 | if getattr(self,'install_task',None): | |
291 | self.pdb_install_task=self.add_install_files(install_to=self.install_task.install_to,install_from=pdbnode) | |
292 | break | |
293 | @feature('fcprogram','fcshlib','fcprogram_test') | |
294 | @after_method('apply_link') | |
295 | def apply_manifest_ifort(self): | |
296 | if self.env.IFORT_WIN32 and getattr(self,'link_task',None): | |
297 | self.link_task.env.FC=self.env.LINK_FC | |
298 | if self.env.IFORT_WIN32 and self.env.IFORT_MANIFEST and getattr(self,'link_task',None): | |
299 | out_node=self.link_task.outputs[0] | |
300 | man_node=out_node.parent.find_or_declare(out_node.name+'.manifest') | |
301 | self.link_task.outputs.append(man_node) | |
302 | self.env.DO_MANIFEST=True |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from __future__ import with_statement | |
5 | import os,re | |
6 | from waflib import Context,Task,Utils,Logs | |
7 | import waflib.Tools.ccroot | |
8 | from waflib.TaskGen import feature,before_method,taskgen_method | |
9 | from waflib.Logs import error | |
10 | from waflib.Configure import conf | |
11 | _style_flags={'ba':'-b','desktop':'-d','keys':'-k','quoted':'--quoted-style','quotedxml':'--quotedxml-style','rfc822deb':'-r','schemas':'-s','xml':'-x',} | |
12 | @taskgen_method | |
13 | def ensure_localedir(self): | |
14 | if not self.env.LOCALEDIR: | |
15 | if self.env.DATAROOTDIR: | |
16 | self.env.LOCALEDIR=os.path.join(self.env.DATAROOTDIR,'locale') | |
17 | else: | |
18 | self.env.LOCALEDIR=os.path.join(self.env.PREFIX,'share','locale') | |
19 | @before_method('process_source') | |
20 | @feature('intltool_in') | |
21 | def apply_intltool_in_f(self): | |
22 | try: | |
23 | self.meths.remove('process_source') | |
24 | except ValueError: | |
25 | pass | |
26 | self.ensure_localedir() | |
27 | podir=getattr(self,'podir','.') | |
28 | podirnode=self.path.find_dir(podir) | |
29 | if not podirnode: | |
30 | error("could not find the podir %r"%podir) | |
31 | return | |
32 | cache=getattr(self,'intlcache','.intlcache') | |
33 | self.env.INTLCACHE=[os.path.join(str(self.path.get_bld()),podir,cache)] | |
34 | self.env.INTLPODIR=podirnode.bldpath() | |
35 | self.env.append_value('INTLFLAGS',getattr(self,'flags',self.env.INTLFLAGS_DEFAULT)) | |
36 | if'-c'in self.env.INTLFLAGS: | |
37 | self.bld.fatal('Redundant -c flag in intltool task %r'%self) | |
38 | style=getattr(self,'style',None) | |
39 | if style: | |
40 | try: | |
41 | style_flag=_style_flags[style] | |
42 | except KeyError: | |
43 | self.bld.fatal('intltool_in style "%s" is not valid'%style) | |
44 | self.env.append_unique('INTLFLAGS',[style_flag]) | |
45 | for i in self.to_list(self.source): | |
46 | node=self.path.find_resource(i) | |
47 | task=self.create_task('intltool',node,node.change_ext('')) | |
48 | inst=getattr(self,'install_path',None) | |
49 | if inst: | |
50 | self.add_install_files(install_to=inst,install_from=task.outputs) | |
51 | @feature('intltool_po') | |
52 | def apply_intltool_po(self): | |
53 | try: | |
54 | self.meths.remove('process_source') | |
55 | except ValueError: | |
56 | pass | |
57 | self.ensure_localedir() | |
58 | appname=getattr(self,'appname',getattr(Context.g_module,Context.APPNAME,'set_your_app_name')) | |
59 | podir=getattr(self,'podir','.') | |
60 | inst=getattr(self,'install_path','${LOCALEDIR}') | |
61 | linguas=self.path.find_node(os.path.join(podir,'LINGUAS')) | |
62 | if linguas: | |
63 | with open(linguas.abspath())as f: | |
64 | langs=[] | |
65 | for line in f.readlines(): | |
66 | if not line.startswith('#'): | |
67 | langs+=line.split() | |
68 | re_linguas=re.compile('[-a-zA-Z_@.]+') | |
69 | for lang in langs: | |
70 | if re_linguas.match(lang): | |
71 | node=self.path.find_resource(os.path.join(podir,re_linguas.match(lang).group()+'.po')) | |
72 | task=self.create_task('po',node,node.change_ext('.mo')) | |
73 | if inst: | |
74 | filename=task.outputs[0].name | |
75 | (langname,ext)=os.path.splitext(filename) | |
76 | inst_file=inst+os.sep+langname+os.sep+'LC_MESSAGES'+os.sep+appname+'.mo' | |
77 | self.add_install_as(install_to=inst_file,install_from=task.outputs[0],chmod=getattr(self,'chmod',Utils.O644)) | |
78 | else: | |
79 | Logs.pprint('RED',"Error no LINGUAS file found in po directory") | |
80 | class po(Task.Task): | |
81 | run_str='${MSGFMT} -o ${TGT} ${SRC}' | |
82 | color='BLUE' | |
83 | class intltool(Task.Task): | |
84 | run_str='${INTLTOOL} ${INTLFLAGS} ${INTLCACHE_ST:INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}' | |
85 | color='BLUE' | |
86 | @conf | |
87 | def find_msgfmt(conf): | |
88 | conf.find_program('msgfmt',var='MSGFMT') | |
89 | @conf | |
90 | def find_intltool_merge(conf): | |
91 | if not conf.env.PERL: | |
92 | conf.find_program('perl',var='PERL') | |
93 | conf.env.INTLCACHE_ST='--cache=%s' | |
94 | conf.env.INTLFLAGS_DEFAULT=['-q','-u'] | |
95 | conf.find_program('intltool-merge',interpreter='PERL',var='INTLTOOL') | |
96 | def configure(conf): | |
97 | conf.find_msgfmt() | |
98 | conf.find_intltool_merge() | |
99 | if conf.env.CC or conf.env.CXX: | |
100 | conf.check(header_name='locale.h') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Errors | |
5 | from waflib.Tools import ccroot,ar | |
6 | from waflib.Configure import conf | |
7 | @conf | |
8 | def find_irixcc(conf): | |
9 | v=conf.env | |
10 | cc=None | |
11 | if v.CC: | |
12 | cc=v.CC | |
13 | elif'CC'in conf.environ: | |
14 | cc=conf.environ['CC'] | |
15 | if not cc: | |
16 | cc=conf.find_program('cc',var='CC') | |
17 | if not cc: | |
18 | conf.fatal('irixcc was not found') | |
19 | try: | |
20 | conf.cmd_and_log(cc+['-version']) | |
21 | except Errors.WafError: | |
22 | conf.fatal('%r -version could not be executed'%cc) | |
23 | v.CC=cc | |
24 | v.CC_NAME='irix' | |
25 | @conf | |
26 | def irixcc_common_flags(conf): | |
27 | v=conf.env | |
28 | v.CC_SRC_F='' | |
29 | v.CC_TGT_F=['-c','-o'] | |
30 | v.CPPPATH_ST='-I%s' | |
31 | v.DEFINES_ST='-D%s' | |
32 | if not v.LINK_CC: | |
33 | v.LINK_CC=v.CC | |
34 | v.CCLNK_SRC_F='' | |
35 | v.CCLNK_TGT_F=['-o'] | |
36 | v.LIB_ST='-l%s' | |
37 | v.LIBPATH_ST='-L%s' | |
38 | v.STLIB_ST='-l%s' | |
39 | v.STLIBPATH_ST='-L%s' | |
40 | v.cprogram_PATTERN='%s' | |
41 | v.cshlib_PATTERN='lib%s.so' | |
42 | v.cstlib_PATTERN='lib%s.a' | |
43 | def configure(conf): | |
44 | conf.find_irixcc() | |
45 | conf.find_cpp() | |
46 | conf.find_ar() | |
47 | conf.irixcc_common_flags() | |
48 | conf.cc_load_tools() | |
49 | conf.cc_add_flags() | |
50 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,shutil | |
5 | from waflib import Task,Utils,Errors,Node | |
6 | from waflib.Configure import conf | |
7 | from waflib.TaskGen import feature,before_method,after_method,taskgen_method | |
8 | from waflib.Tools import ccroot | |
9 | ccroot.USELIB_VARS['javac']=set(['CLASSPATH','JAVACFLAGS']) | |
10 | SOURCE_RE='**/*.java' | |
11 | JAR_RE='**/*' | |
12 | class_check_source=''' | |
13 | public class Test { | |
14 | public static void main(String[] argv) { | |
15 | Class lib; | |
16 | if (argv.length < 1) { | |
17 | System.err.println("Missing argument"); | |
18 | System.exit(77); | |
19 | } | |
20 | try { | |
21 | lib = Class.forName(argv[0]); | |
22 | } catch (ClassNotFoundException e) { | |
23 | System.err.println("ClassNotFoundException"); | |
24 | System.exit(1); | |
25 | } | |
26 | lib = null; | |
27 | System.exit(0); | |
28 | } | |
29 | } | |
30 | ''' | |
31 | @feature('javac') | |
32 | @before_method('process_source') | |
33 | def apply_java(self): | |
34 | Utils.def_attrs(self,jarname='',classpath='',sourcepath='.',srcdir='.',jar_mf_attributes={},jar_mf_classpath=[]) | |
35 | outdir=getattr(self,'outdir',None) | |
36 | if outdir: | |
37 | if not isinstance(outdir,Node.Node): | |
38 | outdir=self.path.get_bld().make_node(self.outdir) | |
39 | else: | |
40 | outdir=self.path.get_bld() | |
41 | outdir.mkdir() | |
42 | self.outdir=outdir | |
43 | self.env.OUTDIR=outdir.abspath() | |
44 | self.javac_task=tsk=self.create_task('javac') | |
45 | tmp=[] | |
46 | srcdir=getattr(self,'srcdir','') | |
47 | if isinstance(srcdir,Node.Node): | |
48 | srcdir=[srcdir] | |
49 | for x in Utils.to_list(srcdir): | |
50 | if isinstance(x,Node.Node): | |
51 | y=x | |
52 | else: | |
53 | y=self.path.find_dir(x) | |
54 | if not y: | |
55 | self.bld.fatal('Could not find the folder %s from %s'%(x,self.path)) | |
56 | tmp.append(y) | |
57 | tsk.srcdir=tmp | |
58 | if getattr(self,'compat',None): | |
59 | tsk.env.append_value('JAVACFLAGS',['-source',str(self.compat)]) | |
60 | if hasattr(self,'sourcepath'): | |
61 | fold=[isinstance(x,Node.Node)and x or self.path.find_dir(x)for x in self.to_list(self.sourcepath)] | |
62 | names=os.pathsep.join([x.srcpath()for x in fold]) | |
63 | else: | |
64 | names=[x.srcpath()for x in tsk.srcdir] | |
65 | if names: | |
66 | tsk.env.append_value('JAVACFLAGS',['-sourcepath',names]) | |
67 | @taskgen_method | |
68 | def java_use_rec(self,name,**kw): | |
69 | if name in self.tmp_use_seen: | |
70 | return | |
71 | self.tmp_use_seen.append(name) | |
72 | try: | |
73 | y=self.bld.get_tgen_by_name(name) | |
74 | except Errors.WafError: | |
75 | self.uselib.append(name) | |
76 | return | |
77 | else: | |
78 | y.post() | |
79 | if hasattr(y,'jar_task'): | |
80 | self.use_lst.append(y.jar_task.outputs[0].abspath()) | |
81 | else: | |
82 | if hasattr(y,'outdir'): | |
83 | self.use_lst.append(y.outdir.abspath()) | |
84 | else: | |
85 | self.use_lst.append(y.path.get_bld().abspath()) | |
86 | for x in self.to_list(getattr(y,'use',[])): | |
87 | self.java_use_rec(x) | |
88 | @feature('javac') | |
89 | @before_method('propagate_uselib_vars') | |
90 | @after_method('apply_java') | |
91 | def use_javac_files(self): | |
92 | self.use_lst=[] | |
93 | self.tmp_use_seen=[] | |
94 | self.uselib=self.to_list(getattr(self,'uselib',[])) | |
95 | names=self.to_list(getattr(self,'use',[])) | |
96 | get=self.bld.get_tgen_by_name | |
97 | for x in names: | |
98 | try: | |
99 | tg=get(x) | |
100 | except Errors.WafError: | |
101 | self.uselib.append(x) | |
102 | else: | |
103 | tg.post() | |
104 | if hasattr(tg,'jar_task'): | |
105 | self.use_lst.append(tg.jar_task.outputs[0].abspath()) | |
106 | self.javac_task.set_run_after(tg.jar_task) | |
107 | self.javac_task.dep_nodes.extend(tg.jar_task.outputs) | |
108 | else: | |
109 | if hasattr(tg,'outdir'): | |
110 | base_node=tg.outdir | |
111 | else: | |
112 | base_node=tg.path.get_bld() | |
113 | self.use_lst.append(base_node.abspath()) | |
114 | self.javac_task.dep_nodes.extend([x for x in base_node.ant_glob(JAR_RE,remove=False,quiet=True)]) | |
115 | for tsk in tg.tasks: | |
116 | self.javac_task.set_run_after(tsk) | |
117 | if getattr(self,'recurse_use',False)or self.bld.env.RECURSE_JAVA: | |
118 | self.java_use_rec(x) | |
119 | self.env.append_value('CLASSPATH',self.use_lst) | |
120 | @feature('javac') | |
121 | @after_method('apply_java','propagate_uselib_vars','use_javac_files') | |
122 | def set_classpath(self): | |
123 | if getattr(self,'classpath',None): | |
124 | self.env.append_unique('CLASSPATH',getattr(self,'classpath',[])) | |
125 | for x in self.tasks: | |
126 | x.env.CLASSPATH=os.pathsep.join(self.env.CLASSPATH)+os.pathsep | |
127 | @feature('jar') | |
128 | @after_method('apply_java','use_javac_files') | |
129 | @before_method('process_source') | |
130 | def jar_files(self): | |
131 | destfile=getattr(self,'destfile','test.jar') | |
132 | jaropts=getattr(self,'jaropts',[]) | |
133 | manifest=getattr(self,'manifest',None) | |
134 | basedir=getattr(self,'basedir',None) | |
135 | if basedir: | |
136 | if not isinstance(self.basedir,Node.Node): | |
137 | basedir=self.path.get_bld().make_node(basedir) | |
138 | else: | |
139 | basedir=self.path.get_bld() | |
140 | if not basedir: | |
141 | self.bld.fatal('Could not find the basedir %r for %r'%(self.basedir,self)) | |
142 | self.jar_task=tsk=self.create_task('jar_create') | |
143 | if manifest: | |
144 | jarcreate=getattr(self,'jarcreate','cfm') | |
145 | if not isinstance(manifest,Node.Node): | |
146 | node=self.path.find_resource(manifest) | |
147 | else: | |
148 | node=manifest | |
149 | if not node: | |
150 | self.bld.fatal('invalid manifest file %r for %r'%(manifest,self)) | |
151 | tsk.dep_nodes.append(node) | |
152 | jaropts.insert(0,node.abspath()) | |
153 | else: | |
154 | jarcreate=getattr(self,'jarcreate','cf') | |
155 | if not isinstance(destfile,Node.Node): | |
156 | destfile=self.path.find_or_declare(destfile) | |
157 | if not destfile: | |
158 | self.bld.fatal('invalid destfile %r for %r'%(destfile,self)) | |
159 | tsk.set_outputs(destfile) | |
160 | tsk.basedir=basedir | |
161 | jaropts.append('-C') | |
162 | jaropts.append(basedir.bldpath()) | |
163 | jaropts.append('.') | |
164 | tsk.env.JAROPTS=jaropts | |
165 | tsk.env.JARCREATE=jarcreate | |
166 | if getattr(self,'javac_task',None): | |
167 | tsk.set_run_after(self.javac_task) | |
168 | @feature('jar') | |
169 | @after_method('jar_files') | |
170 | def use_jar_files(self): | |
171 | self.uselib=self.to_list(getattr(self,'uselib',[])) | |
172 | names=self.to_list(getattr(self,'use',[])) | |
173 | get=self.bld.get_tgen_by_name | |
174 | for x in names: | |
175 | try: | |
176 | y=get(x) | |
177 | except Errors.WafError: | |
178 | self.uselib.append(x) | |
179 | else: | |
180 | y.post() | |
181 | self.jar_task.run_after.update(y.tasks) | |
182 | class JTask(Task.Task): | |
183 | def split_argfile(self,cmd): | |
184 | inline=[cmd[0]] | |
185 | infile=[] | |
186 | for x in cmd[1:]: | |
187 | if x.startswith('-J'): | |
188 | inline.append(x) | |
189 | else: | |
190 | infile.append(self.quote_flag(x)) | |
191 | return(inline,infile) | |
192 | class jar_create(JTask): | |
193 | color='GREEN' | |
194 | run_str='${JAR} ${JARCREATE} ${TGT} ${JAROPTS}' | |
195 | def runnable_status(self): | |
196 | for t in self.run_after: | |
197 | if not t.hasrun: | |
198 | return Task.ASK_LATER | |
199 | if not self.inputs: | |
200 | try: | |
201 | self.inputs=[x for x in self.basedir.ant_glob(JAR_RE,remove=False,quiet=True)if id(x)!=id(self.outputs[0])] | |
202 | except Exception: | |
203 | raise Errors.WafError('Could not find the basedir %r for %r'%(self.basedir,self)) | |
204 | return super(jar_create,self).runnable_status() | |
205 | class javac(JTask): | |
206 | color='BLUE' | |
207 | run_str='${JAVAC} -classpath ${CLASSPATH} -d ${OUTDIR} ${JAVACFLAGS} ${SRC}' | |
208 | vars=['CLASSPATH','JAVACFLAGS','JAVAC','OUTDIR'] | |
209 | def uid(self): | |
210 | lst=[self.__class__.__name__,self.generator.outdir.abspath()] | |
211 | for x in self.srcdir: | |
212 | lst.append(x.abspath()) | |
213 | return Utils.h_list(lst) | |
214 | def runnable_status(self): | |
215 | for t in self.run_after: | |
216 | if not t.hasrun: | |
217 | return Task.ASK_LATER | |
218 | if not self.inputs: | |
219 | self.inputs=[] | |
220 | for x in self.srcdir: | |
221 | if x.exists(): | |
222 | self.inputs.extend(x.ant_glob(SOURCE_RE,remove=False,quiet=True)) | |
223 | return super(javac,self).runnable_status() | |
224 | def post_run(self): | |
225 | for node in self.generator.outdir.ant_glob('**/*.class',quiet=True): | |
226 | self.generator.bld.node_sigs[node]=self.uid() | |
227 | self.generator.bld.task_sigs[self.uid()]=self.cache_sig | |
228 | @feature('javadoc') | |
229 | @after_method('process_rule') | |
230 | def create_javadoc(self): | |
231 | tsk=self.create_task('javadoc') | |
232 | tsk.classpath=getattr(self,'classpath',[]) | |
233 | self.javadoc_package=Utils.to_list(self.javadoc_package) | |
234 | if not isinstance(self.javadoc_output,Node.Node): | |
235 | self.javadoc_output=self.bld.path.find_or_declare(self.javadoc_output) | |
236 | class javadoc(Task.Task): | |
237 | color='BLUE' | |
238 | def __str__(self): | |
239 | return'%s: %s -> %s\n'%(self.__class__.__name__,self.generator.srcdir,self.generator.javadoc_output) | |
240 | def run(self): | |
241 | env=self.env | |
242 | bld=self.generator.bld | |
243 | wd=bld.bldnode | |
244 | srcpath=self.generator.path.abspath()+os.sep+self.generator.srcdir | |
245 | srcpath+=os.pathsep | |
246 | srcpath+=self.generator.path.get_bld().abspath()+os.sep+self.generator.srcdir | |
247 | classpath=env.CLASSPATH | |
248 | classpath+=os.pathsep | |
249 | classpath+=os.pathsep.join(self.classpath) | |
250 | classpath="".join(classpath) | |
251 | self.last_cmd=lst=[] | |
252 | lst.extend(Utils.to_list(env.JAVADOC)) | |
253 | lst.extend(['-d',self.generator.javadoc_output.abspath()]) | |
254 | lst.extend(['-sourcepath',srcpath]) | |
255 | lst.extend(['-classpath',classpath]) | |
256 | lst.extend(['-subpackages']) | |
257 | lst.extend(self.generator.javadoc_package) | |
258 | lst=[x for x in lst if x] | |
259 | self.generator.bld.cmd_and_log(lst,cwd=wd,env=env.env or None,quiet=0) | |
260 | def post_run(self): | |
261 | nodes=self.generator.javadoc_output.ant_glob('**',quiet=True) | |
262 | for node in nodes: | |
263 | self.generator.bld.node_sigs[node]=self.uid() | |
264 | self.generator.bld.task_sigs[self.uid()]=self.cache_sig | |
265 | def configure(self): | |
266 | java_path=self.environ['PATH'].split(os.pathsep) | |
267 | v=self.env | |
268 | if'JAVA_HOME'in self.environ: | |
269 | java_path=[os.path.join(self.environ['JAVA_HOME'],'bin')]+java_path | |
270 | self.env.JAVA_HOME=[self.environ['JAVA_HOME']] | |
271 | for x in'javac java jar javadoc'.split(): | |
272 | self.find_program(x,var=x.upper(),path_list=java_path,mandatory=(x not in('javadoc'))) | |
273 | if'CLASSPATH'in self.environ: | |
274 | v.CLASSPATH=self.environ['CLASSPATH'] | |
275 | if not v.JAR: | |
276 | self.fatal('jar is required for making java packages') | |
277 | if not v.JAVAC: | |
278 | self.fatal('javac is required for compiling java classes') | |
279 | v.JARCREATE='cf' | |
280 | v.JAVACFLAGS=[] | |
281 | @conf | |
282 | def check_java_class(self,classname,with_classpath=None): | |
283 | javatestdir='.waf-javatest' | |
284 | classpath=javatestdir | |
285 | if self.env.CLASSPATH: | |
286 | classpath+=os.pathsep+self.env.CLASSPATH | |
287 | if isinstance(with_classpath,str): | |
288 | classpath+=os.pathsep+with_classpath | |
289 | shutil.rmtree(javatestdir,True) | |
290 | os.mkdir(javatestdir) | |
291 | Utils.writef(os.path.join(javatestdir,'Test.java'),class_check_source) | |
292 | self.exec_command(self.env.JAVAC+[os.path.join(javatestdir,'Test.java')],shell=False) | |
293 | cmd=self.env.JAVA+['-cp',classpath,'Test',classname] | |
294 | self.to_log("%s\n"%str(cmd)) | |
295 | found=self.exec_command(cmd,shell=False) | |
296 | self.msg('Checking for java class %s'%classname,not found) | |
297 | shutil.rmtree(javatestdir,True) | |
298 | return found | |
299 | @conf | |
300 | def check_jni_headers(conf): | |
301 | if not conf.env.CC_NAME and not conf.env.CXX_NAME: | |
302 | conf.fatal('load a compiler first (gcc, g++, ..)') | |
303 | if not conf.env.JAVA_HOME: | |
304 | conf.fatal('set JAVA_HOME in the system environment') | |
305 | javaHome=conf.env.JAVA_HOME[0] | |
306 | dir=conf.root.find_dir(conf.env.JAVA_HOME[0]+'/include') | |
307 | if dir is None: | |
308 | dir=conf.root.find_dir(conf.env.JAVA_HOME[0]+'/../Headers') | |
309 | if dir is None: | |
310 | conf.fatal('JAVA_HOME does not seem to be set properly') | |
311 | f=dir.ant_glob('**/(jni|jni_md).h') | |
312 | incDirs=[x.parent.abspath()for x in f] | |
313 | dir=conf.root.find_dir(conf.env.JAVA_HOME[0]) | |
314 | f=dir.ant_glob('**/*jvm.(so|dll|dylib)') | |
315 | libDirs=[x.parent.abspath()for x in f]or[javaHome] | |
316 | f=dir.ant_glob('**/*jvm.(lib)') | |
317 | if f: | |
318 | libDirs=[[x,y.parent.abspath()]for x in libDirs for y in f] | |
319 | if conf.env.DEST_OS=='freebsd': | |
320 | conf.env.append_unique('LINKFLAGS_JAVA','-pthread') | |
321 | for d in libDirs: | |
322 | try: | |
323 | conf.check(header_name='jni.h',define_name='HAVE_JNI_H',lib='jvm',libpath=d,includes=incDirs,uselib_store='JAVA',uselib='JAVA') | |
324 | except Exception: | |
325 | pass | |
326 | else: | |
327 | break | |
328 | else: | |
329 | conf.fatal('could not find lib jvm in %r (see config.log)'%libDirs) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ar,d | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_ldc2(conf): | |
8 | conf.find_program(['ldc2'],var='D') | |
9 | out=conf.cmd_and_log(conf.env.D+['-version']) | |
10 | if out.find("based on DMD v2.")==-1: | |
11 | conf.fatal("detected compiler is not ldc2") | |
12 | @conf | |
13 | def common_flags_ldc2(conf): | |
14 | v=conf.env | |
15 | v.D_SRC_F=['-c'] | |
16 | v.D_TGT_F='-of%s' | |
17 | v.D_LINKER=v.D | |
18 | v.DLNK_SRC_F='' | |
19 | v.DLNK_TGT_F='-of%s' | |
20 | v.DINC_ST='-I%s' | |
21 | v.DSHLIB_MARKER=v.DSTLIB_MARKER='' | |
22 | v.DSTLIB_ST=v.DSHLIB_ST='-L-l%s' | |
23 | v.DSTLIBPATH_ST=v.DLIBPATH_ST='-L-L%s' | |
24 | v.LINKFLAGS_dshlib=['-L-shared'] | |
25 | v.DHEADER_ext='.di' | |
26 | v.DFLAGS_d_with_header=['-H','-Hf'] | |
27 | v.D_HDR_F='%s' | |
28 | v.LINKFLAGS=[] | |
29 | v.DFLAGS_dshlib=['-relocation-model=pic'] | |
30 | def configure(conf): | |
31 | conf.find_ldc2() | |
32 | conf.load('ar') | |
33 | conf.load('d') | |
34 | conf.common_flags_ldc2() | |
35 | conf.d_platform_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.TaskGen import extension | |
5 | from waflib import Task | |
6 | @extension('.lua') | |
7 | def add_lua(self,node): | |
8 | tsk=self.create_task('luac',node,node.change_ext('.luac')) | |
9 | inst_to=getattr(self,'install_path',self.env.LUADIR and'${LUADIR}'or None) | |
10 | if inst_to: | |
11 | self.add_install_files(install_to=inst_to,install_from=tsk.outputs) | |
12 | return tsk | |
13 | class luac(Task.Task): | |
14 | run_str='${LUAC} -s -o ${TGT} ${SRC}' | |
15 | color='PINK' | |
16 | def configure(conf): | |
17 | conf.find_program('luac',var='LUAC') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,stat | |
5 | from waflib import Utils,Build,Node | |
6 | STRONGEST=True | |
7 | Build.SAVED_ATTRS.append('hashes_md5_tstamp') | |
8 | def h_file(self): | |
9 | filename=self.abspath() | |
10 | st=os.stat(filename) | |
11 | cache=self.ctx.hashes_md5_tstamp | |
12 | if filename in cache and cache[filename][0]==st.st_mtime: | |
13 | return cache[filename][1] | |
14 | if STRONGEST: | |
15 | ret=Utils.h_file(filename) | |
16 | else: | |
17 | if stat.S_ISDIR(st[stat.ST_MODE]): | |
18 | raise IOError('Not a file') | |
19 | ret=Utils.md5(str((st.st_mtime,st.st_size)).encode()).digest() | |
20 | cache[filename]=(st.st_mtime,ret) | |
21 | return ret | |
22 | h_file.__doc__=Node.Node.h_file.__doc__ | |
23 | Node.Node.h_file=h_file |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,sys,re,traceback | |
5 | from waflib import Utils,Logs,Options,Errors | |
6 | from waflib.TaskGen import after_method,feature | |
7 | from waflib.Configure import conf | |
8 | from waflib.Tools import ccroot,c,cxx,ar | |
9 | g_msvc_systemlibs=''' | |
10 | aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet | |
11 | cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs | |
12 | credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d | |
13 | ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp | |
14 | faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid | |
15 | gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop | |
16 | kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi | |
17 | mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree | |
18 | msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm | |
19 | netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp | |
20 | odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 | |
21 | osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu | |
22 | ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm | |
23 | rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 | |
24 | shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 | |
25 | traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg | |
26 | version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm | |
27 | wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp | |
28 | '''.split() | |
29 | all_msvc_platforms=[('x64','amd64'),('x86','x86'),('ia64','ia64'),('x86_amd64','amd64'),('x86_ia64','ia64'),('x86_arm','arm'),('x86_arm64','arm64'),('amd64_x86','x86'),('amd64_arm','arm'),('amd64_arm64','arm64')] | |
30 | all_wince_platforms=[('armv4','arm'),('armv4i','arm'),('mipsii','mips'),('mipsii_fp','mips'),('mipsiv','mips'),('mipsiv_fp','mips'),('sh4','sh'),('x86','cex86')] | |
31 | all_icl_platforms=[('intel64','amd64'),('em64t','amd64'),('ia32','x86'),('Itanium','ia64')] | |
32 | def options(opt): | |
33 | opt.add_option('--msvc_version',type='string',help='msvc version, eg: "msvc 10.0,msvc 9.0"',default='') | |
34 | opt.add_option('--msvc_targets',type='string',help='msvc targets, eg: "x64,arm"',default='') | |
35 | opt.add_option('--no-msvc-lazy',action='store_false',help='lazily check msvc target environments',default=True,dest='msvc_lazy') | |
36 | @conf | |
37 | def setup_msvc(conf,versiondict): | |
38 | platforms=getattr(Options.options,'msvc_targets','').split(',') | |
39 | if platforms==['']: | |
40 | platforms=Utils.to_list(conf.env.MSVC_TARGETS)or[i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] | |
41 | desired_versions=getattr(Options.options,'msvc_version','').split(',') | |
42 | if desired_versions==['']: | |
43 | desired_versions=conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys()))) | |
44 | lazy_detect=getattr(Options.options,'msvc_lazy',True) | |
45 | if conf.env.MSVC_LAZY_AUTODETECT is False: | |
46 | lazy_detect=False | |
47 | if not lazy_detect: | |
48 | for val in versiondict.values(): | |
49 | for arch in list(val.keys()): | |
50 | cfg=val[arch] | |
51 | cfg.evaluate() | |
52 | if not cfg.is_valid: | |
53 | del val[arch] | |
54 | conf.env.MSVC_INSTALLED_VERSIONS=versiondict | |
55 | for version in desired_versions: | |
56 | Logs.debug('msvc: detecting %r - %r',version,desired_versions) | |
57 | try: | |
58 | targets=versiondict[version] | |
59 | except KeyError: | |
60 | continue | |
61 | seen=set() | |
62 | for arch in platforms: | |
63 | if arch in seen: | |
64 | continue | |
65 | else: | |
66 | seen.add(arch) | |
67 | try: | |
68 | cfg=targets[arch] | |
69 | except KeyError: | |
70 | continue | |
71 | cfg.evaluate() | |
72 | if cfg.is_valid: | |
73 | compiler,revision=version.rsplit(' ',1) | |
74 | return compiler,revision,cfg.bindirs,cfg.incdirs,cfg.libdirs,cfg.cpu | |
75 | conf.fatal('msvc: Impossible to find a valid architecture for building %r - %r'%(desired_versions,list(versiondict.keys()))) | |
76 | @conf | |
77 | def get_msvc_version(conf,compiler,version,target,vcvars): | |
78 | Logs.debug('msvc: get_msvc_version: %r %r %r',compiler,version,target) | |
79 | try: | |
80 | conf.msvc_cnt+=1 | |
81 | except AttributeError: | |
82 | conf.msvc_cnt=1 | |
83 | batfile=conf.bldnode.make_node('waf-print-msvc-%d.bat'%conf.msvc_cnt) | |
84 | batfile.write("""@echo off | |
85 | set INCLUDE= | |
86 | set LIB= | |
87 | call "%s" %s | |
88 | echo PATH=%%PATH%% | |
89 | echo INCLUDE=%%INCLUDE%% | |
90 | echo LIB=%%LIB%%;%%LIBPATH%% | |
91 | """%(vcvars,target)) | |
92 | sout=conf.cmd_and_log(['cmd.exe','/E:on','/V:on','/C',batfile.abspath()]) | |
93 | lines=sout.splitlines() | |
94 | if not lines[0]: | |
95 | lines.pop(0) | |
96 | MSVC_PATH=MSVC_INCDIR=MSVC_LIBDIR=None | |
97 | for line in lines: | |
98 | if line.startswith('PATH='): | |
99 | path=line[5:] | |
100 | MSVC_PATH=path.split(';') | |
101 | elif line.startswith('INCLUDE='): | |
102 | MSVC_INCDIR=[i for i in line[8:].split(';')if i] | |
103 | elif line.startswith('LIB='): | |
104 | MSVC_LIBDIR=[i for i in line[4:].split(';')if i] | |
105 | if None in(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR): | |
106 | conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)') | |
107 | env=dict(os.environ) | |
108 | env.update(PATH=path) | |
109 | compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler) | |
110 | cxx=conf.find_program(compiler_name,path_list=MSVC_PATH) | |
111 | if'CL'in env: | |
112 | del(env['CL']) | |
113 | try: | |
114 | conf.cmd_and_log(cxx+['/help'],env=env) | |
115 | except UnicodeError: | |
116 | st=traceback.format_exc() | |
117 | if conf.logger: | |
118 | conf.logger.error(st) | |
119 | conf.fatal('msvc: Unicode error - check the code page?') | |
120 | except Exception as e: | |
121 | Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s',compiler,version,target,str(e)) | |
122 | conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)') | |
123 | else: | |
124 | Logs.debug('msvc: get_msvc_version: %r %r %r -> OK',compiler,version,target) | |
125 | finally: | |
126 | conf.env[compiler_name]='' | |
127 | return(MSVC_PATH,MSVC_INCDIR,MSVC_LIBDIR) | |
128 | def gather_wince_supported_platforms(): | |
129 | supported_wince_platforms=[] | |
130 | try: | |
131 | ce_sdk=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') | |
132 | except OSError: | |
133 | try: | |
134 | ce_sdk=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') | |
135 | except OSError: | |
136 | ce_sdk='' | |
137 | if not ce_sdk: | |
138 | return supported_wince_platforms | |
139 | index=0 | |
140 | while 1: | |
141 | try: | |
142 | sdk_device=Utils.winreg.EnumKey(ce_sdk,index) | |
143 | sdk=Utils.winreg.OpenKey(ce_sdk,sdk_device) | |
144 | except OSError: | |
145 | break | |
146 | index+=1 | |
147 | try: | |
148 | path,type=Utils.winreg.QueryValueEx(sdk,'SDKRootDir') | |
149 | except OSError: | |
150 | try: | |
151 | path,type=Utils.winreg.QueryValueEx(sdk,'SDKInformation') | |
152 | except OSError: | |
153 | continue | |
154 | path,xml=os.path.split(path) | |
155 | path=str(path) | |
156 | path,device=os.path.split(path) | |
157 | if not device: | |
158 | path,device=os.path.split(path) | |
159 | platforms=[] | |
160 | for arch,compiler in all_wince_platforms: | |
161 | if os.path.isdir(os.path.join(path,device,'Lib',arch)): | |
162 | platforms.append((arch,compiler,os.path.join(path,device,'Include',arch),os.path.join(path,device,'Lib',arch))) | |
163 | if platforms: | |
164 | supported_wince_platforms.append((device,platforms)) | |
165 | return supported_wince_platforms | |
166 | def gather_msvc_detected_versions(): | |
167 | version_pattern=re.compile(r'^(\d\d?\.\d\d?)(Exp)?$') | |
168 | detected_versions=[] | |
169 | for vcver,vcvar in(('VCExpress','Exp'),('VisualStudio','')): | |
170 | prefix='SOFTWARE\\Wow6432node\\Microsoft\\'+vcver | |
171 | try: | |
172 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,prefix) | |
173 | except OSError: | |
174 | prefix='SOFTWARE\\Microsoft\\'+vcver | |
175 | try: | |
176 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,prefix) | |
177 | except OSError: | |
178 | continue | |
179 | index=0 | |
180 | while 1: | |
181 | try: | |
182 | version=Utils.winreg.EnumKey(all_versions,index) | |
183 | except OSError: | |
184 | break | |
185 | index+=1 | |
186 | match=version_pattern.match(version) | |
187 | if match: | |
188 | versionnumber=float(match.group(1)) | |
189 | else: | |
190 | continue | |
191 | detected_versions.append((versionnumber,version+vcvar,prefix+'\\'+version)) | |
192 | def fun(tup): | |
193 | return tup[0] | |
194 | detected_versions.sort(key=fun) | |
195 | return detected_versions | |
196 | class target_compiler(object): | |
197 | def __init__(self,ctx,compiler,cpu,version,bat_target,bat,callback=None): | |
198 | self.conf=ctx | |
199 | self.name=None | |
200 | self.is_valid=False | |
201 | self.is_done=False | |
202 | self.compiler=compiler | |
203 | self.cpu=cpu | |
204 | self.version=version | |
205 | self.bat_target=bat_target | |
206 | self.bat=bat | |
207 | self.callback=callback | |
208 | def evaluate(self): | |
209 | if self.is_done: | |
210 | return | |
211 | self.is_done=True | |
212 | try: | |
213 | vs=self.conf.get_msvc_version(self.compiler,self.version,self.bat_target,self.bat) | |
214 | except Errors.ConfigurationError: | |
215 | self.is_valid=False | |
216 | return | |
217 | if self.callback: | |
218 | vs=self.callback(self,vs) | |
219 | self.is_valid=True | |
220 | (self.bindirs,self.incdirs,self.libdirs)=vs | |
221 | def __str__(self): | |
222 | return str((self.compiler,self.cpu,self.version,self.bat_target,self.bat)) | |
223 | def __repr__(self): | |
224 | return repr((self.compiler,self.cpu,self.version,self.bat_target,self.bat)) | |
225 | @conf | |
226 | def gather_wsdk_versions(conf,versions): | |
227 | version_pattern=re.compile(r'^v..?.?\...?.?') | |
228 | try: | |
229 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') | |
230 | except OSError: | |
231 | try: | |
232 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') | |
233 | except OSError: | |
234 | return | |
235 | index=0 | |
236 | while 1: | |
237 | try: | |
238 | version=Utils.winreg.EnumKey(all_versions,index) | |
239 | except OSError: | |
240 | break | |
241 | index+=1 | |
242 | if not version_pattern.match(version): | |
243 | continue | |
244 | try: | |
245 | msvc_version=Utils.winreg.OpenKey(all_versions,version) | |
246 | path,type=Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') | |
247 | except OSError: | |
248 | continue | |
249 | if path and os.path.isfile(os.path.join(path,'bin','SetEnv.cmd')): | |
250 | targets={} | |
251 | for target,arch in all_msvc_platforms: | |
252 | targets[target]=target_compiler(conf,'wsdk',arch,version,'/'+target,os.path.join(path,'bin','SetEnv.cmd')) | |
253 | versions['wsdk '+version[1:]]=targets | |
254 | @conf | |
255 | def gather_msvc_targets(conf,versions,version,vc_path): | |
256 | targets={} | |
257 | if os.path.isfile(os.path.join(vc_path,'VC','Auxiliary','Build','vcvarsall.bat')): | |
258 | for target,realtarget in all_msvc_platforms[::-1]: | |
259 | targets[target]=target_compiler(conf,'msvc',realtarget,version,target,os.path.join(vc_path,'VC','Auxiliary','Build','vcvarsall.bat')) | |
260 | elif os.path.isfile(os.path.join(vc_path,'vcvarsall.bat')): | |
261 | for target,realtarget in all_msvc_platforms[::-1]: | |
262 | targets[target]=target_compiler(conf,'msvc',realtarget,version,target,os.path.join(vc_path,'vcvarsall.bat')) | |
263 | elif os.path.isfile(os.path.join(vc_path,'Common7','Tools','vsvars32.bat')): | |
264 | targets['x86']=target_compiler(conf,'msvc','x86',version,'x86',os.path.join(vc_path,'Common7','Tools','vsvars32.bat')) | |
265 | elif os.path.isfile(os.path.join(vc_path,'Bin','vcvars32.bat')): | |
266 | targets['x86']=target_compiler(conf,'msvc','x86',version,'',os.path.join(vc_path,'Bin','vcvars32.bat')) | |
267 | if targets: | |
268 | versions['msvc %s'%version]=targets | |
269 | @conf | |
270 | def gather_wince_targets(conf,versions,version,vc_path,vsvars,supported_platforms): | |
271 | for device,platforms in supported_platforms: | |
272 | targets={} | |
273 | for platform,compiler,include,lib in platforms: | |
274 | winCEpath=os.path.join(vc_path,'ce') | |
275 | if not os.path.isdir(winCEpath): | |
276 | continue | |
277 | if os.path.isdir(os.path.join(winCEpath,'lib',platform)): | |
278 | bindirs=[os.path.join(winCEpath,'bin',compiler),os.path.join(winCEpath,'bin','x86_'+compiler)] | |
279 | incdirs=[os.path.join(winCEpath,'include'),os.path.join(winCEpath,'atlmfc','include'),include] | |
280 | libdirs=[os.path.join(winCEpath,'lib',platform),os.path.join(winCEpath,'atlmfc','lib',platform),lib] | |
281 | def combine_common(obj,compiler_env): | |
282 | (common_bindirs,_1,_2)=compiler_env | |
283 | return(bindirs+common_bindirs,incdirs,libdirs) | |
284 | targets[platform]=target_compiler(conf,'msvc',platform,version,'x86',vsvars,combine_common) | |
285 | if targets: | |
286 | versions[device+' '+version]=targets | |
287 | @conf | |
288 | def gather_winphone_targets(conf,versions,version,vc_path,vsvars): | |
289 | targets={} | |
290 | for target,realtarget in all_msvc_platforms[::-1]: | |
291 | targets[target]=target_compiler(conf,'winphone',realtarget,version,target,vsvars) | |
292 | if targets: | |
293 | versions['winphone '+version]=targets | |
294 | @conf | |
295 | def gather_vswhere_versions(conf,versions): | |
296 | try: | |
297 | import json | |
298 | except ImportError: | |
299 | Logs.error('Visual Studio 2017 detection requires Python 2.6') | |
300 | return | |
301 | prg_path=os.environ.get('ProgramFiles(x86)',os.environ.get('ProgramFiles','C:\\Program Files (x86)')) | |
302 | vswhere=os.path.join(prg_path,'Microsoft Visual Studio','Installer','vswhere.exe') | |
303 | args=[vswhere,'-products','*','-legacy','-format','json'] | |
304 | try: | |
305 | txt=conf.cmd_and_log(args) | |
306 | except Errors.WafError as e: | |
307 | Logs.debug('msvc: vswhere.exe failed %s',e) | |
308 | return | |
309 | if sys.version_info[0]<3: | |
310 | txt=txt.decode(Utils.console_encoding()) | |
311 | arr=json.loads(txt) | |
312 | arr.sort(key=lambda x:x['installationVersion']) | |
313 | for entry in arr: | |
314 | ver=entry['installationVersion'] | |
315 | ver=str('.'.join(ver.split('.')[:2])) | |
316 | path=str(os.path.abspath(entry['installationPath'])) | |
317 | if os.path.exists(path)and('msvc %s'%ver)not in versions: | |
318 | conf.gather_msvc_targets(versions,ver,path) | |
319 | @conf | |
320 | def gather_msvc_versions(conf,versions): | |
321 | vc_paths=[] | |
322 | for(v,version,reg)in gather_msvc_detected_versions(): | |
323 | try: | |
324 | try: | |
325 | msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,reg+"\\Setup\\VC") | |
326 | except OSError: | |
327 | msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,reg+"\\Setup\\Microsoft Visual C++") | |
328 | path,type=Utils.winreg.QueryValueEx(msvc_version,'ProductDir') | |
329 | except OSError: | |
330 | try: | |
331 | msvc_version=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,"SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7") | |
332 | path,type=Utils.winreg.QueryValueEx(msvc_version,version) | |
333 | except OSError: | |
334 | continue | |
335 | else: | |
336 | vc_paths.append((version,os.path.abspath(str(path)))) | |
337 | continue | |
338 | else: | |
339 | vc_paths.append((version,os.path.abspath(str(path)))) | |
340 | wince_supported_platforms=gather_wince_supported_platforms() | |
341 | for version,vc_path in vc_paths: | |
342 | vs_path=os.path.dirname(vc_path) | |
343 | vsvars=os.path.join(vs_path,'Common7','Tools','vsvars32.bat') | |
344 | if wince_supported_platforms and os.path.isfile(vsvars): | |
345 | conf.gather_wince_targets(versions,version,vc_path,vsvars,wince_supported_platforms) | |
346 | for version,vc_path in vc_paths: | |
347 | vs_path=os.path.dirname(vc_path) | |
348 | vsvars=os.path.join(vs_path,'VC','WPSDK','WP80','vcvarsphoneall.bat') | |
349 | if os.path.isfile(vsvars): | |
350 | conf.gather_winphone_targets(versions,'8.0',vc_path,vsvars) | |
351 | break | |
352 | for version,vc_path in vc_paths: | |
353 | vs_path=os.path.dirname(vc_path) | |
354 | conf.gather_msvc_targets(versions,version,vc_path) | |
355 | @conf | |
356 | def gather_icl_versions(conf,versions): | |
357 | version_pattern=re.compile(r'^...?.?\....?.?') | |
358 | try: | |
359 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') | |
360 | except OSError: | |
361 | try: | |
362 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Compilers\\C++') | |
363 | except OSError: | |
364 | return | |
365 | index=0 | |
366 | while 1: | |
367 | try: | |
368 | version=Utils.winreg.EnumKey(all_versions,index) | |
369 | except OSError: | |
370 | break | |
371 | index+=1 | |
372 | if not version_pattern.match(version): | |
373 | continue | |
374 | targets={} | |
375 | for target,arch in all_icl_platforms: | |
376 | if target=='intel64': | |
377 | targetDir='EM64T_NATIVE' | |
378 | else: | |
379 | targetDir=target | |
380 | try: | |
381 | Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) | |
382 | icl_version=Utils.winreg.OpenKey(all_versions,version) | |
383 | path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') | |
384 | except OSError: | |
385 | pass | |
386 | else: | |
387 | batch_file=os.path.join(path,'bin','iclvars.bat') | |
388 | if os.path.isfile(batch_file): | |
389 | targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file) | |
390 | for target,arch in all_icl_platforms: | |
391 | try: | |
392 | icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+target) | |
393 | path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') | |
394 | except OSError: | |
395 | continue | |
396 | else: | |
397 | batch_file=os.path.join(path,'bin','iclvars.bat') | |
398 | if os.path.isfile(batch_file): | |
399 | targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file) | |
400 | major=version[0:2] | |
401 | versions['intel '+major]=targets | |
402 | @conf | |
403 | def gather_intel_composer_versions(conf,versions): | |
404 | version_pattern=re.compile(r'^...?.?\...?.?.?') | |
405 | try: | |
406 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Wow6432node\\Intel\\Suites') | |
407 | except OSError: | |
408 | try: | |
409 | all_versions=Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE,'SOFTWARE\\Intel\\Suites') | |
410 | except OSError: | |
411 | return | |
412 | index=0 | |
413 | while 1: | |
414 | try: | |
415 | version=Utils.winreg.EnumKey(all_versions,index) | |
416 | except OSError: | |
417 | break | |
418 | index+=1 | |
419 | if not version_pattern.match(version): | |
420 | continue | |
421 | targets={} | |
422 | for target,arch in all_icl_platforms: | |
423 | if target=='intel64': | |
424 | targetDir='EM64T_NATIVE' | |
425 | else: | |
426 | targetDir=target | |
427 | try: | |
428 | try: | |
429 | defaults=Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir) | |
430 | except OSError: | |
431 | if targetDir=='EM64T_NATIVE': | |
432 | defaults=Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T') | |
433 | else: | |
434 | raise | |
435 | uid,type=Utils.winreg.QueryValueEx(defaults,'SubKey') | |
436 | Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir) | |
437 | icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++') | |
438 | path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') | |
439 | except OSError: | |
440 | pass | |
441 | else: | |
442 | batch_file=os.path.join(path,'bin','iclvars.bat') | |
443 | if os.path.isfile(batch_file): | |
444 | targets[target]=target_compiler(conf,'intel',arch,version,target,batch_file) | |
445 | compilervars_warning_attr='_compilervars_warning_key' | |
446 | if version[0:2]=='13'and getattr(conf,compilervars_warning_attr,True): | |
447 | setattr(conf,compilervars_warning_attr,False) | |
448 | patch_url='http://software.intel.com/en-us/forums/topic/328487' | |
449 | compilervars_arch=os.path.join(path,'bin','compilervars_arch.bat') | |
450 | for vscomntool in('VS110COMNTOOLS','VS100COMNTOOLS'): | |
451 | if vscomntool in os.environ: | |
452 | vs_express_path=os.environ[vscomntool]+r'..\IDE\VSWinExpress.exe' | |
453 | dev_env_path=os.environ[vscomntool]+r'..\IDE\devenv.exe' | |
454 | if(r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"'in Utils.readf(compilervars_arch)and not os.path.exists(vs_express_path)and not os.path.exists(dev_env_path)): | |
455 | Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU ''(VSWinExpress.exe) but it does not seem to be installed at %r. ''The intel command line set up will fail to configure unless the file %r''is patched. See: %s')%(vs_express_path,compilervars_arch,patch_url)) | |
456 | major=version[0:2] | |
457 | versions['intel '+major]=targets | |
458 | @conf | |
459 | def detect_msvc(self): | |
460 | return self.setup_msvc(self.get_msvc_versions()) | |
461 | @conf | |
462 | def get_msvc_versions(self): | |
463 | dct=Utils.ordered_iter_dict() | |
464 | self.gather_icl_versions(dct) | |
465 | self.gather_intel_composer_versions(dct) | |
466 | self.gather_wsdk_versions(dct) | |
467 | self.gather_msvc_versions(dct) | |
468 | self.gather_vswhere_versions(dct) | |
469 | Logs.debug('msvc: detected versions %r',list(dct.keys())) | |
470 | return dct | |
471 | @conf | |
472 | def find_lt_names_msvc(self,libname,is_static=False): | |
473 | lt_names=['lib%s.la'%libname,'%s.la'%libname,] | |
474 | for path in self.env.LIBPATH: | |
475 | for la in lt_names: | |
476 | laf=os.path.join(path,la) | |
477 | dll=None | |
478 | if os.path.exists(laf): | |
479 | ltdict=Utils.read_la_file(laf) | |
480 | lt_libdir=None | |
481 | if ltdict.get('libdir',''): | |
482 | lt_libdir=ltdict['libdir'] | |
483 | if not is_static and ltdict.get('library_names',''): | |
484 | dllnames=ltdict['library_names'].split() | |
485 | dll=dllnames[0].lower() | |
486 | dll=re.sub(r'\.dll$','',dll) | |
487 | return(lt_libdir,dll,False) | |
488 | elif ltdict.get('old_library',''): | |
489 | olib=ltdict['old_library'] | |
490 | if os.path.exists(os.path.join(path,olib)): | |
491 | return(path,olib,True) | |
492 | elif lt_libdir!=''and os.path.exists(os.path.join(lt_libdir,olib)): | |
493 | return(lt_libdir,olib,True) | |
494 | else: | |
495 | return(None,olib,True) | |
496 | else: | |
497 | raise self.errors.WafError('invalid libtool object file: %s'%laf) | |
498 | return(None,None,None) | |
499 | @conf | |
500 | def libname_msvc(self,libname,is_static=False): | |
501 | lib=libname.lower() | |
502 | lib=re.sub(r'\.lib$','',lib) | |
503 | if lib in g_msvc_systemlibs: | |
504 | return lib | |
505 | lib=re.sub('^lib','',lib) | |
506 | if lib=='m': | |
507 | return None | |
508 | (lt_path,lt_libname,lt_static)=self.find_lt_names_msvc(lib,is_static) | |
509 | if lt_path!=None and lt_libname!=None: | |
510 | if lt_static: | |
511 | return os.path.join(lt_path,lt_libname) | |
512 | if lt_path!=None: | |
513 | _libpaths=[lt_path]+self.env.LIBPATH | |
514 | else: | |
515 | _libpaths=self.env.LIBPATH | |
516 | static_libs=['lib%ss.lib'%lib,'lib%s.lib'%lib,'%ss.lib'%lib,'%s.lib'%lib,] | |
517 | dynamic_libs=['lib%s.dll.lib'%lib,'lib%s.dll.a'%lib,'%s.dll.lib'%lib,'%s.dll.a'%lib,'lib%s_d.lib'%lib,'%s_d.lib'%lib,'%s.lib'%lib,] | |
518 | libnames=static_libs | |
519 | if not is_static: | |
520 | libnames=dynamic_libs+static_libs | |
521 | for path in _libpaths: | |
522 | for libn in libnames: | |
523 | if os.path.exists(os.path.join(path,libn)): | |
524 | Logs.debug('msvc: lib found: %s',os.path.join(path,libn)) | |
525 | return re.sub(r'\.lib$','',libn) | |
526 | self.fatal('The library %r could not be found'%libname) | |
527 | return re.sub(r'\.lib$','',libname) | |
528 | @conf | |
529 | def check_lib_msvc(self,libname,is_static=False,uselib_store=None): | |
530 | libn=self.libname_msvc(libname,is_static) | |
531 | if not uselib_store: | |
532 | uselib_store=libname.upper() | |
533 | if False and is_static: | |
534 | self.env['STLIB_'+uselib_store]=[libn] | |
535 | else: | |
536 | self.env['LIB_'+uselib_store]=[libn] | |
537 | @conf | |
538 | def check_libs_msvc(self,libnames,is_static=False): | |
539 | for libname in Utils.to_list(libnames): | |
540 | self.check_lib_msvc(libname,is_static) | |
541 | def configure(conf): | |
542 | conf.autodetect(True) | |
543 | conf.find_msvc() | |
544 | conf.msvc_common_flags() | |
545 | conf.cc_load_tools() | |
546 | conf.cxx_load_tools() | |
547 | conf.cc_add_flags() | |
548 | conf.cxx_add_flags() | |
549 | conf.link_add_flags() | |
550 | conf.visual_studio_add_flags() | |
551 | @conf | |
552 | def no_autodetect(conf): | |
553 | conf.env.NO_MSVC_DETECT=1 | |
554 | configure(conf) | |
555 | @conf | |
556 | def autodetect(conf,arch=False): | |
557 | v=conf.env | |
558 | if v.NO_MSVC_DETECT: | |
559 | return | |
560 | compiler,version,path,includes,libdirs,cpu=conf.detect_msvc() | |
561 | if arch: | |
562 | v.DEST_CPU=cpu | |
563 | v.PATH=path | |
564 | v.INCLUDES=includes | |
565 | v.LIBPATH=libdirs | |
566 | v.MSVC_COMPILER=compiler | |
567 | try: | |
568 | v.MSVC_VERSION=float(version) | |
569 | except ValueError: | |
570 | v.MSVC_VERSION=float(version[:-3]) | |
571 | def _get_prog_names(conf,compiler): | |
572 | if compiler=='intel': | |
573 | compiler_name='ICL' | |
574 | linker_name='XILINK' | |
575 | lib_name='XILIB' | |
576 | else: | |
577 | compiler_name='CL' | |
578 | linker_name='LINK' | |
579 | lib_name='LIB' | |
580 | return compiler_name,linker_name,lib_name | |
581 | @conf | |
582 | def find_msvc(conf): | |
583 | if sys.platform=='cygwin': | |
584 | conf.fatal('MSVC module does not work under cygwin Python!') | |
585 | v=conf.env | |
586 | path=v.PATH | |
587 | compiler=v.MSVC_COMPILER | |
588 | version=v.MSVC_VERSION | |
589 | compiler_name,linker_name,lib_name=_get_prog_names(conf,compiler) | |
590 | v.MSVC_MANIFEST=(compiler=='msvc'and version>=8)or(compiler=='wsdk'and version>=6)or(compiler=='intel'and version>=11) | |
591 | cxx=conf.find_program(compiler_name,var='CXX',path_list=path) | |
592 | env=dict(conf.environ) | |
593 | if path: | |
594 | env.update(PATH=';'.join(path)) | |
595 | if not conf.cmd_and_log(cxx+['/nologo','/help'],env=env): | |
596 | conf.fatal('the msvc compiler could not be identified') | |
597 | v.CC=v.CXX=cxx | |
598 | v.CC_NAME=v.CXX_NAME='msvc' | |
599 | if not v.LINK_CXX: | |
600 | conf.find_program(linker_name,path_list=path,errmsg='%s was not found (linker)'%linker_name,var='LINK_CXX') | |
601 | if not v.LINK_CC: | |
602 | v.LINK_CC=v.LINK_CXX | |
603 | if not v.AR: | |
604 | stliblink=conf.find_program(lib_name,path_list=path,var='AR') | |
605 | if not stliblink: | |
606 | return | |
607 | v.ARFLAGS=['/nologo'] | |
608 | if v.MSVC_MANIFEST: | |
609 | conf.find_program('MT',path_list=path,var='MT') | |
610 | v.MTFLAGS=['/nologo'] | |
611 | try: | |
612 | conf.load('winres') | |
613 | except Errors.ConfigurationError: | |
614 | Logs.warn('Resource compiler not found. Compiling resource file is disabled') | |
615 | @conf | |
616 | def visual_studio_add_flags(self): | |
617 | v=self.env | |
618 | if self.environ.get('INCLUDE'): | |
619 | v.prepend_value('INCLUDES',[x for x in self.environ['INCLUDE'].split(';')if x]) | |
620 | if self.environ.get('LIB'): | |
621 | v.prepend_value('LIBPATH',[x for x in self.environ['LIB'].split(';')if x]) | |
622 | @conf | |
623 | def msvc_common_flags(conf): | |
624 | v=conf.env | |
625 | v.DEST_BINFMT='pe' | |
626 | v.append_value('CFLAGS',['/nologo']) | |
627 | v.append_value('CXXFLAGS',['/nologo']) | |
628 | v.append_value('LINKFLAGS',['/nologo']) | |
629 | v.DEFINES_ST='/D%s' | |
630 | v.CC_SRC_F='' | |
631 | v.CC_TGT_F=['/c','/Fo'] | |
632 | v.CXX_SRC_F='' | |
633 | v.CXX_TGT_F=['/c','/Fo'] | |
634 | if(v.MSVC_COMPILER=='msvc'and v.MSVC_VERSION>=8)or(v.MSVC_COMPILER=='wsdk'and v.MSVC_VERSION>=6): | |
635 | v.CC_TGT_F=['/FC']+v.CC_TGT_F | |
636 | v.CXX_TGT_F=['/FC']+v.CXX_TGT_F | |
637 | v.CPPPATH_ST='/I%s' | |
638 | v.AR_TGT_F=v.CCLNK_TGT_F=v.CXXLNK_TGT_F='/OUT:' | |
639 | v.CFLAGS_CRT_MULTITHREADED=v.CXXFLAGS_CRT_MULTITHREADED=['/MT'] | |
640 | v.CFLAGS_CRT_MULTITHREADED_DLL=v.CXXFLAGS_CRT_MULTITHREADED_DLL=['/MD'] | |
641 | v.CFLAGS_CRT_MULTITHREADED_DBG=v.CXXFLAGS_CRT_MULTITHREADED_DBG=['/MTd'] | |
642 | v.CFLAGS_CRT_MULTITHREADED_DLL_DBG=v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG=['/MDd'] | |
643 | v.LIB_ST='%s.lib' | |
644 | v.LIBPATH_ST='/LIBPATH:%s' | |
645 | v.STLIB_ST='%s.lib' | |
646 | v.STLIBPATH_ST='/LIBPATH:%s' | |
647 | if v.MSVC_MANIFEST: | |
648 | v.append_value('LINKFLAGS',['/MANIFEST']) | |
649 | v.CFLAGS_cshlib=[] | |
650 | v.CXXFLAGS_cxxshlib=[] | |
651 | v.LINKFLAGS_cshlib=v.LINKFLAGS_cxxshlib=['/DLL'] | |
652 | v.cshlib_PATTERN=v.cxxshlib_PATTERN='%s.dll' | |
653 | v.implib_PATTERN='%s.lib' | |
654 | v.IMPLIB_ST='/IMPLIB:%s' | |
655 | v.LINKFLAGS_cstlib=[] | |
656 | v.cstlib_PATTERN=v.cxxstlib_PATTERN='%s.lib' | |
657 | v.cprogram_PATTERN=v.cxxprogram_PATTERN='%s.exe' | |
658 | v.def_PATTERN='/def:%s' | |
659 | @after_method('apply_link') | |
660 | @feature('c','cxx') | |
661 | def apply_flags_msvc(self): | |
662 | if self.env.CC_NAME!='msvc'or not getattr(self,'link_task',None): | |
663 | return | |
664 | is_static=isinstance(self.link_task,ccroot.stlink_task) | |
665 | subsystem=getattr(self,'subsystem','') | |
666 | if subsystem: | |
667 | subsystem='/subsystem:%s'%subsystem | |
668 | flags=is_static and'ARFLAGS'or'LINKFLAGS' | |
669 | self.env.append_value(flags,subsystem) | |
670 | if not is_static: | |
671 | for f in self.env.LINKFLAGS: | |
672 | d=f.lower() | |
673 | if d[1:]in('debug','debug:full','debug:fastlink'): | |
674 | pdbnode=self.link_task.outputs[0].change_ext('.pdb') | |
675 | self.link_task.outputs.append(pdbnode) | |
676 | if getattr(self,'install_task',None): | |
677 | self.pdb_install_task=self.add_install_files(install_to=self.install_task.install_to,install_from=pdbnode) | |
678 | break | |
679 | @feature('cprogram','cshlib','cxxprogram','cxxshlib') | |
680 | @after_method('apply_link') | |
681 | def apply_manifest(self): | |
682 | if self.env.CC_NAME=='msvc'and self.env.MSVC_MANIFEST and getattr(self,'link_task',None): | |
683 | out_node=self.link_task.outputs[0] | |
684 | man_node=out_node.parent.find_or_declare(out_node.name+'.manifest') | |
685 | self.link_task.outputs.append(man_node) | |
686 | self.env.DO_MANIFEST=True | |
687 | def make_winapp(self,family): | |
688 | append=self.env.append_unique | |
689 | append('DEFINES','WINAPI_FAMILY=%s'%family) | |
690 | append('CXXFLAGS',['/ZW','/TP']) | |
691 | for lib_path in self.env.LIBPATH: | |
692 | append('CXXFLAGS','/AI%s'%lib_path) | |
693 | @feature('winphoneapp') | |
694 | @after_method('process_use') | |
695 | @after_method('propagate_uselib_vars') | |
696 | def make_winphone_app(self): | |
697 | make_winapp(self,'WINAPI_FAMILY_PHONE_APP') | |
698 | self.env.append_unique('LINKFLAGS',['/NODEFAULTLIB:ole32.lib','PhoneAppModelHost.lib']) | |
699 | @feature('winapp') | |
700 | @after_method('process_use') | |
701 | @after_method('propagate_uselib_vars') | |
702 | def make_windows_app(self): | |
703 | make_winapp(self,'WINAPI_FAMILY_DESKTOP_APP') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os | |
5 | import waflib.Tools.asm | |
6 | from waflib.TaskGen import feature | |
7 | @feature('asm') | |
8 | def apply_nasm_vars(self): | |
9 | self.env.append_value('ASFLAGS',self.to_list(getattr(self,'nasm_flags',[]))) | |
10 | def configure(conf): | |
11 | conf.find_program(['nasm','yasm'],var='AS') | |
12 | conf.env.AS_TGT_F=['-o'] | |
13 | conf.env.ASLNK_TGT_F=['-o'] | |
14 | conf.load('asm') | |
15 | conf.env.ASMPATH_ST='-I%s'+os.sep | |
16 | txt=conf.cmd_and_log(conf.env.AS+['--version']) | |
17 | if'yasm'in txt.lower(): | |
18 | conf.env.ASM_NAME='yasm' | |
19 | else: | |
20 | conf.env.ASM_NAME='nasm' |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Task | |
5 | def build(bld): | |
6 | def run(self): | |
7 | for x in self.outputs: | |
8 | x.write('') | |
9 | for(name,cls)in Task.classes.items(): | |
10 | cls.run=run |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os | |
5 | from waflib import Task,Options,Utils,Errors | |
6 | from waflib.Configure import conf | |
7 | from waflib.TaskGen import extension,feature,before_method | |
8 | @before_method('apply_incpaths','apply_link','propagate_uselib_vars') | |
9 | @feature('perlext') | |
10 | def init_perlext(self): | |
11 | self.uselib=self.to_list(getattr(self,'uselib',[])) | |
12 | if not'PERLEXT'in self.uselib: | |
13 | self.uselib.append('PERLEXT') | |
14 | self.env.cshlib_PATTERN=self.env.cxxshlib_PATTERN=self.env.perlext_PATTERN | |
15 | @extension('.xs') | |
16 | def xsubpp_file(self,node): | |
17 | outnode=node.change_ext('.c') | |
18 | self.create_task('xsubpp',node,outnode) | |
19 | self.source.append(outnode) | |
20 | class xsubpp(Task.Task): | |
21 | run_str='${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' | |
22 | color='BLUE' | |
23 | ext_out=['.h'] | |
24 | @conf | |
25 | def check_perl_version(self,minver=None): | |
26 | res=True | |
27 | if minver: | |
28 | cver='.'.join(map(str,minver)) | |
29 | else: | |
30 | cver='' | |
31 | self.start_msg('Checking for minimum perl version %s'%cver) | |
32 | perl=self.find_program('perl',var='PERL',value=getattr(Options.options,'perlbinary',None)) | |
33 | version=self.cmd_and_log(perl+["-e",'printf \"%vd\", $^V']) | |
34 | if not version: | |
35 | res=False | |
36 | version="Unknown" | |
37 | elif not minver is None: | |
38 | ver=tuple(map(int,version.split("."))) | |
39 | if ver<minver: | |
40 | res=False | |
41 | self.end_msg(version,color=res and'GREEN'or'YELLOW') | |
42 | return res | |
43 | @conf | |
44 | def check_perl_module(self,module): | |
45 | cmd=self.env.PERL+['-e','use %s'%module] | |
46 | self.start_msg('perl module %s'%module) | |
47 | try: | |
48 | r=self.cmd_and_log(cmd) | |
49 | except Errors.WafError: | |
50 | self.end_msg(False) | |
51 | return None | |
52 | self.end_msg(r or True) | |
53 | return r | |
54 | @conf | |
55 | def check_perl_ext_devel(self): | |
56 | env=self.env | |
57 | perl=env.PERL | |
58 | if not perl: | |
59 | self.fatal('find perl first') | |
60 | def cmd_perl_config(s): | |
61 | return perl+['-MConfig','-e','print \"%s\"'%s] | |
62 | def cfg_str(cfg): | |
63 | return self.cmd_and_log(cmd_perl_config(cfg)) | |
64 | def cfg_lst(cfg): | |
65 | return Utils.to_list(cfg_str(cfg)) | |
66 | def find_xsubpp(): | |
67 | for var in('privlib','vendorlib'): | |
68 | xsubpp=cfg_lst('$Config{%s}/ExtUtils/xsubpp$Config{exe_ext}'%var) | |
69 | if xsubpp and os.path.isfile(xsubpp[0]): | |
70 | return xsubpp | |
71 | return self.find_program('xsubpp') | |
72 | env.LINKFLAGS_PERLEXT=cfg_lst('$Config{lddlflags}') | |
73 | env.INCLUDES_PERLEXT=cfg_lst('$Config{archlib}/CORE') | |
74 | env.CFLAGS_PERLEXT=cfg_lst('$Config{ccflags} $Config{cccdlflags}') | |
75 | env.EXTUTILS_TYPEMAP=cfg_lst('$Config{privlib}/ExtUtils/typemap') | |
76 | env.XSUBPP=find_xsubpp() | |
77 | if not getattr(Options.options,'perlarchdir',None): | |
78 | env.ARCHDIR_PERL=cfg_str('$Config{sitearch}') | |
79 | else: | |
80 | env.ARCHDIR_PERL=getattr(Options.options,'perlarchdir') | |
81 | env.perlext_PATTERN='%s.'+cfg_str('$Config{dlext}') | |
82 | def options(opt): | |
83 | opt.add_option('--with-perl-binary',type='string',dest='perlbinary',help='Specify alternate perl binary',default=None) | |
84 | opt.add_option('--with-perl-archdir',type='string',dest='perlarchdir',help='Specify directory where to install arch specific files',default=None) |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,sys | |
5 | from waflib import Errors,Logs,Node,Options,Task,Utils | |
6 | from waflib.TaskGen import extension,before_method,after_method,feature | |
7 | from waflib.Configure import conf | |
8 | FRAG=''' | |
9 | #include <Python.h> | |
10 | #ifdef __cplusplus | |
11 | extern "C" { | |
12 | #endif | |
13 | void Py_Initialize(void); | |
14 | void Py_Finalize(void); | |
15 | #ifdef __cplusplus | |
16 | } | |
17 | #endif | |
18 | int main(int argc, char **argv) | |
19 | { | |
20 | (void)argc; (void)argv; | |
21 | Py_Initialize(); | |
22 | Py_Finalize(); | |
23 | return 0; | |
24 | } | |
25 | ''' | |
26 | INST=''' | |
27 | import sys, py_compile | |
28 | py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3], True) | |
29 | ''' | |
30 | DISTUTILS_IMP=['from distutils.sysconfig import get_config_var, get_python_lib'] | |
31 | @before_method('process_source') | |
32 | @feature('py') | |
33 | def feature_py(self): | |
34 | self.install_path=getattr(self,'install_path','${PYTHONDIR}') | |
35 | install_from=getattr(self,'install_from',None) | |
36 | if install_from and not isinstance(install_from,Node.Node): | |
37 | install_from=self.path.find_dir(install_from) | |
38 | self.install_from=install_from | |
39 | ver=self.env.PYTHON_VERSION | |
40 | if not ver: | |
41 | self.bld.fatal('Installing python files requires PYTHON_VERSION, try conf.check_python_version') | |
42 | if int(ver.replace('.',''))>31: | |
43 | self.install_32=True | |
44 | @extension('.py') | |
45 | def process_py(self,node): | |
46 | assert(hasattr(self,'install_path')),'add features="py" for target "%s" in "%s/wscript".'%(self.target,self.path.nice_path()) | |
47 | self.install_from=getattr(self,'install_from',None) | |
48 | relative_trick=getattr(self,'relative_trick',True) | |
49 | if self.install_from: | |
50 | assert isinstance(self.install_from,Node.Node),'add features="py" for target "%s" in "%s/wscript" (%s).'%(self.target,self.path.nice_path(),type(self.install_from)) | |
51 | if self.install_path: | |
52 | if self.install_from: | |
53 | self.add_install_files(install_to=self.install_path,install_from=node,cwd=self.install_from,relative_trick=relative_trick) | |
54 | else: | |
55 | self.add_install_files(install_to=self.install_path,install_from=node,relative_trick=relative_trick) | |
56 | lst=[] | |
57 | if self.env.PYC: | |
58 | lst.append('pyc') | |
59 | if self.env.PYO: | |
60 | lst.append('pyo') | |
61 | if self.install_path: | |
62 | if self.install_from: | |
63 | target_dir=node.path_from(self.install_from)if relative_trick else node.name | |
64 | pyd=Utils.subst_vars("%s/%s"%(self.install_path,target_dir),self.env) | |
65 | else: | |
66 | target_dir=node.path_from(self.path)if relative_trick else node.name | |
67 | pyd=Utils.subst_vars("%s/%s"%(self.install_path,target_dir),self.env) | |
68 | else: | |
69 | pyd=node.abspath() | |
70 | for ext in lst: | |
71 | if self.env.PYTAG and not self.env.NOPYCACHE: | |
72 | name=node.name[:-3] | |
73 | pyobj=node.parent.get_bld().make_node('__pycache__').make_node("%s.%s.%s"%(name,self.env.PYTAG,ext)) | |
74 | pyobj.parent.mkdir() | |
75 | else: | |
76 | pyobj=node.change_ext(".%s"%ext) | |
77 | tsk=self.create_task(ext,node,pyobj) | |
78 | tsk.pyd=pyd | |
79 | if self.install_path: | |
80 | self.add_install_files(install_to=os.path.dirname(pyd),install_from=pyobj,cwd=node.parent.get_bld(),relative_trick=relative_trick) | |
81 | class pyc(Task.Task): | |
82 | color='PINK' | |
83 | def __str__(self): | |
84 | node=self.outputs[0] | |
85 | return node.path_from(node.ctx.launch_node()) | |
86 | def run(self): | |
87 | cmd=[Utils.subst_vars('${PYTHON}',self.env),'-c',INST,self.inputs[0].abspath(),self.outputs[0].abspath(),self.pyd] | |
88 | ret=self.generator.bld.exec_command(cmd) | |
89 | return ret | |
90 | class pyo(Task.Task): | |
91 | color='PINK' | |
92 | def __str__(self): | |
93 | node=self.outputs[0] | |
94 | return node.path_from(node.ctx.launch_node()) | |
95 | def run(self): | |
96 | cmd=[Utils.subst_vars('${PYTHON}',self.env),Utils.subst_vars('${PYFLAGS_OPT}',self.env),'-c',INST,self.inputs[0].abspath(),self.outputs[0].abspath(),self.pyd] | |
97 | ret=self.generator.bld.exec_command(cmd) | |
98 | return ret | |
99 | @feature('pyext') | |
100 | @before_method('propagate_uselib_vars','apply_link') | |
101 | @after_method('apply_bundle') | |
102 | def init_pyext(self): | |
103 | self.uselib=self.to_list(getattr(self,'uselib',[])) | |
104 | if not'PYEXT'in self.uselib: | |
105 | self.uselib.append('PYEXT') | |
106 | self.env.cshlib_PATTERN=self.env.cxxshlib_PATTERN=self.env.macbundle_PATTERN=self.env.pyext_PATTERN | |
107 | self.env.fcshlib_PATTERN=self.env.dshlib_PATTERN=self.env.pyext_PATTERN | |
108 | try: | |
109 | if not self.install_path: | |
110 | return | |
111 | except AttributeError: | |
112 | self.install_path='${PYTHONARCHDIR}' | |
113 | @feature('pyext') | |
114 | @before_method('apply_link','apply_bundle') | |
115 | def set_bundle(self): | |
116 | if Utils.unversioned_sys_platform()=='darwin': | |
117 | self.mac_bundle=True | |
118 | @before_method('propagate_uselib_vars') | |
119 | @feature('pyembed') | |
120 | def init_pyembed(self): | |
121 | self.uselib=self.to_list(getattr(self,'uselib',[])) | |
122 | if not'PYEMBED'in self.uselib: | |
123 | self.uselib.append('PYEMBED') | |
124 | @conf | |
125 | def get_python_variables(self,variables,imports=None): | |
126 | if not imports: | |
127 | try: | |
128 | imports=self.python_imports | |
129 | except AttributeError: | |
130 | imports=DISTUTILS_IMP | |
131 | program=list(imports) | |
132 | program.append('') | |
133 | for v in variables: | |
134 | program.append("print(repr(%s))"%v) | |
135 | os_env=dict(os.environ) | |
136 | try: | |
137 | del os_env['MACOSX_DEPLOYMENT_TARGET'] | |
138 | except KeyError: | |
139 | pass | |
140 | try: | |
141 | out=self.cmd_and_log(self.env.PYTHON+['-c','\n'.join(program)],env=os_env) | |
142 | except Errors.WafError: | |
143 | self.fatal('The distutils module is unusable: install "python-devel"?') | |
144 | self.to_log(out) | |
145 | return_values=[] | |
146 | for s in out.splitlines(): | |
147 | s=s.strip() | |
148 | if not s: | |
149 | continue | |
150 | if s=='None': | |
151 | return_values.append(None) | |
152 | elif(s[0]=="'"and s[-1]=="'")or(s[0]=='"'and s[-1]=='"'): | |
153 | return_values.append(eval(s)) | |
154 | elif s[0].isdigit(): | |
155 | return_values.append(int(s)) | |
156 | else:break | |
157 | return return_values | |
158 | @conf | |
159 | def test_pyembed(self,mode,msg='Testing pyembed configuration'): | |
160 | self.check(header_name='Python.h',define_name='HAVE_PYEMBED',msg=msg,fragment=FRAG,errmsg='Could not build a python embedded interpreter',features='%s %sprogram pyembed'%(mode,mode)) | |
161 | @conf | |
162 | def test_pyext(self,mode,msg='Testing pyext configuration'): | |
163 | self.check(header_name='Python.h',define_name='HAVE_PYEXT',msg=msg,fragment=FRAG,errmsg='Could not build python extensions',features='%s %sshlib pyext'%(mode,mode)) | |
164 | @conf | |
165 | def python_cross_compile(self,features='pyembed pyext'): | |
166 | features=Utils.to_list(features) | |
167 | if not('PYTHON_LDFLAGS'in self.environ or'PYTHON_PYEXT_LDFLAGS'in self.environ or'PYTHON_PYEMBED_LDFLAGS'in self.environ): | |
168 | return False | |
169 | for x in'PYTHON_VERSION PYTAG pyext_PATTERN'.split(): | |
170 | if not x in self.environ: | |
171 | self.fatal('Please set %s in the os environment'%x) | |
172 | else: | |
173 | self.env[x]=self.environ[x] | |
174 | xx=self.env.CXX_NAME and'cxx'or'c' | |
175 | if'pyext'in features: | |
176 | flags=self.environ.get('PYTHON_PYEXT_LDFLAGS',self.environ.get('PYTHON_LDFLAGS')) | |
177 | if flags is None: | |
178 | self.fatal('No flags provided through PYTHON_PYEXT_LDFLAGS as required') | |
179 | else: | |
180 | self.parse_flags(flags,'PYEXT') | |
181 | self.test_pyext(xx) | |
182 | if'pyembed'in features: | |
183 | flags=self.environ.get('PYTHON_PYEMBED_LDFLAGS',self.environ.get('PYTHON_LDFLAGS')) | |
184 | if flags is None: | |
185 | self.fatal('No flags provided through PYTHON_PYEMBED_LDFLAGS as required') | |
186 | else: | |
187 | self.parse_flags(flags,'PYEMBED') | |
188 | self.test_pyembed(xx) | |
189 | return True | |
190 | @conf | |
191 | def check_python_headers(conf,features='pyembed pyext'): | |
192 | features=Utils.to_list(features) | |
193 | assert('pyembed'in features)or('pyext'in features),"check_python_headers features must include 'pyembed' and/or 'pyext'" | |
194 | env=conf.env | |
195 | if not env.CC_NAME and not env.CXX_NAME: | |
196 | conf.fatal('load a compiler first (gcc, g++, ..)') | |
197 | if conf.python_cross_compile(features): | |
198 | return | |
199 | if not env.PYTHON_VERSION: | |
200 | conf.check_python_version() | |
201 | pybin=env.PYTHON | |
202 | if not pybin: | |
203 | conf.fatal('Could not find the python executable') | |
204 | v='prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split() | |
205 | try: | |
206 | lst=conf.get_python_variables(["get_config_var('%s') or ''"%x for x in v]) | |
207 | except RuntimeError: | |
208 | conf.fatal("Python development headers not found (-v for details).") | |
209 | vals=['%s = %r'%(x,y)for(x,y)in zip(v,lst)] | |
210 | conf.to_log("Configuration returned from %r:\n%s\n"%(pybin,'\n'.join(vals))) | |
211 | dct=dict(zip(v,lst)) | |
212 | x='MACOSX_DEPLOYMENT_TARGET' | |
213 | if dct[x]: | |
214 | env[x]=conf.environ[x]=dct[x] | |
215 | env.pyext_PATTERN='%s'+dct['SO'] | |
216 | num='.'.join(env.PYTHON_VERSION.split('.')[:2]) | |
217 | conf.find_program([''.join(pybin)+'-config','python%s-config'%num,'python-config-%s'%num,'python%sm-config'%num],var='PYTHON_CONFIG',msg="python-config",mandatory=False) | |
218 | if env.PYTHON_CONFIG: | |
219 | if conf.env.HAVE_PYTHON_H: | |
220 | return | |
221 | all_flags=[['--cflags','--libs','--ldflags']] | |
222 | if sys.hexversion<0x2070000: | |
223 | all_flags=[[k]for k in all_flags[0]] | |
224 | xx=env.CXX_NAME and'cxx'or'c' | |
225 | if'pyembed'in features: | |
226 | for flags in all_flags: | |
227 | embedflags=flags+['--embed'] | |
228 | try: | |
229 | conf.check_cfg(msg='Asking python-config for pyembed %r flags'%' '.join(embedflags),path=env.PYTHON_CONFIG,package='',uselib_store='PYEMBED',args=embedflags) | |
230 | except conf.errors.ConfigurationError: | |
231 | conf.check_cfg(msg='Asking python-config for pyembed %r flags'%' '.join(flags),path=env.PYTHON_CONFIG,package='',uselib_store='PYEMBED',args=flags) | |
232 | try: | |
233 | conf.test_pyembed(xx) | |
234 | except conf.errors.ConfigurationError: | |
235 | if dct['Py_ENABLE_SHARED']and dct['LIBDIR']: | |
236 | env.append_unique('LIBPATH_PYEMBED',[dct['LIBDIR']]) | |
237 | conf.test_pyembed(xx) | |
238 | else: | |
239 | raise | |
240 | if'pyext'in features: | |
241 | for flags in all_flags: | |
242 | conf.check_cfg(msg='Asking python-config for pyext %r flags'%' '.join(flags),path=env.PYTHON_CONFIG,package='',uselib_store='PYEXT',args=flags) | |
243 | try: | |
244 | conf.test_pyext(xx) | |
245 | except conf.errors.ConfigurationError: | |
246 | if dct['Py_ENABLE_SHARED']and dct['LIBDIR']: | |
247 | env.append_unique('LIBPATH_PYEXT',[dct['LIBDIR']]) | |
248 | conf.test_pyext(xx) | |
249 | else: | |
250 | raise | |
251 | conf.define('HAVE_PYTHON_H',1) | |
252 | return | |
253 | all_flags=dct['LDFLAGS']+' '+dct['CFLAGS'] | |
254 | conf.parse_flags(all_flags,'PYEMBED') | |
255 | all_flags=dct['LDFLAGS']+' '+dct['LDSHARED']+' '+dct['CFLAGS'] | |
256 | conf.parse_flags(all_flags,'PYEXT') | |
257 | result=None | |
258 | if not dct["LDVERSION"]: | |
259 | dct["LDVERSION"]=env.PYTHON_VERSION | |
260 | for name in('python'+dct['LDVERSION'],'python'+env.PYTHON_VERSION+'m','python'+env.PYTHON_VERSION.replace('.','')): | |
261 | if not result and env.LIBPATH_PYEMBED: | |
262 | path=env.LIBPATH_PYEMBED | |
263 | conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n"%path) | |
264 | result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in LIBPATH_PYEMBED'%name) | |
265 | if not result and dct['LIBDIR']: | |
266 | path=[dct['LIBDIR']] | |
267 | conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n"%path) | |
268 | result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in LIBDIR'%name) | |
269 | if not result and dct['LIBPL']: | |
270 | path=[dct['LIBPL']] | |
271 | conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") | |
272 | result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in python_LIBPL'%name) | |
273 | if not result: | |
274 | path=[os.path.join(dct['prefix'],"libs")] | |
275 | conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") | |
276 | result=conf.check(lib=name,uselib='PYEMBED',libpath=path,mandatory=False,msg='Checking for library %s in $prefix/libs'%name) | |
277 | if result: | |
278 | break | |
279 | if result: | |
280 | env.LIBPATH_PYEMBED=path | |
281 | env.append_value('LIB_PYEMBED',[name]) | |
282 | else: | |
283 | conf.to_log("\n\n### LIB NOT FOUND\n") | |
284 | if Utils.is_win32 or dct['Py_ENABLE_SHARED']: | |
285 | env.LIBPATH_PYEXT=env.LIBPATH_PYEMBED | |
286 | env.LIB_PYEXT=env.LIB_PYEMBED | |
287 | conf.to_log("Include path for Python extensions (found via distutils module): %r\n"%(dct['INCLUDEPY'],)) | |
288 | env.INCLUDES_PYEXT=[dct['INCLUDEPY']] | |
289 | env.INCLUDES_PYEMBED=[dct['INCLUDEPY']] | |
290 | if env.CC_NAME=='gcc': | |
291 | env.append_unique('CFLAGS_PYEMBED',['-fno-strict-aliasing']) | |
292 | env.append_unique('CFLAGS_PYEXT',['-fno-strict-aliasing']) | |
293 | if env.CXX_NAME=='gcc': | |
294 | env.append_unique('CXXFLAGS_PYEMBED',['-fno-strict-aliasing']) | |
295 | env.append_unique('CXXFLAGS_PYEXT',['-fno-strict-aliasing']) | |
296 | if env.CC_NAME=="msvc": | |
297 | from distutils.msvccompiler import MSVCCompiler | |
298 | dist_compiler=MSVCCompiler() | |
299 | dist_compiler.initialize() | |
300 | env.append_value('CFLAGS_PYEXT',dist_compiler.compile_options) | |
301 | env.append_value('CXXFLAGS_PYEXT',dist_compiler.compile_options) | |
302 | env.append_value('LINKFLAGS_PYEXT',dist_compiler.ldflags_shared) | |
303 | conf.check(header_name='Python.h',define_name='HAVE_PYTHON_H',uselib='PYEMBED',fragment=FRAG,errmsg='Distutils not installed? Broken python installation? Get python-config now!') | |
304 | @conf | |
305 | def check_python_version(conf,minver=None): | |
306 | assert minver is None or isinstance(minver,tuple) | |
307 | pybin=conf.env.PYTHON | |
308 | if not pybin: | |
309 | conf.fatal('could not find the python executable') | |
310 | cmd=pybin+['-c','import sys\nfor x in sys.version_info: print(str(x))'] | |
311 | Logs.debug('python: Running python command %r',cmd) | |
312 | lines=conf.cmd_and_log(cmd).split() | |
313 | assert len(lines)==5,"found %r lines, expected 5: %r"%(len(lines),lines) | |
314 | pyver_tuple=(int(lines[0]),int(lines[1]),int(lines[2]),lines[3],int(lines[4])) | |
315 | result=(minver is None)or(pyver_tuple>=minver) | |
316 | if result: | |
317 | pyver='.'.join([str(x)for x in pyver_tuple[:2]]) | |
318 | conf.env.PYTHON_VERSION=pyver | |
319 | if'PYTHONDIR'in conf.env: | |
320 | pydir=conf.env.PYTHONDIR | |
321 | elif'PYTHONDIR'in conf.environ: | |
322 | pydir=conf.environ['PYTHONDIR'] | |
323 | else: | |
324 | if Utils.is_win32: | |
325 | (python_LIBDEST,pydir)=conf.get_python_variables(["get_config_var('LIBDEST') or ''","get_python_lib(standard_lib=0) or ''"]) | |
326 | else: | |
327 | python_LIBDEST=None | |
328 | (pydir,)=conf.get_python_variables(["get_python_lib(standard_lib=0, prefix=%r) or ''"%conf.env.PREFIX]) | |
329 | if python_LIBDEST is None: | |
330 | if conf.env.LIBDIR: | |
331 | python_LIBDEST=os.path.join(conf.env.LIBDIR,'python'+pyver) | |
332 | else: | |
333 | python_LIBDEST=os.path.join(conf.env.PREFIX,'lib','python'+pyver) | |
334 | if'PYTHONARCHDIR'in conf.env: | |
335 | pyarchdir=conf.env.PYTHONARCHDIR | |
336 | elif'PYTHONARCHDIR'in conf.environ: | |
337 | pyarchdir=conf.environ['PYTHONARCHDIR'] | |
338 | else: | |
339 | (pyarchdir,)=conf.get_python_variables(["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''"%conf.env.PREFIX]) | |
340 | if not pyarchdir: | |
341 | pyarchdir=pydir | |
342 | if hasattr(conf,'define'): | |
343 | conf.define('PYTHONDIR',pydir) | |
344 | conf.define('PYTHONARCHDIR',pyarchdir) | |
345 | conf.env.PYTHONDIR=pydir | |
346 | conf.env.PYTHONARCHDIR=pyarchdir | |
347 | pyver_full='.'.join(map(str,pyver_tuple[:3])) | |
348 | if minver is None: | |
349 | conf.msg('Checking for python version',pyver_full) | |
350 | else: | |
351 | minver_str='.'.join(map(str,minver)) | |
352 | conf.msg('Checking for python version >= %s'%(minver_str,),pyver_full,color=result and'GREEN'or'YELLOW') | |
353 | if not result: | |
354 | conf.fatal('The python version is too old, expecting %r'%(minver,)) | |
355 | PYTHON_MODULE_TEMPLATE=''' | |
356 | import %s as current_module | |
357 | version = getattr(current_module, '__version__', None) | |
358 | if version is not None: | |
359 | print(str(version)) | |
360 | else: | |
361 | print('unknown version') | |
362 | ''' | |
363 | @conf | |
364 | def check_python_module(conf,module_name,condition=''): | |
365 | msg="Checking for python module %r"%module_name | |
366 | if condition: | |
367 | msg='%s (%s)'%(msg,condition) | |
368 | conf.start_msg(msg) | |
369 | try: | |
370 | ret=conf.cmd_and_log(conf.env.PYTHON+['-c',PYTHON_MODULE_TEMPLATE%module_name]) | |
371 | except Errors.WafError: | |
372 | conf.end_msg(False) | |
373 | conf.fatal('Could not find the python module %r'%module_name) | |
374 | ret=ret.strip() | |
375 | if condition: | |
376 | conf.end_msg(ret) | |
377 | if ret=='unknown version': | |
378 | conf.fatal('Could not check the %s version'%module_name) | |
379 | from distutils.version import LooseVersion | |
380 | def num(*k): | |
381 | if isinstance(k[0],int): | |
382 | return LooseVersion('.'.join([str(x)for x in k])) | |
383 | else: | |
384 | return LooseVersion(k[0]) | |
385 | d={'num':num,'ver':LooseVersion(ret)} | |
386 | ev=eval(condition,{},d) | |
387 | if not ev: | |
388 | conf.fatal('The %s version does not satisfy the requirements'%module_name) | |
389 | else: | |
390 | if ret=='unknown version': | |
391 | conf.end_msg(True) | |
392 | else: | |
393 | conf.end_msg(ret) | |
394 | def configure(conf): | |
395 | v=conf.env | |
396 | if getattr(Options.options,'pythondir',None): | |
397 | v.PYTHONDIR=Options.options.pythondir | |
398 | if getattr(Options.options,'pythonarchdir',None): | |
399 | v.PYTHONARCHDIR=Options.options.pythonarchdir | |
400 | if getattr(Options.options,'nopycache',None): | |
401 | v.NOPYCACHE=Options.options.nopycache | |
402 | if not v.PYTHON: | |
403 | v.PYTHON=[getattr(Options.options,'python',None)or sys.executable] | |
404 | v.PYTHON=Utils.to_list(v.PYTHON) | |
405 | conf.find_program('python',var='PYTHON') | |
406 | v.PYFLAGS='' | |
407 | v.PYFLAGS_OPT='-O' | |
408 | v.PYC=getattr(Options.options,'pyc',1) | |
409 | v.PYO=getattr(Options.options,'pyo',1) | |
410 | try: | |
411 | v.PYTAG=conf.cmd_and_log(conf.env.PYTHON+['-c',"import sys\ntry:\n print(sys.implementation.cache_tag)\nexcept AttributeError:\n import imp\n print(imp.get_tag())\n"]).strip() | |
412 | except Errors.WafError: | |
413 | pass | |
414 | def options(opt): | |
415 | pyopt=opt.add_option_group("Python Options") | |
416 | pyopt.add_option('--nopyc',dest='pyc',action='store_false',default=1,help='Do not install bytecode compiled .pyc files (configuration) [Default:install]') | |
417 | pyopt.add_option('--nopyo',dest='pyo',action='store_false',default=1,help='Do not install optimised compiled .pyo files (configuration) [Default:install]') | |
418 | pyopt.add_option('--nopycache',dest='nopycache',action='store_true',help='Do not use __pycache__ directory to install objects [Default:auto]') | |
419 | pyopt.add_option('--python',dest="python",help='python binary to be used [Default: %s]'%sys.executable) | |
420 | pyopt.add_option('--pythondir',dest='pythondir',help='Installation path for python modules (py, platform-independent .py and .pyc files)') | |
421 | pyopt.add_option('--pythonarchdir',dest='pythonarchdir',help='Installation path for python extension (pyext, platform-dependent .so or .dylib files)') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from __future__ import with_statement | |
5 | try: | |
6 | from xml.sax import make_parser | |
7 | from xml.sax.handler import ContentHandler | |
8 | except ImportError: | |
9 | has_xml=False | |
10 | ContentHandler=object | |
11 | else: | |
12 | has_xml=True | |
13 | import os,sys,re | |
14 | from waflib.Tools import cxx | |
15 | from waflib import Build,Task,Utils,Options,Errors,Context | |
16 | from waflib.TaskGen import feature,after_method,extension,before_method | |
17 | from waflib.Configure import conf | |
18 | from waflib import Logs | |
19 | MOC_H=['.h','.hpp','.hxx','.hh'] | |
20 | EXT_RCC=['.qrc'] | |
21 | EXT_UI=['.ui'] | |
22 | EXT_QT5=['.cpp','.cc','.cxx','.C'] | |
23 | class qxx(Task.classes['cxx']): | |
24 | def __init__(self,*k,**kw): | |
25 | Task.Task.__init__(self,*k,**kw) | |
26 | self.moc_done=0 | |
27 | def runnable_status(self): | |
28 | if self.moc_done: | |
29 | return Task.Task.runnable_status(self) | |
30 | else: | |
31 | for t in self.run_after: | |
32 | if not t.hasrun: | |
33 | return Task.ASK_LATER | |
34 | self.add_moc_tasks() | |
35 | return Task.Task.runnable_status(self) | |
36 | def create_moc_task(self,h_node,m_node): | |
37 | try: | |
38 | moc_cache=self.generator.bld.moc_cache | |
39 | except AttributeError: | |
40 | moc_cache=self.generator.bld.moc_cache={} | |
41 | try: | |
42 | return moc_cache[h_node] | |
43 | except KeyError: | |
44 | tsk=moc_cache[h_node]=Task.classes['moc'](env=self.env,generator=self.generator) | |
45 | tsk.set_inputs(h_node) | |
46 | tsk.set_outputs(m_node) | |
47 | tsk.env.append_unique('MOC_FLAGS','-i') | |
48 | if self.generator: | |
49 | self.generator.tasks.append(tsk) | |
50 | gen=self.generator.bld.producer | |
51 | gen.outstanding.append(tsk) | |
52 | gen.total+=1 | |
53 | return tsk | |
54 | else: | |
55 | delattr(self,'cache_sig') | |
56 | def add_moc_tasks(self): | |
57 | node=self.inputs[0] | |
58 | bld=self.generator.bld | |
59 | if bld.is_install==Build.UNINSTALL: | |
60 | return | |
61 | try: | |
62 | self.signature() | |
63 | except KeyError: | |
64 | pass | |
65 | else: | |
66 | delattr(self,'cache_sig') | |
67 | include_nodes=[node.parent]+self.generator.includes_nodes | |
68 | moctasks=[] | |
69 | mocfiles=set() | |
70 | for d in bld.raw_deps.get(self.uid(),[]): | |
71 | if not d.endswith('.moc'): | |
72 | continue | |
73 | if d in mocfiles: | |
74 | continue | |
75 | mocfiles.add(d) | |
76 | h_node=None | |
77 | base2=d[:-4] | |
78 | prefix=node.name[:node.name.rfind('.')] | |
79 | if base2==prefix: | |
80 | h_node=node | |
81 | else: | |
82 | for x in include_nodes: | |
83 | for e in MOC_H: | |
84 | h_node=x.find_node(base2+e) | |
85 | if h_node: | |
86 | break | |
87 | else: | |
88 | continue | |
89 | break | |
90 | if h_node: | |
91 | m_node=h_node.change_ext('.moc') | |
92 | else: | |
93 | raise Errors.WafError('No source found for %r which is a moc file'%d) | |
94 | task=self.create_moc_task(h_node,m_node) | |
95 | moctasks.append(task) | |
96 | self.run_after.update(set(moctasks)) | |
97 | self.moc_done=1 | |
98 | class trans_update(Task.Task): | |
99 | run_str='${QT_LUPDATE} ${SRC} -ts ${TGT}' | |
100 | color='BLUE' | |
101 | class XMLHandler(ContentHandler): | |
102 | def __init__(self): | |
103 | ContentHandler.__init__(self) | |
104 | self.buf=[] | |
105 | self.files=[] | |
106 | def startElement(self,name,attrs): | |
107 | if name=='file': | |
108 | self.buf=[] | |
109 | def endElement(self,name): | |
110 | if name=='file': | |
111 | self.files.append(str(''.join(self.buf))) | |
112 | def characters(self,cars): | |
113 | self.buf.append(cars) | |
114 | @extension(*EXT_RCC) | |
115 | def create_rcc_task(self,node): | |
116 | rcnode=node.change_ext('_rc.%d.cpp'%self.idx) | |
117 | self.create_task('rcc',node,rcnode) | |
118 | cpptask=self.create_task('cxx',rcnode,rcnode.change_ext('.o')) | |
119 | try: | |
120 | self.compiled_tasks.append(cpptask) | |
121 | except AttributeError: | |
122 | self.compiled_tasks=[cpptask] | |
123 | return cpptask | |
124 | @extension(*EXT_UI) | |
125 | def create_uic_task(self,node): | |
126 | try: | |
127 | uic_cache=self.bld.uic_cache | |
128 | except AttributeError: | |
129 | uic_cache=self.bld.uic_cache={} | |
130 | if node not in uic_cache: | |
131 | uictask=uic_cache[node]=self.create_task('ui5',node) | |
132 | uictask.outputs=[node.parent.find_or_declare(self.env.ui_PATTERN%node.name[:-3])] | |
133 | @extension('.ts') | |
134 | def add_lang(self,node): | |
135 | self.lang=self.to_list(getattr(self,'lang',[]))+[node] | |
136 | @feature('qt5') | |
137 | @before_method('process_source') | |
138 | def process_mocs(self): | |
139 | lst=self.to_nodes(getattr(self,'moc',[])) | |
140 | self.source=self.to_list(getattr(self,'source',[])) | |
141 | for x in lst: | |
142 | prefix=x.name[:x.name.rfind('.')] | |
143 | moc_target='moc_%s.%d.cpp'%(prefix,self.idx) | |
144 | moc_node=x.parent.find_or_declare(moc_target) | |
145 | self.source.append(moc_node) | |
146 | self.create_task('moc',x,moc_node) | |
147 | @feature('qt5') | |
148 | @after_method('apply_link') | |
149 | def apply_qt5(self): | |
150 | if getattr(self,'lang',None): | |
151 | qmtasks=[] | |
152 | for x in self.to_list(self.lang): | |
153 | if isinstance(x,str): | |
154 | x=self.path.find_resource(x+'.ts') | |
155 | qmtasks.append(self.create_task('ts2qm',x,x.change_ext('.%d.qm'%self.idx))) | |
156 | if getattr(self,'update',None)and Options.options.trans_qt5: | |
157 | cxxnodes=[a.inputs[0]for a in self.compiled_tasks]+[a.inputs[0]for a in self.tasks if a.inputs and a.inputs[0].name.endswith('.ui')] | |
158 | for x in qmtasks: | |
159 | self.create_task('trans_update',cxxnodes,x.inputs) | |
160 | if getattr(self,'langname',None): | |
161 | qmnodes=[x.outputs[0]for x in qmtasks] | |
162 | rcnode=self.langname | |
163 | if isinstance(rcnode,str): | |
164 | rcnode=self.path.find_or_declare(rcnode+('.%d.qrc'%self.idx)) | |
165 | t=self.create_task('qm2rcc',qmnodes,rcnode) | |
166 | k=create_rcc_task(self,t.outputs[0]) | |
167 | self.link_task.inputs.append(k.outputs[0]) | |
168 | lst=[] | |
169 | for flag in self.to_list(self.env.CXXFLAGS): | |
170 | if len(flag)<2: | |
171 | continue | |
172 | f=flag[0:2] | |
173 | if f in('-D','-I','/D','/I'): | |
174 | if(f[0]=='/'): | |
175 | lst.append('-'+flag[1:]) | |
176 | else: | |
177 | lst.append(flag) | |
178 | self.env.append_value('MOC_FLAGS',lst) | |
179 | @extension(*EXT_QT5) | |
180 | def cxx_hook(self,node): | |
181 | return self.create_compiled_task('qxx',node) | |
182 | class rcc(Task.Task): | |
183 | color='BLUE' | |
184 | run_str='${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' | |
185 | ext_out=['.h'] | |
186 | def rcname(self): | |
187 | return os.path.splitext(self.inputs[0].name)[0] | |
188 | def scan(self): | |
189 | if not has_xml: | |
190 | Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') | |
191 | return([],[]) | |
192 | parser=make_parser() | |
193 | curHandler=XMLHandler() | |
194 | parser.setContentHandler(curHandler) | |
195 | with open(self.inputs[0].abspath(),'r')as f: | |
196 | parser.parse(f) | |
197 | nodes=[] | |
198 | names=[] | |
199 | root=self.inputs[0].parent | |
200 | for x in curHandler.files: | |
201 | nd=root.find_resource(x) | |
202 | if nd: | |
203 | nodes.append(nd) | |
204 | else: | |
205 | names.append(x) | |
206 | return(nodes,names) | |
207 | def quote_flag(self,x): | |
208 | return x | |
209 | class moc(Task.Task): | |
210 | color='BLUE' | |
211 | run_str='${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' | |
212 | def quote_flag(self,x): | |
213 | return x | |
214 | class ui5(Task.Task): | |
215 | color='BLUE' | |
216 | run_str='${QT_UIC} ${SRC} -o ${TGT}' | |
217 | ext_out=['.h'] | |
218 | class ts2qm(Task.Task): | |
219 | color='BLUE' | |
220 | run_str='${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' | |
221 | class qm2rcc(Task.Task): | |
222 | color='BLUE' | |
223 | after='ts2qm' | |
224 | def run(self): | |
225 | txt='\n'.join(['<file>%s</file>'%k.path_from(self.outputs[0].parent)for k in self.inputs]) | |
226 | code='<!DOCTYPE RCC><RCC version="1.0">\n<qresource>\n%s\n</qresource>\n</RCC>'%txt | |
227 | self.outputs[0].write(code) | |
228 | def configure(self): | |
229 | self.find_qt5_binaries() | |
230 | self.set_qt5_libs_dir() | |
231 | self.set_qt5_libs_to_check() | |
232 | self.set_qt5_defines() | |
233 | self.find_qt5_libraries() | |
234 | self.add_qt5_rpath() | |
235 | self.simplify_qt5_libs() | |
236 | if not has_xml: | |
237 | Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') | |
238 | if'COMPILER_CXX'not in self.env: | |
239 | self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') | |
240 | frag='#include <QMap>\nint main(int argc, char **argv) {QMap<int,int> m;return m.keys().size();}\n' | |
241 | uses='QT5CORE' | |
242 | for flag in[[],'-fPIE','-fPIC','-std=c++11',['-std=c++11','-fPIE'],['-std=c++11','-fPIC']]: | |
243 | msg='See if Qt files compile ' | |
244 | if flag: | |
245 | msg+='with %s'%flag | |
246 | try: | |
247 | self.check(features='qt5 cxx',use=uses,uselib_store='qt5',cxxflags=flag,fragment=frag,msg=msg) | |
248 | except self.errors.ConfigurationError: | |
249 | pass | |
250 | else: | |
251 | break | |
252 | else: | |
253 | self.fatal('Could not build a simple Qt application') | |
254 | if Utils.unversioned_sys_platform()=='freebsd': | |
255 | frag='#include <QMap>\nint main(int argc, char **argv) {QMap<int,int> m;return m.keys().size();}\n' | |
256 | try: | |
257 | self.check(features='qt5 cxx cxxprogram',use=uses,fragment=frag,msg='Can we link Qt programs on FreeBSD directly?') | |
258 | except self.errors.ConfigurationError: | |
259 | self.check(features='qt5 cxx cxxprogram',use=uses,uselib_store='qt5',libpath='/usr/local/lib',fragment=frag,msg='Is /usr/local/lib required?') | |
260 | @conf | |
261 | def find_qt5_binaries(self): | |
262 | env=self.env | |
263 | opt=Options.options | |
264 | qtdir=getattr(opt,'qtdir','') | |
265 | qtbin=getattr(opt,'qtbin','') | |
266 | paths=[] | |
267 | if qtdir: | |
268 | qtbin=os.path.join(qtdir,'bin') | |
269 | if not qtdir: | |
270 | qtdir=self.environ.get('QT5_ROOT','') | |
271 | qtbin=self.environ.get('QT5_BIN')or os.path.join(qtdir,'bin') | |
272 | if qtbin: | |
273 | paths=[qtbin] | |
274 | if not qtdir: | |
275 | paths=self.environ.get('PATH','').split(os.pathsep) | |
276 | paths.extend(['/usr/share/qt5/bin','/usr/local/lib/qt5/bin']) | |
277 | try: | |
278 | lst=Utils.listdir('/usr/local/Trolltech/') | |
279 | except OSError: | |
280 | pass | |
281 | else: | |
282 | if lst: | |
283 | lst.sort() | |
284 | lst.reverse() | |
285 | qtdir='/usr/local/Trolltech/%s/'%lst[0] | |
286 | qtbin=os.path.join(qtdir,'bin') | |
287 | paths.append(qtbin) | |
288 | cand=None | |
289 | prev_ver=['5','0','0'] | |
290 | for qmk in('qmake-qt5','qmake5','qmake'): | |
291 | try: | |
292 | qmake=self.find_program(qmk,path_list=paths) | |
293 | except self.errors.ConfigurationError: | |
294 | pass | |
295 | else: | |
296 | try: | |
297 | version=self.cmd_and_log(qmake+['-query','QT_VERSION']).strip() | |
298 | except self.errors.WafError: | |
299 | pass | |
300 | else: | |
301 | if version: | |
302 | new_ver=version.split('.') | |
303 | if new_ver>prev_ver: | |
304 | cand=qmake | |
305 | prev_ver=new_ver | |
306 | if not cand: | |
307 | try: | |
308 | self.find_program('qtchooser') | |
309 | except self.errors.ConfigurationError: | |
310 | pass | |
311 | else: | |
312 | cmd=self.env.QTCHOOSER+['-qt=5','-run-tool=qmake'] | |
313 | try: | |
314 | version=self.cmd_and_log(cmd+['-query','QT_VERSION']) | |
315 | except self.errors.WafError: | |
316 | pass | |
317 | else: | |
318 | cand=cmd | |
319 | if cand: | |
320 | self.env.QMAKE=cand | |
321 | else: | |
322 | self.fatal('Could not find qmake for qt5') | |
323 | self.env.QT_HOST_BINS=qtbin=self.cmd_and_log(self.env.QMAKE+['-query','QT_HOST_BINS']).strip() | |
324 | paths.insert(0,qtbin) | |
325 | def find_bin(lst,var): | |
326 | if var in env: | |
327 | return | |
328 | for f in lst: | |
329 | try: | |
330 | ret=self.find_program(f,path_list=paths) | |
331 | except self.errors.ConfigurationError: | |
332 | pass | |
333 | else: | |
334 | env[var]=ret | |
335 | break | |
336 | find_bin(['uic-qt5','uic'],'QT_UIC') | |
337 | if not env.QT_UIC: | |
338 | self.fatal('cannot find the uic compiler for qt5') | |
339 | self.start_msg('Checking for uic version') | |
340 | uicver=self.cmd_and_log(env.QT_UIC+['-version'],output=Context.BOTH) | |
341 | uicver=''.join(uicver).strip() | |
342 | uicver=uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt','') | |
343 | self.end_msg(uicver) | |
344 | if uicver.find(' 3.')!=-1 or uicver.find(' 4.')!=-1: | |
345 | self.fatal('this uic compiler is for qt3 or qt4, add uic for qt5 to your path') | |
346 | find_bin(['moc-qt5','moc'],'QT_MOC') | |
347 | find_bin(['rcc-qt5','rcc'],'QT_RCC') | |
348 | find_bin(['lrelease-qt5','lrelease'],'QT_LRELEASE') | |
349 | find_bin(['lupdate-qt5','lupdate'],'QT_LUPDATE') | |
350 | env.UIC_ST='%s -o %s' | |
351 | env.MOC_ST='-o' | |
352 | env.ui_PATTERN='ui_%s.h' | |
353 | env.QT_LRELEASE_FLAGS=['-silent'] | |
354 | env.MOCCPPPATH_ST='-I%s' | |
355 | env.MOCDEFINES_ST='-D%s' | |
356 | @conf | |
357 | def set_qt5_libs_dir(self): | |
358 | env=self.env | |
359 | qtlibs=getattr(Options.options,'qtlibs',None)or self.environ.get('QT5_LIBDIR') | |
360 | if not qtlibs: | |
361 | try: | |
362 | qtlibs=self.cmd_and_log(env.QMAKE+['-query','QT_INSTALL_LIBS']).strip() | |
363 | except Errors.WafError: | |
364 | qtdir=self.cmd_and_log(env.QMAKE+['-query','QT_INSTALL_PREFIX']).strip() | |
365 | qtlibs=os.path.join(qtdir,'lib') | |
366 | self.msg('Found the Qt5 libraries in',qtlibs) | |
367 | env.QTLIBS=qtlibs | |
368 | @conf | |
369 | def find_single_qt5_lib(self,name,uselib,qtlibs,qtincludes,force_static): | |
370 | env=self.env | |
371 | if force_static: | |
372 | exts=('.a','.lib') | |
373 | prefix='STLIB' | |
374 | else: | |
375 | exts=('.so','.lib') | |
376 | prefix='LIB' | |
377 | def lib_names(): | |
378 | for x in exts: | |
379 | for k in('','5')if Utils.is_win32 else['']: | |
380 | for p in('lib',''): | |
381 | yield(p,name,k,x) | |
382 | for tup in lib_names(): | |
383 | k=''.join(tup) | |
384 | path=os.path.join(qtlibs,k) | |
385 | if os.path.exists(path): | |
386 | if env.DEST_OS=='win32': | |
387 | libval=''.join(tup[:-1]) | |
388 | else: | |
389 | libval=name | |
390 | env.append_unique(prefix+'_'+uselib,libval) | |
391 | env.append_unique('%sPATH_%s'%(prefix,uselib),qtlibs) | |
392 | env.append_unique('INCLUDES_'+uselib,qtincludes) | |
393 | env.append_unique('INCLUDES_'+uselib,os.path.join(qtincludes,name.replace('Qt5','Qt'))) | |
394 | return k | |
395 | return False | |
396 | @conf | |
397 | def find_qt5_libraries(self): | |
398 | env=self.env | |
399 | qtincludes=self.environ.get('QT5_INCLUDES')or self.cmd_and_log(env.QMAKE+['-query','QT_INSTALL_HEADERS']).strip() | |
400 | force_static=self.environ.get('QT5_FORCE_STATIC') | |
401 | try: | |
402 | if self.environ.get('QT5_XCOMPILE'): | |
403 | self.fatal('QT5_XCOMPILE Disables pkg-config detection') | |
404 | self.check_cfg(atleast_pkgconfig_version='0.1') | |
405 | except self.errors.ConfigurationError: | |
406 | for i in self.qt5_vars: | |
407 | uselib=i.upper() | |
408 | if Utils.unversioned_sys_platform()=='darwin': | |
409 | fwk=i.replace('Qt5','Qt') | |
410 | frameworkName=fwk+'.framework' | |
411 | qtDynamicLib=os.path.join(env.QTLIBS,frameworkName,fwk) | |
412 | if os.path.exists(qtDynamicLib): | |
413 | env.append_unique('FRAMEWORK_'+uselib,fwk) | |
414 | env.append_unique('FRAMEWORKPATH_'+uselib,env.QTLIBS) | |
415 | self.msg('Checking for %s'%i,qtDynamicLib,'GREEN') | |
416 | else: | |
417 | self.msg('Checking for %s'%i,False,'YELLOW') | |
418 | env.append_unique('INCLUDES_'+uselib,os.path.join(env.QTLIBS,frameworkName,'Headers')) | |
419 | else: | |
420 | ret=self.find_single_qt5_lib(i,uselib,env.QTLIBS,qtincludes,force_static) | |
421 | if not force_static and not ret: | |
422 | ret=self.find_single_qt5_lib(i,uselib,env.QTLIBS,qtincludes,True) | |
423 | self.msg('Checking for %s'%i,ret,'GREEN'if ret else'YELLOW') | |
424 | else: | |
425 | path='%s:%s:%s/pkgconfig:/usr/lib/qt5/lib/pkgconfig:/opt/qt5/lib/pkgconfig:/usr/lib/qt5/lib:/opt/qt5/lib'%(self.environ.get('PKG_CONFIG_PATH',''),env.QTLIBS,env.QTLIBS) | |
426 | for i in self.qt5_vars: | |
427 | self.check_cfg(package=i,args='--cflags --libs',mandatory=False,force_static=force_static,pkg_config_path=path) | |
428 | @conf | |
429 | def simplify_qt5_libs(self): | |
430 | env=self.env | |
431 | def process_lib(vars_,coreval): | |
432 | for d in vars_: | |
433 | var=d.upper() | |
434 | if var=='QTCORE': | |
435 | continue | |
436 | value=env['LIBPATH_'+var] | |
437 | if value: | |
438 | core=env[coreval] | |
439 | accu=[] | |
440 | for lib in value: | |
441 | if lib in core: | |
442 | continue | |
443 | accu.append(lib) | |
444 | env['LIBPATH_'+var]=accu | |
445 | process_lib(self.qt5_vars,'LIBPATH_QTCORE') | |
446 | @conf | |
447 | def add_qt5_rpath(self): | |
448 | env=self.env | |
449 | if getattr(Options.options,'want_rpath',False): | |
450 | def process_rpath(vars_,coreval): | |
451 | for d in vars_: | |
452 | var=d.upper() | |
453 | value=env['LIBPATH_'+var] | |
454 | if value: | |
455 | core=env[coreval] | |
456 | accu=[] | |
457 | for lib in value: | |
458 | if var!='QTCORE': | |
459 | if lib in core: | |
460 | continue | |
461 | accu.append('-Wl,--rpath='+lib) | |
462 | env['RPATH_'+var]=accu | |
463 | process_rpath(self.qt5_vars,'LIBPATH_QTCORE') | |
464 | @conf | |
465 | def set_qt5_libs_to_check(self): | |
466 | self.qt5_vars=Utils.to_list(getattr(self,'qt5_vars',[])) | |
467 | if not self.qt5_vars: | |
468 | dirlst=Utils.listdir(self.env.QTLIBS) | |
469 | pat=self.env.cxxshlib_PATTERN | |
470 | if Utils.is_win32: | |
471 | pat=pat.replace('.dll','.lib') | |
472 | if self.environ.get('QT5_FORCE_STATIC'): | |
473 | pat=self.env.cxxstlib_PATTERN | |
474 | if Utils.unversioned_sys_platform()=='darwin': | |
475 | pat=r"%s\.framework" | |
476 | re_qt=re.compile(pat%'Qt5?(?P<name>.*)'+'$') | |
477 | for x in dirlst: | |
478 | m=re_qt.match(x) | |
479 | if m: | |
480 | self.qt5_vars.append("Qt5%s"%m.group('name')) | |
481 | if not self.qt5_vars: | |
482 | self.fatal('cannot find any Qt5 library (%r)'%self.env.QTLIBS) | |
483 | qtextralibs=getattr(Options.options,'qtextralibs',None) | |
484 | if qtextralibs: | |
485 | self.qt5_vars.extend(qtextralibs.split(',')) | |
486 | @conf | |
487 | def set_qt5_defines(self): | |
488 | if sys.platform!='win32': | |
489 | return | |
490 | for x in self.qt5_vars: | |
491 | y=x.replace('Qt5','Qt')[2:].upper() | |
492 | self.env.append_unique('DEFINES_%s'%x.upper(),'QT_%s_LIB'%y) | |
493 | def options(opt): | |
494 | opt.add_option('--want-rpath',action='store_true',default=False,dest='want_rpath',help='enable the rpath for qt libraries') | |
495 | for i in'qtdir qtbin qtlibs'.split(): | |
496 | opt.add_option('--'+i,type='string',default='',dest=i) | |
497 | opt.add_option('--translate',action='store_true',help='collect translation strings',dest='trans_qt5',default=False) | |
498 | opt.add_option('--qtextralibs',type='string',default='',dest='qtextralibs',help='additional qt libraries on the system to add to default ones, comma separated') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os | |
5 | from waflib import Errors,Options,Task,Utils | |
6 | from waflib.TaskGen import before_method,feature,extension | |
7 | from waflib.Configure import conf | |
8 | @feature('rubyext') | |
9 | @before_method('apply_incpaths','process_source','apply_bundle','apply_link') | |
10 | def init_rubyext(self): | |
11 | self.install_path='${ARCHDIR_RUBY}' | |
12 | self.uselib=self.to_list(getattr(self,'uselib','')) | |
13 | if not'RUBY'in self.uselib: | |
14 | self.uselib.append('RUBY') | |
15 | if not'RUBYEXT'in self.uselib: | |
16 | self.uselib.append('RUBYEXT') | |
17 | @feature('rubyext') | |
18 | @before_method('apply_link','propagate_uselib_vars') | |
19 | def apply_ruby_so_name(self): | |
20 | self.env.cshlib_PATTERN=self.env.cxxshlib_PATTERN=self.env.rubyext_PATTERN | |
21 | @conf | |
22 | def check_ruby_version(self,minver=()): | |
23 | ruby=self.find_program('ruby',var='RUBY',value=Options.options.rubybinary) | |
24 | try: | |
25 | version=self.cmd_and_log(ruby+['-e','puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() | |
26 | except Errors.WafError: | |
27 | self.fatal('could not determine ruby version') | |
28 | self.env.RUBY_VERSION=version | |
29 | try: | |
30 | ver=tuple(map(int,version.split('.'))) | |
31 | except Errors.WafError: | |
32 | self.fatal('unsupported ruby version %r'%version) | |
33 | cver='' | |
34 | if minver: | |
35 | cver='> '+'.'.join(str(x)for x in minver) | |
36 | if ver<minver: | |
37 | self.fatal('ruby is too old %r'%ver) | |
38 | self.msg('Checking for ruby version %s'%cver,version) | |
39 | @conf | |
40 | def check_ruby_ext_devel(self): | |
41 | if not self.env.RUBY: | |
42 | self.fatal('ruby detection is required first') | |
43 | if not self.env.CC_NAME and not self.env.CXX_NAME: | |
44 | self.fatal('load a c/c++ compiler first') | |
45 | version=tuple(map(int,self.env.RUBY_VERSION.split("."))) | |
46 | def read_out(cmd): | |
47 | return Utils.to_list(self.cmd_and_log(self.env.RUBY+['-rrbconfig','-e',cmd])) | |
48 | def read_config(key): | |
49 | return read_out('puts RbConfig::CONFIG[%r]'%key) | |
50 | cpppath=archdir=read_config('archdir') | |
51 | if version>=(1,9,0): | |
52 | ruby_hdrdir=read_config('rubyhdrdir') | |
53 | cpppath+=ruby_hdrdir | |
54 | if version>=(2,0,0): | |
55 | cpppath+=read_config('rubyarchhdrdir') | |
56 | cpppath+=[os.path.join(ruby_hdrdir[0],read_config('arch')[0])] | |
57 | self.check(header_name='ruby.h',includes=cpppath,errmsg='could not find ruby header file',link_header_test=False) | |
58 | self.env.LIBPATH_RUBYEXT=read_config('libdir') | |
59 | self.env.LIBPATH_RUBYEXT+=archdir | |
60 | self.env.INCLUDES_RUBYEXT=cpppath | |
61 | self.env.CFLAGS_RUBYEXT=read_config('CCDLFLAGS') | |
62 | self.env.rubyext_PATTERN='%s.'+read_config('DLEXT')[0] | |
63 | flags=read_config('LDSHARED') | |
64 | while flags and flags[0][0]!='-': | |
65 | flags=flags[1:] | |
66 | if len(flags)>1 and flags[1]=="ppc": | |
67 | flags=flags[2:] | |
68 | self.env.LINKFLAGS_RUBYEXT=flags | |
69 | self.env.LINKFLAGS_RUBYEXT+=read_config('LIBS') | |
70 | self.env.LINKFLAGS_RUBYEXT+=read_config('LIBRUBYARG_SHARED') | |
71 | if Options.options.rubyarchdir: | |
72 | self.env.ARCHDIR_RUBY=Options.options.rubyarchdir | |
73 | else: | |
74 | self.env.ARCHDIR_RUBY=read_config('sitearchdir')[0] | |
75 | if Options.options.rubylibdir: | |
76 | self.env.LIBDIR_RUBY=Options.options.rubylibdir | |
77 | else: | |
78 | self.env.LIBDIR_RUBY=read_config('sitelibdir')[0] | |
79 | @conf | |
80 | def check_ruby_module(self,module_name): | |
81 | self.start_msg('Ruby module %s'%module_name) | |
82 | try: | |
83 | self.cmd_and_log(self.env.RUBY+['-e','require \'%s\';puts 1'%module_name]) | |
84 | except Errors.WafError: | |
85 | self.end_msg(False) | |
86 | self.fatal('Could not find the ruby module %r'%module_name) | |
87 | self.end_msg(True) | |
88 | @extension('.rb') | |
89 | def process(self,node): | |
90 | return self.create_task('run_ruby',node) | |
91 | class run_ruby(Task.Task): | |
92 | run_str='${RUBY} ${RBFLAGS} -I ${SRC[0].parent.abspath()} ${SRC}' | |
93 | def options(opt): | |
94 | opt.add_option('--with-ruby-archdir',type='string',dest='rubyarchdir',help='Specify directory where to install arch specific files') | |
95 | opt.add_option('--with-ruby-libdir',type='string',dest='rubylibdir',help='Specify alternate ruby library path') | |
96 | opt.add_option('--with-ruby-binary',type='string',dest='rubybinary',help='Specify alternate ruby binary') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Errors | |
5 | from waflib.Tools import ccroot,ar | |
6 | from waflib.Configure import conf | |
7 | @conf | |
8 | def find_scc(conf): | |
9 | v=conf.env | |
10 | cc=conf.find_program('cc',var='CC') | |
11 | try: | |
12 | conf.cmd_and_log(cc+['-flags']) | |
13 | except Errors.WafError: | |
14 | conf.fatal('%r is not a Sun compiler'%cc) | |
15 | v.CC_NAME='sun' | |
16 | conf.get_suncc_version(cc) | |
17 | @conf | |
18 | def scc_common_flags(conf): | |
19 | v=conf.env | |
20 | v.CC_SRC_F=[] | |
21 | v.CC_TGT_F=['-c','-o',''] | |
22 | if not v.LINK_CC: | |
23 | v.LINK_CC=v.CC | |
24 | v.CCLNK_SRC_F='' | |
25 | v.CCLNK_TGT_F=['-o',''] | |
26 | v.CPPPATH_ST='-I%s' | |
27 | v.DEFINES_ST='-D%s' | |
28 | v.LIB_ST='-l%s' | |
29 | v.LIBPATH_ST='-L%s' | |
30 | v.STLIB_ST='-l%s' | |
31 | v.STLIBPATH_ST='-L%s' | |
32 | v.SONAME_ST='-Wl,-h,%s' | |
33 | v.SHLIB_MARKER='-Bdynamic' | |
34 | v.STLIB_MARKER='-Bstatic' | |
35 | v.cprogram_PATTERN='%s' | |
36 | v.CFLAGS_cshlib=['-xcode=pic32','-DPIC'] | |
37 | v.LINKFLAGS_cshlib=['-G'] | |
38 | v.cshlib_PATTERN='lib%s.so' | |
39 | v.LINKFLAGS_cstlib=['-Bstatic'] | |
40 | v.cstlib_PATTERN='lib%s.a' | |
41 | def configure(conf): | |
42 | conf.find_scc() | |
43 | conf.find_ar() | |
44 | conf.scc_common_flags() | |
45 | conf.cc_load_tools() | |
46 | conf.cc_add_flags() | |
47 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib import Errors | |
5 | from waflib.Tools import ccroot,ar | |
6 | from waflib.Configure import conf | |
7 | @conf | |
8 | def find_sxx(conf): | |
9 | v=conf.env | |
10 | cc=conf.find_program(['CC','c++'],var='CXX') | |
11 | try: | |
12 | conf.cmd_and_log(cc+['-flags']) | |
13 | except Errors.WafError: | |
14 | conf.fatal('%r is not a Sun compiler'%cc) | |
15 | v.CXX_NAME='sun' | |
16 | conf.get_suncc_version(cc) | |
17 | @conf | |
18 | def sxx_common_flags(conf): | |
19 | v=conf.env | |
20 | v.CXX_SRC_F=[] | |
21 | v.CXX_TGT_F=['-c','-o',''] | |
22 | if not v.LINK_CXX: | |
23 | v.LINK_CXX=v.CXX | |
24 | v.CXXLNK_SRC_F=[] | |
25 | v.CXXLNK_TGT_F=['-o',''] | |
26 | v.CPPPATH_ST='-I%s' | |
27 | v.DEFINES_ST='-D%s' | |
28 | v.LIB_ST='-l%s' | |
29 | v.LIBPATH_ST='-L%s' | |
30 | v.STLIB_ST='-l%s' | |
31 | v.STLIBPATH_ST='-L%s' | |
32 | v.SONAME_ST='-Wl,-h,%s' | |
33 | v.SHLIB_MARKER='-Bdynamic' | |
34 | v.STLIB_MARKER='-Bstatic' | |
35 | v.cxxprogram_PATTERN='%s' | |
36 | v.CXXFLAGS_cxxshlib=['-xcode=pic32','-DPIC'] | |
37 | v.LINKFLAGS_cxxshlib=['-G'] | |
38 | v.cxxshlib_PATTERN='lib%s.so' | |
39 | v.LINKFLAGS_cxxstlib=['-Bstatic'] | |
40 | v.cxxstlib_PATTERN='lib%s.a' | |
41 | def configure(conf): | |
42 | conf.find_sxx() | |
43 | conf.find_ar() | |
44 | conf.sxx_common_flags() | |
45 | conf.cxx_load_tools() | |
46 | conf.cxx_add_flags() | |
47 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re | |
5 | from waflib import Utils,Task,Errors,Logs,Node | |
6 | from waflib.TaskGen import feature,before_method | |
7 | re_bibunit=re.compile(r'\\(?P<type>putbib)\[(?P<file>[^\[\]]*)\]',re.M) | |
8 | def bibunitscan(self): | |
9 | node=self.inputs[0] | |
10 | nodes=[] | |
11 | if not node: | |
12 | return nodes | |
13 | code=node.read() | |
14 | for match in re_bibunit.finditer(code): | |
15 | path=match.group('file') | |
16 | if path: | |
17 | found=None | |
18 | for k in('','.bib'): | |
19 | Logs.debug('tex: trying %s%s',path,k) | |
20 | fi=node.parent.find_resource(path+k) | |
21 | if fi: | |
22 | found=True | |
23 | nodes.append(fi) | |
24 | if not found: | |
25 | Logs.debug('tex: could not find %s',path) | |
26 | Logs.debug('tex: found the following bibunit files: %s',nodes) | |
27 | return nodes | |
28 | exts_deps_tex=['','.ltx','.tex','.bib','.pdf','.png','.eps','.ps','.sty'] | |
29 | exts_tex=['.ltx','.tex'] | |
30 | re_tex=re.compile(r'\\(?P<type>usepackage|RequirePackage|include|bibliography([^\[\]{}]*)|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P<file>[^{}]*)}',re.M) | |
31 | g_bibtex_re=re.compile('bibdata',re.M) | |
32 | g_glossaries_re=re.compile('\\@newglossary',re.M) | |
33 | class tex(Task.Task): | |
34 | bibtex_fun,_=Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}',shell=False) | |
35 | bibtex_fun.__doc__=""" | |
36 | Execute the program **bibtex** | |
37 | """ | |
38 | makeindex_fun,_=Task.compile_fun('${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}',shell=False) | |
39 | makeindex_fun.__doc__=""" | |
40 | Execute the program **makeindex** | |
41 | """ | |
42 | makeglossaries_fun,_=Task.compile_fun('${MAKEGLOSSARIES} ${SRCFILE}',shell=False) | |
43 | makeglossaries_fun.__doc__=""" | |
44 | Execute the program **makeglossaries** | |
45 | """ | |
46 | def exec_command(self,cmd,**kw): | |
47 | if self.env.PROMPT_LATEX: | |
48 | kw['stdout']=kw['stderr']=None | |
49 | return super(tex,self).exec_command(cmd,**kw) | |
50 | def scan_aux(self,node): | |
51 | nodes=[node] | |
52 | re_aux=re.compile(r'\\@input{(?P<file>[^{}]*)}',re.M) | |
53 | def parse_node(node): | |
54 | code=node.read() | |
55 | for match in re_aux.finditer(code): | |
56 | path=match.group('file') | |
57 | found=node.parent.find_or_declare(path) | |
58 | if found and found not in nodes: | |
59 | Logs.debug('tex: found aux node %r',found) | |
60 | nodes.append(found) | |
61 | parse_node(found) | |
62 | parse_node(node) | |
63 | return nodes | |
64 | def scan(self): | |
65 | node=self.inputs[0] | |
66 | nodes=[] | |
67 | names=[] | |
68 | seen=[] | |
69 | if not node: | |
70 | return(nodes,names) | |
71 | def parse_node(node): | |
72 | if node in seen: | |
73 | return | |
74 | seen.append(node) | |
75 | code=node.read() | |
76 | for match in re_tex.finditer(code): | |
77 | multibib=match.group('type') | |
78 | if multibib and multibib.startswith('bibliography'): | |
79 | multibib=multibib[len('bibliography'):] | |
80 | if multibib.startswith('style'): | |
81 | continue | |
82 | else: | |
83 | multibib=None | |
84 | for path in match.group('file').split(','): | |
85 | if path: | |
86 | add_name=True | |
87 | found=None | |
88 | for k in exts_deps_tex: | |
89 | for up in self.texinputs_nodes: | |
90 | Logs.debug('tex: trying %s%s',path,k) | |
91 | found=up.find_resource(path+k) | |
92 | if found: | |
93 | break | |
94 | for tsk in self.generator.tasks: | |
95 | if not found or found in tsk.outputs: | |
96 | break | |
97 | else: | |
98 | nodes.append(found) | |
99 | add_name=False | |
100 | for ext in exts_tex: | |
101 | if found.name.endswith(ext): | |
102 | parse_node(found) | |
103 | break | |
104 | if found and multibib and found.name.endswith('.bib'): | |
105 | try: | |
106 | self.multibibs.append(found) | |
107 | except AttributeError: | |
108 | self.multibibs=[found] | |
109 | if add_name: | |
110 | names.append(path) | |
111 | parse_node(node) | |
112 | for x in nodes: | |
113 | x.parent.get_bld().mkdir() | |
114 | Logs.debug("tex: found the following : %s and names %s",nodes,names) | |
115 | return(nodes,names) | |
116 | def check_status(self,msg,retcode): | |
117 | if retcode!=0: | |
118 | raise Errors.WafError('%r command exit status %r'%(msg,retcode)) | |
119 | def info(self,*k,**kw): | |
120 | try: | |
121 | info=self.generator.bld.conf.logger.info | |
122 | except AttributeError: | |
123 | info=Logs.info | |
124 | info(*k,**kw) | |
125 | def bibfile(self): | |
126 | for aux_node in self.aux_nodes: | |
127 | try: | |
128 | ct=aux_node.read() | |
129 | except EnvironmentError: | |
130 | Logs.error('Error reading %s: %r',aux_node.abspath()) | |
131 | continue | |
132 | if g_bibtex_re.findall(ct): | |
133 | self.info('calling bibtex') | |
134 | self.env.env={} | |
135 | self.env.env.update(os.environ) | |
136 | self.env.env.update({'BIBINPUTS':self.texinputs(),'BSTINPUTS':self.texinputs()}) | |
137 | self.env.SRCFILE=aux_node.name[:-4] | |
138 | self.check_status('error when calling bibtex',self.bibtex_fun()) | |
139 | for node in getattr(self,'multibibs',[]): | |
140 | self.env.env={} | |
141 | self.env.env.update(os.environ) | |
142 | self.env.env.update({'BIBINPUTS':self.texinputs(),'BSTINPUTS':self.texinputs()}) | |
143 | self.env.SRCFILE=node.name[:-4] | |
144 | self.check_status('error when calling bibtex',self.bibtex_fun()) | |
145 | def bibunits(self): | |
146 | try: | |
147 | bibunits=bibunitscan(self) | |
148 | except OSError: | |
149 | Logs.error('error bibunitscan') | |
150 | else: | |
151 | if bibunits: | |
152 | fn=['bu'+str(i)for i in range(1,len(bibunits)+1)] | |
153 | if fn: | |
154 | self.info('calling bibtex on bibunits') | |
155 | for f in fn: | |
156 | self.env.env={'BIBINPUTS':self.texinputs(),'BSTINPUTS':self.texinputs()} | |
157 | self.env.SRCFILE=f | |
158 | self.check_status('error when calling bibtex',self.bibtex_fun()) | |
159 | def makeindex(self): | |
160 | self.idx_node=self.inputs[0].change_ext('.idx') | |
161 | try: | |
162 | idx_path=self.idx_node.abspath() | |
163 | os.stat(idx_path) | |
164 | except OSError: | |
165 | self.info('index file %s absent, not calling makeindex',idx_path) | |
166 | else: | |
167 | self.info('calling makeindex') | |
168 | self.env.SRCFILE=self.idx_node.name | |
169 | self.env.env={} | |
170 | self.check_status('error when calling makeindex %s'%idx_path,self.makeindex_fun()) | |
171 | def bibtopic(self): | |
172 | p=self.inputs[0].parent.get_bld() | |
173 | if os.path.exists(os.path.join(p.abspath(),'btaux.aux')): | |
174 | self.aux_nodes+=p.ant_glob('*[0-9].aux') | |
175 | def makeglossaries(self): | |
176 | src_file=self.inputs[0].abspath() | |
177 | base_file=os.path.basename(src_file) | |
178 | base,_=os.path.splitext(base_file) | |
179 | for aux_node in self.aux_nodes: | |
180 | try: | |
181 | ct=aux_node.read() | |
182 | except EnvironmentError: | |
183 | Logs.error('Error reading %s: %r',aux_node.abspath()) | |
184 | continue | |
185 | if g_glossaries_re.findall(ct): | |
186 | if not self.env.MAKEGLOSSARIES: | |
187 | raise Errors.WafError("The program 'makeglossaries' is missing!") | |
188 | Logs.warn('calling makeglossaries') | |
189 | self.env.SRCFILE=base | |
190 | self.check_status('error when calling makeglossaries %s'%base,self.makeglossaries_fun()) | |
191 | return | |
192 | def texinputs(self): | |
193 | return os.pathsep.join([k.abspath()for k in self.texinputs_nodes])+os.pathsep | |
194 | def run(self): | |
195 | env=self.env | |
196 | if not env.PROMPT_LATEX: | |
197 | env.append_value('LATEXFLAGS','-interaction=batchmode') | |
198 | env.append_value('PDFLATEXFLAGS','-interaction=batchmode') | |
199 | env.append_value('XELATEXFLAGS','-interaction=batchmode') | |
200 | self.cwd=self.inputs[0].parent.get_bld() | |
201 | self.info('first pass on %s',self.__class__.__name__) | |
202 | cur_hash=self.hash_aux_nodes() | |
203 | self.call_latex() | |
204 | self.hash_aux_nodes() | |
205 | self.bibtopic() | |
206 | self.bibfile() | |
207 | self.bibunits() | |
208 | self.makeindex() | |
209 | self.makeglossaries() | |
210 | for i in range(10): | |
211 | prev_hash=cur_hash | |
212 | cur_hash=self.hash_aux_nodes() | |
213 | if not cur_hash: | |
214 | Logs.error('No aux.h to process') | |
215 | if cur_hash and cur_hash==prev_hash: | |
216 | break | |
217 | self.info('calling %s',self.__class__.__name__) | |
218 | self.call_latex() | |
219 | def hash_aux_nodes(self): | |
220 | try: | |
221 | self.aux_nodes | |
222 | except AttributeError: | |
223 | try: | |
224 | self.aux_nodes=self.scan_aux(self.inputs[0].change_ext('.aux')) | |
225 | except IOError: | |
226 | return None | |
227 | return Utils.h_list([Utils.h_file(x.abspath())for x in self.aux_nodes]) | |
228 | def call_latex(self): | |
229 | self.env.env={} | |
230 | self.env.env.update(os.environ) | |
231 | self.env.env.update({'TEXINPUTS':self.texinputs()}) | |
232 | self.env.SRCFILE=self.inputs[0].abspath() | |
233 | self.check_status('error when calling latex',self.texfun()) | |
234 | class latex(tex): | |
235 | texfun,vars=Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}',shell=False) | |
236 | class pdflatex(tex): | |
237 | texfun,vars=Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}',shell=False) | |
238 | class xelatex(tex): | |
239 | texfun,vars=Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}',shell=False) | |
240 | class dvips(Task.Task): | |
241 | run_str='${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}' | |
242 | color='BLUE' | |
243 | after=['latex','pdflatex','xelatex'] | |
244 | class dvipdf(Task.Task): | |
245 | run_str='${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}' | |
246 | color='BLUE' | |
247 | after=['latex','pdflatex','xelatex'] | |
248 | class pdf2ps(Task.Task): | |
249 | run_str='${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}' | |
250 | color='BLUE' | |
251 | after=['latex','pdflatex','xelatex'] | |
252 | @feature('tex') | |
253 | @before_method('process_source') | |
254 | def apply_tex(self): | |
255 | if not getattr(self,'type',None)in('latex','pdflatex','xelatex'): | |
256 | self.type='pdflatex' | |
257 | outs=Utils.to_list(getattr(self,'outs',[])) | |
258 | try: | |
259 | self.generator.bld.conf | |
260 | except AttributeError: | |
261 | default_prompt=False | |
262 | else: | |
263 | default_prompt=True | |
264 | self.env.PROMPT_LATEX=getattr(self,'prompt',default_prompt) | |
265 | deps_lst=[] | |
266 | if getattr(self,'deps',None): | |
267 | deps=self.to_list(self.deps) | |
268 | for dep in deps: | |
269 | if isinstance(dep,str): | |
270 | n=self.path.find_resource(dep) | |
271 | if not n: | |
272 | self.bld.fatal('Could not find %r for %r'%(dep,self)) | |
273 | if not n in deps_lst: | |
274 | deps_lst.append(n) | |
275 | elif isinstance(dep,Node.Node): | |
276 | deps_lst.append(dep) | |
277 | for node in self.to_nodes(self.source): | |
278 | if self.type=='latex': | |
279 | task=self.create_task('latex',node,node.change_ext('.dvi')) | |
280 | elif self.type=='pdflatex': | |
281 | task=self.create_task('pdflatex',node,node.change_ext('.pdf')) | |
282 | elif self.type=='xelatex': | |
283 | task=self.create_task('xelatex',node,node.change_ext('.pdf')) | |
284 | task.env=self.env | |
285 | if deps_lst: | |
286 | for n in deps_lst: | |
287 | if not n in task.dep_nodes: | |
288 | task.dep_nodes.append(n) | |
289 | if hasattr(self,'texinputs_nodes'): | |
290 | task.texinputs_nodes=self.texinputs_nodes | |
291 | else: | |
292 | task.texinputs_nodes=[node.parent,node.parent.get_bld(),self.path,self.path.get_bld()] | |
293 | lst=os.environ.get('TEXINPUTS','') | |
294 | if self.env.TEXINPUTS: | |
295 | lst+=os.pathsep+self.env.TEXINPUTS | |
296 | if lst: | |
297 | lst=lst.split(os.pathsep) | |
298 | for x in lst: | |
299 | if x: | |
300 | if os.path.isabs(x): | |
301 | p=self.bld.root.find_node(x) | |
302 | if p: | |
303 | task.texinputs_nodes.append(p) | |
304 | else: | |
305 | Logs.error('Invalid TEXINPUTS folder %s',x) | |
306 | else: | |
307 | Logs.error('Cannot resolve relative paths in TEXINPUTS %s',x) | |
308 | if self.type=='latex': | |
309 | if'ps'in outs: | |
310 | tsk=self.create_task('dvips',task.outputs,node.change_ext('.ps')) | |
311 | tsk.env.env=dict(os.environ) | |
312 | if'pdf'in outs: | |
313 | tsk=self.create_task('dvipdf',task.outputs,node.change_ext('.pdf')) | |
314 | tsk.env.env=dict(os.environ) | |
315 | elif self.type=='pdflatex': | |
316 | if'ps'in outs: | |
317 | self.create_task('pdf2ps',task.outputs,node.change_ext('.ps')) | |
318 | self.source=[] | |
319 | def configure(self): | |
320 | v=self.env | |
321 | for p in'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps makeglossaries'.split(): | |
322 | try: | |
323 | self.find_program(p,var=p.upper()) | |
324 | except self.errors.ConfigurationError: | |
325 | pass | |
326 | v.DVIPSFLAGS='-Ppdf' |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Build,Context,Errors,Logs,Node,Options,Task,Utils | |
6 | from waflib.TaskGen import extension,taskgen_method | |
7 | from waflib.Configure import conf | |
8 | class valac(Task.Task): | |
9 | vars=["VALAC","VALAC_VERSION","VALAFLAGS"] | |
10 | ext_out=['.h'] | |
11 | def run(self): | |
12 | cmd=self.env.VALAC+self.env.VALAFLAGS | |
13 | resources=getattr(self,'vala_exclude',[]) | |
14 | cmd.extend([a.abspath()for a in self.inputs if a not in resources]) | |
15 | ret=self.exec_command(cmd,cwd=self.vala_dir_node.abspath()) | |
16 | if ret: | |
17 | return ret | |
18 | if self.generator.dump_deps_node: | |
19 | self.generator.dump_deps_node.write('\n'.join(self.generator.packages)) | |
20 | return ret | |
21 | @taskgen_method | |
22 | def init_vala_task(self): | |
23 | self.profile=getattr(self,'profile','gobject') | |
24 | self.packages=packages=Utils.to_list(getattr(self,'packages',[])) | |
25 | self.use=Utils.to_list(getattr(self,'use',[])) | |
26 | if packages and not self.use: | |
27 | self.use=packages[:] | |
28 | if self.profile=='gobject': | |
29 | if not'GOBJECT'in self.use: | |
30 | self.use.append('GOBJECT') | |
31 | def addflags(flags): | |
32 | self.env.append_value('VALAFLAGS',flags) | |
33 | if self.profile: | |
34 | addflags('--profile=%s'%self.profile) | |
35 | valatask=self.valatask | |
36 | if hasattr(self,'vala_dir'): | |
37 | if isinstance(self.vala_dir,str): | |
38 | valatask.vala_dir_node=self.path.get_bld().make_node(self.vala_dir) | |
39 | try: | |
40 | valatask.vala_dir_node.mkdir() | |
41 | except OSError: | |
42 | raise self.bld.fatal('Cannot create the vala dir %r'%valatask.vala_dir_node) | |
43 | else: | |
44 | valatask.vala_dir_node=self.vala_dir | |
45 | else: | |
46 | valatask.vala_dir_node=self.path.get_bld() | |
47 | addflags('--directory=%s'%valatask.vala_dir_node.abspath()) | |
48 | if hasattr(self,'thread'): | |
49 | if self.profile=='gobject': | |
50 | if not'GTHREAD'in self.use: | |
51 | self.use.append('GTHREAD') | |
52 | else: | |
53 | Logs.warn('Profile %s means no threading support',self.profile) | |
54 | self.thread=False | |
55 | if self.thread: | |
56 | addflags('--thread') | |
57 | self.is_lib='cprogram'not in self.features | |
58 | if self.is_lib: | |
59 | addflags('--library=%s'%self.target) | |
60 | h_node=valatask.vala_dir_node.find_or_declare('%s.h'%self.target) | |
61 | valatask.outputs.append(h_node) | |
62 | addflags('--header=%s'%h_node.name) | |
63 | valatask.outputs.append(valatask.vala_dir_node.find_or_declare('%s.vapi'%self.target)) | |
64 | if getattr(self,'gir',None): | |
65 | gir_node=valatask.vala_dir_node.find_or_declare('%s.gir'%self.gir) | |
66 | addflags('--gir=%s'%gir_node.name) | |
67 | valatask.outputs.append(gir_node) | |
68 | self.vala_target_glib=getattr(self,'vala_target_glib',getattr(Options.options,'vala_target_glib',None)) | |
69 | if self.vala_target_glib: | |
70 | addflags('--target-glib=%s'%self.vala_target_glib) | |
71 | addflags(['--define=%s'%x for x in Utils.to_list(getattr(self,'vala_defines',[]))]) | |
72 | packages_private=Utils.to_list(getattr(self,'packages_private',[])) | |
73 | addflags(['--pkg=%s'%x for x in packages_private]) | |
74 | def _get_api_version(): | |
75 | api_version='1.0' | |
76 | if hasattr(Context.g_module,'API_VERSION'): | |
77 | version=Context.g_module.API_VERSION.split(".") | |
78 | if version[0]=="0": | |
79 | api_version="0."+version[1] | |
80 | else: | |
81 | api_version=version[0]+".0" | |
82 | return api_version | |
83 | self.includes=Utils.to_list(getattr(self,'includes',[])) | |
84 | valatask.install_path=getattr(self,'install_path','') | |
85 | valatask.vapi_path=getattr(self,'vapi_path','${DATAROOTDIR}/vala/vapi') | |
86 | valatask.pkg_name=getattr(self,'pkg_name',self.env.PACKAGE) | |
87 | valatask.header_path=getattr(self,'header_path','${INCLUDEDIR}/%s-%s'%(valatask.pkg_name,_get_api_version())) | |
88 | valatask.install_binding=getattr(self,'install_binding',True) | |
89 | self.vapi_dirs=vapi_dirs=Utils.to_list(getattr(self,'vapi_dirs',[])) | |
90 | if hasattr(self,'use'): | |
91 | local_packages=Utils.to_list(self.use)[:] | |
92 | seen=[] | |
93 | while len(local_packages)>0: | |
94 | package=local_packages.pop() | |
95 | if package in seen: | |
96 | continue | |
97 | seen.append(package) | |
98 | try: | |
99 | package_obj=self.bld.get_tgen_by_name(package) | |
100 | except Errors.WafError: | |
101 | continue | |
102 | package_obj.post() | |
103 | package_name=package_obj.target | |
104 | task=getattr(package_obj,'valatask',None) | |
105 | if task: | |
106 | for output in task.outputs: | |
107 | if output.name==package_name+".vapi": | |
108 | valatask.set_run_after(task) | |
109 | if package_name not in packages: | |
110 | packages.append(package_name) | |
111 | if output.parent not in vapi_dirs: | |
112 | vapi_dirs.append(output.parent) | |
113 | if output.parent not in self.includes: | |
114 | self.includes.append(output.parent) | |
115 | if hasattr(package_obj,'use'): | |
116 | lst=self.to_list(package_obj.use) | |
117 | lst.reverse() | |
118 | local_packages=[pkg for pkg in lst if pkg not in seen]+local_packages | |
119 | addflags(['--pkg=%s'%p for p in packages]) | |
120 | for vapi_dir in vapi_dirs: | |
121 | if isinstance(vapi_dir,Node.Node): | |
122 | v_node=vapi_dir | |
123 | else: | |
124 | v_node=self.path.find_dir(vapi_dir) | |
125 | if not v_node: | |
126 | Logs.warn('Unable to locate Vala API directory: %r',vapi_dir) | |
127 | else: | |
128 | addflags('--vapidir=%s'%v_node.abspath()) | |
129 | self.dump_deps_node=None | |
130 | if self.is_lib and self.packages: | |
131 | self.dump_deps_node=valatask.vala_dir_node.find_or_declare('%s.deps'%self.target) | |
132 | valatask.outputs.append(self.dump_deps_node) | |
133 | if self.is_lib and valatask.install_binding: | |
134 | headers_list=[o for o in valatask.outputs if o.suffix()==".h"] | |
135 | if headers_list: | |
136 | self.install_vheader=self.add_install_files(install_to=valatask.header_path,install_from=headers_list) | |
137 | vapi_list=[o for o in valatask.outputs if(o.suffix()in(".vapi",".deps"))] | |
138 | if vapi_list: | |
139 | self.install_vapi=self.add_install_files(install_to=valatask.vapi_path,install_from=vapi_list) | |
140 | gir_list=[o for o in valatask.outputs if o.suffix()=='.gir'] | |
141 | if gir_list: | |
142 | self.install_gir=self.add_install_files(install_to=getattr(self,'gir_path','${DATAROOTDIR}/gir-1.0'),install_from=gir_list) | |
143 | if hasattr(self,'vala_resources'): | |
144 | nodes=self.to_nodes(self.vala_resources) | |
145 | valatask.vala_exclude=getattr(valatask,'vala_exclude',[])+nodes | |
146 | valatask.inputs.extend(nodes) | |
147 | for x in nodes: | |
148 | addflags(['--gresources',x.abspath()]) | |
149 | @extension('.vala','.gs') | |
150 | def vala_file(self,node): | |
151 | try: | |
152 | valatask=self.valatask | |
153 | except AttributeError: | |
154 | valatask=self.valatask=self.create_task('valac') | |
155 | self.init_vala_task() | |
156 | valatask.inputs.append(node) | |
157 | name=node.name[:node.name.rfind('.')]+'.c' | |
158 | c_node=valatask.vala_dir_node.find_or_declare(name) | |
159 | valatask.outputs.append(c_node) | |
160 | self.source.append(c_node) | |
161 | @extension('.vapi') | |
162 | def vapi_file(self,node): | |
163 | try: | |
164 | valatask=self.valatask | |
165 | except AttributeError: | |
166 | valatask=self.valatask=self.create_task('valac') | |
167 | self.init_vala_task() | |
168 | valatask.inputs.append(node) | |
169 | @conf | |
170 | def find_valac(self,valac_name,min_version): | |
171 | valac=self.find_program(valac_name,var='VALAC') | |
172 | try: | |
173 | output=self.cmd_and_log(valac+['--version']) | |
174 | except Errors.WafError: | |
175 | valac_version=None | |
176 | else: | |
177 | ver=re.search(r'\d+.\d+.\d+',output).group().split('.') | |
178 | valac_version=tuple([int(x)for x in ver]) | |
179 | self.msg('Checking for %s version >= %r'%(valac_name,min_version),valac_version,valac_version and valac_version>=min_version) | |
180 | if valac and valac_version<min_version: | |
181 | self.fatal("%s version %r is too old, need >= %r"%(valac_name,valac_version,min_version)) | |
182 | self.env.VALAC_VERSION=valac_version | |
183 | return valac | |
184 | @conf | |
185 | def check_vala(self,min_version=(0,8,0),branch=None): | |
186 | if self.env.VALA_MINVER: | |
187 | min_version=self.env.VALA_MINVER | |
188 | if self.env.VALA_MINVER_BRANCH: | |
189 | branch=self.env.VALA_MINVER_BRANCH | |
190 | if not branch: | |
191 | branch=min_version[:2] | |
192 | try: | |
193 | find_valac(self,'valac-%d.%d'%(branch[0],branch[1]),min_version) | |
194 | except self.errors.ConfigurationError: | |
195 | find_valac(self,'valac',min_version) | |
196 | @conf | |
197 | def check_vala_deps(self): | |
198 | if not self.env.HAVE_GOBJECT: | |
199 | pkg_args={'package':'gobject-2.0','uselib_store':'GOBJECT','args':'--cflags --libs'} | |
200 | if getattr(Options.options,'vala_target_glib',None): | |
201 | pkg_args['atleast_version']=Options.options.vala_target_glib | |
202 | self.check_cfg(**pkg_args) | |
203 | if not self.env.HAVE_GTHREAD: | |
204 | pkg_args={'package':'gthread-2.0','uselib_store':'GTHREAD','args':'--cflags --libs'} | |
205 | if getattr(Options.options,'vala_target_glib',None): | |
206 | pkg_args['atleast_version']=Options.options.vala_target_glib | |
207 | self.check_cfg(**pkg_args) | |
208 | def configure(self): | |
209 | self.load('gnu_dirs') | |
210 | self.check_vala_deps() | |
211 | self.check_vala() | |
212 | self.add_os_flags('VALAFLAGS') | |
213 | self.env.append_unique('VALAFLAGS',['-C']) | |
214 | def options(opt): | |
215 | opt.load('gnu_dirs') | |
216 | valaopts=opt.add_option_group('Vala Compiler Options') | |
217 | valaopts.add_option('--vala-target-glib',default=None,dest='vala_target_glib',metavar='MAJOR.MINOR',help='Target version of glib for Vala GObject code generation') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,shlex,sys | |
5 | from waflib.TaskGen import feature,after_method,taskgen_method | |
6 | from waflib import Utils,Task,Logs,Options | |
7 | from waflib.Tools import ccroot | |
8 | testlock=Utils.threading.Lock() | |
9 | SCRIPT_TEMPLATE="""#! %(python)s | |
10 | import subprocess, sys | |
11 | cmd = %(cmd)r | |
12 | # if you want to debug with gdb: | |
13 | #cmd = ['gdb', '-args'] + cmd | |
14 | env = %(env)r | |
15 | status = subprocess.call(cmd, env=env, cwd=%(cwd)r, shell=isinstance(cmd, str)) | |
16 | sys.exit(status) | |
17 | """ | |
18 | @taskgen_method | |
19 | def handle_ut_cwd(self,key): | |
20 | cwd=getattr(self,key,None) | |
21 | if cwd: | |
22 | if isinstance(cwd,str): | |
23 | if os.path.isabs(cwd): | |
24 | self.ut_cwd=self.bld.root.make_node(cwd) | |
25 | else: | |
26 | self.ut_cwd=self.path.make_node(cwd) | |
27 | @feature('test_scripts') | |
28 | def make_interpreted_test(self): | |
29 | for x in['test_scripts_source','test_scripts_template']: | |
30 | if not hasattr(self,x): | |
31 | Logs.warn('a test_scripts taskgen i missing %s'%x) | |
32 | return | |
33 | self.ut_run,lst=Task.compile_fun(self.test_scripts_template,shell=getattr(self,'test_scripts_shell',False)) | |
34 | script_nodes=self.to_nodes(self.test_scripts_source) | |
35 | for script_node in script_nodes: | |
36 | tsk=self.create_task('utest',[script_node]) | |
37 | tsk.vars=lst+tsk.vars | |
38 | tsk.env['SCRIPT']=script_node.path_from(tsk.get_cwd()) | |
39 | self.handle_ut_cwd('test_scripts_cwd') | |
40 | env=getattr(self,'test_scripts_env',None) | |
41 | if env: | |
42 | self.ut_env=env | |
43 | else: | |
44 | self.ut_env=dict(os.environ) | |
45 | paths=getattr(self,'test_scripts_paths',{}) | |
46 | for(k,v)in paths.items(): | |
47 | p=self.ut_env.get(k,'').split(os.pathsep) | |
48 | if isinstance(v,str): | |
49 | v=v.split(os.pathsep) | |
50 | self.ut_env[k]=os.pathsep.join(p+v) | |
51 | @feature('test') | |
52 | @after_method('apply_link','process_use') | |
53 | def make_test(self): | |
54 | if not getattr(self,'link_task',None): | |
55 | return | |
56 | tsk=self.create_task('utest',self.link_task.outputs) | |
57 | if getattr(self,'ut_str',None): | |
58 | self.ut_run,lst=Task.compile_fun(self.ut_str,shell=getattr(self,'ut_shell',False)) | |
59 | tsk.vars=lst+tsk.vars | |
60 | self.handle_ut_cwd('ut_cwd') | |
61 | if not hasattr(self,'ut_paths'): | |
62 | paths=[] | |
63 | for x in self.tmp_use_sorted: | |
64 | try: | |
65 | y=self.bld.get_tgen_by_name(x).link_task | |
66 | except AttributeError: | |
67 | pass | |
68 | else: | |
69 | if not isinstance(y,ccroot.stlink_task): | |
70 | paths.append(y.outputs[0].parent.abspath()) | |
71 | self.ut_paths=os.pathsep.join(paths)+os.pathsep | |
72 | if not hasattr(self,'ut_env'): | |
73 | self.ut_env=dct=dict(os.environ) | |
74 | def add_path(var): | |
75 | dct[var]=self.ut_paths+dct.get(var,'') | |
76 | if Utils.is_win32: | |
77 | add_path('PATH') | |
78 | elif Utils.unversioned_sys_platform()=='darwin': | |
79 | add_path('DYLD_LIBRARY_PATH') | |
80 | add_path('LD_LIBRARY_PATH') | |
81 | else: | |
82 | add_path('LD_LIBRARY_PATH') | |
83 | if not hasattr(self,'ut_cmd'): | |
84 | self.ut_cmd=getattr(Options.options,'testcmd',False) | |
85 | @taskgen_method | |
86 | def add_test_results(self,tup): | |
87 | Logs.debug("ut: %r",tup) | |
88 | try: | |
89 | self.utest_results.append(tup) | |
90 | except AttributeError: | |
91 | self.utest_results=[tup] | |
92 | try: | |
93 | self.bld.utest_results.append(tup) | |
94 | except AttributeError: | |
95 | self.bld.utest_results=[tup] | |
96 | @Task.deep_inputs | |
97 | class utest(Task.Task): | |
98 | color='PINK' | |
99 | after=['vnum','inst'] | |
100 | vars=[] | |
101 | def runnable_status(self): | |
102 | if getattr(Options.options,'no_tests',False): | |
103 | return Task.SKIP_ME | |
104 | ret=super(utest,self).runnable_status() | |
105 | if ret==Task.SKIP_ME: | |
106 | if getattr(Options.options,'all_tests',False): | |
107 | return Task.RUN_ME | |
108 | return ret | |
109 | def get_test_env(self): | |
110 | return self.generator.ut_env | |
111 | def post_run(self): | |
112 | super(utest,self).post_run() | |
113 | if getattr(Options.options,'clear_failed_tests',False)and self.waf_unit_test_results[1]: | |
114 | self.generator.bld.task_sigs[self.uid()]=None | |
115 | def run(self): | |
116 | if hasattr(self.generator,'ut_run'): | |
117 | return self.generator.ut_run(self) | |
118 | self.ut_exec=getattr(self.generator,'ut_exec',[self.inputs[0].abspath()]) | |
119 | ut_cmd=getattr(self.generator,'ut_cmd',False) | |
120 | if ut_cmd: | |
121 | self.ut_exec=shlex.split(ut_cmd%' '.join(self.ut_exec)) | |
122 | return self.exec_command(self.ut_exec) | |
123 | def exec_command(self,cmd,**kw): | |
124 | self.generator.bld.log_command(cmd,kw) | |
125 | if getattr(Options.options,'dump_test_scripts',False): | |
126 | script_code=SCRIPT_TEMPLATE%{'python':sys.executable,'env':self.get_test_env(),'cwd':self.get_cwd().abspath(),'cmd':cmd} | |
127 | script_file=self.inputs[0].abspath()+'_run.py' | |
128 | Utils.writef(script_file,script_code,encoding='utf-8') | |
129 | os.chmod(script_file,Utils.O755) | |
130 | if Logs.verbose>1: | |
131 | Logs.info('Test debug file written as %r'%script_file) | |
132 | proc=Utils.subprocess.Popen(cmd,cwd=self.get_cwd().abspath(),env=self.get_test_env(),stderr=Utils.subprocess.PIPE,stdout=Utils.subprocess.PIPE,shell=isinstance(cmd,str)) | |
133 | (stdout,stderr)=proc.communicate() | |
134 | self.waf_unit_test_results=tup=(self.inputs[0].abspath(),proc.returncode,stdout,stderr) | |
135 | testlock.acquire() | |
136 | try: | |
137 | return self.generator.add_test_results(tup) | |
138 | finally: | |
139 | testlock.release() | |
140 | def get_cwd(self): | |
141 | return getattr(self.generator,'ut_cwd',self.inputs[0].parent) | |
142 | def summary(bld): | |
143 | lst=getattr(bld,'utest_results',[]) | |
144 | if lst: | |
145 | Logs.pprint('CYAN','execution summary') | |
146 | total=len(lst) | |
147 | tfail=len([x for x in lst if x[1]]) | |
148 | Logs.pprint('GREEN',' tests that pass %d/%d'%(total-tfail,total)) | |
149 | for(f,code,out,err)in lst: | |
150 | if not code: | |
151 | Logs.pprint('GREEN',' %s'%f) | |
152 | Logs.pprint('GREEN'if tfail==0 else'RED',' tests that fail %d/%d'%(tfail,total)) | |
153 | for(f,code,out,err)in lst: | |
154 | if code: | |
155 | Logs.pprint('RED',' %s'%f) | |
156 | def set_exit_code(bld): | |
157 | lst=getattr(bld,'utest_results',[]) | |
158 | for(f,code,out,err)in lst: | |
159 | if code: | |
160 | msg=[] | |
161 | if out: | |
162 | msg.append('stdout:%s%s'%(os.linesep,out.decode('utf-8'))) | |
163 | if err: | |
164 | msg.append('stderr:%s%s'%(os.linesep,err.decode('utf-8'))) | |
165 | bld.fatal(os.linesep.join(msg)) | |
166 | def options(opt): | |
167 | opt.add_option('--notests',action='store_true',default=False,help='Exec no unit tests',dest='no_tests') | |
168 | opt.add_option('--alltests',action='store_true',default=False,help='Exec all unit tests',dest='all_tests') | |
169 | opt.add_option('--clear-failed',action='store_true',default=False,help='Force failed unit tests to run again next time',dest='clear_failed_tests') | |
170 | opt.add_option('--testcmd',action='store',default=False,dest='testcmd',help='Run the unit tests using the test-cmd string example "--testcmd="valgrind --error-exitcode=1 %s" to run under valgrind') | |
171 | opt.add_option('--dump-test-scripts',action='store_true',default=False,help='Create python scripts to help debug tests',dest='dump_test_scripts') |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import re | |
5 | from waflib import Task | |
6 | from waflib.TaskGen import extension | |
7 | from waflib.Tools import c_preproc | |
8 | @extension('.rc') | |
9 | def rc_file(self,node): | |
10 | obj_ext='.rc.o' | |
11 | if self.env.WINRC_TGT_F=='/fo': | |
12 | obj_ext='.res' | |
13 | rctask=self.create_task('winrc',node,node.change_ext(obj_ext)) | |
14 | try: | |
15 | self.compiled_tasks.append(rctask) | |
16 | except AttributeError: | |
17 | self.compiled_tasks=[rctask] | |
18 | re_lines=re.compile(r'(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|'r'(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)',re.IGNORECASE|re.MULTILINE) | |
19 | class rc_parser(c_preproc.c_parser): | |
20 | def filter_comments(self,node): | |
21 | code=node.read() | |
22 | if c_preproc.use_trigraphs: | |
23 | for(a,b)in c_preproc.trig_def: | |
24 | code=code.split(a).join(b) | |
25 | code=c_preproc.re_nl.sub('',code) | |
26 | code=c_preproc.re_cpp.sub(c_preproc.repl,code) | |
27 | ret=[] | |
28 | for m in re.finditer(re_lines,code): | |
29 | if m.group(2): | |
30 | ret.append((m.group(2),m.group(3))) | |
31 | else: | |
32 | ret.append(('include',m.group(5))) | |
33 | return ret | |
34 | class winrc(Task.Task): | |
35 | run_str='${WINRC} ${WINRCFLAGS} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' | |
36 | color='BLUE' | |
37 | def scan(self): | |
38 | tmp=rc_parser(self.generator.includes_nodes) | |
39 | tmp.start(self.inputs[0],self.env) | |
40 | return(tmp.nodes,tmp.names) | |
41 | def configure(conf): | |
42 | v=conf.env | |
43 | if not v.WINRC: | |
44 | if v.CC_NAME=='msvc': | |
45 | conf.find_program('RC',var='WINRC',path_list=v.PATH) | |
46 | v.WINRC_TGT_F='/fo' | |
47 | v.WINRC_SRC_F='' | |
48 | else: | |
49 | conf.find_program('windres',var='WINRC',path_list=v.PATH) | |
50 | v.WINRC_TGT_F='-o' | |
51 | v.WINRC_SRC_F='-i' |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ccroot,ar | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_xlc(conf): | |
8 | cc=conf.find_program(['xlc_r','xlc'],var='CC') | |
9 | conf.get_xlc_version(cc) | |
10 | conf.env.CC_NAME='xlc' | |
11 | @conf | |
12 | def xlc_common_flags(conf): | |
13 | v=conf.env | |
14 | v.CC_SRC_F=[] | |
15 | v.CC_TGT_F=['-c','-o'] | |
16 | if not v.LINK_CC: | |
17 | v.LINK_CC=v.CC | |
18 | v.CCLNK_SRC_F=[] | |
19 | v.CCLNK_TGT_F=['-o'] | |
20 | v.CPPPATH_ST='-I%s' | |
21 | v.DEFINES_ST='-D%s' | |
22 | v.LIB_ST='-l%s' | |
23 | v.LIBPATH_ST='-L%s' | |
24 | v.STLIB_ST='-l%s' | |
25 | v.STLIBPATH_ST='-L%s' | |
26 | v.RPATH_ST='-Wl,-rpath,%s' | |
27 | v.SONAME_ST=[] | |
28 | v.SHLIB_MARKER=[] | |
29 | v.STLIB_MARKER=[] | |
30 | v.LINKFLAGS_cprogram=['-Wl,-brtl'] | |
31 | v.cprogram_PATTERN='%s' | |
32 | v.CFLAGS_cshlib=['-fPIC'] | |
33 | v.LINKFLAGS_cshlib=['-G','-Wl,-brtl,-bexpfull'] | |
34 | v.cshlib_PATTERN='lib%s.so' | |
35 | v.LINKFLAGS_cstlib=[] | |
36 | v.cstlib_PATTERN='lib%s.a' | |
37 | def configure(conf): | |
38 | conf.find_xlc() | |
39 | conf.find_ar() | |
40 | conf.xlc_common_flags() | |
41 | conf.cc_load_tools() | |
42 | conf.cc_add_flags() | |
43 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from waflib.Tools import ccroot,ar | |
5 | from waflib.Configure import conf | |
6 | @conf | |
7 | def find_xlcxx(conf): | |
8 | cxx=conf.find_program(['xlc++_r','xlc++'],var='CXX') | |
9 | conf.get_xlc_version(cxx) | |
10 | conf.env.CXX_NAME='xlc++' | |
11 | @conf | |
12 | def xlcxx_common_flags(conf): | |
13 | v=conf.env | |
14 | v.CXX_SRC_F=[] | |
15 | v.CXX_TGT_F=['-c','-o'] | |
16 | if not v.LINK_CXX: | |
17 | v.LINK_CXX=v.CXX | |
18 | v.CXXLNK_SRC_F=[] | |
19 | v.CXXLNK_TGT_F=['-o'] | |
20 | v.CPPPATH_ST='-I%s' | |
21 | v.DEFINES_ST='-D%s' | |
22 | v.LIB_ST='-l%s' | |
23 | v.LIBPATH_ST='-L%s' | |
24 | v.STLIB_ST='-l%s' | |
25 | v.STLIBPATH_ST='-L%s' | |
26 | v.RPATH_ST='-Wl,-rpath,%s' | |
27 | v.SONAME_ST=[] | |
28 | v.SHLIB_MARKER=[] | |
29 | v.STLIB_MARKER=[] | |
30 | v.LINKFLAGS_cxxprogram=['-Wl,-brtl'] | |
31 | v.cxxprogram_PATTERN='%s' | |
32 | v.CXXFLAGS_cxxshlib=['-fPIC'] | |
33 | v.LINKFLAGS_cxxshlib=['-G','-Wl,-brtl,-bexpfull'] | |
34 | v.cxxshlib_PATTERN='lib%s.so' | |
35 | v.LINKFLAGS_cxxstlib=[] | |
36 | v.cxxstlib_PATTERN='lib%s.a' | |
37 | def configure(conf): | |
38 | conf.find_xlcxx() | |
39 | conf.find_ar() | |
40 | conf.xlcxx_common_flags() | |
41 | conf.cxx_load_tools() | |
42 | conf.cxx_add_flags() | |
43 | conf.link_add_flags() |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from __future__ import with_statement | |
5 | import atexit,os,sys,errno,inspect,re,datetime,platform,base64,signal,functools,time | |
6 | try: | |
7 | import cPickle | |
8 | except ImportError: | |
9 | import pickle as cPickle | |
10 | if os.name=='posix'and sys.version_info[0]<3: | |
11 | try: | |
12 | import subprocess32 as subprocess | |
13 | except ImportError: | |
14 | import subprocess | |
15 | else: | |
16 | import subprocess | |
17 | try: | |
18 | TimeoutExpired=subprocess.TimeoutExpired | |
19 | except AttributeError: | |
20 | class TimeoutExpired(Exception): | |
21 | pass | |
22 | from collections import deque,defaultdict | |
23 | try: | |
24 | import _winreg as winreg | |
25 | except ImportError: | |
26 | try: | |
27 | import winreg | |
28 | except ImportError: | |
29 | winreg=None | |
30 | from waflib import Errors | |
31 | try: | |
32 | from hashlib import md5 | |
33 | except ImportError: | |
34 | try: | |
35 | from hashlib import sha1 as md5 | |
36 | except ImportError: | |
37 | pass | |
38 | else: | |
39 | try: | |
40 | md5().digest() | |
41 | except ValueError: | |
42 | from hashlib import sha1 as md5 | |
43 | try: | |
44 | import threading | |
45 | except ImportError: | |
46 | if not'JOBS'in os.environ: | |
47 | os.environ['JOBS']='1' | |
48 | class threading(object): | |
49 | pass | |
50 | class Lock(object): | |
51 | def acquire(self): | |
52 | pass | |
53 | def release(self): | |
54 | pass | |
55 | threading.Lock=threading.Thread=Lock | |
56 | SIG_NIL='SIG_NIL_SIG_NIL_'.encode() | |
57 | O644=420 | |
58 | O755=493 | |
59 | rot_chr=['\\','|','/','-'] | |
60 | rot_idx=0 | |
61 | class ordered_iter_dict(dict): | |
62 | def __init__(self,*k,**kw): | |
63 | self.lst=deque() | |
64 | dict.__init__(self,*k,**kw) | |
65 | def clear(self): | |
66 | dict.clear(self) | |
67 | self.lst=deque() | |
68 | def __setitem__(self,key,value): | |
69 | if key in dict.keys(self): | |
70 | self.lst.remove(key) | |
71 | dict.__setitem__(self,key,value) | |
72 | self.lst.append(key) | |
73 | def __delitem__(self,key): | |
74 | dict.__delitem__(self,key) | |
75 | try: | |
76 | self.lst.remove(key) | |
77 | except ValueError: | |
78 | pass | |
79 | def __iter__(self): | |
80 | return reversed(self.lst) | |
81 | def keys(self): | |
82 | return reversed(self.lst) | |
83 | class lru_node(object): | |
84 | __slots__=('next','prev','key','val') | |
85 | def __init__(self): | |
86 | self.next=self | |
87 | self.prev=self | |
88 | self.key=None | |
89 | self.val=None | |
90 | class lru_cache(object): | |
91 | __slots__=('maxlen','table','head') | |
92 | def __init__(self,maxlen=100): | |
93 | self.maxlen=maxlen | |
94 | self.table={} | |
95 | self.head=lru_node() | |
96 | self.head.next=self.head | |
97 | self.head.prev=self.head | |
98 | def __getitem__(self,key): | |
99 | node=self.table[key] | |
100 | if node is self.head: | |
101 | return node.val | |
102 | node.prev.next=node.next | |
103 | node.next.prev=node.prev | |
104 | node.next=self.head.next | |
105 | node.prev=self.head | |
106 | self.head=node.next.prev=node.prev.next=node | |
107 | return node.val | |
108 | def __setitem__(self,key,val): | |
109 | if key in self.table: | |
110 | node=self.table[key] | |
111 | node.val=val | |
112 | self.__getitem__(key) | |
113 | else: | |
114 | if len(self.table)<self.maxlen: | |
115 | node=lru_node() | |
116 | node.prev=self.head | |
117 | node.next=self.head.next | |
118 | node.prev.next=node.next.prev=node | |
119 | else: | |
120 | node=self.head=self.head.next | |
121 | try: | |
122 | del self.table[node.key] | |
123 | except KeyError: | |
124 | pass | |
125 | node.key=key | |
126 | node.val=val | |
127 | self.table[key]=node | |
128 | class lazy_generator(object): | |
129 | def __init__(self,fun,params): | |
130 | self.fun=fun | |
131 | self.params=params | |
132 | def __iter__(self): | |
133 | return self | |
134 | def __next__(self): | |
135 | try: | |
136 | it=self.it | |
137 | except AttributeError: | |
138 | it=self.it=self.fun(*self.params) | |
139 | return next(it) | |
140 | next=__next__ | |
141 | is_win32=os.sep=='\\'or sys.platform=='win32'or os.name=='nt' | |
142 | def readf(fname,m='r',encoding='latin-1'): | |
143 | if sys.hexversion>0x3000000 and not'b'in m: | |
144 | m+='b' | |
145 | with open(fname,m)as f: | |
146 | txt=f.read() | |
147 | if encoding: | |
148 | txt=txt.decode(encoding) | |
149 | else: | |
150 | txt=txt.decode() | |
151 | else: | |
152 | with open(fname,m)as f: | |
153 | txt=f.read() | |
154 | return txt | |
155 | def writef(fname,data,m='w',encoding='latin-1'): | |
156 | if sys.hexversion>0x3000000 and not'b'in m: | |
157 | data=data.encode(encoding) | |
158 | m+='b' | |
159 | with open(fname,m)as f: | |
160 | f.write(data) | |
161 | def h_file(fname): | |
162 | m=md5() | |
163 | with open(fname,'rb')as f: | |
164 | while fname: | |
165 | fname=f.read(200000) | |
166 | m.update(fname) | |
167 | return m.digest() | |
168 | def readf_win32(f,m='r',encoding='latin-1'): | |
169 | flags=os.O_NOINHERIT|os.O_RDONLY | |
170 | if'b'in m: | |
171 | flags|=os.O_BINARY | |
172 | if'+'in m: | |
173 | flags|=os.O_RDWR | |
174 | try: | |
175 | fd=os.open(f,flags) | |
176 | except OSError: | |
177 | raise IOError('Cannot read from %r'%f) | |
178 | if sys.hexversion>0x3000000 and not'b'in m: | |
179 | m+='b' | |
180 | with os.fdopen(fd,m)as f: | |
181 | txt=f.read() | |
182 | if encoding: | |
183 | txt=txt.decode(encoding) | |
184 | else: | |
185 | txt=txt.decode() | |
186 | else: | |
187 | with os.fdopen(fd,m)as f: | |
188 | txt=f.read() | |
189 | return txt | |
190 | def writef_win32(f,data,m='w',encoding='latin-1'): | |
191 | if sys.hexversion>0x3000000 and not'b'in m: | |
192 | data=data.encode(encoding) | |
193 | m+='b' | |
194 | flags=os.O_CREAT|os.O_TRUNC|os.O_WRONLY|os.O_NOINHERIT | |
195 | if'b'in m: | |
196 | flags|=os.O_BINARY | |
197 | if'+'in m: | |
198 | flags|=os.O_RDWR | |
199 | try: | |
200 | fd=os.open(f,flags) | |
201 | except OSError: | |
202 | raise OSError('Cannot write to %r'%f) | |
203 | with os.fdopen(fd,m)as f: | |
204 | f.write(data) | |
205 | def h_file_win32(fname): | |
206 | try: | |
207 | fd=os.open(fname,os.O_BINARY|os.O_RDONLY|os.O_NOINHERIT) | |
208 | except OSError: | |
209 | raise OSError('Cannot read from %r'%fname) | |
210 | m=md5() | |
211 | with os.fdopen(fd,'rb')as f: | |
212 | while fname: | |
213 | fname=f.read(200000) | |
214 | m.update(fname) | |
215 | return m.digest() | |
216 | readf_unix=readf | |
217 | writef_unix=writef | |
218 | h_file_unix=h_file | |
219 | if hasattr(os,'O_NOINHERIT')and sys.hexversion<0x3040000: | |
220 | readf=readf_win32 | |
221 | writef=writef_win32 | |
222 | h_file=h_file_win32 | |
223 | try: | |
224 | x=''.encode('hex') | |
225 | except LookupError: | |
226 | import binascii | |
227 | def to_hex(s): | |
228 | ret=binascii.hexlify(s) | |
229 | if not isinstance(ret,str): | |
230 | ret=ret.decode('utf-8') | |
231 | return ret | |
232 | else: | |
233 | def to_hex(s): | |
234 | return s.encode('hex') | |
235 | to_hex.__doc__=""" | |
236 | Return the hexadecimal representation of a string | |
237 | ||
238 | :param s: string to convert | |
239 | :type s: string | |
240 | """ | |
241 | def listdir_win32(s): | |
242 | if not s: | |
243 | try: | |
244 | import ctypes | |
245 | except ImportError: | |
246 | return[x+':\\'for x in'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] | |
247 | else: | |
248 | dlen=4 | |
249 | maxdrives=26 | |
250 | buf=ctypes.create_string_buffer(maxdrives*dlen) | |
251 | ndrives=ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen,ctypes.byref(buf)) | |
252 | return[str(buf.raw[4*i:4*i+2].decode('ascii'))for i in range(int(ndrives/dlen))] | |
253 | if len(s)==2 and s[1]==":": | |
254 | s+=os.sep | |
255 | if not os.path.isdir(s): | |
256 | e=OSError('%s is not a directory'%s) | |
257 | e.errno=errno.ENOENT | |
258 | raise e | |
259 | return os.listdir(s) | |
260 | listdir=os.listdir | |
261 | if is_win32: | |
262 | listdir=listdir_win32 | |
263 | def num2ver(ver): | |
264 | if isinstance(ver,str): | |
265 | ver=tuple(ver.split('.')) | |
266 | if isinstance(ver,tuple): | |
267 | ret=0 | |
268 | for i in range(4): | |
269 | if i<len(ver): | |
270 | ret+=256**(3-i)*int(ver[i]) | |
271 | return ret | |
272 | return ver | |
273 | def to_list(val): | |
274 | if isinstance(val,str): | |
275 | return val.split() | |
276 | else: | |
277 | return val | |
278 | def console_encoding(): | |
279 | try: | |
280 | import ctypes | |
281 | except ImportError: | |
282 | pass | |
283 | else: | |
284 | try: | |
285 | codepage=ctypes.windll.kernel32.GetConsoleCP() | |
286 | except AttributeError: | |
287 | pass | |
288 | else: | |
289 | if codepage: | |
290 | return'cp%d'%codepage | |
291 | return sys.stdout.encoding or('cp1252'if is_win32 else'latin-1') | |
292 | def split_path_unix(path): | |
293 | return path.split('/') | |
294 | def split_path_cygwin(path): | |
295 | if path.startswith('//'): | |
296 | ret=path.split('/')[2:] | |
297 | ret[0]='/'+ret[0] | |
298 | return ret | |
299 | return path.split('/') | |
300 | re_sp=re.compile('[/\\\\]+') | |
301 | def split_path_win32(path): | |
302 | if path.startswith('\\\\'): | |
303 | ret=re_sp.split(path)[1:] | |
304 | ret[0]='\\\\'+ret[0] | |
305 | if ret[0]=='\\\\?': | |
306 | return ret[1:] | |
307 | return ret | |
308 | return re_sp.split(path) | |
309 | msysroot=None | |
310 | def split_path_msys(path): | |
311 | if path.startswith(('/','\\'))and not path.startswith(('//','\\\\')): | |
312 | global msysroot | |
313 | if not msysroot: | |
314 | msysroot=subprocess.check_output(['cygpath','-w','/']).decode(sys.stdout.encoding or'latin-1') | |
315 | msysroot=msysroot.strip() | |
316 | path=os.path.normpath(msysroot+os.sep+path) | |
317 | return split_path_win32(path) | |
318 | if sys.platform=='cygwin': | |
319 | split_path=split_path_cygwin | |
320 | elif is_win32: | |
321 | if os.environ.get('MSYSTEM')and sys.executable.startswith('/'): | |
322 | split_path=split_path_msys | |
323 | else: | |
324 | split_path=split_path_win32 | |
325 | else: | |
326 | split_path=split_path_unix | |
327 | split_path.__doc__=""" | |
328 | Splits a path by / or \\; do not confuse this function with with ``os.path.split`` | |
329 | ||
330 | :type path: string | |
331 | :param path: path to split | |
332 | :return: list of string | |
333 | """ | |
334 | def check_dir(path): | |
335 | if not os.path.isdir(path): | |
336 | try: | |
337 | os.makedirs(path) | |
338 | except OSError as e: | |
339 | if not os.path.isdir(path): | |
340 | raise Errors.WafError('Cannot create the folder %r'%path,ex=e) | |
341 | def check_exe(name,env=None): | |
342 | if not name: | |
343 | raise ValueError('Cannot execute an empty string!') | |
344 | def is_exe(fpath): | |
345 | return os.path.isfile(fpath)and os.access(fpath,os.X_OK) | |
346 | fpath,fname=os.path.split(name) | |
347 | if fpath and is_exe(name): | |
348 | return os.path.abspath(name) | |
349 | else: | |
350 | env=env or os.environ | |
351 | for path in env['PATH'].split(os.pathsep): | |
352 | path=path.strip('"') | |
353 | exe_file=os.path.join(path,name) | |
354 | if is_exe(exe_file): | |
355 | return os.path.abspath(exe_file) | |
356 | return None | |
357 | def def_attrs(cls,**kw): | |
358 | for k,v in kw.items(): | |
359 | if not hasattr(cls,k): | |
360 | setattr(cls,k,v) | |
361 | def quote_define_name(s): | |
362 | fu=re.sub('[^a-zA-Z0-9]','_',s) | |
363 | fu=re.sub('_+','_',fu) | |
364 | fu=fu.upper() | |
365 | return fu | |
366 | re_sh=re.compile('\\s|\'|"') | |
367 | def shell_escape(cmd): | |
368 | if isinstance(cmd,str): | |
369 | return cmd | |
370 | return' '.join(repr(x)if re_sh.search(x)else x for x in cmd) | |
371 | def h_list(lst): | |
372 | return md5(repr(lst).encode()).digest() | |
373 | if sys.hexversion<0x3000000: | |
374 | def h_list_python2(lst): | |
375 | return md5(repr(lst)).digest() | |
376 | h_list_python2.__doc__=h_list.__doc__ | |
377 | h_list=h_list_python2 | |
378 | def h_fun(fun): | |
379 | try: | |
380 | return fun.code | |
381 | except AttributeError: | |
382 | if isinstance(fun,functools.partial): | |
383 | code=list(fun.args) | |
384 | code.extend(sorted(fun.keywords.items())) | |
385 | code.append(h_fun(fun.func)) | |
386 | fun.code=h_list(code) | |
387 | return fun.code | |
388 | try: | |
389 | h=inspect.getsource(fun) | |
390 | except EnvironmentError: | |
391 | h='nocode' | |
392 | try: | |
393 | fun.code=h | |
394 | except AttributeError: | |
395 | pass | |
396 | return h | |
397 | def h_cmd(ins): | |
398 | if isinstance(ins,str): | |
399 | ret=ins | |
400 | elif isinstance(ins,list)or isinstance(ins,tuple): | |
401 | ret=str([h_cmd(x)for x in ins]) | |
402 | else: | |
403 | ret=str(h_fun(ins)) | |
404 | if sys.hexversion>0x3000000: | |
405 | ret=ret.encode('latin-1','xmlcharrefreplace') | |
406 | return ret | |
407 | reg_subst=re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") | |
408 | def subst_vars(expr,params): | |
409 | def repl_var(m): | |
410 | if m.group(1): | |
411 | return'\\' | |
412 | if m.group(2): | |
413 | return'$' | |
414 | try: | |
415 | return params.get_flat(m.group(3)) | |
416 | except AttributeError: | |
417 | return params[m.group(3)] | |
418 | return reg_subst.sub(repl_var,expr) | |
419 | def destos_to_binfmt(key): | |
420 | if key=='darwin': | |
421 | return'mac-o' | |
422 | elif key in('win32','cygwin','uwin','msys'): | |
423 | return'pe' | |
424 | return'elf' | |
425 | def unversioned_sys_platform(): | |
426 | s=sys.platform | |
427 | if s.startswith('java'): | |
428 | from java.lang import System | |
429 | s=System.getProperty('os.name') | |
430 | if s=='Mac OS X': | |
431 | return'darwin' | |
432 | elif s.startswith('Windows '): | |
433 | return'win32' | |
434 | elif s=='OS/2': | |
435 | return'os2' | |
436 | elif s=='HP-UX': | |
437 | return'hp-ux' | |
438 | elif s in('SunOS','Solaris'): | |
439 | return'sunos' | |
440 | else:s=s.lower() | |
441 | if s=='powerpc': | |
442 | return'darwin' | |
443 | if s=='win32'or s=='os2': | |
444 | return s | |
445 | if s=='cli'and os.name=='nt': | |
446 | return'win32' | |
447 | return re.split(r'\d+$',s)[0] | |
448 | def nada(*k,**kw): | |
449 | pass | |
450 | class Timer(object): | |
451 | def __init__(self): | |
452 | self.start_time=self.now() | |
453 | def __str__(self): | |
454 | delta=self.now()-self.start_time | |
455 | if not isinstance(delta,datetime.timedelta): | |
456 | delta=datetime.timedelta(seconds=delta) | |
457 | days=delta.days | |
458 | hours,rem=divmod(delta.seconds,3600) | |
459 | minutes,seconds=divmod(rem,60) | |
460 | seconds+=delta.microseconds*1e-6 | |
461 | result='' | |
462 | if days: | |
463 | result+='%dd'%days | |
464 | if days or hours: | |
465 | result+='%dh'%hours | |
466 | if days or hours or minutes: | |
467 | result+='%dm'%minutes | |
468 | return'%s%.3fs'%(result,seconds) | |
469 | def now(self): | |
470 | return datetime.datetime.utcnow() | |
471 | if hasattr(time,'perf_counter'): | |
472 | def now(self): | |
473 | return time.perf_counter() | |
474 | def read_la_file(path): | |
475 | sp=re.compile(r'^([^=]+)=\'(.*)\'$') | |
476 | dc={} | |
477 | for line in readf(path).splitlines(): | |
478 | try: | |
479 | _,left,right,_=sp.split(line.strip()) | |
480 | dc[left]=right | |
481 | except ValueError: | |
482 | pass | |
483 | return dc | |
484 | def run_once(fun): | |
485 | cache={} | |
486 | def wrap(*k): | |
487 | try: | |
488 | return cache[k] | |
489 | except KeyError: | |
490 | ret=fun(*k) | |
491 | cache[k]=ret | |
492 | return ret | |
493 | wrap.__cache__=cache | |
494 | wrap.__name__=fun.__name__ | |
495 | return wrap | |
496 | def get_registry_app_path(key,filename): | |
497 | if not winreg: | |
498 | return None | |
499 | try: | |
500 | result=winreg.QueryValue(key,"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe"%filename[0]) | |
501 | except OSError: | |
502 | pass | |
503 | else: | |
504 | if os.path.isfile(result): | |
505 | return result | |
506 | def lib64(): | |
507 | if os.sep=='/': | |
508 | if platform.architecture()[0]=='64bit': | |
509 | if os.path.exists('/usr/lib64')and not os.path.exists('/usr/lib32'): | |
510 | return'64' | |
511 | return'' | |
512 | def sane_path(p): | |
513 | return os.path.abspath(os.path.expanduser(p)) | |
514 | process_pool=[] | |
515 | def get_process(): | |
516 | try: | |
517 | return process_pool.pop() | |
518 | except IndexError: | |
519 | filepath=os.path.dirname(os.path.abspath(__file__))+os.sep+'processor.py' | |
520 | cmd=[sys.executable,'-c',readf(filepath)] | |
521 | return subprocess.Popen(cmd,stdout=subprocess.PIPE,stdin=subprocess.PIPE,bufsize=0,close_fds=not is_win32) | |
522 | def run_prefork_process(cmd,kwargs,cargs): | |
523 | if not kwargs.get('env'): | |
524 | kwargs['env']=dict(os.environ) | |
525 | try: | |
526 | obj=base64.b64encode(cPickle.dumps([cmd,kwargs,cargs])) | |
527 | except(TypeError,AttributeError): | |
528 | return run_regular_process(cmd,kwargs,cargs) | |
529 | proc=get_process() | |
530 | if not proc: | |
531 | return run_regular_process(cmd,kwargs,cargs) | |
532 | proc.stdin.write(obj) | |
533 | proc.stdin.write('\n'.encode()) | |
534 | proc.stdin.flush() | |
535 | obj=proc.stdout.readline() | |
536 | if not obj: | |
537 | raise OSError('Preforked sub-process %r died'%proc.pid) | |
538 | process_pool.append(proc) | |
539 | lst=cPickle.loads(base64.b64decode(obj)) | |
540 | assert len(lst)==5 | |
541 | ret,out,err,ex,trace=lst | |
542 | if ex: | |
543 | if ex=='OSError': | |
544 | raise OSError(trace) | |
545 | elif ex=='ValueError': | |
546 | raise ValueError(trace) | |
547 | elif ex=='TimeoutExpired': | |
548 | exc=TimeoutExpired(cmd,timeout=cargs['timeout'],output=out) | |
549 | exc.stderr=err | |
550 | raise exc | |
551 | else: | |
552 | raise Exception(trace) | |
553 | return ret,out,err | |
554 | def lchown(path,user=-1,group=-1): | |
555 | if isinstance(user,str): | |
556 | import pwd | |
557 | entry=pwd.getpwnam(user) | |
558 | if not entry: | |
559 | raise OSError('Unknown user %r'%user) | |
560 | user=entry[2] | |
561 | if isinstance(group,str): | |
562 | import grp | |
563 | entry=grp.getgrnam(group) | |
564 | if not entry: | |
565 | raise OSError('Unknown group %r'%group) | |
566 | group=entry[2] | |
567 | return os.lchown(path,user,group) | |
568 | def run_regular_process(cmd,kwargs,cargs={}): | |
569 | proc=subprocess.Popen(cmd,**kwargs) | |
570 | if kwargs.get('stdout')or kwargs.get('stderr'): | |
571 | try: | |
572 | out,err=proc.communicate(**cargs) | |
573 | except TimeoutExpired: | |
574 | if kwargs.get('start_new_session')and hasattr(os,'killpg'): | |
575 | os.killpg(proc.pid,signal.SIGKILL) | |
576 | else: | |
577 | proc.kill() | |
578 | out,err=proc.communicate() | |
579 | exc=TimeoutExpired(proc.args,timeout=cargs['timeout'],output=out) | |
580 | exc.stderr=err | |
581 | raise exc | |
582 | status=proc.returncode | |
583 | else: | |
584 | out,err=(None,None) | |
585 | try: | |
586 | status=proc.wait(**cargs) | |
587 | except TimeoutExpired as e: | |
588 | if kwargs.get('start_new_session')and hasattr(os,'killpg'): | |
589 | os.killpg(proc.pid,signal.SIGKILL) | |
590 | else: | |
591 | proc.kill() | |
592 | proc.wait() | |
593 | raise e | |
594 | return status,out,err | |
595 | def run_process(cmd,kwargs,cargs={}): | |
596 | if kwargs.get('stdout')and kwargs.get('stderr'): | |
597 | return run_prefork_process(cmd,kwargs,cargs) | |
598 | else: | |
599 | return run_regular_process(cmd,kwargs,cargs) | |
600 | def alloc_process_pool(n,force=False): | |
601 | global run_process,get_process,alloc_process_pool | |
602 | if not force: | |
603 | n=max(n-len(process_pool),0) | |
604 | try: | |
605 | lst=[get_process()for x in range(n)] | |
606 | except OSError: | |
607 | run_process=run_regular_process | |
608 | get_process=alloc_process_pool=nada | |
609 | else: | |
610 | for x in lst: | |
611 | process_pool.append(x) | |
612 | def atexit_pool(): | |
613 | for k in process_pool: | |
614 | try: | |
615 | os.kill(k.pid,9) | |
616 | except OSError: | |
617 | pass | |
618 | else: | |
619 | k.wait() | |
620 | if(sys.hexversion<0x207000f and not is_win32)or sys.hexversion>=0x306000f: | |
621 | atexit.register(atexit_pool) | |
622 | if os.environ.get('WAF_NO_PREFORK')or sys.platform=='cli'or not sys.executable: | |
623 | run_process=run_regular_process | |
624 | get_process=alloc_process_pool=nada |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,re,sys | |
5 | from waflib import Utils | |
6 | wlock=Utils.threading.Lock() | |
7 | try: | |
8 | from ctypes import Structure,windll,c_short,c_ushort,c_ulong,c_int,byref,c_wchar,POINTER,c_long | |
9 | except ImportError: | |
10 | class AnsiTerm(object): | |
11 | def __init__(self,stream): | |
12 | self.stream=stream | |
13 | try: | |
14 | self.errors=self.stream.errors | |
15 | except AttributeError: | |
16 | pass | |
17 | self.encoding=self.stream.encoding | |
18 | def write(self,txt): | |
19 | try: | |
20 | wlock.acquire() | |
21 | self.stream.write(txt) | |
22 | self.stream.flush() | |
23 | finally: | |
24 | wlock.release() | |
25 | def fileno(self): | |
26 | return self.stream.fileno() | |
27 | def flush(self): | |
28 | self.stream.flush() | |
29 | def isatty(self): | |
30 | return self.stream.isatty() | |
31 | else: | |
32 | class COORD(Structure): | |
33 | _fields_=[("X",c_short),("Y",c_short)] | |
34 | class SMALL_RECT(Structure): | |
35 | _fields_=[("Left",c_short),("Top",c_short),("Right",c_short),("Bottom",c_short)] | |
36 | class CONSOLE_SCREEN_BUFFER_INFO(Structure): | |
37 | _fields_=[("Size",COORD),("CursorPosition",COORD),("Attributes",c_ushort),("Window",SMALL_RECT),("MaximumWindowSize",COORD)] | |
38 | class CONSOLE_CURSOR_INFO(Structure): | |
39 | _fields_=[('dwSize',c_ulong),('bVisible',c_int)] | |
40 | try: | |
41 | _type=unicode | |
42 | except NameError: | |
43 | _type=str | |
44 | to_int=lambda number,default:number and int(number)or default | |
45 | STD_OUTPUT_HANDLE=-11 | |
46 | STD_ERROR_HANDLE=-12 | |
47 | windll.kernel32.GetStdHandle.argtypes=[c_ulong] | |
48 | windll.kernel32.GetStdHandle.restype=c_ulong | |
49 | windll.kernel32.GetConsoleScreenBufferInfo.argtypes=[c_ulong,POINTER(CONSOLE_SCREEN_BUFFER_INFO)] | |
50 | windll.kernel32.GetConsoleScreenBufferInfo.restype=c_long | |
51 | windll.kernel32.SetConsoleTextAttribute.argtypes=[c_ulong,c_ushort] | |
52 | windll.kernel32.SetConsoleTextAttribute.restype=c_long | |
53 | windll.kernel32.FillConsoleOutputCharacterW.argtypes=[c_ulong,c_wchar,c_ulong,POINTER(COORD),POINTER(c_ulong)] | |
54 | windll.kernel32.FillConsoleOutputCharacterW.restype=c_long | |
55 | windll.kernel32.FillConsoleOutputAttribute.argtypes=[c_ulong,c_ushort,c_ulong,POINTER(COORD),POINTER(c_ulong)] | |
56 | windll.kernel32.FillConsoleOutputAttribute.restype=c_long | |
57 | windll.kernel32.SetConsoleCursorPosition.argtypes=[c_ulong,POINTER(COORD)] | |
58 | windll.kernel32.SetConsoleCursorPosition.restype=c_long | |
59 | windll.kernel32.SetConsoleCursorInfo.argtypes=[c_ulong,POINTER(CONSOLE_CURSOR_INFO)] | |
60 | windll.kernel32.SetConsoleCursorInfo.restype=c_long | |
61 | class AnsiTerm(object): | |
62 | def __init__(self,s): | |
63 | self.stream=s | |
64 | try: | |
65 | self.errors=s.errors | |
66 | except AttributeError: | |
67 | pass | |
68 | self.encoding=s.encoding | |
69 | self.cursor_history=[] | |
70 | handle=(s.fileno()==2)and STD_ERROR_HANDLE or STD_OUTPUT_HANDLE | |
71 | self.hconsole=windll.kernel32.GetStdHandle(handle) | |
72 | self._sbinfo=CONSOLE_SCREEN_BUFFER_INFO() | |
73 | self._csinfo=CONSOLE_CURSOR_INFO() | |
74 | windll.kernel32.GetConsoleCursorInfo(self.hconsole,byref(self._csinfo)) | |
75 | self._orig_sbinfo=CONSOLE_SCREEN_BUFFER_INFO() | |
76 | r=windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(self._orig_sbinfo)) | |
77 | self._isatty=r==1 | |
78 | def screen_buffer_info(self): | |
79 | windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole,byref(self._sbinfo)) | |
80 | return self._sbinfo | |
81 | def clear_line(self,param): | |
82 | mode=param and int(param)or 0 | |
83 | sbinfo=self.screen_buffer_info() | |
84 | if mode==1: | |
85 | line_start=COORD(0,sbinfo.CursorPosition.Y) | |
86 | line_length=sbinfo.Size.X | |
87 | elif mode==2: | |
88 | line_start=COORD(sbinfo.CursorPosition.X,sbinfo.CursorPosition.Y) | |
89 | line_length=sbinfo.Size.X-sbinfo.CursorPosition.X | |
90 | else: | |
91 | line_start=sbinfo.CursorPosition | |
92 | line_length=sbinfo.Size.X-sbinfo.CursorPosition.X | |
93 | chars_written=c_ulong() | |
94 | windll.kernel32.FillConsoleOutputCharacterW(self.hconsole,c_wchar(' '),line_length,line_start,byref(chars_written)) | |
95 | windll.kernel32.FillConsoleOutputAttribute(self.hconsole,sbinfo.Attributes,line_length,line_start,byref(chars_written)) | |
96 | def clear_screen(self,param): | |
97 | mode=to_int(param,0) | |
98 | sbinfo=self.screen_buffer_info() | |
99 | if mode==1: | |
100 | clear_start=COORD(0,0) | |
101 | clear_length=sbinfo.CursorPosition.X*sbinfo.CursorPosition.Y | |
102 | elif mode==2: | |
103 | clear_start=COORD(0,0) | |
104 | clear_length=sbinfo.Size.X*sbinfo.Size.Y | |
105 | windll.kernel32.SetConsoleCursorPosition(self.hconsole,clear_start) | |
106 | else: | |
107 | clear_start=sbinfo.CursorPosition | |
108 | clear_length=((sbinfo.Size.X-sbinfo.CursorPosition.X)+sbinfo.Size.X*(sbinfo.Size.Y-sbinfo.CursorPosition.Y)) | |
109 | chars_written=c_ulong() | |
110 | windll.kernel32.FillConsoleOutputCharacterW(self.hconsole,c_wchar(' '),clear_length,clear_start,byref(chars_written)) | |
111 | windll.kernel32.FillConsoleOutputAttribute(self.hconsole,sbinfo.Attributes,clear_length,clear_start,byref(chars_written)) | |
112 | def push_cursor(self,param): | |
113 | sbinfo=self.screen_buffer_info() | |
114 | self.cursor_history.append(sbinfo.CursorPosition) | |
115 | def pop_cursor(self,param): | |
116 | if self.cursor_history: | |
117 | old_pos=self.cursor_history.pop() | |
118 | windll.kernel32.SetConsoleCursorPosition(self.hconsole,old_pos) | |
119 | def set_cursor(self,param): | |
120 | y,sep,x=param.partition(';') | |
121 | x=to_int(x,1)-1 | |
122 | y=to_int(y,1)-1 | |
123 | sbinfo=self.screen_buffer_info() | |
124 | new_pos=COORD(min(max(0,x),sbinfo.Size.X),min(max(0,y),sbinfo.Size.Y)) | |
125 | windll.kernel32.SetConsoleCursorPosition(self.hconsole,new_pos) | |
126 | def set_column(self,param): | |
127 | x=to_int(param,1)-1 | |
128 | sbinfo=self.screen_buffer_info() | |
129 | new_pos=COORD(min(max(0,x),sbinfo.Size.X),sbinfo.CursorPosition.Y) | |
130 | windll.kernel32.SetConsoleCursorPosition(self.hconsole,new_pos) | |
131 | def move_cursor(self,x_offset=0,y_offset=0): | |
132 | sbinfo=self.screen_buffer_info() | |
133 | new_pos=COORD(min(max(0,sbinfo.CursorPosition.X+x_offset),sbinfo.Size.X),min(max(0,sbinfo.CursorPosition.Y+y_offset),sbinfo.Size.Y)) | |
134 | windll.kernel32.SetConsoleCursorPosition(self.hconsole,new_pos) | |
135 | def move_up(self,param): | |
136 | self.move_cursor(y_offset=-to_int(param,1)) | |
137 | def move_down(self,param): | |
138 | self.move_cursor(y_offset=to_int(param,1)) | |
139 | def move_left(self,param): | |
140 | self.move_cursor(x_offset=-to_int(param,1)) | |
141 | def move_right(self,param): | |
142 | self.move_cursor(x_offset=to_int(param,1)) | |
143 | def next_line(self,param): | |
144 | sbinfo=self.screen_buffer_info() | |
145 | self.move_cursor(x_offset=-sbinfo.CursorPosition.X,y_offset=to_int(param,1)) | |
146 | def prev_line(self,param): | |
147 | sbinfo=self.screen_buffer_info() | |
148 | self.move_cursor(x_offset=-sbinfo.CursorPosition.X,y_offset=-to_int(param,1)) | |
149 | def rgb2bgr(self,c): | |
150 | return((c&1)<<2)|(c&2)|((c&4)>>2) | |
151 | def set_color(self,param): | |
152 | cols=param.split(';') | |
153 | sbinfo=self.screen_buffer_info() | |
154 | attr=sbinfo.Attributes | |
155 | for c in cols: | |
156 | c=to_int(c,0) | |
157 | if 29<c<38: | |
158 | attr=(attr&0xfff0)|self.rgb2bgr(c-30) | |
159 | elif 39<c<48: | |
160 | attr=(attr&0xff0f)|(self.rgb2bgr(c-40)<<4) | |
161 | elif c==0: | |
162 | attr=self._orig_sbinfo.Attributes | |
163 | elif c==1: | |
164 | attr|=0x08 | |
165 | elif c==4: | |
166 | attr|=0x80 | |
167 | elif c==7: | |
168 | attr=(attr&0xff88)|((attr&0x70)>>4)|((attr&0x07)<<4) | |
169 | windll.kernel32.SetConsoleTextAttribute(self.hconsole,attr) | |
170 | def show_cursor(self,param): | |
171 | self._csinfo.bVisible=1 | |
172 | windll.kernel32.SetConsoleCursorInfo(self.hconsole,byref(self._csinfo)) | |
173 | def hide_cursor(self,param): | |
174 | self._csinfo.bVisible=0 | |
175 | windll.kernel32.SetConsoleCursorInfo(self.hconsole,byref(self._csinfo)) | |
176 | ansi_command_table={'A':move_up,'B':move_down,'C':move_right,'D':move_left,'E':next_line,'F':prev_line,'G':set_column,'H':set_cursor,'f':set_cursor,'J':clear_screen,'K':clear_line,'h':show_cursor,'l':hide_cursor,'m':set_color,'s':push_cursor,'u':pop_cursor,} | |
177 | ansi_tokens=re.compile(r'(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') | |
178 | def write(self,text): | |
179 | try: | |
180 | wlock.acquire() | |
181 | if self._isatty: | |
182 | for param,cmd,txt in self.ansi_tokens.findall(text): | |
183 | if cmd: | |
184 | cmd_func=self.ansi_command_table.get(cmd) | |
185 | if cmd_func: | |
186 | cmd_func(self,param) | |
187 | else: | |
188 | self.writeconsole(txt) | |
189 | else: | |
190 | self.stream.write(text) | |
191 | finally: | |
192 | wlock.release() | |
193 | def writeconsole(self,txt): | |
194 | chars_written=c_ulong() | |
195 | writeconsole=windll.kernel32.WriteConsoleA | |
196 | if isinstance(txt,_type): | |
197 | writeconsole=windll.kernel32.WriteConsoleW | |
198 | done=0 | |
199 | todo=len(txt) | |
200 | chunk=32<<10 | |
201 | while todo!=0: | |
202 | doing=min(chunk,todo) | |
203 | buf=txt[done:done+doing] | |
204 | r=writeconsole(self.hconsole,buf,doing,byref(chars_written),None) | |
205 | if r==0: | |
206 | chunk>>=1 | |
207 | continue | |
208 | done+=doing | |
209 | todo-=doing | |
210 | def fileno(self): | |
211 | return self.stream.fileno() | |
212 | def flush(self): | |
213 | pass | |
214 | def isatty(self): | |
215 | return self._isatty | |
216 | if sys.stdout.isatty()or sys.stderr.isatty(): | |
217 | handle=sys.stdout.isatty()and STD_OUTPUT_HANDLE or STD_ERROR_HANDLE | |
218 | console=windll.kernel32.GetStdHandle(handle) | |
219 | sbinfo=CONSOLE_SCREEN_BUFFER_INFO() | |
220 | def get_term_cols(): | |
221 | windll.kernel32.GetConsoleScreenBufferInfo(console,byref(sbinfo)) | |
222 | return sbinfo.Size.X-1 | |
223 | try: | |
224 | import struct,fcntl,termios | |
225 | except ImportError: | |
226 | pass | |
227 | else: | |
228 | if(sys.stdout.isatty()or sys.stderr.isatty())and os.environ.get('TERM','')not in('dumb','emacs'): | |
229 | FD=sys.stdout.isatty()and sys.stdout.fileno()or sys.stderr.fileno() | |
230 | def fun(): | |
231 | return struct.unpack("HHHH",fcntl.ioctl(FD,termios.TIOCGWINSZ,struct.pack("HHHH",0,0,0,0)))[1] | |
232 | try: | |
233 | fun() | |
234 | except Exception as e: | |
235 | pass | |
236 | else: | |
237 | get_term_cols=fun |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import sys | |
5 | from waflib import ConfigSet,Logs,Options,Scripting,Task,Build,Configure,Node,Runner,TaskGen,Utils,Errors,Context | |
6 | sys.modules['Environment']=ConfigSet | |
7 | ConfigSet.Environment=ConfigSet.ConfigSet | |
8 | sys.modules['Logs']=Logs | |
9 | sys.modules['Options']=Options | |
10 | sys.modules['Scripting']=Scripting | |
11 | sys.modules['Task']=Task | |
12 | sys.modules['Build']=Build | |
13 | sys.modules['Configure']=Configure | |
14 | sys.modules['Node']=Node | |
15 | sys.modules['Runner']=Runner | |
16 | sys.modules['TaskGen']=TaskGen | |
17 | sys.modules['Utils']=Utils | |
18 | sys.modules['Constants']=Context | |
19 | Context.SRCDIR='' | |
20 | Context.BLDDIR='' | |
21 | from waflib.Tools import c_preproc | |
22 | sys.modules['preproc']=c_preproc | |
23 | from waflib.Tools import c_config | |
24 | sys.modules['config_c']=c_config | |
25 | ConfigSet.ConfigSet.copy=ConfigSet.ConfigSet.derive | |
26 | ConfigSet.ConfigSet.set_variant=Utils.nada | |
27 | Utils.pproc=Utils.subprocess | |
28 | Build.BuildContext.add_subdirs=Build.BuildContext.recurse | |
29 | Build.BuildContext.new_task_gen=Build.BuildContext.__call__ | |
30 | Build.BuildContext.is_install=0 | |
31 | Node.Node.relpath_gen=Node.Node.path_from | |
32 | Utils.pproc=Utils.subprocess | |
33 | Utils.get_term_cols=Logs.get_term_cols | |
34 | def cmd_output(cmd,**kw): | |
35 | silent=False | |
36 | if'silent'in kw: | |
37 | silent=kw['silent'] | |
38 | del(kw['silent']) | |
39 | if'e'in kw: | |
40 | tmp=kw['e'] | |
41 | del(kw['e']) | |
42 | kw['env']=tmp | |
43 | kw['shell']=isinstance(cmd,str) | |
44 | kw['stdout']=Utils.subprocess.PIPE | |
45 | if silent: | |
46 | kw['stderr']=Utils.subprocess.PIPE | |
47 | try: | |
48 | p=Utils.subprocess.Popen(cmd,**kw) | |
49 | output=p.communicate()[0] | |
50 | except OSError as e: | |
51 | raise ValueError(str(e)) | |
52 | if p.returncode: | |
53 | if not silent: | |
54 | msg="command execution failed: %s -> %r"%(cmd,str(output)) | |
55 | raise ValueError(msg) | |
56 | output='' | |
57 | return output | |
58 | Utils.cmd_output=cmd_output | |
59 | def name_to_obj(self,s,env=None): | |
60 | if Logs.verbose: | |
61 | Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"') | |
62 | return self.get_tgen_by_name(s) | |
63 | Build.BuildContext.name_to_obj=name_to_obj | |
64 | def env_of_name(self,name): | |
65 | try: | |
66 | return self.all_envs[name] | |
67 | except KeyError: | |
68 | Logs.error('no such environment: '+name) | |
69 | return None | |
70 | Build.BuildContext.env_of_name=env_of_name | |
71 | def set_env_name(self,name,env): | |
72 | self.all_envs[name]=env | |
73 | return env | |
74 | Configure.ConfigurationContext.set_env_name=set_env_name | |
75 | def retrieve(self,name,fromenv=None): | |
76 | try: | |
77 | env=self.all_envs[name] | |
78 | except KeyError: | |
79 | env=ConfigSet.ConfigSet() | |
80 | self.prepare_env(env) | |
81 | self.all_envs[name]=env | |
82 | else: | |
83 | if fromenv: | |
84 | Logs.warn('The environment %s may have been configured already',name) | |
85 | return env | |
86 | Configure.ConfigurationContext.retrieve=retrieve | |
87 | Configure.ConfigurationContext.sub_config=Configure.ConfigurationContext.recurse | |
88 | Configure.ConfigurationContext.check_tool=Configure.ConfigurationContext.load | |
89 | Configure.conftest=Configure.conf | |
90 | Configure.ConfigurationError=Errors.ConfigurationError | |
91 | Utils.WafError=Errors.WafError | |
92 | Options.OptionsContext.sub_options=Options.OptionsContext.recurse | |
93 | Options.OptionsContext.tool_options=Context.Context.load | |
94 | Options.Handler=Options.OptionsContext | |
95 | Task.simple_task_type=Task.task_type_from_func=Task.task_factory | |
96 | Task.Task.classes=Task.classes | |
97 | def setitem(self,key,value): | |
98 | if key.startswith('CCFLAGS'): | |
99 | key=key[1:] | |
100 | self.table[key]=value | |
101 | ConfigSet.ConfigSet.__setitem__=setitem | |
102 | @TaskGen.feature('d') | |
103 | @TaskGen.before('apply_incpaths') | |
104 | def old_importpaths(self): | |
105 | if getattr(self,'importpaths',[]): | |
106 | self.includes=self.importpaths | |
107 | from waflib import Context | |
108 | eld=Context.load_tool | |
109 | def load_tool(*k,**kw): | |
110 | ret=eld(*k,**kw) | |
111 | if'set_options'in ret.__dict__: | |
112 | if Logs.verbose: | |
113 | Logs.warn('compat: rename "set_options" to options') | |
114 | ret.options=ret.set_options | |
115 | if'detect'in ret.__dict__: | |
116 | if Logs.verbose: | |
117 | Logs.warn('compat: rename "detect" to "configure"') | |
118 | ret.configure=ret.detect | |
119 | return ret | |
120 | Context.load_tool=load_tool | |
121 | def get_curdir(self): | |
122 | return self.path.abspath() | |
123 | Context.Context.curdir=property(get_curdir,Utils.nada) | |
124 | def get_srcdir(self): | |
125 | return self.srcnode.abspath() | |
126 | Configure.ConfigurationContext.srcdir=property(get_srcdir,Utils.nada) | |
127 | def get_blddir(self): | |
128 | return self.bldnode.abspath() | |
129 | Configure.ConfigurationContext.blddir=property(get_blddir,Utils.nada) | |
130 | Configure.ConfigurationContext.check_message_1=Configure.ConfigurationContext.start_msg | |
131 | Configure.ConfigurationContext.check_message_2=Configure.ConfigurationContext.end_msg | |
132 | rev=Context.load_module | |
133 | def load_module(path,encoding=None): | |
134 | ret=rev(path,encoding) | |
135 | if'set_options'in ret.__dict__: | |
136 | if Logs.verbose: | |
137 | Logs.warn('compat: rename "set_options" to "options" (%r)',path) | |
138 | ret.options=ret.set_options | |
139 | if'srcdir'in ret.__dict__: | |
140 | if Logs.verbose: | |
141 | Logs.warn('compat: rename "srcdir" to "top" (%r)',path) | |
142 | ret.top=ret.srcdir | |
143 | if'blddir'in ret.__dict__: | |
144 | if Logs.verbose: | |
145 | Logs.warn('compat: rename "blddir" to "out" (%r)',path) | |
146 | ret.out=ret.blddir | |
147 | Utils.g_module=Context.g_module | |
148 | Options.launch_dir=Context.launch_dir | |
149 | return ret | |
150 | Context.load_module=load_module | |
151 | old_post=TaskGen.task_gen.post | |
152 | def post(self): | |
153 | self.features=self.to_list(self.features) | |
154 | if'cc'in self.features: | |
155 | if Logs.verbose: | |
156 | Logs.warn('compat: the feature cc does not exist anymore (use "c")') | |
157 | self.features.remove('cc') | |
158 | self.features.append('c') | |
159 | if'cstaticlib'in self.features: | |
160 | if Logs.verbose: | |
161 | Logs.warn('compat: the feature cstaticlib does not exist anymore (use "cstlib" or "cxxstlib")') | |
162 | self.features.remove('cstaticlib') | |
163 | self.features.append(('cxx'in self.features)and'cxxstlib'or'cstlib') | |
164 | if getattr(self,'ccflags',None): | |
165 | if Logs.verbose: | |
166 | Logs.warn('compat: "ccflags" was renamed to "cflags"') | |
167 | self.cflags=self.ccflags | |
168 | return old_post(self) | |
169 | TaskGen.task_gen.post=post | |
170 | def waf_version(*k,**kw): | |
171 | Logs.warn('wrong version (waf_version was removed in waf 1.6)') | |
172 | Utils.waf_version=waf_version | |
173 | import os | |
174 | @TaskGen.feature('c','cxx','d') | |
175 | @TaskGen.before('apply_incpaths','propagate_uselib_vars') | |
176 | @TaskGen.after('apply_link','process_source') | |
177 | def apply_uselib_local(self): | |
178 | env=self.env | |
179 | from waflib.Tools.ccroot import stlink_task | |
180 | self.uselib=self.to_list(getattr(self,'uselib',[])) | |
181 | self.includes=self.to_list(getattr(self,'includes',[])) | |
182 | names=self.to_list(getattr(self,'uselib_local',[])) | |
183 | get=self.bld.get_tgen_by_name | |
184 | seen=set() | |
185 | seen_uselib=set() | |
186 | tmp=Utils.deque(names) | |
187 | if tmp: | |
188 | if Logs.verbose: | |
189 | Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') | |
190 | while tmp: | |
191 | lib_name=tmp.popleft() | |
192 | if lib_name in seen: | |
193 | continue | |
194 | y=get(lib_name) | |
195 | y.post() | |
196 | seen.add(lib_name) | |
197 | if getattr(y,'uselib_local',None): | |
198 | for x in self.to_list(getattr(y,'uselib_local',[])): | |
199 | obj=get(x) | |
200 | obj.post() | |
201 | if getattr(obj,'link_task',None): | |
202 | if not isinstance(obj.link_task,stlink_task): | |
203 | tmp.append(x) | |
204 | if getattr(y,'link_task',None): | |
205 | link_name=y.target[y.target.rfind(os.sep)+1:] | |
206 | if isinstance(y.link_task,stlink_task): | |
207 | env.append_value('STLIB',[link_name]) | |
208 | else: | |
209 | env.append_value('LIB',[link_name]) | |
210 | self.link_task.set_run_after(y.link_task) | |
211 | self.link_task.dep_nodes+=y.link_task.outputs | |
212 | tmp_path=y.link_task.outputs[0].parent.bldpath() | |
213 | if not tmp_path in env['LIBPATH']: | |
214 | env.prepend_value('LIBPATH',[tmp_path]) | |
215 | for v in self.to_list(getattr(y,'uselib',[])): | |
216 | if v not in seen_uselib: | |
217 | seen_uselib.add(v) | |
218 | if not env['STLIB_'+v]: | |
219 | if not v in self.uselib: | |
220 | self.uselib.insert(0,v) | |
221 | if getattr(y,'export_includes',None): | |
222 | self.includes.extend(y.to_incnodes(y.export_includes)) | |
223 | @TaskGen.feature('cprogram','cxxprogram','cstlib','cxxstlib','cshlib','cxxshlib','dprogram','dstlib','dshlib') | |
224 | @TaskGen.after('apply_link') | |
225 | def apply_objdeps(self): | |
226 | names=getattr(self,'add_objects',[]) | |
227 | if not names: | |
228 | return | |
229 | names=self.to_list(names) | |
230 | get=self.bld.get_tgen_by_name | |
231 | seen=[] | |
232 | while names: | |
233 | x=names[0] | |
234 | if x in seen: | |
235 | names=names[1:] | |
236 | continue | |
237 | y=get(x) | |
238 | if getattr(y,'add_objects',None): | |
239 | added=0 | |
240 | lst=y.to_list(y.add_objects) | |
241 | lst.reverse() | |
242 | for u in lst: | |
243 | if u in seen: | |
244 | continue | |
245 | added=1 | |
246 | names=[u]+names | |
247 | if added: | |
248 | continue | |
249 | y.post() | |
250 | seen.append(x) | |
251 | for t in getattr(y,'compiled_tasks',[]): | |
252 | self.link_task.inputs.extend(t.outputs) | |
253 | @TaskGen.after('apply_link') | |
254 | def process_obj_files(self): | |
255 | if not hasattr(self,'obj_files'): | |
256 | return | |
257 | for x in self.obj_files: | |
258 | node=self.path.find_resource(x) | |
259 | self.link_task.inputs.append(node) | |
260 | @TaskGen.taskgen_method | |
261 | def add_obj_file(self,file): | |
262 | if not hasattr(self,'obj_files'): | |
263 | self.obj_files=[] | |
264 | if not'process_obj_files'in self.meths: | |
265 | self.meths.append('process_obj_files') | |
266 | self.obj_files.append(file) | |
267 | old_define=Configure.ConfigurationContext.__dict__['define'] | |
268 | @Configure.conf | |
269 | def define(self,key,val,quote=True,comment=''): | |
270 | old_define(self,key,val,quote,comment) | |
271 | if key.startswith('HAVE_'): | |
272 | self.env[key]=1 | |
273 | old_undefine=Configure.ConfigurationContext.__dict__['undefine'] | |
274 | @Configure.conf | |
275 | def undefine(self,key,comment=''): | |
276 | old_undefine(self,key,comment) | |
277 | if key.startswith('HAVE_'): | |
278 | self.env[key]=0 | |
279 | def set_incdirs(self,val): | |
280 | Logs.warn('compat: change "export_incdirs" by "export_includes"') | |
281 | self.export_includes=val | |
282 | TaskGen.task_gen.export_incdirs=property(None,set_incdirs) | |
283 | def install_dir(self,path): | |
284 | if not path: | |
285 | return[] | |
286 | destpath=Utils.subst_vars(path,self.env) | |
287 | if self.is_install>0: | |
288 | Logs.info('* creating %s',destpath) | |
289 | Utils.check_dir(destpath) | |
290 | elif self.is_install<0: | |
291 | Logs.info('* removing %s',destpath) | |
292 | try: | |
293 | os.remove(destpath) | |
294 | except OSError: | |
295 | pass | |
296 | Build.BuildContext.install_dir=install_dir | |
297 | repl={'apply_core':'process_source','apply_lib_vars':'process_source','apply_obj_vars':'propagate_uselib_vars','exec_rule':'process_rule'} | |
298 | def after(*k): | |
299 | k=[repl.get(key,key)for key in k] | |
300 | return TaskGen.after_method(*k) | |
301 | def before(*k): | |
302 | k=[repl.get(key,key)for key in k] | |
303 | return TaskGen.before_method(*k) | |
304 | TaskGen.before=before |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | from __future__ import with_statement | |
5 | import os | |
6 | all_modifs={} | |
7 | def fixdir(dir): | |
8 | for k in all_modifs: | |
9 | for v in all_modifs[k]: | |
10 | modif(os.path.join(dir,'waflib'),k,v) | |
11 | def modif(dir,name,fun): | |
12 | if name=='*': | |
13 | lst=[] | |
14 | for y in'. Tools extras'.split(): | |
15 | for x in os.listdir(os.path.join(dir,y)): | |
16 | if x.endswith('.py'): | |
17 | lst.append(y+os.sep+x) | |
18 | for x in lst: | |
19 | modif(dir,x,fun) | |
20 | return | |
21 | filename=os.path.join(dir,name) | |
22 | with open(filename,'r')as f: | |
23 | txt=f.read() | |
24 | txt=fun(txt) | |
25 | with open(filename,'w')as f: | |
26 | f.write(txt) | |
27 | def subst(*k): | |
28 | def do_subst(fun): | |
29 | for x in k: | |
30 | try: | |
31 | all_modifs[x].append(fun) | |
32 | except KeyError: | |
33 | all_modifs[x]=[fun] | |
34 | return fun | |
35 | return do_subst | |
36 | @subst('*') | |
37 | def r1(code): | |
38 | code=code.replace('as e:',',e:') | |
39 | code=code.replace(".decode(sys.stdout.encoding or'latin-1',errors='replace')",'') | |
40 | return code.replace('.encode()','') | |
41 | @subst('Runner.py') | |
42 | def r4(code): | |
43 | return code.replace('next(self.biter)','self.biter.next()') | |
44 | @subst('Context.py') | |
45 | def r5(code): | |
46 | return code.replace("('Execution failure: %s'%str(e),ex=e)","('Execution failure: %s'%str(e),ex=e),None,sys.exc_info()[2]") |
0 | #! /usr/bin/env python | |
1 | # encoding: utf-8 | |
2 | # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file | |
3 | ||
4 | import os,sys,traceback,base64,signal | |
5 | try: | |
6 | import cPickle | |
7 | except ImportError: | |
8 | import pickle as cPickle | |
9 | try: | |
10 | import subprocess32 as subprocess | |
11 | except ImportError: | |
12 | import subprocess | |
13 | try: | |
14 | TimeoutExpired=subprocess.TimeoutExpired | |
15 | except AttributeError: | |
16 | class TimeoutExpired(Exception): | |
17 | pass | |
18 | def run(): | |
19 | txt=sys.stdin.readline().strip() | |
20 | if not txt: | |
21 | sys.exit(1) | |
22 | [cmd,kwargs,cargs]=cPickle.loads(base64.b64decode(txt)) | |
23 | cargs=cargs or{} | |
24 | if not'close_fds'in kwargs: | |
25 | kwargs['close_fds']=False | |
26 | ret=1 | |
27 | out,err,ex,trace=(None,None,None,None) | |
28 | try: | |
29 | proc=subprocess.Popen(cmd,**kwargs) | |
30 | try: | |
31 | out,err=proc.communicate(**cargs) | |
32 | except TimeoutExpired: | |
33 | if kwargs.get('start_new_session')and hasattr(os,'killpg'): | |
34 | os.killpg(proc.pid,signal.SIGKILL) | |
35 | else: | |
36 | proc.kill() | |
37 | out,err=proc.communicate() | |
38 | exc=TimeoutExpired(proc.args,timeout=cargs['timeout'],output=out) | |
39 | exc.stderr=err | |
40 | raise exc | |
41 | ret=proc.returncode | |
42 | except Exception as e: | |
43 | exc_type,exc_value,tb=sys.exc_info() | |
44 | exc_lines=traceback.format_exception(exc_type,exc_value,tb) | |
45 | trace=str(cmd)+'\n'+''.join(exc_lines) | |
46 | ex=e.__class__.__name__ | |
47 | tmp=[ret,out,err,ex,trace] | |
48 | obj=base64.b64encode(cPickle.dumps(tmp)) | |
49 | sys.stdout.write(obj.decode()) | |
50 | sys.stdout.write('\n') | |
51 | sys.stdout.flush() | |
52 | while 1: | |
53 | try: | |
54 | run() | |
55 | except KeyboardInterrupt: | |
56 | break |