cocoapods-packager-pro 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) 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 +129 -0
  9. data/LICENSE +22 -0
  10. data/README.md +42 -0
  11. data/Rakefile +12 -0
  12. data/cocoapods-packager.gemspec +22 -0
  13. data/lib/cocoapods-packager/builder.rb +339 -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 +232 -0
  17. data/lib/cocoapods-packager/spec_builder.rb +63 -0
  18. data/lib/cocoapods-packager/symbols.rb +42 -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 +177 -0
  23. data/scripts/lstconst.sh +9 -0
  24. data/scripts/lstsym.sh +8 -0
  25. data/spec/command/error_spec.rb +81 -0
  26. data/spec/command/package_spec.rb +410 -0
  27. data/spec/command/subspecs_spec.rb +30 -0
  28. data/spec/fixtures/Archs.podspec +13 -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 +343 -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/LocalSources/LICENSE +0 -0
  44. data/spec/fixtures/LocalSources/LocalNikeKit.h +4 -0
  45. data/spec/fixtures/LocalSources/LocalNikeKit.m +9 -0
  46. data/spec/fixtures/LocalSources/LocalNikeKit.podspec +19 -0
  47. data/spec/fixtures/NikeKit.podspec +19 -0
  48. data/spec/fixtures/OpenSans.podspec +18 -0
  49. data/spec/fixtures/PackagerTest/.gitignore +21 -0
  50. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.pbxproj +539 -0
  51. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  52. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/xcshareddata/xcschemes/PackagerTest.xcscheme +110 -0
  53. data/spec/fixtures/PackagerTest/PackagerTest.xcworkspace/contents.xcworkspacedata +1 -0
  54. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.h +15 -0
  55. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.m +49 -0
  56. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
  57. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
  58. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Info.plist +38 -0
  59. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Prefix.pch +16 -0
  60. data/spec/fixtures/PackagerTest/PackagerTest/en.lproj/InfoPlist.strings +2 -0
  61. data/spec/fixtures/PackagerTest/PackagerTest/main.m +18 -0
  62. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests-Info.plist +22 -0
  63. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests.m +34 -0
  64. data/spec/fixtures/PackagerTest/PackagerTestTests/en.lproj/InfoPlist.strings +2 -0
  65. data/spec/fixtures/PackagerTest/Podfile +10 -0
  66. data/spec/fixtures/PackagerTest/Podfile.lock +32 -0
  67. data/spec/fixtures/Weakly.podspec +13 -0
  68. data/spec/fixtures/a.podspec +19 -0
  69. data/spec/fixtures/foo-bar.podspec +19 -0
  70. data/spec/fixtures/layer-client-messaging-schema.podspec +13 -0
  71. data/spec/integration/project_spec.rb +70 -0
  72. data/spec/pod/utils_spec.rb +58 -0
  73. data/spec/spec_helper.rb +50 -0
  74. data/spec/specification/builder_spec.rb +43 -0
  75. data/spec/specification/spec_builder_spec.rb +61 -0
  76. data/spec/user_interface/build_failed_report_spec.rb +11 -0
  77. metadata +222 -0
@@ -0,0 +1,5 @@
1
+ module Pod
2
+ module Packager
3
+ VERSION = '1.5.1'.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,177 @@
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
+ ['--local', 'Use local state rather than published versions.'],
19
+ ['--bundle-identifier', 'Bundle identifier for dynamic framework'],
20
+ ['--exclude-deps', 'Exclude symbols from dependencies.'],
21
+ ['--configuration', 'Build the specified configuration (e.g. Debug). Defaults to Release'],
22
+ ['--subspecs', 'Only include the given subspecs'],
23
+ ['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependant ' \
24
+ 'pods from (defaults to https://github.com/CocoaPods/Specs.git)']
25
+ ]
26
+ end
27
+
28
+ def initialize(argv)
29
+ @embedded = argv.flag?('embedded')
30
+ @library = argv.flag?('library')
31
+ @dynamic = argv.flag?('dynamic')
32
+ @local = argv.flag?('local', false)
33
+ @package_type = if @embedded
34
+ :static_framework
35
+ elsif @dynamic
36
+ :dynamic_framework
37
+ elsif @library
38
+ :static_library
39
+ else
40
+ :static_framework
41
+ end
42
+ @force = argv.flag?('force')
43
+ @mangle = argv.flag?('mangle', true)
44
+ @bundle_identifier = argv.option('bundle-identifier', nil)
45
+ @exclude_deps = argv.flag?('exclude-deps', false)
46
+ @name = argv.shift_argument
47
+ @source = argv.shift_argument
48
+ @spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',')
49
+
50
+ subspecs = argv.option('subspecs')
51
+ @subspecs = subspecs.split(',') unless subspecs.nil?
52
+
53
+ @config = argv.option('configuration', 'Release')
54
+
55
+ @source_dir = Dir.pwd
56
+ @is_spec_from_path = false
57
+ @spec = spec_with_path(@name)
58
+ @is_spec_from_path = true if @spec
59
+ @spec ||= spec_with_name(@name)
60
+ super
61
+ end
62
+
63
+ def validate!
64
+ super
65
+ help! 'A podspec name or path is required.' unless @spec
66
+ help! 'podspec has binary-only depedencies, mangling not possible.' if @mangle && binary_only?(@spec)
67
+ help! '--bundle-identifier option can only be used for dynamic frameworks' if @bundle_identifier && !@dynamic
68
+ help! '--exclude-deps option can only be used for static libraries' if @exclude_deps && @dynamic
69
+ help! '--local option can only be used when a local `.podspec` path is given.' if @local && !@is_spec_from_path
70
+ end
71
+
72
+ def run
73
+ if @spec.nil?
74
+ help! 'Unable to find a podspec with path or name.'
75
+ return
76
+ end
77
+
78
+ target_dir, work_dir = create_working_directory
79
+ return if target_dir.nil?
80
+ build_package
81
+
82
+ `mv "#{work_dir}" "#{target_dir}"`
83
+ Dir.chdir(@source_dir)
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)
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
+
112
+ @spec.available_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 create_target_directory
123
+ target_dir = "#{@source_dir}/#{@spec.name}-#{@spec.version}"
124
+ if File.exist? target_dir
125
+ if @force
126
+ Pathname.new(target_dir).rmtree
127
+ else
128
+ UI.puts "Target directory '#{target_dir}' already exists."
129
+ return nil
130
+ end
131
+ end
132
+ target_dir
133
+ end
134
+
135
+ def create_working_directory
136
+ target_dir = create_target_directory
137
+ return if target_dir.nil?
138
+
139
+ work_dir = Dir.tmpdir + '/cocoapods-' + Array.new(8) { rand(36).to_s(36) }.join
140
+ Pathname.new(work_dir).mkdir
141
+ Dir.chdir(work_dir)
142
+
143
+ [target_dir, work_dir]
144
+ end
145
+
146
+ def perform_build(platform, static_sandbox, dynamic_sandbox, static_installer)
147
+ static_sandbox_root = config.sandbox_root.to_s
148
+
149
+ if @dynamic
150
+ static_sandbox_root = "#{static_sandbox_root}/#{static_sandbox.root.to_s.split('/').last}"
151
+ dynamic_sandbox_root = "#{config.sandbox_root}/#{dynamic_sandbox.root.to_s.split('/').last}"
152
+ end
153
+
154
+ builder = Pod::Builder.new(
155
+ platform,
156
+ static_installer,
157
+ @source_dir,
158
+ static_sandbox_root,
159
+ dynamic_sandbox_root,
160
+ static_sandbox.public_headers.root,
161
+ @spec,
162
+ @embedded,
163
+ @mangle,
164
+ @dynamic,
165
+ @config,
166
+ @bundle_identifier,
167
+ @exclude_deps
168
+ )
169
+
170
+ builder.build(@package_type)
171
+
172
+ return unless @embedded
173
+ builder.link_embedded_resources
174
+ end
175
+ end
176
+ end
177
+ 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,81 @@
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 'presents the help if --local is specified without .podspec path' do
46
+ command = Command.parse(%w{ package AFNetworking --local })
47
+ should.raise CLAide::Help do
48
+ command.validate!
49
+ end.message.should.match /--local option can only be used when a local `.podspec` path is given/
50
+ end
51
+
52
+ it 'can package a podspec with only resources' do
53
+ command = Command.parse(%w{ package spec/fixtures/layer-client-messaging-schema.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 binary-only dependencies if --no-mangle is specified' do
60
+ command = Command.parse(%w{ package spec/fixtures/CPDColors.podspec --no-mangle })
61
+ command.run
62
+
63
+ true.should == true # To make the test pass without any shoulds
64
+ end
65
+
66
+ it 'can package a podspec with resource bundles' do
67
+ command = Command.parse(%w{ package spec/fixtures/OpenSans.podspec })
68
+ command.run
69
+
70
+ bundles = Dir.glob('OpenSans-*/ios/OpenSans.framework/Versions/A/Resources/*.bundle')
71
+ bundles.count.should == 1
72
+ end
73
+
74
+ it 'can package a podspec with weak frameworks without strong linking' do
75
+ command = Command.parse(%w{ package spec/fixtures/Weakly.podspec })
76
+ command.run
77
+
78
+ `otool -l Weakly-*/ios/Weakly.framework/Weakly`.should.not.match /AssetsLibrary/
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,410 @@
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("Archs-*").each { |dir| Pathname.new(dir).rmtree }
11
+ Dir.glob("CPDColors-*").each { |dir| Pathname.new(dir).rmtree }
12
+ Dir.glob("KFData-*").each { |dir| Pathname.new(dir).rmtree }
13
+ Dir.glob("NikeKit-*").each { |dir| Pathname.new(dir).rmtree }
14
+ Dir.glob("LocalNikeKit-*").each { |dir| Pathname.new(dir).rmtree }
15
+ Dir.glob("foo-bar-*").each { |dir| Pathname.new(dir).rmtree }
16
+ Dir.glob("a-*").each { |dir| Pathname.new(dir).rmtree }
17
+ Dir.glob("FH-*").each { |dir| Pathname.new(dir).rmtree }
18
+ Dir.glob("FirebaseAnalytics-*").each { |dir| Pathname.new(dir).rmtree }
19
+ end
20
+
21
+ it 'registers itself' do
22
+ Command.parse(%w{ package }).should.be.instance_of Command::Package
23
+ end
24
+
25
+ it 'presents the help if no spec is provided' do
26
+ command = Command.parse(%w{ package })
27
+ should.raise CLAide::Help do
28
+ command.validate!
29
+ end.message.should.match /required/
30
+ end
31
+
32
+ it "errors if it cannot find a spec" do
33
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
34
+
35
+ command = Command.parse(%w{ package KFData })
36
+ should.raise CLAide::Help do
37
+ command.run
38
+ end.message.should.match /Unable to find/
39
+ end
40
+
41
+
42
+ it "should produce a dynamic library when dynamic is specified" do
43
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
44
+
45
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
46
+ command.run
47
+
48
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
49
+ file_command = "file #{lib}"
50
+ output = `#{file_command}`.lines.to_a
51
+
52
+ output[0].should.match /Mach-O universal binary with 5 architectures/
53
+ output[1].should.match /Mach-O dynamically linked shared library i386/
54
+ end
55
+
56
+ it "should produce a dSYM when dynamic is specified" do
57
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
58
+
59
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
60
+ command.run
61
+
62
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework.dSYM/Contents/Resources/DWARF/NikeKit").first
63
+ file_command = "file #{lib}"
64
+ output = `#{file_command}`.lines.to_a
65
+
66
+ output[0].should.match /Mach-O universal binary with 3 architectures/
67
+ output[1].should.match /Mach-O dSYM companion file arm/
68
+ end
69
+
70
+ it "should link category symbols when dynamic is specified" do
71
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
72
+
73
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
74
+ command.run
75
+
76
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
77
+ file_command = "nm #{lib}"
78
+ output = `#{file_command}`.lines.to_a
79
+
80
+ match = output.detect { |line| line =~ /UIButton\(AFNetworking\)/ }
81
+ match.should.not.be.empty
82
+ end
83
+
84
+ it "should produce a dynamic library for OSX when dynamic is specified" do
85
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
86
+
87
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic })
88
+ command.run
89
+
90
+ lib = Dir.glob("KFData-*/osx/KFData.framework/KFData").first
91
+ file_command = "file #{lib}"
92
+ output = `#{file_command}`.lines.to_a
93
+
94
+ output[0].should.match /Mach-O 64-bit dynamically linked shared library x86_64/
95
+ end
96
+
97
+ it "should produce a dSYM for OSX when dynamic is specified" do
98
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
99
+
100
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic })
101
+ command.run
102
+
103
+ lib = Dir.glob("KFData-*/osx/KFData.framework.dSYM/Contents/Resources/DWARF/KFData").first
104
+ file_command = "file #{lib}"
105
+ output = `#{file_command}`.lines.to_a
106
+
107
+ output[0].should.match /Mach-O 64-bit dSYM companion file x86_64/
108
+ end
109
+
110
+ it "should produce the default plist for iOS and OSX when --dynamic is specified but --bundle-identifier is not" do
111
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
112
+
113
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic})
114
+ command.run
115
+
116
+ ios_plist = File.expand_path(Dir.glob("KFData-*/ios/KFData.framework/Info.plist").first)
117
+ osx_plist = File.expand_path(Dir.glob("KFData-*/osx/KFData.framework/Resources/Info.plist").first)
118
+
119
+ ios_bundle_id = `defaults read #{ios_plist} CFBundleIdentifier`
120
+ osx_bundle_id = `defaults read #{osx_plist} CFBundleIdentifier`
121
+
122
+ ios_bundle_id.should.match /org.cocoapods.KFData/
123
+ osx_bundle_id.should.match /org.cocoapods.KFData/
124
+ end
125
+
126
+ it "should produce the correct plist for iOS and OSX when --dynamic and --bundle-identifier are specified" do
127
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
128
+
129
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec --dynamic --bundle-identifier=com.example.KFData})
130
+ command.run
131
+
132
+ ios_plist = File.expand_path(Dir.glob("KFData-*/ios/KFData.framework/Info.plist").first)
133
+ osx_plist = File.expand_path(Dir.glob("KFData-*/osx/KFData.framework/Resources/Info.plist").first)
134
+
135
+ ios_bundle_id = `defaults read #{ios_plist} CFBundleIdentifier`
136
+ osx_bundle_id = `defaults read #{osx_plist} CFBundleIdentifier`
137
+
138
+ ios_bundle_id.should.match /com.example.KFData/
139
+ osx_bundle_id.should.match /com.example.KFData/
140
+ end
141
+
142
+ it "should produce a static library when dynamic is not specified" do
143
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
144
+
145
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
146
+ command.run
147
+
148
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
149
+ file_command = "file #{lib}"
150
+ output = `#{file_command}`.lines.to_a
151
+
152
+ output[0].should.match /Mach-O universal binary with 5 architectures/
153
+ output[1].should.match /current ar archive/
154
+ end
155
+
156
+ it "produces package using local sources when --local is specified" do
157
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
158
+
159
+ command = Command.parse(%w{ package spec/fixtures/LocalSources/LocalNikeKit.podspec --local})
160
+ command.run
161
+
162
+ lib = Dir.glob("LocalNikeKit-*/ios/LocalNikeKit.framework/LocalNikeKit").first
163
+ symbols = Symbols.symbols_from_library(lib)
164
+ symbols.should.include('LocalNikeKit')
165
+ symbols.should.not.include('BBUNikePlusActivity')
166
+ end
167
+
168
+ it "includes vendor symbols both from itself and pod dependencies" do
169
+ command = Command.parse(%w{ package FirebaseAnalytics --no-mangle })
170
+ command.run
171
+
172
+ lib = Dir.glob("FirebaseAnalytics-*/ios/FirebaseAnalytics.framework/FirebaseAnalytics").first
173
+ symbols = Symbols.symbols_from_library(lib)
174
+ # from itself
175
+ symbols.should.include('FIRAnalytics')
176
+ # from pod dependency
177
+ symbols.should.include('FIRApp')
178
+ end
179
+
180
+ it "does not include vendor symbols from pod dependencies if option --exclude-deps is specified" do
181
+ command = Command.parse(%w{ package FirebaseAnalytics --no-mangle --exclude-deps})
182
+ command.run
183
+
184
+ lib = Dir.glob("FirebaseAnalytics-*/ios/FirebaseAnalytics.framework/FirebaseAnalytics").first
185
+ symbols = Symbols.symbols_from_library(lib)
186
+ # from itself
187
+ symbols.should.include('FIRAnalytics')
188
+ # from pod dependency
189
+ symbols.should.not.include('FIRApp')
190
+ end
191
+
192
+ it "includes only available architectures when packaging an iOS Pod with binary dependencies" do
193
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
194
+
195
+ command = Command.parse(%w{ package spec/fixtures/Archs.podspec --no-mangle })
196
+ command.run
197
+
198
+ lib = Dir.glob("Archs-*/ios/Archs.framework/Archs").first
199
+ `lipo #{lib} -verify_arch x86_64 i386 armv7 arm64`
200
+ $?.success?.should == true
201
+ end
202
+
203
+ it "mangles symbols if the Pod has dependencies" do
204
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
205
+
206
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
207
+ command.run
208
+
209
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
210
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /PodNikeKit/ }
211
+
212
+ symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager
213
+ BBUNikePlusTag }
214
+ end
215
+
216
+ it "mangles symbols if the Pod has dependencies and framework is dynamic" do
217
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
218
+
219
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
220
+ command.run
221
+
222
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
223
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /PodNikeKit/ }
224
+
225
+ symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager
226
+ BBUNikePlusTag NikeKitVersionNumber NikeKitVersionString }
227
+ end
228
+
229
+ it "mangles symbols if the Pod has dependencies regardless of name" do
230
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
231
+
232
+ command = Command.parse(%w{ package spec/fixtures/a.podspec })
233
+ command.run
234
+
235
+ lib = Dir.glob("a-*/ios/a.framework/a").first
236
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.reject { |e| e =~ /Poda/ }
237
+ symbols.should == %w{ BBUNikePlusActivity BBUNikePlusSessionManager
238
+ BBUNikePlusTag }
239
+ end
240
+
241
+ it "does not mangle symbols if option --no-mangle is specified" do
242
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
243
+
244
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --no-mangle })
245
+ command.run
246
+
247
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
248
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /PodNikeKit/ }
249
+ symbols.should == []
250
+ end
251
+
252
+ it "does not mangle symbols if option --no-mangle and --dynamic are specified" do
253
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
254
+
255
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --no-mangle --dynamic })
256
+ command.run
257
+
258
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
259
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /PodNikeKit/ }
260
+ symbols.should == []
261
+ end
262
+
263
+ it "does not include symbols from dependencies if option --exclude-deps is specified" do
264
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
265
+
266
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --exclude-deps })
267
+ command.run
268
+
269
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
270
+ symbols = Symbols.symbols_from_library(lib).uniq.sort.select { |e| e =~ /AFNetworking|ISO8601DateFormatter|KZPropertyMapper/ }
271
+ symbols.should == []
272
+ end
273
+
274
+ it "includes the correct architectures when packaging an iOS Pod" do
275
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
276
+
277
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
278
+ command.run
279
+
280
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
281
+ `lipo #{lib} -verify_arch x86_64 i386 armv7 armv7s arm64`
282
+ $?.success?.should == true
283
+ end
284
+
285
+ it "includes the correct architectures when packaging an iOS Pod as --dynamic" do
286
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
287
+
288
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
289
+ command.run
290
+
291
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
292
+ `lipo #{lib} -verify_arch armv7 armv7s arm64`
293
+ $?.success?.should == true
294
+ end
295
+
296
+ it "includes Bitcode for device arch slices when packaging an iOS Pod" do
297
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
298
+
299
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
300
+ command.run
301
+
302
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
303
+
304
+ #Check for __LLVM segment in each device architecture
305
+ `lipo -extract armv7 #{lib} -o armv7.a && otool -l armv7.a`.should.match /__LLVM/
306
+ `lipo -extract armv7s #{lib} -o armv7s.a && otool -l armv7s.a`.should.match /__LLVM/
307
+ `lipo -extract arm64 #{lib} -o arm64.a && otool -l arm64.a`.should.match /__LLVM/
308
+ `rm armv7.a armv7s.a arm64.a`
309
+ end
310
+
311
+ it "includes Bitcode for device arch slices when packaging an dynamic iOS Pod" do
312
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
313
+
314
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
315
+ command.run
316
+
317
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
318
+
319
+ #Check for __LLVM segment in each device architecture
320
+ `lipo -extract armv7 #{lib} -o armv7.a && otool -l armv7.a`.should.match /__LLVM/
321
+ `lipo -extract armv7s #{lib} -o armv7s.a && otool -l armv7s.a`.should.match /__LLVM/
322
+ `lipo -extract arm64 #{lib} -o arm64.a && otool -l arm64.a`.should.match /__LLVM/
323
+ `rm armv7.a armv7s.a arm64.a`
324
+ end
325
+
326
+ it "does not include Bitcode for simulator arch slices when packaging an iOS Pod" do
327
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
328
+
329
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
330
+ command.run
331
+
332
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
333
+
334
+ #Check for __LLVM segment in each simulator architecture
335
+ `lipo -extract i386 #{lib} -o i386.a && otool -l i386.a`.should.not.match /__LLVM/
336
+ `lipo -extract x86_64 #{lib} -o x86_64.a && otool -l x86_64.a`.should.not.match /__LLVM/
337
+ `rm i386.a x86_64.a`
338
+ end
339
+
340
+ it "does not include Bitcode for simulator arch slices when packaging an dynamic iOS Pod" do
341
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
342
+
343
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec --dynamic })
344
+ command.run
345
+
346
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
347
+
348
+ #Check for __LLVM segment in each simulator architecture
349
+ `lipo -extract i386 #{lib} -o i386.a && otool -l i386.a`.should.not.match /__LLVM/
350
+ `lipo -extract x86_64 #{lib} -o x86_64.a && otool -l x86_64.a`.should.not.match /__LLVM/
351
+ `rm i386.a x86_64.a`
352
+ end
353
+
354
+ it "does not include local ModuleCache references" do
355
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
356
+
357
+ command = Command.parse(%w{ package spec/fixtures/NikeKit.podspec })
358
+ command.run
359
+
360
+ lib = Dir.glob("NikeKit-*/ios/NikeKit.framework/NikeKit").first
361
+
362
+ #Check for ModuleCache references
363
+ `strings #{lib}`.should.not.match /ModuleCache/
364
+ end
365
+
366
+ it "does not fail when the pod name contains a dash" do
367
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
368
+
369
+ command = Command.parse(%w{ package spec/fixtures/foo-bar.podspec })
370
+ command.run
371
+
372
+ true.should == true # To make the test pass without any shoulds
373
+ end
374
+
375
+ it "runs with a path to a spec" do
376
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
377
+
378
+ command = Command.parse(%w{ package spec/fixtures/KFData.podspec })
379
+ command.run
380
+
381
+ true.should == true # To make the test pass without any shoulds
382
+ end
383
+
384
+ it "it respects module_map directive" do
385
+ Pod::Config.instance.sources_manager.stubs(:search).returns(nil)
386
+
387
+ command = Command.parse(%w{ package spec/fixtures/FH.podspec })
388
+ command.run
389
+
390
+ modulemap_contents = File.read(Dir.glob("FH-*/ios/FH.framework/Modules/module.modulemap").first)
391
+ module_map = <<MAP
392
+ framework module FH {
393
+ umbrella header "FeedHenry.h"
394
+
395
+ export *
396
+ module * { export * }
397
+ }
398
+ MAP
399
+ modulemap_contents.should == module_map
400
+ end
401
+
402
+ it "runs with a spec in the master repository" do
403
+ command = Command.parse(%w{ package KFData })
404
+ command.run
405
+
406
+ true.should == true # To make the test pass without any shoulds
407
+ end
408
+ end
409
+ end
410
+ end