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
if(DEFINED ENV{CONDA_PREFIX})
  set(h5_ignore_path
    $ENV{CONDA_PREFIX}/bin $ENV{CONDA_PREFIX}/lib $ENV{CONDA_PREFIX}/include
    $ENV{CONDA_PREFIX}/Library/bin $ENV{CONDA_PREFIX}/Library/lib $ENV{CONDA_PREFIX}/Library/include
  )
  list(APPEND CMAKE_IGNORE_PATH ${h5_ignore_path})
endif()

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})

Wireless trackballs

Trackballs declutter busy desks and can be more comfortable than mice for precision pointing. Logitech trackballs also support Linux, paired and configured via Solaar. Every few months, you can pop out the trackball and clean the rollers or just blow on them to get the dust out.

The Logitech M575 was released in 2021 and is similar to the M570 with the added benefit of working via Bluetooth Low Energy or the Unifying receiver.

The Logitech M570 was released in 2010. The M570 is a user-maintainable trackball with back/forward buttons and clickable roller for programming and web-browsing convenience. I have multiple Logitech M570’s, and they have proved durable on the road and during heavy usage. I spilled soda into my M570, and successfully cleaned the M570.

The $100 Logitech MX Ergo was released in 2017. The Ergo uses Bluetooth Low Energy or Unifying receiver.

Anaconda Python + Spyder on WSL

Python can be used within Windows Subsystem for Linux. Using Python on WSL can be advantageous because of easier compiler access. We generally use Miniconda Python on WSL.

conda install matplotlib spyder

If Spyder won’t start, look in the error message for missing libraries such as libxcomposite libxss1 X11 prereqs are specified in the error message on starting GUI programs like Spyder. Look above the error:

ModuleNotFoundError: No module named 'PyQt5.QtWebKitWidgets'

to see if libxcomposite or libxss etc. need to be installed via apt install.


Notes on setting up Matplotlib for WSL

CMake download and extract compressed files

Using CMake to download, verify the checksum of files and extract compressed files is easy and seamless. FetchContent downloads the file at configure time.

include(FetchContent)

set(CMAKE_TLS_VERIFY true)

function(download_file url hash)

FetchContent_Declare(download_${hash}
URL ${url}
URL_HASH SHA256=${hash}
DOWNLOAD_NO_EXTRACT true
)

FetchContent_MakeAvailable(download_${hash})

endfunction(download_file)

# === example
download_file(
  https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg
  12794390cce7d0682ffc783c785e4282305684431b30b29ed75c224da24035b4
)

This downloads the file and:

  • checks hash signature
  • verifies the SSL certificate

CMake uses vendored cURL internally.

Extract compressed file

CMake also can extract compressed files like .zip, .tar.bz2, etc. This command can also specify output directory, extract a subset of files matching a pattern and more.

file(ARCHIVE_EXTRACT INPUT in_file.zip)

Notes

Install latest CMake without sudo using cmake_setup.py.

Meson download file

CMake apply patch file

Patching files with the patch program has been a common task for decades. Due to technical issues with potential patch library implementation, CMake does not include a native patch function. We use CMake to detect if “patch” is available, which it virtually always is on Unix-like systems. For Windows, we use WSL.

The example below is for patching a single file, but could be extended to a directory structure. In this example “my.c” is the source file to be patched, and “my.patch” is the “diff -u” generated patch file.

SSH headless Raspberry Pi setup

This guide assumes there is no Internet, no Wifi, no router, no display, no keyboard. It assumes you have a Raspberry Pi and laptop with:

  • Ethernet port (built-in or USB-Ethernet adapter)
  • plain (or crossover) Ethernet cable–no router/switch is required

Some laptops can also work via USB-C connection and the RNDIS Ethernet driver instead of the Ethernet jack. However, some laptops, particularly on Windows may not work for RNDIS. The symptom of this is that the Pi shows up as a serial port instead of an Ethernet connection. Hence, best to use the Ethernet jack for better reliability.

Before going into the field away from internet, download:

Prepare SD card via the Raspberry Pi imaging tool to write the desired SD card image. If the laptop is not on the internet, use the imager tool to write the .img you downloaded previously. After writing the SD card image, in the SD card “boot” partition enable SSH on the headless Pi for first boot by creating an empty file named “ssh”. First navigate in the laptop terminal to this “boot” directory. On Linux or MacOS, this is done by:

touch ssh

On Windows PowerShell, this is done by:

New-Item ssh

N.B.: this is NOT the “boot” directory in the 4 GB main partition of the SD card, this is a separate < 100 MB partition named “boot”. It has other important files like config.txt in it.

Optionally, WiFi is enabled by editing from your laptop on the SD card the file /etc/wpa_supplicant/wpa_supplicant.conf and adding lines like

network={
   ssid="my cool wifi router"
   psk="my wifi password"
}

Optionally, prioritize Wifi networks by the priority field, which can be a positive or negative integer.

  • default priority is 0.
  • equal priority Wifi is based on signal strength, security, etc.

“eject” or unmount the SD card before removal, to avoid corrupting the SD card file system.

Boot the headless Pi by inserting the SD card into the Pi and powering up the Pi. We use link-local networking, where the IP address will be in the 169.254.*.* range, no DHCP server needed. You may need to manually select this network when you plug the Pi into your laptop. After about one minute, on your laptop plugged directly to the Pi via Ethernet:

ssh pi@raspberrypi.local

default password is raspberry

Logged into the Pi, change the default password to something else with

passwd

Set unique hostname via “raspi-config”. For example, if chose mypi then after Pi reboot:

ssh pi@mypi.local

Set locale to be UTF-8. Assuming you wish to have the United States locale, uncheck the default GB and check en_US.UTF-8 UTF-8. When prompted for default locale, also selected en_US.UTF-8 UTF-8. If you don’t pick a UTF8 locale, Python may give UnicodeDecodeError with UTF8, even when .py script already has # -*- coding: utf-8 -*-.

Again assuming you’re using a United States keyboard, set keyboard layout in raspi-config to Generic 104 keyboard, United States layout to avoid not being able to type symbols properly. Reboot to make the locale settings take effect.

Just a simple network switch connecting Raspberry Pis, PCs and other devices makes an internet-free, pure link-local “off the grid” network. Of course, you can also put the Pis on a wired or wireless network connected to the Internet if desired. The .local address functionality will NOT work over the Internet, but only on the LAN segment your device is on.

Without further configuration, SSH servers listen on all interfaces. Normally this is fine. If you want only specific interface(s) to have the SSH server listen, you will need to research ListenAddress of /etc/ssh/sshd_config and/or IPTables.

CMake find on MacOS

Anaconda Python puts itself first on PATH when activated. This can become a problem for libraries like HDF5, where “conda install h5py” puts compiler wrapper “h5cc” on PATH first. Tell CMake to prefer Homebrew for a library like HDF5 by doing:

export HDF5_ROOT=$HOMEBREW_PREFIX

Macports doesn’t have a similar environment variable. We instead hint to CMake by inside the CMakeLists.txt:

# --- detect Macports and hint its location
# this helps avoid issues with Anaconda overriding HDF5 with its broken compiler wrapper
if(APPLE)
  if(NOT DEFINED ENV{HOMEBREW_PREFIX} AND NOT DEFINED ENV{MACPORTS_PREFIX})
    find_program(MACPORTS NAMES port)
    if(MACPORTS)
      cmake_path(GET MACPORTS PARENT_PATH MACPORTS_PREFIX)
    endif()
  endif()
endif()