diff mbox series

Support static-only builds

Message ID 20211111164229.9711-1-hi@alyssa.is (mailing list archive)
State Superseded
Headers show
Series Support static-only builds | expand

Commit Message

Alyssa Ross Nov. 11, 2021, 4:42 p.m. UTC
Sometimes it's useful to have a static-only toolchain.  This can be
due to targetting some weird embedded platform, or it can be because
it ensures that no dynamic libraries are sneaking into a system that's
supposed to be 100% static due to non-cooperative build systems.  Most
build systems support static-only builds, e.g. autoconf provides a
--disable-shared configure option.

libselinux's custom make-based build system did not support such an
option, so here I've added one.  Apart from the obvious changes, I had
to make the utilities that use libpcre link against it manually,
because that can't be inferred from the static libselinux.  For
downstream users of libselinux using pkg-config, this shouldn't be a
problem, because libselinux.pc already includes the Requires.private
line that specifies libpcre should be linked against as well.

Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
 libselinux/src/Makefile   | 11 ++++++++---
 libselinux/utils/Makefile |  6 +++++-
 libsepol/src/Makefile     | 11 ++++++++---
 3 files changed, 21 insertions(+), 7 deletions(-)

Comments

Nicolas Iooss Nov. 11, 2021, 10:37 p.m. UTC | #1
On Thu, Nov 11, 2021 at 5:42 PM Alyssa Ross <hi@alyssa.is> wrote:
>
> Sometimes it's useful to have a static-only toolchain.  This can be
> due to targetting some weird embedded platform, or it can be because
> it ensures that no dynamic libraries are sneaking into a system that's
> supposed to be 100% static due to non-cooperative build systems.  Most
> build systems support static-only builds, e.g. autoconf provides a
> --disable-shared configure option.
>
> libselinux's custom make-based build system did not support such an
> option, so here I've added one.  Apart from the obvious changes, I had
> to make the utilities that use libpcre link against it manually,
> because that can't be inferred from the static libselinux.  For
> downstream users of libselinux using pkg-config, this shouldn't be a
> problem, because libselinux.pc already includes the Requires.private
> line that specifies libpcre should be linked against as well.
>
> Signed-off-by: Alyssa Ross <hi@alyssa.is>

Hello,

Thanks for your patch. It is interesting (as a maintainer) to see that
some SELinux users are still interested in having the static
libraries, as in the past there were messages about users who only
wanted the .so on their systems, if I remember correctly.

Your patch looks right, except for one detail (which I put inline).
Nevertheless I am wondering about how future changes will not break
your use-case and I am thinking of adding a "DISABLE_SHARED=y"
configuration to our Continuous Integration system. More precisely it
would be nice to have something similar to what is currently done to
test various build configurations in
https://github.com/SELinuxProject/selinux/blob/3.3/.github/workflows/run_tests.yml#L84-L94
. Currently when I try to test it, it fails when linking
libsemanage.so:

/usr/bin/ld: /destdir/usr/lib/libselinux.a(seusers.o): warning:
relocation against `stderr@@GLIBC_2.2.5' in read-only section `.text'
/usr/bin/ld: /destdir/usr/lib/libselinux.a(seusers.o): relocation
R_X86_64_PC32 against symbol `stderr@@GLIBC_2.2.5' can not be used
when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value

This build failure is normal, as the files in libselinux.a are not
compiled with -fPIC and cannot be integrated in libsemanage.so. Did
you also modify libsemanage (and other tools) to also use the static
libraries?

This failure also happens when linking the Python bindings (with "make
install-pywrap"). Are you using bindings to Python or Ruby in your
project?

> ---
>  libselinux/src/Makefile   | 11 ++++++++---
>  libselinux/utils/Makefile |  6 +++++-
>  libsepol/src/Makefile     | 11 ++++++++---
>  3 files changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
> index 52c40f01..814012e1 100644
> --- a/libselinux/src/Makefile
> +++ b/libselinux/src/Makefile
> @@ -136,7 +136,10 @@ endif
>
>  SWIGRUBY = swig -Wall -ruby -o $(SWIGRUBYCOUT) -outdir ./ $(DISABLE_FLAGS)
>
> -all: $(LIBA) $(LIBSO) $(LIBPC)
> +all: $(LIBA) $(LIBPC)
> +ifneq ($(DISABLE_SHARED),y)
> +all: $(LIBSO)
> +endif
>
>  pywrap: all selinuxswig_python_exception.i
>         CFLAGS="$(CFLAGS) $(SWIG_CFLAGS)" $(PYTHON) setup.py build_ext
> @@ -175,11 +178,13 @@ $(SWIGRUBYCOUT): $(SWIGRUBYIF)
>  install: all
>         test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR)
>         install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR)
> -       test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
> -       install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
>         test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig
>         install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig
> +ifneq ($(DISABLE_SHARED),y)
> +       test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
> +       install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
>         ln -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET)
> +endif
>
>  install-pywrap: pywrap
>         $(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` $(PYTHON_SETUP_ARGS)
> diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile
> index 36816155..12d028df 100644
> --- a/libselinux/utils/Makefile
> +++ b/libselinux/utils/Makefile
> @@ -52,7 +52,11 @@ else
>  TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
>  endif
>
> -sefcontext_compile: LDLIBS += ../src/libselinux.a $(PCRE_LDLIBS) -lsepol
> +PCRE_USERS = matchpathcon sefcontext_compile selabel_digest \
> +       selabel_get_digests_all_partial_matches selabel_lookup \
> +       selabel_lookup_best_match selabel_partial_match
> +$(PCRE_USERS): LDLIBS += $(PCRE_LDLIBS)
> +sefcontext_compile: LDLIBS += ../src/libselinux.a -lsepol

This makes our CI complain because -lpcre needs to be put after
libselinux.a when linking sefcontext_compile. Here the linker
complains with these messages
(https://github.com/fishilico/selinux/runs/4183433352?check_suite_focus=true#step:9:401):

/usr/bin/ld: /tmp/destdir/usr/lib/libselinux.so: undefined reference
to symbol 'pcre_fullinfo'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpcre.so:
error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [<builtin>: sefcontext_compile] Error 1

When I put the "sefcontext_compile:..." before the new
"$(PCRE_USERS):..." line, this issue is fixed. Could you send a new
version with this change?

Thanks,
Nicolas

>  all: $(TARGETS)
>
> diff --git a/libsepol/src/Makefile b/libsepol/src/Makefile
> index dc8b1773..a3623635 100644
> --- a/libsepol/src/Makefile
> +++ b/libsepol/src/Makefile
> @@ -39,7 +39,10 @@ LDFLAGS += -undefined dynamic_lookup
>  LN=gln
>  endif
>
> -all: $(LIBA) $(LIBSO) $(LIBPC)
> +all: $(LIBA) $(LIBPC)
> +ifneq ($(DISABLE_SHARED),y)
> +all: $(LIBSO)
> +endif
>
>
>  $(LIBA):  $(OBJS)
> @@ -81,11 +84,13 @@ endif
>  install: all
>         test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR)
>         install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR)
> -       test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
> -       install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
>         test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig
>         install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig
> +ifneq ($(DISABLE_SHARED),y)
> +       test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
> +       install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
>         $(LN) -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET)
> +endif
>
>  relabel:
>         /sbin/restorecon $(DESTDIR)$(SHLIBDIR)/$(LIBSO)
> --
> 2.33.0
>
Alyssa Ross Nov. 13, 2021, 1:52 p.m. UTC | #2
Nicolas Iooss <nicolas.iooss@m4x.org> writes:

> On Thu, Nov 11, 2021 at 5:42 PM Alyssa Ross <hi@alyssa.is> wrote:
>>
>> Sometimes it's useful to have a static-only toolchain.  This can be
>> due to targetting some weird embedded platform, or it can be because
>> it ensures that no dynamic libraries are sneaking into a system that's
>> supposed to be 100% static due to non-cooperative build systems.  Most
>> build systems support static-only builds, e.g. autoconf provides a
>> --disable-shared configure option.
>>
>> libselinux's custom make-based build system did not support such an
>> option, so here I've added one.  Apart from the obvious changes, I had
>> to make the utilities that use libpcre link against it manually,
>> because that can't be inferred from the static libselinux.  For
>> downstream users of libselinux using pkg-config, this shouldn't be a
>> problem, because libselinux.pc already includes the Requires.private
>> line that specifies libpcre should be linked against as well.
>>
>> Signed-off-by: Alyssa Ross <hi@alyssa.is>
>
> Hello,
>
> Thanks for your patch. It is interesting (as a maintainer) to see that
> some SELinux users are still interested in having the static
> libraries, as in the past there were messages about users who only
> wanted the .so on their systems, if I remember correctly.
>
> Your patch looks right, except for one detail (which I put inline).
> Nevertheless I am wondering about how future changes will not break
> your use-case and I am thinking of adding a "DISABLE_SHARED=y"
> configuration to our Continuous Integration system. More precisely it
> would be nice to have something similar to what is currently done to
> test various build configurations in
> https://github.com/SELinuxProject/selinux/blob/3.3/.github/workflows/run_tests.yml#L84-L94
> . Currently when I try to test it, it fails when linking
> libsemanage.so:
>
> /usr/bin/ld: /destdir/usr/lib/libselinux.a(seusers.o): warning:
> relocation against `stderr@@GLIBC_2.2.5' in read-only section `.text'
> /usr/bin/ld: /destdir/usr/lib/libselinux.a(seusers.o): relocation
> R_X86_64_PC32 against symbol `stderr@@GLIBC_2.2.5' can not be used
> when making a shared object; recompile with -fPIC
> /usr/bin/ld: final link failed: bad value
>
> This build failure is normal, as the files in libselinux.a are not
> compiled with -fPIC and cannot be integrated in libsemanage.so. Did
> you also modify libsemanage (and other tools) to also use the static
> libraries?

My purposes didn't require libsemanage, so I hadn't tried, but indeed I
wasn't able to build it.  The next version of my patch will add
DISABLE_SHARED support to libsemanage and policycoreutils as well.  I've
now also tested checkpolicy and semodule-utils, which worked without any
further changes.

> This failure also happens when linking the Python bindings (with "make
> install-pywrap"). Are you using bindings to Python or Ruby in your
> project?

No, and I'd expect that it wouldn't be possible, since I assume the
bindings have to be shared libraries so they can be dlopened by the
language runtimes?  Maybe it would be possible to link static binding
libraries with the interpreter, but I've never heard of anybody doing
that…
diff mbox series

Patch

diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index 52c40f01..814012e1 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -136,7 +136,10 @@  endif
 
 SWIGRUBY = swig -Wall -ruby -o $(SWIGRUBYCOUT) -outdir ./ $(DISABLE_FLAGS)
 
-all: $(LIBA) $(LIBSO) $(LIBPC)
+all: $(LIBA) $(LIBPC)
+ifneq ($(DISABLE_SHARED),y)
+all: $(LIBSO)
+endif
 
 pywrap: all selinuxswig_python_exception.i
 	CFLAGS="$(CFLAGS) $(SWIG_CFLAGS)" $(PYTHON) setup.py build_ext
@@ -175,11 +178,13 @@  $(SWIGRUBYCOUT): $(SWIGRUBYIF)
 install: all 
 	test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR)
 	install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR)
-	test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
-	install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
 	test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig
 	install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig
+ifneq ($(DISABLE_SHARED),y)
+	test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
+	install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
 	ln -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET)
+endif
 
 install-pywrap: pywrap
 	$(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` $(PYTHON_SETUP_ARGS)
diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile
index 36816155..12d028df 100644
--- a/libselinux/utils/Makefile
+++ b/libselinux/utils/Makefile
@@ -52,7 +52,11 @@  else
 TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c)))
 endif
 
-sefcontext_compile: LDLIBS += ../src/libselinux.a $(PCRE_LDLIBS) -lsepol
+PCRE_USERS = matchpathcon sefcontext_compile selabel_digest \
+	selabel_get_digests_all_partial_matches selabel_lookup \
+	selabel_lookup_best_match selabel_partial_match
+$(PCRE_USERS): LDLIBS += $(PCRE_LDLIBS)
+sefcontext_compile: LDLIBS += ../src/libselinux.a -lsepol
 
 all: $(TARGETS)
 
diff --git a/libsepol/src/Makefile b/libsepol/src/Makefile
index dc8b1773..a3623635 100644
--- a/libsepol/src/Makefile
+++ b/libsepol/src/Makefile
@@ -39,7 +39,10 @@  LDFLAGS += -undefined dynamic_lookup
 LN=gln
 endif
 
-all: $(LIBA) $(LIBSO) $(LIBPC)
+all: $(LIBA) $(LIBPC)
+ifneq ($(DISABLE_SHARED),y)
+all: $(LIBSO)
+endif
 
 
 $(LIBA):  $(OBJS)
@@ -81,11 +84,13 @@  endif
 install: all
 	test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR)
 	install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR)
-	test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
-	install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
 	test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig
 	install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig
+ifneq ($(DISABLE_SHARED),y)
+	test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR)
+	install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR)
 	$(LN) -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET)
+endif
 
 relabel:
 	/sbin/restorecon $(DESTDIR)$(SHLIBDIR)/$(LIBSO)