H__PAGEZERO(__TEXT__text__TEXT00__stubs__TEXT__stub_helper__TEXTf __cstring__TEXT s __const__TEXT __unwind_info__TEXT@r @r8__DATA_CONST@@__got__DATA_CONST__const__DATA_CONST'__cfstring__DATA_CONSTx x__DATA@@__la_symbol_ptr__DATAx __data__DATAxHx__bss__DATA__common__DATAH__LINKEDITS"0phXXHhPq P33  /usr/lib/dyldH!$ڄ>9<<2  *( hu/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices `=,/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation ` /System/Library/Frameworks/Security.framework/Versions/A/Security 8/usr/lib/libedit.3.dylib 8/usr/lib/libSystem.B.dylib h=/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation&^)fUHWHG]f.fUHSPHHWHCH[]fUHAWAVAUATSHIIHLoJ*H9v\HuйH[HHHHBH9wHyIMt+It$HuLLH}Ml$ M|$E1HuM|$I$MLLMt$H[A\A]A^A_]@UHAWAVAUATSHHHIt8) )0)@)P)`)p))HHLLHLhHHEHHHEHH0HHHLcIMgK4H9v_H[HHHHBH9wH IMt.IwHLLHMg Mo E1MoIMHLLXMwHagHH;EuH[A\A]A^A_]fUHSPHWH@HHtH[]UHAWAVAUATSHHHUȾ9HEH߾-IL}HLhK/H9vVH[HHHHBH9wHIMt(It$LLUI|$gMl$ Mt$ E1Mt$I$MLHuLM|$1H[A\A]A^A_]DUHAWAVAUATSHHHM18IH߾LIIMt~LeILmIMnK,H9L}v|f.fH[HHHHBH9wHIMtBIvLLVI~iMn'IMfID$IH9wDM~M~ E1M~IMLHuLMfMfLmID$IH9vDH[HHHHBH9wHIMtIvLLI~MfE1M~IfC' IE1H[A\A]A^A_]f.fUHSPлHHxdH\1H[]UHSPH蝻HHHtBHpHQD< uHt-DHH< t HH< uHHt HTH5KiH裾H[]ÐUHAWAVAUATSHHHRIHH5H2t-H5HFH5H1西H߾xH߾;H߾IEt$McLH ID$EDILeDHEE1IWH߾HU+H߾莸HIK/HECL=HMLcLHIK/HHEOt=LmL}CD=EYDeAAfCD.H߾LH߾H߾1KD.H߾H߾RH߾1ӵKD.H߾豨H߾H߾CD.H߾耨H߾H߾C.H߾PK|.Ht#H5puCD.HEH߾M9t!HEL0I If.HEHML4IH߾ӧA>HM~HEHHxtHEЃ8L}tAL;}t LiHH[A\A]A^A_]ÐUHAWAVSPIDxE~'I1f.IFH|HI9uI~1H[A^A_]UHAWAVAUATSH8IH5{LL1ILԦH5ILպLL[HL蛦LuMt;t {CH5LtHL1H}Eԃ{1H]HMHHHKL4IH}Lu=E1 1҃;LuIhIcI9wI^MIN4#Jt#HtsL۹LLLAL裥B|#tF;t#EԹDEBT#Er1df.fB|#tLHuLLHL肸fL LLLu ;f.fE1&f.1HEB| I%IcI94IFMIJ Jt H1B| uJ HHMIL{L.LH#LDHE8tC;\&EԹDECT&LuV1HfHELD@L LHLu 迣;賣HEBT EfHMHH]HcCH94 1uԅEH}DLH8[A\A]A^A_]1f.fUHAWAVAUATSPIIҦuZL1Ht}IĻLH`LLALŢEu?HL9v171L1貯Ht!LHLH[A\A]A^A_]!H[A\A]A^A_]f.UHAWAVAUATSPHIzIALZLL/H3L$E1L1E1ZL]t#L1LHE1ALD軡H3LE1ADH[A\A]A^A_]ÐUHAVSHE1fWf.u{\HHcWH߾عMEؼHE軴HE讴H߾tH0ADH[A^]f.@UHSPHHHHyHHHH[]UHAWAVAUATSHEljIIHYHHEHFF(Hdž(H~=puHH= JQLK)L14)L'L0L1)L'I$(L''1GLǢL1(L'L֡La)H,L NL袡L-)H,LLnL(H,LQL:L(H,L@t/Lu M,$LlLعO.AD$ELD֞upLYfLDt9L1R'HLҚI$(HI$(I$(L''1QEL'L1?EHL+N1)EI<$t9L+11ELI'L1DHLXN1DHHpSHH;EuLH[A\A]A^A_]DUHAVSIH(HtH"Hǃ(L[A^]KGUHAWAVSPIA[;Ht}HH5H1IcHHL,H߾1E1E1BAH߾貥AHD HEEETIHt HjRH;H5q1GH;HJRH;H5VH1 H;H[A^A_]f.UHAWAVAUATSH(I1A1(IL8IHPH1AH Y ztKIcAITHt}:-uvr~1wFHc4Hzu0Ãzu"IcITHt3:-t.A똻!t-u1ɀzDAL :IHt 8tHeIcIL5PI>HDH5E11I>CH5H1I>QI>HH51cI>1GLutKIHePH H= 3xH H=A_H;LLuLeL}H]LyDME1D9EDEAVD)L胳E~8D}A1DItLsAHcL迺HI9uH5L臵H=yHIL5`DmA?@ILL18ÅpHCLع\LxE1E9EEAVD)L該E~AD}A1f.HEH4L萩AHcLܹHI9uH5L褴H]H=HH]DmIL5zLeA?@ LnLLHLE1-ÅLȔAH5^L1TLD4L%ŚH5L11DE1E1wÿ1wLDLlL"E1H]A$ADmf.DmAE9IcL,AEH5L1I>XML=JAŃfHDHquHAHL1uHDUHLH1DE1E1虱Aſ1HD H߾荈E`H\[AH߾H- HH5NH߾謈HD11E1E1ML%ՈH߾1HH5@H1袜IML55AI>H56L1 I>^H1贇H AH H= H;HEHAH[A\A]A^A_]fUHAWAVAUATSPAIH2H5#HDH,H"HD1E1L1/HHEHHtyILLSHtA| u HAEu (1Et!A<$=uLHH5L1`LLHPLADH[A\A]A^A_]UHSPH1{HuUHfH߾tH߾t>H߾H߉蕊H50HH1HHH¹nH[]fUH1H=H5 ] UHSPH111 H5H1H[] UHAWAVATSHPIH>HHEHDž1H5HHILHL1E1UHAWAVSHHIHN;HHEHDžH1E1HHHL.IH߾/1W,Mt-HHt!H߾<17,H߾'L1%,H,AHH߾ 1.HHEEu(HHLڔH5~LCAL`DLHNHHH1LHHZH*L)H9HH;EuHH[A^A_]詼UHAWAVAUATSHAH0IH9HHEH@5LLPAf.DALLC 6uL8D9}JL@ ADD9}I|HHuH5oLL1LDHH[A\A]A^A_]FH[A\A]A^A_]DUHAWAVATSIIAHw~6HDLIHu9H߾=xHDHE1MtMt L1IL[A\A^A_]DUHAWAVSPAI苀HHuLwLDHHH[A^A_]f.UHAWAVSPAAHvD9u H[A^A_]HD}wHDHH[A^A_]%DUHAVSAHvt[A^]H$HD[A^]f.@UHAVSHAHHUF}}u%H߾EvHDHEH[A^]fUHAVSHEAHvE~:HUHD|}u%H߾EvHDH7EH[A^]fUHAWAVSPAHHUg}Iƃ}u>HDswtHHDH߾vHDHLH[A^A_]fUHAWAVSPIAH(u~VHUHD|Iƃ}u>HDvtHSHDKH߾uHDH>LH[A^A_]UHAWAVATSIHOHGHH)H9sIM|$HHH)L40H9LCLH)r1H9r,ID$ I9$t=LLHI$H5L1ID$ I9$uþLTWH5Lt%H5L1躅HL趑LILL9HI4$IT$H)I$Mt$ID$H[A\A^A_]f.UHAWAVAUATSHI։IHu^ILQIH}H0HPLAIMtNMuIHuL$HELHH}H0HP1UHHCH5L1wMeMuLH[A\A]A^A_]f.Ht7UHAWAVSPHIIHHLHI^H[A^A_]UHAWAVSPIIHHt HLHHLHˬI^H[A^A_]UHAWAVSPHLwH7HWLHC H9tYHuLIL~HH}H0HP1AHHCL{nLmH[A^A_]UHHw]bfUHAWAVAUATSPILwHULzIMl$ M9,$tL nH]HtLHHLH謫I\$1M9,$@ƃLmLLmH[A\A]A^A_]f.UHH~HF H( ZF]@UHH~HF H(YFHH]f.UHAWAVSPAHApt[HDalAH߉1"H߾1#xIH߾lEt,IcHDHD1Ӑ!H߾Tl HD7{IAIcHD袐DH[A^A_]@xWUHAWAVSPAHkAH߉1xEHDLWHLlHD1H[A^A_]5@UHAWAVAUATSH(IIIH$HHEpkÃMtaH5LL1"H5L蛨HHuRL8虪IL1LxHHH5HH5L&Hg$HHHHtHcHƄ MtDu?HH5:L HHHHmtHcQ L1fwH5HLHM誔AHH6AMtHLEt<j8EIL1vHHH5NHbL4jLi\誥8IL1vHHH5H LM1+~L޺iL_iAH"HH;EuDH([A\A]A^A_]Gf.DUHAWAVSPIHH虦E1=u[HcH DH{ptu=u9HcH DH{NtS=uHcDH{+AE1#u-H{ tuH{AADH[A^A_]f.UHAVSIH~IHH{t 1H[A^]H{HK:If.UHHHuHUH5HU0H]f.UHHFHtHHFH]1]f.DUHAVSHHIHǦH]HEH5HULHE1趑H[A^]f.UHAWAVSPIH蛄t9HL{AH߾ɁtAH߾PgE1E1AHDfDH[A^A_]UHAWAVATSIHJfAH߉ E1trHLzH߾>tIH߾fH߾KfHDpiAH߾1E1胎 H߾fD[A\A^A_]UHAVSHHHUH߾lqIƃ}uH5]H1H߾eLH[A^]fUHAWAVAUATSPIAHHH߅t(kH5H1DiwGH HcHH5 HD{qHH5HDHyNHDoE1H5HxH߾AH߾eH߾dEAH߾1qIAHDiHD1҅t.oH5$HH1xHDdgnH5H߰xkH߾ dHDgH߉ehIHDuH5ȲHLH1xEtH߾)dH߾cH߾LH[A\A]A^A_]pf]fMUHAWAVAUATSPIIUԉBatI?Deu+H5lH L1gI?DeAE)E~IDDufL&fAuIwLDeD]xILu_IMu:IDef.IwLU!xIWLD"I?MuALDH[A\A]A^A_]lbf.fUHAWAVATSIAHzAtEH߾/bHDaAE1H11H߾5eHDL臃D[A\A^A_]f.UHAWAVAUATSPAIIHHعUztHH߾aH߾عFaAH11~H߾dHtHDH߾LyH߾muYH߾:aHL1vHL2uH߾1E1kH߾.dH߾L~H߾LaH߾`Et&H߾cHLH[A\A]A^A_]H[A\A]A^A_]DUHAWAVAUATSPH `H)XIIHIHHHEH貟HLLHH(MHLL號HIE1/f.@LHHHaIHt|MI)t.HLHHLޝLLMLHtHHHzHLH蠝HHIfE1H諞Ht1IHH4HHLZLLMHLLLrHH9t_HL荍IL}oHHH0HP1AHHCL _L^H1kH H H;MuHH [A\A]A^A_]kUHSPH=31<HHtH5=H]HH[]f.HHtH馜UHG1]UHAVSL52I1jH5NHH1I>˚1[A^]UHAWAVSPHEI&]IHtH5L11]I9tH5L1H[A^A_]AEf.u{H5LH[A^A_]eH[A^A_]f.UHAWAVAUATSPIIH\A>$uIHLJpAH5ZHsH߾1iH8$H5@%H1rHLpH߾_H߾1E1DŽH߾1hiHpHIADHߺ\H߾)\HD\H߾ \Eu"HDb\H߾[H5H1TqHLoH߾1E1H߾1hHtHHLt&u7H߾z[HLHt)uH5?Hߺp1H[A\A]A^A_]H5ЪHL1ofDUHAWAVAUATSHIHJHHEZAH HLHqH5SLqL׹]LHyL׹1gIHǾ/IHtA$LՙLLHnH5LyA?$t LLWMtA$/Lֹ`]E~(EA߻LF]Aك˃uA^LD1E1JHLL]H5~LyAvL\H59LxLYH H H;MuD)H[A\A]A^A_]芕fUHAWAVATSE1 AAH]HlH߾A-f.H߾YH߾ƅH߾\uHD\`ugHDDJtH߾YH߾XH5HlAH߾XH߾H߾TXAD[A\A^A_]fUHAVSHHHuنIH߾hHH}H0HP1AHHC1H[A^]UHHz1Ʌ]fUHAWAVSPHA1!IH<t$HjH5OHL16lA H߾nDH[A^A_]ÐUHAWAVAUATSPH1IAH߾1HuHǺ輖IAL觓t;HOjD(89H5çHDLEI1~kH߾OmADH[A\A]A^A_]ÐUHAWAVAUATSP pH)XIHHHEо1IL1HL-ͤLLxIHLjIM.MCL1vL耓HL11_L1PLZIL119L96LHHALBHLLҒL9!MLLLH訒L9HLLq0L)MuL!HLkHNHH;EtWMtLL3hH5LȑLhH5LhH HH;EuCH [A\A]A^A_]L耑LxL1kH HH;EtvLLH@LgH5|sL$HLjgH5vLKLHLpUHAWAVAUATSPI13IL1!IYIHL1tNL1`HHHELfH5LLHٻ1hLMtOH5wLkHHtGH5LH17~HLLi8HL HHuLlL$fH5LL1pgH[A\A]A^A_]f.UHSPHHHHH H[]ÐUHAWAVATSH1IAH߾1IH5HLH1fH߾1_H跑tHAeH5ȣHL1fH߾^hAD[A\A^A_]ÐUHd]UHSP@xH)XHH HHEH@Ht.HHfeH H H;MuH@[]1H v H H;Mt8UH赎1H]ÐUHSPH1[H虎HHdH[]ÐUHSH(HW)E)EH}H11mH5HdW*EHcH߾pH5hHidW*EHcH߾pH5IH=dW*EHcH߾ppH5&HdHuHdH߾Hp}t H})H([]f.UHAWAVAUATSHIHHHEHHG H=NjHHPLPL8L1LE1E1IH8HHH)HLHLE1E1踎H5vH@HHH1@AD$HAD$LA<$ 5AD$ $H ~HcHHHDž@HL(H HH5L\HILH11_H!ILHH$HHH(L8L@LH11贈IH赈M}H8L蒈YH@KLcH0EH90*HDžHH5./HHL#HHHPFIL$MD$H51HPL16L6H^HUHLHCHID$HID$H"HHHHID$HHH;EuLHe[A\A]A^A_]û L<H(0L(L d@3LH5,ewtLLJwLxwfAD/f.@Ht$<$tHLwtLA%E,$A{uI|$}qAHL%qE1HIL9M9IH A݄x؋D<!ЅuLInLu4E1Ex ؋D< A_tf.M9eE,$IA݄yE1QH5 Lq5M9&L-f.DIM9A$xAD<!ȅuJmuƄx AD=u_t.tfUHW1Ƀ]f.UHSPH1[H#1@HbGH[]fDUHSPH1HH)DH[]ÐUHAWAVAUATSPAHIH}HoIH5RHou.L%:f.HIHLotE1MAf.IrIGB|;/ItHIM^Iu ;.OHƒ1A Eȃ LmM9I;.{.L/nLxHMDLH5nLH52kntyLH5)nHueL$@nHuSMwLmM9MDAHCLHt9{/tHIHIM9t$I@A"Lu%LmHE1M9tA~/t A/IMLHLmC&MLH[A\A]A^A_]f.UHAWAVAUATSP@0jH)XAIHHHE .~^ALпA߻Aك˃t4L1tL1SHпLHDNIHпLAHHH;EuH@[A\A]A^A_]if.@UHAWAVAUATSP@PiH)XIHHHE.-~\ALпA޻MAك˃t/L0tL1sLLH1sIHпL@H HH;EuH@[A\A]A^A_]hUHAWAVAUATSP@hH)XIHHHE^,~_ALпA޻MAك˃t2L0tL1裸LLH¹IHпL@HMHH;EuH@[A\A]A^A_]gUHk1H]fDUHSPH1HǾj1H@HBH[]ÐUHAWAVATSSgH)IHHHEؾ1軷HHjILп@LHHMgBƄ%пL=jHLoHHoHHǾjHuHHпH13tHHH;Eu7H[A\A^A_]HпLL=HmHH;Et/fUHAWAVAUATSP@eH)XIH2HHEо1GILп@LeLf.HB<r tu HпE1I>!E1f.AH1@A(A؉A%u+{u%}HD?}HuӀ%u WHӀ$ujG<(u+Hf.f?)Hu$u+G$<{u"Hf.?}HuЉ<%uOD؉<%><$u#DO$A$A{'uMt0L9t+F<\tL>D8L8D> L>0D8L8D>@L>PD8L8D>`L>pD8 8HHuHt>H>HLHHH1D D H H9uMLM9uf.H6D)Hf.HBпI1 Ir*H H%wH$uD <(t <{ufHt+<"t<'u!LJBпIf.DIA$<w$Ay:uBпBƄѿ:IAYIH4 \t/u*BƄп/AA<\t"uXH5uLJ9HRwL:L11E1JL1胮IL"L1bIL%L11>L5LNE1LпfDL1A@LH]LfH/t\tuLL!LLQ5ILLELMx[HпL1pE6@HH]f.D3HH߾H߾lH߾!H߾L?H߾H߾0HL1賺H߾H[A^A_] f.fUHSPHH57qHH5sH&HH5sHPHH5qHZHrH5rHH\H5gHHFH5rHH0H5rHBHH5rH\HH5rHHH5H3MIHSH߾عmAH5iH0H5PrH/<H5ofH0H5=rH<H5?rH0H5nrH;H5rrH0H5rH;H5oH0H5rH;H={rYHu H=orYHH5lrHEHD0H5[rHu;H}H5SrH^;H 1H[]f.UHAWAVSPH1(I1}AH5qH2H5`tH/H߾O3H߾RtH߾葩H 2H߾eH=qL1YDH[A^A_]fUHAWAVATSAAIH5u10LDL޺pLDDE1E1CAL޺HLD[A\A^A_]f.DUH]DUHAWAVAUATSHHMHAIH51/H3LYL1E1BH5pL9L1177ADHEAAf.@I $XIHL1bL-!N,IL9etgJ4L-LijHPL#>N4 LH5rYt LH5rXuI jH5rL8H5lLX0L0AH5>iLN-H=!tH5qL5-H5 L&-H=oVHtHH5qL-LH,L5qLL,HnLH/H5vqL,LL,LH/H5[qL,H5qqL,LYD)LEH5aL]/HkqL0LlH5OqL=,LL2,L1E1k@LiLLJLHkLI9LHHLutLLqurHH;Ht&Hf.LVt"H;HHuLLud'H5jLC+LL8+LDL1$LH1uL11E1E1?tLH[A\A]A^A_]H5!mL-H5L1",LzAALDL1DE1E1F?ALDLFLEt Ia1 ,Lf.DUHAWAVSHIIH;HHEH~PHpPH1PHH޹P0H5*L1 +LL)H=l-SLH)L1E1E1D>tULSLH5hLL)LLA)L LtxLL)kLtH58hL(LL(LcBL1!HLHu.W0BL1!HLLH(HHH;EuH[A^A_]fPf.@UHAWAVATSIItJLL=t;H5E1L1)LL (L1E1C<t"HHtLLE1t&H=$jJQHtLLHsE1upAteHH;HtVHf.@LRtH;HHu*H5fLG'LL<'L@E1D[A\A^A_]UHAWAVSPIH|H;E1HtLRtH{HHuILH[A^A_]@UHAWAVSPIH,H;Ht,IHf.LQtH;HHuH[A^A_]H5eLi&LL^&L?HsHSLLE1H[A^A_]AUHAWAVATSIE11sH|H;HtDIHf.LQtH;HHuHsHSLf%AD[A\A^A_]ÐUHAWAVATSIA:IHLwÅuH jLDLL[A\A^A_]ÐUH]ÐUHAWAVAUATSPIE111HL11HtGIHt?HEPIL:PI9r'LH)HLO1@LD'ADH[A\A]A^A_]ÐUHAVSI1HL1E t)Hf.@ HuL#[A^]DUH华EtHfHu]ÐUH(exG@HGPGX]fUH]@UHAWAVSW@OD_HwLGPE1CDD1D!D1ҁ™yZDЉBAIDDDDAPAAAAMArAO AW3AO3EAB3BArA'wDD1D1¡njA;wDD!DD D! ʁܼHDD1D1b4fnfA:"fA:"oO@fA:"fG@DWP[A^A_]UHSPGXH@4GXGX<@u HCXH[]f.DUHSPGTGXH@4GXGX<@u HfCXH[]f.UHAWAVATSHtRIIIGX1 HI9t9A AD$THA AD$XAD$X<@uLAD$X1[A\A^A_]DUHSPHGXHOXAGX7tI?uHCX1 <8t(HCXCX<@uH|CX1C;fC9CTC8H H;MtDUHAWAVATSIE111豓IL11蝓Mt4HHt,HFLHHF1@L AD[A\A^A_]ÐUH]CEUH6 ]@UHAVSA$ x!tYD5 AwQDH HUHAWAVSPuHGL HW0H)HHcH9~HHAI9Os9IO3HH+G8H@B)E19H5,HUHPtDH[A^A_]HCHcM@UH6]4@UHH9HGLcLHH)HGEHNHFHHFAIAt[MIIA1fHODHFHHHNHOD @HFHHFH K HIHuAtHOIBHF]f.fUHHOHH]HtUHHGH]Hif'F'FwUHHOHW H+ H]UHHGHO H+HH]UHxBHGHO H HHHH9sf.@HH9rHGHO]HcHHOHHHG]f.@UHLOLG ~"HI0L9r@H5jMAy9ٹ}عu:HwH@MAy_HcHLMAxMHLH)H9rRzIytع)LAH 9׹)HI4H MAyHcHHH)HH9s-HzH)EG(EGHHGH9HrHL9s7Iyf.)EG(EGHHGH9HrL9s-I)EAA(EAAHIAL9Ir]fDUHHO ~HHH;Gr9Hi2ٹ}عu;HGH@bHcHHG~SHHH;WrHh]HxtAعA)LAA A9׹)HLH ٹ}عu#HWH@]HcHHW]H ytع)LAH 9~H ?h@@u =׹)HLH @@tHO H H1F tHB t]]fUHHGHW ~HH H9r-H g$ٹ}عu!HOH@ HcHHHG]H ytع)LAH 9׹)HLH UHHG ~HHH;Or0]Áٹ}عu/HOH@H; uWHcHHOH; tCA]Hytع)H y 9׹)HHH H; u]f.UHHcH HD]f.UHHO ~HHH;Gr.Hnf%ٹ}عu+HGH@ HcHHG@f]Hxtع)HP 9׹)HHH fUHHG ~HHH;Or.H e%ٹ}عu HOH@ HcHHO1y]Hxtع)HP 9׹)HHH f.UHHHHO ~HH9H;xr:H=Get3yٹ}عu5HxH@tYHcHHxuHEH]Hxtع)HP 9׹)HH<H tHu}/H]UHHO ~HHH;Gr.Hd%ٹ}عu(HGH@ HcHHGH1]Hxtع)HP 9׹)HHH DUHHO ~HHH;Gr.Hc%ٹ}عu+HGH@ HcHHG@G]Hxtع)HP 9׹)HHH fUHHG ~HH0H;wr9H5nc2ٹ}عuAHwH@iHcHHw~ZHHH;WryH"cH;5urHytAعA)L AI A9׹)HI4 H ٹ}عu8HWH@H;5u.HcHHWH;5tH;t1]v6Hxu1]ùع)Hx 9J׹)HHH H;5AuDUHSPHHO uAHKHHKHQHHICHCH[]UHLW ~HI2H;wr9H5a2ٹ}عuAHwH@nHcHHw~_HIH;Wr~HaH;5suwMAxtAعA)MA@ A9{׹)HI4H ٹ}عuPHWH@H;5uFHcHHWH;5t2H;t)ttu]4]o2]Y0Ixu1]AعA)LAA A9)׹)HIH H;5u@UHSPHHHwHEHtHCH[]UHSPHHHO ~HH9H;xr:H=F`t3uٹ}عu1HxH@tUHcHHxuDEKHxtع)HP 9׹)HH<H tHu*u HE1HtEH[]f.DUHSPHHHO ~HH9H;xr:H=f_t3sٹ}عu/HxH@tSHcHHxuBHHEMHxtع)HP 9׹)HH<H tHu1@*u HE1HtHEH[]UHHG ~HHH;OrHZHfu7sٹ}عu.HGH@HfuQHcHHGHft>t@1]Hxtع)HP 9׹)HHH HfuHHH]DUHHO ~&HHH;GrGHNZHu@ٹ}عu=HGH@Hu`HcHHGHtJu HH(]1]Hxtع)HP 9׹)HHH HuH]@UHHO ~HHH;Gr:HYxHt3iٹ}عu&HGH@xHtIHcHHGxHu8H]Hxtع)HP 9׹)HHH xHt1]fUHHG ~HHH;Or.H X%ٹ}عuCHOH@ HcHHOQ?1$wH5HHcHH]HH(]Hxtع)HP 9׹)HHH f@UHHG@HHG]UHHG@HG]fDUHHGH0@HG]UHAVSIHt LIH5LȞHIFHK@HIFIFHx~L,HH[A^]UHAVSHHt'HyIHCL0AN@HIHCHC@E1HHCHCHx~HL[A^]fUHAVSH1@IHCHx~H苾L[A^]UHAVSHHt))P)`)p)])e)m)u)}H0H8L@LHH7HHEH HEHEHEH0HEHUH{?IHCHx~HսHHH;EuLH[A^]&UHAWAVSPIHAH߉蛫LxHsIcHHHH)H{HJHHFD8 t[tHKHHH1D0 HAt5HHHHH{DH{DDHuHKHAfHCHCHx~%HH[A^A_]̼HCL8@HCH[A^A_]f.@UHHG1Ʌ@HG]ÐUHHGH0@HG]UHHGH8@HHGHO1H9]UHAWAVSPIHHGHx@nIHLpIA~Eu-I>LIxtHCAHCHHC3E1HCL8AO@HHKHAHCHLHHC@H[A^A_]DUHAVSIHG ~!HHI;^r=HHS{Et6ٹ}عuHI^H@{EtpHcHI^{Eu_H;IvH IxtIIFA@QHxtع)HP 9w׹)HHH {EtE1INHLHHIF@[A^]DUHAWAVSPIHG ~HHI;^r2HUR)ٹ}عI^H@ HcHI^LH蟙Iǃ{Eu-H;LKIxtIFAIFHIF3E1IFL8AO@HINHAIFLHHIF@H[A^A_]Hx<ع)Hx 9&׹)HHH @f.UHAWAVSPIIHG ~!HHI;_r=H2Q{Et6ٹ}عuNI_H@{EtvHcHI_{EueH;L[IxtTIGAIGHIGgHxtع)HP 9q׹)HHH {EtE1IGL0@IOHAIGLHHIG@H[A^A_]ÐUHAVSIHO ~HHI;Fr.H(P%ٹ}عu;IFH@ HcHIFI^HsH8CIF@[A^]Hxtع)HP 9׹)HHH f.fUHAVSIHO ~HHI;Fr.HxO%ٹ}عuAIFH@ HcHIFI^H8HIFHHIN@[A^]Hxtع)Hx 9׹)HHH fDUHAVSHIHO ~HHI;Fr.HN%ٹ}عuQIFH@ HcHIFHUEI^H8HuIFHHIN@H[A^]Hxtع)Hx 9w׹)HHH f.@UHAWAVSPAAHHKHAEHCE"EHCHx~.HH[A^A_]޵HHDDMHCHxH[A^A_]UHHO ~&HHH;GrJH~MHuGٹ} عu{HGH@HuHcHHGHuHH(HHuHGHHHHtmHOHAEHG]HxQع)HP 9;׹)HHH HsHHHHu1]f.fUHHO ~HHH;Gr.H^L%ٹ}عu>HGH@ HcHHGHOHHP H@ AHGHHHO@]Hxtع)HP 9׹)HHH f.DUHAVSIHHGHx@!HHL[A^]f.DUHAWAVAUATSPIHHIAEuRI?LIƃxtAHC@@tI7F tHHA t H聦HCH@AHBE1LkHCL AL$@HHSHBHCHJHLMHLHHH[A\A]A^A_]UHAWAVSPIHG ~!HHI;^r@HJ{Et=ٹ}عutI^H@{EtHcHI^{EH;IvHRIǃxtvIF@@tH3F tHHA t LdIF@A]Hx]ع)HP 9G׹)HHH {EtE1INHQHLHMIIFH[A^A_]fUHHG ~HH0H;wrkH5nI]ٹ}عuHwH@]HcHHw]Hxtع)LA@ 9׹)HI4H ]t@UHAWAVAUATSPIIHG ~!HHI;_r@HH{Et=ٹ}عuI_H@{EtHcHI_{EH;LIăxIG@@tH3F tHHA t L螣IGI@A$H}HxRع)HP 9<׹)HHH {EiE1MoIGL0@IWHBIGHJLHMaHMHIH[A\A]A^A_]ÐUHAVSIHG ~HHI;^r.HxG%ٹ}عupI^H@ HcHI^H3IVHLnINAH@ IF@@tH3F tHHA t LWIFHIF[A^]Hxjع)HP 9T׹)HHH jf.UHAVSIHG ~HHI;^r.HF%ٹ}عu^I^H@ HcHI^H3INHLIF@@tH3F tHHA t LyIFHIF[A^]Hxtع)Hx 9j׹)HHH @UHAVSHIHG ~HHI;^r.HE%ٹ}عutI^H@ HcHI^HUEH3HULINAIF@@tH3F tHHA t L蓠IFHIFH[A^]Hxfع)Hx 9P׹)HHH fUHAWAVSPIHG ~%HHI;^rHHDIFxuAٹ}عubI^H@IFxuHcHI^IFxtvLxCtuuHLx(MupINLHxkع)HP 9U׹)HHH IFxuE1CuHLxMt)H3F tAG tLLH3LLIFH[A^A_]f.fUHSPHHO ~HHH;Cr.HyC%ٹ}عubHCH@ HcHHCHKHHqHr IJ HKA@tH0F tHQB t HȜHKHHKH[]Hxxع)HP 9b׹)HHH yf.UHAVSAHHcHHwMt ftHD蜂At&[A^]HC L@ HC HH0HDAuHCHK H9AsHA[A^]fUHAWAVSHAHtHS ~HHH;Cr6H B-1-ٹ}عHCH@ HcHHCH+C8HcHHKHMMt ft&DuH+K8H5HUHI܇Au|hL{ MO MG0HH+S8IW8HIW(HAGB ƒfAWBHHDAgBIG(H1AuHKHS H9JsHJH[A^A_]Hxع)Hx 9׹)HHH DUHHVH]̀f.UHAWAVATSH0MHHIHHF#HELeLHhQLLHL'ÅtH0[A\A^A_]IFLxA tIFHx@IO H Iw H@@tHNH9uLv@UHHGxFuAHHH@Hp]鋉]@UHG ]fDUHAWAVATS ILwH HcHAFW11L1vAFW1L1I^I^H A^A^sEfWAFWtqHcH I^LHGvIGHx~LEfWHZ10AA A((OAA^W[A\A^A_]LHƠuL赦EfW1A~UА(9JZf.fUHiUHSPHHO ~HHH;Cr.H)>%ٹ}عuIHCH@ HcHHCH0HSHH1ɅHSHHHHKH[]Hxtع)HP 9׹)HHH f.DUHAVSH|H)HCHxNtHCHx~?H[A^]aLsH5֐H1,I@@AFHCHCHx[A^]fUHSPHHG ~HHH;Sr.H<%ٹ}عu-HSH@ HcHHSHsHHCH[]Hxtع)HP 9׹)HHH f.UHHt HGH@HHGH]UHHGHPH0]f.DUHAVSHaIHCL0@GHCHCHx~HI(L[A^]f.fUHHO ~dHHH;GH;H?uzHHA9P|zHL H H@XHHHPHHR5HEiٹ}عujHGH@H?uHcHHGH?t&u~ HH 9}1]ÃHH H HHWHG]Hx(ع)LA@ 9׹)HLH H?uUHSPHO ~nHHH;GH:H?HHp9VLD IHvXHHHrHH4HE1|ٹ}!عHGH@H?uHcHHGH?x&u~ H0F 9} 1HH[]ÃHH H HKE1HWHBHGBHtiHG@@tF tHB t2Hxع)HX 9׹)HHH H?KMSIA@FI@H99L|,UHLG ~&HIH;OrJH 8A?&uGٹ} عuxHOH@A?&uHcHHOA?&u#~#HIH;OH i81]Áٹ}kعu{HOH@dIyTع)L AI 9=׹)HI H A?&tHHcHHH]HcHHOHHcHD]IxXع)Hx 9B׹)HHH f.@UHAWAVAUATSPIHG ~HH0I;vr2H5a7)ٹ}عIvH@ HcHIvL>Lc~HHI;Nr2H 7)ٹ}عINH@ HcHINL)IcKt LItKt HFHHNH9tFKt H@@t HNH9tH[A\A]A^A_]LH[A\A]A^A_]H8ع)LAy 9׹)HI49H Hxع)Hp 9׹)HH H UHSPHعHH5H1GgH߾H6H߾&H5/HH/H߾H[]UHSPHtHH[]H߾>WH߾H߾H5/HH߾HH[]5DUHAWAVSPIH/H THH 3L1 XLމAƃ t8t3u;L1A**Y2XLLD IcLH[A^A_]f.fUHAVSH11TIH߾HL1kt H[A^]L H11#H[A^]UHAVSHWIH߾H߾:E~*u%HDNH߾H߾H[A^]f.DUHSPH-UH߾tH .H߾`H>H[]fUHSPHTH5 H1H߾H11E1H߾TtUH߾uH5!H1?H߾uAFu K:9|CDڃuADALɁ%?ADAA|$AT$9qLutSIH@8H5fHc~\ك?<x?# DutRIHq8H=DHc҅~\ك?<x?#u)  DӃuAA E~(AF(LAIH@8I؉f.Hcϋ9DuADALe?ADLEL$A|$AT$9vDAF AF$D}AD@L6AAF AF$ALDAN AN$tyA~(tlIILA8fHcA4:DuALωLρ_? 7A A^(HMDQ DQ$At$HMH LY8MԁLx=fDDLց?AHcMƉL΁ ? AHcM4A9D~AN˃?A<xM˃?#uM~˃?#n;Uu$ у"f.D?D AD։L΁sDA/ID$EAD$A$H[A\A]A^A_]HEHxH5nܪI}H5^̪I~H5N輪f.fUHAWAVSPHI;uCL{;CtgAAF:9}iLH;uCuAN:9|AF u F;Fu]]'UHF;Fu]]UHAVSH HIF;FuLHvqLHw\H HcHEIFH@PHEEEtEE>EE.C=~dLHT\CEEHULH%HCHEEHEEHuHULC= H [A^]ÐA]m}@UHAWAVATSIHI tC toA?uAGuAN:9|AFuAFuAO:9|AG<[A\A^A_]IH5- ˦f.UHAWAVSPIIAH u1IIcVHHA8H~Hʃ?H5<xLL1Pu-Hʁ?1?@ ։0AFtuA~thILA8f.@HcA4:Du؉Lȁ?AAFEFAO AO$AtmA(t`IHI8Hc׋4:DuADAL=s/?AA0EG(AFH[A^A_]IH5UHAWAVSPII IH@8IcO?AF 1@ ƃ"LE~(AF(LAA5ILA8fDHcA4:DuANDELLLA>u8AVA<$t49~9uAw:9|AG<uGAW:9}9u"AvuA:9| AGt79~;uAu:9|AE<uIAU:9};>AWA>uAN9uAu:9|AE<uAM:9|AE<D LAGA IEH@HIcM UԉTH[A\A]A^A_]f.UHHH@HHcO t]f.UHAWAVSPAIBHHiQHH$H?D1Eǁc  ރ+ ƃ+L.LAE~H߾m:HHD AH)AyLH޺QHH߾=LfAHt=EtH߾LH޺HH߾H;HH;Eu5DHĘ[A\A]A^A_]H5tDžLH1Xh&f.@UHAWAVATSHIH,;HHEؾ蓅1MuL,IƻsLIǃLYLu)躄L1D] LH肕qHXL tuM9t"L*uH5wL1eHXLD HthHLLLHLNH*LH :H H;MuHĐ[A\A^A_]L'謼@UHع貃]f.UHSPHm H߾НuH蔓H[]UHAWAVSPHA#IH߾ H߾D.HtHHH߾<E1DH[A^A_]fUHAWAVSPH IH߾D H߾D贮HuHH߾{H߾^ IH߾ H߾DiHuHH߾0H߾蓃tHeH߾ H߾ntH@H߾H߾DE>1H[A^A_]ÐUHAVSH IH߾7 H߾D觭HuHH߾nH߾D^HH[A^]fUHSPH H߾ H߾}H߾aH[]DUHAWAVAUATSHIrE1MuL IAA_LC]AwL1 IL޺ ALD1 HELcf1HLrQD{HDDLl9AOHADL}DiEDNHHHEL|1HEE1E1HiLعt M9]uzL1蘙LH(Lع跡H5 LxHLLwLjM9]t"LzuH5bL1PLؒLLzLLaLHuDD1H[A\A]A^A_]f.@UHAWAVAUATSHIH4HHEоA1MuLڌIƻDkLDc IǍsLU HHHPLDL'L {M9t"LxuH58L1&ALL`yHPLHHHHu LzLH誎H3HH;Eu:DHĘ[A\A]A^A_]HLDAH3HH;Etcf.UHSPH}ttHH߾0H߾zH߾&H[]f.UHAWAVSPHH߾IAH߾aH߾DHtHH葍H߾yE1DH[A^A_]f.fUHAWAVAUATSPH|E1IރuH߾荊IAEoHD1IHt)A1I9HDdHLLDHD|~HD{H[A\A]A^A_]@UHAVSIHH0ع貔HJH߾=u(IcH EH4HbAv(H߅x ҋ [A^]膋H߾11E1[A^]~UHHAAELG A@BtI@(HG(1EHEHEȉ]f.DUHH]UH勇]@UH勇]@UH1xEHO H`H9At H9tAAqHIH9AA}uEt HJx]f.DUHAWAVAUATSPAI uIE IM8HHx8HH8H)HP8Ht*H^xCBMcuIL#II9] tqHK1EqIExFH@HxD1;A} t}EHLc HHxHS(H+W8HD:Hu#IM1E~1H L)HL9|"HkIK 'HIUIEA} uIM IU8H1Hy8HH9H)Hq8H[A\A]A^A_]AHHS HHII H)H)D9~HHDHHH1A} t@UHAWAVAUATSPAI uIE IM8HHx8HH8H)HP8H^xCBMcuL#II9] tBHK1EBrEHLc HHxHS(H+W8HD9Hu#IM1E~2H L)HL9|#HIK 'HIUBIEA} uIM IU8H1Hy8HH9H)Hq8H[A\A]A^A_]AHHS HHII H)H)D9~HHDHHH1A} tUHAWAVAUATSHHHI uIE ME8HHH8LHL)HP8>>uIMHHIME1L{xIAHMuLE1ۊL]HuHKHMHK8HMLvEL%EfAI)wIcLMt A{& H5Hs HC,H?Mt:AGBt3IH HQHJHHt IG(H+B8HHHH C(aMt4AGBH aHEo uIGpB@HCHi1HCHCMt>AGB$ C7Mt4AC C4A{&t)IC@ C6IC@ C51C7C4fC5ICHHhHqHH HDHs H(K,@,C0HqH eHDHC<H}L]SH ǿHL@upHHp(HHxHG8H)HHcDDEA?AJ#HwHcHE1HHAMIEJHHHKHSAԃAAHML]HCHpAAAAAAwAlELuLf HtIEHMIEA} uIE IM8HHp8HH0H)HP8LL¯HHEHtx&uIE@HIE|H@LxHL%pIIEL @EIEEEHEH@x~:1Luf.IcLLLnHHEH@Hc@H9|ًEHH[A\A]A^A_]4++++++X++++++++++++++++++4+++++++++++,@ddd d/$dddddf.fUHAWAVATSIIH׊IHLyH5HLLI1f.DUHAWAVATSHIHt,)@)P)`)p)e)m)u)}H H(L0L8Lc HCHx~H@HHEHEHEH0HEHUHLUAD$BII$HHHHAHHqhAHt"IT$(H+Q8HHHH D@DHMH8cHGXHH0HHHL5ֳLEHH@DHMrH Htj8cueMtlH54LH (H(HDHHGXHHHHHRHEHMHHRH 7HEHMuH6HG0HTu HHHHMHHDzH[A\A]A^A_]fr kkWWllWWWWUHAWAVSPHHXHu;Ls@s IHxXu9IL{tEudIKHHHHQHPHC@IxH5HI@@AG AGAIL{HC L9xsLxHA螟fDUHAWAVATSHIIHDEHGXH@H@HGXHHFu HLAH@HCXfDEHĠ[A\A^A_]ÐUHAWAVAUATSHuIH_8LcMILcLHHLHM~DEIF8E9DD)LHLHt.I4HH1f.HHH9uI)Hr9M)IJ (H8DAAAH@IuEHMHHIN0IVIN@H)HIVHt&f.@HHqH)HHHHuIN HtLf.DHHqH)HHqH)HHABtHQ H)HHA HIHtIF8H[A\A]A^A_]@UHSPH=AB};HKH+K8H=@B@BL9LAB}HH[]H߾H߾CH5H1@UHAWAVSPIH_HG HtfDHHH@H9HBHuI+^8HCKI=6BA6BDLAAB|L :B~2LJ:B"A E;}LDH[A^A_]@H[A^A_]DUHSPHHGHO0H)HBAB}CH+C8HɁ@B@BL9LH߁AB}%HCHHCH[]H߾XCH5H1-f.UHAWAVAUATSHHHHELMHHCL{ H{8II)MoPxL}HK0H)HOU=ABHHLH=@B@BL9LH߁ABHCHHI)H@IGƃAOBHPHAƃHC8IMoILcAgBHHH;EuHĘ[A\A]A^A_]@H߾CAH5RH1UHAWAVAUATSPAIHIDn@t,tM+f8L]Mf8HCHH(IN(HCIcH IF t$Et3Au7EDAua1EuL%A$E9~EDA1f~DfA[1ƃ1f.@AD<D9A<9HH H9uߨt HAIc1HHINH[A\A]A^A_]E1Lǃ1f.@ADDAHH H9uߨt HA41E9EDE)LHHIt3LHH1HI1fHHI9uI)HL)II4H8FFFH@Hufǃ1f.ADDAHH H9uߨ'HA41DUHAWAVAUATSHAHIA@Bf.@HIOC?&IG0I+GHbIGI+_8Hx~L.AABkIGI+G8H@BAM9LABLLI_8LH޺vHIOH95DAHQHH9wIODmHL`MwIG0El$ L)HIL9HIGI+O8Hx~LLmI7-LLmA=ABHMIOI+O8HD=@B@BL9LABWLL]M_8I)IANA|$ AD$ LeCMg1ALcLHLHMI)AxA9DCI|$IAA$HAD4AEIAtdIY(LHH޿IWHJIOCCIOHQIWCH H >HHHuAt!IwH^I_HA9AD9D9s~IO)ƒt1fAH9u)ރrH)DAAA(A8AHAXAhAxH逃uIOIG HXHTI_ EfC@LLc IMLkMoHEH@8HC(fCBE1APHHC(HCE1@BtH@(@?%u fCB"LHC(HHHL0IG0I+GH=OdIGI+_8Hx~LP*A=ABIOI+O8H=@B@BL9LAB~LI_8IG L`Mu L>IMg fEl$@I$@IGID$fAD$BAtL1LAIWHcHHH)LL\ADH[A\A]A^A_]A9D9ANIWD)~t*1f.DBH9uDrE)fBBB(B8BHBXBhBxHꀃuIWMcIG HXHLL IHHLHL1LCH5L1UHSPHf=r t*=s4HuHfH[]H5ٿH1H߾fUHSPHff=r t2=sI@@HADIE=fADžfADžH5BHULEԃtÃMe MofAD$BuMd$MuQMu8Mt$8LLtu1IEHLH54I@@AF IE@AIMuMe AD$B$AfADžLHHH@I9LBHuM+u8IAFANIB16B6BMAAB|LA:B~'L7A:B A;} L8ID$(ILH5HUÉEԃEw|rA] Mut%uGIEHI@@AF0H5߼LI@@AF] AFAIMuIE LpfEfAH[A\A]A^A_]f.DUHAVSHHcHHHWH)€ tNLs C HC8IF8IAFBuQMF MtIV0H߾AЉHSHHH)HL%HHHֺ-t^]H H1[A^]H[A^]fUHAWAVSPIHt]6I^ CBt%fCBHC(If{@uIFH9CsHCHS0LS IVHcHHH)LHI^ M~`L9u-f.DL舗LPI^ L9tkCBuߨt%fCBHC(If{@uIFH9CsHCfHS0LS IVHcHHH)LHeI^ L9uH[A^A_]ÐUH1f]f.UHfuLG G IH+G8I@8A@Bt1]HGH9u=H51IH HtIP0HGHcHHHHIH51lf.fUHAWAVAUATSHIIH_ HHEȊEDL Aƅ Mo8LL3AtAu2IGHH5xL&IE@@AE IG@AEEIMoI_ AfEHtDHCH[I9LBHuM+o8IAEAMIB)=6BA6BDLAAB|L9A:B~)LvA:BA E;} LDuHEIDH[A\A]A^A_]UHAVSH`HfHuHUHMEHEEHEEHEWEHOLH+O8H5HU AHuHUH1膇HEHEHuHcUHH1eHuHcEHH@H1KHuHcEHH@H11fDH`[A^]f.UHAWAVATSHIH>H/sEAL{PAtMMtLtHtoHSHK H3LCXLEC@HGHHHOD L{PAuMtLbŊHt2H3HSXLkLH[A\A^A_]> H5HٶH5նH¶LL1賥LUHAWAVATSH0IIIHH}HUHMDEH5AԉEESu8HuغHLAԉEEuH}HMHuغUEԅtjEEEEEHExVH(w@HMANM؅uH}HMHuغUEHUL19EH0[A\A^A_]H}HMH5UEEtH}HMHuغUEEUH}HMHuغUEE6H}HMHuغUEEH}HMHuغUEEH}HMHuغUEHExVH}HMHuغUEH(w@HM؅HuH}HMȺUEUHAWAVAUATSHIIzEAD$uI<$IL$HuȺAT$AD$AN(MȅAN,MȅAN MȅAN Mȅ8AN MȅTANMȅpA^]M~hI9dM[AA_ HH]HEAD$uf.A$9sLI$uAE$H[A\A]A^A_]f.UHAWAVATSILwtAFVANULvuBAAsc<uAFUIvXLIF`I_KUtfL{UuI_CUAArf.fLCUAsI_CU<tL{UuI_L{UuAFVIvIF(HH(\(HHHIcHH1HHH9HNIvH)L[A\A^A_]>f.@UHAWAVAUATSHAIH_HKXHHHHHCXH ʀP SUwSTʈP HE@@EHuLVEHHuyEDkWAƇCWIOIGE@IOIG HQ IWfHBI+O8H5L1E1WIO faBEDkWEtuH[A\A]A^A_]Ãu6IGHu HPHHYH5]L1LUDUHHwH1]f.fUHAWAVAUATSPLopAMAE €AU !IHpHc HIE0IFpIu(H F IHCIIu(HfoIEIFpIuHtF tLA} 1'@f.@HAE H9CID HtHHPH9tA~UuA@tH1F tLJIMHINpINxIMHMnx$AE I]8HIEf.HH9C@tH3F tLIEIEpIFpIE`Ht@ tIE`IuhHtF tLAEE1f.IHcHI9}rIM0@tHtF tLcAEIEIFpAE I](E1IHI9@tHsF tLAE AE~GE11f.DHHcIH9}!IMXJ49HtF tLAEAM ~41HHcH9}!IE@H4HtF tLAM AE$E11HHcIH9IMPJ49HtF tLAAE$H xA~U@IcHIE8H9sf.DCHH9rM9mPI}@IIEPMAM AEAEAUAU ȃxH 1HH E1F tLdMtfAGuZM'ILkocILv_cLH t.Ae MvHIIE0MI]AM LcIIAE t\E1f.@IHI9s#IM@tHtF tLAE I]L9rrH L9sfCKt=@tHsF t LVC@tH3F tL>f.f@tHC@ tC H L9rAE I} tAM HcH1HHH8-A~VtLIcHAM H HHIF H[A\A]A^A_]AM 1A} Àu:A~UeIIE0MNLL4>M}LcIM 1I M9sAAGt@@tIwF tLuAG@tȃI7N u'tL모@tIG@ tAG 딻uIFxIE0MnxlWf.fUHSPHHHtF tHHHtF tHHHtF tHHHtF tHHHtF tHHHtF tH{HHtF tHaHHtF tHGHHtF tHH[]'H[]UHAWAVAUATSPIIH^N LcII܋V c1A1f.HIH9s)IMB9@tJt9F tLAU I]L9EEf.H L9{tf.fUHAWAVAUATSPX @KH)XAIIHHHELKLLucLL AAL L H11AH"HH;EDHX [A\A]A^A_]H؍pHY{LsHA@HHD>HDuc~HIHLL LLEHLL|KHHL蠟E1Ho1y1ɀ8*"GH ZHcHHL1LdKAʼnLMHH5e!E1AAA@HHHX Hs HLJHH= tHǞA\HL,ADLDžKHL JL53@HtSAGHAO~!IHHIwLHÉwADII uA \uC u>HH;rHݕHHHPH H4 tHH1HH ϿH H;MuH8 [A\A]A^A_]BUHAWAVSPIG1ۅ=1L=r=BAF=AD>IcN HQAV ADI>GHO~HHHHAF=r{=wt1L=*f.DHHHHAF=w?AD=t5IcN H#QAV ADI>GHO_AAFH[A^A_]fUHSPHHuq趎H8rCH߉H[]鮌f.@UHAWAVAUATSPII9AA/mLH54wAE DA9tuLILރu/ L1҅tLH5vH1A@HU跐EtHUоHLAH;E1EuL11(H[A\A]A^A_]fUHAVSIH4puHHxuH5pL1H;@1@L1[A^]鼊f.fUHAVSIHoHxuH5oL1蝇L5=|HoLXCHcLL1L~H5Lz[A^]UHAVSIH4ouHHxuH5oL1H3L[A^]6fDUHAWAVSPIHn"HHxuH5nL1视L3HzoH LYL1踐HcHlLH?tL11H[A^A_]&L~?LHH[A^A_]UHAWAVSPIH!nbHHxuH5 nL1L;H L1螌ú LHcH$lL1H<@1@L1H[A^A_]d@UHAVSHHmŊIHxuH5omH1JM6H߾*HL[A^]fDUHSPHH%mfHxt3H8t-HmH߾EHHHMH@HEH1H[]UHSPHHlHxtHH5mH1H5kmHJH[]f.@UHSPHHel覉H HHHCH5-mHH[]ÐUHAVSHH5>jůHHjH5 mH;IHHMAF H5lHIHH+AF H5lHIHH AF H5lHձIHHAF H5lH賱IHHAF H5xlH葱IHHAF H5MHoIHHAF H58lHMIHH_AF H5|H+IHH=AF H5kH IHHAF H5kHIHHAF H5kHŰIHHAF H5hH裰IHHAF H5LH聰IHHAF H5YkH_IHHqAF H5;kH=IHHOAF H5kHIHH-AF H5kHIHH AF H5jHׯIHHAF H5KH赯IHHAF H5jH蓯IHHAF H5jHqIHHAF [A^]fUHH8H5i1]VH H H8H5iH1]V]f.@UHW@UHAWAVAUATSPIH8IT$`AL$jIM|$8w6I\$HHKHSHqH9v=H?H9r[H5iL1H5iL1VqHIH H VH5hLH=L,H3LL]6HLkHKHqHsI|$8ID$HHH5h1UHH5$iLL1UI|$8DUHAWAVSPIH_8HIHCHHHKL0AN@HIwPHSHHxtLp @HCHx~HHCLH[A^A_]UHSPHFH~8DF !HV@HF0HHFHN`H5dCHChH{8HCHH0HP 5HKHHHA H[]UHSPHGO G!uHsH*CH[]HC CC !H[]UHAWAVAUATSH8HuIHٲHHEHGHHEHGHH@Lo@H7AHHGHHHOAE7AN !Hc HI}H/stAf.fI}H/s+tA u5HHsuI}H/s*al0HHsxI}H/s}ClHGHHHOH?A{ HEHHKHSHqH9{H94 L4I8H3L+HLsHKHqNHGHHHOAHcH YD> ?EE'I_HHKHSHqH9v_H?H9 L<LuI~8H3L*HL{MHKHqLu IIvI}H/s/'k5HHsD$I}H/kAHGHHHO0LuA7HcHHXDuAHEL0INIVHyH9|H?H9 IH HMI8I6)IHMININHyL:HGHHHOD E'IcH &XD8 ]D}>AAHEHH@I}H/HGHHHOAHEHHKHSHqHsH9vOH?H9 L<LuI~8H3L(HL{MHsHNLuf.HHKD$0|HHs{I}H/s fiHGHHHOLmAHcH "WD =HcIfDLE?LpHINIVHqH9vEH?H9" L$HEHx8I6L (IMfINHq f.IIvD<HEH8H/shAf.@HGHHHOD L}E'IcH OVDt'HD<HHIH&=A}m HEH8H/s%hHGHHHOAIGHLhH}H?ALuM)IDHHsD<III~WE>HEHHKHSHqH9vH?H9L$HEHx8H3L&HLcHKHqL}LmLu[HGHHHOAAGHAOA =6 II~@4I}H/sIgLAHGHHHODLuD$FAEIcHHTDuDHEHHKHSHqH9vCLEH?H9L4I8H3L%HLsHKHqLuLEHHsDI}H/sLMfI؉HGHHHO0CE$@AA7HAHMH HA HHsD4I}H/seHGHHHOAI_8IGHH0HPHHHIHCHHHKL0AN@HIwPHSHHxtLp*-,@HCHx~HHCHEL0%Lm@+eAE7IcBD HEHHKHSHqH9v>H?H9-L,I8H3L$HLkHKHq HHsD4HEH8H/tHGHHHOD0E7IcBD lI_8IGHH0HPH軘IHCHHHKL0AN@HIwPHSHHxLp5HGHHHOA::I}H/?cDHGHHHOA>>=I}H/cHHs.I}H/BcA.LHcHZQ.D&HHH;ELHuH8[A\A]A^A_]HGHHHOA~=I}H/p cuHGHHHOA==I}H/TbYHGHHHOA//hI}H/8b=HGHHHOA<<='I}H/XbHGHHHOA.I}H/%b[H5`TI}H/PaUI}H/jaoHGHHHOADvHGHHHOA ZHGHHHOA>HGHHHOA"HGHHHOAHGHHHOA.I}H/a@HCHx~HbHCHEL0$A~AN {HGHHHOAbHGHHHOAIHGHHHOA0HGHHHOAHGHHHOAH ŝH H;MH8[A\A]A^A_]H5RaH5RL%E?AHEHHKHSHqH9vKH?H9vAH5RH}1H5QL1 H5`RL!H&L4HEHx8H3LHLsHKHqHsD<HEH8H/sO_HGHHHOHMH5ARH}%#HEL8IOIWHqH9H9%L4HEHx8I7LIMwIOHqZAHEHHKHSHqH9LH?H9L4HEHx8H3LHLsHKHqHEL8IOIWHqH9\H?H9^L4HEHx8I7LGIMwIOHq!AdHEL8IOIWHqH9H?H9L4HEHx8I7LIMwIOHqHEL8IOIWHqH9H?H9L4HEHx8I7LIMwIOHqwIHEHHKHSHqH9H?H91L4HEHx8H3LHLsHKHqYHEL8IOIWHqH9MH?H9L4HEHx8I7LIMwIOHqIIwI}H/s&Z\.HHsD$HEH8H/s1;\9HGHHHOHMH5!OH}%HGHHHOHMH5OH}%IIw IIwD$I}IIwHEH8H/s[HGHHHOHMH5wNH}%HHsD<I}H/s"f[*IIwI}H/s1K[9HGHHHOHMH5_NH}%HGHHHOHMH5MH}%$$=d40NJ~~hhhq@UHSPHHw(~C H[]@UHAWAVAUATSPID'H_HHKHSHqH9v7H?H96L4I8H3LHLsHKHqHHsD$I@H/DesbVA1ۃ=t"HGHHHOA1ۃ=1I?VA=MgHIL$IT$HqH9v5L9~L4I8I4$LI$Mt$IL$Hq@I$It$=I@H/rHGHHHOA=1;E1ىH[A\A]A^A_]H5GL1]f.UHAWAVAUATSHHUIIH?E}AEEMeHIL$IT$HqH9v1H9 HI}8I4$HI$I\$IL$HqI$It$D<I}@H/sTLeA] u%HGHHHOLeA] t I}@H/swTAE uHGHHHOAE t u9t*I}@H/s H[A\A]A^A_]H5CL1MHSCHHDI}8H5ECM1U/LHƺ!DUHAWAVAUATSHHuIH?D'H_HHKHSHqH9v-H9$L4I8H3LjHLsHKHqHHsD$I@H/sPAE/L5MCA0$HGHHHOD(E/L5'CA0D xI_HHKHSHqH9v7H?H9rL$I8H3LHLcHKHqHHsD,I@H/s ]OAHGHHHOD(E/L5BAA9t/HGHHHOD(E/AA9tAFA9)I_HHKHSHqH9vAH?H9L$I8H3L HLcHKHq f.HHsD,I@H/sNAE/A-u#+HGHHHOD(E/A-t A+I_HHKHSHqH9v8H?H9 L$I8H3LR HLcHKHqHHsD,I@H/s MAHGHHHOD(E/IcH ;DulI_HHKHSHqA.H9H?H9mL$I8H3L HLcHKHqf.DI_HHKHSHqH9v;H?H9L$I8H3LU HLcHKHq@HHsD,I@H/DHHs.I@H/LAAAA9H9v3H?H9w}L4I8H3L HLsHKHqHHsIGHH8Hu HtJ}uHEHMH#EHE"H[A\A]A^A_]H5`>L1H5b?L"UHAVSHtrH1H5H1l:HdH?H߾p:H@H>H߾LIHL7H>H߾#IHLH>H߾[A^]fDUHSPHmH߾t1HHHLHq\T :HH[]fDUHSPH=\< HPH[]@UHSPH \$ H H[]@UHSPH[E;H߾\(E HH[]fUHSPH]tH߾,BH߾m[f: f.;r ;f.vH,HHXH[]f.fUHSPH [~ H H[]@UHSPHZYU8HH[]ÐUHSPHZH HH[]@UHSPHHU}t HHH߾ZHQH[]DUHSPHtH߾BH߾ Zf: f.9r 9f.vH,H"HH[]f.fUHAVSHHxtMH߾gt*H߾E11A>*4L@HIHO)H߾عrHLH߾ZH߾LH߾ XHPH߾lH߾A>*VLLHtE1HH1E.HHA~HHAD[A\A^A_]fUHAWAVAUATSP( PH)XMHIIIHvHHEH P;t*LLHL\IAE<;uf.IAE<;tL;IHuL?IMLL)LLxML1LHH~ L \HLLyHH5 HLH5-H1L諼L.HBNMAE<;HM1H@uHH;Eu-HH( [A\A]A^A_]HHuHH;Etf.UHAVSH1 HIH,H߾ع#H߾LuH5,HL1 [A^]ÐUHAWAVSPH1GIH|H߾׹H߾1!HH L?HLHlIHHL1]H߾1IH߾1H5v,HLLI1H[A^A_]>H54,H H1>H _ L HL1IHgHLEH[A^A_]DUHAWAVSPH1wFIH*H߾׹H߾1HH L HLHM9vtAF.fA..ILL)IHLHLH߾ {H[string IAF"I IM9s,Hu'LHLMMKHLHL6DII)HMDM9MGLHLfC...CD..O$.IAD$fA$"]H[A\A]A^A_]ÐUHSPHoEH1 vH5wH1?H[]fUHSPHfHnfb f\ f(fX^QNH聶H[]DUHAWAVAUATSP H)XIH"\HHEHHx.HLk~L01WHLxI߀;!HH@DIHMH5H{ƅ%HL4L9LLL)HHHqH L9J<%H0HHMI)M~WAaAL=O<|u AfDHLL}McC/tMM9}LLH5JH1LHK$_fHH; H/HHHLBƄ-LHHHHLL9H2LHH@wIMH5L1$L1 ELLH vYH H;MuHĘ [A\A]A^A_]&f.@UHAVSH-IH߾-LHH9[A^]f.DUHAVSI11+HHGLHt [A^]*'[A^]f.UHAVSH H߾u蚫E1A 1-IH߾xtHKHu1[A^]DUHSPH1K+HwHHزH[]f.fUHAVSI1 +HHG1@LH[A^]%UHAVSH1*IH߾1*LH1@H1[A^]G%UHAVSH11)IH'H 7sH߾(HH a  AA LDuH5sAL1EH5XLzEH5BLl^EH5LtLƧALVDuLuLHLLHLH賮HH[A^A_]UHSH(HHETHHE)EH}.t/HuHڮH TH H;Mu(H([]H5\H1H SH H;MtUHAVSIHHc6HH߾IcvHۭH H߾ǻIcvH軭HH߾觻Icv H蛭HH߾臻IcvHHwH|H߾cIcvHlHPH[H߾IT$,AI~8IIt$ L ADLID$ IN0M~XSHL,[J4(BD( Y:B\(B|(AT$(HAX AG9L]}DMo f9}.IOHcHRH I;MuLLL]AG9|MHELPECEH:D)HxLoXAuA8x HLc`4HYPMMEAAӉD)t)K4aHf.HVHH| uArTK aHf.fHQH| HDQH| HDQH| HDQHH| D9wHEЈP:L]ȈHA6A .A &AAAA A H]LmLeDDHX;E~dAEEL.~I}0DLoHTXLLuLI}0DLLDE A߃uH]ȸDH]HK8fH8[A\A]A^A_]HH5HG{(HsHL15{)HssH{0LgtLkHYsH{0H}LmLL-A?uFHshLmLLH{0HuHEEEHULLLm HLpCZx(.t߃:Hr{$LsHrH{0LtHEEELLLHLDu*[t*{t=%ukLLDHLDVQLLHrHL1H{0L{]u7HqLLL H8[A\A]A^A_]H߾$HH߾];H5EH\oD9su H߾)L{8H߾)nIH߾(nH5LLHDE1HHofUHAWAVAUATSH8IHLw0En<$u,LcHqH{0LHEEE7HpLeHL1H{0L{]HpDmAG {=ueHpHuLALmHL1>IGXLL|L DAGEAFt!LLLIFA AF[A\A^A_]fDUHSPHHzuz H HHDHH{8HN H1 HHf.DUHAWAVATSAIH0MfXID$HcH [t@:rrltRtAL$D9~EHH@f.IL$HHT(HTDIcL$HHH9|AL$[A\A^A_]HH_Hc4HRPH[XHHH4{HL2I~8HHL IH5o1 LHUHG0gUHAVSHLw8fH5LH1ɽHHff.@UHAWAVAUATSHHMȉUAILg0AD$:AD$:AL$ I$It$A|$4HRPHvXH6HcH^HLHcH^HLHHFHLA}ELhEDuLt(D˩EEAD$:EID$H@XH(M@EEID$HEHEID$I]0K:u@K:tsDC HHCHRPH@XHK4@t)HcHXHDDHt1)fHcHHHDDYHcHXHDDuD}LGM}0EAG:EIGH@XH(M@EEIGHEHEIGA L8AEDwr uLLbLZL]ԉ轨}tL'UйRDuBL)D}D1DE¦LDuDAL*D LƉۨLDPHH[A\A]A^A_]L@UHAWAVAUATSPAAH}Lo0)ӋPs1CE1DILHDLA|@ALDǬ/t LH~EuIGHp0HcP@HmHMLHULHX0@8LpHH HP(L0LxH@H5.HߺTH[A^A_]fUHAWAVAUATSP"PzH)XHHHHEHIHH߾IH߾AAHHH߾HPALXAD$rHbH߾HH^uIHHHHHpH@DžHL(HLH0LH8H(1E1L;DAIHHpH IL뀽^H(DL;P7ƅLLL;HIH9ILH@HXHH߾C?LAƹDDMDDH@DHt5EL(t!1LLL+A9uHHD1E1|dLLfL;0-HH;HHLL&HXH(HHuHH5C1軿H@HPHOHHx]HHxLILL)Hh1L`3f.HHqH HH;xLA<%}ADHH D=<%tHH5y%1HH;rLHA HHpH eHH;<L?AHf.@<0uLLHh H(LLM)MLL14L2:LML`9LMLLgLL)HL'M!HPH+(HHHLH߾PH߾EH߅t;?uHH߾u_HHHH;E HĘ [A\A]A^A_]HHPHDHP8AtHXMLHPHlLt"ANjtlD$CtH&jfHHPH~5HH;rվHHf.DžtHIcMIA]A LcDH HcHHx4HIǃ7 HHHI9|I9|HxHD`HLȿHDBEADHcD<( E퉝piHzHJHLH2HxA݉dHHÃ( HHHtHxDHB=D`HLHEDHc҈H|EHrHzHrHH9u\HH11\1X\1X\1X\1X\1X\1X\1XHH9ubHrV1@DDDDDDDDDDDDDDH9uLDHJHHLf.|:HH :HHL:H \:H >HHHuHMt&I)II1f.HAHI9uH p|4My/Et HHIcȍrH)H<HeLEc6 ==@UHAWAVAUATSH(I1۾1莳HELuHHM81L}LHEȀ8t{H}HHUHMMAHcELcmIDmԸL)H9wAAu fLH謩AAuLH莩yLH9H([A\A]A^A_]f.UHAWAVAUATSHxHHmHHEо1育IHpHUH߾gHEH߾aIHEMII9vHH߾ԨH`HHhA>E1H]TfHEJ4(hE1EAHDEHH8ELmHp8EULH`LHpH|LEALcm|IHcHHMJ)IHH]r HELH;EvH߾HDH߾HF肧ENAXDH HcHE=HEJ(h EOAT$AWD1@3D5H9uH .HD)H2HEJ4(HHUE7DMHEN4(hHLLeDE1_IIK,H;EvH߾H9ۦLuHLLY7DMTHEN4(LEbHcH}LH+7EIIH]ECED$DHEHH (H1HH9H9uHAA}A[t+.%HE0ALkA^EEMLDeID$ @8taIHL9AL$At$%uAu4ILDfD@-uIM9s@8vLLA8<$rE51@8u?jI|$H5B1I_M9l$ FELeLmL58t-?wHLHuHH H?H$HHf1r+HAT$$9}HHI\0Hu/I|$H51GHHHI\ 0IL$L)H9HI|(LHVMIIL;I_HH9wI|$H5Ȑ1͛AE:IIL$I9AW@18@IL9uA]8uuIIL*v+i-rLmL-IAD$$HHLH H~cHH9HIufA)IA\$$H rI|$H51ݚHHMl(ID01LeI|$H51襚HcHLI+D(ID0LLLHulIH0HYIA\$$H rI|$H51JHHMl(ID0CAD$$LLL/HuAD$$1AD$ H8[A\A]A^A_]1M;l$IDIM9l$HSE1LHULm+1D8LmK.HII9D$D(A[t.tу%uHE0DHUA^EEMLDeID$ D8tXIHH9sQAL$At$%uDuCILHU@-uII9sD8vLLE8,$rEELe"EHUHSLLHUHH/1D8MILLHUH{M9l$nMEmA[t.t%uHE0DA^EEMLDeID$ D8tOIHH9sHAL$At$%uD~u&IL@-uII9sD8wLE8,$rEELeE1LmHMK4.LHIHtf.UHAWAVSPAAiOH HcHADHI#D<AyDH'#D<1A&DH \< AsA,DH#DH5[¹1芑AF AFAAAи wWH1f.HQB= H rڍHrI>H5¹1AA7A1)AЃ /A]AAи wMH1HQB= H rڍHrI>H5 ¹1:A1Aи wUH1fHQB= H rڍHrI>H5¹1ʏA$AI>H5P1衏H[A^A_]A1H1ҍHQBЁ H rAuI>H5dž1;똓F Wao5''5tUHAWAVAUATSHAHuH}ȃL~)FHt(H1H}fHLH H31H}+D)H1H}DHHc4H HA!Et"AADHLH)AuHH[A\A]A^A_]E1HADIEEDtMADIM9tB'A9tH}H5D1MEM蟌H}MEMIL5K,HIH^C,HA9tH}LD1JH}ĐUHAWAVAUATSPIIIBtu.AF 1I$H~H9wt AF 9LL HII1LLFtIML}Ѓ{ uAD$@t IEI;$tHcCHHL<L,I1LL>FLtM+~IAF B89s2Iv҉HHHHf.>uDHHH9rAN )19}eINHH|9u)9|AЃI$AD$INHHDA$IFAD$H[A\A]A^A_]H5TH}1DUHAWAVAUATSHHAIH}Df H~ t AM EIEHEE9rEIEHEE9IuLHELHH}@IEAM D9D)IIMHt3HHH<HH1fHHH9uH)Ir9I)HHH8fD@@@H@IuEu Lm]H5HUH}̡E9Eu DHMLuf.HIM9I]HH|tHLyAU HH9rJAM D!HHIE"f.DHcHHHHHtxuL9xuH;ruL}ELLHULM9\IuIHMHLL?IEEȅL}ЉLaHHEHMHHL5 o f.CIHI~&{tLH L9uLLHLHuHU1>HH[A\A]A^A_]H]HLDH߾5DUHAWAVSPAIHvAW HDHH%>IGAO D9s})IIIHt+HHH<HH1ҐHHH9uH)Ir9H)HHH8fD@@@H@HuEw H[A^A_]f.fUHAWAVAUATSPIH~NAAEԉAMIL11L)=EEOHCH@@ADHAtSHHHڹ1fH{HD78D7(H{HD7XD7HH@H< HHHutHCHHDDEԈC LsHnHCC E1Ls H[A\A]A^A_]H5e~L1UHAVSHIHBN H9s HHFKN Љ!HcHHF"f.DHcXHHHHtxuH9PuH;uHUEHU4AH[A^]@UHAWAVSPIHIHHH;t H[A^A_]LHLH[A^A_]fDUHH~ tN ]1]fUH8 f@ H@@ H mHHW@ ]@UHAVSHIH~ tK HsHcHL1:HsS HL1:8LH1[A^]:fUHAWAVAUATSHIIHHHEЋBHHtuYH5|WHPL15t!HPH(Dž0L(AEf. HHHLLHIƃxMz MIB1f.IH9IHIR HYA|HuIvLL9HHc@HHL9uLH)HHAfAANALfAA~LHtLL)H)HADAFAFML@fWf)Ef)Ef)Ef)Ef)Ef)pf)`f)PEB E1ɺE1BPAII tAD9vDD9w219wIZ1f.@JH| 9vL8AJ LcLHHIE1E1DAAHItHIJ|t1<uH|H~H9wͅt$ILHHPE1H@xuBH@H8H~.H9w$tHLHHPAǸE111L8A9vaFPD9GGEDDA9v0FTD9ʉGFEDDII uEA)ALL։DMyLH@HIH;LLH IqIIcNHtHLL)HH)HATLHHL)HANIIEIFAEAFAE@tAB tIE@ t LLHdHH;EuLHĸ[A\A]A^A_]7H5wL1訌UHAWAVSPIF?wH HcHAN ׃1AN #I^H}7Ykg1f.igr ggf.vH,M1AN փHcHHEM~H>GAN !HcHLAN H#A HcHI^HH[A^A_]8L8UHHFO H9s HHG]ÊO Љ!HcHHOHTdfHcQHHHHtyuH9quH]f.fUHO #F HcHHOHcfHcQHHHHtyDuH9quH]f.fUHAWAVSHFuNO #F HHHGL5cHcHHHHHtgxDuH9puIVHu؃@EL}LFHL5K LIHL9srL]1AsuD)ƒv!BrH|1uAD)ƒw߉]LH)H4L_*fDHHOyMDIELH)HMIIKL9r̊O D!HcHHO!f.@HcQHHHHtyuL9Yuf.DLpAL^fHHHOIyt`IBL9rO D!HcHHO@HcqHHHHtyuL9Quf.DL]ÐUHSPHuH1H5H1蕏H[]fUHAWAVAUATSP8 .H)XIHHHEоL觌IHMHLy~IǺLHLLIHLL9}~L$LXHLLHI9tSLH LpuLLULH5 oHH1vu[LLz Lu.L\LH5nLHL1uH菃HHHH;EuH8 [A\A]A^A_]O-UHAWAVATSICLHL`LtuL~IH~M9~H.nLsL9|6fDLcLH\ LLHCL9HMLL1[A\A^A_]H5mL1[A\A^A_]tfUHAWAVSPIALƺ LzE~"DfLHHCHHIcLhH=LTH[A^A_]@UHAWAVATSI~HLCL~}IE1H)}n[IE1H)|YH=w]AALD&tGI9~&f.LHHI9uLLD[A\A^A_]H5lL1[A\A^A_]sfUHAWAVATSIL覈ILH}IL9t"M~ IGI9~HkLqLLM9}4@I\$LHLLKII9uMLhLL([A\A^A_]f.UHAWAVAUATSHI{HL{IL{ILb1ɉEąD<LCtRL t/H5kLnL!tL@LyLDtLDyLH)"D}IH%J;I9|HRjLHMoHMI)M9~HHjLIoLM9zLH)HE~n}~LUI1MLtLHD}AI)LLHEJ LD K,HIHEHD}xAtjAt$H5hH_DHtDAAt$H5hH5DHtAAHD[A\A^A_]HD[A\A^A_]vfUHAWAVAUATSH(HM9AAIf.A9%HuALLPELL=LLt$Lw LLg D6DH})dL}r+}t%4 HE1f.DA >ALLLLLEL}Lt:L LL LeЃf.fLL}LLLt,HUK LL; LeЃu"LeЃtfDLHULLuE~LLzLL}DEE9QLHU LH Et$LL+LLtlAH]?L3DLLAtD9uLH5d13k뱐AELHMALLLLLu@LALLOL E9sLH5dd1jf.LCLHURLHUAEHuA)H]AE)E9s(AVLHMADI)f.fAvLHMHuAED)D9HR"I1f%HLH DH HEH([A\A]A^A_]UHAWAVSPAAHtmH߾rAHDcAHDTH߾1E1m H߾`AH߾DH[A^A_]HDDH[A^A_]UHAWAVSPI1L=*f.J4;L4INHIFHL4HHuH[A^A_]f.fUHAVSAHH;xt[A^]øDC 1[A^]f.fUHFtu7HH(HHuI$H(H8HuBI$HH8Ht2HCDHxuu#HKHHH8HuHLxuPAGtIH(H8HuIHH8HHCDHxHsL+s8A$FAF HC0HC @BuHߺm HߺHCHK8HPHS@B1-HKHHH8H^H Lxk1H[A\A]A^A_]fUHAWAVATSHDIIIPt H[A\A^A_]ÍCsAu$AE(tuXLLL|tHuL@t#A~u AEHuLu H _LLLtH _LLL=tf.UHSPAHHOtHKAt u19H[]øH[]øH[]UHAVSH0HIH H HM t@t=u HH^HULuHEHuغH[H$E5LuMڃaf H}HuغR[H}SH}Huغ-[H}H}Huغ[H 3EM܁ H}HuغZHq}H}HuغZHL}H}HuغZH'}H}HuغdZH}H}Huغ?ZH}sH}HuغZHH}xVoH}HuغYHEf.JQKH}HuغYHu_uLHIFH@FLc}LˠHCH}H1HHH;EHH0[A^]H5\H}H59\H}H5/\H}H53\H}H56\H}H}H5\H%\NH}H5\H\:H}H5\H\&H}H5q\H\H}H5]\H[16H}HH5[H}H5[H}Wf.DUHAWAVAUATSHHIIHHEI\$hIHuк#XH1EAD$(IHuкXHEAD$,IHuкWHEAD$ IHuкWHEAD$ IHuкWHEAD$ IHuкtWHLcuI?LH11HID$8Et$IHH8WHFIHuкWH+LcuL}I?LH11ID$0LeEt$MHEIMDHs1H}DuE~&I1LIMXHHI9uH[A\A]A^A_]H5}TLiH5nTLZfhl llllllllllllll;@UHSPHHH?HSH5S1.H;ofUHAVSH@IHSHHEHHu"PHUHUHt:HtUHHUH(wKI~HuOHuyI>HUHu賃HHI~HuOHuMHUHu1$I>HoHHpHUI~OHuHHH;EuHH@[A^]H5RL>UHSPHUuH1H5/H1uoH5.@HHRH߾MH[]ÐUHAWAVATSHIHUؾ_IL`IHEHMHHL`HHEHx?HHH9MA$I(HG HEH@HxHHË@&H}LHË@EjH;HuIŃxTLuAF@tH3F tI@ t H}諌AAE]L;-1uH}LHUIHEAEAG @@t*AG t#H@ tH}LH[A\A]A^A_]CH[A\A]A^A_]H}HLHMLEE1H[A\A]A^A_]H5WFH}1JWHFH}LVUHAWAVATSIHIFt/u^AVуuPutH I;AFu(HI{ucD{ HLpxtbL`LHL^LHLYAf./L{HLpxuD` >f.fHL9L9HHHHI)III)HLtAH HH@H9sHH*f.f.zxIH HH@H9s5H*f.Z1돰f.0sLf.0v1H,H95f.0s'f.0s1H1 H,H94[A\A^A_]f.UHAWAVATSIHIFt3ujAVуu\H 4I;AFu0HI{D{ HLpxL`LHLIG fHBLLHڹIO fqBv`Af.?L{HLpxlD` @f.@HL9L9HHHHI)III)HL/t1ɅAH HH@H9sNH*f.f.zMIH HH@H9s2H*f.`1M9녰f.z.sLf.h.s11>f.`.s0f.N.v$H,H9>H,H914ȉ[A\A^A_]LHLUUHAWAVATSHIHFƒ?AO΃?9u2wIAH /HcHHE1I;AƒE1u"L#AG&IE1I9ALeЃtH;HLlH yuI f.HIHH9_ELumE1A;A>AfI~A&H IH9E1M Hy(Ht(G u"ID$H6HIHx(LH IH9E1MHyHt$G uID$HHu9IHxHG uID$HHSMD$LHHLAID$DpE(AE18AH;I7H[A\A^A_]Hk f: f.f.~+ x+f.L,AGH]Ѓf.DtHI?HHPIyuI HIHH9uSEI߃uqAWf: f.u/z-f.*r# *f.vH,LHAAAT$t HLIFLLW,EHxH@IF IEt IMMfLLFW,DAAEM7Ek2B;A;V v H}L~lAK,HH]A f.@ID$HII~7C'H}LH˰C@tAF tH@ tH}LixHxH@LuIFLEI AHEfB fAHUHHHH H%?HMffADAADAHEHDHt1AGI9u)AeIxAGAGAGAGAGAGAGAIu IHEJD HffALHHMHD L0DLH %HEHLA@HEA~EtNLHM4DLH HMHLA@HEA|EI>HDIxHEJD L0LHAA%HMHMELHDLH %HȁHLA@HEA~E I>L迷Iăx C@tI6F tH@ t H}uffA$IHEJt HfAfH@@cHNH9VLuLEEMLHAA%HMHMELHEALH %HAIMA@LEA|EQ I}LжHÃx: AG@LutIuF tI@ tLtfAfLEMEAAALLEHLMHIHADEDD t'D/AD$LHD褧LEIGHxMIMnULHM4DLH HMHLA@HEH3fAfAGA|Eu(I>մIxtfAfALuLEE1H}LIHLhMLHAA%HMHMELHEALH %HAIMA@LEAFgzAII~MLHAA%HMHMELHEALH %HAIMA@LEAFGZAIIIEMLHAA%HMHMELHEALH %HAIMA@LEAF A MLHAA%HMHMELHEALH %HAIMA@LEAFN AU MLHAA%HMHMELHEALH %HAIMA@LEAFEXApII7HFHdHLu%HHuL}H]LHAA%HMHMELHEALH %HAIMA@LEAFaM&AGiIpL}H]LHAA%HMHMELHEALH %HAIMA@LEAF M&AG IL L}H]LHAA%HMHMELHEALH %HAIMA@LEAF M&AG IL1mL}H]LHAA%HMHMELHEALH %HAIMA@LEAF" M&AG* I1 L}H]LHAA%HMHMELHEALH %HAIMA@LEAF M&AG I MMIAO< CD 1I+IADM$IAO4 C|  IIAMLLLMMIAALHLHIGE)ALDFHELLHfAfAIOHy LLHE9HBI_L`zHxHAIGLA ExHEHH4HLiLEXLHƃ%HMHLEHHDLH %HȁHLA@HELL}ID9tlLHƃ%HMHLEHHDLH %HȁHLA@HELL}ID9>tHMH HH4HLhIH HIA| IOIW LIHHH9LIM,IA|Yx(OLmHELh LHEH@H@@IJ HA`DqHMLaXHL}tfE J 12f.DH}Ht H6H| H97u,HH9V A|TAtT tHLH| H97tH}DBfLEIHEIEM/ADFE IE1%DHEHD KD= H@IM9C||Ct| tHLH}fLEMH]ALHxH+HHMHIY E1ADIAsBLmIE0I+EHEL9 LDBHELHELIIMeIEEJ B DHLH)AL$AV9EBA 1L Iw0fAfAOfAW fAWPfAO@fAG0I`M~AALDNHxHBLB IFHB(HHHJ(D MIAMANLfAGfAm@HIHLH9LuLEC51H;HLuLH yuI HE@ uLh`LuIFHxE1H}LILHM 1H}LLILIl= WI*AGA~T WI*AGA~LudL#AGLHL!HMHHEADLuDHIHH9LEELtH;HLmLH yuI HH9LEtfHIHH9LEoELD>KH;HLmL$H yuI HH9LEtLuML#AGLHL fDHIHH9LE ELt H;HLmLH yuI HH9LEtfHIHH9LEEL[huH;HLmLH yuI HH9LEtCLuML#AGcLHL1fDHIHH9LE3ELt% H;HLmLxH yuI HH9LEtfHIHH9LEEL[H;HLmLH yuI HH9LEtmLumL#AGLHHLuHUHuH I+f.DHIHH9LE=ELtI H;HLmLHH yuI HH9LEt fHIHH9LE EL;  H;HLmLH yuI HH9LEtw LumL#AG&LHHLuHUHu I1H?IN DHIHH9LEG ELtm ' H;HLmLH yuI HH9LEt fHIHH9LE EL;  H;HLmLH yuI HH9LEt MHIHMH9LEM& AE   MI}HL}L,IMyuI AOAW LAXfWf.Bf.=IADFLuIFHxHEHIFLnHxHAIFLA WI*LuAEB:WI*Lu^t?A?*tu8tHMHHHffAL}IɅt"HEHHH4HL]LEIHHII^L)HEHUHHHH D AHxH@IGMyAAGA~I>HHuJIy I HH9LE AAGA~I>HHuIy I HH9 1AADAAGA~I>HHuvIyk I HH9LEk [AAG_A~fI>HHuIyF I HH9LEF JAAGBA~IpI>HHuIy! I HH9LE! 9AfWTfAADMeu2I?HHuVIy I HH9LE LLLLMA D1LDD0D7f0f7HH H9uAtHffEE9LuDDE)HHHIt)HHLHI1HHI9uH)HgH)HLH8fAAAH@Hu-Z I>HHuIy I HH9 ' i I>HHuIy I HH9LE 2 f.AHMHJHHB0B8t EI?HHu\IyU I HH9Ei L  MI?HHuIyV I Q H9AHUH J HH HHF0F8WI*AGCkWI*Lu\WI*AGooWI*LufMMf(]f(YXfWfTfUfVfAMLEADWI*AGrFWI*LuX.WI*AGMWI*LuYAMADWI*AGBWI*Lu^Wf: AEAD]II1HIMHAD6 MI?HHuIyW I R  EI?HHuIyn I HH9Ej }  MI?HHuIyo I j  MI?HHugIy I  MI?HHu0Iy I  Wf: f.f. f.L,AGN Wf: f.f.i cf.L,AGz Wf: f.f. f.L,AGA Wf: f.f. f.L,AG Wf: f.f.m gf.L,AGIEHIADLuQAMWf: f.uH}LLILALAGA~ Wf: f.uH}LILHMA  Wf: f.uH}LILHMA膯 Wf: f.uH}LILHMALG Wf: f.uH}LILHMA  Wf: f.uzH}LILHMAخIHH H pHHHLuHnH1H?H!H^HH H Lu\HHHH1yHHIEADeHIHH9LE}HEfHnAGHIHH9}HEfHnAG~HIHH9LE}HEfHnAG-HIHH9LE }HEfHnAGRHIHH9LE}HEfHnAGwHIHH9LE}HEhfHnbWI*LmfWHf.Hyr1HhH[ Wf: LMy!XfTfUfVf(f.h~ bf.lH,LmIMIEAEI+M IMLm~HHx1HIHH9uo}HE fHnHIHH9LE}HEfHnHIHH9Eu}HEfHnEH}LILLA 襫HIHH9LEMu}HEfHnH}LILLA WRf." f.H,H*AGsH*AGH*AGWH*AGH*AG.WH*,u2I?HHuIyI HH9LEHELmHAGuAhu WI*YI?HHu8IyuI HIHH9LE}HEtfHnWH*CCC(uK ku WH*K [@H{ HHuHK yuI HIHH9LE }HEtfHnWH*K C(AEuru WH*cMH;HHu*H yuI HIHH9LEM}HEtfHnWH*\AEAHMHJHHHIHH9LEMu}HEfHnH}LILLAa\HIHH9Eu}HEYfHnH}LILLA HIHH9LEMu}HEfHnH}LILLAɧHIHH9LEMu}HEfHnH}LILLA{vHIHH9LEMu}HEfHnH}LILLA -(f.> f.,H, f.N f.HH{H1~HLx(MLtnHH@HI IB׾LH HRHþLHH*H9\I)LuLHhhH$HHHE1E1oHHHxH-HHH(mHH(@HuH@H(fDž\NLr\t2V5u'ƒHtHH(H@HH1 H(tMH@HV0u.Ar t-uHH`?_HHHF(L買HHgLpHt\Lt_H@LL9?HWH\HH1IHpHHL1UHBIHxtG(t H@t4j?HHQHLLIHH艶H LeLxN LLEjHH~MLHHRH9t趴H-.HL-A%E1HyHL-ALTLH(LjL;tL9iIHuD HH螵IHH1xoH(ddLhuHHx螷L HPIG\AGXAG H@IG0LH+ IG(H1=tLw'LHދpH79tHL1袴HhHLu HxaHH;q" IL1+HI讲L +)I蔲L +10L2L³HHht:KH^+/.HA+HHH(+H*HHALIHLHHIHIH1;H(HLLL8AIH(HH 12IHL1色HHH腲HH3HѱȰH)HHdHA莰H1H!H1)WH1n),H1Y)L!eL;tLeHu Hx^HNHHH蛲H+HLpMtL贰HH@HH0HW膯H(HH"H貰MHH;H5{HCAI)HH'(AE11ʲ農LI?kL%HAîf.UHHu O,1;O(tHWPHtGH`H1@DEuHtAHH HuLOMtA9u1HtH]f.UHHHvHt Ht ](H]ø]ÐHtWUHAWAVSPIHt E11fI>L%HI I;^rI>I~(kLH[A^A_]UHAWAVAUATSPIHGH9vL1&AlIE1H9taIH?LHHt\HEIGL9s2MI)HH]Hf.DHh%H IuMgHEIDH[A\A]A^A_]Lf@UHAWAVATSII0׮HtDIMtPLH辮I$HtaHMf.H$H IuE1L1z%@I$Mt$Mt$WAD$ID$(L1C%LkE1L[A\A^A_]f.fUHAWAVAUATSHHIIHIHUHxlML}LuHELetoM~E1A@HEH@`H HH|HuH<HuкL2 EEHIuI[LE1H]H转Hx7HEHHUH)HEIH=w6HH u-Eu(LeIH]HH߾wH= IH[,HD1H:1H01H&1H1H1H1H-H1H-Hڬ1HЬ1HƬ1H輬1H責1H訬1H螬1H蔬1H芬1H耬A}HqL}H`D}HLD}H;LH }H&LH(DDHuLH0DDHuI8DHu}Huܫ}HuЫ}Huī}Hu踫}Hu謫DH]H蝫DH蒫DH臫AH{LHmDH\DHLLH H:LH(H(LH0HMI8DH}HHEHHEHתHEHƪHEH H質HEH(H蠪HEH0H荪H}H8H}H=Hn1HZ1HP1HF1H<HEIH*LHDH DHLH HLH(HשLH0HũLH8H趩H詩1H蟩1H蕩1H苩LeH=Hx1Hd1HZ1HP1HFHEH=FDDHu!HuDL}LLALM9BLۨLШLL賨H]L9ACL蝨L蒨L肨Lu1A|$HMt8Mt4A^LPLCI>AVL81L"1LL蜦LtIxLHHH[A\A]A^A_]fUHAWAVAUATSHXHMAIIHs"HHEHH=HDL膦I81eIH1eAƃuAtCAAO1AIG(AAuHH uA4u AdL9!HEIO0L9v}HuH0HH 0HH/HHIHH@>HHHH@3HH HH@7HH(HH@3LHH0H@7H8H IO`L9EHLH (HHH uDu A4EIW0UuHH@uHH@uHH @uHH(@uHH0@uH8UEeHHUHHUMHH(MHH0MH8HMEAAgIw8upHUHHHt7EH (HHU)AHHAEE1D%De=DuH]uAM9O0wM9O(v{DuAEA-A{1IO0L9Z1AxAnIwHucHUHLHHHDuAt M9O`rAu-Ew E1ALMADL>-EuA_L$LA_߁LLA_LLۣIGHEH}FH PʋH D4A `H @L菣L脣DLvLkA_ L\LQLAL4I_(H9w+LLL,LLܢLϢLŢI_0H9Dew+L訢L蝢L荢,LvLiL\LRI8^L;L.I@D!AH}!DLLAIH^^LҡLšA_PL趡L諡A_TL蛡L莡A_XLLtLdLWI_`H9w+L>L3L#,L LLLI8HtL^H]HtH߾L I@Ht DL AuIHHtL^^HfL EtH}H H H;MuHX[A\A]A^A_]Hǝf.DUHAVSIH LLLHH LџHH(L迟HH0L譟H8L[A^]雟fUHAVSI~L[A^]mf.UHAVSINLCL3L[A^]"UHSPHh诞Ht=HtAHK`HH`CP@PC@@@KS [0X0P HX1H[]HHHHf@@H@@ W@(@8@F@XH@`@H[]f.DUHHHHGfGGHGG WG(G8GFGXHG`]f.UHSPHttH{8cY{ttH{@{t uH[]H{HH[].Yf.@HtVUHSPHttH{8X{ttH{@8{tt H{HXHH[]@UHH9O0wH9O(wtH9O`w1]@UHh蔜HtQHHHHf@@H@@ W@(@8@F@XH@`]1]UHAWAVAUATSHMIIHH1HHEE1EAAAMt DI9EMHhtIWH]L}LxLuEIHLE˚ELL9LuLxL}s\L)EH/H #HDH];t>L1HAHcHH;EDH[A\A]A^A_]HCHEHHHOfGGHGG WG(G8GFGXHG`EDEt1KHH]HfO HPHUfOHHPHUfOHHPHUOHD@D H}xp  H HE0@Dž8P,($AD ?Ƀ>HH}HGHMHAHQ1HEw AHG(AHG0A DAHUUtGPfGTGX11$qQWPQfWTQWXQHHMDHLHHW`WG8HGHMtI9Ms LHPLufHXHxL`HO8HpMH}IDDHhLLeMHHHD1LUIHӗHpL AMHH}GHXHxL`t(LWL`HxH}+fEMH}IDAHhHp1LeM.AHH1҃}HHpL8IHEL`@HMz}H}HXHxtGfHhMH}IDH1LuMHIHlj1LVTHL{H}H_HAHGt>H߾UH}u(H}1HpHLw(HW8HEHx@upHMHA8HEHx@HEHPHucH}HGHH9G0Le]tI9tH9G`E1AH@AAH1M8HH}u71H9O01H9O(@1H9O`1ɁP 9u,H9O0u)HHHHG0#HEH@HLHHHDȸI9u HHIu$H9G`u HHHG`PuGPuHG`tLHH@HC@MtHEIE1MHPI)EUHHHH]f.UHHHH]f.@UHAWAVAUATSPAIIIHu Eu1LEALH裔Ht!HMt0M/HLL藔MM/c1H}о1i MHLL{L9s4HtL*/ H}о 1EB3MIHCI9HIGH)HH H<1I9IGH)HHHHfHH9~ ftf~@u`f:@udf:@uif:@unf:@usf:@uxf:@}f:@t f:@tD  f:@tD  f:@tD  f:@tD  f:@tD  f:@D  f:@D  H9HH1ff.HH9Wo 3ftf~@f:@f:@f:@ f:@f:@f:@f:@f:@#f: @(f: @-f: @2f: @7f: @<f:@Af:@A3 f:@D3 f:@D3 f:@D3 f:@D3 f:@D3 f:@D3 f:@D3 f:@D3 f: @D3 f: @D3 f: @D3 f: @D3 f: @D3 f:@D3 f:@D3 H9u"HH[A\A]A^A_]1H}оHH @HL9s>u f.UHAWAVSPI։Hu1AE1} HtPf}rIHÀ8uAD{LJD9u0HEHߺ1[LHtHL;KILH[A^A_]f.UHHHADHAq Q AHHH(H L H ]f.@UHAWAVSPIAH1H4Hx\1AHtH}H贍Hu41AMEȃAu#M L:H[A^A_]f.UHSPHH8VHu9(d)UH=U(_)UU HUC fCCHCCPfCTCXH{@HC@H{H|IHCHH[]f.UHAWAVAUATSPHIAHuL@1fIIŋ}ԃ:HtSILHLHAD$D}HLLDD)ALILE1H߾1LH[A\A]A^A_]f.fUHHHHQHHHQH!HHHHzH> HHHHzH> HH HHzH> HH(HHzH> HH0HHzH> H8HHQH]UHAVSHHIH}H}H P p΍ 2 `f H @fAH[A^]@UHSPHHHHEH9pPv HHQH]HUHAWAVSPIH?HtI~Ht赉I~0I~8FI~@FI~`HtNI~PtBI~Pr2A f.I~`HIH M;~PrI~`蝉AFhtOINp1f.HH9s/H<كuH1+INpHHAFhI~I~p4LH[A^A_]"ÐUHSPHBHH;H{H[]f.UHWG ]Ht UHH]f.@UHFG]UHSPHH螈HCH[]f.DUHAVSIHHtMt;~tC1A[A^]f.UHW]@Ht UH7W]UHSPHHHuHUHT/Ht EM CH[]ÐUH1xH 99~ H "]ÐUHAWAVAUATSH(HIHu11fM$$MH]HEE|$ Et$ID$HEEl$HtrHHDhfDx fDpfEt$AH}1HCHu2f.HCHEHHDHMH`HXHІH}Ⱦ1H]Ht#L3H{褆H蜆LMu1H([A\A]A^A_]UHAWAVAUATSPAIAA.Ht=HHD`fDh fDxfEt#AL1+HCHuH1HCHH[A\A]A^A_]f.fUHAVSHt HL3H{ԅH̅LMu[A^]f.DUHAWAVAUATSHHAAAAADfAUЉufAgE11HH HHHt~KAtfD9{ uA9uN!KuAH HtIHIHH{HLUЋuf.A9}AHH{y1HH[A\A]A^A_]E1E1HfCAt!fAtA9u !CtA9}AHIHHuHMt H}IHEHH{BH:fAtH}ȋUЋuA9|[MtLH}ȋUЋu1H}HUЋuE1E1HCAthfD9{ ua!CtA9AFHMt H}IHEHH{衃H虃Mt'LH}ȋUЋuHIHHu1H}HUЋuf.fUHSPHtIA1H?Ht)f9W uDGt9|HtGfft!H_1LϾ 1HH[]HUHAWAVAUATSHIHIHf.IHHuMLu"fDI$MeMLeLuMtzI$HEE|$ @M6MtfE9~ uAVfA;T$uI~I\$HuAD$!A FI$HLLeLuMuMLH[A\A]A^A_]DUHAWAVAUATSH8UH}fHHMAIE1Lm>fIELuMHEL(H]H]LmLmL9jHL9LuH]HAHAL}IL9HIHEAEfEe fEufETLH1 IEHLuMBMAH}Ⱦ1uMf.fII~脀L|IHu~H}Ⱦ12H]HtefL3H{DH<LMu>L*H}Ⱦ1H]HtL3H{HLMuE1LH8[A\A]A^A_]f.DUHAWAVATSHtuHE1I7DL#H{HHI9MDMt9M'LMt6C ft=upt=uctL#If.E1E1L[A\A^A_]f.fUHHt-1f.H?HtwtfG1]UHAWAVSPHtcIAHAf.DHHt:Dst{ LF{L:sHtH{L~H[A^A_]UHAWAVAUATSH8HH9wP ILk`IKD5E1HxH{Hp`H11~MHKL}L}HAO$.L}L}LfEL}f0ALeH{uк}HsAH1HU1IwAHtLIHHuкHHLZ}Ht%LmE1I]HH߾1ADH8[A\A]A^A_]L+H{H }H}I9MDMt.M/LMtaC ft=upt=uctL+IE1He{H߾qHM{H߾YI$HEHHP@HHHH HuHuMLmHU'IHEL8L}LmLeHUMMI$HEEl$ IDM$$MtfE9l$ uAT$fA;WuI|$I_H|uAG!A D$IH{L{qLLmHEHHP@@KL5E1HUyKH@@HA@A7UHAVSHH Ht(H Ht3AhHt+HIp1fH9t HH9rHHH@hH{DsPHzD[A^]UHAVSMH1HtHtH 1Mt @XA[A^]ÐUHAWAVSPIHHHC`HH0Lx`L1zt%#yL:E1LH[A^A_]H{L8xډIItL븐UHAWAVAUATSP xH)XMIHIIHHHE111BI$LL1yt?lxLH H H;MH [A\A]A^A_]H~VLLDH HLӾLLJyHt9II<$LDYBI$L)H1H H H;M}wwHBUHHO0]UHAWAVATSHHHH $E1HE1E10HIHN'x'(byHt)INjKhDclQD9s,HCpNHHLD~HH߾1iA H{pJ4yHt4DclHCpKhQShLILHHt[HIFA~L(AFA>t3IFIGANAO0IG AG4AIFILr_1ZAA~tHuLxLHE tUйA;VutHEI;FtANAF HHH@[A\A^A_]HMu~UHAWAVAUATSPIHtG w?s5AI z_Ht0IH@Au0HUKI1LI1L1.DL11ɅAO H8LLL HHu L^1HH[A\A]A^A_]fDUHAWAVAUATSHIAIDH HcHI$ ADŽ$ IDŽ$ ADŽ$8 IDŽ$0 WA$X IDŽ$h ED$ HJ1۾ E1jpPT-HA$ AD$I$H~HA<$lMaIM$ I$0 E$8 ID$HEID$HEл`vI LW/fB4HHH@H A|$IL$HJ HHI$HLx\D1A|$@L;Hws'A$8 A|$tA$ uuA$ uqA|$uv LHuHxutHMI$ A$ mAD$I$( ID$RHH1HH[A\A]A^A_]A$ AD$A$8 L9s$I)LLLHUA$8 L9r1A;$H륀'v@UHAWAVAUATSHHAIIDH HcHLs LLH&H WX Hǃh L Hpmt CHH\H;LMH0 D8 EL HCHEHCHEL%QH He1fB4Hz tDHBHt;HB 1HIHHHY11HHMH 8 tNLvHwIc L჻ u+{u. LHub HxJuC1 C8 L9sI)L1;HH[A\A]A^A_]CLHHUDfy$f??UHAWAVSHIIHHHHEH?Ht(CHwVH HcHHEMuFJH{HuغSHy%HsHUعASHyHEMtEAMtEAHHH;Eu&H[A^A_]LL1HHH;EtVHEMu뫐Q|UHAWAVAUATSPHt~IHHtxIH~oIԿx>XHtnIHLhL`X1IHL IF`AFLHQH5HLIHu4LWE1'HE1H߾HE1H߾1LH[A\A]A^A_]ÐUHAWAVAUATSHEIIIHuMuI1LjHMLExYWHtEHDuIHMtVL\XIHuHI1L1L?VI1L1HH[A\A]A^A_]1HMM~HUIVX1HuHHH HDEIV`AFHHt IQ Y0[0S KHH5(LLMHHiLU1ZfUHAWAVATSHI"IIH {HcHI<$HtH5hfUID$HA|$tIt$XHtI|$1U^ID$`ID$h7ID$hH9HHBHHDA|$u!I|$It$XH)It$`1TIL$LHTHHID$hHH)ID$hI2I<$I|$SID$H@I|$IA$AL$AT$ A\$0A_0AW AOAA@HID$pIAI<$SA|$tI|$HteSLSE1vI|$fSuSAD$pLISAD$p IEIA/LLE1"IF E1IULL.1IHHH;Eu1LHX[A\A]A^A_]IEHH H H;MtWKIE Mm|UHAVSHtKHL7Mt8{tHsH11ASHsH11ASHL HYE1L[A^]ÐUHSPHHHx{t HHuHtCHH[]H;Ht!HsASHyHu$CHCH{HHʹH[]C륐UHAVSIHt?HI>Ht>HxVI>Iv@HAAVH1Hx-[A^]AF6I~@H޹AVH?[A^]Hu AFAF[A^]ÐUHAWAVATSHHt@III lKHt6L LxLxHCHLH[A\A^A_]HH߾ HH߾11[A\A^A_]ÐUHAWAVAUATSP HH)XHHHEAII1DH56HcHI1HLE1fL)H HCLLHHtOIIL9wIFH9HBHtzLHHHHIFH)IFHuRHtMIFHH7HH;Et>hIFHBH#HHIFHL I1HHH;Eu,HH [A\A]A^A_]HHHH;EtG0UHAWAVAUATSHH HIHIH9SPMAAu+HC`LHH|u|tIE1L^LEDHpHLxJDD LHUH tuHt:LHrH;Ev,IE1L1蛿RIE1LHMA u9Eft0HADIHuIE1LE1@uu&}t)HuIE1Ln1HEIUHL{HLEMLHHuHMH9LMH}LEI)MMEHMLHLPfDždHXHDž0\HSHH0H $E1L1HE1Ht1HUE1LHĸ[A\A]A^A_]E1L111NHHSHpH $E1L1HE1QHtHMt5ULH1LEAHHUu IE1L HHUMH]Ht+HMULH1IHAHUHME1Etf}u Mt L9}tH%LHƺIHHHUHHt9H9Ut(At#HMH)MIELHuHuHHILhE1UHAWAVAUATSPIAIH1IǸMHLeLDHIALuu/HC`LHH|HtL9IEHmLAG AE0IGIE(AoG(fpNAEAGfAE4AGufAE6/@u fAE6fAE6IEMuMeIE1H[A\A]A^A_]HH߾1躻אUHWHGHG0HG(G]ÐUHSPH111 HtH3S H[]fUHHt$HtWf;Vu H?H6;D]H9]1]ÐHt(UHSPHH?*CH{!CHH[]CfUHAWAVATSIHtTAHA@uwIσ{ tTC Ex^uaHCHuH;sHSLHCHtTMtFKA>HsMt2A)H1C EysMtCAH[A\A^A_]1f.@Ht UHG]1UHAWAVAUATSHAfEIΉItt7)EԿ BHu+E1LE BHtILuEI~gBIHtnHLLcBIB0fEgWAG }uPLuAI?MAIDALW tAW t)uu G 9tt[A^]É[A^]ø[A^]DOELA1A&f.DD9sA ry wIrԉʃAt$ʃAtAuyA D9XA AAAeXAAGA$<5f.UHAWAVAUATSPIօtAIAHMu A1MtA1DƒA1H=oAf.@A_H=H_ABDA\4_HAAH_EBAHH9uAt4AH 'o AHH_CDAD>HHEAE1Ln1f@<3HH9tAAJE1HtLfHHHtĨtL3f.u IfDE1HHE1DJII t>J1HtLf.HHHtĨtH3f.1MLIHMAtH38LHHHL@tL3LH1H`HH;Eu HH]/f.@UH]UHIҺAE1PAR H]fDUHAWAVAUATSHHEAHX}pN81EIAH3IE0IE@HuHIE@IEPI}Hu H=I}HEx!qE1ANAAvE1A APʃLEȉ}DMЃA DEI}P0AHZHIE8L(D`,DH@0DxHpDFCLL}AOKxCtC|AG i I}PAU@HCPI}PsDAU@HC`I}PstAU@ADHChHǃ(I}PAU@HCHHSH{Pt\H{`tUHtPH{htIʃHHH IHHEԉEЉC<LH[A\A]A^A_]CHtH@0IE0LDH[A\A]A^A_]fUHAVSHHHw8HDvAN,H@HsHFHtH{PHSHHs8HFhHtH{PHSHHs8HF`HtH{PHSHHs8HFPHtH{PHSHHs8H{PSHHC81Aq@[A^]AtA*jfUHAVSH?HLw8M/H{@$H{HHCWC(CXAF(IFIF AF,yAF,q*DAV111҃uHC`AF@LH[8CDHHCXH{hstfwH[*HcHH TTDHǃHHǃǃHǃCp1[A^]UHAWAVAUATSHHIHILo8MAM,AԃuBA}*AMI~`LDIF`AE,AEDD9vfmAwAE,AEDD9MwKu>I}hAutfwH(ADžIDžADžAEDA)MAAFEIHEEfM>LA@AAMEPEM|M}hMU`E]LAupzA<81D!AupAAMt A~  MuAE@HEAu@*HuA},111IF`IEAM(QAU(IEAM(QAU(IEAM(QAU(IE0H8xDHxHx(Hx8IMAU(rAu(IE0@IMAU(rAu(IE0@ IMAU(rAu(IE0@ IMAU(rAu(IE0@ IMAU(rAu(A tAƒIMAU(rAu(IE0@IMAU(rAu(IE0Hxt2@ IMAU(rAu(IE0@!IMAU(rAu(IE0xDtI~`IuAU(IF`AE8AEEEA~H HI IN0H[A\A]A^A_]AEH 1A"A|@| у ‰у ADHiхBH )) AEqIUAu(~A}(,24IMAU(rAu(At[IF`HHHIUAu(~A}(2IEAU(rAu( IF`IMAU(rAu($IMAU(rAu(111IF`AMEIM0HyAU(Au8A 9ЉI9}AU(I9})vyDtI~`Iu[IF`M~8LuA_(AF 9G؅t1I~Iw ALMfMg Mf(A)^ A)_(uIGIG A}(IM0I9}Au8HI 1IuAU( >Au8Au8IM0Q 98IEAM(QAU(IEAM(QAU(IEAM(QAU(IEAM(QAU(IEAM(QAU(A tAƒIMAU(rAu(IEAM(QAU(kyDt!AE()vI~`IuIF`IM0AE8;A uAE8AEIAMI,IM0Hy(AU(AЉI9EAU(I9ED)vIE0xDtI~`DIuaIF`M~8L!sA_(AF 9G؅t1I~Iw ALMfMg Mf(A)^ A)_(uIGIG AE(I9Et9AIuI}0H(A]8KAM8 AU( CD1IM0yDtAU()vI~`IuIF`tAE8AE[ AM[/IE0Hx8AU(AЉI9Ef.@AU(I9ED)vIE0xDtI~`DIu!IF`M~8LqA_(AF 9G؅t1I~Iw ALMfMg Mf(A)^ A)_(uIGIG AE(I9Et9AIuI}0H8A]8KAM8 AU( CD1IM0yDtAU()vI~`IuiIF`t AEg AMgIE0xDAE(I9EsNM~8LpA_(AF 9G؅t1I~Iw ALMfMg Mf(A)^ A)_(uIGIG AE(HI9Mr?AN`IUpAu( AFaIMAU(rAu(111IF`AEqA}(tmMf8LRpA\$(AF 9G؅td:\>c:\>b:\>a:\>`:\>_:\> ^LOHWIw :\> HtHH?1IEPIAfQIrAfAAAAAA9IHxIuP1H)L1qnAIMuM~8LclA_(AF 9G؅&I~Iw AL/MfMg Mf(A)^ A)_(IGIG HH4HH+HH"HHHHHHHH D)Ɓ9GA@IAfHIQA@4@H sfAHqfA AAAA)AAADž9 t1HuЃ1}ڍHuЍrȍHMȍH9HH@8IF0 }ADž}IHy%1'ADž}IHxۉIuPAH)L@lAIMuM~8L2jA_(AF 9G؅t1I~Iw ALMfMg Mf(A)^ A)_(uIGIG IEx LuȉuAEAIHx"IuPAIHy1AH)L1OkAIMuM~8LAiA_(AF 9G؅t1I~Iw ALMfMg Mf(A)^ A)_(uIGIG IEx LutH]Ѓt}Lu!kin1A~ AE@ 111guDI}hAutfwHDAu!ADžIDžADžMf8L_hA\$(AF 9G؅tIIE1CD5CL5CD2CL2CD5CL5CD2!CL21CD5CL5CD2ACL2QCD5CL5CD2aCL2qIIuMHtAHK2HLH}H1f.@D7 7D3 3H H9uHHIH9}LeLEH}DűU)HMr(IJH;HuHLH9AHMEuAt)D1fDTATH9uIA)HADueD1f\1A\2\1A\2\1A\2\1A\2\1A\2\1A\2\1A\2\1A\2H9uIHUMI{HxL,IIE1CD5CL5CD2CL2CD5CL5CD2!CL21CD5CL5CD2ACL2QCD5CL5CD2aCL2qIIuMHt3IK2HLHMI1D1 1D3 3H I9uIH9}LeuCLu}LEA)HLEu HH `H0s&1A)HLELEuH@1LAD AL D L0AD !AL 1D@LPAD AAL QD`LpAD aAL qHHuH(t)I HHM1D1 1D2 2H H9uHIҋdAH8H9ZDLH)LeMLEu u*H 1IH}LeLuH 1HO0HhI)˃IKHIJHOE)ADgE)A!ADw HhLyHAPHĀ[A\A]A^A_]H W1H}LeyUHHHO8Ht{HA HGWG(AHtHG`HA AHA(HAHAPHPHHAhHA`HH1]UHHHO8HHA4A<HA HGWG(AHtHG`HA AHA(HAHAPHPHHAhHA`HH1]DUHAWAVAUATSPAH1ILg8M!xAAA؃0L؅u E1t؃It$@HtA9\$0u El$A\$0+IPAWHID$@IG8El$A\$0IHID$4AD$<ID$ IGWAG(AD$HtIG`I$AD$ AD$ID$(ID$HAD$PI$PI$ID$hID$`HI$E1DH[A\A]A^A_]UHAWAVATSHp:1IHteAIG0IG@HtXIHtkIPHtcIIG8H@@LD#tLIPLAWHIG870H`IG@IGPIHuH `IOH눻1ۉ[A\A^A_]fDUHSPHp>1HHHC0HC@HH{HH{PHHC8H@@@(;9@0H@ HCWC(HHtHK`H@ @H@(H@H@PHHPHHHhHH`HH1H[]øH[]H?_HC@HCPH{HH 1_HKH H[]f.fUHHtRH8HtIx4@DGPE 0A w2HH!DHHGHDOPHGHGP1]f.@UHAWAVAUATSHHW&IHO8HMHC&MbM6&M M#HuHEЋ uHE AREB HuL~HDnPHPHXHH`HNpHhHHpHHxHNtHHHMMEH@AELU?111被HMHAMID$` AML]HEMILeHEЋc%LeAH %HcHHEЋP A#DE8#A~A1HIYLHHA$AyHAIHHDHADELe"AvAHIyLHHA $AqHAIHHDH A#AHEЋ@'D=A DE8"A9HAvIQIA HHF$AyHAvIQIA HH$AqHANIQIA] H $AAQIHIF DIAAkDE!AvAHIyLHHAsqj#AvAYHIyHHHAwLE#AvAYHIyHHHEu(!#AqHAIHH DLHIAAA  DE AvAHIyLHHAQ "AqHAIHHDH* HEЋPx9 ML]LMEŃH`LxA)AA)@t6H5r3J4F1@~HUfDŽZH9uIAraf.H)3B@HufDŽVBT@fDŽVBT@fDŽVBD@IfDŽFAuHEǀLuHXHUHHB`BpE11HpLh*EH%LUIB0HEHEELML]LuMIzLuHEDHEЋp\A9DDLfoHHI߃9rHEЋp\E+HMЊATLeA$IAHEЃxLADE;DAvAHMALHHAsr AvAyHMAHHHAwMAvAyHMAHHHAw(AqHAIHH DMHMAIAAE)MZ(HELX E LuMLLMEHuL)HEЃxHxD ;LeHEDxAA - LHHHH9E1HMЉATA} HEHEЋXTtsD9AGD9AG؅_L]MLuLmALLLDELM=LMDEA)MA)MLmLMILUL]HE)XTHE Ht"IB0HEIHEǀEELML]ML]DEHEЋH|DAE9MHELP`HpAAALELDD!ADDE9DDHf.HHIHDD!ADH9rHuAAAtfvnff AIA9<EH]:DHHIII9rDeH]HLEAtfwIE)DANH}ЉfGAILELE9AIA9s1EH]p:DHHIII9rH]IE)EDeAFHMDADIAAIA9sVEH]:DHHIII9rDeH]#DeIDIE)ADeID IE)AE1IB40;uCpDMLMfAnpfpHPDiD1A0rs1EEHMBIBIAUQQAU QQAU0QQ@A@uMt$DۉHMQQuHPA9LMD@Ãt)1f.A>HufDV9uA)ArMf.AVDHMfDqAvfDQAVfDqAfDQuHEDDeLELE95HEf%MLMHXHMHHA`Ap HpUH`HLhLxML"LULu EHA" HE IAAHELxMz` E1E1HEЃx }111LuMLmELMMIELmMLuHMHAID$` }HEЃxtDIAHE1ALew%EhAEAAIDHIADHMЉAD HYHc HH)HMHA`H HApH1HAh}u"kH<IB0HMЉIAyLDDD!ELEAXTAXTI)AEIAAjH]LUIB0HELeDEL]LuIAIAHEDxAA HPIAIADHuЉF|DPD VxIAHEǀ1H5,(H4N8fDDH]Љ>f{IAH97AwEQA}AAIDHIAHY HEH@4 HEH@(Ht DAt;fD}H]H{HuEMMMMMLUMEHCHEE1E1DEA1HAVIIIsqLhAqDHAVIIIwJLhzAqDHAVIIIw#HAAQIHIIAHEH@(HtLxHE@t>D}H]H{HuEMMLuMMLuMMEHCHEE1E1EEADHANIAIAs$IAAAIDHIIAHEH@(HtAωHLHHHE@t?fD}H]H{HuEMMLuM3MLuMMEHCHE@E1AuHEH@(HH@EEA1DHAVIIIAs$IAAQIDHIIAHMDyTHI(HtDy t?fD}H]H{HuEMMLuMGMLuMMEHCE11HEAHEЋHHEЋ@TD9AGޅHUHR(HtXHzHtOJ r$)Hω)9FLDELuL]MMMqMMML]LuDEHEЋHtDLeI|$LΉDELuL]LmMM`MMLmL]LuDEID$A)މIHMЋAT)؉ATHE@THEЋHuHEH@(HH@(ELmL]HEHP(DHtxACL)Ht:f.Hr(Ht'H}ЋT;z0sWH]ЉST >f.@tI9sHMHQ(ICL)HuHEЋH%E1f.DC<)MmtI9rt3LeI|$LDDELuMLUMLuDEID$E)DIL]LmHE@THEЋHuHEH@(HH@8EdLmL]HEHP(DHtxACL)Ht:f.Hr8Ht'H}ЋT;z@sWH]ЉST >f.@tI9sHMHQ(ICL)HuHEЋH%E1f.DC<)MmtI9rt3LeI|$LDDELuM趕LUMLuDEID$E)DIL]LmG HEHEЋPuLMHEL]AwUDELe[ A~A1HIYLHHAsD AyHAIHHDH LeHE@I9t%H { IAIAHE@I9uLuL]E1E1MMDHEH@(H PD@HHMHHAhAtA|HAHLHM!}EH:LUIB0HEDELML]MIAIAtnIueE1111LuL]ELMLeID$fEHuHǺMIEL]LuID$A$E1"HE@H@(Ht@HLet4DLHHH{{HHB!BH9 H HMHAIHC`ELMMLuHMЃyDIEH9E1E1EHEHEЃxf HEЃxX ADE DAvAHMALHHAsr AvAyHMAHHHAwM~ AvAyHMAHHHAw(Y AqHAIHH DMHMAIAAHEЋ@ I9 HrIB0HEqHCIB0HEETEHE}DELML]LUM HEArnArhHEIBEB M ErH]L{HDkPLMDMUMINEF MEvL{HDkP; uHEǀMIDEL]HEǀLX`Hp։D!EdEE9sJDDLDEHHIHD!EdL9rԉAELDETA4ADAAALEE!DAEAGtDD9vcIIsA9HIIHDD!D}EtDLH9rHAE1IA։L]3IىGTDICIE)HEDEL]IAIA)AHMDA‰AT@ LUDELe@@HEЉp\|HEЋXTHEЉDEL]HELXhHtЉD!MElEE9sULDDLDEf.@dHHIHD!ElL9rԉHME LeLDADA4@tHMDDƺEA!DAEAGtDDHM9vcAԉAHDMEJAHHIHDD!DDEtDLH9rAHuHDCDC4DIHMD)HMHMDDELUAILmA)AHMD@@u`HMЉAXq\IAL]DEȅA9sWDDLHHI߃9r1HS IB0HEIAL]DELDDD!ELEAXXI)AEIAAHEEvDD)HMЋQX9v$)HE;P8v9HEЃt,H LuMMLeLH)HEЋPTABLuMMHEЋHH<1HHEHHH1oD D H H9uLEL9uELeE)HEЃxTDD)LELep%HEǀ PHQDu?LHQHuЋv0tp9vsAH yIJ0HMIHAIB0HEIAHLUIB0HELeDEHEЉP0LeAD$111LuL]ELMӂMIEE1L]LuID$IB`1A  A$LeE1AHNLUIB0HELeDEILuL]AzR#DIF,NDGlHE1IDeLUDEL]DeGlDIE1DeDGlIE1DeL]E1DeLUDEIL]HE1ADetLmElHE1IDeLUL]DENElHE1IKHEIBEB M ErHELxHDhPRE1E1HEHuIrEB M ErHELxHDhPx4L@t,DD)LLM9t5HEE9t,HEЋw!}Huuw볋CDC IMIE)MzE)MZ(HELX EtFHEЃxtf}tA/f}tA f}tAf}AE1DE9EG޻ff|]uHH9uAAA9DBDmA/LHDMCA!~A INIF(H 0~81fAdž Adž$H[A\A]A^A_]fA@H;fAufAu fAt  11fADufAHufALufAPuHHHuf.UHAWAVAUATSHXH`HHEL>HFLDHH=HE1fADHI9t3fA<tHcHJ ƄHI9u͋MthE1DALAMZHc҉ HcfAƄHATH)|a1ҹMuE1f.YLAM؍BHc҉ HcfAƄH|HMHuNAAf.F CL9McEIc̉ A99}.LcJc HcLc CfA9sGLHcЉË HcAfC9rEuB7:w/f.Du7B:vDHcD I|I Mc#fDLcF IWD XHD D AMcA(f.IcՉ A99}.ʃLcJc HcLc C4fA94sGLÉHcىȋ HcA4fC94rEuB':w/f.DuB:vDHcAIcD Hc HcHr HcHr AfAfC@8BրB7fEtfEtD FA!Icщ A99}.ʃLcJc HcLc C4fA94sGLÉHcىȋ HcA4fC94uB7:y@uB:v뭋 HcHQ HEL(HH@H0HPHUPULc`W  HcHc fADHcH=;L]HHuA<A)H4Hƴ 1E1LEHuTGDAIcIHHuBtHHIHLEHuDAHA9#Lc4CDE\1E9AEfG\A9fAfG\A9IcfG 1D;uYD+EHHuEA<A)L4Iƴ 1E1LU+fDADHcHHEEHA9tjIcAtA\E1A9ADfA\9 fA\9Hcfw 1;E|+uHcMLuA4MLUqEL]-LH IINgI Hf.LLf.HVHftfHf Bg fBg AQAAEL =fu"f.DBg Ift_f.tKHcI@Hc3H9A\A9tMI)A\IHfEdIt$u fE fM fM fM fM fM fM fM fM  fE HfEf fEf fEf fEf fEEAE1fCIM9C|HtL}AfD}G1ۃsDD1fȃ ؉ʃ ‰Puхyfȃ uZHk HH;EuHX[A\A]A^A_]fDUHAWAVAUATSeE1D$I9NHHF,aF IEHM EF$AE)BAAfD fD D9LO(DIDO(E4D!LG(HO(E $(f A Aމ$IXH,fDFD$D)FDf f 9LwO(AG(AD!HO_(CG(D4$(AfD A Dى$IXHH FHg F+AEDE)A fD D9~KLO_(KO(E4D!HO_(CG(D $(AfD A EADى$ADAABHX DFDF DD)A fD 9~\HGO(Y_(D4D!HO_(CG(D$(AfD A EΉ$AKD$A5H6 FH F+,EDD)A fD 9~KHGO(Y_(D4D!HO_(CG(D$(AfD A AD$)f f 9~ELG_(KO(A4D!Hw_(KO(D$@(f  0$[A\A]A^A_]UHHf4HLAAtJH ` fBH 9 HH HHf19]UHAWAVAUATSODF1fEDAA)ÃE1ɸE1ADEI9EFDIE~A9}E9tE9EӋ$"f.DD$AF D)F Df f 9~LoO(AG(A\ D!HO_(CG(D,$(AfD A $AxE1fE 1E9AA)˃f.DEtA9D$EA D D$D)D DDf f A9nL__(KO(AD!HO_(CG(D$(AfD EAD#DD D$D)D DDf f A9L_O(AG(A D!HO_(CG(D$(AfD EAD D$D)D DDf f A9L__(KO(AD!HO_(CG(D$(AfD EADED$D D)D DDf f A9~KL__(KO(AD!HO_(CG(D$(AfD EADEAEDDD$ f A|IL__(KO(AD!HO_(CG(DD$D(AfD AAEAEDDD$ f AL__(KO(AD!HO_(CG(DD$D(AfD AEAEDDD$ f A |LL__(KO(AD!HO_(CG(DD$D(AfD AA AD$E1fEA[A\A]A^A_]ÐUHH]UH帩]DUH)HH !H]fDUH]鳅UHH]ӄUHAWAVAUATSH8IIIHH賆Hø=HكH1A 7tf.=tHA 7u1HH)H9t#h1A|7=HHH)H9JHH[H)H,LHUHzH LeLuHEIH1L% LmH]A<=H]fL90tjH'Hu$I~Ht1,IFHDLDH([A\A]A^A_]I~Ht1IFLAHpHPL#f.DUHAWAVSHLMHIIH7HtH9tHvHuIuo1IGHǃIuOMtJH]LH&H&Ht.H]fDL98tH&HuHpHPL"MtIF0H[A^A_]UHAWAVAUATSHHtoIIL}LH&L`&HtPIL}I$LH&IHCHf.@HtH;H[LAփu MuH[A\A]A^A_]f.fUHAVSH H]H%H%Ht*H]E1DHH@HHuH%HuE1L0LH [A^]f.@UHHdž]ÐUHAWAVSHAIH1HEtHIOt-tuIIH9HM EtVHuHE؉UHuH>vAAHJ0 B0( ݆H)1HHH H[A^A_]1f.DUHH&MMMHPM^M@MHHHHxM@xMHH8MHHpM]UHAWAVATSH H HHE؃Hu H&MMMHPM^M@MHHHHxM@xMHH8MHHpMHH HH;EH [A\A^A_]AL3DžHXHDywtuD8HDH5/DžW)))))) )0)@HHD wt0uD8HDxH5ؿLY<t<t=<H\.3HZHE1.L1,+H`.L衙HthDZfAAHAAOAWCxH<tP<t|<H.rƃHǃ'tD8HDoH5HH5.HH1SHǃIH.轘HtfHƃHǃsD8HDفH5LDH12OH HH;EkqsfUHAWAVAUATSHH} HHEL?LcB/t-1HV HH;E HĨ[A\A]A^A_]AIH@HXtII1HJHNʃttt HH9HLI A( HXt蝁H)HHH H8wLHDuI$LH`pE1EE1LeLx1E1f.DA1pDžp%CHtDKHHHP1D I$A$HXt詀I$E1H9|LH51IA<pI|$pI$A$HXtGH=]DuH`}6DI|$8Du]Ut&A9$D-A$QAƄ$QL}Fq#A$t|HP8EDžlHMLl%rtBpD0DuA8u8DuA8*E!LH51HHP8EDžlHMLlqtoD0DuKDuEID$pHFDp^Du]%LI|$@uAT$8f.@EUEJUoD0K|hHJ].LeLHEHxH}DuDk}LH5LLeHI1GKDhLp(MH8HI$GHCDŽH}t LxHtD`Mu6ID$hHHxxADDLp(MtW]HEH|ht#E9ftMv(Mu4f.DH}LHPMv(MuLxLeADut9I|$8tE9$Du.A$Qt#AƄ$QLDDvnt+LDI|$@DAT$8uEAHu]MIsLeOthLxADubID$hHhxADDHX(HHUI|$htD9stH[(Hu!LHH`juH[(HۋUuI\$pUH5L1H}I|$pEH`D!EHEH@hH~DuxADDLp(MVHtE9ntMv(Mu=H}LH`Mv(MHEH@hHuCHHHA@KDhID$`CDŽHACHDmt[I|$8tA9$Du'A$QtAƄ$QL4lLI|$@AT$8CDŽHLD7Å8HHAƄH@Eu Lq6A@L1L HMLqpEDuAtQL}I8tE9Du'AQtAƇQLDDdkLDI@DAW8}LxLet]A$t DI$;A$t DI$H#A$t DI$ DI$L0LM$xpxH5LLLI1Ejf.fUHAVSAHt.HH8tD9Du*Qt!ƃQHDDYj1[A^]HDHC8H{@D[A^]UHAVSHHL7EHMA#lxH5(L1A#+i0HwwH5LH1AH[A^]f.UHAWAVAUATSPIHL7wIM1H@ǍwMNtttA IL9LLM A( HljLwI)E1IMM I?IHChHCpLHHǃHH;$HshH~(ILHtCfHLutBHKhHq(HshHuH5L1C)A?tIL11A?uEȉH[A\A]A^A_]f.fUHAWAVAUATSHIIH HHEL?FtF F=BЉHHv gIHtIH1Aƃu( iAƃ A$tu<t3<tR<HH.`HuNHHH.1襵&HH.HH5:HL1>t AI$DžPHPDAhH5H1 >ƅyeD(LDsH5a1LDH1AI|$8t&E9$DA$QAƄ$QLDODe) I$DžPHPD"Agy#d0L"sH5"HH1N=HIHt7ID1хtb|H`u]dDž|1H`u=DLDyI|$@DAT$8L1H`Dž|t LHLXH褆I $HDžh8D<HLfuMuLXLHHPpW)E)E)E)E)E)p)`)PMLfH=W)@)0) )))))))))))p)`)PH=įL;fx,H=LfIMI|$8tE9$DukA$Qt`AƄ$QLDDc*gE1ƅQffRAvLD;I|$@DAT$8* a0L5pH5HH1a:I$DžPHPD"Azdy#a0LoH5HH1 :AHPHPDAdI-^PHPDAcyH5LD19I]PHPDAcH5rH5LD1*9ILA$LPpA8t+uIxMuMH5/LH5CHPHLD18xMM$t uI$HhLL1LpfM$HhHH8HPHhHDHH5LLHpLP17HhLE1틅t]HP%IbH?HHH2LpH5cHL1:rHTHP`~ƅQffRAHPDD_yVf.AAHH516ffRDHPD^xDžTW)P)`)p)))))HPHTD_AŅx%H5UH1J61AƄ$:]LAJLkH5>LH189-LXELHHDxSlI$A$A$|I$L(|A$ A$,DžPHDžXDž`HhpW$HPD1ҹE1E1X]ÃH`u\A$A݃r|uwLHˉjH5HLH14AJI|$8t&E9$D.A$QAƄ$QLD.D\Eu1H* HH;EgHĨ[A\A]A^A_]ËDHj\ÃH`[LAJLiH5=LH1$7-Mt1I|$8tE9$Du)A$QtAƄ$QLDWD[LDBI|$@DAT$8؃E LDI|$@DAT$81HHXHP\AƅQffRHHZhZfUHAWAVSHL8 MtYIHHhHu H{`HtAHuL}EHHE}tMtM>A@Hǃ8 H[A^A_]f.@UH1H9>t]F]UHHxt Pu%+@t Hu(\HtH]1H]ÐUHAWAVAUATSHH8IH HHEL?HH@ILDFAEAMtF HHEHJCFLPLE=BЉS Hv LZIHt7I1LH8t9A1t1A}u*AL$#A}AuS}[H8uǸH H H;MuHĨ[A\A]A^A_]UXf.UHt'u.H@|u- $:u:u 1:t]fUHAWAVSPAINu4LD:0u%IcA@1*Å ÉH[A^A_]ÐUHAWAVSPHpHI4CL55f.IH[Ht8H3IAaLfHuHLL1/H[HuIp,EILJpLH[A^A_]BH[A^A_]f.DUHAWAVAUATSH(AIHIIHt^AGHtFH5fHY;t*ELuH5hHWIƳEg MEg AGH(HIHHH=HEIGH_HKE11ELuH L01Eg MtHHtzIL}HǾMLVHHE1*f.L羈LzVHEHHXAHtр| uEE1H1M]L%vIA$IHt`f.@L+H{8A$H{(A$H{A$H{ A$H{A$H{A$H{PA$H{HA$HA$LMuLA$]E1tMt LvUE1LH([A\A]A^A_]ID$ HE H=*L`HMIDLH}f.H t t1҅HuE1E1L羈HUHtSHE1'f.fL羈LTHEHt$HWAHtՀ| uE1Eu?HL}LL}MuTCf.UHAWAVAUATSHhLLIAHHH HHEE11VHH`HIEHHHBHIL;UIf.IA< t< tDž@DMAEƅLH5vLLL1nULUHLUE$Ht3AL t t "ALH t uHuƄHu$fDADHtAL t t1Lf.H t tHHyuQA=uKHL%A$LIGHA$IGAHIupf.t\H=kLLZtH@XH=HLZtH@ZA=DH=8hLLZZLIH(HH,IGAHHHHHSIǀ;"uHHHLRIMB|;"u IB;;/MA|/BD;H=WLYL{;.LEL.)SHLuH=#L^YHlLDMLID߿HHQLM;/uHHX 1HHH=fHHHA HH=LXLIHHHHIGHH>HHpPLAHtFLLLQt%HH5L1;'NAHH{(HLHHC(EuHtH@@ HH=ŜLWLIPHHHIGPHIL^QHLSQHH9 I4H+LHHFWH;tHx.E1H=L Wt9LI8HHHIG8Hf.fMA>IM@IA t tL;APIHu\LUPIMZHDžH5e L7Pt'A?#u0H"LHH^I AEZA?#tL OHtL OHtH5HLOHHE1L= E1ADIcL;.uHHHIE(HEDDE1HH5yZUAE@AH=[HN!H=IHN HHIEAHHHHHNIŀ;"uHHHLMIMXB|+"u IB+;/CMYA|/MBD+BH1 NIE0AHHQIEHEDDAHH&IEHEDDAoML=aLL-AULIHLhLMHEDDMLIE DDHH5͘SAEXA1H5HMAHHD$A1+;/tHH<H=aH<HLI] HtAADHHCPHIHx8"HE1 MHC0LHH)H9L}_Ls0L5Au0H=HIEE1HAAADEAAzA9kHHC0L5ShHH@ +A#ALHH{8HL5t+1HC0HtyHH@0HC0Au7Ht-HH{(uHAHC(HAADEAMMDHHx2L?2KHtL)L/H: L/YKHHL)H{H!LIFHHHLHIIFI~HHt^HHJIƀ;"uHHHLIIMt4B|3"u IB3;/u#Mt=A|/u5BD3-AD1$;/tHHvH=J^HvHHHX HAADELH;ALI}HCAEYE11[JL#MsIE1L=f.IMtqLM$$HC0HtL9}HH;LHDL HAH{8AH{(AH{AH{ AH{AH{AH{PAH{HAHAMuLI$1HVAL#I}8H/OHtw1IH IHxIuOtI~(Iu(HtHt#OtAF@A:E@DHADtI~ Iu HtHtNtA}YIIEI~AI~AI~(AI~AI~ AI~8AI~HAI~PAAEPAFPAE@AF@AEAMAU A]0A^0AV ANALALIHHuLA|${ I}0H I}8I}(I}I} I}I}I}PI}HLE1H HH;ELHh[A\A]A^A_]1MLA|$tBHܒH̒HDINMFMN(H5H1Av0AvTHxMMDM7ID$cMMLA|$uE1LA|$sA~Y-I}8AI}(AI}AI} AI}AI}AI}PAI}HALA8C7X=h@UHAWAVAUATSPHIHG HIIHtcf.@L;H{8MA$H{(A$H{A$H{ A$H{A$H{A$H{PA$H{HA$HA$LMuLLH[A\A]A^A_] H[A\A]A^A_]fDUHAWAVAUATSHHMHHuIE11EMCI>6HEH]1EHEM>ME1L%D xf.IMuf~fDI;LIDL8IFH{8A$H{(A$H{A$H{ A$H{A$H{A$H{PA$H{HA$HA$MtLM?HC0HtH;E|xHUHuCEt M>Mu)RHUHuBEM>M.1HEE1HMGIG0IF0AG@AF@AGXAFXAGYAFYAGZAFZM.HEMHMM?MIG0HtH9~AXt}tI_(Ht{A@ EuCHCIH}CL9r*IHELL)HHHIt M9t1{.t+A@MфfIw(H}IQMg MtLWCH `H\ HII8HtH6 IF8HVI(HtH IF(H7IHtHIFHI HtHIF HIHtHIFHIHtHIFHIPHtH|IFPHIHHHYIFHHtHH}H7HIHǾ?AHtA>/t(LHH=UHIHLAH9rLLHIAtLHL9uLH8ALH~/TL}M-HRJ<H%IMtL@L(MmHMuH )LL1@M.LHL aINIMHOINIwIWAAHI~8HI~(I~I~ I~I~I~PI~HLMtIMuI}8I}(I}I} I}I}I}PI}HLMMuE1LHH[A\A]A^A_]HMuHH޺H9HAHHAHyH8HAHyH8HAHy H H8HHHHuMt)I4H1HI HHHHHI9uKDHLANf.UHAWAVSPHtZHL5_L;H{8AH{(AH{AH{ AH{AH{AH{PAH{HAHALMuH[A^A_]f.fUHAWAVSPL?L6IHt>HI~Ht>H9tk1I~Hu1H9uYI(Ht>>HI~(Ht8>H9u5I1Ht8IvHt/H[A^A_]7>1I~(Hu1H9t1H9 H[A^A_]fDHUHAWAVATSIHHtZL=f.L#H{8AH{(AH{AH{ AH{AH{AH{PAH{HAHALMuIIF[A\A^A_]f.DUHAWAVAUATSPHHHL=nIHH}_f.H{8AH{(AH{AH{ AH{AH{AH{PAH{HAHAH}HGLHLMt!L+H{0uI9MDMH9tL(IL'H[A\A]A^A_]UHAWAVAUATSPHHHxHHL-ԻL5E1LHIHHK(Ht{@MLt9.LtHLLmLKMH PLDLSMMDՀ{XMtL@{ZLtH5#H=1ARss0ASΈH Ht#ILH$HQHLL&1H[A\A]A^A_]fUHAWAVAUATSH(IHIptLzL#MMiI~^]LmIHE1z;HEM&ME1L-vIMufI;LIDL IFH{8AUH{(AUH{AUH{ AUH{AUH{AUH{PAUH{HAUHAUMtZLM$$HC0HtH;E|wtIpHt2%IDžpL"fH=9GH]H9ADžtH5ׅH7HHuH H0HuD}H=7M>MH=HL M?MIO(HtA@IHt9.HJHDMMOMH5TMLDI_HHDAXILDAZH5uIHDH=1SAwAw0ARH HIH}H5DH13LH LL'L5}Lm]t H}e6IEpMHtL;pPtpMtkL= I~AIHtOfDL#H{8AH{(AH{AH{ AH{AH{AH{PAH{HAHALMuLALH([A\A]A^A_] H5zH]H1A}tH5LmIH5L1 ]̅뙐UHAWAVSPHt1HL5 H{ AH{AL{(HALMuH[A^A_]DUHAWAVAUATSHIHHM5AąH]H LuE1L56 E1L5* f.H[(HCtuAH{ uAH{ tËCHtI9wLm0AHID`W@H@(LAIE HtrHs HL[5H{HtMeH I$HtRMMDHEH#Lh(H}Ht34LuE1E1MAAkH% LH I} LH}Ht3AMt+L5 @I AIAI_(LAIHuE1LuM>DH[A\A]A^A_]@UHAWAVAUATSHuHvIHGHHcHEȋEfEAOE1E16HM@AOHUfPIGH0HMHEHHuHDؿ0H HII?H IEHtbHH IE Ht[MMDMtMn(AOAMAEA]Hu7GHMȋ H+Hq LMuPH^ I}LMt9L5G f.DI|$ AI|$AI\$(LAIHuE1LH[A\A]A^A_]UHAWAVAUATSPAIIAH @HHH LHt%IAt*AHC AMK  H HvHC AEC L;HCDcKHH0HKHC0HC8HDIL%0 LA$HA$LL5 LAHA1H[A\A]A^A_]ÐUHAWAVATSH AIHUؿLP1H @H:HH LH IHC M؉K L;HCHHKHH0HKHC0HC8HDIL%I LA$HHUȿL0H @HIH LHtqHIG EAG IIGHIOLH0IOIG0IG8LDIL% HA$LA$H H H~ LE1LH [A\A^A_]f.@UHAWAVAUATSPAIIL-O 0AUHtJHÿjAUHC Ht4I@L0HPHir+L5 LAHAA1GH H17HHKHKEtILLH ILL[/HH[A\A]A^A_]DUHHt*fHG Hf0H(HtGtt]ÐUHH+HsE1HsE1II1foV fo ^ fof fDofofqffofqfffofqffofqfffofqfofqffoffqfffffHI9vI9U@LIIfDo fDo fDo fDo fo% fo- fo5 fo=Ŗ D~fofqfAfofqfAffofqfAfofqfAfffofqffofqfffofqfffffffHI9fI9tYBAAA0AAD0D0AAAAE0ʉD00ʀBIL9u]ÐUH]UH]UHH]UHf]UH]fDUHHH]@UHf>]UH>]UHH>]ÐUHAWAVSPIH+AADuH߾.,HtDH[A^A_]ÐUHHHxH@80t HH9s1]ÐUHAWAVAUATSHIIHH HHEЊEȊOˆUɊGʈUʊOˆUˊGʈŮOˆU͊GʈUELeȾLHHEA1LE1PjAWjAV'H0MoCEȊKˆUɊC ʈUʊK ˆUˊC ʈŮK ˆU͊C ʈUEϾLaHA1LE1HEPjAUjAVY&H0ICEȊKˆUɊCʈUʊKˆUˊCʈŮKˆU͊CʈUEϾLHA1LE1HEPjAWjAV%H0H HH;EuH[A\A]A^A_]F'f.@UHAWAVAUATSH(IIHJ HHEHS*HHAICH}LHs2H<+HǺI)L&EMEȉЈEɊEшMʊMЈEˊEшM̊MЈE͊EшMELuȾLuHLmL%v A1LE1AUjAWjATe$H0I_EMˆEȉЈEɊEÉшMʊMĉЈEˊEʼnшM̊MƉЈE͊EljшMEϾLHA1LE1AUjSjAT#H0AGAGH HH;Eu1H([A\A]A^A_]G%f.DUHAWAVAUATSPIIHd(IHZ MMLHHMtSI1HHAtACDCHI9t&A  CDCALLCDCHI9uHDL"AFAFH H1H[A\A]A^A_]IuHHCH1H[SKCK/H9s JkL9+Is1LHHPHHHH0s1HH1ff.Ao f80fhLSSAoLf80fhLS0TS AoL f80fhLSPTS@AoL0f80fhLSpTS`H@HuHt5H4SLH1ffo :f80fhL~~HH9uI9jAHLHfA80KHH9uI92f.UHAWAVATSMAIԉHH= Ht HHLDUHLj1\A^A_]UHAWAVAUATSH(MLEIIIHMH1HEH<Hx H}HHLeMt*E1f.C<&"BcBDcIM9uLUMLetlN {MI1HHAtAD AIADIHLt5IHAT THDHAT THHHI9uH}AAH=w HuHt)IHHDLLE1AAHf HDH([A\A]A^A_]IrHLHHH1LK*I9sHEHCL9Is1LHHAHHHAAH0s1IH`HH1f@AoL5f80fhLrTrAoL5f80fhLrTrAoL5 f80fhLrTrAoL50f80fhLrrH@HuMtDIwHLI1ff.@o >f80fhLzzHI9uL9AHLHfA80DAQHH9uL9f.UHAWAVAUATSH8LEHMIHuH}HM HHE1"IEgA0HE LAHHIiƀI>ޱIHLH{Aw HHmnAE11jjjjjmH0HsLZHEHHC H{,IwAW IGHCEwH=k HuHt_IHHA(HDHuL(EHEHHED E1H, HH;Eu.DH8[A\A]A^A_]H* HH HH;EtUHAWAVSH(IIHH˚ HHEHHEIHEH= HtLHHuHǺ$HuH8(EAIIF1H h H H;Mu H([A^A_]øH H H H;Mt UHHѺ]f.@UHAWAVAUATSHIH HHEЉHcH |u0AE1HΙ HH;EDHĈ[A\A]A^A_]IHH@L,IŀπHH@HH1襣HAEu:tt1L*ZAEHHgH1HI7A`1ADHA1ɃHB9 J90HHHDHHHHDIHtWIxHpHUI0HA HHHIHHIcHpHA@|HDžHH@1HH@H1E1E1HQ HHIH@HHE1E1jtmH-H8LH4H1HH8LHHHHLH L1HH L1ۉxHIHÈILjHt11#HHHLtNHIDŽϘIHw^HHc HLHǾ)H5hL1@AH HH;EH5MiLHǾtzH5hgLHǾtQH5h>LHǾ*LHǾLHǾLHH85A`u 1ADHAI$XLtH5hL1MH@Lfu|D%=uiA`u 1ADHAmI$PHmHNH5hHHH\H5hFH HHLE11HIHHS HH@H HHHi HHHHH HH H/ HHP11H(H HHXLL0LH HH`L L H@H1xHH(H8HhHaÅH8HI1HXHI9HDžH8HIHHuHHHH1H HuI$Llx,1H54eL1{ E1LE1I$HH5fL1A`u1ADHAu I$hI$HDž,L1H1LH1)HHt1H޺HHDž@1H@L1H1E1PH HHHH81H1HH81E1E1!IHDžH@HHHHHH1H H1HHHcHHL1LH8HtHhHLLHT1HHtlLdH@XLHHt@H4Hڍb+wHS HcHH5df]+,HDžHHHIH11xHt{HW)E)E)E)E)p)`)P)@H@HǹtH5cH@L1HDH8LIH8H H81HHH8HzAHtHEtuH5JcHD1 HH;Ep=t AEH5XH1AH HH;E1Ht&1YHoLHAEIH|HQHIXHvRIhAAE=L =|AHoQQ)4!;;;;;;;;;;q;;q;;q;;q;;q;;;;;;qqqqqqqqqqqqqqq;;;qqqqq;qqqqq;;qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq;;qqqqqqqqqqqqqqqqqqqqqqqqqqqq;qqq;qqq;qqqqqqqqqqqqqqqqqqq;;qqqqqqqq;;qq;;qq;; x x x x x xxxxxxxxxxxxxxx xxxxx xxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx xxx xxxxxxxxxxxxxxxxxxx xxxxxxxx xx xx SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS UHHEHM1H]UHAWAVSPIHcHH߈HtMHI>HIH *HcHH9sH=LH9Hc HHHCH5>H%CH5>H8CH5>HBCH5>HQCH5>HdCH5>HnCH5p>wH}CH5]>dHCH5J>QHCH57>>HCH5$>+HCH5>HCH5=HCH5=HCH5=HCH5=HCH5=HDH5=HDH5=H#DH5y=H1DH5f=pH>DH5V=`HNDH5F=PH^DH56=@HoDH5&=0HDH5= HDHDHDH5<E1H1cHtDH5<H~DH5<HDH5<H\RH5<HLRH5<H8(HJH5+8HJH58HJH58HJH57HJH57HJH57HJH57HJH57HKH57}HKH57jHKH5m7WHEH5Z7DHEH5G71HEH547HEH5!7 HEH57HEH56HEH56HEH56H FH56HFH56H)FH56H:FH56sHJH5v6`HJH5c6MHJH5P6:HJH5=6'HJH5*6HJH56H KH56HKH55HKH55H)KH55H:KH55HaKH55HrKH55|HKH55iHGH5l5VH@H5v5CH@H5c50H@H5P5H@H5=5 H@H5*5HAH55HAH55HAH54H-AH54HXBH54HbBH54HZHH54rH]HH54_HdHH54LHZ:H5l49Hg:H5Y4&Ht:H5F4H:H534H:H5 4H:H5 4H:H53H:H53H:H53H:H53H:H53{H-?H53hH3?H53UH@?H5u3BH?H5b3/H?H5O3H?H5<3 H@H5)3H@H53H%@H53H5@H52HF@H52H@H52H@H52HDH52qHDH52^HDH5~2KHEH5k28H EH5X2%HEH5E2H$EH522H2EH52H@EH5 2HJEH51HYEH51HgEH51H?H51H?H51zH?H51gH?H51TH@H5t1AH @H5a1.H0@H5N1HA@H5;1HR@H5(1Hb@H51Hr@H51H@H50HDH50HEH50HEH50H*EH50pH;EH50]HHEH5}0JHUEH5j07H[EH5W0$HaEH5D0HrEH510HEH50HEH5 0HEH5/HEH5/HAH5/H:H5/H:H5/yH:H5/fH:H5/SH:H5/@HK;H5}/-HY;H5j/Hg;H5W/Hv;H5D/H<H51/H<H5/HBH5 /HBH5.HBH5.H4H5.H4H5.oH4H5.\H4H5.IH4H5.6H4H5s.#H4H5`.H4H5M.H 5H5:.H5H5'.H'5H5.Hv9H5.H|9H5-H9H5-H:H5-xH,:H5-eH<:H5-RHM:H5-?H^:H5|-,Hn:H5i-H~:H5V-H:H5C-H:H50-H:H5-H/?H5 -H5?H5,H@?H5,HJ?H5,HT?H5,nH^?H5,[Hm?H5,HH{?H5,5H?H5r,"H?H5_,H?H5L,H?H59,H:H5&,H*:H5,H7:H5,HH:H5+HY:H5+Hi:H5+wHy:H5+dH:H5+QH:H5+>H:H5{++H:H5h+H:H5U+H$?H5B+HQ?H5/+Hb?H5+Hs?H5 +H?H5*H?H5*H?H5*H?H5*mH?H5*ZH?H5*GH?H5*4H?H5q*!H@H5^*H@H5K*H;<H58*H @H5)H?H5)H?H5)H1H5)H1H5)H1H5)vH1H5y)cH2H5f)PH 2H5S)=H2H5@)*H,2H5-)H>2H5)HP2H5)HX2H5(Hc2H5(Hs2H5(H2H5(H2H5(H2H5(H2H5(lH2H5o(YH2H5\(FH2H5I(3H2H56( H2H5#( H2H5(H 3H5'H7H5'H7H5'H7H5'H7H5'H8H5'H$8H5'uH78H5x'bHI8H5e'OH[8H5R'$ H5H5+$H5H5$H5H5$H5H5#H+H5#H+H5#H+H5#H+H5#sH,H5#`H,H5#MH),H5#:H<,H5w#'HN,H5d#H`,H5Q#Hh,H5>#Hs,H5+#H,H5#H,H5#H,H5"H,H5"H,H5"|H,H5"iH,H5"VH,H5"CH,H5"0H,H5m"H -H5Z" H-H5G"H1H54"H1H5!"H1H5"H 2H5!H!2H5!H42H5!HG2H5!rHY2H5!_Hk2H5!LH2H5!9H2H5v!&H2H5c!H2H5P!H2H5=!H2H5*!H2H5!HtH ;DžHHHHt&H|ADE!E1틕t݃tH5f!H1\A3sssssssssssssssssssssssss%1=sTsIR^ssgolCwwwwwwwww wwww2wEwwXwwwwwwwwwwwwwwwwk~~)_~)Qdwj!4GZm+>Qdw"5H[n)IQdwI"5Hu,?Rex#6I\o-@Sfy) 3FYl*=Pcv!4GZm}+;4.:FR^jv*6BNZfr~UHAVSHMHHcHEHHLjHEHHH褴==t=u,A=t=uHEHu0AQ HE!H;H5$1貐A8HH[A^]f.UHAWAVATSHMHHcHEHL$IĘHǘHLjt*HM11=tYu5I$HEI$QIHMHL=t&uHE.H;H5)$1A7 M<$AQHH[A\A^A_]fDUHAWAVAUATSHHL2H}DoHUHMDHLVIH~LM)u1E1>蠳HMt, t%#t 6uHE@M)HML1H[A\A]A^A_]@UHAWAVAUATSPIIH}DoL2H1I4LH)DH~ HL9r1H9#u HE@IH[A\A]A^A_]f.fUHAWAVAUATSHIIH/ HHEH!0 L L*HHLHIHJM1L1HIW)E)E)E)E)E)p)`)PHPHǹtQLذLLaLŰ1PH5 L1芍8H5  L蘰H5- L臰H5 L1P<H . H H;MuHĈ[A\A]A^A_]|@UHs&$w%H xHcHH5 13]H5 1܌<]H5^.H5(%H5H51謌#]H51藌<]ÑUHE1E1Bt0f.@<=tAtBIIBuBFA=HwL)FTL)HA"ILDAA"AE1HfE1FHt_ArY! t t:f.\t "u&AtAu\HAf.fHE1LH1A=]AE1I$#f.@HE1FHtAr,wIsE1\uAu\HAfUH]UHAWAVAUATSHxH+ HHEH00000001HƅHNTICATEHHAUTHENTIHƅDžauthHEHDž`t<=uA=0MMIHHHEH`HHU*Aƅt)H+ HH;E DHx[A\A]A^A_]LuMtH5uLH:Pt61f."tH>w THuƄ ƅH5!L軰Ht5Pt.1"tH~w pTHuƄ pƅpH5LkHP t:1f.D,tH>w 0T HuƄ 0ƅ0H5L Ht2Pt<1ɀ"tH>w THuƄ Hu L3ƅHu LHmd5-sessH308H A=1Hpu HHLhLxH`LpH5HUHHPHIE1$AE1H5OHU&IEHtXLH53AuLH5״uLH5JĴEAEDA\E1HHt AL`MǾH1H@MȾH1HBMɾH1HDMʾH1HFM˾H1HHM̾H1eHJM;H1KHLMξH11HNMϾH1HH=HpHxHLL1AWH0SHSH IHHk MLELL1Hp!AL LHHk L-DUHAWAVAUATSH8IIH7 HHEHH>H?k HII~IFI~IFI~ IF I~(IF(I~0IF0AF8AFLAF1HLL- A@Dž!f.fILMLAu7f@t AGItxADLHj IH LAHIM@Vt#AIxAD H1IHHa LMtQIT$0Ht-H= H1IHHa LMtHEHHzHMH1H K H H;MuH[A\A]A^A_]UHAWAVSPIHL=LL1I~KL1I~KL1I~KL1I~KL1I~ KL1I~ KL1I~KL1sI~KL1\I~K L1EI~K L1.I~K L1I~K L1I~K L1I~KL1I~KL1H[A^A_]UHAWAVAUATSHI藙H _ HxHIH_ LHIĀ8L? HtHEL-ܮLLe@IA$wLLtܺH=LH=LtH=L蟘H=gL蹘H=ULlH=LU8H=mL>!A$f.fHAD$ItAUD>tIMՈUEH}HHu_H?HIL냸E1C<HEHtL8HEL 1H([A\A]A^A_]E1H5 @ICtAUD>tIMՈUEH}HHu觇H臀HILHLM LVDUHH-M ] UHHM Ht$W@p@`@P@@@0@ @]1]ÐUHAVSHt%HL5L H~hAHChHL[A^] [A^]ÐUHAWAVAUATSHHIHt8))))))) )0HHLLH HHEHHEHEHEH0HEHL HdIHPLHE1Lx H5K A1E1E1IDf.EA$t0Mt+AI_I1AtӰ>f.DUH(wHHMU HMHQHU AoIc LHߨwMH([HHEMUAJ@AI:'H٨@MH($HHEMAIz"H<AJ@AIzH٨'MH( HHEMH$AAB@ {HߨMH(HHEMACMH(HHEMHߨMH(HHEMAJ@0AIzHH٨MH(HHEMAIzP!HHߨiMH(MHHEMGHWAJ@@AIzhIH٨pMH(THHEMNAJ@~MH(HHEMHEHHHMH8AIzXILULUAL LIBXAHAB`E1MH(rHHEMlHEHHHMHIB(E1\HEHHHML81MEEED,@4HEHHHMH8IzAAB@ AHHG LULUAL< H5G AHHEHG H-HMHHH@@HUHJxHHxHBx@ AHnILULUALLIBAH>AJ@&HEHHHMH8Iz0AAB@ AHHF LULUAL<H5F AHHEHF H-HMHH0H@@HUHJxHHxHBx@8E1IH5=F LAcAHTILULUALLIB0AH$AB8E1HEHHHMHAIzpIBpE1HEHHHMHAHI E1MH(HHEMHEHHHMHAHMH(HHEMHEHHHMH8AHCILULUALLIBAHAJ@AB E1HEHHHMHAHIJH"HEHHHMHAHIJhIJE1HEHHHMHIBE1HEHHHMHIBPE1yH}H&D H5-D LALUOLL5C H[xHS{tH;AHC{ tH{AHCC {8tH{0AHC0C8{`tH{XAHCXC`A1HEM1L5jC E1H5kC HMHULkHEHCHXHChH`HC(HhHC0HpHC8HxHC@HEHCXHEHC`HʀHSPHHAHHHHCHL5B HIG0MxHHMHEHME1MI?tHuIucHxIW@I(AtЃHdЃ VH]Ѓ0I GHу 6.I0MlL6H]HHHDM9L{HrE1L=f.@LȈI $HI<$H<tHI9uE1ltNH|1I$HDHt+@I$H|1I$HDHHuI<$H! I$AD$ DH[A\A]A^A_]fUHAWAVSPHIHq! H~IHCH;Ht AVHHCHLH[A^A_] f.UHAWAVAUATSHHMIIIHHcW HLAWL4IHt=DHHxHpLLAWHu H[HuLHL-IG(LuH HthILHt;HHLLGYI^MnH]IH}HwL4tIG("HJ LH< I~L1HH[A\A]A^A_]DUHAWAVAUATSPIIHL'HcW HLSM,MeMtGI$HxHpLLSHuMd$MuܸLLHHC(1H[A\A]A^A_]ÐUHAWAVAUATSPHtRIIIHHcW HLAUHHHt,L#I|$It$LLAUHu H[Hu1I$H[A\A]A^A_]@UHAVSI ~71f.@IHIIF(AF [A^]ÐUHAWAVATSHtTIG ~JE1 IHcI9}8I $N4I6Ht@H^LLID$(HHuAD$ [A\A^A_]UHAWAVAUATSHHUHIG H}tnI1fDAE HUHHcH9IML$I$HtHU LMtHLsH0LUЅtLHLIE(E1f.IHcI9}6IMNFHF]UHHHGHtHHHOHtH]HcGLcB D9})H2Pf.H H HuHL9|HG1]HOWH]UHAWAVAUATSHAHIGO H<HH IHM.I~I~AELHIFE9es-AUI~HDAUA}I~IvHAUEe I~AUI~AUDEtcE1HEfB;46EI~MMLuLAT$B;4\EI}LMMAT$HEIL9uA;EsDHL= L% fDI~LAUI~LAUHAEH9rLH[A\A]A^A_]ÐUHHHP1]f.@UHAWAVSPHIL?HuA_I^IvHAWI~AW HAWIvHAWH L1H[A^A_]ÐUHSP= t H 8H HH 3L,H߾t1 HH[]fDUHSPHGtH[]HH?H HH[] f.DUH=U uH=T G@ ]f.@UH1HtDH(Hu]fUHHHGtu&Hw H]vtHw H]ct1]f.DUHSHH(tgHHPt]H{ptH߾ ;H}RH{PH(HMHEHMH3 Hu:H{pt H߾;H[]f.DUHAWAVATSAIIHH{pHtH߾}:I<$LD.IHtIFH{pt H߾:L[A\A^A_]ÐUHAWAVATSHIH=11莞HIH;t @:tENH;uL`QII~PILLHtZHI(tOH}QI(HEHKHt2HUH)H9|&H5!1L1,&I~PLL1H LHH[A\A^A_]f.UHAWAVAUATSPIIH=E1H։1膝HIH;t@:tEMH;uL`PIHv Ht\HH@L8IILPH{uII~PILLHHt$IH@H L$H LL5 HALAE1LH[A\A]A^A_]UHAWAVAUATSHAIIHHMHH{ptH߾7I?LDIHtHH5EHL1n$IFH{pt H߾7MtHMȋEL1EH{puLYtqHMLLDHtTIH{ptH߾B7HLLDIH{pt H߾Z7Mt%1HML1 }tH[A\A]A^A_]LE1@UHAWAVAUATSH8EEL7HMHAIIAt%1HuHU@LE)EEHHEeHuHULHS㥛 HmHH?HH<FhIELLDHAă};IDH8[A\A]A^A_]fUHH= Kf.UHAVSIHt,HHptH߾U4IFt(H{puH L[A^] I>H LH{ptH߾[A^]:4[A^]DUHHUH L]f.fUHAVSIHtHEHH>HEL=HL=H HxHuH)HpH<HHIH]L)HLHz<I<ILxL`<LLHHuHEHHHpH)H6<AXt#IPHR IdžPAƆXMPAƆX+A&AH_MH=LEAH5lL<Ht*HtuxuoBw rRL}IL8uLy<B| /tL}E/1As aHL1?AHEAMtyEHEuiIXIELHMt,HUHI? HFCuMMuHU1IHUHuLFLjADžIELHMt,H3I?HBu MMu1I1HH HDHMHA HMAI LHAhJIHttI1ЅtejI LE1L)@H@4HIP I`LHAXLIHH9AI LI9|I@LHHM~7I+ LI@L'H5iL1A9Idž LALeȃIEHHHL=3H;LrAu`H[HuAK t,A t"IHtHH~H5L1 AH;tK}IEHHHL=H;L@H[HuI HG ILH=W1I FH]HHH}9HPH}HH]7H}] H}:8HtI8H HEI8H=H8t&H=H1脅I0HdIDž0H;I H_ I@x5I LHt=ILI@LH HHH=10I@LHrH=MILI@LH=x1քI HHزAK t6A t,IHtHH HHOHHDH HtVHpH5HEHHU1G#ADžu5}tXIIIH5ެH}M1#FAH HH;E DHĘ[A\A]A^A_]L6H}LH#ADžuM0ML%MDIIHIDHIDALMtI HLյLEIMHt8MtIHLLEHEHP HIDIHHIDHXILHt8LtIHH=YHEH`I`LtI(HH0HEAHMLMHxL@LHHPtAuuIEAt0`t'HPL8GH5<L1 AKHHL8 I?H5+<MMuL% HH5HUH}HpLELx1uATS`XPH@u HPAIH IDžIpKH w+HHsIH IDžE^I@|uAtIA3IH}u HE1HLIII8HHuHEILHxEHLAHE1H]*HKH}H5ǩ1AHHtLCMtHEuH}H51\u^LCHH5+LL1 A!AƆH/I?E1E1 AAE1H}H}t2Eu-E2HH5eH}HM1AAEtEuH5/H}AE|LHuk$ADžeL1HUb!ADžLHEHH(HMHH0HML`H@LH}}}!HEH0HtAH5H}1ADžILH}L1E1+AH5=H5H}1ADž|HA1HEA\H5H}HU1CADž-6A1HEAH5H}HU1ADžH5pH}ADžILH}L1E1!AH53I@LHHMHAwIEHHHL=٦H;L7:H[HuI@LHHMHAH}1HEHEL`8LH5<L1<A"I$E1HAHEEAH1HMgI HEH/HxAHEfHEAƆKAK t&A tI H1H5H}ADžLHuILH}L1E1HtAH5^AA1ɄHEHErH1HEL1HLEAj`IEHHH\L=H;L5QH[Hu/IXLHMHAPHxIXLM`LAxAAƆKAK A I HHH{ sIEHHH:L=H;L5H[Hu 0*HH1ۃ4 ,IEHHHL=HH;L4H[HuH;IEHHHt,L= H; LV4u H[HuH;uH5H}1ADžIEHHHtJL=H;L3u H[Hu$H;HtH5zH{CAKDAƆKH}r0AK t&A tI &H1I HAHEHuHpHH@xHIXLM`LLH5;H}ADž1ILH}LHE1"AH5L1MH5߲H}SADž-AAH5JcH} H5|H}ADžApH}H5H}HU1ADžI H}HUADžqH5H}wADžQHEHXbI$E1HAHEEAHL1HLEPSHHEH0Ht[L2LA*DDHEHH;U|5H5RLHM1 AƆxAtAdž@E1AAAƆxI@L1HEHHH L(AHEL`HMHHIEHHHL=H;L0u{H[HuzH;HH1 IEHHHL=̟H;L!0H[HuH;|HEHPH5H}1gADžQRI H}H]HfH;HtH5OHPAKH52H}1 ADžAƆKH5H}ADžLHu*H;HJH5ƢH}1ADžAƆK~H;HtH5HYAK%H5vH}1NADž8AƆKHDžhHhLHHhH}HADžH5H}ADžHEHpLILH}L1E1"t.AH5L1 H}衮H5+H1HEL1HLEE1u7fDUHAWAVAUATSPHLH(HHHMAIUMMt$I}H LH ILJt8DmuBIG0IG(HL迭IHHt"G#IGHIG0IG(HDmEuEuA$u tE1DH[A\A]A^A_]HIG(AH;H57H1A4f.@UHAWAVSPII1yL17Åt H[A^A_]A`u AtG1AtI@|uA1L1L tALD1f.UH勇@]f.UHAVSHI1 Åt L[A^]fUHH@|u1]]eDUHAWAVATSIIH#IIHHE1Ht"fH;LLB+u H[HuL3L[A\A^A_]@UHAWAVATSIIH#IIAt`tHPHHHE1Ht%DH;LL*u H[HuL;L[A\A^A_]@UHAWAVATStf.D<:t HuLwLDAt=L=ɜ @f@vtAFItxADLIcD@L#HsI@|LMHuHUH]HMu A`u AuI,H@A@LBHX LLAX M&LELDLLÅt(L5 L}I?ALAH8[A\A]A^A_]LmL+mL}M9MFM)I>t1LLMMtI>MLLMHMHEHH}HLEtL0I)u'GxX7I9cL=H]H IHXLHWXH`LHW`HWHwHwhHWpH2HXLL`LHOLGHGx1UHAWAVSPIHHHSHt*L{xHsL9~LTL{L){UE1PI=L{HCpHt3HKXHShHSHCIHXLHK`H`LCxHCpHCLH[A^A_]UHAVSHHIt))P)`)p)])e)m)u)}H0H8L@LHH HHEH HEHEHEH0HEHuHXbHtGHHhLHHZAHX HH, HH;Eu6DH[A^]H- I>LAH HH;EtUHAWAVATSHHHHsL5 H;AHHAIIHHt HSHH9vAIHL xK6HHrHIHt1HLHt2HLcH{HLL1Ls1"HN LHuHE H\A^A_]f.UHAWAVATSIIIHHLLHcHLAtJL= A@(f.@@VtCHtxADL:HIIIf.ADt+ Au A K A}MI@ I)LL MLILIA(dHCILW HEЁ8,AuAzAzk H5рHUHMLE1H EHMHE A u>A D$HE'AADLH521E'H;H5;HU1A A uxMI@Ht1L3L%LLuLH#u%H[HuֺH=sL\ HEHE H]E(ELELAKtD9~EKA|[AxtQAtAuAu5 Au)I L A A At>A u LH51UL航%Ae ADIHEЋ=0L}t=u-AtAƅLIExIDžAƅzAzuAH3 H=xH3tA_It1xH _{ D<@!Ȁ,uf.LuȺH={uLX tAƅLIAHAH=eL 1ۅ.AH=zL AH=zL AH=zL H=tzL ItwHEHCHu7@t)CHtxHz D<@!ȅu׺H=aH ADžH|H]H3H=uH;GHt'<*t Hy Lx@tTAu Aqt@1wHEIHHu虮IPAqtILhH3H=wtUHEЁ8uIE1mH=wHuH={wH ADžHH3H=wgHMЋ t7Au,H; HDHAH}HHAcw"H3 H=:wt ItHEH@zd*H;Hr8tDIAz/HH IH<H}HLHuHÅ1AIM@ M@Mt,M<$L LLH Md$MuH=]wLAƅADžpA(H5 nL1NAt5HEHEH0Ht>LIExIHu2HE2AtIExIDžIHtHE8tAt1AILLMAƅHEH8tzADž{H5WrL1ADžDAƅADžGAƅ;L3H5lLytKH5lLDADžL01ۉHX[A\A]A^A_]H5+L1?L HtIƀxtIL HtHA L HfHA H5>uLL1D;^Tf.UHAWAVAUATSPIHHFxHLH L9sLkprIH=rH5utL1sH@HML9LGLkpI@ H( H}LHtQL+mMH I@ ILkpHLLHCpJ 0HKpLsxB01H[A\A]A^A_]H5tL1ِUHHGHG0]f.UHAWAVAUATSH(IIHHHMHHEЀtHEЀyM1MHCHEL-C IIMC HwIcDLA$HЀ r#H%H??H~HcKH D IICA<$ uH{(lC ǃdH{(L9IMTIHEЀyu(HEЀuH߾LLdHEL0MM)L)s( C A$< < (HCHC0A $ t HcHHP HHcQ HHcHEЀu#HHcH߾ǃC A<$ "A<$ SC A$< t< u9IL$1< LDI)C Hc9}!H{C C t,H HH4HH Hu&ǃHo HHA $rHc҈ .HcCHDH}Hu\HC(HH9u 8"tpC 1eH߾LL uI=A<$ u1ILHC0 H([A\A]A^A_]kJa@wUHHcH ڐ H]H(ÐUHAWAVATSHL7IKIJLEH=pHtsCHtUL=m A@f.xADH]HH}AH;AtHE@HE@E1DHH[A\A]A^A_]UHSPHHJQHKHH[]QUHAWAVAUATSHHILLMMEH=cH>1L}LuȊCt}HL5j A@fxAD H[A\A]A^A_]f.UHSPHHǐ˓HðHH[]鶓fDUHAWAVAUATSHAHHEHEEt(LHhHpH;HðLhK&LHHH;HÐLHKHH0AEHL=nIDHID׋HMLEHHH賑H}H I<$HkELEHUH=]kL1;I$H}I<$LELMH覒uyH}tpI<$Hx HjELEHUH=jL1;;I$H}HD I<$t9H& I<$I$AE1H[A\A]A^A_]øꐐUHAWAVATSHAH`uIc3E1.!HLW)E)E)E)E)E)p)`)PHEHPHH1軑t?HAu_mL$3IĹHLft%AƃAu H.A<$$E1]HtE1HDE1NH LtAH HHǃDHĐ[A\A^A_]f.UHAWAVAUATSHxELcE1B EAHHxL7B@EƇILHhI(HE1HEE1HELuH}ȉMLmDEuBLH5qhLxL1AIH IdžAHEHH=JhLD1H8H IH]HH5*hH¹ALH, E`L=fH fLDHxH9It:HH HA$H5>H jHDH .HDH=gHDE17H0 IL}LH5]HtE1H=hgL1O7IHLH5(`HLL%iMH`LDHH5]jMHuHEHMtLMMMDLMMDH}H5fLHM1AVARHAMH DetLLE.H]H߾L}Ls LH5p1ZLHHh1E1lLmBDŽLuD}L1emHEuHD輍MP E1EL}E1f.fH蘩IP @HI9L1lHHùH}ȋuLLpbtNQiHHM؋}H0H]s}f.@Hp}H]|8MP HMHHAH*EE1HEIMcIA? AL}tLLLI'A}HLLLMLMA< t< LuMP EA(LAK>HUHLH5 e11EI,HDž`HLH`JEu'ELH5d1ֻHEDŽE11HEC/H=`LtHE8u E1Dm+H=u`LSDmtRAHE8uCLHHAL}LHAHLH EttgH=M\LH]t.HE8cIL1 HE!LH5D_HiAH]DmLuMP E1L}EtxLH5tc1xAƆyHMy HAHDHMHqHHpEu'ELH5b1 HEDŽHEDŽE1f.DI?}LH5WHXnt=HE8cHH5b1蔹H]HHELH5"ZHNLH5bHUHM1(L~H]FIH]lIxK^ƃLH5|a1 HEHx ALuLmD}MDeU8HLmD}MDeUҸELuIUHBu0BDŽLH5a11A+DD}IHA*UH5<`L1&A8MH IH]rL}E:HH]=L5YH}L1&HH(HàH|D:LHP1^&HL<IH|D:LHM17&HJ8HJ|8BD8:LHx1 &HL<IH|D:LHH1%HJ8HJ|8BD8:LHh1%HL<IH|D:LH`1%HJ8HJ|8BD8:LHX1b%HL<IoLptcLeE:HH]xHmXH}1%HL<(IǠIrHH]~lIA:IH%XH}1$HL$(IĠIHH]IA$:IH]IA:HWHP1n$HIII!H}~Iu;A:IH]HtGA:IHvWH1 $HIIH]IH~Iu5A:I+IA:H/WHx1#HIIIH~Iu;A:IHtGIA:HVHH1#HIIIH~Iu5A:I+IA:HVHh1A#HIII#H~IuYA:IHLpMgA:MH7VLH`1"LcMLpHfH]I|$A$:HUHP1"HIII"H}~Iu>A$:IH]HyJA$:I|$HUH1E"HIIH]IH~Iu8A$:I-I|$A$:HQUHx1!HIIIH~Iu>A$:IHyJI|$A$:HUHH1!HIIIH~Iu8A$:I-I|$A$:HTHh1]!HIII2H~,IA$:IMHLp*A$:IhIMIEAM EE EMAE$HTH]H1 HH2HML)H.H9HuLiLIMLpL{MHLp]IA:HSHX1; HIILHpSLH`1 LcMHLp~IuA:IHuA:IAHEHLHH;@v3^E1HM HH;Eu1LHĨ[A\A]A^A_]HuLlHkM HH;Et- 럐UHSPHHP HtH@HXWH[]1H[]fUHAWAVSPIIHH Ht>L8HKHt6IVHMHDH6HpLpt+H2H~LCHIDH1*HW@HS HHBHHHHKH[A^A_]UHAVSHtvIHtlHHFI96tHKHAHCHtHH IHtH@INIFH3HAVWHCH HIF[A^]@UHAWAVATSHIHI_HtIL%× Gff.@HHH3LAWWHCHA$IGtRI_HtHCI9t$HKHAHCHuIOf.IHt H@IGH% L[A\A^A_] [A\A^A_]UHHG]fDUH1HLGMHFH97tLNIAHFHtLH HHtH@LOHGILGHBHt(LAHyH~HNHILJHyHIDH7H2LBWFI0HHB]ÐUH]4fDUH]*fDUH]fDUHAWAVSHhHIL}LHHaLHމLLHh[A^A_]f.@UHAWAVSPIL= AHt*HA~AHCHt L3HAHb H1HH[A^A_]DUHHHP1]f.@UHAVSHHHHwHQL5 H{AHA1[A^]ÐUHH H}HEHuH5H}8tHMHtHUH;Mu BH ]H ]f.UHAWAVAUATSPH)XIIH?H HHEH`HHML8E1HL5L%]HHDžXHHАHPH`%2H%u#H`Huf.fH@XHxHG D=LPHXuLS1LLWG @V0HAD=u@$uXtH`HljXHcH9H(HLE11H0E1@D%A f.@A H` IH`HZ/IcLHGH`ZIc LA H`AH`AH`뤋XH ?F D=tEH1H)F f  HHD=u<$ut H`ʉXA@LcL9ILH` 8*HGH`XGH E D=XtPH1HE f.f  HHD=u拕X<$uXt H`AHcH9HH0HLH`tA@H`dAH`TAAH`=ÀH`*AH`A u>A H`AHH` H0H`A@H`@H(HH3wEH HcHHHDŽ|HHDŽA^HHDŽGHHDŽA)AHHDŽHHDŽAHHDŽAHHDŽAHHDŽHHDŽAHHDŽkHHDŽAPHHDŽ D=H0ItII1H> f.  HAEID=uI<$uItLcIL8II/HHHB=@uHN=MHXHHGH GLGDePuLLDo+tpHSLSHH+HlHǃH{ E11H{(1Hr HE1L[A\A^A_]H=t/HC HwH=[HC(H^HHIHX`L Hǃ8Hǃ If.@UH]f.UH忏a]lf.fUHAWAVAUATSPHt2IH? u&IHtAMu I`tH[A\A]A^A_]H=)HtGIKAtAGAtAXu'IPtAXu/IFPIGPAGX1WHt IGPAGXII II~t IFL8IG IGM~M~Mw`1L1gAFAFWApIIHIHI`IpItaHU'IAIE111HUIHxL9|lp L9 D9E1ZLDHt@IHUyAH:uAxeWIhLHA`BAHUIHHI;puH 1A;x@IhLLA`1fDUHHHo ] f.DUHAWAVATSHLg`MHIHljHS㥛 HHHH?HHHH}i)iΉu؁@B|HH}ЁuMKIKAKHutW蠴IKH~ Hu@tL@I$I$IK%tH5N(L1}EAIKMKI$IKAKI$H[A\A^A_]UHAWAVAUATSPHcIH? SIHBA$M0I|$`"El$I|$HL9'M|$AwAFLI?Ht!AD$wKID$L IT$`HI$Ku A$Kt{DmAI$KHHI$Kt*H5'L1I|HsH1H{uIDŽ$KADŽ$KDDmA|$XuID$PAD$XI7Ht:u Ln3,1M|$A1AAt$L I$xLI$KHt1oIDŽ$KIDŽ$ AD$LLID$HtHIID$`I~ H7HtfDHL9`t HvHuI $ID$HtHI $1PI $ID$HuINIVHqHHDHAF1I`ItU8IAIE111IHxL9|hp L9 D9E1VLDHt@IyAIpu AxtsIpWIhLHA`LAIHHI;puH 1A;xt$Ip@IhLLA`1ۉH[A\A]A^A_]UHAWAVATSHG(L MIL1MtxLM<$Md$AuAGLI~(H1IKAKHut1ہ?BNHHӯHy[A\A^A_]UHAVSHW`Ht{IHKu AKtdIKHHIK;t%H5#L1xfHsH1H{uIdžKAdžK[A^]UHAWAVAUATSHHL;E1APLpAUH}LH/L%$i IA$ILJIA$ILJA*DHHDesAHH@AHUt HDAE*A*tHc*ADEAEƉEHXH`H@HAtAu )AƇPLHsXHtL8VHCXIJH*h ILJJAtt u D t%Hߋu)DmADEDDHEIO`H HyHcAHCHHtCI H9A0v6H5!E1L1vL1/HtIL8H1l)ME1HEI9t&I8 HSPt)HKDeiILJ8 MIGVt HPt HHH H5 L1vHEDmHL(DH[A\A]A^A_]fDUHAWAVAUATSHxHHHxHs HHEfvfEEHuHMHt EHHEE1HEH`fDEnLeIIiADAEDLeFdDeAt!H}Hu_FI f.E11MDhADDMtE9nHxfzDeDeAHxtH}HuEIHuKHe HIHEIEAF H}HuLDHHC0HHK8MFH}DDH}LHGLHEHGHEE6HEHhHEH`/H}LHGLHEHGHEAHEHhEE1%f.EIHEHcI9B\81f.@;\tHI9u]tH}H`DH}HtHHEL(MI`Ht1Hxr:H9:u5HpL_]tdI`HH@^1IXHum1IXHt_HxrXH9:$HLB]IXHH@I`HHHpHH}IXHuHxHA0HtHI8LBH}޺Љ]H}HhBH}IXHHHH}nAHH8DHHu螛DcLH HH;EHx[A\A]A^A_]19f.DDuH}HujBH}HHEHcH9}Dt8DuAtH}HuBH}HtIHEL(MI`Ht*Hxr3I9?u.L[tZI`HH@T1IXHu\1IXHtNHxrGI9?OLm[tiIXHH@cI`HHIH}IXHu HxHA0HHI8MGH}DIXHHIH]Hw2AƉLeL1֔tHA MDHut8]Hw,AƉI1蕔LtH MDD9DtD]Hw8AAΉLeL1<tHA UDDHut6]Hw*AΉI1tHA UD9ʉDHE1H  H H;MuHH[A\A]A^A_]貓f.UH1Kt]HHHtDAAP wHAA wH JcH]ε]&]&`u tpHtE;@D]HHIPHM]11L2ω]ú]KpZZeeOOOf.fUHAWAVAUATSHHH HHEиHIH?  IHULEI$tDIƉUI$E111I$HxL9|2p L9M9E1ILHALEHcI9ljALMHȉMI\$E1HLuf.HHHLDAAAAϩt̃}tƉDAAAAשt}tDAAAAשy}oDAAAAשI}?AA&HUAE1 t!H Y HHHu J1EMd$ME1fDM$$MLHuuu%u<ЋMD fDAMtۋMD fDAMtuu4uO|f.fMD fDAMt̋MD fDAM2uu(uCMD fDAMt؋MD fDAMuu(uCMD fDAMt؋MD fDAMtMD fDA_EDfDAFHEt[AE1 @HI9tAA4 ADfDA|f|ADt̉ƒ f|AAEHDUVdE1DO}UHrAAHs1d1Df.LfALOLfALOLfALOLfALHH9uMt5HLA1f.fA 7Lf HI9uAHV HHEHtD 1H [ H H;MuHH[A\A]A^A_]fDUHƇ]UHAWAVSPIH;ADžu"H1f{tCLstDH[A^A_]@UHAWAVAUATSHHI脛AMI> IAH]I^E1Ht!fLLDHoDEHHuH]f.ILDH{IHEHtHH(LDLH}uAFHMȉEI`ItS貚IAI111蚍IHxL9|_p L9 D91NLD莚Ht9Hy9Ipu AxtgIpWIhLH@IHHI;pu H A;xt"Ip@IhLHA`DH[A\A]A^A_]UHAWAVAUATSHxHuUEEEHJIρM7HMgIGHEIKHEIG HxE1LeH}fAKtiILE1LH5 L1bAGwAE1tAGLAƇKIGf.DHEHHuA$J oƃtHLHEHHH]t2A $Q wL8Aw1҃ LHuHx_A$HE1H HcHE1L^ HEȃ8tAGL L@TC A$t/H}uI A( LH5 $H}uI A( ɗLH5 H1EdE1A<$ ArH;80AAH߾M(MwxH}uI A( ZIIwMGxLH5~ H1cE1A<$ ArwL/SLHHUHMLE1kAŃY~HEȃ8tHEHx(HwLҷE1ADDE1VH;HHLe H;1HUAŅ`}VH`u t / E1LeA<$ lH;Hu.eAHH11ALeA<$,AGL躩H;HuAŀ}EtELHDoE1ADH;HuAŀ}}EtHE LeA$9_AE1E1 IwL1ɃɃ A$9A $H  HHH]uNAbE1E1E1LeA$9A $H 6 HHtLAE1E1wAHEȃ8E1kHHxH.HLH5UH1UH]HL} A$9AE1E1H]f.LeH]AG M(Eo0H{ HwHx1ɅIAfA$YH}L=E1AA)H]HA$AA$A $H  HHLAE1E1I0HI` IIP EX E$IIzA}L IGH`L IGH`HHtSL(褊IKAKHut(1ہ?BNHH]H舊H L19H}IAXIH}H{D IHuILJL^AAaDA$7}&E1LeA<$A$ALeEWA7H]H;HEHumIމÅHEHEAݸ7DDL:LD1-AH}7t`HuL(H]XAH}HFC E1Et(H}H'C IHEILJAE1H11>AE1GAH]E1OE1LeI8H~?Ix IIh Ep E$dFIE11*EDE1M ME1A<$eA$XIAM9LmLA7L踝AIE1HD1u}LeHE A$9DH}HA E1AH]*HuLDkALuLHS㥛 HHIKAKHut^HH?HHiH})iAA1A?B@ANILE1AAHLHuE1E1E1hHEE1E1AHEȃ8t5-HEȃ8tAGLZHEAE1E1H}H@ fHEȋ!EtzAƇKH}IH5I:IGHXLIGH`LELe1A@H;HkLeH;E1Htu:tlH;=A$9u{AA*LeH]uQ]LeA$u L'A$tAGIG`@A$LeH]f1AA $rIG`@H E HAA*HtLH}AH? AE1HEȃ8^AGL~IHH]}AHHHuPAE}teH;Ƈ9OȃpQ@}Let-H]HA$tE1 IA$ *IIfLI E11`I(1UI_HugIP3IP11IX13H; LD[A\A^A_]f.DHǃ HC`LMtL#{XuHsPH)HCPCXf.DUHAWAVSPHtDHH? u8IH{ sHt'H{ H7L61ݡH{ THmAE1LH[A^A_]fDUHAWAVATSHHHX`Ht`Au܃tUILHuܺLoHt5LK0MtI<$HK8L@DAD}HuغLH[A\A^A_]UHHIt&)`)p)U)])e)m)u)}H@HHLPLXH- HHEMI:  H0HEHEHEH0HE'~F Ny H HcHMH(HHEM H HcHMH(HHEM-N~C.Nf9uy:u2MH(HHEM!Na$NMH(HHEMMH(cHHEM]MH(_HHEMYMH([HHEMUMH(WHHEMQMH(kHHEMeMH(gHHEMaMH(kHHEMeMH(oHHEMiMH(HHEMMH(HHEMMH(HHEM~HEHHHMHIjHEHHHMHI OHEHHHMHI(4HEHHHMHI8HEHHHMHI0HEHHHMHIB8HEHHHMHIhHEHHHMH8IPL5,HEHHHMH8IXL2.HEHHHMHIBHpHEHHHMHIHXHEHHHMHI`@HEHHHMHIB@+HEHHHMHI@HEHHHMHIB01H H H;Mu H]ke%DcVu@UHAWAVAUATSPIЉH11AƅH`HtUyIAHE111lHHxL9|`p L9 D9E1NLDyHt8Iy9Hpu xtfHpWHhHH@AHHHH;pu H ;xt!Hp@HhHL`DH[A\A]A^A_]f.@UHAWAVAUATSH(LÉMԉUAIxEtALH;AI]HtLHUHHuDIAH]EЃt`IEHu̺KHtNL0AM@IFHtQUt+HXHtH HtL13WAp1tH`HtHHtL0UIFHtHA|uLLDLIFHtHA|u ǀ LLBwIAE1@Mt"LLDLÅ LL ILDHMlIHEHtLp(LDLL^H}uAEHMH([A\A]A^A_]f.fUHAWAVAUATSPIȉщH1AƅH`HtUvIAHE111iHHxL9|`p L9 D9E1NLDvHt8Iy9Hpu xtfHpWHhHH@AHHHH;pu H ;xt!Hp@HhHL`DH[A\A]A^A_]f.@UHAWAVAUATSPHIuLH AƃI]HtLH%HHuEI`ItRWuIĉIE111?hIHxL9|_p L9 9E1NL4uHt9Iy:Ipu AxthIpWIhLHAAIHHI;pu H A;xt"Ip@IhLLA`DH[A\A]A^A_]f.fUHAWAVAUATSPAHHH? utIHtZ5tIAHE111gHHxL9|3E1p L9D9~#LDtHHEI IM.E1DH[A\A]A^A_]ÐUHAWAVATSHIH- HtMILۖHt"IHtHH8pIAOsH~>E1LLL胔t7[A\A^A_]fDHH8pIAOKsHIH[HuHi- L[A\A^A_] @UHAWAVSPIIrIHS㥛 LHHIKAKHutQHH?HHiD)i1?B@NILrH~ H[A^A_]LLH[A^A_]6fDUHSPut*HHLjHu Ht HX1H[]øH[]f.fHt UHH(]1f.Ht UHH0]1f.Ht UHH@]1f.Ht UHHH]1f.UHHP]UHHX]UHHHcHH H t 1HH]1]UH1; ]ÐUHHm+ ] UHAWAVAUATSHHHIHH HHEHH8HH5 tHbIM&HLbAHdHE1DžDžDžL4f.HH߾LL,bHHH5^HdHtIƀYGHLAjE1ADEE1H5H8dIH`I<$Ht?tHHHt 8YEteAtAuuyH=LiADž^f.DH=\LqiA2H=GLOiADžAtpHH;H( LH) HHcDžDž1H=/mLht:DžDžDžDžaH=nLE1hE1ANjDžAEƉADžf.HL1hE1ADEE1H5H(bIHPI<$Ht?tHHHt 8IAt4AtEuH=LgAuH=k@u=ukH=zLgADž9H;' LH?' I$HADžHH;H& LH& HHaADžDž1H='kLftDžH=LE1fE1ANjDžAEƉADžH0H=vHthIH=T HsH H1IH& LMtvH5 oL]HH% LIMAa^^AHtJHp0HtAH= HzsH 1wIMuAALL\HC HH;EuDHH[A\A]A^A_][UHAVSA1ۅþ11\D1[A^]\UH]UHAWAVAUATSHIHEHEt<=uH5L13=IHEHUHHÅtH[A\A]A^A_]H}HtAFH} rHNTLMSSPH9utHA$ H5HE0AFHEH@IFAFtzL}1I0rjLmI}(0LmI},01ftGAŃ0rWB)I9rKIH# HIFHtHDHuHHHo\LANH# H}1H5L12=Hd# H}H5L1u2UHAWAVSHMIHH HHEH# HzHCCHFH$H$W$D$xD$hD$HD$8D$(DŽ$DŽ$D$`D$XD$ D$D$D$$HHH1E1E11P 1HLM[H  H H;MuH[A^A_]XUHSPHH" HHCCH[]@UHAWAVAUATSHX LLIIHH H HHEDžLHDžAHWH߾\4[Hu H߾/"[HH)LpHLDL-LEHDH(Mt L[1H8H-H51H 10AL0H@H`H Hߺ(ADž HHL2ADž LLLH8LH(4ADž H0HPHH`H09ADžo HH`HLLH0m7ADž< HHHYHAL0AGH H@HHL1ADžH0HpHHH,H`HL.ADžHHH`HH>,H@H!'urHHfH0HIH`HhH`HPQuHH L0A1HHHH8HH(H⋅LHHXHHHHHH0HHHH0HًXHIÉDHDDH(HH8HH@HHHVHE1E111SATASjjjjjjjjjjHSAWSAWjjHSARSARjjHSSjjjjXHSSjjjj@jjjjj譢HİLcAw%HJ%foB%IL)I9H@HsI<,HULIH= HH(M<H8MMIr H5`H 1T.A3I<,HuJLMMTIILL1bpH[A\A]A^A_]f.@UHAVSHL5' H>AHHL[A^] fDUHAWAVATS1HtnIH`HtbIHt;HHt3f.L#LALLHIu H[Hu1H5LL1[A\A^A_]UHAWAVAUATSPIL>HtgHH=mIŸMH;HtBL}HL=8 AHtAIIuLHmt7H;HHuL}E1Mt L1nM.1'L1nL1nH LH[A\A]A^A_]ÐUHHH ] f.DUHH`HtHHtH98]1]f.fUHHXHtHHtH98]1]f.fUHt]ÀQt1]HXHtH HtH99uƆQ]UHt]ÀPt1]H`HtH HtH99uƆP]UHƇP]ÐUHAVSL7IdžFÅu4AuAuIH5MJ1wAdž [A^]DUHAWAVAUATSHH HHEL7E JHAI A HDJAMIH*fWf(fTl fUfV^H,IIWH*^H,II9`IcHi򫪪*HH?H 4v)IH9HOLcK LHI E A AA Lhf)P1҃| HcHiɫ*HH?H ɍ I)ȉALHI A HDyIHHEK K+ H=8A|FH*WH*^ ^H,f(PLhDIIH9HO-HiHH H f(PLhtHH1IAE1@IpHt+IIIIMЅuK_IhHt|IWI*WI*WI*WI*ЅtH5L1AHB HH;EDHĘ[A\A]A^A_]I9t@xYf)PI LHtIH5W15IH5o1 A Af(P@ t3IH~'IHH H NHHHHF11HPL,@@t3IH~'IHH H eHHHH]11HhH9HOHL)1HHOH} H|HHrLA1ɨ H1Ҩ@HJ2J1IIH'|4HHH(\(HHHHH H t0HHHH~)HkdHH H HH111H'|$HH(\(HHHIHHIkdHH H BHHf1H'|$HH(\(HHHIHHoIkdHH H HHO1HHMHucIHuSIHuCIHu3ILmL IH]H H5@E1LHHHMLhLM1SH]SHrSH|SAUH]SH]SP H@I6e1%1eg5f.DUHW]f.UHHxH@]HLJ]UHHxH ]HLJ]UHAVSIC wH @Hc4HI0 A8 [A^]I A( [A^]I A( HljHCA[A^]I A( HljH}CA[A^]I A( HljHTCA[A^]I A( HljH+CA[A^]I A( HljHCA [A^]BI@ AH [A^]I A HljHBA [A^]AjUHSPHLJ BH  HǃP ǃX Hǃh ǃp H[]IHuEu1H)HL9|QUHSPHuHiHL H t HIH1AH>vHDA1H)HOHH[]f.DUHAWAVAUATSPIH7ALH8H~yIALh p LH+x MuuLh Dp Lx DH@H=Γ HI!&ILL &H HH;EuHĨ[A\A]A^A_]m$@UHAWAVSHIHHt,)@)P)`)p)e)m)u)}L H(L0L8H HHEHHEHEHEH0HEHP HM@XHHt*Ju!HP H1rƃJtWLP L&IH=?wC> HP BD8ILP HxHt2LH1LLHB HH;EuRH[A^A_]HH= R$HLL;$H HH;Et"f.UHAWAVAUATSHIAt5)) )0)@)P)`)p)}HLLHi HHEM}HHEHEHEH0HEHuH)tHHL}H1%IH]IE1E9D@LLLLEAhHHx/H}tLHM_I)t3IDDDuAQu!1AH}uAE1 EuA7H}H H[ HH;EuDH[A\A]A^A_]!UHSPLE19DLEhHH1HxH[]ËMtQuHH[]ø7H[]ÉH[]DUHAWAVATSMHHcƋ@HH1"#AHub@ D8I$wHLs Q18L#HDf.H5BLH1HDJH7A[A\A^A_]UHAWAVATSMI19D@1HH1x"HuaD8I$wHLs Q1:I$LD-H5HH1I$DJH7I[A\A^A_]fUHAWAVAUATSPMIHcƋ@HH1!HAHuMD QAt7A#t1M/LD-H5 LH1zIDJ8AHH[A\A]A^A_]fDUHAWAVAUATSHI1HIHH?t@,1@1LHM$HL@HH}Mt^f.@I@@IBHLHAH=`H9H}GI1I)u1LH@HCI@Is89JLJMH IHJLH~HIJHLLlIJMJOH@@E1HH}HMuf.MM)I@A@MBHLLH=L9MH}tHLLAH=tL9H}tH5H LHHHLL}HEHJLJǀJNHEH@|unHs LHt7HHLL,HEHJLJM̉Jt1=6H5LH}HL1sH5H}1ZH[A\A]A^A_]E1HH}r^UHAWAVAUATSPHIAIL/Ht AuLHAI$@x A$AMHAKt)A> uIvHLHIKAƅKL HHI I4HHH9r:H9s` uS AƅKHfZHIKHHH9s: t u fΈHH9sL)HLDLHH[A\A]A^A_]yfUHAVSI11HtIQ8Dك#Dى[A^]f.@UHAWAVAUATSPMIHAIE8HHx`ˁtjI1E9D@ƃ8Iu^IpMxI)M9MCMIhHHLUMpAƇM.}1E9D@IIH0H@HEL9IOE1IH@LELAXHx/HEt IhLHIxIpI1EH[A\A]A^A_]II@@IBIhA눐UHSPH pHHt! HH tH} H1HH[]@UHAVSHIt))P)`)p)])e)m)u)}H0H8L@LHH HHEA~H HEHEHEH0HEлHHc HMH(HHEMMH(weHHEMbMH(weHHEMbMH(HHEMMH(HHEMHEHHHMHIFHEHHHMHIFHEHHHM؋A 1H#Hc HI~Pux111ҹ臿IFPHEHHHM؋A!w?1HHc HI~PHt$IFPHEHHHMHIF1H HH;Eu`H[A^]I~XuIF`H xIFXIFh1HH I~XIFXrfa1IHuuee@UHAWAVSPHtJIHGHtIO1At0IGAHIW1AI IPIXHtHI`t8EI`r(AxIXH$IHxM;w`rIXH IGHt IW1H LE1DH[A^A_]fDUHSPHGpHt1sL@MtHHAH[]UHSPHGpHt1sHHHt HPH[]ÐUHAVSIHH Ht2H@L0Ht&Hf.HHRHuHA1HH[A^]f.DUHAVSIH HHtSHHk Ht1H@HMt2Lf.fHHRHuHAH/ HE1IL[A^]fUHAWAVAUATSPHIE1L% L- IMvMI>A$HtKHÿAUHt.H@HMtLHHRHuHAMvMuGH HMt3L5u f.I?I_AILAIHuE1LH[A\A]A^A_]f.fUHAWAVSPHt0HL5 H;L{AHHALMuH[A^A_]ÐUHAWAVAUATSHII׉ILEI1HEI<$1Hx^A߾Ha~FLLHMQtAƅu)HELH)t/AHtIHEIADH[A\A]A^A_]LmHEL(E1DUHAWAVAUATSHxMƉIIH HHEA xHcA@|M L1HLpADxt-AI>H$HHDH5LA1|1H5LL1bfDžALpuiHƅM'LH=H5/LMH5ZL1%H HH;E?HhLLHhHHHH@HJD{A&HC HHH@H5HL1<H HH;EHHLHxLpHHà xL`u@DžLILcLHH=II1HDHsDLHL QtHHH)HIH`HH5H5HL1nHhLALpH5 LL1:H HH;EtXH`HHuHptGH5fH5/Hp1H^ HH;Eu~Hx[A\A]A^A_]C<waH IHcHxHږHsHDH511?|ϯH HH;Et DDDAAH5=1SARDDH51j[lDDH51j\5DDH51j]ScHxfLUHAWAVAUATSHMAIHHH HHEIcA@ M9A Hz HAtH5,LLD1LDHHr, Lt'I>H51Aƅ LL1H5 H5oT I>H51ƅpHÍCqfDžr 1H5H(Lꋍ1Wˋ LpLLLuUqHH9uA߾謬߾Lt_uiI>H5I>H5(H5gH(1Hn HH;EH[A\A]A^A_]I>H5`E11AI>1}H߾HLLH0QtH0LH)t/HIIII>H5Ӗ18MIuRpuUq<wUH HcHHH8H5_H5{H5H5dH5I~HtiHt_H IH IƅpDqMt:VHrHLd H5cfDžpE1E1I_HpEdHtMtH<+HpHL7LLpLL LHH;A1L0I>1[H H LLLnQtaH0LH)t HIIHIH5+LH%qt!pH5bH(1fDžpƅrHLHpd[HH/L8M#H0@LδAGƅsIG HtHuHv@wH5H0H(1ƅsHtHuSHHHfHfpHHpLL HIL;A E1L0I>1!HM H- HLL4Qt H0LH)HHIIH5H5iƅsIG @tH5ǔH0H(1F$H5ҔE1H0H(1PHH(عMH5H(H1MI !ps<A <utLhHDqE-s<F<U<tuDvDwDxAAH5H(1ARASHHRH5I3AHzMe1HL0LI>1H Hk HLLQtH0LH)HHHIyH51H(1= ͤktuDvDwxH yHzH{H|H}H~HHDAADDDDH5CH(1ARATAWAVASAU JHpTLpG|5CD5HuDCL5 DqH5H(1G|5HLH9H5BNUHW( ]UHAWAVSPAIHHxiH(t_H( 0 GHtHHH; }8H( 0 LD H(HiH)~IHoE1.L( D0 E1H tHi(HH~t_IpHNH9IH9_~+f.HNHH~H>t-H2H>HH9_~H7HtH9^|D9~ HHHIHHNH HMHHMHNHHHNHHHH@IH8[A^A_]UHH3H*L^DF Iu4Au.HH HNHHHNHtHHH:1]W)ELMML9_f.| D9G xHOHL9Y|D9A }HHGH9Hyu b@HIIHAH8IL9_~'HAHHyH9t-I H9IL9_~HHtL9Y|D9A HHHIAHAIHEHHEHAH9t ]ø]HNHtFAH 1]HHL^DF W)ELMML9Xyf.f|D9@ e}~HHHtuL9Y~H|D9A }H9HxHHytTIIHAHIL9X~ HyH8HAH9t-I HIL9X~HHtL9Y|D9A HHHIAHAIHEHHEHAHFHAH 1]HNH 1]ÐUHGO<C]fUHDEtKHtCEBEJAAACDAQAC8uHDHEuE1ABAJ<ACPp@C18]fDHHUHDEtYHf.@tCEBEJAAACDAQAC8uHDHEuE1ABAJ<ACPp@C8]H f.UHAWAVSDEtdHf.HtSD>EtJEAEQAAACE_EwAAAC8u0HHDHEuE1Ht:D>EAEQE_EwAAABAAAB18[A^A_]f.UHHt21DDEBEJAAACʈ <t HH9u]UHDEtKHtCEBEJAAACDAQAC8uHDHEuE1ABAJ<ACPp@C18]fDUHAWAVSDEtdHf.HtSD>EtJEAEQAAACE_EwAAAC8u0HHDHEuE1Ht:D>EAEQE_EwAAABAAAB18[A^A_]ÐUHAWAVSPIIH HHHtHLLHH[A^A_]UHAWAVSPHIHٻ IHtMu H LLH[A^A_]Ã\wUHHcH H]Hّf.DwUHHcH H]Hf.fwUHHcH H]Hf.DUHAWAVATSAHD LƃDLtA>uH_LD1@ƃL HtHL)H|L HtHL)H~D; tD L[A\A^A_]UHHH}1HEUH]UHH)Hi)HcHiMbHH?H&HH]fUHH)u)*^_ ]H*)*^_ X]f.@UHH]ÐUHAWAVAUATSHIIHzm HHEL/HcAtHIH III`LHAXLIAt+AuVH5ҐL1A*3I$@|u>At AtIAIcH9v+AH5H5L1AAAst L%zAbHyL%bLDHsH}ž DM1B>IHcH)IB:Hu]HcIL HLHEuAƅxLMAE>1H k H H;MuH[A\A]A^A_]pUHAWAVSPHƇtE1H H(Ht"HE111ЅtcH5pH߉HHHtWHH߾AH5bE1H߉1CEtH5gHD1ZAADH[A^A_]HXLH;j uH`LE111uH58H1 f.UHAVSAHtFHHHt7uH9)H5> H9|H5E1H1ƃLD[A^]UHAWAVAUATSHHHMIIIDLJtuA*uAI1HHLA t!Au0H5L17 1菿AAtItE-A!AH]IDeuIu L8AIHAILEL AtIHMLM}HEIHII;@LuAƆxH5ّL1HEIH)>IhIIdžAx%HE ALV AuAH]ELmAEHEAdHHEE1HED@x0AI0Hɸ@HDIVxHt/Au%IH)H9HLHf.AI`LLEv2IHurIuhLKA@tQI0A8v;(IL1iH/I^xIAI A( IHMFxH5%fLH1eIAxxxAH}IHx`IHUILH5L1ʹHEI)pAƇHEIHEHEHUHMLLӅu[}zHEnAL*u$3AE1E1HUL@TtHH[A\A]A^A_]Hc}H_IEHIH5SL1IFxHt)IHH)tIKH9tIA3A (H5L1讻DL觇HE&H5dLH1rHMH5{L1CAsIuAbIJu$H HHIJH11HHHHH9tOIIJ uHQ IJD AbuI@LHtHI@LH9u1IH5LH1Y8IJIIH5L1$H~H5L1I9Fxu1H5L1谶LHE HEDH5L1诹!EHHELHu1\AƆLLmAEAdžL0H5xL1/LbH]1A}qf.fUHHH@XHt]1|^LAtу1uAt*u,DD9u t1҃D]fUHHHXHXLH`L]f.@UHSPHHPtHHt$H[]H5H1BH[]HǃƃhJƃJǃKƃKHHHHKHhKH HMHǃM0HDH H@LHptHcHxtHQ/ƃJu HJHxHSHkHHtHg5HHtHS5HHKHhKH!PKH!pK1HLuHxLHv1H[]UH倿t1]HJ 1]f.UHAWAVAUATSHHAIIHW HHEЃIIHt H9|H5}L15/=AƇhJHIAtUAht#H I`ILJ`AƇhH IPI`HAƇhH5HUHML1AŃu`1L&f.D1HwHIHHH t?t܄uu HHHHIPH HøH)DmDuH5 HHxHHDE4$A/H]IA|$/AMl$H_ HHDmDuAL5LeHEHD HIAA $1 t$?ttAyپHL1'!DAu +HIf%2C0HIHȡ H}}EH]IM H?VHtE4$MA?A?tH߾/EHtEeH߾/HHHILD1A.MIU1A}/@IEA|u.1z.z/xLjz.Lt>LL/IL?MtYL9LHBHIDKMHt+t,L/Htu&IHuE1IAHtIIݰ1LD1HsHIHHH t?t܄ufDu HHHHLuLeLuLIHڟ J<#HHHHLLAEHIGA8AH(<HIGA6AH(:HIGA4AH(8HIGA2AH(6HIGA0AH(4HIGA.AH(2HIGA,AH(0HIGA*AH(.HIGA(AH(,HIGA&AH(*HIGA$AH((HIGA"AH(&HIGA AH(@HIGA:AH(>HIGA8IGHHIOHI1J?IGHHIOHI@1-?IGHHIOHIP1?IGHHIOHI90}/I I;uH IdžIdž I01>AH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGA}AH(HIGA}AH(HIGA{AH(~HIGAxAH(|HIGAvAH(|HIGAvAH(|HIGAvAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGALH[A\A^A_]nAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(%HIGAAH(kHIGAeAH(mHIGAgAH(kHIGAeAH(hHIGAbAH(hHIGAbAH(eHIGA_AH(eHIGA_AH(eHIGA_AH(bHIGA\AH(fHIGA`AH(iHIGAcAH(iHIGAcAH(iHIGAcAH(fHIGA`AH(dHIGA^AH(bHIGA\AH(bHIGA\AH(bHIGA\AH(`HIGAZAH(^HIGAXAH(dHIGA^AH({HIGAuAH(~HIGAxAH(|HIGAvAH(zHIGAtAH(xHIGArAH(xHIGArAH(HIGAAH(HIGAAH(HIGAAH(HIGA~AH(HIGA|AH(HIGA|AH(HIGAzAH(~HIGAxAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGALn4AH( 6HIGA60B4AH(5HIGA5AH(0HIGA*AH(0HIGA*AH(0HIGA*AH(0HIGA*AH(0HIGA*AH(0HIGA*AH(0HIGA*AH(EHIGA?AH(CHIGA=IGHHIOHI(L12IGHHIOH8AbAdžAXt#H IPIdžPAƆXAH(LHIGAFAH(HIGAAH(HIGAAH(2HIGA,AH(HIGAAH(HIGAAH(HIGAAH(HIGAAht#Hi I`Idž`AƆhAH(HIGAAH( HIGAAH(BHIGA<AH(yHIGAsAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(-HIGA'AH(+HIGA%AH()HIGA#AH(EHIGA?AH(|HIGAvAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH(5HIGA/AH(3HIGA-AH(jHIGAdAH(HIGAAH(HIGAAH(HIGA AH(GHIGAAAH(~HIGAxAH(HIGAAH(HIGAAH(HIGAAH(HIGAAH( HIGA AH(0!HIGA*!AH(.!HIGA(!AH(,!HIGA&!AH(c!HIGA]!AH(a!HIGA[!AH(!HIGA!AH(!HIGA!AH("HIGA!AH("HIGA!AH("HIGA!AH(~"HIGAx"AH(|"HIGAv"AH("HIGA"AH("HIGA"AH(!#HIGA#AH(X#HIGAR#AH(#HIGA#AH(#HIGA#AH(#HIGA#AH(4$HIGA.$AH(2$HIGA,$AH(i$HIGAc$AH($HIGA$AH($HIGA$AH($HIGA$AH($HIGA$AH($HIGA$AH($HIGA$AH($HIGA$AH($HIGA$AH(%HIGA %AH(F%HIGA@%AH(J%HIGAD%AH(N%HIGAH%AH(R%HIGAL%AH(%HIGA%AƆHAH(HIGAAH(`%HIGAZ%AH(%HIGA%AH(%HIGA%AH(%HIGA%AH(&HIGA%AH(:&HIGA4&AH(q&HIGAk&AH(&HIGA&AH(&HIGA&AH('HIGA'AH(M'HIGAG'AH(y'HIGAs'AƆHAH(eIGHHIOL8Hju IIdž1Mm'HTu LHS'IL'0B'IGHHIOHIhIGHHIOHIH1 'IGHHIOHIx1&IGHHIOHI1&IGHHIOHI1&IGHHIOHI1&IGHHIOHI1y&IGHHIOHI1\&IGHHIOHI1?&IGHHIOHI(1"&IGHHIOHIP1&IGHHIOHI1%IGHHIOHI1%IGHHIOHI1%IGHHIOHI1%IGHHIOHIpHtAƆ1g%AƆ1X%IGHHIOHI01;%IGHHIOHI81%IGHHIOHI1%IGHHIOHiIGHHIOHI 1$IGHHIOHI(1$IGHHIOH8Ab1$IGHHIOHI1s$IGHHIOA1W$IGHHIOHI1:$IGHHIOH8A1$IGHHIOH8A}1#IGHHIOH8AwAB$=$IGHHIOH8A1#IGHHIOH8Ax1#IGHHIOH8tAdžwAdž1]#IGHHIOH8Au1>#IGHHIOH8At1#IGHHIOA1#IGHHIOH8Az1"IGHHIOH8As1"IGHHIOH8A1"IGHHIOHI1"IGHHIOH8Ar1j"IGHHIOH8A1K"IGHHIOHI1."IGHHIOH8Aq1"IGHHIOHI1!IGHHIOH8A1!IGHHIOH8A1!IGHHIOHi{IGHHIO1H8!AdžfAdžj!IGHHIOHH>HA1?!IGHHIOHH!!I1!IGHHIOH8A1 IGHHIOH8A1 IGHHIOHI(1 IGHHIOH8Aa1 IGHHIOH0I0HIdž0IGHHIOH8A1B IGHHIOA 1& IGHHIOH8A|1 IGHHIOH8A1IGHHIOHHI ʃHHHHHHAbKHDH1HHHIsI1IGHHIOHHR!HZ!0HRAdž\1@IGHHIOHHʃHHHHHHAKHDH1HHHIsI1IGHHIOHiI1IGHHIOHIH1IGHHIOA1IGHHIOH8A1bIGHHIOA1FIGHHIOH8A1'IGHHIOH8A1IGHHIOAX1IGHHIOH8nfA81IGHHIOH8+A<1IGHHIOH8A1IGHHIOH8A1iIGHHIOA1MIGHHIOHI10IGHHIOHI1IGHHIOH8A1IGHHIOH8A1IGHHIOHI1IGHHIOHI1IGHHIOH8A1vIGHHIOHH0HOAƆ1@IGHHIOH8貝A1IGHHIOHI1IGHHIOHI1IGHHIOHI1IGHHIOH8A1IGHHIOHHH1H CA1{IGHHIOH8A1\IGHHIOH8A{1=IGHHIOHI1 IGHHIOHI1IGHHIOH8A1IGHHIOHI1IGHHIOHI1IGHHIOA$A1~IGHHIOH8A1_IGHHIOH8A 1@IGHHIOH8A!1!IGHHIOHI(1IGHHIO$A`1IGHHIOH8A"1IGHHIOH8A#1IGHHIOH8A1IGHHIOH8A1jIGHHIOH8Ay1KIGHHIOH8Ax1,IGHHIOHHH5bDL18y+IGHHIOHIp1IGHHIOA$A1H 1H@Hvf IP HIP 1HEjHAy1XIGHHIOHI1;IGHHIOL8Hf IIdž1MHe LHIIPIGHHIOL8He IxIdžx1MHe LHIxIGHHIOL8HEHEM L.E1HUHMLHE1vÅ5H}A?:He H=8HE1HADEIGHHIOL8HEHEML螞E1HUHMLHE1vÅH}A?:xHwd H=HE1HADEPIGHHIOL8H0d IIdž1M3Hd LHIIGHHIOHI1IGHHIOHI1IGHHIOHI Hc IIdžAdž1IGHHIOL8H]c IIdž1MHGc LHoII`8IGHHIOL8Hc I0Idž01M0Hb LH*I0*IGHHIOL8Hb IIdž1MHb LHIIGHHIOL8HTb IIdž1MWH>b LH=I6IGHHIOHIH1IGHHIOHIXAdžAƆ1IGHHIOL8Ha IIdž1MHa LHIIGHHIOL8H[a IHIdžH1M^HEa LHDIH=IGHHIOHIh1 IGHHIOHI1IGHHIOH01HIp#H,IpIGHHIOL8H` IIdž1MHz` LHyIrIGHHIOHI1HQH HI;IGHHIOHIp1IGHHIOHI1IGHHIOL8H_ IIdž1MH_ LHIIGHHIOL8Hs_ IhIdžh1MH]_ LHIhIGHHIOL8H_ IIdž1M H_ LHIIGHHIOHI1IGHHIOL8H^ IIdž1MH^ LHIIGHHIOL8HT^ IIdž1MWH>^ LH=I6IGHHIOHH] IIdžE1HH] HHIzIGHHIOL8H] IIdž1MH] LHIIGHHIOL8HQ] IIdž1MTH;] LH:I3IGHHIOL8H\ I8Idž81MH\ LHI8IGHHIOL8H\ IXIdžX1MH\ LHIXIGHHIOH01Hm>dLH[A\A^A_]IGHHIOHIx13IGHHIOHI1IGHHIOL8I~pL@~A~XuFIFPAFXIFpHHPI;u6IdžHHXI;Ju+IdžJIFpHHPI;tHHXI;JtՃ@L~IFpM~p1MW L}IFp@tHH INPAFXHxPtINIFpHHPIHHXHtH@`IIJLt} IGHHIOL8Mt A?uL=7HZ IIdž1M HyZ LHx Iq IGHHIOHI81T IGHHIOHI@17 IGHHIOL8HY IpIdžp1M HY LH Ip IGHHIOHI1 IGHHIOL8HY I Idž 1M HvY LHu I n IGHHIOL81MT H56L; L{ITIGHHIOL8HX I(Idž(1M HX LH I( IGHHIOHI1 IGHHIOHI1 IGHHIOL8M I0Ht H H*X IIdžHX I0HɿHEH[ II0Ht LL裐M3 IGHHIOHI1 IGHHIOL8HW IIdž1M HW LH Iz IGHHIOL8HBW IIdž1ME H,W LH+ I$ IGHHIOL8HV IIdž1MHV LHIIGHHIOL8HV I Idž 1MHV LHI xIGHHIOL8H@V I0Idž01MCH*V LH)I0"IGHHIOL8HU I8Idž81MHU LHI8IGHHIOL8HU I@Idž@1MH~U LH}I@vIGHHIOL8H>U IhIdžh1MAH(U LH'Ih IGHHIOHI1IGHHIOL8HT IHIdžH1MHT LHIHIGHHIOL8HuT IPIdžP1MxH_T LH^IPWIGHHIOL8HT IXIdžX1M"H T LHIXIGHHIOHI1IGHHIOHIL1IGHHIOHI1IGHHIOHIIx1IGHHIOHI1iIGHHIOH0LH[A\A^A_]|HIGHHIOL8HS IpIdžp1MHR LHIpIGHHIOL8HR IxIdžx1MHR LHIxIGHHIOH0LH[A\A^A_]GIGHHIOH0LH[A\A^A_]GIGHHIOH0LH[A\A^A_]GIGHHIOL8HQ I(Idž(1MHQ LHI(IGHHIOHIP1IGHHIOL8HQ I`Idž`1MHpQ LHoI`hIGHHIOL8H0Q IIdž1M3HQ LHIIGHHIOHI1IGHHIOL8HP IIdž1MHP LHIIGHHIOL8HgP IIdž1MjHQP LHPIIIGHHIOL8HP IIdž1MHO LHIIGHHIOL8HO I@Idž@1MHO LHI@IGHHIOL8HeO I`Idž`1MhHOO LHNI`GIGHHIOL8HO IPIdžP1MHN LHIPIGHHIOL8HN IIdž1MHN LHIIGHHIOL8HcN IIdž1MtjHQN LHtTIPIGHHIOL8HN IIdž1MtHN LHt IH[A\A^A_]IGHHIOHIXH-Adž`1IGHHIOHI@HAdžd1땃A1Idž1uIdž1c1IPUE1H)M IHEII HEI DE1HL I0HEI0I8HEI8D1I`11JHL IIdžAdž`H IX1AdždHq I@1eAƆ1VIGHHIOH8A17IGHHIOH8AA1Adž\1Adž\1IIPII`I0HAvIpRpIdžpIhHAkAIAaL1+HAEI4H5e(LLamIEGLmHJ IIdžHJ LHt]I1II AdžIdž0@1H5'LotL1H1dH5'LDt L8)=IuL11ҹ)IHJ LIHtLItBLAlH=.' L轌It'LH LHI LL1LE1E1,LlH\I Ltf&&&&&&&&&ּ &&&&*&&&&&3&&&&Rq&&&&&&ν +Ji&ƾ&&&#hB&&a&&&&&&ݿ&&&:Y&&x&&&&&&&&'F&e&&&&&>I&&&&]&|&&&&&&&&&&&&&6U&&&&&&&&t&&&.Ml&&&&&&&&r&&&&&&&&&&&&&E&&&&&d&&&&&&&&&&&&=&\&&&&&&{&&&#O&&n&r&&&&& (&&&&&&&&&&GG/Nm5Ts-Lk%Dc<[fzf4Sr ,Kj$Cb;Zyf;Zffyf3RqfбF-LkȲ%DcOnjjjjjjjjjjjjjjjjjjjjjjjjjj0f.fUHAWAVATSHLIL7M=AA$uI$XI$`H@HAIt$XHtL+ID$XL$L薇I$H@`Ht ALIT$PH5L1LI LL1iI~`M$XMt2IHt*fH;L{ƇK LH1pLMuM$`Mt3IHt+H;L{ƇKLH10LMuL1[A\A^A_]DUHAVSHH1iH߾hDtH @tHHtHLtHL5< HAHǃHAHǃHAHǃHAHǃHhAHǃhH(AHǃ(HpAHǃpH0AHǃ0HAHǃHAHǃHAHǃHAHǃHHAHǃHH AHǃ H(AHǃ(H0AHǃ0H8AHǃ8H@AHǃ@HAHǃHAHǃHAHǃHAHǃH8AHǃ8HAHǃHhAHǃhHX1 H`1WXHAHǃH[HX[HAHǃHL[A^] [A^]UH1Ht#HHtf.H99t HIHu]HH1Ӡ]f.fUHAWAVATSIHAPAtHL2AAAQtHL2AAI`Ht:H7Ht2f.@H9t HvHu19EuL 3IXHt,H7Ht$H9t HvHu 1Et [A\A^A_]L[A\A^A_]-f.UHAWAVAUATSH(H }HEALeHLLHtlHE1@H}HtQHH@L fDMd$MtM4$A~HuI A(H}D}H9MOHOE1LH([A\A]A^A_]f.DUHSPtZAHtlHHXƃ wiH5HcHH(H։DI]V1H[]H(H0Ic5t:HAuMH;H51&IƃH[]AuHEHt *DfDf@UHHH?tt H-]Àt HPt HHHHHxLHPLxH51]Ef.UHHH@@Ht]1]DHtUHHH@HH]t1ÐUHHtHH@0Ht]1]f.UHHtHH@8Ht]1]f.UHAVSIHttH1Hy0tf[A^]1uH1u烻`u tOtt 1uHHH(HtHLхu A[A^]Aƃ1[A^]f.fUHAWAVSPIHL?LP6H@|AƃIt@H;4 HHǃIH=$1HHILJILJKyH (@t[L5L5ƃA@HVH;t/HQA}ƃHsXHuhR_t HPt HHHHKxLKPLxH513BxH (1H[A^A_]@UHAWAVATSIIIÅtt[Yu5IYHI>HXHxuH`Hxt A1!I>Ht1qI 1A<$t [A\A^A_]LÅu@UHAWAVAUATSHIIIH HHEHDž`HDžhH`HI}`AIPHHH L%1 A$HHHb HHCPHǃxǃfv@H߾wH08L+A `ǃ IxHtD9t?IHu8IAE1E1E1Nƃƃ1ɈIHt8tƃƃI0ArIAAA"A A!AzbAx`AyaIHHI}`t(Hhu@A$HhHL%JLjHXL[H`HHXIHtH/ HHbA<A8fIHC8IHC@LIIP0iH=ALGH!/ ILfALL%. ILA$ILH7ILLA$HHILL(HL5. HHAIH`HAIHhHAE1HHMMLILMPH5LChHH5 HXE11H`1fXL5- HhAHAHA!ILI}H- fAEE1E1E1AH- LHhH`LLHT HH;EDH[A\A]A^A_]A<:u H5" HI$߀w:A~:L=- u3IHt'H5 mMPAL=, `HHH8,`IǀuL`IIHHH& HIIPHL^LLHpHHH^AXL=% tIPAIDžPAƅXH5 LL14MPAƅXLHH H;LreuHG H;L\eCxAAhJt AtvI$I$HDžHDžHDžM$L@^HtHHHAE1HH5sLL16tLLHt?IHL1^L=\$ IILMLMLLHf/ALHH1C}LLDHHLH\5t/AHLLHN>HHtOAƄ$AƄ$HXH1E1E1uQH`Hf# HXH`HHHXH1E1E13AL=# HLHAHAHAEtDH;?[%\HIH=@H\tH5'L11LHH \H;]u$IHU\HPLH [E$H5H1W1LAHtA$#[HtIP#[HtLI$H0IPH=E11蔨HINJ<:tLHSXCH<:uLAXt#IPH^! IDžPAƅXMPAƅXLI$@|@tI$HL?ZHtIxHtH! I$H[A$ffEfEfEfEfEfpf`fPf@f0f fffffffffffpf`fPf@f0f fffffI0HtHYEI8HtHYƅI$hHL1E1E1tE1-I$pE1HLL1E1E1PtE1ALLIxHt.H( IHu H5+E1H1N1mE1HHHt.H IHu H5E1H1 1,E1H=fIHuH=RIHH8HH@"2tLH\ LE1E1HH@uHH8L1uLL HHHLtHTAIHuAFoxyA_proHIH)H=H]H=UIHH==IHhH_ HXHhHHtIHXH1E1E10AƅHH HXHE1LI6H=_HlL5LDL= RfSHHH^H_IHE1LH~ HHHt[MtLHZ HHHS HHH HHH+Mt&A?tHH@|tLH E1Mt0A>tHH@|u AMuNLH MtyE1E1H`HL0LHx u:EH HL0LHA t]E1E1AHƀHHfǀHfǀƀƀƀHH8tYHH@xu%HuH HHHƀHtD1DHƀƀHt1HH( 11ۉٰ1HHžHtHƀHHH@|tH8tHƀHH8H5H1OSuO]uFHƀHHH]/SHt[HHE1x:LDGHH0HQ~ H5DHH8:"SIE1HHHHJHMtAH8DžHDžHtHAHsu1Hu DHH 1;HHH0HHeHDHLLDLALDHeHDHLH=01ARALS諞H HQHHXt*LIPH IdžPAƆXHHPƀXHMtoI^HHߺ hQH=r&H5H1i)AE1E1H9AHIHHyHH@pHHt7H`H HHH H`HHH t7HhHH HH HA HhHHH(t7HH HH(H HH%HƀHHH8HHpH`Hh"~AHHH5H1$=AO; H5&HƀƀH`HhHH@| tHH HHH9HHH0HH HHE1HHHH8t'HHy HHHHHHHE1HL8A?:HH5xHGHDHH aHDH= 1ÚHNHHMLHIHUHH AMA?:A:IA?BLHq HHLA?[LLpHLx@LLp]LIAI<H D>u<.t<:t<%IwH=OLtHH5<1!AIL:WLAHHHDžLH LH9HHcH9HIA?AA_ItZxH D<! HuH D>uC<r~t_tAIHH5c1 L:]KHtSIHDžAxtgILH KHHtH=w9uA1A)H=rHH5QL1= 1HpHpthHpH IHH MRA?tIHLLƀHH5L10HH E1HƀLHo E1Ex/HDDƀHH5R1`HƀAMHH@HHI<]2AI:H=H HHHt HHH0H=HHǀE1E1LLI0IhI(IdžhHG IpI0IdžpA1HL0LLLHHtB|8.uADHL8HHXHpHHHHA?MtH5L1Ht^HL0LLL[HHtB|8.uADHLA?MtH5L1MH8t^HL0LHLPLGHtB|8.uADHLHA?MtH5,L1Ht^HL0LLLGHtB|8.uADHLA?MtH5L1uHt,HHH;MtHƀHt#H;uHƀHtH8tHƀLI]LsxHL= AHǃHAHǃ8LBHǃADžIHHHtHхHHHHxyH@pHHxH`#HHXH !HhH`HpHHHHHHHHHHHHHHHHHHHHHH HHHH(HHHHHHHHHPHHH8HXH@LHHHXH`H`HLhHPHHHHH8*HHpHHXH*OIAHH HP@HHLDOH=|,HH H$HH Lp@DxHHtHhJHH@xHtHumHHx`1t(HHtHt.HHx`tHH1HHK(t:HHAx'AHDžHt-HhK(tHHAx DžtHHAAE1HH HIư|M Au H HHQ`H Ht H81HPHHDH7LLEH5SDžHL1EA( H5DžH1dAuHHx`t7AuNHHx`u5H5p| H57DžH1IFL8Mk HH(HHhH@ HPHHH1HDžH9HHH;HSPH51WH߾M. IMHXHH`HJLpHLuH~HI΀HtHuHHHHHHHF1?9HH:HH@zH@1HHXH`HJLpI΀MH@HHHHHHHEHHHHH|3K|t%xx;Cx HHH:HH:H H; HHHH;qHHHHDHHH8HH(C#HH0HH0CHH:HH:H8TH`H;`HHXHH;XfHHHHHHC=H@H8HHhBHHpHHpBHH:H`fHH@|HHH8!H|lHHHHHH@x7tHH{`tHt}H{`HTɸDȉHHPPHH5Y1HHXH hHTHHH fHLA\$|xNH0H8HH9HHHH9u H8tHI<$HHH0?Ht)HHHH}?;Ht HH; HH8HH(?HH;HH@|t6HHH8H| H0H8HHB8JHHHH8!Hf9HH;HHHH7HxHYHHxxHH;AxsHZHFteHHhH&HLpMH@H86HHpL6HtWtHfHHv9dML9sHH5*LHHftHH51M HPoL;LHHH>HH@x]HtH9HHx`tt&HHtHt2HHx`5HHHHXH`HIHHHHSPH5AH1 HHHH9HmHH HHH H9H0NH5GtLH#tH1AAH5HH1AHpHHHHDHcHxHsHItuHH(E1"AAH HDžHHHAXE1HuHSH5H1Af.UHSPHHtƆƃPLƃKuu4HHHƃHǃH@ HP H`HX HhHƃyHX&H1H11H[]f.UHAWAVAUATSH8MHUIHHMHtrH߾:(J ;E1H9LBLuMtZH߾;'J ;E1H9LBMtBM9MMGMMDI)J;M9IGLHHHM'E1LuMuE1MuMI)MMD1HEHLHEIM9MGHLMID1H}tMtH I}H"HEE1H}t$H}tH_ HMHyIH1H}tHtH4 H{HHEH}Ht1HuLL}I%C/H LmI}M}L}Mt0ILLLeL%C'H LeI<$M<$E1LeMtSILLHh%AH H]H;L#'H{ H}Hl LH}ADH8[A\A]A^A_]ÐUHAWAVAUATSHHuH>iIH="H(,tNH%IL:%HtIM)MuL%IM MLuI1LEI1LM9L9s9f H?wL!tHI9uf.fL9Is7If.IM9tB +H?wL!tM1<.@HMI)M9OHuL)HHuLI,LEȅ-M9HEЀx.1H[A\A]A^A_]UHAWAVAUATSH8AHHuIHEHEH5H$IH IH=HP-tH5LH1AIH=VH-MԅtAMH=3H,tAMH=H,t AMlH=H,uH=H,t AM1H=Hf,MEAE@L@"Ht.HHL)HUHMLE1AąjHIA>[L}I^AFH]ȄIL% LHAD>u<.t<:t<%L}HsH="tH5L1D; D{HEtsEExCD<!ȅuDuCD>uAG<rA~tA_tL}Lu2AEHH5L}L1IL:!HtsHHEHHuHߺ !IHEHtH/wHHs IrhH57LH1H]Ȁ;ucAH]Ȁ;/H߾/ HtIHA8LE;u@HELxH]Ȁ;(HEHL8}LEEo(H}IH I0IG0HuH}11"IG0AHI8IG8H]Ht"H` H=wH}H11ؖHW H=H]IG8HHEƀLMx+Mw HEHxMuH:u HELxH I?IH HIIGHt8H H}HEH}HEE1DH8[A\A]A^A_]AH<]HH5LH1AUH]f.UHAVSHXH`H@HAuYHHuPIH@zu@1t%L3HSPH5tL1H߾踦1[A^]Ð?1kO?wUHHkHc H]Ájtx~ltI@ÁtxtpurÁ t@t tSWÁtFuDÁt u.Átuø@øø1ÐUHHHHHtHtH=1]hHtH=/1]hHtH=H1]h1]f.UHAVSHt9H?t1H5bHH9vIH}HHI9[A^]1[A^]ÐUHSP= t=b thH[] )  DEVHr HH)HrHH{H)xHt ) = uH PHLH  H[]UHSP= uXk)  DEVH HzH)HrHH{H) Ht  H H[]f.UHSP=; u"H: PH H^  H( H[]ÐUHAVSHH;u_IHG:FuQC A:F uHH{Ivm t7H{Iv\ t&H{ Iv K tH{8Iv8: u1[A^]f.UHAVSIHG F GFHHHHHU IFHH{HH2 IFHtxH{8HH IF8HtYH{0HH IF0Ht:H{(HH IF(HtH{ Ht~H IF Hut1[A^]IFH{HZIFH{8HdIF8H{0HnIF0H{(HxIF(H{ HuIF [A^]f.fUHAVSHL5 HAHCH{AHCH{8AHC8H{0AHC0H{(AHC(H{ AHC [A^]UH ]DUH= u ]DUH= u ]f.UHSPHHc7tH|u t`H;HrH51g#H[]HƄxDŽ|HuH;1H[]øH[]fDUHAWAVSPIHHc7tH|u tYH;HrH5j1A#tH;ADH[A^A_]f.@UHH?HGpHtu]þ]YfUHH?HGpHtu]þ]nf.@UHAWAVAUATSH8HL'`uHcHH}HHEHA$[I|$pHtuI$JI$u4HhI$!H}HMHuHUA8E1*Htjf.DIIxM;$M$JK|.tKt.H}tȀKt.tHtHtCD.tt9uuEC;D.uHH8Kt.QYK4.H},DHMHHHKD.KD.HMHHMHtKD.H1H8[A\A]A^A_]HXHHx[fDUHAVSHHHtHCHC(L5 H{PAHCPH{HAHCHH{pAHCpH{hAHChH{`AHC`H{XAHCXH;AHH{AHC[A^]fUHAVSHHHt-HJHp1f.H9stHHxH9r[A^]HtHHCHCL5 H{AHCH{AHCH;AHH{AHCH{AHCH{AHCH{AHCH{AHC[A^]fUHAWAVAUATSH8HL/MJ`HUHuuHcHHEHEM|$(L5 H8AHHMH\t3HAHHEHtyt#EMupMu!%1HEȀuEMupMtAuIMJIHsFwHXHEHHMAH H}IhIHr3IJHxHztHr(L9LLLLHHxH9rH9I|$HaID$ID$(L=p I|$PAID$PI|$HAID$HI|$pAID$pI|$hAID$hI|$`AID$`I|$XAID$XI<$AI$I|$AID$ LkxMJLmHEID$HEID$ IID$(L5 I<$AI|$AL}M<$Ml$EAD$4}txAD$0HHID$It$8H}1uID$LALAH8[A\A]A^A_]DUHAWAVAUATSPLJM@IHGpHt +IHApL- I|Hf.IDIDI|AUIDI|AUIDI<AUII|AUIDI|AUIDI|AUIDI|AUIDI|AUIDII9sMJIHxI|H2MJH LIdžJH[A\A]A^A_]UH1t,tu@]Ë@]UH]ffDUHHcH ƄxDŽ|H HXH LHh1]UH]DUH]DUH1]UHAWAVSPE1HJu=IHH xLHtLHJHǃJADH[A^A_]f.@UH]ffDUH]vfDUH]fDUHAVSMteI~:1fIMH<IMHHIcMH9|H IMIdžMAdžM[A^]fDUHAWAVSPAIMt\~41IMH %@ %B %D %F %H %J %L %N %P %R %T %V %X %Z %\ %^ %` %b %d %f %h %j %l %n %p %r %t %v %x %z %| %~ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %¿ %Ŀ %ƿ %ȿ %ʿ %̿ %ο %п %ҿ %Կ %ֿ %ؿ %ڿ %ܿ %޿ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %" %$ %& %( %* %, %. %0 %2 %4 %6 %8 %: %< %> %@ %B %D %F %H %J %L %N %P %R %T %V %X %Z %\ %^ %` %b %d %f %h %j %l %n %p %r %t %v %x %z %| %~ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % L AS%)z hy hhhhh h*hRhwhhhxhnhdh Zh&Ph<FhYhv 4h *h h h h h h h h h h h- h= hL hZ hg hs h h vh lh bh Xh Nh Dh :h 0h &h h$ h4 hB hP h] hr h h h h h h h h h h |h$ rh3 hhB ^hR Thf Jhv @h 6h ,h "h h h h h h h& h9 hK h_ hk h h h h h h xh nh dhZhPh$Fh1h4h*h hh hhhhhh'h5hDhVhghhhhhvhlh%bh9XhSNhpDh:h0h&hh h&hIhbhthhhhhh"hShpremake.criteria__gcfilesdatastringmatchPremake/5.0.0-beta1_OPTIONSinsecureheadersprogressuserpwdusernamepasswordtimeouttimeoutmssslverifyhostsslverifypeerproxyurlcannot create state: not enough memoryprinterror calling 'print' (%s) %s: %s LUA_NOENV'%s' needs argument unrecognized option '%s' usage: %s [options] [script [args]] Available options are: -e stat execute string 'stat' -i enter interactive mode after executing 'script' -l name require library 'name' into global 'name' -v show version information -E ignore environment variables -- stop handling options - stop handling options and execute stdin Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rioarg=LUA_INIT_5_3=LUA_INIT=(command line)require---'arg' is not a tabletoo many arguments to scripttoo many results to printluareturn %s_PROMPT_PROMPT2> >> return %s;=stdin__tostring(error object is a %s value)interrupted!wbUnable to open file.%s %s OKstack traceback: ...Slnt %s:%d: in (...tail calls...)bad argument #%d (%s)nmethodcalling '%s' on bad self (%s)?bad argument #%d to '%s' (%s)Sl%s:%d: %s: %sexitsignal__nameinvalid option '%s'stack overflow (%s)stack overflowvalue expectedbuffer too large@%sropenrbreopenreadobject length is not an integer'__tostring' must return a string%I%ftruefalsenil%s: %ptoo many upvalues_LOADEDcore 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 directoryfunction '%s'%s '%s'main chunkfunction <%s:%d>f_G..light userdata%s expected, got %snumber has no integer representationnot enough memory for buffer allocationLUABOXcannot %s %s: %sPANIC: unprotected error in call to Lua API (%s) _SCRIPTunable to switch to directory '%s'unable to set mode %o on '%s', errno %d : %sfailed 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'cp "%s" "%s"unable to copy file to '%s'majorversionminorversionrevisiondescription/System/Library/CoreServices/SystemVersion.plistMac OSProductVersion%d.%d.%d%d.%d.%*dMac OS X TigerMac OS X LeopardMac OS X Snow LeopardOS X LionOS X Mountain LionOS X MavericksOS X YosemiteOS X El CapitanmacOS SierramacOS High SierramacOS MojavemacOS Catalinamacosx/premakepath$/%s/%s..unable to create directory '%s'unable to fetch real path of '%s', errno %d : %sunable 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'unable to open file to '%s'ab /dev/urandom%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.criteriadebugosbufferedtermhttpzip_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_DIRError: %s _PREMAKE_COMMAND_premake_mainPATHPREMAKE_PATHgetEmbeddedResource_compile_deletematchespromptgetabsolutegetrelativeisabsolutejoindeferredjoinhasdeferredjoinresolvedeferredjointranslatewildcardschdirchmodcomparefilescopyfile_is64bitisdirgetcwdgetpassgetWindowsRegistrylistWindowsRegistrygetversionhostisfileislinklocatematchdonematchisfilematchnamematchnextmatchstartmkdirpathsearchrealpathrmdirstatuuidwritefile_ifnotequaltouchfilecompileendswithhashsha1startswithnewwritewritelntostringclosegetTextColorsetTextColorgetpostdownloadextracterrorColor;/.premake/Library/Application Support/Premake;/usr/local/share/premake;/usr/share/premakegsub:/scripts=--scripts=_ARGVsrc/_premake_main.luasrc/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.lua0123456789ABCDEFCLICOLOR1CLICOLOR_FORCE0%s does not exist Failed to create symbolic link [%s->%s] Error creating file: %s Writing data to %s failed %d bytes were written %d bytes were attempted to be written File may be corrupt (*no name)Lua 5.3_VERSIONassertcollectgarbagedofileerrorgetmetatableipairsloadfileloadnextpairspcallrawequalrawlenrawgetrawsetselectsetmetatabletonumbertypexpcallassertion failed!stoprestartcollectcountstepsetpausesetstepmulisrunning__metatablebt=(load)too many nested functionsreader function must return a string__pairs'tostring' must return a string to 'print'table or string expectedindex out of rangenil or table expectedcannot change a protected metatablebase out of range function or expression needs too many registerscontrol structure too longopcodesconstantscreateresumerunningstatuswrapyieldisyieldablethread expectedtoo many arguments to resumetoo many results to resumesuspendednormaldeadgetuservaluegethookgetinfogetlocalgetregistrygetupvalueupvaluejoinupvalueidsetuservaluesethooksetlocalsetupvaluetracebacklua_debug> cont =(debug command)external hooklinetail callflnStu>%sinvalid optionsourceshort_srclinedefinedlastlinedefinedwhatcurrentlinenupsnparamsisvarargnamenamewhatistailcallactivelinesfunclevel out of rangeLua function expectedinvalid upvalue indexkattempt to %s a %s value%sconcatenatenumber%s has no integer representationattempt to compare two %s valuesattempt to compare %s with %s%s:%d: %s(*temporary)(*vararg)=[C]C=?mainLuametamethodhookfor iteratorlocal_ENVglobalfieldupvalueconstant (%s '%s')cannot resume non-suspended coroutinecannot resume dead coroutineC stack overflowattempt to yield across a C-call boundaryattempt to yield from outside a coroutineerror in error handlingcallbinarytextattempt to load a %s chunk (mode is '%s')Lua  no messageerror in __gc metamethod (%s)_Gpackagecoroutinetableiomathutf8_IO_inputstdin_IO_outputstdoutstderrflushinputlinesoutputpopentmpfileFILE*attempt to use a closed filestandard %s file is closedcannot open file '%s' (%s)too many argumentsfile is already closedinvalid formatpPeEinvalid moderwabclosed fileseeksetvbufsetcurnofullfile (closed)file (%p)cannot close standard file'%c''%s'andbreakdoelseelseifendforgotoifinnotorrepeatreturnthenuntilwhile//==>=<=~=<<>>::%s near %slexical element too longinvalid long string delimiterchunk has too many linescommentunfinished long %s (starting at line %d)unfinished stringinvalid escape sequencehexadecimal digit expectedmissing '{'UTF-8 value too largemissing '}'decimal escape too largeEePpmalformed numberpihugemaxintegerminintegerabsacosasinatanceilcosdegexptointegerfloorfmodultlogmaxminmodfradrandomrandomseedsinsqrttanzerowrong number of argumentsinterval is emptyinterval too largeintegerfloattoo many %s (limit is %d)memory allocation error: block too bigLUA_PATH/usr/local/share/lua/5.3/?.lua;/usr/local/share/lua/5.3/?/init.lua;/usr/local/lib/lua/5.3/?.lua;/usr/local/lib/lua/5.3/?/init.lua;./?.lua;./?/init.luacpathLUA_CPATH/usr/local/lib/lua/5.3/?.so;/usr/local/lib/lua/5.3/loadall.so;./?.so/ ; ? ! - configloaded_PRELOADpreloadloadlibsearchpathsearchersinit no file '%s' no field package.preload['%s']'package.%s' must be a stringerror loading module '%s' from file '%s': %s_luaopen_%s no module '%s' in file '%s'%s%s_5_3;;;;'package.searchers' must be a tablemodule '%s' not found:%s%lld%.14g-0123456789(null)<\%d>%p%invalid option '%%%c' to 'lua_pushfstring'...[string ""].xXnNMOVELOADKLOADKXLOADBOOLLOADNILGETUPVALGETTABUPGETTABLESETTABUPSETUPVALSETTABLENEWTABLESELFADDSUBMULMODPOWDIVIDIVBANDBORBXORSHLSHRUNMBNOTNOTLENCONCATJMPEQLTLETESTTESTSETCALLTAILCALLRETURNFORLOOPFORPREPTFORCALLTFORLOOPSETLISTCLOSUREVARARGEXTRAARGclockdatedifftimeexecutegetenvremoverenamesetlocaletimetmpname%ctime result cannot be represented in this installation*tsechourdaymonthyearwdayydayisdstaAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%||EcECExEXEyEYOdOeOHOIOmOMOSOuOUOVOwOWOyinvalid conversion specifier '%%%s'allcollatectypemonetarynumericfield '%s' is not an integerfield '%s' missing in date tablefield '%s' is out-of-bound/tmp/lua_XXXXXXunable to generate a unique filenameupvaluesmain functionfunction at line %dtoo many %s (limit is %d) in %sC levelscannot use '...' outside a vararg functionselffunctionslocal variables or '...' expectedunexpected symbolfunction arguments expectedlabels/gotos at line %d jumps into the scope of local '%s'<%s> at line %d not inside a loopno visible label '%s' for at line %d%s expected (to close %s at line %d)%s expected'=' or 'in' expected(for index)(for limit)(for step)(for generator)(for state)(for control)label '%s' already defined on line %dsyntax errornot enough memorybytechardumpfindformatgmatchlenlowerrepreversesubupperpackpacksizeunpackstring slice too longvalue out of rangeunable to dump given function^$*+?.([%-pattern too complexmissing '[' after '%%f' in patterntoo many capturesinvalid pattern capturemalformed pattern (missing arguments to '%%b')malformed pattern (ends with '%%')malformed pattern (missing ']')invalid capture index %%%dunfinished capturellstring contains zerosinvalid option '%%%c' to 'format'invalid format (repeated flags)invalid format (width or precision too long)%a0x%llxvalue has no literal form\%d\%03dstring/function/table expectedinvalid replacement value (a %s)invalid use of '%c' in replacement stringresulting string too largeinteger overflowunsigned overflowstring longer than given sizestring length does not fit in given sizeinvalid next option for option 'X'format asks for alignment not power of 2missing size for format option 'c'invalid format option '%c'integral size (%d) out of limits [1,%d]format result too largevariable-length formatinitial position out of stringdata string too shorttoo many results%d-byte integer does not fit into Lua Integertable index is niltable index is NaNinvalid key to 'next'table overflowconcatinsertmovesortinvalid value (%s) at index %d in table for 'concat'position out of boundswrong number of arguments to 'insert'too many results to unpacktoo many elements to movedestination wrap aroundarray too biginvalid order function for sortingno 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 onbinary stringnot aversion mismatch informat mismatch incorruptedintsize_tInstructionlua_Integerlua_Numberendianness mismatch infloat format mismatch intruncated%s: %s precompiled chunk%s size mismatch incharpatternoffsetcodepointcodesposition out of rangeinitial position is a continuation byteout of rangeinvalid UTF-8 code%Ufinal position out of stringindex'__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 numberTORRENTZIPPED-XXXXXXXX%08lX%s/.zip.XXXXXX%s.XXXXXXr+bPKPKMulti-disk zip archives not supportedRenaming temporary file failedClosing zip archive failedSeek errorRead errorWrite errorCRC errorContaining zip archive was closedNo such fileFile already existsCan't open fileFailure to create temporary fileZlib errorMalloc failureEntry has been changedCompression method not supportedPremature EOFInvalid argumentNot a zip archiveZip archive inconsistentCan't remove fileEntry has been deletedEncryption method not supportedRead-only archiveNo password providedWrong password providedTORRENTZIPPED-PKPKPK1.2.8incorrect 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 version%c%c==%c%c%c=%c%c%c%c%s:%ldgetpeername() failed with errno %d: %sgetsockname() 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 Could not set SO_NOSIGPIPE: %s Failed to set SO_KEEPALIVE on fd %d Failed to set TCP_KEEPINTVL on fd %d Failed to set TCP_KEEPALIVE on fd %d if!host!Couldn't bind to interface '%s'Local Interface %s is ip %s using address family %i Name '%s' family %i resolved to '%s' family %i Couldn't bind to '%s'Local port: %hu Bind to local port %hu failed, trying next bind failed with errno %d: %signoring failed cookie_init for %s %1023[^; =] =%4999[^; ]securehttponlydomainlocalhostskipped cookie with bad tailmatch domain: %s versionmax-ageexpires#HttpOnly_ TRUEFALSE%s cookie %s="%s" for domain %s, path %s, expire %ld ReplacedAddednoneWARNING: failed to save cookies in %s %s%s%s %s %s %s %ld %s %sw# 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 %c%c%c%c%c%c%c%cselect/poll on SSL socket, errno: %dSSL shutdown timeoutread: %sSecureTransportSSL connection timeoutSSL: couldn't create a context!DarwinSSL: TLS 1.3 is not yet supportedYour version of the OS does not support SSLv3Your version of the OS does not support SSLv2Unrecognized parameter passed via CURLOPT_SSLVERSIONWARNING: SSL: CURLOPT_SSLKEY is ignored by Secure Transport. The private key must be in the Keychain. WARNING: SSL: Certificate type not set, assuming PKCS#12 format. P12WARNING: SSL: The Security framework only supports loading identities that are in PKCS#12 format. Client certificate: %s SSL: SSLSetCertificate() failed: OSStatus %dSSL: Incorrect password for the certificate "%s" and its private key.SSL: Couldn't make sense of the data in the certificate "%s" and its private key.SSL The certificate "%s" requires a password.SSL: Can't find the certificate "%s" and its private key in the Keychain.SSL: Can't load the certificate "%s" and its private key: OSStatus %dSSL: SSLSetSessionOption() failed: OSStatus %dSSL: can't load CA certificate file %sWARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d WARNING: using IP address, SNI is being disabled by the OS. SSL: SSLSetEnabledCiphers() failed: OSStatus %dSSL: Failed to allocate memory for allowed ciphersSSL: SSLSetPeerID() failed: OSStatus %dSSL re-using session ID %s:%d:%d:%s:%hufailed to store ssl sessionSSL: SSLSetIOFuncs() failed: OSStatus %dSSL: SSLSetConnection() failed: %dSSL certificate problem: Invalid certificate chainSSL certificate problem: Untrusted root certificateSSL certificate problem: No root certificateSSL certificate problem: Certificate chain had an expired certificateSSL certificate problem: Couldn't understand the server certificate formatSSL authentication failedSSL peer handshake failed, the server most likely requires a client certificate to connectSSL server rejected the client certificate due to the certificate being signed by an unknown certificate authoritySSL certificate peer verification failed, the certificate did not match "%s" Server dropped the connection during the SSL handshakeServer aborted the SSL handshakeCould not negotiate an SSL cipher suite with the serverInternal SSL engine error encountered during the SSL handshakeFatal SSL engine error encountered during the SSL handshakeUnknown SSL protocol error in connection to %s:%dSSL 2.0 connection using %s SSL 3.0 connection using %s TLS 1.0 connection using %s TLS 1.1 connection using %s TLS 1.2 connection using %s Unknown protocol connection SSL: failed to read or invalid CA certificateSSL: out of memory creating CA certificate arraySSL: invalid CA certificate #%d (offset %d) in bundleSSL: error getting certificate chainSSL: certificate verification failed (result: %d)-----SSL: failed to allocate array for CA certificateSSL: failed to create SecCertificate from CA certificateSSL: invalid CA certificate subjectSSL: invalid CA certificateSSL certificate peer hostname mismatchSSL unexpected certificate error %dSSL_RSA_WITH_NULL_MD5SSL_RSA_WITH_NULL_SHASSL_RSA_EXPORT_WITH_RC4_40_MD5SSL_RSA_WITH_RC4_128_MD5SSL_RSA_WITH_RC4_128_SHASSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5SSL_RSA_WITH_IDEA_CBC_SHASSL_RSA_EXPORT_WITH_DES40_CBC_SHASSL_RSA_WITH_DES_CBC_SHASSL_RSA_WITH_3DES_EDE_CBC_SHASSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHASSL_DH_DSS_WITH_DES_CBC_SHASSL_DH_DSS_WITH_3DES_EDE_CBC_SHASSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHASSL_DH_RSA_WITH_DES_CBC_SHASSL_DH_RSA_WITH_3DES_EDE_CBC_SHASSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHASSL_DHE_DSS_WITH_DES_CBC_SHASSL_DHE_DSS_WITH_3DES_EDE_CBC_SHASSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHASSL_DHE_RSA_WITH_DES_CBC_SHASSL_DHE_RSA_WITH_3DES_EDE_CBC_SHASSL_DH_anon_EXPORT_WITH_RC4_40_MD5SSL_DH_anon_WITH_RC4_128_MD5SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHASSL_DH_anon_WITH_DES_CBC_SHASSL_DH_anon_WITH_3DES_EDE_CBC_SHASSL_FORTEZZA_DMS_WITH_NULL_SHASSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHATLS_RSA_WITH_AES_128_CBC_SHATLS_DH_DSS_WITH_AES_128_CBC_SHATLS_DH_RSA_WITH_AES_128_CBC_SHATLS_DHE_DSS_WITH_AES_128_CBC_SHATLS_DHE_RSA_WITH_AES_128_CBC_SHATLS_DH_anon_WITH_AES_128_CBC_SHATLS_RSA_WITH_AES_256_CBC_SHATLS_DH_DSS_WITH_AES_256_CBC_SHATLS_DH_RSA_WITH_AES_256_CBC_SHATLS_DHE_DSS_WITH_AES_256_CBC_SHATLS_DHE_RSA_WITH_AES_256_CBC_SHATLS_DH_anon_WITH_AES_256_CBC_SHASSL_RSA_WITH_RC2_CBC_MD5SSL_RSA_WITH_IDEA_CBC_MD5SSL_RSA_WITH_DES_CBC_MD5SSL_RSA_WITH_3DES_EDE_CBC_MD5SSL_NULL_WITH_NULL_NULLTLS_ECDH_ECDSA_WITH_NULL_SHATLS_ECDH_ECDSA_WITH_RC4_128_SHATLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHATLS_ECDH_ECDSA_WITH_AES_128_CBC_SHATLS_ECDH_ECDSA_WITH_AES_256_CBC_SHATLS_ECDHE_ECDSA_WITH_NULL_SHATLS_ECDHE_ECDSA_WITH_RC4_128_SHATLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHATLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHATLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHATLS_ECDH_RSA_WITH_NULL_SHATLS_ECDH_RSA_WITH_RC4_128_SHATLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHATLS_ECDH_RSA_WITH_AES_128_CBC_SHATLS_ECDH_RSA_WITH_AES_256_CBC_SHATLS_ECDHE_RSA_WITH_NULL_SHATLS_ECDHE_RSA_WITH_RC4_128_SHATLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHATLS_ECDHE_RSA_WITH_AES_128_CBC_SHATLS_ECDHE_RSA_WITH_AES_256_CBC_SHATLS_ECDH_anon_WITH_NULL_SHATLS_ECDH_anon_WITH_RC4_128_SHATLS_ECDH_anon_WITH_3DES_EDE_CBC_SHATLS_ECDH_anon_WITH_AES_128_CBC_SHATLS_ECDH_anon_WITH_AES_256_CBC_SHATLS_RSA_WITH_NULL_MD5TLS_RSA_WITH_NULL_SHATLS_RSA_WITH_RC4_128_MD5TLS_RSA_WITH_RC4_128_SHATLS_RSA_WITH_3DES_EDE_CBC_SHATLS_RSA_WITH_NULL_SHA256TLS_RSA_WITH_AES_128_CBC_SHA256TLS_RSA_WITH_AES_256_CBC_SHA256TLS_DH_DSS_WITH_3DES_EDE_CBC_SHATLS_DH_RSA_WITH_3DES_EDE_CBC_SHATLS_DHE_DSS_WITH_3DES_EDE_CBC_SHATLS_DHE_RSA_WITH_3DES_EDE_CBC_SHATLS_DH_DSS_WITH_AES_128_CBC_SHA256TLS_DH_RSA_WITH_AES_128_CBC_SHA256TLS_DHE_DSS_WITH_AES_128_CBC_SHA256TLS_DHE_RSA_WITH_AES_128_CBC_SHA256TLS_DH_DSS_WITH_AES_256_CBC_SHA256TLS_DH_RSA_WITH_AES_256_CBC_SHA256TLS_DHE_DSS_WITH_AES_256_CBC_SHA256TLS_DHE_RSA_WITH_AES_256_CBC_SHA256TLS_DH_anon_WITH_RC4_128_MD5TLS_DH_anon_WITH_3DES_EDE_CBC_SHATLS_DH_anon_WITH_AES_128_CBC_SHA256TLS_DH_anon_WITH_AES_256_CBC_SHA256TLS_RSA_WITH_AES_128_GCM_SHA256TLS_RSA_WITH_AES_256_GCM_SHA384TLS_DHE_RSA_WITH_AES_128_GCM_SHA256TLS_DHE_RSA_WITH_AES_256_GCM_SHA384TLS_DH_RSA_WITH_AES_128_GCM_SHA256TLS_DH_RSA_WITH_AES_256_GCM_SHA384TLS_DHE_DSS_WITH_AES_128_GCM_SHA256TLS_DHE_DSS_WITH_AES_256_GCM_SHA384TLS_DH_DSS_WITH_AES_128_GCM_SHA256TLS_DH_DSS_WITH_AES_256_GCM_SHA384TLS_DH_anon_WITH_AES_128_GCM_SHA256TLS_DH_anon_WITH_AES_256_GCM_SHA384TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384TLS_EMPTY_RENEGOTIATION_INFO_SCSVTLS_PSK_WITH_RC4_128_SHATLS_PSK_WITH_3DES_EDE_CBC_SHATLS_PSK_WITH_AES_128_CBC_SHATLS_PSK_WITH_AES_256_CBC_SHATLS_DHE_PSK_WITH_RC4_128_SHATLS_DHE_PSK_WITH_3DES_EDE_CBC_SHATLS_DHE_PSK_WITH_AES_128_CBC_SHATLS_DHE_PSK_WITH_AES_256_CBC_SHATLS_RSA_PSK_WITH_RC4_128_SHATLS_RSA_PSK_WITH_3DES_EDE_CBC_SHATLS_RSA_PSK_WITH_AES_128_CBC_SHATLS_RSA_PSK_WITH_AES_256_CBC_SHATLS_PSK_WITH_NULL_SHATLS_DHE_PSK_WITH_NULL_SHATLS_RSA_PSK_WITH_NULL_SHATLS_PSK_WITH_AES_128_GCM_SHA256TLS_PSK_WITH_AES_256_GCM_SHA384TLS_DHE_PSK_WITH_AES_128_GCM_SHA256TLS_DHE_PSK_WITH_AES_256_GCM_SHA384TLS_RSA_PSK_WITH_AES_128_GCM_SHA256TLS_PSK_WITH_AES_128_CBC_SHA256TLS_PSK_WITH_AES_256_CBC_SHA384TLS_PSK_WITH_NULL_SHA256TLS_PSK_WITH_NULL_SHA384TLS_DHE_PSK_WITH_AES_128_CBC_SHA256TLS_DHE_PSK_WITH_AES_256_CBC_SHA384TLS_DHE_PSK_WITH_NULL_SHA256TLS_RSA_PSK_WITH_NULL_SHA384TLS_RSA_PSK_WITH_AES_128_CBC_SHA256TLS_RSA_PSK_WITH_AES_256_CBC_SHA384TLS_RSA_PSK_WITH_NULL_SHA256TLS_NULL_WITH_NULL_NULLServer certificate: %s SSLRead() return error %dSSLWrite() returned error %d00000001AUTHENTICATEmd5-sess%08x%08x%08x%08x%02xusername="%s",realm="%s",nonce="%s",cnonce="%s",nc="%s",digest-uri="%s",response=%s,qop=%snoncestalerealmopaqueqop,authauth-intalgorithmMD5-sessMD5%s:%s:%sd41d8cd98f00b204e9800998ecf8427e%s:%s:%08x:%s:%s:%susername="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%08x, qop=%s, response="%s"username="%s", realm="%s", nonce="%s", uri="%s", response="%s"%s, opaque="%s"%s, algorithm="%s"nonce="realm="algorithm=qop="auth-conf/.//./..//..easy handle already used in multi handleCONNECT_ONLY is required!Failed to get recent socket%%%02X%s; boundary=%s Content-Type: multipart/form-data--%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-- .gifimage/gif.jpgimage/jpeg.jpeg.txttext/plain.htmltext/html.xmlapplication/xmlapplication/octet-stream; filename="%s"------------------------%08x%08xHostname %s was found in DNS cache remaining timeout of %ld too small to resolve via SIGALRM methodname lookup timed outPrevious alarm fired off!%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 Hostname in DNS cache was stale, zapped %s:%d%dgetaddrinfo(3) failed for %s:%d HTTPHTTPSThe requested URL returned error: %dNTLMAuthentication problem. Ignoring this. Ignoring duplicate digest auth header. BasicEmpty reply from serverHost: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 %ld bytes from the inputFile already completely uploadedRange:Range: bytes=%s Content-Range:Content-Range: bytes 0-%ld/%ld Content-Range: bytes %s%ld/%ld Content-Range: bytes %s/%ld %s ftp://%s:%s@%s%s HTTP/%s %s%s%s%s%s%s%s%s%s%s%sProxy-Connection:Proxy-Connection: Keep-Alive Cookie: %s%s=%s; Content-Length: 0 Failed sending POST requestInternal HTTP POST error!Content-Length:Content-Length: %ld Could not get Content-Type header line!Failed sending PUT requestContent-Type: application/x-www-form-urlencoded Expect:100-continue%x 0 Failed sending HTTP POST requestFailed sending HTTP requestupload completely sent off: %ld out of %ld bytes Received 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: %ld, 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:Rewind stream after send NTLM send, close instead of sending %ld bytes Proxy-authorization:Authorization:%s auth using %s with user '%s' ProxyServer%s:%s%sAuthorization: Basic %s 1.11.0Expect: 100-continue Avoided giant realloc for header (max is %d)!Failed to alloc memory for big header!HTTP/The requested URL returned error: %sToo long hexadecimal numberIllegal or missing hexadecimal sequenceMalformed encoding foundBad content-encoding foundDigest%.*s%sAuthorization: Digest %s Proxy-NTLM auth restarted NTLM handshake rejected NTLM handshake failure (internal error) %sAuthorization: NTLM %s Establish 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 %ld 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 %d.%d.%d.%d%lx0123456789abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ(nil)%ld.%ldInternal error removing splay node = %d Internal error clearing splay node = %d Connection #%ld to host %s left intact Connection cache is full, closing the oldest 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 %ld out of %ld bytes receivedOperation timed out after %ld milliseconds with %ld bytes receivedHostname '%s' was found in DNS cache Re-used connection seems dead, get a new one .netrc machinedefaultloginNTLM handshake failure (empty type-2 message) NTLMSSPNTLM handshake failure (bad type-2 message) NTLMSSP%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%sgethostname() failed, continuing without! NTLMSSP%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%cuser + domain + host name too bigNTLM handshake failure (bad type-2 message). Target Info Offset Len is set incorrect by the peer MonTueWedThuFriSatSunJanFebMarAprMayJunJulAugSepOctNovDec%31[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]%02d:%02d:%02d%n%02d:%02d%nMondayTuesdayWednesdayThursdayFridaySaturdaySundayConn: %ld (%p) Receive pipe weight: (%ld/%zu), penalized: %s Site %s:%d is pipeline blacklisted Server %s is blacklisted Callback aborted** Resuming transfer from byte position %ld %% Total %% Received %% Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed %3ld %s %3ld %s %3ld %s %s %s %s %s %s %s--:--:--%2ld:%02ld:%02ld%3ldd %02ldh%7ldd%5ld%4ldk%2ld.%0ldM%4ldM%2ld.%0ldG%4ldG%4ldT%4ldPWARNING: Using weak random seed %sSend failure: %sRecv failure: %sWrite callback asked for PAUSE when not supported!Failed writing body (%zu != %zu)Failed writing headerDataHeaderfromto[%s %s %s] SOCKS4%s: connecting to HTTP proxy %s port %d aSOCKS4 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.Failed to send SOCKS5 sub-negotiation request.Unable to receive SOCKS5 sub-negotiation response.User was rejected by the SOCKS5 server (%d %d).SOCKS5 GSSAPI per-message authentication is not supported.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 connect to IPv6 %s (locally resolved) SOCKS5 connection to %s not supported Failed to resolve "%s" for SOCKS5 connect.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. Operation too slow. Less than %ld bytes/sec transferred the last %ld secondsNo errorUnsupported 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 errorPlease call curl_multi_perform() soonInvalid multi handleInvalid easy handleInternal errorInvalid socket argumentUnknown optionThe easy handle is already added to a multi handleUnknown share optionShare currently in useInvalid share handleFeature not enabled in this libraryCURLSHcode unknownUnknown error %doperation 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 select/poll returned errorDone waiting for 100-continue transfer closed with %ld bytes remaining to readtransfer closed with outstanding read data remainingNo URL set!Maximum (%ld) redirects followedIssue another request to this URL: '%s' Switch from POST to GET Disables POST, goes with %s HEADGETConnection died, retrying a fresh connect 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 = %ld, maxdownload = %ld, bytecount = %ld, nread = %zd) Excess found in a non pipelined read: excess = %zu, size = %ld, maxdownload = %ld, bytecount = %ld we are done reading and this is set to close, stop send Failed to alloc scratch buffer!We are completely uploaded and fine %15[^?&/:]://%c%%%02xidentityALLSESSFLUSHRELOADSet-Cookie:CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!Closing connection %ld unknown proxytype option givenConnected to %s (%s) port %ld (#%ld) User-Agent: %s %s://%smemory shortageno_proxyNO_PROXYFound connection %ld, with requests in the pipe (%zu) We can reuse, but we want a new connection anyway Re-using existing connection! (#%ld) with %s %s proxyNo 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! Illegal characters found in URLBad URL, colon is first characterfilefile:%*15[^ /:]:%[^ ]%[^ ]Bad URLlocalhost/127.0.0.1/Invalid file://hostname/, expected localhost or 127.0.0.1 or noneFile drive letters are only accepted in MSDOS/Windows.%15[^ /:]:%3[/]%[^ /?#]%[^ ]%[^ /?#]%[^ ] malformedFTP.ftpDICT.DICTLDAP.LDAPIMAP.IMAPSMTP.smtpPOP3.pop3Unwillingly accepted illegal URL using %d slash%s! es%s://%s%sRebuilt URL to: %s %25Please URL encode %% as %%25, see RFC 6874. Invalid IPv6 address format Protocol "%s" not supported or disabled in libcurl*_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:.]%cIPv6 numerical address used in URL without brackets;type=%c%s://%s%s%s:%hu%s%s%s[]Port number out of rangeIllegal port numberCouldn't find host %s in the .netrc file; using defaults anonymousftp@example.comConnecting to hostname: %s Connecting to port: %d %s%s%sNo valid port number in connect to host string (%s) IDN support not present, can't parse Unicode domains Connection %ld seems to be dead! Found bundle for host %s: %p [%s] can pipelinecan multiplexseriallyServer 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 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 %lu-Unix socket path too long: '%s'Couldn't resolve host '%s'Couldn't resolve proxy '%s'%s/%s@%s%s@%s\/@libcurl/7.53.1-DEV7.53.1-DEVDarwin%s:sha256//Unrecognized parameter value passed via CURLOPT_SSLVERSION-----BEGIN PUBLIC KEY----- -----END PUBLIC KEY-----p@ 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 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 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 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 premake.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 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 = {} 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 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 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 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 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 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() 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 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 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 p.field = {} local field = p.field field._list = {} field._loweredList = {} field._sortedList = nil field._kinds = {} premake.fields = field._list field._accessors = {} function field.new(f) if f.kind:startswith("key-") then f.kind = f.kind:sub(5) f.keyed = true end if f.kind:endswith("-list") then f.kind = f.kind:sub(1, -6) f.list = true end local kind = f.kind if kind == "object" or kind == "array" then kind = "table" end if f.list then kind = "list:" .. kind end if f.keyed then kind = "keyed:" .. kind end f._kind = kind if type(f.scope) == "table" then f.scopes = f.scope else f.scopes = { f.scope } end if not field.accessor(f, "store") then return nil, "invalid field kind '" .. f._kind .. "'" end field._list[f.name] = f field._loweredList[f.name:lower()] = f field._sortedList = nil return f end function field.unregister(f) field._list[f.name] = nil field._loweredList[f.name:lower()] = nil field._sortedList = nil end function field.each() local index return function () index = next(field._list, index) return field._list[index] end end function field.eachOrdered() if not field._sortedList then local keys = table.keys(field._list) table.sort(keys) field._sortedList = {} for i = 1, #keys do field._sortedList[i] = field._list[keys[i]] end end local i = 0 return function () i = i + 1 return field._sortedList[i] end end function field.kind(tag, settings) if settings then field._kinds[tag] = settings end return field._kinds[tag] end function field.accessor(f, method) field._accessors[method] = field._accessors[method] or {} local cache = field._accessors[method] local function accessorForKind(kind) if kind == "" then return nil end if cache[kind] then return cache[kind] end local thisKind = kind:match('(.-):') or kind local nextKind = kind:sub(#thisKind + 2) local functions = field._kinds[thisKind] if not functions then return nil, "Invalid field kind '" .. thisKind .. "'" end local processor = functions[method] if not processor then return nil end local nextAccessor = accessorForKind(nextKind) accessor = function(f, current, value) return processor(f, current, value, nextAccessor) end cache[kind] = accessor return accessor end return accessorForKind(f._kind) end function field.compare(f, a, b) local processor = field.accessor(f, "compare") if processor then return processor(f, a, b) else return (a == b) end end function field.get(name) return field._list[name] or field._loweredList[name:lower()] end function field.merge(f, current, value) local processor = field.accessor(f, "merge") if processor then return processor(f, current, value) else return value end end function field.merges(f) return (field.accessor(f, "merge") ~= nil) end function field.property(f, tag) local kinds = string.explode(f._kind, ":", true) for i, kind in ipairs(kinds) do local value = field._kinds[kind][tag] if value ~= nil then return value end end end function field.override(fieldName, accessorName, func) local kind = field.kind(fieldName) p.override(kind, accessorName, func) field._accessors = {} end function field.remove(f, current, value) local processor = field.accessor(f, "remove") if processor then return processor(f, current, value) else return value end end function field.removes(f) return (field.accessor(f, "merge") ~= nil and field.accessor(f, "remove") ~= nil) end function field.store(f, current, value) local processor = field.accessor(f, "store") if processor then return processor(f, current, value) else return value end end function field.translate(f, value) local processor = field.accessor(f, "translate") if processor then return processor(f, value, nil)[1] else return value end end function field.translates(f) return (field.accessor(f, "translate") ~= nil) end local p = premake p.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.detoken = {} local detoken = p.detoken function detoken.expand(value, environ, field, basedir) function expandtoken(token, e, f) local varMap = {} if f.pathVars or e.overridePathVars then local action = p.action.current() if action then varMap = action.pathVars or {} end end local envMap = e.pathVars or {} setmetatable(e, {__index = _G}) local isAbs = false local err local result local success local dontMakeRelative = token:startswith('!') if dontMakeRelative then token = token:sub(2, -1) end local mapped = envMap[token] or varMap[token] if mapped then err = nil result = mapped if type(result) == "function" then success, result = pcall(result, e) if not success then return nil, result end end if (type(result) == "table") then isAbs = result.absolute result = result.token else isAbs = path.isabsolute(result) end else local func func, err = load("return " .. token, nil, 't', e) if not func then return nil, "load error: " .. err end success, result = pcall(func) if not success then err = result result = nil else err = nil result = result or "" end if result ~= nil then result = tostring(result) if path.hasdeferredjoin(result) then result = path.resolvedeferredjoin(result) end isAbs = path.isabsolute(result) if isAbs and not f.paths and basedir and not dontMakeRelative then result = path.getrelative(basedir, result) end end end if result ~= nil and isAbs and f.paths then result = "\0" .. result end return result, err end function expandvalue(value, e, f) if type(value) ~= "string" then return value end local count repeat value, count = value:gsub("%%{(.-)}", function(token) local result, err = expandtoken(token:gsub("\\", "\\\\"), e, f) if err then error(err .. " in token: " .. token, 0) end if not result then error("Token returned nil, it may not exist: " .. token, 0) end return result end) until count == 0 if f.paths then local i, j repeat i, j = value:find("\0") if i then value = value:sub(i + 1) end until not i end return value end local expand_cache = {} function recurse(value, e, f) if type(value) == "table" then local res_table = {} for k, v in pairs(value) do if tonumber(k) ~= nil then res_table[k] = recurse(v, e, f) else local nk = recurse(k, e, f) res_table[nk] = recurse(v, e, f) end end return res_table else local res = expand_cache[value] if res == nil then if type(value) == "string" and path.hasdeferredjoin(value) then value = path.resolvedeferredjoin(value) end res = expandvalue(value, e, f) expand_cache[value] = res end return res end end return recurse(value, environ, field or {}) end local p = premake p.configset = {} local configset = p.configset local criteria = p.criteria function configset.new(parent) local cset = {} cset.parent = parent cset.blocks = {} cset.current = nil cset.compiled = false return cset end function configset.fetch(cset, field, filter, ctx, origin) filter = filter or {} ctx = ctx or {} if p.field.merges(field) then return configset._fetchMerged(cset, field, filter, ctx, origin) else return configset._fetchDirect(cset, field, filter, ctx, origin) end end function configset._dofilter(cset, block, filter) if not filter.matcher then return (cset.compiled or criteria.matches(block._criteria, filter)) else return filter.matcher(cset, block, filter) end end function configset._fetchDirect(cset, field, filter, ctx, origin) if origin and origin ~= cset and not origin.compiled then return configset._fetchDirect(origin, field, filter, ctx, origin) end local abspath = filter.files local basedir local key = field.name local blocks = cset.blocks local n = #blocks for i = n, 1, -1 do local block = blocks[i] if not origin or block._origin == origin then local value = block[key] if value ~= nil and abspath and not cset.compiled and block._basedir and block._basedir ~= basedir then basedir = block._basedir filter.files = path.getrelative(basedir, abspath) end if value ~= nil and configset._dofilter(cset, block, filter) then if type(value) == "table" then value = table.deepcopy(value) end if field.tokens and ctx.environ then value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) end return value end end end filter.files = abspath if cset.parent then return configset._fetchDirect(cset.parent, field, filter, ctx, origin) end end function configset._fetchMerged(cset, field, filter, ctx, origin) if origin and origin ~= cset and not origin.compiled then return configset._fetchMerged(origin, field, filter, ctx, origin) end local result = {} local function remove(patterns) for _, pattern in ipairs(patterns) do if field.tokens and ctx.environ then pattern = p.detoken.expand(pattern, ctx.environ, field, ctx._basedir) end pattern = path.wildcards(pattern):lower() local j = 1 while j <= #result do local value = result[j]:lower() if value:match(pattern) == value then result[result[j]] = nil table.remove(result, j) else j = j + 1 end end end end if cset.parent then result = configset._fetchMerged(cset.parent, field, filter, ctx, origin) end local abspath = filter.files local basedir local key = field.name local blocks = cset.blocks local n = #blocks for i = 1, n do local block = blocks[i] if not origin or block._origin == origin then if abspath and block._basedir and block._basedir ~= basedir and not cset.compiled then basedir = block._basedir filter.files = path.getrelative(basedir, abspath) end if configset._dofilter(cset, block, filter) then if block._removes and block._removes[key] then remove(block._removes[key]) end local value = block[key] if type(value) == "table" then value = table.deepcopy(value) end if value then if field.tokens and ctx.environ then value = p.detoken.expand(value, ctx.environ, field, ctx._basedir) end if field and p.field.translates(field) then value = p.field.translate(field, value) end result = p.field.merge(field, result, value) end end end end filter.files = abspath return result end function configset.metatable(cset) return { __newindex = function(tbl, key, value) local f = p.field.get(key) if f then local status, err = configset.store(cset, f, value) if err then error(err, 2) end else rawset(tbl, key, value) return value end end, __index = function(tbl, key) local f = p.field.get(key) if f then return configset.fetch(cset, f) else return nil end end } end function configset.addblock(cset, terms, basedir) configset.addFilter(cset, terms, basedir, true) return cset.current end function configset.addFilter(cset, terms, basedir, unprefixed) local crit, err = criteria.new(terms, unprefixed) if not crit then return nil, err end local block = {} block._criteria = crit block._origin = cset if basedir then block._basedir = basedir:lower() end table.insert(cset.blocks, block) cset.current = block return true end function configset.getFilter(cset) return { _criteria = cset.current._criteria, _basedir = cset.current._basedir } end function configset.setFilter(cset, filter) local block = {} block._criteria = filter._criteria block._basedir = filter._basedir block._origin = cset table.insert(cset.blocks, block) cset.current = block; end function configset.store(cset, field, value) if not cset.current then configset.addblock(cset, {}) end local key = field.name local current = cset.current local status, result = pcall(function () current[key] = p.field.store(field, current[key], value) end) if not status then if type(result) == "table" then result = result.msg end return nil, result end return true end function configset.remove(cset, field, values) local block = {} block._basedir = cset.current._basedir block._criteria = cset.current._criteria block._origin = cset table.insert(cset.blocks, block) cset.current = block values = p.field.remove(field, {}, values) current = cset.current current._removes = {} current._removes[field.name] = values end function configset.empty(cset) return (#cset.blocks == 0) end function configset.compile(cset, filter) local result if cset.parent then result = configset.compile(cset.parent, filter) else result = configset.new() end local blocks = cset.blocks local n = #blocks local abspath = filter.files local basedir for i = 1, n do local block = blocks[i] if block._origin == cset then block._origin = result end if abspath and block._basedir and block._basedir ~= basedir then basedir = block._basedir filter.files = path.getrelative(basedir, abspath) end if criteria.matches(block._criteria, filter) then table.insert(result.blocks, block) end end filter.files = abspath result.compiled = true return result end local p = premake 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.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.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.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 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.global = p.api.container("global") local global = p.global function global.new(name) return p.container.new(p.global, name) end function global.bake(self) p.container.bakeChildren(self) end function global.eachRule() local root = p.api.rootContainer() return p.container.eachChild(root, p.rule) end function global.eachWorkspace() local root = p.api.rootContainer() return p.container.eachChild(root, p.workspace) end p.alias(global, "eachWorkspace", "eachSolution") function global.getRule(key) local root = p.api.rootContainer() return root.rules[key] end function global.getRuleForFile(fname, rules) for rule in global.eachRule() do if not rules or table.contains(rules, rule.name) then if path.hasextension(fname, rule.fileextension) then return rule end end end end function global.getWorkspace(key) local root = p.api.rootContainer() return root.workspaces[key] end p.alias(global, "getWorkspace", "getSolution") local p = premake p.workspace = p.api.container("workspace", p.global) local workspace = p.workspace p.solution = workspace workspace.alias = "solution" p.alias(_G, "workspace", "solution") p.alias(_G, "externalworkspace", "externalsolution") function workspace.new(name) local wks = p.container.new(workspace, name) return wks end function workspace.eachconfig(self) self = p.oven.bakeWorkspace(self) local i = 0 return function() i = i + 1 if i > #self.configs then return nil else return self.configs[i] end end end function workspace.eachproject(self) local i = 0 return function () i = i + 1 if i <= #self.projects then return p.workspace.getproject(self, i) end end end function workspace.findproject(self, name) name = name:lower() for _, prj in ipairs(self.projects) do if name == prj.name:lower() then return prj end end return nil end function workspace.grouptree(self) if self.grouptree then return self.grouptree end local tr = p.tree.new() for prj in workspace.eachproject(self) do local prjpath = path.join(prj.group, prj.name) local node = p.tree.add(tr, prjpath) node.project = prj end p.tree.traverse(tr, { onbranch = function(node) node.uuid = os.uuid("group:" .. node.path) end }) p.tree.sort(tr, function(a,b) return a.name < b.name end) self.grouptree = tr return tr end function workspace.getproject(self, idx) self = p.oven.bakeWorkspace(self) return self.projects[idx] end function workspace.hasProject(self, func) return p.container.hasChild(self, p.project, func) end function workspace.getrelative(self, filename) if type(filename) == "table" then local result = {} for i, name in ipairs(filename) do if name and #name > 0 then table.insert(result, workspace.getrelative(self, name)) end end return result else if filename then local result = filename if path.hasdeferredjoin(result) then result = path.resolvedeferredjoin(result) end return path.getrelative(self.location, result) end end end local p = premake p.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 local p = premake p.project = p.api.container("project", p.workspace, { "config" }) local project = p.project local tree = p.tree external = externalproject function project.new(name) local prj = p.container.new(project, name) prj.uuid = os.uuid(name) if p.api.scope.group then prj.group = p.api.scope.group.name else prj.group = "" end return prj end function project.eachconfig(prj) local configs = prj._cfglist local count = #configs local seen = {} local i = 0 return function () i = i + 1 if i <= count then local cfg = project.getconfig(prj, configs[i][1], configs[i][2]) if not seen[cfg] then seen[cfg] = true return cfg else i = i + 1 end end end end function project.findClosestMatch(prj, buildcfg, platform) buildcfg = project.mapconfig(prj, buildcfg)[1] platform = project.mapconfig(prj, platform)[1] if not table.contains(prj.configurations, buildcfg) then buildcfg = prj.configurations[1] end if not table.contains(prj.platforms, platform) then platform = prj.platforms[1] end return project.getconfig(prj, buildcfg, platform) end function project.getconfig(prj, buildcfg, platform) if not buildcfg then return prj end local pairing = project.mapconfig(prj, buildcfg, platform) buildcfg = pairing[1] platform = pairing[2] local key = (buildcfg or "*") .. (platform or "") return prj.configs[key] end function project.getdependencies(prj, mode) if not prj.dependencies then prj.dependencies = {} end local m = mode or 'all' local result = prj.dependencies[m] if result then return result end local function add_to_project_list(cfg, depproj, result) local dep = p.workspace.findproject(cfg.workspace, depproj) if dep and not table.contains(result, dep) then table.insert(result, dep) end end local linkOnly = m == 'linkOnly' local depsOnly = m == 'dependOnly' result = {} for cfg in project.eachconfig(prj) do if not depsOnly then for _, link in ipairs(cfg.links) do if link ~= prj.name then add_to_project_list(cfg, link, result) end end end if not linkOnly then for _, depproj in ipairs(cfg.dependson) do add_to_project_list(cfg, depproj, result) end end end prj.dependencies[m] = result return result end function project.getfirstconfig(prj) local iter = project.eachconfig(prj) local first = iter() return first end function project.getrelative(prj, filename) if type(filename) == "table" then local result = {} for i, name in ipairs(filename) do result[i] = project.getrelative(prj, name) end return result else if filename then local result = filename if path.hasdeferredjoin(result) then result = path.resolvedeferredjoin(result) end return path.getrelative(prj.location, result) end end end function project.getsourcetree(prj, sorter) if prj._.sourcetree then return prj._.sourcetree end local tr = tree.new(prj.name) table.foreachi(prj._.files, function(fcfg) if fcfg.generated then return; end local flags if fcfg.vpath ~= fcfg.relpath then flags = { trim = false } end local parent = tree.add(tr, path.getdirectory(fcfg.vpath), flags) local node = tree.insert(parent, tree.new(path.getname(fcfg.vpath))) setmetatable(node, { __index = fcfg }) end) table.foreachi(prj._.files, function(fcfg) if not fcfg.generated then return; end local parent = tree.add(tr, path.getdirectory(fcfg.dependsOn.vpath)) local node = tree.insert(parent, tree.new(path.getname(fcfg.vpath))) setmetatable(node, { __index = fcfg }) end) tree.trimroot(tr) tree.sort(tr, sorter) prj._.sourcetree = tr return tr end function project.getvpath(prj, abspath) local vpath = abspath local fname = path.getname(abspath) local max = abspath:len() - fname:len() for _, vpaths in ipairs(prj.vpaths) do for replacement, patterns in pairs(vpaths) do for _, pattern in ipairs(patterns) do local i = abspath:find(path.wildcards(pattern)) if i == 1 then i = pattern:find("*", 1, true) or (pattern:len() + 1) local leaf if i < max then leaf = abspath:sub(i) else leaf = fname end if leaf:startswith("/") then leaf = leaf:sub(2) end local stem = "" if replacement:len() > 0 then stem, stars = replacement:gsub("%*", "") if stars == 0 then leaf = path.getname(leaf) end else leaf = path.getname(leaf) end vpath = path.join(stem, leaf) return vpath end end end end return vpath end function project.hasConfig(prj, func) for cfg in project.eachconfig(prj) do if func(cfg) then return true end end end function project.hasfile(prj, filename) return (prj._.files[filename] ~= nil) end function project.isdotnet(prj) return p.languages.iscsharp(prj.language) or p.languages.isfsharp(prj.language) end function project.iscsharp(prj) return p.languages.iscsharp(prj.language) end function project.isfsharp(prj) return p.languages.isfsharp(prj.language) end function project.isc(prj) return p.languages.isc(prj.language) end function project.iscpp(prj) return p.languages.iscpp(prj.language) end function project.isnative(prj) return project.isc(prj) or project.iscpp(prj) end function project.mapconfig(prj, buildcfg, platform) local pairing = { buildcfg, platform } local testpattern = function(pattern, pairing, i) local j = 1 while i <= #pairing and j <= #pattern do local wd = path.wildcards(pattern[j]) if pairing[i]:match(wd) ~= pairing[i] then return false end i = i + 1 j = j + 1 end return true end local maps = prj.configmap or {} for mi = 1, #maps do for pattern, replacements in pairs(maps[mi]) do if type(pattern) ~= "table" then pattern = { pattern } end for i = 1, #pairing do if testpattern(pattern, pairing, i) then if #pattern == 1 and #replacements == 1 then pairing[i] = replacements[1] else pairing = { replacements[1], replacements[2] } end end end end end return pairing end function project.systemversion(prj) if prj.systemversion ~= nil then local values = string.explode(prj.systemversion, ":", true) return values[1], values[2] end end local p = premake p.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.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.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.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 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 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 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 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.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 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 p = premake p.tools.snc = {} local snc = p.tools.snc local gcc = p.tools.gcc snc.shared = { flags = { FatalCompileWarnings = "-Xquit=2", }, optimize = { Off = "-O0", On = "-O1", Debug = "-Od", Full = "-O3", Size = "-Os", Speed = "-O2", }, warnings = { Extra = "-Xdiag=2", } } snc.cflags = { } function snc.getcflags(cfg) local shared = p.config.mapFlags(cfg, snc.shared) local cflags = p.config.mapFlags(cfg, snc.cflags) local flags = table.join(shared, cflags, snc.getwarnings(cfg)) return flags end snc.cxxflags = { exceptionhandling = { Default = "-Xc+=exceptions", On = "-Xc+=exceptions", SEH = "-Xc-=exceptions", }, rtti = { Default = "-Xc+=rtti", On = "-Xc+=rtti", SEH = "-Xc-=rtti", } } function snc.getcxxflags(cfg) local shared = config.mapFlags(cfg, snc.shared) local cxxflags = config.mapFlags(cfg, snc.cxxflags) local flags = table.join(shared, cxxflags, snc.getwarnings(cfg)) return flags end function snc.getforceincludes(cfg) local flags = gcc.getforceincludes(cfg) return flags end function snc.getldflags(cfg) local flags = { } if not (cfg.symbols == p.ON) then table.insert(flags, "-s") end return flags end snc.getcppflags = gcc.getcppflags snc.getdefines = gcc.getdefines snc.getincludedirs = gcc.getincludedirs snc.getrunpathdirs = gcc.getrunpathdirs snc.getLibraryDirectories = gcc.getLibraryDirectories snc.getlinks = gcc.getlinks function snc.getmakesettings(cfg) return nil end snc.tools = { } function snc.gettoolname(cfg, tool) local names = snc.tools[cfg.architecture] or snc.tools[cfg.system] or {} return names[tool] end local p = premake p.tools.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.mingw = p.tools.gcc premake.clean = {} newaction { trigger = "clean", description = "Remove all binaries and generated files", execute = function() print("** The clean action has not yet been ported") end } local p = premake local 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 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 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 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 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 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 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 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 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 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 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 local p = premake p.modules.gmake = {} p.modules.gmake._VERSION = p._VERSION p.make = p.modules.gmake local make = p.make local project = p.project function make.defaultconfig(target) local eachconfig = iif(target.project, project.eachconfig, p.workspace.eachconfig) local defaultconfig = nil if target.defaultplatform then for cfg in eachconfig(target) do if cfg.platform == target.defaultplatform then defaultconfig = cfg break end end end if not defaultconfig then local iter = eachconfig(target) defaultconfig = iter() end if defaultconfig then _p('ifndef config') _x(' config=%s', defaultconfig.shortname) _p('endif') _p('') end end function make.esc(value) result = value:gsub("\\", "\\\\") result = result:gsub("\"", "\\\"") result = result:gsub(" ", "\\ ") result = result:gsub("%(", "\\(") result = result:gsub("%)", "\\)") result = result:gsub("$\\%((.-)\\%)", "$(%1)") return result end function make.getmakefilename(this, searchprjs) local count = 0 for wks in p.global.eachWorkspace() do if wks.location == this.location then count = count + 1 end if searchprjs then for _, prj in ipairs(wks.projects) do if prj.location == this.location then count = count + 1 end end end end if count == 1 then return "Makefile" else return ".make" end end function make.header(target) local kind = iif(target.project, "project", "workspace") _p('# %s %s makefile autogenerated by Premake', p.action.current().shortname, kind) _p('') if kind == "workspace" then local haspch = false for _, prj in ipairs(target.projects) do for cfg in project.eachconfig(prj) do if cfg.pchheader then haspch = true end end end if haspch then _p('.NOTPARALLEL:') _p('') end end make.defaultconfig(target) _p('ifndef verbose') _p(' SILENT = @') _p('endif') _p('') end function make.mkdir(dirname) _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) mkdir -p %s', dirname) _p('else') _p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', dirname) _p('endif') end function make.mkdirRules(dirname) _p('%s:', dirname) _p('\t@echo Creating %s', dirname) make.mkdir(dirname) _p('') end function make.list(value, quoted) quoted = false if #value > 0 then if quoted then local result = "" for _, v in ipairs (value) do if #result then result = result .. " " end result = result .. p.quoted(v) end return result else return " " .. table.concat(value, " ") end else return "" end end function make.tovar(value) value = value:gsub("[ -]", "_") value = value:gsub("[()]", "") return value end function make.objdir(cfg) _x(' OBJDIR = %s', p.esc(project.getrelative(cfg.project, cfg.objdir))) end function make.objDirRules(prj) make.mkdirRules("$(OBJDIR)") end function make.phonyRules(prj) _p('.PHONY: clean prebuild prelink') _p('') end function make.buildCmds(cfg, event) _p(' define %sCMDS', event:upper()) local steps = cfg[event .. "commands"] local msg = cfg[event .. "message"] if #steps > 0 then steps = os.translateCommandsAndPaths(steps, cfg.project.basedir, cfg.project.location) msg = msg or string.format("Running %s commands", event) _p('\t@echo %s', msg) _p('\t%s', table.implode(steps, "", "", "\n\t")) end _p(' endef') end function make.preBuildCmds(cfg, toolset) make.buildCmds(cfg, "prebuild") end function make.preBuildRules(prj) _p('prebuild:') _p('\t$(PREBUILDCMDS)') _p('') end function make.preLinkCmds(cfg, toolset) make.buildCmds(cfg, "prelink") end function make.preLinkRules(prj) _p('prelink:') _p('\t$(PRELINKCMDS)') _p('') end function make.postBuildCmds(cfg, toolset) make.buildCmds(cfg, "postbuild") end function make.settings(cfg, toolset) if #cfg.makesettings > 0 then for _, value in ipairs(cfg.makesettings) do _p(value) end end local value = toolset.getmakesettings(cfg) if value then _p(value) end end function make.shellType() _p('SHELLTYPE := posix') _p('ifeq (.exe,$(findstring .exe,$(ComSpec)))') _p('\tSHELLTYPE := msdos') _p('endif') _p('') end function make.target(cfg) _x(' TARGETDIR = %s', project.getrelative(cfg.project, cfg.buildtarget.directory)) _x(' TARGET = $(TARGETDIR)/%s', cfg.buildtarget.name) end function make.targetDirRules(prj) make.mkdirRules("$(TARGETDIR)") end include("gmake_cpp.lua") include("gmake_csharp.lua") include("gmake_makefile.lua") include("gmake_utility.lua") include("gmake_workspace.lua") return p.modules.gmake local p = premake p.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.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 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.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 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.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 m = p.modules.self_test local _ = {} function m.capture(expected) local actual = p.captured() .. p.eol() local ait = actual:gmatch("(.-)" .. p.eol()) local eit = expected:gmatch("(.-)\n") local linenum = 1 local atxt = ait() local etxt = eit() while etxt do if (etxt ~= atxt) then m.fail("(%d) expected:\n%s\n...but was:\n%s\nfulltext:\n%s", linenum, etxt, atxt, actual) end linenum = linenum + 1 atxt = ait() etxt = eit() end end function m.closedfile(expected) if expected and not m.value_closedfile then m.fail("expected file to be closed") elseif not expected and m.value_closedfile then m.fail("expected file to remain open") end end function m.contains(expected, actual) if type(expected) == "table" then for i, v in ipairs(expected) do m.contains(v, actual) end elseif not table.contains(actual, expected) then m.fail("expected value %s not found", expected) end end function m.excludes(expected, actual) if type(expected) == "table" then for i, v in ipairs(expected) do m.excludes(v, actual) end elseif table.contains(actual, expected) then m.fail("excluded value %s found", expected) end end function m.fail(format, ...) local depth = 3 local arg = {...} if type(format) == "number" then depth = depth + format format = table.remove(arg, 1) end for i = 1, #arg do if (arg[i] == nil) then arg[i] = "(nil)" elseif (type(arg[i]) == "table") then arg[i] = "{" .. table.concat(arg[i], ", ") .. "}" end end local msg = string.format(format, table.unpack(arg)) error(debug.traceback(msg, depth), depth) end function m.filecontains(expected, fn) local f = io.open(fn) local actual = f:read("*a") f:close() if (expected ~= actual) then m.fail("expected %s but was %s", expected, actual) end end function m.hasoutput() local actual = p.captured() if actual == "" then m.fail("expected output, received none"); end end function m.isemptycapture() local actual = p.captured() if actual ~= "" then m.fail("expected empty capture, but was %s", actual); end end function m.isequal(expected, actual, depth) depth = depth or 0 if type(expected) == "table" then if expected and not actual then m.fail(depth, "expected table, got nil") end if #expected < #actual then m.fail(depth, "expected %d items, got %d", #expected, #actual) end for k,v in pairs(expected) do m.isequal(expected[k], actual[k], depth + 1) end else if (expected ~= actual) then m.fail(depth, "expected %s but was %s", expected, actual or "nil") end end return true end function m.isfalse(value) if (value) then m.fail("expected false but was true") end end function m.isnil(value) if (value ~= nil) then m.fail("expected nil but was " .. tostring(value)) end end function m.isnotnil(value) if (value == nil) then m.fail("expected not nil") end end function m.issame(expected, action) if expected ~= action then m.fail("expected same value") end end function m.istrue(value) if (not value) then m.fail("expected true but was false") end end function m.missing(value, actual) if table.contains(actual, value) then m.fail("unexpected value %s found", value) end end function m.openedfile(fname) if fname ~= m.value_openedfilename then local msg = "expected to open file '" .. fname .. "'" if m.value_openedfilename then msg = msg .. ", got '" .. m.value_openedfilename .. "'" end m.fail(msg) end end function m.success(fn, ...) local ok, err = pcall(fn, ...) if not ok then m.fail("call failed: " .. err) end end function m.stderr(expected) if not expected and m.stderr_capture then m.fail("Unexpected: " .. m.stderr_capture) elseif expected then if not m.stderr_capture or not m.stderr_capture:find(expected) then m.fail(string.format("expected '%s'; got %s", expected, m.stderr_capture or "(nil)")) end end end function m.notstderr(expected) if not expected and not m.stderr_capture then m.fail("Expected output on stderr; none received") elseif expected then if m.stderr_capture and m.stderr_capture:find(expected) then m.fail(string.format("stderr contains '%s'; was %s", expected, m.stderr_capture)) end end end local p = premake local m = p.modules.self_test local _ = {} _.suites = {} _.suppressed = {} function m.declare(suiteName) if _.suites[suiteName] then error('Duplicate test suite "'.. suiteName .. '"', 2) end local _suite = {} local suite = setmetatable({}, { __index = _suite, __newindex = function (table, key, value) if m.detectDuplicateTests and _suite[key] ~= nil then error('Duplicate test "'.. key .. '"', 2) end _suite[key] = value end, __pairs = function (table) return pairs(_suite) end, __ipairs = function (table) return ipairs(_suite) end, }) suite._SCRIPT_DIR = _SCRIPT_DIR suite._TESTS_DIR = _TESTS_DIR _.suites[suiteName] = suite return suite end function m.suppress(identifier) if type(identifier) == "table" then for i = 1, #identifier do m.suppress(identifier[i]) end else _.suppressed[identifier] = true end end function m.isSuppressed(identifier) return _.suppressed[identifier] end function m.isValid(test) if type(test.testFunction) ~= "function" then return false end if test.testName == "setup" or test.testName == "teardown" then return false end return true end function m.getSuites() return _.suites end function m.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 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 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 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.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 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.vstudio.vs2008 = {} local vs2008 = p.vstudio.vs2008 local vstudio = p.vstudio newaction { trigger = "vs2008", shortname = "Visual Studio 2008", description = "Generate Visual Studio 2008 project files", targetos = "windows", toolset = "msc-v90", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = vstudio.vs2005.generateSolution, onProject = vstudio.vs2005.generateProject, onCleanWorkspace = vstudio.cleanSolution, onCleanProject = vstudio.cleanProject, onCleanTarget = vstudio.cleanTarget, vstudio = { csprojSchemaVersion = "2.0", productVersion = "9.0.30729", solutionVersion = "10", versionName = "2008", toolsVersion = "3.5", } } local p = premake 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.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 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 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.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 m = p.vstudio.cs2005 local dn = p.vstudio.dotnetbase m.elements.userProjectPropertyGroup = function() return { m.referencePath, } end m.elements.userConfigPropertyGroup = function() return { m.localDebuggerCommandArguments, } end function m.generateUser(prj) local prjGroup = p.capture(function() p.push(2) p.callArray(m.elements.userProjectPropertyGroup, prj) p.pop(2) end) local contents = {} local size = 0 for cfg in p.project.eachconfig(prj) do contents[cfg] = p.capture(function() p.push(2) p.callArray(m.elements.userConfigPropertyGroup, cfg) p.pop(2) end) size = size + #contents[cfg] end if #prjGroup > 0 or size > 0 then p.vstudio.projectElement() if #prjGroup > 0 then p.push('') p.outln(prjGroup) p.pop('') end for cfg in p.project.eachconfig(prj) do if #contents[cfg] > 0 then p.push('', dn.condition(cfg)) p.outln(contents[cfg]) p.pop('') end end p.pop('') end end function m.referencePath(prj) local cfg = p.project.getfirstconfig(prj) local paths = p.vstudio.path(prj, cfg.libdirs) if #paths > 0 then p.w('%s', table.concat(paths, ";")) end end function m.localDebuggerCommandArguments(cfg) if #cfg.debugargs > 0 then p.x('%s', table.concat(cfg.debugargs, " ")) end end local p = premake p.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.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.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", } } local p = premake p.vstudio.nuget2010 = {} local vstudio = p.vstudio local nuget2010 = p.vstudio.nuget2010 local dn2005 = p.vstudio.dotnetbase local packageAPIInfos = {} local packageSourceInfos = {} function nuget2010.packageId(package) return package:sub(0, package:find(":") - 1) end function nuget2010.packageVersion(package) return package:sub(package:find(":") + 1, -1) end function nuget2010.packageFramework(prj) if p.project.isdotnet(prj) then local cfg = p.project.getfirstconfig(prj) local action = p.action.current() local framework = cfg.dotnetframework or action.vstudio.targetFramework return dn2005.formatNuGetFrameworkVersion(framework) else return "native" end end function nuget2010.supportsPackageReferences(prj) return _ACTION >= "vs2017" and p.project.isdotnet(prj) end function nuget2010.packageAPIInfo(prj, package) local id = nuget2010.packageId(package) local version = nuget2010.packageVersion(package) local function examinePackageFromCache() if not os.ishost("windows") then return end local cachePath = path.translate(path.join(os.getenv("userprofile"), ".nuget/packages", id)) if os.isdir(cachePath) then local packageAPIInfo = {} printf("Examining cached NuGet package '%s'...", id) io.flush() local versionPath = path.translate(path.join(cachePath, version)) local nuspecPath = path.translate(path.join(versionPath, id .. ".nuspec")) if not os.isfile(nuspecPath) then return end local nuspec = io.readfile(nuspecPath) if not nuspec then return end packageAPIInfo.verbatimVersion = nuspec:match("(.+)") packageAPIInfo.version = version if not packageAPIInfo.verbatimVersion then return end if p.project.isdotnet(prj) then packageAPIInfo.packageEntries = {} for _, file in ipairs(os.matchfiles(path.translate(path.join(versionPath, "**")))) do local extension = path.getextension(file) if extension ~= ".nupkg" and extension ~= ".sha512" then table.insert(packageAPIInfo.packageEntries, path.translate(path.getrelative(versionPath, file))) end end if #packageAPIInfo.packageEntries == 0 then return end if nuspec:match("(.+)") then p.warn("NuGet package '%s' may depend on .NET Framework assemblies - package dependencies are currently unimplemented", id) end end if nuspec:match("(.+)") then p.warn("NuGet package '%s' may depend on other packages - package dependencies are currently unimplemented", id) end packageAPIInfos[package] = packageAPIInfo end end if not packageAPIInfos[package] then examinePackageFromCache() end if not packageAPIInfos[package] then if not packageSourceInfos[prj.nugetsource] then local packageSourceInfo = {} printf("Examining NuGet package source '%s'...", prj.nugetsource) io.flush() local response, err, code = http.get(prj.nugetsource) if err ~= "OK" then p.error("NuGet API error (%d)\n%s", code, err) end response, err = json.decode(response) if not response then p.error("Failed to decode NuGet API response (%s)", err) end if not response.resources then p.error("Failed to understand NuGet API response (no resources in response)", id) end local packageDisplayMetadataUriTemplate, catalog for _, resource in ipairs(response.resources) do if not resource["@id"] then p.error("Failed to understand NuGet API response (no resource['@id'])") end if not resource["@type"] then p.error("Failed to understand NuGet API response (no resource['@type'])") end if resource["@type"]:find("PackageDisplayMetadataUriTemplate") == 1 then packageDisplayMetadataUriTemplate = resource end if resource["@type"]:find("Catalog") == 1 then catalog = resource end end if not packageDisplayMetadataUriTemplate then p.error("Failed to understand NuGet API response (no PackageDisplayMetadataUriTemplate resource)") end if not catalog then if prj.nugetsource == "https://api.nuget.org/v3/index.json" then p.error("Failed to understand NuGet API response (no Catalog resource)") else p.error("Package source is not a NuGet gallery - non-gallery sources are currently unsupported", prj.nugetsource, prj.name) end end packageSourceInfo.packageDisplayMetadataUriTemplate = packageDisplayMetadataUriTemplate packageSourceInfo.catalog = catalog packageSourceInfos[prj.nugetsource] = packageSourceInfo end local packageAPIInfo = {} printf("Examining NuGet package '%s'...", id) io.flush() local response, err, code = http.get(packageSourceInfos[prj.nugetsource].packageDisplayMetadataUriTemplate["@id"]:gsub("{id%-lower}", id:lower())) if err ~= "OK" then if code == 404 then p.error("NuGet package '%s' for project '%s' couldn't be found in the repository", id, prj.name) else p.error("NuGet API error (%d)\n%s", code, err) end end response, err = json.decode(response) if not response then p.error("Failed to decode NuGet API response (%s)", err) end if not response.items or #response.items == 0 then p.error("Failed to understand NuGet API response (no pages for package '%s')", id) end local items = {} for _, page in ipairs(response.items) do if not page.items or #page.items == 0 then p.error("Failed to understand NuGet API response (got a page with no items for package '%s')", id) end for _, item in ipairs(page.items) do table.insert(items, item) end end local versions = {} for _, item in ipairs(items) do if not item.catalogEntry then p.error("Failed to understand NuGet API response (subitem of package '%s' has no catalogEntry)", id) end if not item.catalogEntry.version then p.error("Failed to understand NuGet API response (subitem of package '%s' has no catalogEntry.version)", id) end if not item.catalogEntry["@id"] then p.error("Failed to understand NuGet API response (subitem of package '%s' has no catalogEntry['@id'])", id) end table.insert(versions, item.catalogEntry.version) end if not table.contains(versions, version) then local options = table.translate(versions, function(value) return "'" .. value .. "'" end) options = table.concat(options, ", ") p.error("'%s' is not a valid version for NuGet package '%s' (options are: %s)", version, id, options) end for _, item in ipairs(items) do if item.catalogEntry.version == version then local response, err, code = http.get(item.catalogEntry["@id"]) if err ~= "OK" then if code == 404 then p.error("NuGet package '%s' version '%s' couldn't be found in the repository even though the API reported that it exists", id, version) else p.error("NuGet API error (%d)\n%s", code, err) end end response, err = json.decode(response) if not response then p.error("Failed to decode NuGet API response (%s)", err) end if not response.verbatimVersion and not response.version then p.error("Failed to understand NuGet API response (package '%s' version '%s' has no verbatimVersion or version)", id, version) end packageAPIInfo.verbatimVersion = response.verbatimVersion packageAPIInfo.version = response.version if prj.language == "C#" and not response.packageEntries then p.error("NuGet package '%s' version '%s' has no file listing. This package might be too old to be using this API or it might be a C++ package instead of a .NET Framework package.", id, response.version) end if prj.language == "C#" then packageAPIInfo.packageEntries = {} for _, item in ipairs(response.packageEntries) do if not item.fullName then p.error("Failed to understand NuGet API response (package '%s' version '%s' packageEntry has no fullName)", id, version) end table.insert(packageAPIInfo.packageEntries, path.translate(item.fullName)) end if #packageAPIInfo.packageEntries == 0 then p.error("NuGet package '%s' file listing is empty", id) end if response.frameworkAssemblyGroup then p.warn("NuGet package '%s' may depend on .NET Framework assemblies - package dependencies are currently unimplemented", id) end end if response.dependencyGroups then p.warn("NuGet package '%s' may depend on other packages - package dependencies are currently unimplemented", id) end break end end packageAPIInfos[package] = packageAPIInfo end return packageAPIInfos[package] end function nuget2010.generatePackagesConfig(prj) if #prj.nuget > 0 then p.w('') p.push('') for _, package in ipairs(prj.nuget) do p.x('', nuget2010.packageId(package), nuget2010.packageVersion(package), nuget2010.packageFramework(prj)) end p.pop('') end end function nuget2010.generateNuGetConfig(prj) if #prj.nuget == 0 then return end if prj.nugetsource == "https://api.nuget.org/v3/index.json" then return end p.w('') p.push('') p.push('') p.x('') p.x('', prj.nugetsource, prj.nugetsource) p.pop('') p.pop('') end function nuget2010.uniqueProjectLocationsWithNuGet(wks) local locations = {} for prj in p.workspace.eachproject(wks) do if not nuget2010.supportsPackageReferences(prj) then local function fail() p.error("projects '%s' and '%s' cannot have the same location when using NuGet with different packages (packages.config conflict)", locations[prj.location].name, prj.name) end if locations[prj.location] and #locations[prj.location].nuget > 0 and #prj.nuget > 0 then if #locations[prj.location].nuget ~= #prj.nuget then fail() end for i, package in ipairs(locations[prj.location].nuget) do if prj.nuget[i] ~= package then fail() end end end locations[prj.location] = prj end end end p.override(p.validation.elements, "workspace", function (oldfn, wks) local t = oldfn(wks) table.insert(t, nuget2010.uniqueProjectLocationsWithNuGet) return t end) function nuget2010.NuGetHasHTTP(prj) if not http and #prj.nuget > 0 and not nuget2010.supportsPackageReferences(prj) then p.error("Premake was compiled with --no-curl, but Curl is required for NuGet support (project '%s' is referencing NuGet packages)", prj.name) end end function nuget2010.NuGetPackageStrings(prj) for _, package in ipairs(prj.nuget) do local components = package:explode(":") if #components ~= 2 or #components[1] == 0 or #components[2] == 0 then p.error("NuGet package '%s' in project '%s' is invalid - please give packages in the format 'id:version', e.g. 'NUnit:3.6.1'", package, prj.name) end end end p.override(p.validation.elements, "project", function (oldfn, prj) local t = oldfn(prj) table.insert(t, nuget2010.NuGetHasHTTP) table.insert(t, nuget2010.NuGetPackageStrings) return t end) local p = premake p.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.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 local 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.vstudio.vs2010.rules = {} p.vstudio.vs2010.rules.props = {} local m = p.vstudio.vs2010.rules.props m.elements = {} m.elements.project = function(r) return { p.vstudio.projectElement, m.targetsGroup, m.dependsOnGroup, m.ruleGroup, } end function m.generate(r) p.xmlUtf8() p.callArray(m.elements.project, r) p.pop() p.out('') end m.elements.targetsGroup = function(r) return { m.beforeTargets, m.afterTargets, } end function m.targetsGroup(r) p.w('', r.name, r.name) p.callArray(m.elements.targetsGroup, r) p.pop('') end m.elements.dependsOnGroup = function(r) return { m.dependsOn, } end function m.dependsOnGroup(r) p.push('') p.callArray(m.elements.dependsOnGroup, r) p.pop('') end m.elements.ruleGroup = function(r) return { m.propertyDefaults, m.commandLineTemplates, m.executionDescription, m.additionalDependencies, } end function m.ruleGroup(r) p.push('') p.push('<%s>', r.name) p.callArray(m.elements.ruleGroup, r) p.pop('', r.name) p.pop('') end function m.propertyDefaults(r) local defs = r.propertydefinition for i = 1, #defs do local def = defs[i] local value = def.value if value then if def.kind == "path" then value = path.translate(value) end p.w('<%s>%s', def.name, value, def.name) end end end function m.additionalDependencies(r) local deps = table.concat(r.builddependencies, ";") p.x('%s', deps) end function m.afterTargets(r) p.w('<%sAfterTargets>CustomBuild', r.name, r.name) end function m.beforeTargets(r) p.w('<%sBeforeTargets>Midl', r.name, r.name) end function m.commandLineTemplates(r) local env = p.rule.createEnvironment(r, "[%s]") local ctx = p.context.extent(r, env) local buildcommands = ctx.buildcommands if buildcommands and #buildcommands > 0 then local cmds = os.translateCommands(buildcommands, p.WINDOWS) cmds = table.concat(cmds, p.eol()) p.x('%s', cmds) end end function m.dependsOn(r) p.w('<%sDependsOn', r.name) p.w(' Condition="\'$(ConfigurationType)\' != \'Makefile\'">_SelectedFiles;$(%sDependsOn)', r.name, r.name, r.name) end function m.executionDescription(r) local env = p.rule.createEnvironment(r, "%%(%s)") local ctx = p.context.extent(r, env) local buildmessage = ctx.buildmessage if buildmessage and #buildmessage > 0 then p.x('%s', buildmessage) end end local p = premake p.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.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 vstudio = p.vstudio newaction { trigger = "vs2012", shortname = "Visual Studio 2012", description = "Generate Visual Studio 2012 project files", targetos = "windows", toolset = "msc-v110", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility" }, valid_languages = { "C", "C++", "C#", "F#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onWorkspace = function(wks) vstudio.vs2005.generateSolution(wks) end, onProject = function(prj) vstudio.vs2010.generateProject(prj) end, onRule = function(rule) vstudio.vs2010.generateRule(rule) end, onCleanWorkspace = function(wks) vstudio.cleanSolution(wks) end, onCleanProject = function(prj) vstudio.cleanProject(prj) end, onCleanTarget = function(prj) vstudio.cleanTarget(prj) end, pathVars = vstudio.vs2010.pathVars, vstudio = { solutionVersion = "12", versionName = "2012", targetFramework = "4.5", toolsVersion = "4.0", } } local p = premake 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 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 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", } } 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 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", } } 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", } } 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 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 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 local gmake2 = p.modules.gmake2 gmake2.cs = {} local cs = gmake2.cs local project = p.project local config = p.config local fileconfig = p.fileconfig cs.elements = {} cs.elements.makefile = function(prj) return { gmake2.header, gmake2.phonyRules, gmake2.csConfigs, gmake2.csProjectConfig, gmake2.csSources, gmake2.csEmbedFiles, gmake2.csCopyFiles, gmake2.csResponseFile, gmake2.shellType, gmake2.csAllRules, gmake2.csTargetRules, gmake2.targetDirRules, gmake2.csResponseRules, gmake2.objDirRules, gmake2.csCleanRules, gmake2.preBuildRules, gmake2.csFileRules, } end function cs.generate(prj) p.eol("\n") local toolset = p.tools.dotnet p.callArray(cs.elements.makefile, prj, toolset) end cs.elements.configuration = function(cfg) return { gmake2.csTools, gmake2.target, gmake2.objdir, gmake2.csFlags, gmake2.csLinkCmd, gmake2.preBuildCmds, gmake2.preLinkCmds, gmake2.postBuildCmds, gmake2.settings, } end function gmake2.csConfigs(prj, toolset) for cfg in project.eachconfig(prj) do _x('ifeq ($(config),%s)', cfg.shortname) p.callArray(cs.elements.configuration, cfg, toolset) _p('endif') _p('') end end function cs.getresourcefilename(cfg, fname) if path.getextension(fname) == ".resx" then local name = cfg.buildtarget.basename .. "." local dir = path.getdirectory(fname) if dir ~= "." then name = name .. path.translate(dir, ".") .. "." end return "$(OBJDIR)/" .. p.esc(name .. path.getbasename(fname)) .. ".resources" else return fname end end function cs.listsources(prj, selector) local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) local value = selector(node) if value then _x('\t%s \\', value) end end }) end function gmake2.csAllRules(prj, toolset) _p('all: prebuild $(EMBEDFILES) $(COPYFILES) $(TARGET)') _p('') end function gmake2.csCleanRules(prj, toolset) end function gmake2.csCopyFiles(prj, toolset) end function cs.getresponsefilename(prj) return '$(OBJDIR)/' .. prj.filename .. '.rsp' end function gmake2.csResponseFile(prj, toolset) _x('RESPONSE += ' .. gmake2.cs.getresponsefilename(prj)) end function gmake2.csResponseRules(prj) local toolset = p.tools.dotnet local ext = gmake2.getmakefilename(prj, true) local makefile = path.getname(p.filename(prj, ext)) local response = gmake2.cs.getresponsefilename(prj) _p('$(RESPONSE): %s', makefile) _p('\t@echo Generating response file', prj.name) _p('ifeq (posix,$(SHELLTYPE))') _x('\t$(SILENT) rm -f $(RESPONSE)') _p('else') _x('\t$(SILENT) if exist $(RESPONSE) del %s', path.translate(response, '\\')) _p('endif') local sep = os.istarget("windows") and "\\" or "/" local tr = project.getsourcetree(prj) p.tree.traverse(tr, { onleaf = function(node, depth) if toolset.fileinfo(node).action == "Compile" then _x('\t@echo %s >> $(RESPONSE)', path.translate(node.relpath, sep)) end end }) _p('') end function gmake2.csEmbedFiles(prj, toolset) local cfg = project.getfirstconfig(prj) _p('EMBEDFILES += \\') cs.listsources(prj, function(node) local fcfg = fileconfig.getconfig(node, cfg) local info = toolset.fileinfo(fcfg) if info.action == "EmbeddedResource" then return cs.getresourcefilename(cfg, node.relpath) end end) _p('') end function gmake2.csFileRules(prj, toolset) end function gmake2.csFlags(cfg, toolset) _p(' FLAGS =%s', gmake2.list(toolset.getflags(cfg))) end function gmake2.csLinkCmd(cfg, toolset) local deps = p.esc(config.getlinks(cfg, "dependencies", "fullpath")) _p(' DEPENDS =%s', gmake2.list(deps)) _p(' REFERENCES = %s', table.implode(deps, "/r:", "", " ")) end function gmake2.csProjectConfig(prj, toolset) local cfg = project.getfirstconfig(prj) local kindflag = "/t:" .. toolset.getkind(cfg):lower() local libdirs = table.implode(p.esc(cfg.libdirs), "/lib:", "", " ") _p('FLAGS += %s', table.concat(table.join(kindflag, libdirs), " ")) local refs = p.esc(config.getlinks(cfg, "system", "fullpath")) _p('REFERENCES += %s', table.implode(refs, "/r:", "", " ")) _p('') end function gmake2.csSources(prj, toolset) local cfg = project.getfirstconfig(prj) _p('SOURCES += \\') cs.listsources(prj, function(node) local fcfg = fileconfig.getconfig(node, cfg) local info = toolset.fileinfo(fcfg) if info.action == "Compile" then return node.relpath end end) _p('') end function gmake2.csTargetRules(prj, toolset) _p('$(TARGET): $(SOURCES) $(EMBEDFILES) $(DEPENDS) $(RESPONSE) | $(TARGETDIR)') _p('\t$(PRELINKCMDS)') _p('\t$(SILENT) $(CSC) /nologo /out:$@ $(FLAGS) $(REFERENCES) @$(RESPONSE) $(patsubst %%,/resource:%%,$(EMBEDFILES))') _p('\t$(POSTBUILDCMDS)') _p('') end function gmake2.csTools(cfg, toolset) _p(' CSC = %s', toolset.gettoolname(cfg, "csc")) _p(' RESGEN = %s', toolset.gettoolname(cfg, "resgen")) end local p = premake local 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 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 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 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 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.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 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 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 android = p.modules.android local vsandroid = p.modules.vsandroid local vc2010 = p.vstudio.vc2010 local vstudio = p.vstudio local project = p.project premake.override(vstudio.vs2010, "generateProject", function(oldfn, prj) if prj.kind == p.PACKAGING then p.eol("\r\n") p.indent(" ") p.escaper(vstudio.vs2010.esc) if project.iscpp(prj) then p.generate(prj, ".androidproj", vc2010.generate) local user = p.capture(function() vc2010.generateUser(prj) end) if #user > 0 then p.generate(prj, ".androidproj.user", function() p.outln(user) end) end end else oldfn(prj) end end) premake.override(vstudio, "projectfile", function(oldfn, prj) if prj.kind == p.PACKAGING then return premake.filename(prj, ".androidproj") else return oldfn(prj) end end) premake.override(vstudio, "tool", function(oldfn, prj) if prj.kind == p.PACKAGING then return "39E2626F-3545-4960-A6E8-258AD8476CE5" else return oldfn(prj) end end) premake.override(vc2010.elements, "globals", function (oldfn, cfg) local elements = oldfn(cfg) if cfg.kind == premake.PACKAGING then local pos = table.indexof(elements, vc2010.ignoreWarnDuplicateFilename) table.remove(elements, pos) elements = table.join(elements, { android.projectVersion }) end return elements end) function android.projectVersion(cfg) _p(2, "%s", cfg.project.name) _p(2, "14.0") _p(2, "1.0") end premake.override(vc2010.elements, "configurationProperties", function(oldfn, cfg) local elements = oldfn(cfg) if cfg.kind == p.PACKAGING then elements = { android.androidAPILevel, vc2010.useDebugLibraries, } end return elements end) premake.override(vc2010.elements, "itemDefinitionGroup", function(oldfn, cfg) local elements = oldfn(cfg) if cfg.kind == p.PACKAGING then elements = { android.antPackage, } end return elements end) premake.override(vc2010, "importDefaultProps", function(oldfn, prj) if prj.kind == p.PACKAGING then p.w('') else oldfn(prj) end end) premake.override(vc2010, "importLanguageSettings", function(oldfn, prj) if prj.kind == p.PACKAGING then p.w('') else oldfn(prj) end end) premake.override(vc2010, "propertySheets", function(oldfn, cfg) if cfg.kind ~= p.PACKAGING then oldfn(cfg) end end) premake.override(vc2010.elements, "outputProperties", function(oldfn, cfg) if cfg.kind == p.PACKAGING then return { android.outDir, vc2010.intDir, vc2010.targetName, } else return oldfn(cfg) end end) function android.outDir(cfg) vc2010.element("OutDir", nil, "%s\\", cfg.buildtarget.directory) end premake.override(vc2010, "importLanguageTargets", function(oldfn, prj) if prj.kind == p.PACKAGING then p.w('') else oldfn(prj) end end) function android.link(cfg, file) local fname = path.translate(file.relpath, '/') local link, count = fname:gsub("%.%.%/", "") local external = (count > 0) or fname:find(':', 1, true) or (file.vpath and file.vpath ~= file.relpath) if external and file.vpath ~= file.relpath then link = file.vpath end if external then vc2010.element("Link", nil, path.translate(link)) end end vc2010.categories.AndroidManifest = { name = "AndroidManifest", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "AndroidManifest", {vc2010.generatedFile, android.link, android.manifestSubType}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "AndroidManifest") end } function android.manifestSubType(cfg, file) vc2010.element("SubType", nil, "Designer") end vc2010.categories.AntBuildXml = { name = "AntBuildXml", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "AntBuildXml", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "AntBuildXml") end } vc2010.categories.AntProjectPropertiesFile = { name = "AntProjectPropertiesFile", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "AntProjectPropertiesFile", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "AntProjectPropertiesFile") end } vc2010.categories.JavaCompile = { name = "JavaCompile", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "JavaCompile", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "JavaCompile") end } vc2010.categories.Content = { name = "Content", priority = 99, emitFiles = function(prj, group) vc2010.emitFiles(prj, group, "Content", {vc2010.generatedFile, android.link}) end, emitFilter = function(prj, group) vc2010.filterGroup(prj, group, "Content") end } premake.override(vc2010, "categorizeFile", function(base, prj, file) if prj.kind ~= p.PACKAGING then return base(prj, file) end local filename = path.getname(file.name):lower() local extension = path.getextension(filename) if filename == "androidmanifest.xml" then return vc2010.categories.AndroidManifest elseif filename == "build.xml" then return vc2010.categories.AntBuildXml elseif filename == "project.properties" then return vc2010.categories.AntProjectPropertiesFile elseif extension == ".java" then return vc2010.categories.JavaCompile else return vc2010.categories.Content end end) local p = premake local 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 p.modules.d = {} local m = p.modules.d m._VERSION = p._VERSION m.elements = {} local api = p.api function p.project.isd(prj) return prj.language == p.D end function path.isdfile(fname) return path.hasextension(fname, { ".d" }) end function path.isdheader(fname) return path.hasextension(fname, { ".di" }) end include( "tools/dmd.lua" ) include( "tools/gdc.lua" ) include( "tools/ldc.lua" ) include( "actions/gmake.lua" ) include( "actions/vcxproj.lua" ) include( "actions/visuald.lua" ) return m local p = premake local 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 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 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 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.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 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 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.raw = {} local m = p.modules.raw m.elements = {} dofile("_preload.lua") dofile("raw_action.lua") return m local p = premake p.raw = { } local raw = p.raw local gvisited = { } function raw.workspace(wks) if not gvisited[wks.global] then gvisited[wks.global] = true raw.printTable({ global = wks.global }) end end function raw.printTable(t, i) i = i or 0 placement = raw._createPlacement(t) raw._printTableRecursive(t, i, placement) end function raw._printTableRecursive(t, i, placement) elements = { } for k, v in pairs(t) do table.insert(elements, { key = k, value = v }) end table.sort(elements, function(a, b) local n1 = type(a.key) == "number" local n2 = type(b.key) == "number" if n1 ~= n2 then return n1 end local k1 = n1 and a.key or raw._encode(a.key) local k2 = n2 and b.key or raw._encode(b.key) return k1 < k2 end) for _, elem in ipairs(elements) do p = placement[elem.value] if p and elem.key == p.key and t == p.parent then _p(i, "%s", raw._encode(elem.key) .. ': ' .. raw._encode(elem.value) .. ' {') raw._printTableRecursive(elem.value, i + 1, placement) _p(i, '} # ' .. raw._encode(elem.key)) else _p(i, "%s", raw._encode(elem.key) .. ': ' .. raw._encode(elem.value)) end end end function raw._createPlacement(tbl) placement = { } placementList = { tbl } while #placementList ~= 0 do parentList = { } for _, parent in ipairs(placementList) do for k, v in pairs(parent) do if type(v) == "table" and not placement[v] then table.insert(parentList, v) placement[v] = { parent = parent, key = k } end end end placementList = parentList end return placement end function raw._encode(v) if type(v) == "string" then return '"' .. v .. '"' else return tostring(v) end end local 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 return { "base/_foundation.lua", "base/string.lua", "base/table.lua", "base/path.lua", "base/os.lua", "base/io.lua", "base/tools.lua", "base/tree.lua", "base/globals.lua", "base/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", } return {"gmake", "vstudio", "xcode", "codelite", "gmake2", "d", "android"}#EgܺvT2  $LuaVersion: Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio $$LuaAuthors: R. Ierusalimschy, L. H. de Figueiredo, W. Celes $p@P?  -DT! @cܥL@@9RFߑ?>`qATPP\l<?@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      deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler      `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  @ inflate 1.2.8 Copyright 1995-2013 Mark Adler  #+3;CScsHN !1Aa  0@`@@   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#c             (08@P`p  0@`  0@`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_????????????????KGS!@#$%6\@$@ %GMTUTCWETBSTWAT<ASTADTEST,EDTCSThCDT,MSTMDThPSTPDTYSTYDTHSTXHDTCATXAHSTXNTIDLWCETMETMEWTMESTCESTMESZFWTFSTEETWAST\WADT CCT JSTEASTEADTlGSTNZT0NZST0NZDTIDLE0A<BxCDE,FhGHIKXLMNOPLQRST\U VWXlY0Z;Zx0N@@* < > { } { } .A<<44X!a 0LLL Wh  P` p P""***+,,0`334 677@88990::;<==>?@ABB`CCDpGPHHI`IIJJ0NN@RRRRS WPXXX0Y]0^^^p__`ddPeee`fpff`iiPj klnnq0yzpЄ@Ѝ`PPpP` 0P ``@ @0`  pP` @ p`0P0@Pp P` P    @`"P""@#p#$ %&&&`(( *.0 0`01p22P66@778p9BCDD EpFF0H`L@MMPOOP0QP[@\p_ `@aapcpdpgqr`rst`tuuwwwwy{{`0pp``00P0`0pН@` 0`PPPpP0 @`Pp0@@0 pP    `p HHJKLMMPMRSPSSVW`\ ] ^_``bb0cce0gh h`qr0x`x0y@y {{}0@@`0@0 P`P  @0`@ppp `P@P,,,=>??@NOP QQRYY^__`@abbb`ccdd0e`eeef0fg0hjknnnpor0sstu vvwww@xx zpЉ0@`0P  0`Ъp p`P ` 033444p77P99A0DEGb@chil0l0npnnno@rss t@tuu@y00`` p@P7780;>OPT@VX@Z\^_acc0fghiPiw@xpЊ0pД`Зp00УPЫp P0PpP0@`p  !p!; >>`BCD`FFGPKLLTUY0Z__`yP{{P|`P P`Ы`P`PpPлм@ P`@pp `0P@@P P0!`y`||}p~pp@@P@P@@p  @p1FZ@c@ks9z`А@@0@n`o p`t z{ uu'u:|NvYz^{e |l|s}~p@ p00r0к !)28PEpR CVD[0Ad & p7: M ` _  /o !  $  & \ 2 : 06   P  S p p  !` !! 3!` F! \!  q! ! !p G ! !  !* c?! j "m "`u +" v e@" T" H l"  ~" '"  " + " " " +"H #0^ #Pd .#s .B#@s _#t iu# # # 0# # #P #` $ .$P )9L$ _$ o$ .$" $4 $: $> ^ $J ]$@Q %`  6%m Q%r >k%  % <%% % b%p g%.%P5&PO<-&@K G&Ef& &E&@ &Pv(&& '`)'s H'!i' ','/'3'<'@ 'D9(H9( M((R{:(pghCP(Gi(0(Ps(X (0\([(6)-{)`0=)2,_)G n)Sv)U)r-)`#)@b))) %)P*$*+H(*/JJ*R*Z*b*j*r*z**********+`++++,,0,,`",(,P., 7,p>,E, L,S, `,)0 i,` n, 2+,,,,,,,,*.81.88.p9@.9G.:L.:R. ; =.>.>.P@.D.0F+PF.F.G/ H/H/H$/KS,L-/L8/pM-2`4s/,x/2`22`2=`33L` 3i,02220L3 31@33?433s/&4*4043484?4C4DG4L4O491R4V4Y4`4g4l4r4x49{4~44444444446`6 66 6p66  6P$6.646P960=6pA60E6I6N6PR6Y6d6h6m60i,`5555#8p+88768 8099999999999: ::::::":&:+:0:4:9:=:A:E:J:N:R:Y:]:`:c:f:k:s:x:::::::::::p#:#:&:'`':':(:P(:(;) ;+;;;;<;>@{>p|>`}>@~>P~?@ ?`?H`?p?P"? &?,?1?:?CC,?:?:CCPDD3DA2D3E EEE1"E)E/E4E:E@EFELEREXE_EfElEsEyEEEEEEEFF> ?FF HHHIII*I4IVIcIwIIIIIIIJJ֢+JDJVJmJJJJ      LLpLLLLMMpEvJvTvYvdvYvjvovzvvvvxPxyyyGāI!˚566\@566\% "&*.26:>BFJ (>jח)<]:nƙy9yj˚ٚyyOtΛyDypyy0^zʝy;]՞ 7ޟ!6MnΠ*RAy`ʡP ¢˚֢  ?Tk˚ث ^!(2<FPZ&0:DNXblv $.8BLV`jt~ dnx   " , 6 @ J T ^ h r |                 & 0 : D N X b l v                  * 4 > H R \ f p z                 $ . 8 B L V ` j t ~                 ( 2 < F P Z d n x              ",6@JT^hr|mPs@j0Pp0Pp0P0pP p0P0Pp@@Ppp`@@` P@0@ 0wprpw P@p@OpRO Q0PNO O0Oi_` aI0SRT`TT@UISS OOO`P@MQMpNYZi^@_ph`0fPc`d0FdYUWWX@XXYaapepjijpk5`"p RBVBRB`B`:BXBZBTBVBRBRARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARARE`=ApXB^B` BUA`B`BSASA`%A`/ApppUApRB`/A`BVB`"B^B[A`#C`A `App0TARARF]CSCpWA`y0xRCQ#`A`BRBRCpHpp Q@_kSecAttrLabelQr@_kSecClass@_kSecClassIdentity@_kSecImportExportPassphrase@_kSecImportItemIdentity@_kSecMatchLimit@_kSecMatchLimitAll@_kSecMatchPolicy@_kSecReturnRef@__DefaultRuneLocale@___stack_chk_guard@___stderrp@___stdinp@___stdoutp@_callocs@_fputcr0@_fread@_frees@_fwriterH@_mallocs@_reallocrs@_strduprs@dyld_stub_binderr@___CFConstantStringClassReferenceO@_kCFAllocatorDefaultЯ@_kCFAllocatorNull@_kCFBooleanTrue@_kCFCopyStringDictionaryKeyCallBacks@_kCFTypeArrayCallBacks@_kCFTypeDictionaryValueCallBackss@_CCCrypts@_CC_MD4s@_CC_MD5s@_CC_MD5_Finals @_CC_MD5_Inits(@_CC_MD5_Updates0@_CFArrayAppendValues8@_CFArrayCreates@@_CFArrayCreateMutablesH@_CFArrayGetCountsP@_CFArrayGetValueAtIndexsX@_CFBundleCopyExecutableURLs`@_CFBundleGetMainBundlesh@_CFDataCreatesp@_CFDictionaryCreatesx@_CFDictionaryGetTypeIDs@_CFDictionaryGetValues@_CFDictionaryGetValueIfPresents@_CFGetTypeIDs@_CFPropertyListCreateWithStreams@_CFPropertyListIsValids@_CFReadStreamCloses@_CFReadStreamCreateWithFiles@_CFReadStreamOpens@_CFReleases@_CFRetains@_CFStringCompares@_CFStringCreateWithCStrings@_CFStringCreateWithCStringNoCopys@_CFStringGetCStrings@_CFURLCopyFileSystemPaths@_CFURLCreateDataAndPropertiesFromResources@_CFURLCreateFromFileSystemRepresentations@_CFURLCreateWithFileSystemPaths@_SSLCloses@_SSLCopyPeerTrusts@_SSLCreateContexts@_SSLGetBufferedReadSizes@_SSLGetNegotiatedCiphers@_SSLGetNegotiatedProtocolVersions@_SSLGetNumberSupportedCipherss@_SSLGetSessionStates@_SSLGetSupportedCipherss@_SSLHandshakes@_SSLReads@_SSLSetCertificates@_SSLSetConnections@_SSLSetEnabledCipherss@_SSLSetIOFuncss@_SSLSetPeerDomainNames@_SSLSetPeerIDs@_SSLSetProtocolVersionMaxs@_SSLSetProtocolVersionMins@_SSLSetSessionOptions@_SSLWrites@_SecCertificateCopyCommonNames@_SecCertificateCopyLongDescriptions@_SecCertificateCreateWithDatas@_SecIdentityCopyCertificates@_SecItemCopyMatchings@_SecPKCS12Imports@_SecPolicyCreateSSLs@_SecTrustEvaluates@_SecTrustGetCertificateAtIndexs@_SecTrustGetCertificateCounts@_SecTrustSetAnchorCertificatess@_SecTrustSetAnchorCertificatesOnlys@____chkstk_darwins@___bzeros@___darwin_check_fd_set_overflows@___errors@___maskrunes@___memcpy_chks@___sprintf_chks@___srgets@___stack_chk_fails@___strcat_chks@___strcpy_chks@___strncpy_chks@___tolowers@___touppers@__longjmps@__setjmps@_aborts@_accesss@_acoss@_add_historys@_alarms@_arc4randoms@_asins@_atan2s@_atexits@_atois@_basenames@_binds@_callocs@_chdirs@_chmods@_clearerrs@_clocks@_closes@_closedirs@_connects@_connectxs@_coss@_difftimes@_dlcloses@_dlerrors@_dlopens@_dlsyms@_exits@_exps@_fcloses@_fcntls@_fdopens@_feofs@_ferrors@_fflushs@_fgetss@_filenos@_flockfiles@_fmods@_fnmatchs@_fopens@_fprintfs@_fputss@_freads@_frees@_freeaddrinfos@_freopens@_frexps@_fseeks@_fseekos@_fstat$INODE64s@_ftells@_ftellos@_funlockfiles@_fwrites@_getaddrinfos@_getcs@_getcwds@_getenvs@_geteuids@_gethostnames @_getpasss @_getpeernames @_getpids @_getpwuids @_getsocknames @_getsockopts @_gettimeofdays @_gmtime_rs @_inet_ptons @_ioctls @_isattys @_localeconvs @_localtimes @_localtime_rs @_logs @_log10s @_log2s @_lstat$INODE64s @_mallocs @_memchrs @_memcmps @_memcpys @_memmoves @_memsets @_mkdirs @_mkstemps @_mktimes @_opens @_opendir$INODE64s @_pcloses @_polls @_popens @_pows @_printfs @_putcs @_qsorts @_randoms @_reads @_readdir$INODE64s @_readlines @_reallocs @_realpath$DARWIN_EXTSNs @_recvs @_removes @_renames @_rmdirs @_sends @_setlocales @_setsockopts @_setvbufs @_sigactions @_siglongjmps @_signals @_sigsetjmps @_sins @_snprintfs @_sockets @_sprintfs @_srandoms @_sscanfs @_stat$INODE64s @_strcasecmps @_strcats @_strchrs @_strcmps @_strcolls @_strcpys @_strdups @_strerrors @_strerror_rs @_strftimes @_strlens @_strncasecmps @_strncmps @_strncpys @_strpbrks @_strrchrs @_strspns @_strstrs @_strtods@_strtoks@_strtok_rs@_strtols@_strtouls@_symlinks@_sysctls@_systems@_tans@_times@_tmpfiles@_truncates@_umasks@_ungetcs@_vsnprintfs@_write__bucluadhttp_o pmainregisterModulessterm_zadler32Hget_crc_tableHinflateJCurl_Nmh_execute_headerzip_;tr_Mdist_codeϏlength_codeՏfferiltin_scriptsۏ_ed_initdestroyp,,utsrintf-.newwriteclosetostring12ln377rurlanUseColorsiteria_c32Hcompiledeletematches8>?ProgressCallbackWriteCallbackRequestCleanup_bx_yJKKY_L_open_$K_%G_*D_+U_-F_-C_/X_0M_1O_2Y_parser3E_3S_4H_6T_7V_9Z_:i_ctype_P_opmaincxmoveaversiongsrptil#dump#error#ne#upvalue$yieldk-Zeo_ bug_promptflateIrdownloadgetposttcaewherefileresultnew set op p buffinit re unref l g racebackestudata olstring heckallmeta stackudata option lstring type any number integer version_ rgerrordd rrorxecresultmetatable state metatable funcs Уt enlibs0lstring number integer ЧЩrepbuffsize ushresult lstring string value size бsize f quiref gisterriginal_luaL_loadfilex s_ oad en bufferx string filex et sub metafield subtable  chdir getislocatemkdirpathabsolutetypenormalizetranslatehash cgethostislmpathsearchrstattouchfileuuidwritefile_ifnotequalhodirmodmppyfilearefilesileWindowsRegistrycwdpassversioncwdabsolute64bitdirfilelinkfileabsoluteistWindowsRegistryocateatchkdirstartdonenisfileameextЂsearch_has_deferred_joinealpathmdirath_r getisabsoluteabsolutetypejoindeferred_joinhas_deferred_joinresolve_deferred_joinnormalizetranslatewildcardsabsoluterelativeС_singleinternalemake_intLastErrorinitpcallexecutelotest_filefind_embedded_scriptgetEmbeddedResourcecate_executablead_embedded_scripttring_ha1_cripts_pathendswithhashsinitrhashBlockaddUncountedwritepadol32esultbyteha1tartswithdogetTextColorsetTextColorGetTextColorSetTextColorЀip_libMErrorNcN_errmsgeclose;discard?fBget_CopenDarchive_set_tempdirDsDxtractrror_get_sys_typeAheckstackoreatetable"allk#lose4ЊtpanicbsindexrithЌetc# tglobal"field"i"metatable"u"allocf$hook)stack*local*opable"ett tglobal"field"i"metatable#u#allocf$hook)local*opable"otateawesume-pymparencat$ushcallk# vn!integer!l!string!fstring!cclosure!boolean!thread!aluefstring!ypeo namesdentcfunctionintegernumberstringuserdatayieldable-Жequallen get"set"Мringtonumber atus#numberx integerx boolean lstring cfunction!userdata!thread!pointer!ФЧбil!umber!дstring!ightuserdata!екnfo*i"p"servalue"pvalue$i#p#servalue#pvalue$oad#en$xt#w$userdata$thread4state4id$join$ base%coroutine)debug)io0math1package2os3string6table7utf88 nil&c&jump&re&g&p's'in'dischargevars(exp2(fixline)o&heckstack'de&ncat&AB&k'C&x&Кt&serveregs'etlabel&oif)Мatch'refix)osfix)tohere'list'close't'e(ringK'orevar)tK(dexed)fix)t(lf)returns(oneret(list)Ыnextreg(anyreg(val)RK)up)true)false)mask*count*t*runerror+concaterror+o+addinfo+errormsg+ypeerror+ointerror+raceexec+еpinterror+rdererror+жthrow,r,growstack,shrinkstack,inctop,hook,p,call-awrunprotected,eallocstack,oscall,r-call-ecall-otectedparser-noyield-dump-undump8new.initupvals.f.close.getlocalname/Cclosure.Lclosure.proto.indupval.reeproto.barrier/upv/f0newobj0checkfinalizer0runtilstate0step0_/back_/albarrier_0deccount0Кix0reeallobjects0ullgc0init1token2str1s1ne1lookahead1yntaxerror1etinput1wstring1xt1growaux_2realloc_2toobig2 int2fb2fb2int3c3arith3hexavalue3str2num3utf8esc3tostring3push3nilobject_eillog23hunkid3ЦЭvfstring3fstring3s4extendCI4free4etdebt4hrinkCI4  CI4thread4      eqlngstr5hash5re5c5init5new5  longstr5 size5move6 learcache5reatelngstrobj5  lstr56    udata6  ne6resize6set6free7get7xt6w7  array6int66    key7Ѝ  int7s77К hortstr7tr7   n7  init8gettm8objtypename8call8t8  byobj8  TM8binTM8orderTM8  rybinTM8ypenames_    to9finish9less:e:concat:objlen:div:mod:shiftl:number_9integer9  get9set:Op:  than:equal:Ђ  qualobj:xecute:        fill;init;read; Ѕ  m;c;dirent_poke>u>g?e@fileCneDopenDsFkstemp;emdupD  hangedsize>torrent_normalize> 8=2=4=     inalize=ree=  eds_zip64>w>   2>4>_>8>  data>local_efB    8>4? 2d_time?nchange_dataH et_?uess_encodingHdirent?compression_implementationDencryption_implementationDnameD   ntry_@rr@f_Afinalize@init@  or_@_c@fini@getAinitAsetAlear@opy@      _from_sourceA  cloneBnewBfreeBdelete_by_idBget_by_idBmergeBparseBremove_internalBsizeBwriteB    closeCile_get_external_attributesCopen_indexCreadC_get_offsetCrange_crcC_encryptedCИarchive_flagCnDameDum_entriesDwDrr_strРet_archive_commentEource_Etat_inG bufferEcEdeflateFerrorFfFlayeredFopenFpGreadGstatGwindowGloseErcEilepFreeFunctionFource_Ftring_Gfile_or_pFnewFzip_newGkwareGopGdexGitGcrc32HequalHfreeHgetHlengthHnewHwriteHЁ_combineH64H_combineHР64IЧInitIEndIResetISetIPJJ_I2_IKeepIDictionaryIHeaderIendingJrimeJaramsJTuneJBoundJCopyJ_copyrightÏ_KResetKInitKPrimeKKfastKtableMcopyrightɏKeepKKз2K2_K_KEndLGetLSLCopyLUndermineLMarkMDictionaryLHeaderLetDictionaryLyncLPointLЛinitMstored_blockMflush_bMalignMtallyMitsMlockMVersionNCompileFlagsNallocNfreeNbOcPtRpRuSiSgTsUfWhXaYdZrZw\m\n]FormfHMAC_iljooMD5_rexpireuSOCKSverDIGEST_MD5ase64Olockread_all_Ourl_encodePdecodePencodeP oPlTache_addrjhmmallocfreereallocstrdupcallocnnQokie_Vpy_header_valuemmpareheaderocQectTaliveU_data_pendingVache_QontrolVinitQdestroyRfRadd_connRremove_connRind_RoreachRbundleRfirst_connectionRimeleftRcpnodelayTvlongersistconninfoSriivarsenetrcygrs|o~pdateconninfoSnix2addrYrldecodees_connectedSpXngfqoTient_seTne_primary_ssl_configsocketTбhostTed_proxyetUlobal_host_cache_imtimezconnectinfoUaddrinfoXhostname\formdatafinfogoff_all_pipelines ocketVtrYekhare_̀list_pفafeтingle_getsocksl__check~lVinitWaddWcleaWgetlistWfreelistWoadfilesWistWnupWrWallWsessWlush_cookiesXreeXileofetch_addrjailfaddrinfoXset_М_exXke2aiXmac_md5^agostcache_jttpl2addrYvk2addrY_key_compareicasecompare˂nerrorރЩddYuth_`ck_eintrƐrinfo_set_portY_neZarwinssl_^ipupsetoing_getsock̆s_set_odd_parityZdotdotifybbug~eZa~ad[solvjcv{try_requestmoveHandleFromPipeline16_[32_[64_[_plainle[be[le[be\le[be\аrite\ait_ms~ildcard_܎kday16_le\32_le\64_le\e]k_dnscachejd5itrulti_tozm]ets_timeconditionrchr]duptlm_core_]um_addressesilm_resp]mk_]lm^nt^_hash^v2_resp^_hash^lmv2_^hash^resp^c_s_version`data_pending`random`md5sum`false_start`onnect_lose_heck_cxn`_nonblocking__hutdown_ession_free`d`is_acreate_antlm_cleanupzbuild_spnuser_contains_domainigest_aecode_bget_pairacleanupbdigest_supportedantlm_supportedydigest_antlm_typeymd5_messagebhttp_messagebdigest_http_messagebntlm_type2_messageygcecunescapeefemrsversionjmpenv̐lobal_cetginitccleanupc_memcasy_cscapee initdsdpdcleanupdgetinfodduphandledredescapeeunescapeeedtrerror̃toptdndeerformdauseesetecvereeeormfeinfo_elreadbufferallocedtoreaddfgetffreefrmfllowcleanfpostheaderfInitfReaderfenvgdatezitgput_oet_ntopqfof~infog_sh_gndler_httpinithaddhdehpickhcleanhsthnext_elementiletehstroyh_with_criteriumhrhart_iterateiinitiupdateifinaliMD5initidtoriintable_addressjopetransfer܄prunejcleanj_jtimeoutjunlockjoadhostpairsklist_q6kalidkworksk_scopeqtknd|_dns_kup_opt݅serverslinterfacellocal_ipl4l6l_lmsetup_connmdonemconnectmauth_actnoutput_authninput_authnreadwrite_headersontlm_cleanuppchunk_oeckmunked_strerroroheadersmProxyheadersmbufferncustom_headersotimeconditionohandle_to_pipelinez_nfooinitnfreensendoinitoreadoУdigestontlmputput_ppenׅldest_idle_connectiondigestpntlmpgest_cleanuppsconnectxyptocol__connectqCONNECTq_is_interface_nameq2ipqallocrinsert_nextrremoverdestroyrcountrmoverinitrupdaterfinalrvsssaprintfsprintfsfprintfsulti_tssaprintfsprintftfprintftnprintfsprintfsnprintfsprintfsЮhandletpucwadd_performwmax_xPipeBreakv inuauremove_handleufdsetvwaitwperformwcleanupwswtimeoutxitufo_readwdd_handleussignx_vrocess_pending_handlesvipelining_syclearvlatestxpeline_vn_peer_pubkeywantedvpenalizedzleave_zszcheckget_|onwlosedwhunk_length_penalty_sizeynchangedwtent_length_penalty_sizeyetoptxocketxtrerror҃_axctionxllxенhost_connectionsytotal_connectionsyпite_blyerver_blynonblockytvunjsʍ1_messagez3_messagezЀwritezread|ve_handle_from_send_to_recv_pipeznthite_blacklisted{e{t_s{rver_blacklisted{ite_blacklist{erver_blacklist{pipe_head{_~pipe_head|f_plainЋwrite|read|Done}Update}ResetTimesSizes}S}Time}LimitWaitTime}et}tartNow}Download}Upload}Size}Counter~Size}Counter~nd~w_toupperłll~sttransferhas_postponed_data~plainж_plainchop_writewriterewindwritehare_list_trinitscleanupƀetopttrerror؃lockunlockappend_nodupduplicateappendfree_all4́5ӁeedlayinitcheckЇЉinsertgetbestremovebyaddr_strcasecomparereallocƃЙcasecomparetoupperequalnequalnowdiffУ_secsCONNECTքuserdefinedхdotransferconnrequest_state˅primary_ssl_configЧboseconnectsion_initgetsockƆconnect҆doinging߆_infocbackendinitsgetskill_sessionՊdۊaddsessionidengines_listŋversionыfpush_certinforandommd5sumonlheck_cxn׋ert_status_requestfig_matchesnect҉sessionsˋ_certinfoeanup̉ose_nonblockingehutdownssionid_t_enginelockunlockessionidϊockelsessionidata_pending݋_all_defaultree_certinfoalse_start_lenltoތztoitousiscsuoizličltootouzztosiitouz֎siuis  usiЎsĎcʎ  Ѐ  initdtor  HHHmodesnamesHHtypestrHIIIIJJJJJJsJJJJJKKKKKKKK, 0@0`0 @00P0PP@Ppp@P 0``00P`@ @P p@ @ p`@pPP0ppp @@ @ 0 P`@ @@p@  0 p P0 `p0 0@ 0 PpPP`P`P`0P`P  P`@@0@`p @  PP0`00P@ @P``` P ```` p 0`p`P0 00@0@ @p  `pp`p@@`P```P`P<  `00P000P@00000` p` P0 PPPPp@@P`p"  `@0@Pp @@``@`` 0  P0@` p`Pp@pP0pP``0dP 0` 0@```0p P`p@0 0@@0@@p@p 0 @@``ppP`pP@p00@0 0`0 0@%@ pO`p000P    @ p p PP`  P@P0` P ` P@Px  @ P@@P000`ppp0 p ``@0 Pp 0`0`p@; 0 ` 0& 000`@`` @`40 00     P.p P 0 @00pp0 00@@` 000`pPP@@pP  @@@000 0@`00 @P 00Ѕ `P@p 00@@p@  074cz0pDxL(!(,04T70V8aPTș  048<@D|,O`X$8$h̻lXPT0 \AĢĨ 8T<LG@4< Q{HЍP\ M(p,L(dp(lh4(؂< P#P`$P.P8P ;P0=PP?Q@@ Q@QAQC*QPL>QPIQVTQ]aQ^gQ_mQhvQh}QkQPmQnQ tQwQQ@QPQQ`QRRR1R>R0MRXR`cRoRP{RR RpRR RR RR0 R` S Sp S *S :S GSRSXS0aSp%mS`,{Sp4S 6S8S8Sp9S9S:S:S ;SP; T0<T="T>3T>?TP@KTDXT0FhTPFyTFTGT HTHTHTKTLTLTpMT NUYU`^Uu"UPv*Uz4U}BUTU_U kUqU@|U`UUUUШU`UU`UU`UUV` VV0"V,V5Vp?VJVеWVP_VjV`vVVVV0VV VVVV@VVVVV0 WW`"W-W8W CWpNWXW bWPlWxWWPW0WpW0WWWPWWWWW0 X`XX#Xp/X>XKX@ WX iXp wX X X@XX Xp#X#X&X'X`'X'X(XP( Y(Y) Y+,Y@,:Y-DY`0PY1\Y03hY3sYD}Y FYGYpKYQY0TYXYp[Y\YP^Y^Y`YaZ@bZ0cZ@c-Zc6Z@fEZfQZo\ZriZ@{sZp|}Z`}Z@~ZP~ZZ@Z`ZZ`ZpZPZ ZZ[[Q`[pP*[p7[ H[жT[`[k[@v[`[0[[[[[[[[P[[[P[\p \\!\,\5\=\I\@S\Th\ u\pw\\С\\\\\д\й]`]$] 4]B]P]` _]@Hm]jy]t]py]`]]P]0]]0]^0+^@M;^MK^NW^pOd^Pz^`Q^j^^^^^`^_ _1_C_R_@f_{_`_ _5_6_6_7_Q_PT_`V_Z`\`b `pe.`0o=`xN```n``p```````` a a/a eJ f@Q %f` 8fm Kfr ^f qf f f fp f.fP5fPOf@ gg/gBg@UgPhg{gg`ggg g,g/h3h<&h@9hDLhH_h MrhRhpghh0hPhh0h ii-2i`0Fi2ZiGniSiUiri`i@iii jP"j6jJj+^j/rj0j 0j@0jd1jh1jt1j1j1j@3kp3k3k3-k 4Ak4Zk5qk5k8kXkXk`kpakakal0blpe'li5lpjBljOlpk]lkglktl`llll0mlnlnl nl`nlpnlq mq3mFmZmPkmp{m mmPmmm mmnВnPn`&n-nP3nEnZn0gn`pn znn@nn@n`n@nnPn@ o@o+o`6o xEo Oo \o lo ~o o o o o o Ho Po p #p Np vp p p p (p Xp \p `p pq 8&q @Dq  "`3BS@cu766 @  P0 "4Mj0f0T@D`j@eR T0p8@L@``wP` @ (p0P#B2NИ` n@5Jpfx@P,>`P@g 0 80 % AXopl  `.1;\H0b[Оo{@p'  . 5G PZ 1h z  `       +  8 K  _ n      ` Я   $ 0 ? U `k v 0    0    %  :  O &[ 0&v ' P %  5     0 p%  , : pM 2_  5q 04 3 05 3 @  6  ( 4]uu0uX0kП>``Pa@ /pNmГ`7`@7Tn@P@%?ZPs k'/&AYp@0@ `0%p5@EUPevp@p /.C ]@o@0: /1BUP%j `@  #:L j~0p + B0XppP0p3@D ]Px0@   .`@@Qp``m}0}pp ):K]pbipdw\\]W`ZxT0UU V T,@ fSPgig{fh@hhvvp] `|`~2 ~@S@b}o@~@ z {pp40{ P{`{+{;{L{\{x` yp  -C;`4JpTP_yk0xwooup@0p` " 4 E Y j } x @ e e  e  @ 0 P!0!@ !-!=!K!^!n!!@!`!0!P!!@!@!!,"0%"%+"%>"@tQ"0uf"yx"`t"p"w"@r"`x"@w"y"pq##|*#y7#E#T#pb#~m#{##pp#o#o# #S#PW#V# R$U$0Z4$G$[$@km$$Z$0v$]$$$К%%.%`B%`pS%Uc%pXs%@X%@7%X%%p%%%&&'&07&`|F&pT&g&w&`&&&&& && &&P'@'0#'`1'P?'@M'['pi'w'''9'''0''''' ( ()(;(Q(c(p(0X((n(0(u((({(|(P(p()))7) F)0AU) C_)Dj) s)M)`I)I)J)))O) )) *0*0J1*K>*MP*Ob*@au*0 *P**0* ****+++P3+E+qP+qb+er+`g}+f+ x+h+Pk+y+pc+c+f,b,@i,i+, m<,iJ,iY,e,u,,@,,,0,0,\,Z,\ -Z-[--X<-P[M-]]-0Xm-x--P--- --0--p-`-.p. ". 0.>.J. W.k. x.. .. .p5.P.p'.#.(/.//P (/ 2/C/S/`e/.r/ )/`/0/"/5/`//!//W0W0X"0I10Y@0YS0`b0Sq0T00S0T0Q0I0S0`P0i1K 1pN1M/1_B1`dT10f_1`i1^{1i1@_1 O1ph11@U1R1`T1U2@X#2X82YB2Q2d`2Pco2O2O2 a20F2Z2@M222@2P33!3+3;3`H31Y30!k3~333 3233u3x3ps3s4s40v#4`y-4v;4 zJ4yW4Ptd4q4`44p444 444{45 5 5+5@95pH5@X5h5`x5P5 5 5@5@555556@6p"626@.?6BJ6BU6B`6pn6y606 66Ps66P66666 6p 7`7)7O670OH7 OY7c7pRp7O~7@7@O7p777`7/7P78p80!818pwB8K80U8-_8mm8@j|8888P8@8p8P8p8p990-9=9M9\9@n9P|99@999@9099pr9099P ::N%:/: Q=:O: ]:i:0y:@::@: ::P::p:;0;p&;0;0>;M;P^;Pk;Pv;w;`0;;08;<;;; #;`;z<<#< )<[B<nL<`oV< pg<rs<`t<u< u<u<v<z<z<{<{< |<| =|=#=3=A=O=~^=ph=@w=== =0=p=0===`>А>*>;>@F>`Z>@l>|>@>0>@> >>??0?K?Z?m?Ъ}?? ?P? ??@???и? @@0'@к4@G@p\@q@P@p@@@ @0@0@E@y@0|AAA >A OA0jAPuAA0AAAAAA0B0B`,Bp>B`OBdBxBBPBB BBPBB0C~C~C(C0C8CFCSCbCvCCCCCCCDD/DEDdDqDDDDDDDDE*EKE_ExEEEEEFF0FHFiFFFFFFFFGG*G8GRGlGGGGGGHH,H@HRHqHHHHHII!IAIJIVIdIsI|IIIIIIIIIIJ JJJ$J*J7J>JJJPJWJ_JeJoJuJ}JJJJJJJJJJJJJJJJJK KKK K(K/K7KBKHKQKXKaKhKoKvK|KKKKKKKKKKKKKKKLLL+L3L=LJLVLdLnLyLLLLLLLLM+M6MIMeM}MMMMMMMMMMMN NNN%N.N6N=NFNNNTNeNmNsNzNNNNNNNNNNNNNNNO OO O+O7O?OJOOOYOaOjOsO{OOOOOOOOOOOOOOP PPP'P/P7P?PIPQPZPcPkPsPxP~PPPPPPP     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLOPQRSTUVW\]^_`abcdefghijklmnopqrstuvwxyz{|}~     MXYZ[o     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLOPQRSTUVW\]^_`abcdefghijklmnopqrstuvwxyz{|}~      _Curl_DIGEST_MD5_Curl_FormInit_Curl_FormReader_Curl_HMAC_MD5_Curl_HMAC_final_Curl_HMAC_init_Curl_HMAC_update_Curl_MD5_final_Curl_MD5_init_Curl_MD5_update_Curl_SOCKS4_Curl_SOCKS5_Curl_ack_eintr_Curl_add_buffer_Curl_add_buffer_free_Curl_add_buffer_init_Curl_add_buffer_send_Curl_add_bufferf_Curl_add_custom_headers_Curl_add_handle_to_pipeline_Curl_add_timecondition_Curl_addrinfo_set_port_Curl_auth_build_spn_Curl_auth_create_digest_http_message_Curl_auth_create_digest_md5_message_Curl_auth_create_ntlm_type1_message_Curl_auth_create_ntlm_type3_message_Curl_auth_decode_digest_http_message_Curl_auth_decode_ntlm_type2_message_Curl_auth_digest_cleanup_Curl_auth_digest_get_pair_Curl_auth_is_digest_supported_Curl_auth_is_ntlm_supported_Curl_auth_ntlm_cleanup_Curl_auth_user_contains_domain_Curl_base64_decode_Curl_base64_encode_Curl_base64url_encode_Curl_blockread_all_Curl_cache_addr_Curl_ccalloc_Curl_cfree_Curl_checkProxyheaders_Curl_checkheaders_Curl_chunked_strerror_Curl_client_chop_write_Curl_client_write_Curl_clone_primary_ssl_config_Curl_close_Curl_closesocket_Curl_cmalloc_Curl_compareheader_Curl_conn_data_pending_Curl_connalive_Curl_conncache_add_conn_Curl_conncache_destroy_Curl_conncache_find_bundle_Curl_conncache_find_first_connection_Curl_conncache_foreach_Curl_conncache_init_Curl_conncache_remove_conn_Curl_conncontrol_Curl_connect_Curl_connected_proxy_Curl_connecthost_Curl_cookie_add_Curl_cookie_cleanup_Curl_cookie_clearall_Curl_cookie_clearsess_Curl_cookie_freelist_Curl_cookie_getlist_Curl_cookie_init_Curl_cookie_list_Curl_cookie_loadfiles_Curl_copy_header_value_Curl_crealloc_Curl_cstrdup_Curl_darwinssl_check_cxn_Curl_darwinssl_close_Curl_darwinssl_connect_Curl_darwinssl_connect_nonblocking_Curl_darwinssl_data_pending_Curl_darwinssl_false_start_Curl_darwinssl_md5sum_Curl_darwinssl_random_Curl_darwinssl_session_free_Curl_darwinssl_shutdown_Curl_darwinssl_version_Curl_debug_Curl_dedotdotify_Curl_des_set_odd_parity_Curl_digest_cleanup_Curl_disconnect_Curl_doing_getsock_Curl_dupset_Curl_expire_Curl_expire_clear_Curl_expire_latest_Curl_failf_Curl_fetch_addr_Curl_fileinfo_alloc_Curl_fileinfo_dtor_Curl_fillreadbuffer_Curl_flush_cookies_Curl_follow_Curl_formclean_Curl_formpostheader_Curl_free_primary_ssl_config_Curl_free_request_state_Curl_freeaddrinfo_Curl_freeset_Curl_getaddrinfo_Curl_getaddrinfo_ex_Curl_getconnectinfo_Curl_getformdata_Curl_gethostname_Curl_getinfo_Curl_getoff_all_pipelines_Curl_global_host_cache_dtor_Curl_global_host_cache_init_Curl_gmtime_Curl_handler_http_Curl_handler_https_Curl_hash_add_Curl_hash_clean_Curl_hash_clean_with_criterium_Curl_hash_delete_Curl_hash_destroy_Curl_hash_init_Curl_hash_next_element_Curl_hash_pick_Curl_hash_start_iterate_Curl_hash_str_Curl_he2ai_Curl_hmac_md5_Curl_hostcache_clean_Curl_hostcache_prune_Curl_http_Curl_http_auth_act_Curl_http_connect_Curl_http_done_Curl_http_input_auth_Curl_http_ntlm_cleanup_Curl_http_output_auth_Curl_http_readwrite_headers_Curl_http_setup_conn_Curl_httpchunk_init_Curl_httpchunk_read_Curl_if2ip_Curl_if_is_interface_name_Curl_inet_ntop_Curl_infof_Curl_init_CONNECT_Curl_init_do_Curl_init_userdefined_Curl_initinfo_Curl_input_digest_Curl_input_ntlm_Curl_ip2addr_Curl_ipv6_scope_Curl_ipv6works_Curl_ipvalid_Curl_is_connected_Curl_llist_alloc_Curl_llist_count_Curl_llist_destroy_Curl_llist_insert_next_Curl_llist_move_Curl_llist_remove_Curl_loadhostpairs_Curl_md5it_Curl_meets_timecondition_Curl_memdup_Curl_memrchr_Curl_mk_dnscache_Curl_month_Curl_move_handle_from_send_to_recv_pipe_Curl_multi_add_perform_Curl_multi_chunk_length_penalty_size_Curl_multi_closed_Curl_multi_connchanged_Curl_multi_content_length_penalty_size_Curl_multi_handle_Curl_multi_handlePipeBreak_Curl_multi_max_host_connections_Curl_multi_max_total_connections_Curl_multi_pipelining_server_bl_Curl_multi_pipelining_site_bl_Curl_multi_process_pending_handles_Curl_ntlm_core_lm_resp_Curl_ntlm_core_mk_lm_hash_Curl_ntlm_core_mk_lmv2_resp_Curl_ntlm_core_mk_nt_hash_Curl_ntlm_core_mk_ntlmv2_hash_Curl_ntlm_core_mk_ntlmv2_resp_Curl_num_addresses_Curl_oldest_idle_connection_Curl_open_Curl_output_digest_Curl_output_ntlm_Curl_parsenetrc_Curl_persistconninfo_Curl_pgrsDone_Curl_pgrsLimitWaitTime_Curl_pgrsResetTimesSizes_Curl_pgrsSetDownloadCounter_Curl_pgrsSetDownloadSize_Curl_pgrsSetUploadCounter_Curl_pgrsSetUploadSize_Curl_pgrsStartNow_Curl_pgrsTime_Curl_pgrsUpdate_Curl_pin_peer_pubkey_Curl_pipeline_checkget_read_Curl_pipeline_checkget_write_Curl_pipeline_leave_read_Curl_pipeline_leave_write_Curl_pipeline_penalized_Curl_pipeline_server_blacklisted_Curl_pipeline_set_server_blacklist_Curl_pipeline_set_site_blacklist_Curl_pipeline_site_blacklisted_Curl_pipeline_wanted_Curl_poll_Curl_posttransfer_Curl_pretransfer_Curl_printable_address_Curl_protocol_connect_Curl_protocol_connecting_Curl_protocol_doing_Curl_protocol_getsock_Curl_proxyCONNECT_Curl_proxy_connect_Curl_rand_Curl_raw_toupper_Curl_read_Curl_read16_be_Curl_read16_le_Curl_read32_be_Curl_read32_le_Curl_read64_be_Curl_read64_le_Curl_read_plain_Curl_readrewind_Curl_readwrite_Curl_recv_has_postponed_data_Curl_recv_plain_Curl_recvpipe_head_Curl_removeHandleFromPipeline_Curl_resolv_Curl_resolv_timeout_Curl_resolv_unlock_Curl_retry_request_Curl_safe_strcasecompare_Curl_saferealloc_Curl_send_plain_Curl_sendf_Curl_sendpipe_head_Curl_set_dns_interface_Curl_set_dns_local_ip4_Curl_set_dns_local_ip6_Curl_set_dns_servers_Curl_setopt_Curl_setup_conn_Curl_setup_transfer_Curl_share_lock_Curl_share_unlock_Curl_single_getsock_Curl_slist_append_nodup_Curl_slist_duplicate_Curl_socket_Curl_socket_check_Curl_speedcheck_Curl_speedinit_Curl_splay_Curl_splaygetbest_Curl_splayinsert_Curl_splayremovebyaddr_Curl_ssl_addsessionid_Curl_ssl_backend_Curl_ssl_cert_status_request_Curl_ssl_check_cxn_Curl_ssl_cleanup_Curl_ssl_close_Curl_ssl_close_all_Curl_ssl_config_matches_Curl_ssl_connect_Curl_ssl_connect_nonblocking_Curl_ssl_data_pending_Curl_ssl_delsessionid_Curl_ssl_engines_list_Curl_ssl_false_start_Curl_ssl_free_certinfo_Curl_ssl_getsessionid_Curl_ssl_getsock_Curl_ssl_init_Curl_ssl_init_certinfo_Curl_ssl_initsessions_Curl_ssl_kill_session_Curl_ssl_md5sum_Curl_ssl_push_certinfo_Curl_ssl_push_certinfo_len_Curl_ssl_random_Curl_ssl_sessionid_lock_Curl_ssl_sessionid_unlock_Curl_ssl_set_engine_Curl_ssl_set_engine_default_Curl_ssl_shutdown_Curl_ssl_version_Curl_str2addr_Curl_str_key_compare_Curl_strcasecompare_Curl_strerror_Curl_strncasecompare_Curl_strntoupper_Curl_tcpnodelay_Curl_timeleft_Curl_tvlong_Curl_unix2addr_Curl_updateconninfo_Curl_urldecode_Curl_verboseconnect_Curl_version_init_Curl_wait_ms_Curl_wildcard_dtor_Curl_wildcard_init_Curl_wkday_Curl_write_Curl_write16_le_Curl_write32_le_Curl_write64_le_Curl_write_plain__dist_code__length_code__mh_execute_header__tr_align__tr_flush_bits__tr_flush_block__tr_init__tr_stored_block__tr_tally__zip_cdir_free__zip_cdir_grow__zip_cdir_new__zip_cdir_write__zip_changed__zip_cp437_to_utf8__zip_dirent_clone__zip_dirent_finalize__zip_dirent_free__zip_dirent_init__zip_dirent_needs_zip64__zip_dirent_new__zip_dirent_read__zip_dirent_size__zip_dirent_torrent_normalize__zip_dirent_write__zip_ef_clone__zip_ef_delete_by_id__zip_ef_free__zip_ef_get_by_id__zip_ef_merge__zip_ef_new__zip_ef_parse__zip_ef_remove_internal__zip_ef_size__zip_ef_write__zip_entry_finalize__zip_entry_init__zip_err_str__zip_err_type__zip_error_clear__zip_error_copy__zip_error_fini__zip_error_get__zip_error_init__zip_error_set__zip_error_set_from_source__zip_file_get_offset__zip_filerange_crc__zip_get_compression_implementation__zip_get_dirent__zip_get_encryption_implementation__zip_get_name__zip_guess_encoding__zip_memdup__zip_mkstemp__zip_nerr_str__zip_new__zip_open__zip_poke4__zip_poke8__zip_read2__zip_read4__zip_read8__zip_read_data__zip_read_local_ef__zip_source_file_or_p__zip_source_new__zip_source_zip_new__zip_string_crc32__zip_string_equal__zip_string_free__zip_string_get__zip_string_length__zip_string_new__zip_string_write__zip_u2d_time__zip_unchange_data__zip_write2__zip_write4__zip_write8_adler32_adler32_combine_adler32_combine64_buffer_destroy_buffer_init_buffer_printf_buffer_puts_buffered_close_buffered_new_buffered_tostring_buffered_write_buffered_writeln_builtin_scripts_canUseColors_crc32_crc32_combine_crc32_combine64_criteria_compile_criteria_delete_criteria_matches_curlCleanup_curlProgressCallback_curlRequest_curlWriteCallback_curl_easy_cleanup_curl_easy_duphandle_curl_easy_escape_curl_easy_getinfo_curl_easy_init_curl_easy_pause_curl_easy_perform_curl_easy_recv_curl_easy_reset_curl_easy_send_curl_easy_setopt_curl_easy_strerror_curl_easy_unescape_curl_escape_curl_formadd_curl_formfree_curl_formget_curl_free_curl_getdate_curl_getenv_curl_global_cleanup_curl_global_init_curl_global_init_mem_curl_jmpenv_curl_maprintf_curl_mfprintf_curl_mprintf_curl_msnprintf_curl_msprintf_curl_multi_add_handle_curl_multi_assign_curl_multi_cleanup_curl_multi_fdset_curl_multi_info_read_curl_multi_init_curl_multi_perform_curl_multi_remove_handle_curl_multi_setopt_curl_multi_socket_curl_multi_socket_action_curl_multi_socket_all_curl_multi_strerror_curl_multi_timeout_curl_multi_wait_curl_mvaprintf_curl_mvfprintf_curl_mvprintf_curl_mvsnprintf_curl_mvsprintf_curl_share_cleanup_curl_share_init_curl_share_setopt_curl_share_strerror_curl_slist_append_curl_slist_free_all_curl_strequal_curl_strnequal_curl_unescape_curl_version_curl_version_info_curlx_nonblock_curlx_sitouz_curlx_sltosi_curlx_sltoui_curlx_sltous_curlx_sotouz_curlx_sztosi_curlx_tvdiff_curlx_tvdiff_secs_curlx_tvnow_curlx_uitosi_curlx_uitouc_curlx_uitous_curlx_ultosi_curlx_ultouc_curlx_ultous_curlx_uztosi_curlx_uztoso_curlx_uztosz_curlx_uztoui_curlx_uztoul_debug_prompt_deflate_deflateBound_deflateCopy_deflateEnd_deflateInit2__deflateInit__deflateParams_deflatePending_deflatePrime_deflateReset_deflateResetKeep_deflateSetDictionary_deflateSetHeader_deflateTune_deflate_copyright_do_absolutetype_do_chdir_do_getabsolute_do_getcwd_do_hash_do_isabsolute_do_isfile_do_locate_do_mkdir_do_normalize_do_path_has_deferred_join_do_pathsearch_do_translate_get_crc_table_http_download_http_get_http_post_inflate_inflateCopy_inflateEnd_inflateGetDictionary_inflateGetHeader_inflateInit2__inflateInit__inflateMark_inflatePrime_inflateReset_inflateReset2_inflateResetKeep_inflateSetDictionary_inflateSync_inflateSyncPoint_inflateUndermine_inflate_copyright_inflate_fast_inflate_table_luaC_barrier__luaC_barrierback__luaC_checkfinalizer_luaC_fix_luaC_freeallobjects_luaC_fullgc_luaC_newobj_luaC_runtilstate_luaC_step_luaC_upvalbarrier__luaC_upvdeccount_luaD_call_luaD_callnoyield_luaD_growstack_luaD_hook_luaD_inctop_luaD_pcall_luaD_poscall_luaD_precall_luaD_protectedparser_luaD_rawrunprotected_luaD_reallocstack_luaD_shrinkstack_luaD_throw_luaE_extendCI_luaE_freeCI_luaE_freethread_luaE_setdebt_luaE_shrinkCI_luaF_close_luaF_findupval_luaF_freeproto_luaF_getlocalname_luaF_initupvals_luaF_newCclosure_luaF_newLclosure_luaF_newproto_luaG_addinfo_luaG_concaterror_luaG_errormsg_luaG_opinterror_luaG_ordererror_luaG_runerror_luaG_tointerror_luaG_traceexec_luaG_typeerror_luaH_free_luaH_get_luaH_getint_luaH_getn_luaH_getshortstr_luaH_getstr_luaH_new_luaH_newkey_luaH_next_luaH_resize_luaH_resizearray_luaH_set_luaH_setint_luaK_checkstack_luaK_codeABC_luaK_codeABx_luaK_codek_luaK_concat_luaK_dischargevars_luaK_exp2RK_luaK_exp2anyreg_luaK_exp2anyregup_luaK_exp2nextreg_luaK_exp2val_luaK_fixline_luaK_getlabel_luaK_goiffalse_luaK_goiftrue_luaK_indexed_luaK_infix_luaK_intK_luaK_jump_luaK_nil_luaK_patchclose_luaK_patchlist_luaK_patchtohere_luaK_posfix_luaK_prefix_luaK_reserveregs_luaK_ret_luaK_self_luaK_setlist_luaK_setoneret_luaK_setreturns_luaK_storevar_luaK_stringK_luaL_addlstring_luaL_addstring_luaL_addvalue_luaL_argerror_luaL_buffinit_luaL_buffinitsize_luaL_callmeta_luaL_checkany_luaL_checkinteger_luaL_checklstring_luaL_checknumber_luaL_checkoption_luaL_checkstack_luaL_checktype_luaL_checkudata_luaL_checkversion__luaL_error_luaL_execresult_luaL_fileresult_luaL_getmetafield_luaL_getsubtable_luaL_gsub_luaL_len_luaL_loadbufferx_luaL_loadfilex_luaL_loadstring_luaL_newmetatable_luaL_newstate_luaL_openlibs_luaL_optinteger_luaL_optlstring_luaL_optnumber_luaL_prepbuffsize_luaL_pushresult_luaL_pushresultsize_luaL_ref_luaL_register_luaL_requiref_luaL_setfuncs_luaL_setmetatable_luaL_testudata_luaL_tolstring_luaL_traceback_luaL_unref_luaL_where_luaM_growaux__luaM_realloc__luaM_toobig_luaO_arith_luaO_ceillog2_luaO_chunkid_luaO_fb2int_luaO_hexavalue_luaO_int2fb_luaO_nilobject__luaO_pushfstring_luaO_pushvfstring_luaO_str2num_luaO_tostring_luaO_utf8esc_luaP_opmodes_luaP_opnames_luaS_clearcache_luaS_createlngstrobj_luaS_eqlngstr_luaS_hash_luaS_hashlongstr_luaS_init_luaS_new_luaS_newlstr_luaS_newudata_luaS_remove_luaS_resize_luaT_callTM_luaT_callbinTM_luaT_callorderTM_luaT_gettm_luaT_gettmbyobj_luaT_init_luaT_objtypename_luaT_trybinTM_luaT_typenames__luaU_dump_luaU_undump_luaV_concat_luaV_div_luaV_equalobj_luaV_execute_luaV_finishOp_luaV_finishget_luaV_finishset_luaV_lessequal_luaV_lessthan_luaV_mod_luaV_objlen_luaV_shiftl_luaV_tointeger_luaV_tonumber__luaX_init_luaX_lookahead_luaX_newstring_luaX_next_luaX_setinput_luaX_syntaxerror_luaX_token2str_luaY_parser_luaZ_fill_luaZ_init_luaZ_read_lua_absindex_lua_arith_lua_atpanic_lua_callk_lua_checkstack_lua_close_lua_compare_lua_concat_lua_copy_lua_createtable_lua_dump_lua_error_lua_gc_lua_getallocf_lua_getfield_lua_getglobal_lua_gethook_lua_gethookcount_lua_gethookmask_lua_geti_lua_getinfo_lua_getlocal_lua_getmetatable_lua_getstack_lua_gettable_lua_gettop_lua_getupvalue_lua_getuservalue_lua_ident_lua_iscfunction_lua_isinteger_lua_isnumber_lua_isstring_lua_isuserdata_lua_isyieldable_lua_len_lua_load_lua_main_lua_newstate_lua_newthread_lua_newuserdata_lua_next_lua_pcallk_lua_pushboolean_lua_pushcclosure_lua_pushfstring_lua_pushinteger_lua_pushlightuserdata_lua_pushlstring_lua_pushnil_lua_pushnumber_lua_pushstring_lua_pushthread_lua_pushvalue_lua_pushvfstring_lua_rawequal_lua_rawget_lua_rawgeti_lua_rawgetp_lua_rawlen_lua_rawset_lua_rawseti_lua_rawsetp_lua_resume_lua_rotate_lua_setallocf_lua_setfield_lua_setglobal_lua_sethook_lua_seti_lua_setlocal_lua_setmetatable_lua_settable_lua_settop_lua_setupvalue_lua_setuservalue_lua_status_lua_stringtonumber_lua_toboolean_lua_tocfunction_lua_tointegerx_lua_tolstring_lua_tonumberx_lua_topointer_lua_tothread_lua_touserdata_lua_type_lua_typename_lua_upvalueid_lua_upvaluejoin_lua_version_lua_xmove_lua_yieldk_luai_ctype__luaopen_base_luaopen_coroutine_luaopen_debug_luaopen_io_luaopen_math_luaopen_os_luaopen_package_luaopen_string_luaopen_table_luaopen_utf8_main_original_luaL_loadfilex_os_chdir_os_chmod_os_comparefiles_os_compile_os_copyfile_os_getWindowsRegistry_os_getcwd_os_getpass_os_getversion_os_host_os_is64bit_os_isdir_os_isfile_os_islink_os_listWindowsRegistry_os_locate_os_matchdone_os_matchisfile_os_matchname_os_matchnext_os_matchstart_os_mkdir_os_pathsearch_os_realpath_os_rmdir_os_stat_os_touchfile_os_uuid_os_writefile_ifnotequal_path_absolutetype_path_deferred_join_path_getabsolute_path_getrelative_path_has_deferred_join_path_isabsolute_path_join_path_join_internal_path_join_single_path_normalize_path_resolve_deferred_join_path_translate_path_wildcards_premake_execute_premake_find_embedded_script_premake_getEmbeddedResource_premake_init_premake_load_embedded_script_premake_locate_executable_premake_pcall_premake_test_file_printLastError_registerModules_scripts_path_sha1_addUncounted_sha1_hashBlock_sha1_init_sha1_pad_sha1_result_sha1_rol32_sha1_write_sha1_writebyte_string_endswith_string_hash_string_sha1_string_startswith_term_doGetTextColor_term_doSetTextColor_term_getTextColor_term_setTextColor_zError_z_errmsg_zcalloc_zcfree_zip_archive_set_tempdir_zip_close_zip_discard_zip_error_get_sys_type_zip_extract_zip_fclose_zip_file_get_external_attributes_zip_fopen_index_zip_fopen_index_encrypted_zip_fread_zip_get_archive_flag_zip_get_name_zip_get_num_entries_zip_open_zip_set_archive_comment_zip_source_buffer_zip_source_close_zip_source_crc_zip_source_deflate_zip_source_error_zip_source_filep_zip_source_free_zip_source_function_zip_source_layered_zip_source_open_zip_source_pkware_zip_source_pop_zip_source_read_zip_source_stat_zip_source_window_zip_stat_index_zip_stat_init_zlibCompileFlags_zlibVersion_CCCrypt_CC_MD4_CC_MD5_CC_MD5_Final_CC_MD5_Init_CC_MD5_Update_CFArrayAppendValue_CFArrayCreate_CFArrayCreateMutable_CFArrayGetCount_CFArrayGetValueAtIndex_CFBundleCopyExecutableURL_CFBundleGetMainBundle_CFDataCreate_CFDictionaryCreate_CFDictionaryGetTypeID_CFDictionaryGetValue_CFDictionaryGetValueIfPresent_CFGetTypeID_CFPropertyListCreateWithStream_CFPropertyListIsValid_CFReadStreamClose_CFReadStreamCreateWithFile_CFReadStreamOpen_CFRelease_CFRetain_CFStringCompare_CFStringCreateWithCString_CFStringCreateWithCStringNoCopy_CFStringGetCString_CFURLCopyFileSystemPath_CFURLCreateDataAndPropertiesFromResource_CFURLCreateFromFileSystemRepresentation_CFURLCreateWithFileSystemPath_SSLClose_SSLCopyPeerTrust_SSLCreateContext_SSLGetBufferedReadSize_SSLGetNegotiatedCipher_SSLGetNegotiatedProtocolVersion_SSLGetNumberSupportedCiphers_SSLGetSessionState_SSLGetSupportedCiphers_SSLHandshake_SSLRead_SSLSetCertificate_SSLSetConnection_SSLSetEnabledCiphers_SSLSetIOFuncs_SSLSetPeerDomainName_SSLSetPeerID_SSLSetProtocolVersionMax_SSLSetProtocolVersionMin_SSLSetSessionOption_SSLWrite_SecCertificateCopyCommonName_SecCertificateCopyLongDescription_SecCertificateCreateWithData_SecIdentityCopyCertificate_SecItemCopyMatching_SecPKCS12Import_SecPolicyCreateSSL_SecTrustEvaluate_SecTrustGetCertificateAtIndex_SecTrustGetCertificateCount_SecTrustSetAnchorCertificates_SecTrustSetAnchorCertificatesOnly__DefaultRuneLocale___CFConstantStringClassReference____chkstk_darwin___bzero___darwin_check_fd_set_overflow___error___maskrune___memcpy_chk___sprintf_chk___srget___stack_chk_fail___stack_chk_guard___stderrp___stdinp___stdoutp___strcat_chk___strcpy_chk___strncpy_chk___tolower___toupper__longjmp__setjmp_abort_access_acos_add_history_alarm_arc4random_asin_atan2_atexit_atoi_basename_bind_calloc_chdir_chmod_clearerr_clock_close_closedir_connect_connectx_cos_difftime_dlclose_dlerror_dlopen_dlsym_exit_exp_fclose_fcntl_fdopen_feof_ferror_fflush_fgets_fileno_flockfile_fmod_fnmatch_fopen_fprintf_fputc_fputs_fread_free_freeaddrinfo_freopen_frexp_fseek_fseeko_fstat$INODE64_ftell_ftello_funlockfile_fwrite_getaddrinfo_getc_getcwd_getenv_geteuid_gethostname_getpass_getpeername_getpid_getpwuid_getsockname_getsockopt_gettimeofday_gmtime_r_inet_pton_ioctl_isatty_kCFAllocatorDefault_kCFAllocatorNull_kCFBooleanTrue_kCFCopyStringDictionaryKeyCallBacks_kCFTypeArrayCallBacks_kCFTypeDictionaryValueCallBacks_kSecAttrLabel_kSecClass_kSecClassIdentity_kSecImportExportPassphrase_kSecImportItemIdentity_kSecMatchLimit_kSecMatchLimitAll_kSecMatchPolicy_kSecReturnRef_localeconv_localtime_localtime_r_log_log10_log2_lstat$INODE64_malloc_memchr_memcmp_memcpy_memmove_memset_mkdir_mkstemp_mktime_open_opendir$INODE64_pclose_poll_popen_pow_printf_putc_qsort_random_read_readdir$INODE64_readline_realloc_realpath$DARWIN_EXTSN_recv_remove_rename_rmdir_send_setlocale_setsockopt_setvbuf_sigaction_siglongjmp_signal_sigsetjmp_sin_snprintf_socket_sprintf_srandom_sscanf_stat$INODE64_strcasecmp_strcat_strchr_strcmp_strcoll_strcpy_strdup_strerror_strerror_r_strftime_strlen_strncasecmp_strncmp_strncpy_strpbrk_strrchr_strspn_strstr_strtod_strtok_strtok_r_strtol_strtoul_symlink_sysctl_system_tan_time_tmpfile_truncate_umask_ungetc_vsnprintf_writedyld_stub_binder_testValue_match_pmain_report_loadline_doREPL_pushline_msghandler_laction_lstop_curl_file_cb_pushglobalfuncname_typeerror_resizebox_skipcomment_getF_getS_l_alloc_panic_chunk_wrapper_findfield_boxgc_writer_getversion_lua_error_handler_growstack_auxsetstr_f_call_luaB_assert_luaB_collectgarbage_luaB_dofile_luaB_error_luaB_getmetatable_luaB_ipairs_luaB_loadfile_luaB_load_luaB_next_luaB_pairs_luaB_pcall_luaB_print_luaB_rawequal_luaB_rawlen_luaB_rawget_luaB_rawset_luaB_select_luaB_setmetatable_luaB_tonumber_luaB_tostring_luaB_type_luaB_xpcall_dofilecont_ipairsaux_generic_reader_finishpcall_luaK_code_addk_exp2reg_jumponcond_constfolding_codebinexpval_discharge2reg_luaB_cocreate_luaB_coresume_luaB_corunning_luaB_costatus_luaB_cowrap_luaB_yield_luaB_yieldable_auxresume_luaB_auxwrap_db_debug_db_getuservalue_db_gethook_db_getinfo_db_getlocal_db_getregistry_db_getmetatable_db_getupvalue_db_upvaluejoin_db_upvalueid_db_setuservalue_db_sethook_db_setlocal_db_setmetatable_db_setupvalue_db_traceback_hookf_varinfo_getobjname_resume_unroll_f_parser_DumpFunction_reallymarkobject_sweeplist_singlestep_GCTM_dothecall_propagatemark_markmt_traverseephemeron_iscleared_clearvalues_io_close_io_flush_io_input_io_lines_io_open_io_output_io_popen_io_read_io_tmpfile_io_type_io_write_f_close_g_iofile_io_fclose_io_readline_g_read_read_line_readdigits_io_pclose_g_write_f_flush_f_lines_f_read_f_seek_f_setvbuf_f_write_f_gc_f_tostring_io_noclose_lexerror_llex_skip_sep_read_long_string_read_numeral_math_abs_math_acos_math_asin_math_atan_math_ceil_math_cos_math_deg_math_exp_math_toint_math_floor_math_fmod_math_ult_math_log_math_max_math_min_math_modf_math_rad_math_random_math_randomseed_math_sin_math_sqrt_math_tan_math_type_setpath_gctm_ll_loadlib_ll_searchpath_lookforfunc_searchpath_searcher_preload_searcher_Lua_searcher_C_searcher_Croot_loadfunc_ll_require_intarith_os_clock_os_date_os_difftime_os_execute_os_exit_os_getenv_os_remove_os_rename_os_setlocale_os_time_os_tmpname_setallfields_getfield_newupvalue_close_func_errorlimit_statement_gotostat_test_then_block_leaveblock_subexpr_constructor_body_suffixedexp_recfield_new_localvar_fieldsel_funcargs_singlevaraux_undefgoto_closegoto_semerror_error_expected_forbody_adjust_assign_assignment_f_luaopen_close_state_str_byte_str_char_str_dump_str_find_str_format_gmatch_str_gsub_str_len_str_lower_str_match_str_rep_str_reverse_str_sub_str_upper_str_pack_str_packsize_str_unpack_str_find_aux_match_class_push_onecapture_gmatch_aux_getdetails_getoption_unpackint_setarrayvector_auxsetnode_mainposition_tconcat_tinsert_pack_unpack_tremove_tmove_sort_checktab_auxsort_sort_comp_LoadFunction_error_LoadString_byteoffset_codepoint_utfchar_utflen_iter_codes_iter_aux__zip_torrentzip_cmp__zip_dirent_process_ef_utf_8__zip_ef_utf8__zip_checkcons_read_data_crc_read_deflate_compress_deflate_decompress_read_file_pkware_decrypt_window_read_crc32_combine__fill_window_deflate_stored_deflate_fast_deflate_slow_longest_match_updatewindow_build_tree_compress_block_send_tree_base64_encode_free_bundle_hash_entry_conn_llist_dtor_singleipconnect_conn_is_conn_cookie_sort_darwinssl_connect_common_darwinssl_connect_step2_darwinssl_recv_darwinssl_send_SocketRead_SocketWrite_append_cert_to_array_sslerr_to_curlerr_auth_digest_md5_to_ascii_AddFormDataf_formdata_add_filename_hash_element_dtor_freednsentry_fetch_addr_alarmfunc_hostcache_timestamp_remove_http_getsock_do_https_connecting_https_getsock_http_perhapsrewind_output_auth_headers_readmoredata_header_append_MD5_Init_MD5_Update_MD5_Final_dprintf_formatf_addbyter_alloc_addbyter_storebuffer_multi_freeamsg_multi_freetimeout_multi_done_singlesocket_multi_getsock_multi_runsingle_add_next_timeout_multi_socket_multi_addtimeout_hash_fd_fd_key_compare_sh_freeentry_site_blacklist_llist_dtor_server_blacklist_llist_dtor_time2str_max5data_conn_free_create_conn_parse_login_details_check_noproxy_parse_proxy_llist_dtor_call_disconnect_if_dead_get_protocol_family_lower_digits_upper_digits_dprintf_formatf.null_builtin_script_0_builtin_script_1_builtin_script_2_builtin_script_3_builtin_script_4_builtin_script_5_builtin_script_6_builtin_script_7_builtin_script_8_builtin_script_9_builtin_script_10_builtin_script_11_builtin_script_12_builtin_script_13_builtin_script_14_builtin_script_15_builtin_script_16_builtin_script_17_builtin_script_18_builtin_script_19_builtin_script_20_builtin_script_21_builtin_script_22_builtin_script_23_builtin_script_24_builtin_script_25_builtin_script_26_builtin_script_27_builtin_script_28_builtin_script_29_builtin_script_30_builtin_script_31_builtin_script_32_builtin_script_33_builtin_script_34_builtin_script_35_builtin_script_36_builtin_script_37_builtin_script_38_builtin_script_39_builtin_script_40_builtin_script_41_builtin_script_42_builtin_script_43_builtin_script_44_builtin_script_45_builtin_script_46_builtin_script_47_builtin_script_48_builtin_script_49_builtin_script_50_builtin_script_51_builtin_script_52_builtin_script_53_builtin_script_54_builtin_script_55_builtin_script_56_builtin_script_57_builtin_script_58_builtin_script_59_builtin_script_60_builtin_script_61_builtin_script_62_builtin_script_63_builtin_script_64_builtin_script_65_builtin_script_66_builtin_script_67_builtin_script_68_builtin_script_69_builtin_script_70_builtin_script_71_builtin_script_72_builtin_script_73_builtin_script_74_builtin_script_75_builtin_script_76_builtin_script_77_builtin_script_78_builtin_script_79_builtin_script_80_builtin_script_81_builtin_script_82_builtin_script_83_builtin_script_84_builtin_script_85_builtin_script_86_builtin_script_87_builtin_script_88_builtin_script_89_builtin_script_90_builtin_script_91_builtin_script_92_builtin_script_93_builtin_script_94_builtin_script_95_builtin_script_96_builtin_script_97_builtin_script_98_builtin_script_99_builtin_script_100_builtin_script_101_builtin_script_102_builtin_script_103_builtin_script_104_builtin_script_105_builtin_script_106_builtin_script_107_builtin_script_108_builtin_script_109_builtin_script_110_builtin_script_111_builtin_script_112_builtin_script_113_builtin_script_114_builtin_script_115_builtin_script_116_builtin_script_117_lua_version.version_luaB_collectgarbage.optsnum_luaK_prefix.ef_HOOKKEY_f_seek.mode_f_setvbuf.mode_CLIBS_luaO_ceillog2.log_2_os_setlocale.cat_priority_dummynode__udatatypename_utf8_decode.limits__zip_ef_get_by_id.empty__zip_string_get.empty__cp437_to_unicode_crc_table_inflate.order_fixedtables.lenfix_fixedtables.distfix_inflate_table.lbase_inflate_table.lext_inflate_table.dbase_inflate_table.dext_static_ltree_static_dtree_extra_lbits_extra_dbits_extra_blbits_bl_order_base_length_base_dist_base64_base64url_Curl_ntlm_core_mk_lm_hash.magic_hmac_ipad_hmac_opad_Curl_auth_decode_ntlm_type2_message.type2_marker_tz_my_timegm.month_days_cumulative_showit.s_infotype_premake_functions_criteria_functions_debug_functions_path_functions_os_functions_string_functions_buffered_functions_term_functions_http_functions_zip_functions_base_funcs_luaB_collectgarbage.opts_co_funcs_dblib_hookf.hooknames_iolib_flib_f_seek.modenames_f_setvbuf.modenames_luaX_tokens_mathlib_pk_funcs_ll_funcs_syslib_os_setlocale.catnames_strlib_tab_funcs_luaT_init.luaT_eventname_funcs_configuration_table_ContentTypeForFilename.ctts_mstate.finit_Curl_handler_dummy_protocols__dyld_private_progname_s_shimTable_s_currentColor_s_shouldUseColor__zip_mkstemp.xtra.0__zip_mkstemp.xtra.1_static_l_desc_static_d_desc_static_bl_desc_Curl_ipv6works.ipv6_works_version_info_curl_init.initializedHTTP_globalL__zip_dirent_torrent_normalize.torrenttime__zip_dirent_torrent_normalize.last_mod_initialized_init_flags_host_cache_initialized_hostname_cache_randit.randseed_randit.seeded_curl_version.initialized_curl_version.version_curl_version_info.initialized_curl_version_info.ssl_buffer_init_ssl