Once you master how a Makefile works, you can move on to CMake.


From CS247


  • (includes List.h)
  • List.h
  • (includes List.h)

:= vs. = Syntax

Turns out that you can also use := to define the variables. The difference is that if you assign it to another variable using :=, you need to make sure that the variable is defined before.

The ESENCE OF MAKE: target: preqrequisite

  • this is how make is able to detect changes (they use timestamps of files as a heuristic)
Makefile (v1)
myprogram: main.o, List.o
myprogram (TAB) g++ main.o List.o -o myprogram
  • General format for first line is target: dependencies
  • g++ main.o List.o -o myprogram is called the recipe
main.o : List.h
	g++ -std=c++14 -c
List.o : List.h
	g++ -std=c++14 -c

This text is in a Makefile in our directory.

make creates the first target

Looks at the last modified time of dependencies.

If last modified time is newer for a dependency than a target => target is out of date, recreate it.

Still too much work! Still requires lots of updates to our makefile.

Makefile (V2)
CXX = g++
CXXFLAGS = -std=c++14 -Wall -g -MMD
EXEC = myprogram
CCFILES = $(wildcard *.cc)
-include ${DEPENDS}


  • -Wall for more warnings
  • -g for extra debugging support (so you can use gdb)
  • -MMD to generate dependency information as a side-effect of compilation. The compiler will create a .d file for each .cpp file you compile. These .d files are makefile fragments that the make program can use to determine which .cpp files need to be recompiled when a header file changes.

- include ${DEPENDS}

  • Compiles all object files with dependencies using CXX and CXXFLAGS

CXXFLAGS doesn't seem to be used??

How does it know to use those flags then? StackOverflow has same question.


In WATonomous and in ROS2 in general, every new node has a CMakeLists.txt.