Skip to content

fix: build bundled Linux dependencies with -O2 - #64

Merged
jdx merged 1 commit into
jdx:mainfrom
rzane:rzane/optimize-linux-deps
Oct 2, 2026
Merged

jdx merged 1 commit into
jdx:mainfrom
rzane:rzane/optimize-linux-deps

Conversation

@rzane

@rzane rzane commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

On Linux, dependency_build_env set CFLAGS="-fPIC", which replaces each project's default optimization level, so libyaml, libffi, libxcrypt, zlib, OpenSSL, ncurses, and libedit were all compiled at -O0. With Ruby 3.4.10 held constant, bcrypt is about 5.7x slower and zlib about 4.7x slower than on the official ruby:3.4.10 image. bcrypt is affected because the gem's crypt_ra calls resolve to the libxcrypt linked into ruby.

This puts -O2 ahead of any inherited CFLAGS, so dependencies are optimized even when CFLAGS is set, while an -O level in CFLAGS still takes precedence. -fPIC stays last so it always applies. -O2 matches what Ubuntu builds these libraries with, except zlib, which Ubuntu and upstream build at -O3.

Reproduction

docker run --rm -i ruby:3.4.10 bash -s < repro.sh
set -e
curl -fsSL "https://github.com/jdx/ruby/releases/download/3.4.10-2/ruby-3.4.10.$(uname -m | sed s/aarch64/arm64/)_linux.tar.gz" | tar xz -C /opt

cat > /bench.rb <<'RUBY'
require "bcrypt"
require "zlib"

def measure(label)
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  yield
  printf "  %-16s %6.0f ms\n", label, (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000
end

data = Array.new(200_000) { |i| "user#{i}@example.com" }.join(",")
puts RbConfig.ruby
measure("bcrypt cost 12") { BCrypt::Password.create("password", cost: 12) }
measure("zlib deflate") { 10.times { Zlib::Deflate.deflate(data) } }
RUBY

for ruby in /usr/local/bin/ruby /opt/ruby-3.4.10/bin/ruby; do
  "${ruby%/*}/gem" install bcrypt --no-document > /dev/null
  "$ruby" /bench.rb
done

On arm64 Linux:

/usr/local/bin/ruby
  bcrypt cost 12      160 ms
  zlib deflate        117 ms
/opt/ruby-3.4.10/bin/ruby
  bcrypt cost 12      905 ms
  zlib deflate        548 ms

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: 0cceab79-5368-4279-8c63-e3eecac236ed

📥 Commits

Reviewing files that changed from the base of the PR and between 346cbf3 and 4eff425.

📒 Files selected for processing (1)
  • libexec/package.rb

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The build environment now adds a Linux-only libcrypt exclusion to XLDFLAGS. Linux dependency builds place -fPIC and, on Linux ARM64, -mno-outline-atomics in CC and CXX.

Changes

Linux build flags

Layer / File(s) Summary
Ruby build linker flags
libexec/package.rb
ruby_build_env builds XLDFLAGS from LDFLAGS and adds -Wl,--exclude-libs,libcrypt.a on Linux.
Dependency compiler flags
libexec/package.rb
Linux dependency builds append -fPIC and, on Linux ARM64, -mno-outline-atomics to CC and CXX rather than to CFLAGS and CXXFLAGS.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: jdx

Merge Risk: ⚪ Minimal · up to 4eff4

The changes align with the stated Linux build objectives, with no merge-blocking risk identified.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 4eff4

The changes are confined to Linux build configuration, with no demonstrated new attack path or weakened security control. However, the resulting executable’s symbol exports and native-extension cryptographic provider binding remain unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The relevant exposure is the produced Linux Ruby executable, its native extensions, and bundled libraries, including OpenSSL and libxcrypt. Deployment-wide or tenant-specific exposure cannot be quantified from the supplied build evidence.

Trust Boundaries and Controls

  • inferred — Compiler selection remains controlled by the existing build environment. The change appends fixed flags to CC/CXX rather than introducing a new attacker-controlled input or privilege transition. The linker change narrows intended symbol visibility, but actual native-extension provider binding remains unresolved.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the Linux dependency build optimization issue addressed by moving flags so bundled dependencies retain defaults such as -O2. It does not mention the separate libcrypt sy…
  • Fix all pre-merge checks with AI
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@rzane
rzane force-pushed the rzane/optimize-linux-deps branch from 4eff425 to 0d521a4 Compare October 1, 2026 21:21
@rzane rzane changed the title fix: optimize bundled Linux dependencies and stop exporting libxcrypt fix: build bundled Linux dependencies with their default optimizations Oct 1, 2026
@rzane
rzane marked this pull request as ready for review October 1, 2026 21:32
@greptile-apps

greptile-apps Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[High risk] Changes compiler optimization flags for bundled Linux dependencies.

The PR appears safe to merge based on the reviewed changes.

Summary

The PR adds -O2 to Linux native-dependency build flags while retaining inherited compiler flags and placing -fPIC afterward.

  • The change applies to the bundled dependency builds without changing the main Ruby build.
  • No new actionable issue was identified.

Reviews (3) · Last reviewed commit: "fix: build bundled Linux dependencies wi..."

Comment thread libexec/package.rb Outdated
@rzane
rzane force-pushed the rzane/optimize-linux-deps branch from 0d521a4 to e5c426d Compare October 1, 2026 22:02
@rzane rzane changed the title fix: build bundled Linux dependencies with their default optimizations fix: build bundled Linux dependencies with -O2 Oct 1, 2026
Comment thread libexec/package.rb Outdated
On Linux, dependency_build_env set CFLAGS to just -fPIC (plus
-mno-outline-atomics on arm64). Setting CFLAGS replaces each project's
default optimization level, so libyaml, libffi, libxcrypt, zlib, OpenSSL,
ncurses, and libedit were all compiled at -O0. zlib compression, bcrypt,
and the C parts of OpenSSL ran several times slower than with distro
builds of the same libraries.

Put -O2 ahead of any inherited CFLAGS, so dependencies are optimized even
when CFLAGS is set, while an -O level in CFLAGS still takes precedence.
-fPIC stays last so it always applies. -O2 matches what Ubuntu builds
these libraries with, except zlib, which Ubuntu and upstream build at
-O3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rzane
rzane force-pushed the rzane/optimize-linux-deps branch from e5c426d to 8f85b3b Compare October 1, 2026 22:07
@jdx
jdx merged commit 290439c into jdx:main Oct 2, 2026
11 checks passed
@rzane
rzane deleted the rzane/optimize-linux-deps branch October 2, 2026 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants