diff mbox series

[v4,01/13] new recipe : host-systemd

Message ID 20191212075400.1499536-2-jeremy.rosen@smile.fr
State Superseded
Headers show
Series use host-systemd to enable units | expand

Commit Message

Jérémy ROSEN Dec. 12, 2019, 7:53 a.m. UTC
Add the infrastructure to build the host version of systemd
* disable all optional features, they can be re-added when needed
* systemd has creative way of dealing with cross compile
  we build a "normal" host systemd, but install it in $HOST_DIR
  we use systemctl --root to correctly act on TARGET_DIR
* we need to adjust RPATH using patchelf because meson can't do it
  correctly by itsel

Signed-off-by: Jérémy Rosen <jeremy.rosen@smile.fr>
---
 package/Config.in.host         |  1 +
 package/systemd/Config.in      |  1 -
 package/systemd/Config.in.host |  3 ++
 package/systemd/systemd.mk     | 98 ++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 package/systemd/Config.in.host

Comments

Thomas Petazzoni Dec. 12, 2019, 10:19 a.m. UTC | #1
Hello,

Thanks for this work, very useful!

On Thu, 12 Dec 2019 08:53:48 +0100
Jérémy Rosen <jeremy.rosen@smile.fr> wrote:

> diff --git a/package/systemd/Config.in b/package/systemd/Config.in
> index 8f1d6fc0c0..81761b33a4 100644
> --- a/package/systemd/Config.in
> +++ b/package/systemd/Config.in
> @@ -199,7 +199,6 @@ config BR2_PACKAGE_SYSTEMD_HOSTNAMED
>  config BR2_PACKAGE_SYSTEMD_HWDB
>  	bool "enable hwdb installation"
>  	default y
> -	select BR2_PACKAGE_HOST_EUDEV # for udevadm, during target-finalize
>  	help
>  	  Enables hardware database installation to /usr/lib/udev/hwdb.d
>  
> diff --git a/package/systemd/Config.in.host b/package/systemd/Config.in.host
> new file mode 100644
> index 0000000000..219f24239e
> --- /dev/null
> +++ b/package/systemd/Config.in.host
> @@ -0,0 +1,3 @@
> +# Select this if you need host systemd tools (e.g. systemctl)
> +config BR2_PACKAGE_HOST_SYSTEMD
> +	bool
> diff --git a/package/systemd/systemd.mk b/package/systemd/systemd.mk
> index a292a7512b..ad16b58ceb 100644
> --- a/package/systemd/systemd.mk
> +++ b/package/systemd/systemd.mk
> @@ -204,6 +204,11 @@ endif
>  
>  ifeq ($(BR2_PACKAGE_SYSTEMD_HWDB),y)
>  SYSTEMD_CONF_OPTS += -Dhwdb=true
> +define SYSTEMD_BUILD_HWDB
> +	$(HOST_DIR)/bin/udevadm hwdb --update --root $(TARGET_DIR)
> +endef

I think this change could be a separate patch, no? Or is the udevadm
binary installed by host-systemd conflicting with the one installed by
host-eudev ?

Should be explained in the commit log.

> +SYSTEMD_TARGET_FINALIZE_HOOKS += SYSTEMD_BUILD_HWDB
> +
>  else
>  SYSTEMD_CONF_OPTS += -Dhwdb=false
>  endif
> @@ -551,3 +556,96 @@ SYSTEMD_CONF_ENV = $(HOST_UTF8_LOCALE_ENV)
>  SYSTEMD_NINJA_ENV = $(HOST_UTF8_LOCALE_ENV)
>  
>  $(eval $(meson-package))

We normally have both meson-package and host-meson-package macro
invocations at the end of .mk files.

> +#
> +# Host-systemd configuration
> +#
> +#Options tweaked for buildroot
> +HOST_SYSTEMD_CONF_OPTS= \
> +	-Dsplit-bin=true \
> +	-Dsplit-usr=false \
> +	--prefix=/usr \

This should really be:

	--prefix=$(HOST_DIR)

> +	--libdir=lib \
> +	--sysconfdir=/etc \
> +	--localstatedir=/var

But in fact, all these options are already passed by the
host-meson-package infrastructure. Why are you overriding them ?

> +#disable everything else

Space after #

> +HOST_SYSTEMD_CONF_OPTS+= \

Space before +=


> +HOST_SYSTEMD_DEPENDENCIES = \
> +	host-util-linux \
> +	host-patchelf \
> +	host-libcap \
> +	host-gperf
> +
> +# Fix RPATH After installation
> +# * systemd provides a install_rpath instruction to meson because the binaries need to link with
> +#   libsystemd which is not in a standard path
> +# * meson can only replace the RPATH, not append to it
> +# * the original rpatch is thus lost.

rpatch -> rpath

> +# * the original path had been tweaked by buildroot vial LD_FLAGS to add $(HOST_DIR)/lib

vial -> via

LD_FLAGS -> LDFLAGS

> +# * thus re-tweak rpath after the installation for all binaries that need it

I must admit I don't really understand what's going on here. Can't you
simply do something like this:

HOST_SYSTEMD_CONF_ENV = \
	LDFLAGS="$(HOST_LDFLAGS) -Wl,-rpath,$(HOST_DIR)/lib/systemd"

and that's it ?

> +#buildroot detects incorrect RPATH, so adding new binaries should be safe (it won't compile
> +#unless properly integrated).

Space after #, and lines are too long.

> +HOST_SYSTEMD_HOST_TOOLS = \
> +	systemd-analyze  systemd-mount systemctl udevadm
> +
> +define HOST_SYSTEMD_FIX_RPATH
> +	$(foreach f,$(HOST_SYSTEMD_HOST_TOOLS), \
> +		$(HOST_DIR)/bin/patchelf --set-rpath $(HOST_DIR)/lib:$(HOST_DIR)/lib/systemd $(HOST_DIR)/bin/$(f)
> +	)
> +endef
> +
> +HOST_SYSTEMD_POST_INSTALL_HOOKS +=  HOST_SYSTEMD_FIX_RPATH
> +HOST_SYSTEMD_NINJA_ENV = DESTDIR=$(HOST_DIR)

With the correct --prefix=$(HOST_DIR) passed by the default
host-meson-package infrastructure, this DESTDIR=$(HOST_DIR) should no
longer be necessary.

Thanks!

Thomas
Jérémy ROSEN Dec. 12, 2019, 10:35 a.m. UTC | #2
Le jeu. 12 déc. 2019 à 11:19, Thomas Petazzoni <thomas.petazzoni@bootlin.com>
a écrit :

>
> >  ifeq ($(BR2_PACKAGE_SYSTEMD_HWDB),y)
> >  SYSTEMD_CONF_OPTS += -Dhwdb=true
> > +define SYSTEMD_BUILD_HWDB
> > +     $(HOST_DIR)/bin/udevadm hwdb --update --root $(TARGET_DIR)
> > +endef
>
> I think this change could be a separate patch, no? Or is the udevadm
> binary installed by host-systemd conflicting with the one installed by
> host-eudev ?
>
> Should be explained in the commit log.
>
>
That's a matter of taste, I guess
No it doesn't conflict, i'll split in v5


> > +SYSTEMD_TARGET_FINALIZE_HOOKS += SYSTEMD_BUILD_HWDB
> > +
> >  else
> >  SYSTEMD_CONF_OPTS += -Dhwdb=false
> >  endif
> > @@ -551,3 +556,96 @@ SYSTEMD_CONF_ENV = $(HOST_UTF8_LOCALE_ENV)
> >  SYSTEMD_NINJA_ENV = $(HOST_UTF8_LOCALE_ENV)
> >
> >  $(eval $(meson-package))
>
> We normally have both meson-package and host-meson-package macro
> invocations at the end of .mk files.
>
>
Ok, I wanted to separate the host and target part clearly, but i'll follow
proper styling


> > +#
> > +# Host-systemd configuration
> > +#
> > +#Options tweaked for buildroot
> > +HOST_SYSTEMD_CONF_OPTS= \
> > +     -Dsplit-bin=true \
> > +     -Dsplit-usr=false \
> > +     --prefix=/usr \
>
> This should really be:
>
>         --prefix=$(HOST_DIR)
>
>
No... upstream does not user --prefix properly and we are force to set it
to /usr
even if HOST_DIR would make more sense.

I'll discuss this more in depth in the commit log


> > +     --libdir=lib \
> > +     --sysconfdir=/etc \
> > +     --localstatedir=/var
>
> But in fact, all these options are already passed by the
> host-meson-package infrastructure. Why are you overriding them ?
>
>
it's probably a bit overkill, but these need to be set to the same value as
the target, not the ones provided by the host
It's a bit complex to follow because upstream does not understand the
concept of cross-tool correctly so we might build
a systemctl that does the right thing for the host instead of doing the
right thing for the target


> > +#disable everything else
>
> Space after #
>
> ok

> > +HOST_SYSTEMD_CONF_OPTS+= \
>
> Space before +=
>
> ok

>
> > +HOST_SYSTEMD_DEPENDENCIES = \
> > +     host-util-linux \
> > +     host-patchelf \
> > +     host-libcap \
> > +     host-gperf
> > +
> > +# Fix RPATH After installation
> > +# * systemd provides a install_rpath instruction to meson because the
> binaries need to link with
> > +#   libsystemd which is not in a standard path
> > +# * meson can only replace the RPATH, not append to it
> > +# * the original rpatch is thus lost.
>
> rpatch -> rpath
>
>
darn me typing to fast


> > +# * the original path had been tweaked by buildroot vial LD_FLAGS to
> add $(HOST_DIR)/lib
>
> vial -> via
>
> ditto

> LD_FLAGS -> LDFLAGS
>
> > +# * thus re-tweak rpath after the installation for all binaries that
> need it
>
> I must admit I don't really understand what's going on here. Can't you
> simply do something like this:
>
> HOST_SYSTEMD_CONF_ENV = \
>         LDFLAGS="$(HOST_LDFLAGS) -Wl,-rpath,$(HOST_DIR)/lib/systemd"
>
> and that's it ?
>
>
No.. that's already what is done by host-package-meson but meson+systemd
breaks that.

Meson does not support using -rpath in LDFLAGS. It will rewrite the rpath
at the end of the
build using the information it has, but that does not include parsing the
ENV var and directly
understanding the linker flags.

Normally, everything should be alright since systemd tells meson about
libsystemd's location *
through meson conf files. meson would user systemd's instructions and
combine it with the
--prefix option to rewrite rpath correctly.

However systemd does not handle --prefix correctly (it hardcodes lots of
stuff in its build system based
on --prefix) so --prefix can either be empty or point to /usr. (this is
heavily linked to the split-usr problem)

Because of that, meson will erase our LDFLAGS provided rpath but won't
rewrite them correctly.
I have spent quite some time with Yann at Lyon looking for a way around,
and this seems the best one
until upstream deals correctly with --prefix.

I tried to be both concise and clear in my comment in the .mk (since i'm
pretty sure this is where
future contributors will stumble) but apparently i'm not there yet :)



> > +#buildroot detects incorrect RPATH, so adding new binaries should be
> safe (it won't compile
> > +#unless properly integrated).
>
> Space after #, and lines are too long.
>
> > +HOST_SYSTEMD_HOST_TOOLS = \
> > +     systemd-analyze  systemd-mount systemctl udevadm
> > +
> > +define HOST_SYSTEMD_FIX_RPATH
> > +     $(foreach f,$(HOST_SYSTEMD_HOST_TOOLS), \
> > +             $(HOST_DIR)/bin/patchelf --set-rpath
> $(HOST_DIR)/lib:$(HOST_DIR)/lib/systemd $(HOST_DIR)/bin/$(f)
> > +     )
> > +endef
> > +
> > +HOST_SYSTEMD_POST_INSTALL_HOOKS +=  HOST_SYSTEMD_FIX_RPATH
> > +HOST_SYSTEMD_NINJA_ENV = DESTDIR=$(HOST_DIR)
>
> With the correct --prefix=$(HOST_DIR) passed by the default
> host-meson-package infrastructure, this DESTDIR=$(HOST_DIR) should no
> longer be necessary.
>
>
see my comment above

Thx for the review... I'll wait a bit and send a v5 integrating all your
remarks


> Thanks!
>
> Thomas
> --
> Thomas Petazzoni, CTO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
>
Yann E. MORIN Dec. 12, 2019, 5:31 p.m. UTC | #3
Jérémy, Thomas,All,

On 2019-12-12 11:19 +0100, Thomas Petazzoni spake thusly:
> On Thu, 12 Dec 2019 08:53:48 +0100
> Jérémy Rosen <jeremy.rosen@smile.fr> wrote:
[--SNIP--]
> > diff --git a/package/systemd/systemd.mk b/package/systemd/systemd.mk
> > index a292a7512b..ad16b58ceb 100644
> > --- a/package/systemd/systemd.mk
> > +++ b/package/systemd/systemd.mk
> > @@ -204,6 +204,11 @@ endif
> >  
> >  ifeq ($(BR2_PACKAGE_SYSTEMD_HWDB),y)
> >  SYSTEMD_CONF_OPTS += -Dhwdb=true
> > +define SYSTEMD_BUILD_HWDB
> > +	$(HOST_DIR)/bin/udevadm hwdb --update --root $(TARGET_DIR)
> > +endef
> 
> I think this change could be a separate patch, no? Or is the udevadm
> binary installed by host-systemd conflicting with the one installed by
> host-eudev ?
> 
> Should be explained in the commit log.

I think this change should go in current patch 2, where systemd is made
dependent on host-systemd, which indeed installs its own udevadm which
would conflict with the one from host-eudev.

[--SNIP--]
> > +# Host-systemd configuration
> > +#
> > +#Options tweaked for buildroot
> > +HOST_SYSTEMD_CONF_OPTS= \
> > +	-Dsplit-bin=true \
> > +	-Dsplit-usr=false \
> > +	--prefix=/usr \
> 
> This should really be:
> 
> 	--prefix=$(HOST_DIR)
> 
> > +	--libdir=lib \
> > +	--sysconfdir=/etc \
> > +	--localstatedir=/var
> 
> But in fact, all these options are already passed by the
> host-meson-package infrastructure. Why are you overriding them ?
[--SNIP--]
> > +# * thus re-tweak rpath after the installation for all binaries that need it
> I must admit I don't really understand what's going on here. Can't you
> simply do something like this:
> 
> HOST_SYSTEMD_CONF_ENV = \
> 	LDFLAGS="$(HOST_LDFLAGS) -Wl,-rpath,$(HOST_DIR)/lib/systemd"
> 
> and that's it ?

For the records, here are the explanations I provided on IRC.

The first question is: why do we use --prefix=/usr ?

systemd will store its --prefix in all the executables it generates. As
such, systemctl will have a hardcoded 'prefix', where it will manipulate
and create files/symlinks in. When called natively, this is nice and
shinny.

However, for cross-setup, that does not work obviously.

So, systemd has its tools know about the 'root' directory where this
prefix should be related to. We can call systemctl --root=$(TARGET_DIR)
and systemctl wil do the links and such in there.

However, it does so by appending its known prefix to it.

So, if we were to configure host-systemd as we usually do, with
--prefix=$(HOST_DIR), then when we would call host systemctl --root=$(TARGET_DIR)
it would look for files in $(TARGET_DIR)/$(HOST_DIR), which is wrong.

Calling the host systemctl without --root is also wrong, as it would look for
files in $(HOST_DIR)

So, there is no satisfying official support for this case.

The trick then, is to configure systemd with the prefix it would expect
at runtime (on the target!), that is with /usr, but install out-of-tree.

That was it for the first part of the question: why do we use --prefix.

Now, the second question is: why do we need to muck up with the rpath
after installation?
Well, this boils down to meson (and not systemd itself). When it
installs executables, meson will handily insert whatever rpath the
package meson.build would tell it to use. systemd installs libs in
$(prefix)/lib/systemd and as a NEEDED to those libs, so it uses an RPATH
to find those libs, and meson does introduce that RPATH.
However, we Buildroot also want to insert our own RPATH, because systemd
uses util-linux' libs and libcap, so it needs our RPATH.
However, meson can not extend the RPATH from the LDFLAGS in the
environment; meson can only set the RPATH from what it knows about from
the package's meson.build.

That, in addition to the --prefix=/usr issue above, means that the
executables installed by host-systemd have an RPATH set to
/usr/lib/systemd. when we would want it to be set to
$(HOST_DIR)/lib:$(HOST_DIR)/lib/systemd

That;s what is done in the post-install hook: set the RPATH to the
appropriate values.

[--SNIP--]
> > +HOST_SYSTEMD_POST_INSTALL_HOOKS +=  HOST_SYSTEMD_FIX_RPATH
> > +HOST_SYSTEMD_NINJA_ENV = DESTDIR=$(HOST_DIR)
> With the correct --prefix=$(HOST_DIR) passed by the default
> host-meson-package infrastructure, this DESTDIR=$(HOST_DIR) should no
> longer be necessary.

Alas, this is not possible... :-(

Regards,
Yann E. MORIN.
diff mbox series

Patch

diff --git a/package/Config.in.host b/package/Config.in.host
index 758c268e00..62e860d7c3 100644
--- a/package/Config.in.host
+++ b/package/Config.in.host
@@ -70,6 +70,7 @@  menu "Host utilities"
 	source "package/squashfs/Config.in.host"
 	source "package/sunxi-tools/Config.in.host"
 	source "package/swig/Config.in.host"
+	source "package/systemd/Config.in.host"
 	source "package/tegrarcm/Config.in.host"
 	source "package/ti-cgt-pru/Config.in.host"
 	source "package/uboot-tools/Config.in.host"
diff --git a/package/systemd/Config.in b/package/systemd/Config.in
index 8f1d6fc0c0..81761b33a4 100644
--- a/package/systemd/Config.in
+++ b/package/systemd/Config.in
@@ -199,7 +199,6 @@  config BR2_PACKAGE_SYSTEMD_HOSTNAMED
 config BR2_PACKAGE_SYSTEMD_HWDB
 	bool "enable hwdb installation"
 	default y
-	select BR2_PACKAGE_HOST_EUDEV # for udevadm, during target-finalize
 	help
 	  Enables hardware database installation to /usr/lib/udev/hwdb.d
 
diff --git a/package/systemd/Config.in.host b/package/systemd/Config.in.host
new file mode 100644
index 0000000000..219f24239e
--- /dev/null
+++ b/package/systemd/Config.in.host
@@ -0,0 +1,3 @@ 
+# Select this if you need host systemd tools (e.g. systemctl)
+config BR2_PACKAGE_HOST_SYSTEMD
+	bool
diff --git a/package/systemd/systemd.mk b/package/systemd/systemd.mk
index a292a7512b..ad16b58ceb 100644
--- a/package/systemd/systemd.mk
+++ b/package/systemd/systemd.mk
@@ -204,6 +204,11 @@  endif
 
 ifeq ($(BR2_PACKAGE_SYSTEMD_HWDB),y)
 SYSTEMD_CONF_OPTS += -Dhwdb=true
+define SYSTEMD_BUILD_HWDB
+	$(HOST_DIR)/bin/udevadm hwdb --update --root $(TARGET_DIR)
+endef
+SYSTEMD_TARGET_FINALIZE_HOOKS += SYSTEMD_BUILD_HWDB
+
 else
 SYSTEMD_CONF_OPTS += -Dhwdb=false
 endif
@@ -551,3 +556,96 @@  SYSTEMD_CONF_ENV = $(HOST_UTF8_LOCALE_ENV)
 SYSTEMD_NINJA_ENV = $(HOST_UTF8_LOCALE_ENV)
 
 $(eval $(meson-package))
+
+#
+# Host-systemd configuration
+#
+#Options tweaked for buildroot
+HOST_SYSTEMD_CONF_OPTS= \
+	-Dsplit-bin=true \
+	-Dsplit-usr=false \
+	--prefix=/usr \
+	--libdir=lib \
+	--sysconfdir=/etc \
+	--localstatedir=/var
+
+#disable everything else
+HOST_SYSTEMD_CONF_OPTS+= \
+	-Dutmp=false \
+	-Dhibernate=false \
+	-Dldconfig=false \
+	-Dresolve=false \
+	-Defi=false \
+	-Dtpm=false \
+	-Denvironment-d=false \
+	-Dbinfmt=false \
+	-Dcoredump=false \
+	-Dpstore=false \
+	-Dlogind=false \
+	-Dhostnamed=false \
+	-Dlocaled=false \
+	-Dmachined=false \
+	-Dportabled=false \
+	-Dnetworkd=false \
+	-Dtimedated=false \
+	-Dtimesyncd=false \
+	-Dremote=false \
+	-Dcreate-log-dirs=false \
+	-Dnss-myhostname=false \
+	-Dnss-mymachines=false \
+	-Dnss-resolve=false \
+	-Dnss-systemd=false \
+	-Dfirstboot=false \
+	-Drandomseed=false \
+	-Dbacklight=false \
+	-Dvconsole=false \
+	-Dquotacheck=false \
+	-Dsysusers=false \
+	-Dtmpfiles=false \
+	-Dimportd=false \
+	-Dhwdb=false \
+	-Drfkill=false \
+	-Dman=false \
+	-Dhtml=false \
+	-Dsmack=false \
+	-Dpolkit=false \
+	-Dblkid=false \
+	-Didn=false \
+	-Dadm-group=false \
+	-Dwheel-group=false \
+	-Dzlib=false \
+	-Dgshadow=false \
+	-Dima=false \
+	-Dtests=false \
+	-Dglib=false \
+	-Dacl=false \
+	-Dsysvinit-path=''
+
+HOST_SYSTEMD_DEPENDENCIES = \
+	host-util-linux \
+	host-patchelf \
+	host-libcap \
+	host-gperf
+
+# Fix RPATH After installation
+# * systemd provides a install_rpath instruction to meson because the binaries need to link with
+#   libsystemd which is not in a standard path
+# * meson can only replace the RPATH, not append to it
+# * the original rpatch is thus lost.
+# * the original path had been tweaked by buildroot vial LD_FLAGS to add $(HOST_DIR)/lib
+# * thus re-tweak rpath after the installation for all binaries that need it
+#buildroot detects incorrect RPATH, so adding new binaries should be safe (it won't compile
+#unless properly integrated).
+HOST_SYSTEMD_HOST_TOOLS = \
+	systemd-analyze  systemd-mount systemctl udevadm
+
+define HOST_SYSTEMD_FIX_RPATH
+	$(foreach f,$(HOST_SYSTEMD_HOST_TOOLS), \
+		$(HOST_DIR)/bin/patchelf --set-rpath $(HOST_DIR)/lib:$(HOST_DIR)/lib/systemd $(HOST_DIR)/bin/$(f)
+	)
+endef
+
+HOST_SYSTEMD_POST_INSTALL_HOOKS +=  HOST_SYSTEMD_FIX_RPATH
+HOST_SYSTEMD_NINJA_ENV = DESTDIR=$(HOST_DIR)
+
+$(eval $(host-meson-package))