19
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pyenv環境下でOpenCVのビルドに失敗する

Last updated at Posted at 2018-10-01

この記事は何?

pyenv環境下でOpenCVを野良ビルドしようとしてcmakeを実行した際に,

--
--   Python 2:
--     Interpreter:                 /home/username/.pyenv/shims/python2.7 (ver 2.7.14)
-- 
--   Python 3:
--     Interpreter:                 /usr/bin/python3.4 (ver 3.4.3)
-- 
--   Python (for build):            /home/username/.pyenv/shims/python2.7
--

などと表示されて,makeしてもOpenCVのPython bindings (cv2.soなど) がビルドされない問題への対処方法.

方法

libpython*.soの準備

通常,pyenvでPythonを入れるとstatic library (libpython*.a) が導入される.
しかし,static libraryではOpenCVのビルド時に参照できない.

そこで,pyenvでPython環境をインストールする際にshared libraryを導入する.
pyenv installの際に,以下のように環境変数を設定してからインストールを行う.

$ CONFIGURE_OPTS="--enable-shared" pyenv install <version_to_install>

libpython*.soが導入されているかどうかは,pyenvのインストールディレクトリ以下を見ることで確認できる.

$ ls $(pyenv root)/versions/3.6.3/lib/
libpython3.6m.so  libpython3.6m.so.1.0  libpython3.so  pkgconfig  python3.6
$ ls $(pyenv root)/versions/2.7.14/lib/
libpython2.7.so  libpython2.7.so.1.0  pkgconfig  python2.7

Pythonを入れた後に各バージョンに切り替えてnumpyも入れておく.

cmake時のパス設定

運が良ければ,上記の設定をした後にcmakeをすれば正しくPython bindingsのビルド設定が行われる.
しかし,私の環境ではビルド設定が正しく行われなかったため,以下のオプションをcmake時に追加した.

OpenCVのバージョンは3.4.44.0.0,Pythonのバージョンは2.7.153.6.7で確認しています.

$ PYTHON3_VERSION="3.6.7"
$ PYTHON2_VERSION="2.7.15"
$ rm CMakeCache.txt
$ cmake .. \
  -Dbuild_opencv_python3=YES -Dbuild_opencv_python2=YES \
  -DPYTHON3_EXECUTABLE="$(pyenv global $PYTHON3_VERSION; pyenv which python)" \
  -DPYTHON3_INCLUDE_DIR="$(pyenv global $PYTHON3_VERSION; python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")" \
  -DPYTHON3_NUMPY_INCLUDE_DIRS="$(pyenv global $PYTHON3_VERSION; python -c "import os, numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))")" \
  -DPYTHON3_LIBRARY="$(pyenv global $PYTHON3_VERSION; python -c "import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var('LIBDIR') + '/' + sysconfig.get_config_var('LDLIBRARY'))")" \
  -DPYTHON2_EXECUTABLE="$(pyenv global $PYTHON2_VERSION; pyenv which python)" \
  -DPYTHON2_INCLUDE_DIR="$(pyenv global $PYTHON2_VERSION; python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")" \
  -DPYTHON2_NUMPY_INCLUDE_DIRS="$(pyenv global $PYTHON2_VERSION; python -c "import os, numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))")" \
  -DPYTHON2_LIBRARY="$(pyenv global $PYTHON2_VERSION; python -c "import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var('LIBDIR') + '/' + sysconfig.get_config_var('LDLIBRARY'))")"

これらのオプションを指定しておくと,cmake時のビルド設定が正しく行われる.
(正しく設定されない場合は,キャッシュCMakeCache.txtを消してからもう一度.)

--
--   Python 2:
--     Interpreter:                 /home/username/.pyenv/versions/2.7.15/bin/python (ver 2.7.14)
--     Libraries:                   /home/username/.pyenv/versions/2.7.15/lib/libpython2.7.so (ver 2.7.14)
--     numpy:                       /home/username/.pyenv/versions/2.7.15/lib/python2.7/site-packages/numpy/core/include (ver 1.13.3)
--     packages path:               lib/python2.7/site-packages
-- 
--   Python 3:
--     Interpreter:                 /home/username/.pyenv/versions/3.6.7/bin/python (ver 3.6.3)
--     Libraries:                   /home/username/.pyenv/versions/3.6.7/lib/libpython3.6m.so (ver 3.6.3)
--     numpy:                       /home/username/.pyenv/versions/3.6.7/lib/python3.6/site-packages/numpy/core/include (ver 1.14.2)
--     packages path:               lib/python3.6/site-packages
-- 
--   Python (for build):            /home/username/.pyenv/versions/2.7.15/bin/python
--

よくわかる解説

PYTHON3_EXECUTABLE, PYTHON2_EXECUTABLE

このオプションには,Pythonインタプリタのパスを設定すれば良い.
しかし,pyenv環境ではsym link (~/.pyenv/shims/python) がPythonインタプリタとしてデフォルトで検出されるようで,インクルードディレクトリやライブラリとの整合性が取れなくなる場合がある.
そこで,Pythonインタプリタのリンク元のパスをオプションで指定する.

コマンドの実行結果は以下のようになる.

$ echo "$(pyenv global 3.6.7; pyenv which python)"
/home/username/.pyenv/versions/3.6.3/bin/python
$ echo "$(pyenv global 2.7.15; pyenv which python)"
/home/username/.pyenv/versions/2.7.14/bin/python

PYTHON3_INCLUDE_DIR, PYTHON2_INCLUDE_DIR

このオプションには,Pythonのインクルードパスを指定する.
何も設定せずにcmakeした場合,システムのPythonのインクルードパスを検知することが多い模様である.

コマンドの実行結果は以下のようになる.

$ echo "$(pyenv global 3.6.7; python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")"
/home/username/.pyenv/versions/3.6.3/include/python3.6m
$ echo "$(pyenv global 2.7.15; python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")"
/home/username/.pyenv/versions/2.7.14/include/python2.7

PYTHON3_NUMPY_INCLUDE_DIRS, PYTHON2_NUMPY_INCLUDE_DIRS

このオプションには,numpyのインクルードパスを指定する.
何も設定せずにcmakeした場合,システムのPythonにインストールされているnumpyのインクルードパスを検知することが多い模様である.

コマンドの実行結果は以下のようになる.

$ echo "$(pyenv global 3.6.7; python -c "import os, numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))")"
/home/username/.pyenv/versions/3.6.3/lib/python3.6/site-packages/numpy/core/include
$ echo "$(pyenv global 2.7.15; python -c "import os, numpy.distutils; print(os.pathsep.join(numpy.distutils.misc_util.get_numpy_include_dirs()))")"
/home/username/.pyenv/versions/2.7.14/lib/python2.7/site-packages/numpy/core/include

PYTHON3_LIBRARY, PYTHON2_LIBRARY

このオプションには,Pythonのshared libraryのパスを指定する.
何も設定せずにcmakeした場合,システムのPythonのshared libraryを検知することが多い模様である.
また,pyenvでPython環境を用意した際にlibpython*.soが導入されていないと,ここで詰む.

コマンドの実行結果は以下のようになる.

$ echo "$(pyenv global 3.6.7; python -c "import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var('LIBDIR') + '/' + sysconfig.get_config_var('LDLIBRARY'))")"
/home/username/.pyenv/versions/3.6.3/lib/libpython3.6m.so
$ echo "$(pyenv global 2.7.15; python -c "import distutils.sysconfig as sysconfig; print(sysconfig.get_config_var('LIBDIR') + '/' + sysconfig.get_config_var('LDLIBRARY'))")"
/home/username/.pyenv/versions/2.7.14/lib/libpython2.7.so

PYTHONPATHの設定

OpenCVのモジュールパスを環境変数PYTHONPATHに登録する.
OpenCVのインクルードパスに依存するが,例えば~/usr以下にインストールしている (=CMAKE_PREFIX_PATH$HOME/usrに設定した) 場合には,

$ ls ~/usr/lib/python2.7/site-packages/
cv2.so
$ ls ~/usr/lib/python3.6/site-packages/
cv2.cpython-36m-x86_64-linux-gnu.so

といった場所にモジュールが配置されている.これらをPYTHONPATHに登録する.

Python2系であれば

export PYTHONPATH="$HOME/usr/lib/python2.7/site-packages:$PYTHONPATH"

Python3系であれば

export PYTHONPATH="$HOME/usr/lib/python3.6/site-packages:$PYTHONPATH"

~/.profile等に記述する.

(間違ったバージョンのパスが登録されているとimport時にエラーを吐く.)

もし,Pythonのバージョンに応じて動的にPYTHONPATHを変更したい場合は,

PYTHON_MAJOR_VERSION=$(python -c "import sys; print(sys.version_info.major)")
if [ $PYTHON_MAJOR_VERSION = "3" ]; then
    export PYTHONPATH="$HOME/usr/lib/python3.6/site-packages:$PYTHONPATH"
elif [ $PYTHON_MAJOR_VERSION = "2" ]; then
    export PYTHONPATH="$HOME/usr/lib/python2.7/site-packages:$PYTHONPATH"
fi

のように書いておく.

終わりに

OpenCVをビルドするのが日課になってきた.

19
15
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?