因为公司的需要重新搞了一次CocoaPods,于是记录一下这次折腾下来的整个过程。
准备
开始之前,先说一下开发环境,macOS High Sierra 10.13.1系统(强调这个是因为中间为了它费了不小的功夫)。
开始
因为之前踩了高版本CocoaPods的坑,所以选择了CocoaPods 1.0.1
问题较少的版本作为基本的CocoaPods环境。
安装CocoaPods1.0.1
首先检查一下当前系统ruby版本,应该是要求2.2.2版本以上,终端输入
ruby -v
会显示
ruby 2.3.3p222 (2016-11-21 revision 56859) [universal.x86_64-darwin17]
字样,如果版本过低,请下载rvm自行升级ruby版本。
然后可能还要安装brew、gem这些东西,iOS开发路上应该已经多多少少的了解过这些东西了,不多说。
最后安装主角CocoaPods 1.0.1
:
终端输入
gem install cocoapods -v 1.0.1
在安装各种工具的过程中有一个小插曲,就是提示 /usr/local/*
没有写入权限,这个时候需要在终端输入
sudo chmod -R a+rwx /usr/local/
来修改文件的权限,但是问题又来了,macOS High Sierra 的系统管理员依然没有权限修改文件的权限。。。
网上找了一下,普遍说法10.12系统以后会默认开启内核保护。于是就跟着网上的教程去关闭内核保护:
先关机,然后按开机,在听到开机声音的一瞬间屏幕亮之前按住 Command-R 进入恢复分区。 然后在 实用工具 栏找到 终端启动运行,输入:
csrutil disable
照做了之后,就有修改文件权限的权限了,然后开始
sudo chmod -R a+rwx /usr/local/
修改文件读写权限,终于可以顺利的安装各种工具了。
正儿八经的开始
其实,前面折腾了半天原因是电脑前段时间出现了问题,于是重新安装更新了系统,各种安装过的工具都需要重新安装,如果本身就有CocoaPods1.0左右比较稳定的版本就不需要上面那些步骤了。
回到正题,公司的需求是要把代码托管在自己的git上构建私有仓库,客户端通过CocoaPods方便集成。
文件准备
1、先在自己的服务器上创建git仓库用来托管代码,将git仓库的地址拷贝下来以便告诉CocoaPods从哪里拉取代码,类似这样:
git@git.edtion.tv:edtion/YTStreamingKit.git
https://git.edtion.tv/edtion/YTStreamingKit.git
上面两个地址分别对应SSH和HTTPS两种协议,具同事说,CocoaPods对HTTPS的支持比较好,这个看个人爱好吧。
2、在源码的根目录下添加LICENSE文件,网上很多模板,只要把
Copyright (c) 2017 Edtion@****.com
改成自己需要的样子就可以了
3、项目工程根目录下创建podspec文件:
cd到项目工程根目录下,执行:
pod spec create 工程名称
就会在目录下生成 ****. podspec
文件
编辑****. podspec
文件:
#项目名称
s.name = "YTStreamingKit"
#CocoaPods上对用的版本号
s.version = "0.0.2"
#项目简介
s.summary = "YT streaming SDK."
#项目详细描述
s.description = %{
这是一个私有仓库仅供YT使用!
}
#主页地址
s.homepage = "https://www.edtion.tv"
#license文件的类型和名称 type对应第2步创建的license文件的第一行,是什么类型就写什么类型,我们选择大众型MIT,file对应你的license文件名,我取名为LICENSE
s.license = { :type => "MIT", :file => "LICENSE" }
#开发者姓名和联系邮箱
s.author = { "Edtion" => "edtion@yeah.net" }
#支持的iOS系统最低版本
s.platform = :ios, "8.0"
#源码路径,这里就填写第1步我们的代码仓库地址
s.source = { :git => "https://git.edtion.tv/edtion/YTStreamingKit.git", :tag => s.version }
#源文件路径 一般的OC写的项目只要`{h,m}`就可以了,因为项目中有.c格式的文件,所以改成`{h,m,c}`
s.source_files = "YTStreamingKit/*.{h,m,c}", "YTStreamingKit/Framework*.{h,m,c}"
s.exclude_files = "Classes/Exclude"
到这,遇到了一个问题,项目中用到了其他的第三方lib库和framwork静态库,于是就迷茫了,因为大多数都是说怎样添加xcode自带的依赖库以及同样也托管在CocoaPods上的其他第三方库的方法,并没有说怎么添加项目中的第三方lib库。然后看到了上面的添加源文件路径,是不是可以写成这样{h,m,c,a}
,当时写出来之后自己心里都没谱。。。
后来午休的时候闲着无聊用手机科学上网找了一下,发现了一篇文章有提到添加第三方依赖的方法,感谢作者。
继续编写podspec文件:
#添加项目中的第三方lib
s.vendored_libraries = 'YTStreamingKit/*.{a}'
#添加项目中的第三方framework
s.vendored_frameworks = 'YTStreamingKit/xxxx.framework','YTStreamingKit/xxxx.framework'
#添加资源文件
s.resource_bundles = {'Resources' => 'YTStreamingKit/xxxx.bundle'}
#添加iOS原生framework
s.ios.frameworks = 'Foundation', 'UIKit', 'CoreMotion'
#xcode自带lib
s.library = 'stdc++'
#dependency : 该pod依赖的pod
s.dependency "FFmpeg", "~> 2.8.3"
#build setting 的设置
s.user_target_xcconfig = {'OTHER_LDFLAGS' => ['-lObjC','-all_load']}
#arc模式下运行
s.requires_arc = true
podspec文件基本算是编辑完了
重新回头想了一下{h,m,c,a}
为什么不行,其实参数就已经很好的反映出信息了s.source_files
源文件、有源码的文件,lib当然不是能看见源码的文件 - -!。
4、验证podspec
还是在当前目录,为pod添加版本号,终端运行:
set the new version to 0.0.2
set the new tag to 0.0.2
开始验证
pod spec lint --use-libraries
然后就会各种报错,最主要的是一个不支持模拟器的错误,查资料说只要安装了对应的模拟器就行了,但是我的不一样啊,我的本身就不支持模拟器,最后看到了这篇文章
解决方法是直接修改CocoaPods的验证规范:
1)终端gem which cocoapods
输出:/usr/local/lib/ruby/gems/2.3.0/gems/cocoapods-1.3.0.beta.2/lib/cocoapods.rb
2) 终端open /usr/local/lib/ruby/gems/2.3.0/gems/cocoapods-1.3.0.beta.2/lib/
将第一步命令输出的结果去掉最后的文件名cocoapods.rb,将前面的路径加到 open命令的后面, 执行命令后会在Finder打开一个lib文件夹
3) 在当前lib目录下有个cocoapods文件夹,进入,validator.rb文件就在这个文件夹里找到:
when :ios
command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
command += Fourflusher::SimControl.new.destination('iPhone 4s', deployment_target)
修改为:
when :ios
#command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
#command += Fourflusher::SimControl.new.destination('iPhone 4s', deployment_target)
command += %w(--help)
那么问题又来了,系统提示我文件是lock的状态,并且我没有unlock的权限。。。
又是权限,不用想了,内核保护已经关了,当前用户也是管理员,那最后的权力最大的用户就是ROOT权限的用户了。
启用ROOT用户:
左上角的->系统偏好设置->用户与群组->登录选项->加入->打开目录实用工具
左上角"编辑"->启用ROOT用户 设置好密码之后注销当前用户就可以登录ROOT用户了
登录了ROOT用户就可以执行修改CocoaPods的验证规范
的操作了。
到此,再执行pod spec lint
顺利通过。
5、上传
将上面过程弄好的文件上传到第1步创建的git仓库,并创建0.0.2
分支,分支命名一定要是****. podspec
文件中s.version
对应的版本号,并打上tag0.0.2
。
因为是私有的CocoaPods,我们需要一个托管podspec文件的仓库:
在自己的服务器上创建git仓库
git@git.edtion.tv:edtion/YTPodspec.git
https://git. edtion.tv/edtion/YTPodspec.git
在pod repo中添加托管地址
pod repo add YTPodspec https://git. edtion.tv/edtion/YTPodspec.git
最后上传****. podspec
文件:
pod repo push YTPodspec ****.podspec --use-libraries
到此,我们就创建了CocoaPods私有库。
在项目中引用私有库的时候有一点注意一下,Podfile
文件最开始需要指定repo源地址:
source 'https://git. edtion.tv/edtion/YTPodspec.git'
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
#pod "YTStreamingDemo"
target "YTStreamingDemo" do
pod 'YTStreamingKit', '0.0.2'
end
最后,感谢兄弟全程的陪伴,绕过了很多他前几天他踩过的坑。不然很难这么快搞定。
2017.11.17 更新
私有仓库搭建好之后,用Example工程应用一直在报错,因为之前是用ROOT账户修改validator.rb文件绕过了pod的智能检测,也就避免了检测阶段的各种不通过报错,但是集成到项目中问题就会一一出现。
Command +R 运行Example工程
第一个错误 bitcode enable错误,这个问题大家都知道,在xcode里面点击Project选择相应的targets ,Build Setting 的tab下搜索 Bitcode Enable 将Yes改成No,然后运行。。。还是一样的错误。
最后的解决方法:在Example工程的Podfile文件中添加如下代码:
post_install do |installer|
installer.pods_project.targets.each do |target|
installer.pods_project.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
再次运行,遇见第二个错误,引用的第三方Framework找不到ffmpeg的头文件
Undefined symbols for architecture arm64:
"_av_frame_unref", referenced from:
AVE::CGenericRefObjAllocator<AVE::AVFramePool::AVFrameBlock>::CNode::Release() in ****(libve.a-arm64-master.o)
因为我们的播放器也引用了ffmpeg的头文件,所以这个报错的第三方Framework是要求不要有ffmpeg库的,所以就想到了用pod依赖,pod search ffmpeg
一下,发现pod上有ffmpeg,直接在podspec文件里添加s.dependency "FFmpeg", "~> 2.8.3"
然后在pod install
的时候出现问题了,错误如下:
The 'Pods-YTStreamingKit_Example' target has transitive dependencies that include static binaries: (****/****/libavcodec.a)
过度引用。。
然后继续找问题,发现大家都是把Podfile里面的use_frameworks!
一行删掉了,就是让pod打包成.a
形式的lib文件引用到项目中,这点之前疏忽了,因为framwork只支持iOS8以上系统,我们的主App是要支持iOS7以上的,所以这块是一定要删掉的。
删掉之后继续编译运行,还有错误:
/Users/edtion/Documents/YTStreamingKit/YTStreamingKit/Example/Pods/../../YTStreamingKit/Classes/****.framework/Headers/****.h:17:9: error: include of non-modular header inside framework module '****': '/Users/edtion/Documents/YTStreamingKit/YTStreamingKit/Example/Pods/Headers/Public/YTStreamingKit/****/****.h' [-Werror,-Wnon-modular-include-in-framework-module]
#import <****/****.h>
第三方的framework平时用很方便,怎么到这里就会有这种错误,然后就检查了一下SDK里面引用到这个****.framework的代码,发现是用@import ****;
的方式引用的,并不是常规的 #import <****/****.h>
引用头文件方式,于是改回常规方式。
Command +R
: everything is perfect!
ps:@import ****;
方式引用第三方Framework头文件会把Framework的头文件添加到Modules中,而可能是由于CocoaPods较低的原因,并不支持以这种方式引用第三方Framework。
参考文献:
iOS组件化之cocopods私有库搭建
Cocoapods1.0.1版本安装教程
cocoapods 从1.0.0降到0.39.0问题
如何将自己的项目添加Pod
在自己的私有服务器上创建Git仓库
使用私有Cocoapods仓库 中高级用法
解决pod lib lint/repo push不支持i386编译&只能真机运行的库
mac 查看、修改文件权限的命令
CocoaPods官方文档
网友评论