makefile basics (beginner - intermediate) anthony explains #357

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome to another video in this one we're going to be talking about make files which is a very basic build system and i'm going to show you some of the tricks for them as well as what phony is this is what reminded me to make this video is someone in my chat asked what phony is in a makefile but anyway let's jump into it okay so make file uh is well the command make specifically we're talking about gnu make there are many varieties of make but we're specifically going to be doing gnu make today it is a way to encode a build system in a simple set of rules and targets and it also implements an execution engine which will run those targets for you and we're going to be making a very simple c program today just to demo this mostly so we can have multiple targets inputs outputs that sort of thing so let's start by making a small c program so we're going to do main.c we're going to have a header file lib.h and it's going to have a this this header file is going to define a function for us called hello world again this is not a very interesting example but uh we're going to have it say hello to me and return nothing next we need to make our lib.h uh a little include guard here even though it doesn't matter for this video and if and we're gonna have void hello world and that's going to take a care star for our name it's going to be our little header file there we also need to define that library lib.c uh we're going to need cst standardio.h and void hello hello world takes our name and very simply we're going to printf hello hello percent s new line and name so that's our that's our very simple set of c code here um and we can see all of that right here so we've got lib.c which has our function lib.h which defines our prototype for the function and then main.c which includes that and to build this all together we essentially need to build two things we need to build lib.c and then main.c and then we need to stitch them together into our output binary and that's where make is going to kind of come into play for us so make uses a make file and conventionally the makefile is capitalized and uses tabs as indentation which is really annoying in my opinion so we're going to turn off my normal space expansion in here and use tabs instead and make conventionally uses whatever the first target is in the file now uh the the typical the conventional first target i've seen is called all and all uh i guess the way you define targets and make is you have a name of the target and then a colon and then whatever it depends on and so in our case we're going to be building this target called main which is going to be our executable and our all target is going to require that we're also going to mark all as phony we'll talk more about what that means in a second but for now we'll just write this special dot phony colon all syntax and we'll we'll ignore it for now i'll explain it in a bit cool so next we need to define our rule for main and in this case main is going to depend on our object files for both of our c files so we're going to compile them from c into dot o and then we're going to stitch all of our o files together so in this case main is going to depend on lib.o and main.o i'll put mains first it doesn't really matter i just for whatever reason want to do that and in order to run this we're going to specify what commands are needed to build this so all didn't require any commands so we were able to just you know just write inputs and outputs and we skipped that but commands are indented after the after the target in this case we're going to use gcc and we're going to pass in both of these objects and write out our main so we're going to do main main.olib.o and i'll show you actually a way to simplify the duplication of this later but we need some a little bit more advanced features of make files to that okay next we're going to talk about our object files so we need to write the rule for those and if we do main.o depends on man.h or not dot h mean dot c and this is going to do gcc dash c main.c.o main.o so this is going to compile this c object or this c file into an object file and we need to do the same thing for lib.o and again this is this some code duplication here i'll show you a way to simplify this uh later when we get into automatic make variables but this is kind of our very basic make file and if we were to run make and we can put the target name so let's say we wanted to make specifically main.o we could do make main.o and you'll see it'll run this particular command here if we run it again make will actually tell us that it is up to date and this is because make looks at all of the targets and if they have a newer m time or equivalent m time to the outputs then it knows that it doesn't have to redo any work here so it allows you to kind of skip some already done work and again if we run make with no arguments it's going to run whatever the first target is in our file in this case it's the all target which depends on main and main depends on main.o and lib.o and so it's going to figure out all those dependencies and then build whatever we need to make our our file here so you can see it it built lib.o it didn't need to build main.o because we already built it up here and then it combined those two into our output executable here which we can now run now usually it's also a good idea to make a clean target and this is also going to be phony again we haven't talked about that yet but we will do that in a second and clean is going to remove all of our uh you know outputs here that that are build targets in that case we're gonna get rid of main we're gonna get rid of our o file so we just do rm star dot o and we'll do dash f so it doesn't error uh and main here and so if we run make clean now uh you'll see that we have deleted the non-source files here um and that's that's kind of the basics of what may file is uh so let's talk about what phony is phony is a way to bypass the normal uh execution model of a make file so normally a makefile is designed to have inputs and outputs and build sort of build targets things that actually exist on the file system now there isn't anything named clean on the file system and we don't produce that as a part of this and so we mark it as phony this allows us to use make files as sort of a command runner and less so as a build system and i'll show you what happens if i leave this out so if i leave out clean there and i do make clean you'll see that it ran this and it still kind of works here but if i were to make a file named clean uh make is gonna say oh clean is up to date yeah that file exists because you know none of it has no target so it doesn't need to do any work and it you know it clearly exists there and by marking it phony make will say oh i i don't use my normal build stuff here so i'm always gonna run whatever command is there so that's that's kind of what phony does there and uh you usually only mark your targets that uh are just command execution so like in this case all all is kind of a special command and that like we don't have any commands to run but we always want to make sure that our builds are built properly and clean is an example like this another example would be like running your tests you kind of always want to run your tests to make sure that they still work uh cool so let's talk about how we can simplify this make fall down because again there's a lot of duplication here and make has a bunch of things that make this a little bit easier and for that we're going to be consulting the automatic variables section of the make documentation and this includes a lot of you know special variables that allow us to simplify these things down so the first one we're going to talk about is dollar sign at and this is a special target which refers to the output of the target so in this case it'll refer to main so we can start by replacing mean with dollar sign at here and we'll do the same for this oops right here this is also our output there so that's the first replacement that we can do here and if you make clean and make again uh you'll see that it it substituted those things in for us so we still got our main executable here the next thing we're going to talk about is dollar less than which will be the name of the very first prerequisite in our in our inputs here so in this main.o case it's going to refer to main.c so we can replace up main.c with dollar less than you can also do that down here now you'll notice a kind of neat thing here both of these have the same command now and we'll actually use that fact later to simplify this further uh make clean oh oh you can also specify multiple targets on uh the command line and it will run both of those at the same time so you can see we're able to clean and this still produces our same output here now the next bit of simplification uh is the you know getting rid of all of these being duplicated here for that there is dollar carat which is uh the name of all prerequisites with spaces in between them so this allows us to reference each of these object files uh directly in here do that with dollar carrot and so now if we were to add more object files here we don't need to change our command at all and if we do this again just to show you that it works see that we have replaced that out so now all of our commands actually don't reference our actual file names or outputs at all which is really cool now does this talk about percent substitution in here it does not okay well there's some other part of the make documentation that talks about percent substitution uh we're going to skip the dot because i know how this works and this is kind of a special wildcard as part of your target so you can use a percent in the name and then that will get substituted in any of the targets as well so if we're trying to build main.o for instance this will get substituted as main and this will get substituted as main so main.o depends on main.c and that lets us delete this other target down here so now we have now our entire set of objects are represented by this generic rule here if we clean all again you can see that it it still successfully builds those two targets for us and that's kind of like a simplified make file here using some variable magical variables as well as some substitutions here now another kind of basic thing about make is uh the dash j argument to make and this seems to make help is it going to tell us dash j yeah jane tells j is the number of jobs and this allows you to build stuff in parallel so we were just doing serial builds here but if we do make dash j8 for instance it will use up to eight processes to complete the work here um now this you know is a very silly simple example so it's hard to show that it's faster when doing that but uh it could execute these two in parallel and because it knows about the dependency tree it knows that it has to wait for these two to complete before this one can start so it does it does you know the tree of dependencies for you but anyway that's kind of a short tutorial of make and some examples with the automatic variables as well as a variable substitution we talked about what phony is and showed you a neat little example anyway hopefully this was useful if there are additional things you would like me to explain leave a comment below or reach out to me on the various platforms but thank you all for watching and i will see you in the next one
Info
Channel: anthonywritescode
Views: 27,791
Rating: undefined out of 5
Keywords:
Id: 20GC9mYoFGs
Channel Id: undefined
Length: 12min 47sec (767 seconds)
Published: Fri Nov 12 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.