cocoapods-fanQiePackager 1.5.0.1

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +11 -0
  6. data/Rakefile +13 -0
  7. data/cocoapods-fanQiePackager.gemspec +25 -0
  8. data/lib/cocoapods-fanQiePackager/builder.rb +321 -0
  9. data/lib/cocoapods-fanQiePackager/framework.rb +66 -0
  10. data/lib/cocoapods-fanQiePackager/mangle.rb +32 -0
  11. data/lib/cocoapods-fanQiePackager/pod_utils.rb +252 -0
  12. data/lib/cocoapods-fanQiePackager/spec_builder.rb +63 -0
  13. data/lib/cocoapods-fanQiePackager/symbols.rb +35 -0
  14. data/lib/cocoapods-fanQiePackager/user_interface/build_failed_report.rb +15 -0
  15. data/lib/cocoapods_fanQiePackager.rb +7 -0
  16. data/lib/cocoapods_plugin.rb +8 -0
  17. data/lib/pod/command/fanqiepackage.rb +169 -0
  18. data/scripts/lstconst.sh +9 -0
  19. data/scripts/lstsym.sh +8 -0
  20. data/spec/command/error_spec.rb +74 -0
  21. data/spec/command/package_spec.rb +359 -0
  22. data/spec/command/subspecs_spec.rb +30 -0
  23. data/spec/fixtures/Builder.podspec +25 -0
  24. data/spec/fixtures/CPDColors.podspec +19 -0
  25. data/spec/fixtures/FH.podspec +18 -0
  26. data/spec/fixtures/KFData.podspec +73 -0
  27. data/spec/fixtures/LibraryConsumerDemo/.gitignore +22 -0
  28. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/project.pbxproj +340 -0
  29. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  30. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer.xcodeproj/xcshareddata/xcschemes/LibraryConsumer.xcscheme +100 -0
  31. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/AppDelegate.h +17 -0
  32. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/AppDelegate.m +27 -0
  33. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/Info.plist +40 -0
  34. data/spec/fixtures/LibraryConsumerDemo/LibraryConsumer/main.m +16 -0
  35. data/spec/fixtures/LibraryConsumerDemo/Podfile +5 -0
  36. data/spec/fixtures/LibraryDemo.podspec +14 -0
  37. data/spec/fixtures/NikeKit.podspec +19 -0
  38. data/spec/fixtures/OpenSans.podspec +18 -0
  39. data/spec/fixtures/PackagerTest/.gitignore +21 -0
  40. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.pbxproj +536 -0
  41. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  42. data/spec/fixtures/PackagerTest/PackagerTest.xcodeproj/xcshareddata/xcschemes/PackagerTest.xcscheme +110 -0
  43. data/spec/fixtures/PackagerTest/PackagerTest.xcworkspace/contents.xcworkspacedata +1 -0
  44. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.h +15 -0
  45. data/spec/fixtures/PackagerTest/PackagerTest/CPDAppDelegate.m +49 -0
  46. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
  47. data/spec/fixtures/PackagerTest/PackagerTest/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
  48. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Info.plist +38 -0
  49. data/spec/fixtures/PackagerTest/PackagerTest/PackagerTest-Prefix.pch +16 -0
  50. data/spec/fixtures/PackagerTest/PackagerTest/en.lproj/InfoPlist.strings +2 -0
  51. data/spec/fixtures/PackagerTest/PackagerTest/main.m +18 -0
  52. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests-Info.plist +22 -0
  53. data/spec/fixtures/PackagerTest/PackagerTestTests/PackagerTestTests.m +34 -0
  54. data/spec/fixtures/PackagerTest/PackagerTestTests/en.lproj/InfoPlist.strings +2 -0
  55. data/spec/fixtures/PackagerTest/Podfile +10 -0
  56. data/spec/fixtures/PackagerTest/Podfile.lock +32 -0
  57. data/spec/fixtures/Weakly.podspec +13 -0
  58. data/spec/fixtures/a.podspec +19 -0
  59. data/spec/fixtures/foo-bar.podspec +19 -0
  60. data/spec/fixtures/layer-client-messaging-schema.podspec +13 -0
  61. data/spec/integration/project_spec.rb +70 -0
  62. data/spec/pod/utils_spec.rb +58 -0
  63. data/spec/spec_helper.rb +50 -0
  64. data/spec/specification/builder_spec.rb +40 -0
  65. data/spec/specification/spec_builder_spec.rb +61 -0
  66. data/spec/user_interface/build_failed_report_spec.rb +11 -0
  67. metadata +203 -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,252 @@
1
+ module Pod
2
+ class Command
3
+ class FanqiePackage < 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'] = 'YES'
33
+ end
34
+ end
35
+ static_installer.pods_project.save
36
+ end
37
+
38
+ static_installer
39
+ end
40
+
41
+ def podfile_from_spec(path, spec_name, platform_name, deployment_target, subspecs, sources)
42
+ options = {}
43
+ if path
44
+ options[:podspec] = path
45
+ else
46
+ options[:path] = '.'
47
+ end
48
+ options[:subspecs] = subspecs if subspecs
49
+ Pod::Podfile.new do
50
+ sources.each { |s| source s }
51
+ platform(platform_name, deployment_target)
52
+ pod(spec_name, options)
53
+
54
+ install!('cocoapods',
55
+ :integrate_targets => false,
56
+ :deterministic_uuids => false)
57
+
58
+ target('packager') do
59
+ if path
60
+ if subspecs
61
+ subspecs.each do |subspec|
62
+ pod spec_name + '/' + subspec, :podspec => path
63
+ end
64
+ else
65
+ pod spec_name, :podspec => path
66
+ end
67
+ elsif subspecs
68
+ subspecs.each do |subspec|
69
+ pod spec_name + '/' + subspec, :path => '.'
70
+ end
71
+ else
72
+ pod spec_name, :path => '.'
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def binary_only?(spec)
79
+ deps = spec.dependencies.map { |dep| spec_with_name(dep.name) }
80
+ [spec, *deps].each do |specification|
81
+ %w(vendored_frameworks vendored_libraries).each do |attrib|
82
+ if specification.attributes_hash[attrib]
83
+ return true
84
+ end
85
+ end
86
+ end
87
+
88
+ false
89
+ end
90
+
91
+ def spec_with_name(name)
92
+ return if name.nil?
93
+
94
+ set = Pod::Config.instance.sources_manager.search(Dependency.new(name))
95
+ return nil if set.nil?
96
+
97
+ set.specification.root
98
+ end
99
+
100
+ def spec_with_path(path)
101
+ return if path.nil? || !Pathname.new(path).exist?
102
+
103
+ @path = path
104
+
105
+ if Pathname.new(path).directory?
106
+ help! path + ': is a directory.'
107
+ return
108
+ end
109
+
110
+ unless ['.podspec', '.json'].include? Pathname.new(path).extname
111
+ help! path + ': is not a podspec.'
112
+ return
113
+ end
114
+
115
+ Specification.from_file(path)
116
+ end
117
+
118
+ #----------------------
119
+ # Dynamic Project Setup
120
+ #----------------------
121
+
122
+ def build_dynamic_sandbox(_static_sandbox, _static_installer)
123
+ dynamic_sandbox_root = Pathname.new(config.sandbox_root + '/Dynamic')
124
+ dynamic_sandbox = Sandbox.new(dynamic_sandbox_root)
125
+
126
+ dynamic_sandbox
127
+ end
128
+
129
+ def install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer)
130
+ # 1 Create a dynamic target for only the spec pod.
131
+ dynamic_target = build_dynamic_target(dynamic_sandbox, static_installer)
132
+
133
+ # 2. Build a new xcodeproj in the dynamic_sandbox with only the spec pod as a target.
134
+ project = prepare_pods_project(dynamic_sandbox, dynamic_target.name, static_installer)
135
+
136
+ # 3. Copy the source directory for the dynamic framework from the static sandbox.
137
+ copy_dynamic_target(static_sandbox, dynamic_target, dynamic_sandbox)
138
+
139
+ # 4. Copy the supporting files for the dynamic framework from the static sandbox.
140
+ copy_dynamic_supporting_files(static_sandbox, dynamic_target, dynamic_sandbox)
141
+
142
+ # 5. Update the file accecssors.
143
+ dynamic_target = update_file_accessors(dynamic_target, dynamic_sandbox)
144
+
145
+ # 6. Create the file references.
146
+ install_file_references(dynamic_sandbox, [dynamic_target], project)
147
+
148
+ # 7. Install the target.
149
+ install_library(dynamic_sandbox, dynamic_target)
150
+
151
+ # 9. Write the actual Xcodeproject to the dynamic sandbox.
152
+ write_pod_project(project, dynamic_sandbox)
153
+ end
154
+
155
+ def build_dynamic_target(dynamic_sandbox, static_installer)
156
+ spec_targets = static_installer.pod_targets.select do |target|
157
+ target.name == @spec.name
158
+ end
159
+ static_target = spec_targets[0]
160
+
161
+ dynamic_target = Pod::PodTarget.new(static_target.specs, static_target.target_definitions, dynamic_sandbox)
162
+ dynamic_target.host_requires_frameworks = true
163
+ dynamic_target.user_build_configurations = static_target.user_build_configurations
164
+ dynamic_target
165
+ end
166
+
167
+ def prepare_pods_project(dynamic_sandbox, spec_name, installer)
168
+ # Create a new pods project
169
+ pods_project = Pod::Project.new(dynamic_sandbox.project_path)
170
+
171
+ # Update build configurations
172
+ installer.analysis_result.all_user_build_configurations.each do |name, type|
173
+ pods_project.add_build_configuration(name, type)
174
+ end
175
+
176
+ # Add the pod group for only the dynamic framework
177
+ local = dynamic_sandbox.local?(spec_name)
178
+ path = dynamic_sandbox.pod_dir(spec_name)
179
+ was_absolute = dynamic_sandbox.local_path_was_absolute?(spec_name)
180
+ pods_project.add_pod_group(spec_name, path, local, was_absolute)
181
+
182
+ dynamic_sandbox.project = pods_project
183
+ pods_project
184
+ end
185
+
186
+ def copy_dynamic_target(static_sandbox, _dynamic_target, dynamic_sandbox)
187
+ command = "cp -a #{static_sandbox.root}/#{@spec.name} #{dynamic_sandbox.root}"
188
+ `#{command}`
189
+ end
190
+
191
+ def copy_dynamic_supporting_files(_static_sandbox, dynamic_target, _dynamic_sandbox)
192
+ support_dir = Pathname.new(dynamic_target.support_files_dir.to_s.chomp("/#{dynamic_target.name}"))
193
+ support_dir.mkdir
194
+ end
195
+
196
+ def update_file_accessors(dynamic_target, dynamic_sandbox)
197
+ pod_root = dynamic_sandbox.pod_dir(dynamic_target.root_spec.name)
198
+
199
+ path_list = Sandbox::PathList.new(pod_root)
200
+ file_accessors = dynamic_target.specs.map do |spec|
201
+ Sandbox::FileAccessor.new(path_list, spec.consumer(dynamic_target.platform))
202
+ end
203
+
204
+ dynamic_target.file_accessors = file_accessors
205
+ dynamic_target
206
+ end
207
+
208
+ def install_file_references(dynamic_sandbox, pod_targets, pods_project)
209
+ installer = Pod::Installer::Xcode::PodsProjectGenerator::FileReferencesInstaller.new(dynamic_sandbox, pod_targets, pods_project)
210
+ installer.install!
211
+ end
212
+
213
+ def install_library(dynamic_sandbox, dynamic_target)
214
+ return if dynamic_target.target_definitions.flat_map(&:dependencies).empty?
215
+ target_installer = Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller.new(dynamic_sandbox, dynamic_target)
216
+ target_installer.install!
217
+
218
+ # Installs System Frameworks
219
+ dynamic_target.file_accessors.each do |file_accessor|
220
+ file_accessor.spec_consumer.frameworks.each do |framework|
221
+ if dynamic_target.should_build?
222
+ dynamic_target.native_target.add_system_framework(framework)
223
+ end
224
+ end
225
+
226
+ file_accessor.spec_consumer.libraries.each do |library|
227
+ if dynamic_target.should_build?
228
+ dynamic_target.native_target.add_system_library(library)
229
+ end
230
+ end
231
+ end
232
+ end
233
+
234
+ def write_pod_project(dynamic_project, dynamic_sandbox)
235
+ UI.message "- Writing Xcode project file to #{UI.path dynamic_sandbox.project_path}" do
236
+ dynamic_project.pods.remove_from_project if dynamic_project.pods.empty?
237
+ dynamic_project.development_pods.remove_from_project if dynamic_project.development_pods.empty?
238
+ dynamic_project.sort(:groups_position => :below)
239
+ dynamic_project.recreate_user_schemes(false)
240
+
241
+ # Edit search paths so that we can find our dependency headers
242
+ dynamic_project.targets.first.build_configuration_list.build_configurations.each do |config|
243
+ config.build_settings['HEADER_SEARCH_PATHS'] = "$(inherited) #{Dir.pwd}/Pods/Static/Headers/**"
244
+ config.build_settings['USER_HEADER_SEARCH_PATHS'] = "$(inherited) #{Dir.pwd}/Pods/Static/Headers/**"
245
+ config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -ObjC'
246
+ end
247
+ dynamic_project.save
248
+ end
249
+ end
250
+ end
251
+ end
252
+ 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,7 @@
1
+ module Pod
2
+ module FanqiePackager
3
+ VERSION = '1.5.0.1'.freeze
4
+ end
5
+ end
6
+
7
+
@@ -0,0 +1,8 @@
1
+ require 'pod/command/fanqiepackage'
2
+ require 'cocoapods-fanQiePackager/user_interface/build_failed_report'
3
+ require 'cocoapods-fanQiePackager/builder'
4
+ require 'cocoapods-fanQiePackager/framework'
5
+ require 'cocoapods-fanQiePackager/mangle'
6
+ require 'cocoapods-fanQiePackager/pod_utils'
7
+ require 'cocoapods-fanQiePackager/spec_builder'
8
+ require 'cocoapods-fanQiePackager/symbols'
@@ -0,0 +1,169 @@
1
+ require 'tmpdir'
2
+ module Pod
3
+ class Command
4
+ class FanqiePackage < Command
5
+ self.summary = 'Fanqie plugin which 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
+ ['--toolchain', 'xcodebuild toolchain (e.g. --toolchain=Byteguard-Bitcode)'],
25
+ ['--logpath', 'Logs path (e.g. --logpath=/Users/username/Desktop/fanqie-package/Logs)']
26
+ ]
27
+ end
28
+
29
+ def initialize(argv)
30
+ @embedded = argv.flag?('embedded')
31
+ @force = argv.flag?('force')
32
+ @library = argv.flag?('library')
33
+ @dynamic = argv.flag?('dynamic')
34
+ @mangle = argv.flag?('mangle', true)
35
+ @bundle_identifier = argv.option('bundle-identifier', nil)
36
+ @exclude_deps = argv.flag?('exclude-deps', false)
37
+ @name = argv.shift_argument
38
+ @source = argv.shift_argument
39
+ @spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',')
40
+
41
+ subspecs = argv.option('subspecs')
42
+ @subspecs = subspecs.split(',') unless subspecs.nil?
43
+
44
+ @config = argv.option('configuration', 'Release')
45
+
46
+ @source_dir = Dir.pwd
47
+ @spec = spec_with_path(@name)
48
+ @spec = spec_with_name(@name) unless @spec
49
+ @toolchain = argv.option('toolchain', '')
50
+ @logpath = argv.option('logpath', "#{Dir.home}/fanqie-package/Logs")
51
+ super
52
+ end
53
+
54
+ def validate!
55
+ super
56
+ help! 'A podspec name or path is required.' unless @spec
57
+ help! 'podspec has binary-only depedencies, mangling not possible.' if @mangle && binary_only?(@spec)
58
+ help! '--bundle-identifier option can only be used for dynamic frameworks' if @bundle_identifier && !@dynamic
59
+ help! '--exclude-deps option can only be used for static libraries' if @exclude_deps && @dynamic
60
+ end
61
+
62
+ def run
63
+ if @path.nil? || @spec.nil?
64
+ help! 'Unable to find a podspec with path or name.'
65
+ return
66
+ end
67
+
68
+ target_dir, work_dir = create_working_directory
69
+ return if target_dir.nil?
70
+ build_package
71
+
72
+ `mv "#{work_dir}" "#{target_dir}"`
73
+ Dir.chdir(@source_dir)
74
+ end
75
+
76
+ private
77
+
78
+ def build_in_sandbox(platform)
79
+ config.installation_root = Pathname.new(Dir.pwd)
80
+ config.sandbox_root = 'Pods'
81
+
82
+ static_sandbox = build_static_sandbox(@dynamic)
83
+ static_installer = install_pod(platform.name, static_sandbox)
84
+
85
+ if @dynamic
86
+ dynamic_sandbox = build_dynamic_sandbox(static_sandbox, static_installer)
87
+ install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer)
88
+ end
89
+
90
+ begin
91
+ perform_build(platform, static_sandbox, dynamic_sandbox)
92
+
93
+ ensure # in case the build fails; see Builder#xcodebuild.
94
+ Pathname.new(config.sandbox_root).rmtree
95
+ FileUtils.rm_f('Podfile.lock')
96
+ end
97
+ end
98
+
99
+ def build_package
100
+ builder = SpecBuilder.new(@spec, @source, @embedded, @dynamic)
101
+ newspec = builder.spec_metadata
102
+
103
+ @spec.available_platforms.each do |platform|
104
+ build_in_sandbox(platform)
105
+
106
+ newspec += builder.spec_platform(platform)
107
+ end
108
+
109
+ newspec += builder.spec_close
110
+ File.open(@spec.name + '.podspec', 'w') { |file| file.write(newspec) }
111
+ end
112
+
113
+ def create_target_directory
114
+ target_dir = "#{@source_dir}/#{@spec.name}-#{@spec.version}"
115
+ if File.exist? target_dir
116
+ if @force
117
+ Pathname.new(target_dir).rmtree
118
+ else
119
+ UI.puts "Target directory '#{target_dir}' already exists."
120
+ return nil
121
+ end
122
+ end
123
+ target_dir
124
+ end
125
+
126
+ def create_working_directory
127
+ target_dir = create_target_directory
128
+ return if target_dir.nil?
129
+
130
+ work_dir = Dir.tmpdir + '/cocoapods-' + Array.new(8) { rand(36).to_s(36) }.join
131
+ Pathname.new(work_dir).mkdir
132
+ `cp #{@path} #{work_dir}`
133
+ Dir.chdir(work_dir)
134
+
135
+ [target_dir, work_dir]
136
+ end
137
+
138
+ def perform_build(platform, static_sandbox, dynamic_sandbox)
139
+ static_sandbox_root = config.sandbox_root.to_s
140
+
141
+ if @dynamic
142
+ static_sandbox_root = "#{static_sandbox_root}/#{static_sandbox.root.to_s.split('/').last}"
143
+ dynamic_sandbox_root = "#{config.sandbox_root}/#{dynamic_sandbox.root.to_s.split('/').last}"
144
+ end
145
+
146
+ builder = Pod::FanqieBuilder.new(
147
+ @source_dir,
148
+ static_sandbox_root,
149
+ dynamic_sandbox_root,
150
+ static_sandbox.public_headers.root,
151
+ @spec,
152
+ @embedded,
153
+ @mangle,
154
+ @dynamic,
155
+ @config,
156
+ @bundle_identifier,
157
+ @exclude_deps,
158
+ @toolchain,
159
+ @logpath
160
+ )
161
+
162
+ builder.build(platform, @library)
163
+
164
+ return unless @embedded
165
+ builder.link_embedded_resources
166
+ end
167
+ end
168
+ end
169
+ end