Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions docs/guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ profile = "cli"
shrink = true
appcds = true
crac = false
compact_banner = false
compact_banner = false # deprecated, use banner_size instead
banner_size = "Normal"

# Gradle multi-project options
gradle_project = "app"
Expand All @@ -26,19 +27,28 @@ All fields are optional.

## Options

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `java_version` | integer | `21` | JDK version to bundle |
| `target` | string | current platform | Target platform (`linux-x64`, `macos-aarch64`, etc.) |
| `jvm_args` | array | `[]` | JVM arguments passed at runtime |
| `profile` | string | `"server"` | JVM profile (`"cli"` or `"server"`) |
| `shrink` | boolean | `false` | Shrink uberjar by removing non-essential files |
| `appcds` | boolean | `true` | Enable AppCDS for faster startup |
| `crac` | boolean | `false` | Enable CRaC checkpoint (Linux only) |
| `compact_banner` | boolean | `false` | Use a compact banner in the wrapper |
| `gradle_project` | string | — | Gradle subproject to build (for multi-project) |
| `modules` | array | — | Manual module list (bypasses jdeps detection) |
| `jlink_runtime` | string | — | Path to existing jlink runtime to reuse |
| Field | Type | Default | Description |
|------------------|---------|------------------|------------------------------------------------------|
| `java_version` | integer | `21` | JDK version to bundle |
| `target` | string | current platform | Target platform (`linux-x64`, `macos-aarch64`, etc.) |
| `jvm_args` | array | `[]` | JVM arguments passed at runtime |
| `profile` | string | `"server"` | JVM profile (`"cli"` or `"server"`) |
| `shrink` | boolean | `false` | Shrink uberjar by removing non-essential files |
| `appcds` | boolean | `true` | Enable AppCDS for faster startup |
| `crac` | boolean | `false` | Enable CRaC checkpoint (Linux only) |
| `compact_banner` | boolean | `false` | Use a compact banner in the wrapper *(deprecated)* |
| `banner_size` | enum | `Normal` | Set the banner size in the wrapper |
| `gradle_project` | string | — | Gradle subproject to build (for multi-project) |
| `modules` | array | — | Manual module list (bypasses jdeps detection) |
| `jlink_runtime` | string | — | Path to existing jlink runtime to reuse |

The possible values for the banner size (in both command line and configuration file) are:

| Value | Result |
|-----------|----------------------------|
| `None` | No banner is displayed |
| `Compact` | A compact, one-line banner |
| `Normal` | ASCII art banner |

## Precedence

Expand Down
59 changes: 30 additions & 29 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,29 @@ jbundle build [OPTIONS] --input <PATH> --output <PATH>

### Required Arguments

| Argument | Description |
|----------|-------------|
| `--input <PATH>` | Project directory or JAR file |
| `--output <PATH>` | Output binary path |
| Argument | Description |
|-------------------|-------------------------------|
| `--input <PATH>` | Project directory or JAR file |
| `--output <PATH>` | Output binary path |

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--java-version <N>` | `21` | JDK version to bundle (11, 17, 21, 22, 23, 24, 25) |
| `--target <TARGET>` | current | Target platform (see [Platforms](platforms.md)) |
| `--profile <PROFILE>` | `server` | JVM profile (`cli` or `server`) |
| `--jvm-args <ARGS>` | — | JVM arguments (e.g., `-Xmx512m`) |
| `--shrink [true\|false]` | `false` | Shrink uberjar by removing non-essential files |
| `--no-appcds` | — | Disable AppCDS generation |
| `--crac` | — | Enable CRaC checkpoint (Linux only) |
| `--compact-banner` | — | Use a compact banner in the wrapper |
| `--gradle-project <NAME>` | — | Gradle subproject to build (multi-project) |
| `--all` | — | Build all application subprojects (Gradle) |
| `--modules <LIST>` | — | Manual module list, comma-separated |
| `--jlink-runtime <PATH>` | — | Path to existing jlink runtime to reuse (must contain `bin/java`) |
| `-v, --verbose` | — | Enable verbose output |
| Option | Default | Description |
|---------------------------|----------|-------------------------------------------------------------------|
| `--java-version <N>` | `21` | JDK version to bundle (11, 17, 21, 22, 23, 24, 25) |
| `--target <TARGET>` | current | Target platform (see [Platforms](platforms.md)) |
| `--profile <PROFILE>` | `server` | JVM profile (`cli` or `server`) |
| `--jvm-args <ARGS>` | — | JVM arguments (e.g., `-Xmx512m`) |
| `--shrink [true\|false]` | `false` | Shrink uberjar by removing non-essential files |
| `--no-appcds` | — | Disable AppCDS generation |
| `--crac` | — | Enable CRaC checkpoint (Linux only) |
| `--compact-banner` | `false` | Use a compact banner in the wrapper *(deprecated)* |
| `--banner-size <SIZE>` | `Normal` | Set the banner size in the wrapper |
| `--gradle-project <NAME>` | — | Gradle subproject to build (multi-project) |
| `--all` | — | Build all application subprojects (Gradle) |
| `--modules <LIST>` | — | Manual module list, comma-separated |
| `--jlink-runtime <PATH>` | — | Path to existing jlink runtime to reuse (must contain `bin/java`) |
| `-v, --verbose` | — | Enable verbose output |

### Examples

Expand Down Expand Up @@ -88,9 +89,9 @@ jbundle analyze [OPTIONS]

### Options

| Option | Default | Description |
|--------|---------|-------------|
| `--input <PATH>` | `.` | Project directory or pre-built JAR file |
| Option | Default | Description |
|------------------|---------|-----------------------------------------|
| `--input <PATH>` | `.` | Project directory or pre-built JAR file |

When given a project directory, jbundle detects the build system, builds the uberjar, then analyzes it. When given a JAR file directly, it skips the build step.

Expand Down Expand Up @@ -160,16 +161,16 @@ jbundle build --help

## Exit Codes

| Code | Meaning |
|------|---------|
| `0` | Success |
| `1` | Build error (compilation failed, JAR not found, etc.) |
| `2` | Configuration error (invalid arguments, missing input) |
| Code | Meaning |
|------|--------------------------------------------------------|
| `0` | Success |
| `1` | Build error (compilation failed, JAR not found, etc.) |
| `2` | Configuration error (invalid arguments, missing input) |

## Environment Variables

| Variable | Description |
|----------|-------------|
| Variable | Description |
|------------|-----------------------------------------------------------|
| `RUST_LOG` | Logging level (`error`, `warn`, `info`, `debug`, `trace`) |

### Logging Examples
Expand Down
15 changes: 13 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ pub struct Cli {
pub command: Command,
}

#[derive(clap::ValueEnum, serde::Deserialize, Copy, Clone, Debug, PartialEq)]
pub enum BannerSize {
None,
Compact,
Normal,
}

#[derive(Subcommand)]
pub enum Command {
/// Build a self-contained binary from a JVM project or JAR
Expand Down Expand Up @@ -73,9 +80,13 @@ pub enum Command {
#[arg(short, long)]
verbose: bool,

/// Use a compact banner in the wrapper
#[arg(long)]
/// Use a compact banner in the wrapper (deprecated: use `--banner-size` instead)
#[arg(long, group = "legacy", conflicts_with = "banner_size")]
compact_banner: bool,

/// Set the banner size
#[arg(long, value_enum)]
banner_size: Option<BannerSize>,
},

/// Analyze a JAR or project and report size breakdown
Expand Down
3 changes: 2 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::path::PathBuf;

use crate::cli::BannerSize;
use crate::error::PackError;

#[derive(Debug, Clone, Copy, PartialEq)]
Expand Down Expand Up @@ -173,7 +174,7 @@ pub struct BuildConfig {
pub profile: JvmProfile,
pub appcds: bool,
pub crac: bool,
pub compact_banner: bool,
pub banner_size: BannerSize,
/// Gradle subproject to build (for multi-project builds)
pub gradle_project: Option<String>,
/// Build all application subprojects (Gradle multi-project)
Expand Down
25 changes: 22 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ use error::PackError;
use gradle::Subproject;
use progress::Pipeline;

use crate::cli::BannerSize;

#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
Expand Down Expand Up @@ -66,6 +68,7 @@ async fn main() -> Result<()> {
jlink_runtime,
verbose: _,
compact_banner,
banner_size,
} => {
let input_path =
std::fs::canonicalize(&input).unwrap_or_else(|_| PathBuf::from(&input));
Expand Down Expand Up @@ -141,6 +144,18 @@ async fn main() -> Result<()> {
.and_then(|c| c.compact_banner)
.unwrap_or(false);

let banner_size = if !compact_banner {
match banner_size {
Some(bs) => bs,
None => project_config
.as_ref()
.and_then(|c| c.banner_size)
.unwrap_or(BannerSize::Normal),
}
} else {
BannerSize::Compact
};

// Gradle subproject selection (CLI > config file)
let gradle_project = gradle_project.or_else(|| {
project_config
Expand Down Expand Up @@ -185,7 +200,8 @@ async fn main() -> Result<()> {
profile: jvm_profile,
appcds,
crac,
compact_banner,
//compact_banner,
banner_size,
gradle_project,
build_all: all,
modules_override,
Expand Down Expand Up @@ -521,7 +537,9 @@ async fn run_build(config: BuildConfig) -> Result<()> {
None
};

let compact_banner = config.compact_banner;
//let compact_banner = config.compact_banner;

let banner_size = config.banner_size;

// Step: Pack binary
let step = pipeline.start_step("Packing binary");
Expand All @@ -534,7 +552,8 @@ async fn run_build(config: BuildConfig) -> Result<()> {
profile: &config.profile,
appcds: config.appcds,
java_version,
compact_banner,
//compact_banner,
banner_size,
})?;
let size = std::fs::metadata(&config.output)?.len();
Pipeline::finish_step(
Expand Down
5 changes: 3 additions & 2 deletions src/pack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::path::Path;
use flate2::write::GzEncoder;
use flate2::Compression;

use crate::cli::BannerSize;
use crate::config::JvmProfile;
use crate::error::PackError;

Expand All @@ -19,7 +20,7 @@ pub struct PackOptions<'a> {
pub profile: &'a JvmProfile,
pub appcds: bool,
pub java_version: u8,
pub compact_banner: bool,
pub banner_size: BannerSize,
}

pub fn create_binary(opts: &PackOptions) -> Result<(), PackError> {
Expand Down Expand Up @@ -65,7 +66,7 @@ pub fn create_binary(opts: &PackOptions) -> Result<(), PackError> {
jvm_args: opts.jvm_args,
appcds: opts.appcds,
java_version: opts.java_version,
compact_banner: opts.compact_banner,
banner_size: opts.banner_size,
});
let stub_script = stub::finalize_stub(&stub_script);

Expand Down
16 changes: 10 additions & 6 deletions src/pack/stub.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::cli::BannerSize;
use crate::config::JvmProfile;

pub struct StubParams<'a> {
Expand All @@ -11,7 +12,7 @@ pub struct StubParams<'a> {
pub jvm_args: &'a [String],
pub appcds: bool,
pub java_version: u8,
pub compact_banner: bool,
pub banner_size: BannerSize,
}

pub fn generate(params: &StubParams) -> String {
Expand All @@ -37,17 +38,20 @@ pub fn generate(params: &StubParams) -> String {
let app_hash = params.app_hash;
let app_size = params.app_size;
let crac_size = params.crac_size;
let jbundle_banner = if params.compact_banner {
r#"echo "binary created with jbundle.avelino.run" >&2"#
} else {
r#"cat >&2 <<'BANNER'

let jbundle_banner = match params.banner_size {
BannerSize::None => "# binary created with jbundle.avelino.run",
BannerSize::Compact => r#"echo "binary created with jbundle.avelino.run" >&2"#,
BannerSize::Normal => {
r#"cat >&2 <<'BANNER'
_ _ _ _
(_) |__ _ _ _ __ __| | | ___
| | '_ \| | | | '_ \ / _` | |/ _ \
| | |_) | |_| | | | | (_| | | __/
_/ |_.__/ \__,_|_| |_|\__,_|_|\___|
|__/
BANNER"#
}
};

// AppCDS via AutoCreateSharedArchive (JDK 19+)
Expand Down Expand Up @@ -143,7 +147,7 @@ mod tests {
jvm_args: &[],
appcds: true,
java_version: 21,
compact_banner: false,
banner_size: BannerSize::NORMAL,
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/project_config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::path::Path;

use crate::cli::BannerSize;
use anyhow::Result;
use serde::Deserialize;

Expand All @@ -16,6 +17,7 @@ pub struct ProjectConfig {
pub appcds: Option<bool>,
pub crac: Option<bool>,
pub compact_banner: Option<bool>,
pub banner_size: Option<BannerSize>,
/// Gradle subproject to build (for multi-project builds)
pub gradle_project: Option<String>,
/// Manual module override (bypasses jdeps detection)
Expand Down Expand Up @@ -57,6 +59,7 @@ profile = "cli"
appcds = false
crac = true
compact_banner = false
banner_size = "NORMAL"
gradle_project = "jabkit"
modules = ["java.base", "java.sql"]
jlink_runtime = "./build/jlink"
Expand All @@ -76,6 +79,7 @@ jlink_runtime = "./build/jlink"
assert_eq!(config.appcds, Some(false));
assert_eq!(config.crac, Some(true));
assert_eq!(config.compact_banner, Some(false));
assert_eq!(config.banner_size, Some(BannerSize::NORMAL));
assert_eq!(config.gradle_project.as_deref(), Some("jabkit"));
assert_eq!(
config.modules,
Expand Down