Amazing video. I just tried to reproduce these concepts in my own makefile and had a few problems, so maybe I can share some points that I figured out. From what I understood, the "variables" are, in fact, macros. This means that their values are substituted when called, so trailing white spaces can become a problem. For example, I wrote the following line: SRC = src # Source files directory This became a problem, because $(SRC)/file.cpp would become "src /file.cpp" (mind the space before the slash). Therefore, I had to change to: # Source files directory SRC=src Anyway, this is what I understood, hope it can help someone.
A good scripting exercise is to write a script that creates the Makefile. Between header dependencies (which is missing from the simple wildcard based Makefiles) and the difference between tabs and spaces, hand crafting/maintaining a Makefile gets old very quickly with a project of any size.
thanks for videos on make! Could you go over these topics by any chance: - VPATH - implicit variables - automatic header dependency management - building external library as a prerequisite (for example googletest) and link against them
You sir are a saviour... I spent 19 hours trying to get my makefile to work with this project setup I have and then I saw you upload this video. Thank god. Also, I would like to know how to make the the Makefile to recompile if any custom header files change... Thanks
Adding/modifying like the following should do the trick: CFLAGS=-g -Wall -MD # "-MD" means Make Dependencies DEPS=$(patsubst $(SRC)/%.c, $(OBJ)/%.d, $(SRCS)) # "-MD" outputs makefile dependency files with .d extensions so lets generate a target list -include $(DEPS) # Run each dependency makefile but don't report an error if something fails("-")
Awesome video. Will you in the future make a video explaining directory structures for common open source projects ? Like those include, libs, and other dir that we see in open source projects in GitHub but have no idea how they are designed. Thank you.
1. I often use layered architecture while programming. Therefore, it makes sense for me to keep source files in different sub folders within $(SRC). How would you modify above Makefile to accommodate? 2. I often (CD/CI) incremental build/compile projects on different machines/devices (ex. Apple tablet or Samsung Tablet or Samsung mobiles, depending on which my family members are not using/left out device) using corresponding device specific Linux emulators. A structured $(BIN)/$(PLATFORM) arrangement in Makefile example would benefit hobby developers like me. Thanks!
!! at 7:49, be VERY careful when using make clean like that. I accidentally deleted every regular file on my pc because I changed the name of my DIR variable, making it empty when substituting into the expression "rm -rf $(DIR)/*". Typing "make clean" essentially ran "rm -rf /*", deleting most of my filesystem. Not fun! I suggest always prefixing with ./
Nice tutorial, but still quite simplistic. With a real-world project one would not be overwriting debug and release binaries in the same directory, there should be dedicated rls and dedicated dbg dirtrees. Designing build is often tedious/painful, but also extremely important. Cut corners and you will pay the price over time. Not sure if you should make more videos on this subject - one can spend a lot of time on this and it is a dry/tedious subject. Maybe just make a video illustrating how much effort/complexity real-world builds entail. And in that context please also mention cmake, it is pretty much industry standard.
While for the very simple, one-off stuff I use raw make, it really doesn't scale when you go cross-platform or have dependencies. Adding a basic project setup with CMake is a breeze, abstracts a lot of the nitty gritty tedious details and platform differences away and lets you focus on the important stuff. That's not to say that programmers shouldn't understand make and the low-level details of building a binary, but that doesn't mean you should *always* have to deal with it.
How can I include external libraries in my project with their source files and compile a statically linked binary? Specifically I wanna use libpng, libz and libjpeg.
Hi Jacob good work. I follow your videos to learn more about C programming but lately I found visual studio much more useful than vs code because it points out mistakes in memory allocation/deallocation by providing warning immediately by syntax highlighting. Also I feel as the project grows its easier to add more files and work on it and worry about make file stuff. May be I am a windows user so make file will be much useful in other operating system. Your thoughts are appreciated. Thanks
I have talked about how I feel about IDEs in a few other videos. They're fine, but for new programmers, I prefer tools/systems that hide fewer details from the student.
really timely video, I had to update my makefile last week. some questions: how do you account for both windows and unix systems in the same makefile? i found a flag that detects the OS and i use it to replace my rm (to del) and my .out to .exe, but it still feels weird. I have an issue that if i update a h file (cpp, so the templated code), it doesn't rebuild properly until i clean everything. is there a correct way to handle this?
I'm familiar with cmake, and have used it from time to time. I'm not in love with it - probably a product of the sort of work I do - but I can see why others like it. Also, in my classes, I prefer to use build systems with less magic, so the students can more easily understand what is actually going on. Still, there will probably be a cmake video in the future.
i dont get the 'all: $(BIN)' rules 🤔 First of all, what does it? And when i use this, i always get the error: make: *** No rule to make target 'bin/main', needed by 'all'. Stop.
This would have been so useful in my first year of university. I looked around for this kind of stuff, but found little information at the time. Awesome video!
What if I need a binary for each source file in src folder?. Like I need a structure like following / ---src/ ---bin/ Makefile. Can someone guide me on this?
@@JacobSorber I didn't even see a notification until today! Wow, but having multiple library directories and a main project. How to chain these together appropriately and work with the build system in an optimal manner. Let's safe for purposes of video length, you'd have 2 x small example libraries and 1 x main project folder to compile the executable. How do we handle this for both release and debug builds?
For most of my applications, I prefer to keep different sources in different 1-deep subdirctories, which requires more complex shenanigans to have all of them searched seamlessly. also, i think with this setup, if you update a header file, this makefile won't know to recompile everything that included it. For that, I learned about the -MMD flag, which creates files containing depenendencies which can be imported into the makefile. both clang and gcc have the MMD flag.
The %.o: %.c matching pattern is good for simple projects, but not really precise in some bigger ones. For example, it doen't recompile some source files which depend on some other header files which do not have its .c counterpart. In big projects it's really a mess and a nightmare to keep track of dependencies manually. That's why most modern C/C++ compilers support autodependency file generation with -MD and -MP flags which could be used in conjunction with -include in Makefiles to ease this process. Last thing to note is that there are some missing .PHONY rules to be more precise too. It's not easy to make good scalable Makefiles for big project by hand though. That's when I go to CMake or meson. Anyway, it was a great video! I really enjoy and learn a lot watching your channel!
Thanks for the great tips! I'd love to see a video about testing with make. I have my own routine with a bunch of test-* rules but the catch is that some test modules/cases are much bigger than others, which creates total spaghetti in my project environment. Moreover, at some point you realize some project parts deserve their own folders and even Makefiles but it's always too late. A video on how to manage tests would be deeply appreciated!
Nice one Jacob, I've set this up now for myself. One other thing I did that others might find useful, is a make target to run valgrind. This way you can use to test for memory leaks on all versions.