This page provides details about the CMake build system. Files
processed by the top level CMakeLists.txt script are
listed in the TOC in chronological order.
Coding conventions are always a matter of choice. Nevertheless, the following rules should be considered:
ELSE(), ENDIF(),
ENDFOREACH(), etc. statements shall not repeat the
corresponding condition in IF(),
FOREACH(), etc.
FOREACH(_build ${DEAL_II_BUILD_TYPES})
#
# Set an appropriate keyword depending on target and build type:
#
IF(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "DebugRelease")
SET(_keyword "general")
ELSE()
IF(_build MATCHES DEBUG)
SET(_keyword "debug")
ELSE()
SET(_keyword "optimized")
ENDIF()
ENDIF()
ENDFOREACH()
LIST(APPEND CONFIG_LIBRARIES
${_keyword}
${CONFIG_LIBRARIES_${_build}}
)
SET_TARGET_PROPERTIES(${DEAL_II_BASE_NAME}${DEAL_II_${build}_SUFFIX}
PROPERTIES
VERSION ${VERSION}
SOVERSION ${VERSION}
LINK_FLAGS "${DEAL_II_LINKER_FLAGS_${build}}"
COMPILE_DEFINITIONS "${DEAL_II_DEFINITIONS};${DEAL_II_DEFINITIONS_${build}}"
COMPILE_FLAGS "${DEAL_II_CXX_FLAGS_${build}}"
)
CMake operates almost always with variables in global state. To guard against accidental overwrite of variables the following naming conventions must be followed at all times:
DEAL_II_.
(Global variables defined by CMake are usually prefixed by
CMAKE_.)
./CMakeLists.txt and ./cmake/setup_*.cmake
The very first configuration steps after some initial setup in
./CMakeLists.txt takes place in some
./cmake/setup_*.cmake files:
setup_cached_variables.cmake:
This sets up all cached variables prior to the call to
PROJECT(deal.II). For details see the comment at the
top. Furthermore, some bookkeeping for compiler and linker flags
takes place, see the section
about compile flags.
setup_deal_ii.cmake:
This file is included immediately after the call to
PROJECT(deal.II) and will set up all magic
numbers such as names, definitions, relative and absolute
paths used in the build system. Most of the definitions are
guarded with the help of the SET_IF_EMPTY macro so
that it is possible to override the values from the command line.
setup_compiler_flags.cmake
sets up a suitable set of default compile flag for a known
compiler by including the appropriate
setup_compiler_flags_*.cmake file. When adding new
flags or compiler support, please respect the following note
# # (./cmake/setup_compiler_flags.cmake) # # #################### # # FAT NOTE: # # #################### # # All configuration in setup_compiler_flags.cmake and # setup_compiler_flags_.cmake shall ONLY modify: # # CMAKE_CXX_FLAGS # DEAL_II_CXX_FLAGS_DEBUG # DEAL_II_CXX_FLAGS_RELEASE # DEAL_II_LINKER_FLAGS # DEAL_II_LINKER_FLAGS_DEBUG # DEAL_II_LINKER_FLAGS_RELEASE # # All modifications shall be guarded with the ENABLE_IF_SUPPORTED # or ENABLE_IF_LINKS macro, e.g. # # ENABLE_IF_SUPPORTED(CMAKE_CXX_FLAGS "-fpic") # ENABLE_IF_LINKS(DEAL_II_LINKER_FLAGS "-Wl,--as-needed") # # Compiler flags for platform dependent optimization (such as # -march=native) must always be guarded with # DEAL_II_ALLOW_PLATFORM_INTROSPECTION: # # IF(DEAL_II_ALLOW_PLATFORM_INTROSPECTION) # ENABLE_IF_SUPPORTED(CMAKE_CXX_FLAGS "-march=native") # ENDIF() # # Checks for compiler features (such as C++11 support) and compiler # specific bugs that # - usually set up further configuration (such as preprocessor # definitions) # - disable a specific flag for a specific compiler version. # # belong the corresponding file: # # ./cmake/checks/check_01_compiler_features.cmake # ./cmake/checks/check_01_cpu_features.cmake # ./cmake/checks/check_01_cxx_features.cmake # ./cmake/checks/check_01_system_features.cmake # ./cmake/checks/check_02_compiler_bugs.cmake #
./cmake/checks/check_*.cmake
The next step in the configuration process is to include all
checks residing under ./cmake/checks. Currently
there are:
./cmake/checks/check_01_compiler_features.cmake
- Search for support for compiler dependent features such as stack
trace support, demangler support, etc.
./cmake/checks/check_01_cpu_features.cmake
- Platform introspection for CPU features goes here and must be
guarded with DEAL_II_ALLOW_PLATFORM_INTROSPECTION
./cmake/checks/check_01_cxx_features.cmake
- Check for supported C++ language features such as sufficient C++11
support
./cmake/checks/check_01_system_features.cmake
- Checks for specific platform (Linux/Darwin/CYGWIN/Windows..)
features and support
./cmake/checks/check_02_compiler_bugs.cmake
- Check for compiler bugs
HAVE_<..>, resp.
DEAL_II_(HAVE|USE)_<..>. It is forbidden to
use a variable name starting with
DEAL_II_WITH_<..> because this prefix is
exclusively reserved for the feature mechanism described
below. For some tests it might be necessary to manipulate
global variables.
CHECK_CXX_SOURCE_COMPILES(source variable)
- Checks whether it is possible to compile _and_ link the code snippet
<source>. If successful, variable is set to 1.
CHECK_CXX_SOURCE_RUNS(source variable)
- variable is set to 1 if <source> could be successfully compiled and
linked and the resulting program ran and exited without error.
Avoid this macro outside of a DEAL_II_ALLOW_PLATFORM_INTROSPECTION
guard. A sensible fallback should be provided if the check cannot
be run (e.g. when cross compiling).
CHECK_CXX_COMPILER_BUG(source variable)
- Inverts the logic of CHECK_CXX_SOURCE_COMPILES(), i.e. variable is
set to 1 if it was not possible to compile and link <source>.
CHECK_INCLUDE_FILE_CXX(header variable)
- Check whether it is possible to compile and link a dummy program
including <header>.
CHECK_FUNCTION_EXISTS(function variable)
- Check for the existence of a function prototype with name
<function>. (Don't forget to specify the link libraries, see
below.) Use CHECK_CXX_SYMBOL_EXISTS to search for C++ function
definitions instead, if possible.
CHECK_CXX_SYMBOL_EXISTS(symbol header_file variable)
- Check for the existence of a symbol definition in the header_file
as well as for the presence in the current link interface
(Don't forget to specify the link libraries, see below.)
CHECK_CXX_COMPILER_FLAG(flag variable)
- Sets the variable to 1 if the compiler understands the flag.
CMAKE_REQUIRED_FLAGS. There are two small macros
that do this job nicely:
PUSH_TEST_FLAG("-Werror")
CHECK_CXX_SOURCE_COMPILES(...)
POP_TEST_FLAG()
CMAKE_REQUIRED_INCLUDES and
CMAKE_REQUIRED_LIBRARIES. It is best to append these
lists and later on reset CMAKE_REQUIRED_* (including
CMAKE_REQUIRED_FLAGS) to their default values:
LIST(APPEND CMAKE_REQUIRED_INCLUDES <a list of includes>) LIST(APPEND CMAKE_REQUIRED_LIBRARIES <a list of libraries>) CHECK_CXX_SOURCE_COMPILES(...) RESET_CMAKE_REQUIRED()
./cmake/modules/Find*.cmake
These are find modules for the configure_*.cmake files
and the CONFIGURE_FEATURE macro as will explained later.
It is crucial that a find module behaves correctly. Therefore, the
following rules are mandatory:
FIND_LIBRARY and
FIND_PATH calls. The results of this calls should be the
only cached variables.
FIND_PACKAGE_HANDLE_STANDARD_ARGS should be used for
setting FEATURE_FOUND as this already respects the
QUIET and REQUIRED keywords.
WARNING, SEND_ERROR or
FATAL_ERROR must be avoided (the only exception is
the REQUIRED keyword).
FEATURE_FOUND FEATURE_LIBRARIES FEATURE_INCLUDE_DIRS FEATURE_LINKER_FLAGS FEATURE_VERSION FEATURE_VERSION_MAJOR FEATURE_VERSION_MINOR FEATURE_VERSION_SUBMINORThere are obviously valid exceptions from this rule, though.
_<all lowercase>" or
"global" variables prefixed by FEATURE_ may be
altered. Do not set DEAL_II_* or CMAKE_*
variables directly!
FEATURE_DIR can be set up for
convenience. It is best to start the Find module by
SET_IF_EMPTY(FEATURE_DIR "$ENV{FEATURE_DIR}")
and use FEATURE_DIR as a hint. If the external
library could be found, hide it via
MARK_AS_ADVANCED, if the external library could not
be found, set a cache value:
SET(FEATURE_DIR "" CACHE PATH "An optional hint to a FEATURE directory")
./cmake/configure/configure_*.cmake The final step in the configuration phase is the setup of features (which refer to external or bundled libraries deal.II can optionally interface with.)
At bare minimum configure_<feature>.cmake
file for a feature just consists of a call to the
CONFIGURE_FEATURE(<FEATURE>) macro which is
implemented in
./cmake/macros/macro_configure_feature.cmake.
In this case the corresponding Find<FEATURE>.cmake
module is used to determine whether an external dependency can be
resolved or not. Depending on the current state of
DEAL_II_WITH_<FEATURE> (see
here) the variables
FEATURE_LIBRARIES FEATURE_INCLUDE_DIRS FEATURE_LINKER_FLAGSare appended to the set of global variables and
DEAL_II_WITH_<FEATURE> is set to
TRUE.
It is possible to override this default behaviour with the following variables and macros (all of them are optional and will be replaced by an appropriate default action if unset):
<FEATURE> means all caps,
<feature> means all lowercase
./cmake/configure/configure_<feature>.cmake:
FEATURE_<FEATURE>_DEPENDS (a variable)
- a variable which contains an optional list of other features
this feature depends on (and which have to be enabled for this feature
to work.) The features must be given with the full option toggle:
DEAL_II_WITH_[...]
FEATURE_<FEATURE>_FIND_EXTERNAL(var) (a macro)
- which should set var to TRUE if all dependencies for the feature are
fulfilled. In this case all necessary variables for
FEATURE_<FEATURE>_CONFIGURE_EXTERNAL must be set.
Otherwise var should remain unset.
If this macro is undefined, FIND_PACKAGE(<FEATURES>) is
called directly instead.
FEATURE_<FEATURE>_CONFIGURE_EXTERNAL() (a macro)
- which should setup all necessary configuration for the feature with
external dependencies. If something goes wrong this macro must
issue a FATAL_ERROR.
If this macro is undefined, the information provided in
<FEATURES>_LIBRARIES, <FEATURES>_INCLUDE_DIRS and
<FEATURES>_LINKER_FLAGS is used for the build.
FEATURE_<FEATURE>_CONFIGURE_BUNDLED() (a macro)
- which should setup all necessary configuration for the feature with
bundled source dependencies. If something goes wrong this macro must
issue a FATAL_ERROR.
FEATURE_<FEATURE>_ERROR_MESSAGE() (macro)
- which should print a meaningful error message (with FATAL_ERROR) for
the case that no external library was found (and bundled is not
allowed to be used.) If not defined, a suitable default error message
will be printed.
./bundled/CMakeLists.txt:
FEATURE_<FEATURE>_HAVE_BUNDLED (a boolean)
- which should either be set to TRUE if all necessary libraries of the
features comes bundled with deal.II and hence can be supported
without external dependencies, or unset.
DEAL_II_FORCE_BUNDLED_<FEATURE> (an option)
- If <feature> can be set up by bundled libraries, this
configuration option must be present to force a use of bundled
dependencies
FEATURE_<FEATURE>_BUNDLED_CONFIGURED is set to
TRUE the file ./bundled/CMakeLists.txt
must compile and install the bundled package appropriately.
The following list describes all global variables controlling the
build process and the visibility associated with it (internal use for
compiling deal.Ii, externally used variables will get exported in
deal.IIConfig.cmake). Lists should be manipulated with
LIST(APPEND ...), flags with ADD_FLAGS(...)
(or if it is necessary to guard them with
ENABLE_IF_SUPPORTED(...).)
_DEBUG or
_RELEASE: Used for all targets
<...>_DEBUG: additionally used for debug targets
<...>_RELEASE: additionally used for release targets
DEAL_II_LINKER_FLAGS
DEAL_II_LINKER_FLAGS_DEBUG
DEAL_II_LINKER_FLAGS_RELEASE
-std=c++11 (if available):
CMAKE_CXX_FLAGS
DEAL_II_CXX_FLAGS_DEBUG
DEAL_II_CXX_FLAGS_RELEASE
INCLUDE_DIRECTORIES(...)
-D<...>) for the compilation of the
deal.II library:
DEAL_II_DEFINITIONS
DEAL_II_DEFINITIONS_DEBUG
DEAL_II_DEFINITIONS_RELEASE
DEAL_II_EXTERNAL_LIBRARIES
DEAL_II_EXTERNAL_LIBRARIES_DEBUG
DEAL_II_EXTERNAL_LIBRARIES_RELEASE
DEAL_II_USER_DEFINITIONS
DEAL_II_USER_DEFINITIONS_DEBUG
DEAL_II_USER_DEFINITIONS_RELEASE
DEAL_II_USER_INCLUDE_DIRS
./include/deal.II/base/config.h.in config.h.in should only contain a minimum of
necessary compile definitions to avoid unnecessary recompilation if
configuration changes.
config.h.in should have a
prominent comment explaining it and should be grouped by file
exporting the definition.
./source/CMakeLists.txt
All parts of the library are organized into logical object libraries
with their respective sources lying under
./source/<foo>, or
./bundled/<foo>/<...>. The actual setup of
an object library happens within that subdirectories with the help of
two macros:
#
# Glob for all header files associated with the object target:
# As this list is only for cosmetic reasons, so that associated header
# files show up in IDEs, we don't manage an explicit list (with the
# trade-off to have to run "make rebuild_cache" when a new header file
# emerges...)
#
FILE(GLOB _header
${CMAKE_SOURCE_DIR}/include/deal.II/dofs/*.h
)
#
# A list of source files forming the object target:
#
SET(_src
...
dof_tools.cc
)
#
# A list of instantiations that must be expanded:
#
SET(_inst
...
dof_tools.inst.in
)
#
# The following macro will set up an obj_dofs.debug and
# obj_dofs.release target with appropriate compile flags and
# definitions for a simultaneous build of debug and release library.
# Furthermore, the object name will be stored in
# ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/deal_ii_objects_(debug/release)
# so that it is available in global scope.
#
# Header files and instatiation files (${_header}, ${_inst}) are added
# for cosmetic reasons, so that they show up in IDEs.
#
DEAL_II_ADD_LIBRARY(obj_dofs OBJECT ${_src} ${_header} ${_inst})
#
# This macro will set up an obj_dofs.inst target for expanding all
# files listed in ${inst_in_files}. Appropriate target dependencies
# will be added to obj_dofs.debug and obj_dofs.release.
#
EXPAND_INSTANTIATIONS(obj_dofs "${inst_in_files}")
Later, all object targets are collected in
./source/CMakeLists.txt to define the actual debug and
releases libraries. For further details, see
./source/CMakelists.txt and
./cmake/macros/macro_deal_ii_add_library.cmake.
./cmake/config/CMakeLists.txt
The final bits of configuration happens in
./cmake/config/CMakeLists.txt where the templates for
the project configuration deal.IIConfig.cmake and the
compatibility file Make.global_options get expanded.
Furthermore, the configuration for the template expansion mechanism
resides under ./cmake/config/template_arguments.in.