Slide 1

Slide 1 text

COCOAPODS PLUGINS MOBICONF, OCTOBER 2014 BORIS BÜGLING - @NEONACHO

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

CORE TEAM MEMBER

Slide 4

Slide 4 text

NO

Slide 5

Slide 5 text

CORE TEAM MEMBER

Slide 6

Slide 6 text

CONTENTFUL

Slide 7

Slide 7 text

AGENDA ▸ CocoaPods itself ▸ Useful plugins ▸ How to build your own plugin ▸ Improving your workflow ▸ (Mini CocoaPods state of the union)

Slide 8

Slide 8 text

COCOAPODS

Slide 9

Slide 9 text

THE DE-FACTO DEPENDENCY MANAGER

Slide 10

Slide 10 text

CREATED BY THIS HANDSOME GUY

Slide 11

Slide 11 text

▸ Core ▸ cocoapods-downloader ▸ Xcodeproj ▸ CLAide ▸ CocoaPods

Slide 12

Slide 12 text

CORE spec = Pod::Specification.from_file('CPDColors.podspec') puts spec.name puts spec.version $ ./core.rb CPDColors 0.1.0

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

XCODEPROJ wrkspace = Xcodeproj::Workspace.new_from_xcworkspace( 'CPDColors/Example/Demo.xcworkspace') puts wrkspace.schemes $ ./xcodeproj.rb {"Demo"=>"/Users/boris/Projects/CPDColors/Example/Demo.xcodeproj", "Pods"=>"/Users/boris/Projects/CPDColors/Example/Pods/Pods.xcodeproj"}

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

COCOAPODS PLUGINS

Slide 18

Slide 18 text

COCOAPODS PLUGINS ▸ Add subcommands to pod, the tool ▸ post_install hook ▸ Each plugin is a Gem

Slide 19

Slide 19 text

DO WHATEVER YOU WANT, BECAUSE RUBY !

Slide 20

Slide 20 text

USEFUL PLUGINS

Slide 21

Slide 21 text

$ pod trunk push

Slide 22

Slide 22 text

$ pod plugins list

Slide 23

Slide 23 text

▸ Uses https://github.com/CocoaPods/cocoapods.org/blob/master/ plugins.json

Slide 24

Slide 24 text

$ pod try BBUSegmentedViewController

Slide 25

Slide 25 text

$ pod lib docstats

Slide 26

Slide 26 text

$ pod lib testing

Slide 27

Slide 27 text

$ pod lib coverage

Slide 28

Slide 28 text

$ pod keys set AccessToken 0xFFFFFFFF

Slide 29

Slide 29 text

$ pod package ContentfulDeliveryAPI.podspec

Slide 30

Slide 30 text

$ pod roulette

Slide 31

Slide 31 text

HOW TO BUILD YOUR OWN PLUGIN

Slide 32

Slide 32 text

$ pod plugins create cocoapods-awesome-plugin

Slide 33

Slide 33 text

$ 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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

HOOKS

Slide 36

Slide 36 text

Pod::HooksManager.register(:post_install) do |options| require 'installer' UI.puts "This gets executed after installation" end

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

WHAT? ▸ Package a Pod as a static framework ▸ Including dependencies ▸ All supported platforms ▸ Generate a corresponding podspec

Slide 39

Slide 39 text

$ pod package AFNetworking.podspec

Slide 40

Slide 40 text

LET'S GET STARTED

Slide 41

Slide 41 text

$ pod plugins create cocoapods-packager

Slide 42

Slide 42 text

TEMPLATE ▸ Just a Git repo, similar to the pod template ▸ Reads as much from the environment as possible ▸ Result is installable, shippable

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

PARSE THE SPEC def spec_with_path(path) if !path.nil? && Pathname.new(path).exist? @path = path Specification.from_file(path) end end

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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}'

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

$ rake install

Slide 51

Slide 51 text

$ pod package AFNetworking.podspec

Slide 52

Slide 52 text

▸ Push your repo to GH ▸ Release as Ruby Gem ▸ Send a PR to the cocoapods.org repo

Slide 53

Slide 53 text

$ git push $ rake release $ gem install cocoapods-packager

Slide 54

Slide 54 text

!

Slide 55

Slide 55 text

IMPROVING YOUR WORKFLOW

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

THE CONTENTFUL-MANAGEMENT.OBJC MAKEFILE

Slide 58

Slide 58 text

▸ cocoapods-testing ▸ cocoapods-coverage ▸ cocoapods-packager ▸ cocoapods-docstats ▸ ...

Slide 59

Slide 59 text

THANK YOU!

Slide 60

Slide 60 text

SWIFT FUNTIME

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

LINKS ▸ http://www.objc.io/issue-6/cocoapods-under-the-hood.html ▸ http://guides.cocoapods.org ▸ https://github.com/CocoaPods/Rainforest

Slide 63

Slide 63 text

▸ http://buegling.com/talks ▸ @NeoNacho ▸ [email protected]

Slide 64

Slide 64 text

MINI STATE OF THE UNION

Slide 65

Slide 65 text

0.34 ▸ Dependencies per build configuration ▸ Private spec repositories ▸ Faster downloads ▸ Reorganisation of the Pods directory ▸ Foundation work

Slide 66

Slide 66 text

DETERMINISTIC PODFILE source 'https://github.com/CocoaPods/Specs' source 'https://github.com/Organization/Specs'

Slide 67

Slide 67 text

DO NOT USE PODS_ROOT

Slide 68

Slide 68 text

0.34.2

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

@MRACKWITZ

Slide 71

Slide 71 text

No content