class Pod::Command::Package
Public Class Methods
new(argv)
click to toggle source
Calls superclass method
# File lib/pod/command/package.rb, line 42 def initialize(argv) @embedded = argv.flag?('embedded') @library = argv.flag?('library') @dynamic = argv.flag?('dynamic') @local = argv.flag?('local', false) @output_dsym = argv.flag?('output-dsym', true) @package_type = if @embedded :static_framework elsif @dynamic :dynamic_framework elsif @library :static_library else :static_framework end @force = argv.flag?('force') @mangle = argv.flag?('mangle', true) @bundle_identifier = argv.option('bundle-identifier', nil) @include_deps = argv.flag?('include-deps', false) @exclude_deps = argv.flag?('exclude-deps', !@include_deps) @auto_fix_conflict = argv.flag?('auto-fix-conflict', true) @disable_force_load = argv.flag?('disable-force-load', false) @force_enable_module = argv.flag?('force-enable-module', false) @name = argv.shift_argument @source = argv.shift_argument @spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',') @local_sources = argv.option('local-sources', '').split(',') @no_repos = argv.flag?('no-repos', false) @repo_update = argv.flag?('repo-update', false) @work_dir = argv.option('work-dir', Dir.tmpdir) @git_source = argv.option('git-source', nil) @xcconfig_path = argv.option('xcconfig-path', nil) subspecs = argv.option('subspecs') @subspecs = subspecs.split(',') unless subspecs.nil? @config = argv.option('configuration', 'Release') @source_dir = Dir.pwd @is_spec_from_path = false @spec = spec_with_path(@name) @is_spec_from_path = true if @spec @spec ||= spec_with_name(@name) @source = "{ :git => \"#{@git_source}\", :tag => s.version.to_s }" unless @git_source.nil? super end
options()
click to toggle source
# File lib/pod/command/package.rb, line 13 def self.options [ ['--force', 'Overwrite existing files.'], ['--no-mangle', 'Do not mangle symbols of depedendant Pods.'], ['--embedded', 'Generate embedded frameworks.'], ['--library', 'Generate static libraries.'], ['--dynamic', 'Generate dynamic framework.'], ['--local', 'Use local state rather than published versions.'], ['--bundle-identifier', 'Bundle identifier for dynamic framework'], ['--exclude-deps', 'Exclude symbols from dependencies. default true'], ['--include-deps', 'Include symbols from dependencies. default false'], ['--configuration', 'Build the specified configuration (e.g. Debug). Defaults to Release'], ['--subspecs', 'Only include the given subspecs'], ['--spec-sources=private,https://github.com/CocoaPods/Specs.git', 'The sources to pull dependent ' \ 'pods from (defaults to https://github.com/CocoaPods/Specs.git)'], ['--auto-fix-conflict', 'fix cocoapods conflict .a or .framework , default is true'], ['--local-sources=./', '相对 podspec 路径,Paths from which to find local podspecs for transitive dependencies. Multiple local-sources must be comma-delimited.' \ 'pods from local'], ['--no-repos', '不自动添加 pod repo list 显示出的 source'], ['--repo-update', 'update repo'], ['--work-dir', 'the dir when build '], ['--git-source', 'framework podspec s.source= '], ['--output-dsym', 'generate dSYM file'], ['--xcconfig-path', 'xcode build xcconfig path'], ['--disable-force-load', 'do not add -force_load flag in spec file xcconfig , default is false'], ['--force-enable-module', 'force create module map file in framework, default if public headers contains \#{spec.name}.h will create umbrella header and module map'], ] end
Public Instance Methods
recursive_subspecs_dependencies(spec)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 99 def recursive_subspecs_dependencies(spec) dependencies = [@spec, *@spec.recursive_subspecs].flat_map do |all_spec| all_spec.dependencies.flat_map do |depency| depency if ! "#{depency}".include? "#{spec.name}" end end.compact.uniq # puts dependencies # dependencies = spec.dependencies || [] # spec.recursive_subspecs.each do |subspec| # subspec.dependencies.each do |depency| # if ! "#{depency}".include? "#{spec.name}" # dependencies << depency # end # end # end dependencies end
run()
click to toggle source
# File lib/pod/command/package.rb, line 99 def run if @spec.nil? help! "Unable to find a podspec with path or name `#{@name}`." return end if !@no_repos if @spec_sources.nil? @spec_sources = [] end config.sources_manager.all.each do |s| @spec_sources << s.url end end if @repo_update update_sources end target_dir, work_dir = create_working_directory return if target_dir.nil? build_package `mv "#{work_dir}" "#{target_dir}"` Dir.chdir(@source_dir) end
transitive_local_dependencies(spec, paths)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 119 def transitive_local_dependencies(spec, paths) dependencies = recursive_subspecs_dependencies(spec) return_list = [] dependencies.each do |dependency| found_podspec_file = nil name = dependency.name.split('/')[0] paths.each do |path| # 展开目录 if path[0] != '/' path = File.expand_path(path, @source_dir) end podspec_file = path + '/' + name + '.podspec' next unless File.file?(podspec_file) found_podspec_file = podspec_file break end next unless found_podspec_file return_list << [dependency, found_podspec_file] dep_spec = Pod::Specification.from_file(found_podspec_file) dep_spec.dependencies.each do |d_dep| dependencies << d_dep unless dependencies.include? d_dep end end return_list end
update_sources()
click to toggle source
# File lib/pod/command/package.rb, line 126 def update_sources UI.title 'Updating specs repos' do @spec_sources.each do |source| source = config.sources_manager.source_with_name_or_url(source) UI.titled_section "Updating spec repo `#{source.name}`" do source.update(config.verbose?) source.verify_compatibility! end end end end
validate!()
click to toggle source
Calls superclass method
# File lib/pod/command/package.rb, line 90 def validate! super help! 'A podspec name or path is required.' unless @spec help! 'podspec has binary-only depedencies, mangling not possible.' if @mangle && binary_only?(@spec) help! '--bundle-identifier option can only be used for dynamic frameworks' if @bundle_identifier && !@dynamic help! '--exclude-deps option can only be used for static libraries' if @exclude_deps && @dynamic help! '--local option can only be used when a local `.podspec` path is given.' if @local && !@is_spec_from_path end
Private Instance Methods
binary_only?(spec)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 146 def binary_only?(spec) deps = spec.dependencies.map { |dep| spec_with_name(dep.name) } [spec, *deps].each do |specification| %w(vendored_frameworks vendored_libraries).each do |attrib| if !specification.nil? && specification.attributes_hash[attrib] return true end end end false end
build_dynamic_sandbox(_static_sandbox, _static_installer)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 193 def build_dynamic_sandbox(_static_sandbox, _static_installer) dynamic_sandbox_root = Pathname.new(config.sandbox_root + '/Dynamic') dynamic_sandbox = Sandbox.new(dynamic_sandbox_root) dynamic_sandbox end
build_dynamic_target(dynamic_sandbox, static_installer, platform)
click to toggle source
@param [Pod::Installer] static_installer
@return [Pod::PodTarget]
# File lib/cocoapods-packager/pod_utils.rb, line 232 def build_dynamic_target(dynamic_sandbox, static_installer, platform) spec_targets = static_installer.pod_targets.select do |target| target.name == @spec.name end static_target = spec_targets[0] file_accessors = create_file_accessors(static_target, dynamic_sandbox) archs = [] dynamic_target = Pod::PodTarget.new(dynamic_sandbox, true, static_target.user_build_configurations, archs, platform, static_target.specs, static_target.target_definitions, file_accessors) dynamic_target end
build_in_sandbox(platform)
click to toggle source
# File lib/pod/command/package.rb, line 140 def build_in_sandbox(platform) config.installation_root = Pathname.new(Dir.pwd) config.sandbox_root = 'Pods' static_sandbox = build_static_sandbox(@dynamic) static_installer = install_pod(platform.name, static_sandbox) if @dynamic dynamic_sandbox = build_dynamic_sandbox(static_sandbox, static_installer) install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer, platform) end begin perform_build(platform, static_sandbox, dynamic_sandbox, static_installer) ensure # in case the build fails; see Builder#xcodebuild. Pathname.new(config.sandbox_root).rmtree FileUtils.rm_f('Podfile.lock') end end
build_package()
click to toggle source
# File lib/pod/command/package.rb, line 160 def build_package builder = SpecBuilder.new(@spec, @source, @embedded, @dynamic, !@disable_force_load) newspec = builder.spec_metadata @spec.available_platforms.each do |platform| build_in_sandbox(platform) newspec += builder.spec_platform(platform) end newspec += builder.spec_close File.open(@spec.name + '.podspec', 'w') { |file| file.write(newspec) } end
build_static_sandbox(dynamic)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 6 def build_static_sandbox(dynamic) static_sandbox_root = if dynamic Pathname.new(config.sandbox_root + '/Static') else Pathname.new(config.sandbox_root) end Sandbox.new(static_sandbox_root) end
copy_dynamic_target(static_sandbox, _dynamic_target, dynamic_sandbox)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 268 def copy_dynamic_target(static_sandbox, _dynamic_target, dynamic_sandbox) command = "cp -a #{static_sandbox.root}/#{@spec.name} #{dynamic_sandbox.root}" `#{command}` end
create_file_accessors(target, dynamic_sandbox)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 273 def create_file_accessors(target, dynamic_sandbox) pod_root = dynamic_sandbox.pod_dir(target.root_spec.name) path_list = Sandbox::PathList.new(pod_root) target.specs.map do |spec| Sandbox::FileAccessor.new(path_list, spec.consumer(target.platform)) end end
create_target_directory()
click to toggle source
# File lib/pod/command/package.rb, line 174 def create_target_directory target_dir = "#{@source_dir}/#{@spec.name}-#{@spec.version}" if File.exist? target_dir if @force Pathname.new(target_dir).rmtree else UI.puts "Target directory '#{target_dir}' already exists." return nil end end target_dir end
create_working_directory()
click to toggle source
# File lib/pod/command/package.rb, line 187 def create_working_directory target_dir = create_target_directory return if target_dir.nil? rootDir = @work_dir if rootDir[0] != '/' rootDir = File.expand_path(rootDir,@source_dir) end if rootDir.nil? rootDir = Dir.tmpdir end # work_dir = rootDir + '/cocoapods-' + Array.new(8) { rand(36).to_s(36) }.join work_dir = rootDir + '/cocoapods-packager-build' if File.exist?(work_dir) FileUtils.rm_rf(work_dir) end # Pathname.new(work_dir).mkdir FileUtils.mkdir_p(work_dir) Dir.chdir(work_dir) [target_dir, work_dir] end
install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer, platform)
click to toggle source
@param [Pod::Sandbox] dynamic_sandbox
@param [Pod::Sandbox] static_sandbox
@param [Pod::Installer] static_installer
@param [Pod::Platform] platform
# File lib/cocoapods-packager/pod_utils.rb, line 208 def install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer, platform) # 1 Create a dynamic target for only the spec pod. dynamic_target = build_dynamic_target(dynamic_sandbox, static_installer, platform) # 2. Build a new xcodeproj in the dynamic_sandbox with only the spec pod as a target. project = prepare_pods_project(dynamic_sandbox, dynamic_target.name, static_installer) # 3. Copy the source directory for the dynamic framework from the static sandbox. copy_dynamic_target(static_sandbox, dynamic_target, dynamic_sandbox) # 4. Create the file references. install_file_references(dynamic_sandbox, [dynamic_target], project) # 5. Install the target. install_library(dynamic_sandbox, dynamic_target, project) # 6. Write the actual .xcodeproj to the dynamic sandbox. write_pod_project(project, dynamic_sandbox) end
install_file_references(dynamic_sandbox, pod_targets, pods_project)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 282 def install_file_references(dynamic_sandbox, pod_targets, pods_project) installer = Pod::Installer::Xcode::PodsProjectGenerator::FileReferencesInstaller.new(dynamic_sandbox, pod_targets, pods_project) installer.install! end
install_library(dynamic_sandbox, dynamic_target, project)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 287 def install_library(dynamic_sandbox, dynamic_target, project) return if dynamic_target.target_definitions.flat_map(&:dependencies).empty? target_installer = Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller.new(dynamic_sandbox, project, dynamic_target) result = target_installer.install! native_target = result.native_target # Installs System Frameworks if dynamic_target.should_build? dynamic_target.file_accessors.each do |file_accessor| file_accessor.spec_consumer.frameworks.each do |framework| native_target.add_system_framework(framework) end file_accessor.spec_consumer.libraries.each do |library| native_target.add_system_library(library) end end end end
install_pod(platform_name, sandbox)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 15 def install_pod(platform_name, sandbox) podfile = podfile_from_spec( @path, @spec.name, platform_name, @spec.deployment_target(platform_name), @subspecs, @spec_sources, @local_sources ) static_installer = TalInstaller.new(sandbox, podfile, @auto_fix_conflict) static_installer.install! unless static_installer.nil? static_installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['CLANG_MODULES_AUTOLINK'] = 'NO' config.build_settings['GCC_GENERATE_DEBUGGING_SYMBOLS'] = 'NO' end end static_installer.pods_project.save end static_installer end
perform_build(platform, static_sandbox, dynamic_sandbox, static_installer)
click to toggle source
# File lib/pod/command/package.rb, line 210 def perform_build(platform, static_sandbox, dynamic_sandbox, static_installer) static_sandbox_root = config.sandbox_root.to_s if @dynamic static_sandbox_root = "#{static_sandbox_root}/#{static_sandbox.root.to_s.split('/').last}" dynamic_sandbox_root = "#{config.sandbox_root}/#{dynamic_sandbox.root.to_s.split('/').last}" end builder = Pod::Builder.new( platform, static_installer, @source_dir, static_sandbox_root, dynamic_sandbox_root, static_sandbox.public_headers.root, @spec, @embedded, @mangle, @dynamic, @config, @bundle_identifier, @exclude_deps, @xcconfig_path, @force_enable_module ) builder.build(@package_type) return unless @embedded builder.link_embedded_resources end
podfile_from_spec(path, spec_name, platform_name, deployment_target, subspecs, sources, local_sources)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 42 def podfile_from_spec(path, spec_name, platform_name, deployment_target, subspecs, sources, local_sources) options = {} if path if @local options[:path] = path else options[:podspec] = path end end options[:subspecs] = subspecs if subspecs generator = self spec_file = @spec source_dir = @source_dir Pod::Podfile.new do sources.each { |s| source s } platform(platform_name, deployment_target) # 此处会自动增加非本地依赖项 pod(spec_name, options) # plugin('cocoapods-packager', {}) # plugin 查看 cocoapods_plugin.rb 文件内定义 # 增加本地 local source generator.transitive_local_dependencies(spec_file, local_sources).each do |dependency, podspec_file| pod_options = {} pod_options[:path] = if podspec_file[0] == '/' # absolute path Pathname.new(podspec_file) else expand_path = File.expand_path(podspec_file,source_dir) Pathname.new(expand_path) end pod dependency.name, **pod_options end install!('cocoapods', :integrate_targets => false, :deterministic_uuids => false) target('packager') do inherit! :complete end post_install do |installer| #设置build setting installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES' config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -ObjC' end end end end end
prepare_pods_project(dynamic_sandbox, spec_name, installer)
click to toggle source
@param [Pod::Sandbox] dynamic_sandbox
@param [String] spec_name
@param [Pod::Installer] installer
# File lib/cocoapods-packager/pod_utils.rb, line 251 def prepare_pods_project(dynamic_sandbox, spec_name, installer) # Create a new pods project pods_project = Pod::Project.new(dynamic_sandbox.project_path) # Update build configurations installer.analysis_result.all_user_build_configurations.each do |name, type| pods_project.add_build_configuration(name, type) end # Add the pod group for only the dynamic framework local = dynamic_sandbox.local?(spec_name) path = dynamic_sandbox.pod_dir(spec_name) was_absolute = dynamic_sandbox.local_path_was_absolute?(spec_name) pods_project.add_pod_group(spec_name, path, local, was_absolute) pods_project end
spec_with_name(name)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 159 def spec_with_name(name) return if name.nil? set = Pod::Config.instance.sources_manager.search(Dependency.new(name)) return nil if set.nil? set.specification.root end
spec_with_path(path)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 168 def spec_with_path(path) return if path.nil? path = Pathname.new(path) path = Pathname.new(Dir.pwd).join(path) unless path.absolute? return unless path.exist? @path = path.expand_path if @path.directory? help! @path + ': is a directory.' return end unless ['.podspec', '.json'].include? @path.extname help! @path + ': is not a podspec.' return end Specification.from_file(@path) end
write_pod_project(dynamic_project, dynamic_sandbox)
click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 306 def write_pod_project(dynamic_project, dynamic_sandbox) UI.message "- Writing Xcode project file to #{UI.path dynamic_sandbox.project_path}" do dynamic_project.pods.remove_from_project if dynamic_project.pods.empty? dynamic_project.development_pods.remove_from_project if dynamic_project.development_pods.empty? dynamic_project.sort(:groups_position => :below) dynamic_project.recreate_user_schemes(false) # Edit search paths so that we can find our dependency headers dynamic_project.targets.first.build_configuration_list.build_configurations.each do |config| config.build_settings['HEADER_SEARCH_PATHS'] = "$(inherited) #{Dir.pwd}/Pods/Static/Headers/**" config.build_settings['USER_HEADER_SEARCH_PATHS'] = "$(inherited) #{Dir.pwd}/Pods/Static/Headers/**" config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -ObjC' end dynamic_project.save end end