Learning Makefile(s)
I am learning how to write a proper Makefile using
https://makefiletutorial.com/#getting-started. And I am just writing down the things that jump at me, not complete neither a tutorial, just a look-up post or cheatsheet for me.
- 🗂️ Makefiles must be indented using TABs and not spaces or make will fail.
- 📝 each section, or block, is called a target (
target:) and it's actually a filename - when a target is run (aka when the commands of a target are run), the commands will create a file with the same name as the target
- no target supplied as an argument to the make command, the first target is run
- the target
compile: main.chasmain.cas dependency and will re-run this target when the file had changed - ❛ quotes have no meaning to Make, they are simply characters (that are assigned to the variable)
- 💡 create
allas a first target, so it will run by default if make is called without a target - when there are multiple targets for a rule, the commands will be run for each target
$@is an automatic variable that contains the target name*and%are called wildcards in Make*searches your filesystem for matching filenames, always wrap it in thewildcardfunction- when
*matches no files, it is left as it is (unless run in thewildcardfunction),thing_wrong := *.o # Don't do this! %is really useful, but is somewhat confusingecho $@ # Outputs the target nameecho $? # Outputs all prerequisites newer than the targetecho $^ # Outputs all prerequisites- don't use implicit rules, at least try to prevent them, they become confusing
- each command is run in a new shell (or at least the effect is as such)
- The default shell is /bin/sh, change by adding
SHELL=/bin/bashat the top of the Makefile - Add a
-before a command to suppress the error - Add
-ito suppress the error for every command - To recursively call a makefile, use the special
$(MAKE)instead ofmake - String substitution:
$(text:pattern=replacement)is a shorthand for$(patsubst pattern,replacement,text) - Target scoped variable, for a target
main.ccan be defined (e.g. in the line above) by prefixing it with the target name,main.c: variableName = 42for a target like this with a prerequisite$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.c, a variable can be defined like so:$(BUILD_DIR)/%.o: SOURCE_FILE = $^ # prerequisites