Compiling 64 bit PHP on Mac OS X Leopard

My iMac ships with Leopard 10.5.2 and PHP 5.2.5 was integrated. As I was planning to build optional components into PHP, I decided to compile PHP 5.2.6 myself.

I have MySQL installed on /usr/local/mysql and to preserve the orginal settings of the preinstalled version, I used following configure options:

./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-dbx --enable-sockets \
--with-iodbc=/usr --with-curl=/usr --with-config-file-path=/etc --sysconfdir=/private/etc \
--with-mysql-sock=/var/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config \
--with-mysql=/usr --with-openssl --with-xmlrpc --with-xsl=/usr --without-pear \
--with-mysql=/usr/local/mysql

Then after building, make and install, apache failed to start as libphp5.so was in a “wrong architecture”.

Then I realized, the Apache shipped with Leopard was the 64bit version, so I have to build a 64 bit PHP.

so I added the following before configure:

MACOSX_DEPLOYMENT_TARGET=10.5
CFLAGS="-arch x86_64 -g -Os -pipe -no-cpp-precomp"
CCFLAGS="-arch x86_64 -g -Os -pipe"
CXXFLAGS="-arch x86_64 -g -Os -pipe"
LDFLAGS="-arch x86_64 -bind_at_load"
 
export CFLAGS CXXFLAGS LDFLAGS CCFLAGS MACOSX_DEPLOYMENT_TARGET

The last line seems redundant but strangely on my machine, the flags won’t work until I export them.

In order to configure a 64bit build, I have to install a 64bit version of MySQL, or you’ll fail the configure.

All files compiled successfully, but the linkage failed. The error was “Undefined symbol: _libiconv”. Well that’s a new one, didn’t see that when building the x86 version.

After googling for a while, I found the solution. Apple’s libiconv.dylib has a bug, it forgot to export _libiconv for both 64bit architectures (ppc64 and x86_64). The solution is to compile a universal binary libiconv yourself. (And do not forgot to install the header files too, or you’ll get other undefined symbol errors)

The flags of building universal binary is similar as the above ones. Just remember to put all four architectures (-arch i386 -arch x86_64 -arch pc7400 -arch ppc64) there.

Then finally I have the php built successfully and up n running.

Notes

To build a universal binary version of PHP, you need to build MySQL universal yourself as well, and all the libraries you used should be compiled as universal binary.

A universal binary looks like this :

$ file /usr/sbin/httpd
/usr/sbin/httpd: Mach-O universal binary with 4 architectures
/usr/sbin/httpd (for architecture ppc7400):	Mach-O executable ppc
/usr/sbin/httpd (for architecture ppc64):	Mach-O 64-bit executable ppc64
/usr/sbin/httpd (for architecture i386):	Mach-O executable i386
/usr/sbin/httpd (for architecture x86_64):	Mach-O 64-bit executable x86_64

- Update:
After this post I’ve been using php with Leopard for a while. I found that sometimes (probably after an OS update, but I haven’t confirmed this yet) the system restores old versions of php, which would fail to load the custom-built libiconv. So you have to run “make install” & “make install-cli” again to make the new version working again. (No recompilation, only reinstall)

PSP Internet Browser HTTP Headers

I remember visiting a PSP-only website, which when browsed on PC, gives a different output saying something like “you should view this on PSP”. I wonder how they implemented it.

I guess PSP must send some kind of special info to the server, so I wrote a little PHP script showing request headers. (traditional sniffers / browser plugins won’t work now, unless you wanna port them to PSP yourself, lol).

As my hosting does not allow apache_request_headers, I have to extract the data from $_SERVER myself.

<?php
foreach ($_SERVER as $k => $v) {
	if (substr($k, 0, 5) == "HTTP_") {
		// Format the variable names
		$k = str_replace('_', ' ', substr($k, 5));
		$k = str_replace(' ', '-', ucwords(strtolower($k)));
 
		echo "<tr><td class=\"e\">$k</td><td class=\"v\">$v</td></tr>\r\n";
	}
}
?>

You can point your PSP to http://playground.softboysxp.org/show_request_header.php and test it yourself.

Here’s a snapshot taken on my PSP

Clearly, there are two PSP-specific variables, x-psp-browser and x-psp-productcode. Also notice that the User-Agent was set to reflect PSP’s browser.

Further Research

I googled x-psp-browser and found this document by SCE.

Guidelines for Creating Content for the “PSP” Internet Browser (Japanese)

User-Agent by far can only be “User-Agent: Mozilla/4.0 (PSP (PlayStation Portable); 2.00)

x-psp-productcode represents the region of your PSP and can be one of the following

Region Code
開発ツール (Development Tools) “TOOL”
日本 (Japan) “J1”
北米 (North America) “UC2”
東欧/欧州 (Europe) “CEL”
韓国 (Korea) “KR2”
UK (United Kingdom) “CEK”
メキシコ (Mexico) “MX2”
AU/NZ (Australia/New Zealand) “AU3”
南アジア (South Asia) “E12”
台湾 (Taiwan) “TW1”
ロシア (Russia) “RU3”
中国 (China) “CN9”

x-psp-browser is in the format of “n.nn (xxx; yyy; zzz; …)”
n.nn is the version of the firmware
xxx, yyy, zzz … being parameters, specify from where the browser was lunched, with LX for XMB, SX for applications under XMB, and LU being applications on UMD or Memory Stick. Another parameter, “system”, specifies the version.

Another variable, x-psp-application can be used to specify the name of the game/application, when the browser was launched by an application on UMD/Memory Stick.