Scientific Computing

CMake VS 2026 on GitHub Actions

The CMake variable CMAKE_GENERATOR can be used with GitHub Actions to specify the Visual Studio 18 2026 generator. Currently, the runner image GitHub Actions runner image windows-2025-vs2026 is used until the “windows-latest” runner image incorporates VS 2026.

jobs:

  msvc:
    runs-on: windows-2025-vs2026

    steps:
    - uses: actions/checkout

    - name: Print CMake version
      run: cmake --version

    - name: Configure CMake
      run: cmake -B build -G "Visual Studio 18 2026"

    # and so on

Recursively clean CMake build directories

CMake build directories might contain 100s of megabytes of files for large projects. Over time, a developer computer might contain forgotten build directories that waste tens of gigabytes of disk space. With Python, a script using send2trash allows safe removal of CMake build directories by first moving them to the OS Trash / Recycle bin.

OS Trash location
macOS ~/.Trash
Linux ~/.local/share/Trash/files
Windows Hidden folder accessed from Powershell like Get-ChildItem -Path 'C:\$Recycle.Bin' -Force

In distinction from shutil.rmtree, this send2trash approach allows recovery of files if the deletion was accidental. The heuristic used to detect a CMake build directory was inspired by ctest_empty_binary_directory.

mpi_f08 Fortran on Windows

use mpi_f08 is recommended for Fortran across computing platforms, including Windows.

For native x86 (Intel / AMD CPU) binaries, currently only free Intel oneAPI has mpi_f08 for Fortran. As time progresses and ARM64 CPUs are increasingly widespread, including for Windows PCs, and the complexity / disk space requirements of setting up Visual Studio for Intel oneAPI on Windows, it may be better (easier, faster, performance) to use WSL for Windows MPI. WSL can use OpenMPI or MPICH to access mpi_f08. For Windows ARM CPU users, WSL is the only straightforward option for mpi_f08 in Fortran.

GitHub Actions with Windows Subsystem for Linux

The setup-wsl GitHub Action configures WSLv2 environment in Windows GitHub Actions runners. This allows testing certain quirks and corner cases one might encounter when running software on Windows Subsystem for Linux. For scientific computing Windows users, WSL is often the best way to run computational software on Windows, including software using performance code for GPU and MPI.

Git submodule shallow

Git projects using submodules can be set to default shallow Git clone submodules to save space and time. Edit the “.gitmodules” file to have the “shallow = true” option for each Git submodule. This is particularly useful when the top-level project uses third party libraries or libraries with a large Git revision history.

Example .gitmodules file with shallow Git submodules:

[submodule "proj1"]
	path = proj1
	url = https://github.invalid/nobody/proj1
    shallow = true

Then Git clone with the --recurse-submodules option or Git submodule update with the --init --recursive options:

git clone --recurse-submodules <url>

or if already Git cloned

git submodule update --init --recursive

performs a shallow clone of the Git submodules.

Confirm that the submodules are shallow cloned by checking the Git log of the submodule:

git -C ./proj1 rev-parse --is-shallow-repository

These each return “true” indicating that the submodule is shallow cloned.

USB-C display adapter incompatibilities

USB-C dock display adapters (HDMI, DisplayPort) are generally seen as a preferable replacement for proprietary docking ports on old bulky laptops. A symptom is USB-C adapter works on one laptop, but not on another almost identical laptop model.

For Apple hardware, USB-C docks might only work with DisplayPort connection, not HDMI. This may be because some USB-C docks use “DisplayPort Alternate Mode”, which macOS seems not to recognize with an HDMI connection even on the same monitor that works with a DisplayPort cable connection.

General symptoms across hardware and operating systems include the dock display not being detected by the operating system, to showing a black screen, or very low resolution.

The solution seems to be to stick with expensive OEM display adapters, or at least long established brands. The temptation of a cheap adapter can quickly turn to frustration or botched presentations. Another thing to watch for is cheap adapters may fail intermittently when using more than one high bandwidth feature. For example, using Gigabit Ethernet and HDMI on the cheap USB-C adapter simultaneously may fail intermittently during a conference call or teaching a class, which can be frustrating.

Workarounds

Some adapters that charge the laptop with a USB-C input for power may experience improper operations if the display adapter is plugged into the laptop while the USB-C power input is powered. This problem may persist upon re-plugging the adapter to laptop and/or power cycling the monitor and laptop. A workaround we’ve found is to unplug USB-C power input to the adapter, plug into the laptop with all the desired accessories, then finally plug USB-C power input into the adapter. That is unexpected, but has worked for us sometimes.

Install Intel oneAPI C++ and Fortran compiler

Intel oneAPI is a cross-platform toolset that covers several programming languages including C, C++, Fortran and Python. Intel oneAPI includes the C++ “icpx” compiler, Fortran “ifx” compiler, Intel MKL, and Intel MPI. oneAPI is free-to-use and no login is required to download and install. oneAPI can be installed via package manager or manually.

Package manager install

On Windows, Intel oneAPI offline installer can be installed via WinGet:

winget install --id=Intel.OneAPI.BaseToolkit
winget install --id=Intel.OneAPI.HPCToolkit

On Linux, Intel oneAPI is typically available via distro package managers.

Online install

The “online” installer can be copied over SSH to an HPC user directory for example and installed from the Terminal.

Install the oneAPI Base Toolkit with options:

  • Math Kernel Library (oneMKL)
  • (optional) GDB debugger

Install oneAPI HPC toolkit with options:

  • Intel MPI library
  • Intel C++ compiler
  • Intel Fortran compiler

Intel oneAPI version support spans the last couple releases.

Usage

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.

Windows

Windows requires Visual Studio Community to be installed first–VS IDE integration is optional. For oneAPI ≥ 2025.3.1 and CMake ≥ 4.2, MSVC 2026 is supported. Remarkably, oneAPI Windows on ARM installations work as well! If VS IDE integration is installed, cmake -G can be used to generate Visual Studio project files with CMake 3.29 or newer. Otherwise, at least CMake 3.25.0 is adequate for oneAPI.

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 generator is desired, ensure:

  • CMake ≥ 3.29 is used for the -T fortran=ifx option
  • Intel oneAPI Visual Studio integrations are installed
  • use CMake configure options
  • CMake will automatically pick the “icx.exe” compiler for both C and C++ as “icl.exe” was removed
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.

Linux

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:

export CXXFLAGS=--gcc-toolchain=/opt/rh/gcc-toolset-12/root/usr/

which can be determined like:

scl enable gcc-toolset-12 "which g++"

If using a CMake toolchain file, instead of CXXFLAGS environment variable, one can set

set(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN "/opt/rh/gcc-toolset-12/root/usr/")

CMake add_custom_target() echo example

The COMMENT field of CMake’s add_custom_target() is intended to print messages during the build. However, this field is a no-op when using CMake Generators like Ninja and GNU Make. To reliably print messages during the build regardless of the Generator used, create a custom echo command using CMake’s built-in cmake -E echo functionality.

Example CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(demo LANGUAGES NONE)

set(_out ${PROJECT_BINARY_DIR}/output.txt)

add_custom_target(touchtgt ALL
    COMMAND ${CMAKE_COMMAND} -E touch ${_out}
    COMMAND ${CMAKE_COMMAND} -E echo "Touch ${_out}"
)

Demonstrate by

cmake -Bbuild
cmake --build build

Because of the ALL parameter, the touchtgt target will be built by default when you run cmake --build build, and it will print the message “Touch <path_to_output.txt>” during the build process.

To make the file be touched only if it doesn’t exist, use a combination of add_custom_command() and add_custom_target() instead:

cmake_minimum_required(VERSION 3.10)

project(demo LANGUAGES NONE)

set(_out ${PROJECT_BINARY_DIR}/output.txt)

add_custom_command(
    OUTPUT ${_out}
    COMMAND ${CMAKE_COMMAND} -E touch ${_out}
    COMMAND ${CMAKE_COMMAND} -E echo "Touch ${_out}"
)

add_custom_target(touchtgt ALL
    DEPENDS ${_out}
)

Programatically detect ARM64 Prism or Rosetta emulation

Major projects with CPU arch-specific code may distribute binaries for multiple CPU architectures for operating systems. Apple Silicon or Microsoft Prism are key examples of emulated binaries. Programs, especially computational programs like Anaconda Python should have the native matching CPU arch software installed. Example code to programatically check if a C++, GNU Octave, Matlab, or Python executable on:

  • Apple Silicon is using native or Rosetta
  • Windows on ARM64 is using native or Prism