Skip to content

Commit 3275409

Browse files
committed
Add native gem precompilation support
Package precompiled native gems for Ruby 3.3, 3.4, and 4.0 across 10 platforms: aarch64-linux-gnu, aarch64-linux-musl, aarch64-mingw-ucrt, arm-linux-gnu, arm-linux-musl, arm64-darwin, x64-mingw-ucrt, x86_64-darwin, x86_64-linux-gnu, and x86_64-linux-musl. - Add Ruby-version-aware extension loader in lib/prism.rb with GLIBC error message for musl/glibc mismatches - Add cross-compilation support to Rakefile using rake-compiler-dock - Add CI workflow for building and testing native gems across all platforms and Ruby versions - Add bin/ scripts for building, installing, testing, and verifying gems Also, temporarily switch to manual publishing via bin/build-gems + gem push, and remove automated publish-gem.yml workflow. We should plan on adding automated publishing of native gems once this all works.
1 parent 12608d9 commit 3275409

11 files changed

Lines changed: 699 additions & 46 deletions

File tree

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
name: Native gem precompilation
2+
concurrency:
3+
group: "${{ github.workflow }}-${{ github.ref }}"
4+
cancel-in-progress: true
5+
6+
on:
7+
push:
8+
branches:
9+
- main
10+
tags:
11+
- v*
12+
pull_request:
13+
paths:
14+
- Rakefile
15+
- Gemfile
16+
- Gemfile.lock
17+
- prism.gemspec
18+
- ext/prism/**
19+
- lib/prism.rb
20+
- bin/test-gem-*
21+
- bin/build-gems
22+
- .github/workflows/native-gem-precompilation.yml
23+
workflow_dispatch:
24+
25+
jobs:
26+
native_setup:
27+
name: "Setup"
28+
runs-on: ubuntu-latest
29+
outputs:
30+
rcd_image_version: ${{ steps.rcd_image_version.outputs.rcd_image_version }}
31+
steps:
32+
- uses: actions/checkout@v6
33+
- uses: ruby/setup-ruby@v1
34+
with:
35+
ruby-version: "3.4"
36+
bundler-cache: true
37+
- id: rcd_image_version
38+
run: bundle exec ruby -e 'require "rake_compiler_dock"; puts "rcd_image_version=#{RakeCompilerDock::IMAGE_VERSION}"' >> $GITHUB_OUTPUT
39+
40+
build_source_gem:
41+
name: "build source"
42+
runs-on: ubuntu-latest
43+
steps:
44+
- uses: actions/checkout@v6
45+
- uses: ruby/setup-ruby@v1
46+
with:
47+
ruby-version: "3.4"
48+
bundler-cache: true
49+
- run: ./bin/test-gem-build gems ruby
50+
- uses: actions/upload-artifact@v7
51+
with:
52+
name: source-gem
53+
path: gems
54+
retention-days: 1
55+
56+
install_source_gem:
57+
needs: build_source_gem
58+
name: "test source ${{ matrix.os }} ${{ matrix.ruby }}"
59+
strategy:
60+
fail-fast: false
61+
matrix:
62+
os: [ubuntu, macos, windows]
63+
ruby: ["3.3", "3.4", "4.0"]
64+
runs-on: ${{ matrix.os }}-latest
65+
steps:
66+
- if: matrix.os == 'windows'
67+
name: configure git crlf
68+
run: |
69+
git config --system core.autocrlf false
70+
git config --system core.eol lf
71+
- uses: actions/checkout@v6
72+
- uses: ruby/setup-ruby@v1
73+
with:
74+
ruby-version: ${{ matrix.ruby }}
75+
- uses: actions/download-artifact@v8
76+
with:
77+
name: source-gem
78+
path: gems
79+
- run: ./bin/test-gem-install gems
80+
shell: sh
81+
82+
build_native_gem:
83+
needs: native_setup
84+
name: "build native ${{ matrix.platform }}"
85+
strategy:
86+
fail-fast: false
87+
matrix:
88+
platform:
89+
- aarch64-linux-gnu
90+
- aarch64-linux-musl
91+
- aarch64-mingw-ucrt
92+
- arm-linux-gnu
93+
- arm-linux-musl
94+
- arm64-darwin
95+
- x64-mingw-ucrt
96+
- x86_64-darwin
97+
- x86_64-linux-gnu
98+
- x86_64-linux-musl
99+
runs-on: ubuntu-latest
100+
steps:
101+
- uses: actions/checkout@v6
102+
- run: |
103+
docker run --rm -v $PWD:/work -w /work \
104+
ghcr.io/rake-compiler/rake-compiler-dock-image:${{ needs.native_setup.outputs.rcd_image_version }}-mri-${{ matrix.platform }} \
105+
./bin/test-gem-build gems ${{ matrix.platform }}
106+
- uses: actions/upload-artifact@v7
107+
with:
108+
name: "cruby-${{ matrix.platform }}-gem"
109+
path: gems
110+
retention-days: 1
111+
112+
test_linux_native:
113+
name: "${{ matrix.platform }} ${{ matrix.ruby }}"
114+
needs: build_native_gem
115+
strategy:
116+
fail-fast: false
117+
matrix:
118+
platform:
119+
- aarch64-linux-gnu
120+
- aarch64-linux-musl
121+
- arm-linux-gnu
122+
- arm-linux-musl
123+
- x86_64-linux-gnu
124+
- x86_64-linux-musl
125+
ruby: ["3.3", "3.4", "4.0"]
126+
include:
127+
# musl platforms need alpine image and build-base
128+
- { platform: aarch64-linux-musl, docker_tag: "-alpine", bootstrap: "apk add build-base linux-headers yaml-dev &&" }
129+
- { platform: arm-linux-musl, docker_tag: "-alpine", bootstrap: "apk add build-base linux-headers yaml-dev &&" }
130+
- { platform: x86_64-linux-musl, docker_tag: "-alpine", bootstrap: "apk add build-base linux-headers yaml-dev &&" }
131+
# docker platform for each platform
132+
- { platform: aarch64-linux-gnu, runner: ubuntu-24.04-arm, docker_platform: "--platform=linux/arm64" }
133+
- { platform: aarch64-linux-musl, runner: ubuntu-24.04-arm, docker_platform: "--platform=linux/arm64" }
134+
- { platform: arm-linux-gnu, runner: ubuntu-24.04-arm, docker_platform: "--platform=linux/arm/v7" }
135+
- { platform: arm-linux-musl, runner: ubuntu-24.04-arm, docker_platform: "--platform=linux/arm/v7" }
136+
runs-on: ${{ matrix.runner || 'ubuntu-latest' }}
137+
steps:
138+
- uses: actions/checkout@v6
139+
- uses: actions/download-artifact@v8
140+
with:
141+
name: cruby-${{ matrix.platform }}-gem
142+
path: gems
143+
- run: |
144+
docker run --rm -v $PWD:/work -w /work \
145+
${{ matrix.docker_platform }} ruby:${{ matrix.ruby }}${{ matrix.docker_tag }} \
146+
sh -c "
147+
${{ matrix.bootstrap }}
148+
./bin/test-gem-install ./gems
149+
"
150+
151+
test_darwin_native:
152+
name: "${{ matrix.platform }} ${{ matrix.ruby }}"
153+
needs: build_native_gem
154+
strategy:
155+
fail-fast: false
156+
matrix:
157+
os: [macos-15, macos-15-intel]
158+
ruby: ["3.3", "3.4", "4.0"]
159+
include:
160+
- os: macos-15
161+
platform: arm64-darwin
162+
- os: macos-15-intel
163+
platform: x86_64-darwin
164+
runs-on: ${{ matrix.os }}
165+
steps:
166+
- uses: actions/checkout@v6
167+
- uses: ruby/setup-ruby@v1
168+
with:
169+
ruby-version: "${{ matrix.ruby }}"
170+
- uses: actions/download-artifact@v8
171+
with:
172+
name: cruby-${{ matrix.platform }}-gem
173+
path: gems
174+
- run: ./bin/test-gem-install gems
175+
176+
test_windows_native:
177+
name: "${{ matrix.platform }} ${{ matrix.ruby }}"
178+
needs: build_native_gem
179+
strategy:
180+
fail-fast: false
181+
matrix:
182+
platform: [x64-mingw-ucrt, aarch64-mingw-ucrt]
183+
ruby: ["3.3", "3.4", "4.0"]
184+
include:
185+
- { platform: x64-mingw-ucrt, os: windows-latest }
186+
- { platform: aarch64-mingw-ucrt, os: windows-11-arm }
187+
exclude:
188+
- { platform: aarch64-mingw-ucrt, ruby: "3.3" }
189+
runs-on: ${{ matrix.os }}
190+
steps:
191+
- name: configure git crlf
192+
run: |
193+
git config --system core.autocrlf false
194+
git config --system core.eol lf
195+
- uses: actions/checkout@v6
196+
- uses: ruby/setup-ruby@v1
197+
with:
198+
ruby-version: "${{ matrix.ruby }}"
199+
- uses: actions/download-artifact@v8
200+
with:
201+
name: cruby-${{ matrix.platform }}-gem
202+
path: gems
203+
- run: ./bin/test-gem-install gems
204+
shell: sh

.github/workflows/publish-gem.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ gem "benchmark-ips"
88
gem "parser"
99
gem "rake"
1010
gem "rake-compiler"
11+
gem "rake-compiler-dock", "~> 1.12.0"
1112
gem "ruby_parser"
1213
gem "test-unit"
1314

Gemfile.lock

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ GEM
1313
erb (6.0.2)
1414
erb (6.0.2-java)
1515
ffi (1.17.3)
16+
ffi (1.17.3-aarch64-linux-gnu)
17+
ffi (1.17.3-aarch64-linux-musl)
18+
ffi (1.17.3-arm64-darwin)
19+
ffi (1.17.3-x86_64-darwin)
20+
ffi (1.17.3-x86_64-linux-gnu)
21+
ffi (1.17.3-x86_64-linux-musl)
1622
io-console (0.8.2)
1723
io-console (0.8.2-java)
1824
irb (1.17.0)
@@ -25,8 +31,20 @@ GEM
2531
nokogiri (1.19.1)
2632
mini_portile2 (~> 2.8.2)
2733
racc (~> 1.4)
34+
nokogiri (1.19.1-aarch64-linux-gnu)
35+
racc (~> 1.4)
36+
nokogiri (1.19.1-aarch64-linux-musl)
37+
racc (~> 1.4)
38+
nokogiri (1.19.1-arm64-darwin)
39+
racc (~> 1.4)
2840
nokogiri (1.19.1-java)
2941
racc (~> 1.4)
42+
nokogiri (1.19.1-x86_64-darwin)
43+
racc (~> 1.4)
44+
nokogiri (1.19.1-x86_64-linux-gnu)
45+
racc (~> 1.4)
46+
nokogiri (1.19.1-x86_64-linux-musl)
47+
racc (~> 1.4)
3048
onigmo (0.1.0)
3149
parser (3.3.10.2)
3250
ast (~> 2.4.1)
@@ -46,6 +64,7 @@ GEM
4664
rake (13.3.1)
4765
rake-compiler (1.3.1)
4866
rake
67+
rake-compiler-dock (1.12.0)
4968
rdoc (7.2.0)
5069
erb
5170
psych (>= 4.0.0)
@@ -64,8 +83,14 @@ GEM
6483
tsort (0.2.0)
6584

6685
PLATFORMS
86+
aarch64-linux-gnu
87+
aarch64-linux-musl
88+
arm64-darwin
6789
java
6890
ruby
91+
x86_64-darwin
92+
x86_64-linux-gnu
93+
x86_64-linux-musl
6994

7095
DEPENDENCIES
7196
benchmark-ips
@@ -76,6 +101,7 @@ DEPENDENCIES
76101
prism!
77102
rake
78103
rake-compiler
104+
rake-compiler-dock (~> 1.12.0)
79105
rdoc
80106
ruby_memcheck
81107
ruby_parser

0 commit comments

Comments
 (0)