.. rubric:: Generic TriBITS Project, Build, Test, and Install Reference Guide :Author: Roscoe A. Bartlett :Contact: bartlett.roscoe@gmail.com :Date: |date| :Version: .. include:: ../copied_files/tribits/doc/build_ref/TribitsGitVersion.txt .. |date| date:: :Abstract: This document is generated from the generic template body document ``TribitsBuildReferenceBody.rst`` and provides a general project-independent reference on how to configure, build, test, and install a project that uses the TriBITS CMake build system. The primary audience of this particular build of this document are TriBITS project developers themselves. A project-specific version of this document should be created and accessed by users of a particular TriBITS-based project. .. sectnum:: .. contents:: Introduction ============ This document is created using the script ``create-build-ref.sh`` in this directory which just runs:: $ ./create-project-build-ref.py \ --project-name="" \ --project-template-file=TribitsBuildReferenceTemplate.rst \ --file-base=TribitsBuildReference In a project-specific version, ```` is replaced with the actual project name (e.g. ``Trilinos``). This version of the generated document is referred to by the general TribitsDeveloperGuide.[rst,html,pdf] document. Below are given genetic versions of the sections that show up in every project-specific build of this document. .. Common references to other documents .. _TriBITS Users Guide and Reference: TribitsUsersGuide.html .. _Package Dependencies and Enable/Disable Logic: TribitsUsersGuide.html#package-dependencies-and-enable-disable-logic .. _TriBITS Dependency Handling Behaviors: TribitsUsersGuide.html#tribits-dependency-handling-behaviors .. _tribits_tpl_find_include_dirs_and_libraries(): TribitsUsersGuide.html#tribits-tpl-find-include-dirs-and-libraries .. _tribits_ctest_driver(): TribitsUsersGuide.html#tribits-ctest-driver .. _Ninja: https://ninja-build.org .. _CMake Ninja Fortran Support: https://cmake.org/cmake/help/latest/generator/Ninja.html .. _CTest Resource Allocation System: https://cmake.org/cmake/help/latest/manual/ctest.1.html#resource-allocation .. _CTest Resource Specification File: https://cmake.org/cmake/help/latest/manual/ctest.1.html#ctest-resource-specification-file .. _CTest Resource Allocation Environment Variables: https://cmake.org/cmake/help/latest/manual/ctest.1.html#environment-variables .. _RESOURCE_GROUPS: https://cmake.org/cmake/help/latest/prop_test/RESOURCE_GROUPS.html#prop_test:RESOURCE_GROUPS Getting set up to use CMake =========================== Before one can configure to be built, one must first obtain a version of CMake on the system newer than 3.23.0 This guide assumes that once CMake is installed that it will be in the default path with the name ``cmake``. Installing a binary release of CMake [casual users] --------------------------------------------------- Download and install the binary (version 3.23.0 or greater is recommended) from: http://www.cmake.org/cmake/resources/software.html Installing CMake from source [developers and experienced users] --------------------------------------------------------------- If you have access to the git repositories (which which includes a snapshot of TriBITS), then install CMake with:: $ cd / $ TRIBITS_BASE_DIR=/cmake/tribits $ $TRIBITS_BASE_DIR/devtools_install/install-cmake.py \ --install-dir-base= --cmake-version=X.Y.Z \ --do-all This will result in cmake and related CMake tools being installed in ``/cmake-X.Y.Z/bin/`` (see the instructions printed at the end on how to update your ``PATH`` env var). To get help for installing CMake with this script use:: $ $TRIBITS_BASE_DIR/devtools_install/install-cmake.py --help NOTE: You will want to read the help message about how to install CMake to share with other users and maintainers and how to install with sudo if needed. Installing Ninja from Source ---------------------------- The `Ninja`_ tool allows for much faster parallel builds for some large CMake projects and performs much faster dependency analysis than the Makefiles back-end build system. It also provides some other nice features like ``ninja -n -d explain`` to show why the build system decides to (re)build the targets that it decides to build. As of Ninja 1.10+, Fortran support is part of the official GitHub version of Ninja as can be obtained from: https://github.com/ninja-build/ninja/releases (see `CMake Ninja Fortran Support`_). Ninja is easy to install from source on almost any machine. On Unix/Linux systems it is as simple as ``configure --prefix=``, ``make`` and ``make install``. Getting CMake Help ================== Finding CMake help at the website --------------------------------- http://www.cmake.org Building CMake help locally --------------------------- To get help on CMake input options, run:: $ cmake --help To get help on a single CMake function, run:: $ cmake --help-command To generate the entire documentation at once, run:: $ cmake --help-full cmake.help.html (Open your web browser to the file cmake.help.html) Configuring (Makefile, Ninja and other Generators) =================================================== CMake supports a number of different build generators (e.g. Ninja, Eclipse, XCode, MS Visual Studio, etc.) but the primary generator most people use on Unix/Linux system is ``make`` (using the default cmake option ``-G"Unix Makefiles"``) and CMake generated Makefiles. Another (increasingly) popular generator is Ninja (using cmake option ``-GNinja``). Most of the material in this section applies to all generators but most experience is for the Makefiles and Ninja generators. Setting up a build directory ---------------------------- In order to configure, one must set up a build directory. does **not** support in-source builds so the build tree must be separate from the source tree. The build tree can be created under the source tree such as with:: $ cd / $ mkdir $ cd / but it is generally recommended to create a build directory parallel from the source tree such as with:: / / / NOTE: If you mistakenly try to configure for an in-source build (e.g. with 'cmake .') you will get an error message and instructions on how to resolve the problem by deleting the generated CMakeCache.txt file (and other generated files) and then follow directions on how to create a different build directory as shown above. Basic configuration ------------------- A few different approaches for configuring are given below. * `Create a do-configure script [Recommended]`_ * `Create a *.cmake file and point to it [Most Recommended]`_ * `Using the QT CMake configuration GUI`_ .. _Create a do-configure script [Recommended]: a) Create a 'do-configure' script such as [Recommended]:: #!/bin/bash cmake \ -D CMAKE_BUILD_TYPE=DEBUG \ -D _ENABLE_TESTS=ON \ "$@" \ ${SOURCE_BASE} and then run it with:: ./do-configure [OTHER OPTIONS] -D_ENABLE_=ON where ```` is a valid Package name (see above), etc. and ``SOURCE_BASE`` is set to the source base directory (or your can just give it explicitly in the script). See ``/sampleScripts/*`` for examples of real ``do-configure`` scripts for different platforms. NOTE: If one has already configured once and one needs to configure from scratch (needs to wipe clean defaults for cache variables, updates compilers, other types of changes) then one will want to delete the local CMakeCache.txt and other CMake-generated files before configuring again (see `Reconfiguring completely from scratch`_). .. __CONFIGURE_OPTIONS_FILE: .. _Create a *.cmake file and point to it [Most Recommended]: b) Create a ``*.cmake`` file and point to it [Most Recommended]. Create a do-configure script like:: #!/bin/bash cmake \ -D _CONFIGURE_OPTIONS_FILE=MyConfigureOptions.cmake \ -D _ENABLE_TESTS=ON \ "$@" \ ${SOURCE_BASE} where MyConfigureOptions.cmake (in the current working directory) might look like:: set(CMAKE_BUILD_TYPE DEBUG CACHE STRING "Set in MyConfigureOptions.cmake") set(_ENABLE_CHECKED_STL ON CACHE BOOL "Set in MyConfigureOptions.cmake") set(BUILD_SHARED_LIBS ON CACHE BOOL "Set in MyConfigureOptions.cmake") ... Using a configuration fragment ``*.cmake`` file allows for better reuse of configure options across different configure scripts and better version control of configure options. Using the comment ``"Set in MyConfigureOptions.cmake"`` makes it easy see where that variable got set when looking an the generated ``CMakeCache.txt`` file. Also, when this ``*.cmake`` fragment file changes, CMake will automatically trigger a reconfigure during a make (because it knows about the file and will check its time stamp, unlike when using ``-C .cmake``, see below). One can use the ``FORCE`` option in the ``set()`` commands shown above and that will override any value of the options that might already be set (but when using ``-C`` to include this forced ``set( ... FORCE)`` will only override the value if the file with the ``set()`` is listed after the ``-D=`` command-line option). However, that will not allow the user to override the options on the CMake command-line using ``-D=`` so it is generally **not** desired to use ``FORCE``. One can also pass in a list of configuration fragment files separated by commas ``','`` which will be read in the order they are given as:: -D _CONFIGURE_OPTIONS_FILE=.cmake,.cmake,... One can read in configure option files under the project source directory by using the type ``STRING`` such as with:: -D _CONFIGURE_OPTIONS_FILE:STRING=cmake/MpiConfig1.cmake In this case, the relative paths will be with respect to the project base source directory, not the current working directory (unlike when using ``-C .cmake``, see below). (By specifying the type ``STRING``, one turns off CMake interpretation as a ``FILEPATH``. Otherwise, the type ``FILEPATH`` causes CMake to always interpret relative paths with respect to the current working directory and set the absolute path). Note that CMake options files can also be read in using the built-in CMake argument ``-C .cmake`` as:: cmake -C .cmake -C .cmake ... [other options] \ ${SOURCE_BASE} However, there are some differences to using ``_CONFIGURE_OPTIONS_FILE`` vs. ``-C`` to read in ``*.cmake`` files to be aware of as described below: 1) One can use ``-D_CONFIGURE_OPTIONS_FILE:STRING=/.cmake`` with a relative path w.r.t. to the source tree to make it easier to point to options files in the project source. Using ``cmake -C /.cmake`` would require having to give the absolute path ```` or a longer relative path from the build directory back to the source directory. Having to give the absolute path to files in the source tree complicates configure scripts in some cases (i.e. where the project source directory location may not be known or easy to get). 2) When configuration files are read in using ``_CONFIGURE_OPTIONS_FILE``, they will get reprocessed on every reconfigure (such as when reconfigure happens automatically when running ``make``). That means that if options change in those included ``*.cmake`` files from the initial configure, then those updated options will get automatically picked up in a reconfigure. But when processing ``*.cmake`` files using the built-in ``-C .cmake`` argument, updated options will not get set. Therefore, if one wants to have the ``*.cmake`` files automatically be reprocessed, then one should use ``_CONFIGURE_OPTIONS_FILE``. But if one does not want to have the contents of the ``.cmake`` file reread on reconfigures, then one would want to use ``-C .cmake``. 3) When using ``_CONFIGURE_OPTIONS_FILE``, one can create and use parameterized ``*.cmake`` files that can be used with multiple TriBITS projects. For example, one can have set statements like ``set(${PROJECT_NAME}_ENABLE_Fortran OFF ...)`` since ``PROJECT_NAME`` is known before the file is included. One cannot do that with ``-C`` and instead would have to provide the full variables names specific for a given TriBITS project. 4) When using ``_CONFIGURE_OPTIONS_FILE``, non-cache project-level variables can be set in a ``*.cmake`` file that will impact the configuration. When using the ``-C`` option, only variables set with ``set( CACHE ...)`` will impact the configuration. 5) Cache variables forced set with ``set( CACHE "" FORCE)`` in a ``.cmake`` file pulled in with ``-C .cmake`` will only override a cache variable ``-D=`` passed on the command-line if the ``-C .cmake`` argument comes **after** the ``-D=`` argument (i.e. ``cmake -D= -C .cmake``). Otherwise, if the order of the ``-D`` and ``-C`` arguments is reversed (i.e. ``cmake -C .cmake -D=``) then the forced ``set()`` statement **WILL NOT** override the cache var set on the command-line with ``-D=``. However, note that a forced ``set()`` statement **WILL** override other cache vars set with non-forced ``set()`` statements ``set( CACHE "")`` in the same ``*.cmake`` file or in previously read ``-C .cmake`` files included on the command-line before the file ``-C .cmake``. Alternatively, if the file is pulled in with ``-D_CONFIGURE_OPTIONS_FILE=.cmake``, then a ``set( CACHE "" FORCE)`` statement in a ``.cmake`` **WILL** override a cache variable passed in on the command-line ``-D=`` no matter the order of the arguments ``-D_CONFIGURE_OPTIONS_FILE=.cmake`` and ``-D=``. (This is because the file ``.cmake`` is included as part of the processing of the project's top-level ``CMakeLists.txt`` file.) 6) However, the ``*.cmake`` files specified by ``_CONFIGURE_OPTIONS_FILE`` will only get read in **after** the project's ``ProjectName.cmake`` and other ``set()`` statements are called at the top of the project's top-level ``CMakeLists.txt`` file. So any CMake cache variables that are set in this early CMake code will override cache defaults set in the included ``*.cmake`` file. (This is why TriBITS projects must be careful **not** to set default values for cache variables directly like this but instead should set indirect ``__DEFAULT`` non-cache variables.) But when a ``*.cmake`` file is read in using ``-C``, then the ``set()`` statements in those files will get processed before any in the project's ``CMakeLists.txt`` file. So be careful about this difference in behavior and carefully watch cache variable values actually set in the generated ``CMakeCache.txt`` file. In other words, the context and impact of what get be set from a ``*.cmake`` file read in through the built-in CMake ``-C`` argument is more limited while the code listed in the ``*.cmake`` file pulled in with ``-D_CONFIGURE_OPTIONS_FILE=.cmake`` behaves just like regular CMake statements executed in the project's top-level ``CMakeLists.txt`` file. In addition, any forced set statements in a ``*.cmake`` file pulled in with ``-C`` **may or may not** override cache vars sets on the command-line with ``-D=`` depending on the order of the ``-C`` and ``-D`` options. (There is no order dependency for ``*.cmake`` files passed in through ``-D_CONFIGURE_OPTIONS_FILE=.cmake``.) .. _Using the QT CMake configuration GUI: c) Using the QT CMake configuration GUI: On systems where the QT CMake GUI is installed (e.g. Windows) the CMake GUI can be a nice way to configure (or just explore options) if you are a user. To make your configuration easily repeatable, you might want to create a fragment file and just load it by setting `_CONFIGURE_OPTIONS_FILE`_ in the GUI. Likely the most recommended approach to manage complex configurations is to use ``*.cmake`` fragment files passed in through the `_CONFIGURE_OPTIONS_FILE`_ option. This offers the greatest flexibility and the ability to version-control the configuration settings. Selecting the list of packages to enable ---------------------------------------- The project is broken up into a set of packages that can be enabled (or disabled). For details and generic examples, see `Package Dependencies and Enable/Disable Logic`_ and `TriBITS Dependency Handling Behaviors`_. See the following use cases: * `Determine the list of packages that can be enabled`_ * `Print package dependencies`_ * `Enable a set of packages`_ * `Enable or disable tests for specific packages`_ * `Enable to test all effects of changing a given package(s)`_ * `Enable all packages (and optionally all tests)`_ * `Disable a package and all its dependencies`_ * `Remove all package enables in the cache`_ * `Speed up debugging dependency handling`_ Determine the list of packages that can be enabled ++++++++++++++++++++++++++++++++++++++++++++++++++ In order to see the list of available Packages to enable, just run a basic CMake configure, enabling nothing, and then grep the output to see what packages are available to enable. The full set of defined packages is contained the lines starting with ``'Final set of enabled packages'`` and ``'Final set of non-enabled packages'``. If no packages are enabled by default (which is base behavior), the full list of packages will be listed on the line ``'Final set of non-enabled packages'``. Therefore, to see the full list of defined packages, run:: ./do-configure 2>&1 | grep "Final set of .*enabled packages" Any of the packages shown on those lines can potentially be enabled using ``-D _ENABLE_=ON`` (unless they are set to disabled for some reason, see the CMake output for package disable warnings). Another way to see the full list of packages that can be enabled is to configure with `_DUMP_PACKAGE_DEPENDENCIES`_ = ``ON`` and then grep for ``_INTERNAL_PACKAGES`` using, for example:: ./do-configure 2>&1 | grep "_INTERNAL_PACKAGES: " Print package dependencies ++++++++++++++++++++++++++ .. __DUMP_PACKAGE_DEPENDENCIES: The set of package dependencies can be printed in the ``cmake`` STDOUT by setting the configure option:: -D _DUMP_PACKAGE_DEPENDENCIES=ON This will print the basic forward/upstream dependencies for each package. To find this output, look for the line:: Printing package dependencies ... and the dependencies are listed below this for each package in the form:: -- _LIB_DEFINED_DEPENDENCIES: [O] <[PKG1>[R] ... -- _TEST_DEFINED_DEPENDENCIES: [R] <[PKG8>[R] ... (Dependencies that don't exist are left out of the output. For example, if there are no extra test dependencies, then ``_TEST_DEFINED_DEPENDENCIES`` will not be printed.) To also see the direct forward/downstream dependencies for each package, also include:: -D _DUMP_FORWARD_PACKAGE_DEPENDENCIES=ON These dependencies are printed along with the backward/upstsream dependencies as described above. Both of these variables are automatically enabled when `_VERBOSE_CONFIGURE`_ = ``ON``. Enable a set of packages ++++++++++++++++++++++++ .. __ENABLE_ALL_OPTIONAL_PACKAGES: .. __ENABLE_TESTS: To enable a package ```` (and optionally also its tests and examples), configure with:: -D _ENABLE_=ON \ -D _ENABLE_ALL_OPTIONAL_PACKAGES=ON \ -D _ENABLE_TESTS=ON \ This set of arguments allows a user to turn on ```` as well as all packages that ```` can use. All of the package's optional "can use" upstream dependent packages are enabled with ``-D_ENABLE_ALL_OPTIONAL_PACKAGES=ON``. However, ``-D_ENABLE_TESTS=ON`` will only enable tests and examples for ```` (and any other packages explicitly enabled). If a TriBITS package ```` has subpackages (e.g. subpackages ````, ````, ...), then enabling the package is equivalent to enabling all of the required **and optional** subpackagses:: -D _ENABLE_=ON \ -D _ENABLE_=ON \ ... (In this case, the parent package's optional subpackages are enabled regardless the value of ``_ENABLE_ALL_OPTIONAL_PACKAGES``.) However, a TriBITS subpackage will only be enabled if it is not already disabled either explicitly or implicitly. NOTE: The CMake cache variable type for all ``XXX_ENABLE_YYY`` variables is actually ``STRING`` and not ``BOOL``. That is because these enable variables take on the string enum values of ``"ON"``, ``"OFF"``, end empty ``""``. An empty enable means that the TriBITS dependency system is allowed to decide if an enable should be turned on or off based on various logic. The CMake GUI will enforce the values of ``"ON"``, ``"OFF"``, and empty ``""`` but it will not enforce this if you set the value on the command line or in a ``set()`` statement in an input ```*.cmake`` options files. However, setting ``-DXXX_ENABLE_YYY=TRUE`` and ``-DXXX_ENABLE_YYY=FALSE`` is allowed and will be interpreted correctly.. Enable or disable tests for specific packages +++++++++++++++++++++++++++++++++++++++++++++ The enable tests for explicitly enabled packages, configure with:: -D _ENABLE_=ON \ -D _ENABLE_=ON \ -D _ENABLE_TESTS=ON \ This will result in the enable of the test suites for any package that explicitly enabled with ``-D _ENABLE_=ON``. Note that his will **not** result in the enable of the test suites for any packages that may only be implicitly enabled in order to build the explicitly enabled packages. .. __ENABLE_TESTS: If one wants to enable a package along with the enable of other packages, but not the test suite for that package, then one can use a "exclude-list" appraoch to disable the tests for that package by configuring with, for example:: -D _ENABLE_=ON \ -D _ENABLE_=ON \ -D _ENABLE_=ON \ -D _ENABLE_TESTS=ON \ -D _ENABLE_TESTS=OFF \ The above will enable the package test suites for ```` and ```` but **not** for ```` (or any other packages that might get implicitly enabled). One might use this approach if one wants to build and install package ```` but does not want to build and run the test suite for that package. Alternatively, one can use an "include-list" appraoch to enable packages and only enable tests for specific packages, for example, configuring with:: -D _ENABLE_=ON \ -D _ENABLE_TESTS=ON \ -D _ENABLE_=ON \ -D _ENABLE_=ON \ -D _ENABLE_TESTS=ON \ That will have the same result as using the "exclude-list" approach above. **NOTE:** Setting ``_ENABLE_TESTS=ON`` will set ``_ENABLE_EXAMPLES=ON`` by default. Also, setting ``_ENABLE_TESTS=ON`` will result in setting ``_ENABLE_TESTS=ON`` for all subpackages in a parent package that are explicitly enabled or are enabled in the forward sweep as a result of `_ENABLE_ALL_FORWARD_DEP_PACKAGES`_ being set to ``ON``. These and other options give the user complete control of what packages get enabled or disabled and what package test suites are enabled or disabled. Enable to test all effects of changing a given package(s) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. __ENABLE_ALL_FORWARD_DEP_PACKAGES: To enable a package ```` to test it and all of its down-stream packages, configure with:: -D _ENABLE_=ON \ -D _ENABLE_ALL_FORWARD_DEP_PACKAGES=ON \ -D _ENABLE_TESTS=ON \ The above set of arguments will result in package ```` and all packages that depend on ```` to be enabled and have all of their tests turned on. Tests will not be enabled in packages that do not depend (at least implicitly) on ```` in this case. This speeds up and robustifies testing for changes in specific packages (like in per-merge testing in a continuous integration process). NOTE: setting ``_ENABLE_ALL_FORWARD_DEP_PACKAGES=ON`` also automatically sets and overrides `_ENABLE_ALL_OPTIONAL_PACKAGES`_ to be ``ON`` as well. (It makes no sense to want to enable forward dependent packages for testing purposes unless you are enabling all optional packages.) Enable all packages (and optionally all tests) ++++++++++++++++++++++++++++++++++++++++++++++ To enable all defined packages, add the configure option:: -D _ENABLE_ALL_PACKAGES=ON \ To also optionally enable the tests and examples in all of those enabled packages, add the configure option:: -D _ENABLE_TESTS=ON \ Specific packages can be disabled (i.e. "exclude-listed") by adding ``_ENABLE_=OFF``. This will also disable all packages that depend on ````. Note, all examples are also enabled by default when setting ``_ENABLE_TESTS=ON``. By default, setting ``_ENABLE_ALL_PACKAGES=ON`` only enables primary tested (PT) packages and code. To have this also enable all secondary tested (ST) packages and ST code in PT packages code, one must also set:: -D _ENABLE_SECONDARY_TESTED_CODE=ON \ NOTE: If this project is a "meta-project", then ``_ENABLE_ALL_PACKAGES=ON`` may not enable *all* the packages but only the project's primary meta-project packages. See `Package Dependencies and Enable/Disable Logic`_ and `TriBITS Dependency Handling Behaviors`_ for details. Disable a package and all its dependencies ++++++++++++++++++++++++++++++++++++++++++ To disable a package and all of the packages that depend on it, add the configure option:: -D _ENABLE_=OFF For example:: -D _ENABLE_=ON \ -D _ENABLE_ALL_OPTIONAL_PACKAGES=ON \ -D _ENABLE_=OFF \ will enable ```` and all of the packages that it depends on except for ```` and all of its forward dependencies. If a TriBITS package ```` has subpackages (e.g. a parent package with subpackages ````, ````, ...), then disabling the parent package is equivalent to disabling all of the required and optional subpackages:: -D _ENABLE_=OFF \ -D _ENABLE_=OFF \ ... The disable of the subpackages in this case will override any enables. .. __DISABLE_ENABLED_FORWARD_DEP_PACKAGES: If a disabled package is a required dependency of some explicitly enabled downstream package, then the configure will error out if:: -D _DISABLE_ENABLED_FORWARD_DEP_PACKAGES=OFF \ is set. Otherwise, if ``_DISABLE_ENABLED_FORWARD_DEP_PACKAGES=ON``, a ``NOTE`` will be printed and the downstream package will be disabled and configuration will continue. Remove all package enables in the cache +++++++++++++++++++++++++++++++++++++++ To wipe the set of package enables in the ``CMakeCache.txt`` file so they can be reset again from scratch, re-configure with:: $ cmake -D _UNENABLE_ENABLED_PACKAGES=TRUE . This option will set to empty '' all package enables, leaving all other cache variables as they are. You can then reconfigure with a new set of package enables for a different set of packages. This allows you to avoid more expensive configure time checks (like the standard CMake compiler checks) and to preserve other cache variables that you have set and don't want to loose. For example, one would want to do this to avoid more expensive compiler and TPL checks. Speed up debugging dependency handling +++++++++++++++++++++++++++++++++++++++ To speed up debugging the package enable/disable dependency handling, set the cache variable:: -D _TRACE_DEPENDENCY_HANDLING_ONLY=ON This will result in only performing the package enable/disable dependency handling logic and tracing what would be done to configure the compilers and configure the various enabled packages but not actually do that work. This can greatly speed up the time to complete the ``cmake`` configure command when debugging the dependency handling (or when creating tests that check that behavior). Selecting compiler and linker options ------------------------------------- The compilers for C, C++, and Fortran will be found by default by CMake if they are not otherwise specified as described below (see standard CMake documentation for how default compilers are found). The most direct way to set the compilers are to set the CMake cache variables:: -D CMAKE__COMPILER= The path to the compiler can be just a name of the compiler (e.g. ``-DCMAKE_C_COMPILER=gcc``) or can be an absolute path (e.g. ``-DCMAKE_C_COMPILER=/usr/local/bin/cc``). The safest and more direct approach to determine the compilers is to set the absolute paths using, for example, the cache variables:: -D CMAKE_C_COMPILER=/opt/my_install/bin/gcc \ -D CMAKE_CXX_COMPILER=/opt/my_install/bin/g++ \ -D CMAKE_Fortran_COMPILER=/opt/my_install/bin/gfortran or if ``TPL_ENABLE_MPI=ON`` (see `Configuring with MPI support`_) something like:: -D CMAKE_C_COMPILER=/opt/my_install/bin/mpicc \ -D CMAKE_CXX_COMPILER=/opt/my_install/bin/mpicxx \ -D CMAKE_Fortran_COMPILER=/opt/my_install/bin/mpif90 If these the CMake cache variables are not set, then CMake will use the compilers specified in the environment variables ``CC``, ``CXX``, and ``FC`` for C, C++ and Fortran, respectively. If one needs to drill down through different layers of scripts, then it can be useful to set the compilers using these environment variables. But in general is it recommended to be explicit and use the above CMake cache variables to set the absolute path to the compilers to remove all ambiguity. If absolute paths to the compilers are not specified using the CMake cache variables or the environment variables as described above, then in MPI mode (i.e. ``TPL_ENABLE_MPI=ON``) TriBITS performs its own search for the MPI compiler wrappers that will find the correct compilers for most MPI distributions (see `Configuring with MPI support`_). However, if in serial mode (i.e. ``TPL_ENABLE_MPI=OFF``), then CMake will do its own default compiler search. The algorithm by which raw CMake finds these compilers is not precisely documented (and seems to change based on the platform). However, on Linux systems, the observed algorithm appears to be: 1. Search for the C compiler first by looking in ``PATH`` (or the equivalent on Windows), starting with a compiler with the name ``cc`` and then moving on to other names like ``gcc``, etc. This first compiler found is set to ``CMAKE_C_COMPILER``. 2. Search for the C++ compiler with names like ``c++``, ``g++``, etc., but restrict the search to the same directory specified by base path to the C compiler given in the variable ``CMAKE_C_COMPILER``. The first compiler that is found is set to ``CMAKE_CXX_COMPILER``. 3. Search for the Fortran compiler with names like ``f90``, ``gfortran``, etc., but restrict the search to the same directory specified by base path to the C compiler given in the variable ``CMAKE_C_COMPILER``. The first compiler that is found is set to ``CMAKE_Fortran_COMPILER``. **WARNING:** While this built-in CMake compiler search algorithm may seems reasonable, it fails to find the correct compilers in many cases for a non-MPI serial build. For example, if a newer version of GCC is installed and is put first in ``PATH``, then CMake will fail to find the updated ``gcc`` compiler and will instead find the default system ``cc`` compiler (usually under ``/usr/bin/cc`` on Linux may systems) and will then only look for the C++ and Fortran compilers under that directory. This will fail to find the correct updated compilers because GCC does not install a C compiler named ``cc``! Therefore, if you want to use the default CMake compiler search to find the updated GCC compilers, you can set the CMake cache variable:: -D CMAKE_C_COMPILER=gcc or can set the environment variable ``CC=gcc``. Either one of these will result in CMake finding the updated GCC compilers found first in ``PATH``. Once one has specified the compilers, one can also set the compiler flags, but the way that CMake does this is a little surprising to many people. But the TriBITS CMake build system offers the ability to tweak the built-in CMake approach for setting compiler flags. First some background is in order. When CMake creates the object file build command for a given source file, it passes in flags to the compiler in the order:: ${CMAKE__FLAGS} ${CMAKE__FLAGS_} where ```` = ``C``, ``CXX``, or ``Fortran`` and ```` = ``DEBUG`` or ``RELEASE``. Note that the options in ``CMAKE__FLAGS_`` come after and override those in ``CMAKE__FLAGS``! The flags in ``CMAKE__FLAGS`` apply to all build types. Optimization, debug, and other build-type-specific flags are set in ``CMAKE__FLAGS_``. CMake automatically provides a default set of debug and release optimization flags for ``CMAKE__FLAGS_`` (e.g. ``CMAKE_CXX_FLAGS_DEBUG`` is typically ``"-g -O0"`` while ``CMAKE_CXX_FLAGS_RELEASE`` is typically ``"-O3"``). This means that if you try to set the optimization level with ``-DCMAKE_CXX_FLAGS="-04"``, then this level gets overridden by the flags specified in ``CMAKE__FLAGS_BUILD`` or ``CMAKE__FLAGS_RELEASE``. TriBITS will set defaults for ``CMAKE__FLAGS`` and ``CMAKE__FLAGS_``, which may be different that what raw CMake would set. TriBITS provides a means for project and package developers and users to set and override these compiler flag variables globally and on a package-by-package basis. Below, the facilities for manipulating compiler flags is described. To see that the full set of compiler flags one has to actually build a target by running, for example, ``make VERBOSE=1 `` (see `Building with verbose output without reconfiguring`_). (NOTE: One can also see the exact set of flags used for each target in the generated ``build.ninja`` file when using the Ninja generator.) One cannot just look at the cache variables for ``CMAKE__FLAGS`` and ``CMAKE__FLAGS_`` in the file ``CMakeCache.txt`` and see the full set of flags are actually being used. These variables can override the cache variables by TriBITS as project-level local non-cache variables as described below (see `Overriding CMAKE_BUILD_TYPE debug/release compiler options`_). The TriBITS CMake build system will set up default compile flags for GCC ('GNU') in development mode (i.e. ``_ENABLE_DEVELOPMENT_MODE=ON``) on order to help produce portable code. These flags set up strong warning options and enforce language standards. In release mode (i.e. ``_ENABLE_DEVELOPMENT_MODE=OFF``), these flags are not set. These flags get set internally into the variables ``CMAKE__FLAGS`` (when processing packages, not at the global cache variable level) but the user can append flags that override these as described below. Configuring to build with default debug or release compiler flags +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. _CMAKE_BUILD_TYPE: To build a debug version, pass into 'cmake':: -D CMAKE_BUILD_TYPE=DEBUG This will result in debug flags getting passed to the compiler according to what is set in ``CMAKE__FLAGS_DEBUG``. To build a release (optimized) version, pass into 'cmake':: -D CMAKE_BUILD_TYPE=RELEASE This will result in optimized flags getting passed to the compiler according to what is in ``CMAKE__FLAGS_RELEASE``. The default build type is typically ``CMAKE_BUILD_TYPE=RELEASE`` unless ``-D USE_XSDK_DEFAULTS=TRUE`` is set in which case the default build type is ``CMAKE_BUILD_TYPE=DEBUG`` as per the xSDK configure standard. Adding arbitrary compiler flags but keeping default build-type flags ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To append arbitrary compiler flags to ``CMAKE__FLAGS`` (which may be set internally by TriBITS) that apply to all build types, configure with:: -D CMAKE__FLAGS="" where ```` are your extra compiler options like ``"-DSOME_MACRO_TO_DEFINE -funroll-loops"``. These options will get appended to (i.e. come after) other internally defined compiler option and therefore override them. The options are then pass to the compiler in the order:: \ ${CMAKE__FLAGS_} This that setting ``CMAKE__FLAGS`` can override the default flags that TriBITS will set for ``CMAKE__FLAGS`` but will **not** override flags specified in ``CMAKE__FLAGS_``. Instead of directly setting the CMake cache variables ``CMAKE__FLAGS`` one can instead set environment variables ``CFLAGS``, ``CXXFLAGS`` and ``FFLAGS`` for ``CMAKE_C_FLAGS``, ``CMAKE_CXX_FLAGS`` and ``CMAKE_Fortran_FLAGS``, respectively. In addition, if ``-DUSE_XSDK_DEFAULTS=TRUE`` is set, then one can also pass in Fortran flags using the environment variable ``FCFLAGS`` (raw CMake does not recognize ``FCFLAGS``). But if ``FFLAGS`` and ``FCFLAGS`` are both set, then they must be the same or a configure error will occur. Options can also be targeted to a specific TriBITS package using:: -D __FLAGS="" The package-specific options get appended **after** those already in ``CMAKE__FLAGS`` and therefore override (but not replace) those set globally in ``CMAKE__FLAGS`` (either internally in the CMakeLists.txt files or by the user in the cache). In addition, flags can be targeted to a specific TriBITS subpackage using the same syntax:: -D __FLAGS="" If top-level package-specific flags and subpackage-specific flags are both set for the same parent package such as with:: -D SomePackage__FLAGS="" \ -D SomePackageSpkgA__FLAGS="" \ then the flags for the subpackage ``SomePackageSpkgA`` will be listed after those for its parent package ``SomePackage`` on the compiler command-line as:: That way, compiler options for a subpackage override flags set for the parent package. NOTES: 1) Setting ``CMAKE__FLAGS`` as a cache variable by the user on input be listed after and therefore override, but will not replace, any internally set flags in ``CMAKE__FLAGS`` defined by the CMake system. To get rid of these project/TriBITS set compiler flags/options, see the below items. 2) Given that CMake passes in flags in ``CMAKE__FLAGS_`` after those in ``CMAKE__FLAGS`` means that users setting the ``CMAKE__FLAGS`` and ``__FLAGS`` will **not** override the flags in ``CMAKE__FLAGS_`` which come after on the compile line. Therefore, setting ``CMAKE__FLAGS`` and ``__FLAGS`` should only be used for options that will not get overridden by the debug or release compiler flags in ``CMAKE__FLAGS_``. However, setting ``CMAKE__FLAGS`` will work well for adding extra compiler defines (e.g. -DSOMETHING) for example. WARNING: Any options that you set through the cache variable ``CMAKE__FLAGS_`` will get overridden in the CMake system for GNU compilers in development mode so don't try to manually set ``CMAKE__FLAGS_`` directly! To override those options, see ``CMAKE__FLAGS__OVERRIDE`` below. Overriding CMAKE_BUILD_TYPE debug/release compiler options ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To override the default CMake-set options in ``CMAKE__FLAGS_``, use:: -D CMAKE__FLAGS__OVERRIDE="" For example, to default debug options use:: -D CMAKE_C_FLAGS_DEBUG_OVERRIDE="-g -O1" \ -D CMAKE_CXX_FLAGS_DEBUG_OVERRIDE="-g -O1" -D CMAKE_Fortran_FLAGS_DEBUG_OVERRIDE="-g -O1" and to override default release options use:: -D CMAKE_C_FLAGS_RELEASE_OVERRIDE="-O3 -funroll-loops" \ -D CMAKE_CXX_FLAGS_RELEASE_OVERRIDE="-03 -funroll-loops" -D CMAKE_Fortran_FLAGS_RELEASE_OVERRIDE="-03 -funroll-loops" NOTES: The TriBITS CMake cache variable ``CMAKE__FLAGS__OVERRIDE`` is used and not ``CMAKE__FLAGS_`` because is given a default internally by CMake and the new variable is needed to make the override explicit. Turning off strong warnings for individual packages +++++++++++++++++++++++++++++++++++++++++++++++++++ .. __DISABLE_STRONG_WARNINGS: To turn off strong warnings (for all languages) for a given TriBITS package, set:: -D _DISABLE_STRONG_WARNINGS=ON This will only affect the compilation of the sources for ````, not warnings generated from the header files in downstream packages or client code. Note that strong warnings are only enabled by default in development mode (``_ENABLE_DEVELOPMENT_MODE==ON``) but not release mode (``_ENABLE_DEVELOPMENT_MODE==ON``). A release of should therefore not have strong warning options enabled. Overriding all (strong warnings and debug/release) compiler options +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To override all compiler options, including both strong warning options and debug/release options, configure with:: -D CMAKE_C_FLAGS="-O3 -funroll-loops" \ -D CMAKE_CXX_FLAGS="-03 -fexceptions" \ -D CMAKE_BUILD_TYPE=NONE \ -D _ENABLE_STRONG_C_COMPILE_WARNINGS=OFF \ -D _ENABLE_STRONG_CXX_COMPILE_WARNINGS=OFF \ -D _ENABLE_SHADOW_WARNINGS=OFF \ -D _ENABLE_COVERAGE_TESTING=OFF \ -D _ENABLE_CHECKED_STL=OFF \ NOTE: Options like ``_ENABLE_SHADOW_WARNINGS``, ``_ENABLE_COVERAGE_TESTING``, and ``_ENABLE_CHECKED_STL`` do not need to be turned off by default but they are shown above to make it clear what other CMake cache variables can add compiler and link arguments. NOTE: By setting ``CMAKE_BUILD_TYPE=NONE``, then ``CMAKE__FLAGS_NONE`` will be empty and therefore the options set in ``CMAKE__FLAGS`` will be all that is passed in. Enable and disable shadowing warnings for all packages ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To enable shadowing warnings for all packages (that don't already have them turned on) then use:: -D _ENABLE_SHADOW_WARNINGS=ON To disable shadowing warnings for all packages (even those that have them turned on by default) then use:: -D _ENABLE_SHADOW_WARNINGS=OFF NOTE: The default value is empty '' which lets each package decide for itself if shadowing warnings will be turned on or off for that package. Removing warnings as errors for CLEANED packages ++++++++++++++++++++++++++++++++++++++++++++++++ To remove the ``-Werror`` flag (or some other flag that is set) from being applied to compile CLEANED packages (like the Trilinos package Teuchos), set the following when configuring:: -D _WARNINGS_AS_ERRORS_FLAGS="" Adding debug symbols to the build +++++++++++++++++++++++++++++++++ To get the compiler to add debug symbols to the build, configure with:: -D _ENABLE_DEBUG_SYMBOLS=ON This will add ``-g`` on most compilers. NOTE: One does **not** generally need to create a full debug build to get debug symbols on most compilers. Printing out compiler flags for each package ++++++++++++++++++++++++++++++++++++++++++++ To print out the exact ``CMAKE__FLAGS`` that will be used for each package, set:: -D _PRINT_PACKAGE_COMPILER_FLAGS=ON That will print lines in STDOUT that are formatted as:: : CMAKE__FLAGS="" : CMAKE__FLAGS_="" This will print the value of the ``CMAKE__FLAGS`` and ``CMAKE__FLAGS_`` variables that are used as each package is being processed and will contain the flags in the exact order they are applied by CMake Appending arbitrary libraries and link flags every executable +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ In order to append any set of arbitrary libraries and link flags to your executables use:: -D_EXTRA_LINK_FLAGS="" \ -DCMAKE_EXE_LINKER_FLAGS="" Above, you can pass any type of library and they will always be the last libraries listed, even after all of the TPLs. NOTE: This is how you must set extra libraries like Fortran libraries and MPI libraries (when using raw compilers). Please only use this variable as a last resort. NOTE: You must only pass in libraries in ``_EXTRA_LINK_FLAGS`` and *not* arbitrary linker flags. To pass in extra linker flags that are not libraries, use the built-in CMake variable ``CMAKE_EXE_LINKER_FLAGS`` instead. The TriBITS variable ``_EXTRA_LINK_FLAGS`` is badly named in this respect but the name remains due to backward compatibility requirements. Enabling support for Ninja -------------------------- The `Ninja`_ build tool can be used as the back-end build tool instead of Makefiles by adding:: -GNinja to the CMake configure line (the default on most Linux and OSX platforms is ``-G"Unix Makefiles"``). This instructs CMake to create the back-end ``ninja`` build files instead of back-end Makefiles (see `Building (Ninja generator)`_). .. __WRITE_NINJA_MAKEFILES: In addition, the TriBITS build system will, by default, generate Makefiles in every binary directory where there is a CMakeLists.txt file in the source tree. These Makefiles have targets scoped to that subdirectory that use ``ninja`` to build targets in that subdirectory just like with the native CMake recursive ``-G "Unix Makefiles"`` generator. This allows one to ``cd`` into any binary directory and type ``make`` to build just the targets in that directory. These TriBITS-generated Ninja makefiles also support ``help`` and ``help-objects`` targets making it easy to build individual executables, libraries and object files in any binary subdirectory. **WARNING:** Using ``make -j`` with these TriBITS-generated Ninja Makefiles will **not** result in using ```` processes to build in parallel and will instead use **all** of the free cores to build on the machine! To control the number of processes used, run ``make NP=`` instead! See `Building in parallel with Ninja`_. The generation of these Ninja makefiles can be disabled by setting:: -D_WRITE_NINJA_MAKEFILES=OFF (But these Ninja Makefiles get created very quickly even for a very large CMake project so there is usually little reason to not generate them.) Limiting parallel compile and link jobs for Ninja builds -------------------------------------------------------- When the CMake generator Ninja is used (i.e. ``-GNinja``), one can limit the number of parallel jobs that are used for compiling object files by setting:: -D _PARALLEL_COMPILE_JOBS_LIMIT= and/or limit the number of parallel jobs that are used for linking libraries and executables by setting:: -D _PARALLEL_LINK_JOBS_LIMIT= where ```` and ```` are integers like ``20`` and ``4``. If these are not set, then the number of parallel jobs will be determined by the ``-j

`` argument passed to ``ninja -j

`` or by ninja automatically according to machine load when running ``ninja``. Limiting the number of link jobs can be useful, for example, for certain builds of large projects where linking many jobs in parallel can consume all of the RAM on a given system and crash the build. NOTE: These options are ignored when using Makefiles or other CMake generators. They only work for the Ninja generator. Disabling explicit template instantiation for C++ ------------------------------------------------- By default, support for optional explicit template instantiation (ETI) for C++ code is enabled. To disable support for optional ETI, configure with:: -D _ENABLE_EXPLICIT_INSTANTIATION=OFF When ``OFF``, all packages that have templated C++ code will use implicit template instantiation (unless they have hard-coded usage of ETI). ETI can be enabled (``ON``) or disabled (``OFF``) for individual packages with:: -D _ENABLE_EXPLICIT_INSTANTIATION=[ON|OFF] The default value for ``_ENABLE_EXPLICIT_INSTANTIATION`` is set by ``_ENABLE_EXPLICIT_INSTANTIATION``. For packages that support it, explicit template instantiation can massively reduce the compile times for the C++ code involved and can even avoid compiler crashes in some cases. To see what packages support explicit template instantiation, just search the CMakeCache.txt file for variables with ``ENABLE_EXPLICIT_INSTANTIATION`` in the name. Disabling the Fortran compiler and all Fortran code --------------------------------------------------- To disable the Fortran compiler and all code that depends on Fortran set:: -D _ENABLE_Fortran=OFF NOTE: The Fortran compiler may be disabled automatically by default on systems like MS Windows. NOTE: Most Apple Macs do not come with a compatible Fortran compiler by default so you must turn off Fortran if you don't have a compatible Fortran compiler. Enabling runtime debug checking ------------------------------- a) Enabling ifdefed runtime debug checking: To turn on optional ifdefed runtime debug checking, configure with:: -D _ENABLE_DEBUG=ON This will result in a number of ifdefs to be enabled that will perform a number of runtime checks. Nearly all of the debug checks in will get turned on by default by setting this option. This option can be set independent of ``CMAKE_BUILD_TYPE`` (which sets the compiler debug/release options). NOTES: * The variable ``CMAKE_BUILD_TYPE`` controls what compiler options are passed to the compiler by default while ``_ENABLE_DEBUG`` controls what defines are set in config.h files that control ifdefed debug checks. * Setting ``-DCMAKE_BUILD_TYPE=DEBUG`` will automatically set the default ``_ENABLE_DEBUG=ON``. b) Enabling checked STL implementation: To turn on the checked STL implementation set:: -D _ENABLE_CHECKED_STL=ON NOTES: * By default, this will set -D_GLIBCXX_DEBUG as a compile option for all C++ code. This only works with GCC currently. * This option is disabled by default because to enable it by default can cause runtime segfaults when linked against C++ code that was compiled without -D_GLIBCXX_DEBUG. Configuring with MPI support ---------------------------- To enable MPI support you must minimally set:: -D TPL_ENABLE_MPI=ON There is built-in logic to try to find the various MPI components on your system but you can override (or make suggestions) with:: -D MPI_BASE_DIR="path" (Base path of a standard MPI installation which has the subdirs 'bin', 'libs', 'include' etc.) or:: -D MPI_BIN_DIR="path1;path2;...;pathn" which sets the paths where the MPI executables (e.g. mpiCC, mpicc, mpirun, mpiexec) can be found. By default this is set to ``${MPI_BASE_DIR}/bin`` if ``MPI_BASE_DIR`` is set. **NOTE:** TriBITS uses the MPI compiler wrappers (e.g. mpiCC, mpicc, mpic++, mpif90, etc.) which is more standard with other builds systems for HPC computing using MPI (and the way that MPI implementations were meant to be used). But directly using the MPI compiler wrappers as the direct compilers is inconsistent with the way that the standard CMake module ``FindMPI.cmake`` which tries to "unwrap" the compiler wrappers and grab out the raw underlying compilers and the raw compiler and linker command-line arguments. In this way, TriBITS is more consistent with standard usage in the HPC community but is less consistent with CMake (see "HISTORICAL NOTE" below). There are several different different variations for configuring with MPI support: a) **Configuring build using MPI compiler wrappers:** The MPI compiler wrappers are turned on by default. There is built-in logic in TriBITS that will try to find the right MPI compiler wrappers. However, you can specifically select them by setting, for example:: -D MPI_C_COMPILER:FILEPATH=mpicc \ -D MPI_CXX_COMPILER:FILEPATH=mpic++ \ -D MPI_Fortan_COMPILER:FILEPATH=mpif77 which gives the name of the MPI C/C++/Fortran compiler wrapper executable. In this case, just the names of the programs are given and absolute path of the executables will be searched for under ``${MPI_BIN_DIR}/`` if the cache variable ``MPI_BIN_DIR`` is set, or in the default path otherwise. The found programs will then be used to set the cache variables ``CMAKE_[C,CXX,Fortran]_COMPILER``. One can avoid the search and just use the absolute paths with, for example:: -D MPI_C_COMPILER:FILEPATH=/opt/mpich/bin/mpicc \ -D MPI_CXX_COMPILER:FILEPATH=/opt/mpich/bin/mpic++ \ -D MPI_Fortan_COMPILER:FILEPATH=/opt/mpich/bin/mpif77 However, you can also directly set the variables ``CMAKE_[C,CXX,Fortran]_COMPILER`` with, for example:: -D CMAKE_C_COMPILER:FILEPATH=/opt/mpich/bin/mpicc \ -D CMAKE_CXX_COMPILER:FILEPATH=/opt/mpich/bin/mpic++ \ -D CMAKE_Fortan_COMPILER:FILEPATH=/opt/mpich/bin/mpif77 **WARNING:** If you set just the compiler names and not the absolute paths with ``CMAKE__COMPILER`` in MPI mode, then a search will not be done and these will be expected to be in the path at build time. (Note that his is inconsistent the behavior of raw CMake in non-MPI mode described in `Selecting compiler and linker options`_). If both ``CMAKE__COMPILER`` and ``MPI__COMPILER`` are set, however, then ``CMAKE__COMPILER`` will be used and ``MPI__COMPILER`` will be ignored. Note that when ``USE_XSDK_DEFAULTS=FALSE`` (see `xSDK Configuration Options`_), then the environment variables ``CC``, ``CXX`` and ``FC`` are ignored. But when ``USE_XSDK_DEFAULTS=TRUE`` and the CMake cache variables ``CMAKE_[C,CXX,Fortran]_COMPILER`` are not set, then the environment variables ``CC``, ``CXX`` and ``FC`` will be used for ``CMAKE_[C,CXX,Fortran]_COMPILER``, even if the CMake cache variables ``MPI_[C,CXX,Fortran]_COMPILER`` are set! So if one wants to make sure and set the MPI compilers irrespective of the xSDK mode, then one should set cmake cache variables ``CMAKE_[C,CXX,Fortran]_COMPILER`` to the absolute path of the MPI compiler wrappers. **HISTORICAL NOTE:** The TriBITS system has its own custom MPI integration support and does not (currently) use the standard CMake module ``FindMPI.cmake``. This custom support for MPI was added to TriBITS in 2008 when it was found the built-in ``FindMPI.cmake`` module was not sufficient for the needs of Trilinos and the approach taken by the module (still in use as of CMake 3.4.x) which tries to unwrap the raw compilers and grab the list of include directories, link libraries, etc, was not sufficiently portable for the systems where Trilinos needed to be used. But earlier versions of TriBITS used the ``FindMPI.cmake`` module and that is why the CMake cache variables ``MPI_[C,CXX,Fortran]_COMPILER`` are defined and still supported. b) **Configuring to build using raw compilers and flags/libraries:** While using the MPI compiler wrappers as described above is the preferred way to enable support for MPI, you can also just use the raw compilers and then pass in all of the other information that will be used to compile and link your code. To turn off the MPI compiler wrappers, set:: -D MPI_USE_COMPILER_WRAPPERS=OFF You will then need to manually pass in the compile and link lines needed to compile and link MPI programs. The compile flags can be set through:: -D CMAKE_[C,CXX,Fortran]_FLAGS="$EXTRA_COMPILE_FLAGS" The link and library flags must be set through:: -D _EXTRA_LINK_FLAGS="$EXTRA_LINK_FLAGS" Above, you can pass any type of library or other linker flags in and they will always be the last libraries listed, even after all of the TPLs. NOTE: A good way to determine the extra compile and link flags for MPI is to use:: export EXTRA_COMPILE_FLAGS="`$MPI_BIN_DIR/mpiCC --showme:compile`" export EXTRA_LINK_FLAGS="`$MPI_BIN_DIR/mpiCC --showme:link`" where ``MPI_BIN_DIR`` is set to your MPI installations binary directory. c) **Setting up to run MPI programs:** In order to use the ctest program to run MPI tests, you must set the mpi run command and the options it takes. The built-in logic will try to find the right program and options but you will have to override them in many cases. MPI test and example executables are passed to CTest ``add_test()`` as:: add_test(NAME COMMAND ${MPI_EXEC} ${MPI_EXEC_PRE_NUMPROCS_FLAGS} ${MPI_EXEC_NUMPROCS_FLAG} ${MPI_EXEC_POST_NUMPROCS_FLAGS} ) where ````, ````, and ```` are specific to the test being run. The test-independent MPI arguments are:: -D MPI_EXEC:FILEPATH="exec_name" (The name of the MPI run command (e.g. mpirun, mpiexec) that is used to run the MPI program. This can be just the name of the program in which case the full path will be looked for in ``${MPI_BIN_DIR}`` as described above. If it is an absolute path, it will be used without modification.) :: -D MPI_EXEC_DEFAULT_NUMPROCS=4 (The default number of processes to use when setting up and running MPI test and example executables. The default is set to '4' and only needs to be changed when needed or desired.) :: -D MPI_EXEC_MAX_NUMPROCS=4 (The maximum number of processes to allow when setting up and running MPI tests and examples that use MPI. The default is set to '4' but should be set to the largest number that can be tolerated for the given machine or the most cores on the machine that you want the test suite to be able to use. Tests and examples that require more processes than this are excluded from the CTest test suite at configure time. ``MPI_EXEC_MAX_NUMPROCS`` is also used to exclude tests in a non-MPI build (i.e. ``TPL_ENABLE_MPI=OFF``) if the number of required cores for a given test is greater than this value.) :: -D MPI_EXEC_NUMPROCS_FLAG=-np (The command-line option just before the number of processes to use ````. The default value is based on the name of ``${MPI_EXEC}``, for example, which is ``-np`` for OpenMPI.) :: -D MPI_EXEC_PRE_NUMPROCS_FLAGS="arg1;arg2;...;argn" (Other command-line arguments that must come *before* the numprocs argument. The default is empty "".) :: -D MPI_EXEC_POST_NUMPROCS_FLAGS="arg1;arg2;...;argn" (Other command-line arguments that must come *after* the numprocs argument. The default is empty "".) NOTE: Multiple arguments listed in ``MPI_EXEC_PRE_NUMPROCS_FLAGS`` and ``MPI_EXEC_POST_NUMPROCS_FLAGS`` must be quoted and separated by ``';'`` as these variables are interpreted as CMake arrays. Configuring for OpenMP support ------------------------------ To enable OpenMP support, one must set:: -D _ENABLE_OpenMP=ON Note that if you enable OpenMP directly through a compiler option (e.g., ``-fopenmp``), you will NOT enable OpenMP inside source code. To skip adding flags for OpenMP for ```` = ``C``, ``CXX``, or ``Fortran``, use:: -D OpenMP__FLAGS_OVERRIDE=" " The single space " " will result in no flags getting added. This is needed since one can't set the flags ``OpenMP__FLAGS`` to an empty string or the ``find_package(OpenMP)`` command will fail. Setting the variable ``-DOpenMP__FLAGS_OVERRIDE= " "`` is the only way to enable OpenMP but skip adding the OpenMP flags provided by ``find_package(OpenMP)``. Building shared libraries ------------------------- .. _BUILD_SHARED_LIBS: To configure to build shared libraries, set:: -D BUILD_SHARED_LIBS=ON The above option will result in all shared libraries to be build on all systems (i.e., ``.so`` on Unix/Linux systems, ``.dylib`` on Mac OS X, and ``.dll`` on Windows systems). NOTE: If the project has ``USE_XSDK_DEFAULTS=ON`` set, then this will set ``BUILD_SHARED_LIBS=TRUE`` by default. Otherwise, the default is ``BUILD_SHARED_LIBS=FALSE`` Many systems support a feature called ``RPATH`` when shared libraries are used that embeds the default locations to look for shared libraries when an executable is run. By default on most systems, CMake will automatically add RPATH directories to shared libraries and executables inside of the build directories. This allows running CMake-built executables from inside the build directory without needing to set ``LD_LIBRARY_PATH`` on any other environment variables. However, this can be disabled by setting:: -D CMAKE_SKIP_BUILD_RPATH=TRUE but it is hard to find a use case where that would be useful. Building static libraries and executables ----------------------------------------- To build static libraries, turn off the shared library support:: -D BUILD_SHARED_LIBS=OFF Some machines, such as the Cray XT5, require static executables. To build executables as static objects, a number of flags must be set:: -D BUILD_SHARED_LIBS=OFF \ -D TPL_FIND_SHARED_LIBS=OFF \ -D _LINK_SEARCH_START_STATIC=ON The first flag tells cmake to build static versions of the libraries. The second flag tells cmake to locate static library versions of any required TPLs. The third flag tells the auto-detection routines that search for extra required libraries (such as the mpi library and the gfortran library for gnu compilers) to locate static versions. Changing include directories in downstream CMake projects to non-system ----------------------------------------------------------------------- By default, include directories from IMPORTED library targets from the project's installed ``Config.cmake`` files will be considered ``SYSTEM`` headers and therefore will be included on the compile lines of downstream CMake projects with ``-isystem`` with most compilers. However, when using CMake 3.23+, by configuring with:: -D _IMPORTED_NO_SYSTEM=ON then all of the IMPORTED library targets in the set of installed ``Config.cmake`` files will have the ``IMPORTED_NO_SYSTEM`` target property set. This will cause downstream customer CMake projects to apply the include directories from these IMPORTED library targets as non-SYSTEM include directories. On most compilers, that means that the include directories will be listed on the compile lines with ``-I`` instead of with ``-isystem`` (for compilers that support the ``-isystem`` option). (Changing from ``-isystem `` to ``-I `` moves ```` forward in the compiler's include directory search order and could also result in the found header files emitting compiler warnings that would other otherwise be silenced when the headers were found in include directories pulled in with ``-isystem``.) **NOTE:** Setting ``_IMPORTED_NO_SYSTEM=ON`` when using a CMake version less than 3.23 will result in a fatal configure error (so don't do that). **A workaround for CMake versions less than 3.23** is for **downstream customer CMake projects** to set the native CMake cache variable:: -D CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE This will result in **all** include directories from **all** IMPORTED library targets used in the downstream customer CMake project to be listed on the compile lines using ``-I`` instead of ``-isystem``, and not just for the IMPORTED library targets from this project's installed ``Config.cmake`` files! **NOTE:** Setting ``CMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE`` in the CMake configure will **not** result in changing how include directories from 's IMPORTED targets are handled in a downstream customer CMake project! It will only change how include directories from upstream package's IMPORTED targets are handled in the CMake project build itself. Enabling the usage of resource files to reduce length of build lines -------------------------------------------------------------------- When using the ``Unix Makefile`` generator and the ``Ninja`` generator, CMake supports some very useful (undocumented) options for reducing the length of the command-lines used to build object files, create libraries, and link executables. Using these options can avoid troublesome "command-line too long" errors, "Error 127" library creation errors, and other similar errors related to excessively long command-lines to build various targets. When using the ``Unix Makefile`` generator, CMake responds to the three cache variables ``CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES``, ``CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS`` and ``CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES`` described below. To aggregate the list of all of the include directories (e.g. ``'-I '``) into a single ``*.rsp`` file for compiling object files, set:: -D CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES=ON To aggregate the list of all of the object files (e.g. ``'/.o'``) into a single ``*.rsp`` file for creating libraries or linking executables, set:: -D CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS=ON To aggregate the list of all of the libraries (e.g. ``'/.a'``) into a single ``*.rsp`` file for creating shared libraries or linking executables, set:: -D CMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES=ON When using the ``Ninja`` generator, CMake only responds to the single option:: -D CMAKE_NINJA_FORCE_RESPONSE_FILE=ON which turns on the usage of ``*.rsp`` response files for include directories, object files, and libraries (and therefore is equivalent to setting the above three ``Unix Makefiles`` generator options to ``ON``). This feature works well on most standard systems but there are problems in some situations and therefore these options can only be safely enabled on case-by-case basis -- experimenting to ensure they are working correctly. Some examples of some known problematic cases (as of CMake 3.11.2) are: * CMake will only use resource files with static libraries created with GNU ``ar`` (e.g. on Linux) but not BSD ``ar`` (e.g. on MacOS). With BSD ``ar``, CMake may break up long command-lines (i.e. lots of object files) with multiple calls to ``ar`` but that may only work with the ``Unix Makefiles`` generator, not the ``Ninja`` generator. * Some versions of ``gfortran`` do not accept ``*.rsp`` files. * Some versions of ``nvcc`` (e.g. with CUDA 8.044) do not accept ``*.rsp`` files for compilation or linking. Because of problems like these, TriBITS cannot robustly automatically turn on these options. Therefore, it is up to the user to try these options out to see if they work with their specific version of CMake, compilers, and OS. NOTE: When using the ``Unix Makefiles`` generator, one can decide to set any combination of these three options based on need and preference and what actually works with a given OS, version of CMake, and provided compilers. For example, on one system ``CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS=ON`` may work but ``CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES=ON`` may not (which is the case for ``gfortran`` mentioned above). Therefore, one should experiment carefully and inspect the build lines using ``make VERBOSE=1 `` as described in `Building with verbose output without reconfiguring`_ when deciding which of these options to enable. NOTE: Newer versions of CMake may automatically determine when these options need to be turned on so watch for that in looking at the build lines. External Packages/Third-Party Library (TPL) support --------------------------------------------------- A set of external packages/third-party libraries (TPL) can be enabled and disabled and the locations of those can be specified at configure time (if they are not found in the default path). Enabling support for an optional Third-Party Library (TPL) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To enable a given external packages/TPL, set:: -D TPL_ENABLE_=ON where ```` = ``BLAS``, ``LAPACK`` ``Boost``, ``Netcdf``, etc. (Requires TPLs for enabled package will automatically be enabled.) The full list of TPLs that is defined and can be enabled is shown by doing a configure with CMake and then grepping the configure output for ``Final set of .* TPLs``. The set of TPL names listed in ``'Final set of enabled external packages/TPLs'`` and ``'Final set of non-enabled external packages/TPLs'`` gives the full list of TPLs that can be enabled (or disabled). Optional package-specific support for a TPL can be turned off by setting:: -D _ENABLE_=OFF This gives the user full control over what TPLs are supported by which package independent of whether the TPL is enabled or not. Support for an optional TPL can also be turned on implicitly by setting:: -D _ENABLE_=ON where ```` is a TriBITS package that has an optional dependency on ````. That will result in setting ``TPL_ENABLE_=ON`` internally (but not set in the cache) if ``TPL_ENABLE_=OFF`` is not already set. Specifying the location of the parts of an enabled external package/TPL +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Once an external package/TPL is enabled, the parts of that TPL must be found. For many external packages/TPLs, this will be done automatically by searching the environment paths. Some external packages/TPLs are specified with a call to ``find_package()`` (see CMake documentation for ``find_package()``). Many other external packages/TPLs use a legacy TriBITS system that locates the parts using the CMake commands ``find_file()`` and ``find_library()`` as described below. Every defined external package/TPL uses a specification provided in a ``FindTPL.cmake`` module file. This file describes how the package is found in a way that provides modern CMake IMPORTED targets (including the ``::all_libs`` target) that is used by the downstream packages. Some TPLs require only libraries (e.g. Fortran libraries like BLAS or LAPACK), some TPL require only include directories, and some TPLs require both. For ``FindTPL.cmake`` files using the legacy TriBITS TPL system, a TPL is fully specified through the following cache variables: * ``TPL__INCLUDE_DIRS:PATH``: List of paths to header files for the TPL (if the TPL supplies header files). * ``TPL__LIBRARIES:PATH``: List of (absolute) paths to libraries, ordered as they will be on the link line (of the TPL supplies libraries). These variables are the only variables are used to create IMPORTED CMake targets for the TPL. One can set these two variables as CMake cache variables, for ``SomeTPL`` for example, with:: -D TPL_SomeTPL_INCLUDE_DIRS="${LIB_BASE}/include/a;${LIB_BASE}/include/b" \ -D TPL_SomeTPL_LIBRARIES="${LIB_BASE}/lib/liblib1.so;${LIB_BASE}/lib/liblib2.so" \ Using this approach, one can be guaranteed that these libraries and these include directories and will used in the compile and link lines for the packages that depend on this TPL ``SomeTPL``. **NOTE:** When specifying ``TPL__INCLUDE_DIRS`` and/or ``TPL__LIBRARIES``, the build system will use these without question. It will **not** check for the existence of these directories or files so make sure that these files and directories exist before these are used in the compiles and links. (This can actually be a feature in rare cases the libraries and header files don't actually get created until after the configure step is complete but before the build step.) **NOTE:** It is generally *not recommended* to specify the TPLs libraries as just a set of link options as, for example:: TPL_SomeTPL_LIBRARIES="-L/some/dir;-llib1;-llib2;..." But this is supported as long as this link line contains only link library directories and library names. (Link options that are not order-sensitive are also supported like ``-mkl``.) When the variables ``TPL__INCLUDE_DIRS`` and ``TPL__LIBRARIES`` are not specified, then most ``FindTPL.cmake`` modules use a default find operation. Some will call ``find_package()`` internally by default and some may implement the default find in some other way. To know for sure, see the documentation for the specific external package/TPL (e.g. looking in the ``FindTPL.cmake`` file to be sure). NOTE: if a given ``FindTPL.cmake`` will use ``find_package()`` by default, this can be disabled by configuring with:: -D_ALLOW_PACKAGE_PREFIND=OFF (Not all ``FindTPL.cmake`` files support this option.) Many ``FindTPL.cmake`` files, use the legacy TriBITS TPL system for finding include directories and/or libraries based on the function `tribits_tpl_find_include_dirs_and_libraries()`_. These simple standard ``FindTPL.cmake`` modules specify a set of header files and/or libraries that must be found. The directories where these header files and library files are looked for are specified using the CMake cache variables: * ``_INCLUDE_DIRS:PATH``: List of paths to search for header files using ``find_file()`` for each header file, in order. * ``_LIBRARY_NAMES:STRING``: List of unadorned library names, in the order of the link line. The platform-specific prefixes (e.g.. 'lib') and postfixes (e.g. '.a', '.lib', or '.dll') will be added automatically by CMake. For example, the library ``libblas.so``, ``libblas.a``, ``blas.lib`` or ``blas.dll`` will all be found on the proper platform using the name ``blas``. * ``_LIBRARY_DIRS:PATH``: The list of directories where the library files will be searched for using ``find_library()``, for each library, in order. Most of these ``FindTPL.cmake`` modules will define a default set of libraries to look for and therefore ``_LIBRARY_NAMES`` can typically be left off. Therefore, to find the same set of libraries for ``SimpleTPL`` shown above, one would specify:: -D SomeTPL_LIBRARY_DIRS="${LIB_BASE}/lib" and if the set of libraries to be found is different than the default, one can override that using:: -D SomeTPL_LIBRARY_NAMES="lib1;lib2" Therefore, this is in fact the preferred way to specify the libraries for these legacy TriBITS TPLs. In order to allow a TPL that normally requires one or more libraries to ignore the libraries, one can set ``_LIBRARY_NAMES`` to empty, for example:: -D _LIBRARY_NAMES="" If all the parts of a TPL are not found on an initial configure, the configure will error out with a helpful error message. In that case, one can change the variables ``_INCLUDE_DIRS``, ``_LIBRARY_NAMES``, and/or ``_LIBRARY_DIRS`` in order to help fund the parts of the TPL. One can do this over and over until the TPL is found. By reconfiguring, one avoids a complete configure from scratch which saves time. Or, one can avoid the find operations by directly setting ``TPL__INCLUDE_DIRS`` and ``TPL__LIBRARIES`` as described above. **TPL Example 1: Standard BLAS Library** Suppose one wants to find the standard BLAS library ``blas`` in the directory:: /usr/lib/ libblas.so libblas.a ... The ``FindTPLBLAS.cmake`` module should be set up to automatically find the BLAS TPL by simply enabling BLAS with:: -D TPL_ENABLE_BLAS=ON This will result in setting the CMake cache variable ``TPL_BLAS_LIBRARIES`` as shown in the CMake output:: -- TPL_BLAS_LIBRARIES='/user/lib/libblas.so' (NOTE: The CMake ``find_library()`` command that is used internally will always select the shared library by default if both shared and static libraries are specified, unless told otherwise. See `Building static libraries and executables`_ for more details about the handling of shared and static libraries.) However, suppose one wants to find the ``blas`` library in a non-default location, such as in:: /projects/something/tpls/lib/libblas.so In this case, one could simply configure with:: -D TPL_ENABLE_BLAS=ON \ -D BLAS_LIBRARY_DIRS=/projects/something/tpls/lib \ That will result in finding the library shown in the CMake output:: -- TPL_BLAS_LIBRARIES='/projects/something/tpls/libblas.so' And if one wants to make sure that this BLAS library is used, then one can just directly set:: -D TPL_BLAS_LIBRARIES=/projects/something/tpls/libblas.so **TPL Example 2: Intel Math Kernel Library (MKL) for BLAS** There are many cases where the list of libraries specified in the ``FindTPL.cmake`` module is not correct for the TPL that one wants to use or is present on the system. In this case, one will need to set the CMake cache variable ``_LIBRARY_NAMES`` to tell the `tribits_tpl_find_include_dirs_and_libraries()`_ function what libraries to search for, and in what order. For example, the Intel Math Kernel Library (MKL) implementation for the BLAS is usually given in several libraries. The exact set of libraries needed depends on the version of MKL, whether 32bit or 64bit libraries are needed, etc. Figuring out the correct set and ordering of these libraries for a given platform may be non-trivial. But once the set and the order of the libraries is known, then one can provide the correct list at configure time. For example, suppose one wants to use the threaded MKL libraries listed in the directories:: /usr/local/intel/Compiler/11.1/064/mkl/lib/em64t/ /usr/local/intel/Compiler/11.1/064/lib/intel64/ and the list of libraries being searched for is ``mkl_intel_lp64``, ``mkl_intel_thread``, ``mkl_core`` and ``iomp5``. In this case, one could specify this with the following do-configure script:: #!/bin/bash INTEL_DIR=/usr/local/intel/Compiler/11.1/064 cmake \ -D TPL_ENABLE_BLAS=ON \ -D BLAS_LIBRARY_DIRS="${INTEL_DIR}/em64t;${INTEL_DIR}/intel64" \ -D BLAS_LIBRARY_NAMES="mkl_intel_lp64;mkl_intel_thread;mkl_core;iomp5" \ ... ${PROJECT_SOURCE_DIR} This would call ``find_library()`` on each of the listed library names in these directories and would find them and list them in:: -- TPL_BLAS_LIBRARIES='/usr/local/intel/Compiler/11.1/064/em64t/libmkl_intel_lp64.so;...' (where ``...`` are the rest of the found libraries.) NOTE: When shared libraries are used, one typically only needs to list the direct libraries, not the indirect libraries, as the shared libraries are linked to each other. In this example, one could also play it super safe and manually list out the libraries in the right order by configuring with:: -D TPL_BLAS_LIBRARIES="${INTEL_DIR}/em64t/libmkl_intel_lp64.so;..." (where ``...`` are the rest of the libraries found in order). Adjusting upstream dependencies for a Third-Party Library (TPL) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Some TPLs have dependencies on one or more upstream TPLs. These dependencies must be specified correctly for the compile and links to work correctly. The Project already defines these dependencies for the average situation for all of these TPLs. However, there may be situations where the dependencies may need to be tweaked to match how these TPLs were actually installed on some systems. To redefine what dependencies a TPL can have (if the upstream TPLs are enabled), set:: -D _LIB_DEFINED_DEPENDENCIES=";;..." A dependency on an upstream TPL ```` will be set if the an upstream TPL ```` is actually enabled. If any of the specified dependent TPLs ```` are listed after ```` in the ``TPLsList.cmake`` file (or are not listed at all), then a configure-time error will occur. To take complete control over what dependencies an TPL has, set:: -D _LIB_ENABLED_DEPENDENCIES=";;..." If the upstream TPLs listed here are not defined upstream and enabled TPLs, then a configure-time error will occur. Disabling support for a Third-Party Library (TPL) +++++++++++++++++++++++++++++++++++++++++++++++++ Disabling a TPL explicitly can be done using:: -D TPL_ENABLE_=OFF This will result in the disabling of any direct or indirect downstream packages that have a required dependency on ```` as described in `Disable a package and all its dependencies`_. NOTE: If a disabled TPL is a required dependency of some explicitly enabled downstream package, then the configure will error out if `_DISABLE_ENABLED_FORWARD_DEP_PACKAGES`_ ``= OFF``. Otherwise, a NOTE will be printed and the downstream package will be disabled and configuration will continue. Disabling tentatively enabled TPLs ++++++++++++++++++++++++++++++++++ To disable a tentatively enabled TPL, set:: -D TPL_ENABLE_=OFF where ```` = ``BinUtils``, ``Boost``, etc. NOTE: Some TPLs in are always tentatively enabled (e.g. BinUtils for C++ stacktracing) and if all of the components for the TPL are found (e.g. headers and libraries) then support for the TPL will be enabled, otherwise it will be disabled. This is to allow as much functionality as possible to get automatically enabled without the user having to learn about the TPL, explicitly enable the TPL, and then see if it is supported or not on the given system. However, if the TPL is not supported on a given platform, then it may be better to explicitly disable the TPL (as shown above) so as to avoid the output from the CMake configure process that shows the tentatively enabled TPL being processes and then failing to be enabled. Also, it is possible that the enable process for the TPL may pass, but the TPL may not work correctly on the given platform. In this case, one would also want to explicitly disable the TPL as shown above. Require all TPL libraries be found ++++++++++++++++++++++++++++++++++ By default, some TPLs don't require that all of the libraries listed in ``_LIBRARY_NAMES`` be found. To change this behavior so that all libraries for all enabled TPLs be found, one can set:: -D _MUST_FIND_ALL_TPL_LIBS=TRUE This makes the configure process catch more mistakes with the env. Disable warnings from TPL header files ++++++++++++++++++++++++++++++++++++++ To disable warnings coming from included TPL header files for C and C++ code, set:: -D_TPL_SYSTEM_INCLUDE_DIRS=TRUE On some systems and compilers (e.g. GNU), that will result is include directories for all TPLs to be passed in to the compiler using ``-isystem`` instead of ``-I``. WARNING: On some systems this will result in build failures involving gfortran and module files. Therefore, don't enable this if Fortran code in your project is pulling in module files from TPLs. Building against pre-installed packages --------------------------------------- The project can build against any pre-installed packages defined in the project and ignore the internally defined packages. To trigger the enable of a pre-installed internal package treated as an external package, configure with:: -D TPL_ENABLE_=ON That will cause the CMake project to pull in the pre-installed package ```` as an external package using ``find_package()`` instead of configuring and building the internally defined ```` package. Configuring and building against a pre-installed package treated as an external packages has several consequences: * Any internal packages that are upstream from ```` from an enabled set of dependencies will also be treated as external packages (and therefore must be pre-installed as well). * The TriBITS package ``Dependencies.cmake`` files for the ```` package and all of its upstream packages must still exist and will still be read in by the CMake project and the same enable/disable logic will be performed as if the packages were being treated internal. (However, the base ``CMakeLists.txt`` and all of other files for these internally defined packages being treated as external packages can be missing and will be ignored.) * The same set of enabled and disabled upstream dependencies must be specified to the CMake project that was used to pre-build and pre-install these internally defined packages being treated as external packages. (Otherwise, a configure error will result from the mismatch.) * The definition of any TriBITS external packages/TPLs that are enabled upstream dependencies from any of these external packages should be defined automatically and will **not** be found again. (But there can be exceptions for minimally TriBITS-compliant external packages; see the section "TriBITS-Compliant External Packages" in the "TriBITS Users Guide".) The logic for treating internally defined packages as external packages will be printed in the CMake configure output in the section ``Adjust the set of internal and external packages`` with output like:: Adjust the set of internal and external packages ... -- Treating internal package as EXTERNAL because TPL_ENABLE_=ON -- Treating internal package as EXTERNAL because downstream package being treated as EXTERNAL -- NOTE: is indirectly downstream from a TriBITS-compliant external package -- NOTE: is indirectly downstream from a TriBITS-compliant external package All of these internally defined being treated as external (and all of their upstream dependencies) are processed in a loop over these just these TriBITS-compliant external packages and ``find_package()`` is only called on the terminal TriBITS-compliant external packages. This is shown in the CMake output in the section ``Getting information for all enabled TriBITS-compliant or upstream external packages/TPLs`` and looks like:: Getting information for all enabled TriBITS-compliant or upstream external packages/TPLs in reverse order ... Processing enabled external package/TPL: (...) -- Calling find_package( for TriBITS-compliant external package Processing enabled external package/TPL: (...) -- The external package/TPL was defined by a downstream TriBITS-compliant external package already processed Processing enabled external package/TPL: (...) -- The external package/TPL was defined by a downstream TriBITS-compliant external package already processed Processing enabled external package/TPL: (...) -- The external package/TPL was defined by a downstream TriBITS-compliant external package already processed In the above example ````, ```` and ```` are all direct or indirect dependencies of ```` and therefore calling just ``find_package()`` fully defines those TriBITS-compliant external packages as well. All remaining TPLs that are not defined in that first reverse loop are defined in a second forward loop over regular TPLs:: Getting information for all remaining enabled external packages/TPLs ... NOTE: The case is also supported where a TriBITS-compliant external package like ```` does not define all of it upstream dependencies (i.e. does not define the ``::all_libs`` target) and these external packages/TPLs will be found again. This allows the possibility of finding different/inconsistent upstream dependencies but this is allowed to accommodate some packages with non-TriBITS CMake build systems that don't create fully TriBITS-compliant external packages. xSDK Configuration Options -------------------------- The configure of will adhere to the `xSDK Community Package Policies`_ simply by setting the CMake cache variable:: -D USE_XSDK_DEFAULTS=TRUE Setting this will have the following impact: * ``BUILD_SHARED_LIBS`` will be set to ``TRUE`` by default instead of ``FALSE``, which is the default for raw CMake projects (see `Building shared libraries`_). * ``CMAKE_BUILD_TYPE`` will be set to ``DEBUG`` by default instead of ``RELEASE`` which is the standard TriBITS default (see `CMAKE_BUILD_TYPE`_). * The compilers in MPI mode ``TPL_ENABLE_MPI=ON`` or serial mode ``TPL_ENABLE_MPI=OFF`` will be read from the environment variables ``CC``, ``CXX`` and ``FC`` if they are set but the cmake cache variables ``CMAKE_C_COMPILER``, ``CMAKE_C_COMPILER`` and ``CMAKE_C_COMPILER`` are not set. Otherwise, the TriBITS default behavior is to ignore these environment variables in MPI mode. * The Fortran flags will be read from environment variable ``FCFLAGS`` if the environment variable ``FFLAGS`` and the CMake cache variable ``CMAKE_Fortran_FLAGS`` are empty. Otherwise, raw CMake ignores ``FCFLAGS`` (see `Adding arbitrary compiler flags but keeping default build-type flags`_). The rest of the required xSDK configure standard is automatically satisfied by every TriBITS CMake project, including the project. Generating verbose output ------------------------- There are several different ways to generate verbose output to debug problems when they occur: .. __TRACE_FILE_PROCESSING: a) **Trace file processing during configure:** :: -D _TRACE_FILE_PROCESSING=ON This will cause TriBITS to print out a trace for all of the project's, repository's, and package's files get processed on lines using the prefix ``File Trace:``. This shows what files get processed and in what order they get processed. To get a clean listing of all the files processed by TriBITS just grep out the lines starting with ``-- File Trace:``. This can be helpful in debugging configure problems without generating too much extra output. Note that `_TRACE_FILE_PROCESSING`_ is set to ``ON`` automatically when `_VERBOSE_CONFIGURE`_ = ``ON``. .. __VERBOSE_CONFIGURE: b) **Getting verbose output from TriBITS configure:** To do a complete debug dump for the TriBITS configure process, use:: -D _VERBOSE_CONFIGURE=ON However, this produces a *lot* of output so don't enable this unless you are very desperate. But this level of details can be very useful when debugging configuration problems. To just view the package and TPL dependencies, it is recommended to use ``-D`` `_DUMP_PACKAGE_DEPENDENCIES`_ ``= ON``. To just print the link libraries for each library and executable created, use:: -D _DUMP_LINK_LIBS=ON Of course ``_DUMP_PACKAGE_DEPENDENCIES`` and ``_DUMP_LINK_LIBS`` can be used together. Also, note that ``_DUMP_PACKAGE_DEPENDENCIES`` and ``_DUMP_LINK_LIBS`` both default t ``ON`` when ``_VERBOSE_CONFIGURE=ON`` on the first configure. c) **Getting verbose output from the makefile:** :: -D CMAKE_VERBOSE_MAKEFILE=TRUE NOTE: It is generally better to just pass in ``VERBOSE=`` when directly calling ``make`` after configuration is finished. See `Building with verbose output without reconfiguring`_. d) **Getting very verbose output from configure:** :: -D _VERBOSE_CONFIGURE=ON --debug-output --trace NOTE: This will print a complete stack trace to show exactly where you are. Enabling/disabling deprecated warnings -------------------------------------- To turn off all deprecated warnings, set:: -D _SHOW_DEPRECATED_WARNINGS=OFF This will disable, by default, all deprecated warnings in packages in . By default, deprecated warnings are enabled. To enable/disable deprecated warnings for a single package, set:: -D _SHOW_DEPRECATED_WARNINGS=OFF This will override the global behavior set by ``_SHOW_DEPRECATED_WARNINGS`` for individual package ````. Adjusting CMake DEPRECATION warnings ------------------------------------ By default, deprecated TriBITS features being used in the project's CMake files will result in CMake deprecation warning messages (issued by calling ``message(DEPRECATION ...)`` internally). The handling of these deprecation warnings can be changed by setting the CMake cache variable ``TRIBITS_HANDLE_TRIBITS_DEPRECATED_CODE``. For example, to remove all deprecation warnings, set:: -D TRIBITS_HANDLE_TRIBITS_DEPRECATED_CODE=IGNORE Other valid values include: * ``DEPRECATION``: Issue a CMake ``DEPRECATION`` message and continue (default). * ``AUTHOR_WARNING``: Issue a CMake ``AUTHOR_WARNING`` message and continue. * ``SEND_ERROR``: Issue a CMake ``SEND_ERROR`` message and continue. * ``FATAL_ERROR``: Issue a CMake ``FATAL_ERROR`` message and exit. Disabling deprecated code ------------------------- To actually disable and remove deprecated code from being included in compilation, set:: -D _HIDE_DEPRECATED_CODE=ON and a subset of deprecated code will actually be removed from the build. This is to allow testing of downstream client code that might otherwise ignore deprecated warnings. This allows one to certify that a downstream client code is free of calling deprecated code. To hide deprecated code for a single package set:: -D _HIDE_DEPRECATED_CODE=ON This will override the global behavior set by ``_HIDE_DEPRECATED_CODE`` for individual package ````. Outputting package dependency information ----------------------------------------- .. __DEPS_DEFAULT_OUTPUT_DIR: To generate the various XML and HTML package dependency files, one can set the output directory when configuring using:: -D _DEPS_DEFAULT_OUTPUT_DIR:FILEPATH= This will generate, by default, the output files ``PackageDependencies.xml``, ``PackageDependenciesTable.html``, and ``CDashSubprojectDependencies.xml``. If ``_DEPS_DEFAULT_OUTPUT_DIR`` is not set, then the individual output files can be specified as described below. .. __DEPS_XML_OUTPUT_FILE: The filepath for PackageDependencies.xml can be overridden (or set independently) using:: -D _DEPS_XML_OUTPUT_FILE:FILEPATH= .. __DEPS_HTML_OUTPUT_FILE: The filepath for ``PackageDependenciesTable.html`` can be overridden (or set independently) using:: -D _DEPS_HTML_OUTPUT_FILE:FILEPATH= .. __CDASH_DEPS_XML_OUTPUT_FILE: The filepath for CDashSubprojectDependencies.xml can be overridden (or set independently) using:: -D _CDASH_DEPS_XML_OUTPUT_FILE:FILEPATH= NOTES: * One must start with a clean CMake cache for all of these defaults to work. * The files ``PackageDependenciesTable.html`` and ``CDashSubprojectDependencies.xml`` will only get generated if support for Python is enabled. Test-related configuration settings ----------------------------------- Many options can be set at configure time to determine what tests are enabled and how they are run. The following subsections described these various settings. Enabling different test categories ++++++++++++++++++++++++++++++++++ To turn on a set a given set of tests by test category, set:: -D _TEST_CATEGORIES=";;..." Valid categories include ``BASIC``, ``CONTINUOUS``, ``NIGHTLY``, ``HEAVY`` and ``PERFORMANCE``. ``BASIC`` tests get built and run for pre-push testing, CI testing, and nightly testing. ``CONTINUOUS`` tests are for post-push testing and nightly testing. ``NIGHTLY`` tests are for nightly testing only. ``HEAVY`` tests are for more expensive tests that require larger number of MPI processes and longer run times. These test categories are nested (e.g. ``HEAVY`` contains all ``NIGHTLY``, ``NIGHTLY`` contains all ``CONTINUOUS`` and ``CONTINUOUS`` contains all ``BASIC`` tests). However, ``PERFORMANCE`` tests are special category used only for performance testing and don't nest with the other categories. Disabling specific tests ++++++++++++++++++++++++ Any TriBITS-added ctest test (i.e. listed in ``ctest -N``) can be disabled at configure time by setting:: -D _DISABLE=ON where ```` must exactly match the test listed out by ``ctest -N``. This will result in the printing of a line for the excluded test when `Trace test addition or exclusion`_ is enabled and the test will not be added with ``add_test()`` and therefore CTest (and CDash) will never see the disabled test. Another approach to disable a test is the set the ctest property ``DISABLED`` and print and a message at configure time by setting:: -D _SET_DISABLED_AND_MSG="" In this case, the test will still be added with ``add_test()`` and seen by CTest, but CTest will not run the test locally but will mark it as "Not Run" (and post to CDash as "Not Run" tests with test details "Not Run (Disabled)" in processes where tests get posted to CDash). Also, ```` will get printed to STDOUT when CMake is run to configure the project and ``-D_TRACE_ADD_TEST=ON`` is set. Also, note that if a test is currently disabled using the ``DISABLED`` option in the CMakeLists.txt file, then that ``DISABLE`` property can be removed by configuring with:: -D _SET_DISABLED_AND_MSG=FALSE (or any value that CMake evaluates to FALSE like "FALSE", "false", "NO", "no", "", etc.). Also note that other specific defined tests can also be excluded using the ``ctest -E`` argument. Disabling specific test executable builds +++++++++++++++++++++++++++++++++++++++++ Any TriBITS-added executable (i.e. listed in ``make help``) can be disabled from being built by setting:: -D _EXE_DISABLE=ON where ```` is the name of the target in the build system. Note that one should also disable any ctest tests that might use this executable as well with ``-D_DISABLE=ON`` (see above). This will result in the printing of a line for the executable target being disabled at configure time to CMake STDOUT. Disabling just the ctest tests but not the test executables +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To allow the building of the tests and examples in a package (enabled either through setting `_ENABLE_TESTS`_ ``= ON`` or `_ENABLE_TESTS`_ ``= ON``) but not actually define the ctest tests that will get run, configure with:: -D _SKIP_CTEST_ADD_TEST=TRUE \ (This has the effect of skipping calling the ``add_test()`` command in the CMake code for the package ````.) To avoid defining ctest tests for all of the enabled packages, configure with:: -D _SKIP_CTEST_ADD_TEST=TRUE \ (The default for ``_SKIP_CTEST_ADD_TEST`` for each TriBITS package ```` is set to the project-wide option ``_SKIP_CTEST_ADD_TEST``.) One can also use these options to "white-list" and "black-list" the set of package tests that one will run. For example, to enable the building of all test and example targets but only actually defining ctest tests for two specific packages (i.e. "white-listing"), one would configure with:: -D _ENABLE_ALL_PACKAGES=ON \ -D _ENABLE_TESTS=ON \ -D _SKIP_CTEST_ADD_TEST=TRUE \ -D _SKIP_CTEST_ADD_TEST=FALSE \ -D _SKIP_CTEST_ADD_TEST=FALSE \ Alternatively, to enable the building of all test and example targets and allowing the ctest tests to be defined for all packages except for a couple of specific packages (i.e. "black-listing"), one would configure with:: -D _ENABLE_ALL_PACKAGES=ON \ -D _ENABLE_TESTS=ON \ -D _SKIP_CTEST_ADD_TEST=TRUE \ -D _SKIP_CTEST_ADD_TEST=TRUE \ Using different values for ``_SKIP_CTEST_ADD_TEST`` and ``_SKIP_CTEST_ADD_TEST`` in this way allows for building all of the test and example targets for the enabled packages but not defining ctest tests for any set of packages desired. This allows setting up testing scenarios where one wants to test the building of all test-related targets but not actually run the tests with ctest for a subset of all of the enabled packages. (This can be useful in cases where the tests are very expensive and one can't afford to run all of them given the testing budget, or when running tests on a given platform is very flaky, or when some packages have fragile or poor quality tests that don't port to new platforms very well.) NOTE: These options avoid having to pass specific sets of labels when running ``ctest`` itself (such as when defining ``ctest -S