X.py: Remove Python 2 support

bootstrap.py was migrated from Python 2.7 to work with Python 3 and new features was written in a way that works both with Python 2.7 and 3 (except for XZ support used to download LLVM artifacts from CI). The dev guide promises 2.7 support as well. This meant that we can't even use things like f-strings. Although the Python side of the bootstrapper isn't constantly being changed I think sufficient time has passed since Python 2.7's EOL for us to fully commit to Python 3 and remove the baggage for any future changes to the script.

My motivation is that I'm currently rewriting x.py clean to be implemented in pure python (because it happened to me several times that I need to wait for a good 30 seconds for the Rust bootstrapper to compile, just to delete some files). Due to filesystem compatibility shenanigans I need a feature added in Python 3.5. This cannot be backported in pure Python as it interacts with Windows API.

In terms of code change for "dropping support", we simply need to remove 2.7 from documentations and modify x.py such that it errors out when ran with 2.7 with appropirate message. Code style improvements can be made gradually later on.

21 Likes

I would go with removing python 2.7 support from the documentation and making it a hard error in x.py if you try something other than python3. Continue from there. You can later discus the minimal python3 supported version.

1 Like

I'd love to see this. I'd also love to see x.py automatically handling systems where python3 exists and python (normally the entry point for Python 2, though some systems break backwards compatibility by pointing it at Python 3) does not.

5 Likes

I'm pretty sure x.py already does that: Choose the version of python at runtime (portable version) by jyn514 · Pull Request #80625 · rust-lang/rust · GitHub

That handles the case where python == python2 and python3 also exists, it doesn’t handle the case where there is no executable named python at all.

To handle python not existing at all, the most robust solution would probably be to write x.sh and x.bat wrappers that look first for python3 and maybe also python3.x (x ∈ some plausible range of minor versions) before falling back to python and py.

the most robust solution would probably be to write x.sh

And now you end up with src/tools/x, which is already in tree.

I would go with removing python 2.7 support from the documentation and making it a hard error in x.py if you try something other than python3.

Please make an MCP for this. I still have a few machines running python2 by default, and I know several others on the compiler team doing the same. There should at least be a heads-up for them, so they can explain why they're using python2, instead of it suddenly being a hard error.

I'd love to see this. I'd also love to see x.py automatically handling systems where python3 exists and python (normally the entry point for Python 2, though some systems break backwards compatibility by pointing it at Python 3) does not.

These are separate issues, please don't confuse them. x.py will have trouble with python/python3 even if it completely drops supports for python2 (because python3 doesn't exist on Windows): Rust doesn't build without "python" name being available · Issue #71818 · rust-lang/rust · GitHub

My motivation is that I'm currently rewriting x.py clean to be implemented in pure python (because it happened to me several times that I need to wait for a good 30 seconds for the Rust bootstrapper to compile, just to delete some files).

This seems like a very strange use case. Why do you need to run x.py clean before even building bootstrap? If you do need to run it, why is rm -r build not sufficient? I would like to move as much functionality out of x.py as possible; eventually I want to make it possible to cargo run bootstrap directly using rust-toolchain.

See also the discussion in rust-lang and rust-lang.

1 Like

Are you saying x.py is ran with Python 2 first by the shebang line and then it's able to run bootstrap.py with Python 3 under a different executable name, or that these machines simply don't have Python 3 installed? If it's the former then nothing will break because we can retain the old x.py behaviour and only error out if Python 3 can't be found on the system under any sane name.

I don't, but I did need to run x.py clean on some occasions during my edit-build-debug cycle (mostly due to incremental compilation bugs), and sometimes this triggered a bootstrapper rebuild. The underlying reason was likely due to rust-analyzer running cargo check on save with some different flags than what x.py uses to build the bootstrapper and messing up Cargo's cache. I can't just do rm -rf build because one big point of x.py clean is that it retains the llvm artifacts, be that compiled locally or downloaded.

Changing parts of config.toml will also unnecessarily trigger a bootstrapper rebuild on running x.py, mostly in target-specific build sections (e.g. [target.x86_64-unknown-linux-gnu]) because they change things supplied to cargo build for the bootstrapper.

Another (minor) thing is that on Windows, a running executable cannot be deleted hence an executable cannot delete itself, so x.py clean can't remove bootstrap.exe (which is gracefully detected within the rust-written bootstrapper and prints a warning), leaving a non-empty build folder even when the user runs x.py clean --all, whose point is to remove build folder, including llvm artifacts.

That said there is an alternative to rewriting cleaning logic in Python, that is to "short circuit" and avoid building the bootstrapper for x.py clean if the bootstrap binary is already present, counting on the fact that any changes will not affect the cleaning behaviour. x.py clean --all can still be implemented in Python (requiring few lines of code) to fix the left-over bootstrap.exe.

Yes, that's what I mean. Ok, I'm less opposed to this change then (but I still think it should go through an MCP).

I don't, but I did need to run x.py clean on some occasions during my edit-build-debug cycle (mostly due to incremental compilation bugs), and sometimes this triggered a bootstrapper rebuild. The underlying reason was likely due to rust-analyzer running cargo check on save with some different flags than what x.py uses to build the bootstrapper and messing up Cargo's cache.

Are you sure it's not just because x.py clean also cleans bootstrap artifacts? That wouldn't be solved by moving clean x.py; it would make the clean command faster, but everything else would still need a rebuild. Not cleaning the bootstrap binary by default seems like it would be more likely to help, I'm in favor of that.

Changing parts of config.toml will also unnecessarily trigger a bootstrapper rebuild on running x.py , mostly in target-specific build sections (e.g. [target.x86_64-unknown-linux-gnu] ) because they change things supplied to cargo build for the bootstrapper.

That seems like a bug in itself, bootstrap should be built with the same flags regardless of what targets your building. Only the build option should affect it (and build is broken right now anyway, I've been meaning to make a PR).

For that reason I do rm build/*/stage* -rf.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.