本文记录使用命令 OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh 构建 Tree 2.2.1 的完整过程,包括环境、构建链路、关键日志、常见问题与解决方案、产物验证与重建方法,便于复现与运维。
📖 Tree 简介
Tree 是一个递归目录树显示工具,用于以树状结构显示目录和文件。它可以帮助用户快速了解目录结构,是系统管理和开发调试中常用的可视化工具。
🎯 Tree 的作用与重要性
Tree 是目录结构可视化的核心工具,提供了:
- 目录树显示:以树状结构递归显示目录和文件
- 格式化输出:美观的树状格式,易于阅读
- 过滤功能:支持按文件类型、名称模式等过滤显示
- 统计信息:显示文件数量、目录数量等统计信息
- 多种输出格式:支持 ASCII、HTML、XML 等多种输出格式
- 跨平台兼容:支持多种操作系统和文件系统
🔧 Tree 核心特性
1. 显示选项
- 目录树结构:递归显示目录和文件的树状结构
- 文件信息:显示文件大小、权限、修改时间等信息
- 符号链接:显示符号链接的目标
- 隐藏文件:可选择显示或隐藏隐藏文件
- 深度限制:限制显示的目录深度
2. 过滤功能
- 文件类型过滤:只显示特定类型的文件
- 名称模式过滤:使用通配符或正则表达式过滤文件名
- 目录过滤:排除特定目录(如 node_modules、.git)
- 大小过滤:只显示大于或小于特定大小的文件
3. 输出格式
- ASCII 格式:默认的 ASCII 树状格式
- HTML 格式:生成 HTML 格式的目录树
- XML 格式:生成 XML 格式的目录树
- JSON 格式:生成 JSON 格式的目录树(部分版本支持)
4. 统计信息
- 文件计数:统计文件和目录数量
- 大小统计:统计总文件大小
- 类型统计:统计不同文件类型的数量
5. 应用场景
- 目录导航:快速了解目录结构
- 项目文档:生成项目目录结构文档
- 系统管理:查看系统目录结构
- 调试定位:定位文件和目录位置
- 备份规划:规划备份目录结构
🚀 构建入口与环境
- 📝 执行命令 :
OHOS_ARCH=aarch64 OHOS_ABI=arm64-v8a sh ./create-hnp.sh - 🔧 入口脚本 :
create-hnp.sh- 检查必需的环境变量
OHOS_ARCH和OHOS_ABI - 导出
LC_CTYPE、TOOL_HOME、OHOS_SDK_HOME - 执行
make -C build-hnp
- 检查必需的环境变量
- 📦 顶层构建 :
build-hnp/MakefilePKGS变量定义需要构建的包列表(包含tree)- 通过
check-pkgs机制自动检测PKGS变化并触发重新构建 - 自动合并
external-hnp目录下的外部 HNP 包 base.hnp依赖所有包的.stamp和外部 HNP 包- 总目标
all: copy,打包base.hnp并拷贝到entry/hnp/$(OHOS_ABI)
⚙️ Tree 包的构建配置
- 📁 包目录 :
build-hnp/tree/Makefile- 继承通用规则:
include ../utils/Makefrag - 源地址:
https://github.com/Old-Man-Programmer/tree/archive/refs/tags/2.2.1.tar.gz - 版本:
2.2.1
- 继承通用规则:
- 🔨 构建流程 :
- 下载源码包(支持多镜像回退)
- 解包并进入
temp/tree-2.2.1目录 - 使用自定义 Makefile 直接编译(不使用 Autotools)
- 指定交叉编译器:
CC=$(OHOS_SDK_HOME)/native/llvm/bin/$(OHOS_ARCH)-unknown-linux-ohos-clang - 使用
make install安装 - 复制到
../sysroot
- ⚙️ 关键编译参数 :
CFLAGS="-O3 -static -std=c11 -pedantic -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DLINUX"-O3- 最高优化级别-static- 静态链接-std=c11- 使用 C11 标准-pedantic -Wall- 严格编译检查和警告-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64- 大文件支持-DLINUX- 定义 Linux 平台
LDFLAGS="-static"- 静态链接标志
- 🔧 静态链接策略 :
- 采用静态链接,确保在目标设备上无需额外依赖即可运行
- 适合在设备环境不完整时使用
- 缺点:二进制体积增大(约 1.1MB)
📋 关键日志与过程节点
- 📥 下载与解包 :
- 从 GitHub Releases 下载
2.2.1.tar.gz - 完成解包并进入
temp/tree-2.2.1目录 - 下载规则支持多镜像回退:
wget→curl兜底
- 从 GitHub Releases 下载
- 🔨 编译阶段 :
- 使用交叉编译器直接编译
- 编译警告:
strverscmp函数未声明(不影响构建) - 编译警告:
strverscmp.c中的 UTF-8 注释无效(不影响构建) - 成功编译生成静态链接的
tree二进制
- 📦 安装与打包 :
- 使用
make install安装到临时前缀 - 复制到
../sysroot - 完成
base.hnp重打包,拷贝产物到entry/hnp/arm64-v8a/ - Tree 工具已成功打包到
base.hnp中
- 使用
✅ 产物验证
📦 检查打包文件
bash
ls build-hnp/base.hnp # 应存在
ls entry/hnp/arm64-v8a/*.hnp # 应包含 base.hnp 与 base-public.hnp
🔍 检查二进制文件
bash
# 检查 tree 二进制
ls -lh build-hnp/sysroot/bin/tree
file build-hnp/sysroot/bin/tree
# 测试 tree 版本(在目标设备上)
build-hnp/sysroot/bin/tree --version
✅ 构建验证结果:
- ✅ Tree 二进制已成功安装:
tree(1.1M) - 主程序二进制(静态链接)
- ✅ 文件类型:ELF 64-bit LSB executable, ARM aarch64
- ✅ 链接方式:
statically linked - ✅ 包含调试信息:
with debug_info, not stripped - ✅ 已打包到
base.hnp中(1,059,232 字节)
💻 终端中执行的示例命令
🌳 Tree 基本使用
1. 基本目录树显示
bash
# 显示当前目录树
tree
# 显示指定目录树
tree /path/to/directory
# 显示目录树(限制深度)
tree -L 2
# 显示目录树(只显示目录)
tree -d
# 显示目录树(显示隐藏文件)
tree -a
# 显示目录树(显示文件大小)
tree -h
# 显示目录树(显示权限)
tree -p
# 显示目录树(显示修改时间)
tree -D

2. 过滤和排除
bash
# 排除特定目录
tree -I 'node_modules|.git'
# 只显示特定文件类型
tree -P '*.txt'
# 排除特定文件类型
tree -I '*.log'
# 排除多个模式
tree -I 'node_modules|.git|*.log|*.tmp'
# 只显示匹配的文件
tree -P '*.c|*.h'
# 排除匹配的文件
tree -I '*.o|*.a'

3. 输出格式
bash
# ASCII 格式(默认)
tree
# HTML 格式
tree -H . -o tree.html
# XML 格式
tree -X -o tree.xml
# JSON 格式(如果支持)
tree -J -o tree.json
# 彩色输出
tree -C
# 不使用颜色
tree --noreport
4. 统计信息
bash
# 显示统计信息
tree -s
# 显示文件大小(人类可读)
tree -h -s
# 只显示统计信息(不显示树)
tree --du -h
# 显示目录大小
tree -d -h -s
# 显示文件数量
tree | tail -1

5. 高级选项
bash
# 显示完整路径
tree -f
# 显示相对路径
tree -f -L 2
# 显示文件权限
tree -p
# 显示文件所有者
tree -u
# 显示文件组
tree -g
# 显示文件修改时间
tree -D
# 显示文件大小(字节)
tree -s
# 显示文件大小(人类可读)
tree -h
🌳 Tree 高级用法
6. 目录深度控制
bash
# 限制显示深度为 2 层
tree -L 2
# 限制显示深度为 3 层
tree -L 3
# 显示完整深度
tree -L 999
# 只显示当前目录
tree -L 0
# 显示两层目录
tree -L 2 -d
7. 文件类型过滤
bash
# 只显示目录
tree -d
# 只显示文件
tree -f -I '^$'
# 只显示特定扩展名
tree -P '*.txt'
# 排除特定扩展名
tree -I '*.log'
# 只显示 C 源文件
tree -P '*.c|*.h'
# 排除编译产物
tree -I '*.o|*.a|*.so'
8. 输出到文件
bash
# 输出到文件
tree > tree.txt
# 输出 HTML 格式
tree -H . -o tree.html
# 输出 XML 格式
tree -X -o tree.xml
# 输出并显示统计
tree -s > tree.txt
# 输出并限制深度
tree -L 2 > tree.txt
9. 实际应用示例
bash
# 查看项目目录结构
tree -I 'node_modules|.git|dist|build' -L 3
# 查看系统目录结构
tree -L 2 /etc
# 查看用户目录结构
tree -L 2 ~
# 生成项目文档
tree -H . -o docs/tree.html
# 查看目录大小
tree -d -h -s /path/to/directory
# 查找特定文件
tree -f | grep filename
# 统计文件数量
tree | tail -1
# 查看目录树并保存
tree -L 3 -I 'node_modules|.git' > project_structure.txt
# 查看目录树(带权限)
tree -p -L 2
# 查看目录树(带时间戳)
tree -D -L 2
# 查看目录树(带大小)
tree -h -s -L 2
# 排除多个目录
tree -I 'node_modules|.git|dist|build|.cache' -L 3
# 只显示特定文件类型
tree -P '*.md|*.txt' -L 2
# 查看目录树并过滤
tree -L 2 | grep -v 'node_modules'
# 生成目录结构文档
tree -H . -T "Project Structure" -o docs/structure.html
# 查看目录树(JSON 格式,如果支持)
tree -J -L 2
# 查看目录树(XML 格式)
tree -X -L 2 -o structure.xml
# 查看目录树并统计
tree -s -L 2 | tail -5
# 查看目录树(彩色输出)
tree -C -L 2
# 查看目录树(不显示报告)
tree --noreport -L 2
# 查看目录树(显示完整路径)
tree -f -L 2
# 查看目录树(只显示目录)
tree -d -L 2
# 查看目录树(显示文件大小)
tree -h -L 2
# 查看目录树(显示权限)
tree -p -L 2
# 查看目录树(显示修改时间)
tree -D -L 2
10. 组合使用示例
bash
# 查看项目结构(排除常见目录,限制深度,显示大小)
tree -I 'node_modules|.git|dist|build' -L 3 -h -s
# 生成项目文档(HTML 格式,排除构建目录)
tree -H . -I 'node_modules|.git|dist|build' -o docs/structure.html
# 查看目录树(只显示源代码文件)
tree -P '*.c|*.h|*.cpp|*.hpp' -L 3
# 查看目录树(排除编译产物和依赖)
tree -I '*.o|*.a|*.so|node_modules|.git' -L 3
# 查看目录树(显示统计信息)
tree -s -L 2 | tail -1
# 查看目录树(带权限和时间)
tree -p -D -L 2
# 查看目录树(只显示目录,带大小)
tree -d -h -s -L 2
# 查看目录树(输出到文件并显示)
tree -L 3 | tee tree_output.txt
# 查看目录树(过滤后输出)
tree -L 3 | grep -v 'node_modules' | grep -v '.git'
# 查看目录树(JSON 格式,如果支持)
tree -J -L 2 | jq .
# 查看目录树(XML 格式)
tree -X -L 2 | xmllint --format -
🧪 功能验证脚本
bash
#!/bin/bash
# Tree 工具验证脚本
TREE_BIN="build-hnp/sysroot/bin"
echo "=== Tree 工具验证 ==="
# 检查 tree 二进制
if [ -f "$TREE_BIN/tree" ]; then
echo "✓ tree: 存在"
file "$TREE_BIN/tree"
echo "文件大小: $(ls -lh "$TREE_BIN/tree" | awk '{print $5}')"
echo "架构信息: $(file "$TREE_BIN/tree" | grep -o "ARM aarch64")"
echo "链接方式: $(file "$TREE_BIN/tree" | grep -o "statically linked")"
# 测试版本信息(在目标设备上)
echo ""
echo "版本信息(需要在目标设备上运行):"
echo " $TREE_BIN/tree --version"
# 测试基本功能(在目标设备上)
echo ""
echo "=== 功能测试(需要在目标设备上运行)==="
echo "测试显示目录树:"
echo " $TREE_BIN/tree -L 2"
echo ""
echo "测试显示目录(只显示目录):"
echo " $TREE_BIN/tree -d -L 2"
echo ""
echo "测试显示文件大小:"
echo " $TREE_BIN/tree -h -L 2"
echo ""
echo "测试排除目录:"
echo " $TREE_BIN/tree -I 'node_modules|.git' -L 2"
else
echo "✗ tree: 缺失"
fi
🐛 常见问题与处理
❌ 问题 1:strverscmp 函数未声明
- 🔍 症状 :编译警告
call to undeclared function 'strverscmp' - 🔎 原因 :
strverscmp函数在某些平台上可能未声明 - ✅ 解决方法 :
- 这是编译警告,不影响构建
- Tree 源码中包含了
strverscmp的实现 - 位置:编译阶段日志
❌ 问题 2:UTF-8 注释无效
- 🔍 症状 :编译警告
invalid UTF-8 in comment - 🔎 原因:源码中的注释包含无效的 UTF-8 字符
- ✅ 解决方法 :
- 这是编译警告,不影响构建
- 可以忽略或修复源码中的注释
- 位置:编译阶段日志(
strverscmp.c:4)
❌ 问题 3:静态链接失败
- 🔍 症状:链接错误,无法创建静态链接的二进制
- 🔎 原因:缺少静态库或静态库不完整
- ✅ 解决方法 :
- 确保交叉工具链提供完整的静态库
- 检查
sysroot中是否有必要的静态库 - 如果静态链接失败,可以尝试移除
-static标志使用动态链接 - 位置:
build-hnp/tree/Makefile:7
❌ 问题 4:大文件支持问题
- 🔍 症状:无法正确处理大文件或深目录
- 🔎 原因:缺少大文件支持宏定义
- ✅ 解决方法 :
- 确保
CFLAGS中包含-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 - 这些宏定义确保正确处理大文件和深目录
- 位置:
build-hnp/tree/Makefile:7
- 确保
❌ 问题 5:GitHub Releases 不可达
- 🔍 症状:下载失败,无法获取源码包
- 🔎 原因:网络问题或 GitHub 访问受限
- ✅ 解决方法 :
- 手动下载源码包放置到
build-hnp/tree/download/2.2.1.tar.gz - 通用下载逻辑支持备用镜像与重试(
wget→curl) - 位置:
build-hnp/utils/Makefrag:61-69
- 手动下载源码包放置到
❌ 问题 6:架构不支持
- 🔍 症状 :
Unsupported OHOS_ARCH= - 🔎 原因:传入的架构不在支持列表中
- ✅ 解决方法 :
- 确保传入支持架构(
aarch64或x86_64) - 位置:
build-hnp/Makefile:1-40
- 确保传入支持架构(
❌ 问题 7:二进制体积过大
- 🔍 症状:静态链接的二进制体积较大(约 1.1MB)
- 🔎 原因:静态链接包含了所有依赖库
- ✅ 解决方法 :
- 这是静态链接的正常现象
- 如果需要减小体积,可以移除
-static标志使用动态链接 - 但需要确保目标设备有相应的动态库
- 位置:
build-hnp/tree/Makefile:7
🔄 重建与扩展
-
🔧 重建单包:
bashmake -C build-hnp rebuild-tree # 触发子包重新编译并刷新 .stamp -
🧹 清理:
bashmake -C build-hnp clean # 清理 sysroot、所有 .stamp 和 PKGS_MARKER -
📦 扩展:Tree 是目录结构可视化的基础工具
-
🔄 自动重建机制:
- 修改
PKGS后,check-pkgs会自动检测变化并触发重新构建 - 新增外部 HNP 包到
external-hnp目录后,会自动合并到base.hnp
- 修改
💡 实践建议
- 🔧 构建配置:使用静态链接确保在目标设备上无需额外依赖即可运行
- 🚀 功能使用:根据需求选择合适的显示选项和过滤条件
- 📦 输出格式:使用 HTML 或 XML 格式生成文档
- 🔗 过滤选项 :使用
-I排除不需要的目录,使用-P只显示特定文件类型 - 🌐 深度控制 :使用
-L限制显示深度,避免输出过长
📝 结论与建议
- ✅ 本次已在 aarch64 环境下完成 Tree 2.2.1 的交叉编译与打包,tree 工具已安装到
sysroot并纳入 HNP 包。 - 💡 为保证构建稳定 :
- 使用静态链接确保在目标设备上无需额外依赖即可运行
- 启用大文件支持宏定义以正确处理大文件和深目录
- 编译警告不影响构建,可以忽略
- 确保通过
create-hnp.sh触发构建以获得完整环境变量 - 利用
check-pkgs机制自动检测包列表变化,无需手动清理 - Tree 为目录结构可视化提供了强大的工具支持
- 常见陷阱包括静态链接失败、大文件支持缺失、编译警告;当前已通过编译选项和宏定义处理
- 构建参数简洁且针对设备环境做出静态链接设计,保证可运行性
- 产物开箱即用,可用于设备上目录结构快速查看与调试定位
📚 以上为 Tree 构建的深度解读与实践记录。