How to conditionally load code with package extensions

I have been going through documentation and examples on GitHub to learn how to conditionally load code. I keep running into issues. I think I would benefit from a MWE. I created a repo for this purpose here. I would like some code load conditionally when Distributions.jl is also loaded. Here is what I have done so far:

using PackageExtensionsExample
using Distributions

When I load Distributions, I receive the following error:


[ Info: Precompiling DistributionsExt [e012062e-4c15-5e28-8fa8-ee6d8c117614]
ERROR: LoadError: ArgumentError: Package Base does not have Distributions in its dependencies:

  • You may have a partially installed environment. Try Pkg.instantiate()
    to ensure all packages in the environment are installed.
  • Or, if you have Base checked out for development and have
    added Distributions as a dependency but haven’t updated your primary
    environment’s manifest file, try Pkg.resolve().
  • Otherwise you may need to report an issue with Base
    [1] macro expansion
    @ ./loading.jl:1634 [inlined]
    [2] macro expansion
    @ ./lock.jl:267 [inlined]
    [3] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:1611
    [4] top-level scope
    @ ~/.julia/dev/PackageExtensionsExample/ext/DistributionsExt.jl:1
    [5] include
    @ ./Base.jl:457 [inlined]
    [6] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::Nothing)
    @ Base ./loading.jl:2045
    [7] top-level scope
    @ stdin:3
    in expression starting at /home/dfish/.julia/dev/PackageExtensionsExample/ext/DistributionsExt.jl:1
    in expression starting at stdin:3
    β”Œ Error: Error during loading of extension DistributionsExt of PackageExtensionsExample, use Base.retry_load_extensions() to retry.
    β”‚ exception =
    β”‚ 1-element ExceptionStack:
    β”‚ Failed to precompile DistributionsExt [e012062e-4c15-5e28-8fa8-ee6d8c117614] to β€œ/home/dfish/.julia/compiled/v1.9/DistributionsExt/jl_gb7Rqe”.
    β”‚ Stacktrace:
    β”‚ [1] error(s::String)
    β”‚ @ Base ./error.jl:35
    β”‚ [2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, keep_loaded_modules::Bool)
    β”‚ @ Base ./loading.jl:2296
    β”‚ [3] compilecache
    β”‚ @ ./loading.jl:2163 [inlined]
    β”‚ [4] _require(pkg::Base.PkgId, env::Nothing)
    β”‚ @ Base ./loading.jl:1805
    β”‚ [5] _require_prelocked(uuidkey::Base.PkgId, env::Nothing)
    β”‚ @ Base ./loading.jl:1660
    β”‚ [6] _require_prelocked(uuidkey::Base.PkgId)
    β”‚ @ Base ./loading.jl:1658
    β”‚ [7] run_extension_callbacks(extid::Base.ExtensionId)
    β”‚ @ Base ./loading.jl:1255
    β”‚ [8] run_extension_callbacks(pkgid::Base.PkgId)
    β”‚ @ Base ./loading.jl:1290
    β”‚ [9] run_package_callbacks(modkey::Base.PkgId)
    β”‚ @ Base ./loading.jl:1124
    β”‚ [10] _require_prelocked(uuidkey::Base.PkgId, env::String)
    β”‚ @ Base ./loading.jl:1667
    β”‚ [11] macro expansion
    β”‚ @ ./loading.jl:1648 [inlined]
    β”‚ [12] macro expansion
    β”‚ @ ./lock.jl:267 [inlined]
    β”‚ [13] require(into::Module, mod::Symbol)
    β”‚ @ Base ./loading.jl:1611
    β”‚ [14] eval
    β”‚ @ ./boot.jl:370 [inlined]
    β”‚ [15] eval_user_input(ast::Any, backend::REPL.REPLBackend, mod::Module)
    β”‚ @ REPL ~/julia-1.9.1/share/julia/stdlib/v1.9/REPL/src/REPL.jl:153
    β”‚ [16] repl_backend_loop(backend::REPL.REPLBackend, get_module::Function)
    β”‚ @ REPL ~/julia-1.9.1/share/julia/stdlib/v1.9/REPL/src/REPL.jl:249
    β”‚ [17] start_repl_backend(backend::REPL.REPLBackend, consumer::Any; get_module::Function)
    β”‚ @ REPL ~/julia-1.9.1/share/julia/stdlib/v1.9/REPL/src/REPL.jl:234
    β”‚ [18] run_repl(repl::REPL.AbstractREPL, consumer::Any; backend_on_current_task::Bool, backend::Any)
    β”‚ @ REPL ~/julia-1.9.1/share/julia/stdlib/v1.9/REPL/src/REPL.jl:379
    β”‚ [19] run_repl(repl::REPL.AbstractREPL, consumer::Any)
    β”‚ @ REPL ~/julia-1.9.1/share/julia/stdlib/v1.9/REPL/src/REPL.jl:365
    β”‚ [20] (::Base.var"#1017#1019"{Bool, Bool, Bool})(REPL::Module)
    β”‚ @ Base ./client.jl:421
    β”‚ [21] #invokelatest#2
    β”‚ @ ./essentials.jl:816 [inlined]
    β”‚ [22] invokelatest
    β”‚ @ ./essentials.jl:813 [inlined]
    β”‚ [23] run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)
    β”‚ @ Base ./client.jl:405
    β”‚ [24] exec_options(opts::Base.JLOptions)
    β”‚ @ Base ./client.jl:322
    β”‚ [25] _start()
    β”‚ @ Base ./client.jl:522
    β”” @ Base loading.jl:1261

Running resolve and instantiate do not solve the issue. Any help would be greatly apprecaited.

1 Like

I was able to figure out how to conditionally load an imported function from Distributions based on a custom type: logpdf(d::MyType).

I was hoping that I could also functions and types not defined in another package. I tried using export, but to no avail. Is that possible?

As far as I can tell, it’s not possible to export a function only defined in the extension module. It has to be defined in a different module and imported. The example in the repo now works. I will update it if someone knows a simpler solution.