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产物。