Building Snug from Source
This chapter is for developers and technically experienced readers who want to compile Snug itself. You do not need to build Snug from source to package a Java application, use snug.options, or follow the earlier chapters. Most readers can safely skip this chapter.
Snug is an open-source Rust project. Its source code is available at
https://github.com/synapticloop/snug
These instructions describe a conventional starting point for working with the repository; the README and build files for the particular release remain the authoritative source if commands, dependencies, or outputs change.
Why Build Snug Yourself?
Building from source can be useful when checking how a release was produced, investigating a problem, testing a change, or contributing to the project. It also means that the project can be maintained independently of the precompiled executables. If you simply want to use Snug, download a published release instead.
Before You Begin
For the Windows x64 release described in this book, use a Windows x64 development environment with Git, rustup, and the Microsoft C++ build tools and Windows SDK needed for MSVC linking. The current repository pins Rust 1.98.1, including Clippy and rustfmt, in rust-toolchain.toml; Cargo.toml declares a minimum of Rust 1.89. Follow the files in your chosen release checkout if these versions change.
Open PowerShell or another terminal and confirm that the tools are available:
git --version
rustc --version
cargo --version
The version numbers will vary. If a command is not recognised, install or configure that tool before proceeding. A Java Development Kit is not necessarily required to compile the Rust launcher itself; build or test fixtures involving Java may have their own requirements.
Obtaining the Source Code
To obtain the current development source, clone the repository and enter its directory:
|
|
|
|
For a reproducible build associated with a published release, use a tag rather than assuming that the main branch contains the same code. List the available tags, then check out the tag corresponding to your chosen release:
|
|
|
|
Replace <release-tag> with an actual tag from the repository. A checkout of a release tag is normally in a detached HEAD state; that is expected if you are building rather than making changes. Record the tag and commit identifier when reporting a build problem.
Understanding the Project Layout
At a high level, the project contains Rust source code, Cargo manifests, resources used by its executables, and project-specific build or packaging assets. Start with the root README and Cargo.toml, then inspect the source directories and any workspace members. The exact directory layout may change between releases, so the repository itself is more reliable than a fixed directory tree printed in this book.
Snug's build-time executable and the executable it generates for a Java application serve different purposes. Building the Snug project produces the tooling; running that tooling with an application's JAR and configuration produces the application-specific output described in the earlier chapters.
Building the Complete Windows Release
For a complete Windows distribution, run the repository's build script from the repository root, not from the scripts directory. The script expects Cargo.toml and the demonstration application's configuration files in the current working directory. For a checked release build, use release.cmd instead: it runs the project's checks before the same distribution build.
|
|
|
|
The script performs the distribution pipeline in the required order. It builds the Windows launcher, refreshes bin\launcher-stub-windows-x86_64.exe, then rebuilds snug.exe with that launcher embedded. The sequence matters: rebuilding the builder without first refreshing the stub can leave it containing outdated launcher code. To run checks as well, use
|
|
|
|
which invokes check.ps1 before build.cmd. The wrapper also provides --CheckOnly and --SkipCheck; these are mutually exclusive. For build.cmd development flags, invoke build.cmd directly, since release.cmd forwards other arguments to both scripts.
Next, the script packages the JavaFX demonstration JAR, stamps the appropriate icons into snug.exe, snug_preview.exe, and Snug Quick Build.exe, and builds the associated tools. It also checks that the correct launcher bytes were embedded and that each executable contains the expected icon artwork. These checks protect against subtle problems that an ordinary Cargo compilation would not detect.
Finally, the script stages the distribution files in release\windows-x86_64\. The standard release folder contains:
snug.exe
Snug Quick Build.exe
snug_preview.exe
snug-javafx-demo-windows.jar
The demonstration executable is also created in the assets directory as assets\snug-javafx-demo-windows.exe. Keep Snug Quick Build.exe in the same directory as snug.exe when distributing it: the Quick Build tool looks for snug.exe alongside itself.
The script expects the demonstration JAR at assets\snug-javafx-demo-windows.jar. If that file is absent, the normal packaging step fails; build or obtain the demonstration JAR first, or explicitly use --SkipPackage while working on the builder. The script also supports focused flags such as --SkipLauncherRebuild, --SkipDevTools, --SkipDropper, --SkipVerify, --SkipRelease, and --Clean. These are useful when developing individual parts of Snug, but a full release should be built with the normal pipeline and its verification enabled.
The release directory is updated in place, so files from an earlier run can remain after a partial build. Missing staging inputs are reported as skipped. --Clean cleans snug-launcher, snug-cli, and snug-dropper Cargo outputs; it does not empty the release directory. Use a fresh staging folder before treating the output as a clean distribution.
The script targets Windows x86_64. It also parses --CrossCompile for a GNU-linked build through cargo-zigbuild, but the current script explicitly requires a Windows toolchain for resource compilation. Treat this as a development path, not a supported route to build Windows release artefacts on another operating system.
Building Individual Components with Cargo
Building a Rust component directly with Cargo is useful for development and diagnosis, but it is not a substitute for the complete Windows distribution pipeline. From the directory containing the relevant Cargo.toml, a standard Rust release build is:
|
|
|
|
If the repository uses a Cargo workspace, the command above builds the default members. Consult Cargo.toml or the repository's build instructions to determine whether you need --workspace, -p <package-name>, a specific feature, or an additional packaging command to produce every distributable executable. Do not assume that a single Cargo invocation creates the same collection of files as an official release.
For a faster development build while making changes, use:
|
|
|
|
Cargo normally places development build outputs under target/debug and release outputs under target/release, unless the project configures a different target directory. Check the build output and release scripts for the precise executable names and the files that must accompany them.
Running Tests and Checks
To run the project's defined Windows checks, use .\scripts\windows\check.ps1 from the repository root. This checks formatting, runs Clippy, and executes the workspace tests. For individual development checks, you can also run standard Cargo commands:
|
|
|
|
For a workspace, consult the project configuration to see whether all members are included. Some tests may depend on Windows features, external downloads, local Java installations, or sample projects. Read any failure message before treating it as a defect in the application itself. A passing unit test suite does not replace testing a generated Windows executable on a representative machine.
Checking the Result
Locate the compiled Snug tool, run its --help option and compare the available options with the release you intended to build. Next, package a small known-working Java application using the workflow from this book. Verify that the generated executable starts, handles its runtime requirements, and behaves as expected. Keep this smoke test separate from the build process: a successful compilation only confirms that the compiler produced output.
Common Build Problems
If Cargo is not recognised, check that Rust was installed and that the terminal has been restarted so the toolchain is on PATH. If linking fails on Windows, confirm that the MSVC target and required Visual Studio C++ tools are installed. If dependency downloads fail, check connectivity and any proxy settings. If an executable builds but will not launch, distinguish between a failure in Snug's own build and a failure in the Java application or its runtime.
When asking for assistance, include the checked-out tag or commit, the Windows version and architecture, the Rust version, the command run, and the complete error message. Avoid making unrelated toolchain upgrades while trying to reproduce a release build.
Making Changes and Contributing
Develop changes on a branch rather than directly on a checked-out release tag. Keep individual changes focused, run the relevant tests, and follow the contribution guidance in the repository before opening a pull request. Issues, review discussions, and internal implementation details belong primarily with the source code, where they can stay in step with changes to the project.
A Note About Versions
This chapter deliberately describes the stable outline of the process rather than promising that all command-line flags, package names, or build artefacts will remain unchanged. For a particular Snug release, its Git tag, Cargo manifests, README, and release instructions take precedence. The book explains how to approach building Snug; the repository documents the exact mechanics of the current implementation.