Table of Contents
Below we describe the process of creating a portable executable of PHP on a Fedora Core 3 x86-64 host.
We are going to test the portability on Fedora 12 x86-64.
Maybe we could just copy the php binary from Fedora Core 3 to Fedora 12 and be done with it?
Well, let's try. First just to be sure run the php on Fedora Core 3:
[magicErmine@Fedora3]$ php -v PHP 4.3.9 (cgi) (built: Oct 20 2004 14:07:20) Copyright (c) 1997-2004 The PHP Group Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies
Looks good.
Now, let's copy the executable to Fedora 12 and try to run it there:
[magicErmine@Fedora12]$ php -v ./php: error while loading shared libraries: libexpat.so.0: cannot open shared object file: No such file or directory
Uh oh! That's not so good. Our simple approach of just copying the executable and hoping it would work has failed -- there is a portability problem.
Let's pack php
with the following command:
[magicErmine@Fedora3]$ ErminePro /usr/bin/php -o php.ermine.1
then copy php.ermine.1
to the Fedora12 box and run it there:
[magicErmine@Fedora12]$ ./php.ermine.1 -v PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/curl.so' - /usr/lib64/php4/curl.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/fileinfo.so' - /usr/lib64/php4/fileinfo.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/json.so' - /usr/lib64/php4/json.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/ldap.so' - /usr/lib64/php4/ldap.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/mbstring.so' - /usr/lib64/php4/mbstring.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/mcrypt.so' - /usr/lib64/php4/mcrypt.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/mysql.so' - /usr/lib64/php4/mysql.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/mysqli.so' - /usr/lib64/php4/mysqli.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/pdo.so' - /usr/lib64/php4/pdo.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/pdo_mysql.so' - /usr/lib64/php4/pdo_mysql.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/pdo_sqlite.so' - /usr/lib64/php4/pdo_sqlite.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/phar.so' - /usr/lib64/php4/phar.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/sqlite3.so' - /usr/lib64/php4/sqlite3.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/zip.so' - /usr/lib64/php4/zip.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP 4.3.9 (cgi) (built: Oct 20 2004 14:07:20) Copyright (c) 1997-2004 The PHP Group Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies
Now at least php is able to run. But where do all those warnings come from?
php.ermine.1 tried (and failed) to load a bunch of dynamic libraries. How does php know what libraries should be loaded?
As can be seen from php's man page
(or from strace -e open /usr/bin/php output)
php uses /etc/php.ini
as config file.
Here is the relevant part of this file from Fedora Core 3:
;;;; ; Note: packaged extension modules are now loaded via the .ini files ; found in the directory /etc/php.d; these are loaded by default. ;;;;
Our first packaging attempt left out two important things:
- the php configuration file
- the php extensions directory
Let's add these to Ermine's configuration file
config.2
:
# config.2 /etc/php.ini internal /etc/php.d internal
And then pack them:
[magicErmine@Fedora3]$ ErminePro /usr/bin/php --config=config.2 --output=php.ermine.2
We copy php.ermine.2
to our Fedora 12 machine and run it:
[magicErmine@Fedora12]$ ./php.ermine.2 -v PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/ldap.so' - /usr/lib64/php4/ldap.so: cannot open shared object file: No such file or directory in Unknown on line 0 PHP 4.3.9 (cgi) (built: Oct 20 2004 14:07:20) Copyright (c) 1997-2004 The PHP Group Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies
Now it looks less scary.
If we tak a look at /etc/php.d
on the Fedora Core 3 machine, there is only one entry:
[magicErmine@Fedora3]$ ls /etc/php.d/ ldap.ini
While /etc/php.d
on our Fedora 12 machine has a bit more:
[magicErmine@Fedora12]$ ls /etc/php.d/ curl.ini json.ini mbstring.ini mysqli.ini pdo.ini pdo_sqlite.ini sqlite3.ini fileinfo.ini ldap.ini mcrypt.ini mysql.ini pdo_mysql.ini phar.ini zip.ini
Yes - it's better, but the extensions still can't be loaded.
Lets have a closer look at /etc/php.ini
on Fedora Core 3:
; Directory in which the loadable extensions (modules) reside. extension_dir = /usr/lib64/php4
This directory should be packed too, so we add it to the config file:
# config.3 /etc/php.ini internal /etc/php.d internal /usr/lib64/php4 internal
And now let's package it again:
[magicErmine@Fedora3]$ ErminePro /usr/bin/php --config=config.3 --output=php.ermine.3
Once more we copy php.ermine.3
to our Fedora 12 machine and run it:
[magicErmine@Fedora12]$ ./php.ermine.3 -v PHP Warning: Unknown(): Unable to load dynamic library '/usr/lib64/php4/ldap.so' - libldap-2.2.so.7: cannot open shared object file: No such file or directory in Unknown on line 0 PHP 4.3.9 (cgi) (built: Oct 20 2004 14:07:20) Copyright (c) 1997-2004 The PHP Group Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies
php.ermine.3, like php.ermine.2
is unable to load ldap.so
,
but the reason is different:
php.ermine.2 was unable to find
ldap.so
itself,
while php.ermine.3 is unable to find
ldap's dependencies.
While it's possible to chase down the dependencies of all extensions
and add them to the config file it is tedious and error-prone.
A better solution is to just specify all of those libraries with
--ld_preload
switch:
[magicErmine@Fedora3]$ ld_preload=`echo /usr/lib64/php4/*.so` && ErminePro /usr/bin/php --config=config.3 --ld_preload="$ld_preload" --output=php.ermine.4
Now we copy php.ermine.4
to our Fedora 12 machine and run it:
[magicErmine@Fedora12]$ ./php.ermine.4 -v PHP 4.3.9 (cgi) (built: Oct 20 2004 14:07:20) Copyright (c) 1997-2004 The PHP Group Zend Engine v1.3.0, Copyright (c) 1998-2004 Zend Technologies
That's perfect!
Obviously php.ermine.4 will now run
(and that's a good thing),
but php, like a lot of others programs, makes use of
NSS (Network Switch Service)
libraries.
Those libraries weren't packed, so php.ermine.4
is now only running by chance.
Let's add the
--with-nss='internal'
switch.
Finally, here is the command to pack php
:
[magicErmine@Fedora3]$ ld_preload=`echo /usr/lib64/php4/*.so` && ErminePro /usr/bin/php --config=config.3 --ld_preload="$ld_preload" --with-nss='internal' --output=php.ermine.5
Now it's really perfect.