GiovineItalia / Compose.jl

Declarative vector graphics
http://giovineitalia.github.io/Compose.jl/latest/
Other
248 stars 83 forks source link

Revise + Requires + Cairo + Fontconfig + Compose produces a pango error #402

Open dehann opened 3 years ago

dehann commented 3 years ago

Hi -- has anyone seen this before...

The error below does not occur when just doing:

julia> using Cairo, Fontconfig
julia> using Compose

However, there seems to be some difficulty when using Revise (a VSCode default) with Compose + Cairo + Fontconfig:

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.5.0 (2020-08-01)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using Revise
julia> using Cairo, Fontconfig
julia> using Compose

julia> ┌ Error: evaluation error starting at /home/dehann/.julia/dev/Compose/src/pango.jl:30
│   mod = Compose
│   ex =
│    quote
│        #= /home/dehann/.julia/dev/Compose/src/pango.jl:28 =#
│        let available_font_families = Set{AbstractString}()
│            #= /home/dehann/.julia/dev/Compose/src/pango.jl:29 =#
│            for font_pattern = Fontconfig.list()
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:30 =#
│                push!(available_font_families, lowercase(Fontconfig.format(font_pattern, "%{family}")))
│            end
│            #= /home/dehann/.julia/dev/Compose/src/pango.jl:33 =#
│            meta_families = Set(["serif", "sans", "sans-serif", "monospace", "cursive", "fantasy"])
│            #= /home/dehann/.julia/dev/Compose/src/pango.jl:35 =#
│            global match_font
│            #= /home/dehann/.julia/dev/Compose/src/pango.jl:36 =#
│            function match_font(families::AbstractString, size::Float64)
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:36 =#
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:37 =#
│                matched_family = "sans-serif"
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:38 =#
│                for family = [lowercase(strip(family, [' ', '"', '\''])) for family = split(families, ',')]
│                    #= /home/dehann/.julia/dev/Compose/src/pango.jl:39 =#
│                    if family in available_font_families || family in meta_families
│                        #= /home/dehann/.julia/dev/Compose/src/pango.jl:40 =#
│                        matched_family = family
│                        #= /home/dehann/.julia/dev/Compose/src/pango.jl:41 =#
│                        break
│                    end
│                end
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:44 =#
│                family = Fontconfig.format(match(Fontconfig.Pattern(family = matched_family)), "%{family}")
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:45 =#
│                desc = #= /home/dehann/.julia/dev/Compose/src/pango.jl:45 =# @sprintf("%s %fpx", family, size)
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:46 =#
│                fd = ccall((:pango_font_description_from_string, libpango), Ptr{Cvoid}, (Ptr{UInt8},), desc)
│                #= /home/dehann/.julia/dev/Compose/src/pango.jl:47 =#
│                return fd
│            end
│        end
│    end
│   exception =
│    UndefRefError: access to undefined reference
│    Stacktrace:
│     [1] getindex at ./array.jl:809 [inlined]
│     [2] lookup_var at /home/dehann/.julia/packages/JuliaInterpreter/RmxVj/src/interpret.jl:4 [inlined]
│     [3] collect_args(::JuliaInterpreter.Frame, ::Expr; isfc::Bool) at /home/dehann/.julia/packages/JuliaInterpreter/RmxVj/src/interpret.jl:60
└ @ Revise ~/.julia/packages/Revise/BqeJF/src/lowered.jl:106
WARNING: redefinition of constant pango_attrs. This may fail, cause incorrect answers, or produce other errors.

Attempt to Fix

I had similar-ish problems elsewhere when Requires.jl inputs use a begin end block -- i.e. this is "bad":

function __init__()
    @require SomePkg="abc123..." begin
      @info "Doing stuff"
      include("MoreUtils.jl")
    end
end

but not when doing include directly:

function __init__()
    @require SomePkg="abc123..." include("MoreUtils.jl")
end

So I have been changing to this all over (e.g. IncrementalInference.jl 845)

cc @timholy (Hi) since this might relate to timholy/Revise.jl#520


Different Error with Compose

I have been attempting to fix locally by doing the same pattern, but then ccall starts having issues. The current @require code looks like this https://github.com/GiovineItalia/Compose.jl/blob/121510649e9c195545881a824916d6a81580ddc1/src/Compose.jl#L156-L180

But when I change to this:

function link_fontconfig()
    @debug "Loading Fontconfig backend into Compose.jl"
    include(joinpath(@__DIR__, "pango.jl"))  # THIS IS THE ATTEMPT 2/2

   pango_cairo_ctx[] = C_NULL

    ccall((:g_type_init, libgobject), Cvoid, ())
    pango_cairo_fm[]  = ccall((:pango_cairo_font_map_new, libpangocairo),
                               Ptr{Cvoid}, ())
    pango_cairo_ctx[] = ccall((:pango_font_map_create_context, libpango),
                               Ptr{Cvoid}, (Ptr{Cvoid},), pango_cairo_fm[])
    pangolayout[] = PangoLayout()
end

function link_cairo()
    @debug "Loading Cairo backend into Compose.jl"
    include(joinpath(@__DIR__,"cairo_backends.jl"))
    include(joinpath(@__DIR__,"immerse_backend.jl"))
end

function __init__()
    @require Cairo="159f3aea-2a34-519c-b102-8c37f9878175" link_cairo()
    # THIS IS THE ATTEMPT 1/2
    @require Fontconfig="186bb1d3-e1f7-5a2c-a377-96d770f13627" link_fontconfig()
end

But then this happens (WITHOUT using Revise):

julia> using Cairo, Fontconfig
julia> using Compose

[ Info: Precompiling Compose [a81c6b42-2e10-5240-aca2-a61377ecd94b]
┌ Warning: Error requiring Fontconfig from Compose:
│ TypeError: in ccall: first argument not a pointer or valid constant expression, expected Ptr, got a value of type Tuple{Symbol,String}
│ Stacktrace:
│  [1] link_fontconfig() at /home/dehann/.julia/dev/Compose/src/Compose.jl:162
│  [2] top-level scope at none:1
│  [3] eval at ./boot.jl:331 [inlined]
│  [4] eval at /home/dehann/.julia/dev/Compose/src/Compose.jl:1 [inlined]
│  [5] (::Compose.var"#119#125")() at /home/dehann/.julia/packages/Requires/qy6zC/src/require.jl:85
│  [6] err(::Any, ::Module, ::String) at /home/dehann/.julia/packages/Requires/qy6zC/src/require.jl:42
│  [7] (::Compose.var"#118#124")() at /home/dehann/.julia/packages/Requires/qy6zC/src/require.jl:84
│  [8] withpath(::Any, ::String) at /home/dehann/.julia/packages/Requires/qy6zC/src/require.jl:32
│  [9] (::Compose.var"#117#123")() at /home/dehann/.julia/packages/Requires/qy6zC/src/require.jl:83
│  [10] listenpkg(::Any, ::Base.PkgId) at /home/dehann/.julia/packages/Requires/qy6zC/src/require.jl:15
│  [11] macro expansion at /home/dehann/.julia/packages/Requires/qy6zC/src/require.jl:81 [inlined]
│  [12] __init__() at /home/dehann/.julia/dev/Compose/src/Compose.jl:178
│  [13] _include_from_serialized(::String, ::Array{Any,1}) at ./loading.jl:697
│  [14] _require_from_serialized(::String) at ./loading.jl:749
│  [15] _require(::Base.PkgId) at ./loading.jl:1040
│  [16] require(::Base.PkgId) at ./loading.jl:928
│  [17] require(::Module, ::Symbol) at ./loading.jl:923
│  [18] eval(::Module, ::Any) at ./boot.jl:331
│  [19] eval_user_input(::Any, ::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:134
│  [20] repl_backend_loop(::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:195
│  [21] start_repl_backend(::REPL.REPLBackend, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:180
│  [22] run_repl(::REPL.AbstractREPL, ::Any; backend_on_current_task::Bool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:292
│  [23] run_repl(::REPL.AbstractREPL, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288
│  [24] (::Base.var"#806#808"{Bool,Bool,Bool,Bool})(::Module) at ./client.jl:399
│  [25] #invokelatest#1 at ./essentials.jl:710 [inlined]
│  [26] invokelatest at ./essentials.jl:709 [inlined]
│  [27] run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool) at ./client.jl:383
│  [28] exec_options(::Base.JLOptions) at ./client.jl:313
│  [29] _start() at ./client.jl:506
└ @ Requires ~/.julia/packages/Requires/qy6zC/src/require.jl:44

For Reference

Pretty sure I'm on the latest packages, and

julia> versioninfo()
Julia Version 1.5.0
Commit 96786e22cc (2020-08-01 23:44 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-9.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 6
timholy commented 3 years ago

Thanks for the detailed investigation! I'm sorry for this annoying warning. I don't think it's hurting anything serious, but I really do need to get to it sometime soon.