{"action":"created","comment":{"url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/comments/32596256","id":32596256,"diff_hunk":"@@ -6,6 +6,25 @@ To install release candidates run `[sudo] gem install cocoapods --pre`\n \n ## Master\n \n+##### Highlighted Enhancement That Needs Testing\n+\n+* De-duplicate Pod Targets: CocoaPods now recognizes when a dependency is used\n+  multiple times across different user targets, but need to be built only once.\n+  The targets in Pods.xcodeproj need to be duplicated when one of the following\n+  applies:\n+  * They are used on different platforms.\n+  * They are used with differents sets of subspecs.\n+  * They have any dependency, which needs to be duplicated.\n+\n+  You can opt-out of this behavior installation-wise, by setting the following\n+  option in your ``~/.cocoapods/config.yaml`:\n+  ```yaml\n+  deduplicate_targets: false\n+  ```\n+\n+  [Marius Rackwitz](https://github.com/mrackwitz)\n+  [#3550](https://github.com/CocoaPods/CocoaPods/issues/3550)","path":"CHANGELOG.md","position":21,"original_position":21,"commit_id":"63097fd89efb14eef66e5fbd23979574580be8a3","original_commit_id":"63097fd89efb14eef66e5fbd23979574580be8a3","user":{"login":"segiddins","id":1946610,"avatar_url":"https://avatars.githubusercontent.com/u/1946610?v=3","gravatar_id":"","url":"https://api.github.com/users/segiddins","html_url":"https://github.com/segiddins","followers_url":"https://api.github.com/users/segiddins/followers","following_url":"https://api.github.com/users/segiddins/following{/other_user}","gists_url":"https://api.github.com/users/segiddins/gists{/gist_id}","starred_url":"https://api.github.com/users/segiddins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/segiddins/subscriptions","organizations_url":"https://api.github.com/users/segiddins/orgs","repos_url":"https://api.github.com/users/segiddins/repos","events_url":"https://api.github.com/users/segiddins/events{/privacy}","received_events_url":"https://api.github.com/users/segiddins/received_events","type":"User","site_admin":false},"body":"link to the issues fixed, rather than the PR.","created_at":"2015-06-17T05:29:31Z","updated_at":"2015-06-17T05:29:31Z","html_url":"https://github.com/CocoaPods/CocoaPods/pull/3550#discussion_r32596256","pull_request_url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550","_links":{"self":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/comments/32596256"},"html":{"href":"https://github.com/CocoaPods/CocoaPods/pull/3550#discussion_r32596256"},"pull_request":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550"}}},"pull_request":{"url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550","id":35092805,"html_url":"https://github.com/CocoaPods/CocoaPods/pull/3550","diff_url":"https://github.com/CocoaPods/CocoaPods/pull/3550.diff","patch_url":"https://github.com/CocoaPods/CocoaPods/pull/3550.patch","issue_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/3550","number":3550,"state":"open","locked":false,"title":"Deduplicate pod targets","user":{"login":"mrackwitz","id":1389011,"avatar_url":"https://avatars.githubusercontent.com/u/1389011?v=3","gravatar_id":"","url":"https://api.github.com/users/mrackwitz","html_url":"https://github.com/mrackwitz","followers_url":"https://api.github.com/users/mrackwitz/followers","following_url":"https://api.github.com/users/mrackwitz/following{/other_user}","gists_url":"https://api.github.com/users/mrackwitz/gists{/gist_id}","starred_url":"https://api.github.com/users/mrackwitz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrackwitz/subscriptions","organizations_url":"https://api.github.com/users/mrackwitz/orgs","repos_url":"https://api.github.com/users/mrackwitz/repos","events_url":"https://api.github.com/users/mrackwitz/events{/privacy}","received_events_url":"https://api.github.com/users/mrackwitz/received_events","type":"User","site_admin":false},"body":"This de-duplicates pod targets in the analyzer, if they share the same subspec set and target the same platform. If there is any dependency from at least one target definition, which doesn't fulfill this condition, then all dependencies with this root spec will be scoped.\r\nThis should fix diverse issues related to archiving with Xcode, especially when extensions are integrated. Beside that it will reduce build times, drastically.\r\nA new configuration key was added (38ec3cd), which allows to opt-out of the feature, because these changes cause massive changes to the existing integration and are likely to break edge-case setups.\r\n\r\n#### Open Todos:\r\n\r\nThe following things are still open to do:\r\n\r\n* [x] A `PodTarget` can't be deduplicated if any of its transitive dependencies can't be deduplicated.\r\n* [x] Validate that `PodTarget`s are only initialized legitimate: They can't be scoped when they have more then one target definition.\r\n* [x] Add missing unit tests\r\n* [x] _Decide whether to_ add integration tests with the old behavior\r\n* [x] Tests & experience with real-life projects\r\n* [x] Add a CHANGELOG entry\r\n\r\n#### Dependencies:\r\n\r\nThis depends on the following PRs:\r\n\r\n* [ ] CocoaPods/cocoapods-integration-specs#36\r\n\r\n#### Changes to the Integration\r\n\r\n##### Deduplication / Descoping of PodTargets\r\n\r\nThis de-duplicates pod targets in the analyzer, if they share the same subspec set and target the same platform. If there is any dependency from at least one target definition, which doesn't fulfill this condition, then all dependencies with this root spec will be scoped.\r\nA deduplicated pod target will be fully descoped, which means the prefix of all names is skipped and with frameworks, it builds in the `CONTENTS_FOLDER_PATH` as usual given by Xcode, without the introduced level of further scoping to avoid conflicts, which can't happen that way.\r\nConcrete this means the following: If you used to integrate with the following Podfile:\r\n```ruby\r\nuse_frameworks!\r\nplatform :ios, \"8.1\"\r\npod \"Alamofire\"\r\npod \"Stargate\"\r\npod \"MRProgress/Circular\"\r\n\r\ntarget \"ExampleCLI\" do\r\n  platform :osx, \"10.10\"\r\n  pod \"Alamofire\"\r\nend\r\n\r\ntarget \"ExampleWatchExtension\" do\r\n  pod \"Stargate\"\r\nend\r\n\r\ntarget \"ExampleWidget\" do\r\n  pod \"Alamofire\"\r\n  pod \"MRProgress/ActivityIndicator\"\r\n  pod \"MRProgress/Circular\"\r\nend\r\n```\r\n\r\nYou would end up with an integration, which looks like:\r\n* `Pods-Alamofire`\r\n* `Pods-Stargate`\r\n* `Pods-MRProgress`\r\n* `Pods-ExampleCLI-Alamofire`\r\n* `Pods-ExampleWatchExtension-Stargate`\r\n* `Pods-ExampleWidget-Alamofire`\r\n* `Pods-ExampleWidget-MRProgress`\r\n\r\nNow you should end up with:\r\n* `Pods-Alamofire`\r\n* `Stargate` :tada:\r\n* `Pods-MRProgress`\r\n* `Pods-ExampleCLI-Alamofire`\r\n* ~~`Pods-ExampleWatchExtension-Stargate`~~ :tada:\r\n* `Pods-ExampleWidget-Alamofire`\r\n* `Pods-ExampleWidget-MRProgress`\r\n\r\nAs you can see subspecs and different platforms prevent the deduplication, even when there is a subset of target definitions where the deduplication could been applied as seen for `Alamofire` in the example above.\r\n\r\n##### Environment Header\r\n\r\nAll `PodTarget`s from the same `AggregateTarget` used to share an environment header. This won't be possible anymore for deduplicated pod targets. As the environment header defines precompiler macros to indicate the version for each integrated dependency in the same target definition, altering anything around this can cause unexpected failures when pods have implicit dependencies or offer additional behavior when used along other pods. This PR for now replaces the shared environment header with a dedicated environment header, which in the best case should only have information about all explicit dependencies of the given podspec. Another variant would be that it has additional access to the intersection of all dependencies of all target definitions it belongs to.\r\n\r\n#### Highlighted Architecture Changes\r\n\r\n* Pull down relation `target_definition` from `Target` into `AggregateTarget` and all getters, which depend on this and are only needed for the subclass.\r\n* Pluralize prior singular inherited relation from `PodTarget` to `TargetDefinition`, now known as `PodTarget#target_definitions`\r\n* Add a flag attribute `scoped` to `PodTarget` to indicate them explicitly as scoped, which is only possible if there is only one related `TargetDefinition`\r\n* Extract `TargetInspector` and `TargetInspectionResult` out of `Analyzer`\r\n","created_at":"2015-05-11T01:35:58Z","updated_at":"2015-06-17T05:29:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0c7ccee1aa1ce96e1f9dc95cc236ca5c614f86a0","assignee":null,"milestone":{"url":"https://api.github.com/repos/CocoaPods/CocoaPods/milestones/26","html_url":"https://github.com/CocoaPods/CocoaPods/milestones/0.38","labels_url":"https://api.github.com/repos/CocoaPods/CocoaPods/milestones/26/labels","id":1140527,"number":26,"title":"0.38","description":null,"creator":{"login":"segiddins","id":1946610,"avatar_url":"https://avatars.githubusercontent.com/u/1946610?v=3","gravatar_id":"","url":"https://api.github.com/users/segiddins","html_url":"https://github.com/segiddins","followers_url":"https://api.github.com/users/segiddins/followers","following_url":"https://api.github.com/users/segiddins/following{/other_user}","gists_url":"https://api.github.com/users/segiddins/gists{/gist_id}","starred_url":"https://api.github.com/users/segiddins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/segiddins/subscriptions","organizations_url":"https://api.github.com/users/segiddins/orgs","repos_url":"https://api.github.com/users/segiddins/repos","events_url":"https://api.github.com/users/segiddins/events{/privacy}","received_events_url":"https://api.github.com/users/segiddins/received_events","type":"User","site_admin":false},"open_issues":4,"closed_issues":5,"state":"open","created_at":"2015-05-29T18:35:21Z","updated_at":"2015-06-03T19:52:03Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550/commits","review_comments_url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550/comments","review_comment_url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/3550/comments","statuses_url":"https://api.github.com/repos/CocoaPods/CocoaPods/statuses/63097fd89efb14eef66e5fbd23979574580be8a3","head":{"label":"CocoaPods:mr-deduplicate-frameworks","ref":"mr-deduplicate-frameworks","sha":"63097fd89efb14eef66e5fbd23979574580be8a3","user":{"login":"CocoaPods","id":1189714,"avatar_url":"https://avatars.githubusercontent.com/u/1189714?v=3","gravatar_id":"","url":"https://api.github.com/users/CocoaPods","html_url":"https://github.com/CocoaPods","followers_url":"https://api.github.com/users/CocoaPods/followers","following_url":"https://api.github.com/users/CocoaPods/following{/other_user}","gists_url":"https://api.github.com/users/CocoaPods/gists{/gist_id}","starred_url":"https://api.github.com/users/CocoaPods/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CocoaPods/subscriptions","organizations_url":"https://api.github.com/users/CocoaPods/orgs","repos_url":"https://api.github.com/users/CocoaPods/repos","events_url":"https://api.github.com/users/CocoaPods/events{/privacy}","received_events_url":"https://api.github.com/users/CocoaPods/received_events","type":"Organization","site_admin":false},"repo":{"id":2203645,"name":"CocoaPods","full_name":"CocoaPods/CocoaPods","owner":{"login":"CocoaPods","id":1189714,"avatar_url":"https://avatars.githubusercontent.com/u/1189714?v=3","gravatar_id":"","url":"https://api.github.com/users/CocoaPods","html_url":"https://github.com/CocoaPods","followers_url":"https://api.github.com/users/CocoaPods/followers","following_url":"https://api.github.com/users/CocoaPods/following{/other_user}","gists_url":"https://api.github.com/users/CocoaPods/gists{/gist_id}","starred_url":"https://api.github.com/users/CocoaPods/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CocoaPods/subscriptions","organizations_url":"https://api.github.com/users/CocoaPods/orgs","repos_url":"https://api.github.com/users/CocoaPods/repos","events_url":"https://api.github.com/users/CocoaPods/events{/privacy}","received_events_url":"https://api.github.com/users/CocoaPods/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CocoaPods/CocoaPods","description":"The Cocoa Dependency Manager.","fork":false,"url":"https://api.github.com/repos/CocoaPods/CocoaPods","forks_url":"https://api.github.com/repos/CocoaPods/CocoaPods/forks","keys_url":"https://api.github.com/repos/CocoaPods/CocoaPods/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CocoaPods/CocoaPods/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CocoaPods/CocoaPods/teams","hooks_url":"https://api.github.com/repos/CocoaPods/CocoaPods/hooks","issue_events_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/events{/number}","events_url":"https://api.github.com/repos/CocoaPods/CocoaPods/events","assignees_url":"https://api.github.com/repos/CocoaPods/CocoaPods/assignees{/user}","branches_url":"https://api.github.com/repos/CocoaPods/CocoaPods/branches{/branch}","tags_url":"https://api.github.com/repos/CocoaPods/CocoaPods/tags","blobs_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/refs{/sha}","trees_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CocoaPods/CocoaPods/statuses/{sha}","languages_url":"https://api.github.com/repos/CocoaPods/CocoaPods/languages","stargazers_url":"https://api.github.com/repos/CocoaPods/CocoaPods/stargazers","contributors_url":"https://api.github.com/repos/CocoaPods/CocoaPods/contributors","subscribers_url":"https://api.github.com/repos/CocoaPods/CocoaPods/subscribers","subscription_url":"https://api.github.com/repos/CocoaPods/CocoaPods/subscription","commits_url":"https://api.github.com/repos/CocoaPods/CocoaPods/commits{/sha}","git_commits_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/commits{/sha}","comments_url":"https://api.github.com/repos/CocoaPods/CocoaPods/comments{/number}","issue_comment_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/comments{/number}","contents_url":"https://api.github.com/repos/CocoaPods/CocoaPods/contents/{+path}","compare_url":"https://api.github.com/repos/CocoaPods/CocoaPods/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CocoaPods/CocoaPods/merges","archive_url":"https://api.github.com/repos/CocoaPods/CocoaPods/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CocoaPods/CocoaPods/downloads","issues_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues{/number}","pulls_url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls{/number}","milestones_url":"https://api.github.com/repos/CocoaPods/CocoaPods/milestones{/number}","notifications_url":"https://api.github.com/repos/CocoaPods/CocoaPods/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CocoaPods/CocoaPods/labels{/name}","releases_url":"https://api.github.com/repos/CocoaPods/CocoaPods/releases{/id}","created_at":"2011-08-14T00:10:53Z","updated_at":"2015-06-17T05:27:14Z","pushed_at":"2015-06-17T01:57:19Z","git_url":"git://github.com/CocoaPods/CocoaPods.git","ssh_url":"git@github.com:CocoaPods/CocoaPods.git","clone_url":"https://github.com/CocoaPods/CocoaPods.git","svn_url":"https://github.com/CocoaPods/CocoaPods","homepage":"cocoapods.org","size":65887,"stargazers_count":5813,"watchers_count":5813,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1043,"mirror_url":null,"open_issues_count":225,"forks":1043,"open_issues":225,"watchers":5813,"default_branch":"master"}},"base":{"label":"CocoaPods:master","ref":"master","sha":"67d5c5901fe5845ca7634f11317e53297842583f","user":{"login":"CocoaPods","id":1189714,"avatar_url":"https://avatars.githubusercontent.com/u/1189714?v=3","gravatar_id":"","url":"https://api.github.com/users/CocoaPods","html_url":"https://github.com/CocoaPods","followers_url":"https://api.github.com/users/CocoaPods/followers","following_url":"https://api.github.com/users/CocoaPods/following{/other_user}","gists_url":"https://api.github.com/users/CocoaPods/gists{/gist_id}","starred_url":"https://api.github.com/users/CocoaPods/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CocoaPods/subscriptions","organizations_url":"https://api.github.com/users/CocoaPods/orgs","repos_url":"https://api.github.com/users/CocoaPods/repos","events_url":"https://api.github.com/users/CocoaPods/events{/privacy}","received_events_url":"https://api.github.com/users/CocoaPods/received_events","type":"Organization","site_admin":false},"repo":{"id":2203645,"name":"CocoaPods","full_name":"CocoaPods/CocoaPods","owner":{"login":"CocoaPods","id":1189714,"avatar_url":"https://avatars.githubusercontent.com/u/1189714?v=3","gravatar_id":"","url":"https://api.github.com/users/CocoaPods","html_url":"https://github.com/CocoaPods","followers_url":"https://api.github.com/users/CocoaPods/followers","following_url":"https://api.github.com/users/CocoaPods/following{/other_user}","gists_url":"https://api.github.com/users/CocoaPods/gists{/gist_id}","starred_url":"https://api.github.com/users/CocoaPods/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CocoaPods/subscriptions","organizations_url":"https://api.github.com/users/CocoaPods/orgs","repos_url":"https://api.github.com/users/CocoaPods/repos","events_url":"https://api.github.com/users/CocoaPods/events{/privacy}","received_events_url":"https://api.github.com/users/CocoaPods/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CocoaPods/CocoaPods","description":"The Cocoa Dependency Manager.","fork":false,"url":"https://api.github.com/repos/CocoaPods/CocoaPods","forks_url":"https://api.github.com/repos/CocoaPods/CocoaPods/forks","keys_url":"https://api.github.com/repos/CocoaPods/CocoaPods/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CocoaPods/CocoaPods/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CocoaPods/CocoaPods/teams","hooks_url":"https://api.github.com/repos/CocoaPods/CocoaPods/hooks","issue_events_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/events{/number}","events_url":"https://api.github.com/repos/CocoaPods/CocoaPods/events","assignees_url":"https://api.github.com/repos/CocoaPods/CocoaPods/assignees{/user}","branches_url":"https://api.github.com/repos/CocoaPods/CocoaPods/branches{/branch}","tags_url":"https://api.github.com/repos/CocoaPods/CocoaPods/tags","blobs_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/refs{/sha}","trees_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CocoaPods/CocoaPods/statuses/{sha}","languages_url":"https://api.github.com/repos/CocoaPods/CocoaPods/languages","stargazers_url":"https://api.github.com/repos/CocoaPods/CocoaPods/stargazers","contributors_url":"https://api.github.com/repos/CocoaPods/CocoaPods/contributors","subscribers_url":"https://api.github.com/repos/CocoaPods/CocoaPods/subscribers","subscription_url":"https://api.github.com/repos/CocoaPods/CocoaPods/subscription","commits_url":"https://api.github.com/repos/CocoaPods/CocoaPods/commits{/sha}","git_commits_url":"https://api.github.com/repos/CocoaPods/CocoaPods/git/commits{/sha}","comments_url":"https://api.github.com/repos/CocoaPods/CocoaPods/comments{/number}","issue_comment_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/comments{/number}","contents_url":"https://api.github.com/repos/CocoaPods/CocoaPods/contents/{+path}","compare_url":"https://api.github.com/repos/CocoaPods/CocoaPods/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CocoaPods/CocoaPods/merges","archive_url":"https://api.github.com/repos/CocoaPods/CocoaPods/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CocoaPods/CocoaPods/downloads","issues_url":"https://api.github.com/repos/CocoaPods/CocoaPods/issues{/number}","pulls_url":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls{/number}","milestones_url":"https://api.github.com/repos/CocoaPods/CocoaPods/milestones{/number}","notifications_url":"https://api.github.com/repos/CocoaPods/CocoaPods/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CocoaPods/CocoaPods/labels{/name}","releases_url":"https://api.github.com/repos/CocoaPods/CocoaPods/releases{/id}","created_at":"2011-08-14T00:10:53Z","updated_at":"2015-06-17T05:27:14Z","pushed_at":"2015-06-17T01:57:19Z","git_url":"git://github.com/CocoaPods/CocoaPods.git","ssh_url":"git@github.com:CocoaPods/CocoaPods.git","clone_url":"https://github.com/CocoaPods/CocoaPods.git","svn_url":"https://github.com/CocoaPods/CocoaPods","homepage":"cocoapods.org","size":65887,"stargazers_count":5813,"watchers_count":5813,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1043,"mirror_url":null,"open_issues_count":225,"forks":1043,"open_issues":225,"watchers":5813,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550"},"html":{"href":"https://github.com/CocoaPods/CocoaPods/pull/3550"},"issue":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/3550"},"comments":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/issues/3550/comments"},"review_comments":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550/comments"},"review_comment":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/pulls/3550/commits"},"statuses":{"href":"https://api.github.com/repos/CocoaPods/CocoaPods/statuses/63097fd89efb14eef66e5fbd23979574580be8a3"}}}}