The ACC Build System
Introduction
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.
Prerequisites
- 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.
Example:
set(PREBUILD_ACTION ./generate_some_code.sh)
The mpmnet project uses this mechanism and can be consulted as an example.
Libraries
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(INC_DIRS
../include
../CesrBPM/include
include
)
set(SRC_DIRS
code
)
set(EXE_SPECS cmake.cesrv
)
include($ENV{ACC_BUILD_SYSTEM}/Master.cmake)
Programs
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(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ...") |
Set linker flags. |
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)
set(SRC_FILES
program/cesrv_cl.f90
)
set(LINK_LIBS
cesrv
mpm_utils
cesr_utils
nonlin_bpm
bmad
xsif
xrlf03
xrl
sim_utils
cbpmfio
CesrBPM
c_utils
mpmnet
recipes_f-90_LEPP
cbi_net
pgplot
xsif
forest
lapack95
lapack
blas
)
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:
CMakeLists.txt
cmake_minimum_required(VERSION $ENV{ACC_CMAKE_VERSION})
set(EXE_SPECS
cmake.show
)
include($ENV{ACC_BUILD_SYSTEM}/Master.cmake)
cmake.show
set(EXENAME show)
set(SRC_DIRS
code
)
set(LINK_LIBS
mpm_utils
genplt
mpmnet
cesr_utils
sim_utils
c_utils
)
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.
Examples
A working example of a simple Bmad Fortran 90 program and its associated build description files is presented here.
Building the Example
- Either configure the ON-Site environment or build a Distribution.
- Follow the instructions for the directory set up as outlined in the Code Development wiki page, substituting simple_bmad_program for project directory name.
- Download the simple_bmad_program.f90, CMakeLists.txt and cmake.simple_bmad_program files into your simple_bmad_program directory.
- Download the lat.bmad and layout.bmad data files into your simple_bmad_program directory.
- To build the production version of the executable (see the Build commands section of the ACC Build System wiki), type:
mk
- To run the example executable, type the below command from within the simple_bmad_programdirectory:
../production/bin/simple_bmad_program
- 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
Slaves:
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
simple_bmad_program.f90
program.f90
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
enddo
! 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
CMakeLists.txt
cmake_minimum_required(VERSION $ENV{ACC_CMAKE_VERSION})
set(EXE_SPECS
cmake.simple_bmad_program
)
include($ENV{ACC_BUILD_SYSTEM}/Master.cmake)
cmake.simple_bmad_program
set(EXENAME simple_bmad_program)
set (SRC_FILES
simple_bmad_program.f90
)
set (LINK_LIBS
bmad
xsif
xrlf03
xrl
sim_utils
recipes_f-90_LEPP
forest
)