Scientific Computing

CMake version recommendations and install

Downloading the latest release of CMake is usually easy. Admin / sudo is not required.

  • Linux: snap install cmake
  • macOS: brew install cmake
  • Windows: winget install Kitware.CMake
  • PyPI CMake package: python -m pip install cmake

For platforms where CMake binaries aren’t easily available, build CMake using scripts/build_cmake.cmake.

To see the merge requests for a certain release, use a URL like: https://gitlab.kitware.com/cmake/cmake/-/merge_requests?milestone_title=3.32.0&scope=all&state=all


CMake 4.2 enables Visual Studio 18 2026 generator. The FASTBuild generator is added, and has impressive benchmarks. FASTBuild supports more modern platforms including Windows, versus ccache or distcc.

ExternalProject added options to modify environment variables at each step by CONFIGURE_ENVIRONMENT_MODIFICATION, BUILD_ENVIRONMENT_MODIFICATION, INSTALL_ENVIRONMENT_MODIFICATION, TEST_ENVIRONMENT_MODIFICATION

Targets gain property SPDX_LICENSE


CMake 4.1 project() added COMPAT_VERSION that propagates to subdirectories and can be queried for the top-level COMPAT_VERSION.


CMake 4.0 enables CMAKE_LINK_WARNING_AS_ERROR boolean option sets most compilers to error if a compile warning occurs, which is generally a good setting for CI systems. target_link_libraries() can use a LINKER: prefix to abstract options. CMake SARIF output allows IDEs to better parse build status. CTest –interactive-debug-mode is particularly useful on Windows to enable debug dumps and error popup windows.


CMake 3.31 warns if cmake_minimum_required() is < 3.10. TLS ≥ 1.2 is required by default for internet operations e.g. file(DOWNLOAD), ExternalProject, FetchContent, and similar. file(ARCHIVE_CREATE) gained a long-needed WORKING_DIRECTORY parameter that is essentially necessary to avoid machine-specific paths being embedded in the archive. CMAKE_LINK_LIBRARIES_STRATEGY allows specifying a strategy for ordering target direct link dependencies.


CMake 3.30 adds C++26 support. CMAKE_TLS_VERIFY environment variable was added to set TLS verification (true, false). CMake 3.31 defaults CMAKE_TLS_VERIFY to on, where previously it was off.


CMake 3.29 adds cmake_language(EXIT code) to exit CMake script mode with a specific return code. This is useful when using CMake as a platform-agnostic scripting language instead of shell script.

Environment variable CMAKE_INSTALL_PREFIX is used to set the default install prefix across projects–it can be overridden as typical by cmake -DCMAKE_INSTALL_PREFIX= option.

Target property TEST_LAUNCHER allows specifying a test launcher. For MPI program this allows deduplicating or making more programmatic test runner scripts.

Linker information variables including CMAKE__COMPILER_LINKER_ID have been added to allow programmatic logic like setting target_link_options() based on the particular linker.

ctest --parallel without a number or 0 will use unbounded test run parallelism.


CMake 3.28 changes PATH behavior for Windows find_{library,path,file}() to no longer search PATH. This may break some projects that rely on PATH for finding libraries. The MSYS2-distributed CMake is patched to include PATH like earlier CMake, which can be confusing for CI etc. not using MSYS CMake with that patch. Windows CI/user may need to specify CMAKE_PREFIX_PATH like

cmake -DCMAKE_PREFIX_PATH=$Env:SYSTEMDRIVE/msys64/ucrt64/lib -B build

Support for C++20 modules is considerably improved and most users will want at least CMake 3.28 to make C++ modules usable. Generator expressions $<IF> $<AND> $<OR> now short circuit. Test properties now have a DIRECTORY parameter, useful for setting test parameters from the project’s top level CMakeLists.txt. CMake 3.28.4 fixed a long-standing bug in Ninja Fortran targets that use include statements.


CMake 3.27 emits warning for cmake_minimum_required(VERSION) < 3.5. CTest test properties TIMEOUT_SIGNAL_NAME and TIMEOUT_SIGNAL_GRACE_PERIOD specify a POSIX signal to send to a timed out test process. Interactive CMake debugger added by cmake --debugger is used with an IDE such as Visual Studio. CMake script command cmake_file_api() allows querying CMake File API from within CMake.

ℹ️ Note

Fortran + Ninja was broken for OBJECT libraries in CMake 3.27.0..3.27.8 and fixed in 3.27.9.


Older CMake changelog

Other Tech Blogs

The brief listing of other, somewhat similar blogs is not in any way an endorsement or indication of curation. It’s simply a notepad to remember what other blogs I might have once looked at that reminded me of content I’ve written or helped produce in the past. Since blog addresses might change, discontinue, or go off the deep end, I just put the plain non-linked text.

  • justine.lol - developed Cosmopolitan libc
  • eli.thegreenplace.net
  • noswampcoolers.blogspot.com
  • codeaholicguy.com
  • joelonsoftware.com

Matlab detect Java

Matlab or GNU Octave “.m” script functionality can be readily extended with Java code within the “.m” file. Matlab or GNU Octave do not necessarily include Java from the factory installation. Even if a compatible JDK is installed in Matlab or GNU Octave, Java can be disabled by -nojvm.

Detect if JVM is available from within a Matlab script by:

ok = usejava('jvm');

Obtain the Java version:

javaMethod('getProperty', 'java.lang.System', 'java.version')

GNU Octave Java

GNU Octave also has a JVM interface that extends Octave functionality.

The same commands as for Matlab generally work in Octave via builtin functions javaMethod() and javaObject().

If Java isn’t available in Octave, see if no location or an out of date location to Java is set in the environment variable JAVA_HOME:

getenv('JAVA_HOME')

Currently GNU Octave doesn’t have a way to disable Java from the command line like Matlab’s -nojvm option. One might try setting environment variable JAVA_HOME to an invalid location before starting Octave to simulate no JVM.

macOS

On macOS with Homebrew, Java for Octave can be installed and configured like:

brew install openjdk

Determine the location of the Java Virtual Machine library “libjvm.dylib”:

gfind -L $(brew --prefix openjdk) -name libjvm.dylib

Assuming the path is like “/opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home/lib/server/libjvm.dylib”, add to file “~/.octaverc”:

setenv('JAVA_HOME', '/opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home/lib/server/')

Overview of Free C++ and Fortran Compiler Families

These modern, currently-supported compiler families are free-to-use for C, C++ and Fortran.

Compiler C C++ Fortran
GNU gcc: C23 g++: C++26 gfortran: F2018
Intel oneAPI icx: C23 icpx: C++23 ifx: F2023
LLVM clang: C17 clang++: C++26 flang: F2018
AOCC clang: C17 clang++: C++20 flang: F2008
NVIDIA HPC SDK nvc: C11 nvc++: C++23 nvfortran: F2003
IBM OpenXL xlc: C17 xlc++: C++26 xlf: F2018

GCC

GCC has broad support of modern standards on a very wide range of computing platforms. GCC is competitive in build time and runtime with vendor-specialized compilers. These may offer vendor-specific capabilities not available in general compilers like GCC.

Intel

Intel oneAPI compilers are free to use for any user, supporting Linux and Windows computers with x86-64 CPU including from AMD, Intel, etc. Intel oneAPI components like MKL, IPP, and TBB are available at no cost. Intel MPI Library implements the MPICH specification for massively parallel computation across discrete computing nodes.

LLVM

LLVM Clang C and C++ compilers join with the Flang Fortran compiler using modern C++ internals and robust industry support. LLVM is known for performance, correctness, and prompt implementation of new language standards. LLVM has powerful associated tooling like clang-format, clang-tidy, and sanitizers. It is generally important to ensure that a project builds with both LLVM and GCC for better portability.

AMD

AMD AOCC LLVM compiler is tuned for AMD CPUs. AOCC works on non-AMD CPUs but is generally only useful for those with HPC/AI workloads on AMD CPUs, as it typically uses LLVM releases that are a few versions behind the latest.

AMD GPUs are the focus of the ROCm software stack, which includes the HIP C++ language and ROCm Fortran compiler. Currently the ROCm Fortran Next Gen compiler is in early development and is intended for advanced users who need to use AMD GPUs with Fortran or C/C++ code.

NVIDIA

NVIDIA HPC SDK is free to use and works on a variety of desktop CPUs including x86-64, OpenPOWER, and ARM. A key feature of the NVIDIA compilers is intrinsic support for CUDA Fortran, enabling offloading computationally intensive Fortran code to NVIDIA GPUs. NVIDIA HPC SDK includes specialized tools for NVIDIA Nsight profiling, debugging, and optimizing HPC applications on NVIDIA platforms.

IBM OpenXL

Unlike the other compilers mentioned above, IBM OpenXL LLVM-based compilers are specifically designed for POWER CPUs, such as ppc64le. Consequently, IBM OpenXL compilers do not work with typical x86-based computers.

The IBM OpenXL Fortran compiler features extensive optimization capabilities specifically for POWER CPU architecture. It supports OpenMP for parallel processing and can auto-vectorize code for POWER vector units (VSX, VMX). The compiler includes built-in support for IBM MASS (Mathematical Acceleration Subsystem) libraries and optimization reports to help developers tune code performance. OpenXL compilers include hardware-specific optimizations for POWER CPUs and support for IBM-specific operating systems like AIX.

DOSBox-X USB to Serial RS-232 Port Setup

DOSBox-X uses configuration file dosbox-x.conf for numerous parameters, including for serial port access via USB to serial adapters.

First, identify the device ID for USB to serial adapter:

  • Linux: ls /dev/ttyUSB* or ls /dev/ttyACM*
  • macOS: ls /dev/cu.* or ls /dev/tty.*

On Linux, allow non-sudo serial port access by adding the username to “plugdev” and “dialout” groups, then logout and login.

adduser $(whoami) plugdev dialout

Locate and edit dosbox-x.conf. Under [serial] modify the serial1=dummy according to the device found above. For example on Linux, if the device is at “/dev/ttyUSB0”:

serial1=directserial realport:ttyUSB0

DOSBox-X would present the serial device on COM1 as seen from within DOSBox-X.

Troubleshooting

On Linux, if trouble accessing a device, ensure the username is in “plugdev” group as noted above, and perhaps try (assuming device is /dev/ttyUSB0):

chmod 666 /dev/ttyUSB0

Matlab Startup Accelerator for Windows

Matlab Startup Accelerator for Windows is intended to speed up Matlab startup. However, by default Matlab disables the Startup Accelerator on many systems. To check if Matlab Startup Accelerator is enabled on a Windows system, check Windows Task Scheduler by the snapin:

taskschd.msc

Look under Task Scheduler Library for a task named Matlab R20XXx Startup Accelerator (where 20XXx is the Matlab release). Consider disabling it to avoid needless resource usage if it is not already disabled. On modern computers with SSD drives, Matlab startup is already fast.

Python os.statx for Linux

Python 3.15 added os.statx() function that provides access to the high performance statx() system call available on Linux kernels 4.11 and newer with glibc 2.28 and newer. The Ffilesystem library uses statx() by default if available on Linux. Having os.statx() available in Python allows for easier prototyping of features that might use statx(). See Ffilesystem statx() code for usage examples with graceful fallback to stat().

Minicom serial comms with file transfer

The Minicom serial communication program allows connecting to devices over the serial port and transferring files using XMODEM, YMODEM, or ZMODEM protocols–PuTTY can’t currently do file transfer over serial links.

Install Minicom like:

  • macOS: brew install minicom lrzsz (lrzsz is for file transfer)
  • Linux: apt install minicom lrzsz (or similar for relevant package manager)
  • Windows: use WSL (Windows Subsystem for Linux)

On macOS in particular for file transfers, first be sure that Minicom can find the sz, rz commands by looking under Esc-O for “File transfer protocols”. It may be necessary to point to lsz and lrz installed by Homebrew.

As noted in the documentation for Minicom, it is possible to save profiles. To just use a device directory, set command line options like:

minicom -D /dev/tty.usbserial-0001 -b 115200

List the USB-serial adapter ports:

  • Linux: ls /dev/ttyUSB*
  • macOS: ls /dev/tty.usbserial*

To send a file from Minicom once the device is ready, press Esc-Z and then S for send, select the appropriate protocol.

Python asyncio.run boilerplate

Concurrency is built into Python via asyncio. AsyncIO generators are implemented with yield much like synchronous generators. async for also simplifies expression of asynchronous for loops.

As in Julia, the expression of asynchronous structures in Python does not implement concurrent execution. Concurrent execution in Python is governed by collections of tasks or futures such as asyncio.gather and initiated by a runner such as asyncio.run.

Debugging asyncio code is facilitated by introspection built into Python.

asyncio.subprocess

AsyncIO subprocess may need specific asyncio loop configuration. The options needed are not the same for every project, depending on the asynchronous functions used.

Example date_coro.py uses AsyncIO subprocess.

asyncio.open_connection

For networking apps asyncio.open_connection allows massive amounts of connection, as shown in findssh.

Import Python user modules in Matlab

Matlab can call user Python modules via the Matlab external language interface. For concurrent Python modules using asyncio, you may need to create a shim function to allow Matlab to call the Python module. Anaconda Python works fine from Matlab.

Configure Matlab for Python: Matlab is designed to work with specific Python versions for each Matlab version. Matlab will not specifically tell you when you’re using an incompatible Python version, but you may get unstable operation or errors. pyenv Python environment manager configures the Python interface.

The Python executable is found from Terminal / Command Prompt:

python -c "import sys; print(sys.executable)"

For Windows, it may be like C:/Miniconda3/python.exe and for macOS / Linux it may be like ~/Miniconda3/python.

This Matlab command is persistent–Matlab remembers this Python choice even after restarting Matlab.

pyenv(Version='C:/Miniconda3/python.exe')

Verify Matlab → Python config by typing pyenv from within Matlab.

Troubleshooting

If a non-supported Python version is used, upon the pyenv() command Matlab may show a warning like:

Warning: Python version 3.xx is not supported. See this topic.

In that case, some Python operations may work, but others may not. An example test that may fail is:

py.tuple([1,1]);

PythonError ImportError: PyCapsule_Import could not import module "libmwbuffer"'

Numpy

If only Python standard library modules work, and even commonly used modules like Numpy will not work, errors may occur from Matlab like:

py.numpy.arange(1)
Unable to resolve the name py.numpy.arange

Try diagnosing the issue from Matlab like:

pyenv

help('py.numpy')

Verify the desired Python install is being used, and that there isn’t an error as below. If such an error occurs, check the PATH as seen by Matlab by:

getenv('PATH')

If the Python directories are missing, this may be why user modules are not importable in Python. These paths can be added to Matlab. On Windows, the necessary path is like ~/Miniconda3/Library/bin, the directory with lots of *.{so,dylib,dll} files and the fix is like:

setenv('PATH', fullfile(getenv("USERPROFILE"), "Miniconda3/Library/bin") + pathsep, getenv('PATH'))

The install path on non-Windows OS is like ~/miniconda3/lib.

This command can be issued after a Python command was attempted, it’s not necessary to restart Matlab. Note that this needs to be in PATH, since PYTHONPATH does not help in this case. This change does not persist across Matlab sessions. If it works for you, put it in the ~/Documents/MATLAB/startup.m file to have it reload each time Matlab is started.

This Numpy problem is fixed by the procedure above:

problem in numpy - ImportError:

IMPORTANT: PLEASE READ THIS FOR ADVICE ON HOW TO SOLVE THIS ISSUE!

Importing the numpy c-extensions failed.
- Try uninstalling and reinstalling numpy.
- If you have already done that, then:
  1. Check that you expected to use Python3.7 from "C:/Miniconda3/python.exe",
     and that you have no directories in your PATH or PYTHONPATH that can
     interfere with the Python and numpy version "1.17.4" you're trying to use.
  2. If (1) looks fine, you can open a new issue at
     https://github.com/numpy/numpy/issues.  Please include details on:
     - how you installed Python
     - how you installed numpy
     - your operating system
     - whether or not you have multiple versions of Python installed
     - if you built from source, your compiler versions and ideally a build log

- If you're working with a numpy git repository, try `git clean -xdf`
  (removes all files not under version control) and rebuild numpy.

Note: this error has many possible causes, so please don't comment on
an existing issue about this - open a new one instead.

Original error was: DLL load failed: The specified module could not be found.
  • Python module import is implicit in the Matlab → Python module function call. There is no need to import numpy etc. from Matlab
  • Python executable choice persists across Matlab sessions–Matlab “remembers” even after you restart Matlab or reboot the computer.
  • editing imported Python module code requires restarting Matlab to take effect.