https://github.com/marcoroth/rake-cross-compiler
Cross-compile Ruby native extensions using Zig as a drop-in cross-compiler.
https://github.com/marcoroth/rake-cross-compiler
Last synced: 6 months ago
JSON representation
Cross-compile Ruby native extensions using Zig as a drop-in cross-compiler.
- Host: GitHub
- URL: https://github.com/marcoroth/rake-cross-compiler
- Owner: marcoroth
- Created: 2025-12-20T15:33:19.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-12-20T20:11:32.000Z (6 months ago)
- Last Synced: 2025-12-22T17:44:18.098Z (6 months ago)
- Language: Ruby
- Homepage:
- Size: 64.5 KB
- Stars: 4
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# rake-cross-compiler
Cross-compile Ruby native extensions using [Zig](https://ziglang.org/) as a drop-in C/C++ cross-compiler.
A lightweight alternative to [rake-compiler-dock](https://github.com/rake-compiler/rake-compiler-dock) that doesn't require Docker.
## Why?
Building native Ruby gems for multiple platforms traditionally requires:
- Docker containers with pre-configured cross-compilation toolchains
- Heavy disk usage and slow container startup times
- Complex setup for each target platform
**rake-cross-compiler** uses Zig's built-in cross-compilation capabilities instead:
- No Docker required
- Single `zig` binary handles all targets
- Cross-compile from any OS to Linux, macOS, and Windows
- Vendored Ruby headers for all supported platforms and Ruby versions
## Installation
Install the gem:
```bash
gem install rake-cross-compiler
```
Or add to your Gemfile:
```ruby
gem "rake-cross-compiler"
```
You'll also need [Zig](https://ziglang.org/download/) installed (version 0.13.0 or later). If Zig is not installed, rake-cross-compiler can auto-download it.
## Usage
### Basic Usage
```ruby
require "rake_cross_compiler"
```
**Cross-compile for Linux x86_64**
```ruby
Rake::Cross::Compiler.sh("bundle && rake compile", platform: "x86_64-linux")
```
**Or use the convenience alias**
```ruby
RakeCrossCompiler.sh("bundle && rake compile", platform: "aarch64-linux")
```
### Multiple Platforms
```ruby
RakeCrossCompiler.sh("rake native gem", platform: "x86_64-linux aarch64-linux arm64-darwin")
```
### In a Rakefile (Recommended)
The easiest integration with rake-compiler in `Rakefile`:
```ruby
require "rake/extensiontask"
require "rake_cross_compiler"
PLATFORMS = %w[
x86_64-linux-gnu
aarch64-linux-gnu
x86_64-linux-musl
aarch64-linux-musl
arm64-darwin
x86_64-darwin
].freeze
Rake::ExtensionTask.new("my_extension") do |ext|
ext.cross_compile = true
ext.cross_platform = PLATFORMS
end
namespace :gem do
task :prepare do
spec = Gem::Specification.load("my_gem.gemspec")
# Set RUBY_CC_VERSION based on gemspec and available platforms
Rake::Cross::Compiler.set_ruby_cc_version(spec.required_ruby_version, platforms: PLATFORMS)
# Set up cross-Ruby configurations for rake-compiler
Rake::Cross::Compiler.setup_cross_ruby(platforms: PLATFORMS)
end
PLATFORMS.each do |platform|
desc "Build native gem for #{platform}"
task platform => :prepare do
Rake::Cross::Compiler.sh(
"bundle --local && rake native:#{platform} gem",
platform: platform
)
end
end
desc "Build all native gems"
task :native => PLATFORMS
end
```
Then build gems:
```bash
bundle exec rake gem:prepare # Set up cross-ruby configs
bundle exec rake gem:x86_64-linux-gnu # Build for one platform
bundle exec rake gem:native # Build for all platforms
```
### Error Handling
```ruby
RakeCrossCompiler.sh("rake compile", platform: "x86_64-linux") do |ok, status|
if ok
puts "Build succeeded!"
else
puts "Build failed with status: #{status.exitstatus}"
end
end
```
### Getting Environment Variables
For manual integration or debugging:
```ruby
env = RakeCrossCompiler.env_for("x86_64-linux")
# => {
# "CC" => "zig cc -target x86_64-linux-gnu",
# "CXX" => "zig c++ -target x86_64-linux-gnu",
# "AR" => "zig ar",
# "RANLIB" => "zig ranlib",
# ...
# }
```
### With Extra Compiler Flags
```ruby
RakeCrossCompiler.sh(
"rake compile",
platform: "x86_64-linux",
cflags: ["-O2", "-Wall"],
ldflags: ["-lm"]
)
```
## Supported Platforms
| Ruby Platform | Zig Target |
|---------------|------------|
| `x86_64-linux` | `x86_64-linux-gnu` |
| `x86_64-linux-gnu` | `x86_64-linux-gnu` |
| `x86_64-linux-musl` | `x86_64-linux-musl` |
| `aarch64-linux` | `aarch64-linux-gnu` |
| `aarch64-linux-gnu` | `aarch64-linux-gnu` |
| `aarch64-linux-musl` | `aarch64-linux-musl` |
| `x86-linux` | `x86-linux-gnu` |
| `x86-linux-gnu` | `x86-linux-gnu` |
| `x86-linux-musl` | `x86-linux-musl` |
| `arm-linux` | `arm-linux-gnueabihf` |
| `arm-linux-gnu` | `arm-linux-gnueabihf` |
| `arm-linux-musl` | `arm-linux-musleabihf` |
| `x86_64-darwin` | `x86_64-macos` |
| `arm64-darwin` | `aarch64-macos` |
| `x64-mingw32` | `x86_64-windows-gnu` |
| `x64-mingw-ucrt` | `x86_64-windows-gnu` |
| `x86-mingw32` | `x86-windows-gnu` |
### Supported Ruby Versions
Vendored headers are available for:
- Ruby 3.0.0, 3.1.0, 3.2.0, 3.3.0, 3.4.0, 4.0.0
Note: Not all Ruby versions are available for all platforms. For example, `arm64-darwin` only has Ruby 3.1.0+. The gem automatically detects which versions are available for your target platforms.
## API Reference
### `Rake::Cross::Compiler.sh(cmd, **options)`
Run a shell command with cross-compilation environment.
```ruby
Rake::Cross::Compiler.sh(
"rake compile",
platform: "x86_64-linux",
verbose: true,
cflags: ["-O2"],
ldflags: ["-lm"],
env: { "DEBUG" => "1" },
ruby_cc_version: "3.3.0:3.4.0",
check_zig: true
)
```
Options:
- `platform:` - Target platform(s), space-separated (default: `"x86_64-linux"`)
- `verbose:` - Print command info (default: follows Rake's verbose flag)
- `cflags:` - Additional CFLAGS as array
- `ldflags:` - Additional LDFLAGS as array
- `env:` - Additional environment variables as hash
- `ruby_cc_version:` - RUBY_CC_VERSION value
- `check_zig:` - Verify Zig installation (default: `true`)
### `Rake::Cross::Compiler.exec(*args, **options)`
Run a command directly (without shell) with cross-compilation environment. Same options as `sh`.
### `Rake::Cross::Compiler.env_for(platform, cflags: [], ldflags: [])`
Get environment variables hash for a platform.
### `Rake::Cross::Compiler.setup_cross_ruby(platforms:, ruby_versions: nil)`
Set up cross-Ruby configurations for rake-compiler. Creates `rbconfig.rb` stubs in `~/.rake-compiler`.
```ruby
Rake::Cross::Compiler.setup_cross_ruby(
platforms: %w[x86_64-linux-gnu arm64-darwin],
ruby_versions: %w[3.3.0 3.4.0] # optional, auto-detected if nil
)
```
### `Rake::Cross::Compiler.ruby_cc_version(*requirements, platforms: nil)`
Get a RUBY_CC_VERSION string matching the given requirements.
```ruby
Rake::Cross::Compiler.ruby_cc_version(">= 3.1.0")
# => "4.0.0:3.4.0:3.3.0:3.2.0:3.1.0"
spec = Gem::Specification.load("my.gemspec")
Rake::Cross::Compiler.ruby_cc_version(spec.required_ruby_version, platforms: PLATFORMS)
# => "4.0.0:3.4.0:3.3.0:3.2.0:3.1.0"
```
### `Rake::Cross::Compiler.set_ruby_cc_version(*requirements, platforms: nil)`
Set the `RUBY_CC_VERSION` environment variable.
```ruby
Rake::Cross::Compiler.set_ruby_cc_version(">= 3.1.0", platforms: PLATFORMS)
```
### `Rake::Cross::Compiler.available_ruby_versions(platforms: nil, common_only: false)`
Get available Ruby versions from vendored headers.
```ruby
Rake::Cross::Compiler.available_ruby_versions
# => ["3.0.0", "3.1.0", "3.2.0", "3.3.0", "3.4.0", "4.0.0"]
# Only versions available on ALL platforms
Rake::Cross::Compiler.available_ruby_versions(platforms: PLATFORMS, common_only: true)
# => ["3.1.0", "3.2.0", "3.3.0", "3.4.0", "4.0.0"]
```
### `Rake::Cross::Compiler.supported_platforms`
List all supported Ruby platforms.
### `Rake::Cross::Compiler.zig_target_for(ruby_platform)`
Get the Zig target triple for a Ruby platform name.
### `Rake::Cross::Compiler.zig_available?`
Check if Zig is installed.
### `Rake::Cross::Compiler.zig_version`
Get the installed Zig version.
## GitHub Actions
Example workflow for building native gems:
```yaml
name: Build Gems
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.4'
bundler-cache: true
- uses: mlugg/setup-zig@v1
with:
version: 0.13.0
- name: Setup Cross-Ruby Configs
run: bundle exec rake gem:prepare
- name: Build source gem
run: bundle exec rake build
- name: Build native gems
run: bundle exec rake gem:native
- uses: actions/upload-artifact@v4
with:
name: gems
path: pkg/*.gem
```
## Environment Variables
- `ZIG` - Path to Zig executable (default: `zig`)
- `RAKE_CROSS_COMPILER_PLATFORM` - Default target platform
- `RUBY_CC_VERSION` - Ruby versions for cross-compilation (e.g., `3.3.0:3.4.0`)
## Limitations
1. **Platform-specific code** - Extensions with platform-specific assembly or intrinsics may need additional work.
2. **Windows targets** - Windows cross-compilation is supported but less tested than Linux/macOS.
## Development
```bash
bundle install
bundle exec rake test
bundle exec steep check
```
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/marcoroth/rake-cross-compiler.
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
## See Also
- [Zig](https://ziglang.org/) - The compiler powering cross-compilation
- [rake-compiler](https://github.com/rake-compiler/rake-compiler) - Build native extensions
- [rake-compiler-dock](https://github.com/rake-compiler/rake-compiler-dock) - Docker-based cross-compilation