GNU-TK is a tiny project that provides seamless scriptable access to GNU tools on non-Unix operating systems.
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.
The basic usage example:
gnu-tk -l cp --helpThe 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>You can install GNU-TK using one of the supported methods below.
Setup packages are standalone installers that let you install GNU-TK directly on your system — no additional tools required.
NPM is a part of Node.js. Use the following command to install GNU-TK globally:
npm install -g @gapotchenko/gnu-tkAlternatively, you can install GNU-TK locally within the Node.js project that
uses it: npm install --save-dev @gapotchenko/gnu-tk.
NuGet is a part of .NET. Use the following command to install GNU-TK as a global .NET tool:
dotnet tool install -g Gapotchenko.GnuTKGNU-TK can be readily used on the following platforms:
- Operating systems: Windows, macOS, Linux
- CPU architectures: x64, ARM64
Aside from GNU-TK utility itself, you may also need an actual GNU toolkit installed on your system:
- Windows:
- macOS:
- Linux:
- BusyBox
- OS includes a pre-installed GNU toolkit
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:
- Windows: BusyBox
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.
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 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-tkjust 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 --helpIf 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 --helpThis 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 --helpNow, 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 --helpAnd 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")