LoginSignup
3
4

More than 5 years have passed since last update.

そのインストール/ビルド失敗の悩み、sysconfigモジュールが救う(かもしれない)

Last updated at Posted at 2014-11-08

Homebrewでpyqt5をインストールした際に発生したエラー

Homebrew経由でpyqt5をインストールしたところ、python3 configure.py実行中に以下のエラーが出た。

...
  File "configure.py", line 2693, in main
    target_config.from_introspection(opts.verbose, opts.debug)
  File "configure.py", line 733, in from_introspection
    self.py_pylib_dir = pylib_dir
UnboundLocalError: local variable 'pylib_dir' referenced before assignment
...

configure.pyの該当箇所は以下の通り。py_pylib_dirへの変数が代入されないのは、dynamic_pylibが偽の時だと分かる。
dynamic_pylibは、--enable-frameworkというキーがあるかを判別しているようだ。

configure.py
...
            # Use distutils to get the additional configuration.
            from distutils.sysconfig import get_config_vars
            ducfg = get_config_vars()

            config_args = ducfg.get('CONFIG_ARGS', '')

            if sys.platform == 'darwin':
                dynamic_pylib = '--enable-framework' in config_args
            else:
                dynamic_pylib = '--enable-shared' in config_args

            if dynamic_pylib:
                pyshlib = ducfg.get('LDLIBRARY', '')

                exec_prefix = ducfg['exec_prefix']
                multiarch = ducfg.get('MULTIARCH', '')
                libdir = ducfg['LIBDIR']

                if glob.glob('%s/lib/libpython%d.%d*' % (exec_prefix, py_major, py_minor)):
                    pylib_dir = exec_prefix + '/lib'
                elif multiarch != '' and glob.glob('%s/lib/%s/libpython%d.%d*' % (exec_prefix, multiarch, py_major, py_minor)):
                    pylib_dir = exec_prefix + '/lib/' + multiarch
                elif glob.glob('%s/libpython%d.%d*' % (libdir, py_major, py_minor)):
                    pylib_dir = libdir
                else:
                    pylib_dir = ''
            else:
                pyshlib = ''

        self.py_pylib_dir = pylib_dir
        self.py_pylib_lib = pylib_lib
        self.py_pyshlib = pyshlib
...

sysconfigモジュールによる構成情報の確認

ではget_config_vars関数で取得できる辞書と、そのキーのCONFIG_ARGSはどのような情報を表しているのか。
公式のリファレンスを見ると、「引数がない場合、現在のプラットフォームに関するすべての構成変数の辞書を返します。」という記述がある。「構成変数」というのは同ページで説明されているように、Pythonのビルド時(configure/make)に決定される情報が全て入っている。例えばCONFIG_ARGSには./configure実行時に指定した引数が格納されている。

get_config_varsで取得できる内容は、sysconfigモジュールを直接実行すると簡単に取得できる。実際に取得した結果、確かに--enable-frameworkは入っていない。
(ref.)
http://www.warp1337.com/content/python-32-get-compile-options-get-configargs
https://github.com/python/cpython/blob/master/Lib/sysconfig.py#L694

sysconfigモジュールの実行結果(エラーが発生した際のPython)
$ python -m sysconfig | grep CONFIG_ARGS
        CONFIG_ARGS = "'--prefix=/Users/FGtatsuro/.anyenv/envs/pyenv/versions/3.4.2' '--libdir=/Users/FGtatsuro/.anyenv/envs/pyenv/versions/3.4.2/lib' 'LDFLAGS=-L/usr/local/opt/readline/lib -L/usr/local/opt/readline/lib -L/Users/FGtatsuro/.anyenv/envs/pyenv/versions/3.4.2/lib ' 'CPPFLAGS=-I/usr/local/opt/readline/include -I/usr/local/opt/readline/include -I/Users/FGtatsuro/.anyenv/envs/pyenv/versions/3.4.2/include '"

そもそも--enable-frameworkはなんなのか、というのはPythonのREADMEに記載がある。指定することにより、フレームワーク形式でPythonをビルドできる(フレームワーク形式についてはこちら参照)。この引数がデフォルトでは指定されないため、自身の環境で使用しているPython(pyenv経由でインストール)はフレームワーク形式でビルドされていなかった。

(PythonのREADMより抜粋)
* ``--enable-framework[=DIR]``

 If this argument is specified the build will create a Python.framework rather
than a traditional Unix install. See the section
_`Building and using a framework-based Python on Mac OS X` for more
information on frameworks.

対処方法

HomebrewでインストールしたPythonを使う

Homebrewはデフォルトで--enable-frameworkを指定してビルドしている。
(ref.) https://github.com/Homebrew/homebrew/blob/master/Library/Formula/python3.rb#L77

sysconfigモジュールの実行結果(HomebrewでインストールしたPython)
$ /usr/local/bin/python3 -m sysconfig | grep CONFIG_ARGS
        CONFIG_ARGS = "'--prefix=/usr/local/Cellar/python3/3.4.2_1' '--enable-ipv6' '--datarootdir=/usr/local/Cellar/python3/3.4.2_1/share' '--datadir=/usr/local/Cellar/python3/3.4.2_1/share' '--enable-framework=/usr/local/Cellar/python3/3.4.2_1/Frameworks' '--without-gcc' 'CFLAGS=-I/usr/local/include -I/usr/local/opt/sqlite/include' 'LDFLAGS=-L/usr/local/lib -L/usr/local/opt/sqlite/lib' 'MACOSX_DEPLOYMENT_TARGET=10.9' 'CC=clang'"

ビルド時に--enable-frameworkを指定する(pyenv)

pyenvは環境変数PYTHON_CONFIGURE_OPTSを指定することで、ビルド時の設定を変更できる。
(ref.) https://github.com/yyuu/pyenv/issues/99

bash
$ env PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.3.6

$ pyenv global 3.3.6
$ ~/.anyenv/envs/pyenv/shims/python -m sysconfig | grep CONFIG_ARGS
        CONFIG_ARGS = "'--prefix=/Users/tatsuro/.anyenv/envs/pyenv/versions/3.3.6' '--libdir=/Users/tatsuro/.anyenv/envs/pyenv/versions/3.3.6/lib' '--enable-framework' '--enable-framework=/Users/tatsuro/.anyenv/envs/pyenv/versions/3.3.6' 'LDFLAGS=-L/usr/local/opt/readline/lib -L/usr/local/opt/readline/lib -L/Users/tatsuro/.anyenv/envs/pyenv/versions/3.3.6/lib ' 'CPPFLAGS=-I/usr/local/opt/readline/include -I/usr/local/opt/readline/include -I/Users/tatsuro/.anyenv/envs/pyenv/versions/3.3.6/include '"

最後になるが、Virtualenv環境作成時に指定したPythonがフレームワーク形式でビルドされていない場合、作成した環境で使用するPythonも同様にフレームワーク形式でビルドされていないものであるため注意すること。

3
4
0

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
3
4