Highely Recommended, Inc. Logo

NAVIGATIONMAKEFILE DOCUMENTATION

CM Home
CM Resources
SCM Policy
Help Requests
Release Procedure
Compatibility Matrix
Online Support
Make Process
Release Requests

MAKE PROCESS

Make utilities are design to work on an ordered set of steps. The best way to create a makefile if you are starting from scratch is to start with what you want to create first. That is to say that the end result should be the name of your first target. The dependencies for this target should be what is needed before this target can do its work. The target rules are then, what is needed to translate the dependency into the target or result for that step. Each target should ideally do just one step so that all dependencies are defined and make can do the minimal amount of work.

To summarize in coding terms, start with the application and work backwards until you end up with the source files. Make utilities are usually associated with software development, but can be used to perform any order set of steps where each step is translating something from a given format into another format.

Prerequisites For Building the Application Software

The application software and all the vendor tools for building the software have been put under ClearCase Configuration Management control. You will need to have the ClearCase product installed on your system in order to build the product software.

To configure your system for using the Wind River Tornado tools see, Setting up Your Environment

Building the Application Software

We will be using the ClearCase product clearmake program for doing software builds. Clearmake has extensions over other make utilities in that it does an audited build retaining build dependencies, parameters and all other information associated with creating a derived object. Clearmake will also reuse objects, winkin, created by other users further minimizing the amount of work to be done in a build.

Current build results are created for each board in the target area. For example results are located at:
/product/target/config/pdi/pdi_st/pdi.st
/product/target/config/pdi/pdi_rom/pdirom.bin
The first being the application and the second the boot rom.

Step For Doing a Build

  1. Login
  2. Use ClearCase Home Base to start a view for the build to take place in.
  3. Use ClearCase Home Base to mount the product and vendor VOBs.
  4. In a cmd.exe window or an MKS shell window change directories to your "view drive"/product.
  5. To build type clearmake -C gnu >build.log 2>&1
    The redirection of the make output into a file will will log of the build so that you can check for errors.
  6. If you are modifying application code in a subdirectory, running clearmake will re-build the software in that part of the application. When you need to re-build the system do a clearmake -C gnu product.
  7. Other targets in the make files are clean and clobber. The clean target will remove all intermediate derived objects. The clobber target has a dependency for clean and will remove the end targets as well.

Trouble Shooting Build Problems

For trouble shooting build recreation problems, it is often useful to use the clearmake configuration record created for every derived object generated during a build. cleartool catcr "object file" will list the configuration record for a derived object. If the derived object is the result of combining previously created derived objects then a cleartool catcr -r "object file" will recurse through all the predecessor derived object configuration records to list out all information about how the drived object was created. You can also do a difference compare of configuration records using the cleartool diffcr command. For more information on these cleartool commands you can type cleartool man "command".

To do a build with debugging information generated, type:
    clearmake -C gnu DEBUG=-g

This will set the DEBUG macro to "-g" which will be added to the CFLAGS macro. Since clearmake remembers the parameters used in creating a derived object it will re-compile all files in the subsystem with the debug flag. If you only want one file or a few files to be re-built with debug information then you need to have clearmake behave more like other make utilities that compare the time between the dependencies for a derived object and the derived object. Meaning a derived object would only be created or re-created if it does not exist or is older than one of its dependencies. To create one or more derived objects with debug information, remove the derived objects and then type:
    clearmake -T -C gnu DEBUG=-g

Another quick debugging technique when locality of problem origin is hard to determine is to compare checksums of derived objects to determine which ones changed between two builds.

Makefile Maintenance

In general the types of changes that will be required for makefile maintenance are the adding of new directories to the directory traversal makefiles and new source files to the subsystem makefiles where software or build targets are processed.

To create a makefile for a new build or directory traversal, first copy an appropriate makefile. If it is a directory traversal you need to edit the first target name to match the current directory and the target rules to traverse the appropriate directory structure.

If the new makefile file involves building software, then copy a subsystem makefile. Modify the PROG macro and include paths if necessary. If the makefile is located at a different level in the software tree you will need to modify the TOP and SRC macros. Finally change the SRCS macro to be the list of source files that need to be compiled.

Makefile Examples

Makefile examples from a customer project. NT system platform building an embedded Wind River based application. Three MKS programs; sh, cp, and rm were pulled into ClearCase to allow a generic build process to be created.

Common Makefile

Directory Traversal

Subsystem Makefile

Application Makefile

ROM Makefile

Version Identification

Changing Makefiles

All application makefiles include the makefile.common file which contains definitions for all commonly used macros, SUFFIX rules and Implicit targets. Guard against adding -D compiler macros to the common makefile if they are not used everywhere. That is an example of coding obscurity which is commonly done. The file makefile.common should not include any other files.

Currently the board makefiles, like /product_B/target/config/pdi/pdi_st/makefile, do not include a common definition file. This could change in the future if enough commonality between boards makes this desirable.

When editing makefiles do not remove the tab character at the start of the target rules lines. Lines that have nothing but blanks will look like a blank line but are not to a make program. Continuation character at end of line where it should not be or a blank after the continuation character are also sources of problems.

Watch out for name collisions. If you have a directory name that is in the VPATH and it matches a target or file name it can cause your build to break.

When you need more than one thing to happen within a shell invocation use the shell command line separater character, semicolon or ampersand if you must use cmd.exe, to separate the commands and have them on one line. An example is:

cd directory; "$(MAKE)"
If you put them on separate lines within a target, the change directory
would happen in one shell invocation and the make would happen in a
separate shell.

If you want to only execute the second command if the first command completes successfully use a double ampersand character to separate the commands. If you want the second command to execute if the first command fails use a double vertical bar to separate the commands. An example is:

cd directory && "$(MAKE)"

We are using the MKS shell program to have a more general and capable build process. When passing commands to the shell you need to consider how they are being processed. A few examples should be helpful. When is something an environment variable and when is it a parameter?

PATH=$(PATH) command $(PARAMETER)
You need to know how a command makes use of information and where it
expects to recieve the information from.  In the above example the macro
in front of the command defines the PATH evironment setting and the macro
after the command is a parameter to the command.

Be aware of the what the make utility parser does in its processing. For example how many parameter are being sent to a command?

command $(P1) $(P2) = string2 "$(P3) = string3" \"$(P4) = string4\" \
    $$(P5)
We count nine parameters.  We get this by knowing that spaces are
delimiters to the shell and that the make interpreter will consume
quotation marks unless they are protected by a preceding back slash
character.  The last parameter is an example of preventing the make
interpreter from expanding the macro P5 so the command will receive the
string $(P5) in this case.

Makefile Glossary

  • Continuation line - the line preceding is ended by a back slash character. Example: is interpretted as one line.
    	SRCS = \
    		file1.c \
    		file2.c \
    		file3.c
          
  • Dependancy - any file that a target has a dependency on. Example: the derived object file version.o is dependent on version.c, dependencies are listed on the target line after the colon character.
    	version.o: version.c
          
  • Derived object file - any file created during a build process, example:
    	version.o
          
  • Double colon target - can exist in a makefile more than once with different dependencies and target rules. Another effect is that they are always executed so they work nicely for directory traversal targets where the target name is a directory which is always up to date. Finally once you define a target name with a double colon you can not have the same name with a single colon.
    	directory::
    		cd $@ && "$(MAKE)"
          
  • Explicit target - a target which defines the steps or process to create a specific derived object. Example: the version.c file is created by the following target using a utility defined by the macro SET_VERSION.
    	version.c:
    		$(SET_VERSION)
          
  • File type extensions - file name suffixes. Examples are:
          name.c - is a source file
          name.o - is an object file
          
  • Implicit target - targets are ones that are never refered to directly and have an associate SUFFIX rule. Example: the target below is the most common example which compiles a C source file into a derived object file using the compiler defined by the CC macro and compiler flags defined by the CFLAGS macro.
    	.c.o:
    	    $(CC) $(CFLAGS) $<
          
  • Macro - any makefile variable, example:
    	DEBUG   = -g
    	CFLAGS := $(DEBUG) -c
    	OBJS    = $(SRCS:.c=.o)
    	

    The first line defines a macro DEBUG and the second line gives an example of using the macro as part of the definition for another macro. The second line is also an example of the GNU early macro expansion define statement. For the CFLAGS macro to expand properly the DEBUG macro must be defined in the make file before the CFLAGS define line. The last example shows a string subsitution for the file name suffix changing is from a "c" to an "o" character.

  • Predefined macros - all make utilities have predefined macros, SUFFIXS, and implicit targets.
    	MAKE - current make program name
    	$?   - list of dependencies, can be used in target rules
    	$@   - current target name, can be used in target rules
    	$<   - target prerequisite, can be used in target rules
    	$*   - name without suffix, can be used in target rules
    	$%   - name corresponding .o file, can be used in target rules
    	@D   - directory part of target name, can be used in target rules
    	@F   - file name part of target name, can be used in target rules
    	$$va - make strips first $ and sends $va to shell, contents of var.
          
  • SUFFIX rules - are used in conjunction with Implicit targets for defining the steps for translating from one file type extension to another file type extension. Order of item in SUFFIX rule does not matter. Examples:
    	SUFFIXES:  - empties suffix rule
    	SUFFIXES: .c .o .cpp .s - associates implicit targets with file
    	                          type extensions; .c, .o, .cpp, and .s
          
  • Target - name starting at begining of line followed by a colon character. Example: version.o is a target name.
    	version.o: version.c
          

    Target lines are followed by lines (rules) defining the steps of work to be done to create the specific target. Each one of these lines must start with a tab character. A target is terminated by a blank line. A target should only do one step in the build.

  • VPATH - is a make macro defining an ordered list of locations where the source files should be looked for. The path separator character varies with different make utilities, but for clearmake on the NT platform the separator character is a semicolon. The separator character can also be a space if clearmake is run in the GNU compatibilty mode, -C gnu. Make utilities will still look in the current directory first for a source file. This macro is only used for implicit targets.

Other Make Process Documentation

GNU Make Docs
GNU Make
Make Cook Book
Recursive Make Considered Harmful

Remember all make processes are a compromise. You end up putting in requests for developers that are not all ways necessary. You work around tool problems. You accommodate other process issues. Some languages like java also present make process problems.