cocoapods 0.35.0 → 0.36.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +185 -6
  3. data/README.md +1 -1
  4. data/lib/cocoapods.rb +4 -0
  5. data/lib/cocoapods/command.rb +2 -2
  6. data/lib/cocoapods/command/inter_process_communication.rb +1 -1
  7. data/lib/cocoapods/command/lib.rb +3 -0
  8. data/lib/cocoapods/command/list.rb +0 -35
  9. data/lib/cocoapods/command/search.rb +1 -2
  10. data/lib/cocoapods/command/spec.rb +6 -3
  11. data/lib/cocoapods/config.rb +1 -20
  12. data/lib/cocoapods/external_sources/abstract_external_source.rb +4 -0
  13. data/lib/cocoapods/gem_version.rb +1 -1
  14. data/lib/cocoapods/generator/embed_frameworks_script.rb +107 -0
  15. data/lib/cocoapods/generator/header.rb +13 -1
  16. data/lib/cocoapods/generator/info_plist_file.rb +84 -0
  17. data/lib/cocoapods/generator/module_map.rb +49 -0
  18. data/lib/cocoapods/generator/umbrella_header.rb +44 -0
  19. data/lib/cocoapods/generator/xcconfig/aggregate_xcconfig.rb +69 -23
  20. data/lib/cocoapods/generator/xcconfig/private_pod_xcconfig.rb +12 -0
  21. data/lib/cocoapods/generator/xcconfig/public_pod_xcconfig.rb +1 -9
  22. data/lib/cocoapods/generator/xcconfig/xcconfig_helper.rb +79 -1
  23. data/lib/cocoapods/hooks_manager.rb +75 -13
  24. data/lib/cocoapods/installer.rb +59 -2
  25. data/lib/cocoapods/installer/analyzer.rb +115 -38
  26. data/lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb +6 -1
  27. data/lib/cocoapods/installer/file_references_installer.rb +11 -5
  28. data/lib/cocoapods/installer/migrator.rb +9 -0
  29. data/lib/cocoapods/installer/target_installer.rb +89 -5
  30. data/lib/cocoapods/installer/target_installer/aggregate_target_installer.rb +49 -5
  31. data/lib/cocoapods/installer/target_installer/pod_target_installer.rb +57 -9
  32. data/lib/cocoapods/installer/user_project_integrator.rb +3 -2
  33. data/lib/cocoapods/installer/user_project_integrator/target_integrator.rb +67 -6
  34. data/lib/cocoapods/project.rb +18 -2
  35. data/lib/cocoapods/resolver.rb +2 -2
  36. data/lib/cocoapods/sandbox/file_accessor.rb +23 -3
  37. data/lib/cocoapods/sandbox/headers_store.rb +4 -0
  38. data/lib/cocoapods/sources_manager.rb +5 -1
  39. data/lib/cocoapods/target.rb +117 -1
  40. data/lib/cocoapods/target/aggregate_target.rb +46 -4
  41. data/lib/cocoapods/target/pod_target.rb +39 -1
  42. data/lib/cocoapods/user_interface.rb +16 -21
  43. data/lib/cocoapods/user_interface/error_report.rb +2 -2
  44. data/lib/cocoapods/validator.rb +68 -23
  45. metadata +23 -19
@@ -0,0 +1,49 @@
1
+ module Pod
2
+ module Generator
3
+ # Generates LLVM module map files. A module map file is generated for each
4
+ # Pod and for each Pod target definition that is built as a framework. It
5
+ # specifies a different umbrella header than usual to avoid name conflicts
6
+ # with existing headers of the podspec.
7
+ #
8
+ class ModuleMap
9
+ # @return [Target] the target represented by this Info.plist.
10
+ #
11
+ attr_reader :target
12
+
13
+ # @param [Target] target @see target
14
+ #
15
+ def initialize(target)
16
+ @target = target
17
+ end
18
+
19
+ # Generates and saves the Info.plist to the given path.
20
+ #
21
+ # @param [Pathname] path
22
+ # the path where the prefix header should be stored.
23
+ #
24
+ # @return [void]
25
+ #
26
+ def save_as(path)
27
+ contents = generate
28
+ path.open('w') do |f|
29
+ f.write(contents)
30
+ end
31
+ end
32
+
33
+ # Generates the contents of the module.modulemap file.
34
+ #
35
+ # @return [String]
36
+ #
37
+ def generate
38
+ <<-eos.strip_heredoc
39
+ framework module #{target.product_module_name} {
40
+ umbrella header "#{target.umbrella_header_path.basename}"
41
+
42
+ export *
43
+ module * { export * }
44
+ }
45
+ eos
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,44 @@
1
+ module Pod
2
+ module Generator
3
+ # Generates an umbrella header file for clang modules, which are used by
4
+ # dynamic frameworks on iOS 8 and OSX 10.10 under the hood.
5
+ #
6
+ # If the target is a +PodTarget+, then the umbrella header is required
7
+ # to make all public headers in a convenient manner available without the
8
+ # need to write out header declarations for every library header.
9
+ #
10
+ class UmbrellaHeader < Header
11
+ # @return [Target]
12
+ # the target, which provides the product name
13
+ attr_reader :target
14
+
15
+ # @param [Target] target
16
+ # @see target
17
+ #
18
+ def initialize(target)
19
+ super(target.target_definition.platform)
20
+ @target = target
21
+ end
22
+
23
+ # Generates the contents of the umbrella header according to the included
24
+ # pods.
25
+ #
26
+ # @return [String]
27
+ #
28
+ def generate
29
+ result = super
30
+
31
+ result << "\n"
32
+
33
+ result << <<-eos.strip_heredoc
34
+ FOUNDATION_EXPORT double #{target.product_module_name}VersionNumber;
35
+ FOUNDATION_EXPORT const unsigned char #{target.product_module_name}VersionString[];
36
+ eos
37
+
38
+ result << "\n"
39
+
40
+ result
41
+ end
42
+ end
43
+ end
44
+ end
@@ -47,33 +47,58 @@ module Pod
47
47
  # @return [Xcodeproj::Config]
48
48
  #
49
49
  def generate
50
- header_search_path_flags = target.sandbox.public_headers.search_paths(target.platform)
51
- @xcconfig = Xcodeproj::Config.new(
52
- 'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
53
- 'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)',
54
- 'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_path_flags),
55
- 'PODS_ROOT' => target.relative_pods_root,
56
- 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
57
- 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_path_flags, '-isystem')
58
- )
50
+ pod_targets = target.pod_targets_for_build_configuration(@configuration_name)
51
+ config = {
52
+ 'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
53
+ 'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)',
54
+ 'PODS_ROOT' => target.relative_pods_root,
55
+ 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
56
+ }
59
57
 
60
- target.pod_targets.each do |pod_target|
61
- next unless pod_target.include_in_build_config?(@configuration_name)
58
+ if target.requires_frameworks?
59
+ # Framework headers are automatically discoverable by `#import <…>`.
60
+ header_search_paths = pod_targets.map { |target| "$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers" }
61
+ build_settings = {
62
+ 'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
63
+ 'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
64
+ # Make headers discoverable by `import "…"`
65
+ 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-iquote')
66
+ }
67
+ config.merge!(build_settings)
68
+ else
69
+ # Make headers discoverable from $PODS_ROOT/Headers directory
70
+ header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
71
+ build_settings = {
72
+ # by `#import "…"`
73
+ 'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_paths),
74
+ # by `#import <…>`
75
+ 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem')
76
+ }
77
+ config.merge!(build_settings)
78
+ end
62
79
 
63
- pod_target.file_accessors.each do |file_accessor|
64
- XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, @xcconfig)
65
- file_accessor.vendored_frameworks.each do |vendored_framework|
66
- XCConfigHelper.add_framework_build_settings(vendored_framework, @xcconfig, target.sandbox.root)
67
- end
68
- file_accessor.vendored_libraries.each do |vendored_library|
69
- XCConfigHelper.add_library_build_settings(vendored_library, @xcconfig, target.sandbox.root)
70
- end
71
- end
80
+ @xcconfig = Xcodeproj::Config.new(config)
72
81
 
73
- # Add pod static lib to list of libraries that are to be linked with
74
- # the user’s project.
82
+ XCConfigHelper.add_target_specific_settings(target, @xcconfig)
75
83
 
76
- @xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.name}"))
84
+ pod_targets.each do |pod_target|
85
+ unless pod_target.should_build? && pod_target.requires_frameworks?
86
+ # In case of generated pod targets, which require frameworks, the
87
+ # vendored frameworks and libraries are already linked statically
88
+ # into the framework binary and must not be linked again to the
89
+ # user target.
90
+ XCConfigHelper.add_settings_for_file_accessors_of_target(pod_target, @xcconfig)
91
+ end
92
+
93
+ # Add pod target to list of frameworks / libraries that are
94
+ # linked with the user’s project.
95
+ if pod_target.should_build?
96
+ if pod_target.requires_frameworks?
97
+ @xcconfig.merge!('OTHER_LDFLAGS' => %(-framework "#{pod_target.product_basename}"))
98
+ else
99
+ @xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.product_basename}"))
100
+ end
101
+ end
77
102
  end
78
103
 
79
104
  # TODO Need to decide how we are going to ensure settings like these
@@ -82,9 +107,30 @@ module Pod
82
107
  # See https://github.com/CocoaPods/CocoaPods/issues/1216
83
108
  @xcconfig.attributes.delete('USE_HEADERMAP')
84
109
 
110
+ generate_ld_runpath_search_paths if target.requires_frameworks?
111
+
85
112
  @xcconfig
86
113
  end
87
114
 
115
+ def generate_ld_runpath_search_paths
116
+ ld_runpath_search_paths = ['$(inherited)']
117
+ if target.platform.symbolic_name == :osx
118
+ ld_runpath_search_paths << "'@executable_path/../Frameworks'"
119
+ ld_runpath_search_paths << \
120
+ if target.native_target.symbol_type == :unit_test_bundle
121
+ "'@loader_path/../Frameworks'"
122
+ else
123
+ "'@loader_path/Frameworks'"
124
+ end
125
+ else
126
+ ld_runpath_search_paths << [
127
+ "'@executable_path/Frameworks'",
128
+ "'@loader_path/Frameworks'"
129
+ ]
130
+ end
131
+ @xcconfig.merge!('LD_RUNPATH_SEARCH_PATHS' => ld_runpath_search_paths.join(' '))
132
+ end
133
+
88
134
  #---------------------------------------------------------------------#
89
135
  end
90
136
  end
@@ -57,8 +57,20 @@ module Pod
57
57
  # 'USE_HEADERMAP' => 'NO'
58
58
  }
59
59
 
60
+ if target.requires_frameworks?
61
+ # Only quote the FRAMEWORK_SEARCH_PATHS entry, because it’s a setting that takes multiple values.
62
+ # In addition, quoting CONFIGURATION_BUILD_DIR would make it be interpreted as a relative path.
63
+ build_settings = {
64
+ 'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
65
+ 'CONFIGURATION_BUILD_DIR' => '$PODS_FRAMEWORK_BUILD_PATH',
66
+ 'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
67
+ }
68
+ config.merge!(build_settings)
69
+ end
70
+
60
71
  xcconfig_hash = add_xcconfig_namespaced_keys(public_xcconfig.to_hash, config, target.xcconfig_prefix)
61
72
  @xcconfig = Xcodeproj::Config.new(xcconfig_hash)
73
+ XCConfigHelper.add_target_specific_settings(target, @xcconfig)
62
74
  @xcconfig.includes = [target.name]
63
75
  @xcconfig
64
76
  end
@@ -40,15 +40,7 @@ module Pod
40
40
  #
41
41
  def generate
42
42
  @xcconfig = Xcodeproj::Config.new
43
- target.file_accessors.each do |file_accessor|
44
- XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, @xcconfig)
45
- file_accessor.vendored_frameworks.each do |vendored_framework|
46
- XCConfigHelper.add_framework_build_settings(vendored_framework, @xcconfig, target.sandbox.root)
47
- end
48
- file_accessor.vendored_libraries.each do |vendored_library|
49
- XCConfigHelper.add_library_build_settings(vendored_library, @xcconfig, target.sandbox.root)
50
- end
51
- end
43
+ XCConfigHelper.add_settings_for_file_accessors_of_target(target, @xcconfig)
52
44
  @xcconfig
53
45
  end
54
46
 
@@ -33,6 +33,26 @@ module Pod
33
33
  ld_flags
34
34
  end
35
35
 
36
+ # Configures the given Xcconfig
37
+ #
38
+ # @param [PodTarget] pod_target
39
+ # The pod target, which holds the list of +Spec::FileAccessor+.
40
+ #
41
+ # @param [Xcodeproj::Config] xcconfig
42
+ # The xcconfig to edit.
43
+ #
44
+ def self.add_settings_for_file_accessors_of_target(target, xcconfig)
45
+ target.file_accessors.each do |file_accessor|
46
+ XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, xcconfig)
47
+ file_accessor.vendored_frameworks.each do |vendored_framework|
48
+ XCConfigHelper.add_framework_build_settings(vendored_framework, xcconfig, target.sandbox.root)
49
+ end
50
+ file_accessor.vendored_libraries.each do |vendored_library|
51
+ XCConfigHelper.add_library_build_settings(vendored_library, xcconfig, target.sandbox.root)
52
+ end
53
+ end
54
+ end
55
+
36
56
  # Configures the given Xcconfig according to the build settings of the
37
57
  # given Specification.
38
58
  #
@@ -59,6 +79,9 @@ module Pod
59
79
  # @param [Xcodeproj::Config] xcconfig
60
80
  # The xcconfig to edit.
61
81
  #
82
+ # @param [Pathname] sandbox_root
83
+ # The path retrieved from Sandbox#root.
84
+ #
62
85
  def self.add_framework_build_settings(framework_path, xcconfig, sandbox_root)
63
86
  name = File.basename(framework_path, '.framework')
64
87
  dirname = '$(PODS_ROOT)/' + framework_path.dirname.relative_path_from(sandbox_root).to_s
@@ -70,7 +93,7 @@ module Pod
70
93
  end
71
94
 
72
95
  # Configures the given Xcconfig with the the build settings for the given
73
- # framework path.
96
+ # library path.
74
97
  #
75
98
  # @param [Pathanme] framework_path
76
99
  # The path of the framework.
@@ -78,6 +101,9 @@ module Pod
78
101
  # @param [Xcodeproj::Config] xcconfig
79
102
  # The xcconfig to edit.
80
103
  #
104
+ # @param [Pathname] sandbox_root
105
+ # The path retrieved from Sandbox#root.
106
+ #
81
107
  def self.add_library_build_settings(library_path, xcconfig, sandbox_root)
82
108
  name = File.basename(library_path, '.a').sub(/\Alib/, '')
83
109
  dirname = '$(PODS_ROOT)/' + library_path.dirname.relative_path_from(sandbox_root).to_s
@@ -88,6 +114,58 @@ module Pod
88
114
  xcconfig.merge!(build_settings)
89
115
  end
90
116
 
117
+ # Add the code signing settings for generated targets to ensure that
118
+ # frameworks are correctly signed to be integrated and re-signed when
119
+ # building the application and embedding the framework
120
+ #
121
+ # @param [Target] target
122
+ # The target.
123
+ #
124
+ # @param [Xcodeproj::Config] xcconfig
125
+ # The xcconfig to edit.
126
+ #
127
+ def self.add_code_signing_settings(target, xcconfig)
128
+ build_settings = {}
129
+ if target.platform.to_sym == :osx
130
+ build_settings['CODE_SIGN_IDENTITY'] = ''
131
+ end
132
+ xcconfig.merge!(build_settings)
133
+ end
134
+
135
+ # Checks if the given target requires specific settings and configures
136
+ # the given Xcconfig.
137
+ #
138
+ # @param [Target] target
139
+ # The target.
140
+ #
141
+ # @param [Xcodeproj::Config] xcconfig
142
+ # The xcconfig to edit.
143
+ #
144
+ def self.add_target_specific_settings(target, xcconfig)
145
+ if target.requires_frameworks?
146
+ add_code_signing_settings(target, xcconfig)
147
+ end
148
+ add_language_specific_settings(target, xcconfig)
149
+ end
150
+
151
+ # Checks if the given target requires language specific settings and
152
+ # configures the given Xcconfig.
153
+ #
154
+ # @param [Target] target
155
+ # The target.
156
+ #
157
+ # @param [Xcodeproj::Config] xcconfig
158
+ # The xcconfig to edit.
159
+ #
160
+ def self.add_language_specific_settings(target, xcconfig)
161
+ if target.uses_swift?
162
+ build_settings = {
163
+ 'OTHER_SWIFT_FLAGS' => quote(['-D COCOAPODS']),
164
+ }
165
+ xcconfig.merge!(build_settings)
166
+ end
167
+ end
168
+
91
169
  # Adds the search paths of the developer frameworks to the specification
92
170
  # if needed. This is done because the `SenTestingKit` requires them and
93
171
  # adding them to each specification which requires it is repetitive and
@@ -1,3 +1,5 @@
1
+ require 'rubygems'
2
+
1
3
  module Pod
2
4
  # Provides support for the hook system of CocoaPods. The system is designed
3
5
  # especially for plugins. Interested clients can register to notifications by
@@ -14,27 +16,70 @@ module Pod
14
16
  # from CocoaPods 1.0).
15
17
  #
16
18
  module HooksManager
19
+ # Represents a single registered hook.
20
+ #
21
+ class Hook
22
+ # @return [String]
23
+ # The name of the hook's notification.
24
+ #
25
+ attr_reader :plugin_name
26
+
27
+ # @return [String]
28
+ # The name of the plugin the hook came from.
29
+ #
30
+ attr_reader :name
31
+
32
+ # @return [Proc]
33
+ # The block.
34
+ #
35
+ attr_reader :block
36
+
37
+ # @param [String] name @see {#name}.
38
+ #
39
+ # @param [String] plugin_name @see {#plugin_name}.
40
+ #
41
+ # @param [Proc] block @see {#block}.
42
+ #
43
+ def initialize(name, plugin_name, block)
44
+ raise ArgumentError, 'Missing name' unless name
45
+ raise ArgumentError, 'Missing block' unless block
46
+
47
+ UI.warn '[Hooks] The use of hooks without specifying a `plugin_name` ' \
48
+ 'has been deprecated.' unless plugin_name
49
+
50
+ @name = name
51
+ @plugin_name = plugin_name
52
+ @block = block
53
+ end
54
+ end
55
+
17
56
  class << self
18
- # @return [Hash{Symbol => Proc}] The list of the blocks that are
57
+ # @return [Hash{Symbol => Array<Proc>}] The list of the blocks that are
19
58
  # registered for each notification name.
20
59
  #
21
60
  attr_reader :registrations
22
61
 
23
62
  # Registers a block for the hook with the given name.
24
63
  #
25
- # @param [Symbol] name
64
+ # @param [String] plugin_name
65
+ # The name of the plugin the hook comes from.
66
+ #
67
+ # @param [Symbol] hook_name
26
68
  # The name of the notification.
27
69
  #
28
70
  # @param [Proc] block
29
71
  # The block.
30
72
  #
31
- def register(name, &block)
32
- raise ArgumentError, 'Missing name' unless name
33
- raise ArgumentError, 'Missing block' unless block
73
+ def register(plugin_name, hook_name = nil, &block)
74
+ # TODO: Backwards compatibility with nameless plugins from CP 0.34
75
+ if hook_name.nil?
76
+ hook_name = plugin_name
77
+ plugin_name = nil
78
+ end
34
79
 
35
80
  @registrations ||= {}
36
- @registrations[name] ||= []
37
- @registrations[name] << block
81
+ @registrations[hook_name] ||= []
82
+ @registrations[hook_name] << Hook.new(hook_name, plugin_name, block)
38
83
  end
39
84
 
40
85
  # Runs all the registered blocks for the hook with the given name.
@@ -45,15 +90,32 @@ module Pod
45
90
  # @param [Object] context
46
91
  # The context object which should be passed to the blocks.
47
92
  #
48
- def run(name, context)
93
+ # @param [Hash<String, Hash>] whitelisted_plugins
94
+ # The plugins that should be run, in the form of a hash keyed by
95
+ # plugin name, where the values are the custom options that should
96
+ # be passed to the hook's block if it supports taking a second
97
+ # argument.
98
+ #
99
+ def run(name, context, whitelisted_plugins = nil)
49
100
  raise ArgumentError, 'Missing name' unless name
50
101
  raise ArgumentError, 'Missing options' unless context
51
102
 
52
- if @registrations
53
- blocks = @registrations[name]
54
- if blocks
55
- blocks.each do |block|
56
- block.call(context)
103
+ if registrations
104
+ hooks = registrations[name]
105
+ if hooks
106
+ UI.message "- Running #{name.to_s.gsub('_', ' ')} hooks" do
107
+ hooks.each do |hook|
108
+ next if whitelisted_plugins && !whitelisted_plugins.key?(hook.plugin_name)
109
+ UI.message "- #{hook.plugin_name || 'unknown plugin'} from " \
110
+ "`#{hook.block.source_location.first}`" do
111
+ block = hook.block
112
+ if block.arity > 1
113
+ block.call(context, whitelisted_plugins[hook.plugin_name])
114
+ else
115
+ block.call(context)
116
+ end
117
+ end
118
+ end
57
119
  end
58
120
  end
59
121
  end