(HTTP2+HTTP3)対応cURLを自前ビルドしてpythonから使う その1

pipでpycurlのインストールを試みたら、いろいろと足りないものがあったりしたので自前でビルドしました。

目標

  • HTTP/2が使える
  • HTTP/3が使える
  • virtualenvで使うのでホスト環境はできるだけ汚さない

レシピ

参考にしたサイト

nghttp2 - HTTP/2 C Library

HTTP3 (and QUIC)

準備

まずは環境の確認から。

$ uname -a
Linux plain 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
$ python3 -V
Python 3.10.6

必要となるものをインストールしておきます。

$ sudo apt install build-essential autoconf automake libtool pkg-config
$ sudo apt install python3-dev python3-venv

インストール先のvirtualenvを作ります。

$ mkdir develop
$ python3 -m venv --prompt develop develop/.venv
$ cd develop/
$ ln -s .venv/bin/
$ source bin/activate
(develop) $ mkdir build

以下、virtualenv環境下のプロンプトは(develop) $で表します。

必要なライブラリのビルド

どんどんビルドしていきましょう。 ポイントはconfigure時の設定です。

  1. --prefixオプションで$VIRTUAL_ENVをインストール先にする
  2. LDFLAGSを設定してライブラリの検索先に$VIRTUAL_ENV/libを追加する

zlib

(develop) $ cd build
(develop) $ git clone https://github.com/madler/zlib.git
(develop) $ cd zlib
(develop) $ ./configure --prefix=$VIRTUAL_ENV
(develop) $ make test
(develop) $ make install
(develop) $ cd ..

OpenSSL (QUICパッチ入り)

(develop) $ git clone --depth 1 -b openssl-3.0.0+quic https://github.com/quictls/openssl
(develop) $ cd openssl
(develop) $ LDFLAGS="-Wl,-rpath,$VIRTUAL_ENV/lib" \
./config enable-tls1_3 --prefix=$VIRTUAL_ENV \
  --with-zlib-include=$VIRTUAL_ENV/include \
  --with-zlib-lib=$VIRTUAL_ENV/lib
(develop) $ make
(develop) $ make install_sw install_ssldirs
(develop) $ cd ..

nghttp2

(develop) $ git clone https://github.com/nghttp2/nghttp2.git
(develop) $ cd nghttp2
(develop) $ autoreconf -fi
(develop) $ ./configure --prefix=$VIRTUAL_ENV --enable-lib-only
(develop) $ make
(develop) $ make install
(develop) $ cd ..

nghttp3

(develop) $ git clone https://github.com/ngtcp2/nghttp3
(develop) $ cd nghttp3
(develop) $ autoreconf -fi
(develop) $ ./configure --prefix=$VIRTUAL_ENV --enable-lib-only
(develop) $ make
(develop) $ make install
(develop) $ cd ..

ngtcp2

(develop) $ git clone https://github.com/ngtcp2/ngtcp2
(develop) $ cd ngtcp2
(develop) $ autoreconf -fi
(develop) $ LDFLAGS="-Wl,-rpath,$VIRTUAL_ENV/lib" \
  ./configure \
  PKG_CONFIG_PATH=$VIRTUAL_ENV/lib/pkgconfig \
  --prefix=$VIRTUAL_ENV \
  --with-openssl \
  --enable-lib-only
(develop) $ make
(develop) $ make install
(develop) $ cd ..

curl

(develop) $ git clone https://github.com/curl/curl
(develop) $ cd curl
(develop) $ autoreconf -fi
(develop) $ LDFLAGS="-Wl,-rpath,$VIRTUAL_ENV/lib" ./configure \
  --prefix=$VIRTUAL_ENV \
  --with-zlib=$VIRTUAL_ENV \
  --with-openssl=$VIRTUAL_ENV \
  --with-nghttp2=$VIRTUAL_ENV \
  --with-nghttp3=$VIRTUAL_ENV \
  --with-ngtcp2=$VIRTUAL_ENV
(develop) $ make
(develop) $ make install
(develop) $ cd ..

ちなみにcurlのconfigure結果はこのようになっていました。

zlib HTTP1 HTTP2 HTTP3が有効になっていることが確認できます。

configure: Configured to build curl/libcurl:

  Host setup:       x86_64-pc-linux-gnu
  Install prefix:   /home/yuzu/develop/.venv
  Compiler:         gcc
   CFLAGS:          -Werror-implicit-function-declaration -O2 -Wno-system-headers
   CPPFLAGS:        -isystem /home/yuzu/develop/.venv/include -isystem /home/yuzu/develop/.venv/include -DOPENSSL_SUPPRESS_DEPRECATED -isystem /home/yuzu/develop/.venv/include -isystem /home/yuzu/develop/.venv/include -isystem /home/yuzu/develop/.venv/include -isystem /home/yuzu/develop/.venv/include
   LDFLAGS:         -Wl,-rpath,/home/yuzu/develop/.venv/lib -L/home/yuzu/develop/.venv/lib -L/home/yuzu/develop/.venv/lib64
   LIBS:            -lnghttp3 -lngtcp2_crypto_openssl -lngtcp2 -lnghttp2 -lssl -lcrypto -lssl -lcrypto -lz

  curl version:     7.87.1-DEV
  SSL:              enabled (OpenSSL v3+)
  SSH:              no      (--with-{libssh,libssh2})
  zlib:             enabled
  brotli:           no      (--with-brotli)
  zstd:             no      (--with-zstd)
  GSS-API:          no      (--with-gssapi)
  GSASL:            no      (libgsasl not found)
  TLS-SRP:          enabled
  resolver:         POSIX threaded
  IPv6:             enabled
  Unix sockets:     enabled
  IDN:              no      (--with-{libidn2,winidn})
  Build libcurl:    Shared=yes, Static=yes
  Built-in manual:  enabled
  --libcurl option: enabled (--disable-libcurl-option)
  Verbose errors:   enabled (--disable-verbose)
  Code coverage:    disabled
  SSPI:             no      (--enable-sspi)
  ca cert bundle:   /etc/ssl/certs/ca-certificates.crt
  ca cert path:     no
  ca fallback:      no
  LDAP:             no      (--enable-ldap / --with-ldap-lib / --with-lber-lib)
  LDAPS:            no      (--enable-ldaps)
  RTSP:             enabled
  RTMP:             no      (--with-librtmp)
  PSL:              no      (libpsl not found)
  Alt-svc:          enabled (--disable-alt-svc)
  Headers API:      enabled (--disable-headers-api)
  HSTS:             enabled (--disable-hsts)
  HTTP1:            enabled (internal)
  HTTP2:            enabled (nghttp2)
  HTTP3:            enabled (ngtcp2 + nghttp3)
  ECH:              no      (--enable-ech)
  WebSockets:       no      (--enable-websockets)
  Protocols:        DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS MQTT POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP
  Features:         AsynchDNS HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Largefile NTLM NTLM_WB SSL TLS-SRP UnixSockets alt-svc libz threadsafe

  WARNING:  HTTP3 enabled but marked EXPERIMENTAL. Use with caution!

→その2へつづく