鸿蒙PC生态实践:LAME 音频编码库移植与工程化指南 - 指南

本文详细介绍了如何针对 OpenHarmony PC 平台,使用 CMake 构建系统交叉编译 LAME MP3 编码库。文章聚焦于解决标准库缺失、架构不匹配等核心移植难题,并提供了适配鸿蒙PC开发环境的工程化 CMakeLists.txt 方案。

前言:鸿蒙PC生态的拓展与三方库移植意义

随着 HarmonyOS 正式进军 PC 领域,构建完善的软件生态成为关键。由于鸿蒙 PC 版的底层基于 OpenHarmony 与 Linux 内核的混合架构,现有 Linux/Windows 平台的开源库需要针对鸿蒙 PC 进行交叉编译与系统级适配。本文将以开源音频库 LAME 为例,详细介绍如何在鸿蒙 PC 平台上完成三方库的移植,并提供可复用的工程化方案。

LAME是目前非常优秀的一种MP3编码引擎,在业界,转码成MP3格式的音频文件时,最常用的编码器就是LAME库。当到达320Kbit/s以上时,LAME编码出来的音频质量几乎可以和CD的音质相媲美,并且还能保证整个音频文件的体积非常小,因此若要在移动端平台上编码MP3文件,使用LAME便成为唯一的选择。同时该库也是ffmpeg的依赖库之一。

一、移植工具链环境搭建

鸿蒙 PC 开发需使用专用的交叉编译工具链。关于环境的搭建,参见猫哥的上一篇博文:《鸿蒙PC生态三方软件移植:开发环境搭建及三方库移植指南》

虽然官方提供了示例项目工程和 build.sh 脚本,但这些方案适合批量构建多个库,不方便单独调试。我们采用更灵活的 exports.sh 脚本来配置独立的开发环境。

  1. 配置 SDK 路径与基础工具链

在项目目录下创建 exports.sh 文件,声明 SDK 路径与编译工具。
根据你实际的改下配置:

echo "hello exports"
## 你的SDK路径
SDK_PATH="/root/ohos-sdk/linux"
echo "SDK_PATH:$SDK_PATH"
export OHOS_SDK="$SDK_PATH"
export HNP_PERFIX=
export COMPILER_TOOLCHAIN=${OHOS_SDK}/native/llvm/bin/
BUILD_OS=$(uname)
PYTHON=$(python --version)
echo "python  : $PYTHON"
export CC=${COMPILER_TOOLCHAIN}clang             && echo "CC      : ${CC}"
export CXX=${COMPILER_TOOLCHAIN}clang++          && echo "CXX     : ${CXX}"
export HOSTCC=${CC}                              && echo "HOSTCC  : ${HOSTCC}"
export HOSTCXX=${CXX}                            && echo "HOSTCXX : ${HOSTCXX}"
export CPP="${CXX}  -E"                             && echo "CPP     : ${CPP}"
export AS=${COMPILER_TOOLCHAIN}llvm-as           && echo "AS      : ${AS}"
export LD=${COMPILER_TOOLCHAIN}ld.lld            && echo "LD      : ${LD}"
export STRIP=${COMPILER_TOOLCHAIN}llvm-strip     && echo "STRIP   : ${STRIP}"
export RANLIB=${COMPILER_TOOLCHAIN}llvm-ranlib   && echo "RANLIB  : ${RANLIB}"
export OBJDUMP=${COMPILER_TOOLCHAIN}llvm-objdump && echo "OBJDUMP : ${OBJDUMP}"
export OBJCOPY=${COMPILER_TOOLCHAIN}llvm-objcopy && echo "OBJCOPY : ${OBJCOPY}"
export NM=${COMPILER_TOOLCHAIN}llvm-nm           && echo "NM      : ${NM}"
export AR=${COMPILER_TOOLCHAIN}llvm-ar           && echo "AR      : ${AR}"
export SYSROOT=${OHOS_SDK}/native/sysroot
export PKG_CONFIG_SYSROOT_DIR=${SYSROOT}/usr/lib/aarch64-linux-ohos
export PKG_CONFIG_PATH=${PKG_CONFIG_SYSROOT_DIR}
export PKG_CONFIG_EXECUTABLE=${PKG_CONFIG_SYSROOT_DIR}
export HNP_TOOL=${OHOS_SDK}/toolchains/hnpcli
export CMAKE=${OHOS_SDK}/native/build-tools/cmake/bin/cmake
export TOOLCHAIN_FILE=${OHOS_SDK}/native/build/cmake/ohos.toolchain.cmake
export WORK_ROOT=${PWD}
export ARCHIVE_PATH=${WORK_ROOT}/output
export COMM_DEP_PATH=${WORK_ROOT}/deps_install
export HNP_PUBLIC_PATH=${HNP_PERFIX}/data/service/hnp/
export MAKE_QUITE_PARAM=" -s "
export CONFIGURE_QUITE_PARAM=" --quiet "
export TARGET_PLATFORM=aarch64-linux-ohos
export CFLAGS="-fPIC -D__MUSL__=1 -D__OHOS__ -fstack-protector-strong --target=${TARGET_PLATFORM} --ld-path=${LD}  --sysroot=${SYSROOT}"
export CXXFLAGS="${CFLAGS} "
export LD_LIBRARY_PATH=${SYSROOT}/usr/lib:${LD_LIBRARY_PATH}
export LDFLAGS="${LDFLAGS} --ld-path=${LD}  --target=${TARGET_PLATFORM} --sysroot=${SYSROOT}"
export HOST_TYPE="--host=aarch64-linux --build=aarch64-linux"
#export NCURSES_INSTALL_HNP_PATH="${HNP_PUBLIC_PATH}/ncurses.org/ncurses_v6.4"
mkdir -p ${HNP_PUBLIC_PATH}
mkdir -p ${ARCHIVE_PATH}
mkdir -p code
#export PKG_CONFIG_PATH="${CUSTOM_PREFIX}/lib/pkgconfig:$PKG_CONFIG_PATH"

通过执行 source exports.sh 激活环境。

  1. CMake 工具链配置

鸿蒙 SDK 提供专用的 ohos.toolchain.cmake 文件,用于指导 CMake 的交叉编译行为。该配置已包含在上述 exports.sh 脚本中。

二、LAME 库移植实战

LAME(Lame Aint an MP3 Encoder)是一个高质量的开源 MP3 音频编码器。LAME 原始的构建系统依赖于 configure 脚本生成 config.h 文件和 Makefiles,这在鸿蒙交叉编译环境中容易出现兼容性问题。因此,我们选择使用 CMake 构建系统,并手动解决移植过程中遇到的关键问题。

lame源码地址:https://sourceforge.net/projects/lame/

  1. 移植遇到的主要问题与解决思路
    手动使用 CMake 构建时,跳过了 LAME 原有的 configure 脚本所做的系统类型检查,导致以下错误:
    链接错误:cannot find crti.o 或 file in wrong format (EM: 183),通常是由于工具链未正确配置 sysroot 或架构不匹配导致。
    编译错误:unknown type name ‘ieee754_float32_t’ 或 undeclared identifier ‘INT_MAX’ 等。
    解决思路:
    配置 Sysroot:通过 exports.sh 正确设置 CMAKE_SYSROOT 和 TARGET_PLATFORM,确保编译器能找到标准的 C 库头文件。
    适配类型定义:在 CMake 中手动定义 ieee754_float32_t 类型别名,模拟 config.h 的功能。
  2. 核心 CMake 构建脚本 (CMakeLists.txt)
    将以下内容保存为 LAME 源码根目录下的 CMakeLists.txt:

控制是否构建前端可执行文件 (lame),默认禁用以简化移植:

option(BUILD_FRONTEND "Build the LAME frontend executable (lame)" OFF)
set(LAME_VERSION_MAJOR 3)
set(LAME_VERSION_MINOR 100)
set(LAME_VERSION "${LAME_VERSION_MAJOR}.${LAME_VERSION_MINOR}")

包含头文件路径

include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libmp3lame"
)

定义源代码文件列表

file(GLOB_RECURSE LAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/libmp3lame/*.c")

— 解决编译错误的关键部分 —

  1. 解决 ‘ieee754_float32_t’ unknown type name 错误,手动定义为 float
    add_definitions(-Dieee754_float32_t=float)

注意:此脚本依赖于外部工具链配置(如 exports.sh 中的 --sysroot)来查找标准库头文件。

添加库目标 (构建为动态库 SHARED,适配鸿蒙动态链接机制)

add_library(mp3lame SHARED ${LAME_SOURCES})
set_target_properties(mp3lame PROPERTIES
VERSION ${LAME_VERSION}
SOVERSION ${LAME_VERSION_MAJOR}
PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/lame.h"
)

定义安装规则

install(TARGETS mp3lame
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
)

根据选项决定是否编译前端

if(BUILD_FRONTEND)
message(STATUS "Building LAME frontend executable (lame)")
# ... (此处省略前端构建代码) ...
else()
message(STATUS "Frontend executable build disabled by option BUILD_FRONTEND")
endif()
  1. 开始执行编译
    确保您已经按照第一节配置了 exports.sh 并激活环境。
  2. 激活环境
source exports.sh
  1. 进入 LAME 源码目录,创建并进入 build 目录
cd /path/to/lame/source
mkdir build
cd build
  1. 运行 CMake,指定源码目录(…),并使用鸿蒙专用的工具链文件
    CMAKE 环境变量已经在 exports.sh 中定义
${CMAKE} .. -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} -DBUILD_SHARED_LIBS=ON
  1. 编译
make -j$(nproc)

完整的cmake脚本

CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.12)
project(LAME C)
# --- 添加一个选项来控制是否构建前端 ---
# 默认开启 (ON),如果你想默认禁用,可以改为 OFF
option(BUILD_FRONTEND "Build the LAME frontend executable (lame)" OFF)
set(LAME_VERSION_MAJOR 3)
set(LAME_VERSION_MINOR 100)
set(LAME_VERSION "${LAME_VERSION_MAJOR}.${LAME_VERSION_MINOR}")
# 包含头文件路径
include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/libmp3lame"
)
# 定义源代码文件列表
file(GLOB_RECURSE LAME_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/libmp3lame/*.c")
# --- 解决编译错误的关键部分 ---
# 1. 解决 'ieee754_float32_t' unknown type name 错误
add_definitions(-Dieee754_float32_t=float)
# 添加库目标
add_library(mp3lame SHARED ${LAME_SOURCES})
# 将列表中的每个项目作为单独的选项传递
target_compile_options(mp3lame PRIVATE ${LAME_REQUIRED_INCLUDES})
set_target_properties(mp3lame PROPERTIES
VERSION ${LAME_VERSION}
SOVERSION ${LAME_VERSION_MAJOR}
PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/include/lame.h"
)
install(TARGETS mp3lame
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include
)
# --- 使用 if 语句根据选项决定是否编译前端 ---
if(BUILD_FRONTEND)
message(STATUS "Building LAME frontend executable (lame)")
file(GLOB_RECURSE FRONTEND_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/frontend/*.c")
add_executable(lame ${FRONTEND_SOURCES})
target_link_libraries(lame mp3lame)
target_compile_options(lame PRIVATE ${LAME_REQUIRED_INCLUDES})
install(TARGETS lame RUNTIME DESTINATION bin)
else()
message(STATUS "Frontend executable build disabled by option BUILD_FRONTEND")
endif()

三、编译注意事项

如果待移植的项目原生支持 CMake,强烈建议直接使用 CMake 进行构建,可以省去大量适配 configure 脚本和 Makefile 的麻烦。如本文所示,通过适配 CMake,可以高效地解决鸿蒙 PC 平台移植中遇到的标准库兼容性和架构配置问题。

build_os.sh脚本:

export LAME_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/lame.org/lame_3.100
#make clean
${CMAKE} \
-DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE} \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_INSTALL_PREFIX=${LAME_INSTALL_HNP_PATH}\
-DCMAKE_SYSROOT="${SYSROOT}"
make VERBOSE=1 -j$(nproc)
make install
cp hnp.json ${LAME_INSTALL_HNP_PATH}/
pushd ${LAME_INSTALL_HNP_PATH}/../
${HNP_TOOL} pack -i ${LAME_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/
tar -zvcf ${ARCHIVE_PATH}/ohos_lame_3.100.tar.gz lame_3.100/
popd

编译成功截图:

在这里插入图片描述
如果使用原始的configure脚本形式,编译莫名报错,这个报错原因,至今未找到答案。
原来的build_ohos.sh脚本如下:

export LAME_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/lame.org/lame_3.100
#make clean
./configure  --host=aarch64-linux-musl \
--target=aarch64-linux-musl \
--enable-shared \
--disable-static \
--prefix=${LAME_INSTALL_HNP_PATH}
make VERBOSE=1 -j$(nproc)
make install
cp hnp.json ${LAME_INSTALL_HNP_PATH}/
pushd ${LAME_INSTALL_HNP_PATH}/../
${HNP_TOOL} pack -i ${LAME_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/
tar -zvcf ${ARCHIVE_PATH}/ohos_lame_3.100.tar.gz lame_3.100/
popd

在这里插入图片描述

最后实在没办法了,给lame库写了个cmake的脚本,使用cmake的方式搞定了。
如果其他小伙伴有使用configure脚本生成makefile形式编译成功的,欢迎留言交流下哈。

其他资源

posted @ 2025-12-11 16:42  clnchanpin  阅读(20)  评论(0)    收藏  举报