使用BUCK进行iOS项目打包

关于BUCK

BUCK是Facebook开源的快速打包工具,可以用于多种语言及平台的项目打包,例如:C、C++、Java、iOS、Android等等。用于大型的iOS、Android项目,可以显著提升打包效率。
关于BUCK介绍的一些链接如下:
BUCK官网
What Makes Buck so Fast?:介绍了BUCK如何做到性能提升
BUCK源码: 里面有源码和大量Unit Test提供了很多示例,同时查看Issues可以找到很多问题的解决方案
iOS快速编译BUCK
基于Facebook Buck改造Android构建系统之初体验

核心概念

Build Rule

A **build rule **is a procedure for producing an output file from a set of input files.

Build Target

A **build target **is a string that is used to identify a build rule in your project.

Build File

A **build file **is a file named BUCK that defines one or more build rules.

.buckconfig

The root of your project must contain a configuration file named.buckconfig.

iOS打包相关Rule

Rule 产出 作用
apple_asset_catalog() 没有特定产出,可以作为apple_bundle()的依赖 Contains resources stored in Apple asset catalog directories
apple_binary() 静态库:.a file An apple_binary() rule builds a native executable from the supplied set of Objective-C/C++ source files
apple_bundle() .app 或者 .appex (apple watch extension) An apple_bundle() rule takes an Apple binary and all of the resources and asset catalogs in the rule's transitive dependencies and generates a bundle containing all of those files.
apple_library() 静态库:.a file An apple_library() rule represents a set of Objective-C/C++ source files
apple_package() ipa file An apple_package() rule takes the output of an apple_bundle() rule and compresses it in an IPA (iOS App Store Package) file.
apple_resource() This rule does not have any output on its own and can be built only as a dependency (either direct or transitive) of an apple_bundle() rule. An apple_resource() rule contains sets of resource directories, files and file variants that can be bundled in an application bundle.
apple_test() An apple_test() rule contains Objective-C/C++ code which can be built and used to test code contained in other rules.
core_data_model() This rule does not have any output on its own and can be built only as a dependency (either direct or transitive) of an apple_bundle() rule, in which case all core_data_model() rules that the bundle rule depends on are merged and placed into the final output bundle together. An core_data_model() rule contains models for Apple's Core Data framework.
prebuilt_apple_framework() 引用.framework库

使用BUCK用于iOS工程打包

目录组织结构

对于一个多个子工程组成,通过依赖关系最终集成为单个可执行文件。使用BUCK,需要为每一个子工程都创建BUCK文件,在根目录配置.buckconfig。大致目录结构如下:

|—.buckconfig
|—BUCK
|—SubProject1
|---------src
|---------BUCK
|—SubProject2
|---------src
|---------BUCK
|—SubProject3
|---------src
|---------BUCK
|—SubProject4
|---------src
|---------BUCK
......

每个子工程的BUCK文件,负责配置build rule,生成静态.a 文件,然后最终通过根目录中的BUCK,来生成.ipa文件。

.buckconfig配置

[cache]
mode=dir

[cxx]
cflags= -std=gnu11
cxxflags= -std=c++14-stdlib=libc++default_platform= iphonesimulator-x86_64
combined_preprocess_and_compile=true

[alias]
SubProject1=//SubProject1: SubProject1Lib
SubProject2 =//SubProject2: SubProject2Lib
SubProject3 =//SubProject3: SubProject3Lib
SubProject4 =//SubProject4: SubProject4Lib

[apple]
xctool_zip_target=//third-party/ios/xctool:xctool-minimal-zip[project]
ignore=.buckd, \
.hg, \
.git, \
.idea, \
buck-cache, \
buck-out, \

cxx:定义了一些C++编译的参数
alias: 定义了一些build target的别名。例如CTFoundation为例,在CTFoundation中的BUCK文件中定义了CTFoundationLib的rule,所以如果要打包CTFoundation,可以通过别名的方式,命令如下:

# 未用别名
buck build//SubProject1:SubProject1Lib
# 使用别名
buck build SubProject1

apple: 指定了xctool的文件地址。Buck的iOS打包是依赖于xctool,所以需要把xctool的相关代码引入,具体内容可以参考示例:

git clone git@github.com:fbsamples/bucksamples.git
cd bucksamples/cross-platform-scale-2015-demo/

BUCK文件配置

独立子工程的BUCK配置

下面以一个独立的子工程作为示例,而且没有其他依赖,所以可以作为第一个示例。它的BUCK文件配置如下:

apple_library(
  name='SubProject1Lib',
  preprocessor_flags= ['-fobjc-arc','-Wno-deprecated-declarations','-fmodules'],
  compiler_flags= ['-Wno-objc-designated-initializers','-fembed-bitcode'],
  linker_flags=['-F$DEVELOPER_DIR/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks','-F$DEVELOPER_DIR/../SharedFrameworks','-F$DEVELOPER_DIR/Library/PrivateFrameworks',
  ],
  srcs= glob(['src/**/**/**/*.m',]),
  frameworks=['$SDKROOT/System/Library/Frameworks/Foundation.framework',],
  exported_headers={
    'xxx1.h':'./src/xxx.h',
    'xxx2.h':'./src/xxx2.h',
    ...
  },
  #header_namespace='',
  visibility=['PUBLIC'],
)

整个BUCK文件就一个apple_library,产出libCTLocation.a文件。可以看到里面可以指定一下编译的flags、依赖的framework、源代码、对外暴露的头文件等等。
通过命令 buck build CTLocation就可以打包查看,在buck-out目录中可以看到生成出来的.a文件。

需要注意的exported_headers的配置:
The set of header files that are made available for inclusion to the source files in this target and all targets that transitively depend on this one. These should be specified as either a list of header files or a dictionary of header names to header files. The header names can contain forward slashes (/). If a list of header files is specified, the headers can be imported with#import "$HEADER_PATH_PREFIX/$HEADER_NAME"or, if a header file that belongs to the same rule is being imported, with#import "$HEADER_NAME", where$HEADER_PATH_PREFIXis the value of the target'sheader_path_prefixattribute, and$HEADER_NAMEis the filename of the header file. If a dictionary is specified, each header can be imported with#import "$HEADER_NAME", where$HEADER_NAMEis the key corresponding to this file. In this case, theheader_path_prefixattribute is ignored. In either case, quotes in the import statements can be replaced with angle brackets.

可以有两种配置格式,数组和字典。
使用数组的时候,其他代码引用是需要加上前缀例如:#import "SubProject1/xxx.h",默认前缀和apple_library的name一致,可以通过设置header_path_prefix改变。
使用字典的时候,其他代码引用时候可以通过key来引用,例如:

//BUCK配置:
exported_headers ={'xxx.h':'./src/xxx.h',}

//其他代码引用
#import"xxx.h"

依赖资源文件

如果代码中有资源文件,需要通过apple_resource来引用

apple_resource(
name='SubProject1Resource',
files= glob(['*.png']),
dirs=[],
)

特殊的Compiler flag

在iOS中,有些源代码需要一些特殊的compiler flag,例如非ARC的源码。在src里面可以进行配置:

srcs = glob(['SubProject1/**/**/**/*.m',], excludes = ['**/**/xxx1.m','**/**/xxx2.m'])+[('src/xxx1.m', ['-Wno-shorten-64-to-32']),
('src/xxx2.m', ['-fno-objc-arc'])]

引用外部framework

prebuilt_apple_framework(
name='BuckTest',
framework='BuckTest.framework',
preferred_linkage='shared',
visibility= ['PUBLIC'],
)

引用外部.a 静态库

如下项目有依赖外部的.a库,可以通过以下方法引用


cxx_library(
  name='lib1',
  srcs=[],
  exported_headers={'xxx.h':'libs/xxx.h',},
  visibility= ['PUBLIC'],
)

apple_library(
  name='SubProject1Lib',
  deps= [':lib1'],
  ...
  libraries=['libs/xxx.a',],
)

当前BUCK的局限性

BUCK本身目前还在快速迭代中,所以很多rule还没有完善、文档不全,社区也够活跃,遇到问题会比较难找到解决方案。
目前iOS项目中碰到的一些限制问题:

  • 自定义的script,在XCode的build phase中可以自定义一些shell脚本,但是在BUCK中没有找到对应的方式
  • 无法生成.bundle资源包,iOS打包过程中每个子工程都会产出一个.a和.bundle文件,但是BUCK打包不会产出.bundle文件只会有.a,资源文件只能通过apple_resource()来管理作为其他rule的依赖。
  • 通过apple_library()生成.a文件似乎目前还没办法指定valid architectures。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,079评论 25 707
  • 很喜欢带窗户的房间,尤其是那种大大的落地窗,配上白色的纱帘,在夏夜的微风中飘荡。倘若是墙体窗,一定要有一个小窗台,...
    Log君阅读 864评论 0 1
  • 大漠风暴中,卷走了一棵树。那棵树的根扎的很深,可即便如此,还是被风暴连根拔起。 那一日与往日并没有什么不同,都是太...
    恬冼阅读 193评论 0 0
  • 七十二賢学众筹 筹人筹智共谋求 沉积资源齐分享 山后青山楼外楼 2017.2.27.宋刚. 京西南郊
    宋刚易海游龍阅读 158评论 0 1