Ruby 3.2.0安装unicode 0.4.4.4 gem时原生扩展编译错误求助
安装unicode gem时编译失败的解决办法
环境信息
- Ruby版本:ruby 3.2.0
- RubyGems版本:3.5.6
- rbenv版本:1.2.0
- MacOS:Sonoma 14.1.2 / M2
问题
执行bundle install安装项目依赖时,安装unicode 0.4.4.4(带原生扩展)失败,编译阶段报错:
Installing unicode 0.4.4.4 with native extensions Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/unicode-0.4.4.4/ext/unicode /Users/john.doe/.rbenv/versions/3.2.0/bin/ruby -I /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0 extconf.rb --with-cflags\=-Wno-error\=implicit-function-declaration creating Makefile current directory: /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/unicode-0.4.4.4/ext/unicode make DESTDIR\= sitearchdir\=./.gem.20240308-48017-ak1bt1 sitelibdir\=./.gem.20240308-48017-ak1bt1 clean current directory: /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/unicode-0.4.4.4/ext/unicode make DESTDIR\= sitearchdir\=./.gem.20240308-48017-ak1bt1 sitelibdir\=./.gem.20240308-48017-ak1bt1 compiling unicode.c unicode.c:37:7: warning: 'RB_OBJ_TAINTED' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations] if (OBJ_TAINTED(src)) ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/fl_type.h:151:25: note: expanded from macro 'OBJ_TAINTED' #define OBJ_TAINTED RB_OBJ_TAINTED /**< @old{RB_OBJ_TAINTED} */ ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/fl_type.h:118:30: note: expanded from macro 'RB_OBJ_TAINTED' #define RB_OBJ_TAINTED RB_OBJ_TAINTED ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/fl_type.h:812:1: note: 'RB_OBJ_TAINTED' has been explicitly marked deprecated here RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED' # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) ^ unicode.c:38:5: warning: 'RB_OBJ_TAINT' is deprecated: taintedness turned out to be a wrong idea. [-Wdeprecated-declarations] OBJ_TAINT(obj); ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/fl_type.h:149:25: note: expanded from macro 'OBJ_TAINT' #define OBJ_TAINT RB_OBJ_TAINT /**< @old{RB_OBJ_TAINT} */ ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/fl_type.h:116:30: note: expanded from macro 'RB_OBJ_TAINT' #define RB_OBJ_TAINT RB_OBJ_TAINT ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/fl_type.h:843:1: note: 'RB_OBJ_TAINT' has been explicitly marked deprecated here RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) ^ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/attr/deprecated.h:36:53: note: expanded from macro 'RBIMPL_ATTR_DEPRECATED' # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) ^ unicode.c:1039:20: error: incompatible function pointer types passing 'VALUE (get_categories_param *)' (aka 'unsigned long (struct _get_categories_param *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types] return rb_ensure(get_categories_internal, (VALUE)&param, ^~~~~~~~~~~~~~~~~~~~~~~ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2); ^ unicode.c:1040:20: error: incompatible function pointer types passing 'VALUE (WString *)' (aka 'unsigned long (struct _WString *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types] get_categories_ensure, (VALUE)&wstr); ^~~~~~~~~~~~~~~~~~~~~ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/iterator.h:425:62: note: passing argument to parameter 'e_proc' here VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2); ^ unicode.c:1057:20: error: incompatible function pointer types passing 'VALUE (get_categories_param *)' (aka 'unsigned long (struct _get_categories_param *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types] return rb_ensure(get_categories_internal, (VALUE)&param, ^~~~~~~~~~~~~~~~~~~~~~~ /Users/john.doe/.rbenv/versions/3.2.0/include/ruby-3.2.0/ruby/internal/iterator.h:425:25: note: passing argument to parameter 'b_proc' here VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2); ^ unicode.c:1058:20: error: incompatible function pointer types passing 'VALUE (WString *)' (aka 'unsigned long (struct _WString *)') to parameter of type 'VALUE (*)(VALUE)' (aka 'unsigned long (*)(unsigned long)') [-Wincompatible-function-pointer-types] get_categories_ensure, (VALUE)&wstr); ^~~~~~~~~~~~~~~~~~~~~ . . . 2 warnings and 6 errors generated. make: *** [unicode.o] Error 1 make failed, exit code 2 Gem files will remain installed in /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/unicode-0.4.4.4 for inspection. Results logged to /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/extensions/arm64-darwin-23/3.2.0/unicode-0.4.4.4/gem_make.out /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:102:in `run' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:51:in `block in make' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:43:in `each' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:43:in `make' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/ext_conf_builder.rb:42:in `build' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:170:in `build_extension' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:204:in `block in build_extensions' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:201:in `each' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/ext/builder.rb:201:in `build_extensions' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/site_ruby/3.2.0/rubygems/installer.rb:843:in `build_extensions' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/bundler-2.5.6/lib/bundler/rubygems_gem_installer.rb:76:in `build_extensions' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/bundler-2.5.6/lib/bundler/rubygems_gem_installer.rb:28:in `install' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/bundler-2.5.6/lib/bundler/source/rubygems.rb:205:in `install' /Users/john.doe/.rbenv/versions/3.2.0/lib/ruby/gems/3.2.0/gems/bundler-. . . An error occurred while installing unicode (0.4.4.4), and Bundler cannot continue.
已尝试操作
- 执行
xcode-select --install检查并安装Xcode命令行工具 - 使用asdf版本管理器排查rbenv可能存在的问题
解决方案
方案1:升级unicode gem版本
unicode 0.4.4.4是老旧版本,不兼容Ruby 3.2的API。修改项目Gemfile,将unicode的版本指定为1.4.0及以上(该版本已修复Ruby 3.x兼容问题):
# Gemfile中修改 gem 'unicode', '>= 1.4.0'
然后执行:
bundle update unicode bundle install
方案2:降级Ruby版本
如果无法升级gem,可将Ruby降级到2.7或3.0版本(这些版本与unicode 0.4.4.4兼容):
# 安装Ruby 2.7.8 rbenv install 2.7.8 # 设置当前项目使用该版本 rbenv local 2.7.8 # 重新安装依赖 bundle install
方案3:手动修复gem源码(不推荐)
若必须保留旧版unicode和Ruby 3.2,可手动修改gem的C源码:
- 找到gem安装目录:
gem which unicode,进入该目录下的ext/unicode文件夹 - 修改
unicode.c:- 对
rb_ensure调用的函数,添加强制类型转换,比如把get_categories_internal改为(VALUE (*)(VALUE))get_categories_internal - 删除或注释掉使用
OBJ_TAINTED和OBJ_TAINT的代码(Ruby 3.2已废弃taintedness机制,相关逻辑无实际作用)
- 对
- 重新编译安装:
make clean && make && make install
内容的提问来源于stack exchange,提问作者rxlqx22
相关产品推荐
相关产品推荐

