{"action":"created","comment":{"url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/comments/73810456","id":73810456,"diff_hunk":"@@ -0,0 +1,381 @@\n+.. proposal-number:: Leave blank. This will be filled in when the proposal is\n+                     accepted.\n+\n+.. trac-ticket:: Leave blank. This will eventually be filled with the Trac\n+                 ticket number which will track the progress of the\n+                 implementation of the feature.\n+\n+.. implemented:: Leave blank. This will be filled in with the first GHC version which\n+                 implements the described feature.\n+\n+Componentized Cabal\n+===================\n+\n+This is a proposal for adding per-component configure to the Cabal Setup\n+script API.  A prototype implementation is available at\n+`#3644 <https://github.com/haskell/cabal/pull/3644>`_.\n+\n+Motivation\n+----------\n+\n+A package (e.g., ``bytestring``) consists of multiple components (e.g., a\n+library and its test suite). There are several motivations behind having\n+multiple components in a package:\n+\n+* It is convenient to not have to write a second package just to hold\n+  the test suite for a library. Part of this is historically motivated,\n+  as in the old days it was far more difficult to do development on a\n+  collection of packages than it was on a single package. But there is\n+  large amount of metadata, e.g., authorship, versioning, the package\n+  description, which would be needlessly duplicated if you needed to\n+  publish a separate package.\n+\n+* The package serves as an abstraction barrier: components internal to a\n+  package have access to APIs that package authors don't want to expose\n+  to the wider world. One common \"trick\" which is used to achieve this\n+  (e.g. as seen in cabal-install), is that a test library will literally\n+  recompile the library modules it depends on to get access to private\n+  APIs that are not otherwise available. Similarly, test suites and\n+  benchmarks are not externally useful, except as support code for a\n+  library; it makes little sense to put them into separate packages.\n+\n+* A test suite will usually have a different set of dependencies than\n+  the library proper. Assuming that you want both the library and the\n+  test suite in the same package, you need a way to specify distinct\n+  sets of dependencies for each of them, and the component is the\n+  logical distinction between the two.\n+\n+Unfortunately, components were not designed into Cabal at the beginning,\n+and thus Cabal's support for components was not so much designed as\n+evolved. But there is a basic guiding principle that components are an\n+**internal implementation detail** of a package: the ``Setup`` interface\n+configures and builds a package as a whole, and internally this may mean\n+that several components get built. Over the years we have accumulated\n+options which violate this principle (``--enable-tests``, explicit\n+arguments to ``build``, ``ComponentDeps`` in cabal-install) but the core\n+architectural principle still holds.\n+\n+In this document, I propose a **component** oriented design for Cabal,\n+where every essential operation is done on a per-component basis.\n+I am not the first to have done so: @snoyberg has previously\n+`asked for this very feature <https://github.com/haskell/cabal/issues/2802>`_.\n+The purpose of this proposal is to fully flesh out\n+the implications of the change.\n+\n+This design has multiple benefits:\n+\n+1. It permits building only specific components for packages, without\n+   needing all of the dependencies of the package as a whole to be\n+   built.  (`#1725 <https://github.com/haskell/cabal/issues/1725>`_)\n+   This is helpful, e.g., if a library also has executable components:\n+   if a downstream package only needs the library, time and space\n+   can be saved by building the library without building the components.\n+\n+2. It makes it possible for package managers like cabal-install and\n+   Stack to organize builds on a per-component basis, improving\n+   parallelism (e.g., when a package contains many independent\n+   executables) and making it easier to avoid unnecessary rebuilds when\n+   a new component is built. (`#2775 <https://github.com/haskell/cabal/issues/2775>`_)\n+\n+3. It solves the cyclic dependency problem where a test suite depends on\n+   a testing library that depends on the the library being tested. Now\n+   the test suite can be built independently from the library, after the\n+   testing library has been built.\n+\n+4. It allows for an architecturally sound implementation of Backpack, as\n+   the process of instantiating requirements of a Backpack only makes\n+   sense for libraries, rather than an entire package (an executable and\n+   test suite cannot be instantiated in any meaningful sense).\n+\n+I have divided this proposal into two parts: first the changes necessary\n+for the Cabal library (which is shared between cabal-install and Stack),\n+and then a description of how cabal-install can take advantage of this\n+new feature.  There is not a Stack portion to this proposal, but\n+commentary from the Stack team would be appreciated.\n+\n+Proposed Change: Cabal\n+----------------------\n+\n+**The status quo.** Currently, the Cabal library defines an command line\n+API via the ``./Setup configure`` command. A conventional invocation of\n+this command from, e.g., ``cabal-install``, might look like this::\n+\n+    ./Setup configure --ghc --prefix=$HOME/.cabal --user --ipid=package-name-1.0-abcdefg --dependency=array=array-0.5.1.0-abcdef1234567 --dependency=base=base-4.8.2.0-abcdef123456 --dependency=tasty=tasty-1.0-abcdef123456 --enable-tests --exact-configuration --disable-benchmarks\n+\n+There are a few important flags: ``--ipid`` specifies the *installed\n+package identity* that the package will be built under: this is\n+identifier is a unique identifier chosen by the package manager (for\n+example, ``cabal new-build`` computes this identifier by hashing all of\n+the possible inputs into the build, with the hope that the hash uniquely\n+determines all of the build products of the package), and\n+``--dependency=pkgname=ipid-1.0-abcdef`` specifies a specific dependency\n+to be used during the build of all the components.\n+``--exact-configuration`` requires ALL dependencies of all enabled\n+components to be specified explicitly.  Notice that this particular\n+command has ``--enable-tests`` passed (thus enabling the building of the\n+test suite) and specifies which version of ``tasty`` (a test library)\n+should be used. This command configures both the library and the test\n+suite of this package *simultaneously*.\n+\n+Currently, the ``configure`` command takes no positional arguments.\n+\n+**The proposal.** We extend ``configure`` to take a single argument\n+specifying which component is to be configured::\n+\n+    ./Setup configure test-suite","path":"proposals/0000-componentized-cabal.rst","position":125,"original_position":125,"commit_id":"14c2180144d626e8c383e290529b92b1208a359f","original_commit_id":"14c2180144d626e8c383e290529b92b1208a359f","user":{"login":"dcoutts","id":1339423,"avatar_url":"https://avatars.githubusercontent.com/u/1339423?v=3","gravatar_id":"","url":"https://api.github.com/users/dcoutts","html_url":"https://github.com/dcoutts","followers_url":"https://api.github.com/users/dcoutts/followers","following_url":"https://api.github.com/users/dcoutts/following{/other_user}","gists_url":"https://api.github.com/users/dcoutts/gists{/gist_id}","starred_url":"https://api.github.com/users/dcoutts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dcoutts/subscriptions","organizations_url":"https://api.github.com/users/dcoutts/orgs","repos_url":"https://api.github.com/users/dcoutts/repos","events_url":"https://api.github.com/users/dcoutts/events{/privacy}","received_events_url":"https://api.github.com/users/dcoutts/received_events","type":"User","site_admin":false},"body":"Is there any rationale for this approach rather than using a flag to indicate this new mode, like we do for `--exact-configuration`.","created_at":"2016-08-07T22:31:43Z","updated_at":"2016-08-07T22:31:43Z","html_url":"https://github.com/ghc-proposals/ghc-proposals/pull/4#discussion_r73810456","pull_request_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4","_links":{"self":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/comments/73810456"},"html":{"href":"https://github.com/ghc-proposals/ghc-proposals/pull/4#discussion_r73810456"},"pull_request":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4"}}},"pull_request":{"url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4","id":79448408,"html_url":"https://github.com/ghc-proposals/ghc-proposals/pull/4","diff_url":"https://github.com/ghc-proposals/ghc-proposals/pull/4.diff","patch_url":"https://github.com/ghc-proposals/ghc-proposals/pull/4.patch","issue_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/issues/4","number":4,"state":"open","locked":false,"title":"Componentized Cabal","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},"body":"This is a proposal for adding per-component configure to the Cabal Setup script API. (Yes, I know this is not in the GHC proposals mandate, but I couldn't resist taking it out for a spin.) Credit where credit is due: @snoyberg [suggested this first](https://github.com/haskell/cabal/issues/2802); I just worked out the details.\r\n\r\n[Rendered](https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst).","created_at":"2016-07-30T05:01:43Z","updated_at":"2016-08-07T22:31:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"88a9b9dc9b4998340ef7aa924db4acf3e4c57a55","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4/commits","review_comments_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4/comments","review_comment_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/issues/4/comments","statuses_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/statuses/14c2180144d626e8c383e290529b92b1208a359f","head":{"label":"ezyang:master","ref":"master","sha":"14c2180144d626e8c383e290529b92b1208a359f","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},"repo":{"id":64526456,"name":"ghc-proposals","full_name":"ezyang/ghc-proposals","owner":{"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},"private":false,"html_url":"https://github.com/ezyang/ghc-proposals","description":"Proposed compiler and language changes for GHC and GHC/Haskell","fork":true,"url":"https://api.github.com/repos/ezyang/ghc-proposals","forks_url":"https://api.github.com/repos/ezyang/ghc-proposals/forks","keys_url":"https://api.github.com/repos/ezyang/ghc-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ezyang/ghc-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ezyang/ghc-proposals/teams","hooks_url":"https://api.github.com/repos/ezyang/ghc-proposals/hooks","issue_events_url":"https://api.github.com/repos/ezyang/ghc-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/ezyang/ghc-proposals/events","assignees_url":"https://api.github.com/repos/ezyang/ghc-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/ezyang/ghc-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/ezyang/ghc-proposals/tags","blobs_url":"https://api.github.com/repos/ezyang/ghc-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ezyang/ghc-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ezyang/ghc-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/ezyang/ghc-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ezyang/ghc-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/ezyang/ghc-proposals/languages","stargazers_url":"https://api.github.com/repos/ezyang/ghc-proposals/stargazers","contributors_url":"https://api.github.com/repos/ezyang/ghc-proposals/contributors","subscribers_url":"https://api.github.com/repos/ezyang/ghc-proposals/subscribers","subscription_url":"https://api.github.com/repos/ezyang/ghc-proposals/subscription","commits_url":"https://api.github.com/repos/ezyang/ghc-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/ezyang/ghc-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/ezyang/ghc-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/ezyang/ghc-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/ezyang/ghc-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/ezyang/ghc-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ezyang/ghc-proposals/merges","archive_url":"https://api.github.com/repos/ezyang/ghc-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ezyang/ghc-proposals/downloads","issues_url":"https://api.github.com/repos/ezyang/ghc-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/ezyang/ghc-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/ezyang/ghc-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/ezyang/ghc-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ezyang/ghc-proposals/labels{/name}","releases_url":"https://api.github.com/repos/ezyang/ghc-proposals/releases{/id}","deployments_url":"https://api.github.com/repos/ezyang/ghc-proposals/deployments","created_at":"2016-07-30T04:39:11Z","updated_at":"2016-07-21T22:22:35Z","pushed_at":"2016-08-06T01:00:35Z","git_url":"git://github.com/ezyang/ghc-proposals.git","ssh_url":"git@github.com:ezyang/ghc-proposals.git","clone_url":"https://github.com/ezyang/ghc-proposals.git","svn_url":"https://github.com/ezyang/ghc-proposals","homepage":"http://www.haskell.org/ghc","size":89,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ghc-proposals:master","ref":"master","sha":"1504282469f69babd953b6dac284d02297933fbe","user":{"login":"ghc-proposals","id":20374637,"avatar_url":"https://avatars.githubusercontent.com/u/20374637?v=3","gravatar_id":"","url":"https://api.github.com/users/ghc-proposals","html_url":"https://github.com/ghc-proposals","followers_url":"https://api.github.com/users/ghc-proposals/followers","following_url":"https://api.github.com/users/ghc-proposals/following{/other_user}","gists_url":"https://api.github.com/users/ghc-proposals/gists{/gist_id}","starred_url":"https://api.github.com/users/ghc-proposals/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ghc-proposals/subscriptions","organizations_url":"https://api.github.com/users/ghc-proposals/orgs","repos_url":"https://api.github.com/users/ghc-proposals/repos","events_url":"https://api.github.com/users/ghc-proposals/events{/privacy}","received_events_url":"https://api.github.com/users/ghc-proposals/received_events","type":"Organization","site_admin":false},"repo":{"id":62967877,"name":"ghc-proposals","full_name":"ghc-proposals/ghc-proposals","owner":{"login":"ghc-proposals","id":20374637,"avatar_url":"https://avatars.githubusercontent.com/u/20374637?v=3","gravatar_id":"","url":"https://api.github.com/users/ghc-proposals","html_url":"https://github.com/ghc-proposals","followers_url":"https://api.github.com/users/ghc-proposals/followers","following_url":"https://api.github.com/users/ghc-proposals/following{/other_user}","gists_url":"https://api.github.com/users/ghc-proposals/gists{/gist_id}","starred_url":"https://api.github.com/users/ghc-proposals/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ghc-proposals/subscriptions","organizations_url":"https://api.github.com/users/ghc-proposals/orgs","repos_url":"https://api.github.com/users/ghc-proposals/repos","events_url":"https://api.github.com/users/ghc-proposals/events{/privacy}","received_events_url":"https://api.github.com/users/ghc-proposals/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ghc-proposals/ghc-proposals","description":"Proposed compiler and language changes for GHC and GHC/Haskell","fork":false,"url":"https://api.github.com/repos/ghc-proposals/ghc-proposals","forks_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/forks","keys_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/teams","hooks_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/hooks","issue_events_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/events","assignees_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/tags","blobs_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/languages","stargazers_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/stargazers","contributors_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/contributors","subscribers_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/subscribers","subscription_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/subscription","commits_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/merges","archive_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/downloads","issues_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/labels{/name}","releases_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/releases{/id}","deployments_url":"https://api.github.com/repos/ghc-proposals/ghc-proposals/deployments","created_at":"2016-07-09T20:28:50Z","updated_at":"2016-08-04T20:43:00Z","pushed_at":"2016-08-05T04:18:48Z","git_url":"git://github.com/ghc-proposals/ghc-proposals.git","ssh_url":"git@github.com:ghc-proposals/ghc-proposals.git","clone_url":"https://github.com/ghc-proposals/ghc-proposals.git","svn_url":"https://github.com/ghc-proposals/ghc-proposals","homepage":"http://www.haskell.org/ghc","size":60,"stargazers_count":28,"watchers_count":28,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":2,"forks":4,"open_issues":2,"watchers":28,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4"},"html":{"href":"https://github.com/ghc-proposals/ghc-proposals/pull/4"},"issue":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/issues/4"},"comments":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/issues/4/comments"},"review_comments":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4/comments"},"review_comment":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/pulls/4/commits"},"statuses":{"href":"https://api.github.com/repos/ghc-proposals/ghc-proposals/statuses/14c2180144d626e8c383e290529b92b1208a359f"}}}}
{"actor":{"display_login":"dcoutts"}}