CUBE SUGAR CONTAINER

技術系のこと書きます。

ソースコードから Python をインストールするときにビルドされないモジュールを確認する

ソースコードから Python をインストールするとき、環境によってはビルドされないモジュールが出てくる。 今回は、どんなモジュールがビルドされなかったかを確認する方法について。 先に結論から書くと、ビルドされなかったモジュールがあるときはログにメッセージが残る。

使った環境は次の通り。

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.1 LTS"
$ uname -r
4.15.0-20-generic

下準備

まずは、あえてビルドされないモジュールが出るように環境を整える。 最低限のビルドだけはできるように build-essential パッケージだけインストールしておこう。

$ sudo apt-get -y install build-essential

もちろん使う環境によるけど、これだと結構なモジュールがビルドされないはず。

続いて Python のソースコードを取得する。

$ wget -O - https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgz | tar zxvf -
$ cd Python-3.6.6

Python をビルドする

あとは ./configuremake を使って Python をビルドする。

$ ./configure
$ make 2>&1 | tee make.log

上記で、ちゃんとビルドのログを残しておくのがポイント。

すると、ビルドしたディレクトリに Python のインタプリタが作られる。

$ file python
python: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=27b252471eb5f2c16941f992d26f2e13ec5e3ada, with debug_info, not stripped

実行すると、ちゃんと動く。

$ ./python -c "print('Hello, World')"
Hello, World

ただし、上記だとおそらくビルドされないモジュールがある。 具体的には、ビルドログを以下の文字列で検索をかければ分かる。

$ grep -A 3 "The necessary bits to build these optional modules were not found:" make.log 
The necessary bits to build these optional modules were not found:
_bz2                  _curses               _curses_panel      
_dbm                  _gdbm                 _lzma              
_sqlite3              _tkinter

色々と出てきた。

例えば _sqlite3 という文字列が見えるので sqlite3 パッケージをインポートしてみよう。

$ ./python -c "import sqlite3"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/vagrant/Python-3.6.6/Lib/sqlite3/__init__.py", line 23, in <module>
    from sqlite3.dbapi2 import *
  File "/home/vagrant/Python-3.6.6/Lib/sqlite3/dbapi2.py", line 27, in <module>
    from _sqlite3 import *
ModuleNotFoundError: No module named '_sqlite3'

想定通りではあるけど ModuleNotFoundError というエラーになってしまった。

もちろん、上記のインポートはディストリビューションにデフォルトで入っている Python ならちゃんと動く。

$ which python3
/usr/bin/python3
$ python3 -c "import sqlite3"

つまりビルドした環境に色々とパッケージが足りていない。

ビルドされないモジュールを無くす

ここからは、先ほどビルドされなかったモジュールが、ちゃんとビルドされるように直していこう。 例えば Python のインストールマネージャの pyenv では、各環境用に必要なパッケージを示している。

github.com

ここに記載されているコマンドを、そのまま実行してみよう。

$ sudo apt-get install make build-essential libssl-dev zlib1g-dev libbz2-dev \
  libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
  xz-utils tk-dev libffi-dev liblzma-dev

インストールできたら、再度 Python をビルドする。

$ ./configure && make 2>&1 | tee make.log

もう一度ログを確認すると、ほとんどのモジュールはビルドできたようだ。 ただ、ごく一部に関してはまだ残っている。

$ grep -A 3 "The necessary bits to build these optional modules were not found:" make.log 
The necessary bits to build these optional modules were not found:
_dbm                  _gdbm                                    
To find the necessary bits, look in setup.py in detect_modules() for the module's name.

該当するモジュールに必要なパッケージをインストールして再度チャレンジする。

$ sudo apt-get install libgdbm-dev libdb-dev
$ ./configure && make 2>&1 | tee make.log

ログを確認すると、今度は grep に何も引っかからなくなった。

$ grep -A 3 "The necessary bits to build these optional modules were not found:" make.log 

先ほどエラーになったインポートなどを試しても、今度は問題なく動いている。

$ ./python -c "import sqlite3"
$ ./python -c "import dbm"
$ ./python -c "from dbm import gnu"

ばっちり。

pyenv を使う場合

ちなみに pyenv を使って Python をインストールする場合にも同じ問題が起こる恐れがある。 そのときはインストールするときに -v オプションをつけてビルドログを残しておこう。

$ pyenv install 3.6.6 -v 2>&1 | tee make.log

あとは同じ要領でビルドされなかったモジュールを確認できる。

めでたしめでたし。