Tree 命令行工具鸿蒙化构建过程问题及解决方法

本文记录使用命令 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_ARCHOHOS_ABI
    • 导出 LC_CTYPETOOL_HOMEOHOS_SDK_HOME
    • 执行 make -C build-hnp
  • 📦 顶层构建build-hnp/Makefile
    • PKGS 变量定义需要构建的包列表(包含 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
  • 🔨 构建流程
    1. 下载源码包(支持多镜像回退)
    2. 解包并进入 temp/tree-2.2.1 目录
    3. 使用自定义 Makefile 直接编译(不使用 Autotools)
    4. 指定交叉编译器:CC=$(OHOS_SDK_HOME)/native/llvm/bin/$(OHOS_ARCH)-unknown-linux-ohos-clang
    5. 使用 make install 安装
    6. 复制到 ../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 目录
    • 下载规则支持多镜像回退:wgetcurl 兜底
  • 🔨 编译阶段
    • 使用交叉编译器直接编译
    • 编译警告: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
    • 通用下载逻辑支持备用镜像与重试(wgetcurl
    • 位置:build-hnp/utils/Makefrag:61-69

❌ 问题 6:架构不支持

  • 🔍 症状Unsupported OHOS_ARCH=
  • 🔎 原因:传入的架构不在支持列表中
  • ✅ 解决方法
    • 确保传入支持架构(aarch64x86_64
    • 位置:build-hnp/Makefile:1-40

❌ 问题 7:二进制体积过大

  • 🔍 症状:静态链接的二进制体积较大(约 1.1MB)
  • 🔎 原因:静态链接包含了所有依赖库
  • ✅ 解决方法
    • 这是静态链接的正常现象
    • 如果需要减小体积,可以移除 -static 标志使用动态链接
    • 但需要确保目标设备有相应的动态库
    • 位置:build-hnp/tree/Makefile:7

🔄 重建与扩展

  • 🔧 重建单包

    bash 复制代码
    make -C build-hnp rebuild-tree  # 触发子包重新编译并刷新 .stamp
  • 🧹 清理

    bash 复制代码
    make -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 构建的深度解读与实践记录。

相关推荐
坚果派·白晓明8 小时前
开源鸿蒙化构建GNU Tar 1.35:完整过程与验证
openharmony·开源鸿蒙·开源软件termony
坚果派·白晓明15 小时前
通过开源鸿蒙终端工具Termony完成Libarchive 命令行工具构建过程深度解读
openharmony·开源鸿蒙·开源软件termony
坚果派·白晓明16 小时前
通过开源鸿蒙终端工具Termony完成Zstd 命令行工具构建过程深度解读
openharmony·开源鸿蒙·开源软件termony
●VON1 天前
Electron 实战:纯图片尺寸调节工具(支持锁定纵横比)
前端·javascript·electron·开源鸿蒙
坚果派·白晓明2 天前
通过开源鸿蒙终端工具Termony完成Vim命令行工具构建过程深度解读
vim·openharmony·开源鸿蒙·开源软件termony
坚果派·白晓明2 天前
通过开源鸿蒙终端工具Termony完成Coremark 命令行工具构建过程深度解读
openharmony·命令行工具·开源鸿蒙·开源软件termony
坚果派·白晓明2 天前
通过开源鸿蒙终端工具Termony完成Ncurses 命令行工具构建过程深度解读
openharmony·开源鸿蒙·开源软件termony
A懿轩A2 天前
【2025版 OpenHarmony】GitCode 口袋工具 v1.0.1 更新发布:Flutter + HarmonyOS 封装导航栏进行跳转
flutter·harmonyos·openharmony·gitcode·开源鸿蒙
A懿轩A2 天前
【2025最新】Flutter 编译开发 鸿蒙HarmonyOS 6 项目教程(Windows)
windows·flutter·华为·openharmony·开源鸿蒙