编译环境: ubuntu12.04
目标环境: cotex-A8(AM335-XS),运行linux3.2.0
交叉工具链: arm-arago-linux-gnueabi-
一、下载源码
下载最新的libxml2安装包libxml2-sources-2.7.8.tar.gz,解压:tar zxvf libxml2-sources-2.7.8.tar.gz
二、配置:
进入解压后的目录cd libxml2-2.7.8/ 创建可执行文件setup.sh,在第一行添加配置选项
./configure --build=i386-linux --host=arm-linux --target=arm-linux --enable-static CC= arm-arago-linux-gnueabi-gcc AR= arm-arago-linux-gnueabi-ar LD= arm-arago-linux-gnueabi-ld RANLIB= arm-arago-linux-gnueabi-ranlib export ARCH=arm export CROSS_COMPILE= arm-arago-linux-gnueabi-
注:必须放在一行,不能换行,且所有的操作必须在root权限下执行。
- 给setup.sh增加执行权限:chmod +x setup.sh
- 执行配置文件:./setup.sh即可完成配置
三、 make
执行make命令,编译libxml2库。
四、 make install
执行make install命令,即可在/usr/local/下生成四个子文件夹:bin/ include/ lib/ share,其中lib/是静态和动态库文件,include/是头文件。
五、 测试
测试xml文件eg.xml内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<Authentication>
<user>
<userid>001</userid>
<username>root</username>
<password>root</password>
</user>
<user>
<userid>002</userid>
<username>ctu</username>
<password>ctu</password>
</user>
</Authentication>
测试程序test.c如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include<iconv.h>
static char s_strBufOut[1024];
char *d_ConvertCharset(char *cpEncodeFrom, char *cpEncodeTo, char *cpInput)
{
char *cpOut;
size_t iInputLen, iOutLen, iReturn;
iconv_t c_pt;
if ((c_pt = iconv_open(cpEncodeTo, cpEncodeFrom)) == (iconv_t)-2) {
printf("iconv_open failed!\n");
return NULL;
}
iconv(c_pt, NULL, NULL, NULL, NULL);
iInputLen = strlen(cpInput) + 1;
iOutLen = 1024;
cpOut = s_strBufOut;
iReturn = iconv(c_pt, &cpInput, &iInputLen, &cpOut, &iOutLen);
if (iReturn == -1)
{
return NULL;
}
iconv_close(c_pt);
return s_strBufOut;
}
//输出每一项的内容,使用GB2312编码输出
void parseItem (xmlDocPtr doc, xmlNodePtr cur)
{
struct user
{
char id[20];
char name[64];
char password[64];
};
struct user user[2];
int i, j;
xmlChar *key;
char *p = NULL;
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
for (i=0;i<2;i++) {
if ((!xmlStrcmp(cur->name, (const xmlChar *)"userid"))) {
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
memcpy(user[i].id, key, strlen(key)+1);
xmlFree(key);
} else if((!xmlStrcmp(cur->name, (const xmlChar *)"username"))) {
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
memcpy(user[i].name, key, strlen(key)+1);
xmlFree(key);
} else if ((!xmlStrcmp(cur->name, (const xmlChar *)"password"))) {
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
memcpy(user[i].password, key, strlen(key)+1);
xmlFree(key);
}
}
cur = cur->next;
}
for(j=0;j<2;j++)
{
printf("struct information:\n");
printf("id:%s name:%s password:%s\n",user[j].id,user[j].name,user[j].password);
}
return;
}
void parseDoc(char *docname)
{
xmlDocPtr doc; //解析树
xmlNodePtr cur; //当前节点
struct role
{
char name[64];
char password[64];
};
struct role role1;
xmlChar *key;
doc = xmlParseFile(docname);
if (doc == NULL) {
fprintf(stderr,"Document not parsed successfully. \n");
return;
}
//得到根节点
cur = xmlDocGetRootElement(doc);
if (!cur) {
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return;
}
if (xmlStrcmp(cur->name, (const xmlChar *)"Authentication")) {
fprintf(stderr,"document of the wrong type, root node != Authentication\n");
xmlFreeDoc(doc);
return;
}
//得到当前节点的第一个子节点,即第一个ITEM
cur = cur->xmlChildrenNode;
while ( NULL != cur )
{
if ((!xmlStrcmp(cur->name, (const xmlChar *)"user"))) {
//输出每个ITEM
printf("user information\n");
parseItem (doc, cur);
printf("heeell\n");
}
cur = cur->next;
}
xmlFreeDoc(doc);
return;
}
//入参可以是一个文件,也可以是一个URL,要求必须是UTF-8编码
int main(int argc, char **argv)
{
char *docname;
if (argc <= 1)
{
printf("Usage: %s docname\n", argv[0]);
return(0);
}
docname = argv[1];
parseDoc(docname);
return 0;
}
编译程序:
arm-arago-linux-gnueabi-gcc test.c -I /usr/local/include/libxml2/ -L /usr/local/lib/ -lxml2
此时将编译好的可执行文件和xml文件拷贝到开发板上执行会出错,因为开发板上没有相应的动态库文件,故会出错,解决办法,将/usr/local/lib/中库文件拷贝到开发板上的/usr/lib中。
注:这样做有个不太好的地方,会污染系统文件,所以常用的方法就是将编译好的动态库放到用户自定义的一个路径下面(如:/root/myLib/),然后再添加环境变量:
LD_LIBRARY_PATH=/root/myLib:$LD_LIBRARY_PATH
环境变量一般添加在系统启动脚本里面,比如:/etc/profile或者/etc/bash.bashrc等文件中。
六、将动态库添加到编译器
每次编译程序都要动态的指定头文件和库文件的路径非常麻烦,可以讲头文件和库文件拷贝到交叉工具链中,使用如下命令:
cp /usr/local/libxml2/libxml/ /usr/local/arm/cross/am335xt3/devkit/arm-arago-linux-gnueabi/usr/include –rf
cp /usr/local/lib/* /usr/local/arm/cross/am335xt3/devkit/arm-arago-linux-gnueabi/usr/lib/
这样就可以不用每次都指定头文件和库文件的位置了,即使用如下命令便可以编译程序:arm-arago-linux-gnueabi-gcc test.c –lxml2,其中-lixml2是指定要链接的库文件,当然这个也会污染编译器。