exa 在 HarmonyOS 上的构建与适配

目录


项目简介

exa 是一个现代化的 ls 命令替代品,使用 Rust 语言编写,提供了更丰富的功能和更好的默认设置。本文将详细介绍如何将 exa 适配到 HarmonyOS 平台,包括交叉编译配置、构建脚本编写以及使用说明。

仓库地址: git@gitcode.com:nutpi/exa.git

版本: v0.10.1

Tag: v0.10.1-harmonyos


exa 是什么

exa 是一个命令行工具,用于列出目录内容,是传统 Unix/Linux ls 命令的现代化替代品。它使用颜色来区分文件类型和元数据,支持符号链接、扩展属性和 Git 集成。

主要优势

  • 彩色显示:自动使用颜色区分文件类型
  • Git 集成:显示 Git 仓库中文件的修改状态
  • 树形视图:支持递归显示目录树结构
  • 图标支持:可选的文件类型图标
  • 高性能:Rust 编写,单二进制文件,运行速度快
  • 更好的默认设置 :相比 ls 提供更友好的默认行为

exa 的主要特性

1. 多种显示模式

  • 网格视图(默认):以网格形式显示文件
  • 长列表视图-l):显示详细信息,包括权限、大小、时间等
  • 树形视图-T):递归显示目录树
  • 单行视图-1):每行显示一个文件

2. 智能排序和过滤

  • 按名称、大小、修改时间等排序
  • 支持目录优先显示
  • Git 忽略文件过滤
  • 支持 glob 模式过滤

3. Git 集成

  • 显示 Git 仓库中文件的修改状态
  • 支持 Git 忽略文件过滤
  • 在长列表中显示 Git 状态

4. 丰富的元数据

  • 文件权限(支持八进制格式)
  • 文件大小(支持二进制和十进制前缀)
  • 时间戳(修改、访问、创建时间)
  • 扩展属性
  • 硬链接数
  • inode 号

exa 的使用方法

基本用法

bash 复制代码
# 列出当前目录(网格视图)
exa

# 长列表视图
exa -l

# 显示所有文件(包括隐藏文件)
exa -a

# 树形视图
exa -T

# 递归显示目录
exa -R

常用选项

显示选项
bash 复制代码
# 单行显示
exa -1

# 网格视图(默认)
exa -G

# 长列表视图
exa -l

# 树形视图
exa -T

# 显示文件类型指示符
exa -F

# 显示图标
exa --icons
排序和过滤
bash 复制代码
# 按大小排序
exa -l --sort=size

# 按修改时间排序
exa -l --sort=modified

# 反向排序
exa -l --sort=size --reverse

# 目录优先
exa --group-directories-first

# 只显示目录
exa -D
Git 集成
bash 复制代码
# 显示 Git 状态
exa -l --git

# 忽略 Git 忽略的文件
exa --git-ignore
长列表选项
bash 复制代码
# 显示文件组
exa -l -g

# 显示硬链接数
exa -l -H

# 显示 inode
exa -l -i

# 显示扩展属性
exa -l -@

# 二进制大小前缀
exa -l -b

# 字节大小
exa -l -B

实际使用示例

bash 复制代码
# 查看当前目录的详细信息,按大小排序
exa -l --sort=size

# 查看 Git 仓库的文件状态
exa -l --git

# 递归显示目录树,深度为 2
exa -T --level=2

# 显示所有文件(包括隐藏文件),目录优先
exa -a --group-directories-first

# 长列表视图,显示图标
exa -l --icons

# 查看特定目录
exa -l /path/to/directory

HarmonyOS 适配过程

项目特点

exa 是一个 Rust 项目,使用 Cargo 作为构建系统。与之前适配的 C/C++ 项目(如 unzip、whois)不同,Rust 项目的交叉编译需要特殊的配置。

适配挑战

  1. 构建系统差异:从 Makefile 转向 Cargo
  2. 交叉编译配置:需要配置 Rust 工具链和目标平台
  3. 链接器配置:需要正确配置 HarmonyOS SDK 的链接器
  4. 依赖管理:Rust 的依赖管理需要特殊处理

环境准备

1. 系统要求

  • macOS(本文示例)或 Linux
  • Rust 工具链(rustc 和 cargo)
  • HarmonyOS SDK
  • Python 3(用于构建脚本)

2. 安装 Rust 工具链

bash 复制代码
# 检查 Rust 版本
rustc --version
cargo --version

# 如果未安装,使用 rustup 安装
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

3. 安装交叉编译目标

bash 复制代码
# 添加 aarch64-unknown-linux-musl 目标
rustup target add aarch64-unknown-linux-musl

注意 :HarmonyOS 使用 musl libc,因此选择 aarch64-unknown-linux-musl 作为目标平台。

4. 环境变量设置

构建脚本会自动设置以下环境变量:

bash 复制代码
export CC=${COMPILER_TOOLCHAIN}clang
export CXX=${COMPILER_TOOLCHAIN}clang++
export AR=${COMPILER_TOOLCHAIN}llvm-ar
export RANLIB=${COMPILER_TOOLCHAIN}llvm-ranlib
export STRIP=${COMPILER_TOOLCHAIN}llvm-strip

构建脚本详解

build_ohos.sh 完整代码

bash 复制代码
export TREE_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/exa.org/exa_0.10.1

# 创建安装目录
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/bin
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1
mkdir -p ${TREE_INSTALL_HNP_PATH}/usr/share/man/man5

# 设置 Rust 交叉编译目标
# HarmonyOS 使用 musl libc,目标架构是 aarch64
export CARGO_TARGET_DIR=${PWD}/target
export TARGET=aarch64-unknown-linux-musl

# 配置 cargo 使用 HarmonyOS 工具链
export CC_aarch64_unknown_linux_musl=${CC}
export CXX_aarch64_unknown_linux_musl=${CXX}
export AR_aarch64_unknown_linux_musl=${AR}
export RANLIB_aarch64_unknown_linux_musl=${RANLIB}
export STRIP_aarch64_unknown_linux_musl=${STRIP}

# 设置链接器
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=${CC}

# 清理之前的构建
echo "Cleaning previous build..."
cargo clean 2>/dev/null || true

# 构建 release 版本
echo "Building exa with cargo..."
cargo build --release --target ${TARGET} --verbose || {
    echo "Error: Cargo build failed"
    exit 1
}

# 检查构建产物
BINARY_PATH=${CARGO_TARGET_DIR}/${TARGET}/release/exa
if [ ! -f "${BINARY_PATH}" ]; then
    echo "Error: Binary not found at ${BINARY_PATH}"
    exit 1
fi

# 安装二进制文件
echo "Installing exa binary..."
cp ${BINARY_PATH} ${TREE_INSTALL_HNP_PATH}/usr/bin/exa || {
    echo "Error: Failed to copy binary"
    exit 1
}

# 设置可执行权限
chmod +x ${TREE_INSTALL_HNP_PATH}/usr/bin/exa

# 构建并安装 man pages(如果 pandoc 可用)
if command -v pandoc &> /dev/null; then
    echo "Building man pages..."
    pandoc --standalone -f markdown -t man man/exa.1.md > ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1/exa.1 2>/dev/null || true
    pandoc --standalone -f markdown -t man man/exa_colors.5.md > ${TREE_INSTALL_HNP_PATH}/usr/share/man/man5/exa_colors.5 2>/dev/null || true
fi

# 复制 hnp.json
cp hnp.json ${TREE_INSTALL_HNP_PATH}/ || {
    echo "Error: Failed to copy hnp.json"
    exit 1
}

# 打包
echo "Packaging..."
pushd ${TREE_INSTALL_HNP_PATH}/../
    ${HNP_TOOL} pack -i ${TREE_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/ || {
        echo "Error: HNP pack failed"
        popd
        exit 1
    }
    tar -zvcf ${ARCHIVE_PATH}/ohos_exa_0.10.1.tar.gz exa_0.10.1/ || {
        echo "Error: Tar packaging failed"
        popd
        exit 1
    }
popd

# 打印构建结果
echo ""
echo "=========================================="
echo "Build completed successfully!"
echo "=========================================="
echo "HNP Package: ${ARCHIVE_PATH}/exa.org_exa_0.10.1.hnp"
echo "Tar Archive: ${ARCHIVE_PATH}/ohos_exa_0.10.1.tar.gz"
echo "Installation Path: ${TREE_INSTALL_HNP_PATH}"
echo "=========================================="
echo ""

脚本关键点解析

1. 目标平台设置
bash 复制代码
export TARGET=aarch64-unknown-linux-musl

选择 aarch64-unknown-linux-musl 是因为:

  • HarmonyOS 使用 musl libc 而不是 glibc
  • 目标架构是 aarch64(ARM64)
  • Rust 标准库支持此目标平台
2. 工具链配置
bash 复制代码
export CC_aarch64_unknown_linux_musl=${CC}
export CXX_aarch64_unknown_linux_musl=${CXX}
export AR_aarch64_unknown_linux_musl=${AR}

Cargo 使用特定格式的环境变量来配置交叉编译工具链:

  • CC_<target>:C 编译器
  • CXX_<target>:C++ 编译器
  • AR_<target>:归档工具
  • RANLIB_<target>:归档索引工具
  • STRIP_<target>:符号剥离工具
3. 链接器配置
bash 复制代码
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=${CC}

设置链接器为 HarmonyOS SDK 的 clang,它会自动调用正确的链接器。

4. Cargo 构建
bash 复制代码
cargo build --release --target ${TARGET} --verbose
  • --release:构建优化版本
  • --target:指定目标平台
  • --verbose:显示详细构建信息

关键问题解决

1. Cargo 配置文件

为了正确配置链接器参数,我们创建了 .cargo/config.toml 文件:

toml 复制代码
[target.aarch64-unknown-linux-musl]
linker = "/var/folders/v9/zphc2yds1r568z2cy41mlrtc0000gn/T/linker-wrapper-XXXXXX.I4RDah500e"
rustflags = [
    "-C", "link-arg=--target=aarch64-linux-ohos",
    "-C", "link-arg=--sysroot=/Users/jianguo/Desktop/ohosdk/native/sysroot",
    "-C", "link-arg=-fuse-ld=lld",
    "-C", "link-arg=--ld-path=/Users/jianguo/Desktop/ohosdk/native/llvm/bin/ld.lld",
    # 禁用 --as-needed 选项(LLD 不支持)
    "-C", "link-arg=-Wl,--no-as-needed",
]

注意:这个配置文件中的路径是硬编码的,在实际使用中可能需要根据 SDK 路径调整。更好的做法是在构建脚本中动态生成此文件。

2. 链接器参数

HarmonyOS SDK 使用 LLD 链接器,需要传递特定的参数:

  • --target=aarch64-linux-ohos:指定目标平台
  • --sysroot:指定系统根目录
  • -fuse-ld=lld:使用 LLD 链接器
  • --ld-path:指定链接器路径
  • -Wl,--no-as-needed:禁用 --as-needed 选项(LLD 不支持)

3. Man Pages 构建

Man pages 是可选的,如果系统安装了 pandoc,会自动构建:

bash 复制代码
if command -v pandoc &> /dev/null; then
    pandoc --standalone -f markdown -t man man/exa.1.md > ${TREE_INSTALL_HNP_PATH}/usr/share/man/man1/exa.1
fi

HNP 包配置

hnp.json

json 复制代码
{
    "type":"hnp-config",
    "name":"exa",
    "version":"0.10.1",
    "install":{}
}

这是一个简单的 HNP 包配置,定义了包的基本信息。

安装目录结构

复制代码
exa_0.10.1/
├── usr/
│   ├── bin/
│   │   └── exa          # 可执行文件
│   └── share/
│       └── man/
│           ├── man1/
│           │   └── exa.1        # 用户手册(如果可用)
│           └── man5/
│               └── exa_colors.5 # 颜色配置手册(如果可用)
└── hnp.json              # HNP 包配置

构建结果

构建成功后,会生成以下文件:

  1. HNP 包exa.org_exa_0.10.1.hnp

    • HarmonyOS 原生包格式
    • 可以直接安装到 HarmonyOS 设备
  2. Tar 归档ohos_exa_0.10.1.tar.gz

    • 压缩的 tar 归档
    • 包含完整的安装目录结构

构建输出示例

复制代码
==========================================
Build completed successfully!
==========================================
HNP Package: /path/to/archive/exa.org_exa_0.10.1.hnp
Tar Archive: /path/to/archive/ohos_exa_0.10.1.tar.gz
Installation Path: /path/to/data/service/hnp/exa.org/exa_0.10.1
==========================================

使用示例

在 HarmonyOS 上使用 exa

安装 HNP 包后,可以在 HarmonyOS 设备上使用 exa:

bash 复制代码
# 基本使用
exa

# 长列表视图
exa -l

# 显示图标
exa --icons

# 树形视图
exa -T

# Git 集成
exa -l --git

# 按大小排序
exa -l --sort=size

# 递归显示,限制深度
exa -T --level=2

与 ls 的对比

bash 复制代码
# 传统 ls 命令
ls -lah

# exa 等效命令
exa -lah

# exa 的优势:自动颜色、更好的格式、Git 集成
exa -l --git --icons

总结

适配要点

  1. 构建系统转换:从 Makefile 转向 Cargo,需要理解 Rust 的构建系统
  2. 交叉编译配置:正确配置 Rust 工具链和目标平台
  3. 链接器配置 :通过 .cargo/config.toml 配置 HarmonyOS SDK 的链接器
  4. 环境变量:使用 Cargo 特定的环境变量格式配置工具链

优势

  • 单二进制文件:exa 编译后是单个可执行文件,部署简单
  • 高性能:Rust 编写,运行速度快
  • 功能丰富 :相比 ls 提供更多功能
  • 现代化:支持 Git、图标、颜色等现代特性

适用场景

  • 需要更好的文件列表显示体验
  • 需要 Git 集成功能
  • 需要树形视图显示目录结构
  • 需要更丰富的文件元数据展示

FAQ

Q1: 为什么选择 aarch64-unknown-linux-musl 作为目标平台?

A: HarmonyOS 使用 musl libc 而不是 glibc,因此选择 musl 变体。架构是 aarch64(ARM64),这是 HarmonyOS 的主要架构。

Q2: 如何更新 .cargo/config.toml 中的 SDK 路径?

A: 可以在构建脚本中动态生成此文件,或者使用相对路径。当前版本使用硬编码路径,需要根据实际情况调整。

Q3: 构建失败怎么办?

A: 检查以下几点:

  1. Rust 工具链是否正确安装
  2. 交叉编译目标是否已添加:rustup target add aarch64-unknown-linux-musl
  3. HarmonyOS SDK 路径是否正确
  4. 环境变量是否正确设置

Q4: Man pages 是必需的吗?

A: 不是必需的。Man pages 是可选的,只有在系统安装了 pandoc 时才会构建。即使没有 man pages,exa 也可以正常使用。

Q5: 可以在其他架构上构建吗?

A: 当前配置针对 aarch64 架构。如果需要支持其他架构(如 x86_64),需要修改目标平台和相应的工具链配置。

Q6: 如何验证构建的二进制文件?

A: 可以使用 file 命令检查二进制文件:

bash 复制代码
file target/aarch64-unknown-linux-musl/release/exa

应该显示类似:ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), ...


相关链接

相关推荐
子榆.1 小时前
Flutter 与开源鸿蒙(OpenHarmony)工程化实践:CI/CD、性能监控与多端发布
flutter·开源·harmonyos
Elasticsearch2 小时前
Kibana:使用 ES|QL 构建地图,对国家或地区的指标进行对比
elasticsearch
夏小鱼的blog2 小时前
【HarmonyOS应用开发入门】第三期:ArkTS语言基础(一)
harmonyos
Dxy12393102164 小时前
Elasticsearch如何做向量搜索
大数据·elasticsearch
cui_win4 小时前
Elasticsearch 分片满了?「cluster.max_shards_per_node」报错
大数据·elasticsearch·搜索引擎
子榆.4 小时前
Flutter 与开源鸿蒙(OpenHarmony)国际化与无障碍适配指南:打造真正包容的跨平台应用
flutter·华为·开源·harmonyos
C雨后彩虹5 小时前
斗地主之顺子
java·数据结构·算法·华为·面试
子榆.5 小时前
Flutter 与开源鸿蒙(OpenHarmony)深度集成:从原理到实战进阶
flutter·华为·开源·harmonyos
二流小码农5 小时前
鸿蒙开发:个人开发者如何使用华为账号登录
android·ios·harmonyos
m0_685535085 小时前
Zemax光学设计宏ZPL学习
华为·光学·光学设计·光学工程·镜头设计