CLOVER🍀

That was when it all began.

インストールされているPythonのコンパイルオプションを知りたい(ついでにインストールもしてみる)

これは、なにをしたくて書いたもの?

Pythonは、Linux OSであれば最初からインストールされていたり、比較的新しいバージョンもインストールできたりは
するのですが。

最新かというとそうでもないことが多く、それでも新しいバージョンを使いたい場合はDockerイメージを使うか、
自分でインストールすることになるのではないでしょうか。

環境

今回の環境は、こちらです。Ubuntu Linux 20.04 LTS。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:    20.04
Codename:   focal


$ uname -srvmpio
Linux 5.4.0-73-generic #82-Ubuntu SMP Wed Apr 14 17:39:42 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

インストールされているPython 3のバージョンは、こちらです。

$ python3 -V
Python 3.8.5

Pythonコンパイルオプションを確認する

sysconfigというパッケージから取得できるようです。

Python の配布物は、Python 自体のバイナリや、distutils によってコンパイルされる外部の C 拡張をビルドするために必要な、Makefile と pyconfig.h ヘッダーファイルを含んでいます。

sysconfig はこれらのファイルに含まれるすべての変数を辞書に格納し、get_config_vars() や get_config_var() でアクセスできるようにします。

sysconfig --- Python の構成情報にアクセスする — Python 3.8.10 ドキュメント

スクリプトとして動かせるようなので、まずはこちらを試してみましょう。

sysconfig をスクリプトとして使う

$ python3 -m sysconfig

実行すると、なにやらたくさん表示されます。

Platform: "linux-x86_64"
Python version: "3.8"
Current installation scheme: "posix_prefix"

Paths: 
    data = "/usr"
    include = "/usr/include/python3.8"
    platinclude = "/usr/include/python3.8"
    platlib = "/usr/lib/python3.8/site-packages"
    platstdlib = "/usr/lib/python3.8"
    purelib = "/usr/lib/python3.8/site-packages"
    scripts = "/usr/bin"
    stdlib = "/usr/lib/python3.8"

Variables: 
    ABIFLAGS = ""
    AC_APPLE_UNIVERSAL_BUILD = "0"
    AIX_GENUINE_CPLUSPLUS = "0"
    ALT_SOABI = "0"
    ANDROID_API_LEVEL = "0"
    AR = "x86_64-linux-gnu-gcc-ar"
    ARFLAGS = "rcs"
    BASECFLAGS = "-Wno-unused-result -Wsign-compare"
    BASECPPFLAGS = "-IObjects -IInclude -IPython"
    BASEMODLIBS = ""

〜省略〜

コンパイルオプションまわりは、このあたりですね。特にCONFIG_ARGSを見るのが良さそうです。

  CC = "x86_64-linux-gnu-gcc -pthread"
    CCSHARED = "-fPIC"
    CFLAGS = "-Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g   -fstack-protector-strong -Wformat -Werror=format-security  -g -fwrapv -O2   "
    CFLAGSFORSHARED = "-fPIC"
    CFLAGS_ALIASING = ""
    CFLAGS_NODIST = ""
    CONFIGFILES = "configure configure.ac acconfig.h pyconfig.h.in Makefile.pre.in"
    CONFIGURE_CFLAGS = "-g   -fstack-protector-strong -Wformat -Werror=format-security"
    CONFIGURE_CFLAGS_NODIST = "-std=c99 -Wextra -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration"
    CONFIGURE_CPPFLAGS = "-Wdate-time -D_FORTIFY_SOURCE=2"
    CONFIGURE_LDFLAGS = "-Wl,-Bsymbolic-functions  -Wl,-z,relro -g -fwrapv -O2   "
    CONFIGURE_LDFLAGS_NODIST = ""
    CONFIG_ARGS = "'--enable-shared' '--prefix=/usr' '--enable-ipv6' '--enable-loadable-sqlite-extensions' '--with-dbmliborder=bdb:gdbm' '--with-computed-gotos' '--without-ensurepip' '--with-system-expat' '--with-system-libmpdec' '--with-dtrace' '--with-system-ffi' 'CC=x86_64-linux-gnu-gcc' 'CFLAGS=-g   -fstack-protector-strong -Wformat -Werror=format-security ' 'LDFLAGS=-Wl,-Bsymbolic-functions  -Wl,-z,relro -g -fwrapv -O2   ' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'"
    CONFINCLUDEDIR = "/usr/include"
    CONFINCLUDEPY = "/usr/include/python3.8"

sysconfigをスクリプトとして実行した時に表示されているのは、get_platformget_python_version_get_default_scheme
get_pathsget_config_varsです。

https://github.com/python/cpython/blob/v3.8.5/Lib/sysconfig.py#L696-L707

構成情報はget_config_varsもしくはget_config_varを使って取得するので、大量に表示されているのはget_config_vars
情報になりますね。

インタプリターでも試してみましょう。

$ python3
Python 3.8.5 (default, Jan 27 2021, 15:41:15) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

こんな感じですね。

>>> import sysconfig
>>> print(sysconfig.get_config_var('CONFIG_ARGS'))
'--enable-shared' '--prefix=/usr' '--enable-ipv6' '--enable-loadable-sqlite-extensions' '--with-dbmliborder=bdb:gdbm' '--with-computed-gotos' '--without-ensurepip' '--with-system-expat' '--with-system-libmpdec' '--with-dtrace' '--with-system-ffi' 'CC=x86_64-linux-gnu-gcc' 'CFLAGS=-g   -fstack-protector-strong -Wformat -Werror=format-security ' 'LDFLAGS=-Wl,-Bsymbolic-functions  -Wl,-z,relro -g -fwrapv -O2   ' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'

One Linerでも。

$ python3 -c 'import sysconfig; print(sysconfig.get_config_var("CONFIG_ARGS"))'
'--enable-shared' '--prefix=/usr' '--enable-ipv6' '--enable-loadable-sqlite-extensions' '--with-dbmliborder=bdb:gdbm' '--with-computed-gotos' '--without-ensurepip' '--with-system-expat' '--with-system-libmpdec' '--with-dtrace' '--with-system-ffi' 'CC=x86_64-linux-gnu-gcc' 'CFLAGS=-g   -fstack-protector-strong -Wformat -Werror=format-security ' 'LDFLAGS=-Wl,-Bsymbolic-functions  -Wl,-z,relro -g -fwrapv -O2   ' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'

構成情報は、このあたりの情報から成っているようです。

https://github.com/python/cpython/blob/v3.8.5/configure

https://github.com/python/cpython/blob/v3.8.5/configure.ac

https://github.com/python/cpython/blob/v3.8.5/Include/pymacconfig.h

https://github.com/python/cpython/blob/v3.8.5/pyconfig.h.in

https://github.com/python/cpython/blob/v3.8.5/Makefile.pre.in

https://github.com/python/cpython/blob/v3.8.5/Modules/Setup

コンパイルオプションに関するものは、このあたりを見ればよいでしょうか。

https://github.com/python/cpython/blob/v3.8.5/configure#L3016

https://github.com/python/cpython/blob/v3.8.5/configure.ac#L146-L148

https://github.com/python/cpython/blob/v3.8.5/Makefile.pre.in#L206

Pythonを自分でコンパイルしてインストールする

せっかくなので、ここまで見たのならPythonを自分でコンパイルしてインストールしてみましょう。

3.8の最新(3.8.10)をインストールしてみます。

ドキュメントを見ると、makeしてインストールする感じで書かれていますね。

2. Unix プラットフォームで Python を使う — Python 3.8.10 ドキュメント

というわけで、まずはbuild-essentialをインストールしておきましょう。あとzlibも必要になるので、こちらもインストールして
おきます。

$ sudo apt install build-essential zlib1g-dev

Python 3.8.10のソースコードをダウンロードして、展開。

$ curl -sLO https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz
$ tar xf Python-3.8.10.tgz
$ cd Python-3.8.10

コンパイルオプションの確認は、こちらで。

$ ./configure --help

今回は、prefixだけ指定しておきます。

$ ./configure --prefix=/usr/local/python3.8.10

コンパイル&インストール。

$ make && sudo make install

無事、インストールされました。

$ /usr/local/python3.8.10/bin/python3 -V
Python 3.8.10

コンパイルオプションを確認してみます。

$ /usr/local/python3.8.10/bin/python3 -c 'import sysconfig; print(sysconfig.get_config_var("CONFIG_ARGS"))'
'--prefix=/usr/local/python3.8.10'

見事にprefixのみしか指定されていません。

ちょっと不安になったので、なにも指定せずに確認したら、空っぽになりました。

$ ./configure
$ make && sudo make install
$ /usr/local/bin/python3.8 -c 'import sysconfig; print(sysconfig.get_config_var("CONFIG_ARGS"))'

特にデフォルトの値などはなさそうですね。

では、prefix以外は、パッケージインストールのものにしてみましょう。

$ sudo apt install systemtap-sdt-dev

パッケージインストールされたPythonの結果を使ってconfigureを実行、

$ ./configure --prefix=/usr/local/python3.8.10 '--enable-shared' '--enable-ipv6' '--enable-loadable-sqlite-extensions' '--with-dbmliborder=bdb:gdbm' '--with-computed-gotos' '--without-ensurepip' '--with-system-expat' '--with-system-libmpdec' '--with-dtrace' '--with-system-ffi' 'CC=x86_64-linux-gnu-gcc' 'CFLAGS=-g   -fstack-protector-strong -Wformat -Werror=format-security ' 'LDFLAGS=-Wl,-Bsymbolic-functions  -Wl,-z,relro -g -fwrapv -O2   ' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'

インストール。

$ make && sudo make install

確認。

$ /usr/local/bin/python3.8 -V
Python 3.8.10


$ /usr/local/python3.8.10/bin/python3 -c 'import sysconfig; print(sysconfig.get_config_var("CONFIG_ARGS"))'
'--prefix=/usr/local/python3.8.10' '--enable-shared' '--enable-ipv6' '--enable-loadable-sqlite-extensions' '--with-dbmliborder=bdb:gdbm' '--with-computed-gotos' '--without-ensurepip' '--with-system-expat' '--with-system-libmpdec' '--with-dtrace' '--with-system-ffi' 'CC=x86_64-linux-gnu-gcc' 'CFLAGS=-g   -fstack-protector-strong -Wformat -Werror=format-security ' 'LDFLAGS=-Wl,-Bsymbolic-functions  -Wl,-z,relro -g -fwrapv -O2   ' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'

できました、と。

Ubuntu Linux 20.04 LTSとPython 3.9

ちなみに、パッケージインストールできるPython 3.9のコンパイルオプションは、Python 3.8とはまた違うようです。

$ sudo apt install python3.9


$ python3.9 -c 'import sysconfig; print(sysconfig.get_config_var("CONFIG_ARGS"))'
'--enable-shared' '--prefix=/usr' '--enable-ipv6' '--enable-loadable-sqlite-extensions' '--with-dbmliborder=bdb:gdbm' '--with-computed-gotos' '--without-ensurepip' '--with-system-expat' '--with-dtrace' '--with-system-ffi' 'CC=x86_64-linux-gnu-gcc' 'CFLAGS=-g   -fstack-protector-strong -Wformat -Werror=format-security ' 'LDFLAGS=-Wl,-Bsymbolic-functions  -Wl,-z,relro -g -fwrapv -O2   ' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'

Python 3.9だと'--with-system-libmpdec'が増えていました。