Skip to content

Instantly share code, notes, and snippets.

@skatkov
Created May 25, 2025 14:40
Show Gist options
  • Save skatkov/df4db6f8b76e58fc8eefaa92592f2c1a to your computer and use it in GitHub Desktop.
Save skatkov/df4db6f8b76e58fc8eefaa92592f2c1a to your computer and use it in GitHub Desktop.
Fix exltz4 gem installation
#!/bin/bash
set -e
echo "Simple comprehensive fix for extlz4 gem installation..."
# Create temporary directory
TEMP_DIR=$(mktemp -d)
cd "$TEMP_DIR"
echo "Downloading extlz4 gem..."
gem fetch extlz4
echo "Unpacking gem..."
gem unpack extlz4-0.3.4.gem
cd extlz4-0.3.4
# Backup original files
cp ext/extconf.rb ext/extconf.rb.backup
cp ext/blockapi.c ext/blockapi.c.backup
echo "Patching extconf.rb for GCC compatibility..."
cat > ext/extconf.rb << 'EOF'
#!ruby
#vim: set fileencoding:utf-8
require "mkmf"
# Filter out Clang-specific warning flags that GCC doesn't recognize
clang_only_flags = %w[
-Wno-self-assign
-Wno-parentheses-equality
-Wno-constant-logical-operand
-Wno-tautological-compare
]
# Remove from RbConfig warnflags
if RbConfig::CONFIG["warnflags"]
original_warnflags = RbConfig::CONFIG["warnflags"]
filtered_warnflags = original_warnflags.dup
clang_only_flags.each do |flag|
filtered_warnflags.gsub!(/\s*#{Regexp.escape(flag)}\b/, '')
end
if filtered_warnflags != original_warnflags
puts "Filtering Clang-specific flags from warnflags"
RbConfig::CONFIG["warnflags"] = filtered_warnflags
end
end
module MyExtensions
refine Object do
unless Object.method_defined?(:append_cppflags)
def append_cppflags(flags)
return false unless try_cppflags(flags)
$CPPFLAGS << " #{flags}"
true
end
end
unless Object.method_defined?(:append_cflags)
def append_cflags(flags)
return false unless try_cflags(flags)
$CFLAGS << " #{flags}"
true
end
end
unless Object.method_defined?(:append_ldflags)
def append_ldflags(flags)
return false unless try_ldflags(flags)
$LDFLAGS << " #{flags}"
true
end
end
end
end
using MyExtensions
append_cppflags "-I$(srcdir)/../contrib/lz4/lib"
if RbConfig::CONFIG["arch"] =~ /mingw/
append_ldflags "-static-libgcc"
else
if try_compile(%q(__attribute__ ((visibility("default"))) void testfunc(void) { }))
if append_cflags "-fvisibility=hidden"
localsymbol = true
end
end
end
if localsymbol
$defs << %q('-DRBEXT_API=__attribute__ ((visibility("default")))') <<
%q(-DRBEXT_VISIBILITY=1)
else
$defs << %q(-DRBEXT_API=)
end
create_makefile File.join(RUBY_VERSION[/\d+\.\d+/], "extlz4")
EOF
echo "Patching blockapi.c for Ruby 3.3+ compatibility..."
# Fix function signatures by removing RUBY_METHOD_FUNC wrapper
sed -i 's/RUBY_METHOD_FUNC(\([^)]*\))/\1/g' ext/blockapi.c
# Disable strict pointer type checking by adding pragma
sed -i '1i\
#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"' ext/blockapi.c
# Also patch frameapi.c if it exists
if [ -f "ext/frameapi.c" ]; then
echo "Patching frameapi.c..."
sed -i 's/RUBY_METHOD_FUNC(\([^)]*\))/\1/g' ext/frameapi.c
sed -i '1i\
#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"' ext/frameapi.c
fi
echo "Building patched gem..."
rake gem
echo "Installing patched gem..."
gem install extlz4-0.3.4.gem
echo "Cleaning up..."
cd /
rm -rf "$TEMP_DIR"
echo "Successfully installed extlz4!"
@skatkov
Copy link
Author

skatkov commented May 25, 2025

This script does the following:

  1. Fixes the Clang warning flags issue - Filters out the problematic flags from Ruby's configuration
  2. Fixes the Ruby C API compatibility - Removes the RUBY_METHOD_FUNC wrapper that's causing type mismatches
  3. Adds GCC pragma - Tells GCC to ignore pointer type incompatibilities for this specific case
  4. Applies the fix to all relevant C files - Both blockapi.c and frameapi.c if present

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment