在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

  脚本内容如下:

 package(default_visibility = ['//visibility:public'])

 filegroup(
name = 'gcc',
srcs = [
'bin/arm-linux-gnueabihf-gcc',
],
) filegroup(
name = 'ar',
srcs = [
'bin/arm-linux-gnueabihf-ar',
],
) filegroup(
name = 'ld',
srcs = [
'bin/arm-linux-gnueabihf-ld',
],
) filegroup(
name = 'nm',
srcs = [
'bin/arm-linux-gnueabihf-nm',
],
) filegroup(
name = 'objcopy',
srcs = [
'bin/arm-linux-gnueabihf-objcopy',
],
) filegroup(
name = 'objdump',
srcs = [
'bin/arm-linux-gnueabihf-objdump',
],
) filegroup(
name = 'strip',
srcs = [
'bin/arm-linux-gnueabihf-strip',
],
) filegroup(
name = 'as',
srcs = [
'bin/arm-linux-gnueabihf-as',
],
) filegroup(
name = 'compiler_pieces',
srcs = glob([
'arm-linux-gnueabihf/**',
'libexec/**',
'lib/gcc/arm-linux-gnueabihf/**',
'include/**',
]),
) filegroup(
name = 'compiler_components',
srcs = [
':gcc',
':ar',
':ld',
':nm',
':objcopy',
':objdump',
':strip',
':as',
],
)

cross_toolchain_target_armv6.BUILD

  3. 编写CROSSTOOL文件

  CROSSTOOL文件负责描述交叉编译工具链,从编译选项到链接选项,非常繁杂

  很多选项是放屁脱裤子,吃力不讨好

  愚以为这bazel有点反人类阿

  文件内容以下:  

 major_version: "local"
minor_version: ""
default_target_cpu: "armv6" default_toolchain {
cpu: "armv6"
toolchain_identifier: "arm-linux-gnueabihf"
} default_toolchain {
cpu: "k8"
toolchain_identifier: "local"
} toolchain {
abi_version: "gcc"
abi_libc_version: "glibc_2.23"
builtin_sysroot: ""
compiler: "compiler"
host_system_name: "raspberrypi"
needsPic: true
supports_gold_linker: false
supports_incremental_linker: false
supports_fission: false
supports_interface_shared_objects: false
supports_normalizing_ar: true
supports_start_end_lib: false
supports_thin_archives: true
target_libc: "glibc_2.23"
target_cpu: "armv6"
target_system_name: "raspberrypi"
toolchain_identifier: "arm-linux-gnueabihf" tool_path { name: "ar" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-ar" }
tool_path { name: "compat-ld" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-ld" }
tool_path { name: "cpp" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-cpp" }
tool_path { name: "dwp" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-dwp" }
tool_path { name: "gcc" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc" }
tool_path { name: "gcov" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcov" }
tool_path { name: "ld" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-ld" }
tool_path { name: "nm" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-nm" }
tool_path { name: "objcopy" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-objcopy" }
objcopy_embed_flag: "-I"
objcopy_embed_flag: "binary"
tool_path { name: "objdump" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-objdump" }
tool_path { name: "strip" path: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-strip" } compiler_flag: "-nostdinc"
compiler_flag: "-mfloat-abi=hard"
compiler_flag: "-mfpu=neon-vfpv4"
compiler_flag: "-funsafe-math-optimizations" compiler_flag: "-isystem"
compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/include"
compiler_flag: "-isystem"
compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/usr/include"
compiler_flag: "-isystem"
compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/include" compiler_flag: "-isystem"
compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.3/include"
compiler_flag: "-isystem"
compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.3/include-fixed" compiler_flag: "-isystem"
compiler_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3"
compiler_flag: "-isystem"
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" cxx_flag: "-isystem"
cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/include"
cxx_flag: "-isystem"
cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/usr/include"
cxx_flag: "-isystem"
cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/include"
cxx_flag: "-isystem"
cxx_flag: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3"
cxx_flag: "-isystem"
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"
cxx_flag: "-std=c++11" cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/include"
cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/usr/include"
cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/include"
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"
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"
cxx_builtin_include_directory: "/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/include/c++/4.9.3"
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" linker_flag: "-lstdc++"
linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/lib"
linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/arm-linux-gnueabihf/lib"
linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/lib"
linker_flag: "-L/path/to/toolchain/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib"
linker_flag: "-Wl,--dynamic-linker=/lib/ld-linux-armhf.so.3" # Anticipated future default.
# This makes GCC and Clang do what we want when called through symlinks.
unfiltered_cxx_flag: "-no-canonical-prefixes"
linker_flag: "-no-canonical-prefixes" # Make C++ compilation deterministic. Use linkstamping instead of these
# compiler symbols.
unfiltered_cxx_flag: "-Wno-builtin-macro-redefined"
unfiltered_cxx_flag: "-D__DATE__=\"redacted\""
unfiltered_cxx_flag: "-D__TIMESTAMP__=\"redacted\""
unfiltered_cxx_flag: "-D__TIME__=\"redacted\"" # Security hardening on by default.
# Conservative choice; -D_FORTIFY_SOURCE= may be unsafe in some cases.
# We need to undef it before redefining it as some distributions now have
# it enabled by default.
compiler_flag: "-U_FORTIFY_SOURCE"
compiler_flag: "-fstack-protector"
compiler_flag: "-fPIE"
linker_flag: "-pie"
linker_flag: "-Wl,-z,relro,-z,now" # Enable coloring even if there's no attached terminal. Bazel removes the
# escape sequences if --nocolor is specified.
compiler_flag: "-fdiagnostics-color=always" # All warnings are enabled. Maybe enable -Werror as well?
compiler_flag: "-Wall"
# Enable a few more warnings that aren't part of -Wall.
compiler_flag: "-Wunused-but-set-parameter"
# But disable some that are problematic.
compiler_flag: "-Wno-free-nonheap-object" # has false positives # Keep stack frames for debugging, even in opt mode.
compiler_flag: "-fno-omit-frame-pointer" # Stamp the binary with a unique identifier.
linker_flag: "-Wl,--build-id=md5"
linker_flag: "-Wl,--hash-style=gnu" compilation_mode_flags {
mode: DBG
# Enable debug symbols.
compiler_flag: "-g"
}
compilation_mode_flags {
mode: OPT # No debug symbols.
# Maybe we should enable https://gcc.gnu.org/wiki/DebugFission for opt or
# even generally? However, that can't happen here, as it requires special
# handling in Bazel.
compiler_flag: "-g0" # Conservative choice for -O
# -O3 can increase binary size and even slow down the resulting binaries.
# Profile first and / or use FDO if you need better performance than this.
compiler_flag: "-O3" # Disable assertions
compiler_flag: "-DNDEBUG" # Removal of unused code and data at link time (can this increase binary size in some cases?).
compiler_flag: "-ffunction-sections"
compiler_flag: "-fdata-sections"
linker_flag: "-Wl,--gc-sections"
}
} toolchain {
toolchain_identifier: "local"
abi_libc_version: "local"
abi_version: "local"
builtin_sysroot: ""
compiler: "compiler"
compiler_flag: "-U_FORTIFY_SOURCE"
compiler_flag: "-D_FORTIFY_SOURCE=2"
compiler_flag: "-fstack-protector"
compiler_flag: "-Wall"
compiler_flag: "-Wl,-z,-relro,-z,now"
compiler_flag: "-B/usr/bin"
compiler_flag: "-B/usr/bin"
compiler_flag: "-Wunused-but-set-parameter"
compiler_flag: "-Wno-free-nonheap-object"
compiler_flag: "-fno-omit-frame-pointer"
compiler_flag: "-isystem"
compiler_flag: "/usr/include"
cxx_builtin_include_directory: "/usr/include/c++/5.4.0"
cxx_builtin_include_directory: "/usr/include/c++/5"
cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5/include"
cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu/c++/5.4.0"
cxx_builtin_include_directory: "/usr/include/c++/5.4.0/backward"
cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5.4.0/include"
cxx_builtin_include_directory: "/usr/local/include"
cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5.4.0/include-fixed"
cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed"
cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu"
cxx_builtin_include_directory: "/usr/include"
cxx_flag: "-std=c++11"
host_system_name: "local"
linker_flag: "-lstdc++"
linker_flag: "-lm"
linker_flag: "-Wl,-no-as-needed"
linker_flag: "-B/usr/bin"
linker_flag: "-B/usr/bin"
linker_flag: "-pass-exit-codes"
needsPic: true
objcopy_embed_flag: "-I"
objcopy_embed_flag: "binary"
supports_fission: false
supports_gold_linker: false
supports_incremental_linker: false
supports_interface_shared_objects: false
supports_normalizing_ar: false
supports_start_end_lib: false
supports_thin_archives: false
target_cpu: "k8"
target_libc: "local"
target_system_name: "local"
unfiltered_cxx_flag: "-fno-canonical-system-headers"
unfiltered_cxx_flag: "-Wno-builtin-macro-redefined"
unfiltered_cxx_flag: "-D__DATE__=\"redacted\""
unfiltered_cxx_flag: "-D__TIMESTAMP__=\"redacted\""
unfiltered_cxx_flag: "-D__TIME__=\"redacted\""
tool_path {name: "ar" path: "/usr/bin/ar" }
tool_path {name: "cpp" path: "/usr/bin/cpp" }
tool_path {name: "dwp" path: "/usr/bin/dwp" }
tool_path {name: "gcc" path: "/usr/bin/gcc" }
tool_path {name: "gcov" path: "/usr/bin/gcov" }
tool_path {name: "ld" path: "/usr/bin/ld" }
tool_path {name: "nm" path: "/usr/bin/nm" }
tool_path {name: "objcopy" path: "/usr/bin/objcopy" }
tool_path {name: "objdump" path: "/usr/bin/objdump" }
tool_path {name: "strip" path: "/usr/bin/strip" } compilation_mode_flags {
mode: DBG
compiler_flag: "-g"
}
compilation_mode_flags {
mode: OPT
compiler_flag: "-g0"
compiler_flag: "-O3"
compiler_flag: "-DNDEBUG"
compiler_flag: "-ffunction-sections"
compiler_flag: "-fdata-sections"
linker_flag: "-Wl,--gc-sections"
}
linking_mode_flags { mode: DYNAMIC }
}

CROSSTOOL

  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根据这个文件查找相对应的工具链

  其它的选项并不复杂,不做赘述

  脚本内容如下:

 package(default_visibility = ["//visibility:public"])

 cc_toolchain_suite(
name = "toolchain",
toolchains = {
"armv6|compiler": ":cc-compiler-armv6",
"k8|compiler": ":cc-compiler-local",
},
) filegroup(
name = "empty",
srcs = [],
) filegroup(
name = "arm_linux_all_files",
srcs = [
"@toolchain_target_armv6//:compiler_pieces",
],
) cc_toolchain(
name = "cc-compiler-local",
all_files = ":empty",
compiler_files = ":empty",
cpu = "local",
dwp_files = ":empty",
dynamic_runtime_libs = [":empty"],
linker_files = ":empty",
objcopy_files = ":empty",
static_runtime_libs = [":empty"],
strip_files = ":empty",
supports_param_files = ,
) cc_toolchain(
name = "cc-compiler-armv6",
all_files = ":arm_linux_all_files",
compiler_files = ":arm_linux_all_files",
cpu = "armv6",
dwp_files = ":empty",
dynamic_runtime_libs = [":empty"],
linker_files = ":arm_linux_all_files",
objcopy_files = "arm_linux_all_files",
static_runtime_libs = [":empty"],
strip_files = "arm_linux_all_files",
supports_param_files = ,
)

BUILD

  

  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

  指定编译工具链为树莓派交叉编译工具链

 #!/bin/bash
bazel build --copt="-fPIC" --copt="-march=armv6" \
--copt="-mfloat-abi=hard" \
--copt="-mfpu=neon-vfpv4" \
--copt="-funsafe-math-optimizations" \
--copt="-Wno-unused-function" \
--copt="-Wno-sign-compare" \
--copt="-ftree-vectorize" --copt="-fomit-frame-pointer" \
--cxxopt="-Wno-maybe-uninitialized" \
--cxxopt="-Wno-narrowing" \
--cxxopt="-Wno-unused" \
--cxxopt="-Wno-comment" \
--cxxopt="-Wno-unused-function" \
--cxxopt="-Wno-sign-compare" \
--cxxopt="-funsafe-math-optimizations" \
--linkopt="-mfloat-abi=hard" \
--linkopt="-mfpu=neon-vfpv4" \
--linkopt="-funsafe-math-optimizations" \
--verbose_failures \
--crosstool_top=//armv6-compiler:toolchain --cpu=armv6 --config=opt \
tensorflow/examples/label_image/...

build_armv6.sh

  

  6. 在所有编译之前仅而且必须运行一遍configure

  jmalloc可以选Yes,但是这里还是建议选No,使用C库的malloc

  除了最后一个使用-march=来指定参数,其它一律选No

  新版本的代码加入了一个Android交叉编译交互的配置

  和本文不相干,选No

 

  7. 编译

  运行build_armv6.sh即可开始编译

  编译开始时bazel会自动下载依赖组件

  同时很快将因为错误停止编译

 修正编译错误

  1. 编译时bazel会从网络上下载依赖的子模块,需要网络支持,并且需要**

  否则会出现如下错误:

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贴上来,太懒了,这里先将就

  具体代码内容如下:

 # -*- mode: python; -*-

 # nsync is a C library that exports synchronization primitives, such as reader
# writer locks with conditional critical sections, designed to be open sourced
# in portable C. See https://github.com/google/nsync
#
# See public/*.h for API. When compiled with C++11 rather than C, it's in the
# "nsync" name space.
#
# BUILD file usage:
# deps = "@nsync://nsync" for C version
# deps = "@nsync://nsync_cpp" for C++11 version.
# The latter uses no OS-specific system calls or architecture-specific atomic
# operations. package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) # ---------------------------------------------
# Parameters to the compilation: compiler (e.g., for atomics), architecture
# (e.g., for load and store barrier behaviour), and OS.
# Bazel merges these into one, somewhat slippery, "cpu" string.
# Bazel uses a rather verbose mechanism for choosing which implementations
# are needed on given platforms; hence all the config_setting() rules below. config_setting(
name = "gcc_linux_x86_32_1",
values = {"cpu": "piii"},
) config_setting(
name = "gcc_linux_x86_64_1",
values = {"cpu": "k8"},
) config_setting(
name = "gcc_linux_x86_64_2",
values = {"cpu": "haswell"},
) config_setting(
name = "gcc_linux_aarch64",
values = {"cpu": "arm"},
) config_setting(
name = "gcc_linux_ppc64",
values = {"cpu": "ppc"},
) config_setting(
name = "gcc_linux_s390x",
values = {"cpu": "s390x"},
) config_setting(
name = "clang_macos_x86_64",
values = {"cpu": "darwin"},
) config_setting(
name = "android_x86_32",
values = {"cpu": "x86"},
) config_setting(
name = "android_x86_64",
values = {"cpu": "x86_64"},
) config_setting(
name = "android_armeabi",
values = {"cpu": "armeabi"},
) config_setting(
name = "android_arm",
values = {"cpu": "armeabi-v7a"},
) config_setting(
name = "android_arm64",
values = {"cpu": "arm64-v8a"},
) config_setting(
name = "msvc_windows_x86_64",
values = {"cpu": "x64_windows"},
) config_setting(
name = "freebsd",
values = {"cpu": "freebsd"},
) config_setting(
name = "ios_x86_64",
values = {"cpu": "ios_x86_64"},
) config_setting(
name = "raspberry",
values = {"cpu": "armv6"},
) # ---------------------------------------------
# Compilation options. load(":bazel/pkg_path_name.bzl", "pkg_path_name") # Compilation options that apply to both C++11 and C.
NSYNC_OPTS_GENERIC = select({
# Select the CPU architecture include directory.
# This select() has no real effect in the C++11 build, but satisfies a
# #include that would otherwise need a #if.
":gcc_linux_x86_32_1": ["-I" + pkg_path_name() + "/platform/x86_32"],
":gcc_linux_x86_64_1": ["-I" + pkg_path_name() + "/platform/x86_64"],
":gcc_linux_x86_64_2": ["-I" + pkg_path_name() + "/platform/x86_64"],
":gcc_linux_aarch64": ["-I" + pkg_path_name() + "/platform/aarch64"],
":gcc_linux_ppc64": ["-I" + pkg_path_name() + "/platform/ppc64"],
":gcc_linux_s390x": ["-I" + pkg_path_name() + "/platform/s390x"],
":clang_macos_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"],
":freebsd": ["-I" + pkg_path_name() + "/platform/x86_64"],
":ios_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"],
":android_x86_32": ["-I" + pkg_path_name() + "/platform/x86_32"],
":android_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"],
":android_armeabi": ["-I" + pkg_path_name() + "/platform/arm"],
":android_arm": ["-I" + pkg_path_name() + "/platform/arm"],
":raspberry": ["-I" + pkg_path_name() + "/platform/arm"],
":android_arm64": ["-I" + pkg_path_name() + "/platform/aarch64"],
":msvc_windows_x86_64": ["-I" + pkg_path_name() + "/platform/x86_64"],
}) + [
"-I" + pkg_path_name() + "/public",
"-I" + pkg_path_name() + "/internal",
"-I" + pkg_path_name() + "/platform/posix",
] + select({
":msvc_windows_x86_64": [
],
":freebsd": ["-pthread"],
"//conditions:default": [
"-D_POSIX_C_SOURCE=200809L",
"-pthread",
],
}) # Options for C build, rather then C++11 build.
NSYNC_OPTS = select({
# Select the OS include directory.
":gcc_linux_x86_32_1": ["-I" + pkg_path_name() + "/platform/linux"],
":gcc_linux_x86_64_1": ["-I" + pkg_path_name() + "/platform/linux"],
":gcc_linux_x86_64_2": ["-I" + pkg_path_name() + "/platform/linux"],
":gcc_linux_aarch64": ["-I" + pkg_path_name() + "/platform/linux"],
":gcc_linux_ppc64": ["-I" + pkg_path_name() + "/platform/linux"],
":gcc_linux_s390x": ["-I" + pkg_path_name() + "/platform/linux"],
":clang_macos_x86_64": ["-I" + pkg_path_name() + "/platform/macos"],
":freebsd": ["-I" + pkg_path_name() + "/platform/freebsd"],
":ios_x86_64": ["-I" + pkg_path_name() + "/platform/macos"],
":android_x86_32": ["-I" + pkg_path_name() + "/platform/linux"],
":android_x86_64": ["-I" + pkg_path_name() + "/platform/linux"],
":android_armeabi": ["-I" + pkg_path_name() + "/platform/linux"],
":android_arm": ["-I" + pkg_path_name() + "/platform/linux"],
":raspberry": ["-I" + pkg_path_name() + "/platform/linux"],
":android_arm64": ["-I" + pkg_path_name() + "/platform/linux"],
":msvc_windows_x86_64": ["-I" + pkg_path_name() + "/platform/win32"],
"//conditions:default": [],
}) + select({
# Select the compiler include directory.
":gcc_linux_x86_32_1": ["-I" + pkg_path_name() + "/platform/gcc"],
":gcc_linux_x86_64_1": ["-I" + pkg_path_name() + "/platform/gcc"],
":gcc_linux_x86_64_2": ["-I" + pkg_path_name() + "/platform/gcc"],
":gcc_linux_aarch64": ["-I" + pkg_path_name() + "/platform/gcc"],
":gcc_linux_ppc64": ["-I" + pkg_path_name() + "/platform/gcc"],
":gcc_linux_s390x": ["-I" + pkg_path_name() + "/platform/gcc"],
":clang_macos_x86_64": ["-I" + pkg_path_name() + "/platform/clang"],
":freebsd": ["-I" + pkg_path_name() + "/platform/clang"],
":ios_x86_64": ["-I" + pkg_path_name() + "/platform/clang"],
":android_x86_32": ["-I" + pkg_path_name() + "/platform/gcc"],
":android_x86_64": ["-I" + pkg_path_name() + "/platform/gcc"],
":android_armeabi": ["-I" + pkg_path_name() + "/platform/gcc"],
":android_arm": ["-I" + pkg_path_name() + "/platform/gcc"],
":raspberry": ["-I" + pkg_path_name() + "/platform/gcc"],
":android_arm64": ["-I" + pkg_path_name() + "/platform/gcc"],
":msvc_windows_x86_64": ["-I" + pkg_path_name() + "/platform/msvc"],
}) + select({
# Apple deprecated their atomics library, yet recent versions have no
# working version of stdatomic.h; so some recent versions need one, and
# other versions prefer the other. For the moment, just ignore the
# depreaction.
":clang_macos_x86_64": ["-Wno-deprecated-declarations"],
"//conditions:default": [],
}) + NSYNC_OPTS_GENERIC # Options for C++11 build, rather then C build.
NSYNC_OPTS_CPP = select({
":msvc_windows_x86_64": [
"/TP",
],
"//conditions:default": [
"-x",
"c++",
"-std=c++11",
],
}) + select({
# Some versions of MacOS (notably Sierra) require -D_DARWIN_C_SOURCE
# to include some standard C++11 headers, like <mutex>.
":clang_macos_x86_64": ["-D_DARWIN_C_SOURCE"],
"//conditions:default": [],
}) + [
"-DNSYNC_ATOMIC_CPP11",
"-DNSYNC_USE_CPP11_TIMEPOINT",
"-I" + pkg_path_name() + "/platform/c++11",
] + select({
# must follow the -I...platform/c++11
":ios_x86_64": ["-I" + pkg_path_name() + "/platform/gcc_no_tls"],
":msvc_windows_x86_64": [
"-I" + pkg_path_name() + "/platform/win32",
"-I" + pkg_path_name() + "/platform/msvc",
],
"//conditions:default": ["-I" + pkg_path_name() + "/platform/gcc"],
}) + NSYNC_OPTS_GENERIC # Link options (for tests) built in C (rather than C++11).
NSYNC_LINK_OPTS = select({
":msvc_windows_x86_64": [],
"//conditions:default": ["-pthread"],
}) # Link options (for tests) built in C++11 (rather than C).
NSYNC_LINK_OPTS_CPP = select({
":msvc_windows_x86_64": [],
"//conditions:default": ["-pthread"],
}) # ---------------------------------------------
# Header files the source may include. # Internal library headers.
NSYNC_INTERNAL_HEADERS = [
"internal/common.h",
"internal/dll.h",
"internal/headers.h",
"internal/sem.h",
"internal/wait_internal.h",
] # Internal test headers.
NSYNC_TEST_HEADERS = NSYNC_INTERNAL_HEADERS + [
"testing/array.h",
"testing/atm_log.h",
"testing/closure.h",
"testing/heap.h",
"testing/smprintf.h",
"testing/testing.h",
"testing/time_extra.h",
] # Platform specific headers.
# This declares headers for all platforms, not just the one
# we're building for, to avoid a more complex build file.
NSYNC_INTERNAL_HEADERS_PLATFORM = [
"platform/aarch64/cputype.h",
"platform/alpha/cputype.h",
"platform/arm/cputype.h",
"platform/atomic_ind/atomic.h",
"platform/c++11/atomic.h",
"platform/c++11/platform.h",
"platform/c11/atomic.h",
"platform/clang/atomic.h",
"platform/clang/compiler.h",
"platform/cygwin/platform.h",
"platform/decc/compiler.h",
"platform/freebsd/platform.h",
"platform/gcc/atomic.h",
"platform/gcc/compiler.h",
"platform/gcc_new/atomic.h",
"platform/gcc_new_debug/atomic.h",
"platform/gcc_no_tls/compiler.h",
"platform/gcc_old/atomic.h",
"platform/lcc/compiler.h",
"platform/lcc/nsync_time_init.h",
"platform/linux/platform.h",
"platform/win32/atomic.h",
"platform/macos/platform_c++11_os.h",
"platform/msvc/compiler.h",
"platform/netbsd/atomic.h",
"platform/netbsd/platform.h",
"platform/openbsd/platform.h",
"platform/osf1/platform.h",
"platform/macos/atomic.h",
"platform/macos/platform.h",
"platform/pmax/cputype.h",
"platform/posix/cputype.h",
"platform/posix/nsync_time_init.h",
"platform/posix/platform_c++11_os.h",
"platform/ppc32/cputype.h",
"platform/ppc64/cputype.h",
"platform/s390x/cputype.h",
"platform/shark/cputype.h",
"platform/tcc/compiler.h",
"platform/win32/platform.h",
"platform/win32/platform_c++11_os.h",
"platform/x86_32/cputype.h",
"platform/x86_64/cputype.h",
] # ---------------------------------------------
# The nsync library. # Linux-specific library source.
NSYNC_SRC_LINUX = [
"platform/linux/src/nsync_semaphore_futex.c",
"platform/posix/src/per_thread_waiter.c",
"platform/posix/src/yield.c",
"platform/posix/src/time_rep.c",
"platform/posix/src/nsync_panic.c",
] # Android-specific library source.
NSYNC_SRC_ANDROID = [
"platform/posix/src/nsync_semaphore_sem_t.c",
"platform/posix/src/per_thread_waiter.c",
"platform/posix/src/yield.c",
"platform/posix/src/time_rep.c",
"platform/posix/src/nsync_panic.c",
] # MacOS-specific library source.
NSYNC_SRC_MACOS = [
"platform/posix/src/clock_gettime.c",
"platform/posix/src/nsync_semaphore_mutex.c",
"platform/posix/src/per_thread_waiter.c",
"platform/posix/src/yield.c",
"platform/posix/src/time_rep.c",
"platform/posix/src/nsync_panic.c",
] # Windows-specific library source.
NSYNC_SRC_WINDOWS = [
"platform/posix/src/nsync_panic.c",
"platform/posix/src/per_thread_waiter.c",
"platform/posix/src/time_rep.c",
"platform/posix/src/yield.c",
"platform/win32/src/clock_gettime.c",
"platform/win32/src/init_callback_win32.c",
"platform/win32/src/nanosleep.c",
"platform/win32/src/nsync_semaphore_win32.c",
"platform/win32/src/pthread_cond_timedwait_win32.c",
"platform/win32/src/pthread_key_win32.cc",
] # FreeBSD-specific library source.
NSYNC_SRC_FREEBSD = [
"platform/posix/src/nsync_semaphore_sem_t.c",
"platform/posix/src/per_thread_waiter.c",
"platform/posix/src/yield.c",
"platform/posix/src/time_rep.c",
"platform/posix/src/nsync_panic.c",
] # OS-specific library source.
NSYNC_SRC_PLATFORM = select({
":gcc_linux_x86_32_1": NSYNC_SRC_LINUX,
":gcc_linux_x86_64_1": NSYNC_SRC_LINUX,
":gcc_linux_x86_64_2": NSYNC_SRC_LINUX,
":gcc_linux_aarch64": NSYNC_SRC_LINUX,
":gcc_linux_ppc64": NSYNC_SRC_LINUX,
":gcc_linux_s390x": NSYNC_SRC_LINUX,
":clang_macos_x86_64": NSYNC_SRC_MACOS,
":freebsd": NSYNC_SRC_FREEBSD,
":ios_x86_64": NSYNC_SRC_MACOS,
":android_x86_32": NSYNC_SRC_ANDROID,
":android_x86_64": NSYNC_SRC_ANDROID,
":android_armeabi": NSYNC_SRC_ANDROID,
":android_arm": NSYNC_SRC_ANDROID,
":android_arm64": NSYNC_SRC_ANDROID,
":msvc_windows_x86_64": NSYNC_SRC_WINDOWS,
":raspberry": NSYNC_SRC_LINUX,
}) # C++11-specific (OS and architecture independent) library source.
NSYNC_SRC_PLATFORM_CPP = [
"platform/c++11/src/nsync_semaphore_mutex.cc",
"platform/c++11/src/time_rep_timespec.cc",
"platform/c++11/src/nsync_panic.cc",
"platform/c++11/src/yield.cc",
] + select({
# MacOS and Android don't have working C++11 thread local storage.
":clang_macos_x86_64": ["platform/posix/src/per_thread_waiter.c"],
":android_x86_32": ["platform/posix/src/per_thread_waiter.c"],
":android_x86_64": ["platform/posix/src/per_thread_waiter.c"],
":android_armeabi": ["platform/posix/src/per_thread_waiter.c"],
":android_arm": ["platform/posix/src/per_thread_waiter.c"],
":android_arm64": ["platform/posix/src/per_thread_waiter.c"],
":ios_x86_64": ["platform/posix/src/per_thread_waiter.c"],
":msvc_windows_x86_64": [
"platform/win32/src/clock_gettime.c",
"platform/win32/src/pthread_key_win32.cc",
"platform/c++11/src/per_thread_waiter.cc",
],
"//conditions:default": ["platform/c++11/src/per_thread_waiter.cc"],
}) # Generic library source.
NSYNC_SRC_GENERIC = [
"internal/common.c",
"internal/counter.c",
"internal/cv.c",
"internal/debug.c",
"internal/dll.c",
"internal/mu.c",
"internal/mu_wait.c",
"internal/note.c",
"internal/once.c",
"internal/sem_wait.c",
"internal/time_internal.c",
"internal/wait.c",
] # Generic library header files.
NSYNC_HDR_GENERIC = [
"public/nsync.h",
"public/nsync_atomic.h",
"public/nsync_counter.h",
"public/nsync_cpp.h",
"public/nsync_cv.h",
"public/nsync_debug.h",
"public/nsync_mu.h",
"public/nsync_mu_wait.h",
"public/nsync_note.h",
"public/nsync_once.h",
"public/nsync_time.h",
"public/nsync_time_internal.h",
"public/nsync_waiter.h",
] # The library compiled in C, rather than C++11.
cc_library(
name = "nsync",
srcs = NSYNC_SRC_GENERIC + NSYNC_SRC_PLATFORM,
hdrs = NSYNC_HDR_GENERIC,
copts = NSYNC_OPTS,
includes = ["public"],
textual_hdrs = NSYNC_INTERNAL_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM,
) # The library compiled in C++11, rather than C.
cc_library(
name = "nsync_cpp",
srcs = NSYNC_SRC_GENERIC + NSYNC_SRC_PLATFORM_CPP,
hdrs = NSYNC_HDR_GENERIC,
copts = NSYNC_OPTS_CPP,
includes = ["public"],
textual_hdrs = NSYNC_INTERNAL_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM,
) # nsync_headers provides just the header files for use in projects that need to
# build shared libraries for dynamic loading. Bazel seems unable to cope
# otherwise.
cc_library(
name = "nsync_headers",
hdrs = glob(["public/*.h"]),
includes = ["public"],
) # ---------------------------------------------
# Test code. # Linux-specific test library source.
NSYNC_TEST_SRC_LINUX = [
"platform/posix/src/start_thread.c",
] # Android-specific test library source.
NSYNC_TEST_SRC_ANDROID = [
"platform/posix/src/start_thread.c",
] # MacOS-specific test library source.
NSYNC_TEST_SRC_MACOS = [
"platform/posix/src/start_thread.c",
] # Windows-specific test library source.
NSYNC_TEST_SRC_WINDOWS = [
"platform/win32/src/start_thread.c",
] # FreeBSD-specific test library source.
NSYNC_TEST_SRC_FREEBSD = [
"platform/posix/src/start_thread.c",
] # OS-specific test library source.
NSYNC_TEST_SRC_PLATFORM = select({
":gcc_linux_x86_32_1": NSYNC_TEST_SRC_LINUX,
":gcc_linux_x86_64_1": NSYNC_TEST_SRC_LINUX,
":gcc_linux_x86_64_2": NSYNC_TEST_SRC_LINUX,
":gcc_linux_aarch64": NSYNC_TEST_SRC_LINUX,
":gcc_linux_ppc64": NSYNC_TEST_SRC_LINUX,
":gcc_linux_s390x": NSYNC_TEST_SRC_LINUX,
":clang_macos_x86_64": NSYNC_TEST_SRC_MACOS,
":freebsd": NSYNC_TEST_SRC_FREEBSD,
":ios_x86_64": NSYNC_TEST_SRC_MACOS,
":android_x86_32": NSYNC_TEST_SRC_ANDROID,
":android_x86_64": NSYNC_TEST_SRC_ANDROID,
":android_armeabi": NSYNC_TEST_SRC_ANDROID,
":android_arm": NSYNC_TEST_SRC_ANDROID,
":android_arm64": NSYNC_TEST_SRC_ANDROID,
":msvc_windows_x86_64": NSYNC_TEST_SRC_WINDOWS,
":raspberry": NSYNC_TEST_SRC_LINUX,
}) # C++11-specific (OS and architecture independent) test library source.
NSYNC_TEST_SRC_PLATFORM_CPP = [
"platform/c++11/src/start_thread.cc",
] # Generic test library source.
NSYNC_TEST_SRC_GENERIC = [
"testing/array.c",
"testing/atm_log.c",
"testing/closure.c",
"testing/smprintf.c",
"testing/testing.c",
"testing/time_extra.c",
] # The test library compiled in C, rather than C++11.
cc_library(
name = "nsync_test_lib",
testonly = 1,
srcs = NSYNC_TEST_SRC_GENERIC + NSYNC_TEST_SRC_PLATFORM,
hdrs = ["testing/testing.h"],
copts = NSYNC_OPTS,
textual_hdrs = NSYNC_TEST_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM,
deps = [":nsync"],
) # The test library compiled in C++11, rather than C.
cc_library(
name = "nsync_test_lib_cpp",
testonly = 1,
srcs = NSYNC_TEST_SRC_GENERIC + NSYNC_TEST_SRC_PLATFORM_CPP,
hdrs = ["testing/testing.h"],
copts = NSYNC_OPTS_CPP,
textual_hdrs = NSYNC_TEST_HEADERS + NSYNC_INTERNAL_HEADERS_PLATFORM,
deps = [":nsync_cpp"],
) # ---------------------------------------------
# The tests, compiled in C rather than C++11. cc_test(
name = "counter_test",
size = "small",
srcs = ["testing/counter_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "cv_mu_timeout_stress_test",
size = "small",
srcs = ["testing/cv_mu_timeout_stress_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "cv_test",
size = "small",
srcs = ["testing/cv_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "cv_wait_example_test",
size = "small",
srcs = ["testing/cv_wait_example_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "dll_test",
size = "small",
srcs = ["testing/dll_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "mu_starvation_test",
size = "small",
srcs = ["testing/mu_starvation_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "mu_test",
size = "small",
srcs = ["testing/mu_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "mu_wait_example_test",
size = "small",
srcs = ["testing/mu_wait_example_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "mu_wait_test",
size = "small",
srcs = ["testing/mu_wait_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "note_test",
size = "small",
srcs = ["testing/note_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "once_test",
size = "small",
srcs = ["testing/once_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "pingpong_test",
size = "small",
srcs = ["testing/pingpong_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) cc_test(
name = "wait_test",
size = "small",
srcs = ["testing/wait_test.c"],
copts = NSYNC_OPTS,
linkopts = NSYNC_LINK_OPTS,
deps = [
":nsync",
":nsync_test_lib",
],
) # ---------------------------------------------
# The tests, compiled in C++11, rather than C. cc_test(
name = "counter_cpp_test",
size = "small",
srcs = ["testing/counter_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "cv_mu_timeout_stress_cpp_test",
size = "small",
srcs = ["testing/cv_mu_timeout_stress_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "cv_cpp_test",
size = "small",
srcs = ["testing/cv_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "cv_wait_example_cpp_test",
size = "small",
srcs = ["testing/cv_wait_example_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "dll_cpp_test",
size = "small",
srcs = ["testing/dll_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "mu_starvation_cpp_test",
size = "small",
srcs = ["testing/mu_starvation_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "mu_cpp_test",
size = "small",
srcs = ["testing/mu_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "mu_wait_example_cpp_test",
size = "small",
srcs = ["testing/mu_wait_example_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "mu_wait_cpp_test",
size = "small",
srcs = ["testing/mu_wait_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "note_cpp_test",
size = "small",
srcs = ["testing/note_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "once_cpp_test",
size = "small",
srcs = ["testing/once_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "pingpong_cpp_test",
size = "small",
srcs = ["testing/pingpong_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
) cc_test(
name = "wait_cpp_test",
size = "small",
srcs = ["testing/wait_test.c"],
copts = NSYNC_OPTS_CPP,
linkopts = NSYNC_LINK_OPTS_CPP,
deps = [
":nsync_cpp",
":nsync_test_lib_cpp",
],
)

nsync BUILD

  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

 #!/bin/bash

 tflite_model="tensorflow/contrib/lite/kernels/internal:tensor_utils_test"
if [ $@"z" == "z" ]
then
echo "$0 ${tflite_model}"
else
tflite_model=$@
fi
bazel build --copt="-fPIC" --copt="-march=armv6" \
--copt="-mfloat-abi=hard" \
--copt="-mfpu=neon-vfpv4" \
--copt="-funsafe-math-optimizations" \
--copt="-Wno-unused-function" \
--copt="-Wno-sign-compare" \
--copt="-ftree-vectorize" \
--copt="-fomit-frame-pointer" \
--cxxopt='--std=c++11' \
--cxxopt="-Wno-maybe-uninitialized" \
--cxxopt="-Wno-narrowing" \
--cxxopt="-Wno-unused" \
--cxxopt="-Wno-comment" \
--cxxopt="-Wno-unused-function" \
--cxxopt="-Wno-sign-compare" \
--cxxopt="-funsafe-math-optimizations" \
--linkopt="-lstdc++" \
--linkopt="-mfloat-abi=hard" \
--linkopt="-mfpu=neon-vfpv4" \
--linkopt="-funsafe-math-optimizations" \
--verbose_failures \
--strip=always \
--crosstool_top=//armv6-compiler:toolchain --cpu=armv6 --config=opt \
$@

build_tflite.sh

  

  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

上一篇:c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)


下一篇:Stanford机器学习笔记-6. 学习模型的评估和选择