全志T113 Tina-SDK 配套工具链开发应用从Makefile到CMake再到Autotools本章内容掌握Tina-SDK中交叉编译工具链的用法学会编写Makefile、CMakeLists.txt以及Autotools构建脚本将你的C程序交叉编译为ARM可执行文件并通过ADB部署到开发板上运行。这是嵌入式Linux应用开发的起点学完本章你就能独立完成“编译-部署-运行”的完整闭环。文章目录全志T113 Tina-SDK 配套工具链开发应用从Makefile到CMake再到Autotools第一部分交叉编译工具链位置与配置第二部分系统库和头文件位置第三部分使用 Makefile 交叉编译 Hello 程序3.1 编写源代码 hello.c3.2 编写 Makefile3.3 执行编译第四部分使用 CMake 交叉编译4.1 安装 CMake4.2 编写 CMakeLists.txt4.3 使用外部构建out-of-source4.4 编译4.5 验证第六部分使用 Autotools 交叉编译5.1 准备工作确认开发板架构和交叉工具链5.2 清理之前编译的残留文件5.3 配置交叉编译静态链接5.4 编译5.5 验证生成的可执行文件5.6 通过 ADB 传输到开发板并运行5.7 常见错误汇总与解决方案5.8 完整一键脚本供参考第六部分ADB 连接开发板并部署程序6.1 连接开发板 USB 到虚拟机6.2 推送可执行文件到开发板6.3 通过串口或 adb shell 运行第七部分常见错误与注意事项7.1 Makefile 中缺少 TAB 键7.2 STAGING_DIR 未定义警告7.3 CMake 未使用交叉编译器7.4 Autotools 缺少宏或工具面试官提问环节第1问Tina-SDK 交叉编译工具链的前缀是什么如何将其加入 PATH第2问使用 Makefile 交叉编译时常见的缩进错误是什么如何解决第3问CMake 交叉编译时如何指定交叉编译器需要注意什么顺序第4问Autotools 项目的 ./configure 中 --host 和 --prefix 分别有什么作用第5问adb push 和 adb shell 的作用是什么第一部分交叉编译工具链位置与配置bashbookubuntu1804:~/tina-d1-h/prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/bin$ ls arm-openwrt-linux-addr2line arm-openwrt-linux-muslgnueabi-addr2line arm-openwrt-linux-ar arm-openwrt-linux-muslgnueabi-ar arm-openwrt-linux-as arm-openwrt-linux-muslgnueabi-as arm-openwrt-linux-c arm-openwrt-linux-muslgnueabi-c ... arm-openwrt-linux-gcc arm-openwrt-linux-muslgnueabi-gcc arm-openwrt-linux-gcc-6.4.1 arm-openwrt-linux-muslgnueabi-gcc-6.4.1 ...讲解Tina-SDK 自带的交叉编译工具链位于 SDK 目录下的prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/bin。工具链命名规则前缀为arm-openwrt-linux-muslgnueabi-后面跟具体工具名例如arm-openwrt-linux-muslgnueabi-gccC 编译器arm-openwrt-linux-muslgnueabi-gC 编译器arm-openwrt-linux-muslgnueabi-ld链接器arm-openwrt-linux-muslgnueabi-strip去除调试符号C 库类型musl—— 轻量级 C 库适合嵌入式系统。工具链基于 GCC 6.4.1。配置 PATH 环境变量临时仅当前终端有效bashexport PATH$PATH:/home/ubuntu/tina-d1-h/prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/bin验证工具链basharm-openwrt-linux-muslgnueabi-gcc -v你应该能看到gcc version 6.4.1 (OpenWrt/Linaro GCC 6.4.2017.11)等信息。提示每次新开终端都需要重新执行export或者将命令写入~/.bashrc永久生效。第二部分系统库和头文件位置bash# 系统lib库所在路径 ~/tina-d1-h/out/t113-100ask/staging_dir/target/usr/lib # 系统头文件所在路径 ~/tina-d1-h/out/t113-100ask/staging_dir/target/usr/include # 全志专用头文件 ~/tina-d1-h/out/t113-100ask/staging_dir/target/usr/include/allwinner讲解当你用 Tina-SDK 编译完系统执行过make后out/t113-100ask/staging_dir/target/目录下会生成一个临时的根文件系统镜像里面包含了usr/lib所有编译好的动态库.so和静态库.ausr/include所有头文件usr/include/allwinner全志芯片专用驱动/硬件接口头文件为什么需要这些路径当你编写应用程序并依赖某些库如 libcurl、libxml2、libaw_aacdec 等时编译器和链接器需要知道头文件位置用-I参数库文件位置用-L参数后面我们的 Makefile 和 CMake 都会引用这些路径。第三部分使用 Makefile 交叉编译 Hello 程序3.1 编写源代码 hello.cc#include stdio.h int main(void) { printf (Hello 100ASK T113-Pro !!! \r\n); return 0; }3.2 编写 MakefilemakefileCC : arm-openwrt-linux-muslgnueabi-gcc hello: hello.c ${CC} -o hello hello.c # 注意这行前面必须是【TAB】键不能是空格 clean: rm hello重要错误Makefile 中命令行的缩进必须使用TAB 键不能用空格。如果使用空格会报错textMakefile:3: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.解决方法用vi或vim打开 Makefile将hello:下一行的空格全部删除然后按Tab键重新缩进。3.3 执行编译bashubuntuubuntu1804:~$ make arm-openwrt-linux-muslgnueabi-gcc -o hello hello.c arm-openwrt-linux-muslgnueabi-gcc.bin: warning: environment variable STAGING_DIR not defined arm-openwrt-linux-muslgnueabi-gcc.bin: warning; environment variable STAGING_DIR not defined警告解释STAGING_DIR是 Tina 构建系统使用的环境变量指向out/.../staging_dir目录。如果不定义工具链可能找不到一些库和头文件。但对于一个简单的printf程序这个警告可以忽略因为 libc 是工具链自带的。验证生成的文件bashfile hello输出texthello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-armhf.so.1, not strippedARM说明是 ARM 架构dynamically linked动态链接需要依赖板子上的 musl C 库interpreter /lib/ld-musl-armhf.so.1动态链接器的路径ADB 传输要点:OTG/Debug都要接上串口线,并且虚拟机也要连接上ADBadb push推送通过串口到开发板正常应该看到这样的效果第四部分使用 CMake 交叉编译4.1 安装 CMakebashubuntuubuntu1804:~$ sudo apt install cmake4.2 编写 CMakeLists.txtcmakecmake_minimum_required(VERSION 3.10) project(helloword) SET(CROSS_COMPILE 1) set(CMAKE_SYSTEM_NAME Linux) # 交叉编译器路径 set(CMAKE_C_COMPILER /home/ubuntu/tina-d1-h/prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/bin/arm-openwrt-linux-muslgnueabi-gcc) # 链接库路径 link_directories( /home/ubuntu/tina-d1-h/out/t113-100ask/staging_dir/target/usr/lib ) # 头文件路径 include_directories(/home/ubuntu/tina-d1-h/out/t113-100ask/staging_dir/target/usr/include/) include_directories(/home/ubuntu/tina-d1-h/out/t113-100ask/staging_dir/target/usr/include/allwinner/) include_directories(/home/ubuntu/tina-d1-h/out/t113-100ask/staging_dir/target/usr/include/allwinner/include/) add_executable(hello_word hello.c)4.3 使用外部构建out-of-sourcebashmkdir build cd build cmake ..执行cmake ..后会生成 Makefile 文件。输出注意此处cmake检测到的是主机 GCC而不是交叉编译器——这是错误的text-- The C compiler identification is GNU 7.5.0 -- Check for working C compiler: /usr/bin/cc ...问题上面的 CMakeLists.txt 中明明设置了CMAKE_C_COMPILER为什么还是用了主机的/usr/bin/cc原因set(CMAKE_C_COMPILER ...)必须在project()之前定义否则 CMake 会先使用默认编译器探测。修正后的 CMakeLists.txt 开头应该是cmakecmake_minimum_required(VERSION 3.10) set(CMAKE_C_COMPILER /path/to/arm-openwrt-linux-muslgnueabi-gcc) project(helloword) ...同学们可以按照修正后的顺序编写。4.4 编译bashmake输出显示交叉编译器被调用同样会有STAGING_DIR警告。最终生成hello_word可执行文件。4.5 验证bashfile hello_word应该看到ELF 32-bit LSB executable, ARM。依旧串口传输正常结果第六部分使用 Autotools 交叉编译5.1 准备工作确认开发板架构和交叉工具链首先登录开发板通过串口或 ADB查看架构bash# 在开发板上执行 uname -m典型输出armv7l32位 ARM或aarch6464位 ARM。本文以armv7lTinaLinux使用 musl libc为例。在 Ubuntu 宿主机上你需要目标平台的交叉编译器。Tina SDK 通常自带工具链其前缀类似arm-openwrt-linux-muslgnueabi。如果你还没有配置好环境变量可以先定位工具链位置bash# 假设 $T 指向 Tina SDK 根目录 ls $T/prebuilt/gcc/linux-x86/arm/arm-openwrt-linux-muslgnueabi/bin/确认存在arm-openwrt-linux-muslgnueabi-gcc后将其加入 PATHbashexport PATH$T/prebuilt/gcc/linux-x86/arm/arm-openwrt-linux-muslgnueabi/bin:$PATH注意如果你的 SDK 路径不同请相应修改。也可以使用系统自带的gcc-arm-linux-gnueabihf但 TinaLinux 使用 musl静态链接时一般能兼容不过推荐使用 SDK 配套的工具链。5.2 清理之前编译的残留文件在~/hello_auto目录下执行bashcd ~/hello_auto make distclean这会删除所有由configure和make生成的文件让项目回到刚跑完automake --add-missing的状态。5.3 配置交叉编译静态链接运行configure脚本并指定--host目标三元组告诉 build 系统我们要交叉编译CC明确指定交叉编译器防止 configure 找到宿主机 gccLDFLAGS-static静态链接避免开发板上缺少动态库bash./configure --hostarm-openwrt-linux-muslgnueabi \ --prefix/usr \ CCarm-openwrt-linux-muslgnueabi-gcc \ LDFLAGS-static成功标志输出中应出现checking whether we are cross compiling... yes。如果报错C compiler cannot create executables请检查交叉编译器路径是否正确which arm-openwrt-linux-muslgnueabi-gcc是否缺少必要的库如静态 libc可尝试去掉LDFLAGS-static先测试动态链接。5.4 编译bashmake输出中应看到交叉编译器被调用例如textarm-openwrt-linux-muslgnueabi-gcc -DHAVE_CONFIG_H ... -c -o main.o main.c arm-openwrt-linux-muslgnueabi-gcc -static -o hello main.o如果出现warning: environment variable STAGING_DIR not defined可忽略不影响结果。5.5 验证生成的可执行文件bashfile src/hello期望输出textsrc/hello: ELF 32-bit LSB executable, ARM, statically linked, ...5.6 通过 ADB 传输到开发板并运行常见错误1adb push 时目标路径写错bash# 错误目标是一个目录未指定文件名 adb push src/hello /data/local/tmp/ # 报错remote Is a directory # 正确指定完整路径文件名 adb push src/hello /data/local/tmp/hello常见错误2推送到 /root 后无法 chmod如果你 push 到/root/hello_arm在 Ubuntu 宿主机上执行chmod 755 /root/hello_arm会报Permission denied因为/root是开发板上的目录你需要在开发板上执行 chmod。正确做法bash# 1. 推送到开发板可写的目录例如 /data/local/tmp/ 或 /root adb push src/hello /data/local/tmp/hello_arm # 2. 通过 adb shell 登录开发板修改权限并运行 adb shell chmod 755 /data/local/tmp/hello_arm /data/local/tmp/hello_arm或者一条命令完成bashadb push src/hello /data/local/tmp/hello_arm \ adb shell chmod 755 /data/local/tmp/hello_arm \ adb shell /data/local/tmp/hello_arm预期输出textHello World! This is amhello 1.0:5.7 常见错误汇总与解决方案错误现象原因解决方法config.status: error: cannot find input file: Makefile.in忘记运行automake --add-missing或autoheader执行aclocal; autoheader; autoconf; automake --add-missingmake: *** No targets specified and no makefile found.没有先运行./configure先运行./configure生成 Makefile./hello: line 1: syntax error: unexpected word在开发板上运行了 x86 版本的可执行文件确认交叉编译并file查看架构adb push: remote Is a directory目标路径末尾带了/且未指定文件名指定完整文件名如/data/local/tmp/hellochmod: cannot access /root/hello_arm: Permission denied在宿主机上对开发板路径执行 chmod应通过adb shell chmod ...在开发板上执行arm-openwrt-linux-muslgnueabi-gcc.bin: warning: environment variable STAGING_DIR not definedTina SDK 环境变量缺失可忽略不影响编译若要消除export STAGING_DIR$T/staging_dir/target-…cannot execute binary file: Exec format error开发板架构与编译目标不匹配如 64 位板子运行 32 位程序检查开发板uname -m重新配置正确的--host如aarch64-openwrt-linux-musl5.8 完整一键脚本供参考将以下内容保存为cross_build.sh根据你的实际工具链路径修改bash#!/bin/bash # 交叉编译并自动部署到开发板 # 设置工具链路径根据实际修改 export PATH/path/to/tina-sdk/prebuilt/gcc/linux-x86/arm/arm-openwrt-linux-muslgnueabi/bin:$PATH export STAGING_DIR/path/to/tina-sdk/staging_dir/target-arm_cortex-a7_musl-1.1.16_eabi # 可选 # 清理 make distclean # 配置 ./configure --hostarm-openwrt-linux-muslgnueabi \ --prefix/usr \ CCarm-openwrt-linux-muslgnueabi-gcc \ LDFLAGS-static # 编译 make # 检查 file src/hello # 部署 adb push src/hello /data/local/tmp/hello_arm adb shell chmod 755 /data/local/tmp/hello_arm adb shell /data/local/tmp/hello_arm执行bash cross_build.sh即可完成全流程。第六部分ADB 连接开发板并部署程序6.1 连接开发板 USB 到虚拟机VMware 菜单 → 可移动设备 → 选择Google Tina ADB→ 连接。确保开发板已启动并且 USB 线OTG 口连接到电脑。在虚拟机中执行bashadb devices输出textList of devices attached 20080411 device说明设备已识别。6.2 推送可执行文件到开发板bashadb push hello /root/输出texthello: 1 file pushed. 1.3 MB/s (7132 bytes in 0.005s)6.3 通过串口或 adb shell 运行bashadb shell # 进入板子 shell cd /root ./hello图片输出textHello 100ASK T113-Pro !!!第七部分常见错误与注意事项7.1 Makefile 中缺少 TAB 键错误信息missing separator解决用vi确保命令行前是Tab而不是空格。7.2 STAGING_DIR 未定义警告警告environment variable STAGING_DIR not defined影响简单程序无影响若依赖外部库可能找不到。解决可选bashexport STAGING_DIR/home/ubuntu/tina-d1-h/out/t113-100ask/staging_dir7.3 CMake 未使用交叉编译器现象cmake输出显示/usr/bin/cc解决将set(CMAKE_C_COMPILER ...)放在project()之前。7.4 Autotools 缺少宏或工具bashsudo apt install autoconf automake libtool面试官提问环节第1问Tina-SDK 交叉编译工具链的前缀是什么如何将其加入 PATH参考答案前缀为arm-openwrt-linux-muslgnueabi-。加入 PATHbashexport PATH$PATH:/home/ubuntu/tina-d1-h/prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/bin第2问使用 Makefile 交叉编译时常见的缩进错误是什么如何解决参考答案Makefile 中命令必须以Tab 字符开头不能用空格。错误提示missing separator。用vi打开将空格删除后按Tab键即可。第3问CMake 交叉编译时如何指定交叉编译器需要注意什么顺序参考答案在 CMakeLists.txt 中cmakeset(CMAKE_C_COMPILER /path/to/arm-openwrt-linux-muslgnueabi-gcc) project(helloword)必须先设置编译器再调用project()否则 CMake 会先使用默认编译器探测。第4问Autotools 项目的./configure中--host和--prefix分别有什么作用参考答案--host指定目标系统三元组使 configure 查找对应的交叉编译器。--prefix指定安装目录例如/usr最终可执行文件会安装在/usr/bin相对于 DESTDIR 而言。第5问adb push和adb shell的作用是什么参考答案adb push 本地文件 远程路径将主机文件传输到开发板。adb shell打开开发板的远程终端可直接执行板子上的命令。结束语本章通过 Makefile、CMake、Autotools 三种方式演示了如何交叉编译应用程序并通过 ADB 部署到 T113 开发板运行。这三种构建系统覆盖了绝大多数嵌入式项目的需求。作为初学者建议先熟练掌握 Makefile 方法最直接再了解 CMake 和 Autotools阅读开源项目时会遇到。反复练习直到能独立完成从编写代码到板子上运行的完整流程。加油