Scientific Computing

Static linked executable

Static linking of the executable compiler / libc / system libraries can help mitigate missing library issues. Dynamically / shared linked executables on Windows require the DLL path to be in the environment variable PATH or the executable directory. On Linux / BSD, the shared library path must be in the environment variable LD_LIBRARY_PATH. On macOS, the shared library path must be in the environment variable LIBRARY_PATH. If the developer switches compiler environments, or the end user is missing compiler libraries, the executable may fail to run due unresolved dynamic library path.

Relatively few Windows users have compilers installed. Missing DLLs and DLL Hell are part of distributing Windows programs, where batch scripts can be used to set environment variables and Path for the program. A typical error code for missing DLL is -1073741515 → 0xc0000135 STATUS_DLL_NOT_FOUND.

Simply specifying static compiler linking flags does not guarantee portable executables, which are a more general problem. Even using a slim libc like musl doesn’t generally work for graphical programs using X11 / Wayland. The Cosmopolitan project creates a single binary executable from C/C++ code that works across operating systems.

Compiler flags

GCC / Gfortran can statically link compiler libraries including libgfortran into the final executable using flags -static and -static-libgfortran This increases the size of the executable, which may be negligible compared to the nuisances avoided.

gfortran -static -static-libgfortran myprog.f90 mylib.f90 -o myprog.exe

Other compilers have similar static compiler library link options:

For special cases where the system libc and libc++ aren’t used, the compilers typically have additional flags like -static-libgcc and -static-libstdc++.

Caveats

Some libraries may only be available as dynamic, and the options above typically will use the dynamic version if static isn’t available. macOS static linked executable may only work on your specific computer; macOS prefers dynamic linking. In general, we use the default build system linking (dynamic or static) unless there is a reason to specify static linking.

Convert GitHub Gist to GitHub Repository

GitHub Gists give good visibility in search engines and GitHub Search. Gists integrate well using site generators including Hugo. However, GitHub Gists do not support GitHub Actions, Discussions, etc. Gists also do not allow directory structure. Once a Gist reaches a certain feature level or number of files, it may be more useful to share the content as a GitHub Repository.

Simply import the Gist URL to a new Repository. Once satisfied with the imported Repository, the Gist can be deleted, or leave a simple note with Repository URL.

An advantage of importing rather than just copying the files over is the Gist history is preserved as Git commits. If Git was used to manage the Gist, commit messages are preserved. Edits made to the Gist in the web editor don’t have commit messages.

CMake / Meson run check DLL Hell

CMake check_source_runs and Meson compiler.run check if source code compiles, links, and runs correctly. If the checked program uses shared libraries (DLLs) such as libstdc++ on Windows, the program may fail to run due to conflicting DLLs in the Path environment variable. In CMakeConfigureLog.yaml or meson-logs/meson-log.txt, the error code may be 0xc0000139 STATUS_ENTRYPOINT_NOT_FOUND or 3221225785 corresponding to a conflicting DLL. Error code 0xc0000135 STATUS_DLL_NOT_FOUND corresponds to a missing DLL.

The general solution is to avoid unnecessary paths in the Path environment variable. Ensure the compiler and runtime library path are in the Path environment variable before conflicting DLL paths. Check if libstdc++ has multiple entries in the Path, particularly before the compiler and runtime libraries DLL directory. From Terminal:

where.exe libstdc++*.dll

If this prints

INFO: Could not find files for the given pattern(s).

then the libstdc++ DLL is not in the Path, which may result in error code 0xc0000135. If the libstdc++ DLL is in the Path, check if it is in multiple locations. The ideal is to have one path result. At least the desired compiler/library path must be the first result.

For example, Meld is a program that causes DLL conflicts if put on the Path.

Examples of using small PowerShell scripts for GCC and Clang.

Java catch Ctrl+D EOF

REPL and other command line programs can catch Ctrl+D EOF in Java in a platform-independent way. Assuming java.util.Scanner is used to read input from the command line, the code for Ctrl+D EOF detection works by catching EOF by scanner.hasNextLine() method, and also catches Ctrl+D EOF by checking for Unicode character \u0004 in stdin pipe.

import java.util.Scanner;

public class MyClass {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        String argument = "";
        final String prompt = "MyREPL> ";

        System.out.print(prompt);

        while (scanner.hasNextLine()) {
            String input = scanner.nextLine();

            String[] inputArray = input.split(" ");
            String command = inputArray[0];

            if (inputArray.length > 1) {
                argument = inputArray[1];
            } else {
                argument = "";
            }

            if (command.equals("exit") || command.equals("\u0004")) {
                break;
            }

           // main program logic here
            }
    }
}

Windows set WiFi preference order

Windows can control WiFi from the Command Prompt, including WiFi AP preference order. Via the Windows WiFi settings GUI page, the latest added WiFi pushes to the top of the preference stack. This is typically not desired, as when setting up a device in general, one usually connects to the most needed WiFi AP first, and over time adds temporary or less desired WiFi, which Windows keeps at the top of the WiFi preference list. This netsh command prompt procedure allows correcting the Windows WiFi preference order.

Show known WiFi AP

This command lists the known (previously connected) WiFi AP, just like shown in the Windows WiFi settings GUI:

netsh wlan show profiles

The WiFi AP are listed in preference order, from most preferred at the top to least preferred at the bottom. A key piece of information needed from this command is:

Profiles on interface “Wi-Fi”

The name might be “Wi-Fi 2” or other if multiple WiFi adapters are in the PC.

Set WiFi preference order

Using the information from:

netsh wlan show profiles

Put the WiFi APs in the desired priority order like:

netsh wlan set profileorder my_work_wifi Wi-Fi 1

netsh wlan set profileorder my_home_wifi Wi-Fi 2

where the trailing integer is the position in the Windows WiFi preference.

Notes

  • show graphical report of WiFi AP signal

    sudo netsh wlan show wlanreport
  • Python example parsing netsh wlan signal under netsh.py

Matlab arrays to / from Python

Passing N-dimensional arrays to / from Python from Matlab is straightforward with Matlab. Matlab can work with Python classes including list(), dict(), set(), Numpy.ndarray and Xarray.DataArray.

Matlab using Numpy example:

filtered clown image

Filter an image in Python and display in Matlab

Matlab using Xarray: see example glow.m.

function M = xarray2mat(V)
M = double(py.numpy.asfortranarray(V));
end

function I = xarrayind2vector(V,key)
% convert xarray index to Matlab 1-D vector

I = cell2mat(cell(V.indexes{key}.values.tolist));

end

Related:

Build GPSTest app with Android Studio

The GPSTest app is currently (December 2024) not available to most devices on the Google Play store due to the app temporarily being configured for a too-old minimum Android version. This is a security measure enforced by Google Play store to all apps to preserve security of devices. App stores of other operating systems enforce similar restrictions for security.

A workaround until the GPSTest app authors update the app configuration is to build and install the app using Android Studio. Android Studio is free to use and works on Windows, macOS, or Linux equally well. Default settings were used, including setting up an optional emulator. Any reasonably current Android Studio version should be suitable.

This method doesn’t make any changes to the app, but bypasses the Google Play store restrictions by building and installing GPSTest directly from the laptop onto an Android phone. An inconvenience is lack of easy app distribution as every phone needs to one-time plug into a laptop with USB-C to install the GPSTest app. If the phone isn’t detected, try another USB cable as some cables are power-only and don’t have data lines. A message will popup on the phone asking to authorize the laptop to connect in USB Debugging mode. The app can be used indefinitely after the one-time plugin and install.

Download and Build GPSTest

Use Git as in any other project from the Terminal:

git clone https://github.com/barbeau/gpstest

From Android Studio, open that “gpstest” directory from “File > Open” menu.

Try to build the app with the “Build > Make Project” menu – or click the hammer icon in the upper right toolbar of Android Studio. Failures like

Unknown Kotlin JVM target: 21

may result upon building. This stems from the default JVM version in Android Studio. For repeatability, it is typical across code languages and platforms to have a project manifest specifying exact library versions. Android apps manifests are typically “build.gradle” file(s). We don’t edit the manifest at this time, because maybe we’ll break something unexpectedly in the app. Instead, set Android Studio to use JVM 17 as specified by manifest file “GPSTest/build.gradle”:

compileOptions {
   sourceCompatibility JavaVersion.VERSION_17
   targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
   jvmTarget = JavaVersion.VERSION_17
}

This is accomplished under Android Studio’s Settings icon (geared wheel) in the upper right corner of the Android Studio main window. Select “Build, Execution, Development > Build Tools > Gradle” in the left hand Settings panel. Under “Gradle Projects” in the right panel, “Gradle JDK” may be set to 21 or so. Select in that menu to “Download JDK and selection “Amazon Coretto 17” or JetBrains 17 or similar. This will take a couple minutes to download and install, then click OK.

Again try to build the app with the “Build > Make Project” menu – or click the hammer icon. There will be a number of warnings, but the app should build successfully. If the optional emulator is present, clicking “Run > Run GPSTest” or clicking the green right arrow in the top Android Studio menu bar will run the app in the emulator.

Connecting Phone

The phone needs to have Developer Mode enabled to upload apps from Android Studio. Under Developer Mode settings, USB Debugging needs to be enabled, at least for the brief time the phone is connected to the laptop to upload the app. If this is a personal phone, consider disabling USB Debugging at all other times to help the security of the phone from physical hacking (someone steals/takes the phone and wants to break into it). In Android Studio Device Manager, clicking “+” will add the phone, or it may appear automatically. Clicking the Android Studio “Run” green arrow will install the app automatically if the physical phone is selected in Android Studio Device Manager. After the app is installed, unplug USB at any time and turn off USB Debugging under the phone’s Developer Mode settings if desired.

GPSTest Caveats

Android 14 and newer will not have the “Share” icon at the top of GPSTest app due to enhanced security in Android 14. The GPSTest maintainers will need to update the GPSTest app to work fully with newer Android versions.

CTest stdin pipe

CTest can be used to run test executables that require input from stdin. This is accomplished by having add_test call a CMake script that uses execute_process to run the test executable with the input piped in from a file. Null stdin is also possible.

Suppose CMakeLists.txt contains:

enable_testing()

add_executable(main main.c)

add_test(NAME stdin_null
  COMMAND ${CMAKE_COMMAND} -Dexe:FILEPATH=$<TARGET_FILE:main> -P ${CMAKE_CURRENT_SOURCE_DIR}/stdin_null.cmake
)

add_test(NAME stdin_pipe
  COMMAND ${CMAKE_COMMAND} -Dexe:FILEPATH=$<TARGET_FILE:main> -P ${CMAKE_CURRENT_SOURCE_DIR}/stdin_pipe.cmake
)

In the non-CMakeLists.txt *.cmake script files, we set a reasonable cmake_minimum_required(VERSION) to avoid issues with defaulting to pre-CMake 3.0 behavior for strings, especially for regular expressions.

The null input to stdin may be required for some executables that may hang forever waiting for stdin.

cmake_minimum_required(VERSION 3.19)

if(UNIX)
  set(devnull INPUT_FILE /dev/null)
elseif(WIN32)
  set(devnull INPUT_FILE NUL)
endif()

execute_process(COMMAND ${exe}
${devnull}
COMMAND_ERROR_IS_FATAL ANY
)

A file (typically a text file) may be piped to stdin to replace interactive input.

cmake_minimum_required(VERSION 3.19)

execute_process(COMMAND ${exe}
INPUT_FILE ${CMAKE_CURRENT_LIST_DIR}/cli_exercise.txt
COMMAND_ERROR_IS_FATAL ANY
OUTPUT_VARIABLE out
ERROR_VARIABLE err
)

if(out MATCHES "TRACE")
  message(FATAL_ERROR "TRACE found in stdout")
endif()

if(err MATCHES "TRACE")
  message(FATAL_ERROR "TRACE found in stderr")
endif()

if(NOT err STREQUAL "")
  message(FATAL_ERROR "stderr output is not empty:
  ${err}")
endif()

message(STATUS "stdout:
${out}")

In this example, the developer wishes to ensure the program ran with no unexpected stdout text and no stderr text at all. This can be helpful to catch debugging output that should not be in the final program output.