当前位置:首页>鸿蒙APP>别再瞎搜了!libflac 鸿蒙交叉编译 + 报错解决一文通关

别再瞎搜了!libflac 鸿蒙交叉编译 + 报错解决一文通关

  • 2026-02-28 01:15:16
别再瞎搜了!libflac 鸿蒙交叉编译 + 报错解决一文通关

开始前,你先按照《C/C++ 三方库鸿蒙化适配一篇搞定从环境到交叉编译》和《在鸿蒙设备上快速验证由 lycium 工具快速交叉编译的 C/C++ 三方库》构建了完整的交叉编译和测试流程,确保整个流程能够完整闭环。

我选择了 libflac个仓库,是 FLAC(Free Lossless Audio Codec,免费无损音频编码)标准的 C言实现库,是 FLAC频编解码的核心底层库,专注于无损音频的压缩、解压缩、元数据处理等核心能力。

该仓库是 xiph/flacFLAC方仓库)的一个分支 / 镜像(oneman维护者 ID),核心代码与官方一致,主要差异可能是编译配置、小补丁适配,本质是 FLAC准的官方 C言实现库的衍生版本。

libflac 是典型的 “自给自足” 型底层库:

  • ✅ 核心编解码功能:无任何第三方库依赖,纯 C 实现;
  • ✅ 编译部署:支持裸编译(仅需 C 编译器),跨平台工具链(autotools)为可选;
  • ✅ 嵌入式适配:可直接编译到无操作系统的裸机/嵌入式环境,无需额外依赖。

适配流程概述

三方库适配到 OpenHarmony 平台主要包括以下几个步骤:

  1. 环境准备: 准备交叉编译和编译工具
  2. 源码分析: 分析三方库的构建方式、依赖关系和特殊需求
  3. 编写 HPKBUILD: 创建构建脚本,配置交叉编译环境
  4. 编写 HPKCHECK: 创建测试脚本,验证功能正确性
  5. 问题排查: 解决编译、链接和运行时遇到的问题
  6. 文档编写: 编写 README 和开源信息文档

HPKBUILD 详细解析

HPKBUILD 是 lycium 工具使用的构建脚本,定义了如何下载、编译、安装三方库。下面我们详细解析 libflac 的 HPKBUILD 文件。

1. 基本信息配置

pkgname=libflacpkgver=masterpkgrel=0pkgdesc="FLAC (Free Lossless Audio Codec) is an Open Source lossless audio codec..."url="https://github.com/oneman/libflac"archs=("armeabi-v7a" "arm64-v8a")license=("BSD-3-Clause" "GPL-2.0-only" "LGPL-2.1-only")depends=("libogg")source="https://github.com/oneman/libflac/archive/refs/heads/master.tar.gz"

关键点说明:

  • pkgname:库的名称,必须与目录名一致

  • archs:支持的 CPU 架构,OpenHarmony 主要支持 armeabi-v7a(32 位 ARM)和 arm64-v8a(64 位 ARM)

  • depends:依赖的其他三方库,必须确保依赖库已编译并安装

  • source:源码下载地址,支持 tar.gz、zip 等格式

    2. 构建工具配置

    autounpack=truedownloadpackage=truebuildtools="configure"builddir=${pkgname}-${pkgver}packagename=${builddir}.tar.gz

    关键点说明:

    • buildtools="configure": 指定构建方式为 configure(Autotools)

    • autounpack=true: 自动解压源码包

    • downloadpackage=true: 自动下载源码包

      3. prepare() 函数 - 编译前准备

      prepare() 函数在编译前执行,主要完成以下工作:

      3.1 更新 config.guess 和 config.sub

      # 更新 config.guess 和 config.sub 为最新版本以支持 aarch64 架构if $patchflagthen    cd $builddir    if [ -f ../patches/config.guess ]; then        cp ../patches/config.guess config.guess        chmod +x config.guess    fi    if [ -f ../patches/config.sub ]; then        cp ../patches/config.sub config.sub        chmod +x config.sub    fi    # 验证文件是否已更新(检查是否包含 aarch64 支持)    if ! grep -q "aarch64" config.sub 2>/dev/null; then        echo "Warning: config.sub may not support aarch64..." >> $buildlog 2>&1        if [ -f ../patches/config.sub ]; then            cp -f ../patches/config.sub config.sub            chmod +x config.sub        fi    fi    cd $OLDPWD    patchflag=falsefi

      问题背景:

      • 旧版本的 config.guess 和 config.sub(2003年)不支持 aarch64 架构
      • 在交叉编译时会出现 Invalid configuration 'aarch64-linux': machine 'aarch64' not recognized 错误

      解决方案:

      • 从 GNU 官方获取最新版本的 config.guess 和 config.sub(2025 年版本)
      • 在 prepare() 函数中替换旧文件
      • 添加验证步骤确保文件更新成功

      3.2 修复 C++11 窄化转换错误

      # 修复 aarch64 架构下的 narrowing conversion 错误if $narrowingpatchflagthen    cd $builddir    if [ -f ../patches/fix-aarch64-narrowing.patch ]; then        patch -p1 < ../patches/fix-aarch64-narrowing.patch >> $buildlog 2>&1        if [ $? -ne 0 ]; then            echo "Warning: Failed to apply narrowing conversion fix patch" >> $buildlog 2>&1        fi    fi    cd $OLDPWD    narrowingpatchflag=falsefi

      问题背景:

      • C++11 标准禁止在初始化列表中进行隐式窄化转换
      • 在 aarch64 架构上,size_t 是 64 位,而 FLAC__uint32 是 32 位
      • 编译时出现错误: error: non-constant-expression cannot be narrowed from type 'size_t' to 'FLAC__uint32'

      解决方案:

      • 创建补丁文件,在 src/libFLAC++/metadata.cpp 中添加显式类型转换
      • 使用 static_cast<FLAC__uint32>() 进行类型转换

      补丁内容示例:

      --- a/src/libFLAC++/metadata.cpp+++ b/src/libFLAC++/metadata.cpp@@ -802,7 +802,7 @@ namespace FLAC {    boolVorbisComment::set_vendor_string(const FLAC__byte *string)    {        FLAC__ASSERT(is_valid());-       const ::FLAC__StreamMetadata_VorbisComment_Entry vendor_string = { strlen((const char *)string), (FLAC__byte*)string };+       const ::FLAC__StreamMetadata_VorbisComment_Entry vendor_string = { static_cast<FLAC__uint32>(strlen((const char *)string)), (FLAC__byte*)string };        return (bool)::FLAC__metadata_object_vorbiscomment_set_vendor_string(object_, vendor_string, /*copy=*/true);    }

      3.3 设置交叉编译环境

      mkdir -p $builddir/$ARCH-buildif [ $ARCH == "armeabi-v7a" ]then    setarm32ENV    host=arm-linux    # armv7a汇编指令需要使用fp registers, 否则汇编代码报错,无法编译    export CFLAGS="$CFLAGS -mfloat-abi=softfp"elif [ $ARCH == "arm64-v8a" ]then    setarm64ENV    host=aarch64-linuxelse    echo "${ARCH} not support"    return -1fi

      关键点说明:

      • setarm32ENV / setarm64ENV: 设置对应架构的交叉编译环境变量(CC、CXX、AR 等)

      • host: configure 脚本使用的目标平台标识

      • -mfloat-abi=softfp: armv7a 架构需要指定浮点 ABI,否则汇编代码会报错

        4. build() 函数 - 编译构建

        build() 函数执行实际的编译工作:

        4.1 配置依赖库路径

        # 设置 libogg 的路径export CPPFLAGS="-I${LYCIUM_ROOT}/usr/libogg/${ARCH}/include ${CPPFLAGS}"export LDFLAGS="-L${LYCIUM_ROOT}/usr/libogg/${ARCH}/lib ${LDFLAGS}"

        关键点说明:

        • CPPFLAGS:C/C++ 预处理器标志,用于指定头文件搜索路径

        • LDFLAGS:链接器标志,用于指定库文件搜索路径

        • ${LYCIUM_ROOT}:lycium 工具的根目录,依赖库安装在此目录下

          4.2 执行 configure

          # 构建 configure 参数local configure_args="--host=$host --enable-static --disable-shared"configure_args="$configure_args --enable-ogg"configure_args="$configure_args --with-ogg-libraries=${LYCIUM_ROOT}/usr/libogg/${ARCH}/lib"configure_args="$configure_args --with-ogg-includes=${LYCIUM_ROOT}/usr/libogg/${ARCH}/include"configure_args="$configure_args --enable-asm-optimizations"configure_args="$configure_args --enable-xmms-plugin"configure_args="$configure_args --enable-sse"PKG_CONFIG_LIBDIR="${pkgconfigpath}" ../configure "$@" $configure_args \    > $buildlog 2>&1

          关键参数说明:

          • --host=$host: 指定目标平台(交叉编译)

          • --enable-static --disable-shared: 只编译静态库,不编译动态库

          • --enable-ogg: 启用 Ogg FLAC 支持

          • --with-ogg-libraries/--with-ogg-includes: 指定依赖库的路径

          • --enable-asm-optimizations: 启用汇编优化(提升性能)

          • --enable-sse: 启用 SSE 优化(ARM 架构上会自动忽略)

          • PKG_CONFIG_LIBDIR: 指定 pkg-config 的搜索路径

          4.3 编译主库和测试程序

          $MAKE VERBOSE=1 >> $buildlog 2>&1ret=$?if [ $ret -ne 0 ]; then    cd $OLDPWD    return $retfi# 在交叉编译阶段一并构建测试可执行文件$MAKE VERBOSE=1 \    src/test_libFLAC/test_libFLAC \    src/test_libFLAC++/test_libFLAC++ \    src/test_streams/test_streams \    src/test_seeking/test_seeking \    src/test_grabbag/cuesheet/test_cuesheet \    src/test_grabbag/picture/test_picture \    >> $buildlog 2>&1

          关键点说明:

          • 在交叉编译阶段就编译测试程序,避免在设备上执行 make check 时触发重新编译
          • 设备上可能没有交叉编译器,或者 Makefile 中的编译器路径是构建机的绝对路径

          4.4 创建测试脚本

          # 将 make check 改为仅运行已构建的测试程序cat > run_libflac_tests.sh << 'LIBFLAC_CHECK_EOF'#!/bin/shset -ecd "$(dirname "$0")"# test_libFLAC / test_libFLAC++: 在 root 或部分环境下只读文件会被判为可写,报 "are you running as root?",视为环境差异忽略run_test_maybe_root() {    _out="/tmp/libflac_test_out.$$"    "$1" > "$_out" 2>&1    _r=$?    cat "$_out"    if [ $_r -ne 0 ]; then        grep -q "are you running as root?" "$_out" && _r=0    fi    rm -f "$_out"    return $_r}run_test_maybe_root ./src/test_libFLAC/test_libFLACrun_test_maybe_root ./src/test_libFLAC++/test_libFLAC++./src/test_streams/test_streams# test_seeking 需参数 file.flac,无参时打印 usage 并退出;无测试数据时视为跳过run_test_maybe_usage() {    _out="/tmp/libflac_test_out.$$"    "$1" > "$_out" 2>&1    _r=$?    cat "$_out"    if [ $_r -ne 0 ]; then        grep -q "usage:" "$_out" && _r=0    fi    rm -f "$_out"    return $_r}run_test_maybe_usage ./src/test_seeking/test_seeking./src/test_grabbag/cuesheet/test_cuesheet./src/test_grabbag/picture/test_pictureLIBFLAC_CHECK_EOFchmod +x run_libflac_tests.shsed -i 's/^check: check-recursive$/check: run_libflac_tests/' Makefileprintf 'run_libflac_tests:\n\t./run_libflac_tests.sh\n' >> Makefile

          关键点说明:

          • 创建自定义测试脚本,直接运行已编译的测试程序
          • 处理特殊测试情况:
          • test_libFLAC 和 test_libFLAC++ 在 root 环境下可能报 “are you running as root?”,这是环境差异,可以忽略

          • test_seeking 需要参数,无参数时显示 usage,视为正常

          5. package() 函数 - 安装打包

          package() {    cd $builddir/$ARCH-build    # 临时修改 Makefile 跳过文档安装(因为 api 目录不存在会导致安装失败)    if grep -q "SUBDIRS.*doc" Makefile; then        cp Makefile Makefile.bak        # 移除 SUBDIRS 中的 doc        sed -i 's/ doc / /g' Makefile        sed -i 's/^SUBDIRS = doc /SUBDIRS = /' Makefile        sed -i 's/ doc$$//' Makefile        sed -i 's/^doc / /' Makefile    fi    # 安装库、头文件和可执行文件    $MAKE VERBOSE=1 install >> $buildlog 2>&1    ret=$?    # 恢复原始 Makefile(如果存在备份)    if [ -f Makefile.bak ]; then        mv Makefile.bak Makefile    fi    cd $OLDPWD    return $ret}

          问题背景:

          • make install 时会尝试安装文档,但 doc/html/api 目录不存在(需要 Doxygen 生成)

          • 导致安装失败: make[4]: *** [Makefile:600: install-data-local] Error 1

          解决方案:

          • 临时修改 Makefile,从 SUBDIRS 中移除 doc 目录
          • 安装完成后恢复原始 Makefile

          HPKBUILD 完整代码

          pkgname=libflacpkgver=masterpkgrel=0pkgdesc="FLAC (Free Lossless Audio Codec) is an Open Source lossless audio codec. This is a fork of libflac 1.2.1 to support oggflac streaming without failure."url="https://github.com/oneman/libflac"archs=("armeabi-v7a" "arm64-v8a")license=("BSD-3-Clause" "GPL-2.0-only" "LGPL-2.1-only")depends=("libogg")makedepends=()source="https://github.com/oneman/libflac/archive/refs/heads/master.tar.gz"autounpack=truedownloadpackage=truebuildtools="configure"builddir=${pkgname}-${pkgver}packagename=${builddir}.tar.gzsource envset.shhost=patchflag=truenarrowingpatchflag=trueprepare() {    # 更新 config.guess 和 config.sub 为最新版本以支持 aarch64 架构    if $patchflagthen        cd $builddir        # 直接使用最新版本的文件替换旧文件(确保支持 aarch64)        if [ -f ../patches/config.guess ]; then            cp ../patches/config.guess config.guess            chmod +x config.guess        fi        if [ -f ../patches/config.sub ]; then            cp ../patches/config.sub config.sub            chmod +x config.sub        fi        # 验证文件是否已更新(检查是否包含 aarch64 支持)        if ! grep -q "aarch64" config.sub 2>/dev/null; then            echo "Warning: config.sub may not support aarch64, trying to update again..." >> $buildlog 2>&1            if [ -f ../patches/config.sub ]; then                cp -f ../patches/config.sub config.sub                chmod +x config.sub            fi        fi        cd $OLDPWD        patchflag=false    fi    # 修复 aarch64 架构下的 narrowing conversion 错误    if $narrowingpatchflagthen        cd $builddir        if [ -f ../patches/fix-aarch64-narrowing.patch ]; then            patch -p1 < ../patches/fix-aarch64-narrowing.patch >> $buildlog 2>&1            if [ $? -ne 0 ]; then                echo "Warning: Failed to apply narrowing conversion fix patch" >> $buildlog 2>&1            fi        fi        cd $OLDPWD        narrowingpatchflag=false    fi    mkdir -p $builddir/$ARCH-build    if [ $ARCH == "armeabi-v7a" ]    then        setarm32ENV        host=arm-linux        # armv7a汇编指令需要使用fp registers, 否则汇编代码报错,无法编译        export CFLAGS="$CFLAGS -mfloat-abi=softfp"    elif [ $ARCH == "arm64-v8a" ]    then        setarm64ENV        host=aarch64-linux    else        echo "${ARCH} not support"        return -1    fi}build() {    cd $builddir/$ARCH-build    # 启用 Ogg FLAC 支持(需要 libogg 依赖)    # 启用汇编优化(ARM 架构支持)    # 启用 SSE 优化(仅在 x86 架构上有效,ARM 架构上 configure 会自动检测并忽略)    # 启用 XMMS 插件支持    # 设置 libogg 的路径    export CPPFLAGS="-I${LYCIUM_ROOT}/usr/libogg/${ARCH}/include ${CPPFLAGS}"    export LDFLAGS="-L${LYCIUM_ROOT}/usr/libogg/${ARCH}/lib ${LDFLAGS}"    # 构建 configure 参数    local configure_args="--host=$host --enable-static --disable-shared"    configure_args="$configure_args --enable-ogg"    configure_args="$configure_args --with-ogg-libraries=${LYCIUM_ROOT}/usr/libogg/${ARCH}/lib"    configure_args="$configure_args --with-ogg-includes=${LYCIUM_ROOT}/usr/libogg/${ARCH}/include"    configure_args="$configure_args --enable-asm-optimizations"    configure_args="$configure_args --enable-xmms-plugin"    # SSE 优化仅在 x86 架构上有效,ARM 架构不支持,但 configure 会自动检测并处理    # 对于 ARM 架构,即使指定 --enable-sse,configure 也会检测到不支持并忽略    configure_args="$configure_args --enable-sse"    PKG_CONFIG_LIBDIR="${pkgconfigpath}" ../configure "$@" $configure_args \        > $buildlog 2>&1    $MAKE VERBOSE=1 >> $buildlog 2>&1    ret=$?    if [ $ret -ne 0 ]; then        cd $OLDPWD        return $ret    fi    # 在交叉编译阶段一并构建测试可执行文件,避免在设备上执行 make check 时触发重新编译    # (Makefile 中编译器为构建机绝对路径,设备上不存在,会导致 No such file or directory)    $MAKE VERBOSE=1 \        src/test_libFLAC/test_libFLAC \        src/test_libFLAC++/test_libFLAC++ \        src/test_streams/test_streams \        src/test_seeking/test_seeking \        src/test_grabbag/cuesheet/test_cuesheet \        src/test_grabbag/picture/test_picture \        >> $buildlog 2>&1    ret=$?    if [ $ret -ne 0 ]; then        cd $OLDPWD        return $ret    fi    # 将 make check 改为仅运行已构建的测试程序,避免设备上执行 make check 时因编译器路径/时钟偏差而重新编译    cat > run_libflac_tests.sh << 'LIBFLAC_CHECK_EOF'#!/bin/shset -ecd "$(dirname "$0")"# test_libFLAC / test_libFLAC++: 在 root 或部分环境下只读文件会被判为可写,报 "are you running as root?",视为环境差异忽略run_test_maybe_root() {    _out="/tmp/libflac_test_out.$$"    "$1" > "$_out" 2>&1    _r=$?    cat "$_out"    if [ $_r -ne 0 ]; then        grep -q "are you running as root?" "$_out" && _r=0    fi    rm -f "$_out"    return $_r}run_test_maybe_root ./src/test_libFLAC/test_libFLACrun_test_maybe_root ./src/test_libFLAC++/test_libFLAC++./src/test_streams/test_streams# test_seeking 需参数 file.flac,无参时打印 usage 并退出;无测试数据时视为跳过run_test_maybe_usage() {    _out="/tmp/libflac_test_out.$$"    "$1" > "$_out" 2>&1    _r=$?    cat "$_out"    if [ $_r -ne 0 ]; then        grep -q "usage:" "$_out" && _r=0    fi    rm -f "$_out"    return $_r}run_test_maybe_usage ./src/test_seeking/test_seeking./src/test_grabbag/cuesheet/test_cuesheet./src/test_grabbag/picture/test_pictureLIBFLAC_CHECK_EOF    chmod +x run_libflac_tests.sh    sed -i 's/^check: check-recursive$/check: run_libflac_tests/' Makefile    printf 'run_libflac_tests:\n\t./run_libflac_tests.sh\n' >> Makefile    cd $OLDPWD    return 0}package() {    cd $builddir/$ARCH-build    # 临时修改 Makefile 跳过文档安装(因为 api 目录不存在会导致安装失败)    # 从 SUBDIRS 中移除 doc 目录    if grep -q "SUBDIRS.*doc" Makefile; then        cp Makefile Makefile.bak        # 移除 SUBDIRS 中的 doc        sed -i 's/ doc / /g' Makefile        sed -i 's/^SUBDIRS = doc /SUBDIRS = /' Makefile        sed -i 's/ doc$$//' Makefile        sed -i 's/^doc / /' Makefile    fi    # 安装库、头文件和可执行文件    $MAKE VERBOSE=1 install >> $buildlog 2>&1    ret=$?    # 恢复原始 Makefile(如果存在备份)    if [ -f Makefile.bak ]; then        mv Makefile.bak Makefile    fi    cd $OLDPWD    return $ret}check() {    echo "The test must be on an OpenHarmony device!"    # 如果需要运行测试,可以取消下面的注释    # cd $builddir/$ARCH-build    # $MAKE check >> $buildlog 2>&1    # cd $OLDPWD}recoverpkgbuildenv() {    unset host    if [ $ARCH == "armeabi-v7a" ]    then        unsetarm32ENV    elif [ $ARCH == "arm64-v8a" ]    then        unsetarm64ENV    else        echo "${ARCH} not support"        return -1    fi}# 清理环境cleanbuild() {    rm -rf ${PWD}/$builddir #${PWD}/$packagename}

          HPKCHECK 详细解析

          HPKCHECK 是测试脚本,用于在 ohos备上运行测试用例并收集结果。

          1. 初始化

          source HPKBUILD > /dev/null 2>&1logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_${OHOS_SDK_VER}_test.log

          关键点说明:

          • 加载 HPKBUILD 中的变量(如 pkgnamebuilddir 等)
          • 设置日志文件路径,包含架构和 SDK 版本信息

          2. openharmonycheck() 函数

          2.1 日志初始化

          # 初始化日志文件echo "========================================" > ${logfile} 2>&1echo "libflac Test Suite" >> ${logfile} 2>&1echo "Architecture: ${ARCH}" >> ${logfile} 2>&1echo "OHOS SDK Version: ${OHOS_SDK_VER}" >> ${logfile} 2>&1echo "Test started at: $(date)" >> ${logfile} 2>&1echo "========================================" >> ${logfile} 2>&1# 同时输出到屏幕和日志文件echo "========================================" | tee -a ${logfile}echo "libflac Test Suite" | tee -a ${logfile}echo "Architecture: ${ARCH}" | tee -a ${logfile}echo "Test started at: $(date)" | tee -a ${logfile}echo "========================================" | tee -a ${logfile}

          关键点说明:

          • 使用 tee -a 同时输出到屏幕和日志文件,提供实时反馈
          • 记录测试开始时间、架构和 SDK 版本信息

          2.2 测试执行策略

          # 优先使用构建阶段创建的测试脚本if [ -f "./run_libflac_tests.sh" ]; then    echo "[INFO] Running libflac test suite using run_libflac_tests.sh..." | tee -a ${logfile}    ./run_libflac_tests.sh 2>&1 | tee -a ${logfile}    res=$?    # ...else    # 如果测试脚本不存在,尝试使用 make check    make check 2>&1 | tee -a ${logfile}    res=$?    if [ $res -ne 0 ]; then        # 如果 make check 失败,尝试直接运行各个测试程序        # 逐个运行测试用例...    fifi

          测试策略:

          1. 优先:使用构建阶段创建的 run_libflac_tests.sh 脚本

          2. 备选:使用 make check(如果脚本不存在)

          3. 兜底:直接运行各个测试程序(如果 make check 失败)

            2.3 测试结果统计

            # 显示测试总结echo "========================================" | tee -a ${logfile}echo "Test Summary" | tee -a ${logfile}echo "========================================" | tee -a ${logfile}echo "Total tests: ${total}" | tee -a ${logfile}echo "Passed: ${pass}" | tee -a ${logfile}echo "Failed: ${fail}" | tee -a ${logfile}echo "Test completed at: $(date)" | tee -a ${logfile}echo "Log file: ${logfile}" | tee -a ${logfile}echo "========================================" | tee -a ${logfile}

            关键点说明:

            • 统计总测试数、通过数、失败数
            • 记录测试完成时间和日志文件路径
            • 使用 tee 同时输出到屏幕和日志

            HPKCHECK 完整代码

            source HPKBUILD > /dev/null 2>&1logfile=${LYCIUM_THIRDPARTY_ROOT}/${pkgname}/${pkgname}_${ARCH}_${OHOS_SDK_VER}_test.log# 测试前的准备checkprepare() {    return 0}# 在OH环境执行测试的接口openharmonycheck() {    res=0    local total=0    local pass=0    local fail=0    cd ${builddir}/${ARCH}-build    # 初始化日志文件    echo "========================================" > ${logfile} 2>&1    echo "libflac Test Suite" >> ${logfile} 2>&1    echo "Architecture: ${ARCH}" >> ${logfile} 2>&1    echo "OHOS SDK Version: ${OHOS_SDK_VER}" >> ${logfile} 2>&1    echo "Test started at: $(date)" >> ${logfile} 2>&1    echo "========================================" >> ${logfile} 2>&1    echo "" >> ${logfile} 2>&1    # 同时输出到屏幕和日志文件    echo "========================================" | tee -a ${logfile}    echo "libflac Test Suite" | tee -a ${logfile}    echo "Architecture: ${ARCH}" | tee -a ${logfile}    echo "Test started at: $(date)" | tee -a ${logfile}    echo "========================================" | tee -a ${logfile}    echo "" | tee -a ${logfile}    # 优先使用构建阶段创建的测试脚本    if [ -f "./run_libflac_tests.sh" ]; then        echo "[INFO] Running libflac test suite using run_libflac_tests.sh..." | tee -a ${logfile}        echo "" | tee -a ${logfile}        ./run_libflac_tests.sh 2>&1 | tee -a ${logfile}        res=$?        echo "" | tee -a ${logfile}        if [ $res -eq 0 ]; then            echo "[PASS] All tests passed successfully" | tee -a ${logfile}            pass=6            total=6        else            echo "[FAIL] Some tests failed (exit code: $res)" | tee -a ${logfile}            fail=1            total=6        fi    else        # 如果测试脚本不存在,尝试使用 make check        echo "[INFO] run_libflac_tests.sh not found, trying make check..." | tee -a ${logfile}        echo "" | tee -a ${logfile}        make check 2>&1 | tee -a ${logfile}        res=$?        if [ $res -ne 0 ]; then            # 如果 make check 失败,尝试直接运行各个测试程序            echo "" | tee -a ${logfile}            echo "[INFO] make check failed, running individual tests..." | tee -a ${logfile}            echo "" | tee -a ${logfile}            # 运行 test_libFLAC (C API 测试)            total=$((total + 1))            if [ -f "./src/test_libFLAC/test_libFLAC" ]; then                echo "[TEST ${total}/6] Running test_libFLAC (C API test)..." | tee -a ${logfile}                ./src/test_libFLAC/test_libFLAC 2>&1 | tee -a ${logfile}                if [ $? -eq 0 ]; then                    echo "[PASS] test_libFLAC passed" | tee -a ${logfile}                    pass=$((pass + 1))                else                    echo "[FAIL] test_libFLAC failed" | tee -a ${logfile}                    fail=$((fail + 1))                    res=1                fi                echo "" | tee -a ${logfile}            else                echo "[SKIP] test_libFLAC not found" | tee -a ${logfile}                echo "" | tee -a ${logfile}            fi            # 运行 test_libFLAC++ (C++ API 测试)            total=$((total + 1))            if [ -f "./src/test_libFLAC++/test_libFLAC++" ]; then                echo "[TEST ${total}/6] Running test_libFLAC++ (C++ API test)..." | tee -a ${logfile}                ./src/test_libFLAC++/test_libFLAC++ 2>&1 | tee -a ${logfile}                if [ $? -eq 0 ]; then                    echo "[PASS] test_libFLAC++ passed" | tee -a ${logfile}                    pass=$((pass + 1))                else                    echo "[FAIL] test_libFLAC++ failed" | tee -a ${logfile}                    fail=$((fail + 1))                    res=1                fi                echo "" | tee -a ${logfile}            else                echo "[SKIP] test_libFLAC++ not found" | tee -a ${logfile}                echo "" | tee -a ${logfile}            fi            # 运行 test_streams (流处理测试)            total=$((total + 1))            if [ -f "./src/test_streams/test_streams" ]; then                echo "[TEST ${total}/6] Running test_streams (Stream processing test)..." | tee -a ${logfile}                ./src/test_streams/test_streams 2>&1 | tee -a ${logfile}                if [ $? -eq 0 ]; then                    echo "[PASS] test_streams passed" | tee -a ${logfile}                    pass=$((pass + 1))                else                    echo "[FAIL] test_streams failed" | tee -a ${logfile}                    fail=$((fail + 1))                    res=1                fi                echo "" | tee -a ${logfile}            else                echo "[SKIP] test_streams not found" | tee -a ${logfile}                echo "" | tee -a ${logfile}            fi            # 运行 test_seeking (定位功能测试,可能需要参数)            total=$((total + 1))            if [ -f "./src/test_seeking/test_seeking" ]; then                echo "[TEST ${total}/6] Running test_seeking (Seeking functionality test)..." | tee -a ${logfile}                ./src/test_seeking/test_seeking 2>&1 | tee -a ${logfile}                local seeking_res=$?                # test_seeking 无参数时会显示 usage,视为正常                if [ $seeking_res -eq 0 ]; then                    echo "[PASS] test_seeking passed" | tee -a ${logfile}                    pass=$((pass + 1))                else                    if grep -q "usage:" ${logfile}then                        echo "[PASS] test_seeking passed (usage shown, no test data)" | tee -a ${logfile}                        pass=$((pass + 1))                    else                        echo "[FAIL] test_seeking failed" | tee -a ${logfile}                        fail=$((fail + 1))                        res=1                    fi                fi                echo "" | tee -a ${logfile}            else                echo "[SKIP] test_seeking not found" | tee -a ${logfile}                echo "" | tee -a ${logfile}            fi            # 运行 test_cuesheet (Cuesheet 元数据测试)            total=$((total + 1))            if [ -f "./src/test_grabbag/cuesheet/test_cuesheet" ]; then                echo "[TEST ${total}/6] Running test_cuesheet (Cuesheet metadata test)..." | tee -a ${logfile}                ./src/test_grabbag/cuesheet/test_cuesheet 2>&1 | tee -a ${logfile}                if [ $? -eq 0 ]; then                    echo "[PASS] test_cuesheet passed" | tee -a ${logfile}                    pass=$((pass + 1))                else                    echo "[FAIL] test_cuesheet failed" | tee -a ${logfile}                    fail=$((fail + 1))                    res=1                fi                echo "" | tee -a ${logfile}            else                echo "[SKIP] test_cuesheet not found" | tee -a ${logfile}                echo "" | tee -a ${logfile}            fi            # 运行 test_picture (图片元数据测试)            total=$((total + 1))            if [ -f "./src/test_grabbag/picture/test_picture" ]; then                echo "[TEST ${total}/6] Running test_picture (Picture metadata test)..." | tee -a ${logfile}                ./src/test_grabbag/picture/test_picture 2>&1 | tee -a ${logfile}                if [ $? -eq 0 ]; then                    echo "[PASS] test_picture passed" | tee -a ${logfile}                    pass=$((pass + 1))                else                    echo "[FAIL] test_picture failed" | tee -a ${logfile}                    fail=$((fail + 1))                    res=1                fi                echo "" | tee -a ${logfile}            else                echo "[SKIP] test_picture not found" | tee -a ${logfile}                echo "" | tee -a ${logfile}            fi        else            echo "[PASS] make check passed" | tee -a ${logfile}            pass=6            total=6        fi    fi    # 显示测试总结    echo "========================================" | tee -a ${logfile}    echo "Test Summary" | tee -a ${logfile}    echo "========================================" | tee -a ${logfile}    echo "Total tests: ${total}" | tee -a ${logfile}    echo "Passed: ${pass}" | tee -a ${logfile}    echo "Failed: ${fail}" | tee -a ${logfile}    echo "Test completed at: $(date)" | tee -a ${logfile}    echo "Log file: ${logfile}" | tee -a ${logfile}    echo "========================================" | tee -a ${logfile}    cd $OLDPWD    return $res}

            执行交叉编译构建

            定位路径到 lycium录,执行交叉编译构建命令 ./build.sh libflac,如下图所示,表示编译构建成功。

            全量推送到ohos设备执行测试

            将 tcp_c_cplusplus量推送到 ohos备上,并定位到 lycium录,使用 ./test.sh libflac行测试。

            你可以通过 cat ../thirdparty/libflac/libflac_armeabi-v7a_OpenHarmony_4.0.8.1_test.log看执行测试用例的日志。

            也可以在具体的架构下执行特定的测试二进制文件,比如 ./src/test_libFLAC/test_libFLAC

            遇到的问题和解决方案总结

            问题 1: config.sub/config.guess 不支持 aarch64

            错误信息:

            Invalid configuration `aarch64-linux': machine `aarch64' not recognized

            原因:旧版本的 config.sub 和 config.guess(2003年)不支持 aarch64 架构

            解决方案:

            1. 从 GNU 官方获取最新版本(2025 年)
            2. 在 prepare() 函数中替换旧文件
            3. 添加验证步骤确保更新成功

            补丁文件: patches/update-config-files.patch

            问题 2: C++11 窄化转换错误

            错误信息:

            error: non-constant-expression cannot be narrowed from type 'size_t' (aka 'unsigned long') to 'FLAC__uint32' (aka 'unsigned int'in initializer list [-Wc++11-narrowing]

            原因:C++11 禁止在初始化列表中进行隐式窄化转换,aarch64 上 size_t 是 64 位,FLAC__uint32 是 32 位

            解决方案:

            1. 创建补丁文件 patches/fix-aarch64-narrowing.patch
            2. 在 src/libFLAC++/metadata.cpp 中添加显式类型转换
            3. 使用 static_cast<FLAC__uint32>() 进行转换

            问题 3: 文档安装失败

            错误信息:

            make[4]: *** [Makefile:600: install-data-local] Error 1

            原因: make install 时尝试安装文档,但 doc/html/api 目录不存在(需要 Doxygen 生成)

            解决方案:

            1. 在 package() 函数中临时修改 Makefile
            2. 从 SUBDIRS 中移除 doc 目录
            3. 安装完成后恢复原始 Makefile

            问题 4: 设备上测试时重新编译

            错误信息:

            /bin/sh: /path/to/cross-compiler: No such file or directory

            原因:设备上执行 make check 时,Makefile 中的编译器路径是构建机的绝对路径,设备上不存在

            解决方案:

            1. 在交叉编译阶段就编译测试程序
            2. 创建自定义测试脚本 run_libflac_tests.sh
            3. 修改 Makefile,将 check 目标改为运行测试脚本

            问题 5: 测试输出不可见

            问题描述:在设备上执行测试时,看不到日志和测试结果

            原因:所有输出都重定向到日志文件,没有输出到标准输出

            解决方案:

            1. 使用 tee -a ${logfile} 同时输出到屏幕和日志文件
            2. 添加测试进度显示([TEST X/6]
            3. 添加测试状态标记([PASS][FAIL][SKIP]
            4. 添加测试总结信息

            问题 6: 特殊测试用例处理

            问题描述:

            • test_libFLAC 和 test_libFLAC++ 在 root 环境下报 “are you running as root?”

            • test_seeking 无参数时显示 usage

              解决方案:

              1. 创建辅助函数 run_test_maybe_root() 处理 root 环境警告
              2. 创建辅助函数 run_test_maybe_usage() 处理 usage 输出
              3. 将这些情况视为正常,不标记为失败

              最新文章

              随机文章

              基本 文件 流程 错误 SQL 调试
              1. 请求信息 : 2026-02-28 09:03:18 HTTP/2.0 GET : https://c.mffb.com.cn/a/472346.html
              2. 运行时间 : 0.089557s [ 吞吐率:11.17req/s ] 内存消耗:4,474.09kb 文件加载:140
              3. 缓存信息 : 0 reads,0 writes
              4. 会话信息 : SESSION_ID=493ce21d8a7428911f84f110e7f73c0f
              1. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/public/index.php ( 0.79 KB )
              2. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
              3. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
              4. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
              5. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
              6. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
              7. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
              8. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
              9. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
              10. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
              11. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
              12. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
              13. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
              14. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
              15. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
              16. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
              17. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
              18. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
              19. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
              20. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
              21. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
              22. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/provider.php ( 0.19 KB )
              23. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
              24. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
              25. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
              26. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/common.php ( 0.03 KB )
              27. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
              28. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
              29. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/app.php ( 0.95 KB )
              30. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/cache.php ( 0.78 KB )
              31. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/console.php ( 0.23 KB )
              32. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/cookie.php ( 0.56 KB )
              33. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/database.php ( 2.48 KB )
              34. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
              35. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/filesystem.php ( 0.61 KB )
              36. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/lang.php ( 0.91 KB )
              37. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/log.php ( 1.35 KB )
              38. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/middleware.php ( 0.19 KB )
              39. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/route.php ( 1.89 KB )
              40. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/session.php ( 0.57 KB )
              41. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/trace.php ( 0.34 KB )
              42. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/config/view.php ( 0.82 KB )
              43. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/event.php ( 0.25 KB )
              44. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
              45. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/service.php ( 0.13 KB )
              46. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/AppService.php ( 0.26 KB )
              47. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
              48. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
              49. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
              50. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
              51. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
              52. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/services.php ( 0.14 KB )
              53. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
              54. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
              55. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
              56. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
              57. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
              58. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
              59. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
              60. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
              61. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
              62. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
              63. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
              64. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
              65. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
              66. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
              67. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
              68. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
              69. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
              70. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
              71. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
              72. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
              73. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
              74. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
              75. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
              76. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
              77. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
              78. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
              79. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
              80. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
              81. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
              82. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
              83. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/Request.php ( 0.09 KB )
              84. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
              85. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/middleware.php ( 0.25 KB )
              86. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
              87. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
              88. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
              89. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
              90. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
              91. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
              92. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
              93. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
              94. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
              95. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
              96. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
              97. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
              98. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
              99. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/route/app.php ( 1.72 KB )
              100. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
              101. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
              102. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
              103. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
              104. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/app/BaseController.php ( 2.05 KB )
              105. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
              106. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
              107. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
              108. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
              109. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
              110. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
              111. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
              112. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
              113. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
              114. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
              115. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
              116. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
              117. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
              118. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
              119. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
              120. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
              121. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
              122. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
              123. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
              124. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
              125. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
              126. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
              127. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
              128. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
              129. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
              130. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
              131. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
              132. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
              133. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
              134. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
              135. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
              136. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
              137. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
              138. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
              139. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/runtime/temp/cefbf809ba1a84190cb04b0cb7abcf79.php ( 11.98 KB )
              140. /yingpanguazai/ssd/ssd1/www/c.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
              1. CONNECT:[ UseTime:0.000614s ] mysql:host=127.0.0.1;port=3306;dbname=c_mffb;charset=utf8mb4
              2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000625s ]
              3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000298s ]
              4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000273s ]
              5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000497s ]
              6. SELECT * FROM `set` [ RunTime:0.000204s ]
              7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000500s ]
              8. SELECT * FROM `article` WHERE `id` = 472346 LIMIT 1 [ RunTime:0.002036s ]
              9. UPDATE `article` SET `lasttime` = 1772240599 WHERE `id` = 472346 [ RunTime:0.014636s ]
              10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000242s ]
              11. SELECT * FROM `article` WHERE `id` < 472346 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000396s ]
              12. SELECT * FROM `article` WHERE `id` > 472346 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000368s ]
              13. SELECT * FROM `article` WHERE `id` < 472346 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001372s ]
              14. SELECT * FROM `article` WHERE `id` < 472346 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001015s ]
              15. SELECT * FROM `article` WHERE `id` < 472346 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000720s ]
              0.091079s