Rome icon indicating copy to clipboard operation
Rome copied to clipboard

[Enhancement] Build only missing frameworks (= new pods)

Open absolutlabs opened this issue 8 years ago • 4 comments

Hello

Some pods take a really long time to build (Realm for exemple) , or some Podfile may refer to dozen of pods. Adding a new pod in the Podfile currently means rebuilding every pods.

A cool enhancement would be to build only frameworks that are missing in /Rome folder. or if a new version is available & has been downloaded with Cocoapods

:)

absolutlabs avatar Jul 18 '16 15:07 absolutlabs

Hello

I didn't create a pull request because this is the first time I write in ruby so the code might be ( / may be / is ) ugly :stuck_out_tongue_winking_eye:

It only build new pods (those without corresponding .framework in /Rome folder).

If a new version of a pod is downloaded, it won't be built unless the framework has been previously manually deleted.

post_install.rb

require 'fourflusher'

CONFIGURATION = "Release"
PLATFORMS = { 'iphonesimulator' => 'iOS',
            'appletvsimulator' => 'tvOS',
            'watchsimulator' => 'watchOS' }


def build_for_iosish_platform(sandbox, build_dir, destination, target, device, simulator)
  deployment_target = target.platform_deployment_target
  target_label = target.cocoapods_target_label

  spec_names = target.specs.map { |spec| [spec.root.name, spec.root.module_name] }.uniq
  spec_names.each do |root_name, module_name|

    executable_path = "#{build_dir}/#{root_name}"
    device_lib = "#{build_dir}/#{CONFIGURATION}-#{device}/#{root_name}/#{module_name}.framework/#{module_name}"
    device_framework_lib = File.dirname(device_lib)
    simulator_lib = "#{build_dir}/#{CONFIGURATION}-#{simulator}/#{root_name}/#{module_name}.framework/#{module_name}"
    rome_lib = "#{destination}/#{module_name}.framework"

    if (module_name.start_with?('Pods-') || File.directory?(rome_lib))
        Pod::UI.puts "• Using #{root_name}"
    else
        Pod::UI.puts "→ Building #{root_name}"
        xcodebuild(sandbox, root_name, device, deployment_target)
        xcodebuild(sandbox, root_name, simulator, deployment_target)

        next unless File.file?(device_lib) && File.file?(simulator_lib)

        lipo_log = `lipo -create -output #{executable_path} #{device_lib} #{simulator_lib}`
        puts lipo_log unless File.exist?(executable_path)

        FileUtils.mv executable_path, device_lib
        FileUtils.mv device_framework_lib, build_dir
        FileUtils.rm simulator_lib if File.file?(simulator_lib)
        FileUtils.rm device_lib if File.file?(device_lib)

        end
    end
end


def xcodebuild(sandbox, target, sdk='macosx', deployment_target=nil)
  args = %W(-project #{sandbox.project_path.basename} -scheme #{target} -configuration #{CONFIGURATION} -sdk #{sdk})
  platform = PLATFORMS[sdk]
  args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
  Pod::Executable.execute_command 'xcodebuild', args, true
end


Pod::HooksManager.register('cocoapods-rome', :post_install) do |installer_context|
  Pod::UI.puts "Rome"

  sandbox_root = Pathname(installer_context.sandbox_root)
  sandbox = Pod::Sandbox.new(sandbox_root)

  build_dir = sandbox_root.parent + 'build'
  destination = sandbox_root.parent + 'Rome'

  FileUtils.mkdir_p build_dir
  FileUtils.mkdir_p destination

  installer_context.umbrella_targets.each do |umbrella|
    umbrella.specs.each do |spec|
      consumer = spec.consumer(umbrella.platform_name)
      file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
      if(file_accessor.vendored_frameworks.count > 0)
        file_accessor.vendored_frameworks.each do |framework|
          Pod::UI.puts "• Copying #{spec.root.name}"
          FileUtils.cp_r framework, destination, :remove_destination => true
        end
      end
    end
  end

  Dir.chdir(sandbox.project_path.dirname) do
  targets = installer_context.umbrella_targets.select { |t| t.specs.any? }
  targets.each do |target|
    case target.platform_name
      when :ios then build_for_iosish_platform(sandbox, build_dir, destination, target, 'iphoneos', 'iphonesimulator')
      when :osx then xcodebuild(sandbox, target.cocoapods_target_label)
      when :tvos then build_for_iosish_platform(sandbox, build_dir, destination, target, 'appletvos', 'appletvsimulator')
      when :watchos then build_for_iosish_platform(sandbox, build_dir, destination, target, 'watchos', 'watchsimulator')
      else raise "Unknown platform '#{target.platform_name}'" end
    end
  end

  raise Pod::Informative, 'The build directory was not found in the expected location.' unless build_dir.directory?

  frameworks = Pathname.glob("#{build_dir}/**/*.framework").reject { |f| f.to_s =~ /Pods.*\.framework/ }

  installer_context.umbrella_targets.each do |umbrella|
    umbrella.specs.each do |spec|
      consumer = spec.consumer(umbrella.platform_name)
      file_accessor = Pod::Sandbox::FileAccessor.new(sandbox.pod_dir(spec.root.name), consumer)
      frameworks += file_accessor.vendored_libraries
    end
  end
  frameworks.uniq!

  frameworks.each do |framework|
    FileUtils.cp_r framework, destination, :remove_destination => true
  end

   build_dir.rmtree if build_dir.directory?

end

Far from perfect, but it will do the trick :)

I hope it won't break anything :D

absolutlabs avatar Jul 19 '16 07:07 absolutlabs

I'm not a big fan of making this based solely on the presence of the .framework on the filesystem — that's just bound to confuse people.

neonichu avatar Jul 19 '16 09:07 neonichu

@neonichu Hi there. I see this is an old discussion, but do you have any suggestion about being able to recompile just the pods that are new or upgraded? Basically similar to what pod install does without the Rome plugin? In our case, we are using a caching system to store all the precompiled binaries and would like to change them only if needed. As the system is now, running pod install will rebuild everything and all the binaries will be different (of course).

bpoplauschi avatar Jan 21 '19 09:01 bpoplauschi

@bpoplauschi this plugin might be of use to you (note that I haven't used it myself so I cannot vouchers for anything)

https://github.com/leavez/cocoapods-binary

amorde avatar Jan 23 '19 23:01 amorde