CMake ≥ 3.19 is strongly recommended for general users for more robust and easy syntax.
For project developers, we recommend CMake ≥ 3.24 as the new features make debugging CMake and setting up CI considerably easier.
Downloading the latest release of CMake is usually easy.
For Linux and Mac, admin/sudo is NOT required.
For platforms where CMake binaries aren’t easily available, use
build_cmake.cmake.
CMake 3.24
adds the long-awaited cmake -Bbuild --fresh option to clean the build directory first.
CMake 3.23 further enhances
–debug-find
to allow debugging all find_* command, or specific find_package or find_* variables.
Header files can be more cleanly installed/affiliated with targets, particularly relevant for packaging and installing with
target_sources
file sets.
CMake 3.22 adds several CMake Environment Variables that are generally useful.
CMAKE_BUILD_TYPE default for single configuration build systems.
CMAKE_CONFIGURATION_TYPES defaults available configurations for multi-config build systems like Ninja Multi-Config.
CMAKE_INSTALL_MODE makes symlinks with copy fallback a good choice for installing programs from CMake.
For CTest, the new ENVIRONMENT_MODIFICATION test property makes modifying environment variables for test(s) much easier.
CMake 3.21
adds more preset features, including making “generator” optional–the default CMake behavior will be used to determine generator.
The cmake --install-prefix option can be used instead of cmake -DCMAKE_INSTALL_PREFIX=.
PROJECT_IS_TOP_LEVEL and <PROJECT-NAME>_IS_TOP_LEVEL identify if a project is at the top of the project hierarchy.
ctest --output-junit gives test output in standard tooling format.
CMake 3.20
adds support for Intel NextGen LLVM compiler and NVIDIA HPC compiler.
ExternalProject_Add() learned CONFIGURE_HANDLED_BY_BUILD which avoids CMake commanding a reconfigure on each build.
try_compiler(WORKING_DIRECTORY) was added.
CMake presets in CMakePresets.json now covers configure, build and test, allowing many parameters to be declared with inheritance in JSON.
CMake presets are a key feature for CI, as well as user configurations.
ctest --test-dir build option avoids the need to manually cd build.
cmake_path
allows path manipulation and introspection without actually touching the filesystem.
CMake 3.19 added support for ISPC language.
string(JSON GET|SET) parsing is very useful to avoid hard-coding parameters.
FindPython/find_package accepts version ranges.
Intel oneAPI works with CMake ≥ 3.19.6.
Emits deprecation warning for cmake_minimum_required VERSION less than 2.8.12.
CMakePresets.json enables configure parameter declarations in JSON.
Adds REQUIRED parameter to find_program.
Adds file(ARCHIVE_CREATE) and file(ARCHIVE_EXTRACT)
CMake 3.17
adds
Ninja Multi-Config generator.
cmake
–debug-find
shows what find_*() is doing.
Eliminates Windows “sh.exe is on PATH” error.
Recognizes that Ninja works with Fortran.
CMake 3.15 adds CMAKE_GENERATOR environment variable that works like global -G option.
Enhances Python interpreter finding.
Adds cmake --install command instead of “cmake –build build –target install”.
Added Zstd compression.
CMake 3.14: I created check_fortran_source_runs().
FetchContent was enhanced with simpler syntax.
The transitive link resolution was considerably enhanced in CMake 3.14.
Projects just work in CMake ≥ 3.14 that fail at link-time with CMake < 3.14.
We don’t recommend use of the older CMake versions below as they take significantly more effort to support.
CMake 3.13
adds ctest --progress and better Matlab compiler support.
Lots of new linking options are added, fixes to Fortran submodule bugs.
The very convenient cmake -B build incantation, target_sources() with absolute path are also added.
It’s significantly more difficult to use CMake older than 3.13 with medium to large projects.
CMake 3.12 adds transitive library specification (out of same directory) and full Fortran Submodule support.
get_property(_test_names DIRECTORY . TESTS) retrieves test names in current directory.
CMake 3.11 allows specify targets initially w/o sources.
FetchContent is added, allowing fast hierarchies of CMake and non-CMake projects.
NOTE: This process is for Intel CPU hardware only!
While it may be possible to compile MPICH on Apple Silicon with Intel oneAPI, most programs will not compile or run.
Intel oneAPI for MacOS currently does NOT include MPI.
MPICH can be compiled with Intel oneAPI for MPI programs on MacOS with Intel oneAPI.
This process also produces “mpiexec” for running MPI programs.
We suggest using the “online installer” download, which is a small download.
The “online” installer can be copied over SSH to your HPC user account for example and installed from the Terminal.
Install Xcode and Xcode Command Line Tools.
MPICH will work with Intel oneAPI to provide the MPI libraries and MPIexec with Intel CPU.
Download and extract the stable MPICH source.
Use commands like:
source /opt/intel/oneapi/setvars.sh
export FC=ifort CC=icc CXX=icpc
mkdir -p $HOME/lib_intel/mpich
./configure --prefix=$HOME/lib_intel/mpich
# the configure step may take tens of minutesmake -j4
# limit number of parallel to avoid crashing buildmake install -j4
To use this MPICH with Intel oneAPI in general via CMake, make a file ~/intel.sh like:
If upon compiling a C program stdio.h isn’t found or a C++ program wchar.h isn’t found, install
Xcode Command Line Tools for the Xcode version currently installed.
If the program persists, the problem may be that the Xcode include path may not be in Intel’s scripts.
To workaround this issue, look for the Command Line Tools include directory and make a file ~/intel.sh including (check the directory name):
#!/bin/sh
set -o errexit
source /opt/intel/oneapi/setvars.sh
export LIBRARY_PATH=$LIBRARY_PATH:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
export CPLUS_INCLUDE_PATH=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
export CXXFLAGS=-I$CPLUS_INCLUDE_PATH
export CFLAGS=$CXXFLAGS
export FC=ifort CC=icc CXX=icpc
# oneAPI on MacOS doesn't yet have the IntelLLVM compilers
and
source ~/intel.sh
to use Intel oneAPI.
If you try to use Apple Silicon with Intel oneAPI:
Intel MKL FATAL ERROR: This system does not meet the minimum requirements for use of the Intel(R) Math Kernel Library.
The processor must support the Intel(R) Supplemental Streaming SIMD Extensions 3 (Intel(R) SSSE3) instructions.
The processor must support the Intel(R) Streaming SIMD Extensions 4.2 (Intel(R) SSE4.2) instructions.
The processor must support the Intel(R) Advanced Vector Extensions (Intel(R) AVX) instructions.
On Windows, when building an executable target in Debug mode using Visual Studio or Intel oneAPI, it may be necessary to also have the libraries linked by the target to have Debug symbols.
For example, when building in CMake:
error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in main.cpp.obj
error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MDd_DynamicDebug' in main.cpp.obj
The solution is to build the libraries with Debug mode as well.s
MacOS package managers allow easy download, build and install of developer programs and libraries.
Homebrew
is by far the most popular MacOS package manager.
Homebrew has a large number of packages and the ability to create unofficial “taps” to easily distribute software.
Homebrew installs packages under “/opt/homebrew” on Apple Silicon systems.
Homebrew taps allow distributing binaries via Homebrew before going to include in the main homebrew package repo, which takes time and justification.
Homebrew distributes per-OS compiled binaries, so package install time is almost instant.
It is possible to also download source and build locally with Homebrew if desired.
MacPorts
generally distributes source code that is compiled on install, although it can also use precompiled binaries.
Macports installs packages under a
prefix.
Homebrew is much more popular than MacPorts or
Fink.
Anaconda Python puts itself first on PATH when activated.
This can become a problem for libraries like HDF5, where “conda install h5py” puts compiler wrapper “h5cc” on PATH first.
For systems where Homebrew is used to provide packages to find from CMake, tell CMake to prefer a package location with
CMAKE_PREFIX_PATH.
CMake Git operations such as shallow clone can cause unexpected failures due to too small INACTIVITY_TIMEOUT in ExternalProject or FetchContent.
Be sure to set INACTIVITY_TIMEOUT to a large enough value.
15 seconds is too short a timeout for Git shallow clone, for example.
Consider 60 seconds or larger INACTIVITY_TIMEOUT.
Also check the user ~/.gitconfig file for
timeout:
[http]lowSpeedLimit=1000
lowSpeedTime = 60
If lowSpeedTime is too short, this download failure can also occur.
Set to 60 seconds or more.
Normally it is not necessary to specify the path to the CMake generator backend, assuming the generator executable is on the system PATH.
For special use cases such as testing CMake with different versions of a generator the generator executable absolute path may be specified via
CMAKE_MAKE_PROGRAM.
The absolute path to the generator is necessary or CMake will not find it.
Compilers define macros that can be used to identify a compiler and platform from compiled code, such as C, C++, Fortran, et al.
This can be used for platform-specific or compiler-specific code.
If a significant amount of code is needed, it may be better to swap in different code files using the build system instead of lengthly #ifdef logic.
There are numerous examples for C and C++ so here we focus on macros of Fortran compilers.
Gfortran compiler macro definitions are obtained in an OS-agnostic way by:
echo "" | gfortran -dM -E - > macros.txt
that creates a file “macros.txt” containing all the compiler macros.
commonly used macros to detect operating system / compiler configuration include:
_WIN32 1
__linux__ 1
__unix__ 1
__APPLE__ 1
CAUTION: these macros are actually not available in the Gfortran compiled programs as they are in GCC.
A workaround is to have the build system define these for the particular compiler, OS, etc.
Intel oneAPI classiccompiler macros
include the Gfortran macros noted above and additionally:
CMake Find modules are by their nature a little aggressive about finding libraries and executables.
This becomes a factor on Windows in particular when Anaconda Python is not active in the current Terminal.
CMake find_package(Python) will by default still prefer Anaconda Python, but it won’t operate correctly without conda activate, which presumably the user has either forgotten to do or doesn’t desire at the moment.
To decrease the aggressiveness and find Windows Store Python etc. when conda isn’t activated on Windows, add to the project CMakeLists.txt beforefind_package(Python):
set(Python_FIND_REGISTRYLAST)# this avoids non-active conda from getting picked anyway on Windows
find_package(Python)