本文記錄使用命令 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

✅ 產物驗證

📦 檢查打包文件

ls build-hnp/base.hnp  # 應存在
ls entry/hnp/arm64-v8a/*.hnp  # 應包含 base.hnp 與 base-public.hnp

🔍 檢查二進制文件

# 檢查 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. 基本目錄樹顯示
# 顯示當前目錄樹
tree

# 顯示指定目錄樹
tree /path/to/directory

# 顯示目錄樹(限制深度)
tree -L 2

# 顯示目錄樹(只顯示目錄)
tree -d

# 顯示目錄樹(顯示隱藏文件)
tree -a

# 顯示目錄樹(顯示文件大小)
tree -h

# 顯示目錄樹(顯示權限)
tree -p

# 顯示目錄樹(顯示修改時間)
tree -D

鴻蒙設備開發環境搭建過程中遇到的問題與解決方法_#開源鴻蒙

2. 過濾和排除
# 排除特定目錄
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'

鴻蒙設備開發環境搭建過程中遇到的問題與解決方法_目錄樹_02

3. 輸出格式
# 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. 統計信息
# 顯示統計信息
tree -s

# 顯示文件大小(人類可讀)
tree -h -s

# 只顯示統計信息(不顯示樹)
tree --du -h

# 顯示目錄大小
tree -d -h -s

# 顯示文件數量
tree | tail -1

鴻蒙設備開發環境搭建過程中遇到的問題與解決方法_#OpenHarmony_03

5. 高級選項
# 顯示完整路徑
tree -f

# 顯示相對路徑
tree -f -L 2

# 顯示文件權限
tree -p

# 顯示文件所有者
tree -u

# 顯示文件組
tree -g

# 顯示文件修改時間
tree -D

# 顯示文件大小(字節)
tree -s

# 顯示文件大小(人類可讀)
tree -h

🌳 Tree 高級用法

6. 目錄深度控制
# 限制顯示深度為 2 層
tree -L 2

# 限制顯示深度為 3 層
tree -L 3

# 顯示完整深度
tree -L 999

# 只顯示當前目錄
tree -L 0

# 顯示兩層目錄
tree -L 2 -d
7. 文件類型過濾
# 只顯示目錄
tree -d

# 只顯示文件
tree -f -I '^$'

# 只顯示特定擴展名
tree -P '*.txt'

# 排除特定擴展名
tree -I '*.log'

# 只顯示 C 源文件
tree -P '*.c|*.h'

# 排除編譯產物
tree -I '*.o|*.a|*.so'
8. 輸出到文件
# 輸出到文件
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. 實際應用示例
# 查看項目目錄結構
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. 組合使用示例
# 查看項目結構(排除常見目錄,限制深度,顯示大小)
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 -

🧪 功能驗證腳本

#!/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

🔄 重建與擴展

  • 🔧 重建單包
make -C build-hnp rebuild-tree  # 觸發子包重新編譯並刷新 .stamp
  • 🧹 清理
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 為目錄結構可視化提供了強大的工具支持
  • 常見陷阱包括靜態鏈接失敗、大文件支持缺失、編譯警告;當前已通過編譯選項和宏定義處理
  • 構建參數簡潔且針對設備環境做出靜態鏈接設計,保證可運行性
  • 產物開箱即用,可用於設備上目錄結構快速查看與調試定位