slint icon indicating copy to clipboard operation
slint copied to clipboard

switch to yeslogic-fontconfig-sys from servo-fontconfig

Open Be-ing opened this issue 3 years ago • 9 comments

to use dlopen for fontconfig instead of linking fontconfig at build time. This allows for easier cross compilation, which I am using to cross compile from x86_64-unknown-linux-gnu to aarch64-unknown-linux-gnu with cross:

image

Blocked by:

  • [x] https://github.com/yeslogic/fontconfig-rs/pull/12
  • [x] https://github.com/servo/font-kit/pull/192
  • [ ] https://github.com/38/plotters/pull/337

Be-ing avatar Feb 16 '22 07:02 Be-ing

CLA assistant check
All committers have signed the CLA.

CLAassistant avatar Feb 16 '22 07:02 CLAassistant

The PR for font-kit was finally merged. I'll make a PR for plotters soon.

Be-ing avatar Mar 28 '22 16:03 Be-ing

Yay, that's good news!

tronical avatar Mar 28 '22 17:03 tronical

PR for plotters: https://github.com/38/plotters/pull/337

Be-ing avatar Mar 29 '22 02:03 Be-ing

I am puzzled by the build errors on CI for font-kit. I cannot reproduce them locally.

error[E0425]: cannot find function, tuple struct or tuple variant `FcInitLoadConfigAndFonts` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:320:25
    |
320 |                         FcInitLoadConfigAndFonts,
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcConfigDestroy` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:333:21
    |
333 |                     FcConfigDestroy,
    |                     ^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcPatternCreate` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:359:21
    |
359 |                     FcPatternCreate,
    |                     ^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcNameParse` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:371:21
    |
371 |                     FcNameParse,
    |                     ^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcPatternAddString` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:384:21
    |
384 |                     FcPatternAddString,
    |                     ^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcConfigSubstitute` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:401:21
    |
401 |                     FcConfigSubstitute,
    |                     ^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcDefaultSubstitute` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:415:21
    |
415 |                     FcDefaultSubstitute,
    |                     ^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcFontSort` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:428:21
    |
428 |                     FcFontSort,
    |                     ^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcFontList` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:452:21
    |
452 |                     FcFontList,
    |                     ^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcPatternDestroy` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:473:21
    |
473 |                     FcPatternDestroy,
    |                     ^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcPatternGetString` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:493:21
    |
493 |                     FcPatternGetString,
    |                     ^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcPatternGetInteger` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:521:21
    |
521 |                     FcPatternGetInteger,
    |                     ^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcFontSetDestroy` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:577:21
    |
577 |                     FcFontSetDestroy,
    |                     ^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcObjectSetCreate` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:593:81
    |
593 |                     d: ffi_dispatch!(feature = "source-fontconfig-dlopen", LIB, FcObjectSetCreate,),
    |                                                                                 ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcObjectSetAdd` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:607:25
    |
607 |                         FcObjectSetAdd,
    |                         ^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function, tuple struct or tuple variant `FcObjectSetDestroy` in this scope
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:623:21
    |
623 |                     FcObjectSetDestroy,
    |                     ^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0699]: the type of this value must be known to call a method on a raw pointer on it
Error:    --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/font-kit-0.11.0/src/sources/fontconfig.rs:503:27
    |
503 |                 if string.is_null() {
    |                           ^^^^^^^

Be-ing avatar Mar 31 '22 02:03 Be-ing

I figured out the compile error. The combination of --workspace and --all-features as the CI uses and feature-resolver = 2 in the workspace's Cargo.toml created a strange situation. The plotter example was depending on yeslogic-fontconfig-sys with the dlopen feature because of i-slint-backend-gl and i-slint-compiler's fontconfig-dlopen features. However, plotters did not activate the source-fontconfig-dlopen feature of font-kit required for font-kit to work with yeslogic-fontconfig-sys's dlopen feature:

$ cargo tree --workspace -f "{p} {f}" -i yeslogic-fontconfig-sys --all-features

...

yeslogic-fontconfig-sys v3.0.0 dlopen
├── font-kit v0.11.0 default,source
│   └── plotters v0.3.1 (https://github.com/Be-ing/plotters.git?branch=font-kit-update#cc2c2ffd) bitmap_backend,font-kit,lazy_static,pathfinder_geometry,plotters-bitmap,surface_series,ttf,ttf-parser
│       └── plotter v0.2.2 (/home/be/sw/slint/examples/plotter) 
├── i-slint-backend-gl v0.2.2 (/home/be/sw/slint/internal/backends/gl) default,fontconfig-dlopen,resvg,rtti,svg,tiny-skia,usvg,wayland,x11 (*)
└── i-slint-compiler v0.2.2 (/home/be/sw/slint/internal/compiler) codemap,codemap-diagnostic,cpp,display-diagnostics,fontconfig-dlopen,proc-macro2,proc_macro_span,quote,rust
    ├── slint-build v0.2.2 (/home/be/sw/slint/api/rs/build) default
    │   [build-dependencies]
    │   ├── gallery v0.2.2 (/home/be/sw/slint/examples/gallery) 
    │   ├── imagefilter v0.2.2 (/home/be/sw/slint/examples/imagefilter) 
    │   ├── memory v0.2.2 (/home/be/sw/slint/examples/memory) 
    │   ├── opengl_underlay v0.2.2 (/home/be/sw/slint/examples/opengl_underlay) 
    │   ├── plotter v0.2.2 (/home/be/sw/slint/examples/plotter) 
    │   ├── printerdemo v0.2.2 (/home/be/sw/slint/examples/printerdemo/rust) 
    │   ├── printerdemo_mcu v0.2.2 (/home/be/sw/slint/examples/printerdemo_mcu) chrono,mcu-pico-st7789,mcu-simulator
    │   ├── printerdemo_old v0.2.2 (/home/be/sw/slint/examples/printerdemo_old/rust) 
    │   ├── slide_puzzle v0.2.2 (/home/be/sw/slint/examples/slide_puzzle) 
    │   └── todo v0.2.2 (/home/be/sw/slint/examples/todo/rust) 
    │   [dev-dependencies]
    │   └── slint v0.2.2 (/home/be/sw/slint/api/rs/slint) backend-gl-all,backend-gl-wayland,backend-gl-x11,backend-qt,compat-0-2-0,default,document-features,std (*)
    ├── slint-compiler v0.2.2 (/home/be/sw/slint/tools/compiler) 
    ├── slint-fmt v0.2.2 (/home/be/sw/slint/tools/fmt) 
    ├── slint-interpreter v0.2.2 (/home/be/sw/slint/internal/interpreter) backend-gl-all,backend-gl-wayland,backend-gl-x11,backend-qt,compat-0-2-0,default,display-diagnostics,document-features,ffi,spin_on,std (*)
    ├── slint-lsp v0.2.2 (/home/be/sw/slint/tools/lsp) backend-gl-all,backend-gl-wayland,backend-gl-x11,backend-qt,default
    ├── slint-node v0.2.2 (/home/be/sw/slint/api/node/native) 
    └── syntax_updater v0.2.2 (/home/be/sw/slint/tools/syntax_updater) 
    [dev-dependencies]
    ├── doctests v0.2.2 (/home/be/sw/slint/tests/doctests) 
    └── test-driver-cpp v0.2.2 (/home/be/sw/slint/tests/driver/cpp)

I resolved this by adding a fontconfig-dlopen feature to plotters to activate font-kit's source-fontconfig-dlopen feature in https://github.com/38/plotters/pull/337 then exposing it as a feature in the plotter example. This way --workspace --all-features activates font-kit's source-fontconfig-dlopen feature when the fontconfig-dlopen features of i-slint-backend-gl and i-slint-compiler are enabled by --all-features.

$ cargo tree --workspace -f "{p} {f}" -i yeslogic-fontconfig-sys --all-features

...

yeslogic-fontconfig-sys v3.0.1 dlopen
├── font-kit v0.11.0 default,source,source-fontconfig-dlopen,yeslogic-fontconfig-sys
│   └── plotters v0.3.1 (https://github.com/Be-ing/plotters.git?branch=font-kit-update#fec5dc7c) bitmap_backend,font-kit,fontconfig-dlopen,lazy_static,pathfinder_geometry,plotters-bitmap,surface_series,ttf,ttf-parser
│       └── plotter v0.2.2 (/home/be/sw/slint/examples/plotter) fontconfig-dlopen
├── i-slint-backend-gl v0.2.2 (/home/be/sw/slint/internal/backends/gl) default,fontconfig-dlopen,resvg,rtti,svg,tiny-skia,usvg,wayland,x11 (*)
└── i-slint-compiler v0.2.2 (/home/be/sw/slint/internal/compiler) codemap,codemap-diagnostic,cpp,display-diagnostics,fontconfig-dlopen,proc-macro2,proc_macro_span,quote,rust
    ├── slint-build v0.2.2 (/home/be/sw/slint/api/rs/build) default
    │   [build-dependencies]
    │   ├── gallery v0.2.2 (/home/be/sw/slint/examples/gallery) 
    │   ├── imagefilter v0.2.2 (/home/be/sw/slint/examples/imagefilter) 
    │   ├── memory v0.2.2 (/home/be/sw/slint/examples/memory) 
    │   ├── opengl_underlay v0.2.2 (/home/be/sw/slint/examples/opengl_underlay) 
    │   ├── plotter v0.2.2 (/home/be/sw/slint/examples/plotter) fontconfig-dlopen
    │   ├── printerdemo v0.2.2 (/home/be/sw/slint/examples/printerdemo/rust) 
    │   ├── printerdemo_mcu v0.2.2 (/home/be/sw/slint/examples/printerdemo_mcu) chrono,mcu-pico-st7789,mcu-simulator
    │   ├── printerdemo_old v0.2.2 (/home/be/sw/slint/examples/printerdemo_old/rust) 
    │   ├── slide_puzzle v0.2.2 (/home/be/sw/slint/examples/slide_puzzle) 
    │   └── todo v0.2.2 (/home/be/sw/slint/examples/todo/rust) 
    │   [dev-dependencies]
    │   └── slint v0.2.2 (/home/be/sw/slint/api/rs/slint) backend-gl-all,backend-gl-wayland,backend-gl-x11,backend-qt,compat-0-2-0,default,document-features,std (*)
    ├── slint-compiler v0.2.2 (/home/be/sw/slint/tools/compiler) 
    ├── slint-fmt v0.2.2 (/home/be/sw/slint/tools/fmt) 
    ├── slint-interpreter v0.2.2 (/home/be/sw/slint/internal/interpreter) backend-gl-all,backend-gl-wayland,backend-gl-x11,backend-qt,compat-0-2-0,default,display-diagnostics,document-features,ffi,spin_on,std (*)
    ├── slint-lsp v0.2.2 (/home/be/sw/slint/tools/lsp) backend-gl-all,backend-gl-wayland,backend-gl-x11,backend-qt,default
    ├── slint-node v0.2.2 (/home/be/sw/slint/api/node/native) 
    └── syntax_updater v0.2.2 (/home/be/sw/slint/tools/syntax_updater) 
    [dev-dependencies]
    ├── doctests v0.2.2 (/home/be/sw/slint/tests/doctests) 
    └── test-driver-cpp v0.2.2 (/home/be/sw/slint/tests/driver/cpp)

Be-ing avatar Apr 05 '22 00:04 Be-ing

Using this branch, I got my application to cross compile to ARM64 on Fedora without even using Cross or a container. I had to install a cross toolchain with sudo dnf install aarch64-linux-gnu-{binutils,gcc,glibc} and add this to ~/.cargo/config.toml:

[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
ar = "aarch64-linux-gnu-gcc-ar"

then it just worked with

RUST_FONTCONFIG_DLOPEN=on RUST_JACK_DLOPEN=on cargo build --target aarch64-unknown-linux-gnu --no-default-features --features wayland

Be-ing avatar Apr 05 '22 03:04 Be-ing

I have the feeling that dlopen should actually be the default.

I think that would be difficult to change at this point. build.rs behaves the same way using the same RUST_FONTCONFIG_DLOPEN environment variable up and down the stack from yeslogic-fontconfig-sys, fontconfig, font-kit, i-slint-backend-gl, and i-slint-compiler.

I know that packagers don't like it, but they can play with compilation flags

They can't with the way it is now because the build.rs's mentioned above only check if the environment variable is set. There is not a way to disable dlopening with the environment variable because that is the default behavior.

Be-ing avatar Apr 05 '22 05:04 Be-ing

I have the feeling that dlopen should actually be the default.

I discussed this with @decathorpe who does a lot of Rust packaging for Fedora and his opinion is that linking should generally be the default. If Slint can work without fontconfig, it could be okay to make dlopen the default, but Slint is not written to handle the case of fontconfig not being available. Of course if we could replace the fontconfig C library with a pure Rust solution, that would be best.

Be-ing avatar Apr 06 '22 15:04 Be-ing

The combination of --workspace and --all-features as the CI uses and feature-resolver = 2 in the workspace's Cargo.toml created a strange situation. The plotter example was depending on yeslogic-fontconfig-sys with the dlopen feature because of i-slint-backend-gl and i-slint-compiler's fontconfig-dlopen features. However, plotters did not activate the source-fontconfig-dlopen feature of font-kit required for font-kit to work with yeslogic-fontconfig-sys's dlopen feature:

I resolved this by adding a fontconfig-dlopen feature to plotters to activate font-kit's source-fontconfig-dlopen feature in https://github.com/plotters-rs/plotters/pull/337 then exposing it as a feature in the plotter example. This way --workspace --all-features activates font-kit's source-fontconfig-dlopen feature when the fontconfig-dlopen features of i-slint-backend-gl and i-slint-compiler are enabled by --all-features.

Simpler solution: don't expose fontconfig-dlopen features in i-slint-backend-winit and i-slint-compiler. There's not much point exposing these if they aren't exposed in the user-facing slint crate anyway. The RUST_FONTCONFIG_DLOPEN=ON environment variable needs to be set to enable dlopen'ing.

Be-ing avatar Sep 30 '22 16:09 Be-ing

Rebased and CI passed. Let's get this merged and not let it bitrot again.

Be-ing avatar Sep 30 '22 17:09 Be-ing