Ruby 2.8.0-devビルドのためclangを更新した

TL;DR としては手元の macOS の clang のバージョン更新を怠っていたので、Ruby の head (2.8.0-dev) でコンパイルエラーが起きていた。久しぶりの Ruby 2.8.0-dev でコンパイルエラーが出たら clang を更新してみましょう。

以下ログ込みで記しておく。 Ruby 2.8.0-dev に話題の Endless method definition が入ったこともあり、一昨日あたりに数日ぶりのアップデートをしたら rbenv install 2.8.0-devコンパイルエラーが起きるようになっていたので、ruby/rubyリポジトリで再現するか見たところ期待どおり同様のエラーになった。

% cd path/to/ruby/ruby
% make distclean
(snip)

% make check
        BASERUBY = echo executable host ruby is required.  use --with-baseruby option.; false
        CC = clang -fdeclspec
        LD = ld
        LDSHARED = clang -fdeclspec -dynamiclib
        CFLAGS = -O3 -ggdb3 -Wall -Wextra -Werror=deprecated-declarations -Werror=division-by-zero -Werror=implicit-function-declaration -Werror=implicit-int -Werror=pointer-arith -Werror=shorten-64-to-32 -Werror=write-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Werror=extra-tokens -std=gnu99  -pipe
        XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fno-strict-overflow -DRUBY_DEVEL=1 -fvisibility=hidden -DRUBY_EXPORT -fPIE -DCANONICALIZATION_FOR_MATHN -I. -I.ext/include/x86_64-darwin17 -I./include -I. -I./enc/unicode/12.1.0
        CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT
        DLDFLAGS = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -fstack-protector-strong -Wl,-pie -framework Security -framework Foundation
        SOLIBS = -lpthread -lgmp -ldl -lobjc
        LANG = ja_JP.UTF-8
        LC_ALL =
        LC_CTYPE = ja_JP.UTF-8
        MFLAGS =
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
compiling ./main.c
In file included from ./main.c:21:
In file included from ./include/ruby.h:33:
In file included from ./include/ruby/ruby.h:46:
./include/ruby/3/scan_args.h:264:47: error: use of undeclared identifier 'fmt'; did you mean 'fma'?
    RUBY3_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) <  0,    "bad scan arg format",                    "error")
                                              ^~~
                                              fma
./include/ruby/3/scan_args.h:102:57: note: expanded from macro 'rb_scan_args_count'
#define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0)
                                                        ^
./include/ruby/3/scan_args.h:98:29: note: expanded from macro 'rb_scan_args_count_lead'
    (!rb_scan_args_isdigit((fmt)[ofs]) ? \
                            ^
./include/ruby/3/scan_args.h:67:62: note: expanded from macro 'rb_scan_args_isdigit'
#define rb_scan_args_isdigit(c) (RUBY3_CAST((unsigned char)((c)-'0'))<10)
                                                             ^
./include/ruby/3/cast.h:31:28: note: expanded from macro 'RUBY3_CAST'
# define RUBY3_CAST(expr) (expr)
                           ^
./include/ruby/3/attr/diagnose_if.h:34:36: note: expanded from macro 'RUBY3_ATTR_DIAGNOSE_IF'
    __attribute__((__diagnose_if__(_, __, ___))) \
                                   ^
/usr/include/math.h:554:15: note: 'fma' declared here
extern double fma(double, double, double);
              ^
In file included from ./main.c:21:
In file included from ./include/ruby.h:33:
In file included from ./include/ruby/ruby.h:46:
./include/ruby/3/scan_args.h:264:28: error: subscript of pointer to function type 'double (double, double, double)'
    RUBY3_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) <  0,    "bad scan arg format",                    "error")
    ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./include/ruby/3/scan_args.h:102:33: note: expanded from macro 'rb_scan_args_count'
#define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0)
                                ^
./include/ruby/3/scan_args.h:98:28: note: expanded from macro 'rb_scan_args_count_lead'
    (!rb_scan_args_isdigit((fmt)[ofs]) ? \
                           ^
./include/ruby/3/scan_args.h:67:62: note: expanded from macro 'rb_scan_args_isdigit'
#define rb_scan_args_isdigit(c) (RUBY3_CAST((unsigned char)((c)-'0'))<10)
                                                             ^

(snip)
./include/ruby/3/scan_args.h:102:57: note: expanded from macro 'rb_scan_args_count'
#define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0)
                                                        ^
./include/ruby/3/scan_args.h:99:29: note: expanded from macro 'rb_scan_args_count_lead'
     rb_scan_args_count_var(fmt, ofs, vari) : \
                            ^
./include/ruby/3/scan_args.h:89:31: note: expanded from macro 'rb_scan_args_count_var'
     rb_scan_args_count_trail(fmt, ofs, vari) : \
                              ^
note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
./include/ruby/3/scan_args.h:75:29: note: expanded from macro 'rb_scan_args_count_block'
     rb_scan_args_count_end(fmt, (ofs)+1, (vari)+1))
                            ^
./include/ruby/3/scan_args.h:70:7: note: expanded from macro 'rb_scan_args_count_end'
    ((fmt)[ofs] ? -1 : (vari))
      ^
./include/ruby/3/attr/diagnose_if.h:34:36: note: expanded from macro 'RUBY3_ATTR_DIAGNOSE_IF'
    __attribute__((__diagnose_if__(_, __, ___))) \
                                   ^
/usr/include/math.h:554:15: note: 'fma' declared here
extern double fma(double, double, double);
              ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [main.o] Error 1

自分の環境のことなので、clang のバージョンが古かろうと見てみたところ version 9.0.0 だった。

% clang --version
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

LLVM を更新する。

% brew upgrade llvm
(snip)

==> llvm
To use the bundled libc++ please add the following LDFLAGS:
  LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"

llvm is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have llvm first in your PATH run:
  echo 'export PATH="/usr/local/opt/llvm/bin:$PATH"' >> ~/.zshrc

For compilers to find llvm you may need to set:
  export LDFLAGS="-L/usr/local/opt/llvm/lib"
  export CPPFLAGS="-I/usr/local/opt/llvm/include"

clang のバージョンが 10.0.0 になる。

% clang --version
clang version 10.0.0
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin

rbenv install 2.8.0-dev でふたたびインストール可能になった。

% ruby -v
ruby 2.8.0dev (2020-04-12T05:58:13Z master a07cbacd23) [x86_64-darwin17]

話題の Endless method definition を動かすとこんな感じ。

% ruby -e 'def greet(name) = puts("Hello, #{name}!"); greet("John Smith")'
Hello, John Smith!

ついでに右代入してみる。

% ruby -e '1 + 1 => x; puts x'
2

Enjoy!