Avoid overriding CMake default install prefix

CMake FetchContent is useful to incorporate subprojects at configure time. FetchContent subproject cache variables can override the top-level project cache, which can be confusing.

Projects may wish to use a default install prefix when “cmake –install-prefix” is not specified. Usually we use PROJECT_BINARY_DIR instead of CMAKE_BINARY_DIR, but in this case CMAKE_BINARY_DIR is a better choice to set the default install directory.

  # will not take effect without FORCE
  set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR} CACHE PATH "Install top-level directory" FORCE)

Another possibility is using CMakePresets.json to set the default install directory:

  "version": 3,

"configurePresets": [
  "name": "default",
  "binaryDir": "${sourceDir}/build",
  "installDir": "${sourceDir}/build"

Install Matlab Engine API in Python

Matlab Engine API allows calling Matlab functions from Python code.

These commands are executed from Terminal / PowerShell, not from Matlab. Go to the Matlab Engine directory:

cd $(matlab -batch "disp(matlabroot)")/extern/engines/python

Setup Matlab Engine, where “python” starts the desired Python executable.

  • MacOS or Linux:

    python setup.py build --build-base=$(mktemp -d) install --user
  • Windows / PowerShell:

    python setup.py build --build-base=$env:temp install --user

Root / admin permissions are NOT needed.

A simple example of using Matlab from Python:

import matlab.engine
eng = matlab.engine.start_matlab('-nojvm')
y = eng.asin(1.)


The Matlab Engine should take about 1 second for Matlab Engine to start when called from Python. For Matlab functions requiring JVM remove the “-nojvm” option.

Many Matlab numeric classes (single, double, logical) can be converted to Python types like:


Python floats pass into Matlab Engine by including a period . after the number.

  • asin(1) fails
  • asin(1.) works

Python can pass N-dimensional arrays to Matlab.

Matlab Engine provides asynchronous call with background=True



WSL mount external and network drives

Windows Subsystem for Linux can mount SD card, USB thumb flash drives, CD / DVD drives (CDFS), network drives, and UNC paths via “wsl –mount”. WSL can mount disk formats FAT, ExFAT or NTFS and VHD images.

For Windows 10 or those not desiring to use “wsl –mount” to mount external drives, the following can be used instead.

If Windows changes the external drive letter on a subsequent session, you need to repeat this process. These commands are typed into the Windows Subsystem for Linux Terminal.

Create a mount location in WSL and mount the drive (assume the drive shows in Windows as “F:"):

mkdir /mnt/f

mount -t drvfs f: /mnt/f

One can then create and manipulate files from both Windows and WSL on the same external drive.

For network storage, assume networked storage is already showing in Windows under \\server\share and we want to access this network storage from WSL as /mnt/share.

Create a mount location in WSL and mount the network share:

mkdir /mnt/share

mount -t drvfs '\\server\share' /mnt/share

Reference: external drive mount on WSL

CMake build type default

The default CMAKE_BUILD_TYPE is often desired to be set to Release. CMake ≥ 3.22 checks environment variable CMAKE_BUILD_TYPE, which can be a convenient user default

On Linux and MacOS add to ~/.bashrc, ~/.zshrc or similar:

export CMAKE_BUILD_TYPE=Release

On Windows, set this via the user environment variable GUI.

We also generally recommend setting the default CMake generator.

For projects used by a range of users who may or may not know to set a default build type, and where the developers want to ensure users are normally getting the full performance of a Release build, use GENERATOR_IS_MULTI_CONFIG:

  set(CMAKE_BUILD_TYPE Release CACHE STRING "Release can have faster run time than Debug")

MUMPS CMake FetchContent

It’s helpful to see how CMake FetchContent works by example, which we have provided for MUMPS. This example uses FetchContent to retrieve and build MUMPS via CMake scripts, which itself retrieves MUMPS source code from the authors' website via FetchContent.

Set OpenMPI MCA parameters

OpenMPI MCA parameters can be set in several ways. Some MCA parameters configure hardware, while other configure warnings. Depending on whether the parameters need to be per-user, per-hardware, etc. it may be useful to set some in a file, and others in the environment variables, and still others on the command line.

OpenMPI looks for a file at ~/.openmpi/mca-params.conf to set MCA parameters. The environment variables have a higher priority, and the command line has the highest priority as is intuitive.

The mca-params.conf syntax is like:

btl_openib_warn_no_device_params_found = 0

The environment variables would be set in ~/.bashrc or similar like:

export UCX_TLS=ud,sm,self

mdadm mount RAID

mdadm has become a popular Linux tool to manage RAID arrays. Red Hat Linux also uses mdadm and provides a usage guide.

After creating a RAID array, or to find an existing array that may or may not be mounted, use commands like:

mdadm --detail /dev/md0

You’ll see the individual RAID disk /dev/sd*, which can be further examined like:

mdadm --examine /dev/sda1 /dev/sdb1

Sometimes the operating system (such as CentOS Stream) may change the names of the RAID device, it might be under /dev/md/. To mount the RAID, use commands like:

mkdir /mnt/raid

mount /dev/md0 /mnt/raid

There might be extra devices under /dev/md that can’t be mounted, but one of them should be the desired RAID.

CMake ignore Anaconda libraries

Anaconda Python puts its directions first on PATH, so CMake tends to find libraries under Anaconda. The problem is these libraries are generally incompatible with the system or desired compiler. For certain libraries like HDF5, Anaconda is particularly problematic at interfering with CMake.

We fix this situation by putting in CMakeLists.txt, or in the custom Find*.cmake script code like:

# exclude Anaconda directories from search
    $ENV{CONDA_PREFIX}/Library/bin $ENV{CONDA_PREFIX}/Library/lib $ENV{CONDA_PREFIX}/Library/include
  list(APPEND CMAKE_IGNORE_PATH ${h5_ignore_path})

Assuming the rest of the CMake scripts may need to find Python with Conda, reverse the above ignore by:

# pop off ignored paths so rest of script can find Python
list(REMOVE_ITEM CMAKE_IGNORE_PATH ${h5_ignore_path})