iOS工程08hmap及podspec生成

557 阅读3分钟

一、hmap续

  1. header 搜索目录依次(源文件所在目录-->HEADER_SEARCH_PATHS/USER_HEADER_SEARCH_PATHS)
  2. 第一次搜索源文件所在目录--就进行挂载了hmap
  3. hmap就是在第一次挂载的时候就把对import路径->映射到源文件所在的目录地址上
  4. hmap映射资源的前提是,要有modulemap文件。
OTHER_CFLAGS = -fmodules -fmodule-map-file="${SRCROOT}/App/Zoo/zoo.modulemap"
// -I ==> <> "" --> 系统限定 --》
// clang --〉 modulemap
HEADER_SEARCH_PATHS = "${SRCROOT}/App/Zoo" "${SRCROOT}/../header.hmap"
// -iqoute ""
// header map -> hashmap--》
// 命中 --〉module
//USER_HEADER_SEARCH_PATHS = "${SRCROOT}/../header.hmap"
// 不使用xcode生成
USE_HEADERMAP = NO

小结:

  1. hmap 优化的点,会进行模块映射需要自己编写modulemap文件
  2. hmap xcode 生成耗时是可以加快的(cocoapods-hmap)
  3. 二进制cocoapods内部api->podspec生成xcframework产物->编译生成的.a .o 等格式xcode进行连接

二、podspec生成

spec描述了一个pod库的版本。它包括有关应从何处获取源、使用什么文件、要应用的构建设置以及其他一般元数据(如其名称、版本和描述)的详细信息。

podspec有两种格式:

  1. ruby.语法.podspec
  2. podspec.json
Pod::Spec.new do |spec|
    //库名称
    spec.name          = ‘Reachability’

    //库版本号,这也是我们podfile文件指定的版本号。 每次发布版本都需要打tag标签(名称就是版本号)
    spec.version       = ‘3.1.0'

    //许可证,除非源代码包含了LICENSE.*或者LICENCE.*文件,否则必须指定许可证文件。文件扩展名可以没有,或者是.txt,.md,.markdown
    spec.license       = { :type => 'BSD’ }
    or spec.license = ‘MIT'
    or spec.license = { :type => 'MIT', :file => 'MIT-LICENSE.txt’ }
    or spec.license = { :type => 'MIT', :text => <<-LICENSE
                        Copyright 2012
                         Permission is granted to...
                         LICENSE
                      }

    //pod主页
    spec.homepage      = 'https://github.com/’      

    //pod库维护者的名车和邮箱
    spec.authors       = { 'ning' => 'yyyyyy@gmail.com’ } 
    or spec.author = 'Darth Vader'
    or spec.authors = 'Darth Vader', 'Wookiee'
    or spec.authors = { 'Darth Vader' => 'darthvader@darkside.com',
                    'Wookiee'     => 'wookiee@aggrrttaaggrrt.com' }     

    //指定多媒体地址,如果是推特发布版本会有通知
    spec.social_media_url = 'https: //twitter.com/cocoapods 
    or spec.social_media_url = 'https: //groups.google.com/forum/#!forum/cocoapods'
    
    //pod简介
    spec.summary = 'ARC and GCD Compatible Reachability Class for iOS and OS X.'
        
    //详细描述
    spec.description = <<-DESC                     Computes the meaning of life.
                 Features:
                 1. Is self aware
                 ...
                 42. Likes candies.
               DESC
    
    //获取库的地址
    a. Git:git地址,tag:值以v开头,支持子模块
        spec.source        = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0’ }
        spec.source = { :git => 'https://github.com/typhoon-framework/Typhoon.git',
                :tag => "v#{spec.version}", :submodules => true }
    b. Svn:svn地址
        spec.source = { :svn => 'http://svn.code.sf.net/p/polyclipping/code', :tag => ‘4.8.8‘ }
    c. Hg:Mercurial
        spec.source = { :hg => 'https://bitbucket.org/dcutting/hyperbek', :revision => "#{s.version}" }
    
    // Pod 屏幕截图,支持单个或者数组,主要适用于UI类的pod库。cocoapods推荐使用gif
    spec.screenshot  = 'http://dl.dropbox.com/u/378729/MBProgressHUD/1.png'
    or spec.screenshots = [ 'http://dl.dropbox.com/u/378729/MBProgressHUD/1.png',
                            'http://dl.dropbox.com/u/378729/MBProgressHUD/2.png' ]
    
    // 说明文档地址
    spec.documentation_url  =  'http://www.example.com/docs.html’
    
    // pod下载完成之后,执行的命令。可以创建,删除,修改任何下载的文件。该命令在pod清理之前和pod创建之前执行。
    spec.prepare_command = 'ruby build_files.rb'
    or spec.prepare_command = <<-CMD                        sed -i 's/MyNameSpacedHeader/Header/g' ./**/*.h
                    sed -i 's/MyNameOtherSpacedHeader/OtherHeader/g' ./**/*.h
             CMD
            
    //module name
    spec.module_name   = ‘Rich'
    //支持的swift版本
    spec.swift_version = ‘4.0'
    // 支持的Cocoapods版本
    spec.cocoapods_version = ‘>=0.36’
    
    // 是否使用静态库。如果podfile指明了use_frameworks!命令,但是pod仓库需要使用静态库则需要设置
    spec.static_framework = true
    
    // 库是否废弃
    spec.deprecated = true

    //  废弃的pod名称
    spec.deprecated_in_favor_of = 'NewMoreAwesomePod'

    // pod支持的平台,如果没有设置意味着支持所有平台,使用deployment_target支持选择多个平台
    spec.platform = :osx,  ’10.8'
    or spec.platform = :ios
    or spec.platform = :osx         
            
    // 可以指定多个不同平台
    spec.ios.deployment_target =  ‘6.0'
    or .osx.deployment_target = '10.8'

ruby的源码可直接转json文件,而json转不了ruby格式的文件

podspec.json:

# AmberBin::BinSpecWithSource.generate()
module AmberBin
  module BinSpecWithSource
    # class
    def self.generate(product)
      source_base_url = ''
      # source源
      binary_source = { http: format("#{source_base_url}/%s/%s/%s", product.xcframework_name, product.version, product.zip_product_name) }
      spec_hash = product.root_spec.to_hash
      delete_common_properties(product, spec_hash)
      # 二进制 --》xcframework[ .a .framework]
      # 存放库要携带的二进制
      # vendored_libraries = .a .dylib
      key = :vendored_frameworks
      name = 'BinProduct'
      spec = Pod::Specification.from_hash(spec_hash)

      # subspec
      spec.subspecs.each do |s|
        s.dependency("#{spec.name}/#{name}")
      end
      spec.subspec(name) do |s|
        s.preserve_paths = [product.xcframework_product_name]
        s.send("#{key}=", [product.xcframework_product_name])
        # import = {
        #     'OTHER_SWIFT_FLAGS' => "-Xcc -fmodule-map-file=\"${PODS_XCFRAMEWORKS_BUILD_DIR}/#{product.xcframework_name}/BinProduct/Headers/#{product.xcframework_name}/#{product.xcframework_name}.modulemap\"",
        #     'OTHER_CFLAGS' => "-fmodule-map-file=\"${PODS_XCFRAMEWORKS_BUILD_DIR}/#{product.xcframework_name}/BinProduct/Headers/#{product.xcframework_name}/#{product.xcframework_name}.modulemap\""
        # }
        # if product.uses_swift? && !product.build_as_framework?
        #     import.merge!({ 'SWIFT_INCLUDE_PATHS' => "\"${PODS_XCFRAMEWORKS_BUILD_DIR}/#{product.xcframework_name}/BinProduct/Headers\"" })
        # end
        # moudle --> app -->hook 
        # podfile use_moduler_header!
        # .a -->module --> hook -->
       # s.user_target_xcconfig = import
      end
      spec.subspecs.reverse!
      spec.default_subspecs = [name, spec.default_subspecs].compact.flatten
      spec.source = binary_source
      spec.description = <<-EOF
            name: #{product.xcframework_name}
            version: #{product.version}
            组件二进制化
            #{product.root_spec.description}
      EOF

      path = product.bin_spec_path
      contents = spec.to_pretty_json
      if path.exist?
        content_stream = StringIO.new(contents)
        identical = File.open(path, 'rb') { |f| FileUtils.compare_stream(f, content_stream) }
        return if identical
      end
      File.open(path, 'w+') { |f| f.write(contents) }
    end

    #ruby --json -->删掉--》podspec --》老基础上
    def self.delete_common_properties(product, attributes)
      attributes.delete('source_files')
      attributes.delete('script_phases')
      attributes.delete('script_phase')
      attributes.delete('module_map')
      attributes.delete('header_mappings_dir')
      attributes.delete('preserve_paths')
      attributes.delete('pod_target_xcconfig')
      attributes.delete('compiler_flags')
      attributes.delete('prepare_command')
      attributes.delete('exclude_files')
      unless product.build_as_framework?
        attributes.delete('public_header_files')
        attributes.delete('private_header_files')
      end
      attributes['subspecs'].each { |s| delete_common_properties(product, s) } unless attributes['subspecs'].nil?
    end
  end
end

s.subspec 'Serialization' do |ss| # 会卡住,就不行 -->验证不通过 不能为空

怎么解决呢?

s.subspec 'BinProduct' do |ss|
    s.vendored_frameworks = 'AFNetworking.xcframework'
end 

//编写相互依赖 关系
s.subspec 'Serialization' do |ss|
    ss.dependency 'AFNetworking/BinProduct'
end 

//设置默认subspecs
s.default_subspecs = ['BinProduct']

AFNetworking.podspec.json

{
  "name": "AFNetworking",
  "version": "4.0.1",
  "license": "MIT",
  "summary": "A delightful networking framework for Apple platforms.",
  "homepage": "https://github.com/AFNetworking/AFNetworking",
  "social_media_url": "https://twitter.com/AFNetworking",
  "authors": {
    "Mattt Thompson": "m@mattt.me"
  },
  "source": {
    "git": "https://github.com/AFNetworking/AFNetworking.git",
    "tag": "4.0.1"
  },
  "platforms": {
    "ios": "9.0",
    "osx": "10.10",
    "watchos": "2.0",
    "tvos": "9.0"
  },
  "ios": {
    "pod_target_xcconfig": {
      "PRODUCT_BUNDLE_IDENTIFIER": "com.alamofire.AFNetworking"
    }
  },
  "osx": {
    "pod_target_xcconfig": {
      "PRODUCT_BUNDLE_IDENTIFIER": "com.alamofire.AFNetworking"
    }
  },
  "watchos": {
    "pod_target_xcconfig": {
      "PRODUCT_BUNDLE_IDENTIFIER": "com.alamofire.AFNetworking-watchOS"
    }
  },
  "tvos": {
    "pod_target_xcconfig": {
      "PRODUCT_BUNDLE_IDENTIFIER": "com.alamofire.AFNetworking"
    }
  },
  "source_files": "AFNetworking/AFNetworking.h",
  "subspecs": [
    {
      "name": "Serialization",
      "source_files": "AFNetworking/AFURL{Request,Response}Serialization.{h,m}"
    },
    {
      "name": "Security",
      "source_files": "AFNetworking/AFSecurityPolicy.{h,m}"
    },
    {
      "name": "Reachability",
      "platforms": {
        "ios": "9.0",
        "osx": "10.10",
        "tvos": "9.0"
      },
      "source_files": "AFNetworking/AFNetworkReachabilityManager.{h,m}"
    },
    {
      "name": "NSURLSession",
      "dependencies": {
        "AFNetworking/Serialization": [

        ],
        "AFNetworking/Security": [

        ]
      },
      "ios": {
        "dependencies": {
          "AFNetworking/Reachability": [

          ]
        }
      },
      "osx": {
        "dependencies": {
          "AFNetworking/Reachability": [

          ]
        }
      },
      "tvos": {
        "dependencies": {
          "AFNetworking/Reachability": [

          ]
        }
      },
      "source_files": [
        "AFNetworking/AF{URL,HTTP}SessionManager.{h,m}",
        "AFNetworking/AFCompatibilityMacros.h"
      ]
    },
    {
      "name": "UIKit",
      "platforms": {
        "ios": "9.0",
        "tvos": "9.0"
      },
      "dependencies": {
        "AFNetworking/NSURLSession": [

        ]
      },
      "source_files": "UIKit+AFNetworking"
    }
  ]
}

总结:

CocoaPods工程: podfile三方库:1.网络下载 2.local【有源码】

xcframework gen --no-local: 库是不是本地
--output-dir:工程/所有的文件(xc,bundle)
--use-libraries : .a 
--use-static-frameworks : .framework
--sources:,分割私有源
--include-podspecs: *.podspec,*.podspec podspec是本地
--external-podspecs: *.podspec,*.podspec podspec是网络

module --> 生成 --> podspec --> cocoapods-project-gen podspec -->zip -->upload

大概总结二进制库制作:

  1. github有源码,就是自己代码库。有一个自己podspec版本库用于记录podspec版本信息(二进制库配置信息)。
  2. cocoapods内部API下载git源码,通过podspec得到
  3. xcframework源码,xcode通过.xcframework文件提供多个平台的分发二进制文件.
  4. 生成对应的.a .framework进行链接。

所以podspec文件就是中间桥梁的作用。