-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Fake JLLs for all packages #38347
Fake JLLs for all packages #38347
Conversation
Looks good! What happens if I set |
Nothing changes on that front; these "fake JLLs" provide the Julia API that packages can expect (e.g. exporting functions for calling executables, defining symbols for library SONAMEs, etc...) but they don't actually provide the binaries. They just blindly In the future, we'll use actual JLLs by default, and the binaries will be stored in |
45d02dc
to
27f7b75
Compare
fd0d7a8
to
e982a01
Compare
2756e5c
to
f2424e8
Compare
Looks like this is finally passing tests! Huzzah! Next up, fix the checksums. |
c1a8410
to
d564bac
Compare
I think this is ready for review now! I have checked that it passed all tests with a There is likely some When reviewing this, I suggest looking at the first commit in isolation so as to filter out the massive number of checksum files that were modified. |
If this is what you do then I'll report now that it's broken. |
@nanosoldier |
Your package evaluation job has completed - possible new issues were detected. A full report can be found here. cc @maleadt |
04d1c16
to
233164f
Compare
@nanosoldier |
Your package evaluation job has completed - possible new issues were detected. A full report can be found here. cc @maleadt |
233164f
to
fac77f4
Compare
@nanosoldier |
fac77f4
to
203fa32
Compare
From my reading of PkgEval, this is now good to go once Jameson has a chance to take a look. |
203fa32
to
bb81527
Compare
@vtjnash let's discuss the performance implications here. So it appears that on my Linux machine, this PR doesn't significantly increase startup time (<1ms, which is <1%). On MacOS, on the other hand, it increases it by ~20% (40ms) which is obviously unacceptable. The challenge is that JLLs don't (yet) provide a lazily-loaded API, and there are real packages out there that depend on e.g. Since Julia itself doesn't yet use the JLLs as the Julian API for accessing binaries (that's part of my un-merged work that is getting pushed back to v1.7) it's not critical for me to add in the lazily-loading API, and indeed it's not even critical for the JLL modules to be loaded at startup at all. Is there a way I can include the JLLs in the sysimg (so importing is fast) but not have Julia automatically import them? So, e.g. the |
No, but I think we can just remove all text content from these packages without causing any breakage to the julia build (since nothing changes, they're just made into purely fake stub files)? |
It won't break the julia build, but it will break all packages that use these JLL packages. |
# This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
## dummy stub for https://github.com/JuliaBinaryWrappers/GMP_jll.jl | ||
module GMP_jll |
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.
Comparing this to https://github.com/JuliaBinaryWrappers/GAP_jll.jl/blob/main/src/GAP_jll.jl I notice a couple differences:
A very minor one is that the the real GAP_jll is a baremodule
which supposedly helps performance a bit -- but that's irrelevant for compatibility.
More importantly, though, the JLL API implemented here seems to match the "old" one (you know, from the stone ages, i.e., 2-3 months ago). A quick check shows that it is missing at least these:
best_wrapper
dev_jll
find_artifact_dir
get_libgmp_path
get_libgmpxx_path
I actually just today adapted some of my code to use GMP_jll.find_artifact_dir()
instead of GMP_jll.artifact_dir
, as I just learned about find_artifact_dir
and thought this was the way forward. Now it isn't?
Perhaps it would be a good idea to use something like JLLWrappers here, too, to avoid some of the repetition and ensure consistency. Indeed, perhaps one could adapt JLLWrapper itself?
Finally, and for me perhaps most seriously: this fake JLL will lack the GMP header files, won't it? Because those actually are quite crucial for me, as I have to compile some C code on the user machine which links against GMP_jll. Yes yes, I should put it all into JLLs, and I did it for most of the code, but there are some parts where this is rather problematic.
If there was a way to get the "real" GMP_jll
(and similar for other JLLs in this PR), just for accessing the headers in it, that'd solve this final issue for me (in particular, it would not be necessary for me to load the "real" GMP_jll
, just a way to get paths into it would suffice. Is something like that a possibility?
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.
Now it isn't?
It is.
If there was a way to get the "real" GMP_jll (and similar for other JLLs in this PR), just for accessing the headers in it, that'd solve this final issue for me (in particular, it would not be necessary for me to load the "real" GMP_jll, just a way to get paths into it would suffice. Is something like that a possibility?
Yes! This is precisely why we bundle a StdlibArtifacts.toml
file; so that "special" packages that are in the know can do these kinds of workarounds. In your case, you'll just need to do some artifacts shenanigans if you're on v1.6, where you find the StdlibArtifacts.toml
file, select the appropriate GMP
artifact within it, and then you can use your headers and whatnot as usual.
Perhaps it would be a good idea to use something like JLLWrappers here, too, to avoid some of the repetition and ensure consistency. Indeed, perhaps one could adapt JLLWrapper itself?
I would have loved to, and indeed, the first cut at this did exactly that, but there are some issues:
-
First, the JLLWrappers API has evolved a lot over the past few months. You've seen this (and helped a bit) so I knew that wholesale importing JLLWrappers into v1.6 wasn't quite a possibility yet. IMO, better to ship no API at all then to ship a broken one that we replace two months later in v1.7.
-
Second, we don't have actual artifacts getting installed on v1.6 yet. That breaks a lot of assumptions in the JLLWrapper world. I would like for JLLWrappers to be smart enough to deal with
USE_SYSTEM_XXX=1
configurations where you justdlopen("libfoo.so")
, alternate artifact location configurations (e.g. aLibFoo_jll_debug=true
is set in yourLocalPreferences.toml
) or complete path overrides (e.g. the preferenceLibFoo_jll_libfoo_path=/opt/special_julia_stuff/lib/libfoo.so.1.2
is set). But that API isn't here yet, and that's really what we need in order for JLLs to be useful across all Julia configurations.
Ideally, it would all come together in one piece, but unfortunately that kind of thinking ends up with PRs that have thousands of lines changed at once, and are completely un-reviewable. So we have to do them in small batches, and when release time comes, I can only hold it back for so long. ;)
Unfortunately, this forces a bit of complexity onto you, but hopefully it's not too too inconvenient to have some v1.6
-specific workarounds.
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.
Oh, and we can add some of those API pieces in. Adding e.g. get_libgmp_path()
shouldn't be too hard, and get_artifact_dir()
can just return dirname(Sys.BINDIR)
or something.
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.
Thanks for clarifying. Great to hear about StdlibArtifacts.toml
, that's a relief :-)
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.
Just to give a little higher level context: 1.6 is going to be a somewhat awkward middle state for stdlib JLLs which will be resolved in 1.7 by making stdlib JLLs really be fully normal JLLs, but it's a big change, so not all of it made it into the 1.6 release. I'm really looking forward to consistently using real JLLs everywhere as it will make a lot of things much better and easier.
32414a2
to
3b82a7e
Compare
@vtjnash I think I've found a happy middle ground; by excluding JLL packages from the system image, we should be able to avoid paying the startup costs. This means that when you type This needs JuliaLang/Pkg.jl#2251 to be usable, since precompiling stdlibs (which don't generally have Once Jameson okays this, we can merge this and be one step closer to branching. I will have some backport work to do for @fingolfin's API concerns above, but those aren't blocking the branch, they're fairly easy to add and are isolated from the rest of Julia, so I am confident that Max and I can get it worked out between us without needing to bother others. |
That sounds pretty reasonable (even goes along the lines of #38119, which is blocked on the same Pkg bug). I think, however, that this may indicate it is a more complex and comprehensive API than we want to include in the stdlib distribution? The goal of Jeff's latest feature update to |
For those of us who haven't been following but who find this very interesting...is there going to be any change in latency? Does stdlib precompiliation cache native code or just type-inferred code? |
08526e3
to
492dbac
Compare
JLLs provide the binary interaction interface that both packages and the Pkg resolver require in order to properly version and interact with the binary dependencies shipped with Julia. This PR changes all binary dependencies to carry along a JLL package that dlopen()'s the binary that ships along with Julia. These JLL packages are not the true JLL packages that are generated by BinaryBuilder, but are instead "fake" JLLs that simply `dlopen(filename)` and rely upon the default dlopen path to find the appropriate libraries, which affords the opportunity for system libraries and bundled-with-julia libraries alike to both be represented through the JLL interface.
a67ff03
to
ca4a22a
Compare
There shouldn't be any change to latency after these latest changes. We're basically including these JLL packages so that they can participate in |
It looks like the added patch against pcre makes the build dependent upon automake (which is not listed as build dependency presently IIUC)? Or am I misunderstanding? :)
|
^ specifically, this patch: |
Is it possible that the additions to stdlib/Makefile are missing USE_BINARYBUILDER guards or something to that effect? With USE_BINARYBUILDER=0 (absent network access), we hit
after the deps build finishes. |
This will be addressed via #38962 |
vstr = zeros(UInt8, 32) | ||
ccall((:mbedtls_version_get_string, libmbedcrypto), Cvoid, (Ref{UInt8},), vstr) | ||
vn = VersionNumber(unsafe_string(pointer(vstr))) | ||
@test vn == v"2.24.0" |
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.
These very strict version checks are problematic with USE_SYSTEM_MBEDTLS=1
and equivalents, as the system version is unlikely to match exactly. Would it be OK if we replaced this check with a comparison against the minimum required version?
This completes the Fake JLL work that is necessary for 1.6, although I would still like to add a
CompilerSupportLibraries_jll
package that more reliably sets up ourlibgfortran
/libstdc++
story. EDIT: This has been added.This PR revamps somewhat the manner in which we download the BB-built binaries for base Julia; in particular, it provides "fake" JLL packages that provide roughly the same API as the real ones, and declares the appropriate version of the JLL packages such that the resolver will no longer attempt to download e.g.
OpenBLAS_jll
on client machines anymore; the version will be locked to the version shipped by Julia. Not only does this save users a bit of downloading time, it now allows package developers to express compatibility bounds upon dependencies, and not have to mentally remember that a certain version ships with Julia 1.6 and therefore their package is implicitly locked to Julia v1.6 as well; the resolver can now more faithfully do its job.The build system is changed a bit here to streamline downloading of dependencies/JLLs and bundling the appropriate
Artifacts.toml
files, but don't get too attached to this method as it's going to change yet again once we have actual honest-to-god JLLs embedded as stdlibs (this will hopefully make it into v1.7).There is a good chance that there are edge cases where this is going to break packages. We'll definitely need a PkgEval run with this one merged just to see where we stand on that.
This work formally fixes #35215, and finishes one big chunk of work for #33973.
TODO before this PR is ready: