使用 gSOAP 开发实例 (6) 在 HP-UX 下编译 gSOAP-2.7.17
gSOAP 号称是跨平台的工具包,不过毕竟是属于 g 字头的,如果没有了一系列 GNU 组件的支持,在其他类 Unix 系统编译就会遇到不少困难。
gSOAP 的 README 说得也不是很清楚,只提到依赖于这些组件:
1. Automake tools (make and GNU m4) to configure and build
2. Bison http://www.gnu.org/software/bison or the alternative Yacc
3. Flex http://flex.sourceforge.net
4. OpenSSL (for optional HTTPS) http://www.openssl.org
5. Zlib (for optional compression) http://www.zlib.net
6. Pthreads or win32 threads (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 exit status
以 rpl_realloc 为关键字搜索,发现它出现在 configure 步骤产生的 config.h 当中
/* Define to rpl_realloc if the replacement 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)':
……
一大堆错误信息,其实是指向同一个错误: invalid conversion 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 load module '/usr/lib/hpux32/libl.so.1'.
/usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yyolsp' in load module '/usr/lib/hpux32/libl.so.1'.
/usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yyfnd' in load module '/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
根据以上信息,应当下载 Operating System 为 HP-UX 11i v2(HP-UX 11.23) , Architecture 为 Itanium 2 的二进制包
下载的包是 libxml2-2.7.7-ia64-11.23.depot.gz 。把它解压后,有 root 权限的可以使用 HP-UX 专门的包管理工具安装。没有 root 权限也不要紧, depot 其实就是一个 tar 包,可以直接使用 tar 解包,把解包后的文件移动到合适的目录,再设置好 PATH 和 SHLIB_PATH 环境变量即可。