Skip to content
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

bootstrap.py --help starts with downloading #37305

Closed
bluss opened this issue Oct 20, 2016 · 39 comments · Fixed by #48569
Closed

bootstrap.py --help starts with downloading #37305

bluss opened this issue Oct 20, 2016 · 39 comments · Fixed by #48569
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap)

Comments

@bluss
Copy link
Member

bluss commented Oct 20, 2016

rustbuild really has a proper --help response, but the first time the user asks for it, it starts working / downloading right away. This is a bad first impression, and a stumbling block for getting to know the new build system.

@bluss bluss added the T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) label Oct 20, 2016
@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Oct 22, 2016

Kinda hard to do anything else, the help message comes from the src/bootstrap crate written in Rust. One could duplicate the usage text in the Python script, but besides being gross and prone to divergence from the ground truth, this increases our reliance on the Python wrapper which ideally should be as minimal as possible (perhaps even some day be replaced with a set of really stupid native platform-specific scripts).

@bluss
Copy link
Member Author

bluss commented Oct 22, 2016

It already parses command line flags before download -- it could catch --help and stop there.

@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Oct 22, 2016

It's not hard to catch --help (in fact it already treats that flag specially), but what should it do with that? Outputting the real help message requires knowledge that's not in bootstrap.py, only in bootstrap.rs (for lack of a better name). And simply saying something like

Can't show --help because [...]

doesn't seem like a big improvement to me. It gives you no useful information and the first impression is just as bad.

@bluss
Copy link
Member Author

bluss commented Oct 22, 2016

When I tried to get to know the new build system, my impression was that bootstrap had no --help, because it just started working. So I never found it until much later.

I know, not every misunderstanding is a bug, but it seems like this could be improved? The user just needs to know what they need to do to reach the real --help. Even better of course if that could just be shown, but we can't have it all.

@hanna-kruppe
Copy link
Contributor

hanna-kruppe commented Oct 22, 2016

You have a point. Perhaps instead of stopping dead, a bootstrap.py invocation that needs to download the nightlies could output something like this before downloading?

NOTE: downloading bootstrap requirements before processing bootstrap ${given command line arguments}

@0xmohit
Copy link
Contributor

0xmohit commented Oct 24, 2016

OTOH, the script should probably create the build directory in the repo root. Currently it creates the build directory in the location where the script is invoked. For example, if one happens to invoke it from within the src directory: python bootstrap/bootstrap.py ... then build, build/cache, ... are created inside src.

Not sure if there is a reason for making the build directory relative to pwd. The following would seem more desirable:

diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 2c2260a..056bd36 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -370,7 +370,7 @@ def main():
     rb.config_toml = ''
     rb.config_mk = ''
     rb.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
-    rb.build_dir = os.path.join(os.getcwd(), "build")
+    rb.build_dir = os.path.join(rb.rust_root, "build")
     rb.verbose = args.verbose
     rb.clean = args.clean

@hanna-kruppe
Copy link
Contributor

@0xmohit

I think the intent is to allow out-of-source builds (including multiple independent builds).

Aside: this seems completely unrelated to this issue? If you want to discuss this further please open a new issue.

@xen0n
Copy link
Contributor

xen0n commented Nov 17, 2016

FYI the relevant part is non-trivial and not easily refactored out. Maybe printing a note before proceeding to download is the only reasonable thing we can do without too much effort.

@ranma42
Copy link
Contributor

ranma42 commented Nov 17, 2016

And even after the download, the --help output starts with some cruft (as it checks that the download/build is fine):

    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
unknown command: --help
Usage: x.py --help [options] [<args>...]

Options:
    -v, --verbose       use verbose output
...

Would it be an acceptable compromise to keep the output of ./build/bootstrap/debug/bootstrap --help in a text file that can be written back to the console when the ./x.py --help command is run?

That file would mostly be static and it would be easy to add a (tidy?) check that compares it to the output from ./build/bootstrap/debug/bootstrap --help to ensure consistency when the set of options and flags is changed.

@xen0n
Copy link
Contributor

xen0n commented Nov 17, 2016

@ranma42 I'm not quite sure but your suggestion may be best implemented with automation, i.e. a script that invokes bootstrap multiple times to obtain all the possible help messages. The script would be run by people developing rustbuild to sync their changes. However that's still quite a bit of complexity and tedious to do not to mention easy to forget, I'm not even sure we should go that far for those impatient people.

@alexcrichton What's your opinion on that, since you authored the whole system?

@xen0n
Copy link
Contributor

xen0n commented Nov 17, 2016

I've hacked together such a script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import unicode_literals, absolute_import

import functools
import os
import subprocess
import sys


def extract_usage(bootstrap_path, args):
    argv = [bootstrap_path, ]
    argv.extend(args)
    proc = subprocess.Popen(argv, stdout=subprocess.PIPE)
    stdout, stderr = proc.communicate()
    return stdout


USAGES_TO_EXTRACT = {
        'cmds': [],
        'build': ['build', '-h'],
        'test': ['test', '-h'],
        'doc': ['doc', '-h'],
        'clean': ['clean', '-h'],
        'dist': ['dist', '-h'],
        }


def main():
    rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
    bootstrap_path = os.path.join(rust_root, 'build/bootstrap/debug/bootstrap')

    usage = functools.partial(extract_usage, bootstrap_path)

    for category, args in USAGES_TO_EXTRACT.items():
        out_filename = 'usage-{}.txt'.format(category)
        out_path = os.path.join(rust_root, 'src/bootstrap', out_filename)
        with open(out_path, 'wb') as fp:
            fp.write(usage(args))


if __name__ == '__main__':
    main()

In case bootstrap is invoked without args or an unknown command, it outputs a line of error, which should be discarded but I didn't include it. Anyway it's still undecided whether rustbuild maintainers are expected to sync usage messages while working on it, so let's discuss.

@ranma42
Copy link
Contributor

ranma42 commented Nov 17, 2016

@xen0n I had assumed that only the top-level --help option was to be provided without the download (i.e. the generic usage syntax, not the command-specific options). I was suggesting to add a check to the CI infrastructure to ensure the consistency specifically to prevent contributors from forgetting to update it when needed.

@xen0n
Copy link
Contributor

xen0n commented Nov 17, 2016

@ranma42 Oh that would be much easier to do! However AFAIK the CI infrastructure only deals with testing rustc itself right now? I don't know how much work it'll take extending rustbuild to self-test as well, as all heavy-lifting are done in Cargo.

@ranma42
Copy link
Contributor

ranma42 commented Nov 17, 2016

I think some non-rustc checks are implemented by the tidy tool (found in src/tools/tidy) to enforce some conventions on syntax, licences, error declaration/messages, ...
We could add a check for the files that can be generated automatically but that we decide to ship with the repo for convenience (for example src/libcore/num/dec2flt/table.rs and src/librustc_unicode/tables.rs). This check could also apply to the new --help documentation.

(Side note: I thought the auto-generated files were already verified in some way, but I could not find any such check; would it make sense to implement this and open a PR for it?)

@alexcrichton
Copy link
Member

Unfortunately I don't really see a solution to this. This is to me is just a fact of how rustbuild works, we can't really work around it.

While committing help messages would be possible, I'd personally prefer to avoid putting any form of generated file in the repository as then we have to keep it up to date, add CI for it, ...

@bluss
Copy link
Member Author

bluss commented Nov 17, 2016

It doesn't need to be perfect, there's always solutions. Would it be ok to add a provisional message that explains that it must build itself before the real --help is displayed?

@alexcrichton
Copy link
Member

I'd personally consider that a non-starter because it'd be a pretty bad user experience of typing --help, then going back and typing --help-no-really-please to actually get the work done. Additionally, if we want to tell someone how to print the help message, we now can't say --help because it won't print it half the time.

@petrochenkov
Copy link
Contributor

petrochenkov commented Nov 17, 2016

@alexcrichton
If build system is uninitialized, then x.py --help and preferably x.py without arguments should give minimal help for the python script itself, reporting the build system status(not initialized) and telling how to initialize the build system if network is available (e.g. by simply starting the build) and if network is unavailable (specify paths to snapshots or something).

If build system is initialized then x.py --help can redirect to bootstrap.rs help.

Starting arbitrary long build process on x.py --help and not providing any help offline if just really really bad UI.
Personally, I'd just immediately abort the script trying to do this and start searching help in the source code.

@alexcrichton
Copy link
Member

I basically think that this is "bad UI" no matter what we do. Either:

  • You request --help and then have to pass --help-no-please-really
  • You request --help and it compiles a bunch of stuff you didn't expect

It seems like it's just a matter of weighing these and there's no clear winner

@petrochenkov
Copy link
Contributor

I don't understand why --help-no-please-really is necessary.

@alexcrichton
Copy link
Member

So let's say we make --help abort if the build system isn't built. How do you then build the build system and request --help?

@xen0n
Copy link
Contributor

xen0n commented Nov 17, 2016

@alexcrichton I believe what he means is just printing out why a build is started when being invoked uninitialized.

$ ./x.py
info: build system uninitialized, starting bootstrap
... download progresses and cargo output ...

@xen0n
Copy link
Contributor

xen0n commented Nov 17, 2016

To provide anything more than a simple hint needs extracting the generated output somehow, all the associated maintenance costs apply. I think we shouldn't go that far unless majority of people see it annoying. (Being more friendly to drive-by contributors by providing immediate help is another topic, let's not discuss that here.)

@petrochenkov
Copy link
Contributor

petrochenkov commented Nov 17, 2016

How do you then build the build system and request --help?

By following whatever recommendations uninitialized x.py --help gives me.

More concrete, uninitialized x.py --help should recommend something like x.py init && x.py --help for the "network is present" scenario.

@alexcrichton
Copy link
Member

@petrochenkov that's exactly what I meant by x.py --help-no-please-really. Does that answer your question?

@petrochenkov
Copy link
Contributor

petrochenkov commented Nov 17, 2016

(Writing the edit as a new message in case you are using email)

More concrete, uninitialized x.py --help should recommend something like x.py init && x.py --help for the "network is present" scenario and x.py init --path-to-rustc=blah && x.py --help for offline scenario.

@petrochenkov
Copy link
Contributor

I mean, --help combines help for both x.py itself and bootstrap.rs if available. The first part of help is equally important and needs to always be available.

@bluss
Copy link
Member Author

bluss commented Nov 17, 2016

@alexcrichton I don't see why a provisional message means that --help-really is needed? Can we please focus on solutions.

Example future user experience:

$ ./x.py --help
NOTE: Building rustbuild before processing command line arguments
Download ... more output here
Running ... more output here
 ... lots more output here
 ... lots more output here
 ... lots more output here
 ... lots more output here

unknown command: --help
Usage: x.py --help [options] [<args>...]

Options:
    -v, --verbose       use verbose output
        --config FILE   TOML configuration file for build
        --build BUILD   build target of the stage0 compiler
        --host HOST     host targets to build
        --target TARGET target targets to build
        --stage N       stage to build
        --src DIR       path to the root of the rust checkout
    -j, --jobs JOBS     number of jobs to run in parallel
    -h, --help          print this help message

@alexcrichton
Copy link
Member

@petrochenkov

More concrete, uninitialized x.py --help should recommend something like x.py init && x.py --help

Sorry if I miscommunicated but this is what I meant by my first option above. A two-step print-the-help-message seems a bad UI just as much as download information to print the help is. It seems to me that newbies would far more often prefer to just get a help message rather than go through a multi-stage process just to get a help message.


@bluss

I don't see why a provisional message means that --help-really is needed? Can we please focus on solutions.

I'm sorry if I've miscommunicated as well, but this is precisely what I'm trying to do. @petrochenkov is proposing a two-stage help message where first you get a message saying you have to run something else. You then run that something else and then you get the help message. This is what I intended to communicate many comments back as what I believe is not better than the current situation.

I'm also confused by the code block you had as an example. It seems like that's exactly what happens today beyond an informational message that something is being compiled. Do you think that's sufficient to close this issue?

@bluss
Copy link
Member Author

bluss commented Nov 17, 2016

@alexcrichton It's not perfect, but even a simple thing like that is a noticeable improvement in user experience.

@rkruppe said:

doesn't seem like a big improvement to me. It gives you no useful information and the first impression is just as bad.

But I don't agree. If you just tell the user why something is happening and that it's intentional, that's much better.

@hanna-kruppe
Copy link
Contributor

FWIW I've come around and agree that simply saying that and why it's downloading and building stuff before printing the help message is an improvement.

@alexcrichton
Copy link
Member

@petrochenkov do you agree that an informational message on the first build would be sufficient?

@petrochenkov
Copy link
Contributor

petrochenkov commented Nov 17, 2016

@alexcrichton
Sufficient for what exactly? Fixing this issue? No. Improving the situation? Yes.

(Regarding #37817, this issue is not an absolute blocker, it's just a problem magnified by rustbuild being a default and --help being the first thing people encounter after getting a copy of the repo.)

@alexcrichton
Copy link
Member

@petrochenkov sorry just trying to clarify. You commented on #37817 with

Fix #37305 before merging

which I interpreted as "#37305 must be fixed before merging this", as in an absolute blocker. I can certainly implement an information message, and we can leave this open if we feel it's still not fixed.

@petrochenkov
Copy link
Contributor

@alexcrichton
I tried the new "Submit feedback suggesting changes." GitHub option, it seems to make things appear... more imperative.

@alexcrichton
Copy link
Member

I've added a sample message to #37817

@est31
Copy link
Member

est31 commented Nov 20, 2016

I've stumbled across this today, and I think this UX is really bad.

@alexcrichton

While committing help messages would be possible, I'd personally prefer to avoid putting any form of generated file in the repository as then we have to keep it up to date, add CI for it, ...

As there are already rustbuild related dependencies through cargo vendor (#37524), there isn't much more to mess up here by somehow autogenerating the help text and saving it in a form python can understand.

It can be generated every time after rustbuild is built, and CI can simply pass a flag to the python script to verify that the file didn't change, so that a PR always needs to check in the change of the file. Is that a good solution?

About the sample message: I think it can be improved if it includes a pointer to some document that doesn't require the internet, like src/bootstrap/README.md.

@aturon
Copy link
Member

aturon commented Nov 22, 2016

FWIW, I think that printing an informative message should suffice for rolling out the deprecation process. If you're going to use the build system, you're going to be bootstrapping anyway -- so the main issue is being informed about what's happening.

That said, I'd suggest specifically mentioning --help in the message, to make it more clear that the option is indeed recognized. I also agree with @est31 that a link to the README would be helpful as well.

@paulmenzel
Copy link

[Hopefully, this issue also concerns x.py.]

With Rust 1.16.0 I get the message below.

[…]
configure: mv -f config.tmp config.mk
configure:
configure: configured in release mode. for development consider --enable-debug
configure:
configure: NOTE you have now configured rust to use a rewritten build system 
configure:      called rustbuild, and as a result this may have bugs that
configure:      you did not see before. If you experience any issues you can 
configure:      go back to the old build system with --disable-rustbuild and 
configure:      please feel free to report any bugs!
configure:
configure: run `python /dev/shm/bee-pmenzel/rustc/rustc-1.16.0-0/source/x.py --help`
configure:

Running python /dev/shm/bee-pmenzel/rustc/rustc-1.16.0-0/source/x.py --help also starts downloads, which is unexpected (and unwanted as you can run that command from anywhere, and it creates build in the current directory).

@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 26, 2017
@Mark-Simulacrum Mark-Simulacrum added this to the impl period milestone Sep 15, 2017
@aturon aturon removed this from the impl period milestone Sep 15, 2017
Manishearth added a commit to Manishearth/rust that referenced this issue Mar 3, 2018
… r=petrochenkov

Improve --help performance for x.py

Since compiling the bootstrap command doesn't require any submodules,
we can skip updating submodules when a --help command is passed in.
On my machine, this saves 1 minute if the submodules are already
downloaded, and 10 minutes if run on a clean repo.

This commit also adds a message before compiling/downloading anything
when a --help command is passed in, to tell the user WHY --help
takes so long to complete. It also points the user to the bootstrap
README.md for faster help.

Finally, this fixes one warning message that still referenced using
make instead of x.py, even though x.py is now the standard way of
building rust.

Closes rust-lang#37305
kennytm added a commit to kennytm/rust that referenced this issue Mar 3, 2018
… r=petrochenkov

Improve --help performance for x.py

Since compiling the bootstrap command doesn't require any submodules,
we can skip updating submodules when a --help command is passed in.
On my machine, this saves 1 minute if the submodules are already
downloaded, and 10 minutes if run on a clean repo.

This commit also adds a message before compiling/downloading anything
when a --help command is passed in, to tell the user WHY --help
takes so long to complete. It also points the user to the bootstrap
README.md for faster help.

Finally, this fixes one warning message that still referenced using
make instead of x.py, even though x.py is now the standard way of
building rust.

Closes rust-lang#37305
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap)
Projects
None yet
Development

Successfully merging a pull request may close this issue.