A Quick Introduction to Make

A quick introduction to how Make works and some tips for using it.

Note: It should be noted that this is not a UW-Madison Help Desk or DoIT Middleware supported procedure, and, naturally, we can't take responsibility for any damage you do while following or attempting to follow these procedures. Be sure you understand what you are doing.

Background

Make is a reduction language.

An Example

Given the Makefile

a: b c
	cat b c > a

b:
	echo hi - b > b

c:
	echo hi - c > c
Typing
$ make a

Executes:

  1. echo hi - b > b
    creating a file named b containing hi - b.
  2. echo hi - c > c
    creating a file named c containing hi - c
  3. cat b c > a
    creating a file named a containing the contents of b and a (concatenating them, redirecting the output to a).

Makefile Structure

Generically Makefiles consist of simple rules of the form:

TARGET ... : PREREQUISITES ...
	COMMAND
	...

More than one target can be built by a rule, and a rule can have any number of prequisites.

Important thing about Makefile Rules

  • Make requires real tabs before the COMMAND

Useful Make tricks

  • Using variables in Makefiles. Variables in Makefiles look and generally function like variables in Bourne Shell, with the exception that variables must be referenced as $(VARIABLE).

    For example,

    PREFIX=/home/miner
    
    $(PREFIX)/a: b c
    	cat b c > $(PREFIX)/a
    
    b:
    	echo "hi - b" > b
    
    c:
    	echo "hi - c" > c
    
  • Create aliases for commands. You'll save yourself a lot of headaches if you create variables pointing to the command to use you will be able to easier integrate with AutoConf, and be able to change which specific executable you use if there are broken or outdated versions.

    For example,

    CAT=/bin/cat
    ECHO=/bin/echo
    
    a: b c
    	$(CAT) b c > a
    
    b:
    	$(ECHO) "hi - b" > b
    
    c:
    	$(ECHO) "hi - c" > c
    
    When you find that the version of echo you're using doesn't echo to your satisfaction, you can easily change which one you're using.
  • Creating directories with Make. Directories can be created just as easily as regular files, and can save you a lot of fumbling and debugging.

    For example,

    PREFIX=/usr/local/stuff
    BINDIR=$(PREFIX)/bin
    MKDIR=mkdir
    
    $(BINDIR): $(PREFIX)
    	$(MKDIR) $(BINDIR)
    
    $(PREFIX):
    	$(MKDIR) $(PREFIX)
    
  • Using install targets. Targets in a Makefile don't need to be real files. The pseudo target install is used to gather the files to be installed.

    For example,

    PREFIX=/usr/local/stuff
    CAT=cat
    CP=cp
    MKDIR=mkdir
    
    a: b c
    	$(CAT) b c > a
    
    b:
    	echo "hi - b" > b
    
    c:
    	echo "hi - c" > c
    
    $(PREFIX):
    	$(MKDIR) $(PREFIX)
    
    $(PREFIX)/a: a $(PREFIX)
    	$(CP) a $(PREFIX)/a
    
    install: $(PREFIX)/a
    	echo "Installed!"
    
    

So....

With the Makefile illustrated above, typing

$ make install

Causes the following things to happen (assuming that none of the files or directories already exist):

  1. Make expands all variables in the file:
    • $(PREFIX) becomes /usr/local/stuff
    • $(CAT) becomes cat
    • $(CP) becomes cp
    • $(MKDIR) becomes mkdir
  2. Make looks for a target in the Makefile named install, and attempts to follow the rules to create it, but notices that it has a prerequisite of /usr/local/stuff/a.
    1. Make looks for a target in the Makefile named /usr/local/stuff/a and attempts to follow the rules to create it, but notices that it has prerequisites of a and /usr/local/stuff.
      1. Make looks for a target named a, and attempts to follow the rules to create it, but notices that is has prerequisites of b and c.
        1. Make looks for a target named b, and creates it by executing:
          echo "hi-b" > b
          
        2. Make looks for a target named c, and creates it by executing:
          echo "hi-c" > c
          
        3. Having satisfied the prerequisites of a, Make creates a by following it's rules and executes:
          cat b c > a
          
      2. Make looks for a target named /usr/local/stuff, and creates it by executing:
        mkdir /usr/local/stuff
        
      3. Having satisfied the prerequisites of /usr/local/stuff/a, Make creates /usr/local/stuff/a by following it's rules and executes:
        cp a /usr/local/stuff/a
        
    2. Having satisfied the prerequisites of install, Make follows the rules for install and executes:
      echo "Installed!"
      
  3. And finally, having no other targets to create, Make exits.



Keywords:make usage makefile   Doc ID:4114
Owner:Jon M.Group:Middleware
Created:2005-11-01 19:00 CDTUpdated:2010-08-13 19:00 CDT
Sites:Middleware
Feedback:  5   1