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 产物。
相关推荐
David猪大卫1 小时前
【C++修炼】STL容器—模板进阶:非类型模板参数、模板特化、模板分离编译
c语言·开发语言·c++·经验分享·笔记·学习·面试
老当益壮梁奶奶1 小时前
驱动学习(二):从零开始:驱动工程搭建与字符设备驱动框架详解(基于IMX6ULL)
c语言·arm开发·驱动开发·嵌入式硬件·学习
星 海2 小时前
【json】cJSON库解析文件
c语言·json·cjson
Zip-List2 小时前
工作小记-pytorch的算子优化: 转gpu核函数 python调c
c语言·c++·pytorch·python·cuda
C++ 老炮儿的技术栈3 小时前
char 造成的数据溢出
linux·服务器·c语言·c++·算法·c
Zwawa16 小时前
先把轮子转稳,才不会烧心:编码器速度环 PID 怎么接回 PWM
c语言·单片机·嵌入式
Escalating_xu20 小时前
【C 语言】编译和链接:从源文件、目标文件到可执行程序完整解析
c语言·开发语言
C++ 老炮儿的技术栈20 小时前
std::atomic 是什么
linux·c语言·网络·c++·visual studio
Logic10121 小时前
C语言/数据结构位运算题解:异或XOR找出数轴移动中只出现一次的指令——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质