建立Pod私有庫

weixin_33782386發表於2018-09-20

前言

看本地cocoaPod庫 cd ~/.cocoapods/repos在repos資料夾下面,可以看到你當前存在的一些庫,當你建立了自己的私有倉庫時,也會在這裡顯示。

按照正常邏輯來看,私有庫是一個地址,版本號管理庫是一個地址,最好不要把兩者放在一起,會顯得很亂。
所以建立私有庫,我們需要建立兩個庫:一個是私有倉庫repo,用來做私有庫的版本管理;另一個是私有程式碼庫,用來做程式碼編寫。

建立私有倉庫 repo

這裡的私有空間是指私有庫存放的位置,repo是repository(儲存庫)的縮寫,如果私有庫的podSpec和程式碼存放在一起就會顯得很亂,所有通常的做法就是再私有空間只存放私有庫的podSpec檔案(可以理解為版本號)。

建立一個私有倉庫

這裡使用碼雲,可以免費建立多個私有工程。例如建立了一個私有儲存庫:https://gitee.com/devAlan/PrivateRepo

新增到本地倉庫中

pod repo add [本地倉庫repo名稱] [遠端repo地址]
pod repo add PrivateRepo https://gitee.com/devAlan/PrivateRepo
使用上面步驟就可以將遠端的私有版本儲存倉庫新增到本地。在Finder中檢視repos中就可以發現增加了一個資料夾PrivateRepo。

建立私有程式碼庫

建立一個私人程式碼庫

在碼雲上建立一個私人程式碼庫,例如已經建立好的程式碼庫:https://gitee.com/devAlan/privateAdd

在建立時新增MIT License和README。

將倉庫clone到本地,新增程式碼檔案。

新增.podspec檔案

“.podspec”檔案是這個程式碼庫的pod描述檔案,使用pod命令建立空白模板。

pod spec create 專案名稱

這裡使用上面的私有程式碼庫建立pod spec create privateAdd

需要注意一下:生成的預設的podspec檔案中,所有沒有註釋掉的都必須填寫正確。

編輯“.podspec”檔案

#
#  Be sure to run `pod spec lint PrivateAdd_v2.podspec' to ensure this is a
#  valid spec and to remove all comments including this before submitting the spec.
#
#  To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
#  To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#

# 宣告
Pod::Spec.new do |s|

  # ―――  Spec Metadata  ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  These will help people to find your library, and whilst it
  #  can feel like a chore to fill in it's definitely to your advantage. The
  #  summary should be tweet-length, and the description more in depth.
  #
  # 私有庫名稱
  s.name         = "PrivateAdd_v2"    
  # 版本號,跟當前版本tag有關
  s.version      = "0.0.1"            
  # 專案描述
  s.summary      = "A short description of PrivateAdd_v2." 

  # This description is used to generate tags and improve search results.
  #   * Think: What does it do? Why did you write it? What is the focus?
  #   * Try to keep it short, snappy and to the point.
  #   * Write the description between the DESC delimiters below.
  #   * Finally, don't worry about the indent, CocoaPods strips it!
  s.description  = <<-DESC
                   DESC

  # 主頁,自動生成的podspec檔案中所有的EXAMPLE都需要改
  s.homepage     = "http://EXAMPLE/PrivateAdd_v2" 
  # 專案截圖
  # s.screenshots  = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"  


  # ―――  Spec License  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Licensing your code is important. See http://choosealicense.com for more info.
  #  CocoaPods will detect a license file if there is a named LICENSE*
  #  Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
  #

  # 專案遵守的協議
  s.license      = "MIT (example)"      
  # s.license      = { :type => "MIT", :file => "FILE_LICENSE" }


  # ――― Author Metadata  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the authors of the library, with email addresses. Email addresses
  #  of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
  #  accepts just a name if you'd rather not provide an email address.
  #
  #  Specify a social_media_url where others can refer to, for example a twitter
  #  profile URL.
  #

  # 作者資訊
  s.author             = { "liujiajia" => "liujiajia@gerrit.babytree-inc.com" }  
  # Or just: s.author    = "liujiajia"
  # s.authors            = { "liujiajia" => "liujiajia@gerrit.babytree-inc.com" }
  # s.social_media_url   = "http://twitter.com/liujiajia"

  # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If this Pod runs only on iOS or OS X, then specify the platform and
  #  the deployment target. You can optionally include the target after the platform.
  #

  # s.platform     = :ios           # 平臺
  # 平臺以及版本號
  # s.platform     = :ios, "5.0"    

  #  When using multiple platforms
  # s.ios.deployment_target = "5.0"
  # s.osx.deployment_target = "10.7"
  # s.watchos.deployment_target = "2.0"
  # s.tvos.deployment_target = "9.0"


  # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Specify the location from where the source should be retrieved.
  #  Supports git, hg, bzr, svn and HTTP.
  #

  #當前私有庫資源的git地址,相應的tag,這裡直接使用程式碼來標識使用和當前tag一樣的值
  s.source       = { :git => "http://EXAMPLE/PrivateAdd_v2.git", :tag => "#{s.version}" }  


  # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  CocoaPods is smart about how it includes source code. For source files
  #  giving a folder will include any swift, h, m, mm, c & cpp files.
  #  For header files it will include any header in the folder.
  #  Not including the public_header_files will make all headers public.
  #

  # 需要引用的檔案程式碼,classes資料夾下的所有.h.m檔案。這裡的路徑都是相對路徑
  s.source_files  = "Classes", "Classes/**/*.{h,m}" 
  # 排除掉哪些檔案,不被包含的檔案,這裡是Classes/Exclude資料夾下的所有
  s.exclude_files = "Classes/Exclude"   

  # s.public_header_files = "Classes/**/*.h"


  # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  A list of resources included with the Pod. These are copied into the
  #  target bundle with a build phase script. Anything else will be cleaned.
  #  You can preserve files from being cleaned, please don't preserve
  #  non-essential files like tests, examples and documentation.
  #

  # s.resource  = "icon.png"            # 資原始檔
  # s.resources = "Resources/*.png"     # 所有資原始檔

  # s.preserve_paths = "FilesToSave", "MoreFilesToSave"


  # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  Link your library with frameworks, or libraries. Libraries do not include
  #  the lib prefix of their name.
  #

  # s.framework  = "UIKit"          # 依賴的系統framework,去掉字尾
  # s.frameworks = "SomeFramework", "AnotherFramework"

  # s.library   = "iconv"                   # 依賴的系統library
  # s.libraries = "iconv", "xml2", "z"      # 依賴的library,去除字首和字尾,例如“libz.tbd”,則直接引用為"z"
  
  # s.vendored_frameworks = "*.framework", "*.framework"          #依賴那些靜態庫
  # s.vendored_libraries = "*.a", "*.a"           # 依賴哪些靜態library


  # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  #
  #  If your library depends on compiler flags you can set them in the xcconfig hash
  #  where they will only apply to your library. If you depend on other Podspecs
  #  you can include multiple dependencies to ensure it works.

  # s.requires_arc = true       # 是否開啟ARC

  # s.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => 'HMTIMEINPREGNACYAPP=1', "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }  
  # 這裡配置一些內容,"GCC_PREPROCESSOR_DEFINITIONS":定義一個巨集,
  # "HEADER_SEARCH_PATHS":如果引用該私有庫,則會在主工程中尋找資料夾下的內容
  
  # s.dependency "JSONKit", "~> 1.4"        # 使用了pod,依賴哪些庫

  # s.prefix_header_contents = <<-EOS     #這裡會生成一個預設pch檔案,作用於Xcode工程中新增的pch檔案一樣。
  #      #import <UIKit/UIKit.h>
  # EOS

end

這裡有一個需要注意的地方,在建立私有庫的時候,找不到MIT LICENSE證照,這裡講license修改一下
s.license = { :type => "MIT", :file => "LICENSE" }

二級庫subspec

  s.subspec 'UIView+Category' do |ss| 
    ss.source_files = "PrivateAdd_v3/PrivateAdd_v3/Classes/UIView+Category/*.{h,m}"
    ss.framework = "UIKit"
    # ss.vendored_libraries = '/*.a'
    # ss.vendored_frameworks = '/*.framework'
    # ss.resource = 'Moments/ForPregnacy/**/*.bundle', 'Moments/ForPregnacy/**/*.png', 'Moments/ForPregnacy/**/*.mp3'
  end

驗證私有庫

修改完相應的程式碼塊之後,開始驗證私有庫配置是否正確。

本地驗證

pod lib lint
// 如果使用了私有庫,則使用--sources來標明,給出具體地址
pod lib lint --sources=[私有倉庫repo地址],[私有庫git地址],https://github.com/CocoaPods/Specs.git

如果出現錯誤,基本上都是podspec檔案中的配置出現了問題,例如:

$ pod lib lint

 -> PrivateAdd_v2 (0.0.1)
    - WARN  | attributes: Missing required attribute `license`.
    - WARN  | license: Missing license type.
    - ERROR | description: The description is empty.
    - ERROR | [iOS] unknown: Encountered an unknown error (The `PrivateAdd_v2` pod failed to validate due to 1 error:
    - WARN  | attributes: Missing required attribute `license`.
    - WARN  | license: Missing license type.
    - ERROR | description: The description is empty.

) during validation.

[!] PrivateAdd_v2 did not pass validation, due to 2 errors and 2 warnings.
You can use the `--no-clean` option to inspect any issue.

這就需要將上面的錯誤修改掉。

一般情況下出現警告在後面新增pod lib lint --allow-warnings,就可以通過驗證了。驗證通過會提示passed validation。

如果依賴一些靜態庫(.framework,.a),則在命令後面新增--use-libraries,表示依賴了靜態庫。

如果報錯不是很明顯,這命令後新增--verbose,會輸出驗證的過程,並給出報錯資訊。

遠端驗證

pod spec lint,一般情況下私有庫都是存在遠端git上的,所以基本上只在第一次驗證使用本地驗證之後,就可以直接使用遠端驗證了。
但是一般情況下,建立的私有程式碼庫如果是私有的(並不是官方的),這時候,我們在做遠端驗證時,需要新增程式碼地址。,不然pod會預設從官方repo查詢。

pod spec lint --sources=[私有倉庫repo地址],[私有庫git地址],https://github.com/CocoaPods/Specs.git

# 或者只新增前面兩項,最後一項可以忽略
pod spec lint --sources=[私有倉庫repo地址],[私有庫git地址]

如果出現一些警告,可以直接在命令最後新增--allow-warnings來遮蔽警告。例如:

pod spec lint --sources=https://gitee.com/devAlan/PrivateRepo,https://gitee.com/devAlan/PrivateAdd_v3.git,https://github.com/CocoaPods/Specs.git --allow-warnings

pod spec lint --sources=https://gitee.com/devAlan/PrivateRepo,https://gitee.com/devAlan/PrivateAdd_v3.git --allow-warnings

釋出私有庫

將podspec檔案推送到私有空間repo,在釋出時一定要記住,已經做了tag處理。

pod repo push [私有倉庫repo] [私有庫podspec檔案地址] --allow-warnings
pod repo push [私有倉庫repo] [私有庫podspec檔案地址] --sources=[私有倉庫repo地址],[私有庫地址],https://gitee.com/devAlan/PrivateAdd_v2.git --allow-warnings

由於基本上的所有命令操作都是在該私有庫資料夾下,所以不用管podspec的檔案位置。

pod repo push PrivateRepo PrivateAdd.podspec --allow-warnings

執行該命令時,相當於直接將podspec檔案push到repo的Git地址上。

引用私有庫

本地路徑引用

做好驗證之後,如果需要測試,可以直接在podfile中引用私有庫的本地路徑

// ../是回到上一級檔案目錄,是以當前podfile所在檔案位置決定
pod 'Private_v2', :path => '../../Private_v2'

這個時候如果改動Private_v2中的程式碼就是直接改動。

repo引用

在podfile中先新增source,然後直接pod引入,當然在引用私有庫的時候,不僅需要需要私有倉庫repo的許可權,還需要有私有庫的許可權。

source 'https://gitee.com/devAlan/PrivateRepo'
 
pod 'Private_v2'

#或者使用下面的方式
#pod 'Private_v2', :git=> 'https://gitee.com/devAlan/PrivateRepo'

pod 常用命令

  1. 安裝podfile中依賴的命令
    pod install
    pod update
    --no-repo-update 不需要更新repo
    --repo-update 更新repo

  2. repo相關
    pod repo list
    pod repo remove xxx 移除一個本地repo
    pod repo add [本地倉庫repo名稱] [遠端repo地址] 遠端版本空間新增到本地

  3. 私有庫建立相關
    pod lib lint 本地驗證
    pod spec lint 遠端驗證
    pod repo push [本地倉庫repo] [*.podspec] 釋出版本到repo
    --source=[私有repo地址][私有程式碼庫地址][pod地址]
    --allow-warnings 忽略warning
    --use-libraries 使用了第三方的framework或者.a檔案
    --verbose 列印流程,可以快速定位失敗原因

  4. podspec中使用到的*
    /** 子目錄下所有資料夾
    /* 目錄下所有檔案

遇到的問題

  1. 拿我們的專案來說,一個專案依賴另一個專案中的某些檔案,這些都是強制性的依賴。導致本地驗證和遠端驗證都無法通過,所以更別說釋出了。
    這種是沒有完全的元件化。我們需要在podspec中新增HEADER_SEARCH_PATHS,新增指定位置檔案路徑。這裡的路徑也是相對路徑。

    s.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => 'HMTIMEINPREGNACYAPP=1', 
    "HEADER_SEARCH_PATHS" => "$(SRCROOT)/usr/include/libxml2", $(SRCROOT)/../Commen/** }  
    

    但是這樣做仍然無法通過驗證,這就需要我們將私有空間repo pull到本地,手動建立版本號資料夾新增podspec檔案,然後push。

  2. 在上面的程式碼中還有一個 GCC_PREPROCESSOR_DEFINITIONS,這是定義一個巨集,可以在Project-Build Settings - Preprocessor Macros下看到。

    可以配合一些沒有必要引入私有程式碼庫中的檔案來使用。

相關文章