当前位置: 首页 > news >正文

less 工具 OpenHarmony PC适配实践

less 工具 OpenHarmony PC适配实践

目录

  • 工具概述
  • 主要用途
  • 适配过程
  • 遇到的问题与解决方案
  • 构建脚本说明
  • 总结

工具概述

less 是一个功能强大的终端分页器(terminal pager),用于在终端中查看文本文件的内容。它是 more 命令的增强版本,提供了更丰富的功能和更好的用户体验。

主要特点

  • 双向滚动:支持向前和向后滚动查看文件内容
  • 搜索功能:支持向前和向后搜索文本
  • 标记功能:可以在文件中设置标记,快速跳转
  • 语法高亮:支持代码语法高亮显示
  • 多文件支持:可以同时打开多个文件
  • 终端兼容性:兼容各种终端类型和终端模拟器

效果

image-20251115130506193

版本信息

  • 项目名称:less
  • 版本:1.0.0
  • 许可证:GPL 或 Less License
  • 官方网站:https://www.greenwoodsoftware.com/less/

主要用途

1. 查看大型文件

less 特别适合查看大型日志文件或配置文件,因为它不会一次性加载整个文件到内存中,而是按需加载:

less /var/log/system.log
less /etc/config.conf

2. 查看命令输出

可以将命令的输出通过管道传递给 less

ps aux | less
history | less

3. 代码查看

支持语法高亮,适合查看源代码文件:

less source.c
less Makefile

4. 交互式浏览

提供了丰富的交互命令:

  • 空格键:向下翻页
  • b:向上翻页
  • /:向前搜索
  • ?:向后搜索
  • g:跳转到文件开头
  • G:跳转到文件结尾
  • q:退出

适配过程

1. 项目结构

less 使用传统的 autotools 构建系统(autoconf/automake),需要先运行 configure 脚本生成 Makefile

2. 构建系统分析

  • 构建工具:autotools (configure + make)
  • 编程语言:C
  • 依赖库:termcap/terminfo(终端控制库)
  • 特殊需求:需要终端库支持,但在交叉编译时无法运行测试程序

3. 适配步骤

步骤 1:配置构建脚本

创建 build_ohos.sh 脚本,设置 OpenHarmony 交叉编译环境:

#!/bin/bash
# less 工具 OpenHarmony 构建脚本export LESS_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/less.org/less_1.0.0
export PREFIX=${LESS_INSTALL_HNP_PATH}
mkdir -p ${LESS_INSTALL_HNP_PATH}
步骤 2:运行 configure

配置构建系统,指定目标平台:

sh configure \--prefix=${PREFIX} \--host=aarch64-linux-gnu \CC="${CC}" \CFLAGS="${CFLAGS}" \LDFLAGS="${LDFLAGS}" \TERMLIBS="-ltermcap"
步骤 3:修复配置问题

由于交叉编译时 configure 无法运行测试程序,需要手动修复 defines.h 中的宏定义。

步骤 4:编译和安装
make VERBOSE=1
make install
步骤 5:打包 HNP

使用 HNP 工具打包应用:

${HNP_TOOL} pack -i ${LESS_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/
tar -zvcf ${ARCHIVE_PATH}/ohos_less_1.0.0.tar.gz less_1.0.0/

遇到的问题与解决方案

问题 1:FILE 类型未定义

错误信息

error: unknown type name 'FILE'

原因分析
defines.hHAVE_STDIO_H 被设置为 #undef,导致 stdio.h 没有被包含,FILE 类型未定义。

解决方案
build_ohos.sh 中添加自动修复逻辑:

sed -i.bak 's/^#undef HAVE_STDIO_H$/#define HAVE_STDIO_H 1/' defines.h

问题 2:PATTERN_TYPE 类型未定义

错误信息

error: unknown type name 'PATTERN_TYPE'

原因分析
less 支持多种正则表达式库(GNU regex、POSIX regex、PCRE 等),但 OpenHarmony SDK 中这些库都不可用。PATTERN_TYPE 类型定义在 pattern.h 中,依赖于正则表达式库的宏定义。

解决方案
启用 NO_REGEX 宏,使 PATTERN_TYPE 定义为 void *

sed -i.bak 's/^#undef NO_REGEX$/#define NO_REGEX 1/' defines.h

问题 3:sprintf 未声明警告

错误信息

warning: call to undeclared library function 'sprintf'

原因分析
HAVE_SNPRINTF 未定义,代码回退到使用 sprintf,但 sprintf 未声明。

解决方案
启用 HAVE_SNPRINTF,使用 snprintf 替代 sprintf

sed -i.bak 's/^#undef HAVE_SNPRINTF$/#define HAVE_SNPRINTF 1/' defines.h

问题 4:sgtty.h 文件未找到

错误信息

fatal error: 'sgtty.h' file not found

原因分析
screen.c 中的包含逻辑会尝试包含 sgtty.h(旧式终端控制头文件),但 OpenHarmony SDK 不支持这个文件。

解决方案
启用 POSIX termios.h 支持:

sed -i.bak 's/^#undef HAVE_TERMIOS_H$/#define HAVE_TERMIOS_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_TERMIOS_FUNCS$/#define HAVE_TERMIOS_FUNCS 1/' defines.h

问题 5:INT_MAX 未定义

错误信息

error: use of undeclared identifier 'INT_MAX'

原因分析
HAVE_LIMITS_H 未定义,limits.h 没有被包含。

解决方案
启用 HAVE_LIMITS_H

sed -i.bak 's/^#undef HAVE_LIMITS_H$/#define HAVE_LIMITS_H 1/' defines.h

问题 6:termcap 函数未声明

错误信息

warning: call to undeclared function 'tgetflag'
warning: call to undeclared function 'tgetnum'
warning: call to undeclared function 'tgetstr'

原因分析
OpenHarmony SDK 中没有 termcap.h 头文件,termcap 函数未声明。

解决方案
创建 termcap_stub.htermcap_stub.c 提供 termcap 函数的声明和 stub 实现:

termcap_stub.h

#ifndef TERMCAP_STUB_H
#define TERMCAP_STUB_H#include <stdio.h>extern int tgetflag(const char *id);
extern int tgetnum(const char *id);
extern char *tgetstr(const char *id, char **area);
extern char *tgoto(const char *cap, int col, int row);
extern int tgetent(char *bp, const char *name);
extern int tputs(const char *str, int affcnt, int (*putc)(int));#ifndef TGETENT_OK
#define TGETENT_OK 1
#endif#endif /* TERMCAP_STUB_H */

termcap_stub.c

#include "termcap_stub.h"
#include <stdlib.h>
#include <string.h>int tgetflag(const char *id) {(void)id;return 0;
}int tgetnum(const char *id) {(void)id;return -1;
}char *tgetstr(const char *id, char **area) {(void)id;(void)area;return NULL;
}char *tgoto(const char *cap, int col, int row) {static char buf[32];snprintf(buf, sizeof(buf), "\033[%d;%dH", row + 1, col + 1);return buf;
}int tgetent(char *bp, const char *name) {(void)bp;(void)name;return TGETENT_OK;
}int tputs(const char *str, int affcnt, int (*putc)(int)) {(void)affcnt;if (str != NULL && putc != NULL) {while (*str) {putc(*str++);}}return 0;
}

修改 screen.c,在找不到 termcap.h 时使用 stub:

#if HAVE_TERMCAP_H
#include <termcap.h>
#else
/* OpenHarmony doesn't have termcap.h, use stub */
#include "termcap_stub.h"
#endif

问题 7:termcap 函数链接错误

错误信息

ld.lld: error: undefined symbol: tgetstr
ld.lld: error: undefined symbol: tgetent

原因分析
termcap_stub.o 没有被添加到 Makefile 的 OBJ 变量中。

解决方案
build_ohos.sh 中添加逻辑,自动将 termcap_stub.o 添加到 Makefile:

if [ -f "./termcap_stub.c" ] && ! grep -q "termcap_stub" Makefile 2>/dev/null; thenecho "Adding termcap_stub.c to Makefile..."awk '/^OBJ = /{in_obj=1} in_obj && /xbuf\.\${O}/{sub(/$/, " termcap_stub.${O}"); in_obj=0} {print}' Makefile > Makefile.tmp && mv Makefile.tmp Makefile || \sed -i.bak '/^\t.*xbuf\.\${O}/s/$/ termcap_stub.${O}/' Makefile 2>/dev/null || \sed -i '' '/^\t.*xbuf\.\${O}/s/$/ termcap_stub.${O}/' Makefile 2>/dev/null || true
fi

问题 8:open/time/strerror 函数未声明

错误信息

warning: call to undeclared function 'open'
warning: call to undeclared function 'time'
error: static declaration of 'strerror' follows non-static declaration

原因分析
相应的头文件宏定义未启用。

解决方案
启用 HAVE_FCNTL_HHAVE_TIME_HHAVE_STRERROR

sed -i.bak 's/^#undef HAVE_FCNTL_H$/#define HAVE_FCNTL_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_TIME_H$/#define HAVE_TIME_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_STRERROR$/#define HAVE_STRERROR 1/' defines.h

问题 9:lsystem 函数未定义

错误信息

ld.lld: error: undefined symbol: lsystem

原因分析
lsystem 函数在 lsystem.c 中被 #if HAVE_SYSTEM 条件编译保护,但 HAVE_SYSTEM 未定义。

解决方案
启用 HAVE_SYSTEM

sed -i.bak 's/^#undef HAVE_SYSTEM$/#define HAVE_SYSTEM 1/' defines.h

问题 10:手册页文件缺失

错误信息

make: *** No rule to make target 'lesskey.nro', needed by 'install'. Stop.

原因分析
make install 需要 lesskey.nrolessecho.nro 手册页文件,但这些文件不存在。

解决方案
在安装前创建占位文件:

if [ ! -f "./lesskey.nro" ]; thencp lesskey.nro.VER lesskey.nro 2>/dev/null || touch lesskey.nro
fi
if [ ! -f "./lessecho.nro" ]; thencp lessecho.nro.VER lessecho.nro 2>/dev/null || touch lessecho.nro
fi

构建脚本说明

build_ohos.sh 关键部分

1. 环境设置
export LESS_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/less.org/less_1.0.0
export PREFIX=${LESS_INSTALL_HNP_PATH}
mkdir -p ${LESS_INSTALL_HNP_PATH}
2. Configure 配置
sh configure \--prefix=${PREFIX} \--host=aarch64-linux-gnu \CC="${CC}" \CFLAGS="${CFLAGS}" \LDFLAGS="${LDFLAGS}" \TERMLIBS="-ltermcap"
3. 自动修复 defines.h
# 修复关键宏定义
sed -i.bak 's/^#undef HAVE_STDIO_H$/#define HAVE_STDIO_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_SNPRINTF$/#define HAVE_SNPRINTF 1/' defines.h
sed -i.bak 's/^#undef NO_REGEX$/#define NO_REGEX 1/' defines.h
sed -i.bak 's/^#undef HAVE_TERMIOS_H$/#define HAVE_TERMIOS_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_TERMIOS_FUNCS$/#define HAVE_TERMIOS_FUNCS 1/' defines.h
sed -i.bak 's/^#undef HAVE_LIMITS_H$/#define HAVE_LIMITS_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_FCNTL_H$/#define HAVE_FCNTL_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_TIME_H$/#define HAVE_TIME_H 1/' defines.h
sed -i.bak 's/^#undef HAVE_STRERROR$/#define HAVE_STRERROR 1/' defines.h
sed -i.bak 's/^#undef HAVE_SYSTEM$/#define HAVE_SYSTEM 1/' defines.h
4. 添加 termcap_stub 到 Makefile
if [ -f "./termcap_stub.c" ] && ! grep -q "termcap_stub" Makefile 2>/dev/null; thenawk '/^OBJ = /{in_obj=1} in_obj && /xbuf\.\${O}/{sub(/$/, " termcap_stub.${O}"); in_obj=0} {print}' Makefile > Makefile.tmp && mv Makefile.tmp Makefile
fi
5. 创建手册页占位文件
if [ ! -f "./lesskey.nro" ]; thencp lesskey.nro.VER lesskey.nro 2>/dev/null || touch lesskey.nro
fi
if [ ! -f "./lessecho.nro" ]; thencp lessecho.nro.VER lessecho.nro 2>/dev/null || touch lessecho.nro
fi

关键修复总结

修复的宏定义

宏定义修复前修复后用途
HAVE_STDIO_H#undef#define HAVE_STDIO_H 1FILE 类型定义
HAVE_SNPRINTF#undef#define HAVE_SNPRINTF 1使用 snprintf
NO_REGEX#undef#define NO_REGEX 1PATTERN_TYPE 定义
HAVE_TERMIOS_H#undef#define HAVE_TERMIOS_H 1POSIX termios 支持
HAVE_TERMIOS_FUNCS#undef#define HAVE_TERMIOS_FUNCS 1termios 函数支持
HAVE_LIMITS_H#undef#define HAVE_LIMITS_H 1INT_MAX 定义
HAVE_FCNTL_H#undef#define HAVE_FCNTL_H 1open 函数声明
HAVE_TIME_H#undef#define HAVE_TIME_H 1time 函数声明
HAVE_STRERROR#undef#define HAVE_STRERROR 1使用系统 strerror
HAVE_SYSTEM#undef#define HAVE_SYSTEM 1lsystem 函数编译

创建的新文件

  1. termcap_stub.h - termcap 函数声明
  2. termcap_stub.c - termcap 函数 stub 实现

修改的文件

  1. screen.c - 添加 termcap_stub.h 包含逻辑
  2. build_ohos.sh - 添加自动修复和构建逻辑

使用示例

基本使用

# 查看文件
less filename.txt# 查看命令输出
ps aux | less# 搜索文本(在 less 中)
/pattern    # 向前搜索
?pattern    # 向后搜索
n           # 下一个匹配
N           # 上一个匹配

常用命令

命令功能
空格键向下翻页
b向上翻页
g跳转到文件开头
G跳转到文件结尾
/pattern向前搜索
?pattern向后搜索
q退出
h显示帮助

总结

适配难点

  1. 交叉编译限制configure 脚本无法运行测试程序,需要手动修复配置
  2. 依赖库缺失:OpenHarmony SDK 中没有 termcap 库,需要创建 stub 实现
  3. 头文件缺失:多个标准头文件的宏定义需要手动启用
  4. 条件编译:大量使用条件编译,需要正确设置宏定义

适配成果

  • ✅ 成功编译 lesslesskeylessecho 三个可执行文件
  • ✅ 创建了 termcap stub 实现,解决了终端控制库依赖问题
  • ✅ 修复了所有编译和链接错误
  • ✅ 实现了自动化构建脚本,支持一键构建

经验总结

  1. 交叉编译适配:对于使用 autotools 的项目,需要仔细检查 configure 生成的 defines.h,手动修复无法正确检测的宏定义
  2. 依赖库处理:对于缺失的系统库,可以创建 stub 实现,提供最小功能支持
  3. 自动化构建:使用脚本自动修复配置问题,提高构建效率
  4. 文档记录:详细记录遇到的问题和解决方案,便于后续维护

后续优化建议

  1. termcap 功能增强:可以改进 termcap_stub.c 的实现,提供更完整的终端控制功能
  2. 正则表达式支持:如果 OpenHarmony SDK 未来支持正则表达式库,可以启用相应的宏定义
  3. 测试验证:在实际的 OpenHarmony 设备上测试 less 的功能,确保所有特性正常工作

参考资料

  • less 官方网站
  • less 源代码
  • OpenHarmony Native 开发文档

参考资源

  • sd 官方仓库
  • Rust 交叉编译文档
  • HarmonyOS 原生应用开发文档
  • 项目代码仓
  • PC代码仓
  • PC社区
http://www.dtcms.com/a/613562.html

相关文章:

  • 人工智能之数据分析 numpy:第三章 Ndarray 对象和数组创建
  • Claude Code API Gateway 配置指南
  • 网站怎么做404 301深圳网站论坛建设
  • 网站后台m整套网站设计
  • claude code 食用指南
  • 专题1:双指针
  • 基于Vue的鲜花销售系统33n62(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
  • sdc 编写笔记
  • Rabbit MQ:概述
  • 建站之星管理中心注册海外公司
  • 【HarmonyOS】ArkWeb——从入门到入土
  • 微网站 微信网站优化服务是什么意思
  • VS Code 隐藏顶部标题栏中间的文字
  • 珠海网站哪家好如何给网站流量来源做标记通过在网址后边加问号?
  • Rust入门
  • Rust入门 之一
  • “伪”局域网
  • C语言编译软件Mac | 在Mac上选择最合适的C语言编译工具
  • 怎么样建设一个网上教学网站网页版微信二维码不能直接识别
  • Linux BPF 技术深度解析:从原理到实践
  • 高端网站报价wordpress如何添加背景音乐
  • C# 对多个任务进行符合管理
  • 在Eclipse IDE for Embedded C/C++ Developers软件中定义的宏,编译C源文件时编译器无法找到宏定义!
  • 从局域网到全网可用!PDFMathTranslate 翻译工具的进阶使用法
  • 深入理解 JavaScript 异步编程:从单线程到 Promise 的完整指南
  • 怎么自己做歌曲网站沈阳网站建设方案策划
  • 电脑卡顿因重复文件?AllDup无安装版快速查重+批量删除 文件管理混乱?AllDup多模式查重工具,Python开发者也能高效用
  • Dubbo Mock机制详解:服务降级与本地测试的利器
  • JDBC与事务的协同:ThreadLocal的巧妙运用
  • 底层视觉及图像增强-项目实践理论补充(十六-0-(13):HDR技术全链路解析:从原理到LED显示工程实践):从奥运大屏,到手机小屏,快来挖一挖里面都有什么