IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【podspec】cocoapods 库中头文件存在多层嵌套 -> 正文阅读

[移动开发]【podspec】cocoapods 库中头文件存在多层嵌套

以一个podspec开始聊

#一个podspec文件包含一个Spec和若干个subspec,podfile可以引入整个podspec或subspec
Pod::Spec.new do |s|

  #Pod的名称,必填,如Podfile中pod 'AFNetworking',AFNetworking就是name
  s.name         = "MyLibrary"      s.version      = "0.0.1"  #版本,必填

  #简介,必填
  s.summary      = "A short description of library."  

  #详细的描述,支持多行字符串,必填
  s.description  = <<-DESC
                Add long description of the pod here.
                   DESC  

  #主页,必填
  s.homepage     = "http://EXAMPLE/MyLibrary"  

  #遵守的开源协议,必填。注意GPL可能给公司带来很大风险,不要轻易使用
  s.license      = "MIT"  

  #pod库作者,必填
  s.author             = { "wangbingwf" => "wangbingwf@163.com" }  

  #平台版本信息,这里表示支持iOS,7.0及以上系统
  s.platform     = :ios, "7.0"    

  #当支持多平台时,使用deployment_target替代platform
  #s.osx.deployment_target = '8.0'  

  #代码路径,这里虽然填写的是git仓库的路径,但Podfile中使用path方式引入podspec时,并不会再从git上下载代码,而是使用本地的代码,所以就可以在这种方式下开发lib库。
  #这里支持git,svn,http等。并且可以设置tag或version等信息
  s.source       = { :git => "https://git.coding.net/yourgit/MyLibrary.git", :tag => s.version.to_s} 

  # ———— Subspecs ————————————————————————————————————#
  # ———— MyLibraryCFiles ———————————————————————————————#
  #创建一个subspec
   s.subspec 'MyLibraryCFiles' do |subcfiles|

    #subspec包含的代码文件,上面source是路径,这里source_files是具体要包含哪些文件
    #其中**表示包含子目录,*表示当前目录下的所有文件
    #下面表示当前subspec包含MyLibrary/cfiles目录及其子目录中的所有.h和.c文件;以及MyLibrary/log目录下的所有.h和.c文件
    subcfiles.source_files = ["MyLibrary/cfiles/**/*.{h,c}",
                              "MyLibrary/log/*.{h,c}"]

    #不包含的文件
    subcfiles.exclude_files = ["MyLibrary/jni/**/*",
                            "MyLibrary/profile/unit_test/*"]

    #加入到pod库中,被一起编译
    #这里通常使用私有第三方库时,需要依赖某个lib或framework时使用。
    #添加如下选项后,会将.a添加到工程中,并且添加LIBRARY_SEARCH_PATHS路径
    #但是需要注意的是,如果使用pod package对该pod库进行打包,这个.a并不会打进去。
    #比如说使用pod package对MyLibrary打包成MyLibrary.a,inner.a并不会被编译进MyLibrary.a。
    #此时,如果如果对外提供MyLibrary.a,inner.a也同样需要提供出去
    subcfiles.vendored_libraries = "MyLibrary/lib/ios/inner.a"

    #pod工程的配置
    #对于HEADER_SEARCH_PATHS,对将设置的字符串直接拷贝到xcode中,不会像上面source_files这样使用相对路径。
    #所以,我在这里先获取当前路径,再设置进去。最后加**表示recursive,即循环查找子目录的意思
    $dir = File.dirname(__FILE__)
    $dir = $dir + "/MyLibrary/cfiles/**"  #$dir:/Users/wangbing/TempCode/MyLibrary/cfiles/**
    subcfiles.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => $dir}

    #demo工程的配置,上面是对pod工程的设置,当需要对demo工程设置时,使用user_target_xcconfig,这里就不做介绍了

    #相对于public_headers,这些文件不会被公开给Demo
    subcfiles.private_header_files = "MyLibrary/cfiles/**/*.h"
    #保护目录结构不变,如果不设置,所有头文件都将被放到同一个目录下
    subcfiles.header_mappings_dir = "MyLibrary/cfiles/**"
    end

# ———— MyLibraryMain ———————————————————————————————#
  #创建一个subspec
  s.subspec 'MyLibraryMain' do |submain|

    #引入代码文件
    submain.source_files = "MyLibrary/main/**/*.{h,m}"

    #设置公开头文件
    submain.public_header_files = "MyLibrary/main/public.h"

    #设置资源文件
    submain.resource  = "MyLibrary/resources/configFiles.bundle"

    #设置MyLibraryMain模块依赖的系统库,注意,这里加的是系统库
    submain.frameworks = "SystemConfiguration"

    #设置依赖,这里可以依赖当前spec中的subspec,也可以依赖github上公开的开源库,如'AFNetworking'。
    submain.dependency "MyLibrary/MyLibraryCFiles"
    end
end

什么情况下会出现头文件中存在多层嵌套呢?

1、当一个库是用c写的
要求在使用该静态库时,要在HEADER_SEARCH_PATHS中添加头文件的路径。
如果podspec中这么写

subcfiles.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" =>"MyLibrary/cfiles/**"}

编译会出错,找不到头文件,因为这个设置在xcode中是这样的:
在这里插入图片描述
处理报错的解决方案:
利用CocoaPods总会添加的两个默认路径,设置header_mappings_dir保护目录结构不发生变化

#设置cfiles及子目录结构保持不变
subcfiles.header_mappings_dir = "MyLibrary/cfiles/**"

#将这些文件设置为private_file或public_file
subcfiles.private_header_files = "MyLibrary/cfiles/**/*.h"

#因为我的C头文件有嵌套,需要查找子目录,所以需要将non-recursive改为recursive
subcfiles.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "${PODS_ROOT}/Headers/Private/**"}

另外两种解决方案:
(1)如果知道Demo工程和lib库之间的路径关系,可以通过${PODS_ROOT}/…/…/MyLibrary/cfiles/**来解决。
(2)通过设置绝对路径来解决:
在podspec中使用ruby脚本,获取当前路径,而podspec和lib库的位置一般不会变,所以最终使用了这种方式来设置HEADER_SEARCH_PATHS。

$dir = File.dirname(__FILE__)
$dir = $dir + "/MyLibrary/cfiles/**"  #$dir:/Users/wangbing/TempCode/MyLibrary/cfiles/**
subcfiles.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => $dir}

这里处理报错选中的方案同样使用了${PODS_ROOT},与方法(1)有什么区别呢?区别就是,如果按照选中的方案,可以忽略Demo工程与lib库的路径关系。因为在执行pod install后,系统会在Pods工程目录下生成Private和Public目录,就不用考虑原来cfiles的路径了,如下图
在这里插入图片描述

2、通过插件grpc_objective_c_plugin和脚本

#!/usr/bin/env bash

function buildProto(){
    if ls "$1"/*.proto > /dev/null 2>&1; then
    		mkdir -p protocol_oc/"$1"
       protoc -I . -I "${GOPATH}"/src --plugin=protoc-gen-grpc=grpc_objective_c_plugin --grpc_out=protocol_oc --objc_out=protocol_oc  "$1"/*.proto
    fi
    for element in "$1"/*; do
        if [[ -d "$element" ]]; then
            buildProto "$element"
        fi
    done
}

path=$1
if [ $# == 0 ]; then
		path=.
fi

buildProto "$path"

生成的oc的.h.m文件,也会出现嵌套头文件的问题

 s.subspec "SomeFunctionSubspec" do |ss|
    ss.source_files = "someFunction/**/*.pbrpc.{h,m}"
    ss.header_mappings_dir = "." #设置子目录结构保持不变
    ss.requires_arc = true
    ss.dependency "gRPC-ProtoRPC"
    ss.dependency "#{s.name}/OtherFunctionSubspec"
  end

  s.pod_target_xcconfig = {
    'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',
	  'USER_HEADER_SEARCH_PATHS' => '$SRCROOT/.. $SRCROOT/../protocol_oc'
  }

注意:
protocol_oc是其他各子目录的根目录,即someFunction目录位于protocol_oc目录之下,
而且podspec文件也位于protocol_oc目录之下

其他备注

① 设置子目录结构保持不变。
ss.header_mappings_dir = “.”
② 设置 HEADER_SEARCH_PATHS, 然而这个最关键,我们怎么才知道自己设置的路径到底对不对呢?在执行 pod spec lint {your project}.podspec --verbose 命令后,控制台上的错误信息还是没办法帮到你。因为你并不清楚最终的头文件在什么目录下。怎么办? 其实最关键的是我们忽略了一个重要的参数 --no-clean 。当 pod spec lint 加上这个参数后,当在lint失败后,cocoapods不会清除对应的目录,我们复制控制台里 pods 的路径,再结合 open 命令便可以进入到 pods 生成的目录,这个时候便一目了然,再去设置头文件搜索路径便轻松多了。另外,在设置HEADER_SEARCH_PATHS 时,借助 ${PODS_ROOT} 这个环境变量便会让你事半功倍,无论你的头文件是在 Headers/Public 下,还是在 Headers/Private 下,抑或又是在其他目录下,现在你可以随心所欲的去设置头文件搜索路径了。

参考连接:
参考1
参考2

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:32:50  更:2022-03-16 22:34:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 18:55:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码