Simplified CMake Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Yet another CMake tutorial written by someone who has no idea how to use CMake.

They glob for sources which is bad enough, but then they glob recursively and without setting CONFIGURE_DEPENDS, which is outright incorrect and won't notice additions or removals of files without rerunning CMake (not just the build tool) manually.

The minimum version is 3.10, which is FAR from modern, while 3.16 is available everywhere and 3.20 is around the corner.

Skipped ahead to the "how to use libraries" section. The code doesn't use imported targets. So, again, not modern. Also, findlibrary doesn't have a REQUIRED argument until 3.18, so that code will just outright not work on the advertised version. Edit: worse, the video uses SFML in an unsupported way; the variables they expand were removed in 2018 in favor of imported targets. The example code doesn't even _work on Ubuntu 20.04 LTS.

Skip this.

👍︎︎ 33 👤︎︎ u/AlexReinkingYale 📅︎︎ Feb 07 2021 🗫︎ replies
Captions
hey guys this is going to be a simple tutorial on modern cmake and i might break this up into multiple parts depending on how complex this gets so but i want to keep the first video at least simple and easy to follow so you can follow along and all the information i present here will be available on codevion.github.io which will look like this when i when i upload this and push it and you can click on cmake tutorial and then you can follow along with the video and i'm using a terminal based presentation software called which is quite nice and it actually it's able to render my markdown file as a presentation which is useful for these kinds of videos so let's get started now our starting point is a simple c plus plus file and all it does is prints out hello world to the screen and you can see that it's the only file in this folder and if you were to use g plus a compile it you can do that show some outfit called hello and main.tpp and it compiles to hello binary that you can then just run with hello let's see how we would do this using cmake now so you can see that we have to create a cmake.cmakelist.txt file and then this is a basic um and this is a basic setup to get us started so let's go ahead and do that so create a cmake this.txt file and we will simply just copy and paste this and now to run cmake you must have cmake installed on your system and i was able to install it using sudo pacman that's just cmake on an archbase system you can check the version of cmake that you have by using cmec version and you can see that i have 3.19 installed now let's go through this file a little bit so the first the first line of this is the minimum cmake version required now cmake has now since this video is going to focus on some of the more modern features of cmake we're going to use a pretty high version here and so this makes it so that this program cannot be run with the cmake version lower than this we set up some c plus plus 17 related stuff so that we can use more modern versions of c plus as well and then we give our project a name and we give it a version and then all we're doing is creating a executable called hello which uses the main.cpv file now to run cmake from the command line all you have to do is specify the directory that cmakeslist.txt file is in and then it'll generate a make file for you and the makefile is going to be used to actually build your program now you might ask how this is simpler or better than the g plus version and the answer is as programs get more complicated and we'll see it happen later on in the video cmake will abstract away a lot of the complexity around generating your make files so think of it as a generator for make files and then you can run make to build your files and then you can run them so let's take a look at how that happens so i can use cmake dot to run cmake in the current directory and let's remove our existing binary first so we know this is cmake responsible for building it so i can do cmake dot and this you can see that it generates a bunch of cmake related artifacts and a make file we can simply run make to build it and we can run a little and it works perfectly fine and since we used c plus 17 we can actually use more modern features like std optional all right so now we're able to build a single source file uh and generate our make file and use our make file to build our binary but i don't really like all these cmake files cluttering up my source directory so one thing i usually do is create a build folder and what i do is let's get rid of these all right so now i just have my source file my cmakelist.txt file and a bill directory now i can build from the build directory by calling cmake.slash because i want to build a directory above it and this will do the same c make c make file generation and then we can actually use make here and we can actually just run hello again all right and you can see that our main source directory is now uncluttered all the build artifacts are in the build directory now i won't be going into the terminal and running cmake every time i do use a vim plugin that i mentioned in my coc video here on setting up bim neovim for c plus plus as an ide and include a c make a file you can see the video linked below um and i will be using that and let me show you guys how that works really quickly so if i'm in main.cpp i can just use flash cg to generate my cmake files live cb to build it and then i actually just run it using build slash hello all right that is what i'll be using to build and run my c rank files going forward in this tutorial actually you'll notice that the the cmake bim plugin that i use actually puts everything in the debug folder so it creates a debug folder instead of a build folder so i can just get rid of the the build folder here and the compiling commands dot json is used by clc to give me auto completion and other cool stuff so i can include my stream and all that good stuff and it'll be used later on and it's well integrated with cmake and it'll be used to provide me with an ide like experience if you guys want to check out more about that check out the c plus plus video back to cmake now so we have a source file we have cma.list.txt file and let's say we want to add a header file now so let's take a look at this so in order to include a header file you don't actually explicitly include header files themselves you actually include a directory that contains your header files so we can do target include directories we can link our target in this case which is hello and the purpose of public is to specify the scope of the stuff that you're adding to your target so for include directories you can make it public private or interface and this is more relevant later on when we actually build up a library in cmake because you want to make sure that targets outside of your library should have access to the include directories that are relevant for your library and we say that our header files are going to be in our current source directory slash include and this is a common behavior in cpus programs to put your header files inside special include directory so we'll go ahead and do the same thing here so we'll create an include directory and include let's actually create a header file called blog.h right so let's say fragment once so and this is just good c plus practices and we will create a class here called blah and inside the class we will declare a function called and all it does is mainline this all it does is it does ftd see out or let's just call it blue actually right and it doesn't know what std is so we will include the i stream header all right and we have to end this class with a semicolon cool so this is our simple class and in our main.tpp we will instantiate blah and we'll call here and now i wanted to include the blog.h directories in the blog.h file so i can just do blog image okay so as it is right now um because our cmake does not know how to compile this so right now if we try to compile this actually you'll see that we get an error so in generating cma files this works but in building it'll give us an error because it doesn't really know where blood.h is or how to include this so in order to do this we edit our cmakelist.txt file and like we said we'll just say target include directories and we'll just include the include directory from the current source directory the target starts with your project and you are adding an executable and then you're also adding include directories so once we build it again this time it builds successfully for us and now we can do build actually this actually puts it in the default folder so debug hello and you can see that it also prints out boo in addition to hello world and one cool thing you'll notice is if i open up my main.tv file um this should actually let's reopen it all right yes so you'll notice that cmake is also helps generate the compile.json the compilers or commands are json so i can actually use clc to navigate and get rid of the errors as well now we know how to include files so now any more files that we add in the include directory we can just use them in our program okay but then the next thing is what if we have more source files now the traditional way to add more source files in cma is to add more stuff here so we have main.tpp maybe we have a blog.tpp and then you just keep adding these files and now here's here's where there's a little bit of controversy in terms of what's good practices and what's not good practices now cmake source explicitly discourages this but what we can do is we can do a recursive search for all source dot cpp files in a directory and include them in our executable now why they discourage this is because of cmake is not really supposed to be your build system but it's supposed to be a small part of your build system but for most people who use c plus and who just want to get things done i think this is a perfectly fine way to do things so what we're going to do here is we're going to actually put our source files in a separate source directory and we're just going to do a recursive glob for all cpb files in there and then we're going to add them to our executable so let's see how that works so first off we need to create the source directory so let's do src and inside our source directory what we're going to do is we're going to put the implementation for blog.h for our class law into the source file so let's split from actually include and blog.h and let's do okay i want to include plot.h here and i want to define the implementation for this class in my source file so what i'm going to do is i'm just going to copy this paste it we don't need inline anymore [Music] and here i can get rid of the inline word and now i'm just doing a declaration in the header file and i'm doing a definition in the source file okay and i can actually even move the i o stream here just because um the header file doesn't really need to know about i stream um okay cool so we have a header file and we have source file and but if we try to build it now so by itself if i do slash cg it'll build the cmake we'll build and then if i do slice cb it'll actually fail because it can't find the definition of blood or blah boo because it doesn't really know where the source file is for this header file and so it can't really link the implementation of the the method that we've declared so in order to fix this we have to include tell it where to find the source files for blog.age now one way i can do this is if i can just do src slash blog.cbp and if i generate my c files now this works um all right um and now what we want to do is we want to use a recursive glob now so let's do that let's just copy these actually let's just copy the glob for stuff and what we're going to do is we're going to paste it here and what this does is it globs through recursively all the steep plus files in the source directory and it puts them in this variable uh src underscore files that we can then use in our address or executable so you can just do src underscore files and we'll leave our main.tpp file outside of our source files it's just that's fine we or we could put it in our src folder um it doesn't really matter so if we generate and build and our target is built so we can just run it now tool all right let's talk about creating a custom library now as projects get very large we often have to split it up into libraries and reusable smaller components and library is a perfect way to do that so we can create a library by using add underscore library instead of the add-on score executable we specify the name we specify whether or not we want it to be statically linked or dynamically linked and then we provide the source files similar to ad underscore executable so let's do that for our library and let's actually make a library for our blog class that we were working on so i moved the blog class into the a blog directory where i have blog.tvp and an include folder which has plot of 8. so we can say or create a library blah it will be a static library and the location will be allowed to give you here and for the include directory i am going to say that the include directory for blah is and i wanted to have public scope and i'm going to say you make a current source directory slash slash include and now i don't have to worry about any source files because my hello executable now just has the main file main.cpp and it doesn't even have any include directories so all we have to do is now link this library with our executable so in order to do that you just use target underscore link underscore libraries so let's do that hello public and in our case it'll be just blah cool so let's generate our cmake files and let's build it and this time when we build it which is run the make file you can see that it generates a lib.h and then it generates a binary hello and and if we now run dot slash debug hello this continues to work now note that because we linked our the include directory to the blog target the when we link that library back to the hello executable main is able to understand where blood.h is because it's part of the library that we've linked to our target now one cool thing we can do is we can have law folder have its own cmakelist.txt file so let's create a cmakelist.txt file inside blah and let's compare and all we have to do is we can just take this blah related stuff here we can put it here now the references to the directories um can be relative to the current path and all we have to do is we can just do add underscore subdirectory and this ensures that when we add the subdirectory it'll include the library and we can now use it and we don't have to worry about creating another project or anything like that and let's do that you can see cmake files are built and it continues to work perfectly fine so let's talk about depending on an external library now some external libraries do have some sort of cma configuration in which case you can use a find package which will fill out some certain variables that you can then use to link to your library that you can use to set up include directories so you don't have to worry about those setting those explicitly and that's one of the benefits of finding underscore package in addition to also being able to specify a version requirement um specifying required and even specify sub-components like we can with the sfml which is a media library and has is components for networking audio graphics window systems so we can specify these when we actually find the package and then we can after that we can include it using the sm panel underscore include underscore directory which is a variable that the find underscore package fills out and we can link to the libraries and certain cases like if we want to we will also need the dependencies of the library to be able to link to them in in this video i'm just going to talk about just installing the library in your system but in later videos i will talk about how to create a custom find something cmake file or a custom xx config file for your library so that it can be included a lot easier in cmake and we'll talk about cpm later as well which is a really nice way of hassle-free cmake library dependency management but for now you can install something like i can install with yay on an archbase system sfml or zlib or any other external library that i want and then all i have to do is run find package so let's do that so i do yay and it gets installed and after it's installed i can basically i open up my cmakelist.txt file i can copy this [Music] and i can now link to my i can add the include directories for it in my link libraries i can include the library and its dependencies so you can see our cmake build files build and our hello executable builds as well so if we now let's open up our main.tpb file let's include something like sfml slash system.hpd and then i can use something like sf in 32 blah and i can build it and it builds just fine so we've seen how we can use find package to link to a library and then depend on its libraries and include directories automatically using the variables that define your score package sets or actually the define something about cmake or the xx config does he makes sense and we'll talk more in detail about how this works in later videos but for now let's move on to how to explicitly include a library where you know the path for it and it doesn't maybe even have any sort of scenic configuration now let's talk about depending on an external library manually and this is like in case it doesn't have any sort of cmake configuration or if you just can't figure that out this is the most straightforward way it's the most explicit way and you can literally specify direct paths to the exact library file and link to it basically so the the first thing you can do is you can try find library and this will look through your system default library directories like user lib and you can specify a name for the library and give it a variable and it's always nice to give it a variable and find library will actually tell you whether or not the library was found and then you can just link to it like regular with target link libraries and now let's suppose it's in a custom path right so you can just do find library and you can provide a path variable and then you can specify the exact path that you want to link to the library and then the linking is similar as before and note that you still need to specify the include directories as well because finding this library here is just a lib file and so you also have to include the include directories and to figure out its dependencies you have to refer to the library's documentation and other cool stuff so let's see how we can do this so i've installed zlib using just sudo pacman dash sc lib and the funny thing about zlib is actually it's you can check out where it's included so if i include you can see there is a zlib dot h in my slash user slash include directory and um slash user lib actually the the library file for it is just libsy.a and iso that's um that's zlib so how do we link to this now so we can't use find package here if we try to use find package let's say c-lib and let's make this required [Music] the funny thing about zlib is you can see that we make includes a find zlib by in its default implementation so zero probably isn't the best directory so but it does show that sometimes you can install things and have them just be there but we can see how it would be if we wanted to include it manually instead of using find package so um let's take a look at how we would do that so we do the same thing we use find underscore library and in order to include the library we will let's use the most explicit way possible so we will do let's say zlib and it's just the library file now for all the library files in unix they're like prefix white like lib z but you don't want to explicitly say slim z so you can just say z you remove the the sort of lit part behind it so if i use this you can see that it actually does find it and just to make sure that if i just type libsy it won't actually find it so um then if i go back to just z it will find it just fine cool so but let's say i want to make it even more explicit so i can just do pat and i can specify slide user lib z.a yeah so if i wanted to be very very explicit about the exact file name i can say find underscore library and i'm going to put it in zlib um it would be lib z.a and like this is the exact file name but by default it won't actually look good and then i'll just say required and i'll say pat and i'll actually just specify the exact file name and then i am able to just link to it by just adding clip here to my target link libraries now that still doesn't mean the include will work so i will probably have to do um [Music] i'm yeah so i probably have to just do let's see if i can just do include [Music] yeah actually so by default it will include cmake does include the system like user include directories so we actually don't have to worry about system install libraries having to comply with um having to explicitly include stuff there so but if it wasn't let's say it wasn't um we want to set the blue directory as well so that's it in our case it will be zero include there and it would be something like um [Music] user slash include that's it i mean in in our case it is in the system default directory which is already included but uh and then you would add it to the include directories here and you would say something like sealab also directly and that's basically it for this introduction video um this has gotten a bit longer than i anticipated um and i want to dive into some of the more deeper more complex systems on how like how this grows i want to talk about how to use google test with zmake um and that'll be in a second video and one final thing i want to talk about is cpm and how nice this is um so you'll notice that even in like finer score package use cases you still have to worry about the variables and that's really messy with with cpm all you have to do is you have to once include cpm.cmg and then afterwards any package that's ready for cpm you all you have to do is add this little blurb here and then you can just link to the directory you don't have to worry about include directories you don't have to worry about the library files or anything else and they have a few examples here for some sample libraries that follows convention and you can see that it actually pulls it directly from github as well so this is super nice i'll dive into cpm in a later video as well but i just want to mention it because because it uses some of the real modern some of the nicer modern features of cmake so anyways thank you guys for watching please like and subscribe
Info
Channel: codevion
Views: 19,441
Rating: 4.8434443 out of 5
Keywords: cmake, cpp, build
Id: mKZ-i-UfGgQ
Channel Id: undefined
Length: 27min 46sec (1666 seconds)
Published: Sun Feb 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.