项目开源解决方案

背景

计划将改进后的CroNet单独开源给用户,让用户也能编译及调试,但部分代码不能开源(目前主要是包含加密算法的boringssl代码)。
因此,需要有一个开源方案,使得用户仅获取部分代码,但依然可以编译出包含完整功能的CroNet库。

解决思路

编译本质上是将代码翻译成机器可执行的二进制,因此在没有代码的情况下,直接提供二进制参与链接理论上是可行的。

因此该问题的解决思路是,将boringssl代码编译打包成libboringssl.a静态库,随代码库发布,用户使用时直接将libboringssl.a当做基础lib库。

技术难点

这里的技术难点主要是如何将libboringssl.a库以恰当的方式链接进最终产物。

在这之前,我们可以先产出一个不包含libboringssl.a的最终产物,做法是把boringssl的.cc代码都移除,只保留include头文件,再调整一下编译配置即可。

而最终如何发生链接的可行方案如下:

方案描述 优点 缺点 补充说明
用户手动将libboringssl.a加入link列表中 CroNet不需要过多改动 需要开源用户配合不同IDE、系统,进行最终链接方式不一样 例如编译iOS时,用户将CroNet.framework 与 libboringssl.a都添加到Xcode的link库配置中。
CroNet编译链接过程中,修改编译文件(.ninja)使其主动链接libboringssl.a 对开源用户无感知 对CroNet改动较大实现方式比较trick,可能需要两次编译(编译过程同时修改编译文件可能不会对本次编译生效 由于编译阶段才会出现.ninja编译文件,并且我还需要获取当前的编译参数(如当前系统版本)决定链接哪个版本的libboringssl.a。因此只能在编译阶段触发某个脚本同时进行。
实现编译后置配置(ninja支持)在编译最后对libboringssl进行链接 对开源用户无感知 实现方式遵循ninja编译流程(相较上一个方案不那么trick) 对CroNet改动较大 ninja支持动态库使用libs= [“”]表示需要链接某个已存在的库,并支持action描述后置脚本动作,可用于静态库在最终阶段通过后置动作链接某个库

实际上方案2是在探索TurboNet自己链接方案的一个失败阶段,主要是方案比较trick结果又不完全符合预期,所以才重新构思了解决方案。

最终采用了第三个方案。

具体实现

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
// third_party/boringssl/BUILD.gn
# Support header files for compilation without source codes.
# 定义一个编译配置,将使用boringssl所需要的头文件加载进来
config("lazy_build_config") {
include_dirs = [ "//baidu/build/boringssl/include" ]
}
component("boringssl") {
# (Baidu Modified)
# (Baidu Added)
# Linking libs directly if it is open source solution.
# 定义了一个开关,如果打开,说明采取开源解决方案,直接link已存的lib
if (is_turbonet_opensource) {
assert(is_android || is_ios || is_linux || is_mac, "Your target_os doesn't support open source.")
public_configs = [ ":lazy_build_config" ]
# 对于动态库来说,直接使用gn & ninja编译机制的libs机制进行链接即可
if (!is_turbonet_static) {
if (is_ios) {
libs = [ "//baidu/build/boringssl/ios/libboringssl_shared.a" ]
} else if (is_android) {
libs = [ "//baidu/build/boringssl/android/libboringssl.a" ]
} else if (is_linux) {
libs = [
"//baidu/build/boringssl/linux/libboringssl.a",
# 对于非移动端操作系统,需要再link下asm库
"//baidu/build/boringssl/linux/libboringssl_asm.a"
]
} else if (is_mac) {
libs = [
"//baidu/build/boringssl/mac/libboringssl.a",
"//baidu/build/boringssl/mac/libboringssl_asm.a"
]
}
}
# (Baidu Added End)
} else {
# 如果关闭了开源开关(默认也是关闭的),走原本逻辑,源代码都在all_sources里
sources = all_sources
deps = [
":boringssl_asm",
]
public_configs = [ ":external_config" ]
configs += [ ":internal_config" ]
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
# (Baidu Added)
# Fix symbols conflict for static library
if (is_ios && is_turbonet_static) {
configs += [ ":boringssl_preheader" ]
}
# (Baidu Added End)
if (is_nacl) {
deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
}
}
# (Baidu Modified End)
}

收益点

  • 提供了CroNet缺失部分代码情况下编译出完整功能的能力,解决了代码开源的关键问题。

  • 做到了对用户透明,开关化灵活控制。