Sandboxing should be used by default #1101

Closed
tibbe opened this Issue Nov 6, 2012 · 16 comments
@tibbe
Haskell member

This follows the "make it correct, then make it fast" principle. Sandboxing helps with a certain class of build problems, namely problems due to two different builds overwriting each others' dependencies in the shared package database. This problem shows up as a dangerously sounding cabal warning message, mentioning the --force-reinstalls flag.

Sandboxing is an imperfect solution to this problem, requiring more rebuilding of packages than strictly necessary. A final solution would involve something like a Nix-style, append-only package database. The Nix solution is being worked on, as part of GSoC, but it's a difficult problem and it requires more wide-reaching changes (e.g. to ghc, ghc-pkg, ghci, and cabal). Since sandboxing is working today (with a few minor tweaks yet to be done) and it can be transparently replaced with a better solution once we have one, I think we should enable it by default in 1.18.

Since sandboxing will result in more rebuilding, we should also enabled parallel builds by default, as they typically speed up builds by a factor of 2. Finally I think we need to improve messaging. We could use:

"Installing dependencies. This may take a long time if this is the first time you build this package."

Adding sandboxing by default also makes it easier to depend on unreleased versions of packages, as it has an add-source <dir> sub-command for managing those.

This would be a big change so we should think it over carefully before we do it.

/cc @dcoutts @23Skidoo

@simonmar
Haskell member

I haven't been following the sandbox development in detail - what does cabal install foo do when using a sandbox? (where foo is a library) I ask because a common pattern when teaching is to say "cabal install foo; ghci" to get a new package installed for use in GHCi. Will this mean setting up a new sandbox?

My own preference would be to work on getting multi-instance packages in, because that solves many of the problems that sandboxes solve, and furthermore avoids multiple compilations.

@tibbe
Haskell member

Right now cabal install foo for libraries and executables both install into the sandbox. If we can convince people to use cabal build instead of cabal install when they just want to build a package in development, we could change install to mean "install into the shared package database", even when used in a sandbox.

My hope is that cabal repl will make it into the next release as well. Then you can tell your students to do cabal repl and get the best of each world; correct rebuilds from within ghci, using :r, even if preprocessors are involved and no messing up any shared package databases.

My own preference would be to work on getting multi-instance packages in, because that solves many of the problems that sandboxes solve, and furthermore avoids multiple compilations.

Me too, but it's much harder (we already spent a GSoC on it) and I rather have something than nothing. Right now that project seems stalled.

I don't feel strongly about having sandboxing be the default, but it will definitely help new users who try to install some big package, like yesod.

@simonmar
Haskell member
@23Skidoo
Haskell member

I just built Cabal and cabal-install from git, and tried cabal sandbox-init followed by cabal install on a package, and it installed in my user package DB.

Use cabal sandbox-install. The sandbox-* commands haven't been merged with their normal counterparts yet.

The sandbox commands don't seem to appear in the cabal --help output, any reason for that?

These commands are hidden for now since the UI is not final.

I think it makes sense for cabal install to install in the sandbox if there is one in the current directory, otherwise to install in the user package DB (with appropriate options to override).

Yes, this is what we intend to do. The UI design we agreed on is described here.

Johan's proposal is to make build and configure (maybe also test and bench) initialise and populate a sandbox in the current directory by default.

@23Skidoo 23Skidoo was assigned Nov 10, 2012
@gregwebs

npm installs everything to the local directory sandbox by default, and it works very well for them. The user specifies the -g flag to install a package globally. In cabal 1.20 I think that cabal install or cabal install . (when there is no existing dist folder or other signs of not using a sandbox) should create a sandbox. The question then is: what does the user need to do to not use a sandbox the first time and how do we persist that preference? It seems that we need to write to a cabal.sandbox.config file in that directory that the sandbox is disabled.

@tibbe
Haskell member

We could use a sandbox by default unless some ~/.cabal/config setting (e.g. use-sandbox-by-default) is set to False. As you say, we need a flag to override this behavior on a case-by-case basis as well.

Before we make this change we should let the current implementation bake for a bit and see how users like and use it.

@gregwebs

yeah, I was hoping that the milestone marker on this of 1.20 will give plenty of time for feedback.

@jb55

👍 this is npms default behaviour and it's definitely the way to go. Having to type sandbox init every time just seems strange when it should be doing it for me. A flag like -g on cabal install for installing globally. Simple.

@fujimura

Good change! I did few global install after sandbox was released. Opt in global install by -g sounds fine.

@23Skidoo
Haskell member

Note that as of 1.20 you can use require-sandbox to ensure that a sandbox is always used (but you will still need to run sandbox init manually).

Opt in global install by -g sounds fine.

This is called --ignore-sandbox.

@ivan-m

What happens with this if you want to install a binary for use (e.g. xmonad or pandoc)? Does that mean all the instructions everywhere need to be updated to have something like cabal install pandoc --ignore-sandbox? Will any dependencies then also get installed into the user pkg-db? What about an option to build the executable in a sandbox but then install it?

@gregwebs

for npm, one must indicate that the executable should not be installed locally: npm install -g executable. Without the global flag, it is installed local to the directory, including dependencies. This could expose a big problem with cabal that you can't install an executable that depends on a conflicting set of packages. Of course this problem already exists in a different form when installing multiple executables without a sandbox.

@mietek

Shouldn't --ignore-sandbox imply --no-require-sandbox?

@23Skidoo
Haskell member

Shouldn't --ignore-sandbox imply --no-require-sandbox?

Hmm, I thought it did. I'll look into this.

@hvr
Haskell member
hvr commented Sep 2, 2015

For the record, the original premise of this ticket has changed, i.e. the nix-style package db is becoming a reality:

http://blog.ezyang.com/2015/08/help-us-beta-test-no-reinstall-cabal/

@ezyang

Yes, I think this ticket is obsolete now. s/new-build/build/ is what we should be aiming for now.

@ezyang ezyang closed this May 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment