ELF>@D@8 @@@@pvpv  PPP||(88 `:`J`J88800hhhDDStd88800PtdQtdRtd(88/lib64/ld-linux-x86-64.so.2 GNUGNU@>GV[AwjD`FGNUn @D ! 0*)(I D@$ B AB $B@ @P @BBP C"  `Q0@@@P <aBPL4#0@0$Q  @0 `@ 0! eA! npqtuvw{~  "$%'(*+|ʼe y>s]89\YѱV"$T!Tv&z}1)!N2fsվV0K% -[9.vwPA1eW0 ?gUa |l }eO(L &2mʣ_9 O49 bNC__Di?;YAA5-T -,`Ua91.H #{)K("e_[l2bnMGo?kZ FM+;`*e9iG/FqߟÇ=uzw6Ð׵:lWfuc"qXM 4Z I 舿݋MĒnhq%BWyw 6M 8sF ]]>II$ NkYRBteek(5$9 y{%@sF yu Yy40ۉ8Clq{d +~_Β=BMr93D,KkBJ|B4zm\՟KY :c/vI ,ʠCE,30FǺXM ?.|e&?]X : x?2dCICC ο¨ s2\'E )׵ ?em.Hj|H1IcQy=ͪA%lw^,t < c-a e*8?eL=Bݝare$^N(/ R CIU ON \? w>>t%-RS \  pD+ȒM d1 =w BCM V =h89IvA j&H2 ODMHf= \ R 0l Y E2c& B ~ _"O L)E o F d T) `n ;S E3 u J*t PBB: .XztaqnBqw?1   ?b RܞcʺP Й -zzbMg ն-9A5 A ?>  ߓ}#w ;   C 5 ] `PVNN AnlI Лx -Q](<# |uj=3!D" `:G uQ %GwbP  S_}* _7g. 6 f 2;. 4 ?< R] ri ^4 Z, :`5>< I_ P;0Rm Y[/c&>er3Z :4A @"S>`r!    {kI^ hLP(> @`! <-& ; /<Z6Ax= xe @N]P՟< q~U 1b>]6|װ ̐_ITM_deregisterTMCloneTable__gmon_start___ITM_registerTMCloneTablefloorlog10acoslogfrexpsqrtceilasinatan2tanpowfmodsetlocale__ctype_tolower_locclockdlerror__cxa_finalizemkstemp64fgetsstrchrmallocmemmovesrandomlocaltime_r_setjmprename__libc_start_mainflockfile__fprintf_chkrandstrcmpdlsymfputsfunlockfileremovelocaleconvstat64fclosestrcpy__strncpy_chkstrspngmtime_rstrtodsetvbufstrncmp__ctype_b_locmktime__ctype_toupper_locmemchrstdoutclosedirpclosefreefflushsystemtolowerstrstr__strcpy_chkgetc_unlockedstrncpystrlengetenv__memcpy_chkmemcmpdlopenreallocfopen64ungetcdlclosestdinreaddir64clearerrferrorstrftimeabort__sprintf_chkstderrfnmatchftello64strcoll__longjmp_chkfseeko64difftimestrpbrkstrrchrgettimeofdayopendirstrerrorfread__errno_locationexitpopenfwritetmpfile64readlink__stack_chk_failfreopen64feoflibm.so.6libc.so.6os_statluaopen_iolua_checkstacklua_gettoplua_absindexos_rmdirluaL_openlibluaL_wherelua_settoplua_getlocallua_getstackluaL_tracebacklua_tobooleanluaL_pushresultsizeluaL_callmetalua_touserdataluaL_setfuncsluaL_argerrorluaL_tolstringlua_pushcclosurebuiltin_scriptsluaL_loadbufferxget_relative_pathlua_closelua_nextlua_tointegerxlua_tolstring_edatalua_getinfolua_identos_mkdirluaL_checkoptionluaL_reflua_createtablelua_versionlua_pushvfstringlua_rawsetluaL_checknumberlua_gethooklua_xmoveluaL_optlstringluaL_optnumberluaL_pushresultlua_rawgetipath_getabsoluteluaL_fileresultlua_setlocalluaL_openlibsis_absolute_pathluaopen_debuglua_setfieldlua_gcstring_hashlua_pushintegerluaopen_mathlua_isnumberlua_pushthreadluaL_getsubtableluaL_loadfilexluaopen_stringluaL_checklstringlua_setallocflua_pushvaluelua_pushfstringluaL_prepbuffsizelua_tonumberxlua_gettablelua_setilua_setglobalpath_getrelative__data_startos_matchnameluaL_newstatepath_isabsolutelua_loadluaopen_bit32lua_newuserdataluaL_checkintegerlua_setmetatablelua_rawsetido_isfilelua_setuservalueluaopen_coroutineos_matchnextlua_dumplua_newstatedo_hashstring_endswithos_matchisfile_IO_stdin_usedos_tickslua_getupvaluelua_getgloballua_pushnumberlua_lenlua_settableos_uuidlua_pushbooleanlua_topointerluaL_optintegerluaL_checkstackluaL_testudatalua_atpanicluaL_buffinitsizeluaL_checktypelua_stringtonumberlua_pushlightuserdatalua_getallocfluaL_checkudatalua_isyieldable_endget_absolute_pathlua_getuservalueos_pathsearchlua_rawgetluaL_gsublua_rotatelua_copylua_pushlstringlua_iscfunctionluaL_addstringos_copyfileluaL_checkanylua_yieldklua_newthreadlua_rawequal__bss_startos_isdiros_is64bitlua_callklua_erroros_matchdonepremake_initluaL_addlstringluaL_getmetafieldlua_rawlenlua_sethookluaopen_utf8lua_tothreadluaopen_osluaL_checkversion_lua_typenameluaL_pushmoduleluaL_errorlua_rawgetplua_isuserdatalua_tocfunctionos_matchstartluaopen_packagelua_pushnilpremake_executeluaL_loadstringluaopen_tablelua_upvaluejoinluaL_addvaluelua_concatluaL_setmetatableluaopen_baselua_typeluaL_lenlua_statuslua_upvalueidluaL_execresultluaL_newmetatablelua_resumeluaL_unreflua_arithlua_comparelua_pushstringluaL_buffinitlua_getmetatablelua_gethookcountlua_setupvaluelua_getilua_getfieldos_getcwdlua_pcallklua_rawsetpos_isfilelua_gethookmaskos_chdirluaL_requireflua_isintegerlua_isstringpremake_locateGLIBC_2.2.5GLIBC_2.29GLIBC_2.11GLIBC_2.3.4GLIBC_2.33GLIBC_2.4GLIBC_2.34GLIBC_2.3      0ui m y  ti  ii   ui m ii  889T9T9T9T 9U(9U09U89U`9%Uh9dp9,Ux9 9;U99nl99BU99OU99VU9@9e949}9V9T9:U:x:_U: :eU(:0:nU8:@:uUH:GP:|UX:`:Uh:p:Ux:a:U:Y:R::U::Dj:T:{;W;;^W; ;U(;0;W8;:@;WH;NP;WX;`;Wh;;Y;Y;zY;T;Y;Y;A;Y;;Y;{;Y;6<Y<?<Y< <BU(<0<Z8<b@<ZH<9P<ZX<`<$Zh<p<1Zx<f<9Z<Z<U<<BZ<;<MZ<<w<R^<>=^=^=zY =^(=80=_8=<@=_H=h>P=vX=D`= _h=>p=_x=>=_===_=8=R=@@=^=8=_=z<=^=G=_= H>^R>F> ^>G >#_(><0>v8>D@>)_H>?P>DjX>?`>_h>7>=v>`>`>`>`>>>R>`>c>`>`>v>Y>t>cv>Dv?`?Y?`?R ?`(?`0?`8?LQ@?KQH?`P?`X?``?`h?`p?`x?`?`?`?`?`?`?Ob?Ie?Sb?7c?Xb?c?]b?b@bb@c@Tb@b @gb(@]0@kb8@Rb@@obH@dP@ybX@d`@bh@ap@bx@Oa@b@`@b@*`@b@_@b@d@b@t]@n{@^@b@j^@Yb@:^AbA ^A^bA] ADj(Agc0A1b@A4bPA9b`ADbAQlAtALsAsAeAiAeAhBeB6pBeB?n Be(Bk0Be@B|dPB}d`BQcpBeBOhBThBZhBahBjhBrhB{hBhBhBhBhBhChChChCh Ch(Ch0Ch8Ch@ChHChPChXCh`ChhChpChxChChChChChCiChCiCiCiCiCiC2iC iC(iC1iC:iDBiDJiDQi Di(D/d0Dc8D$j@D+jHD-j`DYhD;jpDCjxDIjDRjDijDZjDD`jDVDejDIDnjDDRDDvjDmE}jE4EjE Ej(E0Eij8E@EjHE`EwhE pErxEhErEErE.E^EErEErEEvE3ErEErE#FrF9FrF Fv(F0Fr8F@FuHFPFrXF`FuhF#FsvFLFuFFuFFuFF}jFFjFFuF3GSG uG_G#Y Gv(G v0Gv8Gv@GvHG!vPG'vXG-v`G3vhG:vpGAvxGGvGNvGTvGZvG`vGgvGlvGqvGzvGnGtGvGvGyGudGycGcHvHvHv HT(Hd0H]8Hu@H\HHvPHycXH`H{hHHpHUbxHHudHH]HeH]HrHYHH}HMI}I:I}I`: I}(I;0I}8I;@I}HI:PI}XI<`I}hI=pI}xI>I}I=I}I>I}I<I}I8?I}I?I}I@I~I9AI ~InBJ~JB J~(JH0J ~8JD@J,~HJ)EPP Pw(P0Pw8P!@PrHP PPvXP`P3VhP= pPwPQ~PPRPPPPP6PPPP#QQMDQQ Qn(Q0QV8Q@QXHQPQPXQ`Q'hQ2pQ8xQ;QkBQ"CQ HQJQPQ uQQ7QJQ8Q<QQ(,Q>Q QRRR*"R' R-(R30RJ98Rx:@RfHRPR"XR2`RhRpR xRRRy$R2RdRqRRROO O?ObORRSxLLLLLLLL L L L LLLLLLMMMM M(M0M8M@MHMPMXM`M hM!pM"xM#M$M%M&M'M(M)M*M+M,M-M.M/M0M1M2M3N4N5N6N7 N8(N90N:8N;@N<HN=PN>XN@`NAhNBpNCxNDNENFNGNHNINJNKNLNMNNNONPNQNRNSNTOUOVOWOX OY(OZ0O[8O\@O]HO^PO_XO``OahOcpOdxOeOfOgOhOiOjOkOlOmHHHtH5B%Chhhhhhhhqhah Qh Ah 1h !h hhhhhhhhhhqhahQhAh1h!hhhh h!h"h#h$h%h&h'qh(ah)Qh*Ah+1h,!h-h.h/h0h1h2h3h4h5h6h7qh8ah9Qh:Ah;1h<!h=h>h?h@hAhBhChDhEhFhGqhHahIQhJAhK1hL!hMhNhOhPhQhRhShThUhVhWqhXahYQhZAh[1h\!h]h^h_h`hahbhchdhehfhgqhha%D%D%D%D%D%}D%uD%mD%eD%]D%UD%MD%ED%=D%5D%-D%%D%D%D% D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%}D%uD%mD%eD%]D%UD%MD%ED%=D%5D%-D%%D%D%D% D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%}D%uD%mD%eD%]D%UD%MD%ED%=D%5D%-D%%D%D%D% D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%D%}D%uD%mD%eD%]DAVAAUIATUQ6HH薨HIuHAϾH5HEuLDHżAH-ZD]A\A]A^f.@1I^HHPTE11H=af.H=HH9tHHt H=H5zH)HH?HHHtHmHtfD=}u+UH=JHt H=fdU]wHW ~HcHHH9Gw_HÁٹ| HcHHGÁعu HGH@HHhzt"H ع)y 9|ٹ)HHH6~VH61!HcƋw?t5E1Ƀ&uuH7~n~ 9fHL HHHHtMH1HH?E1Hw~:;F5HHcHL H9H:MtIHHFXL )H@HtLH LH9sHHOFUSHHHGHW0t$ HcHo H)HH9~HcD$ HHCH9Es7HE1H+G8@BH)ʃ9}1HT$ H5|tH[]H9t4HcHH)G19~#LFIHHNHHHHOAHGLHLHWHt HGH'F'FwHO HWH+HHG HHGHH)HHGx,HW HcHFHHHWH9sHJHOBHcHHHGQHGALH(IcIHExLH)H)HHL"HxLLLX APAIDLIAAع})AA@t"I@ HH0F tIB t LYXPILOIxAAMHZaH HƒH9tBH2HcH*Pf  xHdH%(HD$1HǸtHZHT$dH+%(tH@PG HAH|$eH|$DIUHHI9tH9tL1H鵅1HFSHwHG@H@HGHKHHQHIHk[HAAH|$H|$DIHHoI9t?H9t:AH|$tAtEu$LHLHLH1HSHHHsjHtHC[SHHdH%(HD$1,xHu$HuH$Ht$HD$dH+%(tH[SHHdH%(HD$1xHuHH$HuH$HtH$HT$dH+%(t3H[]H‹@tȸu 1:AUATIUHSQ*HË@tFtMtPI$E1CHEAHx~HDHHHHHMtHPI$L` ZL[]A\A]QHHƒtt1uHH@HH@ H8H]HZlPuLE1fuHL@LCHHƒt1u HH(HE1xHuLLIHHH`@?Hu u E1u LLxLHG@HHGHG@H@HGHGH0H@HGSHHHGHx~HT$H4$vHT$H4$H$HSHHHH @ɉJHSH[ATIUHQHu=:HGHx~LH%HUL` HHH@ɉJHULZ]A\HGHx~+H(HT$Ht$H|$轜HT$Ht$H|$H(HHT$@HL$HLD$PLL$Xt:)D$`)L$p)$)$)$)$)$)$dH%(HD$(HGHx~Ht$H<$!Ht$H<$H$HT$D$HD$HD$0D$0HD$ )HT$(dH+%(tnHATIUHSuHGH0@YHGHx~薛HZHcHMHL`HH)HMtHHHD1D0HAf[HE]A\HG1҅‰H@HGHGH0H@HGHGH8H@HHGHGH9AUIATUSHPHGHx@QLcLHHID$HCb#HHI$@@AD$HCHPH{zHC@Z[]A\A]SH-HHHCHPHFzHC[@ATIUSHLcLHH"HSHHI$@Hу@AD$HBHCyHC[]A\@SHIHSHHHBLHBHCyHC[@USHP\HkH8HuQQHCE@Z[]UISHP%LHkH8yPHCEHP@HSZ[]UISHH(dH%(HD$1LD$Ht$HkH8D$PHCHPE@HSHT$dH+%(tOH([]AUAATAUHGHHx~芘HOHUHHHBEHUEE~DDH]A\A]oQ]A\A]IPtuHHPHHP(I@HcHи1HtI@HH@EI@IIPHHHH HJH ȉJIPAUIATUSHPHGHx@NLcLHHID$HC; HSHHI$@HJH@AD$UxHk Z[]A\A]SH HSHHHJH $xHk [ATIUSHLcLHHID$HCHSHHI$@HJH@AD$wHk []A\SHI{HSHHHBHJHCLBwHk [USHR@HH(HCHHPTIHC@AE @@tE tH@@ t HH譎Hk X[]USHHHT$HT$HH(HCHHHNHC@@tE tH@@ t HHMHkH[]UISHH(dH%(HD$1eHT$HH(LD$D$HSIHC@A@@tE tH@@ t HH̍HkHD$dH+%(tH([]ATE1USHHHCxtL`EtuEHEL`HEL`(MtCW1HCW11HCHCH HCC%DcWCWuHƀHHLDcW4HcHH HkH$IEHx~LDcW1H~:1{U/!(9Lщ CWZ[]A\A]PXPbSHTHKHH0HQEHStHHHS[ATUHH~'HGHx~ t$ -t$ HH]A\pvu)Lg1H5DKI$@@AD$HEH]A\SHHsHHwHC[Ht HGH@HHGHHGHPH0SHHHGHx~Ht$uHt$H[HSHHH(BGHSH[HAIE1dH%(HD$1H$1HDHsHtH $IRHBIRHT$dH+%(tuHATAIH dH%(HD$1H$LD$HD$HD$eHL$HDHIHteIBHt$HP@IRH$Ht @@t>F t8HPB t.L藆$Ht$HtH@@tHVH9uL赆HD$dH+%(tH LA\LcH‹@?t&t1HAMcJD I@HHAUAATUHSDAQLcHcgDHIYHL(IN$It$蓆ID ID$HPH@H9t@It$H@@tHVH9uZH[]A\A]΅X[]A\A]HN1HtH HHFÅATAUHSRt1HH8t޾HDHtHaDHytWHHH5HHHHc>[]A\1AVAUATIUHSH$LH5HAYEnعHHDHts1҃H7H5HHu)HsH;HHDH>HDHD$ |D$ H[]A\A]A^AUIATAUHHA8DH1HD$LD$LHHHH5Ϧ1*DHYHH]A\A]UHSHQHc~ H.H~ A1EuHKH{ HHEHCZ[]AWAVAUAATIUHSAPtzA.LHHu LIILHM)L\HTuKH(;.DHAE1LLHHH[HtH-LcHH;.&E1ZL[]A\A]A^A_P1҃H=6H(H1H=$1ZHHtHP1ZATL%UHSHH{t.A$I9u"HcA<$J DuH{EE1#u%H{{t uH{hAE[D]A\AWAVAAUATIUHSHHT$L|$(dH%(H$1JAD$LLDD$cTDD$At8AA LLDD$ΉL$4TL$DD$tDAىA9|ʃ DMH|$tHT$H5ѣH1H5HAFLDLD$StD;l$u H5HCD$CLH5LTLt$`H1LH5h^T$P~H5ZH1EH5MH;LHt@1҃HOHH5H1H.HkHT$8:tHL$0H5H1IHD$@ H5٢H<NLNH&LHHcHE[]A\ATHIعUHQA1EuXH11HLHhHH}HLعHbZ]A\HHعH|$H|$H#AVIATUHHt$ t$ HuE1GHItLعHHDHLD HL]A\A^HHT$H<$u0HT$H<$HtH5HH51HqHHt$ H<$H<$t$ uHH$HAUATUSHQHoHGHH)H9s{HLgHH)H9sbHHsH5CL1HLOH3HKHIHC H9tLULL+HkH9vHCHZ[]A\A]ATIUHHSHuvHHc)H@8H H=~PHH5g=z%? ЉHG8HcH~PH >?<yHAE1ʃ?#uBAtA9tA?A?A D ʃ"ADw1ҋ?? ʉHG8Hc֋D=tED0DAVAUEATAUSHt)H;DA4uDHD[]A\A]A^ATAUSW HH/w(AC(E9C |+HCHu8HUL AHx8ڏHE8HE8HcS D$E9C |+HCHuHHUL ~AHx8蛏HEHHCHcS HHEH C PS []A\ItI:GItI9?#u 1øG G$JI?t&I9cHcAHG8HDƋ%? ȉt7uHHIHωT$ T$ uLHG Hw(G$9W uAйATH Dg(dH%(HD$1G(H|$H|$Ht$DD$KD$HT$dH+%(t虯H A\AA A D HcG A;G$~tHHR8LDA0?u[AA AAA9|EZE9} A9u29|.A9ANс?ȉ? D9AL) A0E1DʾJJE1&4 AUATAHHщA\A]1ɾH|$DH|$AŃ.HDA\A]HG<J 9}=~PHH5{uB USHP@kE1ɃE1S.CHt$H|$HD$ D$H|$‰JHsH|$HHcSH@8H ?%? ЉK9t E11kHD$(dH+%(tH8[]AWAVAUATAUHSHQ; uSHsH^sDSD9HuDHtcA; t HANjE 1DHAE$HE1AƋE DE$DHAAAD} sEDHD}$DsEDDHDcHCX[]A\A]A^A_ATAUHSH u.HHcVH@8Ѓ?uEO 1A">tHlU uF9FtF9FtATIUHH8dH%(HD$(1EwHuLA|$,HT$u%ID$D$ Ht$D$EH@PHD$D$ HD$LEE7EHt$LD$ HD$TEEE=HT$(dH+%(t)"HD$(dH+%(uH8HL]A\P^H8]A\AVAHAUMUHSHHT$ LHD$LHHT$ DD$uAuDDHUH CH[]A]A^AUATIUHSHAPD.A t&A t7Au\HSLY[]A\A]HlKE1 #~ HDEKS ADHXL[H]A\A]AUATIUHSHPHHDkE<CLHMSHD AAZL[H]A\A]UHSHR#ww,t' usH}ES1HHHsHsH7CX[]UHSHRt ttHH<SHsHsHCX[]SHH֋CC B;  fCC [Hփtw v u%WuKHzu vHHcW H@HtAWEAVAUAATIUHSHHXdH%(HD$H1HzxthHBHD$BD$I|$T$ 8A$t&ID$HD$(AD$D$(EuD$0A wAwAt^AUvUuA uoHt$8u HD$HD$8H|$Ht$/Ht$|$0t6H|$(/"uH*L$(Wf. Wf.D$(ztiHEHL$(HT$DLD$8Hx8|$@uHD$8HCD$8f.z#Wɲf.E„uCAEvAuHHE1LHHHAD9~HHPLLH@H8E1DH CHD$HdH+%(u)HXDH[]A\A]A^A_HD$HdH+%(tHX[]A\A]A^A_ATIUHH(dH%(HD$1$HD$HD$t$Av HLHHA$B H doHcH>A$eA$[At$H}KtHUHH<$AUH<$It$A$AE(HH<$AUH<$It$A $AMID$IEHDD$ H<$[A<$ H<$DD$ uGHIcT$H@8H?u-LAM% ȉAD$AE AEbLDD$ H<$RDD$ LLH<$ LHA\A] IȃL IȃL1HA\A]HA\A]BATIU2SXu1ɁA؉+Ly"+LE1eLރ.2[Al$<]A\HH|$-H|$ܯHHH|$9H|$11҉Hn-AUIATAUHHH5ltxHuHH5ltTDHL1DLH+wMH谦LpA脥u#DH謦H5lL讬 DLHӥLHAD]A\A]HH|$H|$跮HATUHPpHQHILHJZ]A\HH|$H|$H5购HATUHV׹HI舥LHVyGHYt,HH譥H贸YH]A\dZ]A\ATHH|$蕪H|$HIuH?kHLA\ATUHHdH%(H$1H5hH9tZHI輶tu;+HT$1LH5j&Lxt H5j H5jH胪H$dH+%(t袛HĘ]A\ATUHSHILHPy#1HzHE#þHR޺HC[]A\U-fHH1詮H1H5UM]PعvZATUHSHADHt裷H1HtH蒩޺HYC[]A\HH|$0H|$1Hk]AVAAUAATUHQDHADDHHuH jDHZD]A\A]A^UH聣ttHdHH;H]ATIHHH|$肨H|$HLA\铮ATIUHQH9u$HHXLH]A\OATIHcHH|$蚧H|$HLA\!UHHHVHq]UHXHܶHH螩]ATUHSHAHtHUhHHHtH0hH#ADHt[1]A\UHH輫uH ]HH|$CH|$tޥ ׫HATL%gUSHHdH%(H$1H5aLHl$蟗H=xa胙H\aHoHtH5LgH苘uH$dH+%(軖H蓖E1HHHH gt81҃H胣H=`H_H1}H=`E1E1111Hٮu1HH1[]A\ATISHAPuLY[A\LZ[A\AUATUHHdH%(HD$1Ht$1HIċD$p覢IHu$D$Hpe~D$Hp/'D$1L9HpLLHcHD$dH+%(tEH]A\A]AVAUATUHSHdH%(H$1Ht$Ll$HIċD$pHIƋD$pDLLH t$uH8eH\HD$HpGLH肜LLIHu LLH{H$dH+%(t:HĐ[]A\A]A^AWAVAUATUHSHdH%(HD$1Ht$HIŋD$p踝t$HE1E1脜E11HE1HIƋD$pD$1HpcLHA讓rLHA蚓HtAlL脓HtAL5h~AHdعHHeue1HʦH賜HھعH覩H5jH HtcH!HuHLHL袚D$HpAHrDDLL HD$dH+%(tbH1[]A\A]A^A_AVAUATUHHdH%(H$1Ht$HIċD$pHAŋD$pʛt$u'H蔛1HD HHHLt$LL| uD$H bHpܹWDLL IHt4HLkLH膠HL H躟H$dH+%(t$HĘ]A\A]A^ATUHSH dH%(HD$1Ht$ IH L Hu HCxHH9t H5JaHqVHgbعHңLHLxH;HYH؃tD$ct HcDrt HcDlHt$HHD6LHHc譞HD$dH+%(tH []A\UHHaSHعARHHvuEHcHBHH4豞Hcs(Hx+AYH[E111Ҿ]邧X[]AVAUATUHHdH%(H$1Ht$Lt$1H_HIŋD$pqHIċD$pŘu8LHH5_1蜞HIċD$pwLH蹖3D$HpLLjuHALLLuD$H_Hp襶A11HSLmHtbHT$(H5^HHT$@H5^HT$4H5^HT$8H5^HHT$ H5^HblLHtT$0H5^HuLԍHtIT$H艞H_^H裢nLyHt(HT$H5VHHT$H5)^HtL?Ht!t$?HH^H6LL HtH]LHLfAHtH]LHUH$dH+%(t背HĘD]A\A]A^UWH7H1H1H5l?]HHHPHG(H+B8HHHH@HHHHt HAVIAUIATIUSFBHcHtaHn y:HH)HHcH@@ H)H9|1uHHHIEHr]^H]HHxn$Hu4HiM;f uIFID$HH)HcHH9|~H]HHTIU[]A\A]A^AWAAVIAUATUHSHsDH#IIH11AAD$ AAA9HU8DX։?Ƀ%w#w*tt0J)tC9|[9R 9~J9|DD9EDN8AD9~(A9|#9LHi2@t9u ;|$ EOEHQA\Hu8IcLЃ? <H=\Hc H>9EAAAurHD"IHHUXL=[HHtLx DLDHL%n[MH5t[L#H\[LDHa[HHUXHHtHB IL%Z^uBTHHU0Bu:HL%ZH I'LDHL%[L%:ZHL[]A\A]A^A_SHs.HcHHW0Bt HZHH HZHt8cu[UHHH dH%(HD$1H$GBu HcH1LAH Hc9~9ML HI;1uIPHHBXHHZHtHB H$HsY8HH+O xH;wsIHIxHʉLHHoH $H5YH1|HT$dH+%(t虇H]Htu11HG @BtH@(HG(HHxHO H`tH9tHI1H9t HJxSHHHdH%(HT$1Hu.HWzFuYHD$dH+%(uYHB1HxH[L@xHH$LHtH $HSHBHSHT$dH+%(t_H[SHHHvxdH%(HD$1HH$3HtHSH $BHHSHT$dH+%(tH[AWAVAUIATUHSHH8dH%(HD$(1>>uHGHE1L`LgLrxM&AD$E1uM<$Hl$D$HD$g\IMLkcHUIEV?3,% 1HSHH IEHQUIEHuH^IEIEHD$fH3HtHCA$H@HCLH HMtA&uHC@HHCcIGHE1Ll$HhHHSIHHBED$HSD$ IGD9`~JcTLLHIaHD$(dH+%(t:D$H8[]A\A]A^A_PXHHHt7HwHG81ɺH|$FHFHHGH|$AUATUHSHHT$pHL$xL$L$t@)$)$)$)$)$)$)$)$dH%(HD$X1H$@HHHD$HD$`$D$0HD$vHu HFBtWHLl$AHHH@HphHtH <LyfD$?IDLHH5R1uHAUATIH?HFH|$LlH|$LH5RIL1PXPFHFHRAUIATIUHSHHdH%(HD$1~u $HH HDLHL<ATIUHSHHdH%(HD$1~u HH$HH HDHLH5QLH1PXH >PFIЃHTA@HLH9uH5Q1~H5Q1pAUATE1UHSRDH_ AtuACB@t ࿈CBEtHaAtiHHK(AHHPHHr8HRHH)HHtHcDt#HE(H9sHt H)HHLA9tD¾HHC(} HE(u3Et DžHKB@HHC(HEHHaX[]A\A]UHSHQtu/H5Q諱 HGHH@@C HG@HH]X[]UHSPHXHtHH]@u HHXtHGHPHWHUBHt'HUH8HE HUH9PsHPH{SHHHWH|$MH|$H@@CHG:HtNATIUHLH2HT$}HT$HuH5jPHLqHH]A\ATUHSHHH>HHPHHtHGHPHWD,AHsPLcAu#HHPQHKXH3LH/HPHDL$ )DL$ H3LLCXHK HФHHH[]A\HH<$Ht$HT$dH%(H$1fDŽ$fD$HGXHD$ HD$ HGXH|$(A}t8HD$ H $fT$HAX$fH$dH+%(ta{Ht$H<$HD$HAVLcAULcATMIUHo8LLSHHHYHC8HE9~LIHDJD2DHC0HCHH)HCHC@HtHHH)HH@HC Ht4HHHH)HHHHH)H@BtHH HH)HH H@[]A\A]A^H=@B~ HWH+W8Ht@B9O9L@B~"CH|$H|$H5M18HUHSQH_HG HtHPH@H9HBH+]8HHÁ@B~艦T@B+عt @B9O9~ ZH[]8X[]AVAUATUSHLdH%(H$1MHHo HOt$HG8LeI͉T$0I)H$I)HG0H)H=@ HCHt$HH@HEƃMBAHC8ƃILLeHCeBH$dH+%(txHĐ[]A\A]A^ATUSHLg t,tH+w8HHs8HID$H@(HC(AD$@IT$I $HS HcЅuHzH9svHHHcA؅~HG1HHHHHK[]A\AWAVAAUATIUHSHT$ AD$HuLHM0H+]8?H)t&t>M$$I$L`H@ HHE H@HuHT$ H]8HE HfP@HU@BH@HPHEHx~Hx#t 1HHAHuHHHH)Y4I$L)HHLhID~AE HH9H8AE D9~HuH~H}FD)D9LAA} u H]8ILcdAM HE0H+EEu HHH9HIcLe1HkA9~%HuAH~H}ADHH]8IHE HXHu H艢HËD$ H] Lc fC@L3AE HIIE8CBLcHC(HELeHx~H"1HCHC(1@BtH@(@?%u KB HHk(1H HH]8HHIINj@tHDFHHRH]L1HCHL)HH)HHI9HwHGHGHI9ĸHGHH'xAH]A $H[]A\A]A^A_HHG PBtPBHP(Hfx@uHWH9PsHPH|$HP0P H|$HHwHHH)USHRHt6Hk`HC H9t'@BuHmH HL X[]HHHG fH5GwO u8HO`H9t H5GrHrH|$H|$u}H H5BuG HH8HO8H@Bt H|$ 8HH Ht"H|$HP0H|$HHWHH)HH|$H|$1HHUHSAPfff=v$f=uH5F1 f=v ufHuH uffX[]AWAVAUATUSHHDdH%(HD$1Ht fLCHcHfHH5PfǃI)L't D$L=nD$Lu8Ls8HL^ LDHHk EBHfǃHE(LHHT$HD$Dl$A~4Hk Ht EBuHmDk HSDHPHC HSHPfD$fDHT$dH+%(t@qH[]A\A]A^A_1fAPfHG t"HGH5EH9uH5E1G LL+G8L@8@Bu/HH HtHP0HcHHH)HWH1ZAWAVAUATUSHHHL LHL$DDbHL$At?HK8HHHL$HT$HDL{ HDfDHHD[]A\A]A^A_ATSHHxLdH%(HD$h1fHt$H5HT$`HT$HL$XHOH+O8HD$(D$4HD$8D$DHD$HD$THD$HD$ HT$ 1HHt$ALMHcT$41HHt$(HD$HD$ H'MHcT$D1HHt$8HkMHcT$T1HHt$HHkLfHD$hdH+%(tnHxD[A\ÃzuSHHJHHH;SC[HHdH%(HD$1@|$H|$HD$dH+%(trnHHH|$ H|$ HATISHdH%(HD$1HuHD$dH+%(ukH1[A\_HGHHxH<$HwB6HLH$H{ LHpHD$dH+%(tmH[A\AWAVAUATUHSHHdH%(HD$1zu HhH9u H1H}(HE1I},H} H} Hz} Hn}HHcuH}8HH/DuHDE9MHILe0A|$?AD$?tMtuMA$$"tt*4A<$H&I$H$HھL I<$HInDmHE1DE9~0HEXMHIIB|0{HEXHB|0 iDm HE1DE9~HE@HuhHJHEPMHIIJ<06HEPHB|0HEPHB|0 E1{uDmHDE1E9~LHIHHEXH8HD$dH+%(tkH[]A\A]A^A_AUHATUHH5D?H0dH%(HT$(1Ld$HL$IDD$ H|$HD$D$$LSD$$L1LH=>LLLLLLLH$xVRLLHz>H$7}LLL1HJD$$HT$(dH+%(tiH0]A\A]S&P HcX [S HcX IH@HcH)H 1IT HL[ATIUHS1E 9~11ҹ 1L8GHPH@H@HD H[]A\ATLg@UHSHG@HHuM1ҹ 1HFI$H@HP@I$H(H9[Pu)HSHHKPHH9(rt L`H@[]A\UHSHRHs@HtFHH9r>HVH~HS@u1ɺ HYFHFHFF@tHF X[]Px v f@ @ H@H@H@ H@(H@0H@8H@@H@HH@PH@XH@`H@hZAT1IUHPHcVHv8HEHcU Hu@L1H~EHcUHu0L1HhEHcUHuHL1HREHcU$HuPL1H<&tbHCS HU HD!HE nHsHtF tHK HCHU HD(HE HC C @t8@ t2HjHEpHCHEpHC0HEpHCHHEpHCpH]p[]A\I1IHtF u HHHuPLHHHtIHtF tZHIHt A uH PHLH HtA tZHHWhHHt0HHD@ HAA tLHLLLHHHHHuAVAUATAUHSH H_dH%(HD$1HHHHSXHHCXH ʃP @{UWwST ʈP HD$@Ht$H@D$mHPDkWDE11ƅH5HCWHMHA L$IH+M8HEDDkWtGAtAu4HMH29AuHQH H5#9H1XHHD$dH+%(tcH []A\A]A^ATE1USHoHHtD9vHAg1D[]A\HG11HpWHG(d1LcHHHHHHI9}LHHwHwH)鳏G@tHG@ tG ËFAA@t,H6uE1HtF tPDZDF ADAVIIAUE1ATE1USN HcHHNE9A v-DHIA@@tH0F tLAAMY1E1AI9s]A[u L+EIsL׃@2tAt(I@ AEtI3F tLA.I AzUuIBxIA0MJx/tIIA0MEtIIA0M[D]A\A]A^AUATUHSRH_pS ЃC C<w<t1<Z< <&HCHK E1HGpHC0LC(HGpMt#A@ uHLIE1Hs(HtF tH2M"A@M(kI LavLI`LH c MK LKE1HcHLɃ{ AL9vIAyu LZ2AA@tIqF tHEuLHGE1AI 벀}UuHExHC0H]xEHHC0HHuHH-HHC0HK E1HcHHKD;C s'DHHC@@tH0F tHALCL9vIEHEu L]0A@@tIpF tHA@tI0F tHuI K S HHHHH8xHCHsHGpHt F t01C 9~AHD Ht2HHpH9t}Ut @B@tH2F tHH뷍 A@uAHC A9|H1F tH HCHHK8HGpHGxHCHH_xS HH;KsA@tH1F tHZH݀}UuBHcHHC8H9v AHH;[Pu)H{@t"HHCPH}VtHHcH HHCpHGpHC`Ht@ tHC`HshHtF tH19K~'HHHC0@@tH0F tHH19K~&HHHCXH0HtF tH^H19K ~ HC@H4HtF tH7H1HcS$9~&HHHCPH0HtF tHHHcCHcKHLHcC HHHcCHHcSHHHHE X[]A\A]SHH{pt H[ATUSHH1HǃHt"HLf0t H߽Lمu[]A\ATIIUSHI9AI E1HcHIIE9a v'ELIMQLtABAMQI9s,AztLLtABLI MI0u[]A\SIIMtOAJ MJHcHLL9v-Ayt IqLRtAAL&I MR0[HHHրUwIA WT ЈA HGf HPxHV0HpxHHUH0wHt F tHGHf HPXHHHUHщS1PHo8UTXP HUXHHEXZ[]HNuHFH9u 1ɺ U8AWAVL5.AUATIUHSHHHGDhTDAD$M<$MHAG IL$I$AG<w <<IcL><&AG P CLH1AW 9~!It HtHHD$ HD$H֍ Hc1LH`7FLH菼9LH=,IGHP(LH詌IGHP!븃MD AG HE1HL[]A\A]A^A_AUATIUSHAPHv`Hu @kU1Lc`'XLktHsHC`L)Hs(HtҸZ[]A\A]AUATE1USHQHoEULmXLHA'HI9tHE`DZ[]A\A]AWAVAUATUSHHo}UFEUH7-IHcH>HcEH HHH]HH5% ^]UH$HH8N1H]@1zxHH|$kH|$H5$H@H$yH$HAUATUSHH $HH $H8dH%(H$( 1Hl$IIH|LHzLLHMHHD$H{HH$( dH+%(tONH8 []A\A]USHH $HH $H8dH%(H$( 1Hl$HH"| HzHٺ H+MHD$H= tHzH$( dH+%(tMH8 []SHW9t F9u1t-HcC =~CHK TH;LC1[AWAVAUATUSHH $HH $HHT$Lt$IILdH%(H$8 1.{ L$yLIM1LHT$HcLÃt HT$tAHH uϽ L1KHl$(Hl$(t uD$u0 u+H;l$ r LxHD$(HPHT$(HT$ Ly tLYHH$8 dH+%(t(LHH []A\A]A^A_UH5!HHzN1H]@1EuUHSHRN1H]@1uAU1ATUHSV~1ɾHH,I~HIe1HMLLNH -HHKHuYL[H1]A\A]tZ[]A\A]UH H߀H8gKH]tATUHPuHITYLH]A\AUIATIUHSHAPHHHXMtHMTLعH_XL[H]A\A]_ATAUHSSHpHc YDHo[H:SSH[H5]A\ZHH|$H|$1HATUHSi1HH OI}H HcG1LHHk L1[H]A\@1rATUHSH HH1I1}1ҾHHc~LHH0Lt[H1]1A\rLdJHHW[]A\HH|$tH|$HktH|$HuLW$Hx H5[t H5TvWHSHH|$tHHH/HCJH|$HHuH11[qH[HHH|$}H|$Hxu H5VHH51WHAUAATE1USHQLHHcKHUHfJEtt,HcS ~CJAĉK DH;FCZD[]A\A]AWAVAUATIUHSHdH%(H$1OLAoIAuLDkHAAuHHArADA݉D$ D;l$ ~EuDHPuTDH{HHu1L)KLA\I11HyUAAELH1DHy8*uHSA!AM!v AEރ HcH> HH Hu5Hu& A[5A~HH}@HHPHHtHGHPHWEOH}@HHPHHtHGHPHWE- H}@HHPHHtHGHPHWsE[t IhHsHEHH@x1HHEHH@LHH}@HHPHHtHGHPHWEEHwH…xLHqH5 %7H}@HHPHHtHGHPHWE=HQUH}@HHPHHtHGHPHWDE=H<HDEH}@HHPHHtHGHPHWE=HK>HH}@HHPHHtHGHPHWE/HZ[H}@HHPHHtHGHPHWJE=HH}@HHPHHtHGHPHWE:H HDH}@HHPHHtHGHPHWEHbH\LH}@HHPHHHGHPHWD DeAzA[iA iAuA9\t t" t!H5K H%AAD$iH{ HcH>AA"A'A *A A A A HcHAUAHEHHhHuH}@HHPHHtHGHPHW"E1{H_@HAHLcuHH}@HHPHHtHGHPHW8ǍG}Ht/"IA1HHHII@1}HH@H}@HHPHHtHGHPHWBEHEHMcLL)xL|$L#)HcHcIDžA7HHL$IHL$HHA 3HEHHHH}@HHPHHtHGHPHWEUBHN t uHAHHE1McB4#E1uFHtFEk HFd&H}@HHPHHtHGHPHWAljEAu1AHMc@HHEHL)x:AA H}@HHPHHtHGHPHWEHEHDHHHEIH8H}@HHPHHtHGHPHW_EHDH}@HHPHHtHGHPHW#EHEHHHXH0HSH.IA%{H.H}@HHPHHtHGHPHWE.Ht.H|EAEHmHHD$dH+%(H(LH[]A\A]A^A_AEL%'HAtuuHH}@HHPHHtHGHPHWEHAuHEHHA$HPH0IxuU@ tMDDH}@HHPHHtHGHPHWEA!AAHD$dH+%(t ,H(D[]A\A]A^A_USHPHH~8DHV@HN`FFp.F !HF0HFH5`HkHH{8 HChHUHu HEHCHH@ Z[]G !SHGtG G !G HwC[SHw(HC [f/[r Yf/v H,99HH|$Z_Y-H|$9HHH|$'_YH|$Q9HHH|$^*-H|$!9HHH|$^.H|$8HHH|$^-H|$8HPl^H,(.1ZATUHSH@,HH*Y D$m2tt8u[D$HJ8HA^HH@H^HIo^HI9~/HHH51[]A\PHHQMy&HLH9}HH[QL)HH*XIYD$H,L7H[]A\AUATUHSQe1H`HAP/AŻAD9D޹H3DEDH2Z[]A\A]AUATUHSQ0HHA|P/AŻAD9DH]3DEDH1Z[]A\A]UHH+\H$1 $ ((]H $[f. $(z u (S)-(T$S(T$$(@( $^(H5H]UHSP&\HH\1HH9@+8Z[]UHSH1tkH0tZ1ҾH)3HH@HwHuHHN11ҾH2HHHH-53HZHD$ZL$B'H4H[]HH|$|Z*H|$4HHH|$LZ'H|$y4HUHHZHD$iZT$((l(H%4H]HH|$YM)H|$3HHH|$Y&H|$3HUH.Hu+)/H5@u H5H3 PHK3]UH.Ht[-X(HQ]UHH.Ht -WUX$Wf/$$v( (HD$$D$f.zWt  $\(H2H]UH .Ht,$X'H]UHHdH%(HD$1HT$/|$t HH,2HaOH1HD$dH+%(tR#H]UHY-t#1H/HHHHH1HVWTjH1]UH^H1z61H5H[H21H;H7H1HH7HH1HH7HH?0HHk7]PXH5P12AWIAVIAUIATE1HULESHAPHoH}UHu4Ht/LH}HLLUHu LͣL)H]Z[]A\A]A^A_DATISHARIʋ29|ED9|$DLH51vD$6A9DLIcHcLIID#Z[A\AVAUATUSHH $HH $H0dH%(H$( 1Ll$HHLNH׹H2tH5yH1HAL5LH3u5H))LM1҃HZ-HLHH1GHHg/E11ɾHߺP8H)t=H*tH߾(LuM H(IFH$( dH+%(tH0 []A\A]A^AT1ҾUHQRHIA(HعH1HL1H2,H'LH'LHX.H(E11ɾH/7H(tLH94LH 1u(H/Hl(LH3Z]A\AU1ҾL-ATUSHHdH%(H$1QHH&HHAjVHLn0H߅t&z&H'H$HV3HH"-LH;3.HAHHtHPH)HH,HH3HLl$O'LH`uH5H1D%LH5Hxt׃Ha'uȾH߽&H:H%A9|>H&u+H&H&E111ҾH 5H$dH+%(tHĘ[]A\A]UHOH0u'1H90H"&H3HعY/HH11]AT1ҾUHQXOHcعHI?.LH1.uLH5@H+Z]A\AWAVAUATUSHH $HH $H8Lt$IIHdH%(H$( 1LHMIA<$tLLLH%VIL=vIA$<;uIuLE1zH;LkHHu L I,HLHL))1҃H(LLHHUHI#H#LH5HHu>LHH5 1l*H߾#H߾C#L H.H$( dH+%(tfH8 L[]A\A]A^A_AU1HlATUHHM1ɾHHHD$|M1ҾHI1M1ҾHIMLD$LLHHIMuH=(H"H]A\A]AWL=AVILAUIعATUH,LH+HQ'HI"MA>*LEIHuHH>(LعH@,LH5*H"LH'.H,OHHP/Hb!A>*uH)4LL?HHuHH' 1H)1]A\A]A^A_AT1ҾUHSsK1ҾHIaKLHHøt;H&H HpHH5HE'[]A\AVH OL5JAUIHHvATUHS\R-HIHt;HLHHL)M&LHH13'LHHu*LcLLH1 '[LHH]A\A]A^[]A\A]A^UHSQyMHH~5HھHH*H$H<HZ1[]AWIAVIAUMATUHHSAQIHuLIHu LH%}HعH(HF#HuH HLHPLHHHPHHXL[H]A\A]A^A_G+AT1IUHH"H1ҾHD$"LD$LHHHH5V1]A\ =AVI׹AUIATUHQ'1҃H}"IHuLH5@H1a'HعHV`KHH9'HعH8KHH'Hع$HQHH5mJH7Z[]A\A]IHHʃ wbH HcH>HLH)GHAHL¦HLyH!&H !H1HHHئHH1HSH_HCHGDH@@C[à whHzHcH>X\Y^=^tWHL$}L$W(Yf/v XWH1wv t Ƀ1ҁvH8AWIAVMAUAATIUHSH(dH%(HD$B V u HEHD$Ht$HZA|$u I$HD$Ht$Lś2HL$HT$DLAFI@u ED$Ht$HA|$uA$D$Ht$L趚L$D$DAFAu"A\$u*I $HUDL*Ihu ED$Ht$HBtKA|$uA$D$Ht$Lt$L$D$D[AA^3HD$dH+%(u3H(EELL[HL]A\A]A^A_&HD$dH+%(t H([]A\A]A^A_GHHtGà GATHL%UHSHHdH%(HD$1ADtH-u HA E1+uH90uH@@CHD$8dH+%(t HH[]A\A]HHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$H$HD$HD$ D$0HD$HT$dH+%(tb HAWIAVL5AUATE1UHSHHHdH%(HD$81%LH HIHE0H+EH  HLLHL)AUd,U%I ct`psstf/w ЃHC HCHPHSL8MuL=hL1 Hc/w ЃHC HCHPHSH PT$ҍBHtHt$HzH5H1dHuHFHE/w ЃHC HCHPHSHc/HuHFHE/w ЃHC HCHPHSHHF@HuSHFHEwЃHCS HCHPHSFHE/w ЃHC HCHPHSLL|$(LL1 HcL/w ЃHC HCHPHSH0L\$LdHcI)IsH5%H5H1譅AM}KH+EH HL1LHHBEt At$HHEH@H HT$8dH+%(tHH[]A\A]A^A_AVIHAUATIUHSHIŊE<=uHuL9v"IL$LCD&<@u4L9w HuLHIL$fA..IH)AF.LHtr HII AF"H[string IVL9sHuLHH*HtH)IM9LLHIFf..HG.f"]G[]A\A]A^AT11ҾUHPV9H HHI9HLH<HHZ]A\AT1ҾUHP81HI8LH 1YH]A\@1.AT1ҾUHPu8HI 1YLH]A\@.U1ҾH?8HWHH ]USHQuH1@1ҾH<:žH{tH6HtZ1[]U11HSV7HHwHHtY[]<.oZ[]ATUHP+9HI9LHWHZ]A\ATIHcHH|$H|$HLA\$HH|$eH|$H*^?HATH5aUHH8dH%(HD$(1Ld$LrLtLHwH5H1*HT$(dH+%(t&H8]A\ATIUHSHHdH%(HD$1!HT$HD|$uuLH5H1!*þHe HT$dH+%(tH[]A\UHSHHdH%(HD$81:  1HB5H 1H5PH 1H5H$ H5,HD$H53HD$H5HD$ H5HȉD$HH-lD$t HaH2 H\$ 3HHHu HD$8dH+%(tFHH[]AWAVAUATUSHH $HH $HX1ɾH9dH%(H$H!1HM4HI  1  H5HD$A<$!Ht$ H|$u IHHHu HFH5L 1HH5nHASH5<H/SH5NHS H5YH CH5/HPCH5 HlCH5HPCH5 HPs wHHHVLl$XHƄ$| %L-A$*Mt$<%t8HD$`H9D$hr Lo+HD$hHPHT$hHT$XA $ L=AL$tkI?L$9HtWL$I$} ?uƄ$~ Mt$lAL$t+L$L$Ht$~ Mt$Ƅ$ 8IHbL9xLH5H1DHH&L$ H$| HLLLH+MLd+H$H!dH+%(tHX![]A\A]A^A_UH9H 1H1H56]HGw4HcHH@XHHpHHBPÈVG:FHGH@XP(@FF HGVHHw9wu PZ1AWIAVAAUEATUHSHAQDfD9f %HV H8H6L \AHHU0IcHkHL8Dp R:DhPAD$CZD[]A\A]A^A_9~`AUILATAUSHPHGHh8HP(tH5H1IH5HDL1|H{HAWL AVIAUIպATUSHQH/LD;DeAwcE9}'C;HHEXA}@AUL0P E uKcHCHuXHUL AHx8nMIcHEX9~HHHH0AF tHCLHHx8|C;PS;Z[]A\A]A^A_HG8H0H frfAWIAVAUATIUSRLo0H_XImAE8Du$A9~IE8HHEPL8E uG\HuPH8HU$L AM$IcHEP9~HHHH0AG tI|$8LH蚟Am8L RLLɍEfAE8CDpDA+u4D;s L !|I|$8H3HS AHHcCHHKf,BX[]A\A]A^A_HH|$H|$HHUHH}8H5H1HHt;wtPtAUAATAUHSAPsuO9]u DHDH赻DHI觻H}8ALHH5N1HHX[]A\A]Ét !AUATAHUA)HSAQPw+A\$1H؉KE~FAXsH[]A\A]JtOE~%DmuHLHC HC H}1HL>u1[]A\1ÊG:G:DtD)0W PÁ$ATt $LgALA\UHSHPH}0HIHCCZ[]AVAUATIUHH(Lo0dH%(HD$1ILNHLHLLLVRHD$dH+%(t5H(]A\A]A^AUATUHSHH(dH%(HD$1Lk0HHILuBHshHLH{0LHHHLHD$$D$QHD$dH+%(tH([]A\A]AUATUHSHcAPLmXIHkAH0IMHqD8s>HDI H5 HH}8H DL@ 1EHHwqEAEHSA9}IEADHLHLHAEX[]A\A]ATHcUHISH0HkHuXLWDN(HFIcRIHkDA9~LH^ LHHL9u5S8PvAzuE9~pDKSDH1[]A\ATUHS DgHt8H}8H56*HHEXHADHp[H]A\AUATIUHSRHG0LoXH@X A9]~.HcI$HkIEH9uAL$AT$HX[]A\A]AVAUATUSLgHLoI<$t)A|$t!mDAT$H߉ʼnCH'DA|$tDI}8H5-\)IMXLHIE0Hq 1D@ IUXLHcHkHr HCI $LpXC:HKED$D)A)FC:A9}H@s:@S P ۈCHFD$(Lm0H\$(HH}tHtHD H t$(~Lm0HkLA@HA.Ht$(LA-HHL@DL@DHLDLZ@bHH[DHS8Lm0Ht$LHH=HËE=t = H5,Lu0 H5?HE~< H52Ht H5*H`HH<=HH?,H{H*,Ht H)LAAvL=|$( u AuI$HcT$0H@8H%At$:A$LAu AuAAt$:E11LD;;H(H}0:H?mHt$0HH]0 E=t,uHt$(HHD$( 2|$0 tH5H^HHcT$8H@8H%?@HE0P:PAAA^&A<E1>AF$|ADDA=-Aw|HZHcH>AcA[ASAKACA ;A 3A+A #AAA A E1L=6AtgECwD9~ZDEHDD$ H}0DH>HL$CTwHHH $RH}0H $DDD$ AHEBHE8fHD$(dH+%(tH8D[]A\A]A^A_1ATIUHPbLHH}0L+:ZH]]A\AWAVAUATIUHSHHH_0dH%(HD$81$Ll$Ds[tZ~u{tR=%tKgHL=4LHLHL7HNLHLHL6 HLg3DHHwHD$dH+%(tH []A\A]A^AVAUATUHSH0dH%(HD$(Fv H5*诣H,ALkHt$HH\$VD$ t}Lu01Av<{ u6{9u{;|$u CSu{;|$u fsHHut(1L$L@E14,Ly-HE8H}0H DAT$Ht$H\=HLt$>HLH}0D9t#LDD9~"HE0D`HfF$`AHfF$`AHfF$`ArHfF$`AYHfF$`AzCHfF$`Ag0HfF$`A QHfF$`A;HfF$`A(HfF$`AEAED9HDXu EAEDZ[A\AUATAUHSQ~^u(HE1 FV<%u Lnu7LHNH9r%-uLnI9s9|F9| 9t IAZD[]A\A]U1H1HHH1HH5s ]AWAVAUATUSHH $HH $HHL=JdH%(H$8 1HLl$jLHLcD$LIĉ9l$|8H߉t$ IHtt$ LHH$L$ED,HLLH$8 dH+%(tWHH []A\A]A^A_AVAUATIUHS LHH|LD7ILDtD[]A\A]A^AWAVAUATUSHH $HH $HdH%(H$ 1HLd$H?HT$8HD$LHIHD$8HD$ L;t$ A>%Mnt,HD$PH9D$Xr LsHD$XHPHT$XA6A~%u H _HcH>A A$A$A$E1A$AA$A$A$A$AA$뤺A$뤺A$AoLaA$AuVH}H5@1HBA$A2GGH}H5-1AADZ]A\AWIHAVILAUMATUHSHHdH%(HD$1/AċD$Au;I8uH}HѝHT$LHtԃ|$t͋T$~>At8E 9~D$\$D{DtH}H'E!D)D!1A]HD$dH+%(t躵HD[]A\A]A^A_AV1ҾL5mAUATE1UHSH0dH%(HD$(1Hl$HD$HHD$ HD$8tjHL$HT$LH|$LD$ \$ \$AHc۸H)L9sLHLAIAwHH+LHHD$(dH+%(t´H0[]A\A]A^ɉu1LHH9t HAHc1LDLHH)H9t HAW1ҾAVAUATUHSHxdH%(HD$h1lHT$(HHD$ ULl$(HILH^HXH9\$(sHH(HHl$0E1HD$8HD$ 8AGD$HL$HT$ HH|$0LD$Lct$HcL$Hډ$J1MHrH;T$(vHHHL$HL$HHH<$ $HHcH>D|$D$T$8I4HDAHHL$8I4H|$@D(Au D$@ZD$@HII4LHmuT$8DI4E1HL,IK.H;D$(vHHI4LHLL"M<L#LHLcLJ\+D|$LVHsHHD$hdH+%(tD$Hx[]A\A]A^A_AWAVAUATUSHH $HH $H1ҾE1AdH%(H$ 1HLl$hHH\$0HD$ HHD$8LHHD$ 8HT$ LHL$H|$0LD$Lcd$‹D$DHIƋD$HL$~:HD$pH9D$xrLT$"T$HD$xHHHL$xHL$hAohH }HcH>HIA1B HHHL9I9|HӘHMI?A|$)u IT$IT$HHHHHH| HtЅyH{ H5@1HHLHHL,HI+E0IE8HHIE8IT$H9|H9k1AT$btB< NftoDIT$HH9rH{ H51AL$8MuED$H{HUH9s@uA8uuHMl$M@8uHA|$[M|$tH{ H5|1{HL 1IH9kt}MeLL}LLuBσ0t;C(}HcHH|8uH{ 0H5g1HHSHHH)Lh8I9Hx0LH׫LMl$LHRL{LHHILAMu?ZLHLI-*t7+H)?IHuHLHHl$E1I4.LLLvtIIHD$LHI4HHuRIsIM}LLHoHHu*H{LLLyIHHHH[]A\A]A^A_AWAVAUATUHSHxt$HT$(dH%(H$h1HT$0HH Ld$(HIELHH~"IHD$(HL9}HA|$ HCLt$0u6E1K|%H5ӑH|$.HH|$MdM9sLd$(JL;Mt}IM)M9sIEIIHD$M)MXAuLLHHLD$HD$0HPHD$(HD$D$D$vHLlH$xL:|$^u HD$HL$8HD$0Ll$hD$HHHl$PHD$XHD$HD$HD$8HD$`H\$(H9\$HT$Lt$HHD$pLHHHD$|$Ld$ht;|$uVLHHLE11ɺLqJ1LHHL*(HT$@LE1 HD$ L;t$@wHD$ N<0A?%u:蝨HL$ IHN<1ADPuc%t%H5gL1H$H9$rH$xH$HPH$H$xA j0uHH$xHH)(MHH|$HH11҃L LLƫH$xILƯu L蕫HHLH)蚱8LIu)L脬L蜬H5sLH1H$x HtH9rRH9l$XvYH$H9$rH$x}H$HHPH$H$xM H݀|$^SHT$XL$xHLH)L*Ht$L螰H$"dH+%(tءHĨ"[]A\A]A^A_AW׹AVAUATUHSHXdH%(H$H1HT$L|${HT$ֹHHf1ҾչHIHD$Hl$8D$HH\$ HD$(HD$LHD$0萭L$L9d$(rfLLLD$@IHtCHH)I9uHH螯չH2H膩LLL$I1H$HdH+%(t褠HX[]A\A]A^A_UkHXH1!H1H5-]4H11HH5{HשHcHĨH谩HH0k=H薨]ATUHSHHdH%(HD$F?& tUO #O Hw#EHHHH|$ΠY,D$D$yuD$\$K HD$Hc{L&A|$ uAT$ It$I|$ ]AD$ AD$ K HU#B H91HEHH#K 1HEHHHCHT$dH+%(tcH[]A\1u%H?HWHwSHH[AUATIUSHQBIuHHBH=w9V skHL H1HuH.u} u#C@tHH9EuAD$ I+l$HD("HcEuH5rLHH1AL$ H9v'It$HH~tHCC8)AL$ 9~&HIT$ztJ S1Z[]A\A]P8GBHH@(HPf@ @ H@HP ZATHIUHRHvH9tM 1HcHzU HuL1HxzXHL]1ɺ8A\bzG HNHH9sHGHHDO !HHHGxuH;PtHcHt HHHzO #F HHHGxDuH9ptHcPt HHHzUHSHF?tthucH6SH6H[]|H|$( $; $H|$f.z*u(f/ qurouf/vH,H[]HMH1HsH+tHHcCt HHHyH[]SIIHLHH dH%(HD$1_HyH9uHt$HT$LLD$8HD$dH+%(tH [AWAAVAUAATUHSHHF Df LvD$A9s?HvDHH.xK HCHHHHA9v @D{ EuH+E1HCsD~H5̅H1A11AHD$ IcD,$HwDT$ 1HCH@H @@9$uEDS ILCLC E9v^ED{ AIMHKLytLHHL$GL$IIAWA9wHsDLHH wHCL$AAE|$McIO,&Ex'A}tIUHHAEAI HI9tHLLH[1]A\A]A^A_vH[]A\A]A^A_1HH9Ft N AWAVAUIATUSHdH%(H$Bu H5(HIԃuc f.{H516(L$țL$f.z1u/f/ rr%rf/vH,D$0Ld$(HD$(LHxHuHЃH9HELu I9vM~A~L} uJHt$81 DM HIL$1HA9s A9r9EAE1D9wJHHMytADHDI9uM AE1A1AVMcItGH}I Lt2HT$DD$L$Ht$\DD$L$T$Ht$ALE43KE11D1ҾAAD9v!EEt DD9DGGI9t)DHLLHLHsHDH9HcPHHHH9uLH)HAAV[A^{tHL)HAFCCI$HCAD$C@tE tI$@ t HL:H,HcCtHHL)HAFLH)HCLH$dH+%(tLH[]A\A]A^A_AUIATIUHHH[HtH9uLHL]A\A]]A\A]DG Et;HwA@H|u(1D)ƒvAJH|EDDEHHՀH9GteD3xt/A?vADxtAA@EEDD)vGADxEEEDDATIHcҾSHH|$AT$ID$H|$HHcӾ[A\AWAVAUATE1UHSHHHHHD$HIxAF$HHHɻH;\$H^HKuHIL=HL=˥HDHuDHL5\L5HL$H)L9}4H HL$HAHL$DHIT AHL$Hs3HD I)HD$HھHAITDHAHH;\$uDH4H[]A\A]A^A_AUATUHSQHLcDLMH2~LHlILH辠HHIZ[]A\A]AUAATAUHH袛uHDDH]A\A]HRAt$HEAuH9E11ɺH蚩H>HD$ D$ H]A\A]AWAVAUAATAUHSHH8E9McHLUIcľHHHD$UHtDDHH H聙DD)D$ ICD%HߙHHHD$IULHUHDu4HHT$HUHVtDDHH HԘ|$ Ic־HUH詙AD$H߉D$HHHD$ UAL$DHHIGEHD$D$D$ HT$HEwUHt-E9H5 |H1ضH HD$EHcD$ HHD$(L$ HT$(HUHCt,D;l$ |H5{H1tH輗HL$(D;t$ ~[H街HT$ HUHT$HUT$DHHDDAWD)D)9}EAL$ DHHXDHHE,AH8[]A\A]A^A_UHSHRHHF`tlH5rYHHt HHH5zH ĜH輠t HHCH腖H;tH{u4HH;u HHH{u HHCX[]AVAUATUHSH dH%(HD$1Ht$HHL`ߕudH%HH~I9}HyHRLt$I9~'Ml$HLT$LHAMI-HD$dH+%(u1fA.$E8A$9I$I9EHD$dH+%(I4$I}H [A\A]馠HI;$HHxHu I$HxIG uHCH HurHI;$HHx(HuI$Hx(Hu$qG uHCH cHu"G uIHCH AHt/LCLHALHHCPt u 8u1HT$dH+%(tPmH [A\A]AWAVAUAATUHSHH]CwCt.uHsHaHsHSAHHWHCHPCHu AHsH`t LsA!HCHxuCCAHLMcHHD$E9~YAvu1I6IIHH)HvH9wH5\H1]uLHHT$0`HT$HEHH.E1IIcHkHH0MHLLNH LLAuLHH+\$dH@@CAD$A)ŸL)HHEAZH[]A\A]A^A_AUATIUSHASBtEHuVL*I}(Hu LHH,G uHEHHHuCHH@HCX[]A\A]LxHuHZLH%AZIL[LHA]A\A]HBHHHwHHu!PH5Z1HHH1yHHHBHHw1Hu$PH5vZ1HHHHtH1yHHH1HyH|HHH?HHAUATSHLg ID$(IT$ X؃?)4w8u(!)H H5ZHc H> HG@HHHHOHODiEtAAu E1yAHHO!u HHֺxuAD9txID$(pHOHHqIHHH)IHA~HwDH|$H|$HGPHI\$ t ID$HGH[A\A]AWAVAUATUHSHhH_ dH%(HD$X1HHH$H@Lh0Lc HC(HPDHS( t#ttHDD$Lc DD$DD?DHHHL$M4 -wH &YHcH>AIC$A&tAIClA.]HC(HPHS(HAtA69DAFAAHC(AIAFAsH$AJD H8A>DDAs HL HLH $HD LH07DAs HL HLADHLLH,UDAs HL HLDEy HLHLH<$HD H0H$AA&Jt H @@HVH9H= DAs HL HLDEy HLHLLHJqEAHAADD$DD$AFEIIDD DQUDD$EUL$LH|DDHLA.AnsHLsHLaEAEy EIMIMEAAs EIMAIMABuAuIIu AD$HLHt$HLT$mLT$t@Au AD$PHt$PLLT$>LT$tD$HXD$PA<EAEy EIMIMEAAs EIMAIMABuAu(II+IAFu AD$HLHt$HLT$LT$tMAu AD$PHt$PLLT$WLT$tD$H\D$PAFAAHEAEy EIMIMEAAs EIMAIMABuAuIIu AD$HLHt$HLT$LT$t@Au AD$PHt$PLLT$mLT$tD$HYD$PAkEAEy EIMIMDAsHIT %HIAu AD$HHt$HLHT$HT$t>zu D$PHHt$PHT$HT$tD$H^D$PQA EAEy EIMIMDAsHIT %HIAu IHD$HHt$HLHT$HT$t:zu HHD$PHHt$PHT$HT$tHD$HH#D$P A LSEAEy EIMIMDAsHIT %HIAu IHD$HHt$HLHT$HT$t:zu HHD$PHHt$PHT$HT$tHD$HH D$PdA?EAEy EIMIMDAsHIT %HIAu IHD$HHt$HLHT$@HT$t:zu HHD$PHHt$PHT$HT$tHD$HH3D$PAEAEy EIMIMDAsHIT %HIAu IHD$HHt$HLHT$HT$t5zu HHD$PHHt$PHT$\HT$t Ht$PAEAEy EIMIMDAsHIT %HIAu IHD$HHt$HLHT$HT$tBzu HHD$PHHt$PHT$HT$tHt$PHH|$H6AEAEy EIMIMEAAs EIMAIMABuAu%II2H@u AD$HLHt$HLT$ULT$tiAu AD$PHt$PLLT$<$t:L$PD$HL$1^L$W(Yf/XA LLLYEAEy EIMIMEAAs EIMAIMABuAu%II2Hu AD$HLHt$HLT$?LT$tEAu AD$PHt$PLLT$LT$tD$H^D$P`A EAEy EIMIMDAsHIT %HIAu AD$HHt$HLHT$xHT$tCzu D$PHHt$PHT$KHT$tL$PD$HZA MAEIMAGu IHEu AD$PHt$PLtD$PWZ:ACAEIMAu IHD$PHt$PL.t HD$PHALLLH:AIMAPt1u 1A8AAFALHDHLEAHAAA@E)IHApHLHEHC HT$HMHL0Hy2~H9rHBHEHHLc Et HC HL$HDD$Ht$DD$AAMcILC(5DEy @HLHLDAs HL HLH DAs HL HLDEy @HLHLHMDAs HL HLDEy @HLHLHfD9HC(tH7D D%tHS HHHHtHC(AJHC(AAFtt1u 1A>‰tȸu 1A>HS(t HHS(D:kDHLAPtt1u1Ƀ8tʺu1҃8ƒHK(t HHK(;8A>D9D%tHS HHHHtAJEAAAAtEIMLEDLHUtAJH] KBAtEIMLELH|Lm H$MuI]IL#HRDz HPIM} z ~ Hs H1I I9vAAHIU IE(L)LHS HUL)ILeLcKB HC(H] AtEIKDHEH$H@x ~ LHLHCB9H] HCHEA~IF u%IINHH~ H9H9fHnWAAVf/Xvf/f/4AJHC(AFAF8AAN0A~I~A~(M~ Ht$8DD$H|$LH?zH|$DD$tInA~uAFD$P"Ht$PDD$H|$H|$DD$t\L$PWf/v (?/I?I(4I?fD$8Et1HT$8I+F AFIIVAFA~uAFD$H!Ht$HDD$*DD$u H5DLD$HA~(AFAFuAF D$P+Ht$PI~ DD$DD$uH5[DH/L$PA~AF(AN u AD$@0Ht$@LDD$L$L$DD$u H5DD$@AF\AAJHC(Af AnDHA6IF`Iv0AfPAn@Av0HE'HCLc HEHC(DHPHS(EAEIO4 A~HC(A~AJA>HC(xEAAAuLEM)IAEuHC(HPD8HS(AAIAk2L$B9P sHHDD$HD$HD$DD$McLHI΋L$B9E~GHLHHD$QAF@HD$t@ tIB tHH HD$IIHCHEH$AH@H@@NH;uHPt,HHKHHsHI9IFHI)H)HCHL[]A\UHSQLFI9s% H6H9HCLHH,H]HEHEZ[]AT1ҾUHQ詁HI^Nt#H\LH1H57@ ^HY_Z]A\AU1ҾATUHH1ҾHI6LH5@HHI1]1҃HZHMt#HD\LH1H5?v]H^]A\A]ATUL$HH $L9uH@dH%(H$@1Ld$HLMILMt%t \u/HLHG\1H$@dH+%(tMH@]A\P1 ^ZU1ҾHHdH%(H$18tHt$HL1u t$ @H]H$dH+%(toLHĠ]HdH%(H$1Ht$YLT$ @ H$dH+%(tLHĨU1ҾH#HH]]AV1ҾAUIATUS~ I"N/LHLHtJIHM)I~MLLHHE9JLB0LKI<H)MHsHEH8MH5HHE6JLKHxMLHEHJH}JHLHE>\[]A\A]A^UXH8HHtKH}8IH}/IH'I1]HH|$XH|$HpHYHATUHHdH%(H$1?XH5w<HHHHP1HY1҃H!WHIRHt$L+JA1Eu!D$ 1H%=@[H$dH+%(tIHĨ]A\UHSQWH8HHu 1>x.uH; MHCHuH{1HpJuھHZZ[]AT1ҾUHQq|HIAHt#HWLH1H5H;XHZZ]A\AWAVL5!AUAATUHSQHdQD9DHR1DH{Iľ;LH:LIHHMtHtL9IG HtLHLHL)W LHiWHQLHSWHQH%d1҃HUHtHP%HPHt Lc-A1Z[]A\A]A^A_AT1ҾUHQzHIeGt#HVLH1H594WHXZ]A\AT1ҾUHSHdH%(H$1VzHt$HI6GteHUEt u/LH5a9H1V/LH5f9H1VLH5^9H1sVe11HTZH5g9HUHt$`H.UH[H5/HUH*D$8HTHj[H$dH+%(t0FHĠ[]A\U1HH dH%(HD$1H|$zF1uHit$@BH+HHt$HTHD$dH+%(tEH ]HcHF7HHH9uAV11ҾAUIATUHHdH%(HD$81Ld$xHts1HHI 1LHHL/ LHxHu LH[Ha LH>AH5H=7FLHIDLHAdDD$Hl$&H {7HAPD$PD$PD$&PD$-PD$4PD$;PD$BPD$IPD$PPD$WPD$^PD$ePD$lPDL$s1DD$rHHpHL;SHD$8dH+%(tDHHD]A\A]A^ATUL$HH $L9uH1҃dH%(H$@1HLd$vL@HLHRH$@dH+%(twCH@]A\AUATUL$HH $L9uH1ҾdH%(H$@1HLl$Jv1҃HI:vL@LHLHRH$@dH+%(tBH@]A\A]1t$8wHHAUATUH1SQHHHcLl3HLcEuCHHt4BLcJ<#H1L9/@ƀ\ADuHH)9u ug/H_u}.u0Ru)}.u#}.uHH9s ?/u/f/H{$H9v/t/H H9v HHI9w€8HhtHRH9v /uHL9s  H9wGHZH[]A\A]AWAVAUATUSL$HH $L9uHdH%(H$1Hcك>$IHu&1A HD9LHLl$?L$@L9?LLI&fA/1f/ALA: u/tu fE.HEsH‰HHcHIAMt/uHHH9s f..@/HIIA$H9st HIĈPx/uHH9s@HH$dH+%(t@H[]A\A]A^A_U1҃HsHtHP]AVI=AUATILUSHdH%(H$1Ll$?Ht4HHøLL)L9OHcHZBD,HsLL_BH5LTNLLmTH$dH+%(t?H[]A\A]A^U1HHwH5P{H1H?H58{1HHH5 {HH51MH5G3H;S-4HMHH51SHH51MHH52RHH52eMHH52RHH52GMHH52R1]AWL=2AVAUI1ATA1UHSHQ11HQA9HcIt (...tail calls...)Sl%s:%d: bad argument #%d (%s)calling '%s' on bad self (%s)bad argument #%d to '%s' (%s)signalexit__namestack overflow (%s)value expectedbuffer too large=stdin@%srbreopenlight userdata%s expected, got %sinvalid option '%s'number has no integer representationobject length is not an integertruefalse__tostring%I%s: %pname conflict for module '%s'too many upvaluescore and library have incompatible numeric typesmultiple Lua VMs detectedversion mismatch: app. needs %f, Lua core provides %fp@index out of range__indexnil or table expected__metatablecannot change a protected metatabletable or string expected'tostring' must return a string to 'print' too many nested functionsreader function must return a stringcollectbt=(load)assertion failed!__pairsbase out of range _GLua 5.3stoprestartcountstepsetpausesetstepmulisrunningassertcollectgarbagedofilegetmetatableipairsloadfileprintrawequalrawlenrawgetrawsetselectsetmetatabletonumberxpcall P?library 'bit32' has been deprecatedconstantscontrol structure too longopcodesfunction or expression too complexoӆ &&&&ʐʐHHHHHHHHHHHH[[[kkkYtoo many arguments to resumecannot resume dead coroutinetoo many results to resumethread expectedsuspendednormaldeadcreatestatuswrapyieldisyieldable invalid upvalue indexLua function expectedlua_debug> cont =(debug command)level out of range__modeexternal hookflnStu>%sinvalid optionsourceshort_srclastlinedefinedcurrentlinenupsnparamsisvarargnamewhatistailcallactivelinesfuncreturntail calldebuggetuservaluegethookgetinfogetlocalgetregistrygetupvalueupvaluejoinupvalueidsetuservaluesethooksetlocalsetupvaluetraceback(*temporary)(*vararg)fieldconstantglobal_ENV (%s '%s')=?Cfor iteratormetamethod=[C]%s:%d: %sattempt to %s a %s value%sconcatenatenumber%s has no integer representationattempt to compare two %s valuesattempt to compare %s with %s:ccۣUUcccc=<=~=<<>>:: $eeeeeeeeeeo-wrong number of argumentsinterval is emptyinterval too largefloatpihugemaxintegerminintegerabsacosasinatanceildegexptointegerfloorfmodultlogmaxminmodfradrandomseedsqrtC9RFߑ?cܥL@>?$@-DT! @memory allocation error: block too bigtoo many %s (limit is %d)searchers'package.searchers' must be a tablemodule '%s' not found:%s_NAME_M_PACKAGE'module' not called from a Lua function_PRELOAD no field package.preload['%s'] no file '%s'init_luaopen_%sLUA_NOENV;;;;error loading module '%s' from file '%s': %s'package.%s' must be a stringcpath no module '%s' in file '%s'/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.luaLUA_PATHLUA_PATH_5_3/usr/local/lib/lua/5.3/?.so;/usr/local/lib/lua/5.3/loadall.so;./?.soLUA_CPATHLUA_CPATH_5_3/ ; ? ! - configloadedpreloadmodulerequireloadlibsearchpathseeall:?DJU`ejotnN-0123456789(null)<\%d>invalid option '%%%c' to 'lua_pushfstring'`qATPP\l< 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(for index)(for limit)(for step)(for generator)(for state)(for control)'=' or 'in' expectedlabel '%s' already defined on line %dsyntax errorself or '...' expectedcannot use '...' outside a vararg functionitems in a constructorfunction arguments expectedunexpected symbol0*0000+-0*0H.000;-0000j*000000000(/66Q6Q6Q66D7Q6F6Q667%6%6%6%6%6%666%6676676   not enough memory%d-byte integer does not fit into Lua Integermalformed pattern (ends with '%%')malformed pattern (missing ']')resulting string too largevalue out of rangeno value-+ #0invalid format (repeated flags)invalid format (width or precision too long)\%d\%03dinvalid option '%%%c' to 'format'unable to dump given functionstring slice too longintegral size (%d) out of limits [1,%d]missing size for format option 'c'invalid format option '%c'invalid next option for option 'X'format asks for alignment not power of 2format result too largevariable-length formatinitial position out of stringdata string too shorttoo many resultsinteger overflowunsigned overflowwrong lengthstring length does not fit in given sizestring contains zerosinvalid capture index %%%dunfinished capturetoo many capturespattern too complexinvalid pattern capturemalformed pattern (missing arguments to '%%b')missing '[' after '%%f' in pattern^$*+?.([%-string/function/table expectedinvalid use of '%c' in replacement stringinvalid replacement value (a %s)chardumpfindgmatchgsublowerrepreverseupperpacksizeQRQQRR RRRRR&RRRR 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) local i = p:findlast(".", true) if (i) then return p:sub(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.getcommonbasedir(a, b) a = path.getdirectory(a)..'/' b = path.getdirectory(b)..'/' local idx = 0 while (true) do local tst = a:find('/', idx + 1, true) if tst then if a:sub(1,tst) == b:sub(1,tst) then idx = tst else break end else break end end local result = '' if idx > 1 then result = a:sub(1, idx - 1)-- Remove the trailing slash to be consistent with other functions. end return result 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.iscfile(fname) return path.hasextension(fname, { ".c", ".m" }) end function path.iscppfile(fname) return path.hasextension(fname, { ".cc", ".cpp", ".cxx", ".c++", ".c", ".m", ".mm" }) end function path.iscxfile(fname) return path.hasextension(fname, ".cx") end function path.isobjcfile(fname) return path.hasextension(fname, { ".m", ".mm" }) end function path.iscppheader(fname) return path.hasextension(fname, { ".h", ".hh", ".hpp", ".hxx" }) end function path.iscppmodule(fname) return path.hasextension(fname, { ".ixx", ".cppm" }) end function path.isappxmanifest(fname) return path.hasextension(fname, ".appxmanifest") end function path.isandroidbuildfile(fname) return path.getname(fname) == "AndroidManifest.xml" end function path.isnatvis(fname) return path.hasextension(fname, ".natvis") end function path.isasmfile(fname) return path.hasextension(fname, { ".asm", ".s", ".S" }) end function path.isvalafile(fname) return path.hasextension(fname, ".vala") end function path.isgresource(fname) local ending = ".gresource.xml" return ending == "" or fname:sub(-#ending) == ending end function path.isswiftfile(fname) return path.hasextension(fname, ".swift") end function path.issourcefile(fname) return path.iscfile(fname) or path.iscppfile(fname) or path.iscxfile(fname) or path.isasmfile(fname) or path.isvalafile(fname) or path.isswiftfile(fname) end function path.issourcefilevs(fname) return path.hasextension(fname, { ".cc", ".cpp", ".cxx", ".c++", ".c" }) or path.iscxfile(fname) or path.iscppmodule(fname) end function path.isobjectfile(fname) return path.hasextension(fname, { ".o", ".obj" }) end function path.isresourcefile(fname) return path.hasextension(fname, ".rc") end function path.isimagefile(fname) local extensions = { ".png" } local ext = path.getextension(fname):lower() return table.contains(extensions, ext) end function path.join(...) local arg={...} local numargs = select("#", ...) if numargs == 0 then return ""; end local allparts = {} for i = numargs, 1, -1 do local part = select(i, ...) if part and #part > 0 and part ~= "." then while part:endswith("/") do part = part:sub(1, -2) end table.insert(allparts, 1, part) if path.isabsolute(part) then break end end end return table.concat(allparts, "/") end function path.rebase(p, oldbase, newbase) p = path.getabsolute(path.join(oldbase, p)) p = path.getrelative(newbase, p) return p end function path.translate(p, sep) if (type(p) == "table") then local result = { } for _, value in ipairs(p) do table.insert(result, path.translate(value)) end return result else if (not sep) then if (os.is("windows")) then sep = "\\" else sep = "/" end end local result = p:gsub("[/\\]", sep) return result end end function path.wildcards(pattern) pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1") pattern = pattern:gsub("%*%*", "\001") pattern = pattern:gsub("%*", "\002") pattern = pattern:gsub("\001", ".*") pattern = pattern:gsub("\002", "[^/]*") return pattern end function path.trimdots(p) local changed repeat changed = true if p:startswith("./") then p = p:sub(3) elseif p:startswith("../") then p = p:sub(4) else changed = false end until not changed return p 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 string.explode(s, pattern, plain) 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 end table.insert(arr, s:sub(pos)) return arr end function string.findlast(s, pattern, plain) local curr = 0 local term = nil repeat local next, nextterm = s:find(pattern, curr + 1, plain) if (next) then curr = next term = nextterm end until (not next) if (curr > 0) then return curr, term end end function string.startswith(haystack, needle) return (haystack:find(needle, 1, true) == 1) end function string.trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) 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.icontains(t, value) for _, v in ipairs(t) do if v == value then return true end end return false 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.flatten(arr) local result = { } local function flatten(arr) for _, v in ipairs(arr) do if type(v) == "table" then flatten(v) else table.insert(result, v) end end end flatten(arr) 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.insertflat(tbl, values) if type(values) == "table" then for _, value in ipairs(values) do table.insertflat(tbl, value) end else table.insert(tbl, values) end end function table.isempty(t) return next(t) == nil end function table.join(...) local arg={...} local result = { } 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.sortedpairs(t) local keys = table.keys(t) local i = 0 table.sort(keys) return function() i = i + 1 if keys[i] == nil then return nil end return keys[i], t[keys[i]] end end function table.merge(...) local arg={...} local result = { } for _,t in ipairs(arg) do if type(t) == "table" then for k,v in pairs(t) do result[k] = v end else error("invalid value") end end return result end function table.translate(arr, translation) local result = { } for _, value in ipairs(arr) do local tvalue if type(translation) == "function" then tvalue = translation(value) else tvalue = translation[value] end if (tvalue) then table.insert(result, tvalue) end end return result end function table.reverse(arr) for i=1, math.floor(#arr / 2) do arr[i], arr[#arr - i + 1] = arr[#arr - i + 1], arr[i] end return arr end function table.arglist(arg, value) if #value > 0 then local args = {} for _, val in ipairs(value) do table.insert(args, string.format("%s %s", arg, val)) end return table.concat(args, " ") else return "" end end io.eol = "\n" io.indent = "\t" io.indentLevel = 0 local function _escaper(v) return v end _esc = _escaper function io.capture() local prev = io.captured io.captured = '' return prev end function io.endcapture(restore) local captured = io.captured io.captured = restore return captured end local builtin_open = io.open function io.open(fname, mode) if (mode) then if (mode:find("w")) then local dir = path.getdirectory(fname) ok, err = os.mkdir(dir) if (not ok) then error(err, 0) end end end return builtin_open(fname, mode) end function io.printf(msg, ...) local arg={...} if not io.eol then io.eol = "\n" end if not io.indent then io.indent = "\t" end if type(msg) == "number" then s = string.rep(io.indent, msg) .. string.format(table.unpack(arg)) else s = string.format(msg, table.unpack(arg)) end if io.captured then io.captured = io.captured .. s .. io.eol else io.write(s) io.write(io.eol) end end function io.xprintf(msg, ...) local arg = {...} for i = 1, #arg do arg[i] = io.esc(arg[i]) end io.printf(msg, unpack(arg)) end function io.esc(value) if type(value) == "table" then local result = {} local n = #value for i = 1, n do table.insert(result, io.esc(value[i])) end return result end return _esc(value or "") end function io.escaper(func) _esc = func or _escaper end _p = io.printf _x = io.xprintf premake = { } premake.platforms = { Native = { cfgsuffix = "", }, x32 = { cfgsuffix = "32", }, x64 = { cfgsuffix = "64", }, Universal = { cfgsuffix = "univ", }, Universal32 = { cfgsuffix = "univ32", }, Universal64 = { cfgsuffix = "univ64", }, PS3 = { cfgsuffix = "ps3", iscrosscompiler = true, nosharedlibs = true, namestyle = "PS3", }, WiiDev = { cfgsuffix = "wii", iscrosscompiler = true, namestyle = "PS3", }, Xbox360 = { cfgsuffix = "xbox360", iscrosscompiler = true, namestyle = "windows", }, PowerPC = { cfgsuffix = "ppc", iscrosscompiler = true, }, ARM = { cfgsuffix = "ARM", iscrosscompiler = true, }, ARM64 = { cfgsuffix = "ARM64", iscrosscompiler = true, }, Orbis = { cfgsuffix = "orbis", iscrosscompiler = true, namestyle = "Orbis", }, Durango = { cfgsuffix = "durango", iscrosscompiler = true, nosharedlibs = true, namestyle = "windows", }, TegraAndroid = { cfgsuffix = "tegraandroid", iscrosscompiler = true, namestyle = "TegraAndroid", }, NX32 = { cfgsuffix = "nx32", iscrosscompiler = true, namestyle = "NX", }, NX64 = { cfgsuffix = "nx64", iscrosscompiler = true, namestyle = "NX", }, Emscripten = { cfgsuffix = "emscripten", iscrosscompiler = true, nosharedlibs = true, namestyle = "Emscripten", }, } local builtin_dofile = dofile function dofile(fname) local oldcwd = os.getcwd() local oldfile = _SCRIPT if (not os.isfile(fname)) then local path = os.pathsearch(fname, _OPTIONS["scripts"], os.getenv("PREMAKE_PATH")) if (path) then fname = path.."/"..fname end end _SCRIPT = path.getabsolute(fname) local newcwd = path.getdirectory(_SCRIPT) os.chdir(newcwd) local a, b, c, d, e, f = builtin_dofile(_SCRIPT) _SCRIPT = oldfile os.chdir(oldcwd) return a, b, c, d, e, f end function iif(expr, trueval, falseval) if (expr) then return trueval else return falseval end end function include(fname) local dir, name = premake.findDefaultScript(fname, false) if dir ~= nil then return dofile(dir .. "/" .. name) end return nil end function printf(msg, ...) local arg={...} print(string.format(msg, table.unpack(arg))) end function typex(t) local mt = getmetatable(t) if (mt) then if (mt.__type) then return mt.__type end end return type(t) end premake.action = { } premake.action.list = { } function premake.action.add(a) local missing for _, field in ipairs({"description", "trigger"}) do if (not a[field]) then missing = field end end if (missing) then error("action needs a " .. missing, 3) end premake.action.list[a.trigger] = a end function premake.action.call(name) local a = premake.action.list[name] for sln in premake.solution.each() do if a.onsolution then a.onsolution(sln) end if sln.postsolutioncallbacks then for _,cb in ipairs(sln.postsolutioncallbacks) do cb(sln) end end for prj in premake.solution.eachproject(sln) do if a.onproject then a.onproject(prj) end if prj.postprojectcallbacks then for _,cb in ipairs(prj.postprojectcallbacks) do cb(prj) end end end end if a.execute then a.execute() end end function premake.action.current() return premake.action.get(_ACTION) end function premake.action.get(name) return premake.action.list[name] end function premake.action.each() local keys = { } for _, action in pairs(premake.action.list) do table.insert(keys, action.trigger) end table.sort(keys) local i = 0 return function() i = i + 1 return premake.action.list[keys[i]] end end function premake.action.set(name) _ACTION = name local action = premake.action.get(name) if action then _OS = action.os or _OS end end function premake.action.supports(action, feature) if not action then return false end if action.valid_languages then if table.contains(action.valid_languages, feature) then return true end end if action.valid_kinds then if table.contains(action.valid_kinds, feature) then return true end end return false end premake.option = { } premake.option.list = { } function premake.option.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 premake.option.list[opt.trigger] = opt end function premake.option.get(name) return premake.option.list[name] end function premake.option.each() local keys = { } for _, option in pairs(premake.option.list) do table.insert(keys, option.trigger) end table.sort(keys) local i = 0 return function() i = i + 1 return premake.option.list[keys[i]] end end function premake.option.validate(values) for key, value in pairs(values) do local opt = premake.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 premake.tree = { } local tree = premake.tree function premake.tree.new(n) local t = { name = n, children = { } } return t end function premake.tree.add(tr, p, onaddfunc) if p == "." then return tr end if p == "/" then return tr end local parentnode = tree.add(tr, path.getdirectory(p), onaddfunc) local childname = path.getname(p) if childname == ".." then return parentnode end local childnode = parentnode.children[childname] if not childnode or childnode.path ~= p then childnode = tree.insert(parentnode, tree.new(childname)) childnode.path = p if onaddfunc then onaddfunc(childnode) end end return childnode end function premake.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 premake.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 premake.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 premake.tree.sort(tr) tree.traverse(tr, { onnode = function(node) table.sort(node.children, function(a,b) return a.name < b.name end) end }, true) end function premake.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 premake.solution = { } premake.solution.list = { } function premake.solution.new(name) local sln = { } table.insert(premake.solution.list, sln) premake.solution.list[name] = sln setmetatable(sln, { __type="solution" }) sln.name = name sln.basedir = os.getcwd() sln.projects = { } sln.blocks = { } sln.configurations = { } sln.groups = { } sln.importedprojects = { } return sln end function premake.solution.each() local i = 0 return function () i = i + 1 if i <= #premake.solution.list then return premake.solution.list[i] end end end function premake.solution.eachproject(sln) local i = 0 return function () i = i + 1 if (i <= #sln.projects) then return premake.solution.getproject(sln, i) end end end function premake.solution.eachgroup(sln) local i = 0 return function() i = i + 1 if(i <= #sln.groups) then return premake.solution.getgroup(sln, i) end end end function premake.solution.get(key) return premake.solution.list[key] end function premake.solution.getproject(sln, idx) local prj = sln.projects[idx] local cfg = premake.getconfig(prj) cfg.name = prj.name return cfg end function premake.solution.getgroup(sln, idx) local grp = sln.groups[idx] return grp endpremake.project = { } function premake.project.buildsourcetree(prj, allfiles) local tr = premake.tree.new(prj.name) tr.project = prj local isvpath local function onadd(node) node.isvpath = isvpath end for fcfg in premake.project.eachfile(prj, allfiles) do isvpath = (fcfg.name ~= fcfg.vpath) local node = premake.tree.add(tr, fcfg.vpath, onadd) node.cfg = fcfg end premake.tree.sort(tr) return tr end function premake.eachconfig(prj, platform) if prj.project then prj = prj.project end local cfgs = prj.solution.configurations local i = 0 return function () i = i + 1 if i <= #cfgs then return premake.getconfig(prj, cfgs[i], platform) end end end function premake.project.eachfile(prj, allfiles) if not prj.project then prj = premake.getconfig(prj) end local i = 0 local t = iif(allfiles, prj.allfiles, prj.files) local c = iif(allfiles, prj.__allfileconfigs, prj.__fileconfigs) return function () i = i + 1 if (i <= #t) then local fcfg = c[t[i]] fcfg.vpath = premake.project.getvpath(prj, fcfg.name) return fcfg end end end function premake.esc(value) if (type(value) == "table") then local result = { } for _,v in ipairs(value) do table.insert(result, premake.esc(v)) end return result else value = value:gsub('&', "&") value = value:gsub('"', """) value = value:gsub("'", "'") value = value:gsub('<', "<") value = value:gsub('>', ">") value = value:gsub('\r', " ") value = value:gsub('\n', " ") return value end end function premake.filterplatforms(sln, map, default) local result = { } local keys = { } if sln.platforms then for _, p in ipairs(sln.platforms) do if map[p] and not table.contains(keys, map[p]) then table.insert(result, p) table.insert(keys, map[p]) end end end if #result == 0 and default then table.insert(result, default) end return result end function premake.findproject(name) for sln in premake.solution.each() do for prj in premake.solution.eachproject(sln) do if (prj.name == name) then return prj end end end end function premake.findfile(prj, extension) for _, fname in ipairs(prj.files) do if fname:endswith(extension) then return fname end end end function premake.getconfig(prj, cfgname, pltname) prj = prj.project or prj if pltname == "Native" or not table.contains(prj.solution.platforms or {}, pltname) then pltname = nil end local key = (cfgname or "") if pltname then key = key .. pltname end return prj.__configs[key] end function premake.getconfigname(cfgname, platform, useshortname) if cfgname then local name = cfgname if platform and platform ~= "Native" then if useshortname then name = name .. premake.platforms[platform].cfgsuffix else name = name .. "|" .. platform end end return iif(useshortname, name:lower(), name) end end function premake.getdependencies(prj) prj = prj.project or prj local results = { } for _, cfg in pairs(prj.__configs) do for _, link in ipairs(cfg.links) do local dep = premake.findproject(link) if dep and not table.contains(results, dep) then table.insert(results, dep) end end end return results end function premake.project.getbasename(prjname, pattern) return pattern:gsub("%%%%", prjname) end function premake.project.getfilename(prj, pattern) local fname = premake.project.getbasename(prj.name, pattern) fname = path.join(prj.location, fname) return path.getrelative(os.getcwd(), fname) end function premake.getlinks(cfg, kind, part) local result = iif (part == "directory" and kind == "all", cfg.libdirs, {}) local cfgname = iif(cfg.name == cfg.project.name, "", cfg.name) local pathstyle = premake.getpathstyle(cfg) local namestyle = premake.getnamestyle(cfg) local function canlink(source, target) if (target.kind ~= "SharedLib" and target.kind ~= "StaticLib") then return false end if premake.iscppproject(source) then return premake.iscppproject(target) elseif premake.isdotnetproject(source) then return premake.isdotnetproject(target) elseif premake.isswiftproject(source) then return premake.isswiftproject(source) or premake.iscppproject(source) end end for _, link in ipairs(cfg.links) do local item local prj = premake.findproject(link) if prj and kind ~= "system" then local prjcfg = premake.getconfig(prj, cfgname, cfg.platform) if kind == "dependencies" or canlink(cfg, prjcfg) then if (part == "directory") then item = path.rebase(prjcfg.linktarget.directory, prjcfg.location, cfg.location) elseif (part == "basename") then item = prjcfg.linktarget.basename elseif (part == "fullpath") then item = path.rebase(prjcfg.linktarget.fullpath, prjcfg.location, cfg.location) elseif (part == "object") then item = prjcfg end end elseif not prj and (kind == "system" or kind == "all") then if (part == "directory") then item = path.getdirectory(link) elseif (part == "fullpath") then item = link if namestyle == "windows" then if premake.iscppproject(cfg) then item = item .. ".lib" elseif premake.isdotnetproject(cfg) then item = item .. ".dll" end end elseif part == "name" then item = path.getname(link) elseif part == "basename" then item = path.getbasename(link) else item = link end if item:find("/", nil, true) then item = path.getrelative(cfg.project.location, item) end end if item then if pathstyle == "windows" and part ~= "object" then item = path.translate(item, "\\") end if not table.contains(result, item) then table.insert(result, item) end end end return result end function premake.getnamestyle(cfg) return premake.platforms[cfg.platform].namestyle or premake.gettool(cfg).namestyle or "posix" end function premake.getpathstyle(cfg) if premake.action.current().os == "windows" then return "windows" else return "posix" end end function premake.gettarget(cfg, direction, pathstyle, namestyle, system) if system == "bsd" then system = "linux" end local kind = cfg.kind if premake.iscppproject(cfg) or premake.isvalaproject(cfg) then if (namestyle == "windows" or system == "windows") and kind == "SharedLib" and direction == "link" and not cfg.flags.NoImportLib then kind = "StaticLib" end if namestyle == "posix" and system == "windows" and kind ~= "StaticLib" then namestyle = "windows" end end local field = "build" if direction == "link" and cfg.kind == "SharedLib" then field = "implib" end local name = cfg[field.."name"] or cfg.targetname or cfg.project.name local dir = cfg[field.."dir"] or cfg.targetdir or path.getrelative(cfg.location, cfg.basedir) local subdir = cfg[field.."subdir"] or cfg.targetsubdir or "." local prefix = "" local suffix = "" local ext = "" local bundlepath, bundlename dir = path.join(dir, subdir) if namestyle == "windows" then if kind == "ConsoleApp" or kind == "WindowedApp" then ext = ".exe" elseif kind == "SharedLib" then ext = ".dll" elseif kind == "StaticLib" then ext = ".lib" end elseif namestyle == "posix" then if kind == "WindowedApp" and system == "macosx" and not cfg.options.SkipBundling then bundlename = name .. ".app" bundlepath = path.join(dir, bundlename) dir = path.join(bundlepath, "Contents/MacOS") elseif (kind == "ConsoleApp" or kind == "WindowedApp") and system == "os2" then ext = ".exe" elseif kind == "SharedLib" then prefix = "lib" ext = iif(system == "macosx", ".dylib", ".so") elseif kind == "StaticLib" then prefix = "lib" ext = ".a" end elseif namestyle == "PS3" then if kind == "ConsoleApp" or kind == "WindowedApp" then ext = ".elf" elseif kind == "StaticLib" then prefix = "lib" ext = ".a" end elseif namestyle == "Orbis" then if kind == "ConsoleApp" or kind == "WindowedApp" then ext = ".elf" elseif kind == "StaticLib" then prefix = "lib" ext = ".a" elseif kind == "SharedLib" then ext = ".prx" end elseif namestyle == "TegraAndroid" then if kind == "ConsoleApp" or kind == "WindowedApp" or kind == "SharedLib" then prefix = "lib" ext = ".so" elseif kind == "StaticLib" then prefix = "lib" ext = ".a" end elseif namestyle == "NX" then if kind == "ConsoleApp" or kind == "WindowedApp" then ext = ".nspd_root" elseif kind == "StaticLib" then ext = ".a" elseif kind == "SharedLib" then ext = ".nro" end elseif namestyle == "Emscripten" then if kind == "ConsoleApp" or kind == "WindowedApp" then ext = ".html" elseif kind == "StaticLib" then ext = ".bc" elseif kind == "SharedLib" then ext = ".js" end end prefix = cfg[field.."prefix"] or cfg.targetprefix or prefix suffix = cfg[field.."suffix"] or cfg.targetsuffix or suffix ext = cfg[field.."extension"] or cfg.targetextension or ext local result = { } result.basename = name .. suffix result.name = prefix .. name .. suffix .. ext result.directory = dir result.subdirectory = subdir result.prefix = prefix result.suffix = suffix result.fullpath = path.join(result.directory, result.name) result.bundlepath = bundlepath or result.fullpath if pathstyle == "windows" then result.directory = path.translate(result.directory, "\\") result.subdirectory = path.translate(result.subdirectory, "\\") result.fullpath = path.translate(result.fullpath, "\\") end return result end function premake.gettool(prj) if premake.iscppproject(prj) then if _OPTIONS.cc then return premake[_OPTIONS.cc] end local action = premake.action.current() if action.valid_tools then return premake[action.valid_tools.cc[1]] end return premake.gcc elseif premake.isdotnetproject(prj) then return premake.dotnet elseif premake.isswiftproject(prj) then return premake.swift else return premake.valac end end function premake.project.getvpath(prj, abspath) local vpath = abspath local fname = path.getname(abspath) local max = abspath:len() - fname:len() -- First check for an exact match from the inverse vpaths if prj.inversevpaths and prj.inversevpaths[abspath] then return path.join(prj.inversevpaths[abspath], fname) end local matches = {} for replacement, patterns in pairs(prj.vpaths or {}) 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 table.insert(matches, path.join(stem, leaf)) end end end if #matches > 0 then -- for the sake of determinism, return the first alphabetically table.sort(matches) vpath = matches[1] end return path.trimdots(vpath) end function premake.hascppproject(sln) for prj in premake.solution.eachproject(sln) do if premake.iscppproject(prj) then return true end end end function premake.hasdotnetproject(sln) for prj in premake.solution.eachproject(sln) do if premake.isdotnetproject(prj) then return true end end end function premake.project.iscproject(prj) local language = prj.language or prj.solution.language return language == "C" end function premake.iscppproject(prj) local language = prj.language or prj.solution.language return (language == "C" or language == "C++") end function premake.isdotnetproject(prj) local language = prj.language or prj.solution.language return (language == "C#") end function premake.isvalaproject(prj) local language = prj.language or prj.solution.language return (language == "Vala") end function premake.isswiftproject(prj) local language = prj.language or prj.solution.language return (language == "Swift") end premake.config = { } local config = premake.config function premake.config.isdebugbuild(cfg) if cfg.flags.DebugRuntime then return true end if cfg.flags.ReleaseRuntime then return false end if cfg.flags.Optimize or cfg.flags.OptimizeSize or cfg.flags.OptimizeSpeed then return false end if not cfg.flags.Symbols then return false end return true end function premake.config.eachfile(cfg) local i = 0 local t = cfg.files return function () i = i + 1 if (i <= #t) then local fcfg = cfg.__fileconfigs[t[i]] fcfg.vpath = premake.project.getvpath(cfg.project, fcfg.name) return fcfg end end end function premake.config.isincrementallink(cfg) if cfg.kind == "StaticLib" then return false end return not config.islinkeroptimizedbuild(cfg.flags) and not cfg.flags.NoIncrementalLink end function premake.config.isoptimizedbuild(flags) return flags.Optimize or flags.OptimizeSize or flags.OptimizeSpeed end function premake.config.islinkeroptimizedbuild(flags) return config.isoptimizedbuild(flags) and not flags.NoOptimizeLink end function premake.config.iseditandcontinue(cfg) if cfg.flags.NoEditAndContinue or cfg.flags.Managed or (cfg.kind ~= "StaticLib" and not config.isincrementallink(cfg)) or config.islinkeroptimizedbuild(cfg.flags) then return false end return true end premake.bake = { } local bake = premake.bake local nocopy = { blocks = true, keywords = true, projects = true, __configs = true, } local nocascade = { makesettings = true, } local keeprelative = { basedir = true, location = true, } function premake.getactiveterms(obj) local terms = { _action = _ACTION:lower(), os = os.get() } for key, value in pairs(_OPTIONS) do if value ~= "" then table.insert(terms, value:lower()) else table.insert(terms, key:lower()) end end return terms end function premake.iskeywordmatch(keyword, terms) if keyword:startswith("not ") then return not premake.iskeywordmatch(keyword:sub(5), terms) end for _, pattern in ipairs(keyword:explode(" or ")) do for termkey, term in pairs(terms) do if term:match(pattern) == term then return termkey end end end end function premake.iskeywordsmatch(keywords, terms) local hasrequired = false for _, keyword in ipairs(keywords) do local matched = premake.iskeywordmatch(keyword, terms) if not matched then return false end if matched == "required" then hasrequired = true end end if terms.required and not hasrequired then return false else return true end end local function adjustpaths(location, obj) function adjustpathlist(list) for i, p in ipairs(list) do list[i] = path.getrelative(location, p) end end if obj.allfiles ~= nil then adjustpathlist(obj.allfiles) end for name, value in pairs(obj) do local field = premake.fields[name] if field and value and not keeprelative[name] then if field.kind == "path" then obj[name] = path.getrelative(location, value) elseif field.kind == "dirlist" or field.kind == "filelist" then adjustpathlist(value) elseif field.kind == "keypath" then for k,v in pairs(value) do adjustpathlist(v) end end end end end local function removevalue(tbl, remove) for index, item in ipairs(tbl) do if item == remove then table.remove(tbl, index) break end end end local function removevalues(tbl, removes) for k, v in pairs(tbl) do for _, pattern in ipairs(removes) do if pattern == tbl[k] then if type(k) == "number" then table.remove(tbl, k) else tbl[k] = nil end break end end end end local function mergefield(kind, dest, src, mergecopiestotail) local tbl = dest or { } if kind == "keyvalue" or kind == "keypath" then for key, value in pairs(src) do tbl[key] = mergefield("list", tbl[key], value, mergecopiestotail) end else for _, item in ipairs(src) do if tbl[item] then if mergecopiestotail then removevalue(tbl, item) table.insert(tbl, item) tbl[item] = item end else table.insert(tbl, item) tbl[item] = item end end end return tbl end local function mergeobject(dest, src) if not src then return end for fieldname, value in pairs(src) do if not nocopy[fieldname] then local field = premake.fields[fieldname] if field then if type(value) == "table" then dest[fieldname] = mergefield(field.kind, dest[fieldname], value, field.mergecopiestotail) if src.removes then removes = src.removes[fieldname] if removes then removevalues(dest[fieldname], removes) end end else dest[fieldname] = value end else dest[fieldname] = value end end end end local function merge(dest, obj, basis, terms, cfgname, pltname) local key = cfgname or "" pltname = pltname or "Native" if pltname ~= "Native" then key = key .. pltname end terms.config = (cfgname or ""):lower() terms.platform = pltname:lower() local cfg = {} mergeobject(cfg, basis[key]) adjustpaths(obj.location, cfg) mergeobject(cfg, obj) if (cfg.kind) then terms['kind']=cfg.kind:lower() end for _, blk in ipairs(obj.blocks) do if (premake.iskeywordsmatch(blk.keywords, terms))then mergeobject(cfg, blk) if (cfg.kind and not cfg.terms.kind) then cfg.terms['kind'] = cfg.kind:lower() terms['kind'] = cfg.kind:lower() end end end cfg.name = cfgname cfg.platform = pltname for k,v in pairs(terms) do cfg.terms[k] =v end dest[key] = cfg end local function collapse(obj, basis) local result = {} basis = basis or {} local sln = obj.solution or obj local terms = premake.getactiveterms(obj) merge(result, obj, basis, terms)--this adjusts terms for _, cfgname in ipairs(sln.configurations) do local terms_local = {} for k,v in pairs(terms)do terms_local[k]=v end merge(result, obj, basis, terms_local, cfgname, "Native")--terms cam also be adjusted here for _, pltname in ipairs(sln.platforms or {}) do if pltname ~= "Native" then merge(result, obj, basis,terms_local, cfgname, pltname)--terms also here end end end return result end local function builduniquedirs() local num_variations = 4 local cfg_dirs = {} local hit_counts = {} for sln in premake.solution.each() do for _, prj in ipairs(sln.projects) do for _, cfg in pairs(prj.__configs) do local dirs = { } dirs[1] = path.getabsolute(path.join(cfg.location, cfg.objdir or cfg.project.objdir or "obj")) dirs[2] = path.join(dirs[1], iif(cfg.platform == "Native", "", cfg.platform)) dirs[3] = path.join(dirs[2], cfg.name) dirs[4] = path.join(dirs[3], cfg.project.name) cfg_dirs[cfg] = dirs local start = iif(cfg.name, 2, 1) for v = start, num_variations do local d = dirs[v] hit_counts[d] = (hit_counts[d] or 0) + 1 end end end end for sln in premake.solution.each() do for _, prj in ipairs(sln.projects) do for _, cfg in pairs(prj.__configs) do local dir local start = iif(cfg.name, 2, 1) for v = start, iif(cfg.flags.SingleOutputDir==true,num_variations-1,num_variations) do dir = cfg_dirs[cfg][v] if hit_counts[dir] == 1 then break end end cfg.objectsdir = path.getrelative(cfg.location, dir) end end end end local function buildtargets() for sln in premake.solution.each() do for _, prj in ipairs(sln.projects) do for _, cfg in pairs(prj.__configs) do local pathstyle = premake.getpathstyle(cfg) local namestyle = premake.getnamestyle(cfg) cfg.buildtarget = premake.gettarget(cfg, "build", pathstyle, namestyle, cfg.system) cfg.linktarget = premake.gettarget(cfg, "link", pathstyle, namestyle, cfg.system) if pathstyle == "windows" then cfg.objectsdir = path.translate(cfg.objectsdir, "\\") end end end end end local function getCfgKind(cfg) if(cfg.kind) then return cfg.kind; end if(cfg.project.__configs[""] and cfg.project.__configs[""].kind) then return cfg.project.__configs[""].kind; end return nil end local function getprojrec(dstArray, foundList, cfg, cfgname, searchField, bLinkage) if(not cfg) then return end local foundUsePrjs = {}; for _, useName in ipairs(cfg[searchField]) do local testName = useName:lower(); if((not foundList[testName])) then local theProj = nil; local theUseProj = nil; for _, prj in ipairs(cfg.project.solution.projects) do if (prj.name:lower() == testName) then if(prj.usage) then theUseProj = prj; else theProj = prj; end end end --Must connect to a usage project. if(theUseProj) then foundList[testName] = true; local prjEntry = { name = testName, proj = theProj, usageProj = theUseProj, bLinkageOnly = bLinkage, }; dstArray[testName] = prjEntry; table.insert(foundUsePrjs, theUseProj); end end end for _, usePrj in ipairs(foundUsePrjs) do --Links can only recurse through static libraries. if((searchField ~= "links") or (getCfgKind(usePrj.__configs[cfgname]) == "StaticLib")) then getprojrec(dstArray, foundList, usePrj.__configs[cfgname], cfgname, searchField, bLinkage); end end end -- -- This function will recursively get all projects that the given configuration has in its "uses" -- field. The return values are a list of tables. Each table in that list contains the following: --name = The lowercase name of the project. --proj = The project. Can be nil if it is usage-only. --usageProj = The usage project. Can't be nil, as using a project that has no -- usage project is not put into the list. --bLinkageOnly = If this is true, then only the linkage information should be copied. -- The recursion will only look at the "uses" field on *usage* projects. -- This function will also add projects to the list that are mentioned in the "links" -- field of usage projects. These will only copy linker information, but they will recurse. -- through other "links" fields. -- local function getprojectsconnections(cfg, cfgname) local dstArray = {}; local foundList = {}; foundList[cfg.project.name:lower()] = true; --First, follow the uses recursively. getprojrec(dstArray, foundList, cfg, cfgname, "uses", false); --Next, go through all of the usage projects and recursively get their links. --But only if they're not already there. Get the links as linkage-only. local linkArray = {}; for prjName, prjEntry in pairs(dstArray) do getprojrec(linkArray, foundList, prjEntry.usageProj.__configs[cfgname], cfgname, "links", true); end --Copy from linkArray into dstArray. for prjName, prjEntry in pairs(linkArray) do dstArray[prjName] = prjEntry; end return dstArray; end local function isnameofproj(cfg, strName) local sln = cfg.project.solution; local strTest = strName:lower(); for prjIx, prj in ipairs(sln.projects) do if (prj.name:lower() == strTest) then return true; end end return false; end -- -- Copies the field from dstCfg to srcCfg. -- local function copydependentfield(srcCfg, dstCfg, strSrcField) local srcField = premake.fields[strSrcField]; local strDstField = strSrcField; if type(srcCfg[strSrcField]) == "table" then --handle paths. if (srcField.kind == "dirlist" or srcField.kind == "filelist") and (not keeprelative[strSrcField]) then for i,p in ipairs(srcCfg[strSrcField]) do table.insert(dstCfg[strDstField], path.rebase(p, srcCfg.project.location, dstCfg.project.location)) end else if(strSrcField == "links") then for i,p in ipairs(srcCfg[strSrcField]) do if(not isnameofproj(dstCfg, p)) then table.insert(dstCfg[strDstField], p) else printf("Failed to copy '%s' from proj '%s'.", p, srcCfg.project.name); end end else for i,p in ipairs(srcCfg[strSrcField]) do table.insert(dstCfg[strDstField], p) end end end else if(srcField.kind == "path" and (not keeprelative[strSrcField])) then dstCfg[strDstField] = path.rebase(srcCfg[strSrcField], prj.location, dstCfg.project.location); else dstCfg[strDstField] = srcCfg[strSrcField]; end end end -- -- This function will take the list of project entries and apply their usage project data -- to the given configuration. It will copy compiling information for the projects that are -- not listed as linkage-only. It will copy the linking information for projects only if -- the source project is not a static library. It won't copy linking information -- if the project is in this solution; instead it will add that project to the configuration's -- links field, expecting that Premake will handle the rest. -- local function copyusagedata(cfg, cfgname, linkToProjs) local myPrj = cfg.project; local bIsStaticLib = (getCfgKind(cfg) == "StaticLib"); for prjName, prjEntry in pairs(linkToProjs) do local srcPrj = prjEntry.usageProj; local srcCfg = srcPrj.__configs[cfgname]; for name, field in pairs(premake.fields) do if(srcCfg[name]) then if(field.usagecopy) then if(not prjEntry.bLinkageOnly) then copydependentfield(srcCfg, cfg, name) end elseif(field.linkagecopy) then --Copy the linkage data if we're building a non-static thing --and this is a pure usage project. If it's not pure-usage, then --we will simply put the project's name in the links field later. if((not bIsStaticLib) and (not prjEntry.proj)) then copydependentfield(srcCfg, cfg, name) end end end end if((not bIsStaticLib) and prjEntry.proj) then table.insert(cfg.links, prjEntry.proj.name); end end end local function inverseliteralvpaths() for sln in premake.solution.each() do for _,prj in ipairs(sln.projects) do prj.inversevpaths = {} for replacement, patterns in pairs(prj.vpaths or {}) do for _, pattern in ipairs(patterns) do if string.find(pattern, "*") == nil then prj.inversevpaths[pattern] = replacement end end end end end end function premake.bake.buildconfigs() for sln in premake.solution.each() do for _, prj in ipairs(sln.projects) do prj.location = prj.location or sln.location or prj.basedir adjustpaths(prj.location, prj) for _, blk in ipairs(prj.blocks) do adjustpaths(prj.location, blk) end end sln.location = sln.location or sln.basedir end -- convert paths for imported projects to be relative to solution location for sln in premake.solution.each() do for _, iprj in ipairs(sln.importedprojects) do iprj.location = path.getabsolute(iprj.location) end end inverseliteralvpaths() for sln in premake.solution.each() do local basis = collapse(sln) for _, prj in ipairs(sln.projects) do prj.__configs = collapse(prj, basis) for _, cfg in pairs(prj.__configs) do bake.postprocess(prj, cfg) end end end for sln in premake.solution.each() do for prjIx, prj in ipairs(sln.projects) do if(not prj.usage) then for cfgname, cfg in pairs(prj.__configs) do local usesPrjs = getprojectsconnections(cfg, cfgname); copyusagedata(cfg, cfgname, usesPrjs) end end end end for sln in premake.solution.each() do for prjIx, prj in ipairs(sln.projects) do for cfgName, cfg in pairs(prj.__configs) do cfg.build = true local removes = nil if cfg.removes ~= nil then removes = cfg.removes["platforms"]; end if removes ~= nil then for _,p in ipairs(removes) do if p == cfg.platform then cfg.build = false end end end end end end for sln in premake.solution.each() do local removeList = {}; for index, prj in ipairs(sln.projects) do if(prj.usage) then table.insert(removeList, 1, index); --Add in reverse order. end end for _, index in ipairs(removeList) do table.remove(sln.projects, index); end end builduniquedirs() buildtargets(cfg) end function premake.bake.postprocess(prj, cfg) cfg.project = prj cfg.shortname = premake.getconfigname(cfg.name, cfg.platform, true) cfg.longname = premake.getconfigname(cfg.name, cfg.platform) cfg.location = cfg.location or cfg.basedir local platform = premake.platforms[cfg.platform] if platform.iscrosscompiler then cfg.system = cfg.platform else cfg.system = os.get() end if cfg.kind == "Bundle" and _ACTION ~= "gmake" and (_ACTION ~= "ninja" and (not prj.options or not prj.options.SkipBundling)) and not _ACTION:match("xcode[0-9]") then cfg.kind = "SharedLib" end if cfg.kind == "SharedLib" and platform.nosharedlibs then cfg.kind = "StaticLib" end local removefiles = cfg.removefiles if _ACTION == 'gmake' or _ACTION == 'ninja' then removefiles = table.join(removefiles, cfg.excludes) end local removefilesDict = {} for _, fname in ipairs(removefiles) do removefilesDict[fname] = true end local files = {} for _, fname in ipairs(cfg.files) do if removefilesDict[fname] == nil then table.insert(files, fname) end end cfg.files = files local allfiles = {} local allfilesDict = {} if cfg.allfiles ~= nil then for _, fname in ipairs(cfg.allfiles) do if allfilesDict[fname] == nil then if removefilesDict[fname] == nil then allfilesDict[fname] = true table.insert(allfiles, fname) end end end end cfg.allfiles = allfiles for name, field in pairs(premake.fields) do if field.isflags then local values = cfg[name] for _, flag in ipairs(values) do values[flag] = true end end end local cfgfields = { {"__fileconfigs", cfg.files}, {"__allfileconfigs", cfg.allfiles}, } for _, cfgfield in ipairs(cfgfields) do local fieldname = cfgfield[1] local field = cfgfield[2] cfg[fieldname] = { } for _, fname in ipairs(field) do local fcfg = {} if premake._filelevelconfig then cfg.terms.required = fname:lower() for _, blk in ipairs(cfg.project.blocks) do if (premake.iskeywordsmatch(blk.keywords, cfg.terms)) then mergeobject(fcfg, blk) end end end fcfg.name = fname cfg[fieldname][fname] = fcfg table.insert(cfg[fieldname], fcfg) end end end premake.fields = {} premake.check_paths = false function premake.checkvalue(value, allowed) if (allowed) then if (type(allowed) == "function") then return allowed(value) else for _,v in ipairs(allowed) do if (value:lower() == v:lower()) then return v end end return nil, "invalid value '" .. value .. "'" end else return value end end function premake.getobject(t) local container if (t == "container" or t == "solution") then container = premake.CurrentContainer else container = premake.CurrentConfiguration end if t == "solution" then if typex(container) == "project" then container = container.solution end if typex(container) ~= "solution" then container = nil end end local msg if (not container) then if (t == "container") then msg = "no active solution or project" elseif (t == "solution") then msg = "no active solution" else msg = "no active solution, project, or configuration" end end return container, msg end function premake.setarray(obj, fieldname, value, allowed) obj[fieldname] = obj[fieldname] or {} local function add(value, depth) if type(value) == "table" then for _,v in ipairs(value) do add(v, depth + 1) end else value, err = premake.checkvalue(value, allowed) if not value then error(err, depth) end table.insert(obj[fieldname], value) end end if value then add(value, 5) end return obj[fieldname] end function premake.settable(obj, fieldname, value, allowed) obj[fieldname] = obj[fieldname] or {} table.insert(obj[fieldname], value) return obj[fieldname] end local function domatchedarray(fields, value, matchfunc) local result = { } function makeabsolute(value, depth) if (type(value) == "table") then for _, item in ipairs(value) do makeabsolute(item, depth + 1) end elseif type(value) == "string" then if value:find("*") then local arr = matchfunc(value); if (premake.check_paths) and (#arr == 0) then error("Can't find matching files for pattern :" .. value) end makeabsolute(arr, depth + 1) else table.insert(result, path.getabsolute(value)) end else error("Invalid value in list: expected string, got " .. type(value), depth) end end makeabsolute(value, 3) local retval = {} for index, field in ipairs(fields) do local ctype = field[1] local fieldname = field[2] local array = premake.setarray(ctype, fieldname, result) if index == 1 then retval = array end end return retval end function premake.setdirarray(fields, value) return domatchedarray(fields, value, os.matchdirs) end function premake.setfilearray(fields, value) return domatchedarray(fields, value, os.matchfiles) end function premake.setkeyvalue(ctype, fieldname, values) local container, err = premake.getobject(ctype) if not container then error(err, 4) end if not container[fieldname] then container[fieldname] = {} end if type(values) ~= "table" then error("invalid value; table expected", 4) end local field = container[fieldname] for key,value in pairs(values) do if not field[key] then field[key] = {} end table.insertflat(field[key], value) end return field end function premake.setstring(ctype, fieldname, value, allowed) local container, err = premake.getobject(ctype) if (not container) then error(err, 4) end if (value) then value, err = premake.checkvalue(value, allowed) if (not value) then error(err, 4) end container[fieldname] = value end return container[fieldname] end function premake.remove(fieldname, value) local cfg = premake.CurrentConfiguration cfg.removes = cfg.removes or {} cfg.removes[fieldname] = premake.setarray(cfg.removes, fieldname, value) end local function accessor(name, value) local kind = premake.fields[name].kind local scope = premake.fields[name].scope local allowed = premake.fields[name].allowed if (kind == "string" or kind == "path") and value then if type(value) ~= "string" then error("string value expected", 3) end end local container, err = premake.getobject(scope) if (not container) then error(err, 3) end if kind == "string" then return premake.setstring(scope, name, value, allowed) elseif kind == "path" then if value then value = path.getabsolute(value) end return premake.setstring(scope, name, value) elseif kind == "list" then return premake.setarray(container, name, value, allowed) elseif kind == "table" then return premake.settable(container, name, value, allowed) elseif kind == "dirlist" then return premake.setdirarray({{container, name}}, value) elseif kind == "filelist" or kind == "absolutefilelist" then local fields = {{container, name}} if name == "files" then local prj, err = premake.getobject("container") if (not prj) then error(err, 2) end table.insert(fields, {prj.blocks[1], "allfiles"}) end return premake.setfilearray(fields, value) elseif kind == "keyvalue" or kind == "keypath" then return premake.setkeyvalue(scope, name, value) end end function configuration(terms) if not terms then return premake.CurrentConfiguration end local container, err = premake.getobject("container") if (not container) then error(err, 2) end local cfg = { } cfg.terms = table.flatten({terms}) table.insert(container.blocks, cfg) premake.CurrentConfiguration = cfg cfg.keywords = { } for _, word in ipairs(cfg.terms) do table.insert(cfg.keywords, path.wildcards(word):lower()) end for name, field in pairs(premake.fields) do if (field.kind ~= "string" and field.kind ~= "path") then cfg[name] = { } end end return cfg end local function creategroup(name, sln, curpath, parent, inpath) local group = {} setmetatable(group, { __type = "group" }) table.insert(sln.groups, group) sln.groups[inpath] = group if parent ~= nil then table.insert(parent.groups, group) end group.solution = sln group.name = name group.uuid = os.uuid(curpath) group.parent = parent group.projects = { } group.groups = { } return group end local function creategroupsfrompath(inpath, sln) if inpath == nil then return nil end inpath = path.translate(inpath, "/") local groups = string.explode(inpath, "/") local curpath = "" local lastgroup = nil for i, v in ipairs(groups) do curpath = curpath .. "/" .. v:lower() local group = sln.groups[curpath] if group == nil then group = creategroup(v, sln, curpath, lastgroup, curpath) end lastgroup = group end return lastgroup end local function createproject(name, sln, isUsage) local prj = {} setmetatable(prj, { __type = "project", }) table.insert(sln.projects, prj) if(isUsage) then if(sln.projects[name]) then sln.projects[name].usageProj = prj; else sln.projects[name] = prj end else if(sln.projects[name]) then prj.usageProj = sln.projects[name]; end sln.projects[name] = prj end local group = creategroupsfrompath(premake.CurrentGroup, sln) if group ~= nil then table.insert(group.projects, prj) end prj.solution = sln prj.name = name prj.basedir = os.getcwd() prj.uuid = os.uuid(prj.name) prj.blocks = { } prj.usage = isUsage prj.group = group return prj; end function usage(name) if (not name) then if(typex(premake.CurrentContainer) ~= "project") then return nil end if(not premake.CurrentContainer.usage) then return nil end return premake.CurrentContainer end local sln if (typex(premake.CurrentContainer) == "project") then sln = premake.CurrentContainer.solution else sln = premake.CurrentContainer end if (typex(sln) ~= "solution") then error("no active solution", 2) end if((not sln.projects[name]) or ((not sln.projects[name].usage) and (not sln.projects[name].usageProj))) then premake.CurrentContainer = createproject(name, sln, true) else premake.CurrentContainer = iff(sln.projects[name].usage, sln.projects[name], sln.projects[name].usageProj) end configuration { } return premake.CurrentContainer end function project(name) if (not name) then if(typex(premake.CurrentContainer) ~= "project") then return nil end if(premake.CurrentContainer.usage) then return nil end return premake.CurrentContainer end local sln if (typex(premake.CurrentContainer) == "project") then sln = premake.CurrentContainer.solution else sln = premake.CurrentContainer end if (typex(sln) ~= "solution") then error("no active solution", 2) end if((not sln.projects[name]) or sln.projects[name].usage) then premake.CurrentContainer = createproject(name, sln) else premake.CurrentContainer = sln.projects[name]; end configuration { } return premake.CurrentContainer end function solution(name) if not name then if typex(premake.CurrentContainer) == "project" then return premake.CurrentContainer.solution else return premake.CurrentContainer end end premake.CurrentContainer = premake.solution.get(name) if (not premake.CurrentContainer) then premake.CurrentContainer = premake.solution.new(name) end configuration { } return premake.CurrentContainer end function group(name) if not name then return premake.CurrentGroup end premake.CurrentGroup = name return premake.CurrentGroup end function importvsproject(location) if string.find(_ACTION, "vs") ~= 1 then error("Only available for visual studio actions") end sln, err = premake.getobject("solution") if not sln then error(err) end local group = creategroupsfrompath(premake.CurrentGroup, sln) local project = {} project.location = location project.group = group project.flags = {} table.insert(sln.importedprojects, project) end function newaction(a) premake.action.add(a) end function newoption(opt) premake.option.add(opt) end function enablefilelevelconfig() premake._filelevelconfig = true end function newapifield(field) premake.fields[field.name] = field _G[field.name] = function(value) return accessor(field.name, value) end if field.kind == "list" or field.kind == "dirlist" or field.kind == "filelist" or field.kind == "absolutefilelist" then if field.name ~= "removefiles" and field.name ~= "files" then _G["remove"..field.name] = function(value) premake.remove(field.name, value) end end end end newapifield { name = "archivesplit_size", kind = "string", scope = "config", } newapifield { name = "basedir", kind = "path", scope = "container", } newapifield { name = "buildaction", kind = "string", scope = "config", allowed = { "Compile", "Copy", "Embed", "None" } } newapifield { name = "buildoptions", kind = "list", scope = "config", } newapifield { name = "buildoptions_asm", kind = "list", scope = "config", } newapifield { name = "buildoptions_c", kind = "list", scope = "config", } newapifield { name = "buildoptions_cpp", kind = "list", scope = "config", } newapifield { name = "buildoptions_objc", kind = "list", scope = "config", } newapifield { name = "buildoptions_objcpp", kind = "list", scope = "config", } newapifield { name = "buildoptions_vala", kind = "list", scope = "config", } newapifield { name = "clrreferences", kind = "list", scope = "container", } newapifield { name = "configurations", kind = "list", scope = "solution", } newapifield { name = "custombuildtask", kind = "table", scope = "config", } newapifield { name = "debugcmd", kind = "string", scope = "config", } newapifield { name = "debugargs", kind = "list", scope = "config", } newapifield { name = "debugdir", kind = "path", scope = "config", } newapifield { name = "debugenvs" , kind = "list", scope = "config", } newapifield { name = "defines", kind = "list", scope = "config", } newapifield { name = "deploymentoptions", kind = "list", scope = "config", usagecopy = true, } newapifield { name = "dependency", kind = "table", scope = "config", } newapifield { name = "deploymode", kind = "string", scope = "config", } newapifield { name = "excludes", kind = "filelist", scope = "config", } newapifield { name = "forcenative", kind = "filelist", scope = "config", } newapifield { name = "nopch", kind = "filelist", scope = "config", } newapifield { name = "files", kind = "filelist", scope = "config", } newapifield { name = "removefiles", kind = "filelist", scope = "config", } newapifield { name = "flags", kind = "list", scope = "config", isflags = true, usagecopy = true, allowed = function(value) local allowed_flags = { AntBuildDebuggable = 1, C7DebugInfo = 1, Cpp11 = 1, Cpp14 = 1, Cpp17 = 1, Cpp20 = 1, CppLatest = 1, DebugEnvsDontMerge = 1, DebugEnvsInherit = 1, DeploymentContent = 1, EnableMinimalRebuild = 1, EnableSSE = 1, EnableSSE2 = 1, EnableAVX = 1, EnableAVX2 = 1, PedanticWarnings = 1, ExtraWarnings = 1, FatalWarnings = 1, FloatFast = 1, FloatStrict = 1, FullSymbols = 1, GenerateMapFiles = 1, Hotpatchable = 1, LinkSupportCircularDependencies = 1, Managed = 1, MinimumWarnings = 1, NativeWChar = 1, No64BitChecks = 1, NoBufferSecurityCheck = 1, NoEditAndContinue = 1, NoExceptions = 1, NoFramePointer = 1, NoImportLib = 1, NoIncrementalLink = 1, NoJMC = 1, NoManifest = 1, NoMultiProcessorCompilation = 1, NoNativeWChar = 1, NoOptimizeLink = 1, NoPCH = 1, NoRTTI = 1, NoRuntimeChecks = 1, NoWinMD = 1, -- explicitly disables Windows Metadata NoWinRT = 1, -- explicitly disables Windows Runtime Extension FastCall = 1, StdCall = 1, SingleOutputDir = 1, ObjcARC = 1, Optimize = 1, OptimizeSize = 1, OptimizeSpeed = 1, DebugRuntime = 1, ReleaseRuntime = 1, SEH = 1, StaticRuntime = 1, Symbols = 1, Unicode = 1, UnitySupport = 1, Unsafe = 1, UnsignedChar = 1, UseFullPaths = 1, UseLDResponseFile = 1, UseObjectResponseFile = 1, WinMain = 1 } local englishToAmericanSpelling = { nooptimiselink = 'nooptimizelink', optimise = 'optimize', optimisesize = 'optimizesize', optimisespeed = 'optimizespeed', } local lowervalue = value:lower() lowervalue = englishToAmericanSpelling[lowervalue] or lowervalue for v, _ in pairs(allowed_flags) do if v:lower() == lowervalue then return v end end return nil, "invalid flag" end, } newapifield { name = "framework", kind = "string", scope = "container", allowed = { "1.0", "1.1", "2.0", "3.0", "3.5", "4.0", "4.5", "4.5.1", "4.5.2", "4.6", "4.6.1", "4.6.2", } } newapifield { name = "iostargetplatformversion", kind = "string", scope = "project", } newapifield { name = "macostargetplatformversion", kind = "string", scope = "project", } newapifield { name = "tvostargetplatformversion", kind = "string", scope = "project", } newapifield { name = "windowstargetplatformversion", kind = "string", scope = "project", } newapifield { name = "windowstargetplatformminversion", kind = "string", scope = "project", } newapifield { name = "forcedincludes", kind = "list", scope = "config", } newapifield { name = "imagepath", kind = "path", scope = "config", } newapifield { name = "imageoptions", kind = "list", scope = "config", } newapifield { name = "implibdir", kind = "path", scope = "config", } newapifield { name = "implibextension", kind = "string", scope = "config", } newapifield { name = "implibname", kind = "string", scope = "config", } newapifield { name = "implibprefix", kind = "string", scope = "config", } newapifield { name = "implibsuffix", kind = "string", scope = "config", } newapifield { name = "includedirs", kind = "dirlist", scope = "config", usagecopy = true, } newapifield { name = "systemincludedirs", kind = "dirlist", scope = "config", usagecopy = true, } newapifield { name = "userincludedirs", kind = "dirlist", scope = "config", usagecopy = true, } newapifield { name = "usingdirs", kind = "dirlist", scope = "config", usagecopy = true, } newapifield { name = "kind", kind = "string", scope = "config", allowed = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle", } } newapifield { name = "language", kind = "string", scope = "container", allowed = { "C", "C++", "C#", "Vala", "Swift", } } newapifield { name = "libdirs", kind = "dirlist", scope = "config", linkagecopy = true, } newapifield { name = "linkoptions", kind = "list", scope = "config", } newapifield { name = "links", kind = "list", scope = "config", allowed = function(value) if value:find('/', nil, true) then value = path.getabsolute(value) end return value end, linkagecopy = true, mergecopiestotail = true, } newapifield { name = "location", kind = "path", scope = "container", } newapifield { name = "makesettings", kind = "list", scope = "config", } newapifield { name = "messageskip", kind = "list", scope = "solution", isflags = true, usagecopy = true, allowed = function(value) local allowed_messages = { SkipCreatingMessage = 1, SkipBuildingMessage = 1, SkipCleaningMessage = 1, } local lowervalue = value:lower() for v, _ in pairs(allowed_messages) do if v:lower() == lowervalue then return v end end return nil, "invalid message to skip" end, } newapifield { name = "msgarchiving", kind = "string", scope = "config", } newapifield { name = "msgcompile", kind = "string", scope = "config", } newapifield { name = "msgprecompile", kind = "string", scope = "config", } newapifield { name = "msgcompile_objc", kind = "string", scope = "config", } newapifield { name = "msgresource", kind = "string", scope = "config", } newapifield { name = "msglinking", kind = "string", scope = "config", } newapifield { name = "objdir", kind = "path", scope = "config", } newapifield { name = "options", kind = "list", scope = "container", isflags = true, usagecopy = true, allowed = function(value) local allowed_options = { ForceCPP = 1, ArchiveSplit = 1, SkipBundling = 1, XcodeLibrarySchemes = 1, XcodeSchemeNoConfigs = 1, } local lowervalue = value:lower() for v, _ in pairs(allowed_options) do if v:lower() == lowervalue then return v end end return nil, "invalid option" end, } newapifield { name = "pchheader", kind = "string", scope = "config", } newapifield { name = "pchsource", kind = "path", scope = "config", } newapifield { name = "platforms", kind = "list", scope = "solution", allowed = table.keys(premake.platforms), } newapifield { name = "postbuildcommands", kind = "list", scope = "config", } newapifield { name = "prebuildcommands", kind = "list", scope = "config", } newapifield { name = "postcompiletasks", kind = "list", scope = "config", } newapifield { name = "prelinkcommands", kind = "list", scope = "config", } newapifield { name = "propertysheets", kind = "dirlist", scope = "config", } newapifield { name = "pullmappingfile", kind = "path", scope = "config", } newapifield { name = "applicationdatadir", kind = "path", scope = "config", } newapifield { name = "finalizemetasource", kind = "path", scope = "config", } newapifield { name = "resdefines", kind = "list", scope = "config", } newapifield { name = "resincludedirs", kind = "dirlist", scope = "config", } newapifield { name = "resoptions", kind = "list", scope = "config", } newapifield { name = "sdkreferences", kind = "list", scope = "config", } newapifield { name = "startproject", kind = "string", scope = "solution", } newapifield { name = "targetdir", kind = "path", scope = "config", } newapifield { name = "targetsubdir", kind = "string", scope = "config", } newapifield { name = "targetextension", kind = "string", scope = "config", } newapifield { name = "targetname", kind = "string", scope = "config", } newapifield { name = "targetprefix", kind = "string", scope = "config", } newapifield { name = "targetsuffix", kind = "string", scope = "config", } newapifield { name = "trimpaths", kind = "dirlist", scope = "config", } newapifield { name = "uuid", kind = "string", scope = "container", 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 } newapifield { name = "uses", kind = "list", scope = "config", } newapifield { name = "vapidirs", kind = "dirlist", scope = "config", } newapifield { name = "vpaths", kind = "keypath", scope = "container", } newapifield { name = "vsimportreferences", kind = "filelist", scope = "container", } newapifield { name = "dpiawareness", kind = "string", scope = "config", allowed = { "None", "High", "HighPerMonitor", } } newapifield { name = "xcodeprojectopts", kind = "table", scope = "config", } newapifield { name = "xcodetargetopts", kind = "table", scope = "config", } newapifield { name = "xcodescriptphases", kind = "table", scope = "config", } newapifield { name = "xcodecopyresources", kind = "table", scope = "project", } newapifield { name = "xcodecopyframeworks", kind = "filelist", scope = "project", } newapifield { name = "wholearchive", kind = "list", scope = "config", } newapifield { name = "swiftmodulemaps", kind = "filelist", scope = "config", } newapifield { name = "buildoptions_swift", kind = "list", scope = "config", } newapifield { name = "linkoptions_swift", kind = "list", scope = "config", } newapifield { name = "androidtargetapi", kind = "string", scope = "config", } newapifield { name = "androidminapi", kind = "string", scope = "config", } newapifield { name = "androidarch", kind = "string", scope = "config", allowed = { "armv7-a", "armv7-a-hard", "arm64-v8a", "x86", "x86_64", } } newapifield { name = "androidndktoolchainversion", kind = "string", scope = "config", } newapifield { name = "androidstltype", kind = "string", scope = "config", } newapifield { name = "androidcppstandard", kind = "string", scope = "config", allowed = { "c++98", "c++11", "c++1y", "gnu++98", "gnu++11", "gnu++1y", } } newapifield { name = "androidlinker", kind = "string", scope = "config", allowed = { "bfd", "gold", } } newapifield { name = "androiddebugintentparams", kind = "list", scope = "config", } newapifield { name = "antbuildjavasourcedirs", kind = "dirlist", scope = "config", } newapifield { name = "antbuildjardirs", kind = "dirlist", scope = "config", } newapifield { name = "antbuildjardependencies", kind = "list", scope = "config", } newapifield { name = "antbuildnativelibdirs", kind = "dirlist", scope = "config", } newapifield { name = "antbuildnativelibdependencies", kind = "list", scope = "config", } newapifield { name = "antbuildassetsdirs", kind = "dirlist", scope = "config", } newapifield { name = "postsolutioncallbacks", kind = "list", scope = "solution", } newapifield { name = "postprojectcallbacks", kind = "list", scope = "project", } newoption { trigger = "cc", value = "VALUE", description = "Choose a C/C++ compiler set", allowed = { { "gcc", "GNU GCC (gcc/g++)" }, { "ow", "OpenWatcom" }, { "ghs", "Green Hills Software" }, } } newoption { 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 = "file", value = "FILE", description = "Read FILE as a Premake script; default is 'premake4.lua'" } newoption { trigger = "help", description = "Display this information" } newoption { trigger = "os", value = "VALUE", description = "Generate files for a different operating system", allowed = { { "bsd", "OpenBSD, NetBSD, or FreeBSD" }, { "linux", "Linux" }, { "macosx", "Apple Mac OS X" }, { "solaris", "Solaris" }, { "windows", "Microsoft Windows" }, } } newoption { trigger = "platform", value = "VALUE", description = "Add target architecture (if supported by action)", allowed = { { "x32", "32-bit" }, { "x64", "64-bit" }, { "universal", "Mac OS X Universal, 32- and 64-bit" }, { "universal32", "Mac OS X Universal, 32-bit only" }, { "universal64", "Mac OS X Universal, 64-bit only" }, { "ps3", "Playstation 3" }, { "orbis", "Playstation 4" }, { "xbox360", "Xbox 360" }, { "durango", "Xbox One" }, { "ARM", "ARM" }, { "ARM64", "ARM64" }, { "PowerPC", "PowerPC" }, { "nx32", "Nintendo Switch, 32-bit only" }, { "nx64", "Nintendo Switch, 64-bit only" }, } } newoption { trigger = "scripts", value = "path", description = "Search for additional scripts on the given path" } newoption { trigger = "debug-profiler", description = "GENie script generation profiler." } newoption { trigger = "version", description = "Display version information" } -- Copyright (c) 2013 Enrique García Cota local function smartQuote(str) if str:match('"') and not str:match("'") then return "'" .. str .. "'" end return '"' .. str:gsub('"', '\\"') .. '"' end local controlCharsTranslation = { ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v" } local function escapeChar(c) return controlCharsTranslation[c] end local function escape(str) local result = str:gsub("\\", "\\\\"):gsub("(%c)", escapeChar) return result end local function isIdentifier(str) return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" ) end local function isArrayKey(k, length) return type(k) == 'number' and 1 <= k and k <= length end local function isDictionaryKey(k, length) return not isArrayKey(k, length) end local defaultTypeOrders = { ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, ['function'] = 5, ['userdata'] = 6, ['thread'] = 7 } local function sortKeys(a, b) local ta, tb = type(a), type(b) -- strings and numbers are sorted numerically/alphabetically if ta == tb and (ta == 'string' or ta == 'number') then return a < b end local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb] -- Two default types are compared according to the defaultTypeOrders table if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb] elseif dta then return true -- default types before custom ones elseif dtb then return false -- custom types after default ones end -- custom types are sorted out alphabetically return ta < tb end local function getDictionaryKeys(t) local keys, length = {}, #t for k,_ in pairs(t) do if isDictionaryKey(k, length) then table.insert(keys, k) end end table.sort(keys, sortKeys) return keys end local function getToStringResultSafely(t, mt) local __tostring = type(mt) == 'table' and rawget(mt, '__tostring') local str, ok if type(__tostring) == 'function' then ok, str = pcall(__tostring, t) str = ok and str or 'error: ' .. tostring(str) end if type(str) == 'string' and #str > 0 then return str end end local maxIdsMetaTable = { __index = function(self, typeName) rawset(self, typeName, 0) return 0 end } local idsMetaTable = { __index = function (self, typeName) local col = setmetatable({}, {__mode = "kv"}) rawset(self, typeName, col) return col end } local function countTableAppearances(t, tableAppearances) tableAppearances = tableAppearances or setmetatable({}, {__mode = "k"}) if type(t) == 'table' then if not tableAppearances[t] then tableAppearances[t] = 1 for k,v in pairs(t) do countTableAppearances(k, tableAppearances) countTableAppearances(v, tableAppearances) end countTableAppearances(getmetatable(t), tableAppearances) else tableAppearances[t] = tableAppearances[t] + 1 end end return tableAppearances end local function parse_filter(filter) if type(filter) == 'function' then return filter end -- not a function, so it must be a table or table-like filter = type(filter) == 'table' and filter or {filter} local dictionary = {} for _,v in pairs(filter) do dictionary[v] = true end return function(x) return dictionary[x] end end local function makePath(path, key) local newPath, len = {}, #path for i=1, len do newPath[i] = path[i] end newPath[len+1] = key return newPath end function inspect(rootObject, options) options = options or {} local depth = options.depth or math.huge local filter = parse_filter(options.filter or {}) local tableAppearances = countTableAppearances(rootObject) local buffer = {} local maxIds = setmetatable({}, maxIdsMetaTable) local ids = setmetatable({}, idsMetaTable) local level = 0 local blen = 0 -- buffer length local function puts(...) local args = {...} for i=1, #args do blen = blen + 1 buffer[blen] = tostring(args[i]) end end local function down(f) level = level + 1 f() level = level - 1 end local function tabify() puts("\n", string.rep(" ", level)) end local function commaControl(needsComma) if needsComma then puts(',') end return true end local function alreadyVisited(v) return ids[type(v)][v] ~= nil end local function getId(v) local tv = type(v) local id = ids[tv][v] if not id then id = maxIds[tv] + 1 maxIds[tv] = id ids[tv][v] = id end return id end local putValue -- forward declaration that needs to go before putTable & putKey local function putKey(k) if isIdentifier(k) then return puts(k) end puts( "[" ) putValue(k, {}) puts("]") end local function putTable(t, path) if alreadyVisited(t) then puts('') elseif level >= depth then puts('{...}') else if tableAppearances[t] > 1 then puts('<', getId(t), '>') end local dictKeys = getDictionaryKeys(t) local length = #t local mt = getmetatable(t) local to_string_result = getToStringResultSafely(t, mt) puts('{') down(function() if to_string_result then puts(' -- ', escape(to_string_result)) if length >= 1 then tabify() end -- tabify the array values end local needsComma = false for i=1, length do needsComma = commaControl(needsComma) puts(' ') putValue(t[i], makePath(path, i)) end for _,k in ipairs(dictKeys) do needsComma = commaControl(needsComma) tabify() putKey(k) puts(' = ') putValue(t[k], makePath(path, k)) end if mt then needsComma = commaControl(needsComma) tabify() puts(' = ') putValue(mt, makePath(path, '')) end end) if #dictKeys > 0 or mt then -- dictionary table. Justify closing } tabify() elseif length > 0 then -- array tables have one extra space before closing } puts(' ') end puts('}') end end -- putvalue is forward-declared before putTable & putKey putValue = function(v, path) if filter(v, path) then puts('') else local tv = type(v) if tv == 'string' then puts(smartQuote(escape(v))) elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then puts(tostring(v)) elseif tv == 'table' then putTable(v, path) else puts('<',tv,' ',getId(v),'>') end end end putValue(rootObject, {}) return table.concat(buffer) end function printtable(name, table) print("table: ", name, inspect(table), "\n") end function printstack() print(debug.traceback(), "\n") end _profiler = {} function newProfiler(variant, sampledelay) if _profiler.running then print("Profiler already running.") return end variant = variant or "time" if variant ~= "time" and variant ~= "call" then print("Profiler method must be 'time' or 'call'.") return end local newprof = {} for k,v in pairs(_profiler) do newprof[k] = v end newprof.variant = variant newprof.sampledelay = sampledelay or 100000 return newprof end function _profiler.start(self) if _profiler.running then return end _profiler.running = self self.rawstats = {} self.callstack = {} if self.variant == "time" then self.lastclock = os.clock() debug.sethook( _profiler_hook_wrapper_by_time, "", self.sampledelay ) elseif self.variant == "call" then debug.sethook( _profiler_hook_wrapper_by_call, "cr" ) else print("Profiler method must be 'time' or 'call'.") sys.exit(1) end end function _profiler.stop(self) if _profiler.running ~= self then return end debug.sethook( nil ) _profiler.running = nil end function _profiler_hook_wrapper_by_call(action) if _profiler.running == nil then debug.sethook( nil ) end _profiler.running:_internal_profile_by_call(action) end function _profiler_hook_wrapper_by_time(action) if _profiler.running == nil then debug.sethook( nil ) end _profiler.running:_internal_profile_by_time(action) end function _profiler._internal_profile_by_call(self,action) local caller_info = debug.getinfo( 3 ) if caller_info == nil then print "No caller_info" return end local latest_ar = nil if table.getn(self.callstack) > 0 then latest_ar = self.callstack[table.getn(self.callstack)] end local should_not_profile = 0 for k,v in pairs(self.prevented_functions) do if k == caller_info.func then should_not_profile = v end end if latest_ar then if latest_ar.should_not_profile == 2 then should_not_profile = 2 end end if action == "call" then local this_ar = {} this_ar.should_not_profile = should_not_profile this_ar.parent_ar = latest_ar this_ar.anon_child = 0 this_ar.name_child = 0 this_ar.children = {} this_ar.children_time = {} this_ar.clock_start = os.clock() table.insert( self.callstack, this_ar ) else local this_ar = latest_ar if this_ar == nil then return -- No point in doing anything if no upper activation record end this_ar.clock_end = os.clock() this_ar.this_time = this_ar.clock_end - this_ar.clock_start if this_ar.parent_ar then this_ar.parent_ar.children[caller_info.func] = (this_ar.parent_ar.children[caller_info.func] or 0) + 1 this_ar.parent_ar.children_time[caller_info.func] = (this_ar.parent_ar.children_time[caller_info.func] or 0 ) + this_ar.this_time if caller_info.name == nil then this_ar.parent_ar.anon_child = this_ar.parent_ar.anon_child + this_ar.this_time else this_ar.parent_ar.name_child = this_ar.parent_ar.name_child + this_ar.this_time end end if this_ar.should_not_profile == 0 then local inforec = self:_get_func_rec(caller_info.func,1) inforec.count = inforec.count + 1 inforec.time = inforec.time + this_ar.this_time inforec.anon_child_time = inforec.anon_child_time + this_ar.anon_child inforec.name_child_time = inforec.name_child_time + this_ar.name_child inforec.func_info = caller_info for k,v in pairs(this_ar.children) do inforec.children[k] = (inforec.children[k] or 0) + v inforec.children_time[k] = (inforec.children_time[k] or 0) + this_ar.children_time[k] end end table.remove( self.callstack, table.getn( self.callstack ) ) end end function _profiler._internal_profile_by_time(self,action) local timetaken = os.clock() - self.lastclock local depth = 3 local at_top = true local last_caller local caller = debug.getinfo(depth) while caller do if not caller.func then caller.func = "(tail call)" end if self.prevented_functions[caller.func] == nil then local info = self:_get_func_rec(caller.func, 1, caller) info.count = info.count + 1 info.time = info.time + timetaken if last_caller then if last_caller.name then info.name_child_time = info.name_child_time + timetaken else info.anon_child_time = info.anon_child_time + timetaken end info.children[last_caller.func] = (info.children[last_caller.func] or 0) + 1 info.children_time[last_caller.func] = (info.children_time[last_caller.func] or 0) + timetaken end end depth = depth + 1 last_caller = caller caller = debug.getinfo(depth) end self.lastclock = os.clock() end function _profiler._get_func_rec(self,func,force,info) local ret = self.rawstats[func] if ret == nil and force ~= 1 then return nil end if ret == nil then ret = {} ret.func = func ret.count = 0 ret.time = 0 ret.anon_child_time = 0 ret.name_child_time = 0 ret.children = {} ret.children_time = {} ret.func_info = info self.rawstats[func] = ret end return ret end function _profiler.report( self, outfile, sort_by_total_time ) outfile:write [[Lua Profile output created by profiler.lua. Copyright Pepperfish 2002+ ]] local terms = {} if self.variant == "time" then terms.capitalized = "Sample" terms.single = "sample" terms.pastverb = "sampled" elseif self.variant == "call" then terms.capitalized = "Call" terms.single = "call" terms.pastverb = "called" else assert(false) end local total_time = 0 local ordering = {} for func,record in pairs(self.rawstats) do table.insert(ordering, func) end if sort_by_total_time then table.sort( ordering, function(a,b) return self.rawstats[a].time > self.rawstats[b].time end ) else table.sort( ordering, function(a,b) local arec = self.rawstats[a] local brec = self.rawstats[b] local atime = arec.time - (arec.anon_child_time + arec.name_child_time) local btime = brec.time - (brec.anon_child_time + brec.name_child_time) return atime > btime end ) end for i=1,#ordering do local func = ordering[i] local record = self.rawstats[func] local thisfuncname = " " .. self:_pretty_name(func) .. " " if string.len( thisfuncname ) < 42 then thisfuncname = string.rep( "-", math.floor((42 - string.len(thisfuncname))/2) ) .. thisfuncname thisfuncname = thisfuncname .. string.rep( "-", 42 - string.len(thisfuncname) ) end total_time = total_time + ( record.time - ( record.anon_child_time + record.name_child_time ) ) outfile:write( string.rep( "-", 19 ) .. thisfuncname .. string.rep( "-", 19 ) .. "\n" ) outfile:write( terms.capitalized.." count: " .. string.format( "%4d", record.count ) .. "\n" ) outfile:write( "Time spend total: " .. string.format( "%4.3f", record.time ) .. "s\n" ) outfile:write( "Time spent in children: " .. string.format("%4.3f",record.anon_child_time+record.name_child_time) .. "s\n" ) local timeinself = record.time - (record.anon_child_time + record.name_child_time) outfile:write( "Time spent in self: " .. string.format("%4.3f", timeinself) .. "s\n" ) outfile:write( "Time spent per " .. terms.single .. ": " .. string.format("%4.5f", record.time/record.count) .. "s/" .. terms.single .. "\n" ) outfile:write( "Time spent in self per "..terms.single..": " .. string.format( "%4.5f", timeinself/record.count ) .. "s/" .. terms.single.."\n" ) local added_blank = 0 for k,v in pairs(record.children) do if self.prevented_functions[k] == nil or self.prevented_functions[k] == 0 then if added_blank == 0 then outfile:write( "\n" ) -- extra separation line added_blank = 1 end outfile:write( "Child " .. self:_pretty_name(k) .. string.rep( " ", 41-string.len(self:_pretty_name(k)) ) .. " " .. terms.pastverb.." " .. string.format("%6d", v) ) outfile:write( " times. Took " .. string.format("%4.2f", record.children_time[k] ) .. "s\n" ) end end outfile:write( "\n" ) -- extra separation line outfile:flush() end outfile:write( "\n\n" ) outfile:write( "Total time spent in profiled functions: " .. string.format("%5.3g",total_time) .. "s\n" ) outfile:write( [[ END ]] ) outfile:flush() end function _profiler.lua_report(self,outfile) local ordering = {} local functonum = {} for func,record in pairs(self.rawstats) do table.insert(ordering, func) functonum[func] = table.getn(ordering) end outfile:write( "-- Profile generated by profiler.lua Copyright Pepperfish 2002+\n\n" ) outfile:write( "-- Function names\nfuncnames = {}\n" ) for i=1,table.getn(ordering) do local thisfunc = ordering[i] outfile:write( "funcnames[" .. i .. "] = " .. string.format("%q", self:_pretty_name(thisfunc)) .. "\n" ) end outfile:write( "\n" ) outfile:write( "-- Function times\nfunctimes = {}\n" ) for i=1,table.getn(ordering) do local thisfunc = ordering[i] local record = self.rawstats[thisfunc] outfile:write( "functimes[" .. i .. "] = { " ) outfile:write( "tot=" .. record.time .. ", " ) outfile:write( "achild=" .. record.anon_child_time .. ", " ) outfile:write( "nchild=" .. record.name_child_time .. ", " ) outfile:write( "count=" .. record.count .. " }\n" ) end outfile:write( "\n" ) outfile:write( "-- Child links\nchildren = {}\n" ) for i=1,table.getn(ordering) do local thisfunc = ordering[i] local record = self.rawstats[thisfunc] outfile:write( "children[" .. i .. "] = { " ) for k,v in pairs(record.children) do if functonum[k] then -- non-recorded functions will be ignored now outfile:write( functonum[k] .. ", " ) end end outfile:write( "}\n" ) end outfile:write( "\n" ) outfile:write( "-- Child call counts\nchildcounts = {}\n" ) for i=1,table.getn(ordering) do local thisfunc = ordering[i] local record = self.rawstats[thisfunc] outfile:write( "children[" .. i .. "] = { " ) for k,v in record.children do if functonum[k] then -- non-recorded functions will be ignored now outfile:write( v .. ", " ) end end outfile:write( "}\n" ) end outfile:write( "\n" ) outfile:write( "-- Child call time\nchildtimes = {}\n" ) for i=1,table.getn(ordering) do local thisfunc = ordering[i] local record = self.rawstats[thisfunc]; outfile:write( "children[" .. i .. "] = { " ) for k,v in pairs(record.children) do if functonum[k] then -- non-recorded functions will be ignored now outfile:write( record.children_time[k] .. ", " ) end end outfile:write( "}\n" ) end outfile:write( "\n\n-- That is all.\n\n" ) outfile:flush() end function _profiler._pretty_name(self,func) local info = self.rawstats[ func ].func_info local name = "" if info.what == "Lua" then name = "L:" end if info.what == "C" then name = "C:" end if info.what == "main" then name = " :" end if info.name == nil then name = name .. "<"..tostring(func) .. ">" else name = name .. info.name end if info.source then name = name else if info.what == "C" then name = name .. "@?" else name = name .. "@" end end name = name .. ":" if info.what == "C" then name = name .. "?" else name = name .. info.linedefined end return name end function _profiler.prevent(self, func, level) self.prevented_functions[func] = (level or 1) end _profiler.prevented_functions = { [_profiler.start] = 2, [_profiler.stop] = 2, [_profiler._internal_profile_by_time] = 2, [_profiler._internal_profile_by_call] = 2, [_profiler_hook_wrapper_by_time] = 2, [_profiler_hook_wrapper_by_call] = 2, [_profiler.prevent] = 2, [_profiler._get_func_rec] = 2, [_profiler.report] = 2, [_profiler.lua_report] = 2, [_profiler._pretty_name] = 2 } premake.dotnet = { } premake.dotnet.namestyle = "windows" local flags = { FatalWarning = "/warnaserror", Optimize = "/optimize", OptimizeSize = "/optimize", OptimizeSpeed = "/optimize", Symbols = "/debug", Unsafe = "/unsafe" } function premake.dotnet.getbuildaction(fcfg) local ext = path.getextension(fcfg.name):lower() if fcfg.buildaction == "Compile" or ext == ".cs" then return "Compile" elseif fcfg.buildaction == "Embed" or ext == ".resx" then return "EmbeddedResource" elseif fcfg.buildaction == "Copy" or ext == ".asax" or ext == ".aspx" then return "Content" else return "None" end end function premake.dotnet.getcompilervar(cfg) if (_OPTIONS.dotnet == "msnet") then return "csc" elseif (_OPTIONS.dotnet == "mono") then return "mcs" else return "cscc" end end function premake.dotnet.getflags(cfg) local result = table.translate(cfg.flags, flags) return result end function premake.dotnet.getkind(cfg) if (cfg.kind == "ConsoleApp") then return "Exe" elseif (cfg.kind == "WindowedApp") then return "WinExe" elseif (cfg.kind == "SharedLib") then return "Library" end end premake.gcc = { } premake.gcc.cc = "gcc" premake.gcc.cxx = "g++" premake.gcc.ar = "ar" premake.gcc.rc = "windres" premake.gcc.llvm = false local cflags = { EnableSSE = "-msse", EnableSSE2 = "-msse2", EnableAVX = "-mavx", EnableAVX2 = "-mavx2", PedanticWarnings = "-Wall -Wextra -pedantic", ExtraWarnings = "-Wall -Wextra", FatalWarnings = "-Werror", FloatFast = "-ffast-math", FloatStrict = "-ffloat-store", NoFramePointer = "-fomit-frame-pointer", Optimize = "-O2", OptimizeSize = "-Os", OptimizeSpeed = "-O3", Symbols = "-g", StaticRuntime = "-static", } local cxxflags = { Cpp11 = "-std=c++11", Cpp14 = "-std=c++14", Cpp17 = "-std=c++17", Cpp20 = "-std=c++20", CppLatest = "-std=c++2b", NoExceptions = "-fno-exceptions", NoRTTI = "-fno-rtti", UnsignedChar = "-funsigned-char", } local objcflags = { ObjcARC = "-fobjc-arc", } premake.gcc.platforms = { Native = { cppflags = "-MMD -MP", }, x32 = { cppflags = "-MMD -MP", flags = "-m32", }, x64 = { cppflags = "-MMD -MP", flags = "-m64", }, Universal = { ar = "libtool", cppflags = "-MMD -MP", flags = "-arch i386 -arch x86_64 -arch ppc -arch ppc64", }, Universal32 = { ar = "libtool", cppflags = "-MMD -MP", flags = "-arch i386 -arch ppc", }, Universal64 = { ar = "libtool", cppflags = "-MMD -MP", flags = "-arch x86_64 -arch ppc64", }, PS3 = { cc = "ppu-lv2-g++", cxx = "ppu-lv2-g++", ar = "ppu-lv2-ar", cppflags = "-MMD -MP", }, WiiDev = { cppflags = "-MMD -MP -I$(LIBOGC_INC) $(MACHDEP)", ldflags= "-L$(LIBOGC_LIB) $(MACHDEP)", cfgsettings = [[ ifeq ($(strip $(DEVKITPPC)),) $(error "DEVKITPPC environment variable is not set")' endif include $(DEVKITPPC)/wii_rules']], }, Orbis = { cc = "orbis-clang", cxx = "orbis-clang++", ar = "orbis-ar", cppflags = "-MMD -MP", }, Emscripten = { cc = "$(EMSCRIPTEN)/emcc", cxx = "$(EMSCRIPTEN)/em++", ar = "$(EMSCRIPTEN)/emar", cppflags = "-MMD -MP", }, NX32 = { cc = "clang", cxx = "clang++", ar = "armv7l-nintendo-nx-eabihf-ar", cppflags = "-MMD -MP", flags = "-march=armv7l", }, NX64 = { cc = "clang", cxx = "clang++", ar = "aarch64-nintendo-nx-elf-ar", cppflags = "-MMD -MP", flags = "-march=aarch64", }, } local platforms = premake.gcc.platforms function premake.gcc.getcppflags(cfg) local flags = { } table.insert(flags, platforms[cfg.platform].cppflags) if flags[1]:startswith("-MMD") then table.insert(flags, "-MP") end return flags end function premake.gcc.getcflags(cfg) local result = table.translate(cfg.flags, cflags) table.insert(result, platforms[cfg.platform].flags) if cfg.system ~= "windows" and cfg.kind == "SharedLib" then table.insert(result, "-fPIC") end return result end function premake.gcc.getcxxflags(cfg) local result = table.translate(cfg.flags, cxxflags) return result end function premake.gcc.getobjcflags(cfg) return table.translate(cfg.flags, objcflags) end function premake.gcc.getldflags(cfg) local result = { } if not cfg.flags.Symbols then if cfg.system == "macosx" then else table.insert(result, "-s") end end if cfg.kind == "Bundle" then table.insert(result, "-bundle") end if cfg.kind == "SharedLib" then if cfg.system == "macosx" then table.insert(result, "-dynamiclib") else table.insert(result, "-shared") end if cfg.system == "windows" and not cfg.flags.NoImportLib then table.insert(result, '-Wl,--out-implib="' .. cfg.linktarget.fullpath .. '"') end end if cfg.kind == "WindowedApp" and cfg.system == "windows" then table.insert(result, "-mwindows") end local platform = platforms[cfg.platform] table.insert(result, platform.flags) table.insert(result, platform.ldflags) return result end function premake.gcc.getlibdirflags(cfg) local result = { } for _, value in ipairs(premake.getlinks(cfg, "all", "directory")) do table.insert(result, '-L\"' .. value .. '\"') end return result end function premake.gcc.islibfile(p) if path.getextension(p) == ".a" then return true end return false end function premake.gcc.getlibfiles(cfg) local result = {} for _, value in ipairs(premake.getlinks(cfg, "system", "fullpath")) do if premake.gcc.islibfile(value) then table.insert(result, _MAKE.esc(value)) end end return result end function premake.gcc.getlinkflags(cfg) local result = {} for _, value in ipairs(premake.getlinks(cfg, "system", "fullpath")) do if premake.gcc.islibfile(value) then value = path.rebase(value, cfg.project.location, cfg.location) table.insert(result, _MAKE.esc(value)) elseif path.getextension(value) == ".framework" then table.insert(result, '-framework ' .. _MAKE.esc(path.getbasename(value))) else table.insert(result, '-l' .. _MAKE.esc(path.getname(value))) end end return result end function premake.gcc.wholearchive(lib) if premake.gcc.llvm then return {"-force_load", lib} elseif os.get() == "macosx" then return {"-Wl,-force_load", lib} else return {"-Wl,--whole-archive", lib, "-Wl,--no-whole-archive"} end end function premake.gcc.getarchiveflags(prj, cfg, ndx) local result = {} if cfg.platform:startswith("Universal") then if prj.options.ArchiveSplit then error("gcc tool 'Universal*' platforms do not support split archives") end table.insert(result, '-o') else if (not prj.options.ArchiveSplit) then if premake.gcc.llvm then table.insert(result, 'rcs') else table.insert(result, '-rcs') end else if premake.gcc.llvm then if (not ndx) then table.insert(result, 'qc') else table.insert(result, 'cs') end else if (not ndx) then table.insert(result, '-qc') else table.insert(result, '-cs') end end end end return result end function premake.gcc.getdefines(defines) local result = { } for _,def in ipairs(defines) do table.insert(result, "-D" .. def) end return result end function premake.gcc.getincludedirs(includedirs) local result = { } for _,dir in ipairs(includedirs) do table.insert(result, "-I\"" .. dir .. "\"") end return result end function premake.gcc.getquoteincludedirs(includedirs) local result = { } for _,dir in ipairs(includedirs) do table.insert(result, "-iquote \"" .. dir .. "\"") end return result end function premake.gcc.getsystemincludedirs(includedirs) local result = { } for _,dir in ipairs(includedirs) do table.insert(result, "-isystem \"" .. dir .. "\"") end return result end function premake.gcc.getcfgsettings(cfg) return platforms[cfg.platform].cfgsettings end premake.ghs = { } premake.ghs.namestyle = "PS3" premake.ghs.cc = "ccppc" premake.ghs.cxx = "cxppc" premake.ghs.ar = "cxppc" local cflags = { FatalWarnings = "--quit_after_warnings", Optimize = "-Ogeneral", OptimizeSize = "-Osize", OptimizeSpeed = "-Ospeed", Symbols = "-g", } local cxxflags = { NoExceptions = "--no_exceptions", NoRTTI = "--no_rtti", UnsignedChar = "--unsigned_chars", } premake.ghs.platforms = { Native = { cppflags = "-MMD", }, PowerPC = { cc = "ccppc", cxx = "cxppc", ar = "cxppc", cppflags = "-MMD", arflags = "-archive -o", }, ARM = { cc = "ccarm", cxx = "cxarm", ar = "cxarm", cppflags = "-MMD", arflags = "-archive -o", } } local platforms = premake.ghs.platforms function premake.ghs.getcppflags(cfg) local flags = { } table.insert(flags, platforms[cfg.platform].cppflags) return flags end function premake.ghs.getcflags(cfg) local result = table.translate(cfg.flags, cflags) table.insert(result, platforms[cfg.platform].flags) return result end function premake.ghs.getcxxflags(cfg) local result = table.translate(cfg.flags, cxxflags) return result end function premake.ghs.getldflags(cfg) local result = { } local platform = platforms[cfg.platform] table.insert(result, platform.flags) table.insert(result, platform.ldflags) return result end function premake.ghs.getlibdirflags(cfg) local result = { } for _, value in ipairs(premake.getlinks(cfg, "all", "directory")) do table.insert(result, '-L' .. _MAKE.esc(value)) end return result end function premake.ghs.getlibfiles(cfg) local result = {} return result end function premake.ghs.getlinkflags(cfg) local result = {} for _, value in ipairs(premake.getlinks(cfg, "system", "name")) do table.insert(result, '-lnk=' .. _MAKE.esc(value)) end return result end function premake.ghs.getarchiveflags(prj, cfg, ndx) if prj.options.ArchiveSplit then error("ghs tool does not support split archives") end local result = {} local platform = platforms[cfg.platform] table.insert(result, platform.arflags) return result end function premake.ghs.getdefines(defines) local result = { } for _,def in ipairs(defines) do table.insert(result, '-D' .. def) end return result end function premake.ghs.getincludedirs(includedirs) local result = { } for _,dir in ipairs(includedirs) do table.insert(result, "-I" .. _MAKE.esc(dir)) end return result end function premake.ghs.getcfgsettings(cfg) return platforms[cfg.platform].cfgsettings end premake.msc = { } premake.msc.namestyle = "windows" premake.ow = { } premake.ow.namestyle = "windows" premake.ow.cc = "WCL386" premake.ow.cxx = "WCL386" premake.ow.ar = "ar" local cflags = { PedanticWarnings = "-wx", ExtraWarnings = "-wx", FatalWarning = "-we", FloatFast = "-omn", FloatStrict = "-op", Optimize = "-ox", OptimizeSize = "-os", OptimizeSpeed = "-ot", Symbols = "-d2", } local cxxflags = { NoExceptions = "-xd", NoRTTI = "-xr", } premake.ow.platforms = { Native = { flags = "" }, } function premake.ow.getcppflags(cfg) return {} end function premake.ow.getcflags(cfg) local result = table.translate(cfg.flags, cflags) if (cfg.flags.Symbols) then table.insert(result, "-hw") -- Watcom debug format for Watcom debugger end return result end function premake.ow.getcxxflags(cfg) local result = table.translate(cfg.flags, cxxflags) return result end function premake.ow.getldflags(cfg) local result = { } if (cfg.flags.Symbols) then table.insert(result, "op symf") end return result end function premake.ow.getlibfiles(cfg) local result = {} return result end function premake.ow.getlinkflags(cfg) local result = { } return result end function premake.ow.getdefines(defines) local result = { } for _,def in ipairs(defines) do table.insert(result, '-D' .. def) end return result end function premake.ow.getincludedirs(includedirs) local result = { } for _,dir in ipairs(includedirs) do table.insert(result, '-I "' .. dir .. '"') end return result end premake.snc = { } premake.snc.cc = "snc" premake.snc.cxx = "g++" premake.snc.ar = "ar" local cflags = { PedanticWarnings = "-Xdiag=2", ExtraWarnings = "-Xdiag=2", FatalWarnings = "-Xquit=2", } local cxxflags = { NoExceptions = "", -- No exceptions is the default in the SNC compiler. NoRTTI = "-Xc-=rtti", } premake.snc.platforms = { PS3 = { cc = "ppu-lv2-g++", cxx = "ppu-lv2-g++", ar = "ppu-lv2-ar", cppflags = "-MMD -MP", } } local platforms = premake.snc.platforms function premake.snc.getcppflags(cfg) local result = { } table.insert(result, platforms[cfg.platform].cppflags) return result end function premake.snc.getcflags(cfg) local result = table.translate(cfg.flags, cflags) table.insert(result, platforms[cfg.platform].flags) if cfg.kind == "SharedLib" then table.insert(result, "-fPIC") end return result end function premake.snc.getcxxflags(cfg) local result = table.translate(cfg.flags, cxxflags) return result end function premake.snc.getldflags(cfg) local result = { } if not cfg.flags.Symbols then table.insert(result, "-s") end if cfg.kind == "SharedLib" then table.insert(result, "-shared") if not cfg.flags.NoImportLib then table.insert(result, '-Wl,--out-implib="' .. cfg.linktarget.fullpath .. '"') end end local platform = platforms[cfg.platform] table.insert(result, platform.flags) table.insert(result, platform.ldflags) return result end function premake.snc.getlibdirflags(cfg) local result = { } for _, value in ipairs(premake.getlinks(cfg, "all", "directory")) do table.insert(result, '-L' .. _MAKE.esc(value)) end return result end function premake.snc.getlibfiles(cfg) local result = {} return result end function premake.snc.getlinkflags(cfg) local result = {} for _, value in ipairs(premake.getlinks(cfg, "system", "name")) do table.insert(result, '-l' .. _MAKE.esc(value)) end return result end function premake.snc.getdefines(defines) local result = { } for _,def in ipairs(defines) do table.insert(result, '-D' .. def) end return result end function premake.snc.getincludedirs(includedirs) local result = { } for _,dir in ipairs(includedirs) do table.insert(result, "-I" .. _MAKE.esc(dir)) end return result end premake.valac = { } premake.valac.valac = "valac" premake.valac.cc = premake.gcc.cc premake.valac.glibrc = "glib-compile-resources" local valaflags = { DisableAssert = "--disable-assert", -- Disable assertions DisableSinceCheck = "--disable-since-check", -- Do not check whether used symbols exist in local packages DisableWarnings = "--disable-warnings", -- Disable warnings EnableChecking = "--enable-checking", -- Enable additional run-time checks EnableDeprecated = "--enable-deprecated", -- Enable deprecated features EnableExperimental = "--enable-experimental", -- Enable experimental features EnableExperimentalNonNull = "--enable-experimental-non-null", -- Enable experimental enhancements for non-null types EnableGObjectTracing = "--enable-gobject-tracing", -- Enable GObject creation tracing EnableMemProfiler = "--enable-mem-profiler", -- Enable GLib memory profiler FatalWarnings = "--fatal-warnings", -- Treat warnings as fatal HideInternal = "--hide-internal", -- Hide symbols marked as internal NoStdPkg = "--nostdpkg", -- Do not include standard packages Symbols = "-g", -- Produce debug information } local valaccflags = { Optimize = "-O2", OptimizeSize = "-Os", OptimizeSpeed = "-O3", Symbols = "-g", -- Produce debug information } premake.valac.platforms = { Native = { }, x64 = { flags = "-m64" }, } function premake.valac.getvalaflags(cfg) return table.translate(cfg.flags, valaflags) end function premake.valac.getvalaccflags(cfg) return table.translate(cfg.flags, valaccflags) end function premake.valac.getlinks(links) local result = { } for _, pkg in ipairs(links) do table.insert(result, '--pkg ' .. pkg) end return result end function premake.valac.getdefines(defines) local result = { } for _, def in ipairs(defines) do table.insert(result, '-D ' .. def) end return result end function premake.valac.getvapidirs(vapidirs) local result = { } for _, def in ipairs(vapidirs) do table.insert(result, '--vapidir=' .. def) end return result end premake.swift = { } premake.swift.swiftc = "swiftc" premake.swift.swift = "swift" premake.swift.cc = "gcc" premake.swift.ar = "ar" premake.swift.ld = "ld" premake.swift.dsymutil = "dsymutil" local swiftcflags = { Symbols = "-g", -- Produce debug information DisableWarnings = "--suppress-warnings", -- Disable warnings FatalWarnings = "--warnings-as-errors", -- Treat warnings as fatal Optimize = "-O -whole-module-optimization", OptimizeSize = "-O -whole-module-optimization", OptimizeSpeed = "-Ounchecked -whole-module-optimization", MinimumWarnings = "-minimum-warnings", } local swiftlinkflags = { StaticRuntime = "-static-stdlib", } premake.swift.platforms = { Native = { swiftcflags = "", swiftlinkflags = "", }, x64 = { swiftcflags = "", swiftlinkflags = "", } } local platforms = premake.swift.platforms function premake.swift.get_sdk_path(cfg) return string.trim(os.outputof("xcrun --show-sdk-path")) end function premake.swift.get_sdk_platform_path(cfg) return string.trim(os.outputof("xcrun --show-sdk-platform-path")) end function premake.swift.get_toolchain_path(cfg) return string.trim(os.outputof("xcode-select -p")) .. "/Toolchains/XcodeDefault.xctoolchain" end function premake.swift.gettarget(cfg) return "-target x86_64-apple-macosx10.11" end function premake.swift.getswiftcflags(cfg) local result = table.translate(cfg.flags, swiftcflags) table.insert(result, platforms[cfg.platform].swiftcflags) result = table.join(result, cfg.buildoptions_swift) if cfg.kind == "SharedLib" or cfg.kind == "StaticLib" then table.insert(result, "-parse-as-library") end table.insert(result, premake.swift.gettarget(cfg)) return result end function premake.swift.getswiftlinkflags(cfg) local result = table.translate(cfg.flags, swiftlinkflags) table.insert(result, platforms[cfg.platform].swiftlinkflags) result = table.join(result, cfg.linkoptions_swift) if cfg.kind == "SharedLib" or cfg.kind == "StaticLib" then table.insert(result, "-emit-library") else table.insert(result, "-emit-executable") end table.insert(result, premake.swift.gettarget(cfg)) return result end function premake.swift.getmodulemaps(cfg) local maps = {} if next(cfg.swiftmodulemaps) then for _, mod in ipairs(cfg.swiftmodulemaps) do table.insert(maps, string.format("-Xcc -fmodule-map-file=%s", mod)) end end return maps end function premake.swift.getlibdirflags(cfg) return premake.gcc.getlibdirflags(cfg) end function premake.swift.getldflags(cfg) local result = { platforms[cfg.platform].ldflags } local links = premake.getlinks(cfg, "siblings", "basename") for _,v in ipairs(links) do if path.getextension(v) == ".framework" then table.insert(result, "-framework "..v) else table.insert(result, "-l"..v) end end return result end function premake.swift.getlinkflags(cfg) return premake.gcc.getlinkflags(cfg) end function premake.swift.getarchiveflags(cfg) return "" end function premake.checkprojects() local action = premake.action.current() for sln in premake.solution.each() do if (#sln.projects == 0) then return nil, "solution '" .. sln.name .. "' needs at least one project" end if (#sln.configurations == 0) then return nil, "solution '" .. sln.name .. "' needs configurations" end for prj in premake.solution.eachproject(sln) do if (not prj.language) then return nil, "project '" ..prj.name .. "' needs a language" end if (action.valid_languages) then if (not table.contains(action.valid_languages, prj.language)) then return nil, "the " .. action.shortname .. " action does not support " .. prj.language .. " projects" end end for cfg in premake.eachconfig(prj) do if (not cfg.kind) then return nil, "project '" ..prj.name .. "' needs a kind in configuration '" .. cfg.name .. "'" end if (action.valid_kinds) then if (not table.contains(action.valid_kinds, cfg.kind)) then return nil, "the " .. action.shortname .. " action does not support " .. cfg.kind .. " projects" end end end if action.oncheckproject then action.oncheckproject(prj) end end end return true end function premake.checktools() local action = premake.action.current() if (not action.valid_tools) then return true end for tool, values in pairs(action.valid_tools) do if (_OPTIONS[tool]) then if (not table.contains(values, _OPTIONS[tool])) then return nil, "the " .. action.shortname .. " action does not support /" .. tool .. "=" .. _OPTIONS[tool] .. " (yet)" end else _OPTIONS[tool] = values[1] end end return true end function premake.showhelp() printf("") printf("Usage: genie [options] action [arguments]") printf("") printf("OPTIONS") printf("") for option in premake.option.each() 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(" --%-15s %s", trigger, description) if (option.allowed) then for _, value in ipairs(option.allowed) do printf(" %-14s %s", value[1], value[2]) 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://github.com/bkaradzic/genie") end premake._filelevelconfig = false premake._checkgenerate = true function premake.generate(obj, filename, callback) local prev = io.capture() local abort = (callback(obj) == false) local new = io.endcapture(prev) if abort then premake.stats.num_skipped = premake.stats.num_skipped + 1 return end filename = premake.project.getfilename(obj, filename) if (premake._checkgenerate) then local delta = false local f, err = io.open(filename, "rb") if (not f) then if string.find(err, "No such file or directory") then delta = true else error(err, 0) end else local existing = f:read("*all") if existing ~= new then delta = true end f:close() end if delta then printf("Generating %q", filename) local f, err = io.open(filename, "wb") if (not f) then error(err, 0) end f:write(new) f:close() premake.stats.num_generated = premake.stats.num_generated + 1 else premake.stats.num_skipped = premake.stats.num_skipped + 1 end else printf("Generating %q", filename) local f, err = io.open(filename, "wb") if (not f) then error(err, 0) end f:write(new) f:close() premake.stats.num_generated = premake.stats.num_generated + 1 end end function premake.findDefaultScript(dir, search_upwards) search_upwards = search_upwards or true local last = "" while dir ~= last do for _, name in ipairs({ "genie.lua", "solution.lua", "premake4.lua" }) do local script0 = dir .. "/" .. name if (os.isfile(script0)) then return dir, name end local script1 = dir .. "/scripts/" .. name if (os.isfile(script1)) then return dir .. "/scripts/", name end end last = dir dir = path.getabsolute(dir .. "/..") if dir == "." or not search_upwards then break end end return nil, nil end iter = {} function iter.sortByKeys(arr, f) local a = table.keys(arr) table.sort(a, f) local i = 0 return function() i = i + 1 if a[i] ~= nil then return a[i], arr[a[i]] end end end Set_mt = {} function Set(t) local set = {} for k, l in ipairs(t) do set[l] = true end setmetatable(set, Set_mt) return set end function Set_mt.union(a, b) local res = Set{} for k in pairs(a) do res[k] = true end for k in pairs(b) do res[k] = true end return res end function Set_mt.intersection(a, b) local res = Set{} for k in pairs(a) do res[k] = b[k] end return res end local function get_cache(a) if not rawget(a, "__cache") then rawset(a, "__cache", Set_mt.totable(a)) end return rawget(a, "__cache") end function Set_mt.len(a) return #get_cache(a) end function Set_mt.implode(a, sep) return table.concat(get_cache(a), sep) end function Set_mt.totable(a) local res = {} for k in pairs(a) do table.insert(res, k) end return res end function Set_mt.difference(a, b) if getmetatable(b) ~= Set_mt then if type(b) ~= "table" then error(type(b).." is not a Set or table") end b=Set(b) end local res = Set{} for k in pairs(a) do res[k] = not b[k] or nil end rawset(res, "__cache", nil) return res end function Set_mt.__index(a, i) if type(i) == "number" then return get_cache(a)[i] end return Set_mt[i] or rawget(a, i) end Set_mt.__add = Set_mt.union Set_mt.__mul = Set_mt.intersection Set_mt.__sub = Set_mt.difference Set_mt.__len = Set_mt.len Set_mt.__concat = Set_mt.implodepremake.cmake = { } newaction { trigger = "cmake", shortname = "CMake", description = "Generate CMake project files", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc" }, }, onsolution = function(sln) premake.generate(sln, "CMakeLists.txt", premake.cmake.workspace) end, onproject = function(prj) premake.generate(prj, "%%/CMakeLists.txt", premake.cmake.project) end, oncleansolution = function(sln) premake.clean.file(sln, "CMakeLists.txt") end, oncleanproject = function(prj) premake.clean.file(prj, "%%/CMakeLists.txt") end }function premake.cmake.workspace(sln) if (sln.location ~= _WORKING_DIR) then local name = string.format("%s/CMakeLists.txt", _WORKING_DIR) local f, err = io.open(name, "wb") if (not f) then error(err, 0) end f:write([[ # CMakeLists autogenerated by GENie project(GENie) cmake_minimum_required(VERSION 3.15) ######################################################################### # Set a default build type if none was specified # Source: https://blog.kitware.com/cmake-and-the-default-build-type/ set(default_build_type "Release") if(EXISTS "${CMAKE_SOURCE_DIR}/.git") set(default_build_type "Debug") endif() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to '${default_build_type}' as none was specified.") set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() ######################################################################### ]]) if os.is("windows") then f:write('cmake_policy(SET CMP0091 NEW)\n') end f:write('add_subdirectory('.. path.getrelative(_WORKING_DIR, sln.location) ..')\n') f:close() end _p([[ # CMakeLists autogenerated by GENie cmake_minimum_required(VERSION 3.15) ]]) if os.is("windows") then _p('cmake_policy(SET CMP0091 NEW)') end for i,prj in ipairs(sln.projects) do local name = premake.esc(prj.name) _p('add_subdirectory(%s)', name) end end local cmake = premake.cmake local tree = premake.tree local includestr = 'include_directories(../%s)' local definestr = 'add_definitions(-D%s)' local function is_excluded(prj, cfg, file) if table.icontains(prj.excludes, file) then return true end if table.icontains(cfg.excludes, file) then return true end return false end function cmake.excludedFiles(prj, cfg, src) for _, v in ipairs(src) do if (is_excluded(prj, cfg, v)) then _p(1, 'list(REMOVE_ITEM source_list ../%s)', v) end end end function cmake.list(value) if #value > 0 then return " " .. table.concat(value, " ") else return "" end end function cmake.listWrapped(value, prefix, postfix) if #value > 0 then return prefix .. table.concat(value, postfix .. prefix) .. postfix else return "" end end function cmake.files(prj) local ret = {} local tr = premake.project.buildsourcetree(prj) tree.traverse(tr, { onbranchenter = function(node, depth) end, onbranchexit = function(node, depth) end, onleaf = function(node, depth) assert(node, "unexpected empty node") if node.cfg then table.insert(ret, node.cfg.name) _p(1, '../%s', node.cfg.name) end end, }, true, 1) return ret end function cmake.header(prj) _p('# %s project autogenerated by GENie', premake.action.current().shortname) _p('cmake_minimum_required(VERSION 3.15)') if os.is("windows") then -- Add support for CMP0091, see https://cmake.org/cmake/help/latest/policy/CMP0091.html _p('cmake_policy(SET CMP0091 NEW)') end _p('') _p('project(%s)', premake.esc(prj.name)) _p('') _p('include(GNUInstallDirs)') end function cmake.customtasks(prj) local dirs = {} local tasks = {} for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do table.insert(tasks, buildtask) local d = string.format("${CMAKE_CURRENT_SOURCE_DIR}/../%s", path.getdirectory(path.getrelative(prj.location, buildtask[2]))) if not table.contains(dirs, d) then table.insert(dirs, d) _p('file(MAKE_DIRECTORY \"%s\")', d) end end end _p('') for _, buildtask in ipairs(tasks) do local deps = string.format("${CMAKE_CURRENT_SOURCE_DIR}/../%s ", path.getrelative(prj.location, buildtask[1])) local outputs = string.format("${CMAKE_CURRENT_SOURCE_DIR}/../%s ", path.getrelative(prj.location, buildtask[2])) local msg = "" for _, depdata in ipairs(buildtask[3] or {}) do deps = deps .. string.format("${CMAKE_CURRENT_SOURCE_DIR}/../%s ", path.getrelative(prj.location, depdata)) end _p('add_custom_command(') _p(1, 'OUTPUT %s', outputs) _p(1, 'DEPENDS %s', deps) for _, cmdline in ipairs(buildtask[4] or {}) do if (cmdline:sub(1, 1) ~= "@") then local cmd = cmdline local num = 1 for _, depdata in ipairs(buildtask[3] or {}) do cmd = string.gsub(cmd, "%$%(" .. num .. "%)", string.format("${CMAKE_CURRENT_SOURCE_DIR}/../%s ", path.getrelative(prj.location, depdata))) num = num + 1 end cmd = string.gsub(cmd, "%$%(<%)", string.format("${CMAKE_CURRENT_SOURCE_DIR}/../%s ", path.getrelative(prj.location, buildtask[1]))) cmd = string.gsub(cmd, "%$%(@%)", outputs) _p(1, 'COMMAND %s', cmd) else msg = cmdline end end _p(1, 'COMMENT \"%s\"', msg) _p(')') _p('') end end function cmake.depRules(prj) local maintable = {} for _, dependency in ipairs(prj.dependency) do for _, dep in ipairs(dependency) do if path.issourcefile(dep[1]) then local dep1 = premake.esc(path.getrelative(prj.location, dep[1])) local dep2 = premake.esc(path.getrelative(prj.location, dep[2])) if not maintable[dep1] then maintable[dep1] = {} end table.insert(maintable[dep1], dep2) end end end for key, _ in pairs(maintable) do local deplist = {} local depsname = string.format('%s_deps', path.getname(key)) for _, d2 in pairs(maintable[key]) do table.insert(deplist, d2) end _p('set(') _p(1, depsname) for _, v in pairs(deplist) do _p(1, '${CMAKE_CURRENT_SOURCE_DIR}/../%s', v) end _p(')') _p('') _p('set_source_files_properties(') _p(1, '\"${CMAKE_CURRENT_SOURCE_DIR}/../%s\"', key) _p(1, 'PROPERTIES OBJECT_DEPENDS \"${%s}\"', depsname) _p(')') _p('') end end function cmake.commonRules(conf, str) local Dupes = {} local t2 = {} for _, cfg in ipairs(conf) do local cfgd = iif(str == includestr, cfg.includedirs, cfg.defines) for _, v in ipairs(cfgd) do if(t2[v] == #conf - 1) then _p(str, v) table.insert(Dupes, v) end if not t2[v] then t2[v] = 1 else t2[v] = t2[v] + 1 end end end return Dupes end function cmake.cfgRules(cfg, dupes, str) for _, v in ipairs(cfg) do if (not table.icontains(dupes, v)) then _p(1, str, v) end end end function cmake.removeCrosscompiler(platforms) for i = #platforms, 1, -1 do if premake.platforms[platforms[i]].iscrosscompiler then table.remove(platforms, i) end end end function cmake.project(prj) io.indent = " " cmake.header(prj) _p('set(') _p('source_list') local source_files = cmake.files(prj) _p(')') _p('') local nativeplatform = iif(os.is64bit(), "x64", "x32") local cc = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") cmake.removeCrosscompiler(platforms) local configurations = {} for _, platform in ipairs(platforms) do for cfg in premake.eachconfig(prj, platform) do -- TODO: Extend support for 32-bit targets on 64-bit hosts if cfg.platform == nativeplatform then table.insert(configurations, cfg) end end end local commonIncludes = cmake.commonRules(configurations, includestr) local commonDefines = cmake.commonRules(configurations, definestr) _p('') for _, cfg in ipairs(configurations) do _p('if(CMAKE_BUILD_TYPE MATCHES \"%s\")', cfg.name) -- list excluded files cmake.excludedFiles(prj, cfg, source_files) -- add includes directories cmake.cfgRules(cfg.includedirs, commonIncludes, includestr) -- add build defines cmake.cfgRules(cfg.defines, commonDefines, definestr) -- set CXX flags _p(1, 'set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} %s\")', cmake.list(table.join(cc.getcppflags(cfg), cc.getcflags(cfg), cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_cpp))) -- set C flags _p(1, 'set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} %s\")', cmake.list(table.join(cc.getcppflags(cfg), cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_c))) _p('endif()') _p('') end -- force CPP if needed if (prj.options.ForceCPP) then _p('set_source_files_properties(${source_list} PROPERTIES LANGUAGE CXX)') end -- add custom tasks cmake.customtasks(prj) -- per-dependency build rules cmake.depRules(prj) for _, cfg in ipairs(configurations) do _p('if(CMAKE_BUILD_TYPE MATCHES \"%s\")', cfg.name) if (prj.kind == 'StaticLib') then _p(1, 'add_library(%s STATIC ${source_list})', premake.esc(cfg.buildtarget.basename)) -- Install _p(1, 'install(TARGETS %s RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR})', premake.esc(cfg.buildtarget.basename)) end if (prj.kind == 'SharedLib') then _p(1, 'add_library(%s SHARED ${source_list})', premake.esc(cfg.buildtarget.basename)) -- Install _p(1, 'install(TARGETS %s RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR})', premake.esc(cfg.buildtarget.basename)) end if (prj.kind == 'ConsoleApp' or prj.kind == 'WindowedApp') then _p(1, 'add_executable(%s ${source_list})', premake.esc(cfg.buildtarget.basename)) local libdirs = cmake.listWrapped(premake.esc(premake.getlinks(cfg, "all", "directory")), " -L\"../", "\"") _p(1, 'target_link_libraries(%s%s%s%s%s%s)', premake.esc(cfg.buildtarget.basename), libdirs, cmake.list(cfg.linkoptions), cmake.list(cc.getldflags(cfg)), cmake.list(premake.esc(premake.getlinks(cfg, "siblings", "basename"))), cmake.list(cc.getlinkflags(cfg))) -- Install _p(1, 'install(TARGETS %s RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})', premake.esc(cfg.buildtarget.basename)) end _p('endif()') _p('') end end_MAKE = { } premake.make = { } local make = premake.make function _MAKE.esc(value) local result if (type(value) == "table") then result = { } for _,v in ipairs(value) do table.insert(result, _MAKE.esc(v)) end return result else result = value:gsub("\\", "\\\\") result = result:gsub(" ", "\\ ") result = result:gsub("%%(", "\\%(") result = result:gsub("%%)", "\\%)") result = result:gsub("$\\%((.-)\\%)", "$%(%1%)") return result end end function _MAKE.escquote(value) local result if (type(value) == "table") then result = { } for _,v in ipairs(value) do table.insert(result, _MAKE.escquote(v)) end return result else result = value:gsub(" ", "\\ ") result = result:gsub("\"", "\\\"") return result end end function premake.make_copyrule(source, target) _p('%s: %s', target, source) _p('\t@echo Copying $(notdir %s)', target) _p('\t-$(call COPY,%s,%s)', source, target) end function premake.make_mkdirrule(var) _p('\t@echo Creating %s', var) _p('\t-$(call MKDIR,%s)', var) _p('') end function make.list(value) if #value > 0 then return " " .. table.concat(value, " ") else return "" end end function _MAKE.getmakefilename(this, searchprjs) local count = 0 for sln in premake.solution.each() do if (sln.location == this.location) then count = count + 1 end if (searchprjs) then for _,prj in ipairs(sln.projects) do if (prj.location == this.location) then count = count + 1 end end end end if (count == 1) then return "Makefile" else return this.name .. ".make" end end function _MAKE.getnames(tbl) local result = table.extract(tbl, "name") for k,v in pairs(result) do result[k] = _MAKE.esc(v) end return result end function make.settings(cfg, cc) if #cfg.makesettings > 0 then for _, value in ipairs(cfg.makesettings) do _p(value) end end local toolsettings = cc.platforms[cfg.platform].cfgsettings if toolsettings then _p(toolsettings) end end newaction { trigger = "gmake", shortname = "GNU Make", description = "Generate GNU makefiles for POSIX, MinGW, and Cygwin", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#", "Vala", "Swift" }, valid_tools = { cc = { "gcc", "ghs" }, dotnet = { "mono", "msnet", "pnet" }, valac = { "valac" }, swift = { "swift" }, }, onsolution = function(sln) premake.generate(sln, _MAKE.getmakefilename(sln, false), premake.make_solution) end, onproject = function(prj) local makefile = _MAKE.getmakefilename(prj, true) if premake.isdotnetproject(prj) then premake.generate(prj, makefile, premake.make_csharp) elseif premake.iscppproject(prj) then premake.generate(prj, makefile, premake.make_cpp) elseif premake.isswiftproject(prj) then premake.generate(prj, makefile, premake.make_swift) else premake.generate(prj, makefile, premake.make_vala) end end, oncleansolution = function(sln) premake.clean.file(sln, _MAKE.getmakefilename(sln, false)) end, oncleanproject = function(prj) premake.clean.file(prj, _MAKE.getmakefilename(prj, true)) end, gmake = {} } function premake.make_solution(sln) local cc = premake[_OPTIONS.cc] local platforms = premake.filterplatforms(sln, cc.platforms, "Native") _p('# %s solution makefile autogenerated by GENie', premake.action.current().shortname) _p('# Type "make help" for usage help') _p('') _p('ifndef config') _p(' config=%s', _MAKE.esc(premake.getconfigname(sln.configurations[1], platforms[1], true))) _p('endif') _p('export config') _p('') local projects = table.extract(sln.projects, "name") table.sort(projects) _p('PROJECTS := %s', table.concat(_MAKE.esc(projects), " ")) _p('') _p('.PHONY: all clean help $(PROJECTS)') _p('') _p('all: $(PROJECTS)') _p('') for _, prj in ipairs(sln.projects) do _p('%s: %s', _MAKE.esc(prj.name), table.concat(_MAKE.esc(table.extract(premake.getdependencies(prj), "name")), " ")) if (not sln.messageskip) or (not table.contains(sln.messageskip, "SkipBuildingMessage")) then _p('\t@echo "==== Building %s ($(config)) ===="', prj.name) end _p('\t@${MAKE} --no-print-directory -C %s -f %s', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(_MAKE.getmakefilename(prj, true))) _p('') end _p('clean:') for _ ,prj in ipairs(sln.projects) do _p('\t@${MAKE} --no-print-directory -C %s -f %s clean', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(_MAKE.getmakefilename(prj, true))) end _p('') _p('help:') _p(1,'@echo "Usage: make [config=name] [target]"') _p(1,'@echo ""') _p(1,'@echo "CONFIGURATIONS:"') local cfgpairs = { } for _, platform in ipairs(platforms) do for _, cfgname in ipairs(sln.configurations) do _p(1,'@echo " %s"', premake.getconfigname(cfgname, platform, true)) end end _p(1,'@echo ""') _p(1,'@echo "TARGETS:"') _p(1,'@echo " all (default)"') _p(1,'@echo " clean"') for _, prj in ipairs(sln.projects) do _p(1,'@echo " %s"', prj.name) end _p(1,'@echo ""') _p(1,'@echo "For more information, see https://github.com/bkaradzic/genie"') end -- -- premake.make.cpp = { } premake.make.override = { } premake.make.makefile_ignore = false local cpp = premake.make.cpp local make = premake.make function premake.make_cpp(prj) local cc = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") local action = premake.action.current() premake.gmake_cpp_header(prj, cc, platforms) premake.gmake_cpp_configs(prj, cc, platforms) table.sort(prj.allfiles) local objdirs = {} local additionalobjdirs = {} for _, file in ipairs(prj.allfiles) do if path.issourcefile(file) then objdirs[_MAKE.esc(path.getdirectory(path.trimdots(file)))] = 1 end end for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do additionalobjdirs[_MAKE.esc(path.getdirectory(path.getrelative(prj.location,buildtask[2])))] = 1 end end _p('OBJDIRS := \\') _p('\t$(OBJDIR) \\') for dir, _ in iter.sortByKeys(objdirs) do _p('\t$(OBJDIR)/%s \\', dir) end for dir, _ in iter.sortByKeys(additionalobjdirs) do _p('\t%s \\', dir) end _p('') _p('RESOURCES := \\') for _, file in ipairs(prj.allfiles) do if path.isresourcefile(file) then _p('\t$(OBJDIR)/%s.res \\', _MAKE.esc(path.getbasename(file))) end end _p('') _p('.PHONY: clean prebuild prelink') _p('') if os.is("MacOSX") and prj.kind == "WindowedApp" and not prj.options.SkipBundling then _p('all: $(OBJDIRS) $(TARGETDIR) prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist') else _p('all: $(OBJDIRS) $(TARGETDIR) prebuild prelink $(TARGET)') end _p('\t@:') _p('') if (prj.kind == "StaticLib" and prj.options.ArchiveSplit) then _p('define max_args') _p('\t$(eval _args:=)') _p('\t$(foreach obj,$3,$(eval _args+=$(obj))$(if $(word $2,$(_args)),$1 $(_args)$(EOL)$(eval _args:=)))') _p('\t$(if $(_args),$1 $(_args))') _p('endef') _p('') _p('define EOL') _p('') _p('') _p('endef') _p('') end _p('$(TARGET): $(GCH) $(OBJECTS) $(LIBDEPS) $(EXTERNAL_LIBS) $(RESOURCES) $(OBJRESP) $(LDRESP) | $(TARGETDIR) $(OBJDIRS)') if prj.kind == "StaticLib" then if prj.msgarchiving then _p('\t@echo ' .. prj.msgarchiving) else _p('\t@echo Archiving %s', prj.name) end if (not prj.archivesplit_size) then prj.archivesplit_size=200 end if (not prj.options.ArchiveSplit) then _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET)') _p('else') _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') _p('endif') _p('\t$(SILENT) $(LINKCMD) $(LINKOBJS)' .. (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) else _p('\t$(call RM,$(TARGET))') _p('\t@$(call max_args,$(LINKCMD),'.. prj.archivesplit_size ..',$(LINKOBJS))' .. (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) _p('\t$(SILENT) $(LINKCMD_NDX)') end else if prj.msglinking then _p('\t@echo ' .. prj.msglinking) else _p('\t@echo Linking %s', prj.name) end _p('\t$(SILENT) $(LINKCMD)') end _p('\t$(POSTBUILDCMDS)') _p('') _p('$(TARGETDIR):') premake.make_mkdirrule("$(TARGETDIR)") _p('$(OBJDIRS):') if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCreatingMessage")) then _p('\t@echo Creating $(@)') end _p('\t-$(call MKDIR,$@)') _p('') if os.is("MacOSX") and prj.kind == "WindowedApp" and not prj.options.SkipBundling then _p('$(dir $(TARGETDIR))PkgInfo:') _p('$(dir $(TARGETDIR))Info.plist:') _p('') end _p('clean:') if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCleaningMessage")) then _p('\t@echo Cleaning %s', prj.name) end _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('') _p('prebuild:') _p('\t$(PREBUILDCMDS)') _p('') _p('prelink:') _p('\t$(PRELINKCMDS)') _p('') cpp.pchrules(prj) cpp.fileRules(prj, cc) cpp.dependencyRules(prj) for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do local deps = string.format("%s ",path.getrelative(prj.location,buildtask[1])) for _, depdata in ipairs(buildtask[3] or {}) do deps = deps .. string.format("%s ",path.getrelative(prj.location,depdata)) end _p('%s: %s | $(TARGETDIR) $(OBJDIRS)' ,path.getrelative(prj.location,buildtask[2]) , deps ) for _, cmdline in ipairs(buildtask[4] or {}) do local cmd = cmdline local num = 1 for _, depdata in ipairs(buildtask[3] or {}) do cmd = string.gsub(cmd,"%$%(" .. num .."%)", string.format("%s ",path.getrelative(prj.location,depdata))) num = num + 1 end cmd = string.gsub(cmd, "%$%(<%)", "$<") cmd = string.gsub(cmd, "%$%(@%)", "$@") _p('\t$(SILENT) %s',cmd) end _p('') end end _p('-include $(OBJECTS:%%.o=%%.d)') _p('ifneq (,$(PCH))') _p(' -include $(OBJDIR)/$(notdir $(PCH)).d') _p(' -include $(OBJDIR)/$(notdir $(PCH))_objc.d') _p('endif') end function premake.gmake_cpp_header(prj, cc, platforms) _p('# %s project makefile autogenerated by GENie', premake.action.current().shortname) _p('') _p('.SUFFIXES:') -- Delete the default suffix rules. _p('') _p('ifndef config') _p(' config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true))) _p('endif') _p('') _p('ifndef verbose') _p(' SILENT = @') _p('endif') _p('') _p('SHELLTYPE := msdos') _p('ifeq (,$(ComSpec)$(COMSPEC))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('') _p('ifeq (posix,$(SHELLTYPE))') _p(' MKDIR = $(SILENT) mkdir -p "$(1)"') _p(' COPY = $(SILENT) cp -fR "$(1)" "$(2)"') _p(' RM = $(SILENT) rm -f "$(1)"') _p('else') _p(' MKDIR = $(SILENT) mkdir "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p(' COPY = $(SILENT) copy /Y "$(subst /,\\\\,$(1))" "$(subst /,\\\\,$(2))"') _p(' RM = $(SILENT) del /F "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p('endif') _p('') _p('CC = %s', cc.cc) _p('CXX = %s', cc.cxx) _p('AR = %s', cc.ar) _p('') _p('ifndef RESCOMP') _p(' ifdef WINDRES') _p(' RESCOMP = $(WINDRES)') _p(' else') _p(' RESCOMP = %s', cc.rc or 'windres') _p(' endif') _p('endif') _p('') if (not premake.make.makefile_ignore) then _p('MAKEFILE = %s', _MAKE.getmakefilename(prj, true)) _p('') end end local function is_excluded(prj, cfg, file) if table.icontains(prj.excludes, file) then return true end if table.icontains(cfg.excludes, file) then return true end return false end function premake.gmake_cpp_configs(prj, cc, platforms) for _, platform in ipairs(platforms) do for cfg in premake.eachconfig(prj, platform) do premake.gmake_cpp_config(prj, cfg, cc) end end end function premake.gmake_cpp_config(prj, cfg, cc) _p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname)) cpp.platformtools(cfg, cc) local targetDir = _MAKE.esc(cfg.buildtarget.directory) _p(' ' .. (table.contains(premake.make.override,"OBJDIR") and "override " or "") .. 'OBJDIR = %s', _MAKE.esc(cfg.objectsdir)) _p(' ' .. (table.contains(premake.make.override,"TARGETDIR") and "override " or "") .. 'TARGETDIR = %s', iif(targetDir == "", ".", targetDir)) _p(' ' .. (table.contains(premake.make.override,"TARGET") and "override " or "") .. 'TARGET = $(TARGETDIR)/%s', _MAKE.esc(cfg.buildtarget.name)) _p(' DEFINES +=%s', make.list(_MAKE.escquote(cc.getdefines(cfg.defines)))) local id = make.list(cc.getincludedirs(cfg.includedirs)); local uid = make.list(cc.getquoteincludedirs(cfg.userincludedirs)) local sid = make.list(cc.getsystemincludedirs(cfg.systemincludedirs)) if id ~= "" then _p(' INCLUDES +=%s', id) end if uid ~= "" then _p(' INCLUDES +=%s', uid) end if sid ~= "" then _p(' INCLUDES +=%s', sid) end cpp.pchconfig(cfg) cpp.flags(cfg, cc) cpp.linker(prj, cfg, cc) table.sort(cfg.files) if cfg.flags.UseObjectResponseFile then _p(' OBJRESP = $(OBJDIR)/%s_objects', prj.name) else _p(' OBJRESP =') end _p(' OBJECTS := \\') for _, file in ipairs(cfg.files) do if path.issourcefile(file) then if not is_excluded(prj, cfg, file) then _p('\t$(OBJDIR)/%s.o \\' , _MAKE.esc(path.trimdots(path.removeext(file))) ) end end end _p('') _p(' define PREBUILDCMDS') if #cfg.prebuildcommands > 0 then _p('\t@echo Running pre-build commands') _p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t")) end _p(' endef') _p(' define PRELINKCMDS') if #cfg.prelinkcommands > 0 then _p('\t@echo Running pre-link commands') _p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t")) end _p(' endef') _p(' define POSTBUILDCMDS') if #cfg.postbuildcommands > 0 then _p('\t@echo Running post-build commands') _p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t")) end _p(' endef') make.settings(cfg, cc) _p('endif') _p('') end function cpp.platformtools(cfg, cc) local platform = cc.platforms[cfg.platform] if platform.cc then _p(' CC = %s', platform.cc) end if platform.cxx then _p(' CXX = %s', platform.cxx) end if platform.ar then _p(' AR = %s', platform.ar) end end function cpp.flags(cfg, cc) if cfg.pchheader and not cfg.flags.NoPCH then _p(' FORCE_INCLUDE += -include $(OBJDIR)/$(notdir $(PCH))') _p(' FORCE_INCLUDE_OBJC += -include $(OBJDIR)/$(notdir $(PCH))_objc') end if #cfg.forcedincludes > 0 then _p(' FORCE_INCLUDE += -include %s' ,_MAKE.esc(table.concat(cfg.forcedincludes, ";"))) end _p(' ALL_CPPFLAGS += $(CPPFLAGS) %s $(DEFINES) $(INCLUDES)', table.concat(cc.getcppflags(cfg), " ")) _p(' ALL_ASMFLAGS += $(ASMFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_asm))) _p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_c))) _p(' ALL_CXXFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_cpp))) _p(' ALL_OBJCFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getobjcflags(cfg), cfg.buildoptions, cfg.buildoptions_objc))) _p(' ALL_OBJCPPFLAGS += $(CXXFLAGS) $(CFLAGS) $(ALL_CPPFLAGS) $(ARCH)%s', make.list(table.join(cc.getcflags(cfg), cc.getcxxflags(cfg), cc.getobjcflags(cfg), cfg.buildoptions, cfg.buildoptions_objcpp))) _p(' ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES)%s', make.list(table.join(cc.getdefines(cfg.resdefines), cc.getincludedirs(cfg.resincludedirs), cfg.resoptions))) end function cpp.linker(prj, cfg, cc) local libdeps local lddeps if #cfg.wholearchive > 0 then libdeps = {} lddeps = {} for _, linkcfg in ipairs(premake.getlinks(cfg, "siblings", "object")) do local linkpath = path.rebase(linkcfg.linktarget.fullpath, linkcfg.location, cfg.location) if table.icontains(cfg.wholearchive, linkcfg.project.name) then lddeps = table.join(lddeps, cc.wholearchive(linkpath)) else table.insert(lddeps, linkpath) end table.insert(libdeps, linkpath) end libdeps = make.list(_MAKE.esc(libdeps)) lddeps = make.list(_MAKE.esc(lddeps)) else libdeps = make.list(_MAKE.esc(premake.getlinks(cfg, "siblings", "fullpath"))) lddeps = libdeps end _p(' ALL_LDFLAGS += $(LDFLAGS)%s', make.list(table.join(cc.getlibdirflags(cfg), cc.getldflags(cfg), cfg.linkoptions))) _p(' LIBDEPS +=%s', libdeps) _p(' LDDEPS +=%s', lddeps) if cfg.flags.UseLDResponseFile then _p(' LDRESP = $(OBJDIR)/%s_libs', prj.name) _p(' LIBS += @$(LDRESP)%s', make.list(cc.getlinkflags(cfg))) else _p(' LDRESP =') _p(' LIBS += $(LDDEPS)%s', make.list(cc.getlinkflags(cfg))) end _p(' EXTERNAL_LIBS +=%s', make.list(cc.getlibfiles(cfg))) _p(' LINKOBJS = %s', (cfg.flags.UseObjectResponseFile and "@$(OBJRESP)" or "$(OBJECTS)")) if cfg.kind == "StaticLib" then if (not prj.options.ArchiveSplit) then _p(' LINKCMD = $(AR) %s $(TARGET)', make.list(cc.getarchiveflags(prj, cfg, false))) else _p(' LINKCMD = $(AR) %s $(TARGET)', make.list(cc.getarchiveflags(prj, cfg, false))) _p(' LINKCMD_NDX = $(AR) %s $(TARGET)', make.list(cc.getarchiveflags(prj, cfg, true))) end else local tool = iif(cfg.language == "C", "CC", "CXX") local startgroup = '' local endgroup = '' if (cfg.flags.LinkSupportCircularDependencies) then startgroup = '-Wl,--start-group ' endgroup = ' -Wl,--end-group' end _p(' LINKCMD = $(%s) -o $(TARGET) $(LINKOBJS) $(RESOURCES) $(ARCH) $(ALL_LDFLAGS) %s$(LIBS)%s', tool, startgroup, endgroup) end end function cpp.pchconfig(cfg) if not cfg.pchheader or cfg.flags.NoPCH then return end local pch = cfg.pchheader for _, incdir in ipairs(cfg.includedirs) do local abspath = path.getabsolute(path.join(cfg.project.location, incdir)) local testname = path.join(abspath, pch) if os.isfile(testname) then pch = path.getrelative(cfg.location, testname) break end end _p(' PCH = %s', _MAKE.esc(pch)) _p(' GCH = $(OBJDIR)/$(notdir $(PCH)).gch') _p(' GCH_OBJC = $(OBJDIR)/$(notdir $(PCH))_objc.gch') end function cpp.pchrules(prj) _p('ifneq (,$(PCH))') _p('$(GCH): $(PCH) $(MAKEFILE) | $(OBJDIR)') if prj.msgprecompile then _p('\t@echo ' .. prj.msgprecompile) else _p('\t@echo $(notdir $<)') end local cmd = iif(prj.language == "C", "$(CC) $(ALL_CFLAGS) -x c-header", "$(CXX) $(ALL_CXXFLAGS) -x c++-header") _p('\t$(SILENT) %s $(DEFINES) $(INCLUDES) -o "$@" -c "$<"', cmd) _p('') _p('$(GCH_OBJC): $(PCH) $(MAKEFILE) | $(OBJDIR)') if prj.msgprecompile then _p('\t@echo ' .. prj.msgprecompile) else _p('\t@echo $(notdir $<)') end local cmd = iif(prj.language == "C", "$(CC) $(ALL_OBJCFLAGS) -x objective-c-header", "$(CXX) $(ALL_OBJCPPFLAGS) -x objective-c++-header") _p('\t$(SILENT) %s $(DEFINES) $(INCLUDES) -o "$@" -c "$<"', cmd) _p('endif') _p('') end function cpp.fileRules(prj, cc) local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") _p('ifneq (,$(OBJRESP))') _p('$(OBJRESP): $(OBJECTS) | $(TARGETDIR) $(OBJDIRS)') _p('\t$(SILENT) echo $^') _p('\t$(SILENT) echo $^ > $@') _p('endif') _p('') _p('ifneq (,$(LDRESP))') _p('$(LDRESP): $(LDDEPS) | $(TARGETDIR) $(OBJDIRS)') _p('\t$(SILENT) echo $^') _p('\t$(SILENT) echo $^ > $@') _p('endif') _p('') table.sort(prj.allfiles) for _, file in ipairs(prj.allfiles or {}) do if path.issourcefile(file) then if (path.isobjcfile(file)) then _p('$(OBJDIR)/%s.o: %s $(GCH_OBJC) $(MAKEFILE) | $(OBJDIR)/%s' , _MAKE.esc(path.trimdots(path.removeext(file))) , _MAKE.esc(file) , _MAKE.esc(path.getdirectory(path.trimdots(file))) ) else _p('$(OBJDIR)/%s.o: %s $(GCH) $(MAKEFILE) | $(OBJDIR)/%s' , _MAKE.esc(path.trimdots(path.removeext(file))) , _MAKE.esc(file) , _MAKE.esc(path.getdirectory(path.trimdots(file))) ) end if (path.isobjcfile(file) and prj.msgcompile_objc) then _p('\t@echo ' .. prj.msgcompile_objc) elseif prj.msgcompile then _p('\t@echo ' .. prj.msgcompile) else _p('\t@echo $(notdir $<)') end if (path.isobjcfile(file)) then if (path.iscfile(file)) then _p('\t$(SILENT) $(CXX) $(ALL_OBJCFLAGS) $(FORCE_INCLUDE_OBJC) -o "$@" -c "$<"') else _p('\t$(SILENT) $(CXX) $(ALL_OBJCPPFLAGS) $(FORCE_INCLUDE_OBJC) -o "$@" -c "$<"') end elseif (path.isasmfile(file)) then _p('\t$(SILENT) $(CC) $(ALL_ASMFLAGS) -o "$@" -c "$<"') else cpp.buildcommand(path.iscfile(file) and not prj.options.ForceCPP, "o") end for _, task in ipairs(prj.postcompiletasks or {}) do _p('\t$(SILENT) %s', task) _p('') end _p('') elseif (path.getextension(file) == ".rc") then _p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file)) if prj.msgresource then _p('\t@echo ' .. prj.msgresource) else _p('\t@echo $(notdir $<)') end _p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(ALL_RESFLAGS)') _p('') end end end function cpp.dependencyRules(prj) for _, dependency in ipairs(prj.dependency or {}) do for _, dep in ipairs(dependency or {}) do if (dep[3]==nil or dep[3]==false) then _p('$(OBJDIR)/%s.o: %s' , _MAKE.esc(path.trimdots(path.removeext(path.getrelative(prj.location, dep[1])))) , _MAKE.esc(path.getrelative(prj.location, dep[2])) ) else _p('%s: %s' , _MAKE.esc(dep[1]) , _MAKE.esc(path.getrelative(prj.location, dep[2])) ) end _p('') end end end function cpp.buildcommand(iscfile, objext) local flags = iif(iscfile, '$(CC) $(ALL_CFLAGS)', '$(CXX) $(ALL_CXXFLAGS)') _p('\t$(SILENT) %s $(FORCE_INCLUDE) -o "$@" -c "$<"', flags, objext) end local function 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)/" .. _MAKE.esc(name .. path.getbasename(fname)) .. ".resources" else return fname end end function premake.make_csharp(prj) local csc = premake.dotnet local cfglibs = { } local cfgpairs = { } local anycfg for cfg in premake.eachconfig(prj) do anycfg = cfg cfglibs[cfg] = premake.getlinks(cfg, "siblings", "fullpath") cfgpairs[cfg] = { } for _, fname in ipairs(cfglibs[cfg]) do if path.getdirectory(fname) ~= cfg.buildtarget.directory then cfgpairs[cfg]["$(TARGETDIR)/" .. _MAKE.esc(path.getname(fname))] = _MAKE.esc(fname) end end end local sources = {} local embedded = { } local copypairs = { } for fcfg in premake.project.eachfile(prj) do local action = csc.getbuildaction(fcfg) if action == "Compile" then table.insert(sources, fcfg.name) elseif action == "EmbeddedResource" then table.insert(embedded, fcfg.name) elseif action == "Content" then copypairs["$(TARGETDIR)/" .. _MAKE.esc(path.getname(fcfg.name))] = _MAKE.esc(fcfg.name) elseif path.getname(fcfg.name):lower() == "app.config" then copypairs["$(TARGET).config"] = _MAKE.esc(fcfg.name) end end local paths = table.translate(prj.libdirs, function(v) return path.join(prj.basedir, v) end) paths = table.join({prj.basedir}, paths) for _, libname in ipairs(premake.getlinks(prj, "system", "fullpath")) do local libdir = os.pathsearch(libname..".dll", unpack(paths)) if (libdir) then local target = "$(TARGETDIR)/" .. _MAKE.esc(path.getname(libname)) local source = path.getrelative(prj.basedir, path.join(libdir, libname))..".dll" copypairs[target] = _MAKE.esc(source) end end _p('# %s project makefile autogenerated by GENie', premake.action.current().shortname) _p('') _p('.SUFFIXES:') -- Delete the default suffix rules. _p('') _p('ifndef config') _p(' config=%s', _MAKE.esc(prj.configurations[1]:lower())) _p('endif') _p('') _p('ifndef verbose') _p(' SILENT = @') _p('endif') _p('') _p('SHELLTYPE := msdos') _p('ifeq (,$(ComSpec)$(COMSPEC))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('') _p('ifeq (posix,$(SHELLTYPE))') _p(' MKDIR = $(SILENT) mkdir -p "$(1)"') _p(' COPY = $(SILENT) cp -fR "$(1)" "$(2)"') _p('else') _p(' MKDIR = $(SILENT) mkdir "$(subst /,\\\\,$(1))" 2> nul') _p(' COPY = $(SILENT) copy /Y "$(subst /,\\\\,$(1))" "$(subst /,\\\\,$(2))"') _p('endif') _p('') _p('ifndef CSC') _p(' CSC=%s', csc.getcompilervar(prj)) _p('endif') _p('') _p('ifndef RESGEN') _p(' RESGEN=resgen') _p('endif') _p('') local platforms = premake.filterplatforms(prj.solution, premake[_OPTIONS.cc].platforms) table.insert(platforms, 1, "") for cfg in premake.eachconfig(prj) do premake.gmake_cs_config(cfg, csc, cfglibs) end _p('# To maintain compatibility with VS.NET, these values must be set at the project level') _p('TARGET := $(TARGETDIR)/%s', _MAKE.esc(prj.buildtarget.name)) _p('FLAGS += /t:%s %s', csc.getkind(prj):lower(), table.implode(_MAKE.esc(prj.libdirs), "/lib:", "", " ")) _p('REFERENCES += %s', table.implode(_MAKE.esc(premake.getlinks(prj, "system", "basename")), "/r:", ".dll", " ")) _p('') _p('SOURCES := \\') for _, fname in ipairs(sources) do _p('\t%s \\', _MAKE.esc(path.translate(fname))) end _p('') _p('EMBEDFILES := \\') for _, fname in ipairs(embedded) do _p('\t%s \\', getresourcefilename(prj, fname)) end _p('') _p('COPYFILES += \\') for target, source in pairs(cfgpairs[anycfg]) do _p('\t%s \\', target) end for target, source in pairs(copypairs) do _p('\t%s \\', target) end _p('') _p('SHELLTYPE := msdos') _p('ifeq (,$(ComSpec)$(COMSPEC))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('') _p('.PHONY: clean prebuild prelink') _p('') _p('all: $(TARGETDIR) $(OBJDIR) prebuild $(EMBEDFILES) $(COPYFILES) prelink $(TARGET)') _p('') _p('$(TARGET): $(SOURCES) $(EMBEDFILES) $(DEPENDS)') _p('\t$(SILENT) $(CSC) /nologo /out:$@ $(FLAGS) $(REFERENCES) $(SOURCES) $(patsubst %%,/resource:%%,$(EMBEDFILES))') _p('\t$(POSTBUILDCMDS)') _p('') _p('$(TARGETDIR):') premake.make_mkdirrule("$(TARGETDIR)") _p('$(OBJDIR):') premake.make_mkdirrule("$(OBJDIR)") _p('clean:') _p('\t@echo Cleaning %s', prj.name) _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET) $(COPYFILES)') _p('\t$(SILENT) rm -rf $(OBJDIR)') _p('else') _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGETDIR)/%s.*) del $(subst /,\\\\,$(TARGETDIR)/%s.*)', prj.buildtarget.basename, prj.buildtarget.basename) for target, source in pairs(cfgpairs[anycfg]) do _p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target) end for target, source in pairs(copypairs) do _p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target) end _p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))') _p('endif') _p('') _p('prebuild:') _p('\t$(PREBUILDCMDS)') _p('') _p('prelink:') _p('\t$(PRELINKCMDS)') _p('') _p('# Per-configuration copied file rules') for cfg in premake.eachconfig(prj) do _p('ifneq (,$(findstring %s,$(config)))', _MAKE.esc(cfg.name:lower())) for target, source in pairs(cfgpairs[cfg]) do premake.make_copyrule(source, target) end _p('endif') _p('') end _p('# Copied file rules') for target, source in pairs(copypairs) do premake.make_copyrule(source, target) end _p('# Embedded file rules') for _, fname in ipairs(embedded) do if path.getextension(fname) == ".resx" then _p('%s: %s', getresourcefilename(prj, fname), _MAKE.esc(fname)) _p('\t$(SILENT) $(RESGEN) $^ $@') end _p('') end end function premake.gmake_cs_config(cfg, csc, cfglibs) local targetDir = _MAKE.esc(cfg.buildtarget.directory) _p('ifneq (,$(findstring %s,$(config)))', _MAKE.esc(cfg.name:lower())) _p(' TARGETDIR := %s', iif(targetDir == "", ".", targetDir)) _p(' OBJDIR := %s', _MAKE.esc(cfg.objectsdir)) _p(' DEPENDS := %s', table.concat(_MAKE.esc(premake.getlinks(cfg, "dependencies", "fullpath")), " ")) _p(' REFERENCES := %s', table.implode(_MAKE.esc(cfglibs[cfg]), "/r:", "", " ")) _p(' FLAGS += %s %s', table.implode(cfg.defines, "/d:", "", " "), table.concat(table.join(csc.getflags(cfg), cfg.buildoptions), " ")) _p(' define PREBUILDCMDS') if #cfg.prebuildcommands > 0 then _p('\t@echo Running pre-build commands') _p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t")) end _p(' endef') _p(' define PRELINKCMDS') if #cfg.prelinkcommands > 0 then _p('\t@echo Running pre-link commands') _p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t")) end _p(' endef') _p(' define POSTBUILDCMDS') if #cfg.postbuildcommands > 0 then _p('\t@echo Running post-build commands') _p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t")) end _p(' endef') _p('endif') _p('') end premake.make.vala = { } premake.make.makefile_ignore = false local vala = premake.make.vala local make = premake.make function premake.make_vala(prj) local valac = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, valac.platforms, "Native") premake.gmake_vala_header(prj, valac, platforms) for _, platform in ipairs(platforms) do for cfg in premake.eachconfig(prj, platform) do premake.gmake_valac_config(prj, cfg, valac) end end local objdirs = {} local additionalobjdirs = {} for _, file in ipairs(prj.allfiles) do if path.issourcefile(file) or path.isgresource(file) then objdirs[_MAKE.esc(path.getdirectory(path.trimdots(file)))] = 1 end end _p('OBJDIRS := \\') _p('\t$(OBJDIR) \\') for dir, _ in iter.sortByKeys(objdirs) do _p('\t$(OBJDIR)/%s \\', dir) end for dir, _ in iter.sortByKeys(additionalobjdirs) do _p('\t%s \\', dir) end _p('') _p('.PHONY: clean prebuild prelink') _p('') _p('all: $(OBJDIRS) $(TARGETDIR) prebuild prelink $(TARGET)') _p('\t@:') _p('') _p('$(TARGET): $(OBJECTS) | $(TARGETDIR)') _p('\t@echo Linking %s', prj.name) _p('\t$(SILENT) $(LINKCMD)') _p('\t$(POSTBUILDCMDS)') _p('') _p('$(TARGETDIR):') premake.make_mkdirrule("$(TARGETDIR)") _p('$(OBJDIRS):') if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCreatingMessage")) then _p('\t@echo Creating $(@)') end _p('\t-$(call MKDIR,$@)') _p('') _p('clean:') if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCleaningMessage")) then _p('\t@echo Cleaning %s', prj.name) end _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET)') _p('else') _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))') _p('endif') _p('') _p('prebuild:') _p('\t$(PREBUILDCMDS)') _p('') _p('prelink:') _p('\t$(PRELINKCMDS)') _p('') vala.fileRules(prj, valac) end function premake.gmake_vala_header(prj, valac, platforms) _p('# %s project makefile autogenerated by GENie', premake.action.current().shortname) _p('') _p('.SUFFIXES:') -- Delete the default suffix rules. _p('') _p('ifndef config') _p(' config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true))) _p('endif') _p('') _p('ifndef verbose') _p(' SILENT = @') _p('endif') _p('') _p('SHELLTYPE := msdos') _p('ifeq (,$(ComSpec)$(COMSPEC))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))') _p(' SHELLTYPE := posix') _p('endif') _p('') _p('ifeq (posix,$(SHELLTYPE))') _p(' MKDIR = $(SILENT) mkdir -p "$(1)"') _p(' COPY = $(SILENT) cp -fR "$(1)" "$(2)"') _p(' RM = $(SILENT) rm -f "$(1)"') _p('else') _p(' MKDIR = $(SILENT) mkdir "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p(' COPY = $(SILENT) copy /Y "$(subst /,\\\\,$(1))" "$(subst /,\\\\,$(2))"') _p(' RM = $(SILENT) del /F "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p('endif') _p('') _p('VALAC = %s', valac.valac) _p('CC = %s', valac.cc) _p('GLIBRC = %s', valac.glibrc) _p('') if (not premake.make.makefile_ignore) then _p('MAKEFILE = %s', _MAKE.getmakefilename(prj, true)) _p('') end end local function is_excluded(prj, cfg, file) if table.icontains(prj.excludes, file) then return true end if table.icontains(cfg.excludes, file) then return true end return false end function premake.gmake_valac_config(prj, cfg, valac) _p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname)) _p(' BASEDIR = %s', _MAKE.esc(path.getrelative(cfg.location, _WORKING_DIR))) _p(' OBJDIR = %s', _MAKE.esc(cfg.objectsdir)) _p(' TARGETDIR = %s', _MAKE.esc(cfg.buildtarget.directory)) _p(' TARGET = $(TARGETDIR)/%s', _MAKE.esc(cfg.buildtarget.name)) _p(' DEFINES +=%s', make.list(valac.getdefines(cfg.defines))) _p(' VAPIDIRS +=%s', make.list(valac.getvapidirs(cfg.vapidirs))) _p(' PKGS +=%s', make.list(valac.getlinks(cfg.links))) _p(' FLAGS += $(DEFINES) $(VAPIDIRS) $(PKGS)%s', make.list(table.join(valac.getvalaflags(cfg), cfg.buildoptions_vala))) _p(' ALL_LDFLAGS+= $(LDFLAGS)%s', make.list(table.join(cfg.linkoptions))) _p(' LINKOBJS = %s', "$(OBJECTS)") _p(' ALL_CFLAGS += $(CFLAGS) $(ARCH)%s', make.list(table.join(cfg.buildoptions, cfg.buildoptions_c, valac.getvalaccflags(cfg)))) _p(' LINKCMD = $(CC) -o $(TARGET) $(LINKOBJS) $(ARCH) $(ALL_LDFLAGS)'); table.sort(cfg.files) _p(' OBJECTS := \\') for _, file in ipairs(cfg.files) do if path.issourcefile(file) or path.isgresource(file) then if not is_excluded(prj, cfg, file) then _p('\t$(OBJDIR)/%s.o \\' , _MAKE.esc(path.trimdots(path.removeext(file))) ) end end end _p('') _p(' SOURCES := \\') for _, file in ipairs(cfg.files) do if path.issourcefile(file) and path.isvalafile(file) then if not is_excluded(prj, cfg, file) then _p('\t%s \\', _MAKE.esc(file)) end end end _p('') _p(' GRESOURCES := \\') for _, file in ipairs(cfg.files) do if path.isgresource(file) then if not is_excluded(prj, cfg, file) then _p('\t%s \\', _MAKE.esc(file)) end end end _p('') _p(' define PREBUILDCMDS') if #cfg.prebuildcommands > 0 then _p('\t@echo Running pre-build commands') _p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t")) end _p(' endef') _p(' define PRELINKCMDS') if #cfg.prelinkcommands > 0 then _p('\t@echo Running pre-link commands') _p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t")) end _p(' endef') _p(' define POSTBUILDCMDS') if #cfg.postbuildcommands > 0 then _p('\t@echo Running post-build commands') _p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t")) end _p(' endef') _p('endif') _p('') end function vala.fileRules(prj, cc) local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") _p('ifneq (,$(OBJRESP))') _p('$(OBJRESP): $(OBJECTS) | $(TARGETDIR) $(OBJDIRS)') _p('\t$(SILENT) echo $^') _p('\t$(SILENT) echo $^ > $@') _p('endif') _p('') _p('ifneq (,$(LDRESP))') _p('$(LDRESP): $(LDDEPS) | $(TARGETDIR) $(OBJDIRS)') _p('\t$(SILENT) echo $^') _p('\t$(SILENT) echo $^ > $@') _p('endif') _p('') local pattern_targets = "" table.sort(prj.allfiles) for _, file in ipairs(prj.allfiles or {}) do if path.issourcefile(file) or path.isgresource(file) then if path.isvalafile(file) or path.iscfile(file) or path.isgresource(file) then if path.isvalafile(file) or path.isgresource(file) then _p('$(OBJDIR)/%s.o: $(OBJDIR)/%s.c $(GCH) $(MAKEFILE) | $(OBJDIR)/%s' , _MAKE.esc(path.trimdots(path.removeext(file))) , _MAKE.esc(path.trimdots(path.removeext(file))) , _MAKE.esc(path.getdirectory(path.trimdots(file))) ) if not path.isgresource(file) then pattern_targets = pattern_targets .. "$(OBJDIR)/" .. _MAKE.esc(path.trimdots(path.removeext(file))) .. ".% \\\n" -- Pattern rule: https://stackoverflow.com/a/3077254 end else _p('$(OBJDIR)/%s.o: %s $(GCH) $(MAKEFILE) | $(OBJDIR)/%s' , _MAKE.esc(path.trimdots(path.removeext(file))) , file , _MAKE.esc(path.getdirectory(path.trimdots(file))) ) end if prj.msgcompile then _p('\t@echo ' .. prj.msgcompile) else _p('\t@echo $(notdir $<)') end _p('\t$(SILENT) %s $(FORCE_INCLUDE) -o "$@" -c "$<"' , "$(CC) $(ALL_CFLAGS)" , _MAKE.esc(path.getbasename(file)) ) for _, task in ipairs(prj.postcompiletasks or {}) do _p('\t$(SILENT) %s', task) _p('') end _p('') if path.isgresource(file) then _p('$(OBJDIR)/%s.c: %s $(GCH) $(MAKEFILE) | $(OBJDIR)/%s' , _MAKE.esc(path.trimdots(path.removeext(file))) , _MAKE.esc(file) , _MAKE.esc(path.getdirectory(path.trimdots(file))) ) if prj.msgcompile then _p('\t@echo ' .. prj.msgcompile) else _p('\t@echo $(notdir $<)') end _p('\t$(SILENT) %s "$<" --target="$@" --sourcedir="%s" --generate' , "$(GLIBRC)" , _MAKE.esc(path.getdirectory(file)) ) for _, task in ipairs(prj.postcompiletasks or {}) do _p('\t$(SILENT) %s', task) _p('') end end _p('') end end end if pattern_targets ~= "" then _p('%s: $(SOURCES) $(GRESOURCES) $(GCH) $(MAKEFILE)', pattern_targets) if prj.msgcompile then _p('\t@echo ' .. prj.msgcompile) else _p('\t@echo [GEN] valac') end _p('\t$(SILENT) %s $(SOURCES) --directory $(OBJDIR) --basedir $(BASEDIR) --gresources=$(GRESOURCES) -C > /dev/null' , "$(VALAC) $(FLAGS)" ) for _, task in ipairs(prj.postcompiletasks or {}) do _p('\t$(SILENT) %s', task) _p('') end end end local make = premake.make local swift = { } function premake.make_swift(prj) local tool = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, tool.platforms, "Native") _p('# %s project makefile autogenerated by GENie', premake.action.current().shortname) _p('') _p('.SUFFIXES:') -- Delete the default suffix rules. _p('') _p('ifndef config') _p(1, 'config=%s', _MAKE.esc(premake.getconfigname(prj.solution.configurations[1], platforms[1], true))) _p('endif') _p('') _p('ifndef verbose') _p(1, 'SILENT = @') _p('endif') _p('') _p('SHELLTYPE := msdos') _p('ifeq (,$(ComSpec)$(COMSPEC))') _p(1, 'SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(SHELL)))') _p(1, 'SHELLTYPE := posix') _p('endif') _p('ifeq (/bin,$(findstring /bin,$(MAKESHELL)))') _p(1, 'SHELLTYPE := posix') _p('endif') _p('') _p('ifeq (posix,$(SHELLTYPE))') _p(1, 'MKDIR = $(SILENT) mkdir -p "$(1)"') _p(1, 'COPY = $(SILENT) cp -fR "$(1)" "$(2)"') _p(1, 'RM = $(SILENT) rm -f "$(1)"') _p('else') _p(1, 'MKDIR = $(SILENT) mkdir "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p(1, 'COPY = $(SILENT) copy /Y "$(subst /,\\\\,$(1))" "$(subst /,\\\\,$(2))"') _p(1, 'RM = $(SILENT) del /F "$(subst /,\\\\,$(1))" 2> nul || exit 0') _p('endif') _p('') _p('SWIFTC = %s', tool.swift) _p('SWIFTLINK = %s', tool.swiftc) _p('DSYMUTIL = %s', tool.dsymutil) _p('AR = %s', tool.ar) _p('') for _, platform in ipairs(platforms) do for cfg in premake.eachconfig(prj, platform) do swift.generate_config(prj, cfg, tool) end end _p('.PHONY: ') _p('') _p('all: $(WORK_DIRS) $(TARGET)') _p('') _p('$(WORK_DIRS):') _p(1, '$(SILENT) $(call MKDIR,$@)') _p('') _p('SOURCES := \\') for _, file in ipairs(prj.files) do if path.isswiftfile(file) then _p(1, '%s \\', _MAKE.esc(file)) end end _p('') local objfiles = {} _p('OBJECTS_WITNESS := $(OBJDIR)/build.stamp') _p('OBJECTS := \\') for _, file in ipairs(prj.files) do if path.isswiftfile(file) then local objname = _MAKE.esc(swift.objectname(file)) table.insert(objfiles, objname) _p(1, '%s \\', objname) end end _p('') swift.file_rules(prj, objfiles) swift.linker(prj, tool) swift.generate_clean(prj) end function swift.objectname(file) return path.join("$(OBJDIR)", path.getname(file)..".o") end function swift.file_rules(prj, objfiles) _p('$(OBJECTS_WITNESS): $(SOURCES)') _p(1, "@rm -f $(OBJDIR)/data.tmp") _p(1, "@touch $(OBJDIR)/data.tmp") _p(1, "$(SILENT) $(SWIFTC) -frontend -c $(SOURCES) -enable-objc-interop $(SDK) -I $(OUT_DIR) $(SWIFTC_FLAGS) -module-cache-path $(MODULECACHE_DIR) -D SWIFT_PACKAGE $(MODULE_MAPS) -emit-module-doc-path $(OUT_DIR)/$(MODULE_NAME).swiftdoc -module-name $(MODULE_NAME) -emit-module-path $(OUT_DIR)/$(MODULE_NAME).swiftmodule -num-threads 8 %s", table.arglist("-o", objfiles)) _p(1, "@mv -f $(OBJDIR)/data.tmp $(OBJECTS_WITNESS)") _p('') _p('$(OBJECTS): $(OBJECTS_WITNESS)') _p(1, '@if test -f $@; then :; else \\') _p(2, 'rm -f $(OBJECTS_WITNESS); \\') _p(2, '$(MAKE) $(AM_MAKEFLAGS) $(OBJECTS_WITNESS); \\') _p(1, 'fi') _p('') end function swift.linker(prj, tool) local lddeps = make.list(premake.getlinks(prj, "siblings", "fullpath")) if prj.kind == "StaticLib" then _p("$(TARGET): $(OBJECTS) %s ", lddeps) _p(1, "$(SILENT) $(AR) cr $(AR_FLAGS) $@ $(OBJECTS) %s", (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) else _p("$(TARGET): $(OBJECTS) $(LDDEPS)", lddeps) _p(1, "$(SILENT) $(SWIFTLINK) $(SDK) -L $(OUT_DIR) -o $@ $(SWIFTLINK_FLAGS) $(LD_FLAGS) $(OBJECTS)") _p("ifdef SYMBOLS") _p(1, "$(SILENT) $(DSYMUTIL) $(TARGET) -o $(SYMBOLS)") _p("endif") end _p('') end function swift.generate_clean(prj) _p('clean:') if (not prj.solution.messageskip) or (not table.contains(prj.solution.messageskip, "SkipCleaningMessage")) then _p('\t@echo Cleaning %s', prj.name) end _p('ifeq (posix,$(SHELLTYPE))') _p('\t$(SILENT) rm -f $(TARGET)') _p('\t$(SILENT) rm -rf $(OBJDIR)') _p('\t$(SILENT) rm -rf $(SYMBOLS)') _p('\t$(SILENT) rm -rf $(MODULECACHE_DIR)') _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('\t$(SILENT) if exist $(subst /,\\\\,$(SYMBOLS)) rmdir /s /q $(subst /,\\\\,$(SYMBOLS))') _p('\t$(SILENT) if exist $(subst /,\\\\,$(MODULECACHE_DIR)) rmdir /s /q $(subst /,\\\\,$(MODULECACHE_DIR))') _p('endif') _p('') end function swift.generate_config(prj, cfg, tool) _p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname)) _p(1, "OUT_DIR = %s", cfg.buildtarget.directory) _p(1, "MODULECACHE_DIR = $(OUT_DIR)/ModuleCache") _p(1, "TARGET = $(OUT_DIR)/%s", _MAKE.esc(cfg.buildtarget.name)) local objdir = path.join(cfg.objectsdir, prj.name .. ".build") _p(1, "OBJDIR = %s", objdir) _p(1, "MODULE_NAME = %s", prj.name) _p(1, "MODULE_MAPS = %s", make.list(tool.getmodulemaps(cfg))) _p(1, "SWIFTC_FLAGS = %s", make.list(tool.getswiftcflags(cfg))) _p(1, "SWIFTLINK_FLAGS = %s", make.list(tool.getswiftlinkflags(cfg))) _p(1, "AR_FLAGS = %s", make.list(tool.getarchiveflags(cfg, cfg, false))) _p(1, "LD_FLAGS = %s", make.list(tool.getldflags(cfg))) _p(1, "LDDEPS = %s", make.list(premake.getlinks(cfg, "siblings", "fullpath"))) if cfg.flags.Symbols then _p(1, "SYMBOLS = $(TARGET).dSYM") end local sdk = tool.get_sdk_path(cfg) if sdk then _p(1, "TOOLCHAIN_PATH = %s", tool.get_toolchain_path(cfg)) _p(1, "SDK_PATH = %s", sdk) _p(1, "PLATFORM_PATH = %s", tool.get_sdk_platform_path(cfg)) _p(1, "SDK = -sdk $(SDK_PATH)") else _p(1, "SDK_PATH =") _p(1, "SDK =") end _p(1,'WORK_DIRS = $(OUT_DIR) $(OBJDIR)') _p('endif') _p('') end premake.vstudio = { } local toolsets = { vs2010 = "v100", vs2012 = "v110", vs2013 = "v120", vs2015 = "v140", vs2017 = "v141", vs2019 = "v142", vs2022 = "v143", } premake.vstudio.toolset = toolsets[_ACTION] or "unknown?" premake.vstudio.splashpath = '' premake.vstudio.xpwarning = true local vstudio = premake.vstudio vstudio.platforms = { any = "Any CPU", mixed = "Mixed Platforms", Native = "Win32", x86 = "x86", x32 = "Win32", x64 = "x64", PS3 = "PS3", Xbox360 = "Xbox 360", ARM = "ARM", ARM64 = "ARM64", Orbis = "ORBIS", Durango = "Durango", TegraAndroid = "Tegra-Android", NX32 = "NX32", NX64 = "NX64", Emscripten = "Emscripten", } function vstudio.arch(prj) if (prj.language == "C#") then return "Any CPU" else return "Win32" end end function vstudio.iswinrt() return vstudio.storeapp ~= nil and vstudio.storeapp ~= '' end function vstudio.buildconfigs(sln) local cfgs = { } local platforms = premake.filterplatforms(sln, vstudio.platforms, "Native") local hascpp = premake.hascppproject(sln) local hasdotnet = premake.hasdotnetproject(sln) if hasdotnet and (_ACTION > "vs2008" or hascpp) then table.insert(platforms, 1, "mixed") end if hasdotnet and (_ACTION < "vs2010" or not hascpp) then table.insert(platforms, 1, "any") end if _ACTION > "vs2008" then local platforms2010 = { } for _, platform in ipairs(platforms) do if vstudio.platforms[platform] == "Win32" then if hascpp then table.insert(platforms2010, platform) end if hasdotnet then table.insert(platforms2010, "x86") end else table.insert(platforms2010, platform) end end platforms = platforms2010 end for _, buildcfg in ipairs(sln.configurations) do for _, platform in ipairs(platforms) do local entry = { } entry.src_buildcfg = buildcfg entry.src_platform = platform if platform ~= "PS3" or _ACTION > "vs2008" then entry.buildcfg = buildcfg entry.platform = vstudio.platforms[platform] else entry.buildcfg = platform .. " " .. buildcfg entry.platform = "Win32" end entry.name = entry.buildcfg .. "|" .. entry.platform entry.isreal = (platform ~= "any" and platform ~= "mixed") table.insert(cfgs, entry) end end return cfgs end function premake.vstudio.bakeimports(sln) for _,iprj in ipairs(sln.importedprojects) do if string.find(iprj.location, ".csproj") ~= nil then iprj.language = "C#" else iprj.language = "C++" end local f, err = io.open(iprj.location, "r") if (not f) then error(err, 1) end local projcontents = f:read("*all") f:close() local found, _, uuid = string.find(projcontents, "{([%w%-]+)}") if not found then error("Could not find ProjectGuid element in project " .. iprj.location, 1) end iprj.uuid = uuid if iprj.language == "C++" and string.find(projcontents, "true") then iprj.flags.Managed = true end iprj.relpath = path.getrelative(sln.location, iprj.location) end end function premake.vstudio.getimportprj(prjpath, sln) for _,iprj in ipairs(sln.importedprojects) do if prjpath == iprj.relpath then return iprj end end error("Could not find reference import project " .. prjpath, 1) end function vstudio.cleansolution(sln) premake.clean.file(sln, "%%.sln") premake.clean.file(sln, "%%.suo") premake.clean.file(sln, "%%.ncb") premake.clean.file(sln, "%%.userprefs") premake.clean.file(sln, "%%.usertasks") end function vstudio.cleanproject(prj) local fname = premake.project.getfilename(prj, "%%") os.remove(fname .. ".vcproj") os.remove(fname .. ".vcproj.user") os.remove(fname .. ".vcxproj") os.remove(fname .. ".vcxproj.user") os.remove(fname .. ".vcxproj.filters") os.remove(fname .. ".csproj") os.remove(fname .. ".csproj.user") os.remove(fname .. ".pidb") os.remove(fname .. ".sdf") end function vstudio.cleantarget(name) os.remove(name .. ".pdb") os.remove(name .. ".idb") os.remove(name .. ".ilk") os.remove(name .. ".vshost.exe") os.remove(name .. ".exe.manifest") end function vstudio.projectfile(prj) local pattern if prj.language == "C#" then pattern = "%%.csproj" else pattern = iif(_ACTION > "vs2008", "%%.vcxproj", "%%.vcproj") end local fname = premake.project.getbasename(prj.name, pattern) fname = path.join(prj.location, fname) return fname end function vstudio.tool(prj) if (prj.language == "C#") then return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC" else return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" end end premake.vstudio.sln2005 = { } local vstudio = premake.vstudio local sln2005 = premake.vstudio.sln2005 function sln2005.generate(sln) io.eol = '\r\n' sln.vstudio_configs = premake.vstudio.buildconfigs(sln) premake.vstudio.bakeimports(sln) _p('\239\187\191') sln2005.reorderProjects(sln) sln2005.header(sln) for grp in premake.solution.eachgroup(sln) do sln2005.group(grp) end for prj in premake.solution.eachproject(sln) do sln2005.project(prj) end for _,iprj in ipairs(sln.importedprojects) do sln2005.importproject(iprj) end _p('Global') sln2005.platforms(sln) sln2005.project_platforms(sln) sln2005.properties(sln) sln2005.project_groups(sln) _p('EndGlobal') end function sln2005.reorderProjects(sln) if sln.startproject then for i, prj in ipairs(sln.projects) do if sln.startproject == prj.name then local cur = prj.group while cur ~= nil do for j, group in ipairs(sln.groups) do if group == cur then table.remove(sln.groups, j) break end end table.insert(sln.groups, 1, cur) cur = cur.parent end table.remove(sln.projects, i) table.insert(sln.projects, 1, prj) break end end end end function sln2005.header(sln) local action = premake.action.current() _p('Microsoft Visual Studio Solution File, Format Version %d.00', action.vstudio.solutionVersion) if(_ACTION:sub(3) == "2015" or _ACTION:sub(3) == "2017") then _p('# Visual Studio %s', action.vstudio.toolsVersion:sub(1,2)) elseif(_ACTION:sub(3) == "2019") then _p('# Visual Studio Version %s', action.vstudio.toolsVersion:sub(1,2)) else _p('# Visual Studio %s', _ACTION:sub(3)) end end function sln2005.project(prj) local projpath = path.translate(path.getrelative(prj.solution.location, vstudio.projectfile(prj)), "\\") _p('Project("{%s}") = "%s", "%s", "{%s}"', vstudio.tool(prj), prj.name, projpath, prj.uuid) sln2005.projectdependencies(prj) _p('EndProject') end function sln2005.group(grp) _p('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "%s", "%s", "{%s}"', grp.name, grp.name, grp.uuid) _p('EndProject') end function sln2005.importproject(iprj) _p('Project("{%s}") = "%s", "%s", "{%s}"', vstudio.tool(iprj), path.getbasename(iprj.location), iprj.relpath, iprj.uuid) _p('EndProject') end function sln2005.projectdependencies(prj) local deps = premake.getdependencies(prj) if #deps > 0 then local function compareuuid(a, b) return a.uuid < b.uuid end table.sort(deps, compareuuid) _p('\tProjectSection(ProjectDependencies) = postProject') for _, dep in ipairs(deps) do _p('\t\t{%s} = {%s}', dep.uuid, dep.uuid) end _p('\tEndProjectSection') end end function sln2005.platforms(sln) _p('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution') for _, cfg in ipairs(sln.vstudio_configs) do _p('\t\t%s = %s', cfg.name, cfg.name) end _p('\tEndGlobalSection') end function sln2005.project_platform(prj, sln) for _, cfg in ipairs(sln.vstudio_configs) do local mapped local buildfor if premake.isdotnetproject(prj) then buildfor = "x64" mapped = "Any CPU" elseif prj.flags and prj.flags.Managed then mapped = "x64" else if cfg.platform == "Any CPU" or cfg.platform == "Mixed Platforms" then mapped = sln.vstudio_configs[3].platform else mapped = cfg.platform end end local build_project = true if prj.solution ~= nil then build_project = premake.getconfig(prj, cfg.src_buildcfg, cfg.src_platform).build end _p('\t\t{%s}.%s.ActiveCfg = %s|%s', prj.uuid, cfg.name, cfg.buildcfg, mapped) if build_project then if mapped == cfg.platform or cfg.platform == "Mixed Platforms" or buildfor == cfg.platform then _p('\t\t{%s}.%s.Build.0 = %s|%s', prj.uuid, cfg.name, cfg.buildcfg, mapped) end if premake.vstudio.iswinrt() and prj.kind == "WindowedApp" then _p('\t\t{%s}.%s.Deploy.0 = %s|%s', prj.uuid, cfg.name, cfg.buildcfg, mapped) end end end end function sln2005.project_platforms(sln) _p('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution') for prj in premake.solution.eachproject(sln) do sln2005.project_platform(prj, sln) end for _,iprj in ipairs(sln.importedprojects) do sln2005.project_platform(iprj, sln) end _p('\tEndGlobalSection') end function sln2005.properties(sln) _p('\tGlobalSection(SolutionProperties) = preSolution') _p('\t\tHideSolutionNode = FALSE') _p('\tEndGlobalSection') end function sln2005.project_groups(sln) _p('\tGlobalSection(NestedProjects) = preSolution') for grp in premake.solution.eachgroup(sln) do if grp.parent ~= nil then _p('\t\t{%s} = {%s}', grp.uuid, grp.parent.uuid) end end for prj in premake.solution.eachproject(sln) do if prj.group ~= nil then _p('\t\t{%s} = {%s}', prj.uuid, prj.group.uuid) end end for _,iprj in ipairs(sln.importedprojects) do if iprj.group ~= nil then _p('\t\t{%s} = {%s}', iprj.uuid, iprj.group.uuid) end end _p('\tEndGlobalSection') endpremake.vstudio.vc2010 = { } local vc2010 = premake.vstudio.vc2010 local vstudio = premake.vstudio local function vs2010_config(prj) for _, cfginfo in ipairs(prj.solution.vstudio_configs) do if cfginfo.src_platform == "TegraAndroid" then _p(1,'') _p(2,'11') _p(1,'') break end end _p(1,'') for _, cfginfo in ipairs(prj.solution.vstudio_configs) do _p(2,'', premake.esc(cfginfo.name)) _p(3,'%s',cfginfo.buildcfg) _p(3,'%s',cfginfo.platform) _p(2,'') end _p(1,'') end local function vs2010_globals(prj) local action = premake.action.current() _p(1,'') _p(2, '{%s}',prj.uuid) _p(2, '%s',prj.name) if vstudio.storeapp ~= "durango" then local windowsTargetPlatformVersion = prj.windowstargetplatformversion or action.vstudio.windowsTargetPlatformVersion if windowsTargetPlatformVersion ~= nil then _p(2,'%s',windowsTargetPlatformVersion) if windowsTargetPlatformVersion and string.startswith(windowsTargetPlatformVersion, "10.") then _p(2,'%s', prj.windowstargetplatformminversion or "10.0.10240.0") end end end if prj.flags and prj.flags.Managed then local frameworkVersion = prj.framework or "4.0" _p(2, 'v%s', frameworkVersion) _p(2, 'ManagedCProj') elseif vstudio.iswinrt() then _p(2, 'en-US') if vstudio.storeapp == "durango" then _p(2, 'Win32Proj') _p(2, 'title') _p(2, '14.0') _p(2, 'Native') else _p(2, 'true') _p(2, '12.0') _p(2, 'Windows Store') _p(2, '%s', vstudio.storeapp) end else _p(2, 'Win32Proj') end if not vstudio.xpwarning then _p(2, 'false') end _p(1,'') end function vc2010.config_type(config) local t = { SharedLib = "DynamicLibrary", StaticLib = "StaticLibrary", ConsoleApp = "Application", WindowedApp = "Application" } return t[config.kind] end local function if_config_and_platform() return 'Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"' end local function optimisation(cfg) local result = "Disabled" for _, value in ipairs(cfg.flags) do if (value == "Optimize") then result = "Full" elseif (value == "OptimizeSize") then result = "MinSpace" elseif (value == "OptimizeSpeed") then result = "MaxSpeed" end end return result end function vc2010.configurationPropertyGroup(cfg, cfginfo) _p(1, '' , premake.esc(cfginfo.name)) local is2019 = premake.action.current() == premake.action.get("vs2019") local is2022 = premake.action.current() == premake.action.get("vs2022") if is2019 or is2022 then _p(2, '%s', action.vstudio.toolsVersion) if cfg.flags.UnitySupport then _p(2, 'true') end end _p(2, '%s', vc2010.config_type(cfg)) _p(2, '%s', iif(optimisation(cfg) == "Disabled","true","false")) _p(2, '%s', premake.vstudio.toolset) if os.is64bit() then _p(2, 'x64') end if cfg.flags.Unicode then _p(2,'Unicode') end if cfg.flags.Managed then _p(2,'true') end if cfg.platform == "TegraAndroid" then if cfg.androidtargetapi then _p(2,'android-%s', cfg.androidtargetapi) end if cfg.androidminapi then _p(2,'android-%s', cfg.androidminapi) end if cfg.androidarch then _p(2,'%s', cfg.androidarch) end if cfg.androidndktoolchainversion then _p(2,'%s', cfg.androidndktoolchainversion) end if cfg.androidstltype then _p(2,'%s', cfg.androidstltype) end end if cfg.platform == "NX32" or cfg.platform == "NX64" then _p(2,'$(NINTENDO_SDK_ROOT)\\') _p(2,'NX') if premake.config.isdebugbuild(cfg) then _p(2,'Debug') else _p(2,'Release') end end if cfg.flags.Symbols and (premake.action.current() == premake.action.get("vs2017") or is2019) then _p(2, 'true') end _p(1,'') end local function import_props(prj) for _, cfginfo in ipairs(prj.solution.vstudio_configs) do local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) _p(1,'' ,premake.esc(cfginfo.name)) _p(2,'') if #cfg.propertysheets > 0 then local dirs = cfg.propertysheets for _, dir in ipairs(dirs) do local translated = path.translate(dir) _p(2,'', translated, translated) end end _p(1,'') end end local function add_trailing_backslash(dir) if dir:len() > 0 and dir:sub(-1) ~= "\\" then return dir.."\\" end return dir end function vc2010.outputProperties(prj) for _, cfginfo in ipairs(prj.solution.vstudio_configs) do local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) local target = cfg.buildtarget local outdir = add_trailing_backslash(target.directory) local intdir = add_trailing_backslash(iif(action.vstudio.intDirAbsolute , path.translate( path.join(prj.solution.location, cfg.objectsdir) , '\\') , cfg.objectsdir )) _p(1,'', premake.esc(cfginfo.name)) _p(2,'%s', iif(outdir:len() > 0, premake.esc(outdir), ".\\")) if cfg.platform == "Xbox360" then _p(2,'$(OutDir)%s', premake.esc(target.name)) end _p(2,'%s', premake.esc(intdir)) _p(2,'%s', premake.esc(path.getbasename(target.name))) _p(2,'%s', premake.esc(path.getextension(target.name))) if cfg.kind == "SharedLib" then local ignore = (cfg.flags.NoImportLib ~= nil) _p(2,'%s', tostring(ignore)) end if cfg.platform == "NX32" or cfg.platform == "NX64" then if cfg.flags.Cpp17 then _p(2,'Gnu++17') elseif cfg.flags.Cpp20 then _p(2,'Gnu++20') end end if cfg.platform == "Durango" then _p(2, '$(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath)') _p(2, '$(Console_SdkLibPath)') _p(2, '$(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath)') _p(2, '$(Console_SdkIncludeRoot)') _p(2, '$(Console_SdkRoot)bin;$(VCInstallDir)bin\\x86_amd64;$(VCInstallDir)bin;$(WindowsSDK_ExecutablePath_x86);$(VSInstallDir)Common7\\Tools\\bin;$(VSInstallDir)Common7\\tools;$(VSInstallDir)Common7\\ide;$(ProgramFiles)\\HTML Help Workshop;$(MSBuildToolsPath32);$(FxCopDir);$(PATH);') if cfg.imagepath then _p(2, '%s', cfg.imagepath) else _p(2, '%s', prj.name) end if cfg.pullmappingfile ~= nil then _p(2,'%s', premake.esc(cfg.pullmappingfile)) end _p(2, '*.pdb;*.ilk;*.exp;*.lib;*.winmd;*.appxrecipe;*.pri;*.idb') _p(2, 'true') end if cfg.kind ~= "StaticLib" then _p(2,'%s', tostring(premake.config.isincrementallink(cfg))) end if cfg.applicationdatadir ~= nil then _p(2,'%s', premake.esc(cfg.applicationdatadir)) end if cfg.flags.NoManifest then _p(2,'false') end _p(1,'') end end local function runtime(cfg) local runtime local flags = cfg.flags if premake.config.isdebugbuild(cfg) then runtime = iif(flags.StaticRuntime and not flags.Managed, "MultiThreadedDebug", "MultiThreadedDebugDLL") else runtime = iif(flags.StaticRuntime and not flags.Managed, "MultiThreaded", "MultiThreadedDLL") end return runtime end local function precompiled_header(cfg) if not cfg.flags.NoPCH and cfg.pchheader then _p(3,'Use') _p(3,'%s', cfg.pchheader) else _p(3,'') end end local function preprocessor(indent,cfg,escape) if #cfg.defines > 0 then local defines = table.concat(cfg.defines, ";") if escape then defines = defines:gsub('"', '\\"') end local isPreprocessorDefinitionPresent = string.find(defines, "%%%(PreprocessorDefinitions%)") if isPreprocessorDefinitionPresent then _p(indent,'%s' ,premake.esc(defines)) else _p(indent,'%s;%%(PreprocessorDefinitions)' ,premake.esc(defines)) end else _p(indent,'') end end local function include_dirs(indent,cfg) local includedirs = table.join(cfg.userincludedirs, cfg.includedirs, cfg.systemincludedirs) if #includedirs> 0 then _p(indent,'%s;%%(AdditionalIncludeDirectories)' ,premake.esc(path.translate(table.concat(includedirs, ";"), '\\'))) end end local function using_dirs(indent,cfg) if #cfg.usingdirs > 0 then _p(indent,'%s;%%(AdditionalUsingDirectories)' ,premake.esc(path.translate(table.concat(cfg.usingdirs, ";"), '\\'))) end end local function resource_compile(cfg) _p(2,'') preprocessor(3,cfg,true) include_dirs(3,cfg) _p(2,'') end local function cppstandard(cfg) if cfg.flags.CppLatest then _p(3, 'stdcpplatest') _p(3, 'true') elseif cfg.flags.Cpp20 then _p(3, 'stdcpp20') elseif cfg.flags.Cpp17 then _p(3, 'stdcpp17') elseif cfg.flags.Cpp14 then _p(3, 'stdcpp14') end end local function exceptions(cfg) if cfg.platform == "Orbis" then if cfg.flags.NoExceptions then _p(3, 'false') end elseif cfg.platform == "TegraAndroid" then if cfg.flags.NoExceptions then _p(3, 'false') end elseif cfg.platform == "NX32" or cfg.platform == "NX64" then if cfg.flags.NoExceptions then _p(3, 'false') else _p(3, 'true') end else if cfg.flags.NoExceptions then _p(3, 'false') elseif cfg.flags.SEH then _p(3, 'Async') end end end local function rtti(cfg) if cfg.flags.NoRTTI and not cfg.flags.Managed then _p(3,'false') end end local function calling_convention(cfg) if cfg.flags.FastCall then _p(3,'FastCall') elseif cfg.flags.StdCall then _p(3,'StdCall') end end local function wchar_t_builtin(cfg) if cfg.flags.NativeWChar then _p(3,'true') elseif cfg.flags.NoNativeWChar then _p(3,'false') end end local function sse(cfg) if cfg.flags.EnableSSE then _p(3, 'StreamingSIMDExtensions') elseif cfg.flags.EnableSSE2 then _p(3, 'StreamingSIMDExtensions2') elseif cfg.flags.EnableAVX then _p(3, 'AdvancedVectorExtensions') elseif cfg.flags.EnableAVX2 then _p(3, 'AdvancedVectorExtensions2') end end local function floating_point(cfg) if cfg.platform == "Orbis" then if cfg.flags.FloatFast then _p(3,'true') end elseif cfg.platform == "TegraAndroid" then elseif cfg.platform == "NX32" or cfg.platform == "NX64" then if cfg.flags.FloatFast then _p(3, 'true') end else if cfg.flags.FloatFast then _p(3,'Fast') elseif cfg.flags.FloatStrict and not cfg.flags.Managed then _p(3,'Strict') end end end local function debug_info(cfg) local debug_info = '' if cfg.flags.Symbols then if cfg.flags.C7DebugInfo then debug_info = "OldStyle" elseif (action.vstudio.supports64bitEditContinue == false and cfg.platform == "x64") or not premake.config.iseditandcontinue(cfg) then debug_info = "ProgramDatabase" else debug_info = "EditAndContinue" end end _p(3,'%s',debug_info) end local function minimal_build(cfg) if premake.config.isdebugbuild(cfg) and cfg.flags.EnableMinimalRebuild then _p(3,'true') else _p(3,'false') end end local function compile_language(cfg) if cfg.options.ForceCPP then _p(3,'CompileAsCpp') else if cfg.language == "C" then _p(3,'CompileAsC') end end end local function forcedinclude_files(indent,cfg) if #cfg.forcedincludes > 0 then _p(indent,'%s' ,premake.esc(path.translate(table.concat(cfg.forcedincludes, ";"), '\\'))) end end local function vs10_clcompile(cfg) _p(2,'') local unsignedChar = "/J " local buildoptions = cfg.buildoptions if cfg.platform == "Orbis" then unsignedChar = "-funsigned-char "; _p(3,'%s', tostring(cfg.flags.Symbols ~= nil)) end if cfg.platform == "NX32" or cfg.platform == "NX64" then unsignedChar = "-funsigned-char "; _p(3,'%s', tostring(cfg.flags.Symbols ~= nil)) end if cfg.language == "C" and not cfg.options.ForceCPP then buildoptions = table.join(buildoptions, cfg.buildoptions_c) else buildoptions = table.join(buildoptions, cfg.buildoptions_cpp) end _p(3,'%s %s%%(AdditionalOptions)' , table.concat(premake.esc(buildoptions), " ") , iif(cfg.flags.UnsignedChar and cfg.platform ~= "TegraAndroid", unsignedChar, " ") ) if cfg.platform == "TegraAndroid" then _p(3,'%s', tostring(cfg.flags.UnsignedChar == nil)) _p(3,'%s', tostring(cfg.flags.Symbols ~= nil)) if cfg.androidcppstandard then _p(3,'%s', cfg.androidcppstandard) end end if cfg.platform == "Orbis" then local opt = optimisation(cfg) if opt == "Disabled" then _p(3,'Level0') elseif opt == "MinSpace" then _p(3,'Levelz') -- Oz is more aggressive than Os elseif opt == "MaxSpeed" then _p(3,'Level3') else _p(3,'Level2') end elseif cfg.platform == "TegraAndroid" then local opt = optimisation(cfg) if opt == "Disabled" then _p(3,'O0') elseif opt == "MinSpace" then _p(3,'Os') elseif opt == "MaxSpeed" then _p(3,'O3') else _p(3,'O2') end elseif cfg.platform == "NX32" or cfg.platform == "NX64" then local opt = optimisation(cfg) if opt == "Disabled" then _p(3,'O0') elseif opt == "MinSpace" then _p(3,'Os') elseif opt == "MaxSpeed" then _p(3,'O3') else _p(3,'O2') end else _p(3,'%s', optimisation(cfg)) end include_dirs(3, cfg) using_dirs(3, cfg) preprocessor(3, cfg) minimal_build(cfg) if premake.config.isoptimizedbuild(cfg.flags) then if cfg.flags.NoOptimizeLink and cfg.flags.NoEditAndContinue then _p(3, 'false') _p(3, 'false') else _p(3, 'true') _p(3, 'true') end else _p(3, 'true') if cfg.flags.NoRuntimeChecks then _p(3, 'Default') elseif not cfg.flags.Managed then _p(3, 'EnableFastChecks') end if cfg.flags.ExtraWarnings then end end if cfg.platform == "Durango" or cfg.flags.NoWinRT then _p(3, 'false') end _p(3, '%s', runtime(cfg)) if cfg.flags.NoBufferSecurityCheck then _p(3, 'false') end if not cfg.flags.NoMultiProcessorCompilation and not cfg.flags.EnableMinimalRebuild then _p(3, 'true') else _p(3, 'false') end precompiled_header(cfg) if cfg.platform == "Orbis" then if cfg.flags.PedanticWarnings then _p(3, 'MoreWarnings') _p(3, 'true') elseif cfg.flags.ExtraWarnings then _p(3, 'NormalWarnings') _p(3, 'true') elseif cfg.flags.MinimumWarnings then _p(3, 'WarningsOff') _p(3, 'false') else _p(3, 'NormalWarnings') _p(3, 'false') end if cfg.flags.FatalWarnings then _p(3, 'true') end elseif cfg.platform == "TegraAndroid" then if cfg.flags.PedanticWarnings or cfg.flags.ExtraWarnings then _p(3, 'AllWarnings') elseif cfg.flags.MinimumWarnings then _p(3, 'DisableAllWarnings') else _p(3, 'NormalWarnings') end if cfg.flags.FatalWarnings then _p(3, 'true') end elseif cfg.platform == "NX32" or cfg.platform == "NX64" then if cfg.flags.PedanticWarnings then _p(3, 'MoreWarnings') _p(3, 'true') elseif cfg.flags.ExtraWarnings then _p(3, 'NormalWarnings') _p(3, 'true') elseif cfg.flags.MinimumWarnings then _p(3, 'WarningsOff') _p(3, 'false') else _p(3, 'NormalWarnings') _p(3, 'false') end if cfg.flags.FatalWarnings then _p(3, 'true') end else if cfg.flags.PedanticWarnings then _p(3, 'EnableAllWarnings') elseif cfg.flags.ExtraWarnings then _p(3, 'Level4') elseif cfg.flags.MinimumWarnings then _p(3, 'Level1') else _p(3 ,'Level3') end end if cfg.flags.FatalWarnings then _p(3, 'true') end if premake.action.current() == premake.action.get("vs2017") or premake.action.current() == premake.action.get("vs2019") or premake.action.current() == premake.action.get("vs2022") then cppstandard(cfg) end exceptions(cfg) rtti(cfg) calling_convention(cfg) wchar_t_builtin(cfg) sse(cfg) floating_point(cfg) debug_info(cfg) if cfg.flags.Symbols then if cfg.kind == "StaticLib" then _p(3, '$(OutDir)%s.pdb' , path.getbasename(cfg.buildtarget.name) ) else _p(3, '$(IntDir)%s.compile.pdb' , path.getbasename(cfg.buildtarget.name) ) end end if cfg.flags.Hotpatchable then _p(3, 'true') end if cfg.flags.NoFramePointer then _p(3, 'true') end if cfg.flags.UseFullPaths then _p(3, 'true') end if cfg.flags.NoJMC then _p(3,'false' ) end compile_language(cfg) forcedinclude_files(3,cfg); if vstudio.diagformat then _p(3, '%s', vstudio.diagformat) else _p(3, 'Caret') end _p(2,'') end local function event_hooks(cfg) if #cfg.postbuildcommands> 0 then _p(2,'') _p(3,'%s',premake.esc(table.implode(cfg.postbuildcommands, "", "", "\r\n"))) _p(2,'') end if #cfg.prebuildcommands> 0 then _p(2,'') _p(3,'%s',premake.esc(table.implode(cfg.prebuildcommands, "", "", "\r\n"))) _p(2,'') end if #cfg.prelinkcommands> 0 then _p(2,'') _p(3,'%s',premake.esc(table.implode(cfg.prelinkcommands, "", "", "\r\n"))) _p(2,'') end end local function additional_options(indent,cfg) if #cfg.linkoptions > 0 then _p(indent,'%s %%(AdditionalOptions)', table.concat(premake.esc(cfg.linkoptions), " ")) end end local function link_target_machine(index,cfg) local platforms = {x32 = 'MachineX86', x64 = 'MachineX64'} if platforms[cfg.platform] then _p(index,'%s', platforms[cfg.platform]) end end local function item_def_lib(cfg) if cfg.kind == 'StaticLib' and cfg.platform ~= "Xbox360" then _p(1,'') _p(2,'$(OutDir)%s',cfg.buildtarget.name) additional_options(2,cfg) link_target_machine(2,cfg) _p(1,'') end end local function import_lib(cfg) if cfg.kind == "SharedLib" then local implibname = cfg.linktarget.fullpath _p(3,'%s',iif(cfg.flags.NoImportLib, cfg.objectsdir .. "\\" .. path.getname(implibname), implibname)) end end local function hasmasmfiles(prj) local files = vc2010.getfilegroup(prj, "MASM") return #files > 0 end local function ismanagedprj(prj, cfgname, pltname) local cfg = premake.getconfig(prj, cfgname, pltname) return cfg.flags.Managed == true end local function getcfglinks(cfg) local haswholearchive = #cfg.wholearchive > 0 local msvcnaming = premake.getnamestyle(cfg) == "windows" local iscppprj = premake.iscppproject(cfg) local isnetprj = premake.isdotnetproject(cfg) local linkobjs = {} local links = iif(haswholearchive , premake.getlinks(cfg, "all", "object") , premake.getlinks(cfg, "system", "fullpath") ) for _, link in ipairs(links) do local name = nil local directory = nil local whole = nil if type(link) == "table" then if not ismanagedprj(link.project, cfg.name, cfg.platform) then name = link.linktarget.basename directory = path.rebase(link.linktarget.directory, link.location, cfg.location) whole = table.icontains(cfg.wholearchive, link.project.name) end else name = link whole = table.icontains(cfg.wholearchive, link) end if name then if haswholearchive and msvcnaming then if iscppprj then name = name .. ".lib" elseif isnetprj then name = name .. ".dll" end end table.insert(linkobjs, {name=name, directory=directory, wholearchive=whole}) end end return linkobjs end local function vs10_masm(prj, cfg) if hasmasmfiles(prj) then _p(2, '') _p(3,'%s %%(AdditionalOptions)' , table.concat(premake.esc(table.join(cfg.buildoptions, cfg.buildoptions_asm)), " ") ) local includedirs = table.join(cfg.userincludedirs, cfg.includedirs, cfg.systemincludedirs) if #includedirs > 0 then _p(3, '%s;%%(IncludePaths)' , premake.esc(path.translate(table.concat(includedirs, ";"), '\\')) ) end local defines = table.join(cfg.defines) table.insertflat(defines, iif(premake.config.isdebugbuild(cfg), "_DEBUG", {})) table.insert(defines, iif(cfg.platform == "x64" or cfg.platform == "ARM64", "_WIN64", "_WIN32")) table.insert(defines, iif(prj.kind == "SharedLib", "_EXPORT=EXPORT", "_EXPORT=")) _p(3, '%s;%%(PreprocessorDefinitions)' , premake.esc(table.concat(defines, ";")) ) if cfg.flags.FatalWarnings then _p(3,'true') end if cfg.flags.MinimumWarnings then _p(3,'0') else _p(3,'3') end _p(2, '') end end local function additional_manifest(cfg) if(cfg.dpiawareness ~= nil) then _p(2,'') if(cfg.dpiawareness == "None") then _p(3, 'false') end if(cfg.dpiawareness == "High") then _p(3, 'true') end if(cfg.dpiawareness == "HighPerMonitor") then _p(3, 'PerMonitorHighDPIAware') end _p(2,'') end end function vc2010.link(cfg) local vs2017OrLater = premake.action.current() == premake.action.get("vs2017") or premake.action.current() == premake.action.get("vs2019") local links = getcfglinks(cfg) _p(2,'') _p(3,'%s', iif(cfg.kind == "ConsoleApp", "Console", "Windows")) if vs2017OrLater and cfg.flags.FullSymbols then _p(3,'DebugFull') else _p(3,'%s', tostring(cfg.flags.Symbols ~= nil)) end if cfg.flags.Symbols then _p(3, '$(OutDir)%s.pdb' , path.getbasename(cfg.buildtarget.name) ) end if premake.config.islinkeroptimizedbuild(cfg.flags) then if cfg.platform == "Orbis" then _p(3,'StripFuncsAndData') _p(3,'true') else _p(3,'true') _p(3,'true') end elseif cfg.platform == "Orbis" and premake.config.iseditandcontinue(cfg) then _p(3,'true') end if cfg.finalizemetasource ~= nil then _p(3,'%s', premake.esc(cfg.finalizemetasource)) end if cfg.kind ~= 'StaticLib' then vc2010.additionalDependencies(3, cfg, links) vc2010.additionalLibraryDirectories(3, cfg, links) _p(3,'$(OutDir)%s', cfg.buildtarget.name) if vc2010.config_type(cfg) == 'Application' and not cfg.flags.WinMain and not cfg.flags.Managed then if cfg.flags.Unicode then _p(3,'wmainCRTStartup') else _p(3,'mainCRTStartup') end end import_lib(cfg) local deffile = premake.findfile(cfg, ".def") if deffile then _p(3,'%s', deffile) end link_target_machine(3,cfg) additional_options(3,cfg) if cfg.flags.NoWinMD and vstudio.iswinrt() and prj.kind == "WindowedApp" then _p(3,'false' ) end end if cfg.platform == "TegraAndroid" then if cfg.androidlinker then _p(3,'%s',cfg.androidlinker) end end if cfg.flags.Hotpatchable then _p(3, 'Enabled') end if cfg.flags.GenerateMapFiles then _p(3, 'true') end _p(2,'') if #cfg.wholearchive > 0 then _p(2, '') _p(3, 'false') _p(2, '') end end function vc2010.additionalLibraryDirectories(tab, cfg, links) local dirs = cfg.libdirs for _, link in ipairs(links) do if link.directory and not table.icontains(dirs, link.directory) then table.insert(dirs, link.directory) end end _p(tab, '%s;%%(AdditionalLibraryDirectories)' , premake.esc(path.translate(table.concat(dirs, ';'), '\\')) ) end function vc2010.additionalDependencies(tab, cfg, links) if #links > 0 then local deps = "" if cfg.platform == "Orbis" then local iswhole = false for _, link in ipairs(links) do if link.wholearchive and not iswhole then deps = deps .. "--whole-archive;" iswhole = true elseif not link.wholearchive and iswhole then deps = deps .. "--no-whole-archive;" iswhole = false end deps = deps .. "-l" .. link.name .. ";" end else for _, link in ipairs(links) do if link.wholearchive then deps = deps .. "/WHOLEARCHIVE:" .. link.name .. ";" else deps = deps .. link.name .. ";" end end end if cfg.platform == "TegraAndroid" then deps = "-Wl,--start-group;" .. deps .. ";-Wl,--end-group" end _p(tab, '%s;%s' , deps , iif(cfg.platform == "Durango" , '%(XboxExtensionsDependencies)' , '%(AdditionalDependencies)' ) ) elseif cfg.platform == "Durango" then _p(tab, '%%(XboxExtensionsDependencies)') end end function ant_build(prj, cfg) if cfg.platform == "TegraAndroid" then local files = vc2010.getfilegroup(prj, "AndroidBuild") _p(2,'') if #files > 0 then _p(3,'%s',path.translate(files[1].name)) end local isdebugbuild = premake.config.isdebugbuild(cfg) _p(3,'%s',iif(isdebugbuild, 'Debug','Release')) _p(3,'%s',tostring(cfg.flags.AntBuildDebuggable ~= nil)) if #cfg.antbuildjavasourcedirs > 0 then local dirs = table.concat(cfg.antbuildjavasourcedirs,";") _p(3,'%s',dirs) end if #cfg.antbuildjardirs > 0 then local dirs = table.concat(cfg.antbuildjardirs,";") _p(3,'%s',dirs) end if #cfg.antbuildjardependencies > 0 then local dirs = table.concat(cfg.antbuildjardependencies,";") _p(3,'%s',dirs) end if #cfg.antbuildnativelibdirs > 0 then local dirs = table.concat(cfg.antbuildnativelibdirs,";") _p(3,'%s',dirs) end if #cfg.antbuildnativelibdependencies > 0 then local dirs = table.concat(cfg.antbuildnativelibdependencies,";") _p(3,'%s',dirs) end if #cfg.antbuildassetsdirs > 0 then local dirs = table.concat(cfg.antbuildassetsdirs,";") _p(3,'%s',dirs) end _p(2,'') end end local function item_definitions(prj) for _, cfginfo in ipairs(prj.solution.vstudio_configs) do local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) _p(1,'' ,premake.esc(cfginfo.name)) vs10_clcompile(cfg) resource_compile(cfg) item_def_lib(cfg) vc2010.link(cfg) ant_build(prj, cfg) event_hooks(cfg) vs10_masm(prj, cfg) additional_manifest(cfg) _p(1,'') end end function vc2010.getfilegroup(prj, group) local sortedfiles = prj.vc2010sortedfiles if not sortedfiles then sortedfiles = { ClCompile = {}, ClInclude = {}, MASM = {}, Object = {}, None = {}, ResourceCompile = {}, AppxManifest = {}, AndroidBuild = {}, Natvis = {}, Image = {}, DeploymentContent = {} } local foundAppxManifest = false for file in premake.project.eachfile(prj, true) do if path.issourcefilevs(file.name) then table.insert(sortedfiles.ClCompile, file) elseif path.iscppheader(file.name) then if not table.icontains(prj.removefiles, file) then table.insert(sortedfiles.ClInclude, file) end elseif path.isobjectfile(file.name) then table.insert(sortedfiles.Object, file) elseif path.isresourcefile(file.name) then table.insert(sortedfiles.ResourceCompile, file) elseif path.isimagefile(file.name) then table.insert(sortedfiles.Image, file) elseif path.isappxmanifest(file.name) then foundAppxManifest = true table.insert(sortedfiles.AppxManifest, file) elseif path.isandroidbuildfile(file.name) then table.insert(sortedfiles.AndroidBuild, file) elseif path.isnatvis(file.name) then table.insert(sortedfiles.Natvis, file) elseif path.isasmfile(file.name) then table.insert(sortedfiles.MASM, file) elseif file.flags and table.icontains(file.flags, "DeploymentContent") then table.insert(sortedfiles.DeploymentContent, file) else table.insert(sortedfiles.None, file) end end if vstudio.iswinrt() and prj.kind == "WindowedApp" and not foundAppxManifest then vstudio.needAppxManifest = true local fcfg = {} fcfg.name = prj.name .. "/Package.appxmanifest" fcfg.vpath = premake.project.getvpath(prj, fcfg.name) table.insert(sortedfiles.AppxManifest, fcfg) local logo = {} logo.name = prj.name .. "/Logo.png" logo.vpath = logo.name table.insert(sortedfiles.Image, logo) local smallLogo = {} smallLogo.name = prj.name .. "/SmallLogo.png" smallLogo.vpath = smallLogo.name table.insert(sortedfiles.Image, smallLogo) local storeLogo = {} storeLogo.name = prj.name .. "/StoreLogo.png" storeLogo.vpath = storeLogo.name table.insert(sortedfiles.Image, storeLogo) local splashScreen = {} splashScreen.name = prj.name .. "/SplashScreen.png" splashScreen.vpath = splashScreen.name table.insert(sortedfiles.Image, splashScreen) end prj.vc2010sortedfiles = sortedfiles end return sortedfiles[group] end function vc2010.files(prj) vc2010.simplefilesgroup(prj, "ClInclude") vc2010.compilerfilesgroup(prj) vc2010.simplefilesgroup(prj, "Object") vc2010.simplefilesgroup(prj, "None") vc2010.customtaskgroup(prj) vc2010.simplefilesgroup(prj, "ResourceCompile") vc2010.simplefilesgroup(prj, "AppxManifest") vc2010.simplefilesgroup(prj, "AndroidBuild") vc2010.simplefilesgroup(prj, "Natvis") vc2010.deploymentcontentgroup(prj, "Image") vc2010.deploymentcontentgroup(prj, "DeploymentContent", "None") end function vc2010.customtaskgroup(prj) local files = { } for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do local fcfg = { } fcfg.name = path.getrelative(prj.location,buildtask[1]) fcfg.vpath = path.trimdots(fcfg.name) table.insert(files, fcfg) end end if #files > 0 then _p(1,'') local groupedBuildTasks = {} local buildTaskNames = {} for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do if (groupedBuildTasks[buildtask[1]] == nil) then groupedBuildTasks[buildtask[1]] = {} table.insert(buildTaskNames, buildtask[1]) end table.insert(groupedBuildTasks[buildtask[1]], buildtask) end end for _, name in ipairs(buildTaskNames) do custombuildtask = groupedBuildTasks[name] _p(2,'', path.translate(path.getrelative(prj.location,name), "\\")) _p(3,'Text') local cmd = "" local outputs = "" for _, buildtask in ipairs(custombuildtask or {}) do for _, cmdline in ipairs(buildtask[4] or {}) do cmd = cmd .. cmdline local num = 1 for _, depdata in ipairs(buildtask[3] or {}) do cmd = string.gsub(cmd,"%$%(" .. num .."%)", string.format("%s ",path.getrelative(prj.location,depdata))) num = num + 1 end cmd = string.gsub(cmd, "%$%(<%)", string.format("%s ",path.getrelative(prj.location,buildtask[1]))) cmd = string.gsub(cmd, "%$%(@%)", string.format("%s ",path.getrelative(prj.location,buildtask[2]))) cmd = cmd .. "\r\n" end outputs = outputs .. path.getrelative(prj.location,buildtask[2]) .. ";" end _p(3,'%s',cmd) _p(3,'%s%%(Outputs)',outputs) _p(3,'Designer') _p(3,'') _p(2,'') end _p(1,'') end end function vc2010.simplefilesgroup(prj, section, subtype) local configs = prj.solution.vstudio_configs local files = vc2010.getfilegroup(prj, section) if #files > 0 then local config_mappings = {} for _, cfginfo in ipairs(configs) do local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) if cfg.pchheader and cfg.pchsource and not cfg.flags.NoPCH then config_mappings[cfginfo] = path.translate(cfg.pchsource, "\\") end end _p(1,'') for _, file in ipairs(files) do local prjexcluded = table.icontains(prj.excludes, file.name) local excludedcfgs = {} if not prjexcluded then for _, vsconfig in ipairs(configs) do local cfg = premake.getconfig(prj, vsconfig.src_buildcfg, vsconfig.src_platform) local fileincfg = table.icontains(cfg.files, file.name) local cfgexcluded = table.icontains(cfg.excludes, file.name) if not fileincfg or cfgexcluded then table.insert(excludedcfgs, vsconfig.name) end end end if subtype or prjexcluded or #excludedcfgs > 0 then _p(2, '<%s Include=\"%s\">', section, path.translate(file.name, "\\")) if prjexcluded then _p(3, 'true') else for _, cfgname in ipairs(excludedcfgs) do _p(3, 'true' , premake.esc(cfgname) ) end end if subtype then _p(3, '%s', subtype) end _p(2,'', section) else _p(2, '<%s Include=\"%s\" />', section, path.translate(file.name, "\\")) end end _p(1,'') end end function vc2010.deploymentcontentgroup(prj, section, filetype) if filetype == nil then filetype = section end local files = vc2010.getfilegroup(prj, section) if #files > 0 then _p(1,'') for _, file in ipairs(files) do _p(2,'<%s Include=\"%s\">', filetype, path.translate(file.name, "\\")) _p(3,'true') _p(3,'%s', path.translate(file.vpath, "\\")) _p(2,'', filetype) end _p(1,'') end end function vc2010.compilerfilesgroup(prj) local configs = prj.solution.vstudio_configs local files = vc2010.getfilegroup(prj, "ClCompile") if #files > 0 then local config_mappings = {} for _, cfginfo in ipairs(configs) do local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) if cfg.pchheader and cfg.pchsource and not cfg.flags.NoPCH then config_mappings[cfginfo] = path.translate(cfg.pchsource, "\\") end end _p(1,'') local existingBasenames = {}; for _, file in ipairs(files) do local filename = string.lower(path.getbasename(file.name)) local disambiguation = existingBasenames[filename] or 0; existingBasenames[filename] = disambiguation + 1 local translatedpath = path.translate(file.name, "\\") _p(2, '', translatedpath) for _, vsconfig in ipairs(configs) do local cfg = premake.getconfig(prj, vsconfig.src_buildcfg, vsconfig.src_platform) local namestyle = premake.getnamestyle(cfg) if namestyle == "TegraAndroid" or namestyle == "NX" then _p(3, '$(IntDir)%s.o', premake.esc(vsconfig.name), premake.esc(path.translate(path.trimdots(path.removeext(file.name)))) ) else if disambiguation > 0 then _p(3, '$(IntDir)%s\\', premake.esc(vsconfig.name), tostring(disambiguation)) end end end if path.iscxfile(file.name) then _p(3, 'true') _p(3, 'true') _p(3, 'NotUsing') end if vstudio.iswinrt() and string.len(file.name) > 2 and string.sub(file.name, -2) == ".c" then _p(3,'FALSE') end for _, cfginfo in ipairs(configs) do if config_mappings[cfginfo] and translatedpath == config_mappings[cfginfo] then _p(3,'Create', premake.esc(cfginfo.name)) config_mappings[cfginfo] = nil --only one source file per pch end end local nopch = table.icontains(prj.nopch, file.name) for _, vsconfig in ipairs(configs) do local cfg = premake.getconfig(prj, vsconfig.src_buildcfg, vsconfig.src_platform) if nopch or table.icontains(cfg.nopch, file.name) then _p(3,'NotUsing', premake.esc(vsconfig.name)) end end local excluded = table.icontains(prj.excludes, file.name) for _, vsconfig in ipairs(configs) do local cfg = premake.getconfig(prj, vsconfig.src_buildcfg, vsconfig.src_platform) local fileincfg = table.icontains(cfg.files, file.name) local cfgexcluded = table.icontains(cfg.excludes, file.name) if excluded or not fileincfg or cfgexcluded then _p(3, 'true' , premake.esc(vsconfig.name) ) end end if prj.flags and prj.flags.Managed then local prjforcenative = table.icontains(prj.forcenative, file.name) for _,vsconfig in ipairs(configs) do local cfg = premake.getconfig(prj, vsconfig.src_buildcfg, vsconfig.src_platform) if prjforcenative or table.icontains(cfg.forcenative, file.name) then _p(3, 'false', premake.esc(vsconfig.name)) end end end _p(2,'') end _p(1,'') end end function vc2010.masmfiles(prj) local configs = prj.solution.vstudio_configs local files = vc2010.getfilegroup(prj, "MASM") if #files > 0 then _p(1, '') for _, file in ipairs(files) do local translatedpath = path.translate(file.name, "\\") _p(2, '', translatedpath) local excluded = table.icontains(prj.excludes, file.name) for _, vsconfig in ipairs(configs) do local cfg = premake.getconfig(prj, vsconfig.src_buildcfg, vsconfig.src_platform) local fileincfg = table.icontains(cfg.files, file.name) local cfgexcluded = table.icontains(cfg.excludes, file.name) if excluded or not fileincfg or cfgexcluded then _p(3, 'true' , premake.esc(vsconfig.name) ) end end _p(2, '') end _p(1, '') end end function vc2010.header(targets) io.eol = "\r\n" _p('') local t = "" if targets then t = ' DefaultTargets="' .. targets .. '"' end _p('', t, action.vstudio.toolsVersion) end function premake.vs2010_vcxproj(prj) local usemasm = hasmasmfiles(prj) io.indent = " " vc2010.header("Build") vs2010_config(prj) vs2010_globals(prj) _p(1,'') for _, cfginfo in ipairs(prj.solution.vstudio_configs) do local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) vc2010.configurationPropertyGroup(cfg, cfginfo) end _p(1,'') _p(1,'') if usemasm then _p(2, '') end _p(1,'') import_props(prj) _p(1,'') vc2010.outputProperties(prj) item_definitions(prj) vc2010.files(prj) vc2010.clrReferences(prj) vc2010.projectReferences(prj) vc2010.sdkReferences(prj) vc2010.masmfiles(prj) _p(1,'') _p(1,'') if usemasm then _p(2, '') end _p(1,'') _p('') end function vc2010.clrReferences(prj) if #prj.clrreferences == 0 then return end _p(1,'') for _, ref in ipairs(prj.clrreferences) do if os.isfile(ref) then local assembly = path.getbasename(ref) _p(2,'', assembly) _p(3,'%s', path.getrelative(prj.location, ref)) _p(2,'') else _p(2,'', ref) end end _p(1,'') end function vc2010.projectReferences(prj) local deps = premake.getdependencies(prj) if #deps == 0 and #prj.vsimportreferences == 0 then return end local function compareuuid(a, b) return a.uuid < b.uuid end table.sort(deps, compareuuid) table.sort(table.join(prj.vsimportreferences), compareuuid) _p(1,'') for _, dep in ipairs(deps) do local deppath = path.getrelative(prj.location, vstudio.projectfile(dep)) _p(2,'', path.translate(deppath, "\\")) _p(3,'{%s}', dep.uuid) if vstudio.iswinrt() then _p(3,'false') end _p(2,'') end for _, ref in ipairs(prj.vsimportreferences) do local slnrelpath = path.rebase(ref, prj.location, sln.location) local iprj = premake.vstudio.getimportprj(slnrelpath, prj.solution) _p(2,'', ref) _p(3,'{%s}', iprj.uuid) _p(2,'') end _p(1,'') end function vc2010.sdkReferences(prj) local refs = prj.sdkreferences if #refs > 0 then _p(1,'') for _, ref in ipairs(refs) do _p(2,'', ref) end _p(1,'') end end function vc2010.debugdir(cfg) local isnx = (cfg.platform == "NX32" or cfg.platform == "NX64") local debuggerFlavor = iif(isnx, 'OasisNXDebugger' , iif(cfg.platform == "Orbis", 'ORBISDebugger' , iif(cfg.platform == "Durango", 'XboxOneVCppDebugger' , iif(cfg.platform == "TegraAndroid", 'AndroidDebugger' , iif(vstudio.iswinrt(), 'AppHostLocalDebugger' , 'WindowsLocalDebugger' ))))) _p(2, '%s', debuggerFlavor) if cfg.debugdir and not vstudio.iswinrt() then _p(2, '%s' , path.translate(cfg.debugdir, '\\') ) end if cfg.debugcmd then _p(2, '%s', cfg.debugcmd) end if cfg.debugargs then _p(2, '%s' , table.concat(cfg.debugargs, " ") ) end if cfg.debugenvs and #cfg.debugenvs > 0 then _p(2, '%s%s' , table.concat(cfg.debugenvs, "\n") , iif(cfg.flags.DebugEnvsInherit,'\n$(LocalDebuggerEnvironment)', '') ) if cfg.flags.DebugEnvsDontMerge then _p(2, 'false') end end if cfg.deploymode then _p(2, '%s', cfg.deploymode) end if cfg.platform == "TegraAndroid" then if cfg.androiddebugintentparams then _p(2, '%s' , table.concat(cfg.androiddebugintentparams, " ") ) end end end function premake.vs2010_vcxproj_user(prj) io.indent = " " vc2010.header() for _, cfginfo in ipairs(prj.solution.vstudio_configs) do local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) _p(' ', premake.esc(cfginfo.name)) vc2010.debugdir(cfg) _p(' ') end _p('') end local png1x1data = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, -- .PNG........IHDR 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x25, 0xdb, 0x56, -- .............%.V 0xca, 0x00, 0x00, 0x00, 0x03, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0xa7, 0x7a, 0x3d, 0xda, -- .....PLTE....z=. 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x40, 0xe6, 0xd8, 0x66, 0x00, 0x00, 0x00, -- ....tRNS.@..f... 0x0a, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe2, -- .IDAT..c`....... 0x21, 0xbc, 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, -- !.3....IEND.B`. } function png1x1(obj, filename) filename = premake.project.getfilename(obj, filename) local f, err = io.open(filename, "wb") if f then for _, byte in ipairs(png1x1data) do f:write(string.char(byte)) end f:close() end end function premake.vs2010_appxmanifest(prj) io.indent = " " io.eol = "\r\n" _p('') if vstudio.storeapp == "10.0" then _p('') elseif vstudio.storeapp == "durango" then _p('') end _p(1, '') if vstudio.storeapp == "10.0" then _p(1, '') end _p(1, '') _p(2, '' .. prj.name .. '') _p(2, 'PublisherDisplayName') _p(2, '' .. prj.name .. '\\StoreLogo.png') png1x1(prj, "%%/StoreLogo.png") _p(2, '' .. prj.name .. '') _p(1,'') if vstudio.storeapp == "10.0" then _p(1, '') _p(2, '') _p(1, '') elseif vstudio.storeapp == "durango" then _p(1, '') _p(2, '6.2') _p(2, '6.2') _p(1, '') end _p(1, '') _p(2, '') _p(1, '') _p(1, '') _p(2, '') if vstudio.storeapp == "10.0" then _p(3, '') _p(4, '') png1x1(prj, "%%/SplashScreen.png") _p(3, '') elseif vstudio.storeapp == "durango" then _p(3, '') _p(5, '') png1x1(prj, "%%/SplashScreen.png") _p(3, '') _p(3, '') _p(4, '') _p(4, '') _p(4, '') _p(3, '') end _p(2, '') _p(1, '') _p('') end local vc2010 = premake.vstudio.vc2010 local project = premake.project function vc2010.filteridgroup(prj) local filters = { } local filterfound = false for file in premake.project.eachfile(prj, true) do local folders = string.explode(file.vpath, "/", true) local path = "" for i = 1, #folders - 1 do if not filterfound then filterfound = true _p(1,'') end path = path .. folders[i] if not filters[path] then filters[path] = true _p(2, '', path) _p(3, '{%s}', os.uuid(path)) _p(2, '') end path = path .. "\\" end end for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do local folders = string.explode(path.trimdots(path.getrelative(prj.location,buildtask[1])), "/", true) local path = "" for i = 1, #folders - 1 do if not filterfound then filterfound = true _p(1,'') end path = path .. folders[i] if not filters[path] then filters[path] = true _p(2, '', path) _p(3, '{%s}', os.uuid(path)) _p(2, '') end path = path .. "\\" end end end if filterfound then _p(1,'') end end function vc2010.filefiltergroup(prj, section, kind) local files = vc2010.getfilegroup(prj, section) or {} if kind == nill then kind = section end if (section == "CustomBuild") then for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do local fcfg = { } fcfg.name = path.getrelative(prj.location,buildtask[1]) fcfg.vpath = path.trimdots(fcfg.name) table.insert(files, fcfg) end end end if #files > 0 then _p(1,'') for _, file in ipairs(files) do local filter if file.name ~= file.vpath then filter = path.getdirectory(file.vpath) else filter = path.getdirectory(file.name) end if filter ~= "." then _p(2,'<%s Include=\"%s\">', kind, path.translate(file.name, "\\")) _p(3,'%s', path.translate(filter, "\\")) _p(2,'', kind) else _p(2,'<%s Include=\"%s\" />', kind, path.translate(file.name, "\\")) end end _p(1,'') end end function vc2010.generate_filters(prj) io.indent = " " vc2010.header() vc2010.filteridgroup(prj) vc2010.filefiltergroup(prj, "None") vc2010.filefiltergroup(prj, "ClInclude") vc2010.filefiltergroup(prj, "ClCompile") vc2010.filefiltergroup(prj, "Object") vc2010.filefiltergroup(prj, "ResourceCompile") vc2010.filefiltergroup(prj, "CustomBuild") vc2010.filefiltergroup(prj, "AppxManifest") vc2010.filefiltergroup(prj, "Natvis") vc2010.filefiltergroup(prj, "Image") vc2010.filefiltergroup(prj, "DeploymentContent", "None") vc2010.filefiltergroup(prj, "MASM") _p('') end local vc2010 = premake.vstudio.vc2010 local vstudio = premake.vstudio newaction { trigger = "vs2010", shortname = "Visual Studio 2010", description = "Generate Microsoft Visual Studio 2010 project files", os = "windows", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#"}, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onsolution = function(sln) premake.generate(sln, "%%.sln", vstudio.sln2005.generate) end, onproject = function(prj) if premake.isdotnetproject(prj) then premake.generate(prj, "%%.csproj", vstudio.cs2005.generate) premake.generate(prj, "%%.csproj.user", vstudio.cs2005.generate_user) else premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj) premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user) premake.generate(prj, "%%.vcxproj.filters", vstudio.vc2010.generate_filters) end end, oncleansolution = premake.vstudio.cleansolution, oncleanproject = premake.vstudio.cleanproject, oncleantarget = premake.vstudio.cleantarget, vstudio = { productVersion = "8.0.30703", solutionVersion = "11", targetFramework = "4.0", toolsVersion = "4.0", supports64bitEditContinue = false, intDirAbsolute = false, } } premake.vstudio.vc2012 = {} local vc2012 = premake.vstudio.vc2012 local vstudio = premake.vstudio newaction { trigger = "vs2012", shortname = "Visual Studio 2012", description = "Generate Microsoft Visual Studio 2012 project files", os = "windows", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#"}, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onsolution = function(sln) premake.generate(sln, "%%.sln", vstudio.sln2005.generate) end, onproject = function(prj) if premake.isdotnetproject(prj) then premake.generate(prj, "%%.csproj", vstudio.cs2005.generate) premake.generate(prj, "%%.csproj.user", vstudio.cs2005.generate_user) else premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj) premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user) premake.generate(prj, "%%.vcxproj.filters", vstudio.vc2010.generate_filters) end end, oncleansolution = premake.vstudio.cleansolution, oncleanproject = premake.vstudio.cleanproject, oncleantarget = premake.vstudio.cleantarget, vstudio = { solutionVersion = "12", targetFramework = "4.5", toolsVersion = "4.0", supports64bitEditContinue = false, intDirAbsolute = false, } } premake.vstudio.vc2013 = {} local vc2013 = premake.vstudio.vc2013 local vstudio = premake.vstudio newaction { trigger = "vs2013", shortname = "Visual Studio 2013", description = "Generate Microsoft Visual Studio 2013 project files", os = "windows", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#"}, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onsolution = function(sln) premake.generate(sln, "%%.sln", vstudio.sln2005.generate) end, onproject = function(prj) if premake.isdotnetproject(prj) then premake.generate(prj, "%%.csproj", vstudio.cs2005.generate) premake.generate(prj, "%%.csproj.user", vstudio.cs2005.generate_user) else premake.vstudio.needAppxManifest = false premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj) premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user) premake.generate(prj, "%%.vcxproj.filters", vstudio.vc2010.generate_filters) if premake.vstudio.needAppxManifest then premake.generate(prj, "%%/Package.appxmanifest", premake.vs2010_appxmanifest) end end end, oncleansolution = premake.vstudio.cleansolution, oncleanproject = premake.vstudio.cleanproject, oncleantarget = premake.vstudio.cleantarget, vstudio = { solutionVersion = "12", targetFramework = "4.5", toolsVersion = "12.0", supports64bitEditContinue = false, intDirAbsolute = false, } } premake.vstudio.vc2015 = {} local vc2015 = premake.vstudio.vc2015 local vstudio = premake.vstudio newaction { trigger = "vs2015", shortname = "Visual Studio 2015", description = "Generate Microsoft Visual Studio 2015 project files", os = "windows", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onsolution = function(sln) premake.generate(sln, "%%.sln", vstudio.sln2005.generate) end, onproject = function(prj) if premake.isdotnetproject(prj) then premake.generate(prj, "%%.csproj", vstudio.cs2005.generate) premake.generate(prj, "%%.csproj.user", vstudio.cs2005.generate_user) else premake.vstudio.needAppxManifest = false premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj) premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user) premake.generate(prj, "%%.vcxproj.filters", vstudio.vc2010.generate_filters) if premake.vstudio.needAppxManifest then premake.generate(prj, "%%/Package.appxmanifest", premake.vs2010_appxmanifest) end end end, oncleansolution = premake.vstudio.cleansolution, oncleanproject = premake.vstudio.cleanproject, oncleantarget = premake.vstudio.cleantarget, vstudio = { solutionVersion = "12", targetFramework = "4.5", toolsVersion = "14.0", windowsTargetPlatformVersion = "8.1", supports64bitEditContinue = true, intDirAbsolute = false, } } premake.vstudio.vc2017 = {} local vc2017 = premake.vstudio.vc2017 local vstudio = premake.vstudio newaction { trigger = "vs2017", shortname = "Visual Studio 2017", description = "Generate Microsoft Visual Studio 2017 project files", os = "windows", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onsolution = function(sln) premake.generate(sln, "%%.sln", vstudio.sln2005.generate) end, onproject = function(prj) if premake.isdotnetproject(prj) then premake.generate(prj, "%%.csproj", vstudio.cs2005.generate) premake.generate(prj, "%%.csproj.user", vstudio.cs2005.generate_user) else premake.vstudio.needAppxManifest = false premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj) premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user) premake.generate(prj, "%%.vcxproj.filters", vstudio.vc2010.generate_filters) if premake.vstudio.needAppxManifest then premake.generate(prj, "%%/Package.appxmanifest", premake.vs2010_appxmanifest) end end end, oncleansolution = premake.vstudio.cleansolution, oncleanproject = premake.vstudio.cleanproject, oncleantarget = premake.vstudio.cleantarget, vstudio = { solutionVersion = "12", targetFramework = "4.5.2", toolsVersion = "15.0", windowsTargetPlatformVersion = "8.1", supports64bitEditContinue = true, intDirAbsolute = false, } } premake.vstudio.vc2019 = {} local vc2019 = premake.vstudio.vc2019 local vstudio = premake.vstudio newaction { trigger = "vs2019", shortname = "Visual Studio 2019", description = "Generate Microsoft Visual Studio 2019 project files", os = "windows", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onsolution = function(sln) premake.generate(sln, "%%.sln", vstudio.sln2005.generate) end, onproject = function(prj) if premake.isdotnetproject(prj) then premake.generate(prj, "%%.csproj", vstudio.cs2005.generate) premake.generate(prj, "%%.csproj.user", vstudio.cs2005.generate_user) else premake.vstudio.needAppxManifest = false premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj) premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user) premake.generate(prj, "%%.vcxproj.filters", vstudio.vc2010.generate_filters) if premake.vstudio.needAppxManifest then premake.generate(prj, "%%/Package.appxmanifest", premake.vs2010_appxmanifest) end end end, oncleansolution = premake.vstudio.cleansolution, oncleanproject = premake.vstudio.cleanproject, oncleantarget = premake.vstudio.cleantarget, vstudio = { solutionVersion = "12", targetFramework = "4.7.2", toolsVersion = "16.0", windowsTargetPlatformVersion = "10.0", supports64bitEditContinue = true, intDirAbsolute = false, } } premake.vstudio.vc2022 = {} local vc2022 = premake.vstudio.vc2022 local vstudio = premake.vstudio newaction { trigger = "vs2022", shortname = "Visual Studio 2022", description = "Generate Microsoft Visual Studio 2022 project files", os = "windows", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++", "C#" }, valid_tools = { cc = { "msc" }, dotnet = { "msnet" }, }, onsolution = function(sln) premake.generate(sln, "%%.sln", vstudio.sln2005.generate) end, onproject = function(prj) if premake.isdotnetproject(prj) then premake.generate(prj, "%%.csproj", vstudio.cs2005.generate) premake.generate(prj, "%%.csproj.user", vstudio.cs2005.generate_user) else premake.vstudio.needAppxManifest = false premake.generate(prj, "%%.vcxproj", premake.vs2010_vcxproj) premake.generate(prj, "%%.vcxproj.user", premake.vs2010_vcxproj_user) premake.generate(prj, "%%.vcxproj.filters", vstudio.vc2010.generate_filters) if premake.vstudio.needAppxManifest then premake.generate(prj, "%%/Package.appxmanifest", premake.vs2010_appxmanifest) end end end, oncleansolution = premake.vstudio.cleansolution, oncleanproject = premake.vstudio.cleanproject, oncleantarget = premake.vstudio.cleantarget, vstudio = { solutionVersion = "12", targetFramework = "4.7.2", toolsVersion = "16.0", windowsTargetPlatformVersion = "10.0", supports64bitEditContinue = true, intDirAbsolute = false, } } premake.xcode = { } function premake.xcode.checkproject(prj) local last for cfg in premake.eachconfig(prj) do if last and last ~= cfg.kind then error("Project '" .. prj.name .. "' uses more than one target kind; not supported by Xcode", 0) end last = cfg.kind end end premake.xcode.toolset = "macosx" premake.xcode.parameters = { } local xcode = premake.xcode local tree = premake.tree function xcode.getbuildcategory(node) local categories = { [".a"] = "Frameworks", [".h"] = "Headers", [".hh"] = "Headers", [".hpp"] = "Headers", [".hxx"] = "Headers", [".inl"] = "Headers", [".c"] = "Sources", [".cc"] = "Sources", [".cpp"] = "Sources", [".cxx"] = "Sources", [".c++"] = "Sources", [".dylib"] = "Frameworks", [".bundle"] = "Frameworks", [".framework"] = "Frameworks", [".tbd"] = "Frameworks", [".m"] = "Sources", [".mm"] = "Sources", [".S"] = "Sources", [".strings"] = "Resources", [".nib"] = "Resources", [".xib"] = "Resources", [".icns"] = "Resources", [".bmp"] = "Resources", [".wav"] = "Resources", [".xcassets"] = "Resources", [".xcdatamodeld"] = "Sources", [".swift"] = "Sources", } return categories[path.getextension(node.name)] or categories[string.lower(path.getextension(node.name))] end function xcode.getconfigname(cfg) local name = cfg.name if #cfg.project.solution.xcode.platforms > 1 then name = name .. " " .. premake.action.current().valid_platforms[cfg.platform] end return name end function xcode.getfiletype(node) 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", [".entitlements"] = "text.xml", [".bundle"] = "wrapper.cfbundle", [".framework"] = "wrapper.framework", [".tbd"] = "sourcecode.text-based-dylib-definition", [".gif"] = "image.gif", [".h"] = "sourcecode.c.h", [".hh"] = "sourcecode.cpp.h", [".hpp"] = "sourcecode.cpp.h", [".hxx"] = "sourcecode.cpp.h", [".inl"] = "sourcecode.cpp.h", [".html"] = "text.html", [".lua"] = "sourcecode.lua", [".m"] = "sourcecode.c.objc", [".mm"] = "sourcecode.cpp.objcpp", [".S"] = "sourcecode.asm", [".nib"] = "wrapper.nib", [".pch"] = "sourcecode.c.h", [".plist"] = "text.plist.xml", [".strings"] = "text.plist.strings", [".xib"] = "file.xib", [".icns"] = "image.icns", [".bmp"] = "image.bmp", [".wav"] = "audio.wav", [".xcassets"] = "folder.assetcatalog", [".xcdatamodeld"] = "wrapper.xcdatamodeld", [".swift"] = "sourcecode.swift", } return types[path.getextension(node.path)] or (types[string.lower(path.getextension(node.path))] or "text") end function xcode.getfiletypeForced(node) local types = { [".c"] = "sourcecode.cpp.cpp", [".cc"] = "sourcecode.cpp.cpp", [".cpp"] = "sourcecode.cpp.cpp", [".css"] = "text.css", [".cxx"] = "sourcecode.cpp.cpp", [".c++"] = "sourcecode.cpp.cpp", [".entitlements"] = "text.xml", [".bundle"] = "wrapper.cfbundle", [".framework"] = "wrapper.framework", [".tbd"] = "wrapper.framework", [".gif"] = "image.gif", [".h"] = "sourcecode.cpp.h", [".hh"] = "sourcecode.cpp.h", [".hpp"] = "sourcecode.cpp.h", [".hxx"] = "sourcecode.cpp.h", [".inl"] = "sourcecode.cpp.h", [".html"] = "text.html", [".lua"] = "sourcecode.lua", [".m"] = "sourcecode.cpp.objcpp", [".mm"] = "sourcecode.cpp.objcpp", [".nib"] = "wrapper.nib", [".pch"] = "sourcecode.cpp.h", [".plist"] = "text.plist.xml", [".strings"] = "text.plist.strings", [".xib"] = "file.xib", [".icns"] = "image.icns", [".bmp"] = "image.bmp", [".wav"] = "audio.wav", [".xcassets"] = "folder.assetcatalog", [".xcdatamodeld"] = "wrapper.xcdatamodeld", [".swift"] = "sourcecode.swift", } return types[path.getextension(node.path)] or (types[string.lower(path.getextension(node.path))] or "text") end function xcode.getproducttype(node) local types = { ConsoleApp = "com.apple.product-type.tool", WindowedApp = node.cfg.options.SkipBundling and "com.apple.product-type.tool" or "com.apple.product-type.application", StaticLib = "com.apple.product-type.library.static", SharedLib = "com.apple.product-type.library.dynamic", Bundle = node.cfg.options.SkipBundling and "com.apple.product-type.tool" or "com.apple.product-type.bundle", } return types[node.cfg.kind] end function xcode.gettargettype(node) local types = { ConsoleApp = "\"compiled.mach-o.executable\"", WindowedApp = node.cfg.options.SkipBundling and "\"compiled.mach-o.executable\"" or "wrapper.application", StaticLib = "archive.ar", SharedLib = "\"compiled.mach-o.dylib\"", Bundle = node.cfg.options.SkipBundling and "\"compiled.mach-o.bundle\"" or "wrapper.cfbundle", } return types[node.cfg.kind] end function xcode.getxcodeprojname(prj) local fname = premake.project.getfilename(prj, "%%.xcodeproj") return fname end function xcode.isframework(fname) return (path.getextension(fname) == ".framework" or path.getextension(fname) == ".tbd") end function xcode.uuid(param) return os.uuid(param):upper():gsub('-',''):sub(0,24) end function xcode.newid(node, usage) local base = '' local prj = node.project if prj == nil then local parent = node.parent while parent ~= nil do if parent.project ~= nil then prj = parent.project break end parent = parent.parent end end if prj ~= nil then prj.uuidcounter = (prj.uuidcounter or 0) + 1 base = base .. prj.name .. "$" .. prj.uuidcounter .. "$" end base = base .. "$" .. (node.path or node.name or "") base = base .. "$" .. (usage or "") return xcode.uuid(base) end function xcode.getscriptphaselabel(cmd, count, cfg) return string.format("\"Script Phase %s [%s] (%s)\"", count, cmd:match("(%w+)(.+)"), iif(cfg, xcode.getconfigname(cfg), "all")) end function xcode.getcopyphaselabel(type, count, target) return string.format("\"Copy %s %s [%s]\"", type, count, target) end function xcode.preparesolution(sln) sln.xcode = { } sln.xcode.platforms = premake.filterplatforms(sln, premake.action.current().valid_platforms, "Universal") for prj in premake.solution.eachproject(sln) do local cfg = premake.getconfig(prj, prj.configurations[1], sln.xcode.platforms[1]) local node = premake.tree.new(path.getname(cfg.buildtarget.bundlepath)) node.cfg = cfg node.id = premake.xcode.newid(node, "product") node.targetid = premake.xcode.newid(node, "target") prj.xcode = {} prj.xcode.projectnode = node end end function xcode.printlist(list, tag, sort) if #list > 0 then if sort ~= nil and sort == true then table.sort(list) end _p(4,'%s = (', tag) for _, item in ipairs(list) do local escaped_item = item:gsub("\"", "\\\\\\\""):gsub("'", "\\\\'") _p(5, '"%s",', escaped_item) end _p(4,');') end end function xcode.quotestr(str) if str:match("[^a-zA-Z0-9$._/]") == nil then return str end return "\"" .. str:gsub("[\"\\\"]", "\\%0") .. "\"" end function xcode.Header(tr, objversion) _p('// !$*UTF8*$!') _p('{') _p(1,'archiveVersion = 1;') _p(1,'classes = {') _p(1,'};') _p(1,'objectVersion = %d;', objversion) _p(1,'objects = {') _p('') end function xcode.PBXBuildFile(tr) local function gatherCopyFiles(which) local copyfiles = {} local targets = tr.project[which] if #targets > 0 then for _, t in ipairs(targets) do for __, tt in ipairs(t) do table.insertflat(copyfiles, tt[2]) end end end return table.translate(copyfiles, path.getname) end local function gatherCopyFrameworks(which) local copyfiles = {} local targets = tr.project[which] if #targets > 0 then table.insertflat(copyfiles, targets) end return table.translate(copyfiles, path.getname) end local copyfiles = table.flatten({ gatherCopyFiles('xcodecopyresources'), gatherCopyFrameworks('xcodecopyframeworks') }) _p('/* Begin PBXBuildFile section */') tree.traverse(tr, { onnode = function(node) if node.buildid then _p(2,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; };', node.buildid, node.name, xcode.getbuildcategory(node), node.id, node.name) end if table.icontains(copyfiles, node.name) then _p(2,'%s /* %s in %s */ = {isa = PBXBuildFile; fileRef = %s /* %s */; %s };', xcode.uuid(node.name .. 'in CopyFiles'), node.name, 'CopyFiles', node.id, node.name, iif(xcode.isframework(node.name), "settings = {ATTRIBUTES = (CodeSignOnCopy, ); };", "") ) end end }) _p('/* End PBXBuildFile section */') _p('') end function xcode.PBXContainerItemProxy(tr) if #tr.projects.children > 0 then _p('/* Begin PBXContainerItemProxy section */') for _, node in ipairs(tr.projects.children) do _p(2,'%s /* PBXContainerItemProxy */ = {', node.productproxyid) _p(3,'isa = PBXContainerItemProxy;') _p(3,'containerPortal = %s /* %s */;', node.id, path.getname(node.path)) _p(3,'proxyType = 2;') _p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.id) _p(3,'remoteInfo = "%s";', node.project.xcode.projectnode.name) _p(2,'};') _p(2,'%s /* PBXContainerItemProxy */ = {', node.targetproxyid) _p(3,'isa = PBXContainerItemProxy;') _p(3,'containerPortal = %s /* %s */;', node.id, path.getname(node.path)) _p(3,'proxyType = 1;') _p(3,'remoteGlobalIDString = %s;', node.project.xcode.projectnode.targetid) _p(3,'remoteInfo = "%s";', node.project.xcode.projectnode.name) _p(2,'};') end _p('/* End PBXContainerItemProxy section */') _p('') end end function xcode.PBXFileReference(tr,prj) _p('/* Begin PBXFileReference section */') tree.traverse(tr, { onleaf = function(node) if not node.path then return end if node.kind == "product" then _p(2,'%s /* %s */ = {isa = PBXFileReference; explicitFileType = %s; includeInIndex = 0; name = "%s"; path = "%s"; sourceTree = BUILT_PRODUCTS_DIR; };', node.id, node.name, xcode.gettargettype(node), node.name, path.getname(node.cfg.buildtarget.bundlepath)) elseif node.parent.parent == tr.projects then local relpath = path.getrelative(tr.project.location, node.parent.project.location) _p(2,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "%s"; path = "%s"; sourceTree = SOURCE_ROOT; };', node.parent.id, node.parent.name, node.parent.name, path.join(relpath, node.parent.name)) else 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 nodePath = path.getabsolute(path.join(tr.project.location, nodePath)) end pth = nodePath elseif path.getextension(nodePath)=='.tbd' then pth = "/usr/lib/" .. nodePath else pth = "/System/Library/Frameworks/" .. nodePath end if variable then src = variable if string.find(pth, '^/') then pth = string.sub(pth, 2) end else src = "" end else src = "" if node.location then pth = node.location elseif node.parent.isvpath then pth = node.cfg.name else pth = tree.getlocalpath(node) end end if (not prj.options.ForceCPP) then _p(2,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = %s; name = "%s"; path = "%s"; sourceTree = "%s"; };', node.id, node.name, xcode.getfiletype(node), node.name, pth, src) else _p(2,'%s /* %s */ = {isa = PBXFileReference; explicitFileType = %s; name = "%s"; path = "%s"; sourceTree = "%s"; };', node.id, node.name, xcode.getfiletypeForced(node), node.name, pth, src) end end end }) _p('/* End PBXFileReference section */') _p('') 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) _p(4,'%s /* %s in Frameworks */,', node.buildid, node.name) end }) tree.traverse(tr.projects, { onleaf = function(node) _p(4,'%s /* %s in Frameworks */,', node.buildid, node.name) end }) _p(3,');') _p(3,'runOnlyForDeploymentPostprocessing = 0;') _p(2,'};') _p('/* End PBXFrameworksBuildPhase section */') _p('') end function xcode.PBXGroup(tr) _p('/* Begin PBXGroup section */') tree.traverse(tr, { onnode = function(node) if (node.path and #node.children == 0) or node.kind == "vgroup" then return end 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 _p(4,'%s /* %s */,', childnode.id, childnode.name) end _p(3,');') if node.parent == tr.projects then _p(3,'name = Products;') else _p(3,'name = "%s";', node.name) if node.location then _p(3,'path = "%s";', node.location) elseif node.path and not node.isvpath then local p = node.path if node.parent.path then p = path.getrelative(node.parent.path, node.path) end _p(3,'path = "%s";', p) end end _p(3,'sourceTree = "";') _p(2,'};') end }, true) _p('/* End PBXGroup section */') _p('') end function xcode.PBXNativeTarget(tr) _p('/* Begin PBXNativeTarget section */') for _, node in ipairs(tr.products.children) do local name = tr.project.name local function hasBuildCommands(which) if #tr.project[which] > 0 then return true end for _, cfg in ipairs(tr.configs) do if #cfg[which] > 0 then return true end end end local function dobuildblock(id, label, which, action) if hasBuildCommands(which) then local commandcount = 0 for _, cfg in ipairs(tr.configs) do commandcount = commandcount + #cfg[which] end if commandcount > 0 then action(id, label) end end end local function doscriptphases(which, action) local i = 0 for _, cfg in ipairs(tr.configs) do local cfgcmds = cfg[which] if cfgcmds ~= nil then for __, scripts in ipairs(cfgcmds) do for ___, script in ipairs(scripts) do local cmd = script[1] local label = xcode.getscriptphaselabel(cmd, i, cfg) local id = xcode.uuid(label) action(id, label) i = i + 1 end end end end end local function docopyresources(which, action) if hasBuildCommands(which) then local targets = tr.project[which] if #targets > 0 then local i = 0 for _, t in ipairs(targets) do for __, tt in ipairs(t) do local label = xcode.getcopyphaselabel('Resources', i, tt[1]) local id = xcode.uuid(label) action(id, label) i = i + 1 end end end end end local function docopyframeworks(which, action) if hasBuildCommands(which) then local targets = tr.project[which] if #targets > 0 then local label = "Copy Frameworks" local id = xcode.uuid(label) action(id, label) end end end local function _p_label(id, label) _p(4, '%s /* %s */,', id, label) end _p(2,'%s /* %s */ = {', node.targetid, name) _p(3,'isa = PBXNativeTarget;') _p(3,'buildConfigurationList = %s /* Build configuration list for PBXNativeTarget "%s" */;', node.cfgsection, name) _p(3,'buildPhases = (') dobuildblock('9607AE1010C857E500CD1376', 'Prebuild', 'prebuildcommands', _p_label) _p(4,'%s /* Resources */,', node.resstageid) _p(4,'%s /* Sources */,', node.sourcesid) dobuildblock('9607AE3510C85E7E00CD1376', 'Prelink', 'prelinkcommands', _p_label) _p(4,'%s /* Frameworks */,', node.fxstageid) dobuildblock('9607AE3710C85E8F00CD1376', 'Postbuild', 'postbuildcommands', _p_label) doscriptphases("xcodescriptphases", _p_label) docopyresources("xcodecopyresources", _p_label) if tr.project.kind == "WindowedApp" then docopyframeworks("xcodecopyframeworks", _p_label) 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";', name) 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";', p) end _p(3,'productName = "%s";', name) _p(3,'productReference = %s /* %s */;', node.id, node.name) _p(3,'productType = "%s";', xcode.getproducttype(node)) _p(2,'};') end _p('/* End PBXNativeTarget section */') _p('') end function xcode.PBXProject(tr, compatVersion) _p('/* Begin PBXProject section */') _p(2,'__RootObject_ /* Project object */ = {') _p(3,'isa = PBXProject;') _p(3,'buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "%s" */;', tr.name) _p(3,'compatibilityVersion = "Xcode %s";', compatVersion) _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) if #tr.projects.children > 0 then _p('/* Begin PBXReferenceProxy section */') tree.traverse(tr.projects, { onleaf = function(node) _p(2,'%s /* %s */ = {', node.id, node.name) _p(3,'isa = PBXReferenceProxy;') _p(3,'fileType = %s;', xcode.gettargettype(node)) _p(3,'path = "%s";', node.path) _p(3,'remoteRef = %s /* PBXContainerItemProxy */;', node.parent.productproxyid) _p(3,'sourceTree = BUILT_PRODUCTS_DIR;') _p(2,'};') end }) _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, commands, files) if commands ~= nil then commands = table.flatten(commands) end if #commands > 0 then 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 = ('); if files ~= nil then files = table.flatten(files) if #files > 0 then for _, file in ipairs(files) do _p(4, '"%s",', file) end end end _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";', table.concat(commands, "\\n"):gsub('"', '\\"')) _p(2,'};') end end local function wrapcommands(cmds, cfg) local commands = {} if #cmds > 0 then table.insert(commands, 'if [ "${CONFIGURATION}" = "' .. xcode.getconfigname(cfg) .. '" ]; then') for i = 1, #cmds do local cmd = cmds[i] cmd = cmd:gsub('\\','\\\\') table.insert(commands, cmd) end table.insert(commands, 'fi') end return commands end local function dobuildblock(id, name, which) local commands = {} for _, cfg in ipairs(tr.configs) do local cfgcmds = wrapcommands(cfg[which], cfg) if #cfgcmds > 0 then for i, cmd in ipairs(cfgcmds) do table.insert(commands, cmd) end end end doblock(id, name, commands) end local function doscriptphases(which) local i = 0 for _, cfg in ipairs(tr.configs) do local cfgcmds = cfg[which] if cfgcmds ~= nil then for __, scripts in ipairs(cfgcmds) do for ___, script in ipairs(scripts) do local cmd = script[1] local files = script[2] local label = xcode.getscriptphaselabel(cmd, i, cfg) local id = xcode.uuid(label) doblock(id, label, wrapcommands({cmd}, cfg), files) i = i + 1 end end end end end dobuildblock("9607AE1010C857E500CD1376", "Prebuild", "prebuildcommands") dobuildblock("9607AE3510C85E7E00CD1376", "Prelink", "prelinkcommands") dobuildblock("9607AE3710C85E8F00CD1376", "Postbuild", "postbuildcommands") doscriptphases("xcodescriptphases") if wrapperWritten then _p('/* End PBXShellScriptBuildPhase section */') end end function xcode.PBXSourcesBuildPhase(tr,prj) _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" then if not table.icontains(prj.excludes, node.cfg.name) then -- if not excluded _p(4,'%s /* %s in Sources */,', node.buildid, node.name) end end end }) _p(3,');') _p(3,'runOnlyForDeploymentPostprocessing = 0;') _p(2,'};') end _p('/* End PBXSourcesBuildPhase section */') _p('') end function xcode.PBXCopyFilesBuildPhase(tr) local wrapperWritten = false local function doblock(id, name, folderSpec, path, files) if #files > 0 then if not wrapperWritten then _p('/* Begin PBXCopyFilesBuildPhase section */') wrapperWritten = true end _p(2,'%s /* %s */ = {', id, name) _p(3,'isa = PBXCopyFilesBuildPhase;') _p(3,'buildActionMask = 2147483647;') _p(3,'dstPath = \"%s\";', path) _p(3,'dstSubfolderSpec = \"%s\";', folderSpec) _p(3,'files = (') tree.traverse(tr, { onleaf = function(node) if table.icontains(files, node.name) then _p(4,'%s /* %s in %s */,', xcode.uuid(node.name .. 'in CopyFiles'), node.name, 'CopyFiles') end end }) _p(3,');') _p(3,'runOnlyForDeploymentPostprocessing = 0;'); _p(2,'};') end end local function docopyresources(which) local targets = tr.project[which] if #targets > 0 then local i = 0 for _, t in ipairs(targets) do for __, tt in ipairs(t) do local label = xcode.getcopyphaselabel('Resources', i, tt[1]) local id = xcode.uuid(label) local files = table.translate(table.flatten(tt[2]), path.getname) doblock(id, label, 7, tt[1], files) i = i + 1 end end end end local function docopyframeworks(which) local targets = tr.project[which] if #targets > 0 then local label = "Copy Frameworks" local id = xcode.uuid(label) local files = table.translate(table.flatten(targets), path.getname) doblock(id, label, 10, "", files) end end docopyresources("xcodecopyresources") if tr.project.kind == "WindowedApp" then docopyframeworks("xcodecopyframeworks") end if wrapperWritten then _p('/* End PBXCopyFilesBuildPhase section */') end end function xcode.PBXVariantGroup(tr) _p('/* Begin PBXVariantGroup section */') tree.traverse(tr, { onbranch = function(node) 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 }) _p('/* End PBXVariantGroup section */') _p('') end function xcode.PBXTargetDependency(tr) if #tr.projects.children > 0 then _p('/* Begin PBXTargetDependency section */') tree.traverse(tr.projects, { onleaf = function(node) _p(2,'%s /* PBXTargetDependency */ = {', node.parent.targetdependid) _p(3,'isa = PBXTargetDependency;') _p(3,'name = "%s";', node.name) _p(3,'targetProxy = %s /* PBXContainerItemProxy */;', node.parent.targetproxyid) _p(2,'};') end }) _p('/* End PBXTargetDependency section */') _p('') end end function xcode.cfg_excluded_files(prj, cfg) local excluded = {} local function exclude_pattern(file) if path.isabsolute(file) then return file end local start, term = file:findlast("/%.%./") if term then return path.join("*", file:sub(term + 1)) end start, term = file:find("%.%./") if start == 1 then return path.join("*", file:sub(term + 1)) end return path.join("*", file) end local function add_file(file) local name = exclude_pattern(file) if not table.icontains(excluded, name) then table.insert(excluded, name) end end local function verify_file(file) local name = exclude_pattern(file) if table.icontains(excluded, name) then error("'" .. file .. "' would be excluded by the rule to exclude '" .. name .. "'") end end for _, file in ipairs(cfg.excludes) do add_file(file) end for _, file in ipairs(prj.allfiles) do if not table.icontains(prj.excludes, file) and not table.icontains(cfg.excludes, file) then if not table.icontains(cfg.files, file) then add_file(file) else verify_file(file) end end end table.sort(excluded) return excluded end function xcode.XCBuildConfiguration_Impl(tr, id, opts, cfg) local cfgname = xcode.getconfigname(cfg) _p(2,'%s /* %s */ = {', id, cfgname) _p(3,'isa = XCBuildConfiguration;') _p(3,'buildSettings = {') for k, v in table.sortedpairs(opts) do if type(v) == "table" then if #v > 0 then _p(4,'%s = (', k) for i, v2 in ipairs(v) do _p(5,'%s,', xcode.quotestr(tostring(v2))) end _p(4,');') end else _p(4,'%s = %s;', k, xcode.quotestr(tostring(v))) end end _p(3,'};') _p(3,'name = %s;', xcode.quotestr(cfgname)) _p(2,'};') end local function add_options(options, extras) for _, tbl in ipairs(extras) do for tkey, tval in pairs(tbl) do options[tkey] = tval end end end local function add_wholearchive_links(opts, cfg) if #cfg.wholearchive > 0 then local linkopts = {} for _, depcfg in ipairs(premake.getlinks(cfg, "siblings", "object")) do if table.icontains(cfg.wholearchive, depcfg.project.name) then local linkpath = path.rebase(depcfg.linktarget.fullpath, depcfg.location, cfg.location) table.insert(linkopts, "-force_load") table.insert(linkopts, linkpath) end end if opts.OTHER_LDFLAGS then linkopts = table.join(linkopts, opts.OTHER_LDFLAGS) end opts.OTHER_LDFLAGS = linkopts end end function xcode.XCBuildConfiguration(tr, prj, opts) _p('/* Begin XCBuildConfiguration section */') for _, target in ipairs(tr.products.children) do for _, cfg in ipairs(tr.configs) do local values = opts.ontarget(tr, target, cfg) add_options(values, cfg.xcodetargetopts) xcode.XCBuildConfiguration_Impl(tr, cfg.xcode.targetid, values, cfg) end end for _, cfg in ipairs(tr.configs) do local values = opts.onproject(tr, prj, cfg) add_options(values, cfg.xcodeprojectopts) add_wholearchive_links(values, cfg) xcode.XCBuildConfiguration_Impl(tr, cfg.xcode.projectid, values, cfg) end _p('/* End XCBuildConfiguration section */') _p('') end function xcode.XCBuildConfigurationList(tr) local sln = tr.project.solution _p('/* Begin XCConfigurationList section */') for _, target in ipairs(tr.products.children) do _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, xcode.getconfigname(cfg)) end _p(3,');') _p(3,'defaultConfigurationIsVisible = 0;') _p(3,'defaultConfigurationName = "%s";', xcode.getconfigname(tr.configs[1])) _p(2,'};') end _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, xcode.getconfigname(cfg)) end _p(3,');') _p(3,'defaultConfigurationIsVisible = 0;') _p(3,'defaultConfigurationName = "%s";', xcode.getconfigname(tr.configs[1])) _p(2,'};') _p('/* End XCConfigurationList section */') _p('') end function xcode.Footer() _p(1,'};') _p('\trootObject = __RootObject_ /* Project object */;') _p('}') end local xcode = premake.xcode local tree = premake.tree function xcode.buildprjtree(prj) local tr = premake.project.buildsourcetree(prj, true) tr.configs = {} for _, cfgname in ipairs(prj.solution.configurations) do for _, platform in ipairs(prj.solution.xcode.platforms) do local cfg = premake.getconfig(prj, cfgname, platform) cfg.xcode = {} cfg.xcode.targetid = xcode.newid(prj.xcode.projectnode, "tgt:"..platform..cfgname) cfg.xcode.projectid = xcode.newid(tr, "prj:"..platform..cfgname) table.insert(tr.configs, cfg) end 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 }) tree.traverse(tr, { onbranch = function(node) if path.getextension(node.name) == ".xcassets" then node.children = {} end end }) tr.frameworks = tree.new("Frameworks") for cfg in premake.eachconfig(prj) do for _, link in ipairs(premake.getlinks(cfg, "system", "fullpath")) do local name = path.getname(link) if xcode.isframework(name) and not tr.frameworks.children[name] then node = tree.insert(tr.frameworks, tree.new(name)) node.path = link end end end if #tr.frameworks.children > 0 then tree.insert(tr, tr.frameworks) end tr.products = tree.insert(tr, tree.new("Products")) tr.projects = tree.new("Projects") for _, dep in ipairs(premake.getdependencies(prj, "sibling", "object")) do 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, "prodgrp") xcnode.productproxyid = xcode.newid(xcnode, "prodprox") xcnode.targetproxyid = xcode.newid(xcnode, "targprox") xcnode.targetdependid = xcode.newid(xcnode, "targdep") local cfg = premake.getconfig(dep, prj.configurations[1]) node = tree.insert(xcnode, tree.new(cfg.linktarget.name)) node.path = cfg.linktarget.fullpath node.cfg = cfg end if #tr.projects.children > 0 then tree.insert(tr, tr.projects) end tree.traverse(tr, { onbranchexit = function(node) for _, child in ipairs(node.children) do if (child.location) then if (node.location) then while (not string.startswith(child.location, node.location)) do node.location = path.getdirectory(node.location) end else node.location = path.getdirectory(child.location) end end end end, onleaf = function(node) if (node.cfg) then node.location = node.cfg.name end end }, true) tree.traverse(tr, { onbranchexit = function(node, depth) if (node.location and node.parent and node.parent.location) then node.location = path.getrelative(node.parent.location, node.location) end end, onleaf = function(node, depth) if (node.location and node.parent and node.parent.location) then node.location = path.getrelative(node.parent.location, node.location) end end }, true) tree.traverse(tr, { onnode = function(node) node.id = xcode.newid(node) if xcode.getbuildcategory(node) then node.buildid = xcode.newid(node, "build") end if string.endswith(node.name, "Info.plist") then tr.infoplist = node end if string.endswith(node.name, ".entitlements") then tr.entitlements = 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, "cfg") node.resstageid = xcode.newid(node, "rez") node.sourcesid = xcode.newid(node, "src") node.fxstageid = xcode.newid(node, "fxs") return tr end local premake = premake local xcode = premake.xcode local function buildableref(indent, prj, cfg) cfg = cfg or premake.eachconfig(prj)() _p(indent + 0, '', prj.name) _p(indent + 0, '') end local function cmdlineargs(indent, cfg) if #cfg.debugargs > 0 then _p(indent, '') for _, arg in ipairs(cfg.debugargs) do _p(indent + 1, '') _p(indent + 1, '') end _p(indent, '') end end local function envvars(indent, cfg) if #cfg.debugenvs > 0 then _p(indent, '') for _, arg in ipairs(cfg.debugenvs) do local eq = arg:find("=") local k = arg:sub(1, eq) local v = arg:sub(eq + 1) _p(indent + 1, '') _p(indent + 1, '') end _p(indent, '') end end local function workingdir(dir) if not path.isabsolute(dir) then dir = "$PROJECT_DIR/" .. dir end return dir end local function bestconfig(prj, fordebug) local bestcfg = nil local bestscore = -1 for cfg in premake.eachconfig(prj) do local score = 0 if cfg.platform == "Native" then score = score + 10 end if fordebug and cfg.name == "Debug" then score = score + 1 end if not fordebug and cfg.name == "Release" then score = score + 1 end if score > bestscore then bestcfg = cfg bestscore = score end end return bestcfg end function xcode.scheme(tobuild, primary, schemecfg) _p('') _p('') _p(1, '') _p(2, '') for _, prj in ipairs(tobuild) do _p(3, '') buildableref(4, prj) _p(3, '') end local debugcfg = schemecfg or bestconfig(primary, true) local releasecfg = schemecfg or bestconfig(primary, false) local debugname = xcode.getconfigname(debugcfg) local releasename = xcode.getconfigname(releasecfg) _p(2, '') _p(1, '') _p(1, '') _p(2, '') _p(2, '') _p(2, '') buildableref(3, primary, debugcfg) _p(2, '') _p(2, '') _p(2, '') _p(1, '') _p(1, '') if debugcfg.debugcmd then _p(2, '', debugcfg.debugcmd) _p(2, '') else _p(2, '') buildableref(3, primary, debugcfg) _p(2, '') end cmdlineargs(2, debugcfg) envvars(2, debugcfg) _p(2, '') _p(2, '') _p(1, '') _p(1, '') _p(2, '') buildableref(3, primary, releasecfg) _p(2, '') cmdlineargs(2, releasecfg) envvars(2, releasecfg) _p(1, '') _p(1, '', debugname) _p(1, '') _p(1, '') _p(1, '') _p('') end function xcode.generate_schemes(prj, base_path) if (prj.kind == "ConsoleApp" or prj.kind == "WindowedApp") or (prj.options and prj.options.XcodeLibrarySchemes) then if prj.options and prj.options.XcodeSchemeNoConfigs then premake.generate(prj, path.join(base_path, "%%.xcscheme"), function(prj) xcode.scheme({prj}, prj) end) else for cfg in premake.eachconfig(prj) do premake.generate(prj, path.join(base_path, "%% " .. cfg.name .. ".xcscheme"), function(prj) xcode.scheme({prj}, prj, cfg) end) end end end end local premake = premake local xcode = premake.xcode xcode.allscheme = false function xcode.workspace_head() _p('') _p('') end function xcode.workspace_tail() _p('') end function xcode.workspace_file_ref(prj, indent) local projpath = path.getrelative(prj.solution.location, prj.location) if projpath == '.' then projpath = '' else projpath = projpath ..'/' end _p(indent, '', projpath .. prj.name .. '.xcodeproj') _p(indent, '') end function xcode.workspace_group(grp, indent) _p(indent, '', grp.name) local function comparenames(a, b) return a.name < b.name end local groups = table.join(grp.groups) local projects = table.join(grp.projects) table.sort(groups, comparenames) table.sort(projects, comparenames) for _, child in ipairs(groups) do xcode.workspace_group(child, indent + 1) end for _, prj in ipairs(projects) do xcode.workspace_file_ref(prj, indent + 1) end _p(indent, '') end function xcode.workspace_generate(sln) xcode.preparesolution(sln) xcode.workspace_head() xcode.reorderProjects(sln) for grp in premake.solution.eachgroup(sln) do if grp.parent == nil then xcode.workspace_group(grp, 1) end end for prj in premake.solution.eachproject(sln) do if prj.group == nil then xcode.workspace_file_ref(prj, 1) end end xcode.workspace_tail() end function xcode.workspace_scheme(sln) if not xcode.allscheme then return false end local projects = {} local primary = nil for prj in premake.solution.eachproject(sln) do if not primary or (sln.startproject == prj.name) then primary = prj end table.insert(projects, prj) end xcode.scheme(projects, primary) end function xcode.workspace_settings(sln) _p('') _p('') _p('') _p('') _p(1, 'IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded') _p(1, '') _p('') _p('') end function xcode.reorderProjects(sln) if sln.startproject then for i, prj in ipairs(sln.projects) do if sln.startproject == prj.name then local cur = prj.group while cur ~= nil do for j, group in ipairs(sln.groups) do if group == cur then table.remove(sln.groups, j) break end end table.insert(sln.groups, 1, cur) cur = cur.parent end table.remove(sln.projects, i) table.insert(sln.projects, 1, prj) break end end end end local premake = premake premake.xcode8 = { } local xcode = premake.xcode local xcode8 = premake.xcode8 function xcode8.XCBuildConfiguration_Target(tr, target, cfg) local cfgname = xcode.getconfigname(cfg) local installpaths = { ConsoleApp = "/usr/local/bin", WindowedApp = "$(HOME)/Applications", SharedLib = "/usr/local/lib", StaticLib = "/usr/local/lib", Bundle = "$(LOCAL_LIBRARY_DIR)/Bundles", } local options = { ALWAYS_SEARCH_USER_PATHS = "NO", GCC_DYNAMIC_NO_PIC = "NO", GCC_MODEL_TUNING = "G5", INSTALL_PATH = installpaths[cfg.kind], PRODUCT_NAME = cfg.buildtarget.basename, } if not cfg.flags.Symbols then options.DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym" end if cfg.kind ~= "StaticLib" and cfg.buildtarget.prefix ~= "" then options.EXECUTABLE_PREFIX = cfg.buildtarget.prefix end if cfg.targetextension then local ext = cfg.targetextension options.EXECUTABLE_EXTENSION = iif(ext:startswith("."), ext:sub(2), ext) end if cfg.flags.ObjcARC then options.CLANG_ENABLE_OBJC_ARC = "YES" end local outdir = path.getdirectory(cfg.buildtarget.bundlepath) if outdir ~= "." then options.CONFIGURATION_BUILD_DIR = outdir end if tr.infoplist then options.INFOPLIST_FILE = tr.infoplist.cfg.name end local infoplist_file = nil for _, v in ipairs(cfg.files) do if (string.find (string.lower (v), 'info.plist') ~= nil) then infoplist_file = string.format('$(SRCROOT)/%s', v) end end if infoplist_file ~= nil then options.INFOPLIST_FILE = infoplist_file end local action = premake.action.current() local get_opt = function(opt, def) return (opt and #opt > 0) and opt or def end local iosversion = get_opt(cfg.iostargetplatformversion, action.xcode.iOSTargetPlatformVersion) local macosversion = get_opt(cfg.macostargetplatformversion, action.xcode.macOSTargetPlatformVersion) local tvosversion = get_opt(cfg.tvostargetplatformversion, action.xcode.tvOSTargetPlatformVersion) if iosversion then options.IPHONEOS_DEPLOYMENT_TARGET = iosversion elseif macosversion then options.MACOSX_DEPLOYMENT_TARGET = macosversion elseif tvosversion then options.TVOS_DEPLOYMENT_TARGET = tvosversion end if cfg.kind == "Bundle" and not cfg.options.SkipBundling then options.PRODUCT_BUNDLE_IDENTIFIER = "genie." .. cfg.buildtarget.basename:gsub("%s+", ".") --replace spaces with . local ext = cfg.targetextension if ext then options.WRAPPER_EXTENSION = iif(ext:startswith("."), ext:sub(2), ext) else options.WRAPPER_EXTENSION = "bundle" end end return options end function xcode8.XCBuildConfiguration_Project(tr, prj, cfg) local cfgname = xcode.getconfigname(cfg) local archs = { Native = nil, x32 = "i386", x64 = "x86_64", Universal32 = "$(ARCHS_STANDARD_32_BIT)", Universal64 = "$(ARCHS_STANDARD_64_BIT)", Universal = "$(ARCHS_STANDARD_32_64_BIT)", } local checks = { ["-ffast-math"] = cfg.flags.FloatFast, ["-ffloat-store"] = cfg.flags.FloatStrict, ["-fomit-frame-pointer"] = cfg.flags.NoFramePointer, } local cflags = { } for flag, check in pairs(checks) do if check then table.insert(cflags, flag) end end local ldflags = { } for _, lib in ipairs(premake.getlinks(cfg, "system")) do if not xcode.isframework(lib) then table.insert(ldflags, "-l" .. lib) end end local options = { ARCHS = archs[cfg.platform], CLANG_WARN__DUPLICATE_METHOD_MATCH = "YES", CLANG_WARN_BOOL_CONVERSION = "YES", CLANG_WARN_CONSTANT_CONVERSION = "YES", CLANG_WARN_EMPTY_BODY = "YES", CLANG_WARN_ENUM_CONVERSION = "YES", CLANG_WARN_INFINITE_RECURSION = "YES", CLANG_WARN_INT_CONVERSION = "YES", CLANG_WARN_SUSPICIOUS_MOVE = "YES", CLANG_WARN_UNREACHABLE_CODE = "YES", CONFIGURATION_TEMP_DIR = "$(OBJROOT)", ENABLE_STRICT_OBJC_MSGSEND = "YES", ENABLE_TESTABILITY = "YES", GCC_C_LANGUAGE_STANDARD = "gnu99", GCC_NO_COMMON_BLOCKS = "YES", GCC_PREPROCESSOR_DEFINITIONS = cfg.defines, GCC_SYMBOLS_PRIVATE_EXTERN = "NO", GCC_WARN_64_TO_32_BIT_CONVERSION = "YES", GCC_WARN_ABOUT_RETURN_TYPE = "YES", GCC_WARN_UNDECLARED_SELECTOR = "YES", GCC_WARN_UNINITIALIZED_AUTOS = "YES", GCC_WARN_UNUSED_FUNCTION = "YES", GCC_WARN_UNUSED_VARIABLE = "YES", HEADER_SEARCH_PATHS = table.join(cfg.includedirs, cfg.systemincludedirs), LIBRARY_SEARCH_PATHS = cfg.libdirs, OBJROOT = cfg.objectsdir, ONLY_ACTIVE_ARCH = "YES", OTHER_CFLAGS = table.join(cflags, cfg.buildoptions, cfg.buildoptions_c), OTHER_CPLUSPLUSFLAGS = table.join(cflags, cfg.buildoptions, cfg.buildoptions_cpp), OTHER_LDFLAGS = table.join(ldflags, cfg.linkoptions), SDKROOT = xcode.toolset, USER_HEADER_SEARCH_PATHS = cfg.userincludedirs, } if tr.entitlements then options.CODE_SIGN_ENTITLEMENTS = tr.entitlements.cfg.name end local targetdir = path.getdirectory(cfg.buildtarget.bundlepath) if targetdir ~= "." then options.CONFIGURATION_BUILD_DIR = "$(SYMROOT)" options.SYMROOT = targetdir end if cfg.flags.Symbols then options.COPY_PHASE_STRIP = "NO" end local excluded = xcode.cfg_excluded_files(prj, cfg) if #excluded > 0 then options.EXCLUDED_SOURCE_FILE_NAMES = excluded end if cfg.flags.NoExceptions then options.GCC_ENABLE_CPP_EXCEPTIONS = "NO" end if cfg.flags.NoRTTI then options.GCC_ENABLE_CPP_RTTI = "NO" end if cfg.flags.Symbols and not cfg.flags.NoEditAndContinue then options.GCC_ENABLE_FIX_AND_CONTINUE = "YES" end if cfg.flags.NoExceptions then options.GCC_ENABLE_OBJC_EXCEPTIONS = "NO" end if cfg.flags.Optimize or cfg.flags.OptimizeSize then options.GCC_OPTIMIZATION_LEVEL = "s" elseif cfg.flags.OptimizeSpeed then options.GCC_OPTIMIZATION_LEVEL = 3 else options.GCC_OPTIMIZATION_LEVEL = 0 end if cfg.pchheader and not cfg.flags.NoPCH then options.GCC_PRECOMPILE_PREFIX_HEADER = "YES" local pch = cfg.pchheader for _, incdir in ipairs(cfg.includedirs) do local abspath = path.getabsolute(path.join(cfg.project.location, incdir)) local testname = path.join(abspath, pch) if os.isfile(testname) then pch = path.getrelative(cfg.location, testname) break end end options.GCC_PREFIX_HEADER = pch end if cfg.flags.FatalWarnings then options.GCC_TREAT_WARNINGS_AS_ERRORS = "YES" end if cfg.kind == "Bundle" then options.MACH_O_TYPE = "mh_bundle" end if cfg.flags.StaticRuntime then options.STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = "static" end if cfg.flags.PedanticWarnings or cfg.flags.ExtraWarnings then options.WARNING_CFLAGS = "-Wall" end if cfg.flags.Cpp11 then options.CLANG_CXX_LANGUAGE_STANDARD = "c++11" elseif cfg.flags.Cpp14 or cfg.flags.CppLatest then options.CLANG_CXX_LANGUAGE_STANDARD = "c++14" elseif cfg.flags.Cpp17 then if premake.action.current() == premake.action.get("xcode8") then error("XCode8 does not support C++17.") end end for _, val in ipairs(premake.xcode.parameters) do local eqpos = string.find(val, "=") if eqpos ~= nil then local key = string.trim(string.sub(val, 1, eqpos - 1)) local value = string.trim(string.sub(val, eqpos + 1)) options[key] = value end end return options end function xcode8.project(prj) local tr = xcode.buildprjtree(prj) xcode.Header(tr, 48) xcode.PBXBuildFile(tr) xcode.PBXContainerItemProxy(tr) xcode.PBXFileReference(tr,prj) xcode.PBXFrameworksBuildPhase(tr) xcode.PBXGroup(tr) xcode.PBXNativeTarget(tr) xcode.PBXProject(tr, "8.0") xcode.PBXReferenceProxy(tr) xcode.PBXResourcesBuildPhase(tr) xcode.PBXShellScriptBuildPhase(tr) xcode.PBXCopyFilesBuildPhase(tr) xcode.PBXSourcesBuildPhase(tr,prj) xcode.PBXVariantGroup(tr) xcode.PBXTargetDependency(tr) xcode.XCBuildConfiguration(tr, prj, { ontarget = xcode8.XCBuildConfiguration_Target, onproject = xcode8.XCBuildConfiguration_Project, }) xcode.XCBuildConfigurationList(tr) xcode.Footer(tr) end newaction { trigger = "xcode8", shortname = "Xcode 8", description = "Generate Apple Xcode 8 project files", os = "macosx", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc" }, }, valid_platforms = { Native = "Native", x32 = "Native 32-bit", x64 = "Native 64-bit", Universal = "Universal", }, default_platform = "Native", onsolution = function(sln) premake.generate(sln, "%%.xcworkspace/contents.xcworkspacedata", xcode.workspace_generate) premake.generate(sln, "%%.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings", xcode.workspace_settings) premake.generate(sln, "%%.xcworkspace/xcshareddata/xcschemes/-ALL-.xcscheme", xcode.workspace_scheme) end, onproject = function(prj) premake.generate(prj, "%%.xcodeproj/project.pbxproj", xcode8.project) xcode.generate_schemes(prj, "%%.xcodeproj/xcshareddata/xcschemes") end, oncleanproject = function(prj) premake.clean.directory(prj, "%%.xcodeproj") premake.clean.directory(prj, "%%.xcworkspace") end, oncheckproject = xcode.checkproject, xcode = { iOSTargetPlatformVersion = nil, macOSTargetPlatformVersion = nil, tvOSTargetPlatformVersion = nil, }, } local premake = premake premake.xcode9 = { } local xcode = premake.xcode local xcode8 = premake.xcode8 local xcode9 = premake.xcode9 function xcode9.XCBuildConfiguration_Project(tr, prj, cfg) local options = xcode8.XCBuildConfiguration_Project(tr, prj, cfg) if cfg.flags.Cpp17 then options.CLANG_CXX_LANGUAGE_STANDARD = "c++17" elseif cfg.flags.Cpp20 or cfg.flags.CppLatest then options.CLANG_CXX_LANGUAGE_STANDARD = "c++20" end return table.merge(options, { CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = "YES", CLANG_WARN_COMMA = "YES", CLANG_WARN_NON_LITERAL_NULL_CONVERSION = "YES", CLANG_WARN_OBJC_LITERAL_CONVERSION = "YES", CLANG_WARN_RANGE_LOOP_ANALYSIS = "YES", CLANG_WARN_STRICT_PROTOTYPES = "YES", }) end function xcode9.project(prj) local tr = xcode.buildprjtree(prj) xcode.Header(tr, 48) xcode.PBXBuildFile(tr) xcode.PBXContainerItemProxy(tr) xcode.PBXFileReference(tr,prj) xcode.PBXFrameworksBuildPhase(tr) xcode.PBXGroup(tr) xcode.PBXNativeTarget(tr) xcode.PBXProject(tr, "8.0") xcode.PBXReferenceProxy(tr) xcode.PBXResourcesBuildPhase(tr) xcode.PBXShellScriptBuildPhase(tr) xcode.PBXCopyFilesBuildPhase(tr) xcode.PBXSourcesBuildPhase(tr,prj) xcode.PBXVariantGroup(tr) xcode.PBXTargetDependency(tr) xcode.XCBuildConfiguration(tr, prj, { ontarget = xcode8.XCBuildConfiguration_Target, onproject = xcode9.XCBuildConfiguration_Project, }) xcode.XCBuildConfigurationList(tr) xcode.Footer(tr) end newaction { trigger = "xcode9", shortname = "Xcode 9", description = "Generate Apple Xcode 9 project files", os = "macosx", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc" }, }, valid_platforms = { Native = "Native", x32 = "Native 32-bit", x64 = "Native 64-bit", Universal = "Universal", }, default_platform = "Native", onsolution = function(sln) premake.generate(sln, "%%.xcworkspace/contents.xcworkspacedata", xcode.workspace_generate) premake.generate(sln, "%%.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings", xcode.workspace_settings) premake.generate(sln, "%%.xcworkspace/xcshareddata/xcschemes/-ALL-.xcscheme", xcode.workspace_scheme) end, onproject = function(prj) premake.generate(prj, "%%.xcodeproj/project.pbxproj", xcode9.project) xcode.generate_schemes(prj, "%%.xcodeproj/xcshareddata/xcschemes") end, oncleanproject = function(prj) premake.clean.directory(prj, "%%.xcodeproj") premake.clean.directory(prj, "%%.xcworkspace") end, oncheckproject = xcode.checkproject, xcode = { iOSTargetPlatformVersion = nil, macOSTargetPlatformVersion = nil, tvOSTargetPlatformVersion = nil, }, } local premake = premake premake.xcode10 = { } local xcode = premake.xcode local xcode8 = premake.xcode8 local xcode9 = premake.xcode9 local xcode10 = premake.xcode10 function xcode10.XCBuildConfiguration_Project(tr, prj, cfg) local options = xcode9.XCBuildConfiguration_Project(tr, prj, cfg) return table.merge(options, { CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = "YES", CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = "YES", CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = "YES", CLANG_WARN_COMMA = "YES", CLANG_WARN_NON_LITERAL_NULL_CONVERSION = "YES", CLANG_WARN_OBJC_LITERAL_CONVERSION = "YES", CLANG_WARN_RANGE_LOOP_ANALYSIS = "YES", CLANG_WARN_STRICT_PROTOTYPES = "YES", }) end function xcode10.XCBuildConfiguration_Target(tr, target, cfg) local options = xcode8.XCBuildConfiguration_Target(tr, target, cfg) if not cfg.flags.ObjcARC then options.CLANG_ENABLE_OBJC_WEAK = "YES" end return options end function xcode10.project(prj) local tr = xcode.buildprjtree(prj) xcode.Header(tr, 48) xcode.PBXBuildFile(tr) xcode.PBXContainerItemProxy(tr) xcode.PBXFileReference(tr,prj) xcode.PBXFrameworksBuildPhase(tr) xcode.PBXGroup(tr) xcode.PBXNativeTarget(tr) xcode.PBXProject(tr, "8.0") xcode.PBXReferenceProxy(tr) xcode.PBXResourcesBuildPhase(tr) xcode.PBXShellScriptBuildPhase(tr) xcode.PBXCopyFilesBuildPhase(tr) xcode.PBXSourcesBuildPhase(tr,prj) xcode.PBXVariantGroup(tr) xcode.PBXTargetDependency(tr) xcode.XCBuildConfiguration(tr, prj, { ontarget = xcode10.XCBuildConfiguration_Target, onproject = xcode10.XCBuildConfiguration_Project, }) xcode.XCBuildConfigurationList(tr) xcode.Footer(tr) end newaction { trigger = "xcode10", shortname = "Xcode 10", description = "Generate Apple Xcode 10 project files", os = "macosx", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc" }, }, valid_platforms = { Native = "Native", x32 = "Native 32-bit", x64 = "Native 64-bit", Universal = "Universal", }, default_platform = "Native", onsolution = function(sln) premake.generate(sln, "%%.xcworkspace/contents.xcworkspacedata", xcode.workspace_generate) premake.generate(sln, "%%.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings", xcode.workspace_settings) premake.generate(sln, "%%.xcworkspace/xcshareddata/xcschemes/-ALL-.xcscheme", xcode.workspace_scheme) end, onproject = function(prj) premake.generate(prj, "%%.xcodeproj/project.pbxproj", xcode10.project) xcode.generate_schemes(prj, "%%.xcodeproj/xcshareddata/xcschemes") end, oncleanproject = function(prj) premake.clean.directory(prj, "%%.xcodeproj") premake.clean.directory(prj, "%%.xcworkspace") end, oncheckproject = xcode.checkproject, xcode = { iOSTargetPlatformVersion = nil, macOSTargetPlatformVersion = nil, tvOSTargetPlatformVersion = nil, }, } local premake = premake premake.xcode11 = { } local xcode = premake.xcode local xcode10 = premake.xcode10 local xcode11 = premake.xcode11 function xcode11.XCBuildConfiguration_Target(tr, target, cfg) local options = xcode10.XCBuildConfiguration_Target(tr, target, cfg) options.CODE_SIGN_IDENTITY = "-" return options end function xcode11.project(prj) local tr = xcode.buildprjtree(prj) xcode.Header(tr, 48) xcode.PBXBuildFile(tr) xcode.PBXContainerItemProxy(tr) xcode.PBXFileReference(tr,prj) xcode.PBXFrameworksBuildPhase(tr) xcode.PBXGroup(tr) xcode.PBXNativeTarget(tr) xcode.PBXProject(tr, "8.0") xcode.PBXReferenceProxy(tr) xcode.PBXResourcesBuildPhase(tr) xcode.PBXShellScriptBuildPhase(tr) xcode.PBXCopyFilesBuildPhase(tr) xcode.PBXSourcesBuildPhase(tr,prj) xcode.PBXVariantGroup(tr) xcode.PBXTargetDependency(tr) xcode.XCBuildConfiguration(tr, prj, { ontarget = xcode11.XCBuildConfiguration_Target, onproject = xcode10.XCBuildConfiguration_Project, }) xcode.XCBuildConfigurationList(tr) xcode.Footer(tr) end newaction { trigger = "xcode11", shortname = "Xcode 11", description = "Generate Apple Xcode 11 project files", os = "macosx", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc" }, }, valid_platforms = { Native = "Native" }, default_platform = "Native", onsolution = function(sln) premake.generate(sln, "%%.xcworkspace/contents.xcworkspacedata", xcode.workspace_generate) premake.generate(sln, "%%.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings", xcode.workspace_settings) premake.generate(sln, "%%.xcworkspace/xcshareddata/xcschemes/-ALL-.xcscheme", xcode.workspace_scheme) end, onproject = function(prj) premake.generate(prj, "%%.xcodeproj/project.pbxproj", xcode11.project) xcode.generate_schemes(prj, "%%.xcodeproj/xcshareddata/xcschemes") end, oncleanproject = function(prj) premake.clean.directory(prj, "%%.xcodeproj") premake.clean.directory(prj, "%%.xcworkspace") end, oncheckproject = xcode.checkproject, xcode = { iOSTargetPlatformVersion = nil, macOSTargetPlatformVersion = nil, tvOSTargetPlatformVersion = nil, }, } premake.ninja = { } local p = premake newaction { trigger = "ninja", shortname = "ninja", description = "Generate Ninja build files", module = "ninja", valid_kinds = {"ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle"}, valid_languages = {"C", "C++", "Swift"}, valid_tools = { cc = { "gcc" }, swift = { "swift" }, }, onsolution = function(sln) io.eol = "\r\n" io.indent = "\t" io.escaper(p.ninja.esc) p.generate(sln, "Makefile", p.ninja.generate_solution) io.indent = " " p.ninja.generate_ninja_builds(sln) end, onproject = function(prj) io.eol = "\r\n" io.indent = " " io.escaper(p.ninja.esc) p.ninja.generate_project(prj) end, oncleansolution = function(sln) for _,name in ipairs(sln.configurations) do premake.clean.file(sln, p.ninja.get_solution_name(sln, name)) end end, oncleanproject = function(prj) end, oncleantarget = function(prj) end, } local ninja = premake.ninja function ninja.esc(value) if value then value = string.gsub(value, "%$", "$$") -- TODO maybe there is better way value = string.gsub(value, ":", "$:") value = string.gsub(value, "\n", "$\n") value = string.gsub(value, " ", "$ ") end return value end function ninja.shesc(value) if type(value) == "table" then local result = {} local n = #value for i = 1, n do table.insert(result, ninja.shesc(value[i])) end return result end if value:find(" ") then return "\"" .. value .. "\"" end return value end function ninja.list(value) if #value > 0 then return " " .. table.concat(value, " ") else return "" end end function ninja.arglist(arg, value) if #value > 0 then local args = {} for _, val in ipairs(value) do table.insert(args, string.format("%s %s", arg, val)) end return table.concat(args, " ") else return "" end end function ninja.generate_project(prj) if prj.language == "Swift" then ninja.generate_swift(prj) else ninja.generate_cpp(prj) end end local function innerget(self, key) return rawget(getmetatable(self), key) or self.__inner[key] end local prj_proxy = { __index = innerget } local cfg_proxy = { __index = innerget } function new_prj_proxy(prj) prj = prj.project or prj local v = { __inner = prj } local __configs = {} for key, cfg in pairs(prj.__configs) do if key ~= "" then __configs[key] = ninja.get_proxy("cfg", cfg) else __configs[key] = cfg end end v.__configs = __configs return setmetatable(v, prj_proxy) end local function rebasekeys(t, keys, old, new) for _,key in ipairs(keys) do t[key] = path.rebase(t[key], old, new) end return t end local function rebasearray(t, old, new) local res = { } for _,f in ipairs(t) do table.insert(res, path.rebase(f, old, new)) end return res end function new_cfg_proxy(cfg) local keys = { "directory", "fullpath", "bundlepath" } local old = cfg.location local new = path.join(cfg.location, cfg.shortname) local v = { __inner = cfg, location = new, objectsdir = path.rebase(cfg.objectsdir, old, new), buildtarget = rebasekeys(table.deepcopy(cfg.buildtarget), keys, old, new), linktarget = rebasekeys(table.deepcopy(cfg.linktarget), keys, old, new), } v.files = rebasearray(cfg.files, old, new) v.includedirs = rebasearray(cfg.includedirs, old, new) v.libdirs = rebasearray(cfg.libdirs, old, new) v.userincludedirs = rebasearray(cfg.userincludedirs, old, new) v.systemincludedirs = rebasearray(cfg.systemincludedirs, old, new) v.swiftmodulemaps = rebasearray(cfg.swiftmodulemaps, old, new) return setmetatable(v, cfg_proxy) end function cfg_proxy:getprojectfilename(fullpath) local name = self.project.name .. ".ninja" if fullpath ~= nil then return path.join(self.location, name) end return name end function cfg_proxy:getoutputfilename() return path.join(self.buildtarget.directory, self.buildtarget.name) end local proxy_cache = { prj = { new = new_prj_proxy }, cfg = { new = new_cfg_proxy }, } function get_proxy(cache, obj) if not cache[obj] then cache[obj] = cache.new(obj) end return cache[obj] end function ninja.get_proxy(typ, obj) if not proxy_cache[typ] then error("invalid proxy type") end return get_proxy(proxy_cache[typ], obj) end local ninja = premake.ninja local p = premake local solution = p.solution function ninja.generate_solution(sln) local cc = premake[_OPTIONS.cc] local platforms = premake.filterplatforms(sln, cc.platforms, "Native") _p('# %s solution makefile autogenerated by GENie', premake.action.current().shortname) _p('# Type "make help" for usage help') _p('') _p('NINJA=ninja') _p('ifndef config') _p(' config=%s', _MAKE.esc(premake.getconfigname(sln.configurations[1], platforms[1], true))) _p('endif') _p('') local projects = table.extract(sln.projects, "name") table.sort(projects) _p('') _p('.PHONY: all clean help $(PROJECTS)') _p('') _p('all:') if (not sln.messageskip) or (not table.contains(sln.messageskip, "SkipBuildingMessage")) then _p(1, '@echo "==== Building all ($(config)) ===="') end _p(1, '@${NINJA} -C ${config} all') _p('') for _, prj in ipairs(sln.projects) do local prjx = ninja.get_proxy("prj", prj) _p('%s:', _MAKE.esc(prj.name)) if (not sln.messageskip) or (not table.contains(sln.messageskip, "SkipBuildingMessage")) then _p(1, '@echo "==== Building %s ($(config)) ===="', prj.name) end _p(1, '@${NINJA} -C ${config} %s', prj.name) _p('') end _p('clean:') _p(1, '@${NINJA} -C ${config} -t clean') _p('') _p('help:') _p(1,'@echo "Usage: make [config=name] [target]"') _p(1,'@echo ""') _p(1,'@echo "CONFIGURATIONS:"') local cfgpairs = { } for _, platform in ipairs(platforms) do for _, cfgname in ipairs(sln.configurations) do _p(1,'@echo " %s"', premake.getconfigname(cfgname, platform, true)) end end _p(1,'@echo ""') _p(1,'@echo "TARGETS:"') _p(1,'@echo " all (default)"') _p(1,'@echo " clean"') for _, prj in ipairs(sln.projects) do _p(1,'@echo " %s"', prj.name) end _p(1,'@echo ""') _p(1,'@echo "For more information, see https://github.com/bkaradzic/genie"') end local generate local function getconfigs(sln, name, plat) local cfgs = {} for prj in solution.eachproject(sln) do prj = ninja.get_proxy("prj", prj) for cfg in p.eachconfig(prj, plat) do if cfg.name == name then table.insert(cfgs, cfg) end end end return cfgs end function ninja.generate_ninja_builds(sln) local cc = premake[_OPTIONS.cc] sln.getlocation = function(cfg, plat) return path.join(sln.location, premake.getconfigname(cfg, plat, true)) end local platforms = premake.filterplatforms(sln, cc.platforms, "Native") for _,plat in ipairs(platforms) do for _,name in ipairs(sln.configurations) do p.generate(sln, ninja.get_solution_name(sln, name, plat), function(sln) generate(getconfigs(sln, name, plat)) end) end end end function ninja.get_solution_name(sln, cfg, plat) return path.join(sln.getlocation(cfg, plat), "build.ninja") end function generate(prjcfgs) local cfgs = {} local cfg_start = nil local cfg_first = nil local cfg_first_lib = nil _p("# solution build file") _p("# generated with GENie ninja") _p("") _p("# build projects") for _,cfg in ipairs(prjcfgs) do local key = cfg.project.name if not cfgs[key] then cfgs[key] = "" end cfgs[key] = cfg:getoutputfilename() .. " " if not cfgs["all"] then cfgs["all"] = "" end cfgs["all"] = cfgs["all"] .. cfg:getoutputfilename() .. " " if (cfg_start == nil) and (cfg.solution.startproject == key) then cfg_start = key end if (cfg_first == nil) and (cfg.kind == "ConsoleApp" or cfg.kind == "WindowedApp") then cfg_first = key end if (cfg_first_lib == nil) and (cfg.kind == "StaticLib" or cfg.kind == "SharedLib") then cfg_first_lib = key end _p("subninja " .. cfg:getprojectfilename()) end _p("") _p("# targets") for cfg, outputs in iter.sortByKeys(cfgs) do _p("build " .. cfg .. ": phony " .. outputs) end _p("") _p("# default target") _p("default " .. (cfg_start or cfg_first or cfg_first_lib)) _p("") end premake.ninja.cpp = { } local ninja = premake.ninja local cpp = premake.ninja.cpp local p = premake local function wrap_ninja_cmd(c) if os.is("windows") then return 'cmd /c "' .. c .. '"' else return c end end function ninja.generate_cpp(prj) local pxy = ninja.get_proxy("prj", prj) local tool = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, tool.platforms, "Native") for _, platform in ipairs(platforms) do for cfg in p.eachconfig(pxy, platform) do p.generate(cfg, cfg:getprojectfilename(), function() cpp.generate_config(prj, cfg) end) end end end function cpp.generate_config(prj, cfg) local tool = premake.gettool(prj) _p('# Ninja build project file autogenerated by GENie') _p('# https://github.com/bkaradzic/GENie') _p("") _p("ninja_required_version = 1.7") _p("") local flags = { defines = ninja.list(tool.getdefines(cfg.defines)), includes = ninja.list(table.join(tool.getincludedirs(cfg.includedirs), tool.getquoteincludedirs(cfg.userincludedirs), tool.getsystemincludedirs(cfg.systemincludedirs))), cppflags = ninja.list(tool.getcppflags(cfg)), asmflags = ninja.list(table.join(tool.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_asm)), cflags = ninja.list(table.join(tool.getcflags(cfg), cfg.buildoptions, cfg.buildoptions_c)), cxxflags = ninja.list(table.join(tool.getcflags(cfg), tool.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_cpp)), objcflags = ninja.list(table.join(tool.getcflags(cfg), tool.getcxxflags(cfg), cfg.buildoptions, cfg.buildoptions_objc)), } _p("") _p("# core rules for " .. cfg.name) _p("rule cc") _p(" command = " .. wrap_ninja_cmd(tool.cc .. " $defines $includes $flags -MMD -MF $out.d -c -o $out $in")) _p(" description = cc $out") _p(" depfile = $out.d") _p(" deps = gcc") _p("") _p("rule cxx") _p(" command = " .. wrap_ninja_cmd(tool.cxx .. " $defines $includes $flags -MMD -MF $out.d -c -o $out $in")) _p(" description = cxx $out") _p(" depfile = $out.d") _p(" deps = gcc") _p("") if cfg.flags.UseObjectResponseFile then _p("rule ar") _p(" command = " .. wrap_ninja_cmd(tool.ar .. " $flags $out @$out.rsp " .. (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or ""))) _p(" description = ar $out") _p(" rspfile = $out.rsp") _p(" rspfile_content = $in $libs") _p("") else _p("rule ar") _p(" command = " .. wrap_ninja_cmd(tool.ar .. " $flags $out $in $libs" .. (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or ""))) _p(" description = ar $out") _p("") end local link = iif(cfg.language == "C", tool.cc, tool.cxx) _p("rule link") local startgroup = '' local endgroup = '' if (cfg.flags.LinkSupportCircularDependencies) then startgroup = '-Wl,--start-group' endgroup = '-Wl,--end-group' end local rspfile_content = "$all_outputfiles $walibs " .. string.format("%s $libs %s", startgroup, endgroup) if cfg.flags.UseLDResponseFile then _p(" command = " .. wrap_ninja_cmd("$pre_link " .. link .. " -o $out @$out.rsp $all_ldflags $post_build")) _p(" description = link $out") _p(" rspfile = $out.rsp") _p(" rspfile_content = %s", rspfile_content) _p("") else _p(" command = " .. wrap_ninja_cmd("$pre_link " .. link .. " -o $out " .. rspfile_content .. " $all_ldflags $post_build")) _p(" description = link $out") _p("") end _p("rule exec") _p(" command = " .. wrap_ninja_cmd("$command")) _p(" description = Run $type commands") _p("") if #cfg.prebuildcommands > 0 then _p("build __prebuildcommands_" .. premake.esc(prj.name) .. ": exec") _p(1, "command = " .. wrap_ninja_cmd("echo Running pre-build commands && " .. table.implode(cfg.prebuildcommands, "", "", " && "))) _p(1, "type = pre-build") _p("") end cfg.pchheader_full = cfg.pchheader for _, incdir in ipairs(cfg.includedirs) do local abspath = path.getabsolute(path.join(cfg.project.location, cfg.shortname, incdir)) local testname = path.join(abspath, cfg.pchheader_full) if os.isfile(testname) then cfg.pchheader_full = path.getrelative(cfg.location, testname) break end end cpp.custombuildtask(prj, cfg) cpp.dependencyRules(prj, cfg) cpp.file_rules(prj, cfg, flags) local objfiles = {} for _, file in ipairs(cfg.files) do if path.issourcefile(file) then table.insert(objfiles, cpp.objectname(cfg, file)) end end _p('') cpp.linker(prj, cfg, objfiles, tool, flags) _p("") end function cpp.custombuildtask(prj, cfg) local cmd_index = 1 local seen_commands = {} local command_by_name = {} local command_files = {} local prebuildsuffix = #cfg.prebuildcommands > 0 and "||__prebuildcommands_" .. premake.esc(prj.name) or "" for _, custombuildtask in ipairs(prj.custombuildtask or {}) do for _, buildtask in ipairs(custombuildtask or {}) do for _, cmd in ipairs(buildtask[4] or {}) do local num = 1 for _, depdata in ipairs(buildtask[3] or {}) do cmd = string.gsub(cmd,"%$%(" .. num .."%)", string.format("%s ", path.getrelative(cfg.location, depdata))) num = num + 1 end cmd = string.gsub(cmd, '%$%(<%)', '$in') cmd = string.gsub(cmd, '%$%(@%)', '$out') local cmd_name -- shortened command name if seen_commands[cmd] == nil then local _, _, name = string.find(cmd, '([.%w]+)%s') name = 'cmd' .. cmd_index .. '_' .. string.gsub(name, '[^%w]', '_') seen_commands[cmd] = { name = name, index = cmd_index, } cmd_index = cmd_index + 1 cmd_name = name else cmd_name = seen_commands[cmd].name end local index = seen_commands[cmd].index if command_files[index] == nil then command_files[index] = {} end local cmd_set = command_files[index] table.insert(cmd_set, { buildtask[1], buildtask[2], buildtask[3], seen_commands[cmd].name, }) command_files[index] = cmd_set command_by_name[cmd_name] = cmd end end end _p("# custom build rules") for command, details in pairs(seen_commands) do _p("rule " .. details.name) _p(1, "command = " .. wrap_ninja_cmd(command)) end for cmd_index, cmdsets in ipairs(command_files) do for _, cmdset in ipairs(cmdsets) do local file_in = path.getrelative(cfg.location, cmdset[1]) local file_out = path.getrelative(cfg.location, cmdset[2]) local deps = '' for i, dep in ipairs(cmdset[3]) do deps = deps .. path.getrelative(cfg.location, dep) .. ' ' end _p("build " .. file_out .. ': ' .. cmdset[4] .. ' ' .. file_in .. ' | ' .. deps .. prebuildsuffix) _p("") end end end function cpp.dependencyRules(prj, cfg) local extra_deps = {} local order_deps = {} local extra_flags = {} for _, dependency in ipairs(prj.dependency or {}) do for _, dep in ipairs(dependency or {}) do local objfilename = cpp.objectname(cfg, path.getrelative(prj.location, dep[1])) local dependency = path.getrelative(cfg.location, dep[2]) if extra_deps[objfilename] == nil then extra_deps[objfilename] = {} end table.insert(extra_deps[objfilename], dependency) end end local pchfilename = cfg.pchheader_full and cpp.pchname(cfg, cfg.pchheader_full) or '' for _, file in ipairs(cfg.files) do local objfilename = file == cfg.pchheader and cpp.pchname(cfg, file) or cpp.objectname(cfg, file) if path.issourcefile(file) or file == cfg.pchheader then if #cfg.prebuildcommands > 0 then if order_deps[objfilename] == nil then order_deps[objfilename] = {} end table.insert(order_deps[objfilename], '__prebuildcommands_' .. premake.esc(prj.name)) end end if path.issourcefile(file) then if cfg.pchheader_full and not cfg.flags.NoPCH then local nopch = table.icontains(prj.nopch, file) if not nopch then local suffix = path.isobjcfile(file) and '_objc' or '' if extra_deps[objfilename] == nil then extra_deps[objfilename] = {} end table.insert(extra_deps[objfilename], pchfilename .. suffix .. ".gch") if extra_flags[objfilename] == nil then extra_flags[objfilename] = {} end table.insert(extra_flags[objfilename], '-include ' .. pchfilename .. suffix) end end end end cfg.extra_deps = extra_deps cfg.order_deps = order_deps cfg.extra_flags = extra_flags end function cpp.objectname(cfg, file) return path.join(cfg.objectsdir, path.trimdots(path.removeext(file)) .. ".o") end function cpp.pchname(cfg, file) return path.join(cfg.objectsdir, path.trimdots(file)) end function cpp.file_rules(prj,cfg, flags) _p("# build files") for _, file in ipairs(cfg.files) do _p("# FILE: " .. file) if cfg.pchheader_full == file then local pchfilename = cpp.pchname(cfg, file) local extra_deps = #cfg.extra_deps and '| ' .. table.concat(cfg.extra_deps[pchfilename] or {}, ' ') or '' local order_deps = #cfg.order_deps and '|| ' .. table.concat(cfg.order_deps[pchfilename] or {}, ' ') or '' local extra_flags = #cfg.extra_flags and ' ' .. table.concat(cfg.extra_flags[pchfilename] or {}, ' ') or '' _p("build " .. pchfilename .. ".gch : cxx " .. file .. extra_deps .. order_deps) _p(1, "flags = " .. flags['cxxflags'] .. extra_flags .. iif(prj.language == "C", "-x c-header", "-x c++-header")) _p(1, "includes = " .. flags.includes) _p(1, "defines = " .. flags.defines) _p("build " .. pchfilename .. "_objc.gch : cxx " .. file .. extra_deps .. order_deps) _p(1, "flags = " .. flags['objcflags'] .. extra_flags .. iif(prj.language == "C", "-x objective-c-header", "-x objective-c++-header")) _p(1, "includes = " .. flags.includes) _p(1, "defines = " .. flags.defines) elseif path.issourcefile(file) then local objfilename = cpp.objectname(cfg, file) local extra_deps = #cfg.extra_deps and '| ' .. table.concat(cfg.extra_deps[objfilename] or {}, ' ') or '' local order_deps = #cfg.order_deps and '|| ' .. table.concat(cfg.order_deps[objfilename] or {}, ' ') or '' local extra_flags = #cfg.extra_flags and ' ' .. table.concat(cfg.extra_flags[objfilename] or {}, ' ') or '' local cflags = "cflags" if path.isobjcfile(file) then _p("build " .. objfilename .. ": cxx " .. file .. extra_deps .. order_deps) cflags = "objcflags" elseif path.isasmfile(file) then _p("build " .. objfilename .. ": cc " .. file .. extra_deps .. order_deps) cflags = "asmflags" elseif path.iscfile(file) and not cfg.options.ForceCPP then _p("build " .. objfilename .. ": cc " .. file .. extra_deps .. order_deps) else _p("build " .. objfilename .. ": cxx " .. file .. extra_deps .. order_deps) cflags = "cxxflags" end _p(1, "flags = " .. flags[cflags] .. extra_flags) _p(1, "includes = " .. flags.includes) _p(1, "defines = " .. flags.defines) elseif path.isresourcefile(file) then end end _p("") end function cpp.linker(prj, cfg, objfiles, tool) local all_ldflags = ninja.list(table.join(tool.getlibdirflags(cfg), tool.getldflags(cfg), cfg.linkoptions)) local prebuildsuffix = #cfg.prebuildcommands > 0 and ("||__prebuildcommands_" .. premake.esc(prj.name)) or "" local libs = {} local walibs = {} local lddeps = {} if #cfg.wholearchive > 0 then for _, linkcfg in ipairs(premake.getlinks(cfg, "siblings", "object")) do local linkpath = path.rebase(linkcfg.linktarget.fullpath, linkcfg.location, cfg.location) table.insert(lddeps, linkpath) if table.icontains(cfg.wholearchive, linkcfg.project.name) then table.insert(walibs, table.concat(tool.wholearchive(linkpath), ' ')) else table.insert(libs, linkpath) end end else lddeps = premake.getlinks(cfg, "siblings", "fullpath") libs = lddeps end lddeps = ninja.list(lddeps) libs = ninja.list(libs) .. " " .. ninja.list(tool.getlinkflags(cfg)) walibs = ninja.list(walibs) local function writevars() _p(1, "all_ldflags = " .. all_ldflags) _p(1, "libs = " .. libs) _p(1, "walibs = " .. walibs) _p(1, "all_outputfiles = " .. table.concat(objfiles, " ")) if #cfg.prelinkcommands > 0 then _p(1, 'pre_link = echo Running pre-link commands && ' .. table.implode(cfg.prelinkcommands, "", "", " && ") .. " && ") end if #cfg.postbuildcommands > 0 then _p(1, 'post_build = && echo Running post-build commands && ' .. table.implode(cfg.postbuildcommands, "", "", " && ")) end end if cfg.kind == "StaticLib" then local ar_flags = ninja.list(tool.getarchiveflags(cfg, cfg, false)) _p("# link static lib") _p("build " .. cfg:getoutputfilename() .. ": ar " .. table.concat(objfiles, " ") .. " | " .. lddeps .. prebuildsuffix) _p(1, "flags = " .. ninja.list(tool.getarchiveflags(cfg, cfg, false))) _p(1, "all_outputfiles = " .. table.concat(objfiles, " ")) elseif cfg.kind == "SharedLib" or cfg.kind == "Bundle" then local output = cfg:getoutputfilename() _p("# link shared lib") _p("build " .. output .. ": link " .. table.concat(objfiles, " ") .. " | " .. lddeps .. prebuildsuffix) writevars() elseif (cfg.kind == "ConsoleApp") or (cfg.kind == "WindowedApp") then _p("# link executable") _p("build " .. cfg:getoutputfilename() .. ": link " .. table.concat(objfiles, " ") .. " | " .. lddeps .. prebuildsuffix) writevars() else p.error("ninja action doesn't support this kind of target " .. cfg.kind) end end local ninja = premake.ninja local swift = {} local p = premake function ninja.generate_swift(prj) local pxy = ninja.get_proxy("prj", prj) local tool = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, tool.platforms, "Native") for _, platform in ipairs(platforms) do for cfg in p.eachconfig(pxy, platform) do p.generate(cfg, cfg:getprojectfilename(), function() swift.generate_config(prj, cfg) end) end end end function swift.generate_config(prj, cfg) local tool = premake.gettool(prj) local flags = { swiftcflags = ninja.list(tool.getswiftcflags(cfg)), swiftlinkflags = ninja.list(tool.getswiftlinkflags(cfg)), } _p("# Swift project build file") _p("# generated with GENie ninja") _p("") _p("ninja_required_version = 1.7") _p("") _p("out_dir = %s", cfg.buildtarget.directory) _p("obj_dir = %s", path.join(cfg.objectsdir, prj.name .. ".build")) _p("target = $out_dir/%s", cfg.buildtarget.name) _p("module_name = %s", prj.name) _p("module_maps = %s", ninja.list(tool.getmodulemaps(cfg))) _p("swiftc_flags = %s", flags.swiftcflags) _p("swiftlink_flags = %s", flags.swiftlinkflags) _p("ar_flags = %s", ninja.list(tool.getarchiveflags(cfg, cfg, false))) _p("ld_flags = %s", ninja.list(tool.getldflags(cfg))) if cfg.flags.Symbols then _p("symbols = $target.dSYM") symbols_command = string.format("&& %s $target -o $symbols", tool.dsymutil) else _p("symbols = ") symbols_command = "" end local sdk = tool.get_sdk_path(cfg) if sdk then _p("toolchain_path = %s", tool.get_toolchain_path(cfg)) _p("sdk_path = %s", sdk) _p("platform_path = %s", tool.get_sdk_platform_path(cfg)) _p("sdk = -sdk $sdk_path") else _p("sdk_path =") _p("sdk =") end _p("") _p("# core rules for %s", cfg.name) _p("rule swiftc") _p(1, "command = %s -frontend -c $in -enable-objc-interop $sdk -I $out_dir $swiftc_flags -module-cache-path $out_dir/ModuleCache -D SWIFT_PACKAGE $module_maps -emit-module-doc-path $out_dir/$module_name.swiftdoc -module-name $module_name -emit-module-path $out_dir/$module_name.swiftmodule -num-threads 8 $obj_files", tool.swift) _p(1, "description = compile $out") _p("") _p("rule swiftlink") _p(1, "command = %s $sdk -L $out_dir -o $out $swiftlink_flags $ld_flags $in %s", tool.swiftc, symbols_command) _p(1, "description = create executable") _p("") _p("rule ar") _p(1, "command = %s cr $ar_flags $out $in %s", tool.ar, (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) _p(1, "description = ar $out") _p("") local objfiles = {} for _, file in ipairs(cfg.files) do if path.isswiftfile(file) then table.insert(objfiles, swift.objectname(cfg, file)) end end swift.file_rules(cfg, objfiles) _p("") swift.linker(prj, cfg, objfiles, tool) end function swift.objectname(cfg, file) return path.join("$obj_dir", path.getname(file)..".o") end function swift.file_rules(cfg, objfiles) _p("build %s: swiftc %s", ninja.list(objfiles), ninja.list(cfg.files)) _p(1, "obj_files = %s", ninja.arglist("-o", objfiles)) end function swift.linker(prj, cfg, objfiles, tool) local lddeps = ninja.list(premake.getlinks(cfg, "siblings", "fullpath")) if cfg.kind == "StaticLib" then _p("build $target: ar %s | %s ", ninja.list(objfiles), lddeps) else local lddeps = ninja.list(premake.getlinks(cfg, "siblings", "fullpath")) _p("build $target: swiftlink %s | %s", ninja.list(objfiles), lddeps) end end local ninja = premake.ninja local swift = { } local p = premake function ninja.generate_swift_incremental(prj) local pxy = ninja.get_proxy("prj", prj) local tool = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, tool.platforms, "Native") for _, platform in ipairs(platforms) do for cfg in p.eachconfig(pxy, platform) do p.generate(cfg, cfg:getprojectfilename(), function() swift.generate_config(prj, cfg) end) end end end function swift.generate_config(prj, cfg) local tool = premake.gettool(prj) local flags = { swiftcflags = ninja.list(table.join(tool.getswiftcflags(cfg), cfg.buildoptions_swiftc)), } _p("# Swift project build file") _p("# generated with GENie ninja") _p("") _p("ninja_required_version = 1.7") _p("") _p("out_dir = %s", cfg.buildtarget.directory) _p("obj_dir = %s", path.join(cfg.objectsdir, prj.name .. ".build")) _p("module_name = %s", prj.name) _p("module_maps = %s", ninja.list(tool.getmodulemaps(cfg))) _p("swiftc_flags = %s", flags.swiftcflags) _p("swiftlink_flags = %s", flags.swiftlinkflags) _p("ar_flags = %s", ninja.list(tool.getarchiveflags(cfg, cfg, false))) local sdk = tool.get_sdk_path(cfg) if sdk then _p("toolchain_path = %s", tool.get_toolchain_path(cfg)) _p("sdk_path = %s", sdk) _p("platform_path = %s", tool.get_sdk_platform_path(cfg)) _p("sdk = -sdk $sdk_path") _p("ld_baseflags = -force_load $toolchain_path/usr/lib/arc/libarclite_macosx.a -L $out_dir -F $platform_path/Developer/Library/Frameworks -syslibroot $sdk_path -lobjc -lSystem -L $toolchain_path/usr/lib/swift/macosx -rpath $toolchain_path/usr/lib/swift/macosx -macosx_version_min 10.10.0 -no_objc_category_merging") else _p("sdk_path =") _p("sdk =") _p("ld_baseflags =") end _p("") _p("# core rules for %s", cfg.name) _p("rule swiftc") _p(1, "command = %s -frontend -c -primary-file $in $files $target -enable-objc-interop $sdk -I $out_dir -enable-testing -module-cache-path $out_dir/ModuleCache -D SWIFT_PACKAGE $module_maps -emit-module-doc-path $out_doc_name swiftc_flags -module-name $module_name -emit-module-path $out_module_name -emit-dependencies-path $out.d -emit-reference-dependencies-path $obj_dir/$basename.swiftdeps -o $out", tool.swiftc) _p(1, "description = compile $out") _p("") _p("rule swiftm") _p(1, "command = %s -frontend -emit-module $in $parse_as_library swiftc_flags $target -enable-objc-interop $sdk -I $out_dir -F $platform_path/Developer/Library/Frameworks -enable-testing -module-cache-path $out_dir/ModuleCache -D SWIFT_PACKAGE $module_maps -emit-module-doc-path $out_dir/$module_name.swiftdoc -module-name $module_name -o $out", tool.swift) _p(1, "description = generate module") _p("") _p("rule swiftlink") _p(1, "command = %s $target $sdk $swiftlink_flags -L $out_dir -o $out_dir/$module_name -F $platform_path/Developer/Library/Frameworks $in", tool.swiftc) _p(1, "description = linking $target") _p("") _p("rule ar") _p(1, "command = %s cr $ar_flags $out $in $libs %s", tool.ar, (os.is("MacOSX") and " 2>&1 > /dev/null | sed -e '/.o) has no symbols$$/d'" or "")) _p(1, "description = ar $out") _p("") _p("rule link") _p(" command = %s $in $ld_baseflags $all_ldflags $libs -o $out", tool.ld) _p(" description = link $out") _p("") swift.file_rules(cfg, flags) local objfiles = {} local modfiles = {} local docfiles = {} for _, file in ipairs(cfg.files) do if path.issourcefile(file) then table.insert(objfiles, swift.objectname(cfg, file)) table.insert(modfiles, swift.modulename(cfg, file)) table.insert(docfiles, swift.docname(cfg, file)) end end _p("") swift.linker(prj, cfg, {objfiles, modfiles, docfiles}, tool, flags) _p("") end function swift.objectname(cfg, file) return path.join("$obj_dir", path.getname(file)..".o") end function swift.modulename(cfg, file) return path.join("$obj_dir", path.getname(file)..".o.swiftmodule") end function swift.docname(cfg, file) return path.join("$obj_dir", path.getname(file)..".o.swiftdoc") end function swift.file_rules(cfg, flags) _p("# build files") local sfiles = Set(cfg.files) for _, file in ipairs(cfg.files) do if path.issourcefile(file) then if path.isswiftfile(file) then local objn = swift.objectname(cfg, file) local modn = swift.modulename(cfg, file) local docn = swift.docname(cfg, file) _p("build %s | %s %s: swiftc %s", objn, modn, docn, file) _p(1, "out_module_name = %s", modn) _p(1, "out_doc_name = %s", docn) _p(1, "files = ".. ninja.list(sfiles - {file})) build_flags = "swiftcflags" end _p(1, "flags = " .. flags[build_flags]) elseif path.isresourcefile(file) then end end _p("") end function swift.linker(prj, cfg, depfiles, tool) local all_ldflags = ninja.list(table.join(tool.getlibdirflags(cfg), tool.getldflags(cfg), cfg.linkoptions)) local lddeps = ninja.list(premake.getlinks(cfg, "siblings", "fullpath")) local libs = lddeps .. " " .. ninja.list(tool.getlinkflags(cfg)) local function writevars() _p(1, "all_ldflags = " .. all_ldflags) _p(1, "libs = " .. libs) end local objfiles, modfiles, docfiles = table.unpack(depfiles) _p("build $out_dir/$module_name.swiftmodule | $out_dir/$module_name.swiftdoc: swiftm %s | %s", table.concat(modfiles, " "), table.concat(docfiles, " ")) _p("") local output = cfg:getoutputfilename() if cfg.kind == "StaticLib" then local ar_flags = ninja.list(tool.getarchiveflags(cfg, cfg, false)) _p("build %s: ar %s | %s $out_dir/$module_name.swiftmodule $out_dir/$module_name.swiftdoc", output, table.concat(objfiles, " "), lddeps) _p(1, "flags = %s", ninja.list(tool.getarchiveflags(cfg, cfg, false))) elseif cfg.kind == "SharedLib" then _p("build %s : swiftlink %s | %s $out_dir/$module_name.swiftmodule $out_dir/$module_name.swiftdoc", output, table.concat(objfiles, " "), libs) writevars() elseif (cfg.kind == "ConsoleApp") or (cfg.kind == "WindowedApp") then _p("build %s: swiftlink %s | %s $out_dir/$module_name.swiftmodule $out_dir/$module_name.swiftdoc", output, table.concat(objfiles, " "), lddeps) else p.error("ninja action doesn't support this kind of target " .. cfg.kind) end end newaction { trigger = "jcdb", shortname = "compile_commands.json", description = "Generate a compile_commands.json file.", valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Bundle" }, valid_languages = { "C", "C++" }, valid_tools = { cc = { "gcc" } }, onsolution = function(sln) local jsonpath = path.join(sln.location, "compile_commands.json") premake.generate(sln, jsonpath, premake.jcdb.generate) end, } premake.jcdb = {} local premake = premake local jcdb = premake.jcdb local encode_chars = { [0x22] = '\\"', [0x5c] = "\\\\", [0x08] = "\\b", [0x0c] = "\\f", [0x0a] = "\\n", [0x0d] = "\\r", [0x09] = "\\t", } local function encode_string(s) local res = '"' for _, cp in utf8.codes(s) do if encode_chars[cp] then res = res..encode_chars[cp] elseif cp < 32 then res = res..string.format("\\u%04x", cp) else res = res..utf8.char(cp) end end return res..'"' end local function escape_cmdline_arg(s) if s:find("%s") then s = s:gsub("\\", "\\\\") s = s:gsub('"', '\\"') s = '"'..s..'"' end return s end local function list(tbl) return iif(#tbl > 0, " "..table.concat(tbl, " "), "") end local function build_command(cfg, cc, file) local cmdline = "" local function app(s) cmdline = cmdline..s end if path.iscfile(file) or path.isasmfile(file) then app(cc.cc) else app(cc.cxx) end app(list(cc.getcppflags(cfg))) app(list(cc.getdefines(cfg.defines))) app(list(cc.getincludedirs(cfg.includedirs))) app(list(cc.getquoteincludedirs(cfg.userincludedirs))) app(list(cc.getsystemincludedirs(cfg.systemincludedirs))) app(list(cc.getcflags(cfg))) if path.iscppfile(file) then app(list(cc.getcxxflags(cfg))) end if path.isasmfile(file) then app(list(cfg.buildoptions)) app(list(cfg.buildoptions_asm)) elseif path.isobjcfile(file) then local opts = iif(path.iscfile(file), cfg.buildoptions_objc, cfg.buildoptions_objcpp) app(list(cc.getobjcflags(cfg))) app(list(cfg.buildoptions)) app(list(opts)) elseif path.iscfile(file) then app(list(cfg.buildoptions)) app(list(cfg.buildoptions_c)) else app(list(cfg.buildoptions)) app(list(cfg.buildoptions_cpp)) end if cfg.pchheader and not cfg.flags.NoPCH then app(" -include ") app(escape_cmdline_arg(cfg.pchheader)) end for _, i in ipairs(cfg.forcedincludes) do app(" -include ") app(escape_cmdline_arg(i)) end local base = path.trimdots(path.removeext(file))..".o" local output = path.join(cfg.objectsdir, base) app(" -o ") app(escape_cmdline_arg(output)) app(" -c ") app(escape_cmdline_arg(file)) return cmdline end function jcdb.generate_config(prj, cfg, cc) table.sort(cfg.files) local directory = path.getabsolute(prj.location) for _, file in ipairs(cfg.files) do if path.iscppfile(file) or path.isasmfile(file) then _p(' { "directory": %s,', encode_string(directory)) _p(' "command": %s,', encode_string(build_command(cfg, cc, file))) _p(' "file": %s },', encode_string(file)) end end end function jcdb.generate_project(prj) local cc = premake.gettool(prj) local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native") for _, platform in ipairs(platforms) do for cfg in premake.eachconfig(prj, platform) do jcdb.generate_config(prj, cfg, cc) end end end function jcdb.generate(sln) for _, prj in ipairs(sln.projects) do jcdb.generate_project(prj) end io.captured = io.captured:gsub(",%s$", "") io.captured = "["..io.eol..io.captured..io.eol.."]" end _WORKING_DIR = os.getcwd() local function injectplatform(platform) if not platform then return true end platform = premake.checkvalue(platform, premake.fields.platforms.allowed) for sln in premake.solution.each() do local platforms = sln.platforms or { } if #platforms == 0 then table.insert(platforms, "Native") end if not table.contains(platforms, "Native") then return false, sln.name .. " does not target native platform\nNative platform settings are required for the --platform feature." end if not table.contains(platforms, platform) then table.insert(platforms, platform) end sln.platforms = platforms end return true end function _premake_main(scriptpath) if (scriptpath) then local scripts = dofile(scriptpath .. "/_manifest.lua") for _,v in ipairs(scripts) do dofile(scriptpath .. "/" .. v) end end local profiler = newProfiler() if (nil ~= _OPTIONS["debug-profiler"]) then profiler:start() end _PREMAKE_COMMAND = path.getabsolute(_PREMAKE_COMMAND) premake.action.set(_ACTION) math.randomseed(os.time()) if (nil ~= _OPTIONS["file"]) then local fname = _OPTIONS["file"] if (os.isfile(fname)) then dofile(fname) else error("No genie script '" .. fname .. "' found!", 2) end else local dir, name = premake.findDefaultScript(path.getabsolute("./")) if dir ~= nil then local cwd = os.getcwd() os.chdir(dir) dofile(name) os.chdir(cwd) end end if (_OPTIONS["version"] or _OPTIONS["help"] or not _ACTION) then printf("GENie - Project generator tool %s", _GENIE_VERSION_STR) printf("https://github.com/bkaradzic/GENie") if (not _OPTIONS["version"]) then premake.showhelp() end return 1 end action = premake.action.current() if (not action) then error("Error: no such action '" .. _ACTION .. "'", 0) end ok, err = premake.option.validate(_OPTIONS) if (not ok) then error("Error: " .. err, 0) end ok, err = premake.checktools() if (not ok) then error("Error: " .. err, 0) end ok, err = injectplatform(_OPTIONS["platform"]) if (not ok) then error("Error: " .. err, 0) end print("Building configurations...") premake.bake.buildconfigs() ok, err = premake.checkprojects() if (not ok) then error("Error: " .. err, 0) end premake.stats = { } premake.stats.num_generated = 0 premake.stats.num_skipped = 0 printf("Running action '%s'...", action.trigger) premake.action.call(action.trigger) if (nil ~= _OPTIONS["debug-profiler"]) then profiler:stop() local filePath = path.getabsolute("GENie-profile.txt") print("Writing debug-profile report to ''" .. filePath .. "'.") local outfile = io.open(filePath, "w+") profiler:report(outfile, true) outfile:close() end printf("Done. Generated %d/%d projects." , premake.stats.num_generated , premake.stats.num_generated+premake.stats.num_skipped ) return 0 end ;(8@H1,@TThr|4NjJ4Tl0}G8dYz $8L(`qtx,X8lS&0X8v@E\D=HdvXtw(@k`t;YU @ D t  X v ! @!!V!?!V "X"k"""#$# D#|##%#o#y$H$=\$jp$$v$`4%L%l%E%%%(&a&P&M&&&}'@'X'W'' ' (X!D(!p("(#)#,)m$|)%)9%)G%)y%* &@*^&h*&*]'*'*'*A(+(4+)x+ *+*+++u+,,H,_,h,,,@-,-,.-/8-a/T-/-?0-0-2.38.3P.4.4.4.15.X5.5/5/5,/C6h/6/7/G7/R7/7/7/707$0f8D08X09l0290G90909091A: 1:81;L1l;`1;1=1>1> 2>H25?h2I?|2\?2@2-A3AL37B3B3C32C3wC4C4F|4OG4H4I 5EI85kIP5BJ|5jJ5J5J5eK6K(6fLT6L6M65M6M6M6M74NH7Nd7N7N7$O7iO7O8;P08mPL8Pd8Q8 R8R8S@9U9V9X9X0:[l:[:[:\:\:1_8;z_T;e`t;`;`;`;`;`;a<b$<ep<(f<Gg<g<g< h=oh@=h\=i=-j=j=j=Gk(>kX>lt>m>m>}n>no@?pl?bs?s? t?t @buH@v@v@Ww@wA&y8AFyTAylAyAQzA|B*~8BK~TB~pB~BaBBAC0CHCtCBC{C˂C1Cz(DHpApApApBp7FHqfGqHqIqIrJ`0w`hw`wawaw#bx'cPxdcpxcxcxcx2dxdyNe,t@zT&h|IVELZFM E AH#E]S"abl0lMH DH\pNH z E FBHy(}H Q E G E G E FX EZ\uEG gArEG dA4&4HFBD D(A0n(D ABBfBE|)*I$ [EG MA$DD\FDD JABlx?S0gK(^FDD nFB!,4xFJA A(D0X(A AEB@#/Ec(\6`FDA KABj@Et$4EAD dAA$>EDD kDA$xEDG@eAA4fFED H BBE ABBT.`hz04|tFJA A(D0W(A ABB+Ee(aFDA RAB<Ev$6bEAD UAA$@pcEAG0SAA$hEDG@AA(FDA ABIEC$jOGE LAA,FJC G@ AAB40FHE H(G`(D BBBhz-| 8FBA A(A0(A ABBd EAAT8Er0 poFAG0a DBE qAB8 #E]T h | NEG @A tH k @FJ0E =H ,FEA D(E0h (D ABBE A(A ABB4 s,H }JGD ABA<x IBBB D(D0D@0A(A BBB, wBED G0Z FBB$ ;UEDD EAAD hBBB E(D0D8B@8D0A(B BBBX 0<Evp TUH( ZBHD vDBH FBE B(D0D8L8A0A(B BBB( 'FAJAB(, FDJAB8X SFBE F(J(A BBB4 .FED D(A0n(A ABB4 FAD F CDE fFB$ FLD hAB, --H `,D B~FEA G0b DBB t RH n E M E D 6H d E D4 FBA A(D0(A ABB( G-FDG XABH-FJ SH0<UJEAD m DFE AAApk 4aFEA A(K@(A ABB -4FBG D(A0(D ABB4mYFBD ~ BBE ABBPTFBB B(A0A8G L@I@8D0A(B BBB$MH0DY3FJ YH(leFEA TBB( BLD fEB8+BI SHX4H e B Dx9H p0=aFEG0w EBE DEB\jFBB E(A0D8E@w 8D0A(B BBBA U8D0G(B BBB$gH0^<=H0k E D,\FBD G0p DBB$];FG ] BE DEpBH0y$]FAG0KAB${FAG0fDB0"BFBK G0 JBB(P0FQI BB8|FBB D(D0f(A BBB( mFED YBBHMFLI D(D0 (D DBBE A(A ABBP0FBB B(A0A8G L@IA8A0A(B BBB1FjLFDD D0x  MABE X  KCBE D AABHFJE D(E0O (J BBBE D(D DBB<45EoXMEFpC2H i(]FDA AB$SFFD wAE$kFTD DFB01EDA T DJE [FA8RELTEEpMEG!BE|@G;FIB A(D0I@0A(A BBB>MEG0oFKD v LBE XAB$<AFFD eAE(doFKD ODB(QFTD FB@ED uA$EDA fDHH`ET \AZ4< FJA D(D@(A ABB4tqFKB D(D0B(G DBBHEB0kFED l DBE _AD<sEU E OE|H8 FGB B(A0D8Dp8F0A(B BBB$ENC FALHF0BEB B(G0A8GP8D0A(B BBB*$( 8FaPPM'd`]x $8JBBE D(C0r(A BBB(BIA AB`k,0 Dz?XAW dpjFI0XB$0_FBG0L KBB mEB<1]P$TECD JAA|QH0H [H@R\ | T ~Eo E D(b ACGPAAD R BBB B(D0D8D@8A0A(B BBB(h BDD |DB$ =FDD bDB PEG BA  4 FFDGP GBE IAB4< BHD D(G@k(A ABBHt%FBD D(E0d (A ABBE C(D DBB4qrFBD D(D0M(D DBB$oEDD _AA$ ^EDD NAAH(.Ehd:Exk`kBEB E(D0D8G- 8G0A(B BBBE Y8A0A(B BBB(AFDG@,ABDbONG0 BBE _ BBE DBBA,dlIDK KFB(H _&H Y(BED BB(H _$ LFKD nFB0 2H i0H }FAD b DBE AAB| U=BI lE( rFAJFB( xFAD iAB VAE{!wEP(,!unBAD cABX!'H Zp!4!\BGE A(D0~(D BBB!PEJ!.BJ SJ$!&DBDD gLB "B.BJ SJ@"PEE\"y8Er(x"FKD CB"2El"<H s0"=%FHA J CAB0 #.?BDJ T FBE JAB,@#9FBA G0 FBB@p# FBB A(D0G0A(A BBBH#FBB B(A0D8DP8C0A(B BBB8$<FBB A(J(A BBB0<$9FAD D@  FAB0p$EKJ N DME AAA8$fFBB A(J(D BBB$!AE{$8!%=!!8$%J!BEE D(A0(A BBBH`%!iBEE B(A0D8FPB8D0A(B BBB%#IEC%$AG A%$=%% & % $&% 8&$6(L&%EL } AE NAx&%gEG YAH&%FBB E(A0D8Gp8A0A(B BBB&Y)WEAD (')FBA D(G,'*GFBN0L'*#EAA$h'*ZFED D(G@ '*dFDD G0''+IEAH8'T+FBD D(A0(A ABB$ (4,YADD MAA4(e,EDA T(,7AG (p(,TGDJ0zABA,(-FAD G0 GAB(-K8(5.FEI H(K0(A BBB$).sH f0<))/EDA l DAE AAA@p)y/FBB A(A0G0A(A BBB()&0FAA ABH)0DFBH B(D0D8DP8A0A(B BBB,*3]D Q$D*3NEAD AAA$l* 4H S E o E D$*4|EDD lAAH*5eFBB B(A0A8GPE8A0A(B BBB++6+)6~FwD4+6FBB B(A0A8GP8D0A(B BBB,|+6,FAGDB+7 GWA+7ED @+8D Z0+8BDD0i CBE fABH,,8BBB B(A0D8GP8A0A(B BBB0x,:3FEA NP ABB,;!GY,;JED(,Mdh.>9\\.>P@,. ?fBBB D(D0DPK0A(A BBB(p.-@IBDA ~AB.J@.K@F.}@.@<fI8.@BME D(A0(D BBB8,/ABBA D(A0(A ABBh/[FAU(/VFKBAA CAB(/uFBGF AB/FbA`/1G+ 0HG 0MG%40^G%$H0oG7EFH aAAp0~G H0GYBBI B(D0D8GP-8D0A(B BBB40HTBBD C(E0}(A ABB41HCBBD A(D0o(A ABB`@1HsBBB B(A0A8DP 8G0A(B BBBE 8A0A(B BBB41KFBD A(A0(A ABB$1RLoEIA KKE(2L+FAC ]AB@02LFIA } KBE a DBE _DB$t2 MoFAD \AB$2PMAEDH mAA(2iMJBDD |AB\2M7BIB E(G0D8FP 8H0A(B BBBE Y8D0A(B BBBP3^N/H _h3uNAAP nA3N;D0u3N8Eq3N<H s3NGEA3$O4Eb 4m>EIA gFA$0>1mEID0FAX>m0H gp>m0H g>mUEL }F>3n0H g>Kn0H g>cn^EX>n>Ex?nEL |F0?;o>ExL?]otEL \Fl?o\EV?oE?pEAHD?p}FEE E(G0E8E@L8A0A(B BBB(@pmIDE WABH4@qcBBB A(A0G L@I@60A(A BBB$@/rFHD FB8@sFPA A(J(F ABB@tyEs$A%u\FHD AFBP(AYuBBB B(A0A8G L@I@^8D0A(B BBB,|AvFPA G0 ABB8AwIBIH J(A0"(B BBB(A"xFHD lABHBxxBPO A(D0f (J BBBE A(A BBB$`BxWEIA CCADByBEE E(A0G8B@8D0I(B BBB$ByNBIG0hMB4ByhBJE A(D0o(Q IBB00CyxFHG0N ABE IAB0dC4zFHG0x DBE uAB(CznEN J AE IA<C{FMA D(C0(F ABBD|vDK}#Aa4DR}vF gD DTD}$hD}|D}&`D},FEE E(D0D8D` 8K0G(B BBBE Y8A0A(B BBBD!0ElFKD G0K AABFAPH*2FBB B(A0A8G L@LC8F0A(B BBBTHAE{tH)"H7-HPFKDHMBEE E(A0D8E@W8D0A(B BBB,HeFLD A(D0ID,IBIE J(A0A8D@8A0A(B BBBtIO-DIhBEB B(D0A8A@8A0A(B BBBI9D SI@)AJQFE4JIsBED D(D0Y(A ABBPJ'XdJBBG G(B0d (G ABBE _ (D GBBE A(A ABB,JKDD ABAJ_'Kr$IZ$ Kz/ADD cAA4HKrBBB D(GPY(A BBB4KBBA D(GP(A ABB4K(BBA D(E0(A ABB(KBDG zAB(LaBAD MDD4HL4XBBD D(A0D(A ABB8LTBBB A(A0(A BBBHL9BIA A(A0 (D ABBE A(A ABBHMBBB B(A0D8D8A0A(B BBBTM01Ab E HHtMABBB E(A0D8D8A0A(B BBBHMBBB E(A0D8Gp8D0A(B BBB NQ$ ND7BDD ]IBHHNSBBB B(D0D8D8A0A(B BBB(N7BDA lAB@NKBIB I(D0Dp$0A(A BBB(OJBGD yAB@0OOBBE D(D0DP10A(A BBB@tO&HBBB A(D0GP-0A(A BBB@O*BBB A(D0D`0A(A BBB$O]AAG@QAA$$PLAAG@@AALPTAI0HAHlP<;BEE E(I0A8Dp8A0A(B BBBP+A]@P.BBE A(A0Gp0A(A BBBHQ 6FEE J(A0D8J8D0A(B BBBdQA4Q]FEA D(DP(A ABBQ<Q<,Ef$QL;EAD nAAR_5H d$(R|AAE xFA8PRܭFOA F(G`(D ABB(RzCFAD tAB(RFAD AB(RuEFFD _JGS$S3[NwpdCE}$dEID@AA$dLBAG0kII@dFBA A(G L@I@(F ABB e 84e(&FGA D(D@ (A ABB@pesFGB D(A0D@M0F(A BBB@eAQFGB A(D0DP-0D(A BBBeNiEc4fBBD D(G`(A ABB4LfJ^BFE A(A0H(A ABBfp5$fEDG@AAf `fFBE E(D0F8GPt 8A0A(B BBBA b 8J0D(H BBBE t8glFBE E(A0D8IP 8G0A(B BBBE  8G0G(B BBBE a8A0A(B BBB,gFED G@ ABB,g=FED G@ ABB@hFED D@  ABBE   ABBHThFBB E(A0D8DP8A0A(B BBBHhKFBD A(E0b (A ABBA j(G MBBh>]Ni@YNi*00i%jFBA D0W ABBLdi[FBB B(A0D8D8A0A(B BBBilEG [DiD (iP\FDD JAB$j@EDA sAA$^^zY^8_<_h>vD _>_>_=_8R@@^8_z<^G_ H^RF ^G#_<vD)_?Dj?_7=v````>R`c``vYtcvDv`Y`R```LQKQ````````````ObIeSb7cXbc]bbbbcTbbgb]kbRbobdybdbabOab`b*`b_bdbt]n{^bj^Yb:^b ^^b]Djgc1b4b9bDbQltLsseiehe6pe?neke|d}dQceOhThZhahjhrh{hhhhhhhhhhhhhhhhhhhhhhhhhhihiiiii2i i(i1i:iBiJiQii/dc$j+j-jY;jCjIjRjijZj`jVejInjRvjm}j4jjijjw rhrr.^rrv3rr#r9rvruru#svLuuu}jju3S u_#Yv vvvv!v'v-v3v:vAvGvNvTvZv`vgvlvqvzvntvvyudyccvvvTd]u\vyc{HUbud]e]rY}M}:}`:};};}:}<}=}>}=}>}<}8?}?}@~9A ~nB~B~H ~D,~)E O88o & `L l65 ooH6oo3o4`J0@P`pЀ 0@P`pЁ 0@P`pЂ 0@P`pЃ 0@P`pЄ 0@P`pЅ 0@P`pPww!r v3V= wQ~R6#MDnVXP'28;kB"C HJP u7J8<(,> *"'-3J9x:f"2 y$2dqGCC: (Ubuntu 11.2.0-19ubuntu1) 11.2.0.shstrtab.interp.note.gnu.property.note.gnu.build-id.note.ABI-tag.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.plt.got.plt.sec.text.fini.rodata.eh_frame_hdr.eh_frame.init_array.fini_array.data.rel.ro.dynamic.data.bss.comment 880&hh$9 GoQ  PY & & ao33\noH6H6}665Bll  ІІ``OO PPP ((Tp8(8(9)` `J`:`L`<P@ RB0 0B&B