欢迎加入 开源鸿蒙跨平台社区,与开发者一起共建鸿蒙三方库的开源生态。


一、背景与目标

Boost.Regexboostorg/regex)是 Boost 的 C++ 正则表达式库,为标准库 std::regex 的前身,功能更丰富。上游仓库自带 CMakeLists.txt,但仅定义 INTERFACE 目标,不编译 src/posix_api.cppsrc/wide_posix_api.cpp,因此无法直接得到静态库;且默认依赖 Boost 其它模块(config、throw_exception 等)。本适配在 OpenHarmony 三方库共建仓库(tpc_c_cplusplus) 中,使用 lycium 交叉编译框架 将 Boost.Regex 以 Standalone 模式BOOST_REGEX_STANDALONE,无其它 Boost 依赖)接入:通过 patch 或 CMakeLists.ohos.txt 覆盖 在上游 CMake 中增加静态库目标与 BUILD_TEST,在 prepare() 中生成 boost_regex_test.cpp(覆盖 regex_match、regex_search、regex_replace、捕获组等多条用例),并在设备上通过 HPKCHECK 执行 ./boost_regex_test 完成验证。

目标

  • 在 Mac/Linux 宿主机上交叉编译出适用于 OpenHarmony(armeabi-v7a / arm64-v8a)的 libboost_regex.a 与头文件(include/boost/);
  • 使用 Standalone 模式,不依赖 Boost 其它库;
  • 编写 正则测试套件(regex_match、regex_search、regex_replace、捕获组等),编出 boost_regex_test,设备上逐条输出 [PASS];
  • 设备上执行 ./boost_regex_test,输出 “All boost_regex tests passed.” 表示全部通过。

二、环境与框架简介

环境搭建更详细的步骤(SDK 下载、环境变量、依赖工具安装等)可参考:OpenHarmony 交叉编译环境配置。下文仅列出与本文直接相关的要点。

2.1 编译环境搭建

  • 宿主机:建议 Mac(Darwin)或 Linux;需安装 cmakemakewget(或 curl)、patch 等。
  • OHOS SDK:需包含 native/llvmnative/build-tools/cmakenative/build/cmake/ohos.toolchain.cmake;环境变量指向 SDK 根目录,例如:
    export OHOS_SDK=/path/to/OpenHarmony/Sdk/20
    
  • lycium:每个三方库由目录下的 HPKBUILD 定义“下载 → 解压 → prepare → 编译 → 安装”;产物落在 lycium/usr/<pkgname>/<ARCH>/;设备侧测试由 HPKCHECK 中的 openharmonycheck() 定义。

2.2 Boost.Regex 上游特点

  • 源码:使用 develop 分支,通过 https://codeload.github.com/boostorg/regex/zip/refs/heads/develop 下载,解压后目录名为 regex-develop;主要包含 include/boost/(头文件)、src/posix_api.cppsrc/wide_posix_api.cpp(需编成静态库)。
  • 构建:上游 CMakeLists.txt 仅 add_library(boost_regex INTERFACE),不编译 .cpp;提供 BOOST_REGEX_STANDALONE 选项,开启后不依赖 Boost 其它库。本适配通过 patch(两处:else 分支内增加静态库目标、文件末尾增加 BUILD_TEST 块)或失败时用 CMakeLists.ohos.txt 覆盖,编出 libboost_regex_sources.a(安装为 libboost_regex.a)与 boost_regex_test
  • APIboost::regexboost::regex_matchboost::regex_searchboost::regex_replaceboost::smatch 等,头文件 #include <boost/regex.hpp>
  • 依赖:Standalone 模式下无第三方依赖;不启用 ICU。
  • 测试:上游无现成测试可执行文件;本适配在 prepare() 中通过 heredoc 生成 boost_regex_test.cpp,覆盖 regex_match(含邮箱等)、regex_search(数字、单词)、regex_replace、捕获组等十多条用例。

2.3 HPKBUILD / HPKCHECK 在本库中的角色

  • HPKBUILD:定义 pkgname=boost_regex、pkgver=develop、source、builddir=regex-develop、buildtools=cmake;prepare() 中先对解压后的 CMakeLists.txt 做行尾规范化(sed 's/\r$//'),再尝试打 0001-standalone-build-static-lib.patch,失败则 cp CMakeLists.ohos.txt 覆盖;用 heredoc 生成 boost_regex_test.cpp(多条 regex 用例);build() 中 cmake 传入 -DBOOST_REGEX_STANDALONE=ON-DBUILD_TEST=ON 并 make;package() 中拷贝 libboost_regex.a、include/boost、boost_regex_test 到 usr/boost_regex/$ARCH/。
  • HPKCHECK:设备上进入 ${builddir}/${ARCH}-build,执行 ./boost_regex_test,将输出写入 logfile,以退出码作为测试结果。

三、接入步骤

3.1 创建三方库目录与文件

Workspace/tpc_c_cplusplus/thirdparty/ 下新建目录 boost_regex,并准备:

文件 作用
HPKBUILD 包名、版本、源码、prepare(行尾规范化 + patch/覆盖 + 生成测试)/build/package
HPKCHECK 设备上进入构建目录执行 ./boost_regex_test,以退出码为结果
CMakeLists.ohos.txt patch 失败时的完整 CMake 备用(上游逻辑 + standalone 静态库 + BUILD_TEST)
0001-standalone-build-static-lib.patch 两处改动:else 分支静态库、末尾 BUILD_TEST(标准 diff -u 格式)
README.OpenSource 开源协议(BSL-1.0)、上游地址、版本(JSON 格式)
README_zh.md 中文说明:简介、产物、编译、测试、API 用法等
.gitignore 忽略 regex-develop.zip、regex-develop/、.log、.rej 等

3.2 boost_regex 的 HPKBUILD 配置要点

boost_regex 取值 / 说明
pkgname boost_regex
pkgver develop
source https://codeload.github.com/boostorg/regex/zip/refs/heads/develop
builddir regex-develop
buildtools cmake
archs armeabi-v7a、arm64-v8a
depends
  • prepare():进入 builddir 后执行 sed 's/\r$//' CMakeLists.txt > CMakeLists.txt.lf && mv CMakeLists.txt.lf CMakeLists.txt 统一行尾;再 sed 's/\r$//' ... patch \| patch -p1 -N,若 patch 失败则 cp CMakeLists.ohos.txt ./CMakeLists.txt。随后用 heredoc 生成 boost_regex_test.cpp,内含 regex_match(1+$、\d+、简单邮箱)、regex_search(数字、\b\w+\b)、regex_replace(\d→X、world→boost)、捕获组 (\d+)-(\w+) 等用例,每条通过 CHECK 宏输出 [PASS]/[FAIL]。最后 mkdir -p $ARCH-build
  • build():在 builddir 中执行 cmake -DOHOS_ARCH=$ARCH -B$ARCH-build -S. -DBOOST_REGEX_STANDALONE=ON -DBUILD_TEST=ON -DBUILD_SHARED_LIBS=OFF,再 $MAKE -C $ARCH-build;编译结束后检查 $ARCH-build/boost_regex_test 是否存在,不存在则报错。
  • package():拷贝 $ARCH-build/libboost_regex_sources.ausr/boost_regex/$ARCH/lib/libboost_regex.ainclude/boostusr/boost_regex/$ARCH/include/$ARCH-build/boost_regex_testusr/boost_regex/$ARCH/bin/

prepare() 核心片段(行尾规范化 + patch 或覆盖 + 生成测试):

prepare() {
    _pkgdir="$PWD"
    cd $builddir
    sed 's/\r$//' CMakeLists.txt > CMakeLists.txt.lf && mv CMakeLists.txt.lf CMakeLists.txt
    if ! (sed 's/\r$//' "${_pkgdir}/0001-standalone-build-static-lib.patch" | patch -p1 -N); then
        cp "${_pkgdir}/CMakeLists.ohos.txt" ./CMakeLists.txt
    fi
    cat > boost_regex_test.cpp << 'ENDTEST'
#include <boost/regex.hpp>
// ... CHECK 宏与多条 regex_match / regex_search / regex_replace / 捕获组用例 ...
ENDTEST
    mkdir -p $ARCH-build
    cd ${OLDPWD}
}

build() 核心片段

build() {
    cd $builddir
    PKG_CONFIG_LIBDIR="${pkgconfigpath}" ${OHOS_SDK}/native/build-tools/cmake/bin/cmake "$@" \
        -DOHOS_ARCH=$ARCH -B$ARCH-build -S. \
        -DBOOST_REGEX_STANDALONE=ON \
        -DBUILD_TEST=ON \
        -DBUILD_SHARED_LIBS=OFF \
        -L > $buildlog 2>&1
    $MAKE VERBOSE=1 -C $ARCH-build >> $buildlog 2>&1
    if [ ! -f $ARCH-build/boost_regex_test ]; then
        echo "ERROR: boost_regex_test not found after make. Check $buildlog"
        return 1
    fi
    cd $OLDPWD
    return 0
}

3.3 与上游 CMakeLists 的仅有两处差异

  1. else() 分支(BOOST_REGEX_STANDALONE):增加 4 行——add_library(boost_regex_sources STATIC src/posix_api.cpp src/wide_posix_api.cpp)、对 boost_regex_sources 的 target_compile_definitions(BOOST_REGEX_STANDALONE)、target_include_directoriestarget_link_libraries(boost_regex INTERFACE boost_regex_sources)
  2. 文件末尾:增加 option(BUILD_TEST ...)if(BUILD_TEST) 块,编出 boost_regex_test 并 enable_testing()add_test(...)

因此既可维护小 patch(与上游一致时自动打上),又保留 CMakeLists.ohos.txt 作为下载源行尾/空白不一致时的备用。

3.4 HPKCHECK 设备侧测试逻辑

设备上进入 ${builddir}/${ARCH}-build(即 regex-develop/armeabi-v7a-buildregex-develop/arm64-v8a-build):

  • 若存在 boost_regex_test,则执行 ./boost_regex_test,标准输出与错误追加到 ${logfile},以可执行文件退出码作为测试结果(0 为通过);
  • 若不存在,则记录 “No boost_regex_test executable, skip test”,返回 1。

四、编译流程与命令

  1. 进入 lycium 目录

    cd /path/to/tpc_c_cplusplus/lycium
    
  2. 执行编译(仅编译 boost_regex):

    ./build.sh boost_regex
    
  3. 脚本将依次:检查 OHOS_SDK、下载/解压 regex-develop.zip、对每个 ARCH 执行 prepare(行尾规范化 → patch 或覆盖 → 生成 boost_regex_test.cpp)→ cmake → make → package,并写入 lycium/usr/hpk_build.csv

    image-20260212114718739

  4. 产物位置

    • 静态库与头文件:lycium/usr/boost_regex/armeabi-v7a/lycium/usr/boost_regex/arm64-v8a/(lib/libboost_regex.a、include/boost/)。
    • 测试可执行文件:lycium/usr/boost_regex/<ARCH>/bin/boost_regex_test,或构建目录内 thirdparty/boost_regex/regex-develop/<ARCH>-build/boost_regex_test

五、设备侧测试

将对应架构的 boost_regex_test(来自 usr/boost_regex/<ARCH>/bin/regex-develop/<ARCH>-build/)拷贝到设备后执行:

./boost_regex_test

通过时输出示例:

boost_regex tests:
  [PASS] regex_match ^[a-z]+$ "hello"
  [PASS] regex_match ^[a-z]+$ "Hello" (no match)
  [PASS] regex_match ^[a-z]+$ "" (no match)
  [PASS] regex_match ^[a-z]+$ "abc"
  [PASS] regex_match \d+ "123"
  [PASS] regex_match \d+ "12a" (no match)
  [PASS] regex_match email "a@b.co"
  [PASS] regex_match email "x@y.com"
  [PASS] regex_search \d+ in "abc123def"
  [PASS] regex_search first \d+ in "foo 42 bar 99"
  [PASS] regex_search \b\w+\b "one two three"
  [PASS] regex_replace \d -> X "a1b2c3"
  [PASS] regex_replace "world" -> "boost"
  [PASS] regex_match capture (\d+)-(\w+) "99-hello"
All boost_regex tests passed.

退出码 0 表示全部通过。HPKCHECK 在设备上执行同一命令,结果写入 .../boost_regex_<ARCH>_<SDK_VER>_test.log,便于排查。

image-20260212114754451


六、遇到的问题与解决方案

问题一:HPKBUILD 使用 CRLF 导致 source 报错或 syntax error

现象:执行 ./build.sh boost_regex 时出现 syntax error near unexpected token '{'(prepare() 附近)或 cleanbuild: command not found

原因:HPKBUILD 使用 Windows 换行符(CRLF),行尾 \r 导致 bash 解析异常,函数未正确定义。

解决:将 HPKBUILD、HPKCHECK 统一为 Unix 换行(LF),例如:

sed 's/\r$//' HPKBUILD > HPKBUILD.tmp && mv HPKBUILD.tmp HPKBUILD

或在仓库内通过 .gitattributes 指定 HPKBUILD text eol=lfHPKCHECK text eol=lf


问题二:patch 报 malformed patch 或 2 out of 2 hunks failed

现象:prepare() 中执行 patch 时出现 malformed patch at line 182 out of 2 hunks failed--saving rejects to CMakeLists.txt.rej

原因:① 手写 patch 的 hunk 头部(如 section 名、行号)与当前 patch 工具(如 Apple patch)不兼容;② 下载的 zip 中 CMakeLists.txt 与生成 patch 时的上下文不一致(行尾 CRLF、空行差异等)。

解决:① 在 prepare() 中先对 CMakeLists.txt 做行尾规范化sed 's/\r$//' CMakeLists.txt > CMakeLists.txt.lf && mv CMakeLists.txt.lf CMakeLists.txt,再打 patch,使与 GitHub raw 一致。② 使用 diff -u 生成的标准 patch,避免手写 section 名。③ patch 失败时自动回退if ! patch ...; then cp CMakeLists.ohos.txt ./CMakeLists.txt; fi,保证构建总能继续;CMakeLists.ohos.txt 保留完整适配内容作备用。


问题三:设备上只看到 “All boost_regex tests passed.” 看不到每条 [PASS]

现象:测试通过但希望看到每条用例的 [PASS] 输出。

原因:初版测试代码仅在全部通过时打印一句总结,未对每条用例单独 cout。

解决:在 boost_regex_test.cpp 中为每条用例增加输出,使用 CHECK 宏在通过时打印 [PASS] 用例描述,失败时打印 [FAIL];最后再打印 “All boost_regex tests passed.” 或 “Some tests failed.”。重新编译并推送新 boost_regex_test 到设备即可看到完整列表。


七、总结

  • Boost.Regex 在 OpenHarmony 上的交叉编译依赖 lycium 的 HPKBUILD/HPKCHECK 机制。上游 CMake 仅 INTERFACE 目标、不编 .cpp,本适配通过 patch(两处改动)CMakeLists.ohos.txt 覆盖BOOST_REGEX_STANDALONE=ON 下增加静态库与 BUILD_TEST,在宿主机完成构建,得到 libboost_regex.ainclude/boost/boost_regex_test
  • 测试策略:在 prepare() 中生成 boost_regex_test.cpp,覆盖 regex_match、regex_search、regex_replace、捕获组等多条用例,设备上执行 ./boost_regex_test 即可逐条看到 [PASS];HPKCHECK 以该可执行文件退出码与 logfile 记录结果。
  • 典型问题:HPKBUILD 的 CRLF 需统一为 LF;patch 前先规范化 CMakeLists.txt 行尾,失败则回退到 CMakeLists.ohos.txt;测试输出可增强为逐条 [PASS]/[FAIL] 便于查看。
  • 最终产物:lycium/usr/boost_regex/<ARCH>/ 下的静态库与头文件可供应用集成(链接 -lboost_regex,包含 <boost/regex.hpp>);boost_regex_test 用于设备端正则功能验证。

若你在使用 lycium 接入带 CMake 但仅 INTERFACE、需额外编出静态库与测试的 C++ 库时,可参考本文的“行尾规范化 + patch + 备用覆盖 + prepare 内生成测试”的方式。更多鸿蒙三方库共建内容,欢迎在 开源鸿蒙跨平台社区 交流。


参考与相关链接


  1. a-z ↩︎

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐