Hi Thanks for the previous review.I think I never got around to tackle the Multi-Arch understanding issues that you had and my last attempt seems to have gotten lost in the mail ( I do not see it on the mailing list). I am deliberately re-quoting a bit further up for the full context with the goal of aiding you by not requiring you to dig through old emails for context, should you be missing it.
If we can get through this bit, then I feel I am ready to submit these texts for translations.
Justin B Rye:
#. [Hover Doc] Extended description for the field itself [Markdown]. Shown in #. hover docs (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml #, python-brace-format msgctxt "Stanza:Package|Field:Multi-Arch" msgid """**Advanced field**.*This field covers an advanced topic. If you are new to packaging, you are*\n" "*advised to leave it at its default until you have a working basic package or lots of time to understand*\n""*this topic.*\n" "\n" "This field is used to declare the Multi-Arch interface of the package.\n" "\n" "The `Multi-Arch` field is used to inform the installation system (APT and dpkg) about how it should handle\n" "dependency relations involving this package and foreign architectures. This is useful for multiple purposes\n" "such as cross-building without emulation and installing 32-bit packages on a 64-bit system. The latter is\n" "often done to use legacy apps or old games that was never ported to 64-bit machines.\n"One problem here, our old friend number agreement: were never ported."\n" "**Example**:\n" "```\n" "Multi-Arch: foreign\n" "```\n" "\n" "The rules for `Multi-Arch` can be quite complicated, but in many cases the following simple rules of thumb\n" "gets you a long way:\n"get Speaking of rules of thumb, the rule of thumb for number agreement is that English likes to keep its -s endings evenly distributed. Singular subjects take -s on the verb not the verb, plural ones take -s on the noun not the verb."\n" " * If the [Multi-Arch hinter] comes with a hint, then it almost certainly correct. You are recommended\n" " to check the hint for further details (some changes can be complicated to do). Note that the\n" " Multi-Arch hinter is only run for official Debian packages and may not be applicable to your case.\n" "\n"Does "comes with" here mean "comes up with"? I'd suggest " * If the [Multi-Arch hinter] offers a hint, then it is almost certainly correct. You are recommended\n"" * If you have an `Architecture: all` data-only package, then it often want to be `Multi-Arch: foreign`\n"Number: wants."\n" " * If you have an architecture dependent package, where everything is installed in\n" " `/usr/lib/${DEB_HOST_MULTIARCH}` (plus a bit of standard documentation in `/usr/share/doc`), then\n" " you*probably* want `Multi-Arch: same`. Note that when using `debputy` as the build helper, `debputy`\n" " will automatically detect the most common variants of this case and sets the field for you when\n" " relevant.\n"If that's "debputy will detect foo and will set bar" then you need the infinitive: "and set the field for you"."\n" " * If none of the above applies, then omit the field unless you know what you are doing or you are\n" " receiving advice from a Multi-Arch expert.\n" "\n" "\n" "There are 4 possible values for the Multi-Arch field, though not all values are applicable to all\n" "packages:\n" "\n" " * `no` - The default. The package can be installed for at most one architecture at the time. It can\n" "*only* satisfy relations for the same architecture as itself. Note that `Architecture: all` packages\n" " are considered as a part of the system's \"primary\" architecture (see output of\n" " `dpkg --print-architecture`).\n"Here and below, s/at the time/at a time/, but see pedantry above about how*any* package can be installed on (for instance) both amd64 and sh4 simultaneously - what we mean to say here is that any given *build* can only be used on one particular architecture. " * `no` - The default. A given build of this package can only be installed on one particular architecture.\n""\n" " Use of an explicit `no` over omitting the field is commonly done to signal that someone took the\n" " effort to understand the situation and concluded `no` was the right answer.\n"" Using an explicit `no` instead of omitting the field is commonly done to signal that someone took the\n""\n" " Note: Despite the `no`, the package*can* be installed for a foreign architecture (e.g. you can\n" " install a 32-bit version of a package on a 64-bit system). However, packages depending on it must\n" " also be installed for the foreign architecture.\n" "\n" " * `foreign` - The package can be installed for at most one architecture at the time. However, it can\n"" * `foreign` - A given build of this package can only be installed on one particular architecture."" satisfy relations for packages regardless of their architecture. This is often useful for packages\n" " solely providing data or binaries that have \"Multi-Arch neutral interfaces\". Sadly, describing\n" " a \"Multi-Arch neutral interface\" is hard and often only done by Multi-Arch experts on a case-by-case\n" " basis. Among other, scripts despite being the same on all architectures can still have a\n"Among other things or perhaps you really want For instance," \"non-neutral Multi-Arch\" interface if their output is architecture dependent or if their dependencies\n" " force them out of the `foreign` role. The dependency issue usually happens when depending indirectly\n" " on an `Multi-Arch: allowed` package.\n" "\n" " Some programs have \"Multi-Arch dependent interfaces\" and are not safe to declare as\n" " `Multi-Arch: foreign`. The name `foreign` refers to the fact that the package can satisfy relations\n" " for native*and foreign* architectures at the same time.\n" "\n" " * `same` - The same version of the package can be co-installed for multiple architecture. However,\n"No, sorry, I give up. I thought I understood what this was saying, but then I can't see how "co-installed" fits in. If it's one single version of one binary package that works for multiple architectures, what does it mean to talk about it being "co-installed"? What*with*? I can at least diagnose a number error: you want "multiple architectures".
A key feature of `Multi-Arch: same` is that you can simultaneously install the same package (name + version) for different architectures on the system. As an example, suppose you wanted the amd64 variant (64-bit) of pkg-a and the i386 variant (32-bit) of pkg-b with both of them depending on pkg-c.
If pkg-c is `Multi-Arch: same`, then what happens is that apt will install the following packages:
* pkg-c version X for i386 * pkg-c version X for amd64 * pkg-a version Y for amd64 * pkg-b version Z for i386In other words, you have pkg-c *twice* but each built for a different architecture. The technical term used here is "co-installation" or "co-installable" (see https://wiki.debian.org/Multiarch and https://wiki.debian.org/Multiarch/HOWTO as existing literature that uses "co-install*").
The way this works is that pkg-a (amd64) "sees" the amd64 variant as pkg-c while pkg-b (i386) "sees" the i386 variant - that is, they see the pkg-c built for the "same" architecture as package itself was built for.
" for this to work, the package **must** ship all files in architecture unique paths (usually\n" " beneath `/usr/lib/${DEB_HOST_MULTIARCH}`) **or** have bit-for-bit identical content in files\n" " that are in non-architecture unique paths (e.g. `/usr/share/doc`). Note that these packages\n" " typically do not contain configuration files or `dpkg` `conffile`s.\n" "\n" " The name `same` refers to the fact that the package can satisfy relations only for the \"same\"\n" " architecture as itself. However, in this case, it is co-installable with itself as noted above.\n"This makes no sense to me.
Hopefully, what I am getting at is more clear now. Another phrase used from the wiki page above is:
"""To enable more than one architecture version of a package to be installed at the **same** time (generally libraries and dev- packages) files need to be moved so they don't clash. These packages are marked 'Multi-Arch: same'.
"""My goal is that "hook" the term with something memorable that explains what it does in a way that helps the reader remember it and tell it apart from the others. I feel `same` here ends in the same problem we have with `any` vs. `all` in the `Architecture` field, where people confuse the two.
"\n" " Note: This value **cannot** be used with `Architecture: all`.\n" "\n" " * `allowed` - **Advanced value**. This value is for a complex use-case that most people do not\n" " need. Consider it only if none of the other values seem to do the trick.\n" "\n" " The package is **NOT** co-installable with itself but can satisfy Multi-Arch `foreign` and Multi-Arch\n" " `same` relations at the same. This is useful for implementations of scripting languages\n" " (e.g. Perl or Python). Here the interpreter contextually need to satisfy some relations as\n" " `Multi-Arch: foreign` and others as `Multi-Arch: same` (or `Multi-Arch: no`).\n"I think that's "needs to satisfy", but if this is more complicated than "same", I don't understand it and can't review it.
Once you understand "same" and "foreign", "allowed" is not that much more difficult. However, it is almost never needed, so I am happy scaring people away from it by default - especially to avoid people using "allowed" when they should have picked one of the other values.
To go over the Multi-Arch values with the example from before. Imagine you want pkg-a (amd64) and pkg-b (i386) installed on the system. Both depend on pkg-c to be installed.
* If pkg-c is `Multi-Arch: no` (or the field is omitted), then this is not possible. The `apt` tool will abort with an error, and you are forced to pick either pkg-a or pkg-b, but you can never have both. * If pkg-c is `Multi-Arch: same`, then as explained above, you end up with pkg-a (amd64) + pkg-c (amd64) and pkg-b (i386) + pkg-c (i386) * If pkg-c is `Multi-Arch: foreign`, then you end up with - pkg-a (amd64) - pkg-b (i386) - pkg-c (amd64 OR i386) That is, you will have pkg-c installed. It might be built for amd64 or for i386 (apt decides which you get), but it is only installed once. It is not possible to have pkg-c installed twice (a difference to `Multi-Arch: same`).These are the 3 "simple" Multi-Arch values. The `allowed` comes with a twist. Up till now, all the scenarios have been decided entirely based on pkg-c and its Multi-Arch value. However, if pkg-c is `Multi-Arch: allowed` then the scenario depends on pkg-a or/and pkg-b.
Case 1) If pkg-a and pkg-b both have "Depends: pkg-c", then this ends up like the `Multi-Arch: no`-case. Case 2) If pkg-a and pkg-b both have "Depends: pkg-c:any", then this ends up like the `Multi-Arch: foreign`-case. Case 3) If pkg-a has "Depends: pkg-c:any" and pkg-b has "Depends: pkg-c", then you end up with: - pkg-a (amd64) - pkg-b (i386) - pkg-c (i386) Case 4) Case 3 except we swap the Depends lines around, then you get pkg-c (amd64)With Case 3, pkg-a works with pkg-c as if pkg-c had `Multi-Arch: foreign` due to the `:any` suffix in the Depends. Meanwhile, pkg-b works with pkg-c as if pkg-c had `Multi-Arch: same`. Case 4 is conceptually the same only we have to swap pkg-a and pkg-b around.
"\n" " Typically, native extensions or plugins will need a `Multi-Arch: same`-relation as they only work with\n" " the interpreter compiled for the same machine architecture as themselves whereas scripts are usually\n" " less picky and can rely on the `Multi-Arch: foreign` relation. Packages wanting to rely on the\n" " `Multi-Arch: foreign` interface must explicitly declare this adding a `:any` suffix to the package\n" " name in the dependency relation (such as `Depends: python3:any`). However, the `:any` suffix cannot\n" " be used unconditionally and should not be used unless you know you need it.\n"Should there be a "by" in "declare this by adding"? *Advanced question*: and should "a `:any` suffix" be "an `:any` suffix"?
"Chefs choice?" :DI have changed to "an" because I end up skipping the punctuation myself most of the time. But if you read it as "colon any", then "a" would have been correct!
"\n" " Note that depending indirectly on a `Multi-Arch: allowed` package can require a `Architecture: all` +\n" " `Multi-Arch: foreign` package to be converted to a `Architecture: any` package. This case is named\n" " the \"Multi-Arch interpreter problem\", since it is commonly seen with script interpreters. However,\n" " despite the name, it can happen to any kind of package. The bug [Debian#984701] is an example of\n" " this happen in practice.\n"I'm fairly sure it's "a⁁n `Architecture: ..." (repeatedly). Plus: " this happening in practice.\n""\n" "[Multi-Arch hinter]:https://wiki.debian.org/MultiArch/Hints\n" "[Debian#984701]:https://bugs.debian.org/984701\n" msgstr "" #. [Synopsis] One-line description for the value "same" [Plaintext]. Shown #. with completion (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml msgctxt "Stanza:Package|Field:Multi-Arch" msgid "" "Co-installable with itself for different architectures (common for native" "libraries)" msgstr ""I've bounced off "native libraries" before, and in this context I have little hope that I'll guess what it means.
The packages that can be `Multi-Arch: same` is 99% "native libraries". These are packages compiled into machine code (usually from C, C++, etc.) and are therefore `Architecture: any` packages.
Native library is jargon for a library being compiled into native machine language . So libc would be a native library. These would also be `Architecture: any` (that is, they must be built for each architecture separately).
On the other hand, libraries written in most scripting languages will be a library but will not be native (machine code). These would generally be Architecture: all (ignoring the special-cases). However, `Architecture: all` packages *cannot* be `Multi-Arch: same`.
In other words, "native (code) libraries" defines the subset of libraries that could and typically are `Multi-Arch: same` in contract to "non-native (code) libraries" that never is `Multi-Arch: same` (instead they tend to be `Multi-Arch: foreign`)
You can find examples of native library packages on your system with the command:
dpkg -l | awk '{print $2}' | grep '^lib.*:'(it has a few false positives, but you should see a clear pattern of `lib<name><version>:<architecture>` like liblz4-1:amd64 in the output)
On the flip side, non-native library packages are often named after the language they are written in, such as `python3-X` or `libX-perl` to take the two patterns I know best.
PS: In the previous case of me using "native libraries" (not quoted in this email), the "native" part was irrelevant and I ended up removing it.
#. [Hover Doc] Extended description for the value "same" [Markdown]. Shown in #. hover docs (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml #, python-brace-format msgctxt "Stanza:Package|Field:Multi-Arch" msgid "" "The exact same version of the package can be co-installed for multiple architecture. However,\n"Same old same old. Oh, except that this version is even more insistent that the things that can be installed together are exactly one thing. On multiple but unpluralised architecture."for this to work, the package*must* ship all files in architecture unique paths (usually\n" "beneath `/usr/lib/<DEB_HOST_MULTIARCH>`) or have bit-for-bit identical content\n" "in files that are in non-architecture unique paths (such as files beneath `/usr/share/doc`).\n" "\n" "The name `same` refers to the fact that the package can satisfy relations only for the `same`\n" "architecture as itself. However, in this case, it is co-installable with itself as noted above.\n" "Note: This value **cannot** be used with `Architecture: all`.\n" msgstr "" #. [Synopsis] One-line description for the value "no" [Plaintext]. Shown with #. completion (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml msgctxt "Stanza:Package|Field:Multi-Arch" msgid "" "No Multi-Arch support (often used for \"reviewed and no support" "possible/needed\")" msgstr "" #. [Hover Doc] Extended description for the value "no" [Markdown]. Shown in #. hover docs (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml #, python-brace-format msgctxt "Stanza:Package|Field:Multi-Arch" msgid "" "The default. The package can be installed for at most one architecture at the time. It can\n" "*only* satisfy relations for the same architecture as itself. Note that `Architecture: all`\n" "packages are considered as a part of the system's \"primary\" architecture (see output of\n" "`dpkg --print-architecture`).\n" "\n" "Note: Despite the `no`, the package*can* be installed for a foreign architecture (as an example,\n" "you can install a 32-bit version of a package on a 64-bit system). However, packages depending\n" "on it must also be installed for the foreign architecture.\n" msgstr ""Perhaps this needs the same fixes as above. Perhaps I need to give up reviewing this and get some sleep - I am after all very near the halfway point.
I hope the examples above will help with this and the cases below. The rest is just quoting for full context.
#. [Synopsis] One-line description for the value "foreign" [Plaintext]. Shown #. with completion (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml msgctxt "Stanza:Package|Field:Multi-Arch" msgid "" "Can satisfy dependencies for other architectures (common for data and some" "scripts)" msgstr "" #. [Hover Doc] Extended description for the value "foreign" [Markdown]. Shown #. in hover docs (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml #, python-brace-format msgctxt "Stanza:Package|Field:Multi-Arch" msgid "" "The package can be installed for at most one architecture at the time. However, it can\n" "satisfy relations for packages regardless of their architecture. This is often useful for packages\n" "solely providing data or binaries that have \"Multi-Arch neutral interfaces\".\n" "\n" "Sadly, describing a \"Multi-Arch neutral interface\" is hard and often only done by Multi-Arch\n" "experts on a case-by-case basis. Some programs and scripts have \"Multi-Arch dependent interfaces\"\n" "and are not safe to declare as `Multi-Arch: foreign`.\n" "\n" "The name \"foreign\" refers to the fact that the package can satisfy relations for native\n" "*and foreign* architectures at the same time.\n" msgstr ""As above, or before, or somewhere.#. [Synopsis] One-line description for the value "allowed" [Plaintext]. Shown #. with completion (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml msgctxt "Stanza:Package|Field:Multi-Arch" msgid "Consumer decides whether it is same and foreign" msgstr ""Same*and* foreign? I'm not even going to*try* to understand.#. [Hover Doc] Extended description for the value "allowed" [Markdown]. Shown #. in hover docs (etc.) #: src/debputy/lsp/data/debian_control_reference_data.yaml #, python-brace-format msgctxt "Stanza:Package|Field:Multi-Arch" msgid "" "**Advanced and very rare value**. This value is exceedingly rare to the point that less\n" "than 0.40% of all packages in Debian used in it (May 2024). It is even rarer for for\n"use it (as of May 2024). Is that an excess "for" or should it be "rarer than"?"`Architecture: all` packages, where the number an order of magnitude smaller. Unless\n"⁁is"a Multi-Arch expert or the Multi-Arch hinter suggested that you use this value, for\n" "this package, then probably it is not the right choice.\n" "\n" "The value means that the package is*not* co-installable with itself but can satisfy Multi-Arch\n" "`foreign` and Multi-Arch `same` relations at the same time. This is useful for implementations of\n" "scripting languages (such as Perl or Python). Here the interpreter contextually need to\n"Number agreement: "needs"."satisfy some relations as `Multi-Arch: foreign` and others as `Multi-Arch: same`.\n" "\n" "Typically, native extensions or plugins will need a `Multi-Arch: same`-relation as they only\n" "work with the interpreter compiled for the same machine architecture as themselves whereas\n" "scripts are usually less picky and can rely on the `Multi-Arch: foreign` relation. Packages\n" "wanting to rely on the \"Multi-Arch: foreign\" interface must explicitly declare this adding a\n"Missing "by", and should that be "an"?"`:any` suffix to the package name in the dependency relation (e.g. `Depends: python3:any`).\n" "However, the `:any\"`suffix cannot be used unconditionally and should not be used unless you\n" "know you need it.\n" msgstr ""[...]
Best regards, Niels
Attachment:
OpenPGP_signature.asc
Description: OpenPGP digital signature