at_yasu's blog

ロード的なことを

無茶なバイナリーの作り方。

Leopardに入っているPHPにはPostgreSQLのライブラリがサポートされてなかったので、作りました。ただ、今度はMySQLが無くなってしまったけど・・・*1

*ちなみに動きません。理由は最下部*

作成したバイナリーは、Universal Binaryになっています。

ダウンロードは、http://a-yasui.info/~yasui/LeopardPHP.tgzです。

ハッシュ値

  • md5: 941d465a9ad3a7e2c79aa1d33e0fd9c4 LeopardPHP.tgz
  • shasum: 5e911796b2c1709c2e125a3525713521d9e856aa LeopardPHP.tgz

なお、インストールする時、/usr/libexec/apache2以下にある、libphp5.soをコピーして使用してください。

PostgresのバイナリーとPHPのソースコードは下記からダウンロードしました。

無保証です。


以下作り方。

下記のような、configureコマンドを実行。後にmake && make testで作成とテストをしてます。

#!/bin/sh
setenv CFLAGS "-arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk"
./configure \
--prefix=/usr \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--disable-dependency-tracking \
--with-apxs2=/usr/sbin/apxs \
--with-ldap=/usr \
--with-kerberos=/usr \
--enable-cli \
--with-zlib-dir=/usr \
--enable-trans-sid \
--with-xml \
--enable-exif \
--enable-ftp \
--enable-mbstring \
--enable-mbregex \
--enable-sockets \
--with-iodbc=/usr \
--with-curl=/usr \
--with-config-file-path=/etc \
--sysconfdir=/private/etc \
--with-pgsql=/usr/local/pgsql \
--with-xmlrpc \
--with-xsl=/usr \
--without-pear


追記:ごめん、これ動かない・・・orz

LeopardのApacheは、x86_64,ppc64,i386,ppcのそれぞれを持っているユニバーサルバイナリーで、それに吊られてPHPの方も合わせて作らなきゃ行けない。頭が痛いのは、PHPのバイナリーを作る為には、PostgreSQLの方もそれように作らなきゃ行けない訳。ちょっと現実逃避のため、つらつらと詳しい理由を掻いてみる。

先ず、Apacheは起動する時に共有ライブラリをずらずら読み込んで行く。その際に、dlopenは気をきかして、Apacheの動いているバイナリーのタイプ(例えば、G5だとppc64、Xeonだとx86_64といった感じで読み込んでいる。)、それと同じ物を読み込もうとし少しでも違う物はエラーとして扱う。つまりx86_64で動いており、共有ライブラリがi386だとしてもエラーとして扱われる。そして、これは共有ライブラリを作る際も同じで、この場合だとPHPとPostgreSQLの双方とも、(ppc|ppc64|i386|x86_64)が必要になる。

むぅ、PostgreSQLだけど、heaptuple.cがどうもこの四つのユニバーサルバイナリーを作成することができないみたい。どうも、内部マクロのinclude/access/tupmacs.hにあるstore_att_byval(下の文、参考)で使われているswich文のcaseに同じ値のが使われていると文句を言っている気配。でその比較には、int16やint32があり、それはinclude/c.hで定義されている。(下の文、参考)後、Datumというのもinclude/fmgr.h で定義されており、下記を参考に。

推測だけど、Darwin 9.0以降、int型は(強制的に)64bitになった。今まで、関数のポインターには(多分)long型が使われてて、int32と名付けられたint型とDatum型がダブルブッキング起こしたんじゃないかなぁ・・・


困った事に、こんな所を自分勝手に修正したくないよ・・・

むぅ、DarwinPortsでApache+PHP+PostgreSQL/ppc,i386か・・・

#if SIZEOF_DATUM == 8

#define store_att_byval(T,newdatum,attlen) \
    do { \
        switch (attlen) \
        { \
            case sizeof(char): \
                *(char *) (T) = DatumGetChar(newdatum); \
                break; \
            case sizeof(int16): \
                *(int16 *) (T) = DatumGetInt16(newdatum); \
                break; \
            case sizeof(int32): \
                *(int32 *) (T) = DatumGetInt32(newdatum); \
                break; \
            case sizeof(Datum): \
                *(Datum *) (T) = (newdatum); \
                break; \
            default: \
                elog(ERROR, "unsupported byval length: %d", \
                     (int) (attlen)); \
                break; \
        } \
    } while (0)

#else                           /* SIZEOF_DATUM != 8 */

#define store_att_byval(T,newdatum,attlen) \
    do { \
        switch (attlen) \
        { \
            case sizeof(char): \
                *(char *) (T) = DatumGetChar(newdatum); \
                break; \
            case sizeof(int16): \
                *(int16 *) (T) = DatumGetInt16(newdatum); \
                break; \
            case sizeof(int32): \
                *(int32 *) (T) = DatumGetInt32(newdatum); \
                break; \
            default: \
                elog(ERROR, "unsupported byval length: %d", \
                     (int) (attlen)); \
                break; \
        } \
    } while (0)
#endif   /* SIZEOF_DATUM == 8 */
/*
 * intN
 *      Signed integer, EXACTLY N BITS IN SIZE,
 *      used for numerical computations and the
 *      frontend/backend protocol.
 */
#ifndef HAVE_INT8
typedef signed char int8;       /* == 8 bits */
typedef signed short int16;     /* == 16 bits */
typedef signed int int32;       /* == 32 bits */
#endif   /* not HAVE_INT8 */

/*
 * uintN
 *      Unsigned integer, EXACTLY N BITS IN SIZE,
 *      used for numerical computations and the
 *      frontend/backend protocol.
 */
#ifndef HAVE_UINT8
typedef unsigned char uint8;    /* == 8 bits */
typedef unsigned short uint16;  /* == 16 bits */
typedef unsigned int uint32;    /* == 32 bits */
#endif   /* not HAVE_UINT8 */
 * All functions that can be called directly by fmgr must have this signature.
 * (Other functions can be called by using a handler that does have this
 * signature.)
 */

typedef struct FunctionCallInfoData *FunctionCallInfo;

typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);

*1:右を立たせば左が立たぬと申します・・・いやいや