Skip to content

Commit 5efee07

Browse files
add news, docs, tests
1 parent eb249a6 commit 5efee07

File tree

5 files changed

+138
-5
lines changed

5 files changed

+138
-5
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Pkg v1.13 Release Notes
33

44
- Project.toml environments now support a `readonly` field to mark environments as read-only, preventing modifications. ([#4284])
55
- Packages are now automatically added to `[sources]` when they are added by url or devved.
6+
- Added `Pkg.precompile() do` block syntax to delay autoprecompilation until after multiple operations complete, improving efficiency when performing several environment changes. ([#4262])
7+
- Added `Pkg.autoprecompilation_enabled(state::Bool)` to globally enable or disable automatic precompilation for Pkg operations. ([#4262])
68

79
Pkg v1.12 Release Notes
810
=======================
@@ -13,7 +15,7 @@ Pkg v1.12 Release Notes
1315
- Pkg now supports "apps" which are Julia packages that can be run directly from the terminal after installation.
1416
Apps can be defined in a package's Project.toml and installed via Pkg. ([#3772])
1517
- `status` now shows when different versions/sources of dependencies are loaded than that which is expected by the manifest ([#4109])
16-
- When adding or developing a package that exists in the `[weakdeps]` section, it is now automatically removed from
18+
- When adding or developing a package that exists in the `[weakdeps]` section, it is now automatically removed from
1719
weak dependencies and added as a regular dependency. ([#3865])
1820
- Enhanced fuzzy matching algorithm for package name suggestions.
1921

docs/src/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Pkg.gc
3939
Pkg.status
4040
Pkg.compat
4141
Pkg.precompile
42+
Pkg.autoprecompilation_enabled
4243
Pkg.offline
4344
Pkg.why
4445
Pkg.dependencies

docs/src/environments.md

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,16 +190,53 @@ If a given package version errors during auto-precompilation, Pkg will remember
190190
automatically tries and will skip that package with a brief warning. Manual precompilation can be used to
191191
force these packages to be retried, as `pkg> precompile` will always retry all packages.
192192

193-
To disable the auto-precompilation, set `ENV["JULIA_PKG_PRECOMPILE_AUTO"]=0`.
194-
195193
The indicators next to the package names displayed during precompilation
196-
indicate the status of that package's precompilation.
194+
indicate the status of that package's precompilation.
197195

198196
- `[◐, ◓, ◑, ◒]` Animated "clock" characters indicate that the package is currently being precompiled.
199197
- `` A green checkmark indicates that the package has been successfully precompiled (after which that package will disappear from the list). If the checkmark is yellow it means that the package is currently loaded so the session will need to be restarted to access the version that was just precompiled.
200198
- `?` A question mark character indicates that a `PrecompilableError` was thrown, indicating that precompilation was disallowed, i.e. `__precompile__(false)` in that package.
201199
- `` A cross indicates that the package failed to precompile.
202200

201+
#### Controlling Auto-precompilation
202+
203+
Auto-precompilation can be controlled in several ways:
204+
205+
- **Environment variable**: Set `ENV["JULIA_PKG_PRECOMPILE_AUTO"]=0` to disable auto-precompilation globally.
206+
- **Programmatically**: Use `Pkg.autoprecompilation_enabled(false)` to disable auto-precompilation for the current session, or `Pkg.autoprecompilation_enabled(true)` to re-enable it.
207+
- **Scoped control**: Use `Pkg.precompile(f, args...; kwargs...)` to execute a function `f` with auto-precompilation temporarily disabled, then automatically trigger precompilation afterward if any packages were modified during the execution.
208+
209+
!!! compat "Julia 1.13"
210+
The `Pkg.autoprecompilation_enabled()` function and `Pkg.precompile()` do-block syntax require at least Julia 1.13.
211+
212+
For example, to add multiple packages without triggering precompilation after each one:
213+
214+
```julia-repl
215+
julia> Pkg.precompile() do
216+
Pkg.add("Example")
217+
Pkg.dev("JSON")
218+
Pkg.update("HTTP")
219+
end
220+
Resolving package versions...
221+
...
222+
Precompiling environment...
223+
14 dependencies successfully precompiled in 25 seconds
224+
```
225+
226+
Or to temporarily disable auto-precompilation:
227+
228+
```julia-repl
229+
julia> Pkg.autoprecompilation_enabled(false)
230+
false
231+
232+
julia> Pkg.add("Example") # No precompilation happens
233+
Resolving package versions...
234+
...
235+
236+
julia> Pkg.autoprecompilation_enabled(true)
237+
true
238+
```
239+
203240
### Precompiling new versions of loaded packages
204241

205242
If a package that has been updated is already loaded in the session, the precompilation process will go ahead and precompile

src/Pkg.jl

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ can_fancyprint(io::IO) = (usable_io(io)) && (get(ENV, "CI", nothing) != "true")
7373

7474
_autoprecompilation_enabled::Bool = true
7575
_autoprecompilation_enabled_scoped = Base.ScopedValues.ScopedValue{Bool}(true)
76-
autoprecompilation_enabled(state::Bool) = (autoprecompilation_enabled = state)
76+
autoprecompilation_enabled(state::Bool) = (global _autoprecompilation_enabled = state)
7777
function should_autoprecompile()
7878
if Base.JLOptions().use_compiled_modules == 1 &&
7979
_autoprecompilation_enabled &&
@@ -251,6 +251,9 @@ end
251251
!!! compat "Julia 1.9"
252252
Timing mode requires at least Julia 1.9.
253253
254+
!!! compat "Julia 1.13"
255+
The `Pkg.precompile(f, args...; kwargs...)` do-block syntax requires at least Julia 1.13.
256+
254257
# Examples
255258
```julia
256259
Pkg.precompile()
@@ -260,6 +263,39 @@ Pkg.precompile(["Foo", "Bar"])
260263
"""
261264
const precompile = API.precompile
262265

266+
"""
267+
Pkg.autoprecompilation_enabled(state::Bool)
268+
269+
Enable or disable automatic precompilation for Pkg operations.
270+
271+
When `state` is `true` (default), Pkg operations that modify the project environment
272+
will automatically trigger precompilation of affected packages. When `state` is `false`,
273+
automatic precompilation is disabled and packages will only be precompiled when
274+
explicitly requested via [`Pkg.precompile`](@ref).
275+
276+
This setting affects the global state and persists across Pkg operations in the same
277+
Julia session. It can be used in combination with [`Pkg.precompile`](@ref) do-syntax
278+
for more fine-grained control over when precompilation occurs.
279+
280+
!!! compat "Julia 1.13"
281+
This function requires at least Julia 1.13.
282+
283+
# Examples
284+
```julia
285+
# Disable automatic precompilation
286+
Pkg.autoprecompilation_enabled(false)
287+
Pkg.add("Example") # Will not trigger auto-precompilation
288+
Pkg.precompile() # Manual precompilation
289+
290+
# Re-enable automatic precompilation
291+
Pkg.autoprecompilation_enabled(true)
292+
Pkg.add("AnotherPackage") # Will trigger auto-precompilation
293+
```
294+
295+
See also [`Pkg.precompile`](@ref).
296+
"""
297+
const autoprecompilation_enabled = autoprecompilation_enabled
298+
263299
"""
264300
Pkg.rm(pkg::Union{String, Vector{String}}; mode::PackageMode = PKGMODE_PROJECT)
265301
Pkg.rm(pkg::Union{PackageSpec, Vector{PackageSpec}}; mode::PackageMode = PKGMODE_PROJECT)

test/api.jl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,63 @@ import .FakeTerminals.FakeTerminal
158158
@test !occursin("Precompiling", String(take!(iob))) # test that the previous precompile was a no-op
159159
end
160160

161+
dep8_srcfile = joinpath("packages", "Dep8", "src", "Dep8.jl")
162+
@testset "delayed precompilation with do-syntax" begin
163+
iob = IOBuffer()
164+
Pkg.develop(Pkg.PackageSpec(path="packages/Dep7"))
165+
166+
# Test that operations inside Pkg.precompile() do block don't trigger auto-precompilation
167+
Pkg.precompile(io=iob) do
168+
write(dep8_srcfile, read(dep8_srcfile, String) * " ") # Modify the source to ensure it is recompiled
169+
Pkg.add(Pkg.PackageSpec(path="packages/Dep8"))
170+
Pkg.rm("Dep8")
171+
write(dep8_srcfile, read(dep8_srcfile, String) * " ") # Modify the source to ensure it is recompiled
172+
Pkg.add(Pkg.PackageSpec(path="packages/Dep8"))
173+
end
174+
175+
# The precompile should happen once at the end
176+
str = String(take!(iob))
177+
@test occursin("Precompiling", str)
178+
179+
# Verify it was precompiled by checking a second call is a no-op
180+
Pkg.precompile(io=iob)
181+
@test !occursin("Precompiling", String(take!(iob)))
182+
end
183+
184+
@testset "autoprecompilation_enabled global control" begin
185+
iob = IOBuffer()
186+
187+
# Test disabling autoprecompilation globally
188+
original_state = Pkg._autoprecompilation_enabled
189+
try
190+
Pkg.autoprecompilation_enabled(false)
191+
@test Pkg._autoprecompilation_enabled == false
192+
193+
# Operations should not trigger autoprecompilation when globally disabled
194+
write(dep8_srcfile, read(dep8_srcfile, String) * " ") # Modify the source to ensure it is recompiled
195+
Pkg.add(Pkg.PackageSpec(path="packages/Dep8"), io=iob)
196+
@test !occursin("Precompiling", String(take!(iob)))
197+
198+
# Manual precompile should still work
199+
Pkg.precompile(io=iob)
200+
@test occursin("Precompiling", String(take!(iob)))
201+
202+
# Re-enable autoprecompilation
203+
Pkg.autoprecompilation_enabled(true)
204+
@test Pkg._autoprecompilation_enabled == true
205+
206+
# Operations should now trigger autoprecompilation again
207+
Pkg.rm("Dep8", io=iob)
208+
write(dep8_srcfile, read(dep8_srcfile, String) * " ") # Modify the source to ensure it is recompiled
209+
Pkg.add(Pkg.PackageSpec(path="packages/Dep8"), io=iob)
210+
@test occursin("Precompiling", String(take!(iob)))
211+
212+
finally
213+
# Restore original state
214+
Pkg.autoprecompilation_enabled(original_state)
215+
end
216+
end
217+
161218
@testset "instantiate" begin
162219
iob = IOBuffer()
163220
Pkg.activate("packages/Dep7")

0 commit comments

Comments
 (0)