Homebrew GCC version select
Homebrew can select GCC versions like:
brew install gcc@13Of course, the Homebrew binaries (or source conmpile scripts) must be available for the CPU architecture and OS version of the computer.
Homebrew can select GCC versions like:
brew install gcc@13Of course, the Homebrew binaries (or source conmpile scripts) must be available for the CPU architecture and OS version of the computer.
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.
Check for timeout in:
git config --get http.lowSpeedLimit
git config --get http.lowSpeedTimelowSpeedLimit might be set to 1000 (bits/second) or as appropriate for the network. 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 in environment variable $PATH or
CMAKE_PROGRAM_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.
Suppose a GitHub Actions Linux image has ninja-linux.zip containing executable file “ninja”. Get the absolute path using realpath.
- run: unzip ninja-linux.zip
- name: CMake configure
run: cmake -G Ninja -DCMAKE_MAKE_PROGRAM=$(realpath ./ninja) -BbuildCMake 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) by default prefers Anaconda Python over system Python unless overridden as below.
Anaconda Python 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 before
find_package(Python):
set(Python_FIND_REGISTRY LAST)
# this avoids non-active conda from getting picked anyway on Windows
set(Python_FIND_VIRTUALENV STANDARD)
# Use environment variable PATH to decide preference for Python
find_package(Python)Anaconda Python by default auto-activates the “base” environment each time a new Terminal is opened. This slows opening new Terminal, particularly on systems with slow disks or virtual disks. Particularly if the user isn’t constantly using Python, it can be beneficial to make conda only active when specified. To disable conda auto-activation on new Terminal, type:
conda config --set auto_activate_base falseThis setting takes effect in .condarc
Fortran compilers typically have options for enforcing Fortran standards.
The compilers raise additional warnings or errors for code that is not deemed compliant.
Fortran standard options can make false warnings, so we generally do not enable standards checking for user defaults.
However, we do enforce implicit none as a quality measure.
It’s also important to use implicit none so that each variable must be assigned beforehand.
We recommend the Fortran 2018 statement:
implicit none (type, external)which requires explicitly defined procedure interfaces as well.
typeimplicit none defaultexternalGCC Gfortran -std=f2018 enforces Fortran 2018 standard. Consider these Gfortran options:
gfortran -Wall -fimplicit-noneIntel oneAPI
-stand f18
enforces Fortran 2018 standard.
Consider these
options
that also enforce implicit none:
ifx -warnCray Fortran compiler enforces implicit none via
option:
ftn -eInote that’s a capital “I” not a lowercase “ell”.
Nvidia HPC Fortran compiler enforces implicit none via:
nvfortran -MdclchkNAG Fortran has
-f2018
Fortran 2018 flag.
Enforce implicit none by:
nagfor -uCMake logic to enforce these standards:
if(CMAKE_Fortran_COMPILER_ID STREQUAL "Cray")
add_compile_options("$<$<COMPILE_LANGUAGE:Fortran>:-eI>")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
add_compile_options(-Wall "$<$<COMPILE_LANGUAGE:Fortran>:-fimplicit-none>")
elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel")
add_compile_options("$<$<COMPILE_LANGUAGE:Fortran>:-warn>")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "NVHPC")
add_compile_options("$<$<COMPILE_LANGUAGE:Fortran>:-Mdclchk>")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "NAG")
add_compile_options("$<$<COMPILE_LANGUAGE:Fortran>:-u>")
endif()GCC Gfortran and Intel oneAPI are the most advanced, widely available modern Fortran compilers.
Useful Fortran 2018 enhancements include:
select rank
assumed array rank,
error stop
within pure procedures,
random_init
to initialize random number seed, and
implicit none (type, external)
to require external procedures to be explicitly declared.
GCC 10 is the
oldest version
currently maintained.
Intel oneAPI has full Fortran 2018
support.
To get recent GCC is usually straightforward. Red Hat should use GCC Toolset. macOS Homebrew quickly adds the latest GCC version. If Ubuntu gfortran repo defaults aren’t adequate, get recent Gfortran via PPA.
Here are some of the major changes in Gfortran by version:
bind(C) with character length greater than one.select rankrandom_init() to initialize the random generator seed.do concurrent, actual argument array with too few elements for dummy argument now errors, initial support for parameterized derived types (simply define kind at initialization) and coarray support for teams. Standard flag -std=f2018 added and deprecated -std=f2008ts.select type. Complete Fortran 2003 support, Fortran 2018 non-constant stop and error stop codes, and -fdec- options to help compile very old non-standard code.Gfortran 6 added Fortran 2008 submodule support, useful for large projects to save compilation time and allow powerful use scenarios.
Fortran 2003 deferred-length character are
useful
for avoiding bothersome trim() everywhere.
GCC 5 added full support for OpenMP 4.0, Fortran 2003 ieee_ intrinsics, Fortran 2008 error stop in pure procedures with constant error code.
GCC 4.9 added Fortran 2003 deferred-length character variables in derived types.
GCC 4.8 supported Fortran 2008 polymorphism, including select type, class(*), type(*), and Fortran 2018 assumed rank dimension(..).
GCC 4.6 was the first version of Gfortran reaching beyond Fortran 95, with Fortran 2003 deferred-length character variable and Fortran 2008 impure elemental support.
GCC 4.5 added Fortran 2008 iso_fortran_env.
GCC 4.4 added initial support for polymorphism and OpenMP 3.
CMake allows switching parameters based on compiler version. This is very useful for modern Fortran programs.
Example CMakeLists.txt for Fortran compiler version dependent options.
if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
add_compile_options(
-Wall
$<$<COMPILE_LANGUAGE:Fortran>:-fimplicit-none>
)
endif()
add_executable(myprog main.f90)Reference: Gfortran changelog
CMake can detect the host CPU arch to use with Intel compilers. We discourage package maintainers from setting flags automatically like “-march=native” (GCC, Clang) and “-xHost” (Intel oneAPI) because they may break on user systems such as ARM or HPC. However, the user can set flags for a project by setting environment variables like CFLAGS before the first project configure in CMake. This allows optimizing for a target compiler while compiling from a different host. Or, the user on an appropriate system may simply set their ~/.profile to have CFLAGS=-march=native or similar.
Projects use a variety of methods to detect which compiler is being used to thereby set compilation options. Although this discussion focuses on Fortran, it is easily and equally applicable to other languages such as C and C++.
Robustly detect compiler in CMake CMAKE_Fortran_COMPILER_ID. This tells the compiler vendor (GNU, Intel, Clang, etc.) Don’t use CMAKE_Fortran_COMPILER because there are several compiler executables per vendor and this will not be robust over time. To get the compiler version, CMAKE_Fortran_COMPILER_VERSION allows version comparisons.
Example:
if(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel")
add_compile_options("$<$<COMPILE_LANGUAGE:Fortran>:-check;-warn;-traceback>")
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
# Gfortran
add_compile_options("$<$<COMPILE_LANGUAGE:Fortran>:-Wall;-Werror=array-bounds;-Wextra;-Wpedantic>")
endif()_set_printf_count_output is a Visual-Studio only function. Therefore, C++ programs that call it should use a preprocessor conditional:
#ifdef _MSC_VER
_set_printf_count_output();
#endif