Make—AProgramforMaintainingComputerPrograms S.I.Feldman ABSTRACT Inaprogrammingproject,itiseasytolosetrackofwhichfilesneedtobe reprocessedorrecompiledafterachangeismadeinsomepartofthesource. Makeprovidesasimplemechanismformaintainingup-to-dateversionsofpro-gramsthatresultfrommanyoperationsonanumberoffiles.Itispossibletotell Makethesequenceofcommandsthatcreatecertainfiles,andthelistoffilesthat requireotherfilestobecurrentbeforetheoperationscanbedone.Whenevera changeismadeinanypartoftheprogram,theMakecommandwillcreatethe properfilessimply,correctly,andwithaminimumamountofeffort. ThebasicoperationofMakeistofindthenameofaneededtargetinthe description,ensurethatallofthefilesonwhichitdependsexistandareupto date,andthencreatethetargetifithasnotbeenmodifiedsinceitsgenerators were.Thedescriptionfilereallydefinesthegraphofdependencies;Makedoesa depth-firstsearchofthisgraphtodeterminewhatworkisreallynecessary. Makealsoprovidesasimplemacrosubstitutionfacilityandtheabilityto encapsulatecommandsinasinglefileforconvenientadministration. August15,1978 Make—AProgramforMaintainingComputerPrograms S.I.Feldman Introduction Itiscommonpracticetodividelargeprogramsintosmaller,moremanageablepieces.The piecesmayrequirequitedifferenttreatments:somemayneedtoberunthroughamacroprocessor,somemayneedtobeprocessedbyasophisticatedprogramgenerator(e.g.,Yacc[1]orLex[2]). Theoutputsofthesegeneratorsmaythenhavetobecompiledwithspecialoptionsandwithcertaindefinitionsanddeclarations.Thecoderesultingfromthesetransformationsmaythenneedto beloadedtogetherwithcertainlibrariesunderthecontrolofspecialoptions.Relatedmaintenanceactivitiesinvolverunningcomplicatedtestscriptsandinstallingvalidatedmodules.Unfortunately,itisveryeasyforaprogrammertoforgetwhichfilesdependonwhichothers,whichfiles havebeenmodifiedrecently,andtheexactsequenceofoperationsneededtomakeorexercisea newversionoftheprogram.Afteralongeditingsession,onemayeasilylosetrackofwhichfiles havebeenchangedandwhichobjectmodulesarestillvalid,sinceachangetoadeclarationcan obsoleteadozenotherfiles.Forgettingtocompilearoutinethathasbeenchangedorthatuses changeddeclarationswillresultinaprogramthatwillnotwork,andabugthatcanbeveryhard totrackdown.Ontheotherhand,recompilingeverythinginsightjusttobesafeisverywasteful. Theprogramdescribedinthisreportmechanizesmanyoftheactivitiesofprogramdevelopmentandmaintenance.Iftheinformationoninter-filedependencesandcommandsequencesis storedinafile,thesimplecommand make isfrequentlysufficienttoupdatetheinterestingfiles,regardlessofthenumberthathavebeen editedsincethelast‘‘make’’.Inmostcases,thedescriptionfileiseasytowriteandchangesinfrequently.Itisusuallyeasiertotypethemakecommandthantoissueevenoneoftheneededoperations,sothetypicalcycleofprogramdevelopmentoperationsbecomes think—edit—make—test... Makeismostusefulformedium-sizedprogrammingprojects;itdoesnotsolvetheproblems ofmaintainingmultiplesourceversionsorofdescribinghugeprograms.Makewasdesignedfor useonUnix,butaversionrunsonGCOS. BasicFeatures Thebasicoperationofmakeistoupdateatargetfilebyensuringthatallofthefileson whichitdependsexistandareuptodate,thencreatingthetargetifithasnotbeenmodified sinceitsdependentswere.Makedoesadepth-firstsearchofthegraphofdependences.Theoper-ationofthecommanddependsontheabilitytofindthedateandtimethatafilewaslastmodi-fied. Toillustrate,letusconsiderasimpleexample:Aprogramnamedprogismadebycompiling andloadingthreeC-languagefilesx.c,y.c,andz.cwiththelSlibrary.Byconvention,theoutput oftheCcompilationswillbefoundinfilesnamedx.o,y.o,andz.o.Assumethatthefilesx.cand y.csharesomedeclarationsinafilenameddefs,butthatz.cdoesnot.Thatis,x.candy.chave theline #include"defs" Thefollowingtextdescribestherelationshipsandoperations:

-2-prog:x.oy.oz.o ccx.oy.oz.o−lS−oprog x.oy.o:defs Ifthisinformationwerestoredinafilenamedmakefile,thecommand make wouldperformtheoperationsneededtorecreateprogafteranychangeshadbeenmadetoanyof thefoursourcefilesx.c,y.c,z.c,ordefs. Makeoperatesusingthreesourcesofinformation:auser-supplieddescriptionfile(asabove), filenamesand‘‘last-modified’’timesfromthefilesystem,andbuilt-inrulestobridgesomeofthe gaps.Inourexample,thefirstlinesaysthatprogdependsonthree‘‘.o’’files.Oncetheseobject filesarecurrent,thesecondlinedescribeshowtoloadthemtocreateprog.Thethirdlinesays thatx.oandy.odependonthefiledefs.Fromthefilesystem,makediscoversthatthereare three‘‘.c’’filescorrespondingtotheneeded‘‘.o’’files,andusesbuilt-ininformationonhowtogen-erateanobjectfromasourcefile(i.e.,issuea‘‘cc−c’’command). Thefollowinglong-windeddescriptionfileisequivalenttotheoneabove,buttakesno advantageofmake’sinnateknowledge: prog:x.oy.oz.o ccx.oy.oz.o−lS−oprog x.o:x.cdefs cc−cx.c y.o:y.cdefs cc−cy.c z.o:z.c cc−cz.c Ifnoneofthesourceorobjectfileshadchangedsincethelasttimeprogwasmade,allofthe fileswouldbecurrent,andthecommand make wouldjustannouncethisfactandstop.If,however,thedefsfilehadbeenedited,x.candy.c (butnotz.c)wouldberecompiled,andthenprogwouldbecreatedfromthenew‘‘.o’’files.If onlythefiley.chadchanged,onlyitwouldberecompiled,butitwouldstillbenecessaryto reloadprog. Ifnotargetnameisgivenonthemakecommandline,thefirsttargetmentionedinthe descriptioniscreated;otherwisethespecifiedtargetsaremade.Thecommand makex.o wouldrecompilex.oifx.cordefshadchanged. Ifthefileexistsafterthecommandsareexecuted,itstimeoflastmodificationisusedinfurtherdecisions;otherwisethecurrenttimeisused.Itisoftenquiteusefultoincluderuleswith mnemonicnamesandcommandsthatdonotactuallyproduceafilewiththatname.These entriescantakeadvantageofmake’sabilitytogeneratefilesandsubstitutemacros.Thus,an entry‘‘save’’mightbeincludedtocopyacertainsetoffiles,oranentry‘‘cleanup’’mightbeused tothrowawayunneededintermediatefiles.Inothercasesonemaymaintainazero-lengthfile purelytokeeptrackofthetimeatwhichcertainactionswereperformed.Thistechniqueisuseful formaintainingremotearchivesandlistings. Makehasasimplemacromechanismforsubstitutingindependencylinesandcommand strings.Macrosaredefinedbycommandargumentsordescriptionfilelineswithembeddedequal signs.Amacroisinvokedbyprecedingthenamebyadollarsign;macronameslongerthanone charactermustbeparenthesized.Thenameofthemacroiseitherthesinglecharacterafterthe -3-dollarsignoranameinsideparentheses.Thefollowingarevalidmacroinvocations: $(CFLAGS) $2 $(xy) $Z $(Z) Thelasttwoinvocationsareidentical.$$isadollarsign.Allofthesemacrosareassignedvalues duringinput,asshownbelow.Fourspecialmacroschangevaluesduringtheexecutionofthe command:$∗,$@,$?,and$<.Theywillbediscussedlater.Thefollowingfragmentshowsthe use: OBJECTS=x.oy.oz.o LIBES=−lS prog:$(OBJECTS) cc$(OBJECTS)$(LIBES)−oprog ... Thecommand make loadsthethreeobjectfileswiththelSlibrary.Thecommand make"LIBES=−ll−lS" loadsthemwithboththeLex(‘‘−ll’’)andtheStandard(‘‘−lS’’)libraries,sincemacrodefinitions onthecommandlineoverridedefinitionsinthedescription.(Itisnecessarytoquotearguments withembeddedblanksinUNIX◯rcommands.) Thefollowingsectionsdetailtheformofdescriptionfilesandthecommandline,anddiscuss optionsandbuilt-inrulesinmoredetail. DescriptionFilesandSubstitutions Adescriptionfilecontainsthreetypesofinformation:macrodefinitions,dependencyinformation,andexecutablecommands.Thereisalsoacommentconvention:allcharactersaftera sharp(#)areignored,asisthesharpitself.Blanklinesandlinesbeginningwithasharpare totallyignored.Ifanon-commentlineistoolong,itcanbecontinuedusingabackslash.Ifthe lastcharacterofalineisabackslash,thebackslash,newline,andfollowingblanksandtabsare replacedbyasingleblank. Amacrodefinitionisalinecontaininganequalsignnotprecededbyacolonoratab.The name(stringoflettersanddigits)totheleftoftheequalsign(trailingblanksandtabsare stripped)isassignedthestringofcharactersfollowingtheequalsign(leadingblanksandtabsare stripped.)Thefollowingarevalidmacrodefinitions: 2=xyz abc=−ll−ly−lS LIBES= ThelastdefinitionassignsLIBESthenullstring.Amacrothatisneverexplicitlydefinedhasthe nullstringasvalue.Macrodefinitionsmayalsoappearonthemakecommandline(seebelow). Otherlinesgiveinformationabouttargetfiles.Thegeneralformofanentryis: target1[target2...]:[:][dependent1...][;commands][#...] [(tab)commands][#...] ... Itemsinsidebracketsmaybeomitted.Targetsanddependentsarestringsofletters,digits,periods,andslashes.(Shellmetacharacters‘‘∗’’and‘‘?’’areexpanded.)Acommandisanystringof -4-charactersnotincludingasharp(exceptinquotes)ornewline.Commandsmayappeareither afterasemicolononadependencylineoronlinesbeginningwithatabimmediatelyfollowinga dependencyline. Adependencylinemayhaveeitherasingleoradoublecolon.Atargetnamemayappear onmorethanonedependencyline,butallofthoselinesmustbeofthesame(singleordouble colon)type. 1.Fortheusualsingle-coloncase,atmostoneofthesedependencylinesmayhaveacommand sequenceassociatedwithit.Ifthetargetisoutofdatewithanyofthedependentsonany ofthelines,andacommandsequenceisspecified(evenanullonefollowingasemicolonor tab),itisexecuted;otherwiseadefaultcreationrulemaybeinvoked. 2.Inthedouble-coloncase,acommandsequencemaybeassociatedwitheachdependencyline; ifthetargetisoutofdatewithanyofthefilesonaparticularline,theassociatedcommandsareexecuted.Abuilt-inrulemayalsobeexecuted.Thisdetailedformisofparticu-larvalueinupdatingarchive-typefiles. Ifatargetmustbecreated,thesequenceofcommandsisexecuted.Normally,eachcommandlineisprintedandthenpassedtoaseparateinvocationoftheShellaftersubstitutingfor macros.(Theprintingissuppressedinsilentmodeorifthecommandlinebeginswithan@sign). Makenormallystopsifanycommandsignalsanerrorbyreturninganon-zeroerrorcode.(Errors areignoredifthe‘‘−i’’flagshasbeenspecifiedonthemakecommandline,ifthefaketargetname ‘‘.IGNORE’’appearsinthedescriptionfile,orifthecommandstringinthedescriptionfilebegins withahyphen.SomeUNIXcommandsreturnmeaninglessstatus).Becauseeachcommandlineis passedtoaseparateinvocationoftheShell,caremustbetakenwithcertaincommands(e.g.,cd andShellcontrolcommands)thathavemeaningonlywithinasingleShellprocess;theresultsare forgottenbeforethenextlineisexecuted. Beforeissuinganycommand,certainmacrosareset.$@issettothenameofthefiletobe ‘‘made’’.$?issettothestringofnamesthatwerefoundtobeyoungerthanthetarget.Ifthe commandwasgeneratedbyanimplicitrule(seebelow),$<isthenameoftherelatedfilethat causedtheaction,and$∗istheprefixsharedbythecurrentandthedependentfilenames. Ifafilemustbemadebuttherearenoexplicitcommandsorrelevantbuilt-inrules,the commandsassociatedwiththename‘‘.DEFAULT’’areused.Ifthereisnosuchname,make printsamessageandstops. CommandUsage Themakecommandtakesfourkindsofarguments:macrodefinitions,flags,descriptionfile names,andtargetfilenames. make[flags][macrodefinitions][targets] Thefollowingsummaryoftheoperationofthecommandexplainshowtheseargumentsareinterpreted. First,allmacrodefinitionarguments(argumentswithembeddedequalsigns)areanalyzed andtheassignmentsmade.Command-linemacrosoverridecorrespondingdefinitionsfoundinthe descriptionfiles. Next,theflagargumentsareexamined.Thepermissibleflagsare −iIgnoreerrorcodesreturnedbyinvokedcommands.Thismodeisenteredifthefaketarget name‘‘.IGNORE’’appearsinthedescriptionfile. −sSilentmode.Donotprintcommandlinesbeforeexecuting.Thismodeisalsoenteredifthe faketargetname‘‘.SILENT’’appearsinthedescriptionfile. −rDonotusethebuilt-inrules. −nNoexecutemode.Printcommands,butdonotexecutethem.Evenlinesbeginningwithan ‘‘@’’signareprinted.

-5- −tTouchthetargetfiles(causingthemtobeuptodate)ratherthanissuetheusualcommands. −qQuestion.Themakecommandreturnsazeroornon-zerostatuscodedependingonwhether thetargetfileisorisnotuptodate. −pPrintoutthecompletesetofmacrodefinitionsandtargetdescriptions −dDebugmode.Printoutdetailedinformationonfilesandtimesexamined. −fDescriptionfilename.Thenextargumentisassumedtobethenameofadescriptionfile. Afilenameof‘‘−’’denotesthestandardinput.Ifthereareno‘‘−f’’arguments,thefile namedmakefileorMakefileinthecurrentdirectoryisread.Thecontentsofthedescription filesoverridethebuilt-inrulesiftheyarepresent). Finally,theremainingargumentsareassumedtobethenamesoftargetstobemade;they aredoneinlefttorightorder.Iftherearenosucharguments,thefirstnameinthedescription filesthatdoesnotbeginwithaperiodis‘‘made’’. ImplicitRules Themakeprogramusesatableofinterestingsuffixesandasetoftransformationrulesto supplydefaultdependencyinformationandimpliedcommands.(TheAppendixdescribesthese tablesandmeansofoverridingthem.)Thedefaultsuffixlistis: .oObjectfile .cCsourcefile .eEflsourcefile .rRatforsourcefile .fFortransourcefile .sAssemblersourcefile .yYacc-Csourcegrammar .yrYacc-Ratforsourcegrammar .yeYacc-Eflsourcegrammar .lLexsourcegrammar Thefollowingdiagramsummarizesthedefaulttransformationpaths.Iftherearetwopathsconnectingapairofsuffixes,thelongeroneisusedonlyiftheintermediatefileexistsorisnamedin thedescription. .o .c.r.e.f.s.y.yr.ye.l.d .y.l.yr.ye Ifthefilex.owereneededandtherewereanx.cinthedescriptionordirectory,itwouldbe compiled.Iftherewerealsoanx.l,thatgrammarwouldberunthroughLexbeforecompilingthe result.However,iftherewerenox.cbuttherewereanx.l,makewoulddiscardtheintermediate C-languagefileandusethedirectlinkinthegraphabove. Itispossibletochangethenamesofsomeofthecompilersusedinthedefault,ortheflag argumentswithwhichtheyareinvokedbyknowingthemacronamesused.Thecompilernames arethemacrosAS,CC,RC,EC,YACC,YACCR,YACCE,andLEX.Thecommand makeCC=newcc willcausethe‘‘newcc’’commandtobeusedinsteadoftheusualCcompiler.Themacros -6-CFLAGS,RFLAGS,EFLAGS,YFLAGS,andLFLAGSmaybesettocausethesecommandsto beissuedwithoptionalflags.Thus, make"CFLAGS=−O" causestheoptimizingCcompilertobeused. Example Asanexampleoftheuseofmake,wewillpresentthedescriptionfileusedtomaintainthe makecommanditself.ThecodeformakeisspreadoveranumberofCsourcefilesandaYacc grammar.Thedescriptionfilecontains: #DescriptionfilefortheMakecommand P=und−3|opr−r2#sendtoGCOStobeprinted FILES=Makefileversion.cdefsmain.cdoname.cmisc.cfiles.cdosys.cgram.ylex.cgcos.c OBJECTS=version.omain.odoname.omisc.ofiles.odosys.ogram.o LIBES=−lS LINT=lint−p CFLAGS=−O make:$(OBJECTS) cc$(CFLAGS)$(OBJECTS)$(LIBES)−omake sizemake $(OBJECTS):defs gram.o:lex.c cleanup: -rm*.ogram.c -du install: @sizemake/usr/bin/make cpmake/usr/bin/make;rmmake print:$(FILES)#printrecentlychangedfiles pr$?|$P touchprint test: make−dp|grep−vTIME>1zap /usr/bin/make−dp|grep−vTIME>2zap diff1zap2zap rm1zap2zap lint:dosys.cdoname.cfiles.cmain.cmisc.cversion.cgram.c $(LINT)dosys.cdoname.cfiles.cmain.cmisc.cversion.cgram.c rmgram.c arch: aruv/sys/source/s2/make.a$(FILES) Makeusuallyprintsouteachcommandbeforeissuingit.Thefollowingoutputresultsfromtypingthesimplecommand make inadirectorycontainingonlythesourceanddescriptionfile:

-7-cc−cversion.c cc−cmain.c cc−cdoname.c cc−cmisc.c cc−cfiles.c cc−cdosys.c yaccgram.y mvy.tab.cgram.c cc−cgram.c ccversion.omain.odoname.omisc.ofiles.odosys.ogram.o−lS−omake 13188+3348+3044=19580b=046174b Althoughnoneofthesourcefilesorgrammarswerementionedbynameinthedescriptionfile, makefoundthemusingitssuffixrulesandissuedtheneededcommands.Thestringofdigits resultsfromthe‘‘sizemake’’command;theprintingofthecommandlineitselfwassuppressedby an@sign.The@signonthesizecommandinthedescriptionfilesuppressedtheprintingofthe command,soonlythesizesarewritten. Thelastfewentriesinthedescriptionfileareusefulmaintenancesequences.The‘‘print’’ entryprintsonlythefilesthathavebeenchangedsincethelast‘‘makeprint’’command.Azerolengthfileprintismaintainedtokeeptrackofthetimeoftheprinting;the$?macrointhecommandlinethenpicksuponlythenamesofthefileschangedsinceprintwastouched.Theprinted outputcanbesenttoadifferentprinterortoafilebychangingthedefinitionofthePmacro: makeprint"P=opr−sp" or makeprint"P=cat>zap" SuggestionsandWarnings Themostcommondifficultiesarisefrommake’sspecificmeaningofdependency.Iffilex.c hasa‘‘#include"defs"’’line,thentheobjectfilex.odependsondefs;thesourcefilex.cdoesnot. (Ifdefsischanged,itisnotnecessarytodoanythingtothefilex.c,whileitisnecessarytorecreatex.o.) Todiscoverwhatmakewoulddo,the‘‘−n’’optionisveryuseful.Thecommand make−n ordersmaketoprintoutthecommandsitwouldissuewithoutactuallytakingthetimetoexecute them.Ifachangetoafileisabsolutelycertaintobebenign(e.g.,addinganewdefinitiontoan includefile),the‘‘−t’’(touch)optioncansavealotoftime:insteadofissuingalargenumberof superfluousrecompilations,makeupdatesthemodificationtimesontheaffectedfile.Thus,the command make−ts (‘‘touchsilently’’)causestherelevantfilestoappearuptodate.Obviouscareisnecessary,since thismodeofoperationsubvertstheintentionofmakeanddestroysallmemoryoftheprevious relationships. Thedebuggingflag(‘‘−d’’)causesmaketoprintoutaverydetaileddescriptionofwhatitis doing,includingthefiletimes.Theoutputisverbose,andrecommendedonlyasalastresort. Acknowledgments IwouldliketothankS.C.Johnsonforsuggestingthisapproachtoprogrammaintenance control.IwouldliketothankS.C.JohnsonandH.Gajewskaforbeingtheprimeguineapigs duringdevelopmentofmake.

-8-References 1.S.C.Johnson,‘‘Yacc—YetAnotherCompiler-Compiler’’,BellLaboratoriesComputingSci-enceTechnicalReport#32,July1978. 2.M.E.Lesk,‘‘Lex—ALexicalAnalyzerGenerator’’,ComputingScienceTechnicalReport #39,October1975.

-9-Appendix.SuffixesandTransformationRules Themakeprogramitselfdoesnotknowwhatfilenamesuffixesareinterestingorhowto transformafilewithonesuffixintoafilewithanothersuffix.Thisinformationisstoredinan internaltablethathastheformofadescriptionfile.Ifthe‘‘−r’’flagisused,thistableisnot used. Thelistofsuffixesisactuallythedependencylistforthename‘‘.SUFFIXES’’;makelooks forafilewithanyofthesuffixesonthelist.Ifsuchafileexists,andifthereisatransformation ruleforthatcombination,makeactsasdescribedearlier.Thetransformationrulenamesarethe concatenationofthetwosuffixes.Thenameoftheruletotransforma‘‘.r’’filetoa‘‘.o’’fileis thus‘‘.r.o’’.Iftheruleispresentandnoexplicitcommandsequencehasbeengivenintheuser’s descriptionfiles,thecommandsequencefortherule‘‘.r.o’’isused.Ifacommandisgeneratedby usingoneofthesesuffixingrules,themacro$∗isgiventhevalueofthestem(everythingbutthe suffix)ofthenameofthefiletobemade,andthemacro$<isthenameofthedependentthat causedtheaction. Theorderofthesuffixlistissignificant,sinceitisscannedfromlefttoright,andthefirst namethatisformedthathasbothafileandaruleassociatedwithitisused.Ifnewnamesareto beappended,theusercanjustaddanentryfor‘‘.SUFFIXES’’inhisowndescriptionfile;the dependentswillbeaddedtotheusuallist.A‘‘.SUFFIXES’’linewithoutanydependentsdeletes thecurrentlist.(Itisnecessarytoclearthecurrentlistiftheorderofnamesistobechanged). Thefollowingisanexcerptfromthedefaultrulesfile: .SUFFIXES:.o.c.e.r.f.y.yr.ye.l.s YACC=yacc YACCR=yacc−r YACCE=yacc−e YFLAGS= LEX=lex LFLAGS= CC=cc AS=as− CFLAGS= RC=ec RFLAGS= EC=ec EFLAGS= FFLAGS= .c.o: $(CC)$(CFLAGS)−c$< .e.o.r.o.f.o: $(EC)$(RFLAGS)$(EFLAGS)$(FFLAGS)−c$< .s.o: $(AS)−o$@$< .y.o: $(YACC)$(YFLAGS)$< $(CC)$(CFLAGS)−cy.tab.c rmy.tab.c mvy.tab.o$@ .y.c: $(YACC)$(YFLAGS)$< mvy.tab.c$@