CSc 352: Lecture-17

Makefiles

Note: All the programs mentioned in this lecture are in:

/home/cs352/SUMMER02/lecture17progs/

- How to write a simple makefile?

  - Simplest form (Inside a description file, named Makefile)

  program : main.o file1.o file2.o 
          gcc -o program main.o file1.o file2.o

  main.o : main.c 
          gcc -c main.c

  file1.o : file1.c 
        gcc -c file1.c

  file2.o : file2.c 
        gcc -c file2.c

  clean :
        /bin/rm -f *.o

  - 5 entries. 
    Each entry has a line containing a colon(dependency line)
    One or more command lines starting with a tab.
  
  - To the left of the colon on the dependency line is 'target'
    To the right are the 'target's dependency files.(In this
    case the first target is 'program' for example.)
    
  - The command lines show how to build the targets out of 
    their dependency files.

  - In general the command:
       make program
    looks for the dependency line with 'program' in the descr. file
    (Makefile), checks whether any of the dependency files are
    newer than target. (Do this recursively.)
    If at any line reached during this recursive checking, target
    is older than its dependency file execute the corr. commands.

  - In short, it does the compilation only when necessary.(if the 
    target is not uptodate.)

  - Some simple syntax:
    - make    will do the first target in the descr. file.
    - Every command begins with a tab, and only command do so.
      (not at the beginning of a comment or a dependency line, etc)
    - #       for comments
    - can have targets without dependency files(The colon must
      still be there, see the target "clean" above.)
    - Every nonexistsent target is outofdate.(That's why the commands
      for "clean" gets executed whenever the command 'make clean' is
      issued.
    - can continue a long line with a backslash(\) at the end.(Right
      before the newline.)

    - see makefiles1/


- Macros in the makefiles
  - Entries of the form:
    identifier = token-string
    are macro definitions.

  - Further references to $(identifier) or ${identifier} are the 
    same as token-string.

  - A macro must be defined before any dependency line in which it 
    appears.(ow order doesn't matter.)

  - Macro String Substituion:
    Assume the definition:
    SRCS = calcmain.c calcgetop.c calcstack.c calcgetch.c
    then the definition:
    OBJS = ${SRCS:.c=.o}
    is equivalent to:
    OBJS = calcmain.o calcgetop.o calcstack.o calcgetch.o

  - Internal Macros for Dependency Files and Targets:
    - $@ refers to target (only in a command line)
    - $? refers to the list of dep. files that are newer than
      the target (only in a command line.)
    - $$@ refers to the target (only on a dependency line.)

  - see makefiles2/
    

- Suffix Rules
  - Unix can recognize suffixes(.o or .c or .h etc.)
  - The only compilation we needed to specify is:
    calculator : ${OBJS}
          ${CC} -o $@ ${OBJS}
  
    i.e. we don't specify anything on how to build the .o files. Why?

  - Because implicitly(predefined) there are the following suffix rules:

    .SUFFIXES : .o .c
    .c.o : 
        $(CC) $CFLAGS -c $<   

  - .SUFFIXES: Specify the suffixes that "make" considers significant.
    If a dependency file has such a suffix, but has no explicit commands
    make, looks for an applicable suffix rule(like the one given above)
    Steps that make take upon finding that no explicit command for, say
    calcmain.o :
    1- Sees that .o is significant(implicitly defined)
    2- Look for a file in the current directory that:
      - has the same name as the file(i.e. calcmain)
      - has a significant suffix(.c for example)
      - can be used according to a suffix rule.
    3- The appropriate suffix rule is:
        .c.o :
        $(CC) $CFLAGS -c $<
	
       which describes how to make a .o file from a .c file. $< is the
       same as $? (But $< can only be used with the suffix rules.) In 
       this case it evaluates to calcmain.c
    4- If there are no further recursive checks and calcmain.o is
       outdated with respect to calcmain.c, executes the suffix rule:
       gcc -c calcmain.c

  - CFLAGS is a predefined macro, can overwrite it if necessary.       
  
  - see makefiles3/
 
- More on gcc and its options:
  - preprocessing, compiling, assembly, and linking
  - Options:    
    -c        Compile or assemble the source files, but do not link.
              The ultimate output is in the form of an object file 
              for each source file. (.o files)

    -o file   Place output in file.

    -Wall     Give All the warnings.

    -w        Suppress all warnings

    -g        Enable debugging

    -O        Optimize(Also -O1, -O2, -O3)

    -D identifier=token-str  define a constant

    -U identifier            undefine

    -Idir    Add the directory dir to the list of directories to be
              searched for header files.  Directories named by -I are
              searched before the standard system include directories.

    -llibrary Search the library named "library" when linking. The 
              linker searches a standard list of directories for the 
	      library, which is actually a file named liblibrary.a.  
              The directories searched include several standard system
              directories plus any that you specify with -L.

    -Ldir    Add directory dir to the list of directories to be
              searched for -l.