Whenthenamewasoriginallychosen,thereweretwomainlimitations:theremustnotexisteitheraDebianpackageoraSourceforgeprojectofthegivenname.Thisruledouttensofpotentialprojectnames.AtsomepointthenameGluonwasconsidered.Gluonsareelementaryparticlesthatholdprotonsandneutronstogether,muchlikeabuildsystem'sjobistotakepiecesofsourcecodeandacompilerandbindthemtoacompletewhole.
Unfortunatelythisnamewastaken,too.ThentherestofsubatomicparticleswereexaminedandMesonwasfoundtobeavailable.
thread_dep=dependency('threads')Thiswillsetupeverythingonyourbehalf.PeoplecomingfromAutotoolsorCMakewanttodothisbylookingforlibpthread.somanually.Don'tdothat,ithastrickycornercasesespeciallywhencrosscompiling.
$pip3install
$/path/to/meson.py
Insteadofspecifyingfilesexplicitly,peopleseemtowanttodothis:
executable('myprog',sources:'*.cpp')#ThisdoesNOTwork!Mesondoesnotsupportthissyntaxandthereasonforthisissimple.Thiscannotbemadebothreliableandfast.Byreliablewemeanthatiftheuseraddsanewsourcefiletothesubdirectory,Mesonshoulddetectthatandmakeitpartofthebuildautomatically.
OneofthemainrequirementsofMesonisthatitmustbefast.Thismeansthatano-opbuildinatreeof10000sourcefilesmusttakenomorethanafractionofasecond.ThisisonlypossiblebecauseMesonknowstheexactlistoffilestocheck.Ifanytargetisspecifiedasawildcardglob,thisisnolongerpossible.Mesonwouldneedtore-evaluatetheglobeverytimeandcomparethelistoffilesproducedagainstthepreviouslist.Thismeansinspectingtheentiresourcetree(becausetheglobpatterncouldbesrc/\*/\*/\*/\*.cpporsomethinglikethat).Thisisimpossibletodoefficiently.
ThemainbackendofMesonisNinja,whichdoesnotsupportwildcardmatcheseither,andforthesamereasons.
Becauseofthis,allsourcefilesmustbespecifiedexplicitly.
Ifthetradeoffbetweenreliabilityandconvenienceisacceptabletoyou,thenMesongivesyouallthetoolsnecessarytodowildcardglobbing.Youareallowedtorunarbitrarycommandsduringconfiguration.Firstyouneedtowriteascriptthatlocatesthefilestocompile.Here'sasimpleshellscriptthatwritesall.cfilesinthecurrentdirectory,oneperline.
#!/bin/shforiin*.c;doecho$idoneThenyouneedtorunthisscriptinyourMesonfile,converttheoutputintoastringarrayandusetheresultinatarget.
c=run_command('grabber.sh',check:true)sources=c.stdout().strip().split('\n')e=executable('prog',sources)Thescriptcanbeanyexecutable,soitcanbewritteninshell,Python,Lua,Perlorwhateveryouwish.
Theanswerisalmostalwayssubdir.Subprojectexistsforaveryspecificusecase:embeddingexternaldependenciesintoyourbuildprocess.Asanexample,supposewearewritingagameandwishtouseSDL.LetusfurthersupposethatSDLcomeswithaMesonbuilddefinition.Letussupposeevenfurtherthatwedon'twanttouseprebuiltbinariesbutwanttocompileSDLforourselves.
Inthiscaseyouwouldusesubproject.ThewaytodoitwouldbetograbthesourcecodeofSDLandputitinsideyourownsourcetree.Thenyouwoulddosdl=subproject('sdl'),whichwouldcauseMesontobuildSDLaspartofyourbuildandwouldthenallowyoutolinkagainstitordowhateverelseyoumayprefer.
Foreveryotheruseyouwouldusesubdir.Asanexample,ifyouwantedtobuildasharedlibraryinonedirandlinktestsagainstitinanotherdir,youwoulddosomethinglikethis:
TheonlyreasonwhyonewoulduseMakeinsteadofNinjaisworkingonaplatformthatdoesnothaveaNinjaport.EveninthiscaseitisanorderofmagnitudelessworktoportNinjathanitistowriteaMakebackendforMeson.
JustuseNinja,you'llbehappierthatway.Iguaranteeit.
ArelatedquestiontothisisWhyisMeson'sconfigurationlanguagenotTuring-complete
Inadditiontothosereasons,notexposingPythonoranyother"real"programminglanguagemakesitpossibletoportMeson'simplementationtoadifferentlanguage.Thismightbecomenecessaryif,forexample,Pythonturnsouttobeaperformancebottleneck.ThisisanactualproblemthathascausedcomplicationsforGNUAutotoolsandSCons.
Youprobablydidtheequivalenttothis:
executable('foobar',...c_args:'-some_arg-other_arg')Mesonisexplicit.Inthisparticularcaseitwillnotautomaticallysplityourstringsatwhitespaces,insteaditwilltakeitasisandworkextrahardtopassittothecompilerunchanged,includingquotingitproperlyovershellinvocations.Thisismandatorytomakee.g.fileswithspacesinthemworkflawlessly.Topassmultiplecommandlinearguments,youneedtoexplicitlyputtheminanarraylikethis:
executable('foobar',...c_args:['-some_arg','-other_arg'])WhyarechangestodefaultprojectoptionsignoredYouprobablyhadaprojectthatlookedsomethinglikethis:
project('foobar','cpp')Thisdefaultstoc++11onGCCcompilers.Supposeyouwanttousec++14instead,soyouchangethedefinitiontothis:
project('foobar','cpp',default_options:['cpp_std=c++14'])Butwhenyourecompile,itstillusesc++11.Thereasonforthisisthatdefaultoptionsareonlylookedatwhenyouaresettingupabuilddirectoryfortheveryfirsttime.Afterthatthesettingisconsideredtohaveavalueandthusthedefaultvalueisignored.Tochangeanexistingbuilddirtoc++14,eitherreconfigureyourbuilddirwithmesonconfigureordeletethebuilddirandrecreateitfromscratch.
Thereasonwedon'tautomaticallychangetheoptionvaluewhenthedefaultischangedisthatitisimpossibletoknowtodothatreliably.Theactualquestionthatweneedtosolveis"iftheoption'svalueisfooandthedefaultvalueisbar,shouldwechangetheoptionvaluetobaralso".Therearemanychoices:
Inordertosolvethelatterquestionwewouldneedtoremembernotonlythecurrentandoldvalue,butalsoallthetimestheuserhaschangedthevalueandfromwhichvaluetowhichothervalue.Sincepeopledon'tremembertheirownactionsthatfarback,togglingbetweenstatesbasedonlonghistorywouldbeconfusing.
Becauseofthiswedothesimpleandunderstandablething:defaultvaluesareonlydefaultsandwillneveraffectthevalueofanoptiononceset.
Itdoesnot.InorderforMesontodownloadanythingfromthenetwhilebuilding,twoconditionsmustbemet.
Firstofallthereneedstobea.wrapfilewithadownloadURLinthesubprojectsdirectory.Ifonedoesnotexist,Mesonwillnotdownloadanything.
Thesecondrequirementisthatthereneedstobeanexplicitsubprojectinvocationinyourmeson.buildfiles.Eithersubproject('foobar')ordependency('foobar',fallback:['foobar','foo_dep']).Ifthesedeclarationseitherarenotinanybuildfileortheyarenotcalled(duetoe.g.if/else)thennothingisdownloaded.
Ifthisisnotsufficientforyou,startingfromrelease0.40.0Mesonhasaoptioncalledwrap-modewhichcanbeusedtodisablewrapdownloadsaltogetherwith--wrap-mode=nodownload.Youcanalsodisabledependencyfallbacksaltogetherwith--wrap-mode=nofallback,whichalsoimpliesthenodownloadoption.
Ifontheotherhand,youwantMesontoalwaysusethefallbackfordependencies,evenwhenanexternaldependencyexistsandcouldsatisfytheversionrequirements,forexampleinordertomakesureyourprojectbuildswhenfallbacksareused,youcanuse--wrap-mode=forcefallbacksince0.46.0.
Becausebuildsystemsarespecialinwaysnormalapplicationsaren't.
PerhapsthebiggestlimitationisthatbecauseMesonisusedtobuildsoftwareattheverylowestlevelsoftheOS,itispartofthecorebootstrapfornewsystems.WheneversupportforanewCPUarchitectureisadded,Mesonmustrunonthesystembeforesoftwareusingitcanbecompilednatively.Thisrequirementaddstwohardlimitations.
ThefirstoneisthatMesonmusthavetheminimalamountofdependencies,becausetheymustallbebuiltduringthebootstraptogetMesontowork.
ThesecondisthatMesonmustsupportallCPUarchitectures,bothexistingandfutureones.AsanexamplemanynewprogramminglanguageshaveonlyanLLVMbasedcompileravailable.LLVMhaslimitedCPUsupportcomparedto,say,GCC,andthusbootstrappingMesononsuchplatformswouldfirstrequireaddingnewprocessorsupporttoLLVM.Thisisinmostcasesunfeasible.
AfurtherlimitationisthatwewantdevelopersonasmanyplatformsaspossibletosubmittoMesondevelopmentusingthedefaulttoolsprovidedbytheiroperatingsystem.InpracticewhatthismeansisthatWindowsdevelopersshouldbeabletocontributeusingnothingbutVisualStudio.
Atthetimeofwriting(April2018)thereareonlythreelanguagesthatcouldfulfilltheserequirements:
OutofthesewehavechosenPythonbecauseitisthebestfitforourneeds.
Ecosystemdiversityisgood.WeencourageinteresteduserstowritethiscompetingimplementationofMesonthemselves.AsofSeptember2021,thereare3projectsattemptingtodojustthis:
Mesonneedstoknowseveraldetailsabouteachcompilerinordertocompilecodewithit.Theseincludethingssuchaswhichcompilerflagstouseforeachoptionandhowtodetectthecompilerfromitsoutput.Thisinformationcannotbeinputviaaconfigurationfile,insteaditrequireschangestoMeson'ssourcecodethatneedtobesubmittedtoMesonmasterrepository.Intheoryyoucanrunyourownforkedversionwithcustompatches,butthat'snotgooduseofyourtime.Pleasesubmitthecodeupstreamsoeveryonecanusethetoolchain.
Thestepsforaddinganewcompilerforanexistinglanguageareroughlythefollowing.Forsimplicitywe'regoingtoassumeaCcompiler.
ThenamingconventionforstaticlibrariesonWindowsisusuallyfoo.lib.Unfortunately,importlibrariesarealsocalledfoo.lib.
Thiscausesfilenamecollisionswiththedefaultlibrarytypewherewebuildbothsharedandstaticlibraries,andalsocausescollisionsduringinstallationsincealllibrariesareinstalledtothesamedirectorybydefault.
Toresolvethis,wedecidedtodefaulttocreatingstaticlibrariesoftheformlibfoo.awhenbuildingwithMSVC.Thishasthefollowingadvantages:
Autotoolsrequiresyoutoaddprivateandpublicheaderstothesourceslistsothatitknowswhatfilestoincludeinthetarballgeneratedbymakedist.Meson'sdistcommandsimplygatherseverythingcommittedtoyourgit/hgrepositoryandaddsittothetarball,soaddingheaderstothesourceslistispointless.
MesonusesNinjawhichusescompilerdependencyinformationtoautomaticallyfigureoutdependenciesbetweenCsourcesandheaders,soitwillrebuildthingscorrectlywhenaheaderchanges.
If,forwhateverreason,youdoaddnon-generatedheaderstothesourceslistofatarget,Mesonwillsimplyignorethem.
libfoo_gen_headers=custom_target('gen-headers',...,output:'foo-gen.h')libfoo_sources=files('foo-utils.c','foo-lib.c')#Addgeneratedheaderstothelistofsourcesforthebuildtargetlibfoo=library('foo',sources:[libfoo_sources+libfoo_gen_headers])Nowlet'ssayyouhaveanewtargetthatlinkstolibfoo:
libbar_sources=files('bar-lib.c')libbar=library('bar',sources:libbar_sources,link_with:libfoo)Thisaddsalink-timedependencybetweenthetwotargets,butnotethatthesourcesofthetargetshavenocompile-timedependenciesandcanbebuiltinanyorder;whichimprovesparallelismandspeedsupbuilds.
Ifthesourcesinlibbaralsousefoo-gen.h,that'sacompile-timedependency,andyou'llhavetoaddlibfoo_gen_headerstosources:forlibbartoo:
libbar_sources=files('bar-lib.c')libbar=library('bar',sources:libbar_sources+libfoo_gen_headers,link_with:libfoo)Alternatively,ifyouhavemultiplelibrarieswithsourcesthatlinktoalibraryandalsouseitsgeneratedheaders,thiscodeisequivalenttoabove:
#Addgeneratedheaderstothelistofsourcesforthebuildtargetlibfoo=library('foo',sources:libfoo_sources+libfoo_gen_headers)#Declareadependencythatwilladdthegeneratedheaderstosourceslibfoo_dep=declare_dependency(link_with:libfoo,sources:libfoo_gen_headers)...libbar=library('bar',sources:libbar_sources,dependencies:libfoo_dep)Note:Youshouldonlyaddheaderstosources:whiledeclaringadependency.Ifyourcustomtargetoutputsbothsourcesandheaders,youcanusethesubscriptnotationtogetonlytheheader(s):
Withthecpp_ehandcpp_rttioptions.Atypicalinvocationwouldlooklikethis:
meson-Dcpp_eh=none-Dcpp_rtti=false
Thisdependshighlyonwhatyouactuallyneedtohappen.The′buildtype`optionismeantdodescribethecurrentbuild'sintent.Thatis,whatitwillbeusedfor.Individualoptionsarefordeterminingwhattheexactstateis.Thisbecomesclearerwithafewexamples.
Supposeyouhaveasourcefilethatisknowntomiscompilewhenusing-O3andrequiresaworkaround.Thenyou'dwritesomethinglikethis:
ifget_option('optimization')=='3'add_project_arguments('-DOPTIMIZATION_WORKAROUND',...)endifOntheotherhandifyourprojecthasextraloggingandsanitychecksthatyouwouldliketobeenabledduringthedaytodaydevelopmentwork(whichusesthedebugbuildtype),you'ddothisinstead:
ifget_option('buildtype')=='debug'add_project_arguments('-DENABLE_EXTRA_CHECKS',...)endifInthiswaytheextraoptionsareautomaticallyusedduringdevelopmentbutarenotcompiledinreleasebuilds.Notethat(sinceMeson0.57.0)youcansetoptimizationto,say,2inyourdebugbuildsifyouwantto.Ifyoutriedtosetthisflagbasedonoptimizationlevel,itwouldfailinthiscase.
Thisisvalid(andgood)code:
libA=library('libA','fileA.cpp',link_with:[])libB=library('libB','fileB.cpp',link_with:[libA])Butthereiscurrentlynowaytogetsomethinglikethistowork:
Thetl;dranswertothisisthatmeson'sdesignisfocusedonsolvingspecificproblemsratherthanprovidingageneralpurposelanguagetowritecomplexcodesolutionsinbuildfiles.Buildsystemsshouldbequicktowriteandquicktounderstand,functionsmuddlethissimplicity.
Thelongansweristwofold:
First,Mesonaimstoprovidearichsetoftoolsthatsolvespecificproblemssimplyoutofthebox.Thisissimilartothe"batteriesincluded"mentalityofPython.ByprovidingtoolsthatsolvecommonproblemsinthesimplestwaypossibleinMesonwearesolvingthatproblemforeveryoneinsteadofforcingeveryonetosolvethatproblemforthemselvesoverandoveragain,oftenbadly.OneexampleofthisareMeson'sdependencywrappersaroundvariousconfig-toolexecutables(sdl-config,llvm-config,etc).Inotherbuildsystemseachuserofthatdependencywritesawrapperanddealswiththecornercases(ordoesn't,asisoftenthecase),inMesonwehandletheminternally,everyonegetsfixesandthecornercasesareironedoutforeveryone.Providinguserdefinedfunctionsormacrosgoesdirectlyagainstthisdesigngoal.
Second,functionsandmacrosmakesthebuildsystemmoredifficulttoreasonabout.Whenyouencountersomefunctioncall,youcanrefertothereferencemanualtoseethatfunctionanditssignature.Insteadofspendingfrustratinghourstryingtointerpretsomebitofm4orfollowlongincludepathstofigureoutwhatfunction1(whichcallsfunction2,whichcallsfunction3,adinfinitum),youknowwhatthebuildsystemisdoing.Unlessyou'reactivelydevelopingMesonitself,it'sjustatooltoorchestratebuildingthethingyouactuallycareabout.Wewantyoutospendaslittletimeworryingaboutbuildsystemsaspossiblesoyoucanspendmoretimeonyourcode.
Manytimesuserdefinedfunctionsareusedduetoalackofloopsorbecauseloopsaretedioustouseinthelanguage.Mesonhasbotharrays/listsandhashes/dictsnatively.Comparethefollowingpseudocode:
func(name,sources,extra_args)executable(name,sources,c_args:extra_args)endfuncfunc(exe1,['1.c','common.c'],[])func(exe2,['2.c','common.c'],[])func(exe2_a,['2.c','common.c'],['-arg'])foreache:[['1','1.c',[]],['2','2.c',[]],['2','2.c',['-arg']]]executable('exe'+e[0],e[1],c_args:e[2],)endforeachTheloopisbothlesscodeandismucheasiertoreasonaboutthanthefunctionversionis,especiallyifthefunctionweretoliveinaseparatefile,asiscommoninotherpopularbuildsystems.
BuildsystemDSLsalsotendtobebadlythoughtoutasgenericprogramminglanguages,Mesontriestomakeiteasytouseexternalscriptsorprogramsforhandlingcomplexproblems.Whileonecan'talwaysconvertbuildlogicintoascriptinglanguage(orcompiledlanguage),whenitcanbedonethisisoftenabettersolution.Externallanguagestendtobewell-thought-outandtested,generallydon'tregress,andusersaremorelikelytohavedomainknowledgeaboutthem.Theyalsotendtohavebettertooling(suchasautocompletion,linting,testingsolutions),whichmakethemalowermaintenanceburdenovertime.
Givencodelikethis:
add_project_link_arguments(['-Wl,-foo'],language:['c'])executable('main','main.c','helper.cpp',)Onemightbesurprisedtofindthat-Wl,-fooisnotappliedtothelinkageofthemainexecutable.InthisMesonisworkingasexpected,sincemesonwillattempttodeterminethecorrectlinkertouseautomatically.ThisavoidssituationslikeinautotoolswheredummyC++sourceshavetobeaddedtosomecompilationtargetstogetcorrectlinkage.SointheabovecasetheC++linkerisused,insteadoftheClinker,ashelper.cpplikelycannotbelinkedusingtheClinker.
Generallythebestwaytoresolvethisistoaddthecpplanguagetotheadd_project_link_argumentscall.
add_project_link_arguments(['-Wl,-foo'],language:['c','cpp'])executable('main','main.c','helper.cpp',)ToforcetheuseoftheClinkeranywaythelink_languagekeywordargumentcanbeused.NotethatthiscanresultinacompilationfailureiftherearesymbolsthattheClinkercannotresolve.
add_project_link_arguments(['-Wl,-foo'],language:['c'])executable('main','main.c','helper.cpp',link_language:'c',)HowdoIignorethebuilddirectoryinmyVCSYoudon'tneedto,assumingyouusegitormercurial!Meson>=0.57.0willcreatea.gitignoreand.hgignorefileforyou,insideeachbuilddirectory.Itglobignores"*",sinceallgeneratedfilesshouldnotbecheckedintogit.
UsersofolderversionsofMesonmayneedtosetupignorefilesthemselves.
Justadd-DFOOtoc_argsorcpp_args.Thisworksforallknowncompilers.