picostitch
crafting (and) JavaScript

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.c has main.c as 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 all as 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 the wildcard function
  • when * matches no files, it is left as it is (unless run in the wildcard function), thing_wrong := *.o # Don't do this!
  • % is really useful, but is somewhat confusing
  • echo $@ # Outputs the target name
  • echo $? # Outputs all prerequisites newer than the target
  • echo $^ # 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/bash at the top of the Makefile
  • Add a - before a command to suppress the error
  • Add -i to suppress the error for every command
  • To recursively call a makefile, use the special $(MAKE) instead of make
  • String substitution: $(text:pattern=replacement) is a shorthand for $(patsubst pattern,replacement,text)
  • Target scoped variable, for a target main.c can be defined (e.g. in the line above) by prefixing it with the target name, main.c: variableName = 42 for 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