class Pod::Installer

a force disable option for integral

a option to disable install complete message

Public Class Methods

disable_install_complete_message(value) click to toggle source
# File lib/cocoapods-hd/helper/feature_switches.rb, line 68
def self.disable_install_complete_message(value)
  @@disable_install_complete_message = value
end
force_disable_integration(value) click to toggle source
# File lib/cocoapods-hd/helper/feature_switches.rb, line 52
def self.force_disable_integration(value)
  @@force_disable_integration = value
end

Public Instance Methods

have_exact_prebuild_cache?() click to toggle source

check if need to prebuild

# File lib/cocoapods-hd/prebuild.rb, line 36
def have_exact_prebuild_cache?
  # check if need build frameworks
  return false if local_manifest == nil

  changes = prebuild_pods_changes
  added = changes.added
  changed = changes.changed
  unchanged = changes.unchanged
  deleted = changes.deleted

  exsited_framework_pod_names = sandbox.exsited_framework_pod_names
  missing = unchanged.select do |pod_name|
    not exsited_framework_pod_names.include?(pod_name)
  end

  needed = (added + changed + deleted + missing)
  return needed.empty?
end
install_when_cache_hit!() click to toggle source

The install method when have completed cache

# File lib/cocoapods-hd/prebuild.rb, line 56
def install_when_cache_hit!
  # just print log
  self.sandbox.exsited_framework_target_names.each do |name|
    UI.puts "Using #{name}"
  end
end
prebuild_frameworks!() click to toggle source

Build the needed framework files

# File lib/cocoapods-hd/prebuild.rb, line 64
def prebuild_frameworks!

  # build options
  sandbox_path = sandbox.root
  existed_framework_folder = sandbox.generate_framework_path
  bitcode_enabled = Pod::Podfile::DSL.bitcode_enabled

  if local_manifest != nil

    changes = prebuild_pods_changes
    added = changes.added
    changed = changes.changed
    unchanged = changes.unchanged
    deleted = changes.deleted

    existed_framework_folder.mkdir unless existed_framework_folder.exist?
    exsited_framework_pod_names = sandbox.exsited_framework_pod_names

    # additions
    missing = unchanged.select do |pod_name|
      not exsited_framework_pod_names.include?(pod_name)
    end

    root_names_to_update = (added + changed + missing)

    # transform names to targets
    cache = []
    targets = root_names_to_update.map do |pod_name|
      tars = Pod.fast_get_targets_for_pod_name(pod_name, self.pod_targets, cache)
      if tars.nil? || tars.empty?
        raise "There's no target named (#{pod_name}) in Pod.xcodeproj.\n #{self.pod_targets.map(&:name)}" if t.nil?
      end
      tars
    end.flatten

    # add the dendencies
    dependency_targets = targets.map { |t| t.recursive_dependent_targets }.flatten.uniq || []
    targets = (targets + dependency_targets).uniq
  else
    targets = self.pod_targets
  end

  # STDERR.puts "targets ------- : #{targets}".cyan
  # 移除local target, ps: HDTestKit
  # targets = targets.reject { |pod_target| sandbox.local?(pod_target.pod_name) }

  unless Prebuild::Passer.target_names.nil?
    targets = targets.select { |pod_target| Prebuild::Passer.target_names.include? pod_target.pod_name }
  end

  Pod::UI.puts "Prebuild frameworks (total #{targets.count})"
  Pod::Prebuild.remove_build_dir(sandbox_path)

  targets.each do |target|

    STDERR.puts "开始build: #{target.name} ,should_build: #{target.should_build?} "

    # fix: 注释掉下面方法,否则Pod::Prebuild.build不执行
    if !target.should_build?
      # STDERR.puts "prebuilding: --------- #{target.label}"
      next
    end

    output_path = sandbox.framework_folder_path_for_target_name(target.name)
    output_path.mkpath unless output_path.exist?
    STDERR.puts "output_path : ------ #{output_path}".yellow

    Pod::Prebuild.build(sandbox_path, target, output_path, bitcode_enabled, Podfile::DSL.custom_build_options, Podfile::DSL.custom_build_options_simulator)

    # save the resource paths for later installing
    if !target.resource_paths.empty?
      # fix:  framework_path 添加 target.name
      framework_path = output_path + target.framework_name
      standard_sandbox_path = sandbox.standard_sanbox_path

      resources = begin
                    if Pod::VERSION.start_with? "1.5"
                      target.resource_paths
                    else
                      # resource_paths is Hash{String=>Array<String>} on 1.6 and above
                      # (use AFNetworking to generate a demo data)
                      # https://github.com/leavez/cocoapods-binary/issues/50
                      target.resource_paths.values.flatten
                    end
                  end
      raise "Wrong type: #{resources}" unless resources.kind_of? Array

      path_objects = resources.map do |path|
        object = Prebuild::Passer::ResourcePath.new
        object.real_file_path = framework_path + File.basename(path)
        STDERR.puts "framework_path------ #{framework_path}".yellow

        object.target_file_path = path.gsub('${PODS_ROOT}', standard_sandbox_path.to_s + "/_Prebuild") if path.start_with? '${PODS_ROOT}'
        # object.target_file_path = path.gsub('${PODS_ROOT}', standard_sandbox_path.to_s) if path.start_with? '${PODS_ROOT}'
        # object.target_file_path = path.gsub("${PODS_CONFIGURATION_BUILD_DIR}", standard_sandbox_path.to_s) if path.start_with? "${PODS_CONFIGURATION_BUILD_DIR}"
        object
      end
      Prebuild::Passer.resources_to_copy_for_static_framework[target.name] = path_objects
    end

  end

  # copy vendored libraries and frameworks
  targets.each do |target|
    root_path = self.sandbox.pod_dir(target.name)
    target_folder = sandbox.framework_folder_path_for_target_name(target.name)

    # If target shouldn't build, we copy all the original files
    # This is for target with only .a and .h files

    if not target.should_build?
      Prebuild::Passer.target_names_to_skip_integration_framework << target.name
      STDERR.puts "copy vendored libraries and frameworks ------ #{root_path}, #{target_folder}".yellow
      FileUtils.cp_r(root_path, target_folder, :remove_destination => true)
      next
    end

    target.spec_consumers.each do |consumer|
      file_accessor = Sandbox::FileAccessor.new(root_path, consumer)
      lib_paths = file_accessor.vendored_frameworks || []
      lib_paths += file_accessor.vendored_libraries

      # @TODO dSYM files
      lib_paths.each do |lib_path|
        relative = lib_path.relative_path_from(root_path)
        destination = target_folder + relative
        UI.puts "destination -------  #{destination}"
        destination.dirname.mkpath unless destination.dirname.exist?
        FileUtils.cp_r(lib_path, destination, :remove_destination => true)
      end

      # 将destination替换成target_folder,不需要全路径还原
      # 需要将外部依赖的vendored_frameworks和vendored_libraries复制到target的同级目录中
      lib_paths.each do |lib_path|
        UI.puts "lib_path -----  #{lib_path}"
        relative = lib_path.relative_path_from(root_path)
        destination = target_folder + relative
        destination.dirname.mkpath unless destination.dirname.exist?
        FileUtils.cp_r(lib_path, target_folder, :remove_destination => true)
      end

    end
  end

  targets.each do |target|
    target_name = target.name
    module_name = target.product_module_name
    hash = Prebuild::Passer.resources_to_copy_for_static_framework || {}
    # 将podspec.resource资源复制到framework里面 ps: SVProgerssHUD
    path_objects = hash[target_name]
    if path_objects != nil
      path_objects.each do |object|
        if object.target_file_path != nil
          UI.puts "target_file_path ---  #{object.target_file_path}"
          UI.puts "real_file_path ------  #{object.real_file_path}"
          FileUtils.cp_r(object.target_file_path, object.real_file_path, :remove_destination => true)
        end
      end
    end

    output_path = sandbox.framework_folder_path_for_target_name(target.name)
    output_path.mkpath unless output_path.exist?

    sandbox_root = Pathname(sandbox_path)
    build_dir = sandbox_root.parent + 'build'

    bundle_path = "#{build_dir}/Release-iphoneos/#{module_name}/*.bundle"
    if Dir[bundle_path].any?
      FileUtils.cp_r Dir.glob(bundle_path), output_path, verbose: true
    end

    originPath = Dir.pwd

    Dir.chdir(output_path) {

      zipTargetFramework = "#{target_name}.zip"
      frameworkFileType = "#{output_path}/*.framework"
      bundleFileType = "#{output_path}/*.bundle"
      staticLibraryFileType = "#{output_path}/*.a"
      zipFiles = ""
      if Dir[bundleFileType].any?
        zipFiles += " *.bundle "
      end
      if Dir[frameworkFileType].any?
        zipFiles += " *.framework "
      end
      if Dir[staticLibraryFileType].any?
        zipFiles += " *.a "
      end
      # puts "output_path: zipTargetFramework--------  #{output_path}, #{zipTargetFramework}, zipfile: #{zipFiles}"
      `zip -r #{zipTargetFramework} #{zipFiles}`
      %x[`cd #{originPath}`]
    }

  end
  Pod::Prebuild.remove_build_dir(sandbox_path)

  # 上传zip包和二进制repo
  targets.each do |target|
    root_spec = target.specs.select { |spec|
      spec.root?
    }.first

    UI.puts "上传zip包和二进制repo -------  #{root_spec}"

    if !root_spec.nil?
      #output_path:  ~/Example/Pods/_Prebuild/GeneratedFrameworks/MBProgressHUD
      output_path = sandbox.framework_folder_path_for_target_name(target.name)
      output_path.mkpath unless output_path.exist?
      UI.puts "output_path -------  #{output_path}"

      # 上传二进库的podspec
      upload_binary(root_spec, output_path)
    end

  end

  # save the pod_name for prebuild framwork in sandbox
  targets.each do |target|
    sandbox.save_pod_name_for_target target
  end

  # Remove useless files
  # remove useless pods
  all_needed_names = self.pod_targets.map(&:name).uniq
  useless_target_names = sandbox.exsited_framework_target_names.reject do |name|
    all_needed_names.include? name
  end
  useless_target_names.each do |name|
    path = sandbox.framework_folder_path_for_target_name(name)
    path.rmtree if path.exist?
  end

  if not Podfile::DSL.dont_remove_source_code
    # only keep manifest.lock and framework folder in _Prebuild
    to_remain_files = ["Manifest.lock", File.basename(existed_framework_folder)]
    to_delete_files = sandbox_path.children.select do |file|
      filename = File.basename(file)
      not to_remain_files.include?(filename)
    end
    to_delete_files.each do |path|
      path.rmtree if path.exist?
    end
  else
    # just remove the tmp files
    path = sandbox.root + 'Manifest.lock.tmp'
    path.rmtree if path.exist?
  end

end
prebuild_pod_names() click to toggle source

the root names who needs prebuild, including dependency pods.

# File lib/cocoapods-hd/helper/podfile_options.rb, line 101
def prebuild_pod_names 
   @prebuild_pod_names ||= self.prebuild_pod_targets.map(&:pod_name)
end
prebuild_pod_targets() click to toggle source
# File lib/cocoapods-hd/helper/podfile_options.rb, line 71
def prebuild_pod_targets
    @prebuild_pod_targets ||= (
    all = []

    aggregate_targets = self.aggregate_targets
    aggregate_targets.each do |aggregate_target|
        target_definition = aggregate_target.target_definition
        targets = aggregate_target.pod_targets || []

        # filter prebuild
        prebuild_names = target_definition.prebuild_framework_pod_names
        if not Podfile::DSL.is_all_binary
            targets = targets.select { |pod_target| prebuild_names.include?(pod_target.pod_name) } 
        end
        dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
        targets = (targets + dependency_targets).uniq

        # filter should not prebuild
        explict_should_not_names = target_definition.should_not_prebuild_framework_pod_names
        targets = targets.reject { |pod_target| explict_should_not_names.include?(pod_target.pod_name) } 

        all += targets
    end

    all = all.reject {|pod_target| sandbox.local?(pod_target.pod_name) }
    all.uniq
    )
end
upload_binary(root_spec, output_path) click to toggle source

上传二进库

# File lib/cocoapods-hd/prebuild.rb, line 316
def upload_binary(root_spec, output_path)
  puts "开始上传 ------------------------------- "
  upload_helper = CocoapodsHd::UploadHelper.new(root_spec, output_path)
  upload_helper.spec_creator
  upload_helper.upload
end
validate_every_pod_only_have_one_form() click to toggle source
# File lib/cocoapods-hd/helper/podfile_options.rb, line 106
def validate_every_pod_only_have_one_form

    multi_targets_pods = self.pod_targets.group_by do |t|
        t.pod_name
    end.select do |k, v|
        v.map{|t| t.platform.name }.count > 1
    end

    multi_targets_pods = multi_targets_pods.reject do |name, targets|
        contained = targets.map{|t| self.prebuild_pod_targets.include? t }
        contained.uniq.count == 1 # all equal
    end

    return if multi_targets_pods.empty?

    warnings = "One pod can only be prebuilt or not prebuilt. These pod have different forms in multiple targets:\n"
    warnings += multi_targets_pods.map{|name, targets| "         #{name}: #{targets.map{|t|t.platform.name}}"}.join("\n")
    raise Informative, warnings
end

Private Instance Methods

local_manifest() click to toggle source
# File lib/cocoapods-hd/prebuild.rb, line 12
def local_manifest
  if not @local_manifest_inited
    @local_manifest_inited = true
    raise "This method should be call before generate project" unless self.analysis_result == nil
    @local_manifest = self.sandbox.manifest
  end
  @local_manifest
end
prebuild_pods_changes() click to toggle source

@return [Analyzer::SpecsState]

# File lib/cocoapods-hd/prebuild.rb, line 22
def prebuild_pods_changes
  return nil if local_manifest.nil?
  if @prebuild_pods_changes.nil?
    changes = local_manifest.detect_changes_with_podfile(podfile)
    @prebuild_pods_changes = Analyzer::SpecsState.new(changes)
    # save the chagnes info for later stage
    Pod::Prebuild::Passer.prebuild_pods_changes = @prebuild_pods_changes
  end
  @prebuild_pods_changes
end