NERSC logo National Energy Research Scientific Computing Center
  A DOE Office of Science User Facility
  at Lawrence Berkeley National Laboratory
 

Example: making a library archive

In this example a number of subroutines are incorporated info a library archive. Routines from the library are linked into the main program during the linking process.

It is often convenient to maintain object files in a library. By doing so, you can reduce the number of .o files you need to keep in a directory, which can have many advantages.

The example project

Let's say we have four routines that we want to maintain in a library and a main program (libex.f90) that will call those routines. In this example, the routines simply perform an operation on two real numbers and print the result. We'll make a library file, named operators.a, that will contain the subroutines. After we create the library file, we will delete the object files (*.o).

Here's what the files look like:

% ls
add.f90        libex.f90      multiply.f90
divide.f90     makefile       subtract.f90

! FILENAME: add.f

SUBROUTINE add(x,y)
        IMPLICIT NONE
        REAL, INTENT(IN) :: x, y

        PRINT *, "The sum of", x, " and ", y, "is ", x+y

        RETURN
END SUBROUTINE add

!FILENAME: divide.f

SUBROUTINE divide(x,y)
        IMPLICIT NONE
        REAL, INTENT(IN) :: x, y

        IF(y==0.) THEN
                PRINT *, "Can not divide by zero!"
                RETURN
        END IF

        PRINT *, x, "divided by", y, "is ", x/y

        RETURN
END SUBROUTINE divide 

!FILENAME: multiply.f

SUBROUTINE multiply(x,y)
        IMPLICIT NONE
        REAL, INTENT(IN) :: x, y

        PRINT *, "The product of", x, " and ", y, "is ", x*y

        RETURN
END SUBROUTINE multiply 

!FILENAME: subtract.f

SUBROUTINE  subtract(x,y)
        IMPLICIT NONE
        REAL, INTENT(IN) :: x, y

        PRINT *, "The difference, ", x, " - ", y, "is ", x-y

        RETURN
END SUBROUTINE subtract 

!FILENAME: libex.f
! An example program that illustrates calling routines
! from a user-built library of object modules.

PROGRAM libex 
        IMPLICIT NONE

        REAL:: a=2.0,b=3.0

        CALL add(a,b)
        CALL multiply(a,b)
        CALL subtract(a,b)
        CALL divide(a,b)

END PROGRAM libex

The makefile

The following simple makefile can be used to maintain the archive and produce the executable. make has a special syntax for dealing with libraries. The library is defined on the line

$(LIB) : $(LIB)(add.o) $(LIB)(multiply.o) \
		$(LIB)(divide.o) $(LIB)(subtract.o)

The the rule for producing the library is the following (note that the .o files are removed immediately after updating the library).

.f90.a : 
         $(CF) -c $<
         $(AR) -r $@ $*.o
         /bin/rm -f $*.o

This rule says

  1. If the .f file has been modified since the .a file was modified, compile the .f file using $(CF) -c.
  2. Take the corresponding .o file and replace it in the proper library (as defined above) using $(AR) (The ar command builds and maintains libraries, see man ar).
  3. Remove the .o file.
CF = xlf90 
LD = xlf90 
LIBOBJS = add.o multiply.o divide.o subtract.o
LIB = operators.a
EXE = libex
OBJS = libex.o
AR = ar 


$(EXE): $(OBJS) $(LIB) 
        $(CF) -o $(EXE) $(OBJS) $(LIB) 

$(LIB) : $(LIB)(add.o) $(LIB)(multiply.o) \
		$(LIB)(divide.o) $(LIB)(subtract.o)
        
.f.a : 
        $(CF) -c $<
        $(AR) -r $@ $*.o
        /bin/rm -f $*.o
        
.f.o : 
        $(CF) -c $<


clean :
        /bin/rm  $(OBJS) 

clobber :
        /bin/rm $(EXE) $(LIB) $(OBJS) 

The Output

% make
        xlf90  -c libex.f
** libex   === End of Compilation 1 ===
1501-510  Compilation successful for file libex.f.
        xlf90  -c add.f
** add   === End of Compilation 1 ===
1501-510  Compilation successful for file add.f.
        ar -r operators.a add.o
ar: Creating an archive file operators.a.
        /bin/rm -f add.o
        xlf90  -c multiply.f
** multiply   === End of Compilation 1 ===
1501-510  Compilation successful for file multiply.f.
        ar -r operators.a multiply.o
        /bin/rm -f multiply.o
        xlf90  -c divide.f
** divide   === End of Compilation 1 ===
1501-510  Compilation successful for file divide.f.
        ar -r operators.a divide.o
        /bin/rm -f divide.o
        xlf90  -c subtract.f
** subtract   === End of Compilation 1 ===
1501-510  Compilation successful for file subtract.f.
        ar -r operators.a subtract.o
        /bin/rm -f subtract.o
        xlf90  -o libex libex.o operators.a 

s00505% ./libex
 The sum of 2.000000000  and  3.000000000 is  5.000000000
 The product of 2.000000000  and  3.000000000 is  6.000000000
 The difference,  2.000000000  -  3.000000000 is  -1.000000000
 2.000000000 divided by 3.000000000 is  0.6666666865


LBNL Home
Page last modified: Fri, 29 Feb 2008 23:54:47 GMT
Page URL: http://www.nersc.gov/nusers/help/tutorials/make/library.php
Web contact: webmaster@nersc.gov
Computing questions: consult@nersc.gov

Privacy and Security Notice
DOE Office of Science