-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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
Build arbitrary Julia package environments in Nixpkgs #225513
Conversation
👍 Seems to work, with a non-critical error as it tries to access REPL history. This is x86_64-linux:
|
Right, I added a note at the top about giving Julia a writable depot to make that error go away. |
I think as of now this approach does not work with PyCall (or PythonCall packages), trying to build for example
for the previous PRs this could be fixed by adding a preBuild like |
@benneti it should work now in the latest branch! I had forgotten to pass Python to Julia in the earlier parts of the process. I also added a mapping where we can keep common Julia packages and the Python packages they depend on, so In general, you can pass a custom Python with extra packages installed via override:
|
Great! This fixes SymPy, there is however another whole class that needs to be treated (and I think actually two cases therein) namely PythonCall packages (like PythonPlot) without any PyCall and with PyCall in the same depot.
I think not all are strictly necessary, but the last one ist the most important one and should point to |
Okay, I think I've got it @benneti. I added a map of "package implications," so we can say that FWIW, there appear to be about 20 other packages in the General registry which use |
Nice, thanks! The automatic scan would be amazing, but maybe also a bit overkill as a solution. Last question, is there a reason you don't To make it slightly more clear, why not add this line as the first line of the wrapper: |
How much of an effort will it be to support darwin? I was thinking of using Do you see any problem in using |
Also I just tried a julia "instantiate" a julia package and realized, that the julia intern package manager is completely broken in juliaWithPkgs even when setting |
I think that's a good idea! Let me try doing that (with an overridable option to disable it).
Not off the top of my head @sbh69840. It would be great if you could figure out what's happening with
Hmm, that's sort of the goal of |
Sorry indeed installing works, but precompilation and using fails for me. EDIT: Are you sure having JULIA_PROJECT as a ":" separated list is supported if not it might be better to have set-default instead of suffix. |
You're right, I just changed it to set-default
I had to add a mapping for the Python package Trying to add it to a local project seems to work for me, other than the missing Python package. To be clear I'm doing this: cd $(mktemp -d)
nix run --impure --expr 'with import <nixpkgs> {}; ((juliaWithPackages) ["SymPy"])'
julia> ]
(project) pkg> activate .
(tmp.SwF22zOWgb) pkg> add ExcelFiles
...
(tmp.SwF22zOWgb) pkg> <backspace>
julia> import Pkg
julia> Pkg.precompile()
julia> using ExcelFiles
[ Info: Precompiling ExcelFiles [89b67f3b-d1aa-5f6f-9ca4-282e8d98620d]
ERROR: LoadError: InitError: PyError (PyImport_ImportModule
The Python package xlrd could not be imported by pyimport.
... It seems like it would work if you injected a Python with |
Yeah with set-default everything seems to work as expected on the julia side! But I think overriding python3 with a python that has packages installed is ignored, due to recalling withPackages, it would be great if it was possible to add python packages manually. |
Yeah it's weird that multiple However, it does work to set PYTHONPATH before launching Julia. |
Hmm, I think the new default |
is the precompilation happening always? For me it seems to work (at least sometimes) as long as I am not in a Julia project. |
I will have a look at this, if this works we can support Darwin as well. |
I'm having trouble pinning down exactly what causes it to happen. Julia's always been a little twitchy about what causes additional precompiles. It does seem related to when you've activated your own project, so I'm not going to worry about it. |
Regarding this: #20649 (comment) |
@sbh69840 I can't reproduce that problem. I think it will work as long as you have a writable depot in |
I just realized that while now building the packages works, the artifacts in the local depot are not patched such that a lot of packages don't work. |
I don't follow, what do you mean "not patched"? Can you provide an example? |
for example if I have a typical julia project with its own "Manifest.toml" and "Project.toml" which might contain a certain version of Plots.jl which will pull in the GR manifest. This is why the other PR introduced the FHS environemnt, here it would probably make more sense to have a way to make the project into a flake project and have the flake read the Manifest and Project.toml and build the dependencies in the nix store. |
Hmm, I still don't totally see what you mean by "patched" -- do you mean fixing up dynamic library paths? A precise repro would be helpful. I do think that activating your own project is borderline out-of-scope for |
Nevermind, it is actually trivial to wrap juliaWithPackages in buildFHSUserEnv such that project based package management actually works. It might not be the most nix way, but is simple enough for easy compatibility if necessary. What I initially meant was what you say (I think), but gluing them more together by allowing something like juliaWithProject that takes in a Manifest.toml and Project.toml and generates the appropriate nix expression. |
Sorry for spamming this thread, but there is (hopefully one last change I would suggest), taking a look at https://docs.julialang.org/en/v1/manual/environment-variables/#JULIA_LOAD_PATH the second expression of the default value does not make sense the versioned environment should probably point to the nix store, therefore I would suggest to do |
👍🏻
...a What I mean is that the python script contains some pieces of Nix code and the only way to run a syntax check on is to actually build a sample package. But you could (unless I'm not seeing something) replace those chunks of Nix with a single |
FWIW what you describe sort of already exists for the Julia sources; see the The artifacts side of things is even more complex. I think the refactor you describe could be done, but most of the meat would have to stay in Python (for example, using |
These motivations should be on the next PR.
Agreed, I have been using this PR for some time now, and it is time to merge it into nixpkgs. Although there may be some other tasks pending, this PR is already sufficiently refined. |
@SuperSandro2000 @NickCao |
As previously said, I have little knowledge of the julia ecosystem so might not be able to give constructive suggestions, but I trust your expertise as the maintainer of Julia2Nix.jl. The overall implementation does looks a bit convoluted but do lay a solid foundation for future improvements. So, I do intend to merge this, but after the branch of 23.11, giving it more time to mature before getting into a stable release. And a bit bike shedding: I see that julia is wrapped twice, first as juliaWrapped, then into julia-env, is this a hard requirement of the implementation? |
The first wrapper just merges |
May you add release note entries and some documentation? Then this would be good to merge. |
6cb69be
to
dcda203
Compare
Okay @NickCao, I've added some documentation! Also added a release note but I'm not sure if it's good/in the right place, so please take a look. |
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.
For the document part, cc @NixOS/documentation-team
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.
Docs are very well-written, but please reformat to one sentence per line. There is a style guide on nix.dev which the docs team applies to all documentation we review. 👍
Side note: I'm not a fan of withPackages [ "strings" ]
, but I have no say here and likely this is bikeshedding, but there is at least the consideration of consistency with Python that you should probably check with the Nixpkgs architecture team (@infinisil since there is still now way to ping the team on GitHub).
No approval here because what matters is the code. Looks like a great contribution overall, thanks a lot!
Thanks @fricklerhandwerk!
FWIW, a previous version of this PR had a full list of package names checked in, to make it possible to present an attrset of packages like Python does. It was decided that it wasn't worth it because it was large (>100KB IIRC) and would require extra maintainance work to keep updated. |
42875e0
to
e160388
Compare
Be able to build arbitrary Julia environments in Nixpkgs, in the same style as python.withPackages.
e160388
to
c8f0d30
Compare
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.
Implementation is complicated, but we can improve that later. The document is easy to follow, played with Plots and it works. Regarding the API design, since we are using IFD and it's expensive to construct the attrset beforehand, I'm happy with the current approach. This is a final call for comments and I will merge in 3 days if no objections.
And once again thank @thomasjm and everyone in this thread for your efforts.
Description of changes
tl;dr: this PR offers a new approach to build arbitrary Julia environments in Nixpkgs, in the same style as
python.withPackages
. You can try it like this (using whatever packages you like):How does it work?
The steps are documented in
default.nix
. To summarize:.nix
file containingfetchgit
calls for all the desired packages, leveraging sha256 hashes from the special registry.repo
fields have been replaced with on-disk paths in the Nix store..nix
file.Overrides.toml
pointing all the artifacts to local Nix store paths (IFD)makeWrapper
call on Julia to set everything up. You can optionally pass a booleanprecompile
to control whether everything gets precompiled.The only downside here is that this process involves IFD in step 4 and step 7. I'm hoping the benefits will outweigh the drawbacks here and the community will be willing to land this. In practical terms, the IFD means that Nix isn't able to process the package downloads and artifacts downloads in parallel, which means it takes a bit longer to run them sequentially. And possibly this isn't testable on Hydra. But still, Julia packaging has been a challenge for years and this gets it done!
If the IFD is a no-go, we could move the pieces around to make this a 2-step process where you first generate a set of
.nix
files, and then build them yourself, similar to julia2nix. IMO the ergonomics of that are worse though.A couple other notes:
package-names.nix
. The only purpose of this is to expose them in anattrset
, so that it's easy to explore the available packages in a Nix repl. I figure it's not too big of a file, but we could remove it.Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)