Scientific Computing

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 Intel.OneAPI.BaseToolkit
winget install 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.

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

add_custom_target(
    COMMAND ${CMAKE_COMMAND} -E touch ${_out}
    COMMAND ${CMAKE_COMMAND} -E echo "Touch ${_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

CMake GoogleTest override flags

GoogleTest internally set CMake compiler flags are too aggressive for end users, and can cause build errors. We experienced this with Intel oneAPI, and created a workaround for the GoogleTest-consuming CMake project to override the offending flags. This technique is useful in general with third-party CMake projects, including those obtained by FetchContent.

For GoogleTest, we determined that Intel oneAPI was experiencing nuisance internal errors:

  • Windows “-WX” flag
  • Linux “-Werror” flag

We overrode those flags with this CMake script:

FetchContent_MakeAvailable(googletest)

if(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
  foreach(t IN ITEMS gtest gtest_main gmock gmock_main)
    if(WIN32)
      # necessary since GoogleTest injects /WX blindly and that fails builds with modern IntelLLVM.
      # https://learn.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level
      target_compile_options(${t} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/WX->)
    else()
      # necessary to avoid
      # error: unknown warning option '-Wno-implicit-float-size-conversion' [-Werror,-Wunknown-warning-option]
      target_compile_options(${t} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-error=unknown-warning-option>)
    endif()
  endforeach()
endif()

The override “/WX-” nullifies the /WX flag that errors for nuisance warnings internal to GoogleTest. The “-Wno-” flag is the same as the underlying GCC compiler on Linux.

Wi-Fi 6GHz hardware

The 6 GHz Wi-Fi band is widely available in new hardware (routers and clients). However, for economic reasons, many devices still omit the 6 GHz Wi-Fi band. 6 GHz Wi-Fi helps provide more data bandwidth on less congested RF spectrum, which is important for latency-sensitive applications like gaming and video conferencing. While the ultimate connection quality can be achieved by wired Ethernet, practical considerations often lead to Wi-Fi being used even within the same room as the network router.

Wi-Fi 7 (802.11be) MLO (Multi-Link Operation) avoids connection hiccups between Wi-Fi bands because multiple available bands are used simultaneously for clients so capable. A multi-radio router that has simultaneous MLO is a key feature to look for.

Typical contemporary mobile phones already have Wi-Fi 7 support. Laptop support can be checked from the manufacturer.

For example:

Snapdragon X Elite laptop CPU

Laptops with the Snapdragon X Elite CPU widely emerged in 2024. Certain benchmarks show performance comparable with the Apple M3 CPU. The Snapdragon X2 Elite CPU is available in laptops emerging in 2026, and surpasses the Apple M5 in some benchmarks. Windows 11 24H2 added Prism x86-64 emulation like Rosetta on macOS but tuned for Snapdragon X CPUs, offering significant performance improvements for x86-64 applications on ARM-based laptops.

CMake target dependency graph

CMake --graphviz can generate GraphViz target dependency graphsfor CMake-supported project code languages including C, C++, and Fortran. Fortran executables and modules are shown in the directed dependency graph.

The “dot” GraphViz program converts the .dot files to PNG, SVG, etc. dot program is available by:

  • Homebrew: brew install graphviz
  • Winget: winget install -e --id Graphviz.Graphviz

Generating the dependency graph requires CMake configure and generate. Thus, the compiler and generator needed by the CMake project must be working. The project does not need to be compiled before generating the dependency graph. However, the user should select the same CMake configure options as they would for compiling the project.

Example: MUMPS dependency graph is below. SVG vector graphics can be zoomed arbitrarily large in a web browser. The “graphviz/” directory is to avoid making files in the source directory.

cmake -B build

cmake --build build -t graphviz

using script in CMakeLists.txt like:

find_program(GRAPHVIZ_DOT NAMES dot)
if(GRAPHVIZ_DOT)
    file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/graphviz)
    set(_graph_name ${PROJECT_BINARY_DIR}/graphviz/${PROJECT_NAME})
    add_custom_target(graphviz
      COMMAND ${CMAKE_COMMAND} --graphviz=${_graph_name}.dot -B${PROJECT_BINARY_DIR} -S${PROJECT_SOURCE_DIR}
      COMMAND ${GRAPHVIZ_DOT} -Tsvg ${_graph_name}.dot -o ${_graph_name}.svg
      COMMAND ${CMAKE_COMMAND} -E echo "CMake ${PROJECT_NAME} targets graph: ${_graph_name}.svg"
    )
endif()

Another example is the h5fortran project graph:

h5fortran dependency graph

The “dependers” files show only the nodes depending on a node.

Scripts and Viewing output

CMakeUtils graph.py converts a directory of CMake dot diagrams to SVG or PNG and collects them in an HTML document for easy viewing:

python cmakeutils/graph.py ~/myprog/graphviz/

To open a web browser from the Terminal:

python -m webbrowser -t file:///$HOME/myprog/graphviz/index.html

Note that “file:///” has three slashes and the file path must be absolute.


Related: Dependency graphs are also easily created in Python and Matlab.

Get list of CMake target names

CMake build targets are declared by “add_[executable,library,custom_target]” commands. Targets can be dynamically set by arbitrarily complex foreach(), if(), etc. logic. A list of CMake targets in the directory scope is retrieved by the BUILDSYSTEM_TARGETS directory property.

The variable “target_names” contains all the target names previously added in the CMakeLists.txt in the DIRECTORY scope. Retrieving the list of targets in a whole project, or in a FetchContent dependency is possible with this CMake function:

function(print_targets dir)
    get_property(subdirs DIRECTORY "${dir}" PROPERTY SUBDIRECTORIES)
    foreach(sub IN LISTS subdirs)
        print_targets("${sub}")
    endforeach()

    get_directory_property(targets DIRECTORY "${dir}" BUILDSYSTEM_TARGETS)
    if(targets)
        message("Targets in ${dir}:")
        foreach(t IN LISTS targets)
            message("  • ${t}")
        endforeach()
    endif()
endfunction()

Use this function like:

print_targets("${CMAKE_CURRENT_SOURCE_DIR}")

Or supposing FetchContent, here using “googletest”:

FetchContent_MakeAvailable(googletest)

FetchContent_GetProperties(googletest)
print_targets(${googletest_SOURCE_DIR})

results in:

Targets in _deps/googletest-src/googletest:
  • gtest
  • gtest_main
Targets in _deps/googletest-src/googlemock:
  • gmock
  • gmock_main

Note: get_property(test_names GLOBAL PROPERTY BUILDSYSTEM_TARGETS) will return an empty list–DIRECTORY scope must be used.

Compact WSL Disk Image unused space

Windows Subsystem for Linux (WSL) uses VHDX files to store each distribution’s filesystem. Over time these disk images grow in size as files are added and deleted. However, the space used by deleted files is not automatically reclaimed, leading to larger disk images than necessary.

There is a PowerShell script to automatically compact WSL VHDX files that works with any of the Windows release levels (including Home).