在Ubuntu 16.04上使用bazel交叉编译tensorflow
鸽了这么久,正式开工
Author: carbon
email: ecras_y@163.com
参考资料:
https://github.com/tensorflow/tensorflow
https://github.com/snipsco/tensorflow-build
年中6月份的时候被抽到AI项目组,有幸接触目前最火的深度学习神经网络,
从开始到现在,一直坚守在google的tensorflow
目前行业的趋势是在PC或者服务器集群上进行训练,然后将训练好的模型export到mobile设备上,
由mobile设备加载使用这些训练好的模型。
我早几年前做过很多嵌入式的项目,所以将tensorflow移植到mobile嵌入式平台上的任务就落到了我的身上,我也当仁不让,
一撸到底。
目前仅支持交叉编译tensorflow的c和c++模块。
python模块由于链接目标库问题,在mobile设备上也没有训练模型的需求,
兼具性能的考虑,暂时没做python这一块的交叉编译支持。感兴趣的同学可以自己试试看。
测试板子使用树莓派,
树莓派可以跑完整的Linux操作系统,如果需要在树莓派上运行基于python的tensorflow,
需要在树莓派上进行编译,但是可能需要编译几天时间
基于以后可能需要将项目export到其它的嵌入式系统上,需要考虑到通用性
Android的编译比较特殊,直接使用官方的预编译好的组件即可
这里只考虑非Android和iOS的嵌入式平台
tensorflow编译使用bazel进行自动化编译管理,涉及到:
1. 子模块网络下载
2. 预编译期代码生成(generate files)
3. 模块之间依赖判定
4. 代码编译
如果将工程更改为Makefile编译,工作量巨大,难以操作
最好的做法还是使用bazel,加入交叉编译支持
bazel交叉编译官方有一些指导文档,有很好的参考意义
https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain
下载源码
使用git命令下载tensorflow源码
git clone git@github.com:tensorflow/tensorflow.git
google在最近发布了tensorflow lite,用于支持mobile设备,
更小的编译目标文件,更好的性能
但是还没有export到最新的tag中,所以这里我们直接基于master分支来操作
git checkout master
git checkout -b cross-compile
文章最后加入对交叉编译tensorflow lite的说明
编译之前需要先修正数据对齐bug
x86和x64平台无对齐问题
但是在某些arm平台上,需要地址对齐,
否则程序会在运行时,访问内存奇数地址或者未对齐地址,导致crash
vim tensorflow/core/lib/gtl/inlined_vector.h +288
将 T* unused_aligner 替换为 uint64_t unused_aligner
强制为8字节对齐
准备交叉编译工具链
这里以树莓派为例
git clone https://github.com/raspberrypi/tools.git
下载完成之后,将工具链路径添加到PATH中
脚本编写
目录结构
.
└── tensorflow
├── armv6-compiler
│ ├── BUILD
│ ├── CROSSTOOL
│ └── cross_toolchain_target_armv6.BUILD
├── build_armv6.sh
├── build_tflite.sh
└── WORKSPACE
1. 修改WORKSPACE文件,添加交叉编译工具链仓库描述
打开WORKSPACE文件,按照bazel的语法在文件末尾添加以下内容
new_local_repository(
name='toolchain_target_armv6',
path='/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf',
build_file = 'armv6-compiler/cross_toolchain_target_armv6.BUILD'
)
参数说明:
交叉编译工具链别名: toolchain_target_armv6
交叉编译工具链路经: /path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf
交叉编译工具链描述文件: armv6-compiler/cross_toolchain_target_armv6.BUILD
2. 编写WORKSPACE仓库引用的交叉编译工具链的BUILD描述文件
mkdir armv6-compiler && cd armv6-compiler
touch cross_toolchain_target_armv6.BUILD
vi cross_toolchain_target_armv6.BUILD
具体语法规则参考详见
https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain
脚本内容如下:
1 package(default_visibility = ['//visibility:public']) 2 3 filegroup( 4 name = 'gcc', 5 srcs = [ 6 'bin/arm-linux-gnueabihf-gcc', 7 ], 8 ) 9 10 filegroup( 11 name = 'ar', 12 srcs = [ 13 'bin/arm-linux-gnueabihf-ar', 14 ], 15 ) 16 17 filegroup( 18 name = 'ld', 19 srcs = [ 20 'bin/arm-linux-gnueabihf-ld', 21 ], 22 ) 23 24 filegroup( 25 name = 'nm', 26 srcs = [ 27 'bin/arm-linux-gnueabihf-nm', 28 ], 29 ) 30 31 filegroup( 32 name = 'objcopy', 33 srcs = [ 34 'bin/arm-linux-gnueabihf-objcopy', 35 ], 36 ) 37 38 filegroup( 39 name = 'objdump', 40 srcs = [ 41 'bin/arm-linux-gnueabihf-objdump', 42 ], 43 ) 44 45 filegroup( 46 name = 'strip', 47 srcs = [ 48 'bin/arm-linux-gnueabihf-strip', 49 ], 50 ) 51 52 filegroup( 53 name = 'as', 54 srcs = [ 55 'bin/arm-linux-gnueabihf-as', 56 ], 57 ) 58 59 filegroup( 60 name = 'compiler_pieces', 61 srcs = glob([ 62 'arm-linux-gnueabihf/**', 63 'libexec/**', 64 'lib/gcc/arm-linux-gnueabihf/**', 65 'include/**', 66 ]), 67 ) 68 69 filegroup( 70 name = 'compiler_components', 71 srcs = [ 72 ':gcc', 73 ':ar', 74 ':ld', 75 ':nm', 76 ':objcopy', 77 ':objdump', 78 ':strip', 79 ':as', 80 ], 81 )
3. 编写CROSSTOOL文件
CROSSTOOL文件负责描述交叉编译工具链,从编译选项到链接选项,非常繁杂
很多选项是放屁脱裤子,吃力不讨好
愚以为这bazel有点反人类阿
文件内容以下:
1 major_version: "local" 2 minor_version: "" 3 default_target_cpu: "armv6" 4 5 default_toolchain { 6 cpu: "armv6" 7 toolchain_identifier: "arm-linux-gnueabihf" 8 } 9 10 default_toolchain { 11 cpu: "k8" 12 toolchain_identifier: "local" 13 } 14 15 toolchain { 16 abi_version: "gcc" 17 abi_libc_version: "glibc_2.23" 18 builtin_sysroot: "" 19 compiler: "compiler" 20 host_system_name: "raspberrypi" 21 needsPic: true 22 supports_gold_linker: false 23 supports_incremental_linker: false 24 supports_fission: false 25 supports_interface_shared_objects: false 26 supports_normalizing_ar: true 27 supports_start_end_lib: false 28 supports_thin_archives: true 29 target_libc: "glibc_2.23" 30 target_cpu: "armv6" 31 target_system_name: "raspberrypi" 32 toolchain_identifier: "arm-linux-gnueabihf" 33 34 tool_path { name: "ar" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-ar" } 35 tool_path { name: "compat-ld" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-ld" } 36 tool_path { name: "cpp" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-cpp" } 37 tool_path { name: "dwp" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-dwp" } 38 tool_path { name: "gcc" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc" } 39 tool_path { name: "gcov" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcov" } 40 tool_path { name: "ld" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-ld" } 41 tool_path { name: "nm" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-nm" } 42 tool_path { name: "objcopy" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-objcopy" } 43 objcopy_embed_flag: "-I" 44 objcopy_embed_flag: "binary" 45 tool_path { name: "objdump" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-objdump" } 46 tool_path { name: "strip" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-strip" } 47 48 compiler_flag: "-nostdinc" 49 compiler_flag: "-mfloat-abi=hard" 50 compiler_flag: "-mfpu=neon-vfpv4" 51 compiler_flag: "-funsafe-math-optimizations" 52 53 compiler_flag: "-isystem" 54 compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/include" 55 compiler_flag: "-isystem" 56 compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/usr/include" 57 compiler_flag: "-isystem" 58 compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/include" 59 60 compiler_flag: "-isystem" 61 compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.3/include" 62 compiler_flag: "-isystem" 63 compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.3/include-fixed" 64 65 compiler_flag: "-isystem" 66 compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3" 67 compiler_flag: "-isystem" 68 compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3/arm-linux-gnueabihf" 69 70 cxx_flag: "-isystem" 71 cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/include" 72 cxx_flag: "-isystem" 73 cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/usr/include" 74 cxx_flag: "-isystem" 75 cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/include" 76 cxx_flag: "-isystem" 77 cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3" 78 cxx_flag: "-isystem" 79 cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3/arm-linux-gnueabihf" 80 cxx_flag: "-std=c++11" 81 82 cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/include" 83 cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/usr/include" 84 cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/include" 85 cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.3/include" 86 cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.3/include-fixed" 87 cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3" 88 cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3/arm-linux-gnueabihf" 89 90 linker_flag: "-lstdc++" 91 linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/lib" 92 linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/arm-linux-gnueabihf/lib" 93 linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/lib" 94 linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib" 95 linker_flag: "-Wl,--dynamic-linker=/lib/ld-linux-armhf.so.3" 96 97 # Anticipated future default. 98 # This makes GCC and Clang do what we want when called through symlinks. 99 unfiltered_cxx_flag: "-no-canonical-prefixes" 100 linker_flag: "-no-canonical-prefixes" 101 102 # Make C++ compilation deterministic. Use linkstamping instead of these 103 # compiler symbols. 104 unfiltered_cxx_flag: "-Wno-builtin-macro-redefined" 105 unfiltered_cxx_flag: "-D__DATE__=\"redacted\"" 106 unfiltered_cxx_flag: "-D__TIMESTAMP__=\"redacted\"" 107 unfiltered_cxx_flag: "-D__TIME__=\"redacted\"" 108 109 # Security hardening on by default. 110 # Conservative choice; -D_FORTIFY_SOURCE=2 may be unsafe in some cases. 111 # We need to undef it before redefining it as some distributions now have 112 # it enabled by default. 113 compiler_flag: "-U_FORTIFY_SOURCE" 114 compiler_flag: "-fstack-protector" 115 compiler_flag: "-fPIE" 116 linker_flag: "-pie" 117 linker_flag: "-Wl,-z,relro,-z,now" 118 119 # Enable coloring even if there's no attached terminal. Bazel removes the 120 # escape sequences if --nocolor is specified. 121 compiler_flag: "-fdiagnostics-color=always" 122 123 # All warnings are enabled. Maybe enable -Werror as well? 124 compiler_flag: "-Wall" 125 # Enable a few more warnings that aren't part of -Wall. 126 compiler_flag: "-Wunused-but-set-parameter" 127 # But disable some that are problematic. 128 compiler_flag: "-Wno-free-nonheap-object" # has false positives 129 130 # Keep stack frames for debugging, even in opt mode. 131 compiler_flag: "-fno-omit-frame-pointer" 132 133 # Stamp the binary with a unique identifier. 134 linker_flag: "-Wl,--build-id=md5" 135 linker_flag: "-Wl,--hash-style=gnu" 136 137 compilation_mode_flags { 138 mode: DBG 139 # Enable debug symbols. 140 compiler_flag: "-g" 141 } 142 compilation_mode_flags { 143 mode: OPT 144 145 # No debug symbols. 146 # Maybe we should enable https://gcc.gnu.org/wiki/DebugFission for opt or 147 # even generally? However, that can't happen here, as it requires special 148 # handling in Bazel. 149 compiler_flag: "-g0" 150 151 # Conservative choice for -O 152 # -O3 can increase binary size and even slow down the resulting binaries. 153 # Profile first and / or use FDO if you need better performance than this. 154 compiler_flag: "-O3" 155 156 # Disable assertions 157 compiler_flag: "-DNDEBUG" 158 159 # Removal of unused code and data at link time (can this increase binary size in some cases?). 160 compiler_flag: "-ffunction-sections" 161 compiler_flag: "-fdata-sections" 162 linker_flag: "-Wl,--gc-sections" 163 } 164 } 165 166 toolchain { 167 toolchain_identifier: "local" 168 abi_libc_version: "local" 169 abi_version: "local" 170 builtin_sysroot: "" 171 compiler: "compiler" 172 compiler_flag: "-U_FORTIFY_SOURCE" 173 compiler_flag: "-D_FORTIFY_SOURCE=2" 174 compiler_flag: "-fstack-protector" 175 compiler_flag: "-Wall" 176 compiler_flag: "-Wl,-z,-relro,-z,now" 177 compiler_flag: "-B/usr/bin" 178 compiler_flag: "-B/usr/bin" 179 compiler_flag: "-Wunused-but-set-parameter" 180 compiler_flag: "-Wno-free-nonheap-object" 181 compiler_flag: "-fno-omit-frame-pointer" 182 compiler_flag: "-isystem" 183 compiler_flag: "/usr/include" 184 cxx_builtin_include_directory: "/usr/include/c++/5.4.0" 185 cxx_builtin_include_directory: "/usr/include/c++/5" 186 cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5/include" 187 cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu/c++/5.4.0" 188 cxx_builtin_include_directory: "/usr/include/c++/5.4.0/backward" 189 cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5.4.0/include" 190 cxx_builtin_include_directory: "/usr/local/include" 191 cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5.4.0/include-fixed" 192 cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed" 193 cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu" 194 cxx_builtin_include_directory: "/usr/include" 195 cxx_flag: "-std=c++11" 196 host_system_name: "local" 197 linker_flag: "-lstdc++" 198 linker_flag: "-lm" 199 linker_flag: "-Wl,-no-as-needed" 200 linker_flag: "-B/usr/bin" 201 linker_flag: "-B/usr/bin" 202 linker_flag: "-pass-exit-codes" 203 needsPic: true 204 objcopy_embed_flag: "-I" 205 objcopy_embed_flag: "binary" 206 supports_fission: false 207 supports_gold_linker: false 208 supports_incremental_linker: false 209 supports_interface_shared_objects: false 210 supports_normalizing_ar: false 211 supports_start_end_lib: false 212 supports_thin_archives: false 213 target_cpu: "k8" 214 target_libc: "local" 215 target_system_name: "local" 216 unfiltered_cxx_flag: "-fno-canonical-system-headers" 217 unfiltered_cxx_flag: "-Wno-builtin-macro-redefined" 218 unfiltered_cxx_flag: "-D__DATE__=\"redacted\"" 219 unfiltered_cxx_flag: "-D__TIMESTAMP__=\"redacted\"" 220 unfiltered_cxx_flag: "-D__TIME__=\"redacted\"" 221 tool_path {name: "ar" path: "/usr/bin/ar" } 222 tool_path {name: "cpp" path: "/usr/bin/cpp" } 223 tool_path {name: "dwp" path: "/usr/bin/dwp" } 224 tool_path {name: "gcc" path: "/usr/bin/gcc" } 225 tool_path {name: "gcov" path: "/usr/bin/gcov" } 226 tool_path {name: "ld" path: "/usr/bin/ld" } 227 tool_path {name: "nm" path: "/usr/bin/nm" } 228 tool_path {name: "objcopy" path: "/usr/bin/objcopy" } 229 tool_path {name: "objdump" path: "/usr/bin/objdump" } 230 tool_path {name: "strip" path: "/usr/bin/strip" } 231 232 compilation_mode_flags { 233 mode: DBG 234 compiler_flag: "-g" 235 } 236 compilation_mode_flags { 237 mode: OPT 238 compiler_flag: "-g0" 239 compiler_flag: "-O3" 240 compiler_flag: "-DNDEBUG" 241 compiler_flag: "-ffunction-sections" 242 compiler_flag: "-fdata-sections" 243 linker_flag: "-Wl,--gc-sections" 244 } 245 linking_mode_flags { mode: DYNAMIC } 246 }
toolchain:
有两个描述
一个用于描述交叉编译工具链
一个用于描述本地编译环境
tensorflow编译时会同时用到本地编译环境和交叉编译环境
本地编译描述使用bazel build官网的描述即可
以下为交叉编译描述的一些事项:
abi_libc_version:
target_libc:
可以通过以下代码提前获取
printf("GNU libc version: %s\n", gnu_get_libc_version());
host_system_name:
树莓派3的值是armeabi-v6
Android的一般是armeabi-v7a
全志A33的也是armeabi-v7a
target_cpu:
树莓派3的值是armv6
Android的一般是armeabi-v7a
这个值需要和BUILD文件里面的描述一致
同时编译时--cpu来指定该用哪个交叉编译工具链
tensorflow里面有些依赖的模块BUILD文件描述里会用到这个值,稍后提到
tool_path:
涉及到的变量,替换为交叉编译工具链的绝对路径即可
compiler_flag:
编译选项,由于嵌入式平台,所以-nostdinc是必须的,否则会提示缺失头文件导致编译失败
-isystem 用于设置include的系统头文件目录
可以在交叉编译的工具链目录使用find命令查找
find /path/to/toolchain -name 'include*' -type d
一般找到的目录包括include和include-fixed,而且不会遗漏sysroot中的目录
其实这一步令人非常不解,因为工具链知道自己的头文件目录,根本不需指定
使用这个方法,导致可能会遗漏导致编译失败
cxx_flag:
和compiler_flag大同小异,需要额外指定c++的头文件目录
同时多了一个-std=c++11的值,用于开启c++11的特性
如果工具链不支持c++11,可以关掉
cxx_builtin_include_directory:
我觉得这个值和cxx_flag描述重复了
但是为了避免出错,依葫芦画瓢,把cxx_flag的值重新赋给它即可
linker_flag:
编译链接选项
主要是指定链接库
因为使用了c++11特性,第一个值就是-lstdc++
其它的值可以使用find命令查找
find /path/to/toolchain -name 'lib*' -type d
将查找结果赋值给-L即可
最后一个值是指定linker的加载器
典型值是-Wl,--dynamic-linker=/lib/ld-linux-armhf.so.3
可以在嵌入式设备上使用find命令找到具体的值
find / -name 'ld*' -type f
4. 编写BUILD文件
The BUILD file next to the CROSSTOOL is what ties everything together.
这个BUILD文件负责将以上的东西都串联起来,组成一个交叉编译工具链的完整描述
cc_toolchain_suite:
负责描述所有的编译工具链
里面的值必须和之前的cpu值定义相一致
bazel根据这个文件查找相对应的工具链
其它的选项并不复杂,不做赘述
脚本内容如下:
1 package(default_visibility = ["//visibility:public"]) 2 3 cc_toolchain_suite( 4 name = "toolchain", 5 toolchains = { 6 "armv6|compiler": ":cc-compiler-armv6", 7 "k8|compiler": ":cc-compiler-local", 8 }, 9 ) 10 11 filegroup( 12 name = "empty", 13 srcs = [], 14 ) 15 16 filegroup( 17 name = "arm_linux_all_files", 18 srcs = [ 19 "@toolchain_target_armv6//:compiler_pieces", 20 ], 21 ) 22 23 cc_toolchain( 24 name = "cc-compiler-local", 25 all_files = ":empty", 26 compiler_files = ":empty", 27 cpu = "local", 28 dwp_files = ":empty", 29 dynamic_runtime_libs = [":empty"], 30 linker_files = ":empty", 31 objcopy_files = ":empty", 32 static_runtime_libs = [":empty"], 33 strip_files = ":empty", 34 supports_param_files = 1, 35 ) 36 37 cc_toolchain( 38 name = "cc-compiler-armv6", 39 all_files = ":arm_linux_all_files", 40 compiler_files = ":arm_linux_all_files", 41 cpu = "armv6", 42 dwp_files = ":empty", 43 dynamic_runtime_libs = [":empty"], 44 linker_files = ":arm_linux_all_files", 45 objcopy_files = "arm_linux_all_files", 46 static_runtime_libs = [":empty"], 47 strip_files = "arm_linux_all_files", 48 supports_param_files = 1, 49 )
5. 编写build_armv6.sh文件
目的是避免每次重复输入命令
使用-march=armv6指定树莓派的架构
查看树莓派官网,树莓派3支持硬件浮点运算,并且支持到neon vfp v4
使用-mfloat-abi=hard -mfpu=neon-vfpv4打开浮点运算硬件支持
gcc需要-funsafe-math-optimizations额外打开浮点运算硬件支持
使用--crosstool_top=//armv6-compiler:toolchain --cpu=armv6 --config=opt
指定编译工具链为树莓派交叉编译工具链
1 #!/bin/bash 2 bazel build --copt="-fPIC" --copt="-march=armv6" \ 3 --copt="-mfloat-abi=hard" \ 4 --copt="-mfpu=neon-vfpv4" \ 5 --copt="-funsafe-math-optimizations" \ 6 --copt="-Wno-unused-function" \ 7 --copt="-Wno-sign-compare" \ 8 --copt="-ftree-vectorize" --copt="-fomit-frame-pointer" \ 9 --cxxopt="-Wno-maybe-uninitialized" \ 10 --cxxopt="-Wno-narrowing" \ 11 --cxxopt="-Wno-unused" \ 12 --cxxopt="-Wno-comment" \ 13 --cxxopt="-Wno-unused-function" \ 14 --cxxopt="-Wno-sign-compare" \ 15 --cxxopt="-funsafe-math-optimizations" \ 16 --linkopt="-mfloat-abi=hard" \ 17 --linkopt="-mfpu=neon-vfpv4" \ 18 --linkopt="-funsafe-math-optimizations" \ 19 --verbose_failures \ 20 --crosstool_top=//armv6-compiler:toolchain --cpu=armv6 --config=opt \ 21 tensorflow/examples/label_image/...
6. 在所有编译之前仅而且必须运行一遍configure
jmalloc可以选Yes,但是这里还是建议选No,使用C库的malloc
除了最后一个使用-march=来指定参数,其它一律选No
新版本的代码加入了一个Android交叉编译交互的配置
和本文不相干,选No
7. 编译
运行build_armv6.sh即可开始编译
编译开始时bazel会自动下载依赖组件
同时很快将因为错误停止编译
修正编译错误
1. 编译时bazel会从网络上下载依赖的子模块,需要网络支持,并且需要梯子FQ
否则会出现如下错误:
java.io.IOException: Error downloading
2. 为nsync添加交叉编译支持
缺乏配置描述,会在编译时出现类似以下错误
external/nsync/BUILD:401:13: Configurable attribute "copts" doesn't match this configuration
根据错误提示,打开nsync对应工程的BUILD文件
vi /path/to/bazel-cache/external/nsync/BUILD
参考android_arm的描述增加树莓派的配置描述
config_setting(
name = "armv6",
values = {"cpu": "armv6"},
)
本来想做个patch贴上来,太懒了,这里先将就
具体代码内容如下:
1 # -*- mode: python; -*- 2 3 # nsync is a C library that exports synchronization primitives, such as reader 4 # writer locks with conditional critical sections, designed to be open sourced 5 # in portable C. See https://github.com/google/nsync 6 # 7 # See public/*.h for API. When compiled with C++11 rather than C, it's in the 8 # "nsync" name space. 9 # 10 # BUILD file usage: 11 # deps = "@nsync://nsync" for C version 12 # deps = "@nsync://nsync_cpp" for C++11 version. 13 # The latter uses no OS-specific system calls or architecture-specific atomic 14 # operations. 15 16 package(default_visibility = ["//visibility:public"]) 17 18 licenses(["notice"]) # Apache 2.0 19 20 exports_files(["LICENSE"]) 21 22 # --------------------------------------------- 23 # Parameters to the compilation: compiler (e.g., for atomics), architecture 24 # (e.g., for load and store barrier behaviour), and OS. 25 # Bazel merges these into one, somewhat slippery, "cpu" string. 26 # Bazel uses a rather verbose mechanism for choosing which implementations 27 # are needed on given platforms; hence all the config_setting() rules below. 28 29 config_setting( 30 name = "gcc_linux_x86_32_1", 31 values = {"cpu": "piii"}, 32 ) 33 34 config_setting( 35 name = "gcc_linux_x86_64_1", 36 values = {"cpu": "k8"}, 37 ) 38 39 config_setting( 40 name = "gcc_linux_x86_64_2", 41 values = {"cpu": "haswell"}, 42 ) 43 44 config_setting( 45 name = "gcc_linux_aarch64", 46 values = {"cpu": "arm"}, 47 ) 48 49 config_setting( 50 name = "gcc_linux_ppc64", 51 values = {"cpu": "ppc"}, 52 ) 53 54 config_setting( 55 name = "gcc_linux_s390x", 56 values = {"cpu": "s390x"}, 57 ) 58 59 config_setting( 60 name = "clang_macos_x86_64", 61 values = {"cpu": "darwin"}, 62 ) 63 64 config_setting( 65 name = "android_x86_32", 66 values = {"cpu": "x86"}, 67 ) 68 69 config_setting( 70 name = "android_x86_64", 71 values = {"cpu": "x86_64"}, 72 ) 73 74 config_setting( 75 name = "android_armeabi", 76 values = {"cpu": "armeabi"}, 77 ) 78 79 config_setting( 80 name = "android_arm", 81 values = {"cpu": "armeabi-v7a"}, 82 ) 83 84 config_setting( 85 name = "android_arm64", 86 values = {"cpu": "arm64-v8a"}, 87 ) 88 89 config_setting( 90 name = "msvc_windows_x86_64", 91 values = {"cpu": "x64_windows"}, 92 ) 93 94 config_setting( 95 name = "freebsd", 96 values = {"cpu": "freebsd"}, 97 ) 98 99 config_setting( 100 name = "ios_x86_64", 101 values = {"cpu": "ios_x86_64"}, 102 ) 103 104 config_setting( 105 name = "raspberry", 106 values = {"cpu": "armv6"}, 107 ) 108 109 # --------------------------------------------- 110 # Compilation options. 111 112 load(":bazel/pkg_path_name.bzl", "pkg_path_name") 113 114 # Compilation options that apply to both C++11 and C. 115 NSYNC_OPTS_GENERIC = select({ 116 # Select the CPU architecture include directory. 117 # This select() has no real effect in the C++11 build, but satisfies a 118 # #include that would otherwise need a #if. 119 ":gcc_linux_x86_32_1": ["-I" + pkg_path_name() + "/platform/x86_32"], 120 ":gcc_linux_x86_64_1": ["-I" + pkg_path_name() + "/platform/x86_64"], 121 ":gcc_linux_x86_64_2": ["-I" + pkg_path_name() + "/platform/x86_64"], 122 ":gcc_linux_aarch64": ["-I" + pkg_path_name() + "/platform/aarch64"], 123 ":gcc_linux_ppc64": ["-I" + pkg_path_name() + "/platform/ppc64"], 124 ":gcc_linux_s390x": ["-I" + pkg_path_name() + "/platform/s390x"], 125 ":clang_macos_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"], 126 ":freebsd": ["-I" + pkg_path_name() + "/platform/x86_64"], 127 ":ios_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"], 128 ":android_x86_32": ["-I" + pkg_path_name() + "/platform/x86_32"], 129 ":android_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"], 130 ":android_armeabi": ["-I" + pkg_path_name() + "/platform/arm"], 131 ":android_arm": ["-I" + pkg_path_name() + "/platform/arm"], 132 ":raspberry": ["-I" + pkg_path_name() + "/platform/arm"], 133 ":android_arm64": ["-I" + pkg_path_name() + "/platform/aarch64"], 134 ":msvc_windows_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"], 135 }) + [ 136 "-I" + pkg_path_name() + "/public", 137 "-I" + pkg_path_name() + "/internal", 138 "-I" + pkg_path_name() + "/platform/posix", 139 ] + select({ 140 ":msvc_windows_x86_64": [ 141 ], 142 ":freebsd": ["-pthread"], 143 "//conditions:default": [ 144 "-D_POSIX_C_SOURCE=200809L", 145 "-pthread", 146 ], 147 }) 148 149 # Options for C build, rather then C++11 build. 150 NSYNC_OPTS = select({ 151 # Select the OS include directory. 152 ":gcc_linux_x86_32_1": ["-I" + pkg_path_name() + "/platform/linux"], 153 ":gcc_linux_x86_64_1": ["-I" + pkg_path_name() + "/platform/linux"], 154 ":gcc_linux_x86_64_2": ["-I" + pkg_path_name() + "/platform/linux"], 155 ":gcc_linux_aarch64": ["-I" + pkg_path_name() + "/platform/linux"], 156 ":gcc_linux_ppc64": ["-I" + pkg_path_name() + "/platform/linux"], 157 ":gcc_linux_s390x": ["-I" + pkg_path_name() + "/platform/linux"], 158 ":clang_macos_x86_64": ["-I" + pkg_path_name() + "/platform/macos"], 159 ":freebsd": ["-I" + pkg_path_name() + "/platform/freebsd"], 160 ":ios_x86_64": ["-I" + pkg_path_name() + "/platform/macos"], 161 ":android_x86_32": ["-I" + pkg_path_name() + "/platform/linux"], 162 ":android_x86_64": ["-I" + pkg_path_name() + "/platform/linux"], 163 ":android_armeabi": ["-I" + pkg_path_name() + "/platform/linux"], 164 ":android_arm": ["-I" + pkg_path_name() + "/platform/linux"], 165 ":raspberry": ["-I" + pkg_path_name() + "/platform/linux"], 166 ":android_arm64": ["-I" + pkg_path_name() + "/platform/linux"], 167 ":msvc_windows_x86_64": ["-I" + pkg_path_name() + "/platform/win32"], 168 "//conditions:default": [], 169 }) + select({ 170 # Select the compiler include directory. 171 ":gcc_linux_x86_32_1": ["-I" + pkg_path_name() + "/platform/gcc"], 172 ":gcc_linux_x86_64_1": ["-I" + pkg_path_name() + "/platform/gcc"], 173 ":gcc_linux_x86_64_2": ["-I" + pkg_path_name() + "/platform/gcc"], 174 ":gcc_linux_aarch64": ["-I" + pkg_path_name() + "/platform/gcc"], 175 ":gcc_linux_ppc64": ["-I" + pkg_path_name() + "/platform/gcc"], 176 ":gcc_linux_s390x": ["-I" + pkg_path_name() + "/platform/gcc"], 177 ":clang_macos_x86_64": ["-I" + pkg_path_name() + "/platform/clang"], 178 ":freebsd": ["-I" + pkg_path_name() + "/platform/clang"], 179 ":ios_x86_64": ["-I" + pkg_path_name() + "/platform/clang"], 180 ":android_x86_32": ["-I" + pkg_path_name() + "/platform/gcc"], 181 ":android_x86_64": ["-I" + pkg_path_name() + "/platform/gcc"], 182 ":android_armeabi": ["-I" + pkg_path_name() + "/platform/gcc"], 183 ":android_arm": ["-I" + pkg_path_name() + "/platform/gcc"], 184 ":raspberry": ["-I" + pkg_path_name() + "/platform/gcc"], 185 ":android_arm64": ["-I" + pkg_path_name() + "/platform/gcc"], 186 ":msvc_windows_x86_64": ["-I" + pkg_path_name() + "/platform/msvc"], 187 }) + select({ 188 # Apple deprecated their atomics library, yet recent versions have no 189 # working version of stdatomic.h; so some recent versions need one, and 190 # other versions prefer the other. For the moment, just ignore the 191 # depreaction. 192 ":clang_macos_x86_64": ["-Wno-deprecated-declarations"], 193 "//conditions:default": [], 194 }) + NSYNC_OPTS_GENERIC 195 196 # Options for C++11 build, rather then C build. 197 NSYNC_OPTS_CPP = select({ 198 ":msvc_windows_x86_64": [ 199 "/TP", 200 ], 201 "//conditions:default": [ 202 "-x", 203 "c++", 204 "-std=c++11", 205 ], 206 }) + select({ 207 # Some versions of MacOS (notably Sierra) require -D_DARWIN_C_SOURCE 208 # to include some standard C++11 headers, like <mutex>. 209 ":clang_macos_x86_64": ["-D_DARWIN_C_SOURCE"], 210 "//conditions:default": [], 211 }) + [ 212 "-DNSYNC_ATOMIC_CPP11", 213 "-DNSYNC_USE_CPP11_TIMEPOINT", 214 "-I" + pkg_path_name() + "/platform/c++11", 215 ] + select({ 216 # must follow the -I...platform/c++11 217 ":ios_x86_64": ["-I" + pkg_path_name() + "/platform/gcc_no_tls"], 218 ":msvc_windows_x86_64": [ 219 "-I" + pkg_path_name() + "/platform/win32", 220 "-I" + pkg_path_name() + "/platform/msvc", 221 ], 222 "//conditions:default": ["-I" + pkg_path_name() + "/platform/gcc"], 223 }) + NSYNC_OPTS_GENERIC 224 225 # Link options (for tests) built in C (rather than C++11). 226 NSYNC_LINK_OPTS = select({ 227 ":msvc_windows_x86_64": [], 228 "//conditions:default": ["-pthread"], 229 }) 230 231 # Link options (for tests) built in C++11 (rather than C). 232 NSYNC_LINK_OPTS_CPP = select({ 233 ":msvc_windows_x86_64": [], 234 "//conditions:default": ["-pthread"], 235 }) 236 237 # --------------------------------------------- 238 # Header files the source may include. 239 240 # Internal library headers. 241 NSYNC_INTERNAL_HEADERS = [ 242 "internal/common.h", 243 "internal/dll.h", 244 "internal/headers.h", 245 "internal/sem.h", 246 "internal/wait_internal.h", 247 ] 248 249 # Internal test headers. 250 NSYNC_TEST_HEADERS = NSYNC_INTERNAL_HEADERS + [ 251 "testing/array.h", 252 "testing/atm_log.h", 253 "testing/closure.h", 254 "testing/heap.h", 255 "testing/smprintf.h", 256 "testing/testing.h", 257 "testing/time_extra.h", 258 ] 259 260 # Platform specific headers. 261 # This declares headers for all platforms, not just the one 262 # we're building for, to avoid a more complex build file. 263 NSYNC_INTERNAL_HEADERS_PLATFORM = [ 264 "platform/aarch64/cputype.h", 265 "platform/alpha/cputype.h", 266 "platform/arm/cputype.h", 267 "platform/atomic_ind/atomic.h", 268 "platform/c++11/atomic.h", 269 "platform/c++11/platform.h", 270 "platform/c11/atomic.h", 271 "platform/clang/atomic.h", 272 "platform/clang/compiler.h", 273 "platform/cygwin/platform.h", 274 "platform/decc/compiler.h", 275 "platform/freebsd/platform.h", 276 "platform/gcc/atomic.h", 277 "platform/gcc/compiler.h", 278 "platform/gcc_new/atomic.h", 279 "platform/gcc_new_debug/atomic.h", 280 "platform/gcc_no_tls/compiler.h", 281 "platform/gcc_old/atomic.h", 282 "platform/lcc/compiler.h", 283 "platform/lcc/nsync_time_init.h", 284 "platform/linux/platform.h", 285 "platform/win32/atomic.h", 286 "platform/macos/platform_c++11_os.h", 287 "platform/msvc/compiler.h", 288 "platform/netbsd/atomic.h", 289 "platform/netbsd/platform.h", 290 "platform/openbsd/platform.h", 291 "platform/osf1/platform.h", 292 "platform/macos/atomic.h", 293 "platform/macos/platform.h", 294 "platform/pmax/cputype.h", 295 "platform/posix/cputype.h", 296 "platform/posix/nsync_time_init.h", 297 "platform/posix/platform_c++11_os.h", 298 "platform/ppc32/cputype.h", 299 "platform/ppc64/cputype.h", 300 "platform/s390x/cputype.h", 301 "platform/shark/cputype.h", 302 "platform/tcc/compiler.h", 303 "platform/win32/platform.h", 304 "platform/win32/platform_c++11_os.h", 305 "platform/x86_32/cputype.h", 306 "platform/x86_64/cputype.h", 307 ] 308 309 # --------------------------------------------- 310 # The nsync library. 311 312 # Linux-specific library source. 313 NSYNC_SRC_LINUX = [ 314 "platform/linux/src/nsync_semaphore_futex.c", 315 "platform/posix/src/per_thread_waiter.c", 316 "platform/posix/src/yield.c", 317 "platform/posix/src/time_rep.c", 318 "platform/posix/src/nsync_panic.c", 319 ] 320 321 # Android-specific library source. 322 NSYNC_SRC_ANDROID = [ 323 "platform/posix/src/nsync_semaphore_sem_t.c", 324 "platform/posix/src/per_thread_waiter.c", 325 "platform/posix/src/yield.c", 326 "platform/posix/src/time_rep.c", 327 "platform/posix/src/nsync_panic.c", 328 ] 329 330 # MacOS-specific library source. 331 NSYNC_SRC_MACOS = [ 332 "platform/posix/src/clock_gettime.c", 333 "platform/posix/src/nsync_semaphore_mutex.c", 334 "platform/posix/src/per_thread_waiter.c", 335 "platform/posix/src/yield.c", 336 "platform/posix/src/time_rep.c", 337 "platform/posix/src/nsync_panic.c", 338 ] 339 340 # Windows-specific library source. 341 NSYNC_SRC_WINDOWS = [ 342 "platform/posix/src/nsync_panic.c", 343 "platform/posix/src/per_thread_waiter.c", 344 "platform/posix/src/time_rep.c", 345 "platform/posix/src/yield.c", 346 "platform/win32/src/clock_gettime.c", 347 "platform/win32/src/init_callback_win32.c", 348 "platform/win32/src/nanosleep.c", 349 "platform/win32/src/nsync_semaphore_win32.c", 350 "platform/win32/src/pthread_cond_timedwait_win32.c", 351 "platform/win32/src/pthread_key_win32.cc", 352 ] 353 354 # FreeBSD-specific library source. 355 NSYNC_SRC_FREEBSD = [ 356 "platform/posix/src/nsync_semaphore_sem_t.c", 357 "platform/posix/src/per_thread_waiter.c", 358 "platform/posix/src/yield.c", 359 "platform/posix/src/time_rep.c", 360 "platform/posix/src/nsync_panic.c", 361 ] 362 363 # OS-specific library source. 364 NSYNC_SRC_PLATFORM = select({ 365 ":gcc_linux_x86_32_1": NSYNC_SRC_LINUX, 366 ":gcc_linux_x86_64_1": NSYNC_SRC_LINUX, 367 ":gcc_linux_x86_64_2": NSYNC_SRC_LINUX, 368 ":gcc_linux_aarch64": NSYNC_SRC_LINUX, 369 ":gcc_linux_ppc64": NSYNC_SRC_LINUX, 370 ":gcc_linux_s390x": NSYNC_SRC_LINUX, 371 ":clang_macos_x86_64": NSYNC_SRC_MACOS, 372 ":freebsd": NSYNC_SRC_FREEBSD, 373 ":ios_x86_64": NSYNC_SRC_MACOS, 374 ":android_x86_32": NSYNC_SRC_ANDROID, 375 ":android_x86_64": NSYNC_SRC_ANDROID, 376 ":android_armeabi": NSYNC_SRC_ANDROID, 377 ":android_arm": NSYNC_SRC_ANDROID, 378 ":android_arm64": NSYNC_SRC_ANDROID, 379 ":msvc_windows_x86_64": NSYNC_SRC_WINDOWS, 380 ":raspberry": NSYNC_SRC_LINUX, 381 }) 382 383 # C++11-specific (OS and architecture independent) library source. 384 NSYNC_SRC_PLATFORM_CPP = [ 385 "platform/c++11/src/nsync_semaphore_mutex.cc", 386 "platform/c++11/src/time_rep_timespec.cc", 387 "platform/c++11/src/nsync_panic.cc", 388 "platform/c++11/src/yield.cc", 389 ] + select({ 390 # MacOS and Android don't have working C++11 thread local storage. 391 ":clang_macos_x86_64": ["platform/posix/src/per_thread_waiter.c"], 392 ":android_x86_32": ["platform/posix/src/per_thread_waiter.c"], 393 ":android_x86_64": ["platform/posix/src/per_thread_waiter.c"], 394 ":android_armeabi": ["platform/posix/src/per_thread_waiter.c"], 395 ":android_arm": ["platform/posix/src/per_thread_waiter.c"], 396 ":android_arm64": ["platform/posix/src/per_thread_waiter.c"], 397 ":ios_x86_64": ["platform/posix/src/per_thread_waiter.c"], 398 ":msvc_windows_x86_64": [ 399 "platform/win32/src/clock_gettime.c", 400 "platform/win32/src/pthread_key_win32.cc", 401 "platform/c++11/src/per_thread_waiter.cc", 402 ], 403 "//conditions:default": ["platform/c++11/src/per_thread_waiter.cc"], 404 }) 405 406 # Generic library source. 407 NSYNC_SRC_GENERIC = [ 408 "internal/common.c", 409 "internal/counter.c", 410 "internal/cv.c", 411 "internal/debug.c", 412 "internal/dll.c", 413 "internal/mu.c", 414 "internal/mu_wait.c", 415 "internal/note.c", 416 "internal/once.c", 417 "internal/sem_wait.c", 418 "internal/time_internal.c", 419 "internal/wait.c", 420 ] 421 422 # Generic library header files. 423 NSYNC_HDR_GENERIC = [ 424 "public/nsync.h", 425 "public/nsync_atomic.h", 426 "public/nsync_counter.h", 427 "public/nsync_cpp.h", 428 "public/nsync_cv.h", 429 "public/nsync_debug.h", 430 "public/nsync_mu.h", 431 "public/nsync_mu_wait.h", 432 "public/nsync_note.h", 433 "public/nsync_once.h", 434 "public/nsync_time.h", 435 "public/nsync_time_internal.h", 436 "public/nsync_waiter.h", 437 ] 438 439 # The library compiled in C, rather than C++11. 440 cc_library( 441 name = "nsync", 442 srcs = NSYNC_SRC_GENERIC + NSYNC_SRC_PLATFORM, 443 hdrs = NSYNC_HDR_GENERIC, 444 copts = NSYNC_OPTS, 445 includes = ["public"], 446 textual_hdrs = NSYNC_INTERNAL_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM, 447 ) 448 449 # The library compiled in C++11, rather than C. 450 cc_library( 451 name = "nsync_cpp", 452 srcs = NSYNC_SRC_GENERIC + NSYNC_SRC_PLATFORM_CPP, 453 hdrs = NSYNC_HDR_GENERIC, 454 copts = NSYNC_OPTS_CPP, 455 includes = ["public"], 456 textual_hdrs = NSYNC_INTERNAL_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM, 457 ) 458 459 # nsync_headers provides just the header files for use in projects that need to 460 # build shared libraries for dynamic loading. Bazel seems unable to cope 461 # otherwise. 462 cc_library( 463 name = "nsync_headers", 464 hdrs = glob(["public/*.h"]), 465 includes = ["public"], 466 ) 467 468 # --------------------------------------------- 469 # Test code. 470 471 # Linux-specific test library source. 472 NSYNC_TEST_SRC_LINUX = [ 473 "platform/posix/src/start_thread.c", 474 ] 475 476 # Android-specific test library source. 477 NSYNC_TEST_SRC_ANDROID = [ 478 "platform/posix/src/start_thread.c", 479 ] 480 481 # MacOS-specific test library source. 482 NSYNC_TEST_SRC_MACOS = [ 483 "platform/posix/src/start_thread.c", 484 ] 485 486 # Windows-specific test library source. 487 NSYNC_TEST_SRC_WINDOWS = [ 488 "platform/win32/src/start_thread.c", 489 ] 490 491 # FreeBSD-specific test library source. 492 NSYNC_TEST_SRC_FREEBSD = [ 493 "platform/posix/src/start_thread.c", 494 ] 495 496 # OS-specific test library source. 497 NSYNC_TEST_SRC_PLATFORM = select({ 498 ":gcc_linux_x86_32_1": NSYNC_TEST_SRC_LINUX, 499 ":gcc_linux_x86_64_1": NSYNC_TEST_SRC_LINUX, 500 ":gcc_linux_x86_64_2": NSYNC_TEST_SRC_LINUX, 501 ":gcc_linux_aarch64": NSYNC_TEST_SRC_LINUX, 502 ":gcc_linux_ppc64": NSYNC_TEST_SRC_LINUX, 503 ":gcc_linux_s390x": NSYNC_TEST_SRC_LINUX, 504 ":clang_macos_x86_64": NSYNC_TEST_SRC_MACOS, 505 ":freebsd": NSYNC_TEST_SRC_FREEBSD, 506 ":ios_x86_64": NSYNC_TEST_SRC_MACOS, 507 ":android_x86_32": NSYNC_TEST_SRC_ANDROID, 508 ":android_x86_64": NSYNC_TEST_SRC_ANDROID, 509 ":android_armeabi": NSYNC_TEST_SRC_ANDROID, 510 ":android_arm": NSYNC_TEST_SRC_ANDROID, 511 ":android_arm64": NSYNC_TEST_SRC_ANDROID, 512 ":msvc_windows_x86_64": NSYNC_TEST_SRC_WINDOWS, 513 ":raspberry": NSYNC_TEST_SRC_LINUX, 514 }) 515 516 # C++11-specific (OS and architecture independent) test library source. 517 NSYNC_TEST_SRC_PLATFORM_CPP = [ 518 "platform/c++11/src/start_thread.cc", 519 ] 520 521 # Generic test library source. 522 NSYNC_TEST_SRC_GENERIC = [ 523 "testing/array.c", 524 "testing/atm_log.c", 525 "testing/closure.c", 526 "testing/smprintf.c", 527 "testing/testing.c", 528 "testing/time_extra.c", 529 ] 530 531 # The test library compiled in C, rather than C++11. 532 cc_library( 533 name = "nsync_test_lib", 534 testonly = 1, 535 srcs = NSYNC_TEST_SRC_GENERIC + NSYNC_TEST_SRC_PLATFORM, 536 hdrs = ["testing/testing.h"], 537 copts = NSYNC_OPTS, 538 textual_hdrs = NSYNC_TEST_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM, 539 deps = [":nsync"], 540 ) 541 542 # The test library compiled in C++11, rather than C. 543 cc_library( 544 name = "nsync_test_lib_cpp", 545 testonly = 1, 546 srcs = NSYNC_TEST_SRC_GENERIC + NSYNC_TEST_SRC_PLATFORM_CPP, 547 hdrs = ["testing/testing.h"], 548 copts = NSYNC_OPTS_CPP, 549 textual_hdrs = NSYNC_TEST_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM, 550 deps = [":nsync_cpp"], 551 ) 552 553 # --------------------------------------------- 554 # The tests, compiled in C rather than C++11. 555 556 cc_test( 557 name = "counter_test", 558 size = "small", 559 srcs = ["testing/counter_test.c"], 560 copts = NSYNC_OPTS, 561 linkopts = NSYNC_LINK_OPTS, 562 deps = [ 563 ":nsync", 564 ":nsync_test_lib", 565 ], 566 ) 567 568 cc_test( 569 name = "cv_mu_timeout_stress_test", 570 size = "small", 571 srcs = ["testing/cv_mu_timeout_stress_test.c"], 572 copts = NSYNC_OPTS, 573 linkopts = NSYNC_LINK_OPTS, 574 deps = [ 575 ":nsync", 576 ":nsync_test_lib", 577 ], 578 ) 579 580 cc_test( 581 name = "cv_test", 582 size = "small", 583 srcs = ["testing/cv_test.c"], 584 copts = NSYNC_OPTS, 585 linkopts = NSYNC_LINK_OPTS, 586 deps = [ 587 ":nsync", 588 ":nsync_test_lib", 589 ], 590 ) 591 592 cc_test( 593 name = "cv_wait_example_test", 594 size = "small", 595 srcs = ["testing/cv_wait_example_test.c"], 596 copts = NSYNC_OPTS, 597 linkopts = NSYNC_LINK_OPTS, 598 deps = [ 599 ":nsync", 600 ":nsync_test_lib", 601 ], 602 ) 603 604 cc_test( 605 name = "dll_test", 606 size = "small", 607 srcs = ["testing/dll_test.c"], 608 copts = NSYNC_OPTS, 609 linkopts = NSYNC_LINK_OPTS, 610 deps = [ 611 ":nsync", 612 ":nsync_test_lib", 613 ], 614 ) 615 616 cc_test( 617 name = "mu_starvation_test", 618 size = "small", 619 srcs = ["testing/mu_starvation_test.c"], 620 copts = NSYNC_OPTS, 621 linkopts = NSYNC_LINK_OPTS, 622 deps = [ 623 ":nsync", 624 ":nsync_test_lib", 625 ], 626 ) 627 628 cc_test( 629 name = "mu_test", 630 size = "small", 631 srcs = ["testing/mu_test.c"], 632 copts = NSYNC_OPTS, 633 linkopts = NSYNC_LINK_OPTS, 634 deps = [ 635 ":nsync", 636 ":nsync_test_lib", 637 ], 638 ) 639 640 cc_test( 641 name = "mu_wait_example_test", 642 size = "small", 643 srcs = ["testing/mu_wait_example_test.c"], 644 copts = NSYNC_OPTS, 645 linkopts = NSYNC_LINK_OPTS, 646 deps = [ 647 ":nsync", 648 ":nsync_test_lib", 649 ], 650 ) 651 652 cc_test( 653 name = "mu_wait_test", 654 size = "small", 655 srcs = ["testing/mu_wait_test.c"], 656 copts = NSYNC_OPTS, 657 linkopts = NSYNC_LINK_OPTS, 658 deps = [ 659 ":nsync", 660 ":nsync_test_lib", 661 ], 662 ) 663 664 cc_test( 665 name = "note_test", 666 size = "small", 667 srcs = ["testing/note_test.c"], 668 copts = NSYNC_OPTS, 669 linkopts = NSYNC_LINK_OPTS, 670 deps = [ 671 ":nsync", 672 ":nsync_test_lib", 673 ], 674 ) 675 676 cc_test( 677 name = "once_test", 678 size = "small", 679 srcs = ["testing/once_test.c"], 680 copts = NSYNC_OPTS, 681 linkopts = NSYNC_LINK_OPTS, 682 deps = [ 683 ":nsync", 684 ":nsync_test_lib", 685 ], 686 ) 687 688 cc_test( 689 name = "pingpong_test", 690 size = "small", 691 srcs = ["testing/pingpong_test.c"], 692 copts = NSYNC_OPTS, 693 linkopts = NSYNC_LINK_OPTS, 694 deps = [ 695 ":nsync", 696 ":nsync_test_lib", 697 ], 698 ) 699 700 cc_test( 701 name = "wait_test", 702 size = "small", 703 srcs = ["testing/wait_test.c"], 704 copts = NSYNC_OPTS, 705 linkopts = NSYNC_LINK_OPTS, 706 deps = [ 707 ":nsync", 708 ":nsync_test_lib", 709 ], 710 ) 711 712 # --------------------------------------------- 713 # The tests, compiled in C++11, rather than C. 714 715 cc_test( 716 name = "counter_cpp_test", 717 size = "small", 718 srcs = ["testing/counter_test.c"], 719 copts = NSYNC_OPTS_CPP, 720 linkopts = NSYNC_LINK_OPTS_CPP, 721 deps = [ 722 ":nsync_cpp", 723 ":nsync_test_lib_cpp", 724 ], 725 ) 726 727 cc_test( 728 name = "cv_mu_timeout_stress_cpp_test", 729 size = "small", 730 srcs = ["testing/cv_mu_timeout_stress_test.c"], 731 copts = NSYNC_OPTS_CPP, 732 linkopts = NSYNC_LINK_OPTS_CPP, 733 deps = [ 734 ":nsync_cpp", 735 ":nsync_test_lib_cpp", 736 ], 737 ) 738 739 cc_test( 740 name = "cv_cpp_test", 741 size = "small", 742 srcs = ["testing/cv_test.c"], 743 copts = NSYNC_OPTS_CPP, 744 linkopts = NSYNC_LINK_OPTS_CPP, 745 deps = [ 746 ":nsync_cpp", 747 ":nsync_test_lib_cpp", 748 ], 749 ) 750 751 cc_test( 752 name = "cv_wait_example_cpp_test", 753 size = "small", 754 srcs = ["testing/cv_wait_example_test.c"], 755 copts = NSYNC_OPTS_CPP, 756 linkopts = NSYNC_LINK_OPTS_CPP, 757 deps = [ 758 ":nsync_cpp", 759 ":nsync_test_lib_cpp", 760 ], 761 ) 762 763 cc_test( 764 name = "dll_cpp_test", 765 size = "small", 766 srcs = ["testing/dll_test.c"], 767 copts = NSYNC_OPTS_CPP, 768 linkopts = NSYNC_LINK_OPTS_CPP, 769 deps = [ 770 ":nsync_cpp", 771 ":nsync_test_lib_cpp", 772 ], 773 ) 774 775 cc_test( 776 name = "mu_starvation_cpp_test", 777 size = "small", 778 srcs = ["testing/mu_starvation_test.c"], 779 copts = NSYNC_OPTS_CPP, 780 linkopts = NSYNC_LINK_OPTS_CPP, 781 deps = [ 782 ":nsync_cpp", 783 ":nsync_test_lib_cpp", 784 ], 785 ) 786 787 cc_test( 788 name = "mu_cpp_test", 789 size = "small", 790 srcs = ["testing/mu_test.c"], 791 copts = NSYNC_OPTS_CPP, 792 linkopts = NSYNC_LINK_OPTS_CPP, 793 deps = [ 794 ":nsync_cpp", 795 ":nsync_test_lib_cpp", 796 ], 797 ) 798 799 cc_test( 800 name = "mu_wait_example_cpp_test", 801 size = "small", 802 srcs = ["testing/mu_wait_example_test.c"], 803 copts = NSYNC_OPTS_CPP, 804 linkopts = NSYNC_LINK_OPTS_CPP, 805 deps = [ 806 ":nsync_cpp", 807 ":nsync_test_lib_cpp", 808 ], 809 ) 810 811 cc_test( 812 name = "mu_wait_cpp_test", 813 size = "small", 814 srcs = ["testing/mu_wait_test.c"], 815 copts = NSYNC_OPTS_CPP, 816 linkopts = NSYNC_LINK_OPTS_CPP, 817 deps = [ 818 ":nsync_cpp", 819 ":nsync_test_lib_cpp", 820 ], 821 ) 822 823 cc_test( 824 name = "note_cpp_test", 825 size = "small", 826 srcs = ["testing/note_test.c"], 827 copts = NSYNC_OPTS_CPP, 828 linkopts = NSYNC_LINK_OPTS_CPP, 829 deps = [ 830 ":nsync_cpp", 831 ":nsync_test_lib_cpp", 832 ], 833 ) 834 835 cc_test( 836 name = "once_cpp_test", 837 size = "small", 838 srcs = ["testing/once_test.c"], 839 copts = NSYNC_OPTS_CPP, 840 linkopts = NSYNC_LINK_OPTS_CPP, 841 deps = [ 842 ":nsync_cpp", 843 ":nsync_test_lib_cpp", 844 ], 845 ) 846 847 cc_test( 848 name = "pingpong_cpp_test", 849 size = "small", 850 srcs = ["testing/pingpong_test.c"], 851 copts = NSYNC_OPTS_CPP, 852 linkopts = NSYNC_LINK_OPTS_CPP, 853 deps = [ 854 ":nsync_cpp", 855 ":nsync_test_lib_cpp", 856 ], 857 ) 858 859 cc_test( 860 name = "wait_cpp_test", 861 size = "small", 862 srcs = ["testing/wait_test.c"], 863 copts = NSYNC_OPTS_CPP, 864 linkopts = NSYNC_LINK_OPTS_CPP, 865 deps = [ 866 ":nsync_cpp", 867 ":nsync_test_lib_cpp", 868 ], 869 )
3. 再次运行build_armv6.sh编译即可
如果还出现错误,可以继续返回步骤2,修复错误
也可以给我邮件,但回复可能很慢
编译成功,目标文件生成目录:
bazel-bin/tensorflow/examples/label_image
bazel-bin/tensorflow/libtensorflow_framework.so
bazel并没有执行strip,如果有必要,需要手动执行strip
4. 刚发现最新的代码,使用-O2会触发树莓派交叉编译工具链崩溃
解决办法是,修改CROSSTOOL,更改为-O3
交叉编译tensorflow lite
1. Activate fpu support
vi tensorflow/contrib/lite/kernels/internal/BUILD
Add
config_setting(
name = "armv6",
values = { "cpu": "armv6", },
)
Add value
"armv6": [
"-O2",
"-mfpu=neon-vfpv4",
"-mfloat-abi=hard",
],
to NEON_FLAGS_IF_APPLICABLE
and replace armv7a value with armv6
Add
":armv6": [
":neon_tensor_utils",
],
":armv7a": [
":neon_tensor_utils",
],
to cc_library tensor_utils select options
2. 编译编译脚本sh
1 #!/bin/bash 2 3 tflite_model="tensorflow/contrib/lite/kernels/internal:tensor_utils_test" 4 if [ $@"z" == "z" ] 5 then 6 echo "$0 ${tflite_model}" 7 else 8 tflite_model=$@ 9 fi 10 bazel build --copt="-fPIC" --copt="-march=armv6" \ 11 --copt="-mfloat-abi=hard" \ 12 --copt="-mfpu=neon-vfpv4" \ 13 --copt="-funsafe-math-optimizations" \ 14 --copt="-Wno-unused-function" \ 15 --copt="-Wno-sign-compare" \ 16 --copt="-ftree-vectorize" \ 17 --copt="-fomit-frame-pointer" \ 18 --cxxopt='--std=c++11' \ 19 --cxxopt="-Wno-maybe-uninitialized" \ 20 --cxxopt="-Wno-narrowing" \ 21 --cxxopt="-Wno-unused" \ 22 --cxxopt="-Wno-comment" \ 23 --cxxopt="-Wno-unused-function" \ 24 --cxxopt="-Wno-sign-compare" \ 25 --cxxopt="-funsafe-math-optimizations" \ 26 --linkopt="-lstdc++" \ 27 --linkopt="-mfloat-abi=hard" \ 28 --linkopt="-mfpu=neon-vfpv4" \ 29 --linkopt="-funsafe-math-optimizations" \ 30 --verbose_failures \ 31 --strip=always \ 32 --crosstool_top=//armv6-compiler:toolchain --cpu=armv6 --config=opt \ 33 $@
3. 输出库和头文件
libbuiltin_ops.a libframework.a libneon_tensor_utils.a libquantization_util.a libtensor_utils.a
libcontext.a libfarmhash.a libgemm_support.a libportable_tensor_utils.a libstring_util.a
使用find命令和cp命令组合,将它们拷贝出来备用
头文件目录
tensorflow/contrib/lite
bazel-tensorflow/external/flatbuffers/include
4. Build toco
tensorflow lite加载的model文件需要预先使用toco转换格式
5. Configure and Build
configure with -march=native before building toco
bazel build tensorflow/contrib/lite/toco:toco
restore configure to cross compile after toco built
6. Run toco
具体用法参考tensorflow lite官网说明
bazel run --config=opt tensorflow/contrib/lite/toco:toco -- \
--input_file=(pwd)/mobilenet_v1_1.0_224/frozen_graph.pb \
--input_format=TENSORFLOW_GRAPHDEF --output_format=TFLITE \
--output_file=/tmp/mobilenet_v1_1.0_224.lite --inference_type=FLOAT \
--input_type=FLOAT --input_arrays=input \
--output_arrays=MobilenetV1/Predictions/Reshape_1 --input_shapes=1,224,224,3
7. Done
enjoy
https://github.com/tensorflow/tensorflow