4

I have been attempting to create a statically linked version of vips but have been unable to. Is it possible to create a statically linked vips command?

The platform I am compiling on is Ubuntu 16.04.

The make command I am running:

 make LDFLAGS=-all-static

I am not configuring it to use python or imagemagick, (those show "no" in the config output). The error I am getting is:

/usr/bin/ld: cannot find -lgdk_pixbuf-2.0
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libgio-2.0.a(libgio_2_0_la-glocalfileinfo.o): In function `lookup_gid_name':
(.text+0x11d7): warning: Using 'getgrgid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libgio-2.0.a(libgio_2_0_la-glocalvfs.o): In function `g_local_vfs_parse_name':
(.text+0x1cd): warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libglib-2.0.a(libglib_2_0_la-gutils.o): In function `g_get_user_database_entry':
(.text+0x249): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libglib-2.0.a(libglib_2_0_la-gutils.o): In function `g_get_user_database_entry':
(.text+0xcf): warning: Using 'getpwnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libgio-2.0.a(libgio_2_0_la-glocalfileinfo.o): In function `lookup_uid_data':
(.text+0x1054): warning: Using 'getpwuid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libxml2.a(nanohttp.o): In function `xmlNanoHTTPConnectHost':
(.text+0x924): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libxml2.a(nanohttp.o): In function `xmlNanoHTTPConnectHost':
(.text+0x9f4): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libgio-2.0.a(libgio_2_0_la-gnetworkaddress.o): In function `g_network_address_parse':
(.text+0xc39): warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libgio-2.0.a(libgio_2_0_la-gnetworkaddress.o): In function `g_network_address_parse':
(.text+0xc4e): warning: Using 'endservent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
collect2: error: ld returned 1 exit status
Makefile:597: recipe for target 'vips' failed
make[2]: *** [vips] Error 1
make[2]: Leaving directory '/usr/local/src/vips-8.4.1/tools'
Makefile:631: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/usr/local/src/vips-8.4.1'
Makefile:536: recipe for target 'all' failed
make: *** [all] Error 2

From what I've found on, for example here: Create statically-linked binary that uses getaddrinfo? is that this is an issue with libnss. But in the ./configure --help output there is no --enable-static-flag. Even so I tried that and it didn't fix my problem.

The libraries I am linking against (according to the config output, I've truncated it):

build radiance support:         yes
build analyze support:          yes
build PPM support:          yes
use fftw3 for FFT:          yes
accelerate loops with orc:      yes
ICC profile support with lcms:      yes (lcms2)
SVG import with librsvg-2.0:        yes
zlib:                   yes
file import/export with libwebp:    yes
file import/export with libpng:     yes (pkg-config libpng >= 1.2.9)
file import/export with libtiff:    yes (pkg-config libtiff-4)
file import/export with giflib:     yes (found by search)
file import/export with libjpeg:    yes
use libexif to load/save JPEG metadata: yes

Is there a particular library I am linking against that is causing the problem?

Community
  • 1
  • 1
SjB
  • 213
  • 4
  • 16

2 Answers2

2

After failing to convince the build mechanism to statically link, I was able to successfully create a working static vips executable with staticx, after reporting an issue to staticx and seeing that it was fixed. See here for how I'm building.

Just in case that link of mines dies in the future, here are the relevant parts:

RUN curl -sL https://github.com/libvips/libvips/releases/download/v8.9.2/vips-8.9.2.tar.gz | tar -xz -f- --strip-components=1 -C .

# TODO: Add --disable-deprecated
# Blocked by https://github.com/libvips/libvips/pull/1593

# XXX: -static doesn't work here, I'm using staticx to make the final vips binary static.
RUN CFLAGS="-O3 -flto -pipe" CXXFLAGS="-O3 -flto -pipe" \
    ./configure \
        --disable-shared \
        --disable-static \
        --disable-dependency-tracking

# This is the fastest easiest way I found to compile the
# CLI as fast as possible. You can probably get more optimal,
# but it'd be a lot harder wrestling autotools.
RUN cd libvips \
    && make -j"$(nproc)"
RUN cd tools \
    && make -j"$(nproc)" vips

RUN cd tools \
    && staticx vips ../vips

Since configure automatically feature-detects, here are the Debian 10 (June 22) packages I installed:

    libglib2.0-dev \
    libexpat1-dev \
    libjpeg-dev \
    libpng-dev \
    libimagequant-dev \
    libexif-dev \
    liborc-0.4-dev

It weighs 3.3M, which is fairly impressive and a heck of a lot smaller than distribution packages, which is why I set out to do this in the first place.

$ file vips-glibc-gcc
vips-glibc-gcc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
$ ls -lah vips-glibc-gcc
-rwxr-xr-x 1 josh josh 3.3M Jun 23 02:51 vips-glibc-gcc
JoshuaRLi
  • 1,665
  • 14
  • 23
1

I tried like this:

$ CFLAGS="-static" CXXFLAGS="-static" ./configure --prefix=/home/john/vips --without-python --without-magick

And it seems to work:

$ ls ~/vips/lib
girepository-1.0  libvipsCC.a   libvips-cpp.a   libvips.la  python2.7
libvips.a         libvipsCC.la  libvips-cpp.la  pkgconfig
$ which vips
/home/john/vips/bin/vips
$ ls -l ~/vips/bin/vips
-rwxr-xr-x 1 john john 6373864 Sep 27 13:16 /home/john/vips/bin/vips
$ vips invert /data/john/pics/k2.jpg x.jpg
$ eog x.jpg

I've not tested it much though, and I suspect it's not very static. If you run ldd on the vips binary, for example, you get a long list. True static binaries do not really exist any more.

Why do you want a static binary? If it's to ease distribution, things like flatpack and snappy might be better. You can also sort-of make your own --- for example, vips comes with a simple wrapper script which can make the shared binary relocatable.

jcupitt
  • 10,213
  • 2
  • 23
  • 39
  • I was hoping to deploy it in a minimalist docker container that also has static versions of ffmpeg and ffprobe. I guess I just wasn't sure why an image conversion program needs calls like getservbyname so was hoping there was some dependency I could drop. – SjB Sep 27 '16 at 14:41
  • vips uses glib to help portability, and glib has a lot of stuff in. You could try making your own glib with some things removed, it might help. I think the static binary ^^^^ would work in any 16.04 install, which is something, but it probably wouldn't work on a very minimal linux install. OpenWRT have a libvips package and that's very minimal, maybe you could adapt that? – jcupitt Sep 27 '16 at 15:24
  • I think using something like dietlibc might work but haven't had a chance to re-visit that yet. – SjB Sep 28 '16 at 13:57