cocoapods-xzpackager 1.0.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 (73) 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 +42 -0
  11. data/Rakefile +12 -0
  12. data/TAGS +180 -0
  13. data/cocoapods-xzpackager.gemspec +22 -0
  14. data/lib/cocoapods-packager/builder.rb +335 -0
  15. data/lib/cocoapods-packager/framework.rb +75 -0
  16. data/lib/cocoapods-packager/mangle.rb +32 -0
  17. data/lib/cocoapods-packager/pod_utils.rb +244 -0
  18. data/lib/cocoapods-packager/spec_builder.rb +219 -0
  19. data/lib/cocoapods-packager/symbols.rb +42 -0
  20. data/lib/cocoapods-packager/user_interface/build_failed_report.rb +15 -0
  21. data/lib/cocoapods_plugin.rb +8 -0
  22. data/lib/cocoapods_xzpackager.rb +5 -0
  23. data/lib/pod/command/package.rb +226 -0
  24. data/scripts/lstconst.sh +9 -0
  25. data/scripts/lstsym.sh +8 -0
  26. data/spec/command/error_spec.rb +74 -0
  27. data/spec/command/package_spec.rb +359 -0
  28. data/spec/command/subspecs_spec.rb +30 -0
  29. data/spec/fixtures/Builder.podspec +25 -0
  30. data/spec/fixtures/CPDColors.podspec +19 -0
  31. data/spec/fixtures/FH.podspec +18 -0
  32. data/spec/fixtures/KFData.podspec +73 -0
  33. data/spec/fixtures/LibraryConsumerDemo/.gitignore +22 -0
  34. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/project.pbxproj +340 -0
  35. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  36. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/xcshareddata/xcschemes/LibraryConsumer.xcscheme +100 -0
  37. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/AppDelegate.h +17 -0
  38. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/AppDelegate.m +27 -0
  39. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/Info.plist +40 -0
  40. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/main.m +16 -0
  41. data/spec/fixtures/LibraryConsumerDemo/Podfile +5 -0
  42. data/spec/fixtures/LibraryDemo.podspec +14 -0
  43. data/spec/fixtures/NikeKit.podspec +19 -0
  44. data/spec/fixtures/OpenSans.podspec +18 -0
  45. data/spec/fixtures/PackagerTest/.gitignore +21 -0
  46. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.pbxproj +536 -0
  47. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  48. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/xcshareddata/xcschemes/PackagerTest.xcscheme +110 -0
  49. data/spec/fixtures/PackagerTest/PackagerTest.xcworkspace/contents.xcworkspacedata +1 -0
  50. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.h +15 -0
  51. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.m +49 -0
  52. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
  53. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
  54. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Info.plist +38 -0
  55. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Prefix.pch +16 -0
  56. data/spec/fixtures/PackagerTest/PackagerTest/en.lproj/InfoPlist.strings +2 -0
  57. data/spec/fixtures/PackagerTest/PackagerTest/main.m +18 -0
  58. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests-Info.plist +22 -0
  59. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests.m +34 -0
  60. data/spec/fixtures/PackagerTest/PackagerTestTests/en.lproj/InfoPlist.strings +2 -0
  61. data/spec/fixtures/PackagerTest/Podfile +10 -0
  62. data/spec/fixtures/PackagerTest/Podfile.lock +32 -0
  63. data/spec/fixtures/Weakly.podspec +13 -0
  64. data/spec/fixtures/a.podspec +19 -0
  65. data/spec/fixtures/foo-bar.podspec +19 -0
  66. data/spec/fixtures/layer-client-messaging-schema.podspec +13 -0
  67. data/spec/integration/project_spec.rb +70 -0
  68. data/spec/pod/utils_spec.rb +58 -0
  69. data/spec/spec_helper.rb +50 -0
  70. data/spec/specification/builder_spec.rb +40 -0
  71. data/spec/specification/spec_builder_spec.rb +61 -0
  72. data/spec/user_interface/build_failed_report_spec.rb +11 -0
  73. metadata +225 -0
@@ -0,0 +1,42 @@
1
+ module Symbols
2
+ def symbols_from_library(library)
3
+ syms = `nm -defined-only -extern-only #{library}`.split("\n")
4
+ result = classes_from_symbols(syms)
5
+ result += constants_from_symbols(syms)
6
+
7
+ result.select do |e|
8
+ case e
9
+ when 'llvm.cmdline', 'llvm.embedded.module', '__clang_at_available_requires_core_foundation_framework'
10
+ false
11
+ else
12
+ true
13
+ end
14
+ end
15
+ end
16
+
17
+ module_function :symbols_from_library
18
+
19
+ private
20
+
21
+ def classes_from_symbols(syms)
22
+ classes = syms.select { |klass| klass[/OBJC_CLASS_\$_/] }
23
+ classes = classes.uniq
24
+ classes.map! { |klass| klass.gsub(/^.*\$_/, '') }
25
+ end
26
+
27
+ def constants_from_symbols(syms)
28
+ consts = syms.select { |const| const[/ S /] }
29
+ consts = consts.select { |const| const !~ /OBJC|\.eh/ }
30
+ consts = consts.uniq
31
+ consts = consts.map! { |const| const.gsub(/^.* _/, '') }
32
+
33
+ other_consts = syms.select { |const| const[/ T /] }
34
+ other_consts = other_consts.uniq
35
+ other_consts = other_consts.map! { |const| const.gsub(/^.* _/, '') }
36
+
37
+ consts + other_consts
38
+ end
39
+
40
+ module_function :classes_from_symbols
41
+ module_function :constants_from_symbols
42
+ 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,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,5 @@
1
+ module Pod
2
+ module Packager
3
+ VERSION = '1.0.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,226 @@
1
+ require 'tmpdir'
2
+ require 'net/sftp'
3
+ module Pod
4
+ class Command
5
+ class Package < Command
6
+ self.summary = 'Package a podspec into a static library.'
7
+ self.arguments = [
8
+ CLAide::Argument.new('NAME', true),
9
+ CLAide::Argument.new('SOURCE', false)
10
+ ]
11
+
12
+ def self.options
13
+ [
14
+ ['--force', 'Overwrite existing files.'],
15
+ ['--no-mangle', 'Do not mangle symbols of depedendant Pods.'],
16
+ ['--embedded', 'Generate embedded frameworks.'],
17
+ ['--library', 'Generate static libraries.'],
18
+ ['--dynamic', 'Generate dynamic framework.'],
19
+ ['--local', 'Use local state rather than published versions.'],
20
+ ['--bundle-identifier', 'Bundle identifier for dynamic framework'],
21
+ ['--exclude-deps', 'Exclude symbols from dependencies.'],
22
+ ['--configuration', 'Build the specified configuration (e.g. Debug). Defaults to Release'],
23
+ ['--subspecs', 'Only include the given subspecs'],
24
+ ['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependent ' \
25
+ 'pods from (defaults to https://github.com/CocoaPods/Specs.git)']
26
+ ]
27
+ end
28
+
29
+ def initialize(argv)
30
+ @embedded = argv.flag?('embedded')
31
+ @library = argv.flag?('library')
32
+ @dynamic = argv.flag?('dynamic')
33
+ @local = argv.flag?('local', false)
34
+ @package_type = if @embedded
35
+ :static_framework
36
+ elsif @dynamic
37
+ :dynamic_framework
38
+ elsif @library
39
+ :static_library
40
+ else
41
+ :static_framework
42
+ end
43
+ @force = argv.flag?('force',true)
44
+ @mangle = argv.flag?('mangle', true)
45
+ @bundle_identifier = argv.option('bundle-identifier', nil)
46
+ @exclude_deps = argv.flag?('exclude-deps', true)
47
+ @name = argv.shift_argument
48
+ @source = argv.shift_argument
49
+ @spec_sources = argv.option('spec-sources', 'git@gitlab.idc.xiaozhu.com:iOS/XZPrivatePodsRepo.git,https://github.com/CocoaPods/Specs.git').split(',')
50
+ subspecs = argv.option('subspecs')
51
+ @subspecs = subspecs.split(',') unless subspecs.nil?
52
+ @config = argv.option('configuration', 'Release')
53
+ @source_dir = Dir.pwd
54
+ @is_spec_from_path = false
55
+ @spec = spec_with_path(@name)
56
+ @is_spec_from_path = true if @spec
57
+ @spec ||= spec_with_name(@name)
58
+ @target_path = ''
59
+ super
60
+ end
61
+
62
+ def validate!
63
+ super
64
+ help! 'A podspec name or path is required.' unless @spec
65
+ help! 'podspec has binary-only depedencies, mangling not possible.' if @mangle && binary_only?(@spec)
66
+ help! '--bundle-identifier option can only be used for dynamic frameworks' if @bundle_identifier && !@dynamic
67
+ help! '--exclude-deps option can only be used for static libraries' if @exclude_deps && @dynamic
68
+ help! '--local option can only be used when a local `.podspec` path is given.' if @local && !@is_spec_from_path
69
+ end
70
+
71
+ def run
72
+ if @spec.nil?
73
+ help! "Unable to find a podspec with path or name `#{@name}`."
74
+ return
75
+ end
76
+
77
+ target_dir, work_dir = create_working_directory
78
+ return if target_dir.nil?
79
+ build_package
80
+ `mv "#{work_dir}" "#{target_dir}"`
81
+ `rm -rf #{target_dir}/build`
82
+ Dir.chdir(@source_dir)
83
+ zip_upload_static_server
84
+ end
85
+
86
+ private
87
+
88
+ def build_in_sandbox(platform)
89
+ config.installation_root = Pathname.new(Dir.pwd)
90
+ config.sandbox_root = 'Pods'
91
+
92
+ static_sandbox = build_static_sandbox(@dynamic)
93
+ static_installer = install_pod(platform.name, static_sandbox)
94
+
95
+ if @dynamic
96
+ dynamic_sandbox = build_dynamic_sandbox(static_sandbox, static_installer)
97
+ install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer, platform)
98
+ end
99
+
100
+ begin
101
+ perform_build(platform, static_sandbox, dynamic_sandbox, static_installer)
102
+ ensure # in case the build fails; see Builder#xcodebuild.
103
+ Pathname.new(config.sandbox_root).rmtree
104
+ FileUtils.rm_f('Podfile.lock')
105
+ end
106
+ end
107
+
108
+ def build_package
109
+ builder = SpecBuilder.new(@spec, @source, @embedded, @dynamic)
110
+ newspec = builder.spec_metadata
111
+ need_platforms = @spec.available_platforms.select {|plat| plat.name == :ios}
112
+ need_platforms.each do |platform|
113
+ build_in_sandbox(platform)
114
+
115
+ newspec += builder.spec_platform(platform)
116
+ end
117
+
118
+ newspec += builder.spec_close
119
+ File.open(@spec.name + '.podspec', 'w') { |file| file.write(newspec) }
120
+ end
121
+
122
+ def zip_upload_static_server
123
+ Dir.chdir(@target_path)
124
+ `zip -r #{@spec.name}-#{@spec.version}.zip *`
125
+ if $?.exitstatus != 0
126
+ UI.puts "#{@target_path} zip failed"
127
+ else
128
+ upload_ftp_server
129
+ end
130
+ end
131
+
132
+ def upload_ftp_server
133
+ Net::SFTP.start('10.0.2.77','devuser',:password => 'love1993') do |ftp|
134
+ ftp.open("/home/devuser/local/www/staticpods/#{@spec.name}") do |response|
135
+ if response.ok?
136
+ sftp_upload(ftp)
137
+ else
138
+ ftp.mkdir!("/home/devuser/local/www/staticpods/#{@spec.name}")
139
+ sftp_upload(ftp)
140
+ end
141
+ end
142
+ end
143
+ end
144
+ def sftp_upload(ftp)
145
+ local_path = "#{@target_path}/#{@spec.name}-#{@spec.version}.zip"
146
+ remote_path = "/home/devuser/local/www/staticpods/#{@spec.name}/#{@spec.name}-#{@spec.version}.zip"
147
+ ftp.upload!(local_path,remote_path) do |event ,uploader,*args|
148
+ case event
149
+ when :open
150
+ # args[0] : file metadata
151
+ UI.puts "framework starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
152
+ when :put
153
+ # args[0] : file metadata
154
+ # args[1] : byte offset in remote file
155
+ # args[2] : data being written (as string)
156
+ UI.puts "framework writing to #{args[0].remote}"
157
+ when :close
158
+ # args[0] : file metadata
159
+ UI.puts "framework finished with #{args[0].remote}"
160
+ when :mkdir
161
+ # args[0] : remote path name
162
+ UI.puts "framework creating directory #{args[0]}"
163
+ when :finish
164
+ UI.puts "framework all done!"
165
+ else
166
+ UI.puts "encounter unknown case"
167
+ end
168
+ end
169
+ end
170
+ def create_target_directory
171
+ target_dir = "#{@source_dir}/#{@spec.name}-#{@spec.version}"
172
+ if File.exist? target_dir
173
+ if @force
174
+ Pathname.new(target_dir).rmtree
175
+ else
176
+ UI.puts "Target directory '#{target_dir}' already exists."
177
+ return nil
178
+ end
179
+ end
180
+ @target_path = target_dir
181
+ target_dir
182
+ end
183
+
184
+ def create_working_directory
185
+ target_dir = create_target_directory
186
+ return if target_dir.nil?
187
+
188
+ work_dir = Dir.tmpdir + '/cocoapods-' + Array.new(8) { rand(36).to_s(36) }.join
189
+ Pathname.new(work_dir).mkdir
190
+ Dir.chdir(work_dir)
191
+
192
+ [target_dir, work_dir]
193
+ end
194
+
195
+ def perform_build(platform, static_sandbox, dynamic_sandbox, static_installer)
196
+ static_sandbox_root = config.sandbox_root.to_s
197
+
198
+ if @dynamic
199
+ static_sandbox_root = "#{static_sandbox_root}/#{static_sandbox.root.to_s.split('/').last}"
200
+ dynamic_sandbox_root = "#{config.sandbox_root}/#{dynamic_sandbox.root.to_s.split('/').last}"
201
+ end
202
+
203
+ builder = Pod::Builder.new(
204
+ platform,
205
+ static_installer,
206
+ @source_dir,
207
+ static_sandbox_root,
208
+ dynamic_sandbox_root,
209
+ static_sandbox.public_headers.root,
210
+ @spec,
211
+ @embedded,
212
+ @mangle,
213
+ @dynamic,
214
+ @config,
215
+ @bundle_identifier,
216
+ @exclude_deps
217
+ )
218
+
219
+ builder.build(@package_type)
220
+
221
+ return unless @embedded
222
+ builder.link_embedded_resources
223
+ end
224
+ end
225
+ end
226
+ 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
@@ -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
@@ -0,0 +1,359 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ module Pod
4
+
5
+ DONT_CODESIGN = true
6
+
7
+ describe Command::Spec::Package do
8
+ describe 'CLAide' do
9
+ after do
10
+ Dir.glob("KFData-*").each { |dir| Pathname.new(dir).rmtree }
11
+ Dir.glob("NikeKit-*").each { |dir| Pathname.new(dir).rmtree }
12
+ Dir.glob("foo-bar-*").each { |dir| Pathname.new(dir).rmtree }
13
+ Dir.glob("a-*").each { |dir| Pathname.new(dir).rmtree }
14
+ Dir.glob("FH-*").each { |dir| Pathname.new(dir).rmtree }
15
+ end
16
+
17
+ it 'registers itself' do
18
+ Command.parse(%w{ package }).should.be.instance_of Command::Package
19
+ end
20
+
21
+ it 'presents the help if no spec is provided' do
22
+ command = Command.parse(%w{ package })
23
+ should.raise CLAide::Help do
24
+ command.validate!
25
+ end.message.should.match /required/
26
+ end
27
+
28
+ it "errors if it cannot find a spec" do
29
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
30
+
31
+ command = Command.parse(%w{ package KFData })
32
+ should.raise CLAide::Help do
33
+ command.run
34
+ end.message.should.match /Unable to find/
35
+ end
36
+
37
+
38
+ it "should produce a dynamic library when dynamic is specified" do
39
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
40
+
41
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
42
+ command.run
43
+
44
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
45
+ file_command = "file #{lib}"
46
+ output = `#{file_command}`.lines.to_a
47
+
48
+ output[0].should.match /Mach-O universal binary with 5 architectures/
49
+ output[1].should.match /Mach-O dynamically linked shared library i386/
50
+ end
51
+
52
+ it "should produce a dSYM when dynamic is specified" do
53
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
54
+
55
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
56
+ command.run
57
+
58
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework.dSYM/Contents/Resources/DWARF/NikeKit").first
59
+ file_command = "file #{lib}"
60
+ output = `#{file_command}`.lines.to_a
61
+
62
+ output[0].should.match /Mach-O universal binary with 3 architectures/
63
+ output[1].should.match /Mach-O dSYM companion file arm/
64
+ end
65
+
66
+ it "should link category symbols when dynamic is specified" do
67
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
68
+
69
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
70
+ command.run
71
+
72
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
73
+ file_command = "nm #{lib}"
74
+ output = `#{file_command}`.lines.to_a
75
+
76
+ match = output.detect { |line| line =~ /UIButton\(AFNetworking\)/ }
77
+ match.should.not.be.empty
78
+ end
79
+
80
+ it "should produce a dynamic library for OSX when dynamic is specified" do
81
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
82
+
83
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic })
84
+ command.run
85
+
86
+ lib = Dir.glob("KFData-*/osx/KFData.framework/KFData").first
87
+ file_command = "file #{lib}"
88
+ output = `#{file_command}`.lines.to_a
89
+
90
+ output[0].should.match /Mach-O 64-bit dynamically linked shared library x86_64/
91
+ end
92
+
93
+ it "should produce a dSYM for OSX when dynamic is specified" do
94
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
95
+
96
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic })
97
+ command.run
98
+
99
+ lib = Dir.glob("KFData-*/osx/KFData.framework.dSYM/Contents/Resources/DWARF/KFData").first
100
+ file_command = "file #{lib}"
101
+ output = `#{file_command}`.lines.to_a
102
+
103
+ output[0].should.match /Mach-O 64-bit dSYM companion file x86_64/
104
+ end
105
+
106
+ it "should produce the default plist for iOS and OSX when --dynamic is specified but --bundle-identifier is not" do
107
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
108
+
109
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic})
110
+ command.run
111
+
112
+ ios_plist = File.expand_path(Dir.glob("KFData-*/ios/KFData.framework/Info.plist").first)
113
+ osx_plist = File.expand_path(Dir.glob("KFData-*/osx/KFData.framework/Resources/Info.plist").first)
114
+
115
+ ios_bundle_id = `defaults read #{ios_plist} CFBundleIdentifier`
116
+ osx_bundle_id = `defaults read #{osx_plist} CFBundleIdentifier`
117
+
118
+ ios_bundle_id.should.match /org.cocoapods.KFData/
119
+ osx_bundle_id.should.match /org.cocoapods.KFData/
120
+ end
121
+
122
+ it "should produce the correct plist for iOS and OSX when --dynamic and --bundle-identifier are specified" do
123
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
124
+
125
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic --bundle-identifier=com.example.KFData})
126
+ command.run
127
+
128
+ ios_plist = File.expand_path(Dir.glob("KFData-*/ios/KFData.framework/Info.plist").first)
129
+ osx_plist = File.expand_path(Dir.glob("KFData-*/osx/KFData.framework/Resources/Info.plist").first)
130
+
131
+ ios_bundle_id = `defaults read #{ios_plist} CFBundleIdentifier`
132
+ osx_bundle_id = `defaults read #{osx_plist} CFBundleIdentifier`
133
+
134
+ ios_bundle_id.should.match /com.example.KFData/
135
+ osx_bundle_id.should.match /com.example.KFData/
136
+ end
137
+
138
+ it "should produce a static library when dynamic is not specified" do
139
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
140
+
141
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
142
+ command.run
143
+
144
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
145
+ file_command = "file #{lib}"
146
+ output = `#{file_command}`.lines.to_a
147
+
148
+ output[0].should.match /Mach-O universal binary with 5 architectures/
149
+ output[1].should.match /current ar archive/
150
+ end
151
+
152
+ it "mangles symbols if the Pod has dependencies" do
153
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
154
+
155
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
156
+ command.run
157
+
158
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
159
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /PodNikeKit/ }
160
+
161
+ symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager
162
+ BBUNikePlusTag }
163
+ end
164
+
165
+ it "mangles symbols if the Pod has dependencies and framework is dynamic" do
166
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
167
+
168
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
169
+ command.run
170
+
171
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
172
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /PodNikeKit/ }
173
+
174
+ symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager
175
+ BBUNikePlusTag NikeKitVersionNumber NikeKitVersionString }
176
+ end
177
+
178
+ it "mangles symbols if the Pod has dependencies regardless of name" do
179
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
180
+
181
+ command = Command.parse(%w{ package spec/fixtures/a.podspec })
182
+ command.run
183
+
184
+ lib = Dir.glob("a-*/ios/a.framework/a").first
185
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /Poda/ }
186
+ symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager
187
+ BBUNikePlusTag }
188
+ end
189
+
190
+ it "does not mangle symbols if option --no-mangle is specified" do
191
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
192
+
193
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --no-mangle })
194
+ command.run
195
+
196
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
197
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /PodNikeKit/ }
198
+ symbols.should == []
199
+ end
200
+
201
+ it "does not mangle symbols if option --no-mangle and --dynamic are specified" do
202
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
203
+
204
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --no-mangle --dynamic })
205
+ command.run
206
+
207
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
208
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /PodNikeKit/ }
209
+ symbols.should == []
210
+ end
211
+
212
+ it "does not include symbols from dependencies if option --exclude-deps is specified" do
213
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
214
+
215
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --exclude-deps })
216
+ command.run
217
+
218
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
219
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /AFNetworking|ISO8601DateFormatter|KZPropertyMapper/ }
220
+ symbols.should == []
221
+ end
222
+
223
+ it "includes the correct architectures when packaging an iOS Pod" do
224
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
225
+
226
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
227
+ command.run
228
+
229
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
230
+ `lipo #{lib} -verify_arch x86_64 i386 armv7 armv7s arm64`
231
+ $?.success?.should == true
232
+ end
233
+
234
+ it "includes the correct architectures when packaging an iOS Pod as --dynamic" do
235
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
236
+
237
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
238
+ command.run
239
+
240
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
241
+ `lipo #{lib} -verify_arch armv7 armv7s arm64`
242
+ $?.success?.should == true
243
+ end
244
+
245
+ it "includes Bitcode for device arch slices when packaging an iOS Pod" do
246
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
247
+
248
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
249
+ command.run
250
+
251
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
252
+
253
+ #Check for __LLVM segment in each device architecture
254
+ `lipo -extract armv7 #{lib} -o armv7.a && otool -l armv7.a`.should.match /__LLVM/
255
+ `lipo -extract armv7s #{lib} -o armv7s.a && otool -l armv7s.a`.should.match /__LLVM/
256
+ `lipo -extract arm64 #{lib} -o arm64.a && otool -l arm64.a`.should.match /__LLVM/
257
+ `rm armv7.a armv7s.a arm64.a`
258
+ end
259
+
260
+ it "includes Bitcode for device arch slices when packaging an dynamic iOS Pod" do
261
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
262
+
263
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
264
+ command.run
265
+
266
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
267
+
268
+ #Check for __LLVM segment in each device architecture
269
+ `lipo -extract armv7 #{lib} -o armv7.a && otool -l armv7.a`.should.match /__LLVM/
270
+ `lipo -extract armv7s #{lib} -o armv7s.a && otool -l armv7s.a`.should.match /__LLVM/
271
+ `lipo -extract arm64 #{lib} -o arm64.a && otool -l arm64.a`.should.match /__LLVM/
272
+ `rm armv7.a armv7s.a arm64.a`
273
+ end
274
+
275
+ it "does not include Bitcode for simulator arch slices when packaging an iOS Pod" do
276
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
277
+
278
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
279
+ command.run
280
+
281
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
282
+
283
+ #Check for __LLVM segment in each simulator architecture
284
+ `lipo -extract i386 #{lib} -o i386.a && otool -l i386.a`.should.not.match /__LLVM/
285
+ `lipo -extract x86_64 #{lib} -o x86_64.a && otool -l x86_64.a`.should.not.match /__LLVM/
286
+ `rm i386.a x86_64.a`
287
+ end
288
+
289
+ it "does not include Bitcode for simulator arch slices when packaging an dynamic iOS Pod" do
290
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
291
+
292
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
293
+ command.run
294
+
295
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
296
+
297
+ #Check for __LLVM segment in each simulator architecture
298
+ `lipo -extract i386 #{lib} -o i386.a && otool -l i386.a`.should.not.match /__LLVM/
299
+ `lipo -extract x86_64 #{lib} -o x86_64.a && otool -l x86_64.a`.should.not.match /__LLVM/
300
+ `rm i386.a x86_64.a`
301
+ end
302
+
303
+ it "does not include local ModuleCache references" do
304
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
305
+
306
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
307
+ command.run
308
+
309
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
310
+
311
+ #Check for ModuleCache references
312
+ `strings #{lib}`.should.not.match /ModuleCache/
313
+ end
314
+
315
+ it "does not fail when the pod name contains a dash" do
316
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
317
+
318
+ command = Command.parse(%w{ package spec/fixtures/foo-bar.podspec })
319
+ command.run
320
+
321
+ true.should == true # To make the test pass without any shoulds
322
+ end
323
+
324
+ it "runs with a path to a spec" do
325
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
326
+
327
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec })
328
+ command.run
329
+
330
+ true.should == true # To make the test pass without any shoulds
331
+ end
332
+
333
+ it "it respects module_map directive" do
334
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
335
+
336
+ command = Command.parse(%w{ package spec/fixtures/FH.podspec })
337
+ command.run
338
+
339
+ modulemap_contents = File.read(Dir.glob("FH-*/ios/FH.framework/Modules/module.modulemap").first)
340
+ module_map = <<MAP
341
+ framework module FH {
342
+ umbrella header "FeedHenry.h"
343
+
344
+ export *
345
+ module * { export * }
346
+ }
347
+ MAP
348
+ modulemap_contents.should == module_map
349
+ end
350
+
351
+ # it "runs with a spec in the master repository" do
352
+ # command = Command.parse(%w{ package KFData })
353
+ # command.run
354
+ #
355
+ # true.should == true # To make the test pass without any shoulds
356
+ # end
357
+ end
358
+ end
359
+ end