MZ@ !L!This program cannot be run in DOS mode. $tQh000000UV0UV0UV-040Z0Z$0Z)0UV=0000D[0D[10D[10Rich00PEL@\ L c` @@ctU`SpS@` .textJ L  `.rdataF `  P @@.datahd@.rsrcr@@.reloctUVt@BXTUQSVWUMGȋ7;vG4v;F;wjV>؃GtPwSow蔧G_7_uVuPo w_^[]Uj {U@@J AB ]UQVuEWPjV ΅t<Htt3 u3_^]j2UQSVuW=Rt @vEPjV! t]]33sHtt3 00t S׋XjIG3_^[]j1UMVHtt3 00vҥVFF踥3^]UW}蝿ȋAtt3 HtJPA| Et8| HEȅt)VQzw P@VWG ^z &IzO @@AGG x ~U_]U 3SVuWj(j~цO<؀KCO@ _@C CRCRCCF @GFF x ~eUhIVCC2taIzN @@AFF N x ~ UN @AFF x ~TjVGjVݽH?w&@$ @@@ b3D$ C @P詣3C$9|$ 3ɉL$C$ΉD$gǙRP_N T$F jL$F y~AxtC9tCL$G L$;|$ |_^[]f?@N@G@W@USVڋW\$贼H?w,@$@xx aD$3|${PzӃ3ۉB3ɉL$BΉD$@&ÙRP^N F ΋~ jj^F ػHt,t3(Ћ{lFx ~R衻L$΃F ~ 腻jj ^F cHt,t3(ЋlFx ~&R,L$A΃F ~ jj]jVF RL$ A ΃F ~ ںjj_]jVF L$0 A~ ~ ItHI:utQ:Puu3T$uD$@~ T$L$GCF L$;\$_^3[]fh@w@p@@UMSVHtt3 00^~"W3F t謟 u_v 蘟3^[]UE xSVWqC{ D$+L$KC C up֋tK @@ACC x ~OEuC PtK @@ACC S x ~ OS fCljfCl蠸@tuv膸Ht,t3(Ћ)iCx ~IOO:utN:Huu33ɅL$t$SPD$_^[]Ë:u&tN:Huu33_^[]3_^[]UQSVڋW\$ 覷=R@<胷H?w(x@$h@XX Q\3ۿ;r>f6jWYN T$ F QF uG;v3_^[]ø_^[]ÃHt(uыЋgFx ~M貶tS_^[]Ð@@@@U$SVuWID$ rN @@AFF ~ x ~ M~ WYGHt,t3(ЋfFx ~LŵF IΉ\$ |qN @@AFF ~ x ~ vL~ wW-YG\Htt3 88F ?|$ttu 3_^[]ËNhIjjI(WЋhIЋ333ۍJ\$T$D$;WW 33T$,3|$(D$$;BZT;߅{t|$ uT$,3@L$ 2pN @@AFF ~ x ~ ,K~ -WWӋGSF {tL$;C DʉL$K L$ D$ t{ tSЋ3F @F ~ 蔳OQ΋NEN t#ӋN uy~ 붍AF K 39K L$ D$$|$(@D$$|$(u%T$,~T$\$B|$ȃ /T$\$BD$ |$T$\$|$ L$ t 3҅DʉL$ V 39L$ _ BF ^[]UM f. SVW}7D{tعtGRPTN jF ΋F E@F F @F 3 te_^]_3^]UMUVu uV^]USVWUG @G ϻ許O +Q)LEO jjW uG P6T؃u E3U0jtTЃu3*BuF΅t ȋAuQu S|TEU0=_^[]j"UL=ȗTSVD$ X@WL$@@ @uhC?ȗT|$ u_^[]~IL$XIIfD$XD$`AIuI IA$IjAf(IjVfA 腷 Ph'W jj4W jj+Wt jj-Wg Sh'WX D$XPh"'WEN I(h,IjjRЋ蒻8I3kN @@AFF ~ |$x ~)F~ |$&؃{Et L$33 WRN 39PƒtPQQӋ ׮=Rt@t \$ jjQSl jj@S_ \$ ~ E~ =Ћ艮=R)@<GF U΋~ XOQ΋HEN pjjV贵 DIϊ:utA:Buu3uFjVϱu6F΋V |$W+7h''S] F ׋=Rt.@<u$t$׋D$0h''Sq t$Vh'S^ h @h+NSK >t/jj+S9 VhI'S* h`@hXNS _F^[]jj jjUQS‹VWEt57w|TW|Tu܋Et?_^[]UEPju up0]UjjjuhIuUju# ̗TA@"t@AAXp+@AdAhAp ]SVڋWHt,t3(ЋVFx ~<¥8Tt,PhIj菌P j|PΏWhIjcP jPP袏F _^[UQVu9Ht*u0ЋUFx ~<hIjV+ tV٤ȋF jF V fFlfFl衤=Rt Ht@胤=Rt@4IhIV/ jPVVR^]U SVWT$ Gw +,@FGG +ڃx ~:jSW蔦 =̗Th+@j诗u3 Ӌˣ+G L$ W Au+щt$T$+W PRD$@P D$ uOW 9QsQjjGjSWD$ G _^[]UDISVڹLIWDNPjjI(EЋ2Ht(u*ЋSFx ~9Ң8uۿXI\IDj蝉PW衑j茉 PތjyPD$hP& u_^[]ÃF L$QDAu+t |  uID t&|$=uD$PhhIV _^[]ÅuI]QT$A]N @@AFF x ~8_^[]UVW褡Ht0t339ЋERFx ~e8ixuHH jD$ D$ hIPhX@VL$ 覹SHt+;6ЋQFx ~7xuPP  `I@:utP:Quu3F 3ҋ68IB\N @@AFF ~ x ~ <7~ ΃:O;s  ;r;sfD;rFx 16%_^]UVWF9N sfDF @F 9N rN .u _^]ÃgHt,t3(Ћ PFx ~*60PhtIVЃ z BujD$ +hID$T$PhX@VXujjVu F F jjVU ǃF _^]UTVuWD$ TuW3ҋ׋AFN +qNhIWjI(@Ћ3~ ΃O;sD  ;rV ;s;rV FjD$+D$+ыΉT$+V RP@ pHt,t3(ЋNFx ~349PhIV T t,QhIjPC jP3WhIjȃP j赃PBF9N sfF @F 9N rjN kPh8IkjV P訆D$T3_^]UEPjuu u6pQH]U]U$SVuWjjVD$D$ d hIPĕ؃΅uUIyWN @@AFF N 9X ~ t2N xSAF _^[]ÿR=RtH3ET$P3EP3EWE tXjjPW貹 Sh'W裹 h5@h+NW萹 薻D$D$Ph W" T$SBD$t0L$,Q藼PhI$<hP/$0I7VN @@AFF x ~41t$(3fnD$F _@F ^[]j USVuWD$ ׋֙=RtH3ET$P3EP3EW jjPW2 8؍D$ Ph Wƺ T$8uMD$΅u IU T$ PtTN @@AFF x ~/IL$IL$u>LIMN @@AFF x ~(T$UlD$ PhTIS D$DPh\IV艜D$@ ~PhdIVr hIcMN @@AFF x ~`(T$ 5thWHt,t3(ЋAFx ~( PhIVߛ jjV袓 F {D$(8tt$$Ph IV谛]D$,jhIV{ u  jhIV{ u 3;>\Fj\EPEmt/NMt)+uFPEVuEPzE0!EEENfDFuE+MQhjPW`I}3ɅE}8MtuD}u{tUtQ>\MQjjFEjPWE `Iu/E@P\DEPVjjuW `ItVD_^C[]ËE_s^[]U VuWjjV{e tbЍM }uF x׋N @@AFF x ~WCu`I_^]jDU`sxSVPh`I3ۅÅtIjjh@PjPjh`ItuV @@BFF x ~^[]^3[]US]WjjS(d V54`IjjE֋ϋuAAuj+ȍEPQWu=8`I׍EPVD`IjV5<`IjEPhPu@`IuujEPjh8Iu׍hIPwyƄK ^@@ACC x ~_[]jrU$SVWD$D$PhjhIhI`IuPD$D$PD$4PD$(PjhIt$( `It$`I|$ uD$0PHD$jhI8bInV AWVjhI4bILD$,PD$PhIW_^[]_^3[]UVu$I=V @@BFF x ~:^]UQVh,IhN uWhIAF VDY _^]AF _^]jUQSVW}T$ j;W؃u5uF X׋ N @@AFF ~ 9X ~G;Ë+u I  PN @@AFF x ~~ MlIF B N @@AFF N x ~ <N D$ uAЋ N @@AFF x ~贤Fx ~LHt,t3(ЋFx ~L7N u A߉F C#l3_^[]ÍAF `@@FF ~ x ~ F~ GLjF V fFlZfFl_^[]USVuWjjVS؃ t|FN + |J׋K=Rt@t!jWVMS ΅t3P|uFGN +;~3_^[]_^[]jHj:UcfS]jjSR EhPPj~ uDC VW@C I0IVMP7uhISU_^[]ÍK @@ACC x ~[]jbU"eSVuWjjVR Ch$PjWjhaI,$Pd`It F @F _^[]`IjjD$D$PhSjh`ItTjjhD$Pjt$ jh`Iu#If8IfD$0D$(ID$ t$ h`I#T$N @@AFF x ~_^[]jcjWjIUsRS]VWjjS> 5jjS> ˅*V W PPDqu I$OGuflIfOOuf3U88=t<P4p=Q$pU;u=/DGU=uu<:/u ;]t,;t"C5MUEUM‹U}uUEMP=K@MSDusHA@E‰}{L[PADEAXAHEljALE_AP^[]SVW~X8t2ҋ~X8u2ҋv2ҋm2ҋdVTWVTJVT =VT0VT#N@с Ћ ND ЋV@ Ћ NH ЋVD Ћ NL ЋVH Ћ  ЉVLVP‹  ʍF@ ~P_^[UD$S]VWPjS |$3DŽ$#EgDŽ$DŽ$ܺDŽ$vT2DŽ$É$$t)DL$@@$vt $܍L$@T$pNvR -SB-SNB-SB-SNB-SB-SNB-SB-SNB-SB-SBQj(T$D$@_K @@ACC 9x ~_^[]jzUSVuW=Rt@vjjV4؃ t}3ۺ=Rt@vjjV t[3t>t:ύQAu+QWS9V 3Ʌ_ BF ^[]_^3[]jyjyVTybh-Sb-SEȀ90tjPvPW u h-S,-SEȀ90u3Tt#SSj4`I5|`IPSj4`IP[^UEPj4`IPx`IuEVuN QAF ^]Ujjju3]Ul!SVUEWt9PV1u%hIVtM؋QQlc3EuVh-S_^[]ËP4H0EM̉UЅWfE}]}p ЋȃjWSw IyM֍I v!vjEEu td@uHDPHA;rYz PEpL#u-E t @}WjuXMyH}ALIDEU@LE@DBrBU@@r E;z4rw;Z0rtNF?MJ@Au#t׃y ttFt H @LMEM3VWSۖ tH83VjPuԍh-SPt Qt'Ft!Gx=w ֋l @<$ ˆAV{G _^[Y]UU SVW}Mw ؋NJNJFBW B@t9 Yt/RBt&Gx=wlG _^[]Ê@<$ ÈAG _^[]UE M@VuWV +Ѕt`f~luYFHNEAfFnf@fFnf;rf;tbf;sc}W'uDfFn}fFlW+fFluFN 9HsH_^]h:SV"UE VuHfFlQ%+fFl^]UU SVuWu3 +~ M V AE+щT$f~lVT$ BEBD$+F BF\BFt ~\ȿB"f#f fJ"fFnf@fFnf;rf;f;]΋T$SI&uCfFnD$ f!H"@F\3 +V D$]WRP@\$ 0 uNV 9QsQ_^[]h:SV UTE 4ID$ AESVuD$D$ D$ EfFlWv\Eȉt$$ED$\F +F PD$,L$dPD$D$ D$@D$HD$LD$TD$XD$`D$4D$< /v \$0|$(D$ jSWv3Ʌ}E)N t$DD$8D$LjD$DSVw3jE)G E\$lt$dxSVw3jE)G E$$xSVw3@uEË\$ )G fFluPF xrDNSjI(蔈O GB@t;uNy=w Btg_^[]UMA VxFuc@MMEp E EEEEE裧}F E uuE jPuUEE3PE^]ø^]UE@]UE S]VW3s '$@F?_^[]ËN3N F?N+ȉF N_^[]3ҋ|_^[]Ë~ ~ _^[]Ë~ ~_^[]ÊF?VN шE EF?u&;O+щN ˉVc{- ȍ;ȉM M+ЉF VC9x ~ 2{M E F?~I~=uC_^[]Ë~pEFp_^[]Ë~t(9MMMNt_^[]~?_^[]Ã_^[]Ð@@"@2@B@U@@@@@UMEUU VuWN Q~EN _^]UE VW}| Ћ:'u#w IPޜ@@FG Gx ~y_^]UQU VuV P=F ^Y]UU tMA@A]ËE@]UUEJAJE ]UQMS] VWwrqCPj3^N<OGN@M~@_ GRGRGGA 8@GAA x ~xG_^[Y]שUU VuWH?t2&u|U|tA;jIыN _F ^]ËM|Gx ;O =D G@DuN <9S_F ^]ÃtN _F ^]3_^]UU 3SVW}3ۋωE#H?t1&MC;I3@uB ;p T @@U tu<9SG G t8O A@tfct^BtVOy=v=A<$ ĈC_^[]Åt3B@t+E;u!Oy=wBt2b_^[]3_^[]UU MЋJ?t&t3]ËE]ËU MED ]UU SVW}UE4V BEuB9ujjxK N AN A;t A N B@t!A;uOy=wBt _^[]-a_^[]̋VP r8tA+B0D^Ã^UU St]u33ҋMA@"t@AEAdAhÉQXAp[]UE@X]UE@p]UE@d]UE y3]VuN~V4@;tIHuF4;tE^H`]3ҋ^]USVuWMG"y7ދ@ HG++;E _^H9S[]ËG3ɋWމE@ E+P0J9H ~&@uW D$AW M uv`t$BT$<u23t$щt$Vuejfu D$ttD$O G uWBG +O JjLu t0~&F 3ҋwj j@8D$赟N<ЀT$JBN@ V@3BfBB BBRBG D$0D$8@ED$ G @ 9p(D$0D$ʉD$QL$ L$Py=Ru0D$ϋT$D$ D$D$$D$ PD$,w(D$4D$ F@ ;p|D$_^]ËG @G D$_^]USVWڋ]}U3ɋw B~ZW@jZWdj|Z[{ sjWVs3t$E)C ~ t#F4ΉFNF`΋V jPjh8FPD$ pЃ_^[]UQSVW}_{ ~ awj|jjvЃu29ыbj|jjvЃF |׍pCFFF FF0FxdžF=FdF`FHF@FDFPFLF\FXFTFhF8F FlFpFtdždždždždždždždždžt$jbt 3_^[]UQEHI|~Y]UQVt.tF @EF ^]j:S؀ FM@@AAF ^]UQSVW~0u+~^W|z0t0J AB F @w|~0tՋF0jXDF0Pxdxt]N L$ t%t A)j:S/L$@@AFN 9HsHGxVЃeU`AnEA0EEVA0EjPUMEuu uVUEF0fEfFnE^]U VUBWN`~ M=S‹PSE裍UF E;}+ȋF [DuEN$F FF +ljV`F F [t+ǃF IuFt;fDH+σN H+σN @"tH+σN H@u_^]ËΌUSVKыs Mt;rBrRu+s Fƙи@B ;OЉU9C`~ =y t:WQ z t+jj$dMfCy Oσ Mu_U;B ;S`}L^[]UpSVU^X~tN +V EW~UW+V EEEF+UU}=@1N`@Bh @B;O;M;ыVN @GEPFtfO"VӋF EFtGF EF f!G"_^[]úFC\h\IV!UQSڋVWUBp{ t:t(u+r jUCJ @ΉBCM@BM3CBt9U ;=~"+΋fff@D@uUz _^[]3ۅ~+΋ڍ@D@u;}ȋË+f@u롃} REz _^[]Ë} ~+΋׍@D@uU3z _^[]USVWG?@$&F+F YF+~ ߃x ~kXN`@BfV  +V @B=@BO;M;W\~ j׋,ЃJF ;vHI;wF F G?0^ +@ KEPF+F U;iF+~ }x ~ WUN`@B NjEF+F =@YF+~ ߃x ~GWN`@BBV  +V @B=@BO;M;38~ FX u(j$S3ҋ؃FX FCC fFfE^fC ;F @C3fC"Fptj3ҋVUN P+Qe_^[]ËF +F Ѝ =@B@BO;M;ot~ }MyQtfN M+3MEt2;}.N AF EȋE@EAM;|C;}?+ЋF @F u(;}F C@F A;|GEFX u(j$S3ҋ蝆N؃Y NKC fFfEM^fC EC;CF E@0CfK"Fpt93҉CCH"t@@?<%u "QfC"jC_^3[]úh:S׋Ch\IVUVWfFnf@fFnf;rf;t1f;s2uufFn_^]h:SV^bUVufFl~fFl^]UQE SVW}tVw΋F"t%fF"FOG\f~ u G 9AsAvFRWЋO P+QwG4;bF"uSΨt%fF"FOG\f~ u G 9AsAvFjWЋO P+Q8FNM XÃ?#A$AG O E G Htuxt3ɃG F"y 5fF";tgFaW @U +ЋE +@~ ωG JO FA@rFG wG4;_^[Y]A1AA~AAAUQE SVuWV ~+Ѐ~u!jupQ_^[]FGF G"t1jVy_^[]ËGtwjVЋV ؋˃ +SR׋FjV;_^[]U SVW}GlD$Gu>G49GtA:SϋEw +w u@@FG _^[]<t;SċE t f@nf@fGnf;r:S3AfGlEPwD$D$ u "@wt F"u4vuw GF^_ pD$t$t G @(j:Sr G@@CCwG ϊF"$Gt3fGlFAG\ύD$ PD$D$ %8j:SUr G@@FGNO HD$ L$fOlfOn_^[]UM3f9Al]UMVfylqv A;H|tNAA+A F"Ft3^]ËEFtEFU A R+ºh4;SQh`;SQUSVWuGw\EGtEGlEEuG\N؃tEw u nVӋ EGϊEGtEfGloEG\_^[]Éw\_^[]USVu WB>t G@G3D$Pw GwЃ tL$tIG@G~4tjbW[SV86 @t=t HUSEB}L$D$$|$t$ GjT$L$ T$9mG t$0@FGO +:G`=@BN+O Q@B;O;M;ы6 O AωG mjЉF L$ 耝Gt"jtWoRuuWh;Sh;S}FSv8PFPmD$38^vNL$fDwjjjvЋȃu(9tXPUMjjjvЋȃt8F ACA@D$D$D$@;|_^[]úuWh;Sh;SVZjCh\IWUASVWuQ P_^[]$<xupp xT$gcЅtL$+׉L$BL$L$-T$aЅtD$+D$BL$3ҍF;u8uT$L$_^[]D$_^[]_^3[]U4SVW\$~|$8F$<xupp XT$ ybЅtL$ L$0+ӋL$$BL$4|$8-T$(`ЅtD$(+D$0|$8B3ҍF;t$0b\$D$0D$0$ \$(T$(f.ŸD{EtX~XSf/SrA hSf/v3({S_^[]Ë\$FC_^[]_^3[]UESVW3uP֋Bvȃy(HtyAusC3uȃtZQƒ<t4Et3U Uxu G}GE _^[]ju ыuVv_^[]ËE _^[@]h;S֋h;SSwU SVD$\$ W}t$ t9KAFttn\$jӋu~N<މ\$Et3UTuvD$@D$=t$ [t$ RuuӋ@QE C@@t"St@tNSAPCYP_^[]ËU B@t(6^t@tL$ I^APFqP_^[]ËL$ ju uSu_^[]ËL$ h;SL$ h;SQUQySVWquyy zBEuZZ PVuQ@ƍP@u+;t2;t$M@QV+M+t_^[]_^[]3;_^[]UQSVuWWƒeN<|;u;~|;_^[]˃ =@w#ru׋w3f/_^[]f/hSsf/S+m;|;_^[]u3f/_^[]f.ɟDNL$  =@w&ru ы3f/_^[]f/ hSr3_^[]f/ Sr(9T$ |;v3_^[]Ãu"F$<u3Ʌ_^[]js ׋Vs t%C Ht8w_^3[]V׋-UQSVuWWƒeN<|;u;~|;_^[]˃ =@w#ru׋w3f/_^[]f/hSsf/S+m;|;_^[]u3f/_^[]f.ɟDNL$  =@w&ru ы3f/_^[]f/ hSr3_^[]f/ Sv(9T$ |;r3_^[]Ãu"F$<u3Ʌ_^[]js ׋Vq t%C Ht8w3_^[]ËCjf H"s WLq uC Htu8t3ɋCf1P"x3_^[]V׋U SVuWVƒ?O?;tvO;u^uYujT$t9|$\$~uFjT$tD$L$;u;t.3_^[]Ã)A$t)A;uڋG;FuҸ_^[]f.Dz_^[]Ë6;tҋJ ;N ur;ust:qtB:F`tB:FOtB:F9;_)It A uCluvH>;It A uClu6HA CPljs ЋVWmC Hk8Y_^[]Ë3;_^[]f'Ab)A'A(Aw(A'A(Ab)AUDSVWT$|$O L$ Atu\QƒtuJQXL$ QDAxuxAQXqAjωD$ kxuT$jkx jVt$$ЋVlyDquxu Ayu T$|$\$;~RFtu>L$WT$xuHH ;eC|$\$;|L$ +ȉL$ (w_\$ 3ۋxupp VPD$0PTT$, JރT$ ɋ|$T$(\$W|$aL$3ҋD$Pyjw8Nnȉ\$(G<$L$$3ۈAAG@D$O@qt$ ADA @xuxx WPAP/TL$, I߃L$ ɋL$$Ƌ\$|$t$ @@FO T$++ˉT$L$ O `_^[]h$1Єt>D$@rBT$\$0J Jrt$T$\$0 Jrt$t$,‹L$t  %tҋPRыP@ t$,‹L$t  %tҋPыPFttu>utu>t3T$Jt\$0t$J1ЄtD$@@T$JT$\$0 t$JxD$Httu8utu8t3ɅtT$t$B%D$P2ȄtD$PыL@D$P\$0T$t$BJT$tƉG R֋t$T$\$0BG rt$ot։W j֋OL$@Q1T$D$(@ @AD$HD$P@ x~ Rb?3;t$Hs$|$(3fA80;T$Hr|$TT$@\$0BT$+ƃD$(BG +ƋT$@D$(G FBfN" Fw^~}N F$~|$ |$T|~ vF9D$ V|;NF;D$ B| 9N7T$BD$ FN0F4F8t$F 3f/V(Xvf/f/T$BN0F8t$~F<~(2N$V T$@L$(D$  |sQT$\~Nu$0$0$0f/D$0v'|$(L$XT$\:||$@s123ɺL$XT$\9L$(|9L$@rAT$\L$XD$ tWfD$8D$ACA7A@A8A9A:A;AQ=ACADA EACEApEAFAEFA+GAGAGAHA-IAIAGRAbJAAKAMAMAMA@OAQAUVWFf"@f UA$TAVt BtF NGF@Nt{AtufF"v_^]FNG_^]ËF NG_^]ËGLFwL_^]ËGLFwL_^]ËGLF(wL_^]ËGLFLwL_^]TATATA>TATATATATAUSVM uW3ENFEE]9yv8]3A D@tBtEiMG;yrӋA];+؍pKCDʋF@utF@tv nt*~Out MF3Ƀ@tEt.F@t%EtVBtME cMUz=uuJPENrP_^[]Ã}tBXAEJX_^[]Ã}t B\AJ\E_^[]U SVW]C|@t3>Ct@t Ћ=F$<0jkPlEjvQ\MucK s3;KىM;fF@~utcF@tZF QtVBt :Mu6F@t/$R<utMƒEȉM ;r]=uGPC_PGTC_TuӋG\C_\K C3ЉMU9Kv13C D0@t0Bt qMAM;Kr׋CU;sn+ЍpJBUNF@utE@t=F 4tAtыFU@tF@t ЋU Uu{uC3ҍP_^[]ÊKC_^[P]U SVW\$FDt @tFDVHt Btv39~~+3ۋF,D@tBt L$QG;~|ۋ\$39~ ~F@t Bt&G;~ |V3~&F4t BtVG;|~ 3ɉL$~33fF<tBt L$L$~ A L$;|ԋVF N HHFF_^[]UQSVW{LGO!\A$h\AG׉CLC_^[]ËGCLW t Bt#O3҉UtKw@t-A;t{=t A B@tBtOE9E|C_^[]ËG3ɉCLWMt/wF@tBt MWAƒM;|@C_^[]ËG(CLCPG({Pgw uC_^[];w sF@tBt#;w r{=u9G`G ;sF;r9,u$tChG,{h {>tG G`xC_^[]ËGL׉CLC_^[]ZAZA[AN\AH[A^\ASVWfff~X3FXׅt0Tt~Lt ~Luׅuԅu_^[U SډM]t|VWK s;s[]D~tCF@t$J<ut.%tF@FtF@tF ;r}E};,_^[]UQVWF" aAS$`AFV0jP;FϋV4jP;FϋV,jP:FϋV8jP:F ϋVEt>W}Ot/]BȃMuM* $ ÈB>u_39D^[]UVujV fFl ffFl^]UVT$W~O`G`G@O@QQG=,<w G<$ ˆAAT$L$@jΉD$3ЃJu}FtD$ G?D$ FtG?F jaAF D$@FF f H"΋F +F Pj蔷N f!Q"L$ NtL$ O?t|$ u_^]Ãu-N A$<uAt/F ~ ϙ9F}F ˙+"N +NF=3_^[]Ã~`t~>ti_^[]F=_^3[]f5gAWgAgAgAhAQhAhAfASVWsF ~t3,Qn Bʙ;}F ~?u(Nȍ;O+ʉV N_^[ +~~=u~=uFQ~pfʋ;}V V+ύ;M+Ӊ^V _^[ËǙ~tV Vi_;M+щN V^[.SVW_tC>w{=wjV@F=FDwF=tD)F=uwN=uN=twF=tF=uwF=tF=uQspcC>ʋ;}S S+΍;M{+_^S [UBS?VWH}tlA$\lAOH#G_^[]EP$ѧ `S ]Ef/Sr! hSf/v^E=v3ONW_^[]ÊO H#AG_^[]ËExPu9p 3C;r#L7+ȋ3;s}EP@OH#G_^[]ÊO3NW_^[]f,kA7lAFkAkAkA7lAU SVW}T$L$GuZu'O|twr=w tZ;viL$3W^$u6~ u G@t;t$F3W^tʋT$Z+rCƋ;s$L$I ʃ9PuBƒ;r\$+ƊK;}s΃9u>@ ;|3_^[]ËL$GGA G_^[]D0KG_^[]h=St$UQEVщUuFRFF^]H3=r=sSRWjG=wbM3PjE{+F~%3ɋFI DDDu݋FE_^[F^]h,=SR+USVWt$ WT$u D$OD$]GD$;vPC=8ËP‹W P*G G;sȋ+ЋG IDu_u ׋L$;sgÉ_D$fG ÃxtL$ PFjPL$ F;rԋE@=t$W QL$*G D$XxHt$f~t&֋=RuL$ VnF y̋D$~T$L$ jP)_^[]Ët$ l)UWMSZ3VE3ɸUWdEtMEEEEEE3;v;wT;F;w4ȋE@ ȋE+FƉE9BID‹ЃuEMdUAM~E33HtxPэRN:t^zuSJ B|ItCw?r=w6t2H3=r@=sRd3CuEMÉEyuTI|KtEwAr=w8t4H3=rfD=sRd33ɋE3@}3ۉEuQt73dfD7t;v ىuu҃9EwڋEU+ËMPVX_^[]U$SVuW\$|$ Fu7jT$hD$t$ D$ D$D$$D$(u֋u { stC;vDs~tS;wuӋ|$ V/֋c=Ru VӋ2_^[]f.DstWc;tcJL$;t\$ӋZ;u\$+BGFt+FGG Gt +F+GuGFGFGF@t&St@tL$ ISAPCYP_^[]h<=SWvhP=SWkUUVu Wʃwr;OsG _^]ÊOH#Gxu 9Pu9ptHtR_^]QVW3WV u fFt3WVt_^Y_R^YUBV<u7NH#BFxDu9Pt/HtR^]T$@T$D$O^]UVWF?vA$tvAOH#BGxDu9PtaHtR_^]v6`_^]jT$ tt$ t$ 4_^]Ë֋_^]vA9vAuA&vAevAUS]VW} L$ WS=Ru#L$ D$P։\$|$D$M_^[]UQSVWZT$ t@r |u23҃v"@ DEEˋ+ʃw_^[]Ãz{ϸwr;sB 8JH#Bxu 9xuxtHtRxtJ߁?w뎾jVxt|$ FjVxu^_^[]Ë+Ãv/4;jVaT$@EE+Ãw_^[]USVW '$zAEEU U_^[]ËE+EU U_^[]uuu uns_^[]Ëu΋}ǃw&rw WfEMU_^[]Ë]WVu Su tE 33ljE |s׋_^[]Ë}ϋUƒwrw h(u SRWVus][]33uu-|# M_^[]ËEU #E#U_^[]ËEU E U_^[]ËEU 3E3U_^[]ËME|sB|wWfEEU_^[]~MfnffMEU_^[]Å|ă@s~MfnffMEU_^[]ËEM؃م|y|{@rqEU ؃_^[]ËEU _^[]33_^[]hhBSW֋ gfܘA#AAUQESVuW8ƉU+;|;}C 4?;LN3u ;ȋw2} E UPWIM_1^[]Vuh,?SShUhH?SQgU SVu ًM3WV{QET$RwD$$Ѓu,t(9t.PVut$wЃt+t$w _^[]úpUQSىT$VW{Gs8t F@F3D$Pv FvЃ tL$tIF@F t u|$ ufDD$@^\A$LA;u׋nK8BK8A@A{Gs8t F@F3D$Pv FvЃ tL$tIF@F;T${‰D$@]ȱA$A{%>_^[]ËO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ/+%/_^[]ËO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ=%~_^[]ËO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ:C%:_^[]ËL$ Q2%_^[]ËӋO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ.t._^[]ËqRu ._^[]ËT$ _^[]ø!_^[]ÍD$Pv FvЃ tL$tIF@FqRAWSϻO @@AGG w x ~ w V讹FG @Et^<>SCO @@AGG w x ~ 萬w ӋVHFG @tuEt[P>SC4O @@AGG w x ~ .w Ӌ0VFG @tSWM_^[]Ë]ϋ=Rt @<tjӋ諆US]VWjS P9oC xu8p jT$$`t$$|$ C CK |$t$+QȃyuIjT$E`L$D$D$L$  ;|;;|I;vCVWjS;!t$,t$,jS%L$@ |$t$;͋D$| ;wNjQPjS%3_^[]h,IShASS܅谍hASjS賃US]VWjSS PmC ȃyuIjT$_L$D$C QPjSD$ L$ōL$D$ |$t$;u;t+ Ћ;| ;w{VWjS;t$ A|;|$s9VWjSt$(t$(jS@$ |$t$;t$ |;|$rNjC VWj@C S$_^[]hASjSSh,ISXU4SVuWxu@ jT$<]D$Ӌ3 UϋRt=RtPӋY_^[]úO SG ϋw URG w jG W fGlJfGlZHtu8tG _^[]3G _^[]U ESVHWD$D$ @^ GD$xEt33jWfЃ39Bt F -;CCF RT$PHAN P/U jPt;|$F fD$ ^ HD$ ND$xEt33jt$Ѓ39Bt F 1D$ CCF RT$PHAN PT jtD$ ;rVF [\$ j;rWjVjSjV t$F jVjWjV _^[]hLBSVxUS]VW|$t$;1D$xEt33jW觨3Ƀ9JF t F -8@@F RT$PHAN PmS F ΉD$ D$xEt33jS-3Ƀ9JD$ t F -@@F RT$PHAN PR jtjWjVQjSjVF F +ljD$cdr U t3ҍ ?|$D$xEt33jSM3Ƀ9JF t F -@@F RT$PHAN PR F ΉD$ ]D$xEt33jWӦ3Ƀ9JD$ t F -8@@F RT$PHAN PQ jjtSjVjWjV CuF jVFjztjSjVjujV F |$kD$xEt33jS3Ƀ9JF t F -@@F RT$PHAN PP F ΉD$ D$ F D$F EHD$ D$xEt33jt$;3Ƀ9JD$t F 1L$ @@F RT$PHAN PO jSjVnjt$ jV`]ST$4++ڃ$HH;ߋu CCщt$uCCEt$t$ PL$;ߋC+D$;v {jAL$ƒljE D$ى]|$;l_^[]U SVuWjtV P \F Xxu8H jT$~ML$|$^ ^ |=Rt#@v=Rtb@<uXF0;sF @F 9N rN jW+_^3[]h,IVshpBSjVpj)rU8VuW~t+=XRHSf.ȟDj j3ҋO<ЀjjJBO@ ΉW@BfBB BBRBF @EF 舜Fx ~腖jhRVx _^]hIVqL$$h,IVqU SVuWhLIjF~ Nj+8I(|$ 諡Ћ/ ;~ ӋF ~ jF V fFl@fFlHt,ЋLFx ~lrxuxx D$tv~j4PjjhBS0jPWjt$ F C~ ;\$jPjjh8IjP13_^[]hBSVgpU,SVuW=R1@'WfD$0xu8X jT$,I6\$,|$(|$$N=R,@$<*Ht6t D$ 3=ЋŭFx ~xuHH L$ D$| $WD$(hBSPfD$t|$<-u D$(<+uGGP9D$D$ D$D$fP3:t0P5XɋD$$;}_t$ t$RP!ȉT$ Ë\$ ȉL$OG\$ Q@9uhBSWsT$|$(tڃ T$03\$4D$D$ ;NN YAF _^[]úm=RYV=RtA@<u7F 9N sF @F 9N rN _^[]úHt.Ћ襫Fx ~őxuHH xL$(tc^ T$0诩ЅtL$0 L$4K T$0 ЅtD$0+׉CtF 3ҋD$(@;tF @F _^[]úthBSjVjjkhlIjV|jUVuWjjjVtN 9N sF @F 9N rN =Rt'@$<u~WVkjV;jVVUVuM=Rtu:Pʃtt F @@N t%hBSjAEF V ^]AF ^]hlIjVDiUVuW=Rtx=Rta@<uWtu\hBSjV' uUF09N sF @F 9N rjVN " _^]jihCSjVhh CSVjUVuW=Rtm=Rtg΋Rt=RtP3L3V 3Ʌ_ BF ^]hlIjVghlIjVgUQVu)=Rtu@tueȋA?w&pA$`A@@ қ3N AAF ^]hDCSjV gA'A A0AUVuW\=Rtq@<ug?=RtbF809~ sfffF @F 9~ r~ W贙G_^]jghlIjVIfUVu=Rto@<ue=Rt`}=RtZF@9N sfF @F 9N rjVN B^]jfhlIjVehlIjVeUVuWhJhpCSjVljjj<,JVoPWV,ЃtKt$tN QAF _^]ËN 3AF _^]ËFfn_H HF fn@Y SXF ^]UVu =RtK@IuF P趯V @@BVF z ~賊^]hlIjV.dUVu=R@<}FW809~ sfDF @F 9~ r~ >΋GPЃҿEF F _t^]@F ^]jdUVuW=RhCSjVqy u[F `A@FF ~ x ~ s~ tF F @F _^]úCN jV fFlV Q4fFl_^]hlIjV}bU VuxuPjT$ =t:T$ L$F RQjP@F V@^]úkUVuWI=RtfF A@FF ~ x ~ ~  F F _@@F ^]hlIjVOaUVu6Ut'N jjVF S uF ^]ËF jjV@F  ^]UQSVuW:=Rt@vjjV؃ 3ۺ=Rt@vjjV }t`E=RtxuSV3ɺEʋQ_^[]jSajEaUQSVW}T$ GO +_ 5+O >BD$ `@P(T$ w ҍ9CsCw jW fGlBG 1fGl=Rt@uEG 3_^[]Ã@tuGxϋlujWG _^[]hCShHIW`hCSW`USVuWHt0t339Ћ趞Fx ~քxuXX x=Rt!@vjjV3 D$4D$CS~=Rt@3ɃEȉL$΍PQtB=Rt@vjjV t$|$PD$ \$$PhX@}=Rt@vjjV CS=Rt_@<uUF`9N sfDF @F 9N rt$N WjhAVЋt$_^[]j0^j"^j^UEH@ +H]UVuW =Rt@vjjV 3F 9N s@F @F 9N rjWVN ~ V FlfudF@AF@fFnf@fFnf;rf;f;~j|)uFfFn@jfFlU-fFlNF 9As ANF +_H^]j\V2h:SV#UVuHtu8tNF ^+]jVCcjjVjVhDSVjV,VeUSVuWF~ +8'=Rt{@$<ur Ht.t3*Ћ讚Fx ~΀8#u#N GQAF _^[]úxuXjT$5t`\$L$L$ǙT$щ\$|s\$\$t$;t$u| ;v\$ȅ|r+_^[]ú|chDSjVYUE t@t;VW}ϋG @G w G _^]ËEH@ ++E]UW}}=RG jjW@G GO hAj+jjAPWQ$t<t7G V@G w G ^_]ËOG _+]hlIjWPXUSVW}ϋGw +=R@<FσG w bjjWG hAjjjCPWY$t<t7G @G w G _^[]ËOG _^+[]jXUVu=RtjjV\o ^]hlIjVWUQVuعyjjN jh RVF DrGN h:SF )Ћ`DSN @@AFF x ~|hDSЋ^]UQSًV3EWsI3@t LG$ @ 8u 8>|s8|p tjDxt 8txBr<x4t.*|;D$s"L8t|u ڋ}O uACqG _^[]AG _^[]Ë}hESjWkMjNCW}hESWUOU $SVuWPjV5؃ ΅xu0x%jT$(u WfD$t$|$L$ V|sWfD$|$t$39|;s)D$USVuWjjV} j.Wxiu_^[]Ë+u I茈 PN @@AFF x ~|cHt,t3(Ћ%}Fx ~EcKQhFSy؃t&WӋtu^SWhFSV_^[]ËӋLJN @@AFF x ~b_^[]j=jjVB PSjjV3 PhFSV$>UQVuWjjV ΅tOhGSعcЋzWLЋcuWhGSV _^Y]jVu}V @@BFF x ~X^]hHSu94UVujjV tMPu F @Ћ6}N @@AFF x ~3X^]j2UJ:MfnA @^PSA ]SVWhHSs VFC ЋK GQA˃C hHSЋK GQA˃C hHSLЋK G QA˃C hHSЋOGK @hHSQA˃C ЋK GlAQ˃C hHS調ЋGK @hHSQA˃C uЋGK @hHSQA˃C @Ћww x4K 3hHSA˃C Ћ<_^[U SVڋWS׾Ћ΋迾xux5jT$ uuYEx^F _^[]Ë|$L$|+r!|?wE +ȃF _^[]Sh+U$SVuW蕺=R>@4t=R^@<PF 9N sF @F 9N rN HSjj8jjHSD$$jj HSD$(jjHSD$4jjHSD$@hljHSD$L0D$ hHS諹Ћu$茹Htu8t3F D$,D$ P=ڍT$ ΋nj#ڋ#ÃtF 8X@F _^[]hISV+j*U SVuWոxu8XjT$tq\$|$蠸xu@jT$tHD$L$PQSW,7F \$D$@F _^[]ú22UVuW =Rt@vjjV腿 tk3h$JhISjV.W4JM6u F @Ћ}sN @@AFF x ~zN_^]jC)UVuWY=Rt1@$<u(=Htu8t3jjjV52Htu8t NI|u_3^]W2U8VuW~t+=XRHSf.ȟDj j3ҋ~O<Ѐj jJBO@ ΉW@BfBB BBRBF @EF SFx ~Mjh(RVA _^]hIV(L$$h,IVf(UQVuD$PjVH t%N D$AAF ^]jN'USVuD$WPjV D$΅E9xuP jT$_"T$\$L$ T$|1s-;vWfD$L$\$3ʃL$jjjV/|0s,L$ ;vWfD$T$|$3уыL$ D$|s3| ;v3;!|;w+΃tT$JW~o κIoN @@AFF x ~J_^[]j%V.USVuD$WPjVM؃ teD$ t$t$ D$D$VPD$ D$03ɋtVӊR9A;rt$D$P1_^[]j%U@SVuD$WPjV譺؃ tn|$ D$ D$D$WPt$$D$ D$y/t+3P}vu|$ |$D$PE1_^[]jh$USVuD$WPjV؃ tn|$ D$ D$D$WPt$$D$ D$.t+3Pvu|$ |$D$P0_^[]j#U4SVuD$ WPjVM D$(΅袱xu8X jT$\$|$i=Rt*@v$D$,PjV߸ȃ L$$tD$, 3D$$ID$E|u?IlN @@AFF x G_^[]D$D$;D$SWjh!3;| 9D$Ot$<L$D$D$8D$4ȍD$@D$0D$0QPL$ ,|Gv@t$t$,V^t$ D$tPt$(Vq^ t$|wt$t$,VQ^D$$ D$8D$0P._^[]hdJSVr"j!:*j!U$SVuD$ WPjV$ D$,jjjV*L$ T$ ؉\$|9s5;vWfD$T$\$T$ 3ʃщL$ \$RSjV?*|0s,L$;vWfD$T$|$3уыL$D$ |s 3\$| ;v3;|;v 3_^[]Ë+ЉT$$xF+N G^+׉T$ ;0+N @B+ǃ;iD$ `@PuQT$ F 9CsC3ۅ~.D$HD$,D$,CN D$,QAF ;|ߋ_^[]hTEShHIVo jhTESVV U$SVW}G_ +D$0D$ D$ SP|$4D$0D$,*D$$;|]D֋WxuxL$|$jT$utQ|$L$;u3;u/D$LF;}\$(D$ P+_^[]hESVu]֋D'UVW}tuWVJ)Wu PZ~_3^]UVuWHtu8t3Y=R@<uvF 9N sF @F 9N rD$N D$D$WPh0%BVt$$D$ D$-u&L$Ql*_^]jhJSVEVŠ B%t-[t^À:^NEB;t B<%u;sB:]uB^;Vt^hJSv hJSv SVWW'B$'BV|VoVbV&UVMHVq;V.V!VV3ۅWu_^[3;_^[&B&B&B'B'B'B('B5'BB'BO'B\'B}'B        US]3VrW^MEFE;sU<%uVFt0E_^[]À~-uN;s;;~;tF;rM3^_^[]U$SVW\$$s|$FCKu;܃w$.BF;s֋ЉT$;{3VƒЃ6w<.B$,.BVA;287uGFD$G{;s1:T$uux|$t:uA@;r3D$$@_^[]Ã>[T֋D$(;;u2OHP։D$0@ut$,+tt$(Wʃ1C;TT$ C+;_L׋\$ rfD;ust=:*t.A:BtA:Bt A:B|$ |$\$$L$,D$<%t-<.t"<[t3;D$,&BP1VT$Ȋu<*t ;~w'@vF N Ot;Fu G;~v_^3[]P׉FN &_^[]USVuEWPjV EEPjV EF09N sF @F 9N r~3҉N h<j'eO<؀KCO@ _@C $CRCRCCF @GFF x ~3MEUC(Ej‰s0h3BVC4K$C,KSC 螧 _^[]jAj3USVWx Eω}>Pt.ЋLGx ~3xuHH PM3ۉU %t)V;Vr_jVXEV  FUuDCPU u2%V;VrjV EV  FU*0u6} +}tWVWuPIU~}C;]P_^[]u uM1jjW#jjW螝G VaUj%hKSWl U ET$L$SVq Wtktu uA_^[]ú苚N ~ ] USL$fFl@+jfFlf] 3Su)D$~ xEt33=39P‹tT$PQQ ֙Ht&u8t軙@tKuYD΋E+u IcU ST@@BFx ~U0t$_^[]jV:PVcPhKSV UT0S]D$VWPjS蝠 8D$PjS胠 D$˅(D$$И=RtxD$j@|$$PjST$8T$WD$,fD$0D$ttt $\$`$PL$DŽ$XDŽ$T<^uBIT$D$Ɖ\$D|$(D$<D$Ht$8D$@ |$,D$4L$0D$L$fRD$PL$0xEE$EM],M0W\M MD>EHMf/ SEvxq M>F@ffY 0SME$MpM],M0W\M M>Ff/ SwEP>h0LSP S uM$ht=SWRȉEC @PM>F;|_^][BUt@SVuWD$FN +D$PjVL$X蓘؃ D$$Ét$|L$p3ɉD$TL$xt$t;d33f%t*;rD$pjP9 L$xD$pL$xAC;%u/%;rD$pjP $D$pL$xAD$phP D$ D$@D$D$;D$L; tPhLS,tOGu+ÃPtGPtG?.u$GGPtGPtGPD$,%+FPD$1SP=D4: A7R\$Ӌu谍xu D$hT$hYD$hL$,QAu+ʺId +\ +fDRvu#D 4D$4$Pt$$FK\$T$pMSD$\$D$PPSu ؀|$.uD$pPY D$^ˍQAut$P+;D$,j.PZ)udrD$pP D$SD$0Pt$ Ju F L$xCL$x;\$Ts t$tD$pP _^[]j ӋjӋhLSt$uQhMSuhLSuhLSu~h=SPu`CB@DBBBBBDBDBEBUSVW}PAZIB$IB3_^[]_^[]3_^[]_^[]3_^[]3_^[]_^[]_^[]_^[]_^[]Ê"0|B9=3č BI H",0< w ~߃3_^[]Ê<0|><9:3f I HB,0< w ~݃ph_^[]Ê<0|<<983ɋ I HB,0< w ~݃,$_^[]Ê<0<93f I HB,0< w ~݉_^[]ø_^[]_^[]ø_^[]C_^[]C_^[]Ê<0|:<963fD I HB,0< w ~݃d~`K_^[]QhMS3SjQh8MS3DjQh8MS35jQh8MS3&h`MS3jQh8MS3&IBHBHBHBFBFBGB GBGBHBFBJHB;GB+GBFBKGBFBFBGBHBHB0IB    USVu WUUV&؃M u&E9t[M QtFM t?~*t%;OOOQu5#E+ȋE#ʉ_^[]ËE3_^[]hMSj7hMSj7U S]VWUSW}MS3E9uD ;~?}tE u 2B;| SЍsE RJuE}t?~:}Kt!эxʃEX_^[]Ã@u__^[]U@SVuWjjV谍Ѓ 'F 3ɻT$L$$~EO;$r$jP$$$A$D$OC|$4\$$RBMxuPL$@T$D jT$D5+T$DL$@}[33ۃ C3@ËCۉD$\$\$;| 9L$;T$|; |s3PVRT$8Q$K.MIxux\$H|$L jT$Lg]|$L\$H}.3ҍ3ƒ C3у@C;r;$VPc3ҍN9T$,Dѹ;~J|$,t A;|$\$lNf@Xu$\$9$VPMӋAxu D$XT$XtgD$Xu fZD$`D$`|$,L$`u&tD+ID9ut$ $VׅtDRBIut$ ${D$8PSu" D$|$8;t.$WPWt$ P0$ω$$;sAG;$r$jP$$$A$;rGD$8}D$$PSWn D$D$$} ;3$VP.3ҍN9T$,DэO;~79|$,tA;| NfD@Xu$\$$t#$SPSt$ Pf/$L$ˋ\$L$D$TPSu苈 ύQAut$T+;Et+$VPRVWP.$Ή$$;$r$jP$$L$$AΉL$<;$r$jP$$$\$L$D$<8U$Q_^[]ËMjjhMSSuPhNSt$ u?M%MjyhNSSuh8NSSWhLSSuLBMBNB`OBPBPBQBQBQBUVW}jjWȆ 3D$ 8|$D$D$tID$PD$ PD$PL$ 4T$T$ +ʉT$;w7|~FD$ 8uG 0@@G _^]hdNSjWjXh|NSjWU(S] WVfE;މMMNUW}܉uFx4+K}DC Uyދu] M}9}tw33 C3փ@C33+ދ_^[]~B}t |s3;}%+I}Ƌ]D] ;uFI;|]_^[]ShNSuUlSVW}jjWׄ {D$t$(PjW蹄 D$ijjjW.؅|$s L$;vWfD$8\$8؃K3҉T$;\$+|$DD$HD$L8fD$,T$8PD$PD$0PL$Pt$$ˉD$@ыD$8 ; ;L$O ؋GD$0G+\$ T$$ 5+O >BD$$`@P۵zT$$L$0G 9AsAD$L$4w8$|XBT$3ɋPVt$PYO QAG T$D$(ހ8O CBAAG _^[]ËL$˃|$Hut7T$P+DID uT4OtRBIut$u D$PZD$PG t$@G Pυu I6T$V$6O @@AGG x T$jVt$P0 D$4 0;L$υu IJ6T$P5O @@AGG x ~4\$4T$ӋڍKCu+ًu I5 SQ5O @@AGG x ~D$ @ÉD$ &T$8T$hNSjW?jjshESjWhNShHIWfVBVBVBVBKWBWB'XB'XB'XBU8VW}wt+=XRHSf.ȟDj j3ҋAN<ЀjjJBN@ ωV@BfBB BBRBG @EG Gx ~jhRWw 3ҋj j@N<ЀjjJBN@ ωV@BfBB BBRBG @EG  Gx ~I3O @@AGG w x ~ w wjWG 贌G w wh4>SG wЋʇG _^]hIWL$$h,IWU Vu7w΃xue%wxuH%jT$ Ku WfD$T$L$  |sڃًF H@F ^]vxuT$t)D$F TS@F ^]j>UVW}FvxuT$t(D$w FG _^]jUVW}uxuT$t(D$w mFG _^]jUUVW}fuxuT$t(D$w FG _^]jUVW}txuT$/t(D$w =FG _^]juUVW}txuT$迿t(D$w 譧FG _^]jUVW}txu;D$s=RtF@v@sxu0T$tO뾍T$ tLD$SD$w D$D$详FG _^]j9j+U Vu7sxu"PF P@F ^]jT$ Bt%F T$ L$P@F ^]úr=RtN AF ^]hlIjVU8VW}frxu1G 9O sG @G 9O rO _^]ú#rxuaD$8D$8$4\$@D$@f/SrB hSf/v4w 辢VFG _^]ÍT$8t똋G @G _^]jPU8VW}Vqxu1G 9O sG @G 9O rO _^]úqxuaD$8D$8$w\$@D$@f/SrB hSf/v4w 计VFG _^]ÍT$8t똋G @G _^]j@USVW}Epx/pxpxuH%jT$?u WfD$\$L$ӉL$w6rw/ G @@G _^[]úoxu@%jT$蹻u WfD$L$D$t$w SPQrVFG _^[]ú*oxuOD$oxuDD$D$D$w FG _^[]ÍT$t*몍T$ ujPyhLOSjWj^U8VW}fnxu.G 9O sG @G 9O rO W&nxu D$0T$0YD$0D$0WD$@f/$vt\$8L$8f/ Sr-hSf/vw (荞L$0VFG @G D$8O f.D/\AG _^]j UVW}mxuT$Ot(D$w FG _^]jU SVuWlxu8XjT$˸tl\$|$plxu@jT$薸tCD$L$;w r;s3ɋF _@F ^[]ú|pUVukxuT$D$D$k=Rtv@vpkxuT$t{D$f.(SD$D$Dz觭'PD$D$?L$^.(ȋF @F ^]jjUVW}jxuT$t(D$w FG _^]jEU VuWjxuT$萵t*D$F Y8S@F ^]jU VuixuT$ t*D$F YS@F ^]jdUSVW}GO +E;;|ZEKiUωE>iURt=Rt PE3DMFE;~w ЋhG _^[]hlIjWSUSVW}GO +E;|};|SEh։EhURt=RtP)E}DEFE;~w ЋAhG _^[]hlIjWUSVW}fnGW +YSD$@twMQgxup jT$۳)t$\$t$ xgxuP[jT$螳93Ӊt$ =gxuP jT$cL$T$;|;*|s$ÃD$;|;L$w +T$ 肘XSYD$薗FT$ VG _^[]BG _^[]hTOSWӋhpOSjWhOSjWUM fxu$Dt$͖P3]ËMjUVue=Rtn@<ude΃xuOSN!V @@BOS3!N @@AFF x ~00^]ú,e=RtN AF ^]hlIjVU8VuW~t+=XRHSf.ȟDj j3ҋ,O<ЀjjJBO@ ΉW@BfBB BBRBF @EF 8Fx ~5jhRV(F  S@F h0PS dЋAtF pS@F h4PScЋ tF @@F hF|݋u}u4 u/;rjP 8 P tJMATH?w(~B$ ~B@@ u 3_^[]_^[]f}B}B}B}BU$nSVWS\$F~ +8O|$u]jӋZ}Gt$OIRF S@F UF @FN +^|$ ;8+N @B+ǃ;D$ `@P趌|$ F 9CsC}D$|$ HD$2׋R=R@<׋Rxu@\$D$jT$覞!\$uY\$S%PD$ SP{I N @@AFF x ~3ۃ|$ +D$0t$,D$ D$ SPD$0D$,ct$SjPRD$8|$@PF3;Nj|$ jWV)Y i*uH"DB$BT$<T$jrT$ja|$D$0t$,D$ D$(D$$D$ hPWhjPQD$@=tՋ|$ D$ PgD$G|$ 8Ћ N @@ANF ~ y ~ z~ GWF _^[]ÅuF F XF +}_^[]hQShHIV׋h8QSWVj׋fB̀BBBρBUVuعhQSOЋ[OHtt3 ztj^]h QShPSVUVuh\PSjV< txt"jd^]h\PSmhPSVU׹SVuWNHtt3 ֹ\$ Nxu8@|$D$!jT$u WfD$|${FD$ 9N s!F @F 9N rFD$F+N T$;8+N @B+ǃ;8D$`@P؇T$D$N 9HsH|%ԹӋMN KF u\$ j׋MHtu8t _^[]ÃչMHqu8tgF89~ sF @F 9~ r׹~ =Mh\PSjVF ȃ t[AD$D$VAЃ_^3[]hHQSV聿hQShHIVqj+PVaT Ph`QSVRh\PSU4S]VWT$$GO ++IӉL$,rL=R@<ӋPLӋσxuMALxu@PQL$8D$0JO jG H_^]h\PS0hPSWeUQSVW}h\PSjW覿 xh4KhhQSjWjjjW4JRPS]d0tEHG S@G Ku G @ЋO @@AOG w y ~ w FVG _^[]S`O QAG _^[]h\PShPSW6U S]VWh\PSjSt tRxt]8h>KjjS膿jhjSuP4JjW3ɅjQS<_^[]h\PSjhPSS蟺UVuعhPSGЋSGHtt3 xtj01@PVg ^]hPShPSVUVuh\PSjV\ t$xt/j01@PV ^]h\PS耸hPSV赹UVuh\PSjV ΅tJ@BQSF @F N @@AFF x ~^]h\PSU8VW}wt+=XRHSf.ȟD j j3ҋSN<Ѐj jJBN@ ωV@BfBB BBRBG @EG Gx ~jhHRW h\PSW*EO h4>SG EЋUjhRWvG j`,ϋω0@BYEO عhQSG ;EЋrUhQSEЋUUj+ϋ/ω0@BDO عhPSG DЋUhQSDЋTj+ϋhQSω0@BxDЋT_^]hIWL$$h,IWͶUSVW;tVFN +U^U;.+N @B+ƒ;1E`@P}uUF 9CsC_^[]h\IWGUVuعCN F ^]UVumC=RteZCPʃtt F @@N tAEF ^]AF ^]hlIjVtUVuB=RtO@tuBF09N s@F @F 9N rjVN W^]hCSjVUVuW\B=Rt@~ tGF _^]ú"BAAGAGF _^]UVuWA=R@<A=RF809~ sF @F 9~ r~ AЋG AGAGAN A@t::Gt1QBt(Ny=wNF _^]ÊI<$ ȈOF _^]jhlIjV茱U|SVuW@=Rt;@$<u2@xHt3D$ { D$ D$ ׉|$@=Rt"@vjWVHD$  QS|$jӋT$<@=RtX@<uNWhQSVJT$ Ή|$ @ȋF N AF ;N C C pT$ ?xujT$L$S~C4;tRIuC4;t$3D$ PWSf ~3j jFȃG<$AAG@O@AfAA AARAF @EFF x ~|$jSWxcT$0uF PN @@AFF x ~hRS>ЋNT$D;N @@AFF x ~8hRS7>ЋnNN D$8QA΃F h$RS>Ћ9NN D$KuQ1O @@AGG O x ~ +O FxQAAG ϋW fGlj4sfGl_^]U$SVW}Ӌ0=Rt5@$<u,Ӌ0xHt3D$D$D$D$։t$s0=R@jt$W7 D$υ:0=R@<{jjt$ W3D$ 3jct$(BD$0jrt$0E tjlt$otƃ|$NVW13D$D$عD$/w T$ D$ DKD$(4G G @w3j jMN<ЀjjJBN@ ωV@BfBB BBRBG @EG Gx ~.O hDKhعWG C RSyO @@AGG x ~vhH>Su.Ћ>_.O jWG :CjӋ C @HK AC ;tK G G T$.O jWG @T$ tL$u33ҋC@"t@CD$_CdCh3^SXKp[]ËT$jvj֋kUSVW}u-=Rt#@$<uY-xHt3ߋCpD$ CXuG @G =Bt6RSO @@AGG x ع,w T$D$DKD$ jӋG |C @HK AC ;tK G G w q,V'jjWF. G L$ cD$EˆD$D$ tD rAtD lAD T$O @@AOG w y ~ w CdVFG _^[]UVhSSh`QSjPل jwPjdPD$hP uSSD$f:utP:Quu3^L$QAujD$+ʉD$ D$ hSSPhX@VL$ `Cu0F @D$D$+F jPD$Ps tr*Ht,t3(ЋRFx ~rx*PhIjNP蝃 j;PF9N sffF @F 9N rhSSh`QSjN P@ jP0jPD$hPx j3^]U SVuW)=Rt;@$<u2y)xHt3D$_ 8D$D$Ӊ\$7)Ht+t3)ЋFx ~Ӌ)uˆTS+O@FDK+G@UȊOtE G;~}yWN,U ˈN,S@BC3IWE~(N,_>G;~}4WN,ˈN,}MU;~G0*H,_^[]ËNWSNWSUSVWXDH0EC ƉEP UUE:B EraR@;QuQQQP_@RhRA KA;}C vG0D0KA;|_A^C[]UOuPEpPhUSv4=ЋQU A0SYDVE@ s UPMKW;}>C98tB;|3_^[]ÊH 8N vNvAtB] I0 ? ω I0 tFu΋UMP_^[]USVWMG_S;~I4h0VShjP.ECM LMI0I*L MLG_^[]QVWxu x@VSwdVSvPRw4ЋU$SVW}_ w]u;{ wG@VUE>C M@t;P0fD%? ƉP0-tAȃu֋GWuωG=u{N4t?SFN0VDEUAEJMAEB];]~"N4h0VShjPUM}M<}DF0 @*D ϋ}|E}BF0NDM@ QUUp;q}<}fDA ;uR֋MUF;q|؋}]G G[ ˋPDG*+JG*:v-O*GO*O$@DH@H _0uF;Ft7=>u"F;Ft#C*N;|Q֋@ ֋A !GGtG G !G WGUFUˈF A> fF _F ^[]SVW~ !FFtF F !F VF׋G׋^0;Gt7<?u"G;Gt*C*O;|Q׋?׋@z<~]u3~ !FFtF F !F_^[ÍV_F^[ú]U}2EuUj2uRSJEF΃[t9=$tUEE*V(F UЋ΃=tEEUF,u'~ !FFJF F !FC;tu}j{Mt:EЃ t UЋ >MUQuˋRxIU3Ƀr6rsr BAs  ыu@0 % ‰3ɋUr7rsr @BAs  ы_@031^[]jUЋD8EMxQI}F  +.׋+5.֋5EC,MKXSX{U SV3W~0EX~)F- +~ !FEFFtF F !F VFUEC@uo~,ui~ !FFtF F !FxVLFf~ !FFtF F !F VFE@v0^*t/fDFN*+N$@DH@H2u)j(M̋u^ ttt Ű6G,+3Ӌ Ё$/UFF FO@8T_,_^[]úVS9U,SVWCK{0M(t=$Q{ !KtC C !C SC֋+ u)j(K01C(=(@B$B֋> uF;Ft9֋n1>u"F;Ft#G*N;|Q֋\4 ֋5U؋4FU؋ψF 5> fF F u{ !CCtC C !C SCU؋C֋0>u"F;Ft#G*N;|Q֋3 ֋4>NMuu G*;|O,G,FO,у@;vPO,U؈O,4U  V m-}usMuhG*;|`O,[֋/>uNu G*;|O,O,B@;vsEPO,HO,P2u֋C(=_^[]ËOWS`VSVf1BB&BBBUVWG=B$BFFFGFFFFGFGF GO0E@@EEP+LF@F1F"O0x-*FFF !GGtG G !G_^]ÍWG_^]_^]Á !GGt$G PjG !G _^]ÍW|G֋GPj_^]l_^]úVS芽fBB)BBBB B5BaBB       U0SVWںG4f@nf9PnGG=1B$BEEEE !GEGtG G !G WGj Ӌcw0E$BhxRSP C5Ӌ*;KMu$C;Ct.F* ;|QӋ-KMӋ/MM;uu F*;|N,E 'MU N@8TӋ]3G=TB$B3|ung`YR K D = 6/ (! uunK;E" !GEGtG G !G WGO0MdB$PBi1-)t ttMj@0CMSP#UKBBQM#C$-C;Cu t tl-unKUPUO0EuPS6 uG4_fHn^[]ËO0hUSBBBBBBBB8BB/B BBB!BgBuBB6B=BBB(BRB`B|BnBYBDBKBB     iB`BBB}BUj]UPSVF^]WA 8G,' !GGtG G !G WGUuM G03ۋUĉE@,EE~ uGF;uF;uEFFUċMuF;‹EufFYUċME6utG] иD !3S,AF;vGNS,ˆS,]G4M@n=/APUT=% !GGtG G !G WGUԋGU;tDMQP4O0A,HEE܍EPEE)_^[]ËEԋw0 u2EӋH0E܋E܍EP)_^[]Ãu#H0E܍ % w0E EԋPj)_^[]úWSKWS O0hUS=mUQSVUW^^~ uc~ !tF F !F VcF~$~ !VF:FtF F !F@'F4~ !tF F !F VFN4t?SuVDSW Ћ0_^[]ú$}USVWF0^DE@ SH;}CD;8A;|~ ~ !FFtF F !F V9FMSAPuAW> N;t u w"B$BE׋Kҋ@ @ D F0׋ND S@ UMx;y},;uR׋)MUG;y|_^[]ú 2Cɋ]tGPCh,WSp4KB B BUDSVWT$ !G_0GtG G !G WGCT$8jωD$CID$ЈEG;~WV,U EF,ˋ{0G*EԋG@D@E̋G@D@EEG EȍEȉG FV}WF]}t '0U  )%NU@8*TӋO~;uPV~QhQЋ NU_@8^[T]úNWSBU,SVWj TWS_0C,D$)Ћj `WSЋj lWSЋ֋= !GGtG G !G W\GjT$$O0T$$,[ !GGtG G !G W GjT$$O0T$$,uN !GGtG G !G WGjT$$:O0T$$;D$D$ PT$$D$,D$D$D$S,  ˃.֋3K,BF;vs?VK,K,T$ jjun _^[]ú=,KWSU,SVW]jF0xWSE@,EҨЋj WS踨Ћj WS螨Ћ׋F,u<~ !FFtF F !FFVF3ɅtP=$~ !F^FtF F !F V跾FӋ]C]f= ~ !FFtF F !FVh~FEPQЋPMQ, A;v s6QUCjPW _^[]ú$ MWSIU4SVT$W~ !F^0FtF F !F V蓽FjT$,~"~ !FFtF F !F VIFF= tU=tNN0T$(D$&C*D$$C@D@D$C@D@D$ D$%C D$D$C D$<~0T$()D$(t"ttjT$,9 D$0PT$<T$@GωGRWD$@D$&ΊC*D$$C@D@D$C@D@D$ D$%C D$D$C T$8F;t= u wB$B_^[]Ë{CWT$D$D$ΉD${F=t=u973VT$D$T$t$ Ct$ˉC_^[]úBBBUDSVWF4^f@nf9Pn\F=C$C~ !FFtF F !FV蟺F~0T$|$D$F=uDT$F=t=u{~ !FFtF F !F V*F~0D$&G*D$$G@D@D$G@D@D$ D$%G D$D$G $|$Sh GWt$ωG ~ !FFtF F !F VwF~0D$&G*D$$G@D@D$G@D@D$ D$%G D$D$G q ShXg~0D$&G*D$$G@D@D$G@D@D$ D$%G D$D$G ~ !FFtF F !F V謸F~$~ !V FL$FtF F !FlL$FF,t!=t = ыSA ыShai]~ !FFtF F !F V޷FT$3F.ufDT$EF.t:uT$΍x*SWT$8 N0D$8PT$$F0 H@8\~ !FFtF F !F V=F~ ~ !FFtF F !F VF~$^0~ !FD$FFtF F !F V迶FT$~0G*G*O$ȋG@DDH@HPhP%NW FA;~$NhWShjI4RW0蓐G0NG0OVB;~$W8hWShjQNI4\G8VFO8_@FHN^[USVW\$C;H4@@L$ȉD$blȉL$RuT$L$V&iD$ȃyu81;s}1MW,B3A?uQ3st _^[]ËL$D$_3@D$D$Q@A ;~"W,L$hXShjS^OG,;}G,IFD;3|\$ËMG,D$@A@t7Gt0Bt(L$Iy=wI_^[]ÊI<$ ȈO_^[]UQVW u R@0 E@3%1_^Y]ÃuTJ@0M%I ȉ ?F, >N,BG;vsWN,N,_^Y]ËNWSQVWH$ C_^YËVF _^YNu G*;|O,~ uF :G*rO,V F  ыF _^Yà uN@0F_^YÃuN@0 %  _^YL CV Cs C C C C CU0SVWuA 7$ CujEp_^[]Ëu3҃D ~u ֋.FUEEEP*u bFUԋN EEEME봋VuH03%?1Ep_^[]ËVu;t Ep_^[]j C C C C C% Cu C C C C CG CVtDp0D|L?dJ| ?#u-tBЃu3^ø^USVWu? uwWWw;EEPu֋C? u E-sCVUEIEEuˋC։C@KK֋ˉEmKSuKˉEususWV}W uuVi EGGG_^[]SVW?uOu F*;|N,N,BC;vs SN,HN,Pg_^[ËNWS3U VWF;Ft7'>u"F;Ft*G*N;|Q֋֋GH$@CEEbEERGE@@EEEE9FUN EEEEMEFEEEUP]FF= _^]Ë֋3>u)F;Ft*G*N;|Q֋!F_^]Ë֋LF_^]sCSCcCCCCUUSVW}t<3ۀz Í]OMQ A   Il?u"G;Gt#F*O;|Q׋Z ׋MQ W s?uGOu<F*;|4N,_^[]Ã?uOu F*;|N,r׋_^[]USVW u7s@0ƒ?<u(OD3@9ED kt>7O,BF;vVO,HO,PZ;uKu G*;|O,S U?cwGMVUEE_^[]ËOWSňSVW w[C$CN@0|JZ?dJ| ڋ%??@ Fj֋PV6NWGGQF_^[ÐCCCSVWA dC$PCN@0|JZ?dJ| ڋ%??@ nt:O,BC;vspSO,HO,PV>uNu G*;|O,VhF FϋVVF V_^[OWS҆fXCcCCnC!CUCCUS] VUWUΉE E8uP;uK;~#u F*;|N,u.F*;!u F*;|N,u F*;|N, }  }M_A V^[H8ED]UQS]VUU s;WEs;EuSE 8uH;~#u G*;|O,u.G*;!u G*;|O,u G*;|O,Ut0BwM  у@!  u փ@ u֋wGyVU E E C _^[]USVW|C$C} uWv~GfF_^[]Ë} uWvʋu ֋F;Ft7>u"F;Ft*C*N;|Q֋o֋J> uuNx0?<ucUE:u*BEuC*M9B|K,FE[0ߋ B ȋE  FB_^[]Ë֋uVu _^[]Ë} Wuu)uV Wu _^[]u uQ_^[]CCCTCCUQSVuڸQWv3BU DЁ  +5È_,_^[Y]Á* +֋.È_,_^[Y]ËOXS苀ULSVW} 3WfE9_,uG;Gt4fE w 0 G@űMȉEEĉEEEW@T u}9T}u}D}t 9t uEEUE;w4rW0w;rM  O ;O4rE;vEP~ȃMOrw t(PF"_^[]Vj4XSKY؃]3ҋcuH3s ֚S͚)uF譚_^[]Ëw(t6蒚v 臚V~O$G(Af;C} r;ust1:u't&A:ButA:Bu t A:Bt3t"3s S3_(G,4WfEfEw 0UċEԋu]ЉUEfDG@Ƀ| ugEO M9Ewzr;]ssUEQRV0ωP3҉EEȃ tI8G Pj3UMăUAEEEU;W4wCt;w0s8juEăR@_^[]ËEԋ];Ew2r;]s+u軘 G_^[]ËOPwPtVQAu+ʍA P蓘؃]u+ uGL_^[]ùTXS*QAu+ʍAP>؉EtdXSPQSp hS^P_3hpXSDV*U؃]uH谰 t  GVa\uV0V蜗u著_^[]hS4PYGut'h.CjVuTGt Gu3҃}WUEfEwEԉE̋EЉEԋ] ËD_@MىE]؃{uustu E sEjXΖt2CFC F C0F0C@F@~CPfFPM3FF fFFFFF F(F,F0F4F8F~tFjjjjvVЃFjjjjvVV臎_^[]jQSu&X9u 4{tCjjjjsSЃCjjjjsSS#;uOG>R~tFjjjjvVЃFjjjjvVVՍ_^[]Ëu]u M׉Eu Eu jQj@EPwGЃ|UZrOTUIIy G 8jjj@EPwG7Ѓ$|su tG E;tHEtGjjjjwWЃGjjjjwWW};u}u VjuV y3蓥C_^[]Ë_^[]ËMdduVt EȉẺB R0EԉFEЉF EF0EF4+E虉F(EV,@t:-U Su .x59EujWu  33_^[]Åt C_^[]U SVuW} ljUMteut]fDu Ɓ v QPjPI؃tUuSjPE;uM+wru_^3[] EtW_^H[]ugt!ܣEt'_^H[]ËEt @_^[]U ÿSVWΉ]8yK D_^[]3ED~NVjjh uPRуWRPыڃ|IrC|bt\uWjP ;tM t AE+uGtF F  ߋM 3|su_}~t>NFjjjjQuЃF_^[]RЋF_^[]UEHE @u]Åu]ÉE M]dUSVWjjW yE 3_^[]Wu1u uW^_^[]É~_^[]Pu ؃tu u4W3_^[]ËF@CF0C F4CF8CFPKt!E@3_^[]Ã~t!E@3_^[]ÍF;r"~PKVu]SQuuWz ]SQuu uFEFEFUEU+EȋEȋGMEʋGE;r E;EM9MU 9U tM SjfDG GM;|+EEEEDuVE92jwV V78V;G&GWOEԋG UfE܅wUu܉U u@}w }jX~tZ3@@@ fH@HHH H(H,H0H4H8H3_^[]SѱEh*u uEt3_^[]S+Sh*jV4SE试tEtV-3_^[]ËU3ۋM *EEE]‰]+ƍyr_GPjPVLȃ tDAuXSf;QuBuXS:BQ+PjPRȃ uM U3ƅ}FWQRUPQMM U]}|}wMEPEUMEP9U1|9Es*EߋEȉU M UUM [Nj M UWfEUMUUMM Q}}P|}sHuԃwPKFNAAA؉ME@؋E@؋E3ƉMM߉E]AAAAMAEE@EEEE@EEEEEʋU3MM9E|;tAAAAA ؉ME@؋E@؋E3ƉMM߉E]AAAAA M؋ʋE@؋E@؋EM3ƉE߅urw}wyr=wpمwhr=w_uMuWt^MpH_^[]ËEtG@3_^[]ËEt*@3_^[]ËEt @_^3[]U 裫S] VWjRW}聫 t%NE_^H[]Ëu~K WOPjPt* WL+} _^3[]ΎEt H_^[]Vtq~t0NFjjjjQuЃ RЋFNFjjjjQuЃVku^RЋVSu^UV u3jQjEPrBЃn|sh3tF^]ËB w$PCC33ݹԍEPUF4EMjjjEPrBQЃ|rEMCC%CCCCCCV~t7NFjjjjQuЃF^RЋF^U\SVWE ;F4Er ;F0]u4ȋF@Ƀ|u| t 3G_^[]ÍEPu u9 y R3G_^[]ËE$ D u>Eft6}$u  3G_^[]fECEMufEftfECu _ up,ȉEU EȋȋU j ruVpC_^[]à W3G_^[]à 83G_^[]jGGGIGWjprut CW7r3_^[]F FF|C~_^[]ÍMQQRPuuv2Et%u$juVWЃu3_^[]ËMtEjPVWуtՋ}tf}uj֋i!t_^[]à t G_^3[]U SVWtw~ WfEr1w~v)]}D49;^ rw;~r6p~ t7pw pWpVp_^[]U SVWj(put G3_^[]Ë] E u } Pput GVLp3_^[]Ë} WfEr>wt8UM@@@ ;rw;rΉ~Ɖ~ _^^FFF ^[]U(SVuW} VU]}y%腈 C _^[]Ù3ۉEWUfE܅r{w}tuME}܉EQ uƋuA@HuRh'YUME;U UQ rwQ ;}r}Vy(E H _^[]ÙȉEE+ȉMʉUUʉMwrw} wrwVjjhXSbvjj,Vj-6Vj6Vj-6Vj6Vj6@Vj6Vj6Vj6Vj6Vj6Vj6Vj6] SW@SWuuuEP~Vjjh|XSuVjA6Vj96Vj16@Vj&6uu?Vj6Vj 6Vj6Vj50] VjjhtXSKuVj5Vj5Vj5Vj50usNjىEVP5VS5} wsEVP\5VSR5}w EsVP05VP!5VP5VS5 }w]rVP4VP4VP4VS4E x,tx(x$tG3VP4VS4tGVPj7sVBt$跄E t H _^[]ËEU_^[]SVCtt"s8t6zkv rkVlkC tt%W{^W8^us@C<_t6^v ^V ^ ^C@[UDESVW3%}WEjXSuظXS]D]jPeN83e&N@3҉EX&MEut uuf Ff!Vu#u V8upP؃]E}uQuLu V@uc"u.s 3]S]ޅu_^[]É؉]EU%}u-F,N(Mw rwF4N0MEu V4F0ȉEEUMN0UĈM‹N0EŋEƋ‹V,ENjF(EEȈMËȋˆUMɋN(MʋN(E͋E΋UЈMˈEDu F4JN0JN0JJBBBFTNPMurQ FTJMJEEBJBBF0EF4EF(JEN,E;f+jEZE܅tqfHM@fH ftHɉMt*QZEu3uMQP"M E܉H uPFZ3@ V4^(N,EF0EEU]E%=u9w.r}s&w"rsEt~Tw r~Ps3 E܃}Eu'-uF WP9"WS/"}-uFWP"WS"^WP!WS!^WP!WS!FEFEEPuHpx MfHffHffP!uSz!EDNj}WPU!WSK!uW^ P;!WP,!WP!WS!N(0~,w'rs EE ]É]WP Wu Wu WS N0 ~4w'rs EE ]É]WPl Wuc WuZ WSS F8 t@WP8 WS. N<Et(fU}A#ǩt fA ffЋ ufU}Et)fUAt fA ffЋ ufUEEuPuS}'F@t@uPtuSh^DuPXuSL^HuP<uS0^LuP!uP@uPuSFP~TEwFrs?]SPESPESPESP 7]ShShShwShl ]N8tASjP1]tSP Nt3GOjjjjPuу Rы^EGuCtF _^[]_F3^[]UQSVW~t}E =wsMrwiutt]F>^EE jPQRuuӃ_^[]ËFPWӃ5|s/u tF _^[]ÃF  _^[]USVWuG t4_^P3[]j PuG t @_^3[]ËEFF FFFFtjOt_p^@ @@hC[]UEDSVWO$jCE @@@33_^[]Ëu >MU }RUQ=ʃL$ ؅|Fr@ 9F6u2jQj@D$PwGЃ|sz_^[]ÍT$` yG _^[]jjj@D$PwG7Ѓ,|s&u tG _^[]ËL$ t#D$@;FtFF _^[]ÃtZD$(;Fu D$,;FtHFF _^[]^UNuT$ 3F_^[]ËNSa$FT$ _^[]ËU :t2MBABABA0BA BA$3 A4AA33_^[]ËU MBB A33_^[]u M33_^[]hChCjCrjCjCjCUWщUu_]Ë Ut MȅuSVډEGEf9CuaC f;G uSS G r ;uste :u'tZJ:HutMJ:Hu t@J:Ht8GuEt3fDw 7LWLuG% CËE}8EU"^[_]USV3WU;C;eKfKEC]fE؉];jnKEMGEfGfO ft9u3"P1K؃tMPuSC _ t-]G tEU}8U}WJE t @v >JVJu_^3[]ËE t @t_fDv >NJVHJu_^3[]ËE t @tfDv >JVJu_^3[]_^[]USV3ۅttWucupDFf;tf;t tދ6F;ΉEEE@v >IVIuut3Mucupu_^[]UQVUtgSW}F#©tN^WPWS^ WPWSF ftWjPv PU6u_[^]UE SVW};C4r'w;{0r 6_^C[]{@x@PjPs} y#Ma _C^[]sE jjPct#a _C^[]MEfEfE s jQs| y`t?_F^[]ËEKMtPG؃ut F_^[]uMPjSDbU;sNSMGu]t"`t_F^[]Åt_F^[]Vh0SFfЋI<A<@Otyu@u t GV>_^3[]_p^@ @@pyC[]UEtvQF33_^[]Ã}w }@uF Ft0E 3FF @F0@ F@@0@_^[]ËFtPoBL$QPp D$P6u+M AA0AAA A$A4D$8A(D$utV7G3G tSf7wtVO7_^[UUщUuA]Ë WzMBV3E|S vrY tT tO tJ$t ϋNj_^[]Ë} EuWfD$L$ы|$_^[]Ë]$ (  fV҃O+Hw$C( ~t̓ u ~{~SKjjh WRu уPуȅ|Cr=|WrQ u FFF-  uAtC C FP  FM3ҋ( ;w}r;s+ʋ_^[]Ë_^[]ËM  D433_^[]Ë } @rfB4 rtGB GB$3 r3_^[]Ã3 3r3_^[]ËM AB3_^[]u {233_^[]ËE _^[@ Ћ]Ð҂CKCCCZCuCCCCCCCCCUE SVW0$DC}u ^WOjjh SRukуdž8  dž< dž@  TF _^[]Pу|su tG _^[]G _^[]Ëu >t ϋNj_^[]Ë} EuWfD$L$ы|$_^[]ËE]$ ( (   Hw$\C ~{~tztvSKjjh WRu уPуȅ|3r-|GrA u Fb  QuAtC C FPFF  FM3ҋ( ;w}r;s+ʋ_^[]Ë_^[]Ëu  tfFt_N$tXP4tRv(ыFN$Pv(уF33_^[]ËE3fH49H$w9H vPHutH P$33_^[]Ã}wrJ}rDU MB3҉A_^[]u .33_^[]ËE @_^ []CCjCCCClC(C(C(C@C@CC(CUQSVW} ] f}Et"E @3_^[]j;.uE p3_^[]ËFFxV4F gE#FxV4QAuj+3jQW}t"j-u&G t @V-3_^[]@ @@pCp_^[]ËE t @_^3[]U}WSVWfEw } MCuM}MUuȃ2шUt>KUjKUщCC ij@C E[MЉCM;M{w ;u p_^[]U\SVW~NVjjj uuEPRуrh A9RRPEPu`jQj@EPvFЃ|3_^[]Í]SRPу|su tF UYyF 3_^[]jjj@EPvF6Ѓ&|s u tF 3_^[]ËEЉEEԉEEPM؃U:@fHffHfff:G_^[]G_^[]F GP_^[]UE SVW$CU M _^[]u}uMڃ|s_^[]ËM jSVWƋ_^[]ËU3 fB6BBD$tB R$33_^[]ËU MB3҉A_^[]u )33_^[]ËE _^[@ Ћ]ÏCC)CC4CRCUu3]]UQSW}хttC33 RuV E3 ЋR3R3R3R3S‰]ȋuR3R3R3R3ȋR3R3R3R3VȋR3R3R3R3^ȋR3R3R3R3V ȋR3R 3R3R3^ÉuȋR3R3RË3R3ȋ R3 R3 R3 Rm*rH3 ЋR3R3R3Rʃu^t[33 Ru_[]̋HA(A,A0HtA@@@QtP00AlAPAL3AA AA A8A<ǁǁøVuA^ËF FuF(3F CCN(~$uF$CShjQЋ؃ uC[^É^WC4~t=G4t$tPv(F$ЃG4GG$tF$Sv(ЃF_[^UQSڋVrF4Eu-N$jPr(B Ѓ EF4u ^[]W~(uN$~(F0F,U;r#W+SPF( F,3F0_^[]+~0;G+WPEF0PE +ljEt$P+Sv4F( UF,3V0_^[]~03ҋF0;F(D‰F0F,;F(sljF,_^3[]ULSщUVWJMB E؅:}u 9z u B :Eظ }zZQ8q<}܉}3}̋}]Uu]ăYEEfD$CAEu  s-KuЉ]GU}rًMEtIuAj33MUjfEAM3҃U3uAA At@0Aʋ3MuҋU$<tE@XSC‰Uuy$EuLA$M3ҋMjA3 5MUAB0U҃ 33Uu;A$vE@XSE@XSs*uKuЉ]GU}rًMQtE@ YSSq UȉEtAEȋEEtIUUjE MA3U3 s'KЉ]GU} r܋MA tPAt/IEˆUUUjEMA3U3s)fJKЉ]GU}r܋Mq Eȅt‰FA uȉp AtIUUjE MA33UuAtus-fDKЉ]GU}r܋MA Q@tPAtIUUUjMA3EuA t@AEЩA@;FЉUY ۉ]]Et_y Eȋ_ۋ}Љ]]}Ћ}tCMI+ȋEMЋHE;Ev+EQWPbM QA@UЋUEEtAu3R׋MAU+ڋE+‰]}A@kA@AI3D:BEA t#putq@;p s]Ƌu0A@]Et;rAuUt9QUUu EMRMUEE]Y]+]}A t@A@Az3fD:BEA t#p$utq@;p(s]Ƌu0A@]Et;rAuUt9QUUu EMR$MUEE]Y]+]}A t@$UAEtXs*KuЉ]GU}rًMA;tE@(YS 3EuA tU P,A @0j334MUAB0U B s&f KЉ]GU} r܋ʋȋ%M‹UAB03҉U3 y ` j33.MUAB0U yt΃+MUus'U KЉ]GU}r܋MAƒ$0C Uu2ALSAT APSAXUuUuE@E@ZSqEM؉H M܉HM8X_q<^Q8[]E3EEE}M؋]O M܉OMGE{(sMV(*~G0NFFNFFNFV^BVFFNFFNFFNFFNFVBV u} |2F FNF qFFK$C,ɀ$ȋC$ȋC$ȃ;ȋF FVFN@ FVFN@ FVFN@ FFVN@ VBV u} |2F FFVN@  VFBVxt&@N FFVN@ FVFx,tFtO0RmG0EF FN0 x}0|%} @P u P P 3P ȃ~lt ˸BFqF+A+ًNFNF^C~l^t?W2F FNFF_0VˋF FNFFG0FEVzBNىM9F soD;^ u:z,t ;vV+u3 O0SG0NىM;N t+FNPF  ^F CM^VB9F rVz,t#;vV+u3 O0SG0VF ;BuQF IFIFxNىMD;^ uBFx,t%;v!V+u 3F빋O0SCG0NىM;N t0FN @‰EAMF F^C}^t EFx,t ;vV+u3 O0SG0}uRF [F[Fx$NىMfD;^ uBFx,t%;v!V+u 3F븋O0ScG0NىM;N t0FN @$‰EAMF F^C}^t EFx,t ;vV+u3 O0SG0}FggguUFx,tEVN B;v AVN B;w+NG0 FVNG1 FG0Fq~tt]F=u u~tu=uwӋF8Fg1]uM3 O 3+Ѓ Oȍ+;h_K[G_^]Ãu ӋSV@SЃtuF;Sff Ѓ ~?NFfFVN F*ȃf Af ~)NFFVN F3 fu_NFFVN F3f]FC[_^]Ã|ɋNV Ff렃tjj3ҋk,uFD3ҋNLfTHFLEPRvD蒺 ~t[FlF\dž>uVG0N FVG1N FVG2N FVG3N FVNG FVNG  FVNG  FVNG  ?_2NӋFFNFF_0VˋF FNFF[F~؉F39F[_^]ÃuF([_3^]áܤKG_^]VWFx*t!EtIt[tgt qtu{HtF$Qv(ЋFHDtF$Qv(ЋFH@tF$Qv(ЋFH8tF$Qv(ЋFPv(F$ЃF3q_D^_^U,SVWډ}O8GlWxw|MO,EEU9GlvGl+EEMG@E؋G4E܍D E EEE;U@tB֋uUU;ЉEGЉUUE82E8D2:B:AAfH@:JuEH@:JuxV83ҋFl+jPg&FlF\3_^[9A]ËFl;~5xV83+jP%&FlF\xm_^[]US] VuW@Ft=s!Ft=s10rf~lF8VHNXD8#~43#VTFDN@VHfPfyVl#N4F@F\xV83+jQQ#FlF\3_^[9A]Ãt8F\xV83+jQ #FlF\xb_^[]USVuW@Ft] =s!Ft=s#3rE~lF8VHNXD8#~43#VTFDN@VHfPfyVl#N4F@X:Xw@\ M}  fQ< fċu=tvDt\U썻,uk󍎔3Ґtf9uHB~f9u8f9u/f9u& fDf9uA|3G, $  v( e0 fKf~ uKKf~ u8Kf~ u!Kf~ u } K]}  ;G}OэG;wEt] SW k; ~U} ffNf ЋFfFVN F*ȃfAE ff f΋ CP( B@P P ] ] ~K{ffNf ЋFfFVN F*ȃfACff hxS "SfltR~"VN FVN~VN F3f_^[]U SV3҉uWEZ9@Q]< BUU\jS7kS0(kS)*ttt3^økS TkS8kShPV Ɔ^CCCCCCCCCC&C0C:CDCNCXClCbCvCCCCCCCCCCCCCCC CCC$C+C2C9C@CGCUCcC\CNCC.........................  !"#$%&'()...................*+,.......-SVW`IƘx#;8}hWPV ?Q֋gu.PhVPWPhaIuWWhkShV0j VƆqt +΃|j Vqt +΃|`I;tS$aI_^[UTƁSVW`I؁ _$TDkSkSkS lS$lSG֋|TLJ|TLJt t*uE@ t uSVЃ ؃*tiΉEǀǀVu7Euuh8I&Eǀ3u *Eً@ A t"BuUuG3_^[]ÍƇGBVHt]FHTF|TLJTFBt t \UUG@yH 3F@t99Hv,htSW[1Et2҉8E3;tS [t(ZtWtPvDhtSW0LJ U{uE؋E|TLJ|TLJ_^[]U SVW? Hy~@fF NEtE91tE} O-Nt7F w,@@%…u:Ut UN1E+~<uF8F<Vt }tuVN]聛G膲PGt3GdžPGdžF !!Ft FF@Ot9pt Ru j&FNtGFtAO ='3_^[]O ωG''3_^[]ø_^[]_^[]̅tQ`t2UQaGVWyA ~ }q $ DI@ ljRQЃ _^]ËIR@$ӋI_^9hE‹]ËI33uB8uu:u_^]Ã_^]Ët 3: N_^]ËI@(q3S3ۋ>@,tjRVЃ [_^]ËE$<u3ɉE$*<u"9uu 3ۅÉC[_^]3_^] D D De De D D D DJ Dc Dc Dc DU(SVW3u]}o> cU#Ex;L؉]FEtMQU܋3ҸttGttGtBrًEEuut$PtTEu _^[]3ۅFEQU܋3ҹtuD܉޸fDCt܋tuD܉޸fDCt܃tBrEEuutuӋN3ۃOu3V|TEt3_^[]_^[]USVWT$3D$@RSЋ7QVD$x@*7htSt$S*UtƆUj3ҍL$3t 7D$D$P׋u*9p uA9p u6|$u/T$Yujtt 2藓3|$t@3ҋt CHT$-t2ҋ>|$WS@Ѓ7_^[]Ë|$uk?tfƀ;FȋA;t+ыp\$fn^ XS;t+fnXP_^[]U tG D$ WHQ;ۃLD$tt 2&D$@W΋VD$<;ۋD$@;uT$8;tƀ jj t D$w|$t tI&SG 1|$D$t5L$ P3ƒ9G tG &StWЃw`GwO hu(E&SG 1WЃ&&SG  WЃZt L$Wt L$ D$ D$@L$8AHttPt pjjQ҃t$@T$ KD$(t@T$8JHt$tq t$@wtqjRT$LD$4 D$@t#t$h`vSƃ3W2# T$@؋D$@D$(L$ |$(D$@t HHǀT$j؅tL$@2yto|$D$t%L$ P3ƒ9G tHG &S2O hut)&SG t&SG tWЃ:D$0D$@UtƀU菭؅uZL$@u8utCht:@@t)D$Pu؃tD$@UtƀUD$3ۋnt53S3҉D$q WG g.sku 8uVhI D$8&SG $WЃD$Py2؀|$u8ut hu)  &SG  WЃ eD$39G  G 3&Sw WЃl 23ۈL$D$@8at"8ct"9XDȈL$w8cuj衫؅u]L$@u8utHetZt ht3)@tQT$RQЋ؃u L$@Ɓc|$u0  &SG  WЃ D$뽅uAL$ 9G G &SWЃD$A jӋD$) 3ۅt29Xt'\$T$RQ@ЋO ؊D$L$@D$@D$u L$ S53ƒ9D$@Mqu:   99 ƀ t&SG tWЃD$Q Yt<Ut ƀU t&SG tWЃ3ۃD$ T$؅8D$u}8ttNGtu>j3ҋ d&SG PWЃD$  t&SG tWЃ3D$t O `t t&SG ʃ &SG 7VT$D$D$1t D$ |$D$jӋ|$tXt7tT$R|T T$j.؃u) tWG )3ۉD$ D$t$|Tp >4j!3ۅt.9Xt#\$T$RQ@ЋW ؊D$  D$u `3 ;G 3&S3ɉL$$3ۉT$@@L$$QRЋL$,؃DT$@;FȋAD$@ML$@p;Ƌtt$8t$0wt$++D$8fnfn^ XSX+fn^ XSD$@PL$$3E zT$0D$(99t Iux rt$8wq;u0wu @7A@'ApyAuD$(qpw qFwD$(H z u$ A@B JL$0ND$8w@AD$8AxtpNwHL$0B JHL$0B L$08tƁjj L$ u!u 9&SG  !&SG  WЃD$Xqu>@2 (99 ƀ &SG WЃD$~<t *u uÚ؃WfD$@|At;u uQP&:(T$( D$DD$(D$@WD$fD$8|=t7u uQP9(T$tttGt t>G 5 G@G H&StWЃ  4L$ ƇaGƀƀtt9:t Ru j)t"tD9:t Ru j)|$t| tG@G H&StWЃt$ uJL$ GxXIPQ( t&SG tWЃL$  uw~t%QP׋?ME؋EuMEQNDUP>*UFDtuRuAˋEN_^[]_^[]UQSVW? _hCt3AUtƀU2ҋgyu͋trG,A8N8Mt#FHttPtpjjVҋMj3@>tFHttH t pjVу @OH=t=O3&O3&w~<uaF8EFHttPt pjjV҃M3j=FHttH t pjVу F8F<džF@uO,=t3&LJt3%WLJ|T3_^[]_^[]UjjTEUˋEVjF9t>}MUBtv r QuuЃEFG}uUV|T_^[]Ë]E{4s u63~;tt@;|u؃MU؃Hj:ȃSEtmt-x v'E9ut9EE}t@t&x v 9uQt92҄t@5}t/UBtq r jVSЃMUju؍IHc9Eu@Eu;C4PEPC PR {4_^[]UVWMx@tOuStjUOHd9M3t*Wtp w jV1҃jUuOH8[_^]USVWPGUMt^DCEjh0@+E RPq+uʉEiuʅ|ujӋ!E؅uU7u0G34G_^[]Ë0GA4G tcN;7uuO$F@FHNFuGA6GjVFF|TU O 4Gu0G8GND"FD3_^[]UM3҅E9 9E ='Ft7t(tE]ËE]ËEA`]ËE]à t'-'tE]ËEA ]ËE]ÍMN%]=$NHt9-'t t-'uFEA]ËEA(]ÍML&]ËE]-.Nt/- 'tt ]ËE]ËE]ËEA$]ø]UQSVW~D5Tȋ5TMNDk ЃVDJ ;M|NJ;}3;~5Br +jhRP蛺+uiu$3_^[]3_^[]_^3[]UVWU!t _^]ËUyHx yxKKjVЃ _^]ËNDA ;| A;|~+A ARVЃ _^]_3^]Uu |T]U SVWU3ۉuj]tT}EPWMU9^ tX6tO]䐋jh8@+™RP+}iʙʅ|uUދv]u]}uWӋxuW|T_^[]_^3[]UA@SM0GEMVW}jhu WQ 0iM+iÉE=@B| AME}?u +G]jhRPM+EiMuxtPGUm_^[]ËPGYu8GNDQ tPhvSS ME8GGLGwND7FD_^[]Ë]uUQSVWbjhu u,Mi+i=@B|F0Gu 4Gt4+4GjhRP+0Giʙʅ|uu u'_^[Y]SVWK@0Gu 4GPG8GDQ StPhvSS O t|fDwtgtcN;7uuO$F@FHNFuGA6GjVFF|T O G ȅuǃ0Gǃ4G_^[U SVW}w6DFE{ SC  t`N;7uuO$F@FHNFuGA6GjVFF|T O jjE}W_^[]U =TSVhD$ 2jP:5LaI D$D$ D$jjjjD$(jjRPjj RPjjRPjjRPRPj3D$PPaIӹvSEѹvSEoTthwSPL`It УTu ^[]^3[]USVW}WUfGG蚄j\V57uj/V&7u E,wS3 ؉u+PpTȃQffu+ʍ]POtTtuSuWG3f_EVx_ |TMtLVpTȃt2OQffu+VO|TG3_^[]V|T_^[]UVW}@EEMEEPu +EtEt;EEu@NFu+tVQjWЃ_^]jjh&S艅jVPt _^]U SVW}M+EEE@,EEPu tEt;EEu@ t)dFu ,h`QShPƇdF@tz,NfFu+?s3 F,,tVSjWЃ_^[]jjh&ShjVSY _^[]UQMU SVW~+~@<ttmjjj# tXtTu.hFtT~ȃFF tFjWPS|bI~ FFjuuSxbI}uMbI؁3'uQ3_^[]ËM+PEh0wS0E hF7_^[]UE USVW}M>tuFN ;v%+;B‹؋SPuCF ^ N 3;u&6|TFFF ~M_^[]ËUMjRuQ|bIuEuHbI؁3'uEQ_^[]ËӋ PhDwS7 hFE8_^[]US] V13҉M3ɉEMUWtl;\Ft A8_^[]ËXFWTFxTȃM u _^[]ËXFSuPAE TF3XF_^[]èt pUt"tu90tpMȉEEE @;Ft (WjP҃=td;uDE Mt(0WjPу=;E MljE +UWPhwSVA_^[]ËE􋀐@@thXwSV_^[]StTSu W@E\FBhwSV_^[]StTSu WX@dž\F TFXF_^3[]USVE8W@@t@`tp8u2]3;EtU+} ;B t'WPu? Ɔm3;_^[]ù@9M BM &M @E;| @EϋE}WQPRVЋy E_^[]À}tW u? ;3_^[]USVWڀ(EKwS$BDwSwS wSwSRQPhwS\hP#\NFu+t!\VQjWЃt3_^[]jjh&S}\jVP} tu uSWЃ_^[]Ãw/]&SjjP}ju un} _^3[]ADADADADUS3ۉU8]VEE؉u3W}t ~t&tkt}u33_^[]Ë;MЋ™؉UEuKEEU}8@jht#+tRPȋE+p!+|RPߨȋE+xi߃+U u _^[]Ë_^[]UUSVWEEElhEu fhhjPf. ύQfDAu+ʁjhhjP(. jWhHxSx uWhTxSS -_^[]jWhLxSF u}EMu ǀMQj!u MUEM쉈EBuRhhPzEphPuWhtxSS`U# }lPhy~iVfhpbIfjEGWhxSS -_^[]Ã}u$VfhpbIfjE3=HbIPhPuׅyMEHEPhxSS FfhuVbIfjuhPuׅxhEjP', EPPu\bIyhbIM։hFDPVhxSS-_^[]bIM։hFPVh$ySS-_^[]PhxSSE ƀo_^3[]UESVىUWȍxf4<u4}EtP~vtFCPE8t9~t vu*u֋ ЃUu vt EȋE0ut[t'{8t;u*t!ƃ֋]VPbIE_^[]Ë֋CC8Vs<ЋE_^[]_^[]VHH~"fւ$H*,H.f0H48HDHH~TfցXH\`H`fdHlH@}舸3ɉE싇UEE~tt u;M™EUE+tjhRPȋEU+pi؃+EEU ‰U }U3ɋt@AuFPjhFTdžFPUxuE jjRuJFPt'WЋv؃t FP@FPu?uD؋_^[]ËEG3_^[]hySu _^[]UM E;u A]3]UVW t=NDu9N@t1}EuN@hYDhUR}udž _^]Ë_^]U`S]3EщUEE]VW| u r3۾]u }u/;u+tyh&'TbI_^[]V,aI3_^[]Å|tu轵UUE3ɉt!DžDž9ED;tB3Džt9t@;r;u@s ;Gׅ |s3}؍B}EԋM|-t'Mb‰Ei+iE uE؉EW3ɍ9PD9PDPuDbIbIt=ėT='ZP@aI؋ʺwM]ȉEú/$j؉UЋwhȉUE/$ωẺUUًMЃ]]3ыMʋUЋE+ i+i+ERP蘏M+i+ΉM]}]3bIt/QSЅPbIESЅbIt}t'QWЅtPbIWЅt_^[]U`UMEESVWo3eGHttHt pjjWуuUutuh({SWJF 3ۋGHttH t pjWу uMEUMQuEu09EtMUէu3ۅËE 0_^[]ËGHttHt pjjWуuUuGHttH t pjWу uM&[E 0_^[]ËE 3ۉ0_^[]_^[]VWt FHttHt pjjVуGuZW|TtFHttH t pjVу _^UVuFulZV|T^]WjGpiEGiEG eDGGtTV3fjtTt@ @ eE@<t F|^3_ÅtN3ҋ uP|TG^_G_USVW]~8-M@QQhL{SPft 3hX{SAuPhzS~؃ P t:tP$NFuNFuGH+ttHt pjjWуO8FPGHttH t pjWу S|T]QMQQh{SPt 3h{S]uEPV9VPUQ[EuPhzS_ E(t:tPNFuENfDFuGH+ttHt pjjWуUFO8Pu|Tu0uUPtNFF M+WGHttH t pjWу tRPuPh{SW-3h{SW []jLJ3_^[]ËMV_^[]SVW9p6|Tvu8t|TLJt|TƇLJ_^[U S]3VWU3EEt8׍JBu+эE3ɅjD9MPEDP[ uXE}t;u$t ?:uhITED}7|TEt3|TE_^[]U SVWN@tNDt[PGt3džPGnGdžHtpG|TdG|TdždGdžhG|Tdž|TLFdžFHt 3D$93|$| ˅toGuTW@W|T|$O D D}4|Tt|TD$DLF|$@@D$|$;kS|TdžLFDF|TdžDF`F|Tdž`F輪|Tdžt|TƆdžt|TƆ,dž|Tdž,$|Tdž$#pF|TxFdžpFdžtFt$PT@$xF|TdžxF|F|TFdž|FdžFt$PT@$F|TdžFG|TdžGH|TFHdžHtFtPtpjjVҋNHIFHIHFHttH t pjVу tt GMV|T_^3[]VjIjFIjFIfdž< 83FXFFdFHFhFlF@XdždždžhdždždžxFHFLF0dž0džTfdž,Ɔ.dždž<džF džF$F(ƆdžDƆdžLdžPdž@džDƆHƆ\dž`dždƆtdž|<džx<ƆƆ>fdždžƆ^USVW3t$  &@D$DE_^[]ËE98U_^[]ËE_^[]ËE98B_^[]ËE98C_^[]ËE98@_^[]ËE985_^[]ËE/Dȋlj_^[]ËE988_^[]ËE980_^[]ËE981_^[]ËE9tƆ8H_^[]øH_^[]ËE98)_^[]ËEt4t$dž_^[]dž_^[]É_^[]ËEi_^[]ËE98_^[]ËE_^[]ËE98-_^[]ËE98,_^[]ËE_^[]ËE<_^[]ËE98+_^[]ËE<_^[]ËE@ljD_^[]ËEP_^[]ËE_^[]ËE987_^[]ËE983_^[]ËE982_^[]ËE984_^[]ËEH_^[]ËEL_^[]ËE98Ɔ8H_^[]ËEʋ؉L$9d2|9`s(P9TuP|TL$PT`ljd_^[]ËE$_^[]ËE98_^[]ËE98z"džHf8_^[]ËE| _^[]ÉL_^[]ËEu<_^[]Ë$Gt3A#u|_^[]É<_^[]ËE_^[]ËE98*_^[]ËE$_^[]ËEu@_^[]Ë$&Gt3ɸA#u|_^[]É@_^[]ËE_^[]ËEt!Ɔl_^[]Ɔl_^[]ËE98`_^[]ËE98E_^[]ËE98D_^[]ËE98F_^[]ËEP_^[]ËE98X_^[]ËElj_^[]ËE_^[]ËE_^[]ËE8_^[]ËEi_^[]ËE_^[]ËEi_^[]ËE_^[]ËE_^[]ËElj_^[]ËE98_^[]ËEffh_^[]ËE%l_^[]ËE_^[]ËE98T_^[]ËE98_^[]ËEtU_^[]ËEuhP|SV+_^[]Å_^[]ËE98_^[]ËE=~dž#}dž@_^[]=@L@P,xT,-_^[]ËE98T_^[]ËElj_^[]ËEH_^[]ËE$鈆pq_^[]ËEL_^[]ËE _^[]ËE98V_^[]ËE98W_^[]ËE98Y_^[]ËE98_^[]ËE98`_^[]ËE98a_^[]ËEd_^[]ËEh_^[]ËET_^[]ËEX_^[]ËE\_^[]ËE98h_^[]ËEH $8Dl_^[]øl_^[]øl_^[]øl_^[]øl_^[]øl_^[]øl_^[]øl_^[]ø l_^[]ø l_^[]ø l_^[]3l_^[]ËEG_^[]ËE98t_^[]ËE98_^[]ËE_^[]ËE_^[]ËE98_^[]ËE98_^[]ËE98_^[]ËE98_^[]ËE$鈆_^[]Á't,D$dDE8|TdžtWT 3_^[]ËE8|TdžtWT3_^[]ËE8|TdžtWT3_^[]ËE8|TdžtWT;3_^[]ËE8t ?u|S|TdžtWT3_^[]ËETP|TPdžH_^[]ËEdžHƆ8_^[]Àt|TƆE8|Tdž3t.WTu_^[]É3_^[]ËE8|TdžtWT3_^[]ËE_^[]ËE_^[]ËE8|TdžtWTV3_^[]ËEe;suDt$3{|TS|T߅udž_^[]É_^[]ËE8|TdžtWTux33PuD_^[]ËE(|SltiFHttHt pjjVуt F|;{ FH5,H !pjVу _^[]ú,|Srl3FHttHt pjjVуT$T$t$ڋfC C L$;ENj;uL$ s |Ts|Ts |Ts|Ts|Ts|Ts,|Ts(|TS|TL$N T$ӉT$مR>3t$FHH pjVу _^[]ú4|S+kt3ҋ{_^[]ú<|S ktf_^[]9ujj3ҋ`sST؃NHD$t+D$t"QD$tqjjVҋD$j ӹD|SkK uˋT$jjQP|gFHttH t pjVу S|T_^[]S|T_^[]ËE8|TdžtWT.3_^[]ËE8|TdžtWT3_^[]ËE0_^[]ËE _^[]ËE(_^[]ËE8|Tdž3t1WTux._^[]É3._^[]ËE,_^[]Àt|TƆE8|Tdž3t.WTu_^[]É3_^[]ËMP \_^[]ËE_^[]ËE _^[]ËE_^[]ËE_^[]ËM$P  _^[]ËE8|TdžtWT3_^[]ËE_^[]ËEj2_^[]ËE_^[]ËEp8|TdžptWT2p3_^[]ËEx8|TdžxtWTx3_^[]ËE8|TdžtWT3_^[]ËE8|TdžtWTc3_^[]ËE8|TdžtWT3_^[]ËE-8$_^[]ËE8|TdžtWT3_^[]ËE8|Tdž3t1WTuxA_^[]É3A_^[]ËE8|TdžtWT3_^[]ËE0_^[]ËEFHtutHt pjjVу~<u~8~?@ABCDEeeeeFeeeeGHeeeeeIeJKLeeeeeMNeeeOOeePeeeeeeeeeQeeReSTUVWeXeeeeeeYZ[e\ee%%]ee^e_ee`e%aeebcd,{D@{DT{Dh{D|{D{D{D{D{D{D{D„DUDUD݅DPDsDADD~D~DքD{DDD~D D D(DD-DD̆DDD{DDDɕDݕDDDDADUDiD}D-DDD     `D}D˖D&DCDDV񋆴t2P|Tdždždždžt2P|Tdždždždž^SVWGHlt-3ҋFyu džUu@ A VHtFHt8tyGHttHt pjjWуD$PmT$O8D$D$D$ D$haDD$(qGHttH t pjWу Օ\ʕ@0tSVЃvDh|SW8p D$tKKt(92t Ruj$D$Kdžp{u ӋAD$tHt-3ҋ$su dž@uGE+jhRPDȋڋE+i;]|;Mv M]}}vu]Ut C؉]u4E؋ʋp;}$Au ;|U ؋щ]Ut C_^[]VWG;Fu!G;FuOFtt Eu _2^ÅuOFttEtu؋OFttʋdEt_^Åu_^UQVu@ A uK8F@uF@<ujjj, tvDE h|SP蒐 63^]Uh|SW 3 t 3Ʌt֋RtNv=8FXuvDh}SW豍 LU?Z@A@;tI<);;B<=T0L$Zt$:Z[:[ t!t$L$WD$:WXD$:XML$e:euPt"44cVx c4'L$t$|$ u ~@\u D$f9`twf`t$f;`t$0dt$;dt$0t=\f:utP:Quu3ۋ\$xxhh:utP:Quu3GllfD:utP:Quu3tu eL$U?u*K<8\$;A<T\$|$t ?|$t;o>V;Dt1a't|$D$|$}hh:utP:Quu3ll:utP:Quu3t zD$`R:utY:Xuu3\$: utH:Juu3D$L$^V8D$ D$<L$$t+;r'|$Ph~SW貈 \룋D$D$H@t3؋t3D$4D$8D$,t4t.pP@Tt$4t$0D$8|t;| 9\$4v\$|t9V,| 9N(v|$۹SSDPv,v(t$Dt$DVvDhSWӇ$th4~SW\$$|$$D$<\$;D$@t$(D$@wt$(t u t^\tUE D$t$(toE0_^[]vDD$UDh}SWD$ ( \$ً|$D$|$DtD$D5hH~SWD$덄t!D$thh~SPӆE_^2[]QVWhxjTdždždždžUdž'SFDdždžtƆU]>džt 8t2Ytt tu2ɈZtu2[t8tƆYƆ[ ]*e\DhEiVTU:89 G@t-@`t' ujh@T jtTt@ @D@jtTt@ @D@tTtPtPT\t2ldfhf`F8F<_^YË3貛3襛 dždž|T\|TV|T_3^YU,ESVWUhIEEhG] ^th\SWY_^[]Ë<:uh|SW3_^[]Ph|S1tF;ru;~s$u7Ph|SuG;ruEVM<.E֋+U;w*+ыMUVU.t;ut#Ex.tw}u;\_^2[]_^[]U싁SVW8|tP`KFu衄SfSfFSF|P TaIƅt0hQPӀtPT|S?-u~|BJ؀G؈_tuݍ|Pq TaIƅt0hQPӀtPThS# ƅt,hQPӀtPTuIhSƅt/hQPӀtPT_^[]3_^[]U$SVu3WىUhSV]EEEEӨxjS}t,jֹS[,t jֹāS<,t jֹ́S,t jֹԁS+uEjֹ܁S+u0jֹS+u'VhSSw _^[]ûCu] u]VhSSow _^[]Ãttt EuEj@WLt2jEPE+P E~EE}E?[GG}t"PuMu <:t<.uFFu<%umjVh S  th$SuuFFtAPKu"P Mu<-t <.t<_t<~uFFu<]uFhTSu_uj:VDtWj EPFEV Ett:t3j:u8+lFtZpWfEEt8+tA-IDEPhSEj PkblGE슏^IPhGlID„PSDPSDP0hSc$u F_^[]Àt|Tƃ}@83_^[]Åtj MFQP xC=tQj EPV,M ؅t9uv,Vh`Sum E W|T3_^[]uTMuW|T_^[]U(ESVWM3ۉ}I Ɖ]M]9:EEuq^SDPSDPhS`ȃM܅=VFu+ыMV!u|TE}<0:F>:ut2j:VmtGj E]Pu 9uu.;u&EPEVuP.]EEEuEt(8t$ShSVƇWk SƇW|T3ۋux,VhSuƇXkE @EfEƇX@EN_^[]3_^[]USVE3uEWҋE~tt{u;Mы™EUA+tj™hRPȋE+pi߃+}U u ׀VtM3_^[]Ë덀YXWEt}DE URQ蜔}}D4hԃSujE ECHE_^[]Ê[ɈMEDƅ|~rxMQuEECHE_^[]ÃtA}uB}D4hSuKjE ECHE_^[]EE_CHE^[]VW|T|T$B4B\\t[h|TlLJh|TLJlhhlldžhdžl]]|TLJ|TLJ|TLJ|TLJdždždždž|TLJ|TLJWWXXuƇVh|Tldžh|Tdžl|Tdž|Tdž|Tdž|T\dž|T3dž\2~3%~ dždž|T(dž _^UhSEV]WC@uEEEEEEEEEt MEt EEEu }>NFudG+;B|TǃdGǃhGVtTdGt=VhGtTumdG|TǃdGǃhGu|Tu|Tu|Tu|Tu|T_^[]ÉhITEhITEhITEԃ}p}f^EԋPEPEPEP=8Etq0h SZW E <:t@P6v<:u逻t|TEƃ@@@tj?hG覘tHtPTt{]hjPJ hjP4  thPP E$thPP ƅQjPQQPPQ`t$PTEuhSS}ctPTEth$S@5TaIƅt4hQPրtPTuL5TaIh0Sƅt,hQPրtPT3(u2(uu}u8}u2E&u|TEu|TEV|Tut >t @@tV|T3uMt 9t @@tQ|T3ɉMuu@fZ׋V9u|T EMt-Qu|T Et#@<ueu LJ'S Ƈe2ψZtXuDu;LJ|TLJƇ[ Ƈ[2ZutYufLJY2Ɉ[]e@@t tƇe׋z9t&u|TTEct&u|TTE4t&u|TTEԅƇk<tIEPU ~hSS^ ƇkƇ\E3EEE@@ t3\u*hDSTht8hPST(uThtuT3ɋljl9ht(;t$E8t!PTpD8׋ыErBu+t| . u @tIxuh~Su]WtaыErBu+t| . u @t&Ixuh~Su$]Zt\ыErfBu+t| . u @tIxuh~Su\[tZыErBu+t| . u @tIxuh~Su\\Wt&Uߋt ƇW2UߊXt;u ƇX2ɄutZtƇe7|Tdž|TFPhjP薔F` FdLJHtWыt} @8LJ),p;L$tt&++pfnfn^ XSX+fn^ XS8@@t 3_^[]ƆntB|TdžhSGu _^[]LJY+u Ɔa΋VHr0_^[]+p;L$tt&++pfnfn^ XSX+fn^ XS@*p;L$tt&++pfnfn^ XSX+fn^ XSHƆab@tU[t(ZtWtvDFXPQh~SR.S)_3^[]VtƂ`8ƆGƆ`Gt džHHu džH)W΋‰ƆFpFt,0$jƆjfֆGujjt3^́@w8teI?"D$Døøø ø@Áw3t+ttøøøÁt Á wOtGw,t$ttuuø@øÁt9t+3ø Áw2t*@ttu(øø@øÁt t3øDDDDDDWQTu_VNFu+?"uVGPW跬 Nt |>"uD>N?/tW|ThlIT^_Åt |>/uD>^_SVWGHttHt pjjWуϋP u6hȅSWO vuËt*fD3s|TS|Tޅu܋GHLJttH t pjWу _^[U SVWj\'3EUE@V‹N >tp;Mk|;Usd;3u;E8K v |Tv|Tv |Tv|Tv|Tv|Tv,|Tv(|TV|T$uu_^[]U<SVWjUԉM&E܉UEj8jT؃]}9htT}u j;VEt@ t uNFuEEWPhSVƅu׍JfBu+эyAu+&et-FN< t< u!t< t< u t FNIuƄ }tfDD< t< u Du}t< t< uFFuu{=PTCVTC{tEC,*8"u@j jP'}܃ CȉS+E;|;KS6uDSt C0@St C2#}=xItt0s |TVTȉC "XCS00>.uFuj.V觀uֹ$S0SE}}}E̅PEEt5teϋƊ:utP:Quu3s|TVTCQ}C$O@GuU+NFu+;r-M+‹ЉE/t;utÈx.zuVh4SuEJ dSts(|TVTC(VlSts,|TVTC,*tSt!s |TVTC @E980pt< t< uFFuj;V~}}>jV~EUKS\K tUUEE%wU؋M ʋ‰S Ku C|sCC}{uEtPTCti{ ug}t`j?W}j/W|t<+FFPtTC t!VWPNC K CuEu|T}u {s |Ts|Ts |Ts|Ts|Ts|Ts,|Ts(|TS|T3_^[]Íp;f>/N;sLu j h|SVE u C2>#tj V|tj V|tEBSP3E}}$tD>.uFVTChE_SC$FθS:utP:Quu3teθS:utP:Quu3t5VTC u ECEhlITMC ٸDhlITMEAˋ]DȉMSC0Lj jV CS7VTCu&E VTMCɸDȈMPhBSzFFu3E@E$uhITC}uԊNu8Nt C CK162ɈM{NNCtptpiteF$:C$u]b>CF~7fPhBSyuC{߄uߋ] ?t{]tMt1NCttMu)t2ɈMMu܋6+}E{1u ~1v|Tv|Tv|Tv |Tv|Tv |Tv(|Tv,|TCSFC F ~C0fF0|Tދ6uM3uԀ~t2sɺSsSs DsssPhSuhC$}utF _^[]F _^[]PDtDDqDDDDUSVW}3ۉMEu>jjTE?SEPTMA߉]Ct[I:utP:Quu3uPE>thSV3E uC9htT؃]tFVhW2Ѓ DʍqAu+t[| uTtp2N3S|Tu ]s|T S|T}t t V3_^[]óuVhWЃ wVtOj ׹D|SsO uϊ„t< t< uAAujjQMRUuuW|T}t V]_^C[]UESVWE K 8tQfDAu+3ɋW trBu+3;t _^H[]ËKtQAu+3ɋWtrBu+3;uKt#Gt:utQ:Puu_^3[]_^[]U$SVWjuG3ۉEUE]j9bEPB?EW‹O t;M ;U0t } Ot|$teeu^VfDFu]+SCu+;r(+EЉEt ;t.Ex.t%eO]uыGENFu+uT؃]j?SstˍQAu+t;/t%S|ThlIT؉ErKCu+;sE2)Vuu Et2;u</P|T jj8TG tPTF GtPTFG tPTF GtPTFGtPTFGtPTFtzG,tPTF,tbG(tPTF(tJG]FCGFG$F$G0F0G1F1G2F2Eu]]?u5v |Tv|Tv |Tv|Tv|Tv|Tv,|Tv(|TV|TM3_^[]ÅtgStTt؋Mt @ u}hDjWV?x3҉Et DB;rD3V|TE_^[]VtdWv >|Tv|Tv |Tv|Tv|Tv|Tv,|Tv(|TV|T$u_^U ѹISVWBlISEȋB EBE؊B$D$Btt 8.IuIz0QrSD$SrrDD$$|$#PDL$(|Sz2WQSIVDPhS-.,_^[]U SًVWE􃻄XtCHttHt pjjSуEj~ `<ϸID:utP:Quu3ujxE}hSW}}WhSR6t:~t(StE0ELEZE      EEEEEE)EDE_EEEEEZE  U SV33WEH$@ Muz>GHttPtpjjWҋMыSYEu M衶OHttA t qjWЃ UE_Ɔ@$^[]ûU SVuWv F8hSEEj P!N^FSPUXt bIӅtӋ^D~60aI~PtV4aItP}jxH0tTU؃t,CtF΅t @ȋAuYޅuYR|TxH8t,7w|TW|Tu܋}xH_^[]ËxH3_^[]SVW3Pjt:O v$u ǍN_^ [_^3[USVWM3҉}3U8=AM<%8u AM FU3ۉuWD33ɉE;EuN}M}ufDjhȈSV蓵 t1jḧSV tZPE$HEjhȈSuL uu ujḧSu( uu@upEp uZXE$EB:,$>*u7NuFMUu:E;ωMNNj} j EPVE @ @ D ˀ uj E PFP E\}UG΁@}~uE};}}6}.U}B]M3M E$@ ERR7RR#RRRRRRRRR RRRRR|RRkRRTRR=RR&RRRRuEZrB @t+FB@ DDD Et&HB @ DDD UAuUU9u ]G@tOF IDTGtOF IDTG $ E_^[]ËO%@=@uFGg@tFGS% = Fu G4 tW'tGGm_^3[]fE"EE$EEEE,EEEEEEEEPE        NE|ETEEEE7E&EeEkEEEWEEEE   EEEEE0E0EE0E)EUSVWu DŽ$t'S$M$3|$LP$t$X$t _^[]Í$$E8E(SDŽ$t'S$%t>MfDWPӃEF@t$PEȊ%uA9%u"AWj%MӃEFt$PT$TL$|uHAL$T @L$L  @t.@|$hy߁|$h D$T D$||$hHL$TʁL$dt%L$L @ɸHȋD$Tt L$L @L$\D$|D$TD$LH$+E\$L\$l$D$pu%O~ fDt$Hj ӃtpOFD$pt$HPӃtTD$LFt$PtO~t$Hj Ӄt,FOt$P|$H$$Ȁ8_^[]t D$XD$X T$l|D$dD$pډT$lD$LD$Xu5t} I3ɉD$X74OD$XD$LuȍAD$TAu+L$TL$\G+t$t$Hj"ӃD$LFt$Pu*~%t$HOj ӃFt$POD$\t@L$XDHD$\t,t$HPӋL$`AL$XD$\Ft$PuɋD$Lt-~)t$HOj ӃKFt$PD$L|$HWj"ӃFt$PD$LD$pD$TD$lD$XL'SD$$D$dDʃ|$l$L$\T$`wtK\$pT$lt$XSjVRS2\$x[؋$Owru׋t$PL$\|$`|$hT$`$+Ë$ȋD$Tt|$Xu  0JT$`O~+0IJT$`t |$XuL$dD$Lu t Ou(~#t$HOj ӃFt$PL$dOtt$Hj-!D$Ltt$Hj+ tt$Hj ӃrFt$P|$TtK|$XuDt$Hj0ӃKD$Lt$HtjXjxӃt$PD$Lu+t$~t$HOj0ӃFt$POD$`$@D$`;w/t$HPӃD$`$@Ft$PD$`;vыD$Ljb@t$HOj ӃkFt$P;t ~t$HOj Ӄ;FOD$TaO(t$HPӃD$TF@t$PD$Tu֋D$Lt$HOj ӃFt$PWDŽ$%fք$$f$$fDŽ$yAu+ϸ +L$LD$pD$T t @t @D$TD$ht |$dt @D$h$ʃ-EDžɈ$$$Et+Gt Gt#GD$Tx&=FEMPhЈSt$xW)D$pT$hxQD$LD$f/r^If/s;эANPhԈSt$xWmL$L  t lG t $ Et $ GfG$ $P$P,e|$X$D$d$}WPӃD$TF@t$PD$TuQ@tL$Lƙ Q0D$L t0|$Hu0 f0_F^[]Ð$E%E"E1+E~#E~#E(EUM UA;AsA]Ã]UEL$D$+EE D$ EPuD$ȃt!D$ t;D$D$u @]]US]Vu Wu1j tTȃtYF 3FF_^[]ËV~B;r;~v'WQxTȃtV~_F^[]_F ^[]UE $PuP,ED$ L$D$D$t2|$ u+|$tD$ $$]hIT]Ã|$t 4$|T3]URQP,ED$L$D$ D$D$7t2|$ u+|$tD$ $$]hIT]Ã|$t 4$|T3]UMEPu G]UE ǀp]UVutNt3"FV|T^]QVW[t(ZtWtPh܈S t-ύQAu+ʋQ8W|T_^Y_3^YUEW}MEEE:tiS]Vuf98tHt Fu.MËy;}  @ u ;|؅t!}u^[_]pPM7^[_]USډMVW3E j tT=jw7tTt@ @ .E@G[t(ZtWtPh܈S[ȃ Mt8EыBEBu+UWRы5u|T u+Ot3y GW|T_^[]ËNSQt!MpFACDAA3_^[]ÅtE׋_^[]UUMMSEE8؅|MW}MVUt Gu-Ep;}Au ;|MUt33ۋr6tuvPUt uMu^_[]U SVMMWEE7tZu]@@uNt Fu2MËy;}"  @ u ;|؅tu_^3[]Ë_^[]QV1ƁgWTHXt1jjjЃPhdSV A_^YËt;jVЃ WhSVr tRWhSV? A_^YÁGFujjG萹 uhȉSVA_^Y_3^Y̋@<0utw w3øU3D$dD$D$ D$ESVuEWfff@EȋFD$ #Ft~Hu+V D$ F$|;sʅt7D$PQ D$Q L$3ɉL$F F$ubF( F,uZ+tpL$ fn^ XS;t+fnXX~F|L$E u9uD$ 2D$ $F\@4t'L$QL$QWSЃD$28D$~Ht{D$D$PD$PqD$@4t<~6|~w.|$~'L$QL$QWSЃD$8D$n|$q~\L$ ~H|$8@<t!8Uh؊SSƆDxG‹|G t~luHu  <tnpGue tU@ DtGt";D|8;@w*S$;D|;@@t<~LWtvX$ ~LuWt$v\ twV\D$Pt$uTG0D$ tBPhS7 A@t)@`t#t$ hԋSQD$, )Ƈm~Ltu FXF V$Nu 9ND$F V$;V;F +D$D$uz@@t @`t3Vt;t$v$v vQRPhGt$8hSS&D$D,)Ƈmv$v vQRPt$0h`SS$F+F HD$D$˙F V$v$v #|$u~LuL$ ~L~NV#ƒt/3;|)9NXv"$u9ʍAD$ fAu+L$ !NX$uʍAD$ Au+L$ QRdD$D$~L}=u4L$V\uʍAD$ Au+L$ QRD$FLL$ x4tT$t mtf L$IL$L$@@t1@`t+hGQhHSS)D$ )ƇmhGt$hSS9u99Nu4hSSUtƇUE3_^[]h SS!_^[]øSPSEƃGh`SSǃG0nU<ƇU3_^[]ÃuhSS_^[]Hw1$w9bG@E3t!t;MEUuuEUuE6jh@+|RPq)EM+xiu+ tU|KG O@7WEƉM#‹OD+t$tIRVWujhRPʋE+piQVhuSS _^[]WujhRP蹦ʋE+piQVhvSS_^[]À8us‹O#t/j?S3$t>?tj/Ss#tj/S$tX3ۊ]<.u&~/u F<.u~.u~/u G>.ttat]j/SO#t uD?~/u1j/S($j?S$tt;Bt3҈EMt9؀ tBB3ɀ?PEEȈM tB_Gű]}OGu+BPtTEuu|T3_^[]WuP5 9t@<GpWt 8V88t @<tol tfhSWT u _^[ÀUtƆUƆd@<tA( A,t _^[q_^3[UQEV1u EFXEƆFPFTFhttd`GtT@<t>xXu2džΉRP^Y]dž^Y]USVWj ڋtTu_^[]ËE u"7F@G w_^[]ÍCuNjF^upCG 7_^[]ËCtpsG _^[]ÉwsG _^[]UVWtg taN;7uuO$F@FHNFuGA6GuVFF|T O _^]SWڅO twVwtftbN;7uuO$F@FHNFuGA6GSVFF|T O G ȅu^W|T_[U$SVWu 3_^[]Ë} ]uEEE];q |JQ;|A3;tbQYtU;r |;z~Z; t9UMJ ]뱋t&;r |;z}B:Jt ً 녋]U_^BAEEA[]UQSVWu_^[Y]Ë] }ttSWȃA ;|6?;Y|/-N~ ^AFtMA xMAƉ1_^[Y];|;Y|AFAN F~ _^F^[Y]UQSVWu 3_^[Y]u ]S=;^ | M ,;N}tqpp M ;^ |W;N|PFtN H NHNH7_^[Y]Ëu F7_^[Y]QSN7H_^[Y]_^[Y]UQVWF ;|9~3|1uB_^Y]ËFBVtE3_^Y]vP<;t _^Y]ËWt"G MB GBGB3_^Y]ËuM3W_^Y]vv OЃ3JM_^Y]_^Y]UVu 6|TV|T^]U SVWp@ډEtbtX6tRE>ЋetG;tvt%Quh Su_^[]_^2[]U S‹VW3E0ujtTG G@UEGt~PTEjtTj:utj @jPa PfFϋEWVat(Cuut 3ҋpE83_^[]6|TV|T3ҋA_^[]u|T3ҋ _^[]USV3WE]tejtTF F2DFt/PT؃΅tWVStt(Guԋ]t 3ҋE_03^[]3ҋlS|T_^[]3O_^[]U S]Vu W}!|u~`SfhSG_^[]jhVS ʉEM| cjhQP蠓+ȋjj<PQ͓u؋}+u}+Ƌu+E PVRSuuhlSj u$_^[]jhQVS\ʉEM H|=w?jhQQP+jhVS'RPu uhSj W_^[]QPhSj Wy_^[]USVuW} |sWVhSjS1_^[]Å|@s'jhWV臒RPhSjS_^[]ÅO|@sEjhWVjhRPDRPjhWV4RPhSjS_^[]Ã1|qs'jhWVRPhSjSo_^[]ÃK|sEjh@WV茓jhfffRP辑RPjh@WV讑RPhȏSjS_^[]Á -|s'jh@WVyRPh؏SjS_^[]Á'-|s'hjWVDRPhSjS_^[]hjWVRPhSjS_^[]UE+EM M} SVu$Wuts]};|;s_^[]jhQP{SWRP貐؋E,j+ƙhRP蚐M(+M E iM ;|;s +ً_^[]_^3[]U SVWp}] EU|StMRPQSW(uEE_^[]U SVWг}] EU|StMRPQSW[(uEE_^[]USV1WfEWfEfEUfEfEEh؋]؋l+‰Mfn^ XS;t+fnX(M EWf/EĉUvE SEȋ谥^EͤEWf/(,w SEn^E苤0É49u 9E;|;vȋE쉌ƨƬ@M˃;|3+jǙhRP:ȋE+iȉMu uEU싄֨+ި֬ެxH=7Av?ы<ME-^PSM^(; YjhQPXWuRP荌 24,0(;|;w‹ω tXЋ$thSV_^[]Ëtq!$$$֢$e}xJxG‹|G tQRhSh8S 40RPQW͊EU؅|:'v&jjdPW訊RP蕊ẺU\|u}M}܉MDjjd QWRPQẺUEUE܋EE̋EU؉E@,(QPSWEU|='v)jjdSW։RPÉEEUY|uEMEEM>jjdHSWRPEEUEEEEEEE}؋M;| ];w؋|t ˋ+MEWfEEMPQMWStuԍMu t E@tNj]EMą|J'vjjdSWuRPuuhU,|tjjdQPSWRPEU EEE jE=`PEPEPtP40PQ,V( BPPuuQ8 LPuuSWPuuhܐS D>W_^3[]UVu v|TFtPE@ ЃVF|T^]USڋUWE MGPWO G_tTV3~?jtTȃtA A eEA <t F;|^_3[]Åt#N3ҋ #uP|TG^_[]G_[]U S]VWEwSPGЋ E0t4fSuppGЃu vuMWOj tTtpStTEtUSuPBEFEȉ^] PVt G_^[]v|TV|T3_^[]V|T_^3[]UQSVWwGuSЋ E0tuSppGЃuvu_^[]ËMWO3_^[]UQSً‰EVWt?suPCЋ 46t%@u>uCwwЃuvu_^3[]Ë_^[]VW39~~ D֋ G;~|6|TFF_^U SىU3҉U9SMVW<7FEt0uуth t_N;7uuO$F@FHNFuGA6GSVFF|T O KEMnUBU;SO_^[]UUSVW} 33 :;GtȍRFJ3;r3u_^[]UM V;MuVUur;ust-:u/t"B:Fu"tB:FutB:Fu^]3^]VWFt @Fu:Nz;}$Au ;|FFNu _F3^Ë_^Uj`jTȃu]ËE3]̊tЊ€:t AAЄuSVWyDtfDPʥtGGuj Wu!j WuPWot1;vfPztN;w+FFPtT؃u_^3[VWS 3_^[̋A#tAAètAAètAAè tA AètAA2A@AUSVW>H؃S(US,UfUҋtWfEMUcuWfEMUkt/t"u\G#GtIG?SK 7G#Gt GTtЍJBu+3ɋƆg#tE; ;UGt Gt t u=+UMx~rt uk\ubUutQRhlSW!@@%u:UtUEGPGTM t)_^[]À}uhPSWƆg_^3[]UQSVWE23ۋ7Acw 3_^[]8(Gt380E_^[]8\t5t8ft%,}GЈUҊuƆ(G8]t4=t8ft=,}GЄuƆ(G8]ufub,8G8fHTt7ƆG_|TTu _^[]ËHtt8gu ؅u\0tI=|B=t=u]\t (GthSV _^[]U0S]3VWEu۸FFD‹MȉMFIy yȑSE۹FEGED FGDURURQ4躬Eth}tbP۸,SDPhS t|T|Tu|T3DP|T  Eu@ E:uӋϾԑS~_^[]Ã7ܑSEu܄t,|FEE츤E$GE&G*hpFElE츰EGEG48ΉME|TEIEEЋEUEЋEU8uU2uXE<0E t(j?PftM +QPhħS莺 E PTEtfUMQMQuPuuiu|Tu=u۹I,SVDPḩS)M V|TE8u_^[]ËE܋Uu0]t\YUtt Sj`{u vuttp]MuA Ia\\t͋Ut1Sjzu vuuU]E SEEtE两lhE丰uǹ@EVEh$SQ,蘷E,ʍqAuE+PEPQRبuu F _^[]ËE0|TI۸,SDVPh4S#M V|TE8_^[]ËhEȄQSSVDPh$SuMy A 3_^[]ËM2A 3_^[]U SVU3WUGG8Zt8]u 8\t9_uGt9YuA8Ztie:E u^juыu3؃ uqU@Ft>ku5DFt+4u"xuG _^[]A ju׋u _^[]G 3A _^[]U8SUEVuFW8GF}DGDŽ҉ED3߄҉]Gǀ>EQj ֹȑSxqCuEPTh(S@DЅM K{Et}SE8}t*8E؋EEF(hl<E؋EE踈FDžɉE~ IE҉EܸIE‰EtP*tGGuύQAuE+ux u#U܋MPWuSutM蹿}]}TE]Ƈ(GxjֹԑSxvC(uEPThpS@DЅ>M KCt #} \DٹԑS]jvt[F~tPt\GGu}hS7 .\#3}](GtEEEE܍AE؊Au+Mt2=t-EPUoueEtC4EC8h|Su#=kuD}hS7 d\Y}hHSWտ]Eh S0赿jֹܑSttLCthpSW芿wEPThԻS@DЅu`EUMVKqtC,jֹ SAtt,EK{uChHSWƇ(GtfD,t FFȄu֊<,uNF<,Et!PtNFu3_^[]À>3_^[]_^[]̋0t5=|.=t=u]\u(G3US]VW} }F F u_^[]Ã~X~ FNq|;wkPQuNP ~T NjVt:FHFF@~ N _G FDGFXFPFT^[]_FF ^[]WQu~ )~ǃ^ _^[]USVWE0uMH+E E苇M@@u u>xt5@E @GE PE 0VP7 M 0uU3;URQEVPWЋЃUyuQ3҉U;U‹7GE+ȉEM @u WPVM uuE(RhwShwShwS MtFH;v}ww э;r]St$PExTtu.u|TtTuV|TG_^[]ËV^]>SuP^ 3_^[]UQVuUtƆUDuSu8ut@ht7@@t%u }tUtƆU^Y]ËE 3^Y]UEE ]UQVu utUtƆU^Y]UM@@t:}t4uE ]ÃuE ]3]USVuW>Ft FuV=t3=t,Yu#@@%u:UtUF袵F藵XC\Et0|Tu|TC\Hu2K(K C,C$OpˉGt莣C8t)PJC8uK(K C,C$OpGtE uU8EuN8duF8Yu>ȋ򋇀+C S$|uhSW衷4_^[]3_^[]USVW\G ƃ`Gx  Lt t"@>Sj0ku+vuhВSuuƃ`G_^[]ÅtjSjtsGwtPtFFuj Vuj Vu PV+ rj SjuOF s2`G3_^[]_`G3^[]USVu MWtFZt eu3t?tu>8t- +Et Eu E3ɉMD|d@j:7FF-P蘋t FFu>tSjQiEHuSj ,iftSj itSj h|xu]Sjhu^Fj;7tJFFt"P誊t FFu>u ~;uF:7h0Su uMuAM;3_^[]UVuWWD$dD$(I>|$`D$4fD$PhGD$D$hE fD$tD$|HxT$fD$@tudžx_^]À@FD$,u@DF|TTDFT$HFD$,H (AD$L@L$l@<t9EЉT$L$$u=88t D$$S+Bw$ED$$SD$$SD$$SD$tRfDēSj ȉD$$fuD$@D$u |$ t|TdžT$$jt$ 8Gu8%GtD$t t2f|TdžtdD$t3ГSjȉD$$euD$@D$u|$ u!hܓSɣtMD$t3SjȉD$$[euD$@D$u|$ u D$4D$t5fSjȉD$$ euD$@D$u|$ uJtA|TdžhSu$_^]|TdžD$t.SjȉD$$fdD$@D$uҋ@<9xG#Gcfu=\G 4x 'Lt  ƇTSIDȉL$(D$ _jScD$ D$t&P艅tOGu|$|$`D$j PCȃu#j t$/ȃuPt$ȋD$+ȉL$r4j Scu!L$D$I@L$D$s2* h(SW襮_^]Ƈ|TdžID$t1fSjȉD$lburD$@D$uֺI@<t tSPF^SDPt$lSDPhtS+GD$t@FtDF1asD$ЉT$u R|T]<[u1ʍAD$ @Au+L$ APBPR j]t$j:RTt|TD$L$S:utP:Quu3t&t$h0S1uV_^]dž?^SDPt$pSDPhSߞZ+e;PQL$$D$QAu+ʋL$ JBu+ыL$T$qAu+΍B+L$ L$pPtTt$0@D$L$+QPVlM +t$D$t$PLT$ D$pL$+APD$$PD$P" t|TD$0uƇSjЉD$ K_lhSt$ et9hxŊ, aЀGЀAtfDtaIt\hGT$t8u*L$AD$0Au+L$0D$|/t D$t/T$u38+aPhSjR輛\tD$dlDD$d|$uaD$t.Sj ȉD$4;^D$@D$u3ɋT$,BPQɖ MD$t.SjȉD$4]=D$@D$u33ҸSɋL$,E‰AD$t tuDؕSjȉD$4YuvuދMD$dS|$0u MD$dS MD$dItT$uD$It8tT$ uD$ IIEЋD$,T$0֋@EЋT$pt8tD$$uD$$ImGtD$uD$IIEEЋIEȋD$(Pt$hD$|t$t$,t$@$t$V|TU385À@tR" uʍqAu+QMRS贑 Gj G|TG`EjSxB8؋E]ptn9uiw@tbt^tT6tNэZBu+Ӌ]RAu vuSShDSW腌E pSM ZؕSj>Au MFtP*ctFFuj V؃uj V؃u PV+ރ rj S@uJKF sMxƃ ZؕSj@u-EUtƀUhSWSCstPJbtFFuj V؃uj V؃u PV+ރr#jXI?KFsEx \Sj ?twF tPatFFuj Vi؃uj VX؃u PVH+ރ r j S>?KF s\Sj ?F tP atFFuj Vо؃uj V迾؃u PV课+ރr#jXI>KFsjֹS|>t%Pj`u>,uFFujֹ S5>UtƇBB0B @jֹ|S=LJbEUtƀUh4SW貈EUtƀUhhSW茈U@@%:UUjֹSC=tLJjֹS=tLJjֹS< LJ^jֹS<FtP^tFFujֹ|Sv<tLJjֹSR<tLJzjֹS.<ujֹS<LLJ=jֹDS;FtP]u >*tFFuP]tFj jV 0 xG;9|GUƇLJxGLJ|Gj ֹD|S4;GH΋Ӆt%t ptpjjW֋]uhGPA Pjb7GHttH t pjWу jֹS:tt<u )tbj]UEE >wEM ȋU)mGbjֹ̚S:tt#jֹS9tQuCpMVHV|T_^[]Ë-,cwxj ֹSz9tcuZs8uP2{PTM荶NU@<;_^[]< u C< u CAcdt_tDƇLJ]U,=  Ƈ뷃]ƇLJ~LJ늋GP#GTƇq]dUdx J@<7H*hj VE 詴؃uj VE 蔴؃[VhSWhE _^[]hcSWI?_^[]ø_^[]h,SWCLJƇLJ_^[]À8u tGPPu5;u1G`OdmtލGPG`@Gd| r@WfEUMGPOTG`Odu u>t@uS؅ 3_^[]hSW  _^[]U SVW ;|;E +jhRPK0ȋi+ME+iMU+ȋE…'|u!ShSW0~_^[]PQx3_^[]ÃEE tiϙRP]x_^3[]VtbFtvЃFFN t3^F v|TvF|TFF^SVW3tQVVjWjhaI؅~9PtTt&SVjWjhaIuV|T3_^[_^[UVWheZ7D$j`jPD$ UtƇUWtXtjQP3ҋ> u|TLJ3_^[]UHSVWEW}fEEhEEEEE̋EƇnEfhu uVhSSs|Tǃj jT}ԅ u VhSe E؅ MSjP2u؋|T nUSSu؋uEIE^E;tj:V?u ɺISDPSVDPhSPeu܅ EY0tt t.>Sj&u vuu}ԋuVhțSdE؅a MYEMtt t>ؕSj]&u vu3uISD}Ett t+>ēSj &u vuuMtEMu싁Iu}ԅEȋQM؅EPuuhԛSW E؅t P|Tu|Tu@MWu,hIW赵uUQPGPɲ 3thSSq 7|TW|T9Eǀh3EE~t-u;MʋE܉UvF+tj™hRP="+pi߃+}܋U O G = }twMwDtt;w$jjj~   ,3u܉uEEMP ,@;3EE~tu;MʋE؉U'E+tj™hRP +pi؋+E؉E}  }u܍EUȋMPjVVt Qu[ E|=r3MWPj; 9hXSSu|n} 9E7UMBUUЋ}̋,E ljut$UЃ}\R}T}EPjEjRM,hĜSSlLJh3 MA> Mt FuT@}tuQW:tM 385ƒ}uύqAu+QMWpMG;< ?< 79j̚S:!tt#j׹S!tQuC MWoW|TA_^[]j׹|S t08dj GjP EЉUj \Sl G w tPZBtFFuj V uj Vu PV+r#jXIOFs}jSzGwtPAtFFuj V芟uj Vyu PVi+r j S_OFs}jؕS<GwtP*AtFFuj Vuj Vߞu PVϞ+r#jXIOFs}VEPhSW臑uG,3Eu܉uU}@M8dQhhSSb}_;EV}uP}uJύQAu+3UA;URQMWPVa} ;E}EPjP }8thSSq`_^[]H4$E}I(SEPhSSK_ EEPh~fWdbI3_^[]P QPPPPh؟SS_ _^[]P QPPPPh0SSy_ _^[]P QPPPPhSS*_ _^[]P QPPPPhHSS^ _^[]hPSS^_^[]h(SS^_^[]hySS^_^[]fHEEE&EUSVMMW}U׋EEB]܉EDBu+UU8Ztu WhSS]MUtvRhS1\ E3EE~tu;MʋEUt3+tj™hRP;+pi߃+}lj}U ‰U}E5dbIPh~fWEuuW| u%EhS0\_^[]Ë=uEh0S0\_^[]ètEhLS0\_^[]Ã}ƅfDžƅEPh~fWEu uhxSS_[uU3R;QQPV4]}$E~;lMEPh~fQEdbIuMujg{ uhS6[G_^[]ÅuhآS6[_^[]èthS6w[8_^[]ÍEEPh~fudbIUEPjPh }th4SS[_^[]Ê<u-3e[hlSSZ_^[]<_}t6}t0ύQAu+ʋUMBEBu+UU3ɉMMƅttQWPM Ey MttPQPӟE M3U;MQRQPV[}Euu9EupUEPjP u8}u2PPhSSYG_^[]hȣSSY_^[]hSSiY_^[]ϸS:utP:Quu3u G/jWhS u;v`N>/tW;wϸS:utP:Quu3u/;v N>/t;wϸI@:utP:Quu3tJϸI:utP:Quu3tDGFttF~{PhSGGuUQ|TVTMqE}t4}u}u2|TVTM7EֹSt EֹlItEvֹStfEXM3DEىEɃM3ֹStֹS}t Et'DPhSt FFu>F~ PhS袂u GGu?GE vEu YE_^[]UVҸpF|FD1ܑSW}ju0u _=^]ÊGt@P$tGGuSߍKfCu+ك>utP#tFFuuEPPpStxIu4utPj#tFFuu>,cFZu6|TFFtPT@$v|TFCPtTuE[_0F^][_C^]ÍCPWVME X[03_^]USV1utE&t?Ԋ, a؀G؊Ɖ], EaG:Uu qAFuu1, ؍J€^G؊, aȀG3:[]UQESVW6utL/tFtFՊ̀ aـGيΉ] MaG:Uu vFHuGuu _^[]Ê6ʀaBŠG؀a, G3_:^[]UTSVWEEE7t\$Ghl G߉MIEȅҸIMMEƒ=TEuG=TMt{t|UEPEPQMDH u3|TI},SDVPhLSv< V|T;Q_^[]3|T3_^[]ÍEȋ?EUA4REЍUA8REȍUREEEčUA0E܋A,EԋAPjRjjjh,wSPTqEE@EEEЅtPhSWpH 8_^[]Ë}EPEPuw0+EHEu\9EtU3|TI},SDuPhLS8; u|T;u _^[]3_^[]USVW}u7t PS|tFFu_^3[]À>tFtPSf|u u8t@_^[]UlSVUȃEU ʉU ډUW U}M]EuEEfff}}EPuFFuP@EWPhSVEEn t}OGu+3}uWEMEpMG؋MEu@E܃|E}EȉMă]}uWMEMEfMVEuM@E܉M |E}EȉMuKu-0(SE@ӍMuE܃ @E܃Dr_^[]ËK+KM P}Eu_EPEPEPEPh4SV'muu}u.EPEPEPhHSVluuE`IjE$aIj EPV% `IȋE܉M;t P$aIMMuW+ƃuNxwF9usAFE<+t<-u3QE+ȋ+ًM}+]uۉ]]U+ƃuRuM9]uH;uDYы i']+ȸQJ‰EQkd+ЉUzMusu؅u0=GɃ׾FMGUUu؄uAU  }lslFwE3Du؋u}Eԋ]g}MUtEЋu33EủEЃ}E@_^[]Ã[ RI;@}<6F} y# +™ȸ +‰MUEU3j+QQhQ+ȋƙ#QʋEĺQ MENMmRPwMʺQEʺEʺ<EʙʁQMtC3ɃE˅~-+9U| ;vE@E_^[]ËMʋE_0^H3[]USVD$WD$4u"xE<8tD$PhTSS@h$jPyDŽ$DŽ$DŽ$DŽ$jjjjLaIjjRPLaIjj RPLaIjjRPLaIjjRPLaIRPj3$ PPaIthSSN@thShS`aIPL`IhP$Px DŽ$DŽ$DŽ$DŽ$jjjjLaIjjRPLaIjj RPLaIjjRPLaIjjRPLaIRPj3$ PPaIt2"džAHttPt pjjQ҃t$T$Qu5D$ h$SS?@phTSS>AHttP t pjQ҃ j8D$LjPw D$Ht.q  ESD$xȪSqE D$xSPSg>uL$xhSSK>$TED$h JD$h@D$h6D$h,hSS>#_^[]D$h D$hjtTWf@@APQjjD$XPTjjhS@ jЅto=" u D$ lSD$ SЋnPt$S3> |Tdž#_^[]hSS>#_^[]ËT$D$ Pcth̬SS<"tqhShSSDŽ$Ƅ$DŽ$httpDŽ$/1.1< DŽ$f$ $D$$D$(D$,D$$D$(D$,D$$D$4D$8D$jD$4D$D$ D$$D$@D$HD$DdžtTuhSS<_^[]ËL$WLЉT$ tۋAPPD$DPQ3ɍD$@8"jDPTQQ@RQt$ D$|TD$= tU=" u D$ lSD$ 4SЋQPt$S< |Tdž#_^[]t$hpSS:D$ 3ɋ;D$Pt$t$(QW< Tt$ I@у|$D$u9;u5WhSS: džfdž 3dž_^[]PWhSSM;#_^[]f~E~EEEEEEEUtS‹VWE3<]胻uu"xE<tPh0SVEE9u0hLJLJtT u.hLJtTȃ W+‰U=sCPQxTuhlSV9_^[]É EEtA +jȋERQ|bI^hSVt8VtTMuMԃEMEEEEEEEEEEEEEEEEME PQ~M 6E؍JQQPjjEPTjj@VRVE|Tu|TEE= E=  = tA3ۍufD~uVtPPhSu7U E3ɋ;EP6vQR8ȃ}9Ft PT@@C |}EuPhpSV6 U; +RQP迒E E= ]2kbI=3'u*t LJhSV63_^[]hЮSV6#_^[]=" lS[tQhSu6#_^[]ËuLJE= uLJ3_^[]ÅuhSVLJn53_^[]Ëy*Et$ Eh|S0Z+E }= 7DʋEt$|T;D\$<_^[]UlESVW3E D$|$4EPhسSSL$$)E MU8t;whSS)}\thbI=3'EuQشSPS.(Z8SPS(CEuEh@SSƄ!'~EQhhSS' EhSS'Uȋ Et9r! D$$D$jD$XD$PjPTL$,D$0D$8D$<D$@D$DD$HD$LD$PD$TD$XD$\D$`@hЋ|$t! t  L|$,t$(hSS&L$4E };ʉL$ Gы+;‹Er 9|$sS};BȋQL$xT|$HUL$(D$ L$ Ut*Qt$4PlE L$ QhSS%E hܵSS%|$DukD$@tcPhpSS%M D$@;v* P+D$DPQӁM D$@ЉRhSSM%EDŽ! hLSS#%}t QEhSS$EL$U QjDŽDŽh4S3S|$$  UȅPhSSr$}hķSSV$ hSSH$M! hD$\jP\=LaI D$XD$\D$`jjjjD$xjjRPjj RPjjRPjjRPRPj3D$dPPaI|$}MƄ  u$}?uQh`SSV#}E׋}8FPhSS*# h|SS#}hSS#}hSS8"}}!Ƅ nh@SSƄ!"SEh SS8"M}Et Qt;BEWuhE +P9PQ~E )Wh\SS"E hķSS!E_^[]Ëu]8!u QQu3_^[]UDSVWE4Mu"xEƒ<8tShSQ@!ZLMEMM؉MԍMQPTEEE@(EЅtЋPhĸSu! ?؅u C_^[]ËEEEEAEPEPEEPTQjj@jjSQSE|TEt= u_E3ɋ;EPuuQW" TuI@ыMu9]tS:]PhSS]t7h,SST@$|Tdžto؋JHttAtqjjRЋCuTS@S|TAHttP t pjQ҃ dž t(P|Tdž dždžt(P|Tdždždž_^3[]UVuhjjjV `ItFPjjh6`I^]UEjuu p`I]UQVu EjPjjvE`I}ujEPujv`IFtP`I^t jP`I]U ‰MSV3E0QEW30Au+<3<=tt DF<=u<=u|=D7;MI+ljE@PtTEu _^[]Ã}EE33ɉU3D3=u BU&`+SAfD:t BBFu:uoU΋]GrusNsN+t:]E@u]E;EnEM_^ME[3]u|T_^=[]UESEVu W}uNfDFu+?b RtTE؉]5fD33tCGN2ɈL@|eMĀ? Ȉe E$MMEEU `+S`+Stat4E `+SPE`+SPPPhpSjus BE`+SPPPhhSjuK PPh`Sju/ EE ]Ej|TKfCuE+ى3_^[]_^[]U$SVuWMyM EƙEMEE`tBu9uNFu+VuSEt_^[]ËuEU MfDG$#F 0|9~A|F~A<w EE}GtmC 8UUGA[8EjPWE G W$uu菰8" UG; u4 u'$u!CGdžUUGCUUG O$EE;|9UrʉMM}u7`uy}uˍQAu+QSUEE}e} M~)O _$+щU E$GE붊< u%CFF0F UU<  CUU< < E;|Tt PxThdžtTrUE}􋎰C~UU E  E`uAuʍAEAu+MQR&EUdžG; tXCUUKGE; CGUU%< t < tGCUUGM J3_^[]ø_^[]ø_^[]ø_^[]À; uBG(_^[]_^[]Fj F Fk!F#F!F#F4#FULESU3҉MUEVWu }t9W9vjtT؃u C_^[]ËUM u$MFEfDFu+uE|Mt=FPtTCupVuEPz[C UƉC ƉKC ECSt t7EGMt3_^[]ËsIΊ:utP:Quu3tEPVtuE%=@t EE늾+S|TEt P|T_^[]_^+[]UMUVWu F_^]u M3jjVt V|T_^]SV3t-WD~> v|TV|Tu܉;_^[UQSVq,3W3Uufq Tj/WFj\WFtt ;؋GF stpVTW|TtQ3j\VGuj"VGtf΍QfAu+ʍMPtT؃uW|T_^[]ÊÄtf\t"u\@F@uVhSuu`S|TW|T_^[]UhS]‰EWMEfEEVW Eu _^[]PE SEȍEQhSjPEE؉EԋE EthIEPEP uEhкSPEP|hغSEPEP] fEPCMRPsVhAhSEPEP "9C$tU 3Y +֋}EE;vIMERQPQE +O[_^][_^]U S`IVW}3h@jjjEEP `ItU\P3u9dt 9heaItPtFFuuEPXPX,SX"jjjXPjhӋ 6QtTVWjXPjhWpTttd|TdNffu+Wh|Tut"PtFFuu>,FuW|T]S|T_^[]Ë}]\3xPEPTjjV@ jjhԻSjЅtQt76|Tv|TFv|TFW|TC_^[]ËU EEECJEEEEEUBuEE+щEEMUEEEEE}E3؅uCEPT@Ѕt+6|Tv|T^v|T^WjjTMAxQMQMQPjEPjjhSjEPT@S|T   EPT@Ѕt76|Tv|TFv|TF]S|T]s|TC_^[]ÍEPEPT@ Ћ}EPT@Ѕt76|Tv|TFv|TFGPtT]!WSVKE >0ES8|T3_^[]UXSVu3W3UM}]9^ t9^uC_^[]9^0uBuu h-S Etu|Tu3ۉ^039~8uQEPTh(S@DЉFt _^[]ËMQAF4T@@v4tTF89~Mt#9tUFPF3jF,tTF:WfEPvTjjv,@ jjh(SjЉFjtTF WfMtltf<=t!EPUME]3uhE8EȋىMSCuj/Q+?3t!uT؃]uh_^[]ËQAu+ʍAPtTEt̋ʍAEAu+MC]Ruh-SPSEDžhlE؉xEEXPEDždPTjjjjjhSEEEDžtDžpEEEEDž|EE@ jЅt_= tX= tQ= tJЋ PhShS6h4SWS|TEPT@и_^[]Ë2EtXQMQpQMQjdQjjhPuEPT@Ћ؋Et P|TMtTQ@@3ɉMMt t t  |E؅t~PfEpbIMfE3;MQjMQPV} M3;MQuuPV}r9EiMEtPT@@ЋMEEtTQ@@EE UEPEjPD D}:E< <ubIS]tTEUMQuP c9]ZMEE4~E _^[]ËӋ褼PhTShS6bu|TEPT@ЍEPT@$ЋEt PT@@hpSW_^[]hĽSWu|TE t PT@@ЋEt PT@@ЍEPT@ЍEPT@$и_^[]hSWu|TE t PT@@ЋEt PT@@ЍEPT@ЍEPT@$и_^[]hSW=u|T u|TEPT@ЍEPT@$и_^[]PEPhPSEhPh SWu|TUhSWu|T 9u|TEPjEPT@Ћ T؍EPIхtk tc t[ tSӋ胺PhShS6AEPT@$СTu@@hоSW_^[]uhSWT u@@ЋEfEt t$S0SElQSPh@SW `tjHPjEPT@,Ѕt[= tT= tM= tFЋ蒹PhtShS6PEPT@$hSW4_^[]ËTPEEtTEjEtTEuTu@@PPE EtTE̅uTu@@СTu@@j|PhEPT@dЅ= t{= tt= tmЋ脸PhShS6BTu@@СTu@@u̡T@@ЍEPT@$hSW_^[]ËEEEPEtTEu*Tu@@СTu@@СTű@@uuPM<E EuuP8<E EEuuP <T u@@СTuEE@@СTuEE@@uEEpbI]MQfEM3;jQPV}38`t:;وEMQjMQPV}utQhSW.;ٍMQuuPV}i9E`Et PT@@ЍEPEjPo }EW ;s7@xfu>t"G;s8tVЍMt;r3_^[];sG@_^[]Ë+;w3u@ рu+;wG‰G_^[]USV‹WE+TUUUw^}PtTEtF33;uG}t5Ph`SjWCv;]rE_^[]3_^[]USVu‹щEW} +UMAJF$JFM3ҋ=?PtT؃} u!t WVST6 E_^[]3;u sM3tuN  FF =rX=r<=r = scȺ? @ɀL ?ɀBL 0?ɀBL;u ^E_^[]S|T_^[]âIFIFIFJFUQS]VWM3EtPkMًM;}0F;}_^[]USVW}ỦuGkȸMEtUPVE +ًM3UE;}0F;}.F3+։ẺUEtUMP؃E )MMEU;}0 C;};} U;u}.F3ېG ؄xME+θ̉MEtыMPfM +ًM3U;}0@;};} q;u}E_^[]_^[]UQSډE;VSP3OFWPtTtgSu֋!>+S+StCϊ:utP:Quu3t!N臠uFu_^[]ÅtW|TvT_^[]^3[]3[]U ySVWQ BPF$PFAQ+ƒ:SSDPT_^[]ËQ‹q+tWvu_^[]F ;r IQhSFPhlS_ _^[]ËQIA;v3_^[]ËQI_^[]hIT_^[]ËQQI_^[]ËQq;s ,0< wA;r~ +ǃtt3_^[]ÿ,QS;zZuSAQZSE+PWFPFPFPFP3>5VPhS~(_^[]ËqyEI;s,0< wA;rE0+ǃ ttAEy03ҋ;sY.t,u0A@;s 0|9~+уtfD|0uu;s8Zu tSxSE I@P+VuIQRIDPPEPG PGPGPGPWh|S8_^[]qqMM3҅H_^[]NF3NFNFNFNFNF`PFNFlOFNF       UXESVډMP3@W;IPMMЋEU;QЍM}ԍMUЃEWMWMEt^P葿tfDGGPyu?u +}|S~lIU+f;s1F<1uEU8t+;s1F<1uEP|T};s>=MFЅtI:t;s>AF9uR|TEM;UE@;_^[]_^[]UE(SٍMVWPSCmu _^[]ËuM܋UVMK0V?K@V1uMUCCoICpIV }u!uUKMVEV׍K0C KPVMVuK`UVKpVu䍋VyVhEK5EƃƃEƃǃǃǃIǃIǃIǃIǃǃIǃI;stVЍMMu E;sOVЍMMu E;s*VЍMcMuuUG_^3[]V3t]BDBtLBDBt0BDBt@r F^à F^à F^F F^UU(SVWrRBM},S豘#]MUSjU}ʉE:u;sA9t+tx fDOyW hSGVU t+WhStWhSWW|T Mt4tWhS)WhShSVuW|TUMSMtotWhSWhS6dSz8] MsS1EMt4tWh$SwWh$ShSVW|TsUMEMt4tWh,S!Wh,ShSVmW|TsUMMjt4tWh4SWh4ShSVW|TM(#tWhE@+PQgYYt'x$|!EE3Ɂ8ËeE2Md Y_^[Uyt}u 3T]U=Tt} uutJuYY]UT3TuȃuH hTHYY#E]UuYH]VjDJP]j0 ^tshhFPBYYuQZt hfFJJYȠàFPOY2t"E~tujN13ZP\YjhXTj*YP2ۈ]eEܡT3A;/uI ThbIhbIIYYtEhbIhbIIYYTو]uY39>tVgYt6WjWbI9>tVAYt6YCI0IWV0I_ QtkujjYYE5MEQP<YYËet2}uAEEMd Y_^[jVtu0tU%T$S3C Tj ~le3 T3VWT}S[wO3ɉW E܋}EGenuE5ineIEE5ntelE3@S[]܉E E ljsKS uCE%?=t#=`t=pt=Pt=`t=pu=T=T=T}EE|2jX3S[]܉EsKS ]t=T]_^tf TTtNtG3ЉEUEMu.TTT t TT3[3@39HTU$SjtM)j$jP |xffftfpflfhEEDž@jPEjPp E E@EEhaIjXۍEEۉEpaIEPlaIu ujY[3jP`It4MZf9u*H<ȁ9PEu f9Auytv t2hfFpaIUE8csmu%xu@= t=!t="t =@t3]+X̃%Th0qFd5D$l$l$+SVWT1E3PeuEEEEdËMd Y__^[]QUeEePaIE3EEaI1E|aI1EEPxaIEM3E3E3Ë TVWN@;tu&;uO@u G ȉ T_ T^ø@hTaIðhhj?W uj貧HH4HH39TøDTø@TSVXTXT;sW>t bI׃;r_^[SVXTXT;sW>t bI׃;r_^[; Tu(UjpaIulaIh H`IPaI]U$j6tjY)T TTT5T=TfЍTf čTfTfTf%Tf-TȍTETETE̍TTTČTT TȌTjXkǀ̌TjXk TLjX TLhcIUj]Uj1tM)T TTT5T=TfЍTf čTfTfTf%Tf-TȍTETETE̍TTČTT TȌTjXkM̌ThcI̋L$D$WSV=T fnpftufoftfڅuf~ڻ#؁w'offtftffكtۃtj:uЍNu9#ځw/o foftftftffڅut:bH^[_3^[_À9t#فwo"1f: fsKt tf~»#؁vt:tf:c@ ws׋#ށw)#ځwo f:cN qyLA:x뭊toqtUL$:tt :t u^[_3Ê:u~at(:uAtf:t3^[_G^[_Ë^[_UW=T}wwU  fnp۹#σ+3offtftf#uf#DžEЃSf#3+#I#[DžD_U t93t;DDžt Gufnƒf:cG@L9Bu_ø#fft#Ϻf#ufft@ft뽋}3كE 8t3_̃=Tr_D$ fnpۋT$#+o fftftff#uf~3:E3D$ST$t :tYtQu WV ؋ ~333ƃu!%t%uu^_[3ÍB[ËB:t6t:t't:tt:tt^_B[ÍB^_[ÍB^_[ÍB^_[Uu;Y]SSQQUkl$K=TV}2ftf;s tfu3f;S H#hfS fnpfp%=wffufuffujf;tftjX3f93^][nu2;uU}uRj^Y]UVuW} t N3 8FN 3 8_^]US]VWE3Eb] Cs3TVPuEumE{ @fuZEEEECtiMGGHEtMxHMuɄt. EthTVVuE_^[]ËE8csmu8=kIt/hkIwt5kIjubI֋uEM mE 9x thTV׋rE VuX sM֋I̋L$ D$׋|$<i %Ts D$%Tfnfp+ρvL$$ffGfG fG0fG@fGPfG`fGpu%Ts>fnfp rG stb|GD$tGutt $GuD$UEM ;u3]Ã:utP:Qu u]UP\$XE&EEEEE+sd;5tSVjPh~tFVt^[t0C P tC =02CVu C$ tS CPVjC]ӋZzr D$\bb]U졨bI=Dtd E;Ar;Avj Y)]U졨bI=Dtd E@;Ar;Avj Y)]UEt=ԏTtPBY] Ã= Tu3SW`I5 TYtuYj5 TYYu3BVj(j%YYtV5 TYYu3S5 TYY3V BY^W$aI_[h>uF TYu2hԏTPzYYuá TtP TYVWT3jhWw tTr۰2_^V5Tt kWTWt>t6aI&$Tu^]áT8TSVWT$D$L$URPQQh zFd5T3ĉD$d%D$0XL$,3p t;T$4t;v.4v\ H {uhCC+d_^[ËL$At3D$H3Uhp pp> ]D$T$ËUt$L$)qqq( ]UVWS33333[_^]Ðjg33333IUSVWjRhzFQaI_^[]ËUl$RQt$ ]USVWUjjh{FuaI]_^[]ËL$At2D$H3UhP(RP$R]D$T$SVWD$UPjh!{Fd5T3PD$dD$(Xp t:|$,t;t$,v-4v L$ H |uhDODe뷋L$d _^[3d y!{FuQ R 9QuÍISQ0TISQ0TL$ KCk UQPXY]Y[j hYTeE3@E3Ɂ8Ëe3EEMd Y_^[UQEMSVXWx ׉Ux-kË]t<J9X};~uuIUyB;w;wEM _p ^PH[ABUTMe3MEE EE@E~FMEdEEduQuȋEdU@S}#u~FM 3@eE`FTM3EȋEE̋E EЋEEԋE E؃eeee܉mdEEdEEEEEr@EbIEMUEEEPE0UYYe}td]d EdE[UQSE EddE] mc[UQQSVWd5uE~Fju uuaIE @M Ad=];d_^[UVu N3jVvv juvu ^]UM VuUH$NJp$^]UV9u;p$uv)p$^]H$;t Ht F?UQSE H3M bE@ftE @$3@ljjE pE pE p juE pu E x$u uu jjjjjEPh#tE] ck 3@[USVWE3PPPuuuu uK E_^[E]WVt$L$|$ ;v; s%T%Ts D$ ^_Ë3Ʃu%T%Ts vs~vftefoNvfo^0foF fon0v00fof: ffof: fGfof: fo 0sv foNvIfo^0foF fon0v00fof:ffof:fGfof:fo 0svVfoNvfo^0foF fon0v00fof:ffof:fGfof:fo 0svrovfs vs~vfFtIuу $F$FFFȂF܂FD$ ^_ÐD$ ^_ÐFGD$ ^_ÍIFGFGD$ ^_Ð4< Q%Tt׃+ʊFGNOu $PF`FhFxFFD$ ^_ÐFGD$ ^_ÍIFGFGD$ ^_ÐFGFGFGD$ ^_tINOurhooNoV o^0of@onPov`o~pOW _0g@oPw`pu r# ooNO ututuD$ ^_̋ƃуtf$fofoNfoV fo^0ffOfW f_0fof@fonPfov`fo~pfg@foPfw`fpJut_t!ooNOv  Jut0tuȃtFGIu$ID$ ^_Í$++Q‹ȃt FGIut vHuYjhYT`3ۋEH 8YHu9u x ]}y txTEtbIU MtIGPQ7t=ywqV uV>tQGP67YY@I9_u#tZtVwGPQYYPVd t7t3j[C]E 3@Ëe3Md Y_^[K8jhYT"UM :}y zeuVRQ]St!u4FPsx YYjPvW FPs\ YYPvW EMd Y_^[3@Ëe7U} S]VW} tu SWuHE,uuPu$6uuW F@PuW hu(s uuWu48tWP:_^[]UhSVW}3WuEu E Ej;Ga];csm{{ t{!t {"39s9pXE@E;csmu*{u${ t{!t {"u 9sp9pthf@E[uSpi YYuF}97ΉuGh TL MFM;7|W3MMME}̉uЁ;csm{{ t{!t {"w9w u WuPEPEPUEEԉU;UkM}jpEY9E;E3ɉM9MC@ E܋EU؉E}}܋~&sE7P u"NMEUAME;Mu/uEEuu$u P7EPuuuu S0UMBEԃUM;U#}3}t jS YY}uj%=!r\uG tL} uFG wSmYYtX'9w v"}u$u PWuQu Sw 9pud_^[jSYYM4hZTEP> XMHE$uE SPWuu WPL3U8S];VW39xtFWaI~9pt3;MOCt+;RCCt#u$u uuuu SQEE}9x u PuEuPEPOUE܉EU;UkM}jpEY9EN;EIMԋEHtyu.@u)jju$Mu QjPuuuu SU0MBEUM;Ur_^[]2UUSVWBtvH9tn} tua_3;t0C:utY:Xuut3+ttEtt tt3F3@_^[]USVWueYM3U"9p u":csmt:&t#;r A Bft&9q9uQuu  9q u#=!r9qu;rhA t^:csmu:zr49zv/Bpt%E$Pu uQuuu RbIփ u uu$Quuu R 3@_^[]UVu%kI^]aaAkIkIUVFkI `PEP[YY^]AkIPYUEPAPYY]UVFkIPpEYt j V\YY^]j3ۅ~qEӉ]@@ MEȋEME~;F‰EUr1P uEMHEMEUEUu_^[/,UuMU ] UuMuU ]UE@]ËAukIUSQE EEUuMmVW_^]MUuQ{]Y[ Vpt bI+UEMxA]ËA]UEMH]jhhZT0Ett8csmulxufx tx!t x"uKHtDQteRpIE'38E t@tQpbI֋Md Y_^[Ëe*UMU ]U@$tM9t @u3@]3]UM UVq…x I ^]UE8RCCt8MOCt8csmu!Y`2*Kx~@H3]UW}tHtBQAu+SVYS"Yt7SV>E ΃ 3@V"Y^[ M A_]UVu~t6`"Y&F^]U S]VWjYkI}} tt Qp ΋xbI։]}t tE@EPuuuaI_^[WVt$L$|$ ;v; s%T%Ts D$ ^_Ë3Ʃu%T%Ts vs~vftefoNvfo^0foF fon0v00fof: ffof: fGfof: fo 0sv foNvIfo^0foF fon0v00fof:ffof:fGfof:fo 0svVfoNvfo^0foF fon0v00fof:ffof:fGfof:fo 0svrovfs vs~vftFtIuу $tF$FFFFFD$ ^_ÐD$ ^_ÐFGD$ ^_ÍIFGFGD$ ^_Ð4< Q%Tt׃+ʊFGNOu $ F0F8FHF\FD$ ^_ÐFGD$ ^_ÍIFGFGD$ ^_ÐFGFGFGD$ ^_tINOurhooNoV o^0of@onPov`o~pOW _0g@oPw`pu r# ooNO ututuD$ ^_̋ƃуtf$fofoNfoV fo^0ffOfW f_0fof@fonPfov`fo~pfg@foPfw`fpJut_t!ooNOv  Jut0tuȃtFGIu$ID$ ^_Í$++Q‹ȃt FGIut vHuYU]9j hZTeE0YeM NuE uE0zYËUT3ʼnE}ES]u4;ttVWu|M33ҫ ‰u uƅu Puu QPGetKE3Ƀ tuuo;u*x);v%[ tMty ;tM t |P_^M3[]ÅuË;uj^L밃uËËUQVuWvO3 2SS39uv;w1V9EYtEPEPr9Y[_^]UEHtt t} tEut_^[]SVH&t39^-3^[É^8^F9^vF1PFtw$*FEN(^$^0^ ^,^<8'f ^(!.KjFF1kFPPJF?FFģFͣF֣FۣFFFSVH3t39^r,2^[É^8^F9^vF1PFtw$>FEN(^$^0^ ^,^<8'R ^(!jFF1kFPPJF?FäFؤFFFFFFA1 t-t"tHt uI I I  I I 9u8+e12ðVu+F12ðËUQVjVt#F1HEuqtFN^]ËVju^ÍFPF1HP ^ËSVh^1PFF<0 t=SH tFNF@N1FuK*x02^[SVh^1PFF<0_ t4FPSHK F@N1Fu)02^[y1*Q(tRÃAA@y ÊA1ut^[]UM A=w EH#E]3]ËU8EMUEEEEE܋E UMEu]T4ǃ?k8`TDt tuF8GTu_3^ËUkE8@T]ËV:O@3T4@TY PYYt5ON3M3AM@UЉUEEjY +3ҋu U} t}tEu3]ÍMEMMEEMM PMEPMEMPMj hH[T輦eE0YeM *uE Ϧ uE0YËUQSVW8W,E0F0Fj0N3Wu;(-C_^[]ËU}uE tH V uoWP|HTYttЋȃ?k8<`T ȋ?)_utt k84`TF-tRAMQAuE +ʉEEEEEE EEEPEMPEPMx^]j h[T/eE0w8Ye5T΃35TΉuE 9 uM18YËUTj Y+ȋE3T]jh[T趤3uuj7YuTȋ}uT35Tj T35TjΉu_}ttEu3#u}j7YÃt WbIY3@kUEHt-t! tt t3]øT]øT]øT]øT]ËUk I E ;tU9Pt ;u3]ËUEtt t~~ S ]ËU jXEMEEPEPEP']ËUETTTT]j$h[T+eeMuj[;t7Ft"Ht)HuG tt ~61V>}u[7VYYus ؍x2ɈM}܃et j5YMeEe?t T3=TϊM}؃Euo;t tu&EHMԃ`;u>EE;u"k I kI M;ta TM܉E)}ud;u.PpSbIY#j[u}؀}tj>5YVbIY;t tuEMԉH;u MЉH3諡Ätj4Yjjhh[TD] }tt tW?t=Iu(5IBYt5IhIPӹ PWYYȅtQEkI ;t9zu  JE3ۈ]uuj3Y]tu:=Tu1jh^FaIt T `I]uWEt&5T΃30Ήu܋E t PYME}]ujN3YuYj h(\T蓟ej 2Yeuuuuu u(uE 藟Ëuj 2YËUQVW}uj^0T'u t&}tSuYtOˍQAu+jAPEGYYuj Y[_^]Ë}SWP  u t>33PPPPPj h[T蓞uuHu3<WV YY;sڃej 1YeV&YuE }Ëuj 1YËUQVWtM}tGuNFu+0эBEBu+U;v<1=uVuQ}5 tu3_^]Ë@j h\T话ej 0Yeuuu u(uE 蹝Ëuj 1YËUQS]Vuj^0A s#uW} tu ލEP4Y}u eeuuWV7uE >Ëuu u4YuYjhh\Tћuu 3e} t3f9tf9u _܍EP#4Y9]u C]]uuWVp6uE 蒛Ëuu u14YukYËUj@u uB ]ËUj@u u~ ]ËUVuu RF W t9V9V-VQP@y~t v fYV3Y_^]jh\T耚uuu2_ uu 9~ u jujF3fWWjVj u2u`IPY4} ;G v Pu w wjVj uE2tHG3_^]ËUQuEPu u6]ËUjME9Pt +3҅uB}t MP‹]ËV~t vYF^ËUVW}V?PFP t f F F3~ _^]Uu nYM ]ËU}uu j1YYT3VEEEEEEPEPu tu u~1YY}t uY^]ËUEuEtEt } v ]Á} w2]ËUEuEt,Et}rw} v]Á}wr} w2]ËUEMU Ht]ËU(M SV@t!ut0|$~&y3ۋUtM ^[]WuME 3}EE @E EPjP] uEE-uE+u} G]} } tux,0< wÃ#,a<wÃ,A<wÃt u=j ^8GE} ]ËUESVW<t2<t.M3E 33+9M #t9 uAC;u8u3ɋE 3+3@9u #tf> uC;uɋ_^[]ËU]U]U]tUU+USVW} }33A9E  |9Es9E |9Es;t,9E  |9Es;|;r;t My_^[]j hH]T_|}uBGut tuڃMuKYeVuu uuE >|Ëuu$YËU}VWE@ t~E@ usE39p~iP‹ʃ?k8 `T|(|J|)uC9uuDjVVR;|);r#uE PF+WQuu oy 2_^]ËuF+;U} |;wF9U|;wϰM)yƋUE@ u]ËESVWjY !u}] VWSuuuY3uEYH`E@ Et jY !#@ A} t9uvLy^]juu u^]ËU}SVWuMR}t] tM;vNE􃸨uQSW 3+MQP=MQP.Cmtt;t+}t MP_^[3]UV3PPPPPPPPU I t $uI t $s ^j hh]TNweE0YeM uuE aw uE0G YËUDW} u!8SVj03ۍESP: uj Yuu`l fxK;5`T}CƋփ?k8`TD(t(EuEME uEEPEPEP 6^[_]ËU}uu j\YYT3VEEEEEE_PEPu3 tu uYY}t uY^]ËU<} u Z eSVWj83ۍESP} uă jY}u MlShjSjhWaIu utVjWWYYu j8ESPu} uă jYutV\aI_^[]ËU}uu j\YYT3VEEEEEEPEPu tu uYY}t uY^]ËU4} u  ;SVWj03ۍESP} ũ j Y}ulShjSjhWaIu utVjWWYYu j0ESP} ũ j YutV\aI_^[]ËUQuiYu jY2iSVWuju 3C3}fFEPuf^vt3EjWWWSHShF ȉF(V,N ÉV$N0V4_^[]ËUQuYu jjY2iSVWuj[u 3C3}fFEPuf^t3EjWWWSHShF ȉF V$NÉVN(V,_^[]ËU@T3ʼnEES]VuWSEaI3@;fF3Eąt M}QPTYYEHFj4EWPi} EPSaIEPueWWufFuARPu؉F(uԉV,.v,F v(V$uuF0FPEȉV4P@uwt't"u. 2[`IPY3H#fF3@fFE Ft3EWPWWWSaIt EęFV3@M_^3[r]ËU@T3ʼnEES]VuWSEaI3@;fF3Eąt M}QPYYEHFj4EWP{ EPSaIEPuWWufFuRPu؉F uԉV$v$Fv VuuF(FPEȉV,P/@ust't"u 2W`IPlY3H#fF3@fFE Ft3EWPWWWSaItMĉN3@M_^3[?q]ËU(T3ʼnE}u} uEUUEPEPaIt>EPEPjaIt*MEPEPEPEPEPEPEP‹M3p]ËUE 0EPEPEPEPE PEP:]ËU0VWу?k8`TD2(uO 9G0t2Qj{uj0EjPyuЃ ?j Y3_^]ËUVW0uu uc t0$8"t3ju j03 M _^]ËUM E!x u@$=w]|2]ËUM Vu!aV vO23F$Q^]ËUVuW} uWYt@Aց tWj.WuYYtGh nIWYYt3h,nIWYYt"h8nIWYYthDnIWYYu@8 _ ^]ËUQMSVu 3WjAXEf;wZv Bf;Ew,fy:u%f9Yu jY2Bf;Ew A_^[]ËUMtGjAXf;wZv Bfwfy:uftPt fyu]2]ËUUVW3qff;u+PBPtBP{unJft!V\ufuft;ft.R+uЋfuftf9yu2_^]ËUf}\t f}/t2]ð]ËUT3ʼnEVuhPnIV蒡YYu2pS3PhVPzЃt6Wyff;u+_t RYtVaI3C;w3LY[M3^l]ËU]MU]U]dU]U}u jYP3VEEEEEEePEPu9 t udY}t uY^]ËUVuuM 3S3f9u%u 9^ ujBF3^zSSSSjVSu\ u`IPYMW} ;G v Pu7SSw wjVSu u`IPYHG3_[^]ËUSVuuu ~3ۉ^^ ^33f9u u 9^ ujFSSSSjVSu u`IPYIMW} ;G v PHu7SSw wjVSuG u`IPYHG3_^[]ËUHT3ʼnEE S3VuW؍SPV u2PaYYuSW t YtW{YM_^3[h]ËUHT3ʼnEE S3VuW؍SPV u2PXYYuSW t YtWrYM_^3[g]ËUVW} 3Vww uaIu`IPY0-;G v%@PtVww uaItG_^]ËUVW} 3Vww uaIu`IPYG0-;G v%@P"tVww uaItG_^]ËUVW} 3Vww uaIu`IPY0-;G v%@PtVww uaItG_^]ËUQuEPu u]ËUQuEPu u]ËUM Vtt9tout+EEE3EEEPQuu8#T3EEEEEEEPQYYM}t uYE;rPuYY^]ËUM Vtl3f9teuUUt#EEEEPQuu#LEUPQUUUZYYM^}t ugYE;rPuCYY^]ËV~t v1YF^ËV~tFj"Yf F^UVW}FVWP_ t f F F3~ _^]UVWu}V?PFP t f F F3~ _^]Uu 蘳YM ]ËVW~t>Ft7~utPbv vvWfFFF 3_^ËVW~t@Ft9~u tPv vvWvfFFF 3_^38AtAAA AËUjjjuu u]ËUjjjuu u]j h]TaeE0 Ye} 0ƃ?k8`TD(tGp0V j ^0uE oa uE0U YËUSVu3WjSSVyjSSVWjM G+ȋE‰wGljW O_^[] UE RPu{ ]ËU(S]MVWuu SzE#E܃#E#EE}Ejh:YYu zhSatYEEY|rPVS1 t++E‰E|uuStV 3z{8u yV8YU|sjuu S#ƒt,S~ YPaIu5 `I8juuu_^[]ËUVuuj Xxj;5`TsbƋփ?k8`TD(tG}|} s j7EuEME uEEPEPEPV aj ^0^]ËUPu u ]ËUMSup]sMEPSeYYt$}E苀 t E䃠P}E䃠P3fEEEx~.ÍMEQPeYYtEE3j]EY3*3]AEfEUEEjpjRQMQu EP2$u8Et M䃡P:u}Et+M䃡PUE Ѐ}t M䃡P[]ËUMSu)]sMEPS:YYt$}E苀 t E䃠P}E䃠P3fEEEx~.ÍMEQPYYtEE3j]EY:3*3]AEfEUEEjpjRQMQu EP$u8Et M䃡P:u}Et+M䃡PUE Ѐ}t M䃡P[]ËUu ju} ]ËUu jua ]ËUu hul ]ËUu hu ]ËU=8TtjuYYMAw ]ËU=8TtjuYYMAw]ËUVuW} FAw GBw t;t+_^]ËU=8Tu)}u]Ã} t]ju u ]ËUMSVWu萓}t] u+XFE􃸨u SW.YY-+MQPMQPuCt;t+}t MP_^[]ËUu MEPhu }t MP]ËUu M辒EPhuF }t MP]ËUu M胒EPj u }t MP]ËUu MKEPju }t MP]ËUu MEPhu }t MP]ËUu MؑEPjuc }t MP]ËUu M蠑EPju+ }t MP]ËUu MhEPju }t MP]ËUu M0EPju }t MP]ËUu MEPhu }t MP]ËU=8TtjuYY]hu5T蛧 ]ËU=8TtjuYY]hu5Tg ]ËU=8TtjuYY]j u5T6 ]ËU=8TtjuYY]ju5T ]ËU=8TtjuYY]hu5TѦ ]ËU=8TtjuYY]ju5T蠦 ]ËU=8TtjuYY]ju5To ]ËU=8TtjuYY]ju5T> ]ËU=8TtjuYY]ju5T ]ËU=8TtjuYY]hu5T٥ ]ËUQQVuut3^]Ã} ueEePEM->Ձޱx|=GsSSjhQPx][kd3V@[N뜋U3W}jEP^YY_tUEMtQ]ttj蹱YTt"jdaItjY)jh@j j{;̋UMVu軍MtE uV^U􋲤u':utQ:Puu3;4rjPjQhEVP  u}^t MP]ËUju u= ]ËUQQVuu衽SWSh?wEYYM#f;uHQQ$lYYt&t!tESW\$$jjDSWEYY^Dz8QQ$7 YYt%&XnIW\$E$jjU EVQQ$SW]E_[^]UV3PPPPPPPPU I t $u t $sF ^ËUEM 3 A]ËUM EI ȋE% ȋE3]ËUE3 MVu   E% Ep3^]ËUVuW} t7u迻WuMEPQQWVP] EPtu r"}Et E䃠P_^]ËUQQE EEPuESYY]ËUQQE EEPuE0YY]ËUQQE EEPuEw,YY]ËUQQE EEPuET,YY]ËUT3ʼnEEVutu螺3@"QM QP,VQPU^tM M3JR]ËUSVu W>]}G@SjPM u]M-Ut+u @MIpigNKnBE0u4>WEjX_^[]EP2MUEtPt et pu EE43*B͈M+tՀ-u @Mщ20uƋ@Mщ0t,0< wƒ0#,a<wƒWAw7 s"k P@Mщ뫿Q,0< w0#,a<wW,A<w7 s @M뼀-u߄uurEEEEuUU;ta{uK;u;tRPC;|3M3H@EP;|E+ډ8XRjJj CjG[GGGGGUE $Guu nYY]uu E 38E H3]ËE 38ڋE 38EE uPYY뭋E @랋E `3@]ËE 3j8E HX]ËE 3j8ٍI8GGGTGrGGGGGGGVFPFF^Àytjhh(xIhxIhxI蛷̀yujhh(xIhyIhdyIv̋UM ytE !A]M]ËU$SVu 3W};wwlj]t@Ɖ]t@à M3ҊIɈMMJ+3+ʉU8EMH%E;X38EH%;1EMHىEM؉E@H33@$MEUE3U@3#E# u]EM## uˈM8]tEU## ŠtEut5Nt=t=u]]8]t 8]u8]tMNjÙ t)M!;lw;b]+]+]KVuu!YYj%M*ډU@r 3J@3ME܃UE3U@3#E# u]E܋M## uˈM8]tEU## ŠtEut5)t=t=u]]8]t 8]u8]tMNjyÙM-%;rQw;vKM3]C8AH%;~,uuYYjX_^[]~M֋]M ##EȀxt[PVWSumPVWSuc뤋U 3S]VW} 8SJ@w7M9vq39vI3ɊE4SPu3RQP+MwEE\]]]uOM}ʉM3LMMMtP:R"ȃuMSuuuWu3CHEj@X+EEM3҉EEIMEEU3ҋD#EEEUЋ}3ҋM#MȉMU}u}t2ۈ]tM9I"؈]uMuUuuuRQ5_^[]ËUM ytE!A]M]ËU0 T3ʼnEM 3USV8AHWy3ۋB;r+ٍz‰3ۉ3+3ɉ,;i 3ʚ;3ɋ0Ɖ0A;u䋽tK,ss0,C,03P,P0hPa,tn3҅t30,B;utLss0,C,1,jP0hP,33k AG;03j Yʉ&vj&X fwI4gwIW1jPVKPdwI`nIPPX3A;uC3P,Ph0P,;ut3300F;ut,ss0,A,3ۍSP0hP,O,g;0,PP0VP3uP,PV,@;330Ɖ0G;u,s!0;Ír00ut ЉӉu33<u;G33ɉst[;uG$AF;ut4s;uF3FЋȃsG;,PP0hP,t1+dCE_A^ [];ы+;|$u A4 >;u H;}sBE ]̋4LƉuЉMt + }+ljEԅt'Me uЃvu MԋD E3EU0]EȍK MčK M;EwA3Q EEEMtI‹M3UMAM Ƌu}EurEEMԋD EuSjuPRq][3‰]E]Eu܅uv*juЃPS 3u܉]]EEwWr wP$PS3ɋ MjuMʥ;r)w;Ev"E]}ЉEUEu vE]uM33tVE ]ăE܉M쐋EEeȋEe3;s+E܃mEu]M3;w@r9}s9t.u 3ۋUă v3RNˉJ؃u]UEHEu3UËM]mJ}EEHUEȉMM]A;sSd$R@;r t <u uE_^[]_^33[]Àyt ø3ËUju u ]ËUQ記HLMMQPEYY]ËU VWWh?EYYM#f;uvQQ$YY~:~nu0E]E\$E$jWV]KEsESV\$E]E\$$jj?DzWVEYY)EPQQ$M Uy +;|Z+; = =~-PQQ$ V\$E]E\$=}%V\$E]E\$E$jj|=}&PQQ$$ V\$E]EPQQ$WV]V\$I$\$E]E$QQE$jj$_^]UV3PPPPPPPPU I t $uI t $r ^ËUQSVW=TS5TWu u踢[jhVQE聡5TWRP賡jhSu__^[]ËUEPaIt3EPxaIt%MU tE𣰐TE TTTTTT3]ËUQQT#Tt>EPxaIt0E+TM TxrQPYY | =v]jh]TE0ҮYeM E E0Yjh]TC=T3@T3ۉ]u,=TσT;t3SSSϋbIhT u h T]YE9uhbIhbI_YYhbIhbI_YYF9u TFËE0 Ëer̋U3}csm]ËU}ut uYE EEMEEEjEXEEEPEPEP}t]űUqt d0@huuH`IPaIu YuaI̋UQeEPhyIjaIt#VhyIuL`It ubI^}t uaI]ËUET]jjj jjj ËUjju ]ËU졼T;T2qu-tYT]ËUjju ]j h]TeE0,YeM *uE  uE0?YËUSVWF00KYYtCE3ۋHLMHHEPSWSEMSP]t"3_^[]ËEP蛈YtMQjWuCPjYt"S&Y뭋}T$t&ut$Yd$EPu9Tu0D$t"Iut$谇Yd$O C  ɉ\$ ɉD3SSSSSC̋UQ} uju,fYYtVWhu 3EWWP衶t tU"tPjuۄYYt/ju uVWot t#"t VueYYVY_^]WWWWW覆̋U+EEMjE EXEEEPEPEPv]ËUQQ}|)}r!E |Mr+MMEEm ]ËU}u j$YP3VEEEEEEKPEPu t uY}t uY^]ËUQMSVWjZEE ځ+RhPQ輚jjdSu諚jjSu+蚚׃_^[]ËUSVu 3W}SjVW/ uSjdVW! uSlhVW u2_^[]ËUDT3ʼnES]u~Ȅ ]CVWủ}Ѕ3 E( r NKMąx u} ~pj YʙMċƉuE}Ћ׉UKy MċƃKű׉}Љu} Er =NIWVEȉUYYt}~EUWV(YYMEċEFjhmQP趘MȋC Mșuԋ‰}ƉEȉEЅ|7r1{ |;|5s16} _^M3[]Ã{ } |ӅsjjPW>EUȋ ʉutRWVPduuCȋEu}ԃ}}|$r|6r0k&a|s|KCjjE8btME Ë]j YËUSVW}WXY>u W}YhVYY3hVYYSVYYtދUt6} t΍YAu+;r tj"U3VWRv uJC资t7x(t0ujhwSy t VhPjj X_^[]SSSSSy̋USVuWj.VYYtD;r@+9M v7j$3ۍxSW超  t j$+u VWRP)uy2_^[]SSSSSy̋UVuĐTu$jhvjĐT"yĐT ^]ËUQS]WSYWhYYtl=weV48tt uut^s|aIj$+WVjPUu&NFu+f.0D^2_[]3PPPPP1xj h(^Tuuqj^0wDÃ&ej EYeu V,YYutq0E뼋uj UYjh^TjYuj X?u jYt"EPY}ujhWYj3u܉uq q0uhu hBWEPu܃uhWYYup8up}t[uW_YFE39Puu`Yj ^3PEPE @TE MEAMEuE Ëu܋ExuPkYuXYËSVĐT3۸АT;W6v&vCY;uАT3ܐT;ۃ6]v&vGY;u_^[ËUQeEj@PEYY]ËUQeEPjhuE]ËUVuuwoj^0uSWj Y} uRoj^0u-S39_|9rjX9G|?*Xvoj^0[_^]E]P]]YEPYEPYы_ ÃwnrAPwdE+ȍEPډMV]YYr9EtVYeE)EEPUVYYYtEEF E+jj<SW<y <ĉjjFN j[F VVхF NF mFV3SSSSSDs̋UVtuVUYY#^]ËU]=|iHCÞ&HËUf|MH]j hh^Tuuuvlj^0rgVTYejYF !V YYt0VYYt$VYVXYY?k8`THT`(E 3ËuViTYj(h^T#}ukr3LÃ} tu EPYYffM@EtӸMtu@bu PhEP t3ۀ}wËEȋM̉EtMЅۉMtEԃej הYe8k0EPSEPuQ}k0u]؍uЉu;t>t6YE }j 賔YËUhSVH`IuЃMEjjjP?k8R`TtRaIu36Fu v EtjYu3Et؉EyI]WjD_WEjP `T }}EuEE}AEЋEtAPEԋˉE؍QAu+ʺyIzBu+׋}_Gu+Yj:Sm}YYuSWl hyISW0 uSW ]SEYȅt\+Í}3#E3E܋}PEPSSSjSSWQ(tu]3E\aIE܉F3umoY3WbouZoYY_tf&EtPvdY}t u\aI^[]3PPPPPn̋UM 3VufFA< tF u)WCkjkYYu Th@WShWPF0_^[ËUEM MEAEM EHE`3]ËU MMud5jYEt t@uڅt@u E=wčEMEEEEEE EEPEMPEPMb]ËUSVu WV  usVOPHTYttЋȃ?k8`T ȋ߃?{)utt k8<`TG-t&cSi_^[]ÍV ]t uuۋFu VFV Y;u ~uA I$t 8t A뜈FjX!3@ j h^Tu ubh-MVJYeVuYY}EËu }VJYËUQVu3W@T} FG< tV4.V &EPV벍EPVzVRV+Yj Ztj Xf9tu3f9Fjh4zIWb j [f;u f;tf=f9tjhYY؉]E !u]V"YU [ËUQESVW?k84`TD(\)ȁMM @tPt@t$tuB D(`TD). D(`TD)$D( D( `TD)}uu@3H%_^[]j hH_TeE0eYeE 0ƃ?k8`TD(t VYjT uE uE0趓YËUVuuT T axE;5`Ts=Ƌփ?k8`TD(t"EuEMEuPEPEPS S Y^]ËUVW}WҔYu3N`Tu u u@`tj裔j蚔YY;tW莔YP\aIu`IWYσ?k8 `TD(t VRY3_^]ËUQQSVuW} WV\YY;;aI~E3E;rX_^[]ËUVuuQX3"΍QAu+ʍAPVYY#^]ËUQVu Ej@huuPZuu^]ËUU jy Ru~YY]ËM]j hh_Tu u?QlWeV9YeF V=Yt t?k8`THTHTً?{)utt k8 `TA-t(PVjMQhT@ UVuYY}EËu }V8YËU]U}SWt?M3Qff;u+YPP7YtuSW} u 3_[]3PPPPP6V̸hzIøP~IËUMW}t-U +:fftutt 3fE_]ËUT3ʼnEW}u|OUu}tVuW8YYYuhu 7x|Ml}Puxu uPcMt^t hPM3_]ËUuMuuu E]ËUT3ʼnEEVu,tuNT3@"QM QPVQPEU$^t M M u M3H]ËUT3ʼnEEVu,tu&NST3@"QM QP1VQP6U$^t M M u M3]ËU$SVu Wb8FΉEFEw]MMMu܉M\SEjPe_ uMU-t+u &ȈMIiNn3ۈ]0uCF΋~EEFlNlYulCI2_^[]t AFlxu! t N3!C 븃}F0EF4E]}t tGE33ɋE EMUt ;Uu;MteNPuΉEt9~.uEtMUAHMEUM룃f^UNR MU  }u;Uu;Mt~.u }tEUSV3W8^.u>FlNlYu B:H2_^[]t AFlxu# t N3fA 붃}F0EF4E]}t tGE33ɋE EMUt ;Uu;MtkN{PuΉEt@~.u}t&uEPEPWS% t'UM뜃_UuN| UM }u;Uu;Mt~.u}tM3fUSM؃tu jQR u܋[]ËUAlAlHu@F2 E]UAlAlPuP@}F2MAB]UES3Wz,E BEjB3YZ _ZfZZZZZ Z$Z([] UEaaE AEA EAt]UU ESVuWu{CKPRZEcpChE_Cl^[]VFP} FFp0^ËSV39^ u)F^f^^^^^ ^$^(u F2^[P~YNt$F FFP~YuȀ9%u|A8%ttFF8*u@FFtqTzkN( F 8X~Iu^f^^^^^ ^$^(F EFF39%SAΉF QAVqQ A qt ;q wr;Qw u2^ËыJ;JuAJÍA 3;V ;wAB;u^ËUU Vt&Et4t u@D2Du2^] | ~ tA(x~+~t t t 3q q Y38A$@ËSVW^t~u_^[Ët u~pu~(tu P6tv$t <0B뢀y.tËA+AjPËA@ wA$Gjjjjj|jj jjjjj02[GcGkGuG{GGGGgGGVNtt2^Ë^^UQQVcu EEu Pv4Fv0PQvh,}u2~.t RP^]VWNЃu2F,R;t N_^ËUSVWs]f`t4~tYFt tP\aIF tt uPbIuaI̋UQVWjj53Wu8 tME FF PQjaI}M(_^]ËUQQ}u[173NVuuEYYt,MQuPhGu uaIu`IP0Y3M^]ËMtEeߋUűUQSVWA93ۋʍ;t}99t ;u˅yu 3Y@uFEE FyB$PlX ;u^9wGt>9t/9t 9t9ubXQJC<9t/9t 9t9u FPjbIY^qYbI׋EYF3_^[]ËUS]u3VttY/j^05WhT3VW60T 5 TEt8uƉuM}QM}QWWPjuu u .j _82EPEPEPVuxuEH$TƋ(TJE}PVYYtE&Uϋ9:t@A98ulj $TE߉(TP4Y}V4Y_^[]ËUQES]VuW#}E t0E 2ɈM?"u ɰ"GM5tFGEPMYt tFGEtMu< t< utFOE< t< uGM t1M E3B3G@\t"u1uMtO9"u M3҄E Ht\Fut=}u< t3< t/t%tFPpYt GtFGstF1M _^[t!E]ËUVu?s9M 3u;s*M;vjP0j3 3^]ËU]Tu"9Ttt auT3Ã=Tt3VWu$V*Yu T3Tj2YVx2Y_^ËUQQS]3VW<=tB΍yAu+FuBjP/YYtn}RˍqAu+΍AE=t7jP/YYt1SuV. uBEj0E1EY؊uW)j1YY3j1Y_^[]3PPPPPm1̋UVutW P1YuVv1Y_^]ËSVW=Ttmt\3SSSSjPSSq؃ tNjS.YYt7jjSVj73SSq tSV/S 1 u3 V0Y_^[ËUVW~MVbIUY;u_^]UE;TtP Y]ËUE;TtPY]hGThGT~5T5TYYáTu TTuj h_TeE09SYeM uE  uE0LSYj h_T蠿eE0RYeM *uE 賿 uE0RYËU ESVW0Tȋ~3؋v33;+;wƍ<0uj _;rjWS臹jE%/Mu$j~WSgjE/MىE4T}ωE+ǃ;#t}3@9I;u}E@0S] GP V A  A3_^[]ËUSW]8uTV733υU}u;rT;Et3‹UȋȉEbIUTʃ@33;]]]u;EtuE뢃t V-TYPP3^_[]ËUuhT\YY]ËUjEEMXEEEPEPEP]ËUMu]Ë;Au TAA3]ËUEEMjE EXEEEPEPEP ]\TThT$ TY8ËV5TV+VV VV^jYËUQhtTMV]ËV5TTa,5XT35TTN,5(T5XT=,5,T5(T,,5,T^ËUVuuW8T9>t 6+Y>_^]h(IhI%YYËU}t=Tt]h(IhI^YY]áTËUET]áT3TȅËUET]ËUV5T35T΅u3ubIY^]ËUuYT]ËUQE SVu+ƃW39u #tEt bIUG;u_^[]ËUVuW>tbIׅu ;u u3_^]bI0T bI4Tø$Tø(Tjh(`TIeM Er EPjh`TE0ZMYeM E, E0wMYj h_T˹E0MYe\TTu`Tt9>t WVeYYEȹ E0MYËU VWhjI'j2) t:MEGEGEG EGjEXEEEPEPEP_^]ËVFpL0F0F 00 NFt?@TWf83Af;:uftfxf;zufu3 _t8T0FLP=0<F PuOTuFpLh\T \TYY^ `T T@|TË00YY^ËU}SWt@jUu,YYUs- ]QS(YtKQuQW9u 3_[]3PPPPP'38T@ËU jXEMEEPEPEP]ËUVW}Wu uN 3uFf90tPhIju uf97tWhIju u_^]VVVVV'̋UQQSVW}3hSWZu fu3j.Yf;u-Ff9t%jPjP&fhIV]YYtIj,Z FMMu@@s1PVj@Wuj.Xf;udF3AutpUtV_^[]Ãu@s_tPVj@uփsftf;uPVjPlu?uMj,Xf;fAhIVMYYj,Z0q3SSSSS%̋UV%/UjXP@t3t6tt0]%P T^]ËUVu tEt;tWj.Y` PY_^]ËUT3ʼnEE S]VuW} l\.jUHh,Hl r(Pu3ɉW$@3f>Cu2f9Vu,h|IuVK tލKff;u+sv(ff;uftfPf;Qufu3` ff;uftfPf;Qufu3%EE3Ʉ0VPYY0P,Pt ta0Ph( t;PQff;u+APPPuW{?f00PC{f0tt0hIPXYYt0hIPyXYYth3ۍQff;u+APWjU'3M_^3[]j$Ph VAt $u $,{WVh(~WVu cW0PjUC3f9t ;sWVP u\ 3ft ,(SuVH u3ۍQff;u3PPPPPB!̋US3V9]~"W}7u u u F;u|_^[]SSSSS!̋U(ee}v 3WQ*E\B EMPEEEE؍EE܍EEEEE EEPEPEP$E]ËUSV3Fhu 3YW{f3uF00EhxI5IjhQWIEhtIhQW EHM Mff;uftfPf;Qufu3uhxI!EEEE E0jhQWWE=Ij}uJN(tu v(YF$t8Ou v$Yf$Cf^(F _^[]SeYN(tu v(JYF$t8Ou v$3Y3F$FF(F F@3PPPPP̋UT3ʼnEE SVuW}8t!tVPW }3Dž<4؉DTf>Lhf~C]f~_RhlIV؉0YY.+<j;Xf9f0Df;18u5f8t'fpf;qfB8ufBuDucQff;Du+A4EPY(Y  >, OQ4@PA \fC@>ufu DHPQYD0ы<ΉG@F 4F$G`T\.;|}܍E|E|3]}Q@EPE?xTAM;}3ttx}@QEPEPEPEHMT-tD.EEEjT-EPCE<Mf9H},GE;E5jEWP I}jWEP ,SSjEGPu؍E}PSuK E̅SMQPEPubIu+uEu9E} u4j XSfEԍEPjEPubI}EFu;}M~&u܋Eы `T3CD .M؋U;|u}uS~u܋EӋ `T3CD .U;|΋UM]`T\.`TL-F`IE8]t EPEuM3ͥ_^[O]ËUQSVu3W} EljE;s?SYf;u(F uj [SjYf;uFF;}r`I_^[]ËUQVuWVYtU?k8`T|0(}<@Lu`T|0)tEP`Tt0D`It2_^]ËU T3ʼnEM U?k8S]`TVWDMщ3;ss;sA< uC FFE;r䍅M+jPVPWbItC;rM;r`IM_^3[蕙]ËUT3ʼnEM U?k8S]`TVWDMщ3u;s% u Cj _f>fE;r׋+MjPVPWbItC;rM;r`IM_^3[誘]ËUT3ʼnEM U?k8SV`TuWDM3;P;s! u j ZffM;rjjhU QP+PPjh$Gu tQ3ۅt5j+QPPbIt&;rˋ+EF;F`IM_^3[v]jh`T谕uuQ \ ;5`Tƃ?k8M`TD(tiV=Y}e`TMD(u uu VG }E )u}V3>Y ËU(ME EMSVuWu W bƋ?k8U`T}\:)tuШtD:( tjjjV83}VYt?t%ˀ]uESP u]ESVPMU`T|(}EË]t*tuluESVPuESVPuESVP뢋L}؋]3jEPuSQbIu `IE؍u؍}䥥MUEu\Et*j^;u 0PY`TD(@t;t h+E3_^[]ËUUVtM t uuj^0^]W+>Gtu_u _j"3ӋUEu]ËM UVt2ft f;1u +^]ËUQEjj QQja]ËUQEjj QQja5]ËUVut j3X;E r4u uFt VYtVj5TbIt 3^]ËU(T3ʼnE}Wt u胑YjPjPh0jPݜ0ffffffEEDž0@E EEhaIjpaIPlaIuu}t u|YM3_4]ËUEDT]ËUV@ t)\tuuuu ubIփ^]u5Tu35DTuu uu3PPPPPjdaItjY)VjVj! VH`IPaI^ËU}t-uj5TbIuV^`IPY^]ËUVuw0uFOt V荧YtVj5TbIt  3^]ËUSW} ]?uE 3fVuMExu!hHTSWuuMtf3FEPP$AYYtBu~~);^|'39EPuvWj v.uu ;^r0t*v339E3PuEFVWj p.u*}t MP^%HT%LT3_[]ËUjuu u]ËUW} u9}vEt!83S]t }Vv_j^0uME3Hu,EuPEPWu t~? 069u^fEf;v9t9uv uVW菘 j*^0}t M胡P^[_]Åt9uv\tЍEuPVuEWjPVQ= t 9uut`Izut9uv uVW Pj"^0~nUjuuu u]ËU졤TVW|zu֋} j X+#;s׍ 2;t 8t@;u+;+ȃ;ttu ;uE 9tA;u+w|ru֋} jX+#;s׍ 2;t 8t@;u+;uU+ȃW;tftfu;uE 9tA;u+UʋE ;t 9tA;u+_^]ËU졤TVWMt!E A;t3f9t;u+jуj X+#ЋE ;sЋut>t6aI&Tu^]jhhaTmej Yej^u;5|TtYTtJ@ tT4YtE䡀T Pfftu_u3f&j"3ˋU=8Tu]}juu u]ËUMSVWu1Eu3MtU uh;vM}􋟤uuVPRQX-wPRPQhESPA u Op}t MP_^[]j haT^g3u>jY}EPsYtxx8xHE ^gËujYËUE3ɉEHEHEHEHEHEHE ]ËUQS|TVW=T ]B7tTF u.V躸YV   u] ШuV觸Y;uE _^[]ËE0j8j8j~ tуHjh P7 F V3Y벋UVWu EPm}YY}_^tWhuEuuPT\u9ET M E3ɉHEHEHEMEAE3]ËUVWu EP)o}YY}_^tWhuEuuP_u9ET M E3ɉHEHEHEMEAE3]ËU]U]eUW}u u NY$Vu u WYv%z 3^_]舼tV|YtVWj5T`ItҋUEVu2_b@ S3 CKE@ 9E@ ËEtjY  E@ u ueeYEHuvvVzYPF EP@ u_uFYt7u8Yt)uWV(VY?Yk8`T_HT@($Yu؋މ]܃eE`TMD(uQ 3 uuu WSu؋ډ]E .}]܋uWY $֋e\ËUQQVuWVY;u NjMuMQuu P`Iu`IPZYӋEU#;tNjE΃?k8 `Td1(_^]ËUuuu uj]ËUuuu uQ]UWVSM tMu} AZ I& t' t#:r:w:r:w:u u3:t rً[^_ËUMftfy:uarzw ]3]ËUT3ʼnEWh 3WPf Ph`I=wPYBSVXjS^YYt VS`Iu  VJYV}Y^[M3_[]ËU=8TunUu]ËM tSVWj+[4 Ff;wF 9Gf;wG ǃftf;t_^+[]ju u ]ËUMSVu蜒]tu u7dEWu?j+Z 3Af;wA Af;wA ft:f;t3MQPM[QPٶvftf;t+_}^[t MP‹]ËUQQSVj8j@3ۉuYYuK;tAW~ ShGPWO8_̍GG G g_ֈ_;uɋu_SY^[]ËUVut%SW;tWYtE t j (Y3^[]ËUEE]ËUjuuuuu u]ËUE3S3CHEW HEH Mt E Xt EHt EHt EHt EHMVu 3A1AM3A1AM3A1AM3A1AM3A#1ActMI tEH tEH tEH  tE X  #t5=t"=t ;u)E!MM E #t =t ;u"E M MEM31E X } t,E` EEXE X`E]``EXP:MA A EEXE X`M]A`A`EXPEPjjWaIMAt&At&At&At&At&ߋt5t"t u( % % !tt u!#  # } ^tAPAP_[]ËUEtw豪"]褪!]ËUU 3ɋ9It@| IMtUEEEEEEEVuEE hu(EE$uE0EP6 uVUYE^hu(u9E ]ËUEVDz 3Wf}ǩM UutpپS3AuCEu'ɋM y M Ntf}Uf#f}[t fEEjQQ$1 #jQQ$ _E0^]ËUQQMEE%] fME]ËU} Euu@]Á} u ujX]fMf#f;ujf;uE utj3]jh(bT>=T|[E@tJ=TtAeUE:E8t 8t33@Ëe%TeUǃ࿉EU>ËUQ}E]ËUQQ}M Ef#M#E f fMmE]ËUM t -ؗI]t-ؗI]t -I]t ؛ t]]ËUQ}E]裟P{YËUQQE]EE3E %3EEE]ËUfMff#f;u3EQQ$#YYttt3@]jjX]ø]ɁfuE u}tɃᐍ]EDz ɃA@]Ɂ]ËUQV5Tu-d0!uF@x|EP9uuj^θT^]ËUQd0V3u@9p|EP}t3F^]j0YI}3E ]}؉Eut u3tuXuMuEȉuHuEԉuPSEuPWw9u:Mf9n7MfF;rxuat#Ef90tut f90u+]CEPVSWSuVQ5 }|7)N#EPVSWjuVQ t}w}`Iz EUȋJ~jY]SVQMQjPVr]Ѓ }:;ƉE܅~M؊D9E@GE;|EE;nt*-9u)Mftf;w7Ffu3EPVVVjuVQ t }ux董*}t MăPXËUQVu 3EW}t.t.tS]t9}wE=v /jYt"j^0PkuPuVutE@t5;v'}t;wԢj"^0jPYMD0Mt[_^]ËUud`Iu`IPOY]3]Tp3TTTTøTøTøTáTËUMu'TjX]áT3]ËUMu(jX]áT3]ËUMuϡjX]áT3]̋USVE3PuaY9u]W{;= Tu ;=,T^95T ZTf95XTu\T3^T@]u^TƋ։u]`T]bT]dT]fTSu]uuuuRQWPVO T, T]T]T]T]]f95Tu T3=T@ Ƌ֋5 TuuuuVWRQsPj,XVVV3kjV@VP3kPWjVVV3kVjVVP3k Psjj|X$T0TK_;};|S;O;~;}3@^[];|;;~;|.kC<Ck<i3;u ;5(T;54T3VVVVVޥ̋UQQeS]VWS=&} }YEujt 4$I4ISF%Yimj6YkM+u;U}t (II}u ;~t 4$I4Iu kE$<E(k<E,iE0}u5$T(T T_^[]ã4TEP50TYuAiM4T4Ty \& 0T=\&|0T4T,T3PPPPP蜤̋U SVe؃eEP]NYEPYTut4ʋƊ:utX:Yuu3L]RHY΍QAu+ʍAPjjT$TYYWyAu+VAPR͠ j_WVj@3>tFu_-uFVHYiM+tB< wF:uLFV!k}f}uEf%tfMEHMEa9]]ȃ#u uEfEt fOuuMRQMQuPEPaEt"MU^t] 3f+]4t3fuu 謇"蟇̍}t M؃P[^_]j hbTEE0YeM 1؈]E  ]E0 YËUQQVu uC}>tEtߋtـ8tSWj\Vd#j/VZ#ޅj:V=#YYur΍QAu+jyWʊYYuP Y_[^]hIWSlj ,VWS P{͌Y t;v+j.W#"YYt+jS YYuuSuˍQAu+jAPEYYuS]SW CljE贅IESju uWPWYYtIuWY%ouMuWu'W̋YVŋY3PPPPP}̋Ul} u!N}t}v SWE3PE}Pu}u7;uuEu}:YYC}}PEPEP u(u u}u} ?}Vuj^LjD8E_WjP%fEfEƋEEȍEPE}P3PuVjPPuu u؃4}܅tJEu_SV`IEPu`It!EE;tW\aI;tV\aI]B`IP膃Y;tW\aI;t&V\aIu<;tW\aI;tV\aI3uueue-;tW\aIuˉue迉ue賉ƃ ^_[]j!̋USVW] C 5`Tt$~Nj׃?k8`T|(tOu߁23rɂ 2kjPEՆEYYu蚂2 P0 2U3MMtB‹ًϋ׃?k8 `TQ(u8I8 G;uˋE]UK9u%3Ƀsj_;t}AB}݋ K3ۋEC jiY_^[]ËUEEME EEjEXEEEPEPEP1]ËU]sU,T3ʼnEEVu uEW}}؅un蛇h>ttߋtSDEԄuj6u WVu]m8u"j\VYYuj/VYYu~:u3EPATHEMPQEMP7zM t ujh趄YYahVu E܅E]>6΍QAu+ʍ~j\VYY;t.j/VYY;t EfE\PhV (֍JBu+ыˍyAu+ύ;SQV uu؃ Vu8t]8tSj/V~BYY;uj/W4EYY;tEj\VYY;uj\WYY;u2}uthVu E܅]V菅YMQ腅eYEԃ8ut[M_3^]Ë]3PPPPP̋U])U(T3ʼnEEVu~ ~j^0̈́|S] tm~ x~j^0覄TMQjP`Iu`IP~Y)Eu,Et&t~'~ ~3[M3^]ËU}uu j(YYT3VEEEEEEqPEPuE tu uYY}t uY^]ËUju ul`Iu`IP9}Y]3]ËUQQM3S] VW]E8Etj-XfCE3@ىE]u]3ҋuj ȋCEX;'0f‹UFfEt;rˋ] ;ur3f|j"^03ffff;r3_^[]ËUE3ɋU S]VEWM8MtA-ۉMpuڋEuuESjuRS͖][؍FEj X;$'0E@Eut Mu;rMu;rE|j"^0@EOF;r3_^[]ËUM Vu{j^0OUSt$]3f@;w {j"uF"v{j^0āSVRQu[^]ËUMVuc{j^0葁PUSt"]@;w :{j"uF"v&{j^0TSVRQu uY[^]ËUQ} u }E|Euuuu u]ËUjuuuu u=]ËUT3ʼnEVu Wh 3WP. PhaIt*QWWu؍VjQ@WPq tH3M_3^#]jhbT]uuzj^0@Y}t}t Eu3EEEuuuu uVEP}Et+Ëu}}t%t?k8`Td(6YjhbTuu[yj^0Y}t}t Eu3EEEuuuu uVEP}EttËu}}t%t?k8`Td(69YËUQEU?SVW}(3k8`T8\(u$@u%E]Px!YE%@uC@%@=@tE=t,=@t%=t+=@t$=t=@u 뿹#;uE @vE#‹ˋ=@t=t1;REGvv[43FjE]Pul ~ N#tIMtXuGjSSu  t~SSSu#ƒu 0wMr=u w=uSSju讱#ƒtSSSu蔱#ƒttQ]tujE^jE^t%+PEPuw L;3_^[]SSSSS|̋UE E$jPuu uuuaI]ËUE#¹;w(t!t=t=t;=ujjjX]=t$=t;tu|]j3@]ËUQS] VuWtGt!tu{*#"#@SFYFEjY+t>+t5+t,+t$@t;uh{39~jjX3@3fF Fyu@uEPYuz9}ttT#ExF@tNNN t N tN t N tN_^[]3PPPPPz̋UQSVu֋?k8W`TD(Hu{ywjjjVخڋσ#˃us8tNsG3fEEjPV2i uf}uSWVa t3PPPVw#ƒt3_^[]ËU3VEEEEEE)xPEPuw tu uuuuu u;}t uyY^]ËUjuuuuu ]ËUDSVWuEuuP+}ԋjY9uur E 0rh] ;ur 3rϋEuԃe3AE E#jYEEPu }ukM؋#;u5Et/EuԉMjYPu }u+ ?k8`Td(`IPqYWaIuG`IVqY ?k8W`Td(\aIq uE @ Eu W3EhUYY U?k8Uԋ`TT( ?k8E`TD)t3Yt3}Y*EEPuuԃjY3D$tRƊE?k8 `TD) ?k8 `TE2D-$0D-EHuEt ?k8`TL( uع#;Etu\aIEu؍ujYPuЃ u2`IPo ?k8`Td(3輰Y ?k8`TT3_^[]ËUjuuuuu `]jhcTejBYe3u;5|TtQT<}܅t2WWYEG tt WjYEeF뱋uuWYE Ej YËUVu tj3X;Eso 3BS]Wt SnY3uVS6YYt;s+;VjPx _[^]ËUSVW}tM t ]u3fnj^0t_^[]Ë3f92tut+fRftuu3fNnj"봋UVuWtM t }u&nj^0Tt_^]Ëր:tBut+Btuu mj"3ŋUQSVW}tu ;tntiSV`IuEPV`It tE2`Ium jmP9mYt;tV\aI Rm _^[]ËUE u2m3]Vutwm3MA;tNSWtR;tRA"u&t'ڊӀ"t@A;tڄut A@;tul"3;uA9;t+#_[^]ËU]1UHS3V]]]]ĉ]Ȉ]̉]Љ]ԉ]؉]܉]]]]u]]]pPEPup u`pPEPu p uG9]$tpPEPu$ipu u&u,u(Su uuuuuuaI؀}tV'rY}t urY}t u rY^[]j(h8cTEu!Yk dkqÃx8M?t%k 0k]qˋ#;tE 3ۉ]̋ЃEu EPEPEP`Iu`IPjYlu;u)jju\aIu\aIw]ƃ?k8`TD(`T\)`Td-E/E;u+?k8`T\(q3ۃuV裩YE}؋ǃ?k8`TD(`T\)`Td-E]ԍEPY]u @u79Eu2ƃ?k8`Td(ǃ?k8`Td(y2ƃ?k8`TL(ǃ?k8`TL(uV(uWE0x33ۋu܋}W蓨YSSSSSTőUju u ]ËUMSVu3/8MuhnQ]9suu Q2YY:WMD;tAt 9} uu 9} uAu_}t M샡P^[]ËUTVuWWnjFn~F YYtj@Y  FjF_~Ff_^]ËUQ=8TW}3UugnmM tSVj[+щ]4 Ff;wF Cf;EwC Ãt ftj[f;t^+[juu u_]ËUSVW39}]u/g\mu tuMZ6E9uOM+E3j_Bf;wB Bf;EwB ƒtEft@f;t9EPPZEPPZm[vt ftf;t+}t M샡P_^[]ËUju u ]ËUVuu(fUl3iW} u f9l3LuMD5M39Qt%tDt F;t 8t F;v}t MP_^]ËUE ;Ev]]ËUSVuuu ]j3ۉ^^ ^33f9u u 9^ ujFSSSSjVSu] u`IPdYeMW} ;G v P=u7SSw wjVSu u`IPdYdHG3_^[]ËUE (Vudj^0juS3Wˉ}؉M܉]taMfE*?QP]YYuEPSSQuURPQ( Euuu}؋M܋]+NjЉuB;ΉU#t/NjӋAEAu+MCEكBE;u݋U]3juR6 uu}E}ȉEljM;Et[+׉UЉEBEBu+UBPuEE+EPQutEUM MME;EuE ]0SiYE܋+‰U9U#ȉMt7yiCY;u}؋uWdiY_[^]SSSSSi̋UQMQAuW}+ʋAЉM;vj X_]SV_jSfYYtWu SV/uPu+ߍ>uSPu7]3Et VhuY C0CWhY^[3WWWWWih̋UT3ʼnEM USW};t#u&jjcje tFF+>vj X5Sj?S6 uj ^ NF3jeY[_^ËU]5U,T3ʼnEEhQPt`Iu`IP^Y3UM Eƅ)cPPPPM3O]jhcTE0ՇYeM E E0YËVQ@HPQ5xT`Q@HPQ5|T}`F uF88Tt0'dYFBH@H^ËUE-t(t tt3]áI]áI]áI]áI]ËUMj,%TEuT`I,uT`IuET@}t MP]ËUS]VWh3sWVr{3{ { 8T+7Fu9Au_^[]ËUT3ʼnESVuW~ Pv`I3ۿÈ@;rƅ Q ;s Ƅ @;vuSvPWPjSSvWPWPWS蟦@SvWPWPhSw$EtLtL ˈ@;r>3ۿˍQB w LA w F AÈA;rˋM_^3[]ËUuuuM EIH;Au3SSVWh paYt.uvHWu'YY;uZW`Y_^[]À} u8E@HKuExH8Tt pH`YϋE3HHEPuTuEEMjEEXEEEPEPEP} kEE+PVEYYMxO9tK4<[YM8]u0UDA9ujQRpSE[Etb[E4V8]؉EP;?jRQ#SEZEM4\T9] tNFu+jFPE5XYYtFuuVCW uZM+EAE#YPVTYYuS*V0ZYSWZY_[^]SSSSSY̋UQW}u3_]3ɋ9t @A8uVAjPWYYtftPS+ߍQAu+jAPEVWj;Y <;t.7u4;XV uu[jmYY^p"3PPPPPY̡T;Tu P;YTËUSVW=Tt*] SPu{ u <=ttu+_^[]+U]`ITÃ%TËUSVW};} tQtbIӄt;u u;u t.;t&~tt jbIYF;u2_^[]ËUVu 9utW~t jbIY;uu_^]ËUET]ËUV"tubIYt3@3^]j hcTejzYe5T΃35TΉuE ËujzYËUMS]Vuuu9u t)Pj^0&W^[]ÅtE tu 3f3u3f+ًWufRft.u'fRft tuɋMu3f_uuE 3jPfTAXt3fVPj"YU]*UQ`HLMMQPCbEYY@]ËUXT3ʼnESVu3ۉủ]]]܉]؉u]W~]9uWhPESPQZjjSSE$VjhSSEVjhSSEUjhSSEUjhSSEU<9]9]M؅9]9]È@=|EP7`IEEȃvS?uEhj P~ 3U8]t+M؊Bt2;w  FB;~8uۋűEMS7ARPRQhMSY$EܹS7QPQuhS'$ES7Phu؉EjS E3҃}fU܉MMYZuuЈ?u3]Ѝ+ f A|Uh}8]tb]GtV7u;wAMč+ʋU4sEظfv BGC;~U܋M]?u3ۋEj?YjEYjfYffűtIu@-PBS+P/S+P!SSEEEEEЉEȉF&uRuRuRuR3ۃCuRY_<t3IdžIdžIFM^3[]ËUVuF ;TtP:RYF; TtP(RYF;$TtPRYF;(TtPRYF;,TtPQYF ;0TtPQYF$;4TtPQYF8;HTtPQYF<;LTtPQYF@;PTtPQYFD;TTtPQYFH;XTtPtQYFL;\TtPbQY^]ËUS]3VWM]M9u9uMT4jPjNjuQ u3@VjjNj}P u VPYӃjjxNj}P uVPEPPY‹F PjWEjPELMEQjWjP.L EPjWEjPL EPjWEjPLP EEPjWEjPK E PjPWEjPK E$PjQWEjPK E(PjWEjPKP E)PjWEjPK E*PjTWEjPmK E+PjUWEjPVK E,PjVWEjP?KP E-PjWWEjP%K E.PjRWEjPK E/PjSWEjPJ E8PjWjEPJP Eu9LjLj}LYYSu LY'E싾jWjP"HKQjWEjPH CPjWEjPG C0PjWEjPGP C4PjWEjPG t*SbSLuK MMQKEYpS HЀ wj Bu}uM3@ttN|tuv|KKYYEF|3_^[]<;uFu넡TTCTC@TC0DTC4dUM SVuW3?;#t6KGvY;u_^[]ËUE eSVWVuE"YM3j1`XjZEUMj_3PuEVjPLFu ؋EPVuEjP+F ؋EPuEujP F ؋E}PVWEjPE ؃PE@mEhEj8^huEE Ѓ PVWEjPEu ؍EuWjPE ؋EPVWEjPEu ؋EPVWEjPgE ؃PEFmEuuuPj(WEjP7E ؍Pj)WEjP E ؍LPj(WEjP E ؍PPj)WEjPDP ؍PjWEjPD ؍Pj WEjPD ؍PhWEjPD ؍Ph WEjPDP ؍TPjWjEPsD ؍XPj WEjP\D ؍\PhWEjPBD< _^[]ËUVujV1FjP&F8j PFhj PjP"HH HjPjPDj Pj PLjPTGXG\G`G(^]ËUS]VW39uIFhdjEYYtSVgYYuVYWEG3@$Wdž0GY3Y_^[]ËUQQU3SVWf9t8u ft#Ef9EtЉUUfu3f9u_+^[]ËUT3ʼnESVWuMq]uEX339E WWuuPSvEJU;#t5=wf^tPiFYt Ut1RWV?uVuujS4v$tuPVu `IV蚊Y}t E䃠PǍe_^[M33]ËUE@ H|ttttVjH(^y@Tt tyt QtuNY^]ËUQSVuWtl=TteF|t^8uYt8uPDYYt8uPD)YYv|DDYYtE8u@-PD+PD+PvDkDYjXE~(@Ttt8uP3D3,DYYEtGt 8uPDYEEuVCY_^[]ËUMtIt3@@]ø]ËUVut!ItuV+VCYY^]ËUMtItH]ø]ËUEtsH H|t t t t VjH(^y@Tt t yt Qt uZY^]j hcTe"LxL TPt7u=jeYe5\TW3YYuE t ujeYË8}̋UVu Wt|Iff;uftfPf;QufuދhIVrYYtjhIVqYYtYIff;uftfPf;Qu fuu0jEPh E PPZt)E}_^]VS9YjEPh 3UT3ʼnEVuEj PjYVPZtj EVP8 u@3M3^]ËUQVu 3WB3xNStH7+‹؋Ek M4E0pYYuEMȋE ys{;~[3_^]ËUQQS]VWTD33҉UpPPVf~Eˍf9tWjhIE 3Vf9tGf9t3Y9Fu2Vj@hI t3Vf9t |QY39~6f9;u f98u`I VPzYY P`IE t0}M 3fQff;Eu+APujUSj@WhS_Xj@Sh P=Xtjj_SYYuj.SYYtj@Sj P Xt9ujhIjWuj jWV轷3@3_^[]3PPPPP8̋UT3ʼnESVuWIBBBVLYKdٍ jxɁPQV`Iu!@3 PsTBnYYuVYt wwЃM_^3[]UVWA3JTqff;u+3jh@HBd`IEu8_^]ËUSVWhA3jZNPyff;u+3NTF`yff;u+3}Fd_9^`u vPYjhZHV\`I "u_^[]ËUSVW@3jZNPyff;u+3F`t vP"YjhHV\`IEu_^[]ËUM3fArfZv fwB]ËUT3ʼnESVuW/@(@VLYKdٍ jxɁPQV`I PsT"lYYjx PC`%PV`I PsPkYYu wdub{\tBs\ PsP u)wKPQff;u+;K\uwuV6Ytw#;jx PC`%PV`I PsPkYYuj9C`t9G9C\tSPBff;u+;S\uWjV tN3339C`u99C\t4 PsPjYYuW3SVi t9_uwЃ3@M_^3[-]UT3ʼnESVuW==VLYK`ٍ jxɁPQV`Iu!@a PsPiYYK`u u2Wj u29K\t- PsPiYYuWPV t wwЃM_^3[V]UUV3 ft9Wj_ARf;wAf;wɃ fu_^]ËUQMVW3f9|If:f;>uftfzf;~ufuދ҃t]If:f;>uftfzf;~u fuu jEPE h p`It)E5Q?0Y,jEPE h p`Iu3 Eu`I_^]ËUM3f;It r3@]3]ËUQVW;ujEPh Q`It2;ut(} t"wPNffuwP+Y;t3@3_^]ËUQSVu W3x47+‹؋Ek M4E0sgYYtys{;~2_^[]ËMEMUT3ʼnEE S]VuWE:P}E3:M3҉LE0xtf9t IWHPhI.E 3҉Utnf9titf9t EP EPy}YIuHPhI tN3tf98t EP EP2Y,tf9t EP5YE`IEE3}u3M_^3[]3EP#VYYtQ`Itju`ItEt0EWjUPPu.E|@u ]EݕΉ%u33C 33ۋu&QQ${'YY$>ȉj _tu33ۋ0É4\C,3DžDž3ɋ ; 0u䍂ϋ3҃+ȉ3@<,HɉЉtA33+su 9v2Ƀsrr jrZʉ+0;rg;s3F;sB3##苍㋍ É0INt,땋t΍03󫋽9v B,3,+3P,P0SP3jXA\PP`SPϋ3҃+ȉ3@:,HɉЉtA33+su 9v2Ƀsrr jrZʉ+0;rg;s3F;sB3##苍㋍ É0INt,땋t΍03󫋽9v B,3,+3P,P0SP3@Dž\j!5DžDž3ɋ ; 0u䃥t@3+,΍;s0A;s3ҋ Љ0It,볋s F,,5+VjPǻ3@5,t@3+,΍;s0A;s3ҋ Љ0It,봋s F,,4+VjP3@5G\PP`SP3j YZ񉅐ʉ|h&vj&X fwI4gwIW1jPDPdwI`nIPPwru3\\\33؋``F;u`\_\`PP`\SP]u3\P\\3ɋ3؋``F;u\s43\P;\r``ut ω \t\33<u;F3ҋ!stj;u@Ɖ$@A;ljut4s;uA3AȃsF;\PP`SP:tr+|wI|u]3\P:3\PP`SP2늃\jP`\33`lj`|F;u]\sQ`\<񉅠ʉG&vj&X fwI4gwIW1jPPdwI`nIPPnu3,Ps{,n,33؋00F;u9,s0,,0P|P0,SP6,,3ɋ|3؋00F;uE;,r00ut ω ,t,33<u;F3ҋ!stj;u@Ɖ$@A;lj|ut4s;uA3AȃsF;,PP0SP+wI,330lj0F;ut,ssN0,e3P,P0SP?27,j3P,P0SP,t|j 33[0Ɖ0G;u䉵tB,ss‰0,&3P,P0SPn\P,PYY w\1j 33[`lj`A;u䋵tV\ss`\<3P\P`SPu H 0wAx wȋEH;r;,33ɋ0ʚ;lj0A;u߻t@,ss0,&3P,P0SP\P,PsYYj_+30;r7Ou vj Y;4t_^[t lP2YM3踥]hI hIhIuQ u hI3PPPPP̋USV3۸W]EEU+‹Mj[4IM+1Bf;wB >Gf;wG ǃmt ftf;tƋM]+t"yAE EY];wI_^[]ËUMSVWt{ts} uufxb3;+‹+ȦItyXx;~݃x1̦IjUSVYY~;}SVu 9 u G3_^[]3PPPPPk̋U}tuYx=s ȦI]3]ËUuuu u`I]ËUf9Eu M E싀u!MAfw f EfEjf9Us0uWCYYu fEEMEMQjMQRP{u fEEfE}t M胡P]ËUM38t ;E t@<u]ËUSV@3W}#Jf;u f@u f;tދǹ`#t%= t=@t ;u 3ɋA#ы# Ћ # Ћ # ƒ Ƀ _ ^ []ËUQS]VWËU#j^t ;t uE #t"=t=t ;u 3ɋA## Ћ# Ћ# ƒ _ E^[]ËUMSV? W#3tt;t j@[@ƹ#t%=t=t ;u` @ 3ɋA#ы# Ћ# Ћ# ƒ  _^[]ËUQMSV% W#Ej_0t;t ڋ#t%=t=t ;u 3ɋA## Ћ# Ћ#  E _^[]ËUM##;t]ËU VWjY3}ueE%?Pa=TY}3 ]MQYЋȃ? ы? ы  _ ^]ËUQQV3WfE}M3?G## # # # 9=T}3 ]U?ʋ## ȋ# ȋ# ȋ# ʋ  _ ^]ËU WuYjЍ}Y3uE3Ё?3‰Eeu=TY_|]E%? EU]ËU SVW]?3F## Ћ# Ћ# Ћ# #ƍ}j 3YuM3ƒ?3ȉMe?Ë## ȋ# ȋ# ȋ# #_ 95T^[|]E? EU]ËU T3ʼnEE MMES]]VW8E}sMMΉuSPQJ؃ tSE;t9]r1SPV t 3ytt}E+]E뜋E3qU+uY}t u/Y^[]ËUT3ʼnESVWuME3WWu@u E#؅t}H;#t2=wtVPYtAt0SVuu 1#tEWWP#EPjVWu&E V)IY}t E胠PǍe_^[M3•]ËUT3ʼnEE MS]VuW3px;h|PuVQttFjPW 9;tAP|PQ333`IzWWuVpYtjPYYt*tVuxptƋV+Ywu$u<f;w VYZ(f;w'@ 3=VQu|.f;wčE3P%#}Pu}Q>~ _^]j daIPT3U$~$fD$f(ffs4ff( If(If( If(%If(5IfTfVfXf%f(If(IfTf\fYf\XfYf(fXƁ*f Df( pIf(f(IfYfYfXf(IYf(-IfYf(IfTfXfXfYYfXf(IfYf(ffY˃f(fXfXXXfD$D$fD$f( 0IfwHt^wlfD$f( If( IfTfVftXIúOf I^f PI4f @IYs:fW^ɺ fL$T$ ԃT$T$$D$fT$fD$f~fs f~с t릍$ƅp uJ$$ƅp2+at@u tF t2t-Iƅpݽ`aAuƅp-I uS u uu tƅp-Iu tBXݽ`au-I tƅp -Iƅp u-I-Iٛݽ`aAuݽ`aݽ`ٛu Iٛt øVtV$$vzft^t.̀zuf\?f?f^٭^>I剕lݽ`ƅpa$؃PRQ bIYZX#zuf\?f?f^٭^>I剕lݽ`ƅpɊaݽ`ɊaŊ$׊$ ؃PRQ bIYZX#ɍ$I؍$$ÐtؐÍ$d$۽bۭbi@tƅpƅp.Iɍ$$۽bۭbi@t ƅpƅpÍ$۽bۭbi@t ۽bۭbi@t ƅpƅpÐ-Ipƅp ÍI-$I t t6I tËT$fT$l$étPIËB%=tËB D$B  D$ $,$ BËD$%=tËD$f<$t,$Zf$f=tf tf t Z,$ZÃ$D$%$D$%t==t_f$f=t*f u!f tt{Z]Z,$Z|IlIs ItIdIv IUEEEEE UE]MEMEMEMPQRU Ef}tmËU =TVWt5LTXaIGEetPjY+t:t)tEIMEI?EIMEI$EEItT tC9EIEϋuEE ]E]P]bIYEEIEtAt3 t%t-t EE$IE,IEDIEIEϋuEE ]E]P]bIYuQO!DEEIEϋuE ]E]P]bIYu "E_^]ËUQQSVVh?BEYYM#QQ$f;u=AHYYw VSBEaESS\$$j j8?UED{ uS\$$j jVSFBEYY^[]ËUQQEQQ$BYYuJEQQ$xEYYDz+ IQQU$UEYYDzjX 3@3]ËUE9Mu;}uuzIAE9Eu;}u5z AEI9M u.}EAsE{b\9E uY}uSEQQ$EYYыAuIu zuЗIE3]ËSQQUkl$T3ʼnECVs W|t)t tttuljj jjj_QFPWX8 uGKtt teEF]EFPFPQW|PEP:h|?>YYtt VYu6nЁuT$ t0 # fnfs f Sf$^ʺ #fWfSfWfTfvfɁf%=umfL$f(ѹfnfT Sfs4ffffvf%=t-fL$f%t fpSfhSfL$f%9fWfL$f%fWXĺnf$f~fs f~ҁ ¹kf XSfSYɺ(f$$fT$f~u)fs f~?u fSfSfWfTfvf%=ucff$$% уtf%=?r!fWf%=?sfWf`SXºUf~fs f~ fSt,f~%=wrwf SÃfD$T$ ԃT$T$$ fD$(Ã~(="VЃW?&=VЃ €WXXSfY\SfY\f(.Tf(5 SfYfXfpYXXf%@Sfnʁƒ fW?fYT$Yfs-fpDf(=0SXfYXffYYfYfXfYYfpYfpYYfnfs-fnfvfXXfTXfWfvf\XfTf_\XXÃA^YYXYXf%=^XYYXf%=fSfnYfs-fVtfxSYS}fSYlfpDfYf%@+-p< Ё$=rɀfnfs-f$$f?f3%;Yf$fL$y$~$Í$\$D$%=u<$f$ffd${ff%f-00f=6f SYfS-XfS\f(SYfɁv?f(-SSfY\Y S\fxf\fYf\f(5SY\fYfY\f(\fXX\YfYYfYfYfX-SY fX5SfYXXYXfXfh\\XHfYXXXXXfXXf(,ff= u Y SfSY\YSÃf$$~$ÍĨ\$D$%=<$$f%=t0%uQf$<$uPuHfu>ًu$f%uf%u f%tf$L$$D$1T$ ԃT$T$$UfD$f$$~$Ë\$D$%=u<$f$ffd$ff%f- 8f=ff( @SfY-f(PSfXf(`Sf\f-S)f(%pSfYكYfYf\fY SXf(f\f5S6TfT-Sf(f\f^f\f(x\fYf\f(H0fYf(``fYXf(fYfX8fXH fYfX`PfXf(HpfYfYfXf(H@fYfXf(fYYfYfYfXYfXfX\XffXYXXXf=SYffTYY\\\Y\X\X\X3ff=~ u YSSYXYSf(Ãf$ $~$\Ë$̃=PT \$D$%=u<$f$ffd$ ~D$f(Sf(f(fs4f~fT Sffʩu"=|Yf=2 fL$D$D$~D$ff(f.zf= |!=2 fTS\fL$D$fSfVSfTSf\$D$;&22d$ƅp t tݽ`au2X -IÍ$ t t t$؊ U0Sٽ\}}PQR<mmZYXu8[ݕzUU0Sٽ\}PQRg<mZYXuE88S[ݕzU0Su uuuٽ\8c[À8=TuOݕ0p t\ЁuT$t1 # fnfs f pQTfT$^ʺg #f`QTfWfTfvfɁf%=uefL$ fT$ fnfT QTfs4ffffvf%=t#fL$ f%tQTQTfL$ f%fL$ f%Xĺ]fT$f~fs f~ҁ ¹f QTfRTYɺfd$fT$ f~u fs f~?uf`QTfWfTfvf%=uUffd$% уtf%=?rf%=?sQTXºYf~fs f~ fpQTt0f~%=wrwfD$D$ÃfD$T$ ԃT$T$$-D$Ã~(=<VЃW?&=VЃ €WXXPQTfY\PQTfY\f(.Tf(5QTfYfXfpYXXf%QTfnʁƒ fW?fYT$Yfs-fpDf(=QTXfYXffYYfYfXfYYfpYfpYYfnfs-fnfvfXXfTXfWfvf\XfTf_\XXÃN^YYXYXf%=fD$D$^XYYXf%=fD$D$fQTfnYfs-fVtfQTYQTefQTYTfpDfYf%@+-p< Ё!=r ɀfnfs-fD$D$fd$f?f3%-KU$~$fD$ff%f-00f=Bf PRTYfXRT-XfpRT\f(`RTYfɁv?f(-@RTSfY\Y xRT\fxf\fYf\f(5 RTY\fYfY\f(\fXX\YfYYfYfYfX-0RTY fX5RTfYXXYXfXfh\\XHfYXXXXXfX΃Xfd$D$Iff= uYRTfD$D$fRTY\YRTfD$D$̃ $ R<$D$ tQf<$tYu=T̋ RTɋu,u%|$u."u|$u%t-I=To RThZU$~$fD$ff%f- 8f=ff( RTfY-f(RTfXf(RTf\f-ST)f(%RTfYكYfYf\fY STXf(f\f5ST6TfT- STf(f\f^f\f(x\fYf\f(H0fYf(``fYXf(fYfX8fXH fYfX`PfXf(HpfYfYfXf(H@fYfXf(fYYfYfYfXYfXfX\XffXYXXXf=STYffTYY\\\Y\X\X\ǃXfD$D$?ff=~ u Y@STf8STYXY@STf\$D$$̋T$B J3YT"&MFT$B J3J3LbT%jjJgZgng,jjljTjBj~ih$h4hFhVhhh|hhhhhhhhii"i8iVirggrqqqqqqqlq^qHq2qq qppppppptp^pHp8p&pggggg&rljjjjj kk&k.kFk^k|kkkkkkk6r,l:lNljl~llllllm*m@mTm`mmmmmmmmmnn n0nNn\nlnnnnnnn oo,o>oNo\oxoooooooooppiiiip j otsj0gDbFhaFbF FJGf.HHHGaHHFTTcIXcI+++&->*<>,()^|&&||*=+=-=/=%=>>=<<=&=|=^=`vftable'`vbtable'`vcall'`typeof'`local static guard'`string'`vbase destructor'`vector deleting destructor'`default constructor closure'`scalar deleting destructor'`vector constructor iterator'`vector destructor iterator'`vector vbase constructor iterator'`virtual displacement map'`eh vector constructor iterator'`eh vector destructor iterator'`eh vector vbase constructor iterator'`copy constructor closure'`udt returning'`EH`RTTI`local vftable'`local vftable constructor closure' new[] delete[]`omni callsig'`placement delete closure'`placement delete[] closure'`managed vector constructor iterator'`managed vector destructor iterator'`eh vector copy constructor iterator'`eh vector vbase copy constructor iterator'`dynamic initializer for '`dynamic atexit destructor for '`vector copy constructor iterator'`vector vbase copy constructor iterator'`managed vector copy constructor iterator'`local static thread guard'operator "" operator co_awaitoperator<=> Type Descriptor' Base Class Descriptor at ( Base Class Array' Class Hierarchy Descriptor' Complete Object Locator'tTTF_nj f29.EZ%qVJ.C|!@Ί Ą' |Ô%I@T̿aYܫ\ DgR)`*! VG6K]_܀ @َЀk#cd8L2WBJa"=UD~ $s%rс@b;zO]3AOmm!3VV%(w;I-G 8NhU]i<$qE}A'JnWb쪉"f37>,ެdNj5jVg@;*xh2kůid&_U JW {,Ji)Ǫv6 UړǚK%v t:H孎cY˗i&>r䴆["93uzKG-wn@  _l%Bɝ s|-Ciu+-,W@zbjUUYԾX1EL9MLy;-"m^8{yrvxyN\lo};obwQ4Y+XW߯_w[R/=OB R E]B.4o?nz(wKgg;ɭVl H[=J6RMq! EJjت|Lu<@rd 6x)Q9%0+L ;<(wXC=sF|bt!ۮ.P9B4Ҁy7P,=87MsgmQĢR:#שsDp:RRN/M׫ Ob{!@fu)/wdq=v/}fL3. iLs&`@< q!-7ڊ1BALlȸ|Rabڇ3ah𔽚j-6zƞ) ?IϦw#[/r5D¨N2Lɭ3v2!L.2>p6\BF8҇i>o@@w,=q/ cQrFZ**F΍$'#+GK ŎQ1VÎX/4Bycg6fvPbag ;s?.❲ac*&pa%¹u !,`j;҉s}`+i7$fnIoۍut^6n16B(Ȏy$dAՙ,C瀢.=k=yICyJ"pפldNnEtTWtøBncW[5laQۺNPqc+/ޝ"^̯p?m- }oi^,dH94X<H'W&|.ڋu;-Hm~$P  %-5 > H R ] i u -C Y p        %  d'@Bʚ;minkernel\crts\ucrt\inc\corecrt_internal_strtox.h__crt_strtox::floating_point_value::as_double_is_double__crt_strtox::floating_point_value::as_float!_is_doubleINFinfINITYinityNANnanSNAN)snan)IND)ind)/mscoree.dllCorExitProcessCOMSPECcmd.exe/ccmd.exe /c COMSPEC\PATHccsUTF-8UTF-16LEUNICODEccsUTF-8UTF-16LEUNICODE{I${I<{IX{Ih{I{I{I{I{I{I{I|I(|I<|IP|I\|Il|I||I|I|I|I|I|I|I|I}I\|I4}ID}I\}Il}I}I}I}I}I\|I}I\|I}I}I~I$~I8~I\|INo errorOperation not permittedNo such file or directoryNo such processInterrupted function callInput/output errorNo such device or addressArg list too longExec format errorBad file descriptorNo child processesResource temporarily unavailableNot enough spacePermission deniedBad addressUnknown errorResource deviceFile existsImproper linkNo such deviceNot a directoryIs a directoryInvalid argumentToo many open files in systemToo many open filesInappropriate I/O control operationFile too largeNo space left on deviceInvalid seekRead-only file systemToo many linksBroken pipeDomain errorResult too largeResource deadlock avoidedFilename too longNo locks availableFunction not implementedDirectory not emptyIllegal byte sequence+INFinfINITYinityNANnanSNAN)snan)IND)ind)   oGGGG%hF%hF5GG~H~H̪GGGG GG%hFwH%hFGժG%hFG|G%hF  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~IfFI@TfFI@TĀH,I@THDI@T!H\I@T̏HLC_ALLLC_COLLATELC_CTYPELC_MONETARYLC_NUMERICLC_TIME=;;=Cutf8utf-8_.,_.INFinfNANnanNAN(SNAN)nan(snan)NAN(IND)nan(ind)e+000TIXI\I`IdIhIlIpIxIIIIIIIIIIăIȃĨIЃIԃI؃I܃IIIIIIăIIII I,I4I@ILIPITI`ItIIIIIIIIIȄI؄IIII I4I?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~ ((((( H ( 0IIII II!I$I ,I4IhI?pI@xIAICIDIFIGIIIJIKINIOȯIPЯIVدIWIZIeIIIIIؘI I,I8IDI I PI \I hItIIII̘IIIIIȰI԰IIIIIII (I!4I"@I#LI$XI%dI&pI'|I)I*I+I,I-ıI/бI2ܱI4I5I6I7 I8I9$I:0I;HI?TI@`IAlICxIDIEIFIGIIIJ̲IKزILINIOIPIRIV IW,IZ8ICDIk\I lI xI I I I I I; ̴Ik شIIII  I I $I0I;II7IPI IN`I/ItIIIZXI IO(I( IjI,Ia`I8IPhIDIPIQpI\IRPI-hIrpI1tIxI:IxII?IISxI2IyI%IgI$IfI@I+ImIЯI=II;IhI0IIw Iu,IUI8IDITPII\II6hI~ItIVIIWIIIIIIXIIYȯI<IIIvIII[I"Id(I8IHIXIhIxIII\IIIIIȮIII]I3 IzI@II8(II94IЮI@I^LInخIXI_I5dI|I pIbI|I`I4II{ I'IiIoIIIIII IF,Ipaf-zaar-aear-bhar-dzar-egar-iqar-joar-kwar-lbar-lyar-maar-omar-qaar-saar-syar-tnar-yeaz-az-cyrlaz-az-latnbe-bybg-bgbn-inbs-ba-latnca-escs-czcy-gbda-dkde-atde-chde-dede-lide-ludiv-mvel-gren-auen-bzen-caen-cben-gben-ieen-jmen-nzen-phen-tten-usen-zaen-zwes-ares-boes-cles-coes-cres-does-eces-eses-gtes-hnes-mxes-nies-paes-pees-pres-pyes-sves-uyes-veet-eeeu-esfa-irfi-fifo-fofr-befr-cafr-chfr-frfr-lufr-mcgl-esgu-inhe-ilhi-inhr-bahr-hrhu-huhy-amid-idis-isit-chit-itja-jpka-gekk-kzkn-inkok-inko-krky-kglt-ltlv-lvmi-nzmk-mkml-inmn-mnmr-inms-bnms-mymt-mtnb-nonl-benl-nlnn-nons-zapa-inpl-plpt-brpt-ptquz-boquz-ecquz-pero-roru-rusa-inse-fise-nose-sesk-sksl-sisma-nosma-sesmj-nosmj-sesmn-fisms-fisq-alsr-ba-cyrlsr-ba-latnsr-sp-cyrlsr-sp-latnsv-fisv-sesw-kesyr-syta-inte-inth-thtn-zatr-trtt-ruuk-uaur-pkuz-uz-cyrluz-uz-latnvi-vnxh-zazh-chszh-chtzh-cnzh-hkzh-mozh-sgzh-twzu-za=CONOUT$log10??33??BBxPD?X1=??0C0CΗ5@=)d U5j%5j?~@5wzA.lzZ?ܧ׹fq @ @6C ??expHHHH5h!?5h!??@  ?5h!>@@ |?Q-8>=޶W?0 k8=ޮp? x9=>.ښ?pn5=Yح? Q*=c??b6=Y?T?=>?W!=@-32?Dz=p(?vP(=`?US?>=e?g7=`ŀ'?bͬ/=^s?}#=Jwk?zn=N ָ?LN9=@$"3?5Wg4p6=T?Nv$^)=&?.)<lB?M%=`j?w*= <śm?E2=ެ> ?E=t?? =OQ?w(@ <0?Ac 0=Pyp?dry?=St)?4K >=$?QhBC .=0 ub?-0=?a>-?=?Й,<(lX ?T@b ==P?3h,%=f??# =V ?ߠϡ6=Y?z $=G? $l35=@n?[+3=Rŷ?sdLi==p|?rx"#2=@.?|U2=lԝ?rF=a? 4=Y?sl׼#{ =`~R=?.i1=,? =vX?=p?h}s"= E[ ?%S#[k=7H?j=!V1?}a2=jq?20J5=?5=x¾/@?"B <1=iz?\-!y!=X0z?~b>==:? #.X'=HBO&?(~=xbb? .=Cq?y7i9+= v?:=0 ?2ض8=xPD?X1=??Q?Q?????????]?]?P?P? ? ?U?U?(?(?`?`?_?_?????z?z?1?1?p?p???(e?(e?@#?@#???`?`?hk?hk?,?,?x?x?????N?N?x?x?p?p???~?~?HN?HN???????p?p?Xi?Xi???????????8?8?s?s?pI?pI?&?&?????o?o? *? *???`?`?Z?Z???0?0???PY?PY???`?`???pm?pm?/?/??????UTH premake.criteria__gcfilesdatastringmatchPremake/5.0.0-alpha14_OPTIONSinsecureheadersprogressuserpwdusernamepasswordtimeouttimeoutmssslverifyhostsslverifypeerproxyurlluainterrupted!%s: %s __tostring(error object is a %s value)Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio require_PROMPT_PROMPT2> >> return %sreturn %s;=stdinprinterror calling 'print' (%s)---LUA_NOENVwbUnable to open file.%s %s OK.f_LOADED_G.function '%s'%s '%s'main chunkfunction <%s:%d>?stack traceback: ...Slnt %s:%d: in (...tail calls...)bad argument #%d (%s)nmethodcalling '%s' on bad self (%s)bad argument #%d to '%s' (%s)__namelight userdata%s expected, got %sSl%s:%d: %s: %sexitinvalid option '%s'stack overflow (%s)stack overflowvalue expectednumber has no integer representationnot enough memory for buffer allocationLUABOXbuffer too largecannot %s %s: %s@%sropenLuarbreopenreadobject length is not an integer'__tostring' must return a string%I%ftruefalsenil%s: %ptoo many upvaluesPANIC: unprotected error in call to Lua API (%s) core and library have incompatible numeric typesmultiple Lua VMs detectedversion mismatch: app. needs %f, Lua core provides %f_SCRIPT_DIRcannot open %s: No such file or directory_SCRIPTunable to encode pathunable to switch to directory '%s'unable to set mode %o on '%s', errno %d : %sunable to encode first pathunable to encode second pathrbfailed to open first filefailed to open second filefailed to read first file contentfailed to read second file content(error with no message)Unable to compile '%s': %sunable to write to '%s'unable to encode source pathunable to copy file to '%s', reason: '%s'HKCU:HKLM:HKCR:HKU:HKCC:majorversionminorversionrevisiondescriptionkernel32.dll\WindowsSoftware\Microsoft\Windows NT\CurrentVersionproductNamewindowsIsWow64Processkernel32unable to encode filepath/premakepath$/unable to encode maskunable to decode filename...unable to create directory '%s'unable to fetch real path of '%s', errno %d : %sfailed to translate error messagefailed to get error messageunable to encode dest pathunable to remove directory '%s''%s' could not be accessed'%s' was not foundAn unknown error %d occured while accessing '%s'mtimesizeab unable to touch file '%s'wbunable to open file to '%s'%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02Xunable to write file to '%s'..../Filename)Extension)./**normalizegetDefaultSeparatorWildcards expansion too big._compile_deletematchespromptgetabsolutegetrelativeisabsolutejoindeferredjoinhasdeferredjoinresolvedeferredjointranslatewildcardschdirchmodcomparefilescopyfile_is64bitisdirgetcwdgetpassgetWindowsRegistrygetversionhostisfileislinklocatematchdonematchisfilematchnamematchnextmatchstartmkdirremoverenamepathsearchrealpathrmdirstatuuidwritefile_ifnotequaltouchfilecompilegetEmbeddedResourceendswithhashsha1startswithnewwritewritelntostringclosegetTextColorsetTextColorgetpostdownloadextractcriteriadebugosbufferedtermhttpzip_COPYRIGHT_PREMAKE_VERSIONCopyright (C) 2002-2018 Jason Perkins and the Premake Project_PREMAKE_COPYRIGHThttps://github.com/premake/premake-core/wiki_PREMAKE_URL_TARGET_OSHOMEUSERPROFILE~_USER_HOME_DIR_WORKING_DIRerrorColorError: %s _PREMAKE_COMMAND_premake_mainPATHPREMAKE_PATH;/.premake;/usr/local/share/premake;/usr/share/premake/scripts=--scripts=_ARGVDI`@PI@\I@hI@pI@IС@I @I@I@I@ I@,I@4I@`I@pI@I8@I9@I6@I@SdI>SI:S>SdI$>S,>S.SM?.SQ7.S``J.SJ .S`Md,/SO/SJ$/SP\ 8/SȭOP/SQ p/SO/SXO/SPCLp/SM/SP/SJ/S8?R0SJ 0SM 80S PP0S(gKh0S@JG 0S@mO0S@pR) 0SK=0S@tO0SnK0SM0Sp]Pe1SЋK(1S(RPH @1ShO_T1SJ&h1SQ 1SxP+ 1SjM1SpQR1SOT'1SxO1SJ2SpP4 2SP42SQdL2SO\d2SJ[x2SHK062SM{2SP2SHO,2SJ3S8COO,3S8RsL3S00J.0l3SKV |3S`N3SQQ3SJ3SOr#3S8Q`3SsP3ShvK?3S|M 4SpP4S`K/04S8NH4S(Ld4SMR|4S P^ 4SP4SM4ShNyC4S@OG4Sx7K5SMs,5SpIX H5SK%\5SfMh5S(=L$|5SMC5SI5ShJ5SpM5SHK6SN 6SyJ$46S(;OH6S,Jb\6SRfx6SxO6S@M6SLf46SuM6S7LE7SP ,7SJEL7S`@P`7S>Kv(|7SN7SaO 7S8M7SPs 7SEM! 8Sx!P@8SJT8S]Oh8SPlR|8SPhR8SP8S`Ma8SwO8Sp{R08SQt8SXLh-SHMH9SpgMR(9SMJuserdatalocal p = premake local gmake2 = p.modules.gmake2 local tree = p.tree local project = p.project function gmake2.generate_workspace(wks) p.eol("\n") gmake2.header(wks) gmake2.configmap(wks) gmake2.projects(wks) gmake2.workspacePhonyRule(wks) gmake2.groupRules(wks) gmake2.projectrules(wks) gmake2.cleanrules(wks) gmake2.helprule(wks) end function gmake2.configmap(wks) local first = true for cfg in p.workspace.eachconfig(wks) do if first then _p('ifeq ($(config),%s)', cfg.shortname) first = false else _p('else ifeq ($(config),%s)', cfg.shortname) end for prj in p.workspace.eachproject(wks) do local prjcfg = project.getconfig(prj, cfg.buildcfg, cfg.platform) if prjcfg then _p(' %s_config = %s', gmake2.tovar(prj.name), prjcfg.shortname) end end _p('') end if not first then _p('else') _p(' $(error "invalid configuration $(config)")') _p('endif') _p('') end end function gmake2.cleanrules(wks) _p('clean:') for prj in p.workspace.eachproject(wks) do local prjpath = p.filename(prj, gmake2.getmakefilename(prj, true)) local prjdir = path.getdirectory(path.getrelative(wks.location, prjpath)) local prjname = path.getname(prjpath) _x(1,'@${MAKE} --no-print-directory -C %s -f %s clean', prjdir, prjname) end _p('') end function gmake2.helprule(wks) _p('help:') _p(1,'@echo "Usage: make [config=name] [target]"') _p(1,'@echo ""') _p(1,'@echo "CONFIGURATIONS:"') for cfg in p.workspace.eachconfig(wks) do _x(1, '@echo " %s"', cfg.shortname) end _p(1,'@echo ""') _p(1,'@echo "TARGETS:"') _p(1,'@echo " all (default)"') _p(1,'@echo " clean"') for prj in p.workspace.eachproject(wks) do _p(1,'@echo " %s"', prj.name) end _p(1,'@echo ""') _p(1,'@echo "For more information, see https://github.com/premake/premake-core/wiki"') end function gmake2.projects(wks) _p('PROJECTS := %s', table.concat(p.esc(table.extract(wks.projects, "name")), " ")) _p('') end function gmake2.workspacePhonyRule(wks) local groups = {} local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onbranch = function(n) table.insert(groups, n.path) end }) _p('.PHONY: all clean help $(PROJECTS) ' .. table.implode(groups, '', '', ' ')) _p('') _p('all: $(PROJECTS)') _p('') end function gmake2.groupRules(wks) local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onbranch = function(n) local rule = n.path .. ":" local projectTargets = {} local groupTargets = {} for i, c in pairs(n.children) do if type(i) == "string" then if c.project then table.insert(projectTargets, c.name) else table.insert(groupTargets, c.path) end end end if #groupTargets > 0 then table.sort(groupTargets) rule = rule .. " " .. table.concat(groupTargets, " ") end if #projectTargets > 0 then table.sort(projectTargets) rule = rule .. " " .. table.concat(projectTargets, " ") end _p(rule) _p('') end }) end function gmake2.projectrules(wks) for prj in p.workspace.eachproject(wks) do local deps = project.getdependencies(prj) deps = table.extract(deps, "name") _p('%s:%s', p.esc(prj.name), gmake2.list(deps)) local cfgvar = gmake2.tovar(prj.name) _p('ifneq (,$(%s_config))', cfgvar) _p(1,'@echo "==== Building %s ($(%s_config)) ===="', prj.name, cfgvar) local prjpath = p.filename(prj, gmake2.getmakefilename(prj, true)) local prjdir = path.getdirectory(path.getrelative(wks.location, prjpath)) local prjname = path.getname(prjpath) _x(1,'@${MAKE} --no-print-directory -C %s -f %s config=$(%s_config)', prjdir, prjname, cfgvar) _p('endif') _p('') end end local p = premake local m = p.modules.self_test local _ = {} function m.capture(expected) local actual = p.captured() .. p.eol() local ait = actual:gmatch("(.-)" .. p.eol()) local eit = expected:gmatch("(.-)\n") local linenum = 1 local atxt = ait() local etxt = eit() while etxt do if (etxt ~= atxt) then m.fail("(%d) expected:\n%s\n...but was:\n%s\nfulltext:\n%s", linenum, etxt, atxt, actual) end linenum = linenum + 1 atxt = ait() etxt = eit() end end function m.closedfile(expected) if expected and not m.value_closedfile then m.fail("expected file to be closed") elseif not expected and m.value_closedfile then m.fail("expected file to remain open") end end function m.contains(expected, actual) if type(expected) == "table" then for i, v in ipairs(expected) do m.contains(v, actual) end elseif not table.contains(actual, expected) then m.fail("expected value %s not found", expected) end end function m.excludes(expected, actual) if type(expected) == "table" then for i, v in ipairs(expected) do m.excludes(v, actual) end elseif table.contains(actual, expected) then m.fail("excluded value %s found", expected) end end function m.fail(format, ...) local depth = 3 local arg = {...} if type(format) == "number" then depth = depth + format format = table.remove(arg, 1) end for i = 1, #arg do if (arg[i] == nil) then arg[i] = "(nil)" elseif (type(arg[i]) == "table") then arg[i] = "{" .. table.concat(arg[i], ", ") .. "}" end end local msg = string.format(format, table.unpack(arg)) error(debug.traceback(msg, depth), depth) end function m.filecontains(expected, fn) local f = io.open(fn) local actual = f:read("*a") f:close() if (expected ~= actual) then m.fail("expected %s but was %s", expected, actual) end end function m.hasoutput() local actual = p.captured() if actual == "" then m.fail("expected output, received none"); end end function m.isemptycapture() local actual = p.captured() if actual ~= "" then m.fail("expected empty capture, but was %s", actual); end end function m.isequal(expected, actual, depth) depth = depth or 0 if type(expected) == "table" then if expected and not actual then m.fail(depth, "expected table, got nil") end if #expected < #actual then m.fail(depth, "expected %d items, got %d", #expected, #actual) end for k,v in pairs(expected) do m.isequal(expected[k], actual[k], depth + 1) end else if (expected ~= actual) then m.fail(depth, "expected %s but was %s", expected, actual or "nil") end end return true end function m.isfalse(value) if (value) then m.fail("expected false but was true") end end function m.isnil(value) if (value ~= nil) then m.fail("expected nil but was " .. tostring(value)) end end function m.isnotnil(value) if (value == nil) then m.fail("expected not nil") end end function m.issame(expected, action) if expected ~= action then m.fail("expected same value") end end function m.istrue(value) if (not value) then m.fail("expected true but was false") end end function m.missing(value, actual) if table.contains(actual, value) then m.fail("unexpected value %s found", value) end end function m.openedfile(fname) if fname ~= m.value_openedfilename then local msg = "expected to open file '" .. fname .. "'" if m.value_openedfilename then msg = msg .. ", got '" .. m.value_openedfilename .. "'" end m.fail(msg) end end function m.success(fn, ...) local ok, err = pcall(fn, ...) if not ok then m.fail("call failed: " .. err) end end function m.stderr(expected) if not expected and m.stderr_capture then m.fail("Unexpected: " .. m.stderr_capture) elseif expected then if not m.stderr_capture or not m.stderr_capture:find(expected) then m.fail(string.format("expected '%s'; got %s", expected, m.stderr_capture or "(nil)")) end end end function m.notstderr(expected) if not expected and not m.stderr_capture then m.fail("Expected output on stderr; none received") elseif expected then if m.stderr_capture and m.stderr_capture:find(expected) then m.fail(string.format("stderr contains '%s'; was %s", expected, m.stderr_capture)) end end end local p = premake local m = p.modules.self_test local _ = {} _.suites = {} _.suppressed = {} function m.declare(suiteName) if _.suites[suiteName] then error('Duplicate test suite "'.. suiteName .. '"', 2) end local _suite = {} local suite = setmetatable({}, { __index = _suite, __newindex = function (table, key, value) if m.detectDuplicateTests and _suite[key] ~= nil then error('Duplicate test "'.. key .. '"', 2) end _suite[key] = value end, __pairs = function (table) return pairs(_suite) end, __ipairs = function (table) return ipairs(_suite) end, }) suite._SCRIPT_DIR = _SCRIPT_DIR suite._TESTS_DIR = _TESTS_DIR _.suites[suiteName] = suite return suite end function m.suppress(identifier) if type(identifier) == "table" then for i = 1, #identifier do m.suppress(identifier[i]) end else _.suppressed[identifier] = true end end function m.isSuppressed(identifier) return _.suppressed[identifier] end function m.isValid(test) if type(test.testFunction) ~= "function" then return false end if test.testName == "setup" or test.testName == "teardown" then return false end return true end function m.getSuites() return _.suites end function m.getTestWithIdentifier(identifier) local suiteName, testName = m.parseTestIdentifier(identifier) local suite, test, err = _.checkTestIdentifier(_.suites, suiteName, testName) if err then return nil, err end return { suiteName = suiteName, suite = suite, testName = testName, testFunction = test } end function m.parseTestIdentifier(identifier) local suiteName, testName if identifier then local parts = string.explode(identifier, ".", true) suiteName = iif(parts[1] ~= "", parts[1], nil) testName = iif(parts[2] ~= "", parts[2], nil) end return suiteName, testName end function _.checkTestIdentifier(suites, suiteName, testName) local suite, test if suiteName then suite = suites[suiteName] if not suite then return nil, nil, "No such test suite '" .. suiteName .. "'" end if testName then test = suite[testName] if not _.isValidTestPair(testName, test) then return nil, nil, "No such test '" .. suiteName .. "." .. testName .. "'" end end end return suite, test end function _.isValidTestPair(testName, testFunc) if type(testFunc) ~= "function" then return false end if testName == "setup" or testName == "teardown" then return false end return true end `qATPP\l<') p.callArray(m.elements.dCompile, cfg) p.pop('') end end vc2010.categories.DCompile = { name = "DCompile", extensions = { ".d" }, priority = 3, emitFiles = function(prj, group) local fileCfgFunc = function(fcfg, condition) if fcfg then return { vc2010.excludedFromBuild, m.dOptimization, m.dImportPaths, m.dStringImportPaths, m.dVersionConstants, m.dDebugConstants, m.dCompilationModel, m.dRuntime, m.dCodeGeneration, m.dMessages, m.dDocumentation, } else return { vc2010.excludedFromBuild } end end vc2010.emitFiles(prj, group, "DCompile", {m.generatedFile}, fileCfgFunc) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "DCompile") end } function m.dOptimization(cfg, condition) local map = { Off="false", On="true", Debug="true", Full="true", Size="true", Speed="true" } if cfg.optimize then vc2010.element('Optimizer', condition, map[cfg.optimize] or "false") end end function m.dImportPaths(cfg, condition) if cfg.importdirs and #cfg.importdirs > 0 then local dirs = vstudio.path(cfg, cfg.importdirs) if #dirs > 0 then vc2010.element("ImportPaths", condition, "%s;%%(ImportPaths)", table.concat(dirs, ";")) end end end function m.dStringImportPaths(cfg, condition) if cfg.stringimportdirs and #cfg.stringimportdirs > 0 then local dirs = vstudio.path(cfg, cfg.stringimportdirs) if #dirs > 0 then vc2010.element("StringImportPaths", condition, "%s;%%(StringImportPaths)", table.concat(dirs, ";")) end end end function m.dVersionConstants(cfg, condition) if cfg.versionconstants and #cfg.versionconstants > 0 then local versionconstants = table.concat(cfg.versionconstants, ";") vc2010.element("VersionIdentifiers", condition, versionconstants) end end function m.dDebugConstants(cfg, condition) if cfg.debugconstants and #cfg.debugconstants > 0 then local debugconstants = table.concat(cfg.debugconstants, ";") vc2010.element("DebugIdentifiers", condition, debugconstants) end end function m.dCompilationModel(cfg, condition) if cfg.compilationmodel and cfg.compilationmodel ~= "Default" then vc2010.element("CompilationModel", condition, cfg.compilationmodel) end end function m.dRuntime(cfg, condition) if cfg.flags.OmitDefaultLibrary then vc2010.element("CRuntimeLibrary", condition, "None") else local releaseruntime = not config.isDebugBuild(cfg) local staticruntime = true if cfg.staticruntime == "Off" then staticruntime = false end if cfg.runtime == "Debug" then releaseruntime = false elseif cfg.runtime == "Release" then releaseruntime = true end if (cfg.staticruntime and cfg.staticruntime ~= "Default") or (cfg.runtime and cfg.runtime ~= "Default") then if staticruntime == true and releaseruntime == true then vc2010.element("CRuntimeLibrary", condition, "MultiThreaded") elseif staticruntime == true and releaseruntime == false then vc2010.element("CRuntimeLibrary", condition, "MultiThreadedDebug") elseif staticruntime == false and releaseruntime == true then vc2010.element("CRuntimeLibrary", condition, "MultiThreadedDll") elseif staticruntime == false and releaseruntime == false then vc2010.element("CRuntimeLibrary", condition, "MultiThreadedDebugDll") end end end end function m.dCodeGeneration(cfg, condition) if cfg.buildtarget then local ObjectFileName = "" if cfg.buildtarget.basename then if cfg.buildtarget.prefix then ObjectFileName = cfg.buildtarget.prefix end ObjectFileName = ObjectFileName .. cfg.buildtarget.basename .. ".obj" end if cfg.buildtarget.directory then local outdir = vstudio.path(cfg, cfg.buildtarget.directory) ObjectFileName = path.join(outdir, ObjectFileName) end vc2010.element("ObjectFileName", condition, ObjectFileName) end if cfg.optimize then if config.isOptimizedBuild(cfg) then vc2010.element("Optimizer", condition, "true") end end if cfg.flags.Profile then vc2010.element("Profile", condition, "true") end if cfg.flags.CodeCoverage then vc2010.element("Coverage", condition, "true") end if cfg.flags.UnitTest then vc2010.element("Unittest", condition, "true") end if cfg.inlining then local types = { Default = "true", Disabled = "false", Explicit = "true", Auto = "true", } vc2010.element("Inliner", condition, types[cfg.inlining]) end if cfg.boundscheck and cfg.boundscheck ~= "Default" then local types = { Off = "Off", SafeOnly = "SafeOnly", On = "On", } vc2010.element("BoundsCheck", condition, types[cfg.boundscheck]) end if cfg.symbols then if cfg.symbols == p.Off then vc2010.element("DebugInfo", condition, "None") elseif cfg.symbols ~= "Default" then vc2010.element("DebugInfo", condition, iif(cfg.flags.SymbolsLikeC, "VS", "Mago")) end end if cfg.flags.ProfileGC then vc2010.element("ProfileGC", condition, "true") end if cfg.flags.StackFrame then vc2010.element("StackFrame", condition, "true") end if cfg.flags.StackStomp then vc2010.element("StackStomp", condition, "true") end if cfg.flags.AllTemplateInst then vc2010.element("AllInst", condition, "true") end if cfg.flags.BetterC then vc2010.element("BetterC", condition, "true") end if cfg.flags.Main then vc2010.element("Main", condition, "true") end if cfg.flags.PerformSyntaxCheckOnly then vc2010.element("PerformSyntaxCheckOnly", condition, "true") end end function m.dMessages(cfg, condition) if cfg.warnings == p.OFF then vc2010.element("Warnings", condition, "None") elseif cfg.warnings and cfg.warnings ~= "Default" then vc2010.element("Warnings", condition, iif(cfg.flags.FatalCompileWarnings, "Error", "Info")) end if cfg.deprecatedfeatures and cfg.deprecatedfeatures ~= "Default" then local types = { Error = "Error", Warn = "Info", Allow = "Allow", } vc2010.element("Deprecations", condition, types[cfg.deprecatedfeatures]) end if cfg.flags.ShowCommandLine then vc2010.element("ShowCommandLine", condition, "true") end if cfg.flags.Verbose then vc2010.element("Verbose", condition, "true") end if cfg.flags.ShowTLS then vc2010.element("ShowTLS", condition, "true") end if cfg.flags.ShowGC then vc2010.element("ShowGC", condition, "true") end if cfg.flags.IgnorePragma then vc2010.element("IgnorePragma", condition, "true") end if cfg.flags.ShowDependencies then vc2010.element("ShowDependencies", condition, "true") end end function m.dDocumentation(cfg, condition) if cfg.docdir then vc2010.element("DocDir", condition, cfg.docdir) end if cfg.docname then vc2010.element("DocFile", condition, cfg.docname) end if cfg.dependenciesfile then vc2010.element("DepFile", condition, cfg.dependenciesfile) end if cfg.headerdir then vc2010.element("HeaderDir", condition, cfg.headerdir) end if cfg.headername then vc2010.element("HeaderFile", condition, cfg.headername) end if cfg.jsonfile then vc2010.element("JSONFile", condition, cfg.jsonfile) end end  pBPBBBlocal p = premake p.vstudio.vs2008 = {} local vs2008 = p.vstudio.vs2008 local vstudio = p.vstudio newaction { trigger = "vs2008", shortname = "Visual Studio 2008", description = "Generate Visual Studio 2008 project files", targetos = "windows", toolset = "msc-v90", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = vstudio.vs2005.generateSolution, onProject = vstudio.vs2005.generateProject, onCleanWorkspace = vstudio.cleanSolution, onCleanProject = vstudio.cleanProject, onCleanTarget = vstudio.cleanTarget, vstudio = { csprojSchemaVersion = "2.0", productVersion = "9.0.30729", solutionVersion = "10", versionName = "2008", toolsVersion = "3.5", } } local p = premake local tree = p.tree local project = p.project local config = p.config local codelite = p.modules.codelite codelite.project = {} local m = codelite.project function codelite.getLinks(cfg) return config.getlinks(cfg, "system", "fullpath") end function codelite.getSiblingLinks(cfg) return config.getlinks(cfg, "siblings", "fullpath") end m.elements = {} m.ctools = { gcc = "gnu gcc", clang = "clang", msc = "Visual C++", } m.cxxtools = { gcc = "gnu g++", clang = "clang++", msc = "Visual C++", } function m.getcompilername(cfg) local tool = _OPTIONS.cc or cfg.toolset or p.CLANG local toolset = p.tools[tool] if not toolset then error("Invalid toolset '" + (_OPTIONS.cc or cfg.toolset) + "'") end if p.languages.isc(cfg.language) then return m.ctools[tool] elseif p.languages.iscpp(cfg.language) then return m.cxxtools[tool] end end function m.getcompiler(cfg) local toolset = p.tools[_OPTIONS.cc or cfg.toolset or p.CLANG] if not toolset then error("Invalid toolset '" + (_OPTIONS.cc or cfg.toolset) + "'") end return toolset end local function configuration_iscustombuild(cfg) return cfg and (cfg.kind == p.MAKEFILE) and (#cfg.buildcommands > 0) end local function configuration_isfilelist(cfg) return cfg and (cfg.buildaction == "None") and not configuration_iscustombuild(cfg) end local function configuration_needresoptions(cfg) return cfg and config.findfile(cfg, ".rc") and not configuration_iscustombuild(cfg) end m.internalTypeMap = { ConsoleApp = "Console", WindowedApp = "Console", Makefile = "", SharedLib = "Library", StaticLib = "Library" } function m.header(prj) _p('') local type = m.internalTypeMap[prj.kind] or "" _x('', prj.name, type) end function m.plugins(prj) _p(1, '') end function m.description(prj) _p(1, '') end function m.files(prj) local tr = project.getsourcetree(prj) tree.traverse(tr, { onbranchenter = function(node, depth) _p(depth, '', node.name) end, onbranchexit = function(node, depth) _p(depth, '') end, onleaf = function(node, depth) local excludesFromBuild = {} for cfg in project.eachconfig(prj) do local cfgname = codelite.cfgname(cfg) local fcfg = p.fileconfig.getconfig(node, cfg) if not fcfg or fcfg.flags.ExcludeFromBuild then table.insert(excludesFromBuild, cfgname) end end if #excludesFromBuild > 0 then _p(depth, '', node.relpath, table.concat(excludesFromBuild, ';')) else _p(depth, '', node.relpath) end end, }, true) end function m.dependencies(prj) local dependencies = project.getdependencies(prj) for cfg in project.eachconfig(prj) do cfgname = codelite.cfgname(cfg) if #dependencies > 0 then _p(1, '', cfgname) for _, dependency in ipairs(dependencies) do _p(2, '', dependency.name) end _p(1, '') else _p(1, '', cfgname) end end end function m.global_compiler(prj) _p(3, '') _p(4, '') _p(3, '') end function m.global_linker(prj) _p(3, '') _p(4, '') _p(3, '') end function m.global_resourceCompiler(prj) _p(3, '') end m.elements.globalSettings = function(prj) return { m.global_compiler, m.global_linker, m.global_resourceCompiler, } end function m.compiler(cfg) if configuration_iscustombuild(cfg) or configuration_isfilelist(cfg) then _p(3, '') return end local toolset = m.getcompiler(cfg) local forceincludes = toolset.getforceincludes(cfg) local cxxflags = table.concat(table.join(toolset.getcxxflags(cfg), forceincludes, cfg.buildoptions), ";") local cflags = table.concat(table.join(toolset.getcflags(cfg), forceincludes, cfg.buildoptions), ";") local asmflags = "" local pch = "" _x(3, '', cxxflags, cflags, asmflags, pch) for _, includedir in ipairs(cfg.includedirs) do _x(4, '', project.getrelative(cfg.project, includedir)) end for _, define in ipairs(cfg.defines) do _x(4, '', p.esc(define)) end _p(3, '') end function m.linker(cfg) if configuration_iscustombuild(cfg) or configuration_isfilelist(cfg) then _p(3, '') return end local toolset = m.getcompiler(cfg) local flags = table.join(toolset.getldflags(cfg), cfg.linkoptions, toolset.getlinks(cfg)) _x(3, '', table.concat(flags, ";")) for _, libdir in ipairs(cfg.libdirs) do _p(4, '', project.getrelative(cfg.project, libdir)) end _p(3, '') end function m.resourceCompiler(cfg) if not configuration_needresoptions(cfg) then _p(3, '') return end local toolset = m.getcompiler(cfg) local defines = table.implode(toolset.getdefines(table.join(cfg.defines, cfg.resdefines)), "", ";", "") local options = table.concat(cfg.resoptions, ";") _x(3, '', defines, options) for _, includepath in ipairs(table.join(cfg.includedirs, cfg.resincludedirs)) do _x(4, '', project.getrelative(cfg.project, includepath)) end _p(3, '') end function m.general(cfg) if configuration_isfilelist(cfg) then _p(3, '') return end local prj = cfg.project local isExe = prj.kind == "WindowedApp" or prj.kind == "ConsoleApp" local targetpath = project.getrelative(prj, cfg.buildtarget.directory) local objdir = project.getrelative(prj, cfg.objdir) local targetname = project.getrelative(prj, cfg.buildtarget.abspath) local workingdir = cfg.debugdir or prj.location local command = iif(isExe, path.getrelative(workingdir, cfg.buildtarget.abspath), "") local cmdargs = iif(isExe, table.concat(cfg.debugargs, " "), "") -- TODO: should this be debugargs instead? local useseparatedebugargs = "no" local debugargs = "" local workingdir = iif(isExe, project.getrelative(prj, cfg.debugdir), "") local pauseexec = iif(prj.kind == "ConsoleApp", "yes", "no") local isguiprogram = iif(prj.kind == "WindowedApp", "yes", "no") local isenabled = iif(cfg.flags.ExcludeFromBuild, "no", "yes") local ldPath = '' for _, libdir in ipairs(cfg.libdirs) do ldPath = ldPath .. ":" .. project.getrelative(cfg.project, libdir) end if ldPath == nil or ldPath == '' then _x(3, '', targetname, objdir, command, cmdargs, useseparatedebugargs, debugargs, workingdir, pauseexec, isguiprogram, isenabled) else ldPath = string.sub(ldPath, 2) _x(3, '', targetname, objdir, ldPath, command, cmdargs, useseparatedebugargs, debugargs, workingdir, pauseexec, isguiprogram, isenabled) end end function m.environment(cfg) local envs = table.concat(cfg.debugenvs, "\n") _p(3, '') _x(4, '', envs) _p(3, '') end function m.debugger(cfg) _p(3, '', iif(cfg.debugremotehost, "yes", "no"), cfg.debugremotehost or "", iif(cfg.debugport, tostring(cfg.debugport), ""), iif(cfg.debugextendedprotocol, "yes", "no")) if #cfg.debugsearchpaths > 0 then _p(4, '%s', table.concat(p.esc(project.getrelative(cfg.project, cfg.debugsearchpaths)), "\n")) else _p(4, '') end if #cfg.debugconnectcommands > 0 then _p(4, '%s', table.concat(p.esc(cfg.debugconnectcommands), "\n")) else _p(4, '') end if #cfg.debugstartupcommands > 0 then _p(4, '%s', table.concat(p.esc(cfg.debugstartupcommands), "\n")) else _p(4, '') end _p(3, '') end function m.preBuild(cfg) if #cfg.prebuildcommands > 0 then _p(3, '') local commands = os.translateCommandsAndPaths(cfg.prebuildcommands, cfg.project.basedir, cfg.project.location) for _, command in ipairs(commands) do _x(4, '%s', command) end _p(3, '') end end function m.postBuild(cfg) if #cfg.postbuildcommands > 0 then _p(3, '') local commands = os.translateCommandsAndPaths(cfg.postbuildcommands, cfg.project.basedir, cfg.project.location) for _, command in ipairs(commands) do _x(4, '%s', command) end _p(3, '') end end function m.customBuild(cfg) if not configuration_iscustombuild(cfg) then _p(3, '') return end local build = table.implode(cfg.buildcommands,"","","") local clean = table.implode(cfg.cleancommands,"","","") local rebuild = table.implode(cfg.rebuildcommands,"","","") _p(3, '') _x(4, '%s', build) _x(4, '%s', clean) _x(4, '%s', rebuild) _p(4, '') _p(4, '') _p(4, '') _p(4, '') _p(4, '') _p(3, '') end function m.additionalRules(cfg) if configuration_iscustombuild(cfg) then _p(3, '') return end _p(3, '') _p(4, '') _p(4, '') _p(3, '') end function m.isCpp11(cfg) return (cfg.cppdialect == 'gnu++11') or (cfg.cppdialect == 'C++11') or (cfg.cppdialect == 'gnu++0x') or (cfg.cppdialect == 'C++0x') end function m.isCpp14(cfg) return (cfg.cppdialect == 'gnu++14') or (cfg.cppdialect == 'C++14') or (cfg.cppdialect == 'gnu++1y') or (cfg.cppdialect == 'C++1y') end function m.completion(cfg) _p(3, '', iif(m.isCpp11(cfg), "yes", "no"), iif(m.isCpp14(cfg), "yes", "no") ) _p(4, '') _p(4, '') _p(4, '') -- TODO: we might want to set special code completion macros...? _p(4, '') -- TODO: search paths for code completion? _p(3, '') end m.elements.settings = function(cfg) return { m.compiler, m.linker, m.resourceCompiler, m.general, m.environment, m.debugger, m.preBuild, m.postBuild, m.customBuild, m.additionalRules, m.completion, } end m.types = { ConsoleApp = "Executable", Makefile = "", SharedLib = "Dynamic Library", StaticLib = "Static Library", WindowedApp = "Executable", Utility = "", } m.debuggers = { Default = "GNU gdb debugger", GDB = "GNU gdb debugger", LLDB = "LLDB Debugger", } function m.settings(prj) _p(1, '', m.types[prj.kind] or "") _p(2, '') p.callArray(m.elements.globalSettings, prj) _p(2, '') for cfg in project.eachconfig(prj) do local cfgname = codelite.cfgname(cfg) local compiler = m.getcompilername(cfg) local debugger = m.debuggers[cfg.debugger] or m.debuggers.Default local type = m.types[cfg.kind] _x(2, '', cfgname, compiler, debugger, type) p.callArray(m.elements.settings, cfg) _p(2, '') end _p(1, '') end m.elements.project = function(prj) return { m.header, m.plugins, m.description, m.files, m.dependencies, m.settings, } end function m.generate(prj) p.utf8() p.callArray(m.elements.project, prj) _p('') end function table.arraycopy(object) local result = {} for i, value in ipairs(object) do result[i] = value end return result end function table.contains(t, value) for _,v in pairs(t) do if (v == value) then return true end end return false end function table.shallowcopy(object) local copy = {} for k, v in pairs(object) do copy[k] = v end return copy end function table.deepcopy(object) local seen = {} local function copy(object) if type(object) ~= "table" then return object elseif seen[object] then return seen[object] end local clone = {} seen[object] = clone for key, value in pairs(object) do clone[key] = copy(value) end setmetatable(clone, getmetatable(object)) return clone end return copy(object) end function table.extract(arr, fname) local result = { } for _,v in ipairs(arr) do table.insert(result, v[fname]) end return result end function table.filter(arr, fn) local result = { } table.foreachi(arr, function(val) if fn(val) then table.insert(result, val) end end) return result end function table.flatten(arr) local result = {} local function flatten(arr) local n = #arr for i = 1, n do local v = arr[i] if type(v) == "table" then flatten(v) elseif v then table.insert(result, v) end end end flatten(arr) return result end function table.foreachi(arr, func) if arr then local n = #arr for i = 1, n do local v = arr[i] if v then func(v, i) end end end end function table.fold(list1, list2) local result = {} for _, item1 in ipairs(list1 or {}) do if list2 and #list2 > 0 then for _, item2 in ipairs(list2) do table.insert(result, { item1, item2 }) end else table.insert(result, { item1 }) end end return result end function table.implode(arr, before, after, between) local result = "" for _,v in ipairs(arr) do if (result ~= "" and between) then result = result .. between end result = result .. before .. v .. after end return result end function table.indexof(tbl, obj) for k, v in ipairs(tbl) do if v == obj then return k end end end function table.findKeyByValue(tbl, obj) for k, v in pairs(tbl) do if v == obj then return k end end end function table.insertafter(tbl, after, value) local i = table.indexof(tbl, after) if i then table.insert(tbl, i + 1, value) else table.insert(tbl, value) end end function table.insertflat(tbl, values) if values == nil then return elseif type(values) == "table" then for _, value in ipairs(values) do table.insertflat(tbl, value) end else table.insert(tbl, values) end return tbl end function table.insertkeyed(tbl, pos, value) if value == nil then value = pos pos = #tbl + 1 end if tbl[value] ~= nil then return false end table.insert(tbl, pos, value) tbl[value] = value return true end function table.insertsorted(tbl, value, fn) if value == nil then return else fn = fn or function(a, b) return a < b end local minindex = 1 local maxindex = #tbl + 1 while minindex < maxindex do local index = minindex + ((maxindex - minindex) >> 1) local test = tbl[index] if fn(value, test) then maxindex = index else minindex = index + 1 if not fn(test, value) then break end end end table.insert(tbl, minindex, value) end return tbl end function table.isempty(t) return next(t) == nil end function table.join(...) local result = { } local arg = {...} for _,t in ipairs(arg) do if type(t) == "table" then for _,v in ipairs(t) do table.insert(result, v) end else table.insert(result, t) end end return result end function table.keys(tbl) local keys = {} for k, _ in pairs(tbl) do table.insert(keys, k) end return keys end function table.merge(...) local result = {} local arg = {...} for _,t in ipairs(arg) do if type(t) == "table" then for k,v in pairs(t) do if type(result[k]) == "table" and type(v) == "table" then result[k] = table.merge(result[k], v) else result[k] = v end end else error("invalid value") end end return result end function table.replace(self, value, replacement) for i = 1, #self do if self[i] == value then self[i] = replacement end end end function table.translate(arr, translation) if not translation then return {} end local result = {} for i = 1, #arr do local tvalue if type(translation) == "function" then tvalue = translation(arr[i]) else tvalue = translation[arr[i]] end if (tvalue) then table.insert(result, tvalue) end end return result end function table.tostring(tab, recurse, indent) local res = '' if not indent then indent = 0 end local format_value = function(k, v, i) formatting = string.rep("\t", i) if k then if type(k) == "table" then k = '[table]' end formatting = formatting .. k .. ": " end if not v then return formatting .. '(nil)' elseif type(v) == "table" then if recurse and recurse > 0 then return formatting .. '\n' .. table.tostring(v, recurse-1, i+1) else return formatting .. "" end elseif type(v) == "function" then return formatting .. tostring(v) elseif type(v) == "userdata" then return formatting .. "" elseif type(v) == "boolean" then if v then return formatting .. 'true' else return formatting .. 'false' end else return formatting .. v end end if type(tab) == "table" then local first = true local mt = getmetatable(tab) if mt then res = res .. format_value('__mt', mt, indent) first = false end for k, v in pairs(tab) do if not first then res = res .. '\n' end res = res .. format_value(k, v, indent) first = false end else res = res .. format_value(nil, tab, indent) end return res end function table.unique(tab) local elems = { } local result = { } table.foreachi(tab, function(elem) if not elems[elem] then table.insert(result, elem) elems[elem] = true end end) return result end function table.filterempty(dirs) return table.translate(dirs, function(val) if val and #val > 0 then return val else return nil end end) end function table.equals(a, b) for k, v in pairs(a) do if b[k] ~= v then return false end end for k, v in pairs(b) do if a[k] ~= v then return false end end return true end function spairs(t) local keys = {} for k in pairs(t) do table.insert(keys, k) end table.sort(keys) local i = 0 return function() i = i + 1 if keys[i] then return keys[i], t[keys[i]] end end end function table.intersect(a, b) local result = {} for _, v in ipairs(b) do if table.indexof(a, v) then table.insert(result, v) end end return result end function table.difference(a, b) local result = {} for _, v in ipairs(a) do if not table.indexof(b, v) then table.insert(result, v) end end return result end local p = premake p.modules.vstudio = p.modules.vstudio or {} p.modules.vstudio._VERSION = p._VERSION p.vstudio = p.modules.vstudio local vstudio = p.vstudio local project = p.project local config = p.config vstudio.vs200x_architectures = { win32 = "x86", x86 = "x86", x86_64 = "x64", ARM = "ARM", ARM64 = "ARM64", } vstudio.vs2010_architectures = { win32 = "x86", } local function architecture(system, arch) local result if _ACTION >= "vs2010" then result = vstudio.vs2010_architectures[arch] or vstudio.vs2010_architectures[system] end return result or vstudio.vs200x_architectures[arch] or vstudio.vs200x_architectures[system] end vstudio._cultures = { ["af"] = 0x0036, ["af-ZA"] = 0x0436, ["sq"] = 0x001C, ["sq-AL"] = 0x041C, ["ar"] = 0x0001, ["ar-DZ"] = 0x1401, ["ar-BH"] = 0x3C01, ["ar-EG"] = 0x0C01, ["ar-IQ"] = 0x0801, ["ar-JO"] = 0x2C01, ["ar-KW"] = 0x3401, ["ar-LB"] = 0x3001, ["ar-LY"] = 0x1001, ["ar-MA"] = 0x1801, ["ar-OM"] = 0x2001, ["ar-QA"] = 0x4001, ["ar-SA"] = 0x0401, ["ar-SY"] = 0x2801, ["ar-TN"] = 0x1C01, ["ar-AE"] = 0x3801, ["ar-YE"] = 0x2401, ["hy"] = 0x002B, ["hy-AM"] = 0x042B, ["az"] = 0x002C, ["az-Cyrl-AZ"] = 0x082C, ["az-Latn-AZ"] = 0x042C, ["eu"] = 0x002D, ["eu-ES"] = 0x042D, ["be"] = 0x0023, ["be-BY"] = 0x0423, ["bg"] = 0x0002, ["bg-BG"] = 0x0402, ["ca"] = 0x0003, ["ca-ES"] = 0x0403, ["zh-HK"] = 0x0C04, ["zh-MO"] = 0x1404, ["zh-CN"] = 0x0804, ["zh-Hans"] = 0x0004, ["zh-SG"] = 0x1004, ["zh-TW"] = 0x0404, ["zh-Hant"] = 0x7C04, ["hr"] = 0x001A, ["hr-HR"] = 0x041A, ["cs"] = 0x0005, ["cs-CZ"] = 0x0405, ["da"] = 0x0006, ["da-DK"] = 0x0406, ["dv"] = 0x0065, ["dv-MV"] = 0x0465, ["nl"] = 0x0013, ["nl-BE"] = 0x0813, ["nl-NL"] = 0x0413, ["en"] = 0x0009, ["en-AU"] = 0x0C09, ["en-BZ"] = 0x2809, ["en-CA"] = 0x1009, ["en-029"] = 0x2409, ["en-IE"] = 0x1809, ["en-JM"] = 0x2009, ["en-NZ"] = 0x1409, ["en-PH"] = 0x3409, ["en-ZA"] = 0x1C09, ["en-TT"] = 0x2C09, ["en-GB"] = 0x0809, ["en-US"] = 0x0409, ["en-ZW"] = 0x3009, ["et"] = 0x0025, ["et-EE"] = 0x0425, ["fo"] = 0x0038, ["fo-FO"] = 0x0438, ["fa"] = 0x0029, ["fa-IR"] = 0x0429, ["fi"] = 0x000B, ["fi-FI"] = 0x040B, ["fr"] = 0x000C, ["fr-BE"] = 0x080C, ["fr-CA"] = 0x0C0C, ["fr-FR"] = 0x040C, ["fr-LU"] = 0x140C, ["fr-MC"] = 0x180C, ["fr-CH"] = 0x100C, ["gl"] = 0x0056, ["gl-ES"] = 0x0456, ["ka"] = 0x0037, ["ka-GE"] = 0x0437, ["de"] = 0x0007, ["de-AT"] = 0x0C07, ["de-DE"] = 0x0407, ["de-LI"] = 0x1407, ["de-LU"] = 0x1007, ["de-CH"] = 0x0807, ["el"] = 0x0008, ["el-GR"] = 0x0408, ["gu"] = 0x0047, ["gu-IN"] = 0x0447, ["he"] = 0x000D, ["he-IL"] = 0x040D, ["hi"] = 0x0039, ["hi-IN"] = 0x0439, ["hu"] = 0x000E, ["hu-HU"] = 0x040E, ["is"] = 0x000F, ["is-IS"] = 0x040F, ["id"] = 0x0021, ["id-ID"] = 0x0421, ["it"] = 0x0010, ["it-IT"] = 0x0410, ["it-CH"] = 0x0810, ["ja"] = 0x0011, ["ja-JP"] = 0x0411, ["kn"] = 0x004B, ["kn-IN"] = 0x044B, ["kk"] = 0x003F, ["kk-KZ"] = 0x043F, ["kok"] = 0x0057, ["kok-IN"] = 0x0457, ["ko"] = 0x0012, ["ko-KR"] = 0x0412, ["ky"] = 0x0040, ["ky-KG"] = 0x0440, ["lv"] = 0x0026, ["lv-LV"] = 0x0426, ["lt"] = 0x0027, ["lt-LT"] = 0x0427, ["mk"] = 0x002F, ["mk-MK"] = 0x042F, ["ms"] = 0x003E, ["ms-BN"] = 0x083E, ["ms-MY"] = 0x043E, ["mr"] = 0x004E, ["mr-IN"] = 0x044E, ["mn"] = 0x0050, ["mn-MN"] = 0x0450, ["no"] = 0x0014, ["nb-NO"] = 0x0414, ["nn-NO"] = 0x0814, ["pl"] = 0x0015, ["pl-PL"] = 0x0415, ["pt"] = 0x0016, ["pt-BR"] = 0x0416, ["pt-PT"] = 0x0816, ["pa"] = 0x0046, ["pa-IN"] = 0x0446, ["ro"] = 0x0018, ["ro-RO"] = 0x0418, ["ru"] = 0x0019, ["ru-RU"] = 0x0419, ["sa"] = 0x004F, ["sa-IN"] = 0x044F, ["sr-Cyrl-CS"] = 0x0C1A, ["sr-Latn-CS"] = 0x081A, ["sk"] = 0x001B, ["sk-SK"] = 0x041B, ["sl"] = 0x0024, ["sl-SI"] = 0x0424, ["es"] = 0x000A, ["es-AR"] = 0x2C0A, ["es-BO"] = 0x400A, ["es-CL"] = 0x340A, ["es-CO"] = 0x240A, ["es-CR"] = 0x140A, ["es-DO"] = 0x1C0A, ["es-EC"] = 0x300A, ["es-SV"] = 0x440A, ["es-GT"] = 0x100A, ["es-HN"] = 0x480A, ["es-MX"] = 0x080A, ["es-NI"] = 0x4C0A, ["es-PA"] = 0x180A, ["es-PY"] = 0x3C0A, ["es-PE"] = 0x280A, ["es-PR"] = 0x500A, ["es-ES"] = 0x0C0A, ["es-ES_tradnl"]= 0x040A, ["es-UY"] = 0x380A, ["es-VE"] = 0x200A, ["sw"] = 0x0041, ["sw-KE"] = 0x0441, ["sv"] = 0x001D, ["sv-FI"] = 0x081D, ["sv-SE"] = 0x041D, ["syr"] = 0x005A, ["syr-SY"] = 0x045A, ["ta"] = 0x0049, ["ta-IN"] = 0x0449, ["tt"] = 0x0044, ["tt-RU"] = 0x0444, ["te"] = 0x004A, ["te-IN"] = 0x044A, ["th"] = 0x001E, ["th-TH"] = 0x041E, ["tr"] = 0x001F, ["tr-TR"] = 0x041F, ["uk"] = 0x0022, ["uk-UA"] = 0x0422, ["ur"] = 0x0020, ["ur-PK"] = 0x0420, ["uz"] = 0x0043, ["uz-Cyrl-UZ"] = 0x0843, ["uz-Latn-UZ"] = 0x0443, ["vi"] = 0x002A, ["vi-VN"] = 0x042A, } function vstudio.archFromConfig(cfg, win32) local isnative = project.isnative(cfg.project) local arch = architecture(cfg.system, cfg.architecture) if not arch then arch = iif(isnative, "x86", "Any CPU") end if win32 and isnative and arch == "x86" then arch = "Win32" end return arch end function vstudio.archFromPlatform(platform) local system = p.api.checkValue(p.fields.system, platform) local arch = p.api.checkValue(p.fields.architecture, platform) return architecture(system, arch or platform:lower()) end function vstudio.cultureForLocale(locale) if locale then local culture = vstudio._cultures[locale] if not culture then p.warnOnce("Locale" .. locale, 'Unsupported locale "%s"', locale) end return culture end end function vstudio.getLinks(cfg, explicit) return p.tools.msc.getlinks(cfg, not explicit) end function vstudio.isMakefile(cfg) return (cfg.kind == p.MAKEFILE or cfg.kind == p.NONE) end function vstudio.needsExplicitLink(cfg) if not cfg._needsExplicitLink then local ex = cfg.flags.NoImplicitLink if not ex then local prjdeps = project.getdependencies(cfg.project, "linkOnly") local cfgdeps = config.getlinks(cfg, "dependencies", "object") ex = #prjdeps ~= #cfgdeps end cfg._needsExplicitLink = ex end return cfg._needsExplicitLink end function vstudio.path(cfg, value) cfg = cfg.project or cfg local dirs = path.translate(project.getrelative(cfg, value)) if type(dirs) == 'table' then dirs = table.filterempty(dirs) end return dirs end function vstudio.projectConfig(cfg, arch) local platform = vstudio.projectPlatform(cfg) local architecture = arch or vstudio.archFromConfig(cfg, true) return platform .. "|" .. architecture end function vstudio.projectElement() p.push('') end function vstudio.projectfile(prj) local extension if project.iscsharp(prj) then extension = ".csproj" elseif project.isfsharp(prj) then extension = ".fsproj" elseif project.isc(prj) or project.iscpp(prj) then extension = iif(_ACTION > "vs2008", ".vcxproj", ".vcproj") end return p.filename(prj, extension) end function vstudio.projectPlatform(cfg) local platform = cfg.platform if platform then local pltarch = vstudio.archFromPlatform(cfg.platform) or platform local cfgarch = vstudio.archFromConfig(cfg) if pltarch == cfgarch then platform = nil end end if platform then return cfg.buildcfg .. " " .. platform else return cfg.buildcfg end end function vstudio.solutionPlatform(cfg) local platform = cfg.platform local platarch if platform then platform = vstudio.archFromPlatform(platform) or platform if platform ~= "x86" then return platform end end local hasnative = false local hasnet = false local slnarch for prj in p.workspace.eachproject(cfg.workspace) do hasnative = hasnative or project.isnative(prj) hasnet = hasnet or project.isdotnet(prj) local prjcfg = project.getconfig(prj, cfg.buildcfg, cfg.platform) if prjcfg then local prjarch = vstudio.archFromConfig(prjcfg) if not slnarch then slnarch = prjarch elseif slnarch ~= prjarch then slnarch = "Mixed Platforms" end end end if platform then return iif(hasnet, "x86", "Win32") elseif slnarch then return iif(slnarch == "x86" and not hasnet, "Win32", slnarch) elseif hasnet and hasnative then return "Mixed Platforms" elseif hasnet then return "Any CPU" else return "Win32" end end function vstudio.solutionarch(cfg) local hasnative = false local hasdotnet = false local arch = cfg.platform for prj in p.workspace.eachproject(cfg.workspace) do hasnative = hasnative or project.isnative(prj) hasnet = hasnet or project.isdotnet(prj) if hasnative and hasdotnet then return "Mixed Platforms" end if not arch then local prjcfg = project.getconfig(prj, cfg.buildcfg, cfg.platform) if prjcfg then if prjcfg.architecture then arch = vstudio.archFromConfig(prjcfg) end end end end arch = arch or iif(hasnative, "Win32", "Any CPU") return arch end function vstudio.solutionconfig(cfg) local platform = cfg.platform if not platform then platform = vstudio.solutionarch(cfg) end return string.format("%s|%s", cfg.buildcfg, platform) end function vstudio.tool(prj) if project.iscsharp(prj) then return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC" elseif project.isfsharp(prj) then return "F2A71F9B-5D33-465A-A702-920D77279786" elseif project.isc(prj) or project.iscpp(prj) then return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" end end include("vs200x_vcproj.lua") include("vs200x_vcproj_user.lua") include("vs2005_solution.lua") include("vs2005_dotnetbase.lua") include("vs2005_csproj.lua") include("vs2005_csproj_user.lua") include("vs2005_fsproj.lua") include("vs2005_fsproj_user.lua") include("vs2010_nuget.lua") include("vs2010_vcxproj.lua") include("vs2010_vcxproj_user.lua") include("vs2010_vcxproj_filters.lua") include("vs2010_rules_props.lua") include("vs2010_rules_targets.lua") include("vs2010_rules_xml.lua") return p.modules.vstudio ESAES@AESAESAESAFSISISJSJSJSJSlocal p = premake p.container = {} local container = p.container container.classes = {} function container.newClass(name, parent, extraScopes) local class = p.configset.new(parent) class.name = name class.pluralName = name:plural() class.containedClasses = {} class.extraScopes = extraScopes if parent then table.insert(parent.containedClasses, class) end container.classes[name] = class return class end function container.new(class, name) local self = p.configset.new() setmetatable(self, p.configset.metatable(self)) self.class = class self.name = name self.filename = name self.script = _SCRIPT self.basedir = os.getcwd() self.external = false for childClass in container.eachChildClass(class) do self[childClass.pluralName] = {} end return self end function container.addChild(self, child) local children = self[child.class.pluralName] table.insert(children, child) children[child.name] = child child.parent = self child[self.class.name] = self if self.class.alias then child[self.class.alias] = self end end function container.bake(self) if self._isBaked then return self end self._isBaked = true local ctx = p.context.new(self) for key, value in pairs(self) do ctx[key] = value end local parent = self.parent if parent then ctx[parent.class.name] = parent end for class in container.eachChildClass(self.class) do for child in container.eachChild(self, class) do child.parent = ctx child[self.class.name] = ctx end end if type(self.class.bake) == "function" then self.class.bake(ctx) end return ctx end function container.bakeChildren(self) for class in container.eachChildClass(self.class) do local children = self[class.pluralName] for i = 1, #children do local ctx = container.bake(children[i]) children[i] = ctx children[ctx.name] = ctx end end end function container.classCanContain(class, scope) if type(scope) == "table" then for i = 1, #scope do if container.classCanContain(class, scope[i]) then return true end end return false end for child in container.eachChildClass(class) do if (container.classCanContain(child, scope)) then return true end end if class.name == scope or class.alias == scope then return true end if class.extraScopes and table.contains(class.extraScopes, scope) then return true end return false end function container.classIsA(class, scope) while class do if class.name == scope or class.alias == scope then return true end class = class.parent end return false end function container.eachChildClass(class) local children = class.containedClasses local i = 0 return function () i = i + 1 if i <= #children then return children[i] end end end function container.eachChild(self, class) local children = self[class.pluralName] local i = 0 return function () i = i + 1 if i <= #children then return children[i] end end end function container.getChild(self, class, name) local children = self[class.pluralName] return children[name] end function container.getClass(name) return container.classes[name] end function container.hasChild(self, class, func) for child in container.eachChild(self, class) do if func(child) then return true end end end function container.validate(self) if type(self.class.validate) == "function" then self.class.validate(self) end end function container.validateChildren(self) for class in container.eachChildClass(self.class) do local children = self[class.pluralName] for i = 1, #children do container.validate(children[i]) end end end local p = premake p.oven = {} local oven = p.oven local context = p.context p.oven.bubbledFields = { configmap = true, vpaths = true } function oven.bake() local root = p.api.rootContainer() root._isBaked = false; p.container.bake(root) end function oven.bakeWorkspace(wks) return p.container.bake(wks) end p.alias(oven, "bakeWorkspace", "bakeSolution") local function addCommonContextFilters(self) context.addFilter(self, "_ACTION", _ACTION) context.addFilter(self, "action", _ACTION) self.system = self.system or os.target() context.addFilter(self, "system", os.getSystemTags(self.system)) context.addFilter(self, "host", os.getSystemTags(os.host())) local options = {} for key, value in pairs(_OPTIONS) do local term = key if value ~= "" then term = term .. "=" .. tostring(value) end table.insert(options, term) end context.addFilter(self, "_OPTIONS", options) context.addFilter(self, "options", options) end function p.workspace.bake(self) addCommonContextFilters(self) self.environ = { wks = self, sln = self, } context.compile(self) self.location = self.location or self.basedir context.basedir(self, self.location) self.configs = oven.bakeConfigs(self) p.container.bakeChildren(self) oven.bakeObjDirs(self) oven.addGeneratedFiles(self) end function oven.addGeneratedFiles(wks) local function addGeneratedFile(cfg, source, filename) cfg.project.hasGeneratedFiles = true local files = cfg.project._.files local node = files[filename] if not node then node = p.fileconfig.new(filename, cfg.project) files[filename] = node table.insert(files, node) end node.dependsOn = source node.generated = true if not p.fileconfig.getconfig(node, cfg) then p.fileconfig.addconfig(node, cfg) end end local function addFile(cfg, node) local filecfg = p.fileconfig.getconfig(node, cfg) if not filecfg or filecfg.flags.ExcludeFromBuild or not filecfg.compilebuildoutputs then return end if p.fileconfig.hasCustomBuildRule(filecfg) then local buildoutputs = filecfg.buildoutputs if buildoutputs and #buildoutputs > 0 then for _, output in ipairs(buildoutputs) do if not path.islinkable(output) then addGeneratedFile(cfg, node, output) end end end end end for prj in p.workspace.eachproject(wks) do local files = table.shallowcopy(prj._.files) for cfg in p.project.eachconfig(prj) do table.foreachi(files, function(node) addFile(cfg, node) end) end if prj.hasGeneratedFiles and p.project.isnative(prj) then oven.assignObjectSequences(prj) end end end function p.project.bake(self) verbosef(' Baking %s...', self.name) self.solution = self.workspace self.global = self.workspace.global local wks = self.workspace context.copyFilters(self, wks) self.system = self.system or os.target() context.addFilter(self, "system", os.getSystemTags(self.system)) context.addFilter(self, "host", os.getSystemTags(os.host())) context.addFilter(self, "architecture", self.architecture) context.addFilter(self, "tags", self.tags) context.addFilter(self, "kind", self.kind) self.project = self self.environ = { wks = wks, sln = wks, prj = self, } context.compile(self) p.container.bakeChildren(self) self.location = self.location or self.basedir context.basedir(self, self.location) local cfgs = table.fold(self.configurations or {}, self.platforms or {}) oven.bubbleFields(self, self, cfgs) self._cfglist = oven.bakeConfigList(self, cfgs) local projectSystem = self.system self.system = nil self.configs = {} for _, pairing in ipairs(self._cfglist) do local buildcfg = pairing[1] local platform = pairing[2] local cfg = oven.bakeConfig(wks, self, buildcfg, platform) if p.action.supportsconfig(p.action.current(), cfg) then self.configs[(buildcfg or "*") .. (platform or "")] = cfg end end self._ = {} self._.files = oven.bakeFiles(self) if p.project.isnative(self) then oven.assignObjectSequences(self) end self.system = projectSystem end function p.rule.bake(self) addCommonContextFilters(self) self.environ = { rule = self, } context.compile(self) table.sort(self.propertydefinition, function (a, b) return a.name < b.name end) self.location = self.location or self.basedir context.basedir(self, self.location) end function oven.bakeObjDirs(wks) local function getobjdirs(cfg) local objdir = cfg.objdir or "obj" local i = objdir:find("!", 1, true) if i then cfg.objdir = objdir:sub(1, i - 1) .. objdir:sub(i + 1) return nil end local dirs = {} local dir = path.getabsolute(path.join(cfg.project.location, objdir)) table.insert(dirs, dir) if cfg.platform then dir = path.join(dir, cfg.platform) table.insert(dirs, dir) end dir = path.join(dir, cfg.buildcfg) table.insert(dirs, dir) dir = path.join(dir, cfg.project.name) table.insert(dirs, dir) return dirs end local counts = {} local configs = {} for prj in p.workspace.eachproject(wks) do for cfg in p.project.eachconfig(prj) do local dirs = getobjdirs(cfg) if dirs then configs[cfg] = dirs for _, dir in ipairs(dirs or {}) do counts[dir] = (counts[dir] or 0) + 1 end end end end for cfg, dirs in pairs(configs) do for _, dir in ipairs(dirs) do if counts[dir] == 1 then cfg.objdir = dir break end end end end function oven.bakeConfigs(wks) local buildcfgs = wks.configurations or {} local platforms = wks.platforms or {} local configs = {} local pairings = table.fold(buildcfgs, platforms) for _, pairing in ipairs(pairings) do local cfg = oven.bakeConfig(wks, nil, pairing[1], pairing[2]) if p.action.supportsconfig(p.action.current(), cfg) then table.insert(configs, cfg) end end return configs end function oven.bubbleFields(ctx, cset, cfgs) local configurations = {} local platforms = {} for _, cfg in ipairs(cfgs) do if cfg[1] then table.insert(configurations, cfg[1]:lower()) end if cfg[2] then table.insert(platforms, cfg[2]:lower()) end end local terms = table.deepcopy(ctx.terms) terms.configurations = configurations terms.platforms = platforms for key in pairs(oven.bubbledFields) do local field = p.field.get(key) if not field then ctx[key] = rawget(ctx, key) else local value = p.configset.fetch(cset, field, terms, ctx) if value then ctx[key] = value end end end end function oven.bakeConfigList(ctx, cfgs) for i, cfg in ipairs(cfgs) do cfgs[i] = p.project.mapconfig(ctx, cfg[1], cfg[2]) end local buildcfgs = {} local platforms = {} for _, pairing in ipairs(cfgs) do local buildcfg = pairing[1] local platform = pairing[2] if not table.contains(buildcfgs, buildcfg) then table.insert(buildcfgs, buildcfg) end if platform and not table.contains(platforms, platform) then table.insert(platforms, platform) end end return table.fold(buildcfgs, platforms) end function oven.bakeConfig(wks, prj, buildcfg, platform, extraFilters) local system = os.target() local architecture = nil local toolset = p.action.current().toolset if platform then system = p.api.checkValue(p.fields.system, platform) or system architecture = p.api.checkValue(p.fields.architecture, platform) or architecture toolset = p.api.checkValue(p.fields.toolset, platform) or toolset end local environ = { wks = wks, sln = wks, prj = prj, } local ctx = context.new(prj or wks, environ) ctx.project = prj ctx.workspace = wks ctx.solution = wks ctx.global = wks.global ctx.buildcfg = buildcfg ctx.platform = platform ctx.action = _ACTION environ.cfg = ctx context.copyFilters(ctx, wks) context.addFilter(ctx, "configurations", buildcfg) context.addFilter(ctx, "platforms", platform) if prj then context.addFilter(ctx, "language", prj.language) end ctx.system = ctx.system or system context.addFilter(ctx, "system", os.getSystemTags(ctx.system)) context.addFilter(ctx, "host", os.getSystemTags(os.host())) ctx.architecture = ctx.architecture or architecture context.addFilter(ctx, "architecture", ctx.architecture) ctx.toolset = _OPTIONS.cc or ctx.toolset or toolset context.addFilter(ctx, "toolset", ctx.toolset) context.addFilter(ctx, "kind", ctx.kind) context.addFilter(ctx, "sharedlibtype", ctx.sharedlibtype) context.addFilter(ctx, "tags", ctx.tags) if extraFilters then for k, v in pairs(extraFilters) do context.addFilter(ctx, k, v) end end context.compile(ctx) ctx.location = ctx.location or prj and prj.location context.basedir(ctx, ctx.location) oven.finishConfig(ctx) return ctx end function oven.bakeFiles(prj) local files = {} for cfg in p.project.eachconfig(prj) do local function addFile(fname, i) local fcfg = files[fname] if not fcfg then fcfg = p.fileconfig.new(fname, prj) fcfg.order = i files[fname] = fcfg table.insert(files, fcfg) end p.fileconfig.addconfig(fcfg, cfg) end table.foreachi(cfg.files, addFile) if #prj.nuget > 0 and (_ACTION < "vs2017" or p.project.iscpp(prj)) then addFile("packages.config") end end table.sort(files, function(a,b) return a.vpath < b.vpath end) return files end function oven.uniqueSequence(f, cfg, seq, bases) while true do f.sequence = seq[cfg] or 0 seq[cfg] = f.sequence + 1 if seq[cfg] == 1 then break end if not bases[f.objname] then bases[f.objname] = {} end if not bases[f.objname][cfg] then bases[f.objname][cfg] = 1 break end end end function oven.assignObjectSequences(prj) local bases = {} table.foreachi(prj._.files, function(file) if not path.isnativefile(file.abspath) then return end if not bases[file.basename] then bases[file.basename] = {} end local sequences = bases[file.basename] for cfg in p.project.eachconfig(prj) do local fcfg = p.fileconfig.getconfig(file, cfg) if fcfg ~= nil and not fcfg.flags.ExcludeFromBuild then oven.uniqueSequence(fcfg, cfg, sequences, bases) end end oven.uniqueSequence(file, prj, sequences, bases) end) end function oven.finishConfig(cfg) cfg.longname = table.concat({ cfg.buildcfg, cfg.platform }, "|") cfg.shortname = table.concat({ cfg.buildcfg, cfg.platform }, " ") cfg.shortname = cfg.shortname:gsub(" ", "_"):lower() cfg.name = cfg.longname if cfg.project and cfg.kind then cfg.buildtarget = p.config.gettargetinfo(cfg) cfg.buildtarget.relpath = p.project.getrelative(cfg.project, cfg.buildtarget.abspath) cfg.linktarget = p.config.getlinkinfo(cfg) cfg.linktarget.relpath = p.project.getrelative(cfg.project, cfg.linktarget.abspath) end end 0 then local color = table.remove(term._colorStack) term.setTextColor(color) end end local p = premake p.criteria = criteria -- criteria namespace is defined in C host local criteria = p.criteria criteria._validPrefixes = { _action = true, action = true, architecture = true, configurations = true, files = true, kind = true, language = true, _options = true, options = true, platforms = true, sharedlibtype = true, system = true, toolset = true, tags = true, host = true, } function criteria.flatten(terms) local result = {} local function flatten(terms) for key, value in pairs(terms) do if type(key) == "number" then if type(value) == "table" then flatten(value) elseif value then table.insert(result, value) end elseif type(key) == "string" then local word = key .. ":" if type(value) == "table" then local values = table.flatten(value) word = word .. table.concat(values, " or ") else word = word .. value end table.insert(result, word) else error("Unknown key type in terms.") end end end flatten(terms) return result end function criteria.new(terms, unprefixed) terms = criteria.flatten(terms) local patterns = {} for i, term in ipairs(terms) do term = term:lower() local pattern = {} local prefix = iif(unprefixed, nil, "configurations") local words = term:explode(" or ") for _, word in ipairs(words) do word, prefix = criteria._word(word, prefix) if prefix and not criteria._validPrefixes[prefix] then return nil, string.format("Invalid field prefix '%s'", prefix) end if prefix then local fld = p.field.get(prefix) if fld and fld.aliases then word[1] = fld.aliases[word[1]] or word[1] end end table.insert(pattern, word) end table.insert(patterns, pattern) end local crit = {} crit.patterns = patterns crit.data = criteria._compile(patterns) crit.terms = terms return crit end function criteria._word(word, prefix) local wildcard local assertion = true while (true) do if word:startswith("not ") then assertion = not assertion word = word:sub(5) else local i = word:find(":", 1, true) if prefix and i then prefix = word:sub(1, i - 1) word = word:sub(i + 1) else wildcard = (word:find("*", 1, true) ~= nil) if wildcard then word = path.wildcards(word) end break end end end return { word, prefix, assertion, wildcard }, prefix end function criteria.allowPrefix(prefix) criteria._validPrefixes[prefix:lower()] = true end local p = premake local m = p.vstudio.fs2005 local dn = p.vstudio.dotnetbase m.elements.userProjectPropertyGroup = function() return { m.referencePath, } end m.elements.userConfigPropertyGroup = function() return { m.localDebuggerCommandArguments, } end function m.generateUser(prj) local prjGroup = p.capture(function() p.push(2) p.callArray(m.elements.userProjectPropertyGroup, prj) p.pop(2) end) local contents = {} local size = 0 for cfg in p.project.eachconfig(prj) do contents[cfg] = p.capture(function() p.push(2) p.callArray(m.elements.userConfigPropertyGroup, cfg) p.pop(2) end) size = size + #contents[cfg] end if #prjGroup > 0 or size > 0 then p.vstudio.projectElement() if #prjGroup > 0 then p.push('') p.outln(prjGroup) p.pop('') end for cfg in p.project.eachconfig(prj) do if #contents[cfg] > 0 then p.push('', dn.condition(cfg)) p.outln(contents[cfg]) p.pop('') end end p.pop('') end end function m.referencePath(prj) local cfg = p.project.getfirstconfig(prj) local paths = p.vstudio.path(prj, cfg.libdirs) if #paths > 0 then p.w('%s', table.concat(paths, ";")) end end function m.localDebuggerCommandArguments(cfg) if #cfg.debugargs > 0 then p.x('%s', table.concat(cfg.debugargs, " ")) end end local p = premake local vstudio = p.vstudio newaction { trigger = "vs2012", shortname = "Visual Studio 2012", description = "Generate Visual Studio 2012 project files", targetos = "windows", toolset = "msc-v110", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = function(wks) vstudio.vs2005.generateSolution(wks) end, onProject = function(prj) vstudio.vs2010.generateProject(prj) end, onRule = function(rule) vstudio.vs2010.generateRule(rule) end, onCleanWorkspace = function(wks) vstudio.cleanSolution(wks) end, onCleanProject = function(prj) vstudio.cleanProject(prj) end, onCleanTarget = function(prj) vstudio.cleanTarget(prj) end, pathVars = vstudio.vs2010.pathVars, vstudio = { solutionVersion = "12", versionName = "2012", targetFramework = "4.5", toolsVersion = "4.0", } } @local p = premake p.tools.snc = {} local snc = p.tools.snc local gcc = p.tools.gcc snc.shared = { flags = { FatalCompileWarnings = "-Xquit=2", }, optimize = { Off = "-O0", On = "-O1", Debug = "-Od", Full = "-O3", Size = "-Os", Speed = "-O2", }, warnings = { Extra = "-Xdiag=2", } } snc.cflags = { } function snc.getcflags(cfg) local shared = p.config.mapFlags(cfg, snc.shared) local cflags = p.config.mapFlags(cfg, snc.cflags) local flags = table.join(shared, cflags, snc.getwarnings(cfg)) return flags end snc.cxxflags = { exceptionhandling = { Default = "-Xc+=exceptions", On = "-Xc+=exceptions", SEH = "-Xc-=exceptions", }, rtti = { Default = "-Xc+=rtti", On = "-Xc+=rtti", SEH = "-Xc-=rtti", } } function snc.getcxxflags(cfg) local shared = config.mapFlags(cfg, snc.shared) local cxxflags = config.mapFlags(cfg, snc.cxxflags) local flags = table.join(shared, cxxflags, snc.getwarnings(cfg)) return flags end function snc.getforceincludes(cfg) local flags = gcc.getforceincludes(cfg) return flags end function snc.getldflags(cfg) local flags = { } if not (cfg.symbols == p.ON) then table.insert(flags, "-s") end return flags end snc.getcppflags = gcc.getcppflags snc.getdefines = gcc.getdefines snc.getincludedirs = gcc.getincludedirs snc.getrunpathdirs = gcc.getrunpathdirs snc.getLibraryDirectories = gcc.getLibraryDirectories snc.getlinks = gcc.getlinks function snc.getmakesettings(cfg) return nil end snc.tools = { } function snc.gettoolname(cfg, tool) local names = snc.tools[cfg.architecture] or snc.tools[cfg.system] or {} return names[tool] end local p = premake p.tools = {} function p.tools.normalize(identifier) if identifier:startswith("v") then -- TODO: this should be deprecated? identifier = 'msc-' .. identifier end local parts = identifier:explode("-", true, 1) if parts[2] == nil then return parts[1] end if parts[1] == "msc" and tonumber(parts[2]:sub(1,3)) ~= nil then parts[2] = "v" .. parts[2] end if parts[2]:startswith("llvm-vs") then parts[2] = "LLVM-" .. parts[2]:sub(6) end return parts[1] .. '-' .. parts[2] end function p.tools.canonical(identifier) identifier = p.tools.normalize(identifier) local parts = identifier:explode("-", true, 1) return p.tools[parts[1]], parts[2] end function path.appendExtension(p, ext) if not ext or ext == "" then return p end local endquote if p:endswith('"') then p = p:sub(1, -2) endquote = '"' end if not path.hasextension(p, ext) then p = p .. ext end if endquote then p = p .. endquote end return p end path.appendextension = path.appendExtension function path.getbasename(p) local name = path.getname(p) local i = name:findlast(".", true) if (i) then return name:sub(1, i - 1) else return name end end function path.getdirectory(p) local i = p:findlast("/", true) if (i) then if i > 1 then i = i - 1 end return p:sub(1, i) else return "." end end function path.getdrive(p) local ch1 = p:sub(1,1) local ch2 = p:sub(2,2) if ch2 == ":" then return ch1 end end function path.getextension(p) p = path.getname(p) local i = p:findlast(".", true) if (i) then return p:sub(i) else return "" end end function path.removeextension(p) local i = p:findlast(".", true) if (i) then if i > 1 then i = i - 1 end return p:sub(1, i) else return "" end end function path.getname(p) local i = p:findlast("[/\\]") if (i) then return p:sub(i + 1) else return p end end function path.hasextension(fname, extensions) local fext = path.getextension(fname):lower() if type(extensions) == "table" then for _, extension in pairs(extensions) do if fext == extension then return true end end return false else return (fext == extensions) end end function path.isasmfile(fname) return path.hasextension(fname, { ".s" }) end function path.iscfile(fname) return path.hasextension(fname, { ".c" }) or path.isasmfile(fname)-- is this really right? or path.isobjcfile(fname)-- there is code that depends on this behaviour, which would need to change end function path.iscppfile(fname) return path.hasextension(fname, { ".cc", ".cpp", ".cxx" }) or path.isobjcppfile(fname)-- is this really right? or path.iscfile(fname) end function path.isobjcfile(fname) return path.hasextension(fname, { ".m" }) end function path.isobjcppfile(fname) return path.hasextension(fname, { ".mm" }) end function path.iscppheader(fname) return path.hasextension(fname, { ".h", ".hh", ".hpp", ".hxx" }) end function path.isnativefile(fname) return path.iscfile(fname) or path.iscppfile(fname) or path.isasmfile(fname) or path.isobjcfile(fname) or path.isobjcppfile(fname) end function path.isframework(fname) return path.hasextension(fname, ".framework") end function path.islinkable(fname) return path.hasextension(fname, { ".o", ".obj", ".a", ".lib", ".so" }) end function path.isobjectfile(fname) return path.hasextension(fname, { ".o", ".obj" }) end function path.isresourcefile(fname) return path.hasextension(fname, ".rc") end function path.isidlfile(fname) return path.hasextension(fname, ".idl") end function path.ishlslfile(fname) return path.hasextension(fname, ".hlsl") end function path.rebase(p, oldbase, newbase) p = path.getabsolute(path.join(oldbase, p)) p = path.getrelative(newbase, p) return p end function path.replaceextension(p, newext) local ext = path.getextension(p) if not ext then return p end if #newext > 0 and not newext:findlast(".", true) then newext = "."..newext end return p:match("^(.*)"..ext.."$")..newext end function path.getDefaultSeparator() if os.istarget('windows') then return '\\' else return '/' end end dQShQS?Slocal p = premake p.modules.vsandroid = { } local android = p.modules.android local vsandroid = p.modules.vsandroid local vc2010 = p.vstudio.vc2010 local vstudio = p.vstudio local project = p.project local config = p.config local function setBoolOption(optionName, flag, value) if flag ~= nil then vc2010.element(optionName, nil, value) end end if vstudio.vs2010_architectures ~= nil then if _ACTION >= "vs2015" then vstudio.vs2010_architectures.arm = "ARM" else vstudio.vs2010_architectures.android = "Android" end end premake.override(vc2010.elements, "globals", function (oldfn, prj) local elements = oldfn(prj) if prj.system == premake.ANDROID and prj.kind ~= premake.PACKAGING then local pos = table.indexof(elements, vc2010.ignoreWarnDuplicateFilename) table.remove(elements, pos) elements = table.join(elements, { android.androidApplicationType }) end return elements end) premake.override(vc2010.elements, "globalsCondition", function (oldfn, prj, cfg) local elements = oldfn(prj, cfg) if cfg.system == premake.ANDROID and cfg.system ~= prj.system and cfg.kind ~= premake.PACKAGING then elements = table.join(elements, { android.androidApplicationType }) end return elements end) function android.androidApplicationType(cfg) vc2010.element("Keyword", nil, "Android") vc2010.element("RootNamespace", nil, "%s", cfg.project.name) vc2010.element("MinimumVisualStudioVersion", nil, "15.0") -- Use 14.0 for VS2015? vc2010.element("ApplicationType", nil, "Android") if _ACTION >= "vs2017" then vc2010.element("ApplicationTypeRevision", nil, "3.0") elseif _ACTION >= "vs2015" then vc2010.element("ApplicationTypeRevision", nil, "2.0") else vc2010.element("ApplicationTypeRevision", nil, "1.0") end end premake.override(vc2010.elements, "configurationProperties", function(oldfn, cfg) local elements = oldfn(cfg) if cfg.kind ~= p.UTILITY and cfg.kind ~= p.PACKAGING and cfg.system == premake.ANDROID then table.remove(elements, table.indexof(elements, vc2010.characterSet)) table.remove(elements, table.indexof(elements, vc2010.wholeProgramOptimization)) table.remove(elements, table.indexof(elements, vc2010.windowsSDKDesktopARMSupport)) elements = table.join(elements, { android.androidAPILevel, android.androidStlType, }) if _ACTION >= "vs2015" then elements = table.join(elements, { android.thumbMode, }) end end return elements end) function android.androidAPILevel(cfg) if cfg.androidapilevel ~= nil then vc2010.element("AndroidAPILevel", nil, "android-" .. cfg.androidapilevel) end end function android.androidStlType(cfg) if cfg.stl ~= nil then local stlType = { ["none"] = "system", ["gabi++"] = "gabi++", ["stlport"] = "stlport", ["gnustl"] = "gnustl", ["libc++"] = "c++", } local postfix = iif(cfg.staticruntime == "On", "_static", "_shared") local runtimeLib = iif(cfg.stl == "none", "system", stlType[cfg.stl] .. postfix) if _ACTION >= "vs2015" then vc2010.element("UseOfStl", nil, runtimeLib) else vc2010.element("AndroidStlType", nil, runtimeLib) end end end function android.thumbMode(cfg) if cfg.thumbmode ~= nil then local thumbMode = { thumb = "Thumb", arm = "ARM", disabled = "Disabled", } vc2010.element("ThumbMode", nil, thumbMode[cfg.thumbmode]) end end premake.override(vc2010, "platformToolset", function(oldfn, cfg) if cfg.system ~= premake.ANDROID then return oldfn(cfg) end if _ACTION >= "vs2015" then local gcc_map = { ["4.6"] = "GCC_4_6", ["4.8"] = "GCC_4_8", ["4.9"] = "GCC_4_9", } local clang_map = { ["3.4"] = "Clang_3_4", ["3.5"] = "Clang_3_5", ["3.6"] = "Clang_3_6", ["3.8"] = "Clang_3_8", ["5.0"] = "Clang_5_0", } if cfg.toolchainversion ~= nil then local map = iif(cfg.toolset == "gcc", gcc_map, clang_map) local ts = map[cfg.toolchainversion] if ts == nil then p.error('Invalid toolchainversion for the selected toolset (%s).', cfg.toolset or "clang") end vc2010.element("PlatformToolset", nil, ts) end else local archMap = { arm = "armv5te", -- should arm5 be default? vs-android thinks so... arm5 = "armv5te", arm7 = "armv7-a", mips = "mips", x86 = "x86", } local arch = cfg.architecture or "arm" if (cfg.architecture ~= nil or cfg.toolchainversion ~= nil) and archMap[arch] ~= nil then local defaultToolsetMap = { arm = "arm-linux-androideabi-", armv5 = "arm-linux-androideabi-", armv7 = "arm-linux-androideabi-", aarch64 = "aarch64-linux-android-", mips = "mipsel-linux-android-", mips64 = "mips64el-linux-android-", x86 = "x86-", x86_64 = "x86_64-", } local toolset = defaultToolsetMap[arch] if cfg.toolset == "clang" then error("The clang toolset is not yet supported by vs-android", 2) toolset = toolset .. "clang" elseif cfg.toolset and cfg.toolset ~= "gcc" then error("Toolset not supported by the android NDK: " .. cfg.toolset, 2) end local version = cfg.toolchainversion or iif(cfg.toolset == "clang", "3.5", "4.9") vc2010.element("PlatformToolset", nil, toolset .. version) vc2010.element("AndroidArch", nil, archMap[arch]) end end end) premake.override(vc2010.elements, "clCompile", function(oldfn, cfg) local elements = oldfn(cfg) if cfg.system == premake.ANDROID then elements = table.join(elements, { android.debugInformation, android.strictAliasing, android.fpu, android.pic, android.shortEnums, android.cStandard, android.cppStandard, }) if _ACTION >= "vs2015" then table.remove(elements, table.indexof(elements, vc2010.debugInformationFormat)) table.remove(elements, table.indexof(elements, vc2010.languageStandard)) table.remove(elements, table.indexof(elements, vc2010.multiProcessorCompilation)) table.remove(elements, table.indexof(elements, vc2010.minimalRebuild)) table.replace(elements, vc2010.enableEnhancedInstructionSet, android.enableEnhancedInstructionSet) table.replace(elements, vc2010.precompiledHeaderFile, android.precompiledHeaderFile) end end return elements end) function android.precompiledHeaderFile(fileName, cfg) vc2010.element("PrecompiledHeaderFile", nil, "%s", path.getabsolute(path.rebase(fileName, cfg.basedir, cfg.location))) end function android.debugInformation(cfg) if cfg.flags.Symbols then _p(3,'true') end end function android.strictAliasing(cfg) if cfg.strictaliasing ~= nil then vc2010.element("StrictAliasing", nil, iif(cfg.strictaliasing == "Off", "false", "true")) end end function android.fpu(cfg) if cfg.fpu ~= nil then _p(3,'true', iif(cfg.fpu == "Software", "true", "false")) end end function android.pic(cfg) if cfg.pic ~= nil then vc2010.element("PositionIndependentCode", nil, iif(cfg.pic == "On", "true", "false")) end end function android.verboseCompiler(cfg) setBoolOption("Verbose", cfg.flags.VerboseCompiler, "true") end function android.undefineAllPreprocessorDefinitions(cfg) setBoolOption("UndefineAllPreprocessorDefinitions", cfg.flags.UndefineAllPreprocessorDefinitions, "true") end function android.showIncludes(cfg) setBoolOption("ShowIncludes", cfg.flags.ShowIncludes, "true") end function android.dataLevelLinking(cfg) setBoolOption("DataLevelLinking", cfg.flags.DataLevelLinking, "true") end function android.shortEnums(cfg) setBoolOption("UseShortEnums", cfg.flags.UseShortEnums, "true") end function android.cStandard(cfg) local c_langmap = { ["C98"] = "c98", ["C99"] = "c99", ["C11"] = "c11", ["gnu99"] = "gnu99", ["gnu11"] = "gnu11", } if c_langmap[cfg.cdialect] ~= nil then vc2010.element("CLanguageStandard", nil, c_langmap[cfg.cdialect]) end end function android.cppStandard(cfg) local cpp_langmap = { ["C++98"] = "c++98", ["C++11"] = "c++11", ["C++14"] = "c++1y", ["C++17"] = "c++1z", ["C++latest"] = "c++1z", ["gnu++98"] = "gnu++98", ["gnu++11"] = "gnu++11", ["gnu++14"] = "gnu++1y", ["gnu++17"] = "gnu++1z", } if cpp_langmap[cfg.cppdialect] ~= nil then vc2010.element("CppLanguageStandard", nil, cpp_langmap[cfg.cppdialect]) end end p.override(vc2010, "additionalCompileOptions", function(oldfn, cfg, condition) if cfg.system == p.ANDROID then local opts = cfg.buildoptions if cfg.disablewarnings and #cfg.disablewarnings > 0 then for _, warning in ipairs(cfg.disablewarnings) do table.insert(opts, '-Wno-' .. warning) end end if cfg.visibility ~= nil then table.insert(opts, p.tools.gcc.cxxflags.visibility[cfg.visibility]) end if #opts > 0 then opts = table.concat(opts, " ") vc2010.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts) end else oldfn(cfg, condition) end end) p.override(vc2010, "warningLevel", function(oldfn, cfg) if _ACTION >= "vs2015" and cfg.system == p.ANDROID and cfg.warnings and cfg.warnings ~= "Off" then vc2010.element("WarningLevel", nil, "EnableAllWarnings") elseif (_ACTION >= "vs2015" and cfg.system == p.ANDROID and cfg.warnings) or not (_ACTION >= "vs2015" and cfg.system == p.ANDROID) then oldfn(cfg) end end) premake.override(vc2010, "clCompilePreprocessorDefinitions", function(oldfn, cfg, condition) if cfg.system == p.ANDROID then vc2010.preprocessorDefinitions(cfg, cfg.defines, false, condition) else oldfn(cfg, condition) end end) premake.override(vc2010, "exceptionHandling", function(oldfn, cfg, condition) if cfg.system == p.ANDROID then local exceptions = { On = "Enabled", Off = "Disabled", UnwindTables = "UnwindTables", } if _ACTION >= "vs2015" then if exceptions[cfg.exceptionhandling] ~= nil then vc2010.element("ExceptionHandling", condition, exceptions[cfg.exceptionhandling]) end else if cfg.exceptionhandling == premake.ON then vc2010.element("GccExceptionHandling", condition, "true") end end else oldfn(cfg, condition) end end) function android.enableEnhancedInstructionSet(cfg) if cfg.vectorextensions == "NEON" then vc2010.element("EnableNeonCodegen", nil, "true") end end premake.override(vc2010, "runtimeTypeInfo", function(oldfn, cfg, condition) if cfg.system == premake.ANDROID then if cfg.rtti == premake.ON then vc2010.element("RuntimeTypeInfo", condition, "true") end else oldfn(cfg, condition) end end) premake.override(vc2010, "generateDebugInformation", function(oldfn, cfg) if cfg.system ~= premake.ANDROID then oldfn(cfg) end end) premake.override(vc2010.elements, "itemDefinitionGroup", function(oldfn, cfg) local elements = oldfn(cfg) if cfg.system == premake.ANDROID and _ACTION < "vs2015" then elements = table.join(elements, { android.antBuild, }) end return elements end) function android.antPackage(cfg) p.push('') if cfg.androidapplibname ~= nil then vc2010.element("AndroidAppLibName", nil, cfg.androidapplibname) else vc2010.element("AndroidAppLibName", nil, "$(RootNamespace)") end p.pop('') end function android.antBuild(cfg) if cfg.kind == premake.STATICLIB or cfg.kind == premake.SHAREDLIB then return end _p(2,'') _p(3,'%s', iif(premake.config.isDebugBuild(cfg), "Debug", "Release")) _p(2,'') end premake.override(vc2010, "additionalCompileOptions", function(oldfn, cfg, condition) if cfg.system == premake.ANDROID then vsandroid.additionalOptions(cfg, condition) end return oldfn(cfg, condition) end) premake.override(vc2010.elements, "user", function(oldfn, cfg) if cfg.system == p.ANDROID then return {} else return oldfn(cfg) end end) function vsandroid.additionalOptions(cfg) if _ACTION >= "vs2015" then else local function alreadyHas(t, key) for _, k in ipairs(t) do if string.find(k, key) then return true end end return false end if not cfg.architecture or string.startswith(cfg.architecture, "arm") then if cfg.fpu ~= "Software" and cfg.floatabi ~= "soft" then if cfg.architecture == "armv7" then if not alreadyHas(cfg.buildoptions, "-mfpu=") then if cfg.vectorextensions == "NEON" then table.insert(cfg.buildoptions, "-mfpu=neon") elseif cfg.fpu == "Hardware" or cfg.floatabi == "softfp" or cfg.floatabi == "hard" then table.insert(cfg.buildoptions, "-mfpu=vfpv3-d16") -- d16 is the lowest common denominator end end if not alreadyHas(cfg.buildoptions, "-mfloat-abi=") then if cfg.floatabi == "hard" then table.insert(cfg.buildoptions, "-mfloat-abi=hard") else table.insert(cfg.buildoptions, "-mfloat-abi=softfp") end end else if not alreadyHas(cfg.buildoptions, "-mfpu=") then if cfg.fpu == "Hardware" or cfg.floatabi == "softfp" or cfg.floatabi == "hard" then table.insert(cfg.buildoptions, "-mfpu=vfp") end end if not alreadyHas(cfg.buildoptions, "-mfloat-abi=") then if cfg.floatabi == "softfp" then table.insert(cfg.buildoptions, "-mfloat-abi=softfp") elseif cfg.floatabi == "hard" then table.insert(cfg.buildoptions, "-mfloat-abi=hard") end end end elseif cfg.floatabi == "soft" then table.insert(cfg.buildoptions, "-mfloat-abi=soft") end if cfg.endian == "Little" then table.insert(cfg.buildoptions, "-mlittle-endian") elseif cfg.endian == "Big" then table.insert(cfg.buildoptions, "-mbig-endian") end elseif cfg.architecture == "mips" then if cfg.vectorextensions == "MXU" then table.insert(cfg.buildoptions, "-mmxu") end elseif cfg.architecture == "x86" then end end end p.override(vc2010, "subSystem", function(oldfn, cfg) if cfg.system ~= p.ANDROID then return oldfn(cfg) end end) p.override(vc2010, "additionalDependencies", function(oldfn, cfg, explicit) if cfg.system == p.ANDROID then local links = {} if explicit then links = config.getlinks(cfg, "siblings", "fullpath") end local system = config.getlinks(cfg, "system", "name") for i = 1, #system do local link = system[i] table.insert(links, link) end if #links > 0 then links = path.translate(table.concat(links, ";")) vc2010.element("LibraryDependencies", nil, "%%(LibraryDependencies);%s", links) end else return oldfn(cfg, explicit) end end) function android.useMultiToolTask(cfg) if cfg.flags.MultiProcessorCompile then vc2010.element("UseMultiToolTask", nil, "true") end end premake.override(vc2010.elements, "outputProperties", function(oldfn, cfg) if cfg.system == p.ANDROID then return table.join(oldfn(cfg), { android.useMultiToolTask, }) else return oldfn(cfg) end end) p.override(vc2010, "outDir", function(oldfn, cfg) if cfg.system ~= p.ANDROID then return oldfn(cfg) end end) local p = premake local gmake2 = p.modules.gmake2 gmake2.makefile = {} local makefile = gmake2.makefile local project = p.project local config = p.config local fileconfig = p.fileconfig makefile.elements = {} makefile.elements.makefile = function(prj) return { gmake2.header, gmake2.phonyRules, makefile.configs, makefile.targetRules } end function makefile.generate(prj) p.eol("\n") p.callArray(makefile.elements.makefile, prj) end makefile.elements.configuration = function(cfg) return { gmake2.target, gmake2.buildCommands, gmake2.cleanCommands, } end function makefile.configs(prj) local first = true for cfg in project.eachconfig(prj) do local toolset = p.tools[cfg.toolset or "gcc"] if not toolset then error("Invalid toolset '" .. cfg.toolset .. "'") end if first then _x('ifeq ($(config),%s)', cfg.shortname) first = false else _x('else ifeq ($(config),%s)', cfg.shortname) end p.callArray(makefile.elements.configuration, cfg, toolset) _p('') end if not first then _p('else') _p(' $(error "invalid configuration $(config)")') _p('endif') _p('') end end function makefile.targetRules(prj) _p('$(TARGET):') _p('\t$(BUILDCMDS)') _p('') _p('clean:') _p('\t$(CLEANCMDS)') _p('') end function gmake2.buildCommands(cfg) _p(' define BUILDCMDS') local steps = cfg.buildcommands if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) _p('\t@echo Running build commands') _p('\t%s', table.implode(steps, "", "", "\n\t")) end _p(' endef') end function gmake2.cleanCommands(cfg) _p(' define CLEANCMDS') local steps = cfg.cleancommands if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) _p('\t@echo Running clean commands') _p('\t%s', table.implode(steps, "", "", "\n\t")) end _p(' endef') end lQSpQSxQS:S?SxQSxCSRSlocal p = premake p.vstudio.nuget2010 = {} local vstudio = p.vstudio local nuget2010 = p.vstudio.nuget2010 local dn2005 = p.vstudio.dotnetbase local packageAPIInfos = {} local packageSourceInfos = {} function nuget2010.packageId(package) return package:sub(0, package:find(":") - 1) end function nuget2010.packageVersion(package) return package:sub(package:find(":") + 1, -1) end function nuget2010.packageFramework(prj) if p.project.isdotnet(prj) then local cfg = p.project.getfirstconfig(prj) local action = p.action.current() local framework = cfg.dotnetframework or action.vstudio.targetFramework return dn2005.formatNuGetFrameworkVersion(framework) else return "native" end end function nuget2010.supportsPackageReferences(prj) return _ACTION >= "vs2017" and p.project.isdotnet(prj) end function nuget2010.packageAPIInfo(prj, package) local id = nuget2010.packageId(package) local version = nuget2010.packageVersion(package) local function examinePackageFromCache() if not os.ishost("windows") then return end local cachePath = path.translate(path.join(os.getenv("userprofile"), ".nuget/packages", id)) if os.isdir(cachePath) then local packageAPIInfo = {} printf("Examining cached NuGet package '%s'...", id) io.flush() local versionPath = path.translate(path.join(cachePath, version)) local nuspecPath = path.translate(path.join(versionPath, id .. ".nuspec")) if not os.isfile(nuspecPath) then return end local nuspec = io.readfile(nuspecPath) if not nuspec then return end packageAPIInfo.verbatimVersion = nuspec:match("(.+)") packageAPIInfo.version = version if not packageAPIInfo.verbatimVersion then return end if p.project.isdotnet(prj) then packageAPIInfo.packageEntries = {} for _, file in ipairs(os.matchfiles(path.translate(path.join(versionPath, "**")))) do local extension = path.getextension(file) if extension ~= ".nupkg" and extension ~= ".sha512" then table.insert(packageAPIInfo.packageEntries, path.translate(path.getrelative(versionPath, file))) end end if #packageAPIInfo.packageEntries == 0 then return end if nuspec:match("(.+)") then p.warn("NuGet package '%s' may depend on .NET Framework assemblies - package dependencies are currently unimplemented", id) end end if nuspec:match("(.+)") then p.warn("NuGet package '%s' may depend on other packages - package dependencies are currently unimplemented", id) end packageAPIInfos[package] = packageAPIInfo end end if not packageAPIInfos[package] then examinePackageFromCache() end if not packageAPIInfos[package] then if not packageSourceInfos[prj.nugetsource] then local packageSourceInfo = {} printf("Examining NuGet package source '%s'...", prj.nugetsource) io.flush() local response, err, code = http.get(prj.nugetsource) if err ~= "OK" then p.error("NuGet API error (%d)\n%s", code, err) end response, err = json.decode(response) if not response then p.error("Failed to decode NuGet API response (%s)", err) end if not response.resources then p.error("Failed to understand NuGet API response (no resources in response)", id) end local packageDisplayMetadataUriTemplate, catalog for _, resource in ipairs(response.resources) do if not resource["@id"] then p.error("Failed to understand NuGet API response (no resource['@id'])") end if not resource["@type"] then p.error("Failed to understand NuGet API response (no resource['@type'])") end if resource["@type"]:find("PackageDisplayMetadataUriTemplate") == 1 then packageDisplayMetadataUriTemplate = resource end if resource["@type"]:find("Catalog") == 1 then catalog = resource end end if not packageDisplayMetadataUriTemplate then p.error("Failed to understand NuGet API response (no PackageDisplayMetadataUriTemplate resource)") end if not catalog then if prj.nugetsource == "https://api.nuget.org/v3/index.json" then p.error("Failed to understand NuGet API response (no Catalog resource)") else p.error("Package source is not a NuGet gallery - non-gallery sources are currently unsupported", prj.nugetsource, prj.name) end end packageSourceInfo.packageDisplayMetadataUriTemplate = packageDisplayMetadataUriTemplate packageSourceInfo.catalog = catalog packageSourceInfos[prj.nugetsource] = packageSourceInfo end local packageAPIInfo = {} printf("Examining NuGet package '%s'...", id) io.flush() local response, err, code = http.get(packageSourceInfos[prj.nugetsource].packageDisplayMetadataUriTemplate["@id"]:gsub("{id%-lower}", id:lower())) if err ~= "OK" then if code == 404 then p.error("NuGet package '%s' for project '%s' couldn't be found in the repository", id, prj.name) else p.error("NuGet API error (%d)\n%s", code, err) end end response, err = json.decode(response) if not response then p.error("Failed to decode NuGet API response (%s)", err) end if not response.items or #response.items == 0 then p.error("Failed to understand NuGet API response (no pages for package '%s')", id) end local items = {} for _, page in ipairs(response.items) do if not page.items or #page.items == 0 then p.error("Failed to understand NuGet API response (got a page with no items for package '%s')", id) end for _, item in ipairs(page.items) do table.insert(items, item) end end local versions = {} for _, item in ipairs(items) do if not item.catalogEntry then p.error("Failed to understand NuGet API response (subitem of package '%s' has no catalogEntry)", id) end if not item.catalogEntry.version then p.error("Failed to understand NuGet API response (subitem of package '%s' has no catalogEntry.version)", id) end if not item.catalogEntry["@id"] then p.error("Failed to understand NuGet API response (subitem of package '%s' has no catalogEntry['@id'])", id) end table.insert(versions, item.catalogEntry.version) end if not table.contains(versions, version) then local options = table.translate(versions, function(value) return "'" .. value .. "'" end) options = table.concat(options, ", ") p.error("'%s' is not a valid version for NuGet package '%s' (options are: %s)", version, id, options) end for _, item in ipairs(items) do if item.catalogEntry.version == version then local response, err, code = http.get(item.catalogEntry["@id"]) if err ~= "OK" then if code == 404 then p.error("NuGet package '%s' version '%s' couldn't be found in the repository even though the API reported that it exists", id, version) else p.error("NuGet API error (%d)\n%s", code, err) end end response, err = json.decode(response) if not response then p.error("Failed to decode NuGet API response (%s)", err) end if not response.verbatimVersion and not response.version then p.error("Failed to understand NuGet API response (package '%s' version '%s' has no verbatimVersion or version)", id, version) end packageAPIInfo.verbatimVersion = response.verbatimVersion packageAPIInfo.version = response.version if prj.language == "C#" and not response.packageEntries then p.error("NuGet package '%s' version '%s' has no file listing. This package might be too old to be using this API or it might be a C++ package instead of a .NET Framework package.", id, response.version) end if prj.language == "C#" then packageAPIInfo.packageEntries = {} for _, item in ipairs(response.packageEntries) do if not item.fullName then p.error("Failed to understand NuGet API response (package '%s' version '%s' packageEntry has no fullName)", id, version) end table.insert(packageAPIInfo.packageEntries, path.translate(item.fullName)) end if #packageAPIInfo.packageEntries == 0 then p.error("NuGet package '%s' file listing is empty", id) end if response.frameworkAssemblyGroup then p.warn("NuGet package '%s' may depend on .NET Framework assemblies - package dependencies are currently unimplemented", id) end end if response.dependencyGroups then p.warn("NuGet package '%s' may depend on other packages - package dependencies are currently unimplemented", id) end break end end packageAPIInfos[package] = packageAPIInfo end return packageAPIInfos[package] end function nuget2010.generatePackagesConfig(prj) if #prj.nuget > 0 then p.w('') p.push('') for _, package in ipairs(prj.nuget) do p.x('', nuget2010.packageId(package), nuget2010.packageVersion(package), nuget2010.packageFramework(prj)) end p.pop('') end end function nuget2010.generateNuGetConfig(prj) if #prj.nuget == 0 then return end if prj.nugetsource == "https://api.nuget.org/v3/index.json" then return end p.w('') p.push('') p.push('') p.x('') p.x('', prj.nugetsource, prj.nugetsource) p.pop('') p.pop('') end function nuget2010.uniqueProjectLocationsWithNuGet(wks) local locations = {} for prj in p.workspace.eachproject(wks) do if not nuget2010.supportsPackageReferences(prj) then local function fail() p.error("projects '%s' and '%s' cannot have the same location when using NuGet with different packages (packages.config conflict)", locations[prj.location].name, prj.name) end if locations[prj.location] and #locations[prj.location].nuget > 0 and #prj.nuget > 0 then if #locations[prj.location].nuget ~= #prj.nuget then fail() end for i, package in ipairs(locations[prj.location].nuget) do if prj.nuget[i] ~= package then fail() end end end locations[prj.location] = prj end end end p.override(p.validation.elements, "workspace", function (oldfn, wks) local t = oldfn(wks) table.insert(t, nuget2010.uniqueProjectLocationsWithNuGet) return t end) function nuget2010.NuGetHasHTTP(prj) if not http and #prj.nuget > 0 and not nuget2010.supportsPackageReferences(prj) then p.error("Premake was compiled with --no-curl, but Curl is required for NuGet support (project '%s' is referencing NuGet packages)", prj.name) end end function nuget2010.NuGetPackageStrings(prj) for _, package in ipairs(prj.nuget) do local components = package:explode(":") if #components ~= 2 or #components[1] == 0 or #components[2] == 0 then p.error("NuGet package '%s' in project '%s' is invalid - please give packages in the format 'id:version', e.g. 'NUnit:3.6.1'", package, prj.name) end end end p.override(p.validation.elements, "project", function (oldfn, prj) local t = oldfn(prj) table.insert(t, nuget2010.NuGetHasHTTP) table.insert(t, nuget2010.NuGetPackageStrings) return t end) local p = premake p.context = {} local context = p.context local configset = p.configset function context.new(cfgset, environ) local ctx = {} ctx._cfgset = cfgset ctx.environ = environ or {} ctx.terms = {} ctx._basedir = os.getcwd() setmetatable(ctx, context.__mt) return ctx end function context.extent(baseContext, newEnvVars) local ctx = {} ctx._ctx = baseContext ctx.environ = newEnvVars or baseContext.environ ctx.terms = {} ctx._basedir = baseContext._basedir setmetatable(ctx, context.__mt_uncached) return ctx end function context.addFilter(ctx, key, value) if type(value) == "table" then for i = 1, #value do value[i] = tostring(value[i]):lower() end elseif value ~= nil then value = tostring(value):lower() end ctx.terms[key:lower()] = value end function context.copyFilters(ctx, src) ctx.terms = {} for k,v in pairs(src.terms) do ctx.terms[k] = v end end function context.mergeFilters(ctx, src) for k, v in pairs(src.terms) do if k == "tags" then ctx.terms[k] = table.join(ctx.terms[k], v) else ctx.terms[k] = v end end end function context.basedir(ctx, basedir) ctx._basedir = basedir or ctx._basedir return ctx._basedir end function context.compile(ctx) ctx._cfgset = configset.compile(ctx._cfgset, ctx.terms) end function context.empty(ctx) return configset.empty(ctx._cfgset) end function context.fetchvalue(ctx, key, onlylocal) if not onlylocal then local value = rawget(ctx, key) if value ~= nil then return value end end local field = p.field.get(key) if not field then return nil end local value = configset.fetch(ctx._cfgset, field, ctx.terms, ctx, onlylocal and ctx._cfgset) if value then rawset(ctx, key, value) end return value end context.__mt = { __index = context.fetchvalue } context.__mt_uncached = { __index = function(ctx, key) local field = p.field.get(key) if not field then return nil end local parent = rawget(ctx, '_ctx') return configset.fetch(parent._cfgset, field, ctx.terms, ctx, nil) end }   local p = premake p.workspace = p.api.container("workspace", p.global) local workspace = p.workspace p.solution = workspace workspace.alias = "solution" p.alias(_G, "workspace", "solution") p.alias(_G, "externalworkspace", "externalsolution") function workspace.new(name) local wks = p.container.new(workspace, name) return wks end function workspace.eachconfig(self) self = p.oven.bakeWorkspace(self) local i = 0 return function() i = i + 1 if i > #self.configs then return nil else return self.configs[i] end end end function workspace.eachproject(self) local i = 0 return function () i = i + 1 if i <= #self.projects then return p.workspace.getproject(self, i) end end end function workspace.findproject(self, name) name = name:lower() for _, prj in ipairs(self.projects) do if name == prj.name:lower() then return prj end end return nil end function workspace.grouptree(self) if self.grouptree then return self.grouptree end local tr = p.tree.new() for prj in workspace.eachproject(self) do local prjpath = path.join(prj.group, prj.name) local node = p.tree.add(tr, prjpath) node.project = prj end p.tree.traverse(tr, { onbranch = function(node) node.uuid = os.uuid("group:" .. node.path) end }) p.tree.sort(tr, function(a,b) return a.name < b.name end) self.grouptree = tr return tr end function workspace.getproject(self, idx) self = p.oven.bakeWorkspace(self) return self.projects[idx] end function workspace.hasProject(self, func) return p.container.hasChild(self, p.project, func) end function workspace.getrelative(self, filename) if type(filename) == "table" then local result = {} for i, name in ipairs(filename) do if name and #name > 0 then table.insert(result, workspace.getrelative(self, name)) end end return result else if filename then local result = filename if path.hasdeferredjoin(result) then result = path.resolvedeferredjoin(result) end return path.getrelative(self.location, result) end end end local p = premake p.tools.ldc = { } local ldc = p.tools.ldc local project = p.project local config = p.config local d = p.modules.d ldc.namestyle = "posix" ldc.dflags = { architecture = { x86 = "-m32", x86_64 = "-m64", }, flags = { OmitDefaultLibrary= "-mscrtlib=", CodeCoverage= "-cov", Documentation= "-D", FatalWarnings= "-w", -- Use LLVM flag? : "-fatal-assembler-warnings", GenerateHeader= "-H", GenerateJSON= "-X", RetainPaths= "-op", SymbolsLikeC= "-gc", UnitTest= "-unittest", Verbose= "-v", AllTemplateInst= "-allinst", BetterC= "-betterC", Main= "-main", PerformSyntaxCheckOnly= "-o-", ShowGC= "-vgc", IgnorePragma= "-ignore", }, boundscheck = { Off = "-boundscheck=off", On = "-boundscheck=on", SafeOnly = "-boundscheck=safeonly", }, deprecatedfeatures = { Allow = "-d", Warn = "-dw", Error = "-de", }, floatingpoint = { Fast = "-fp-contract=fast -enable-unsafe-fp-math", }, optimize = { Off = "-O0", On = "-O2", Debug = "-O0", Full = "-O3", Size = "-Oz", Speed = "-O3", }, pic = { On = "-relocation-model=pic", }, vectorextensions = { AVX = "-mattr=+avx", SSE = "-mattr=+sse", SSE2 = "-mattr=+sse2", }, warnings = { Default = "-wi", High = "-wi", Extra = "-wi",-- TODO: is there a way to get extra warnings? }, symbols = { On = "-g", FastLink = "-g", Full = "-g", } } function ldc.getdflags(cfg) local flags = config.mapFlags(cfg, ldc.dflags) if config.isDebugBuild(cfg) then table.insert(flags, "-d-debug") else table.insert(flags, "-release") end if not cfg.flags.OmitDefaultLibrary then local releaseruntime = not config.isDebugBuild(cfg) local staticruntime = true if cfg.staticruntime == "Off" then staticruntime = false end if cfg.runtime == "Debug" then releaseruntime = false elseif cfg.runtime == "Release" then releaseruntime = true end if (cfg.staticruntime and cfg.staticruntime ~= "Default") or (cfg.runtime and cfg.runtime ~= "Default") then if staticruntime == true and releaseruntime == true then table.insert(flags, "-mscrtlib=libcmt") elseif staticruntime == true and releaseruntime == false then table.insert(flags, "-mscrtlib=libcmtd") elseif staticruntime == false and releaseruntime == true then table.insert(flags, "-mscrtlib=msvcrt") elseif staticruntime == false and releaseruntime == false then table.insert(flags, "-mscrtlib=msvcrtd") end end end if cfg.flags.Documentation then if cfg.docname then table.insert(flags, "-Df=" .. p.quoted(cfg.docname)) end if cfg.docdir then table.insert(flags, "-Dd=" .. p.quoted(cfg.docdir)) end end if cfg.flags.GenerateHeader then if cfg.headername then table.insert(flags, "-Hf=" .. p.quoted(cfg.headername)) end if cfg.headerdir then table.insert(flags, "-Hd=" .. p.quoted(cfg.headerdir)) end end return flags end function ldc.getversions(versions, level) local result = {} for _, version in ipairs(versions) do table.insert(result, '-d-version=' .. version) end if level then table.insert(result, '-d-version=' .. level) end return result end function ldc.getdebug(constants, level) local result = {} for _, constant in ipairs(constants) do table.insert(result, '-d-debug=' .. constant) end if level then table.insert(result, '-d-debug=' .. level) end return result end function ldc.getimportdirs(cfg, dirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-I=' .. p.quoted(dir)) end return result end function ldc.getstringimportdirs(cfg, dirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-J=' .. p.quoted(dir)) end return result end function ldc.gettarget(name) return "-of=" .. name end ldc.ldflags = { architecture = { x86 = { "-m32" }, x86_64 = { "-m64" }, }, kind = { SharedLib = "-shared", StaticLib = "-lib", }, } function ldc.getldflags(cfg) local flags = config.mapFlags(cfg, ldc.ldflags) return flags end ldc.libraryDirectories = { architecture = { x86 = "-L=-L/usr/lib", x86_64 = "-L=-L/usr/lib64", } } function ldc.getLibraryDirectories(cfg) local flags = config.mapFlags(cfg, ldc.libraryDirectories) for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do table.insert(flags, '-L=-L' .. project.getrelative(cfg.project, dir)) end return flags end function ldc.getlinks(cfg, systemonly) local result = {} local links if not systemonly then links = config.getlinks(cfg, "siblings", "object") for _, link in ipairs(links) do if not link.project.external then if link.kind == p.STATICLIB then table.insert(result, "-L=" .. project.getrelative(cfg.project, link.linktarget.abspath)) else table.insert(result, "-L=-l" .. link.linktarget.basename) end end end end links = config.getlinks(cfg, "system", "fullpath") for _, link in ipairs(links) do if path.isframework(link) then table.insert(result, "-framework " .. path.getbasename(link)) elseif path.isobjectfile(link) then table.insert(result, "-L=" .. link) else table.insert(result, "-L=-l" .. path.getbasename(link)) end end return result end ldc.makesettings = { } function ldc.getmakesettings(cfg) local settings = config.mapFlags(cfg, ldc.makesettings) return table.concat(settings) end ldc.tools = { dc = "ldc2", ar = "ar", } function ldc.gettoolname(cfg, tool) return ldc.tools[tool] end newaction { trigger = "raw", shortname = "Raw output", description = "Generate raw representation of Premake structures", onsolution = function(sln) require('raw') premake.generate(sln, ".raw", premake.raw.workspace) end, } return function(cfg) return (_ACTION == "raw") end local p = premake p.config = {} local project = p.project local config = p.config function config.buildtargetinfo(cfg, kind, field) local basedir = cfg.project.location local targetdir if cfg.platform then targetdir = path.join(basedir, 'bin', cfg.platform, cfg.buildcfg) else targetdir = path.join(basedir, 'bin', cfg.buildcfg) end local directory = cfg[field.."dir"] or cfg.targetdir or targetdir local basename = cfg[field.."name"] or cfg.targetname or cfg.project.name local prefix = cfg[field.."prefix"] or cfg.targetprefix or "" local suffix = cfg[field.."suffix"] or cfg.targetsuffix or "" local extension = cfg[field.."extension"] or cfg.targetextension or "" local bundlename = "" local bundlepath = "" if table.contains(os.getSystemTags(cfg.system), "darwin") and (kind == p.WINDOWEDAPP or (kind == p.SHAREDLIB and cfg.sharedlibtype)) then bundlename = basename .. extension bundlepath = path.join(bundlename, iif(kind == p.SHAREDLIB and cfg.sharedlibtype == "OSXFramework", "Versions/A", "Contents/MacOS")) end local info = {} info.directory = directory info.basename = basename .. suffix info.name = prefix .. info.basename .. extension info.extension = extension info.abspath = path.join(directory, info.name) info.fullpath = info.abspath info.bundlename = bundlename info.bundlepath = path.join(directory, bundlepath) info.prefix = prefix info.suffix = suffix return info end function config.canLink(cfg, target, linkage) if type(target) ~= "string" then if target.kind ~= "SharedLib" and target.kind ~= "StaticLib" then return false end if cfg.language == "C++" then if cfg.clr == p.ON then return true end end if target.language == "C++" then if target.clr == p.ON then return true end end local cfgManaged = project.isdotnet(cfg.project) or (cfg.clr ~= p.OFF) local tgtManaged = project.isdotnet(target.project) or (target.clr ~= p.OFF) return (cfgManaged == tgtManaged) end if project.isdotnet(cfg.project) then return true end local isManaged = (path.getextension(target) == ".dll") if isManaged and cfg.clr == p.OFF then return false end return (isManaged) == (linkage == "managed") end function config.canLinkIncremental(cfg) if cfg.kind == "StaticLib" or config.isOptimizedBuild(cfg) or cfg.flags.NoIncrementalLink then return false end return true end function config.findfile(cfg, ext) for _, fname in ipairs(cfg.files) do if fname:endswith(ext) then return project.getrelative(cfg.project, fname) end end end function config.getlinkinfo(cfg) local kind = cfg.kind if project.isnative(cfg.project) then if cfg.system == p.WINDOWS and kind == p.SHAREDLIB and not cfg.flags.NoImportLib then kind = p.STATICLIB end end return config.buildtargetinfo(cfg, kind, "implib") end function config.getlinks(cfg, kind, part, linkage) local result = {} if part == "directory" then table.foreachi(cfg.libdirs, function(dir) table.insert(result, project.getrelative(cfg.project, dir)) end) end for i = 1, #cfg.links do local link = cfg.links[i] local item local prj = p.workspace.findproject(cfg.workspace, link) if prj and kind ~= "system" then local prjcfg = project.getconfig(prj, cfg.buildcfg, cfg.platform) if prjcfg and (kind == "dependencies" or config.canLink(cfg, prjcfg)) then if part == "object" then item = prjcfg else item = project.getrelative(cfg.project, prjcfg.linktarget.fullpath) end end elseif not prj and (kind == "system" or kind == "all") then if config.canLink(cfg, link, linkage) then item = link if item:find("/", nil, true) then item = project.getrelative(cfg.project, item) end end end if item and item ~= cfg then if part == "directory" then item = path.getdirectory(item) if item == "." then item = nil end elseif part == "name" then item = path.getname(item) elseif part == "basename" then item = path.getbasename(item) elseif type(part) == "function" then part(link, item) end end if item and not table.contains(result, item) then table.insert(result, item) end end return result end function config.getruntime(cfg) if (not cfg.staticruntime or cfg.staticruntime == "Default") and not cfg.runtime then return nil -- indicate that no runtime was explicitly selected end local linkage = iif(cfg.staticruntime == "On", "Static", "Shared") -- assume 'Shared' is default? if not cfg.runtime then return linkage .. iif(config.isDebugBuild(cfg), "Debug", "Release") else return linkage .. cfg.runtime end end function config.gettargetinfo(cfg) return config.buildtargetinfo(cfg, cfg.kind, "target") end function config.hasFile(self, testfn) local files = self.files for i = 1, #files do if testfn(files[i]) then return true end end return false end function config.isCopyLocal(cfg, linkname, default) if cfg.flags.NoCopyLocal then return false end if #cfg.copylocal > 0 then return table.contains(cfg.copylocal, linkname) end return default end function config.isDebugBuild(cfg) return cfg.symbols ~= nil and cfg.symbols ~= p.OFF and cfg.symbols ~= "Default" and not config.isOptimizedBuild(cfg) end function config.isOptimizedBuild(cfg) return cfg.optimize ~= nil and cfg.optimize ~= p.OFF and cfg.optimize ~= "Debug" end function config.linksToProject(cfg, prjName) prjName = prjName:lower() local n = #cfg.links for i = 1,n do if cfg.links[i]:lower() == prjName then return true end end end function config.mapFlags(cfg, mappings) local flags = {} local function add(replacement) if type(replacement) == "function" then replacement = replacement(cfg) end table.insertflat(flags, replacement) end for field in p.field.eachOrdered() do local map = mappings[field.name] if type(map) == "function" then map = map(cfg, mappings) end if map then local values = cfg[field.name] if type(values) == "boolean" then values = iif(values, "On", "Off") end if type(values) ~= "table" then values = { values } end local foundValue = false table.foreachi(values, function(value) local replacement = map[value] if replacement ~= nil then foundValue = true add(replacement) end end) if not foundValue then add(map._) end for key, replacement in pairs(map) do if #key > 1 and key:startswith("_") then key = key:sub(2) if values[key] == nil then add(replacement) end end end end end return flags end function config.normalize(cfg) if cfg and cfg.config ~= nil then return cfg.config, cfg else return cfg, nil end end function config.toolset(cfg) if cfg.toolset then return p.tools.canonical(cfg.toolset) end end      ZSZSIZSZSZSZS[S[SI     local p = premake local api = p.api p.D = "D" api.addAllowed("language", p.D) api.addAllowed("floatingpoint", "None") api.addAllowed("flags", { "CodeCoverage", "Deprecated",-- DEPRECATED "Documentation", "GenerateHeader", "GenerateJSON", "GenerateMap", "NoBoundsCheck",-- DEPRECATED "Profile", "Quiet", "RetainPaths", "SeparateCompilation",-- DEPRECATED "SymbolsLikeC", "UnitTest", "ProfileGC", "StackFrame", "StackStomp", "AllTemplateInst", "BetterC", "Main", "PerformSyntaxCheckOnly", "ShowCommandLine", "Verbose", "ShowTLS", "ShowGC", "IgnorePragma", "ShowDependencies", }) api.register { name = "versionconstants", scope = "config", kind = "list:string", tokens = true, } api.register { name = "versionlevel", scope = "config", kind = "integer", } api.register { name = "debugconstants", scope = "config", kind = "list:string", tokens = true, } api.register { name = "debuglevel", scope = "config", kind = "integer", } api.register { name = "docdir", scope = "config", kind = "path", tokens = true, } api.register { name = "docname", scope = "config", kind = "string", tokens = true, } api.register { name = "headerdir", scope = "config", kind = "path", tokens = true, } api.register { name = "headername", scope = "config", kind = "string", tokens = true, } api.register { name = "compilationmodel", scope = "config", kind = "string", allowed = { "Default", "File", "Package",-- TODO: this doesn't work with gmake!! "Project", }, } api.register { name = "importdirs", scope = "config", kind = "list:path", tokens = true, } api.register { name = "stringimportdirs", scope = "config", kind = "list:path", tokens = true, } api.register { name = "deprecatedfeatures", scope = "config", kind = "string", allowed = { "Default", "Allow", "Warn", "Error", }, } api.register { name = "boundscheck", scope = "config", kind = "string", allowed = { "Default", "Off", "On", "SafeOnly", }, } api.register { name = "dependenciesfile", scope = "config", kind = "path", tokens = true, } api.register { name = "jsonfile", scope = "config", kind = "path", tokens = true, } newoption { category= "compilers", trigger= "dc", value= "VALUE", description= "Choose a D compiler", allowed = { { "dmd", "Digital Mars (dmd)" }, { "gdc", "GNU GDC (gdc)" }, { "ldc", "LLVM LDC (ldc2)" }, } } api.deprecateValue("flags", "SeparateCompilation", 'Use `compilationmodel "File"` instead', function(value) compilationmodel "File" end, function(value) compilationmodel "Default" end) api.deprecateValue("flags", "Deprecated", 'Use `deprecatedfeatures "Allow"` instead', function(value) deprecatedfeatures "Allow" end, function(value) deprecatedfeatures "Default" end) api.deprecateValue("flags", "NoBoundsCheck", 'Use `boundscheck "Off"` instead', function(value) boundscheck "Off" end, function(value) boundscheck "Default" end) return function (cfg) return (cfg.language == p.D or cfg.language == "C" or cfg.language == "C++") end local p = premake p.make.cpp = {} local make = p.make local cpp = p.make.cpp local project = p.project local config = p.config local fileconfig = p.fileconfig cpp.elements = {} cpp.elements.makefile = function(prj) return { make.header, make.phonyRules, make.cppConfigs, make.cppObjects, make.shellType, make.cppTargetRules, make.cppCustomFilesRules, make.cppTargetDirRules, make.cppObjDirRules, make.cppCleanRules, make.preBuildRules, make.preLinkRules, make.pchRules, make.cppFileRules, make.cppDependencies, } end function make.fileTypeExtensions() return { ["objects"] = "o", ["resources"] = "res", } end function make.fileType(node) local kind if path.iscppfile(node.abspath) then kind = "objects" elseif path.isresourcefile(node.abspath) then kind = "resources" end return kind end function make.fileDependency(prj, node) local filetype = make.fileType(node) _x('$(OBJDIR)/%s.%s: %s', node.objname, make.fileTypeExtensions()[filetype], node.relpath) _p('\t@echo $(notdir $<)') end function make.cpp.generate(prj) p.eol("\n") p.callArray(cpp.elements.makefile, prj) end cpp.elements.standardFileRules = function(prj, node) return { make.fileDependency, cpp.standardFileRules, } end cpp.elements.customFileRules = function(prj, node) return { make.fileDependency, cpp.customFileRules, } end cpp.elements.customBuildRules = function(prj, node) return { cpp.customFileRules } end cpp.elements.configuration = function(cfg, toolset) return { make.configBegin, make.cppTools, make.target, make.objdir, make.pch, make.defines, make.includes, make.forceInclude, make.cppFlags, make.cFlags, make.cxxFlags, make.resFlags, make.libs, make.ldDeps, make.ldFlags, make.linkCmd, make.exePaths, make.preBuildCmds, make.preLinkCmds, make.postBuildCmds, make.cppAllRules, make.settings, make.configEnd, } end function make.cppConfigs(prj) for cfg in project.eachconfig(prj) do local toolset = p.tools[_OPTIONS.cc or cfg.toolset or "gcc"] if not toolset then error("Invalid toolset '" .. cfg.toolset .. "'") end p.callArray(cpp.elements.configuration, cfg, toolset) _p('') end end function make.exePaths(cfg) local dirs = project.getrelative(cfg.project, cfg.bindirs) if #dirs > 0 then _p(' EXECUTABLE_PATHS = "%s"', table.concat(dirs, ":")) _p(' EXE_PATHS = export PATH=$(EXECUTABLE_PATHS):$$PATH;') end end function cpp.compileas(prj, node) local result if node["compileas"] then if p.languages.isc(node.compileas) then result = '$(CC) $(ALL_CFLAGS)' elseif p.languages.iscpp(node.compileas) then result = '$(CXX) $(ALL_CXXFLAGS)' end end return result end function cpp.buildcommand(prj, objext, node) local flags = cpp.compileas(prj, node) if not flags then local iscfile = node and path.iscfile(node.abspath) or false flags = iif(prj.language == "C" or iscfile, '$(CC) $(ALL_CFLAGS)', '$(CXX) $(ALL_CXXFLAGS)') end _p('\t$(SILENT) %s $(FORCE_INCLUDE) -o "$@" -MF "$(@:%%.%s=%%.d)" -c "$<"', flags, objext) end function make.cppFileRules(prj) local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) local rules for cfg in project.eachconfig(prj) do local filecfg = fileconfig.getconfig(node, cfg) if fileconfig.hasCustomBuildRule(filecfg) then rules = cpp.elements.customBuildRules(prj, node) break end if fileconfig.hasFileSettings(filecfg) then rules = cpp.elements.customFileRules(prj, node) break end end if not rules and make.fileType(node) then rules = cpp.elements.standardFileRules(prj, node) end if rules then p.callArray(rules, prj, node) end end }) _p('') end function cpp.standardFileRules(prj, node) local kind = make.fileType(node) if kind == "objects" then cpp.buildcommand(prj, make.fileTypeExtensions()[kind], node) elseif kind == "resources" then _p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(ALL_RESFLAGS)') end end function cpp.customFileRules(prj, node) for cfg in project.eachconfig(prj) do local filecfg = fileconfig.getconfig(node, cfg) if filecfg then make.configBegin(cfg) if fileconfig.hasCustomBuildRule(filecfg) then local output = project.getrelative(prj, filecfg.buildoutputs[1]) local dependencies = filecfg.relpath if filecfg.buildinputs and #filecfg.buildinputs > 0 then local inputs = project.getrelative(prj, filecfg.buildinputs) dependencies = dependencies .. " " .. table.concat(p.esc(inputs), " ") end _p('%s: %s', output, dependencies) _p('\t@echo "%s"', filecfg.buildmessage or ("Building " .. filecfg.relpath)) local cmds = os.translateCommandsAndPaths(filecfg.buildcommands, cfg.project.basedir, cfg.project.location) for _, cmd in ipairs(cmds) do if cfg.bindirs and #cfg.bindirs > 0 then _p('\t$(SILENT) $(EXE_PATHS) %s', cmd) else _p('\t$(SILENT) %s', cmd) end end else cpp.standardFileRules(prj, filecfg) end make.configEnd(cfg) end end end function make.cppObjects(prj) local root = { objects={}, resources={}, customfiles={} } local configs = {} for cfg in project.eachconfig(prj) do configs[cfg] = { objects={}, resources={}, customfiles={} } end local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) local incfg = {} local inall = true local custom = false for cfg in project.eachconfig(prj) do local filecfg = fileconfig.getconfig(node, cfg) if filecfg and not filecfg.flags.ExcludeFromBuild then incfg[cfg] = filecfg custom = fileconfig.hasCustomBuildRule(filecfg) else inall = false end end if not custom then local kind if path.iscppfile(node.abspath) then kind = "objects" elseif path.isresourcefile(node.abspath) then kind = "resources" end if not custom and not kind then return end objectname = "$(OBJDIR)/" .. node.objname .. iif(kind == "objects", ".o", ".res") if inall then table.insert(root[kind], objectname) else for cfg in project.eachconfig(prj) do if incfg[cfg] then table.insert(configs[cfg][kind], objectname) end end end else for cfg in project.eachconfig(prj) do local filecfg = incfg[cfg] if filecfg then local output = project.getrelative(prj, filecfg.buildoutputs[1]) if path.isobjectfile(output) and (filecfg.linkbuildoutputs == true or filecfg.linkbuildoutputs == nil) then table.insert(configs[cfg].objects, output) else table.insert(configs[cfg].customfiles, output) end end end end end }) function listobjects(var, list) _p('%s \\', var) for _, objectname in ipairs(list) do _x('\t%s \\', objectname) end _p('') end listobjects('OBJECTS :=', root.objects, 'o') listobjects('RESOURCES :=', root.resources, 'res') listobjects('CUSTOMFILES :=', root.customfiles) for cfg in project.eachconfig(prj) do local files = configs[cfg] if #files.objects > 0 or #files.resources > 0 or #files.customfiles > 0 then make.configBegin(cfg, toolset) if #files.objects > 0 then listobjects(' OBJECTS +=', files.objects) end if #files.resources > 0 then listobjects(' RESOURCES +=', files.resources) end if #files.customfiles > 0 then listobjects(' CUSTOMFILES +=', files.customfiles) end make.configEnd(cfg, toolset) _p('') end end end function make.configBegin(cfg, toolset) if cfg then _x('ifeq ($(config),%s)', cfg.shortname) end end function make.configEnd(cfg, toolset) if cfg then _p('endif') end end function make.cFlags(cfg, toolset) _p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS)%s', make.list(table.join(toolset.getcflags(cfg), cfg.buildoptions))) end function make.cppAllRules(cfg, toolset) if cfg.system == p.MACOSX and cfg.kind == p.WINDOWEDAPP then _p('all: prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist') _p('\t@:') _p('') _p('$(dir $(TARGETDIR))PkgInfo:') _p('$(dir $(TARGETDIR))Info.plist:') else _p('all: prebuild prelink $(TARGET)') _p('\t@:') end end function make.cppFlags(cfg, toolset) _p(' ALL_CPPFLAGS += $(CPPFLAGS)%s $(DEFINES) $(INCLUDES)', make.list(toolset.getcppflags(cfg))) end function make.cxxFlags(cfg, toolset) _p(' ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS)%s', make.list(table.join(toolset.getcxxflags(cfg), cfg.buildoptions))) end function make.cppCleanRules(prj) _p('clean:') _p('\t@echo Cleaning %s', prj.name) _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET)') _p('\t$(SILENT) rm -rf $(OBJDIR)') _p('else') _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') _p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))') _p('endif') _p('') end function make.cppDependencies(prj) _p('-include $(OBJECTS:%%.o=%%.d)') _p('ifneq (,$(PCH))') _p(' -include $(OBJDIR)/$(notdir $(PCH)).d') _p('endif') end function make.cppTargetRules(prj) _p('$(TARGET): $(GCH) ${CUSTOMFILES} $(OBJECTS) $(LDDEPS) $(RESOURCES) | $(TARGETDIR)') _p('\t@echo Linking %s', prj.name) _p('\t$(SILENT) $(LINKCMD)') _p('\t$(POSTBUILDCMDS)') _p('') end function make.cppCustomFilesRules(prj) _p('$(CUSTOMFILES): | $(OBJDIR)') _p('') end function make.cppTargetDirRules(prj) _p('$(TARGETDIR):') _p('\t@echo Creating $(TARGETDIR)') make.mkdir('$(TARGETDIR)') _p('') end function make.cppObjDirRules(prj) _p('$(OBJDIR):') _p('\t@echo Creating $(OBJDIR)') make.mkdir('$(OBJDIR)') _p('') end function make.cppTools(cfg, toolset) local tool = toolset.gettoolname(cfg, "cc") if tool then _p(' ifeq ($(origin CC), default)') _p(' CC = %s', tool) _p(' endif' ) end tool = toolset.gettoolname(cfg, "cxx") if tool then _p(' ifeq ($(origin CXX), default)') _p(' CXX = %s', tool) _p(' endif' ) end tool = toolset.gettoolname(cfg, "ar") if tool then _p(' ifeq ($(origin AR), default)') _p(' AR = %s', tool) _p(' endif' ) end tool = toolset.gettoolname(cfg, "rc") if tool then _p(' RESCOMP = %s', tool) end end function make.defines(cfg, toolset) _p(' DEFINES +=%s', make.list(table.join(toolset.getdefines(cfg.defines, cfg), toolset.getundefines(cfg.undefines)))) end function make.forceInclude(cfg, toolset) local includes = toolset.getforceincludes(cfg) if not cfg.flags.NoPCH and cfg.pchheader then table.insert(includes, 1, "-include $(OBJDIR)/$(notdir $(PCH))") end _x(' FORCE_INCLUDE +=%s', make.list(includes)) end function make.includes(cfg, toolset) local includes = toolset.getincludedirs(cfg, cfg.includedirs, cfg.sysincludedirs) _p(' INCLUDES +=%s', make.list(includes)) end function make.ldDeps(cfg, toolset) local deps = config.getlinks(cfg, "siblings", "fullpath") _p(' LDDEPS +=%s', make.list(p.esc(deps))) end function make.ldFlags(cfg, toolset) local flags = table.join(toolset.getLibraryDirectories(cfg), toolset.getrunpathdirs(cfg, cfg.runpathdirs), toolset.getldflags(cfg), cfg.linkoptions) _p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(flags)) end function make.libs(cfg, toolset) local flags = toolset.getlinks(cfg) _p(' LIBS +=%s', make.list(flags, true)) end function make.linkCmd(cfg, toolset) if cfg.kind == p.STATICLIB then if cfg.architecture == p.UNIVERSAL then _p(' LINKCMD = libtool -o "$@" $(OBJECTS)') else _p(' LINKCMD = $(AR) ' .. (toolset.arargs or '-rcs') ..' "$@" $(OBJECTS)') end elseif cfg.kind == p.UTILITY then _p(' LINKCMD =') else local cc = iif(p.languages.isc(cfg.language), "CC", "CXX") _p(' LINKCMD = $(%s) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)', cc) end end function make.pch(cfg, toolset) if not cfg.pchheader or cfg.flags.NoPCH then return end local pch = cfg.pchheader local found = false local testname = path.join(cfg.project.basedir, pch) if os.isfile(testname) then pch = project.getrelative(cfg.project, testname) found = true else for _, incdir in ipairs(cfg.includedirs) do testname = path.join(incdir, pch) if os.isfile(testname) then pch = project.getrelative(cfg.project, testname) found = true break end end end if not found then pch = project.getrelative(cfg.project, path.getabsolute(pch)) end _x(' PCH = %s', pch) _p(' GCH = $(OBJDIR)/$(notdir $(PCH)).gch') end function make.pchRules(prj) _p('ifneq (,$(PCH))') _p('$(OBJECTS): $(GCH) $(PCH) | $(OBJDIR)') _p('$(GCH): $(PCH) | $(OBJDIR)') _p('\t@echo $(notdir $<)') local cmd = iif(prj.language == "C", "$(CC) -x c-header $(ALL_CFLAGS)", "$(CXX) -x c++-header $(ALL_CXXFLAGS)") _p('\t$(SILENT) %s -o "$@" -MF "$(@:%%.gch=%%.d)" -c "$<"', cmd) _p('else') _p('$(OBJECTS): | $(OBJDIR)') _p('endif') _p('') end function make.resFlags(cfg, toolset) local resflags = table.join(toolset.getdefines(cfg.resdefines), toolset.getincludedirs(cfg, cfg.resincludedirs), cfg.resoptions) _p(' ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)%s', make.list(resflags)) end local p = premake local m = p.modules.self_test local _ = {} function m.runTest(test) local failed = 0 local failedTests = {} local suites = m.getSuites() local suitesKeys, suiteTestsKeys, totalTestCount = _.preprocessTests(suites, test) _.log(term.lightGreen, "[==========]", string.format(" Running %d tests from %d test suites.", totalTestCount, #suitesKeys)) local startTime = os.clock() for index, suiteName in ipairs(suitesKeys) do suite = suites[suiteName] if not m.isSuppressed(suiteName) then local test = { suiteName = suiteName, suite = suite } local suiteFailed, suiteFailedTests = _.runTestSuite(test, suiteTestsKeys[suiteName]) failed = failed + suiteFailed failedTests = table.join(failedTests, suiteFailedTests) end end _.log(term.lightGreen, "[==========]", string.format(" %d tests from %d test suites ran. (%.0f ms total)", totalTestCount, #suitesKeys, (os.clock() - startTime) * 1000)) _.log(term.lightGreen, "[ PASSED ]", string.format(" %d tests.", totalTestCount - failed)) if failed > 0 then _.log(term.lightRed, "[ FAILED ]", string.format(" %d tests, listed below:", failed)) for index, testName in ipairs(failedTests) do _.log(term.lightRed, "[ FAILED ]", " " .. testName) end end return (totalTestCount - failed), failed end function _.runTestSuite(test, keys) local failed = 0 local failedTests = {} _.log(term.lightGreen, "[----------]", string.format(" %d tests from %s", #keys, test.suiteName)) local startTime = os.clock() if test.suite ~= nil then for index, testName in ipairs(keys) do testFunction = test.suite[testName] test.testName = testName test.testFunction = testFunction if m.isValid(test) and not m.isSuppressed(test.suiteName .. "." .. test.testName) then local err = _.runTest(test) if err then failed = failed + 1 table.insert(failedTests, test.suiteName .. "." .. test.testName .. "\n" .. err) end end end end _.log(term.lightGreen, "[----------]", string.format(" %d tests from %s (%.0f ms total)\n", #keys, test.suiteName, (os.clock() - startTime) * 1000)) return failed, failedTests end function _.runTest(test) _.log(term.lightGreen, "[ RUN ]", string.format(" %s.%s", test.suiteName, test.testName)) local startTime = os.clock() local cwd = os.getcwd() local hooks = _.installTestingHooks() _TESTS_DIR = test.suite._TESTS_DIR _SCRIPT_DIR = test.suite._SCRIPT_DIR m.suiteName = test.suiteName m.testName = test.testName local ok, err = _.setupTest(test) if ok then ok, err = _.executeTest(test) end local tok, terr = _.teardownTest(test) ok = ok and tok err = err or terr _.removeTestingHooks(hooks) os.chdir(cwd) if ok then _.log(term.lightGreen, "[ OK ]", string.format(" %s.%s (%.0f ms)", test.suiteName, test.testName, (os.clock() - startTime) * 1000)) return nil else _.log(term.lightRed, "[ FAILED ]", string.format(" %s.%s (%.0f ms)", test.suiteName, test.testName, (os.clock() - startTime) * 1000)) m.print(string.format("%s", err)) return err end end function _.log(color, left, right) term.pushColor(color) io.write(left) term.popColor() m.print(right) end function _.preprocessTests(suites, filter) local suitesKeys = {} local suiteTestsKeys = {} local totalTestCount = 0 for suiteName, suite in pairs(suites) do if not m.isSuppressed(suiteName) and suite ~= nil and (not filter.suiteName or filter.suiteName == suiteName) then local test = {} table.insertsorted(suitesKeys, suiteName) test.suiteName = suiteName test.suite = suite suiteTestsKeys[suiteName] = {} for testName, testFunction in pairs(suite) do test.testName = testName test.testFunction = testFunction if m.isValid(test) and not m.isSuppressed(test.suiteName .. "." .. test.testName) and (not filter.testName or filter.testName == testName) then table.insertsorted(suiteTestsKeys[suiteName], testName) end end totalTestCount = totalTestCount + #suiteTestsKeys[suiteName] end end return suitesKeys, suiteTestsKeys, totalTestCount end function _.installTestingHooks() local hooks = {} hooks.action = _ACTION hooks.options = _OPTIONS hooks.targetOs = _TARGET_OS hooks.io_open = io.open hooks.io_output = io.output hooks.os_writefile_ifnotequal = os.writefile_ifnotequal hooks.p_utf8 = p.utf8 hooks.print = print hooks.setTextColor = term.setTextColor local mt = getmetatable(io.stderr) _.builtin_write = mt.write mt.write = _.stub_stderr_write _OPTIONS = table.shallowcopy(_OPTIONS) or {} setmetatable(_OPTIONS, getmetatable(hooks.options)) io.open = _.stub_io_open io.output = _.stub_io_output os.writefile_ifnotequal = _.stub_os_writefile_ifnotequal print = _.stub_print p.utf8 = _.stub_utf8 term.setTextColor = _.stub_setTextColor stderr_capture = nil p.clearWarnings() p.eol("\n") p.escaper(nil) p.indent("\t") p.api.reset() m.stderr_capture = nil m.value_openedfilename = nil m.value_openedfilemode = nil m.value_closedfile = false return hooks end function _.removeTestingHooks(hooks) p.action.set(hooks.action) _OPTIONS = hooks.options _TARGET_OS = hooks.targetOs io.open = hooks.io_open io.output = hooks.io_output os.writefile_ifnotequal = hooks.os_writefile_ifnotequal p.utf8 = hooks.p_utf8 print = hooks.print term.setTextColor = hooks.setTextColor local mt = getmetatable(io.stderr) mt.write = _.builtin_write end function _.setupTest(test) if type(test.suite.setup) == "function" then return xpcall(test.suite.setup, _.errorHandler) else return true end end function _.executeTest(test) local result, err p.capture(function() result, err = xpcall(test.testFunction, _.errorHandler) end) return result, err end function _.teardownTest(test) if type(test.suite.teardown) == "function" then return xpcall(test.suite.teardown, _.errorHandler) else return true end end function _.errorHandler(err) local msg = err if not msg:find("stack traceback:", 1, true) then msg = debug.traceback(err, 2) end local i = msg:find("[C]: in function 'xpcall'", 1, true) if i then msg = msg:sub(1, i - 3) end local n = select(2, msg:gsub('\n', '\n')) if n == 2 then msg = msg:sub(1, msg:find('\n', 1, true) - 1) end return msg end function _.stub_io_open(fname, mode) m.value_openedfilename = fname m.value_openedfilemode = mode return { read = function() end, close = function() m.value_closedfile = true end } end function _.stub_io_output(f) end function _.stub_os_writefile_ifnotequal(content, fname) m.value_openedfilename = fname m.value_closedfile = true return 0 end function _.stub_print(s) end function _.stub_stderr_write(...) if select(1, ...) == io.stderr then m.stderr_capture = (m.stderr_capture or "") .. select(2, ...) else return _.builtin_write(...) end end function _.stub_utf8() end function _.stub_setTextColor() end HxSlocal p = premake p.api = {} local api = p.api local configset = p.configset api.scope = {} function api.container(containerName, parentContainer, extraScopes) local class, err = p.container.newClass(containerName, parentContainer, extraScopes) if not class then error(err, 2) end _G[containerName] = function(name) local c = api._setContainer(class, name) if api._isIncludingExternal then c.external = true end return c end _G["external" .. containerName] = function(name) local c = _G[containerName](name) c.external = true return c end p.alias(_G, "external" .. containerName, "external" .. containerName:capitalized()) return class end function includeexternal(fname) local fullPath = p.findProjectScript(fname) local wasIncludingExternal = api._isIncludingExternal api._isIncludingExternal = true fname = fullPath or fname dofile(fname) api._isIncludingExternal = wasIncludingExternal end p.alias(_G, "includeexternal", "includeExternal") function api.rootContainer() return api.scope.global end function api._setContainer(class, name) local instance if name == "*" then return api._setContainer(class.parent) end if not name then instance = api.scope[class.name] if not instance then error("no " .. class.name .. " in scope", 3) end end local parent if not instance and class.parent then parent = api.scope[class.parent.name] if not parent then error("no " .. class.parent.name .. " in scope", 3) end instance = p.container.getChild(parent, class, name) end if instance then configset.addFilter(instance, {}, os.getcwd()) end if not instance then instance = class.new(name, parent) if parent then p.container.addChild(parent, instance) end end api._clearContainerChildren(class) if not class.placeholder then api.scope.current = instance end while instance do api.scope[instance.class.name] = instance if instance.class.alias then api.scope[instance.class.alias] = instance end instance = instance.parent end return api.scope.current end function api._clearContainerChildren(class) for childClass in p.container.eachChildClass(class) do api.scope[childClass.name] = nil if childClass.alias then api.scope[childClass.alias] = nil end api._clearContainerChildren(childClass) end end function api.register(field) local name = field.name if not name then error("missing name", 2) end if rawget(_G, name) then error("name '" .. name .. "' in use", 2) end field, err = p.field.new(field) if not field then error(err) end field.paths = p.field.property(field, "paths") if type(field.allowed) == "table" then for i, item in ipairs(field.allowed) do field.allowed[item:lower()] = item end end if type(field.aliases) == "table" then local keys = table.keys(field.aliases) for i, key in ipairs(keys) do field.aliases[key:lower()] = field.aliases[key] end end _G[name] = function(value) return api.storeField(field, value) end if p.field.removes(field) then _G["remove" .. name] = function(value) return api.remove(field, value) end end return field end function api.unregister(field) if type(field) == "string" then field = p.field.get(field) end p.field.unregister(field) _G[field.name] = nil _G["remove" .. field.name] = nil end function api.alias(original, alias) p.alias(_G, original, alias) if _G["remove" .. original] then p.alias(_G, "remove" .. original, "remove" .. alias) end end function api.addAllowed(fieldName, value) local field = p.field.get(fieldName) if not field then error("No such field: " .. fieldName, 2) end if type(value) == "table" then for i, item in ipairs(value) do api.addAllowed(fieldName, item) end else field.allowed = field.allowed or {} if field.allowed[value:lower()] == nil then table.insert(field.allowed, value) field.allowed[value:lower()] = value end end end function api.addAliases(fieldName, value) local field = p.field.get(fieldName) if not field then error("No such field: " .. fieldName, 2) end field.aliases = field.aliases or {} for k, v in pairs(value) do field.aliases[k] = v field.aliases[k:lower()] = v end end function api.deprecateField(name, message, handler) p.fields[name].deprecated = { handler = handler, message = message } end function api.deprecateValue(name, value, message, addHandler, removeHandler) if type(value) == "table" then for _, v in pairs(value) do api.deprecateValue(name, v, message, addHandler, removeHandler) end else local field = p.fields[name] field.deprecated = field.deprecated or {} field.deprecated[value] = { add = addHandler, remove = removeHandler, message = message } end end function api.deprecations(value) value = value:lower() if not table.contains({ "on", "off", "error"}, value) then error("Invalid value: " .. value, 2) end api._deprecations = value:lower() end api._deprecations = "on" function api.target(field) if p.container.classCanContain(api.scope.current.class, field.scope) then return api.scope.current end return nil end function api.storeField(field, value) if value == nil then return end if field.deprecated and type(field.deprecated.handler) == "function" then field.deprecated.handler(value) if field.deprecated.message and api._deprecations ~= "off" then local caller = filelineinfo(2) local key = field.name .. "_" .. caller p.warnOnce(key, "the field %s has been deprecated and will be removed.\n %s\n @%s\n", field.name, field.deprecated.message, caller) if api._deprecations == "error" then error("deprecation errors enabled", 3) end end end local target = api.target(field) if not target then local err = string.format("unable to set %s in %s scope, should be %s", field.name, api.scope.current.class.name, table.concat(field.scopes, ", ")) error(err, 3) end local status, err = configset.store(target, field, value) if err then error(err, 3) end end function api.remove(field, value) if value == nil then return end local target = api.target(field) if not target then local err = string.format("unable to remove %s from %s scope, should be %s", field.name, api.scope.current.class.name, table.concat(field.scopes, ", ")) error(err, 3) end local hasDeprecatedValues = (type(field.deprecated) == "table") local removes = {} local function check(value) if field.deprecated[value] then local handler = field.deprecated[value] if handler.remove then handler.remove(value) end if handler.message and api._deprecations ~= "off" then local caller = filelineinfo(8) local key = field.name .. "_" .. value .. "_" .. caller p.warnOnce(key, "the %s value %s has been deprecated and will be removed.\n %s\n @%s\n", field.name, value, handler.message, caller) if api._deprecations == "error" then error { msg="deprecation errors enabled" } end end end end local function recurse(value) if type(value) == "table" then table.foreachi(value, recurse) elseif hasDeprecatedValues and value:contains("*") then local current = configset.fetch(target, field, { matcher = function(cset, block, filter) local current = cset.current return criteria.matches(current._criteria, block._criteria.terms or {}) or criteria.matches(block._criteria, current._criteria.terms or {}) end }) local mask = path.wildcards(value) for _, item in ipairs(current) do if item:match(mask) == item then recurse(item) end end else local value, err, additional = api.checkValue(field, value) if err then error { msg=err } end if field.deprecated then check(value) end table.insert(removes, value) if additional then table.insert(removes, additional) end end end local ok, err = pcall(function () recurse(value) end) if not ok then if type(err) == "table" then err = err.msg end error(err, 3) end configset.remove(target, field, removes) end function api.checkValue(field, value, kind) if not field.allowed then return value end local canonical, result local lowerValue = value:lower() if field.aliases then canonical = field.aliases[lowerValue] end if not canonical then if type(field.allowed) == "function" then canonical = field.allowed(value, kind or "string") else canonical = field.allowed[lowerValue] end end if not canonical then return nil, "invalid value '" .. value .. "' for " .. field.name end if field.deprecated and field.deprecated[canonical] then local handler = field.deprecated[canonical] handler.add(canonical) if handler.message and api._deprecations ~= "off" then local caller = filelineinfo(9) local key = field.name .. "_" .. value .. "_" .. caller p.warnOnce(key, "the %s value %s has been deprecated and will be removed.\n %s\n @%s\n", field.name, canonical, handler.message, caller) if api._deprecations == "error" then return nil, "deprecation errors enabled" end end end return canonical end local numBuiltInGlobalBlocks function api.reset() if numBuiltInGlobalBlocks == nil then numBuiltInGlobalBlocks = #api.scope.global.blocks end for containerClass in p.container.eachChildClass(p.global) do api.scope.global[containerClass.pluralName] = {} end api.scope.current = api.scope.global local currentGlobalBlockCount = #api.scope.global.blocks for i = currentGlobalBlockCount, numBuiltInGlobalBlocks, -1 do table.remove(api.scope.global.blocks, i) end configset.addFilter(api.scope.current, {}, os.getcwd()) end premake.field.kind("array", { store = function(field, current, value, processor) if type(value) ~= "table" then value = { value } end for i, item in ipairs(value) do value[i] = processor(field, nil, value[i]) end return value end, compare = function(field, a, b, processor) if a == nil or b == nil or #a ~= #b then return false end for i = 1, #a do if not processor(field, a[i], b[i]) then return false end end return true end }) premake.field.kind("boolean", { store = function(field, current, value, processor) local mapping = { ["false"] = false, ["no"] = false, ["off"] = false, ["on"] = true, ["true"] = true, ["yes"] = true, } if type(value) == "string" then value = mapping[value:lower()] if value == nil then error { msg="expected boolean; got " .. value } end return value end if type(value) == "boolean" then return value end if type(value) == "number" then return (value ~= 0) end return (value ~= nil) end, compare = function(field, a, b, processor) return (a == b) end }) premake.field.kind("directory", { paths = true, store = function(field, current, value, processor) return path.getabsolute(value) end, remove = function(field, current, value, processor) return path.getabsolute(value) end, compare = function(field, a, b, processor) return (a == b) end, translate = function(field, current, _, processor) if current:find("*") then return os.matchdirs(current) end return { current } end }) premake.field.kind("file", { paths = true, store = function(field, current, value, processor) return path.getabsolute(value) end, remove = function(field, current, value, processor) return path.getabsolute(value) end, compare = function(field, a, b, processor) return (a == b) end, translate = function(field, current, _, processor) if current:find("*") then return os.matchfiles(current) end return { current } end }) premake.field.kind("function", { store = function(field, current, value, processor) local t = type(value) if t ~= "function" then error { msg="expected function; got " .. t } end return value end, compare = function(field, a, b, processor) return (a == b) end }) premake.field.kind("integer", { store = function(field, current, value, processor) local t = type(value) if t ~= "number" then error { msg="expected number; got " .. t } end if math.floor(value) ~= value then error { msg="expected integer; got " .. tostring(value) } end return value end, compare = function(field, a, b, processor) return (a == b) end }) local function storeKeyed(field, current, value, processor) current = current or {} for k, v in pairs(value) do if processor then v = processor(field, current[k], v) end current[k] = v end return current end local function mergeKeyed(field, current, value, processor) value = value or {} for k, v in pairs(value) do current[k] = v end return current end premake.field.kind("keyed", { store = storeKeyed, merge = mergeKeyed, compare = function(field, a, b, processor) if a == nil or b == nil then return false end for k in pairs(a) do if not processor(field, a[k], b[k]) then return false end end return true end, translate = function(field, current, _, processor) if not processor then return { current } end for k, v in pairs(current) do current[k] = processor(field, v, nil)[1] end return { current } end }) local function storeListItem(current, item, allowDuplicates) if not allowDuplicates and current[item] then table.remove(current, table.indexof(current, item)) end table.insert(current, item) current[item] = item end local function storeList(field, current, value, processor) if type(value) == "table" then if #value > 0 then for i = 1, #value do current = storeList(field, current, value[i], processor) end return current end if table.isempty(value) then return current end end current = current or {} if processor then value = processor(field, nil, value) end if type(value) == "table" then if #value > 0 then for i = 1, #value do storeListItem(current, value[i], field.allowDuplicates) end elseif not table.isempty(value) then storeListItem(current, value, field.allowDuplicates) end elseif value then storeListItem(current, value, field.allowDuplicates) end return current end local function mergeList(field, current, value, processor) value = value or {} for i = 1, #value do storeListItem(current, value[i], field.allowDuplicates) end return current end premake.field.kind("list", { store = storeList, remove = storeList, merge = mergeList, compare = function(field, a, b, processor) if a == nil or b == nil or #a ~= #b then return false end for i = 1, #a do if not processor(field, a[i], b[i]) then return false end end return true end, translate = function(field, current, _, processor) if not processor then return { current } end local ret = {} for _, value in ipairs(current) do for _, processed in ipairs(processor(field, value, nil)) do table.insert(ret, processed) end end return { ret } end }) premake.field.kind("mixed", { paths = true, store = function(field, current, value, processor) if type(value) == "string" and value:find('/', nil, true) then if string.sub(value, 1, 2) ~= "%{" then value = path.getabsolute(value) end end return value end, compare = function(field, a, b, processor) return (a == b) end }) premake.field.kind("number", { store = function(field, current, value, processor) local t = type(value) if t ~= "number" then error { msg="expected number; got " .. t } end return value end, compare = function(field, a, b, processor) return (a == b) end }) premake.field.kind("path", { paths = true, store = function(field, current, value, processor) return path.deferredjoin(os.getcwd(), value) end, compare = function(field, a, b, processor) return (a == b) end }) premake.field.kind("string", { store = function(field, current, value, processor) if type(value) == "table" then error { msg="expected string; got table" } end if value ~= nil then local err value, err = api.checkValue(field, value) if err then error { msg=err } end end return value end, compare = function(field, a, b, processor) return (a == b) end }) premake.field.kind("table", { store = function(field, current, value, processor) if type(value) ~= "table" then value = { value } end return value end, compare = function(field, a, b, processor) return true end }) function configuration(terms) if terms then if (type(terms) == "table" and #terms == 1 and terms[1] == "*") or (terms == "*") then terms = nil end configset.addblock(api.scope.current, {terms}, os.getcwd()) end return api.scope.current end function filter(terms) if terms then if (type(terms) == "table" and #terms == 1 and terms[1] == "*") or (terms == "*") then terms = nil end local ok, err = configset.addFilter(api.scope.current, {terms}, os.getcwd()) if not ok then error(err, 2) end end end function newaction(a) p.action.add(a) end function newoption(opt) p.option.add(opt) end local p = premake local m = p.vstudio.cs2005 local dn = p.vstudio.dotnetbase m.elements.userProjectPropertyGroup = function() return { m.referencePath, } end m.elements.userConfigPropertyGroup = function() return { m.localDebuggerCommandArguments, } end function m.generateUser(prj) local prjGroup = p.capture(function() p.push(2) p.callArray(m.elements.userProjectPropertyGroup, prj) p.pop(2) end) local contents = {} local size = 0 for cfg in p.project.eachconfig(prj) do contents[cfg] = p.capture(function() p.push(2) p.callArray(m.elements.userConfigPropertyGroup, cfg) p.pop(2) end) size = size + #contents[cfg] end if #prjGroup > 0 or size > 0 then p.vstudio.projectElement() if #prjGroup > 0 then p.push('') p.outln(prjGroup) p.pop('') end for cfg in p.project.eachconfig(prj) do if #contents[cfg] > 0 then p.push('', dn.condition(cfg)) p.outln(contents[cfg]) p.pop('') end end p.pop('') end end function m.referencePath(prj) local cfg = p.project.getfirstconfig(prj) local paths = p.vstudio.path(prj, cfg.libdirs) if #paths > 0 then p.w('%s', table.concat(paths, ";")) end end function m.localDebuggerCommandArguments(cfg) if #cfg.debugargs > 0 then p.x('%s', table.concat(cfg.debugargs, " ")) end end local p = premake p.raw = { } local raw = p.raw local gvisited = { } function raw.workspace(wks) if not gvisited[wks.global] then gvisited[wks.global] = true raw.printTable({ global = wks.global }) end end function raw.printTable(t, i) i = i or 0 placement = raw._createPlacement(t) raw._printTableRecursive(t, i, placement) end function raw._printTableRecursive(t, i, placement) elements = { } for k, v in pairs(t) do table.insert(elements, { key = k, value = v }) end table.sort(elements, function(a, b) local n1 = type(a.key) == "number" local n2 = type(b.key) == "number" if n1 ~= n2 then return n1 end local k1 = n1 and a.key or raw._encode(a.key) local k2 = n2 and b.key or raw._encode(b.key) return k1 < k2 end) for _, elem in ipairs(elements) do p = placement[elem.value] if p and elem.key == p.key and t == p.parent then _p(i, "%s", raw._encode(elem.key) .. ': ' .. raw._encode(elem.value) .. ' {') raw._printTableRecursive(elem.value, i + 1, placement) _p(i, '} # ' .. raw._encode(elem.key)) else _p(i, "%s", raw._encode(elem.key) .. ': ' .. raw._encode(elem.value)) end end end function raw._createPlacement(tbl) placement = { } placementList = { tbl } while #placementList ~= 0 do parentList = { } for _, parent in ipairs(placementList) do for k, v in pairs(parent) do if type(v) == "table" and not placement[v] then table.insert(parentList, v) placement[v] = { parent = parent, key = k } end end end placementList = parentList end return placement end function raw._encode(v) if type(v) == "string" then return '"' .. v .. '"' else return tostring(v) end end LxSlocal VERSION = '20161109.21' -- version history at end of file local AUTHOR_NOTE = "-[ JSON.lua package by Jeffrey Friedl (http://regex.info/blog/lua/json) version 20161109.21 ]-" local OBJDEF = { VERSION = VERSION, AUTHOR_NOTE = AUTHOR_NOTE, } local default_pretty_indent = " " local default_pretty_options = { pretty = true, align_keys = false, indent = default_pretty_indent } local isArray = { __tostring = function() return "JSON array" end } isArray.__index = isArray local isObject = { __tostring = function() return "JSON object" end } isObject.__index = isObject function OBJDEF:newArray(tbl) return setmetatable(tbl or {}, isArray) end function OBJDEF:newObject(tbl) return setmetatable(tbl or {}, isObject) end local function getnum(op) return type(op) == 'number' and op or op.N end local isNumber = { __tostring = function(T) return T.S end, __unm = function(op) return getnum(op) end, __concat = function(op1, op2) return tostring(op1) .. tostring(op2) end, __add = function(op1, op2) return getnum(op1) + getnum(op2) end, __sub = function(op1, op2) return getnum(op1) - getnum(op2) end, __mul = function(op1, op2) return getnum(op1) * getnum(op2) end, __div = function(op1, op2) return getnum(op1) / getnum(op2) end, __mod = function(op1, op2) return getnum(op1) % getnum(op2) end, __pow = function(op1, op2) return getnum(op1) ^ getnum(op2) end, __lt = function(op1, op2) return getnum(op1) < getnum(op2) end, __eq = function(op1, op2) return getnum(op1) == getnum(op2) end, __le = function(op1, op2) return getnum(op1) <= getnum(op2) end, } isNumber.__index = isNumber function OBJDEF:asNumber(item) if getmetatable(item) == isNumber then -- it's already a JSON number object. return item elseif type(item) == 'table' and type(item.S) == 'string' and type(item.N) == 'number' then -- it's a number-object table that lost its metatable, so give it one return setmetatable(item, isNumber) else -- the normal situation... given a number or a string representation of a number.... local holder = { S = tostring(item), -- S is the representation of the number as a string, which remains precise N = tonumber(item), -- N is the number as a Lua number. } return setmetatable(holder, isNumber) end end function OBJDEF:forceString(item) if type(item) == 'table' and type(item.S) == 'string' then return item.S else return tostring(item) end end function OBJDEF:forceNumber(item) if type(item) == 'table' and type(item.N) == 'number' then return item.N else return tonumber(item) end end local function unicode_codepoint_as_utf8(codepoint) -- -- codepoint is a number -- if codepoint <= 127 then return string.char(codepoint) elseif codepoint <= 2047 then -- -- 110yyyxx 10xxxxxx <-- useful notation from http://en.wikipedia.org/wiki/Utf8 -- local highpart = math.floor(codepoint / 0x40) local lowpart = codepoint - (0x40 * highpart) return string.char(0xC0 + highpart, 0x80 + lowpart) elseif codepoint <= 65535 then -- -- 1110yyyy 10yyyyxx 10xxxxxx -- local highpart = math.floor(codepoint / 0x1000) local remainder = codepoint - 0x1000 * highpart local midpart = math.floor(remainder / 0x40) local lowpart = remainder - 0x40 * midpart highpart = 0xE0 + highpart midpart = 0x80 + midpart lowpart = 0x80 + lowpart -- -- Check for an invalid character (thanks Andy R. at Adobe). -- See table 3.7, page 93, in http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#G28070 -- if ( highpart == 0xE0 and midpart < 0xA0 ) or ( highpart == 0xED and midpart > 0x9F ) or ( highpart == 0xF0 and midpart < 0x90 ) or ( highpart == 0xF4 and midpart > 0x8F ) then return "?" else return string.char(highpart, midpart, lowpart) end else -- -- 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx -- local highpart = math.floor(codepoint / 0x40000) local remainder = codepoint - 0x40000 * highpart local midA = math.floor(remainder / 0x1000) remainder = remainder - 0x1000 * midA local midB = math.floor(remainder / 0x40) local lowpart = remainder - 0x40 * midB return string.char(0xF0 + highpart, 0x80 + midA, 0x80 + midB, 0x80 + lowpart) end end function OBJDEF:onDecodeError(message, text, location, etc) if text then if location then message = string.format("%s at byte %d of: %s", message, location, text) else message = string.format("%s: %s", message, text) end end if etc ~= nil then message = message .. " (" .. OBJDEF:encode(etc) .. ")" end if self.assert then self.assert(false, message) else assert(false, message) end end function OBJDEF:onTrailingGarbage(json_text, location, parsed_value, etc) return self:onDecodeError("trailing garbage", json_text, location, etc) end OBJDEF.onDecodeOfNilError = OBJDEF.onDecodeError OBJDEF.onDecodeOfHTMLError = OBJDEF.onDecodeError function OBJDEF:onEncodeError(message, etc) if etc ~= nil then message = message .. " (" .. OBJDEF:encode(etc) .. ")" end if self.assert then self.assert(false, message) else assert(false, message) end end local function grok_number(self, text, start, options) -- -- Grab the integer part -- local integer_part = text:match('^-?[1-9]%d*', start) or text:match("^-?0", start) if not integer_part then self:onDecodeError("expected number", text, start, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end local i = start + integer_part:len() -- -- Grab an optional decimal part -- local decimal_part = text:match('^%.%d+', i) or "" i = i + decimal_part:len() -- -- Grab an optional exponential part -- local exponent_part = text:match('^[eE][-+]?%d+', i) or "" i = i + exponent_part:len() local full_number_text = integer_part .. decimal_part .. exponent_part if options.decodeNumbersAsObjects then return OBJDEF:asNumber(full_number_text), i end -- -- If we're told to stringify under certain conditions, so do. -- We punt a bit when there's an exponent by just stringifying no matter what. -- I suppose we should really look to see whether the exponent is actually big enough one -- way or the other to trip stringification, but I'll be lazy about it until someone asks. -- if (options.decodeIntegerStringificationLength and (integer_part:len() >= options.decodeIntegerStringificationLength or exponent_part:len() > 0)) or (options.decodeDecimalStringificationLength and (decimal_part:len() >= options.decodeDecimalStringificationLength or exponent_part:len() > 0)) then return full_number_text, i -- this returns the exact string representation seen in the original JSON end local as_number = tonumber(full_number_text) if not as_number then self:onDecodeError("bad number", text, start, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end return as_number, i end local function grok_string(self, text, start, options) if text:sub(start,start) ~= '"' then self:onDecodeError("expected string's opening quote", text, start, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end local i = start + 1 -- +1 to bypass the initial quote local text_len = text:len() local VALUE = "" while i <= text_len do local c = text:sub(i,i) if c == '"' then return VALUE, i + 1 end if c ~= '\\' then VALUE = VALUE .. c i = i + 1 elseif text:match('^\\b', i) then VALUE = VALUE .. "\b" i = i + 2 elseif text:match('^\\f', i) then VALUE = VALUE .. "\f" i = i + 2 elseif text:match('^\\n', i) then VALUE = VALUE .. "\n" i = i + 2 elseif text:match('^\\r', i) then VALUE = VALUE .. "\r" i = i + 2 elseif text:match('^\\t', i) then VALUE = VALUE .. "\t" i = i + 2 else local hex = text:match('^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i) if hex then i = i + 6 -- bypass what we just read -- We have a Unicode codepoint. It could be standalone, or if in the proper range and -- followed by another in a specific range, it'll be a two-code surrogate pair. local codepoint = tonumber(hex, 16) if codepoint >= 0xD800 and codepoint <= 0xDBFF then -- it's a hi surrogate... see whether we have a following low local lo_surrogate = text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i) if lo_surrogate then i = i + 6 -- bypass the low surrogate we just read codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16) else -- not a proper low, so we'll just leave the first codepoint as is and spit it out. end end VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint) else -- just pass through what's escaped VALUE = VALUE .. text:match('^\\(.)', i) i = i + 2 end end end self:onDecodeError("unclosed string", text, start, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end local function skip_whitespace(text, start) local _, match_end = text:find("^[ \n\r\t]+", start) -- [http://www.ietf.org/rfc/rfc4627.txt] Section 2 if match_end then return match_end + 1 else return start end end local grok_one -- assigned later local function grok_object(self, text, start, options) if text:sub(start,start) ~= '{' then self:onDecodeError("expected '{'", text, start, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end local i = skip_whitespace(text, start + 1) -- +1 to skip the '{' local VALUE = self.strictTypes and self:newObject { } or { } if text:sub(i,i) == '}' then return VALUE, i + 1 end local text_len = text:len() while i <= text_len do local key, new_i = grok_string(self, text, i, options) i = skip_whitespace(text, new_i) if text:sub(i, i) ~= ':' then self:onDecodeError("expected colon", text, i, options.etc) return nil, i -- in case the error method doesn't abort, return something sensible end i = skip_whitespace(text, i + 1) local new_val, new_i = grok_one(self, text, i, options) VALUE[key] = new_val -- -- Expect now either '}' to end things, or a ',' to allow us to continue. -- i = skip_whitespace(text, new_i) local c = text:sub(i,i) if c == '}' then return VALUE, i + 1 end if text:sub(i, i) ~= ',' then self:onDecodeError("expected comma or '}'", text, i, options.etc) return nil, i -- in case the error method doesn't abort, return something sensible end i = skip_whitespace(text, i + 1) end self:onDecodeError("unclosed '{'", text, start, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end local function grok_array(self, text, start, options) if text:sub(start,start) ~= '[' then self:onDecodeError("expected '['", text, start, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end local i = skip_whitespace(text, start + 1) -- +1 to skip the '[' local VALUE = self.strictTypes and self:newArray { } or { } if text:sub(i,i) == ']' then return VALUE, i + 1 end local VALUE_INDEX = 1 local text_len = text:len() while i <= text_len do local val, new_i = grok_one(self, text, i, options) -- can't table.insert(VALUE, val) here because it's a no-op if val is nil VALUE[VALUE_INDEX] = val VALUE_INDEX = VALUE_INDEX + 1 i = skip_whitespace(text, new_i) -- -- Expect now either ']' to end things, or a ',' to allow us to continue. -- local c = text:sub(i,i) if c == ']' then return VALUE, i + 1 end if text:sub(i, i) ~= ',' then self:onDecodeError("expected comma or ']'", text, i, options.etc) return nil, i -- in case the error method doesn't abort, return something sensible end i = skip_whitespace(text, i + 1) end self:onDecodeError("unclosed '['", text, start, options.etc) return nil, i -- in case the error method doesn't abort, return something sensible end grok_one = function(self, text, start, options) -- Skip any whitespace start = skip_whitespace(text, start) if start > text:len() then self:onDecodeError("unexpected end of string", text, nil, options.etc) return nil, start -- in case the error method doesn't abort, return something sensible end if text:find('^"', start) then return grok_string(self, text, start, options.etc) elseif text:find('^[-0123456789 ]', start) then return grok_number(self, text, start, options) elseif text:find('^%{', start) then return grok_object(self, text, start, options) elseif text:find('^%[', start) then return grok_array(self, text, start, options) elseif text:find('^true', start) then return true, start + 4 elseif text:find('^false', start) then return false, start + 5 elseif text:find('^null', start) then return nil, start + 4 else self:onDecodeError("can't parse JSON", text, start, options.etc) return nil, 1 -- in case the error method doesn't abort, return something sensible end end function OBJDEF:decode(text, etc, options) -- -- If the user didn't pass in a table of decode options, make an empty one. -- if type(options) ~= 'table' then options = {} end -- -- If they passed in an 'etc' argument, stuff it into the options. -- (If not, any 'etc' field in the options they passed in remains to be used) -- if etc ~= nil then options.etc = etc end if type(self) ~= 'table' or self.__index ~= OBJDEF then local error_message = "JSON:decode must be called in method format" OBJDEF:onDecodeError(error_message, nil, nil, options.etc) return nil, error_message -- in case the error method doesn't abort, return something sensible end if text == nil then local error_message = "nil passed to JSON:decode()" self:onDecodeOfNilError(error_message, nil, nil, options.etc) return nil, error_message -- in case the error method doesn't abort, return something sensible elseif type(text) ~= 'string' then local error_message = "expected string argument to JSON:decode()" self:onDecodeError(string.format("%s, got %s", error_message, type(text)), nil, nil, options.etc) return nil, error_message -- in case the error method doesn't abort, return something sensible end if text:match('^%s*$') then -- an empty string is nothing, but not an error return nil end if text:match('^%s*<') then -- Can't be JSON... we'll assume it's HTML local error_message = "HTML passed to JSON:decode()" self:onDecodeOfHTMLError(error_message, text, nil, options.etc) return nil, error_message -- in case the error method doesn't abort, return something sensible end -- -- Ensure that it's not UTF-32 or UTF-16. -- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3), -- but this package can't handle them. -- if text:sub(1,1):byte() == 0 or (text:len() >= 2 and text:sub(2,2):byte() == 0) then local error_message = "JSON package groks only UTF-8, sorry" self:onDecodeError(error_message, text, nil, options.etc) return nil, error_message -- in case the error method doesn't abort, return something sensible end -- -- apply global options -- if options.decodeNumbersAsObjects == nil then options.decodeNumbersAsObjects = self.decodeNumbersAsObjects end if options.decodeIntegerStringificationLength == nil then options.decodeIntegerStringificationLength = self.decodeIntegerStringificationLength end if options.decodeDecimalStringificationLength == nil then options.decodeDecimalStringificationLength = self.decodeDecimalStringificationLength end -- -- Finally, go parse it -- local success, value, next_i = pcall(grok_one, self, text, 1, options) if success then local error_message = nil if next_i ~= #text + 1 then -- something's left over after we parsed the first thing.... whitespace is allowed. next_i = skip_whitespace(text, next_i) -- if we have something left over now, it's trailing garbage if next_i ~= #text + 1 then value, error_message = self:onTrailingGarbage(text, next_i, value, options.etc) end end return value, error_message else -- If JSON:onDecodeError() didn't abort out of the pcall, we'll have received -- the error message here as "value", so pass it along as an assert. local error_message = value if self.assert then self.assert(false, error_message) else assert(false, error_message) end -- ...and if we're still here (because the assert didn't throw an error), -- return a nil and throw the error message on as a second arg return nil, error_message end end local function backslash_replacement_function(c) if c == "\n" then return "\\n" elseif c == "\r" then return "\\r" elseif c == "\t" then return "\\t" elseif c == "\b" then return "\\b" elseif c == "\f" then return "\\f" elseif c == '"' then return '\\"' elseif c == '\\' then return '\\\\' else return string.format("\\u%04x", c:byte()) end end local chars_to_be_escaped_in_JSON_string = '[' .. '"' -- class sub-pattern to match a double quote .. '%\\' -- class sub-pattern to match a backslash .. '%z' -- class sub-pattern to match a null .. '\001' .. '-' .. '\031' -- class sub-pattern to match control characters .. ']' local LINE_SEPARATOR_as_utf8 = unicode_codepoint_as_utf8(0x2028) local PARAGRAPH_SEPARATOR_as_utf8 = unicode_codepoint_as_utf8(0x2029) local function json_string_literal(value, options) local newval = value:gsub(chars_to_be_escaped_in_JSON_string, backslash_replacement_function) if options.stringsAreUtf8 then -- -- This feels really ugly to just look into a string for the sequence of bytes that we know to be a particular utf8 character, -- but utf8 was designed purposefully to make this kind of thing possible. Still, feels dirty. -- I'd rather decode the byte stream into a character stream, but it's not technically needed so -- not technically worth it. -- newval = newval:gsub(LINE_SEPARATOR_as_utf8, '\\u2028'):gsub(PARAGRAPH_SEPARATOR_as_utf8,'\\u2029') end return '"' .. newval .. '"' end local function object_or_array(self, T, etc) -- -- We need to inspect all the keys... if there are any strings, we'll convert to a JSON -- object. If there are only numbers, it's a JSON array. -- -- If we'll be converting to a JSON object, we'll want to sort the keys so that the -- end result is deterministic. -- local string_keys = { } local number_keys = { } local number_keys_must_be_strings = false local maximum_number_key for key in pairs(T) do if type(key) == 'string' then table.insert(string_keys, key) elseif type(key) == 'number' then table.insert(number_keys, key) if key <= 0 or key >= math.huge then number_keys_must_be_strings = true elseif not maximum_number_key or key > maximum_number_key then maximum_number_key = key end else self:onEncodeError("can't encode table with a key of type " .. type(key), etc) end end if #string_keys == 0 and not number_keys_must_be_strings then -- -- An empty table, or a numeric-only array -- if #number_keys > 0 then return nil, maximum_number_key -- an array elseif tostring(T) == "JSON array" then return nil elseif tostring(T) == "JSON object" then return { } else -- have to guess, so we'll pick array, since empty arrays are likely more common than empty objects return nil end end table.sort(string_keys) local map if #number_keys > 0 then -- -- If we're here then we have either mixed string/number keys, or numbers inappropriate for a JSON array -- It's not ideal, but we'll turn the numbers into strings so that we can at least create a JSON object. -- if self.noKeyConversion then self:onEncodeError("a table with both numeric and string keys could be an object or array; aborting", etc) end -- -- Have to make a shallow copy of the source table so we can remap the numeric keys to be strings -- map = { } for key, val in pairs(T) do map[key] = val end table.sort(number_keys) -- -- Throw numeric keys in there as strings -- for _, number_key in ipairs(number_keys) do local string_key = tostring(number_key) if map[string_key] == nil then table.insert(string_keys , string_key) map[string_key] = T[number_key] else self:onEncodeError("conflict converting table with mixed-type keys into a JSON object: key " .. number_key .. " exists both as a string and a number.", etc) end end end return string_keys, nil, map end local encode_value -- must predeclare because it calls itself function encode_value(self, value, parents, etc, options, indent, for_key) -- -- keys in a JSON object can never be null, so we don't even consider options.null when converting a key value -- if value == nil or (not for_key and options and options.null and value == options.null) then return 'null' elseif type(value) == 'string' then return json_string_literal(value, options) elseif type(value) == 'number' then if value ~= value then -- -- NaN (Not a Number). -- JSON has no NaN, so we have to fudge the best we can. This should really be a package option. -- return "null" elseif value >= math.huge then -- -- Positive infinity. JSON has no INF, so we have to fudge the best we can. This should -- really be a package option. Note: at least with some implementations, positive infinity -- is both ">= math.huge" and "<= -math.huge", which makes no sense but that's how it is. -- Negative infinity is properly "<= -math.huge". So, we must be sure to check the ">=" -- case first. -- return "1e+9999" elseif value <= -math.huge then -- -- Negative infinity. -- JSON has no INF, so we have to fudge the best we can. This should really be a package option. -- return "-1e+9999" else return tostring(value) end elseif type(value) == 'boolean' then return tostring(value) elseif type(value) ~= 'table' then self:onEncodeError("can't convert " .. type(value) .. " to JSON", etc) elseif getmetatable(value) == isNumber then return tostring(value) else -- -- A table to be converted to either a JSON object or array. -- local T = value if type(options) ~= 'table' then options = {} end if type(indent) ~= 'string' then indent = "" end if parents[T] then self:onEncodeError("table " .. tostring(T) .. " is a child of itself", etc) else parents[T] = true end local result_value local object_keys, maximum_number_key, map = object_or_array(self, T, etc) if maximum_number_key then -- -- An array... -- local ITEMS = { } for i = 1, maximum_number_key do table.insert(ITEMS, encode_value(self, T[i], parents, etc, options, indent)) end if options.pretty then result_value = "[ " .. table.concat(ITEMS, ", ") .. " ]" else result_value = "[" .. table.concat(ITEMS, ",") .. "]" end elseif object_keys then -- -- An object -- local TT = map or T if options.pretty then local KEYS = { } local max_key_length = 0 for _, key in ipairs(object_keys) do local encoded = encode_value(self, tostring(key), parents, etc, options, indent, true) if options.align_keys then max_key_length = math.max(max_key_length, #encoded) end table.insert(KEYS, encoded) end local key_indent = indent .. tostring(options.indent or "") local subtable_indent = key_indent .. string.rep(" ", max_key_length) .. (options.align_keys and " " or "") local FORMAT = "%s%" .. string.format("%d", max_key_length) .. "s: %s" local COMBINED_PARTS = { } for i, key in ipairs(object_keys) do local encoded_val = encode_value(self, TT[key], parents, etc, options, subtable_indent) table.insert(COMBINED_PARTS, string.format(FORMAT, key_indent, KEYS[i], encoded_val)) end result_value = "{\n" .. table.concat(COMBINED_PARTS, ",\n") .. "\n" .. indent .. "}" else local PARTS = { } for _, key in ipairs(object_keys) do local encoded_val = encode_value(self, TT[key], parents, etc, options, indent) local encoded_key = encode_value(self, tostring(key), parents, etc, options, indent, true) table.insert(PARTS, string.format("%s:%s", encoded_key, encoded_val)) end result_value = "{" .. table.concat(PARTS, ",") .. "}" end else -- -- An empty array/object... we'll treat it as an array, though it should really be an option -- result_value = "[]" end parents[T] = false return result_value end end local function top_level_encode(self, value, etc, options) local val = encode_value(self, value, {}, etc, options) if val == nil then --PRIVATE("may need to revert to the previous public verison if I can't figure out what the guy wanted") return val else return val end end function OBJDEF:encode(value, etc, options) if type(self) ~= 'table' or self.__index ~= OBJDEF then OBJDEF:onEncodeError("JSON:encode must be called in method format", etc) end -- -- If the user didn't pass in a table of decode options, make an empty one. -- if type(options) ~= 'table' then options = {} end return top_level_encode(self, value, etc, options) end function OBJDEF:encode_pretty(value, etc, options) if type(self) ~= 'table' or self.__index ~= OBJDEF then OBJDEF:onEncodeError("JSON:encode_pretty must be called in method format", etc) end -- -- If the user didn't pass in a table of decode options, use the default pretty ones -- if type(options) ~= 'table' then options = default_pretty_options end return top_level_encode(self, value, etc, options) end function OBJDEF.__tostring() return "JSON encode/decode package" end OBJDEF.__index = OBJDEF function OBJDEF:new(args) local new = { } if args then for key, val in pairs(args) do new[key] = val end end return setmetatable(new, OBJDEF) end return OBJDEF:new() local p = premake p.vstudio.dotnetbase = {} local vstudio = p.vstudio local dotnetbase = p.vstudio.dotnetbase local project = p.project local config = p.config local fileconfig = p.fileconfig local dotnet = p.tools.dotnet dotnetbase.elements = {} dotnetbase.langObj = {} function dotnetbase.prepare(langObj) dotnetbase.elements.project = langObj.elements.project dotnetbase.elements.projectProperties = langObj.elements.projectProperties dotnetbase.elements.configuration = langObj.elements.configuration dotnetbase.langObj = langObj end function dotnetbase.generate(prj) p.utf8() p.callArray(dotnetbase.elements.project, prj) _p(1,'') dotnetbase.files(prj) _p(1,'') dotnetbase.projectReferences(prj) dotnetbase.packageReferences(prj) dotnetbase.langObj.targets(prj) dotnetbase.buildEvents(prj) p.out('') end function dotnetbase.projectElement(prj) local ver = '' local action = p.action.current() if action.vstudio.toolsVersion then ver = string.format(' ToolsVersion="%s"', action.vstudio.toolsVersion) end _p('', ver) end function dotnetbase.projectProperties(prj) _p(1,'') local cfg = project.getfirstconfig(prj) p.callArray(dotnetbase.elements.projectProperties, cfg) _p(1,'') end function dotnetbase.configurations(prj) for cfg in project.eachconfig(prj) do dotnetbase.configuration(cfg) end end function dotnetbase.configuration(cfg) p.callArray(dotnetbase.elements.configuration, cfg) _p(1,'') end function dotnetbase.dofile(node, cfg, condition) local filecfg = fileconfig.getconfig(node, cfg) if filecfg then local fname = path.translate(node.relpath) local link, count = node.relpath:gsub("%.%.%/", "") local external = (count > 0) if external and node.vpath ~= node.relpath then link = node.vpath end local info = dotnet.fileinfo(filecfg) local contents = p.capture(function () local elements = { "AutoGen", "CopyToOutputDirectory", "DesignTime", "DependentUpon", "DesignTimeSharedInput", "Generator", "LastGenOutput", "SubType", } for _, el in ipairs(elements) do local value = info[el] if value then _p(3,"<%s>%s", el, value, el) end end if info.action == "EmbeddedResource" and cfg.customtoolnamespace then _p(3,"%s", cfg.customtoolnamespace) end end) if #contents > 0 or external then _p(2,'<%s%s Include="%s">', info.action, condition, fname) if external then _p(3,'%s', path.translate(link)) end if #contents > 0 then _p("%s", contents) end _p(2,'', info.action) else _p(2,'<%s%s Include="%s" />', info.action, condition, fname) end end end function dotnetbase.files(prj) local firstcfg = project.getfirstconfig(prj) local processfcfg = function(node) local allsame = true local first = nil for cfg in project.eachconfig(prj) do local filecfg = fileconfig.getconfig(node, cfg) local info = dotnet.fileinfo(filecfg) if first == nil then first = info elseif not table.equals(first, info) then allsame = false end end if allsame then dotnetbase.dofile(node, firstcfg, '') else for cfg in project.eachconfig(prj) do dotnetbase.dofile(node, cfg, ' ' .. dotnetbase.condition(cfg)) end end end if project.isfsharp(prj) then sorter = function(a,b) verbosef('Sorting F# proj file (%s, %s), index %s < %s', a.name, b.name, a.order, b.order) return a.order < b.order end table.sort(prj._.files, sorter) table.foreachi(prj._.files, processfcfg) else local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = processfcfg }, false) end end function dotnetbase.buildEvents(prj) local function output(name, steps) if #steps > 0 then steps = os.translateCommandsAndPaths(steps, prj.basedir, prj.location) steps = table.implode(steps, "", "", "\r\n") _x(2,'<%sBuildEvent>%s', name, steps, name) end end local cfg = project.getfirstconfig(prj) if #cfg.prebuildcommands > 0 or #cfg.postbuildcommands > 0 then _p(1,'') output("Pre", cfg.prebuildcommands) output("Post", cfg.postbuildcommands) _p(1,'') end end function dotnetbase.compilerProps(cfg) _x(2,'%s', table.concat(cfg.defines, ";")) _p(2,'prompt') _p(2,'4') if cfg.clr == "Unsafe" then _p(2,'true') end if cfg.flags.FatalCompileWarnings then _p(2,'true') end dotnetbase.debugCommandParameters(cfg) end function dotnetbase.debugCommandParameters(cfg) if #cfg.debugargs > 0 then _x(2,'%s', table.concat(cfg.debugargs, " ")) end end function dotnetbase.debugProps(cfg) if cfg.symbols == p.ON then _p(2,'true') _p(2,'full') else _p(2,'pdbonly') end _p(2,'%s', iif(config.isOptimizedBuild(cfg), "true", "false")) end function dotnetbase.outputProps(cfg) local outdir = vstudio.path(cfg, cfg.buildtarget.directory) _x(2,'%s\\', outdir) local objdir = vstudio.path(cfg, cfg.objdir) if _ACTION > "vs2008" then _x(2,'%s\\', objdir) _p(2,'$(BaseIntermediateOutputPath)') else _x(2,'%s\\', objdir) end end dotnetbase.elements.references = function(prj) return { dotnetbase.assemblyReferences, dotnetbase.nuGetReferences, } end function dotnetbase.references(prj) _p(1,'') p.callArray(dotnetbase.elements.references, prj) _p(1,'') end function dotnetbase.assemblyReferences(prj) local cfg = project.getfirstconfig(prj) config.getlinks(cfg, "system", function(original, decorated) local name = path.getname(decorated) if path.getextension(name) == ".dll" then name = name.sub(name, 1, -5) end if decorated:find("/", nil, true) then _x(2,'', name) local decPath, decVars = decorated:match("(.-),") if not decPath then decPath = decorated end _x(3,'%s', path.appendextension(path.translate(decPath), ".dll")) if not config.isCopyLocal(prj, original, true) then _p(3,"False") end _p(2,'') else _x(2,'', name) end end) end function dotnetbase.makeVersionComparable(version) local numbers = "" for number in version:gmatch("%d") do numbers = numbers .. number end return string.format("%-10d", numbers):gsub(" ", "0") end function dotnetbase.frameworkVersionForFolder(folder) if folder:match("^net%d+$") or folder:match("^[0-9%.]+$") then return dotnetbase.makeVersionComparable(folder) elseif folder == "net" then return dotnetbase.makeVersionComparable("0") end end function dotnetbase.nuGetReferences(prj) if _ACTION >= "vs2010" and not vstudio.nuget2010.supportsPackageReferences(prj) then for _, package in ipairs(prj.nuget) do local id = vstudio.nuget2010.packageId(package) local packageAPIInfo = vstudio.nuget2010.packageAPIInfo(prj, package) local cfg = p.project.getfirstconfig(prj) local action = p.action.current() local targetFramework = cfg.dotnetframework or action.vstudio.targetFramework local targetVersion = dotnetbase.makeVersionComparable(targetFramework) local files = {} local bestVersion, bestFolder for _, file in ipairs(packageAPIInfo.packageEntries) do local folder = file:match("^lib[\\/](.+)[\\/]") if folder and path.hasextension(file, ".dll") then local version = dotnetbase.frameworkVersionForFolder(folder) if version then files[folder] = files[folder] or {} table.insert(files[folder], file) if version <= targetVersion and (not bestVersion or version > bestVersion) then bestVersion = version bestFolder = folder end end end end if not bestVersion then p.error("NuGet package '%s' is not compatible with project '%s' .NET Framework version '%s'", id, prj.name, targetFramework) end for _, file in ipairs(files[bestFolder]) do _x(2, '', path.getbasename(file)) _x(3, '%s', vstudio.path(prj, p.filename(prj.workspace, string.format("packages\\%s.%s\\%s", id, packageAPIInfo.verbatimVersion or packageAPIInfo.version, file)))) if config.isCopyLocal(prj, package, true) then _p(3, 'True') else _p(3, 'False') end _p(2, '') end end end end function dotnetbase.projectReferences(prj) _p(1,'') local deps = project.getdependencies(prj, 'linkOnly') if #deps > 0 then for _, dep in ipairs(deps) do local relpath = vstudio.path(prj, vstudio.projectfile(dep)) _x(2,'', relpath) _p(3,'{%s}', dep.uuid) _x(3,'%s', dep.name) if not config.isCopyLocal(prj, dep.name, true) then _p(3,"False") end _p(2,'') end end _p(1,'') end function dotnetbase.packageReferences(prj) if vstudio.nuget2010.supportsPackageReferences(prj) then local hasNuget = prj.nuget and #prj.nuget>0 for cfg in project.eachconfig(prj) do if cfg.nuget and #cfg.nuget>0 then hasNuget = true end end if hasNuget then _p(1,'') if prj.nuget and #prj.nuget>0 then for _, package in ipairs(prj.nuget) do _p(2,'', vstudio.nuget2010.packageId(package), vstudio.nuget2010.packageVersion(package)) end end for cfg in project.eachconfig(prj) do if cfg.nuget and #cfg.nuget>0 then for _, package in ipairs(cfg.nuget) do if prj.nuget[package]==nil then _p(2,'', vstudio.nuget2010.packageId(package), vstudio.nuget2010.packageVersion(package), dotnetbase.condition(cfg)) end end end end _p(1,'') end end end function dotnetbase.arch(cfg) local arch = vstudio.archFromConfig(cfg) if arch == "Any CPU" then arch = "AnyCPU" end return arch end function dotnetbase.propertyGroup(cfg) p.push('', dotnetbase.condition(cfg)) local arch = dotnetbase.arch(cfg) if arch ~= "AnyCPU" or _ACTION > "vs2008" then p.x('%s', arch) end end function dotnetbase.applicationIcon(prj) if prj.icon then local icon = vstudio.path(prj, prj.icon) _p(1,'') _x(2,'%s', icon) _p(1,'') end end function dotnetbase.condition(cfg) local platform = vstudio.projectPlatform(cfg) local arch = dotnetbase.arch(cfg) return string.format('Condition=" \'$(Configuration)|$(Platform)\' == \'%s|%s\' "', platform, arch) end function dotnetbase.formatNuGetFrameworkVersion(framework) return "net" .. framework:gsub("%.", "") end function dotnetbase.appDesignerFolder(cfg) _p(2,'Properties') end function dotnetbase.assemblyName(cfg) _p(2,'%s', cfg.buildtarget.basename) end function dotnetbase.commonProperties(prj) if _ACTION > "vs2010" then _p(1,'') end end function dotnetbase.configurationCondition(cfg) _x(2,'%s', cfg.buildcfg) end function dotnetbase.fileAlignment(cfg) if _ACTION >= "vs2010" then _p(2,'512') end end function dotnetbase.bindingRedirects(cfg) if _ACTION >= "vs2015" then _p(2, 'true') end end function dotnetbase.outputType(cfg) _p(2,'%s', dotnet.getkind(cfg)) end function dotnetbase.platformCondition(cfg) _p(2,'%s', dotnetbase.arch(cfg.project)) end function dotnetbase.productVersion(cfg) local action = p.action.current() if action.vstudio.productVersion then _p(2,'%s', action.vstudio.productVersion) end end function dotnetbase.projectGuid(cfg) _p(2,'{%s}', cfg.uuid) end function dotnetbase.projectTypeGuids(cfg) if cfg.flags.WPF then _p(2,'{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') end end function dotnetbase.rootNamespace(cfg) _p(2,'%s', cfg.namespace or cfg.buildtarget.basename) end function dotnetbase.schemaVersion(cfg) local action = p.action.current() if action.vstudio.csprojSchemaVersion then _p(2,'%s', action.vstudio.csprojSchemaVersion) end end function dotnetbase.NoWarn(cfg) if #cfg.disablewarnings > 0 then local warnings = table.concat(cfg.disablewarnings, ";") _p(2,'%s', warnings) end end function dotnetbase.targetFrameworkVersion(cfg) local action = p.action.current() local framework = cfg.dotnetframework or action.vstudio.targetFramework if framework then _p(2,'v%s', framework) end end function dotnetbase.csversion(cfg) if cfg.csversion then _p(2,'%s', cfg.csversion) end end function dotnetbase.targetFrameworkProfile(cfg) if _ACTION == "vs2010" then _p(2,'') _p(2,'') end end function dotnetbase.xmlDeclaration() if _ACTION > "vs2008" then p.xmlUtf8() end end local p = premake local m = p.modules.xcode local xcode = p.modules.xcode local project = p.project local config = p.config local fileconfig = p.fileconfig local tree = p.tree function xcode.mustExcludeFromTarget(node, prj) if not node.configs then return false end local value for cfg in premake.project.eachconfig(prj) do local filecfg = premake.fileconfig.getconfig(node, cfg) if filecfg then local newValue = not not filecfg.flags.ExcludeFromBuild if value == nil then value = newValue elseif value ~= newValue then p.warn(node.name .. " is excluded in just some configurations. Autocompletion will not work correctly on this file in Xcode.") return false end end end return value end function xcode.buildprjtree(prj) local tr = project.getsourcetree(prj, nil , false) tr.project = prj tr.configs = {} for cfg in project.eachconfig(prj) do cfg.xcode = {} cfg.xcode.targetid = xcode.newid(prj.xcode.projectnode.name, cfg.buildcfg, "target") cfg.xcode.projectid = xcode.newid(tr.name, cfg.buildcfg) table.insert(tr.configs, cfg) end tree.traverse(tr, { onbranch = function(node) if path.getextension(node.name) == ".lproj" then local lang = path.getbasename(node.name) -- "English", "French", etc. for _, filenode in ipairs(node.children) do local grpnode = node.parent.children[filenode.name] if not grpnode then grpnode = tree.insert(node.parent, tree.new(filenode.name)) grpnode.kind = "vgroup" end filenode.name = path.getbasename(lang) tree.insert(grpnode, filenode) end tree.remove(node) end end }) tr.frameworks = tree.new("Frameworks") for cfg in project.eachconfig(prj) do for _, link in ipairs(config.getlinks(cfg, "system", "fullpath")) do local name = path.getname(link) if xcode.isframework(name) and not tr.frameworks.children[name] then node = tree.insert(tr.frameworks, tree.new(name)) node.path = link end end end if #tr.frameworks.children > 0 then tree.insert(tr, tr.frameworks) end tr.products = tree.insert(tr, tree.new("Products")) tr.projects = tree.new("Projects") for _, dep in ipairs(project.getdependencies(prj, "linkOnly")) do xcode.addDependency(prj, tr, dep, true) end for _, dep in ipairs(project.getdependencies(prj, "dependOnly")) do xcode.addDependency(prj, tr, dep, false) end if #tr.projects.children > 0 then tree.insert(tr, tr.projects) end tree.traverse(tr, { onnode = function(node) local nodePath if node.path then nodePath = path.getrelative(tr.project.location, node.path) end node.id = xcode.newid(node.name, nil, nodePath) node.isResource = xcode.isItemResource(prj, node) if node.configs then for cfg in project.eachconfig(prj) do local filecfg = fileconfig.getconfig(node, cfg) if fileconfig.hasCustomBuildRule(filecfg) then if not node.buildcommandid then node.buildcommandid = xcode.newid(node.name, "buildcommand", nodePath) end end end end if xcode.getbuildcategory(node) and not node.excludefrombuild and not xcode.mustExcludeFromTarget(node, tr.project) then node.buildid = xcode.newid(node.name, "build", nodePath) end if string.endswith(node.name, "Info.plist") then tr.infoplist = node end end }, true) node = tree.insert(tr.products, prj.xcode.projectnode) node.kind = "product" node.path = node.cfg.buildtarget.fullpath node.cfgsection = xcode.newid(node.name, "cfg") node.resstageid = xcode.newid(node.name, "rez") node.sourcesid = xcode.newid(node.name, "src") node.fxstageid = xcode.newid(node.name, "fxs") return tr end function xcode.addDependency(prj, tr, dep, build) local xcpath = xcode.getxcodeprojname(dep) local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath))) xcnode.path = xcpath xcnode.project = dep xcnode.productgroupid = xcode.newid(xcnode.name, "prodgrp") xcnode.productproxyid = xcode.newid(xcnode.name, "prodprox") xcnode.targetproxyid = xcode.newid(xcnode.name, "targprox") xcnode.targetdependid = xcode.newid(xcnode.name, "targdep") local lprj = p.workspace.findproject(prj.workspace, dep.name) local cfg = project.findClosestMatch(lprj, prj.configurations[1]) node = tree.insert(xcnode, tree.new(cfg.linktarget.name)) node.path = cfg.linktarget.fullpath node.cfg = cfg if build == false then node.excludefrombuild = true end end m.elements.project = function(prj) return { m.header, } end function m.generateProject(prj) local tr = xcode.buildprjtree(prj) p.callArray(m.elements.project, prj) xcode.PBXBuildFile(tr) xcode.PBXContainerItemProxy(tr) xcode.PBXFileReference(tr) xcode.PBXFrameworksBuildPhase(tr) xcode.PBXGroup(tr) xcode.PBXNativeTarget(tr) xcode.PBXAggregateTarget(tr) xcode.PBXProject(tr) xcode.PBXReferenceProxy(tr) xcode.PBXResourcesBuildPhase(tr) xcode.PBXShellScriptBuildPhase(tr) xcode.PBXSourcesBuildPhase(tr) xcode.PBXTargetDependency(tr) xcode.PBXVariantGroup(tr) xcode.XCBuildConfiguration(tr) xcode.XCBuildConfigurationList(tr) xcode.footer(prj) end function m.header(prj) p.w('// !$*UTF8*$!') p.push('{') p.w('archiveVersion = 1;') p.w('classes = {') p.w('};') p.w('objectVersion = 46;') p.push('objects = {') p.w() end function xcode.footer(prj) p.pop('};') p.w('rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;') p.pop('}') end local p = premake p.make.makefile = {} local make = p.make local makefile = p.make.makefile local project = p.project local config = p.config local fileconfig = p.fileconfig makefile.elements = {} makefile.elements.makefile = { "header", "phonyRules", "makefileConfigs", "makefileTargetRules" } function make.makefile.generate(prj) p.eol("\n") p.callarray(make, makefile.elements.makefile, prj) end makefile.elements.configuration = { "target", "buildCommands", "cleanCommands", } function make.makefileConfigs(prj) for cfg in project.eachconfig(prj) do local toolset = p.tools[cfg.toolset or "gcc"] if not toolset then error("Invalid toolset '" .. cfg.toolset .. "'") end _x('ifeq ($(config),%s)', cfg.shortname) p.callarray(make, makefile.elements.configuration, cfg, toolset) _p('endif') _p('') end end function make.makefileTargetRules(prj) _p('$(TARGET):') _p('\t$(BUILDCMDS)') _p('') _p('clean:') _p('\t$(CLEANCMDS)') _p('') end function make.buildCommands(cfg) _p(' define BUILDCMDS') local steps = cfg.buildcommands if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) _p('\t@echo Running build commands') _p('\t%s', table.implode(steps, "", "", "\n\t")) end _p(' endef') end function make.cleanCommands(cfg) _p(' define CLEANCMDS') local steps = cfg.cleancommands if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) _p('\t@echo Running clean commands') _p('\t%s', table.implode(steps, "", "", "\n\t")) end _p(' endef') end local p = premake p.vstudio.sln2005 = {} local vstudio = p.vstudio local sln2005 = p.vstudio.sln2005 local project = p.project local tree = p.tree sln2005.elements = {} function sln2005.solutionSections(wks) return { "ConfigurationPlatforms", "SolutionProperties", "NestedProjects", "ExtensibilityGlobals" } end function sln2005.generate(wks) p.utf8() p.outln('') sln2005.reorderProjects(wks) sln2005.header() sln2005.projects(wks) p.push('Global') sln2005.sections(wks) p.pop('EndGlobal') p.w() end function sln2005.header() local action = p.action.current() p.w('Microsoft Visual Studio Solution File, Format Version %d.00', action.vstudio.solutionVersion) p.w('# Visual Studio %s', action.vstudio.versionName) end function sln2005.reorderProjects(wks) if wks.startproject then local np local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) if n.project.name == wks.startproject then np = n end end }) while np and np.parent do local p = np.parent local i = table.indexof(p.children, np) table.remove(p.children, i) table.insert(p.children, 1, np) np = p end end end function sln2005.projects(wks) local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) local prj = n.project local prjpath = vstudio.projectfile(prj) prjpath = vstudio.path(prj.workspace, prjpath) prjpath = prjpath:gsub("$%((.-)%)", "%%%1%%") p.x('Project("{%s}") = "%s", "%s", "{%s}"', vstudio.tool(prj), prj.name, prjpath, prj.uuid) p.push() sln2005.projectdependencies(prj) p.pop('EndProject') end, onbranch = function(n) p.push('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "%s", "%s", "{%s}"', n.name, n.name, n.uuid) p.pop('EndProject') end, }) end function sln2005.projectdependencies(prj) local deps = project.getdependencies(prj, 'dependOnly') if #deps > 0 then p.push('ProjectSection(ProjectDependencies) = postProject') for _, dep in ipairs(deps) do p.w('{%s} = {%s}', dep.uuid, dep.uuid) end p.pop('EndProjectSection') end end sln2005.elements.projectConfigurationPlatforms = function(cfg, context) return { sln2005.activeCfg, sln2005.build0, } end function sln2005.projectConfigurationPlatforms(wks, sorted, descriptors) p.w("GlobalSection(ProjectConfigurationPlatforms) = postSolution") local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) local prj = n.project table.foreachi(sorted, function(cfg) local context = {} context.prj = prj context.prjCfg = project.getconfig(prj, cfg.buildcfg, cfg.platform) context.excluded = (context.prjCfg == nil or context.prjCfg.flags.ExcludeFromBuild) if context.prjCfg == nil then context.prjCfg = project.findClosestMatch(prj, cfg.buildcfg, cfg.platform) end context.descriptor = descriptors[cfg] context.platform = vstudio.projectPlatform(context.prjCfg) context.architecture = vstudio.archFromConfig(context.prjCfg, true) p.push() p.callArray(sln2005.elements.projectConfigurationPlatforms, cfg, context) p.pop() end) end }) p.w("EndGlobalSection") end function sln2005.activeCfg(cfg, context) p.w('{%s}.%s.ActiveCfg = %s|%s', context.prj.uuid, context.descriptor, context.platform, context.architecture) end function sln2005.build0(cfg, context) if not context.excluded and context.prjCfg.kind ~= p.NONE then p.w('{%s}.%s.Build.0 = %s|%s', context.prj.uuid, context.descriptor, context.platform, context.architecture) end end function sln2005.configurationPlatforms(wks) local descriptors = {} local sorted = {} for cfg in p.workspace.eachconfig(wks) do local platform = vstudio.solutionPlatform(cfg) descriptors[cfg] = string.format("%s|%s", cfg.buildcfg, platform) table.insert(sorted, cfg) end table.sort(sorted, function(cfg0, cfg1) return descriptors[cfg0]:lower() < descriptors[cfg1]:lower() end) if wks.defaultplatform then p.push('GlobalSection(SolutionConfigurationPlatforms) = preSolution') table.foreachi(sorted, function (cfg) if cfg.platform == wks.defaultplatform then p.w('%s = %s', descriptors[cfg], descriptors[cfg]) end end) p.pop("EndGlobalSection") end p.push('GlobalSection(SolutionConfigurationPlatforms) = preSolution') table.foreachi(sorted, function (cfg) if not wks.defaultplatform or cfg.platform ~= wks.defaultplatform then p.w('%s = %s', descriptors[cfg], descriptors[cfg]) end end) p.pop("EndGlobalSection") sln2005.projectConfigurationPlatforms(wks, sorted, descriptors) end function sln2005.properties(wks) p.push('GlobalSection(SolutionProperties) = preSolution') p.w('HideSolutionNode = FALSE') p.pop('EndGlobalSection') end function sln2005.nestedProjects(wks) local tr = p.workspace.grouptree(wks) if tree.hasbranches(tr) then p.push('GlobalSection(NestedProjects) = preSolution') tree.traverse(tr, { onnode = function(n) if n.parent.uuid then p.w('{%s} = {%s}', (n.project or n).uuid, n.parent.uuid) end end }) p.pop('EndGlobalSection') end end function sln2005.premakeExtensibilityGlobals(wks) if wks.editorintegration then local args = {} for _, arg in ipairs(_ARGV) do if not (arg:startswith("--file") or arg:startswith("/file")) then table.insert(args, arg); end end p.w('PremakeBinary = %s', _PREMAKE_COMMAND) p.w('PremakeScript = %s', p.workspace.getrelative(wks, _MAIN_SCRIPT)) p.w('PremakeArguments = %s', table.concat(args, ' ')) end end sln2005.elements.extensibilityGlobals = function(wks) return { sln2005.premakeExtensibilityGlobals, } end function sln2005.extensibilityGlobals(wks) local contents = p.capture(function () p.push() p.callArray(sln2005.elements.extensibilityGlobals, wks) p.pop() end) if #contents > 0 then p.push('GlobalSection(ExtensibilityGlobals) = postSolution') p.outln(contents) p.pop('EndGlobalSection') end end sln2005.elements.sections = function(wks) return { sln2005.configurationPlatforms, sln2005.properties, sln2005.nestedProjects, sln2005.extensibilityGlobals, } end function sln2005.sections(wks) p.callArray(sln2005.elements.sections, wks) end return {"gmake", "vstudio", "xcode", "codelite", "gmake2", "d", "android"}'S'Spremake.override(os, "execute", function(base, cmd) cmd = os.translateCommands(cmd) return base(cmd) end) function os.executef(cmd, ...) cmd = string.format(cmd, ...) return os.execute(cmd) end local function parse_ld_so_conf(conf_file) local first, last local dirs = { } for line in io.lines(conf_file) do first = line:find("#", 1, true) if first ~= nil then line = line:sub(1, first - 1) end if line ~= "" then first, last = line:find("include%s+") if first ~= nil then local include_glob = line:sub(last + 1) local includes = os.matchfiles(include_glob) for _, v in ipairs(includes) do dirs = table.join(dirs, parse_ld_so_conf(v)) end else table.insert(dirs, line) end end end return dirs end local function get_library_search_path() local path if os.istarget("windows") then path = os.getenv("PATH") or "" elseif os.istarget("haiku") then path = os.getenv("LIBRARY_PATH") or "" else if os.istarget("darwin") then path = os.getenv("DYLD_LIBRARY_PATH") or "" else path = os.getenv("LD_LIBRARY_PATH") or "" for _, prefix in ipairs({"", "/opt"}) do local conf_file = prefix .. "/etc/ld.so.conf" if os.isfile(conf_file) then for _, v in ipairs(parse_ld_so_conf(conf_file)) do if (#path > 0) then path = path .. ":" .. v else path = v end end end end end path = path or "" local archpath = "/lib:/usr/lib:/usr/local/lib" if os.is64bit() and not (os.istarget("darwin")) then archpath = "/lib64:/usr/lib64/:usr/local/lib64" .. ":" .. archpath end if (#path > 0) then path = path .. ":" .. archpath else path = archpath end end return path end function os.findlib(libname, libdirs) local path = get_library_search_path() local formats if os.istarget("windows") then formats = { "%s.dll", "%s" } elseif os.istarget("haiku") then formats = { "lib%s.so", "%s.so" } else if os.istarget("darwin") then formats = { "lib%s.dylib", "%s.dylib" } else formats = { "lib%s.so", "%s.so" } end table.insert(formats, "%s") end local userpath = "" if type(libdirs) == "string" then userpath = libdirs elseif type(libdirs) == "table" then userpath = table.implode(libdirs, "", "", ":") end if (#userpath > 0) then if (#path > 0) then path = userpath .. ":" .. path else path = userpath end end for _, fmt in ipairs(formats) do local name = string.format(fmt, libname) local result = os.pathsearch(name, path) if result then return result end end end function os.findheader(headerpath, headerdirs) local path = get_library_search_path() path = path .. ':' path = path:gsub ('/lib[0-9]*([:/])', '/include%1') path = path:sub (1, #path - 1) local userpath = "" if type(headerdirs) == "string" then userpath = headerdirs elseif type(headerdirs) == "table" then userpath = table.implode(headerdirs, "", "", ":") end if (#userpath > 0) then if (#path > 0) then path = userpath .. ":" .. path else path = userpath end end local result = os.pathsearch (headerpath, path) return result end function os.target() return _OPTIONS.os or _TARGET_OS end function os.get() local caller = filelineinfo(2) premake.warnOnce(caller, "os.get() is deprecated, use 'os.target()' or 'os.host()'.\n @%s\n", caller) return os.target() end _G_metatable = { __index = function(t, k) if (k == '_OS') then premake.warnOnce("_OS+get", "_OS is deprecated, use '_TARGET_OS'.") return rawget(t, "_TARGET_OS") else return rawget(t, k) end end, __newindex = function(t, k, v) if (k == '_OS') then premake.warnOnce("_OS+set", "_OS is deprecated, use '_TARGET_OS'.") rawset(t, "_TARGET_OS", v) else rawset(t, k, v) end end } setmetatable(_G, _G_metatable) function os.istarget(id) local tags = os.getSystemTags(os.target()) return table.contains(tags, id:lower()) end function os.is(id) local caller = filelineinfo(2) premake.warnOnce(caller, "os.is() is deprecated, use 'os.istarget()' or 'os.ishost()'.\n @%s\n", caller) return os.istarget(id) end function os.ishost(id) local tags = os.getSystemTags(os.host()) return table.contains(tags, id:lower()) end premake.override(os, "isdir", function(base, p) p = path.normalize(p) return base(p) end) premake.override(os, "isfile", function(base, p) p = path.normalize(p) return base(p) end) local _is64bit local _64BitHostTypes = { "x86_64", "ia64", "amd64", "ppc64", "powerpc64", "sparc64" } function os.is64bit() if _is64bit ~= nil then return _is64bit end _is64bit = false if (os._is64bit()) then _is64bit = true else local arch if os.ishost("windows") then arch = os.getenv("PROCESSOR_ARCHITECTURE") elseif os.ishost("macosx") then arch = os.outputof("echo $HOSTTYPE") else arch = os.outputof("uname -m") end arch = arch:lower() for _, hosttype in ipairs(_64BitHostTypes) do if arch:find(hosttype) then _is64bit = true end end end return _is64bit end function os.match(mask) mask = path.normalize(mask) local starpos = mask:find("%*") local before = path.getdirectory(starpos and mask:sub(1, starpos - 1) or mask) local slashpos = starpos and mask:find("/", starpos) local after = slashpos and mask:sub(slashpos + 1) local recurse = starpos and mask:sub(starpos + 1, starpos + 1) == '*' and (starpos == 1 or mask:sub(starpos - 1, starpos - 1) == '/') local results = { } if recurse then local submask = mask:sub(1, starpos) .. mask:sub(starpos + 2) results = os.match(submask) local pattern = mask:sub(1, starpos) local m = os.matchstart(pattern) while os.matchnext(m) do if not os.matchisfile(m) then local matchpath = path.join(before, os.matchname(m), mask:sub(starpos)) results = table.join(results, os.match(matchpath)) end end os.matchdone(m) else local pattern = mask:sub(1, slashpos and slashpos - 1) local m = os.matchstart(pattern) while os.matchnext(m) do if not (slashpos and os.matchisfile(m)) then local matchpath = path.join(before, matchpath, os.matchname(m)) if after then results = table.join(results, os.match(path.join(matchpath, after))) else table.insert(results, matchpath) end end end os.matchdone(m) end return results end function os.matchdirs(mask) local results = os.match(mask) for i = #results, 1, -1 do if not os.isdir(results[i]) then table.remove(results, i) end end return results end function os.matchfiles(mask) local results = os.match(mask) for i = #results, 1, -1 do if not os.isfile(results[i]) then table.remove(results, i) end end return results end local builtin_mkdir = os.mkdir function os.mkdir(p) p = path.normalize(p) local dir = iif(p:startswith("/"), "/", "") for part in p:gmatch("[^/]+") do dir = dir .. part if (part ~= "" and not path.isabsolute(part) and not os.isdir(dir)) then local ok, err = builtin_mkdir(dir) if (not ok) then return nil, err end end dir = dir .. "/" end return true end function os.outputof(cmd) cmd = path.normalize(cmd) local pipe = io.popen(cmd .. " 2>&1") local result = pipe:read('*a') local success, what, code = pipe:close() if success then if result then result = string.gsub(result, "[\r\n]+$", "") end return result, code, what else return nil, code, what end end local builtin_remove = os.remove function os.remove(f) if type(f) == "string" then local p = os.matchfiles(f) for _, v in pairs(p) do local ok, err = builtin_remove(v) if not ok then return ok, err end end elseif type(f) == "table" then for _, v in pairs(f) do local ok, err = os.remove(v) if not ok then return ok, err end end end end local builtin_rmdir = os.rmdir function os.rmdir(p) local dirs = os.matchdirs(p .. "/*") for _, dname in ipairs(dirs) do os.rmdir(dname) end local files = os.matchfiles(p .. "/*") for _, fname in ipairs(files) do os.remove(fname) end builtin_rmdir(p) end premake.override(os, "stat", function(base, p) p = path.normalize(p) return base(p) end) os.commandTokens = { _ = { chdir = function(v) return "cd " .. path.normalize(v) end, copy = function(v) return "cp -rf " .. path.normalize(v) end, delete = function(v) return "rm -f " .. path.normalize(v) end, echo = function(v) return "echo " .. v end, mkdir = function(v) return "mkdir -p " .. path.normalize(v) end, move = function(v) return "mv -f " .. path.normalize(v) end, rmdir = function(v) return "rm -rf " .. path.normalize(v) end, touch = function(v) return "touch " .. path.normalize(v) end, }, windows = { chdir = function(v) return "chdir " .. path.translate(path.normalize(v)) end, copy = function(v) v = path.translate(path.normalize(v)) local src = string.match(v, '^".-"') or string.match(v, '^.- ') or v src = string.match(src, '^.*%S') return "IF EXIST " .. src .. "\\ (xcopy /Q /E /Y /I " .. v .. " > nul) ELSE (xcopy /Q /Y /I " .. v .. " > nul)" end, delete = function(v) return "del " .. path.translate(path.normalize(v)) end, echo = function(v) return "echo " .. v end, mkdir = function(v) v = path.translate(path.normalize(v)) return "IF NOT EXIST " .. v .. " (mkdir " .. v .. ")" end, move = function(v) return "move /Y " .. path.translate(path.normalize(v)) end, rmdir = function(v) return "rmdir /S /Q " .. path.translate(path.normalize(v)) end, touch = function(v) v = path.translate(path.normalize(v)) return string.format("type nul >> %s && copy /b %s+,, %s", v, v, v) end, } } function os.translateCommands(cmd, map) map = map or os.target() if type(map) == "string" then map = os.commandTokens[map] or os.commandTokens["_"] end local processOne = function(cmd) local i, j, prev repeat i, j = cmd:find("{.-}") if i then if i == prev then break end local token = cmd:sub(i + 1, j - 1):lower() local args = cmd:sub(j + 2) local func = map[token] or os.commandTokens["_"][token] if func then cmd = cmd:sub(1, i -1) .. func(args) end prev = i end until i == nil return cmd end if type(cmd) == "table" then local result = {} for i = 1, #cmd do result[i] = processOne(cmd[i]) end return result else return processOne(cmd) end end function os.translateCommandAndPath(dir, map) if map == 'windows' then return path.translate(dir) end return dir end function os.translateCommandsAndPaths(cmds, basedir, location, map) local translatedBaseDir = path.getrelative(location, basedir) map = map or os.target() local translateFunction = function(value) local result = path.join(translatedBaseDir, value) result = os.translateCommandAndPath(result, map) if value:endswith('/') or value:endswith('\\') or -- if orginal path ends with a slash then ensure the same value:endswith('/"') or value:endswith('\\"') then result = result .. '/' end return result end local processOne = function(cmd) local replaceFunction = function(value) value = value:sub(3, #value - 1) return '"' .. translateFunction(value) .. '"' end return string.gsub(cmd, "%%%[[^%]\r\n]*%]", replaceFunction) end if type(cmds) == "table" then local result = {} for i = 1, #cmds do result[i] = processOne(cmds[i]) end return os.translateCommands(result, map) else return os.translateCommands(processOne(cmds), map) end end os._uuids = {} local builtin_uuid = os.uuid function os.uuid(name) local id = builtin_uuid(name) if name then if os._uuids[id] and os._uuids[id] ~= name then premake.warnOnce(id, "UUID clash between %s and %s", os._uuids[id], name) end os._uuids[id] = name end return id end os.systemTags = { ["aix"] = { "aix", "posix" }, ["bsd"] = { "bsd", "posix" }, ["haiku"] = { "haiku", "posix" }, ["ios"] = { "ios", "darwin", "posix", "mobile" }, ["linux"] = { "linux", "posix" }, ["macosx"] = { "macosx", "darwin", "posix" }, ["solaris"] = { "solaris", "posix" }, ["windows"] = { "windows", "win32" }, } function os.getSystemTags(name) return os.systemTags[name:lower()] or { name:lower() } end ISlocal p = premake p.vstudio.vs2010.rules.targets = {} local m = p.vstudio.vs2010.rules.targets m.elements = {} m.elements.project = function(r) return { p.vstudio.projectElement, m.availableItemGroup, m.computedProperties, m.computeInputsGroup, m.usingTask, m.ruleTarget, m.computeOutputTarget, } end function m.generate(r) p.xmlUtf8() p.callArray(m.elements.project, r) p.pop() p.out('') end m.elements.availableItemGroup = function(r) return { m.propertyPageSchema, m.availableItemName, } end function m.availableItemGroup(r) p.push('') p.callArray(m.elements.availableItemGroup, r) p.pop('') end function m.computedProperties(r) local pathVars = p.rule.createPathVars(r, "%%(%s)") local ctx = p.context.extent(r, { pathVars = pathVars, overridePathVars = true }) local buildoutputs = ctx.buildoutputs if buildoutputs and #buildoutputs > 0 then local outputs = table.concat(buildoutputs, ";") p.push('') p.push('<%s>', r.name) p.x('%s', path.translate(outputs)) p.pop('', r.name) p.pop('') end end m.elements.computeInputsGroup = function(r) return { m.computeCompileInputsTargets, m.computeLinkInputsTargets, m.computeLibInputsTargets, } end function m.computeInputsGroup(r) p.push('') p.callArray(m.elements.computeInputsGroup, r) p.pop('') end m.elements.ruleTargetAttributes = function(r) return { m.targetName, m.beforeTargets, m.afterTargets, m.targetCondition, m.targetOutputs, m.targetInputs, m.dependsOnTargets, } end m.elements.ruleTarget = function(r) return { m.selectedFiles, m.tlog, m.message, m.tlogWrite, m.tlogRead, m.rule, } end function m.ruleTarget(r) local attribs = p.capture(function() p.push() p.callArray(m.elements.ruleTargetAttributes, r) p.pop() end) p.push('') p.callArray(m.elements.ruleTarget, r) p.pop('') end m.elements.tlog = function(r) return { m.tlogSource, m.tlogInputs, m.tlogProperties, } end function m.tlog(r) p.push('') p.push('<%s_tlog', r.name) p.w('Include="%%(%s.Outputs)"', r.name) p.w('Condition="\'%%(%s.Outputs)\' != \'\' and \'%%(%s.ExcludedFromBuild)\' != \'true\'">', r.name, r.name) p.callArray(m.elements.tlog, r) p.pop('', r.name) p.pop('') end m.elements.ruleAttributes = function(r) return { m.ruleCondition, m.commandLineTemplate, m.properties, m.additionalOptions, m.inputs, m.standardOutputImportance, } end function m.rule(r) local attribs = p.capture(function() p.push() p.callArray(m.elements.ruleAttributes, r) p.pop() end) p.w('<%s', r.name) p.outln(attribs .. ' />') end m.elements.computeOutputItems = function(r) return { m.outputs, m.linkLib, } end m.elements.computeOutputTarget = function(r) return { m.makeDir, } end function m.computeOutputTarget(r) p.push('', r.name) p.push('') p.callArray(m.elements.computeOutputItems, r) p.pop('') p.callArray(m.elements.computeOutputTarget, r) p.pop('') end function m.additionalOptions(r) p.w('AdditionalOptions="%%(%s.AdditionalOptions)"', r.name) end function m.commandLineTemplate(r) p.w('CommandLineTemplate="%%(%s.CommandLineTemplate)"', r.name) end function m.afterTargets(r) p.w('AfterTargets="$(%sAfterTargets)"', r.name) end function m.availableItemName(r) p.push('', r.name) p.w('_%s', r.name) p.pop('') end function m.beforeTargets(r) p.w('BeforeTargets="$(%sBeforeTargets)"', r.name) end function m.computeLibInputsTargets(r) p.push('') p.w('$(ComputeLibInputsTargets);') p.w('Compute%sOutput;', r.name) p.pop('') end function m.computeLinkInputsTargets(r) p.push('') p.w('$(ComputeLinkInputsTargets);') p.w('Compute%sOutput;', r.name) p.pop('') end function m.computeCompileInputsTargets(r) p.push('') p.w('$(ComputeCompileInputsTargets);') p.w('Compute%sOutput;', r.name) p.pop('') end function m.dependsOnTargets(r) p.w('DependsOnTargets="$(%sDependsOn);Compute%sOutput"', r.name, r.name) end function m.inputs(r) p.w('Inputs="%%(%s.Identity)"', r.name) end function m.linkLib(r) local pathVars = p.rule.createPathVars(r, "%%(%s)") local ctx = p.context.extent(r, { pathVars = pathVars, overridePathVars=true }) local buildoutputs = ctx.buildoutputs local linkable, compileable for i = 1, #buildoutputs do if (path.islinkable(buildoutputs[i])) then linkable = true end if (path.iscppfile(buildoutputs[i])) then compileable = true end end if linkable then for i, el in pairs { 'Link', 'Lib', 'ImpLib' } do p.push('<%s', el) p.w('Include="%%(%sOutputs.Identity)"', r.name) p.w('Condition="\'%%(Extension)\'==\'.obj\' or \'%%(Extension)\'==\'.res\' or \'%%(Extension)\'==\'.rsc\' or \'%%(Extension)\'==\'.lib\'" />') p.pop() end end if compileable then p.push('') p.pop() end end function m.makeDir(r) p.w('', r.name) end function m.message(r) p.w('', r.name) end function m.outputs(r) p.w('<%sOutputs', r.name) p.w(' Condition="\'@(%s)\' != \'\' and \'%%(%s.ExcludedFromBuild)\' != \'true\'"', r.name, r.name) p.w(' Include="%%(%s.Outputs)" />', r.name) end function m.properties(r) local defs = r.propertydefinition for i = 1, #defs do local name = defs[i].name p.w('%s="%%(%s.%s)"', name, r.name, name) end end function m.propertyPageSchema(r) p.w('') end function m.ruleCondition(r) p.w('Condition="\'@(%s)\' != \'\' and \'%%(%s.ExcludedFromBuild)\' != \'true\'"', r.name, r.name) end function m.selectedFiles(r) p.push('') p.w('<%s Remove="@(%s)" Condition="\'%%(Identity)\' != \'@(SelectedFiles)\'" />', r.name, r.name) p.pop('') end function m.standardOutputImportance(r) p.w('StandardOutputImportance="High"') p.w('StandardErrorImportance="High"') end function m.targetCondition(r) p.w('Condition="\'@(%s)\' != \'\'"', r.name) end function m.targetInputs(r) local extra = {} local defs = r.propertydefinition for i = 1, #defs do local def = defs[i] if def.dependency then table.insert(extra, string.format("%%(%s.%s);", r.name, def.name)) end end extra = table.concat(extra) p.w('Inputs="%%(%s.Identity);%%(%s.AdditionalDependencies);%s$(MSBuildProjectFile)"', r.name, r.name, extra) end function m.targetName(r) p.w('Name="_%s"', r.name) end function m.targetOutputs(r) p.w('Outputs="%%(%s.Outputs)"', r.name) end function m.tlogInputs(r) p.w("@(%s, ';')", r.name) end function m.tlogProperties(r) local defs = r.propertydefinition for i = 1, #defs do local def = defs[i] if def.dependency then p.w('<%s>%%(%s.%s)', def.name, r.name, def.name, def.name) end end end function m.tlogRead(r) local extra = {} local defs = r.propertydefinition for i = 1, #defs do local def = defs[i] if def.dependency then table.insert(extra, string.format("%%(%s_tlog.%s);", r.name, def.name)) end end extra = table.concat(extra) p.w('', r.name, extra, r.name) end function m.tlogWrite(r) p.w('', r.name, r.name) end function m.tlogSource(r) p.w("@(%s, '|')", r.name) end function m.usingTask(r) p.push('') p.w('$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml') p.pop('') end local p = premake p.modules.raw = {} local m = p.modules.raw m.elements = {} dofile("_preload.lua") dofile("raw_action.lua") return m return { "base/_foundation.lua", "base/string.lua", "base/table.lua", "base/path.lua", "base/os.lua", "base/io.lua", "base/tools.lua", "base/tree.lua", "base/globals.lua", "base/moduledownloader.lua", "base/semver.lua", "base/http.lua", "base/json.lua", "base/jsonwrapper.lua", "base/languages.lua", "base/term.lua", "base/field.lua", "base/criteria.lua", "base/detoken.lua", "base/configset.lua", "base/context.lua", "base/container.lua", "base/option.lua", "base/action.lua", "base/api.lua", "base/global.lua", "base/workspace.lua", "base/group.lua", "base/project.lua", "base/config.lua", "base/fileconfig.lua", "base/rule.lua", "base/oven.lua", "base/validation.lua", "base/premake.lua", "base/help.lua", "tools/dotnet.lua", "tools/gcc.lua", "tools/msc.lua", "tools/snc.lua", "tools/clang.lua", "actions/clean/_clean.lua", "_premake_init.lua", } 0123456789function premake.showhelp() printf("Premake %s, a build script generator", _PREMAKE_VERSION) printf(_PREMAKE_COPYRIGHT) printf("%s %s", _VERSION, _COPYRIGHT) printf("") printf("Usage: premake5 [options] action [arguments]") printf("") local categories = {} for option in premake.option.each() do local cat = "OPTIONS - General" if option.category then cat = "OPTIONS - " .. option.category; end if categories[cat] then table.insert(categories[cat], option) else categories[cat] = {option} end end for k, options in spairs(categories) do printf(k) printf("") local length = 0 for _, option in ipairs(options) do local trigger = option.trigger if (option.value) then trigger = trigger .. "=" .. option.value end if (#trigger > length) then length = #trigger end end for _, option in ipairs(options) do local trigger = option.trigger local description = option.description if (option.value) then trigger = trigger .. "=" .. option.value end if (option.allowed) then description = description .. "; one of:" end printf(" --%-" .. length .. "s %s", trigger, description) if (option.allowed) then local function compareValue(a, b) return a[1] < b[1] end table.sort(option.allowed, compareValue) for _, value in ipairs(option.allowed) do printf(" %-" .. length-1 .. "s %s", value[1], value[2]) end printf("") end end printf("") end printf("ACTIONS") printf("") for action in premake.action.each() do printf(" %-17s %s", action.trigger, action.description) end printf("") printf("For additional information, see https://premake.github.io") end SSSSSSSlocal p = premake local m = p.modules.self_test function m.createWorkspace() local wks = workspace("MyWorkspace") configurations { "Debug", "Release" } local prj = m.createProject(wks) return wks, prj end function m.createsolution() local wks = workspace("MySolution") configurations { "Debug", "Release" } local prj = m.createproject(wks) return wks, prj end function m.createProject(wks) local n = #wks.projects + 1 if n == 1 then n = "" end local prj = project ("MyProject" .. n) language "C++" kind "ConsoleApp" return prj end function m.createGroup(wks) local prj = group ("MyGroup" .. (#wks.groups + 1)) return prj end function m.getWorkspace(wks) p.oven.bake() return p.global.getWorkspace(wks.name) end function m.getRule(name) p.oven.bake() return p.global.getRule(name) end function m.getProject(wks, i) wks = m.getWorkspace(wks) return p.workspace.getproject(wks, i or 1) end function m.getConfig(prj, buildcfg, platform) local wks = m.getWorkspace(prj.workspace) prj = p.workspace.getproject(wks, prj.name) return p.project.getconfig(prj, buildcfg, platform) end m.print = print p.alias(m, "createProject", "createproject") p.alias(m, "getConfig", "getconfig") p.alias(m, "getProject", "getproject") p.alias(m, "getWorkspace", "getsolution") local p = premake p.vstudio.cs2005 = {} local vstudio = p.vstudio local cs2005 = p.vstudio.cs2005 local dotnetbase = p.vstudio.dotnetbase local project = p.project local config = p.config local fileconfig = p.fileconfig local dotnet = p.tools.dotnet cs2005.elements = {} cs2005.elements.project = function () return { dotnetbase.xmlDeclaration, dotnetbase.projectElement, dotnetbase.commonProperties, dotnetbase.projectProperties, dotnetbase.configurations, dotnetbase.applicationIcon, dotnetbase.references } end cs2005.elements.projectProperties = function () return { dotnetbase.configurationCondition, dotnetbase.platformCondition, dotnetbase.productVersion, dotnetbase.schemaVersion, dotnetbase.projectGuid, dotnetbase.outputType, dotnetbase.appDesignerFolder, dotnetbase.rootNamespace, dotnetbase.assemblyName, dotnetbase.targetFrameworkVersion, dotnetbase.targetFrameworkProfile, dotnetbase.fileAlignment, dotnetbase.bindingRedirects, dotnetbase.projectTypeGuids, dotnetbase.csversion } end cs2005.elements.configuration = function () return { dotnetbase.propertyGroup, dotnetbase.debugProps, dotnetbase.outputProps, dotnetbase.compilerProps, dotnetbase.NoWarn } end function cs2005.generate(prj) dotnetbase.prepare(cs2005) dotnetbase.generate(prj) end function cs2005.targets(prj) local bin = iif(_ACTION <= "vs2010", "MSBuildBinPath", "MSBuildToolsPath") _p(1,'', bin) _p(1,'') end local p = premake local project = p.project newaction { trigger = "gmake", shortname = "GNU Make", description = "Generate GNU makefiles for POSIX, MinGW, and Cygwin", toolset = "gcc", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Utility", "Makefile" }, valid_languages = { "C", "C++", "C#" }, valid_tools = { cc = { "clang", "gcc" }, dotnet = { "mono", "msnet", "pnet" } }, onWorkspace = function(wks) p.escaper(p.make.esc) p.generate(wks, p.make.getmakefilename(wks, false), p.make.generate_workspace) end, onProject = function(prj) p.escaper(p.make.esc) local makefile = p.make.getmakefilename(prj, true) if prj.kind == p.UTILITY then p.generate(prj, makefile, p.make.utility.generate) elseif prj.kind == p.MAKEFILE then p.generate(prj, makefile, p.make.makefile.generate) else if project.isdotnet(prj) then p.generate(prj, makefile, p.make.cs.generate) elseif project.isc(prj) or project.iscpp(prj) then p.generate(prj, makefile, p.make.cpp.generate) end end end, onCleanWorkspace = function(wks) p.clean.file(wks, p.make.getmakefilename(wks, false)) end, onCleanProject = function(prj) p.clean.file(prj, p.make.getmakefilename(prj, true)) end } return function(cfg) return (_ACTION == "gmake") end hSlSpStSxS|SSlocal p = premake p.group = p.api.container("group", p.workspace) local group = p.group group.placeholder = true function group.new(name) return p.container.new(group, name) end FPFpFlocal p = premake local android = p.modules.android local vsandroid = p.modules.vsandroid local sln2005 = p.vstudio.sln2005 premake.override(sln2005.elements, "projectConfigurationPlatforms", function(oldfn, cfg, context) local elements = oldfn(cfg, context) if cfg.system == premake.ANDROID and _ACTION >= "vs2015" then elements = table.join(elements, { android.deployProject }) end return elements end) function android.deployProject(cfg, context) if context.prjCfg.kind == p.PACKAGING and _ACTION >= "vs2015" then p.w('{%s}.%s.Deploy.0 = %s|%s', context.prj.uuid, context.descriptor, context.platform, context.architecture) end end ;Zx0N2.5.29.17local shorthelp = "Type 'premake5 --help' for help" local versionhelp = "premake5 (Premake Build Script Generator) %s" local startTime = os.clock() _PREMAKE_STARTTIME = startTime local modules = dofile("_modules.lua") local manifest = dofile("_manifest.lua") for i = 1, #manifest do dofile(manifest[i]) end local p = premake p.main = {} local m = p.main m._preloaded = {} function m.installModuleLoader() if not os.ishost('windows') then local premakeDir = path.getdirectory(_PREMAKE_COMMAND) package.cpath = package.cpath .. ';' .. premakeDir .. '/?.so' end table.insert(package.searchers, 2, m.moduleLoader) end function m.moduleLoader(name) local dir = path.getdirectory(name) local base = path.getname(name) if dir ~= "." then dir = dir .. "/" .. base else dir = base end local full = dir .. "/" .. base .. ".lua" local paths = { ".modules/" .. full, "modules/" .. full, full, name .. ".lua" } for _, p in ipairs(paths) do local file = os.locate(p) if file then local chunk, err = loadfile(file) if chunk then return chunk end if err then return "\n\tload error " .. err end end end for _, p in ipairs(paths) do local chunk, err = loadfile("$/" .. p) if chunk then return chunk end end end function m.prepareEnvironment() math.randomseed(os.time()) _PREMAKE_DIR = path.getdirectory(_PREMAKE_COMMAND) p.path = p.path .. ";" .. _PREMAKE_DIR .. ";" .. _MAIN_SCRIPT_DIR end function m.preloadModules() for i = 1, #modules do local name = modules[i] local preloader = name .. "/_preload.lua" preloader = os.locate("modules/" .. preloader) or os.locate(preloader) if preloader then m._preloaded[name] = include(preloader) if not m._preloaded[name] then p.warn("module '%s' should return function from _preload.lua", name) end else require(name) end end end function m.runSystemScript() dofileopt(_OPTIONS["systemscript"] or { "premake5-system.lua", "premake-system.lua" }) filter {} end function m.locateUserScript() local defaults = { "premake5.lua", "premake4.lua" } for i = 1, #defaults do if os.isfile(defaults[i]) then _MAIN_SCRIPT = defaults[i] break end end if not _MAIN_SCRIPT then _MAIN_SCRIPT = defaults[1] end if _OPTIONS.file then _MAIN_SCRIPT = _OPTIONS.file end _MAIN_SCRIPT = path.getabsolute(_MAIN_SCRIPT) _MAIN_SCRIPT_DIR = path.getdirectory(_MAIN_SCRIPT) end function m.prepareAction() if _ACTION and _ACTION:endswith("ng") then p.warnOnce(_ACTION, "'%s' has been deprecated; use '%s' instead", _ACTION, _ACTION:sub(1, -3)) end p.action.set(_ACTION) local action = p.action.current() if action then p.action.initialize(action.trigger) end end function m.runUserScript() if os.isfile(_MAIN_SCRIPT) then dofile(_MAIN_SCRIPT) end end function m.checkInteractive() if _OPTIONS.interactive then debug.prompt() end end function m.processCommandLine() if (_OPTIONS["version"]) then printf(versionhelp, _PREMAKE_VERSION) os.exit(0) end if (_OPTIONS["help"]) then p.showhelp() os.exit(1) end ok, err = p.option.validate(_OPTIONS) if not ok then print("Error: " .. err) os.exit(1) end if not _OPTIONS.interactive then if not _ACTION then print(shorthelp) os.exit(1) end local action = p.action.current() if not action then print("Error: no such action '" .. _ACTION .. "'") os.exit(1) end if p.action.isConfigurable() and not os.isfile(_MAIN_SCRIPT) then print(string.format("No Premake script (%s) found!", path.getname(_MAIN_SCRIPT))) os.exit(1) end end end function m.tryHookDebugger() if (_OPTIONS["debugger"]) then print("Loading luasocket...") require('luasocket') print("Starting debugger...") local mobdebug = require('mobdebug') mobdebug.start() end end function m.preBake() if p.action.isConfigurable() then print("Building configurations...") end end function m.bake() if p.action.isConfigurable() then p.oven.bake() end end function m.postBake() local function shouldLoad(func) for wks in p.global.eachWorkspace() do for prj in p.workspace.eachproject(wks) do for cfg in p.project.eachconfig(prj) do if func(cfg) then return true end end end end end for module, func in pairs(m._preloaded) do if not package.loaded[module] and shouldLoad(func) then require(module) end end end function m.validate() if p.action.isConfigurable() then p.container.validate(p.api.rootContainer()) end end function m.preAction() local action = p.action.current() printf("Running action '%s'...", action.trigger) end function m.callAction() local action = p.action.current() p.action.call(action.trigger) end function m.postAction() if p.action.isConfigurable() then local duration = math.floor((os.clock() - startTime) * 1000); printf("Done (%dms).", duration) end end m.elements = { m.tryHookDebugger, m.installModuleLoader, m.locateUserScript, m.prepareEnvironment, m.preloadModules, m.runSystemScript, m.prepareAction, m.runUserScript, m.checkInteractive, m.processCommandLine, m.preBake, m.bake, m.postBake, m.validate, m.preAction, m.callAction, m.postAction, } function _premake_main() p.callArray(m.elements) return 0 end local p = premake local gmake2 = p.modules.gmake2 gmake2.utility = {} local utility = gmake2.utility local project = p.project local config = p.config local fileconfig = p.fileconfig utility.elements = {} utility.elements.makefile = function(prj) return { gmake2.header, gmake2.phonyRules, gmake2.shellType, utility.initialize, utility.createFileTable, utility.outputConfigurationSection, utility.outputFilesSection, utility.outputRulesSection, utility.outputFileRuleSection, } end function utility.generate(prj) p.eol("\n") p.callArray(utility.elements.makefile, prj) for cfg in project.eachconfig(prj) do cfg._gmake = nil end prj._gmake = nil end function utility.initialize(prj) prj._gmake = prj._gmake or {} prj._gmake.rules = prj.rules prj._gmake.filesets = { } end function utility.createFileTable(prj) for cfg in project.eachconfig(prj) do cfg._gmake = cfg._gmake or {} cfg._gmake.filesets = {} cfg._gmake.fileRules = {} local files = table.shallowcopy(prj._.files) table.foreachi(files, function(node) utility.addFile(cfg, node, prj) end) for _, f in pairs(cfg._gmake.filesets) do table.sort(f) end cfg._gmake.kinds = table.keys(cfg._gmake.filesets) table.sort(cfg._gmake.kinds) prj._gmake.kinds = table.join(prj._gmake.kinds or {}, cfg._gmake.kinds) end prj._gmake.kinds = table.unique(prj._gmake.kinds) table.sort(prj._gmake.kinds) end function utility.addFile(cfg, node, prj) local filecfg = fileconfig.getconfig(node, cfg) if not filecfg or filecfg.flags.ExcludeFromBuild then return end if node.generated then return end if fileconfig.hasCustomBuildRule(filecfg) then local env = table.shallowcopy(filecfg.environ) env.PathVars = { ["file.basename"] = { absolute = false, token = node.basename }, ["file.abspath"] = { absolute = true, token = node.abspath }, ["file.relpath"] = { absolute = false, token = node.relpath }, ["file.name"] = { absolute = false, token = node.name }, ["file.path"] = { absolute = true, token = node.path }, } local shadowContext = p.context.extent(filecfg, env) local buildoutputs = p.project.getrelative(cfg.project, shadowContext.buildoutputs) if buildoutputs and #buildoutputs > 0 then local file = { buildoutputs = buildoutputs, source = node.relpath, buildmessage = shadowContext.buildmessage, buildcommands = shadowContext.buildcommands, buildinputs = p.project.getrelative(cfg.project, shadowContext.buildinputs) } table.insert(cfg._gmake.fileRules, file) for _, output in ipairs(buildoutputs) do utility.addGeneratedFile(cfg, node, output) end end else utility.addRuleFile(cfg, node) end end function utility.addGeneratedFile(cfg, source, filename) cfg.project.hasGeneratedFiles = true local files = cfg.project._.files local node = files[filename] if not node then node = fileconfig.new(filename, cfg.project) files[filename] = node table.insert(files, node) end node.dependsOn = source node.generated = true if not fileconfig.getconfig(node, cfg) then fileconfig.addconfig(node, cfg) end local filesets = cfg.project._gmake.filesets local kind = "CUSTOM" local fileset = cfg._gmake.filesets[kind] or {} table.insert(fileset, filename) cfg._gmake.filesets[kind] = fileset utility.addRuleFile(cfg, node) end function utility.addRuleFile(cfg, node) local rules = cfg.project._gmake.rules local rule = rules[path.getextension(node.abspath):lower()] if rule then local filecfg = fileconfig.getconfig(node, cfg) local environ = table.shallowcopy(filecfg.environ) if rule.propertydefinition then gmake2.prepareEnvironment(rule, environ, cfg) gmake2.prepareEnvironment(rule, environ, filecfg) end local shadowContext = p.context.extent(rule, environ) local buildoutputs = shadowContext.buildoutputs local buildmessage = shadowContext.buildmessage local buildcommands = shadowContext.buildcommands local buildinputs = shadowContext.buildinputs buildoutputs = p.project.getrelative(cfg.project, buildoutputs) if buildoutputs and #buildoutputs > 0 then local file = { buildoutputs = buildoutputs, source = node.relpath, buildmessage = buildmessage, buildcommands = buildcommands, buildinputs = buildinputs } table.insert(cfg._gmake.fileRules, file) for _, output in ipairs(buildoutputs) do utility.addGeneratedFile(cfg, node, output) end end end end utility.elements.configuration = function(cfg) return { utility.bindirs, utility.exepaths, gmake2.settings, gmake2.preBuildCmds, gmake2.preLinkCmds, gmake2.postBuildCmds, } end function utility.outputConfigurationSection(prj) _p('# Configurations') _p('# #############################################') _p('') gmake2.outputSection(prj, utility.elements.configuration) end function utility.bindirs(cfg, toolset) local dirs = project.getrelative(cfg.project, cfg.bindirs) if #dirs > 0 then p.outln('EXECUTABLE_PATHS = "' .. table.concat(dirs, ":") .. '"') end end function utility.exepaths(cfg, toolset) local dirs = project.getrelative(cfg.project, cfg.bindirs) if #dirs > 0 then p.outln('EXE_PATHS = PATH=$(EXECUTABLE_PATHS):$$PATH;') end end utility.elements.filesets = function(cfg) local result = {} for _, kind in ipairs(cfg._gmake.kinds) do for _, f in ipairs(cfg._gmake.filesets[kind]) do table.insert(result, function(cfg, toolset) utility.outputFileset(cfg, kind, f) end) end end return result end function utility.outputFilesSection(prj) _p('# File sets') _p('# #############################################') _p('') for _, kind in ipairs(prj._gmake.kinds) do _x('%s :=', kind) end _x('') gmake2.outputSection(prj, utility.elements.filesets) end function utility.outputFileset(cfg, kind, file) _x('%s += %s', kind, file) end utility.elements.rules = function(cfg) return { utility.allRules, utility.targetRules, gmake2.targetDirRules, utility.cleanRules, } end function utility.outputRulesSection(prj) _p('# Rules') _p('# #############################################') _p('') gmake2.outputSection(prj, utility.elements.rules) end function utility.allRules(cfg, toolset) local allTargets = 'all: $(TARGETDIR) $(TARGET)' for _, kind in ipairs(cfg._gmake.kinds) do allTargets = allTargets .. ' $(' .. kind .. ')' end _p(allTargets) _p('\t@:') _p('') end function utility.targetRules(cfg, toolset) local targets = '' for _, kind in ipairs(cfg._gmake.kinds) do targets = targets .. '$(' .. kind .. ') ' end _p('$(TARGET): %s', targets) _p('\t$(PREBUILDCMDS)') _p('\t$(PRELINKCMDS)') _p('\t$(POSTBUILDCMDS)') _p('') end function utility.cleanRules(cfg, toolset) _p('clean:') _p('\t@echo Cleaning %s', cfg.project.name) _p('') end utility.elements.fileRules = function(cfg) local funcs = {} for _, fileRule in ipairs(cfg._gmake.fileRules) do table.insert(funcs, function(cfg, toolset) utility.outputFileRules(cfg, fileRule) end) end return funcs end function utility.outputFileRuleSection(prj) _p('# File Rules') _p('# #############################################') _p('') gmake2.outputSection(prj, utility.elements.fileRules) end function utility.outputFileRules(cfg, file) local outputs = table.concat(file.buildoutputs, ' ') local dependencies = p.esc(file.source) if file.buildinputs and #file.buildinputs > 0 then dependencies = dependencies .. " " .. table.concat(p.esc(file.buildinputs), " ") end _p('%s: %s', outputs, dependencies) if file.buildmessage then _p('\t@echo %s', file.buildmessage) end if file.buildcommands then local cmds = os.translateCommandsAndPaths(file.buildcommands, cfg.project.basedir, cfg.project.location) for _, cmd in ipairs(cmds) do if cfg.bindirs and #cfg.bindirs > 0 then _p('\t$(SILENT) $(EXE_PATHS) %s', cmd) else _p('\t$(SILENT) %s', cmd) end end end end ȨS̨SШSԨSبSܨSSSSSSSlocal p = premake local project = p.project local tree = p.tree local m = p.vstudio.vc2010 function m.generateFilters(prj) m.xmlDeclaration() m.filtersProject() m.uniqueIdentifiers(prj) m.filterGroups(prj) p.out('') end function m.filtersProject() local action = p.action.current() p.push('', action.vstudio.filterToolsVersion or action.vstudio.toolsVersion) end function m.filterGroups(prj) local groups = m.categorizeSources(prj) for _, group in ipairs(groups) do group.category.emitFilter(prj, group) end end function m.uniqueIdentifiers(prj) local tr = project.getsourcetree(prj) local contents = p.capture(function() p.push() tree.traverse(tr, { onbranch = function(node, depth) p.push('', path.translate(node.path, '\\')) p.w('{%s}', os.uuid(node.path)) p.pop('') end }, false) p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end end function m.filterGroup(prj, group, tag) local files = group.files if files and #files > 0 then p.push('') for _, file in ipairs(files) do if file.parent.path then p.push('<%s Include=\"%s\">', tag, path.translate(file.relpath)) p.w('%s', path.translate(file.parent.path, '\\')) p.pop('', tag) else p.w('<%s Include=\"%s\" />', tag, path.translate(file.relpath)) end end p.pop('') end end local p = premake p.detoken = {} local detoken = p.detoken function detoken.expand(value, environ, field, basedir) function expandtoken(token, e, f) local varMap = {} if f.pathVars or e.overridePathVars then local action = p.action.current() if action then varMap = action.pathVars or {} end end local envMap = e.pathVars or {} setmetatable(e, {__index = _G}) local isAbs = false local err local result local success local dontMakeRelative = token:startswith('!') if dontMakeRelative then token = token:sub(2, -1) end local mapped = envMap[token] or varMap[token] if mapped then err = nil result = mapped if type(result) == "function" then success, result = pcall(result, e) if not success then return nil, result end end if (type(result) == "table") then isAbs = result.absolute result = result.token else isAbs = path.isabsolute(result) end else local func func, err = load("return " .. token, nil, 't', e) if not func then return nil, "load error: " .. err end success, result = pcall(func) if not success then err = result result = nil else err = nil result = result or "" end if result ~= nil then result = tostring(result) if path.hasdeferredjoin(result) then result = path.resolvedeferredjoin(result) end isAbs = path.isabsolute(result) if isAbs and not f.paths and basedir and not dontMakeRelative then result = path.getrelative(basedir, result) end end end if result ~= nil and isAbs and f.paths then result = "\0" .. result end return result, err end function expandvalue(value, e, f) if type(value) ~= "string" then return value end local count repeat value, count = value:gsub("%%{(.-)}", function(token) local result, err = expandtoken(token:gsub("\\", "\\\\"), e, f) if err then error(err .. " in token: " .. token, 0) end if not result then error("Token returned nil, it may not exist: " .. token, 0) end return result end) until count == 0 if f.paths then local i, j repeat i, j = value:find("\0") if i then value = value:sub(i + 1) end until not i end return value end local expand_cache = {} function recurse(value, e, f) if type(value) == "table" then local res_table = {} for k, v in pairs(value) do if tonumber(k) ~= nil then res_table[k] = recurse(v, e, f) else local nk = recurse(k, e, f) res_table[nk] = recurse(v, e, f) end end return res_table else local res = expand_cache[value] if res == nil then if type(value) == "string" and path.hasdeferredjoin(value) then value = path.resolvedeferredjoin(value) end res = expandvalue(value, e, f) expand_cache[value] = res end return res end end return recurse(value, environ, field or {}) end local p = premake p.modules.self_test = {} local m = p.modules.self_test m._VERSION = p._VERSION newaction { trigger = "self-test", shortname = "Test Premake", description = "Run Premake's own local unit test suites", execute = function() m.executeSelfTest() end } newoption { trigger = "test-only", value = "suite[.test]", description = "For self-test action; run specific suite or test" } function m.executeSelfTest() m.detectDuplicateTests = true m.loadTestsFromManifests() m.detectDuplicateTests = false local test, err = m.getTestWithIdentifier(_OPTIONS["test-only"]) if err then error(err, 0) end local passed, failed = m.runTest(test) if failed > 0 then printf("\n %d FAILED TEST%s", failed, iif(failed > 1, "S", "")) os.exit(5) end end function m.loadTestsFromManifests() local mask = path.join(_MAIN_SCRIPT_DIR, "**/tests/_tests.lua") local manifests = os.matchfiles(mask) local top = path.join(_MAIN_SCRIPT_DIR, "tests/_tests.lua") if os.isfile(top) then table.insert(manifests, 1, top) end for i = 1, #manifests do local manifest = manifests[i] _TESTS_DIR = path.getdirectory(manifest) local files = dofile(manifest) for i = 1, #files do local filename = path.join(_TESTS_DIR, files[i]) dofile(filename) end end end dofile("test_assertions.lua") dofile("test_declare.lua") dofile("test_helpers.lua") dofile("test_runner.lua") return m local p = premake p.api.register { name = "xcodebuildsettings", scope = "config", kind = "key-array", } p.api.register { name = "xcodebuildresources", scope = "config", kind = "list", } p.api.register { name = "xcodecodesigningidentity", scope = "config", kind = "string", } p.api.register { name = "xcodesystemcapabilities", scope = "project", kind = "key-boolean", } p.api.register { name = "iosfamily", scope = "config", kind = "string", allowed = { "iPhone/iPod touch", "iPad", "Universal", } } newaction { trigger = "xcode4", shortname = "Apple Xcode 4", description = "Generate Apple Xcode 4 project files", toolset = "clang", valid_kinds = { "ConsoleApp", "WindowedApp", "SharedLib", "StaticLib", "Makefile", "Utility", "None" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc", "clang" }, }, onWorkspace = function(wks) p.generate(wks, ".xcworkspace/contents.xcworkspacedata", p.modules.xcode.generateWorkspace) end, onProject = function(prj) p.generate(prj, ".xcodeproj/project.pbxproj", p.modules.xcode.generateProject) end, } return function(cfg) return (_ACTION == "xcode4") end 1.2.8json = {} local implementation = dofile('json.lua') local err json.implementation = implementation function implementation.assert(condition, message) if not condition then err = message end assert(condition, message) end function json.encode(value) err = nil local success, result = pcall(implementation.encode, implementation, value) if not success then return nil, err end return result end function json.encode_pretty(value) err = nil local success, result = pcall(implementation.encode_pretty, implementation, value) if not success then return nil, err end return result end function json.decode(value) err = nil local success, result = pcall(implementation.decode, implementation, value) if not success then return nil, err end return result end premake = premake or {} premake._VERSION = _PREMAKE_VERSION package.loaded["premake"] = premake premake.modules = {} premake.extensions = premake.modules local semver = dofile('semver.lua') local p = premake local _warnings = {} local _aliases = {} premake.C = "C" premake.C7 = "c7" premake.CLANG = "clang" premake.CONSOLEAPP = "ConsoleApp" premake.CPP = "C++" premake.CSHARP = "C#" premake.GCC = "gcc" premake.HAIKU = "haiku" premake.ANDROID = "android" premake.IOS = "ios" premake.LINUX = "linux" premake.MACOSX = "macosx" premake.MAKEFILE = "Makefile" premake.MBCS = "MBCS" premake.NONE = "None" premake.DEFAULT = "Default" premake.ON = "On" premake.OFF = "Off" premake.POSIX = "posix" premake.PS3 = "ps3" premake.SHAREDLIB = "SharedLib" premake.STATICLIB = "StaticLib" premake.UNICODE = "Unicode" premake.UNIVERSAL = "universal" premake.UTILITY = "Utility" premake.PACKAGING = "Packaging" premake.WINDOWEDAPP = "WindowedApp" premake.WINDOWS = "windows" premake.X86 = "x86" premake.X86_64 = "x86_64" premake.ARM = "ARM" premake.ARM64 = "ARM64" function p.alias(scope, canonical, alias) scope, canonical = p.resolveAlias(scope, canonical) if not scope[canonical] then error("unable to alias '" .. canonical .. "'; no such function", 2) end _aliases[scope] = _aliases[scope] or {} _aliases[scope][alias] = canonical scope[alias] = function(...) return scope[canonical](...) end end function premake.callArray(funcs, ...) if type(funcs) == "function" then funcs = funcs(...) end if funcs then for i = 1, #funcs do funcs[i](...) end end end function premake.callarray(namespace, array, ...) local n = #array for i = 1, n do local fn = namespace[array[i]] if not fn then error(string.format("Unable to find function '%s'", array[i])) end fn(...) end end function p.checkVersion(version, checks) if not version then return false end if not premake.isSemVer(version) then p.warn("'" .. version .. "' is not semver compatible, and cannot be compared against '" .. checks .. "'."); return true end local function eq(a, b) return a == b end local function le(a, b) return a <= b end local function lt(a, b) return a < b end local function ge(a, b) return a >= b end local function gt(a, b) return a > b end local function compat(a, b) return a ^ b end version = semver(version) checks = string.explode(checks, " ", true) for i = 1, #checks do local check = checks[i] local func if check:startswith(">=") then func = ge check = check:sub(3) elseif check:startswith(">") then func = gt check = check:sub(2) elseif check:startswith("<=") then func = le check = check:sub(3) elseif check:startswith("<") then func = lt check = check:sub(2) elseif check:startswith("=") then func = eq check = check:sub(2) elseif check:startswith("^") then func = compat check = check:sub(2) else func = ge end check = semver(check) if not func(version, check) then return false end end return true end function premake.clearWarnings() _warnings = {} end function premake.error(message, ...) error(string.format("** Error: " .. message, ...), 0) end function premake.findProjectScript(fname) return os.locate(fname, fname .. ".lua", path.join(fname, "premake5.lua"), path.join(fname, "premake4.lua")) end function iif(condition, trueValue, falseValue) if condition then return trueValue else return falseValue end end function premake.override(scope, name, repl) scope, name = p.resolveAlias(scope, name) local original = scope[name] if not original then error("unable to override '" .. name .. "'; no such function", 2) end scope[name] = function(...) return repl(original, ...) end if scope == premake.main then table.replace(premake.main.elements, original, scope[name]) end end function p.resolveAlias(scope, name) local aliases = _aliases[scope] if aliases then while aliases[name] do name = aliases[name] end end return scope, name end function premake.warn(message, ...) message = string.format(message, ...) if _OPTIONS.fatal then error(message) else term.pushColor(term.warningColor) io.stderr:write(string.format("** Warning: " .. message .. "\n", ...)) term.popColor(); end end function premake.warnOnce(key, message, ...) if not _warnings[key] then _warnings[key] = true premake.warn(message, ...) end end function premake.info(message, ...) message = string.format(message, ...) term.pushColor(term.infoColor) io.stdout:write(string.format("** Info: " .. message .. "\n", ...)) term.popColor(); end function printf(msg, ...) print(string.format(msg, ...)) end function verbosef(msg, ...) if _OPTIONS.verbose then print(string.format(msg, ...)) end end function filelineinfo(level) local info = debug.getinfo(level+1, "Sl") if info == nil then return nil end if info.what == "C" then return "C function" else local sep = iif(os.ishost('windows'), '\\', '/') return string.format("%s(%d)", path.translate(info.short_src, sep), info.currentline) end end function premake.isSemVer(version) local sMajor, sMinor, sPatch, sPrereleaseAndBuild = version:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$") return (type(sMajor) == 'string') end local p = premake local project = p.project p.modules.gmake2 = {} p.modules.gmake2._VERSION = p._VERSION local gmake2 = p.modules.gmake2 function gmake2.defaultconfig(target) local eachconfig = iif(target.project, project.eachconfig, p.workspace.eachconfig) local defaultconfig = nil if target.defaultplatform then for cfg in eachconfig(target) do if cfg.platform == target.defaultplatform then defaultconfig = cfg break end end end if not defaultconfig then local iter = eachconfig(target) defaultconfig = iter() end if defaultconfig then _p('ifndef config') _x(' config=%s', defaultconfig.shortname) _p('endif') _p('') end end function gmake2.esc(value) result = value:gsub("\\", "\\\\") result = result:gsub("\"", "\\\"") result = result:gsub(" ", "\\ ") result = result:gsub("%(", "\\(") result = result:gsub("%)", "\\)") result = result:gsub("$\\%((.-)\\%)", "$(%1)") return result end function gmake2.getmakefilename(this, searchprjs) local count = 0 for wks in p.global.eachWorkspace() do if wks.location == this.location then count = count + 1 end if searchprjs then for _, prj in ipairs(wks.projects) do if prj.location == this.location then count = count + 1 end end end end if count == 1 then return "Makefile" else return ".make" end end function gmake2.header(target) local kind = iif(target.project, "project", "workspace") _p('# %s %s makefile autogenerated by Premake', p.action.current().shortname, kind) _p('') gmake2.defaultconfig(target) _p('ifndef verbose') _p(' SILENT = @') _p('endif') _p('') end function gmake2.mkdir(dirname) _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) mkdir -p %s', dirname) _p('else') _p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', dirname) _p('endif') end function gmake2.mkdirRules(dirname) _p('%s:', dirname) _p('\t@echo Creating %s', dirname) gmake2.mkdir(dirname) _p('') end function gmake2.list(value, quoted) quoted = false if #value > 0 then if quoted then local result = "" for _, v in ipairs (value) do if #result then result = result .. " " end result = result .. p.quoted(v) end return result else return " " .. table.concat(value, " ") end else return "" end end function gmake2.tovar(value) value = value:gsub("[ -]", "_") value = value:gsub("[()]", "") return value end function gmake2.path(cfg, value) cfg = cfg.project or cfg local dirs = path.translate(project.getrelative(cfg, value)) if type(dirs) == 'table' then dirs = table.filterempty(dirs) end return dirs end function gmake2.getToolSet(cfg) local default = iif(cfg.system == p.MACOSX, "clang", "gcc") local toolset = p.tools[_OPTIONS.cc or cfg.toolset or default] if not toolset then error("Invalid toolset '" .. cfg.toolset .. "'") end return toolset end function gmake2.outputSection(prj, callback) local root = {} for cfg in project.eachconfig(prj) do local toolset = gmake2.getToolSet(cfg) local settings = {} local funcs = callback(cfg) for i = 1, #funcs do local c = p.capture(function () funcs[i](cfg, toolset) end) if #c > 0 then table.insert(settings, c) end end if not root.settings then root.settings = table.arraycopy(settings) else root.settings = table.intersect(root.settings, settings) end root[cfg] = settings end if #root.settings > 0 then for _, v in ipairs(root.settings) do p.outln(v) end p.outln('') end local first = true for cfg in project.eachconfig(prj) do local settings = table.difference(root[cfg], root.settings) if #settings > 0 then if first then _x('ifeq ($(config),%s)', cfg.shortname) first = false else _x('else ifeq ($(config),%s)', cfg.shortname) end for k, v in ipairs(settings) do p.outln(v) end _p('') end end if not first then p.outln('else') p.outln(' $(error "invalid configuration $(config)")') p.outln('endif') p.outln('') end end function gmake2.expandRuleString(rule, prop, value) if type(value) == "table" then if #value > 0 then if prop.switch then return prop.switch .. table.concat(value, " " .. prop.switch) else prop.separator = prop.separator or " " return table.concat(value, prop.separator) end else return nil end end if prop.switch and type(value) == "boolean" then if value then return prop.switch else return nil end end local switch = prop.switch or "" if prop.values then value = table.findKeyByValue(prop.values, value) if value == nil then value = "" end end value = tostring(value) if #value > 0 then return switch .. value else return nil end end function gmake2.prepareEnvironment(rule, environ, cfg) for _, prop in ipairs(rule.propertydefinition) do local fld = p.rule.getPropertyField(rule, prop) local value = cfg[fld.name] if value ~= nil then if fld.kind == "path" then value = gmake2.path(cfg, value) elseif fld.kind == "list:path" then value = gmake2.path(cfg, value) end value = gmake2.expandRuleString(rule, prop, value) if value ~= nil and #value > 0 then environ[prop.name] = p.esc(value) end end end end function gmake2.phonyRules(prj) _p('.PHONY: clean prebuild') _p('') end function gmake2.shellType() _p('SHELLTYPE := posix') _p('ifeq (.exe,$(findstring .exe,$(ComSpec)))') _p('\tSHELLTYPE := msdos') _p('endif') _p('') end function gmake2.target(cfg, toolset) p.outln('TARGETDIR = ' .. project.getrelative(cfg.project, cfg.buildtarget.directory)) p.outln('TARGET = $(TARGETDIR)/' .. cfg.buildtarget.name) end function gmake2.objdir(cfg, toolset) p.outln('OBJDIR = ' .. project.getrelative(cfg.project, cfg.objdir)) end function gmake2.settings(cfg, toolset) if #cfg.makesettings > 0 then for _, value in ipairs(cfg.makesettings) do p.outln(value) end end local value = toolset.getmakesettings(cfg) if value then p.outln(value) end end function gmake2.buildCmds(cfg, event) _p('define %sCMDS', event:upper()) local steps = cfg[event .. "commands"] local msg = cfg[event .. "message"] if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) msg = msg or string.format("Running %s commands", event) _p('\t@echo %s', msg) _p('\t%s', table.implode(steps, "", "", "\n\t")) end _p('endef') end function gmake2.preBuildCmds(cfg, toolset) gmake2.buildCmds(cfg, "prebuild") end function gmake2.preLinkCmds(cfg, toolset) gmake2.buildCmds(cfg, "prelink") end function gmake2.postBuildCmds(cfg, toolset) gmake2.buildCmds(cfg, "postbuild") end function gmake2.targetDirRules(cfg, toolset) gmake2.mkdirRules("$(TARGETDIR)") end function gmake2.objDirRules(cfg, toolset) gmake2.mkdirRules("$(OBJDIR)") end function gmake2.preBuildRules(cfg, toolset) _p('prebuild: | $(OBJDIR)') _p('\t$(PREBUILDCMDS)') _p('') end include("gmake2_cpp.lua") include("gmake2_csharp.lua") include("gmake2_makefile.lua") include("gmake2_utility.lua") include("gmake2_workspace.lua") return gmake2 local p = premake p.vstudio.vc2010 = {} local vstudio = p.vstudio local project = p.project local config = p.config local fileconfig = p.fileconfig local tree = p.tree local m = p.vstudio.vc2010 m.elements = {} m.conditionalElements = {} m.elements.project = function(prj) return { m.xmlDeclaration, m.project, m.projectConfigurations, m.globals, m.importDefaultProps, m.configurationPropertiesGroup, m.importLanguageSettings, m.importExtensionSettings, m.propertySheetGroup, m.userMacros, m.outputPropertiesGroup, m.itemDefinitionGroups, m.assemblyReferences, m.files, m.projectReferences, m.importLanguageTargets, m.importExtensionTargets, m.ensureNuGetPackageBuildImports, } end function m.generate(prj) p.utf8() p.callArray(m.elements.project, prj) p.out('') end function m.project(prj) local action = p.action.current() if _ACTION >= "vs2019" then p.push('') else p.push('', action.vstudio.toolsVersion) end end function m.projectConfigurations(prj) local platforms = {} for cfg in project.eachconfig(prj) do local arch = vstudio.archFromConfig(cfg, true) if not table.contains(platforms, arch) then table.insert(platforms, arch) end end local configs = {} p.push('') for cfg in project.eachconfig(prj) do for _, arch in ipairs(platforms) do local prjcfg = vstudio.projectConfig(cfg, arch) if not configs[prjcfg] then configs[prjcfg] = prjcfg p.push('', vstudio.projectConfig(cfg, arch)) p.x('%s', vstudio.projectPlatform(cfg)) p.w('%s', arch) p.pop('') end end end p.pop('') end function m.targetFramework(prj) local action = p.action.current() local tools = string.format(' ToolsVersion="%s"', action.vstudio.toolsVersion) local framework = prj.dotnetframework or action.vstudio.targetFramework or "4.0" p.w('v%s', framework) end m.elements.globals = function(prj) return { m.projectGuid, m.ignoreWarnDuplicateFilename, m.keyword, m.projectName, m.preferredToolArchitecture, m.targetPlatformVersionGlobal, } end m.elements.globalsCondition = function(prj, cfg) return { m.targetPlatformVersionCondition, } end function m.globals(prj) m.propertyGroup(nil, "Globals") p.callArray(m.elements.globals, prj) p.pop('') for cfg in project.eachconfig(prj) do local captured = p.capture(function() p.push() p.callArray(m.elements.globalsCondition, prj, cfg) p.pop() end) if captured ~= '' then m.propertyGroup(cfg, "Globals") p.callArray(m.elements.globalsCondition, prj, cfg) p.pop('') end end end m.elements.configurationProperties = function(cfg) if cfg.kind == p.UTILITY then return { m.configurationType, m.platformToolset, } else return { m.configurationType, m.useDebugLibraries, m.useOfMfc, m.useOfAtl, m.clrSupport, m.characterSet, m.platformToolset, m.wholeProgramOptimization, m.nmakeOutDirs, m.windowsSDKDesktopARMSupport, } end end function m.configurationProperties(cfg) m.propertyGroup(cfg, "Configuration") p.callArray(m.elements.configurationProperties, cfg) p.pop('') end function m.configurationPropertiesGroup(prj) for cfg in project.eachconfig(prj) do m.configurationProperties(cfg) end end m.elements.outputProperties = function(cfg) if cfg.kind == p.UTILITY then return { m.outDir, m.intDir, m.extensionsToDeleteOnClean, m.executablePath, } else return { m.linkIncremental, m.ignoreImportLibrary, m.outDir, m.intDir, m.targetName, m.targetExt, m.includePath, m.libraryPath, m.generateManifest, m.extensionsToDeleteOnClean, m.executablePath, } end end function m.outputProperties(cfg) if not vstudio.isMakefile(cfg) then m.propertyGroup(cfg) p.callArray(m.elements.outputProperties, cfg) p.pop('') end end m.elements.nmakeProperties = function(cfg) return { m.executablePath, m.includePath, m.libraryPath, m.nmakeOutput, m.nmakeBuildCommands, m.nmakeRebuildCommands, m.nmakeCleanCommands, m.nmakePreprocessorDefinitions, m.nmakeIncludeDirs } end function m.nmakeProperties(cfg) if vstudio.isMakefile(cfg) then m.propertyGroup(cfg) p.callArray(m.elements.nmakeProperties, cfg) p.pop('') end end function m.outputPropertiesGroup(prj) for cfg in project.eachconfig(prj) do m.outputProperties(cfg) m.nmakeProperties(cfg) end end m.elements.itemDefinitionGroup = function(cfg) if cfg.kind == p.UTILITY then return { m.ruleVars, m.buildEvents, m.buildLog, } else return { m.clCompile, m.fxCompile, m.resourceCompile, m.linker, m.manifest, m.buildEvents, m.ruleVars, m.buildLog, } end end function m.itemDefinitionGroup(cfg) if not vstudio.isMakefile(cfg) then p.push('', m.condition(cfg)) p.callArray(m.elements.itemDefinitionGroup, cfg) p.pop('') else if cfg == project.getfirstconfig(cfg.project) then p.w('') p.w('') end end end function m.itemDefinitionGroups(prj) for cfg in project.eachconfig(prj) do m.itemDefinitionGroup(cfg) end end m.elements.clCompile = function(cfg) local calls = { m.precompiledHeader, m.warningLevel, m.treatWarningAsError, m.disableSpecificWarnings, m.treatSpecificWarningsAsErrors, m.basicRuntimeChecks, m.clCompilePreprocessorDefinitions, m.clCompileUndefinePreprocessorDefinitions, m.clCompileAdditionalIncludeDirectories, m.clCompileAdditionalUsingDirectories, m.forceIncludes, m.debugInformationFormat, m.optimization, m.functionLevelLinking, m.intrinsicFunctions, m.minimalRebuild, m.omitFramePointers, m.stringPooling, m.runtimeLibrary, m.omitDefaultLib, m.exceptionHandling, m.runtimeTypeInfo, m.bufferSecurityCheck, m.treatWChar_tAsBuiltInType, m.floatingPointModel, m.floatingPointExceptions, m.inlineFunctionExpansion, m.enableEnhancedInstructionSet, m.multiProcessorCompilation, m.additionalCompileOptions, m.compileAs, m.callingConvention, m.languageStandard, m.structMemberAlignment, } if cfg.kind == p.STATICLIB then table.insert(calls, m.programDatabaseFileName) end return calls end function m.clCompile(cfg) p.push('') p.callArray(m.elements.clCompile, cfg) p.pop('') end m.elements.fxCompile = function(cfg) return { m.fxCompilePreprocessorDefinition, m.fxCompileShaderType, m.fxCompileShaderModel, m.fxCompileShaderEntry, m.fxCompileShaderVariableName, m.fxCompileShaderHeaderOutput, m.fxCompileShaderObjectOutput, m.fxCompileShaderAssembler, m.fxCompileShaderAssemblerOutput, m.fxCompileShaderAdditionalOptions, } end function m.fxCompile(cfg) if p.config.hasFile(cfg, path.ishlslfile) then local contents = p.capture(function () p.push() p.callArray(m.elements.fxCompile, cfg) p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end end end m.elements.resourceCompile = function(cfg) return { m.resourcePreprocessorDefinitions, m.resourceAdditionalIncludeDirectories, m.culture, } end function m.resourceCompile(cfg) if p.config.hasFile(cfg, path.isresourcefile) then local contents = p.capture(function () p.push() p.callArray(m.elements.resourceCompile, cfg) p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end end end m.elements.linker = function(cfg, explicit) return { m.link, m.lib, m.linkLibraryDependencies, } end function m.linker(cfg) local explicit = vstudio.needsExplicitLink(cfg) p.callArray(m.elements.linker, cfg, explicit) end m.elements.link = function(cfg, explicit) if cfg.kind == p.STATICLIB then return { m.subSystem, m.fullProgramDatabaseFile, m.generateDebugInformation, m.optimizeReferences, } else return { m.subSystem, m.fullProgramDatabaseFile, m.generateDebugInformation, m.optimizeReferences, m.additionalDependencies, m.additionalLibraryDirectories, m.importLibrary, m.entryPointSymbol, m.generateMapFile, m.moduleDefinitionFile, m.treatLinkerWarningAsErrors, m.ignoreDefaultLibraries, m.largeAddressAware, m.targetMachine, m.additionalLinkOptions, m.programDatabaseFile, } end end function m.link(cfg, explicit) local contents = p.capture(function () p.push() p.callArray(m.elements.link, cfg, explicit) p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end end m.elements.lib = function(cfg, explicit) if cfg.kind == p.STATICLIB then return { m.additionalDependencies, m.additionalLibraryDirectories, m.treatLinkerWarningAsErrors, m.targetMachine, m.additionalLinkOptions, } else return {} end end function m.lib(cfg, explicit) local contents = p.capture(function () p.push() p.callArray(m.elements.lib, cfg, explicit) p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end end m.elements.manifest = function(cfg) return { m.enableDpiAwareness, m.additionalManifestFiles, } end function m.manifest(cfg) if cfg.kind ~= p.STATICLIB then local contents = p.capture(function () p.push() p.callArray(m.elements.manifest, cfg) p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end end end function m.buildEvents(cfg) local write = function (event) local name = event .. "Event" local field = event:lower() local steps = cfg[field .. "commands"] local msg = cfg[field .. "message"] if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) p.push('<%s>', name) p.x('%s', table.implode(steps, "", "", "\r\n")) if msg then p.x('%s', msg) end p.pop('', name) end end write("PreBuild") write("PreLink") write("PostBuild") end function m.getRulePropertyString(rule, prop, value, kind) if kind == "list:path" then return table.concat(vstudio.path(cfg, value), ';') end if kind == "path" then return vstudio.path(cfg, value) end if type(value) == "table" then return table.concat(value, ";") end if prop.values then value = table.findKeyByValue(prop.values, value) end return tostring(value) end function m.ruleVars(cfg) for i = 1, #cfg.rules do local rule = p.global.getRule(cfg.rules[i]) local contents = p.capture(function () p.push() for prop in p.rule.eachProperty(rule) do local fld = p.rule.getPropertyField(rule, prop) local value = cfg[fld.name] if value ~= nil then value = m.getRulePropertyString(rule, prop, value, fld.kind) if value ~= nil and #value > 0 then m.element(prop.name, nil, '%s', value) end end end p.pop() end) if #contents > 0 then p.push('<%s>', rule.name) p.outln(contents) p.pop('', rule.name) end end end function m.assemblyReferences(prj) local cfg = project.getfirstconfig(prj) local refs = config.getlinks(cfg, "system", "fullpath", "managed") if #refs > 0 then p.push('') for i = 1, #refs do local value = refs[i] if value:find('/', 1, true) then p.push('', path.getbasename(value)) p.x('%s', path.translate(value)) p.pop('') else p.x('', path.getbasename(value)) end end p.pop('') end end function m.generatedFile(cfg, file) if file.generated then local path = path.translate(file.dependsOn.relpath) m.element("AutoGen", nil, 'true') m.element("DependentUpon", nil, path) end end function m.files(prj) local groups = m.categorizeSources(prj) for _, group in ipairs(groups) do group.category.emitFiles(prj, group) end end m.categories = {} m.categories.ClInclude = { name = "ClInclude", extensions = { ".h", ".hh", ".hpp", ".hxx", ".inl" }, priority = 1, emitFiles = function(prj, group) m.emitFiles(prj, group, "ClInclude", {m.generatedFile}) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "ClInclude") end } m.categories.ClCompile = { name = "ClCompile", extensions = { ".cc", ".cpp", ".cxx", ".c", ".s", ".m", ".mm" }, priority = 2, emitFiles = function(prj, group) local fileCfgFunc = function(fcfg, condition) if fcfg then return { m.excludedFromBuild, m.objectFileName, m.clCompilePreprocessorDefinitions, m.clCompileUndefinePreprocessorDefinitions, m.optimization, m.forceIncludes, m.precompiledHeader, m.enableEnhancedInstructionSet, m.additionalCompileOptions, m.disableSpecificWarnings, m.treatSpecificWarningsAsErrors, m.basicRuntimeChecks, m.exceptionHandling, m.compileAsManaged, m.compileAs, m.runtimeTypeInfo, m.warningLevelFile, } else return { m.excludedFromBuild } end end m.emitFiles(prj, group, "ClCompile", {m.generatedFile}, fileCfgFunc) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "ClCompile") end } m.categories.FxCompile = { name = "FxCompile", extensions = { ".hlsl" }, priority = 4, emitFiles = function(prj, group) local fileCfgFunc = function(fcfg, condition) if fcfg then return { m.excludedFromBuild, m.fxCompilePreprocessorDefinition, m.fxCompileShaderType, m.fxCompileShaderModel, m.fxCompileShaderEntry, m.fxCompileShaderVariableName, m.fxCompileShaderHeaderOutput, m.fxCompileShaderObjectOutput, m.fxCompileShaderAssembler, m.fxCompileShaderAssemblerOutput, m.fxCompileShaderAdditionalOptions, } else return { m.excludedFromBuild } end end m.emitFiles(prj, group, "FxCompile", nil, fileCfgFunc) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "FxCompile") end } m.categories.None = { name = "None", priority = 5, emitFiles = function(prj, group) m.emitFiles(prj, group, "None", {m.generatedFile}) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "None") end } m.categories.ResourceCompile = { name = "ResourceCompile", extensions = ".rc", priority = 6, emitFiles = function(prj, group) local fileCfgFunc = { m.excludedFromBuild } m.emitFiles(prj, group, "ResourceCompile", nil, fileCfgFunc, function(cfg) return cfg.system == p.WINDOWS end) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "ResourceCompile") end } m.categories.CustomBuild = { name = "CustomBuild", priority = 7, emitFiles = function(prj, group) local fileFunc = { m.fileType } local fileCfgFunc = { m.excludedFromBuild, m.buildCommands, m.buildOutputs, m.linkObjects, m.buildMessage, m.buildAdditionalInputs } m.emitFiles(prj, group, "CustomBuild", fileFunc, fileCfgFunc, function (cfg, fcfg) return fileconfig.hasCustomBuildRule(fcfg) end) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "CustomBuild") end } m.categories.Midl = { name = "Midl", extensions = ".idl", priority = 8, emitFiles = function(prj, group) local fileCfgFunc = { m.excludedFromBuild } m.emitFiles(prj, group, "Midl", nil, fileCfgFunc, function(cfg) return cfg.system == p.WINDOWS end) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "Midl") end } m.categories.Masm = { name = "Masm", extensions = ".asm", priority = 9, emitFiles = function(prj, group) local fileCfgFunc = function(fcfg, condition) if fcfg then return { m.MasmPreprocessorDefinitions, m.excludedFromBuild, m.exceptionHandlingSEH, } else return { m.excludedFromBuild } end end m.emitFiles(prj, group, "Masm", nil, fileCfgFunc) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "Masm") end, emitExtensionSettings = function(prj, group) p.w('') end, emitExtensionTargets = function(prj, group) p.w('') end } m.categories.Image = { name = "Image", extensions = { ".gif", ".jpg", ".jpe", ".png", ".bmp", ".dib", "*.tif", "*.wmf", "*.ras", "*.eps", "*.pcx", "*.pcd", "*.tga", "*.dds" }, priority = 10, emitFiles = function(prj, group) local fileCfgFunc = function(fcfg, condition) return { m.excludedFromBuild } end m.emitFiles(prj, group, "Image", nil, fileCfgFunc) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "Image") end } m.categories.Natvis = { name = "Natvis", extensions = { ".natvis" }, priority = 11, emitFiles = function(prj, group) m.emitFiles(prj, group, "Natvis", {m.generatedFile}) end, emitFilter = function(prj, group) m.filterGroup(prj, group, "Natvis") end } function m.categorizeSources(prj) if prj._vc2010_sources then return prj._vc2010_sources end local result = {} local groups = {} prj._vc2010_sources = result local tr = project.getsourcetree(prj) tree.traverse(tr, { onleaf = function(node) local cat = m.categorizeFile(prj, node) groups[cat.name] = groups[cat.name] or { category = cat, files = {} } table.insert(groups[cat.name].files, node) end }) for name, group in pairs(groups) do table.sort(group.files, function (a, b) return a.relpath < b.relpath end) table.insert(result, group) end table.sort(result, function (a, b) if (a.category.priority == b.category.priority) then return a.category.name < b.category.name end return a.category.priority < b.category.priority end) return result end function m.categorizeFile(prj, file) for cfg in project.eachconfig(prj) do local fcfg = fileconfig.getconfig(file, cfg) if fcfg then if fileconfig.hasCustomBuildRule(fcfg) then return m.categories.CustomBuild end if fcfg.buildaction then return m.categories[fcfg.buildaction] or m.categories.None end end end local rule = p.global.getRuleForFile(file.name, prj.rules) if rule then return { name = rule.name, priority = 100, rule = rule, emitFiles = function(prj, group) m.emitRuleFiles(prj, group) end, emitFilter = function(prj, group) m.filterGroup(prj, group, group.category.name) end } end for _, cat in pairs(m.categories) do if cat.extensions and path.hasextension(file.name, cat.extensions) then return cat end end return m.categories.None end function m.configPair(cfg) return vstudio.projectPlatform(cfg) .. "|" .. vstudio.archFromConfig(cfg, true) end function m.getTotalCfgCount(prj) if prj._totalCfgCount then return prj._totalCfgCount else local result = 0 for _ in p.project.eachconfig(prj) do result = result + 1 end prj._totalCfgCount = result return result end end function m.indexConditionalElements() local nameMap, nameList, settingList nameMap = {} nameList = {} -- to preserve ordering settingList = {} -- to preserve ordering for _, element in ipairs(m.conditionalElements) do local settingMap = nameMap[element.name] if not settingMap then settingMap = {} nameMap[element.name] = settingMap if not table.contains(nameList, element.name) then table.insert(nameList, element.name) end end local elementSet = settingMap[element.setting] if elementSet then table.insert(elementSet, element) else elementSet = {element} settingMap[element.setting] = elementSet if not table.contains(settingList, element.setting) then table.insert(settingList, element.setting) end end end return nameMap, nameList, settingList end function m.emitConditionalElements(prj) local keyCount = function(tbl) local count = 0 for _ in pairs(tbl) do count = count + 1 end return count end local nameMap, nameList, settingList nameMap, nameList, settingList = m.indexConditionalElements() local totalCfgCount = m.getTotalCfgCount(prj) for _, name in ipairs(nameList) do local settingMap = nameMap[name] local done = false if keyCount(settingMap)==1 then for _, setting in ipairs(settingList) do local elements = settingMap[setting] if elements~=nil and #elements==totalCfgCount then local element = elements[1] local format = string.format('<%s>%s', name, element.value, name) p.w(format, table.unpack(element.args)) done = true end end end if not done then for _, setting in ipairs(settingList) do local elements = settingMap[setting] if elements then for _, element in ipairs(elements) do local format = string.format('<%s %s>%s', name, m.conditionFromConfigText(element.condition), element.value, name) p.w(format, table.unpack(element.args)) end end end end end end function m.emitFiles(prj, group, tag, fileFunc, fileCfgFunc, checkFunc) local files = group.files if files and #files > 0 then p.push('') for _, file in ipairs(files) do local contents = p.capture(function () p.push() p.callArray(fileFunc, cfg, file) m.conditionalElements = {} for cfg in project.eachconfig(prj) do local fcfg = fileconfig.getconfig(file, cfg) if not checkFunc or checkFunc(cfg, fcfg) then p.callArray(fileCfgFunc, fcfg, m.configPair(cfg)) end end if #m.conditionalElements > 0 then m.emitConditionalElements(prj) end p.pop() end) local rel = path.translate(file.relpath) if #contents > 0 then p.push('<%s Include="%s">', tag, rel) p.outln(contents) p.pop('', tag) else p.x('<%s Include="%s" />', tag, rel) end end p.pop('') end end function m.emitRuleFiles(prj, group) local files = group.files local rule = group.category.rule if files and #files > 0 then p.push('') for _, file in ipairs(files) do local contents = p.capture(function() p.push() for prop in p.rule.eachProperty(rule) do local fld = p.rule.getPropertyField(rule, prop) m.conditionalElements = {} for cfg in project.eachconfig(prj) do local fcfg = fileconfig.getconfig(file, cfg) if fcfg and fcfg[fld.name] then local value = m.getRulePropertyString(rule, prop, fcfg[fld.name]) if value and #value > 0 then m.element(prop.name, m.configPair(cfg), '%s', value) end end end if #m.conditionalElements > 0 then m.emitConditionalElements(prj) end end p.pop() end) if #contents > 0 then p.push('<%s Include=\"%s\">', rule.name, path.translate(file.relpath)) p.outln(contents) p.pop('', rule.name) else p.x('<%s Include=\"%s\" />', rule.name, path.translate(file.relpath)) end end p.pop('') end end function m.isClrMixed(prj) local isMixed = false if not prj.clr or prj.clr == p.OFF then if prj._isClrMixed ~= nil then isMixed = prj._isClrMixed else table.foreachi(prj._.files, function(file) for cfg in p.project.eachconfig(prj) do local fcfg = p.fileconfig.getconfig(file, cfg) if fcfg and fcfg.clr and fcfg.clr ~= p.OFF then isMixed = true end end end) prj._isClrMixed = isMixed -- cache the results end end return isMixed end m.elements.projectReferences = function(prj, ref) if prj.clr ~= p.OFF or (m.isClrMixed(prj) and ref and ref.kind ~=p.STATICLIB) then return { m.referenceProject, m.referencePrivate, m.referenceOutputAssembly, m.referenceCopyLocalSatelliteAssemblies, m.referenceLinkLibraryDependencies, m.referenceUseLibraryDependences, } else return { m.referenceProject, } end end function m.projectReferences(prj) local refs = project.getdependencies(prj, 'linkOnly') if #refs > 0 then p.push('') for _, ref in ipairs(refs) do local relpath = vstudio.path(prj, vstudio.projectfile(ref)) p.push('', relpath) p.callArray(m.elements.projectReferences, prj, ref) p.pop('') end p.pop('') end end function m.additionalDependencies(cfg, explicit) local links local toolset = config.toolset(cfg) if toolset then links = toolset.getlinks(cfg, not explicit) else links = vstudio.getLinks(cfg, explicit) end if #links > 0 then links = path.translate(table.concat(links, ";")) m.element("AdditionalDependencies", nil, "%s;%%(AdditionalDependencies)", links) end end function m.additionalIncludeDirectories(cfg, includedirs) if #includedirs > 0 then local dirs = vstudio.path(cfg, includedirs) if #dirs > 0 then m.element("AdditionalIncludeDirectories", nil, "%s;%%(AdditionalIncludeDirectories)", table.concat(dirs, ";")) end end end function m.additionalLibraryDirectories(cfg) if #cfg.libdirs > 0 then local dirs = table.concat(vstudio.path(cfg, cfg.libdirs), ";") m.element("AdditionalLibraryDirectories", nil, "%s;%%(AdditionalLibraryDirectories)", dirs) end end function m.additionalManifestFiles(cfg) local manifests = {} for _, fname in ipairs(cfg.files) do if path.getextension(fname) == ".manifest" then table.insert(manifests, project.getrelative(cfg.project, fname)) end end if #manifests > 0 then m.element("AdditionalManifestFiles", nil, "%s;%%(AdditionalManifestFiles)", table.concat(manifests, ";")) end end function m.additionalUsingDirectories(cfg) if #cfg.usingdirs > 0 then local dirs = vstudio.path(cfg, cfg.usingdirs) if #dirs > 0 then m.element("AdditionalUsingDirectories", nil, "%s;%%(AdditionalUsingDirectories)", table.concat(dirs, ";")) end end end function m.largeAddressAware(cfg) if (cfg.largeaddressaware == true) then m.element("LargeAddressAware", nil, 'true') end end function m.languageStandard(cfg) if _ACTION >= "vs2017" then if (cfg.cppdialect == "C++14") then m.element("LanguageStandard", nil, 'stdcpp14') elseif (cfg.cppdialect == "C++17") then m.element("LanguageStandard", nil, 'stdcpp17') elseif (cfg.cppdialect == "C++latest") then m.element("LanguageStandard", nil, 'stdcpplatest') end end end function m.structMemberAlignment(cfg) local map = { [1] = "1Byte", [2] = "2Bytes", [4] = "4Bytes", [8] = "8Bytes", [16] = "16Bytes" } local value = map[cfg.structmemberalign] if value then m.element("StructMemberAlignment", nil, value) end end function m.additionalCompileOptions(cfg, condition) local opts = cfg.buildoptions if _ACTION == "vs2015" then if (cfg.cppdialect == "C++14") then table.insert(opts, "/std:c++14") elseif (cfg.cppdialect == "C++17") then table.insert(opts, "/std:c++latest") elseif (cfg.cppdialect == "C++latest") then table.insert(opts, "/std:c++latest") end end if cfg.toolset and cfg.toolset:startswith("msc") then local value = iif(cfg.unsignedchar, "On", "Off") table.insert(opts, p.tools.msc.shared.unsignedchar[value]) end if #opts > 0 then opts = table.concat(opts, " ") m.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts) end end function m.additionalLinkOptions(cfg) if #cfg.linkoptions > 0 then local opts = table.concat(cfg.linkoptions, " ") m.element("AdditionalOptions", nil, "%s %%(AdditionalOptions)", opts) end end function m.compileAsManaged(fcfg, condition) if fcfg.clr and fcfg ~= p.OFF then m.element("CompileAsManaged", condition, "true") end end function m.basicRuntimeChecks(cfg, condition) local prjcfg, filecfg = p.config.normalize(cfg) local runtime = config.getruntime(prjcfg) or iif(config.isDebugBuild(cfg), "Debug", "Release") if filecfg then if filecfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(filecfg) and runtime:endswith("Debug")) then m.element("BasicRuntimeChecks", condition, "Default") end else if prjcfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(prjcfg) and runtime:endswith("Debug")) then m.element("BasicRuntimeChecks", nil, "Default") end end end function m.buildAdditionalInputs(fcfg, condition) if fcfg.buildinputs and #fcfg.buildinputs > 0 then local inputs = project.getrelative(fcfg.project, fcfg.buildinputs) m.element("AdditionalInputs", condition, '%s', table.concat(inputs, ";")) end end function m.buildCommands(fcfg, condition) local commands = os.translateCommandsAndPaths(fcfg.buildcommands, fcfg.project.basedir, fcfg.project.location) commands = table.concat(commands,'\r\n') m.element("Command", condition, '%s', commands) end function m.buildLog(cfg) if cfg.buildlog and #cfg.buildlog > 0 then p.push('') m.element("Path", nil, "%s", vstudio.path(cfg, cfg.buildlog)) p.pop('') end end function m.buildMessage(fcfg, condition) if fcfg.buildmessage then m.element("Message", condition, '%s', fcfg.buildmessage) end end function m.buildOutputs(fcfg, condition) local outputs = project.getrelative(fcfg.project, fcfg.buildoutputs) m.element("Outputs", condition, '%s', table.concat(outputs, ";")) end function m.linkObjects(fcfg, condition) if fcfg.linkbuildoutputs ~= nil then m.element("LinkObjects", condition, tostring(fcfg.linkbuildoutputs)) end end function m.characterSet(cfg) if not vstudio.isMakefile(cfg) then local charactersets = { ASCII = "NotSet", MBCS = "MultiByte", Unicode = "Unicode", Default = "Unicode" } m.element("CharacterSet", nil, charactersets[cfg.characterset]) end end function m.wholeProgramOptimization(cfg) if cfg.flags.LinkTimeOptimization then m.element("WholeProgramOptimization", nil, "true") end end function m.clCompileAdditionalIncludeDirectories(cfg) m.additionalIncludeDirectories(cfg, cfg.includedirs) end function m.clCompileAdditionalUsingDirectories(cfg) m.additionalUsingDirectories(cfg, cfg.usingdirs) end function m.clCompilePreprocessorDefinitions(cfg, condition) local defines = cfg.defines if cfg.exceptionhandling == p.OFF then defines = table.join(defines, "_HAS_EXCEPTIONS=0") end m.preprocessorDefinitions(cfg, defines, false, condition) end function m.clCompileUndefinePreprocessorDefinitions(cfg, condition) m.undefinePreprocessorDefinitions(cfg, cfg.undefines, false, condition) end function m.clrSupport(cfg) local value if cfg.clr == "On" or cfg.clr == "Unsafe" then value = "true" elseif cfg.clr ~= p.OFF then value = cfg.clr end if value then m.element("CLRSupport", nil, value) end end function m.compileAs(cfg, condition) if p.languages.isc(cfg.compileas) then m.element("CompileAs", condition, "CompileAsC") elseif p.languages.iscpp(cfg.compileas) then m.element("CompileAs", condition, "CompileAsCpp") end end function m.configurationType(cfg) local types = { SharedLib = "DynamicLibrary", StaticLib = "StaticLibrary", ConsoleApp = "Application", WindowedApp = "Application", Makefile = "Makefile", None = "Makefile", Utility = "Utility", } m.element("ConfigurationType", nil, types[cfg.kind]) end function m.culture(cfg) local value = vstudio.cultureForLocale(cfg.locale) if value then m.element("Culture", nil, "0x%04x", tostring(value)) end end function m.debugInformationFormat(cfg) local value local tool, toolVersion = p.config.toolset(cfg) if (cfg.symbols == p.ON) or (cfg.symbols == "FastLink") or (cfg.symbols == "Full") then if cfg.debugformat == "c7" then value = "OldStyle" elseif (cfg.architecture == "x86_64" and _ACTION < "vs2015") or cfg.clr ~= p.OFF or config.isOptimizedBuild(cfg) or cfg.editandcontinue == p.OFF or (toolVersion and toolVersion:startswith("LLVM-vs")) then value = "ProgramDatabase" else value = "EditAndContinue" end m.element("DebugInformationFormat", nil, value) elseif cfg.symbols == p.OFF then if _ACTION < "vs2015" then value = "" else value = "None" end m.element("DebugInformationFormat", nil, value) end end function m.enableDpiAwareness(cfg) local awareness = { None = "false", High = "true", HighPerMonitor = "PerMonitorHighDPIAware", } local value = awareness[cfg.dpiawareness] if value then m.element("EnableDpiAwareness", nil, value) end end function m.enableEnhancedInstructionSet(cfg, condition) local v local x = cfg.vectorextensions if x == "AVX" and _ACTION > "vs2010" then v = "AdvancedVectorExtensions" elseif x == "AVX2" and _ACTION > "vs2012" then v = "AdvancedVectorExtensions2" elseif cfg.architecture ~= "x86_64" then if x == "SSE2" or x == "SSE3" or x == "SSSE3" or x == "SSE4.1" then v = "StreamingSIMDExtensions2" elseif x == "SSE" then v = "StreamingSIMDExtensions" elseif x == "IA32" and _ACTION > "vs2010" then v = "NoExtensions" end end if v then m.element('EnableEnhancedInstructionSet', condition, v) end end function m.entryPointSymbol(cfg) if cfg.entrypoint then m.element("EntryPointSymbol", nil, cfg.entrypoint) end end function m.exceptionHandling(cfg, condition) if cfg.exceptionhandling == p.OFF then m.element("ExceptionHandling", condition, "false") elseif cfg.exceptionhandling == "SEH" then m.element("ExceptionHandling", condition, "Async") elseif cfg.exceptionhandling == "On" then m.element("ExceptionHandling", condition, "Sync") elseif cfg.exceptionhandling == "CThrow" then m.element("ExceptionHandling", condition, "SyncCThrow") end end function m.excludedFromBuild(filecfg, condition) if not filecfg or filecfg.flags.ExcludeFromBuild then m.element("ExcludedFromBuild", condition, "true") end end function m.exceptionHandlingSEH(filecfg, condition) if not filecfg or filecfg.exceptionhandling == "SEH" then m.element("UseSafeExceptionHandlers", condition, "true") end end function m.extensionsToDeleteOnClean(cfg) if #cfg.cleanextensions > 0 then local value = table.implode(cfg.cleanextensions, "*", ";", "") m.element("ExtensionsToDeleteOnClean", nil, value .. "$(ExtensionsToDeleteOnClean)") end end function m.fileType(cfg, file) m.element("FileType", nil, "Document") end function m.floatingPointModel(cfg) if cfg.floatingpoint and cfg.floatingpoint ~= "Default" then m.element("FloatingPointModel", nil, cfg.floatingpoint) end end function m.floatingPointExceptions(cfg) if cfg.floatingpointexceptions ~= nil then if cfg.floatingpointexceptions then m.element("FloatingPointExceptions", nil, "true") else m.element("FloatingPointExceptions", nil, "false") end end end function m.inlineFunctionExpansion(cfg) if cfg.inlining then local types = { Default = "Default", Disabled = "Disabled", Explicit = "OnlyExplicitInline", Auto = "AnySuitable", } m.element("InlineFunctionExpansion", nil, types[cfg.inlining]) end end function m.forceIncludes(cfg, condition) if #cfg.forceincludes > 0 then local includes = vstudio.path(cfg, cfg.forceincludes) if #includes > 0 then m.element("ForcedIncludeFiles", condition, table.concat(includes, ';')) end end if #cfg.forceusings > 0 then local usings = vstudio.path(cfg, cfg.forceusings) if #usings > 0 then m.element("ForcedUsingFiles", condition, table.concat(usings, ';')) end end end function m.fullProgramDatabaseFile(cfg) if _ACTION >= "vs2015" and cfg.symbols == "FastLink" then m.element("FullProgramDatabaseFile", nil, "true") end end function m.functionLevelLinking(cfg) if cfg.functionlevellinking ~= nil then if cfg.functionlevellinking then m.element("FunctionLevelLinking", nil, "true") else m.element("FunctionLevelLinking", nil, "false") end elseif config.isOptimizedBuild(cfg) then m.element("FunctionLevelLinking", nil, "true") end end function m.generateDebugInformation(cfg) local lookup = {} if _ACTION >= "vs2017" then lookup[p.ON] = "true" lookup[p.OFF] = "false" lookup["FastLink"] = "DebugFastLink" lookup["Full"] = "DebugFull" elseif _ACTION == "vs2015" then lookup[p.ON] = "true" lookup[p.OFF] = "false" lookup["FastLink"] = "DebugFastLink" lookup["Full"] = "true" else lookup[p.ON] = "true" lookup[p.OFF] = "false" lookup["FastLink"] = "true" lookup["Full"] = "true" end local value = lookup[cfg.symbols] if value then m.element("GenerateDebugInformation", nil, value) end end function m.generateManifest(cfg) if cfg.flags.NoManifest then m.element("GenerateManifest", nil, "false") end end function m.generateMapFile(cfg) if cfg.flags.Maps then m.element("GenerateMapFile", nil, "true") end end function m.ignoreDefaultLibraries(cfg) if #cfg.ignoredefaultlibraries > 0 then local ignored = cfg.ignoredefaultlibraries for i = 1, #ignored do if not p.tools.msc.getLibraryExtensions()[ignored[i]:match("[^.]+$")] then ignored[i] = path.appendextension(ignored[i], ".lib") end end m.element("IgnoreSpecificDefaultLibraries", condition, table.concat(ignored, ';')) end end function m.ignoreWarnDuplicateFilename(prj) if _ACTION > "vs2012" then m.element("IgnoreWarnCompileDuplicatedFilename", nil, "true") end end function m.ignoreImportLibrary(cfg) if cfg.kind == p.SHAREDLIB and cfg.flags.NoImportLib then m.element("IgnoreImportLibrary", nil, "true") end end function m.importLanguageTargets(prj) p.w('') end m.elements.importExtensionTargets = function(prj) return { m.importGroupTargets, m.importRuleTargets, m.importNuGetTargets, m.importBuildCustomizationsTargets } end function m.importExtensionTargets(prj) p.push('') p.callArray(m.elements.importExtensionTargets, prj) p.pop('') end function m.importGroupTargets(prj) local groups = m.categorizeSources(prj) for _, group in ipairs(groups) do if group.category.emitExtensionTargets then group.category.emitExtensionTargets(prj, group) end end end function m.importRuleTargets(prj) for i = 1, #prj.rules do local rule = p.global.getRule(prj.rules[i]) local loc = vstudio.path(prj, p.filename(rule, ".targets")) p.x('', loc) end end local function nuGetTargetsFile(prj, package) local packageAPIInfo = vstudio.nuget2010.packageAPIInfo(prj, package) return p.vstudio.path(prj, p.filename(prj.workspace, string.format("packages\\%s.%s\\build\\native\\%s.targets", vstudio.nuget2010.packageId(package), packageAPIInfo.verbatimVersion or packageAPIInfo.version, vstudio.nuget2010.packageId(package)))) end function m.importNuGetTargets(prj) if not vstudio.nuget2010.supportsPackageReferences(prj) then for i = 1, #prj.nuget do local targetsFile = nuGetTargetsFile(prj, prj.nuget[i]) p.x('', targetsFile, targetsFile) end end end function m.importBuildCustomizationsTargets(prj) for i, build in ipairs(prj.buildcustomizations) do p.w('', path.translate(build)) end end function m.ensureNuGetPackageBuildImports(prj) if #prj.nuget > 0 then p.push('') p.push('') p.x('This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.') p.pop('') for i = 1, #prj.nuget do local targetsFile = nuGetTargetsFile(prj, prj.nuget[i]) p.x('', targetsFile, targetsFile) end p.pop('') end end function m.importDefaultProps(prj) p.w('') end function m.importLanguageSettings(prj) p.w('') end m.elements.importExtensionSettings = function(prj) return { m.importGroupSettings, m.importRuleSettings, m.importBuildCustomizationsProps } end function m.importExtensionSettings(prj) p.push('') p.callArray(m.elements.importExtensionSettings, prj) p.pop('') end function m.importGroupSettings(prj) local groups = m.categorizeSources(prj) for _, group in ipairs(groups) do if group.category.emitExtensionSettings then group.category.emitExtensionSettings(prj, group) end end end function m.importRuleSettings(prj) for i = 1, #prj.rules do local rule = p.global.getRule(prj.rules[i]) local loc = vstudio.path(prj, p.filename(rule, ".props")) p.x('', loc) end end function m.importBuildCustomizationsProps(prj) for i, build in ipairs(prj.buildcustomizations) do p.w('', path.translate(build)) end end function m.importLibrary(cfg) if cfg.kind == p.SHAREDLIB then m.element("ImportLibrary", nil, "%s", path.translate(cfg.linktarget.relpath)) end end function m.includePath(cfg) local dirs = vstudio.path(cfg, cfg.sysincludedirs) if #dirs > 0 then m.element("IncludePath", nil, "%s;$(IncludePath)", table.concat(dirs, ";")) end end function m.intDir(cfg) local objdir = vstudio.path(cfg, cfg.objdir) m.element("IntDir", nil, "%s\\", objdir) end function m.intrinsicFunctions(cfg) if cfg.intrinsics ~= nil then if cfg.intrinsics then m.element("IntrinsicFunctions", nil, "true") else m.element("IntrinsicFunctions", nil, "false") end elseif config.isOptimizedBuild(cfg) then m.element("IntrinsicFunctions", nil, "true") end end function m.keyword(prj) local isWin, isManaged, isMakefile for cfg in project.eachconfig(prj) do if cfg.system == p.WINDOWS then isWin = true end if cfg.clr ~= p.OFF then isManaged = true end if vstudio.isMakefile(cfg) then isMakefile = true end end if isWin then if isMakefile then m.element("Keyword", nil, "MakeFileProj") else if isManaged or m.isClrMixed(prj) then m.targetFramework(prj) end if isManaged then m.element("Keyword", nil, "ManagedCProj") else m.element("Keyword", nil, "Win32Proj") end m.element("RootNamespace", nil, "%s", prj.name) end end end function m.libraryPath(cfg) local dirs = vstudio.path(cfg, cfg.syslibdirs) if #dirs > 0 then m.element("LibraryPath", nil, "%s;$(LibraryPath)", table.concat(dirs, ";")) end end function m.linkIncremental(cfg) if cfg.kind ~= p.STATICLIB then m.element("LinkIncremental", nil, "%s", tostring(config.canLinkIncremental(cfg))) end end function m.linkLibraryDependencies(cfg, explicit) if explicit then p.push('') m.element("LinkLibraryDependencies", nil, "false") p.pop('') end end function m.MasmPreprocessorDefinitions(cfg, condition) if cfg.defines then m.preprocessorDefinitions(cfg, cfg.defines, false, condition) end end function m.minimalRebuild(cfg) if config.isOptimizedBuild(cfg) or cfg.flags.NoMinimalRebuild or cfg.flags.MultiProcessorCompile or cfg.debugformat == p.C7 then m.element("MinimalRebuild", nil, "false") end end function m.moduleDefinitionFile(cfg) local df = config.findfile(cfg, ".def") if df then m.element("ModuleDefinitionFile", nil, "%s", df) end end function m.multiProcessorCompilation(cfg) if cfg.flags.MultiProcessorCompile then m.element("MultiProcessorCompilation", nil, "true") end end function m.nmakeBuildCommands(cfg) m.nmakeCommandLine(cfg, cfg.buildcommands, "Build") end function m.nmakeCleanCommands(cfg) m.nmakeCommandLine(cfg, cfg.cleancommands, "Clean") end function m.nmakeCommandLine(cfg, commands, phase) if #commands > 0 then commands = os.translateCommandsAndPaths(commands, cfg.project.basedir, cfg.project.location) commands = table.concat(p.esc(commands), p.eol()) p.w('%s', phase, commands, phase) end end function m.nmakeIncludeDirs(cfg) if cfg.kind ~= p.NONE and #cfg.includedirs > 0 then local dirs = vstudio.path(cfg, cfg.includedirs) if #dirs > 0 then m.element("NMakeIncludeSearchPath", nil, "%s", table.concat(dirs, ";")) end end end function m.nmakeOutDirs(cfg) if vstudio.isMakefile(cfg) then m.outDir(cfg) m.intDir(cfg) end end function m.windowsSDKDesktopARMSupport(cfg) if cfg.system == p.WINDOWS then if cfg.architecture == p.ARM then p.w('true') end if cfg.architecture == p.ARM64 then p.w('true') end end end function m.nmakeOutput(cfg) m.element("NMakeOutput", nil, "$(OutDir)%s", cfg.buildtarget.name) end function m.nmakePreprocessorDefinitions(cfg) if cfg.kind ~= p.NONE and #cfg.defines > 0 then local defines = table.concat(cfg.defines, ";") defines = defines .. ";$(NMakePreprocessorDefinitions)" m.element('NMakePreprocessorDefinitions', nil, defines) end end function m.nmakeRebuildCommands(cfg) m.nmakeCommandLine(cfg, cfg.rebuildcommands, "ReBuild") end function m.objectFileName(fcfg) if fcfg.objname ~= fcfg.basename then m.element("ObjectFileName", m.configPair(fcfg.config), "$(IntDir)\\%s.obj", fcfg.objname) end end function m.omitDefaultLib(cfg) if cfg.flags.OmitDefaultLibrary then m.element("OmitDefaultLibName", nil, "true") end end function m.omitFramePointers(cfg) local map = { Off = "false", On = "true" } local value = map[cfg.omitframepointer] if value then m.element("OmitFramePointers", nil, value) end end function m.optimizeReferences(cfg) if config.isOptimizedBuild(cfg) then m.element("EnableCOMDATFolding", nil, "true") m.element("OptimizeReferences", nil, "true") end end function m.optimization(cfg, condition) local map = { Off="Disabled", On="Full", Debug="Disabled", Full="Full", Size="MinSpace", Speed="MaxSpeed" } local value = map[cfg.optimize] if value or not condition then m.element('Optimization', condition, value or "Disabled") end end function m.outDir(cfg) local outdir = vstudio.path(cfg, cfg.buildtarget.directory) m.element("OutDir", nil, "%s\\", outdir) end function m.executablePath(cfg) local dirs = vstudio.path(cfg, cfg.bindirs) if #dirs > 0 then dirs = table.translate(dirs, function(dir) if path.isabsolute(dir) then return dir end return "$(ProjectDir)" .. dir end) m.element("ExecutablePath", nil, "%s;$(ExecutablePath)", table.concat(dirs, ";")) end end function m.platformToolset(cfg) local tool, version = p.config.toolset(cfg) if not version then local value = p.action.current().toolset tool, version = p.tools.canonical(value) end if version then if cfg.kind == p.NONE or cfg.kind == p.MAKEFILE then if p.config.hasFile(cfg, path.iscppfile) or _ACTION >= "vs2015" then m.element("PlatformToolset", nil, version) end else m.element("PlatformToolset", nil, version) end end end function m.precompiledHeaderFile(fileName, cfg) m.element("PrecompiledHeaderFile", nil, "%s", fileName) end function m.precompiledHeader(cfg, condition) local prjcfg, filecfg = p.config.normalize(cfg) if filecfg then if prjcfg.pchsource == filecfg.abspath and not prjcfg.flags.NoPCH then m.element('PrecompiledHeader', condition, 'Create') elseif filecfg.flags.NoPCH then m.element('PrecompiledHeader', condition, 'NotUsing') end else if not prjcfg.flags.NoPCH and prjcfg.pchheader then m.element("PrecompiledHeader", nil, "Use") m.precompiledHeaderFile(prjcfg.pchheader, prjcfg) else m.element("PrecompiledHeader", nil, "NotUsing") end end end function m.preprocessorDefinitions(cfg, defines, escapeQuotes, condition) if #defines > 0 then defines = table.concat(defines, ";") if escapeQuotes then defines = defines:gsub('"', '\\"') end defines = defines .. ";%%(PreprocessorDefinitions)" m.element('PreprocessorDefinitions', condition, defines) end end function m.undefinePreprocessorDefinitions(cfg, undefines, escapeQuotes, condition) if #undefines > 0 then undefines = table.concat(undefines, ";") if escapeQuotes then undefines = undefines:gsub('"', '\\"') end undefines = undefines .. ";%%(UndefinePreprocessorDefinitions)" m.element('UndefinePreprocessorDefinitions', condition, undefines) end end local function getSymbolsPathRelative(cfg) if cfg.symbolspath and cfg.symbols ~= p.OFF and cfg.debugformat ~= "c7" then return p.project.getrelative(cfg.project, cfg.symbolspath) else return nil end end function m.programDatabaseFile(cfg) local value = getSymbolsPathRelative(cfg) if value then m.element("ProgramDatabaseFile", nil, value) end end function m.programDatabaseFileName(cfg) local value = getSymbolsPathRelative(cfg) if value then m.element("ProgramDataBaseFileName", nil, value) end end function m.projectGuid(prj) m.element("ProjectGuid", nil, "{%s}", prj.uuid) end function m.projectName(prj) if prj.name ~= prj.filename then m.element("ProjectName", nil, "%s", prj.name) end end function m.propertyGroup(cfg, label) local cond if cfg then cond = string.format(' %s', m.condition(cfg)) end if label then label = string.format(' Label="%s"', label) end p.push('', cond or "", label or "") end function m.propertySheets(cfg) p.push('', m.condition(cfg)) p.w('') p.pop('') end function m.propertySheetGroup(prj) for cfg in project.eachconfig(prj) do m.propertySheets(cfg) end end function m.referenceCopyLocalSatelliteAssemblies(prj, ref) m.element("CopyLocalSatelliteAssemblies", nil, "false") end function m.referenceLinkLibraryDependencies(prj, ref) m.element("LinkLibraryDependencies", nil, "true") end function m.referenceOutputAssembly(prj, ref) m.element("ReferenceOutputAssembly", nil, "true") end function m.referencePrivate(prj, ref) m.element("Private", nil, "true") end function m.referenceProject(prj, ref) m.element("Project", nil, "{%s}", ref.uuid) end function m.referenceUseLibraryDependences(prj, ref) m.element("UseLibraryDependencyInputs", nil, "false") end function m.resourceAdditionalIncludeDirectories(cfg) m.additionalIncludeDirectories(cfg, table.join(cfg.includedirs, cfg.resincludedirs)) end function m.resourcePreprocessorDefinitions(cfg) local defines = table.join(cfg.defines, cfg.resdefines) if cfg.exceptionhandling == p.OFF then table.insert(defines, "_HAS_EXCEPTIONS=0") end m.preprocessorDefinitions(cfg, defines, true) end function m.runtimeLibrary(cfg) local runtimes = { StaticDebug = "MultiThreadedDebug", StaticRelease = "MultiThreaded", SharedDebug = "MultiThreadedDebugDLL", SharedRelease = "MultiThreadedDLL" } local runtime = config.getruntime(cfg) if runtime then m.element("RuntimeLibrary", nil, runtimes[runtime]) end end function m.callingConvention(cfg) if cfg.callingconvention then m.element("CallingConvention", nil, cfg.callingconvention) end end function m.runtimeTypeInfo(cfg, condition) if cfg.rtti == p.OFF and ((not cfg.clr) or cfg.clr == p.OFF) then m.element("RuntimeTypeInfo", condition, "false") elseif cfg.rtti == p.ON then m.element("RuntimeTypeInfo", condition, "true") end end function m.bufferSecurityCheck(cfg) local tool, toolVersion = p.config.toolset(cfg) if cfg.flags.NoBufferSecurityCheck or (toolVersion and toolVersion:startswith("LLVM-vs")) then m.element("BufferSecurityCheck", nil, "false") end end function m.stringPooling(cfg) if cfg.stringpooling ~= nil then if cfg.stringpooling then m.element("StringPooling", nil, "true") else m.element("StringPooling", nil, "false") end elseif config.isOptimizedBuild(cfg) then m.element("StringPooling", nil, "true") end end function m.subSystem(cfg) local subsystem = iif(cfg.kind == p.CONSOLEAPP, "Console", "Windows") m.element("SubSystem", nil, subsystem) end function m.targetExt(cfg) local ext = cfg.buildtarget.extension if ext ~= "" then m.element("TargetExt", nil, "%s", ext) else p.w('') p.w('') end end function m.targetMachine(cfg) local targetmachine = { x86 = "MachineX86", x86_64 = "MachineX64", } if cfg.kind == p.STATICLIB and config.hasFile(cfg, path.isresourcefile) then local value = targetmachine[cfg.architecture] if value ~= nil then m.element("TargetMachine", nil, '%s', value) end end end function m.targetName(cfg) m.element("TargetName", nil, "%s%s", cfg.buildtarget.prefix, cfg.buildtarget.basename) end function m.targetPlatformVersion(cfgOrPrj) if _ACTION >= "vs2015" then local min = project.systemversion(cfgOrPrj) if min == "latest" then if _ACTION >= "vs2019" then min = "10.0" else min = iif(_ACTION == "vs2017", m.latestSDK10Version(), nil) end end return min end end function m.targetPlatformVersionGlobal(prj) local min = m.targetPlatformVersion(prj) if min ~= nil then m.element("WindowsTargetPlatformVersion", nil, min) end end function m.targetPlatformVersionCondition(prj, cfg) local cfgPlatformVersion = m.targetPlatformVersion(cfg) local prjPlatformVersion = m.targetPlatformVersion(prj) if cfgPlatformVersion ~= nil and cfgPlatformVersion ~= prjPlatformVersion then m.element("WindowsTargetPlatformVersion", nil, cfgPlatformVersion) end end function m.preferredToolArchitecture(prj) if _ACTION >= "vs2013" then if prj.preferredtoolarchitecture == p.X86_64 then m.element("PreferredToolArchitecture", nil, 'x64') elseif prj.preferredtoolarchitecture == p.X86 then m.element("PreferredToolArchitecture", nil, 'x86') end else if prj.preferredtoolarchitecture == p.X86_64 then m.element("UseNativeEnvironment", nil, 'true') end end end function m.treatLinkerWarningAsErrors(cfg) if cfg.flags.FatalLinkWarnings then local el = iif(cfg.kind == p.STATICLIB, "Lib", "Linker") m.element("Treat" .. el .. "WarningAsErrors", nil, "true") end end function m.treatWChar_tAsBuiltInType(cfg) local map = { On = "true", Off = "false" } local value = map[cfg.nativewchar] if value then m.element("TreatWChar_tAsBuiltInType", nil, value) end end function m.treatWarningAsError(cfg) if cfg.flags.FatalCompileWarnings and cfg.warnings ~= p.OFF then m.element("TreatWarningAsError", nil, "true") end end function m.disableSpecificWarnings(cfg, condition) if #cfg.disablewarnings > 0 then local warnings = table.concat(cfg.disablewarnings, ";") warnings = warnings .. ";%%(DisableSpecificWarnings)" m.element('DisableSpecificWarnings', condition, warnings) end end function m.treatSpecificWarningsAsErrors(cfg, condition) if #cfg.fatalwarnings > 0 then local fatal = table.concat(cfg.fatalwarnings, ";") fatal = fatal .. ";%%(TreatSpecificWarningsAsErrors)" m.element('TreatSpecificWarningsAsErrors', condition, fatal) end end function m.useDebugLibraries(cfg) local runtime = config.getruntime(cfg) or iif(config.isDebugBuild(cfg), "Debug", "Release") m.element("UseDebugLibraries", nil, tostring(runtime:endswith("Debug"))) end function m.useOfMfc(cfg) if cfg.flags.MFC then m.element("UseOfMfc", nil, iif(cfg.staticruntime == "On", "Static", "Dynamic")) end end function m.useOfAtl(cfg) if cfg.atl then m.element("UseOfATL", nil, cfg.atl) end end function m.userMacros(cfg) p.w('') end function m.warningLevel(cfg) local map = { Off = "TurnOffAllWarnings", Extra = "Level4" } m.element("WarningLevel", nil, map[cfg.warnings] or "Level3") end function m.warningLevelFile(cfg, condition) local map = { Off = "TurnOffAllWarnings", Extra = "Level4" } if cfg.warnings then m.element("WarningLevel", condition, map[cfg.warnings] or "Level3") end end function m.xmlDeclaration() p.xmlUtf8() end function m.fxCompilePreprocessorDefinition(cfg, condition) if cfg.shaderdefines and #cfg.shaderdefines > 0 then local shaderdefines = table.concat(cfg.shaderdefines, ";") shaderdefines = shaderdefines .. ";%%(PreprocessorDefinitions)" m.element('PreprocessorDefinitions', condition, shaderdefines) end end function m.fxCompileShaderType(cfg, condition) if cfg.shadertype then m.element("ShaderType", condition, cfg.shadertype) end end function m.fxCompileShaderModel(cfg, condition) if cfg.shadermodel then m.element("ShaderModel", condition, cfg.shadermodel) end end function m.fxCompileShaderEntry(cfg, condition) if cfg.shaderentry then m.element("EntryPointName", condition, cfg.shaderentry) end end function m.fxCompileShaderVariableName(cfg, condition) if cfg.shadervariablename then m.element("VariableName", condition, cfg.shadervariablename) end end function m.fxCompileShaderHeaderOutput(cfg, condition) if cfg.shaderheaderfileoutput then m.element("HeaderFileOutput", condition, cfg.shaderheaderfileoutput) end end function m.fxCompileShaderObjectOutput(cfg, condition) if cfg.shaderobjectfileoutput then m.element("ObjectFileOutput", condition, cfg.shaderobjectfileoutput) end end function m.fxCompileShaderAssembler(cfg, condition) if cfg.shaderassembler then m.element("AssemblerOutput", condition, cfg.shaderassembler) end end function m.fxCompileShaderAssemblerOutput(cfg, condition) if cfg.shaderassembleroutput then m.element("AssemblerOutputFile", condition, cfg.shaderassembleroutput) end end function m.fxCompileShaderAdditionalOptions(cfg, condition) local opts = cfg.shaderoptions if #opts > 0 then opts = table.concat(opts, " ") m.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts) end end function m.conditionFromConfigText(cfgText) return string.format('Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"', p.esc(cfgText)) end function m.condition(cfg) return m.conditionFromConfigText(vstudio.projectConfig(cfg)) end function m.latestSDK10Version() local arch = iif(os.is64bit(), "\\WOW6432Node\\", "\\") local version = os.getWindowsRegistry("HKLM:SOFTWARE" .. arch .."Microsoft\\Microsoft SDKs\\Windows\\v10.0\\ProductVersion") if version ~= nil then return version .. ".0" else return nil end end function m.element(name, condition, value, ...) local arg = {...} if select('#',...) == 0 then value = p.esc(value) else for i = 1, #arg do arg[i] = p.esc(arg[i]) end end if condition then local element = {} element.name = name element.condition = condition element.value = value element.args = arg if ... then if value == '%s' then element.setting = table.concat(arg) else element.setting = value .. table.concat(arg) end else element.setting = element.value end table.insert(m.conditionalElements, element) else local format = string.format('<%s>%s', name, value, name) p.w(format, table.unpack(arg)) end end local p = premake local project = p.project p.modules.vstudio = p.modules.vstudio or {} p.modules.vstudio._VERSION = p._VERSION p.vstudio = p.modules.vstudio include("vs2005.lua") include("vs2008.lua") include("vs2010.lua") include("vs2012.lua") include("vs2013.lua") include("vs2015.lua") include("vs2017.lua") include("vs2019.lua") p.api.register { name = "shaderoptions", scope = "config", kind = "list:string", tokens = true, pathVars = true, } p.api.register { name = "shaderdefines", scope = "config", kind = "list:string", tokens = true, } p.api.register { name = "shadertype", scope = "config", kind = "string", allowed = { "Effect", "Vertex", "Pixel", "Geometry", "Hull", "Domain", "Compute", "Texture", "RootSignature", } } p.api.register { name = "shadermodel", scope = "config", kind = "string", allowed = { "2.0", "3.0", "4.0_level_9_1", "4.0_level_9_3", "4.0", "4.1", "5.0", "rootsig_1.0", "rootsig_1.1", "6.0", "6.1", "6.2", "6.3" } } p.api.register { name = "shaderentry", scope = "config", kind = "string", tokens = true, } p.api.register { name = "shadervariablename", scope = "config", kind = "string", tokens = true, } p.api.register { name = "shaderheaderfileoutput", scope = "config", kind = "string", tokens = true, } p.api.register { name = "shaderobjectfileoutput", scope = "config", kind = "string", tokens = true, } p.api.register { name = "shaderassembler", scope = "config", kind = "string", allowed = { "NoListing", "AssemblyCode", "AssemblyCodeAndHex", } } p.api.register { name = "shaderassembleroutput", scope = "config", kind = "string", tokens = true, } p.api.register { name = "debuggerflavor", scope = "config", kind = "string", allowed = { "Local", "Remote", "WebBrowser", "WebService" } } return function(cfg) return _ACTION == "vs2005" or _ACTION == "vs2008" or _ACTION == "vs2010" or _ACTION == "vs2012" or _ACTION == "vs2013" or _ACTION == "vs2015" or _ACTION == "vs2017" or _ACTION == "vs2019" or false; end local p = premake p.make.cs = {} local make = p.make local cs = p.make.cs local project = p.project local config = p.config local fileconfig = p.fileconfig cs.elements = {} cs.elements.makefile = function(prj) return { make.header, make.phonyRules, make.csConfigs, make.csProjectConfig, make.csSources, make.csEmbedFiles, make.csCopyFiles, make.csResponseFile, make.shellType, make.csAllRules, make.csTargetRules, make.targetDirRules, make.csResponseRules, make.objDirRules, make.csCleanRules, make.preBuildRules, make.preLinkRules, make.csFileRules, } end function make.cs.generate(prj) p.eol("\n") local toolset = p.tools.dotnet p.callArray(cs.elements.makefile, prj, toolset) end cs.elements.configuration = function(cfg) return { make.csTools, make.target, make.objdir, make.csFlags, make.csLinkCmd, make.preBuildCmds, make.preLinkCmds, make.postBuildCmds, make.settings, } end function make.csConfigs(prj, toolset) for cfg in project.eachconfig(prj) do _x('ifeq ($(config),%s)', cfg.shortname) p.callArray(cs.elements.configuration, cfg, toolset) _p('endif') _p('') end end function cs.getresourcefilename(cfg, fname) if path.getextension(fname) == ".resx" then local name = cfg.buildtarget.basename .. "." local dir = path.getdirectory(fname) if dir ~= "." then name = name .. path.translate(dir, ".") .. "." end return "$(OBJDIR)/" .. p.esc(name .. path.getbasename(fname)) .. ".resources" else return fname end end function cs.listsources(prj, selector) local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) local value = selector(node) if value then _x('\t%s \\', value) end end }) end function make.csAllRules(prj, toolset) _p('all: $(TARGETDIR) $(OBJDIR) prebuild $(EMBEDFILES) $(COPYFILES) prelink $(TARGET)') _p('') end function make.csCleanRules(prj, toolset) end function make.csCopyFiles(prj, toolset) end function make.cs.getresponsefilename(prj) return '$(OBJDIR)/' .. prj.filename .. '.rsp' end function make.csResponseFile(prj, toolset) _x('RESPONSE += ' .. make.cs.getresponsefilename(prj)) end function make.csResponseRules(prj) local toolset = p.tools.dotnet local ext = make.getmakefilename(prj, true) local makefile = path.getname(p.filename(prj, ext)) local response = make.cs.getresponsefilename(prj) _p('$(RESPONSE): %s', makefile) _p('\t@echo Generating response file', prj.name) _p('ifeq (posix,$(SHELLTYPE))') _x('\t$(SILENT) rm -f $(RESPONSE)') _p('else') _x('\t$(SILENT) if exist $(RESPONSE) del %s', path.translate(response, '\\')) _p('endif') local sep = os.istarget("windows") and "\\" or "/" local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) if toolset.fileinfo(node).action == "Compile" then _x('\t@echo %s >> $(RESPONSE)', path.translate(node.relpath, sep)) end end }) _p('') end function make.csEmbedFiles(prj, toolset) local cfg = project.getfirstconfig(prj) _p('EMBEDFILES += \\') cs.listsources(prj, function(node) local fcfg = fileconfig.getconfig(node, cfg) local info = toolset.fileinfo(fcfg) if info.action == "EmbeddedResource" then return cs.getresourcefilename(cfg, node.relpath) end end) _p('') end function make.csFileRules(prj, toolset) end function make.csFlags(cfg, toolset) _p(' FLAGS =%s', make.list(toolset.getflags(cfg))) end function make.csLinkCmd(cfg, toolset) local deps = p.esc(config.getlinks(cfg, "dependencies", "fullpath")) _p(' DEPENDS =%s', make.list(deps)) _p(' REFERENCES = %s', table.implode(deps, "/r:", "", " ")) end function make.csProjectConfig(prj, toolset) local cfg = project.getfirstconfig(prj) local kindflag = "/t:" .. toolset.getkind(cfg):lower() local libdirs = table.implode(p.esc(cfg.libdirs), "/lib:", "", " ") _p('FLAGS += %s', table.concat(table.join(kindflag, libdirs), " ")) local refs = p.esc(config.getlinks(cfg, "system", "fullpath")) _p('REFERENCES += %s', table.implode(refs, "/r:", "", " ")) _p('') end function make.csSources(prj, toolset) local cfg = project.getfirstconfig(prj) _p('SOURCES += \\') cs.listsources(prj, function(node) local fcfg = fileconfig.getconfig(node, cfg) local info = toolset.fileinfo(fcfg) if info.action == "Compile" then return node.relpath end end) _p('') end function make.csTargetRules(prj, toolset) _p('$(TARGET): $(SOURCES) $(EMBEDFILES) $(DEPENDS) $(RESPONSE)') _p('\t$(SILENT) $(CSC) /nologo /out:$@ $(FLAGS) $(REFERENCES) @$(RESPONSE) $(patsubst %%,/resource:%%,$(EMBEDFILES))') _p('\t$(POSTBUILDCMDS)') _p('') end function make.csTools(cfg, toolset) _p(' CSC = %s', toolset.gettoolname(cfg, "csc")) _p(' RESGEN = %s', toolset.gettoolname(cfg, "resgen")) end HNlocal p = premake p.modules.d = {} local m = p.modules.d m._VERSION = p._VERSION m.elements = {} local api = p.api function p.project.isd(prj) return prj.language == p.D end function path.isdfile(fname) return path.hasextension(fname, { ".d" }) end function path.isdheader(fname) return path.hasextension(fname, { ".di" }) end include( "tools/dmd.lua" ) include( "tools/gdc.lua" ) include( "tools/ldc.lua" ) include( "actions/gmake.lua" ) include( "actions/vcxproj.lua" ) include( "actions/visuald.lua" ) return m local p = premake local gmake2 = p.modules.gmake2 gmake2.cpp = {} local cpp = gmake2.cpp local project = p.project local config = p.config local fileconfig = p.fileconfig cpp.elements = {} cpp.elements.makefile = function(prj) return { gmake2.header, gmake2.phonyRules, gmake2.shellType, cpp.createRuleTable, cpp.outputConfigurationSection, cpp.outputPerFileConfigurationSection, cpp.createFileTable, cpp.outputFilesSection, cpp.outputRulesSection, cpp.outputFileRuleSection, cpp.dependencies, } end function cpp.generate(prj) p.eol("\n") p.callArray(cpp.elements.makefile, prj) for cfg in project.eachconfig(prj) do cfg._gmake = nil end prj._gmake = nil end function cpp.initialize() rule 'cpp' fileExtension { ".cc", ".cpp", ".cxx", ".mm" } buildoutputs { "$(OBJDIR)/%{file.objname}.o" } buildmessage '$(notdir $<)' buildcommands {'$(CXX) %{premake.modules.gmake2.cpp.fileFlags(cfg, file)} $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"'} rule 'cc' fileExtension {".c", ".s", ".m"} buildoutputs { "$(OBJDIR)/%{file.objname}.o" } buildmessage '$(notdir $<)' buildcommands {'$(CC) %{premake.modules.gmake2.cpp.fileFlags(cfg, file)} $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"'} rule 'resource' fileExtension ".rc" buildoutputs { "$(OBJDIR)/%{file.objname}.res" } buildmessage '$(notdir $<)' buildcommands {'$(RESCOMP) $< -O coff -o "$@" $(ALL_RESFLAGS)'} global(nil) end function cpp.createRuleTable(prj) local rules = {} local function addRule(extension, rule) if type(extension) == 'table' then for _, value in ipairs(extension) do addRule(value, rule) end else rules[extension] = rule end end local usedRules = table.join({'cpp', 'cc', 'resource'}, prj.rules) for _, name in ipairs(usedRules) do local rule = p.global.getRule(name) addRule(rule.fileExtension, rule) end local filesets = { ['.o'] = 'OBJECTS', ['.obj'] = 'OBJECTS', ['.cc'] = 'SOURCES', ['.cpp'] = 'SOURCES', ['.cxx'] = 'SOURCES', ['.mm'] = 'SOURCES', ['.c'] = 'SOURCES', ['.s'] = 'SOURCES', ['.m'] = 'SOURCES', ['.rc'] = 'RESOURCES', } prj._gmake = prj._gmake or {} prj._gmake.rules = rules prj._gmake.filesets = filesets end function cpp.createFileTable(prj) for cfg in project.eachconfig(prj) do cfg._gmake = cfg._gmake or {} cfg._gmake.filesets = {} cfg._gmake.fileRules = {} local files = table.shallowcopy(prj._.files) table.foreachi(files, function(node) cpp.addFile(cfg, node) end) for _, f in pairs(cfg._gmake.filesets) do table.sort(f) end cfg._gmake.kinds = table.keys(cfg._gmake.filesets) table.sort(cfg._gmake.kinds) prj._gmake.kinds = table.join(prj._gmake.kinds or {}, cfg._gmake.kinds) end if prj.hasGeneratedFiles and p.project.iscpp(prj) then p.oven.assignObjectSequences(prj) end prj._gmake.kinds = table.unique(prj._gmake.kinds) table.sort(prj._gmake.kinds) end function cpp.addFile(cfg, node) local filecfg = fileconfig.getconfig(node, cfg) if not filecfg or filecfg.flags.ExcludeFromBuild then return end if node.generated then return end if fileconfig.hasCustomBuildRule(filecfg) then local env = table.shallowcopy(filecfg.environ) env.PathVars = { ["file.basename"] = { absolute = false, token = node.basename }, ["file.abspath"] = { absolute = true, token = node.abspath }, ["file.relpath"] = { absolute = false, token = node.relpath }, ["file.name"] = { absolute = false, token = node.name }, ["file.objname"] = { absolute = false, token = node.objname }, ["file.path"] = { absolute = true, token = node.path }, ["file.directory"] = { absolute = true, token = path.getdirectory(node.abspath) }, ["file.reldirectory"] = { absolute = false, token = path.getdirectory(node.relpath) }, } local shadowContext = p.context.extent(filecfg, env) local buildoutputs = p.project.getrelative(cfg.project, shadowContext.buildoutputs) if buildoutputs and #buildoutputs > 0 then local file = { buildoutputs = buildoutputs, source = node.relpath, buildmessage = shadowContext.buildmessage, buildcommands = shadowContext.buildcommands, buildinputs = p.project.getrelative(cfg.project, shadowContext.buildinputs) } table.insert(cfg._gmake.fileRules, file) for _, output in ipairs(buildoutputs) do cpp.addGeneratedFile(cfg, node, output) end end else cpp.addRuleFile(cfg, node) end end function cpp.determineFiletype(cfg, node) local filecfg = fileconfig.getconfig(node, cfg) local fileext = path.getextension(node.abspath):lower() if filecfg and filecfg.compileas then if p.languages.isc(filecfg.compileas) then fileext = ".c" elseif p.languages.iscpp(filecfg.compileas) then fileext = ".cpp" end end return fileext; end function cpp.addGeneratedFile(cfg, source, filename) cfg.project.hasGeneratedFiles = true local files = cfg.project._.files local node = files[filename] if not node then node = fileconfig.new(filename, cfg.project) files[filename] = node table.insert(files, node) end node.dependsOn = source node.generated = true if not fileconfig.getconfig(node, cfg) then fileconfig.addconfig(node, cfg) end local fileext = cpp.determineFiletype(cfg, node) local filesets = cfg.project._gmake.filesets local kind = filesets[fileext] or "CUSTOM" if path.isobjectfile(filename) and source.linkbuildoutputs == false then kind = "CUSTOM" end local fileset = cfg._gmake.filesets[kind] or {} table.insert(fileset, filename) cfg._gmake.filesets[kind] = fileset cpp.addRuleFile(cfg, node) end function cpp.addRuleFile(cfg, node) local rules = cfg.project._gmake.rules local fileext = cpp.determineFiletype(cfg, node) local rule = rules[fileext] if rule then local filecfg = fileconfig.getconfig(node, cfg) local environ = table.shallowcopy(filecfg.environ) if rule.propertydefinition then gmake2.prepareEnvironment(rule, environ, cfg) gmake2.prepareEnvironment(rule, environ, filecfg) end local shadowContext = p.context.extent(rule, environ) local buildoutputs = shadowContext.buildoutputs local buildmessage = shadowContext.buildmessage local buildcommands = shadowContext.buildcommands local buildinputs = shadowContext.buildinputs buildoutputs = p.project.getrelative(cfg.project, buildoutputs) if buildoutputs and #buildoutputs > 0 then local file = { buildoutputs = buildoutputs, source = node.relpath, buildmessage = buildmessage, buildcommands = buildcommands, buildinputs = buildinputs } table.insert(cfg._gmake.fileRules, file) for _, output in ipairs(buildoutputs) do cpp.addGeneratedFile(cfg, node, output) end end end end cpp.elements.configuration = function(cfg) return { cpp.tools, gmake2.target, gmake2.objdir, cpp.pch, cpp.defines, cpp.includes, cpp.forceInclude, cpp.cppFlags, cpp.cFlags, cpp.cxxFlags, cpp.resFlags, cpp.libs, cpp.ldDeps, cpp.ldFlags, cpp.linkCmd, cpp.bindirs, cpp.exepaths, gmake2.settings, gmake2.preBuildCmds, gmake2.preLinkCmds, gmake2.postBuildCmds, } end function cpp.outputConfigurationSection(prj) _p('# Configurations') _p('# #############################################') _p('') gmake2.outputSection(prj, cpp.elements.configuration) end function cpp.tools(cfg, toolset) local tool = toolset.gettoolname(cfg, "cc") if tool then _p('ifeq ($(origin CC), default)') _p(' CC = %s', tool) _p('endif' ) end tool = toolset.gettoolname(cfg, "cxx") if tool then _p('ifeq ($(origin CXX), default)') _p(' CXX = %s', tool) _p('endif' ) end tool = toolset.gettoolname(cfg, "ar") if tool then _p('ifeq ($(origin AR), default)') _p(' AR = %s', tool) _p('endif' ) end tool = toolset.gettoolname(cfg, "rc") if tool then _p('RESCOMP = %s', tool) end end function cpp.pch(cfg, toolset) if not cfg.pchheader or cfg.flags.NoPCH then return end local pch = cfg.pchheader local found = false local testname = path.join(cfg.project.basedir, pch) if os.isfile(testname) then pch = project.getrelative(cfg.project, testname) found = true else for _, incdir in ipairs(cfg.includedirs) do testname = path.join(incdir, pch) if os.isfile(testname) then pch = project.getrelative(cfg.project, testname) found = true break end end end if not found then pch = project.getrelative(cfg.project, path.getabsolute(pch)) end p.outln('PCH = ' .. pch) p.outln('PCH_PLACEHOLDER = $(OBJDIR)/$(notdir $(PCH))') p.outln('GCH = $(PCH_PLACEHOLDER).gch') end function cpp.defines(cfg, toolset) p.outln('DEFINES +=' .. gmake2.list(table.join(toolset.getdefines(cfg.defines, cfg), toolset.getundefines(cfg.undefines)))) end function cpp.includes(cfg, toolset) local includes = toolset.getincludedirs(cfg, cfg.includedirs, cfg.sysincludedirs) p.outln('INCLUDES +=' .. gmake2.list(includes)) end function cpp.forceInclude(cfg, toolset) local includes = toolset.getforceincludes(cfg) p.outln('FORCE_INCLUDE +=' .. gmake2.list(includes)) end function cpp.cppFlags(cfg, toolset) local flags = gmake2.list(toolset.getcppflags(cfg)) p.outln('ALL_CPPFLAGS += $(CPPFLAGS)' .. flags .. ' $(DEFINES) $(INCLUDES)') end function cpp.cFlags(cfg, toolset) local flags = gmake2.list(table.join(toolset.getcflags(cfg), cfg.buildoptions)) p.outln('ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS)' .. flags) end function cpp.cxxFlags(cfg, toolset) local flags = gmake2.list(table.join(toolset.getcxxflags(cfg), cfg.buildoptions)) p.outln('ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS)' .. flags) end function cpp.resFlags(cfg, toolset) local resflags = table.join(toolset.getdefines(cfg.resdefines), toolset.getincludedirs(cfg, cfg.resincludedirs), cfg.resoptions) p.outln('ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)' .. gmake2.list(resflags)) end function cpp.libs(cfg, toolset) local flags = toolset.getlinks(cfg) p.outln('LIBS +=' .. gmake2.list(flags, true)) end function cpp.ldDeps(cfg, toolset) local deps = config.getlinks(cfg, "siblings", "fullpath") p.outln('LDDEPS +=' .. gmake2.list(p.esc(deps))) end function cpp.ldFlags(cfg, toolset) local flags = table.join(toolset.getLibraryDirectories(cfg), toolset.getrunpathdirs(cfg, cfg.runpathdirs), toolset.getldflags(cfg), cfg.linkoptions) p.outln('ALL_LDFLAGS += $(LDFLAGS)' .. gmake2.list(flags)) end function cpp.linkCmd(cfg, toolset) if cfg.kind == p.STATICLIB then if cfg.architecture == p.UNIVERSAL then p.outln('LINKCMD = libtool -o "$@" $(OBJECTS)') else p.outln('LINKCMD = $(AR) -rcs "$@" $(OBJECTS)') end elseif cfg.kind == p.UTILITY then p.outln('LINKCMD =') else local cc = iif(p.languages.isc(cfg.language), "CC", "CXX") p.outln('LINKCMD = $(' .. cc .. ') -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS)') end end function cpp.bindirs(cfg, toolset) local dirs = project.getrelative(cfg.project, cfg.bindirs) if #dirs > 0 then p.outln('EXECUTABLE_PATHS = "' .. table.concat(dirs, ":") .. '"') end end function cpp.exepaths(cfg, toolset) local dirs = project.getrelative(cfg.project, cfg.bindirs) if #dirs > 0 then p.outln('EXE_PATHS = export PATH=$(EXECUTABLE_PATHS):$$PATH;') end end function cpp.outputPerFileConfigurationSection(prj) _p('# Per File Configurations') _p('# #############################################') _p('') for cfg in project.eachconfig(prj) do table.foreachi(prj._.files, function(node) local fcfg = fileconfig.getconfig(node, cfg) if fcfg then cpp.perFileFlags(cfg, fcfg) end end) end _p('') end function cpp.makeVarName(prj, value, saltValue) prj._gmake = prj._gmake or {} prj._gmake.varlist = prj._gmake.varlist or {} prj._gmake.varlistlength = prj._gmake.varlistlength or 0 local cache = prj._gmake.varlist local length = prj._gmake.varlistlength local key = value .. saltValue if (cache[key] ~= nil) then return cache[key], false end local var = string.format("PERFILE_FLAGS_%d", length) cache[key] = var prj._gmake.varlistlength = length + 1 return var, true end function cpp.perFileFlags(cfg, fcfg) local toolset = gmake2.getToolSet(cfg) local isCFile = path.iscfile(fcfg.name) local getflags = iif(isCFile, toolset.getcflags, toolset.getcxxflags) local value = gmake2.list(table.join(getflags(fcfg), fcfg.buildoptions)) if fcfg.defines or fcfg.undefines then local defs = table.join(toolset.getdefines(fcfg.defines, cfg), toolset.getundefines(fcfg.undefines)) if #defs > 0 then value = value .. gmake2.list(defs) end end if fcfg.includedirs or fcfg.sysincludedirs then local includes = toolset.getincludedirs(cfg, fcfg.includedirs, fcfg.sysincludedirs) if #includes > 0 then value = value .. gmake2.list(includes) end end if #value > 0 then local newPerFileFlag = false fcfg.flagsVariable, newPerFileFlag = cpp.makeVarName(cfg.project, value, iif(isCFile, '_C', '_CPP')) if newPerFileFlag then if isCFile then _p('%s = $(ALL_CFLAGS)%s', fcfg.flagsVariable, value) else _p('%s = $(ALL_CXXFLAGS)%s', fcfg.flagsVariable, value) end end end end function cpp.fileFlags(cfg, file) local fcfg = fileconfig.getconfig(file, cfg) local flags = {} if cfg.pchheader and not cfg.flags.NoPCH and (not fcfg or not fcfg.flags.NoPCH) then table.insert(flags, "-include $(PCH_PLACEHOLDER)") end if fcfg and fcfg.flagsVariable then table.insert(flags, string.format("$(%s)", fcfg.flagsVariable)) else local fileExt = cpp.determineFiletype(cfg, file) if path.iscfile(fileExt) then table.insert(flags, "$(ALL_CFLAGS)") elseif path.iscppfile(fileExt) then table.insert(flags, "$(ALL_CXXFLAGS)") end end return table.concat(flags, ' ') end cpp.elements.filesets = function(cfg) local result = {} for _, kind in ipairs(cfg._gmake.kinds) do for _, f in ipairs(cfg._gmake.filesets[kind]) do table.insert(result, function(cfg, toolset) cpp.outputFileset(cfg, kind, f) end) end end return result end function cpp.outputFilesSection(prj) _p('# File sets') _p('# #############################################') _p('') for _, kind in ipairs(prj._gmake.kinds) do _x('%s :=', kind) end _x('') gmake2.outputSection(prj, cpp.elements.filesets) end function cpp.outputFileset(cfg, kind, file) _x('%s += %s', kind, file) end cpp.elements.rules = function(cfg) return { cpp.allRules, cpp.targetRules, gmake2.targetDirRules, gmake2.objDirRules, cpp.cleanRules, gmake2.preBuildRules, cpp.customDeps, cpp.pchRules, } end function cpp.outputRulesSection(prj) _p('# Rules') _p('# #############################################') _p('') gmake2.outputSection(prj, cpp.elements.rules) end function cpp.allRules(cfg, toolset) if cfg.system == p.MACOSX and cfg.kind == p.WINDOWEDAPP then _p('all: $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist') _p('\t@:') _p('') _p('$(dir $(TARGETDIR))PkgInfo:') _p('$(dir $(TARGETDIR))Info.plist:') else _p('all: $(TARGET)') _p('\t@:') end _p('') end function cpp.targetRules(cfg, toolset) local targets = '' for _, kind in ipairs(cfg._gmake.kinds) do if kind ~= 'OBJECTS' and kind ~= 'RESOURCES' then targets = targets .. '$(' .. kind .. ') ' end end targets = targets .. '$(OBJECTS) $(LDDEPS)' if cfg._gmake.filesets['RESOURCES'] then targets = targets .. ' $(RESOURCES)' end _p('$(TARGET): %s | $(TARGETDIR)', targets) _p('\t$(PRELINKCMDS)') _p('\t@echo Linking %s', cfg.project.name) _p('\t$(SILENT) $(LINKCMD)') _p('\t$(POSTBUILDCMDS)') _p('') end function cpp.customDeps(cfg, toolset) for _, kind in ipairs(cfg._gmake.kinds) do if kind == 'CUSTOM' or kind == 'SOURCES' then _p('$(%s): | prebuild', kind) end end end function cpp.cleanRules(cfg, toolset) _p('clean:') _p('\t@echo Cleaning %s', cfg.project.name) _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET)') _p('\t$(SILENT) rm -rf $(OBJDIR)') _p('else') _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') _p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))') _p('endif') _p('') end function cpp.pchRules(cfg, toolset) _p('ifneq (,$(PCH))') _p('$(OBJECTS): $(GCH) | $(PCH_PLACEHOLDER)') _p('$(GCH): $(PCH) | prebuild') _p('\t@echo $(notdir $<)') local cmd = iif(p.languages.isc(cfg.language), "$(CC) -x c-header $(ALL_CFLAGS)", "$(CXX) -x c++-header $(ALL_CXXFLAGS)") _p('\t$(SILENT) %s -o "$@" -MF "$(@:%%.gch=%%.d)" -c "$<"', cmd) _p('$(PCH_PLACEHOLDER): $(GCH) | $(OBJDIR)') _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) touch "$@"') _p('else') _p('\t$(SILENT) echo $null >> "$@"') _p('endif') _p('else') _p('$(OBJECTS): | prebuild') _p('endif') _p('') end cpp.elements.fileRules = function(cfg) local funcs = {} for _, fileRule in ipairs(cfg._gmake.fileRules) do table.insert(funcs, function(cfg, toolset) cpp.outputFileRules(cfg, fileRule) end) end return funcs end function cpp.outputFileRuleSection(prj) _p('# File Rules') _p('# #############################################') _p('') gmake2.outputSection(prj, cpp.elements.fileRules) end function cpp.outputFileRules(cfg, file) local dependencies = p.esc(file.source) if file.buildinputs and #file.buildinputs > 0 then dependencies = dependencies .. " " .. table.concat(p.esc(file.buildinputs), " ") end _p('%s: %s', file.buildoutputs[1], dependencies) if file.buildmessage then _p('\t@echo %s', file.buildmessage) end if file.buildcommands then local cmds = os.translateCommandsAndPaths(file.buildcommands, cfg.project.basedir, cfg.project.location) for _, cmd in ipairs(cmds) do if cfg.bindirs and #cfg.bindirs > 0 then _p('\t$(SILENT) $(EXE_PATHS) %s', cmd) else _p('\t$(SILENT) %s', cmd) end end end if #file.buildoutputs > 1 then _p('%s: %s', table.concat({ table.unpack(file.buildoutputs, 2) }, ' '), file.buildoutputs[1]) end end function cpp.dependencies(prj) _p('-include $(OBJECTS:%%.o=%%.d)') _p('ifneq (,$(PCH))') _p(' -include $(PCH_PLACEHOLDER).d') _p('endif') end  #+3;CScslocal p = premake p.vstudio.vs2005 = {} local vs2005 = p.vstudio.vs2005 local vstudio = p.vstudio function vs2005.generateSolution(wks) p.indent("\t") p.eol("\r\n") p.escaper(vs2005.esc) p.generate(wks, ".sln", vstudio.sln2005.generate) end function vs2005.generateProject(prj) p.indent(" ") p.eol("\r\n") p.escaper(vs2005.esc) if p.project.iscsharp(prj) then p.generate(prj, ".csproj", vstudio.cs2005.generate) local user = p.capture(function() vstudio.cs2005.generateUser(prj) end) if #user > 0 then p.generate(prj, ".csproj.user", function() p.outln(user) end) end elseif p.project.isfsharp(prj) then p.generate(prj, ".fsproj", vstudio.fs2005.generate) local user = p.capture(function() vstudio.fs2005.generateUser(prj) end) if #user > 0 then p.generate(prj, ".fsproj.user", function() p.outln(user) end) end else p.generate(prj, ".vcproj", vstudio.vc200x.generate) local user = p.capture(function() vstudio.vc200x.generateUser(prj) end) if #user > 0 then p.generate(prj, ".vcproj.user", function() p.outln(user) end) end end end function vs2005.esc(value) value = string.gsub(value, '&', "&") value = value:gsub('"', """) value = value:gsub("'", "'") value = value:gsub('<', "<") value = value:gsub('>', ">") value = value:gsub('\r', " ") value = value:gsub('\n', " ") return value end newaction { trigger = "vs2005", shortname = "Visual Studio 2005", description = "Generate Visual Studio 2005 project files", targetos = "windows", toolset = "msc-v80", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = vstudio.vs2005.generateSolution, onProject = vstudio.vs2005.generateProject, onCleanWorkspace = vstudio.cleanSolution, onCleanProject = vstudio.cleanProject, onCleanTarget = vstudio.cleanTarget, vstudio = { csprojSchemaVersion = "2.0", productVersion = "8.0.50727", solutionVersion = "9", versionName = "2005", } } local p = premake p.modules.codelite = {} p.modules.codelite._VERSION = p._VERSION local codelite = p.modules.codelite local project = p.project function codelite.cfgname(cfg) local cfgname = cfg.buildcfg if codelite.workspace.multiplePlatforms then cfgname = string.format("%s|%s", cfg.platform, cfg.buildcfg) end return cfgname end function codelite.esc(value) local result = value:gsub('&', '&') result = result:gsub('<', '<') result = result:gsub('>', '>') return result end function codelite.generateWorkspace(wks) p.eol("\r\n") p.indent(" ") p.escaper(codelite.esc) p.generate(wks, ".workspace", codelite.workspace.generate) end function codelite.generateProject(prj) p.eol("\r\n") p.indent(" ") p.escaper(codelite.esc) if project.isc(prj) or project.iscpp(prj) then p.generate(prj, ".project", codelite.project.generate) end end function codelite.cleanWorkspace(wks) p.clean.file(wks, wks.name .. ".workspace") p.clean.file(wks, wks.name .. "_wsp.mk") p.clean.file(wks, wks.name .. ".tags") p.clean.file(wks, ".clang") end function codelite.cleanProject(prj) p.clean.file(prj, prj.name .. ".project") p.clean.file(prj, prj.name .. ".mk") p.clean.file(prj, prj.name .. ".list") p.clean.file(prj, prj.name .. ".out") end function codelite.cleanTarget(prj) end include("codelite_workspace.lua") include("codelite_project.lua") return codelite local p = premake local android = p.modules.android local vsandroid = p.modules.vsandroid local vc2010 = p.vstudio.vc2010 local vstudio = p.vstudio local project = p.project premake.override(vstudio.vs2010, "generateProject", function(oldfn, prj) if prj.kind == p.PACKAGING then p.eol("\r\n") p.indent(" ") p.escaper(vstudio.vs2010.esc) if project.iscpp(prj) then p.generate(prj, ".androidproj", vc2010.generate) local user = p.capture(function() vc2010.generateUser(prj) end) if #user > 0 then p.generate(prj, ".androidproj.user", function() p.outln(user) end) end end else oldfn(prj) end end) premake.override(vstudio, "projectfile", function(oldfn, prj) if prj.kind == p.PACKAGING then return premake.filename(prj, ".androidproj") else return oldfn(prj) end end) premake.override(vstudio, "tool", function(oldfn, prj) if prj.kind == p.PACKAGING then return "39E2626F-3545-4960-A6E8-258AD8476CE5" else return oldfn(prj) end end) premake.override(vc2010.elements, "globals", function (oldfn, cfg) local elements = oldfn(cfg) if cfg.kind == premake.PACKAGING then local pos = table.indexof(elements, vc2010.ignoreWarnDuplicateFilename) table.remove(elements, pos) elements = table.join(elements, { android.projectVersion }) end return elements end) function android.projectVersion(cfg) _p(2, "%s", cfg.project.name) _p(2, "14.0") _p(2, "1.0") end premake.override(vc2010.elements, "configurationProperties", function(oldfn, cfg) local elements = oldfn(cfg) if cfg.kind == p.PACKAGING then elements = { android.androidAPILevel, vc2010.useDebugLibraries, } end return elements end) premake.override(vc2010.elements, "itemDefinitionGroup", function(oldfn, cfg) local elements = oldfn(cfg) if cfg.kind == p.PACKAGING then elements = { android.antPackage, } end return elements end) premake.override(vc2010, "importDefaultProps", function(oldfn, prj) if prj.kind == p.PACKAGING then p.w('') else oldfn(prj) end end) premake.override(vc2010, "importLanguageSettings", function(oldfn, prj) if prj.kind == p.PACKAGING then p.w('') else oldfn(prj) end end) premake.override(vc2010, "propertySheets", function(oldfn, cfg) if cfg.kind ~= p.PACKAGING then oldfn(cfg) end end) premake.override(vc2010.elements, "outputProperties", function(oldfn, cfg) if cfg.kind == p.PACKAGING then return { android.outDir, vc2010.intDir, vc2010.targetName, } else return oldfn(cfg) end end) function android.outDir(cfg) vc2010.element("OutDir", nil, "%s\\", cfg.buildtarget.directory) end premake.override(vc2010, "importLanguageTargets", function(oldfn, prj) if prj.kind == p.PACKAGING then p.w('') else oldfn(prj) end end) function android.link(cfg, file) local fname = path.translate(file.relpath, '/') local link, count = fname:gsub("%.%.%/", "") local external = (count > 0) or fname:find(':', 1, true) or (file.vpath and file.vpath ~= file.relpath) if external and file.vpath ~= file.relpath then link = file.vpath end if external then vc2010.element("Link", nil, path.translate(link)) end end vc2010.categories.AndroidManifest = { name = "AndroidManifest", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "AndroidManifest", {vc2010.generatedFile, android.link, android.manifestSubType}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "AndroidManifest") end } function android.manifestSubType(cfg, file) vc2010.element("SubType", nil, "Designer") end vc2010.categories.AntBuildXml = { name = "AntBuildXml", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "AntBuildXml", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "AntBuildXml") end } vc2010.categories.AntProjectPropertiesFile = { name = "AntProjectPropertiesFile", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "AntProjectPropertiesFile", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "AntProjectPropertiesFile") end } vc2010.categories.JavaCompile = { name = "JavaCompile", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "JavaCompile", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "JavaCompile") end } vc2010.categories.Content = { name = "Content", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "Content", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "Content") end } premake.override(vc2010, "categorizeFile", function(base, prj, file) if prj.kind ~= p.PACKAGING then return base(prj, file) end local filename = path.getname(file.name):lower() local extension = path.getextension(filename) if filename == "androidmanifest.xml" then return vc2010.categories.AndroidManifest elseif filename == "build.xml" then return vc2010.categories.AntBuildXml elseif filename == "project.properties" then return vc2010.categories.AntProjectPropertiesFile elseif extension == ".java" then return vc2010.categories.JavaCompile else return vc2010.categories.Content end end) local p = premake local vstudio = p.vstudio newaction { trigger = "vs2013", shortname = "Visual Studio 2013", description = "Generate Visual Studio 2013 project files", targetos = "windows", toolset = "msc-v120", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = function(wks) vstudio.vs2005.generateSolution(wks) end, onProject = function(prj) vstudio.vs2010.generateProject(prj) end, onRule = function(rule) vstudio.vs2010.generateRule(rule) end, onCleanWorkspace = function(wks) vstudio.cleanSolution(wks) end, onCleanProject = function(prj) vstudio.cleanProject(prj) end, onCleanTarget = function(prj) vstudio.cleanTarget(prj) end, pathVars = vstudio.vs2010.pathVars, vstudio = { solutionVersion = "12", versionName = "2013", targetFramework = "4.5", toolsVersion = "12.0", filterToolsVersion = "4.0", } } (nil)local p = premake local m = p.vstudio.vc2010 m.elements.user = function(cfg) return { m.debugSettings, } end function m.generateUser(prj) local contents = {} local size = 0 for cfg in p.project.eachconfig(prj) do contents[cfg] = p.capture(function() p.push(2) p.callArray(m.elements.user, cfg) p.pop(2) end) size = size + #contents[cfg] end if size > 0 then m.xmlDeclaration() m.userProject() for cfg in p.project.eachconfig(prj) do p.push('', m.condition(cfg)) if #contents[cfg] > 0 then p.outln(contents[cfg]) end p.pop('') end p.pop('') end end function m.userProject() local action = p.action.current() p.push('', action.vstudio.userToolsVersion or action.vstudio.toolsVersion) end m.elements.debugSettings = function(cfg) return { m.localDebuggerCommand, m.localDebuggerWorkingDirectory, m.debuggerFlavor, m.localDebuggerCommandArguments, m.localDebuggerDebuggerType, m.localDebuggerEnvironment, m.localDebuggerMergeEnvironment, } end function m.debugSettings(cfg) p.callArray(m.elements.debugSettings, cfg) end function m.debuggerFlavor(cfg) local map = { Local = "WindowsLocalDebugger", Remote = "WindowsRemoteDebugger", WebBrowser = "WebBrowserDebugger", WebService = "WebServiceDebugger" } local value = map[cfg.debuggerflavor] if value then p.w('%s', value) elseif cfg.debugdir or cfg.debugcommand then p.w('WindowsLocalDebugger') end end function m.localDebuggerCommand(cfg) if cfg.debugcommand then local dir = path.translate(cfg.debugcommand) p.w('%s', dir) end end function m.localDebuggerDebuggerType(cfg) if cfg.debuggertype then p.w('%s', cfg.debuggertype) end end function m.localDebuggerCommandArguments(cfg) if #cfg.debugargs > 0 then local args = os.translateCommandsAndPaths(cfg.debugargs, cfg.project.basedir, cfg.project.location) p.x('%s', table.concat(args, " ")) end end function m.localDebuggerWorkingDirectory(cfg) if cfg.debugdir then local dir = p.vstudio.path(cfg, cfg.debugdir) p.x('%s', dir) end end function m.localDebuggerEnvironment(cfg) if #cfg.debugenvs > 0 then local envs = table.concat(cfg.debugenvs, "\n") if cfg.flags.DebugEnvsInherit then envs = envs .. "\n$(LocalDebuggerEnvironment)" end p.w('%s', envs) if cfg.flags.DebugEnvsDontMerge then p.w(2,'false') end end end function m.localDebuggerMergeEnvironment(cfg) if #cfg.debugenvs > 0 and cfg.flags.DebugEnvsDontMerge then p.w(2,'false') end end local p = premake p.option = {} local m = p.option local _OPTIONS_metatable = { __index = function(tbl, key) if type(key) == "string" then key = key:lower() end return rawget(tbl, key) end, __newindex = function(tbl, key, value) if type(key) == "string" then key = key:lower() end rawset(tbl, key, value) end } _OPTIONS = {} setmetatable(_OPTIONS, _OPTIONS_metatable) for i, arg in ipairs(_ARGV) do local key, value local i = arg:find("=", 1, true) if i then key = arg:sub(1, i - 1) value = arg:sub(i + 1) else key = arg value = "" end if key:startswith("/") then _OPTIONS[key:sub(2)] = value elseif key:startswith("--") then _OPTIONS[key:sub(3)] = value end end m.list = {} function m.add(opt) local missing for _, field in ipairs({ "description", "trigger" }) do if (not opt[field]) then missing = field end end if (missing) then error("option needs a " .. missing, 3) end p.option.list[opt.trigger:lower()] = opt if opt.default and not _OPTIONS[opt.trigger] then _OPTIONS[opt.trigger] = opt.default end end function m.get(name) return p.option.list[name] end function m.each() local keys = { } for _, option in pairs(p.option.list) do table.insert(keys, option.trigger) end table.sort(keys) local i = 0 return function() i = i + 1 return p.option.list[keys[i]] end end function m.validate(values) for key, value in pairs(values) do local opt = p.option.get(key) if (not opt) then return false, "invalid option '" .. key .. "'" end if (opt.value and value == "") then return false, "no value specified for option '" .. key .. "'" end if opt.allowed then local found = false for _, match in ipairs(opt.allowed) do if match[1] == value then found = true break end end if not found then return false, string.format("invalid value '%s' for option '%s'", value, key) end end end return true end local p = premake p.global = p.api.container("global") local global = p.global function global.new(name) return p.container.new(p.global, name) end function global.bake(self) p.container.bakeChildren(self) end function global.eachRule() local root = p.api.rootContainer() return p.container.eachChild(root, p.rule) end function global.eachWorkspace() local root = p.api.rootContainer() return p.container.eachChild(root, p.workspace) end p.alias(global, "eachWorkspace", "eachSolution") function global.getRule(key) local root = p.api.rootContainer() return root.rules[key] end function global.getRuleForFile(fname, rules) for rule in global.eachRule() do if not rules or table.contains(rules, rule.name) then if path.hasextension(fname, rule.fileextension) then return rule end end end end function global.getWorkspace(key) local root = p.api.rootContainer() return root.workspaces[key] end p.alias(global, "getWorkspace", "getSolution") local p = premake p.modules.xcode = {} local m = p.modules.xcode m._VERSION = p._VERSION m.elements = {} include("xcode_common.lua") include("xcode4_workspace.lua") include("xcode_project.lua") return m local p = premake p.tools.msc = {} local msc = p.tools.msc local project = p.project local config = p.config function msc.getcppflags(cfg) return {} end msc.shared = { clr = { On = "/clr", Unsafe = "/clr", Pure = "/clr:pure", Safe = "/clr:safe", }, flags = { FatalCompileWarnings = "/WX", MultiProcessorCompile = "/MP", NoMinimalRebuild = "/Gm-", OmitDefaultLibrary = "/Zl" }, floatingpoint = { Fast = "/fp:fast", Strict = "/fp:strict", }, floatingpointexceptions = { On = "/fp:except", Off = "/fp:except-", }, functionlevellinking = { On = "/Gy", Off = "/Gy-", }, callingconvention = { Cdecl = "/Gd", FastCall = "/Gr", StdCall = "/Gz", VectorCall = "/Gv", }, intrinsics = { On = "/Oi", }, optimize = { Off = "/Od", On = "/Ot", Debug = "/Od", Full = "/Ox", Size = "/O1", Speed = "/O2", }, vectorextensions = { AVX = "/arch:AVX", AVX2 = "/arch:AVX2", SSE = "/arch:SSE", SSE2 = "/arch:SSE2", SSE3 = "/arch:SSE2", SSSE3 = "/arch:SSE2", ["SSE4.1"] = "/arch:SSE2", }, warnings = { Extra = "/W4", High = "/W4", Off = "/W0", }, staticruntime = { _ = function(cfg) return iif(config.isDebugBuild(cfg), "/MDd", "/MD") end, Default = function(cfg) return iif(config.isDebugBuild(cfg), "/MDd", "/MD") end, On = function(cfg) return iif(config.isDebugBuild(cfg), "/MTd", "/MT") end, Off = function(cfg) return iif(config.isDebugBuild(cfg), "/MDd", "/MD") end, }, stringpooling = { On = "/GF", Off = "/GF-", }, symbols = { On = "/Z7" }, unsignedchar = { On = "/J", }, omitframepointer = { On = "/Oy" } } msc.cflags = { } function msc.getcflags(cfg) local shared = config.mapFlags(cfg, msc.shared) local cflags = config.mapFlags(cfg, msc.cflags) local flags = table.join(shared, cflags, msc.getwarnings(cfg)) return flags end msc.cxxflags = { exceptionhandling = { Default = "/EHsc", On = "/EHsc", SEH = "/EHa", }, rtti = { Off = "/GR-" } } function msc.getcxxflags(cfg) local shared = config.mapFlags(cfg, msc.shared) local cxxflags = config.mapFlags(cfg, msc.cxxflags) local flags = table.join(shared, cxxflags, msc.getwarnings(cfg)) return flags end msc.defines = { characterset = { Default = { '/D"_UNICODE"', '/D"UNICODE"' }, MBCS = '/D"_MBCS"', Unicode = { '/D"_UNICODE"', '/D"UNICODE"' }, ASCII = { }, } } function msc.getdefines(defines, cfg) local result if cfg and defines then result = config.mapFlags(cfg, msc.defines) else result = {} end for _, define in ipairs(defines) do table.insert(result, '/D"' .. define .. '"') end if cfg and cfg.exceptionhandling == p.OFF then table.insert(result, "/D_HAS_EXCEPTIONS=0") end return result end function msc.getundefines(undefines) local result = {} for _, undefine in ipairs(undefines) do table.insert(result, '/U"' .. undefine .. '"') end return result end function msc.getforceincludes(cfg) local result = {} table.foreachi(cfg.forceincludes, function(value) local fn = project.getrelative(cfg.project, value) table.insert(result, "/FI" .. p.quoted(fn)) end) return result end function msc.getrunpathdirs() return {} end function msc.getincludedirs(cfg, dirs, sysdirs) local result = {} dirs = table.join(dirs, sysdirs) for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-I' .. p.quoted(dir)) end return result end msc.linkerFlags = { flags = { FatalLinkWarnings = "/WX", LinkTimeOptimization = "/GL", NoIncrementalLink = "/INCREMENTAL:NO", NoManifest = "/MANIFEST:NO", OmitDefaultLibrary = "/NODEFAULTLIB", }, kind = { SharedLib = "/DLL", }, symbols = { On = "/DEBUG" } } msc.librarianFlags = { flags = { FatalLinkWarnings = "/WX", } } function msc.getldflags(cfg) local map = iif(cfg.kind ~= p.STATICLIB, msc.linkerFlags, msc.librarianFlags) local flags = config.mapFlags(cfg, map) table.insert(flags, 1, "/NOLOGO") for i, ignore in ipairs(cfg.ignoredefaultlibraries) do if not msc.getLibraryExtensions()[ignore:match("[^.]+$")] then ignore = path.appendextension(ignore, ".lib") end table.insert(flags, '/NODEFAULTLIB:' .. ignore) end return flags end function msc.getLibraryDirectories(cfg) local flags = {} local dirs = table.join(cfg.libdirs, cfg.syslibdirs) for i, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(flags, '/LIBPATH:"' .. dir .. '"') end return flags end function msc.getLibraryExtensions() return { ["lib"] = true, ["obj"] = true, } end function msc.getlinks(cfg, systemonly, nogroups) local links = {} if not systemonly then links = config.getlinks(cfg, "siblings", "fullpath") end local system = config.getlinks(cfg, "system", "fullpath") for i = 1, #system do local link = system[i] if not p.tools.msc.getLibraryExtensions()[link:match("[^.]+$")] then link = path.appendextension(link, ".lib") end table.insert(links, link) end return links end function msc.getmakesettings(cfg) return nil end function msc.gettoolname(cfg, tool) return nil end function msc.getwarnings(cfg) local result = {} for _, disable in ipairs(cfg.disablewarnings) do table.insert(result, '/wd"' .. disable .. '"') end for _, fatal in ipairs(cfg.fatalwarnings) do table.insert(result, '/we"' .. fatal .. '"') end return result end local semver = { _VERSION = '1.2.1', _DESCRIPTION = 'semver for Lua', _URL = 'https://github.com/kikito/semver.lua', _LICENSE = [[ MIT LICENSE Copyright (c) 2015 Enrique García Cota Permission is hereby granted, free of charge, to any person obtaining a copy of tother software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and tother permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] } local function checkPositiveInteger(number, name) assert(number >= 0, name .. ' must be a valid positive number') assert(math.floor(number) == number, name .. ' must be an integer') end local function present(value) return value and value ~= '' end local function splitByDot(str) str = str or "" local t, count = {}, 0 str:gsub("([^%.]+)", function(c) count = count + 1 t[count] = c end) return t end local function parsePrereleaseAndBuildWithSign(str) local prereleaseWithSign, buildWithSign = str:match("^(-[^+]+)(+.+)$") if not (prereleaseWithSign and buildWithSign) then prereleaseWithSign = str:match("^(-.+)$") buildWithSign = str:match("^(+.+)$") end assert(prereleaseWithSign or buildWithSign, ("The parameter %q must begin with + or - to denote a prerelease or a build"):format(str)) return prereleaseWithSign, buildWithSign end local function parsePrerelease(prereleaseWithSign) if prereleaseWithSign then local prerelease = prereleaseWithSign:match("^-(%w[%.%w-]*)$") assert(prerelease, ("The prerelease %q is not a slash followed by alphanumerics, dots and slashes"):format(prereleaseWithSign)) return prerelease end end local function parseBuild(buildWithSign) if buildWithSign then local build = buildWithSign:match("^%+(%w[%.%w-]*)$") assert(build, ("The build %q is not a + sign followed by alphanumerics, dots and slashes"):format(buildWithSign)) return build end end local function parsePrereleaseAndBuild(str) if not present(str) then return nil, nil end local prereleaseWithSign, buildWithSign = parsePrereleaseAndBuildWithSign(str) local prerelease = parsePrerelease(prereleaseWithSign) local build = parseBuild(buildWithSign) return prerelease, build end local function parseVersion(str) local sMajor, sMinor, sPatch, sPrereleaseAndBuild = str:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$") assert(type(sMajor) == 'string', ("Could not extract version number(s) from %q"):format(str)) local major, minor, patch = tonumber(sMajor), tonumber(sMinor), tonumber(sPatch) local prerelease, build = parsePrereleaseAndBuild(sPrereleaseAndBuild) return major, minor, patch, prerelease, build end local function compare(a,b) return a == b and 0 or a < b and -1 or 1 end local function compareIds(myId, otherId) if myId == otherId then return 0 elseif not myId then return -1 elseif not otherId then return 1 end local selfNumber, otherNumber = tonumber(myId), tonumber(otherId) if selfNumber and otherNumber then -- numerical comparison return compare(selfNumber, otherNumber) -- numericals are always smaller than alphanums elseif selfNumber then return -1 elseif otherNumber then return 1 else return compare(myId, otherId) -- alphanumerical comparison end end local function smallerIdList(myIds, otherIds) local myLength = #myIds local comparison for i=1, myLength do comparison = compareIds(myIds[i], otherIds[i]) if comparison ~= 0 then return comparison == -1 end -- if comparison == 0, continue loop end return myLength < #otherIds end local function smallerPrerelease(mine, other) if mine == other or not mine then return false elseif not other then return true end return smallerIdList(splitByDot(mine), splitByDot(other)) end local methods = {} function methods:nextMajor() return semver(self.major + 1, 0, 0) end function methods:nextMinor() return semver(self.major, self.minor + 1, 0) end function methods:nextPatch() return semver(self.major, self.minor, self.patch + 1) end local mt = { __index = methods } function mt:__eq(other) return self.major == other.major and self.minor == other.minor and self.patch == other.patch and self.prerelease == other.prerelease -- notice that build is ignored for precedence in semver 2.0.0 end function mt:__lt(other) if self.major ~= other.major then return self.major < other.major end if self.minor ~= other.minor then return self.minor < other.minor end if self.patch ~= other.patch then return self.patch < other.patch end return smallerPrerelease(self.prerelease, other.prerelease) -- notice that build is ignored for precedence in semver 2.0.0 end function mt:__pow(other) if self.major == 0 then return self == other end return self.major == other.major and self.minor <= other.minor end function mt:__tostring() local buffer = { ("%d.%d.%d"):format(self.major, self.minor, self.patch) } if self.prerelease then table.insert(buffer, "-" .. self.prerelease) end if self.build then table.insert(buffer, "+" .. self.build) end return table.concat(buffer) end local function new(major, minor, patch, prerelease, build) assert(major, "At least one parameter is needed") if type(major) == 'string' then major,minor,patch,prerelease,build = parseVersion(major) end patch = patch or 0 minor = minor or 0 checkPositiveInteger(major, "major") checkPositiveInteger(minor, "minor") checkPositiveInteger(patch, "patch") local result = {major=major, minor=minor, patch=patch, prerelease=prerelease, build=build} return setmetatable(result, mt) end setmetatable(semver, { __call = function(_, ...) return new(...) end }) semver._VERSION= semver(semver._VERSION) return semver local p = premake p.rule = p.api.container("rule", p.global) local rule = p.rule function rule.new(name) local self = p.container.new(rule, name) _G[name .. "Vars"] = function(vars) rule.setVars(self, vars) end local lowerName = name:gsub("^%u+", string.lower) _G[lowerName .. "Vars"] = _G[name .. "Vars"] return self end function rule.eachProperty(self) local props = self.propertydefinition local i = 0 return function () i = i + 1 if i <= #props then return props[i] end end end function rule.getProperty(self, name) local props = self.propertydefinition for i = 1, #props do local prop = props[i] if prop.name == name then return prop end end end function rule.getPropertyField(self, prop) if prop._field then return prop._field end local kind = prop.kind or "string" if kind == "list" then kind = "list:string" end local fld = p.field.new { name = "_rule_" .. self.name .. "_" .. prop.name, scope = "config", kind = kind, tokens = true, } prop._field = fld return fld end function rule.setVars(self, vars) for key, value in pairs(vars) do local prop = rule.getProperty(self, key) if not prop then error (string.format("rule '%s' does not have property '%s'", self.name, key)) end local fld = rule.getPropertyField(self, prop) p.api.storeField(fld, value) end end function rule.prepareEnvironment(self, environ, format) for _, def in ipairs(self.propertydefinition) do environ[def.name] = string.format(format, def.name) end end function rule.createEnvironment(self, format) local environ = {} rule.prepareEnvironment(self, environ, format) return environ end function rule.preparePathVars(self, pathVars, format) for _, def in ipairs(self.propertydefinition) do pathVars[def.name] = { absolute = true, token = string.format(format, def.name) } end end function rule.createPathVars(self, format) local pathVars = {} rule.preparePathVars(self, pathVars, format) return pathVars end function dofileopt(fname) if type(fname) == "string" then fname = {fname} end for i = 1, #fname do local found = os.locate(fname[i]) if not found then found = os.locate(fname[i] .. ".lua") end if found then dofile(found) return true end end end io._includedFiles = {} function include(fname) local fullPath = premake.findProjectScript(fname) fname = fullPath or fname if not io._includedFiles[fname] then io._includedFiles[fname] = true return dofile(fname) end end premake.override(_G, "require", function(base, modname, versions) local result, mod = pcall(base,modname) if not result then if (premake.downloadModule(modname, versions)) then result, mod = pcall(base, modname); end if not result then error(mod, 3) end end if mod and versions and not premake.checkVersion(mod._VERSION, versions) then error(string.format("module %s %s does not meet version criteria %s", modname, mod._VERSION or "(none)", versions), 3) end return mod end) local p = premake local m = p.vstudio.vc200x m.elements.user = function(cfg) return { m.debugSettings, } end function m.generateUser(prj) p.indent("\t") local contents = {} local size = 0 for cfg in p.project.eachconfig(prj) do contents[cfg] = p.capture(function() p.push(4) p.callArray(m.elements.user, cfg) p.pop(4) end) size = size + #contents[cfg] end if size > 0 then m.xmlElement() m.visualStudioUserFile() p.push('') for cfg in p.project.eachconfig(prj) do m.userConfiguration(cfg) p.push(' 0 then p.outln(contents[cfg]) end p.pop('/>') p.pop('') end p.pop('') p.pop('') end end function m.visualStudioUserFile() p.push('') end function m.userConfiguration(cfg) p.push('') end m.elements.debugSettings = function(cfg) return { m.debugCommand, m.debugDir, m.debugArgs, m.debugEnvironment, } end function m.debugSettings(cfg) p.callArray(m.elements.debugSettings, cfg) end function m.debugArgs(cfg) if #cfg.debugargs > 0 then p.x('CommandArguments="%s"', table.concat(cfg.debugargs, " ")) end end function m.debugCommand(cfg) if cfg.debugcommand then p.x('Command="%s"', p.vstudio.path(cfg, cfg.debugcommand)) end end function m.debugDir(cfg) if cfg.debugdir then p.x('WorkingDirectory="%s"', p.vstudio.path(cfg, cfg.debugdir)) end end function m.debugEnvironment(cfg) if #cfg.debugenvs > 0 then p.x('Environment="%s"', table.concat(cfg.debugenvs, "\n")) if cfg.flags.DebugEnvsDontMerge then p.x('EnvironmentMerge="false"') end end end (nil)local p = premake local gmake2 = p.modules.gmake2 gmake2.cs = {} local cs = gmake2.cs local project = p.project local config = p.config local fileconfig = p.fileconfig cs.elements = {} cs.elements.makefile = function(prj) return { gmake2.header, gmake2.phonyRules, gmake2.csConfigs, gmake2.csProjectConfig, gmake2.csSources, gmake2.csEmbedFiles, gmake2.csCopyFiles, gmake2.csResponseFile, gmake2.shellType, gmake2.csAllRules, gmake2.csTargetRules, gmake2.targetDirRules, gmake2.csResponseRules, gmake2.objDirRules, gmake2.csCleanRules, gmake2.preBuildRules, gmake2.csFileRules, } end function cs.generate(prj) p.eol("\n") local toolset = p.tools.dotnet p.callArray(cs.elements.makefile, prj, toolset) end cs.elements.configuration = function(cfg) return { gmake2.csTools, gmake2.target, gmake2.objdir, gmake2.csFlags, gmake2.csLinkCmd, gmake2.preBuildCmds, gmake2.preLinkCmds, gmake2.postBuildCmds, gmake2.settings, } end function gmake2.csConfigs(prj, toolset) for cfg in project.eachconfig(prj) do _x('ifeq ($(config),%s)', cfg.shortname) p.callArray(cs.elements.configuration, cfg, toolset) _p('endif') _p('') end end function cs.getresourcefilename(cfg, fname) if path.getextension(fname) == ".resx" then local name = cfg.buildtarget.basename .. "." local dir = path.getdirectory(fname) if dir ~= "." then name = name .. path.translate(dir, ".") .. "." end return "$(OBJDIR)/" .. p.esc(name .. path.getbasename(fname)) .. ".resources" else return fname end end function cs.listsources(prj, selector) local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) local value = selector(node) if value then _x('\t%s \\', value) end end }) end function gmake2.csAllRules(prj, toolset) _p('all: prebuild $(EMBEDFILES) $(COPYFILES) $(TARGET)') _p('') end function gmake2.csCleanRules(prj, toolset) end function gmake2.csCopyFiles(prj, toolset) end function cs.getresponsefilename(prj) return '$(OBJDIR)/' .. prj.filename .. '.rsp' end function gmake2.csResponseFile(prj, toolset) _x('RESPONSE += ' .. gmake2.cs.getresponsefilename(prj)) end function gmake2.csResponseRules(prj) local toolset = p.tools.dotnet local ext = gmake2.getmakefilename(prj, true) local makefile = path.getname(p.filename(prj, ext)) local response = gmake2.cs.getresponsefilename(prj) _p('$(RESPONSE): %s', makefile) _p('\t@echo Generating response file', prj.name) _p('ifeq (posix,$(SHELLTYPE))') _x('\t$(SILENT) rm -f $(RESPONSE)') _p('else') _x('\t$(SILENT) if exist $(RESPONSE) del %s', path.translate(response, '\\')) _p('endif') local sep = os.istarget("windows") and "\\" or "/" local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) if toolset.fileinfo(node).action == "Compile" then _x('\t@echo %s >> $(RESPONSE)', path.translate(node.relpath, sep)) end end }) _p('') end function gmake2.csEmbedFiles(prj, toolset) local cfg = project.getfirstconfig(prj) _p('EMBEDFILES += \\') cs.listsources(prj, function(node) local fcfg = fileconfig.getconfig(node, cfg) local info = toolset.fileinfo(fcfg) if info.action == "EmbeddedResource" then return cs.getresourcefilename(cfg, node.relpath) end end) _p('') end function gmake2.csFileRules(prj, toolset) end function gmake2.csFlags(cfg, toolset) _p(' FLAGS =%s', gmake2.list(toolset.getflags(cfg))) end function gmake2.csLinkCmd(cfg, toolset) local deps = p.esc(config.getlinks(cfg, "dependencies", "fullpath")) _p(' DEPENDS =%s', gmake2.list(deps)) _p(' REFERENCES = %s', table.implode(deps, "/r:", "", " ")) end function gmake2.csProjectConfig(prj, toolset) local cfg = project.getfirstconfig(prj) local kindflag = "/t:" .. toolset.getkind(cfg):lower() local libdirs = table.implode(p.esc(cfg.libdirs), "/lib:", "", " ") _p('FLAGS += %s', table.concat(table.join(kindflag, libdirs), " ")) local refs = p.esc(config.getlinks(cfg, "system", "fullpath")) _p('REFERENCES += %s', table.implode(refs, "/r:", "", " ")) _p('') end function gmake2.csSources(prj, toolset) local cfg = project.getfirstconfig(prj) _p('SOURCES += \\') cs.listsources(prj, function(node) local fcfg = fileconfig.getconfig(node, cfg) local info = toolset.fileinfo(fcfg) if info.action == "Compile" then return node.relpath end end) _p('') end function gmake2.csTargetRules(prj, toolset) _p('$(TARGET): $(SOURCES) $(EMBEDFILES) $(DEPENDS) $(RESPONSE) | $(TARGETDIR)') _p('\t$(PRELINKCMDS)') _p('\t$(SILENT) $(CSC) /nologo /out:$@ $(FLAGS) $(REFERENCES) @$(RESPONSE) $(patsubst %%,/resource:%%,$(EMBEDFILES))') _p('\t$(POSTBUILDCMDS)') _p('') end function gmake2.csTools(cfg, toolset) _p(' CSC = %s', toolset.gettoolname(cfg, "csc")) _p(' RESGEN = %s', toolset.gettoolname(cfg, "resgen")) end local p = premake local api = p.api api.addAllowed("system", p.ANDROID) api.addAllowed("architecture", { "armv5", "armv7", "aarch64", "mips", "mips64", "arm" }) api.addAllowed("vectorextensions", { "NEON", "MXU" }) api.addAllowed("exceptionhandling", {"UnwindTables"}) api.addAllowed("flags", { "Thumb" }) api.addAllowed("kind", p.PACKAGING) premake.action._list["vs2015"].valid_kinds = table.join(premake.action._list["vs2015"].valid_kinds, { p.PACKAGING }) premake.action._list["vs2017"].valid_kinds = table.join(premake.action._list["vs2017"].valid_kinds, { p.PACKAGING }) premake.action._list["vs2019"].valid_kinds = table.join(premake.action._list["vs2019"].valid_kinds, { p.PACKAGING }) local osoption = p.option.get("os") if osoption ~= nil then table.insert(osoption.allowed, { "android", "Android" }) end os.systemTags[p.ANDROID] = { "android", "mobile" } api.register { name = "floatabi", scope = "config", kind = "string", allowed = { "soft", "softfp", "hard", }, } api.register { name = "androidapilevel", scope = "config", kind = "integer", } api.register { name = "toolchainversion", scope = "config", kind = "string", allowed = { "4.6", -- NDK GCC versions "4.8", "4.9", "3.4", -- NDK clang versions "3.5", "3.6", "3.8", "5.0", }, } api.register { name = "stl", scope = "config", kind = "string", allowed = { "none", "gabi++", "stlport", "gnu", "libc++", }, } api.register { name = "thumbmode", scope = "config", kind = "string", allowed = { "thumb", "arm", "disabled", }, } api.register { name = "androidapplibname", scope = "config", kind = "string" } return function(cfg) return (cfg.system == p.ANDROID) end premake.override(io, "open", function(base, fname, mode) if mode and (mode:find("w") or mode:find("a")) then local dir = path.getdirectory(fname) ok, err = os.mkdir(dir) if not ok then error(err, 0) end end return base(fname, mode) end) function io.writefile(filename, content) local file = io.open(filename, "w+b") if file then file:write(content) file:close() return true end end function io.readfile(filename) local file = io.open(filename, "rb") if file then local content = file:read("*a") file:close() return content end endlocal p = premake p.tools.gcc = {} local gcc = p.tools.gcc local project = p.project local config = p.config gcc.cppflags = { system = { haiku = "-MMD", wii = { "-MMD", "-MP", "-I$(LIBOGC_INC)", "$(MACHDEP)" }, _ = { "-MMD", "-MP" } } } function gcc.getcppflags(cfg) local flags = config.mapFlags(cfg, gcc.cppflags) return flags end function gcc.getdebugformat(cfg) local flags = { Default = "", Dwarf = "dwarf", SplitDwarf = "split-dwarf", } return flags end gcc.shared = { architecture = { x86 = "-m32", x86_64 = "-m64", }, flags = { FatalCompileWarnings = "-Werror", LinkTimeOptimization = "-flto", ShadowedVariables = "-Wshadow", UndefinedIdentifiers = "-Wundef", }, floatingpoint = { Fast = "-ffast-math", Strict = "-ffloat-store", }, strictaliasing = { Off = "-fno-strict-aliasing", Level1 = { "-fstrict-aliasing", "-Wstrict-aliasing=1" }, Level2 = { "-fstrict-aliasing", "-Wstrict-aliasing=2" }, Level3 = { "-fstrict-aliasing", "-Wstrict-aliasing=3" }, }, optimize = { Off = "-O0", On = "-O2", Debug = "-Og", Full = "-O3", Size = "-Os", Speed = "-O3", }, pic = { On = "-fPIC", }, vectorextensions = { AVX = "-mavx", AVX2 = "-mavx2", SSE = "-msse", SSE2 = "-msse2", SSE3 = "-msse3", SSSE3 = "-mssse3", ["SSE4.1"] = "-msse4.1", }, isaextensions = { MOVBE = "-mmovbe", POPCNT = "-mpopcnt", PCLMUL = "-mpclmul", LZCNT = "-mlzcnt", BMI = "-mbmi", BMI2 = "-mbmi2", F16C = "-mf16c", AES = "-maes", FMA = "-mfma", FMA4 = "-mfma4", RDRND = "-mrdrnd", }, warnings = { Extra = {"-Wall", "-Wextra"}, High = "-Wall", Off = "-w", }, symbols = function(cfg, mappings) local values = gcc.getdebugformat(cfg) local debugformat = values[cfg.debugformat] or "" return { On = "-g" .. debugformat, FastLink = "-g" .. debugformat, Full = "-g" .. debugformat, } end, unsignedchar = { On = "-funsigned-char", Off = "-fno-unsigned-char" }, omitframepointer = { On = "-fomit-frame-pointer", Off = "-fno-omit-frame-pointer" } } gcc.cflags = { cdialect = { ["C89"] = "-std=c89", ["C90"] = "-std=c90", ["C99"] = "-std=c99", ["C11"] = "-std=c11", ["gnu89"] = "-std=gnu89", ["gnu90"] = "-std=gnu90", ["gnu99"] = "-std=gnu99", ["gnu11"] = "-std=gnu11", } } function gcc.getcflags(cfg) local shared_flags = config.mapFlags(cfg, gcc.shared) local cflags = config.mapFlags(cfg, gcc.cflags) local flags = table.join(shared_flags, cflags) flags = table.join(flags, gcc.getwarnings(cfg)) return flags end function gcc.getwarnings(cfg) local result = {} for _, enable in ipairs(cfg.enablewarnings) do table.insert(result, '-W' .. enable) end for _, disable in ipairs(cfg.disablewarnings) do table.insert(result, '-Wno-' .. disable) end for _, fatal in ipairs(cfg.fatalwarnings) do table.insert(result, '-Werror=' .. fatal) end return result end gcc.cxxflags = { exceptionhandling = { Off = "-fno-exceptions" }, flags = { NoBufferSecurityCheck = "-fno-stack-protector", }, cppdialect = { ["C++98"] = "-std=c++98", ["C++0x"] = "-std=c++0x", ["C++11"] = "-std=c++11", ["C++1y"] = "-std=c++1y", ["C++14"] = "-std=c++14", ["C++1z"] = "-std=c++1z", ["C++17"] = "-std=c++17", ["gnu++98"] = "-std=gnu++98", ["gnu++0x"] = "-std=gnu++0x", ["gnu++11"] = "-std=gnu++11", ["gnu++1y"] = "-std=gnu++1y", ["gnu++14"] = "-std=gnu++14", ["gnu++1z"] = "-std=gnu++1z", ["gnu++17"] = "-std=gnu++17", }, rtti = { Off = "-fno-rtti" }, visibility = { Default = "-fvisibility=default", Hidden = "-fvisibility=hidden", Internal = "-fvisibility=internal", Protected = "-fvisibility=protected", }, inlinesvisibility = { Hidden = "-fvisibility-inlines-hidden" } } function gcc.getcxxflags(cfg) local shared_flags = config.mapFlags(cfg, gcc.shared) local cxxflags = config.mapFlags(cfg, gcc.cxxflags) local flags = table.join(shared_flags, cxxflags) flags = table.join(flags, gcc.getwarnings(cfg)) return flags end function gcc.getdefines(defines) local result = {} for _, define in ipairs(defines) do table.insert(result, '-D' .. p.esc(define)) end return result end function gcc.getundefines(undefines) local result = {} for _, undefine in ipairs(undefines) do table.insert(result, '-U' .. p.esc(undefine)) end return result end function gcc.getforceincludes(cfg) local result = {} table.foreachi(cfg.forceincludes, function(value) local fn = project.getrelative(cfg.project, value) table.insert(result, string.format('-include %s', p.quoted(fn))) end) return result end function gcc.getincludedirs(cfg, dirs, sysdirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-I' .. p.quoted(dir)) end for _, dir in ipairs(sysdirs or {}) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-isystem ' .. p.quoted(dir)) end return result end function gcc.getrunpathdirs(cfg, dirs) local result = {} if not (table.contains(os.getSystemTags(cfg.system), "darwin") or (cfg.system == p.LINUX)) then return result end local rpaths = {} for _, fullpath in ipairs(cfg.runpathdirs) do local rpath = path.getrelative(cfg.buildtarget.directory, fullpath) if not (table.contains(rpaths, rpath)) then table.insert(rpaths, rpath) end end for _, sibling in ipairs(config.getlinks(cfg, "siblings", "object")) do if (sibling.kind == p.SHAREDLIB) then local fullpath = sibling.linktarget.directory local rpath = path.getrelative(cfg.buildtarget.directory, fullpath) if not (table.contains(rpaths, rpath)) then table.insert(rpaths, rpath) end end end for _, rpath in ipairs(rpaths) do if table.contains(os.getSystemTags(cfg.system), "darwin") then rpath = "@loader_path/" .. rpath elseif (cfg.system == p.LINUX) then rpath = iif(rpath == ".", "", "/" .. rpath) rpath = "$$ORIGIN" .. rpath end table.insert(result, "-Wl,-rpath,'" .. rpath .. "'") end return result end function gcc.getsharedlibarg(cfg) if table.contains(os.getSystemTags(cfg.system), "darwin") then if cfg.sharedlibtype == "OSXBundle" then return "-bundle" elseif cfg.sharedlibtype == "XCTest" then return "-bundle" elseif cfg.sharedlibtype == "OSXFramework" then return "-framework" else return "-dynamiclib" end else return "-shared" end end function gcc.ldsymbols(cfg) return iif(table.contains(os.getSystemTags(cfg.system), "darwin"), "-Wl,-x", "-s") end gcc.ldflags = { architecture = { x86 = "-m32", x86_64 = "-m64", }, flags = { LinkTimeOptimization = "-flto", }, kind = { SharedLib = function(cfg) local r = { gcc.getsharedlibarg(cfg) } if cfg.system == p.WINDOWS and not cfg.flags.NoImportLib then table.insert(r, '-Wl,--out-implib="' .. cfg.linktarget.relpath .. '"') elseif cfg.system == p.LINUX then table.insert(r, '-Wl,-soname=' .. p.quoted(cfg.linktarget.name)) elseif table.contains(os.getSystemTags(cfg.system), "darwin") then table.insert(r, '-Wl,-install_name,' .. p.quoted('@rpath/' .. cfg.linktarget.name)) end return r end, WindowedApp = function(cfg) if cfg.system == p.WINDOWS then return "-mwindows" end end, }, system = { wii = "$(MACHDEP)", }, symbols = { Off = gcc.ldsymbols, Default = gcc.ldsymbols, } } function gcc.getldflags(cfg) local flags = config.mapFlags(cfg, gcc.ldflags) return flags end gcc.libraryDirectories = { architecture = { x86 = function (cfg) local r = {} if not table.contains(os.getSystemTags(cfg.system), "darwin") then table.insert (r, "-L/usr/lib32") end return r end, x86_64 = function (cfg) local r = {} if not table.contains(os.getSystemTags(cfg.system), "darwin") then table.insert (r, "-L/usr/lib64") end return r end, }, system = { wii = "-L$(LIBOGC_LIB)", } } function gcc.getLibraryDirectories(cfg) local flags = {} for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do table.insert(flags, '-L' .. p.quoted(dir)) end if cfg.flags.RelativeLinks then for _, dir in ipairs(config.getlinks(cfg, "siblings", "directory")) do local libFlag = "-L" .. p.project.getrelative(cfg.project, dir) if not table.contains(flags, libFlag) then table.insert(flags, libFlag) end end end for _, dir in ipairs(cfg.syslibdirs) do table.insert(flags, '-L' .. p.quoted(dir)) end local gccFlags = config.mapFlags(cfg, gcc.libraryDirectories) flags = table.join(flags, gccFlags) return flags end function gcc.getlinks(cfg, systemonly, nogroups) local result = {} if not systemonly then if cfg.flags.RelativeLinks then local libFiles = config.getlinks(cfg, "siblings", "basename") for _, link in ipairs(libFiles) do if string.startswith(link, "lib") then link = link:sub(4) end table.insert(result, "-l" .. link) end else result = config.getlinks(cfg, "siblings", "fullpath") end end if not nogroups and #result > 1 and (cfg.linkgroups == p.ON) then table.insert(result, 1, "-Wl,--start-group") table.insert(result, "-Wl,--end-group") end local links = config.getlinks(cfg, "system", "fullpath") local static_syslibs = {"-Wl,-Bstatic"} local shared_syslibs = {} for _, link in ipairs(links) do if path.isframework(link) then table.insert(result, "-framework") table.insert(result, path.getbasename(link)) elseif path.isobjectfile(link) then table.insert(result, link) else local endswith = function(s, ptrn) return ptrn == string.sub(s, -string.len(ptrn)) end local name = path.getname(link) if endswith(name, ":static") then name = string.sub(name, 0, -8) table.insert(static_syslibs, "-l" .. name) elseif endswith(name, ":shared") then name = string.sub(name, 0, -8) table.insert(shared_syslibs, "-l" .. name) else table.insert(shared_syslibs, "-l" .. name) end end end local move = function(a1, a2) local t = #a2 for i = 1, #a1 do a2[t + i] = a1[i] end end if #static_syslibs > 1 then table.insert(static_syslibs, "-Wl,-Bdynamic") move(static_syslibs, result) end move(shared_syslibs, result) return result end gcc.makesettings = { system = { wii = [[ ifeq ($(strip $(DEVKITPPC)),) $(error "DEVKITPPC environment variable is not set")' endif include $(DEVKITPPC)/wii_rules']] } } function gcc.getmakesettings(cfg) local settings = config.mapFlags(cfg, gcc.makesettings) return table.concat(settings) end gcc.tools = { cc = "gcc", cxx = "g++", ar = "ar", rc = "windres" } function gcc.gettoolname(cfg, tool) if (cfg.gccprefix and gcc.tools[tool]) or tool == "rc" then return (cfg.gccprefix or "") .. gcc.tools[tool] end return nil end if http == nil then return end function http.reportProgress(total, current) local width = 70 local progress = math.floor(current * width / total) if progress == width then io.write(string.rep(' ', width + 2) .. '\r') else io.write('[' .. string.rep('=', progress) .. string.rep(' ', width - progress) .. ']\r') end end function http.escapeUrlParam(param) local url_encodings = { [' '] = '%%20', ['!'] = '%%21', ['"'] = '%%22', ['#'] = '%%23', ['$'] = '%%24', ['&'] = '%%26', ['\''] = '%%27', ['('] = '%%28', [')'] = '%%29', ['*'] = '%%2A', ['+'] = '%%2B', ['-'] = '%%2D', ['.'] = '%%2E', ['/'] = '%%2F', [':'] = '%%3A', [';'] = '%%3B', ['<'] = '%%3C', ['='] = '%%3D', ['>'] = '%%3E', ['?'] = '%%3F', ['@'] = '%%40', ['['] = '%%5B', ['\\'] = '%%5C', [']'] = '%%5D', ['^'] = '%%5E', ['_'] = '%%5F', ['`'] = '%%60' } param = param:gsub('%%', '%%25') for k,v in pairs(url_encodings) do param = param:gsub('%' .. k, v) end return param endlocal p = premake local m = p.modules.d m.visuald = {} require ("vstudio") local vstudio = p.vstudio local workspace = p.workspace local project = p.project local config = p.config local tree = p.tree for k,v in pairs({ "vs2005", "vs2008", "vs2010", "vs2012", "vs2013", "vs2015", "vs2017", "vs2019" }) do local vs = p.action.get(v) if vs ~= nil then table.insert( vs.valid_languages, p.D ) vs.valid_tools.dc = { "dmd", "gdc", "ldc" } p.override(vs, "onProject", function(oldfn, prj) oldfn(prj) if project.isd(prj) then p.generate(prj, ".visualdproj", m.visuald.generate) end end) end end p.override(project, "isnative", function(oldfn, prj) return project.isd(prj) or oldfn(prj) end) p.override(vstudio, "projectfile", function(oldfn, prj) if project.isd(prj) then return p.filename(prj, ".visualdproj") end return oldfn(prj) end) p.override(vstudio, "tool", function(oldfn, prj) if project.isd(prj) then return "002A2DE9-8BB6-484D-9802-7E4AD4084715" end return oldfn(prj) end) m.elements.project = function(prj) return { m.visuald.header, m.visuald.globals, m.visuald.projectConfigurations, m.visuald.files, } end function m.visuald.generate(prj) p.eol("\r\n") p.indent(" ") p.callArray(m.elements.project, prj) _p('') end function m.visuald.header(prj) _p('') end function m.visuald.globals(prj) _p(1,'{%s}', prj.uuid) end function m.visuald.projectConfigurations(prj) for cfg in project.eachconfig(prj) do local prjPlatform = p.esc(vstudio.projectPlatform(cfg)) local slnPlatform = vstudio.solutionPlatform(cfg) local is64bit = slnPlatform == "x64" -- TODO: this seems like a hack _p(1,'', prjPlatform, slnPlatform) _p(2,'0') _p(2,'0') local isWindows = false local isDebug = string.find(cfg.buildcfg, 'Debug') ~= nil local isOptimised = config.isOptimizedBuild(cfg) if cfg.kind == p.CONSOLEAPP then _p(2,'0') _p(2,'1') elseif cfg.kind == p.STATICLIB then _p(2,'1') _p(2,'0') elseif cfg.kind == p.SHAREDLIB then _p(2,'2') _p(2,'0') -- SHOULD THIS BE '2' (windows)?? else _p(2,'0') _p(2,'2') isWindows = true end _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.flags.Profile, '1', '0')) _p(2,'%s', iif(cfg.flags.Quiet, '1', '0')) _p(2,'%s', iif(cfg.flags.Verbose, '1', '0')) _p(2,'0') _p(2,'%s', iif(cfg.symbols == p.ON or cfg.symbols == "FastLink" or cfg.symbols == "Full", iif(cfg.flags.SymbolsLikeC, '2', '1'), '0')) _p(2,'%s', iif(isOptimised, '1', '0')) _p(2,'0') _p(2,'%s', iif(is64bit, '1', '0')) _p(2,'0') _p(2,'0') _p(2,'%s', iif(isWindows, '1', '0')) _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.deprecatedfeatures == "Allow", '1', '0')) _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.boundscheck == "Off", '1', '0')) _p(2,'0') _p(2,'%s', iif(cfg.flags.UnitTest, '1', '0')) _p(2,'%s', iif(cfg.flags.Inline or isOptimised, '1', '0')) _p(2,'%s', iif(cfg.flags.Release or not isDebug, '1', '0')) _p(2,'0') _p(2,'%s', iif(cfg.flags.FatalCompileWarnings, '1', '0')) _p(2,'%s', iif(cfg.warnings and cfg.warnings ~= "Off", '1', '0')) _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.pic == "On", '1', '0')) _p(2,'%s', iif(cfg.flags.CodeCoverage, '1', '0')) _p(2,'%s', iif(cfg.floatingpoint and cfg.floatingpoint == "None", '1', '0')) _p(2,'2') _p(2,'0') local compiler = { dmd="0", gdc="1", ldc="2" } m.visuald.element(2, "compiler", compiler[_OPTIONS.dc or cfg.toolset or "dmd"]) m.visuald.element(2, "otherDMD", '0') m.visuald.element(2, "program", '$(DMDInstallDir)windows\\bin\\dmd.exe') local impdirs if #cfg.importdirs > 0 then impdirs = vstudio.path(cfg, cfg.importdirs) end m.visuald.element(2, "imppath", impdirs) m.visuald.element(2, "fileImppath") m.visuald.element(2, "outdir", path.translate(project.getrelative(cfg.project, cfg.buildtarget.directory))) m.visuald.element(2, "objdir", path.translate(project.getrelative(cfg.project, cfg.objdir))) m.visuald.element(2, "objname") m.visuald.element(2, "libname") m.visuald.element(2, "doDocComments", iif(cfg.flags.Documentation, '1', '0')) m.visuald.element(2, "docdir", cfg.docdir) m.visuald.element(2, "docname", cfg.docname) m.visuald.element(2, "modules_ddoc") m.visuald.element(2, "ddocfiles") m.visuald.element(2, "doHdrGeneration", iif(cfg.flags.GenerateHeader, '1', '0')) m.visuald.element(2, "hdrdir", cfg.headerdir) m.visuald.element(2, "hdrname", cfg.headername) m.visuald.element(2, "doXGeneration", iif(cfg.flags.GenerateJSON, '1', '0')) m.visuald.element(2, "xfilename", '$(IntDir)\\$(TargetName).json') m.visuald.element(2, "debuglevel", iif(cfg.debuglevel, tostring(cfg.debuglevel), '0')) m.visuald.element(2, "debugids", cfg.debugconstants) m.visuald.element(2, "versionlevel", iif(cfg.versionlevel, tostring(cfg.versionlevel), '0')) m.visuald.element(2, "versionids", cfg.versionconstants) _p(2,'0') _p(2,'0') _p(2,'%s', iif(cfg.kind ~= p.SHAREDLIB or cfg.flags.NoImportLib, '0', '1')) _p(2,'') _p(2,'') _p(2,'') _p(2,'0') _p(2,'') _p(2,'1') -- we will just leave this always enabled, since it's ignored if no debuginfo is written _p(2,'$(VisualDInstallDir)cv2pdb\\cv2pdb.exe') _p(2,'0') _p(2,'0') _p(2,'0') _p(2,'') _p(2,'') _p(2,'') local links local explicit = vstudio.needsExplicitLink(cfg) local toolset = config.toolset(cfg) if toolset then links = toolset.getlinks(cfg, not explicit) else local scope = iif(explicit, "all", "system") links = config.getlinks(cfg, scope, "fullpath") end m.visuald.element(2, "libfiles", table.concat(links, " ")) m.visuald.element(2, "libpaths", cfg.libdirs) _p(2,'') _p(2,'') local target = config.gettargetinfo(cfg) _p(2,'$(OutDir)\\%s', target.name) _p(2,'1') local runtime = 0 if not cfg.flags.OmitDefaultLibrary then if config.isDebugBuild(cfg) then runtime = iif(cfg.flags.StaticRuntime, "2", "4") else runtime = iif(cfg.flags.StaticRuntime, "1", "3") end end m.visuald.element(2, "cRuntime", runtime) local additionalOptions if #cfg.buildoptions > 0 then additionalOptions = table.concat(cfg.buildoptions, " ") end if #cfg.linkoptions > 0 then local linkOpts = table.implode(cfg.linkoptions, "-L", "", " ") if additionalOptions then additionalOptions = additionalOptions .. " " .. linkOpts else additionalOptions = linkOpts end end m.visuald.element(2, "additionalOptions", additionalOptions) if #cfg.prebuildcommands > 0 then _p(2,'%s',p.esc(table.implode(cfg.prebuildcommands, "", "", "\r\n"))) else _p(2,'') end if #cfg.postbuildcommands > 0 then _p(2,'%s',p.esc(table.implode(cfg.postbuildcommands, "", "", "\r\n"))) else _p(2,'') end _p(2,'*.obj;*.cmd;*.build;*.json;*.dep;*.o') _p(1,'') end end function m.visuald.files(prj) _p(1,'', prj.name) local tr = project.getsourcetree(prj) tree.traverse(tr, { onbranchenter = function(node, depth) _p(depth, '', node.name) end, onbranchexit = function(node, depth) _p(depth, '') end, onleaf = function(node, depth) _p(depth, '', path.translate(node.relpath)) end }, false, 2) _p(1,'') end function m.visuald.fileConfiguration(prj, node, depth) end function m.visuald.element(depth, name, value, ...) local isTable = type(value) == "table" if not value or (isTable and #value == 0) then _p(depth, '<%s />', name) else if isTable then value = p.esc(table.implode(value, "", "", ";")) _p(depth, '<%s>%s', name, value, name) else if select('#',...) == 0 then value = p.esc(value) end _x(depth, string.format('<%s>%s', name, value, name), ...) end end end local p = premake p.vstudio.vs2010.rules.xml = {} local m = p.vstudio.vs2010.rules.xml m.elements = {} m.elements.project = function(r) return { m.projectSchemaDefinitions, m.rule, m.ruleItem, m.fileExtension, m.contentType, } end function m.generate(r) p.xmlUtf8() p.callArray(m.elements.project, r) p.out('') end m.elements.rule = function(r) return { m.dataSource, m.categories, m.inputs, m.properties, m.commandLineTemplate, m.beforeTargets, m.afterTargets, m.outputs, m.executionDescription, m.additionalDependencies, m.additionalOptions, } end function m.rule(r) p.push('') p.callArray(m.elements.rule, r) p.pop('') end function m.categories(r) local categories = { [1] = { name="General" }, } local propCategory = {} local defs = r.propertydefinition for i = 1, #defs do local def = defs[i] local cat = def.category if cat then if type(cat) == "string" and cat ~= "Command Line" and cat ~= "General" then if not propCategory[cat] then table.insert(categories, { name=cat }) propCategory[cat] = true end else def.category = nil end end end table.insert(categories, { name="Command Line", subtype="CommandLine" }) p.push('') for i = 1, #categories do m.category(categories[i]) end p.pop('') end function m.category(cat) local attribs = p.capture(function() p.push() p.w('Name="%s"', cat.name) if cat.subtype then p.w('Subtype="%s"', cat.subtype) end p.pop() end) p.push('') p.push('') p.w('%s', cat.name) p.pop('') p.pop('') end function m.properties(r) local defs = r.propertydefinition for i = 1, #defs do local def = defs[i] if def.kind == "boolean" then m.boolProperty(def) elseif def.kind == "list" then m.stringListProperty(def) elseif type(def.values) == "table" then m.enumProperty(def) elseif def.kind and def.kind:startswith("list:") then m.stringListProperty(def) else m.stringProperty(def) end end end function m.baseProperty(def, suffix) local c = p.capture(function () p.w('Name="%s"', def.name) p.w('HelpContext="0"') p.w('DisplayName="%s"', def.display or def.name) if def.description then p.w('Description="%s"', def.description) end if def.category then p.w('Category="%s"', def.category) end end) if suffix then c = c .. suffix end p.outln(c) end function m.boolProperty(def) p.push('') p.pop() end function m.enumProperty(def) p.push('') local values = def.values local switches = def.switch or {} local keys = table.keys(def.values) table.sort(keys) for _, key in pairs(keys) do p.push('') p.pop() end p.pop('') end function m.stringProperty(def) p.push('') p.pop() end function m.stringListProperty(def) p.push('') p.pop() end function m.additionalDependencies(r) p.push('') p.pop() end function m.additionalOptions(r) p.push('') p.push('') p.w('Additional Options') p.pop('') p.push('') p.w('Additional Options') p.pop('') p.pop('') end function m.afterTargets(r) p.push('') p.push('') p.w('Execute After') p.pop('') p.push('') p.w('Specifies the targets for the build customization to run after.') p.pop('') p.push('') p.push('', r.name) p.pop() p.pop('') p.push('') p.push('') p.pop() p.pop('') p.pop('') end function m.beforeTargets(r) p.push('') p.push('') p.w('Execute Before') p.pop('') p.push('') p.w('Specifies the targets for the build customization to run before.') p.pop('') p.push('') p.push('', r.name) p.pop() p.pop('') p.push('') p.push('') p.pop() p.pop('') p.pop('') end function m.commandLineTemplate(r) p.push('') p.pop() end function m.contentType(r) p.push('', r.name) p.pop() end function m.dataSource(r) p.push('') p.push('', r.name) p.pop() p.pop('') end function m.executionDescription(r) p.push('') p.pop() end function m.fileExtension(r) for _, v in ipairs(r.fileextension) do p.push('', r.name) p.pop() end end function m.inputs(r) p.push('') p.push('') p.push('') p.pop() p.pop('') p.pop('') end function m.outputs(r) p.push('') p.pop() end function m.ruleItem(r) p.push('', r.display or r.name) p.pop() end function m.projectSchemaDefinitions(r) p.push('') end local p = premake p.vstudio.vs2010 = {} local vs2010 = p.vstudio.vs2010 local vstudio = p.vstudio local project = p.project local tree = p.tree vs2010.pathVars = { ["cfg.objdir"] = { absolute = true, token = "$(IntDir)" }, ["prj.location"] = { absolute = true, token = "$(ProjectDir)" }, ["prj.name"] = { absolute = false, token = "$(ProjectName)" }, ["sln.location"] = { absolute = true, token = "$(SolutionDir)" }, ["sln.name"] = { absolute = false, token = "$(SolutionName)" }, ["wks.location"] = { absolute = true, token = "$(SolutionDir)" }, ["wks.name"] = { absolute = false, token = "$(SolutionName)" }, ["cfg.buildtarget.directory"] = { absolute = false, token = "$(TargetDir)" }, ["cfg.buildtarget.name"] = { absolute = false, token = "$(TargetFileName)" }, ["cfg.buildtarget.basename"] = { absolute = false, token = "$(TargetName)" }, ["file.basename"] = { absolute = false, token = "%(Filename)" }, ["file.abspath"] = { absolute = true, token = "%(FullPath)" }, ["file.relpath"] = { absolute = false, token = "%(Identity)" }, ["file.path"] = { absolute = false, token = "%(Identity)" }, ["file.directory"] = { absolute = true, token = "%(RootDir)%(Directory)" }, ["file.reldirectory"] = { absolute = false, token = "%(RelativeDir)" }, ["file.extension"] = { absolute = false, token = "%(Extension)" }, ["file.name"] = { absolute = false, token = "%(Filename)%(Extension)" }, } function vs2010.generateProject(prj) p.eol("\r\n") p.indent(" ") p.escaper(vs2010.esc) if p.project.iscsharp(prj) then p.generate(prj, ".csproj", vstudio.cs2005.generate) local user = p.capture(function() vstudio.cs2005.generateUser(prj) end) if #user > 0 then p.generate(prj, ".csproj.user", function() p.outln(user) end) end elseif p.project.isfsharp(prj) then p.generate(prj, ".fsproj", vstudio.fs2005.generate) local user = p.capture(function() vstudio.fs2005.generateUser(prj) end) if #user > 0 then p.generate(prj, ".fsproj.user", function() p.outln(user) end) end elseif p.project.isc(prj) or p.project.iscpp(prj) then local projFileModified = p.generate(prj, ".vcxproj", vstudio.vc2010.generate) local user = p.capture(function() vstudio.vc2010.generateUser(prj) end) if #user > 0 then p.generate(prj, ".vcxproj.user", function() p.outln(user) end) end if tree.hasbranches(project.getsourcetree(prj)) then if p.generate(prj, ".vcxproj.filters", vstudio.vc2010.generateFilters) == true and projFileModified == false then p.touch(prj, ".vcxproj") end end end if not vstudio.nuget2010.supportsPackageReferences(prj) then local packages = p.capture(function() vstudio.nuget2010.generatePackagesConfig(prj) end) if #packages > 0 then p.generate(prj, "packages.config", function() p.outln(packages) end) end local config = p.capture(function() vstudio.nuget2010.generateNuGetConfig(prj) end) if #config > 0 then p.generate(prj, "NuGet.Config", function() p.outln(config) end) end end end function vs2010.generateRule(rule) p.eol("\r\n") p.indent(" ") p.escaper(vs2010.esc) p.generate(rule, ".props", vs2010.rules.props.generate) p.generate(rule, ".targets", vs2010.rules.targets.generate) p.generate(rule, ".xml", vs2010.rules.xml.generate) end function vs2010.esc(value) value = value:gsub('&', "&") value = value:gsub('<', "<") value = value:gsub('>', ">") return value end newaction { trigger = "vs2010", shortname = "Visual Studio 2010", description = "Generate Visual Studio 2010 project files", targetos = "windows", toolset = "msc-v100", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = function(wks) vstudio.vs2005.generateSolution(wks) end, onProject = function(prj) vstudio.vs2010.generateProject(prj) end, onRule = function(rule) vstudio.vs2010.generateRule(rule) end, onCleanWorkspace = function(wks) vstudio.cleanSolution(wks) end, onCleanProject = function(prj) vstudio.cleanProject(prj) end, onCleanTarget = function(prj) vstudio.cleanTarget(prj) end, pathVars = vs2010.pathVars, vstudio = { csprojSchemaVersion = "2.0", productVersion = "8.0.30703", solutionVersion = "11", versionName = "2010", targetFramework = "4.0", toolsVersion = "4.0", } } local p = premake p.fileconfig = {} local fileconfig = p.fileconfig local context = p.context local project = p.project fileconfig.fcfg_mt = {} fileconfig.fsub_mt = {} function fileconfig.new(fname, prj) local environ = { } local fcfg = context.new(prj, environ) context.copyFilters(fcfg, prj) context.addFilter(fcfg, "files", fname:lower()) for key, value in pairs(prj.environ) do environ[key] = value end environ.file = fcfg context.compile(fcfg) fcfg.project = prj fcfg.workspace = prj.workspace fcfg.configs = {} fcfg.abspath = fname context.basedir(fcfg, prj.location) setmetatable(fcfg, fileconfig.fcfg_mt) local vpath = project.getvpath(prj, fname) if vpath ~= fcfg.abspath then fcfg.vpath = vpath end return fcfg end function fileconfig.addconfig(fcfg, cfg) local prj = cfg.project local wks = cfg.workspace local environ = {} local fsub = context.new(prj, environ) context.copyFilters(fsub, fcfg) context.mergeFilters(fsub, cfg) fcfg.configs[cfg] = fsub for key, value in pairs(cfg.environ) do environ[key] = value end for key, value in pairs(fcfg.environ) do environ[key] = value end context.compile(fsub) fsub.abspath = fcfg.abspath fsub.vpath = fcfg.vpath fsub.config = cfg fsub.project = prj fsub.workspace = wks context.basedir(fsub, prj.location) return setmetatable(fsub, fileconfig.fsub_mt) end function fileconfig.getconfig(fcfg, cfg) return fcfg.configs[cfg] end function fileconfig.hasCustomBuildRule(fcfg) return fcfg and (#fcfg.buildcommands > 0) and (#fcfg.buildoutputs > 0) end function fileconfig.hasFileSettings(fcfg) if not fcfg then return false end for key, field in pairs(p.fields) do if field.scopes[1] == "config" then local value = fcfg[field.name] if value then if type(value) == "table" then if #value > 0 then return true end else return true end end end end return false end local fcfg_mt = fileconfig.fcfg_mt fcfg_mt.__index = function(fcfg, key) if type(fcfg_mt[key]) == "function" then return fcfg_mt[key](fcfg) end return context.__mt.__index(fcfg, key) end fileconfig.fsub_mt.__index = function(fsub, key) if type(fcfg_mt[key]) == "function" then return fcfg_mt[key](fsub) end return context.__mt.__index(fsub, key) end function fcfg_mt.basename(fcfg) return path.getbasename(fcfg.abspath) end function fcfg_mt.directory(fcfg) return path.getdirectory(fcfg.abspath) end function fcfg_mt.reldirectory(fcfg) return path.getdirectory(fcfg.relpath) end function fcfg_mt.name(fcfg) return path.getname(fcfg.abspath) end function fcfg_mt.objname(fcfg) if fcfg.sequence ~= nil and fcfg.sequence > 0 then return fcfg.basename .. fcfg.sequence else return fcfg.basename end end function fcfg_mt.path(fcfg) return fcfg.relpath end function fcfg_mt.relpath(fcfg) return project.getrelative(fcfg.project, fcfg.abspath) end function fcfg_mt.vpath(fcfg) return fcfg.relpath end function fcfg_mt.extension(fcfg) return path.getextension(fcfg.abspath) end local p = premake p.project = p.api.container("project", p.workspace, { "config" }) local project = p.project local tree = p.tree external = externalproject function project.new(name) local prj = p.container.new(project, name) prj.uuid = os.uuid(name) if p.api.scope.group then prj.group = p.api.scope.group.name else prj.group = "" end return prj end function project.eachconfig(prj) local configs = prj._cfglist local count = #configs local seen = {} local i = 0 return function () i = i + 1 if i <= count then local cfg = project.getconfig(prj, configs[i][1], configs[i][2]) if not seen[cfg] then seen[cfg] = true return cfg else i = i + 1 end end end end function project.findClosestMatch(prj, buildcfg, platform) buildcfg = project.mapconfig(prj, buildcfg)[1] platform = project.mapconfig(prj, platform)[1] if not table.contains(prj.configurations, buildcfg) then buildcfg = prj.configurations[1] end if not table.contains(prj.platforms, platform) then platform = prj.platforms[1] end return project.getconfig(prj, buildcfg, platform) end function project.getconfig(prj, buildcfg, platform) if not buildcfg then return prj end local pairing = project.mapconfig(prj, buildcfg, platform) buildcfg = pairing[1] platform = pairing[2] local key = (buildcfg or "*") .. (platform or "") return prj.configs[key] end function project.getdependencies(prj, mode) if not prj.dependencies then prj.dependencies = {} end local m = mode or 'all' local result = prj.dependencies[m] if result then return result end local function add_to_project_list(cfg, depproj, result) local dep = p.workspace.findproject(cfg.workspace, depproj) if dep and not table.contains(result, dep) then table.insert(result, dep) end end local linkOnly = m == 'linkOnly' local depsOnly = m == 'dependOnly' result = {} for cfg in project.eachconfig(prj) do if not depsOnly then for _, link in ipairs(cfg.links) do if link ~= prj.name then add_to_project_list(cfg, link, result) end end end if not linkOnly then for _, depproj in ipairs(cfg.dependson) do add_to_project_list(cfg, depproj, result) end end end prj.dependencies[m] = result return result end function project.getfirstconfig(prj) local iter = project.eachconfig(prj) local first = iter() return first end function project.getrelative(prj, filename) if type(filename) == "table" then local result = {} for i, name in ipairs(filename) do result[i] = project.getrelative(prj, name) end return result else if filename then local result = filename if path.hasdeferredjoin(result) then result = path.resolvedeferredjoin(result) end return path.getrelative(prj.location, result) end end end function project.getsourcetree(prj, sorter) if prj._.sourcetree then return prj._.sourcetree end local tr = tree.new(prj.name) table.foreachi(prj._.files, function(fcfg) if fcfg.generated then return; end local flags if fcfg.vpath ~= fcfg.relpath then flags = { trim = false } end local parent = tree.add(tr, path.getdirectory(fcfg.vpath), flags) local node = tree.insert(parent, tree.new(path.getname(fcfg.vpath))) setmetatable(node, { __index = fcfg }) end) table.foreachi(prj._.files, function(fcfg) if not fcfg.generated then return; end local parent = tree.add(tr, path.getdirectory(fcfg.dependsOn.vpath)) local node = tree.insert(parent, tree.new(path.getname(fcfg.vpath))) setmetatable(node, { __index = fcfg }) end) tree.trimroot(tr) tree.sort(tr, sorter) prj._.sourcetree = tr return tr end function project.getvpath(prj, abspath) local vpath = abspath local fname = path.getname(abspath) local max = abspath:len() - fname:len() for _, vpaths in ipairs(prj.vpaths) do for replacement, patterns in pairs(vpaths) do for _, pattern in ipairs(patterns) do local i = abspath:find(path.wildcards(pattern)) if i == 1 then i = pattern:find("*", 1, true) or (pattern:len() + 1) local leaf if i < max then leaf = abspath:sub(i) else leaf = fname end if leaf:startswith("/") then leaf = leaf:sub(2) end local stem = "" if replacement:len() > 0 then stem, stars = replacement:gsub("%*", "") if stars == 0 then leaf = path.getname(leaf) end else leaf = path.getname(leaf) end vpath = path.join(stem, leaf) return vpath end end end end return vpath end function project.hasConfig(prj, func) for cfg in project.eachconfig(prj) do if func(cfg) then return true end end end function project.hasfile(prj, filename) return (prj._.files[filename] ~= nil) end function project.isdotnet(prj) return p.languages.iscsharp(prj.language) or p.languages.isfsharp(prj.language) end function project.iscsharp(prj) return p.languages.iscsharp(prj.language) end function project.isfsharp(prj) return p.languages.isfsharp(prj.language) end function project.isc(prj) return p.languages.isc(prj.language) end function project.iscpp(prj) return p.languages.iscpp(prj.language) end function project.isnative(prj) return project.isc(prj) or project.iscpp(prj) end function project.mapconfig(prj, buildcfg, platform) local pairing = { buildcfg, platform } local testpattern = function(pattern, pairing, i) local j = 1 while i <= #pairing and j <= #pattern do local wd = path.wildcards(pattern[j]) if pairing[i]:match(wd) ~= pairing[i] then return false end i = i + 1 j = j + 1 end return true end local maps = prj.configmap or {} for mi = 1, #maps do for pattern, replacements in pairs(maps[mi]) do if type(pattern) ~= "table" then pattern = { pattern } end for i = 1, #pairing do if testpattern(pattern, pairing, i) then if #pattern == 1 and #replacements == 1 then pairing[i] = replacements[1] else pairing = { replacements[1], replacements[2] } end end end end end return pairing end function project.systemversion(prj) if prj.systemversion ~= nil then local values = string.explode(prj.systemversion, ":", true) return values[1], values[2] end end local p = premake p.tools.gdc = { } local gdc = p.tools.gdc local project = p.project local config = p.config local d = p.modules.d gdc.dc = "gdc" gdc.dflags = { architecture = { x86 = "-m32", x86_64 = "-m64", }, flags = { Documentation= "-fdoc", FatalWarnings= "-Werror", GenerateHeader= "-fintfc", GenerateJSON= "-fX", RetainPaths= "-op", SymbolsLikeC= "-fdebug-c", UnitTest= "-funittest", Verbose= "-fd-verbose", ShowTLS= "-fd-vtls", ShowDependencies= "-fdeps", }, boundscheck = { Off = "-fno-bounds-check", }, deprecatedfeatures = { Allow = "-fdeprecated", }, floatingpoint = { Fast = "-ffast-math", Strict = "-ffloat-store", }, optimize = { Off = "-O0", On = "-O2 -finline-functions", Debug = "-Og", Full = "-O3 -finline-functions", Size = "-Os -finline-functions", Speed = "-O3 -finline-functions", }, pic = { On = "-fPIC", }, vectorextensions = { AVX = "-mavx", SSE = "-msse", SSE2 = "-msse2", }, warnings = { High = "-Wall", Extra = "-Wall -Wextra", }, symbols = { On = "-g", FastLink = "-g", Full = "-g -gf", } } function gdc.getdflags(cfg) local flags = config.mapFlags(cfg, gdc.dflags) if config.isDebugBuild(cfg) then table.insert(flags, "-fdebug") else table.insert(flags, "-frelease") end if cfg.flags.Documentation then if cfg.docname then table.insert(flags, "-fdoc-file=" .. p.quoted(cfg.docname)) end if cfg.docdir then table.insert(flags, "-fdoc-dir=" .. p.quoted(cfg.docdir)) end end if cfg.flags.GenerateHeader then if cfg.headername then table.insert(flags, "-fintfc-file=" .. p.quoted(cfg.headername)) end if cfg.headerdir then table.insert(flags, "-fintfc-dir=" .. p.quoted(cfg.headerdir)) end end return flags end function gdc.getversions(versions, level) local result = {} for _, version in ipairs(versions) do table.insert(result, '-fversion=' .. version) end if level then table.insert(result, '-fversion=' .. level) end return result end function gdc.getdebug(constants, level) local result = {} for _, constant in ipairs(constants) do table.insert(result, '-fdebug=' .. constant) end if level then table.insert(result, '-fdebug=' .. level) end return result end function gdc.getimportdirs(cfg, dirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-I' .. p.quoted(dir)) end return result end function gdc.getstringimportdirs(cfg, dirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-J' .. p.quoted(dir)) end return result end function gdc.gettarget(name) return "-o " .. name end gdc.ldflags = { architecture = { x86 = { "-m32" }, x86_64 = { "-m64" }, }, kind = { SharedLib = function(cfg) local r = { iif(cfg.system == p.MACOSX, "-dynamiclib", "-shared") } if cfg.system == "windows" and not cfg.flags.NoImportLib then table.insert(r, '-Wl,--out-implib="' .. cfg.linktarget.relpath .. '"') end return r end, WindowedApp = function(cfg) if cfg.system == p.WINDOWS then return "-mwindows" end end, }, } function gdc.getldflags(cfg) local flags = config.mapFlags(cfg, gdc.ldflags) return flags end gdc.libraryDirectories = { architecture = { x86 = "-L/usr/lib", x86_64 = "-L/usr/lib64", } } function gdc.getLibraryDirectories(cfg) local flags = config.mapFlags(cfg, gdc.libraryDirectories) for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do table.insert(flags, '-Wl,-L' .. project.getrelative(cfg.project, dir)) end return flags end function gdc.getlinks(cfg, systemonly) local result = {} local links if not systemonly then links = config.getlinks(cfg, "siblings", "object") for _, link in ipairs(links) do if not link.project.external then if link.kind == p.STATICLIB then table.insert(result, "-Wl," .. project.getrelative(cfg.project, link.linktarget.abspath)) else table.insert(result, "-Wl,-l" .. link.linktarget.basename) end end end end links = config.getlinks(cfg, "system", "fullpath") for _, link in ipairs(links) do if path.isframework(link) then table.insert(result, "-framework " .. path.getbasename(link)) elseif path.isobjectfile(link) then table.insert(result, "-Wl," .. link) else table.insert(result, "-Wl,-l" .. path.getbasename(link)) end end return result end gdc.makesettings = { } function gdc.getmakesettings(cfg) local settings = config.mapFlags(cfg, gdc.makesettings) return table.concat(settings) end gdc.tools = { ps3 = { dc = "ppu-lv2-gdc", ar = "ppu-lv2-ar", }, } function gdc.gettoolname(cfg, tool) local names = gdc.tools[cfg.architecture] or gdc.tools[cfg.system] or {} local name = names[tool] return name or gdc[tool] end local p = premake p.vstudio.fs2005 = {} local vstudio = p.vstudio local fs2005 = p.vstudio.fs2005 local dotnetbase = p.vstudio.dotnetbase local project = p.project local config = p.config local fileconfig = p.fileconfig local dotnet = p.tools.dotnet fs2005.elements = {} fs2005.elements.project = function () return { dotnetbase.xmlDeclaration, dotnetbase.projectElement, dotnetbase.commonProperties, dotnetbase.projectProperties, dotnetbase.configurations, dotnetbase.applicationIcon, dotnetbase.references } end fs2005.elements.projectProperties = function () return { dotnetbase.configurationCondition, dotnetbase.platformCondition, dotnetbase.schemaVersion, dotnetbase.productVersion, dotnetbase.projectGuid, dotnetbase.outputType, dotnetbase.appDesignerFolder, dotnetbase.rootNamespace, dotnetbase.assemblyName, dotnetbase.targetFrameworkVersion, dotnetbase.targetFrameworkProfile, dotnetbase.projectTypeGuids } end fs2005.elements.configuration = function () return { dotnetbase.propertyGroup, dotnetbase.debugProps, dotnetbase.outputProps, dotnetbase.compilerProps, dotnetbase.NoWarn, fs2005.tailCalls } end function fs2005.generate(prj) dotnetbase.prepare(fs2005) dotnetbase.generate(prj) end function fs2005.tailCalls(cfg) local tc if cfg.tailcalls == nil then tc = config.isDebugBuild(cfg) else tc = cfg.tailcalls end _p(2, '%s', iif(tc, "true", "false")) end function fs2005.targets(prj) _p(1, '') _p(2, '') _p(3, '') _p(4, '$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\FSharp\\Microsoft.FSharp.Targets') _p(3, '') _p(2, '') _p(2, '') _p(2, '') _p(3, '$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)\\FSharp\\Microsoft.FSharp.Targets') _p(2, '') _p(2, '') _p(1, '') _p(1, '') end local p = premake local project = p.project newaction { trigger = "gmake2", shortname = "Alternative GNU Make", description = "Generate GNU makefiles for POSIX, MinGW, and Cygwin", toolset = "gcc", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Utility", "Makefile" }, valid_languages = { "C", "C++", "C#" }, valid_tools = { cc = { "clang", "gcc" }, dotnet = { "mono", "msnet", "pnet" } }, onInitialize = function() require("gmake2") p.modules.gmake2.cpp.initialize() end, onWorkspace = function(wks) p.escaper(p.modules.gmake2.esc) p.generate(wks, p.modules.gmake2.getmakefilename(wks, false), p.modules.gmake2.generate_workspace) end, onProject = function(prj) p.escaper(p.modules.gmake2.esc) local makefile = p.modules.gmake2.getmakefilename(prj, true) if prj.kind == p.UTILITY then p.generate(prj, makefile, p.modules.gmake2.utility.generate) elseif prj.kind == p.MAKEFILE then p.generate(prj, makefile, p.modules.gmake2.makefile.generate) else if project.isdotnet(prj) then p.generate(prj, makefile, p.modules.gmake2.cs.generate) elseif project.isc(prj) or project.iscpp(prj) then p.generate(prj, makefile, p.modules.gmake2.cpp.generate) end end end, onCleanWorkspace = function(wks) p.clean.file(wks, p.modules.gmake2.getmakefilename(wks, false)) end, onCleanProject = function(prj) p.clean.file(prj, p.modules.gmake2.getmakefilename(prj, true)) end } return function(cfg) return (_ACTION == "gmake2") end local p = premake p.modules.gmake = {} p.modules.gmake._VERSION = p._VERSION p.make = p.modules.gmake local make = p.make local project = p.project function make.defaultconfig(target) local eachconfig = iif(target.project, project.eachconfig, p.workspace.eachconfig) local defaultconfig = nil if target.defaultplatform then for cfg in eachconfig(target) do if cfg.platform == target.defaultplatform then defaultconfig = cfg break end end end if not defaultconfig then local iter = eachconfig(target) defaultconfig = iter() end if defaultconfig then _p('ifndef config') _x(' config=%s', defaultconfig.shortname) _p('endif') _p('') end end function make.esc(value) result = value:gsub("\\", "\\\\") result = result:gsub("\"", "\\\"") result = result:gsub(" ", "\\ ") result = result:gsub("%(", "\\(") result = result:gsub("%)", "\\)") result = result:gsub("$\\%((.-)\\%)", "$(%1)") return result end function make.getmakefilename(this, searchprjs) local count = 0 for wks in p.global.eachWorkspace() do if wks.location == this.location then count = count + 1 end if searchprjs then for _, prj in ipairs(wks.projects) do if prj.location == this.location then count = count + 1 end end end end if count == 1 then return "Makefile" else return ".make" end end function make.header(target) local kind = iif(target.project, "project", "workspace") _p('# %s %s makefile autogenerated by Premake', p.action.current().shortname, kind) _p('') if kind == "workspace" then local haspch = false for _, prj in ipairs(target.projects) do for cfg in project.eachconfig(prj) do if cfg.pchheader then haspch = true end end end if haspch then _p('.NOTPARALLEL:') _p('') end end make.defaultconfig(target) _p('ifndef verbose') _p(' SILENT = @') _p('endif') _p('') end function make.mkdir(dirname) _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) mkdir -p %s', dirname) _p('else') _p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', dirname) _p('endif') end function make.mkdirRules(dirname) _p('%s:', dirname) _p('\t@echo Creating %s', dirname) make.mkdir(dirname) _p('') end function make.list(value, quoted) quoted = false if #value > 0 then if quoted then local result = "" for _, v in ipairs (value) do if #result then result = result .. " " end result = result .. p.quoted(v) end return result else return " " .. table.concat(value, " ") end else return "" end end function make.tovar(value) value = value:gsub("[ -]", "_") value = value:gsub("[()]", "") return value end function make.objdir(cfg) _x(' OBJDIR = %s', p.esc(project.getrelative(cfg.project, cfg.objdir))) end function make.objDirRules(prj) make.mkdirRules("$(OBJDIR)") end function make.phonyRules(prj) _p('.PHONY: clean prebuild prelink') _p('') end function make.buildCmds(cfg, event) _p(' define %sCMDS', event:upper()) local steps = cfg[event .. "commands"] local msg = cfg[event .. "message"] if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) msg = msg or string.format("Running %s commands", event) _p('\t@echo %s', msg) _p('\t%s', table.implode(steps, "", "", "\n\t")) end _p(' endef') end function make.preBuildCmds(cfg, toolset) make.buildCmds(cfg, "prebuild") end function make.preBuildRules(prj) _p('prebuild:') _p('\t$(PREBUILDCMDS)') _p('') end function make.preLinkCmds(cfg, toolset) make.buildCmds(cfg, "prelink") end function make.preLinkRules(prj) _p('prelink:') _p('\t$(PRELINKCMDS)') _p('') end function make.postBuildCmds(cfg, toolset) make.buildCmds(cfg, "postbuild") end function make.settings(cfg, toolset) if #cfg.makesettings > 0 then for _, value in ipairs(cfg.makesettings) do _p(value) end end local value = toolset.getmakesettings(cfg) if value then _p(value) end end function make.shellType() _p('SHELLTYPE := posix') _p('ifeq (.exe,$(findstring .exe,$(ComSpec)))') _p('\tSHELLTYPE := msdos') _p('endif') _p('') end function make.target(cfg) _x(' TARGETDIR = %s', project.getrelative(cfg.project, cfg.buildtarget.directory)) _x(' TARGET = $(TARGETDIR)/%s', cfg.buildtarget.name) end function make.targetDirRules(prj) make.mkdirRules("$(TARGETDIR)") end include("gmake_cpp.lua") include("gmake_csharp.lua") include("gmake_makefile.lua") include("gmake_utility.lua") include("gmake_workspace.lua") return p.modules.gmake local p = premake p.tree = {} local tree = p.tree function tree.new(n) local t = { name = n, children = {} } return t end function tree.add(tr, p, extraFields) if p == "." or p == "/" then return tr end local parentnode = tree.add(tr, path.getdirectory(p), extraFields) local childname = path.getname(p) local childnode = parentnode.children[childname] if not childnode or childnode.path ~= p then childnode = tree.insert(parentnode, tree.new(childname)) childnode.path = p if extraFields then for k,v in pairs(extraFields) do childnode[k] = v end end end return childnode end function tree.insert(parent, child) table.insert(parent.children, child) if child.name then parent.children[child.name] = child end child.parent = parent return child end function tree.getlocalpath(node) if node.parent.path then return node.name elseif node.cfg then return node.cfg.name else return node.path end end function tree.hasbranches(tr) local n = #tr.children if n > 0 then for i = 1, n do if #tr.children[i].children > 0 then return true end end end return false end function tree.isparent(n, child) local p = child.parent while p do if p == n then return true end p = p.parent end return false end function tree.remove(node) local children = node.parent.children for i = 1, #children do if children[i] == node then table.remove(children, i) end end node.children = {} end function tree.sort(tr, fn) if not fn then fn = function(a,b) return a.name < b.name end end tree.traverse(tr, { onnode = function(node) table.sort(node.children, fn) end }, true) end function tree.traverse(t, fn, includeroot, initialdepth) local donode, dochildren donode = function(node, fn, depth) if node.isremoved then return end if fn.onnode then fn.onnode(node, depth) end if #node.children > 0 then if fn.onbranchenter then fn.onbranchenter(node, depth) end if fn.onbranch then fn.onbranch(node, depth) end dochildren(node, fn, depth + 1) if fn.onbranchexit then fn.onbranchexit(node, depth) end else if fn.onleaf then fn.onleaf(node, depth) end end end dochildren = function(parent, fn, depth) local i = 1 while i <= #parent.children do local node = parent.children[i] donode(node, fn, depth) if node == parent.children[i] then i = i + 1 end end end if not initialdepth then initialdepth = 0 end if includeroot then donode(t, fn, initialdepth) else dochildren(t, fn, initialdepth) end end function tree.trimroot(tr) local trimmed while #tr.children == 1 do local node = tr.children[1] if #node.children == 0 or node.trim == false then break end trimmed = true local numChildren = #node.children for i = 1, numChildren do local child = node.children[i] child.parent = node.parent tr.children[i] = child end end local dotdot local count = #tr.children repeat dotdot = false for i = 1, count do local node = tr.children[i] if node.name == ".." and #node.children == 1 then local child = node.children[1] child.parent = node.parent tr.children[i] = child trimmed = true dotdot = true end end until not dotdot if trimmed then tree.traverse(tr, { onnode = function(node) if node.parent.path then node.path = path.join(node.parent.path, node.name) else node.path = node.name end end }, false) end end local p = premake p.tools.clang = {} local clang = p.tools.clang local gcc = p.tools.gcc local config = p.config function clang.getcppflags(cfg) local flags = gcc.getcppflags(cfg) return flags end clang.shared = { architecture = gcc.shared.architecture, flags = gcc.shared.flags, floatingpoint = { Fast = "-ffast-math", }, strictaliasing = gcc.shared.strictaliasing, optimize = { Off = "-O0", On = "-O2", Debug = "-O0", Full = "-O3", Size = "-Os", Speed = "-O3", }, pic = gcc.shared.pic, vectorextensions = gcc.shared.vectorextensions, isaextensions = gcc.shared.isaextensions, warnings = gcc.shared.warnings, symbols = gcc.shared.symbols, unsignedchar = gcc.shared.unsignedchar, omitframepointer = gcc.shared.omitframepointer } clang.cflags = table.merge(gcc.cflags, { }) function clang.getcflags(cfg) local shared = config.mapFlags(cfg, clang.shared) local cflags = config.mapFlags(cfg, clang.cflags) local flags = table.join(shared, cflags) flags = table.join(flags, clang.getwarnings(cfg)) return flags end function clang.getwarnings(cfg) return gcc.getwarnings(cfg) end clang.cxxflags = table.merge(gcc.cxxflags, { }) function clang.getcxxflags(cfg) local shared = config.mapFlags(cfg, clang.shared) local cxxflags = config.mapFlags(cfg, clang.cxxflags) local flags = table.join(shared, cxxflags) flags = table.join(flags, clang.getwarnings(cfg)) return flags end function clang.getdefines(defines) local flags = gcc.getdefines(defines) return flags end function clang.getundefines(undefines) local flags = gcc.getundefines(undefines) return flags end function clang.getforceincludes(cfg) local flags = gcc.getforceincludes(cfg) return flags end function clang.getincludedirs(cfg, dirs, sysdirs) local flags = gcc.getincludedirs(cfg, dirs, sysdirs) return flags end clang.getrunpathdirs = gcc.getrunpathdirs function clang.getsharedlibarg(cfg) return gcc.getsharedlibarg(cfg) end clang.ldflags = { architecture = { x86 = "-m32", x86_64 = "-m64", }, flags = { LinkTimeOptimization = "-flto", }, kind = { SharedLib = function(cfg) local r = { clang.getsharedlibarg(cfg) } if cfg.system == "windows" and not cfg.flags.NoImportLib then table.insert(r, '-Wl,--out-implib="' .. cfg.linktarget.relpath .. '"') elseif cfg.system == p.LINUX then table.insert(r, '-Wl,-soname=' .. p.quoted(cfg.linktarget.name)) elseif table.contains(os.getSystemTags(cfg.system), "darwin") then table.insert(r, '-Wl,-install_name,' .. p.quoted('@rpath/' .. cfg.linktarget.name)) end return r end, WindowedApp = function(cfg) if cfg.system == p.WINDOWS then return "-mwindows" end end, }, system = { wii = "$(MACHDEP)", } } function clang.getldflags(cfg) local flags = config.mapFlags(cfg, clang.ldflags) return flags end function clang.getLibraryDirectories(cfg) local flags = gcc.getLibraryDirectories(cfg) return flags end function clang.getlinks(cfg, systemonly, nogroups) return gcc.getlinks(cfg, systemonly, nogroups) end function clang.getmakesettings(cfg) local flags = gcc.getmakesettings(cfg) return flags end clang.tools = { cc = "clang", cxx = "clang++", ar = "ar" } function clang.gettoolname(cfg, tool) return clang.tools[tool] end local p = premake p.vstudio.vs2010.rules = {} p.vstudio.vs2010.rules.props = {} local m = p.vstudio.vs2010.rules.props m.elements = {} m.elements.project = function(r) return { p.vstudio.projectElement, m.targetsGroup, m.dependsOnGroup, m.ruleGroup, } end function m.generate(r) p.xmlUtf8() p.callArray(m.elements.project, r) p.pop() p.out('') end m.elements.targetsGroup = function(r) return { m.beforeTargets, m.afterTargets, } end function m.targetsGroup(r) p.w('', r.name, r.name) p.callArray(m.elements.targetsGroup, r) p.pop('') end m.elements.dependsOnGroup = function(r) return { m.dependsOn, } end function m.dependsOnGroup(r) p.push('') p.callArray(m.elements.dependsOnGroup, r) p.pop('') end m.elements.ruleGroup = function(r) return { m.propertyDefaults, m.commandLineTemplates, m.executionDescription, m.additionalDependencies, } end function m.ruleGroup(r) p.push('') p.push('<%s>', r.name) p.callArray(m.elements.ruleGroup, r) p.pop('', r.name) p.pop('') end function m.propertyDefaults(r) local defs = r.propertydefinition for i = 1, #defs do local def = defs[i] local value = def.value if value then if def.kind == "path" then value = path.translate(value) end p.w('<%s>%s', def.name, value, def.name) end end end function m.additionalDependencies(r) local deps = table.concat(r.builddependencies, ";") p.x('%s', deps) end function m.afterTargets(r) p.w('<%sAfterTargets>CustomBuild', r.name, r.name) end function m.beforeTargets(r) p.w('<%sBeforeTargets>Midl', r.name, r.name) end function m.commandLineTemplates(r) local env = p.rule.createEnvironment(r, "[%s]") local ctx = p.context.extent(r, env) local buildcommands = ctx.buildcommands if buildcommands and #buildcommands > 0 then local cmds = os.translateCommands(buildcommands, p.WINDOWS) cmds = table.concat(cmds, p.eol()) p.x('%s', cmds) end end function m.dependsOn(r) p.w('<%sDependsOn', r.name) p.w(' Condition="\'$(ConfigurationType)\' != \'Makefile\'">_SelectedFiles;$(%sDependsOn)', r.name, r.name, r.name) end function m.executionDescription(r) local env = p.rule.createEnvironment(r, "%%(%s)") local ctx = p.context.extent(r, env) local buildmessage = ctx.buildmessage if buildmessage and #buildmessage > 0 then p.x('%s', buildmessage) end end local p = premake p.configset = {} local configset = p.configset local criteria = p.criteria function configset.new(parent) local cset = {} cset.parent = parent cset.blocks = {} cset.current = nil cset.compiled = false return cset end function configset.fetch(cset, field, filter, ctx, origin) filter = filter or {} ctx = ctx or {} if p.field.merges(field) then return configset._fetchMerged(cset, field, filter, ctx, origin) else return configset._fetchDirect(cset, field, filter, ctx, origin) end end function configset._dofilter(cset, block, filter) if not filter.matcher then return (cset.compiled or criteria.matches(block._criteria, filter)) else return filter.matcher(cset, block, filter) end end function configset._fetchDirect(cset, field, filter, ctx, origin) if origin and origin ~= cset and not origin.compiled then return configset._fetchDirect(origin, field, filter, ctx, origin) end local abspath = filter.files local basedir local key = field.name local blocks = cset.blocks local n = #blocks for i = n, 1, -1 do local block = blocks[i] if not origin or block._origin == origin then local value = block[key] if value ~= nil and abspath and not cset.compiled and block._basedir and block._basedir ~= basedir then basedir = block._basedir filter.files = path.getrelative(basedir, abspath) end if value ~= nil and configset._dofilter(cset, block, filter) then if type(value) == "table" then value = table.deepcopy(value) end if field.tokens and ctx.environ then value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) end return value end end end filter.files = abspath if cset.parent then return configset._fetchDirect(cset.parent, field, filter, ctx, origin) end end function configset._fetchMerged(cset, field, filter, ctx, origin) if origin and origin ~= cset and not origin.compiled then return configset._fetchMerged(origin, field, filter, ctx, origin) end local result = {} local function remove(patterns) for _, pattern in ipairs(patterns) do if field.tokens and ctx.environ then pattern = p.detoken.expand(pattern, ctx.environ, field, ctx._basedir) end pattern = path.wildcards(pattern):lower() local j = 1 while j <= #result do local value = result[j]:lower() if value:match(pattern) == value then result[result[j]] = nil table.remove(result, j) else j = j + 1 end end end end if cset.parent then result = configset._fetchMerged(cset.parent, field, filter, ctx, origin) end local abspath = filter.files local basedir local key = field.name local blocks = cset.blocks local n = #blocks for i = 1, n do local block = blocks[i] if not origin or block._origin == origin then if abspath and block._basedir and block._basedir ~= basedir and not cset.compiled then basedir = block._basedir filter.files = path.getrelative(basedir, abspath) end if configset._dofilter(cset, block, filter) then if block._removes and block._removes[key] then remove(block._removes[key]) end local value = block[key] if type(value) == "table" then value = table.deepcopy(value) end if value then if field.tokens and ctx.environ then value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) end if field and p.field.translates(field) then value = p.field.translate(field, value) end result = p.field.merge(field, result, value) end end end end filter.files = abspath return result end function configset.metatable(cset) return { __newindex = function(tbl, key, value) local f = p.field.get(key) if f then local status, err = configset.store(cset, f, value) if err then error(err, 2) end else rawset(tbl, key, value) return value end end, __index = function(tbl, key) local f = p.field.get(key) if f then return configset.fetch(cset, f) else return nil end end } end function configset.addblock(cset, terms, basedir) configset.addFilter(cset, terms, basedir, true) return cset.current end function configset.addFilter(cset, terms, basedir, unprefixed) local crit, err = criteria.new(terms, unprefixed) if not crit then return nil, err end local block = {} block._criteria = crit block._origin = cset if basedir then block._basedir = basedir:lower() end table.insert(cset.blocks, block) cset.current = block return true end function configset.getFilter(cset) return { _criteria = cset.current._criteria, _basedir = cset.current._basedir } end function configset.setFilter(cset, filter) local block = {} block._criteria = filter._criteria block._basedir = filter._basedir block._origin = cset table.insert(cset.blocks, block) cset.current = block; end function configset.store(cset, field, value) if not cset.current then configset.addblock(cset, {}) end local key = field.name local current = cset.current local status, result = pcall(function () current[key] = p.field.store(field, current[key], value) end) if not status then if type(result) == "table" then result = result.msg end return nil, result end return true end function configset.remove(cset, field, values) local block = {} block._basedir = cset.current._basedir block._criteria = cset.current._criteria block._origin = cset table.insert(cset.blocks, block) cset.current = block values = p.field.remove(field, {}, values) current = cset.current current._removes = {} current._removes[field.name] = values end function configset.empty(cset) return (#cset.blocks == 0) end function configset.compile(cset, filter) local result if cset.parent then result = configset.compile(cset.parent, filter) else result = configset.new() end local blocks = cset.blocks local n = #blocks local abspath = filter.files local basedir for i = 1, n do local block = blocks[i] if block._origin == cset then block._origin = result end if abspath and block._basedir and block._basedir ~= basedir then basedir = block._basedir filter.files = path.getrelative(basedir, abspath) end if criteria.matches(block._criteria, filter) then table.insert(result.blocks, block) end end filter.files = abspath result.compiled = true return result end local p = premake local make = p.make local tree = p.tree local project = p.project function make.generate_workspace(wks) p.eol("\n") make.header(wks) make.configmap(wks) make.projects(wks) make.workspacePhonyRule(wks) make.groupRules(wks) make.projectrules(wks) make.cleanrules(wks) make.helprule(wks) end function make.configmap(wks) for cfg in p.workspace.eachconfig(wks) do _p('ifeq ($(config),%s)', cfg.shortname) for prj in p.workspace.eachproject(wks) do local prjcfg = project.getconfig(prj, cfg.buildcfg, cfg.platform) if prjcfg then _p(' %s_config = %s', make.tovar(prj.name), prjcfg.shortname) end end _p('endif') end _p('') end function make.cleanrules(wks) _p('clean:') for prj in p.workspace.eachproject(wks) do local prjpath = p.filename(prj, make.getmakefilename(prj, true)) local prjdir = path.getdirectory(path.getrelative(wks.location, prjpath)) local prjname = path.getname(prjpath) _x(1,'@${MAKE} --no-print-directory -C %s -f %s clean', prjdir, prjname) end _p('') end function make.helprule(wks) _p('help:') _p(1,'@echo "Usage: make [config=name] [target]"') _p(1,'@echo ""') _p(1,'@echo "CONFIGURATIONS:"') for cfg in p.workspace.eachconfig(wks) do _x(1, '@echo " %s"', cfg.shortname) end _p(1,'@echo ""') _p(1,'@echo "TARGETS:"') _p(1,'@echo " all (default)"') _p(1,'@echo " clean"') for prj in p.workspace.eachproject(wks) do _p(1,'@echo " %s"', prj.name) end _p(1,'@echo ""') _p(1,'@echo "For more information, see https://github.com/premake/premake-core/wiki"') end function make.projects(wks) _p('PROJECTS := %s', table.concat(p.esc(table.extract(wks.projects, "name")), " ")) _p('') end function make.workspacePhonyRule(wks) local groups = {} local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onbranch = function(n) table.insert(groups, n.path) end }) _p('.PHONY: all clean help $(PROJECTS) ' .. table.implode(groups, '', '', ' ')) _p('') _p('all: $(PROJECTS)') _p('') end function make.groupRules(wks) local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onbranch = function(n) local rule = n.path .. ":" local projectTargets = {} local groupTargets = {} for i, c in pairs(n.children) do if type(i) == "string" then if c.project then table.insert(projectTargets, c.name) else table.insert(groupTargets, c.path) end end end if #groupTargets > 0 then table.sort(groupTargets) rule = rule .. " " .. table.concat(groupTargets, " ") end if #projectTargets > 0 then table.sort(projectTargets) rule = rule .. " " .. table.concat(projectTargets, " ") end _p(rule) _p('') end }) end function make.projectrules(wks) for prj in p.workspace.eachproject(wks) do local deps = project.getdependencies(prj) deps = table.extract(deps, "name") _p('%s:%s', p.esc(prj.name), make.list(deps)) local cfgvar = make.tovar(prj.name) _p('ifneq (,$(%s_config))', cfgvar) _p(1,'@echo "==== Building %s ($(%s_config)) ===="', prj.name, cfgvar) local prjpath = p.filename(prj, make.getmakefilename(prj, true)) local prjdir = path.getdirectory(path.getrelative(wks.location, prjpath)) local prjname = path.getname(prjpath) _x(1,'@${MAKE} --no-print-directory -C %s -f %s config=$(%s_config)', prjdir, prjname, cfgvar) _p('endif') _p('') end end local p = premake p.languages = {} function p.languages.isc(value) return value == "C"; end function p.languages.iscpp(value) return value == "C++"; end function p.languages.iscsharp(value) return value == "C#"; end function p.languages.isfsharp(value) return value == "F#"; end local p = premake local vstudio = p.vstudio newaction { trigger = "vs2019", shortname = "Visual Studio 2019", description = "Generate Visual Studio 2019 project files", targetos = "windows", toolset = "msc-v142", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = function(wks) p.vstudio.vs2005.generateSolution(wks) end, onProject = function(prj) p.vstudio.vs2010.generateProject(prj) end, onRule = function(rule) p.vstudio.vs2010.generateRule(rule) end, onCleanWorkspace = function(wks) p.vstudio.cleanSolution(wks) end, onCleanProject = function(prj) p.vstudio.cleanProject(prj) end, onCleanTarget = function(prj) p.vstudio.cleanTarget(prj) end, pathVars = vstudio.vs2010.pathVars, vstudio = { solutionVersion = "12", versionName = "16", targetFramework = "4.7.2", toolsVersion = "15.0", userToolsVersion = "Current", filterToolsVersion = "4.0", } } premake.clean = {} newaction { trigger = "clean", description = "Remove all binaries and generated files", execute = function() print("** The clean action has not yet been ported") end } local p = premake local _captured local _esc = function(v) return v end local _eol = "\n" local _indentString = "\t" local _indentLevel = 0 global("root") function premake.capture(fn) local old = _captured _captured = buffered.new() fn() local captured = p.captured() buffered.close(_captured) _captured = old return captured end function premake.captured() if _captured then return buffered.tostring(_captured) else return "" end end function premake.eol(s) _eol = s or _eol return _eol end function premake.esc(value) if type(value) == "table" then local result = {} local n = #value for i = 1, n do table.insert(result, p.esc(value[i])) end return result end return _esc(value or "") end function premake.escaper(func) _esc = func if not _esc then _esc = function (value) return value end end end function premake.generate(obj, ext, callback) local output = p.capture(function () _indentLevel = 0 callback(obj) _indentLevel = 0 end) local fn = p.filename(obj, ext) local dir = path.getdirectory(fn) local ok, err = os.mkdir(dir) if not ok then error(err, 0) end local f, err = os.writefile_ifnotequal(output, fn); if (f == 0) then return false -- file not modified elseif (f < 0) then error(err, 0) elseif (f > 0) then printf("Generated %s...", path.getrelative(os.getcwd(), fn)) return true -- file modified end end function premake.touch(obj, ext) local fn = premake.filename(obj, ext) local dir = path.getdirectory(fn) local ok, err = os.mkdir(dir) if not ok then error(err, 0) end local f, err = os.touchfile(fn); if (f == 0) then return false -- file marked as modified elseif (f < 0) then error(err, 0) elseif (f > 0) then return true -- file created end end function premake.filename(obj, ext) local fname = obj.location or obj.basedir if ext and not ext:startswith(".") then fname = path.join(fname, ext) else fname = path.join(fname, obj.filename) if ext then fname = fname .. ext end end return path.getabsolute(fname) end function premake.indent(s, i) _indentString = s or "\t" _indentLevel = i or 0 end function premake.out(s) if not _captured then io.write(s) else buffered.write(_captured, s) end end function premake.outln(s) p.out(s) p.out(_eol or "\n") end function premake.pop(i, ...) if i == nil or type(i) == "number" then _indentLevel = _indentLevel - (i or 1) else _indentLevel = _indentLevel - 1 p.w(i, ...) end end function premake.push(i, ...) if i == nil or type(i) == "number" then _indentLevel = _indentLevel + (i or 1) else p.w(i, ...) _indentLevel = _indentLevel + 1 end end function premake.quoted(value) local q = value:find(" ", 1, true) if not q then q = value:find("$%(.-%)", 1) end if q then value = '"' .. value .. '"' end return value end function p.utf8() p.out('\239\187\191') end function premake.w(...) if select("#", ...) > 0 then p.outln(string.rep(_indentString or "\t", _indentLevel) .. string.format(...)) else p.outln(''); end end function premake.x(msg, ...) local arg = {...} for i = 1, #arg do arg[i] = p.esc(arg[i]) end p.w(msg, table.unpack(arg)) end function premake.xmlUtf8(upper) local encoding = iif(upper, "UTF-8", "utf-8") p.w('', encoding) end function _p(i, ...) if type(i) == "number" then _indentLevel = i p.w(...) else _indentLevel = 0 p.w(i, ...) end end function _x(i, ...) local arg = {...} for i = 2, #arg do arg[i] = p.esc(arg[i]) end _p(i, table.unpack(arg)) end local p = premake local android = p.modules.android local vsandroid = p.modules.vsandroid local vstudio = p.vstudio premake.override(vstudio, "solutionPlatform", function (oldfn, cfg) local platform = oldfn(cfg) if cfg.system == premake.ANDROID and _ACTION >= "vs2015" then if cfg.platform == "x86" then platform = "x86" end end return platform end) premake.override(vstudio, "archFromConfig", function (oldfn, cfg, win32) if cfg.system == premake.ANDROID and _ACTION >= "vs2015" then return oldfn(cfg) end return oldfn(cfg, win32) end) S S,S4S@S4SHSPS\SdSpSxSfunction premake.downloadModule(modname, versions) if http == nil then return false end local user = 'UNKNOWN' if os.ishost('windows') then user = os.getenv('USERNAME') or user else user = os.getenv('LOGNAME') or user end local server = package.server or 'http://packagesrv.com'; local url = 'api/v1/module/' .. http.escapeUrlParam(modname) if versions then url = url .. '/' .. http.escapeUrlParam(versions) end local content, result_str, response_code = http.get(server .. '/' .. url) if content then url = content else return false end local location = '.modules/' .. modname local destination = location .. '/temp.zip' os.mkdir(location) local result_str, response_code = http.download(url, destination, { headers = {'X-Premake-User: ' .. user}, progress = iif(_OPTIONS.verbose, http.reportProgress, nil) }) if result_str ~= 'OK' then premake.error('Download of %s failed (%d)\n%s', url, response_code, result_str) end verbosef(' UNZIP : %s', destination) zip.extract(destination, location) os.remove(destination) return true; end local p = premake p.validation = {} local m = p.validation m.elements = {} m.elements.global = function(glb) return { } end function p.global.validate(self) p.callArray(m.elements.global, self) p.container.validateChildren(self) end m.elements.workspace = function(wks) return { m.workspaceHasConfigs, m.uniqueProjectIds, } end function p.workspace.validate(self) p.callArray(m.elements.workspace, self) p.container.validateChildren(self) end m.elements.project = function(prj) return { m.projectHasLanguage, m.actionSupportsLanguage, m.actionSupportsKind, m.projectRulesExist, m.projectValuesInScope, } end function p.project.validate(self) p.callArray(m.elements.project, self) for cfg in p.project.eachconfig(self) do p.config.validate(cfg) end end m.elements.config = function(cfg) return { m.configHasKind, m.configSupportsKind, m.configValuesInScope, } end function p.config.validate(self) p.callArray(m.elements.config, self) end m.elements.rule = function(rule) return { } end function p.rule.validate(self) p.callArray(m.elements.rule, self) end function p.config.validateScopes(self, container, expected) for f in p.field.each() do local scope for i = 1, #f.scopes do if f.scopes[i] == "config" or p.container.classIsA(container.class, f.scopes[i]) then scope = f.scopes[i] break end end local okay = (not scope or scope == "config") okay = okay or scope == expected okay = okay or p.oven.bubbledFields[f.name] okay = okay or p.field.compare(f, self[scope][f.name], self[f.name]) if not okay then local key = "validate." .. f.name p.warnOnce(key, "'%s' on %s '%s' differs from %s '%s'; may be set out of scope", f.name, expected, self.name, scope, self[scope].name) end end end function m.actionSupportsKind(prj) if not p.action.supports(prj.kind) then p.warn("Unsupported kind '%s' used for project '%s'", prj.kind, prj.name) end end function m.actionSupportsLanguage(prj) if not p.action.supports(prj.language) then p.warn("Unsupported language '%s' used for project '%s'", prj.language, prj.name) end end function m.configHasKind(cfg) if not cfg.kind then p.error("Project '%s' needs a kind in configuration '%s'", cfg.project.name, cfg.name) end end function m.configSupportsKind(cfg) if not p.action.supports(cfg.kind) then p.warn("Unsupported kind '%s' used in configuration '%s'", cfg.kind, cfg.name) end if (cfg.kind == p.MAKEFILE or cfg.kind == p.NONE) and p.project.isdotnet(cfg.project) then p.error("Project '%s' uses '%s' kind in configuration '%s'; language must not be C#", cfg.project.name, cfg.kind, cfg.name) end end function m.configValuesInScope(cfg) p.config.validateScopes(cfg, cfg.project, "config") end function m.projectHasLanguage(prj) if not prj.language then p.error("project '%s' does not have a language", prj.name) end end function m.projectRulesExist(prj) for i = 1, #prj.rules do local rule = prj.rules[i] if not p.global.getRule(rule) then p.error("project '%s' uses missing rule '%s'", prj.name, rule) end end end function m.projectValuesInScope(prj) p.config.validateScopes(prj, prj, "project") end function m.uniqueProjectIds(wks) local uuids = {} for prj in p.workspace.eachproject(wks) do if uuids[prj.uuid] then p.error("projects '%s' and '%s' have the same UUID", uuids[prj.uuid], prj.name) end uuids[prj.uuid] = prj.name end end function m.workspaceHasConfigs(wks) if not wks.configurations or #wks.configurations == 0 then p.error("workspace '%s' does not contain any configurations", wks.name) end end function string.capitalized(self) return self:gsub("^%l", string.upper) end function string.contains(s, match) return string.find(s, match, 1, true) ~= nil end function string.explode(s, pattern, plain, maxTokens) if (pattern == '') then return false end local pos = 0 local arr = { } for st,sp in function() return s:find(pattern, pos, plain) end do table.insert(arr, s:sub(pos, st-1)) pos = sp + 1 if maxTokens ~= nil and maxTokens > 0 then maxTokens = maxTokens - 1 if maxTokens == 0 then break end end end table.insert(arr, s:sub(pos)) return arr end function string.findlast(s, pattern, plain) local curr = 0 repeat local next = s:find(pattern, curr + 1, plain) if (next) then curr = next end until (not next) if (curr > 0) then return curr end end function string.lines(s) local trailing, n = s:gsub('.-\n', '') if #trailing > 0 then n = n + 1 end return n end function string:plural() if self:endswith("y") then return self:sub(1, #self - 1) .. "ies" else return self .. "s" end end function string.escapepattern(s) return s:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0") end local p = premake local xcode = p.modules.xcode local tree = p.tree local workspace = p.workspace local project = p.project local config = p.config local fileconfig = p.fileconfig function xcode.getbuildcategory(node) local categories = { [".a"] = "Frameworks", [".c"] = "Sources", [".cc"] = "Sources", [".cpp"] = "Sources", [".cxx"] = "Sources", [".dylib"] = "Frameworks", [".framework"] = "Frameworks", [".m"] = "Sources", [".mm"] = "Sources", [".strings"] = "Resources", [".nib"] = "Resources", [".xib"] = "Resources", [".storyboard"] = "Resources", [".icns"] = "Resources", [".s"] = "Sources", [".S"] = "Sources", } if node.isResource then return "Resources" end return categories[path.getextension(node.name)] end function xcode.isItemResource(project, node) local res; if project and project.xcodebuildresources then if type(project.xcodebuildresources) == "table" then res = project.xcodebuildresources end end local function checkItemInList(item, list) if item then if list then if type(list) == "table" then for _,v in pairs(list) do if string.find(item, v) then return true end end end end end return false end if (checkItemInList(node.path, res)) then return true end return false end function xcode.getfiletypekey(node, cfg) if node.configs then local filecfg = fileconfig.getconfig(node, cfg) if filecfg and filecfg["compileas"] then return "explicitFileType" end end return "lastKnownFileType" end function xcode.getfiletype(node, cfg) if node.configs then local filecfg = fileconfig.getconfig(node, cfg) if filecfg then if p.languages.isc(filecfg.compileas) then return "sourcecode.c.c" elseif p.languages.iscpp(filecfg.compileas) then return "sourcecode.cpp.cpp" elseif filecfg.language == "ObjC" then return "sourcecode.c.objc" elseif filecfg.language == "ObjCpp" then return "sourcecode.cpp.objcpp" end end end local types = { [".c"] = "sourcecode.c.c", [".cc"] = "sourcecode.cpp.cpp", [".cpp"] = "sourcecode.cpp.cpp", [".css"] = "text.css", [".cxx"] = "sourcecode.cpp.cpp", [".S"] = "sourcecode.asm.asm", [".framework"] = "wrapper.framework", [".gif"] = "image.gif", [".h"] = "sourcecode.c.h", [".html"] = "text.html", [".lua"] = "sourcecode.lua", [".m"] = "sourcecode.c.objc", [".mm"] = "sourcecode.cpp.objc", [".nib"] = "wrapper.nib", [".storyboard"] = "file.storyboard", [".pch"] = "sourcecode.c.h", [".plist"] = "text.plist.xml", [".strings"] = "text.plist.strings", [".xib"] = "file.xib", [".icns"] = "image.icns", [".s"] = "sourcecode.asm", [".bmp"] = "image.bmp", [".wav"] = "audio.wav", [".xcassets"] = "folder.assetcatalog", } return types[path.getextension(node.path)] or "text" end local function xcodePrintUserConfigReferences(offset, cfg, tr, kind) local referenceName if kind == "project" then referenceName = cfg.xcodeconfigreferenceproject elseif kind == "target" then referenceName = cfg.xcodeconfigreferencetarget end tree.traverse(tr, { onleaf = function(node) filename = node.name if node.id and path.getextension(filename) == ".xcconfig" then if filename == referenceName then _p(offset, 'baseConfigurationReference = %s /* %s */;', node.id, filename) return end end end }, false) end local escapeSpecialChars = { ['\n'] = '\\n', ['\r'] = '\\r', ['\t'] = '\\t', } local function escapeChar(c) return escapeSpecialChars[c] or '\\'..c end local function escapeArg(value) value = value:gsub('[\'"\\\n\r\t ]', escapeChar) return value end local function escapeSetting(value) value = value:gsub('["\\\n\r\t]', escapeChar) return value end local function stringifySetting(value) value = value..'' if not value:match('^[%a%d_./]+$') then value = '"'..escapeSetting(value)..'"' end return value end local function customStringifySetting(value) value = value..'' local test = value:match('^[%a%d_./%+]+$') if test then value = '"'..escapeSetting(value)..'"' end return value end local function printSetting(level, name, value) if type(value) == 'function' then value(level, name) elseif type(value) ~= 'table' then _p(level, '%s = %s;', stringifySetting(name), stringifySetting(value)) elseif #value >= 1 then _p(level, '%s = (', stringifySetting(name)) for _, item in ipairs(value) do _p(level + 1, '%s,', stringifySetting(item)) end _p(level, ');') end end local function printSettingsTable(level, settings) local keys = table.keys(settings) table.sort(keys) for _, k in ipairs(keys) do printSetting(level, k, settings[k]) end end local function overrideSettings(settings, overrides) if type(overrides) == 'table' then for name, value in pairs(overrides) do settings[name] = iif(not table.equals(value, { false }), value, nil) end end end function xcode.getproducttype(node) local types = { ConsoleApp = "com.apple.product-type.tool", WindowedApp = "com.apple.product-type.application", StaticLib = "com.apple.product-type.library.static", SharedLib = "com.apple.product-type.library.dynamic", OSXBundle = "com.apple.product-type.bundle", OSXFramework = "com.apple.product-type.framework", XCTest = "com.apple.product-type.bundle.unit-test", } return types[iif(node.cfg.kind == "SharedLib" and node.cfg.sharedlibtype, node.cfg.sharedlibtype, node.cfg.kind)] end function xcode.gettargettype(node) local types = { ConsoleApp = "\"compiled.mach-o.executable\"", WindowedApp = "wrapper.application", StaticLib = "archive.ar", SharedLib = "\"compiled.mach-o.dylib\"", OSXBundle = "wrapper.cfbundle", OSXFramework = "wrapper.framework", XCTest = "wrapper.cfbundle", } return types[iif(node.cfg.kind == "SharedLib" and node.cfg.sharedlibtype, node.cfg.sharedlibtype, node.cfg.kind)] end function xcode.getdebugformat(cfg) local formats = { ["Dwarf"] = "dwarf", ["Default"] = "dwarf-with-dsym", ["SplitDwarf"] = "dwarf-with-dsym", } local rval = "dwarf-with-dsym" if cfg.debugformat then rval = formats[cfg.debugformat] or rval end return rval end function xcode.getxcodeprojname(prj) local fname = p.filename(prj, ".xcodeproj") return fname end function xcode.isframework(fname) return (path.getextension(fname) == ".framework") end function xcode.newid(...) local name = '' local arg = {...} for i, v in pairs(arg) do name = name..v..'****' end return ("%08X%08X%08X"):format(name:hash(16777619), name:hash(2166136261), name:hash(46577619)) end function xcode.prepareWorkspace(wks) wks.xcode = { } for prj in p.workspace.eachproject(wks) do local cfg = project.getconfig(prj, prj.configurations[1], prj.platforms[1]) local bundlepath = cfg.buildtarget.bundlename ~= "" and cfg.buildtarget.bundlename or cfg.buildtarget.name; if (prj.external) then bundlepath = cfg.project.name end local node = p.tree.new(path.getname(bundlepath)) node.cfg = cfg node.id = xcode.newid(node.name, "product") node.targetid = xcode.newid(node.name, "target") prj.xcode = {} prj.xcode.projectnode = node end end function xcode.PBXBuildFile(tr) local settings = {}; tree.traverse(tr, { onnode = function(node) if node.buildid then settings[node.buildid] = function(level) _p(level,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; };', node.buildid, node.name, xcode.getbuildcategory(node), node.id, node.name) end end end }) if not table.isempty(settings) then _p('/* Begin PBXBuildFile section */') printSettingsTable(2, settings); _p('/* End PBXBuildFile section */') _p('') end end function xcode.PBXContainerItemProxy(tr) local settings = {} for _, node in ipairs(tr.projects.children) do settings[node.productproxyid] = function() _p(2,'%s /* PBXContainerItemProxy */ = {', node.productproxyid) _p(3,'isa = PBXContainerItemProxy;') _p(3,'containerPortal = %s /* %s */;', node.id, path.getrelative(node.parent.parent.project.location, node.path)) _p(3,'proxyType = 2;') _p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.id) _p(3,'remoteInfo = %s;', stringifySetting(node.project.xcode.projectnode.name)) _p(2,'};') end settings[node.targetproxyid] = function() _p(2,'%s /* PBXContainerItemProxy */ = {', node.targetproxyid) _p(3,'isa = PBXContainerItemProxy;') _p(3,'containerPortal = %s /* %s */;', node.id, path.getrelative(node.parent.parent.project.location, node.path)) _p(3,'proxyType = 1;') _p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.targetid) _p(3,'remoteInfo = %s;', stringifySetting(node.project.xcode.projectnode.name)) _p(2,'};') end end if not table.isempty(settings) then _p('/* Begin PBXContainerItemProxy section */') printSettingsTable(2, settings); _p('/* End PBXContainerItemProxy section */') _p('') end end function xcode.PBXFileReference(tr) local cfg = project.getfirstconfig(tr.project) local settings = {} tree.traverse(tr, { onleaf = function(node) if not node.path then return end if node.kind == "product" then settings[node.id] = function(level) _p(level,'%s /* %s */ = {isa = PBXFileReference; explicitFileType = %s; includeInIndex = 0; name = %s; path = %s; sourceTree = BUILT_PRODUCTS_DIR; };', node.id, node.name, xcode.gettargettype(node), stringifySetting(node.name), stringifySetting(path.getname(node.cfg.buildtarget.bundlename ~= "" and node.cfg.buildtarget.bundlename or node.cfg.buildtarget.relpath))) end elseif node.parent.parent == tr.projects then settings[node.parent.id] = function(level) local relpath = path.getrelative(path.getabsolute(tr.project.location), path.getabsolute(node.parent.project.location)) _p(level,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = %s; path = %s; sourceTree = SOURCE_ROOT; };', node.parent.id, node.name, customStringifySetting(node.parent.name), stringifySetting(path.join(relpath, node.parent.name))) end else settings[node.id] = function(level) local pth, src if xcode.isframework(node.path) then local nodePath = node.path local _, matchEnd, variable = string.find(nodePath, "^%$%((.+)%)/") if variable then nodePath = string.sub(nodePath, matchEnd + 1) end if string.find(nodePath,'/') then if string.find(nodePath,'^%.')then pth = path.getrelative(tr.project.location, node.path) src = "SOURCE_ROOT" variable = src else pth = nodePath src = "" end end if variable then src = variable if string.find(pth, '^/') then pth = string.sub(pth, 2) end else pth = "System/Library/Frameworks/" .. node.path src = "SDKROOT" end else src = "" if node.abspath then pth = path.getrelative(tr.project.location, node.abspath) else pth = node.path end end _p(level,'%s /* %s */ = {isa = PBXFileReference; %s = %s; name = %s; path = %s; sourceTree = %s; };', node.id, node.name, xcode.getfiletypekey(node, cfg), xcode.getfiletype(node, cfg), stringifySetting(node.name), stringifySetting(pth), stringifySetting(src)) end end end }) if not table.isempty(settings) then _p('/* Begin PBXFileReference section */') printSettingsTable(2, settings) _p('/* End PBXFileReference section */') _p('') end end function xcode.PBXFrameworksBuildPhase(tr) _p('/* Begin PBXFrameworksBuildPhase section */') _p(2,'%s /* Frameworks */ = {', tr.products.children[1].fxstageid) _p(3,'isa = PBXFrameworksBuildPhase;') _p(3,'buildActionMask = 2147483647;') _p(3,'files = (') tree.traverse(tr.frameworks, { onleaf = function(node) if node.buildid then _p(4,'%s /* %s in Frameworks */,', node.buildid, node.name) end end }) tree.traverse(tr.projects, { onleaf = function(node) if node.buildid then _p(4,'%s /* %s in Frameworks */,', node.buildid, node.name) end end }) _p(3,');') _p(3,'runOnlyForDeploymentPostprocessing = 0;') _p(2,'};') _p('/* End PBXFrameworksBuildPhase section */') _p('') end function xcode.PBXGroup(tr) local settings = {} tree.traverse(tr, { onnode = function(node) if (node.path and #node.children == 0) or node.kind == "vgroup" then return end local function isAggregateTarget(node) local productsId = xcode.newid("Products") return node.id == productsId and node.parent.project and node.parent.project.kind == "Utility" end if isAggregateTarget(node) then return end settings[node.productgroupid or node.id] = function() if node.parent == tr.projects then _p(2,'%s /* Products */ = {', node.productgroupid) else _p(2,'%s /* %s */ = {', node.id, node.name) end _p(3,'isa = PBXGroup;') _p(3,'children = (') for _, childnode in ipairs(node.children) do if not isAggregateTarget(childnode) then _p(4,'%s /* %s */,', childnode.id, childnode.name) end end _p(3,');') if node.parent == tr.projects then _p(3,'name = Products;') else _p(3,'name = %s;', stringifySetting(node.name)) local vpath = project.getvpath(tr.project, node.name) if node.path and node.name ~= vpath then local p = node.path if node.parent.path then p = path.getrelative(node.parent.path, node.path) end _p(3,'path = %s;', stringifySetting(p)) end end _p(3,'sourceTree = "";') _p(2,'};') end end }, true) if not table.isempty(settings) then _p('/* Begin PBXGroup section */') printSettingsTable(2, settings) _p('/* End PBXGroup section */') _p('') end end local function xcode_GetBuildCommands(tr) local buildCommandInfos = {} tree.traverse(tr, { onnode = function(node) if node.buildcommandid then local info = { node = node, inputs = { node.relpath }, outputs = {}, depends = {}, transact = false, } for cfg in project.eachconfig(tr.project) do local filecfg = fileconfig.getconfig(node, cfg) if filecfg then for _, v in ipairs(filecfg.buildinputs) do table.insert(info.inputs, project.getrelative(tr.project, v)) end for _, v in ipairs(filecfg.buildoutputs) do table.insert(info.outputs, project.getrelative(tr.project, v)) end end end table.insert(buildCommandInfos, info) end end }) for _, mine in ipairs(buildCommandInfos) do for _, their in ipairs(buildCommandInfos) do if mine ~= their then for _, input in ipairs(mine.inputs) do if table.contains(their.outputs, input) then table.insert(mine.depends, their) break end end end end end local buildCommands = {} local leftover = #buildCommandInfos while leftover > 0 do local prev = leftover for _, info in ipairs(buildCommandInfos) do if not info.transact then local transact = true for _, depend in ipairs(info.depends) do transact = depend.transact if not transact then break end end if transact then table.insert(buildCommands, info.node) info.transact = true leftover = leftover - 1 end end end if prev == leftover then error('detect circular reference.') end end return buildCommands end local function xcode_PBXAggregateOrNativeTarget(tr, pbxTargetName) local kinds = { Aggregate = { "Utility", }, Native = { "ConsoleApp", "WindowedApp", "SharedLib", "StaticLib", }, } local hasTarget = false for _, node in ipairs(tr.products.children) do hasTarget = table.contains(kinds[pbxTargetName], node.cfg.kind) if hasTarget then break end end if not hasTarget then return end _p('/* Begin PBX%sTarget section */', pbxTargetName) local buildCommands = xcode_GetBuildCommands(tr) for _, node in ipairs(tr.products.children) do local name = tr.project.name local function hasBuildCommands(which) if #tr.project[which] > 0 then return true end for _, cfg in ipairs(tr.configs) do if #cfg[which] > 0 then return true end end end _p(2,'%s /* %s */ = {', node.targetid, name) _p(3,'isa = PBX%sTarget;', pbxTargetName) _p(3,'buildConfigurationList = %s /* Build configuration list for PBX%sTarget "%s" */;', node.cfgsection, pbxTargetName, escapeSetting(name)) _p(3,'buildPhases = (') if hasBuildCommands('prebuildcommands') then _p(4,'9607AE1010C857E500CD1376 /* Prebuild */,') end for _, v in ipairs(buildCommands) do _p(4,'%s /* Build "%s" */,', v.buildcommandid, v.name) end if pbxTargetName == "Native" then _p(4,'%s /* Resources */,', node.resstageid) _p(4,'%s /* Sources */,', node.sourcesid) end if hasBuildCommands('prelinkcommands') then _p(4,'9607AE3510C85E7E00CD1376 /* Prelink */,') end if pbxTargetName == "Native" then _p(4,'%s /* Frameworks */,', node.fxstageid) end if hasBuildCommands('postbuildcommands') then _p(4,'9607AE3710C85E8F00CD1376 /* Postbuild */,') end _p(3,');') _p(3,'buildRules = (') _p(3,');') _p(3,'dependencies = (') for _, node in ipairs(tr.projects.children) do _p(4,'%s /* PBXTargetDependency */,', node.targetdependid) end _p(3,');') _p(3,'name = %s;', stringifySetting(name)) if pbxTargetName == "Native" then local p if node.cfg.kind == "ConsoleApp" then p = "$(HOME)/bin" elseif node.cfg.kind == "WindowedApp" then p = "$(HOME)/Applications" end if p then _p(3,'productInstallPath = %s;', stringifySetting(p)) end end _p(3,'productName = %s;', stringifySetting(name)) if pbxTargetName == "Native" then _p(3,'productReference = %s /* %s */;', node.id, node.name) _p(3,'productType = %s;', stringifySetting(xcode.getproducttype(node))) end _p(2,'};') end _p('/* End PBX%sTarget section */', pbxTargetName) _p('') end function xcode.PBXAggregateTarget(tr) xcode_PBXAggregateOrNativeTarget(tr, "Aggregate") end function xcode.PBXNativeTarget(tr) xcode_PBXAggregateOrNativeTarget(tr, "Native") end function xcode.PBXProject(tr) _p('/* Begin PBXProject section */') _p(2,'08FB7793FE84155DC02AAC07 /* Project object */ = {') _p(3,'isa = PBXProject;') local capabilities = tr.project.xcodesystemcapabilities if not table.isempty(capabilities) then local keys = table.keys(capabilities) table.sort(keys) _p(3, 'attributes = {') _p(4, 'TargetAttributes = {') _p(5, '%s = {', tr.project.xcode.projectnode.targetid) _p(6, 'SystemCapabilities = {') for _, key in pairs(keys) do _p(7, '%s = {', key) _p(8, 'enabled = %d;', iif(capabilities[key], 1, 0)) _p(7, '};') end _p(6, '};') _p(5, '};') _p(4, '};') _p(3, '};') end _p(3,'buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */;', tr.name) _p(3,'compatibilityVersion = "Xcode 3.2";') _p(3,'hasScannedForEncodings = 1;') _p(3,'mainGroup = %s /* %s */;', tr.id, tr.name) _p(3,'projectDirPath = "";') if #tr.projects.children > 0 then _p(3,'projectReferences = (') for _, node in ipairs(tr.projects.children) do _p(4,'{') _p(5,'ProductGroup = %s /* Products */;', node.productgroupid) _p(5,'ProjectRef = %s /* %s */;', node.id, path.getname(node.path)) _p(4,'},') end _p(3,');') end _p(3,'projectRoot = "";') _p(3,'targets = (') for _, node in ipairs(tr.products.children) do _p(4,'%s /* %s */,', node.targetid, node.name) end _p(3,');') _p(2,'};') _p('/* End PBXProject section */') _p('') end function xcode.PBXReferenceProxy(tr) local settings = {} tree.traverse(tr.projects, { onleaf = function(node) settings[node.id] = function() _p(2,'%s /* %s */ = {', node.id, node.name) _p(3,'isa = PBXReferenceProxy;') _p(3,'fileType = %s;', xcode.gettargettype(node)) _p(3,'path = %s;', stringifySetting(node.name)) _p(3,'remoteRef = %s /* PBXContainerItemProxy */;', node.parent.productproxyid) _p(3,'sourceTree = BUILT_PRODUCTS_DIR;') _p(2,'};') end end }) if not table.isempty(settings) then _p('/* Begin PBXReferenceProxy section */') printSettingsTable(2, settings) _p('/* End PBXReferenceProxy section */') _p('') end end function xcode.PBXResourcesBuildPhase(tr) _p('/* Begin PBXResourcesBuildPhase section */') for _, target in ipairs(tr.products.children) do _p(2,'%s /* Resources */ = {', target.resstageid) _p(3,'isa = PBXResourcesBuildPhase;') _p(3,'buildActionMask = 2147483647;') _p(3,'files = (') tree.traverse(tr, { onnode = function(node) if xcode.getbuildcategory(node) == "Resources" then _p(4,'%s /* %s in Resources */,', node.buildid, node.name) end end }) _p(3,');') _p(3,'runOnlyForDeploymentPostprocessing = 0;') _p(2,'};') end _p('/* End PBXResourcesBuildPhase section */') _p('') end function xcode.PBXShellScriptBuildPhase(tr) local wrapperWritten = false local function doblock(id, name, which) local prjcmds = tr.project[which] local commands = table.join(prjcmds, {}) for _, cfg in ipairs(tr.configs) do local cfgcmds = cfg[which] if #cfgcmds > #prjcmds then table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. cfg.buildcfg .. '" ]; then') for i = #prjcmds + 1, #cfgcmds do table.insert(commands, cfgcmds[i]) end table.insert(commands, 'fi') end end if #commands > 0 then table.insert(commands, 1, 'set -e') -- Tells the shell to exit when any command fails commands = os.translateCommands(commands, p.MACOSX) if not wrapperWritten then _p('/* Begin PBXShellScriptBuildPhase section */') wrapperWritten = true end _p(2,'%s /* %s */ = {', id, name) _p(3,'isa = PBXShellScriptBuildPhase;') _p(3,'buildActionMask = 2147483647;') _p(3,'files = (') _p(3,');') _p(3,'inputPaths = ('); _p(3,');'); _p(3,'name = %s;', name); _p(3,'outputPaths = ('); _p(3,');'); _p(3,'runOnlyForDeploymentPostprocessing = 0;'); _p(3,'shellPath = /bin/sh;'); _p(3,'shellScript = %s;', stringifySetting(table.concat(commands, '\n'))) _p(2,'};') end end doblock("9607AE1010C857E500CD1376", "Prebuild", "prebuildcommands") local settings = {} tree.traverse(tr, { onnode = function(node) if node.buildcommandid then settings[node.buildcommandid] = function(level) local commands = {} local inputs = {} local outputs = {} for cfg in project.eachconfig(tr.project) do local filecfg = fileconfig.getconfig(node, cfg) if filecfg then table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. cfg.buildcfg .. '" ]; then') if filecfg.buildmessage then table.insert(commands, '\techo "' .. filecfg.buildmessage .. '"') end local cmds = os.translateCommandsAndPaths(filecfg.buildcommands, filecfg.project.basedir, filecfg.project.location) for _, cmd in ipairs(cmds) do table.insert(commands, '\t' .. cmd) end table.insert(commands, 'fi') for _, v in ipairs(filecfg.buildinputs) do inputs[v] = true end for _, v in ipairs(filecfg.buildoutputs) do outputs[v] = true end end end if #commands > 0 then table.insert(commands, 1, 'set -e') -- Tells the shell to exit when any command fails end _p(level,'%s /* Build "%s" */ = {', node.buildcommandid, node.name) _p(level+1,'isa = PBXShellScriptBuildPhase;') _p(level+1,'buildActionMask = 2147483647;') _p(level+1,'files = (') _p(level+1,');') _p(level+1,'inputPaths = ('); _p(level+2,'"%s",', escapeSetting(node.relpath)) for v, _ in pairs(inputs) do _p(level+2,'"%s",', escapeSetting(project.getrelative(tr.project, v))) end _p(level+1,');') _p(level+1,'name = %s;', stringifySetting('Build "' .. node.name .. '"')) _p(level+1,'outputPaths = (') for v, _ in pairs(outputs) do _p(level+2,'"%s",', escapeSetting(project.getrelative (tr.project, v))) end _p(level+1,');') _p(level+1,'runOnlyForDeploymentPostprocessing = 0;'); _p(level+1,'shellPath = /bin/sh;'); _p(level+1,'shellScript = %s;', stringifySetting(table.concat(commands, '\n'))) _p(level,'};') end end end }) if not table.isempty(settings) then if not wrapperWritten then _p('/* Begin PBXShellScriptBuildPhase section */') wrapperWritten = true end printSettingsTable(2, settings) end doblock("9607AE3510C85E7E00CD1376", "Prelink", "prelinkcommands") doblock("9607AE3710C85E8F00CD1376", "Postbuild", "postbuildcommands") if wrapperWritten then _p('/* End PBXShellScriptBuildPhase section */') _p('') end end function xcode.PBXSourcesBuildPhase(tr) _p('/* Begin PBXSourcesBuildPhase section */') for _, target in ipairs(tr.products.children) do _p(2,'%s /* Sources */ = {', target.sourcesid) _p(3,'isa = PBXSourcesBuildPhase;') _p(3,'buildActionMask = 2147483647;') _p(3,'files = (') tree.traverse(tr, { onleaf = function(node) if xcode.getbuildcategory(node) == "Sources" and node.buildid then _p(4,'%s /* %s in Sources */,', node.buildid, node.name) end end }) _p(3,');') _p(3,'runOnlyForDeploymentPostprocessing = 0;') _p(2,'};') end _p('/* End PBXSourcesBuildPhase section */') _p('') end function xcode.PBXVariantGroup(tr) local settings = {} tree.traverse(tr, { onbranch = function(node) settings[node.id] = function() if node.kind == "vgroup" then _p(2,'%s /* %s */ = {', node.id, node.name) _p(3,'isa = PBXVariantGroup;') _p(3,'children = (') for _, lang in ipairs(node.children) do _p(4,'%s /* %s */,', lang.id, lang.name) end _p(3,');') _p(3,'name = %s;', node.name) _p(3,'sourceTree = "";') _p(2,'};') end end end }) if not table.isempty(settings) then _p('/* Begin PBXVariantGroup section */') printSettingsTable(2, settings) _p('/* End PBXVariantGroup section */') _p('') end end function xcode.PBXTargetDependency(tr) local settings = {} tree.traverse(tr.projects, { onleaf = function(node) settings[node.parent.targetdependid] = function() _p(2,'%s /* PBXTargetDependency */ = {', node.parent.targetdependid) _p(3,'isa = PBXTargetDependency;') _p(3,'name = %s;', stringifySetting(node.name)) _p(3,'targetProxy = %s /* PBXContainerItemProxy */;', node.parent.targetproxyid) _p(2,'};') end end }) if not table.isempty(settings) then _p('/* Begin PBXTargetDependency section */') printSettingsTable(2, settings) _p('/* End PBXTargetDependency section */') _p('') end end function xcode.XCBuildConfiguration_Target(tr, target, cfg) local settings = {} settings['ALWAYS_SEARCH_USER_PATHS'] = 'NO' if cfg.symbols ~= p.OFF then settings['DEBUG_INFORMATION_FORMAT'] = xcode.getdebugformat(cfg) end if cfg.kind ~= "StaticLib" and cfg.buildtarget.prefix ~= '' then settings['EXECUTABLE_PREFIX'] = cfg.buildtarget.prefix end if cfg.buildtarget.extension then local exts = { WindowedApp = "app", SharedLib = "dylib", StaticLib = "a", OSXBundle = "bundle", OSXFramework = "framework", XCTest = "xctest", } local ext = cfg.buildtarget.extension:sub(2) if ext ~= exts[iif(cfg.kind == "SharedLib" and cfg.sharedlibtype, cfg.sharedlibtype, cfg.kind)] then if cfg.kind == "WindowedApp" or (cfg.kind == "SharedLib" and cfg.sharedlibtype) then settings['WRAPPER_EXTENSION'] = ext elseif cfg.kind == "SharedLib" or cfg.kind == "StaticLib" then settings['EXECUTABLE_EXTENSION'] = ext end end end local outdir = path.getrelative(tr.project.location, path.getdirectory(cfg.buildtarget.relpath)) if outdir ~= "." then settings['CONFIGURATION_BUILD_DIR'] = outdir end settings['GCC_DYNAMIC_NO_PIC'] = 'NO' if tr.infoplist then settings['INFOPLIST_FILE'] = config.findfile(cfg, path.getextension(tr.infoplist.name)) end local installpaths = { ConsoleApp = '/usr/local/bin', WindowedApp = '"$(HOME)/Applications"', SharedLib = '/usr/local/lib', StaticLib = '/usr/local/lib', OSXBundle = '$(LOCAL_LIBRARY_DIR)/Bundles', OSXFramework = '$(LOCAL_LIBRARY_DIR)/Frameworks', } settings['INSTALL_PATH'] = installpaths[iif(cfg.kind == "SharedLib" and cfg.sharedlibtype, cfg.sharedlibtype, cfg.kind)] local fileNameList = {} local file_tree = project.getsourcetree(tr.project) tree.traverse(tr, { onnode = function(node) if node.buildid and not node.isResource and node.abspath then local filecfg = fileconfig.getconfig(node, cfg) if filecfg and filecfg.flags.ExcludeFromBuild then table.insert(fileNameList, escapeArg(node.name)) end end end }) if not table.isempty(fileNameList) then settings['EXCLUDED_SOURCE_FILE_NAMES'] = fileNameList end settings['PRODUCT_NAME'] = iif(cfg.kind == "ConsoleApp" and cfg.buildtarget.extension, cfg.buildtarget.basename .. cfg.buildtarget.extension, cfg.buildtarget.basename) if os.istarget(p.IOS) then settings['SDKROOT'] = 'iphoneos' settings['CODE_SIGN_IDENTITY[sdk=iphoneos*]'] = cfg.xcodecodesigningidentity or 'iPhone Developer' local minOSVersion = project.systemversion(cfg) if minOSVersion ~= nil then settings['IPHONEOS_DEPLOYMENT_TARGET'] = minOSVersion end local families = { ['iPhone/iPod touch'] = '1', ['iPad'] = '2', ['Universal'] = '1,2', } local family = families[cfg.iosfamily] if family then settings['TARGETED_DEVICE_FAMILY'] = family end end overrideSettings(settings, cfg.xcodebuildsettings) _p(2,'%s /* %s */ = {', cfg.xcode.targetid, cfg.buildcfg) _p(3,'isa = XCBuildConfiguration;') _p(3,'buildSettings = {') printSettingsTable(4, settings) _p(3,'};') printSetting(3, 'name', cfg.buildcfg); _p(2,'};') end xcode.cLanguageStandards = { ["Default"] = "compiler-default", -- explicit compiler default ["C89"] = "c89", ["C90"] = "c90", ["C99"] = "c99", ["C11"] = "c11", ["gnu89"] = "gnu89", ["gnu90"] = "gnu90", ["gnu99"] = "gnu99", ["gnu11"] = "gnu11" } function xcode.XCBuildConfiguration_CLanguageStandard(settings, cfg) if not cfg.cdialect then return end local cLanguageStandard = xcode.cLanguageStandards[cfg.cdialect] if cLanguageStandard then settings['GCC_C_LANGUAGE_STANDARD'] = cLanguageStandard end end xcode.cppLanguageStandards = { ["Default"] = "compiler-default", -- explicit compiler default ["C++98"] = "c++98", ["C++11"] = "c++11", ["C++14"] = "c++14", ["C++17"] = "c++1z", ["gnu++98"] = "gnu++98", ["gnu++11"] = "gnu++0x", -- Xcode project GUI uses gnu++0x, but gnu++11 also works ["gnu++14"] = "gnu++14", ["gnu++17"] = "gnu++1z" } function xcode.XCBuildConfiguration_CppLanguageStandard(settings, cfg) if not cfg.cppdialect then return end local cppLanguageStandard = xcode.cppLanguageStandards[cfg.cppdialect] if cppLanguageStandard then settings['CLANG_CXX_LANGUAGE_STANDARD'] = cppLanguageStandard end end function xcode.XCBuildConfiguration_Project(tr, cfg) local settings = {} local archs = { Native = "$(NATIVE_ARCH_ACTUAL)", x86 = "i386", x86_64 = "x86_64", Universal32 = "$(ARCHS_STANDARD_32_BIT)", Universal64 = "$(ARCHS_STANDARD_64_BIT)", Universal = "$(ARCHS_STANDARD_32_64_BIT)", } settings['ARCHS'] = archs[cfg.platform or "Native"] local targetdir = path.getdirectory(cfg.buildtarget.relpath) if targetdir ~= "." then settings['CONFIGURATION_BUILD_DIR'] = '$(SYMROOT)' end settings['CONFIGURATION_TEMP_DIR'] = '$(OBJROOT)' if config.isDebugBuild(cfg) then settings['COPY_PHASE_STRIP'] = 'NO' end xcode.XCBuildConfiguration_CLanguageStandard(settings, cfg) xcode.XCBuildConfiguration_CppLanguageStandard(settings, cfg) if cfg.exceptionhandling == p.OFF then settings['GCC_ENABLE_CPP_EXCEPTIONS'] = 'NO' end if cfg.rtti == p.OFF then settings['GCC_ENABLE_CPP_RTTI'] = 'NO' end if cfg.symbols == p.ON and cfg.editandcontinue ~= "Off" then settings['GCC_ENABLE_FIX_AND_CONTINUE'] = 'YES' end if cfg.exceptionhandling == p.OFF then settings['GCC_ENABLE_OBJC_EXCEPTIONS'] = 'NO' end local optimizeMap = { On = 3, Size = 's', Speed = 3, Full = 'fast', Debug = 1 } settings['GCC_OPTIMIZATION_LEVEL'] = optimizeMap[cfg.optimize] or 0 if cfg.pchheader and not cfg.flags.NoPCH then settings['GCC_PRECOMPILE_PREFIX_HEADER'] = 'YES' settings['GCC_PREFIX_HEADER'] = cfg.pchheader end local escapedDefines = { } for i,v in ipairs(cfg.defines) do escapedDefines[i] = escapeArg(v) end settings['GCC_PREPROCESSOR_DEFINITIONS'] = escapedDefines settings["GCC_SYMBOLS_PRIVATE_EXTERN"] = 'NO' if cfg.unsignedchar ~= nil then settings['GCC_CHAR_IS_UNSIGNED_CHAR'] = iif(cfg.unsignedchar, "YES", "NO") end if cfg.flags.FatalWarnings then settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES' end settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'YES' settings['GCC_WARN_UNUSED_VARIABLE'] = 'YES' local includedirs = project.getrelative(cfg.project, cfg.includedirs) for i,v in ipairs(includedirs) do cfg.includedirs[i] = p.quoted(v) end settings['USER_HEADER_SEARCH_PATHS'] = cfg.includedirs local sysincludedirs = project.getrelative(cfg.project, cfg.sysincludedirs) for i,v in ipairs(sysincludedirs) do cfg.sysincludedirs[i] = p.quoted(v) end if not table.isempty(cfg.sysincludedirs) then table.insert(cfg.sysincludedirs, "$(inherited)") end settings['HEADER_SEARCH_PATHS'] = cfg.sysincludedirs for i,v in ipairs(cfg.libdirs) do cfg.libdirs[i] = p.project.getrelative(cfg.project, cfg.libdirs[i]) end settings['LIBRARY_SEARCH_PATHS'] = cfg.libdirs for i,v in ipairs(cfg.frameworkdirs) do cfg.frameworkdirs[i] = p.project.getrelative(cfg.project, cfg.frameworkdirs[i]) end settings['FRAMEWORK_SEARCH_PATHS'] = cfg.frameworkdirs local objDir = path.getrelative(tr.project.location, cfg.objdir) settings['OBJROOT'] = objDir settings['ONLY_ACTIVE_ARCH'] = iif(p.config.isDebugBuild(cfg), 'YES', 'NO') local checks = { ["-ffast-math"] = cfg.floatingpoint == "Fast", ["-fomit-frame-pointer"] = cfg.omitframepointer == "On", ["-fno-omit-frame-pointer"] = cfg.omitframepointer == "Off", } local flags = { } for flag, check in pairs(checks) do if check then table.insert(flags, flag) end end settings['OTHER_CFLAGS'] = table.join(flags, cfg.buildoptions) flags = { } for _, lib in ipairs(config.getlinks(cfg, "system")) do if not xcode.isframework(lib) then table.insert(flags, "-l" .. lib) end end for _, lib in ipairs(config.getlinks(cfg, "dependencies", "object")) do if (lib.external) then if not xcode.isframework(lib.linktarget.basename) then table.insert(flags, "-l" .. escapeArg(lib.linktarget.basename)) end end end settings['OTHER_LDFLAGS'] = table.join(flags, cfg.linkoptions) if cfg.flags.StaticRuntime then settings['STANDARD_C_PLUS_PLUS_LIBRARY_TYPE'] = 'static' end if targetdir ~= "." then settings['SYMROOT'] = path.getrelative(tr.project.location, targetdir) end if cfg.warnings == "Extra" then settings['WARNING_CFLAGS'] = '-Wall -Wextra' end overrideSettings(settings, cfg.xcodebuildsettings) _p(2,'%s /* %s */ = {', cfg.xcode.projectid, cfg.buildcfg) _p(3,'isa = XCBuildConfiguration;') _p(3,'buildSettings = {') printSettingsTable(4, settings) _p(3,'};') printSetting(3, 'name', cfg.buildcfg); _p(2,'};') end function xcode.XCBuildConfiguration(tr) local settings = {} for _, target in ipairs(tr.products.children) do for _, cfg in ipairs(tr.configs) do settings[cfg.xcode.targetid] = function() xcode.XCBuildConfiguration_Target(tr, target, cfg) end end end for _, cfg in ipairs(tr.configs) do settings[cfg.xcode.projectid] = function() xcode.XCBuildConfiguration_Project(tr, cfg) end end if not table.isempty(settings) then _p('/* Begin XCBuildConfiguration section */') printSettingsTable(0, settings) _p('/* End XCBuildConfiguration section */') _p('') end end function xcode.XCBuildConfigurationList(tr) local wks = tr.project.workspace local defaultCfgName = stringifySetting(tr.configs[1].buildcfg) local settings = {} for _, target in ipairs(tr.products.children) do settings[target.cfgsection] = function() _p(2,'%s /* Build configuration list for PBXNativeTarget "%s" */ = {', target.cfgsection, target.name) _p(3,'isa = XCConfigurationList;') _p(3,'buildConfigurations = (') for _, cfg in ipairs(tr.configs) do _p(4,'%s /* %s */,', cfg.xcode.targetid, cfg.buildcfg) end _p(3,');') _p(3,'defaultConfigurationIsVisible = 0;') _p(3,'defaultConfigurationName = %s;', defaultCfgName) _p(2,'};') end end settings['1DEB928908733DD80010E9CD'] = function() _p(2,'1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */ = {', tr.name) _p(3,'isa = XCConfigurationList;') _p(3,'buildConfigurations = (') for _, cfg in ipairs(tr.configs) do _p(4,'%s /* %s */,', cfg.xcode.projectid, cfg.buildcfg) end _p(3,');') _p(3,'defaultConfigurationIsVisible = 0;') _p(3,'defaultConfigurationName = %s;', defaultCfgName) _p(2,'};') end _p('/* Begin XCConfigurationList section */') printSettingsTable(2, settings) _p('/* End XCConfigurationList section */') end local tdmd = {} local p = premake local project = p.project local config = p.config local d = p.modules.d tdmd.gcc = {} tdmd.gcc.dc = "dmd" tdmd.optlink = {} tdmd.optlink.dc = "dmd" tdmd.gcc.ldflags = { architecture = { x86 = { "-m32" }, x86_64 = { "-m64" }, }, kind = { SharedLib = "-shared", StaticLib = "-lib", } } function tdmd.gcc.getldflags(cfg) local flags = config.mapFlags(cfg, tdmd.gcc.ldflags) return flags end tdmd.gcc.libraryDirectories = { architecture = { x86 = "-L-L/usr/lib", x86_64 = "-L-L/usr/lib64", } } function tdmd.gcc.getLibraryDirectories(cfg) local flags = config.mapFlags(cfg, tdmd.gcc.libraryDirectories) for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do table.insert(flags, '-L-L' .. project.getrelative(cfg.project, dir)) end return flags end function tdmd.gcc.getlinks(cfg, systemonly) local result = {} local links if not systemonly then links = config.getlinks(cfg, "siblings", "object") for _, link in ipairs(links) do if not link.project.external then if link.kind == p.STATICLIB then table.insert(result, "-L" .. project.getrelative(cfg.project, link.linktarget.abspath)) else table.insert(result, "-L-l" .. link.linktarget.basename) end end end end links = config.getlinks(cfg, "system", "fullpath") for _, link in ipairs(links) do if path.isframework(link) then table.insert(result, "-framework " .. path.getbasename(link)) elseif path.isobjectfile(link) then table.insert(result, "-L" .. link) else table.insert(result, "-L-l" .. path.getbasename(link)) end end return result end tdmd.optlink.ldflags = { architecture = { x86 = { "-m32" }, x86_64 = { "-m64" }, }, kind = { SharedLib = "-shared", StaticLib = "-lib", } } function tdmd.optlink.getldflags(cfg) local flags = config.mapFlags(cfg, tdmd.optlink.ldflags) return flags end function tdmd.optlink.getLibraryDirectories(cfg) local flags = {} for _, dir in ipairs(config.getlinks(cfg, "system", "directory")) do table.insert(flags, '-Llib "' .. project.getrelative(cfg.project, dir) .. '"') end return flags end function tdmd.optlink.getlinks(cfg) local result = {} local links = config.getlinks(cfg, "dependencies", "object") for _, link in ipairs(links) do if not link.project.externalname then local linkinfo = config.getlinkinfo(link) if link.kind == p.STATICLIB then table.insert(result, project.getrelative(cfg.project, linkinfo.abspath)) end end end links = config.getlinks(cfg, "system", "basename") for _, link in ipairs(links) do if path.isobjectfile(link) then table.insert(result, link) elseif path.hasextension(link, p.systems[cfg.system].staticlib.extension) then table.insert(result, link) end end return result end if string.match( os.getversion().description, "Windows" ) ~= nil then p.tools.dmd = tdmd.optlink else p.tools.dmd = tdmd.gcc end local dmd = p.tools.dmd dmd.dflags = { architecture = { x86 = "-m32mscoff", x86_64 = "-m64", }, flags = { OmitDefaultLibrary= "-mscrtlib=", CodeCoverage= "-cov", Documentation= "-D", FatalWarnings= "-w", GenerateHeader= "-H", GenerateJSON= "-X", GenerateMap= "-map", Profile= "-profile", Quiet= "-quiet", RetainPaths= "-op", SymbolsLikeC= "-gc", UnitTest= "-unittest", Verbose= "-v", ProfileGC= "-profile=gc", StackFrame= "-gs", StackStomp= "-gx", AllTemplateInst= "-allinst", BetterC= "-betterC", Main= "-main", PerformSyntaxCheckOnly= "-o-", ShowTLS= "-vtls", ShowGC= "-vgc", IgnorePragma= "-ignore", ShowDependencies= "-deps", }, boundscheck = { Off = "-boundscheck=off", On = "-boundscheck=on", SafeOnly = "-boundscheck=safeonly", }, deprecatedfeatures = { Allow = "-d", Warn = "-dw", Error = "-de", }, floatingpoint = { None = "-nofloat", }, optimize = { On = "-O -inline", Full = "-O -inline", Size = "-O -inline", Speed = "-O -inline", }, pic = { On = "-fPIC", }, warnings = { Default = "-wi", High = "-wi", Extra = "-wi", }, symbols = { On = "-g", FastLink = "-g", Full = "-g", } } function dmd.getdflags(cfg) local flags = config.mapFlags(cfg, dmd.dflags) if config.isDebugBuild(cfg) then table.insert(flags, "-debug") else table.insert(flags, "-release") end if not cfg.flags.OmitDefaultLibrary then local releaseruntime = not config.isDebugBuild(cfg) local staticruntime = true if cfg.staticruntime == "Off" then staticruntime = false end if cfg.runtime == "Debug" then releaseruntime = false elseif cfg.runtime == "Release" then releaseruntime = true end if (cfg.staticruntime and cfg.staticruntime ~= "Default") or (cfg.runtime and cfg.runtime ~= "Default") then if staticruntime == true and releaseruntime == true then table.insert(flags, "-mscrtlib=libcmt") elseif staticruntime == true and releaseruntime == false then table.insert(flags, "-mscrtlib=libcmtd") elseif staticruntime == false and releaseruntime == true then table.insert(flags, "-mscrtlib=msvcrt") elseif staticruntime == false and releaseruntime == false then table.insert(flags, "-mscrtlib=msvcrtd") end end end if cfg.flags.Documentation then if cfg.docname then table.insert(flags, "-Df" .. p.quoted(cfg.docname)) end if cfg.docdir then table.insert(flags, "-Dd" .. p.quoted(cfg.docdir)) end end if cfg.flags.GenerateHeader then if cfg.headername then table.insert(flags, "-Hf" .. p.quoted(cfg.headername)) end if cfg.headerdir then table.insert(flags, "-Hd" .. p.quoted(cfg.headerdir)) end end return flags end function dmd.getversions(versions, level) local result = {} for _, version in ipairs(versions) do table.insert(result, '-version=' .. version) end if level then table.insert(result, '-version=' .. level) end return result end function dmd.getdebug(constants, level) local result = {} for _, constant in ipairs(constants) do table.insert(result, '-debug=' .. constant) end if level then table.insert(result, '-debug=' .. level) end return result end function dmd.getimportdirs(cfg, dirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-I' .. p.quoted(dir)) end return result end function dmd.getstringimportdirs(cfg, dirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-J' .. p.quoted(dir)) end return result end function dmd.gettarget(name) return "-of" .. name end dmd.makesettings = { } function dmd.getmakesettings(cfg) local settings = config.mapFlags(cfg, dmd.makesettings) return table.concat(settings) end dmd.tools = { } function dmd.gettoolname(cfg, tool) local names = dmd.tools[cfg.architecture] or dmd.tools[cfg.system] or {} local name = names[tool] return name or dmd[tool] end local p = premake local m = p.modules.d m.make = {} local dmake = m.make require ("gmake") local make = p.make local cpp = p.make.cpp local project = p.project local config = p.config local fileconfig = p.fileconfig local gmake = p.action.get( 'gmake' ) if gmake == nil then error( "Failed to locate prequisite action 'gmake'" ) end gmake.valid_languages = table.join(gmake.valid_languages, { p.D } ) gmake.valid_tools.dc = { "dmd", "gdc", "ldc" } function m.make.separateCompilation(prj) local some = false local all = true for cfg in project.eachconfig(prj) do if cfg.compilationmodel == "File" then some = true else all = false end end return iif(all, "all", iif(some, "some", "none")) end p.override( gmake, "onProject", function(oldfn, prj) p.escaper(make.esc) if project.isd(prj) then local makefile = make.getmakefilename(prj, true) p.generate(prj, makefile, m.make.generate) return end oldfn(prj) end) p.override( make, "objdir", function(oldfn, cfg) if cfg.project.language ~= "D" or cfg.compilationmodel == "File" then oldfn(cfg) end end) p.override( make, "objDirRules", function(oldfn, prj) if prj.language ~= "D" or m.make.separateCompilation(prj) ~= "none" then oldfn(prj) end end) m.elements = {} m.elements.makefile = function(prj) return { make.header, make.phonyRules, m.make.configs, m.make.objects,-- TODO: This is basically identical to make.cppObjects(), and should ideally be merged/shared make.shellType, m.make.targetRules, make.targetDirRules, make.objDirRules, make.cppCleanRules,-- D clean code is identical to C/C++ make.preBuildRules, make.preLinkRules, m.make.dFileRules, } end function m.make.generate(prj) p.callArray(m.elements.makefile, prj) end function m.make.buildRule(prj) _p('$(TARGET): $(SOURCEFILES) $(LDDEPS)') _p('\t@echo Building %s', prj.name) _p('\t$(SILENT) $(BUILDCMD)') _p('\t$(POSTBUILDCMDS)') end function m.make.linkRule(prj) _p('$(TARGET): $(OBJECTS) $(LDDEPS)') _p('\t@echo Linking %s', prj.name) _p('\t$(SILENT) $(LINKCMD)') _p('\t$(POSTBUILDCMDS)') end function m.make.targetRules(prj) local separateCompilation = m.make.separateCompilation(prj) if separateCompilation == "all" then m.make.linkRule(prj) elseif separateCompilation == "none" then m.make.buildRule(prj) else for cfg in project.eachconfig(prj) do _x('ifeq ($(config),%s)', cfg.shortname) if cfg.compilationmodel == "File" then m.make.linkRule(prj) else m.make.buildRule(prj) end _p('endif') end end _p('') end function m.make.dFileRules(prj) local separateCompilation = m.make.separateCompilation(prj) if separateCompilation ~= "none" then make.cppFileRules(prj) end end p.override(cpp, "standardFileRules", function(oldfn, prj, node) if path.isdfile(node.abspath) then _p('\t$(SILENT) $(DC) $(ALL_DFLAGS) $(OUTPUTFLAG) -c $<') else oldfn(prj, node) end end) p.override(make, "fileType", function(oldfn, node) if path.isdfile(node.abspath) then return "objects" else return oldfn(node) end end) m.elements.makeconfig = function(cfg) return { m.make.dTools, make.target, m.make.target, make.objdir, m.make.versions, m.make.debug, m.make.imports, m.make.stringImports, m.make.dFlags, make.libs, make.ldDeps, make.ldFlags, m.make.linkCmd, make.preBuildCmds, make.preLinkCmds, make.postBuildCmds, m.make.allRules, make.settings, } end function m.make.configs(prj) for cfg in project.eachconfig(prj) do local toolset = p.tools[_OPTIONS.dc or cfg.toolset or "dmd"] if not toolset then error("Invalid toolset '" + (_OPTIONS.dc or cfg.toolset) + "'") end _x('ifeq ($(config),%s)', cfg.shortname) p.callArray(m.elements.makeconfig, cfg, toolset) _p('endif') _p('') end end function m.make.dTools(cfg, toolset) local tool = toolset.gettoolname(cfg, "dc") if tool then _p(' DC = %s', tool) end end function m.make.target(cfg, toolset) if cfg.compilationmodel == "File" then _p(' OUTPUTFLAG = %s', toolset.gettarget('"$@"')) end end function m.make.versions(cfg, toolset) _p(' VERSIONS +=%s', make.list(toolset.getversions(cfg.versionconstants, cfg.versionlevel))) end function m.make.debug(cfg, toolset) _p(' DEBUG +=%s', make.list(toolset.getdebug(cfg.debugconstants, cfg.debuglevel))) end function m.make.imports(cfg, toolset) local imports = p.esc(toolset.getimportdirs(cfg, cfg.importdirs)) _p(' IMPORTS +=%s', make.list(imports)) end function m.make.stringImports(cfg, toolset) local stringImports = p.esc(toolset.getstringimportdirs(cfg, cfg.stringimportdirs)) _p(' STRINGIMPORTS +=%s', make.list(stringImports)) end function m.make.dFlags(cfg, toolset) _p(' ALL_DFLAGS += $(DFLAGS)%s $(VERSIONS) $(DEBUG) $(IMPORTS) $(STRINGIMPORTS) $(ARCH)', make.list(table.join(toolset.getdflags(cfg), cfg.buildoptions))) end function m.make.linkCmd(cfg, toolset) if cfg.compilationmodel == "File" then _p(' LINKCMD = $(DC) ' .. toolset.gettarget("$(TARGET)") .. ' $(ALL_LDFLAGS) $(LIBS) $(OBJECTS)') else _p(' BUILDCMD = $(DC) ' .. toolset.gettarget("$(TARGET)") .. ' $(ALL_DFLAGS) $(ALL_LDFLAGS) $(LIBS) $(SOURCEFILES)') end end function m.make.allRules(cfg, toolset) if cfg.compilationmodel == "File" then _p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)') else _p('all: $(TARGETDIR) prebuild prelink $(TARGET)') end _p('\t@:') end function m.make.objects(prj) local root = { sourcefiles={}, objects={} } local configs = {} for cfg in project.eachconfig(prj) do configs[cfg] = { sourcefiles={}, objects={} } end local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) local incfg = {} local inall = true local custom = false for cfg in project.eachconfig(prj) do local filecfg = fileconfig.getconfig(node, cfg) if filecfg and not filecfg.flags.ExcludeFromBuild then incfg[cfg] = filecfg custom = fileconfig.hasCustomBuildRule(filecfg) else inall = false end end if not custom then if not path.isdfile(node.abspath) then return end local sourcename = node.relpath local objectname = "$(OBJDIR)/" .. node.objname .. ".o" if inall then table.insert(root.sourcefiles, sourcename) table.insert(root.objects, objectname) else for cfg in project.eachconfig(prj) do if incfg[cfg] then table.insert(configs[cfg].sourcefiles, sourcename) table.insert(configs[cfg].objects, objectname) end end end else for cfg in project.eachconfig(prj) do local filecfg = incfg[cfg] if filecfg then local output = project.getrelative(prj, filecfg.buildoutputs[1]) if path.isobjectfile(output) then table.insert(configs[cfg].objects, output) end end end end end }) local separateCompilation = m.make.separateCompilation(prj) function listobjects(var, list) _p('%s \\', var) for _, objectname in ipairs(list) do _x('\t%s \\', objectname) end _p('') end if separateCompilation ~= "all" then listobjects('SOURCEFILES :=', root.sourcefiles) end if separateCompilation ~= "none" then listobjects('OBJECTS :=', root.objects, 'o') end for cfg in project.eachconfig(prj) do local files = configs[cfg] if (#files.sourcefiles > 0 and separateCompilation ~= "all") or (#files.objects > 0 and separateCompilation ~= "none") then _x('ifeq ($(config),%s)', cfg.shortname) if #files.sourcefiles > 0 and separateCompilation ~= "all" then listobjects(' SOURCEFILES +=', files.sourcefiles) end if #files.objects > 0 and separateCompilation ~= "none" then listobjects(' OBJECTS +=', files.objects) end _p('endif') end end _p('') end 2.5.4.3local p = premake local api = p.api local DOC_URL = "See https://github.com/premake/premake-core/wiki/" api.register { name = "architecture", scope = "config", kind = "string", allowed = { "universal", p.X86, p.X86_64, p.ARM, p.ARM64, }, aliases = { i386 = p.X86, amd64 = p.X86_64, x32 = p.X86,-- these should be DEPRECATED x64 = p.X86_64, }, } api.register { name = "atl", scope = "config", kind = "string", allowed = { "Off", "Dynamic", "Static", }, } api.register { name = "basedir", scope = "project", kind = "path" } api.register { name = "buildaction", scope = "config", kind = "string", } api.register { name = "buildcommands", scope = { "config", "rule" }, kind = "list:string", tokens = true, pathVars = true, } api.register { name = "buildcustomizations", scope = "project", kind = "list:string", } api.register { name = "builddependencies", scope = { "rule" }, kind = "list:string", tokens = true, pathVars = true, } api.register { name = "buildlog", scope = { "config" }, kind = "path", tokens = true, pathVars = true, } api.register { name = "buildmessage", scope = { "config", "rule" }, kind = "string", tokens = true, pathVars = true, } api.register { name = "buildoptions", scope = "config", kind = "list:string", tokens = true, pathVars = true, } api.register { name = "buildoutputs", scope = { "config", "rule" }, kind = "list:path", tokens = true, pathVars = false, } api.register { name = "buildinputs", scope = "config", kind = "list:path", tokens = true, pathVars = false, } api.register { name = "buildrule", -- DEPRECATED scope = "config", kind = "table", tokens = true, } api.register { name = "characterset", scope = "config", kind = "string", allowed = { "Default", "ASCII", "MBCS", "Unicode", } } api.register { name = "cleancommands", scope = "config", kind = "list:string", tokens = true, pathVars = true, } api.register { name = "cleanextensions", scope = "config", kind = "list:string", } api.register { name = "clr", scope = "config", kind = "string", allowed = { "Off", "On", "Pure", "Safe", "Unsafe", } } api.register { name = "compilebuildoutputs", scope = "config", kind = "boolean" } api.register { name = "compileas", scope = "config", kind = "string", allowed = { "Default", "C", "C++", } } api.register { name = "configmap", scope = "project", kind = "list:keyed:array:string", } api.register { name = "configurations", scope = "project", kind = "list:string", } api.register { name = "copylocal", scope = "config", kind = "list:mixed", tokens = true, } api.register { name = "debugargs", scope = "config", kind = "list:string", tokens = true, pathVars = true, allowDuplicates = true, } api.register { name = "debugcommand", scope = "config", kind = "path", tokens = true, pathVars = true, } api.register { name = "debugconnectcommands", scope = "config", kind = "list:string", tokens = true, } api.register { name = "debugdir", scope = "config", kind = "path", tokens = true, pathVars = true, } api.register { name = "debugenvs", scope = "config", kind = "list:string", tokens = true, pathVars = true, } api.register { name = "debugextendedprotocol", scope = "config", kind = "boolean", } api.register { name = "debugformat", scope = "config", kind = "string", allowed = { "Default", "c7", "Dwarf", "SplitDwarf", }, } api.register { name = "debugger", scope = "config", kind = "string", allowed = { "Default", "GDB", "LLDB", } } api.register { name = "debuggertype", scope = "config", kind = "string", allowed = { "Mixed", "NativeOnly", "ManagedOnly", } } api.register { name = "debugpathmap", scope = "config", kind = "list:keyed:path", tokens = true, } api.register { name = "debugport", scope = "config", kind = "integer", } api.register { name = "debugremotehost", scope = "config", kind = "string", tokens = true, } api.register { name = "debugsearchpaths", scope = "config", kind = "list:path", tokens = true, } api.register { name = "debugstartupcommands", scope = "config", kind = "list:string", tokens = true, } api.register { name = "debugtoolargs", scope = "config", kind = "list:string", tokens = true, pathVars = true, } api.register { name = "debugtoolcommand", scope = "config", kind = "path", tokens = true, pathVars = true, } api.register { name = "defaultplatform", scope = "project", kind = "string", } api.register { name = "defines", scope = "config", kind = "list:string", tokens = true, } api.register { name = "dependson", scope = "config", kind = "list:string", tokens = true, } api.register { name = "disablewarnings", scope = "config", kind = "list:string", tokens = true, } api.register { name = "display", scope = "rule", kind = "string", } api.register { name = "dpiawareness", scope = "config", kind = "string", allowed = { "Default", "None", "High", "HighPerMonitor", } } api.register { name = "editandcontinue", scope = "config", kind = "string", allowed = { "Default", "On", "Off", }, } api.register { name = "exceptionhandling", scope = "config", kind = "string", allowed = { "Default", "On", "Off", "SEH", "CThrow", }, } api.register { name = "enablewarnings", scope = "config", kind = "list:string", tokens = true, } api.register { name = "endian", scope = "config", kind = "string", allowed = { "Default", "Little", "Big", }, } api.register { name = "entrypoint", scope = "config", kind = "string", } api.register { name = "fatalwarnings", scope = "config", kind = "list:string", tokens = true, } api.register { name = "fileextension", scope = "rule", kind = "list:string", } api.register { name = "filename", scope = { "project", "rule" }, kind = "string", tokens = true, } api.register { name = "files", scope = "config", kind = "list:file", tokens = true, } api.register { name = "functionlevellinking", scope = "config", kind = "boolean" } api.register { name = "flags", scope = "config", kind = "list:string", allowed = { "Component", -- DEPRECATED "DebugEnvsDontMerge", "DebugEnvsInherit", "EnableSSE", -- DEPRECATED "EnableSSE2", -- DEPRECATED "ExcludeFromBuild", "ExtraWarnings", -- DEPRECATED "FatalCompileWarnings", "FatalLinkWarnings", "FloatFast", -- DEPRECATED "FloatStrict", -- DEPRECATED "LinkTimeOptimization", "Managed", -- DEPRECATED "Maps", "MFC", "MultiProcessorCompile", "NativeWChar", -- DEPRECATED "No64BitChecks", "NoCopyLocal", "NoEditAndContinue", -- DEPRECATED "NoFramePointer", -- DEPRECATED "NoImplicitLink", "NoImportLib", "NoIncrementalLink", "NoManifest", "NoMinimalRebuild", "NoNativeWChar", -- DEPRECATED "NoPCH", "NoRuntimeChecks", "NoBufferSecurityCheck", "NoWarnings", -- DEPRECATED "OmitDefaultLibrary", "Optimize", -- DEPRECATED "OptimizeSize", -- DEPRECATED "OptimizeSpeed", -- DEPRECATED "RelativeLinks", "ReleaseRuntime", -- DEPRECATED "ShadowedVariables", "StaticRuntime", -- DEPRECATED "Symbols", -- DEPRECATED "UndefinedIdentifiers", "WinMain", -- DEPRECATED "WPF", "C++11", -- DEPRECATED "C++14", -- DEPRECATED "C90", -- DEPRECATED "C99", -- DEPRECATED "C11", -- DEPRECATED }, aliases = { FatalWarnings = { "FatalWarnings", "FatalCompileWarnings", "FatalLinkWarnings" }, Optimise = 'Optimize', OptimiseSize = 'OptimizeSize', OptimiseSpeed = 'OptimizeSpeed', }, } api.register { name = "floatingpoint", scope = "config", kind = "string", allowed = { "Default", "Fast", "Strict", } } api.register { name = "floatingpointexceptions", scope = "config", kind = "boolean" } api.register { name = "inlining", scope = "config", kind = "string", allowed = { "Default", "Disabled", "Explicit", "Auto" } } api.register { name = "callingconvention", scope = "config", kind = "string", allowed = { "Cdecl", "FastCall", "StdCall", "VectorCall", } } api.register { name = "forceincludes", scope = "config", kind = "list:mixed", tokens = true, } api.register { name = "forceusings", scope = "config", kind = "list:file", tokens = true, } api.register { name = "fpu", scope = "config", kind = "string", allowed = { "Software", "Hardware", } } api.register { name = "dotnetframework", scope = "config", kind = "string", } api.register { name = "csversion", scope = "config", kind = "string", } api.register { name = "gccprefix", scope = "config", kind = "string", tokens = true, } api.register { name = "ignoredefaultlibraries", scope = "config", kind = "list:mixed", tokens = true, } api.register { name = "icon", scope = "project", kind = "file", tokens = true, } api.register { name = "imageoptions", scope = "config", kind = "list:string", tokens = true, } api.register { name = "imagepath", scope = "config", kind = "path", tokens = true, } api.register { name = "implibdir", scope = "config", kind = "path", tokens = true, } api.register { name = "implibextension", scope = "config", kind = "string", tokens = true, } api.register { name = "implibname", scope = "config", kind = "string", tokens = true, } api.register { name = "implibprefix", scope = "config", kind = "string", tokens = true, } api.register { name = "implibsuffix", scope = "config", kind = "string", tokens = true, } api.register { name = "includedirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "intrinsics", scope = "config", kind = "boolean" } api.register { name = "bindirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "kind", scope = "config", kind = "string", allowed = { "ConsoleApp", "Makefile", "None", "SharedLib", "StaticLib", "WindowedApp", "Utility", }, } api.register { name = "sharedlibtype", scope = "project", kind = "string", allowed = { "OSXBundle", "OSXFramework", "XCTest", }, } api.register { name = "language", scope = "project", kind = "string", allowed = { "C", "C++", "C#", "F#" } } api.register { name = "cdialect", scope = "config", kind = "string", allowed = { "Default", "C89", "C90", "C99", "C11", "gnu89", "gnu90", "gnu99", "gnu11", } } api.register { name = "cppdialect", scope = "config", kind = "string", allowed = { "Default", "C++latest", "C++98", "C++0x", "C++11", "C++1y", "C++14", "C++1z", "C++17", "gnu++98", "gnu++0x", "gnu++11", "gnu++1y", "gnu++14", "gnu++1z", "gnu++17", } } api.register { name = "libdirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "frameworkdirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "linkbuildoutputs", scope = "config", kind = "boolean" } api.register { name = "linkoptions", scope = "config", kind = "list:string", tokens = true, } api.register { name = "links", scope = "config", kind = "list:mixed", tokens = true, } api.register { name = "linkgroups", scope = "config", kind = "string", allowed = { "Off", "On", } } api.register { name = "locale", scope = "config", kind = "string", tokens = false, } api.register { name = "location", scope = { "project", "rule" }, kind = "path", tokens = true, } api.register { name = "makesettings", scope = "config", kind = "list:string", tokens = true, } api.register { name = "namespace", scope = "project", kind = "string", tokens = true, } api.register { name = "nativewchar", scope = "config", kind = "string", allowed = { "Default", "On", "Off", } } api.register { name = "nuget", scope = "config", kind = "list:string", tokens = true, } api.register { name = "nugetsource", scope = "project", kind = "string", tokens = true, } api.register { name = "objdir", scope = "config", kind = "path", tokens = true, } api.register { name = "optimize", scope = "config", kind = "string", allowed = { "Off", "On", "Debug", "Size", "Speed", "Full", } } api.register { name = "runpathdirs", scope = "config", kind = "list:path", tokens = true, } api.register { name = "runtime", scope = "config", kind = "string", allowed = { "Debug", "Release", } } api.register { name = "pchheader", scope = "config", kind = "string", tokens = true, } api.register { name = "pchsource", scope = "config", kind = "path", tokens = true, } api.register { name = "pic", scope = "config", kind = "string", allowed = { "Off", "On", } } api.register { name = "platforms", scope = "project", kind = "list:string", } api.register { name = "postbuildcommands", scope = "config", kind = "list:string", tokens = true, pathVars = true, allowDuplicates = true, } api.register { name = "postbuildmessage", scope = "config", kind = "string", tokens = true, pathVars = true, } api.register { name = "prebuildcommands", scope = "config", kind = "list:string", tokens = true, pathVars = true, allowDuplicates = true, } api.register { name = "prebuildmessage", scope = "config", kind = "string", tokens = true, pathVars = true, } api.register { name = "prelinkcommands", scope = "config", kind = "list:string", tokens = true, pathVars = true, } api.register { name = "prelinkmessage", scope = "config", kind = "string", tokens = true, pathVars = true, } api.register { name = "propertydefinition", scope = "rule", kind = "list:table", } api.register { name = "rebuildcommands", scope = "config", kind = "list:string", tokens = true, pathVars = true, } api.register { name = "resdefines", scope = "config", kind = "list:string", tokens = true, } api.register { name = "resincludedirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "resoptions", scope = "config", kind = "list:string", tokens = true, } api.register { name = "resourcegenerator", scope = "project", kind = "string", allowed = { "internal", "public" } } api.register { name = "rtti", scope = "config", kind = "string", allowed = { "Default", "On", "Off", }, } api.register { name = "rules", scope = "project", kind = "list:string", } api.register { name = "startproject", scope = "workspace", kind = "string", tokens = true, } api.register { name = "staticruntime", scope = "config", kind = "string", allowed = { "Default", "On", "Off" } } api.register { name = "strictaliasing", scope = "config", kind = "string", allowed = { "Off", "Level1", "Level2", "Level3", } } api.register { name = "stringpooling", scope = "config", kind = "boolean" } api.register { name = "symbols", scope = "config", kind = "string", allowed = { "Default", "On", "Off", "FastLink", -- Visual Studio 2015+ only, considered 'On' for all other cases. "Full", -- Visual Studio 2017+ only, considered 'On' for all other cases. }, } api.register { name = "symbolspath", scope = "config", kind = "path", tokens = true, } api.register { name = "sysincludedirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "syslibdirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "system", scope = "config", kind = "string", allowed = { "aix", "bsd", "haiku", "ios", "linux", "macosx", "solaris", "wii", "windows", }, } api.register { name = "systemversion", scope = "config", kind = "string", } api.register { name = "tags", scope = "config", kind = "list:string", } api.register { name = "tailcalls", scope = "config", kind = "boolean" } api.register { name = "targetdir", scope = "config", kind = "path", tokens = true, } api.register { name = "targetextension", scope = "config", kind = "string", tokens = true, } api.register { name = "targetname", scope = "config", kind = "string", tokens = true, } api.register { name = "targetprefix", scope = "config", kind = "string", tokens = true, } api.register { name = "targetsuffix", scope = "config", kind = "string", tokens = true, } api.register { name = "toolset", scope = "config", kind = "string", allowed = function(value) value = value:lower() local tool, version = p.tools.canonical(value) if tool then return p.tools.normalize(value) else return nil end end, } api.register { name = "customtoolnamespace", scope = "config", kind = "string", } api.register { name = "undefines", scope = "config", kind = "list:string", tokens = true, } api.register { name = "usingdirs", scope = "config", kind = "list:directory", tokens = true, } api.register { name = "uuid", scope = "project", kind = "string", allowed = function(value) local ok = true if (#value ~= 36) then ok = false end for i=1,36 do local ch = value:sub(i,i) if (not ch:find("[ABCDEFabcdef0123456789-]")) then ok = false end end if (value:sub(9,9) ~= "-") then ok = false end if (value:sub(14,14) ~= "-") then ok = false end if (value:sub(19,19) ~= "-") then ok = false end if (value:sub(24,24) ~= "-") then ok = false end if (not ok) then return nil, "invalid UUID" end return value:upper() end } api.register { name = "vectorextensions", scope = "config", kind = "string", allowed = { "Default", "AVX", "AVX2", "IA32", "SSE", "SSE2", "SSE3", "SSSE3", "SSE4.1", } } api.register { name = "isaextensions", scope = "config", kind = "list:string", allowed = { "MOVBE", "POPCNT", "PCLMUL", "LZCNT", "BMI", "BMI2", "F16C", "AES", "FMA", "FMA4", "RDRND", } } api.register { name = "vpaths", scope = "project", kind = "list:keyed:list:path", tokens = true, pathVars = true, } api.register { name = "warnings", scope = "config", kind = "string", allowed = { "Off", "Default", "High", "Extra", } } api.register { name = "largeaddressaware", scope = "config", kind = "boolean", } api.register { name = "editorintegration", scope = "workspace", kind = "boolean", } api.register { name = "preferredtoolarchitecture", scope = "workspace", kind = "string", allowed = { "Default", p.X86, p.X86_64, } } api.register { name = "unsignedchar", scope = "config", kind = "boolean", } p.api.register { name = "structmemberalign", scope = "config", kind = "integer", allowed = { "1", "2", "4", "8", "16", } } api.register { name = "omitframepointer", scope = "config", kind = "string", allowed = { "Default", "On", "Off" } } api.register { name = "visibility", scope = "config", kind = "string", allowed = { "Default", "Hidden", "Internal", "Protected" } } api.register { name = "inlinesvisibility", scope = "config", kind = "string", allowed = { "Default", "Hidden" } } api.alias("buildcommands", "buildCommands") api.alias("builddependencies", "buildDependencies") api.alias("buildmessage", "buildMessage") api.alias("buildoutputs", "buildOutputs") api.alias("cleanextensions", "cleanExtensions") api.alias("dotnetframework", "framework") api.alias("editandcontinue", "editAndContinue") api.alias("fileextension", "fileExtension") api.alias("propertydefinition", "propertyDefinition") api.alias("removefiles", "excludes") api.deprecateField("buildrule", 'Use `buildcommands`, `buildoutputs`, and `buildmessage` instead.', function(value) if value.description then buildmessage(value.description) end buildcommands(value.commands) buildoutputs(value.outputs) end) api.deprecateValue("flags", "Component", 'Use `buildaction "Component"` instead.', function(value) buildaction "Component" end) api.deprecateValue("flags", "EnableSSE", 'Use `vectorextensions "SSE"` instead.', function(value) vectorextensions("SSE") end, function(value) vectorextensions "Default" end) api.deprecateValue("flags", "EnableSSE2", 'Use `vectorextensions "SSE2"` instead.', function(value) vectorextensions("SSE2") end, function(value) vectorextensions "Default" end) api.deprecateValue("flags", "FloatFast", 'Use `floatingpoint "Fast"` instead.', function(value) floatingpoint("Fast") end, function(value) floatingpoint "Default" end) api.deprecateValue("flags", "FloatStrict", 'Use `floatingpoint "Strict"` instead.', function(value) floatingpoint("Strict") end, function(value) floatingpoint "Default" end) api.deprecateValue("flags", "NativeWChar", 'Use `nativewchar "On"` instead."', function(value) nativewchar("On") end, function(value) nativewchar "Default" end) api.deprecateValue("flags", "NoNativeWChar", 'Use `nativewchar "Off"` instead."', function(value) nativewchar("Off") end, function(value) nativewchar "Default" end) api.deprecateValue("flags", "Optimize", 'Use `optimize "On"` instead.', function(value) optimize ("On") end, function(value) optimize "Off" end) api.deprecateValue("flags", "OptimizeSize", 'Use `optimize "Size"` instead.', function(value) optimize ("Size") end, function(value) optimize "Off" end) api.deprecateValue("flags", "OptimizeSpeed", 'Use `optimize "Speed"` instead.', function(value) optimize ("Speed") end, function(value) optimize "Off" end) api.deprecateValue("flags", "ReleaseRuntime", 'Use `runtime "Release"` instead.', function(value) runtime "Release" end, function(value) end) api.deprecateValue("flags", "ExtraWarnings", 'Use `warnings "Extra"` instead.', function(value) warnings "Extra" end, function(value) warnings "Default" end) api.deprecateValue("flags", "NoWarnings", 'Use `warnings "Off"` instead.', function(value) warnings "Off" end, function(value) warnings "Default" end) api.deprecateValue("flags", "Managed", 'Use `clr "On"` instead.', function(value) clr "On" end, function(value) clr "Off" end) api.deprecateValue("flags", "NoEditAndContinue", 'Use editandcontinue "Off"` instead.', function(value) editandcontinue "Off" end, function(value) editandcontinue "On" end) api.deprecateValue("flags", "Symbols", 'Use `symbols "On"` instead', function(value) symbols "On" end, function(value) symbols "Default" end) api.deprecateValue("flags", "C++11", 'Use `cppdialect "C++11"` instead', function(value) cppdialect "C++11" end, function(value) cppdialect "Default" end) api.deprecateValue("flags", "C++14", 'Use `cppdialect "C++14"` instead', function(value) cppdialect "C++14" end, function(value) cppdialect "Default" end) api.deprecateValue("flags", "C90", 'Use `cdialect "gnu90"` instead', function(value) cdialect "gnu90" end, function(value) cdialect "Default" end) api.deprecateValue("flags", "C99", 'Use `cdialect "gnu99"` instead', function(value) cdialect "gnu99" end, function(value) cdialect "Default" end) api.deprecateValue("flags", "C11", 'Use `cdialect "gnu11"` instead', function(value) cdialect "gnu11" end, function(value) cdialect "Default" end) api.deprecateValue("flags", "WinMain", 'Use `entrypoint "WinMainCRTStartup"` instead', function(value) entrypoint "WinMainCRTStartup" end, function(value) entrypoint "mainCRTStartup" end) api.deprecateValue("flags", "StaticRuntime", 'Use `staticruntime "On"` instead', function(value) staticruntime "On" end, function(value) staticruntime "Default" end) api.deprecateValue("flags", "NoFramePointer", 'Use `omitframepointer "On"` instead.', function(value) omitframepointer("On") end, function(value) omitframepointer("Default") end) newoption { category= "compilers", trigger = "cc", value = "VALUE", description = "Choose a C/C++ compiler set", allowed = { { "clang", "Clang (clang)" }, { "gcc", "GNU GCC (gcc/g++)" }, } } newoption { category= "compilers", trigger = "dotnet", value = "VALUE", description = "Choose a .NET compiler set", allowed = { { "msnet", "Microsoft .NET (csc)" }, { "mono", "Novell Mono (mcs)" }, { "pnet", "Portable.NET (cscc)" }, } } newoption { trigger = "fatal", description = "Treat warnings from project scripts as errors" } newoption { trigger = "debugger", description = "Start MobDebug remote debugger. Works with ZeroBrane Studio" } newoption { trigger = "file", value = "FILE", description = "Read FILE as a Premake script; default is 'premake5.lua'" } newoption { trigger = "help", description = "Display this information" } newoption { trigger = "verbose", description = "Generate extra debug text output" } newoption { trigger = "interactive", description = "Interactive command prompt" } newoption { trigger = "os", value = "VALUE", description = "Generate files for a different operating system", allowed = { { "aix", "IBM AIX" }, { "bsd", "OpenBSD, NetBSD, or FreeBSD" }, { "haiku", "Haiku" }, { "hurd", "GNU/Hurd" }, { "ios", "iOS" }, { "linux", "Linux" }, { "macosx", "Apple Mac OS X" }, { "solaris", "Solaris" }, { "windows", "Microsoft Windows" }, } } newoption { trigger = "scripts", value = "PATH", description = "Search for additional scripts on the given path" } newoption { trigger = "systemscript", value = "FILE", description = "Override default system script (premake5-system.lua)" } newoption { trigger = "version", description = "Display version information" } if http ~= nil then newoption { trigger = "insecure", description = "forfit SSH certification checks." } end characterset "Default" clr "Off" editorintegration "Off" exceptionhandling "Default" rtti "Default" symbols "Default" nugetsource "https://api.nuget.org/v3/index.json" language "C++" filter { "kind:SharedLib" } targetprefix "lib" targetextension ".so" filter { "kind:StaticLib" } targetprefix "lib" targetextension ".a" filter { "system:darwin", "kind:WindowedApp" } targetextension ".app" filter { "system:darwin", "kind:SharedLib" } targetextension ".dylib" filter { "system:darwin", "kind:SharedLib", "sharedlibtype:OSXBundle" } targetprefix "" targetextension ".bundle" filter { "system:darwin", "kind:SharedLib", "sharedlibtype:OSXFramework" } targetprefix "" targetextension ".framework" filter { "system:darwin", "kind:SharedLib", "sharedlibtype:XCTest" } targetprefix "" targetextension ".xctest" filter { "system:Windows or language:C# or language:F#", "kind:ConsoleApp or WindowedApp" } targetextension ".exe" filter { "system:Windows", "kind:SharedLib" } targetprefix "" targetextension ".dll" implibextension ".lib" filter { "system:Windows", "kind:StaticLib" } targetprefix "" targetextension ".lib" filter { "language:C# or language:F#", "kind:SharedLib" } targetprefix "" targetextension ".dll" implibextension ".dll" filter { "kind:SharedLib", "system:not Windows" } pic "On" filter { "system:darwin" } toolset "clang" filter { "platforms:Win64" } architecture "x86_64" filter {} local p = premake local project = p.project local workspace = p.workspace local tree = p.tree local codelite = p.modules.codelite codelite.workspace = {} local m = codelite.workspace function m.generate(wks) p.utf8() p.w('') local tagsdb = "" p.push('', wks.name, tagsdb) local tr = workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) local prj = n.project local prjpath = p.filename(prj, ".project") prjpath = path.getrelative(prj.workspace.location, prjpath) if (prj.name == wks.startproject) then p.w('', prj.name, prjpath) else p.w('', prj.name, prjpath) end end, onbranchenter = function(n) p.push('', n.name) end, onbranchexit = function(n) p.pop('') end, }) local platformsPresent = {} local numPlatforms = 0 for cfg in workspace.eachconfig(wks) do local platform = cfg.platform if platform and not platformsPresent[platform] then numPlatforms = numPlatforms + 1 platformsPresent[platform] = true end end if numPlatforms >= 2 then codelite.workspace.multiplePlatforms = true end p.push('') for cfg in workspace.eachconfig(wks) do local cfgname = codelite.cfgname(cfg) p.push('', cfgname) local tr = workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) local prj = n.project p.w('', prj.name, cfgname) end }) p.pop('') end p.pop('') p.pop('') end local p = premake p.field = {} local field = p.field field._list = {} field._loweredList = {} field._sortedList = nil field._kinds = {} premake.fields = field._list field._accessors = {} function field.new(f) if f.kind:startswith("key-") then f.kind = f.kind:sub(5) f.keyed = true end if f.kind:endswith("-list") then f.kind = f.kind:sub(1, -6) f.list = true end local kind = f.kind if kind == "object" or kind == "array" then kind = "table" end if f.list then kind = "list:" .. kind end if f.keyed then kind = "keyed:" .. kind end f._kind = kind if type(f.scope) == "table" then f.scopes = f.scope else f.scopes = { f.scope } end if not field.accessor(f, "store") then return nil, "invalid field kind '" .. f._kind .. "'" end field._list[f.name] = f field._loweredList[f.name:lower()] = f field._sortedList = nil return f end function field.unregister(f) field._list[f.name] = nil field._loweredList[f.name:lower()] = nil field._sortedList = nil end function field.each() local index return function () index = next(field._list, index) return field._list[index] end end function field.eachOrdered() if not field._sortedList then local keys = table.keys(field._list) table.sort(keys) field._sortedList = {} for i = 1, #keys do field._sortedList[i] = field._list[keys[i]] end end local i = 0 return function () i = i + 1 return field._sortedList[i] end end function field.kind(tag, settings) if settings then field._kinds[tag] = settings end return field._kinds[tag] end function field.accessor(f, method) field._accessors[method] = field._accessors[method] or {} local cache = field._accessors[method] local function accessorForKind(kind) if kind == "" then return nil end if cache[kind] then return cache[kind] end local thisKind = kind:match('(.-):') or kind local nextKind = kind:sub(#thisKind + 2) local functions = field._kinds[thisKind] if not functions then return nil, "Invalid field kind '" .. thisKind .. "'" end local processor = functions[method] if not processor then return nil end local nextAccessor = accessorForKind(nextKind) accessor = function(f, current, value) return processor(f, current, value, nextAccessor) end cache[kind] = accessor return accessor end return accessorForKind(f._kind) end function field.compare(f, a, b) local processor = field.accessor(f, "compare") if processor then return processor(f, a, b) else return (a == b) end end function field.get(name) return field._list[name] or field._loweredList[name:lower()] end function field.merge(f, current, value) local processor = field.accessor(f, "merge") if processor then return processor(f, current, value) else return value end end function field.merges(f) return (field.accessor(f, "merge") ~= nil) end function field.property(f, tag) local kinds = string.explode(f._kind, ":", true) for i, kind in ipairs(kinds) do local value = field._kinds[kind][tag] if value ~= nil then return value end end end function field.override(fieldName, accessorName, func) local kind = field.kind(fieldName) p.override(kind, accessorName, func) field._accessors = {} end function field.remove(f, current, value) local processor = field.accessor(f, "remove") if processor then return processor(f, current, value) else return value end end function field.removes(f) return (field.accessor(f, "merge") ~= nil and field.accessor(f, "remove") ~= nil) end function field.store(f, current, value) local processor = field.accessor(f, "store") if processor then return processor(f, current, value) else return value end end function field.translate(f, value) local processor = field.accessor(f, "translate") if processor then return processor(f, value, nil)[1] else return value end end function field.translates(f) return (field.accessor(f, "translate") ~= nil) end local p = premake p.make.utility = {} local make = p.make local utility = p.make.utility local project = p.project local config = p.config local fileconfig = p.fileconfig utility.elements = {} utility.elements.makefile = { "header", "phonyRules", "utilityConfigs", "utilityTargetRules" } function make.utility.generate(prj) p.eol("\n") p.callarray(make, utility.elements.makefile, prj) end utility.elements.configuration = { "target", "preBuildCmds", "postBuildCmds", } function make.utilityConfigs(prj) for cfg in project.eachconfig(prj) do local toolset = p.tools[cfg.toolset or "gcc"] if not toolset then error("Invalid toolset '" .. cfg.toolset .. "'") end _x('ifeq ($(config),%s)', cfg.shortname) p.callarray(make, utility.elements.configuration, cfg, toolset) _p('endif') _p('') end end function make.utilityTargetRules(prj) _p('$(TARGET):') _p('\t$(PREBUILDCMDS)') _p('\t$(POSTBUILDCMDS)') _p('') end local p = premake p.tools.dotnet = {} local dotnet = p.tools.dotnet local project = p.project local config = p.config function dotnet.fileinfo(fcfg) local info = {} if (fcfg == nil) then return info end local fname = fcfg.abspath local ext = path.getextension(fname):lower() if fcfg.buildaction == "Compile" or ext == ".cs" or ext == ".fs" then info.action = "Compile" elseif fcfg.buildaction == "Embed" or ext == ".resx" then info.action = "EmbeddedResource" elseif fcfg.buildaction == "Copy" or ext == ".asax" or ext == ".aspx" or ext == ".dll" or ext == ".tt" then info.action = "Content" elseif fcfg.buildaction == "Resource" then info.action = "Resource" elseif ext == ".xaml" then if fcfg.buildaction == "Application" or path.getbasename(fname) == "App" then if fcfg.project.kind == p.SHAREDLIB then info.action = "None" else info.action = "ApplicationDefinition" end else info.action = "Page" end else info.action = "None" end if info.action == "Compile" and fname:endswith(".cs") then if fname:endswith(".Designer.cs") then local basename = fname:sub(1, -13) local testname = basename .. ".resx" if project.hasfile(fcfg.project, testname) then info.AutoGen = "True" info.DependentUpon = testname end testname = basename .. ".settings" if project.hasfile(fcfg.project, testname) then info.AutoGen = "True" info.DependentUpon = testname info.DesignTimeSharedInput = "True" end testname = basename .. ".cs" if project.hasfile(fcfg.project, testname) then info.AutoGen = nil info.SubType = "Dependency" info.DependentUpon = testname end testname = basename .. ".xsd" if project.hasfile(fcfg.project, testname) then info.AutoGen = "True" info.DesignTime = "True" info.DependentUpon = testname end elseif fname:endswith(".xaml.cs") then info.SubType = "Code" info.DependentUpon = fname:sub(1, -4) else local basename = fname:sub(1, -4) testname = basename .. ".xsd" if project.hasfile(fcfg.project, testname) then info.DependentUpon = testname end testname = basename .. ".Designer.cs" if project.hasfile(fcfg.project, testname) then info.SubType = "Form" end testname = basename .. ".tt" if project.hasfile(fcfg.project, testname) then info.AutoGen = "True" info.DesignTime = "True" info.DependentUpon = testname end end if fcfg.buildaction == "Component" or fcfg.buildaction == "Form" or fcfg.buildaction == "UserControl" then info.SubType = fcfg.buildaction end if fcfg.flags and fcfg.flags.Component then info.SubType = "Component" end end if info.action == "Content" then info.CopyToOutputDirectory = "PreserveNewest" end if info.action == "EmbeddedResource" and fname:endswith(".resx") then local basename = fname:sub(1, -6) local testname = basename .. ".cs" if project.hasfile(fcfg.project, testname) then info.DependentUpon = testname if project.hasfile(fcfg.project, basename .. ".Designer.cs") then info.SubType = "DesignerType" end else testname = basename .. ".Designer.cs" if project.hasfile(fcfg.project, testname) then info.SubType = "Designer" local resourceAccessGenerator = "ResXFileCodeGenerator" if fcfg.project.resourcegenerator then if fcfg.project.resourcegenerator == "public" then resourceAccessGenerator = "PublicResXFileCodeGenerator" end end info.Generator = resourceAccessGenerator info.LastGenOutput = path.getname(testname) end end end if info.action == "None" and fname:endswith(".settings") then local testname = fname:sub(1, -10) .. ".Designer.cs" if project.hasfile(fcfg.project, testname) then info.Generator = "SettingsSingleFileGenerator" info.LastGenOutput = path.getname(testname) end end if info.action == "Content" and fname:endswith(".tt") then local testname = fname:sub(1, -4) .. ".cs" if project.hasfile(fcfg.project, testname) then info.Generator = "TextTemplatingFileGenerator" info.LastGenOutput = path.getname(testname) info.CopyToOutputDirectory = nil end end if info.action == "None" and fname:endswith(".xsd") then local testname = fname:sub(1, -5) .. ".Designer.cs" if project.hasfile(fcfg.project, testname) then info.SubType = "Designer" info.Generator = "MSDataSetGenerator" info.LastGenOutput = path.getname(testname) end end if info.action == "None" and (fname:endswith(".xsc") or fname:endswith(".xss")) then local testname = fname:sub(1, -5) .. ".xsd" if project.hasfile(fcfg.project, testname) then info.DependentUpon = testname end end if fname:endswith(".xaml") then local testname = fname .. ".cs" if project.hasfile(fcfg.project, testname) then info.SubType = "Designer" info.Generator = "MSBuild:Compile" end end if info.DependentUpon then info.DependentUpon = path.getname(info.DependentUpon) end return info end function dotnet.gettoolname(cfg, tool) local compilers = { msnet = "csc", mono = "mcs", pnet = "cscc", } if tool == "csc" then local toolset = _OPTIONS.dotnet or "msnet" return compilers[toolset] else return "resgen" end end dotnet.flags = { clr = { Unsafe = "/unsafe", }, flags = { FatalWarning = "/warnaserror", }, optimize = { On = "/optimize", Size = "/optimize", Speed = "/optimize", }, symbols = { On = "/debug", } } function dotnet.getflags(cfg) local flags = config.mapFlags(cfg, dotnet.flags) table.insert(flags, '/noconfig') if cfg.project.icon then local fn = project.getrelative(cfg.project, cfg.project.icon) table.insert(flags, string.format('/win32icon:"%s"', fn)) end if #cfg.defines > 0 then table.insert(flags, table.implode(cfg.defines, "/d:", "", " ")) end if cfg.csversion ~= nil then table.insert(flags, '/langversion:' .. cfg.csversion) end return table.join(flags, cfg.buildoptions) end function dotnet.getkind(cfg) if (cfg.kind == "ConsoleApp") then return "Exe" elseif (cfg.kind == "WindowedApp") then return "WinExe" elseif (cfg.kind == "SharedLib") then return "Library" else error("invalid dotnet kind " .. cfg.kind .. ". Valid kinds are ConsoleApp, WindowsApp, SharedLib") end end function dotnet.getmakesettings(cfg) return nil end local p = premake local vstudio = p.vstudio newaction { trigger = "vs2017", shortname = "Visual Studio 2017", description = "Generate Visual Studio 2017 project files", targetos = "windows", toolset = "msc-v141", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = function(wks) p.vstudio.vs2005.generateSolution(wks) end, onProject = function(prj) p.vstudio.vs2010.generateProject(prj) end, onRule = function(rule) p.vstudio.vs2010.generateRule(rule) end, onCleanWorkspace = function(wks) p.vstudio.cleanSolution(wks) end, onCleanProject = function(prj) p.vstudio.cleanProject(prj) end, onCleanTarget = function(prj) p.vstudio.cleanTarget(prj) end, pathVars = vstudio.vs2010.pathVars, vstudio = { solutionVersion = "12", versionName = "15", targetFramework = "4.5.2", toolsVersion = "15.0", filterToolsVersion = "4.0", } } local p = premake local vstudio = p.vstudio newaction { trigger = "vs2015", shortname = "Visual Studio 2015", description = "Generate Visual Studio 2015 project files", targetos = "windows", toolset = "msc-v140", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = function(wks) vstudio.vs2005.generateSolution(wks) end, onProject = function(prj) vstudio.vs2010.generateProject(prj) end, onRule = function(rule) vstudio.vs2010.generateRule(rule) end, onCleanWorkspace = function(wks) vstudio.cleanSolution(wks) end, onCleanProject = function(prj) vstudio.cleanProject(prj) end, onCleanTarget = function(prj) vstudio.cleanTarget(prj) end, pathVars = vstudio.vs2010.pathVars, vstudio = { solutionVersion = "12", versionName = "14", targetFramework = "4.5", toolsVersion = "14.0", filterToolsVersion = "4.0", } } local p = premake p.action = {} local action = p.action _ACTION = nil _ARGS = {} for i, arg in ipairs(_ARGV) do if not arg:startswith("/") and not arg:startswith("--") then if not _ACTION then _ACTION = arg else table.insert(_ARGS, arg) _ARGS[arg] = arg end end end action._list = {} function action.add(act) local missing for _, field in ipairs({"description", "trigger"}) do if not act[field] then missing = field end end if missing then local name = act.trigger or "" error(string.format('action "%s" needs a %s', name, missing), 3) end if act.os ~= nil then p.warnOnce(act.trigger, "action '" .. act.trigger .. "' sets 'os' field, which is deprecated, use 'targetos' instead.") act.targetos = act.os act.os = nil end action._list[act.trigger] = act end function action.initialize(name) local a = action._list[name] if (a.onInitialize) then a.onInitialize() end end function action.call(name) local a = action._list[name] if a.onStart then a.onStart() end for wks in p.global.eachWorkspace() do local onWorkspace = a.onWorkspace or a.onSolution or a.onsolution if onWorkspace and not wks.external then onWorkspace(wks) end for prj in p.workspace.eachproject(wks) do local onProject = a.onProject or a.onproject if onProject and not prj.external then onProject(prj) end end end for rule in p.global.eachRule() do local onRule = a.onRule or a.onrule if onRule and not rule.external then onRule(rule) end end if a.execute then a.execute() end if a.onEnd then a.onEnd() end end function action.current() return action.get(_ACTION) end function action.get(name) if name and name:endswith("ng") then name = name:sub(1, -3) end return action._list[name] end function action.each() local keys = { } for _, act in pairs(action._list) do table.insert(keys, act.trigger) end table.sort(keys) local i = 0 return function() i = i + 1 return action._list[keys[i]] end end function action.isConfigurable(self) if not self then self = action.current() or {} end if self.onWorkspace or self.onSolution or self.onsolution then return true end if self.onProject or self.onproject then return true end return false end function action.set(name) _ACTION = name local act = action.get(name) if act then _TARGET_OS = act.targetos or _TARGET_OS end if act and act.module then require(act.module) end end function action.supports(feature) if not feature then return true end local self = action.current() if not self then return false end if not self.valid_languages and not self.valid_kinds then return true end if self.valid_languages and table.contains(self.valid_languages, feature) then return true end if self.valid_kinds and table.contains(self.valid_kinds, feature) then return true end return false end function p.action.supportsconfig(action, cfg) if not action then return false end if action.supportsconfig then return action.supportsconfig(cfg) end return true end local p = premake local m = p.modules.xcode local tree = p.tree m.elements.workspace = function(wks) return { m.xmlDeclaration, m.workspace, m.reorderProjects, m.workspaceFileRefs, m.workspaceTail, } end function m.generateWorkspace(wks) m.prepareWorkspace(wks) p.callArray(m.elements.workspace, wks) end function m.workspace() p.push('') end function m.workspaceTail() p.out('') end function m.reorderProjects(wks) if wks.startproject then local np local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) if n.project.name == wks.startproject then np = n end end }) while np and np.parent do local p = np.parent local i = table.indexof(p.children, np) table.remove(p.children, i) table.insert(p.children, 1, np) np = p end end end m.elements.workspaceFileRef = function(prj) return { m.workspaceLocation, } end function m.workspaceFileRefs(wks) local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) local prj = n.project p.push('") p.pop('') end, onbranchenter = function(n) local prj = n.project p.push('', n.name) end, onbranchexit = function(n) p.pop('') end, }) end function m.workspaceLocation(prj) local fname = p.filename(prj, ".xcodeproj") fname = path.getrelative(prj.workspace.location, fname) p.w('location = "group:%s"', fname) end function m.xmlDeclaration() p.xmlUtf8(true) end local p = premake p.vstudio.vc200x = {} local m = p.vstudio.vc200x local vstudio = p.vstudio local context = p.context local project = p.project local config = p.config local fileconfig = p.fileconfig m.elements = {} m.elements.project = function(prj) return { m.xmlElement, m.visualStudioProject, m.platforms, m.toolFiles, m.configurations, m.references, m.files, m.globals } end function m.generate(prj) p.indent("\t") p.callArray(m.elements.project, prj) p.pop('') p.w() end m.elements.visualStudioProject = function(prj) return { m.projectType, m.version, m.projectName, m.projectGUID, m.rootNamespace, m.keyword, m.targetFrameworkVersion } end function m.visualStudioProject(prj) p.push('') end function m.configurations(prj) p.push('') local mapping = {} for cfg in project.eachconfig(prj) do local name = vstudio.projectConfig(cfg) mapping[cfg] = name mapping[name] = cfg end for cfg in project.eachconfig(prj) do for i, arch in ipairs(architectures) do local target local testName = vstudio.projectConfig(cfg, arch) if testName == mapping[cfg] then target = cfg elseif not mapping[testName] then target = { fake = true } end if target then m.configuration(target, testName) m.tools(target) p.pop('') end end end p.pop('') end m.elements.configuration = function(cfg) if cfg.fake then return { m.intermediateDirectory, m.configurationType } else return { m.outputDirectory, m.intermediateDirectory, m.configurationType, m.useOfMFC, m.characterSet, m.managedExtensions, } end end function m.configuration(cfg, name) p.push('') end m.elements.tools = function(cfg) if vstudio.isMakefile(cfg) and not cfg.fake then return { m.VCNMakeTool } end return { m.VCPreBuildEventTool, m.VCCustomBuildTool, m.VCXMLDataGeneratorTool, m.VCWebServiceProxyGeneratorTool, m.VCMIDLTool, m.VCCLCompilerTool, m.VCManagedResourceCompilerTool, m.VCResourceCompilerTool, m.VCPreLinkEventTool, m.VCLinkerTool, m.VCALinkTool, m.VCManifestTool, m.VCXDCMakeTool, m.VCBscMakeTool, m.VCFxCopTool, m.VCAppVerifierTool, m.VCPostBuildEventTool, } end function m.tools(cfg) p.callArray(m.elements.tools, cfg, config.toolset(cfg)) end m.elements.references = function(prj) return { m.assemblyReferences, m.projectReferences, } end function m.references(prj) p.push('') p.callArray(m.elements.references, prj) p.pop('') end function m.files(prj) local tr = m.filesSorted(prj) p.push('') p.tree.traverse(tr, { onbranchenter = m.filesFilterStart, onbranchexit = m.filesFilterEnd, onleaf = m.filesFile, }, false) p.pop('') end function m.filesSorted(prj) return project.getsourcetree(prj, function(a,b) local istop = (a.parent.parent == nil) local aSortName = a.name local bSortName = b.name if a.relpath then if not b.relpath then return not istop end aSortName = a.relpath:gsub("%.%.%/", "") end if b.relpath then if not a.relpath then return istop end bSortName = b.relpath:gsub("%.%.%/", "") end return aSortName < bSortName end) end function m.filesFilterStart(node) p.push('') end function m.filesFilterEnd(node) p.pop('') end function m.filesFile(node) p.push('') local prj = node.project for cfg in project.eachconfig(prj) do m.fileConfiguration(cfg, node) end p.pop('') end m.elements.fileConfigurationAttributes = function(filecfg) return { m.excludedFromBuild, } end function m.fileConfiguration(cfg, node) local filecfg = fileconfig.getconfig(node, cfg) local configAttribs = p.capture(function () p.push() p.callArray(m.elements.fileConfigurationAttributes, filecfg) p.pop() end) local compilerAttribs = p.capture(function () p.push() m.VCCLCompilerTool(filecfg) p.pop() end) if #configAttribs > 0 or compilerAttribs:lines() > 3 then p.push(' 0 then p.outln(configAttribs) end p.w('>') p.outln(compilerAttribs) p.pop('') end end m.elements.globals = function(prj) return {} end function m.globals(prj) p.push('') p.callArray(m.elements.globals, prj) p.pop('') end function m.VCTool(name, cfg, ...) p.push('') end m.elements.DebuggerTool = function(cfg) return {} end function m.DebuggerTool(cfg) p.push('') end m.elements.VCALinkTool = function(cfg) return {} end function m.VCALinkTool(cfg) m.VCTool("VCALinkTool", cfg) end m.elements.VCAppVerifierTool = function(cfg) return {} end function m.VCAppVerifierTool(cfg) if cfg.kind ~= p.STATICLIB then m.VCTool("VCAppVerifierTool", cfg) end end m.elements.VCBscMakeTool = function(cfg) return {} end function m.VCBscMakeTool(cfg) m.VCTool("VCBscMakeTool", cfg) end m.elements.VCCLCompilerTool = function(cfg, toolset) if not toolset then return { m.customBuildTool, m.objectFile, m.additionalCompilerOptions, m.optimization, m.additionalIncludeDirectories, m.wholeProgramOptimization, m.preprocessorDefinitions, m.undefinePreprocessorDefinitions, m.minimalRebuild, m.basicRuntimeChecks, m.bufferSecurityCheck, m.stringPooling, m.exceptionHandling, m.runtimeLibrary, m.enableFunctionLevelLinking, m.enableEnhancedInstructionSet, m.floatingPointModel, m.runtimeTypeInfo, m.treatWChar_tAsBuiltInType, m.usePrecompiledHeader, m.programDataBaseFileName, m.warningLevel, m.warnAsError, m.detect64BitPortabilityProblems, m.debugInformationFormat, m.compileAs, m.disableSpecificWarnings, m.forcedIncludeFiles, m.omitDefaultLib, } else return { m.additionalExternalCompilerOptions, m.additionalIncludeDirectories, m.preprocessorDefinitions, m.undefinePreprocessorDefinitions, m.usePrecompiledHeader, m.programDataBaseFileName, m.debugInformationFormat, m.compileAs, m.forcedIncludeFiles, } end end function m.VCCLCompilerToolName(cfg) local prjcfg, filecfg = config.normalize(cfg) if filecfg and fileconfig.hasCustomBuildRule(filecfg) then return "VCCustomBuildTool" else return "VCCLCompilerTool" end end function m.VCCLCompilerTool(cfg, toolset) m.VCTool("VCCLCompilerTool", cfg, toolset) end m.elements.VCCustomBuildTool = function(cfg) return {} end function m.VCCustomBuildTool(cfg) m.VCTool("VCCustomBuildTool", cfg) end m.elements.VCFxCopTool = function(cfg) return {} end function m.VCFxCopTool(cfg) m.VCTool("VCFxCopTool", cfg) end m.elements.VCLinkerTool = function(cfg, toolset) if cfg.kind ~= p.STATICLIB then return { m.linkLibraryDependencies, m.ignoreImportLibrary, m.additionalLinkerOptions, m.additionalDependencies, m.outputFile, m.linkIncremental, m.additionalLibraryDirectories, m.moduleDefinitionFile, m.generateManifest, m.generateDebugInformation, m.programDatabaseFile, m.subSystem, m.largeAddressAware, m.optimizeReferences, m.enableCOMDATFolding, m.entryPointSymbol, m.importLibrary, m.targetMachine, } else return { m.additionalLinkerOptions, m.additionalDependencies, m.outputFile, m.additionalLibraryDirectories, } end end function m.VCLinkerToolName(cfg) if cfg.kind == p.STATICLIB then return "VCLibrarianTool" else return "VCLinkerTool" end end function m.VCLinkerTool(cfg, toolset) m.VCTool("VCLinkerTool", cfg, toolset) end m.elements.VCManagedResourceCompilerTool = function(cfg) return {} end function m.VCManagedResourceCompilerTool(cfg) m.VCTool("VCManagedResourceCompilerTool", cfg) end m.elements.VCManifestTool = function(cfg) return { m.additionalManifestFiles, } end function m.VCManifestTool(cfg) if cfg.kind ~= p.STATICLIB then m.VCTool("VCManifestTool", cfg) end end m.elements.VCMIDLTool = function(cfg) return { m.targetEnvironment } end function m.VCMIDLTool(cfg) m.VCTool("VCMIDLTool", cfg) end m.elements.VCNMakeTool = function(cfg) return { m.buildCommandLine, m.reBuildCommandLine, m.cleanCommandLine, m.output, m.preprocessorDefinitions, m.undefinePreprocessorDefinitions, m.includeSearchPath, m.forcedIncludes, m.assemblySearchPath, m.forcedUsingAssemblies, m.compileAsManaged, } end function m.VCNMakeTool(cfg) m.VCTool("VCNMakeTool", cfg) end m.elements.VCBuildTool = function(cfg, stage) return { m.commandLine, } end function m.VCBuildToolName(cfg, stage) return "VC" .. stage .. "EventTool" end function m.VCPreBuildEventTool(cfg) m.VCTool("VCBuildTool", cfg, "PreBuild") end function m.VCPreLinkEventTool(cfg) m.VCTool("VCBuildTool", cfg, "PreLink") end function m.VCPostBuildEventTool(cfg) m.VCTool("VCBuildTool", cfg, "PostBuild") end m.elements.VCResourceCompilerTool = function(cfg) return { m.additionalResourceOptions, m.resourcePreprocessorDefinitions, m.additionalResourceIncludeDirectories, m.culture, } end function m.VCResourceCompilerTool(cfg) m.VCTool("VCResourceCompilerTool", cfg) end m.elements.VCWebServiceProxyGeneratorTool = function(cfg) return {} end function m.VCWebServiceProxyGeneratorTool(cfg) m.VCTool("VCWebServiceProxyGeneratorTool", cfg) end m.elements.VCXDCMakeTool = function(cfg) return {} end function m.VCXDCMakeTool(cfg) m.VCTool("VCXDCMakeTool", cfg) end m.elements.VCXMLDataGeneratorTool = function(cfg) return {} end function m.VCXMLDataGeneratorTool(cfg) m.VCTool("VCXMLDataGeneratorTool", cfg) end function m.symbols(cfg) if not (cfg.symbols == p.ON) then return 0 elseif cfg.debugformat == "c7" then return 1 else if cfg.editandcontinue == p.OFF or config.isOptimizedBuild(cfg) or cfg.clr ~= p.OFF or cfg.architecture == p.X86_64 then return 3 else return 4 end end end function m.additionalCompilerOptions(cfg) local opts = cfg.buildoptions if cfg.flags.MultiProcessorCompile then table.insert(opts, "/MP") end if #opts > 0 then p.x('AdditionalOptions="%s"', table.concat(opts, " ")) end end function m.additionalDependencies(cfg, toolset) if #cfg.links == 0 then return end local ex = vstudio.needsExplicitLink(cfg) local links if not toolset then links = vstudio.getLinks(cfg, ex) for i, link in ipairs(links) do if link:find(" ", 1, true) then link = '"' .. link .. '"' end links[i] = path.translate(link) end else links = path.translate(toolset.getlinks(cfg, not ex)) end if #links > 0 then p.x('AdditionalDependencies="%s"', table.concat(links, " ")) end end function m.additionalExternalCompilerOptions(cfg, toolset) local buildoptions = table.join(toolset.getcxxflags(cfg), cfg.buildoptions) if not cfg.flags.NoPCH and cfg.pchheader then table.insert(buildoptions, '--use_pch="$(IntDir)/$(TargetName).pch"') end if #buildoptions > 0 then p.x('AdditionalOptions="%s"', table.concat(buildoptions, " ")) end end function m.additionalImageOptions(cfg) if #cfg.imageoptions > 0 then p.x('AdditionalOptions="%s"', table.concat(cfg.imageoptions, " ")) end end function m.additionalIncludeDirectories(cfg) if #cfg.includedirs > 0 then local dirs = vstudio.path(cfg, cfg.includedirs) p.x('AdditionalIncludeDirectories="%s"', table.concat(dirs, ";")) end end function m.additionalLibraryDirectories(cfg) if #cfg.libdirs > 0 then local dirs = vstudio.path(cfg, cfg.libdirs) p.x('AdditionalLibraryDirectories="%s"', table.concat(dirs, ";")) end end function m.additionalLinkerOptions(cfg, toolset) local flags if toolset then flags = table.join(toolset.getldflags(cfg), cfg.linkoptions) else flags = cfg.linkoptions end if #flags > 0 then p.x('AdditionalOptions="%s"', table.concat(flags, " ")) end end function m.additionalManifestFiles(cfg) local manifests = {} for i, fname in ipairs(cfg.files) do if path.getextension(fname) == ".manifest" then table.insert(manifests, project.getrelative(cfg.project, fname)) end end if #manifests > 0 then p.x('AdditionalManifestFiles="%s"', table.concat(manifests, ";")) end end function m.additionalResourceIncludeDirectories(cfg) local dirs = table.join(cfg.includedirs, cfg.resincludedirs) if #dirs > 0 then dirs = vstudio.path(cfg, dirs) p.x('AdditionalIncludeDirectories="%s"', table.concat(dirs, ";")) end end function m.additionalResourceOptions(cfg) if #cfg.resoptions > 0 then p.x('AdditionalOptions="%s"', table.concat(cfg.resoptions, " ")) end end function m.assemblyReferences(prj) local cfg = project.getfirstconfig(prj) local refs = config.getlinks(cfg, "system", "fullpath", "managed") table.foreachi(refs, function(value) p.push('') end) end function m.assemblySearchPath(cfg) p.w('AssemblySearchPath=""') end function m.basicRuntimeChecks(cfg) local cfg, filecfg = config.normalize(cfg) if not filecfg and not config.isOptimizedBuild(cfg) and cfg.clr == p.OFF and not cfg.flags.NoRuntimeChecks then p.w('BasicRuntimeChecks="3"') end end function m.bufferSecurityCheck(cfg) if cfg.flags.NoBufferSecurityCheck then p.w('BufferSecurityCheck="false"') end end function m.buildCommandLine(cfg) local cmds = os.translateCommandsAndPaths(cfg.buildcommands, cfg.project.basedir, cfg.project.location) p.x('BuildCommandLine="%s"', table.concat(cmds, "\r\n")) end function m.characterSet(cfg) if not vstudio.isMakefile(cfg) then p.w('CharacterSet="%s"', iif(cfg.characterset == p.MBCS, 2, 1)) end end function m.cleanCommandLine(cfg) local cmds = os.translateCommandsAndPaths(cfg.cleancommands, cfg.project.basedir, cfg.project.location) cmds = table.concat(cmds, "\r\n") p.x('CleanCommandLine="%s"', cmds) end function m.commandLine(cfg, stage) local field = stage:lower() local steps = cfg[field .. "commands"] local msg = cfg[field .. "message"] if #steps > 0 then if msg then p.x('Description="%s"', msg) end steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) p.x('CommandLine="%s"', table.implode(steps, "", "", "\r\n")) end end function m.compileAs(cfg, toolset) local cfg, filecfg = config.normalize(cfg) local c = p.languages.isc(cfg.language) if filecfg then if path.iscfile(filecfg.name) ~= c then if path.iscppfile(filecfg.name) then local value = iif(c, 2, 1) p.w('CompileAs="%s"', value) end end else local compileAs if toolset then compileAs = "0" elseif c then compileAs = "1" end if compileAs then p.w('CompileAs="%s"', compileAs) end end end function m.disableSpecificWarnings(cfg) if #cfg.disablewarnings > 0 then p.x('DisableSpecificWarnings="%s"', table.concat(cfg.disablewarnings, ";")) end end function m.compileAsManaged(cfg) p.w('CompileAsManaged=""') end function m.configurationType(cfg) local cfgtypes = { Makefile = 0, None = 0, SharedLib = 2, StaticLib = 4, } p.w('ConfigurationType="%s"', cfgtypes[cfg.kind] or 1) end function m.culture(cfg) local value = vstudio.cultureForLocale(cfg.locale) if value then p.w('Culture="%d"', value) end end function m.customBuildTool(cfg) local cfg, filecfg = config.normalize(cfg) if filecfg and fileconfig.hasCustomBuildRule(filecfg) then local cmds = os.translateCommandsAndPaths(filecfg.buildcommands, filecfg.project.basedir, filecfg.project.location) p.x('CommandLine="%s"', table.concat(cmds,'\r\n')) local outputs = project.getrelative(filecfg.project, filecfg.buildoutputs) p.x('Outputs="%s"', table.concat(outputs, ';')) if filecfg.buildinputs and #filecfg.buildinputs > 0 then local inputs = project.getrelative(filecfg.project, filecfg.buildinputs) p.x('AdditionalDependencies="%s"', table.concat(inputs, ';')) end end end function m.debugInformationFormat(cfg, toolset) local prjcfg, filecfg = config.normalize(cfg) if not filecfg then local fmt = iif(toolset, "0", m.symbols(cfg)) p.w('DebugInformationFormat="%s"', fmt) end end function m.detect64BitPortabilityProblems(cfg) local prjcfg, filecfg = config.normalize(cfg) if _ACTION < "vs2008" and cfg.clr == p.OFF and cfg.warnings ~= p.OFF and not filecfg then p.w('Detect64BitPortabilityProblems="%s"', tostring(not cfg.flags.No64BitChecks)) end end function m.enableCOMDATFolding(cfg, toolset) if config.isOptimizedBuild(cfg) and not toolset then p.w('EnableCOMDATFolding="2"') end end function m.largeAddressAware(cfg) if (cfg.largeaddressaware == true) then p.w('LargeAddressAware="2"') end end function m.enableEnhancedInstructionSet(cfg) local map = { SSE = "1", SSE2 = "2" } local value = map[cfg.vectorextensions] if value and cfg.architecture ~= "x86_64" then p.w('EnableEnhancedInstructionSet="%d"', value) end end function m.enableFunctionLevelLinking(cfg) local cfg, filecfg = config.normalize(cfg) if not filecfg then p.w('EnableFunctionLevelLinking="true"') end end function m.entryPointSymbol(cfg, toolset) if cfg.entrypoint then p.w('EntryPointSymbol="%s"', cfg.entrypoint) end end function m.exceptionHandling(cfg) if cfg.exceptionhandling == p.OFF then p.w('ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0)) elseif cfg.exceptionhandling == "SEH" and _ACTION > "vs2003" then p.w('ExceptionHandling="2"') end end function m.excludedFromBuild(filecfg) if not filecfg or filecfg.flags.ExcludeFromBuild then p.w('ExcludedFromBuild="true"') end end function m.floatingPointModel(cfg) local map = { Strict = "1", Fast = "2" } local value = map[cfg.floatingpoint] if value then p.w('FloatingPointModel="%d"', value) end end function m.forcedIncludeFiles(cfg) if #cfg.forceincludes > 0 then local includes = vstudio.path(cfg, cfg.forceincludes) p.w('ForcedIncludeFiles="%s"', table.concat(includes, ';')) end if #cfg.forceusings > 0 then local usings = vstudio.path(cfg, cfg.forceusings) p.w('ForcedUsingFiles="%s"', table.concat(usings, ';')) end end function m.forcedIncludes(cfg) p.w('ForcedIncludes=""') end function m.forcedUsingAssemblies(cfg) p.w('ForcedUsingAssemblies=""') end function m.keyword(prj) local windows, managed, makefile for cfg in project.eachconfig(prj) do if cfg.system == p.WINDOWS then windows = true end if cfg.clr ~= p.OFF then managed = true end if vstudio.isMakefile(cfg) then makefile = true end end if windows then local keyword = "Win32Proj" if managed then keyword = "ManagedCProj" end if makefile then keyword = "MakeFileProj" end p.w('Keyword="%s"', keyword) end end function m.generateDebugInformation(cfg, toolset) if not toolset then p.w('GenerateDebugInformation="%s"', tostring(m.symbols(cfg) ~= 0)) end end function m.generateManifest(cfg, toolset) if cfg.flags.NoManifest or toolset then p.w('GenerateManifest="false"') end end function m.ignoreImportLibrary(cfg, toolset) if cfg.flags.NoImportLib and not toolset then p.w('IgnoreImportLibrary="true"') end end function m.importLibrary(cfg, toolset) if cfg.kind == p.SHAREDLIB and not toolset then local implibdir = cfg.linktarget.abspath if cfg.flags.NoImportLib then implibdir = path.join(cfg.objdir, path.getname(implibdir)) end implibdir = vstudio.path(cfg, implibdir) p.x('ImportLibrary="%s"', implibdir) end end function m.includeSearchPath(cfg) p.w('IncludeSearchPath=""') end function m.intermediateDirectory(cfg) local objdir if not cfg.fake then objdir = vstudio.path(cfg, cfg.objdir) else objdir = "$(PlatformName)\\$(ConfigurationName)" end p.x('IntermediateDirectory="%s"', objdir) end function m.linkIncremental(cfg, toolset) local value if not toolset then value = iif(config.canLinkIncremental(cfg) , 2, 1) else value = 0 end p.w('LinkIncremental="%s"', value) end function m.linkLibraryDependencies(cfg, toolset) if vstudio.needsExplicitLink(cfg) and not toolset then p.w('LinkLibraryDependencies="false"') end end function m.managedExtensions(cfg) if cfg.clr ~= p.OFF then p.w('ManagedExtensions="1"') end end function m.minimalRebuild(cfg) if config.isDebugBuild(cfg) and cfg.debugformat ~= "c7" and not cfg.flags.NoMinimalRebuild and cfg.clr == p.OFF and not cfg.flags.MultiProcessorCompile then p.w('MinimalRebuild="true"') end end function m.moduleDefinitionFile(cfg, toolset) if not toolset then local deffile = config.findfile(cfg, ".def") if deffile then p.w('ModuleDefinitionFile="%s"', deffile) end end end function m.objectFile(cfg) local cfg, filecfg = config.normalize(cfg) if filecfg and path.iscppfile(filecfg.name) then if filecfg.objname ~= path.getbasename(filecfg.abspath) then p.x('ObjectFile="$(IntDir)\\%s.obj"', filecfg.objname) end end end function m.omitDefaultLib(cfg) if cfg.flags.OmitDefaultLibrary then p.w('OmitDefaultLibName="true"') end end function m.omitFramePointers(cfg) if cfg.omitframepointer == "On" then p.w('OmitFramePointers="true"') end end function m.optimization(cfg) local map = { Off=0, On=3, Debug=0, Full=3, Size=1, Speed=2 } local value = map[cfg.optimize] if value or not cfg.abspath then p.w('Optimization="%s"', value or 0) end end function m.optimizeReferences(cfg, toolset) if config.isOptimizedBuild(cfg) and not toolset then p.w('OptimizeReferences="2"') end end function m.output(cfg) p.w('Output="$(OutDir)%s"', cfg.buildtarget.name) end function m.outputDirectory(cfg) local outdir = project.getrelative(cfg.project, cfg.buildtarget.directory) p.x('OutputDirectory="%s"', path.translate(outdir)) end function m.outputFile(cfg) p.x('OutputFile="$(OutDir)\\%s"', cfg.buildtarget.name) end function m.outputFileName(cfg) if cfg.imagepath ~= nil then p.x('OutputFileName="%s"', path.translate(cfg.imagepath)) end end function m.platforms(prj) architectures = {} for cfg in project.eachconfig(prj) do local arch = vstudio.archFromConfig(cfg, true) if not table.contains(architectures, arch) then table.insert(architectures, arch) end end p.push('') table.foreachi(architectures, function(arch) p.push('') end) p.pop('') end function m.preprocessorDefinitions(cfg) if #cfg.defines > 0 or vstudio.isMakefile(cfg) then p.x('PreprocessorDefinitions="%s"', table.concat(cfg.defines, ";")) end end function m.undefinePreprocessorDefinitions(cfg) if #cfg.undefines > 0 then p.x('UndefinePreprocessorDefinitions="%s"', table.concat(cfg.undefines, ";")) end end function m.programDatabaseFile(cfg, toolset) if toolset then p.w('ProgramDatabaseFile=""') end end function m.programDataBaseFileName(cfg, toolset) if toolset then p.w('ProgramDataBaseFileName=""') end end function m.projectGUID(prj) p.w('ProjectGUID="{%s}"', prj.uuid) end function m.projectName(prj) p.x('Name="%s"', prj.name) end function m.projectReferences(prj) local deps = project.getdependencies(prj) if #deps > 0 then for i, dep in ipairs(deps) do local relpath = vstudio.path(prj.workspace, vstudio.projectfile(dep)) if not relpath:startswith(".") then relpath = ".\\" .. relpath end p.push('') end end end function m.projectType(prj) p.w('ProjectType="Visual C++"') end function m.reBuildCommandLine(cfg) commands = table.concat(cfg.rebuildcommands, "\r\n") p.x('ReBuildCommandLine="%s"', commands) end function m.resourcePreprocessorDefinitions(cfg) local defs = table.join(cfg.defines, cfg.resdefines) if #defs > 0 then p.x('PreprocessorDefinitions="%s"', table.concat(defs, ";")) end end function m.rootNamespace(prj) local hasWindows = project.hasConfig(prj, function(cfg) return cfg.system == p.WINDOWS end) if hasWindows and _ACTION > "vs2003" then p.x('RootNamespace="%s"', prj.name) end end function m.runtimeLibrary(cfg) local cfg, filecfg = config.normalize(cfg) if not filecfg then local runtimes = { StaticRelease = 0, StaticDebug = 1, SharedRelease = 2, SharedDebug = 3, } local runtime = config.getruntime(cfg) if runtime then p.w('RuntimeLibrary="%s"', runtimes[runtime]) else p.w('RuntimeLibrary="%s"', iif(config.isDebugBuild(cfg), 3, 2)) end end end function m.runtimeTypeInfo(cfg) if cfg.rtti == p.OFF and cfg.clr == p.OFF then p.w('RuntimeTypeInfo="false"') elseif cfg.rtti == p.ON then p.w('RuntimeTypeInfo="true"') end end function m.stringPooling(cfg) if config.isOptimizedBuild(cfg) then p.w('StringPooling="true"') end end function m.subSystem(cfg, toolset) if not toolset then p.w('SubSystem="%s"', iif(cfg.kind == "ConsoleApp", 1, 2)) end end function m.targetEnvironment(cfg) if cfg.architecture == "x86_64" then p.w('TargetEnvironment="3"') end end function m.targetFrameworkVersion(prj) local windows, makefile for cfg in project.eachconfig(prj) do if cfg.system == p.WINDOWS then windows = true end if vstudio.isMakefile(cfg) then makefile = true end end local version = 0 if makefile or not windows then version = 196613 end p.w('TargetFrameworkVersion="%d"', version) end function m.targetMachine(cfg, toolset) if not toolset then p.w('TargetMachine="%d"', iif(cfg.architecture == "x86_64", 17, 1)) end end function m.toolFiles(prj) if _ACTION > "vs2003" then p.w('') p.w('') end end function m.treatWChar_tAsBuiltInType(cfg) local map = { On = "true", Off = "false" } local value = map[cfg.nativewchar] if value then p.w('TreatWChar_tAsBuiltInType="%s"', value) end end function m.useOfMFC(cfg) if (cfg.flags.MFC) then p.w('UseOfMFC="%d"', iif(cfg.staticruntime == "On", 1, 2)) end end function m.usePrecompiledHeader(cfg) local prj, file = config.normalize(cfg) if file then if prj.pchsource == file.abspath and not prj.flags.NoPCH and prj.system == p.WINDOWS then p.w('UsePrecompiledHeader="1"') elseif file.flags.NoPCH then p.w('UsePrecompiledHeader="0"') end else if not prj.flags.NoPCH and prj.pchheader then p.w('UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2)) p.x('PrecompiledHeaderThrough="%s"', prj.pchheader) else p.w('UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or prj.flags.NoPCH, 0, 2)) end end end function m.version(prj) local map = { vs2002 = '7.0', vs2003 = '7.1', vs2005 = '8.0', vs2008 = '9.0' } p.w('Version="%s0"', map[_ACTION]) end function m.warnAsError(cfg) if cfg.flags.FatalCompileWarnings and cfg.warnings ~= p.OFF then p.w('WarnAsError="true"') end end function m.warningLevel(cfg) local prjcfg, filecfg = config.normalize(cfg) local level if cfg.warnings == p.OFF then level = "0" elseif cfg.warnings == "Extra" then level = "4" elseif not filecfg then level = "3" end if level then p.w('WarningLevel="%s"', level) end end function m.wholeProgramOptimization(cfg) if cfg.flags.LinkTimeOptimization then p.x('WholeProgramOptimization="true"') end end function m.xmlElement() p.w('') end p@:SpA:SP B:S`B:SA:S`BI0BIXB:SmB:S0AIpB4>S<>SIH>SP>SX>S`>Sh>Sp>Sx>S>S>S>S>S>S>S>S>S>S>S>S>S>S>Sp?St?S|?S?S?S?SI?S>S?S?S?S9SI?S?S?S?S?SxI?S?S?SI=S?S?S?S?S?S?S?S`I?S@S@S@SBSABS0ABSABSAIоABS@ABS`A,DS@A4DSADDSALDSATDSAdDSAlDSAxDSADS`ADS ADSpAIADSADSADSADS@ADSADS@ADS0ALI0ADSADS@A:SDSGSAGS BGSFSxI@GSGS$JSB,JSB4JSB@JSB,IBHJS`BI0BIBPJSBJSPB\JSBNSP"BES@$BNS`%BOS3BOS@BOS`4BOS8BES0B OSBI3B(OS B,OS B4OSB8OSpBBSKB@OSRBBSTBOSZBOS`]BOS\BOS]BOS`BOS\BOSgBOS gBOS^BOS_BOSaBOS@eBOSfBOS0iBHSphBPScBPShB PSiBPSkB PS[B$PSdB,PS\BDS@lB0PS4PS?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~# #%%%%$%a%b%V%U%c%Q%W%]%\%[%%%4%,%%%<%^%_%Z%T%i%f%`%P%l%g%h%d%e%Y%X%R%S%k%j%% %%%%%%")"a"e"d" #!#H""" %0w,aQ mjp5c飕d2yҗ+L |~-d jHqA}mQDžӃVlkdzbeO\lcc=  n;^iLA`rqgjm Zjz  ' }Dңhi]Wbgeq6lknv+ӉZzJgo߹ホCՎ`~ѡ8ROggW?K6H+ L J6`zA`Ugn1yiFafo%6hRw G "/&U;( Z+j\1е,[d&c윣ju m ?6grWJz+{8 Ғ |! ӆBhn[&wowGZpj;f\ eibkaElx TN³9a&g`MGiIwn>JjѮZf @;7SŞϲG0򽽊º0S$6к)WTg#.zfJah]+o*7 Z-A1b62S-+ldEw}ZVǖAOIъ OM~-QJ#SpxAaU׮.7׵Y-6]]wll?AԞZ͢$ Faw$eڪ]]FD(koipvk19Z* ,  m86F߲]qTp0ek*1u4yީ%8S1bSWĔՖk1**ykʬHpo].*F6fcTT"eM©g0&):{ϼkZ> 8$,52F*sw1pHkQ6Fzw]cN̵J #pAF]#l8?1(BOgT~yUbL8^#ܖTZ1ObbSyOIV~P-{b-R4٠~^eGnHl/Su6: #jT$+e?yHf'*b#ٽЧ ?&~?$pi;FBzw[keZ~7 Sv8H 3?r$7jnԄYFܨ |OQ;օ U d S - =G\ p&Gw)` /a߫i5&LsZ<#0zMzFM8,9; :R:(q-v,.7/pXqYs3r%w+OQvrtEux܉~OK }!b|tyBxʠz{.lD~m8onlk[wjR1h58ib?mcf+aQ`צedd"fig HINSKyuJcO NZLݘMFGN@E$DD2AsX@*IBCPhTg3U>uW ַVS:R|P~Q9ZS [fYX4])\ZEo^m/_5qϱ٥s\ۼqދ!K7 kfֶԁ-b3Πjp]$^'~*I@VW<âM˟ŏ{ tDCm-@wm.B+(铜>Td"ŀǼϭ~8y$owJ1}05_K^ iϏ은BI#ƈdX܁T̓cQ: rՆ⩗ fn|xK)o%ƭ/3vUuA?)C:|sĵ@͂ Ͳ;bIUeh"׻_HS1޼^Z4eg Wb27_k%8ם(ŊO}do׸Jj3wVcXWP0qB{߭gCru&op-?'Bs ưGz>2[Ȏg; i8P/ _Y=чe:ZO?(3wwXR @hQ+ğH*0"ZOWoI}@mNП5+#*'G| AH=XX?#1jvʬ`p^Y<L~i/{kHwâ hs)aLoD~Pf7VM'(@ﰤ ہg9x+n&;f?/X)T`D1 ߨMߒ.FgTp'Hq/L0UEc?kǃh6ry7]P\@TN%s7@'>$!AxUʰ\3;Y^U~PGl!;b F2ȂpԞ(Q_V:1X: n3 m:@/)IJNv"2x+ٗ Kx.HҥfAj^y9*O]#kM`~b_R 7zFh!1߈Vc0a"j6nS Nr)Υ{t*F8#vufz`rs"WG9^EMvc΍&DAdQy/4Aڱ&S֚E biLQ<6'5P..T&q]w4.6IE? v\[YI>U!lDa>Ԫ΋ϩ7~8A]&nv|oY yKiw\¹9~$ 66nQfq>,o,IӔ 渱{I .H>C-Yn馑gQz tafw0a, Qmpjc5dۈ2yܸو L+~|-dj qHA}mԵQӅlVdkbze\Ocl=c ;n Li^`Agqr<KG k5Blۻ֬@2lE\u ϫ=Y&0Q:Qa!V#Ϻ(_ ٲ $/o|XhLaf-=vAq *q3xɢ4 j m=-dlc\kkQlabe0bNl{WeP|b-I|LeMaX:QΣtԻ0JߥA=ؕפmCij4ngF`D-s3 L_ |Pq<'A  Wh% of a^)ɘИ"רY=. \;l  tҚG9w&sc d; mj>zjZ '}DhibW]egl6qnkv+zZgJoC`֣ѓ~8ORѻgWg?H6K +گ L6JAz``ègU1nFiyaf%oҠRh6 w G"U&/ź; (+Z\j1,ٞ[ޮd°c&ujm 6?rgWJz{+ 8Ҏվ | !Bhݳڃn&[owGwZjpf; \ebiaklE x NT9§g&a`IiGM>nwۮjJZ@ f7;𩼮S޻G0齽ʺŠS0$6TW)#gfz.aJ]h*o+ 7 Z-1A26b+-Sdl}wEVZOAي»IˬO ~M-JQS#xpaA.U7Y-۩6˚w]]llA?Z$㧲F waރ$Ųe]]DFok(vpi91k *Z  ,8mF6]pTqke0*1¶u4%y<8syjHA}X*ݹ1SbSW§ٖծ1k**kypH]oF*.f6TTcMe"¤0g)&Ůޟ:{kZ >8,$5*F21wsHpQkzF6c]wN̵ׄJ# pȄA#]F8l1?(gOB~TUyLbˁ8#^TO1ZbbySIOP~V{-b-4R^~Ge­lHnuS/:6# $Tj?e+y䏼Hf*'˼Ѝb# &??~p$iBF;[wzek~ZS 7H8v ?3$rj7nFY |OQ; U dؓS - \G=&pGw`)/ ai5&sL <:R=Pe6^X7}o5641W0ճ2k3$k%'1&-[#bML"'{ "!$*x(+)`F(> q-q,v.Ț/7pqXsYr3w%vQO+tru՛E~xKO} |b!ytxBz{l.m~Do8nkljw[h1Ri85bcm?a+f`Qeddf"giH IKSNJuyOcN LZMݥFĚGE@ND$A2D@XsBI*CThPU3gWu>V SR:P|Q~Z9[ SYfX]4\)^oEZ_/m5qs<\kg2z &J8 좞V`a/6i\lU,zB\uHƒ=&FW A+Ox]`غ7W>9q߳!7Kk ֩fض-bѠ3pj$]^Ĝ'*~@IWVÕ<ӂMʏş{ Dt͆mC-@mw+B.(>dT"ş~Ϝ8yo$w1J}50K_ ^ϋiBۉI#dXфTQc:r Р fΫnx|)Ko%3/uUv?A)ġ:C|sд@͉ ;IbeU"hH_S1ފZ^ھ4ge ȋbW72%k_ܝ8Ŵ(}OodJֿjw3XcVPW0Bq{gǧurCo&p-?О'sB zGɠ2>[ ;g/P8i_ Y=嗇e:ϏOZw3(?RXw@ Qh+HZ"0*WOIo@}m5N#+'*GA |􏒨HX=#?X1vjʨ`^pYL'!$UxAׯ3\Y;U^GP~b;!lڇF 2p(ԐQV_:X1: 3n :m@I)/NJ2"v+x xKH.jAf^O*9y]#Mk~`bю_޶ Rz7hFм!10cV"ajحn6 SrN){t*8Fv#fu`zrϮsɛW"G9E^vMcD&dA/yQA4S&ֿ EbLil!>aDƋΪ~7A8n&]|vYoᡱ Kyi׫w¡\~9$66 Qnf>q,o,ӹI 散 I{.C>HnY-Qg̰t zfa`Psp0  ` @ X ;x8 h( H T+t4  d$ D \ S|< l,  L R#r2  b" B Z Cz: j*  J V@3v6 f& F  ^ c~> n. N `Qq1  a! A Y ;y9 i)  I U+u5  e% E ] S}= m-  M S#s3  c# C [ C{; k+  K W@3w7 g' G  _ c? o/ O `Psp0  ` @ X ;x8 h( H T+t4  d$ D \ S|< l,  L R#r2  b" B Z Cz: j*  J V@3v6 f& F  ^ c~> n. N `Qq1  a! A Y ;y9 i)  I U+u5  e% E ] S}= m-  M S#s3  c# C [ C{; k+  K W@3w7 g' G  _ c? o/ O A@!  @a`10  @ CCC CC CC C C C@@ !1Aa  0@`         0@`  0@`  (08@P`p L,l\<|B"bR2r J*jZ:zF&fV6vN.n^>~A!aQ1q I)iY9yE%eU5u M-m]=}   S S  3 3  s s    K K  + +  k k     [ [  ; ;  { {     G G  ' '  g g     W W  7 7  w w     O O  / /  o o     _ _  ? ?     @ `P0pH(hX8xD$dT4tC#cFE* < > { } { } |S0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzSjEEEpEEPSjEEEpEE@EEGMTUTCWETBSTWAT<ASTADTEST,EDTCSThCDT,MSTMDThPSTPDTYSTYDTHSTXHDTCATXAHSTXNTIDLWCETMETMEWTMESTCESTMESZFWTFSTEETWAST\WADT CCT JSTEASTEADTlGSTNZT0NZST0NZDTIDLE0A<BxCDE,FhGHIKXLMNOPLQRST\U VWXlY0ZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_PSdShS|SSSSSSSSSS,S%s] Writing data to %s failed %d bytes were written %d bytes were attempted to be written File may be corrupt src/base/_foundation.luasrc/base/string.luasrc/base/table.luasrc/base/path.luasrc/base/os.luasrc/base/io.luasrc/base/tools.luasrc/base/tree.luasrc/base/globals.luasrc/base/moduledownloader.luasrc/base/semver.luasrc/base/http.luasrc/base/json.luasrc/base/jsonwrapper.luasrc/base/languages.luasrc/base/term.luasrc/base/field.luasrc/base/criteria.luasrc/base/detoken.luasrc/base/configset.luasrc/base/context.luasrc/base/container.luasrc/base/option.luasrc/base/action.luasrc/base/api.luasrc/base/global.luasrc/base/workspace.luasrc/base/group.luasrc/base/project.luasrc/base/config.luasrc/base/fileconfig.luasrc/base/rule.luasrc/base/oven.luasrc/base/validation.luasrc/base/premake.luasrc/base/help.luasrc/tools/dotnet.luasrc/tools/gcc.luasrc/tools/msc.luasrc/tools/snc.luasrc/tools/clang.luasrc/actions/clean/_clean.luasrc/_premake_init.luaandroid/_preload.luaandroid/android.luaandroid/vsandroid_vcxproj.luaandroid/vsandroid_sln2005.luaandroid/vsandroid_vstudio.luaandroid/vsandroid_androidproj.luacodelite/_preload.luacodelite/codelite.luacodelite/codelite_workspace.luacodelite/codelite_project.luad/_preload.luad/d.luad/actions/gmake.luad/actions/vcxproj.luad/actions/visuald.luad/tools/dmd.luad/tools/gdc.luad/tools/ldc.luagmake/_preload.luagmake/gmake.luagmake/gmake_cpp.luagmake/gmake_csharp.luagmake/gmake_makefile.luagmake/gmake_utility.luagmake/gmake_workspace.luagmake2/_preload.luagmake2/gmake2.luagmake2/gmake2_cpp.luagmake2/gmake2_csharp.luagmake2/gmake2_makefile.luagmake2/gmake2_utility.luagmake2/gmake2_workspace.luaraw/_preload.luaraw/raw.luaraw/raw_action.luaself-test/self-test.luaself-test/test_assertions.luaself-test/test_declare.luaself-test/test_helpers.luaself-test/test_runner.luavstudio/_preload.luavstudio/vstudio.luavstudio/vs2005.luavstudio/vs2008.luavstudio/vs200x_vcproj.luavstudio/vs200x_vcproj_user.luavstudio/vs2005_solution.luavstudio/vs2005_dotnetbase.luavstudio/vs2005_csproj.luavstudio/vs2005_csproj_user.luavstudio/vs2005_fsproj.luavstudio/vs2005_fsproj_user.luavstudio/vs2010.luavstudio/vs2010_nuget.luavstudio/vs2010_vcxproj.luavstudio/vs2010_vcxproj_user.luavstudio/vs2010_vcxproj_filters.luavstudio/vs2010_rules_props.luavstudio/vs2010_rules_targets.luavstudio/vs2010_rules_xml.luavstudio/vs2012.luavstudio/vs2013.luavstudio/vs2015.luavstudio/vs2017.luavstudio/vs2019.luaxcode/_preload.luaxcode/xcode.luaxcode/xcode4_workspace.luaxcode/xcode_common.luaxcode/xcode_project.luasrc/_manifest.luasrc/_modules.lua(*no name)(*vararg)(*temporary)=[C]C=?mainLuametamethodlocal_ENVglobalfieldupvalueconstanthookfor iterator (%s '%s')attempt to %s a %s value%sconcatenatenumber%s has no integer representationattempt to compare two %s valuesattempt to compare %s with %s%s:%d: %s_Gpackagecoroutinetableiomathutf8error in error handlingcallC stack overflowcannot resume non-suspended coroutinecannot resume dead coroutineattempt to yield across a C-call boundaryattempt to yield from outside a coroutineattempt to load a %s chunk (mode is '%s')binarytextindex'__index' chain too long; possible loop'__newindex' chain too long; possible loopstring length overflowget length ofattempt to divide by zeroattempt to perform 'n%%0''for' limit must be a number'for' step must be a number'for' initial value must be a numberno messageerror in __gc metamethod (%s)invalid key to 'next'table overflowtable index is niltable index is NaN.xXnN%lld%.14g-0123456789(null)<\%d>%p%invalid option '%%%c' to 'lua_pushfstring'...[string ""]not enough memory  no valuebooleannumberfunctionthreadproto__index__newindex__mode__len__eq__add__sub__mul__mod__pow__div__idiv__band__bor__bxor__shl__shr__unm__bnot__lt__le__concat__callperform bitwise operation onperform arithmetic ontoo many %s (limit is %d)memory allocation error: block too bigandbreakdoelseelseifendforgotoifinnotorrepeatreturnthenuntilwhile//==>=<=~=<<>>::lexical element too long'%c''%s'%s near %schunk has too many linesEexXPp-+malformed numbercommentunfinished long %s (starting at line %d)hexadecimal digit expectedmissing '{'UTF-8 value too largemissing '}'decimal escape too largeunfinished stringinvalid escape sequenceinvalid long string delimiterposition out of boundswrong number of arguments to 'insert'too many elements to movedestination wrap aroundinvalid value (%s) at index %d in table for 'concat'too many results to unpackinvalid order function for sortingarray too bigconcatinsertpackunpackmovesort'tostring' must return a string to 'print' base out of range__metatablenil or table expectedcannot change a protected metatabletable or string expectedstoprestartcollectcountstepsetpausesetstepmulisrunning__pairstoo many nested functionsreader function must return a stringbt=(load)assertion failed!index out of rangeassertcollectgarbagedofileerrorgetmetatableipairsloadfileloadnextpairspcallrawequalrawlenrawgetrawsetselectsetmetatabletonumbertypexpcall_VERSIONLua 5.3initial position out of stringfinal position out of stringout of rangestring slice too longinvalid UTF-8 codevalue out of range%Uposition out of rangeinitial position is a continuation byteoffsetcodepointcharlencodescharpattern[--][-]*unable to get ModuleFileName!system error %d _5_3%s%s;;;;init no file '%s''package.%s' must be a stringerror loading module '%s' from file '%s': %s_luaopen_%scpath no module '%s' in file '%s'_PRELOAD no field package.preload['%s']searchers'package.searchers' must be a tablemodule '%s' not found:%sloadlibsearchpathpreloadloaded!\lua\?.lua;!\lua\?\init.lua;!\?.lua;!\?\init.lua;!\..\share\lua\5.3\?.lua;!\..\share\lua\5.3\?\init.lua;.\?.lua;.\?\init.luaLUA_PATH!\?.dll;!\..\lib\lua\5.3\?.dll;!\loadall.dll;.\?.dllLUA_CPATH\ ; ? ! - configunable to generate a unique filenamesecminhourdaymonthyearwdayydayisdstfield '%s' is not an integerfield '%s' missing in date tablefield '%s' is out-of-boundaAbBcdHIjmMpSUwWxXyYzZ%||#c#x#d#H#I#j#m#M#S#U#w#W#y#Yinvalid conversion specifier '%%%s'%ctime result cannot be represented in this installation*tallcollatectypemonetarynumerictimeclockdatedifftimeexecutegetenvsetlocaletmpnameresulting string too largeunable to dump given functioninvalid capture index %%%dinvalid pattern capturemalformed pattern (ends with '%%')malformed pattern (missing ']')malformed pattern (missing arguments to '%%b')too many capturespattern too complexmissing '[' after '%%f' in patternunfinished capture^$*+?.([%-invalid use of '%c' in replacement stringinvalid replacement value (a %s)string/function/table expected%.14gx0p+0p%+dmodifiers for format '%%a'/'%%A' not implemented\%d\%03d%a0x%llxvalue has no literal form-+ #0invalid format (repeated flags)invalid format (width or precision too long)llstring contains zerosinvalid option '%%%c' to 'format'integral size (%d) out of limits [1,%d]missing size for format option 'c'invalid format option '%c'invalid next option for option 'X'format asks for alignment not power of 2integer overflowunsigned overflowstring longer than given sizestring length does not fit in given sizeformat result too largevariable-length format%d-byte integer does not fit into Lua Integerdata string too shorttoo many resultsbytedumpfindformatgmatchgsublowerrepreversesubupperpacksizezerowrong number of argumentsinterval is emptyinterval too largeintegerfloatabsacosasinatanceilcosdegexptointegerfloorfmodultlogmaxmodfradrandomrandomseedsinsqrttanpihugemaxintegerminintegerrwabFILE*closed filefilefile (closed)file (%p)attempt to use a closed file_IO_outputcannot open file '%s' (%s)invalid modestandard %s file is closed_IO_inputwtoo many arguments00pPeEinvalid formatfile is already closed%ssetcurnofulllineflushinputlinesoutputpopentmpfileseeksetvbufcannot close standard filestdinstdoutstderrflnStu>%sinvalid optionsourceshort_srclinedefinedlastlinedefinedwhatcurrentlinenupsnparamsisvarargnamenamewhatistailcallactivelinesfunclevel out of rangeinvalid upvalue indexLua function expectedtail callkexternal hooklua_debug> cont =(debug command)getuservaluegethookgetinfogetlocalgetregistrygetupvalueupvaluejoinupvalueidsetuservaluesethooksetlocalsetupvaluetracebackthread expectedtoo many arguments to resumetoo many results to resumerunningsuspendednormaldeadcreateresumestatuswrapyieldisyieldable%s: %s precompiled chunktruncated%s size mismatch innot aversion mismatch informat mismatch incorruptedintsize_tInstructionlua_Integerlua_Numberendianness mismatch infloat format mismatch inbinary string%s expectedmain functionfunction at line %dtoo many %s (limit is %d) in %s%s expected (to close %s at line %d)local variablesupvaluesC levels at line %d jumps into the scope of local '%s'labels/gotos<%s> at line %d not inside a loopno visible label '%s' for at line %dfunctions or '...' expectedselffunction arguments expectedunexpected symbolcannot use '...' outside a vararg functionsyntax errorlabel '%s' already defined on line %d(for index)(for limit)(for step)(for generator)(for state)(for control)'=' or 'in' expectedcontrol structure too longopcodesfunction or expression needs too many registersconstantsconstructor too longTORRENTZIPPED-XXXXXXXX%08lX%s/.zip.XXXXXX%s.XXXXXXr+bPKPKTORRENTZIPPED-PKPKPKNo errorWrite errorincorrect header checkunknown compression methodinvalid window sizeunknown header flags setheader crc mismatchinvalid block typeinvalid stored block lengthstoo many length or distance symbolsinvalid code lengths setinvalid bit length repeatinvalid code -- missing end-of-blockinvalid literal/lengths setinvalid distances setinvalid literal/length codeinvalid distance codeinvalid distance too far backincorrect data checkincorrect length checkneed dictionarystream endfile errorstream errordata errorinsufficient memorybuffer errorincompatible versioneasy handle already used in multi handleUnsupported protocolFailed initializationURL using bad/illegal format or missing URLA requested feature, protocol or option was not found built-in in this libcurl due to a build-time decision.Couldn't resolve proxy nameCouldn't resolve host nameCouldn't connect to serverWeird server replyAccess denied to remote resourceFTP: The server failed to connect to data portFTP: Accepting server connect has timed outFTP: The server did not accept the PRET command.FTP: unknown PASS replyFTP: unknown PASV replyFTP: unknown 227 response formatFTP: can't figure out the host in the PASV responseError in the HTTP2 framing layerFTP: couldn't set file typeTransferred a partial fileFTP: couldn't retrieve (RETR failed) the specified fileQuote command returned errorHTTP response code said errorFailed writing received data to disk/applicationUpload failed (at start/before it took off)Failed to open/read local data from file/applicationOut of memoryTimeout was reachedFTP: command PORT failedFTP: command REST failedRequested range was not delivered by the serverInternal problem setting up the POSTSSL connect errorCouldn't resume downloadCouldn't read a file:// fileLDAP: cannot bindLDAP: search failedA required function in the library was not foundOperation was aborted by an application callbackA libcurl function was given a bad argumentFailed binding local connection endNumber of redirects hit maximum amountAn unknown option was passed in to libcurlMalformed telnet optionSSL peer certificate or SSH remote key was not OKServer returned nothing (no headers, no data)SSL crypto engine not foundCan not set SSL crypto engine as defaultFailed to initialise SSL crypto engineFailed sending data to the peerFailure when receiving data from the peerProblem with the local SSL certificateCouldn't use specified SSL cipherPeer certificate cannot be authenticated with given CA certificatesProblem with the SSL CA cert (path? access rights?)Unrecognized or bad HTTP Content or Transfer-EncodingInvalid LDAP URLMaximum file size exceededRequested SSL level failedFailed to shut down the SSL connectionFailed to load CRL file (path? access rights?, format?)Issuer check against peer certificate failedSend failed since rewinding of the data stream failedLogin deniedTFTP: File Not FoundTFTP: Access ViolationDisk full or allocation exceededTFTP: Illegal operationTFTP: Unknown transfer IDRemote file already existsTFTP: No such userConversion failedCaller must register CURLOPT_CONV_ callback optionsRemote file not foundError in the SSH layerSocket not ready for send/recvRTSP CSeq mismatch or invalid CSeqRTSP session errorUnable to parse FTP file listChunk callback failedThe max connection limit is reachedSSL public key does not match pinned public keySSL server certificate status verification FAILEDStream error in the HTTP/2 framing layerUnknown errorCall interruptedBad fileBad accessBad argumentInvalid argumentsOut of file descriptorsCall would blockBlocking call in progressDescriptor is not a socketNeed destination addressBad message sizeBad protocolProtocol option is unsupportedProtocol is unsupportedSocket is unsupportedOperation not supportedAddress family not supportedProtocol family not supportedAddress already in useAddress not availableNetwork downNetwork unreachableNetwork has been resetConnection was abortedConnection was resetNo buffer spaceSocket is already connectedSocket is not connectedSocket has been shut downToo many referencesTimed outConnection refusedLoop??Name too longHost downHost unreachableNot emptyProcess limit reachedToo many usersBad quotaSomething is staleRemote errorDisconnectedWinsock library is not readyWinsock library not initialisedWinsock version not supportedHost not foundHost not found, try againUnrecoverable error in call to nameserverNo data record of requested typeUnknown error %d (%#x)CRYPT_E_REVOKEDSEC_E_ALGORITHM_MISMATCHSEC_E_BAD_BINDINGSSEC_E_BAD_PKGIDSEC_E_BUFFER_TOO_SMALLSEC_E_CANNOT_INSTALLSEC_E_CANNOT_PACKSEC_E_CERT_EXPIREDSEC_E_CERT_UNKNOWNSEC_E_CERT_WRONG_USAGESEC_E_CONTEXT_EXPIREDSEC_E_CROSSREALM_DELEGATION_FAILURESEC_E_CRYPTO_SYSTEM_INVALIDSEC_E_DECRYPT_FAILURESEC_E_DELEGATION_POLICYSEC_E_DELEGATION_REQUIREDSEC_E_DOWNGRADE_DETECTEDSEC_E_ENCRYPT_FAILURESEC_E_ILLEGAL_MESSAGESEC_E_INCOMPLETE_CREDENTIALSSEC_E_INCOMPLETE_MESSAGESEC_E_INSUFFICIENT_MEMORYSEC_E_INTERNAL_ERRORSEC_E_INVALID_HANDLESEC_E_INVALID_PARAMETERSEC_E_INVALID_TOKENSEC_E_ISSUING_CA_UNTRUSTEDSEC_E_ISSUING_CA_UNTRUSTED_KDCSEC_E_KDC_CERT_EXPIREDSEC_E_KDC_CERT_REVOKEDSEC_E_KDC_INVALID_REQUESTSEC_E_KDC_UNABLE_TO_REFERSEC_E_KDC_UNKNOWN_ETYPESEC_E_LOGON_DENIEDSEC_E_MAX_REFERRALS_EXCEEDEDSEC_E_MESSAGE_ALTEREDSEC_E_MULTIPLE_ACCOUNTSSEC_E_MUST_BE_KDCSEC_E_NOT_OWNERSEC_E_NO_AUTHENTICATING_AUTHORITYSEC_E_NO_CREDENTIALSSEC_E_NO_IMPERSONATIONSEC_E_NO_IP_ADDRESSESSEC_E_NO_KERB_KEYSEC_E_NO_PA_DATASEC_E_NO_S4U_PROT_SUPPORTSEC_E_NO_TGT_REPLYSEC_E_OUT_OF_SEQUENCESEC_E_PKINIT_CLIENT_FAILURESEC_E_PKINIT_NAME_MISMATCHSEC_E_POLICY_NLTM_ONLYSEC_E_QOP_NOT_SUPPORTEDSEC_E_REVOCATION_OFFLINE_CSEC_E_REVOCATION_OFFLINE_KDCSEC_E_SECPKG_NOT_FOUNDSEC_E_SECURITY_QOS_FAILEDSEC_E_SHUTDOWN_IN_PROGRESSSEC_E_SMARTCARD_CERT_EXPIREDSEC_E_SMARTCARD_CERT_REVOKEDSEC_E_SMARTCARD_LOGON_REQUIREDSEC_E_STRONG_CRYPTO_NOT_SUPPORTEDSEC_E_TARGET_UNKNOWNSEC_E_TIME_SKEWSEC_E_TOO_MANY_PRINCIPALSSEC_E_UNFINISHED_CONTEXT_DELETEDSEC_E_UNKNOWN_CREDENTIALSSEC_E_UNSUPPORTED_FUNCTIONSEC_E_UNSUPPORTED_PREAUTHSEC_E_UNTRUSTED_ROOTSEC_E_WRONG_CREDENTIAL_HANDLESEC_E_WRONG_PRINCIPALSEC_I_COMPLETE_AND_CONTINUESEC_I_COMPLETE_NEEDEDSEC_I_CONTEXT_EXPIREDSEC_I_CONTINUE_NEEDEDSEC_I_INCOMPLETE_CREDENTIALSSEC_I_LOCAL_LOGONSEC_I_NO_LSA_CONTEXTSEC_I_RENEGOTIATESEC_I_SIGNATURE_NEEDEDSEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs when a fatal SSL/TLS alert is received (e.g. handshake failed). More detail may be available in the Windows System event log.%s (0x%08X)%s - %sConnection cache is full, closing the oldest one. Connection #%ld to host %s left intact Re-used connection seems dead, get a new one Pipe broke: handle %p, url = %s In state %d with no easy_conn, bail out! Resolving timed out after %ld millisecondsConnection timed out after %ld millisecondsOperation timed out after %ld milliseconds with %I64d out of %I64d bytes receivedOperation timed out after %ld milliseconds with %I64d bytes receivedHostname '%s' was found in DNS cache Internal error removing splay node = %d Internal error clearing splay node = %d security.dllsecur32.dllInitSecurityInterfaceWSend failure: %sRecv failure: %sWrite callback asked for PAUSE when not supported!Failed writing body (%zu != %zu)Failed writing headerDataHeaderfromto[%s %s %s]Failed to set SO_KEEPALIVE on fd %d Failed to set SIO_KEEPALIVE_VALS on fd %d: %d if!host!Couldn't bind to interface '%s'Name '%s' family %i resolved to '%s' family %i Couldn't bind to '%s'getsockname() failed with errno %d: %sLocal port: %hu Bind to local port %hu failed, trying next bind failed with errno %d: %sgetpeername() failed with errno %d: %sssrem inet_ntop() failed with errno %d: %sssloc inet_ntop() failed with errno %d: %sConnection time-outAfter %ldms connect time, move on! Connection failed connect to %s port %ld failed: %s Failed to connect to %s port %ld: %sCould not set TCP_NODELAY: %s TCP_NODELAY set sa_addr inet_ntop() failed with errno %d: %s Trying %s... Immediate connect fail for %s: %s %s:%dHostname in DNS cache was stale, zapped Hostname %s was found in DNS cache %255[^:]:%dCouldn't parse CURLOPT_RESOLVE removal entry '%s'! %255[^:]:%d:%255sCouldn't parse CURLOPT_RESOLVE entry '%s'! Address in '%s' found illegal! Added %s:%d:%s to DNS cache identityALLSESSFLUSHRELOADSet-Cookie:CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!Closing connection %ld Connection %ld seems to be dead! can pipelinecan multiplexseriallyFound bundle for host %s: %p [%s] Server doesn't support multi-use yet, wait Server doesn't support multi-use (yet) Could pipeline, but not asked to! Could multiplex, but not asked to! Connection #%ld is still name resolving, can't reuse Connection #%ld isn't open enough, can't reuse Pipe is full, skip (%zu) Penalized, skip Multiplexed connection found! Found pending candidate for reuse and CURLOPT_PIPEWAIT is set unknown proxytype option givenConnected to %s (%s) port %ld (#%ld) IDN support not present, can't parse Unicode domains Protocol "%s" not supported or disabled in libcurlIllegal characters found in URLBad URL, colon is first characterfile:%*15[^ /:]:%[^ ]%[^ ]Bad URLlocalhost/127.0.0.1/Invalid file://hostname/, expected localhost or 127.0.0.1 or none%15[^ /:]:%3[/]%[^ /?#]%[^ ]%[^ /?#]%[^ ] malformedFTP.ftpDICT.DICTLDAP.LDAPIMAP.IMAPSMTP.smtpPOP3.pop3esUnwillingly accepted illegal URL using %d slash%s! %s://%s%sRebuilt URL to: %s %25Please URL encode %% as %%25, see RFC 6874. Invalid IPv6 address format %I64u-, *_proxyhttp_proxyall_proxyALL_PROXY://httpssocks5hsocks5socks4asocks4sockshttp:Unsupported proxy scheme for '%s'Unsupported proxy '%s', libcurl is built without the HTTPS-proxy support.No valid port number in proxy string (%s) [%*45[0123456789abcdefABCDEF:.]%c;type=%c][%s://%s%s%s:%hu%s%s%sPort number out of rangeIllegal port numberCouldn't find host %s in the _netrc file; using defaults anonymousftp@example.comNo valid port number in connect to host string (%s) %s%s%sConnecting to hostname: %s Connecting to port: %d Couldn't resolve host '%s'Couldn't resolve proxy '%s'%s://%smemory shortageno_proxyNO_PROXYFound connection %ld, with requests in the pipe (%zu) We can reuse, but we want a new connection anyway proxyRe-using existing connection! (#%ld) with %s %s No more connections allowed to host: %d No connections available in cache No connections available. NTLM picked AND auth done set, clear picked! NTLM-proxy picked AND auth done set, clear picked! User-Agent: %s ignoring failed cookie_init for %s %1023[^; =] =%4999[^; ]securehttponlydomainlocalhost:skipped cookie with bad tailmatch domain: %s versionmax-ageexpires#HttpOnly_TRUEFALSEReplacedAdded%s cookie %s="%s" for domain %s, path %s, expire %I64d nonertunknown%s%s%s %s %s %s %I64d %s %swt# Netscape HTTP Cookie File # https://curl.haxx.se/docs/http-cookies.html # This file was generated by libcurl! Edit at your own risk. # # Fatal libcurl error WARNING: failed to save cookies in %s %dCould not resolve %s: %sinit_resolve_thread() failed for %s; %s getaddrinfo() failed for %s:%d; %s Unrecognized parameter value passed via CURLOPT_SSLVERSION%s:libcurl/7.53.1-DEV7.53.1-DEVi386-pc-win32I32I64%ld.%ld%s:%ldoperation aborted by callbackRead callback asked for PAUSE when not supported!read function returned funny value%x%sseek callback returned error %dthe ioctl callback returned %d ioctl callback returned error %dnecessary data rewind wasn't possibleThe requested document is not new enough The requested document is not old enough Rewinding stream by : %zd bytes on url %s (zero-length body) Excess found in a non pipelined read: excess = %zd url = %s (zero-length body) Ignoring the response-body The entire document is already downloadedHTTP server doesn't seem to support byte ranges. Cannot resume.Simulate a HTTP 304 response! Failed writing data%s in chunked-encodingLeftovers after chunking: %zu bytes Rewinding %zu bytes Rewinding stream by : %zu bytes on url %s (size = %I64d, maxdownload = %I64d, bytecount = %I64d, nread = %zd) Excess found in a non pipelined read: excess = %zu, size = %I64d, maxdownload = %I64d, bytecount = %I64d we are done reading and this is set to close, stop send Failed to alloc scratch buffer!We are completely uploaded and fine select/poll returned errorDone waiting for 100-continue transfer closed with %I64d bytes remaining to readtransfer closed with outstanding read data remainingNo URL set!%%%02x%15[^?&/:]://%cMaximum (%ld) redirects followedIssue another request to this URL: '%s' Switch from POST to GET HEADGETDisables POST, goes with %s Connection died, retrying a fresh connect Conn: %ld (%p) Receive pipe weight: (%I64d/%zu), penalized: %s Site %s:%d is pipeline blacklisted Server %s is blacklisted --:--:--%2I64d:%02I64d:%02I64d%3I64dd %02I64dh%7I64dd%5I64d%4I64dk%2I64d.%0I64dM%4I64dM%2I64d.%0I64dG%4I64dG%4I64dT%4I64dPCallback aborted** Resuming transfer from byte position %I64d %% Total %% Received %% Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed %3I64d %s %3I64d %s %3I64d %s %s %s %s %s %s %sHTTPHTTPS%s:%sProxy-%sAuthorization: Basic %s Rewind stream after send NTLM send, close instead of sending %I64d bytes The requested URL returned error: %dNegotiateNTLMDigestProxy-authorization:Authorization:BasicProxyServer%s auth using %s with user '%s' Authentication problem. Ignoring this. Ignoring duplicate digest auth header. Empty reply from server1.11.0Expect:100-continueExpect: 100-continue Host:Content-Type:Content-LengthConnectionTransfer-Encoding:%s Invalid TIMEVALUE%s, %02d %s %4d %02d:%02d:%02d GMTIf-Modified-Since: %s If-Unmodified-Since: %s Last-Modified: %s POSTPUTUser-Agent:Referer:Referer: %s Cookie:Accept-Encoding:Accept-Encoding: %s chunkedChunky upload is not supported by HTTP 1.0Transfer-Encoding: chunked Host: %s%s%s Host: %s%s%s:%hu ftp://;type=Accept:Accept: */* Could not seek streamCould only read %I64d bytes from the inputFile already completely uploadedRange:Range: bytes=%s Content-Range:Content-Range: bytes 0-%I64d/%I64d Content-Range: bytes %s%I64d/%I64d Content-Range: bytes %s/%I64d %s ftp://%s:%s@%sProxy-Connection:Proxy-Connection: Keep-Alive %s HTTP/%s %s%s%s%s%s%s%s%s%s%s%sCookie: ; %s%s=%sContent-Length: 0 Failed sending POST requestContent-Length:Content-Length: %I64d Could not get Content-Type header line!Failed sending PUT requestContent-Type: application/x-www-form-urlencoded %x 0 Failed sending HTTP POST requestFailed sending HTTP requestupload completely sent off: %I64d out of %I64d bytes HTTP/Avoided giant realloc for header (max is %d)!Failed to alloc memory for big header!The requested URL returned error: %sReceived 101 no chunk, no close, no size. Assume close to signal end Connection closure while negotiating auth (HTTP 1.0?) HTTP error before end of send, keep sending HTTP error before end of send, stop sending Keep sending data to get tossed away! HTTP/%d.%d %d HTTP/2 %dLying server, not serving HTTP/2 HTTP %3d RTSP/%d.%d %3dHTTP 1.0, assume close after body Negative content-length: %I64d, closing after transfer Server:keep-aliveHTTP/1.0 proxy connection set to keep alive! HTTP/1.1 proxy connection set close! Connection:HTTP/1.0 connection set to keep alive! deflategzipx-gzipContent-Encoding:Last-Modified:WWW-Authenticate:Proxy-authenticate:Location:Operation too slow. Less than %ld bytes/sec transferred the last %ld secondsLoadLibraryExW\/AddDllDirectory%d.%d.%d.%dEstablish HTTP proxy tunnel to %s:%hu %s:%huCONNECT%s%s%s:%huHost: %s CONNECT %s HTTP/%s %s%s%s%sFailed sending CONNECT to proxyProxy CONNECT aborted due to timeoutCONNECT response too large!Proxy CONNECT aborted due to select/poll errorProxy CONNECT connection closed Proxy CONNECT abortedchunk reading DONE Ignore %I64d bytes of response-body Ignore chunked response-body Content-Length: in %03d responseTransfer-Encoding: in %03d responseCONNECT responded chunked HTTP/1.%d %dTUNNEL_STATE switched to: %d Connect me again please Received HTTP code %d from proxy after CONNECTProxy replied OK to CONNECT request aSOCKS4%s: connecting to HTTP proxy %s port %d SOCKS4 communication to %s:%d SOCKS4 connect to IPv4 %s (locally resolved) SOCKS4 connection to %s not supported Failed to resolve "%s" for SOCKS4 connect.Too long SOCKS proxy name, can't use! Failed to send SOCKS4 connect request.Failed to receive SOCKS4 connect request ack.SOCKS4 reply has wrong version, version should be 4.SOCKS4%s request granted. Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), request rejected or failed.Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), request rejected because SOCKS server cannot connect to identd on the client.Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), request rejected because the client program and identd report different user-ids.Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d), Unknown.SOCKS5: connecting to HTTP proxy %s port %d SOCKS5: server resolving disabled for hostnames of length > 255 [actual len=%zu] SOCKS5: no connection hereSOCKS5: connection timeoutSOCKS5: error occurred during connectionSOCKS5 communication to %s:%d Unable to send initial SOCKS5 request.SOCKS5 nothing to readSOCKS5 read timeoutSOCKS5 read error occurredUnable to receive initial SOCKS5 response.Received invalid version in initial SOCKS5 response.Unable to negotiate SOCKS5 GSS-API context.Failed to send SOCKS5 sub-negotiation request.Unable to receive SOCKS5 sub-negotiation response.User was rejected by the SOCKS5 server (%d %d).No authentication method was acceptable. (It is quite likely that the SOCKS5 server wanted a username/password, since none was supplied to the server on this connection.)No authentication method was acceptable.Undocumented SOCKS5 mode attempted to be used by server.SOCKS5 connect to IPv4 %s (locally resolved) SOCKS5 connection to %s not supported Failed to resolve "%s" for SOCKS5 connect.SOCKS5 GSS-API protection not yet implemented.Failed to send SOCKS5 connect request.Failed to receive SOCKS5 connect request ack.SOCKS5 reply has wrong version, version should be 5.Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)Can't complete SOCKS5 connection to %s:%d. (%d)Can't complete SOCKS5 connection to %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)SOCKS5 request granted. /.//./..//.._netrc machinedefaultlogin%.*s%sAuthorization: Digest %s NTLM auth restarted NTLM handshake rejected NTLM handshake failure (internal error) %sAuthorization: NTLM %s MonTueWedThuFriSatSunMondayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSepOctNovDec%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]%02d:%02d:%02d%n%02d:%02d%nschannel: SSL/TLS connection with %s port %hu (step 1/3) schannel: WinSSL version is old and may not be able to connect to some servers due to lack of SNI, algorithms, etc. wine_get_versionntdllschannel: re-using existing credential handle schannel: incremented credential handle refcount = %d schannel: disabled server certificate revocation checks schannel: checking server certificate revocation schannel: verifyhost setting prevents Schannel from comparing the supplied target name with the subject names in server certificates. Schannel: TLS 1.3 is not yet supportedUnrecognized parameter passed via CURLOPT_SSLVERSIONschannel: unable to allocate memoryMicrosoft Unified Security Protocol Providerschannel: SNI or certificate check failed: %sschannel: AcquireCredentialsHandle failed: %sschannel: using IP address, SNI is not supported by OS. http/1.1schannel: ALPN, offering %s schannel: initial InitializeSecurityContext failed: %sschannel: sending initial handshake data: sending %lu bytes... schannel: failed to send initial handshake data: sent %zd of %lu bytesschannel: sent initial handshake data: sent %zd bytes schannel: SSL/TLS connection with %s port %hu (step 2/3) schannel: unable to re-allocate memoryschannel: failed to receive handshake, need more data schannel: failed to receive handshake, SSL/TLS connection failedschannel: encrypted data buffer: offset %zu length %zu schannel: received incomplete message, need more data schannel: a client certificate has been requested schannel: sending next handshake data: sending %lu bytes... schannel: failed to send next handshake data: sent %zd of %lu bytesschannel: next InitializeSecurityContext failed: %sschannel: encrypted data length: %lu schannel: SSL/TLS handshake complete schannel: SSL/TLS connection with %s port %hu (step 3/3) schannel: failed to setup sequence detectionschannel: failed to setup replay detectionschannel: failed to setup confidentialityschannel: failed to setup memory allocationschannel: failed to setup stream orientationschannel: failed to retrieve ALPN resultschannel: ALPN, server accepted to use %.*s ALPN, server did not agree to a protocol schannel: old credential handle is stale, removing schannel: failed to store credential handleschannel: stored credential handle in session cache schannel: failed to retrieve remote cert contextSSL/TLS connection timeoutselect/poll on SSL/TLS socket, errno: %dschannel: timed out sending data (bytes sent: %zd)select/poll on SSL socket, errno: %dschannel: client wants to read %zu bytes schannel: enough decrypted data is already available schannel: an unrecoverable error occurred in a prior call schannel: server indicated shutdown in a prior call schannel: encdata_buffer resized %zu schannel: Curl_read_plain returned CURLE_AGAIN schannel: Curl_read_plain returned CURLE_RECV_ERROR schannel: server closed the connection schannel: encrypted data got %zd schannel: decrypted data length: %lu schannel: decrypted data added: %zu schannel: decrypted data cached: offset %zu length %zu schannel: encrypted data cached: offset %zu length %zu schannel: remote party requests renegotiation schannel: can't renogotiate, an error is pending schannel: can't renogotiate, encrypted data available schannel: renegotiating SSL/TLS connection schannel: renegotiation failed schannel: SSL/TLS connection renegotiated schannel: failed to decrypt data, need more data schannel: failed to read data from server: %s schannel: decrypted data buffer: offset %zu length %zu schannel: schannel_recv cleanup schannel: server closed abruptly (missing close_notify) schannel: decrypted data returned %zu schannel: shutting down SSL/TLS connection with %s port %hu schannel: ApplyControlToken failure: %sschannel: failed to send close msg: %s (bytes written: %zd) schannel: clear security context handle WinSSL%c%c==%c%c%c=%c%c%c%cToo long hexadecimal numberIllegal or missing hexadecimal sequenceMalformed encoding foundBad content-encoding found%sAuthorization: Negotiate %s .gifimage/gif.jpgimage/jpeg.jpeg.txttext/plain.htmltext/html.xmlapplication/xml; filename="%s"Content-Type: multipart/form-data%s; boundary=%s --%s Content-Disposition: form-data; name="" Content-Type: multipart/mixed; boundary=%s --%s Content-Disposition: attachment Content-Type: %s %s couldn't open file "%s" --%s-- --%s-- ------------------------%08x%08xWDigestrealmstaledigest_sspi: MakeSignature failed, error 0x%08lx NegotiateSPNEGO handshake failure (empty challenge message) NTLMNTLM handshake failure (empty type-2 message) NTLM handshake failure (type-3 message): Status=%x SSPI error: %s failed: %srcmdKerberosAcquireCredentialsHandleFailed to acquire credentials.InitializeSecurityContextFailed to initialise security context.Failed to send SSPI authentication request.Failed to send SSPI authentication token.Failed to receive SSPI authentication response.User was rejected by the SOCKS5 server (%u %u).Invalid SSPI authentication response type (%u %u).Failed to receive SSPI authentication token.QueryCredentialAttributesFailed to determine user name.SOCKS5 server authencticated user %s with GSS-API. integrityconfidentialitySOCKS5 server supports GSS-API %s data protection. QueryContextAttributesFailed to query security context attributes.EncryptMessageFailed to send SSPI encryption request.Failed to send SSPI encryption type.Failed to receive SSPI encryption response.Invalid SSPI encryption response type (%u %u).Failed to receive SSPI encryption type.DecryptMessageInvalid SSPI encryption response length (%lu).out GSS-API data GSS-API integrity GSS-API confidentialitySOCKS5 access with%s protection granted. 1.2.840.10040.4.1dsa1.2.840.10040.4.3dsa-with-sha11.2.840.10045.2.1ecPublicKey1.2.840.10045.3.0.1c2pnb163v11.2.840.10045.4.1ecdsa-with-SHA11.2.840.10046.2.1dhpublicnumber1.2.840.113549.1.1.1rsaEncryption1.2.840.113549.1.1.2md2WithRSAEncryption1.2.840.113549.1.1.4md5WithRSAEncryption1.2.840.113549.1.1.5sha1WithRSAEncryption1.2.840.113549.1.1.10RSASSA-PSS1.2.840.113549.1.1.14sha224WithRSAEncryption1.2.840.113549.1.1.11sha256WithRSAEncryption1.2.840.113549.1.1.12sha384WithRSAEncryption1.2.840.113549.1.1.13sha512WithRSAEncryption1.2.840.113549.2.2md21.2.840.113549.2.5md51.3.14.3.2.26CN2.5.4.4SN2.5.4.5serialNumber2.5.4.62.5.4.7L2.5.4.8ST2.5.4.9streetAddress2.5.4.10O2.5.4.11OU2.5.4.12title2.5.4.132.5.4.17postalCode2.5.4.412.5.4.42givenName2.5.4.43initials2.5.4.44generationQualifier2.5.4.45X500UniqueIdentifier2.5.4.46dnQualifier2.5.4.65pseudonym1.2.840.113549.1.9.1emailAddress2.5.4.72rolesubjectAltName2.5.29.18issuerAltName2.5.29.19basicConstraints2.16.840.1.101.3.4.2.4sha2242.16.840.1.101.3.4.2.1sha2562.16.840.1.101.3.4.2.2sha3842.16.840.1.101.3.4.2.3sha512%02x:0x%s%lx GMT%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*sGMT%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s %s: %s RSA Public Key (%lu bits) %luRSA Public Keyrsa(n)rsa(e)dsa(p)dsa(q)dsa(g)dsa(pub_key)dh(p)dh(g)dh(pub_key)Subject%2d Subject: %s Issuer Issuer: %s %lxVersion Version: %lu (0x%lx) Serial Number Serial Number: %s Signature Algorithm Signature Algorithm: %s Start Date Start Date: %s Expire Date Expire Date: %s Public Key Algorithm Public Key Algorithm: %s Signature Signature: %s -----BEGIN CERTIFICATE----------END CERTIFICATE-----Cert?P?9RFߑ??-DT! @$@0@cܥL@(w@p@@@.AAC ` ?Afmod@IHPHHHHPHH@H@HH@HHHPHH8C8C\3&<-DT!?\3&-DT! \3&<-DT! @UUUUUUſ333333m۶mۦ颋.?333333?qq?UUUUUU?ONđ?m۶mۦ?$rxxx????9B.@׽2b 78C8C\3&<-DT!?UUUUUU?333333?m۶mۦ?颋.?333333?qq?UUUUUU?ONđ?m۶mۦ?$rxxx???9B.@׽2b UUUUUUſ?UUUUUU?*llV4V>>m0_$@8C`a=`a=@T!?sp.c;`C>m0_$@8C`a=`a=@T!?sp.c;`CB<'HR%?I&<^:ȅe?>!ʎ<sl?ecb~q<ۧ?rʀ<F(&?Zn<'`f?47j<㚦?+i U<oX?F.K;<.'?Yhʼn<4lkQg?;+U<3?М m8<&?<S(?Y=t<:@Xh?,n@4`<$?<n?9ܮ<-)?\<Řwi?=<R%é?f@<*B?aw<G^*?m(<<2;j?PE<?Ҳ?<w*I?n'$<23?z7<[>t?V-Ai<?`DTb< ;?S.<TR*?)R<2k?,%ً<r?SC? <H?Zxgf<`/-?#<މ7m?w <悆a?_"C<lX^?@<{Х/?$8^<]hNp?bX*<?}_Ͼ<s?pt<hf2?$V<4{#s?Ug <?w<J.?IZ <*Ow5?.@<FHv?N <!?j<v(?z"<i68??!<Uۊ<o]2'?I<Рi?G<o? Ιn<9[? |^<.?>oj<._p?1S<X?l<~?o.x<%3d?{=4 L?V!=b#?@g = a?Gz =]ư?6 =oJV?J b='4?/t><w?a`<_?a e=F``?/f =#&?5SmT4<W?Rz< ъ(?vY<k?pY. =y?8'<KuC?j<{ =2<5?ýd =x?"a =@ic?%[9=?kRF<6DC?ş ܬ_<5Z?ȡk*=3?*+xi(<G&?r ly=:3S?z j<[?'<;!?h=<?:<sd?3 =? ?{!mB<<>? *2=2?cMyoG=Vsw?8K$<}?Cl<Ϲ?-<'F?ɕ{<$R?܊)B<#?<c?? ~<F]?&= /?94E<? T9?9* )<l?e/?B6!F=u0wu?M떐 =k`(?<4=?Kp=G"zI?$}Tw5< [?ߪb<Ka?aF7=V j?Ty<R߂e?M]-e<$[?3<Ễ?QZo =n6)}?, ,?؏?M?x%q? ?/xbJ?Ȉb?uÏ?(Z?t?{}2F??_2?>T^?u ??4td? Z?( ?WIY?d?{?|:?S9?s? ?K???l.?Z3?;E?2:@?>?@@?"Ir?64?@Û??765@Z?&+-?w'?Q?Gpt?2&?X9Ш?Bq?/? ?vɛ?Mj$?3?s? b里?V?% S?Vѩ?ߖ%@?U>?2,|?ܜm?Vkށ?9?I@|?P3y??}>v?H|As?#?(b;?탿7?]o-4?Ph0? H,?:5)?Iٓ\%?f,!?갸%?N?$k?oay?*??Y ?$??(?a?9y?9 9R?%R?F?@I?j T?0ұR?VDD?oWsg6?UJ(?>t?2̄λ ?1_?$*2?[ێ?N)?V?l$G~ٮ?+6?tF4؎?,~?"n?<փ]?|ߠL?l6;?6**?|59?:?HK?s7 ?I-?$z?9\?>|.~?-W?^\sY0?:Rp7?mbzA?G4's?IyȊ?%=_?C\2?Ou?m.?M?nw?KK'F?l^?:" ?Ѭ?}6lw?:@?7Z8> ?$ f?e')lW?zD@ [?jq?PJ?F?i i1mm.s?,)'><i? i<ȿmb<Z" ?.ҿu<ϕk|?c}ؿ,g<ysh:?;8]+޿ ^ty[g?h9; %S ? %L jh2yʿ;f 4݋<Xw$3Ak ł<࿇暳s)f09N,J?8v<uZEeu?F2k Wt-v1-VA`пgY?\ϗb buпP/Ye?&%ѣ@}<P/Ye&%ѣ@}<?gY\ϗb bu?-v1?-VA`?uZEeuF2k Wt?N,J8v<?暳s?)f09?Xw$3?Ak ł<?2y?;f 4݋<?S Ϳ %L jh?ty[gſh9; %?ysh:;8]+޿ ^?ϕk|c}ؿ,g<?Z" .ҿu<?i i<ȿmb<?1mm.s,)'><?Mu{<`w>,g5RҌ<2ؼcnQU Zsnim?Lyc>=*p%??C;0=|?Ix"<=`` ә?yM==orO?+C==v?R1=PQ ?Ӏb=@P?5M[g?=V?d+[7=?nB>= kz*?w#8=0nط?C#7={?D i00=ˮf?j -=x)?}z= ? 0$=HV?o=X a?;M_8=@? 5=?^@'=L$?/r(==ɥ%?Nl,"=@\r??t8=85R?ӇӜ=L. ? >)g=Ը3U?Ӱ== ?hXg+=og?X=ذ0?{fHn=<w?y5s3R6=)?a8< O4W?4bV0=L?4@=@?Xۓ4=Tk?>_(=?*o=@[c?,=$4b?dO"=lx?#608=ě&m*?ɉh"0=בl?n6ѯ{<9[P?cezb<$?F 8"=8B.?0gǓW.=pow????D???@?@W????w?A? ?@??q????@??}?N?@ ????m?A?????q?H?!?????a?Š#4<Xq?BJ=_D?mKF=Ԛ?s7E=@[-?K>d:=g?Z}=\uI=s~Q?g:"(N='?9~$O1=q?n1%=p)k?vʌ=`X:?q.W =Pi?g>M=[?ֲa M=_3?֍,uXO=`Ɏ/?1w<=>'eH?` JJ=x~? Š&=n`Y?˖C=0?]/=# g?uP= ?,lC=5q?ᕎ =@Dӳ?-[@=pt4z? فpnJ=l?i.Eg<y~??O^'=(Tt? x;;=P?RRF=&?XɣN=J@?~=Ht=c?AzU"=nB?U_lj7=]?qBD= h0"ؿ؍ IQn0ؿHn&E:׿E7D57A׿ %@@ֿ*Z+ASTֿrJD@ӑտNT?w3kտr19]ԿFKm8C!`Կ1y2Y@ Կ*(FEO5iѿ4Q!?: пC +pڌXпxO,C"пAri<q~_ϿR v== ~οo6@mPͿ d+>̿9Ȓ[\˿8B'&˿i[JZOʿbnEDE}ɿUgc@H ȿUZdL" ǿ=Dj!ǿVm:A@`3ƿ~%3kcſ"7M Ŀp>)%ÿ\Bjx¿#6HˆQ;`t-¿=]PH0;TaָE&a-#KV\ Vb4M@U@Xx55@캿D=iI^Gי'7AԷUNҪ1GƴO\C@+Bg:IB@Zu}M:(T!1n]vQ<)8h׾o$|f+x2S74U".mœFB*6IKS_ D 5M-Cz1}BKG c?OfFL,sX4I+xm w$VcE?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@?@??????????????????????@????@?? ? ?@ ? ? ? ?@ ? ? ? ?@ ? ? ? ?@ ? ? ? ?@ ? ???@????@????@????@????@????@????@????@????@??|)P!?Ua0 !=+34?2Q =`??7; WJ=`7E?'a%C=MkK?*b<=0ɘP?*,z?=d|S?KT'K=R_V?bF=p^BY?E&= 9&\?߇N9=p _?߭Eb2]A=`?f#I=hb?O2H`3=c?e2a1=ԆLe?2RM=f?A3_:=@0h?[2ieO=i?1rK=k?Σ-=l?̈[8=yQm?>|W8A=՛ko?>qݲN=np?z m{ M=t)(q?m,SD=E`q?}e?=ԩr?}~:fE=PSs?&A=& t?,&8=tt?eѴN@=PSu?^p?o40=!9v?W?N=<v?+#GYM=Hw?qC@=Pex?0 &ے=Xy?8=<8y?!({=H= z?d,GB=6K{?ҝE M=¾|?w31!=L|?^X-F=Dfqsg~7(7s6uE(ruv.E,t]rLvOrȚ p&qC"5FzIqoOjpO|Wp Ȯ/N#D5pO/3N^o I!` 1nDCE"Bnu ^!EWΉm--0lNpCP&`l™J$akN8xj[ -=8Riy~ La8i[٬zF+ghk<@8KHg}7ڒ%gmg1&3{4WfI8e}OA8ӌd_\MP4.dó6D@uc2I{bTWB`b.r}X]La6MŞr<P`;ƥIpη_v<-UF^9M\̢N3e[ݻk>? #JY&-DPZXm4I@@7eWO/jUIlNAi0TWq uIbR|m:K@VNQ?|G¾d0`7O84 fXLzB7CIp4"%H`/G: WI`ȃ1D/!H@%OAA9"Ix'8RؔN;*2]@G?E?@D?C?A?@?>?@=?;?@:?8?7?6?4?3?1?@0?.?@-?+?*?)?'?&?$?@#?!?@ ???????@??@???? ? ? ?@ ??@???????@??@?????@??@??@?????@??@???????@??@???????@??@???????@??@???????@??@?????@??@??@?????@??@????????@????@????@???@????@???@????@???????@????@???@????@???????@??~?~?@}?|?|?@{?z?y?y?@x?w?v?@v?u?t?t?@s?r?q?q?@p?o?o?@n?m?l?l?@k?j?j?@i?h?g?g?@f?e?d?d?c?b?b?@a?`?_?_?@^?]?]?@\?[?Z?Z?@Y?X?W?W?V?U?U?@T?S?R?R?@Q?P?P?@O?N?M?M?@L?K?J?@J?I?H?H?@G?>Y"G=>.ܶlWE=>jۋbH=>^IL#=>(i&I=h>gݟP'E=p>*)D=>&N=x>.;ĝ@=H >Qyu3= >c-=@>Rݡ:==> {M= @>C=` >bߔB= >tdC=$ >9O=>B NC=>j&==>.<=@>`lrG=>!ls1= ?8= @? mN=&?UtQ$=X?PiB{^C=?Gv72=@?qlm+=?!.j7/=d?L C=`?m +=P ?5Od% =?r<(?*Hga2=@ ?CI=r ?sA=* ?GTiA= ` ?KՋD=r" ?Dp`q=L$ ?~G=4& ? D='@?E=)?'P<+?f4±cC=@?qWn{;=?gC i8=?XKD=P?G;R"=7?8΁3,'1D=B'@?:+NB=(?1z@J=*?3=+`?wU4?=,?DO=;.?$b=/p?g)([|X>=H1?>gV=20?OBO=*4?bPA<5?e4=f7@?|[{~*L=9?ٹE=t:?G]C='"?@(6F=? #?'A=@H#?43 A=Ax#?uN}*J=C#?)r7Yr7=]D#?.K="=rE$?r =F0$?3=1Z1=H`$?h|=G=gI$?ܩN:=J$?4e 6=K$?{<9==M%?uYPwH=NH%?-*8=Px%?yF.=-Q%?\9 ;,=R%?29Zd@=T&?~YK| =sU0&?WĻ(J=VX&?RIG=X&?W N=Y&?g'9=[&? D"^=2)$7bmLMӿ( ԏS4_ >L|/ dM4g±82qڜ1ןqaPCQo%;9?_0Cw4g%6L&M;k@ڿ81ABۏ1uB)_ Y/󓎣,:x.Ճ^-?ޯԝI-:]=O>O#w_jُBn(+E -V~|_B}_ACK!ܨY:_5Gt/C$>#Hm- MVn@QU^tA$OÄþiM@K8|;2@(AV64oꬠTC9?&u.~Fs:4Կ J_L II=@0(ן$.G?}3Rʏ3 !|.4*ڟ ඄}3? G"jm >; *O 0 :O 2K;޿ Q`4_  ZD 69* F_ T3ʢK M.֢> @_@? 1\hUXpM&Jx3Ҭx/h 78Lv]EV 3Bv9r_cM*5&Lq3?:R$@܎$=K'\?Ъ{b>$EvCIw8R'FG_j,)+jBD|_ `kA%'r BL TE_GO#i# ;^طH?6(`JJ\HB5``.11\?QDTӾ96оk< xE˾CqTR;ǾdG GgL@_h %? SS@b?Wdy>c*GPAiFC.ֿ?53=?͸)a,?][SqnC?nwtӰY?eus<)kp?&<ߑțuE?Ka<>?5a1xH<lX? aJ.?#Eq<1 ?1j<1Lp!?|眊<dD8`<;f?Ud4ݛ u? gVr/eT'?*mb|L%?2L#FG?AֈDh?ԛƟfNJ?:|”<۠*B?&KVU?An/X0y?c~˛ ? c??-[6?N}X<?]݃?'Z4?e-CS?F?,w?(F_e?X2CQ? ُ㈏?wT?/VW?#(7? L?hC!߶?c(y?-˶?X1Uu??Y.<?PB?>SŎ?6 Ӷ?'P9?z^3? ΂?&1yA?(+_R?mY?}"?ƟlW?P),H?,b??@??c\5j?=Mpm?c+?BpVV?Q9V%?]|=3?.?|_P?%?ػZq\? ,6?5DKBӹ?@IK?Xf?v?'?+3?2y?g/p<?7C ??ED;?h7r?=?(r? EVw?У? ?0SM`??3?/*2?56Yz?Ʊ?Ge?4?%KV?rH?I,+?U&X>?i.?c4?? ?NT?j86?f*"!?~w"?nJR?17!?|GD|??*a?} Ũ<?ƼpAؒ?ZM$^@]>= @Z7@abK?؝Z@t?,@T4s?a g @XpM@D$_@n}in@)M@֐@P(*C? mz@E3&ԿfYeY!@,d&@#7̓B,@@=U&2@UUUUUU@9E47@ @}=m=@@ 8λB@[[@u+E6G@@?@ӸHO3oX ?% #Z."S- >Q!r?M%ᾎ;DŽ cd3>$9t?JyA]VJ]>Q䫢I?ZIο7t`=cH??ZS +ߏ?Y9m|1~-g>b/[E?8QSվ7KǓ>€p?[j3HX& CUx>XzvC?*ɿa#wi#:wB??x#qQ?L yaF5d>2*q?ɾ?c3yƟ0>q澺k?g\>{O>>u>=?)IſX3{9lf??V}X9܈?+*tsJEX*yhU&>3H?ܨ9ԪFr>)(g?VtFcfy>?p6?K=3il??Kk0vB-G? 8dlMV>|s`?Pt"!k?JI>΃+תd?s{c|HY"?X:n>//2?6G^#f??dčDo=z>-Bվy%#(A>ō:?S/|o3fW|aD `N>Fb?kt LR3ec>Df/?@b̰kع??"])E}>r>ľ>nzru>Cԑ?lf6 noP"Q?m˹A>fǰa?+kWZbI#݄,[>=h,?nĠ}P=Ȣ_??+j>&D(>ll?bIJm>gjVa?\yNW> 4w+?UUUUUU??"])>E}>r>>>nz?ru>Cԑ?lf6 n>oP"Q??m˹A>fǰa?+kWZb>I#?݄,[>=h,?nĠ?}PȢ_??dčD?o=z>-B>y%#?(A>ō:?S/|>o3fW|a?D `N>Fb?kt> LR3?ec>Df/?@b̰?k=ع??Kk?0vB-G? 8d>l?MV>|s`?P>t"!k??JI>΃+תd?s{c|H>Y"??X:n>//2?6G?^=#f??V}X9?܈?+*tsJ>EX*?yhU&>3H?ܨ9>ԪFr?>)(g?V>tF?cfy>?p6??K=3=il??x#?qQ?L ya>F?5d>2*q?>?c3y?Ɵ0>q澺k?>g\>{O?>>u>=?)I?X3{9=lf??ZS +?ߏ?Y9?m|1~?-g>b/[E?8QS>7K?Ǔ>€p?[j3H>X& CU?x>XzvC?*?a#wi#:=wB??ӸHO3?oX ?% ?#Z?."S- >Q!r?M%>;DŽ? cd3>$9t?Jy>A]?VJ]>Q䫢I?ZI?7t`cH??fYeY!,d&@#7̓B,=U&2@UUUUUU@9E47 }=m=@@ 8λB[[u+E6G@@@ZM$^]>= @Z7abK؝Z@t?,T4sa g @XpM@D$_n}in)M@֐@P(*C mz<@E3&ԿI,+U&X>?i.c4? ?NTj86f*"!?~w"?nJR17!|GD|??*a} Ũ?ƼpAؒ?߿ED;?h7rۿ=(r? EVw?У׿ 0SM`??3?/*2Կ56Yz⿛Ʊ?Ge?4%KV<?rH?BpVV̿Q9V%?]|=3ſ.߿|_P?%?ػZq\ ,6ڿ5DKBӹ?@IK?Xf䵿vӿ'?+3?2yڿg/p?7C ?>SŎ6 Ӷ?'P9z^3տ ΂?&1yA?(+_RmYп}"?ƟlW?P),H,bſ?@??c\5jӿ=Mpm<?c+?'Z4e-CS?F,wʿ(F_e?X2CQ? ُ㈏wT¿/VW?#(7? LhC!߶c(y?-˶?X1Uuɿ?Y.?PB?_CN?Fn 棿 c??-[6N}X?]݃?8C8C\3&<-DT!?\3&-DT! \3&<-DT! @UUUUUUſ333333m۶mۦ颋.?333333?qq?UUUUUU?ONđ?m۶mۦ?$rxxx????9B.@׽2b 78C8C\3&<-DT!?UUUUUU?333333?m۶mۦ?颋.?333333?qq?UUUUUU?ONđ?m۶mۦ?$rxxx???9B.@׽2b UUUUUUſ?UUUUUU?*llV4V>>m0_$@8C`a=`a=@T!?sp.c;`C>m0_$@8C`a=`a=@T!?sp.c;`CoNo\oxoooooooooppiiiip j otsj0g'CoCreateGuidole32.dllRegOpenKeyExARegQueryValueExA[RegCloseKeyADVAPI32.dllMultiByteToWideChar SetCurrentDirectoryWFormatMessageWaGetLastErrorCopyFileWWideCharToMultiByteGetCurrentDirectoryWGetStdHandleWriteConsoleASetConsoleModefReadConsoleAGetConsoleModeGetCurrentProcessGetProcAddressxGetModuleHandleWEGetFileAttributesWFindFirstFileWFindNextFileWuFindCloseDeleteFileWLocalFreeMoveFileExWRemoveDirectoryWtGetModuleFileNameWGetConsoleScreenBufferInfoSetConsoleTextAttributeKERNEL32.dll@CertFreeCertificateContextCRYPT32.dllGetFileVersionInfoSizeAVerQueryValueAGetFileVersionInfoAVERSION.dll:WSAIoctlfreeaddrinfogetaddrinfoWS2_32.dllCryptReleaseContextCryptGenRandomCryptAcquireContextWCryptGetHashParamCryptDestroyHashCryptHashDataCryptCreateHashsGetModuleFileNameALoadLibraryExAFreeLibraryFormatMessageAMoveFileExA2SetLastErrorSleepEx}Sleep1EnterCriticalSectionLeaveCriticalSection`InitializeCriticalSectionExDeleteCriticalSectionGetTickCount64GetSystemDirectoryWLoadLibraryWVerSetConditionMaskVerifyVersionInfoWaExpandEnvironmentStringsAWaitForSingleObjectExCloseHandleuGetModuleHandleAIsProcessorFeaturePresentIsDebuggerPresentUnhandledExceptionFiltermSetUnhandledExceptionFilterGetStartupInfoWMQueryPerformanceCounterGetCurrentProcessIdGetCurrentThreadIdGetSystemTimeAsFileTimecInitializeSListHeadTerminateProcessRtlUnwind_InitializeCriticalSectionAndSpinCountTlsAllocTlsGetValueTlsSetValueTlsFreeLoadLibraryExW-EncodePointerbRaiseExceptionSetConsoleCtrlHandlersReadFileCreateFileW/GetDriveTypeWGGetFileInformationByHandleNGetFileType"PeekNamedPipeSystemTimeToTzSpecificLocalTimejFileTimeToSystemTimeYGetFullPathNameWSetEndOfFileNQueryPerformanceFrequency^ExitProcesswGetModuleHandleExWGetTempPathW+DuplicateHandleCreateProcessWCreateThread_ExitThreadFreeLibraryAndExitThreadWriteFileGetCommandLineAGetCommandLineWpReadConsoleWGetConsoleCPEHeapAllocIHeapFree!GetDateFormatW GetTimeFormatWCompareStringWLCMapStringWeGetLocaleInfoWIsValidLocaleGetUserDefaultLCIDTEnumSystemLocalesWFlushFileBuffersLGetFileSizeEx#SetFilePointerExLHeapReAllocBGetFileAttributesExWSetFileAttributesWJSetStdHandleCreateDirectoryWGetCPInfoGetTimeZoneInformationWaitForSingleObject<GetExitCodeProcessCreatePipe{FindFirstFileExWIsValidCodePageGetACPGetOEMCP7GetEnvironmentStringsWFreeEnvironmentStringsWSetEnvironmentVariableWGetProcessHeapGetStringTypeWNHeapSizeWriteConsoleW DecodePointerDN@   $ dTTTTTTTTTThTTTTTTTTT.. II@T@T@T@T@TTIIIT8TC I IPSTPDTT؃T abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`y!@~ڣ @ڣ AϢ[@~QQ^ _j21~uGFFF׿GFIP@PA A0A@@@ @@@@@@@@`@@@0@`@@@ @@@`@@@@@@@`@ @@p@@@@@@@@@@@@@`@@0@p@@@@@@@P@@ @@@P@@@ @ @p@@@AA@A@P@`@@@0@0@`@@P@@@@@@@@@P@`@p@c@X@Y@Z@B@J@ K@K@K@L@ M@I@J@J@`F@G@G@H@D@ I@D@E@R@T@Pd@@X@X@c@0Z@a@]@0_@>@0`@0R@N@ P@PP@pQ@P@PQ@`R@xS!SS "S@ SS5S EMI.?AVbad_exception@std@@I.?AVexception@std@@I.?AVtype_info@@0 H`} L0W112X3`333344;4 5555]5d5^77777[:::h;l;p;t;;E<< =o? t000>111111111u22*3x33`44F55&667~8B99:V::;;;;;D>\>>>8?=???0\00611233j3{33r444455586N6667k77+8889\:::q;;;U<<0?\??@l*0=0T0b00101D1T111?2u22223*3;3[3333L4f4y4&5 66M788>99):\:h::::5;;<;=>9?A?p???Pl 002333333_55K66666777c88::U;q;;<[<`<<< ==;=B=V==========2>? ??`\>0333334 494445'67w777788899h:y:::;Rz>\?t???p040\01Y111111@2^2|222[333o444x55555556666666677077777/888999999::&;;;;:-???&0x00.112P2{324y45.6 77778A8L8R8c8r8{88888m9999:':2:8:I:X:a:f:w::::M;^;k;;<\J>>??+???Dh01g22344 555<66667?77 8888$9;1;%<==?9??\*0Z01265786888Q;X;;<<<<>>>>>>> ??)?7?I?W?i?w???????'0D0y00001:1o111112222233%444D55@66"7=7778,8 9w:::;;-;?;_;q;; <6X>>?d0N0j00000(112x22223;358?8U8_8u888888F9v9 ::":K:X:p::::::U;;w===:??@p0 181V1>2V22335)6>7E777/:6:X:\:`:d:;&;<;@;D;;8T1/5568%:P:}::<> >$>(>,>0>4>8><>@>>??H001H144r6y6666667777778$8888888888888999 99999 9$9::;;7<<<@=b=k======>O>s>z>>>>>>>>>>>>>?????40700,1;113 4444b5556 99B9:v;>?D4!445566666678/8888$9P9:(:e;=P22233%3<3@3D3H3L3P3T3X3\3`3d3h3l3p3t3x3|33333333333333333333333333333334:444444555::h>`P000000000{222688888888!;(;];p;z;\<`Q>>p 012^3p4{44F55556t6x6|66667w8::::::::::::::::5;;;;;;;;<<< <<<>V>>>?;?[???\ 000&1I11111[2n222233V4]4m4445666666777 7778!8e8r88888`a2h233333<44t55o6666788989H9L9P999:: ;;K;f;z;;;;z<=?k?y?~????D11533366&6/6L6P6T6X6 77899:_::v;;]>>0!0.0#1[2b233M4455_66 888899;111111182n2222334L44i5+66677c88809U9s9999%:8:Z:a:::: ;;T;`;d;h;l;;;+F>t>8?C?[??\00%111322@3333G4r444445-5n55t6777899$:f::D;`;;;;<?*?d0*1C1P1]1h1m1 2222 515l66L7^777708X8q888899\9999:::;;;k<<==Z>b>]??x_0r061\1n1122293j3333?4d44;555b666 7b8889:;U;u;;;;"L>t>>>`K01(1w1111M2k222333454F44O5 67,7l777778808L889::.::L;^;;;< <= 000234404555A66666777777777777888::======>>>> >$>(>,>0>4>8>t>x>|>>> ?K?V??0@"0'0K15 5N57d8819S;;;;;>>?@U0a0000000122j33455566 6$6(6,60646866629A9P9_9q999999999999999999999999::<Pl#212X2f2r2222222222^3y34567}7758^8k8p8|88888888888(9^999S:::g;>W>7?V?`h 001'1X3;4E4a667A888!9999 :B;;;;T$>\>>>>>>1?W?????p0l0t0000131b1s11111)2q2222203h3333448555S6^6o66666#787\77777%8F8S888899J9r9v;{;== >>>>>W??0011111111-2222223455545?5556G6M77778!8>8b8g88?9P9p99999 :p:u:::::;;H;|;;;<,?>>?$?z??T0:001z11112n333*4z444D5z5546n667z77;8:\:r;_<<<==>\>??`%00.1111y22/3L3{3444,5N6S66677777l89999.:G:`:::;;*<6>=>D>P>Z>d>i>>>>?}?,^01G11v2R5_5'6!77788<<<<<H2E4T44s5O7899;;;;;;;==>>>>>>>>>>>??x0000111222222233333444 44444 4$4(4,4044484<4@4D4H4L4P4P5T5X5\5`588 8899::::,001013K3m33466777 88>>pW0m00000000000000112Q3?566h7k888f99!;H;<< <$<(<,<0?XO0@1D1H1L1P1T1R3y333444M4T44E5P5T5X5\5`536:6 7$7(7I9P9:::::;>> >>>o2t223555555555555555h7D9H9L9P9T9X9\9`9d9h9l9p9t9x9:=>>>>>>>??(?2?U?\?h?r??????????T0 000070F0P0p0w00000000111912272I24y556i6);~<<<>C?[?x12e2246N78K9:::::::::::::::::::;;; ;;;;; ;$;(;,;0;4;8;<;a;h;u;V=`=j=====&>646'9 000434>477>>>>{5553666688 :::];j;<" >>>>">)>.>L>S>f>m>t>|>>>>>>>>>>>>? ???"?,?6?A?F?Q?W?a?k?????j0y0012&223333 4444#4)4/454;4A4G4M4S4Y4_4e4k4q4w4}444444444444444444444455 5555%5+51575=5C5I5O5U5[5a5g5m5s5y555555555555555555555556 66666 6$6(6,6064686<6@6D6H6L6P6T6X6\6`6d6h6l6p6t6x6|666666666666666666666666666666666777 77777 7$7(7,7074787<7@7D7H7L7P7T7X7\7`7d7h7l7p7t7x7|77777777777 888'818;8E8O8Y8c8m8w888888888888889 999%9,939:9A9H9O9V9]9d9k99999999999999999999999::: ::::: :$:(:,:0:4:8:<:@:D:H:L:P:T:X:\:`:d:h:l::A;L;;;;< << <*<4<> >>>(>2><>F>P>Z>d>n>x>>>>>>>>>>>i??????????????\ 020=0T0X0\0`0d0h0l0p0t0x0|000000000000000000000000000000000111 11111 1$1(1,1014181<1@1D1H1L1P1T1X1\1`1d1h1l1p1t1x1|1111111111111111111111111111111R22222 33333H3d3y34f44444444444455+5=5E5Y5t55555566G77K8889a;<<<<=== ======>?H0,1,2v223~34.5`55k6 7:7M7m88!99E:2;u;;> X0'0013444`5556e77R8j88888888888888888888s;<E?n????@pz11111112b22222o444F55555616|6666667N9X9j999995:G:::`>r?Px05001_1{11111Q2222233)3b3333 4/4h4r4444k556t6667e7w77{99::;;;%<=#=0=Z=/????`00u11 222%3r3333\456(6/666J6d6y6607E7Y778)8x89y999 :1:::::{;;;;!<..>G>`>>(?6?p<1148]9(;)=0=A=Y=====>(>W>c>{>>?%?????? 0Z0j000112(242@2L2X2d2p2z222<3334454b4z444f55566717^7v77778-8E88888F9^9r::;;I;a;;;;;^<<<<==U===== >$>Q>i>>>>>:?R?????(050b0z0000111I1v111122E2]22222(3@33333 4#444456667777777777777777777777888 88888 8$8(8,8084888<8@8D8H8L8P8T8X8\8`8d8h8l8p8t8x8|888888888888888888888888888888888999 99999 9$9(9,9094989<98:<:@:D:H:L:P:T:X:\:`:d:h:l:p:t:x:|:::::::::::::::::::::::::::::::::;;; ;;;;; ;$;(;;;;;;;;;;;;;;;;<<< <<<<< <$<(<,<0<4<8<<<@l>>>?#?/?`060O0h0000000101I1b1{1111112*2C2\2u2224n45 569!:+:0:R:x::::;;01111z2222D344455N55556-6S6666667=7e7778 8m88888899,9=9V9g9t9{999999;;;;;<-<2<\,>>?f??Y0a0j00001D1T1111202L2k222222333E4425555#656V6b6h7777778<8e88f9999999h:::*;;;;;<<08`8888,9~9:,:L:[:{:::;;1;7;G;];;<<Z>d>n>,000>1}11122N3\3333344445556x677888888$9v9{999':7:::::::;;;l;;;<>x>>??1?;?K?]?g?w???00101<1H1T1`1l1x11112L2Y2u2222#3)3D3J3r3333444z5555555556'6<6t6x6|666666666@7k7777488:; ;;h;};;;;;<$<<'>.>[>b>o>w>>>>7?????0&0J0Z0001122q2222 333333374>4555|6678888 8$8(8,8084888<8@8D8H8L8P8T8X8\8`8d88888888888888999 99999 9$9(93:c::::::::;(;4;G;O;f;n;z;;;;;4<=>?/?=?S?]?x???? 00 0F0W0012:2^22222233(3335566666(7177777'8888979G9S:g::::::;IH?L??????????????? @0D0H0L0P0T0X0\0`0d0h0l0p0t0x0|000000000000_1l12.4;45o8:e:;;;;;;;;f<<c>>>?0l 00|000343G3c334[667788}::::;+;h;;;;;;;;;;z<<<<<<<=>E>r>>>>??@T1!1&111#3,4{556>666W788,999;;b;;;>>PT.0:1113'3K5X55#6>6X6n666 7_7z77728;88B9[999/:e:::;F;==8>?`<n0"1514,5\5555?6662797L7o8;9:^;==?5?J??p+0O0000001I1m111I2]222222C3z33384444444456667p7}77/8N8S8889999::0:5:f::====>>>I?]?d???00$04072@22s333%4T5y5555<6607?7777778K8889D9999:9:::;;;<<3<[<<<< =^=t=====>2?T?~?0d000111_2c3~33314k4}4444455555566[6z66666,77_8888 99;99999!:(:/::::;;<<=C=z==d>>>??d 0C0t0011H222233 484 556 666d666 7a888q99::;;;|<S>>>g??x0+0r0001d111112U2y222s3 4445-5v561788b889:=:c:{;V<<=I=Y=t========>>;>m>>>>7?V??0X000001c11111122'2F2222$3Z3a3m3333333(4/4_4 6666677(7-7:7o7t7}7777F8i8n888 9%919Q9999<>>F?i??0j001=1111J2w2222223M3334W4p44556 7797B7$8:888:D:M:R:[:{:: ;\;;;;;<<< <<>>>?=?w??011E1L1g1222L3Z33l44q555555 6&6b6r6666677V777 888919C9H9N9\9t999|:::::;;0;s;;;;l<=3=====????F0N0W0a0r000161111113?3K333o44444478 99%919=9O9X9s9x9~99999: ::::;%;>;[;z;;;;>X>b>>>>?9?T?X?\?`?d?h?l?p??20h000 121E1"2C2O222!3w33333.4\4444M5~555556(6G666I7X77778G8n888;;;<??+?g??? 020000$1U1b1w11111[22e3334Y444445P5^556P6|66666777f888@9f99999 :X:e:::%;>;c;;;;;R<<5==*>0>E>Q>_>y>>>>? 1233333333-445~5556'6Z66667A7U7\7778&8B88888Q9|99I::::p; >>>??+?:??0 00+0001L1a1111 2212C2V2g233'363L33333344'4J4[4l4~444455V5z55556#666M66%7@7m7777778828B888889%989T9999-:;:R:`:y:::::::&;m;;;<,<<<<<D>>>?#?3???M?_?i?????????@00%030I0X0f0r000000000 1?1D1W1a1n111111120252H2R2~222222 3>3C3O3_3o3}333333!414L4y4455x555506k6p66666677.777<7E7\7g7z7777789999:::::%=G=L=====>>%>i>o>x>>>?$?0?Y?w?P0 00#0*0M0000000000011122233344 4T555556,616>6q6666666$74797F7w77777778'8,898j8z888888809d9v99999:B:Z:h:u::::(;8;H;o;;;;;;6.>p>t>x>|>>>>I?u?????`0 0000!0'0-0B0W0^0d0v00001$1=11102[2p2u2z2222233334444445'505>5G5X596Y6c66667!7>7777778 88 8j8s8y88888888889 9)9/959;9A9G9N9U9\9c9j9q9x99999999999999.:4:::@:F:L:S:Z:a:h:o:v:}::::::::::::f=>?p[112212>2`222P3t44455I5j5x5~55555566.6?6K6g6666666667727X777777788&8+808K8U8a8f8k88888888888999"9-9P9b9n9x9}999:: ;;r;~;;<>Ht0000a22222223K3P3T3X3\35666%9X;;A>>>>>> ?/?@01D333e4556D6W6u6618h8o8t8x8|8889 9$9(9,9;;LU0]0d0112E2W23*4.42464:4>4B4F44>5B5F5J5N5R5V5Z5u>|>>>>>>?P;3T333 44Z5!8;8J8X8d8p8~88888899#919<9R9f9o99 :::<<<=|[081W11122E2X2a2~222222%3,333:3G333333445555a555D6L6^6c6666667$778h9:F;<=>K?P?W?}??u00002n45(34S555l678k888T9:~;[>?H00172;3344155626M6657y777789: :1:<,<<==>>><01!1W111111)25577 8!8;;K233&6::::M;U;R>> >>>>>4>? ?$?(?,?0?4?8?=E=W=k=s=}======>>3>?P(02388b:w::;<>2>>>>>n?`L^00000S44446A6L6667\77*88,99b:l:::::;e>pd'0Y0w000o2222J33335f6+7X777 8Z8879:D:Q::::o;;;;)<\<<???,0&0G000O1#227777P8X8]9e999Hb2W44444444444;;;;;;;>+>2>h>>>>??[????01F1111.272p2{2m4w444445666666666 77&7w77r89`9k999*:q:u:}::::::;;;";(;6;T;m;r;;;;;;;;;;;<+>>>>>>>z???D0M1122Z4q4667 7h77W889^9n9C;==>#>>?.?7???\?M0001e11d22222$33334*4n445&5Y5v55a6~6077788E8`888888$9@999:):r::;X;m<<<=@=K=Y==>8>J>T>x>>?,?U?v??d0@0_01K1g1111233333K5Q5w5e6o6|66666-7P7W7o7u77778899m::;== >;>>>??x{0000011(151N1g11111122/2X2m222222223353?3*8:+;2;=;H;S;~;;;K=V====Y>>>>?Q?c???D0$0I0s0z000000000011 11!1&161;1@1P1U1Z1j1o1t1111111111111111272E2Q2]2q22222343D3X3]3b3333333 4D4q44444444455(5-525M5\5g5l5q555556/6?6D6I6d6s6666667 7*7:7[7r777828O8T8Y8t88888889+9=9I9W9x9999999::S:::::::::: ; ;1;;;~==>.>>?TY0a0_1122335 88R8\88849:6:V:}:=;G;q;Z<<<<>?P?_?m???????L)000r0y0000001,1[1g11111A2U222f4m4446_77889C<R>h>t>~>>>>>>>>>#?c?k?w??????????00 000(050>0G0W000)141w111111222(222H2O2\2p2u2{2203;34444444555E5t55555 66666699:-:W::\;;;=>>?@H-0\00F2J2N2R2V2Z2^2b2356i9^:.;[;<<===-=8=J=U====>M?P8$222^3h3@6s66\7q78G8:<<>>>>?#?~??`T00H0p0000 1@1G1%343K33$5`55636<6X6d6o66666?7X7u7788;;>?p000122223)3t3{333333333;4s4466677[777777777777,8V889D9k99: ;l;y;;;;;;;< >> >/>>>>>>$?B?`?x???H014445)5;5M5_5q55555555.699999:M:<<<<&L>>?"???@00f0001233,4r4444 5566b6l66 77b77c8: 008%8\8c8;y<<<N>>>>>?P??x0N0061111K2L3\3m3u3333444Q4`4l4{44444<5E5N5W5555<66:778"8S8W9]99999:::(;;!?>??? r0z4 004080<0@0D0H0L0P0T0X0\0`0d0h0l0p0t0x0|00000000000000^111;2[22263l333333!5155555 656=6`6x6777K7[7g7p77778x8888888::3:;::::;);U;];;;;0<<<\1?9?A? 00(040Q0W0l0000R111112"2C2g2s2233344844444444Y5e5y55556696I6U6d6a7i7q7y7778 8!8-89888888899:":-:h:~:::::::::;M;;;;F>q>y>>>>>?K???? ~0000T111Q2e2}2222424:4G4<5H5X5d5555566~6668 8,888F8e8888~99992:z::: ;;;;?'?n?y???0 #050[0~00001'191D1j1u111111]2w222222333334515R55555 66'6R6666677+7788&888888999999:::::';/;7;C;O;v;;<<==r=z====>%>H>>>??1?A?M?V????@ N0[0g000001F2N2V2 33%313N3T3i3333^444444 5+5O5[556666(7y7777778%898E8Q8888899"999 :: :[:q::::::::::@;;;;9>v>~>>>>>?L????P hn0v0011`1-2A2Y2a2223(404=4 55%515N5T5i5555Z6p6666)747F7777777 888 999999` 222222222222233333(4,4044484<4@4D4H4L4P4T4X4\4`4d4h4l4p4t4x4|444444444444444444444444444444444555 55555 5$5(5,5054585<5@5D5H5L5P5T5X5\5`5d5h5l5p5t5x5|5555555555555555555;;;;;;;p h:l:p:t:x:|:::::::::::::::::::::::::::::::::;;; ;;;?????????????????? 0 0000 0$0000000000000000001111222 22222 2$2(2,2024282<2@2D2H2L2P2T2X2\2`2d2h2l2p2t2x2|2222222222222222222222222222222333 33333 3$3(3,3034383<3@3D3H3L3P366666666666666666666 66$6,646<6D6L6T6\6d6l6t6|66666666666666668888889 99$909<9H9T9`9l9x999999999999:: :,:8:D:P:\:h:t::::::::::::;;;(;4;@;L;X;d;p;|;;;;;;;;;;;<<<(<4<@>>> >(>0>8>@>H>P>X>`>h>p>x>>>>>>>>>>>>>>>>>? 8899 11 11111111111111111111111111222 222 2$2(2,282<2H2L2X2\2`2d2h2l2p2t2x2|222222222222222222222222222333 33333 3$3(3,3034383<3@3D3H3L3P3T3X3\3`3d3h3l3p3t3x3|3333333333333333333333333333344 4444$4(40444<4@4H4L4T4X4`4d4l4p4x4|444444444444444444444455 555 5$5,50585<5D5H5P5T5\5`5h5l5t5x5555555555555555555555566666 6(6,64686@6D6L6P6X6\6d6h6p6t6|666666666666666666666677 7777$7(70747<7@7H7L7T7X7`7d7l7p7x7|777777777777777777777788 888 8$8,80888<8D8H8P8T8\8`8h8l8t8x8888888888888888888888899999 9(9,94989@9D9L9P9 ???????? <<<< ,=====>>> >>>$>(>,>0>4>8> l2p2 4181<10 >>>>>>>> 4444444444 :@ L3 T9X9@ 55p 0000000 1111111|222 66 66666 6$6(6,606 000000000000`8d8h8l8p8t8x8|8888888888888999999::: ::::: :$:(:,:0:4:8:<:@:D:H:L:P:T:X:\:`:d:h:l:p:t:x:|::::::::::::::::::::::::::::::::;;; ;;; ;$;(;,;0;4;8;<;@;D;H;L;P;T;X;\;`;d;h;l;p;t;x;|;;;;;;;;;;;;;;;;;;;;;;;;;;;;<<<<(<,<0<4<8<<<@>> >>>>> >$>(>,>0>4>8><>H>L>P>T>X>\>`>d>h>l>p>t>x>|>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>??? ????? ?$?0?4?8? >@>`>>>>>? ?@?`??????`T0 0@0\0`000001 1@1`111112 2<2@2H2T222223(343P3\3x3333331111 1$1(1,10141@1D1H1L1P1T1X1\1`1p1222222333383<33344p9t9x9|99999999999999999999999999999999::: ::::: :$:(:,:0:4:8:<:@:D:H:L:P:T:X:\:`:d:h:l:p:t:x:|:::::::::::::::::::::::::::::::::;;; ;;;;; ;$;(;,;0;4;8;<;@;D;H;L;P;T;X;\;`;d;h;l;p;t;x;|;;;;;;;;;;;;;;;;;< <@<\<