Clang,
LLVM Flang Fortran compiler,
GCC, Boost and many more packages are easily available on Windows via
MSYS2.
Clang is also available via direct
download.
it’s often useful to have separate development environments for each compiler.
The Powershell script “clang.ps1” creates a Clang LLVM environment.
We don’t permanently put Clang on the user or system PATH to avoid DLL conflicts.
Running “clang.ps1” in Powershell enables Clang until that Powershell window is closed.
$r="$Env:SystemDrive/msys64/ucrt64"$b="$r/bin"$Env:CC="$b/clang"$Env:CXX="$b/clang++"$Env:FC="$b/flang"# important to put UCRT first to avoid "collect2.exe: error: ld returned 116 exit status" and DLL Hell$Env:Path = "$b;$Env:Path"$Env:CMAKE_PREFIX_PATH="$r"
For standalone (non-MSYS2) Clang make “clang.ps1” like:
HDF4
is a predecessor to the industry-standard HDF5 data file format.
This
HDF4 CMake example
shows how to build and link HDF4 seamlessly with Fortran example code.
Users and developers might accidentally build a program or library without optimizations when they are desired.
This could make the runtime 10 to 1000 times or more slower than it would be with optimizations.
This could be devastating in computational cost on HPC and cause needless schedule delays.
Programmatically detecting or using a heuristic to determine if a program was built with optimizations can help prevent this.
Such methods are language-specific.
CMake, NDEBUG is set if CMAKE_BUILD_TYPE is Release or RelWithDebInfo.
Meson: NDEBUG is set if buildtype is release or debugoptimized with
There is currently no universal language standard method in C / C++ to determine if optimization was used on build.
The presence of macro NDEBUG is used by the
standard library
to
disable assertions.
One could use if NDEBUG is defined as an indication if optimizations were used.
boolfs_is_optimized(){
// This is a heuristic, trusting the build system or user to set NDEBUG if optimized.
#if defined(NDEBUG)
return true;
#else
return false;
#endif
}
If the Fortran code is compiled with preprocessing, a method using NDEBUG as above could be used.
Fortran iso_fortran_env provides functions
compiler_version
and
compiler_options.
These could be used in a fine-grained, per compiler way to determine if optimizations were used.
Distributed Python environments would virtually always be optimized.
One can use heuristic checks to help indicate if the Python executable was built in debug mode.
I am not yet aware of a universal method to determine if the CPython executable was built with optimizations.
HDF5 command line tools
h5dump and h5ls are handy to quickly explore HDF5 files from the command line.
Backup link to
old documentation.
They are particularly useful when accessing a remote computer such as HPC where the HDF5 files may be very large and would take a while to transfer to a local computer.
h5ls
provides a high-level look at objects in an HDF5 file.
Typically we start examining HDF5 files by printing the dataset hierarchy:
h5ls --recursive my.h5
Determine the filters used (e.g. was the data compressed):
h5ls --verbose my.h5
h5dump
can print the entire contents of an HDF5 file to the screen.
This can be overwhelming, so we typically print only the headers to start:
h5dump --header my.h5
Individual variables can be printed like:
h5dump --dataset=myvar my.h5
Determine the filters used (e.g. was the data compressed):
The C++ Standard Library uses size_type as a property of containers like std::vector, std::string, etc.
This is
generally recommended
over using size_t directly.
Example C++ code snippets using size_type property:
Intel oneAPI is a cross-platform toolset that covers several programming languages including C, C++, Fortran and Python.
Intel oneAPI replacesIntel Parallel Studio.
Intel oneAPI including the C++ “icpx” compiler, Fortran “ifx” compiler, and Intel MPI is free-to-use and no login is required to download oneAPI.
We suggest using the “online installer” download, which is a small download.
The “online” installer can be copied over SSH to an HPC user directory for example and installed from the Terminal.
Windows requires Visual Studio Community to be installed first–IDE integration is optional and we don’t use it.
Visual Studio integration is optional–if installed, cmake -G "Visual Studio 17 2022" can be used to generate Visual Studio project files.
There are distinct usage patterns to access Intel oneAPI compilers on Windows vs. Linux.
Set environment variables CC, CXX, FC
via script.
oneapi-vars sets environment variable CMAKE_PREFIX_PATH so don’t just blindly overwrite that environment variable.
On Windows a Start menu shortcut for a oneAPI command prompt is installed.
Powershell can also use “oneapi-vars.bat” to set the environment variables as per the oneapi.ps1 in the Gist above.
If CMake Visual Studio generater is desired, ensure:
CMake ≥ 3.29 is used
Intel oneAPI Visual Studio integrations are installed
cmake -Bbuild -G "Visual Studio 17 2022" -T fortran=ifx
Troubleshooting:
If problems with finding packages with oneAPI on Windows and CMake occur, ensure that MSYS2 paths aren’t mixed in with the oneAPI environment.
See the project
CMakeConfigureLog.yaml
and look for unwanted paths in the include commands.
On Linux, oneAPI requires
GNU GCC toolchain.
Some HPC systems have a too-old GCC version default for Intel oneAPI.
This can cause problems with C++ STL linking.
If needed, set environment variable CXXFLAGS for
Intel GCC toolchain
in custom “oneapi.sh” like:
CI runners across CI services often update software images regularly, perhaps weekly.
This can break workflows, but reflects user devices.
GitHub Actions updates the runners weekly or so.
A few times a year on average across projects and operating system this may require updating the CI YaML configuration.
Apple updates of XCode a few times a year this can disrupt end users and CI runs.
To have a version stable CI image would generally require private on-premises CI like Jenkins or GitHub Actions for on-premises.
Those on-premises CI runners then need maintenance.
The key issue with such frozen CI runners is they are out of date with what end users have.
For example, macOS with Homebrew is probably the majority of scientific computing users besides HPC.
Homebrew updates often and breaks occur across projects a few times a year.
Better to catch that in CI rather than on end user devices.
CMake can detect if a project is “top level” that is, NOT via FetchContent using
PROJECT_IS_TOP_LEVEL
and
PROJECT_NAME_IS_TOP_LEVEL
.
For simplicity, we denote these variables in this article as “*_IS_TOP_LEVEL”.
Example use:
if(${PROJECT_NAME}_IS_TOP_LEVEL) message(STATUS"${PROJECT_NAME} directly building, not FetchContent")endif()
Directory property
PARENT_DIRECTORY
and *_IS_TOP_LEVEL are NOT useful for detecting if the child project is being used as an ExternalProject.
These variables are based on the last “project()” command and so are not as universally useful as it first seems.
For example, these variables do not work as expected when using ExternalProject.
Even setting CMAKE_CACHE_ARGS of ExternalProject does not help, nor does cmake (1) command line options–the CMake-internal setting of *_IS_TOP_LEVEL overrides this attempt to set it.
To workaround this, use an arbitrary auxiliary variable to detect if the project is top level.
Rather than try to directly workaround all the corner cases of *_IS_TOP_LEVEL, using this auxiliary variable allows the user to clearly force the intended behavior.
This is useful when the subprojects and main project can build required ExternalProjects, and you want to only build the required ExternalProjects once.
GCC on macOS including Homebrew-installed depends on the macOS SDK.
When the macOS SDK is updated, the system headers may become incompatible with
GCC versions < 13.3.
Specifically, there can be syntax changes requiring C23 but that GCC < 13.3 could not handle.
Homebrew GCC 14.1 and newer work just fine, so the solution is to update GCC.