Skip to content
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

Demo: Remove SparseArrays from sysimage & set up as weak dep of Statistics #47745

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ Julia v1.10 Release Notes
New language features
---------------------


New feature for packages that allows loading a piece of code based on other
packages being loaded in the Julia session.
This has similar applications as the Requires.jl package but also
supports precompilation and setting compatibility.
Look in the documentation for Pkg.jl for "glue packages" for more information.
Language changes
----------------

Expand Down
263 changes: 238 additions & 25 deletions base/loading.jl

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ let
:InteractiveUtils,
:LibGit2,
:Profile,
:SparseArrays,
:UUIDs,

# 3-depth packages
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bd49ed22b9fa0f86885d26265cc09161
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c531b521fa0976f8c155d06c226824b65e3542f0c06e0b0fcb4052e6027f1baf749566e0191f8a83ab0a13165825447f71474d3685b282ffbf3e270a64e21c17
39 changes: 39 additions & 0 deletions doc/src/manual/code-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,46 @@ The subscripted `rootsᵢ`, `graphᵢ` and `pathsᵢ` variables correspond to th
2. Packages in non-primary environments can end up using incompatible versions of their dependencies even if their own environments are entirely compatible. This can happen when one of their dependencies is shadowed by a version in an earlier environment in the stack (either by graph or path, or both).

Since the primary environment is typically the environment of a project you're working on, while environments later in the stack contain additional tools, this is the right trade-off: it's better to break your development tools but keep the project working. When such incompatibilities occur, you'll typically want to upgrade your dev tools to versions that are compatible with the main project.
### "Glue" packages and dependencies

A "glue package" is a module that is automatically loaded when a specified set of other packages (its "glue dependencies") are loaded in the current Julia session. The glue dependencies of a glue package is a subset of those packages listed under the `[weakdeps]` section of a Project file. Glue packages are defined under the `[gluepkgs]` section in the project file:

```toml
name = "MyPackage"

[weakdeps]
GlueDep = "c9a23..." # uuid
OtherGlueDep = "862e..." # uuid

[gluepkgs]
GlueBar = ["GlueDep", "OtherGlueDep"]
GlueFoo = "GlueDep"
...
```

The keys under `gluepkgs` are the name of the glue packages.
They are loaded when all the packages on the right hand side (the glue dependencies) of that glue package are loaded.
If a glue package only has one glue dependency the list of glue dependencies can be written as just a string for brevity.
The location for the entry point of the glue package is either in `glue/GlueFoo.jl` or `glue/GlueFoo/GlueFoo.jl` for
glue package `GlueFoo`.
The content of a glue package is often structured as:

```
module GlueFoo

# Load main package and glue dependencies
using MyPackage, GlueDep

# Extend functionality in main package with types from the glue dependencies
MyPackage.func(x::GlueDep.SomeStruct) = ...

end
```

When a package with glue packages is added to an environment, the `weakdeps` and `gluepkgs` sections
are stored in the manifest file in the section for that package. The dependency lookup rules for
a package are the same as for its "parent" except that the listed glue dependencies are also considered as
dependencies.
### Package/Environment Preferences

Preferences are dictionaries of metadata that influence package behavior within an environment.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Pkg.version
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PKG_BRANCH = master
PKG_SHA1 = ed6a5497e46ed541b2718c404c0f468b7f92263a
PKG_SHA1 = f1a47ed18bd3a306e318143befe9466a5f5fd571
PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git
PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1
8 changes: 4 additions & 4 deletions stdlib/Statistics.version
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
STATISTICS_BRANCH = master
STATISTICS_SHA1 = 20fbe576ec406180b1dddf4c7fbe16458a7aef21
STATISTICS_GIT_URL := https://github.com/JuliaStats/Statistics.jl.git
STATISTICS_TAR_URL = https://api.github.com/repos/JuliaStats/Statistics.jl/tarball/$1
STATISTICS_BRANCH = ib/glue
STATISTICS_SHA1 = 86454ce6e8f6dc11e548921be8522d790dc1ea86
STATISTICS_GIT_URL := https://github.com/IanButterworth/Statistics.jl.git
STATISTICS_TAR_URL = https://api.github.com/repos/IanButterworth/Statistics.jl/tarball/$1
32 changes: 32 additions & 0 deletions test/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -991,5 +991,37 @@ end
end
end


@testset "GluePkgs" begin
old_depot_path = copy(DEPOT_PATH)
try
tmp = mktempdir()
push!(empty!(DEPOT_PATH), joinpath(tmp, "depot"))

proj = joinpath(@__DIR__, "project", "GluePkgs", "HasDepWithGluePkgs.jl")
for i in 1:2 # Once when requiring precomilation, once where it is already precompiled
cmd = `$(Base.julia_cmd()) --project=$proj --startup-file=no -e '
begin
using HasGluePkgs
Base.get_gluepkg(HasGluePkgs, :GluePkg) === nothing || error("unexpectedly got a glue module")
HasGluePkgs.glue_loaded && error("glue_loaded set")
using HasDepWithGluePkgs
Base.get_gluepkg(HasGluePkgs, :GluePkg).gluevar == 1 || error("gluevar in GluePkg not set")
HasGluePkgs.glue_loaded || error("glue_loaded not set")
HasGluePkgs.glue_folder_loaded && error("glue_folder_loaded set")
HasDepWithGluePkgs.do_something() || error("do_something errored")
using GlueDep2
HasGluePkgs.glue_folder_loaded || error("glue_folder_loaded not set")

end
'`
@test success(cmd)
end
finally
copy!(DEPOT_PATH, old_depot_path)
end
end


empty!(Base.DEPOT_PATH)
append!(Base.DEPOT_PATH, original_depot_path)
2 changes: 1 addition & 1 deletion test/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ precompile_test_harness(false) do dir
:LazyArtifacts, :LibCURL, :LibCURL_jll, :LibGit2, :Libdl, :LinearAlgebra,
:Logging, :Markdown, :Mmap, :MozillaCACerts_jll, :NetworkOptions, :OpenBLAS_jll, :Pkg, :Printf,
:Profile, :p7zip_jll, :REPL, :Random, :SHA, :Serialization, :SharedArrays, :Sockets,
:SparseArrays, :TOML, :Tar, :Test, :UUIDs, :Unicode,
:TOML, :Tar, :Test, :UUIDs, :Unicode,
:nghttp2_jll]
),
)
Expand Down
3 changes: 3 additions & 0 deletions test/project/GluePkgs/GlueDep.jl/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name = "GlueDep"
uuid = "fa069be4-f60b-4d4c-8b95-f8008775090c"
version = "0.1.0"
5 changes: 5 additions & 0 deletions test/project/GluePkgs/GlueDep.jl/src/GlueDep.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module GlueDep

struct GlueDepStruct end

end # module GlueDep
3 changes: 3 additions & 0 deletions test/project/GluePkgs/GlueDep2/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name = "GlueDep2"
uuid = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d"
version = "0.1.0"
5 changes: 5 additions & 0 deletions test/project/GluePkgs/GlueDep2/src/GlueDep2.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module GlueDep2

greet() = print("Hello World!")

end # module GlueDep2
25 changes: 25 additions & 0 deletions test/project/GluePkgs/HasDepWithGluePkgs.jl/Manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# This file is machine-generated - editing it directly is not advised

julia_version = "1.10.0-DEV"
manifest_format = "2.0"
project_hash = "7cbe1857ecc6692a8cc8be428a5ad5073531ff98"

[[deps.GlueDep]]
path = "../GlueDep.jl"
uuid = "fa069be4-f60b-4d4c-8b95-f8008775090c"
version = "0.1.0"

[[deps.GlueDep2]]
path = "../GlueDep2"
uuid = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d"
version = "0.1.0"

[[deps.HasGluePkgs]]
weakdeps = ["GlueDep", "GlueDep2"]
path = "../HasGluePkgs.jl"
uuid = "4d3288b3-3afc-4bb6-85f3-489fffe514c8"
version = "0.1.0"

[deps.HasGluePkgs.gluepkgs]
GluePkg = "GlueDep"
GluePkgFolder = ["GlueDep", "GlueDep2"]
8 changes: 8 additions & 0 deletions test/project/GluePkgs/HasDepWithGluePkgs.jl/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name = "HasDepWithGluePkgs"
uuid = "d4ef3d4a-8e22-4710-85d8-c6cf2eb9efca"
version = "0.1.0"

[deps]
GlueDep = "fa069be4-f60b-4d4c-8b95-f8008775090c"
GlueDep2 = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d"
HasGluePkgs = "4d3288b3-3afc-4bb6-85f3-489fffe514c8"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module HasDepWithGluePkgs

using HasGluePkgs: HasGluePkgs, HasGluePkgsStruct
using GlueDep: GlueDepStruct
# Loading GlueDep makes the glue module "GluePkg" load

function do_something()
HasGluePkgs.foo(HasGluePkgsStruct()) == 1 || error()
HasGluePkgs.foo(GlueDepStruct()) == 2 || error()
return true
end

end # module
7 changes: 7 additions & 0 deletions test/project/GluePkgs/HasGluePkgs.jl/Manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This file is machine-generated - editing it directly is not advised

julia_version = "1.10.0-DEV"
manifest_format = "2.0"
project_hash = "c87947f1f1f070eea848950c304d668a112dec3d"

[deps]
11 changes: 11 additions & 0 deletions test/project/GluePkgs/HasGluePkgs.jl/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name = "HasGluePkgs"
uuid = "4d3288b3-3afc-4bb6-85f3-489fffe514c8"
version = "0.1.0"

[weakdeps]
GlueDep = "fa069be4-f60b-4d4c-8b95-f8008775090c"
GlueDep2 = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d"

[gluepkgs]
GluePkg = "GlueDep"
GluePkgFolder = ["GlueDep", "GlueDep2"]
13 changes: 13 additions & 0 deletions test/project/GluePkgs/HasGluePkgs.jl/glue/GluePkg.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module GluePkg

using HasGluePkgs, GlueDep

HasGluePkgs.foo(::GlueDep.GlueDepStruct) = 2

function __init__()
HasGluePkgs.glue_loaded = true
end

const gluevar = 1

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module GluePkgFolder

using GlueDep, GlueDep2, HasGluePkgs

function __init__()
HasGluePkgs.glue_folder_loaded = true
end

end
10 changes: 10 additions & 0 deletions test/project/GluePkgs/HasGluePkgs.jl/src/HasGluePkgs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module HasGluePkgs

struct HasGluePkgsStruct end

foo(::HasGluePkgsStruct) = 1

glue_loaded = false
glue_folder_loaded = false

end # module