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

Support reproducible builds via Nix #1285

Merged
merged 60 commits into from
Dec 3, 2015

Conversation

YPares
Copy link
Collaborator

@YPares YPares commented Nov 4, 2015

This pull request implements the capability for stack to launch the build inside a nix-shell, in order to specify dependencies to libraries out of Hackage that exist in Nixpkgs.

Simply modify your stack.yaml so it contains for instance:

nix:
    enable: false
    packages: [glpk]
    #shell-file: shell.nix

Build this project with stack --nix build. It will open a Nix-shell that will first download the glpk dependency, and then launch the build. Of course, this requires nix to be installed on your system, and it requires your stack.yaml to depend on an LTS resolver that has been mirrored in the nix packages (see for instance in https://github.com/NixOS/nixpkgs/tree/master/pkgs/development/haskell-modules the configuration-lts-X.Y.nix files).
If you know nix, you can also specify a shell.nix that creates a derivation that will be used to set the build environment. You cannot specify packages and shell-file at the same time!
For now, this works much like the docker backend, by relauching the same stack executable inside a new environment. It requires GHC to be installed by Nix.

It's not possible to use stack ghci, because GHCi fails to find the extra libraries, but this is not specific to stack, as the command:
nix-shell --pure -p ghc extra-libs --command "stack ghci"
without enabling nix support in stack already fails.

Theoretically, activating both Nix and Docker could be possible (resulting in a nix-shell running inside a container), but that requires a Docker image providing Nix, of course.

YPares and others added 30 commits November 4, 2015 16:00
Don't dispatch on the ExecEnv type. Using Docker and nix is no longer
mutually exclusive. We run commands in a docker container if configured,
and then fork a nix-shell inside if configured.
Using PackageNames forbid to use '.' in names, which is required when
you use attributes
Just filePath -> "from file: " ++ filePath
Nothing -> "with nix packages: " ++ (intercalate ", " pkgsInConfig))
e <- try (callProcess'
(if isTerm then id else \cp -> cp { delegate_ctlc = False })
Copy link
Contributor

Choose a reason for hiding this comment

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

I doubt the extra logic to prevent delegating Ctrl-C is necessary in this case. For Docker, it's there because of some specific weird stuff that docker run and docker start do with container terminals, but this nix-shell looks like a regular process that uses the existing std* file handles and TTY normally.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed along with previous

@borsboom
Copy link
Contributor

When I tried this with a resolver that hadn't been mirrored to nix yet, I got the following error:

error: attribute ‘lts-3_14’ missing, at (string):1:163
(use ‘--show-trace’ to show detailed location information)

After reading the docs I understood what this meant, but is it possible to make this more user-friendly? It would be nice if the error at least indicates why this would happen and perhaps suggests running nix-channel --update (if that makes sense). Perhaps it could even run the update automatically and retry, kind of like how Stack will download a snapshot automatically the first time it's encountered (not sure if Nix users would like automatic update though; I defer to your judgement about whether this is a good idea).

@borsboom
Copy link
Contributor

Thanks for all the work on this, it looks really close to being ready to merge! Don't forget to add a changelog entry. It should go in the major changes section; this deserves lots of attention!

@YPares
Copy link
Collaborator Author

YPares commented Nov 27, 2015

@borsboom I pushed a new commit addressing your comments.

Although, regarding this Nix error about the missing attribute, to provide a more informative error message I would need to ask nix about which attributes are available, which is not easy to automate as I pointed out in the manual.

The real fix would be to stop to depend on a GHC provided by Nix and use a GHC downloaded by Stack, but for now on Linux this results in failure to find libs in the nix store.

@borsboom
Copy link
Contributor

Fair enough, I don't think the error message should hold up merging this, although it would be nice to improve at some point. I'm not surprised that trying to use a non-Nix GHC causes problems, so leaving that as-is is reasonable.

Do you think this may end up with similar problems as Docker in #911 and #1367? I'm beginning work on a fix for those two now, and most likely the same approach can be used for Nix as well.

Just filePath -> "from file: " <> (T.pack filePath)
Nothing -> "with nix packages: " <> (T.intercalate ", " pkgsInConfig))
e <- try (exec
(EnvSettings {esIncludeLocals = False
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use Stack.Config.Types.minimalEnvSettings instead.

@YPares
Copy link
Collaborator Author

YPares commented Dec 1, 2015

@borsboom I corrected the escaping of the command line and re-merged the master.
Also, for coherence's sake, I made a slight adjustment: the section in the yaml is just called nix: now (no longer nix-shell:).
That's because the CL option was already --nix and because soon nix will adopt a git-like CL interface. I.e. the nix-shell tool will become just another subcommand of a big nix command.

borsboom added a commit that referenced this pull request Dec 3, 2015
Support reproducible builds via Nix
@borsboom borsboom merged commit 931cb02 into commercialhaskell:master Dec 3, 2015
@borsboom
Copy link
Contributor

borsboom commented Dec 3, 2015

LGTM, thanks for this awesome new feature!

@mgsloan
Copy link
Contributor

mgsloan commented Dec 3, 2015

Awesome :D

I think this warrants a Major changes entry in the ChangeLog

@YPares
Copy link
Collaborator Author

YPares commented Dec 3, 2015

@mgsloan @borsboom Thanks guys!

@YPares
Copy link
Collaborator Author

YPares commented Dec 3, 2015

I will publish a blog post about this feature shortly.

@codygman
Copy link

@YPares looking forward to it, will you post it back here?

@borsboom
Copy link
Contributor

@mboes mboes deleted the nix-merged branch December 13, 2015 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants