{"action":"created","issue":{"url":"https://api.github.com/repos/haskell/cabal/issues/2716","labels_url":"https://api.github.com/repos/haskell/cabal/issues/2716/labels{/name}","comments_url":"https://api.github.com/repos/haskell/cabal/issues/2716/comments","events_url":"https://api.github.com/repos/haskell/cabal/issues/2716/events","html_url":"https://github.com/haskell/cabal/issues/2716","id":94383426,"number":2716,"title":"Scoped packages (i.e. multiple libraries in a Cabal package)","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},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-07-10T20:16:59Z","updated_at":"2015-07-10T22:10:43Z","closed_at":null,"body":"Currently, Cabal only supports one (optional) library section in a Cabal file. Cabal currently supports compiling many components per Cabal file (libraries, test suites, executables, benchmarks), but only one of these components can be a library. I propose to remove this restriction, thus making libraries treated uniformly with other components in Cabal.\r\n\r\nThis ticket is to track the design considerations for removing it.\r\n\r\nUse-cases:\r\n\r\n1. For Backpack, we absolutely need the ability for a single Cabal file to result in the installation of multiple \"packages\" in the installed package database, because these packages are how you do modular development in Backpack. I took a detour to implement this feature, because it will serve as a good blueprint for how to make it easier for Cabal to support this use-case.\r\n\r\n2. There are many packages which have been split it a wide constellation of packages in order to make it easier for users to install useful subsets of functionality without pulling in the rest of the dependencies they don't want. However, maintaining N different Cabal files can be a bit of a pain for tightly coupled packages. With scoped packages, all of these packages could be placed in one Cabal file. (We have to make sure components get depsolved separately, but @edsko has put us most of the way there.)\r\n\r\n3. This change presents a really good opportunity to substantially simplify Cabal's handling of components. Currently, benchmarks, testsuites, executables and libraries are all separately special cased in Cabal, and anything that, e.g. mucks about the BuildInfos has to be implemented FOUR times for each of these cases. Here's a simpler model: every Cabal package has some number of components, which may be one of a few types.\r\n\r\nIt is a relatively simple matter to refactor Cabal to accept multiple library sections, since much of Cabal is already written with the assumption that there will be multiple components. Users who don't want to use scoped packages can continue to define a single library section and remain unaffected, even if the code is changed to accept multiple libraries.\r\n\r\nIf we actually want multiple libraries to be a feature users can use, the primary problem is that if a Cabal file can define multiple libraries (which live in the same namespace a package names), then both `foo.cabal` and `bar.cabal` could define the `helper`package (collision). Furthermore, from `cabal-install`'s perspective, if we need the `helper` package, it is not obvious where to look if there is no `helper.cabal`.\r\n\r\nI think the easiest and most unintrusive way to solve this is to introduce a hierarchy of scoping to package names. For the rest of this bug, I'll assume we delimit scopes with `-`. (If we don't care about compatibility with older versions of GHC, we could use something less ambiguous). The invariant is that a package named `p` can only define libraries `p` and `p-anysubname`. (We might even further imagine publishing a package named `p-anysubname`, thus allowing multiple libraries to be split up from a Cabal file). If `cabal-install` encounters a dependency on `p-subpackage`, it looks at `p.cabal` for a description of how to build it (or for `p-subpackage.cabal`). There is some ambiguity since package names today can use hyphens, but the potential massive conflicts are reduced, and `cabal-install` only has to query a few Cabal packages to see where a package is defined, as opposed to the ENTIRE package database.\r\n\r\nEach library gets its own entry in the installed package database, so from GHC's perspective, a Cabal file with multiple libraries should be equivalent to multiple Cabal files with the same library. Thus, this Cabal feature would be backwards compatible with old GHCs. We can't use a non hyphen separator because old versions of `ghc-pkg` will not accept it."},"comment":{"url":"https://api.github.com/repos/haskell/cabal/issues/comments/120539910","html_url":"https://github.com/haskell/cabal/issues/2716#issuecomment-120539910","issue_url":"https://api.github.com/repos/haskell/cabal/issues/2716","id":120539910,"user":{"login":"DanBurton","id":713692,"avatar_url":"https://avatars.githubusercontent.com/u/713692?v=3","gravatar_id":"","url":"https://api.github.com/users/DanBurton","html_url":"https://github.com/DanBurton","followers_url":"https://api.github.com/users/DanBurton/followers","following_url":"https://api.github.com/users/DanBurton/following{/other_user}","gists_url":"https://api.github.com/users/DanBurton/gists{/gist_id}","starred_url":"https://api.github.com/users/DanBurton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DanBurton/subscriptions","organizations_url":"https://api.github.com/users/DanBurton/orgs","repos_url":"https://api.github.com/users/DanBurton/repos","events_url":"https://api.github.com/users/DanBurton/events{/privacy}","received_events_url":"https://api.github.com/users/DanBurton/received_events","type":"User","site_admin":false},"created_at":"2015-07-10T22:10:43Z","updated_at":"2015-07-10T22:10:43Z","body":"> For Backpack, we absolutely need the ability for a single Cabal file to result in the installation of multiple \"packages\" in the installed package database, because these packages are how you do modular development in Backpack.\r\n\r\nCan you elaborate on why Backpack can't just use one cabal file per package?\r\n\r\n> There are many packages which have been split it a wide constellation of packages in order to make it easier for users to install useful subsets of functionality without pulling in the rest of the dependencies they don't want. However, maintaining N different Cabal files can be a bit of a pain for tightly coupled packages.\r\n\r\nAre there some concrete examples of this?\r\n\r\nIt would make more sense to me to have backpack sit as a layer on top of cabal, rather than inside of it."}}