Hello Crystal community,
I want to share an update regarding the ongoing initiative to bring the Crystal programming language natively into official Fedora Linux and EPEL (Extra Packages for Enterprise Linux) repositories.
Over the past few months, we have developed and verified the packaging architecture (Gemini and me), RPM macro toolchain, automated spec generator (cr2rpm), and a multi-stage bootstrap pipeline that complies with Fedora Packaging Guidelines.
Here is an overview of the technical architecture, bootstrap model, current status, and roadmap.
1. Compliance Requirements and Architecture Overview
Packaging a self-hosted language in Fedora requires addressing two primary constraints:
-
No Pre-compiled Binaries Policy: All binaries in Fedora must be built from source inside isolated build environments (Koji/Mock) without downloading opaque binary seeds during the build.
-
Hermetic Builds (No Network Access): Build roots have network access disabled. Package managers cannot fetch dependencies dynamically during rpmbuild.
To meet these requirements, we established the Shard-as-RPM model:
- Offline Dependency Resolution: Standardized
CRYSTAL_PATH="lib:/usr/share/crystal/shards:/usr/share/crystal/src". When dependent shards are installed as RPMs, their source trees are located under /usr/share/crystal/shards/<name>, enabling compiler discovery without vendoring or network access.
- Automatic RPM Dependency Triggers: Custom RPM file attributes (
crystalshard.attr) and generator scripts (crystalshard.prov, crystalshard.req) parse shard.yml to automatically emit virtual provides (crystal-shard(name) = version) and build requirements (crystal-shard(dep)).
- Hardening and DWARF Debuginfo: Build macros (
%crystal_flags) pass %build_ldflags (-Wl,-z,relro -Wl,--as-needed) and preserve DWARF debug symbols for standard Fedora -debuginfo subpackage generation.
2. Multi-Stage Bootstrap Pipeline
To achieve self-hosting compliance without external binaries, the toolchain is structured into three discrete stages:
[ Stage 0: Bootstrap Seed ]
│ C source bundle (crystal build --cross-compile)
│ Compiled with system GCC/Clang + LLVM, GC, PCRE2, libffi
▼
[ Stage 1: Core Toolchain ]
│ • crystal (Self-hosted compiler built by Stage 0)
│ • crystal-rpm-macros (RPM build macros & fileattr generators)
│ • shards (Dependency manager built from source)
▼
[ Stage 2: Ecosystem Verification & Shards ]
│ • Libraries: kemal, radix, exception_page
│ • CLI Tools & Linters: ameba (1.7.0), flaw (0.1.0)
│ • Applications: Native standalone ELF executables
Stage 0: Source-Based Bootstrap
The bootstrap seed is built using cross-compiled C source representation (crystal build --cross-compile) linked against system libraries (llvm-devel, gc-devel, pcre2-devel, libffi-devel) using system gcc or clang. This produces a functional Stage 0 compiler without violating Fedora build policies.
Stage 1: Self-Hosted Compiler & Packaging Tools
Using the Stage 0 compiler in a transient build environment:
-
crystal is rebuilt from its Crystal source tree into the final self-hosted compiler.
-
crystal-rpm-macros installs /usr/lib/rpm/macros.d/macros.crystal and dependency extraction helpers.
-
shards is compiled from source and tested against the new compiler.
Stage 2: Ecosystem & Applications
With Stage 1 packages published into the build root, higher-level shards and applications are built and tested offline.
3. Automated Spec Generation: cr2rpm
To simplify packaging shards and applications for packagers, we created cr2rpm, an automated spec generator written in Python:
- Metadata Extraction: Reads
shard.yml and shard.lock to determine package type (library vs. executable), licenses (mapping to standard SPDX identifiers), and target dependencies.
- Template Generation: Produces Fedora-compliant
.spec files utilizing %crystal_setup, %crystal_build, %crystal_install, and %crystal_check.
- Dependency Tree Analysis: Generates recursive dependency trees and mock chain-build ordering scripts.
4. Current Status and Verification
We have validated the entire multi-stage pipeline locally using mock --chain against clean Fedora build environments:
- Stage 0 (
crystal-1.21.0): Compiled from source, self-hosted, and passed the full spec/std_spec.cr standard library test suite.
- Stage 1 (
crystal-rpm-macros, shards-0.20.0): Built and passed all unit and integration test suites.
- Stage 2 Applications & Tools:
ameba (1.7.0): Built and verified in chroot; all 2,139 spec examples passed.
flaw (0.1.0): Built and verified in chroot; security rules and tests passed.
hello-crystal (0.1.0): Verified compilation, packaging, and chroot execution.
5. Next Steps and Collaboration
-
Fedora Change Proposal: Finalizing the system-wide FESCo change proposal targeting Fedora 44+ (subject to change).
-
Koji Staging: Establishing the Koji side-tag workflow for the official bootstrap build.
-
Fedora Crystal SIG: Forming the Fedora Crystal Special Interest Group (SIG) to maintain the compiler and core shard packages collaboratively.
We welcome feedback, suggestions, and contributors interested in packaging or testing shards on Fedora/EPEL.
Why Packaged Shards and Offline Builds Matter
The standard Crystal workflow relies on shards fetching Git repositories at build time. For Linux distributions, enterprise infrastructure, and production operations, the Shard-as-RPM model provides several foundational advantages:
-
Air-Gapped and Secure Enclaves
In regulated environments (defense, finance, healthcare, government, and critical infrastructure), build environments and production nodes operate with zero internet connectivity. By installing shard source trees into %{_datadir}/crystal/shards/ and leveraging CRYSTAL_PATH=“lib:/usr/share/crystal/shards:/usr/share/crystal/src”, Crystal applications can compile and run purely from internal, offline package mirrors without touching external Git hosts.
-
Supply Chain Security and Immutability
Dynamic Git downloads leave builds vulnerable to branch deletions, force-pushes, repository takeovers, and typosquatting. Packaged shards anchor dependencies to cryptographically signed RPM checksums and verified SPDX licenses.
-
Centralized CVE Remediation and Auditing
When a vulnerability is identified in a shared shard (such as an HTTP router or cryptographic library), system administrators and security tools (DNF, RPM, OpenSCAP) can track, audit, and patch the library system-wide at the RPM layer, eliminating the need to locate and manually patch vendored lib/ directories across multiple independent application trees.
-
Hermetic, Reproducible Builds
Buildroots in Koji and Mock require deterministic, hermetic environments. Packaging shards ensures that every single build input is accounted for and reproducible without network drift.