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

dmenu-rs: add package #200977

Merged
merged 2 commits into from
Dec 20, 2022
Merged

dmenu-rs: add package #200977

merged 2 commits into from
Dec 20, 2022

Conversation

benjaminedwardwebb
Copy link
Contributor

@benjaminedwardwebb benjaminedwardwebb commented Nov 13, 2022

dmenu-rs is a pixel perfect port of dmenu, rewritten in Rust with extensive plugin support.

See: https://github.com/Shizcow/dmenu-rs

Description of changes
Things done
  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 22.11 Release Notes (or backporting 22.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
    • (Release notes changes) Ran nixos/doc/manual/md-to-db.sh to update generated release notes
  • Fits CONTRIBUTING.md.

@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux labels Nov 13, 2022
@ofborg ofborg bot added 8.has: package (new) This PR adds a new package 11.by: package-maintainer This PR was created by the maintainer of the package it changes 10.rebuild-linux: 1-10 10.rebuild-linux: 1 and removed 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux labels Nov 13, 2022
@benjaminedwardwebb benjaminedwardwebb force-pushed the dmenu-rs branch 3 times, most recently from c9e9d92 to 2d3abfb Compare November 20, 2022 04:19
@benjaminedwardwebb
Copy link
Contributor Author

benjaminedwardwebb commented Nov 20, 2022

Ran nix-env -iA dmenu-rs -f . on the nixos-unstable branch at 52b2ac8ae18bbad4374ff0dd5aeee0fdf1aea739 in my local nixpkgs repository on my x86_64-linux laptop. Installed successfully and was usable.

@benjaminedwardwebb
Copy link
Contributor Author

Also ran the above with nix.useSandbox = true;.

@benjaminedwardwebb benjaminedwardwebb marked this pull request as ready for review November 20, 2022 22:00
@benjaminedwardwebb
Copy link
Contributor Author

Also, anecdotally, I've been using this (or a largely similar derivation) as my daily driver launcher for about a week and have observed no issues.

The overlay I use is here.

# Tests require an X11 server and yields a cannot open display error. It's
# probably possible to get an X server running in the build but seems hard.
doCheck = false;
checkPhase = ''
make test
'';
Copy link
Contributor Author

@benjaminedwardwebb benjaminedwardwebb Nov 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I'd like to enable this, the test triggered by make test invokes dmenu directly.

It runs

seq 1 100 | target/dmenu $(ARGS)

This not only requires an X11 server but it also hangs waiting for user input.

I was able to hack together the following checkPhase that works locally using timeout

timeout --preserve-status 5s xvfb-run make test

however simply hoping that 5 seconds is long enough for xvfb-run to spin up and the test to complete on every machine seems like an awful idea. I'm not sure how to kill the hanging call to dmenu, no option seems to allow that and I don't know how to feed in a keypress like <RETURN> into the xvfb-run context.

So I'm just leaving it disabled and relying on the other manual tests like installing, running the binary, and using it personally on a regular basis (at least for now).

Copy link
Contributor Author

@benjaminedwardwebb benjaminedwardwebb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ElvishJerricco @symphorien thanks for your help in working through some issues that stumped me while working on this derivation.

Of course not a priority, but if either of you have write-access and think the changes are worth merging, I'd appreciate getting this package out of a personal overlay and into nixpkgs where others can use it.

'';

RUST_BACKTRACE = "full";
LIBCLANG_PATH = "${libclang.lib}/lib";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RUST_BACKTRACE is not needed, it's just a vestige of development that I've now removed.

LIBCLANG_PATH is required but I'm not well-versed enough in these C libraries to know why. Not including it yields this error

error: failed to run custom build command for `headers v0.1.0 (/build/source/src/headers)`

Caused by:
  process didn't exit successfully: `/build/source/src/target/release/build/headers-ce9f3c3aabdd9ea3/build-script-build` (exit status: 101)
  --- stderr
  thread 'main' panicked at 'Unable to find libclang: "couldn't find any valid shared libraries matching: ['libclang.so', 'libclang-*.so', 'libclang.so.*', 'libclang-*.so.*'], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: [])"', /build/cargo-vendor-dir/bindgen-0.53.3/src/lib.rs:1956:31
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
make: *** [makefile:35: dmenu] Error 101

So I followed the error's advice and looked at the dependencies to see where I could find the .so files mentioned -- I found them and set LIBCLANG_PATH to the place where they lived.

Copy link
Member

@symphorien symphorien Nov 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to provide clang and the right flags to bindgen, use rustPlaftorm.bindgenHook instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That worked! Thanks for the tip about rustPlatform.bindgenHook.

# and make it writeable.
# See: https://github.com/rust-x-bindings/rust-xcb/tree/v0.8.2
patchPhase = ''
chmod +w /build/cargo-vendor-dir
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use /build. It is different depending on the machine. Use $NIX_BUILD_TOP.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment on lines 86 to 95
buildPhase = ''
make
'';

installPhase = ''
make install
'';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought these looked fishy at first, but it actually does make sense. We want the rust platform stuff because it does the vendoring and all that, but it doesn't just do make and make install like stdenv.mkDerivation does by default.

That said, this is very much not going to cross compile correctly. Not critical, but unfortunate, and probably fixable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a comment that tries to explain these phases' surprising appearance.

I'll be honest, I don't know the exact consequences of this package not cross compiling correctly, but it sure sounds bad. Is it related to not running ./configure in the configurePhase? Should I go read up on Autoconf and figure out how to add that into this derivation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't worry about it not cross compiling; frankly I don't think you can cross compile a desktop environment with nixpkgs right now anyway. It was just something I found noteworthy. But basically the package's makefile is hostile to cross compilation because e.g. it hardcodes CC=cc and doesn't have a way to choose the cargo target. It would need (relatively trivial) changes to their build scripting to fix this.

Copy link
Contributor Author

@benjaminedwardwebb benjaminedwardwebb Nov 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for calling it out. I'm not really a contributor to dmenu-rs (I fixed 1 typo) but it's something I'll keep in mind and who knows maybe I can fix it upstream some time in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you consider using mkDerivation with cargoSetupHook to handle fetching sources?

to quote the manual:

The rustPlatform.buildRustPackage function is split into several hooks: cargoSetupHook to set up vendoring for Cargo-based projects, cargoBuildHook to build a project using Cargo, cargoInstallHook to install a project using Cargo, and cargoCheckHook to run tests in Cargo-based projects. With this change, mixed-language projects can use the relevant hooks within builders other than buildRustPackage. However, these changes also required several API changes to buildRustPackage itself:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't. That sounds like a more natural way to write this derivation -- as a standard make-based build that happens to include cargo deps. I'll take a stab at rewriting it that way later today. Thanks for this!

@benjaminedwardwebb benjaminedwardwebb force-pushed the dmenu-rs branch 2 times, most recently from feee0f4 to abfee93 Compare November 21, 2022 02:30
Copy link
Contributor

@ElvishJerricco ElvishJerricco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little unhappy with the LIBCLANG_PATH thing; I don't really understand why this package is so picky about using clang and having this lib in this particular environment variable. But it's probably not worth blocking this PR over given that it's probably due to the package's excessively wonky build system.

cp -r "$NIX_BUILD_TOP/cargo-vendor-dir/xcb-0.8.2/." "$NIX_BUILD_TOP/cargo-vendor-dir/xcb-0.8.2-readwrite"
unlink "$NIX_BUILD_TOP/cargo-vendor-dir/xcb-0.8.2"
mv "$NIX_BUILD_TOP/cargo-vendor-dir/xcb-0.8.2-readwrite" "$NIX_BUILD_TOP/cargo-vendor-dir/xcb-0.8.2"
chmod -R +w "$NIX_BUILD_TOP/cargo-vendor-dir/xcb-0.8.2/"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need the copy step, and not only the recursive chmod?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.../cargo-vendor-dir/xcb-0.8.2/ is a symlink to the nix store. I don't think I can chmod the nix store inside of the build and in general making anything in the nix store writeable seems conceptually wrong?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh it's originally a symlink, I thought it was a copy. My bad.

you can remove the final chmod -R by using cp --no-preserve=mod then

};

nativeBuildInputs = [
clang
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with bindgenHook you presumably need neither libclang, llvm nor clang.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to drop llvm and libclang, but it wouldn't build without keeping clang.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please drop clang and modify https://github.com/Shizcow/dmenu-rs/blob/master/config.mk#L14 as suggested by the error message

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting I modify this upstream at Shizcow/dmenu-rs or through a patch in the nix derivation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

downstream is ok (either as a patch or as substituteInplace config.mk --replace 'clang' '$(CC)' in postPatch for example)
But hard coding clang as compiler is not distro-friendly in general so you may submit this change upstream if so you wish, after we merge this PR. Using $(CC) is more portable and preferable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added it as a patch here, but also opened this PR upstream.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you forgot to remove the dependency on clang. Thank you for reaching upstream :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh you're right, woops

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Comment on lines 74 to 75
# As suggested in the nixpkgs manual section on building rust packages, the
# derivation's Cargo.lock file is copied into the source.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# As suggested in the nixpkgs manual section on building rust packages, the
# derivation's Cargo.lock file is copied into the source.

Mentioning the manual is not needed.

cp ${./Cargo.lock} src/Cargo.lock
'';

# The cargo project does not live at the repository's top-level directory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too obvious to be commented.

Suggested change
# The cargo project does not live at the repository's top-level directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for keeping things concise! :)

@benjaminedwardwebb benjaminedwardwebb force-pushed the dmenu-rs branch 4 times, most recently from cc5e910 to d0a1a0f Compare December 14, 2022 04:59
benjaminedwardwebb added a commit to benjaminedwardwebb/dmenu-rs that referenced this pull request Dec 14, 2022
While adding dmenu-rs as a package to my distro, some reviewers
suggested the hardcoded clang be dropped upstream in favor of using the
system default.

See: NixOS/nixpkgs#200977

cargoRoot = "src";

preConfigure = ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more corners to trim

  1. this should be a postPatch
  2. It is better to remove this setting from config.mk: sed -i "s@PREFIX = /usr/local@@g" config.mk
  3. Way better: remove this preConfigure completely, and use installFlags = [ "PREFIX=$(out)" ]; instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually was trying to go with something like 3 initially, but then decided to just copy what the vanilla C-based dmenu was doing in its build: https://github.com/NixOS/nixpkgs/blob/d0a1a0f243138978b1d258056eb5988787da7aac/pkgs/applications/misc/dmenu/default.nix#L21-L23

But I agree, installFlags seems more sensible. Let me see if I can get it working.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, updated to use installFlags. I think the first time I was trying to use makeFlags and couldn't figure out why it wasn't working -- thanks for suggesting the right way.

runHook postPatch
'';

postPatch = ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no reason to have both postPatch and a patchPhase. As the default patchPhase is still useful if someone downstream wants to add a patch with overrideAttrs, it is probably better to move the content of patchPhase (except runHook) to postPatch.

Copy link
Contributor Author

@benjaminedwardwebb benjaminedwardwebb Dec 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I've moved everything over into postPatch.

But, any guidance on what is a good definition of a patch is / what should generally go in patchPhase?

Should it only be applying .patch files? Or any change to the project's source code? Any change to the project's build? Any change to the project's dependencies' source code or build?

I guess what this patchPhase was doing was

  • changing the project's build code (config.mk and copying in Cargo.lock)
  • subtly changing a vendored dependency so that it can be written to, without actually altering any of that dependency's source code or build code

So if we drew the line at "patches are things that alter a project's source code (but not necessarily build code)" then it seems like it makes sense to keep it all out of patchPhase.

Probably there's no hard rule but just trying to get a feel for what is what in nixpkgs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, any guidance on what is a good definition of a patch is / what should generally go in patchPhase?

Should it only be applying .patch files? Or any change to the project's source code? Any change to the project's build? Any change to the project's dependencies' source code or build?

Typically, many distros (if not all!) provide .patch files in order to directly modify the source code of the apps they provide.

A typical case is when a new compiler release does not compile some old code (indeed it happened to me when I tried to compile qemu in Slackware a long time ago...). So, usually a package manager provides patch files for cases like these.
Indeed, many times those patchsets are generated by merely diffing the master git branch with the current stable git branch, maybe because some people like ultra fresh, pre-alpha code...

Another thing that such package managers can do too is run sanitization scripts that clean up some quirks on the original source code; things like removing annoying lines from a Makefile or fixing hardcoded locations (e.g. FreeBSD ports system installs things on /usr/local/ instead of /usr/; so maybe some tool that expects to find things on /usr will not get it without help).

It gets a bit complicated when both things need to be done: .patch files to modify C source code, plus sanitization scripts that cleanup Makefiles.

Now, switch to Nix(pkgs).

In Nixpkgs, we provide both use cases via the same patchPhase. However, as I said above, it is a bit complicated...

The typical, unedited patchPhase usually works like this:

patchPhase = ''
  runHook prePatch

  patch -p1 < <the .patch files provided in patches =[ ... ];>
 
  runHook postPatch
''

The runHooks are there because of composability:

Nix has the ability of compose overlays of package trees, in a similar manner when you add third party repositories in other package managers (/etc/apt/sources.lst anyone?).
Such pre and post hooks allow the creator of an overlay to easily modify the phases without having to rewrite them completely.

Well, when you customize this phase as above, it would look like

patchPhase = ''
  runHook prePatch

  <a giant script modifying the source code>
 
  runHook postPatch
''

However, by doing this, you are basically ignoring any .patch files eventually provided in patches list.

So, when you need to use such "sanitization scripts", it is better to use postPatch instead of rewriting the whole patchPhase.

Probably there's no hard rule but just trying to get a feel for what is what in nixpkgs.

Sometimes many things are developed by trial and error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah thank you for all that good background knowledge!

@benjaminedwardwebb benjaminedwardwebb force-pushed the dmenu-rs branch 2 times, most recently from 2a3c898 to fb3ac05 Compare December 15, 2022 22:57
@symphorien
Copy link
Member

Looks good now! Thank you for bearing with us. One last thing before I merge: this does not build on aarch64 (see https://github.com/NixOS/nixpkgs/pull/200977/checks?check_run_id=10128726771 ). It looks due to upstream but unintended, so please mark it as broken like here

https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/audio/eq10q/default.nix#L36

You can optionally report it upstream, and if they answer that aarch64 support is not in scope for the project, remove the broken attribute and restrict platforms to x86-64-linux only instead.

dmenu-rs is a pixel perfect port of dmenu, rewritten in Rust with
extensive plugin support.

See: https://github.com/Shizcow/dmenu-rs
@benjaminedwardwebb
Copy link
Contributor Author

Looks good now! Thank you for bearing with us. One last thing before I merge: this does not build on aarch64 (see https://github.com/NixOS/nixpkgs/pull/200977/checks?check_run_id=10128726771 ). It looks due to upstream but unintended, so please mark it as broken like here

https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/audio/eq10q/default.nix#L36

You can optionally report it upstream, and if they answer that aarch64 support is not in scope for the project, remove the broken attribute and restrict platforms to x86-64-linux only instead.

@symphorien added aarch64-linux as broken. However, I use an aarch64-linux machine pretty regularly, so am interested in adding support upstream if possible (and filed this issue related to it). I don't know how easy this will be, though, so maybe it will have to wait for another PR to nixpkgs.

@AndersonTorres Anything holding up an approval?

@AndersonTorres AndersonTorres merged commit 60d4720 into NixOS:master Dec 20, 2022
@benjaminedwardwebb benjaminedwardwebb deleted the dmenu-rs branch December 20, 2022 06:06
@benjaminedwardwebb
Copy link
Contributor Author

Thanks all for the help reviewing and getting this merged! Adding my first package to nixpkgs was a very pleasant experience.

benjaminedwardwebb added a commit to benjaminedwardwebb/dmenu-rs that referenced this pull request Jan 19, 2023
While adding dmenu-rs as a package to my distro, some reviewers
suggested the hardcoded clang be dropped upstream in favor of using the
system default.

See: NixOS/nixpkgs#200977
benjaminedwardwebb added a commit to benjaminedwardwebb/dmenu-rs that referenced this pull request Feb 23, 2023
While adding dmenu-rs as a package to my distro, some reviewers
suggested the hardcoded clang be dropped upstream in favor of using the
system default.

See: NixOS/nixpkgs#200977
@Janik-Haag Janik-Haag added the 12. first-time contribution This PR is the author's first one; please be gentle! label Jun 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
8.has: package (new) This PR adds a new package 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 10.rebuild-linux: 1 11.by: package-maintainer This PR was created by the maintainer of the package it changes 12. first-time contribution This PR is the author's first one; please be gentle!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants