CHAPTER 8: COMPILERS/UTILITIES
back to the Computing Guide Contents


In the MMM computing environment, it is possible to compile programs written in either C or FORTRAN programming languages. This chapter covers both the C and FORTRAN compilers, makefiles, and the basic information listed below.


8.1 Compilers


8.1.1 The FORTRAN Compiler

Introduction

The command to compile FORTRAN programs on the Sun, SGI, and Compaq workstations is f77 or f90, and pgf77 and pgf90 on the Intel boxes running Linux. The file extension that you should use for FORTRAN source files is .f. This command creates an executable file called a.out. When you enter a.out on the command line, the program executes. To create an executable file with a different name, use the -o option. This option compiles prog.f and names the executable file prog. If you must combine more than one source code file to build the executable, list them sequentially on the command line. This creates an executable file called a.out from the three source code files. Note that by default, f77 compiles and links the files to create an executable. To create just an object file for later use, use the -c option. This creates object files called sub1.o, sub2.o, and sub3.o, but no executable file. If you have an object file sub4.o that you previously created with f77 and you want to combine this file with sub1.o, sub2.o, and sub3.o to create an executable file, enter

Linking your Program with Other Libraries

If you want to use only the NCAR Graphics libraries, use the special compile command ncargf77 to link your program with system libraries. This command compiles your program and links it with the NCAR Graphics libraries. The ncargf77 command invokes f77 with specific options to load those libraries. Most f77 options can also be used with ncargf77.

To use other libraries, such as mathematical or locally created libraries, use the -L and -l options. The -L option specifies directories in which the libraries reside, and the -l option specifies the libraries to include. As an alternate way to link with the NCAR Graphics libraries on our systems, enter

This command instructs f77 to link prog.f with the ncarg, ncarg_gks, and ncarg_loc libraries, located in the directory /usr/local/lib. If you create and use your own libraries or are using many interdependent libraries, the order in which you list them on the f77 command line is important. See a systems programmer for more information.

Optimization Options

Compiler optimization options are useful for speeding up programs. We have seen speedups of approximately a factor of two on our local machines with these options. However, there are sometimes costs for optimizing a program, such as longer compile and link times and greater memory usage by the program. For this reason, programs are not always fully optimized by default, and the default optimizations vary from machine to machine. Experience has shown that on the DEC workstations, an optimization level of 2 works best. To compile a program and specify an optimization level, enter On the Sun workstations, we recommend using level 3. To do this, enter

Common f77 Options

-ansi     (This option is for Sun workstations only.) 
          Identifies all nonstandard extensions. Good for 
          ensuring that the code is portable.


-std      (This option is for DEC workstations only.) 
          Identifies all nonstandard extensions. Good for 
          ensuring that the code is portable.

-c        Suppresses linking and produces an object (.o) 
          file for each source file.
-C        Compiles code to check during program execution 
          that subscripts are within the declared array bounds.
-g        Creates symbol table information for use in debugging.

-lx       Links with object library x.
        
-Ldir     Searches dir for library routines in 
          addition to standard system directories.

-o output  Names the final output file "output" 
          instead of "a.out."
-On       Optimizes the object code at level n.

-p        Prepares object files for profiling.

8.1.2 Debugging

Debugging is the process of finding and fixing errors in a program. One debugging method is to simply put WRITE statements around parts of the code that you suspect have errors. However, this method becomes tedious because you must continually recompile the code, and you cannot easily interact with it while it is running. Programs like dbx provide a solution.

The dbx Program

To use dbx, first compile and link your code with the -g option. This causes the compiler to store additional symbol information in the executable file for use by the debugger. Use the command After the executable file is created, invoke dbx with the command where a.out is the name of your executable file. Once in dbx, a special prompt appears. The dbx program is usually used in the following way.
  1. Set breakpoints within the program. A breakpoint is a line at which you want to suspend the execution, such as before or after a piece of code that you suspect has errors.
  2. Execute the program, under control of dbx.
  3. When the program stops at a breakpoint, print the values of certain variables, looking for strange or incorrect values that could reveal an error or pinpoint the section of code containing an error. If an error is found, exit dbx and fix that code.
  4. If an error is not found, continue executing the program, or add more breakpoints and then continue executing the program.

Common dbx Commands

Below are some common dbx commands and their actions.

Setting Breakpoints

        stop in xxxxxx  This causes the program to stop whenever
                subroutine xxxxxx is called. Once dbx stops, 
                you can perform other tasks, such as printing the values  
                of variables.

Printing Variable Values

print var1  Prints the current value of var1 
            in the current routine.
dump        Prints values of all variables in current 
            subroutine.

Running the Program

run             Executes the program.        
cont            This causes the program to continue after 
                execution has been suspended (and the user has 
                presumably printed out the values of some 
                variables).
run < prog.inp  Runs the program, taking input from 
                the file, prog.inp.
step            Executes the next line of code. It is often 
                very useful to step through part of a program as 
                it executes. Each source code line will be displayed 
                before it is executed.

quit            Exits dbx.

Miscellaneous Commands

where           Prints a traceback of the current call stack.
list            Lists current subroutine (the one in which the 
                program is currently stopped) to screen with line 
                numbers. Shows the first 20 lines of the routine. 
                To show the next 20 lines, enter list again.
The Sun workstations feature the option to use dbx on an executing program that was not initially started under dbx. This option is useful if a program unexpectedly malfunctions and appears to be in an infinite loop. To interrupt the process and find the subroutine that the program is in, enter
        a.out pid
where pid is the process number. The process will be suspended, and control turned over to dbx. This works well only when the running program was compiled with the -g option.

Some known problems exist with dbx. dbx was written to debug C programs, and may not return correct values for certain FORTRAN variables, such as those in data statements or common blocks. In addition, dbx does not work consistently on different hardware platforms.

8.1.3 Profiling

Profiling is the process of listing the CPU time a running program spends in each subroutine. This information can be used to speed up the program. Knowing which subroutines use the most time helps the programmer knows where to apply the most effort in optimizing. If routine A takes 200 seconds of CPU time and routine B takes 20 seconds, speeding up routine B will not significantly reduce the total execution time.

The basic profiling process works as follows. First, compile and link the program with a special option, then run the program normally. A special data file is created automatically during execution. After the run is complete, another program analyzes this data file and generates the CPU usage statistics.

Several tools (programs) exist to analyze this data file. This document discusses the prof tool. To prepare a program for profiling, you must compile and link it with the -p option.

        f77 -p prog.f
This creates an executable program, a.out, that was built to generate CPU usage statistics.

After the program runs, a file called mon.out, which contains the coded CPU usage information, will be present. To learn which routines used the most CPU time, use the prof command.

        prof a.out mon.out
This command generates a list of the routines in a.out (the executable program), the number of times each was called, and the approximate time each routine spent executing.

Note that the timings represent CPU times, not wall-clock times. Therefore, time spent waiting for input or output (i/o) operations to complete will not be measured. Thus, if your program consumes substantial wall-clock time due to i/o operations, the results from prof could be misleading. The delay may be caused by routines that are performing a lot of i/o, not those that prof shows as using the most CPU time.

8.1.4 FORTRAN Random Number Generators

There are system random number generators on the DEC and Sun workstations that can be called from FORTRAN programs. The generated numbers are adequately uniform in one dimension. For a generator that is random in more dimensions, or one with very specific spectral properties, it is best to find one in a numerical recipe book and code it yourself.

The DEC Random Number Generator

The DEC random number generator is a FORTRAN function call that takes an integer and returns a value in the range [0,1]. The syntax is
        RVAL = RAN(IR1)
You should initially set IR1 to a small integer. Each time RAN is called, a random number RVAL will be returned. IR1 will also be changed by RAN when it is called. The following code generates a series of random values.
        IR1 = 3

        DO 100 I=1,20 

                RVAL = RAN(IR1) 

                WRITE(*,10)RVAL 

        10  FORMAT(F8.6) 

        100 CONTINUE
You do not need to load an extra library when compiling code with a call to RAN in it.

Sun Random Number Generator

The Sun random number generator is simply a FORTRAN function call that takes an integer and returns a value in the range [0,1]. The seeding is accomplished by passing a non-zero integer to the function. Random values from the same stream are obtained by calling the function with zero as the argument. The syntax for seeding is
        RVAL = RAND(IR1)
where IR1 is a non-zero integer.

The random values are then obtained with the call, RVAL = RAND(0). The following code generates a series of random values.

        IR1 = 3 
        
        RVAL = RAND(IR1)

        DO 100 I=1,20

                RVAL = RAND(0)

                WRITE(*,10)RVAL 

        10    FORMAT(F8.6) 

        100   CONTINUE
You do not need to load an extra library when compiling code with a call to RAND in it.

8.1.5 FORTRAN Bitwise Intrinsic Functions

Bitwise functions are those that operate on the bits of a variable. A common example is the SHIFT function used to shift bits. FORTRAN 77 does not have bitwise functions as part of the standard. Thus, any such system functions that you use on one machine might not exist on another. However, we have found that the functions below work on DEC, Sun, SGI, and IBM RS6000 workstations, as well as on the Cray Y-MP.
        IOUT = AND(IN1, IN2)

        IOUT = OR(IN1, IN2)

Shifting (noncircular)

This function shifts bits to the left (IN2 > 0) or to the right (IN2 < 0). When shifting to the left, the uppermost bits are lost, and zeroes are placed in the lowermost bits. When shifting to the right, the lowermost bits are lost, and zeroes are placed in the uppermost bits. IN1 is the variable whose bits will be shifted, and IN2 is the number of bits by which it will be shifted.
        IOUT = ISHFT(IN1, IN2)
Exclusive or
        IOUT = XOR(IN1, IN2)

8.1.6 The C Compiler

The compiler options and utilities for the C compiler are similar to those for the FORTRAN compiler. Refer to the previous sections of this chapter for more information.
        Syntax: cc [options] filename
The default file type for a C source program file is .c.

On-line Information



Return to top of page

8.2 The make Utility


8.2.1 Overview of make

The make utility's most common use is to build executable programs from many source or object files. make compiles each source file and links all the object files, saving you the work of performing these functions manually. The user creates a file named Makefile or makefile, which lists the dependencies of the executable (the files that you must build the executable from). The make utility is beneficial only if your source code is split into more than one source file. make is unnecessary with a single large source file.

The make utility's advantage is that it creates a program with the minimum possible work. For example, if you use make to create an executable program, prog.e from five source codes, make automatically compiles them, creating five object files and the executable file. If you later modify only one of the source files and create a new executable file, make will recompile only the source file that changed, and then link the five object files together. Thus, make surpasses a simple shell script that always recompiles all source files regardless of how many have been modified. It is also more efficient than manually compiling and linking, especially when many files are involved. Once the makefile is created, enter

        make
The utility builds the executable program described in the makefile.

The make utility checks the modification date and time of the dependencies and compares them with the date and time of the "targets." In the above example, make first compares the time of each object file against that of each source file. If any object is older than a source file, it is rebuilt. make then links the object files to create the executable file. If no object file is older than a source file, make compares the time of each object file with that of the executable file. If the executable file is older than any of the objects, the files are relinked, and no compiling is necessary. If no source file or object file is younger than the executable file, make does nothing.

As mentioned above, the user creates a makefile to provide instructions for make. These files can become complicated, but are easy to create and use for most operations. This document describes only simple and common uses of make. See other make documentation for more details.

8.2.2 A Sample makefile

#--------------------------------begin makefile-------------------------
#
# makefile for the sample program 
#
SRCS=   file1.f    file2.f    file3.f    file4.f \ 
        file5.f    file6.f    file7.f    file8.f \ 
        file9.f

OBJS=   file1.o    file2.o    file3.o    file4.o \ 
        file5.o    file6.o    file7.o    file8.o \ 
        file9.o

PROGRAM=prog
LDR= f77  
FFLAGS= -g 
$(PROGRAM):     $(OBJS)   
        $(LDR) -o $(PROGRAM) $(OBJS) 
#------------------------------end makefile-----------------------------

Explanation of Commands

SRCS    A list of all the source files needed to build prog.

OBJS    A list of the corresponding object file names.

PROGRAM The name of the executable file. 

LDR     The name of the program used to link 
        (should be left f77).

FFLAGS  The set of flags that you want make to use when
        compiling each routine. Here, the -g option for debugging 
        has been supplied. Optimization and profiling options 
        would also go here.
The last two lines in the file tell make how to link the OBJS files to create the executable file. You do not need to modify these lines. Note that a single TAB (entered while editing), and nothing else, must precede the $(LDR) in the last line. In particular, do not place spaces before the $ character, or make will not work. make is strict about the syntax and structure of the makefile. Another example is the use of continuation characters (\) as above in the SRCS and OBJS lines. After the continuation character, a carriage return must follow immediately. There cannot be a space after the backslash. If you use make and see error messages that indicate a problem with spacing or TABS, see a more detailed manual for all the make syntax rules, or ask a systems programmer for assistance.

On-line Information



Return to top of page

Copyright © UCAR 1998 - Disclaimer - mmminfo@ncar.ucar.edu
Last Modified: 1 December 2002