tectonic icon indicating copy to clipboard operation
tectonic copied to clipboard

Cannot link with other crates that use *-sys crates

Open drahnr opened this issue 1 year ago • 1 comments

When attempting to link tectonic within a project that also uses resvg, it turned out to be rather hairy.

resvg has a linkage dependency on i.e. harfbuzz through harfbuzz-sys, fontconfig through fontconfig-sys and a few more.

There is no good solution in rust to avoid the double linkage other than to modify the dependencies, at least I couldn't find one to convince cargo ov.

Solution proposal:

Expose a feature flag, that allows to not link the system library via the links=.. cargo manifest key, but link in harfbuzz-sys just for the sake of consuming linkage. That way harfbuzz-sys will be linked sufficiently early, and the duplication is avoided.

I am happy to implement it, if there is interest in such a feature

drahnr avatar Dec 12 '22 07:12 drahnr

Thanks for raising this issue. I am actually a little surprised that it has not cropped up earlier.

The key challenge here — and the reason that Tectonic does not just depend on standard *-sys crates — is that it has several tiers of C/C++ code that go along with the Rust code, split among several crates, and depending on several system libraries that might depend on each other as well. This leads to two unusual challenges that most *-sys crates do not need to address:

  1. The build.rs script needs to be aware of these potential interdependencies and honor them appropriately. (For instance, the tectonic_bridge_harfbuzz crate depends on tectonic_bridge_graphite2 and tectonic_bridge_icu.)
  2. The headers and prototypes provided by the libraries need to be made available for the C/C++ code in the crates that depend on them. This can be accomplished using environment variables like DEP_HARFBUZZ_INCLUDE_PATH, which are created by printing out the right magic lines in the build.rs scripts.

So, basically, for dependencies like Harfbuzz, Tectonic needs to build it with build.rs script that is more specialized and customized than a generic harfbuzz-sys crate.

Given all that, I would think that it might be more tractable to get resvg to use Tectonic's Harfbuzz bridge crate, rather than the other way around. This would, however, require duplicating the Rust-to-C/C++ interfaces provided by harfbuzz-sys — Tectonic doesn't provide those since it only has C/C++ code invoking Harfbuzz (for now), not Rust code. But I would be open to adding Rust interfaces to enable precisely this kind of use case, and also because we'll hopefully be gradually replacing C/C++ code with Rust.

If you do want to try to implement something within Tectonic, I am definitely also open to contributions that make it possible to use harfbuzz-sys as an option. I think there will be some challenges but for constrained use cases, maybe it won't be so hard to get working.

pkgw avatar Jan 09 '23 15:01 pkgw