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

Support installing manpages (and potentially other files) #2729

Open
joshtriplett opened this Issue May 23, 2016 · 28 comments

Comments

Projects
None yet
@joshtriplett
Member

joshtriplett commented May 23, 2016

I use Cargo to build a command-line tool written in Rust. I've also written an accompanying manpage, command.1. I'd like to tell Cargo about manpages via Cargo.toml, so that cargo install will install them to the appropriate location (gzip-compressed and installed to ${root}/share/man/man1/command.1.gz, where the section 1 in man1 gets extracted from the first character of the manpage extension).

Note that once Cargo has a mechanism for a post-build script, some packages may wish to use that to build the manpage. For instance, a package might parse --help output to generate a manpage, process some other document language to produce a manpage, or use help2man-like functionality from an argument parser. However, for a first pass, I'd just like to have support for installing manpages already written directly in manpage format.

@joshtriplett

This comment has been minimized.

Member

joshtriplett commented Jun 30, 2016

Thinking about this, I think that with the specification hashed out, this becomes an E-easy issue. Given that, I'd like to propose a more precise specification for how Cargo should handle this:

cargo install should automatically detect manpages in a man subdirectory adjacent to Cargo.toml. Manpages should match the glob man/*.[1-9]. Given a manpage man/command.N, cargo install should compress it with gzip (with no timestamp and no embedded filename, as though with gzip -9n), and install it to share/man/manN/command.N.gz relative to the install root.

Optionally, cargo install could gain a new option --no-man to disable installing manpages.

(I think it makes sense to use convention-over-configuration for this. If someone has a use case for specifying additional manpages by filename or directory name, we can always add a new field to Cargo.toml at that point.)

@davidszotten

This comment has been minimized.

davidszotten commented Jul 4, 2016

just to note that bash (or other shell) completion might be another reasonable "potential other file" for a binary to ship

@alexcrichton

This comment has been minimized.

Member

alexcrichton commented Jul 5, 2016

@joshtriplett yeah I agree that once we have a specification for this it's an easy bug to knock off, but unfortunately the specification is the hard part. I don't think we'll want to extend Cargo to install just man pages (if at all) as as @davidszotten mentioned there's other things like bash completions, perhaps documentation, and even files like assets in games.

We don't want Cargo to become a replacement package manager for the system or other "proper" installation methods, so I'm hesitant to make progress on this as well. The purpose of cargo install was a cross-platform method of quickly sharing code with others using Rust.

This probably wants to be discussed a little more broadly before trying to tackle each of the sub-issues associated.

@joshtriplett

This comment has been minimized.

Member

joshtriplett commented Jul 5, 2016

@alexcrichton I can understand that, but on the other hand, cargo doesn't quite yet support the constraints of distro package managers either, though folks are working on that. And in any case, distribution package managers don't support installing into $HOME, while cargo does.

I definitely wouldn't want to use cargo to install anything systemwide into /usr; however, man will also automatically find manpages installed into ~/.local/share/man/manN/command.N , so I'd like to have this support in cargo for installing into $HOME.

For that matter, many distribution package build systems just have the package install itself into a temporary directory via $DESTDIR, and then tweak and package up that temporary directory. So, if cargo knows about various assets to install, the distribution package build system can just use that.

@alexcrichton

This comment has been minimized.

Member

alexcrichton commented Jul 6, 2016

Yeah right now we just don't want to open the floodgates to a whole litany of various post-installation steps of Cargo just yet. It may be worth prototyping this as a new subcommand (perhaps leveraging package.metadata to store configuration) before moving into Cargo as well.

@vu3rdd

This comment has been minimized.

Contributor

vu3rdd commented Aug 30, 2016

We could create a .cargo/share/man directory where the cargo install can install the manpage into, depending on the section (inferred from the name of the man page - foo.N). And then, as part of the installation of rust/cargo toolchain, we could add .cargo/share/man into the MANPATH environment variable.

How does that sound?

@jugglerchris

This comment has been minimized.

jugglerchris commented Oct 6, 2016

I have a use case where I want to install extra non-manpage files, but need the binary to know the path to them somehow (ie when installed needs to point to the install location, otherwise to somewhere in the source tree).
I might be up for prototyping a cargo subcommand.

@joshtriplett

This comment has been minimized.

Member

joshtriplett commented Oct 6, 2016

We could create a .cargo/share/man directory where the cargo install can install the manpage into, depending on the section (inferred from the name of the man page - foo.N). And then, as part of the installation of rust/cargo toolchain, we could add .cargo/share/man into the MANPATH environment variable.

You don't actually need to add $TARGET/share/man to $MANPATH if $PATH already contains $TARGET/bin; man will automatically look for ../share/man relative to directories on your $PATH.

But otherwise, cargo install installing manpages named foo.N into $TARGET/share/man/manN/ sounds perfect.

@cardoe

This comment has been minimized.

Contributor

cardoe commented Nov 26, 2016

I'd like to see this relative to the --root argument to cargo install so in the default case it goes to $HOME/.cargo/share/man so that it just works for people that have $HOME/.cargo/bin in their path. But that's cause I'm lazy and use cargo install --root=${D}/usr && rm /usr/.crates.toml for packaging.

@casey

This comment has been minimized.

Contributor

casey commented Feb 11, 2017

I propose that we tackle this issue in two steps:

  1. Decide on a standard way for crate authors to ship man pages with their crate. I think that man/*.[1-9] in the crate root would be a very reasonable way to go.

  2. Later decide if we want to extend cargo to actually install man pages and the details of how that would work.

I think that part 1 would be easy and uncontroversial, since there isn't any code to write or behavior to decide on. Also, it would would be very useful on its own for downstream packagers of rust binaries. For example, tools like https://github.com/mmstick/cargo-deb could be extended to include man pages in the .deb, if present.

@joshtriplett

This comment has been minimized.

Member

joshtriplett commented Feb 11, 2017

@casey That sounds good to me. I'd be happy to enable that in debcargo as well.

@cardoe

This comment has been minimized.

Contributor

cardoe commented Feb 12, 2017

@alexreg

This comment has been minimized.

alexreg commented Mar 21, 2017

If we could extend this beyond man pages to general data files, that would be great.

@kballard

This comment has been minimized.

Contributor

kballard commented May 2, 2017

I think manpages are the most useful thing to handle first, and should be tackled before handling arbitrary other files.

Also, while a man/foo.N convention to auto-detect manpages is fine, Cargo.toml will need a way to explicitly specify the location for manpages as well, as there are other conventions in use (e.g. oghamn/exa uses contrib/man/exa.1, and I've seen share/man/man1/foo.1 in other projects).

@joshtriplett

This comment has been minimized.

Member

joshtriplett commented May 3, 2017

@kballard That seems reasonable. Convention first, but also a Cargo.toml key that accepts either a string or list of strings; the strings can specify either directory names (install all manpages in the directory) or filenames (install the specified manpage).

@BartMassey

This comment has been minimized.

BartMassey commented Jul 3, 2017

In my opinion, once we've gone down the road of having cargo install and a $HOME/.cargo, it is unreasonable not to be able to have the install put arbitrary needed assets in there. I would hate to see this limited to just manpages. The distro package manager is not really a viable substitute for one's own programs under development and in use on one's own machines...

@alexreg

This comment has been minimized.

alexreg commented Jul 5, 2017

I fully concur with @BartMassey on the above.

@hasufell

This comment has been minimized.

hasufell commented Jul 5, 2017

This is a must-have feature. You might also want to check how cabal handles this:

  • in the package definition there is a data-files setting
  • you can get the data locations via generated module functions in the code, so it doesn't really matter if it's installed into $HOME, still residing in the build dir or already system-wide (if applicable)

Automagic detection of manpages is fishy, imo. Instead, there should be wildcard support in the corresponding config syntax.

Also, doing this properly and increasing compatibility with package managers will also involve having more fine-grained control over the installation destination (not just --root), because otherwise it will make crate devs hardcode weird and incompatible suffix directories.

I wouldn't want to give full control over the installation procedure to the crate dev. It should not be possible to define arbitrary installation destinations. There must be a set of things, most likely corresponding to the FHS, like --mandir and --datadir, which can be extended carefully, if needed. But this format must be decided upon first in a generic way. As such, I agree with @BartMassey ...it will just make it worse if this is handled per use case.

Or to put it simple: this feature is not a substitute for package managers at all, instead it increases package manager compatibility (if done right).

@alexreg

This comment has been minimized.

alexreg commented Jul 5, 2017

@alexcrichton Could we kindly get your thoughts on the recent developments in this discussion? 😊

@alexcrichton

This comment has been minimized.

Member

alexcrichton commented Jul 6, 2017

Adding support for this was explicitly avoided in the initial RFC for this feature. To me that means that adding support will likely entail a further RFC with rationale, detailed design, etc.

@alexreg

This comment has been minimized.

alexreg commented Jul 8, 2017

@alexcrichton I didn't see any rationale given there, however. Is there? This seems to be a much in-demand feature... perhaps someone here (more qualified than me) could take up the task of writing an RFC though.

@zeenix

This comment has been minimized.

zeenix commented Aug 29, 2017

@alex reading through that link your provided, it sounds to me that installation and uninstallation of data is considered to be only useful for deployments/distros and not devs. As a maintainer/developer of system D-Bus services (Geoclue and gps-share), I need to install (and sometimes also uninstall) files from the source/build directory to test changes etc. It would be very annoying for folks like myself to have to create custom scripts or rpm packages for just being able to install files.

@remexre

This comment has been minimized.

remexre commented Oct 2, 2017

I think that installing to a $DESTDIR (which just so happens to default to ~/.cargo) should be the priority -- creating actual distro packages de facto requires this. I think @hasufell has the right idea, maybe have something like:

# globs supported for all paths
# paths are relative to workspace root directory

[assets]
# defaults to ["man/*.[0-9]"]
# install to mandir
manpages = ["example.1"]

# assets.data defaults to []
# assets.data.FOO = { path = "BAR" } installs BAR to datadir/FOO
[assets.data."icon.png"]
path = "img/icon.png"
@joshtriplett

This comment has been minimized.

Member

joshtriplett commented Mar 12, 2018

Checking back about the current status of this.

I brought this up in the @rust-lang/cargo meeting, and there wasn't any objection to the premise, just a concern about getting the details nailed down.

Is anyone interested in writing down an RFC for this? I'd be happy to talk to someone about possibilities and requirements, for both autodetection and manual specification.

@joshtriplett

This comment has been minimized.

Member

joshtriplett commented Mar 27, 2018

Please see https://github.com/rust-lang/rfcs/2376 for an RFC proposing a solution to this.

@alexreg

This comment has been minimized.

alexreg commented Mar 27, 2018

@joshtriplett Link doesn't work unfortunately.

@lnicola

This comment has been minimized.

lnicola commented Mar 27, 2018

@michaelmior

This comment has been minimized.

michaelmior commented May 29, 2018

For a stopgap I thought I would share a script that I use to link man pages from crates in my local registry. It doesn't always work (e.g. when the man page is templated and generated at build-time) but it does a decent job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment