cargo icon indicating copy to clipboard operation
cargo copied to clipboard

Support installing manpages (and potentially other files)

Open joshtriplett opened this issue 9 years ago • 73 comments

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 avatar May 23 '16 14:05 joshtriplett

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.)

joshtriplett avatar Jun 30 '16 07:06 joshtriplett

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

davidszotten avatar Jul 04 '16 09:07 davidszotten

@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.

alexcrichton avatar Jul 05 '16 20:07 alexcrichton

@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.

joshtriplett avatar Jul 05 '16 21:07 joshtriplett

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.

alexcrichton avatar Jul 06 '16 18:07 alexcrichton

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?

vu3rdd avatar Aug 30 '16 13:08 vu3rdd

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.

jugglerchris avatar Oct 06 '16 06:10 jugglerchris

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.

joshtriplett avatar Oct 06 '16 06:10 joshtriplett

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.

cardoe avatar Nov 26 '16 20:11 cardoe

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.

casey avatar Feb 11 '17 04:02 casey

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

joshtriplett avatar Feb 11 '17 10:02 joshtriplett

On 2/10/17 10:04 PM, Casey Rodarmor wrote:

I propose that we tackle this issue in two steps:

Decide on a standard way for crate authors to ship man pages as part
of their project. I think that |man/*.[1-9]| in the crate root would
a very reasonable way to go.
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.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rust-lang/cargo/issues/2729#issuecomment-279119341, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAih5WT_A-xnOqPpDHk0_k6xfXpgspUks5rbTM4gaJpZM4IkmVI.

FWIW, Gentoo and Yocto already do this with man pages appearing in man/*.[1-9] because that's how I ship my crates.

-- Doug Goldstein

cardoe avatar Feb 12 '17 22:02 cardoe

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

alexreg avatar Mar 21 '17 16:03 alexreg

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).

lilyball avatar May 02 '17 20:05 lilyball

@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).

joshtriplett avatar May 03 '17 01:05 joshtriplett

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...

BartMassey avatar Jul 03 '17 18:07 BartMassey

I fully concur with @BartMassey on the above.

alexreg avatar Jul 05 '17 01:07 alexreg

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).

hasufell avatar Jul 05 '17 08:07 hasufell

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

alexreg avatar Jul 05 '17 15:07 alexreg

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.

alexcrichton avatar Jul 06 '17 14:07 alexcrichton

@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.

alexreg avatar Jul 08 '17 16:07 alexreg

@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.

zeenix avatar Aug 29 '17 15:08 zeenix

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"

remexre avatar Oct 02 '17 20:10 remexre

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 avatar Mar 12 '18 19:03 joshtriplett

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

joshtriplett avatar Mar 27 '18 22:03 joshtriplett

@joshtriplett Link doesn't work unfortunately.

alexreg avatar Mar 27 '18 22:03 alexreg

https://github.com/rust-lang/rfcs/pull/2376

lnicola avatar Mar 27 '18 22:03 lnicola

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.

michaelmior avatar May 29 '18 19:05 michaelmior

Interested in this feature as well. Something that hasn't been mentioned so far, I think, is that it's very common for any installation procedure to also install "package documentation" (those top-level files in capital letters, like README, NEWS, etc.) under share/doc/<package>/. Just wanted to make sure that it's possible to put these in place as well with whatever mechanism is implemented here.

jmmv avatar Jan 02 '19 06:01 jmmv

@jmmv Yeah. Ideally it would be possible to install anything (in a declarative way) under /usr/local/ or similar. I really think we need to move forward on this. Would anyone be interested in writing up an RFC with me on this topic?

alexreg avatar Jan 02 '19 16:01 alexreg