Simpatico  v1.10
5.1 Build System

5.2 Coding Standards (Next)

Simpatico is compiled using a system of unix makefiles. All development was done using gnu make (gmake).

Source directory

All C++ files for simpatico, including both header (*.h) and source (*.cpp) files, are in the simpatico/src/ directory tree. The header and source file for each class are in the same directory. The name of each C++ file is the same as the class name, followed by the extension .h or .cpp. All class names and corresponding file names are upper space camel (like Util::Vector or McMd::Species).

The src/util, src/simp, src/mcMd, src/ddMd, and src/tools directories each contain all the source and header files for a particular C++ namespace:

These five directories will be referred to in what follows as "namespace" level directories.

When the implementation of one or more classes in one namespace use class names defined in a second namespace, the first namespace will be said to "depend" upon the second. The following dependencies exist among the five namespaces:

The build system assumes that these are the only inter-namespace dependencies. These conventions must thus be respected by any new code added to the system.

The src/mcMd, src/ddMd, and src/tools directories each also contain one or more main program source files. The main programs mdSim.cpp and mcSim.cpp for single processor simulations are both in the src/mcMd directory. The main program ddSim.cpp for parallel MD simulations is in the src/ddMd directory. The main program mdPp.cpp for single-processor analysis is in the src/tools directory.

Each namespace level source directory contains a subdirectory named tests/ that contains unit tests for classes in the associated name space. These unit tests are not automatically compiled or run by the build system that compiles the source code.

Build directories

When source files from the src/ directory are compiled, the resulting object (*.o) files and other files generated by compilation are placed in a build directory. The simpatico build system can implement either an "out-of-source" build, in which the build directory tree is distinct from the src/ directory, or an "in-source-build", in which all generated files are placed in the src/ directory alongside the source files. Which occurs depends on what directory the "make" command is invoked from.

When make is invoked from the simpatico/ root directory, all programs are built "out-of-source". Two different subdirectories of the simpatico/obj directory are used to build parallel and serial programs. Invoking "make mcMd" from the root directory builds single processor versions of mcSim and mdSim in the bld/serial directory. Invoking "make tools" from the root directory builds the mdPp single-processor analysis program in the bld/serial directory. Invoking "make ddSim" from the root directory builds the ddSim parallel MD program in the bld/parallel directory. Invoking "make mcMd-mpi" builds multi-processor versions of mcSim and mdSim in the bld/parallel directory.

Any simpatico programs can also built in any build directory (i.e., in bld/serial, bld/parallel, or bld/src), by invoking "make" with the appropriate target (make mcMd, make mcMd-mpi, make ddMd, or make tools) from the root directory of the desired build directory. Specifically, any program can be build "in-source" by invoking "make" from the simpatico/src/ directory. When make is invoked from the root simpatico/ directory, the commands associated with the main makefile targets simply cd to either bld/serial (for serial programs) or bld/parallel (for parallel programs) and then invoke make recursively from the appropriate build directory.

The bld/serial and bld/parallel directories each contains a tree of subdirectories similar to that of the src/ directory. These two build directory trees are initially almost empty except for a few makefiles and makefile fragments (discussed below). Compiling a *.cpp source file located in any subdirectory of the simpatico/src directory tree creates a *.o object file with the same base name in the corresponding subdirectory of the build directory tree. In an in-source build, the src/ directory is also the build directory.

Compiling a source file also normally creates a dependency file with the same base name as the source file but with file name extension *.d. Each such dependency file contains a makefile target rule that lists all the files upon which the associated *.o object file depends, including all the header files that it includes. This dependency file is placed in the same directory as the corresonding object file, in the build directory tree.

Build configuration files

After the setup script has been run, but before any code has has been compiled, each of the three build directories (src/, bld/serial, and bld/parallel) contain the following files and subdirectories:

BLD_DIR/
makefile
config.mk
configure
util/
simp/
mcMd/
ddMd/
tools/

Here, we use the BLD_DIR to represent the path to a specific build directory. The purposes of the files in this directory are:

After setup but before compilation, each of the five namespace level subdirectories (util/, simp/, mcMd/, ddMd/, and tools/) of each build directory also contains a few makefile fragments with similar names, of the form:

namespace/
makefile
config.mk \tests
makefile

Here, we use "namespace/" to denote a namespace level directory name util/, simp/, mcMd/, ddMd/, or tools/. The purposes of these files are:

The makefile in each namespace level subdirectory contains an "all" target that compiles all of the source files in the corresponding namespace (or subdirectory) and builds a static library that contains all of the resulting objects.

After setup but before compilation, the bld/serial and bld/parallel directories are empty except for the files listed above. The src/ directory contains the same set of files alongside source files and other makefile fragments. The src/ directory and its namespace level sub-directories each also contain a file named compiler.mk_r, which is a default repository version of the corresponding config.mk file.

The config.mk files in each build directory and its namespace level subdirectories will be referred to in what follows as build configuration files. Each config.mk file is a makefile fragment that is created by the setup script by making a copy of the default config.mk_r version in the src/ directory and (in some cases) automatically editing a few path variables. The contents of the build configuration files in each build directory determine what options will be passed to the compiler when a program is built in that directory, and which features will be enabled or disabled in the resulting executable. The configuration files in different build directories are independent: Changing a configuration files in a build directory only affects code that is built in that directory. Users may modify the config.mk file, either manually or by using the ./configure script in the same build directory, but should avoid modifying the corresponding config.mk_r repository versions in the src/ directory.

The makefile system that is used to build the source code does not automatically compile or run the unit tests in the namespace/tests directory. Unit tests for each namespace may be compiled by cd'ing to the namespace/tests subdirectory of the relevant namespace-level directory, and invoking make from there. Entering "make all" compiles a program that can run all the unit tests for that namespace. Entering "make run" will run that test program.

Build directory config.mk file

The main config.mk in each build directory defines makefile variables that contain paths to the source, build and binary directories, and other variables that define the choice of compiler and various compiler options.

The following variables defined in the main config.mk file define paths:

In the config.mk file within each build directory, BLD_DIR should expand to the absolute path for that build directory. By default, BIN_DIR points to the simpatico/bin directory. The values of the above three variables are expressed in terms of a variable ROOT_DIR that contains the absolute path to the simpatico/ root directory. The correct value for ROOT_DIR is set by the setup script. Here is an example of the relevant part of the file bld/serial/config.mk:

ROOT_DIR=${HOME}/simpatico
SRC_DIR=$(ROOT_DIR)/src
BLD_DIR=$(ROOT_DIR)/bld/serial
BIN_DIR=$(ROOT_DIR)/bin

Here, for simplicity, we have assumed that the simpatico/ root directory is a subdirectory of the users home directory. In the actual file, this would be replaced by the literal absolute path to whatever parent directory contains the simpatico/ directory. In the config.mk files in the bld/parallel and src/ directories, the value of BLD_DIR would be set to ROOT_DIR/bld/parallel and ROOT_DIR/src, respectively.

Namespace directory config.mk files

The "config.mk" file in each of the namespace level subdirectories of each build directory contains definitions of makefile variables that control conditional compilation of specific features of the code. For example, the definition of a variable SIMP_ANGLE in the file simp/config.mk may be commented out to disable 3-body angle potentials or uncommented to enable angle potentials. Similarly, the definition of UTIL_DEBUG in the file util/config.mk can commented out to disable extra sanity checks that are intended for the debug version of the code, or uncommented to enable these checks.

Each namespace level config.mk file defines a variable with a name of the form NAMESPACE_DEFS, in which NAMESPACE represents an upper case form of the name of the associated namespace. Thus, util/config.mk defines a variable named UTIL_DEFS, simp/config.mk defines SIMP_DEFS, mcMd/config.mk defines MCMD_DEFS, and ddMd/config.mk defines DDMD_DEFS. Each such makefile variable expands to a (possibly empty) string of compiler options that define C++ preprocessor macros, using the compiler "-D" option. Thus for example, when angle potentials are enabled by uncommenting the definition of the makefile variable SIMP_ANGLE in the file BLD_DIR/simp/config.mk, the variable SIMP_DEFS will contain a string "-DSIMP_ANGLE" that, when passed to the compiler, defines a corresponding C++ preprocessor macro, also named SIMP_ANGLE.

Preprocessor macros that are defined in a particular namespace level config.mk file are only used in the source code of the associated C++ namespace and in any other namespaces that depends upon it. Thus for example, preprocessor macros defined by the MCMD_DEFS string only appear in the McMd namespce, but preprocessor macros defined by the UTIL_DEFS can appear in any namespace, since the Simp, McMd, DdMd, and Tools namespaces all depend upon the Util namespace.

The configure script

Each build directory also contains a bash script named "configure". This script may be used to edit the configuration files in that directory from the command line. The configure script must be invoked from the main build directory that contains the script, and uses specific command line options to enable or disable specific features. For example, the command to enable MPI is

./configure -m1

The corresponding command to disable MPI is "./configre -m0". Here, the -m option denotes MPI, while the argument 1 is used to enable MPI, or an argument 0 to disable MPI. The configure script in each build directory edits only the build configuration files in that directory tree, and thus only effects the configuration of programs that are built in that directory.

Root directory makefile

The makefile in the simpatico/ root directory contains five primary targets named "mcMd", "mcSim-mpi", "ddSim", "tools" and "all":

-"make mcMd" builds the single-processor mcSim and mdSim simulation programs.

-"make mcMd-mpi" builds multi-processor versions of mcSim and mdSim.

-"make ddMd" builds the ddSim parallel MD simulation program.

-"make tools" builds the mdPp single-processor MD postprocessing analysis program.

-"make all" build all of the above programs

The commands associated with these targets invoke make recursively: The "mcMd", "mcMd-mpi", "ddMd", and "tools" targets each invoke commands to cd (change directory) to the appropriate build directory (i.e., to bld/serial for serial programs and to bld/parallel for MPI programs) and then recursively invoke make with the same target name from within the appropriate build directory. The definitions of the main makefile targets in the root directory makefile thus look like this:

all:
make mcMd
make mcMd-mpi
make ddSim
mcMd:
cd bld/serial; make mcMd
mcMd-mpi:
cd bld/parallel; make mcMd-mpi
ddMd:
cd bld/parallel; make ddMd
tools:
cd bld/serial; make tools

The default "all" target simply invokes the other three targets, thus building all of the programs in the package.

Main build directory makefile

The main makefile in each build directory also contains primary targets named "mcMd", "mcMd-mpi", "ddMd" and "tools". Invoking make with one of these primary targets from any object file directory will cause the corresponding program or programs to be built in the build directory from which make was invoked, using the build configuration files in that directory. The result executable file or files are then installed in directory BIN_DIR (which is src/bin by default).

The primary "mcMd", "mcMd-mpi", "ddMd", and "tools" targets of the main makefile in each build directory are also recursive. Each of them invokes commands that first invokes the configure script to enable or disable MPI, as appropriate, then descends to the namespace level directory for each namespace that is required to build the target program or programs, and finally invokes "make all" from within each such namespace sub-directory. The key part of the main makefile file in each build directory thus looks like this:

mcMd:
./configure -m0
cd util; make all
cd inter; make all
cd mcMd; make all
mcMd-mpi:
./configure -m1
cd util; make all
cd inter; make all
cd mcMd; make all
ddMd:
./configure -m1
cd util; make all
cd inter; make all
cd ddMd; make all
tools:
./configure -m0
cd util; make all
cd inter; make all
cd tools; make all

The command "./configure -m0" or "./configure -m1" uses the configure script to either disable ("./configure -m0") or enable ("./configure -m1") conditional compilation of parts of the code that use an MPI library. Note that the only difference between the the "mcMd" and "mcMd-mpi" targets is that the "mcMd" target disables MPI before compiling any source files, while "mcMd-mpi" enables MPI before compiling. The ddMd target always enables MPI, because MPI is essential to the functioning of the ddSim target program.

Namespace directory makefiles

The makefile in each namespace level subdirectory of each build directory defines an "all" target. The "all" target compiles all of the source files in the corresponding subdirectory of src/, or the corresponding namespace.

The "all" target in each namespace level directory also creates a static library that contains the object files for all classes in the associated namespace. The base name of each such library is given by a prefix "lib" followed by the namespace level directory name with a file extension ".a". Each such library is placed in the corresponding namespace level build directory. For example, the makefile in the util/ subdirectory creates a static library that (by default) is named BLD_DIR/util/libutil.a. Executable files are built by linking main program files to these namespace level libraries.

The "all" targets of the makefiles in the mcMd, ddMd, and tools namespace level subdirectories also compile main programs and install the resulting executables in the BIN_DIR directory. Entering "make all" from the BLD_DIR/mcMd directory compiles and links the main programs src/mcMd/mcSim.cpp and src/mcMd/mdSim.cpp to create the mcSim and mdSim executables, in addition to compiling all of the required class files and aggregating the source files into a static library. Similarly, entering "make all" from the BLD_DIR/ddMd/ directory compiles and links src/ddMd/ddSim.cpp to create the ddSim executable.

Unlike higher level makefiles, the namespace level makefiles are not recursive, i.e., they do not recursively invoke make in yet lower level subdirectories. The "all" target in each namespace-level directory instead compiles all files in a list of source files for that namespace. This list is defined in a file named sources.mk.

Source file lists (sources.mk files)

Every subdirectory of src/ (other than the tests/ directories) contains a makefile fragment named "sources.mk". Each such file defines a variable that contains a list of the source files in that directory and all of its subdirectories (if any). In each such subdirectory of src/, this variable has a name of the form [directory]_, where "[directory]" represents a mangled form of the subdirectory name. Specifically, the [directory] string is constructed by taking the path from the src/ directory to the subdirectory of interest and replacing each "/" directory separator by an underscore ("_"). For example, the file src/util/sources.mk defines a variable util_ that expands to a list of all of the source files in the directory tree rooted at src/util. The file src/util/space/sources.mk defines a corresponding variable named util_space_. The value of the [directory]_ variable is a list of relative paths for all source files in the corresponding directory and its descendant subdirectories, in which the path to each source file is expressed relative to the simpatico/src/ directory.

The code that assigns a value to a [directory]_ source list variable is straightforward in directories that contain source files but no subdirectories, such as the util/space directory. For example, here is the definition of util_space_ from the file src/util/space/sources.mk:

util_space_=\
util/space/Grid.cpp \ util/space/IntVector.cpp \ util/space/Tensor.cpp \ util/space/Vector.cpp

The directory src/util/space contains four sources files named Grid.cpp, IntVector.cpp, Vector.cpp and Tensor.cpp, and has no subdirectories.

In source file directories that do contain subdirectories, however, the source file list is constructed by concatenating corresponding lists defined in the source.mk files of subdirectories. In this case, the "sources.mk" file in the parent directory must include the sources.mk files from all of subdirectories. The value of the [directory]_ variable for the parent directory is then constructed by concatenating values of the [subdirectory]_ variables, and then appending additional source files from the parent directory, if any. For example, here is the makefile code that defines the variable util_ in the file src/util/sources.mk:

# Include subdirectory sources.mk files
include $(SRC_DIR)/util/misc/sources.mk
include $(SRC_DIR)/util/format/sources.mk
include $(SRC_DIR)/util/containers/sources.mk
include $(SRC_DIR)/util/mpi/sources.mk
include $(SRC_DIR)/util/signal/sources.mk
include $(SRC_DIR)/util/param/sources.mk
include $(SRC_DIR)/util/math/sources.mk
include $(SRC_DIR)/util/space/sources.mk
include $(SRC_DIR)/util/random/sources.mk
include $(SRC_DIR)/util/boundary/sources.mk
include $(SRC_DIR)/util/crystal/sources.mk
include $(SRC_DIR)/util/ensembles/sources.mk
include $(SRC_DIR)/util/accumulators/sources.mk
include $(SRC_DIR)/util/archives/sources.mk
# Concatenate subdirectory source file lists
util_=$(util_misc_) $(util_format_) \
$(util_containers_) $(util_mpi_) \
$(util_signal_) $(util_param_) $(util_math_) \
$(util_space_) $(util_random_) $(util_boundary_) \
$(util_crystal_) $(util_ensembles_) \
$(util_accumulators_) $(util_archives_)

The first segment of the file is a set of include statements that include the sources.mk files from all subdirectories of src/util. The definition of util_ then simply concatenates the corresponding source file lists for all subdirectories.

The sources.mk file in each such subdirectory of src/ also defines two variables that expand into lists of absolute paths for all source files and all object file targets in that subdirectory and its subdirectories. These variables have names of the form [directory]_SRCS and [directory]_OBJS, respectively, where [directory] again represents the mangled directory name. Thus, for example, the file src/util/sources.mk defines variables named util_SRCS and util_OBJS, in addition to util_. The [directory]_SRCS and [directory]_OBJS variables are constructed by using the gmake "addprefix" function to add absolute paths for the source and build directories as prefixes to each relative path listed in the [directory]_ variable. The relevant lines in the file src/util/sources.mk look like this:

util_SRCS=\
$(addprefix $(SRC_DIR)/, $(util_))
util_OBJS=\
$(addprefix $(BLD_DIR)/, $(util_:.cpp=.o))

Here, SRC_DIR expands to the absolute path to the simpatico/src directory and BLD_DIR expands to the absolute path to the relevant build directory. Note that the only difference between the paths in a [directory]_ variable (e.g., util_) and those in a [directory]_SRCS variable (e.g., util_SRCS) is that the [directory]_ variable contains relative paths, relative to src/, while the [directory]_SRCS variable contains corresponding absolute paths.

Pattern rules (patterns.mk files)

Each namespace level subdirectory of the src/ directory has a makefile fragment named "patterns.mk". This file defines a pattern rule for compiling source files in that directory or namespace. The pattern rule has the same structure in all five namespace level directories. In each case, the rule looks like this:

$(BLD_DIR)/%.o:$(SRC_DIR)/%.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) $(DEFINES) -c -o $@ $<
ifdef MAKEDEP
$(MAKEDEP) $(INCLUDES) $(DEFINES) $(MAKE_DEPS) -S$(SRC_DIR) -B$(BLD_DIR) $<
endif

This target pattern creates a rule for creating an object file with file extension *.o in a subdirectory of the build directory BLD_DIR by compiling a *.cpp source file with the same base name in the corresponding subdirectory of the source directory SRC_DIR. The first command actually compiles the source file and creates the object file. The second command, which is within an ifdef MAKEDEP .. endif block, generates a dependency file with extension *.d as a side-effect of compilation.

The following variables used in the above pattern are defined in the main config.mk file file in the build directory from which make was invoked:

The same values are used for the above variables in all five namespaces. Two additional variables are defined within each patterns.mk file that are assigned different values in different namespaces. These are:

The DEFINES variable, if not empty, contains a series of preprocessor macro definitions, defined using the "-D" compiler option. Thus, for example, if debugging, bonds, and angles are enabled, and no other optional features, the value of DEFINES within the file src/simp/patterns.mk might expand to

DEFINES=-DUTIL_DEBUG -DSIMP_BOND -DSIMP_ANGLE

The definitions of DEFINES and MAKE_DEPS within the file src/simp/patterns.mk are shown below as an example:

# C preprocessor macro definitions
DEFINES=$(UTIL_DEFS) $(SIMP_DEFS)
# Dependencies of source files in src/simp on makefile fragments
MAKE_DEPS= -A$(BLD_DIR)/config.mk
MAKE_DEPS+= -A$(BLD_DIR)/util/config.mk
MAKE_DEPS+= -A$(BLD_DIR)/simp/config.mk

The DEFINES variable is constructing by concatenating the NAMESPACE_DEFS variables (UTIL_DEFS, SIMP_DEFS, etc.) for this namespace (i.e., SIMP_DEFS) and for all namespaces upon which this namespace depends (i.e., UTIL_DEFS). For the Simp namespace, this yields a concatenation of UTIL_DEFS and SIMP_DEFS. The resulting string contains all of the preprocessor definitions that are allowed to be used by code in this namespace.

The MAKE_DEPS variable contains a list of build configuration files whose contents can effect compilation of source code in this namespace. This list always contains the main config.mk file from the parent build directory, the config.mk file for the namespace of interest, and config.mk files for any namespace(s) upon which this namespace depends. For the Simp namespace, MAKE_DEPS thus contains paths to the config.mk files in the simp/ and util/ subdirectories. These build configuration files are added to the list of dependencies for every object file in this namespace because changes to these config.mk files can change which preprocessor macros are defined or which compiler options are set, and thus can change the contents of the resulting object files.

Dependency Files (*.d Files)

If automatic dependency generation is not disabled, a dependency file will be generated for each source file whenever the file is compiled, as a side effect of compilation. Each dependency file defines a makefile rule for constructing the corresponding object file. This rule can be used to determine when the source file needs to be recompiled as a result of changes in header files or other files upon which it depends. The rule consists of the name of the object file target followed by a colon and list of files upon which it depends, of the form

class.o: class.cpp class.h header1.h header2.h ....

The list of dependencies for each object (*.o) file target includes the corresponding source (*.cpp) file, all of the header files that this source file directly or indirectly includes. The end of this list also includes all of the configuration files specified by the MAKE_DEPS variable for the relevant namespace. Each such makefile rule only lists dependencies, but does not contain an explicit command, because the required compiler command is given implicitly by the appropriate pattern rule.

Though not shown in the above example, all paths to the target and its dependencies are actually given in dependency files as absolute paths.

Dependency files are created by the bash script simpatico/bin/makeDep. The pattern rules defined in the namespace level patterns.mk files apply the makeDep script to a source file whenever that file is compiled. The "makeDep" script works by calling the gnu g++ compiler with the -MM option to determine dependencies, and using a separate python script to edit the resulting file.

In each makefile at the namespace level and below, all relevant dependency files are included into the makefile by a command of the form

-include $([directory]_OBJS:.o=.d)

in which [directory] represents the mangled name of the directory containing the makefile. For example, the file src/mcMd/makefile contains a line

-include $(mcMd_OBJS:.o=.d)

This command attempts to include a *.d dependency file for each *.o object file in the object file list. The dash in front of "include" instructs "make" to continue quietly if no dependency file is found for any object file target.

Example: A Namespace Directory makefile

As an example of how the system works, here are the essential parts of the namespace level makefile from the directory bld/serial/simp. The actual makefile also includes "clean" and "veryclean" targets" that have been excluded for clarity. Corresponding makefiles in bld/parallel/simp and src/simp are identical:

BLD_DIR_REL =..
include $(BLD_DIR_REL)/config.mk
include $(BLD_DIR)/util/config.mk
include $(BLD_DIR)/simp/config.mk
include $(SRC_DIR)/simp/patterns.mk
include $(SRC_DIR)/simp/sources.mk
all: $(simp_OBJS) $(simp_LIB)
-include $(simp_OBJS:.o=.d)

This simplified makefile contains three blocks:

(1) The block of include statements at the top of this file include all of the relevant build configuration files, the appropriate patterns.mk file, and the appropriate source file lists. The main config.mk file must be included using a relative path BLD_DIR_REL_=.. to the parent build directory. The main config.mk file defines variables BLD_DIR and SRC_DIR that contain absolute paths to the object and source directories, which can be used in the remainder of this makefile, and in makefile fragments that it includes. Next, the makefile includes the namespace level config.mk files for this namespace and any namespaces that it depends on. In this example, it thus includes the simp/config.mk and util/config.mk files from the build directory, because the Simp namespace depends upon the Util namespace. Finally, the makefile includes the patterns.mk file and sources.mk file list from the associated namespace level source directory src/simp.

(2) The "all" target builds all of the object files in the Simp namespace, which are listed in the variable simp_OBJS, and builds the associated library, whose name given by the variable simp_LIB. The file simp/sources.mk defines both the object file list simp_OBJS and a target rule for building the library simp_LIB. The library name simp_LIB is defined in the namespace level configuration file simp/config.mk.

(3) The last line of the above makefile fragment instructs make to include all of the dependency files for all of the source files in this namespace. The syntax $(simp_OBJS:.o=.d) creates a list of vfiles in which the .o extension of each object file is replaced by a .d extension. The dash in front of the -include command tells make to continue quietly if any dependency file does not exist.

The first time "make all" is invoked in this directory, neither the object file nor the associated dependency files exist. In this case, since each object target file is absent, make knows that it must be built, and uses the pattern rule defined in simp/patterns.mk to create each object file listed in simp_OBJS. If "make all" is a called again from the same directory, however, make can use the information in the dependency files to determine which object files needs to be rebuilt as a result in changes in C++ or configuration files.

The target rule for library simp_LIB lists all of the object files in simp_OBJS as dependencies. The library will thus be built only after the object files are all built, and will automatically be rebuilt if any object file in the Simp namespace is rebuilt.

Namespace Directory makefiles with Executable Targets

The makefile for the simp/ namespace level directory, which we used above as an example, does not build any executable files. Corresponding makefiles for the mcMd/, ddMd/, and tools/ subdirectories of each build directory, however, also contain targets that that build executables. Each executable is built by linking an object file that is created by compiling a main program file to several namespace-level static libraries. For example, the mcSim and mdSim executables are created by compiling the main program source files src/mcMd/mcSim.cpp and src/mcMd/mdSim.cpp and then linking the resulting object files to static libraries from the mcMd/, simp/ and util/ build directories. The target rules for the final executables list the required static libraries as dependencies.

The fact that executable targets depend on libraries that are defined in other namespaces requires the following further changes to the structure of makefiles that contain executable targets:

Thus, for example, the mcMd/makefile in each build directory must include the sources.mk files from the simp/ and util/ subdirectories of the src/ directory, and must include all dependency files from corresponding subdirectories of BLD_DIR, in addition to files from the mcMd/ subdirectory. Inclusion of these additional files from other namespace level directories allows make to decide when any required library needs to be rebuilt, and provides instructions how to rebuild any required source file or library if necessary.

Subdirectory Makefiles

As a convenience for developers, every subdirectory src/ at the namespace level and below contains a makefile. The "all" target of each such src/ subdirectory makefile executes an in-source build of the files in that subdirectory and any descendant subdirectories. The structure of the makefiles in subdirectories of the namespace level directories is very similar to that of the namespace level makefiles, except for the absence of targets to build a library or executables.

During development, the most convenient way to test whether a source file that you have just modified compiles correctly is usually to just enter

> make all

from the directory that contains the new or newly modified source file. If automatic dependency generation is enabled, and if you only modify one class at a time, this will normally cause the build system to compile only the source file that you have just modified. If a directory contains more than one incomplete or broken file, you should temporarily comment out all but one of these files (the one you are working on) in the definition of the [directory]_ variable in the corresponding sources.mk file, and then uncomment each such file when you are ready to work on it.

The file name conventions used in the simpatico build system make it awkward for a user to explictly request compilation of a specific source file. The build system uses absolute paths for all source and object files. The "make" program is not smart enough to recognize when an absolute and relative path are equivalent. As a result, the only way explicitly request compilation of a specific source file is to use the absolute path to the object file as a makefile target. For example, if the absolute path to the root simpatico directory within a user account named "george" was "/home/george/simpatico/", you (or George) could compile the source file src/mcMd/simulation/Simulation.cpp in-source by entering

make /home/george/simpatico/src/mcMd/simulation/Simulation.o

or

make ~/simpatico/src/mcMd/simulation/Simulation.o

from either the src/mcMd/simulation or src/mcMd/ directory. Most programmers, however, are unwilling to repeatedly type absolute paths. This is why we recommend getting in the habit of simply using "make all" from the directory that contains the file of interest, and working on only one file at a time.


5 Developer Information (Up)         5.2 Coding Standards (Next)