Dealing with optional dependencies in v1.5?

I’ve been having an issue for a long time with Compose and its optional Cairo backend. Compose uses Requires.jl to support Cairo. This works fine unless you make a new package that uses both :

module TestCompose
    using Cairo
    using Compose

    import Compose.absolute_native_units            
end 

This throws a warning, showing that the Cairo optional code hasn’t been loaded :

julia> using TestCompose
[ Info: Precompiling TestCompose [8e4707c8-58a9-410c-9b10-f498f0d6d1ed]
WARNING: could not import Compose.absolute_native_units into TestCompose

Previously I would force Compose to load compose to load Cairo code using @eval, but in v1.5 this had been turned into a precompilation error (instead of a warning).

I’ve tried to do it from __init__() too and it does work when using the module in isolation but If you try to use it in another module it crashes again at precompilation.

function __init__()
    Compose.link_cairo() #or @eval...
end

Any way to make this work ? It’s not clear to me if it’s an issue with my code, Compose, or Require.

The error message tells me not to do this, but not what to do :

ERROR: LoadError: InitError: Evaluation into the closed module `Compose` breaks incremental compilation because the side effects will not be permanent. This is likely due to some other module mutating `Compose` with `eval` during precompilation - don't do this.

I haven’t thought about the actual problem much, but you might be able to work around that InitError by only running link_cairo when

isprecompiling() = ccall(:jl_generating_output, Cint, ()) == 1

returns false.

2 Likes

That works yes, thanks. Feels a bit like a hack though.

On the other hand the startup time is awesome on v1.5, I haven’t timed it but it almost feels fast.