{"action":"created","issue":{"url":"https://api.github.com/repos/haskell/cabal/issues/2365","labels_url":"https://api.github.com/repos/haskell/cabal/issues/2365/labels{/name}","comments_url":"https://api.github.com/repos/haskell/cabal/issues/2365/comments","events_url":"https://api.github.com/repos/haskell/cabal/issues/2365/events","html_url":"https://github.com/haskell/cabal/issues/2365","id":54468234,"number":2365,"title":"Faster cabal builds by caching the build directory","user":{"login":"nh2","id":399535,"avatar_url":"https://avatars.githubusercontent.com/u/399535?v=3","gravatar_id":"","url":"https://api.github.com/users/nh2","html_url":"https://github.com/nh2","followers_url":"https://api.github.com/users/nh2/followers","following_url":"https://api.github.com/users/nh2/following{/other_user}","gists_url":"https://api.github.com/users/nh2/gists{/gist_id}","starred_url":"https://api.github.com/users/nh2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nh2/subscriptions","organizations_url":"https://api.github.com/users/nh2/orgs","repos_url":"https://api.github.com/users/nh2/repos","events_url":"https://api.github.com/users/nh2/events{/privacy}","received_events_url":"https://api.github.com/users/nh2/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/haskell/cabal/labels/enhancement","name":"enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/haskell/cabal/milestones/29","html_url":"https://github.com/haskell/cabal/milestones/cabal-install-1.24","labels_url":"https://api.github.com/repos/haskell/cabal/milestones/29/labels","id":929438,"number":29,"title":"cabal-install-1.24","description":"","creator":{"login":"tibbe","id":17277,"avatar_url":"https://avatars.githubusercontent.com/u/17277?v=3","gravatar_id":"","url":"https://api.github.com/users/tibbe","html_url":"https://github.com/tibbe","followers_url":"https://api.github.com/users/tibbe/followers","following_url":"https://api.github.com/users/tibbe/following{/other_user}","gists_url":"https://api.github.com/users/tibbe/gists{/gist_id}","starred_url":"https://api.github.com/users/tibbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tibbe/subscriptions","organizations_url":"https://api.github.com/users/tibbe/orgs","repos_url":"https://api.github.com/users/tibbe/repos","events_url":"https://api.github.com/users/tibbe/events{/privacy}","received_events_url":"https://api.github.com/users/tibbe/received_events","type":"User","site_admin":false},"open_issues":137,"closed_issues":21,"state":"open","created_at":"2015-01-09T23:38:12Z","updated_at":"2015-12-24T20:24:38Z","due_on":"2016-01-30T23:00:00Z","closed_at":null},"comments":4,"created_at":"2015-01-15T16:16:04Z","updated_at":"2015-12-25T05:30:48Z","closed_at":null,"body":"Imported from [reddit](http://www.reddit.com/r/haskell/comments/2s8bk7/faster_cabal_builds_by_caching_the_build_directory/):\r\n\r\nI got annoyed that every time I build something in a new cabal sandbox I have to wait for the same versions of `lens` or `haskell-src-exts` to compile forever.\r\n\r\nCouldn't we just cache the build directory from which we installed a package instead of throwing it away after every build?\r\n\r\nCabal tries to guarantee that running `cabal install` in a source directory always produces the correct result without us having to run `cabal clean` first (so no matter what the state of the `dist/` directory is). Cabal does this by using `ghc --make` for building, which has very good recompilation avoidance and flag change detection.\r\n\r\nThis means that this kind of cache introduces no additional correctness guarantees we would have to provide, it is only relying on guarantees that cabal already tries to provide.\r\n\r\nThe cache does take some space in my home directory, but I accept that for the 20x faster build it allows.\r\n\r\nFor example, a no-op rebuild of for `haskell-src-exts` is 7 seconds on my computer vs. a full build that takes 132 seconds.\r\n\r\nThis method *will* pick up changed dependencies (e.g. it will build correctly when the version of `haskell-src-exts`'s dependency `pretty` changes between two builds) because `ghc --make` notices that.\r\n\r\nThis method will also provide for cases where other approaches cannot. For example, as [mentioned here](http://www.reddit.com/r/haskell/comments/2s8bk7/faster_cabal_builds_by_caching_the_build_directory/cnob1s2) and [here](http://www.reddit.com/r/haskell/comments/2s8bk7/faster_cabal_builds_by_caching_the_build_directory/cnnpepm), it can cache more than a nix-like approach can: With nix caching ends completely at the first dependency that has changed, while `ghc --make` caches on the module level, recompiling only those modules that depend on changed code, not packages. Nevertheless, the biggest speedup to be expected is for CI systems like TravisCI, CircleCI etc., and sandboxes, as those compile share huge parts of the dependency graph where all code is exactly the same.\r\n\r\nHere's a proof of concept patch: https://github.com/nh2/cabal/compare/nh2:before-buildcache...buildcache\r\n\r\nWhat do you think?\r\n\r\n---\r\n\r\nSome things we would need:\r\n\r\n* Are you aware of any recent or past cabal bugs mentioning that `cabal clean` was necessary in order to build correctly?\r\n* Also I think that if we want to try this out, the best might be to hide it behind a `cabal install --cached` option defaulting to False, and if it works out well, make it the default at some point in the future. Do you agree?"},"comment":{"url":"https://api.github.com/repos/haskell/cabal/issues/comments/167194761","html_url":"https://github.com/haskell/cabal/issues/2365#issuecomment-167194761","issue_url":"https://api.github.com/repos/haskell/cabal/issues/2365","id":167194761,"user":{"login":"ezyang","id":13564,"avatar_url":"https://avatars.githubusercontent.com/u/13564?v=3","gravatar_id":"","url":"https://api.github.com/users/ezyang","html_url":"https://github.com/ezyang","followers_url":"https://api.github.com/users/ezyang/followers","following_url":"https://api.github.com/users/ezyang/following{/other_user}","gists_url":"https://api.github.com/users/ezyang/gists{/gist_id}","starred_url":"https://api.github.com/users/ezyang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ezyang/subscriptions","organizations_url":"https://api.github.com/users/ezyang/orgs","repos_url":"https://api.github.com/users/ezyang/repos","events_url":"https://api.github.com/users/ezyang/events{/privacy}","received_events_url":"https://api.github.com/users/ezyang/received_events","type":"User","site_admin":false},"created_at":"2015-12-25T05:30:48Z","updated_at":"2015-12-25T05:30:48Z","body":"This should be fixed by the nix-local-build branch, which introduces \"projects\" which have a shared (monotonically growing) global database and a per-project database for local sources / vendored things."}}