🐶

【Rails/Docker CE】CMake を Docker にインストールする【Gem::Ext::BuildError】

2023/12/20に公開

WSL docker CE(Ubuntu 22.04) で Rails 開発環境を構築しています。
ある gem を Gemfile に追記し、bundle install を実行したところ、Gem::Ext::BuildError: ERROR: Failed to build gem native extension.というエラーが発生してインストールを完了することができませんでした。
原因の調査と対応を残しておきます。

該当のエラーメッセージ

$ bundle install
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies...

-----中略-----

Fetching h3 3.7.2 <- 該当の gem
Installing h3 3.7.2 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native
extension. 

-----中略-----

cd src; cmake . -DBUILD_SHARED_LIBS=true -DBUILD_FILTERS=OFF
-DBUILD_BENCHMARKS=OFF; make
/bin/sh: 1: cmake: not found
make[1]: Entering directory
'/usr/local/bundle/gems/h3-3.7.2/ext/h3/src'
make[1]: *** No targets specified and no makefile found.  Stop.
make[1]: Leaving directory
'/usr/local/bundle/gems/h3-3.7.2/ext/h3/src'
make: *** [Makefile:2: make] Error 2

make failed, exit code 2

要約

  • 追加しようとした gem は、ネイティブ拡張を用いて C 言語や C++ などで作成されたライブラリを利用するものだった
  • 作成した環境に、それらをビルドするための CMake がインストールされていなかった
  • dockerfile に CMake をインストールするためのコマンドを追記し、再ビルドしたところ bundle install に成功した

経緯

  1. h3 という地理空間を扱うための gem の install を試みた
  2. bundle install に失敗し、冒頭のエラーメッセージに遭遇

Gem::Ext::BuildError: と cmake not found

冒頭のエラーメッセージの、Gem::Ext::BuildError: ERROR: Failed to build gem native extension. cmake: not found という部分に着目しました
前半で、ネイティブ拡張のビルドに失敗したこととその理由が、後半で、CMake がインストールされていないことによるものであるためであると類推することができます

実際に、h3_ruby のリポジトリを確認すると、README.md を確認すると C言語で構築されたライブラリに ffi を用いてアクセスしている旨が記されています。

This gem uses FFI to link directly into the H3 library (written in C).

https://github.com/seanhandley/h3_ruby?tab=readme-ov-file#getting-started

CMake を install する

開発環境に CMake を導入するために、dockerfile に追記を行いました
また、バージョンはこちらで確認しました

RUN apt-get update && \
    apt-get -y install build-essential && \
    apt-get install -y wget && \
    wget https://github.com/Kitware/CMake/releases/download/v3.28.1/cmake-3.28.1-linux-x86_64.sh -q -O /tmp/cmake-install.sh && \
    chmod u+x /tmp/cmake-install.sh && \
    mkdir /opt/cmake-3.28.1 && \
    /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-3.28.1 && \
    rm /tmp/cmake-install.sh && \
    ln -s /opt/cmake-3.28.1/bin/* usr/local/bin

再ビルドして bundle install

$ docker compose build --no-cache
$ docker compose up -d
$ docker compose exec [コンテナ] /bin/bash
$ bash: # bundle install
-> Bundle complete! xx Gemfile dependencies, xx gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

参考

https://github.com/Kitware/CMake/releases
https://www.softwarepronto.com/2022/09/dockerubuntu-installing-latest-cmake-on.html

Discussion