弊社は受託開発を主業務としていますので、 顧客の要望次第では、 あまり一般的ではない環境での開発も行います。
例えば:
- OpenSolaris
- SunStudio 11(最新は 12) 付属のコンパイラ
- GCC は無し
といった環境での開発だったりします。
社内の構成管理(私の趣味?)の都合上、 何とかして Mercurial ぐらいは使えるようにしたいのですが、 そもそも Python をソースからインストールしなければならない、 といった事態もあります。
世間的には、オープンソースプロダクトは configure & make で一発インストール、 と思われている節もありますが、 世の中それ程甘くはありません(特に GCC が無い場合)。
そういうわけで、 非常にニッチではありますが、 折角あちこち咬まれたのですから、 OpenSolaris(Solaris10) + SunStudio11 環境での Pytho 2.5.2 導入に関する情報を公開しておこうと思います (いずれ本家にパッチを contrib したいなぁ)。
ビルド~インストールまでの基本的な手順を以下に示します。
% export CC="/opt/SUNWspro/bin/cc"
% export CFLAGS="-xarch=v8"
% export CPP="${CC} -xarch=v8 -E"
% ./configure \
--prefix=/usr/local \
--without-gcc \
% make \
CC="/opt/SUNWspro/bin/cc -xarch=v8" \
CPP="/opt/SUNWspro/bin/cc -xarch=v8 -E" \
all
% make \
CC="/opt/SUNWspro/bin/cc -xarch=v8" \
CPP="/opt/SUNWspro/bin/cc -xarch=v8 -E" \
install
CC/CPP 等を環境変数/make マクロの両方で指定しているのは、 本来冗長な筈なのですが、 GNU の make なのか否かとか、 内部的なサブコマンド起動の手順に依存して、 make マクロは引継ぎが想定と異なる場合があるため、 覚悟の上での冗長指定です。
また、32bit バイナリ指定("-xarch=v8")
は無くても良いのですが、
うっかり 64bit バイナリでビルドされて変な地雷を踏むことのないように、
念のため指定しています。
人柱体質の人は、
ぜひとも "-xarch=v9"
とかでビルドして欲しいものです。
本当は、 これで無事ビルドできれば良いのですが、 残念ながらそうは問屋が卸しません。 以下、トラブル対処の様子を時系列を追って見て行きます。
__attribute__ 対策Python のソースでは、
ISO C99 標準に準拠していない GCC の固有拡張機能である __attribute__ が使用されています
(C99 仕様を確認したわけではないですが、
「Some people object to the __attribute__ feature,
suggesting that ISO C's #pragma should be used instead.」
と記されているぐらいですので、
「どちらが適切か?」の議論は別として、
標準化はされていないと見ました)。
一応、
非 GCC 環境で
__attribute__
を除外するために、
Py_GCC_ATTRIBUTE マクロが用意されているのですが、
この利用が徹底されていない部分があるため、
以下のような対処が必要です。
diff -r 1d96914254ef Modules/_ctypes/libffi/include/ffi.h.in
--- a/Modules/_ctypes/libffi/include/ffi.h.in Thu Apr 10 12:53:35 2008 +0900
+++ b/Modules/_ctypes/libffi/include/ffi.h.in Fri Apr 11 22:35:29 2008 +0900
@@ -60,6 +60,7 @@ extern "C" {
/* ---- System configuration information --------------------------------- */
+#include <pyport.h> /* ensure Py_GCC_ATTRIBUTE definition */
#include <ffitarget.h>
#ifndef LIBFFI_ASM
@@ -218,7 +219,7 @@ typedef struct {
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
-} ffi_closure __attribute__((aligned (8)));
+} ffi_closure Py_GCC_ATTRIBUTE((aligned (8)));
ffi_status
ffi_prep_closure (ffi_closure*,
diff -r 1d96914254ef Modules/_ctypes/libffi/include/ffi_common.h
Py_GCC_ATTRIBUTE マクロ利用の徹底各アーキテクチャ固有のヘッダ・ソース
(e.g.: Modules/_ctypes/libffi/src/sparc
配下のファイル)
なら兎も角、
思い切りアーキテクチャ中立な
Modules/_ctypes/libffi/include
配下にこういったソースがあることから、
SunStudio を用いたビルド率が極めて低いことが伺えます。
ssize_t 対策Include/pyport.h で使用している ssize_t 型は、
OpenSolaris では sys/types.h で
typedef されているのですが、
このヘッダの読み込みが保証されていないらしく、
以下のような対処が必要です。
diff -r 1d96914254ef Include/pyport.h
--- a/Include/pyport.h Thu Apr 10 12:53:35 2008 +0900
+++ b/Include/pyport.h Fri Apr 11 22:35:29 2008 +0900
@@ -110,6 +110,9 @@ typedef PY_LONG_LONG Py_intptr_t;
* unsigned integral type). See PEP 353 for details.
*/
#ifdef HAVE_SSIZE_T
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
typedef ssize_t Py_ssize_t;
#elif SIZEOF_VOID_P == SIZEOF_SIZE_T
typedef Py_intptr_t Py_ssize_t;
ここまでの対処で、 随分目処が立ったような気になるのですが、 結局のところ、 以下のような GCC 固有のインラインアセンブラ記述が邪魔をするため、 _ctypes モジュールのビルドは諦めざるを得ません。
asm volatile ("iflush %0" : : "r" (closure) : "memory");
asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory");
alpha プラットフォームだと対処済みの模様ですが、
これは命令キャッシュをクリアする命令の体系が、
レジスタによるアドレス渡しが必要な SPARC に対して、
alpha では簡単な記述
(asm("call_pal 0x86;"); で済む)
だからなのでしょう(詳細求ム)。
完全アセンブラの関数を組むのも、 SPRAC なら save/restore を使えば簡単なのですが、 そこまでやるか?というと、 心情的には微妙な感じです (後述するように、_ctypes は Mercurial 稼動上は必要無いですし…)。
RELEASE NOTE を読むに、 どうやら SunStudio 12 を使えば、 ここまで述べてきた問題が実は殆ど解決する模様なのですが、 顧客が SunStudio 11 と言ったなら、 SunStudio 11 を使わなければならないところが、 下請けの悲しい宿命です。
結局、与えられた条件下では _ctypes モジュールはビルドできませんから、 これをビルド対象から除外する必要が有ります。
古い世代の人間としては、
Makefile にモジュール一覧を定義したマクロか、
Modules ディレクトリ配下を走査するルール記述等がある、
と思っていたのですが、
Python は素のビルドで出来上がったインタプリタを使用して、
setup.py
経由で拡張モジュールインストール用のライブラリを起動しているのでした。
特定のモジュールをビルド対象から除外するには、
setup.py を直接編集して、
除外対象モジュール名を
disabled_module_list 配列の定義に追加する必要が有ります。
diff -r 1d96914254ef setup.py
--- a/setup.py Thu Apr 10 12:53:35 2008 +0900
+++ b/setup.py Fri Apr 11 22:49:39 2008 +0900
@@ -15,7 +15,7 @@ from distutils.command.install_lib impor
from distutils.command.install_lib import install_lib
# This global variable is used to hold the list of modules to be disabled.
-disabled_module_list = []
+disabled_module_list = [ '_ctypes' ]
def add_dir_to_list(dirlist, dir):
"""Add the directory 'dir' to the list 'dirlist' (at the front) if
Google で disabled_module_list を検索しても、
ヒット数が非常に少ないことから、
一般にはフルビルドしかされていないのか、
あるいは setup.py
界隈ではあえて書くまでも無い常識なのでしょう
(今時の情報氾濫を考えると、絶対前者だと思いますが)。
ありがたいことに、 _ctypes モジュールが無くても Mercurial の稼動に支障はありませんので、 OpenSolaris において SunStudio11 で生成した Python バイナリで _ctypes を使用したくてこのページを読んでいる方には申し訳ありませんが、 このエントリはこれで終わりです。