M1 Macbook ProでRubyGemsのeventmachineをインストールした際に吐かれたSSL関連のビルドエラーについて

仕事で8年ぶりくらいにRubyに触れる機会があり、M1 Macbook ProRailsの環境を構築中、RubyGemsのeventmachineをインストールしたらSSL関連のビルドエラーが生じたので、その問題解消までのメモを残しておく。

環境

  • M1 Macbook Pro (14インチ、2021)
  • macOS Monterey バージョン12.6
  • anyenv 1.1.5
  • rbenv 1.2.0-33-ga6cf6ae
  • Ruby 2.7.5
  • RubyGems 3.1.6
  • eventmachine 1.2.7

エラー内容

$ gem install eventmachine
Building native extensions. This could take a while...
ERROR:  Error installing eventmachine:
    ERROR: Failed to build gem native extension.

    current directory: /Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/eventmachine-1.2.7/ext
/Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/bin/ruby -I /Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib/ruby/2.7.0 -r ./siteconf20221021-64873-1gud8b.rb extconf.rb
checking for -lcrypto... no
checking for openssl/ssl.h... yes
checking for openssl/err.h... yes
checking for rb_trap_immediate in ruby.h,rubysig.h... no
checking for rb_thread_blocking_region()... no
checking for rb_thread_call_without_gvl() in ruby/thread.h... yes
checking for rb_thread_fd_select()... yes
checking for rb_fdset_t in ruby/intern.h... yes
checking for rb_wait_for_single_fd()... yes
checking for rb_enable_interrupt()... no
checking for rb_time_new()... yes
checking for inotify_init() in sys/inotify.h... no
checking for __NR_inotify_init in sys/syscall.h... no
checking for writev() in sys/uio.h... yes
checking for pipe2() in unistd.h... no
checking for accept4() in sys/socket.h... no
checking for SOCK_CLOEXEC in sys/socket.h... no
checking for sys/event.h... yes
checking for sys/queue.h... yes
checking for clock_gettime()... yes
checking for CLOCK_MONOTONIC_RAW in time.h... yes
checking for CLOCK_MONOTONIC in time.h... yes
CXXFLAGS=-g -O2 -Wall -Wextra -Wno-deprecated-declarations -Wno-ignored-qualifiers -Wno-unused-result -Wno-address
creating Makefile

current directory: /Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/eventmachine-1.2.7/ext
make "DESTDIR=" clean

current directory: /Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/eventmachine-1.2.7/ext
make "DESTDIR="
compiling binder.cpp
compiling cmain.cpp
compiling ed.cpp
compiling em.cpp
compiling kb.cpp
compiling page.cpp
compiling pipe.cpp
compiling rubymain.cpp
rubymain.cpp:220:3: warning: 'rb_rescue' is deprecated: Use of ANYARGS in this function is deprecated [-Wdeprecated-declarations]
                rb_rescue((VALUE (*)(ANYARGS))event_callback, (VALUE)&e, (VALUE (*)(ANYARGS))event_error_handler, Qnil);
                ^
/Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/include/ruby-2.7.0/ruby/backward/cxxanyargs.hpp:184:1: note: 'rb_rescue' has been explicitly marked deprecated here
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
^
/Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/include/ruby-2.7.0/arm64-darwin21/ruby/config.h:152:49: note: expanded from macro 'RUBY_CXX_DEPRECATED'
#define RUBY_CXX_DEPRECATED(msg) __attribute__((__deprecated__(msg)))
                                                ^
1 warning generated.
compiling ssl.cpp
linking shared-object rubyeventmachine.bundle
Undefined symbols for architecture arm64:
  "_BIO_ctrl", referenced from:
      t_get_peer_cert(unsigned long, unsigned long) in rubymain.o
      _ssl_verify_wrapper in ssl.o
      SslBox_t::CanGetCiphertext() in ssl.o
      SslBox_t::PutPlaintext(char const*, int) in ssl.o
  "_BIO_free", referenced from:
      t_get_peer_cert(unsigned long, unsigned long) in rubymain.o
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
      _ssl_verify_wrapper in ssl.o
  "_BIO_new", referenced from:
      t_get_peer_cert(unsigned long, unsigned long) in rubymain.o
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
      _ssl_verify_wrapper in ssl.o
  "_BIO_new_file", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_BIO_new_mem_buf", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_BIO_read", referenced from:
      SslBox_t::GetCiphertext(char*, int) in ssl.o
  "_BIO_s_mem", referenced from:
      t_get_peer_cert(unsigned long, unsigned long) in rubymain.o
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
      _ssl_verify_wrapper in ssl.o
  "_BIO_write", referenced from:
      _ssl_verify_wrapper in ssl.o
      SslBox_t::PutCiphertext(char const*, int) in ssl.o
  "_DH_free", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_EC_KEY_free", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_EC_KEY_new_by_curve_name", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_ERR_print_errors_fp", referenced from:
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
      SslBox_t::GetPlaintext(char*, int) in ssl.o
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) (.cold.2) in ssl.o
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) (.cold.3) in ssl.o
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) (.cold.4) in ssl.o
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) (.cold.5) in ssl.o
  "_EVP_PKEY_free", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
  "_OBJ_sn2nid", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_OPENSSL_init_crypto", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_OPENSSL_init_ssl", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_PEM_read_bio_DHparams", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_PEM_read_bio_PrivateKey", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_PEM_read_bio_X509", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_PEM_write_bio_X509", referenced from:
      t_get_peer_cert(unsigned long, unsigned long) in rubymain.o
      _ssl_verify_wrapper in ssl.o
  "_SSL_CIPHER_get_bits", referenced from:
      SslBox_t::GetCipherBits() in ssl.o
  "_SSL_CIPHER_get_name", referenced from:
      SslBox_t::GetCipherName() in ssl.o
  "_SSL_CIPHER_get_version", referenced from:
      SslBox_t::GetCipherProtocol() in ssl.o
  "_SSL_CTX_ctrl", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_free", referenced from:
      SslContext_t::~SslContext_t() in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
  "_SSL_CTX_new", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_set_cipher_list", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_set_options", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_set_session_id_context", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_use_PrivateKey", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_use_PrivateKey_file", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_use_certificate", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_CTX_use_certificate_chain_file", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_SSL_accept", referenced from:
      SslBox_t::GetPlaintext(char*, int) in ssl.o
  "_SSL_clear", referenced from:
      SslBox_t::~SslBox_t() in ssl.o
  "_SSL_connect", referenced from:
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
      SslBox_t::GetPlaintext(char*, int) in ssl.o
  "_SSL_ctrl", referenced from:
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
  "_SSL_free", referenced from:
      SslBox_t::~SslBox_t() in ssl.o
  "_SSL_get_current_cipher", referenced from:
      SslBox_t::GetCipherBits() in ssl.o
      SslBox_t::GetCipherName() in ssl.o
      SslBox_t::GetCipherProtocol() in ssl.o
  "_SSL_get_error", referenced from:
      SslBox_t::GetPlaintext(char*, int) in ssl.o
      SslBox_t::PutPlaintext(char const*, int) in ssl.o
  "_SSL_get_ex_data", referenced from:
      _ssl_verify_wrapper in ssl.o
  "_SSL_get_ex_data_X509_STORE_CTX_idx", referenced from:
      _ssl_verify_wrapper in ssl.o
  "_SSL_get_peer_certificate", referenced from:
      SslBox_t::GetPeerCert() in ssl.o
  "_SSL_get_servername", referenced from:
      SslBox_t::GetSNIHostname() in ssl.o
  "_SSL_get_shutdown", referenced from:
      SslBox_t::~SslBox_t() in ssl.o
  "_SSL_is_init_finished", referenced from:
      SslBox_t::GetPlaintext(char*, int) in ssl.o
      SslBox_t::PutPlaintext(char const*, int) in ssl.o
  "_SSL_new", referenced from:
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
  "_SSL_read", referenced from:
      SslBox_t::GetPlaintext(char*, int) in ssl.o
  "_SSL_set_bio", referenced from:
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
  "_SSL_set_ex_data", referenced from:
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
  "_SSL_set_verify", referenced from:
      SslBox_t::SslBox_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool, bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, unsigned long) in ssl.o
  "_SSL_shutdown", referenced from:
      SslBox_t::~SslBox_t() in ssl.o
  "_SSL_write", referenced from:
      SslBox_t::PutPlaintext(char const*, int) in ssl.o
  "_TLS_client_method", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_TLS_server_method", referenced from:
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
  "_X509_STORE_CTX_get_current_cert", referenced from:
      _ssl_verify_wrapper in ssl.o
  "_X509_STORE_CTX_get_ex_data", referenced from:
      _ssl_verify_wrapper in ssl.o
  "_X509_free", referenced from:
      t_get_peer_cert(unsigned long, unsigned long) in rubymain.o
      SslContext_t::SslContext_t(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
      SslContext_t::~SslContext_t() in ssl.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [rubyeventmachine.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/eventmachine-1.2.7 for inspection.
Results logged to /Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/extensions/arm64-darwin-21/2.7.0/eventmachine-1.2.7/gem_make.out

上記エラーメッセージから一部を抜粋すると、以下の様にssl.cppのコンパイルで落ちている事が分かる。

compiling ssl.cpp
linking shared-object rubyeventmachine.bundle
Undefined symbols for architecture arm64:

〜〜〜 中略 〜〜〜

ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [rubyeventmachine.bundle] Error 1

make failed, exit code 2

ここから、リンカがSSLライブラリを参照出来ていないのではないかと問題のあたりをつけて調べてみた。

調査

rbenvではRubyが依存しているOpenSSLを、Rubyのバージョン毎に個別にインストールしているのだが(昔はHomebrewのOpenSSLに依存していた)、自分の環境だとanyenvとrbenvを使っているので、バージョン2.7.5が依存しているOpenSSLは以下のディレクトリに入っている。

~/.anyenv/envs/rbenv/versions/2.7.5/openssl

そして、RubyGemsでインストールしたeventmachineのソースは、以下のディレクトリに保存される。

~/.anyenv/envs/rbenv/versions/2.7.5/lib/ruby/gems/2.7.0/gems/eventmachine-1.2.7/ext

この中にextconf.rbで生成されたMakefileが入っているので、定義されているリンカオプションを確認してみたのだが、LDFLAGSにopenssl/libのパスは見当たらなかった。

ldflags  = -L. -L/Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib  -fstack-protector-strong

これが原因ではないかと推察し、extconf.rbのコードから環境変数「PKG_CONFIG_PATH」が使える感じだったので、ビルド時にHomebrewでインストールしたOpenSSLのpcファイルを参照させてみる事に。

問題解消

MacではmacOS High Sierraから、OpenSSLのハートブリード問題を機に標準のSSLライブラリがLibreSSL(OpenSSL1.0.1からフォークされた)へと代わっており、これを書いている時点ではバージョン2.8.3がインストールされている。

$ openssl version
LibreSSL 2.8.3

しかし、Rubyが依存しているのはOpenSSLとなる為、まずはHomebrewを使ってOpenSSLをインストールする。

$ brew install openssl@1.1

ここでバージョン指定しないと現行の最新版であるバージョン3がインストールされるのだが、Ruby 2.7系はOpenSSLのバージョン3に対応していないので、バージョン1.1の方が必要となる。

インストールしたら、環境変数「PKG_CONFIG_PATH」にOpenSSL@1.1のpcファイルのパスを設定するのだが、brew info opsnssl@1.1コマンドを実行すると、以下の様に環境変数設定のコマンド実行例が出力される。

$ brew info openssl@1.1
==> openssl@1.1: stable 1.1.1q (bottled) [keg-only]
Cryptography and SSL/TLS Toolkit
https://openssl.org/
/opt/homebrew/Cellar/openssl@1.1/1.1.1q (8,097 files, 18MB)
  Poured from bottle on 2022-10-04 at 15:51:35
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openssl@1.1.rb
License: OpenSSL
==> Dependencies
Required: ca-certificates ✔
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /opt/homebrew/etc/openssl@1.1/certs

and run
  /opt/homebrew/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /opt/homebrew,
because macOS provides LibreSSL.

If you need to have openssl@1.1 first in your PATH, run:
  echo 'export PATH="/opt/homebrew/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/openssl@1.1/include"

For pkg-config to find openssl@1.1 you may need to set:
  export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@1.1/lib/pkgconfig"

==> Analytics
install: 712,643 (30 days), 2,287,873 (90 days), 11,108,325 (365 days)
install-on-request: 26,710 (30 days), 82,513 (90 days), 390,982 (365 days)
build-error: 1,533 (30 days)

上記メッセージの通りにコマンドを実行。

$ export PKG_CONFIG_PATH="/opt/homebrew/opt/openssl@1.1/lib/pkgconfig"

その上で、gem install eventmachineコマンドを再度実行してみると、今度は問題無くインストールが完了した。

改めて、生成されたMakefileに定義されるLDFLAGSを確認してみたところ、以下の様にopenssl/libのパスが追加されている事が分かる。

ldflags  = -L. -L/Users/heroween/.anyenv/envs/rbenv/versions/2.7.5/lib  -fstack-protector-strong -L/opt/homebrew/Cellar/openssl@1.1/1.1.1q/lib

という訳で、結論としては、やはりリンカがSSLライブラリを参照出来ていなかったというのが、ビルドエラーの根本原因だったと思われる。

おまけ

rbenvでは、Rubyインストール時のオプションによって、バンドルされたOpenSSLを使うのではなく、HomebrewのOpenSSLを使う事も可能となっている模様。

$ export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"

この環境変数を設定してrbenv installコマンドを実行した場合は、Rubyと一緒にOpenSSLはインストールされなくなり、最初からHomebrewのOpenSSLに依存する様になる。

この形でインストールしていれば、今回のビルドエラーを回避出来たかもしれないのだが、取り敢えず問題は解消しているので、その検証自体はまた後日にでもやろうと思う。