@ -160,83 +160,87 @@ stdenv.mkDerivation {
- - replace \
" f i n d _ p r o g r a m ( ' o b j c o p y ' " \
" f i n d _ p r o g r a m ( ' ${ stdenv . cc . bintools . targetPrefix } o b j c o p y ' "
'' + ( l e t
# The folllowing dlopen patches ensure that all the features that are
# implemented via dlopen(3) are available (or explicitly deactivated) by
# pointing dlopen to the absolute store path instead of relying on the
# linkers runtime lookup code.
#
# All of the dlopen calls have to be handled. When new ones are introduced
# by upstream (or one of our patches) they must be explicitly declared,
# otherwise the build will fail.
#
# As of systemd version 247 we've seen a few errors like `libpcre2.… not
# found` when using e.g. --grep with journalctl. Those errors should
# become less unexpected now.
#
# There are generally two classes of dlopen(3) calls. Those that we want to
# support and those that should be deactivated / unsupported. This change
# enforces that we handle all dlopen calls explicitly. Meaning: There is
# not a single dlopen call in the source code tree that we did not
# explicitly handle.
#
# In order to do this we introduced a list of attributes that maps from
# shared object name to the package that contains them. The package can be
# null meaning the reference should be nuked and the shared object will
# never be loadable during runtime (because it points at an invalid store
# path location).
#
# To get a list of dynamically loaded libraries issue something like
# `grep -ri 'dlopen("lib' $src` and update the below list.
dlopenLibs = [
# We did never provide support for libxkbcommon & qrencode
{ name = " l i b x k b c o m m o n . s o . 0 " ; pkg = null ; }
{ name = " l i b q r e n c o d e . s o . 4 " ; pkg = null ; }
# We did not provide libpwquality before so it is safe to disable it for
# now.
{ name = " l i b p w q u a l i t y . s o . 1 " ; pkg = null ; }
# Only include cryptsetup if it is enabled. We might not be able to
# provide it during "bootstrap" in e.g. the minimal systemd build as
# cryptsetup has udev (aka systemd) in it's dependencies.
{ name = " l i b c r y p t s e t u p . s o . 1 2 " ; pkg = if withCryptsetup then cryptsetup else null ; }
# We are using libidn2 so we only provide that and ignore the others.
# Systemd does this decision during configure time and uses ifdef's to
# enable specific branches. We can safely ignore (nuke) the libidn "v1"
# libraries.
{ name = " l i b i d n 2 . s o . 0 " ; pkg = libidn2 ; }
{ name = " l i b i d n . s o . 1 2 " ; pkg = null ; }
{ name = " l i b i d n . s o . 1 1 " ; pkg = null ; }
# journalctl --grep requires libpcre so lets provide it
{ name = " l i b p c r e 2 - 8 . s o . 0 " ; pkg = pcre2 ; }
] ;
patchDlOpen = dl : let
library = " ${ lib . makeLibraryPath [ dl . pkg ] } / ${ dl . name } " ;
in if dl . pkg == null then ''
# remove the dependency on the library by replacing it with an invalid path
for file in $ ( grep - lr ' dlopen ( " ${ dl . name } " ' src ) ; do
echo " p a t c h i n g d l o p e n ( \" ${ dl . name } \" , … ) i n $ f i l e t o a n i n v a l i d s t o r e p a t h ( " /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-not-implemented / $ { dl . name } " ) … "
substituteInPlace " $ f i l e " - - replace ' dlopen ( " ${ dl . name } " ' ' dlopen ( " / n i x / s t o r e / e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e - n o t - i m p l e m e n t e d / ${ dl . name } " '
done
'' e l s e ''
# ensure that the library we provide actually exists
if ! [ - e $ { library } ] ; then
echo ' The shared library ` $ { library } ` does not exist but was given as subtitute for ` $ { dl . name } ` '
exit 1
fi
# make the path to the dependency explicit
for file in $ ( grep - lr ' dlopen ( " ${ dl . name } " ' src ) ; do
echo " p a t c h i n g d l o p e n ( \" ${ dl . name } \" , … ) i n $ f i l e t o ${ library } … "
substituteInPlace " $ f i l e " - - replace ' dlopen ( " ${ dl . name } " ' ' dlopen ( " ${ library } " '
done
'' ;
in # patch all the dlopen calls to contain absolute paths to the libraries
lib . concatMapStringsSep " \n " patchDlOpen dlopenLibs )
'' + (
let
# The folllowing dlopen patches ensure that all the features that are
# implemented via dlopen(3) are available (or explicitly deactivated) by
# pointing dlopen to the absolute store path instead of relying on the
# linkers runtime lookup code.
#
# All of the dlopen calls have to be handled. When new ones are introduced
# by upstream (or one of our patches) they must be explicitly declared,
# otherwise the build will fail.
#
# As of systemd version 247 we've seen a few errors like `libpcre2.… not
# found` when using e.g. --grep with journalctl. Those errors should
# become less unexpected now.
#
# There are generally two classes of dlopen(3) calls. Those that we want to
# support and those that should be deactivated / unsupported. This change
# enforces that we handle all dlopen calls explicitly. Meaning: There is
# not a single dlopen call in the source code tree that we did not
# explicitly handle.
#
# In order to do this we introduced a list of attributes that maps from
# shared object name to the package that contains them. The package can be
# null meaning the reference should be nuked and the shared object will
# never be loadable during runtime (because it points at an invalid store
# path location).
#
# To get a list of dynamically loaded libraries issue something like
# `grep -ri 'dlopen("lib' $src` and update the below list.
dlopenLibs = [
# We did never provide support for libxkbcommon & qrencode
{ name = " l i b x k b c o m m o n . s o . 0 " ; pkg = null ; }
{ name = " l i b q r e n c o d e . s o . 4 " ; pkg = null ; }
# We did not provide libpwquality before so it is safe to disable it for
# now.
{ name = " l i b p w q u a l i t y . s o . 1 " ; pkg = null ; }
# Only include cryptsetup if it is enabled. We might not be able to
# provide it during "bootstrap" in e.g. the minimal systemd build as
# cryptsetup has udev (aka systemd) in it's dependencies.
{ name = " l i b c r y p t s e t u p . s o . 1 2 " ; pkg = if withCryptsetup then cryptsetup else null ; }
# We are using libidn2 so we only provide that and ignore the others.
# Systemd does this decision during configure time and uses ifdef's to
# enable specific branches. We can safely ignore (nuke) the libidn "v1"
# libraries.
{ name = " l i b i d n 2 . s o . 0 " ; pkg = libidn2 ; }
{ name = " l i b i d n . s o . 1 2 " ; pkg = null ; }
{ name = " l i b i d n . s o . 1 1 " ; pkg = null ; }
# journalctl --grep requires libpcre so lets provide it
{ name = " l i b p c r e 2 - 8 . s o . 0 " ; pkg = pcre2 ; }
] ;
patchDlOpen = dl :
let
library = " ${ lib . makeLibraryPath [ dl . pkg ] } / ${ dl . name } " ;
in
if dl . pkg == null then ''
# remove the dependency on the library by replacing it with an invalid path
for file in $ ( grep - lr ' dlopen ( " ${ dl . name } " ' src ) ; do
echo " p a t c h i n g d l o p e n ( \" ${ dl . name } \" , … ) i n $ f i l e t o a n i n v a l i d s t o r e p a t h ( " /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-not-implemented / $ { dl . name } " ) … "
substituteInPlace " $ f i l e " - - replace ' dlopen ( " ${ dl . name } " ' ' dlopen ( " / n i x / s t o r e / e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e - n o t - i m p l e m e n t e d / ${ dl . name } " '
done
'' e l s e ''
# ensure that the library we provide actually exists
if ! [ - e $ { library } ] ; then
echo ' The shared library ` $ { library } ` does not exist but was given as subtitute for ` $ { dl . name } ` '
exit 1
fi
# make the path to the dependency explicit
for file in $ ( grep - lr ' dlopen ( " ${ dl . name } " ' src ) ; do
echo " p a t c h i n g d l o p e n ( \" ${ dl . name } \" , … ) i n $ f i l e t o ${ library } … "
substituteInPlace " $ f i l e " - - replace ' dlopen ( " ${ dl . name } " ' ' dlopen ( " ${ library } " '
done
'' ;
in
# patch all the dlopen calls to contain absolute paths to the libraries
lib . concatMapStringsSep " \n " patchDlOpen dlopenLibs
)
# finally ensure that there are no left-over dlopen calls that we didn't handle
+ ''
if grep - qr ' dlopen ( " [ ^ / ] ' s r c ; t h e n