使用gSOAP开发实例(6) 在HP-UX下编译gSOAP-2.7.17
gSOAP号称是跨平台的工具包,不过毕竟是属于g字头的,如果没有了一系列GNU组件的支持,在其他类Unix系统编译就会遇到不少困难。
gSOAP的README说得也不是很清楚,只提到依赖于这些组件:
1. Automake tools (makeand GNU m4) to configure and build
2. Bisonhttp://www.gnu.org/software/bison or the alternative Yacc
3. Flexhttp://flex.sourceforge.net
4. OpenSSL (foroptional HTTPS) http://www.openssl.org
5. Zlib (for optionalcompression) http://www.zlib.net
6. Pthreads or win32threads (optional)
实际上,我在HP-UX下编译gSOAP的时候发现,要成功编译,还需要安装autoconf、gawk和make,为解决中文乱码问题,还需要安装libiconv。虽然原系统就有awk和make,但是可能由于版本问题,编译时会出错。所以,建议大家编译最新版的gSOAP-2.7.17时,按一下顺序安装组件:
1. autoconf-2.66 (http://ftp.gnu.org/gnu/autoconf/)
autoconf是一个用于生成可以自动地配置软件源代码包以适应多种Unix类系统的shell脚本的工具。
2. automake-1.10 (http://ftp.gnu.org/gnu/automake/)
automake是一个从文件Makefile.am自动生成Makefile.in的工具。每个Makefile.am基本上是一系列make的宏定义(make规则也会偶尔出现)。生成的Makefile.in服从GNU Makefile标准。
3. m4-1.4.14 (http://ftp.gnu.org/gnu/m4/)
m4是一个宏处理器。介绍是这么说的,具体用途不详,可以肯定的是编译器会用到
4. gawk-3.1.8 (http://ftp.gnu.org/gnu/gawk/)
awk地球人都知道。HP-UX自带的awk不是GNU的,编译gSOAP时执行某些语句出错,因此要使用GNU新版本的
5. make-3.81 (http://ftp.gnu.org/gnu/make/)
make也是地球人都知道。HP-UX自带的make编译gSOAP时会出错。
6. bison-2.4 (http://ftp.gnu.org/gnu/bison/)
语法分析生成器。
7. flex-2.5.35 (http://flex.sourceforge.net/)
词法分析生成器。
8. zlib-1.2.5 (http://www.zlib.net/)
gzip和LZW压缩库。
9. libiconv-1.13.1 (http://ftp.gnu.org/pub/gnu/libiconv/)
字符编码转换工具。上一节有介绍
openssl原来就已经有,无需安装。如果没有或者版本很低,可以到这里下载: http://www.openssl.org/source/
补充事项:
1. 如何判断某个组件是否需要安装?很简单,到LFS官方网站参考用户手册:http://www.linuxfromscratch.org/lfs/view/stable/,查看一下该组件包含的Installed program,然后在命令行使用which命令找一下,如果找不到,可以肯定需要安装
2. 如何判断某个组件是否需要升级?如果通过上述方法能够找到已安装的组件,但是文件的时间比较久远,而且不支持--help查看帮助信息或者--version查看版本信息,几乎可以肯定需要升级,因为比较新的GNU程序一般都支持这些参数的。如果通过--version显示版本较低,也应该升级
3. 上述组件的安装一般都是./configure&& make && make install三部曲。如果没有root权限,可以使用./configure --prefix=/path/to/your/directory指定合法的安装路径,然后根据需要指定PATH和SHLIB_PATH环境变量。千万要注意,HP-UX的动态链接库的环境变量是SHLIB_PATH,而不是和Linux下的LD_LIBRARY_PATH
4. 设置环境变量的时候也要注意,如果系统中已经有旧版本的组件,并且新旧版本不在同一目录,export环境变量的时候要把新版本组件所在的lib目录居前,这样系统才能优先搜索得到
5. HP-UX下编译flex-2.5.35时会遇到一个棘手的问题
ld: Unsatisfied symbol"rpl_realloc" in file dfa.o
1 errors.
collect2: ld returned 1 exitstatus
以rpl_realloc为关键字搜索,发现它出现在configure步骤产生的config.h当中
/* Define to rpl_realloc if thereplacement function should be used. */
#define realloc rpl_realloc
看样子,好像是为了避免有些系统没有realloc,而转用rpl_realloc代替。这个rpl_realloc不知是哪个系统的函数,HP-UX应该可以使用realloc这个标准C函数呀!于是,我把这一行注释了,重新make就正常了
6. gSOAP-2.7.17的编译指定要automake-1.10版本,如果像我那样不慎安装了automake-1.11,需要自行在其bin目录创建两个链接,否则gSOAP就是傻到不认帐!
aclocal-1.10 -> aclocal-1.11
automake-1.10 -> automake-1.11
7. gSOAP的傻事还不止一件,它只认flex的动态库而不认静态库,偏偏flex只安装了静态库。所以,安装flex之后,需要手动编译以生成libfl.so,然后再拷贝到其lib目录。
gcc-shared -fPCI -o libfl.so libmain.o libyywrap.o
此外,还需要在其lib目录创建两个链接,其中第一个是LFS为保持lex与flex的兼容性而建议的,至于第二个,完全是迁就gSOAP的坏脾气
libl.so -> libfl.so
libl.so.1 -> libl.so
如果上述准备工作全部完毕,那么即可正式编译gSOAP。编译步骤同样是./configure && make&& make install,似乎乏善可陈。但是,gSOAP-2.7.17似乎有一个bug,在HP-UX下编译会报错:
stdsoap2_cpp.cpp: In function 'size_t frecv(soap*, char*,size_t)':
stdsoap2_cpp.cpp:876: error: invalid conversion from 'socklen_t*'to 'int*'
stdsoap2_cpp.cpp:876: error: initializing argument 6 of 'int recvfrom(int, void*, int, int, void*,int*)'
stdsoap2_cpp.cpp: In function 'int tcp_connect(soap*, const char*,const char*, int)':
……
一大堆错误信息,其实是指向同一个错误:invalidconversion from 'socklen_t*' to 'int*'
首先,使用find命令查找stdsoap2_cpp.cpp只有一个
> find . -name"stdsoap2_cpp.cpp"
./gsoap/stdsoap2_cpp.cpp
然后,根据错误信息,查看该源程序的876行附近,函数的第六个参数,也就是最后一个参数k是SOAP_SOCKLEN_T类型的
接着,查找所有的头文件,看看该类型是哪个文件定义的
> find . -name"*.h" | xargs grep -l SOAP_SOCKLEN_T
./gsoap/samples/calc_vs2005/calc_vs2005/stdsoap2.h
./gsoap/samples/wsse/stdsoap2.h
./gsoap/stdsoap2.h
./gsoap/VisualStudio2005/wsdl2h/wsdl2h/stdsoap2.h
很明显,就在./gsoap/stdsoap2.h中。Vi之,在709行开始其定义:
709 /* Portability: define SOAP_SOCKLEN_T */
710 #if defined(_AIX)
711 # if defined(_AIX43)
712 # define SOAP_SOCKLEN_T socklen_t
713 # else
714 # define SOAP_SOCKLEN_T int
715 # endif
716 #elif defined(SOCKLEN_T)
717 # define SOAP_SOCKLEN_T SOCKLEN_T
718 #elif defined(__socklen_t_defined) ||defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) ||defined(__FreeBSD__) || defined(OPENBSD) || define
d(__QNX__) || defined(QNX) || defined(OS390) || defined(HP_UX)
719 #define SOAP_SOCKLEN_T socklen_t
720 #elif defined(IRIX) || defined(WIN32) ||defined(__APPLE__) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64)|| defined(VXWORKS)
721 # define SOAP_SOCKLEN_T int
722 #else
723 # define SOAP_SOCKLEN_T size_t
724 #endif
注意718和719行,gSOAP-2.7.17在HP-UX下,把SOAP_SOCKLEN_T定义为socklen_t,而其它操作系统不是定义为int就定义为size_t,再联系之前的错误信息invalid conversion from 'socklen_t*' to'int*',很清楚了,只要在719行把socklen_t改为int就肯定能够在HP-UX下编译通过了。或者严谨一些,把718行的defined(HP_UX)移到720行最后也可以。
上面的问题解决了,继续编译工作,很可能会遇上另一个问题
/usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yylsp' in loadmodule '/usr/lib/hpux32/libl.so.1'.
/usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yyolsp' in loadmodule '/usr/lib/hpux32/libl.so.1'.
/usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yyfnd' in loadmodule '/usr/lib/hpux32/libl.so.1'.
……
这是由于系统原来就装有flex,但不是最新版本,结果系统搜索到旧版本的libl.so.1而搜索不到新版本libl.so.1,这就是为什么我在前面要特别强调,export环境变量的时候,要确保新版本所在的路径在前面,并且要在flex的lib目录建立两个链接的原因了。
按照上述步骤和错误处理方法,在HP-UX下编译gSOAP应该是不成问题的,推而广之,在其它Unix下编译gSOAP也应该差不多。
最后一个小问题是,在HP-UX下要使用刚刚编译出来的soapcpp2生成存根程序,而不要使用前四节在linux目录下的soapcpp2
> ../../src/soapcpp2-C -L -x stock.h
更进一步,如果在 HP-UX 下,需要用到 libxml2 解析 SOAP 响应消息,除了编译源代码之外,也可以直接到下列网址下载基于 HP-UX 的二进制包:
http://hpux.connect.org.uk/hppd/hpux/Gnome/libxml2-2.7.7/
这个地址提供了几种版本的二进制包,下载之前应该在命令行输入 uname –a 查看一下当前的操作系统信息:
> uname -a
HP-UX hostname B.11.23 U ia64 0850816723 unlimited-user license
根据以上信息,应当下载 OperatingSystem 为 HP-UX 11i v2(HP-UX 11.23) , Architecture 为 Itanium2 的二进制包
下载的包是 libxml2-2.7.7-ia64-11.23.depot.gz 。把它解压后,有 root 权限的可以使用 HP-UX 专门的包管理工具安装。没有 root 权限也不要紧, depot 其实就是一个 tar 包,可以直接使用 tar 解包,把解包后的文件移动到合适的目录,再设置好 PATH 和 SHLIB_PATH 环境变量即可。