sigildocs

Shipping Sigil Applications

This guide explains how to package Sigil applications for distribution, covering the different commands and scenarios you'll encounter.

Overview

Sigil provides two commands for creating distributable applications:

  • sigil bundle - Package your app using the existing CLI runtime (fast, simple)
  • sigil build - Build a custom runtime with full control over native dependencies

The right choice depends on your application's needs.

Quick Reference

ScenarioCommandResult
Simple scriptsigil bundle script.sglUses CLI runtime
Multi-module app (no native deps)sigil bundle myappUses CLI runtime
App with TLS/crypto/SQLitesigil build myappCustom runtime with native libs
Minimal binary sizesigil build myappCustom runtime, only needed deps

Understanding the Two Commands

sigil bundle - Fast Packaging

The sigil bundle command creates a standalone executable by packaging your application into the existing Sigil CLI runtime. This is the fast path for distribution.

Bundling a single script:

sigil bundle script.sgl                    # Creates ./script executable
sigil bundle script.sgl -o dist/mytool     # Custom output path

For simple scripts, no package.sgl is needed. The script is compiled and embedded directly. Top-level code in the script runs immediately when the executable starts—no main procedure is required.

Bundling a multi-module application:

sigil bundle .                             # Bundle current directory
sigil bundle myapp/                        # Bundle specific directory
sigil bundle myapp/ -o dist/myapp          # Custom output path

For multi-module applications, create a minimal package.sgl specifying the entry point. The entry module must define a main procedure that will be called when the executable starts:

(package
  name: "myapp"
  entry: '(myapp main))

What it does:

  1. Takes the pre-built Sigil CLI binary as the base
  2. Compiles and embeds your modules (.sgl.sgb files)
  3. Embeds any assets from your assets/ directory
  4. Sets the entry point as the startup module

When to use:

  • Your app only uses packages included in the CLI (stdlib, json, http, etc.)
  • You want fast iteration during development
  • You don't need to minimize binary size

Limitations:

  • Cannot add native packages not already in the CLI
  • Binary includes all CLI dependencies (larger size)

sigil build - Custom Runtime

The sigil build command compiles your application with full control, building a custom runtime that includes exactly the native dependencies your app needs.

sigil build myapp
sigil build myapp --config release

What it does:

  1. Compiles all dependency packages
  2. Detects native packages (C code) in your dependency tree
  3. Generates a custom entrypoint that initializes native modules
  4. Links a custom runtime with only the needed native libraries
  5. Creates a standalone executable

When to use:

  • Your app uses native packages (crypto, TLS, SQLite, custom C extensions)
  • You want minimal binary size (only include what you use)
  • You're building for a platform different from your development machine

Scenarios

Scenario 1: Simple Application

A basic application that uses only the standard library and pure-Scheme packages.

;; package.sgl
(package
  name: "hello-world"
  version: "1.0.0"
  entry: '(hello main)

  dependencies: (list
    (from-workspace name: "sigil-stdlib")
    (from-workspace name: "sigil-json")))

Recommended: sigil bundle hello-world

The app has no native dependencies, so bundling with the CLI runtime is fastest. Pure-Scheme dependencies (like sigil-json, sigil-http) work fine with bundle since all .sgb files are replaced in the bundle anyway.

Scenario 2: Web Application with TLS

An application that makes HTTPS requests or serves HTTPS traffic.

;; package.sgl
(package
  name: "web-client"
  version: "1.0.0"
  entry: '(web-client main)

  dependencies: (list
    (from-workspace name: "sigil-stdlib")
    (from-workspace name: "sigil-http")
    (from-workspace name: "sigil-tls")
    (from-workspace name: "sigil-crypto")))

Recommended: sigil build web-client --config release

The app needs TLS and crypto native libraries, so a custom runtime is built automatically.

Scenario 3: Database Application

An application that uses SQLite for local storage.

;; package.sgl
(package
  name: "notes-app"
  version: "1.0.0"
  entry: '(notes main)

  dependencies: (list
    (from-workspace name: "sigil-stdlib")
    (from-workspace name: "sigil-sqlite")))

Recommended: sigil build notes-app --config release

SQLite is a native package, so a custom runtime includes the SQLite library.

Scenario 4: Application with Assets

An application with bundled data files, templates, or other assets.

;; package.sgl
(package
  name: "my-app"
  version: "1.0.0"
  entry: '(my-app main)

  dependencies: (list
    (from-workspace name: "sigil-stdlib")))

Place assets in the assets/ directory (by convention). They are automatically included in the bundle.

my-app/
├── package.sgl
├── src/
│   └── my-app/
│       └── main.sgl
└── assets/
    ├── templates/
    │   └── report.html
    └── data/
        └── config.json

Recommended: sigil bundle my-app

Accessing bundled assets:

(import (sigil resources))

;; Read a bundled file
(define template (resource-read "templates/report.html"))

;; Check if a resource exists
(resource-exists? "data/config.json")

;; Assets are accessed via @bundle/assets/ path internally

Scenario 5: Minimal Distribution

When binary size matters (embedded systems, quick downloads).

;; package.sgl
(package
  name: "tiny-tool"
  version: "1.0.0"
  entry: '(tiny-tool main)

  dependencies: (list
    (from-workspace name: "sigil-stdlib")))

Recommended: sigil build tiny-tool --config release

Using sigil build creates a custom runtime that only includes the modules your app actually uses, rather than the full CLI with all its dependencies.

Build Configurations

Both commands support the --config flag to select a build configuration:

sigil build myapp --config dev      # Local development (dynamic linking, fast builds)
sigil build myapp --config debug    # Debug build (static linking, debug symbols)
sigil build myapp --config release  # Release (static linking, optimized)

Common Configurations

ConfigStatic LinkingOptimizationUse Case
devNoNoneLocal development, fast iteration
debugYes (musl)NoneDebugging static builds
releaseYes (musl)O2Distribution

Cross-Compilation

For building on one platform and running on another:

sigil build myapp --config linux-arm64     # Linux ARM64
sigil build myapp --config windows-amd64   # Windows x64
sigil build myapp --config macos-arm64     # macOS Apple Silicon

Cross-compilation requires the appropriate toolchain (zig or platform-specific cross-compiler).

Native Packages

Native packages contain C code that must be compiled and linked into the runtime. Sigil's native packages include:

PackageProvidesNative Library
sigil-cryptoSHA, HMAC, base64, randomlibsigil-crypto.a
sigil-tlsTLS/SSL connectionslibsigil-tls.a
sigil-sqliteSQLite databaselibsigil-sqlite.a

When your app depends on a native package, sigil build automatically:

  1. Compiles the native code to a static library
  2. Generates an entrypoint that calls each package's init function
  3. Links everything into a custom runtime

Creating Native Packages

If you're writing a package with C code:

;; package.sgl
(package
  name: "my-native-pkg"
  version: "1.0.0"

  dependencies: (list
    (from-workspace name: "sigil-stdlib"))

  libraries: (list
    (library
      name: 'my-native-pkg
      c-sources: '("native/mycode.c")
      c-include-dirs: '("native/include")
      native-init: "my_pkg_init"))

  tasks: (list
    (task
      name: 'build
      steps: (list
        (compile-c-sources
          sources: '("native/mycode.c")
          include-dirs: '("../sigil-lib/include"
                          "../sigil-lib/src"
                          "native/include"))
        (create-static-library
          name: "my-native-pkg")))))

The native-init field specifies the C function called to register the module's primitives with the VM.

Troubleshooting

"Native packages detected but using CLI baseline"

This message appears when your app uses native packages that are already included in the CLI runtime. The build system reuses the CLI rather than building a custom runtime.

"Version mismatch detected"

When the CLI version differs from your project's dependency versions, a custom runtime is built to avoid compatibility issues.

"sigil-run executable not found"

The build system couldn't find a base runtime. Run make to build the bootstrap first.

Summary

  • Use sigil bundle for fast packaging when your app fits within the CLI's capabilities
  • Use sigil build when you need native packages or minimal binary size
  • Native packages (crypto, TLS, SQLite) automatically trigger custom runtime builds
  • Assets are bundled automatically from your assets/ directory
  • Cross-compilation is available via --config flags