Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile PHP into Static Binary

I need to run a php script on a system with a somewhat broken PHP install. Rather than trying to workaround the issues I want to just package my code with it's own PHP binary (I can execute an executable). I want to just have a simple php binary that has all the modules I need compiled in. My general process is:

./configure --enable-static --enable-cli --disable-all

This gives me a php binary with no extensions. From here I can add the extensions I need. For example to add curl and json support

./configure --enable-static --enable-cli --disable-all --with-curl --enable-json

This seems to work well generally. My script needs libxml support for interacting with AWS. So I added --enable-libxml --enable-simplexml to the configure command. When I copy the binary to the remote machine it gets an error when trying to use the XML library that looks like:

/usr/lib/x86_64-linux-gnu/libxml2.so.2: version `LIBXML2_2.9.0' not found

Obviously it is dynamically linking to libxml2. I take this to mean that while the PHP extension is statically compiled into PHP, the library that the PHP extension is using is not. Running ldd confirms this:

$ ldd sapi/cli/php
linux-vdso.so.1 =>  (0x00007fff05cf3000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f3c69f82000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f3c69d68000)
libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f3c69afc000)
librt.so.1 => /lib64/librt.so.1 (0x00007f3c698f4000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3c695ed000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f3c693e8000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f3c691cf000)
libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f3c68e66000)
libz.so.1 => /lib64/libz.so.1 (0x00007f3c68c4f000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3c68890000)
libfreebl3.so => /lib64/libfreebl3.so (0x00007f3c6860f000)
libidn.so.11 => /lib64/libidn.so.11 (0x00007f3c683db000)
libssh2.so.1 => /lib64/libssh2.so.1 (0x00007f3c681b1000)
libssl3.so => /lib64/libssl3.so (0x00007f3c67f72000)
libsmime3.so => /lib64/libsmime3.so (0x00007f3c67d44000)
libnss3.so => /lib64/libnss3.so (0x00007f3c679fc000)
libnssutil3.so => /lib64/libnssutil3.so (0x00007f3c677d0000)
libplds4.so => /lib64/libplds4.so (0x00007f3c675cb000)
libplc4.so => /lib64/libplc4.so (0x00007f3c673c6000)
libnspr4.so => /lib64/libnspr4.so (0x00007f3c67188000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3c66f6a000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f3c66d20000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f3c66a40000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f3c6680a000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f3c66606000)
liblber-2.4.so.2 => /lib64/liblber-2.4.so.2 (0x00007f3c663f7000)
libldap-2.4.so.2 => /lib64/libldap-2.4.so.2 (0x00007f3c661a4000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3c6a1d7000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f3c65f7f000)
libssl.so.10 => /lib64/libssl.so.10 (0x00007f3c65d12000)
libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f3c6592b000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f3c6571c000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f3c65518000)
libsasl2.so.3 => /lib64/libsasl2.so.3 (0x00007f3c652fa000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f3c650d6000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f3c64e6f000)

As you can see there are many libraries that are dynamically linked to my php binary. I am guessing it was generally working because my target system had a lot of these same libraries but not the libxml library.

So my question is, how do I make a completely static binary with no dependencies on shared libraries. I realize this will make my executable bigger but it would also mean I can package my php executable with the code and it will work on any 64-bit linux machine.

like image 904
Eric Anderson Avatar asked Jun 11 '14 22:06

Eric Anderson


1 Answers

I have found a solution although it's a bit messier than I would like. I am leaving the libxml as a shared object and just including it with my code package and using the LD_LIBRARY_PATH environment variable so that it loads my shared library objects instead of the ones installed on the system.

Ideally I would like just a single binary file but this solution works. It also has the slight advantage of using the system libraries if those are suitable (i.e. my code package doesn't have to include all the shared libraries). But I would still be interested in knowing if there is a way to compile a completely static php binary.

like image 88
Eric Anderson Avatar answered Nov 17 '22 12:11

Eric Anderson