Skip to content

Commit 9331af4

Browse files
committed
Support linux jail on FreeBSD
1 parent b2e380f commit 9331af4

File tree

4 files changed

+196
-107
lines changed

4 files changed

+196
-107
lines changed

.github/workflows/build.yml

Lines changed: 15 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -31,76 +31,33 @@ jobs:
3131

3232
runs-on: ${{ matrix.os }}
3333

34-
container: ${{ matrix.container.image != 'docker.io/nixos/nix:latest' && matrix.container || null }}
35-
3634
strategy:
3735
fail-fast: false
3836
matrix:
39-
os:
40-
- macos-latest
41-
- ubuntu-latest
42-
- ubuntu-24.04-arm
43-
- windows-latest
44-
container:
45-
-
46-
vm:
47-
-
48-
ruby-version:
49-
- '3.1'
50-
- '3.2'
51-
- '3.3'
52-
- '3.4'
53-
- jruby
54-
- truffleruby
55-
- truffleruby+graalvm
56-
exclude:
57-
- os: windows-latest
58-
ruby-version: truffleruby
59-
- os: windows-latest
60-
ruby-version: truffleruby+graalvm
6137
include:
62-
- os: ubuntu-latest
63-
container:
64-
image: docker.io/library/ruby:3.1-alpine
65-
- os: ubuntu-latest
66-
container:
67-
image: docker.io/library/ruby:3.2-alpine
68-
- os: ubuntu-latest
69-
container:
70-
image: docker.io/library/ruby:3.3-alpine
71-
- os: ubuntu-latest
72-
container:
73-
image: docker.io/library/ruby:3.4-alpine
74-
- os: ubuntu-latest
75-
container:
76-
image: docker.io/nixos/nix:latest
77-
- os: ubuntu-24.04-arm
78-
container:
79-
image: docker.io/nixos/nix:latest
8038
- os: ubuntu-latest
8139
vm:
8240
os: freebsd
83-
run: pkg install -y node npm protobuf ruby rubygem-bundler rubygem-rake
84-
- os: ubuntu-latest
85-
vm:
86-
os: openbsd
8741
run: |
88-
pkg_add node protobuf ruby%3.3 ruby-shims
89-
echo 3.3 | tee /etc/ruby-version
42+
pkg install -y node npm protobuf ruby rubygem-bundler rubygem-rake
9043
- os: ubuntu-latest
9144
vm:
92-
os: netbsd
93-
run: /usr/sbin/pkg_add nodejs protobuf ruby
94-
- os: ubuntu-latest
95-
vm:
96-
os: dragonflybsd
97-
run: pkg install -y libnghttp2 libuv node npm protobuf ruby rubygem-bundler rubygem-rake
45+
os: freebsd
46+
run: |
47+
pkg install -y node npm protobuf ruby rubygem-bundler rubygem-rake
48+
sysrc linux_enable="YES"
49+
service linux start
9850
- os: ubuntu-latest
9951
vm:
100-
os: omnios
52+
os: freebsd
10153
run: |
102-
pkg install build-essential node-22 protobuf ruby-33
103-
pkg install "$(pkg search -HI -o pkg.name "$(ruby -e 'puts RbConfig::CONFIG["CC"]')")"
54+
pkg install -y debootstrap ruby rubygem-bundler rubygem-rake
55+
sysrc linux_enable="YES"
56+
service linux start
57+
debootstrap jammy /compat/ubuntu
58+
ln -sf ../lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /compat/ubuntu/lib64/ld-linux-x86-64.so.2
59+
mount -t linprocfs linproc /compat/ubuntu/proc
60+
sysctl compat.linux.emul_path=/compat/ubuntu
10461
10562
steps:
10663
- name: Checkout
@@ -113,33 +70,14 @@ jobs:
11370
os: ${{ matrix.vm.os }}
11471
run: ${{ matrix.vm.run }}
11572

116-
- name: Initialize nix
117-
if: matrix.container.image == 'docker.io/nixos/nix:latest'
118-
uses: ./.github/actions/setup-nix
119-
with:
120-
image: ${{ matrix.container.image }}
121-
packages: ruby
122-
123-
- name: Install dependencies
124-
if: endsWith(matrix.container.image, ':alpine') || endsWith(matrix.container.image, '-alpine')
125-
run: apk add build-base
126-
127-
- name: Setup ruby
128-
if: matrix.ruby-version
129-
uses: ruby/setup-ruby@v1
130-
with:
131-
ruby-version: ${{ matrix.ruby-version }}
132-
bundler-cache: true
133-
13473
- name: Bundle
135-
if: "!matrix.ruby-version"
13674
run: bundle install
13775

13876
- name: Compile
13977
run: bundle exec rake compile
14078

14179
- name: Spec
142-
if: "!matrix.vm" # TODO: remove after https://github.com/sass/dart-sass/pull/2413
80+
if: "!matrix.vm || contains(matrix.vm.run, 'sysctl compat.linux.emul_path')"
14381
run: bundle exec rake spec
14482

14583
- name: Install

ext/sass/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/dart-sass/
66
/embedded_sass.proto
77
/embedded_sass_pb.rb
8+
/exit-*
89
/node_modules/
910
/package-lock.json
1011
/pnpm-lock.yaml

ext/sass/Rakefile

Lines changed: 162 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ task install: %w[cli.rb] do
99
end
1010

1111
CLEAN.include %w[
12+
exit-aarch64
13+
exit-arm
14+
exit-i386
15+
exit-riscv64
16+
exit-x86_64
1217
protoc.exe
1318
ruby
1419
*.proto
@@ -65,6 +70,15 @@ end
6570

6671
task 'dart-sass' do
6772
Rake::Task['dart-sass/sass'].invoke
73+
74+
if SassConfig.linuxulator?
75+
begin
76+
sh 'dart-sass/sass', '--version'
77+
rescue StandardError
78+
rm_rf 'dart-sass'
79+
raise NotImplementedError
80+
end
81+
end
6882
rescue NotImplementedError
6983
Rake::Task['node_modules/sass'].invoke
7084
end
@@ -158,6 +172,123 @@ rule '_pb.rb' => %w[.proto protoc.exe] do |t|
158172
sh './protoc.exe', '--proto_path=.', '--ruby_out=.', t.source
159173
end
160174

175+
rule(/^exit-\w+$/) do |t|
176+
require_relative '../../lib/sass/elf'
177+
178+
elf = Sass.const_get(:ELF)
179+
180+
case t.name.delete_prefix('exit-')
181+
when 'aarch64'
182+
ei_class = elf::ELFCLASS64
183+
ei_data = elf::ELFDATA2LSB
184+
e_machine = 0xb7
185+
e_flags = 0
186+
187+
# 0x0000000000000078: A8 0B 80 D2 mov x8, #0x5d
188+
# 0x000000000000007c: 00 00 80 D2 mov x0, #0
189+
# 0x0000000000000080: 01 00 00 D4 svc #0
190+
entry = ['a80b80d2000080d2010000d4'].pack('H*')
191+
when 'arm'
192+
ei_class = elf::ELFCLASS32
193+
ei_data = elf::ELFDATA2LSB
194+
e_machine = 0x28
195+
e_flags = 0x5000400
196+
197+
# 0x0000000000000054: 00 00 A0 E3 mov r0, #0
198+
# 0x0000000000000058: 01 70 A0 E3 mov r7, #1
199+
# 0x000000000000005c: 00 00 00 EF svc #0
200+
entry = ['0000a0e30170a0e3000000ef'].pack('H*')
201+
when 'riscv64'
202+
ei_class = elf::ELFCLASS64
203+
ei_data = elf::ELFDATA2LSB
204+
e_machine = 0xf3
205+
e_flags = 0x5
206+
207+
# 0x0000000000000078: 93 08 D0 05 addi a7, x0, 93
208+
# 0x000000000000007c: 01 45 c.li a0, 0
209+
# 0x000000000000007e: 73 00 00 00 ecall
210+
entry = ['9308d005014573000000'].pack('H*')
211+
when 'x86_64'
212+
ei_class = elf::ELFCLASS64
213+
ei_data = elf::ELFDATA2LSB
214+
e_machine = 0x3e
215+
e_flags = 0
216+
217+
# 0x0000000000000078: 31 FF xor edi, edi
218+
# 0x000000000000007a: B8 3C 00 00 00 mov eax, 0x3c
219+
# 0x000000000000007f: 0F 05 syscall
220+
entry = ['31ffb83c0000000f05'].pack('H*')
221+
when 'i386'
222+
ei_class = elf::ELFCLASS32
223+
ei_data = elf::ELFDATA2LSB
224+
e_machine = 0x03
225+
e_flags = 0
226+
227+
# 0x0000000000000054: 31 DB xor ebx, ebx
228+
# 0x0000000000000056: B8 01 00 00 00 mov eax, 1
229+
# 0x000000000000005b: CD 80 int 0x80
230+
entry = ['31dbb801000000cd80'].pack('H*')
231+
else
232+
raise NotImplementedError
233+
end
234+
235+
File.open(t.name, 'wb', 0o755) do |file|
236+
elf.allocate.instance_eval do
237+
case ei_class
238+
when elf::ELFCLASS32
239+
e_ehsize = elf::Elf32_Ehdr.sizeof
240+
e_phentsize = elf::Elf32_Phdr.sizeof
241+
e_shentsize = elf::Elf32_Shdr.sizeof
242+
when elf::ELFCLASS64
243+
e_ehsize = elf::Elf64_Ehdr.sizeof
244+
e_phentsize = elf::Elf64_Phdr.sizeof
245+
e_shentsize = elf::Elf64_Shdr.sizeof
246+
else
247+
raise EncodingError
248+
end
249+
e_phoff = e_ehsize
250+
p_offset = e_phoff + e_phentsize
251+
e_entry = (2**22) + p_offset
252+
p_vaddr = e_entry
253+
p_filesz = entry.length
254+
p_memsz = p_filesz
255+
256+
@ehdr = {
257+
e_ident: [127, 69, 76, 70, ei_class, ei_data, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
258+
e_type: 2,
259+
e_machine:,
260+
e_version: 1,
261+
e_entry:,
262+
e_phoff:,
263+
e_shoff: 0,
264+
e_flags:,
265+
e_ehsize:,
266+
e_phentsize:,
267+
e_phnum: 1,
268+
e_shentsize:,
269+
e_shnum: 0,
270+
e_shstrndx: 0
271+
}
272+
@phdrs = [
273+
{
274+
p_type: 1,
275+
p_flags: 5,
276+
p_offset:,
277+
p_vaddr:,
278+
p_paddr: 0,
279+
p_filesz:,
280+
p_memsz:,
281+
p_align: 4096
282+
}
283+
]
284+
@shdrs = []
285+
286+
dump(file)
287+
file.write(entry)
288+
end
289+
end
290+
end
291+
161292
# This is a FileUtils extension that defines several additional commands to be
162293
# added to the FileUtils utility functions.
163294
module FileUtils
@@ -305,6 +436,33 @@ end
305436
# The {SassConfig} module.
306437
module SassConfig
307438
module Platform
439+
CPU = case RbConfig::CONFIG['host_cpu'].downcase
440+
when /amd64|x86_64|x64/
441+
'x86_64'
442+
when /i\d86|x86|i86pc/
443+
'x86'
444+
when /arm64|aarch64/
445+
'aarch64'
446+
when /arm/
447+
'arm'
448+
when /ppc64le|powerpc64le/
449+
'powerpc64le'
450+
else
451+
RbConfig::CONFIG['host_cpu']
452+
end
453+
454+
LINUXULATOR = if RbConfig::CONFIG['host_os'].include?('freebsd')
455+
begin
456+
Rake::Task["exit-#{CPU}"].invoke
457+
RbConfig::CONFIG['host_os'] = 'linux-gnu' if system("./exit-#{CPU}")
458+
true
459+
rescue NotImplementedError
460+
false
461+
end
462+
else
463+
false
464+
end
465+
308466
OS = case RbConfig::CONFIG['host_os'].downcase
309467
when /darwin/
310468
'darwin'
@@ -322,21 +480,6 @@ module SassConfig
322480
RbConfig::CONFIG['host_os'].downcase
323481
end
324482

325-
CPU = case RbConfig::CONFIG['host_cpu'].downcase
326-
when /amd64|x86_64|x64/
327-
'x86_64'
328-
when /i\d86|x86|i86pc/
329-
'x86'
330-
when /arm64|aarch64/
331-
'aarch64'
332-
when /arm/
333-
'arm'
334-
when /ppc64le|powerpc64le/
335-
'powerpc64le'
336-
else
337-
RbConfig::CONFIG['host_cpu']
338-
end
339-
340483
ARCH = "#{CPU}-#{OS}".freeze
341484
end
342485

@@ -518,4 +661,8 @@ module SassConfig
518661
platform
519662
end
520663
end
664+
665+
def linuxulator?
666+
Platform::LINUXULATOR
667+
end
521668
end

0 commit comments

Comments
 (0)