PyGreSQLをソースコードからビルド

PyGreSQLは、PythonからPostgreSQLにアクセスできる、BSDライクなライセンスのライブラリです。
[公式マニュアルにある手順](http://www.pygresql.org/contents/install.html)に従って、PyGreSQLをソースコードからビルドしてみました。

動作確認はmacOS 10.13.3、Python3.5.2、PostgreSQL 9.4.6で行いました。

# ビルド要件

ビルドするには、以下がインストールされている必要があるとのことです。

* Pythonヘッダーファイル
* PostgreSQL クライアント・サーバーヘッダーファイル

通常、これらは"devel"パッケージに含まれているとのこと。

precompiled PostgreSQLを利用している場合は、 pg_configツールも必要で、これも通常、 "devel"パッケージに含まれるとのことです。

# ビルドしてみる

PyGreSQLをダウンロード、解凍します。

```sh
$ wget http://pygresql.org/files/PyGreSQL.tar.gz
$ tar xvf PyGreSQL.tar.gz
```

DistUtilsを使ってビルドできるとのことなので、してみましょう。

ビルド前のディレクトリ構成はこんな感じ。

```sh
$ cd PyGreSQL-5.0.4
$ ls -l
total 672
-rw-r--r--@  1 hz  staff    1290  7 23  2017 LICENSE.txt
-rw-r--r--@  1 hz  staff     556  7 23  2017 MANIFEST.in
-rw-r--r--@  1 hz  staff    1362  7 23  2017 PKG-INFO
drwxr-xr-x@  7 hz  staff     224  7 23  2017 PyGreSQL.egg-info
-rw-r--r--@  1 hz  staff     859  7 23  2017 README.rst
drwxr-xr-x@ 15 hz  staff     480  7 23  2017 docs
-rw-r--r--@  1 hz  staff   96135  7 23  2017 pg.py
-rw-r--r--@  1 hz  staff   61267  7 23  2017 pgdb.py
-rw-r--r--@  1 hz  staff  145938  7 23  2017 pgmodule.c
-rw-r--r--@  1 hz  staff    3063  7 23  2017 pgtypes.h
-rw-r--r--@  1 hz  staff    3974  7 23  2017 py3c.h
-rw-r--r--@  1 hz  staff     165  7 23  2017 setup.cfg
-rwxr-xr-x@  1 hz  staff    8026  7 23  2017 setup.py
drwxr-xr-x@ 13 hz  staff     416  7 23  2017 tests
```

ビルドします。

```sh
$ python setup.py build
running build
running build_py
creating build
creating build/lib.macosx-10.6-x86_64-3.5
copying pg.py -> build/lib.macosx-10.6-x86_64-3.5
copying pgdb.py -> build/lib.macosx-10.6-x86_64-3.5
running build_ext
building '_pg' extension
creating build/temp.macosx-10.6-x86_64-3.5
/usr/bin/clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/hz/.pyenv/versions/anaconda3-4.2.0/include -arch x86_64 -DPYGRESQL_VERSION=5.0.4 -DDIRECT_ACCESS -DLARGE_OBJECTS -DDEFAULT_VARS -DESCAPING_FUNCS -I/Users/hz/.pyenv/versions/anaconda3-4.2.0/include/python3.5m -I/usr/local/pgsql/include -I/Users/hz/.pyenv/versions/anaconda3-4.2.0/include/python3.5m -c pgmodule.c -o build/temp.macosx-10.6-x86_64-3.5/pgmodule.o -O2 -funsigned-char -Wall -Werror
/usr/bin/clang -bundle -undefined dynamic_lookup -L/Users/hz/.pyenv/versions/anaconda3-4.2.0/lib -arch x86_64 build/temp.macosx-10.6-x86_64-3.5/pgmodule.o -L/Users/hz/.pyenv/versions/anaconda3-4.2.0/lib/python3.5/site-packages -L/usr/local/pgsql/lib -L/Users/hz/.pyenv/versions/anaconda3-4.2.0/lib -lpq -o build/lib.macosx-10.6-x86_64-3.5/_pg.cpython-35m-darwin.so
```

ビルドすると、buildディレクトリが作られ、その中にビルドされたライブラリファイルが格納されます。

```sh
$ ls -l
total 672
-rw-r--r--@  1 hz  staff    1290  7 23  2017 LICENSE.txt
-rw-r--r--@  1 hz  staff     556  7 23  2017 MANIFEST.in
-rw-r--r--@  1 hz  staff    1362  7 23  2017 PKG-INFO
drwxr-xr-x@  7 hz  staff     224  7 23  2017 PyGreSQL.egg-info
-rw-r--r--@  1 hz  staff     859  7 23  2017 README.rst
drwxr-xr-x   4 hz  staff     128  4  1 06:19 build
drwxr-xr-x@ 15 hz  staff     480  7 23  2017 docs
-rw-r--r--@  1 hz  staff   96135  7 23  2017 pg.py
-rw-r--r--@  1 hz  staff   61267  7 23  2017 pgdb.py
-rw-r--r--@  1 hz  staff  145938  7 23  2017 pgmodule.c
-rw-r--r--@  1 hz  staff    3063  7 23  2017 pgtypes.h
-rw-r--r--@  1 hz  staff    3974  7 23  2017 py3c.h
-rw-r--r--@  1 hz  staff     165  7 23  2017 setup.cfg
-rwxr-xr-x@  1 hz  staff    8026  7 23  2017 setup.py
drwxr-xr-x@ 13 hz  staff     416  7 23  2017 tests

$ ls -l build
total 0
drwxr-xr-x  5 hz  staff  160  4  1 06:19 lib.macosx-10.6-x86_64-3.5
drwxr-xr-x  3 hz  staff   96  4  1 06:19 temp.macosx-10.6-x86_64-3.5

$ ls -l build/lib.macosx-10.6-x86_64-3.5/
total 520
-rwxr-xr-x  1 hz  staff  102644  4  1 06:19 _pg.cpython-35m-darwin.so
-rw-r--r--  1 hz  staff   96135  7 23  2017 pg.py
-rw-r--r--  1 hz  staff   61267  7 23  2017 pgdb.py
```

生成されたpg.pyの末尾、`if __name__ == '__main__'`の直前に、こんな一行を加えてみましょう。

```python
# この一行を加える。
print('### built from source pg.py ###')

# if run as script, print some information

if __name__ == '__main__':
    print('PyGreSQL version' + version)
    print('')
    print(__doc__)
```

これで、`import pg`とやったときに、自分がビルドしたモジュールが読み込まれたことを確認できます。

# importしてみる

[Pythonの公式ドキュメント](https://docs.python.org/3.6/tutorial/modules.html#the-module-search-path)によると、`import spam`とコマンドを書いたときに、`spam`モジュールの検索順序は以下の通りです。

1. 組み込みモジュールに`spam`という名前のモジュールがあれば、それをロードする。
2. 見つからなければ、`sys.path`にリストされているディレクトリを順に検索し、`spam`が見つかればそれをロードする。

ここで、`sys.path`には初期値として以下のディレクトリがリストに含まれます。

* 入力したスクリプトのディレクトリ。あるいは、スクリプトの指定がなければカレントディレクトリ。
* 環境変数`PYTHONPATH`
* インストール依存のデフォルト

というわけで、今回はビルドしたpg.pyがあるディレクトリに移動してからpythonを起動することで、ビルドしたpg.pyがモジュール検索時に見つかるようにしましょう。

```sh
$ cd build/lib.macosx-10.6-x86_64-3.5/
$ python
```

pythonインタプリタで`import`してみましょう。

```python
> import pg
### built from source pg.py ###
```

追加した一行がプリントされ、自身でビルドしたモジュールが読み込まれたことを確認できました。

# まとめ

公式ドキュメントの手順に従い、DistUtilsを利用してPyGreSQLをソースコードからビルドしてみました。
ビルドしたモジュールがロードされたことを確認しました。