MZ@ !L!This program cannot be run in DOS mode. $/qAqAqABqAD~qAEqAqADqAEqABqA@qAq@2qAIVqAqAqqACqARichqAPEL{a T gsp @@T00@Up@@p .textS T  `.rdata p X @@.datap@.rsrc00@@.relocU@V@B`)UUQSVWUMGȋ7;vG4v;F;wjV芕؃GtPwSĀwG_7_uVuP蝀 w_^[]Uj 襱U@@J AB ]UQVuEWPjV ΅t<Htt3 u3_^]j2UQSVuW=(ySt @vEPjV t]]33SHtt3 00t S׋XjIG3_^[]j1UMVHtt3 00vVFF3^]UW}}ȋAtt3  AtDQ| ut5| ut)VP裄w P@VWG ^z &IO @@AGG x ~__]U 3S]VWj({jG<$FFG@w@F F(yS ,ySFNFC 0@GCC x ~u^hISFF2tQI)K @@ACC K x ~ #^K j @AC SjSH?,@$@@@ Gl @D$ QF 3F$9|$ 3ɉL$F$ˉD$W3ɋ׃QRiK T$C L$C y~AxtF9tFL$G L$;|$ |_^[]jF 7F$_^[]f3@B@;@@USVW|$H?a@$@@@ j D$QG蚬3ۉG9\$,3ɉL$GΉD$@3ɋӃQR1hN F ΋~ jj hF Ht,t3(ЋvFx ~[~L$΃F ~ bjjgF @Ht,t3(ЋvFx ~3[ L$A΃F ~ jj!gjVF /L$ A ΃F ~ jjfjVF L$0 A~ ~ ItFI:utQ:Puu3uD$@D$~ L$G|$CF L$;\$3_^[]jGbG_^3[]f|@@@@UMSVHtt3 00^~"W3F t踩 u_v 褩3^[]UE xSVWqC{ D$+L$ C C up֋~K @@ACC x ~XEuC P~K @@ACC S x ~ XS fCljfCl`@tuvFHt,t3(ЋsCx ~9X:utN:Huu33ɅL$t$SD$_^[]Ë:u&tN:Huu33_^[]3_^[]UQSVڋW\$ f=(yS@<CH?wq@$@XX eؿ;rBfDjW,cN T$ F QF uG;v3_^[]ø_^[]Ã襽Ht(uыЋ|qFx ~VrtS_^[]Ð@@@@U$SVuWID$ |N @@AFF ~ x ~ V~ ׼W=cG輼Ht,t3(ЋpFx ~U腼F IΉ\$ l{N @@AFF ~ x ~ fU~ 7WbGHtt3 88F ?|$ttu 3_^[]ËNhIjjI( aЋhI譻Ћ333ۍJ\$T$D$;WW 33T$,3|$(D$$;BZT;߅{t|$ uT$,3@L$ "zN @@AFF ~ x ~ T~ WSaӋGSF {tL$;C DʉL$K L$ D$ t{ tSЋ3F @F ~ TOQ΋'WN t)AӋΉF N uy~ 뿍AF K A3ɉF 9K L$ D$$|$(@D$$|$(u%T$,T$\$B|$ȃ 2T$\$BD$ |$T$\$!|$ L$ t 3҅DʉL$ V 39L$ _ BF ^[]UM f. `YTVW}7D{tع4GRPg^N jF ΋F E@F F @F 3 tu_^]_3^]UMUVu uV^]USVWUG @G @iO Q9UO jAjWG ˿ uG P6U؃u E3U0jtUЃuS|UEU30qBuEU0UF΅t ȋAuEQU03AG _^[]jz"UL='USVD$ X@WL$@@ @uhCDO'U|$ u_^[]~IL$XIIfD$XD$`AIuIIjAIjVA? Ph'Wx jj4Wk jj+W^ jj-WQ Sh'WB D$XPh"'W/N I(hIjjx[ЋLIuN @@AFF ^ \$x ~O^ \$EtOL$3PQQ׋ 趵=(ySt@t>\$ jjQS{ jj@Sn "S[N xt뫋\$ ~ E~ YЋJ=(ySE@<7GF U΋~ OQ΋QN jAjVF ~  Iϊ:utA:Buu3uQ觴=(ySt@@<u6F΋V |$W+7h''SL F :INJ:utP:Quu3uR&=(yStA@<u7|$Ή7N hعVF }-GF I:utP:Quu3u Ph'Sw F e0I@:utP:Quu3Ixu D$8T$8texu#,D$ Pj S F T$ zD$ ,Pj S F 8INJ:utP:Quu3腱xu D$@T$@tkZxu&,D$PhS F T$-D$,PhS F DIf:utP:Quu3蹰xu D$HT$H,te莰xu#,D$(PjQSQ F ?T$(dD$(,PjQS F TINJ:utP:Quu3xu D$PT$Phteʯxu#,D$0Pj@S F {T$0&D$0,Pj@S[ F IdI:utO:Huu3u3jVt$jjV踶 ;Ph'S F AF } tK׋=(ySt;@<u1D$׋Ή0ʮN hعVF B(L$A}t>׋蘮=(ySt.@<u$t$׋D$0h''SF t$Vh'S3 h @h+NS  >t/jj+S VhI'S h@hXNS _F^[]jjjjUQS‹VWEt57w|UW|Uu܋EtM_^[]UEPju uip0ܕ]UjjjuhtIuUju^ 'UA@"t@AAX+@AdAhAp ]SVڋW虬Ht,t3(Ћl`Fx ~Eb8Ut,PhIjyP jfPԙWhIjMP j:P訙F _^[UQVu٫Ht*u0Ћ_Fx ~D褫hIjVL+ tVyȋF jF V fFlfFlA=(ySt Ht@#=(ySt@4pIhIVϵ jPVV2^]U SVWT$ jGw +,@+FG SWB ='Uh+@ju3 Ӌy+G L$ W Au+щt$T$+W PRD$@P D$ uOW 9QsQjj萡jSW輬D$ G _^[]UISVڹIWDNPjjI(OЋ赩Ht(u*Ћ]Fx ~B肩8uۿIIDj藓PW˛j膓 PjsPD$hPD u_^[]ÃF L$QDAu+t |  uID t&|$=uD$Ph IV讳 _^[]ÅuIgQT$!gN @@AFF x ~A_^[]UVWTHt0t339Ћ%\Fx ~EAxuHH jD$ D$ h8IPhW@VL$ &SΧHt+;6Ћ[Fx ~@蘧xuPP  I@:utP:Quu3F 3ҋ6I"fN @@AFF ~ x ~ @~ ΃O;s  ;r;sfD;rFx 1?%_^]UVWF9N sfDF @F 9N rN .u _^]ÃHt,t3(ЋYFx ~ ?Ph,IV蟰Ѓ z BujD$ +h8ID$T$PhW@VؽujjV% F F jjV ǃF _^]UUVuWD$ UuW3ҋ/׋QFN +qNh@IWjI(JЋ~ ΃认O;sD  ;rV ;s;rV FjD$+D$+ыΉT$+V RP@  Ht,t3(ЋWFx ~=PhHIV訮 U t,QhIjPS jۍPIWhIjP' j词PBF9N sfF @F 9N rjN ePhI蕕jP P辐D$U3_^]UEPjuu upQH]U]U$SVuWjjVD$D$  hxIPI؃΅uU|IYaN @@AFF N 9X ~ T;N YTAF _^[]ÿ=(yStH3ET$P3EP3EWE tXjjPW Sh'W h 6@h+NWp D$D$Ph W" T$SǟD$t0L$,QPhI$<hP/$0I`N @@AFF x ~:t$(/fnD$F _@F ^[]j USVuWD$ ׋膠=(yStH3ET$P3EP3EW jjPW 8؍D$ Ph W T$HuMD$΅u I^ T$ PT^N @@AFF x ~8IO @@AGG w x ~ w V&FG pu G _^Y]jjW ƃG _^Y]_3^Y]UVuW} 'F='Fw FN +uWV u_^]Ë׋N jF ΋V fFlXfFl_^]UU Vu~V PF ~xuPF ^]jT$ tL$F T$ ^]hIVU4SVuW} ߍ'F='Fw F^ +hISV ΅tZ~N jF ΋V fFlVfFl}@<H.}=(ySB@3$|]@׋}׋΃xuLs}xu@%jT$<u WfD$8L$8D$iG u+iV%ihIViuiDIG @G )O @@AGG x ~_^[]j=j/Uujuu [t }t]3]UQSVuWjjV|q EZjjVdq؃ Qjhb@t OAxc@UjiHt(u*Ћ^Gx ~~TiuIF QuhI@F VsOI|_^[]hxISfEu4OI|F ShIV@F s _^[]jPhn@WʂugOI|褜F _@F ^[]jfjXUCӈSVuWjjVo؃ #jjVo hPjSpIjhӅhPjWjhӅjPPDpIN uxPAF hPh@pIPjhpIjjhPhPjhHpIPWhIV#r_^[]_AF ^[]hIV\qV3jjVjh$I6 u A^jh,IQ u A^jh4IQ蟆 u A^jh33G @GG x ~ V)OSpI_^[]Ë]];\uC]j\S( t+FEt%+FPNVS؉ESm3E]NFu+EPhjSupI]3ɅEى]8MtEPN]EƉM8\HEȍEPjjjQSM pIE@PNNEPVjjuS pItVNE]֋#O @@AjxU`SVPhLpI3ۅÅtIjjh@PjPjhHpItu"V @@BFF x ~^[]^3[]US]WjjS8k V5PpIjjE֋ϋuAAuj+ȍEPQWu=TpI׍EPV`pIjV5XpIjEPhPu\pIuujEPjhIu׍hIPGƄ!K ^@@ACC x ~_[]jU$SVWD$D$PhjhIhIpIuPD$D$PD$4PD$(PjhIt$( pIt$pI|$ uD$0P.TD$jhILrInVfKWVjhITrILD$,PD$PhIWPrI.D$3ҋ}j jHwL$,H@L$0ωD$,N<ЀJBN@ V@BfBB BBySBG @EGG x ~[LI/ O @@AGG O x ~ )O fnD$$jAWG r\IO @@AGG O x ~ O fnD$(jAWG qlI}O @@AGG O x ~ wO fnD$jAWG cqxI$O @@AGG O x ~ O uYӋO @@AGG x ~jWp|$t SH_^[]_^3[]UVuI}V @@BFF x ~z^]UQVhIhIlpIPhpIt=EEPdpIPօt%U39E^J AB ]ËM^A @A ]U8 @VuWjjVAf hD$DPjWjhpIύQAu+uF @AF _^]ÍD$@PppIt N )D$PW蕌N uD$AF _^]jh\IV hVyUVujjVOe ΅t&/V 3Ʌ BF ^]jtU }VhPjRjhpIt&PppIt Ѓ^]3^]hIV_gV6yU }VujjVd tfhQjPjhpItTPppIN At F ^]F ^]jjh\IVfVxUQS]Vu W{u|~3j jj'O<ЀJBO@ W@BfBB BBySBF @EFF x VJC w[$@$IO0IH8IAHI:TI3`I,xI%IIII I3ۋ~3j j&O<ЀjjJBO@ ΉW@BfBB BBySBF @EF Fx ~ ۺIEӅuF PN @@AFF x ~hIZЋj]C $@C΅u Ie SPN @@AFF x PSuF Pԋ뼋CN AAQS~  B J J GWCV @ BB~3j j$O<ЀJBO@ W@BfBB BBySBF @EFF x ~Q3D$ 39CvS<:u`;tr+uI QЋeN @@AFF x ~jt$jV1lGD$ G;{rF @F hIXЋhκxX Qh_^[]f!}@(}@/}@6}@=}@D}@K}@R}@Y}@`}@g}@n}@h~@~@~@h~@~@~@~@<@h~@h~@h~@ @U4SVW}jjWw_ L$D$YL$9\uAT$ RhjQPpI\$ 3ɅEى\$\$  w3j j"N<ЀJBN@ V@BfBB BBySBG @EGG x ~;jjD$D$<PD$D$DPD$8D$LPjD$DPD$@PjjjSpI(L$9L$,GL$,D$AQL$@L$AD$Q@L$3L$09t$$vBD$jjjjD$(D$(PQVt$8pID$0WPL$F;t$$r3\$49t$(D$D$D$D$8D$8PSD$DPjD$(PQVt$8pIuQD$8WD$S>G G @G t$pI_^[]Q>S>ًG @G _^[]j6UVWu< IN @@AFF x ~uF x׋N @@AFF x ~έFx ~_^]_3^]U SVuWhIjF~ Nj+8I(|$ Ћ_`hI-TЋD`THt2t D$,ЋFx ~SD$;@ӋSHt+t3'ЋFx ~ӋS8?$u/u O BuH׋΅t$Au6C;\$f3_^[]ËӋSN F _^[]ú IN @@AFF ~ x ~ ~ ӋRF ǫFx ~_^[]ËF @@~ ~ kRjF V fFl辕fFl_^[]U rVW}jjWY tdhQjPjhpItRhXB;NQPtpIFO 1AG _^]j苼h$IW[WmUMVoQHtt3 00tP|pIV:3^]UqVuQȋAtt3 jjh4QjPjhHpIt:V @@BVF z ~^]hN uWhdIAF VY _^]AF _^]jUQSVW}T$ j;W؃u5uF X׋ N @@AFF ~ 9X ~G;Ë+u I  P N @@AFF x ~u~ HM IF 2 N @@AFF N x ~ ,N D$ uAЋ N @@AFF x ~Fx ~LHt,t3(Ћ}Fx ~sLN uAF t {n3_^[]ÍAF @@~ ~ LjF V fFlmfFl_^[]USVuWjjV]S؃ t|FN + |J׋K=(ySt@t!jWVS ΅t3PuFGN +;~3_^[]_^[]j8j*UkS]jjSR EhPP迁 uDC VW@C M0MVhQP7uhISU_^[]Í K @@ACC x ~[]jRU"jSVuWjjVQ Ch$PjWjhpI,$PpIt F @F _^[]@pIjjD$D$PhSjhpItTjjhD$Pjt$ jhHpIu#IfIfD$0D$ID$ t$ pI#IID$(D$~IfD$ F @D$F PWhIVSF @@F _^[]j³h\IVSVdUB iSVuWjjV P jjV P؃ h$"PjWjhpIih$PjSjhpIXj$P$"PpIt F @F _^[]@pIjjD$D$PhSjhpItTjjhD$Pjt$ jhHpIu#IfIfD$0D$ID$ t$ pI#IID$(D$~IfD$ F @D$F PWhIVQF @@F _^[]jܱjαhIVQVbhIVPVbU #gVuWjjV$N tqhPjWjhpIt_PpIN u!WhIAF VQ _^]AF _^]jh\IVAPVbU0 `fVW}jjWaM hD$j2j$UWS]VWjjS> 5jjS> ˅*V W PPpu I$OGuf IfOOuf3U88=t<Pxo=QhoU;u=/DGU=uu<:/u 1IN @@ANF y ~ NI(hIjjЋ0IN @@ANF y ~ 誹NI(h(IjjЋ0I[N @@ANF y ~ XNI(h8IjjdЋH0hDILЃuhLI9XIEЋN @@ANF y ~ NI(h\IjjЋ/VNI(hlIjjЋ/3^]U$SVWJHt,t3(ЋFx ~=8D$PjPpIPpIu D$ D$ D$ N hpIjjI( Ћ*|IN @@AFF x ~謷D$xEtDN 3T$PQQ`m S=(ySt@tM<xu%9V N xtjT$kt-\$F WhIL$_^[]ÃF̸U SVWjG @@_ _ G++KSW u3 Ӌ\+G W Nu+щt$T$+W PRD$@Pf D$ uOW 9QsQjSWD$ G _^[]U SVuWC @@C S fCl j`KfClI(hIjjЋ,׋VOdj tj6Ht,t3(Ћ Cx ~)jPS1 C @D$D$+C jPD$P=eK S 9QsQKhIPjI(Ћ'3ҋjuMfxu,_^[]ÍT$guW,_^[]D$,_^[]Ë_^[]U 0;SVWh$3PWڋpID$tfWWhL$$QP$,PWhHpID$|$D׋N @@AFF x ~衳_^[]ËF @@F F uxӋLN @@AFF 9x ~JhIauF xЋN @@AFF N 9x ~ N AD$D$@+F jPD$P:c =(ySt @ IN @@AFF N 9x ~ 胲N uyӋNN @@AFF 9x ~L@rF9x ~1Ht-tF 6ЋF9x ~8F F V5 IN @@AFF N x ~ 蠱N uYӋkN @@AFF x ~htPq.F ЉF uXӋN @@AF Fx ~Ht,t3(ЋFx ~ٰ8F F xUS]Vt{StmF S@@F PN @@AFF V x ~ JV fFljZfFl3^[]á'UttPSt)hItPSzS< IN @@AFF x ~腯SYN @@AFF x ~VJoFx ~:3^[]^[]UQSVWhIjNjI( Ћ!F^ I+N @@AFF x ~贮='UtkIN @@AFF x ~|'UuF PCN @@AFF x ~@hIWt[IN @@AFF x ~׋N @@AFF x ~ҭIN @@ANF y ~ 裭NI(h\Ijj诹Ћ ITN @@AFF x ~QI%N @@AFF ~ x ~ ~ F++˃| ыl$u QI@@GF Fx ~ɬhIЋ#F _^[]USVWT$j j3ҋ~O<ЀJBO@ W@BfBB BBySBF @EFF x ~\$ 9\$P}uF PN @@AFF ~ x ~ ī~ P׋nF zxu@L$D$ jT$_D$L$F PQjV%}j hI4 L$u!hfT$ j6j hIQ u3h.S j^\$E='UuUQu ZNI|:C_^]UQSVW}=(ySt@vjjW؃ 3ۺ=(ySt@vjjW_ 3tutqˍQAu+ʋ֍BEBu+U;rL+ˊ:utA:Fuu3҃O 3AG _^[]_^3[]jyjyUVW}jjW t[jjjWttvŠȄuG @@G _^]jyxUSى]CXCX{X@7C@2ҋKDECPVsHEW{LMUE@ErsEH 3 E3 3 Ur;(s33En85M3#3yZMUEUMŠU}‹EuMUP9K@MSDusHA@E‰}{L[PADEAXAHEljALE_AP^[]SVW~X8t2ҋ~X8u2ҋv2ҋm2ҋdVTWVTJVT =VT0VT#N@с Ћ ND ЋV@ Ћ NH ЋVD Ћ NL ЋVH Ћ  ЉVLVP‹  ʍF@ ~P_^[UD$S]VWPjS1 |$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 ~:_^[]jsUSVuW=(ySt@vjjVT؃ t}3ۺ=(ySt@vjjV$ t[3t>t:ύQAu+QWSI V 3Ʌ_ BF ^[]_^3[]j sjsVUybhSCSEȀ90tjPP u hS SEȀ90u3Ut#SSjPpI5pIPSjPpIP[^UEPjPpIPpIuEVuN QAF ^]UjjjuL{3]Uts'SVUEWDPV75,hIVM؋QQ`jP0H0MԋIEUȉM̅WEfEH }]Mĉ}1ЋȃjWS~  yM֍I }R}jeEEu td@ }HDPHA;rYz PEpL+u-E t @}W|_MyH}ALIDEU@LE@DB@@rEEBUr ;xrw;rtJF;MJ@Aut׃y ttF H @LMEM3VWS辞 tH83Vj躮PuЍh8SPt F _^[]ËV  ЃztʋF @@t(?_t@@tN_APGyPN A_F ^[]UQuU MMDY]U U SVW}D$xEt3uu ȃL$yu=G UQωUP@W BG PRT$l= G _^[]ËG @@t&St@@tOSAPCYPO AD$G _^[]UQU SVuW~ ؃ ׋ȉD$ r=(ySuT$ W?N A@N A@t0Zt&A@tNZAPBQPF _^[]ÍA_F ^[]UU SVuWwu~ u 襑=(ySu'E΋D$ED$D$PD$臏GN A@t0Zt&A@tNZAPBQPF _^[]ÍA_F ^[]UU SVuWMT$؉L$D$;=(ySuD$PN AN A@t0Zt&A@tNZAPBQPF _^[]ÍA_F ^[]UQU SVW},w ؃~u3vKt%tGG _^[Y]Ëppt> Qt'Ft!Gx=w ֋o @<$ ˆAV~G _^[Y]UU S]VW}{ E0WONVGFS B@t:u6ft-RBt$Ky=wnC _^[]ÊA<$ ĈFC _^[]UE M@VuWV +Ѕt`f~luYFHNEAfFnf@fFnf;rf;tbf;sc}W)uFfFn}fFlW,fFluFN 9HsH_^]hLSV##UE VuHfFlQ,fFl^]UU SVuWu3 +~ M V AE+щT$f~lVT$ BEBD$+F BF\BFt ~\ȿB"f#f fJ"fFnf@fFnf;rf;f;]΋T$S'u+EfFnD$ f!H"@F\3 +V D$]WRP@\$ ~1 uNV 9QsQ_^[]hLSV:"UTE ID$ "AESVuD$D$ D$ EfFlWv\Eȉt$$ED$\F +F PD$,L$dPD$D$ D$@D$HD$LD$TD$XD$`D$4D$<0v \$0|$(D$ jSWv3Ʌ}E)N t$DD$8D$LjD$DSVw3jE)G E\$lt$dxSVw3jE)G E$$xSVw3@uEË\$ )G fFluPF xrDNSjI(tO GB@t;uNy=w Bt^j_^[]UMA VxFuc@MMEp E EEEEE}F E uuE jPuUEE3PUE^]ø^]UE@]UE S]VW3s ($@F?_^[]ËN3N F?N+ȉF N_^[]3ҋU_^[]Ë~ ~ _^[]Ë~ ~_^[]ÊF?VN шE EF?u';O+щN ˉV}E F?7 ȍ;ȉM M+ЉF VC9x ~ }M E F?~I~=uC_^[]Ë~pEFp_^[]Ë~t(9MMMNt_^[]~?_^[]Ã_^[]á@@@@@@@@@@UMUUU VuWN Q莀EN _^]UE VW}| Ћ<'u#w IP>@@FG Gx ~[|_^]UQU VuV P#?F ^Y]UU tMA@A]ËE@]UUEJAJE ]UQMS] VWwsqCPj3辭N<OGN@~@_ G(yS ,ySOMGGA 8@GAA x ~T{G_^[Y]6UU VuWH?t2&u|U|tA;jIыN _F ^]ËM|Gx ;O =D G@DuN S_F ^]ÃtN _F ^]3_^]UU 3SVW}3ۋωESH?t1&MC;I3@uB ;p T @@U tuSG G t8O A@tfct^BtVOy=v=A<$ ĈC_^[]Åt3B@t+E;u!Oy=wBtd_^[]3_^[]UU M2ЋJ?t&t3]ËE]ËU MED ]UU SVW}UE4V BEuB9ujjتK N AN A;t A N B@t!A;uOy=wBt _^[]c_^[]̋VP r8tA+B0D^Ã^UU St]u33ҋMA@"t@AEAdAhÉQXAp[]UE@X]UE@p]UE@d]UE y3]VuN~V4@;t!IHuF4;tE^H`]3ҋ^]USVuWMG"y7ދ@ HG++;E _^S[]ËG3ɋWމE@ E+P0J9H ~&@uW D$AW M uv`t$BT$<u23t$щt$VuUjfu D$}tD$O G uWBG +O JjLu }0~&F 3ҋwj j@8D$N<ЀT$JBN@ V@3BfBB BBySBG D$0D$8@ED$ G @ 9p(D$0D$ʉD$QL$ L$Ps|=(ySu0D$ϋT$D$ D$D$$D$ PD$,Qz(D$4D$ F@ ;p|D$_^]ËG @G D$_^]USVWڋ]}U3ɋw B~\W@j\Wdj\[{ sjWVs3t$E)C ~ t#F4ΉFNF`΋V jP;jh8FPD$ pЃ_^[]UQSVW}_{ ~ cwj|jjvЃu29ыdj|jjvЃF |׍pCFFF FF0FxdžF=FdF`FHF@FDFPFLF\FXFTFhF8F FlFpFtdždždždždždždždždžt$jt 3_^[]UQEHI|~Y]UQSVxSW=xSD$ DXhIhعVmM S/ЋFHt8F F 8@F F uXӋׅN @@AFF V x ~ _V fFlj fFlN SF nЋjjVF ~ DSjjNF I(jkЋND$F D$ 8_^[]UQVt.tF @EF ^]j,S蘂 FM@@AAF ^]UQSVW~0u+~^W|z0t0J AB F @w|~0tՋF0jXDF0Plxt&v Ӌ;FN 9HsHGxVЃU`AnEA0EEVA0EjPUMENuu 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`~ r=y t:WQ z t+jj$TMfCy 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"_^[]úvC\hIVUQSڋVWUBp{ t:t(u+r jUCJ @ΉBCM@BM3CBt9U ;=~"+΋fff@D@uUz _^[]3ۅ~+΋ڍ@D@u;}ȋË+f@u롃} (ySEz _^[]Ë} ~+΋׍@D@uU3z _^[]USVWG?@$&F+F YF+~ ߃x ~[YN`@BfV  +V @B=@BO;M;W\~ j׋ЃJF ;vHI;wF F G?0^ +@ KEPF+F U;iF+~ }x ~ XUN`@B NjEF+F =@YF+~ ߃x ~7XN`@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;s?+Ћ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[]ú*hDS׋|ChIVeUVWfFnf@fFnf;rf;t1f;s2uu8fFn_^]hLSVUVufFl~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 zO FA@rFG wG4;_^[Y]AQA AAAAUQE SVuWV ~+Ѐ~u!jup_^[]FGF G"tajVy_^[]ËGtwjVЋV ؋˃ +SR׋FjV;_^[]U SVW}GlD$Gu>G49GtA`SEϋw +w w@@FG _^[]<tSċE tf@nf@fGnf;rLS럸fGn3AfGlύEPuD$D$ u  fwt F"u4vuw GF^_ rD$t$t G @(j,St G@@CCwG ϊF"$Gt3fGlFAG\ύD$ PD$D$ %8j,SEt G@@FGNO HD$ L$fOlfOn_^[]UM3f9Al]UMVfylqv A;H|tNAA+A F"Ft3^]ËEFtEFU A R+ºhSQihSQ^USVWuGw\EGtEGlEEuG\N؃tEw u pVӋtG-D$Pw GwЃ L$IG@ىG~4tjbW/[V86 @t=t SEB}L$D$$|$t$ ;jT$L$ T$-oG t$0@FGO +:G`=@BR+O Q@B;O;M;ы:$O AωG ojЉF L$ tM~4t"jtW=ZuuWh4ShS}FSv8PFP[D$38^v}NL$@wjjjvЋȃu(9tXPeNjjjvЋȃt8F ACA@D$D$D$@;|_^[]úuWh,ShSVJl ChIWJUASډ\$VWuQ |_^[]$<xuxx XT$SetL$+T$FL$T$-T$ctD$+D$FL$ 3G;u@u!T$L$D$ _^[]ËD$ D$_^[]_^3[]U4SVW\$~|$8F$<)xuXX T$ ȉD$Udt +t$L$ FT$$L$0T$4|$81L$T$(btD$(+t$D$0F|$83C;t$0X\$D$0D$0$i \$(T$(f.ŸD{EtX~XYTf/YTrA YTf/v3(S_^[]Ë\$NK_^[]_^3[]UESVW3uP֋xȃy(HtyAusC3wȃtZQƒ<t4Et3U Vxu G}GE _^[]ju ыuVx_^[]ËE _^[@]h_^[]σ =@w#ruӋ3f/_^[]f/YTsf/YT+;|;_^[] u3f/_^[]f.ɟDN>L$  =@w&ru ы 3f/_^[]f/ YTr3_^[]f/ YTv(9T$ |;r3_^[]Ãu"F$<u 3Ʌ_^[]jw ӋVcs t%G Ht8w3_^[]ËGjf H"w Ss tJG Ht&u8tGf1H"3ҋ_^[]ËO_3^f1A"[]ËGVf1H"5U SVuWVƒ?O?;tvO;u^uYujT$t9|$\$~uFjT$tD$L$;u;t.3_^[]Ã1A$1A;uڋG;FuҸ_^[]f.3DKʋ_^[]Ë6;t͋J ;N ur;ust:ltB:F[tB:FJoB:F4;Z$It A uCnuvH>;It A uCrnu6HA CP@njs ЋVWoC Hf8T_^[]Ë3;_^[]Ð00A1A<0A 1A0A"0A[0A1AUDSY VWT$L$ fCtuXSƒtuFSZSL$ DCxu}C-$SHZCsD$$jpmxuS\$ jWm\$ xjVt$,VCn{Dsuxu CSzuRR T$|$9|$~PFt u@YxuHH T$;tGL$ T$|$;|$|+؉\$ (wr|$D$$\$$xupp VPD$0P^]L$( IރL$ɋD$T$(L$ \$ |$P_cL$ BPj3ҋyw8pȃG<$L$$AAG@D$O@|$qAD|$3A \$fxupp VPAP\L$( IL$ɋL$$Ƌ\$ |$@@CL$ Y T$++߉T$Y T_^[]ËL$ hSQt$$USVW}ًG?t7tjjxF@ FF_^[]ËEHt9Au3CCjtjVWWЋk_^[]ËEJVF_^[]Ë_@VF^[]hS׋Ud0ZTWSVW$P|$T\$0OfI"L$(Dqt$D$P@ @,D$,AD$D$t$L$OpT$ GhwutGdD$ GhL$D$ L$F"@t%fF"|$ tj;L$ tmN@ P0+T$HIP8t D$D$t&G9Fvt +D$HLD$;tD$PFG$\$0T$D$(pt$ȉD$L$H?t$ -$\AT$T$,D$T$L$,bFt$D$K9NJIuD$PDL$PDD$Ht T$, T$xET$t3*FxtD$\$0t$T$PVRT$T4 D$(\$0pD$t$wL$D$Ht T$, уxET$t 3QVR땋9FȃytD$\$0t$T$D$HQVR[t$D$PL$D0t$Ht D$,D$t T$, у~ET$t3QRP֋EȉL$$yuT$D$QRP֋t$F@t(T$HBt@tObAPBQPL$$t$\$0D$D$Pt$LD$B@A;ЋD$Oy=B"D$L$t D$,D$t T$, у~ET$t3QRP֋MDȉL$Hyt$F@t(D$ Bt@tObAPBQPL$Ht$\$0D$wρT$3j jD$PhN<T$HD$$H@N@L$ F@t$@f@@ @@yS@AEut@r΃IrJЋD$$VRЋq<L$(G\$0t$x D$AωG 5L$(\$0AG qD$t$L$D$Ht T$,  T$FxEt 3QVRыBHL$t D$,D$t T$, ыHT$u,9Ju; BT$BFD$Ft$u$$to$T$zD$8u$#t$$t5$t$ XD$8\$0D$Ft$]t$T$jt$$VdL$t D$,D$t T$, ыHT$u(9Ju7+ @BFD$Ft$u$$ts$T$zD$8u $#t$$t9$t$ D$8\$0\D$Ft$.t$T$jt$$VXcL$t D$,D$t T$, ыHT$u39JuBp0r2ܸ\$0D$VFt$u$$to$T$zD$8u$#t$$]t5$t$ YD$8D$\$0Ft$t$T$jt$$V"bIL$t D$,D$t T$, уxT$u$$ts$T$zD$8u $#t$$at9$t$ D$8^D$F\$0t$t$T$j t$$V"aIL$t D$,D$$t T$, уxT$u@L$D$@L$`D$d(jT$dttD$dT$D$@D$`D$zuJD$hL$l$t$T$hjWt7L$lD$ht$ #D$#L$@\$0D$NFt$t$T$$j t$$V`>L$t D$,D$t T$, уxT$u@L$$D$@L$pD$t(jT$tttD$tT$D$@D$pD$$zuJD$xL$|$t$T$xjLt7L$|D$xt$ D$$ L$@\$0D$NFt$t$T$jt$$V _3L$t D$,D$t T$, уxT$u@L$$D$@$$5j$y$T$D$@$D$$zuJ$$-t$$j%t=$$t$ 3D$$3L$@\$0D$NFt$t$T$jt$$V]D$t L$,L$$t T$, ЃyT$uI$$j$UT$zuJ$$1t$$j$$t$ |s,|w WfD$8B~$fnf'|ڃ@r WfD$8~$fnffL$8D$8L$<\$0D$NFt$@t$T$$jt$$Vj\D$t L$,L$$t T$, ЃyT$uI$$j$T$zuJ$$1t$$j$$t$ ؃م|s,|w WfD$8B~$fnf'|ڃ@r WfD$8~$fnffL$8D$8L$<\$0D$NFt$t$T$$jt$$VZD$t L$,L$$t T$, ЋAT$9BD$$BT$$T$ D$ D$wCr|$ w: T$\$0WfD$8D$8T$<D$VFt$t$IRQPD$XL$PȉD$ t1D$$3L$HL$HL$3L$@L$<||$HsD$ T$D$ \$0D$VFt$qu$$T$zu$#t$$Nti$t$ ݄$݄$D$8tT$8\$0\$HL$H(Yf/vXʋD$Ft$t$T$$j t$$VXL$t D$,D$$t T$, ыHT$9JL$ HD$$BT$$T$D$D$L$Hw=r|$w4 T$D$ \$0؉D$FNt$St$RQt$0\$<[D$D$$3D$ L$@L$3L$HL$L;|s5D$@ D$8D$t+\$0D$FNt$aD$\$0ʉD$NFt$<u$#$J$T$zD$8u $#t$$tO$t$ D$8^D$@D$@$(\$8D$Ft$t$T$$j t$$VVL$t D$,D$$t T$, уxT$u$$0tt$T$zD$8u $ #t$$ t:$ t$ D$8\$0D$Ft$t$T$$j t$$VUT$T$Bu% BىF؉Ft$D$2u/\$0$(W$PFD$t$t$$(t3t$ $(W$P\$0D$Ft$jt$$֋VT T$T$zuJ$$-t$$jt5$$t$ \$0щD$NFt$'jt$$֋VWT~T$Bt"u:t3Ft$D$Ft$D$T$RdB+BD$G GD$(L$HPʉT$Gx ~8;ʍAB‰G #L$(\$0AG qAG D$t$*L$(t$\$0AG D$ |$tD$(PыDT$t$\$0t$D$t$,‹L$t t  RЋL$ ;D$tD$1ЄtD$(@^CD$D$ t$,‹L$t  %t PL$ ;D$bD$%t$,‹L$t  %t P,L$ ;D$D$Ft9tu>t3t$tL\$0D$t$t*u>t D$\$0D$t$t$T$Ht$D$8D$(L$8PыAT$Ht$\$0D$ t$xD$Ht3tu8t3L$t>t$.t"u8tL$t$L$2ȄtD$(Pы@D$\$0t$t$D$JT$tƉG R֋t$D$(@G t։W j֋TOL$@Q1T$(D$$@ @AD$HD$P@ x~ R@3;t$Hs"|$$3A80;T$Hr|$TT$@\$0BT$(+ƃD$$BG T$@+ƃD$$G ABfI" AOW~u~N F$~|$|$T|~ vF9D$K|;NF;D$7| 9N,T$D$FF4‰N0F8t$F 3f/V(Xvf/f/L$N0F8t$~F5~(+N$V T$L$@D$$ |sQT$\~Nu$0$0\$0f/D$0v1|$@L$XT$\||$sD$$tB3ɺL$XT$\9L$@|+9L$r#WfD$8D$tG G`xC_^[]ËGL׉CLC_^[]cAcAdAneAhdA~eASVWfff~X3FXׅt0tt~Lt ~Luׅuԅu_^[U ‰MESVWH p;sbFt;N@tIVZut MFu'ÃtFF@tF@tF ;rE@Eu_^[]UESVWM};@O 3_]9wvO3O ˋA@t+$R<utMƒtAF;wr]Ew;sY}FtB@t>$J<ut.%tF@FtF@tF ;r}E};,_^[]UQVWF" 0jAS$ jAFV0jP;FϋV4jP;FϋV,jP;FϋV8jP;F ϋVEt>W}Ot/]BȃMuM* $ ÈB>u_39D^[]UVujV fFl VfFl^]UVT$W~O`G`G@O@QQG=,<w G<$ ˆAAT$L$@jΉD$4ЃJu}FtD$ G?D$ FtG?F jjAF D$@FF f H"΋F +F Pj脶N f!Q"L$ NtL$ O?t|$ u_^]Ãu-N A$<uA\SPhhSVL% Ћ USVWuF{Mt{Auu&3t^G=*<w1FO<$ ȈNGD;ujЋ;tuGDO@W@;t ы;uGHwHN_^[]U SVWyGPG=GAD$ t ыG0@tW(Bt t BtuOh_htQAu y$tY,:A,q$I,t+~ t@@tBtF vuՋ uLtLuD$ _GLtDLuGWTjW\jGTw`_WHD$ G\D$t ȅu tAu  uw`GltFt ֋6uLtDLuGWXQjW\`WTt$ W\t$3f9 @t 9 9@t 9|w<G_^[]UQSVW]sF=e$qAF V|FFPFLFXF\FTBtF0@tV(Bt{ t Bt]u~`tGt ׋??uFF=_^[]ËF}~LuF=F_^[]Ã~LtY~LuMjyW@G=GDF FF_^[]ËVDt(~ jPN +ωFDNt _^[]ÍFHF=FD3_^[]ËVDt~ jPN +ωFDNuF`F=FD3_^[]ËVDt~ jPUN +ωFDNuF=3FD_^[]ËV|N<B$ ȈJ~>t/F ~ ϙ9F}F ˙+O#N +NF=3_^[]Ã~`tA~>t;3;~ls"kG~`u3Fl_^[]ËFlFl_^[]F=_^3[]fpA7pApApApA1qAqAsoASVWsF 3/~tQn Bʙ;}F ~?u(Nȍ;O+ʉV N_^[+~~=u~=uFQ~pfʋ;}V V+ύ;M+Ӊ^V _^[ËǙ~tV Vi;M+щN V3{9w`t;wlsF`u3Gl_^[ËGlGl_^[SVW_tC>w{=wjV@F=FDwF=tDF=uwN=uN=twF=tF=uwF=tuF=uQspcC>ʋ;}S S+΍;M{+_^S [UBS?H]VWuA$uAKH#C_^[]EP$ݤ YT ]Ef/YTr! YTf/v觗E=v3KNS_^[]ÊK H#AC_^[]ËExPu@ ;|3_^[]ËL$GGA G_^[]D0KG_^[]hSt$wUVW}G=wFV PFP,NF ;s+ѐN @Du~_^]Q,UQEVщUuFySFF^]H3=r=sS8ySWjG=wbM3PjE+F~%3ɋFI DDDu݋FE_^[F^]hSRN+UU Mr]U$SVWى\$ wt$u D$OD$GD$E;v PaE pxAD$,ˍD$(|$(PE;soT$GȉD$$L$G xtPFjPL$$ T$FL$;r΋E@=t$$RW *G D$XxHt$~t&֋=(ySuL$ VvF y̋D$~T$L$ jP'*_^[]V׋CD)UWMSZ3VE3ɸUWdEtMEEEEEE3;v;wT;F;w4ȋE@ ȋE+FƉE9BID‹ЃuEMdUAM~E33ۊHtxPэRN:t^zuSJ B|ItCw?r=w6t2H3=r@=s8ySd3GuEMyXuUI|LtFwBr=w9t5H3=r=s8ySd3߉Ud]33۸3u9Mv7t;v ډuuu؋EU+ËMPVr_^[]U$SVuW\$|$ Fu7jT$D$t$ L$D$ L$$D$(u֋u { stC;vDs~tS;wuӋ|$ V?֋c=(ySu VӋ2_^[]f.DstW;tcJL$;t\$ӋZ;u\$+BGFt+FGG Gt +F+GuNGOFGF@t&St@tL$ ISAPCYP_^[]hSW覊hSW蛊UUVu Wʃwr;OsG _^]ÊOH#Gxu 9Pu9ptHt(yS_^]QVW3WVɰu fFt3WV詰t_^Y_(yS^YUBV<u7NH#BFxDu9Pt/Ht(yS^]T$@T$D$O^]UVWF?A$AOH#BGxDu9PtaHt(yS_^]v6`_^]jT$ 蚦tt$ t$ 4_^]Ë֋_^]ëAA|AAAUS]VW} L$ WS=(ySu#L$ D$P։\$|$D$M_^[]USYL$\$VWt@q |u23҃v DEEˋً+ƒw3_^[]Ãyu 3ҋ_^[]3\$׃T$ ΋ǃwr;L$sD$@ >L$IL$H#Axu 9pu9xtHt(ySxtut$׉T$ ށ?wrw m|$3t$ VSe9ptσVSNxut$ T$ Ã_^[]Ë΋+‰D$uvWL$ƋSPD$ xu t$T$ D$ӉD$T$ \$+ˋ…wrw_^[]USVW '$̄AEEU U_^[]ËE+EU U_^[]uuu uu_^[]Ëu΋}ǃw&rw WfEMU_^[]Ë]WVu S_w tE 33ljE |s׋_^[]Ë}ϋUƒwrw h(u SRWVu#v][]33uu-|# M_^[]ËEU #E#U_^[]ËEU E U_^[]ËEU 3E3U_^[]ËME|sB|wWfEEU_^[]~MfnffMEU_^[]Å|ă@s~MfnffMEU_^[]ËEM؃م|y|{@rqEU ؃_^[]ËEU _^[]33_^[]hSShSSAAAɂAAA6AAAȃAۃAWAAAS܃Ukl$((ME $AX][\][Y][^][趝][^EE$(]E][W0ZT][EE]W]E(Yf/vXË][W][IATA_AAuAjAAAAAAAAUSډL$VW} C ćA$Au~u NL$ $jT$ D$D$ D$D$uO jT$$軟L$$D$ QL$ Pt$t$MQA_^[]Ëu~uT$ `D$ D$ uT$5tYD$T$ (؋E@_^[]ËuFu9Guw7v6Os놋L$CPuW _^[]A_AjAS܃Ukl$ VWU33MWɋE3EE0StNFSuV-u E +}Eր:0;BGs8t F@F3D$Pv FvЃ tL$tIF@F;T$‰D$@]ԻA$ĻA{6D$ <D$(Pv FvЃ tL$(tIF@ɉF  Cx%>_^[]ËO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ/%/_^[]ËO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ=%~_^[]ËO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ:%:_^[]ËL$ Q%_^[]ËӋO8BtO8A@A6w8D$Pv FvЃ tL$tIF@FϺ.t.r_^[]ËSu ._^[]ËT$ n_^[]ø!_^[]ÍD$Pv FvЃ tL$tIF@FS;WӋ3`UϋT(ySt=(yStPӋ[T_^[]ú!O SG ϋw URG w jG W fGl@EfGlHtu8tG _^[]3G _^[]U ESVHWD$D$ @^ GPD$xEtO3҉;CCN RT$QAQΉF P j~t1;|$ F 뗋jW-ЃztF 뼋D$ ^ HD$ D$xEtS3ҋD$ CCN RT$QAQΉF O jt2D$ ;rwF 돋jt$蔥ЃztF 빋\$ j;rWjV*jSjV t$F jVjWjV _^[]hSVkUS]VW|$t$;D$xEN 3҉9AAN RT$QAQΉF wN F ΉD$ aD$xE3ҋD$ RT$@@N QQAΉF &N jtrjWjVjSjV [jW+N Ѓz;F VjSЃz`D$ F {F +ljD$dr U t3ҍ ?|$TD$xEN 3҉AAN RT$QAQΉF M F ΉD$ D$xE3ҋD$ RT$8@@N QQAΉF L j(tujSjVjWjV jSɢN Ѓz6F QjW螢Ѓz[D$ F vF ΉD$ F #D$xEtc3ҋL$ ERT$AAN QQAΉF K jJtDjSjVjujV +juЃztL$ F 멃F |$wtD$xEdN 3҉AAN RT$QAQΉF :K F ΉD$ &D$ F D$F EHD$ D$xE3ҋD$L$ RT$@@N QQAΉF J jSjV jt$ jV ]ST$4++ڃ$HH;ߋu CCщt$uCCEt$t$ PuL$;ߋC+D$;vusjl:L$ƒljE D$ى]|$;L_^[]ËjS8N ЃzF jt$ ЃzD$F U SVuWjtV PyVF Xxu8H jT$GL$|$^ ^ |=(ySt#@v=(yStb@<uXF0;sF @F 9N rN jW_^3[]hIVehSjVcjIdU8VuW~t+=xSYTf.ȟDj j3ҋ3O<ЀjjJBO@ ΉW@BfBB BBySBF @EF XFx ~赑jh0{SVx} _^]hIVdL$$hIVcU SVuWhIjF~ Nj+8I(|$ [Ћ/;~ ӋF ~ jF V fFl/;fFlHt,Ћ|Fx ~蜐rxuxx D$tv~j~PjjhPSjePWjt$ F C~ ;\$j<PjjhIbj&P3_^[]h$SVwbU,SVuW=(yS1@'WfD$0xu8X jT$,DS\$,|$(|$$N=(ySI@$<<*Ht6t D$ 3=ЋFx ~xuHH L$ D$| $WD$(hTSPfD$l|$<-u D$(<+uGGP"2D$D$ D$D$fP2t0P|.XɋD$$;}_t$ t$RPȉT$ Ë\$ ȉL$OG\$ Q1uhTSWkT$|$(tڃ T$03\$4D$D$ ;^N YAF _^[]úm=(ySBV=(yStA@<u7F 9N sF @F 9N rN _^[]úHt.ЋէFx ~xuHH XL$$tsF T$0ˉD$(ۥtD$(L$0T$4P$T$02t#D$(D$0+HtF 3D$$@;F _@F ^[]h$IjV\fh\SjV\j]UVuWjjjVfjVjV u~WV]jV\jVVUVum=(yStxZPʃtt F @@t(N hpSjVAEF q ^]ËF @F ^]h$IjV[UVuW=(yStx=(ySta@<uWtu\hpSjVGq uUF09N sF @F 9N rjVN _^]j(\h|SjVZhSV\UVuW=(yStm=(yStg΋(ySt=(yStP3?G3V 3Ʌ_ BF ^]h$IjV+Zh$IjVZUQVuI=(yStu@tue&ȋA?w&0A$ A@@ 袗3N AAF ^]hSjVpYAAAAUVuW|=(yStq@<ug_=(yStbF809~ sfffF @F 9~ r~ W脕G_^]jYh$IjVXUVu=(ySto@<ue=(ySt`=(yStZF@9N sfF @F 9N rjVN 2^]j9Yh$IjVWh$IjVWUVuWhJhSjV3^jjj<[JV bPWV,ЃtKt$tN QAF _^]ËN 3AF _^]ËFfn_H HF fn@Y pYTXF ^]UVu-=(yStK@pIuF PV @@BVF z ~^]h$IjV~VUVu=(ySty@<uoFW809~ sF @F 9~ r~ l΋GP?N _tAF ^]ÃN AF ^]jWUVW}=(ySh SjWk υuCG A@w w G G @G _^]O jW fGlW .fGl_^]h$IjWTU SVuW%xu8X jT$8\$|$F ΃8X@F D$ F D$xEtC3ҋD$ RT$8X@N QQAΉF 9 F _^[@@]ËSW贏ЃztD$ F ź]UVW})=(yStUG A@w w G G @@G _^]h$IjWpSUVu6Ut'N jjVF  uF ^]ËF jjV@F  ^]UQSVuW*=(ySt@vjjV؃ 3ۺ=(ySt@vjjVo }t`E=(yStxuSVs3ɺEʋQ_^[]jcSjUSUQSVW}T$ GO +_ 5+O >BD$ @@P#T$ w ҍ9CsCw jW fGlBG 7+fGl=(ySt@uEG 3_^[]Ã@tuGhϋ\ujWG _^[]h(ShIWRhDSWRUSVuWHt0t339Ћ֚Fx ~xuXX x=(ySt!@vjjV# D$4D$lSn=(ySt@3ɃEȉL$΍PAtB=(ySt@vjjV t$|$PD$ \$$PhW@}=(ySt@vjjVt pS=(ySt_@<uUF`9N sfDF @F 9N rt$N WjhAVЋt$_^[]j@Pj2Pj$PUEH@ +H]UVuW=(ySt@vjjVr 3F 9N s@F @F 9N rjWVN o V FlfudF@AF@fFnf@fFnf;rf;f;~j#uAfFn@jfFl'fFlNF 9As ANF +_H^]jNVhLSV+UVuHtu8tNF ^+]jVCUjjV jVhxSVjV,VeUSVuWF~ +8=(ySt{@$<urHt.t3*ЋΖFx ~{8#u#N GQAF _^[]úxuXjT$/t`\$L$L$ǙT$щ\$|s\$\$t$;t$u| ;v\$ȅ|r+_^[]ú|UhSjVKUE t@t;VW}ϋG @G w G _^]ËEH@ ++E]UW}m=(ySG jjW@G GO hAj+jjAPW$t<t7G V@G w G ^_]ËOG _+]h$IjWpJUSVW}ϋGw +=(yS@<Fϋw w PjjWG hAjjjCPW$t>t9G @w w G _^[]ËOG _^+[]jJUVu=(yStjjV @ 8u 8>|s8|p tjDxt 8txBr<x4t.*|;D$s"L8t|u ڋ}O uACqG _^[]AG _^[]Ë}hSjW{?j@3I}hSWEAU $SVuWPjV؃ ΅lxu0x%jT$"u WfD$t$|$L$ V|sWfD$|$t$39|;s)D$U8VuW~t+=xSYTf.ȟDj j3ҋ賞O<ЀjjJBO@ ΉW@BfBB BBySBF @EF rFx ~5ljh$qJVW xSjgN @@AFF x ~khlSЋ_^]hIV>>L$$hIV%>UVW@pIjhEPjWjh8qIt3UBN @@AFF x ~?k_^]WhSV _^]USVuWhSVUhSWP؃uV؃uw ?hlIعЋHtIu8t?G w U uPd@@AGx ~@cj7G w hShSSWYu hSPWYjjW,hPj,qI=j\PEuHt,t3(Ћ萄Gx ~iQhSPWXjjWuOЋv_^[]hSW;U SVuWV P ,F xu8X jT$_~\$|$F F D$|^ rWfDSWtjVD$ F %P4qIF F D$|s_^3[]hIV:U,SںعVW\$w T$D$)JD$ duSG ЋHttG G G \$jjS0qI؋υuC_^[]úعkw T$(D$()JD$0tG G @G w &t$G  Ћ3W P)G xu@ jT$ND$L$G PQjWG G M9*u@G 3_^[]QShpIȅu_^[]ËG @G 3_^[]hIW8UVuWjjV jjV ΅PuG_^]ËF jjV@F Z SIE蠋N @@AFF x ~e_^]jV7jJ7UD$$D$E VWD$8|$D$tuPRWTD$E<;u DFF<;tj;VqEu΍QAu+ʍ1E+u I誊 PO @@AGG x ~d}]fHt,t3(Ћ9Gx ~Yd/t$hIPWSw D$ σ֍H;s  ;r;sfD;rt$ G hIVu|VhSWdw σ֍H;sfD  ;r;sfD;rG D$PB$P_^]ÍD$PA3_^]UQVuW=(ySt@vjjVT IS=(ySt@vjjV؃ IjjV EttjjV ΅toWSu [t _^]ËF jjV@F  _^]j3j3j3j3USVuڋ׹ЋHt(uEЋ{|Fx ~aqthIhIPӋ ^[]uhSV3UVt?UuF P"N @@AFF x ~a^]jjV} PujjVl PhSVm3UVujjV? t@QhIЋu^]PQjPVRP.^]jJ2USVWhDShIuUVOj-Wl؃tn+uI Q׋nN 9G@AFF x ~_GPhHSVU Pu {WhHSVrU Pd_^[]UQVuWjjV tEQhTS׋u _^Y]PQWЋP_^Y]j1USVuWjjV j.Wku_^[]Ë+u Ī P2N @@AFF x ~^Ht,t3(ЋeyFx ~^[QhTSy؃t&WӋtu^SWh\SV_^[]ËӋN @@AFF x ~^_^[]j/jjVR PSjjVC PhSVD0UQVuWjjV ΅tOh|SعsЋW\ЋsuWhSV _^Y]j/USVWD$D$D$ t$hS׹D$ЋPD$ jjhN F F @uXӋvN @@AFF V x ~ p\V fFljf~ljVtp~ jVtGF D$Pt;~ ~ D$ D$ RPhF F @t._^[]hSVD.jVD$P": jjV PShSV.UQSVuWjjV؃ {F 9N sF @F 9N rN عhIЋ/SЋHt8F ӋӋ躀N @@AFF x ~ZjjV-V fFl0jfFld=(ySt@tSJЋqS1ЋHuDF @F ~ SF Ћ_^[]j+U43SVW}j jwыN<ЀJBN@ V@BfBB BBySBG @EwG ~ ~ ^Ywj j3ҋ^N<ЀjjJBN@ ωV@BfBB BBySBG @EG _Gx ~XG hIB@G 蛿ЋjWGh)JhعWw=xSYTf.ȟDj j3ҋiN<ЀjjJBN@ ωV@BfBB BBySBG @EG ^Gx ~WjNjh8|SPC jjV$J D$<3ۺ蓾O 3j jG ϋw覉N<ЋD$DJB&N@ V@BB G G BG @fGG x ~CWCÙRPjW$JD$<`hSPЋIh ShShShSTSS|O @@AGG x ~VhSuЋhIhعWC hSEЋlh|ShعWYC h SЋ<عjj2bO G ϋw ּjhJWG AG _^[]hIWA(L$$hIW((UVum=(ySt*@v$jjV tVuzV @@BFF x ~T^]hSuy&UVujjVO tMPu F @ЋyN @@AFF x ~S^]jM%U2MfnA @^YTA ]SVWh,Ss VFC ԹЋK GQA˃C h0S蠹ЋK GQA˃C h4SlЋK G QA˃C h@4蔳=(yS^@<PF 9N sF @F 9N rN ,Sjj8jj0SD$$jj 4SD$(jju2OHPӉD$0@ut$,+t\$(Yʃ1F; TT$ F+;_L׋t$ rfD;ust=:*t.A:BtA:Bt A:B|$ |$t$$L$,D$<%tG<.t(<[t3;D$,L$,8BP+$ փwPTuHMUϋF M9AsA3t@uRUF;|_^[]hShIVUDSVWD$$T$,PjS\$$: D$D$(PjS D$jjjSt$4|$ |(s;wK3ɋуD$ х|4r-3΃;|1;v+C @C _^[]ÿD$4|$ |$,T$(sߙHt u@8u;3t$hSVK0NFu+G;|$(vϋt$$|$ D$+FXߋ|$(u\$I;wG+D$,t$$tD$D$ VPSh tȋT$Gt$,Bσr;ustJ:u't?A:But2A:Bu t%A:Btt$$+ߋD$ t$$u\$D$_|$(t$+؋N C;QAF N AAF _^[]Ë|$ T$(L$t$ND$<^uAJL$|$D$$lj\$DD$< D$H|$8D$@QD$PL$;~w'@vF N ?t;Fu G;~v_^3[]P׉FN &_^[]USVuEWPjV( EEPjV EF09N sF @F 9N r~3҉N h<jgaO<؀KCO@ _@C $C(yS ,ySCKCF @GFF x ~.MEUC(Ej‰s0hABVC4K$C,KSC 譠 _^[]jpjbUSVWx Eω}NPt.Ћ!IGx ~A.xuHH PM3ۉU %t)V;Vr_jVx EV  FUuDCPU u2%V;VrjV- EV  FU*0u6} +}tWV WuPLU~}C;]P_^[]u uM1jjWjjW讖G Vq Uj%h$SWU ET$L$SVq Wtktu uA_^[]ú蛓N ~ ] USL$fFl@+jfFlB] 3Su9D$~ xEtO3ɋT$QPP HtEu8t;@tjuxcA9ȋyt@몃΋E+u IQ SQ@@BFx ~+t$ _^[]jVOPVxPhPSVU\谲S]D$VWPjS譙 D$0xEE$E4M],M0W\M MD>EHMf/ `YTEvx!M>F@ffY YTME$MM],M0W\M M>Ff/ `YTwEP>hSPK uM$hSWKȉEC @PM>F;|_^][\$Ӌu1xu D$hT$hYD$hT$,JBu+ѹId+\++DID1u#D4D$4$Pt$$D\$T$pMSD$\$D$PPSu0 ؀|$.uD$pPD$^ˍQAut$P+;D$,j.P*udrD$pPD$SD$0Pt$ ]Cu F L$xCL$x;\$Ts t$tD$pPi_^[]jӋ3jӋhlSt$uGQhSu)h8SuhSuhpSPuRBRBNQBPB1SBNSBITBUSVW}PAZDXB$WB3_^[]_^[]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_^[]QhS3jQhS3jQhS3jQhS3hS3jQhS3WB>WB-WBWB$UBAUBVBkUB{UBWBUBVBUBUB4UBUB^UBQUBWVBWBVBWB    USVu WUUV&؃M u&E9t[M QtFM t?~*t%;OOOQu5#E+ȋE#ʉ_^[]ËE3_^[]hSj7Th4Sj7FUQSVuWUVW3ɍV؃EDʋU;~?tE fA;|"FNEE ːImQuE}t5~0NtQCjPL* w_^[]ÍF@uw_^[]U@SVuWjjV@Ѓ 'F 3ɻT$L$$~EO;$r$jP$$$A$D$OC|$4\$$`BM}xuPL$@T$D jT$D+T$DL$@}[33ۃ C3@ËCۉD$\$\$;| 9L$;T$|; |s3PVRT$8Q$[.M|xux\$H|$L jT$LG]|$L\$H}.3ҍ3ƒ C3у@C;r;$VP3ҍN9T$,Dѹ;~J|$,t A;|$\$lNf@Xu$\$9$VPMӋ{xu D$XT$XDgD$Xu fZD$`D$`|$,L$`u&tD+ID9ut$ $VׅtDRBIut$ ${D$8PSu貂 D$|$8;t.$WPWt$ P*3$ω$$;sAG;$r$jPQ$$$A$;rGD$8}D$$PSW D$D$$} ;3$VP3ҍN9T$,DэO;~79|$,tA;| NfD@Xu$\$$t#$SPaSt$ P1$L$ˋ\$L$D$TPSu ύQAut$T+;Et+$VPVWP1$Ή$$;$r$jP$$L$$AΉL$<;$r$jPu$$$\$L$D$<8U$Q'_^[]ËMjlj^h`SSuhtSt$ uMMj)hSSuhSSWhlSSu/[B[B\B]Bc^BG_B_B'`B'`BUVW}jjWX 3D$ 8|$D$D$tID$PD$ PD$PL$ DT$T$ +ʉT$;w7tKtFD$ 8uG 0@@G _^]hSjWjhSjWU(S] WVfE;މMMNUW}܉uFx4+K}DC Uyދu] M}9}tw33 C3փ@C33+ދ_^[]~B}t |s3;}%+I}Ƌ]D] ;uFI;|]_^[]ShSuUlSVW}jjWg} {D$t$(PjWI} 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$fBT$3ɋPVt$PYO QAG T$D$(ހ8O CBAAG _^[]ËL$˃|$Hut7T$P+DID uT4OtRBIut$u D$PZD$PG t$@G Pυu I2T$V1O @@AGG x j T$jVt$P0 D$4 0;L$υu I 2T$Pj1O @@AGG x ~ \$4T$ӋڍKCu+ًu I1 S1O @@AGG x ~ D$ @ÉD$ &T$8T$h4SjWj1j#hpSjWhLShIWfldBldBdBMeBeBfBwfBwfBwfBU8VW}wt+=xSYTf.ȟDj j3ҋphSG #pЋJG _^]hIWL$$hIWU Vuo΃xueoxuH%jT$ +u WfD$T$L$  |sڃًF H@F ^]PoxuT$ɻt)D$F T ZT@F ^]jUVW}nxuT$Ot(D$w MFG _^]juUVW}fnxuT$ߺt(D$w 譮FG _^]jUVW}mxuT$ot(D$w =FG _^]jUVW}mxuT$t(D$w }FG _^]j%UVW}mxuT$菹t(D$w FG _^]jUVW}lxu;D$l=(yStF@v@qlxu0T$tO뾍T$ٸtLD$YTD$w D$D$FG _^]jjU Vukxu"PF P@F ^]jT$ "t%F T$ L$P@F ^]úZk=(yStN AF ^]h$IjVU8VW}kxu1G 9O sG @G 9O rO _^]újxuaD$8D$8$\$@D$@f/YTrB YTf/v4w VFG _^]ÍT$8t똋G @G _^]jU8VW}ixu1G 9O sG @G 9O rO _^]úixuaD$8D$8$v\$@D$@f/YTrB YTf/v4w VFG _^]ÍT$8ѵt똋G @G _^]jUSVW}hxhxhxuH%jT$/u WfD$\$L$ӉL$w6rw/ G @@G _^[]ú3hxu@%jT$詵u WfD$L$D$t$w SPQ肉VFG _^[]úgxuOD$gxuDD$D$D$w nFG _^[]ÍT$t*몍T$ujP9hSjWjU8VW}gxu.G 9O sG @G 9O rO Wfxu D$0T$09D$0D$0WD$@f/$vrV\$8L$8f/ YTr-YTf/vw (ƙL$0VFG @G D$8O f.D/\AG _^]jUVW}exuT$/t7D$w Wf.wQFG _^]jFU SVuW5exu8XjT$諲tl\$|$exu@jT$vtCD$L$;w r;s3ɋF _@F ^[]úUVugdxuT$D$D$0d=(yStv@vpdxuT$萰t{D$f.YTD$D$Dz'萫D$D$L$^n(ȋF @F ^]jqjcUVW}VcxuT$ϯt(D$w ]FG _^]jU VubxuT$`t*D$F YYT@F ^]jU VuwbxuT$t*D$F YxYT@F ^]jUSVW}GO +E;;|ZEaUωEaU(ySt=(ySt PԳE3DMFE;~w ЋaG _^[]h$IjWUSVW}GO +E;|};|SEa։EaU(ySt=(yStPE}DEFE;~w Ћ`G _^[]h$IjW^USVW}fnGW +YhYTD$@twMQE`xup jT$軭5t$\$t$ `xuP[jT$~93Ӊt$ _xuP jT$CL$T$;|;*|s$ÃD$;|;L$w +T$ 肓XYTYD$迒FT$ VG _^[]BG _^[]hSWk_hSjWhSjWuUM^xu$$t$P3]ËMjSUVuM^=(yStn@<ud0^΃xuSV @@BSN @@AFF x ~0^]ú]=(yStN AF ^]h$IjVRU8VuW~t+=xSYTf.ȟDj j3ҋ(O<ЀjjJBO@ ΉW@BfBB BBySBF @EF Fx ~jhh}SVF YT@F hS\ЋlF YT@F hSs\ЋlF @@F hS;\ЋblF @@F hS\Ћ*l_^]hIVL$$hIVhUVu[=(yShSjV uF @F ^]Ãxu&SfV @@BFF x $S@N @@ANF y ~=^]h$IjVUVuhSjV tUxu7SN @@AFF x ~^]0hSVke ^]hSSVW3j jw%N<؀KCN@ ^@C C(yS ,ySCKCG @GGG x ~ hSعCYЋejWnC_^[UQVuhSjV t5xt@hSjV tHM@EVЃ^]hShSVUQVuhSVSUQVuhSjV tF|݋u}uO uJ;rjP8 Pd_^[]ÍPI tMLH?w(B$|B@@ $u_^3[]VBeB^BpBU$lSVWS\$F~ +8O|$u]jӋJ}Gt$/LNF S@F `RF @FN +^|$ ;8+N @B+ǃ;D$ @@Pf|$ F 9CsC}D$|$ HD$2׋K=(yS@<׋Jxu@\$D$jT$f!\$uY\$SLD$ SPI N @@AFF x ~3ۃ|$ +D$0t$,D$ D$ SPD$0D$,t$SjPOD$8|$@P3;Nj|$ jWVQ i*uH"DlB$XBT$|T$jrT$ja|$D$0t$,D$ D$(D$$D$ hPWhjP-ND$@=tՋ|$ D$ PD$G|$ 8Ћ N @@ANF ~ y ~ ~ GWF _^[]ÅuF F XF +}_^[]hShIVJ׋!hSWVEj׋zf,B=BB B?BUVuعhxS8HЋOT"HHtt3 ztj^]h|Sh\SV~UVuhSjV輶 txt"jd^]hS hSV"U׹SVuWeGHtt3 ֹ\$ 8Gxu8@|$D$!jT$覔u WfD$|${FD$ 9N s!F @F 9N rFD$F+N T$;8+N @B+ǃ;8D$@@P舁T$D$N 9HsH|%ԹӋRFN KF u\$ j׋ FHtu8t _^[]ÃչEHqu8tgF89~ sF @F 9~ r׹~ EhSjVF 薴ȃ t[AD$D$VAЃ_^3[]hSVhShIVj+PVL PhSVҰhS衯U4S]VWT$$GO ++IӉL$,D=(yS@<ӋDӋσxuMDxu@PQL$8D$0BO jG H_^]hSЬhSWUQSVW}hSjW& xhLJhSjW-jjjW4bJRPS`0tDG S@G \Hu G @ЋO @@AOG w y ~ w FVG _^[]S]O QAG _^[]hS衫hSW趬U S]VWhSjS tRxt]8hlJjjSjhjSP4\qJjW3ɅjQS腬<_^[]hS hSSUVuعh$SX@ЋoLB@Htt3 xtj0-@PV ^]h(Sh\SV葫UVuhSjVܮ t$xt/j0o-@PV藫 ^]hS hSV5UVuhSjV| ΅tJ@PB0SF @F TN @@AFF x ~Q^]hS蚩U8VW}wt+=xSYTf.ȟD j j3ҋ N<Ѐj jJBN@ ωV@BfBB BBySBG @EG Gx ~ujh~SW8 hSW誫->O hSG >Ћ6NjhH~SWG j(ϋlω0@PB=O عhxSG =ЋMhLS=ЋMj'ϋω0@PB\=O عh$SG >=ЋeMhTS!=ЋHMj@'ϋh\Sω0@PB<ЋM_^]hIWfL$$hIWMUSVW;tVFN +U^U;.+N @B+ƒ;1E@@PSwuUF 9CsC_^[]hIWǧUVuع ~U+u_^[]ÅtMSFU4SVWٍUj]XEE=ujU;Eu_^[]HE(w&PŰEŰ P_^[]Ë Pj3ҋyw8VO<؋EPKSCO@ M_@sCDC _^[]U$SVWjT$t$0\$} \$L$ C=ayPjjwD$(ЋL$(u:t693L$ P賰t$jjwЃ L$O F,^3ɋӋF,IDu3v,T$L$jD$B$BFL$T$jD$FbL$T$jkD$F=L$T$ jFD$$L$$NFL$@@Ft$,-_^[]LL$ OfBB&BsBKBBUSVWT$jT$\$;\$C=? wPjjvЃD$ uCt?9PƮPjjvЃD$ N 3L$A4y4|$Y~arFK ;w;s8%yH@+ȃ;||$A 3|$;}@F;|3~-L$ D$L$pHwF;|_^[]ËMUSVWjT$%L$3A=?FQjjpD$$ЋЃuSD$ tDD$9TL$PD$jjpЋЃ~L$D$4p OVW8|T$jlt$ T$t$F=UUU;B vQjjpD$$L$ ЋL$ ЃuFtBD$9L$葬t$D$jjpЋЃL$D$H WUSVWFx4@$uSPhSWt PSuhSWaNUVW9~u1~ !FFtF F !F_^]ÍV_F^]ËE ;Ft-UPP׋vPhSv4ЋlUSVW~$ui~ !VFFtF F !FFCN0@EEPЉ]IGGG_^[]ú$wU A0SVE@(s @MUWyDK ;~@SˆTS+O@FDK+G@UȊOtt$V׋bFF F_^[Y]Ã} E@@PuڋK A ;v A ;w_^A [Y]U4SVW~$~ !VEFFtF F !FF^0ˋUjW?ukVLjWEN0EE@@EEEPED E؊GUЋˈG K? fG G _^[]ú$BU SVډUU +]W}w0 tMtHtJ~~N,>E G;~}yWN,U ˈN,S@BC3IWE~(N,_>G;~}4WN,ˈN,}MU;~G0*H,_^[]ËNPSNPSUSVWXDH0EC ƉEP UUE:B EraR@;QuQQQP@RhR B KA;}C vG0D0KA;|_A^C[]U_uPEpPhhSv4]ЋqU A0SYDVE@ s UPMKW;}>C98tB;|3_^[]ÊH 8N vNvAtB] I0 ? ω I0 tFu΋UMP_^[]USVWMG_S;~I4hShjPNECM LMI0I*L MLG_^[]QVWxu xSwSvPRw4ЋU$SVW}_ w]u;{ wG@VUE1>C M@t;P0fD%? ƉP0-tAȃu֋GWuωG=u{N4SfN0VDEUAEJMAEB];]~"N4hShjPUM}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׋5G׋^0;Gt7<?u"G;Gt*C*O;|Q׋?׋@z<~]u3~ !FFtF F !F_^[ÍV_F^[ú]U}2EuUj2uRcJEF΃[t9=$tUEE*V( F UЋ΃=tEEUF,u'~ !FFJF F !FC;tu}j{Mt:EЃ t UЋ >MUQuˋRIU3Ƀr6rsr BAs  ыu@0 % ‰3ɋUr7rsr @BAs  ы_@031^[]jUЋD8EMxQI}F  +.׋+5.֋5EC,MKSX{U SV3W~0EX~)F- +~ !FEFFtF F !F VFUEC@uo~,ui~ !FFtF F !FxVlFf~ !FFtF F !F V:FE@v0^*t/fDFN*+N$@DH@H uF;Ft9֋~1>u"F;Ft#G*N;|Q֋l4 ֋5U؋DFU؋ψF 5> fF F u{ !CCtC C !C SCU؋s֋0>u"F;Ft#G*N;|Q֋3 ֋4>NMuu G*;|O,G,FO,у@;vPO,U؈O,5U  V }-}usMuhG*;|`O,[֋0>uNu G*;|O,O,B@;vsEPO,HO,P2u֋C(=_^[]ËOPSpLSffB~BBBBUVWG=B$BFFFGFFFFGON GO0E@@EEP+vFFFjFFFMFFF0O0x-*FFF !GGtG G !G_^]ÍWG_^]_^]Á !GGt$G PjG !G_^]ÍWG֋GPj_^]E_^]ú`Ss%BB0BgBBBBB>BB       U0SVWC4f@nf9PnEC=. B$BEEEE{ !CECtC C !C SCj cs0E$BhȀSWP 35׋*?u*GOM;Gt+F* ;|Q׋-O׋.OM?uu F*;|N,E 'MU N@8T׋P3C=dB$ B3|ung`YR K D = 6/ (! uuJ;E"{ !CECtC C !C SCK0MtB$`B[1)t ttMj20GMWP#UOBBQM#G$,G;Gu t tN-uJUPUK0EuPWs6 uC4_fHn^[]ËK0h\SBBBBB-B-BBHB BЈ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]úNPS"U,SVWj S_0C,D$ Ћj SЋj SզЋ֋= !GGtG G !G W\GjT$$O0T$$,[ !GGtG G !G W GjT$$O0T$$j,uN !GGtG G !G W躼GjT$$:O0T$$D$D$ PT$$D$,D$D$D$S,  ˃.֋3K,BF;vs?VK,K,T$ jjun _^[]ú=,KPSߤU,SVW]jF0SE@,E貤Ћj S蘤Ћj S~Ћ׋F,u~ !FFtF F !F VF~$~ !F^FtF F !F VʺFӋ]C]y= ~ !FFtF F !FV{~FEPQЋPMQ, A;v s6QUCjPW _^[]ú$ MPSIU4SVT$W~ !F^0FtF F !F V賹FjT$,3~K~ !FFtF F !F ViFF= tU=tNN0T$(D$&C*D$$C@D@D$C@D@D$ D$%C D$D$C D$PhPENW FA;~$NhHShjI4RW0賌G0NG0OVB;~$W8hHShjQNI4|G8VFO8_@FHN^[USVW\$C;H4@@L$ȉD$hȉL$(ySuT$L$VdD$ȃyu81;s}1MW,B3A?uQ3t _^[]ËL$D$_3@D$D$Q@A ;~"W,L$hShjS~OG,;}G,IFD;3|\$ËMG,D$@A@t7Gt0Bt(L$Iy=wD_^[]ÊI<$ ȈO_^[]UQVW u R@0 E@3%1_^Y]ÃuTJ@0M%I ȉ ?F, >N,BG;vsWN,N,_^Y]ËNPSQVWH$C_^YËVF _^YNu G*;|O,~ uF :G*rO,V F  ыF _^Yà uN@0F_^YÃuN@0 %  _^Y<CFCcCCCCCU0SVWuA 7$CujEp_^[]Ëu3҃D ~u ֋.FUEEEP*u bFUԋN EEEME봋VuH03%?1Ep_^[]ËVu;t Ep_^[]ZC~C~CCCCeCCCCC7CVtDp0D|L?DbJ| ?#u-tBЃu3^ø^USVWu? uwWWw;EEPu֋C? u E-sCVUEiEEuˋC։C@KK֋ˉEmKSuKˉEususWVW uuV EGGG_^[]SVW?uOu F*;|N,N,BC;vs SN,HN,Pg_^[ËNPS3U VWF;Ft7'>u"F;Ft*G*N;|Q֋֋GH$0CEEbEERGE@@EEEE9FUN EEEEMEFEEEUP]FF= _^]Ë֋3>u)F;Ft*G*N;|Q֋!F_^]Ë֋LF_^]cCCCSCCCCUUSVuWt<3ۀz Í]OMQ A   Jl>^u!F;Ft"G* ;|Q֋X ֋MQ  r>uGNu<G*;|4O,_^[]Ã>uNu G*;|O,r֋_^[]USVW u7s@0ƒ?<u(OD3@9ED kt>7O,BF;vVO,HO,PJ;uKu G*;|O,S U?SwG=VUEE_^[]ËOPS资SVW w["C$"CN@0|JZ?DbJ| ڋ%??@ Fj֋PVFNWGGQ/F_^[Ð!C!C!CSVWA d#C$P#CN@0|JZ?DbJ| ڋ%??@ nt:O,BC;vspSO,HO,PF>uNu G*;|O,VXF FϋVVFV_^[OPS‚fX"Cc"C"Cn"C!#CUu"F;Ft*C*N;|Q֋_֋:> uuNx0?<ucUE:u*BEuC*M9B|K,FE[0ߋ B ȋE  FB_^[]Ë֋uVu _^[]Ë} Wuu)uV Wu _^[]u uQ_^[](C'C(CT'C'CUQSVuڸQWv3BU DЁ  +%È_,_^[Y]Á* +֋.È_,_^[Y]ËOS{|ULSVuWw 3WfE9^,uF;Ft~4fEo w ~0c F@}̋MȉEEĉEEEV@T uu9TuuuDut 9t uEEUE;~4rV0w;rM  ;N4rE;vEP託EFs~ t*uGP_^[]WjSY؃Z3ҋ7duH3s S&uGۖ_^[]Ë~(t7w 赖W謖N$F(Af;C} r;ust1:u't&A:ButA:Bu t A:Bt3t"3's S3^(F,~4WfEfEw ~0ŰEċ}ȋ]UEF@Ƀ| ugEN M9Ewzr;]ssUEQRW8ΉP3҉E6Fȃ tI8F Pj3-VMԃUAEEEU;V4wCt;~0s8ju.Eԃ)@_^[]ËEċ];Ew2r;]s+u F_^[]ËNP~PtSQAu+ʍA PȔ؃]u+ uF胔_^[]ùS0QfDAu+ʍAPm؉EtSPQSAi hSVP2W3hSDW2M؃]uH腭 t  FWxT}W(W͓u“_^[]hS臙PQF}t'hp~tFjjjjvVЃFjjjjvVV_^[]jQSuX9u 4{tCjjjjsSЃCjjjjsSS;uOG>R~tFjjjjvVЃFjjjjvVV1_^[]Ëu]u 谼M׉Eu Eu jQj@EPwGЃ|UZrOTUIy G 8jjj@EPwG7Ѓ$|su tG E;tHEtGjjjjwWЃGjjjjwWW?};u}u V辻juV萾 y3蓢C_^[]Ë_^[]ËMdduVt EȋM̉J REԋMFEЉF EF0+E虉F(EN4V,@t-U Su\.x59EujWu ǽ 33_^[]Åt C_^[]U CSVuW} ljUMtWu Ɓ v QPjPU؃tUuSjP׏;uM+wru_^3[]EtW_^H[]ult!Et'_^H[]ËEt @_^[]U CSVWΉ]9yK d_^[]Ë]~NVjjh uPRуWRPу|Ar;|ZtTSWjP蓎;tE tGHNFjjjjQuЃF_^[]RЋF_^[]UEHE @u]Åu]ÉE M]USVWjjW yE 3_^[]Wu1u uWS_^[]É~_^[]Pu ؃tu udW3_^[]ËF@CK F0N4CKF8NPKt!E@3_^[]Ã~t!E@3_^[]ÍF;r"~PKVu]SQuuW ]SQuu FEFEFUEU+EȋEȋGMEʋGE;r"E;EM9M U 9U tM SjEG GM;|+EEEEDuVE*jwV· V>QVƴ;G?GWOU؋W EfE܅wEu܉E u@}Ew }jX3@@@ fH@HHH H(H,H0H4H8H3_^[]SaEh*{uuEt3_^[]S#Sh*jVSEvtEtVY{3_^[]ËE3=*EE E]؃u+lj]rVFPjPWȃ tA@ASf;QuBS:BQt^+PjPRȃ uuz} | }uԃPKFNAAA؉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%.E_^H[]Ëu~K WGPjPߍt* WnM+} _^3[]讋Et H_^[]Vtq~t0NFjjjjQuЃ RЋFNFjjjjQuЃVq^RЋVq^UV u3jQjEPrBЃn|sh3tF^]ËB w$@QC33ݹԍEPU4EMjjjEPrBQЃ|rEMPCQCPCPCV~t7NFjjjjQuЃF^RЋF^U\SVWE ;F4Er ;F0]u4ȋF@Ƀ|u| t 3G_^[]ÍEPu u: y R3G_^[]ËE$ D u>Eft6}$u  3G_^[]fECEMufEftfE@Cu _ u,ȉEU EȋȋU j 5ouVpC_^[]à W3G_^[]à 83G_^[]jGGGGWjnut CWsn3_^[]F FF C~_^[]ÍMQQRPuuv2Et%u$juVWЃu3_^[]ËMtEjPVWуtՋ}tf}uj֋ "t_^[]à t G_^3[]U SVWtw~ WfEr1w~v)]}D9;^ rw;~r6/m~ t7mw mW mVm_^[]U SVWj(lut G3_^[]Ë] E u } Plut GVl3_^[]Ë} WfEr>wt8UM@@@ ;rw;rΉ~Ɖ~ _^^FFF ^[]U(SVuW} VU]}耞y%e C _^[]Ù3ۉEWUfE܅r{w}tuME}܉EQ uƋuA@HuRhWYUME;U UQ rwQ ;}r}V軝y(蠄E H _^[]ÙȉEE+ȉMʉUUʉMwrw} wrwVjjhSrjj,Vj- /Vj/Vj-.Vj.Vj.@Vj.Vj.Vj.Vj.Vj.Vj.Vj.] SWE@SW9uu,uEPVjjhSrVjd.Vj\.VjT.@VjI.uuVj4.Vj,.Vj$.Vj.0] VjjhSqVj-Vj-Vj-Vj-0usNjىEVP-VS-} wsEVP-VSu-}w EsVPS-VPD-VP5-VS+- }w]rVP -VP,VP,VS,E x,tx(x$tG3VP,VS,tGVPj7BpVt$藁E t H _^[]ËEU_^[]SVCtt&s8t6gv gVgC tt)W{N,F(Ew1rw*F4V0UEwrw~TUw ~PF,UN(MurBЈMˆUMN(ˆMN(EE‹UĈMEËF4N0MEurD F4JN0F4JN0JN4JBBBFTNPM܅urT FTJMJNTEE܈BJBBF0EF4EF(JEN,E;f+jEmVE܅~fHM@fH ftRɉM؅tQ-VEuEP@ U3+u؍MQP$E܃ MH NM @ E܉V4^(N,EF0EEU]E%=u9w.r}s&w"rsEt~Tw r~Ps3 E؃}Eu'-uF WPWS}-uFWPWS{EWPeWS[^WPMWSCFNEEPMuHpx MfHffHffPuSE܃DNj}WPWSuW^ PWPWPWSN(0~,w'rs EE ]É]WP?Wu6Wu-WS&N0 ~4w'rs EE ]É]WPWuWuWSF8 t@WPWSN<Et(fU܋}A#ǩt fA ffЋ ufU܋}Et)fUAt fA ffЋ ufUEEuPuS}'F@t@uPuS^DuPuS^HuPuS^LuPuP@uPouScFP~TEwFrs?]SP@ESP0ESP ESP 7]ShShShSh ]N8tASjP1kYtS N;s 8u @;r_^[]Ë]SWjVi;sV.NS+et gEt&_^H3[]ËEt @_^3[]US]VWWPHu ӋWP3ˋWP!WPWPWPWPWS@_^[]UQSVW~tF _^[]Ëu+FQQQQvЃ|_^[]yF _^[]ËFjjjjv6Ћ؃‰E`|sZ>t3GOjjjjPuу RыEGuCtF _^[]_F3^[]UQSVW~t}E =wsMrwiutt]F>^EE jPQRuuӃ_^[]ËFPWӃ5|s/u tF _^[]ÃF  _^[]USVWuG t4_^P3[]j KuG t @_^3[]ËEFF FFFFtjEKt_p^@ @@ wC[]UEDSVWO$|yCE @@@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 >t2UFNBJFB0FNB 3 B4BJ$B33_^[]ËE P HEP33_^[]u H33_^[]?wChwCJFVDFu_^3[]ËE t @t_fDv > FVFu_^3[]ËE t @tfDv >EVEu_^3[]USV3ۅttWucupDFf;tf;t tދ6F;ΉEEE@v >JEVDEuut3Mucupu_^[]UQVUtgSW}F#©tN^WP` WSV ^ WPH WS> F ftWjPv LU6u_[^]UE SVW};C4r'w;{0r 6_^C[]{@x@PjPsy y#] _C^[]sE jjPx_t#r] _C^[]MEfEfE s jQsy y ]t?_F^[]ËEKMtPiC؃ut F_^[]uMPjS^U;sNS CuZt\t_F^[]Åt_F^[]Vh0SBfЋI<A<@Otyu@؃]u E t X[_F 3^]39Uvx3E< ESs=ً?ˀs$_ $? _G] B;Uru}ND;tG}^ tF^ [_^]ÅtF[_^]UQSfډMVWftLE%t =t= 3jJ=uE t p_^3[]@P=ȃuV<3_^[]PuQ  f^FF FtG׋ u96<v <V< E i_^@3[]_^[]UVu9jPjEPqAЃq|sk3tMt^]ËQ w$pC33׹u֋^]jjjURqPAЃ|rEM'CHC4C-CUS]VWuG _X3^[]jp;uG _p3^[]ËME UFPNTM ‰^u ыE NXV\Ft!F@F @ F0@0F@Y3FFFF F$F@F8FtvNF33_^[]Ã}w }@}G Gt0E 3GG @G0@ G@@0@_^[]ËGtPM>L$QPs} D$P7x}tGhQGl _^[]Ëu 3L$utZV(3G3G t4S3wtV2_^[UUщUuA]Ë WzMBV3E|S vrY tT tO tJ$t ϋNj_^[]Ë} EuWfD$L$ы|$_^[]Ë]$ (  fV҃?+Hw$PC( ~t̓ u ~{~SKjjh WRuуȅ|krePуȅ|9r3 u FFF-  uAtC C FP  FM3ҋ( ;w}r;s+ʋ_^[]Ë_^[]ËM  D433_^[]Ë2M @zfB42zytAIB 3J$2z3_^[]Ã323z3_^[]ËE @B 3_^[]u .33_^[]ËE _^[@ Ћ]ÐbCۑC~CCCCqCt ϋNj_^[]Ë} EuWfD$L$ы|$_^[]ËE]$ ( (   Hw$C ~{~tztvSKjjh WRuуȅ|[rUPуȅ|)r# u Fb  QuAtC C FP&F  FM3ҋ( ;w}r;s+ʋ_^[]Ë_^[]Ëu  tfFt_N$tXP4tRv(ыFN$Pv(уF33_^[]ËE3fH49H$w9H vPHutH P$33_^[]Ã}wrJ}rDE PEP3҉_^[]u z*33_^[]ËE @_^ []ÏCxCCDCvCCCCCCЕCЕCCCUQSVW} ] f}Et"E @3_^[]j)uE p3_^[]ËFFxV4F gE#FxV4QAuj+3jQW}t"j^)u&G t @V")3_^[]@ @@Cp_^[]ËE t @_^3[]U}WSVWfEw } MCuM}MUuȃ2шUt>KUjKUщCC ij@C E[MЉCM;M{w ;u p_^[]U\SVW~NVjjj uuEPRуph A9RRPEPu`jQj@EPvFЃ|3_^[]Í]SRPу|su tF U9yF 3_^[]jjj@EPvF6Ѓ&|s u tF 3_^[]ËEЋMԉEEPM~M؃U:@fHffHfff:G_^[]G_^[]F GP_^[]UE SVW$CU M _^[]u}uMڃ|s_^[]ËM jSVWƋ_^[]ËU3 fB6BBD$tB R$33_^[]ËE PEP3҉_^[]u :%33_^[]ËE _^[@ Ћ]C>CCCĜCCUu3]]UQSW}хttC33 PSuV E3 ЋPS3PS3PS3PS3S‰]ȋuPS3PS3PS3PS3ȋPS3PS3PS3PS3VȋPS3PS3PS3PS3^ȋPS3PS3PS3PS3V ȋPS3PS 3PS3PS3^ÉuȋPS3PS3PSË3PS3ȋ PS3 PS3 PS3 PSm*rH3 ЋPS3PS3PS3PSʃu^t[33 PSu_[]̋HA(A,A0HtA@@@QtP00AlAPAL3AA AA A8A<ǁǁøVuA^ËF FuF(3F 0C0CN(~$uF$PCShjQЋ؃ uC[^É^WC4~t=G4t$tPv(F$ЃG4GG$tF$Sv(ЃF_[^UQSڋVrF4Eu-N$jPr(B Ѓ EF4u ^[]W~(uN$~(F0F,U;r#W+SP8F( 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]9EEfD$$CAEu  s-KuЉ]GU}rًMEtIuAj33MUjfEAM3҃U3uAA At@0Aʋ3MuҋU$<tE@`S#‰Uuy$EuLA$M3ҋMjA3 5MUAB0U҃ 33Uu;A$vE@|SE@HSs*UKuЉ]GU}rًMQtE@S3q UątEAEċEEtIUUjE MA3U3 s'KЉ]GU} r܋MA tPAt/IEˆUUUjEMA3U3s)f*KЉ]GU}r܋Mq t‰FA up AtIUUjE MA33UuAtqs)fKЉ]GU}r܋MA Q@tPAtIUUUjMA3EuA t@AEЩA@;FЉUȅy }Et^y Eċ_ۋ}Љ]]}Ћ}tBI Yy+؋Eȍ +;ϋ}GPEWPM ]QA@UЋUȉEEtAu3R׋MAU+ڋE+‰]}A@PA@A.3Ҋ:BEA t#putq@;p s]Ƌu0A@]Et;rAuUt9QUUu EMRMUEĊE]ĉY]+]}A t@A@Ad3Ҋ:BEA t#p$utq@;p(s]Ƌu0A@]Et;rAuUt9QUUu EMR4MUEĊE]ĉY]+]}A t@$UAEtXs*KuЉ]GU}rًMA;tE@S 3EuA tU P,A @0j33DMUAB0U 2 s&f KЉ]GU} r܋ʋȋ%M‹UAB03҉U3 y P j33.MUAB0U yt΃+MUu{s'E KЉ]GU}r܋MAƒ$C Uu"ALPSAT APPSAXUuUuE@SUu΃+Uu s'r KuЉ]GU} rًЉM;ȋMtE@SSE33A@UuA@EtJ9]ËMFE;FȉM QWuE M+)EE؋U)A@]} s$ KЉ]GU}r܋EGH`xd}‹}UuG\}}MAhAh;A\sgs+ KЉ]GU}r܋Eʋ}U@huEKfLGpϋ}AhAh;A\rsAh3EKfTApAhyhr十0ATQlALTEPQRU3jRp3.MUE̅t-E@SiEM@SQAhEAdA`9AhSITHEM@LEM#‹MEm;vG KMЋEG#‰]U}MEm;wMɉMɃMs+}+MUuIhfDOpAhAhE]ulM;s'f* KUG]};urދU+MUuyh,EЋAhDAnEf}uIM;s%KUG]};urދUƒEиMM;s+fDjKUG]};urދUƒ Eи+EMEIdUuH`@hE;MwD}ЋUAhfTApYh[]ĉYhu]UA`}EAdE9EE@4SEăfpuE@PSQlAT 0UALATWPRq`Qp}+}ME̅tEU@xSQUuAXAPAXPA`RqdpA*MUE̅tE@Srq}rhE}؉x }܉x}8XQ8Uԉq</EH 8XM؋HM܋M}]9 Q8qE@SqEM؉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,tFtO0R}G0EF FN0 x}0|%} @P u P P 3P ȃ~lt ˸BFqF+A+ًNFNF^C~l^t?W2F FNFF_0VˋF FNFFG0FEVz BNىM9F soD;^ u:z,t ;vV+u3 O0S+G0NىM;N t+FNPF  ^F CM^VB9F rVz,t#;vV+u3 O0SG0VF ;BuQF IFIIFxNىM;^ uKFx,t.;v*V+u3FFI뽋O0SJG0NىM;N t0FN @‰EAMF F^C}^t EFx,t ;vV+u3 O0SG0}uPF [F[[Fx$NىM;^ uKFx,t.;v*V+u3FF[뾋O0ScG0NىM;N t0FN @$‰EAMF F^C}^t EFx,t ;vV+u3 O0SG0}FggguUFx,tEVN B;v 1VN B;w+NG0 FVNG1 FG0Fq~tt]F=u u~tu=uwӋF8Fg1]uM3 O 3+Ѓ Oȍ+;h_h-K[G_^]Ãu ӋSV@ثSЃtuF;Xff E ~HNUfFFVN *Ff Qf؃ ~/NFFVN F3ҋ BӉfu_NFFVN F3f]FC[_^]Ã|ɋNV Ff렃tjj3ҋ-uFD3ҋNLfTHFLEPRvD蝽 ~t[FlF\dž>uVG0N FVG1N FVG2N FVG3N FVNG FVNG  FVNG  FVNG  ?_2NӋFFNFF_0VˋF FNFFFF~؉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+jP&FlF\3_^[9A]ËFl;~5xV83+jP&FlF\xm_^[]US] VuW@Ft=s!Ft=s10rf~lF8VHNXD8#~43#VTFDN@VHfPfyVl#N4F@F\xV83+jQ#FlF\3_^[9A]Ãt8F\xV83+jQ#FlF\xb_^[]USVuW@Ft] =s!Ft=s#3rE~lF8VHNXD8#~43#VTFDN@VHfPfyVl#N4F@ fQ< fċu=tvDt\U썻}䉈f  Mff +҉U;~BHfPE E@pP *U䋰@f҉f҃~WffHf ڋPf @pP @*ʃffN    ʉMff +҉U;~BHfPE E@pP *U䋰@f҉f҃ ~WffHf ڋPf @pP @*ʃff NWff f  ʉMff +҉U;~FHfPE E@pP *U@fꋈ ҉f ~LPffHf f @pP *@ffWff փf]3uu O9]u J J]Em;_^[]USVUW ~TffNf ЋFfFVN *FffYf f ~R}OffNf ЋFfFVN *FfESHff UMf؃ ~T} FffNf fFVN *FfE ff 3f9] ff\Jʍ ~Z~ fff FNfFVN *Ff󋖼ff~ ff C;] qEHPE HP}_^[]UQSVW} ~N} PffHf f @pP *@f׃ }fU ff փҋpf~P @p ~P @pU3fHڈ@ӋpH@pHU҈@PH @]ptfDPO @pu_^[]UQSVU3W9_>,uk󍎔3Ґtf9uHB~f9u8f9u/f9u& fDf9uA|3G, $  v( e0 lJ@fAf~ uGAf~ u7f~ u$Af~ u]J} K]}  ;G}OэG;wEt] SW#k; ~U} ffNf ЋFfFVN F*ȃfAE ff f΋ CP( B@P P] ] ~K{ffNf ЋFfFVN F*ȃfACff hȯSpSfs tR~"VN FVN~VN F3f_^[]U Sڋ3҉]VWEr9w@Q]< BUU\<+Ӊ];~NPfff ًHf @pP U*@fff fȬSEUUЋEʉM싈ff ʋM΋u+;ыM~MPfHE E@pP *U@fʋUM։fM英Su+S+;~[ffHf ڋPf @pP] *@fMfff ΉKsȭS ȮSULMʉMff ʋUM+;M~MPfHE E@pP *U@fʋUM։f4Su+S+;~XPfff ًHf @pP *@fMfff ΉU;]ڋ+ff ];~AHPf @pP *U@fꋈ҃_^f[]U'U@'UVAtU?F|U$FxUSFUGUХFpUG8 ,(Uu,(UqIpPhrIp<<1I(U8-(UuifT(UTf(UT(U(UNFu++ƃv!HhITP(UP> tƆ(U -(U=.(Uu%hITjPh0(Ud> U0(U.(U3^]rI^]̡'U'U=((Ut(Ub{((U(Ut:=,(Ut1 'Ut Q4qI(U'U'U,(Ut*rI'UtP4qI'U'U(UQ='UVWu hHjUh@LJHtU,htU$tu<~LJ(LJ LJ8FLJ Ӌt7_^[]És@33ۉ]D]Ѕ}\qI؋ʺwM]ԉE؋ú/$؉UwȉUE/$ωU܋UEًM]]ԃ3ыMʋUЋE+ i}+iEԍEP{] ;}ut0+Uԋj™hRP:+}܋iʙʅC| w<]C]~5 }Mиt"yh&'lrIPHqI3ۉ]U59EE> N9A |WE^F@ %EEЅSŰ΋X_^[]ËŨ+D_^[]_^[]Uuu u/ ]̃\$DSøSøSø Sø8SøSøSøSøSøSø4SødSøSøSøSøSøSøLSøpSøSøSøSøSø SøTSøSøSøSøSøSøSøDSølSøSøSøSøSøSøSøLSøxSøSøSøSøSøDDDJDDPDVD\DbDDhDnDDtDzDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDD4DD:D@DFDLDRDXD^DdDjDpDDvD|D"DD(D.DDDDDDDDDDV*a D$dDSSSS S S8SLShS~StSjS`SVSLSBS8,S.LS$lSSSSSSSSS4SLShS|SSSSS}SvSoShSaSZSS(SL8SEHS>hS7S0S)*ttt3^øS SShPVj Ɔ^rD|DDDDDDDDDDDDDDDDD&D0D:DDDNDXDbDlDvDDDDDDDDDDDDDDDDDD DD3D.........................  !"#$%&'()...................*+,.......-SVW@pIƘx#\};8}hWPV ?Q֋gu.PhVPWPh8qIuWWh$ShV2j VƆ3st +΃|j Vst +΃|@pI;tS@qI_^[UTƁSVW@pI؁ w_$DLSVPhTEjPP>1EjhPjVjh8qIEj P?rȃt+ƒ|j Prȃt+ƒ|PEPhThW0~hSB|S8S.S$SSSSS(SLShSSSSSSS$S@SXSzpSpSfS\SRSHS>S4$S*@S XSlS SSSSSTT4TLT`TtTTTTTvTl Tb$TX@TN`TDxT:T0T&TTT4TLT\TxTTTTTT(TE^hhzEhzEPd ujtUuXFNHsgN,kgNht_gTgN3dž ON3OV|U3_^[@ @`D@jFtUuFv@ @`D@FEp@_dždž^[SVW3; 'H@t _^[jtUu _^[@ @AD@ PGtG U <=((Uj(UzE(UzE(UPtD$(U (UtU(U3jtUȃtA APvEA(U (U<t F|((UG8(UG<ct&DLN3M(U(UuP|U(U (U8t<u C,G<G8Ch{t C8G G{j{j_@-C WCfփ+3_^[ø_^[_^[USVW0ډE>G֋薟|ULJ|ULJt t*uE@ t uSVЃ ؃*tiΉEǀǀXu7EuuhI*(Eǀ3u *Eً@ A t"BuUuG3_^[]ÍƇGVHtd]FHTF|ULJTFBt t \UUG@yH 3F@t99Hv,hTWk1QEt2҉8E3;tS [t(ZtWtPvDh$TW0LJ U uE؋E|ULJ|ULJ_^[]U SVW? H|~@iF NEtE91tE} O-Nt:F w/@@%©u:Ut UN1E+~<uF8F<Vt }tuVNZGӳPGt3RHdžPGdžF >!Ft FF@Ot9pt Ru jsGNtGFtAO J'3_^[]O ωG4'3_^[]ø_^[]_^[]UQaGVWyA ~ }q $DI@ ljRQЃ _^]ËIR@$ӋI_^9hE‹]ËI33uB8uu:u_^]Ã_^]Ët 3: N_^]ËI@(q3S3ۋ>@,tjRVЃ [_^]ËE$<u3ɉE$*<u"9uu 3ۅÉC[_^]3_^]DbD>DDDD(D(DDDDDU(SVW3u]}o> cU9$Ex;L؉]FEtMQU܋3ҸttGttGtBrًEEuut$PtUEu _^[]3ۅFEQU܋3ҹtuD܉޸fDCt܋tuD܉޸fDCt܃tBrEEuutuӋN3ۃOu3V|UEt3_^[]_^[]USVWT$3D$@RSЋ7WVD$x@07hLTt$S*UtƆUj3ҍL$Ct7uRD$D$P׋u+79A ui9B u^T$uZT$Yu+|$WS@Ѓtt2ŠT$ut3ҋ&t CHT$t2ҋ迓_^[]ø7_^[]Ë|$uk?tfƀ;FȋA;ct+ыp\$fn^ YT;t+fnXP_^[]UT$ RQЋ؃u L$8Ɓc|$ u"  SG wD$ ЅupD$@`Ѓ9G G SWЃD$l tLxt@D$ L$ QR@ЋO ؃tjӋ D$  D$ 3ۈD$  D$@`Ѓ;^qu:   99 ƀ tSG tWЃD$ Yt<Ut ƀU t0SG tWЃ3ۃD$H T$I؉\$88D$u}8ttNGtu>j3ҋ `0SG LWЃD$  tSG tWЃ3D$ O `t tSG ʃ  SG 7VT$D$d3؋jt"D$PD$|U \$<ȃD$tԅt7tP|UD$ jЋ0؃u( tWG *3ۉD$\$ t$|UD$ >_jLt;xt/D$T$RQ@ЋW ؃tjD$  D$3ۄ, `3 ;yG 3Sv3ɉL$ 3҉\$8@L$ QSЋL$(Ѓ؅T$8;FȋA2t$$tp;Ƌ|$Dt$8wt8+fnɋT$$+p^ YTfnXPL$ *+ыD$$fn^ YTPL$ څu3E TjD$ T$,D$$99t Iux rt$0wq;u0wu @7A@'ApyAuD$$qpw qFwD$$H z u$ A@B JL$,ND$0w@AD$0AxtpNwHL$,B JHL$,B L$,8tƁjj L$u!u 0SG  $SG WЃD$Gqu>/! 99ƀ e(SG QWЃD$>t *u u؃WfD$8|At;u uQP<(T$$ D$tttGt t>G 5 G@G H4StWЃ , 2L$ƇaGƀƀtt9:t Ru j+t"tD9:t Ru j*|$ t| tG@G H4StWЃt$ uHL$GxXIPQ) t8SG tWЃL$>yd4__^[]Ët7x*@@%©u:UtUO 3;t'G |G@H30StWЃPhTW _^[]É_3_^[]_^[]7"DT5D{"DS$D$'D &D'D(D`)D)D+DX,D}-D /D0D|/D4DG5D47DUSVWU3EʉM> uw~tQP׋?ME؋EuQNDUP+UFDtuRusEMˋEN_^[]_^[]UQSVW? _h t3AUtƀU2ҋy u͋G,A8N8Mt1FHt*t%HtpjjVыM3j@Mj3@tFHttH t pjVу .@OH&@t@O3'O3'w~<uaF8EFHttPt pjjV҃M3j@FHttH t pjVу F8F<džF@uO,t?t3C'LJt3('WLJ|U3_^[]_^[]U8SVډMWQUEEEEE$ЃU3ϾOƉuȅ(DȋMHEE܉MtkjU>OE#E؋ȃ#UDȉMt9NEEEtGMUj=t1c#֍Oڸڋʃ#EEDʉEEEMEjjUMUEVjF;t1MUBtv r QuSЃMNG}UV|U_^[]Ã{4Es u63~;t@;|u܃EU܃HjȉE<ȃSEtVtx vE9ut9u@tx v9uEt9u@2}t,UBtq r jVSЃMUju;Eu@Eu;C4PEPC PT {4_^[]UEVWx@tKuStAjUOH;t-Otp Ew jV0уjUuOH;[_^]USVWPGUMt^DCEjh0@+E RP+uʉEiuʅ|ujӋ"E؅uU7u0G34G_^[]Ë@0G4G tcN;7uuO$F@FHNFuGA6GjVFF|UU 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~DtxJ5'UND5'UE!ȃNDQ ;U|;9Y~4Aj+ÙhRP$+uiu$3_^[]3_^[]_^3[]UVWUAt _^]ËUyIx yy|lK lKjVЃ _^]ËNDA ;| A;|~+A IRVЃ _^]_3^]Uu |U]U SVWU3ۉuj]tU}EPWMU9^ tX6tO]䐋jh8@+™RP舶+}iʙʅ|uUދv]u]}uWӋuW|U_^[]_^3[]UA@SM0GEMVW}jhu W 0iM+iÉE=@B| AME}?u +G]jhRP莵M+EiMuxtPGUm_^[]ËPGYu8GNDQ tPhTS ME8GGLGwND7FD_^[]Ë]uUQSVWjhu u輴M0i+iǍz=@BLLȃ0Gu 4Gt6+4GjhRPi+0Giʙʅ|uu u_^[Y]SVWK@0Gu 4GPG8GDQ tPhTS O t|fDwtgtcN;7uuO$F@FHNFuGA6GjVFF|U O G ȅuǃ0Gǃ4G_^[U SVW}w6DFE{ SC  t`N;7uuO$F@FHNFuGA6GjVFF|U O jjE}W_^[]U ='USVhD$ 2jP=5hqI D$D$ D$jjjjD$(jjRPjj RPjjRPjjRPRPj3D$PlqIӹHTEѹdTE识'Uth|TPhpIt У'Uu ^[]^3[]USVW}WUfGGڅj\Ve8uj/VV8u ET3 ؉u+PpUPfffu+G]PtUtsSuW0?3f_EVx_ |UM*tJVpUt2GPffu+VG|UG3_^[]V|U_^[]UVut|@tsEEMEEPu ;E+tEt;EEu@JfBu+эRP3ҋ^]UVuMW;EEE@,EEPu tEt;EEu@ t)dFu ,hShPƆdF@tB,эzBu+ׁ?s B,,RQ3ҋ_^]UQMU SVW~+~@<0KDuv>ttmjjjS tXtTu.hFtU~ȃFF tFjWPSrI~ FFjuuSrI}uMrI؁3'uQ3_^[]ËM蛾PEhT0 E hF7_^[]UE USVW}M>tuFN ;v%+;B‹؋SPuEF ^ N 3;u&6|UFFF ~M_^[]ËUMjRuQrIuEuHrI؁3'uEQ_^[]ËӋ}PhT7 hFE8_^[]US] V13҉M3ɉEMUWtl;\Ft A8_^[]ËXFWTFxUȃM u _^[]ËXFSuP^DE TF3XF_^[]èt pUt"tu90tpMȉEEE @;Ft (WjP҃=td;uDE Mt(0WjPу=;E MljE +UWPhTV_^[]ËE􋀐@@thTVX_^[]StUSu W;CE\FBhTV_^[]StUSu WBdž\F TFXF_^3[]UQS]VE8W@@t}@`twp8ul3;‹} +;EB t'WPuNB Ɔm3;_^[]ù@9M BM =3ҋM ;E@E;| @EϋE}WQPRVЋy E_^[]À}tW uA ;3_^[]UV񋆐tu uRVЃ^]˃t tu/U}(E3ɸU3҉EU~tt u;M™EUE+tjhRPߑȋEU+pi؃+M׋}ȋM lj}U3ɋtfD@AuFPjhFTEdž~PEUt jjRP"t(fPp؃t FPx~PuڋE8uD؋_^[]ËEG3_^[]h, Tu_^[]UM E;u A]3]UVW t=NDu9N@t1}EuN@hhDhU}udž _^]Ë_^]U`S]3EщUEE]VW| u r3۾]u }u/;u+tyh&'lrI_^[]VHqI3_^[]Å|tu]UUE3ɉt!DžDž9ED;tB3Džt9t@;r;u@s ;Gׅ |s3}؍B}EԋM|-t'Mb‰Ei+iE uE؉EW3ɍ9PD9PDPu\rIrIt='U='ZP\qI؋ʺwM]ȉEú/$j؉UЋwhȉUE/$ωẺUUًMЃ]]3ыMʋUЋE+ i+i+ERPxM+i+ΉM]}]3rIt/QSЅPrIESЅrIt}t'QWЅtPrIWЅt_^[]U`S3UMEEEVWjbGHttHt pjjWуuUutuh TWF 3ۋGHttH t pjWу uMEUMQu/Eu09EtMU腩u3ۅËE 0_^[]ËGHttHt pjjWуuUuGHttH t pjWу uM\E 0_^[]ËE 3ۉ0_^[]_^[]VWt FHttHt pjjVуGuY\W|UtFHttH t pjVу _^UVuFu \V|U^]WjGzEGzEG PtDGGtUV3fjtUt@ @PvE@<t F|^3_ÅtN3ҋ =uP|UG^_G_USVW]~8-M@QQh TPft 3h TAuPh\ TN؃ P t:tP(NFuNFuGH+ttHt pjjWуO8FPbGHttH t pjWу S|U]QMQQh TPt 3h T]uEPlX9VPU\EuPh\ T/ E(t:tPNFuENfDFuGH+ttHt pjjWуUFO8Pu|Uu0uUPtNFF MXGHttH t pjWу tRPuPhT TW3h4 TW{ []jLJ3_^[]ËMOX_^[]SVW9p6|Uvu8t|ULJt|UƇLJ_^[U S]3VWU3EEt8׍JBu+эE3ɅjD9MPEDP5] uXE}t;u$t ?:uhIUED}7|UEt3|UE_^[]U SVWN@tWNDt諾PGt3džPGnGdžHtpG|UdG|UdždGdžhG|Udž|ULFdžFHt 3D$93|$| ˅toGu'UW@W|U|$O D D-4|Ut|UD$DLF|$@@D$|$;kS|UdžLFDF|UdžDF`F|Udž`Fl|Udžt|UƆdžt|UƆ,dž|Udž,$|Udž$ÒpF|UxFdžpFdžtFt$P'U@$xF|UdžxF|F|UFdž|FdžFt$P'U@$F|UdžFG|UdžGH|UFHdžHtFtPtpjjVҋNHIFHIHFHttH t pjVу tt GOV|U_^3[]VjEjFEjFEfdž< 83FXGFFdFHFhFlF@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žƆ^USVW3|$  R'D$DE_^[]ËE90U_^[]ËE_^[]ËE90B_^[]ËE90C_^[]ËE90@_^[]ËE905_^[]ËE/DȋƉ_^[]ËE908_^[]ËE900_^[]ËE901_^[]ËE9tƇ8H_^[]øH_^[]ËE90)_^[]ËEt4t%LJ_^[]LJ_^[]É_^[]ËEi_^[]ËE90_^[]ËE_^[]ËE90-_^[]ËE90,_^[]ËE_^[]ËE<_^[]ËE90+_^[]ËE<_^[]ËE@ƉD_^[]ËEP_^[]ËE_^[]ËE907_^[]ËE903_^[]ËE902_^[]ËE904_^[]ËEH_^[]ËEL_^[]ËE90Ƈ8H_^[]ËEʋ؉L$9d2|9`s(P9TuP|UL$PT`Ɖd_^[]ËE$_^[]ËE90_^[]ËE90G#LJHf8_^[]ËE| _^[]ÉL_^[]ËEu<_^[]Ë$Gt3A#u|_^[]É<_^[]ËE_^[]ËE90*_^[]ËE$_^[]ËEu@_^[]Ë$&Gt3ɸA#u|_^[]É@_^[]ËE_^[]ËEt!Ƈl_^[]Ƈl_^[]ËE90`_^[]ËE90E_^[]ËE90D_^[]ËE90F_^[]ËEP_^[]ËE90X_^[]ËEƉ_^[]ËE_^[]ËE_^[]ËE8_^[]ËEi_^[]ËE_^[]ËEi_^[]ËE_^[]ËE_^[]ËEƉ_^[]ËE90_^[]ËEffh_^[]ËE%l_^[]ËE_^[]ËE90T_^[]ËE90_^[]ËEtU_^[]ËEuh TW+_^[]Å_^[]ËE90_^[]ËE=~LJ#}LJ@_^[]=@@P,xU,_^[]ËE90T_^[]ËEƉ_^[]ËEH_^[]ËE$鈇pq_^[]ËEL_^[]ËE _^[]ËE90V_^[]ËE90W_^[]ËE90Y_^[]ËE90_^[]ËE90`_^[]ËE90a_^[]ËEd_^[]ËEh_^[]ËET_^[]ËEX_^[]ËE\_^[]ËE90h_^[]ËEH $xDl_^[]øl_^[]øl_^[]øl_^[]øl_^[]øl_^[]øl_^[]øl_^[]ø l_^[]ø l_^[]ø l_^[]3l_^[]ËEG_^[]ËE90t_^[]ËE90_^[]ËE_^[]ËE_^[]ËE90_^[]ËE90_^[]ËE90_^[]ËE90_^[]ËE$鈇_^[]Á'hNAlD$DE0|ULJtVU 3_^[]ËE0|ULJtVU3_^[]ËE0|ULJtVU3_^[]ËE0|ULJtVU;3_^[]ËE0t%>u  T|ULJ|ULJtVU3_^[]ËETP|UPLJH_^[]ËELJHƇ8_^[]Àt|UƇE0|ULJ3t.VUu_^[]É3_^[]ËE0|ULJtVU3_^[]ËE_^[]ËE_^[]ËE0|ULJtVU;3_^[]ËEPUD$tjtUЃD$uXP|Ut.ff3s|US|UޅuLJ_^[]ÉruڋƉ_^[]ËC˅t ȋAuQƉ_^[]ËE0|ULJtVUup33PvD_^[]ËE\$ TntiGHttHt pjjWуt S}3s GHvH kpjWу _^[]ú Tm1GHttHt pjjWуT$T$|$ڋC C L$;EƋ;uL$ s |Us|Us |Us|Us|Us|Us,|Us(|US|UL$O T$ӉT$مR73|$GH:1H &pjWу _^[]ú TZlt3ҋ|_^[]ú T8ltMg_^[]9ufjjU؃tGhLTUCt CC*j|Us|U <{S|U3ۉ\$SU؃OHD$t+D$t"QD$tqjjWҋD$j ӹ TkK uˋT$jjQPgGHttH t pjWу S|U_^[]S|U_^[]ËE0|ULJtVU]3_^[]ËE0|ULJtVU3_^[]ËE0_^[]ËE _^[]ËE(_^[]ËE0|ULJ3t1VUup._^[]É3._^[]ËE,_^[]Àt|UƇE0|ULJ3t.VUu_^[]É3_^[]ËMP {_^[]ËE_^[]ËE _^[]ËE_^[]ËE_^[]ËM$P  _^[]ËE0|ULJtVU3_^[]ËE_^[]ËEj,_^[]ËE_^[]ËEp0|ULJptVUap3_^[]ËEx0|ULJxtVUx3_^[]ËE0|ULJtVU3_^[]ËE0|ULJtVU3_^[]ËE0|ULJtVUM3_^[]ËE)8 _^[]ËE0|ULJtVU3_^[]ËE0|ULJ3t1VUupA_^[]É3A_^[]ËE0|ULJtVU43_^[]ËE0_^[]ËEGHtttPtpjjWҋOH<uw8w?@ABCDEeeeeFeeeeGHeeeeeIeJKLeeeeeMNeeeOOeePeeeeeeeeeQeeReSTUVWeXeeeeeeYZ[e\ee%%]ee^e_ee`e%aeebcdDDĉD؉DDDD(DUu@ A VHtFHt8tyGHttHt pjjWуD$PdT$L$D$D$L$$O8h0pDD$$aGHttH t pjWу 赖\誖@0tSVЃvDh TW踔p D$tKKt(92t RujD$Kdžp{u Ӌ1D$tHt-3ҋsu dž0KDdžIDG@t@`tH=f_^3[]̋@<tNct Uu@uGE+jhRPAȋڋE+i;]|;Mv M]}}vu]Ut C؉]u4E؋ʋp;}$Au ;|U ؋щ]Ut C_^[]VWG;Fu!G;FuOFtt Fu _2^ÅuOFttcFtu؋OFttʋDFt_^Åu_^UQVu@ A uK8F@uF@<ujjj\ tvDE h TP 63^]UDSVW2\$ 3|$t$0D$G(ЉT$$tD$A<uD$]tG(t@<tD$2D$E EtӋ^L$$3҄EʉL$$o t-G@t3D$,D$(uT$,, TT$(3҉T$(T$,< TL TE€WtPVQhX TWŽ|$$to+ut h| TWnh TW葎D$$uG@t@`u,h Tu G@t@`uh TWQD$,F0@D$Lt$8T$4A B u@T$48F@u7@<ujjjj uRT$4B A |$$D$Hct U?qt%#vD>h TW腍 3 t 3Ʌt֋yRtNd=8FXuvDhTW dUWZ@A@;tI<;;B<UTHL$ Zt$:Z4[:["t!t$L$ WD$:WXD$:X;L$ e:euPt"44dnx dL?L$ t$|$$u ~@&\u D$ f9`tuf`t$ f;`t$8dt$ ;dt$8t;\:utP:Quu3ۋ\$ thh:utP:Quu3]llf:utP:Quu3"tu eL$ %@u*K< 9\$ ;A<T\$ |$t?|$t;?p;^t1zbAt|$D$1|$}hh:utP:Quu3ll:utP:Quu3t D$zl:utY:Xuu3\$ .: utH:Juu3D$L$xp8D$$D$HT$(t+;r'|$PhTW" \룋D$D$@@t؋D$(D$(WT$(fD$@3ɋ|$D\$@D$<ȃD$@D$4t4t.pP@Tt$dž28)Ytt Z2Ɉ[t9t Ɔ[ ]*e\DhEiVTU:89 G@t-@`t' ujh@U jtUu";2ҍYƆZ@ @`D@jtUt@ @`D@tTtPtPU\t2ldfhf`F8F<_^YË303# dždž|U\|UV|U_3^YU,ESVWUhIEEhG]TthTWY_^[]Ë<:uhTW3_^[]PhTmtFu;r;s!u7PhT@uG;ruEVM<.E֋+U;w*+ыMUVU1/t;utEx.twu;s}Z_^[]_^2[]U싁SVW8|tPBFuTfTfFTF|PpqIƅt0hQPӀtPU|T-u~|BJ؀G؈_tuݍ|PbpqIƅt0hQPӀtPUhTƅt,hQPӀtPUuIh Tƅt/hQPӀtPU_^[]3_^[]U$SVu3WىUhTV]EEEExjT},jֹ$T,t jֹ,T,t jֹ4T},t jֹ<T^,uEjֹDTI,u0jֹLT4,u'VhTTSqv _^[]ûCu] u]VhxTS?v _^[]Ãttt EuEj@W茫t2jEPE+P E~EE}E?[GG}t"PDu <:t<.uFFu<%umjVhT6 thTutFFtAP Bu"PCu<-t <.t<_t<~uFFu<]uFhTuotj:V脪tWj EPFEV` Ett:t3j:赤8+lFtZpWfEEt8+tA-IDEPhTEj PblGE슏^IPhG ID„P TDP$TDP0h(Tc$u F_^[]Àt|Uƃ}@83_^[]Åtj MFQP xC=tQj EPV M ؅t9uv,VhTul E W|U3_^[]uUMuW|U_^[]U(ESVWM3ۉ}I Ɖ]M]9:EEuq^ TDP$TDPhT`ȃM܅=VFu+ыMV"u|UE}<0:F>:ut2j:V譡tGj E]Pu 9uu.;u&EPEVuP.]EEEuEt(8t$ShTVƇWk SƇW|U3ۋux,Vh$TuƇXjE @EfEƇX@EN_^[]3_^[]USVEډu3ҸE3UW~tt}u;Mы™EUPB+tj™hRPWȋE+pi؃+M֋uȋ u VtM3_^[]Ë닀YXWEt}DE MQRK}}D4h<TuiE ECHE_^[]Ê[҈UEDDž|~rxMQ贒uEECHE_^[]ÃtA}uB}D4hXTuiE ECHE_^[]EE_CHE^[]VW|U|UB4yB\\t[h|UlLJh|ULJlhhlldžhdžl]]|ULJ|ULJ|ULJ|ULJdždždždž|ULJ|ULJWWXX~tG@ƇVh|Uldžh|Udžl|Udž|Udž|Udž|U\dž|U3dž\~3u~ dždž|U(dž _^UhSEV]WC@uEEEEEEEEEtM̉EEEEu }>NFudG+;B|UǃdGǃhGVtUdGt=VhGtUumdG|UǃdGǃhGu|Uu|Uu|Uu|Uu|U_^[]ÉhIUEhIUEhIUEЃ}p}f^EЋPEPEPEPj=8Etm0htTW E <:tP,v<:u逻t|UEƃ@@@tj?hGtHtPUt]hjPD hjP.  thPP E$thPP| ƅQjPQQPPQt$PUEuh|TSWbtPUEthT;5pqIƅt4hQPրtPUuL5pqIhTƅt,hQPրtPU3( (u}u}u EV|Uut >t @@tV|U3uMt 9t @@tQ|U3ɉMuMuu9/׋Vbu|U EMt-Q.u|U Et#@<ueu LJS Ƈe2ψZtNu?9u7|ULJƇ[DƇ[9u|UEu|UEV|UfLJZ2Zu-u)Y[]eEfLJYEƇY@@t tƇe׋j9t&u|UUEMt&u|UUEt&u|UUEЅƇk<tIEPUL~hpTS] ƇkƇ\EuЉE@@ t3\u*hTUht8hTU(uUhtuU3ɋljlh >tVUp8׋ыErBu+t| . u @tIxuhXTu\WtaыErBu+t| . u @t&IxuhXTu4\Zt\ыErfBu+t| . u @tIxuhXTu[[tZыErBu+t| . u @tIxuhXTul[Wt&Uߋ t ƇW2UߊXt;u ƇX2ɄutZtƇe7|Udž|UFPhjP膖F` FdLJHtWыn} @8LJ0KDLJIDLJ0KDLJIDrX\dhlptx |x|`P24h2 1E‰Ej+A$hRP ME+H iMux1r'hDQMH MȉH$Ct @FEPEPEP[ tu}u֋N@ A PvDhTSWu؃Mԋp9Hs\M9HsNhTSW3@@t tƇttƇs}t}EF@ϋUAW|U}؃Eĉ8ttYIPTDPwDhTS#Wn>MEԅ9FE/NEȋ‰E1\3ۋy@uL+jhRPMȉEU+iMȋE;E| ;vEEvu}ۉ]]M2҉}M̅t%9Hr2҉LM G(t(GthTSUǃ GƃGG(t($GthTSUǃGƃ$GG@ ‰xG|GuY9uQ2MQhLTSdU hTSVU輺EľYhxTS.UȀnGtpG|UxG|G tRQhTI UpGpGnGumG׋XˉkU SVW>,p;L$tt&++pfnfn^ YTX+fn^ YT8@@t 3_^[]ƆntB|UdžhTaHu _^[]LJ+u Ɔa΋VHSq0_^[]+p;L$tt&++pfnfn^ YTX+fn^ YT@&+p;L$tt&++pfnfn^ YTX+fn^ YTHƆaa@tU[t(ZtWtvDFXPQh0TR>RV*_3^[]VtƂ`8ƆGƆ`Gt džHHu džH)ʉWΉƆFpFt,0$jƆjfֆvjj,v3^́@w8teI?"D$tDøøø ø@Áw3t+ttøøøÁt Á wOtGw,t$ttuuø@øÁt9t+3ø Áw2t*@ttu(øø@øÁt t3øTDZD`DfDlDhDWQUu_VNFu+?"uVGPW Nt |>"uD>N?/tW|Uh IU^_Åt |>/uD>^_SVWGHttHt pjjWуϋP u6h0TWN vuËt*fD3s|US|Uޅu܋GHLJttH t pjWу _^[U SVWj3EUE@V‹N >tp;Mk|;Usd;3u;E8K v |Uv|Uv |Uv|Uv|Uv|Uv,|Uv(|UV|U$uu_^[]U4SVWjU؉MEUEj8jU؃].}fhtU}u j;V0E܄t@ t uNFuEEWPhTTVƅSt׍JfBu+эyAu+&et)FN< t < u< t< u t FNIuƄ }t"GD t u Hue}t< t< uFFuu{=PUCVUC{tEC,&8"u@j jP} CȉS+E;|;KSEuDpT&t C0:xT t C2}=It0s |UVUȉC "VCT*>.uFuj.VuֹTrTE}}}EЅPE/Et5teϋƊ:utP:Quu3s|UVUCQ}C$OfGuU+NFu+;r)M+‹ЉEt;utEЀx.tuVhTuEI T\ts(|UVUC(VT0ts,|UVUC,*Tt!s |UVUC FE܅?86ptf< t< uFFuj;V}܅}>jV~E܅UKSoK thUEEtttCC%U‹M SKu C|sCC}{uEtPUC({ uk}tdj?W~j/W|t@+FFPtUC VWPeC K CuEu|U}u {'s |Us|Us |Us|Us|Us|Us,|Us(|US|U3_^[]Íp;rf>/N;su|U[u|UTu j hTVE  u C2>#tj V|tj V|tEPSP3E}}$PE>.uFVUChE_TC$FθT:utP:Quu3teθT:utP:Quu3t5VUC u ECEh IUMC ٸDh IUMEAˋ]DȉMTC0Lj jVH CS7VUCu&E VUMCɸDȈM@PhPSzFFuߋE@uhIUC}u؊Nu8Nt C CK162ɈM{NNCtwtwtlF$:C$udi>QF~t7@PhPSyuC{߄u ?t{]E@E3tMt1NCtt+Mu)t2ɈMMu6$}E{1u ~1v|Uv|Uv|Uv |Uv|Uv |Uv(|Uv,|UCSFC F ~C0fF0|UfD6uM3u؀~t2sɺ TsTs DsssPhTuIB$}utF _^[]F _^[]-EQEjENEdEyEEUS] VW}M}u>jjUEOLTEPUMAlj}@dIƊ:utP:Quu3uP2u}->uMYًC_^[]hTTVuEMYAhtUEtBVhW2uЃ fʍqAu+t]| uVtr2P33P|Uu ]s|U S|U}t t VX3_^[]óuVhWЃ uVtOj ׹ TO uϊ„t< t< uAAujjQMRUuuW|UtV]C_^[]ÈX]_^C[]UESVWE K 8tQfDAu+3ɋW trBu+3;t _^H[]ËKtQAu+3ɋWtrBu+3;uKt#Gt:utQ:Puu_^3[]_^[]U$SVWjU3E3U}u93aUEPEE7fS‹K t;M ;U{0t } Kto{$tW}uQWGuu+VFu+;M+EЉE4;t!Ex.#ыMCEOGu+uUj?Vst΍QAu+t>/t"V|Uh IU΍QAu+ʉM;`WVu K;}t <7/<V|Ujj8UC tPUF CtPUFwC tPUF [CtPUF?CtPUF#CtPUFC,tPUF,C(tPUF(CKFNC$F$C0F0C1F1C2F2EuF}uV|Uu};tlStUt 8@?u}hEjWVn3҉Et DB;rD3V|UE_^[]v |Uv|Uv |Uv|Uv|Uv|Uv,|Uv(|UV|UM_^3[]VtdWv >|Uv|Uv |Uv|Uv|Uv|Uv,|Uv(|UV|U$u_^U ѹISVWB IXTEȋB EBE؊B$D$Btt 8.IuIz0QrTD$TrrDD$$|$#PDL$(Tz2WQSIVDPh`T].,_^[]U SًVWE􃻄XteCHttHt pjjSуEj~ `ϸdID:utP:Quu3uj袳E}h|TW2}WhT謻6t:~t(StE0ELEZE      EEEEEE)EDE_EEEEEZE  U SV33WEH$@ Muz>GHttPtpjjWҋMыWEu M衶OHttA t qjWЃ UE_Ɔ@$^[]ûU SVuWv F8hPTEEj P!N~FWPUX؃t#=rIׅtׅDF^~6LqI~PtVPqItPXqI6|Uv|Ut覵j_^[]ËuWVEhPTEԍEj PEEejPjUEE?pj}jxH0tU؃EuQP|UxH8t$@7w|UW|Uu}xH_^[]CtF΅t ȋAuYދxH3_^[]SVW3Pt:O v$u ǍN_^ [_^3[USVWM3҉}3U8=AM<%8u AM FU3ۉuWD33ɉE;EuN}M}ufDjh0TVc t1jh4TVO tZP/E$H/Ejh0Tu uu ujh4Tu uu@upEp uZX/E$/EB:,$>*u7NuFMUu:E;ωMNNj} j EPVE @ @ D ˀ uj E PFP E\}UG΁@}~uE};}}6}.U}B]M3M0E$@0ERR7RR#RRRRRRRRR RRRRR|RRkRRTRR=RR&RRRRuEZrB @t+FB@ DDD Et&HB @ DDD UAuUU9u ]G@tOF IDTGtOF IDTG $0E_^[]ËO%@=@uNOg@tNOS% = Fu G4 tW'tGGm_^3[]f*E",E+E$+E+E+E+E,+E+E+E+E+E+E+E+EP*E        N-E|-ET,E,E-E,E7-E&-Ee-Ek,E,E,EW,E,E,E-E   .E.E.E.E.E0/E0/E/E0/E)/EUSVWu DŽ$ķS$M$3|$LP$t$\$t _^[]Í$$E8EYTDŽ$ķS$%t>MfDWPӃEF@t$TEȊ%uA9%u"AWj%MӃEFt$TT$XL$|uHAL$X @L$L  @t.@|$hy߁|$h D$X D$||$hHL$XʁL$dt%L$L @ɸHȋD$Xt L$L @L$PD$|D$XD$LH$;E\$L\$l$D$pu%O~ fDt$Hj ӃtpOFD$pt$HPӃtTD$LFt$TtO~t$Hj Ӄt,FOt$T|$H$$Ȁ8_^[]t D$\D$\ T$l|D$dD$pډT$lD$LD$\u5t} I3ɉD$\7,kND$\D$LuȍAD$XAu+L$XL$PG+t$t$Hj"ӃD$LFt$Tu*~%t$HOj ӃFt$TOD$Pt@L$\DHD$Pt,t$HPӋL$dAL$\D$PFt$TuɋD$Lt-~)t$HOj ӃKFt$TD$L|$HWj"ӃFt$TD$LD$pD$XD$lD$\SD$$D$dDʃ|$lL$P$wtL\$pT$lt$\SjVRS\$x[؋$Owru׋t$TL$P|$`|$hT$`$+Ë$ȋD$Xt|$\u 0JO8|$PT$`~+|$P0IJT$`υt|$\|$PT$`u yT$`|$PT$dL$Lu t O|$Pu4~+Dt$HOj ӃFt$TL$LT$dO|$P|$HtWj- tWj+tWj ӃSFt$T|$XtE|$\u>Wj0Ӄ/D$LWtjXjxӃt$TD$Lu;t4D$P~'@HWj0D$XӃD$PFt$THD$PD$`$@D$`;w0@WPӃD$`$@Ft$TD$`;vԋD$LDD$P8fDHWj D$XӃ:D$PFt$T t~t$HOj ӃFOD$XTsL(t$HPӃD$XF@t$TD$Xu֋D$Lt$HOj ӃFt$TgWDŽ$%fք$$f$$fDŽ$yAu+ϸ +L$LD$pD$X t @t @D$XD$ht |$dt @D$h$ʃ-E$$$Et+Gt Gt#GD$Xx&=FEMPh8Tt$xW)D$pT$hxID$LD$f/r ^If/s;эANPh<Tt$xWmL$L  t lG t $ Et $ GfG$ $P$P\|$X$D$h$MWPӃXD$XF@t$TD$Xu!@tL$Lƙ QD$L t0|$Hu0f0_F^[]Ð4E5E2Ea;E~3E~3E9EUM UA;AsA]Ã]UEL$D$;EE D$ EPuD$ȃt!D$ t;D$D$u @]]US]Vu Wu1j tUȃtYF 3FF_^[]ËV~B;r;~v'WQxUȃtV~_F^[]_F ^[]UE $PuE0pG[t(ZtWtPhDTkȃ Mt8EыBEBu+UWRы6u|U u+Ot3Y GW|U_^[]ËNSQt!MpFACDAA3_^[]ÅtE׋_^[]UUMMSEE9؅|MW}MVUt Gu-Ep;}Au ;|MUt33ۋr6tuvPUt uMu^_[]U SVMMWEE8tZu]@@uNt Fu2MËy;}"  @ u ;|؅tu_^3[]Ë_^[]QV1ƁgWTHXt1jjjЃPhTV A_^YËt;jVЃ WhTV tRWh TV A_^YÁGFujjG  uh0TVeA_^Y_3^Y̋@<0utw w3øU3D$dD$D$ D$ESVuEWfff@EȋFD$ #Ft&~Hu+V D$ F$|;sʅuL$5D$PQ D$QL$F F$ubF( F,uZ+tpL$ fn^ YT;t+fnXX~F|L$E u9uD$ 2D$ F\@4t'L$QL$QWSЃD$&8D$~Ht{D$D$PD$PqD$@4t<~6|~w.|$~'L$QL$QWSЃD$8D$c|$c~\L$ ~H|$8@<t!8U|h@TSƆxG‹|G t~luHu <tspGuj tZ@ DtLt'u";D|8;@r*T;D;@@t<~LWtvX$ ~LuWt$v\ twV\D$Pt$QuTG0D$ tBPhT7 A@t)@`t#t$ h<TQD$, )Ƈm~Ltu FXF V$Nu 9ND$F V$;V;V +L$D$tvum@@tB@`tƇU3_^[]ÃuhTS_^[]Hw1$LEIT(JT!(JT(SDJT SIPhTS7 8_^[]Ë@@%u:UtUE_^[]ËD$L$F\QL$T$Q@4WSЃuY8D$t|$ELJP$<uUth4TS3_^[]KEKEKEKEKEKEUSVW}ډ\$D$G G$uGG( G,u?+tpL$ fn^ YT;t+fnXXE \ uGyXuALJG|΋E RP3_^[]Ë@<t yXD$@\$L$ t? L$ GQjPGЋȃL$ L$ uLT*PS_^[]Áu7L$@@tlT+  ;L$vTPSn_^[]ÀD$IID$,ESQhTj PL$0D$ ) PD$0P  B˃ QAuD$+QS D$PA |$ u D$ƀKCu+ًL$ ˉL$ |$ `Fu2htU`FuhpTVN_^[]Ë|$ 33 `F uJ A`Fu6GGD$#D$tD$GGBA;|\$;ϋ}t[`F GL$  L$g6_^[]Ë\$3;D$PD$ QSЃD$ yD$QD$ @t}( L$PhHTh0ThLTD$HhP\$PKCu+مtL$w9bG@E3t!t;MEUuuEUuE6jh@+|RP)EM+xiu+ tU|KG O@7WEƉM#‹OD+t$tIRVWujhRPPʋE+piQVh(TS _^[]WujhRP ʋE+piQVhTSD_^[]À8us‹O#t/j?S3$t>?tj/Sc#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+BPtUEuu|U3_^[]WuP5 9t@<GpWt 8V88t @<tol tfhTWU u _^[ÀUtƆUƆd@<tA( A,t _^[_^3[UQEV1u EFXEƆFPFTFhttd`GtT@<t>xXu2džΉRP^Y]dž^Y]USVWj ڋtUu_^[]ËE u"7F@G w_^[]Åt6CF^CtpsG _^[]ÉwsG _^[]ËF^pG 7_^[]UVWtg taN;7uuO$F@FHNFuGA6GuVFF|U O _^]SWڅO twVwtftbN;7uuO$F@FHNFuGA6GSVFF|U O G ȅu^W|U_[U$SVWu 3_^[]Ë} ]uEEE];q |JQ;|A3;tbQYtU;r |;z~Z; t9UMJ ]뱋t&;r |;z}B:Jt ً 녋]U_^BAEEA[]UQSVWu_^[Y]Ë] }tuSWЃB ;|7@;Z|0. KV~ ^BFKB Ɖ2J_^[Y];|;Z|BFBV F~ _^F^[Y]UQSVWu 3_^[Y]u ]S=;^ | M ,;N}tqpp M ;^ |W;N|PFtN VH PNH7_^[Y]Ëu F7_^[Y]QSN7H_^[Y]_^[Y]UQVWF ;|9~3|1uB_^Y]ËFBVtE3_^Y]vP<;t _^Y]ËWt"G OJMB GB3_^Y]ËuM3W_^Y]vv OЃ3JM_^Y]_^Y]UVu 6|UV|U^]U SVWp@ډEtbtX6tRE>Ћ腘tG;tvt%QuhTu_^[]_^2[]U S‹VW3E0ujtUG G@eEGt~PUEjtUj:utj @jP PfFϋEWVat(Cuut 3ҋpE83_^[]6|UV|U3ҋA_^[]u|U3ҋ _^[]USV3WE]tejtUF FADFt/PU؃΅tWVStt(Guԋ]t 3ҋE_03^[]3ҋlS|U_^[]3O_^[]US] ыMUVW!|u~TfTB_^[]Ëͫ⿉gE#EͫUȋڋE gE#΋u EM}3ًMˋ]+ }E| cjhPW莏+jj<VQ轏؋}+u}+Ƌu+E PVRSuuhTj u$_^[]ËùJrE.‰EUE ڋȋE E.ΉEM}}3UO|wEjhQRW覎u+E jhPVΎRPuWhTj u_^[]RWh Tj u_^[]U E SًM]VW|sPQh TjSÃ_^[]Å|@s" PQh TjSÃ_^[]Å| @-Mx@EU3ȋ3x@ΉEM}3ًMˋ]+ٸًMPE SPQh T,|qs"PQh( TjSÃ_^[]Ã|?AM@EU3ȋ3@ΉEM}3ًMˋ]+ٸًMPE SPQh0 TujV_^[]= (|s"PQh@ TjSÃ_^[]='%|sjPhH TjSÃ_^[]jPhP TjS_^[]UE+EM M} SVu$Wuts]};|;s_^[]jhQP苋SWRP‹؋E,j+ƙhRP誋M(+M E iM ;|;s +ً_^[]_^3[]U SVW@}] EU|StMRPQSW(uEE_^[]U SVW蠲}] EU|StMRPQSW[(uEE_^[]USV1WfEWfE苆fEfE]fEEʱh‰}lE+‰Mfn^ YT;t+fnX(M FEWf/ẺUvE YTEЋ轝^EEWf/(,w YTE{^E0lj49u 9E;|;v‰}܉ެިA}CAu74,0(;|;w‹ω |3+jǙhRPȋE+iȉMu uEMΨ+ިάެx<=7Av3ыME^YTM^(<jhQP<WuRPq tXЋ$thX TV`_^[]Ëtq9$ $$$e}xJxG‹|G tQRhl Th T 40RPQWEU܅|:'v&jjdPWRP譅EU\|u}M}ԉMDjjd8QWRPiEUEUEԋEEEU܉E@,(QPSW EUą|='v)jjdSWRPۄEEUY|uEMEEM>jjd`SWRP藄EEUEEEEEEċE}܋M;| ];w؋|t ˋ+MEWfEEMPQMWS|u؍Muw t E@tNj]EM̅|J'vjjdSW荃RPuu考U,|tjjdQP&SWRP]U EEE rEhPEPEP|P40{PQ,^(_ JPDPuuQ@" TPuuSW PuuhD!TDLP_^3[]UVu v|UFtPE@ ЃVF|U^]USڋUWE MGPWO G_tUV3~?jtUȃtA APvEA <t F;|^_3[]Åt#N3ҋ uP|UG^_[]G_[]U S]VWEwSPGЋ E0t4fSuppGЃu vuMWOj tUtpStUEtUSuPEFEȉ^] PVt G_^[]v|UV|U3_^[]V|U_^3[]UQSVWwGuSЋ E0tuSppGЃuvu_^[]ËMWO3_^[]UQSً‰EVWt?suPCЋ 46t%@u>uCwwЃuvu_^3[]Ë_^[]VW39~~ D֋ G;~|6|UFF_^U SىU3҉U9SMVW<7FEt0uуth t_N;7uuO$F@FHNFuGA6GSVFF|U O KEMnUBU;SO_^[]UUVu ;s B3;r3u^]UM V;MuVUur;ust-:u/t"B:Fu"tB:FutB:Fu^]3^]VWFt @Fu&Nz;},Au;|Ft_^ÉF_N^_F3^Uj`jUȃu]ËE3]̊tЊ€:t AAЄuSVWyDtfDPtGGuj Wpu!j W_uPWOt1;vfP謚tN;w+FFPtU؃u_^3[VWS 3_^[̋A#tAAètAAètAAè tA AètAA2A@AUSVW>H؃S(US,UfUҋu cuWƆgfEMUt/t"ucG#GtPGFSK >G#GtGƆg*TtЍJBu+3ɋƆg#tE; ;UGt Gt t uA+UMrw un\ueUuwQRhH&TW@@%u:UtUEGPGTM t)_^[]À}uh,&TWƆgh_^3[]UQSVWE23ۋ7Acw 3_^[]8(Gt380E_^[]8\t5t8ft%,}G ЈUҊuƆ(G8]t4=t8ft=,}GЄuƆ(G8]ufub,8G8fHUt7ƆG_|UUu _^[]ËHtt8gu ؅u\0tI=|B=t=u]\t (Gth|&TV _^[]U(S]FVWU۾FDƾIMȉMBy Jy@۹FEGEDF GDƍuVuVQ4苫u9E۹I&TVDPh`JT1 Et|UE|UEV|U39EDuEI&T@ E1V|U _^[]Ãu)Ӌ|-&T|Et-|FMMM썈$G&G+pFMhMlM썈GG4:EMU|UE8EEȋEMEȋEM8uE&T2Eu 8t"j?V+tV+Ph,8T薹 VUEtiUMQMQuMPuuSu|Uu?u۹I&TVDPh48T3M V9|UE<8u_^[]ËEI&Th]tkYtt t%@&TjȉEMzuvuEE`}>UB 2B 3_^[]À\tt-&TjȉEyvuEEhlǹ@VEREh&TQ,Զ,ʍqfDAuE+PEPQRȧ9]E0|U&TIS]DPh&TfM u|UE8uD_^[]Ã}}EE E&T@ ihEVQ&T&TDPh'Tu+Uz _^B 3[]U SVU3WUGG8Zt8]u 8\t9_uGt9YuA8Ztie:E u^juыu3؃ uqU@Ft>ku5DFt+4u"wuG _^[]A ju׋u _^[]G 3A _^[]U@USEҹFFD]ÉEGVWuGuG҉E GDȍ GGMD>}@j ֹ&TvluEP'UhLT@DЅME 8Et}%TEt+8EEE荃F)hl<EEE荃FEɸI}E~ E؅ҸIE‰E܊tP<tGGuύQAuE+ux u$U؋PWuuutM訾]]UEƃ(Gtjֹ&T]u(uEP'UhLT@DЅ;ME t } \Dٹ&T]jtt^F~tPtPGGu}hT8T7^  \]ƃ(GtEEEE܍AE؊Au+MtC=t>EPU-EtC4EC8]ƃ(GhLTu谽]u6}hl8T7葽 S\H]Eh8T0R]jֹ&TstJthL'TS"vEP'Uht}_^[]̋0t5=|.=t=u]\u(G3US]VW} }F F u_^[]Ã~X~ FNq|;wkPQuBNP ~T NjVt:FHFF@~ N _G FDGFXFPFT^[]_FF ^[]WQu~ )~ǃ^ _^[]USVWEUMH+E E싆M@@u u4xt+@;G؋SR0PS 0UًM3;M QSE RPVЋ؃y] Q3;]ËGE+ȉEM@t6VPuM tEEVQPM EO(W,;]trUO GG@ӋGGDGGHGGPOTǀGEGE+ÉWGEG\3G GX_^[]û7#GX;]t 7_^[]Ɔ3ۋu6|UV|U_^[]UM UVW@t0ύQDAu+ʋQM<W|Uƃ_^]Ëu6|UV|U_^]US]VUЋV;s#6|UV|U^[]W> MtFH;v}ww э;r]St$PExUtu.u|UtUuV|UG_^[]ËV^]>SuP^ 3_^[]UQVuUtƆUQDuSu8ut@ht7@@t%u MtUtƆU^Y]ËE 3^Y]UEE ]UQVu utUtƆU^Y]UM@@t:}t4uE ]ÃuE ]3]USVuW>Ft FuY=t6=t/Yu&@@%u:UtUFFtXC\Et0|Uu|UC\Hu2K(K C,C$OpˉGt;C8t)PDC8uK(K C,C$OpGtE uU8EuN8duF8Yu>ȋ򋇀+C S$|uht'TW޵4_^[]3_^[]USVW\G ƃ`Gx  Lt t"@>'Tjku+vuh'Tuuƃ`G_^[]Åtj'TjtsGwtPtFFuj V[uj VJu PV:+ rj 'TPjuOF s2`G3_^[]_`G3^[]USVu MWtt? =Zt.eu%Et Eu E3ɉM|bfj:7gFF-P躁t FFu>t'TjAiEHu'Tj ift'Tjht'Tj h|xu]'Tjhu^Fj;7ttJFFt"P̀t FFu>u ~;uF:7h (Tu uMuAM;3_^[]UVuWWD$@D$(I>|$hD$DfD$XhGD$$D$lE fD$tD$|HxT$fD$Htudžx_^]À@FD$0u@DF|UUDFT$HFD$0H (AD$T@L$d@<t9EЉT$L$,u=88t D$,T+Bw$ED$,(TD$,(TD$,TD$tRfD(Tj ȉD$$|fuD$@D$u |$ t|UdžT$,jt$(?8Gu8%GtD$t t2f|UdžtdD$t3(TjȉD$$euD$@D$u|$ u!h(T٣tMD$t3(TjȉD$$KeuD$@D$u|$ u D$DD$t5f(TjȉD$$duD$@D$u|$ uJtA|Udžh(Tu$_^]|UdžD$t.'TjȉD$VdD$@D$uҋ@<|9oG#GZfu=\G +x Lt ƇD$(0)TD$bj'TcD$D$t(fP{tOGu|$|$hD$j Pȃu#j t$ȃuPt$ȋD$+ȉL$r,j(Tbu!L$D$I@L$D$s2* h)TW_^]Ƈ|UdžID$t/'TjȉD$gburD$@D$uֺI@<t tVPI^ TDPt$p$TDPhP)TFJD$t@FtDFD$ @D$ u33Ҹ)TɋL$0E‰AD$t tu|$vIv+TDPh+Tt$$D$,u G|$6uL$8d|$h|$DD$,tYuUD$uGt$h +TVv D$t$DI+TDPhSVHL$(At$ыL$t$t jI u<,D$(@DD$8D$8PL$@蚶e$@)$fsf~ KuK$$$l$P$4 K$1h((Th?t$L <(tt u-(T d(TL(Tt$(D$QP  t$2ҋJv T$0B߉D$3L$Ij" QL$PGP D$t2@"TPW0D$_^]h(TW+_^]ËD$0H3ED$TPIQt$l΃ #L$dt$`L$4 ftWfD$HD$Lt$HD$GƋG#L$uhuFED$(t3X+TjȉD$< SuD$(@D$(u|$8ut$Vh|!Tt$ j D$tt$UI L$Ij D$| rփ WfD$XD$\T$XQL$UGjP D$th!TWvD$_^]Ë D$t D$T3V3LfJ0AAA GB<LJG=FGBXfD$(t7X+TjȉD$PxVEPh($TS蹷u5}Sh8$T萷  E HuthD$TW轏UGG\Gt;~\G0 \Shh$T϶  t  NP|VEPht$TSpEUǂx xu ]u+xG |GH u#h$TWdEUt_ƀUVtEu et3 |:Uu1pt(uEp p-tdu3<tƇGGPGTG`GdƇWX+TjCj FjP2à t;|;|*r$wPWTw`Wd@]@@%u:UtURVh$TWތF'Tj C>V|UU385À@tR uʍqAu+QMRS% G| G|UGfEj$Tx6B>+؋E]pto9ujw@tct_tU6tOэZfBu+Ӌ]RAu vuSShTW\E pSE Zj*TmATCst PYtFFuj V؃uj V؃u PV+ރ r#j $T@KF sEx ZE*Tj@&Ft PXtFFuj V@؃uj V/؃u PV+ރr#jI2@)KFsEx L%Tj ?twF tP%XtFFuj V虿؃uj V舿؃u PVx+ރ r j $T?KF sL%Tj h?F tPWtFFuj V؃uj V؃u PV߾+ރr#jI>5KFsjֹ'T>t%PVu>,uFFujֹ(T>UtƇBB0B njֹ TA>LJfEUtƀUh$TW趇EUtƀUh$%TW萇EUtƀUhX%TWjU@@%:UUjֹ%Tn=tLJjֹ%TG=tLJpjֹ%T =1LJEjֹ%T<FtP UtFFujֹ T<tLJjֹ%T<tLJjֹ%Tb<ujֹ%TM<^LJOjֹ *T%<FtPSu >*tFFuPhStFj jV* xG;9|GUƇLJxGLJ|Gj ֹ Th;GH΋Ӆt%t ptpjjW֋]uhGPA Pj67GHttH t pjWу jֹ%T:~<u )tlj TUEE:>tt t EMU)qGfjֹ%T9:tt#jֹ%T:tQuC MV~V|U_^[]Ë-,cwxj ֹ%T9tcuZ虶8uP2PUM賷RU@<?_^[]< u C< u CAcdt_tDƇLJ]U/=  )Ƈ뷃]ƇLJ~LJ늋GP#GTƇq]dUdx J@<7H*h,#TW虁@@%:UU=u\uhh#TWHƇ(G5385$ƒ+މ]u΍YAu+ˋ]QVu踄3GdcGʉ],8f8U8gHtt 1t*h#TW7~hLJUh#TW @@%u:UtUƇ`Gt LJgth$TW$LJ;toE0j SD aEWP0Bu59u+v"$uLJƇ3_^[]ËEƇ8tLJ3_^[]LJ03_^[]Ëjh%TV j V´F>j VE 蟴؃uj VE 芴؃cVh"TW~E _^[]ht@uS薄 3_^[]h|&TW} _^[]U SVW ;|;E +jhRP,ȋi+ME+iMU+ȋE…'|u!Shh+TW|_^[]PQXw3_^[]ÃEM tiϙRPw_^3[]VtbFtvЃFFN t3^F v|UvF|UFF^SVW3tQVVjWjhpI؅~9PtUt&SVjWjhpIuV|U3_^[_^[UVWhI3lpIEu_^]Sh+TPhpIh+TV]t$tjjV[_^]V(qI[_^]Åt%h+TuhpIthjV[_^]jj`qIЉU΍Yffu+EPtU؃ttuS`qItfˍQffu+K\ˍQDffu++vfD1fuEt jjSS(qIS|U[_^]U SEVW3]3EPAhKMMt5ʍ ɁKȅttVwN u"FB}.u5t1t,C3MEu|ME_^[]_^3[]UVth?'@qI3^]BPBPBPPh+TEEjPkMQfAu+t);M s$uE֋+@@Lu^]j@qI3^]Vt/Wv|Uv|U~V|U u_^U E V3u0EPuRQrIExS]WV{{Cj tU KOKOC jG GGGGtUGKCtPUGtoEDtx}[=]EtPrItrt)@v|Uv|U~V|U uۋE 3_0[^]w|UW|UW|U놻|u *SlrIE _0[^]UVWU3}Eu_3^]ËG EuSj jU؃7UCjjUCttEDtXGCCCu%{EuGEf@frIfG}MG ]MET[_^]s|US|U S|Ut-v|Uv|U~V|U u3[_^]UVWjtUu_^]SuU؃uW|U3[_^]ËOU GGGG @@S|UW|U[_^]USVWNFu+FPtUE3ۅu _^C[]ÅtvME<%u]vXGPBtAGEPBt+G}EjEEEPEP EM GCuEEtE M_^3[]UdSVWu3uuu$VNtƇU_^[]À>eZ7D$j`jP薮D$ UtƇUWtXtjQP3ҋ> u|ULJ3_^[]UHhWSVWME]EfEEEE2EE̋EƁnEhu }Wh+TSq|Uǃj jUuԅ u Wh,T f  M,TjWSW|U  }'T'Tu؋uEIE^E;tj:V2u ɺI TDP$TVDPh$,Teu܅ Y7tt t$>'Tj&u vuuuVh0,TeE؅u MYEMtt t>*Tj}&u vu3uI*TD}Ett t+>(Tj &u vuuMtEMuIu}ԅEȋQM؅EPuuh<,TWJ E؅t P|Uu|U) MWe hIWUQPGP P|UEǀh3ҸUE3~tt u;Lʋ™E܉UF+tj™hRP+pi؃+M֋u   } MtwPwGtt;w'jjj   M,3}܉u}EEԅl賓 ,@;6u33Uػҋ~tt u;Lʋ™؉U\E+tj™hRPcȋE+pi؃+֋u؋ }܍EċUȋMPjWr QuK |r3MVSjӌ] h,TSu!m@]29EUuBU~gUЋM̋,E }t$UЃMMjMEPjERqM?uF? ut G}7@}tuVWMs 3ҋ85ƒuύqAu+΋uQMWZoG< $< j>%T!tt#j׹%T|!tMu?prMWW|U+!j׹X+T!t08d&j GjP EЉUj L%T }G w tP8tFFuj Vpuj V_u PVO+r#jIb OFs}j'T? t{GwtPj8tFFuj Vޟuj V͟u PV轟+r!j(TOFs}j*Tt{GwtP7tFFuj VNuj V=u PV-+r!jIBOFs}VEPh-TWWuG,3Eԉ}܉}UM@)u8d h-TSlhEE@@0@ E뎋,3E}8(G~UоM̋ utQRh@-TSgMh9}tFhh-TSgUMBƃ8 DЍEPUBj3Nuh,-TSg3uMǁhh,-TS{gMǁhu0@ti Gt`Eh,TSƀn?guMAiGMtQ轝>M8Ut9E9h-TSug룋]h|,TSngu눀}tYy8t ;^QƁ+[VhrI}LJO>hgjh-TSǁh0f  M7h\,TSfj|U _^[]V|U}7|UW|U_^[]Ë}7|UW|U_^[]6|UV|U_^[]Qh-TSf 8_^[]Qh-TSf 8_^[]h,TSe8_^[]ËY}Vwϸ7T:utP:Quu3u G/jWh7T1 u;v`N>/tW;wϸ8T:utP:Quu3u/;v N>/t;wϸI@:utP:Quu3tJϸPI:utP:Quu3tDGFttF~tPh8TxGGuiQ|UVUMgE}t4}u}u2|UVUM-Eֹ$8Tt Eֹ$ItEsֹ8TtcEUMM3EۉMۃ3ֹ8Ttֹ8Tvt Et"Ph8T谂t FFu:>1F~%DPh8Tru GGu?GEEEPE_^[]UVҸpF|FD1&TW}ju u _=^]ÊGt@P<tGGuSߍKfCu+ك>utPtFFuuEPPmpTLTt0Iu4utPtFFuu>,cFZu6|UFFtP'U@$v|UFCPtUuE[_0F^][_C^]ÍCPWV E X[03_^]U!SVtE6ut<Ԋ, a؀G؊Ɖ], EaG8Uu aAFu1, ؍J€^G؊, aȀG3:[]USVuWt-t't'Hw, Jw :uGGNCuӅu _^[]Ê7_^JBŠG؊, aȀG3:[]UTSVWEEE7t \$GEh lGE:IEЅɉU躏IEу='UUuPF='U@UH`$FMEEQEMC4EЋC8QEȍMQEEEčMC0E܋C,EԋCPjQjjjhTP'UsEE@EEEЅtPhMTuG 8_^[]ÍEPEPus0g,EjIEu`9EtYE48|UI}&TDuPh8TtFtPSF|u u8t@_^[]U\ESVE E EE3WE ߉U3҉M}uĉŪqTDPuFFuPEWPh`9TVEEl t}OGu+3}uG3 KEKGEfMMEAMEԃ|كE}u9 KEMԋMudEM@EMԃ |Eu,SEӍMVuEԃ @EԃDr_^[]ËC+P*}Eu_EPEPEPEPh9TVkuu}u.EPEPEPh9TVkuuE@pIjE@qIj EPV @pIȋEԉM;t P@qIMȅMЁu[+ƃuRx9uN+t -Q+++UM+ƃuXuS9MuN;uJYы Ei'+ȸQJ‰EQkd+ЉUpUMuu'@ph:TS=AHttP t pjQ҃ j8D$LjP}y D$Ht.q  E:TD$x0;TqE D$x:TPSg=uL$xhh;TSK=$FD$h JD$h@D$h6D$h,h;TS=#_^[]D$h D$hjtUWf@@APQjjD$XP'UjjhxTVEE8u0hLJLJtU u.hLJtUȃ W+‰U=sCPQxUuh>TV8_^[]É EEtA +jȋERQrI^h|?TVt7VtUMuMԃEMEEEEEEEEEEEEEEEEME PqM vE؍JQQPjjEP'Ujj@VRVE|Uu|UEE= E=  = tA3ۍufD~uVtPPh @Tu6U E3ɋ;EP6vQR[7ȃ}9Ft P'U@@C |}EuPh@TV5 U; +RQP~E E= ]2krI=3'u*t LJh>TV53_^[]h8?TV5#_^[]=" 4\$(ӋL$ 73t$$|$tt [33ɉT$~ttu;M ™؉T$7D$jh+t™RP:ȋD$+pi؃+L$؋ VNDt$$tuLDT$,Dt$,}tWfD$L$\$QSRM t$$\$(ӋL$ |$8E|$ uӋ:u$džDŽ`FDŽ F2ɋE 3dž_^[]À}t3E 3_^[]rIPhCTt$!- #_^[]hCTt$-_^[]UTE S]V WL$ u!P'Uj@,ЅuL$ };vE7_^[]ËPtUȃL$uE_^[]ËT$ L$8WuȉD$8D$P9D$<D$XD$8Q|$HD$LL$PD$XD$`D$dD$hD$0D$8D$4s D$$jPD$j'U@dЅ|$03|$<|$Ht$ } 3L$t3t(tWfD$L$D$;MD$jh+|™RPȋÙ؉T$D$+ً+xi+؋É\$ }D$t$ ]QPE IJ xutUE 3ɋ;D$ P+PD$PQSc+L$4Qt ut$ ;{VhCT3N*E brIPhDT3**E 7>t$ EhCT0*E }= 7DʋEt$|U;Dt$<_^[]UlESVW3E D$|$4EPh@DTSL$$(E MU8t';whlDTS(hdHTS({thDTS(CE thDTS_(#!+‰D$ =r};D$;D$CʍPD$E xUu'Eh>TSj(hdHTS'UL$ QhET +SD$'M PRh|?TSh'M jt$PE rIȃu>rI=3'EuQ@ETPS'Z8pETPS&CEuEhETSƄ!&~EQhETS& Eh|?TS&UfEt9r! D$$D$jD$XD$PjP'UL$,D$0D$8D$<D$@D$DD$HD$LD$PD$TD$XD$\D$`@hЋ|$t! t  N|$,t$(hETS%L$4E };ʉL$ Gы+;‹Er 9|$sS};BȋQL$xU|$UL$(D$ L$ Ut*Qt$4PmE L$ QhFTS$E hDFTS$|$DunD$@tfPh@TS$M D$@;v* P+D$DPQmM D$@ЉRh|FTS1$EEDŽ! hFTS$}t QEhPGTS#EL$U QjDŽDŽhGT3S|$#  UȅPh|?TSS#Eh,HTS7# hdHTS)#}U! hD$\jP^=hqI D$XD$\D$`jjjjD$xjjRPjj RPjjRPjjRPRPj3D$dPlqI|$UƄ  u!}?uQhGTS8"E׋M8PhGTS" Eh>TS"hFTS!h|GTS!hGTS8!z!Ƅ dhETSƄ!!IEhHTS8i!UEt QtM;Bt~WuiE +P9PQiE )WhHTS E h,HTS E_^[]Ëu]8!u QQu3_^[]UDSVWE4Mu"xEƒ<8tShHTQ ZLMEMM؉MԍMQP'UEEE@(EЅtЋPh,ITuI _؅u C_^[]ËEEEEAEPEPEEP'UQjj@jjSQSE|UEt= u_E3ɋ;EPuuQWo 'UuI@ыMu9]tS ]PhTITS]t7hITS'U@$|Udžto؋JHttAtqjjRЋCu'US@S|UAHttP t pjQ҃ dž t(P|Udž dždžt(P|Udždždž_^3[]UVuhjjjV$pItFPjjh6pI^]UEjuu p0pI]UQVu EjPjjvE pI}ujEPujv pIFtPpI^t jP,pI]U ‰MSV3E0QEW30Au+@7<=tt DF<=u<=u|=D7;MI+ljE@PtUEu _^[]Ã}EE33҉M3D3=u AM&SAfD:t AAFu:usM֋]GrusVsF+t:]E@u]E;EjEM_^ME[3]u|U_^=[]UESEVu W}uNfDFu+?b RtUE؉]5fD33tCGN2ɈL@|eMĀ? Ȉe E$MMEEU °SStat4E SPESPPPhITju BESPPPhITju PPhITju EE ]Ej|UKfCuE+ى3_^[]_^[]U$SVuWMyM EƙEMEE`tBu9uNFu+VuSEt_^[]ËuEU MfDG$3F 0|9~A|F~A<w"GqC 8UUGEG\8EjPWE貽 G W$uu蒫8"!UG; u4 u'$u!CGdžUUGCUUG O$EE;|9UrʉMM}u7`uy}uˍQAu+QShUEE}x} M~)O _$+щU E$GE붊< u%CFF0F UU<  CUU< < E;|Tt PxUhdžtUsUE}􋎰C~UU E  E`uBuʍAEAu+MQREUdžG; tXCUUKGE; CGUU%< t < tGCUUGM \3_^[]ø_^[]ø_^[]ø_^[]À; uBG(_^[]_^[]f/F70F0F81Fa3F{1F2F3FULEUMEESVWu ]t{ ;jtUu G_^[]ËUM u MFEfFu+uE&|rW+|U_^[]ËMtKFPtUEGuWp|U_^[]VuPl\G UƉG ƉOG EGWt t3ECMt893_^[]ËwdIΊ:utP:Quu3tEPVuE%=@t EEW|UE+t P|U_^[]_^+[]UMUVWu F_^]u M3jjVt V|U_^]SV3t-WD~> v|UV|Uu܉;_^[UQSVq,3W3Uufq Uj/WFj\WFtt ;؋GF stpVUW|UtQ3j\VGuj"VGtf΍QfAu+ʍMPtU؃uW|U_^[]ÊÄtf\t"u\@F@uVhJTuu`S|UW|U_^[]UhS]‰EWMEfEEVWEu _^[]PE KTEȍEQh$KTjPEE܉EԋE EthIEPEP uEh8KTPEP|h@KTEPEP] yEPCMRPsVHThhKTEPEP 59C$tU 3Y +֋}EE;vIMERQPRE +O[_^][_^]U S,pIVW}3h@jjjEEP$pItU\P3u9dt 9hepItPLtFFuuEPXPX,LLTX2jjjXPjhӋ 6QtUVWjXPjhWpUttd|UdNffu+Wh|Uut"PLtFFuu>,FuW|U]S|U_^[]Ë}]\3xPEP'UjjV@ jjh0ES8|U3_^[]UXSVu3W3UM}]9^ t9^uC_^[]9^0uQuu h8S؃ t҇ESu|U~0_^[]|UEF039~8uQEP'UhLT@DЉFt _^[]ËMQAF4'U@@v4tUF89~Mt#9tUFP*F3jF,tUF:WfEPv'Ujjv,@ jjhLTjЉFjtUF WfMtltf<=t!EPUE]3uhLTuC=_^[]ÍMEEME]EEEE؍U܋F83RE̍UF4REčUЋF ERPj3EEEDP'UjRjv0@QvSF|UFy _^[]= t= u$EP'Uv @ ЉFy 8_^[]ËEĉF<_^[]VWF tP'U@$v |UF FtP'U@v|UF~,t17|Uw|UwG|U Gv0F,|Uv8F0|UF8FF4_^U8SVuWUEP'UhLT@DЅt _^[]ËMQAF,'U@@v,tUF0<t!?tU^ S#t _^[]3j^(tUFWfEPv'Ujjv(@ jjhLTjЅt C_^[]jtUFWfẺEF0EԋF,E̍EPEEPEEPv'UjjjjjhTjvE@= t= tt$= t8_^[]ÍEP'Uv@ uu uv0_^[]_^[]VWFtP'U@$v|UFFtP'U@v|UF~(t17|Uw|UwG|U Gv4F(|Uv0F4|UF0F,_^UVu tvD|UVFD|U^]USVEWdMTE>E8EȋىMSCuj/Q+3t!uU؃]uh_^[]ËQAu+ʍAPtUEt̋ʍAEAu+MC]Ruh8SPSEDžhlE؉xEEXPEDždP'UjjjjjhlMTEEEDžtDžpEEEEDž|EE@ jЅt_= tX= tQ= tJЋ蚽PhMThHMT6(hMTWS|UEP'U@и_^[]ËEtXQMQpQMQjdQjjhPuEP'U@u|UMtQ 'UA@3ɉMMt t t  |E؅t~PfErIMfE3;MQjMQPV} M3;MQuuPV}r9EiMEtP'U@@ЋMEEt'UQ@@EE UEPEjPH D}:E< <urIS]tUEUMQuP c9]ZMEE~E _^[]ËӋ8PhMThHMT6u|UEP'U@ЍEP'U@$ЋEt P'U@@hMTW_^[]h,NTWgu|UE t P'U@@ЋEt P'U@@ЍEP'U@ЍEP'U@$и_^[]hNTWu|UE t P'U@@ЋEt P'U@@ЍEP'U@ЍEP'U@$и_^[]hNTWu|U u|UEP'U@ЍEP'U@$и_^[]PEPhNTEhPhNTW:u|UUhXNTWu|U 9u|UEPjEP'U@Ћ 'U؍EPIхtk tc t[ tSӋPhOThHMT6EP'U@$С'Uu@@h8OTW|_^[]uhXOTW'U u@@ЋEfEt tOTOTESPhOTWr `tjHPjEP'U@,Ѕt[= tT= tM= tFЋ&PhOThHMT6EP'U@$hOTW_^[]ËTPEEtUEjEtUEu'Uu@@PPE EtUE̅u'Uu@@С'Uu@@j|PhEP'U@dЅ= t{= tt= tmЋPh$PThHMT6'Uu@@С'Uu@@u̡'U@@ЍEP'U@$hOTWc_^[]ËEEEPEtUEu*'Uu@@С'Uu@@С'Uű@@uuP=E EuuP<E EEuuP<'U u@@С'UuEE@@С'UuEE@@uEErI]MQfEM3;jQPV4}38`t:;وEMQjMQPV}utQh\PTW.;ٍMQuuPV}i9E`Et P'U@@ЍEPEjPs }EW ;s7@xfu:t"G;s8tVЍMt;r3_^[]ÉG@_^[]Ë+;w3@u@ рu+;wG‰G_^[]USVWlj}+=TUUUwK@@PtU؃]t6;s2]DPhVTjWF;rE_^[]3_^[]USVu‹щEW} +UMAZF$ZFM3ҋ=?PtU؃} u!t WVS47 E_^[]3;u sM3tuN  FF =rX=r<=r = scȺ? @ɀL ?ɀBL 0?ɀBL;u ^E_^[]S|U_^[]âYFYFYFZFUQS]VWM3EtPkMًM;}0F;}_^[]USVW}̉M3UGkȸMEtUMPUE +ًMEU;}0F;}.F3+ƉEEEtUMP؃E )MMEU;}0 C;};} fDU;u}.F3ېG ؄xME+θ̉MEtыMPfM +ًM3U;}0@;};} q;u}E_^[]_^[]UQSډE;VSP3OFWPtUtgSu֋!>@S@StCϊ:utP:Quu3t!N觠uFu_^[]ÅtW|UvU_^[]^3[]3[]U ySVWQ B`F$`FAQ+ƒ:TTDPU_^[]ËQ‹q+tWv_^[]F ;r IQVTFPhVT _^[]ËQIA;v3_^[]ËQI6_^[]hIU_^[]ËQQI_^[]ËQq;s ,0< wA;r~ +ǃtt3_^[]ÿS;z9Zu WTWTAQ+эFRWPFPFPFP3>5VPhWT(_^[]ËYIqˉ];s ,0< wA;rE0+à ttAEAEE03ҋ;s^].]t},u4A@;s 0|9~+уty?0uOuI;s8Zu VTVTVT@P+VWQRIIDPEPEPC PCPCPCPShVT8_^[]qqMM3҅H_^[]^F3^F^F^F^F^Fa`F^Fd_F^F       UXESVډMP3@W;IPMMЋEU;QЍM}ԍMUЃEWMWMEt^PӵtfDGGP軵u?u +}T~ IU+f;s1F<1uEU8t+;s1F<1uEP|U};s>=MFЅtI:t;s>AF9uR|UEM;UE@;_^[]_^[]UE(SٍMVWPSCu _^[]ËuM܋UVmK0V_K@VQuMUCC7IC8IV*}u!uUKMVEV׍K0C KPVMVuK`UVKpVu䍋VVEkUEƃƃEƃǃǃǃIǃIǃIǃIǃǃIǃI;stVЍMMu E;sOVЍMMu E;s*VЍMMuuUg_^3[]VW3yGt_BGBtOBBt4BGBt@r_ F^Ã_ F^Ã_ F^F_ F^UU(SVWrRBM}RTј#]MUSU}ʉE:u;sA9t+tx fDOyW hLWTGVU t+WhlWT-tWhpWTgW|U Mt4tWhWT9WhWTh@WTV5W|UUMSMtotWhWTWhWT6QT蚗8] MsSQEMt4tWhWTWhWTh@WTVW|UsUMEMt4tWhWT1WhWTh@WTV-W|UsUMMjt4tWhWTWhWTh@WTVW|UM(#tWhWTWhWTlRTN] MsSMt4tWhWT>WhWTh@WTV:W|UsSMMwt4tWhWTWhWTh@WTVW|UM5t4tWhWT詿WhWTh@WTVW|U_^[]U$USV1Wu uN`3P3؃CPtU`PS~;tWhWTWjhWTVW|U033P6؃TCPtU=0PS;tWhWTtWhWTVu W|U3;sfDA ;r󀾈t/WhXT؃Sh XTS|U WGPhXTVMntWh0XT载Wh@XTV W|UMЋW,EE}};sWЍM UQMtWhXXT7WhlXTV8 W|U@tWhXTWhXTV W|UP9ZtWhXT詼WhXTV W|U}MЋUWEE}};sWЍMUQMtWhXT)WhXTV* EPEPW W|U _tWhYTϻWh YTV W|UEPEP+PQfu/MA?7PtUuu|U_^[]ú YT3ۉE9]v$U 7@;]ruuE E@+PQ|YYt'x$|!EE3Ɂ8ËeE2Md Y_^[Ut}u 3U]U=Ut} uu@uYY]U=Uuu> hU3?YY#E]UuYH]Vj@P:Xj06 ^ts!hxFP8YYuQt hrvF@YП˟PFYttS;ujs3P*XYjhhT?jMYP2ۈ]eEܡU3A;/uI UhrIhrI.@YYtEhrIhrI?YYUو]uY39>tVuYt6WjWrI9>tVOYt6,Y+:?0?WV0qV tkujjYYE5MEQP2YYËeMt2}uEEMd Y_^[jVurVtU%U$ Uj qIe3SVW3ɍ}S[wO3ɉW E܋}EntelE5ineIEE5GenuE3@S[]܉Es EKS uCE%?=t#=`t=pt=Pt=`t=pu=U=U=UMjXM9E|/3S[]܉sKMS ]t=U]UUUUUtytq3ЉEUEMj^#;uWUUU t; UU#;uEM#;u U@5U_^[33@39P)UU$SjqItM)j$jP |xffftfpflfhEEDž@jPEjPE E@EEqIjXۍEEۉEqIEPqIu ujY[3jlpIt4MZf9u*H<ȁ9PEu f9Auytv t2hvFqIUVW}7>csmu%~uF= t=!t="t=@t_3^] 0w 0)S̃%UhFd5D$l$l$+SVWU1E3PeuEEEEdUeEePqIE3EEqI1EqI1EEPqIEM3E3E3Ë UVWN@;tu&;uO@u G ȉ U_ U^ø@hUqIðhhjKR uj踗H$HHH39UøL)UøH)USVt rI׃;r_^[SVDTDT;sW>t rI׃;r_^[; Uu(UjqIuqIh dpIPqI]U$jqItjY)U UUU5U=UfUf UfUfUf%Uf-UUEUEUEUUUUU UUjXkǀUjXk ULjX ULh sIUj]UjqItM)U UUU5U=UfUf UfUfUf%Uf-UUEUEUEUUUU UUjXkMUh sI̋L$D$WSV=U fnpftufoftfڅuf~ڻ#؁w'offtftffكtۃj:uЍNu9#ځw/o foftftftffڅut:^H^[_3^[_À9t#فwo"1f: fsKt tf~»#؁vt:tf:c@ ws׋#ށw)#ځwo f:cN qyLA:x뭊oqtUL$:tt :t u^[_3Ê:u~at(:uAtf:t3^[_G^[_Ë^[_UW=U}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_̃=Ur_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^_[UuY]SQQUkl$K=UV}2ftf;s tfu3f;S H#hfS fnpfp%=wffufuffujf;tftjX3f93^][fu2 uU}u #u]UVuW} t N3 8FN 3 8_^]US]VWE3E賊] Cs3UVPuEuDE{ @fuZEEEECtiMGGHEtMxHMuɄt. EthUVVuE_^[]ËE8csmu8=(sIt/h(sItt5(sIjurI֋uEM iE 9x thUV׋rE VuX sM֋IjhTEt~8csmuvxupx tx!t x"uUHtNQt)eRpJE1u uCYYËet@tQprI֋Md Y_^[UMU ]U} t2VW}7>csmu!~u~ t~!t~"t_^3]pwpFU@$tM9t @u3@]3]UM UVq…x I ^]UVuW>?RCCt?MOCt ?csmt)x~H_3^]xvp.F̋L$ D$׋|$<i %Us D$%Ufnfp+ρvL$$ffGfG fG0fG@fGPfG`fGpu%Us>fnfp rG stb|GD$tGutt $GuD$UEM ;u3]Ã:utP:Qu u]UP\$XE&EEEEE+sd;5SVjPh"FVo^[?C P !C =02CVC$ S CPVjCjӋZzr D$\bb]UrI=`Dtd E;Ar;Avj Y)]UrI=`Dtd E@;Ar;Avj Y)]UEt=UtP;Y] @Ã= Uu3SW@pI5 UjYtuYj5 UYYu3BVj(jcYYtV5 UdYYu3S5 UPYY3V:Y^W@qI_[hFy UYu2hUPYYuá UtP{ UYVW U3jhW t Ur۰2_^V5 Ut kWUWXqI Uu_^SVWT$D$L$URPQQhFd5U3ĉD$d%D$0XL$,3p FT$4t;54v\ H {hCCd_^[̋L$At3D$H3Uhp pp. ]D$T$UVWS33333[_^]̋jS33333USVWjRhFQqI_^[]Ul$RQt$ ]̋L$A2D$H3UhP(RP$R]D$T$SVWD$UPjhFd5U3PD$dD$(Xp I|$, ;t$,44v L$ H |hD9DPL$d _^[SQ0USQ0UL$ KCk UQPXY]Y[j hT!eE3@E3Ɂ8Ëe3EEMd Y_^[UQSVW}o` U3tuvV|IhjPEqIuG@pIWu(ujh$}IV:T tjjVqIu;} u3_^[ËƇtV4qIUEVWtQGP6:YY@H9_u#tZtVwGPQYYPV t7t3j[C]E 3@Ëe3Md Y_^[荀jhTRUM :}y zeuVRQ]St!u4FPs{YYjPvW FPs_YYPvW EMd Y_^[3@ËeU} S]VW} tu SWuHE,uuPu$6uuW F@PuW hu(s uuWu?8tWPG_^[]UdSVW}3WuEu E ȃ Ms;Oj];csm{{ t{!t {"39s9pXE@E;csmu*{u${ t{!t {"u 9sE9ptb;@E0uSpw YYu@}970Gh ULE@E;ӋUUUM3}ЉEԁ;csm{{ t{!t {"u$9G u EWuQPEPUăEE؉U;UkM}jpEY9E;E3ɉM9MC@ EEU܉E}}~&sE7P u"NMEUAME;Mu+uEuu$u P7EPuuuu S0UMBE؃UM;U'}u$}t jSYY%=!rluG t\} uVG t:X2MHGwStYYt]&9G v!8Eu$u QWuRu Sz xuf_^[.jS3YYM1hTEP XMHuu SVWuu WPL{U8S];VW_39xtFWqIJ9pt3;MOCt+;RCCt#u$u uuuu SCEE}9x u PuEuPEPBUE܉EU;UkM}jpEY9EN;EIMԋEHtyu.@u)jju$Mu QjPuuuu SU0MBEUM;Ur_^[zUUSVWBtvH9tn} tua_3;t0C:utY:Xuut3+ttEtt tt3F3@_^[]USVWu1YM3U"9p u":csmt:&t#;r A Bft&9q9uQuu  9q u#=!r9qu;rhA t^:csmu:zr49zv/Bpt%E$Pu uQuuu RrIփ u uu$Quuu R 3@_^[]UVu%}I^]aaA}I}IUVF}I `PEP#YY^]A}IPnYUEPAPYY]UVF}IP8EYt j VGXYY^]j3ۅ~qEӉ]@@ MEȋEME~;F‰EUr1P uEMHEMEUEUu_^[atUuMU ] UuMuU ]UE@]ËAu}IUSQE EEUuMmmVW_^]MUuQK]Y[ Vpt rI%UEMxA]ËA]UEMH]UW}tHtBQAu+SVYSAYt7SV8:E ΃ 3@VY^[ M A_]UVu~t6Y&F^]UESW} Et-tVQp ΋xrI^t t@EEEPjjhcsm]}qI_[̋U]E:j hTIeE0yYeM PuEƋMd Y_^[ uE0NYËUU3ʼnE}ES]uN5;ttVWu|M33ҫ ‰u uƅu Puu QP?e}tKE3Ƀ tuum;u*x);v%Y tKty ;tK t |P_^M3[:Åuŋ;uj^L벃uËËUQVuWv3 2SS39uv;w1V:EYtEPEP.:Y[_^UEHtt t} tEut_^[SVHt39^.{4^[É^8^F9^vF1PFtw$rFEN(^$^0^ ^,^<8'` ^(!,IjFF1kFPPJF?FF FFF#F,F5FSVHt39^,g3^[É^8^F9^vF1PFtw$FEN(^$^0^ ^,^<8'L ^(!jFF1kFPPJF?F F F)F2F7F@FIFA1 t-t"tHt uI I I  I I 9u+-22ðTu+22ðËUQVjTt#F1HEu]tFN^ËVju^ÍFPF1HP ^ËSVh^1PFF<0 t=SH tFNF@N1Fu*B12^[SVh^1PFF<0G t4FPSH9 F@N1Fuq*02^[y1*Q(tRÃAA@y ÊA1ut^[UM A=w EH#E]3]ËU8EMUEEEEE܋E UMEul ÅtEMEȍEE̍E܉EЍEEԍEE؍EPEȉMPEPMËUu uuuuu u]ËUQuEE1 YËU]]  UVj^u;}ƣ UjPj U = Uu+jV5 Uj U = Uu^W3@UjhF P> U4ǃ?k8h"UDt tuF8GUu_3^ËUkE8@U]ËVV@3 U4A UY PXqI u5 U % UY^ËUE PLqI]ËUE PPqI]jh T莳E0Yeu v0YYt2F8u@ t0SYtFF EMd Y_^[ E0bYj,h@TE0AYe5 U U} u;tOE7PYYt7WO}}ĉEȉM̉UЋEE܉E؍EPEPEPM} EMd Y_^[ E0@Yj h`TVeE0YeE 0?YuEƋMd Y_^[ uE0VYËU eEeMEEEEjEXEEEPEPEP}EuEËUEtH tQu E 2]ð]ËUE$<uEu Et]2]ËUMVWq $<uGtB9A+a~1WPQYPb ;t jX tjX!3_^]ËUVuu VY/VYu!F tVP?YYu3^]jYËUEEu PYË@ Pu3ÍEEMEEEEPEPEPËUMu  8x$; h$Us?k8h"UD(@] 3]jhT} }ut_3hx}tt3ۉ]uY]uUYt.uu3@E;tuYE؃u+;ut]]E%ËMd Y_^[ÈFu< tЋE@뭋]uYËU]3UEu ]Ë@]j hTeE0,YeM 4uEƋMd Y_^[ uE0YËUQVW8W/E0F 0F0F0Wu0_^ËU S] VWtut}u33_^[Ã}t3;w؍G EtOމMUG t@Gt9G GE;sƉuPR7E )G+k;rlG tW>YMƅt 3+‰EurjXEPuW5YPЃ tSM;w+;rBM%WP:?YYt5ON3M3AM@UЉUEEjY +3ҋu U} t}tEuJ3ÍMEMMEEMM PMEPMEMPMj hTzeE0YeM 4uEƋMd Y_^[ uE0YËUQSVW8W-E0F0Fj0N3Wu;-C_^[ËU}uNËE tH V uoWPsHUYttЋȃ?k8؉]؅ug3VYYu K؃2ɈME܃et jY6YMeEeE܄tUʃ3ʊMUUԃEul;t tu&CEЃc;u>EU;u"kHI k LI ȉE;t` UM܉E1}um;u9pWMrIUY-j_u]؋UԉU}t j5YUVrIUY;t tuEЉC;u M̉H3Md Y_^[ÄtjY5Yj莃jhT٦u }tt tWCz؅t=Iu(5DIYt5DIhIP8 PWYYȅtQEk@I ;t9zu 2 JE3ۈ]ÉEEj4Y]tu:= Uu1jhFqIt  U# @pI]u WЉU؅t%Uȃ3ȉEE܃t VYM؉Eu}]uj3YuYMd Y_^[j hTej 23Yeuuuuu u2uEƋMd Y_^[Ëuj .3YËUQVW}u. j^0T'u t&}tSuYtMˍQAu+jAPEYYuj Y[_^Ë}SWPR  u t>33PPPPP(j h`Tuu3<WVYY;sڃej 1YeV0YuEƋMd Y_^[Ëuj 2YËUQVWtM}tGuNFu+0эBEBu+U;v<1=uVuQ5 tu3_^Ë@j hT&ej >1Yeuuu u2uEƋMd Y_^[Ëuj @1YËUQS]Vu@j^0 s#uW} tu =ލEP5Y}u eeuuWVU7uEƋMd Y_^[Ëuu u5YuYjhT6uu 3e} t3f9tf9u ܍EPY4Y9]u h]]uuWV6uEƋMd Y_^[Ëuu ug4YuYËUj@u u8 ]ËUj@u uj ]ËUVuu: RF W t9VV-VP蝫y~t v6 fYV3Y_^]jhT۟uuuM tM~@3ۅujhSF@W~@ t%u2hPhW43uF@I_^[]SSSSS̋UV訧u;0r蜧0菧^]ËU]\UVuWuu 3~~ ~3>uu 9~ u jujF3fWWjVj u2u@pIPY4} ;G v Pu w wjVj uN2tHG3_^]ËUQuEPu u6ËUjME9Pt '3҅uB}t MPËV~t vYF^ËUVW}V?PFP t f F F3~ _^]Uu YM ]ËU}uu j1YY3VEEEEEEPEPu tu u1YY}t uY^ËUEuEtEt } v ]Á} w2]ËUEuEt,Et}rw} v]Á}wr} w2]ËUEMU Ht]ËU(M SVt!ut.|$~$w3ۋUtM ^[WuME 3}EE @E EPjP] uEE-uE+u} G]} } tux,0< wÃ#,a<wÃ,A<wÃt u=j ^8GE} uC;uɋ_^[]ËU]U]U]iUU+USVW} }33A9E  |9Es9E |9Es;t,9E  |9Es;|;r;t My_^[]j hT߁}uUGut tuڃMuYeVuu u uEƋMd Y_^[ËuuYËU}VWE@ t~E@ usE39p~iP‹ʃ?k8 h"U|(|J|)uC9uuDjVVR; ;|);r#uE PF+WQuu ey 2_^]ËuF+;U} |;wF9U|;wϰM)yƋUE@ u]ËESVWjY !u}] VWSuuuY3uEYH`E@ Et jY !#@ A} t9uv^]Ujuu u^]ËUW}uKS] u)|VuvsXu3PuM豰EMGU C+u tMuـ}t M샡P^[_UV3PPPPPPPPU I t $uI t $s ^j hT|eE0 YeM euEƋMd Y_^[ uE0 YËUDW} u!8ASVj03ۍESP0 uj Yuu fxK;5h$U}CƋփ?k8h"UD(t(EuEME uEEPEPEP#/ ^[_ËU}uu jZYY3VEEEEEEPEPuc tu uYY}t ulY^ËU<} u SVWj83ۍESP} uă jY}uAMlShjSjhW$qIu utVjWWYYu j8ESPr} uă jYutVxqI_^[ËU}uu jZYY3VEEEEEE=PEPu tu uYY}t uY^ËU4} u4 ?SVWj03ۍESP蝆} ũ j Y}ujlShjSjhW$qIu utVjWWYYu j0ESP"} ũ j YutVxqI_^[ËUQuDYu j,Y2SVWuju 3C3}fFEPuf^jt3EjWWWSHShF ȉF(V,N ÉV$N0V4_^[ËUQuYu jY2SVWujQu 3C3}fFEPuf^t3EjWWWSHShFX ȉF V$NÉVN(V,_^[ËU@U3ʼnEES]VuWSEqI3@;fF3Eąt M}QPLYYEHFj4EWPs EPSqIEPu]WWufFu=RPu؉F(uԉV,*v,F v(V$uuF0FPEȉV4P@uwt't"uh 2[@pIPY3H#fF3@fFE Ft3EWPWWWSqIt EęFV3@M_^3[xËU@U3ʼnEES]VuWSEqI3@;fF3Eąt M}QPYYEHFj4EWP EPSqIEPuWWufFuRPu؉F uԉV$v$Fv VuuF(FPEȉV,P)@ust't"u 2W@pIPY3H#fF3@fFE Ft3EWPWWWSqItMĉN3@M_^3[vËU(U3ʼnE}u} uEUUEPEPqIt>EPEPjqIt*MEPEPEPEPEPEPEP‹M3vËUE 0EPEPEPEPE PEP]ËU0VWу?k8h"UD2(u 9G0t2Qjuj0EjPހuЃ ?j Y3_^ËUVW;04uu u: t0$8"t3ju j0 M _^]ËUM E!x u@$=w]2]ËUM Vu!aV v23F$Q^]ËUVuW} uWYt@Aց tWj.WYYtGhIWYYt3hIWYYt"hIWYYthIWsYYu@8 _ ^]ËUUVu W3> ArZvAw)fz:u"f9zu jWY2Aw A_^]ËUMtCƒArZv arzw fy:uftPt fyu]2]ËUUVW3qff;u+PBPtBP{unJft!V\ufuft;ft.R+uЋfuftf9yu2_^]ËUf}\t f}/t2]ð]ËUU3ʼnEVuh(IVYYu2pS3PhVPЃt6Wyff;u+_t RYtVqI3C;w3Y[M3^qËU]U]MU]U]U}u jY3VEEEEEEPEPu t uY}t uY^ËUVuuM 3S3f9u%u 9^ uj6F3^zSSSSjVSu u@pIPGYwMW} ;G v Pu7SSw wjVSu u@pIPY1HG3_[^]ËUSVuuu r3ۉ^^ ^33f9u u 9^ ujFSSSSjVSu u@pIPxYMW} ;G v P<u7SSw wjVSu u@pIP2YbHG3_^[]ËUHU3ʼnEE S3VuWt؍SPVG u2P]YYuSW} t *YtWYM_^3[mnËUHU3ʼnEE S3VuWm؍SPV@ u2PVYYuSW t #YtWYM_^3[fmËUVW} 3Vww uqIu@pIPY0-;G v%@PtVww uqItG_^]ËUVW} 3Vww uqIu@pIPzY0-;G v%@PtVww uqItG_^]ËUVW} 3Vww uqIu@pIPYA0-;G v%@PtVww uqItG_^]ËUQuEPu u ËUQuEPu uËUM Vtt9tout+EEE3EEEPQuu@#T3EEEEEEEPQYYM}t uĴYE;rPu>YY^ËUM Vtl3f9teuUUt#EEEEPQuu#LEUPQUUU`YYM\}t u,YE;rPuYY^ËV~t vYF^ËV~tFjj"Yf F^UVW}FVWP_ t f F F3~ _^]UVWu}V?PFP t f F F3~ _^]Uu ]YM ]ËVW~t>Ft7~utP'v vvW;fFFF 3_^ËVW~t@Ft9~u tPղv vvWfFFF 3_^38AtAAA AËUjjjuu u]ËUjjjuu u]ËUPu u ]ËUS];Wu MZ;s)}EˋE䃠P3EEx~.ÍMEQPYYtEE3j]EY3*3]AEfEUEEjpjRQMQWEP$uUt E Ѐ}t M䃡P_[ËUS];u MWs)}EˋE䃠P3EEx~.ÍMEQP YYtEE3j]EY3*3]AEfEUEEjpjRQMQhEP$uUt E Ѐ}t M䃡P[ËU=@"UtjuYYMAw ]ËU=@"UtjuYYMAw]ËUVuW} Aw FBw G+uu_^]ËU=@"Uu)}u_]Ã} t]ju u ]ËUVuudW} uDSuM@E􋘔F G+uu}[t MP_^ËUu MEPhu }t MPËUu M踖EPhu^ }t MPËUu MEPj u( }t MPËUu MIEPju }t MPËUu MEPhu }t MPËUu MڕEPju }t MPËUu M褕EPjuM }t MPËUu MnEPju }t MPËUu M8EPju }t MPËUu MEPhu }t MPËU=@"UtjuYY]hu5U臫 ]ËU=@"UtjuYY]hu5US ]ËU=@"UtjuYY]j u5U" ]ËU=@"UtjuYY]ju5U ]ËU=@"UtjuYY]hu5U轪 ]ËU=@"UtjuYY]ju5U茪 ]ËU=@"UtjuYY]ju5U[ ]ËU=@"UtjuYY]ju5U* ]ËU=@"UtjuYY]ju5U ]ËU=@"UtjuYY]hu5Uũ ]ËUQQVuuo3^Ã} ueEeP5EM->Ձޱx|=GsSSjhQP][kd3V@[N랋U3W}jEP`YY_tUEMtQ蟵tjYUt"jqItjY)jh@j j7;̋UMVuˑMtE uU^U􋲤u':utQ:Puu3;4rjPjQhEVP u}^t MPËUju u? ]ËUQQVuu5SWSh? EYYM#f;uHQQ$YYt&t!tEYTW\$$jjDSWEYY^Dz8QQ$YYt%&0IW\$E$jjEVQQ$pSW]TE_[^UV3PPPPPPPPU I t $u t $sF ^ËUEM 3 A]ËUM EI ȋE% ȋE3]ËUE3 MVu   E% Ep3^]ËUVuW} t7uOWuMEPQQWVP]b EPtu "}Et E䃠P_^ËUQQE EEPuE>YYËUQQE EEPuEYYËUQQE EEPuE;,YYËUQQE EEPuE,YYËUU3ʼnEEVutu83@"QM QP*VQPU^tM M3\ËUSVu W}] C@WjPM2 uUM-Ut+u @MIbiYN=n43ۈ]0u4>WEI4?IWjPVPI4?IW1jPQPI4?IW1jPJPI4?IWj1PEPCE_A^ [];ы+;|"u A4 >;9u H;}sBE ]̋4LƉuЉMt + }+ljEԅt'Me uЃvu MԋD E3EU.]EȍK MčK M;EwA3Q EEEMtI‹M3UM蓯M Ƌu}EurEEMԋD EuSjuPR][3‰]E]Eu܅uv*juЃPS\3u܉]]EEwPrwIPS3ɋ MjuM#;r)w;Ev"E]}ЉEUEu vE]uM33tUE ]ăE܉MEEeȋEe3;s+E܃mEu]M3;wFr9}s?t4u 3ۋUă v3RNˉJ؃u]UEHEu3UËM]mJ}EEHUEȉMM]A;sSR@;r t <u uE_^[]_^33[]Àyt ø3ËUju uR ]ËUQ؝HLMMQPEYYËU VWWh?sEYYM#f;uvQQ$cYY~:~nu0E]E\$E$DWV]EsEYTV\$E]E\$$jj?DzWVEYY)EPQQ$M Uy +;|Z+; = =~-PQQ$P V\$E]E\$=}%V\$E]E\$E$jj|=}&PQQ$ V\$E]EPQQ$WV]V\$ȧI$c\$E]E$QQE$jj$_^UV3PPPPPPPPU I t $uI t $r ^ËUQSVW= US5 UWu u[jhVQE5 UWRPjhSu迧_^[ËUEPqIt3EPqIt%MU tE UE U U U U U U3ËUQQ U# Ut>EPqIt0E+ UM UxrQPYY | =vjh T%E0ųYeM *EMd Y_^[ E0سYjhT_%= U3@ U3ۉ]u,=Uσ U;t3SSSrIh"U u h"U]YE9uhsIhrI_YYhsIh sI_YYF9u  UFMd Y_^[ËE0 Ëew̋U3}csm]ËU}u#t uYE EEMEEEjEXEEEPEPEPs}tűU6t d0@huudpIPqIu YuqI̋UQeEPhIjqIt#VhIuhpIt urI^}t u4qIËUE U]jjj jjj ËUjju ]ËU U;U>vuxY U]ËUjju ]j h@T"eE0YeM 4uEƋMd Y_^[ uE0YËUSVWF00IYYtC,E3ۋHLMHHEPSWSEMSP]^t"3_^[ËEP詍YtMQjWuCPjt"S4Y믋}T$t&ut$Yd$EPu9Uu0D$t"Iut$辌Yd$O C  ɉ\$ ɉD3SSSSSQ̋UQ} ujugYYVWhu 3EWWP耻t tS"tNjuYYt/ju uVWNt t!"t VufYYVY_^WWWWW趋̋UEEMjE EXEEEPEPEPpËUQQ}|)}r!E |Mr+MMEEm躄ËU}u jY3VEEEEEE%PEPu t uY}t uY^ËUQMSVWjZEE ځ+RhPQjjdSujjSu+׃_^[ËUSVu 3W}SjVW臢 uSjdVWy uSlhVW` u2_^[]ËUDU3ʼnES]us ]CVWủ}Ѕ3 E( r NKMąx u} ~pj YʙMċƉuE}Ћ׉UKy MċƃKű׉}Љu} Er =NIWVEȉUYYt}~EUWV*YYMEċEFjhmQPMȋC Mșuԋ‰}ƉEȉEЅ|5r/{ |9|3s/ _^M3[Ã{ } |ՅsjjPW蘞EUȋ ʉutRWVP辞uuCȋEu}ԃ}}|$r|6r0m&c|s|MEjjE8FyMEËMd Y_^[Ë]j YËUSVW}WXY>u W}YhVYY3hVYYSVYYtދUt6} t΍YAu+;r tj"U3VWR| uJCt7x(t0ujh|S t VhPjj X_^[]SSSSS~̋USVuWj.VYYtD;r@+9M v7j$3ۍxSWG  t j$+u VWRPu8~2_^[]SSSSS7~̋UVu Uu$jh{j U<~ U ^]ËUQWuYWh~YYtv=woSV48Euރtt uuts^]qI+}j$WVjPu$NFu+f.0D^[2_3PPPPPF}j hT0uu!vj^0}ƋMd Y_^[Ã&ej Yeu V,YYut]v0E벋uj -Yjh`TjYuj X?ujYujhWYEP٤Y}uj3u܉uuu0uhu hBWEPeu܃uhW~YYuu8uu}t[uWdYFE39PuumYj ^3PEPE H"UE MEAMEuEƋMd Y_^[Ëu܋ExuPGYu\YËSV U3۸ U;W6{&vCY;u U3 U;ۃ6^{&vGY;u_^[ËUQeEj@PEYYËUQeEPjhuEËUVuuF ;WVYY!}tVYtEEF E+jj<SW胑y <ĉjjFN j[F VVхF NF mFV3SSSSSKx̋UVtuVWYY#^]ËU]?賁iHCÞ&HËU荁MH]j hT uuu=qj^0wgVXYejYF !Ve]Yt0VY]Yt$VM]VB]YY?k8h"UHU`(E3Md Y_^[ËuVXYj(hT }upw3} tu EP?YYffM@EtԸMtu@bu PhEP t3ۀ}wËEȋM̉EtMЅۉMtEԃej 袙Yeo0EPSEPu\}o0u]؍uЉu;t>t6YENjMd Y_^[Ë}j sYËUlSVdpIuЃMEjj3SP?k8Rh"UtRrI6=u v ESYh܋IE]SPGh tE]̋I]WjD_WEjPI h"U }}EuEE EEt؉E뾃}AE̋EtAPEЋˉEԍQAu+ʺԋIzBu+׋}_Gu+Yj:Sr}YYuSWq hԋISW u}uSW ul]S Yȅte+Í}3#E3E؋}PEPSSSjSSWQ.(tu܋]3ExqIE؉F3uGtY 3PPPPPF3W3tu+tYY_tf&EtPhY}t uxqI^[SSSSSs̋UM 3VufFA< tF u)WYpjpYYu  Uh@WShWPF0_^[ËUEM MEAEM EHE`3]ËU MMuhKoËEt t@uڅt@u E=wčEMEEEEEE EEPEMPEPMXËUSVu WV  usVTHUYttЋȃ?k8h"U ȋ߃?{)utt k8V<.V&EPV벍EPVVZV3Yj Ztj Xf9tu3f9Fjh IWrg j [f;u f;tf=f9tjhIW6 u j :jh IW u jjh0IW u+jX f;u If;tf/bh_^[j$h`T} uZb]uBb ;h$UÃ?k8h"UD(tnu EPYY}إ}tbEPɐYEu aDe UM܃ EXEEumIYa h3Md Y_^[ËUM@t2]Ã@]ËUMt2] ‰]ËUMt2] ]ËUE 8t2]ËMI]ËUE 8t2]ËMa]ËUE 8u%U u JJ]2]ËUMt2] @]ËUMu2] ]ËU]̋UE W};t&Vut+@TLPu^_]̋UU3ʼnEM S]VuW}u%t!_;fM_^3[]ÅtۅtDžrIΉ3+x;7IƋ;w1PVrIӃ~ Ɖ;vы;t4+߉ RBDƈJu㋝+ϋ;kIt ˋWPrIӃ~VW rIӃ~V WrIӃ~VW ؋d$;v7;s%WVrI~;w=;wWVrIӋ~ۋ+ډ;vWSrIփً;rYt6+ӋIRLDJu답;;s5+‰;v#WPrIӋt;r;+Ɖ;vWPrIӃt׋ʋ++;|A;s| A;I{;st @;8UMu[)bjX]áx'U3]ËUE=@t#=t=t~[ajX]ùx'U3]jhT} @t0t(t tt'[uu[ ;5h$UsMƃ?k8U܋h"UD(t^V觙Y]eEh"UMD(u Z WVHYY؉]E !u]VYpZ `Md Y_^[ËUQESVW?k84h"UD(\)ȁMM @tPt@t$tuB D(h"UD). D(h"UD)$D( D( h"UD)}uu@3H%_^[j hTeE0CYeE 0ƃ?k8h"UD(t VY2Y uEƋMd Y_^[ uE0舘YËUVuuX X axE;5h$Us=Ƌփ?k8h"UD(t"EuEMEuPEPEPpX {X ^^ËUVW}W谙Yu3Nh"Uu u u@`tj聙jxYY;tWlYPxqIu@pIWYσ?k8 h"UD(t VWY3_^]ËUQQSVuW} WVaYY;;qI~E3E;r]_^[ËUVuuV]3"΍QAu+ʍAPVYY#^]ËUQVu Ej@huuPuu^ËUU jy Ru趃YY]ËM]j hTu uVs\eV=YeF VBYt t?k8h"UHUHUً?{)utt k8 h"UA-t(sU[jMQhU UVuYY}ENjMd Y_^[Ëu }V2At-tHtuߋEE FEfEfE^]Uu uuuuu u]ËUM3SVWf9t1U :ftf;t!fu3f9u3_^[]Ëj hT}u @pIPrIG`אuj^Ge7wrIPMEQP~YYËeuP̋VW7t%~t vxqI~ t v 4qIV=Y'_^ËUVeHt>`t4~tr^Ft tPxqIF tt uPrIurI̋UQVWjj:3Wu8= tME FF PQjqI}M(_^ËUQQ}u86<3VuuEYYt,MQuPh Gu u rIu@pIP5Y3M^ËMtEeUűUQSVW*G93ۋʍ;t}99t ;u˅yu 3Y@uFEE FyB$PlX ;u^9wGt>9t/9t 9t9ubXQJC<9t/9t 9t9u FPjrIY^qYrI׋EYF3_^[ËUS]u3Vtt:4j^0:Wh U3VW8"U 5("UEt8uƉuM}QM}QWWPjuu u 3j _82EPEPEPVuvuEH,"UƋ0"UJE}PVYYtE&Uϋ9:t@A98ulj ,"UE߉0"UP9Y}V9Y_^[ËUQES]VuW#}E t0E 2ɈM?"u ɰ"GM5tFGEPYt tFGEtMu< t< utFOE< t< uGM t1M E3B3G@\t"u1uMtO9"u M3҄E Ht\Fut=}u< t3< t/t%tFPYt GtFGstF1M _^[t!EËUVu?s9M 3u;s*M;vjP5j-8 3^]ËU]!Uu"9!Utt _u!U3Ã=!Ut3VW{u$V*Yu "U3!Uj7YV7Y_^ËUQQS]3VW<=tB΍yAu+FuBjP5YYtn}RˍqAu+΍AE=t7jP4YYt1SuV3 u@Ej0E7EY؊uW'j6YY3j6Y_^[3PPPPP6̋UVutW P6YuV6Y_^]ËSVW=!Utmt\3SSSSjPSSv؃ tNjS4YYt7jjSVj73SSv tSVS36 u3 V6Y_^[ËUVW~MVrIUY;u_^]UE;"UtP Y]ËUE;"UtPY]hG!UhG!U~5"U5"UYYá"Uu V"Uwj h TeE0-XYeM uEƋMd Y_^[ uE06XYj hTeE0WYeM 4uEƋMd Y_^[ uE0WYËU ESVW0Uȋ~3؋v33;+;wƍ<0uj _;rjWSIjE84Mu$j~WS)jE4MىE4U}ωE+ǃ;#t}3@9I;u}E@0S] GP V A  A3_^[ËUSW]8uUV733υU}u;rT;Et3‹UȋȉErIUUʃ@33;]]]u;EtuE뢃t V2UYPP3^_[ËUuh"UZYY]ËUjEEMXEEEPEPEPËUMu]Ë;Au UAA3]ËUEEMjE EXEEEPEPEPd"UUh"U$"UY,ËV5UV1VV{VV^jYËUQh'UMTËV5\"U~15`"U35\"Uk150"U5`"UZ154"U50"UI154"U^ËUVuuW8U9>t 61Y>_^]hБIhPIYYËU}t= Ut]hБIhPIYY]á "UËUE "U]áU3$"UȅËUE$"U]ËUV5U35$"U΅u3urIY^]ËUuY$"U]ËUQE SVu+ƃW39u #tEt rIUG;u_^[ËUVuW>trIׅu ;u u3_^]rI8"U rI<"Uø,"Uø0"UjhTheM bEMd Y_^[ EPjh`T#E0t WVYYEMd Y_^[ E0QYËUEU SVu3WjUGPPRV7W_ .u _^[] SSSSS4.̀y uqA1PjUPu3PPPPP.̋U VWhj+j2. t:MEGEGEG EGjEXEEEPEPEPe_^ËVFpL0F0F 00V NFt?@UWf83Af;:uftfxf;zufu3 _t@"U0FLPL0AF PuOUuFpLhd"Ud"UYY^ `U U@DUË00YY^ËUVu ujUFPP]uu u^]3PPPPPX,̋UVu uv6u F ^]3PPPPP#,̋U}SWt@jUu0YYUs- ]Qc,YtKQuQWu 3_[]3PPPPP+3@"U@ËU jXEMEEPEPEPËUVW}Wu uR 3uFf90tPhC u,f9Fu&h0IuSO T6h2PPuH,"H($W3ҍOff;u+sr΋ff;uftfPf;Qufu3n$ff;uftfPf;Qufu33GI3ۄ0VPYYuy0ۋ,PSPtU tY(0PhSP Qff; u+APPPGe,V:GVt0 GWV(hSWV0P YYlPPFXf0fȍAw j8ZuuA2Aw tu*4Aw fuf96u f8t)f6-f98f: PP YGWV(hS!PQff; u+APPPi3f9t$9sWVP$t S$3f,SuL u"3؍dËM_^3[3PPPPPz%̋US3V9]~"W}7u u u F;u|_^[]SSSSS9%̋U(ee}v%3.EWFEMPEEEE؍EE܍EEEEE EEPEPEP=EËUSV3Fhu %3YW{f3uF00Eh I5\IjhQW\IEhIhQW EHM Mff;uftfPf;Qufu3uh I!EEEE E0jhQWYE=Ij}uHN(tu v(#YF$t8Ou v$#Yf$Cf^(F _^[S#YN(tu v(#YF$t8Ou v$o#Y3F$FF(F F@3PPPPP#̋UU3ʼnEE SVuW}8t!tVPW 3Dž<0؉DZf>Lhf~C]f~_RhIV؉4YY.+<j;Xf9<\IDž@WV3 u Qff;0u+;t@ I~Ë4hIS8YYu j;Xf9@_VShPu6=b3fP@WWD tADD4sftf34PjUHPhPV3ɍW D f8f;98u3f8t'fPf;QfBDufBu3ɋ3Ʌt,PVWlD tC3 3ɋ<Cf0Df;18u5f8t'fpf;qfB8ufBuDucQff;Du+A4EP(Y  >, OQ4@PE ZfC@>ufu DHPyYD0ы<ΉG@F 4F$ I _;h$USË?k8Mh"U3A}MT8('Mv } tыT8UT8)UV3tOtU MUШux !0 }U MUh"UШtjXE;rMP3jj uu djjjSCM h"UD ET$֋Mh"U]3UD(H]]D*]< ]GBEI}UMh"UD* ]tE]h"UD+]< tgtc]BEI}jUh"U_MD+ ]u;E]h"UD,]< t#tBEIMMjh"UU_D, S*YtqEMh"U|(}]EPu`pItL}uJjEPEPuu$rIu@pIPoYVWY^EMGh"U\.;|}܍E|E|3]}Q@EPE?xUAM;}3ttx}@QEPEPEPEHMT-tD.EEEjT-EPCEy<Mf9H},GE;E5jEWP I}jWEP ,SSjEGPu؍E}PSuK E̅SMQPEPurIu+uEu9E} u4j XSfEԍEPjEPurI}EFu;}M~&u܋Eы h"U3CD .M؋U;|u}uS~u܋EӋ h"U3CD .U;|΋UM]h"U\.h"UL-F@pIE8]t EPEuM3ͥ_^[/ËUQSVu3W} EljE;s?SYf;u(F uj [SYf;uFF;}r@pI_^[ËUQVuWVYtU?k8h"U|0(}<@Luh"U|0)tEPh"Ut0`pIt2_^ËU U3ʼnEM U?k8S]h"UVWDMщ3;ss;sA< uC FFE;r䍅M+jPVPWrItC;rM;r@pIM_^3[{ËUU3ʼnEM U?k8S]h"UVWDMщ3u;s% u Cj _f>fE;r׋+MjPVPWrItC;rM;r@pIM_^3[蒝ËUU3ʼnEM U?k8SVh"UuWDM3;P;s! u j ZffM;rjjhU QP+PPjhFu tQ3ۅt5j+QPPrIt&;rˋ+EF;F@pIM_^3[`jhT貚uu  ;5h$Uƃ?k8Mh"UD(tiV=Y}eh"UMD(u uu VQ }E )u}V >Y` k Md Y_^[ËU(ME EMSVuWu  Ƌ?k8Uh"U}\:)tuШtD:( tjjjV83}V Yt?t%ˀ]uESP u]ESVPMUh"U|(}EË]t*tuluESVPuESVPuESVP뢋L}؋]3jEPuSQrIu @pIE؍u؍}䥥MUEu\Et*j^;u 0PrYh"UD(@t;tl h+E3_^[ËUUVtM t uuHj^0^]W+>Gtu_u j"3ӋUQEjj QQjauËUQEjj QQja-ËUEu]ËM UVt2ft f;1u +^]ËUVut j3X;E r4u uFt VrYtVj5'U,rIt ? 3^]ËU(U3ʼnE}Wt uyYjPjP~h0jPk0ffffffEEDž0@E EEqIjqIPqIuu}t urYM3_ËUEL"U]ËUV` t)\tuuuu urIփ^]u5Uu35L"Uuu uu3PPPPPjqItjY)VjVj# VdpIPqI^ËU}t-uj5'U0rIuV@pIPY^]ËUVuw0uFEt VYtVj5'U,rIt 3^]ËUSW} ]?uE 3fVuMFExu!hP"USWuuMtf3FEPP@YYtBu~~);^|'39EPuvWj v.uu ;^r0t*v339E3PuEFVWj p.u*}t MP^%P"U%T"U3_[ËUjuu u]ËUW} u9}vEt!83S]t }Vv!j^0uME3Hu,EuPEPWu t~?069u\fEf;v7t9uv uVW! j*^0}t M胡P^[_Åt9uv\tҍEuPVuEWjPVQ= t 9uut@pIzut9uv uVW蛞 j"^0pUjuuu u]ËU졤UVW|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졤UVWMt!E A;t3f9t;u+jуj X+#ЋE ;sЋut>t64qI&$Uu^]jhTrejYej^u;5 UtY UtJ@ t U4YtE䡈 U PXqI U4Y U$FEEMd Y_^[jYËUVuW~  t%tvrY!3FF_^]ËVWP%U3jhWt&UPr۰ jY2_^ËUkEP%UPLqI]ËV5&Ut kW8%UWXqI &Uu_^ËUkEP%UPPqI]j hTrq3uE0YuE 8ǃ?k8h"UD(t!WYPqIu@pI uEƋMd Y_^[ uM1YËUVuu G YxE;5h$Us=Ƌփ?k8h"UD(t"EuEMEuPEPEP ^^ËUWu "YM I u E jY E @ t "ыE @ t(u wYM aE tHE jY !E Sj[ E jY !E `E @ u3Vu j~Y;tu SpY;u W1Yu u kY^u ]SYYuE jY [_]ËUVWu YM ЋI M 3A1+@E HIH~$E VpR@ E ;HEett‹ʃ?k8h"UHU@( tjWWR #ƒuE jY jEPR H_^]ËUE@ tËESV@ Et;HtN@PYt<3ۍECSPjjVpIt%EPVpItE;EuE;Et2ۊ2^[ËU]UUVtM t uu3fJj^0^]W+>fftu_u3fj"3ˋU=@"Uu]*juu u]ËUMSVWu蜠Eu3MtU uh;vM}􋟤uuVPRQ-wPRPQhESP: u <p}t MP_^[j hTl3u>jY}EP}Ytxx8xHEƋMd Y_^[ËujYËUE3ɉEHEHEHEHEHEHE ]ËUQS UVW= U ]B7tRF u.VYV   u] ШuVY;uE _^[ËE0j8jaj tӃHjh P7 F VtY벋UVWu EPh}YY}_^tWhuEuuP"\u9E U M E3ɉHEHEHEMEAE3ËUVWu EP?j}YY}_^tWhuEuuP^u9E U M E3ɉHEHEHEMEAE3ËU]U]gUW}u u yY$Vu u W.Yv%e 3^_]詼tV^|YtVWj5'UpItҋUEVub@ S3 CKE@ 9E@ ËEtjY  E@ u uCeYEHuvvVYPF EP@ u_u诹Yt7u衹Yt)uWV葹V膹Y?Yk8h"U_HU@($Ytu }2_]ËU]UjupIu@pIPͻY]3]ËUVuyQ3S]t-SQYu)觻读 3؅t@fE:.3]EfE.3W} uaVMEEEEEEEPEPYYuM|}t u蜡Y}t u艡Y3_[^ÅrEEEPE}Pu}uYYu뺋U$U3ʼnES] W}y誺31Vut7VYu3px 3^M_3[}WtF@j:fEXfEj.XfE3fE j.XfE3fEug3MWE܉EEEEEEPEPYYuM~8]t uOYi}]u5YO賹63]fEEEPE}P]}YY U U3ʼnEEvAI 趿7u3@0@j:fEXfEj\XfE3fEEPqItu3M3VËU3PPju uP]ËU3PPju uP]ËUM3SVW~;t;u5;w'tN*tI+v8.v91t13t!vv;t ;t U #E$P#E PuuuuRQHpI_^[]ËU(U3ʼnEESVu E3W} D@ |ӋʃD FD ܄uu}؋?3@߄Dt&?t~3@ʋ߄Du܀?t%3@FDu ?uE+M3#8_^[MTvŰUu MEhu0諜 }t MPËUQQU3ʼnESVuW~Vu赫Y;Yp|}$u Ex}$39E(jjVuPWTЃUXH;#t5=w"܅tPEYt U3ۅRSVujW}3PPPPPWSuu Ut8E ;3QQQPuWSuu 6H;#t/;w\t`PYtK3t:jjjVWuSuu 6t3PP9E u:PPVWPu$ u,WxY3SoYƍe_^[M34Ru uWLYԋUuM迃u(Eu$u uuuuu P$}t MPËUEt8uPXY]ËU,U3ʼnEESVuE؋E EԋEEW}}~VWKYEY *] ~ SP+YY  E$u E؋@E$t;CMQPpI~4}r&}EtHt:r:8ujX~7}r)}Et u܊Ht:r:\8u3@U3WWVuj u$*E؅3 Q;#tA=wĉEPEYElj}uPVuu$jVWWSuj VE Q;#t2=wdt\P臹YtGt6uVSuju$.t]WWWuVuSuuX]VY]SuY jl3e_^[M3/OËUuMˀu$Eu uuuuu PD }t MPËUE%]ËUE tjt3@]ètjtjX]]ËSQQUkl$U3ʼnEVs CWVPsw u&ePCPCPs C sPEPks s^Yt)t%CV\$\$C$s WR$W$VCYYM_3^M][ËSQQUkl$U3ʼnEVs(C WVPsC u4EEC jPCPs C(s]PEPs(s}Y2t*t&C V\$C\$C$s Wp$W6$VC YYM_3^L][ËUS]VtEtjY#EtjYEjEY #tT=t7=t;ubM ЧI{LHM {,ЧI2M zЧIM zȧIȧIEE WDEPQQ$U U}3GgAu EeEfE;}0E+ʋUEtuGEEt EUu؃}EtE 3G_tj2YtE t j Y3^[ËUEE]ËUjuuuuu u]ËUE3S3CHEW HEH Mt E Xt EHt EHt EHt EHMVu 3A1AM3A1AM3A1AM3A1AM3A#1AWtMI 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`EXP~EPjjWqIMAt&At&At&At&At&ߋt5t"t u( % % !tt u!#  # } ^tAPAP_[]ËUEtw詪"]蜪!]ËUU 3ɋ9hIt@| lIMtUEEEEEEEVuEE hu(EE$uE(EPQ uVUYE^hu(u9E ËUEVDz 3Wf}ǩuzM UuthپS3AuCEuɉM yM NEtf}Uf#f}[t fEEjQQ$1 #jQQ$ _E0^]ËUQQMEE%] fMEËU} Euu@]Á} u ujX]fMf#f;ujf;uE utj3]jhT D=U|[E@tJ=UtAeUE:E8t 8t33@Ëe%UeUǃ࿉EUMd Y_^[ËUQ}EËUQQ}M Ef#M#E f fMmEËUM t -I]t-I]t -I]t ؛ t]ËUQ}E覟P~YËUQQEEE3E %3EEEËUfMff#f;u3EQQ$(YYttt3@]jjX]ø]ɁfuE u}tɃᐍ]EDz ɃA@]Ɂ]ËUQV5&Uu-d0!uF@x|EP#9uuj^θ&U^ËUQd0V3u@9p|EP}t3F^j0ucI}3E ]}؉Eut u3tu_XuMtEȉuHuEԉuPSEuPW}9u:Mf9n7MfF;rxuat#Ef90tut f90u+]CEPVSWSuVQ\ }|7)N#EPVSWjuVQ! t}w}@pIz EUȋJ~jY]SVQMQjPVr]Ѓ }:;ƉE܅~M؊D9E@GE;|EE;nt*-9u)Mftf;w7Ffu3EPVVVjuVQ t }ux袣*}t MăP ËUQVu 3EW}t.t.tS]t9}wE=v @jYt3j^0衩kuPuVutE@t5;v'}t;wj"^0SjPYMD0Mt[_^ËUupIu@pIPbY]3]&Up3&U&U&UUø&Uø&Uø&Uá&UËUMu:觨jX]á&U3]ËUMu{jX]á&U3]ËUMuOjX]á&U3]ËUSVE3PudY9u]W{;= Uu ;=,U^95&U b'Uf95`'Uud'U3f'U@]uf'UƋ։u]h'U]j'U]l'U]n'USu]uuuuRQWPVM'U, 'U]'U]'U]'U]]f95 'Uu'U3='U@ Ƌ֋5'UuuuuVWRQsPj,XVVV3kjV@VP3kPWjVVV3kVjVVP3k PsjjzX$U0UK_;};|Q;M;~;}3@^[;|;;~;|.kC<Ck<i3;u ;5(U;54U3VVVVV6̋UQQeS]VWSy!} }YEujt 4,I4ISF!Yimj6YkM+u;U}t 0II}u ;~t 4,I4Iu kE$<E(k<E,iE0}u5$U(U U_^[ã4UEP50UYuAiM4U4Uy \& 0U=\&|0U4U,U3PPPPP̋U SV e؃eEP]UYEPY&Uut4ʋƊ:utX:Yuu3L]R袤Y΍QAu+ʍAPĤj&U~&UYYWyAu+VAPR- j_WVj@3;>tFu_-uFVlYiM+tB< wF:uLFVEk3.uMWUu E܋UE S3ۉME>}f}uEf%tfMEHMEa9]]ȃ#u uEfEt fOuuMRQMQuPEPeEt"MU^t] 3f+]4t3fuu 輇"诇}t M؃P[^_j hT#EE0YeM 0؈]EËMd Y_^[ ]E0YËUQQVu u苍y>tEtߋtـ8tSWj\V(j/V(ޅu~j:Vi(YYup΍QAu+jyWYYuPWY_[^hIWS ,VWS P{Y t;v+j.W#'YYt+jSYYuuSuˍQAu+jAPEdYYuS]SWo CljE…IESjuB uWPW~YYtIuWDY%}uMuWu'WYVY3PPPPPˋ̋Ul} u/蜋Ã}t}v SWE3PE}Pu}u7;uu薋u}苋YYC}}PEPEP u(u]u}Ru}G ?}Vuj^]jD8E_WjP,fEfEƋEEȍEPE}P3PuVjPPuu u؃4}܅tJEu_SVpIEPupIt!EE;tWxqI;tVxqI]B@pIP藃Y;tWxqI;t&VxqIu<;tWxqI;tVxqI3uKue?ue3-;tWxqIuueueƃ ^_[j^̋USVW] C 5h$Ut$~Nj׃?k8h"U|(tOu߁23r܂ 2kjPE*EYYu譂2 P0 2U3MMtB‹ًϋ׃?k8 h"UQ(u8I8 G;uˋE]UK9u%3Ƀsj_;t}AB}݋ K3ۋEC j輈Y_^[ËUEEME EEjEXEEEPEPEP4ËU]U,U3ʼnEEVu uEW}}؅u腁h>ttߋtS[EԄu6u WVu]m8u"j\V#YYuj/V#YYu~:u3EPATHEMPQEMPzM t ujhYYahVu E܅E]>6΍QAu+ʍ~j\V!YY;t.j/V!YY;t EfE\PhV &֍JBu+ыˍyAu+ύ;SQV uu؃ Vu8t]8tSj/V~y"YY;uj/Wk"EYY;tEj\VU"YY;uj\WG"YY;u2}uthVu E܅]VYMQ܅eYEԃ8ut[M_3^Ë]3PPPPPs̋U]+U(U3ʼnEEVu~ ~j^0&|S] t~ ~j^0TMQjPpIu@pIP0~Y)Eu,Et&t8~@~ 5~3[M3^BËU}uu j*YY3VEEEEEE蒂PEPuh tu uYY}t uqY^ËUju upIu@pIPV}Y]3]ËUQQM3S] VW]E8Etj-XfCE3@ىE]u]3ҋuj ȋCEX;'0f‹UFfEt;rˋ] ;ur3f|j"^0m3ffff;r3_^[ËUE3ɋU S]VEWM8MtA-ۉMpuڋEuuESjuRS茘][؍FEj X;$'0E@Eut Mu;rMu;rE1|j"^0蟂EOF;r3_^[ËUM Vu{j^0dOUSt$]3f@;w {j"uF"v{j^0%SVRQu[^]ËUMVu{j^0PUSt"]@;w [{j"uF"vG{j^0赁SVRQu u[[^]ËUQ} u }E|Euuuu uËUjuuuu u?]ËUU3ʼnEVu Wh 3WP!# PhrIt*vWWu؍VjQ@WP tH3M_3^pjh(Tuu7zj^0襀Y}t}t Eu3EEEuuuu uVEP,}EtNjMd Y_^[Ëu}}t%t?k8h"Ud(6YjhHTuuvyj^0Y}t}t Eu3EEEuuuu uVEP}EtNjMd Y_^[Ëu}}t%t?k8h"Ud(6^YËUQEU?SVW}(3k8h"U8\(u$@u%E]PYE%@uC@%@=@tE=t,=@t%=t+=@t$=t=@u 뿹#;uE @vE#‹ˋ=@t=t1;REGvv[43FjE]Pu+t5+t,+t$@tNu{39~jjX3@3fF Fyu@uEP(Yux9}tt'U#ExF@tNNN t N tN t N tN_^[3PPPPPz̋UQSVu֋?k8Wh"UD(Hu{ywjjjVڋσ#˃u t8tNtG3fEEjPVi uf}uSWVs t3PPPV蕮#ƒt3_^[ËU3VEEEEEEFxPEPux tu uuuuu u9}t uzY^ËUjuuuuu ]ËUDSVWuEuuP1}ԋjY9uur E 0r蕲] ;ur 3rϋEuԃe3AE E#jYEEPu }ukM؋#;u5Et/EuԉMjYPu }u+ ?k8h"Ud(@pIPqYWqIuG@pIVqY ?k8Wh"Ud(xqIq uE @ Eu W3E藰UYY U?k8Uԋh"UT( ?k8Eh"UD)t3Yt3Y*EEPuuԃjY3L$tRƊE?k8 h"UD) ?k8 h"UE2D-$0D-EHuEt ?k8h"UL( uع#;EtuxqIEu؍ujYPuЃ u2@pIPp ?k8h"Ud(3Y ?k8h"UT3_^[ËUjuuuuu `]jhhTR ejjYe3u;5 UtQ U<}܅t2W^WYEG tt WjYEeF뱋uu8WYEEMd Y_^[j)YËUVu tj3X;Eso 3BS]Wt SpY3uVS\YYt;s+;VjPY _[^]ËUSVW}tM t ]u3fnj^0u_^[]Ë3f92tut+fRftuu3f_nj"봋UVuWtM t }u7nj^0t_^]Ëր:tBut+Btuu mj"3ŋUQSVW}tu ;tntiSVpIuEPVpIt tE2@pIum {mPJmYt;tVxqI cm _^[ËUE uEm3]Vutw&m3MA;tNSWtR;tRA"u&t'ڊӀ"t@A;tڄut A@;tul"3;uA9;t+#_[^]ËU]1UHS3V]]]]ĉ]Ȉ]̉]Љ]ԉ]؉]܉]]]]u]]]pPEPup u`pPEPu p uG9]$tpPEPu$pu u&u,u(Su uuuuuurI؀}tVzrY}t ukrY}t u\rY^[j(hT Eu+nk ykqMd Y_^[Ãx8M?t0k ;kq#;tE 3ۉ]̋ЃEu EPEPEPpIu@pIPjY苪u;u)jjuxqIuxqIw]ƃ?k8h"UD(h"U\)h"Ud-E/E;u+?k8h"U\(q3ۃuV©YE}؋ǃ?k8h"UD(h"U\)h"Ud-E]ԍEPY]u @u79Eu2ƃ?k8h"Ud(ǃ?k8h"Ud(y2ƃ?k8h"UL(ǃ?k8h"UL(uVIuW@E0x33ۋu܋}W貨YSSSSSőUju u ]ËUMSVu37MuhIoQ]9suu Q] YY:WMD;tAt 9} uu 9} uAu_}t M샡P^[ËU UVuWWCojFn~F YYtj@Y  FjF_~Ff_^]ËUMu3]S] VW}Bw 3Fw ƒ+u tu_^[]ËU=@"Uu)}ugn]Ã} t]zjuu u]ËUW}u_gmS] u=gmVuu3vuM5EuVSW >MQP5ME[QPU+u tu€}t E샠P^[_ËUju u ]ËUVuuufl3iW} uYfl3LuM5M39Qt%tDt F;t 8t F;v}t MP_^ËUE ;Ev]]ËUSVuuu j3ۉ^^ ^33f9u u 9^ ujFSSSSjVSu¬ u@pIP8eYheMW} ;G v P7u7SSw wjVSu| u@pIPdY"eHG3_^[]ËUE (Vudj^0lkuS3Wˉ}؉M܉]taMfE*?QP]YYuEPSSQuURPQ$ Euuu}؋M܋]+NjЉuB;ΉU#t/NjӋAEAu+MCEكBE;u݋U]3juR_2 uu}E}ȉEljM;Et[+׉UЉEBEBu+UBPuEE+EPQdurEUM MME;EuE ]0S0jYE܋+‰U9U#ȉMt7jCY;u}؋uWiY_[^SSSSSi̋UQMQAuW}+ʋAЉM;vj X_SV_jSYgYYtWu SV蓙uPu+ߍ>uSPzu7]3Et VZiuY C0CWCiY^[3WWWWWh̋UU3ʼnEM USW};t#u&jj/djsf tFF+>vj X5Sj?S6F uj ^ NF3jfY[_^ËU];U,U3ʼnEEhQPpIu@pIP^Y3UM EƅcPPPPيM3jhT E09YeM *EMd Y_^[ E0LYËVQ@HPQ5|'U`Q@HPQ5'U`F uF88Ut0dYFBH@H^ËUE-t(t tt3]áI]áI]áI]áI]ËUMj],%'UEu'UpI,u'UpIuE'U@}t MPËUS]VWh3sWV{3{ { 8U+7Fu9Au_^[]ËUU3ʼnESVuW~ PvpI3ۿÈ@;rƅ Q ;s Ƅ @;vuSvPWPjSSvWPWPWS@SvWPWPhS֦$EtLtL ˈ@;r>3ۿˍQB w LA w F AÈA;rˋM_^3[iËUuuuM EIH;Au3SVWh bYt.uvHWu'YY;uZWaY_^[À} u~5E@HKuExH8Ut pHSaYϋE3HHEPuUuEEMjEEXEEEPEPEP} mE<U^j hT3u}UPt9wLt wHtmYj蛃YuwHu] ;3t'tu8UtV`Y3wHuE뭋uj蓃YËƋMd Y_^[=̀='Uu<'U8U'U`U|'UXUHjh'UPjj 'Uh'UeiPYYËU U3ʼnESVu WuuY3ϋljM9hUA0M=rPpI;u&F~f~~3~ VFEPSpItuhFWP ^}u}Et!HtLA;v8uߍF@uvI3Gf9='UhFWPq kE0ExUE8t5At+s`UDBA;v9u΋EGErS^FEN jlU_fRfIuV%3YM_^3[bËUVuM%u EML0u39UtEp#E…t3B}^t MPËUjjuj]ËUUW3f9:t!Vʍqff;u+Jf9:u^B_]ËUQSVWpI3tYVWWWW+SVWW謝$Et6PQ]Yt3PPuWSVPP脝 t33W\Y߅tVpI_^[ËUVuuV SWj=VEYY;@E39!Uu{9] t9!Ut&vZ8]u3jjYS!U9\ 9!Uy9!Uu#jjYS!U\ 9!UN!UE>E+PVEYYMxO9tK4[YM8]u0UDA9ujQRSE[Etb[E4V8]؉EP;?jRQaSEQ[EM4\!U9] tNFu+jFPEXYYtFuuVW uXM+EAE#YPVVYYuT*VZYSWZY_[^SSSSSbZ̋UQW}u3_3ɋ9t @A8uVAjPXYYtftPS+ߍQAu+jAPEWj;.Z <;t.7u4;V uu[jZY^r3PPPPPY̡!U;"Uu P=Y!UËUSVW=!Ut*] SPu u <=ttu+_^[]+U]qI'UÃ%'UËUSVW};} tQtrIӄt;u u;u t.;t&~tt jrIYF;u2_^[]ËUVu 9utW~t jrIY;uu_^]ËUE'U]ËUV"turIYt3@3^]j hT2ejJ{Ye5U΃35'UΉuEƋMd Y_^[ËujO{YËUMS]Vuuu9u t)AQj^0W^[]ÅtE tu 3f3u3f+ًWufRft.u'fRft tuɋMu3f_uuE 3jPfTAXt3fPj"YU]*UQ`HLMMQPbEYY@ËUXU3ʼnESVu3Wű]䋎]]܉u]F]9uPhQESPSjjlTSEVjWVTSEVjWETS}Vjh.TSErVjhTSE]V<9]9]M܅9]È@=|EPvpIEEȃvT~uEhj P 3U8]t+M܊Bt2;w  FB;~8uۋűM܍SvARPRQhMS趙$'ESvQPQuhS胙$ESvPhu܉EjSE3҃}fU؉MMZ}Y}~uWE؍j+X++‰Eԍj2[;؋]E%f]ԍA =~h}8]tb]GtV7u;wAUԍ+ыMč4sEظfv  AGC;~U؋M]?u3ۋEj?YjEYjfYffűtIu@-PS+PS+PS|SEEEEEEȉF$u:Su2SW,Su$S3ۃCuSY<t3`IdžIdž`IFM_^3[+ËUVuF ;UtPRYF; UtPRYF;$UtPRYF;(UtPnRYF;,UtP\RYF ;0UtPJRYF$;4UtP8RYF8;HUtP&RYF<;LUtPRYF@;PUtPRYFD;TUtPQYFH;XUtPQYFL;\UtPQY^]ËUS]3VWM]M9u9uMU4jPj:Oju{Q u3@VjjOj}WQ u VJQYӃjjNj}%Q uVQEPQY‹F PjWEjPNMEQjWjPM EPjWEjPM EPjWEjPMP EEPjWEjPM E PjPWEjPM E$PjQWEjPM E(PjWEjPlMP E)PjWEjPRM E*PjTWEjP;M E+PjUWEjP$M E,PjVWEjP MP E-PjWWEjPL E.PjRWEjPL E/PjSWEjPL E8PjWjEPLP Eu9JjBMj}LYYSu LY'E싾jWjPIKQjWEjPI CPjWEjPI C0PjWEjPIP C4PjWEjPI t*SbSmLueL MMQULEYpS HЀ wh Bu}uM3@ttN|tuv|LKYYEF|3_^[<;uFu놡UUCUC@UC0DUC4fUM SVuW3?;#t6oKGvY;u_^[]ËUE eSVWVuEYM3j1`XjZEUMj_3PuEVjPHu ؋EPVuEjPG ؋EPuEujPG ؋E}PVWEjPG ؃PE@mEhEj8^huEE Ѓ PVWEjPGu ؍EuWjPlG ؋EPVWEjPTGu ؋EPVWEjP9G ؃PEFmEuuuPj(WEjP G ؍Pj)WEjPF ؍LPj(WEjPF ؍PPj)WEjPFP ؍PjWEjPF ؍Pj WEjPF ؍PhWEjPyF ؍Ph WEjP_FP ؍TPjWjEPEF ؍XPj WEjP.F ؍\PhWEjPF< _^[ËUVujV3FjP(F8j PFhj PjPHH|HjPjPDj Pj PLjPT(HXH\H`H(^]ËUS]VW39uȓIFhdjEYYtSViYYuVYWG3@$WdžGY{3Y_^[]ËUQMSVuWu u 9M u3,tE t]tu3f@j^0F_^[Ëыf:tut̓u+fRft8u1t&[fft tuMMEuf]uE 3jPfTAXv3f?j"[U]UQQU3SVWf9t8u ft#Ef9EtЉUUfu3f9u_+^[ËUU3ʼnESVWuM/]uEX339E WWuuPSuEJU;#t5=w^tPEYt Ut1RWVOuVuujSu$tuPVu qIVY}t E䃠PǍe_^[M3ËUE@ H|ttttVjH(^y@Ut tyt QtuLY^]ËUQSVuWtl=UteF|t^8uYt8uP}DYYt8uP[D?YYv|FD;DYYtE8u@-PD+PD+PCCYjXE~(@Utt8uPC3CYYEtGt 8uPCYEEuVyCY_^[ËUMtȓIt3@@]ø]ËUVut!ȓItuV?VCYY^]ËUMtȓItH]ø]ËUEtsH H|t t t t VjH(^y@Ut t yt Qt uZY^]j hT&eK UxLPt7u=j"eYe5d"UW=YYuE t uj6eYËƋMd Y_^[w̋UVu WtI|j@PNdɁQW ^u !FX@rS|PvT_u3ۉxYYj@|PF`%PW]u!^X|PvPuYYNXuNXύQff;u;uX9^\v\|PvP uzNXύQff;u+APWjUPxFX#;uN`|j@ɁPQW\u5^X3@NFXuWYtNXύQff;up|PvPtYYNXNX9^`t1NXf9ύYff;xu9^\tyVPZff;xu+;V\uYWsYu$^P3ҍKff;uvP+Y;tlNX3f9uXύYff;xu*3ہNXf9u,ύYff;xu+APWjURuFXЃ[M_3^ 3SSSSS<̋UU3ʼnEVW}^F jxPN`ɁQW,[u!FX@V PvPrYYu6S3ۍQff;u+APWjUP0u NX[FXЃM_3^ SSSSS<̋UQVuW3f9>Iff;uftfPf;Qufuދh|IVqYYtjhIVqYYtYIff;uftfPf;Qu fuu.jEPh E PPYt'E}_^V8YjEPh 3UU3ʼnEVuEj PjYVYtj EVP8 u@3M3^tËUQVu 3WB3xNStH7+‹؋Ek M4E0pYYuEMȋE ys{;~[3_^ËUQQS]VWC33҉UpPPVf~Eˍf9tWjhIG 3Vf9tGf9t&3Y9Fu2Vj@hI t3Vf9t _Y39~6f9;u f98upI VPYY PpIE t0}M 3fQff;Eu+APujUSj@WhSWj@Sh PWtjj_S}YYuj.SoYYtj@Sj PWWt9ujh|IjWuj jWV3@3_^[3PPPPPt8̋UU3ʼnESVuWAAVL YKdٍ jxɁPQVDrIu!@3 PsTnYYuVYt wwЃM_^3[gUVW`A3JTqff;u+3jhƩHBdqIEu8_^]ËUSVWA3jZNPyff;u+3NTF`yff;u+3}Fd_9^`u vPYjhޫHV\qI "u_^[]ËUSVWy@3jZNPyff;u+3F`t vP"Yjh1HV\qIEu_^[]ËUM3fArfZv fwB]ËUU3ʼnESVuW??VLYKdٍ jxɁPQVDrI PsTkYYjx PC`%PVDrI PsPkYYu wdub{\tBs\ PsP& u)wKPQff;u+;K\uwuV0Ytw#;jx PC`%PVDrI PsPjYYuj9C`t9G9C\tSPBff;u+;S\uWjV tN3339C`u99C\t4 PsPRjYYuW3SVc t9_uwЃ3@M_^3[UU3ʼnESVuW==VLYK`ٍ jxɁPQVDrIu!@a PsPiYYK`u u2Wj u29K\t- PsPoiYYuWPV t wwЃM_^3[UUV3 ft9Wj_ARf;wAf;wɃ fu_^]ËUQMVW3f9If:f;>uftfzf;~ufuދ҃t]If:f;>uftfzf;~u fuu jEPE h pDrIt)E5Q/Y,jEPE h pDrIu3 EupI_^ËUM3f;It r3@]3]ËUQVWo;ujEPh QDrIt2;ut(} t"wPNffuwP+Y;t3@3_^ËUQSVu W3x47+‹؋Ek M4E0?gYYtys{;~2_^[ËMEMUU3ʼnEE S]VuWE:P}E3t:M3҉LE0xtf9t IWHPhI0E 3҉Utnf9titf9t EP EP}YIuHPhI tN3tf98t EP EPȉj _tu33ۋ0É4\C,3DžDž3ɋ ; 0u䍂ϋ3҃+ȉ3@k=,HЉt@33+su 9v2Ƀsrr jrZʉ+0;rg;s3F;sB3##苍㋍ É0INt,땋t΍03󫋽9v B,3,+3P,P0SP63jXA\PP`SPϋ3҃+ȉ3@;,HЉt@33+su 9v2Ƀsrr jrZʉ+0;rg;s3F;sB3##苍㋍ É0INt,땋t΍03󫋽9v B,3,+3P,P0SP`3@Dž\j#5DžDž3ɋ ; 0u䃥t@3+,΍;s0A;s3ҋ Љ0It,볋s F,,5+VjP3@5,t@3+,΍;s0A;s3ҋ Љ0It,봋s F,,4+VjP&3@5G\PP`SP3j YT񉅐ʉ|b&vj&X I4IW1jPzPI8IPP@wru3\\\33؋``F;u`\Y\`PP`\SPu3\P\\3ɋ3؋``F;u\s43\P;\r``ut ω \t\33<u;F3ҋ!std;u@Ɖ$@A;ljut4s;uA3AȃsF;\PP`SPtr+|ԉI|u]3\P:3\PP`SP:2늃\jP`\33`lj`|F;uW\sQ`\6񉅠ʉA&vj&X I4IW1jP$PI8IPPu3,Pmu,h,33؋00F;u3,s0,,0P|P0,SPS6,,3ɋ|3؋00F;uE;,r00ut ω ,t,33<u;F3ҋ!std;u@Ɖ$@A;ljut4s;uA3AȃsF;,PP0SP}+ԉI,330lj0F;ut,ssN0,e3P,P0SP27,j3P,P0SPz,t|j 33[0Ɖ0G;u䉵tB,ss‰0,&3P,P0SP\P,P|YY w\1j 33[`lj`A;u䋵tV\ss`\<3P\P`SP4u H 0wAx wȋEH;r;,33ɋ0ʚ;lj0A;u߻t@,ss0,&3P,P0SP_\P,P{YYj_+30;r7Ou vj Y;4t_^[t lP9YM3ThhI h`IhXIuQ u hPI3PPPPP}̋USVW3;+‹jU4Iu軤 ty^~;~ЃI_^[]ËUMSVWt{ts} uufxb3;+‹+pItyXx;~݃x1tIjUSjYY~;}SVu 9 u G3_^[]3PPPPP̋U}tuYx=s pI]3]ËUuuu uqI]ËUf9Eu McfMf;s$UbItEEujMQjMQRPu EE}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%?Pe=UY}3 ]MQYЋȃ? ы? ы  _ ^ËUQQV3WfE}M3?G## # # # 9=U}3 ]U?ʋ## ȋ# ȋ# ȋ# ʋ  _ ^ËU WuYjЍ}Y3uE3Ё?3‰Eeu=UY_|]E%? EUËU SVW]?3F## Ћ# Ћ# Ћ# #ƍ}j 3YuM3ƒ?3ȉMe?Ë## ȋ# ȋ# ȋ# #_ 95U^[|]E? EUËU U3ʼnEE MMES]]VW8E}sMMΉuSPQ؃ tSE;t9]r1SPV, t 3ytt}E+]E뜋E3qU+u];uCE03jYWY_[uYƋM3^jjjjj>̋UQQVE3PuuiYYt uJGEuPu YYtu(u MEVMEVYY^ËUSVu3WjSSV:jSSVW:M G+ȋE‰wGljW O_^[] U(S]MVWuu SE#E܃#E#EE}EjhYYu zhSYEEY|rPVS t++E‰E|uuSΤV 3z8u  V8YU|sjuu S9#ƒt,S@YPqIu @pI8juuuL9_^[ËU}uo]uj5'UqI]ËUju u ]ËU}u"3Vu us9ur3EuMMVytJ9Uw Du+‹փ+J}t MP^3ɄËU0S3V]Љ]ԉ]؉]܉]]]]u]]] PEPu u(PEPu u u VupI؀}tVY}t uY^[ËUU3ʼnESVWuME3WWu@u E!؅t}H;#t2=wktVPYtAt0SVuu !tEWWP#EPjVWuC VGY}t E胠PǍe_^[M3FËUU3ʼnEE MS]VuW3px;h|PuVQttFjP,Wq 9;tAP|PQ3M23@pIzWWuVp[tjPYYt*tVuxptƋVYwu$u<f;w VYZ(f;w'@ 3=VQu.f;wčE3P%#}Pu}_>~ _^j qIX)U3U$~$fD$f(ffs4ff( `If(pIf(If(%If(5IfTfVfXf%f(`If(PIfTf\fYf\XfYf(fXƁ*f Df( If(f(0IfYfYfXf(@IYf(-IfYf(IfTfXfXfYYfXf(PIfYf(ffY˃f(fXfXXXfD$D$fD$f( IfwHt^wlfD$f( `If(IfTfVftIúOfI^f I4f IYs:fW^ɺ fL$T$ ԃT$T$$D$fT$fD$f~fs f~с t릍$ƅp uJ$$ƅp2+at@u tF t2t-`Iƅpݽ`aAuƅp-jI uS u uu tƅp-`Iu tBXݽ`au-`I tƅp -`Iƅp u-`I-~Iٛݽ`aAuݽ`aݽ`ٛu Iٛt øVtV$$vtft^t.̀zuf\?f?f^٭^I剕lݽ`ƅpa$؃PRQ rIYZX#zuf\?f?f^٭^I剕lݽ`ƅpɊaݽ`ɊaŊ$׊$ ؃PRQ rIYZX#ɍ$I؍$$ÐtؐÍ$d$۽bۭbi@tƅpƅpIɍ$$۽bۭbi@t ƅpƅpÍ$۽bۭbi@t ۽bۭbi@t ƅpƅpÐ-Ipƅp ÍI-I t tI tËT$fT$l$étIË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,IIs \ЁuT$t1 # fnfs f TfT$^ʺg #fTfWfTfvfɁf%=uefL$ fT$ fnfT Tfs4ffffvf%=t#fL$ f%tPTHTfL$ f%fL$ f%Xĺ]fT$f~fs f~ҁ ¹f 8TfpTYɺfd$fT$ f~u fs f~?ufTfWfTfvf%=uUffd$% уtf%=?rf%=?s@TXºYf~fs f~ fTt0f~%=wrwfD$D$ÃfD$T$ ԃT$T$$D$Ã~(=<VЃW?&=VЃ €WXXTfY\TfY\f(Tf(5TfYfXfpYXXf% Tfnʁƒ fW?fYT$Yfs-fpDf(=TXfYXffYYfYfXfYYfpYfpYYfnfs-fnfvfXXfTXfWfvf\XfTf_\XXÃN^YYXYXf%=fD$D$^XYYXf%=fD$D$fhTfnYfs-fVtfXTY`Tef`TYTfpDfYf%@+-p< Ё!=r ɀfnfs-fD$D$fd$f?f3%-KU$~$fD$ff%f-00f=Bf TYfT-XfT\f(TYfɁv?f(-TPzTfY\Y T\fxf\fYf\f(5TY\fYfY\f(\fXX\YfYYfYfYfX-TY fX5TfYXXYXfXfh\\XHfYXXXXXfX΃Xfd$D$Iff= uYTfD$D$fTY\YTfD$D$̃ $轎 R<$D$ tQf<$t)u='U T陎u,u%|$u"u|$u%t-I='U? T8ZU$~$fD$ff%f- 8f=ff( 0TfY-f(@TfXf(PTf\f-T)f(%`TfYكYfYf\fY pTXf(f\f5T0TfT-Tf(f\f^f\f(x\fYf\f(H0fYf(``fYXf(fYfX8fXH fYfX`PfXf(HpfYfYfXf(H@fYfXf(fYYfYfYfXYfXfX\XffXYXXXf=TYffTYY\\\Y\X\X\ǃXfD$D$?ff=~ u YTfTYXYTf\$D$$̐T$B J3mLT}-MGT$B J3JJ3@TP-h T<*|&8HZn0HXn|rf\J6(vbR>(".Fd|"6Rf(<Hp| (6Fh&BN`r.HZp  ots`DqF qFqFJFPG#9H HUHGkH!H"FUUnFvIvIvIvI vI vI vI wI wIwI $wI 0wI8wI DwI PwI I\wIdwIlwIdS`SSPSpwItwIxwIwITwIhIdIwIwIwI ISwIXSwITSwIwIXIwIwIwIwIwIwIwIwIwIwIwIwIwIwIwI wI wIxI xI$xI0xIDxIdxIxIxIxIxI#yI$yI HyIhyI&yIyIyIyIyIyI#yIzI zI zI+++&->*<>,()^|&&||*=+=-=/=%=>>=<<=&=|=^=`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'`anonymous namespace'|I|IIapi-ms-win-core-fibers-l1-1-1api-ms-win-core-synch-l1-2-0api-ms-FlsAllocFlsFreeFlsGetValueFlsSetValueInitializeCriticalSectionExTF,FUnknown exceptionHTF,Fbad exceptionEEE50P( 8PX700WP `h````xpxxxx(null)        ! 5A CPR S WY l m pr  )   Y* Visual C++ CRT: Not enough memory to complete call to strerror..exe.cmd.bat.com./\ Tc-^k@tFМ, a\)cd4҇f;lDِe,BbE"&'O@V$gmsmrd'c%{pk>_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-16LEUNICODESII$I4IPIdIIIIIЍIIIIS(I8IDITIdItI4SIIIS܎IIII,I?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~IrvFI@UrvFI@UIHԒI@UHI@UŔHI@UlHLC_ALLLC_COLLATELC_CTYPELC_MONETARYLC_NUMERICLC_TIME=;;=--_.C_.,_IIIIIIIIIIIIIIIIINFinfNANnanNAN(SNAN)nan(snan)NAN(IND)nan(ind)e+0008T8T8T8T8T8T8T(9T8T8T8T9T9T9T09T49T89T<9T@9TD9TH9TL9TP9TT9TX9T\9T,I4I@IHI@9TPIXI`IhItI|IIIIIIIȕIЕIؕIIIIIII I0IDIXIhI|IIIIIIIIIĖI̖IԖIܖIII III$I0I@ITIdIxIIIIIؗIIJanuaryFebruaryMarchAprilJuneJulyAugustSeptemberOctoberNovemberDecemberAMPMMM/dd/yydddd, MMMM dd, yyyyHH:mm:ssSunMonTueWedThuFriSatSundayMondayTuesdayWednesdayThursdayFridaySaturdayJanFebMarAprMayJunJulAugSepOctNovDecJanuaryFebruaryMarchAprilJuneJulyAugustSeptemberOctoberNovemberDecemberAMPMMM/dd/yydddd, MMMM dd, yyyyHH:mm:ssen-USHI|IIIIhII|II0IlIIIPIIIIIIPIapi-ms-win-core-datetime-l1-1-1api-ms-win-core-file-l1-2-2api-ms-win-core-localization-l1-2-1api-ms-win-core-localization-obsolete-l1-2-0api-ms-win-core-processthreads-l1-1-2api-ms-win-core-string-l1-1-0api-ms-win-core-sysinfo-l1-2-1api-ms-win-core-winrt-l1-1-0api-ms-win-core-xstate-l2-1-0api-ms-win-rtcore-ntuser-window-l1-1-0api-ms-win-security-systemfunctions-l1-1-0ext-ms-win-ntuser-dialogbox-l1-1-0ext-ms-win-ntuser-windowstation-l1-1-0advapi32ntdllapi-ms-win-appmodel-runtime-l1-1-2user32ext-ms-AreFileApisANSICompareStringExEnumSystemLocalesExGetDateFormatExGetLocaleInfoExGetSystemTimePreciseAsFileTimeGetTimeFormatExGetUserDefaultLocaleNameIsValidLocaleNameLCMapStringExLCIDToLocaleNameLocaleNameToLCID RoInitialize RoUninitializeAppPolicyGetProcessTerminationMethodAppPolicyGetThreadInitializationType ((((( H   !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~ ((((( H ( 0DSPIhSTI\IdI!lI$S S,StISS H R ] i u -C Y p        % 1#INF1#QNAN1#SNAN1#INDIIIIIIȾIоI ؾI I I I IIIII I(I0I8I@IHIPIXI`IhIpIxII I!I"I#I$I%I&I'I)I*ȿI+пI,ؿI-I/I6I7I8I9I>I?I@ IA(IC0ID8IF@IGHIIPIJXIK`INhIOpIPxIVIWIZIeITIIIܨIIIII I I I  II$I0IIШII?I@IAICID4IE@IFLIGXIIdIJpIK|ILINIOIPIRIVIWIZIeIkIlII(IĨI4I @I LI XIdIpI|IIII,I;I>ICIkI I I (I 4I @I LI XI; pIk |IIII I I II;IIII I  I ,I8I;PI`I lI xI II;II I II;I I I I; (I$8I $DI $PI;$\I(lI (xI (I,I ,I ,I0I 0I 0I4I 4I 4I8I 8I<I < I@,I @8I DDI HPI L\I PhI|tI|Iarbgcazh-CHScsdadeelenesfifrhehuisitjakonlnoplptroruhrsksqsvthtruridbesletlvltfavihyazeumkafkafohimskkkyswuzttpagutateknmrsamnglkoksyrdivar-SAbg-BGca-EScs-CZda-DKde-DEel-GRfi-FIfr-FRhe-ILhu-HUis-ISit-ITnl-NLnb-NOpl-PLpt-BRro-ROru-RUhr-HRsk-SKsq-ALsv-SEth-THtr-TRur-PKid-IDuk-UAbe-BYsl-SIet-EElv-LVlt-LTfa-IRvi-VNhy-AMaz-AZ-Latneu-ESmk-MKtn-ZAxh-ZAzu-ZAaf-ZAka-GEfo-FOhi-INmt-MTse-NOms-MYkk-KZky-KGsw-KEuz-UZ-Latntt-RUbn-INpa-INgu-INta-INte-INkn-INml-INmr-INsa-INmn-MNcy-GBgl-ESkok-INsyr-SYdiv-MVquz-BOns-ZAmi-NZar-IQde-CHen-GBes-MXfr-BEit-CHnl-BEnn-NOpt-PTsr-SP-Latnsv-FIaz-AZ-Cyrlse-SEms-BNuz-UZ-Cyrlquz-ECar-EGzh-HKde-ATen-AUes-ESfr-CAsr-SP-Cyrlse-FIquz-PEar-LYzh-SGde-LUen-CAes-GTfr-CHhr-BAsmj-NOar-DZzh-MOde-LIen-NZes-CRfr-LUbs-BA-Latnsmj-SEar-MAen-IEes-PAfr-MCsr-BA-Latnsma-NOar-TNen-ZAes-DOsr-BA-Cyrlsma-SEar-OMen-JMes-VEsms-FIar-YEen-CBes-COsmn-FIar-SYen-BZes-PEar-JOen-TTes-ARar-LBen-ZWes-ECar-KWen-PHes-CLar-AEes-UYar-BHes-PYar-QAes-BOes-SVes-HNes-NIes-PRzh-CHTsrTBI,IqIIIIIIIIII(I4I@ILICXIdIpIؿI)|IIkI!IcIIDI}IIIEIIGII IHȾII$I0IItIHI7II INI/ItXIIIZI IOпI(IjIIaIIPIIIQIIRI-IrI1Ix`I:(I II?4IDIS I2PIyI%\IgI$hIftII+ImIxI=IhI;II0IIwIuIU(IIITI0II@I6I~8IIV@I(IW4I@IPI`IHIpIXPI|IYpI<IIIvI`II[I"IdIIIII IhI0I\I@@ |?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?/?/??????THO_ premake.criteria__gcfilesdatastringmatchPremake/5.0.0-beta1_OPTIONSinsecureheadersprogressuserpwdusernamepasswordtimeouttimeoutmssslverifyhostsslverifypeerproxyurlluainterrupted!%s: %s __tostring(error object is a %s value)Lua 5.3.5 Copyright (C) 1994-2018 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 filepathREG_NONEREG_SZREG_EXPAND_SZREG_BINARYREG_DWORDREG_DWORD_BIG_ENDIANREG_LINKREG_MULTI_SZREG_RESOURCE_LISTREG_FULL_RESOURCE_DESCRIPTORREG_RESOURCE_REQUIREMENTS_LISTREG_QWORDUnknowntypevalue/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'mtimesizeunable 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_is64bitisdirgetcwdgetpassgetWindowsRegistrylistWindowsRegistrygetversionhostisfileislinklocatematchdonematchisfilematchnamematchnextmatchstartmkdirremoverenamepathsearchrealpathrmdirstatuuidwritefile_ifnotequaltouchfilecompilegetEmbeddedResourceendswithhashsha1startswithnewwritewritelntostringclosegetTextColorsetTextColorgetpostdownloadextractcriteriadebugosbufferedtermhttpzip_COPYRIGHT_PREMAKE_VERSIONCopyright (C) 2002-2021 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=_ARGVI@I@I@I@IШ@I@(I@@xI@SxN ShK<%SxRSpQbSPg SpdN,SNHSsO<hSpJK S!MES8I S KES%L SKv(S?M,SHJ LSJpSPVLs SGK!SxNSBJSNSHJStS,SnO @SK9TSK9hS`L|SlK{SvPhCSx{JGSBPSJsS8kNX SO\0S8'M[DSP2Q6dS#L{S@PSJ,SN S`!SShSSwQ- S*N#$SpOb4SbSDSQTS@K%hSh!MtSH9L$S(KSKHS?MJuserdatalocal 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 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 = { VisualStudioLocal = "WindowsLocalDebugger", VisualStudioRemote = "WindowsRemoteDebugger", VisualStudioWebBrowser = "WebBrowserDebugger", VisualStudioWebService = "WebServiceDebugger" } local value = map[cfg.debugger] 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 SSSSSSSSlocal 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 local rel = path.translate(file.relpath) if prj.kind == p.SHAREDITEMS then rel = "$(MSBuildThisFileDirectory)" .. rel end if file.parent.path then p.push('<%s Include=\"%s\">', tag, rel) p.w('%s', path.translate(file.parent.path, '\\')) p.pop('', tag) else p.w('<%s Include=\"%s\" />', tag, rel) end end p.pop('') end 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.vc2013 = {} local vstudio = p.vstudio local project = p.project local config = p.config local fileconfig = p.fileconfig local tree = p.tree local m = p.vstudio.vc2013 local vc2010 = p.vstudio.vc2010 m.elements = {} m.conditionalElements = {} m.elements.project = function(prj) return { vc2010.xmlDeclaration, m.project, m.globals, m.itemDefinitionGroup, m.itemGroup, vc2010.files, } end function m.generate(prj) p.utf8() p.callArray(m.elements.project, prj) p.out('') end function m.project(prj) p.push('') end m.elements.globals = function(prj) return { m.msbuildAllProjects, m.hasSharedItems, m.itemsProjectGuid, m.itemsProjectName, } end function m.globals(prj) vc2010.propertyGroup(nil, "Globals") p.callArray(m.elements.globals, prj) p.pop('') end function m.msbuildAllProjects(prj) vc2010.element("MSBuildAllProjects", nil, "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)") end function m.hasSharedItems(prj) vc2010.element("HasSharedItems", nil, "true") end function m.itemsProjectGuid(prj) vc2010.element("ItemsProjectGuid", nil, "{%s}", prj.uuid) end function m.itemsProjectName(prj) if prj.name ~= prj.filename then vc2010.element("ItemsProjectName", nil, "%s", prj.name) end end m.elements.itemDefinitionGroup = function(prj) return { m.clCompile, } end function m.itemDefinitionGroup(prj) p.push('') p.callArray(m.elements.itemDefinitionGroup, prj) p.pop('') end m.elements.clCompile = function(prj) return { m.additionalIncludeDirectories, } end function m.clCompile(prj) p.push('') p.callArray(m.elements.clCompile, prj) p.pop('') end function m.additionalIncludeDirectories(prj) vc2010.element("AdditionalIncludeDirectories", nil, '%s', '%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)') end m.elements.itemGroup = function(prj) return { m.projectCapability, } end function m.itemGroup(prj) p.push('') p.callArray(m.elements.itemGroup, prj) p.pop('') end function m.projectCapability(prj) p.w('') end @B B`BBlocal 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 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 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", } } dShSpSxSSSlocal 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.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 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.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.escElementText(value) local result = value:gsub('&', '&') result = result:gsub('<', '<') result = result:gsub('>', '>') return result end function codelite.esc(value) local result = value:gsub('&', '&') result = result: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 p.tools.mingw = p.tools.gcc `qATPP\l<> $(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 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) DS,SSSXSlocal 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, compileas = gcc.shared.compileas } 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), clang.getsystemversionflags(cfg)) return flags end function clang.getwarnings(cfg) return gcc.getwarnings(cfg) end function clang.getsystemversionflags(cfg) local flags = {} if cfg.system == p.MACOSX or cfg.system == p.IOS then local minVersion = p.project.systemversion(cfg) if minVersion ~= nil then local name = iif(cfg.system == p.MACOSX, "macosx", "iphoneos") table.insert (flags, "-m" .. name .. "-version-min=" .. p.project.systemversion(cfg)) end end return flags 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), clang.getsystemversionflags(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, frameworkdirs) local flags = gcc.getincludedirs(cfg, dirs, sysdirs, frameworkdirs) 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 = function(cfg) return iif(cfg.flags.LinkTimeOptimization, "llvm-ar", "ar") end } function clang.gettoolname(cfg, tool) local value = clang.tools[tool] if type(value) == "function" then value = value(cfg) end return value 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", ".c++" }) 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 IpB   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.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 (prj) if dotnetbase.isNewFormatProject(prj) then return { dotnetbase.projectElement, dotnetbase.projectProperties, dotnetbase.configurations, dotnetbase.applicationIcon, dotnetbase.references } else return { dotnetbase.xmlDeclaration, dotnetbase.projectElement, dotnetbase.commonProperties, dotnetbase.projectProperties, dotnetbase.configurations, dotnetbase.applicationIcon, dotnetbase.references } end end cs2005.elements.projectProperties = function (cfg) if dotnetbase.isNewFormatProject(cfg) then return { dotnetbase.outputType, dotnetbase.appDesignerFolder, dotnetbase.rootNamespace, dotnetbase.assemblyName, dotnetbase.netcore.targetFramework, dotnetbase.allowUnsafeBlocks, dotnetbase.fileAlignment, dotnetbase.bindingRedirects, dotnetbase.netcore.useWpf, dotnetbase.csversion, dotnetbase.netcore.enableDefaultCompileItems, } else 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 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) if not dotnetbase.isNewFormatProject(prj) then local bin = iif(_ACTION <= "vs2010", "MSBuildBinPath", "MSBuildToolsPath") _p(1,'', bin) _p(1,'') end 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 p.rule.prepareEnvironment(rule, environ, cfg) p.rule.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 SSS     local 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.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 SSSTlocal 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.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 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.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 0S@SILSXShStSSSITlocal p = premake local m = p.modules.self_test local _ = {} function m.runTest(tests) local failed = 0 local failedTests = {} local suites = m.getSuites() local suitesKeys, suiteTestsKeys, totalTestCount = _.preprocessTests(suites, tests) _.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, filters) local suitesKeys = {} local suiteTestsKeys = {} local totalTestCount = 0 for i, filter in ipairs(filters) do 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 = {} test.suiteName = suiteName test.suite = suite if not table.contains(suitesKeys, suiteName) then table.insertsorted(suitesKeys, suiteName) suiteTestsKeys[suiteName] = {} end 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 if not table.contains(suiteTestsKeys[suiteName], testName) then table.insertsorted(suiteTestsKeys[suiteName], testName) totalTestCount = totalTestCount + 1 end end end end 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 local 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.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") S8Slocal 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.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('endif') p.outln('') 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 xITlocal 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) json = {} 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 local p = premake local vstudio = p.vstudio newaction { trigger = "vs2022", shortname = "Visual Studio 2022", description = "Generate Visual Studio 2022 project files", targetos = "windows", toolset = "msc-v143", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility", "SharedItems" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc", "clang" }, 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 = "Version 16", targetFramework = "4.7.2", toolsVersion = "15.0", userToolsVersion = "Current", filterToolsVersion = "4.0", } }      0123456789return { "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/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", "tools/mingw.lua", "actions/clean/_clean.lua", "_premake_init.lua", } 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.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 if prj.kind == p.SHAREDITEMS then extension = ".vcxitems" else extension = iif(_ACTION > "vs2008", ".vcxproj", ".vcproj") end 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") include("vs2013_vcxitems.lua") return p.modules.vstudio 8T8T8T8T8T8T8Tlocal 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", "SharedItems" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc", "clang" }, 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 = "Version 16", targetFramework = "4.7.2", toolsVersion = "15.0", userToolsVersion = "Current", filterToolsVersion = "4.0", } } 1.2.88T8T8T9T9T9T(9Tlocal 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" } if string.startswith(_SCRIPT_DIR, '$/') then table.insert(paths, 1, '$/' .. full) end 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 local modulePath = path.getdirectory(preloader) m._preloaded[modulePath] = include(preloader) if not m._preloaded[modulePath] 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() 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 modulePath, func in pairs(m._preloaded) do local moduleName = path.getbasename(modulePath) if not package.loaded[moduleName] and shouldLoad(func) then _SCRIPT_DIR = modulePath require(moduleName) 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 HN09T49T89T<9T@9TD9TH9TL9TP9TT9TX9T\9T*F0+FP+Fpremake.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, streams) cmd = path.normalize(cmd) streams = streams or "both" local redirection if streams == "both" then redirection = " 2>&1" elseif streams == "output" then redirection = " 2>/dev/null" elseif streams == "error" then redirection = " 2>&1 1>/dev/null" else error ('Invalid stream(s) selection. "output", "error", or "both" expected.') end local pipe = io.popen(cmd .. redirection) 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, code = builtin_remove(v) if not ok then return ok, err, code end end if #p == 0 then return nil, "Couldn't find any file matching: " .. f, 1 end elseif type(f) == "table" then for _, v in pairs(f) do local ok, err, code = os.remove(v) if not ok then return ok, err, code end end end return true end local builtin_rmdir = os.rmdir function os.rmdir(p) local dirs = os.matchdirs(p .. "/*") for _, dname in ipairs(dirs) do local ok, err = os.rmdir(dname) if not ok then return ok, err end end local files = os.matchfiles(p .. "/*") for _, fname in ipairs(files) do local ok, err = os.remove(fname) if not ok then return ok, err end end return 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, copyfile = function(v) return "cp -f " .. path.normalize(v) end, copydir = 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, copyfile = function(v) v = path.translate(path.normalize(v)) return "copy /B /Y " .. v end, copydir = function(v) v = path.translate(path.normalize(v)) return "xcopy /Q /E /Y /I " .. v 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 local 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 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 if prj.kind == p.SHAREDITEMS then local projFileModified = p.generate(prj, ".vcxitems", vstudio.vc2013.generate) if tree.hasbranches(project.getsourcetree(prj)) then if p.generate(prj, ".vcxitems.filters", vstudio.vc2010.generateFilters) == true and projFileModified == false then p.touch(prj, ".vcxitems") end end else 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 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", } }  #+3;CScsJTJTJTJTJTJTJTJTJTJTJTJTlocal 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 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 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 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 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.getTestsWithIdentifier(identifier) local suiteName, testName = m.parseTestIdentifier(identifier) if suiteName ~= nil and string.contains(suiteName, "*") then local tests = {} local pattern = string.gsub(suiteName, "*", ".*") for _suiteName, suite in pairs(_.suites) do local length = string.len(_suiteName) local start, finish = string.find(_suiteName, pattern) if start == 1 and finish == length then if testName ~= nil then if string.contains(testName, "*") then local testPattern = string.gsub(testName, "*", ".*") for _testName, test in pairs(suite) do length = string.len(_testName) start, finish = string.find(_testName, testPattern) if start == 1 and finish == length then table.insert(tests, { suiteName = _suiteName, suite = suite, testName = _testName, testFunction = test, }) end end else table.insert(tests, { suiteName = _suiteName, suite = suite, testName = testName, testFunction = suite[testName], }) end else table.insert(tests, { suiteName = _suiteName, suite = suite, testName = nil, testFunction = nil, }) end end end return tests else 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 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 (nil)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 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", [".c++"] = "Sources", [".dylib"] = "Frameworks", [".framework"] = "Frameworks", [".m"] = "Sources", [".mm"] = "Sources", [".strings"] = "Resources", [".nib"] = "Resources", [".xib"] = "Resources", [".storyboard"] = "Resources", [".icns"] = "Resources", [".s"] = "Sources", [".S"] = "Sources", [".swift"] = "Sources", [".metal"] = "Resources", } if node.isResource then return "Resources" elseif node.cfg and (node.cfg.kind == p.SHAREDLIB or node.cfg.kind == p.STATICLIB) then return "Frameworks" 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 for _,v in pairs(list) do if string.find(item, path.wildcards(v)) then return true 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.compileas == p.OBJECTIVEC then return "sourcecode.c.objc" elseif filecfg.compileas == p.OBJECTIVECPP 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", [".c++"] = "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", [".swift"] = "sourcecode.swift", [".metal"] = "sourcecode.metal", [".dylib"] = "compiled.mach-o.dylib", } return types[path.getextension(node.path)] or "text" end xcode.escapeSpecialChars = { ['\n'] = '\\n', ['\r'] = '\\r', ['\t'] = '\\t', } function xcode.escapeChar(c) return xcode.escapeSpecialChars[c] or '\\'..c end function xcode.escapeArg(value) value = value:gsub('[\'"\\\n\r\t ]', xcode.escapeChar) return value end function xcode.escapeSetting(value) value = value:gsub('["\\\n\r\t]', xcode.escapeChar) return value end function xcode.stringifySetting(value) value = value..'' if not value:match('^[%a%d_./]+$') then value = '"'..xcode.escapeSetting(value)..'"' end return value end function xcode.customStringifySetting(value) value = value..'' local test = value:match('^[%a%d_./%+]+$') if test then value = '"'..xcode.escapeSetting(value)..'"' end return value end function xcode.printSetting(level, name, value) if type(value) == 'function' then value(level, name) elseif type(value) ~= 'table' then _p(level, '%s = %s;', xcode.stringifySetting(name), xcode.stringifySetting(value)) elseif #value >= 1 then _p(level, '%s = (', xcode.stringifySetting(name)) for _, item in ipairs(value) do _p(level + 1, '%s,', xcode.stringifySetting(item)) end _p(level, ');') end end function xcode.printSettingsTable(level, settings) local keys = table.keys(settings) table.sort(keys) for _, k in ipairs(keys) do xcode.printSetting(level, k, settings[k]) end end function xcode.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.getToolSet(cfg) local default = "clang" local minOSVersion = project.systemversion(cfg) if minOSVersion ~= nil and cfg.system == p.MACOSX and p.checkVersion(minOSVersion, "<10.7") then default = "gcc" end 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 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.isdylib(fname) return (path.getextension(fname) == ".dylib") end function xcode.isframeworkordylib(fname) return xcode.isframework(fname) or xcode.isdylib(fname) 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) if node.embedid then local attrs = "" if xcode.shouldembedandsign(tr, node) then attrs = attrs .. "CodeSignOnCopy, " end if xcode.isframework(node.name) then attrs = attrs .. "RemoveHeadersOnCopy, " end if attrs ~= "" then attrs = " settings = {ATTRIBUTES = (" .. attrs .. "); };" end _p(level,'%s /* %s in Embed Libraries */ = {isa = PBXBuildFile; fileRef = %s /* %s */;%s };', node.embedid, node.name, node.id, node.name, attrs) end end end end }) if not table.isempty(settings) then _p('/* Begin PBXBuildFile section */') xcode.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;', xcode.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;', xcode.stringifySetting(node.project.xcode.projectnode.name)) _p(2,'};') end end if not table.isempty(settings) then _p('/* Begin PBXContainerItemProxy section */') xcode.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), xcode.stringifySetting(node.name), xcode.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, xcode.customStringifySetting(node.parent.name), xcode.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 elseif xcode.isdylib(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 pth = nodePath src = "" else pth = path.getrelative(tr.project.location, node.path) src = "SOURCE_ROOT" 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), xcode.stringifySetting(node.name), xcode.stringifySetting(pth), xcode.stringifySetting(src)) end end end }) if not table.isempty(settings) then _p('/* Begin PBXFileReference section */') xcode.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.embedListContains(list, node) local entryname = node.name if node.parent.project then entryname = node.parent.project.name end return table.contains(list, entryname) end function xcode.shouldembed(tr, node) if not xcode.isframeworkordylib(node.name) then return false end for _, cfg in ipairs(tr.configs) do if xcode.embedListContains(cfg.embed, node) or xcode.embedListContains(cfg.embedAndSign, node) then return true end end end function xcode.shouldembedandsign(tr, node) if not xcode.isframeworkordylib(node.name) then return false end for _, cfg in ipairs(tr.configs) do if xcode.embedListContains(cfg.embedAndSign, node) then return true end end end function xcode.PBXCopyFilesBuildPhaseForEmbedFrameworks(tr) _p('/* Begin PBXCopyFilesBuildPhase section */') _p(2,'%s /* Embed Libraries */ = {', tr.products.children[1].embedstageid) _p(3,'isa = PBXCopyFilesBuildPhase;') _p(3,'buildActionMask = 2147483647;') _p(3,'dstPath = "";') _p(3,'dstSubfolderSpec = 10;') _p(3,'files = (') tree.traverse(tr.frameworks, { onleaf = function(node) if node.embedid then _p(4,'%s /* %s in Frameworks */,', node.embedid, node.name) end end }) tree.traverse(tr.projects, { onleaf = function(node) if node.embedid then _p(4,'%s /* %s in Projects */,', node.embedid, node.parent.project.name) end end }) _p(3,');') _p(3,'name = "Embed Libraries";') _p(3,'runOnlyForDeploymentPostprocessing = 0;') _p(2,'};') _p('/* End PBXCopyFilesBuildPhase 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;', xcode.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;', xcode.stringifySetting(p)) end end _p(3,'sourceTree = "";') _p(2,'};') end end }, true) if not table.isempty(settings) then _p('/* Begin PBXGroup section */') xcode.printSettingsTable(2, settings) _p('/* End PBXGroup section */') _p('') end end 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 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) 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, xcode.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) _p(4,'%s /* Embed Libraries */,', node.embedstageid) 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;', xcode.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;', xcode.stringifySetting(p)) end end _p(3,'productName = %s;', xcode.stringifySetting(name)) if pbxTargetName == "Native" then _p(3,'productReference = %s /* %s */;', node.id, node.name) _p(3,'productType = %s;', xcode.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;', xcode.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 */') xcode.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 commands = {} for _, cfg in ipairs(tr.configs) do local cfgcmds = cfg[which] if #cfgcmds > 0 then table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. cfg.buildcfg .. '" ]; then') for i = 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;', xcode.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 if not table.indexof(inputs, v) then table.insert(inputs, v) end end for _, v in ipairs(filecfg.buildoutputs) do if not table.indexof(outputs, v) then table.insert(outputs, v) end 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",', xcode.escapeSetting(node.relpath)) for _, v in ipairs(inputs) do _p(level+2,'"%s",', xcode.escapeSetting(project.getrelative(tr.project, v))) end _p(level+1,');') _p(level+1,'name = %s;', xcode.stringifySetting('Build "' .. node.name .. '"')) _p(level+1,'outputPaths = (') for _, v in ipairs(outputs) do _p(level+2,'"%s",', xcode.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;', xcode.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 xcode.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 */') xcode.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;', xcode.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 */') xcode.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, xcode.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 else local minOSVersion = project.systemversion(cfg) if minOSVersion ~= nil then settings['MACOSX_DEPLOYMENT_TARGET'] = minOSVersion end end xcode.overrideSettings(settings, cfg.xcodebuildsettings) _p(2,'%s /* %s */ = {', cfg.xcode.targetid, cfg.buildcfg) _p(3,'isa = XCBuildConfiguration;') _p(3,'buildSettings = {') xcode.printSettingsTable(4, settings) _p(3,'};') xcode.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++0x"] = "c++11", ["C++11"] = "c++11", ["C++1y"] = "c++14", ["C++14"] = "c++14", ["C++1z"] = "c++1z", ["C++17"] = "c++1z", ["C++2a"] = "c++2a", ["C++20"] = "c++2a", ["gnu++98"] = "gnu++98", ["gnu++0x"] = "gnu++0x", ["gnu++11"] = "gnu++0x", -- Xcode project GUI uses gnu++0x, but gnu++11 also works ["gnu++1y"] = "gnu++14", ["gnu++14"] = "gnu++14", ["gnu++1z"] = "gnu++1z", ["gnu++17"] = "gnu++1z", ["gnu++2a"] = "gnu++2a", ["gnu++20"] = "gnu++2a", } 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_SwiftLanguageVersion(settings, cfg) if cfg.swiftversion then settings['SWIFT_VERSION'] = cfg.swiftversion end end function xcode.XCBuildConfiguration_Project(tr, cfg) local settings = {} local toolset = xcode.getToolSet(cfg) 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] = xcode.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['SYSTEM_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 for i,v in ipairs(cfg.syslibdirs) do cfg.syslibdirs[i] = p.project.getrelative(cfg.project, cfg.syslibdirs[i]) end settings['LIBRARY_SEARCH_PATHS'] = table.join (cfg.libdirs, cfg.syslibdirs) 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 runpathdirs = table.join (cfg.runpathdirs, config.getsiblingtargetdirs (cfg)) settings['LD_RUNPATH_SEARCH_PATHS'] = toolset.getrunpathdirs(cfg, runpathdirs, "path") 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.isframeworkordylib(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.isframeworkordylib(lib.linktarget.basename) then table.insert(flags, "-l" .. xcode.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 == "Off" then settings['WARNING_CFLAGS'] = '-w' elseif cfg.warnings == "High" then settings['WARNING_CFLAGS'] = '-Wall' elseif cfg.warnings == "Extra" then settings['WARNING_CFLAGS'] = '-Wall -Wextra' elseif cfg.warnings == "Everything" then settings['WARNING_CFLAGS'] = '-Weverything' end xcode.XCBuildConfiguration_SwiftLanguageVersion(settings, cfg) xcode.overrideSettings(settings, cfg.xcodebuildsettings) _p(2,'%s /* %s */ = {', cfg.xcode.projectid, cfg.buildcfg) _p(3,'isa = XCBuildConfiguration;') _p(3,'buildSettings = {') xcode.printSettingsTable(4, settings) _p(3,'};') xcode.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 */') xcode.printSettingsTable(0, settings) _p('/* End XCBuildConfiguration section */') _p('') end end function xcode.XCBuildConfigurationList(tr) local wks = tr.project.workspace local defaultCfgName = xcode.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 */') xcode.printSettingsTable(2, settings) _p('/* End XCConfigurationList section */') end local p = premake p.modules.raw = {} local m = p.modules.raw m.elements = {} dofile("_preload.lua") dofile("raw_action.lua") return m 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 if not p.modules.android then require ("vstudio") p.modules.android = {} if _ACTION < "vs2015" then configuration { "Android" } system "android" toolset "gcc" end include("vsandroid_vcxproj.lua") include("vsandroid_sln2005.lua") include("vsandroid_vstudio.lua") include("vsandroid_androidproj.lua") end return p.modules.android 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 return {"gmake", "vstudio", "xcode", "codelite", "gmake2", "d", "android"}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.latestTargetPlatformVersion, m.windowsTargetPlatformVersion, m.fastUpToDateCheck, m.toolsVersion, } end m.elements.globalsCondition = function(prj, cfg) return { m.windowsTargetPlatformVersion, m.xpDeprecationWarning, } 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, m.toolsVersion, } else return { m.configurationType, m.useDebugLibraries, m.useOfMfc, m.useOfAtl, m.clrSupport, m.characterSet, m.platformToolset, m.toolsVersion, 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, m.additionalCompileOptions } 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.buildStep, 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.justMyCodeDebugging, m.supportOpenMP, 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.conformanceMode, m.structMemberAlignment, m.useFullPaths, m.removeUnreferencedCodeData } 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.buildStep = function(cfg) local calls = { m.buildCommands, m.buildMessage, m.buildOutputs, m.buildInputs } return calls end function m.buildStep(cfg) if #cfg.buildCommands > 0 or #cfg.buildOutputs > 0 or #cfg.buildInputs > 0 or cfg.buildMessage then p.push('') p.callArray(m.elements.buildStep, cfg) p.pop('') end end m.elements.fxCompile = function(cfg) return { m.fxCompilePreprocessorDefinition, m.fxCompileAdditionalIncludeDirs, 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, m.assemblyDebug, } 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++", ".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.fxCompileAdditionalIncludeDirs, 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) 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 prj.kind == p.SHAREDITEMS then rel = "$(MSBuildThisFileDirectory)" .. rel end 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') local contents = p.capture(function() p.push() for _, ref in ipairs(refs) do if ref.kind == p.SHAREDITEMS then local relpath = vstudio.path(prj, vstudio.projectfile(ref)) p.x('', relpath) end end p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end local contents = p.capture(function() p.push() for _, ref in ipairs(refs) do if ref.kind ~= p.SHAREDITEMS then local relpath = vstudio.path(prj, vstudio.projectfile(ref)) p.push('', relpath) p.callArray(m.elements.projectReferences, prj, ref) p.pop('') end end p.pop() end) if #contents > 0 then p.push('') p.outln(contents) p.pop('') end end function m.additionalDependencies(cfg, explicit) local links local toolset = config.toolset(cfg) if cfg.system ~= premake.WINDOWS and 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++20") then m.element("LanguageStandard", nil, 'stdcpplatest') elseif (cfg.cppdialect == "C++latest") then m.element("LanguageStandard", nil, 'stdcpplatest') end end end function m.conformanceMode(cfg) if _ACTION >= "vs2017" then if cfg.conformancemode ~= nil then if cfg.conformancemode then m.element("ConformanceMode", nil, "true") else m.element("ConformanceMode", nil, "false") end 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.useFullPaths(cfg) if cfg.useFullPaths ~= nil then if cfg.useFullPaths then m.element("UseFullPaths", nil, "true") else m.element("UseFullPaths", nil, "false") end end end function m.removeUnreferencedCodeData(cfg) if cfg.removeUnreferencedCodeData ~= nil then if cfg.removeUnreferencedCodeData then m.element("RemoveUnreferencedCodeData", nil, "true") else m.element("RemoveUnreferencedCodeData", nil, "false") end end end function m.additionalCompileOptions(cfg, condition) local opts = cfg.buildoptions if _ACTION == "vs2015" or vstudio.isMakefile(cfg) then if (cfg.cppdialect == "C++14") then table.insert(opts, "/std:c++14") elseif (cfg.cppdialect == "C++17") then table.insert(opts, "/std:c++17") elseif (cfg.cppdialect == "C++20") 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]) elseif _ACTION >= "vs2019" and cfg.toolset and cfg.toolset == "clang" 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.buildInputs(cfg, condition) if cfg.buildinputs and #cfg.buildinputs > 0 then local inputs = project.getrelative(cfg.project, cfg.buildinputs) m.element("Inputs", condition, '%s', table.concat(inputs, ";")) 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) if #fcfg.buildcommands > 0 then local commands = os.translateCommandsAndPaths(fcfg.buildcommands, fcfg.project.basedir, fcfg.project.location) m.element("Command", condition, '%s', table.concat(commands,'\r\n')) end 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) if #fcfg.buildoutputs > 0 then local outputs = project.getrelative(fcfg.project, fcfg.buildoutputs) m.element("Outputs", condition, '%s', table.concat(outputs, ";")) end 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") elseif cfg.compileas == "Module" then m.element("CompileAs", condition, "CompileAsCppModule") elseif cfg.compileas == "ModulePartition" then m.element("CompileAs", condition, "CompileAsCppModuleInternalPartition") elseif cfg.compileas == "HeaderUnit" then m.element("CompileAs", condition, "CompileAsHeaderUnit") 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" or x == "SSE4.2" 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.assemblyDebug(cfg) if cfg.assemblydebug then m.element("AssemblyDebug", 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.justMyCodeDebugging(cfg) if _ACTION >= "vs2017" then local jmc = cfg.justmycode if jmc == "On" then m.element("SupportJustMyCode", nil, "true") elseif jmc == "Off" then m.element("SupportJustMyCode", nil, "false") end end end function m.supportOpenMP(cfg) if cfg.openmp == "On" then m.element("OpenMPSupport", nil, "true") elseif cfg.openmp == "Off" then m.element("OpenMPSupport", nil, "false") 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.toolsVersion(cfg) local version = cfg.toolsversion if _ACTION >= "vs2017" and version then m.element("VCToolsVersion", nil, version) end end function m.platformToolset(cfg) local tool, version = p.config.toolset(cfg) if not version and _ACTION >= "vs2019" and cfg.toolset == "clang" then version = "ClangCL" end 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.latestTargetPlatformVersion(prj) if _ACTION == "vs2017" then m.element("LatestTargetPlatformVersion", nil, "$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))") end end function m.windowsTargetPlatformVersion(prj, cfg) if _ACTION < "vs2015" then return end local target = cfg or prj local version = project.systemversion(target) if cfg then local prjVersion = project.systemversion(prj) if not prjVersion or version == prjVersion then return end end if version == "latest" then if _ACTION == "vs2015" then version = nil -- SDK v10 is not supported by VS2015 elseif _ACTION == "vs2017" then version = "$(LatestTargetPlatformVersion)" else version = "10.0" end end if version then m.element("WindowsTargetPlatformVersion", nil, version) end end function m.xpDeprecationWarning(prj, cfg) if cfg.toolset == "msc-v141_xp" then m.element("XPDeprecationWarning", nil, "false") end end function m.fastUpToDateCheck(prj) if prj.fastuptodate ~= nil then m.element("DisableFastUpToDateCheck", nil, iif(prj.fastuptodate, "false", "true")) 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", High = "Level4", Extra = "Level4", Everything = "EnableAllWarnings" } m.element("WarningLevel", nil, map[cfg.warnings] or "Level3") end function m.warningLevelFile(cfg, condition) local map = { Off = "TurnOffAllWarnings", High = "Level4", Extra = "Level4", Everything = "EnableAllWarnings" } 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.fxCompileAdditionalIncludeDirs(cfg, condition) if cfg.shaderincludedirs and #cfg.shaderincludedirs > 0 then local dirs = vstudio.path(cfg, cfg.shaderincludedirs) m.element('AdditionalIncludeDirectories', condition, "%s;%%(AdditionalIncludeDirectories)", table.concat(dirs, ";")) 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.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 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" } local compilerName, err = p.api.checkValue(p.fields.toolset, _OPTIONS.dc or cfg.toolset or "dmd") if err then error { msg=err } end m.visuald.element(2, "compiler", compiler[compilerName]) 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.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 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.OBJECTIVEC = "Objective-C" premake.OBJECTIVECPP = "Objective-C++" premake.ON = "On" premake.OFF = "Off" premake.POSIX = "posix" premake.PS3 = "ps3" premake.SHAREDITEMS = "SharedItems" 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 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 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 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 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") include("vs2022.lua") p.api.addAllowed("debugger", "VisualStudioLocal") p.api.addAllowed("debugger", "VisualStudioRemote") p.api.addAllowed("debugger", "VisualStudioWebBrowser") p.api.addAllowed("debugger", "VisualStudioWebService") 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 = "shaderincludedirs", scope = "config", kind = "list:directory", tokens = true, pathVars = true, } p.api.register { name = "shadertype", scope = "config", kind = "string", allowed = { "Effect", "Vertex", "Pixel", "Geometry", "Hull", "Domain", "Compute", "Mesh", "Amplification", "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", "5.1", "rootsig_1.0", "rootsig_1.1", "6.0", "6.1", "6.2", "6.3", "6.4", "6.5" } } 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 { -- DEPRECATED 2019-10-21 name = "debuggerflavor", scope = "config", kind = "string", allowed = { "Local", "Remote", "WebBrowser", "WebService" } } p.api.deprecateField("debuggerflavor", 'Use `debugger` instead.', function(value) debugger('VisualStudio' .. value) end) 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.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) or node.compileas == p.OBJECTIVEC then result = '$(CC) $(ALL_CFLAGS)' elseif p.languages.iscpp(node.compileas) or node.compileas == p.OBJECTIVECPP 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, cfg.frameworkdirs) _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, table.join(cfg.runpathdirs, config.getsiblingtargetdirs(cfg))), 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) local pch = p.tools.gcc.getpch(cfg) if pch == nil then return 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 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.buildRelativePath(prj) local prjpath = vstudio.projectfile(prj) prjpath = vstudio.path(prj.workspace, prjpath) return prjpath:gsub("$%((.-)%)", "%%%1%%") end function sln2005.projects(wks) local tr = p.workspace.grouptree(wks) tree.traverse(tr, { onleaf = function(n) local prj = n.project p.x('Project("{%s}") = "%s", "%s", "{%s}"', vstudio.tool(prj), prj.name, sln2005.buildRelativePath(prj), 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 function sln2005.sharedProjects(wks) local contents = p.capture(function () local tr = p.workspace.grouptree(wks) p.tree.traverse(tr, { onleaf = function(n) local prj = n.project if prj.kind == p.SHAREDITEMS then p.w('%s*{%s}*SharedItemsImports = %s', sln2005.buildRelativePath(prj), prj.uuid:lower(), "9") else local deps = p.project.getdependencies(prj, 'linkOnly') for _, dep in ipairs(deps) do if dep.kind == p.SHAREDITEMS then p.w('%s*{%s}*SharedItemsImports = %s', sln2005.buildRelativePath(dep), prj.uuid:lower(), "4") end end end end, }) end) if #contents > 0 then p.push('GlobalSection(SharedMSBuildProjectFiles) = preSolution') p.outln(contents) p.pop('EndGlobalSection') 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 if prj.kind == p.SHAREDITEMS then return end 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.sharedProjects, sln2005.configurationPlatforms, sln2005.properties, sln2005.nestedProjects, sln2005.extensibilityGlobals, } end function sln2005.sections(wks) p.callArray(sln2005.elements.sections, wks) 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", "SharedItems" }, 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", } } 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('') local selected = "yes" -- only one configuration should be selected for cfg in workspace.eachconfig(wks) do local cfgname = codelite.cfgname(cfg) p.push('', cfgname, selected) selected = "no" 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 newaction { trigger = "codelite", shortname = "CodeLite", description = "Generate CodeLite project files", toolset = "clang", valid_kinds = { "ConsoleApp", "WindowedApp", "Makefile", "SharedLib", "StaticLib", "Utility" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc", "clang", "msc" } }, onWorkspace = function(wks) p.modules.codelite.generateWorkspace(wks) end, onProject = function(prj) p.modules.codelite.generateProject(prj) end, onCleanWorkspace = function(wks) p.modules.codelite.cleanWorkspace(wks) end, onCleanProject = function(prj) p.modules.codelite.cleanProject(prj) end, onCleanTarget = function(prj) p.modules.codelite.cleanTarget(prj) end, } return function(cfg) return (_ACTION == "codelite") end local p = premake local api = p.api p.D = "D" api.addAllowed("language", p.D) api.addAllowed("floatingpoint", "None") api.addAllowed("flags", { "CodeCoverage", "Color", "Documentation", "GenerateHeader", "GenerateJSON", "GenerateMap", "LowMem", "Profile", "Quiet", "RetainPaths", "SymbolsLikeC", "UnitTest", "UseLDC", "ProfileGC", "StackFrame", "StackStomp", "AllInstantiate", "BetterC", "Main", "PerformSyntaxCheckOnly", "ShowCommandLine", "Verbose", "ShowTLS", "ShowGC", "IgnorePragma", "ShowDependencies", }) api.addAllowed("toolset", { "dmd", "gdc", "ldc", }) api.register { name = "boundscheck", scope = "config", kind = "string", allowed = { "Default", "Off", "On", "SafeOnly", }, } api.register { name = "compilationmodel", scope = "config", kind = "string", allowed = { "Default", "File", "Package",-- TODO: this doesn't work with gmake!! "Project", }, } api.register { name = "checkaction", scope = "config", kind = "string", allowed = { "Default", "D", "C", "Halt", "Context", }, } api.register { name = "computetargets", scope = "config", kind = "list:string", } api.register { name = "debugconstants", scope = "config", kind = "list:string", tokens = true, } api.register { name = "debuglevel", scope = "config", kind = "integer", } api.register { name = "dependenciesfile", scope = "config", kind = "path", tokens = true, } api.register { name = "deprecatedfeatures", scope = "config", kind = "string", allowed = { "Default", "Allow", "Warn", "Error", }, } 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 = "jsonfile", scope = "config", kind = "path", tokens = true, } api.register { name = "importdirs", scope = "config", kind = "list:path", tokens = true, } api.register { name = "preview", scope = "config", kind = "list:string", allowed = { "dip25", "dip1000", "dip1008", "fieldwise", "markdown", "fixAliasThis", "intpromote", "dtorfields", }, } api.register { name = "revert", scope = "config", kind = "list:string", allowed = { "dip25", "import", }, } api.register { name = "stringimportdirs", scope = "config", kind = "list:path", tokens = true, } api.register { name = "transition", scope = "config", kind = "list:string", allowed = { "field", "checkimports", "complex", "tls", "vmarkdown", }, } api.register { name = "versionconstants", scope = "config", kind = "list:string", tokens = true, } api.register { name = "versionlevel", scope = "config", kind = "integer", } 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)" }, } } return function (cfg) return (cfg.language == p.D or cfg.language == "C" or cfg.language == "C++") 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 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) 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 2.5.4.3local 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 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", Color= "-color", Documentation= "-D", FatalWarnings= "-w", GenerateHeader= "-H", GenerateJSON= "-X", GenerateMap= "-map", LowMem= "-lowmem", Profile= "-profile", Quiet= "-quiet", RetainPaths= "-op", SymbolsLikeC= "-gc", UnitTest= "-unittest", Verbose= "-v", ProfileGC= "-profile=gc", StackFrame= "-gs", StackStomp= "-gx", AllInstantiate= "-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", }, checkaction = { D = "-checkaction=D", C = "-checkaction=C", Halt = "-checkaction=halt", Context = "-checkaction=context", }, cppdialect = { ["C++latest"] = "-extern-std=c++20", -- TODO: keep this up to date >_< ["C++98"] = "-extern-std=c++98", ["C++0x"] = "-extern-std=c++11", ["C++11"] = "-extern-std=c++11", ["C++1y"] = "-extern-std=c++14", ["C++14"] = "-extern-std=c++14", ["C++1z"] = "-extern-std=c++17", ["C++17"] = "-extern-std=c++17", ["C++2a"] = "-extern-std=c++20", ["C++20"] = "-extern-std=c++20", ["gnu++98"] = "-extern-std=c++98", ["gnu++0x"] = "-extern-std=c++11", ["gnu++11"] = "-extern-std=c++11", ["gnu++1y"] = "-extern-std=c++14", ["gnu++14"] = "-extern-std=c++14", ["gnu++1z"] = "-extern-std=c++17", ["gnu++17"] = "-extern-std=c++17", ["gnu++2a"] = "-extern-std=c++20", ["gnu++20"] = "-extern-std=c++20", }, 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", }, symbols = { On = "-g", FastLink = "-g", Full = "-g", }, vectorextensions = { AVX = "-mcpu=avx", AVX2 = "-mcpu=avx2", }, warnings = { Default = "-wi", High = "-wi", Extra = "-wi", Everything = "-wi", }, } 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 if #cfg.preview > 0 then for _, opt in ipairs(cfg.preview) do table.insert(flags, "-preview=" .. opt) end end if #cfg.revert > 0 then for _, opt in ipairs(cfg.revert) do table.insert(flags, "-revert=" .. opt) end end if #cfg.transition > 0 then for _, opt in ipairs(cfg.transition) do table.insert(flags, "-transition=" .. opt) 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 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 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 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 f.sequence == 0 then break end local lowerobj = f.objname:lower() if not bases[lowerobj] then bases[lowerobj] = {} end if not bases[lowerobj][cfg] then bases[lowerobj][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 local lowerbase = file.basename:lower() if not bases[lowerbase] then bases[lowerbase] = {} end local sequences = bases[lowerbase] 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 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 error(mod, 3) 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 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", "SharedItems" }, 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 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 = {} dotnetbase.netcore = {} 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) if dotnetbase.isNewFormatProject(prj) then if prj.flags.WPF then _p('') else _p('') end else local ver = '' local action = p.action.current() if action.vstudio.toolsVersion then ver = string.format(' ToolsVersion="%s"', action.vstudio.toolsVersion) end _p('', ver) end 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 and info.action ~= "EmbeddedResource" 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 not dotnetbase.isNewFormatProject(cfg) then dotnetbase.allowUnsafeBlocks(cfg) 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 _ACTION >= "vs2019" then if cfg.symbols == "Full" then _p(2,'full') _p(2,'true') elseif cfg.symbols == p.OFF then _p(2,'none') _p(2,'false') elseif cfg.symbols == p.ON or cfg.symbols == "FastLink" then _p(2,'pdbonly') _p(2,'true') else _p(2,'portable') _p(2,'true') end else if cfg.symbols == p.ON then _p(2,'true') _p(2,'full') else _p(2,'pdbonly') end 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" and not dotnetbase.isNewFormatProject(cfg) then _x(2,'%s\\', objdir) _p(2,'$(BaseIntermediateOutputPath)') else _x(2,'%s\\', objdir) end end dotnetbase.elements.references = function(cfg) return { dotnetbase.assemblyReferences, dotnetbase.nuGetReferences, } end function dotnetbase.references(prj) for cfg in project.eachconfig(prj) do _p(1,'', dotnetbase.condition(cfg)) p.callArray(dotnetbase.elements.references, cfg) _p(1,'') end end function dotnetbase.assemblyReferences(cfg) local prj = cfg.project 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(cfg) local prj = cfg.project 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 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) if not dotnetbase.isNewFormatProject(prj) then _p(1,'') end local deps = project.getdependencies(prj, 'linkOnly') if #deps > 0 then if dotnetbase.isNewFormatProject(prj) then _p(1,'') end 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 if dotnetbase.isNewFormatProject(prj) then _p(1,'') end end if not dotnetbase.isNewFormatProject(prj) then _p(1,'') end 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) if not dotnetbase.isNewFormatProject(cfg) then _p(2,'%s', cfg.buildtarget.basename) end 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" and not dotnetbase.isNewFormatProject(cfg) then _p(2,'512') end end function dotnetbase.bindingRedirects(cfg) if _ACTION >= "vs2015" and not dotnetbase.isNewFormatProject(cfg) 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) if not dotnetbase.isNewFormatProject(cfg) or cfg.namespace then _p(2,'%s', cfg.namespace or cfg.buildtarget.basename) end 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 and not dotnetbase.isNewFormatProject(cfg) 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 function dotnetbase.isNewFormatProject(cfg) local framework = cfg.dotnetframework if not framework then return false end if framework:find('^net') ~= nil then return true end return false end function dotnetbase.netcore.targetFramework(cfg) local action = p.action.current() local framework = cfg.dotnetframework or action.vstudio.targetFramework if framework and dotnetbase.isNewFormatProject(cfg) then _p(2,'%s', framework) end end function dotnetbase.netcore.enableDefaultCompileItems(cfg) _p(2,'%s', iif(cfg.enableDefaultCompileItems, "true", "false")) end function dotnetbase.netcore.useWpf(cfg) if cfg.flags.WPF then _p(2,'true') end end function dotnetbase.allowUnsafeBlocks(cfg) if cfg.clr == "Unsafe" then _p(2,'true') end endlocal 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", } } p.api.register { name = "embed", scope = "config", kind = "list", } p.api.register { name = "embedAndSign", scope = "config", kind = "list", } 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 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.msc = {} local msc = p.tools.msc local project = p.project local config = p.config function msc.getcppflags(cfg) return {} end local function getRuntimeFlag(cfg, isstatic) local rt = cfg.runtime local flag = iif(isstatic, "/MT", "/MD") if (rt == "Debug") or (rt == nil and config.isDebugBuild(cfg)) then flag = flag .. "d" end return flag end msc.shared = { clr = { On = "/clr", Unsafe = "/clr", Pure = "/clr:pure", Safe = "/clr:safe", }, flags = { FatalCompileWarnings = "/WX", LinkTimeOptimization = "/GL", 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", ["SSE4.2"] = "/arch:SSE2", }, warnings = { Off = "/W0", High = "/W4", Extra = "/W4", Everything = "/Wall", }, staticruntime = { _ = function(cfg) return getRuntimeFlag(cfg, false) end, Default = function(cfg) return getRuntimeFlag(cfg, false) end, On = function(cfg) return getRuntimeFlag(cfg, true) end, Off = function(cfg) return getRuntimeFlag(cfg, false) end, }, stringpooling = { On = "/GF", Off = "/GF-", }, symbols = { On = "/Z7" }, unsignedchar = { On = "/J", }, omitframepointer = { On = "/Oy" }, justmycode = { On = "/JMC", Off = "/JMC-" }, openmp = { On = "/openmp", Off = "/openmp-" } } 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, frameworkdirs) 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 = "/LTCG", NoIncrementalLink = "/INCREMENTAL:NO", NoManifest = "/MANIFEST:NO", OmitDefaultLibrary = "/NODEFAULTLIB", }, kind = { SharedLib = "/DLL", WindowedApp = "/SUBSYSTEM:WINDOWS" }, 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 _, enable in ipairs(cfg.enablewarnings) do table.insert(result, '/w1"' .. enable .. '"') end 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 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.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 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) 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 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.createEnvironment(self, format) local environ = {} for _, def in ipairs(self.propertydefinition) do environ[def.name] = string.format(format, def.name) end 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 rule.prepareEnvironment(self, environ, cfg) local function 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 local function expandRuleString(prop, value) if type(value) == "table" then if #value > 0 then local switch = prop.switch or "" if prop.separator then return switch .. table.concat(value, prop.separator) else return switch .. table.concat(value, " " .. switch) 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 if prop.values then local switch = prop.switch or {} value = table.findKeyByValue(prop.values, value) if value == nil then return nil end return switch[value] end local switch = prop.switch or "" value = tostring(value) if #value > 0 then return switch .. value else return nil end end for _, prop in ipairs(self.propertydefinition) do local fld = p.rule.getPropertyField(self, prop) local value = cfg[fld.name] if value ~= nil then if fld.kind == "path" then value = path(cfg, value) elseif fld.kind == "list:path" then value = path(cfg, value) end value = expandRuleString(prop, value) if value ~= nil and #value > 0 then environ[prop.name] = p.esc(value) end end end 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.getsiblingtargetdirs(cfg) local paths = {} for _, sibling in ipairs(config.getlinks(cfg, "siblings", "object")) do if (sibling.kind == p.SHAREDLIB) then local p = sibling.linktarget.directory if not (table.contains(paths, p)) then table.insert(paths, p) end end end return paths 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 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 tests = {} local isAction = true for i, arg in ipairs(_ARGS) do local _tests, err = m.getTestsWithIdentifier(arg) if err then error(err, 0) end tests = table.join(tests, _tests) end if #tests == 0 or _OPTIONS["test-only"] ~= nil then local _tests, err = m.getTestsWithIdentifier(_OPTIONS["test-only"]) if err then error(err, 0) end tests = table.join(tests, _tests) end local passed, failed = m.runTest(tests) 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 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 local generatedKind = "GENERATED" local generatedFileset = cfg._gmake.filesets[generatedKind] or {} table.insert(generatedFileset, filename) cfg._gmake.filesets[generatedKind] = generatedFileset 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 p.rule.prepareEnvironment(rule, environ, cfg) p.rule.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) local pch = p.tools.gcc.getpch(cfg) if pch == nil then return 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, cfg.frameworkdirs) 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, table.join(cfg.runpathdirs, config.getsiblingtargetdirs(cfg))), 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 or fcfg.frameworkdirs then local includes = toolset.getincludedirs(cfg, fcfg.includedirs, fcfg.sysincludedirs, fcfg.frameworkdirs) 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 $(GENERATED)') _p('\t$(SILENT) rm -rf $(OBJDIR)') _p('else') _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') _p('\t$(SILENT) if exist $(subst /,\\\\,$(GENERATED)) rmdir /s /q $(subst /,\\\\,$(GENERATED))') _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 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) local compileAs if filecfg then if filecfg.compileas then compileAs = iif(p.languages.iscpp(filecfg.compileas), 2, 1) elseif path.iscfile(filecfg.name) ~= c then if path.iscppfile(filecfg.name) then compileAs = iif(c, 2, 1) end end else if toolset then compileAs = "0" elseif c then compileAs = "1" end end if compileAs then p.w('CompileAs="%s"', compileAs) 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 == "High" then level = "4" 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 local 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.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.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) if _ACTION >= "vs2019" then vc2010.element("MinimumVisualStudioVersion", nil, "16.0") elseif _ACTION >= "vs2017" then vc2010.element("MinimumVisualStudioVersion", nil, "15.0") elseif _ACTION >= "vs2015" then vc2010.element("MinimumVisualStudioVersion", nil, "14.0") end 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", ["gnu"] = "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 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.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", } } term.black = 0 term.blue = 1 term.green = 2 term.cyan = 3 term.red = 4 term.purple = 5 term.brown = 6 term.lightGray = 7 term.gray = 8 term.lightBlue = 9 term.lightGreen = 10 term.lightCyan = 11 term.lightRed = 12 term.magenta = 13 term.yellow = 14 term.white = 15 term.warningColor = term.magenta term.errorColor = term.lightRed term.infoColor = term.lightCyan term._colorStack = {} function term.pushColor(color) local old = term.getTextColor() table.insert(term._colorStack, old) term.setTextColor(color) end function term.popColor() if #term._colorStack > 0 then local color = table.remove(term._colorStack) term.setTextColor(color) end end local p = premake require ("vstudio") p.modules.d.vc2010 = {} local vc2010 = p.vstudio.vc2010 local m = p.modules.d.vc2010 m.elements = {} local vstudio = p.vstudio local vc2010 = p.vstudio.vc2010 local config = p.config p.override(vc2010.elements, "configurationProperties", function(oldfn, cfg) local items = oldfn(cfg) if cfg.kind ~= p.UTILITY then table.insert(items, m.dCompiler) end return items end) function m.dCompiler(cfg) local dc = nil if _OPTIONS.dc then local dcMap = { ["dmd"] = "DMD", ["ldc"] = "LDC", } dc = dcMap[_OPTIONS.dc] end if cfg.flags.UseLDC then dc = "LDC" end if dc then if cfg.kind == p.NONE or cfg.kind == p.MAKEFILE then if p.config.hasFile(cfg, path.isdfile) or _ACTION >= "vs2015" then vc2010.element("DCompiler", nil, dc) end else vc2010.element("DCompiler", nil, dc) end end end p.override(vc2010.elements, "itemDefinitionGroup", function(oldfn, cfg) local items = oldfn(cfg) if cfg.kind ~= p.UTILITY then table.insertafter(items, vc2010.clCompile, m.dCompile) end return items end) m.elements.dCompile = function(cfg) return { m.dOptimization, m.dImportPaths, m.dStringImportPaths, m.dVersionConstants, m.dDebugConstants, m.dCompilationModel, m.dPreserveSourcePath, m.dRuntime, m.dCodeGeneration, m.dLanguage, m.dMessages, m.dDocumentation, m.dAdditionalCompileOptions, } end function m.dCompile(cfg) if config.hasFile(cfg, path.isdfile) then p.push('') 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.dPreserveSourcePath, m.dRuntime, m.dCodeGeneration, m.dLanguage, m.dMessages, m.dDocumentation, m.dAdditionalCompileOptions, } 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="false", 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.dPreserveSourcePath(cfg, condition) if cfg.flags.RetainPaths then vc2010.element("PreserveSourcePath", condition, "true") 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.flags.Profile then vc2010.element("Profile", condition, "true") end if cfg.flags.ProfileGC then vc2010.element("ProfileGC", 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 and cfg.inlining ~= "Default" then local types = { Disabled = "false", Explicit = "true", Auto = "true", } vc2010.element("Inliner", condition, types[cfg.inlining]) 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.AllInstantiate then vc2010.element("AllInst", condition, "true") end if cfg.flags.Main then vc2010.element("Main", condition, "true") end if _OPTIONS.dc ~= "ldc" and not cfg.flags.UseLDC then if cfg.vectorextensions then local vextMap = { AVX = "avx", AVX2 = "avx2", } if vextMap[cfg.vectorextensions] ~= nil then vc2010.element("CPUArchitecture", condition, vextMap[cfg.vectorextensions]) end end end if config.isDebugBuild(cfg) then vc2010.element("DebugCode", condition, "Debug") else vc2010.element("DebugCode", condition, "Release") 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.boundscheck and cfg.boundscheck ~= "Default" then local types = { Off = "Off", SafeOnly = "SafeOnly", On = "On", } vc2010.element("BoundsCheck", condition, types[cfg.boundscheck]) end if cfg.flags.PerformSyntaxCheckOnly then vc2010.element("PerformSyntaxCheckOnly", condition, "true") end end function m.dLanguage(cfg, condition) if cfg.flags.BetterC then vc2010.element("BetterC", condition, "true") end if #cfg.preview > 0 then for _, opt in ipairs(cfg.preview) do if opt == "dip25" then vc2010.element("DIP25", condition, "true") elseif opt == "dip1000" then vc2010.element("DIP1000", condition, "true") elseif opt == "dip1008" then vc2010.element("DIP1008", condition, "true") elseif opt == "fieldwise" then vc2010.element("PreviewFieldwise", condition, "true") elseif opt == "dtorfields" then vc2010.element("PreviewDtorFields", condition, "true") elseif opt == "intpromote" then vc2010.element("PreviewIntPromote", condition, "true") elseif opt == "fixAliasThis" then vc2010.element("PreviewFixAliasThis", condition, "true") end end end if #cfg.revert > 0 then for _, opt in ipairs(cfg.revert) do if opt == "import" then vc2010.element("RevertImport", condition, "true") end end 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 if #cfg.transition > 0 then for _, opt in ipairs(cfg.transition) do if opt == "field" then vc2010.element("TransitionField", condition, "true") elseif opt == "checkimports" then vc2010.element("TransitionCheckImports", condition, "true") elseif opt == "complex" then vc2010.element("TransitionComplex", condition, "true") end end 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.preview > 0 then for _, opt in ipairs(cfg.preview) do if opt == "markdown" then vc2010.element("PreviewMarkdown", condition, "true") end end end if #cfg.transition > 0 then for _, opt in ipairs(cfg.transition) do if opt == "vmarkdown" then vc2010.element("TransitionVMarkdown", condition, "true") end end 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 function m.dAdditionalCompileOptions(cfg, condition) local opts = cfg.buildoptions if cfg.flags.LowMem then table.insert(opts, "-lowmem") end if cfg.cppdialect and cfg.cppdialect ~= "Default" then local cppMap = { ["C++latest"] = "c++20", ["C++98"] = "c++98", ["C++0x"] = "c++11", ["C++11"] = "c++11", ["C++1y"] = "c++14", ["C++14"] = "c++14", ["C++1z"] = "c++17", ["C++17"] = "c++17", ["C++2a"] = "c++20", ["C++20"] = "c++20", ["gnu++98"] = "c++98", ["gnu++0x"] = "c++11", ["gnu++11"] = "c++11", ["gnu++1y"] = "c++14", ["gnu++14"] = "c++14", ["gnu++1z"] = "c++17", ["gnu++17"] = "c++17", ["gnu++2a"] = "c++20", ["gnu++20"] = "c++20", } if cppMap[cfg.cppdialect] ~= nil then table.insert(opts, "-extern-std=" .. cppMap[cfg.cppdialect]) end end if _OPTIONS.dc == "ldc" or cfg.flags.UseLDC then if cfg.vectorextensions then local vextMap = { AVX = "avx", AVX2 = "avx2", SSE = "sse", SSE2 = "sse2", SSE3 = "sse3", SSSE3 = "ssse3", ["SSE4.1"] = "sse4.1", ["SSE4.2"] = "sse4.2", } if vextMap[cfg.vectorextensions] ~= nil then table.insert(opts, "-mattr=+" .. vextMap[cfg.vectorextensions]) end end if #cfg.isaextensions > 0 then local isaMap = { MOVBE = "movbe", POPCNT = "popcnt", PCLMUL = "pclmul", LZCNT = "lzcnt", BMI = "bmi", BMI2 = "bmi2", F16C = "f16c", AES = "aes", FMA = "fma", FMA4 = "fma4", RDRND = "rdrnd", } for _, ext in ipairs(cfg.isaextensions) do if isaMap[ext] ~= nil then table.insert(opts, "-mattr=+" .. isaMap[ext]) end end end if #cfg.computetargets > 0 then table.insert(opts, "-mdcompute-targets=" .. table.concat(cfg.computetargets, ',')) end end if #opts > 0 then opts = table.concat(opts, " ") vc2010.element("AdditionalOptions", condition, '%s %%(AdditionalOptions)', opts) end end premake.clean = {} newaction { trigger = "clean", description = "Remove all binaries and generated files", execute = function() print("** The clean action has not yet been ported") end } function 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 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.isframeworkordylib(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) if xcode.shouldembed(tr, node) then node.embedid = xcode.newid(node.name, "embed", nodepath) end 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") node.embedstageid = xcode.newid(node.name, "embed") 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.PBXCopyFilesBuildPhaseForEmbedFrameworks(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 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 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 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 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", ARM = "-march=arm", ARM64 = "-march=aarch64", }, flags = { OmitDefaultLibrary= "-mscrtlib=", CodeCoverage= "-cov", Color= "-enable-color", Documentation= "-D", FatalWarnings= "-w", -- Use LLVM flag? : "-fatal-assembler-warnings", GenerateHeader= "-H", GenerateJSON= "-X", LowMem= "-lowmem", RetainPaths= "-op", SymbolsLikeC= "-gc", UnitTest= "-unittest", Verbose= "-v", AllInstantiate= "-allinst", BetterC= "-betterC", Main= "-main", PerformSyntaxCheckOnly= "-o-", ShowGC= "-vgc", IgnorePragma= "-ignore", }, boundscheck = { Off = "-boundscheck=off", On = "-boundscheck=on", SafeOnly = "-boundscheck=safeonly", }, checkaction = { D = "-checkaction=D", C = "-checkaction=C", Halt = "-checkaction=halt", Context = "-checkaction=context", }, cppdialect = { ["C++latest"] = "-extern-std=c++17", -- TODO: keep this up to date >_< ["C++98"] = "-extern-std=c++98", ["C++0x"] = "-extern-std=c++11", ["C++11"] = "-extern-std=c++11", ["C++1y"] = "-extern-std=c++14", ["C++14"] = "-extern-std=c++14", ["C++1z"] = "-extern-std=c++17", ["C++17"] = "-extern-std=c++17", ["C++2a"] = "-extern-std=c++20", ["C++20"] = "-extern-std=c++20", ["gnu++98"] = "-extern-std=c++98", ["gnu++0x"] = "-extern-std=c++11", ["gnu++11"] = "-extern-std=c++11", ["gnu++1y"] = "-extern-std=c++14", ["gnu++14"] = "-extern-std=c++14", ["gnu++1z"] = "-extern-std=c++17", ["gnu++17"] = "-extern-std=c++17", ["gnu++2a"] = "-extern-std=c++20", ["gnu++20"] = "-extern-std=c++20", }, 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", AVX2 = "-mattr=+avx2", SSE = "-mattr=+sse", SSE2 = "-mattr=+sse2", SSE3 = "-mattr=+sse3", SSSE3 = "-mattr=+ssse3", ["SSE4.1"] = "-mattr=+sse4.1", ["SSE4.2"] = "-mattr=+sse4.2", }, warnings = { Default = "-wi", High = "-wi", Extra = "-wi",-- TODO: is there a way to get extra warnings? Everything = "-wi", }, 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 if #cfg.computetargets > 0 then table.insert(flags, "-mdcompute-targets=" .. table.concat(cfg.computetargets, ',')) end if #cfg.isaextensions > 0 then local isaMap = { MOVBE = "movbe", POPCNT = "popcnt", PCLMUL = "pclmul", LZCNT = "lzcnt", BMI = "bmi", BMI2 = "bmi2", F16C = "f16c", AES = "aes", FMA = "fma", FMA4 = "fma4", RDRND = "rdrnd", } for _, ext in ipairs(cfg.transition) do if isaMap[ext] ~= nil then table.insert(flags, "-mattr=+" .. isaMap[ext]) end end end if #cfg.preview > 0 then for _, opt in ipairs(cfg.preview) do table.insert(flags, "-preview=" .. opt) end end if #cfg.revert > 0 then for _, opt in ipairs(cfg.revert) do table.insert(flags, "-revert=" .. opt) end end if #cfg.transition > 0 then for _, opt in ipairs(cfg.transition) do table.insert(flags, "-transition=" .. opt) 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 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.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 local 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", "NetCore", } } api.register { name = "compilebuildoutputs", scope = "config", kind = "boolean" } api.register { name = "compileas", scope = "config", kind = "string", allowed = { "Default", "C", "C++", "Objective-C", "Objective-C++", "Module", "ModulePartition", "HeaderUnit" } } 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 = "fastuptodate", scope = "project", kind = "boolean", } 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 = "enabledefaultcompileitems", scope = "config", kind = "boolean", default = false } 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", "SharedItems", }, } 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", "C++2a", "C++20", "gnu++98", "gnu++0x", "gnu++11", "gnu++1y", "gnu++14", "gnu++1z", "gnu++17", "gnu++2a", "gnu++20", } } api.register { name = "conformancemode", scope = "config", kind = "boolean" } api.register { name = "usefullpaths", scope = "config", kind = "boolean" } api.register { name = "removeunreferencedcodedata", scope = "config", kind = "boolean" } api.register { name = "swiftversion", scope = "config", kind = "string", allowed = { "4.0", "4.2", "5.0", } } 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 = "toolsversion", scope = "project", kind = "string", tokens = true, } 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", "SSE4.2", } } 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", "Everything", } } 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.register { name = "assemblydebug", scope = "config", kind = "boolean" } api.register { name = "justmycode", scope = "project", kind = "string", allowed = { "On", "Off" } } api.register { name = "openmp", scope = "project", kind = "string", allowed = { "On", "Off" } } 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++)" }, { "mingw", "MinGW 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 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 sysincludedirs = toolset.getincludedirs(cfg, {}, cfg.sysincludedirs, cfg.frameworkdirs) local forceincludes = toolset.getforceincludes(cfg) local cxxflags = table.concat(table.join(sysincludedirs, toolset.getcxxflags(cfg), forceincludes, cfg.buildoptions), ";") local cflags = table.concat(table.join(sysincludedirs, toolset.getcflags(cfg), forceincludes, cfg.buildoptions), ";") local asmflags = "" local pch = p.tools.gcc.getpch(cfg) local usepch = "yes" if pch == nil then pch = ""; usepch = "no" end _x(3, '', cxxflags, cflags, asmflags, pch, usepch) for _, includedir in ipairs(cfg.includedirs) do _x(4, '', project.getrelative(cfg.project, includedir)) end for _, define in ipairs(cfg.defines) do _p(4, '', p.esc(define):gsub(' ', '\\ ')) 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), toolset.getincludedirs(cfg, {}, nil, cfg.frameworkdirs), toolset.getrunpathdirs(cfg, table.join(cfg.runpathdirs, config.getsiblingtargetdirs(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.sysincludedirs, 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") _x(3, '', targetname, objdir, command, cmdargs, useseparatedebugargs, debugargs, workingdir, pauseexec, isguiprogram, isenabled) end function m.environment(cfg) local envs = table.concat(cfg.debugenvs, "\n") _p(3, '') _p(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.escaper(codelite.escElementText) _p(4, '%s', table.concat(p.esc(project.getrelative(cfg.project, cfg.debugsearchpaths)), "\n")) p.escaper(codelite.esc) else _p(4, '') end if #cfg.debugconnectcommands > 0 then p.escaper(codelite.escElementText) _p(4, '%s', table.concat(p.esc(cfg.debugconnectcommands), "\n")) p.escaper(codelite.esc) else _p(4, '') end if #cfg.debugstartupcommands > 0 then p.escaper(codelite.escElementText) _p(4, '%s', table.concat(p.esc(cfg.debugstartupcommands), "\n")) p.escaper(codelite.esc) else _p(4, '') end _p(3, '') end function m.preBuild(cfg) if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then _p(3, '') p.escaper(codelite.escElementText) if cfg.prebuildmessage then local command = os.translateCommandsAndPaths("@{ECHO} " .. cfg.prebuildmessage, cfg.project.basedir, cfg.project.location) _x(4, '%s', command) end local commands = os.translateCommandsAndPaths(cfg.prebuildcommands, cfg.project.basedir, cfg.project.location) for _, command in ipairs(commands) do _x(4, '%s', command) end p.escaper(codelite.esc) _p(3, '') end end function m.postBuild(cfg) if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then _p(3, '') p.escaper(codelite.escElementText) if cfg.postbuildmessage then local command = os.translateCommandsAndPaths("@{ECHO} " .. cfg.postbuildmessage, cfg.project.basedir, cfg.project.location) _x(4, '%s', command) end local commands = os.translateCommandsAndPaths(cfg.postbuildcommands, cfg.project.basedir, cfg.project.location) for _, command in ipairs(commands) do _x(4, '%s', command) end p.escaper(codelite.esc) _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, '') local dependencies = {} local makefilerules = {} local function addrule(dependencies, makefilerules, config, filename) if #config.buildcommands == 0 or #config.buildOutputs == 0 then return false end local inputs = table.implode(project.getrelative(cfg.project, config.buildInputs), "", "", " ") if filename ~= "" and inputs ~= "" then filename = filename .. " " end local outputs = project.getrelative(cfg.project, config.buildOutputs[1]) local buildmessage = "" if config.buildmessage then buildmessage = "\t@{ECHO} " .. config.buildmessage .. "\n" end local commands = table.implode(config.buildCommands,"\t","\n","") table.insert(makefilerules, os.translateCommandsAndPaths(outputs .. ": " .. filename .. inputs .. "\n" .. buildmessage .. commands, cfg.project.basedir, cfg.project.location)) table.insertflat(dependencies, outputs) return true end local tr = project.getsourcetree(cfg.project) p.tree.traverse(tr, { onleaf = function(node, depth) local filecfg = p.fileconfig.getconfig(node, cfg) local prj = cfg.project local rule = p.global.getRuleForFile(node.name, prj.rules) if not addrule(dependencies, makefilerules, filecfg, node.relpath) and rule then local environ = table.shallowcopy(filecfg.environ) if rule.propertydefinition then p.rule.prepareEnvironment(rule, environ, cfg) p.rule.prepareEnvironment(rule, environ, filecfg) end local rulecfg = p.context.extent(rule, environ) addrule(dependencies, makefilerules, rulecfg, node.relpath) end end }) addrule(dependencies, makefilerules, cfg, "") if #makefilerules == 0 and #dependencies == 0 then _p(4, '') else _p(4, '' .. table.implode(dependencies,"",""," ")) _p(0, table.implode(makefilerules,"","","\n") .. '') end _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 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 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.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", ["SSE4.2"] = "-msse4.2", }, isaextensions = { MOVBE = "-mmovbe", POPCNT = "-mpopcnt", PCLMUL = "-mpclmul", LZCNT = "-mlzcnt", BMI = "-mbmi", BMI2 = "-mbmi2", F16C = "-mf16c", AES = "-maes", FMA = "-mfma", FMA4 = "-mfma4", RDRND = "-mrdrnd", }, warnings = { Off = "-w", High = "-Wall", Extra = {"-Wall", "-Wextra"}, Everything = "-Weverything", }, 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" }, compileas = { ["Objective-C"] = "-x objective-c", ["Objective-C++"] = "-x objective-c++", } } 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, gcc.getsystemversionflags(cfg)) 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 function gcc.getsystemversionflags(cfg) local flags = {} if cfg.system == p.MACOSX then local minVersion = p.project.systemversion(cfg) if minVersion ~= nil then table.insert (flags, "-mmacosx-version-min=" .. minVersion) end end return flags 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", ["C++2a"] = "-std=c++2a", ["C++20"] = "-std=c++20", ["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", ["gnu++2a"] = "-std=gnu++2a", ["gnu++20"] = "-std=gnu++20", ["C++latest"] = "-std=c++20", }, 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), gcc.getsystemversionflags(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, frameworkdirs) local result = {} for _, dir in ipairs(dirs) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-I' .. p.quoted(dir)) end if table.contains(os.getSystemTags(cfg.system), "darwin") then for _, dir in ipairs(frameworkdirs or {}) do dir = project.getrelative(cfg.project, dir) table.insert(result, '-F' .. p.quoted(dir)) end 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.getpch(cfg) if not cfg.pchheader or cfg.flags.NoPCH then return nil end local pch = cfg.pchheader local found = false local testname = path.join(cfg.project.basedir, pch) if os.isfile(testname) then return project.getrelative(cfg.project, testname) else for _, incdir in ipairs(cfg.includedirs) do testname = path.join(incdir, pch) if os.isfile(testname) then return project.getrelative(cfg.project, testname) end end end return project.getrelative(cfg.project, path.getabsolute(pch)) end function gcc.getrunpathdirs(cfg, dirs, mode) local result = {} mode = iif (mode == nil, "linker", mode) if not (table.contains(os.getSystemTags(cfg.system), "darwin") or (cfg.system == p.LINUX)) then return result end for _, fullpath in ipairs(dirs) do local rpath = path.getrelative(cfg.buildtarget.directory, fullpath) 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 if mode == "linker" then rpath = "-Wl,-rpath,'" .. rpath .. "'" end table.insert(result, 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 table.contains(os.getSystemTags(cfg.system), "darwin") then for _, dir in ipairs(cfg.frameworkdirs) do dir = project.getrelative(cfg.project, dir) table.insert(flags, '-F' .. p.quoted(dir)) end 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 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) 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 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 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 = m.make.getToolset(cfg) 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.getToolset(cfg) local toolset, err = p.api.checkValue(p.fields.toolset, _OPTIONS.dc or cfg.toolset or "dmd") if err then error { msg=err } end return p.tools[toolset] 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 local 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 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 type(field.allowed) == "function" then field.allowed = { field.allowed } end 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 for _, allow in ipairs(field.allowed) do if type(allow) == "function" then canonical = allow(value, kind or "string") end if canonical then break end 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) premake.warnOnce("configuration", "`configuration` has been deprecated; use `filter` instead (https://premake.github.io/docs/Filters/)") 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 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", Everything = "-Weverything", }, 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 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", "SharedItems" }, 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", } } p@SpAS BSpBSASЙB`I(BIfBS@{B$SBXIBSSISSSSSSSSSS SSS$S,S4S?@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  @C@C@C @CPC PCPC PC PC PC@@ !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#cVE* < > { } { } t T0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz%T{EEБEE0EP%T{EEБEEPEE0EGMTUTCWETBSTWAT<ASTADTEST,EDTCSThCDT,MSTMDThPSTPDTYSTYDTHSTXHDTCATXAHSTXNTIDLWCETMETMEWTMESTCESTMESZFWTFSTEETWAST\WADT CCT JSTEASTEADTlGSTNZT0NZST0NZDTIDLE0A<BxCDE,FhGHIKXLMNOPLQRST\U VWXlY0ZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_QTQTQTQTQTRTRT(RT4RTHRTXRTlRT|RTRTRTRTRTRTSTST4STLSTXSTpSTSTSTSTSTSTTTTT,TT0TTDTTHTTIOXTT\TTdTThTTpTTTTSTTTTTTTTTTTTTTTTTTTTTTTTTTxITTUTUTSUT(UT4UT@UTLUTXUTlUTxUTUTUTUTUTUTUTUTUT%LUT VTVT(VT4VTHVT`VThVTVTVTVTVTVTsrc/_premake_main.lua0123456789ABCDEF1CLICOLOR0CLICOLOR_FORCEError creating file: %s %s does not exist %s/%s Failed to create symbolic link [%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/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/tools/mingw.luasrc/actions/clean/_clean.luasrc/_premake_init.luaxcode/_preload.luaxcode/xcode.luaxcode/xcode4_workspace.luaxcode/xcode_common.luaxcode/xcode_project.luacodelite/_preload.luacodelite/codelite.luacodelite/codelite_workspace.luacodelite/codelite_project.luagmake/_preload.luagmake/gmake.luagmake/gmake_cpp.luagmake/gmake_csharp.luagmake/gmake_makefile.luagmake/gmake_utility.luagmake/gmake_workspace.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/vs2013_vcxitems.luavstudio/vs2015.luavstudio/vs2017.luavstudio/vs2019.luavstudio/vs2022.luagmake2/_preload.luagmake2/gmake2.luagmake2/gmake2_cpp.luagmake2/gmake2_csharp.luagmake2/gmake2_makefile.luagmake2/gmake2_utility.luagmake2/gmake2_workspace.luaandroid/_preload.luaandroid/android.luaandroid/vsandroid_vcxproj.luaandroid/vsandroid_sln2005.luaandroid/vsandroid_vstudio.luaandroid/vsandroid_androidproj.luad/_preload.luad/d.luad/actions/gmake.luad/actions/vcxproj.luad/actions/visuald.luad/tools/dmd.luad/tools/gdc.luad/tools/ldc.luaraw/_preload.luaraw/raw.luaraw/raw_action.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 rangeassertcollectgarbagedofileerrorgetmetatableipairsloadfileloadnextpairspcallrawequalrawlenrawgetrawsetselectsetmetatabletonumberxpcall_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 errorInvalid argumentincorrect 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_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 %sContent-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:HTTPHTTPS%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: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 ` ?AfmodI HH0HPH HH0HHHHH H HH H8C8C\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;`C(".Fd|"6Rf(<Hp| (6Fh&BN`r.HZp  ots'CoCreateGuidole32.dllRegOpenKeyExARegQueryValueExA[RegCloseKeyyRegEnumKeyExA|RegEnumValueARegQueryInfoKeyAADVAPI32.dllGetFileVersionInfoSizeAVerQueryValueAGetFileVersionInfoAVERSION.dllMultiByteToWideChar SetCurrentDirectoryWFormatMessageWaGetLastErrorCopyFileWWideCharToMultiByteGetCurrentDirectoryWGetStdHandleWriteConsoleASetConsoleModefReadConsoleAGetConsoleModeGetCurrentProcessGetProcAddressxGetModuleHandleWEGetFileAttributesWFindFirstFileWFindNextFileWuFindCloseDeleteFileWLocalFreeMoveFileExWRemoveDirectoryW&SetFileTimeCreateFileWSystemTimeToFileTimeGetSystemTimetGetModuleFileNameWGetConsoleScreenBufferInfoSetConsoleTextAttributeKERNEL32.dll@CertFreeCertificateContextCRYPT32.dll:WSAIoctlfreeaddrinfogetaddrinfoWS2_32.dllCryptReleaseContextCryptGenRandomCryptAcquireContextWCryptGetHashParamCryptDestroyHashCryptHashDataCryptCreateHashsGetModuleFileNameALoadLibraryExAFreeLibraryFormatMessageAMoveFileExA2SetLastErrorSleepEx}Sleep1EnterCriticalSectionLeaveCriticalSection`InitializeCriticalSectionExDeleteCriticalSectionGetTickCount64GetSystemDirectoryWLoadLibraryWVerSetConditionMaskVerifyVersionInfoWaExpandEnvironmentStringsAWaitForSingleObjectExCloseHandleuGetModuleHandleAIsProcessorFeaturePresentIsDebuggerPresentUnhandledExceptionFiltermSetUnhandledExceptionFilterGetStartupInfoWMQueryPerformanceCounterGetCurrentProcessIdGetCurrentThreadIdGetSystemTimeAsFileTimecInitializeSListHeadTerminateProcessRtlUnwind_InitializeCriticalSectionAndSpinCountTlsAllocTlsGetValueTlsSetValueTlsFreeLoadLibraryExW-EncodePointerbRaiseExceptionSetConsoleCtrlHandlersReadFile/GetDriveTypeWGGetFileInformationByHandleNGetFileType"PeekNamedPipeSystemTimeToTzSpecificLocalTimejFileTimeToSystemTimeYGetFullPathNameWNQueryPerformanceFrequency^ExitProcesswGetModuleHandleExWGetTempPathW+DuplicateHandleCreateProcessWCreateThread_ExitThreadFreeLibraryAndExitThreadWriteFileGetCommandLineAGetCommandLineWpReadConsoleWGetConsoleCPEHeapAllocIHeapFree!GetDateFormatW GetTimeFormatWCompareStringWLCMapStringWeGetLocaleInfoWIsValidLocaleGetUserDefaultLCIDTEnumSystemLocalesWFlushFileBuffersLGetFileSizeEx#SetFilePointerExLHeapReAllocBGetFileAttributesExWSetFileAttributesWJSetStdHandleCreateDirectoryWGetCPInfoGetTimeZoneInformationWaitForSingleObject<GetExitCodeProcessCreatePipe{FindFirstFileExWIsValidCodePageGetACPGetOEMCP7GetEnvironmentStringsWFreeEnvironmentStringsWSetEnvironmentVariableWGetProcessHeapGetStringTypeWSetEndOfFileNHeapSizeWriteConsoleW DecodePointerDN@   $ dU U U U U U U U U UhU U U U U U U UU..dI`I@U@U@U@U@UUI`IȓIU8UC `IbIPSTPDTUU abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`y!@~ڣ @ڣ AϢ[@~QQ^ _j21~uG?FSF$FGХFpI@ APAA@@@@ @@@ @@@@`@@@@@@@@@@@@p@@`@@@@@@@@P@p@@@ @p@@@@@@@0@`@@@@@@0@p@@@@@@@P@@@P@@@ @@!AAp@!A@@@P@@@@@0@A@`@@p@@@@@@ @c@X@Y@Z@B@J@K@K@K@L@M@I@pJ@J@PF@G@G@H@D@I@D@E@pR@S@ d@ X@`X@c@Z@pa@]@_@ >@`@R@N@P@0P@PQ@pP@0Q@@R@ȯSS@SpSST5 T  K|I.?AVbad_exception@std@@|I.?AVexception@std@@|I.?AVtype_info@@ 8Ph  03}4VS_VERSION_INFO?pStringFileInfoL040904E4l&CompanyNameJason Perkins and the Premake Project: FileDescriptionPremake58 FileVersion5.0.0-beta1>LegalCopyrightCopyright (C) 2002-2021 Jason Perkins and the Premake ProjectB OriginalFilenamepremake5.exe2 ProductNamePremake5< ProductVersion5.0.0-beta1DVarFileInfo$Translation  L0W112W3]3333(4/45 5$5(5q5x5a77778{:::;;;;;e<=*=? t000n1111122"222+334:4445v55V6778r99I:::G;W;;;<<<C>H>>>>h?m??0\000f11303>333444 55E555h6~666A777[88#9E9:::;<%<|<<==?L?x?@p0F0Y0p0~0121L1`1p112N22222-3:3K3k333=4W4j4556=788.99:L:X::::%;;<+=>)?/?a????Ph02|333333?5x5+666666z77C88::5;Q;;;;<@<{<<<<="=6=q=|========>>??``0O3333333 4[4u4 56677`7777t88}99(:9:C::g;<$:>?4?????p001?1M1v11112;2]223334}44H5w555555T6^6d6666666677z777X88X999999R:::;;; <=E=L=S=Z=a=h=o===6>d>r>??@00000000000000000000000003112n223Q33p445\667F77 8N8 949p9:R;;<>=>>>?_>>,?7???,D0(2Q2E344:6Y67J7z7?89>U>1?V??022 303438334445555 66)676I6W6i6w666666666727g7777 8(8]8z88888&9R999:&:::G;;p>>?>??5???U?_?u??P060000 1101A1G1S1n1u1244445667788J896999:< =>%>>>,1181<1@1D1122 2$22$8;<8=?01-16134444444444v5w6}666777:{;"=)=G=O=\=n=s==> >>>>>>>'?=?R?l?p?t?x?|????????????????tI112223Y3`3424;4h4u444445C5J5\5`5d5h5l5555555T6{666666777C8::\;~;;2>>>>>? D!0F0X00D1p1=2H23_4d4'5,5\5777889D:R:;;Ia>0(00111111114557;P7&<1<<0>4>8><>@>D>H>`83355555578 ::::: :$:(:,:;$<* >>>!?q?x??00 000U0s124444444444444445E5555666 66666 6$6(6T6[67778)8f888)9H9h99 ::::6;Y;;;;;k<~<<< ===f>m>}>>>?H!00011 11111 1$1'212u222222q>> >L>>??\0000122%3H3X3\3`3334 55+5Q5b5}55555555j678[9i9n9~999;;6===l00&0/0L0P0T0X0 112334V44v55]6d6 771999;;;;;;;;4<8<<<@HT33z44444444444444444f55>667!9,9C9;;<==4000112334*6A6i6668>?b?m???0N0g000111,22I3 4t4455t666737M777778!8Y8f88889 9$9(9,9e999:1:D::::::{;;;<4<<<==>>???`#000111172b2s2222 33^33d45556t778V88D9`9999::k<=*=>*?C?P?]?h?m?d 0000 313l44,5>5555686Q6o66666)77777g88q999P::y;;*<2<-==/>B>?,?>?d?|w0|00 1:1111242~2 33324_44426a66}7w88)919Z9v999:4::::; ;;;;,;[;x;;;; <5>7?k??? \ 0+0`00u11111223344,5M5555555 667777h8 99x9999;X>>>?0|i11112h334U4b444H5L5P5T5X5\5`5d5h5l5p5t5u66688;;;;;;;;;;;;;;;<<@>>>>>???Pp500012294K4X4e4r44444444 5577777777777888 88888 8$8(8,8084888<8@8/9=9+;`ts00000000000000112)4h4T55.66666666666666 77x778:88889W<<==M>W>]?g?px1{2244!6677q777&8p899:::::;2;\;n;;;<-;>Q>>>>)?C?r??????|0#090X0000!1G1^1m1112@2222/33[4t455575<5W5\555 6t6666667577777"899K>?'0,0@0X0\0`0d0h00001C1T1L243u333333E4q445669666666677778F8W8}888809A9X9p9u9999X:::::; ;I;{;;;;;<)<<<=s===>>>[???T050G0V112Z2223\333B4441555 66!8l8y9b:::;;*>>???d 000?1\11222<3^4c44 55+5555|6"7778>8W8p88 999:: ;;.===='>P>>>>???P.0G0`0x0!122333333::;;;;;?L??$g0B3O34555q66:::::T052D22W3/56s7z79999999::<<<<<<<<<<<==)>.>>????p00001111222 22222 2$2(2,2024282<2@2D2H2L2P2T2X2\2`2`3d3h3l3p366066788888>?&?@?H(1[1}112445556"6<}>>>>>>>>>>>>>>??\0a1O344x5]666V77989: ::::: :V:;;;;;;;;;;;;;=?>0?4?8?>0=223=@57F77u8P$0@1D1H1L1223x7(88i;n;`$x2B7K7Y7`7e7l7s7x777A8I8p7;7|9999998234#6p6t6x6|6778;;; ;;;9;<<<<<<01^1L284<4@4D4H4L4P4T4X4\4`4d4h4l44577777777777888!9<=== =$=(=u========>>">.>8>R>Y>e>o>>>>>>>>>????;?B?N?X??????,000#3 44449:";0;i;;B=i===xQ0|00-1.355R77$9(9,9094989<9@9D9H9L9P9T9X9\9`9d9h9l9p9t9x9|99999999999999999;;;>A>44425577&999::3;E;d>>#>,>7><>B>L>V>a>f>q>w>>>>>>>???t00112222222222223 3333!3'3-33393?3E3K3Q3W3]3c3i3o3u3{333333333333333333333334 4444#4)4/454;4A4G4M4S4Y4_4e4k4q4w4}444444444444444444444444444555 55555 5$5(5,5054585<5@5D5H5L5P5T5X5\5`5d5h5l5p5t5x5|555555555555555555555555555555555666 66666 6$6(6,606g6n6s6}66666666666666 777'717;7E7O7Y7c7m7w777777777777777778 88888?8F8d8h8l8p8t8x8|888888888888888888888888888888888999 99999999M:X::::::];u;;;;;;;;;;;;;;< <<<)<3<=>>5>?>V>]>b>l>v>>>>>>>>>>??? ?$?(?,?0?4?8?>W?0P0213r33484E4756`677L7P7T7X7\7`7d7h7l7p7t7x7|77777775:z;;>@hH0S0"1(111r234C56N6p6666667 77777858O88991:m:::::;;;<<==== >?P|:0J0O0T0[0`0h00 1111223334D4]444445*5C5a5V67778#85889,9O9a9;;;; <'<1>*????`t 00000 11[1e1t1111=2G2S2y2222<3F3M334|445;5|55567_899R:a:k::q;;;;=4>C>M>>f???p0/1N111&202F224g4444444%5555R6t666b777D8i889!9<9P999 :&::::: ;#;<;\;~;;;;<,<=+>>>>>>?'??? 00 11%111=1I1U1a1k1112(2.2J2V2g2}22)3A3^3v333$4>444455Z6r66666)7A7n77778688899A:Y::: ;;";:;;; < 0>w>>>>??Z?r?????()0A0n000001=1U11111 282e2}22233H3`33249445676666666777 77777 7$7(7,7074787<7@7D7H7L7P7T7X7\7`7d7h7l7p7t7x7|777777777777777777777777777777777888 88888 8$8(8,8084888<8@8D8H8L8P8T8X8\8`8d8h8l8p8t8x8|8x9|999999999999999999999999999999999::: ::::: :$:(:,:0:4:8:<:@:D:H:L:P:T:X:\:`:d:h:;; ;;;;; ;$;(;,;0;4;8;<;@;D;H;L;P;T;X;\;`;d;h;l;p;t;x;|;;;;;;;;;<< <<<<< <$<(<,<0<4<8<<<@*>Y>c>o>]?v??????P 0%0>0W0p0000001181Q1j11112-2R33B4L4?6R8e9}999999::G;D011:1L112=2n22484o4444I5X5b55556B6T6Y6u66667z7777 8.8?8X8i888888888.939=9[9n9::&;w;;;;;<=;=L=X=d=== >>">;>>?G? 000/0b0x0001<1H111112:2Y2n2222333[4415555566777K7o777778B8999E9V9e9v99:7::::G;;;;;"<[0J0000114111/2E2[2q2222233404U4a4m4y44444444'5n55666667*7/7g777 8E8y88829E9V999 ::;:J::::::;;J;;0<< >>>?g0001171C1t223383X3t3334O444=5Y555(6I7P7t8x8|88888&9+919999:::::::::;A;;r<<==E=W=a====*>4>>>>>> ??#?5???U0000111)151A1M1W11111)262R2m22233!3'3O3|333334S5_5k5w555555566P6T6X6\6`6d6h66666<7c7777&8v8:::;R;_;z;;;;;<"<><<<<=$=0=<=H=T=`=l=x===========>'>.>[>b>o>w>>>>7?????0&0J0Z0001122q2222333333374>4555|6678888 8$8(8,8084888<8@8D8H8L8P8T8X8\8`8d88888888888888999 99999 9$9(93:c::::::::%;8;D;W;_;v;~;;;;;>'???M?c?m????? 0%050[0l002&2J2n2222233(3833355 6666617:777787888889#9S:g::::::;IH?L???????????????0|@0D0H0L0P0T0X0\0`0d0h0l0p0t0x0|000000000000_1l12.4;458@::;;;;;;;%<<<(=v=|===>>>>>>> ?@l 0:0O0001"3T3g3334y677788::: ;%;;;x;;;;;;;;;;<<<<<<< =0>e>>>>>??PT:1?1D111#3,4{556>666W788,999;;b;;;>>`P.0:111 3%3K5X55#6>6X6n666 7_7z77728;8=99:I:}:0;R;<4<`<<>9?{?p411Z2m2 6\66677o788b8i8|89k:;n<>>30U0j0011111122;2@2V223F3q3333333 44c44,5555556+606967775888+9Z9x9}99:::;.;D;X;];;;>-?7??????|F0\0d0t0z22(3333e4t55555\66P7_7778 8838k888.9d999 :5:Y: ;%;;;<3>>N?p??%0s001111o23334Q4444444%555556-686z66667H7O8s8{888888/99999:$:+::::;;<<=5=p==_>>>>??d30d001182222333(44555555D6666=8a88"99::;;;d<{< =H==>>>'?K???t20v0000I1p111 212U2j22O33~4445`567/8Y889:7:]:};V<<=I=Y=t========>>;>m>>>>7?V??0X000001c11111122'2F2222$3Z3a3m3333333%4,4_4 6666677%7*777l7q7z777768Y8^88889!9I99;=;====S>v>>?s???l0000 1}111,2Z2h2{2222222233}33414s444557*777Z7d7I8888E:t:}:::::=;;;;<)h>s>>>?;?j???151O1w1~1122Q3_33q44v555555606J666666707K7778<889@9U9c9h9n9|9999::::; ;+;D;Z;;;;<9E9999999H:k::::;:;g;;;;;<(">E>g>>>>??? ?$?(?,?0???(0a0m0001122^22273V3m33334C4q44 5>5V5n555556C66 77?7T7778.8A888;;;;;R<>>>;????? 000000/1<1Q1h1111722A333354b4445/5=555.6U6k666666u77F888 9F9999998:E:::;;C;n;;;;2<<== >>%>1>?>Y>g>>>?011333333334f444 5g5}55 66J6666617E7L7777828v8888A9l999:w:::<>>>>??;?J??@0*0;000,1\1q11112-2A2S2f2w23)373F3\3333344(474Z4k4|44444E5h555555!6B6U6l66D7_7777788(888R8b88888$9E9X9t999 :M:[:r:::::::;;F;;;;=`>>>:???O?[?i?{????????P00!030A0O0e0t00000000011%1[1`1s1}111111112L2Q2d2n2222223)3Z3_3k3{33333333=4M4h44 5Q55555L66666667797J7S7X7a7x77777779%9999:::::%=G=L=====>>%>i>o>x>>>?"?'?Q?h??` 000%0*0N0000000000011122233344 4T555556,616>6q6666666$74797F7w77777778'8,898j8z888888809d9v99999:8:P:^:k::::;.;>;e;u;;;;;,<<<_<<<<<<=E=\=n=~==>$>h>l>p>t>x>$?P???????????p 00$0*0<0F00000X1112(2-222S2X2e22v3330494A4|444444444550575J5`5,6L6V6y666717N7777777888d8m8s8{888888888899!9'9-93999?9F9M9T9[9b9i9p9x9999999999999:':-:3:9:?:E:L:S:Z:a:h:o:v:~:::::::::::V=>?;111122@2q22e4x44666667!7/757P7x7777777788>8L8S8Y88899<:H:::;b;v;;;;;;;<9<>H>`>e>>r??HT1g111A3x3333333+4044484<46667:F<<,?k??????L012444555B6:::^;}<<<=r>v>z>~>>>>>>????????(8888888C9o===>A>>?K2e2t222222223323?3M3[3f3|333%4?4D446777+8:;;;=<[7><>A>S>?|?????HN000001U1_1e1o111 234:55L779:::D:e:E;u;;;=F??7>>?40>01A2223\33H568i:-;C;<<=*>R?m??LU0000;11 262]2q23444466 7*8p88?9j9q:;;;;;->F>M>@1>?Pla0h00000001 111&1,1;1H1Q1{11111222)2A2F2R2W2k2:3A3S3g3o3y33333334-45(89>>`HR0g00124(44444s5c66666\:::;6<_i>?Q?pPH0R000001_2]3|33;44&6X6v666j8888C9999;f<+=X=== >Z>>7?X0D0Q0000y111112d222b3333)4556 6/6P677b7488====Y>a>d?l??? _8T:::::::::::x11111114 4'4]4444 55P5555!7777778&8_8j8X:b:{::::;l<<<<<<<<<<==j==o> ?[?f???!0f0j0r0~0000001 111)1G1`1e1~111111111122U2222222223Q3j3o3x345O5Z5d5s5{55z6667:889G9====>>n>+???P20B02e4444X56Z699:4:=:E:b:S;;;>>>+?>??? 080k000}11L222!383a3|333334@4\445+5C55546r677898Z8e8s88/9N9`9j999:@:g::;);P;o;+<[>>?]0c00w111112 2=2`2g222222H3%4,4y55688!9[99:5::;;;;<1=_========>#>8>B>e>o>T3X6x6 88Q8c8i89S9999:#:W:z:::;=;D;J;Q;V;;;;;;;;;;;;; <<<$<)<.<>>*>/>4>Q>j>o>t>>>>?C?z???????????00 0/0:0?0D0b0q0000111171F1q11111111 2.2E2o2223"3'3,3G3Z3_3d3|3333344*4K4R4i44444505]5d5o5}555555556x66c8j8999:D;L;H<>?x2233=3b33445'5N56"6L6(7W778C8996:E:S:p:x:::::;;V;];f;;;;; <:E:N:W:g:x:::::::::::;;;;;;/<8P<b00'4 5567777777 88E888<9:<7=A=>>`L0 1e12&223V56b79999995:Q::::';Y;s;;;;;== >A>?pd000011)141c111122:2S2P33966J90:;5;k;o<<<=j=====> >&>5>?>L>V>f>>>? 191y1111$2-21272;2A2E2O2b2k22223333=4!5555+696E6V6d6o67788889 9999i99999::R;W?2?b??P0080001.22h5:6t66678C88899:::#;,;;;;4<~>v???,000F00511111:2222236;"<033336778#8;>>>>>?U?u???(2044`5`66W8:< =Y=_=>>?40E1d1p122233"333K3Q3]3|33R4444585C5P5b555G6\6e6n66Y7^77777777Q8]8q8}88889"9?9O9[9j9}:::';D;X;c;;9<|<<==&>F>V>>??????X]0h0n0w000000 181S1111112(225333]4|44566-6K6_6e67a77;!<9< l0a;e;i;m;q;u;y;};;;;;;;;;;;;;;;;;;;;;;;;;;b<<==?=H=>>?"?.?????? 0000001w1111222$202W2y23333:4B4N444445p55555566w666667D7s7{7778889999999!:f:r::N;V;^;f;;;;;I>Q>Y>a>>>>> ??!?A??????? 001 1'1/11111172?2a2q2}22p3x333334$4-484@4^4j44444A5{55555616Q66\7m7778 8/8S8\8g88889z99::]:i::;H;;; <<6>>>??,?Q???0 00'011111122!23s3{333 4#4444445c6677&767B7"8888 9929999::+:B::::::;;2;l;v;;;<>>>I?W?i?t?????@ I0Y0k0v000011112!2M2U2x22D3\3p33334%4-494444445(5t6|6667 77t77777E8V8888888Y9e9m99993:b:j:r::;;;<<<<<<<=c=o==6>>>F>N>>>>>>V?P I0\0000 111!1?1G11111182b2j22222c3k3333344 4+434Q4]4s4|44445n555555$6D66^7o7778848X8a8l888;9{999:Q:::;;;;>>>>>>?c?o??` 400g0y0000-1=1I1U1c11111233+3d33p 2222222222233 3$3(30383@3H3P3X3`3h3p3x333333333333333334444 4(40484@4H4P4X4`4h4p4x444444444444444445555 5(50585@5H5P5X5`5h5p5x555555555555555556666 6(60686@6H6P6X6`6h6p6x6666666<<<====== `@ >>>$>,>4><>D>L>T>\>d>l>t>|>>> 888888888888889999 9(90989@9H9P9X9`9h9p9x99999999999999999:::: :(:0:8:@:H:P:X:`:h:p:x:::::::::::::::::;;;; ;(;0;8;@;H;P;X;`;h;p;x;;;;;;;;;;;;;;;;;<<<< <(<0<8<@>>> >(>0>8>@>H>P>X>`>h>p>x>>>>>>>>>>>>>>>>>???? ?(?0?8?@?H?P?X?`?h?p?x??????? 9999 x2|2 034383<3@3D3H3L3P3T3X3\3`3d3h3l3p3t3x3|333333333333333333333444 44444 4$40444@4D4H4L4P4T4X4\4h4l4p4t4x4|444444444444444444444444444444444555 55555 5$5(5,5054585<5@5D5H5L5P5T5X5\5h5l5p5t5x5|555555555555555555555555566666 6(6,64686@6D6L6P6X6\6d6h6p6t6|666666666666666666666677 7777$7(70747<7@7H7L7T7X7`7d7l7p7x7|777777777777777777777788 888 8$8,80888<8D8H8P8T8\8`8h8l8t8x8888888888888888888888899999 9(9,94989@9D9L9P9X9\9d9h9p9t9|9999999999999999999999:: ::::$:(:0:4:<:@:H:L:T:X:`:d:l:p:x:|::::::::::::::::::::::;; ;;; ??? 000 00 4444@ l6p6t6x6|66p $1(1,1014181<1@1D1H1L1 22222 11 L>P>T> l>> >>>>> >(>0>8>H>L>P>T>X>\>`>d>h>l>p>t>x>|>>>>>>>>>>>>>>>>>>>>>>>>>>>>>??? ????? ?$?(?,?0?4?8?>8>X>x>>>>>?8?X?x??????X080X0x000000181X1x11111282X2x2222223 3@3`3333333404L4P41111 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;|;;;;;;;;;;;;;;;;;< <@<\<