Package Development Guide

This document describes how to create and maintain package scripts for the toolarium common-build package installation system.

Overview

The package system allows cb --install <package> [version] to download, extract, and register developer tools. Each package is defined by a pair of scripts:

bin/packages/<package-name>/<package-name>.sh    (Linux/macOS)
bin/packages/<package-name>/<package-name>.bat   (Windows)

The package script's sole job is to set environment variables that tell the main cb installer what to download, where to extract, and how to register the tool. The script does not download or extract anything itself.

Installation Flow

When a user runs cb --install maven 3.9.14 --default, the following steps happen:

  1. Version resolution — If no version is given, cb looks up the default in conf/tool-version-default.properties (or the custom config's version).
  2. Package script execution — cb sources bin/packages/maven/maven.sh (or .bat), passing the version as $1. The script sets CB_PACKAGE_* variables.
  3. URL construction — If CB_PACKAGE_DOWNLOAD_URL is not set, cb constructs it from CB_PACKAGE_BASE_URL + CB_PACKAGE_DOWNLOAD_NAME.
  4. Download — The archive is downloaded to $CB_DEVTOOLS/.repository/ (skipped if already cached).
  5. Extraction — The archive is extracted into $CB_DEVTOOLS/. The top-level directory is auto-detected from the archive, or forced via CB_PACKAGE_DEST_VERSION_NAME.
  6. Post-install commandsCB_PACKAGE_BUILD_CMD and CB_PACKAGE_PERMISSION_CMD run inside the extracted directory.
  7. Junction/symlink creation — If --default is given (or this is the first install), a symlink is created: $CB_HOME/current/<package>$CB_DEVTOOLS/<extracted-dir>.
  8. Version tracking — The version is recorded in conf/tool-version-installed.properties.

Environment Variables Set by Package Scripts

These variables are the contract between a package script and the cb installer.

Mandatory

VariableDescriptionExample
CB_PACKAGE_DOWNLOAD_NAME Exact filename of the downloaded archive. Must match what the download URL produces. Used as the filename in $CB_DEVTOOLS/.repository/. apache-maven-3.9.14-bin.zip

URL (one of these must be set)

VariableDescriptionExample
CB_PACKAGE_BASE_URL Base URL directory. Combined with CB_PACKAGE_DOWNLOAD_NAME to form the full URL. Use this when the URL follows the pattern base/filename. https://archive.apache.org/dist/maven/maven-3/3.9.14/binaries
CB_PACKAGE_DOWNLOAD_URL Complete download URL. Overrides CB_PACKAGE_BASE_URL when set. Use this when the URL cannot be split into base + filename. Set to "NA" to skip the download entirely. https://github.com/git-for-windows/git/releases/download/v2.53.0/Git-2.53.0-64-bit.exe

Optional

VariableDefaultDescription
CB_PACKAGE_VERSION (empty) The version being installed. Used in log messages and version tracking. Set this if the actual version differs from the input parameter (e.g., after API lookup).
CB_PACKAGE_VERSION_NAME Same as CB_PACKAGE_DOWNLOAD_NAME Friendly name for the extracted tool directory. Used in log messages.
CB_PACKAGE_DEST_VERSION_NAME (auto-detected from archive) Forces extraction into $CB_DEVTOOLS/<this-value>/ instead of auto-detecting the top-level directory from the archive. Use when the archive has non-standard structure or no top-level directory.
CB_PACKAGE_DIRECTORY_NAME (set by cb after extraction) Full path to the extracted tool. Normally set by cb, but package scripts may pre-set it for the CB_PACKAGE_ALREADY_EXIST check.
CB_PACKAGE_ALREADY_EXIST false Set to true when the target directory already exists and overwrite is not forced. Critical: without this, re-running an install extracts over the existing directory but does not update the current/ symlink or tool-version-installed.properties.
CB_PACKAGE_NO_DEFAULT false Set to true to skip symlink creation and version tracking. Use for tools that install system-wide (e.g., Docker via system package manager).
CB_PACKAGE_BUILD_CMD (empty) Shell command executed inside the extracted directory after extraction. Use for flattening nested structures, compiling from source, or post-install setup.
CB_PACKAGE_PERMISSION_CMD (empty) Shell command executed inside the extracted directory after the build command. Use for setting executable permissions.
CB_PACKAGE_INSTALL_PARAMETER (empty) Parameters passed to .exe or .sh installers. Use for silent/unattended installation flags.
CB_POST_INSTALL_ACTION (empty) Command executed after extraction and symlink creation. Use for creating desktop shortcuts, wrapper scripts, or additional configuration.

Environment Variables Available to Package Scripts

These variables are set by cb before calling the package script. Package scripts can read them to make platform-specific decisions.

Platform and Architecture

VariableValuesDescription
CB_OSlinux, mac, cygwin, freebsd, solaris, aixOperating system (normalized from uname)
CB_MACHINEx86_64, aarch64, arm, s390x, etc.Machine architecture from uname -m
CB_PROCESSOR_ARCHITECTURE_NUMBER32 or 64Processor word size (from getconf LONG_BIT)

Directories

VariableDescriptionTypical value
CB_HOMECommon-build installation root/home/user/devtools/toolarium-common-build-1.1.0
CB_DEVTOOLSRoot directory for all installed tools/home/user/devtools
CB_DEV_REPOSITORYDownload cache directory/home/user/devtools/.repository
CB_CURRENT_PATHSymlink directory (current/<tool> → versioned dir)/home/user/devtools/toolarium-common-build-1.1.0/current
CB_TEMPTemporary directory for work files/tmp/cb-user
CB_LOGSLog directory$CB_HOME/logs

Flags

VariableValuesDescription
CB_INSTALL_OVERWRITE_DISTtrue / falseWhether to force re-download and re-extraction
CB_INSTALL_SILENTtrue / falseSuppress console output
CB_VERBOSEtrue / falseEnable verbose logging
CB_SET_DEFAULTtrue / falseWhether to create the current/ symlink (set by --default or -d flag)
CB_OFFLINEtrue / falseOffline mode (skip downloads)

Writing a Package Script

Minimal example (shell)

#!/bin/bash
# bin/packages/mytool/mytool.sh

# Default version (can be overridden via CB_MYTOOL_VERSION env var)
[ -z "$CB_MYTOOL_VERSION" ] && CB_MYTOOL_VERSION="1.2.3"

# Accept version from command line, fall back to default
CB_PACKAGE_VERSION="$1"
[ -z "$CB_PACKAGE_VERSION" ] && CB_PACKAGE_VERSION="$CB_MYTOOL_VERSION"

# Set download coordinates
CB_PACKAGE_BASE_URL="https://releases.example.com/mytool/${CB_PACKAGE_VERSION}"
CB_PACKAGE_DOWNLOAD_NAME="mytool-${CB_PACKAGE_VERSION}.tar.gz"
CB_PACKAGE_VERSION_NAME="mytool-${CB_PACKAGE_VERSION}"

export CB_PACKAGE_VERSION CB_PACKAGE_BASE_URL CB_PACKAGE_DOWNLOAD_NAME CB_PACKAGE_VERSION_NAME

Minimal example (batch)

@ECHO OFF
:: bin\packages\mytool\mytool.bat

if not defined CB_MYTOOL_VERSION set "CB_MYTOOL_VERSION=1.2.3"

set "CB_PACKAGE_VERSION=%1"
if .%CB_PACKAGE_VERSION%==. set "CB_PACKAGE_VERSION=%CB_MYTOOL_VERSION%"

set "CB_PACKAGE_BASE_URL=https://releases.example.com/mytool/%CB_PACKAGE_VERSION%"
set "CB_PACKAGE_DOWNLOAD_NAME=mytool-%CB_PACKAGE_VERSION%.zip"
set "CB_PACKAGE_VERSION_NAME=mytool-%CB_PACKAGE_VERSION%"

With already-exist check (recommended)

#!/bin/bash
[ -z "$CB_MYTOOL_VERSION" ] && CB_MYTOOL_VERSION="1.2.3"
CB_PACKAGE_VERSION="$1"
[ -z "$CB_PACKAGE_VERSION" ] && CB_PACKAGE_VERSION="$CB_MYTOOL_VERSION"

CB_PACKAGE_BASE_URL="https://releases.example.com/mytool/${CB_PACKAGE_VERSION}"
CB_PACKAGE_DOWNLOAD_NAME="mytool-${CB_PACKAGE_VERSION}.tar.gz"
CB_PACKAGE_VERSION_NAME="mytool-${CB_PACKAGE_VERSION}"

# Prevent redundant extraction when already installed
CB_PACKAGE_DIRECTORY_NAME="$CB_DEVTOOLS/mytool-${CB_PACKAGE_VERSION}"
[ "$CB_INSTALL_OVERWRITE_DIST" = "false" ] && [ -d "$CB_PACKAGE_DIRECTORY_NAME" ] && CB_PACKAGE_ALREADY_EXIST=true

export CB_PACKAGE_VERSION CB_PACKAGE_BASE_URL CB_PACKAGE_DOWNLOAD_NAME CB_PACKAGE_VERSION_NAME
export CB_PACKAGE_DIRECTORY_NAME CB_PACKAGE_ALREADY_EXIST

Platform-specific downloads

#!/bin/bash
CB_PACKAGE_VERSION="$1"
[ -z "$CB_PACKAGE_VERSION" ] && CB_PACKAGE_VERSION="2.0.0"

case "$CB_OS" in
  linux)  CB_PACKAGE_DOWNLOAD_NAME="mytool-${CB_PACKAGE_VERSION}-linux-x${CB_PROCESSOR_ARCHITECTURE_NUMBER}.tar.gz" ;;
  mac)    CB_PACKAGE_DOWNLOAD_NAME="mytool-${CB_PACKAGE_VERSION}-macos-x${CB_PROCESSOR_ARCHITECTURE_NUMBER}.tar.gz" ;;
  cygwin) CB_PACKAGE_DOWNLOAD_NAME="mytool-${CB_PACKAGE_VERSION}-windows-x${CB_PROCESSOR_ARCHITECTURE_NUMBER}.zip" ;;
  *)      CB_PACKAGE_DOWNLOAD_NAME="mytool-${CB_PACKAGE_VERSION}-linux-x${CB_PROCESSOR_ARCHITECTURE_NUMBER}.tar.gz" ;;
esac

CB_PACKAGE_DOWNLOAD_URL="https://github.com/example/mytool/releases/download/v${CB_PACKAGE_VERSION}/${CB_PACKAGE_DOWNLOAD_NAME}"
CB_PACKAGE_VERSION_NAME="mytool-${CB_PACKAGE_VERSION}"
CB_PACKAGE_DEST_VERSION_NAME="mytool-${CB_PACKAGE_VERSION}"

export CB_PACKAGE_VERSION CB_PACKAGE_DOWNLOAD_URL CB_PACKAGE_DOWNLOAD_NAME
export CB_PACKAGE_VERSION_NAME CB_PACKAGE_DEST_VERSION_NAME

With post-install build command

#!/bin/bash
# When the archive has a nested directory structure that needs flattening
CB_PACKAGE_VERSION="$1"
[ -z "$CB_PACKAGE_VERSION" ] && CB_PACKAGE_VERSION="21.0.2"

CB_PACKAGE_DOWNLOAD_URL="https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${CB_PACKAGE_VERSION}/graalvm-community-jdk-${CB_PACKAGE_VERSION}_linux-x64_bin.tar.gz"
CB_PACKAGE_DOWNLOAD_NAME="graalvm-community-jdk-${CB_PACKAGE_VERSION}_linux-x64_bin.tar.gz"
CB_PACKAGE_VERSION_NAME="graalvm-${CB_PACKAGE_VERSION}"
CB_PACKAGE_DEST_VERSION_NAME="graalvm-${CB_PACKAGE_VERSION}"

# Flatten nested directory after extraction
CB_PACKAGE_BUILD_CMD="mv graalvm-community-*/* . 2>/dev/null; rmdir graalvm-community-* 2>/dev/null"

export CB_PACKAGE_VERSION CB_PACKAGE_DOWNLOAD_URL CB_PACKAGE_DOWNLOAD_NAME
export CB_PACKAGE_VERSION_NAME CB_PACKAGE_DEST_VERSION_NAME CB_PACKAGE_BUILD_CMD
Important: Shell scripts must export all CB_PACKAGE_* variables. Batch scripts do not need explicit export since set variables are visible to the calling process.

Supported Archive Formats

ExtensionTool requiredNotes
.zipunzipMost common on Windows
.tar.gz, .tgztarMost common on Linux/macOS
.tartarUncompressed tar
.xzxz, tarHigh-compression (cb checks for xz before use)
.exenoneWindows installer (executed via cmd /c on Cygwin)
.shnoneShell installer (executed directly with CB_PACKAGE_INSTALL_PARAMETER)
.debdpkgDebian package (requires root via sudo)
.rpmrpmRed Hat package (requires root via sudo)

Adding a Tool to PATH

After installing a package, it must be added to PATH in two separate code paths in cb/cb.bat:

  1. --setenv (function setCBEnv() / label :SET_ENV) — Sets environment variables for interactive shell use.
  2. Build execution (function commonBuild() / label :COMMON_BUILD) — Adds tools to PATH for build-time use. This path does NOT go through setCBEnv.
When adding a new tool that needs to be in PATH during builds, ensure it is added in both paths. Otherwise, cb --setenv will find the tool but cb (build mode) will not.

Custom Package Hooks

If a custom settings script (CB_CUSTOM_SETTING_SCRIPT) is configured, cb calls it at these points during installation:

HookWhen
install-startBefore any installation logic
download-package-startBefore download, receives package name and version
download-package-endAfter download completes
extract-package-startBefore extraction
extract-package-endAfter extraction and symlink creation
install-endAfter all installation steps complete

Version Configuration

Default versions for all tools are defined in conf/tool-version-default.properties:

maven = 3.9.14
gradle = 8.14
node = 22.16.0
java = 21

Installed versions are tracked in conf/tool-version-installed.properties (auto-maintained by cb).

Each package script should also define a fallback default version constant (e.g., CB_MAVEN_VERSION=3.9.14) used when no version is specified and the properties file is unavailable.

Platform Compatibility

PlatformCB_OS valuePackage scriptArchive format
Ubuntu / Debian / RHEL / Alpinelinux.sh.tar.gz, .tgz, .zip
macOSmac.sh.tar.gz, .zip
Windows (native)n/a.bat.zip, .exe
Windows (Git Bash / MSYS2 / Cygwin)cygwin.sh.zip, .tar.gz
FreeBSDfreebsd.sh.tar.gz
Solarissolaris.sh.tar.gz

Global Configuration Variables

These environment variables can be set by the user or in CI to customize common-build behavior globally. They affect installation, connectivity, and directory layout.

Directory Layout

VariableDefaultDescription
CB_DEVTOOLS$HOME/devtools (Unix), c:\devtools (Windows)Root directory for all dev tools.
CB_DEVTOOLS_NAMEdevtoolsName of the devtools directory (without path). Changing this overrides the directory name within $HOME.
CB_DEVTOOLS_DRIVEc:(Windows only) Drive letter where devtools are installed.
CB_HOME$CB_DEVTOOLS/toolarium-common-build-v<version>Common-build installation directory.
CB_TEMP$TMPDIR/cb-$USER (Unix), %TEMP%\cb (Windows)Temporary directory for work files, download caches, and lock files.

Network and Connectivity

VariableDefaultDescription
CB_ONLINE_ADDRESS8.8.8.8IP address or hostname used for the internet connectivity check. Override in corporate environments that block direct DNS or use a proxy.
CB_ONLINE_ADDRESS_PORT53Port used for the connectivity check.
CB_ONLINE_TIMEOUT2Timeout in seconds for the connectivity check.

Custom Configuration

VariableDefaultDescription
CB_CUSTOM_CONFIG(empty)Git URL to a custom config project for full organization-wide customization.
CB_CUSTOM_SETTING(empty)Path to a custom hook script called during all operations. See $CB_HOME/bin/sample/cb-custom-sample.sh.
CB_PACKAGE_URL(empty)URL to a directory of additional package zip files (for private/corporate package hosting).
CB_PACKAGE_USER(empty)Username for accessing CB_PACKAGE_URL.
CB_PACKAGE_PASSWORD(empty)Password for CB_PACKAGE_URL. Set to ask for interactive prompt.

Installer Behavior

VariableDefaultDescription
CB_INSTALL_ONLY_STABLEtrueSet to false to allow draft/pre-release versions when running cb-install.
CB_INSTALL_NO_PERSIST(unset)(Windows only) Set to true to prevent cb-install.bat from writing CB_HOME and PATH to the user registry via setx. Used for automated testing.

System Dependencies

The following tools must be present on the system. cb-install verifies these at installation time:

ToolRequired byPurpose
curl or wgetcb-install, cb --installDownloading packages
tarcb-install, cb --installExtracting .tar.gz / .tgz archives
unzipcb-install, cb --installExtracting .zip archives
findcb-install, cbLocating installed tool versions
diffcb-installComparing configuration files
gitcb (custom config)Cloning organization config repositories

Checklist for New Packages

  1. Create bin/packages/<name>/<name>.sh and .bat
  2. Set CB_PACKAGE_DOWNLOAD_NAME (mandatory)
  3. Set CB_PACKAGE_BASE_URL or CB_PACKAGE_DOWNLOAD_URL
  4. Set CB_PACKAGE_VERSION_NAME for clean directory naming
  5. Add the CB_PACKAGE_ALREADY_EXIST check
  6. Handle platform differences using CB_OS / CB_MACHINE / CB_PROCESSOR_ARCHITECTURE_NUMBER
  7. Add a default version to conf/tool-version-default.properties
  8. If the tool needs PATH access: add it to both setCBEnv() and commonBuild() in cb/cb.bat
  9. Shell scripts: export all CB_PACKAGE_* variables
  10. Test with cb --install <name> --default and verify current/<name> symlink is created

GNU General Public License v3.0 — see LICENSE for details.

← Back