class Pod::Command::Package

Public Class Methods

new(argv) click to toggle source
Calls superclass method
# File lib/pod/command/package.rb, line 27
def initialize(argv)
  @embedded = argv.flag?('embedded')
  @force = argv.flag?('force')
  @library = argv.flag?('library')
  @dynamic = argv.flag?('dynamic')
  @mangle = argv.flag?('mangle', true)
  @bundle_identifier = argv.option('bundle-identifier', nil)
  @exclude_deps = argv.flag?('exclude-deps', false)
  @name = argv.shift_argument
  @source = argv.shift_argument
  @spec_sources = argv.option('spec-sources', 'https://github.com/CocoaPods/Specs.git').split(',')

  subspecs = argv.option('subspecs')
  @subspecs = subspecs.split(',') unless subspecs.nil?

  @config = argv.option('configuration', 'Release')

  @source_dir = Dir.pwd
  @spec = spec_with_path(@name)
  @spec = spec_with_name(@name) unless @spec
  super
end
options() click to toggle source
# File lib/pod/command/package.rb, line 11
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.'],
    ['--bundle-identifier', 'Bundle identifier for dynamic framework'],
    ['--exclude-deps', 'Exclude symbols from dependencies.'],
    ['--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 dependant ' \
      'pods from (defaults to https://github.com/CocoaPods/Specs.git)']
  ]
end

Public Instance Methods

run() click to toggle source
# File lib/pod/command/package.rb, line 58
def run
  if @path.nil? || @spec.nil?
    help! 'Unable to find a podspec with path or name.'
    return
  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
validate!() click to toggle source
Calls superclass method
# File lib/pod/command/package.rb, line 50
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
end

Private Instance Methods

binary_only?(spec) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 78
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.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 122
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) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 155
def build_dynamic_target(dynamic_sandbox, static_installer)
  spec_targets = static_installer.pod_targets.select do |target|
    target.name == @spec.name
  end
  static_target = spec_targets[0]

  dynamic_target = Pod::PodTarget.new(static_target.specs, static_target.target_definitions, dynamic_sandbox)
  dynamic_target.host_requires_frameworks = true
  dynamic_target.user_build_configurations = static_target.user_build_configurations
  dynamic_target
end
build_in_sandbox(platform) click to toggle source
# File lib/pod/command/package.rb, line 74
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)
  end

  begin
    perform_build(platform, static_sandbox, dynamic_sandbox)

  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 95
def build_package
  builder = SpecBuilder.new(@spec, @source, @embedded, @dynamic)
  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_supporting_files(_static_sandbox, dynamic_target, _dynamic_sandbox) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 191
def copy_dynamic_supporting_files(_static_sandbox, dynamic_target, _dynamic_sandbox)
  support_dir = Pathname.new(dynamic_target.support_files_dir.to_s.chomp("/#{dynamic_target.name}"))
  support_dir.mkdir
end
copy_dynamic_target(static_sandbox, _dynamic_target, dynamic_sandbox) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 186
def copy_dynamic_target(static_sandbox, _dynamic_target, dynamic_sandbox)
  command = "cp -a #{static_sandbox.root}/#{@spec.name} #{dynamic_sandbox.root}"
  `#{command}`
end
create_target_directory() click to toggle source
# File lib/pod/command/package.rb, line 109
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 122
def create_working_directory
  target_dir = create_target_directory
  return if target_dir.nil?

  work_dir = Dir.tmpdir + '/cocoapods-' + Array.new(8) { rand(36).to_s(36) }.join
  Pathname.new(work_dir).mkdir
  `cp #{@path} #{work_dir}`
  Dir.chdir(work_dir)

  [target_dir, work_dir]
end
install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 129
def install_dynamic_pod(dynamic_sandbox, static_sandbox, static_installer)
  # 1 Create a dynamic target for only the spec pod.
  dynamic_target = build_dynamic_target(dynamic_sandbox, static_installer)

  # 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. Copy the supporting files for the dynamic framework from the static sandbox.
  copy_dynamic_supporting_files(static_sandbox, dynamic_target, dynamic_sandbox)

  # 5. Update the file accecssors.
  dynamic_target = update_file_accessors(dynamic_target, dynamic_sandbox)

  # 6. Create the file references.
  install_file_references(dynamic_sandbox, [dynamic_target], project)

  # 7. Install the target.
  install_library(dynamic_sandbox, dynamic_target)

  # 9. Write the actual Xcodeproject 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 208
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) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 213
def install_library(dynamic_sandbox, dynamic_target)
  return if dynamic_target.target_definitions.flat_map(&:dependencies).empty?
  target_installer = Pod::Installer::Xcode::PodsProjectGenerator::PodTargetInstaller.new(dynamic_sandbox, dynamic_target)
  target_installer.install!

  # Installs System Frameworks
  dynamic_target.file_accessors.each do |file_accessor|
    file_accessor.spec_consumer.frameworks.each do |framework|
      if dynamic_target.should_build?
        dynamic_target.native_target.add_system_framework(framework)
      end
    end

    file_accessor.spec_consumer.libraries.each do |library|
      if dynamic_target.should_build?
        dynamic_target.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(
    File.basename(@path),
    @spec.name,
    platform_name,
    @spec.deployment_target(platform_name),
    @subspecs,
    @spec_sources
  )

  static_installer = Installer.new(sandbox, podfile)
  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) click to toggle source
# File lib/pod/command/package.rb, line 134
def perform_build(platform, static_sandbox, dynamic_sandbox)
  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(
    @source_dir,
    static_sandbox_root,
    dynamic_sandbox_root,
    static_sandbox.public_headers.root,
    @spec,
    @embedded,
    @mangle,
    @dynamic,
    @config,
    @bundle_identifier,
    @exclude_deps
  )

  builder.build(platform, @library)

  return unless @embedded
  builder.link_embedded_resources
end
podfile_from_spec(path, spec_name, platform_name, deployment_target, subspecs, sources) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 41
def podfile_from_spec(path, spec_name, platform_name, deployment_target, subspecs, sources)
  options = {}
  if path
    options[:podspec] = path
  else
    options[:path] = '.'
  end
  options[:subspecs] = subspecs if subspecs
  Pod::Podfile.new do
    sources.each { |s| source s }
    platform(platform_name, deployment_target)
    pod(spec_name, options)

    install!('cocoapods',
             :integrate_targets => false,
             :deterministic_uuids => false)

    target('packager') do
      if path
        if subspecs
          subspecs.each do |subspec|
            pod spec_name + '/' + subspec, :podspec => path
          end
        else
          pod spec_name, :podspec => path
        end
      elsif subspecs
        subspecs.each do |subspec|
          pod spec_name + '/' + subspec, :path => '.'
        end
      else
        pod spec_name, :path => '.'
      end
    end
  end
end
prepare_pods_project(dynamic_sandbox, spec_name, installer) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 167
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)

  dynamic_sandbox.project = pods_project
  pods_project
end
spec_with_name(name) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 91
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 100
def spec_with_path(path)
  return if path.nil? || !Pathname.new(path).exist?

  @path = path

  if Pathname.new(path).directory?
    help! path + ': is a directory.'
    return
  end

  unless ['.podspec', '.json'].include? Pathname.new(path).extname
    help! path + ': is not a podspec.'
    return
  end

  Specification.from_file(path)
end
update_file_accessors(dynamic_target, dynamic_sandbox) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 196
def update_file_accessors(dynamic_target, dynamic_sandbox)
  pod_root = dynamic_sandbox.pod_dir(dynamic_target.root_spec.name)

  path_list = Sandbox::PathList.new(pod_root)
  file_accessors = dynamic_target.specs.map do |spec|
    Sandbox::FileAccessor.new(path_list, spec.consumer(dynamic_target.platform))
  end

  dynamic_target.file_accessors = file_accessors
  dynamic_target
end
write_pod_project(dynamic_project, dynamic_sandbox) click to toggle source
# File lib/cocoapods-packager/pod_utils.rb, line 234
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