coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: static build


From: Assaf Gordon
Subject: Re: static build
Date: Sat, 6 Apr 2019 22:33:29 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1

Hello,

On 2019-04-06 9:15 a.m., Alex Zimnitsky wrote:
I would really appreciate if coreutils could be built statically
with something like bash's --enable-static-link parameter co configure.

There is no single switch like bash's, but I can offer few methods
to build static coreutils binaries.

First,
I assume you are trying to build on a GNU/Linux system,
with glibc and gcc.
That is because in other configurations (non-glibc or non-linux),
there are actually less complications (due to less detected features),
and this typically "just works":

     ./configure LDFLAGS="-static"
     make


Second,
Understand that on most modern GNU/Linux systems (using dynalic glibc),
static building is tricky depending on which functions you use.
If your program use getpwnam(3) and similar functions, they will still
require the dynamic glibc during run time (due to the NSS mechanism).

Older Debians and Redhats provided a "glibc-static" package,
which allowed static binaries easily, but this is not available
any longer.

The result is that few coreutils programs will run at reduced
features when built statically, and executed on a different system.
Examples:
  "id" and "groups" will print numeric UID/GID, but not names.
  "chown" will accept numeric UID/GID, but will fail when given names.



Third,
The "coreutils" package includes a program named stdbuf(1) that
on linux with GCC builds a shared library as a dependency.
Building this library fails with static builds, but there
is currently no user-friendly way to disable it.
https://lists.gnu.org/archive/html/coreutils/2010-07/msg00010.html

I show a Makefile hack below to disable it.



Fourth,
On GNU/Linux coreutils automatically detects many supporting libraries
(eg. xattr, selinux, libcap, etc.). If these libraries are only
available as shared-libraries (and not static libraries), building will fail.
You can explicitly disable these libraries (shown below),
or rebuild them with static components (which is beyond the scope of this email).

----

Having said all that, here's what worked for me:

1.
On Debian Stretch 9.8, gcc 6.3.0-18+deb9u1, coreutils 8.31,
the following works:

    ./configure LDFLAGS="-static" --disable-xattr --disable-libcap \
                --disable-libsmack --without-selinux --without-gmp
    make

Note that you'll see warnings such as these (as explained in item 2 above):
----
  CCLD     src/groups
src/src_ginstall-install.o: In function `get_ids':
/home/gordon/projects/coreutils/src/install.c:602: warning: Using 'getgrnam' in statically linked applications requires at runtime the shared libraries from the glibc
 version used for linking
src/src_ginstall-install.o: In function `have_same_content':
/home/gordon/projects/coreutils/src/install.c:154: warning: Using 'endgrent' in statically linked applications requires at runtime the shared libraries from the glibc
 version used for linking
src/src_ginstall-install.o: In function `need_copy':
/home/gordon/projects/coreutils/src/install.c:220: warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc
 version used for linking
----

But the binaries will be built successfully (and will be static).
If you run them on the same system, they will automatically find
the dynamic glibc, load it, and will be able to use the getpwnam(3)
family of functions.

If you copy them to a different Linux-based system (not necessarily glibc system), they will still work, except any user/group name-related functionality, e.g. on an Alpine-Linux system with user miles having UID=1000:

  $ ./groups
  ./groups: cannot find name for group ID 1000
  1000

  $ ./chown miles 1
  ./chown: invalid user: 'miles'

  $ ./chown 1000 1
  [[ works ]]



2.
On same Debian 9.8 machine,
the "musl" libc can be used to build fully static binaries ( http://www.musl-libc.org/ ).
A typical installation of "musl" on a GNU/Linux system provides
a compiler-wrapper script called "musl-gcc" which can be used
as $CC .


A typical scenario will be (YMMV):

    wget http://www.musl-libc.org/releases/musl-1.1.21.tar.gz
    tar -xzf musl-1.1.21.tar.gz
    cd musl*
    ./configure
    make
    make install   # into /usr/local/musl

    export PATH=/usr/local/musl/bin:$PATH
    musl-gcc -v  # sanity check

    wget https://ftp.gnu.org/gnu/coreutils/coreutils-8.31.tar.xz
    tar -xf coreutils-8.31.tar.xz
    cd coreutils-8.31/
    ./configure CC=musl-gcc LDFLAGS="-static"
    make

This *almost* works, but will fail to link "libstdbuf" (as explained
in item 3 above).
It is easy to to modify the Makefile to simply disable building that
library:

    sed -i '/pkglibexec_PROGRAMS/s|src/libstdbuf.so||' Makefile
    make

And all the binaries will be built successfully, as static binaries.



3.
On Alpine Linux 3.9.2 (which uses "musl" libc natively, not glibc),
the following "just works":

     ./configure CC=clang LDFLAGS="-static"
     make



4.
In coreutils version 8.23 (released 2014) a new feature was added
to create a single binary executable (conceptually similar to busybox).
This could be useful for your situation.
To use it, add "--enable-single-binary=symlinks" or "--enable-single-binary=shebangs" to the "./configure" invocations above.

The result will be a "./src/coreutils" static binary,
which will act as different coreutils programs based on invocation.

see https://git.savannah.gnu.org/cgit/coreutils.git/diff/NEWS?id=71e2ea773414b2316bbe6b803b9a52c38d3752e8 .


---

Hope this helps,
regards,
 - assaf














reply via email to

[Prev in Thread] Current Thread [Next in Thread]