読者です 読者をやめる 読者になる 読者になる

non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

Windowsでmruby-http2を動かした

こんにちは、kindle fireYouTubeで車モノ(knight riderやワイルドスピード)の映像を中毒患者の様に見まくる長男からタブレットを修理に出したといって、隔離してしばらくたち、今のところ、長男は隙を見て奥さんがおもに使っているChromebookYouTubeを見ています。kjunichiです。

mruby-http2 for win32

Xeonで昨年末久々にPC組んだ流れで、Windowsでの開発環境をあれこれ試している。 そんな中、今回はmrubyでhttp2をしゃべることが可能になるmrbgemのmruby-http2をWindowsで動かしてみた。

事前に必要なモノ

  • openssl
  • libevent
  • nghttp2
  • zlib

zlib以外は、

- Windows 10でMSVCでnghttp2のサンプルを動かす - non vorrei lavorare

の記事に少し書いてます。

ヘッダ無い問題

以下に挙げるヘッダがWindowsでは用意されていない模様。

  • pwd.h
  • unistd.h
  • sys/socket.h
  • sys/wait.h
  • sys/resource.h
  • sys/queue.h
  • netdb.h
  • netinet/in.h
  • netinet/tcp.h
  • poll.h
  • signal.h
  • pthread.h
  • err.h

定数無い問題

mruby-http2をWindowsでビルドする際、以下の定数が未定義でエラーとなった。

  • F_GETFL
  • O_NONBLOCK
  • SHUT_WR

型や構造体無い問題

mruby-http2をWindowsでビルドする際、以下の型が未定義でエラーとなった。

  • ssize_t
  • uid_t
  • nfds_t
  • struct pollfd

関数無い問題

mruby-http2をWindowsでビルドする際、以下の関数が未定義でエラーとなった。

  • pipe
  • fcntl
  • alloca
  • gmtime_r
  • fork
  • TAILQ_FOREACH
  • kill
  • daemon

pipe

_pipeなる関数が用意されており、これを用いることで対応出来た。 ただし、引数がUNIXのpipeと異なり3つ必要。

#ifndef _WIN32
  rv = pipe(pipefd);
  #else
  rv = _pipe(pipefd, 65535, _O_BINARY);
#endif

作成するパイプのバッファサイズの指定は決め打ちで暫定的に対処した。

fcntl

mruby-http2ではfcntlでソケットをノンブロッキング指定にする為に用いられていた。 Windowsではこのような用途にはioctlsocketを用いることで対応出来た。

#ifndef _WIN32
  while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
    ;
  if (flags == -1) {
    mrb_raisef(mrb, E_RUNTIME_ERROR, "fcntl: %S", mrb_str_new_cstr(mrb, strerror(errno)));
  }
  while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
    ;
  if (rv == -1) {
    mrb_raisef(mrb, E_RUNTIME_ERROR, "fcntl: %S", mrb_str_new_cstr(mrb, strerror(errno)));
  }
  #else
  flags = 1;
  rv = ioctlsocket(fd, FIONBIO, &flags);
  if (rv != NO_ERROR) {
    mrb_raisef(mrb, E_RUNTIME_ERROR, "ioctlsocket: %S", mrb_str_new_cstr(mrb, "error")); // TODO
  }
#endif

シグナルがWindowsでないと勘違いしてた問題

シグナル周りは一旦全部コメントアウトして無視することにして対応した。

  • struct sigaction
  • sigaction

関数自体を無効にしたものたち

単純にWindowsで動かすにには不要な機能はスパッと諦めて作業した。 その結果、以下の関数は、戻るだけだったり、固定値を返すだけにしたり、関数そのものをコメントアウトした。

  • mrb_http2_get_uid
  • mrb_http2_config_get_worker
  • tune_rlimit

成果物

mrubyのbuild_config.rbに以下を記述することでwindowsでビルド可能なmruby-http2が利用できるハズ。

conf.gem :github => 'kjunichi/mruby-http2', :branch => 'support-for-win32'

まとめ

クライアントは、これらの問題を解決することで、動かせた。 サーバー側は、さらに対応が必要だった。これはまた、別の記事にするつもり。

ちなみに、mruby-cliバイナリを作る場合は、今回のMSVCの対応とは別にmingw-w64での対応が必要となる。 もし、dockerを使わず直接Windows上でmruby-cliでワンバイナリをMSVCで作製すれば、今回のmrbgemが使えるかもしれません。

関連記事