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

feature request: Nix Integration support for flake.nix #9046

Open
peterbecich opened this issue Jun 19, 2023 · 7 comments
Open

feature request: Nix Integration support for flake.nix #9046

peterbecich opened this issue Jun 19, 2023 · 7 comments

Comments

@peterbecich
Copy link
Member

Currently

If the package (which must be locally unpacked) provides a shell.nix or default.nix file, this flag will cause cabal to run most commands through nix-shell. If both expressions are present, shell.nix is preferred.

https://cabal.readthedocs.io/en/stable/nix-integration.html#nix-integration

flake.nix can do everything that shell.nix and default.nix can do, as I understand it. Some projects only have flake.nix.

Can we support Nix Flake Integration in Cabal?


Question:

  • Using Cabal's Nix Integration feature as it works today, provided a default.nix is present, will Cabal pull Haskell library dependencies from the Nix project?

or

  • Is Cabal's Nix Integration intended to provide system dependencies like openssl or libjpeg?

or

  • both?

If Cabal's Nix Integration is intended to provide system dependencies, not Haskell library dependencies, I think Nix Flake Integration is unnecessary. The reason is, working in a nix develop shell provided by flake.nix, Cabal will already have access to the system dependencies provided by flake.nix.

@fendor
Copy link
Collaborator

fendor commented Jun 19, 2023

Hi!

Cabal's nix integration is for v1- commands, afaict, and is not used in v2- commands. In other words, whenever you use cabal build, enable-nix doesn't do anything (maybe it causes a dependency cache miss).

see issues labelled nix integration

@ulysses4ever
Copy link
Collaborator

Cabal's nix integration is for v1- commands

Correct. And v1 is deprecated. I think spending energy on improving v1-only features it's not the best...

Also, I don't remember seeing many project that have flake.nix but no default.nix

@geekosaur
Copy link
Collaborator

xmonad does, for what little that's worth. Flakes are, as I understand it, still a new feature.

@fgaz
Copy link
Member

fgaz commented Jun 20, 2023

Using Cabal's Nix Integration feature as it works today, provided a default.nix is present, will Cabal pull Haskell library dependencies from the Nix project?

no

Is Cabal's Nix Integration intended to provide system dependencies like openssl or libjpeg?

no

--enable-nix just runs commands through a nix shell, nothing more. As written by others it isn't supported by v2- commands, and I think there are better ways to do that anyway, such as direnv and similar tools, or hooks (#7394)

I have plans for a deeper nix integration but that's still in my head
edit: #9089

@ScottFreeCode
Copy link

@peterbecich Your questions sound like you're looking for how to have Nix provide the environment for Cabal; if I'm understanding that correctly, I've written up a basic example on that. https://gist.github.com/ScottFreeCode/9b0ea3e52fa56c93ea8ca14791e55bb4 (You'll probably want the "one package" variant and ignore the "monorepo" and "+preprocessing" versions unless and until you need them, and I expect you'll know if/when that is.)

@fgaz I'd be curious how that compares to your ideas about Nix integration; it turns out that the crux of it is a simple use of the callCabal2Nix command in the Nix file (and putting all the right things in the right places in the cabal file[s]), but this function is basically undocumented last I checked.

Anyway now that I've got these examples up I should go share it around to various issues that it's relevant to (the bugs that affect it, issues where people are looking for a way to use Haskell in Nix with Nix providing the environment but without changing how they use Haskell, etc.). I just saw this issue when I was checking that nobody had already filed another bug I needed to file, and figured I'd drop in and offer the suggestion in answer to the questions.

@peterbecich
Copy link
Member Author

peterbecich commented Aug 14, 2023

Thanks everybody, apologies for my late response.

@ScottFreeCode , thank you. I am not sure https://gist.github.com/ScottFreeCode/87bec0c569598014053579990a5bef6e is what I'm attempting to describe.

Your gist here "Cabal v2 Build inside Nix Shell does not see executables such as Alex, Happy (BNFC?)" is part of what I'm attempting to describe: https://gist.github.com/ScottFreeCode/ef9f254e2dd91544bba4a068852fc81f

Inside a nix develop shell defined in a flake.nix, I would like cabal commands to pull all resources from the flake.nix environment. This includes system utilities such as alex and happy, and all Hackage dependencies. IMO this would be a great user experience for the Haskell developer; cabal commands would be used as normal, but the inputs to cabal would be carefully controlled by the flake.nix environment.

To my knowledge, the only way to accomplish this today is by nix build and nix run ... commands, regardless of using the nix develop shell and/or direnv. Is this accurate?

Right now a.f.a.i.k. most Haskell projects with a flake.nix have:

  • a Nix build and workflow
  • a Cabal build and workflow

and there is no link between the inputs of these two.
If my understanding of the current situation is accurate, this proposal would make the inputs to these two builds/workflows guaranteed to be identical.


Regarding Cabal v1- commands Nix support, I understand now this runs the Cabal v1- commands in the provided nix-shell. Utilities would be provided by the shell. Does this feature also pull the Hackage dependencies from Nix?

@ScottFreeCode
Copy link

@peterbecich Both cabal v1-build and cabal v2-build use Nix-provided packages. It's only Nix-provided executables that don't work in v2-build. Triple-checked this, details below.

(Caveat: I don't know for certain about nix develop and flakes, I've only tested with nix-shell as in those gists. As you say, I would expect flakes/develop to be able to do everything nix-shell does, but I'm not as familiar with how to try it. I could be wrong but I would not expect any changes to be needed on Cabal's side, since – if I understand correctly – Nix handles providing the dependencies to Cabal in the case of nix-shell, rather than Cabal calling out to Nix or something.)

Phase One

First, to make sure I have a package that is not provided with GHC.

We'll test this with a script, no callCabal2nix.

Sanity Check with a GHC-provided package

For example, this script saved as process.hs and run as chmod +x process.hs ; ./process.hs, works:

#! /usr/bin/env nix-shell
#! nix-shell -i runhaskell --packages ghc

module Main where

import System.Process (callProcess)

main = callProcess "pwd" []

Sanity Check that if Nix provides the additional package, it works

This one also works (saved as shh.included.hs)…

#! /usr/bin/env nix-shell
#! nix-shell -i runhaskell --packages "haskellPackages.ghcWithPackages (ps: [ps.shh])"
{-# LANGUAGE TemplateHaskell #-}

module Main where

import Shh

loadExe SearchPath "pwd"

main = pwd

But if we use that package without Nix providing it, it does not work

This one, which does not specify the package shh, fails (saved as shh.notincluded.hs):

#! /usr/bin/env nix-shell
#! nix-shell -i runhaskell --packages ghc
{-# LANGUAGE TemplateHaskell #-}

module Main where

import Shh

loadExe SearchPath "pwd"

main = pwd

It gives me this error:

shh.notincluded.hs:7:1: error:
    Could not find module `Shh'
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.
  |
7 | import Shh
  | ^^^^^^^^^^

Phase Two

Now we have a package that will only compile if something provides it, and we have a Main module that uses that package.

  1. Clone the one-package, no +preprocessing gist.
  2. Add , shh to the dependencies list after base in the .cabal file.
  3. Copy ssh.included.hs over app/Main.hs but delete the lines starting with #!
  4. nix-shell
  5. cabal v2-build
  6. ./dist-newstyle/**/example
  7. cabal v1-build
  8. ./dist/example/example

Both cabal build commands will start with a warning:

Warning: The package list for 'hackage.haskell.org' does not exist. Run 'cabal
update' to download it.

I don't see any evidence that ~/.cabal contains any downloaded packages.

It should build and run OK, however.

It appears that both v1- and v2- can build using Nix-provided packages inside nix-shell

Alternative Phase One

Instead of saving all those scripts, you could instead do a version of Phase Two but skipping step 2 (don't modify the .cabal file) to see that it fails to build if shh is not provided, I guess.

What about flakes and nix develop

Could anyone port the above proof of concept to use flakes and nix develop in place of nix-shell? At risk of repeating myself, I'm not super familiar with flakes and the new CLI.

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

No branches or pull requests

6 participants