# demo

### Packaging the Result

A program is finished only when another machine can build and run it reliably.

Packaging means organizing source code, build logic, tests, dependencies, documentation, and release artifacts into a form that others can use.

A small Zig project usually begins like this:

```text
project/
    build.zig
    build.zig.zon
    src/
        main.zig
```

`build.zig` describes how to build the project.

`build.zig.zon` describes package metadata and dependencies.

`src/main.zig` contains the program entry point.

A minimal `build.zig.zon` looks like this:

```zig
.{
    .name = "demo",
    .version = "0.1.0",
    .minimum_zig_version = "0.16.0",
    .dependencies = .{},
}
```

The fields are:

| Field | Meaning |
|---|---|
| `.name` | package name |
| `.version` | package version |
| `.minimum_zig_version` | minimum supported Zig version |
| `.dependencies` | package dependencies |

The build script describes the build graph.

```zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "demo",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the application");
    run_step.dependOn(&run_cmd.step);
}
```

The project can now be built and run with standard commands.

```sh
zig build
zig build run
```

The executable is installed into Zig's output directory.

Release builds should specify an optimization mode.

```sh
zig build -Doptimize=ReleaseFast
```

Cross compilation is built into Zig. The same source tree can target another operating system or CPU architecture.

```sh
zig build -Dtarget=x86_64-linux
```

A packaged project should define clear outputs:

| Output | Example |
|---|---|
| executable | `demo` |
| static library | `libdemo.a` |
| tests | `zig build test` |
| documentation | `README.md` |

Documentation does not need to be large. It should answer four questions quickly:

1. What does the program do?
2. How is it built?
3. How is it run?
4. What Zig version is required?

A small `README.md` is enough.

```text
# demo

Small example Zig application.

## Build

    zig build

## Run

    zig build run

## Release build

    zig build -Doptimize=ReleaseFast
```

Dependencies belong in `build.zig.zon`.

Suppose a package named `httpz` is added.

```zig
.{
    .name = "demo",
    .version = "0.1.0",
    .minimum_zig_version = "0.16.0",

    .dependencies = .{
        .httpz = .{
            .url = "https://example.com/httpz.tar.gz",
            .hash = "1220...",
        },
    },
}
```

The build script imports the dependency.

```zig
const httpz = b.dependency("httpz", .{
    .target = target,
    .optimize = optimize,
});
```

Then its module is added to the executable.

```zig
exe.root_module.addImport(
    "httpz",
    httpz.module("httpz"),
);
```

A package should also define tests as build steps.

```zig
const tests = b.addTest(.{
    .root_source_file = b.path("src/main.zig"),
    .target = target,
    .optimize = optimize,
});

const run_tests = b.addRunArtifact(tests);

const test_step = b.step("test", "Run tests");
test_step.dependOn(&run_tests.step);
```

Now every important operation has one command:

| Command | Purpose |
|---|---|
| `zig build` | build |
| `zig build run` | run |
| `zig build test` | test |
| `zig build -Doptimize=ReleaseFast` | optimized build |

A release artifact should contain only what users need:

- executable or library
- license
- README
- version information

Do not package temporary build directories or editor files.

Programs that expose command-line interfaces should support:

```text
--help
--version
```

A simple version flag may be enough.

```zig
const std = @import("std");

pub fn main() !void {
    var args = std.process.args();

    _ = args.next();

    if (args.next()) |arg| {
        if (std.mem.eql(u8, arg, "--version")) {
            std.debug.print("demo 0.1.0\n", .{});
            return;
        }
    }

    std.debug.print("normal execution\n", .{});
}
```

Real packaging also includes compatibility concerns:

| Concern | Example |
|---|---|
| Zig version | 0.16-specific APIs |
| target platform | Linux, macOS, Windows |
| libc usage | glibc, musl, none |
| architecture | x86_64, ARM64 |
| optimization mode | debug vs release |

These choices should be visible in documentation and build scripts.

A Zig project scales well when it keeps several properties:

- explicit build steps
- explicit dependencies
- explicit allocators
- explicit error handling
- small source files
- testable functions

The same structure works for small tools and large systems.

Exercise 20-36. Add a `--version` flag to an earlier program.

Exercise 20-37. Create a `README.md` for the file copier.

Exercise 20-38. Add a `test` step to a packaged project.

Exercise 20-39. Build the project for another operating system.

Exercise 20-40. Split a project into multiple source files and modules.

