libxml2 源码编译与 XML 读取验证(x86 / ARM)

libxml2 源码编译与 XML 读取验证(x86 / ARM)

目标:在 Ubuntu 虚拟机用源码编译 libxml2,先做 x86(gcc) 验证,再复用同一份源码交叉编译 ARM 版本。

安装目录:x86 → /home/jp/Desktop/xml/lib/x86,ARM → /home/jp/Desktop/xml/lib/arm


第 1 步:下载 libxml2 源码

用官方 release 包(自带 configure,不需要 autotools):

bash 复制代码
cd ~
wget https://download.gnome.org/sources/libxml2/2.11/libxml2-2.11.5.tar.xz
tar -xf libxml2-2.11.5.tar.xz
cd libxml2-2.11.5

备选:git clone https://gitlab.gnome.org/GNOME/libxml2.git,但需多跑 ./autogen.sh,且依赖 autoconf/automake/libtool,验证场景不推荐。

第 2 步:原生编译,装到 /home/jp/Desktop/xml/lib/x86(免 sudo)

bash 复制代码
./configure \
    --prefix=/home/jp/Desktop/xml/lib/x86 \
    --without-python \
    --without-zlib \
    --without-lzma

make -j$(nproc)
make install

说明:

  • --without-zlib / --without-lzma:去掉 gzip/xz 压缩 XML 支持,免装 zlib1g-dev、liblzma-dev(明文 XML 用不到)。
  • --without-python:不编译 Python 绑定。
  • iconv 保持默认(Ubuntu 的 glibc 内置,无需额外包)。

第 3 步:验证安装结果

头文件在 include/libxml2/libxml/ 这一层(libxml/ 前缀由 #include <libxml/...> 自己补):

bash 复制代码
ls -l /home/jp/Desktop/xml/lib/x86/lib/libxml2.so*
# 应看到: libxml2.so -> libxml2.so.2.x.y(符号链接)和实体 libxml2.so.2.x.y

ls /home/jp/Desktop/xml/lib/x86/include/libxml2/libxml/parser.h
ls /home/jp/Desktop/xml/lib/x86/include/libxml2/libxml/xpath.h
ls /home/jp/Desktop/xml/lib/x86/lib/pkgconfig/libxml-2.0.pc

第 4 步:写测试程序 test_xml.c

c 复制代码
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>

/* 用 XPath 查询所有匹配节点的文本内容 */
static void query_by_xpath(xmlDocPtr doc, const char *xpath)
{
    xmlXPathContextPtr ctx = xmlXPathNewContext(doc);
    if (ctx == NULL) {
        printf("创建 XPath 上下文失败\n");
        return;
    }

    xmlXPathObjectPtr result = xmlXPathEvalExpression((xmlChar *)xpath, ctx);
    if (result == NULL) {
        printf("XPath [%s] 执行失败\n", xpath);
        xmlXPathFreeContext(ctx);
        return;
    }

    xmlNodeSetPtr nodes = result->nodesetval;
    printf("XPath [%s] 命中 %d 个节点:\n", xpath,
           nodes ? nodes->nodeNr : 0);

    for (int i = 0; i < (nodes ? nodes->nodeNr : 0); i++) {
        xmlChar *content = xmlNodeGetContent(nodes->nodeTab[i]);
        printf("  [%d] %s\n", i, content);
        xmlFree(content);
    }

    xmlXPathFreeObject(result);
    xmlXPathFreeContext(ctx);
}

int main(int argc, char *argv[])
{
    const char *file = (argc > 1) ? argv[1] : "test.xml";

    xmlInitParser();

    /* 读文件建 DOM,XML_PARSE_RECOVER 容错,和项目里一致 */
    xmlDocPtr doc = xmlReadFile(file, "UTF-8", XML_PARSE_RECOVER);
    if (doc == NULL) {
        printf("解析 XML 失败: %s\n", file);
        xmlCleanupParser();
        return -1;
    }

    /* 根节点名称 */
    xmlNodePtr root = xmlDocGetRootElement(doc);
    printf("根节点: <%s>\n\n", root->name);

    /* XPath 查询 */
    query_by_xpath(doc, "/root/server/ip");
    query_by_xpath(doc, "//port");

    xmlFreeDoc(doc);
    xmlCleanupParser();

    printf("\nXML 读取验证通过\n");
    return 0;
}

第 5 步:准备测试 XML test.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <server>
        <ip>192.168.1.100</ip>
        <port>2404</port>
    </server>
    <device name="inverter">
        <port>502</port>
    </device>
</root>

第 6 步:编译

注意 -I 指到 include/libxml2 这一层(不要 再加 /libxml,#include <libxml/parser.h> 会自己补上 libxml/):

bash 复制代码
# 方式 A:直接给路径
gcc -o test_xml test_xml.c \
    -I/home/jp/Desktop/xml/lib/x86/include/libxml2 \
    -L/home/jp/Desktop/xml/lib/x86/lib \
    -Wl,-rpath,/home/jp/Desktop/xml/lib/x86/lib \
    -lxml2

# 方式 B:用 pkg-config(自动给对 -I 和 -lxml2)
export PKG_CONFIG_PATH=/home/jp/Desktop/xml/lib/x86/lib/pkgconfig
gcc -o test_xml test_xml.c $(pkg-config --cflags --libs libxml-2.0) \
    -Wl,-rpath,/home/jp/Desktop/xml/lib/x86/lib

第 7 步:运行

bash 复制代码
./test_xml test.xml

预期输出:

复制代码
根节点: <root>

XPath [/root/server/ip] 命中 1 个节点:
  [0] 192.168.1.100
XPath [//port] 命中 2 个节点:
  [0] 2404
  [1] 502

XML 读取验证通过

附:复用同一份源码做 ARM 交叉编译

bash 复制代码
cd ~/libxml2-2.11.5

make distclean   # 清理 x86 编译产物

./configure \
    --host=arm-linux-gnueabihf \
    CC=arm-linux-gnueabihf-gcc \
    --prefix=/home/jp/Desktop/xml/lib/arm \
    --without-python \
    --without-zlib \
    --without-lzma

make -j$(nproc)
make install

file /home/jp/Desktop/xml/lib/arm/lib/libxml2.so.2
# 应显示 ARM,而不是 x86-64

之后把 /home/jp/Desktop/xml/lib/arm/lib/libxml2.so.2(实体文件,不是符号链接)拷到目标板 /usr/lib/,并把项目 makefile 的 XMLINCPATH 与 -L 指到 /home/jp/Desktop/xml/lib/arm 即可。


要点回顾

  • 头文件真实位置是 include/libxml2/libxml/parser.h,但 -I 只需到 include/libxml2 这一层;
  • 库装在非系统目录,靠 -Wl,-rpath 或 LD_LIBRARY_PATH 让运行期能找到;
  • --without-zlib --without-lzma --without-python 是为了免 sudo 装额外依赖,明文 XML 用不到压缩功能;
  • x86 与 ARM 分两个 --prefix,make install 只装头文件 + 库,两者互不覆盖;
  • 交叉编译前必须 make distclean 清理 x86 的 .o 产物。
相关推荐
anguoyang1 天前
RK3588 上模型「能跑但很慢」:逐算子查 CPU 回退的完整方法与实测
嵌入式
§ꦿCFོ༉1 天前
嵌入式八股—C语言入门学习(一)
c语言·编程语言·嵌入式八股文
沐晓时光1 天前
C语言入门,字符串和字符串函数知识讲解
c语言·开发语言
xbronze1 天前
STM32+RC522读取MIFARE 1K卡排坑实录
嵌入式
La Pulga1 天前
【FreeRTOS源码学习笔记】空闲任务与阻塞延时
笔记·mcu·学习·嵌入式·freertos·实时操作系统
小李不想当小白1 天前
WDG看门狗(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
智者知已应修善业1 天前
【51单片机实现从下到上,从上到下,从中间到两边,两边到中间】2024-10-23
c语言·经验分享·笔记·单片机·嵌入式硬件·51单片机
布莱克6052 天前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
揽星河..2 天前
【C语言】底层程序设计
c语言·开发语言
La Pulga2 天前
【FreeRTOS源码学习笔记】任务切换
单片机·mcu·学习·嵌入式·freertos·实时操作系统