-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
build_rust: remove linker handling that broke cross compilation #269
Conversation
I confirm that there is the same issue in Yocto Linux, and it's fixed by this PR - thanks! |
Well, as the guy who wrote it, I don't think it's quite that bad 😄! I'll leave it to the maintainers to make a decision on this PR, but I can provide some clarification here. First, I'm very interested in all things related to Python cross-compiling, and I would love to see what exactly the issue was that you were facing. Can you provide a link to the problems you have been seeing? (I'm especially interested in Yocto, because that's my day job.)
None of the code here is crossenv specific. It should be valid for any system using the
Well, they're arguably more official than
Could you elaborate? This doesn't seem like it would ever work.
For context: The reason for this is that a lot of distros like to set it to something like
I believe you are confusing
This logic is only meant to provide defaults in case the
I 100% agree, but we're coming at this from very different perspectives. Crossenv was originally conceived as a tool for developers with some self-contained app that they wanted to distribute on a different architecture. Crossenv's job is to cross compile the app along with any dependencies it may have, with minimum pain for the developer. If one dependency uses In that light, I believe it's entirely appropriate to attempt to use the most standard-ish API available to handle the common cases. If additional customization is needed, then the developer can set the Again, I'd really like to help you diagnose whatever issues you are running into with this code, but I suspect the ultimate fix might be a little more measured that what you have here. |
My central position is that If Specific points are addressed below.
Void cross-builds of
I am well aware of how Void handles sysconfig data for cross-compilation of Python packages. I was under the impression that Overridding the sysconfig path is the right way to gather basic configuration information for the build target when cross-compiling, such as sizes of basic types, extensions for compiled extensions and the like. However, it is not suitable for gleaning compiler and linker settings for at least two reasons: the first, which I noted before, is that
Relying on
When I say "native builds", I mean native on the build system, not the host system. Void cross-compiles Python for If an aarch64 user installs the Again, my view is that
It's not just an imperfect default, it provides no mechanism for overrides. If the As it stands, without killing the linker selection from #139, I can forcefully override the linker by adding the right one back with
Mea culpa.
Another mea culpa. |
I'm ok with merging this since it did not break |
Yocto log with the failure attached. The failure disappears if I add the changes in this pull request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ahesford @kanavin for the discussion and evidence. Sorry it's taken me a few days to have some time to sit down and read this all. I get the sense that this logic has spent you a great deal of time and frustration to investigate as well as impacted your users, and I'm sorry for that.
As in #139 (comment), my personal experience is still heavily weighted towards Python/Rust language integration rather than cross-compiling the languages in tandem. Input from more knowledgeable parties is extremely valued to make sure that setuptools-rust
provides the widest compatibility possible.
I agree with @benfogle that this is a case where different needs and toolchains of individual developers and package maintainers make the space complicated. The impression I have is that cross-compiling Python packages is very much DIY / best-effort. I would love to see this improved; I don't have time to champion such an effort myself though would gladly make setuptools-rust
compliant with any official standard. @ahesford @kanavin I would strongly encourage you to join the thread at https://discuss.python.org/t/towards-standardizing-cross-compiling/10357/25, where @benfogle has been floating ideas for a possible future PEP.
Circling back to this PR, on balance I agree with @messense that CI demonstrates this is mergeable as-is and setuptools-rust
would still be compatible with crossenv
. However, I think it removes more functionality than it strictly needs to, so I would like us to discuss on a few of the changes before we commit. See comments below. Hopefully we can reach an implementation which suits all parties.
if linker is not None: | ||
rustflags.extend(["-C", "linker=" + linker]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per discussion here I am now 100% in agreement that this was wrong and it is correct to remove linker handling from setuptools-rust
.
if cross_lib: | ||
env.setdefault("PYO3_CROSS_LIB_DIR", cross_lib) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correction: this does not "force" PYO3_CROSS_LIB_DIR
- setdefault
will not overwrite any value already in the environment. So build environments should be untainted by this.
Whether setuptools-rust
should be attempting to set this is a separate question. I think it's reasonable for it to make an educated guess if it's on balance helpful for users. As this value comes from the sysconfig, it seems reasonable to me to use that as a first guess.
assert self.plat_name is not None | ||
cross_compile_info = _detect_unix_cross_compile_info() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With an appropriate implementation of setuptools_rust
that handles all build environment correctly, I still think there's value in a best-effort attempt to recognise the correct rust build target for use-cases like crossenv
. My preference would be to not completely remove this, however the heavy-handedness with which it splats the build environment absolutely needs fixing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been thinking about the right implementation for _detect_unix_cross_compile_info
, but don't have any good ideas right now. I'm also not terribly familiar with rust, but wound up with responsibility for setuptools-rust
packaging in Void because it is required by our python3-adblock
package as well as python3-cryptography
.
For the reasons I've noted earlier, I think looking for *_GNU_TYPE
variables in the target sysinfo is wrong because it will reflect the cross or native build environment of the Python interpreter rather than the compilation intent for the package being built with setuptools-rust
. The best method here would be determining the native triple for the rust compiler and comparing that to self.target
, but I don't know how to determine a native triple short of hacks like looking at uname
output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the reasons I've noted earlier, I think looking for
*_GNU_TYPE
variables in the target sysinfo is wrong because it will reflect the cross or native build environment of the Python interpreter rather than the compilation intent for the package being built withsetuptools-rust
. The best method here would be determining the native triple for the rust compiler and comparing that toself.target
, but I don't know how to determine a native triple short of hacks like looking atuname
output.
That's what GNU autotools do though (look at uname
).
However, Yocto project does not generally trust any guessing that the components might try to do: we prefer to pass in all three triplets (host/build/target) explicitly via pre-written config files or command line switches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically, here:
https://git.savannah.gnu.org/cgit/config.git/tree/config.guess
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think the better check for cross-compilation in this project is just "is self.target
(read from CARGO_BUILD_TARGET
) defined?"
Aside from checking the *_GNU_TYPE
macros to pick cross info, all the _detect_unix_cross_compile_info
does is attempt to determine the cross_lib
path and set a default PYO3_CROSS_LIB_DIR
based on it. I'd be OK with preserving that logic. (It determines the wrong value in our Void setup, but because I explicitly set the environment variable to the right value beforehand, it has no ill effect.)
return _TargetInfo( | ||
forced_target_triple, | ||
cross_compile_info.cross_lib, | ||
cross_compile_info.linker, | ||
cross_compile_info.linker_args, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On reflection this line is clearly wrong - should have just been return _TargetInfo(forced_target_info)
and not carry any of the detected cross-compile with it. (The user is already setting --target
externally, they should be totally able to set the rest of the flags in this case.)
FYI getting the linker settings right for cargo cross compilation is rather complex. Our infrastructure passes our cargo cross environment in addition to our python cross environment and some pyo3 specific variables which generally seems to work for packages like cryptography. |
Thanks all for the discussion here. I've come to opinion that while it's potentially useful for setuptools-rust to make an educated guess at cross-compile configuration, there's some downsides to the current implementation:
So I think the simplest course of action is to merge this PR as-is, and then if anyone comes forward in future with better heuristics for setuptools-rust to consider we can evaluate those later. I'll rebase and push this through. Thanks. |
The changes in #139 that attempt to fix issues in #138 break cross compilation of the Void Linux
python3-cryptography
package. (It probably would break any cross-compiled Python package that usessetuptools-rust
, butpython3-cryptography
is the only package in Void that uses it.) The Void package build system, xbps-src, sets up cross-compilation environments for several officially supported architectures and even more for which we do not provide prebuilt packages.The changes in #139 are the incorrect solution to a problem that was caused by crossenv itself. The crossenv package appears to hack up the Python sysconfig file to reflect the cross-compilation environment. It then relies on the modified sysconfig data to determine how it should behave; while that might be acceptable in the package that creates the modified sysconfig, copying and relying on that behavior in
setuptools-rust
is wrong for several reasons:HOST_GNU_TYPE
andBUILD_GNU_TYPE
variables in Python sysconfig, whichsetuptools-rust
are to be built. (For example, Void's Python packages foraarch64{,-musl}
andarmv{6,7}l{,-musl}
all have sysconfig files that define these variables because the Python interpreter was cross compiled; however, that cross-compiled Python interpreter may be used for native builds of Python packages that usesetuptools-rust
,setuptools-rust
will always assume that cross compilation is expected.)$BLDSHARED
and force its use in Rust builds will fail catastrophically if, e.g.,$BLDSHARED
is a wrapper that relies on proper ordering of all following arguments.linker_args
, all of which are then ignored when actually building.PYO3_CROSS_LIB_DIR
is forced, potentially masking desired variables set in the user's environment with an incorrectly determined path.The responsibility for correctly setting up the cross-compilation environment should lie in the system that constructs the environment, not fragile logic in packages like
setuptools-rust
. This PR removes most of the special-case handling imposed by #139 to restore cross-compilation support in general environments. The right fix for crossenv is to properly configure its build environment:PYO3_CROSS_LIB_DIR
andPYO3_CROSS_INCLUDE_DIR
as necessary to configure the proper paths for compilation.CARGO_BUILD_TARGET
can be set to the expected target triple. (This is already recognized in thebuild_rust
class.)CARGO_TARGET_<triple>_LINKER
environment variable can be set to the proper linker for cross-compilation.RUSTFLAGS
insetuptools-rust
.This implies that crossenv must do a little extra work by, e.g., modifying the virtualenv activation script to set these variables (or providing its own activation script to do so before calling the stock activation script). However, doing this work is the right fix for this problem, not special-casing stuff in
setuptools-rust
.cc: @benfogle (original author) @davidhewitt (did the merge)