New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generalize notion of arch-dependent modules #26287
Conversation
cc @edolstra for general approval, @vcunat for video, @ericsagnes for input methods, @nbp for Checklist:
|
lib/types.nix
Outdated
function = from: to: | ||
assert from.getSubModules == null; | ||
mkOptionType rec { | ||
name = "function"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, No, No, NO, and NO!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please elaborate :3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks for the reference!
I'm unsure how to do it the other way (avoid using functions). Without them every added package would need to be effectively doubled, e.g. we'd need to have two lists of identical packages but for different architectures specified by users (we in fact have this now as hardware.opengl.extraPackages{,32}
and it looks quite ugly). Also I think a function is just a very natural way to express this idea (abstract away from arch, and focus on "what packages are needed").
Any ideas much appreciated!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could have a pkgs
-like module argument which corresponds to the recursiveUpdate
of both pkgs
and pkgsi686Linux
packages, with a predicate to stop at derivations. Thus selecting a attribute name in the zipped set of packages would select the same attribute name in both sets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nbp Won't this be a heavy computation (zipping two package sets)? Still yes, sans that it sounds like a good idea. I'll try to implement it and see if it would indeed be slow (I think it won't be, after all).
nixos/modules/config/system-libs.nix
Outdated
|
||
packages = mkOption { | ||
type = types.function types.attrs (types.listOf types.package); | ||
default = pkgs: []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkgs
is provided as argument of the module, why do you need a function here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is that this function returns needed packages from passed package set. So when we need 32-bit support we evaluate this function twice, first with pkgs
and then with pkgsi686Linux
, getting what we want.
EDIT: the same idea is used in buildFHSEnv
-- you pass it a function that gets pkgs
and returns needed packages, and it evaluates it once or twice with different archs depending on what you need.
nixos/modules/config/system-libs.nix
Outdated
|
||
unsafePackages = mkOption { | ||
type = types.function types.attrs (types.listOf types.package); | ||
default = pkgs: []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkgs
is provided as argument of the module, why do you need a function here?
nixos/modules/config/system-libs.nix
Outdated
}; | ||
|
||
libPath = mkLibPath pkgs; | ||
libPath32 = mkLibPath pkgs.pkgsi686Linux; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having both implies that installing lib32 support would cause the system to compile an x86 toolchain in addition to the existing x86_64 toolchain. This sounds like way too much overhead to me. Couldn't such package already provide a lib32 directory as part of the outputs of the package?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nbp Not the whole system, only libraries which need to be multiarch. We already do this with video drivers, this just extends the idea to similar packages.
I only skimmed all this, but if we're blocked on the function type, why not use some attrmaps instead of function maps? Nix is lazy, so there's not too much difference. (EDIT: and the memoization we get might actually be a good thing.) I also don't have any idea about problems caused by cross-compiling NixOS, but I guess we would better leave such questions for some later iteration. |
@vcunat Yeah, I plan to do it this way after all (I had some doubts because while Nix is lazy we still need to compute at least the shallow top-level set one more time, and I don't know how long does it take). I'll push a second revision in several days. |
I expect each top-level set to be just a set of platforms, so that should be very cheap for all the unused platforms. |
`recursiveZipWithUntil` is a generalization of `recursiveUpdateUntil` for a list of attribute sets and using a custom merge function. `recursiveZipWith` to `recursiveZipWithUntil` is like `recursiveUpdate` to `recursiveUpdateUntil`.
Until now we had several options that accepted environment variables which had different types and copied functionality. Two side-effects from this change: * systemd.service.*.environment.NAME no longer accepts `null`s; * systemd combines global and service-local variables: for example when LD_LIBRARY_PATH is defined both in globalEnvironment and in service's environment as a list they are merged together.
Most of needed variables are already defined system-wide or could be moved there.
This makes it possible to have working input methods in 32-bit programs on a 64-bit system.
Currently we have several places in NixOS which use global architecture-dependent modules: * OpenGL drivers; * Input methods; * sane drivers; * GTK engines; All of those share common properties: * They are necessarily "impure"; * They are architecture-dependent -- that is, 32-bit program must use 32-bit modules; * They are commonly found through hardcoded paths or environment variables. This patch allows NixOS modules to specify functions that return needed packages given a package set as value for `libraries.packages`. Those functions are combined and used to build per-arch environments in /run/current-system/${system}-lib where `system` is `stdenv.system` for a given arch. Also we add a way to specify PATH-like variables that refer to those directories in `libraries.environment`.
FIXME: fglrx is not patched to use new paths yet! References to OpenGL drivers path and other paths are replaced throughout nixpkgs tree. User-facing changes: * `hardware.opengl.driSupport32Bit` is gone, replaced by generic `libraries.support32Bit`; * `hardware.opengl.driSupport` is gone (not used anywhere); * `hardware.opengl.extraPackages{,32}` are replaced by `libraries.packages` which is a function;
We expect now to have libraries handled by libraries.packages.
`i18n.inputMethod.{ibus,fcitx}.engines` are now a function.
`hardware.sane.extraBackends` is now a function.
Instead of placing GTK engines and GIO modules in system path, place then in arch-dependent directories.
It's a zip of package sets for all supported architectures on the system.
I've updated this patchset to use zipped packages instead -- sorry for the delay, life gets into the way :D. To me it looks a step back: zipped packages are much less intuitive and composable. Compare for example abbradar@9bd3dd5 and 388a942. Still, this seems an improvement over what we have now, so if others approve this approach I'll continue the work (see TODO list above). |
Oh, I originally thought it would be |
@vcunat Won't that way also complicate users specifying their packages? For example, how'd I specify that I want libraries from package |
Yes, that seems similar. I can't immediately see into further consequences of either approach, it was mainly intuition to do it the other way. Zipping the top-level set hopefully won't make a noticeable slow-down (it's memoized). |
Hm, but how? If you have `pkgs_multiarch.<system>.foo` then I see no simple way to specify a package for a user because they have to specify either a path (string) or both `arch32.foo` and `arch64.foo` (as we do now). In fact one can think of `pkgs` and `pkgs.pkgsi686Linux` as members of that set, so if we can figure out how can it work nicely we may not even need `pkgs_multiarch` - but I see no immediate solution...
--
Nikolay (from phone).
|
A string wouldn't be much flexible. It would be nice to support |
I think the changes @Ericson2314 is constantly working on should supersede this pull request? Or at least make it easier to implement. |
Which changes haha? |
If you mean cross in general, I haven't yet got rid of the old multi-lib stuff but yes that would be nice. |
What is the status of this pull request? |
I want to return to this idea some time as the problem of different arch-dependent modules is still there. We can close this as my next attempt will likely be a complete rewrite. |
Motivation for this change
Currently we have several places in NixOS which use global architecture-dependent modules:
All of those share common properties:
This patch allows NixOS modules to specify functions that return needed packages given a package set as value for
libraries.packages
. Those functions are combined and used to build per-arch environments in /run/current-system/${system}-lib wheresystem
isstdenv.system
for a given arch. Also we add a way to specify PATH-like variables that refer to those directories inlibraries.environment
.For now those paths are added in
LD_LIBRARY_PATH
like OpenGL drivers currently. We want to move from this whenlibglvnd
allows us but meanwhile I sanitize all packages inlibraries.packages
, removing all non-directories in/lib
. This shields people from accidentially polluting their library path by e.g. adding a VDPAU driver. To avoid sanitization one needs to uselibraries.unsafePackages
, the only current user now is our OpenGL module. WhenLD_LIBRARY_PATH=/lib
is dropped this won't be necessary.The end goal of this patch is to both streamline arch-dependent modules and add multi-arch support to things that don't have it now, for example IM modules. If implemented correctly all applications, both 32-bit and 64-bit, should have same themes, input modules, drivers and all other arch-dependent modules available in the system as long as
libraries.support32Bit
is flipped. Also we get rid of/run/opengl-driver{,-32}
which I dislike personally (why have it when we already have/run/current-system
?) :DThis patchset also cleans up our environment variables situation, some things being prerequisites to the main idea and some (DEs envvar cleanup) because they came along and were straightforward.
Things done
(nix.useSandbox on NixOS,
or option
build-use-sandbox
innix.conf
on non-NixOS)
nix-shell -p nox --run "nox-review wip"
./result/bin/
)Initial implementation is finished and I'm now trying to build my system with this. Before continuing though I'd like to hear feedback from others.