一、hmap续
header搜索目录依次(源文件所在目录-->HEADER_SEARCH_PATHS/USER_HEADER_SEARCH_PATHS)- 第一次搜索源文件所在目录--就进行
挂载了hmap hmap就是在第一次挂载的时候就把对import路径->映射到源文件所在的目录地址上。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
小结:
- hmap 优化的点,会进行模块映射需要自己编写modulemap文件
- hmap xcode 生成耗时是可以加快的(cocoapods-hmap)
- 二进制cocoapods内部api->podspec生成xcframework产物->编译生成的.a .o 等格式xcode进行连接
二、podspec生成
spec描述了一个pod库的版本。它包括有关应从何处获取源、使用什么文件、要应用的构建设置以及其他一般元数据(如其名称、版本和描述)的详细信息。
podspec有两种格式:
- ruby.语法.podspec
- 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
大概总结二进制库制作:
- github有源码,就是自己代码库。有一个自己podspec版本库用于记录podspec版本信息(二进制库配置信息)。
- cocoapods内部API下载git源码,通过
podspec得到 xcframework源码,xcode通过.xcframework文件提供多个平台的分发二进制文件.- 生成对应的
.a .framework进行链接。
所以podspec文件就是中间桥梁的作用。