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

rr: include gdb as a propagated input #57590

Merged
merged 1 commit into from Nov 30, 2019

Conversation

langston-barrett
Copy link
Contributor

Motivation for this change

rr crashes at runtime when gdb isn't available

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Assured whether relevant documentation is up to date
  • Fits CONTRIBUTING.md.

@thoughtpolice
Copy link
Member

Thanks! I probably missed this because I normally have gdb in my environment.systemPackages on my development machines.

Hmmm, I wonder if it might be better to actually use wrapProgram to add gdb to the prefix of $PATH -- generally I, at least, like to not pollute "extra" paths into your user environment through propagated* inputs if possible. Or maybe we could substituteInPlace on the source (but wrapProgram is more robust)...

@langston-barrett
Copy link
Contributor Author

@thoughtpolice Thanks for taking a look! I'm afraid I haven't used either technique before. What would wrapProgram look like here? Similar to the second makeWrapper example in the manual?

@thoughtpolice
Copy link
Member

After some discussion with other developers on IRC, the makeWrapper approach was suggested as superior: notably, propagatedBuildInputs results do not appear in $PATH/bin e.g. when you use nix-env to install packages, for example. A wrapper makes this consistently work in all cases.


Here's an example from an expression I updated the other day, which is the Souffle Datalog compiler: https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/souffle/default.nix#L41

The basic idea is just to add makeWrapper to your nativeBuildInputs (this helps cross compilation and ensures it is only available at build time, and that makeWrapper is not needed at runtime), and then write something like this for a postInstall hook:

let
  neededToolsPath = stdenv.lib.makeBinPath [ gdb ];
in
  ...
  postInstall = ''
    wrapProgram "$out/bin/rr" --prefix PATH : "${neededToolsPath}"
  '';

The use of makeBinPath automatically converts the list of packages to a $PATH-style semicolon list, and this makes the wrapper more robust to changes over time -- e.g. in case you maybe wanted to add binutils to that path later for some other tool, you only need to add it to the list and be done with it.

You may also use wrapProgram at another point in the expression, for example, in a different phase -- but for things like rr (or souffle), where you can use the default installPhase rules, postInstall is the most ideal, and will be run after make install succeeds.

Copy link
Member

@thoughtpolice thoughtpolice left a comment

Choose a reason for hiding this comment

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

(Requesting changes based on previous comments)

@langston-barrett
Copy link
Contributor Author

@thoughtpolice Thank you so much for the detailed explanation! I will make the required changes.

@catern
Copy link
Contributor

catern commented Mar 15, 2019

wrapProgram works but it would be even better if you could just patch the software to hardcode the path of gdb at build time. That would be more idiomatic Nix, would be slightly more reliable, and would remove the unnecessary shell script wrapper.

Hopefully rr only actually has the string "gdb" in one place, which it uses to look gdb up on PATH; in which case you can just replace that string with the full Nix path.

@thoughtpolice
Copy link
Member

thoughtpolice commented Mar 15, 2019

That would be more idiomatic Nix

Whether or not one or another is more idiomatic is up to opinion of maintainer (in my opinion, both are so pervasive calling one more "idiomatic" than the other is largely a moot point).

would be slightly more reliable

This is not really true in my experience, especially compared to makeWrapper; in practice programmers regularly refactor code and move things around, making updates for changes like this more tedious as you may have to search the source code to ensure things keep working (in this case, it will fail outright if GDB is not available; in many other circumstances the functionality may be more subtle to ensure it keeps working correctly.) substituteInPlace can also often become tricky or annoying to use because you often have to use a unique search prefix to ensure only exact cases you call for are matched, and this happens more often than most people would like (you often cannot just search X or "X" or even = "X" because you will hit too many otherwise irrelevant matches and break the program.)

You can alternatively write a .patch for it, but in this case that's a bit overkill, IMO.

But even then, in this case, rr is a complicated enough codebase and I cannot easily even find where it re-invokes GDB without downloading and looking over the source; I of course could not be trying hard enough. On the other hand, I have enough things to do that putting time into this particular endeavor is, on all counts, mostly a waste. In contrast, wrapProgram works all the time and has easy to understand semantics and is much easier to refactor and change over the course of an expressions life.

There are of course uses for the family of substitute functions -- they obviously do not do the same thing, so some instances will have advantages and some won't. And I use them (substutitute*, .patch files) plenty. But I don't think either of these arguments mean very much in this particular instance, and as an rr maintainer, wrapProgram seems perfectly fine.

@catern
Copy link
Contributor

catern commented Mar 16, 2019

As you say, some software is designed such that it's hard to make a single patch to override an executable location. For such software, it would be good to send a change upstream so that the executable location can be more easily patched.

Best yet would be to send a change upstream so that the executable location can be passed as an input to the build process, via whatever equivalent to "./configure --some-executable-location=$gdb/bin/gdb" rr has. Then there's no wrapper and no patching, it's just a natural part of the build process.

Ideally, such an option already exists in the rr build process, and we can just use it. Certainly such an option is something that would be useful to anyone compiling rr from source...

But wrapProgram works, and it requires less effort, so it's fine; using it is certainly an improvement over the status quo of getting gdb from the user's PATH.

@aanderse
Copy link
Member

aanderse commented Aug 5, 2019

ping (triage)

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

Successfully merging this pull request may close these issues.

None yet

5 participants