cocoapods-packager-tj 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +3 -0
  4. data/.rubocop-cocoapods.yml +71 -0
  5. data/.rubocop.yml +38 -0
  6. data/.travis.yml +9 -0
  7. data/Gemfile +12 -0
  8. data/Gemfile.lock +121 -0
  9. data/LICENSE +22 -0
  10. data/README.md +1 -0
  11. data/Rakefile +12 -0
  12. data/cocoapods-packager-tj.gemspec +22 -0
  13. data/lib/cocoapods-packager/builder.rb +298 -0
  14. data/lib/cocoapods-packager/framework.rb +66 -0
  15. data/lib/cocoapods-packager/mangle.rb +32 -0
  16. data/lib/cocoapods-packager/pod_utils.rb +253 -0
  17. data/lib/cocoapods-packager/spec_builder.rb +63 -0
  18. data/lib/cocoapods-packager/symbols.rb +35 -0
  19. data/lib/cocoapods-packager/user_interface/build_failed_report.rb +15 -0
  20. data/lib/cocoapods_packager.rb +5 -0
  21. data/lib/cocoapods_plugin.rb +8 -0
  22. data/lib/pod/command/package.rb +163 -0
  23. data/scripts/lstconst.sh +9 -0
  24. data/scripts/lstsym.sh +8 -0
  25. data/spec/command/error_spec.rb +74 -0
  26. data/spec/command/package_spec.rb +359 -0
  27. data/spec/command/subspecs_spec.rb +30 -0
  28. data/spec/fixtures/Builder.podspec +25 -0
  29. data/spec/fixtures/CPDColors.podspec +19 -0
  30. data/spec/fixtures/FH.podspec +18 -0
  31. data/spec/fixtures/KFData.podspec +73 -0
  32. data/spec/fixtures/LibraryConsumerDemo/.gitignore +22 -0
  33. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/AppDelegate.h +17 -0
  34. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/AppDelegate.m +27 -0
  35. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/Info.plist +40 -0
  36. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/main.m +16 -0
  37. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/project.pbxproj +340 -0
  38. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  39. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/xcshareddata/xcschemes/LibraryConsumer.xcscheme +100 -0
  40. data/spec/fixtures/LibraryConsumerDemo/Podfile +5 -0
  41. data/spec/fixtures/LibraryDemo.podspec +14 -0
  42. data/spec/fixtures/NikeKit.podspec +19 -0
  43. data/spec/fixtures/OpenSans.podspec +18 -0
  44. data/spec/fixtures/PackagerTest/.gitignore +21 -0
  45. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.h +15 -0
  46. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.m +49 -0
  47. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
  48. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
  49. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Info.plist +38 -0
  50. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Prefix.pch +16 -0
  51. data/spec/fixtures/PackagerTest/PackagerTest/en.lproj/InfoPlist.strings +2 -0
  52. data/spec/fixtures/PackagerTest/PackagerTest/main.m +18 -0
  53. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.pbxproj +536 -0
  54. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  55. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/xcshareddata/xcschemes/PackagerTest.xcscheme +110 -0
  56. data/spec/fixtures/PackagerTest/PackagerTest.xcworkspace/contents.xcworkspacedata +1 -0
  57. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests-Info.plist +22 -0
  58. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests.m +34 -0
  59. data/spec/fixtures/PackagerTest/PackagerTestTests/en.lproj/InfoPlist.strings +2 -0
  60. data/spec/fixtures/PackagerTest/Podfile +10 -0
  61. data/spec/fixtures/PackagerTest/Podfile.lock +32 -0
  62. data/spec/fixtures/Weakly.podspec +13 -0
  63. data/spec/fixtures/a.podspec +19 -0
  64. data/spec/fixtures/foo-bar.podspec +19 -0
  65. data/spec/fixtures/layer-client-messaging-schema.podspec +13 -0
  66. data/spec/integration/project_spec.rb +70 -0
  67. data/spec/pod/utils_spec.rb +58 -0
  68. data/spec/spec_helper.rb +50 -0
  69. data/spec/specification/builder_spec.rb +40 -0
  70. data/spec/specification/spec_builder_spec.rb +61 -0
  71. data/spec/user_interface/build_failed_report_spec.rb +11 -0
  72. metadata +209 -0
@@ -0,0 +1,32 @@
1
+ module Symbols
2
+ #
3
+ # performs symbol aliasing
4
+ #
5
+ # for each dependency:
6
+ # - determine symbols for classes and global constants
7
+ # - alias each symbol to Pod#{pod_name}_#{symbol}
8
+ # - put defines into `GCC_PREPROCESSOR_DEFINITIONS` for passing to Xcode
9
+ #
10
+ def mangle_for_pod_dependencies(pod_name, sandbox_root)
11
+ pod_libs = Dir.glob("#{sandbox_root}/build/lib*.a").select do |file|
12
+ file !~ /lib#{pod_name}.a$/
13
+ end
14
+
15
+ dummy_alias = alias_symbol "PodsDummy_#{pod_name}", pod_name
16
+ all_syms = [dummy_alias]
17
+
18
+ pod_libs.each do |pod_lib|
19
+ syms = Symbols.symbols_from_library(pod_lib)
20
+ all_syms += syms.map! { |sym| alias_symbol sym, pod_name }
21
+ end
22
+
23
+ "GCC_PREPROCESSOR_DEFINITIONS='$(inherited) #{all_syms.uniq.join(' ')}'"
24
+ end
25
+
26
+ def alias_symbol(sym, pod_name)
27
+ pod_name = pod_name.tr('-', '_')
28
+ sym + "=Pod#{pod_name}_" + sym
29
+ end
30
+
31
+ module_function :mangle_for_pod_dependencies, :alias_symbol
32
+ end
@@ -0,0 +1,253 @@
1
+ module Pod
2
+ class Command
3
+ class Package < Command
4
+ private
5
+
6
+ def build_static_sandbox(dynamic)
7
+ static_sandbox_root = if dynamic
8
+ Pathname.new(config.sandbox_root + '/Static')
9
+ else
10
+ Pathname.new(config.sandbox_root)
11
+ end
12
+ Sandbox.new(static_sandbox_root)
13
+ end
14
+
15
+ def install_pod(platform_name, sandbox)
16
+ podfile = podfile_from_spec(
17
+ File.basename(@path),
18
+ @spec.name,
19
+ platform_name,
20
+ @spec.deployment_target(platform_name),
21
+ @subspecs,
22
+ @spec_sources
23
+ )
24
+
25
+ static_installer = Installer.new(sandbox, podfile)
26
+ static_installer.install!
27
+
28
+ unless static_installer.nil?
29
+ static_installer.pods_project.targets.each do |target|
30
+ target.build_configurations.each do |config|
31
+ config.build_settings['CLANG_MODULES_AUTOLINK'] = 'NO'
32
+ config.build_settings['GCC_GENERATE_DEBUGGING_SYMBOLS'] = 'NO'
33
+ config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
34
+ end
35
+ end
36
+ static_installer.pods_project.save
37
+ end
38
+
39
+ static_installer
40
+ end
41
+
42
+ def podfile_from_spec(path, spec_name, platform_name, deployment_target, subspecs, sources)
43
+ options = {}
44
+ if path
45
+ options[:podspec] = path
46
+ else
47
+ options[:path] = '.'
48
+ end
49
+ options[:subspecs] = subspecs if subspecs
50
+ Pod::Podfile.new do
51
+ sources.each { |s| source s }
52
+ platform(platform_name, deployment_target)
53
+ pod(spec_name, options)
54
+
55
+ install!('cocoapods',
56
+ :integrate_targets => false,
57
+ :deterministic_uuids => false)
58
+
59
+ target('packager') do
60
+ if path
61
+ if subspecs
62
+ subspecs.each do |subspec|
63
+ pod spec_name + '/' + subspec, :podspec => path
64
+ end
65
+ else
66
+ pod spec_name, :podspec => path
67
+ end
68
+ elsif subspecs
69
+ subspecs.each do |subspec|
70
+ pod spec_name + '/' + subspec, :path => '.'
71
+ end
72
+ else
73
+ pod spec_name, :path => '.'
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ def binary_only?(spec)
80
+ deps = spec.dependencies.map { |dep| spec_with_name(dep.name) }
81
+ [spec, *deps].each do |specification|
82
+ %w(vendored_frameworks vendored_libraries).each do |attrib|
83
+ if specification.attributes_hash[attrib]
84
+ return true
85
+ end
86
+ end
87
+ end
88
+
89
+ false
90
+ end
91
+
92
+ def spec_with_name(name)
93
+ return if name.nil?
94
+
95
+ set = Pod::Config.instance.sources_manager.search(Dependency.new(name))
96
+ return nil if set.nil?
97
+
98
+ set.specification.root
99
+ end
100
+
101
+ def spec_with_path(path)
102
+ return if path.nil? || !Pathname.new(path).exist?
103
+
104
+ @path = path
105
+
106
+ if Pathname.new(path).directory?
107
+ help! path + ': is a directory.'
108
+ return
109
+ end
110
+
111
+ unless ['.podspec', '.json'].include? Pathname.new(path).extname
112
+ help! path + ': is not a podspec.'
113
+ return
114
+ end
115
+
116
+ Specification.from_file(path)
117
+ end
118
+
119
+ #----------------------
120
+ # Dynamic Project Setup
121
+ #----------------------
122
+
123
+ def build_dynamic_sandbox(_static_sandbox, _static_installer)
124
+ dynamic_sandbox_root = Pathname.new(config.sandbox_root + '/Dynamic')
125
+ dynamic_sandbox = Sandbox.new(dynamic_sandbox_root)
126
+
127
+ dynamic_sandbox
128
+ end
129
+
130
+ def install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer)
131
+ # 1 Create a dynamic target for only the spec pod.
132
+ dynamic_target = build_dynamic_target(dynamic_sandbox, static_installer)
133
+
134
+ # 2. Build a new xcodeproj in the dynamic_sandbox with only the spec pod as a target.
135
+ project = prepare_pods_project(dynamic_sandbox, dynamic_target.name, static_installer)
136
+
137
+ # 3. Copy the source directory for the dynamic framework from the static sandbox.
138
+ copy_dynamic_target(static_sandbox, dynamic_target, dynamic_sandbox)
139
+
140
+ # 4. Copy the supporting files for the dynamic framework from the static sandbox.
141
+ copy_dynamic_supporting_files(static_sandbox, dynamic_target, dynamic_sandbox)
142
+
143
+ # 5. Update the file accecssors.
144
+ dynamic_target = update_file_accessors(dynamic_target, dynamic_sandbox)
145
+
146
+ # 6. Create the file references.
147
+ install_file_references(dynamic_sandbox, [dynamic_target], project)
148
+
149
+ # 7. Install the target.
150
+ install_library(dynamic_sandbox, dynamic_target)
151
+
152
+ # 9. Write the actual Xcodeproject to the dynamic sandbox.
153
+ write_pod_project(project, dynamic_sandbox)
154
+ end
155
+
156
+ def build_dynamic_target(dynamic_sandbox, static_installer)
157
+ spec_targets = static_installer.pod_targets.select do |target|
158
+ target.name == @spec.name
159
+ end
160
+ static_target = spec_targets[0]
161
+
162
+ dynamic_target = Pod::PodTarget.new(static_target.specs, static_target.target_definitions, dynamic_sandbox)
163
+ dynamic_target.host_requires_frameworks = true
164
+ dynamic_target.user_build_configurations = static_target.user_build_configurations
165
+ dynamic_target
166
+ end
167
+
168
+ def prepare_pods_project(dynamic_sandbox, spec_name, installer)
169
+ # Create a new pods project
170
+ pods_project = Pod::Project.new(dynamic_sandbox.project_path)
171
+
172
+ # Update build configurations
173
+ installer.analysis_result.all_user_build_configurations.each do |name, type|
174
+ pods_project.add_build_configuration(name, type)
175
+ end
176
+
177
+ # Add the pod group for only the dynamic framework
178
+ local = dynamic_sandbox.local?(spec_name)
179
+ path = dynamic_sandbox.pod_dir(spec_name)
180
+ was_absolute = dynamic_sandbox.local_path_was_absolute?(spec_name)
181
+ pods_project.add_pod_group(spec_name, path, local, was_absolute)
182
+
183
+ dynamic_sandbox.project = pods_project
184
+ pods_project
185
+ end
186
+
187
+ def copy_dynamic_target(static_sandbox, _dynamic_target, dynamic_sandbox)
188
+ command = "cp -a #{static_sandbox.root}/#{@spec.name} #{dynamic_sandbox.root}"
189
+ `#{command}`
190
+ end
191
+
192
+ def copy_dynamic_supporting_files(_static_sandbox, dynamic_target, _dynamic_sandbox)
193
+ support_dir = Pathname.new(dynamic_target.support_files_dir.to_s.chomp("/#{dynamic_target.name}"))
194
+ support_dir.mkdir
195
+ end
196
+
197
+ def update_file_accessors(dynamic_target, dynamic_sandbox)
198
+ pod_root = dynamic_sandbox.pod_dir(dynamic_target.root_spec.name)
199
+
200
+ path_list = Sandbox::PathList.new(pod_root)
201
+ file_accessors = dynamic_target.specs.map do |spec|
202
+ Sandbox::FileAccessor.new(path_list, spec.consumer(dynamic_target.platform))
203
+ end
204
+
205
+ dynamic_target.file_accessors = file_accessors
206
+ dynamic_target
207
+ end
208
+
209
+ def install_file_references(dynamic_sandbox, pod_targets, pods_project)
210
+ installer = Pod::Installer::Xcode::PodsProjectGenerator::FileReferencesInstaller.new(dynamic_sandbox, pod_targets, pods_project)
211
+ installer.install!
212
+ end
213
+
214
+ def install_library(dynamic_sandbox, dynamic_target)
215
+ return if dynamic_target.target_definitions.flat_map(&:dependencies).empty?
216
+ target_installer = Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller.new(dynamic_sandbox, dynamic_target)
217
+ target_installer.install!
218
+
219
+ # Installs System Frameworks
220
+ dynamic_target.file_accessors.each do |file_accessor|
221
+ file_accessor.spec_consumer.frameworks.each do |framework|
222
+ if dynamic_target.should_build?
223
+ dynamic_target.native_target.add_system_framework(framework)
224
+ end
225
+ end
226
+
227
+ file_accessor.spec_consumer.libraries.each do |library|
228
+ if dynamic_target.should_build?
229
+ dynamic_target.native_target.add_system_library(library)
230
+ end
231
+ end
232
+ end
233
+ end
234
+
235
+ def write_pod_project(dynamic_project, dynamic_sandbox)
236
+ UI.message "- Writing Xcode project file to #{UI.path dynamic_sandbox.project_path}" do
237
+ dynamic_project.pods.remove_from_project if dynamic_project.pods.empty?
238
+ dynamic_project.development_pods.remove_from_project if dynamic_project.development_pods.empty?
239
+ dynamic_project.sort(:groups_position => :below)
240
+ dynamic_project.recreate_user_schemes(false)
241
+
242
+ # Edit search paths so that we can find our dependency headers
243
+ dynamic_project.targets.first.build_configuration_list.build_configurations.each do |config|
244
+ config.build_settings['HEADER_SEARCH_PATHS'] = "$(inherited) #{Dir.pwd}/Pods/Static/Headers/**"
245
+ config.build_settings['USER_HEADER_SEARCH_PATHS'] = "$(inherited) #{Dir.pwd}/Pods/Static/Headers/**"
246
+ config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -ObjC'
247
+ end
248
+ dynamic_project.save
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,63 @@
1
+ module Pod
2
+ class SpecBuilder
3
+ def initialize(spec, source, embedded, dynamic)
4
+ @spec = spec
5
+ @source = source.nil? ? '{ :path => \'.\' }' : source
6
+ @embedded = embedded
7
+ @dynamic = dynamic
8
+ end
9
+
10
+ def framework_path
11
+ if @embedded
12
+ @spec.name + '.embeddedframework' + '/' + @spec.name + '.framework'
13
+ else
14
+ @spec.name + '.framework'
15
+ end
16
+ end
17
+
18
+ def spec_platform(platform)
19
+ fwk_base = platform.name.to_s + '/' + framework_path
20
+ spec = <<RB
21
+ s.#{platform.name}.deployment_target = '#{platform.deployment_target}'
22
+ s.#{platform.name}.vendored_framework = '#{fwk_base}'
23
+ RB
24
+
25
+ %w(frameworks weak_frameworks libraries requires_arc xcconfig).each do |attribute|
26
+ attributes_hash = @spec.attributes_hash[platform.name.to_s]
27
+ next if attributes_hash.nil?
28
+ value = attributes_hash[attribute]
29
+ next if value.nil?
30
+
31
+ value = "'#{value}'" if value.class == String
32
+ spec += " s.#{platform.name}.#{attribute} = #{value}\n"
33
+ end
34
+ spec
35
+ end
36
+
37
+ def spec_metadata
38
+ spec = spec_header
39
+ spec
40
+ end
41
+
42
+ def spec_close
43
+ "end\n"
44
+ end
45
+
46
+ private
47
+
48
+ def spec_header
49
+ spec = "Pod::Spec.new do |s|\n"
50
+
51
+ %w(name version summary license authors homepage description social_media_url
52
+ docset_url documentation_url screenshots frameworks weak_frameworks libraries requires_arc
53
+ deployment_target xcconfig).each do |attribute|
54
+ value = @spec.attributes_hash[attribute]
55
+ next if value.nil?
56
+ value = value.dump if value.class == String
57
+ spec += " s.#{attribute} = #{value}\n"
58
+ end
59
+
60
+ spec + " s.source = #{@source}\n\n"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,35 @@
1
+ module Symbols
2
+ def symbols_from_library(library)
3
+ syms = `nm -gU #{library}`.split("\n")
4
+ result = classes_from_symbols(syms)
5
+ result += constants_from_symbols(syms)
6
+
7
+ result.reject { |e| e == 'llvm.cmdline' || e == 'llvm.embedded.module' }
8
+ end
9
+
10
+ module_function :symbols_from_library
11
+
12
+ private
13
+
14
+ def classes_from_symbols(syms)
15
+ classes = syms.select { |klass| klass[/OBJC_CLASS_\$_/] }
16
+ classes = classes.uniq
17
+ classes.map! { |klass| klass.gsub(/^.*\$_/, '') }
18
+ end
19
+
20
+ def constants_from_symbols(syms)
21
+ consts = syms.select { |const| const[/ S /] }
22
+ consts = consts.select { |const| const !~ /OBJC|\.eh/ }
23
+ consts = consts.uniq
24
+ consts = consts.map! { |const| const.gsub(/^.* _/, '') }
25
+
26
+ other_consts = syms.select { |const| const[/ T /] }
27
+ other_consts = other_consts.uniq
28
+ other_consts = other_consts.map! { |const| const.gsub(/^.* _/, '') }
29
+
30
+ consts + other_consts
31
+ end
32
+
33
+ module_function :classes_from_symbols
34
+ module_function :constants_from_symbols
35
+ end
@@ -0,0 +1,15 @@
1
+ module Pod
2
+ module UserInterface
3
+ module BuildFailedReport
4
+ class << self
5
+ def report(command, output)
6
+ <<-EOF
7
+ Build command failed: #{command}
8
+ Output:
9
+ #{output.map { |line| " #{line}" }.join}
10
+ EOF
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module Pod
2
+ module Packager
3
+ VERSION = '1.5.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'pod/command/package'
2
+ require 'cocoapods-packager/user_interface/build_failed_report'
3
+ require 'cocoapods-packager/builder'
4
+ require 'cocoapods-packager/framework'
5
+ require 'cocoapods-packager/mangle'
6
+ require 'cocoapods-packager/pod_utils'
7
+ require 'cocoapods-packager/spec_builder'
8
+ require 'cocoapods-packager/symbols'
@@ -0,0 +1,163 @@
1
+ require 'tmpdir'
2
+ module Pod
3
+ class Command
4
+ class Package < Command
5
+ self.summary = 'Package a podspec into a static library.'
6
+ self.arguments = [
7
+ CLAide::Argument.new('NAME', true),
8
+ CLAide::Argument.new('SOURCE', false)
9
+ ]
10
+
11
+ def self.options
12
+ [
13
+ ['--force', 'Overwrite existing files.'],
14
+ ['--no-mangle', 'Do not mangle symbols of depedendant Pods.'],
15
+ ['--embedded', 'Generate embedded frameworks.'],
16
+ ['--library', 'Generate static libraries.'],
17
+ ['--dynamic', 'Generate dynamic framework.'],
18
+ ['--bundle-identifier', 'Bundle identifier for dynamic framework'],
19
+ ['--exclude-deps', 'Exclude symbols from dependencies.'],
20
+ ['--configuration', 'Build the specified configuration (e.g. Debug). Defaults to Release'],
21
+ ['--subspecs', 'Only include the given subspecs'],
22
+ ['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependant ' \
23
+ 'pods from (defaults to https://github.com/CocoaPods/Specs.git)']
24
+ ]
25
+ end
26
+
27
+ def initialize(argv)
28
+ @embedded = argv.flag?('embedded')
29
+ @force = argv.flag?('force')
30
+ @library = argv.flag?('library')
31
+ @dynamic = argv.flag?('dynamic')
32
+ @mangle = argv.flag?('mangle', true)
33
+ @bundle_identifier = argv.option('bundle-identifier', nil)
34
+ @exclude_deps = argv.flag?('exclude-deps', false)
35
+ @name = argv.shift_argument
36
+ @source = argv.shift_argument
37
+ @spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',')
38
+
39
+ subspecs = argv.option('subspecs')
40
+ @subspecs = subspecs.split(',') unless subspecs.nil?
41
+
42
+ @config = argv.option('configuration', 'Release')
43
+
44
+ @source_dir = Dir.pwd
45
+ @spec = spec_with_path(@name)
46
+ @spec = spec_with_name(@name) unless @spec
47
+ super
48
+ end
49
+
50
+ def validate!
51
+ super
52
+ help! 'A podspec name or path is required.' unless @spec
53
+ help! 'podspec has binary-only depedencies, mangling not possible.' if @mangle && binary_only?(@spec)
54
+ help! '--bundle-identifier option can only be used for dynamic frameworks' if @bundle_identifier && !@dynamic
55
+ help! '--exclude-deps option can only be used for static libraries' if @exclude_deps && @dynamic
56
+ end
57
+
58
+ def run
59
+ if @path.nil? || @spec.nil?
60
+ help! 'Unable to find a podspec with path or name.'
61
+ return
62
+ end
63
+
64
+ target_dir, work_dir = create_working_directory
65
+ return if target_dir.nil?
66
+ build_package
67
+
68
+ `mv "#{work_dir}" "#{target_dir}"`
69
+ Dir.chdir(@source_dir)
70
+ end
71
+
72
+ private
73
+
74
+ def build_in_sandbox(platform)
75
+ config.installation_root = Pathname.new(Dir.pwd)
76
+ config.sandbox_root = 'Pods'
77
+
78
+ static_sandbox = build_static_sandbox(@dynamic)
79
+ static_installer = install_pod(platform.name, static_sandbox)
80
+
81
+ if @dynamic
82
+ dynamic_sandbox = build_dynamic_sandbox(static_sandbox, static_installer)
83
+ install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer)
84
+ end
85
+
86
+ begin
87
+ perform_build(platform, static_sandbox, dynamic_sandbox)
88
+
89
+ ensure # in case the build fails; see Builder#xcodebuild.
90
+ Pathname.new(config.sandbox_root).rmtree
91
+ FileUtils.rm_f('Podfile.lock')
92
+ end
93
+ end
94
+
95
+ def build_package
96
+ builder = SpecBuilder.new(@spec, @source, @embedded, @dynamic)
97
+ newspec = builder.spec_metadata
98
+
99
+ @spec.available_platforms.each do |platform|
100
+ build_in_sandbox(platform)
101
+
102
+ newspec += builder.spec_platform(platform)
103
+ end
104
+
105
+ newspec += builder.spec_close
106
+ File.open(@spec.name + '.podspec', 'w') { |file| file.write(newspec) }
107
+ end
108
+
109
+ def create_target_directory
110
+ target_dir = "#{@source_dir}/#{@spec.name}-#{@spec.version}"
111
+ if File.exist? target_dir
112
+ if @force
113
+ Pathname.new(target_dir).rmtree
114
+ else
115
+ UI.puts "Target directory '#{target_dir}' already exists."
116
+ return nil
117
+ end
118
+ end
119
+ target_dir
120
+ end
121
+
122
+ def create_working_directory
123
+ target_dir = create_target_directory
124
+ return if target_dir.nil?
125
+
126
+ work_dir = Dir.tmpdir + '/cocoapods-' + Array.new(8) { rand(36).to_s(36) }.join
127
+ Pathname.new(work_dir).mkdir
128
+ `cp #{@path} #{work_dir}`
129
+ Dir.chdir(work_dir)
130
+
131
+ [target_dir, work_dir]
132
+ end
133
+
134
+ def perform_build(platform, static_sandbox, dynamic_sandbox)
135
+ static_sandbox_root = config.sandbox_root.to_s
136
+
137
+ if @dynamic
138
+ static_sandbox_root = "#{static_sandbox_root}/#{static_sandbox.root.to_s.split('/').last}"
139
+ dynamic_sandbox_root = "#{config.sandbox_root}/#{dynamic_sandbox.root.to_s.split('/').last}"
140
+ end
141
+
142
+ builder = Pod::Builder.new(
143
+ @source_dir,
144
+ static_sandbox_root,
145
+ dynamic_sandbox_root,
146
+ static_sandbox.public_headers.root,
147
+ @spec,
148
+ @embedded,
149
+ @mangle,
150
+ @dynamic,
151
+ @config,
152
+ @bundle_identifier,
153
+ @exclude_deps
154
+ )
155
+
156
+ builder.build(platform, @library)
157
+
158
+ return unless @embedded
159
+ builder.link_embedded_resources
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+
3
+ #
4
+ # List symbols for all constants
5
+ #
6
+
7
+ nm "$@"|grep ' S '|grep -v 'OBJC\|\.eh$'| \
8
+ cut -d_ -f2-|sort|uniq
9
+ nm "$@"|grep ' T '|cut -d_ -f2-|sort|uniq
data/scripts/lstsym.sh ADDED
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+
3
+ #
4
+ # List symbols for all Objective-C classes
5
+ #
6
+
7
+ nm "$@"| grep 'OBJC_CLASS_\$_'|grep -v '_NS\|_UI'| \
8
+ rev|cut -d' ' -f-1|rev|sort|uniq|cut -d'_' -f5-
@@ -0,0 +1,74 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ module Pod
4
+ describe 'Packager' do
5
+ after do
6
+ Dir.glob("CPDColors-*").each { |dir| Pathname.new(dir).rmtree }
7
+ Dir.glob("layer-client-messaging-schema-*").each { |dir| Pathname.new(dir).rmtree }
8
+ Dir.glob("OpenSans-*").each { |dir| Pathname.new(dir).rmtree }
9
+ Dir.glob("Weakly-*").each { |dir| Pathname.new(dir).rmtree }
10
+ end
11
+
12
+ it 'presents the help if a directory is provided' do
13
+ should.raise CLAide::Help do
14
+ command = Command.parse(%w{ package spec })
15
+ end.message.should.match /is a directory/
16
+ end
17
+
18
+ it 'presents the help if a random file is provided instead of a specification' do
19
+ should.raise CLAide::Help do
20
+ command = Command.parse(%w{ package README.md })
21
+ end.message.should.match /is not a podspec/
22
+ end
23
+
24
+ it 'presents the help if a podspec with binary-only dependencies is used' do
25
+ command = Command.parse(%w{ package spec/fixtures/CPDColors.podspec })
26
+ should.raise CLAide::Help do
27
+ command.validate!
28
+ end.message.should.match /binary-only/
29
+ end
30
+
31
+ it 'presents the help if only --bundle-identifier is specified' do
32
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --bundle-identifier=com.example.NikeKit })
33
+ should.raise CLAide::Help do
34
+ command.validate!
35
+ end.message.should.match /--bundle-identifier option can only be used for dynamic frameworks/
36
+ end
37
+
38
+ it 'presents the help if both --exclude-deps and --dynamic are specified' do
39
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --exclude-deps --dynamic })
40
+ should.raise CLAide::Help do
41
+ command.validate!
42
+ end.message.should.match /--exclude-deps option can only be used for static libraries/
43
+ end
44
+
45
+ it 'can package a podspec with only resources' do
46
+ command = Command.parse(%w{ package spec/fixtures/layer-client-messaging-schema.podspec --no-mangle })
47
+ command.run
48
+
49
+ true.should == true # To make the test pass without any shoulds
50
+ end
51
+
52
+ it 'can package a podspec with binary-only dependencies if --no-mangle is specified' do
53
+ command = Command.parse(%w{ package spec/fixtures/CPDColors.podspec --no-mangle })
54
+ command.run
55
+
56
+ true.should == true # To make the test pass without any shoulds
57
+ end
58
+
59
+ it 'can package a podspec with resource bundles' do
60
+ command = Command.parse(%w{ package spec/fixtures/OpenSans.podspec })
61
+ command.run
62
+
63
+ bundles = Dir.glob('OpenSans-*/ios/OpenSans.framework/Versions/A/Resources/*.bundle')
64
+ bundles.count.should == 1
65
+ end
66
+
67
+ it 'can package a podspec with weak frameworks without strong linking' do
68
+ command = Command.parse(%w{ package spec/fixtures/Weakly.podspec })
69
+ command.run
70
+
71
+ `otool -l Weakly-*/ios/Weakly.framework/Weakly`.should.not.match /AssetsLibrary/
72
+ end
73
+ end
74
+ end