- 由于 .a 会把引用一起打包, 所以当有多个 .a 的时候很有可能会有引用冲突, 也就是 .o 重复定义
- 假设 gt.a 与 ali.a 冲突, 我们决定把冲突的 .o 从 gt.a 中摘出来
- 先查看 gt.a 是由哪些平台的包组成的
1 | $ lipo -info gt.a |
我们先处理 armv7 下的包, 先把它摘出来
1
$ lipo gt.a -thin armv7 -output armv7/gt-armv7.a
把包解压, 会得到一堆 .o
1
armv7 $ ar xv gt-armv7.a
找到冲突的 .o 删除之, 最好这时候把 gt-armv7.a 也删除并且删除时要清空回收站, 要不然还会把删除的包打包进去
1
armv7 $ ar rcs gt-armv7.a *.o
将其他几个平台也按上述步骤操作
重新合并几个平台的包
1
$ lipo -create gt_armv7.a gt_armv7s.a gt_x86_64.a -output gt.a
把新生成的 .a 覆盖项目中的 .a 就行了
—分割线—
- 网上大多数文章到此结束了, 但是没人觉得上面的步骤很繁琐么, 我们是程序猿, 怎么能忍, 写了个脚本, 源码如下(需要把脚本和需要处理的 .a 放在同一目录下)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64#!usr/bin/env ruby
module FilterConstants
CONFLICT_OS = ['NSObject+JSON.o'].freeze
TARGET_A = 'gt.a'.freeze
end
class ConflictFilter
attr_reader :target_a, :conflict_os
def initialize(target_a, conflict_os)
@target_a = target_a
@conflict_os = conflict_os
end
def get_platforms
platforms = `lipo -info #{target_a}`.split(' ') & %w(armv7 armv7s arm64 i386 x86_64)
block_given? ? yield(platforms) : platforms
end
def create_platform_directory(platform)
`mkdir ./#{platform}`
end
def get_thin_a(plat_form)
a_path = "./#{plat_form}/#{target_a}"
`lipo #{target_a} -thin #{plat_form} -output #{a_path}`
a_path
end
def unzip_a(a_path)
`cd #{File.dirname(a_path)} && ar xv #{File.basename(a_path)}`
end
def delete_conflict_os(a_path)
conflict_os.each do |o|
`cd #{File.dirname(a_path)} && rm #{o}`
end
`cd #{File.dirname(a_path)} && rm #{File.basename(a_path)} && rm __*`
end
def zip_a(a_path)
`cd #{File.dirname(a_path)} && ar rcs #{File.basename(a_path)} *.o && rm *.o`
end
def merge_multi_platform_a
`rm #{target_a} && lipo -create ./*/*a -output #{target_a}`
end
def filter
get_platforms do |platforms|
platforms.each do |p|
create_platform_directory(p)
a_path = get_thin_a(p)
unzip_a(a_path)
delete_conflict_os(a_path)
zip_a(a_path)
end
end
merge_multi_platform_a
end
end
if $PROGRAM_NAME == __FILE__
ConflictFilter.new(FilterConstants::TARGET_A, FilterConstants::CONFLICT_OS).filter
end