On Wed, Feb 15, 2023, at 7:51 PM, Fabian Grünbichler wrote:
> Hi,
> 
> I'm writing this mail in order to get further input from knowledgeable, but 
> not directly involved DDs - mostly those involved with cross-building and 
> multi-arch matters.

sorry for the noise - now with correct CC of debian-cr...@lists.debian.org, 
instead of the mis-pasted d-cross@ ..

> 
> Some background for those not familiar with rust packaging in Debian, skip 
> below for the actual examples and question.
> 
> The debian-rust team uses a rather unified workflow to build a large amount 
> of rust library crates and a not-quite-as-large amount of binary 
> crates/applications. Each source package (rust-foo) corresponds to a single 
> crate (rust package) released on crates.io, building one or more 
> librust-foo*-dev binary packages that actually contain the crate's (patched) 
> source code, and in case of a "bin" crate shipping an actual 
> program/application, a binary package containing the compiled executable + 
> support files (which can have an arbitrary name - usually just that of the 
> program in question). The reason that the library packages ship source code 
> in a binary package is that rust doesn't (properly) support rust->rust 
> dynamic linking (yet), so each rust executable is statically linking all it's 
> rust dependencies. This has the side-effect that what are actually 
> (transitive) build-dependencies are encoded as a mix of build-dependencies 
> (direct) and regular dependencies (transitive dependencies of direct 
> build-dependencies).
> 
> E.g., a crate foo that depends on a crate bar which in turn depends on a 
> crate baz will have the foo->bar relationship encoded as build-dependency 
> (rust-foo -> librust-bar-dev) and dependency (librust-foo-dev -> 
> librust-bar-dev, for packages [build-]depending on crate foo), while the 
> bar->baz dependency will *only* be encoded as regular dependency 
> (librust-bar-dev -> librust-baz-dev) in rust-foo's dependency tree.
> 
> debcargo, the tool used by the Debian rust team to streamline the work of 
> transforming upstream crates into Debian source packages generates d/control 
> entries for librust-* binary packages qualified as arch:any and M-A:same, in 
> order to support cross compilation. This solution was suggested by dpkg 
> developers (Guillem?) according to the following comment left in the debcargo 
> source code:
> 
>             // This is the best but not ideal option for us.
>             //
>             // Currently Debian M-A spec has a deficiency where a package X 
> that
>             // build-depends on a (M-A:foreign+arch:all) package that itself
>             // depends on an arch:any package Z, will pick up the BUILD_ARCH 
> of
>             // package Z instead of the HOST_ARCH. This is because we 
> currently
>             // have no way of telling dpkg to use HOST_ARCH when checking 
> that the
>             // dependencies of Y are satisfied, which is done at install-time
>             // without any knowledge that we're about to do a cross-compile. 
> It
>             // is also problematic to tell dpkg to "accept any arch" because 
> of
>             // the presence of non-M-A:same packages in the archive, that are 
> not
>             // co-installable - different arches of Z might be depended-upon 
> by
>             // two conflicting chains. (dpkg has so far chosen not to add an
>             // exception for the case where package Z is M-A:same 
> co-installable).
>             //
>             // The recommended work-around for now from the dpkg developers 
> is to
>             // make our packages arch:any M-A:same even though this results in
>             // duplicate packages in the Debian archive. For very large 
> crates we
>             // will eventually want to make debcargo generate -data packages 
> that
>             // are arch:all and have the arch:any -dev packages depend on it.
> 
> https://salsa.debian.org/rust-team/debcargo/-/blob/master/src/debian/control.rs#L342
> 
> Some time ago, Jonas (CCed) started packaging rust crates in the same 
> "namespace" (src:rust-foo building bin:librust-foo-*) using a slightly 
> different approach, but in a *mostly* compatible fashion. More recently, 
> Jonas started switching over his rust packages from arch:any, M-A:same (like 
> the rust team's) to arch:all, M-A:foreign. There was no agreement between the 
> Debian rust team and Jonas whether this change is problematic and should be 
> reverted (or not), after a bit of discussion we agreed on getting feedback 
> from people more involved with cross-building efforts (hence this mail).
> 
> One example of a working in practice (as in, the build doesn't fail), but 
> technically wrong (cross-)build (pulls in dependencies from wrong 
> architecture) can be found here:
> 
> https://paste.debian.net/1270516/
> 
> The chain is
> 
> rust-lscolors (arch:any) --BD--> librust-tempfile-dev (arch:any)
> librust-tempfile-dev (arch:any) --D--> librust-remove-dir-all-0.7+default-dev 
> (arch:any) --D--> librust-log-0.4+default-dev (arch:any) --D--> 
> librust-value-bag-1.0.0+serde-dev (arch:any) --D--> 
> librust-serde-fmt-1+default-dev (arch:all) --D--> librust-serde-dev 
> (arch:any, but wrongly resolved!)
> 
> with librust-serde-fmt-dev being switched to arch:all, it will resolve to 
> :amd64 instead of :i386 and in turn pull in its own dependencies 
> librust-serde-1+std-dev & librust-serde-1-dev (both provided by 
> librust-serde-dev) from amd64 (in addition to librust-serde-dev:i386, which 
> is also part of the arch:any (build-)dependency tree of rust-lscolors itself, 
> without the "hop" over librust-serde-fmt-dev).
> 
> src:rust-lscolors was taken as minimal example bin crate here - many rust 
> binary crates are affected by this issue since a few crates which are part of 
> common dependency chains are maintained by Jonas and recently got switched to 
> arch:all (serde-fmt and ahash are the two most prominent). Note that much of 
> the rust ecosystem relies on a crate called bindgen to generate rust bindings 
> for C libraries, which in turn leverages clang under the hood, which 
> unfortunately makes those packages currently not cross-compilable because 
> libclang-common-14-dev is not co-installable on multiple architectures. 
> Many/most rust-*-sys packages and crates depending on those are practically 
> not cross-compilable for this reason (in addition to pulling in packages from 
> the wrong architecture via arch:all, as described above).
> 
> Another example would be src:rust-hashbrown, which directly build-depends on 
> librust-ahash-0.7-dev which got switched to arch:all, cross building it on an 
> amd64 machine for i386 with
> 
> DEB_BUILD_OPTIONS='' sbuild -c debian-unstable-amd64-sbuild -d unstable 
> --host i386 --profiles cross rust-hashbrown_0.12.3-1.dsc
> 
> will pull in all librust-* packages from the wrong architecture (am64 instead 
> of i386):
> 
> $ grep -E '^Get.*librust-serde' rust-hashbrown_0.12.3-1_i386.build
> 
> Get:144 http://deb.debian.org/debian unstable/main amd64 librust-cfg-if-dev 
> amd64 1.0.0-1 [10.4 kB]
> Get:145 http://deb.debian.org/debian unstable/main amd64 librust-libc-dev 
> amd64 0.2.139-1 [290 kB]
> [ .. snip lots of librust-*-dev amd64 downloads ..]
> Get:170 http://deb.debian.org/debian unstable/main amd64 
> librust-version-check-dev amd64 0.9.4-1 [15.9 kB]
> Get:171 http://deb.debian.org/debian unstable/main amd64 
> librust-ahash-0.7-dev all 0.7.6-11 [477 kB]
> 
> Reverting librust-ahash-0.7-dev to arch:any, M-A:same (and injecting both the 
> resulting amd64 and i386 package into the build env, to override the arch:all 
> one from the archive) makes the cross-build correctly only pull in 
> librust-*-dev packages from i386.
> 
> TL;DR: Is the switch to arch:all one that should be reverted in the face of 
> it apparently breaking cross builds? Or is there another alternative 
> (nowadays) that makes the "workaround" employed by debcargo no longer needed?
> 
> Depending on feedback, the rust team would either ask Jonas to switch back 
> his packages to arch:any, M-A:same (probably after bookworm, to prevent 
> further fallout/need for RMs/.. during the freeze), or will evaluate whether 
> switching to arch:all is an option for debcargo-managed packages as well, and 
> which changes on the team tooling side are needed to avoid losing test 
> coverage or increasing friction.
> 
> Thanks for reading and any informed input,
> Fabian

Reply via email to