Change:
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.
Kinda hard to do anything else, the help message comes from the 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).
It already parses command line flags before download -- it could catch --help and stop there.
It's not hard to catch (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 , only in (for lack of a better name). And simply saying something like doesn't seem like a big improvement to me. It gives you no useful information and the first impression is just as bad.
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.
You have a point. Perhaps instead of stopping dead, a invocation that needs to download the nightlies could output something like this before downloading?
OTOH, the script should probably create the directory in the repo root. Currently it creates the directory in the location where the script is invoked. For example, if one happens to invoke it from within the directory: then , , ... are created inside . Not sure if there is a reason for making the directory relative to . The following would seem more desirable:
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.
FYI 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.
And even after the download, the output starts with some cruft (as it checks that the download/build is fine): Would it be an acceptable compromise to keep the output of in a text file that can be written back to the console when the 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 to ensure consistency when the set of options and flags is changed.
I'm not quite sure but your suggestion may be best implemented with automation, i.e. a script that invokes multiple times to obtain all the possible help messages. The script would be run by people developing 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. What's your opinion on that, since you authored the whole system?
I've hacked together such a script: In case 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 maintainers are expected to sync usage messages while working on it, so let's discuss.
I had assumed that only the top-level 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.
Oh that would be much easier to do! However AFAIK the CI infrastructure only deals with testing itself right now? I don't know how much work it'll take extending to self-test as well, as all heavy-lifting are done in Cargo.
I think some non- checks are implemented by the tool (found in ) 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 and ). This check could also apply to the new 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?)
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, ...
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?
I'd personally consider that a non-starter because it'd be a pretty bad user experience of typing , then going back and typing to actually get the work done. Additionally, if we want to tell someone how to print the help message, we now can't say because it won't print it half the time.
If build system is uninitialized, then and preferably 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 can redirect to help. Starting arbitrary long build process on 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.
I basically think that this is "bad UI" no matter what we do. Either: You request and then have to pass You request 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
I don't understand why is necessary.
So let's say we make abort if the build system isn't built. How do you then build the build system and request ?
I believe what he means is just printing out why a build is started when being invoked uninitialized.
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.)
By following whatever recommendations uninitialized gives me.
that's exactly what I meant by . Does that answer ?
(Writing the edit as a new message in case you are using email) More concrete, uninitialized should recommend something like for the "network is present" scenario and for offline scenario.
I mean, combines help for both itself and if available. The first part of help is equally important and needs to always be available.
I don't see why a provisional message means that --help-really is needed? Can we please focus on solutions. Example future user experience:
Sorry if I miscommunicated but this is what I meant by my . 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. I'm sorry if I've miscommunicated as well, but this is precisely what I'm trying to do. 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 as what I believe is not better than the current situation. I'm also confused by 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?
It's not perfect, but even a simple thing like that is a noticeable improvement in user experience. said: But I don't agree. If you just tell the user why something is happening and that it's intentional, that's much better.
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.
do you agree that an informational message on the first build would be sufficient?
Sufficient for what exactly? Fixing this issue? No. Improving the situation? Yes. (Regarding , this issue is not an absolute blocker, it's just a problem magnified by rustbuild being a default and being the first thing people encounter after getting a copy of the repo.)
sorry just trying to clarify. You with which I interpreted as " 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.
I tried the new "Submit feedback suggesting changes." GitHub option, it seems to make things appear... more imperative.
I've a to
I've stumbled across this today, and I think this UX is really bad. As there are already rustbuild related dependencies through cargo vendor (), 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 .
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 in the message, to make it more clear that the option is indeed recognized. I also agree with that a link to the README would be helpful as well.
[Hopefully, this issue also concerns .] With Rust 1.16.0 I get the message below. Running also starts downloads, which is unexpected (and unwanted as you can run that command from anywhere, and it creates in the current directory).

Discussion:
self.build_dir = os.path.join(os.getcwd(), "build") self.clean = False self.config_toml = '' <del> self.printed = False </del> self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) self.use_locked_deps = '' self.use_vendored_sources = ''

if self.rustc().startswith(self.bin_root()) and  (not os.path.exists(self.rustc()) or self.program_out_of_date(self.rustc_stamp())): <del> self.print_what_bootstrap_means() </del> if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) filename = "rust-std-{}-{}.tar.gz".format(

if self.cargo().startswith(self.bin_root()) and  (not os.path.exists(self.cargo()) or self.program_out_of_date(self.cargo_stamp())): <del> self.print_what_bootstrap_means() </del> filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build) self._download_stage0_helper(filename, "cargo") self.fix_executable("{}/bin/cargo".format(self.bin_root()))

return '.exe' return '' <del> def print_what_bootstrap_means(self): """Prints more information about the build system""" if hasattr(self, 'printed'): return self.printed = True if os.path.exists(self.bootstrap_binary()): return if '--help' not in sys.argv or len(sys.argv) == 1: return print('info: the build system for Rust is written in Rust, so this') print('      script is now going to download a stage0 rust compiler') print('      and then compile the build system itself') print('') print('info: in the meantime you can read more about rustbuild at') print('      src/bootstrap/README.md before the download finishes') </del> def bootstrap_binary(self): """Return the path of the boostrap binary

def build_bootstrap(self): """Build bootstrap""" <del> self.print_what_bootstrap_means() </del> build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir)

self._download_url = 'https://dev-static.rust-lang.org' <del> def bootstrap(): </del> <ins> def bootstrap(help_triggered): </ins> """Configure, fetch, build and run the initial bootstrap""" <ins> # If the user is asking for help, let them know that the whole download-and-build # process has to happen before anything is printed out. if help_triggered: print("info: Downloading and building bootstrap before processing --help") print("      command. See src/bootstrap/README.md for help with common") print("      commands.") </ins> parser = argparse.ArgumentParser(description='Build rust') parser.add_argument('--config') parser.add_argument('--build')

print('      and so in order to preserve your $HOME this will now') print('      use vendored sources by default. Note that if this') print('      does not work you should run a normal build first') <del> print('      before running a command like `sudo make install`') </del> <ins> print('      before running a command like `sudo ./x.py install`') </ins> if build.use_vendored_sources: if not os.path.exists('.cargo'):

if 'dev' in data: build.set_dev_environment() <del> build.update_submodules() </del> <ins> # No help text depends on submodules. This check saves ~1 minute of git commands, even if # all the submodules are present and downloaded! if not help_triggered: build.update_submodules() </ins> # Fetch/build the bootstrap build.build = args.build or build.build_triple()

help_triggered = ( '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) try: <del> bootstrap() </del> <ins> bootstrap(help_triggered) </ins> if not help_triggered: print("Build completed successfully in {}".format( format_build_time(time() - start_time)))