Scientific Computing

C / C++ exit status macro

Exit status by convention has integer zero to represent “OK” no error status. Non-zero status is generally considered a failure. Coding languages such as Fortran also have built-in syntax to manage program exit code returned to the operating system.

C++ defines EXIT_SUCCESS and EXIT_FAILURE macros in header cstdlib. C defines EXIT_SUCCESS and EXIT_FAILURE macros in header stdlib.h.

Because typical headers already included often #include <cstdlib> or #include <stdlib.h>, developers may not realize these exit status macros need to be included somewhere. As compilers transition to providing stdlib via C++20 modules and generally cleanup excessive includes from built-in headers, code may suddenly complain about missing exit status macros at build time.

We feel it’s a good practice to use exit status macros as a findable and readable indication that program flow is ending and returning to system. A best practice is to include the appropriate header in any code file where the exit status macros are used.

#include <stdlib.h>

int main(void){
  return EXIT_SUCCESS;
}
#include <cstdlib>

int main(){
  return EXIT_SUCCESS;
}

Anaconda Python clean unused packages

The conda clean command allows cleaning up cached downloads and unused packages. Over time, Conda’s cache can grow over several gigabytes, even more than 10 GB of disk storage. To clean the unused files, use a command like:

conda clean --all --verbose

Zoom Windows 64-bit client

Many Windows users of Zoom may have downloaded the 32-bit Zoom client. We have observed that manually reinstalling the Zoom 64-bit Windows client can significantly help avoid choppiness of Zoom audio/video under high CPU usage. In most cases, it’s good to use the 64-bit version of a program for a 64-bit CPU and operating system. For Zoom as with many other programs, if the 32-bit version is installed, the updater doesn’t go to 64-bit version. The user typically has to manually once reinstall the 64-bit version of the program and from there on the updates stay at 64-bit program. Latency-sensitive 32-bit Windows programs may not work as well as 64-bit programs on 64-bit Windows due to WOW64 emulation for 32-bit programs on 64-bit Windows.

CMake presets build options

CMake presets can have specific build preset option for particular build tools. This CMakePresets.json shows example build presets for Ninja. The preset name “ninja” in this example is arbitrary. As usual, the presets help avoid copying script parameters and the possibility of typos in duplicated script code, whether for CI or developers themselves.

For example, to have ninja “explain” why a target is dirty:

cmake --build --preset explain
{
  "version": 2,
  "configurePresets": [
  {
    "name": "ninja",
    "generator": "Ninja",
    "binaryDir": "${sourceDir}/build"
  }
  ],
  "buildPresets":[
    {
      "name": "explain",
      "configurePreset": "ninja",
      "nativeToolOptions": ["-d", "explain"]
    },
    {
      "name": "keep",
      "configurePreset": "ninja",
      "nativeToolOptions": ["-d", "keeprsp", "-d", "keepdepfile"]
    },
    {
      "name": "stats",
      "configurePreset": "ninja",
      "nativeToolOptions": ["-d", "stats"]
    }
  ]
}

CMake and Meson compiler option family

On Windows, compiler option syntax is generally MSVC-like or GCC-like. On Windows, the compiler option families are:

  • MSVC-like: Intel oneAPI (IntelLLVM), Clang-CL, Visual Studio
  • GCC-like: GCC, Clang, non-Windows OS.

Meson and CMake can each detect compiler option family. In general, the “else” branch would have further nested “if” to handle compiler options with distinct syntax.

CMake uses the MSVC variable to detect compiler option family. More specific compiler option selection is often handled with an if-else tree for each compiler ID and / or check_compiler_flag().

project(Hello LANGUAGES C)

if(MSVC)
  message(STATUS "${CMAKE_C_COMPILER_ID} is MSVC-like")
else()
  message(STATUS "${CMAKE_C_COMPILER_ID} is GCC-like")
endif()

Meson uses the .get_argument_syntax() property to detect compiler option family. Getting more specific compiler options can be done with an if-else tree for each compiler ID and / or the .has_argument() method.

project('hello', 'c')

cc = meson.get_compiler('c')

if cc.get_argument_syntax() == 'msvc'
  message(cc.get_id() + ' is MSVC-like')
else
  message(cc.get_id() + ' is GCC-like')
endif

Detect Bash, zsh or other shell

A 5-way shell detect script can detect bash, csh, dash, ksh, or zsh. However, often we simply want to detect if the shell is Bash or something else. For example, in a Bash-dependent script we may thereby stop and recommend the user use Bash to avoid needing to test across numerous shells. There are a number of pitfalls in detecting a shell type so this method is not completely robust either, but has worked. The key to this technique is that while different shells have distinct “if-else” syntax, most shells have “case-esac”.

CMake script relocate

When relocating / moving / renaming a CMake script within a project, it may be desired to leave a placeholder at the original script location until users know to use the new script path in the project. Many CMake scripts call other scripts in the project. In general, CMake scripts should use absolute paths, except for install() parameters. That is, CMake scripts should generally start file paths with CMake built-in absolute paths like CMAKE_CURRENT_LIST_DIR and CMAKE_CURRENT_FUNCTION_LIST_DIR. If the script directory is changed, the script references to paths within the project will of course also need to be changed.

Legacy users may take a while to start calling the CMake script at the new location. Note that making a softlink will NOT work in general because the path references would be from the placeholder script location, which in general is distinct from the new script location. To bridge this UX gap, create a trivial one-line script at the original script path like:

include(${CMAKE_CURRENT_LIST_DIR}/../path/to/new-script.cmake)

ATLAS build questions

ATLAS gives a higher performance subset of LAPACK. ATLAS has problems building on modern computers. Debian and Ubuntu have numerous patches needed to build ATLAS. Thus we don’t currently have an easy CMake script to build ATLAS as we do for other popular libraries like LAPACK, Scalapack, METIS and Scotch.

An attempt to build ATLAS via CMake that fails due to ATLAS Autotools issues:

project(atlas LANGUAGES C)

include(ExternalProject)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

set_property(DIRECTORY PROPERTY EP_UPDATE_DISCONNECTED true)
# don't recheck for updates to the Git repo at subsequent CMake reconfigure

set(atlas_url https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/atlas/3.10.3-10ubuntu3/atlas_3.10.3-10ubuntu3.debian.tar.xz)

find_package(Autotools REQUIRED)

ExternalProject_Add(atlas
URL ${atlas_url}
CONFIGURE_HANDLED_BY_BUILD true
CONFIGURE_COMMAND <SOURCE_DIR>/configure
BUILD_COMMAND ${MAKE_EXECUTABLE} -j
INSTALL_COMMAND ${MAKE_EXECUTABLE} install
)

Aspell for Windows

The native Windows Aspell port is no longer supported. Instead, use Aspell in Windows via Windows Subsystem for Linux. Install Aspell in Windows Subsystem for Linux:

wsl apt install aspell

Then check spelling of a file like:

wsl aspell -c myfile.txt

Note: don’t include the prefix .\ in the file name, as that will not work in WSL.


Alernatively, MSYS2 can provide Aspell in Windows by installing packages

mingw-w64-ucrt-x86_64-aspell
mingw-w64-ucrt-x86_64-aspell-en

Related: Aspell don’t backup Related: Aspell user dictionary location