Make and Makefile

make is a tool responsible for generating binary and other non-source files of a program from the program’s source.

make can be used to compile source code of any language.

Features

  • enables user to build and install software without knowing the details of that specific software
  • compiles source files as needed. can relate to hot-reloading.
  • make is also capable of installing and uninstalling packages.

A Makefile contains instructions for make to run. A series of instructions are known as a rule. A Makefile also describes relationship among files.Example of a simple rule:

target … : prerequisites …
        recipe
        …
        …
  • target is usually the name of the file that is generated by a program. This file generally is an executable or object file. A target can also be the name of an action to carry out, sucj as clean.
  • prerequisite is a file that is used as input to create target.
  • recipe is an action make caries out.

make uses tab for indentation. Failing to use it would throw an error

Makefile Processing

  • by default, starts with first target. also known as default goal
  • make must process rules the target depends on
  • recompilation is done only when target is older than source files; or when target does not exists

Variables

  • allows storing data in variable
  • variable declaration example: objects = main.o kbd.o.
objects = main.o kbd.o

edit : $(objects)
        cc -o edit $(objects)
main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
clean :
        rm edit $(objects)

Implicit Rules

make has an implicit rule for updating .o file from a correspondingly named .c file using cc -c command.

when a .c file is used through implicit rule, it is also added to the list of prerequisites. Hence, .c files can be omitted from prerequisites' list.

Example:

objects = main.o kbd.o command.o display.o

edit : $(objects)
        cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h

.PHONY : clean
clean :
        rm edit $(objects)

when using implicit rules, an alternate way of writing Makefile can be used. in this type of Makefile, entries are grouped by their prerequisites instead of by their targets

Example:

objects = main.o kbd.o command.o display.o

edit : $(objects)
        cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o : buffer.h

Cleaning Directory

make can clean a given directory. for that Makefile should have an explicit .PHONY target.

.PHONY prevents make to confuse it with an actual file target and causes it to continue in spite of errors from rm.

taget clean can be executed by passing it as an arg to make

clean should not be placed at top of the Makefile. Otherwise it would become global target and will be executed by default.

.PHONY : clean
clean :
        -rm edit $(objects)

what a Makefile may contain

  1. variable definitions
  2. directives (instruction for make to do something special while reading the makefile)
    • Reading another makefile
    • deciding whether to ignore a part of Makefile
  3. comments (starts with #). for multiline comment, a backslash should be used at breakpoints
  • Long lines can be splitted into multiple lines using backslash

Including other Makefile

  • make can read multiple Makefiles which are added using include directive. filenames can contain shell file name patterns.
  • if included file is empty, make does nothing.
    include foo *.make $(bar)
    
  • when path of file is not absolute, and the file is not found in current dir, make looks for it in some other places(in following order).
    1. dirs mentioned with -I flag (--include-dir)
    2. prefix/include
    3. /usr/gnu/include
    4. /usr/local/include
    5. /usr/include
  • NOT_FOUND warnings/errors can be supressed with -include directive
  • env variable MAKEFILES can be used to preload other makefiles (spearated by whitespace)