FSL Makefile Reference Guide

Table of Contents

  • Introduction
  • Writing a makefile
  • Makefile variables
  • Standard targets
  • Makefile examples
  • Implementation
  • default.mk
  • vars.mk
  • systemvars.mk
  • rules.mk

  • Introduction

    To help ensure that projects are managed in a simple standard way, a skeletal Makefile has been created which contains consistent methods for the targets clean, distclean, install-dev, install-stable and install-all. In addition, it also includes code to automatically build all *.o and *.c/cc dependencies, which are then stored in a file depend.mk and this is generated whenever a fresh build occurs. To use these features the line include ${FSLCONFDIR}/default.mk should be included at the beginning of all project makefiles.

    Example

    A simple Makefile for an executable file called solution, that is split into files solution.cc and subsoltion.cc (with appropriate headers) would be:
    include ${FSLCONFDIR}/default.mk
     
    PROJNAME = solution
    
    OBJS = solution.o subsolution.o
    LIBS = -lnewmat -lavwio -lm
    
    XFILES = solution
    all: solution
    
    solution: ${OBJS}
    	${CXX}  ${CXXFLAGS} ${LDFLAGS} -o $@  ${OBJS} ${LIBS}
    

    Note the PROJNAME and XFILES macros. These control what gets installed and where they are installed to respectively. For libraries there are also HFILES and AFILES macros. For languages other than C/C++ there will be equivalent variables.


    Writing a Makefile

    Essentially, a makefile is a collection of variable definitions and commands which control the building of a project. The skeletal definitions provides by the default.mk file greatly simplify the writing of makefiles within FSL.

    Basics

    Within FSL, all Makefiles should begin with the line
       include ${FSLCONFDIR}/default.mk
    
    in order to use the standard rules and variables.

    Building library modules

    The command to use to create a library module (compile all code and then archive) is:
    libprojname.a: ${OBJS}
    	${AR} -r libprojname.a ${OBJS}
    
    where libprojname.a should be replaced by the appropriate name for the module (e.g. libavwio.a).

    Building binaries

    The command to use to create an executable program (compile all code and link) is:
    projname: ${OBJS}
            ${CXX}  ${CXXFLAGS} ${LDFLAGS} -o $@  ${OBJS} ${LIBS}
    
    where projname should be replaced by the appropriate name for the executable (e.g. flirt) and OBJS is a list of all the dependent object files (e.g. flirt.o io.o reg.o).

    The all target

    This target has special meaning, and is the default target that is executed when make is typed without any other arguments.
    In all Makefiles this line must be defined.
    For a library module it should be:
    all: libprojname.a
    

    For executable code it should be:

    all: projname
    

    Linking with other library modules

    If you simply want to use code from another library then you just need to list the library in LIBS (e.g. LIBS = -lavwio -lm. The default makefile automatically searches for headers and librares as follows:
    1. Look in the current directory
    2. Look in ${FSLDEVDIR}/{include,lib}
    3. Look in ${FSLDIR}/{include,lib}
    4. Look in ${FSLDIR}/extras/{include,lib}
    5. Use ${USRINCFLAGS} and ${USRLDFLAGS} to specify custom locations not covered above.
    This means that you can also work on projects and their dependant libraries simultaneously. For example, say you want to develop and test new features in the avwio library. Check out avwio and some client project that you're going to use for testing purposes, e.g., flirt.
    1. cd avwio; make and make install will place the headers and freshly built libraries in ${FSLDEVDIR}/{include,lib}.
    2. cd ../flirt; make will build flirt and link it using the headers and libraries installed in the previous stage. Any other dependencies will be catered for via the versions in FSLDIR.

    Makefile Variables

    In FSL, many special variables are defined to help simplify the process of writing Makefiles. Some variables will need to be redefined by the user for their project, but otherwise there is a default behaviour which occurs when the variables are not defined in the user's Makefile.
    That is, a blank definition (e.g. "XFILES = ") will cause the variable to be blank and prevent the default behaviour from occurring.

    The full specification of FSL variables is given in the section that describes vars.mk, however, the most commonly used and important variables to know in FSL are:

    LIBS
    This specifies the libraries required to build the project that is, the -l compiler flags (e.g. LIBS = -ltransform -lm).
    For FSL libraries, the pre-defined variable INCDIR should be used to reference FSL include directories, together with the convention projname for stable libraries and projname_dev for development libraries (e.g. LIBS = -limage_dev -lavwio -lnewmat -lm).
    Note that the order is very important when the library modules depend on each other. Module 1 will only be able to find an element in module 2 if module 1 is before module 2 in the list.

    No default.
    XFILES
    This specifies the name(s) of the executable files to be installed in /usr/local/fsl/bin. This should always be provided for executable programs.
    No default.
    TESTXFILES
    This specifies the name(s) of the executable files that are NOT to be installed in /usr/local/fsl/bin.
    No default.
    AFILES
    This specifies the library modules to be installed.
    Default is all *.a files.
    HFILES
    This specifies the header files to be installed.
    Default is all *.h files.
    TCLFILES
    This specifies the name(s) of tcl scripts to be installed in /usr/local/fsl/tcl and featured in the tcl index.
    No default.
    SCRIPTS
    This specifies the name(s) of non-tcl scripts to be installed in /usr/local/fsl/bin.
    No default.
    RUNTCLS
    This specifies the name(s) of GUIs to be included in /usr/local/fsl/bin. This represents names only, not files, and will create links to the Runtcl script in bin.
    No default.
    OBJS
    This specifies the object files in this directory that are required to build the project (e.g. OBJS = interpolation.o generalio.o projname.o).
    This should be provided, although the name is not important, as long as it matches the one used in the make rule. For instance, separate objects may be needed by several programs within a single project. In this case names like TOBJS, AOBJS, etc. might be the most appropriate.
    No default.
    USRLDFLAGS
    This specifies any compiler flags needed for extra library paths. That is, -L flags (e.g. USRLDFLAGS = -L/usr/local/newmat/lib).
    No paths need to be inserted for FSL libraries as these are automatically included.
    No default.
    USRINCFLAGS
    This specifies any compiler flags needed for extra include paths. That is, -I flags (e.g. USRINCFLAGS = -I/usr/local/newmat/include).
    Within FSL, the pre-defined variable INCDIR should be used to reference FSL include directories, together with the convention projname for stable libraries and projname_dev for development libraries (e.g. USRINCFLAGS = -I${INCDIR}/avwio -I${INCDIR}/image_dev).
    No default.

    In addition, the skeletal Makefile uses several variables to set up the functionality. These variables (and some system defaults) should not be redefined by the user. They include: CXX, CC, AR, RM, MAKE, INSTALL, MKDIR, CHMOD, FSLDIR, INCDIR, LIBDIR, BINDIR, PROJNAME, OPTFLAGS, DBGFLAGS, CFLAGS, CXXFLAGS.


    Standard Targets

    The targets automatically included by FSL makefiles are:

    make clean
    This removes all *.o, core and depend.mk files
    make distclean
    This does a make clean and removes all *.a and executable files
    make install
    Does a make all and then copies appropriate *.h into ${FSLDEVDIR}/include/<projname>/*.h and *.a into ${FSLDEVDIR} /lib/*.a
    make all
    Same as just plain make and will build/rebuild all the code as determined by the automatic dependencies
    make debug
    Invokes make with debugging flags set.
    make release
    Invokes make with our choice of optimisation flags.

    Makefile Examples

    A simple Makefile for an executable file called simple, that is split into files main.cc, module1.cc and module2.cc (with any appropriate headers) which uses the FSL library libstats would be:

    Note that you never need to specify object file dependencies. These are created for you. The only caveat is that they aren't rebuilt unless they are missing so if you add a file to your project you must manually run make depend.

    include ${FSLCONFDIR}/default.mk
     
    PROJNAME = simple
    
    OBJS = main.o module1.o module2.o
    LIBS = -lstats
    XFILES = simple
    
    all: simple
    
    simple: ${OBJS}
    	${CXX}  ${CXXFLAGS} ${LDFLAGS} -o $@  ${OBJS} ${LIBS}
    

    Similarly, for a library module called lut a typical Makefile would be:
    include ${FSLCONFDIR}/default.mk
    
    OBJS = lut.o
    
    all: liblut.a
    
    liblut.a: ${OBJS}
    	${AR} -r liblut.a ${OBJS}
    

    Finally, a more complicated example is provided by an actual FSL application - /usr/local/fsl/src/avscale/Makefile - (without the comments):
    Note that the order in LIBS is important as mjimage depends on both mjavwio and newmat, and so the linking will fail if these are given in another order.
    include ${FSLCONFDIR}/default.mk
    
    OBJS = avscale.o
    
    NEWMATDIR = /usr/local
    NEWMATLIB = ${NEWMATDIR}/lib
    NEWMATINC = ${NEWMATDIR}/include
    
    LIBS = -lmjimage -lmjavwio -lnewmat -lm
    
    XFILES = avscale
    
    all: avscale
    
    avscale: ${OBJS}
    	${CXX}  ${CXXFLAGS} ${LDFLAGS} -o $@  ${OBJS} ${LIBS}
    

    Implementation

    Currently four files make up the central makefile definition. One of these, ${FSLCONFDIR}/${FSLMACHTYPE}/systemvars.mk is the site specific configuration file and anyone porting to another site should take a careful look in here. The other three define the FSL rules and macros.

    The following tables describe the main contents of each of the make files. Reading this and looking at the actual file should help you to decipher what each file does.

    ${FSLCONFDIR}/default.mk

    Really this is only a stub which includes the other three components. All project makefiles include this file, ie, they contain the line include ${FSLCONFDIR}/default.mk as the first line of Makefile.

    ${FSLCONFDIR}/common/vars.mk

    These are the macros defining the locations, files of interrest, compiler flags, etc, required to build any FSL project.

    MacroFMRIBs default valueDescription
    INCDIR${FSLDIR}/include The location of the include tree
    LIBDIR${FSLDIR}/lib The location of the FSL libraries
    BINDIR${FSLDIR}/bin Where any generated binaries should go
    MANDIR${FSLDIR}/man/man3 The place for man entries
    TCLDIR${FSLDIR}/tcl Installed tcl scripts go here
    DOCDIR${FSLDIR}/doc Installed user documentation goes here
    REFDOCDIR${FSLDIR}/refdoc Installed reference (e.g. library) documentation goes here
    STABLESRCDIR${FSLDIR}/stable-src The location of the stable release sources.
    PROJNAMEN/A Always redifine this in your local project makefile. It should usually be the same name as your src directories. It dictates where header files and libraries should go.
    USRLDFLAGSN/A Additional flags you want to pass to the linker.
    USRINCFLAGSN/A Additional flags to indicate where you want to look for headers, e.g., USRINCFLAGS = -I/opt/boost.
    USRCFLAGSN/A User specified additional C language flags.
    USRCXXFLAGSN/A User specified additional C++ language flags.
    CFLAGS${ANSI_FLAGS} ${DBGFLAGS} ${USRCFLAGS} ${OPTFLAGS} -I. -I${INCDIR} ${USRINCFLAGS} -L. -L${LIBDIR} ${USRLDFLAGS} C language flags.
    CXXFLAGS${ANSI_FLAGS} ${DBGFLAGS} ${USRCXXFLAGS} ${OPTFLAGS} -I. -I${INCDIR} ${USRINCFLAGS} -L. -L${LIBDIR} ${USRLDFLAGS} C++ language flags.
    HFILES*.h The headers you want installed.
    AFILES*.a The libraries you want installed.
    XFILESN/A since there is isn't a simple way to find them. The binaries you want installed in the generally accessible FSL bin.
    TESTXFILESN/A since there is isn't a simple way to find them. The binaries you do not want installed in the generally accessible FSL bin.
    TCLFILES*.tcl The tcl scripts that you want installed in the FSL bin.
    RUNTCLSN/A since there is isn't a simple way to find them. The GUIs to be made available (they represent names only, not files, and will be linked to the Runtcl script in bin).
    MANFILESman/* User specified additional C++ language flags.
    DATATYPES if [ $$FDT = "8UI" ] ; then STR="unsigned char" ; fi ; \
    if [ $$FDT = "8SI" ] ; then STR="signed char" ; fi ; \
    if [ $$FDT = "16UI" ] ; then STR="unsigned short" ; fi ; \
    if [ $$FDT = "16SI" ] ; then STR="signed short" ; fi ; \
    if [ $$FDT = "32UI" ] ; then STR="unsigned int" ; fi ; \
    if [ $$FDT = "32SI" ] ; then STR="signed int" ; fi ; \
    if [ $$FDT = "32R" ] ; then STR="float" ; fi
    Yeugh! For C programs which need to be compiled for different datatypes. A necessary evil.

    ${FSLCONFDIR}/${FSLMACHTYPE}/systemvars.mk

    This file is filled with locally specific macros. Anyone porting FSL to another location ought to spend some time reviewing these and ensuring that they match his/her local preferences. The ANSI compilation flags (GNU_ANSI_FLAGS and SGI_ANSI_FLAGS) are included here as a hint/example of how one might approach customising the FSL makefiles for your site. An autoconfiguration is done on the first use of BUILD by running the script etc/autoconfig. This uses the program which to determine what programs (e.g. ginstall) are available. Supposedly safe values are used as backups, however if this does not work then the etc/autoconfig program should be moved (e.g. mv autoconfig autoconfig.disabled and the config/systemvars.mk file editted by hand.

    MacroFMRIBs default valueDescription
    RM/bin/rmHow to remove a file.
    CHMOD/bin/chmodThe program to use to change a files permisions.
    MKDIR/bin/mkdirThe program which creates new directories
    CP/bin/cpThe standard copy command (used for single files only).
    INSTALLginstall -pThe program which installs a file.
    TCLSHtclshThe tcl shell.
    RANLIBranlibThe ranlib command (if required - if not, set to echo).
    FSLML${FSLDIR}/bin/fslmlThe XML interpretter for documentation (no longer used).
    SHELL/bin/shThe Bourne shell (should not need to be changed).
    CCgccThe default C compiler.
    CXXc++The default C++ compiler.
    CSTATICFLAGS-staticThe options required for static linking (with the C compiler).
    CXXSTATICFLAGS-staticThe options required for static linking (with the C++ compiler).
    ARCHFLAGS-march=pentium -mcpu=pentiumFlags which best match your target platforms architecture.
    DEPENDFLAGS-MMThe flags which convert your chosen C compiler into a dependency builder.
    OPTFLAGS-O3 -fexpensive-optimizations ${ARCHFLAGS}Default optimizations.
    DBGFLAGSShould really be -g but is actually blank!Default debugging options.
    GNU_ANSI_FLAGS-Wall -ansi -pedanticANSI compile gcc.
    SGI_ANSI_FLAGS-ansi -fullwarnANSI compiler SGI cc.
    ANSI_FLAGS${GNU_ANSI_FLAGS}How to invoke the compiler in ANSI alone mode.

    ${FSLCONFDIR}/common/rules.mk

    The rules defining how to build, install and document any FSL project. The following table lists those targets which a programmer should be concerned about. There are other rules but they are mostly there to implement the

    RuleUsage instructions
    allThis is an empty rule. You can define it as you please.
    distcleanRemove all executable (as listed in XFILES, object, library, corey and dependency files from the current directory.
    cleanAs above but leaves behind executables.
    install Installs headers, libraries, scripts, etc., into ${FSLDEVDIR}


    David Flitney
    Mark Jenkinson
    Last modified: Mon Feb 24 08:34:37 GMT 2003