[Draft Guidelines] Crystal Packaging Guidelines (Changes/CrystalLanguage)

Hello Fedora Packagers & Fedora Packaging Committee,

In conjunction with the System-Wide Change Proposal Changes/CrystalLanguage targeting Fedora 45+, I would like to present the initial draft of the Fedora Packaging Guidelines for Crystal for community review and FPC feedback.

Per the Fedora Changes Policy on Essential Communication, we are sharing this draft early so the packaging committee and the wider community can evaluate the proposed packaging model.

Draft Documents


Key Architectural Highlights

  1. Shard-as-RPM Model (Unbundled Sources):

    • Shard libraries are packaged as unbundled source packages installing into versioned directories: %{_datadir}/crystal/shards/<name>-<version>.
    • Multiple versions of the same shard can coexist on the same system without RPM filesystem collisions, allowing applications to build against specific SemVer versions matching shard.lock.
  2. Offline Dependency Discovery & Resolution:

    • Builds in Mock/Koji run with zero network access.
    • During %prep, %crystal_setup links required shard dependencies from %{_datadir}/crystal/shards/ into local ./lib/<name>.
    • Compilation and check macros configure CRYSTAL_PATH="lib:%{crystal_shards_dir}:%{_datadir}/crystal/src".
  3. Virtual Provides & File Attributes:

    • Automatic RPM file attribute generator (/usr/lib/rpm/fileattrs/crystalshard.attr) inspects installed shard.yml files and emits:
      Provides: crystal-shard(<name>) = <version>
    • Applications specify dependencies via BuildRequires: crystal-shard(<name>).
  4. Compiler Hardening & Standard Macros:

    • Packages use the standard macro suite (%crystal_build, %crystal_install, %crystal_install_lib, %crystal_check).
    • Binaries inherit standard Fedora hardening flags: %optflags via CFLAGS and %build_ldflags via --link-flags.
  5. Bootstrap Policy Compliance:

    • Initial compiler bootstrap into Fedora uses the standard Koji side-tag workflow (identical to rustc and zig), complying fully with the No Pre-compiled Binaries Policy. Routine updates self-host natively.

We welcome feedback, questions, and suggestions from packagers and the FPC on this draft specification!

Can you bring this up during a Packaging Committee meeting (bi-weekly, next one is on Sep 3)? Most of us don’t monitor Discourse regularly :slight_smile:

One thing that I noticed in the guidelines draft at https://codeberg.org/renich/crystal-in-fedora/src/branch/master/guidelines/packaging-crystal.rst#package-naming-parallel-versioning:

Use upstream shard name (e.g., kemal, radix), or crystal-<name> when disambiguation against existing packages is required.

I think it would make sense to just use the crystal- prefix unconditionally. It results in a clear 1:1 mapping from shard names to RPM package names. Only using the prefix to disambiguate in case of collisions means that it’s not easy to determine programmatically, and makes some things more annoying (repository queries, defining policies that are supposed to cover all “Crystal library packages”, etc.).

Side note: You’ll also need to rewrite whatever ends up being submitted as policy to the Packaging Guidelines in AsciiDoc - the docs system uses that and not reStructured Text :sad_but_relieved_face:

2 Likes

Yep. I will look for the schedule and be there.

About discourse, got it. ;D

The thing is some shards are libraries and others might be frameworks or binaries (or mixed). Additionally, there are crystal shards that already use `crystal-` as a prefix.

I think we could consider rust’s or go’s guidelines as base and use either `shard-` or `crystal-` as prefix for libraries and use just the name when it comes to binary apps or frameworks.

This definitely needs more consideration. I would like to hear the opinion of the crystal community on this as well.

Yeah, noted. I will re-write in AsciiDoc as required once the guidelines are approved.

Thank you, Fabio, for taking the time to comment and review.

1 Like

xref

(Change Proposal discussion)

The Rust guidelines actually do both:

  • source package name is unconditionally rust-$crate
  • if the package also includes an application, the built binary package name defaults to $crate (but this is configurable) - i.e. dnf install ripgrep gives you ripgrep, even if the source package name is rust-ripgrep
  • if the package also includes a library interface, the built packages are named rust-$crate-*-devel
1 Like

Thanks for clarifying the clarification.

That makes a lot of sense.

I will update the draft packaging guidelines (and cr2rpm) to adopt this model.

Looking forward to discussing this at tomorrow’s Packaging Committee meeting. :slight_smile:

1 Like