The ACC Build System


The build system is simply a collection of scripts (based on cmake, python and bash) used by an Accelerator code developer to build projects against libraries in a ("on-site") Release or a ("off-site") Distribution. It will compile C, C++, and Fortran source code into object code and link into libraries and/or executables (programs).

The Overview and Definitions page gives information on the terminology used.

IAll syntax in build description files mentioned below conforms to the rules for CMake CMakeLists.txt files as found in the cmake documentation.

If you need to contact someone for help, please see the Help and Mailing List Information wiki page.


  • For building on Lab computer systems: Before proceeding with building software using this system, one must have their bash shell environment set up via the ACC environment setup procedure described in the Environment Setup wiki. This step provides several environment variables with the prefix ACC_ that inform the behavior of the build system.
  • For building on computers outside the Lab: Setup instructions are included in the INSTALL file included in the Bmad Distribution download.

Directory Setup

In order to build programs or libraries the first step is to create a base directory which will be called <BASE_DIR>. It is possible to have multiple base directories if, say, parallel versions of the same code are needed. For outside the Lab work it is recommended that <BASE_DIR> not be the root directory of the Distribution. This separates the Distribution code from code developed locally. This is only a recommendation and if the code under development is code in the Distribution it may be advantageous to work in the Distribution area.

The <BASE_DIR> will contain a set of one or more project directories. A project directory will be called <PROJ_DIR> = <BASE_DIR>/<PROJECT>.
  • A given project can be setup to build a library and/or one or several executables.
  • The source code and header files for a project can be in <PROJ_DIR> directly or may be put in some subdirectory or subdirectories of <PROJ_DIR>. There is no restriction on the directory structure of the directory tree of <PROJ_DIR> .
  • Production executables will be put in <BASE_DIR>/production/bin. These executables are made with the mk command. Production executables run faster than debug executables.
  • Debug executables will be put in the <BASE_DIR>/debug/bin. These executables are made with the mkd command. Debug executables do more error checking and have symbol information for use with a debugger.
  • Intermediate files are stored in <PROJ_DIR>/production and <PROJ_DIR>/debug. You never have to look at these files.

Building Code

To control how a project's source code is built, one composes or edits an existing script file named CMakeLists.txt. This file must appear in <PROJ_DIR> in order for the build system to recognize that directory as a project that can be processed.

An additional cmake.XXX script file is necessary for each program you wish to build, if any. Here XXX is generally the named after the program name. Thus, for example, the Tao program has an associated cmake.tao script file.

Example CMakeLists.txt and cmake.XXX files are given below. Additionally, such files can be found in a Distribution (if you are building outside the lab) or in a Release (if you are building on a Lab computer system).

After the script files have been constructed, using the mk or mkd command in <PROJ_DIR> will build everything.

The Build Commands

Command Action
mk Acts upon a build directory containing a CMakeLists.txt file to build production binaries.
mkd Acts upon a build directory containing a CMakeLists.txt file to build debug-equipped binaries.
mk[d] clean Will remove the object files and binaries of the production[debug] build type.
mk[d] cleaner Will remove the object files and binaries of the production[debug] build type, the generated build directory, the CMake cache file so as to force a CMake reconfiguration upon the next build request, and the ../config/<PROJECT> directory if one was created.
mk[d] obliterate CAUTION!! - Performs the "cleaner" operation in ALL project directories contained in the upper level directory tree and removes the upper level production[debug] directory. For example, If your current-working-directory is "/home/mybuild/bmad", typing "mk obliterate" will perform a "cleaner" on ALL build directories in "/home/mybuild" and removes "/home/mybuild/production". Please use this option carefully!!
mk[d] -j N Acts upon a build directory containing a CMakeLists.txt file to build production binaries using gmake to run in "N" parallel "jobs". The default is "2", setting ACC_SET_GMAKE_JOBS has the same effect.

Environment Variables That Control The Build Process

Variable Value Effect On Build Process
VERBOSE Y Display all compiler and linker commands and their output. This is a native feature supported by CMake and is also found in the official documentation.
ACC_BUILD_EXES Y Enable all executable targets. mk[d] will produce all executables listed in CMakeLists.txt. mk[d] <exe-name>-exe will now produce a single exe. This is the default and is part of the user's environment if they use the environment setup procedure noted in the "Prerequisites" section above.
ACC_ENABLE_SHARED Y Produce a shared object library if the project has CREATE_SHARED set to TRUE in the CMakeLists.txt file.
ACC_ENABLE_OPENMP N Enable OpenMP support during the build. See http://openmp.org, http://software.intel.com/en-us/articles/getting-started-with-openmp and http://gcc.gnu.org/onlinedocs/gfortran/OpenMP.html
ACC_ENABLE_MPI N Enable Open MPI support during the build. See http://www.open-mpi.org/doc/
ACC_ENABLE_GFORTRAN_OPTIMIZATION N Enable gfortran -O2 optimization support during the build - Type "gfortran -Q --help=optimizers -O2" to see what optimizations are enabled with the "-O2" flag. Ignored when "mkd" is used.
ACC_SET_GMAKE_JOBS 2 Configure gmake to execute that number of recipes or "jobs" at once, effectively running parallel compilations using that number of CPU cores. The default value is "2" and cannot be set lower than "1" - for an explanation of gmake "jobs", please see http://www.gnu.org/software/make/manual/html_node/Parallel.html.
ACC_SET_F_COMPILER ifort Configure the Build System to use the specified Fortran compiler. The default value is "ifort" and the only other acceptable value is "gfortran". Please note that end user use of this variable is NOT yet completely supported and will not work until support for ACC_SET_F_COMPILER is configured throughout the Build System and a gfortran version of the "release" and "packages" builds are made.
ACC_ENABLE_FPIC N Produce a shared object library.
ACC_BUILD_TEST_EXES N Produce "test" binaries, specified in "Set (TEST_EXE_SPECS)" in CMakeLists.txt.

General Options

Prebuild action: This allows for the user to specify a command to run immediately prior to each build. The prebuild action target allows for the user of the build system to request that a particular action is taken prior to building their project. This allows one to run a preprocessing or code generation tool whose product is required for the build process. The user must specify the path of a single command to run as a string in the variable PREBUILD_ACTION. If this variable is present, the build system will run the specified command in a shell prior to starting the build process. The command cannot have any arguments but it may generate console output along with doing other tasks. The output it generates will show up as part of the output produced during the build process.

set(PREBUILD_ACTION ./generate_some_code.sh)

The mpmnet project uses this mechanism and can be consulted as an example.


Provided a CmakeLists.txt build description file exists in the project directory that you wish to build, invoking the command mk will build a “production” binary which is suitable for everyday running. The command mkd will build a “debug” binary that contains debugging symbols for use in an interactive debugger.

The object and other support files are kept in a separate build tree automatically created within the project directory called production or debug, depending on the build type requested.

Build Modifier Function
set(LIBNAME <name> ) Set the name of the library to be produced-- libLIBNAME.a (libLIBNAME.so if shared object libraries have been requested and enabled.)
set(INC_DIRS ... ) Define the collection of include directories to search for header files during compilation.
set(SRC_DIRS ... ) Define the collection of directories containing source files with supported filename extensions to incorporate into the build.
set(EXE_SPECS ... ) Define the collection of executable build description files. One build description file per standalone application desired.
set(TEST_EXE_SPECS ... ) Define the collection of test executable build description files. One build description file per standalone application desired. You must export ACC_BUILD_TEST_EXE=Y to create executables for files in the TEST_EXE_SPECS list. Use this list to prevent problems with the nightly build of all programs in EXE_SPECS.
set(SHARED_DEPS ...) Define list of libraries the library to build depends upon. This is required for proper shared-object linking at run-time.

To control the building of a library, create or copy a file named CmakeLists.txt into <PROJ_DIR>. An example CmakeLists.txt file is shown and annotated here.
The bold text is boilerplate and must appear verbatim. The remaining sections are meant to be modified by the user to configure the details of the build. This example is used to build the libcesrv.a static library file and to allow for building the cesrv_cl program.

set(LIBNAME cesrv)
cmake_minimum_required(VERSION $ENV{ACC_CMAKE_VERSION})



set(EXE_SPECS cmake.cesrv



Build Modifier Function
set(EXENAME <exename> ) Assign a name to the program to produce.
set(SRC_FILES ... ) Define the collection of explicit filename paths (relative to the project directory root, or an absolute path) to compile when building the program.
file(GLOB SRC_FILES ...) Like set(SRC_FILES ...) but here can use wild card characters instead of having to list each file.
set(SRC_DIRS ... ) Define the collection of directories containing source files with supported filename extensions to incorporate into the program. Can be used in conjunction with SRC_FILES.
set(LINK_DIRS ... ) Can hold a list of additional paths to search for the libraries mentioned in the LINK_LIBS list mentioned below.
set(LINK_LIBS ... ) Define the collection of static libraries needed for linking of the program. This list must be ordered with dependent libraries appearing BELOW the libraries that they support.

I.e. higher level libraries with the most abstraction appear earlier in the list, and lower level libraries appear later.
set(CFLAGS "..." ) Quote-delimited string containing C compiler flags to use when building the files specified using SRC_FILES and/or SRC_DIRS
set(FFLAGS "..." ) Quote-delimited string containing Fortran compiler flags to use when building the files specified using SRC_FILES and/or SRC_DIRS
set(SHARED_LINK_LIBS ... ) Define the collection of shared (dynamic) libraries needed for linking of the program. This list is not order dependent.
set(EXTRA_SHARED_LINK_LIBS ... ) Similar to SHARED_LINK_LIBS except these libraries will not get linked in except if the associated library is being built shared. In particular, this is used with Tao which, when the Tao library is built shared, has a additional set of libraries to link to.
set(LINKER_LANGUAGE_PROP <lang> ) Set the language of the main program. This is used when mixing code of differnt languages and CMake is not correctly figuring out what language the main program is. Use <lang> = Fortran if the main program is Fortran.
set(IMPLICIT_LINK_LIBS <lang> ) When linking an executable using differnet linker then the one used to build libraries in the LINK_LIBS statement, the user must set IMPLICIT_LINK_LIBS to the language of the libraries in LINK_LIBS. Use <lang> = Fortran if the Libraries were built with Fortran.
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES false) Prevents automatic use of C++ linker. This prevents a problem when building a library and a program using the same CMakeLists.txt file where the library has a C/C++ routine but the program has a Fortran main program.
Separate flag lists can be specified for a library and each executable.

To control the building of an executable, create or copy a file named after the program to produce into <PROJ_DIR>. In this example, the supplementary build description file is called cmake.cesrv which will be used to produce the executable file cesrv_cl.

set(EXENAME cesrv_cl)


This allows the creation of all executables for which <executable>.cmake files have been created and for which references are present in the
SET (EXE_SPECS <spec1> <spec2>...) line.

Individual executables can be created by using the name of their target after the mk[mkd] command. Program target names have an “-exe” appended to them.
I.e. mk <program_name>-exe.

Even if you wish to only produce a single program with no associated library, you must always have a CMakeLists.txt file. This will be minimal and only reference the <program>.cmake file that describes how to build the desired program.

The file(GLOB SRC_FILES ...) construct can be used in place of the set(SRC_FILES ...) construct. Globbing allows for the standard Unix wild card characters to be used instead of having to list each file to be compiled. There are advantages and disadvantages to this. Globbing can make the .cmake file shorter but listing each file individually ensures that only the files that are needed are used.

Program Example

For the 'show' program, for example, a minimum of two files are required:


cmake_minimum_required(VERSION $ENV{ACC_CMAKE_VERSION})




set(EXENAME show)



Noteworthy Default Behaviors

Reserved Directory Names

Any directory with the name "config" will be automatically have its contents copied to the directory <BASE_DIR>/config/<PROJECT_DIR>

For example:

You are building in /home/smith/project1

project1/config/... exists with some files and subdirectories.

The build process will create /home/smith/config/project1/... filled with the exact contents of the project's config directory.

Forbidden directory names:

You may not have a subdirectory within a project with the name "production" or "debug".

These are reserved by the build system and directories with those names are automatically created to hold administrative data and intermediate build products.

Matlab MEX Files

For lab builds: If a project is configured to produce a shared object library AND a Makefile.mex file is present in the project directory that can be used to produce Matlab MEX wrappers, when the ACC_ENABLE_SHARED variable is set affirmatively, a build request will build the project as normally done and will then execute a gmake process upon the Makefile.mex file in order to produce those MEX files.

Include Directory Search behavior

NOTE: The possibility exists that if a developer deletes a locally built copy of a library, and initiates a build that requires that library while leaving the local source tree and include files intact, the build system will perform the divergent action of linking against the release version of the library while employing the header file information from the user's LOCAL source tree.

One may prevent confusion by deleting local source trees as soon as they are no longer needed.

Build Errors For Executables

If a project has more than one executable being requested in the CMakeLists.txt file and an error occurs when compiling or linking the code for that executable, the build process will terminate immediately and not attempt to build executables mentioned after the failed one in the list of EXE_SPECS. To force the building of one of the skipped executables, one may run mk[d] <executable_name>-exe for each executable desired.


A working example of a simple Bmad Fortran 90 program and its associated build description files is presented here.

Building the Example

  1. Either configure the ON-Site environment or build a Distribution.
  2. Follow the instructions for the directory set up as outlined in the Code Development wiki page, substituting simple_bmad_program for project directory name.
  3. Download the simple_bmad_program.f90, CMakeLists.txt and cmake.simple_bmad_program files into your simple_bmad_program directory.
  4. Download the lat.bmad and layout.bmad data files into your simple_bmad_program directory.
  5. To build the production version of the executable (see the Build commands section of the ACC Build System wiki), type:
  6. To run the example executable, type the below command from within the simple_bmad_programdirectory:
  7. To see the correct resulting output:
      Ix  Name              Ele_type                   S      Beta_a
       0  BEGINNING         BEGINNING_ELE                                 0.0000      0.9379
       1  IP_L0             MARKER                                        0.0000      0.9379
       2  CLEO_SOL#3        SOLENOID                                      0.6223      1.3472
       3  DET_00W           MARKER                                        0.6223      1.3472
       4  CLEO_SOL#4        SOLENOID                                      0.6380      1.3682
       5  Q00W\CLEO_SOL     SOL_QUAD                                      1.7550      8.0285
       6  Q00W#1            QUADRUPOLE                                    2.1628     16.8607
       7  D003              DRIFT                                         2.4934     28.5769
       8  DET_01W           MARKER                                        2.4934     28.5769
       9  D004              DRIFT                                         2.9240     48.4524
      10  Q01W              QUADRUPOLE                                    3.8740     66.8800
     ! Information on element: CLEO_SOL
      Element #              872
      Element Name: CLEO_SOL
      Key: SOLENOID
      S:              1.75500
      Ref_time:  5.854050E-09
      Attribute values [Only non-zero/non-default values shown]:
          1   L                            =  3.5100000E+00
          5   KS                           = -8.4023386E-02
         31   L_HARD_EDGE                  =  3.5100000E+00
         49   BS_FIELD                     = -1.4823578E+00
         50   DELTA_REF_TIME               =  1.1708100E-08
         53   P0C                          =  5.2890000E+09,          BETA            =  0.999999995
         54   E_TOT                        =  5.2890000E+09
         66   NUM_STEPS                    = 18
         67   DS_STEP                      =  2.0000000E-01
              TRACKING_METHOD              =  Bmad_Standard
              MAT6_CALC_METHOD             =  Bmad_Standard
              SPIN_TRACKING_METHOD         =  Bmad_Standard
              PTC_INTEGRATION_TYPE         =  Matrix_Kick
              FIELD_CALC                   =  Bmad_Standard
              APERTURE_AT                  =  Exit_End
              OFFSET_MOVES_APERTURE        =  F
              SYMPLECTIFY                  =  F
              FIELD_MASTER                 =  F
              CSR_CALC_ON                  =  T
     Slave_status: FREE
     Lord_status:  SUPER_LORD
        Name                   Type                Index
        Q00E\CLEO_SOL          SOL_QUAD            865
        CLEO_SOL#1             SOLENOID            866
        CLEO_SOL#2             SOLENOID            868
        CLEO_SOL#3             SOLENOID            2
        CLEO_SOL#4             SOLENOID            4
        Q00W\CLEO_SOL          SOL_QUAD            5

View Example Files Source Code


program test

use bmad                 ! Define the structures we need to know about.
implicit none
type (lat_struct), target :: lat   ! This structure holds the lattice info
type (ele_struct), pointer :: ele, cleo
type (ele_pointer_struct), allocatable :: eles(:)
integer i, ix, n_loc
logical err

! Programs should always implement "intelligent bookkeeping".
bmad_com%auto_bookkeeper = .false.

! Read in a lattice, and modify the ks solenoid strength of the 
! element named "cleo_sol".

call bmad_parser ("lat.bmad", lat)  ! Read in a lattice.

call lat_ele_locator ('CLEO_SOL', lat, eles, n_loc, err)  ! Find element
cleo => eles(1)%ele                        ! Point to cleo_sol element.
cleo%value(ks$) = cleo%value(ks$) + 0.001  ! Modify ks component.
call set_flags_for_changed_attribute (cleo, cleo%value(ks$))
call lat_make_mat6 (lat, cleo%ix_ele)      ! Remake transfer matrix

! Calculate starting Twiss params if the lattice is closed, 
! and then propagate the Twiss parameters through the lattice.

if (lat%param%geometry == closed$) call twiss_at_start (lat)
call twiss_propagate_all (lat)      ! Propagate Twiss parameters

! Print info on the first 11 elements

print *, ' Ix  Name              Ele_type                   S      Beta_a'
do i = 0, 10
  ele => lat%ele(i)
  print '(i4,2x,a16,2x,a,2f12.4)', i, ele%name, key_name(ele%key), ele%s, ele%a%beta

! print information on the CLEO_SOL element.

print *
print *, '!---------------------------------------------------------'
print *, '! Information on element: CLEO_SOL'
print *
call type_ele (cleo, .false., 0, .false., 0, .true.)

deallocate (eles)

end program


cmake_minimum_required(VERSION $ENV{ACC_CMAKE_VERSION})




set(EXENAME simple_bmad_program)


Topic revision: r26 - 19 Apr 2024, DavidSagan

  • ACC/ACL Web

  • CLASSE Computing Info

Create personal sidebar

This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding CLASSE Wiki? Send feedback