Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CocoaPods Plugins

CocoaPods Plugins

Longer version of my CocoaPods Plugins talk, given at mobiconf 2014 in Krakow.

Boris Bügling

October 02, 2014
Tweet

More Decks by Boris Bügling

Other Decks in Technology

Transcript

  1. NO

  2. AGENDA ▸ CocoaPods itself ▸ Useful plugins ▸ How to

    build your own plugin ▸ Improving your workflow ▸ (Mini CocoaPods state of the union)
  3. COCOAPODS-DOWNLOADER def download_head! hg! %|clone #{url} #{@target_path.shellescape}| [...] end def

    download_revision! hg! %|clone "#{url}" --rev '#{options[:revision]}' #{@target_path [...] end def download_tag! hg! %|clone "#{url}" --updaterev '#{options[:tag]}' #{@target_path [...] end
  4. CLAIDE argv = CLAide::ARGV.new(['tea', '--no-milk', '--sweetner=honey']) argv.shift_argument # => 'tea'

    argv.shift_argument # => nil argv.flag?('milk') # => false argv.flag?('milk') # => nil argv.option('sweetner') # => 'honey' argv.option('sweetner') # => nil
  5. COCOAPODS $ pod install Analyzing dependencies Pre-downloading: `DBCamera` from `https://github.com/[...]`

    Downloading dependencies Installing ARASCIISwizzle (1.1.0) Installing Bolts (1.1.0) [...] Generating Pods project Integrating client project
  6. COCOAPODS PLUGINS ▸ Add subcommands to pod, the tool ▸

    post_install hook ▸ Each plugin is a Gem
  7. $ tree . !"" Gemfile !"" LICENSE.txt !"" README.md !""

    Rakefile !"" cocoapods_awesome_plugin.gemspec #"" lib !"" cocoapods_awesome_plugin.rb !"" cocoapods_plugin.rb #"" pod #"" command #"" plugin.rb 3 directories, 8 files
  8. module Pod class Command class Plugin < Command self.summary =

    "Short description." self.arguments = [CLAide::Argument.new('NAME', true)] def initialize(argv) @name = argv.shift_argument super end def validate! super help! "A Pod name is required." unless @name end def run UI.puts "Add your implementation here" end
  9. WHAT? ▸ Package a Pod as a static framework ▸

    Including dependencies ▸ All supported platforms ▸ Generate a corresponding podspec
  10. TEMPLATE ▸ Just a Git repo, similar to the pod

    template ▸ Reads as much from the environment as possible ▸ Result is installable, shippable
  11. DEFINE THE COMMAND module Pod class Command class Package <

    Command self.summary = 'Package a podspec into a static library.' self.arguments = [['NAME', :required]] [...] end end end
  12. RUN def run if @spec builder = SpecBuilder.new(@spec) 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) } else help! 'Unable to find a podspec with path or name.' end end
  13. FRAGMENT OF SPECGENERATOR s.#{platform.name}.platform = :#{platform.symbolic_name}, '#{platform.deployment_target}' s.#{platform.name}.preserve_paths = '#{fwk_base}'

    s.#{platform.name}.public_header_files = '#{fwk_base}/Versions/A/Headers/*.h' s.#{platform.name}.vendored_frameworks = '#{fwk_base}'
  14. BUILD FOR A SPECIFIC PLATFORM def build_in_sandbox(platform) config.sandbox_root = 'Pods'

    config.integrate_targets = false config.skip_repo_update = true sandbox = install_pod(platform.name) UI.puts 'Building framework' xcodebuild versions_path, headers_path = create_framework_tree(platform.name.to_s) `cp #{sandbox.public_headers.root}/#{@spec.name}/*.h #{headers_path}` Pathname.new(config.sandbox_root).rmtree Pathname.new('Podfile.lock').delete end
  15. INSTALL FROM GENERATED PODFILE def install_pod(platform_name) podfile = podfile_from_spec(platform_name, @spec.deployment_target(platform_name))

    sandbox = Sandbox.new(config.sandbox_root) installer = Installer.new(sandbox, podfile) installer.install! sandbox end
  16. GENERATE THAT PODFILE def podfile_from_spec(platform_name, deployment_target) name = @spec.name path

    = @path podfile = Pod::Podfile.new do platform(platform_name, deployment_target) if path pod name, :podspec => path else pod name, :path => '.' end end podfile end
  17. ▸ Push your repo to GH ▸ Release as Ruby

    Gem ▸ Send a PR to the cocoapods.org repo
  18. !

  19. THE CONTENTFUL.OBJC MAKEFILE WORKSPACE=ContentfulSDK.xcworkspace .PHONY: all clean doc example example-static

    pod really-clean static-lib test clean: rm -rf build Examples/UFO/build Examples/*.zip really-clean: clean rm -rf Pods $(HOME)/Library/Developer/Xcode/DerivedData/* all: test example-static pod: pod install example: set -o pipefail && xcodebuild -workspace $(WORKSPACE) \ -scheme ContentfulDeliveryAPI \ -sdk iphonesimulator | xcpretty -c set -o pipefail && xcodebuild -workspace $(WORKSPACE) \ -scheme 'UFO Example' \ -sdk iphonesimulator | xcpretty -c example-static: static-lib cd Examples/UFO; set -o pipefail && xcodebuild \ -sdk iphonesimulator | xcpretty -c static-lib: @sed -i '' -e 's/GCC_GENERATE_TEST_COVERAGE_FILES = YES/GCC_GENERATE_TEST_COVERAGE_FILES = NO/g' ContentfulSDK.xcodeproj/project.pbxproj @sed -i '' -e 's/GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES/GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO/g' ContentfulSDK.xcodeproj/project.pbxproj set -o pipefail && xcodebuild VALID_ARCHS='i386 x86_64 armv7 armv7s arm64' -workspace $(WORKSPACE) \ -scheme Pods-ContentfulDeliveryAPI \ -sdk iphonesimulator | xcpretty -c set -o pipefail && xcodebuild VALID_ARCHS='i386 x86_64 armv7 armv7s arm64' -workspace $(WORKSPACE) \ -scheme 'Static Framework' | xcpretty -c @cd Examples/UFO/Distribution; ./update.sh cd Examples; ./ship_it.sh @sed -i '' -e 's/GCC_GENERATE_TEST_COVERAGE_FILES = NO/GCC_GENERATE_TEST_COVERAGE_FILES = YES/g' ContentfulSDK.xcodeproj/project.pbxproj @sed -i '' -e 's/GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO/GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES/g' ContentfulSDK.xcodeproj/project.pbxproj test: example set -o pipefail && xcodebuild -workspace $(WORKSPACE) \ -scheme ContentfulDeliveryAPI \ -sdk iphonesimulator -destination 'name=iPhone Retina (4-inch)' \ test | xcpretty -c doc: appledoc --project-name 'Contentful Delivery API' \ --project-version 1.0 \ --project-company 'Contentful GmbH' \ --company-id com.contentful \ --output ./doc \ --create-html \ --no-create-docset \ --no-install-docset \ --no-publish-docset \ --no-keep-intermediate-files \ --no-keep-undocumented-objects \ --no-keep-undocumented-members \ --merge-categories \ --warn-missing-output-path \ --warn-missing-company-id \ --warn-undocumented-object \ --warn-undocumented-member \ --warn-empty-description \ --warn-unknown-directive \ --warn-invalid-crossref \ --warn-missing-arg \ --logformat 1 \ --verbose 2 ./Code
  20. 0.34 ▸ Dependencies per build configuration ▸ Private spec repositories

    ▸ Faster downloads ▸ Reorganisation of the Pods directory ▸ Foundation work
  21. SWIFT PODS SUPPORT IS COMING ▸ there are no Swift

    static libraries ▸ CocoaPods needs to support frameworks ▸ You can use existing Pods in your Swift apps just fine