Compiling Cheops Programs

This document describes fundamentals of Cheops Makefiles. A natural follow-up to this file is the Howdy, World Primer, which describes the step-by-step process of writing and compiling the standard "Howdy, world" program.

We use the GNU/960 cross compiler and associated tools for compiling programs for Cheops. These tools are supported on Sun SPARC, IBM AIX/R6000, and DEC Ultrix/DECStation 5000 machines. Unfortunately, they aren't supported on either the HP700 or the DEC Alpha architectures at this time.

Environment

Cheops Makefiles require that your shell have all Cheops environment variables specified to describe the compile-time system configuration. To insure that your shell's path, environment variables and aliases are set up properly, refer to Host environment.

Copying a Makefile Template

The proper way to set up your Makefile is to copy one of the following files from the path /mas/garden/cheops/doc to a Makefile in the directory in which you will write your source code.

Use this template
For this type of code
Makefile.local.bin
A program that executes on Cheops (for use with chex)
Makefile.local.lib
A library which gets linked to a Cheops executable.
Makefile.host.bin
A program that executes on the host machine that may or may not communicate with Cheops.
Makefile.host.lib
A library which gets linked to a host executable.

Editing your Makefile

Once you have copied a fresh template to your own directory (and named it Makefile, not Makefile.something ) you will need to modify it to suit your needs. Be careful to avoid altering those lines that say they should not be changed.

Define the Ultimate Target(s)

The ultimate target is either BINFILE for binary executable or LIBFILE for an archived set of object files. Which ever is appropriate, set the target to the name of the binary or the name of the library without the .a suffix.

Define the list of object files

The OBJS variable is a list of .o files that need to be linked or archived together to create the ultimate target. If the list gets long, put a backspace at the end of the line and put in a carriage return to get to the next line. For each file in the OBJS list, make will search for a corresponding .c or .s file in that directory and try to compile or assemble it to make a .o file.

Define Compiler and Linker Flags

This section lets you add command line options to the compiler and linker

CCDEFS
list of defines for each .c file
CCOPTS
options to the gcc c compiler
INCS
the include directory path
LDOPTS
options to the gld object linker
LIBS
the library directory path, and libraries to link
FIXED
special gld960 option that defines the Cheops base addresses of different regions of the .t file (a non-relocatable version of the binary executable). Default value is -Ttext 3040000. Refer to "GNU/960 Tools 2.0 - Using gld960".
UNFXD
special gld960 option that defines the base addresses of different regions of the binary executable. Default base is relocatable, -r. Refer to "GNU/960 Tools 2.0 - Using gld960".
CHEOPS_ASM_ACTION
This determines the fate of the asssembly files generated as part of compilation. If this is set to "delete", they are deleted. (Use "none" otherwise).

Define Special Dependancies

Make, by default, creates a new target .o file if the corresponding .c or .s dependancy file is younger. To specify other useful dependancies the last section of your Makefile should list these.

Here's an example of how to define dependancies. Let's say we want to compile howdy.c and doody.c both of which include stuff.h and only doody.c includes cheops.h. howdy.o and doody.o are linked with libcheops.a to make the binary executable file, howdy. The additional dependancies should look like this:

${BINFILE} : $(CHEOPS_LOCAL_LIB)/libcheops.a
${OBJS} : ./stuff.h
doody.o : ${CHEOPS_LOCAL_INC}/cheops.h

Assembly problems

In developing assembly code, it is not unusual to make errors. The default set of rules for a local application aren't very helpful in this situation, as they pass a copy of the code through the C preprocessor, then pipe it into the assembler (which then refers to a line number in the piped stream). You can specify a separate set of compilation instructions in your Makefile which will override the defaults and produce a file which you can examine to localize the errors.

To do this for a file, file.s, use the following :

file.o: ;  ${CP} $*.s $*_s.c
           ${CCP} $*_s.c -o $*_s.s
           ${AS} $*_s.s -o $@
           ${RM} -f $*_s.c $*_s.s

Standard Makefile targets

The template Makefiles support several useful make targets that you should know about:

make
make all
compile .c files and assemble .s files that are younger than their corresponding .o files to create target OBJS and link them together to make the BINFILE executable (or LIBFILE library).
make clean
delete all OBJS files and the BINFILE (LIBFILE) for a fresh start
make clean all
same as make clean; make all;
make install
generate the BINFILE (LIBFILE) and install into the platform specific $CHEOPS_LOCAL_BIN ($CHEOPS_LOCAL_LIB).
make clean install
same as make clean; make install;
make listing
list the downloadable addresses of all functions and variables

Host/Local Architecture Independance

The template Makefiles keep track of the last system configuration that your code was last compiled under. The reason for this is that .o files compiled by different platforms are not compatible during the link or archive stage. To keep things straight, your Makefile automatically makes a .oldenv file in that directory which stores the values of environment variables that defines the current configuration. Each time make is invoked in your directory, the last compiled environment is compared to the current environment. If they don't match exactly, make clean all is automatically done to ensure that all .o files will be compatible.

While this is necessary to guarantee that .o are compatible, it can be bothersome to have to recompile all .o files each time you make for a different platform. Only the .c or .s files that have been altered should need to be recompiled. To solve this problem when developing code on different platforms alternately, the two make targets pre and post are useful in eliminating redundant compilation:

make post
copy all .o targets in the current directory into the current platform specific storage directory.
make pre
copies all .o targets in the platform specific storage directory to the current directory.

Thus if you always invoke make pre all post, then you will never need to recompile all .o files just because you are now on a new platform. Note: this procedure is primarily recommended only when the number of files in OBJS is large.

Multiple Ultimate Targets in a Single Directory

This implementation of template Makefiles supports having only a single ultimate target. If you require having multiple BINFILEs or LIBFILEs in a single directory, then do the following:


Jump to Software Tools
Jump to the Cheops Homepage
cheops-web@media.mit.edu
This is a "fix it yourself" web page, located at /mas/garden/cheops/WWW/software/compiling_code.html