macOS上にplenvで導入したPerl環境へのNet::SSLeayのインストール

macOSでPerlを使おうとすると結構めんどい

macOSのバージョンが上がる度に苦労している気がしますが今回は大分苦労したのでメモ。

plenvでPerl 5.30.1を導入して、その上でcpanmを使ってNet::SSLeayをインストールしようとしたら失敗しまくりました。

そもそも、macOSはOpenSSLのライブラリはhomebrewでインストールしないといけないのですが、現在のCatalina環境でOpenSSLをインストールすると1.1系統が入り、しかしこれはNet::SSLeayのコンパイルに使えないっぽい? ちょっと調べが足りないかもしれないのですが1.0系統を導入して共存させる方法とかあるんでしょうか。

ちなみに、標準で使われているのはLibreSSLで、homebrewでインストールしたバージョンは1.1.1d。

% openssl version
LibreSSL 2.8.3
% brew info openssl
openssl@1.1: stable 1.1.1d (bottled) [keg-only]
Cryptography and SSL/TLS Toolkit
https://openssl.org/
/usr/local/Cellar/openssl@1.1/1.1.1d (7,983 files, 17.9MB)
  Poured from bottle on 2019-10-26 at 19:26:37
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/openssl@1.1.rb
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

and run
  /usr/local/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because openssl/libressl is provided by macOS so don't link an incompatible version.

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

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

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

==> Analytics
install: 492,916 (30 days), 1,756,066 (90 days), 2,537,136 (365 days)
install-on-request: 72,982 (30 days), 165,468 (90 days), 443,205 (365 days)
build-error: 0 (30 days)

素直にコンパイルしようとするとエラー

cpanmでインストールしようとしてもエラーが発生するため、ログファイルを覗くとld: library not found for -lsslという行があり、原因はライブラリが見つからないことというのは分かります。

LD_RUN_PATH="/usr/lib" cc  -mmacosx-version-min=10.15 -bundle -undefined dynamic _lookup -L/usr -L/usr/lib -L/usr/local/lib -fstack-protector-strong  SSLeay.o  -[K
[Ko blib/arch/auto/Net/SSLeay/SSLeay.bundle  \
           -L/usr -L/usr/lib -lssl -lcrypto -lz   \
          
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [blib/arch/auto/Net/SSLeay/SSLeay.bundle] Error 1

ここで、1.1のライブラリを指定してやると今度は別のエラーが出て失敗。

cc -c  -I/usr/local/opt/openssl@1.1/include -fno-common -DPERL_DARWIN -mmacosx-v ersion-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/loca l/include -DPERL_USE_SAFE_PUTENV -O3   -DVERSION=\"1.88\" -DXS_VERSION=\"1.88\"  "-I/Users/yuuichi/.plenv/versions/5.30.0/lib/perl5/5.30.0/darwin-2level/CORE"  SSLeay.c
SSLeay.xs:1890:28: warning: 'TLSv1_method' is deprecated [-Wdeprecated-declarati ons]
     RETVAL = SSL_CTX_new (TLSv1_method());
                           ^
:[K
[K/usr/local/opt/openssl@1.1/include/openssl/ssl.h:1877:1: note: 'TLSv1_method' has been explicitly marked deprecated here
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_method(void)) /* TLSv1.0 */
^
/usr/local/opt/openssl@1.1/include/openssl/opensslconf.h:155:34: note: expanded  from macro 'DEPRECATEDIN_1_1_0'
# define DEPRECATEDIN_1_1_0(f)   DECLARE_DEPRECATED(f)
                                 ^
/usr/local/opt/openssl@1.1/include/openssl/opensslconf.h:118:55: note: expanded  from macro 'DECLARE_DEPRECATED'
#   define DECLARE_DEPRECATED(f)    f __attribute__ (deprecated);
                                                      ^
SSLeay.xs:1899:28: warning: 'TLSv1_1_method' is deprecated [-Wdeprecated-declarations]
     RETVAL = SSL_CTX_new (TLSv1_1_method());
                           ^
/usr/local/opt/openssl@1.1/include/openssl/ssl.h:1883:1: note: 'TLSv1_1_method' has been explicitly marked deprecated here
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_method(void)) /* TLSv1.1 */
^
/usr/local/opt/openssl@1.1/include/openssl/opensslconf.h:155:34: note: expanded from macro 'DEPRECATEDIN_1_1_0'
# define DEPRECATEDIN_1_1_0(f)   DECLARE_DEPRECATED(f)
                                 ^

わりと本気でmacOS上で使うのを諦めかけましたが、もう少し悪あがきしてみました。

OpenSSL 1.0.2t をソースコードからインストール

OpenSSL 1.0系統の最新版である1.0.2tをソースコードからインストールして、そのライブラリを使ってコンパイルを試します。

% cd Downloads
% wget https://www.openssl.org/source/openssl-1.0.2t.tar.gz
% tar zxvf openssl-1.0.2t.tar.gz
% cd openssl-1.0.2t
% ./Configure darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp --o
penssldir=/usr/local/ssl/macos-x86_64
% make depend
% make test
% sudo make install

コンパイルオプションなどは、OpenSSLのWikiを参照しました。これで、OpenSSL 1.0.2tが、/usr/local/ssl/macos-x86_64以下にインストールされました。

Net::SSLeayをソースコードからインストール

% export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/ssl/macos-x86_64/lib/
% cd Net-SSLeay-1.88
% perl Makefile.PL
Do you want to run external tests?
These tests *will* *fail* if you do not have network connectivity. [n]
*** Found LibreSSL-2.8.3 installed in /usr
*** Be sure to use the same compiler and options to compile your OpenSSL, perl,
    and Net::SSLeay. Mixing and matching compilers is not supported.
Checking if your kit is complete...
Looks good
Writing Makefile for Net::SSLeay
Writing MYMETA.yml and MYMETA.json
% make
cp lib/Net/SSLeay/Handle.pm blib/lib/Net/SSLeay/Handle.pm
cp lib/Net/SSLeay.pod blib/lib/Net/SSLeay.pod
cp lib/Net/SSLeay.pm blib/lib/Net/SSLeay.pm
AutoSplitting blib/lib/Net/SSLeay.pm (blib/lib/auto/Net/SSLeay)
blib/lib/Net/SSLeay.pm: some names are not unique when truncated to 8 characters:
 directory blib/lib/auto/Net/SSLeay:
  do_https3.al, do_https2.al, do_https4.al, do_https.al truncate to do_https
  do_httpx3.al, do_httpx2.al, do_httpx4.al truncate to do_httpx
  get_https.al, get_https3.al, get_https4.al, get_http.al, get_http3.al, get_http4.al, get_httpx.al, get_httpx3.al, get_httpx4.al truncate to get_http
  head_https.al, head_https3.al, head_https4.al, head_http.al, head_http3.al, head_http4.al, head_httpx.al, head_httpx3.al, head_httpx4.al truncate to head_htt
  post_https.al, post_https3.al, post_https4.al, post_http.al, post_http3.al, post_http4.al, post_httpx.al, post_httpx3.al, post_httpx4.al truncate to post_htt
  put_https.al, put_https3.al, put_https4.al, put_http.al, put_http3.al, put_http4.al, put_httpx.al, put_httpx3.al, put_httpx4.al truncate to put_http
  ssl_read_all.al, ssl_read_until.al, ssl_read_CRLF.al truncate to ssl_read
  ssl_write_all.al, ssl_write_CRLF.al truncate to ssl_writ
  tcp_read_all.al, tcp_read_until.al, tcp_read_CRLF.al truncate to tcp_read
  tcp_write_all.al, tcp_write_CRLF.al truncate to tcp_writ
/Users/yuuichi/.plenv/shims/perl /System/Library/Perl/5.18/ExtUtils/xsubpp  -typemap /System/Library/Perl/5.18/ExtUtils/typemap -typemap typemap  SSLeay.xs > SSLeay.xsc && mv SSLeay.xsc SSLeay.c
cc -c   -g -pipe -fno-common -DPERL_DARWIN -fno-strict-aliasing -fstack-protector -Os   -DVERSION=\"1.88\" -DXS_VERSION=\"1.88\"  -iwithsysroot "/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE"   SSLeay.c
Running Mkbootstrap for Net::SSLeay ()
chmod 644 SSLeay.bs
rm -f blib/arch/auto/Net/SSLeay/SSLeay.bundle
LD_RUN_PATH="/usr/lib" cc  -bundle -undefined dynamic_lookup -fstack-protector SSLeay.o  -o blib/arch/auto/Net/SSLeay/SSLeay.bundle 	\
	   -L/usr -L/usr/lib -lssl -lcrypto -lz  	\

chmod 755 blib/arch/auto/Net/SSLeay/SSLeay.bundle
cp SSLeay.bs blib/arch/auto/Net/SSLeay/SSLeay.bs
chmod 644 blib/arch/auto/Net/SSLeay/SSLeay.bs
Manifying 2 pod documents
% cpanm Net::SSLeay

コンパイル問題なかったので、cpanmでplenvで構築したPerl環境にモジュールをインストールして、無事成功しました。

厄介なモジュールのインストールに成功したので、あとはサクサクと進められるかと思います。

Pyhtonとかも勉強中なので、そっちへの乗り換えを頑張って進めるというのも手ではありますが、まぁ、簡単なスクリプトは結構あるので使えるうちは使いますよ。