Skip to content

Proposal: extend the manifest build.zig.zon with additional (optional) fields #23816

@r4gus

Description

@r4gus

In practice, manifest files are not only used by the build system/ package manager itself but also by other tools that consume them, e.g. for the generation of SBOMs (e.g. CycloneDX, SPDX) or a package registry (e.g. Zigistry). I propose to extend the build.zig.zon by the following optional top-level fields to allow maintainers to communicate certain properties of their packages more precisely. While there are other means of obtaining some of the data (e.g. reading the .git/config, trying to derive the license from a file as done by Github, etc.) having a standardized format makes the inspection of Zig packages less error prone. The proposed fields are also common in other manifests, e.g., gemspec or Cargo.toml.

license

String. Optional.

The license MUST be a valid SPDX license expression. This is a de facto standard used by the most common SBOM formats CycloneDX and SPDX, as well as other tool like the REUSE-tool.

The most common expression would contain just an identifier, e.g.

.license = "MIT",

... but more complex expressions are also supported:

.license = "Apache-2.0 AND (MIT OR GPL-2.0-only)",

authors

List. Optional.

A list of authors for the given package.

An optional email address is specified between angle brackets following the authors name.

Usage:

.authors = .{ "John Smith", "Max Musterman <max@musterman.de>" },

Note: this field is marked deprecated in the Cargo.toml spec because of the mutability of the manifest (at least that's what I read).

repository

String. Optional.

The URL of the package repository.

Usage:

.repository = "https://github.com/r4gus/zbor",

documentation

String. Optional.

The URL of the package documentation.

Usage:

.documentation = "https://docs.zml.ai/misc/zml_api/",

summary

String. Optional.

A small summary of the package. For a longer description see description.

Usage:

.summary = "This is a small summary of my package",

description

String. Optional.

A long description of the package. It should be more detailed than the summary.

Usage:

.description =
    \\ The descriptions shouldn't be longer
    \\ than a few sentences.
    ,

Let me know what you think.

Activity

myclevorname

myclevorname commented on May 6, 2025

@myclevorname

How should more complicated license expressions be handled? A lot of Rust libraries are MIT OR Apache-2.0, yet I had packaged a program once with BSD-2-Clause AND CC-BY-NC-3.0 due to some artwork used. Should said license list be replaced with a single expression as a string?

BratishkaErik

BratishkaErik commented on May 6, 2025

@BratishkaErik
Contributor

How should more complicated license expressions be handled? A lot of Rust libraries are MIT OR Apache-2.0, yet I had packaged a program once with BSD-2-Clause AND CC-BY-NC-3.0 due to some artwork used.

It would be nice to use special tooling for license expressions such as https://github.com/fsfe/reuse-tool , which would handle all complicated scenarios. And then if we still add field for license expressions in build.zig.zon, another tool can combine knowledge of reuse-tool and paths field to make one single string with full expression of all licenses used in referenced files, like this:

.{
    .paths = .{
        // Usual stuff:
        "build.zig",
        "build.zig.zon"
        "src/",

        "LICENSE/"
    },

    // Generated
    .license = "0BSD OR MPL-2.0"

    // Let's say README is licensed under some Creative Commonds license,
    // It can see that README is not included in "paths" field,
    // and omit that license from full list.
}

Should said license list be replaced with a single expression as a string?

I think yes.

r4gus

r4gus commented on May 6, 2025

@r4gus
Author

Should said license list be replaced with a single expression as a string?

Yes I think so. One could use a string representing a SPDX license expression.

This would also be compatible with REUSE as mentioned above.

BratishkaErik

BratishkaErik commented on May 6, 2025

@BratishkaErik
Contributor

authors

Note: this field is marked deprecated in the Cargo.toml spec because of the mutability of the manifest (at least that's what I read).

Some discussion: rust-lang/rfcs#3052

repository

documentation

Maybe they can be combined into one section, like links or resources?

summary

👍

description

.description =
    \\ The descriptions shouldn't be longer
    \\ than a few sentences.
    ,

I feel like 2-4 sentences might be too limiting for the description. It's too similar to the summary then.
Maybe a longer format (up to around 10 let's say) could make it more useful.
But on the other hand README already covers this...

I guess result would be something like this:

.{
    .fingerprint = 0x12345678_12345678,
    .minimum_zig_version = "0.15.0",

    .name = .example,
    .version = "0.1.0",
    .summary = "This is a small summary of my package",
    .description =
    \\ The descriptions shouldn't be longer
    \\ than a few sentences.
    ,

    .authors = .{ "John Smith", "Max Musterman <max@musterman.de>" },
    .resources = .{
        .repository = "https://github.com/r4gus/zbor",
        .documentation = "https://docs.zml.ai/misc/zml_api/",
    },

    .paths = .{"..."},
    .license = "MIT",
}
r4gus

r4gus commented on May 6, 2025

@r4gus
Author

Maybe they can be combined into one section, like links or resources?

In that case it would be very similar to metadata when using rspec, which groups the URIs nicely together.

Maybe a longer format (up to around 10 let's say) could make it more useful.
But on the other hand README already covers this...

I think the description and the content of a README are two different things. The description should explain in a few sentences (even if its 10) what the packages is about. No formatting, just plain text (maybe one could also leave out the summary and just have a description...). A typical REAMDE on the other hand contains many things: usually a description, how to get started, how to use the library, attributions, sponsors, etc.. Every README is a little bit different what makes it hard to reliably consume such data.

.{
    .fingerprint = 0x12345678_12345678,
    .minimum_zig_version = "0.15.0",

    .name = .example,
    .version = "0.1.0",
    .description =
      \\ Zbor is a Concise Binary Object Representation (CBOR) en-/decoder for Zig.
      \\ It allows the easy en-/ decoding of arbitrary objects to/ from CBOR.
    ,
    .authors = .{ 
        "John Smith", 
        "Max Musterman <max@musterman.de>", 
    },
    .resources = .{
        .repository = "https://github.com/r4gus/zbor",
        .documentation = "https://docs.zml.ai/misc/zml_api/",
    },

    .paths = .{""},
    .license = "MIT",
}
paperdev-code

paperdev-code commented on May 17, 2025

@paperdev-code

Nix packages have a meta field for this sort of information. Which might be a nice way to filter the required elements from the optional, more 'descriptive' components of the .zon file.

.{
    .fingerprint = 0x12345678_12345678,
    .minimum_zig_version = "0.15.0",

    .name = .ziguanasay,
    .version = "0.1.0",
    .paths = .{ "src", "build.zig", "build.zig.zon" },

    .meta = .{
        .description =
          \\ Program inspired by cowsay written in Zig
        ;
        .authors = .{ "foobar@example.com" } // OR '.maintainers = ...' ?
        .license = "Apache-2.0 AND (MIT OR GPL-2.0-only)",
        .homepage = "https://foobar.github.io/ziguanasay",
    },
}
r4gus

r4gus commented on May 17, 2025

@r4gus
Author
.meta = .{

The question then becomes what is metadata, e.g. why is the version a top level field but the license is not. I think grouping can make sense (e.g. grouping all URIs related to the package into a references field (called metadata in gemspec)) then we have to clearly define whats falling under meta and whats not.

    .licenses = .{ "MIT", "Apache-2.0", "./LICENSE.md" }, // allow reference to file?

I'd stick to SPDX license expressions as they are the de facto standard but one could also reference files:

.licenses = .{
    .{   // the library ...
        .expression = "MIT",
        .paths = .{
             "src/root.zig",
             "src/bar/*,                      // Allow wild cards
        },
     },
     .{  // ... and the application are licensed differently
        .expression = "Apache-2.0 AND (MIT OR GPL-2.0-only)",
        .paths = .{
             "src/main.zig",
             "src/foo/*,                      // Allow wild cards
        },
     },
},

I like the idea of referencing files. Instead of referencing a license file one could reference arbitrary files. The combination of SPDX license expressions and file references comes very close to REUSE with the difference that we wouldn't put the license information into each file. You can always obtain the license from the SPDX site.

r4gus

r4gus commented on Aug 11, 2025

@r4gus
Author

I've analyzed a lot of packages on Github and looked at their licenses.

  • Most use permissive licenses, e.g. MIT or Apache-2.0
  • Some use multiple licenses
  • For a lot of repositories with multiple licenses, it is ambiguous how they apply to the package, e.g. by having multiple license files but no statement about their relationship.
  • Some maintainers apply different licenses to different parts of their code, e.g. GPL for the lib and MIT for the examples.

In conclusion, it would make sense to give maintainers the capability to a) express more complex licenses using SPDX license expressions and b) also give them the capability to scope licenses/ apply them to specific files and folders.

For example, a package licensed under MIT would specify the following in its build.zig.zon:

.licenses = .{
    .{ 
        .expression = "MIT",
        .paths = .{
             "", // use "" to refer to the build root itself
        },
     },
},

And a package that licenses the examples under MIT but the rest under GPL could specify:

.licenses = .{
    .{ 
        .expression = "MIT",
        .paths = .{
             "examples/",
        },
     },
    .{ 
        .expression = "GPL-3.0-or-later",
        .paths = .{
             "src/", "build.zig", "build.zig.zon"
        },
     },
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @BratishkaErik@r4gus@paperdev-code@myclevorname

        Issue actions

          Proposal: extend the manifest `build.zig.zon` with additional (optional) fields · Issue #23816 · ziglang/zig