Monterey系统下semacode-ruby19 gem安装失败的解决与替代方案咨询
问题描述
在Mac OS X 10.13.6系统上用Ruby 3.1.0、Rails 7.0.3创建的Rails应用,通过Bundler 2.3.3可正常打包所有依赖gem。迁移至Mac OS X 12.3(Monterey)系统并使用相同版本Bundler时,出现以下错误:
An error occurred while installing semacode-ruby19 (0.7.4), and Bundler cannot continue.
注释该gem后可完成安装,但应用功能不完整,例如需注释test/test_helper.rb中Barby::DataMatrix.new(...)相关测试代码。
该gem已长期未更新,但仍需实现Ruby的DataMatrix编码功能,目前有哪些可行方案?另外不确定问题根源是OS X还是Homebrew,不知该向何处反馈,求建议。
更新
按建议手动安装gem仍失败,执行命令:
gem install semacode -v 0.7.4 -- --with-cflags="-Wno-error=implicit-function-declaration"
得到错误输出:
Fetching semacode-0.7.4.gem Building native extensions with: '--with-cflags=-Wno-error=implicit-function-declaration' This could take a while... ERROR: Error installing semacode: ERROR: Failed to build gem native extension. current directory: /Users/deploy/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/semacode-0.7.4/ext /Users/deploy/.rbenv/versions/3.1.0/bin/ruby -I /Users/deploy/.rbenv/versions/3.1.0/lib/ruby/3.1.0 -r ./siteconf20220830-40292-dndt8s.rb extconf.rb --with-cflags\=-Wno-error\=implicit-function-declaration creating Makefile current directory: /Users/deploy/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/semacode-0.7.4/ext make DESTDIR\= clean current directory: /Users/deploy/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/semacode-0.7.4/ext make DESTDIR\= compiling iec16022ecc200.c iec16022ecc200.c:284:80: warning: data argument not used by format string [-Wformat-extra-args] rb_raise(rb_eArgError, \"cannot encode character in X12\", c); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ iec16022ecc200.c:299:80: warning: data argument not used by format string [-Wformat-extra-args] rb_raise(rb_eArgError, \"cannot encode character in X12\", c); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ iec16022ecc200.c:323:89: warning: data argument not used by format string [-Wformat-extra-args] rb_raise(rb_eRuntimeError, \"this should not be happening!\", c); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ iec16022ecc200.c:498:9: warning: incompatible pointer to integer conversion initializing 'VALUE' (aka 'unsigned long') with an expression of type 'void *' [-Wint-conversion] VALUE rb_str = NULL; ^ ~~~~ iec16022ecc200.c:908:12: warning: assigning to 'unsigned char *' from 'char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not [-Wpointer-sign] grid = ALLOC_N(char, W * H); ^ ~~~~~~~~~~~~~~~~~~~~ 5 warnings generated. compiling reedsol.c compiling semacode.c semacode.c:61:3: warning: implicit declaration of function 'iec16022init' is invalid in C99 [-Wimplicit-function-declaration] iec16022init(&semacode->width, &semacode->height, message); ^ semacode.c:96:28: warning: 'bzero' call operates on objects of type 'semacode_t' (aka 'struct semacode_t') while the size is based on a different type 'semacode_t *' (aka 'struct semacode_t *') [-Wsizeof-pointer-memaccess] bzero(semacode, sizeof(semacode)); ~~~~~~~~ ^~~~~~~~ semacode.c:96:28: note: did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)? bzero(semacode, sizeof(semacode)); ^~~~~~~~ semacode.c:129:27: error: no member named 'len' in 'struct RString' encode_string(semacode, StringValueLen(message), StringValuePtr(message)); ^~~~~~~~~~~~~~~~~~~~~~~ ./semacode.h:26:56: note: expanded from macro 'StringValueLen' #define StringValueLen(s) RSTRING(RB_STRING_VALUE(s))->len ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ semacode.c:239:20: warning: equality comparison result unused [-Wunused-comparison] semacode->data == NULL; ~~~~~~~~~~~~~~~^~~~~~~ semacode.c:239:20: note: use '=' to turn this equality comparison into an assignment semacode->data == NULL; ^~ = semacode.c:243:44: error: no member named 'len' in 'struct RString' DATA_PTR(self) = encode_string(semacode, StringValueLen(message), StringValuePtr(message)); ^~~~~~~~~~~~~~~~~~~~~~~ ./semacode.h:26:56: note: expanded from macro 'StringValueLen' #define StringValueLen(s) RSTRING(RB_STRING_VALUE(s))->len ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ 3 warnings and 2 errors generated. make: *** [semacode.o] Error 1 make failed, exit code 2 Gem files will remain installed in /Users/deploy/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/semacode-0.7.4 for inspection. Results logged to /Users/deploy/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/extensions/arm64-darwin-21/3.1.0/semacode-0.7.4/gem_make.out
可行方案
方案一:替换为维护活跃的DataMatrix编码gem
放弃semacode-ruby19,改用以下维护状态良好的gem:
barby:代码中已用到Barby::DataMatrix,可单独使用barby的DataMatrix功能,无需依赖semacode,其维护状态远优于semacode,且兼容当前Ruby和OS版本。data_matrix:专门的DataMatrix编码gem,可直接替代semacode的功能。
方案二:修复semacode的本地扩展代码
从错误日志看,核心问题是Ruby 3.x的C API变化,struct RString不再直接暴露len成员,需用RSTRING_LEN()宏替代。具体修改步骤:
- 下载semacode-0.7.4源码并解压到本地。
- 修改
ext/semacode.h中的StringValueLen宏:#define StringValueLen(s) RSTRING_LEN(RB_STRING_VALUE(s)) - 修复其他问题:比如
semacode.c中bzero调用错误,需改为sizeof(*semacode);补充iec16022init的函数原型声明。 - 本地编译安装修改后的gem:执行
gem build semacode.gemspec生成gem包,再用gem install semacode-0.7.4.gem安装。 - 在Gemfile中指定本地gem路径,或上传到私有gem源供项目使用。
方案三:用Docker容器运行应用
若不想修改代码或gem,可构建基于旧版Mac OS或Linux的Docker容器,在容器内运行应用,避开Monterey系统的编译兼容性问题。
问题反馈建议
- 问题根源:从错误日志判断,是semacode的C扩展代码不兼容Ruby 3.x的API和Monterey的Clang编译器,与Homebrew关系不大,核心是gem本身过时。
- 反馈渠道:
- 若想反馈gem兼容性问题,可在semacode的代码仓库提交issue,但因gem长期未更新,大概率不会得到响应。
- 若怀疑是OS X系统问题,可在Apple开发者论坛提问,但更可能是gem适配问题而非系统问题。
- 也可在Ruby社区发帖求助,分享编译错误信息,寻求其他开发者的修复经验。
内容的提问来源于stack exchange,提问作者Jerome
相关产品推荐
相关产品推荐

