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

nix-shell always uses '<nixpkgs>', despite giving it a different path #459

Open
cstrahan opened this issue Jan 25, 2015 · 19 comments
Open
Labels
nix-shell nix-shell, nix develop, nix print-dev-env, etc UX The way in which users interact with Nix. Higher level than UI.

Comments

@cstrahan
Copy link
Contributor

λ nix-shell --version
nix-shell (Nix) 1.8

Note that the two paths are the same when I use nix-shell:

λ nix-shell --pure -p ruby_2_1_3 --command "which ruby" '<nixpkgs>'
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
/nix/store/73ysd4rxnfzgvk8r1xxyzrsdvfkbs21h-ruby-2.1.3-p0/bin/ruby

λ nix-shell --pure -p ruby_2_1_3 --command "which ruby" ~/src/nixpkgs
warning: dumping very large path (> 256 MiB); this may run out of memory
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
/nix/store/73ysd4rxnfzgvk8r1xxyzrsdvfkbs21h-ruby-2.1.3-p0/bin/ruby

Setting $NIX_PATH gives me the store path I would expect:

λ NIX_PATH=nixpkgs=$HOME/src/nixpkgs:$NIX_PATH nix-shell --pure -p ruby_2_1_3 --command "which ruby"
bash: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF-8): No such file or directory
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
/nix/store/lxc9ikrvvq4z1jmla25yzdgvi99hcwcw-ruby-2.1.3-p0/bin/ruby

Also, nix-build works as I would expect:

λ nix-build ~/src/nixpkgs -A ruby_2_1_3
/nix/store/lxc9ikrvvq4z1jmla25yzdgvi99hcwcw-ruby-2.1.3-p0

nix-shell is apparently not using the path that I'm providing. Interestingly, though, it does at least validate that the path is real:

λ nix-shell --pure -p ruby_2_1_3 --command "which ruby" this/path/does/not/exist
error: getting attributes of path ‘/home/cstrahan/src/nixpkgs/pkgs/applications/version-management/gitlab/this/path/does/not/exist’: No such file or directory
(use ‘--show-trace’ to show detailed location information)

I'm also seeing the same behavior on the latest unstable Nix in Nixpkgs.

@cstrahan
Copy link
Contributor Author

Using a full path to nixpkgs/default.nix:

λ nix-shell -p ruby_2_1_3 --command "which ruby" ~/src/nixpkgs/default.nix
bash: /nix/store/gidslcaj9jg5pan2zvwf8vid6fl8ny3g-default.nix: line 5: syntax error near unexpected token `else'
closeNest: command not found

@cstrahan
Copy link
Contributor Author

Here's the relevant code:

if ($packages) {
    push @instArgs, "--expr";
    @exprs = (
        'with import <nixpkgs> { }; runCommand "shell" { buildInputs = [ '
        . (join " ", map { "($_)" } @exprs) . ']; } ""');
} elsif (!$fromArgs) {
    @exprs = ("shell.nix") if scalar @exprs == 0 && $runEnv && -e "shell.nix";
    @exprs = ("default.nix") if scalar @exprs == 0;
}

And here's an excerpt from man nix-shell:

If path is not given, nix-shell defaults to shell.nix if it exists, and default.nix otherwise.

From reading that, I would expect the above code to use "path" in place of <nixpkgs> - to be more specific, the same semantics as nix-build.

@edwtjo
Copy link
Member

edwtjo commented Jan 25, 2015

You can work around it and use NIX_PATH to set it straight, NIX_PATH="nixpkgs=$NIXPKGS_REPO:nixos=$NIXPKGS_REPO/nixos:$NIX_PATH" nix-shell

@cstrahan
Copy link
Contributor Author

@edwtjo Right, but that's pretty inconvenient. And, I think we should keep the semantics of nix-build and nix-shell as close as possible. I'd hate to tell newcomers

  • When using nix-build, just pass the path to the expression you want to pull attrs out of, but
  • When using nix-shell, you have to preface it with NIX_PATH=nixpkgs=some/path/here:$NIX_PATH

@edolstra Would you welcome a PR that resolves the disparity?

@edwtjo
Copy link
Member

edwtjo commented Jan 25, 2015

@cstrahan I agree completely and obviously a bit tired since I failed to spot that you gave that exact example in your initial report :)

@edolstra
Copy link
Member

Well, when you use nix-shell -p, all arguments are interpreted as attribute names inside Nixpkgs. So nix-shell -p firefox /path/to/nixpkgs is equivalent to buildInputs = [ firefox /path/to/nixpkgs ];. We could give an error/warning for arguments that don't look like attribute names though.

@cstrahan
Copy link
Contributor Author

@edolstra

Well, when you use nix-shell -p, all arguments are interpreted as attribute names inside Nixpkgs. So nix-shell -p firefox /path/to/nixpkgs is equivalent to buildInputs = [ firefox /path/to/nixpkgs ];. We could give an error/warning for arguments that don't look like attribute names though.

I think I'd rather just clarify that in the docs/manpage.

However, I'm more concerned about the verbosity required to do something along the lines of nix-env -f some/path/here ... or nix-build some/path/here .... Could we, perhaps, add a -f flag identical to nix-env's?

@edolstra
Copy link
Member

There is -I nixpkgs=/path/to/nixpkgs.

@cstrahan
Copy link
Contributor Author

Yeah, that's not super terrible. I wasn't stating that what I wanted to do was impossible, just not very intuitive given the semantics of the other nix-* commands.

I'm not really speaking for myself, so much as the people that I'd like to get hooked on Nix. Unfortunately, my experience is that most people's brains (including those I have much respect for) turn to mush when given many similar-but-not-quite-the-same ways to do the same thing.

@copumpkin
Copy link
Member

Agreed, the inconsistency in interface across the various tools feels like a bit of a barrier.

@lucabrunox
Copy link
Contributor

@edolstra I think it could be possible to do nix-shell ./nixpkgs -p foo.bar, so that all arguments after -p are interpreted as build inputs.

@bjornfor
Copy link
Contributor

IMHO, allowing -p a b c is a bit odd. I think a more typical command line interface would be -p a -p b -p c. Yes, it's a bit more typing.

@stale
Copy link

stale bot commented Feb 15, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added the stale label Feb 15, 2021
@balodja
Copy link

balodja commented Jul 25, 2021

Just ran into this issue trying to understand, what's wrong with my corrections to nixpkgs. So one additional vote to make command arguments more homogeneous.

@stale stale bot removed the stale label Jul 25, 2021
@AleXoundOS
Copy link

AleXoundOS commented Dec 10, 2021

@edolstra I think it could be possible to do nix-shell ./nixpkgs -p foo.bar, so that all arguments after -p are interpreted as build inputs.

Instead, this works: nix-shell -p '(import ./nixpkgs {}).foo.bar'.
Multiple packages variant: nix-shell -p 'with (import ./nixpkgs {}); [ foo.bar foo2 foo3 ]'.

But I think nowadays nix with flakes support offers something better.


Note for newcomers, who follow import ./nixpkgs {} pattern: make sure there is no .git inside ./nixpkgs, or you end up copying 2 GiB + into /nix/store for no reason. Or quick workaround is to exclude it: import (builtins.filterSource (p: _t: baseNameOf p != ".git") ./nixpkgs) {}.

More flexible approach for local projects is to import some pkgs.nix instead.

let
  pin = builtins.fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/ffffffffffffffffffffffffffffffffffffffff.tar.gz";
    sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffff";
  };
in
import pin { overlays = [ (import ./some-project-specific-overlay.nix) ]; }

@tobiasBora
Copy link

I'm curious, what's wrong with this:

### This fails:
$ nix-shell -I nixpkgs=channel:nixgl -p auto.nixGLDefault
warning: Nix search path entry 'channel:nixgl' cannot be downloaded, ignoring
error: undefined variable 'auto'

       at «string»:1:107:

            1| {...}@args: with import <nixpkgs> args; (pkgs.runCommandCC or pkgs.runCommand) "shell" { buildInputs = [ (auto.nixGLDefault) ]; } ""
             |                                                                                                           ^
(use '--show-trace' to show detailed location information)

### This works:
$ nix-shell -p '(import <nixgl> {}).auto.nixGLDefault'
building '/nix/store/in6bypjy4wf3xh7mp9bpfy25x8cn63x9-impure-nvidia-version-file.drv'...
cp: cannot stat '/proc/driver/nvidia/version': No such file or directory
[nix-shell:~]$ 

@tobiasBora
Copy link

@AleXoundOS Also, what do you mean by saying that flakes provides something better? How would you do that in the flake flavor?

@jtojnar
Copy link
Member

jtojnar commented May 5, 2022

I'm curious, what's wrong with this:

### This fails:
$ nix-shell -I nixpkgs=channel:nixgl -p auto.nixGLDefault

channel: URIs have nothing to do with nix-channel:

/* Resolve deprecated 'channel:<foo>' URLs. */
std::string resolveUri(std::string_view uri);

if (uri.compare(0, 8, "channel:") == 0)
return "https://nixos.org/channels/" + std::string(uri.substr(8)) + "/nixexprs.tar.xz";

You could specify -I nixpkgs=$HOME/Projects/nixGL or -I nixpkgs=https://github.com/guibou/nixGL/archive/master.tar.gz but that will still not work since nix-shell expect that nixpkgs NIX_PATH entry is really Nixpkgs:

joined << "{...}@args: with import <nixpkgs> args; (pkgs.runCommandCC or pkgs.runCommand) \"shell\" { buildInputs = [ ";

Also, what do you mean by saying that flakes provides something better?

Flakes introduce nix shell command, which does not depend on Nixpkgs for execution:

nix shell --impure github:guibou/nixGL#nixGLDefault

Though that also obviously removes Nixpkgs features like running setup hooks that set-up environment variables like PKG_CONFIG_PATH. Fortunately, you can still use nix develop if you need that.

@tobiasBora
Copy link

Oh interesting, thanks! It would be great to document this (like man nix-shell does not even mention -I in the list of arguments, the single reference to -I is somewhere in the examples and just says You can override it by passing -I or setting NIX_PATH.. It's too bad that nix shell does not allow environment variable configuration.

@fricklerhandwerk fricklerhandwerk added nix-shell nix-shell, nix develop, nix print-dev-env, etc UX The way in which users interact with Nix. Higher level than UI. labels Sep 12, 2022
zolodev pushed a commit to zolodev/nix that referenced this issue Jan 1, 2024
@edolstra edolstra removed their assignment Apr 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
nix-shell nix-shell, nix develop, nix print-dev-env, etc UX The way in which users interact with Nix. Higher level than UI.
Projects
None yet
Development

No branches or pull requests