Skip to content

A multi-platform command-line utility that provides seamless access to GNU toolkits on non-GNU operating systems.

License

Notifications You must be signed in to change notification settings

gapotchenko/gnu-tk

Repository files navigation

GNU-TK

GNU-TK is a tiny project that provides seamless scriptable access to GNU tools on non-Unix operating systems.

Overview

GNU is a software system that has been developed by many people working together for the sake of freedom of all software users to control their computing.

The GNU system offers a wide range of tools, including essential command-line utilities such as bash, cp, sed, and many others. For instance, GNU core utilities are crucial for automating cross-platform projects by enabling the creation of reproducible scripts. Beyond that, GNU tools support a wide variety of other use cases.

A recurring issue with GNU tools, however, is their limited accessibility on non-Unix operating systems. For example, on Windows, you can use toolkits such as MSYS2, Cygwin or WSL. Yet, they introduce their own challenges: correctly identifying the toolkit installation path, modifying environment variables, configuring shells with toolkit-specific parameters, and, finally, managing the handoff of control to and from the toolkit. All of this makes using GNU tools far from easy and reproducible.

GNU-TK project addresses these problems by providing a small gnu-tk command-line utility that acts as an automatic gateway to a GNU toolkit installed on the system. gnu-tk has a concise and stable command-line interface making it suitable for effortless cross-platform scripting. In addition, it smoothes out the inconsistencies and shortcomings that typically come with individual GNU toolkit distributions.

Usage

The basic usage example:

gnu-tk -l cp --help

The command above invokes cp GNU utility with --help command-line option.

You can also pass a command to execute as a single command-line argument:

gnu-tk -c "cp --help"

Or as a script file:

gnu-tk -f <script-file>

Installation

You can install GNU-TK using one of the supported methods below.

Setup Packages

Setup packages are standalone installers that let you install GNU-TK directly on your system — no additional tools required.

Windows

Package Managers

NPM

NPM is a part of Node.js. Use the following command to install GNU-TK globally:

npm install -g @gapotchenko/gnu-tk

Alternatively, you can install GNU-TK locally within the Node.js project that uses it: npm install --save-dev @gapotchenko/gnu-tk.

NuGet

NuGet is a part of .NET. Use the following command to install GNU-TK as a global .NET tool:

dotnet tool install -g Gapotchenko.GnuTK

Supported Platforms

GNU-TK can be readily used on the following platforms:

  • Operating systems: Windows, macOS, Linux
  • CPU architectures: x64, ARM64

GNU Toolkits

Aside from GNU-TK utility itself, you may also need an actual GNU toolkit installed on your system:

  • Windows:
    • BusyBox
    • Cygwin
    • Git (isn't a GNU toolkit by itself, but it conveniently includes a stripped-down immutable version of MSYS2)
    • MSYS2 (recommended)
    • WSL
  • macOS:
    • Homebrew package manager with installed GNU packages; bash and coreutils is a recommended bare minimum
    • OS includes a pre-installed GNU-like toolkit
  • Linux:
    • BusyBox
    • OS includes a pre-installed GNU toolkit

Built-in Toolkits

The following built-in toolkits are bundled with GNU-TK packages to guarantee that GNU tools minimally work even when no specialized GNU toolkit is available:

How it Works

Internally, gnu-tk automatically finds and selects an appropriate GNU toolkit installed in the system, and then executes a specified command using it.

To list all available toolkits, you can use gnu-tk list command:

Available GNU Toolkits

Name               Description                Location
------------------------------------------------------------------------------
busybox            BusyBox 1.38.0             (built-in)
cygwin             Cygwin 3.6.2               C:\cygwin64
git                Git 2.50.1                 C:\Program Files\Git
msys2-clang64      MSYS2 2025-02-21           C:\msys64
msys2-clangarm64   MSYS2 2025-02-21           C:\msys64
msys2-mingw32      MSYS2 2025-02-21           C:\msys64
msys2-mingw64      MSYS2 2025-02-21           C:\msys64
msys2-msys         MSYS2 2025-02-21           C:\msys64
msys2-ucrt64       MSYS2 2025-02-21           C:\msys64
wsl                WSL 2.5.9.0                C:\Program Files\WSL

Tips:
  - You can install a GNU toolkit to add it to the list:
    https://gapt.ch/help/gnu-tk/install-toolkits
  - You can use 'GNU_TK_TOOLKIT_PATH' environment variable to specify the
    directory paths of portable GNU toolkits
  - GNU toolkits supported on Windows: BusyBox, Cygwin, Git, MSYS2, WSL

To simplify usage, GNU-TK automatically selects the most suitable GNU toolkit based on common-sense factors. You can verify the GNU toolkit selection and availability using gnu-tk check command:

GNU Toolkit Check

Name: msys2-ucrt64
Description: MSYS2 2025-02-21
Location: C:\msys64
Semantics: GNU
Isolation: none

Check status: PASS

Tips:
  - To change the selected toolkit, specify '--toolkit' command-line option or
    its shorthand '-t'
  - Alternatively, you can set 'GNU_TK_TOOLKIT' environment variable to the
    name of a GNU toolkit to use by default

You can affect GNU toolkit selection during command invocation. For example, you can pass -s (or --strict) command-line option to gnu-tk, indicating that a toolkit with strict GNU semantics is required:

gnu-tk -s -l sed --help

This can be vital on Unix operating systems like macOS that have built-in versions of Unix utilities. By specifying the -s command-line option, you explicitly assert that only a GNU version of sed utility should be ever used. Without that option, gnu-tk works in relaxed mode allowing built-in Unix OS commands to work as close-enough substitutes when no corresponding GNU utilities are found.

Examples

GNU-TK is an adaptable tool that can work with a variety of technologies. In this section, we'll explore a few integration examples.

Node.js

Node.js projects use a package.json file to define project configuration. One key feature of this file is the ability to specify custom scripts, which can be executed using the npm run <script> command.

By default, custom scripts defined in package.json are executed using the command shell of the host operating system. This is sufficient for basic tasks, but more complex scenarios may require commands like cp, mv, sed, and others. While some of these commands have OS-specific equivalents, relying on them can reduce the portability of your project across different environments.

In that case, you can use gnu-tk to make your scripts provably portable across different platforms. Let's examine a sample package.json file:

{
  "scripts": {
    "rebuild": "npm run clear && npm run build",
    "build": "docusaurus build && gnu-tk -l rm -rf public && gnu-tk -l mkdir public && gnu-tk -l cp -r build public/content && gnu-tk -l mv public/content/_* public && gnu-tk -l mv public/content/*.txt public && gnu-tk -s -l sed -i public/content/sitemap.xml -f src/patches/sitemap.xml.sed",
    "clear": "docusaurus clear && gnu-tk -l rm -rf public"
  }
}

Note how the gnu-tk tool is used in the script definitions. In this mode, you can seamlessly switch between native shell commands and GNU tools as needed.

For this to work, gnu-tk must be installed either globally, or locally within the Node.js project that uses gnu-tk:

npm install --save-dev @gapotchenko/gnu-tk

Just

just is a cross-platform script runner.

By default, just executes scripts using the command shell of the host operating system. This approach works well for trivial cases but falls apart on more complex scenarios. Let's examine a sample justfile:

run:
    echo Just hello
    cp --help

If you try to run this script with just run command on a Unix system, you will get the expected correct result. On Windows, you'll encounter an error because the cp command is not available on this OS.

One way to solve that problem is to use gnu-tk in place:

set windows-shell := ["cmd", "/c"]

run:
    echo Just hello
    gnu-tk -l cp --help

This gives us the desired result.

While the above approach works, repeatedly invoking gnu-tk can become tedious. To simplify things, we can configure gnu-tk as the default command shell for justfile:

set windows-shell := ["gnu-tk", "-i", "-c"]

run:
    echo Just hello
    cp --help

Now, just run command will produce the correct results on all supported platforms.

Setting windows-shell to gnu-tk for an entire justfile can sometimes be too aggressive. In such cases, a more gradual approach using the [script] attribute may be preferable (docs):

set windows-shell := ["cmd", "/c"]
set script-interpreter := ["gnu-tk", "-i", "-l", "/bin/sh", "-eu"]

[script]
run:
    echo Just hello
    cp --help

And if you would like to write your cross-platform just recipes in another language – say, Python:

[script("gnu-tk", "-i", "-l", "/usr/bin/env", "python3")]
run:
    print("Hello from Python script")

About

A multi-platform command-line utility that provides seamless access to GNU toolkits on non-GNU operating systems.

Resources

License

Stars

Watchers

Forks