Okay so here is the other solution I mentionned in my previous answer, it's more tricky, but should always work on systems with GLIBC>=2.12 and GLIBCXX>=3.4.13.
In my case it was on a CentOS 6.7, but it's also fine for Ubuntu 12.04.
We're going to need a version of gcc that supports c++11, either on another machine or an isolated install; but not for the moment.
What we're gonna do here is edit the _pywrap_tensorflow.so binary in order to 'weakify' its libc and libstdc++ dependencies, so that ld accepts to link the stubs we're gonna make. Then we'll make those stubs for the missing symbols, and finally we're gonna pre-load all of this when running python.
First of all, I want to thank James for his great article ( http://www.lightofdawn.org/wiki/wiki.cgi/NewAppsOnOldGlibc ) and precious advices, I couldn't have made it without him.
So let's start by weakifying the dependencies, it's just about replacing the right bytes in _pywrap_tensorflow.so. Please note that this step only works for the current version of tensorflow (0.6.0). So if its not done already create and activate your virtualenv if you have one (if you're not admin virtualenv is a solution, another is to add --user
flag to pip command), and install tensorflow 0.6.0 (replace cpu by gpu in the url if you want the gpu version) :
pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.6.0-cp27-none-linux_x86_64.whl
And let's weakify all the annoying dependencies, here is the command for the cpu version of tensorflow:
TENSORFLOW_DIR=`python -c "import imp; print(imp.find_module('tensorflow')[1])"`
for addr in 0xC6A93C 0xC6A99C 0xC6A9EC 0xC6AA0C 0xC6AA1C 0xC6AA3C; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/python/_pywrap_tensorflow.so bs=1 seek=$((addr)) ; done
And here is the gpu one (run only the correct one or you'll corrupt the binary):
TENSORFLOW_DIR=`python -c "import imp; print(imp.find_module('tensorflow')[1])"`
for addr in 0xDC5EA4 0xDC5F04 0xDC5F54 0xDC5F74 0xDC5F84 0xDC5FA4; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/python/_pywrap_tensorflow.so bs=1 seek=$((addr)) ; done
You can check it with:
readelf -V ${TENSORFLOW_DIR}/python/_pywrap_tensorflow.so
Have a look at the article if you want to understand what's going on here.
Now we're gonna make the stubs for the missing libc symbols:
mkdir ~/my_stubs
cd ~/my_stubs
MYSTUBS=~/my_stubs
printf "#include <time.h>\n#include <string.h>\nvoid* memcpy(void *dest, const void *src, size_t n) {\nreturn memmove(dest, src, n);\n}\nint clock_gettime(clockid_t clk_id, struct timespec *tp) {\nreturn clock_gettime(clk_id, tp);\n}" > mylibc.c
gcc -s -shared -o mylibc.so -fPIC -fno-builtin mylibc.c
You need to perform that step on the machine with the missing dependencies (or machine with similar versions of standard libraries (in a cluster for example)).
Now we're gonna probably change of machine since we need a gcc that supports c++11, and it is probably not on the machine that lacks all the dependencies (or you can use an isolated install of a recent gcc). In the following I assume we're still in ~/my_stubs
and somehow you share your home accross the machines, otherwise you'll just have to copy the .so files we're gonna generate when it's done.
So, one stub that we can do for libstdc++, and for the remaining missing ones we're going to compile them from gcc source (it might take some time to clone the repository):
printf "#include <functional>\nvoid std::__throw_bad_function_call(void) {\nexit(1);\n}" > bad_function.cc
gcc -std=c++11 -s -shared -o bad_function.so -fPIC -fno-builtin bad_function.cc
git clone https://github.com/gcc-mirror/gcc.git
cd gcc
mkdir my_include
mkdir my_include/ext
cp libstdc++-v3/include/ext/aligned_buffer.h my_include/ext
gcc -I$PWD/my_include -std=c++11 -fpermissive -s -shared -o $MYSTUBS/hashtable.so -fPIC -fno-builtin libstdc++-v3/src/c++11/hashtable_c++0x.cc
gcc -std=c++11 -fpermissive -s -shared -o $MYSTUBS/chrono.so -fPIC -fno-builtin libstdc++-v3/src/c++11/chrono.cc
gcc -std=c++11 -fpermissive -s -shared -o $MYSTUBS/random.so -fPIC -fno-builtin libstdc++-v3/src/c++11/random.cc
gcc -std=c++11 -fpermissive -s -shared -o $MYSTUBS/hash_bytes.so -fPIC -fno-builtin ./libstdc++-v3/libsupc++/hash_bytes.cc
And that's it! You can now run a tensorflow python script by preloading all our shared libraries (and your local libstdc++):
LIBSTDCPP=`ldconfig -p | grep libstdc++.so.6 | grep 64 | cut -d' ' -f4` #For 64bit machines
LD_PRELOAD="$MYSTUBS/mylibc.so:$MYSTUBS/random.so:$MYSTUBS/hash_bytes.so:$MYSTUBS/chrono.so:$MYSTUBS/hashtable.so:$MYSTUBS/bad_function.so:$LIBSTDCPP" python ${TENSORFLOW_DIR}/models/image/mnist/convolutional.py
:)