ProC抱怨Linux上的未定义符号(CentOS 7.3)

时间:2017-09-04 06:47:11

标签: linux oracle gcc centos7

TLDR:在CentOS 7.3上从Oracle即时客户端12.2运行ProC似乎无法正常处理一个简单的输入文件。

显示问题的最小输入文件:

EXEC SQL BEGIN DECLARE SECTION;
     EXEC SQL INCLUDE oci.h;
EXEC SQL END DECLARE SECTION;

真正的文件显然包含我自己的项目标题,但最终它们会引入oci.h,这是即时客户端SDK标头之一,这似乎是构建问题的来源。

调用ProC:

以下脚本演示了该问题(同样,真实情况的简化版本):

#!/bin/sh

export ORACLE_HOME=/some/path/instantclient_12_2
export ORACLE_SID=SomeSID
export PATH=/various/paths:${ORACLE_HOME}:${ORACLE_HOME}/sdk:${ORACLE_HOME}/bin:/some/more/paths/like:usr/bin:
export LD_LIBRARY_PATH=${ORACLE_HOME}:${ORACLE_HOME}/lib32:${ORACLE_HOME}/lib

${ORACLE_HOME}/sdk/proc \
  LTYPE=LONG \
  PARSE=PARTIAL \
  MODE=ORACLE \
  CODE=ANSI_C \
  iname=foo.pc

Oracle配置:

我的pcscfg.cfg文件的内容如下所示:

sys_include=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
sys_include=/usr/include
include=/some/path/instantclient_12_2/sdk/include

我也尝试了各种重新排序,切换includesys_include,但似乎所有人都表现出同样的行为。如各种在线参考文献中所示,添加define=__x86_64__没有任何区别。我已经选择扩展上面的$ORACLE_PATH以使示例更清晰。

示例错误输出:

使用上面定义的输入文件会导致输出出现如下错误(截断以帮助集中讨论):

Pro*C/C++: Release 12.2.0.1.0 - Production on Mon Sep 4 16:19:45 2017

Copyright (c) 1982, 2017, Oracle and/or its affiliates.  All rights reserved.

System default option values taken from: /some/path/instantclient_12_2/precomp/admin/pcscfg.cfg

Syntax error at line 46, column 1, file /usr/include/bits/byteswap-16.h:
Error at line 46, column 1 in file /usr/include/bits/byteswap-16.h
{
1
PCC-S-02201, Encountered the symbol "{" when expecting one of the following:

   ; , = ( [

它抱怨的行内容如下:

static __inline unsigned short int
__bswap_16 (unsigned short int __bsx)
{                                       // <---- this is line 46
  return __bswap_constant_16 (__bsx);
}

如果我在#include <stdlib.h>行之前插入EXEC SQL BEGIN DECLARE SECTION,则错误消息会更改为:

Syntax error at line 265, column 50, file /some/path/instantclient_12_2/sdk/include/ociextp.h:
Error at line 265, column 50 in file /some/path/instantclient_12_2/sdk/include/ociextp.h
void  *ociepacm(OCIExtProcContext *with_context, size_t amount);
.................................................1
PCC-S-02201, Encountered the symbol "size_t" when expecting one of the following
:

   ... auto, char, const, double, enum, float, int, long,
   ulong_varchar, OCIBFileLocator OCIBlobLocator,
   OCIClobLocator, OCIDateTime, OCIExtProcContext, OCIInterval,
   OCIRowid, OCIDate, OCINumber, OCIRaw, OCIString, register,
   short, signed, sql_context, sql_cursor, static, struct,
   union, unsigned, utext, uvarchar, varchar, void, volatile,
   a typedef name, exec oracle, exec oracle begin, exec,
   exec sql, exec sql begin, exec sql type, exec sql var,
The symbol "enum," was substituted for "size_t" to continue.

这个更有趣,因为我已经更仔细地追踪逻辑,甚至强迫size_t通过各种方式定义,我仍然得到上述错误。但是,如果我将ProC调用更改为使用PARSE=FULL,则会成功。不幸的是,这会导致实际代码出现其他问题,并且这些问题与此问题具有相似的性质(即编译器头上的扼流圈应该由编译器头定义)。

进一步评论:

在线查看各种解决方案,这些问题通常是错误设置包含搜索路径的结果,但我已从输出列表中验证确实找到了正确的标头。就好像有一些编译器定义缺少GCC通常会提供的,但ProC不提供。有许多其他相关的例子支持这个理论,在__INT_LEAST8_TYPE__未知的事情上给出了错误(据我所知,GCC在内部而不是在任何标题中明确定义)。

具体问题:

ProC似乎没有正确处理系统编译器头文件。知道为什么甚至是进一步的事情来帮助诊断根本原因?

3 个答案:

答案 0 :(得分:2)

我已经能够正确编译我的应用程序,我发现即使通过将命令“gcc -dM -E - &lt; / dev / null”的输出添加到头文件中解决了一些编译问题并将其包含在每个Pro * C源文件中,因此引入了新的编译问题,并尝试再次解决这些新问题,以便其他方法无处可去。

最后,我从头开始,只包括proc编译器真正需要的#defines。另外,我必须重新安排proc配置文件中的路径$ {ORACLE_HOME} /precomp/admin/pcscfg.cfg

这就是现在的样子:

sys_include=$ORACLE_HOME/precomp/public
sys_include=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
sys_include=/usr/local/include
sys_include=/usr/include
sys_include=/usr/include/linux
ltype=short
define=__x86_64__

原因是gcc include目录中有几个文件也存在于某些其他目录中,但是那些假设所有这些gcc内部定义都被设置了。系统包含位于gcc include目录中的文件有时与下面列出的通常include目录中的文件有很大不同,看起来proc在解析位于gcc 4.8.5目录中的文件时遇到的困难要少得多。

接下来,我创建的包含文件和#include现在被阻塞的每个源文件看起来都是这样的:

#ifndef __GCC4_INTERNAL_DEFINES_H__
#define __GCC4_INTERNAL_DEFINES_H__

/* Proceed only when using the Oracle Pro*C compiler on RHEL7 */
#ifdef DB_PRE_COMP
#ifdef OS_IS_RHEL7

/* These are some of the defines that gcc4 sets by itself. The Pro*C precompiler
   does not know them and they are needed in order to correctly parse several
   system header files. Full list of gcc4 internal defines may be obtained with
   the following command: gcc -dM -E - < /dev/null */
#define __INT_LEAST8_TYPE__ signed char
#define __INT_LEAST16_TYPE__ short int
#define __INT_LEAST32_TYPE__ int
#define __INT_LEAST64_TYPE__ long int
#define __UINT_LEAST8_TYPE__ unsigned char
#define __UINT_LEAST16_TYPE__ short unsigned int
#define __UINT_LEAST32_TYPE__ unsigned int
#define __UINT_LEAST64_TYPE__ long unsigned int
#define __INT_FAST8_TYPE__ signed char
#define __INT_FAST16_TYPE__ long int
#define __INT_FAST32_TYPE__ long int
#define __INT_FAST64_TYPE__ long int
#define __UINT_FAST8_TYPE__ unsigned char
#define __UINT_FAST16_TYPE__ long unsigned int
#define __UINT_FAST32_TYPE__ long unsigned int
#define __UINT_FAST64_TYPE__ long unsigned int
#define __INTMAX_TYPE__ long int
#define __UINTMAX_TYPE__ long unsigned int

#include </usr/include/stdint.h>

#endif /* OS_IS_RHEL7 */
#endif /* DB_PRE_COMP */

#endif /* __GCC4_INTERNAL_DEFINES_H__ */

令我感到宽慰的是,我已经通过这些更新获得了所有内容。为了完整起见,proc使用parse = full选项执行,这也是我以前在RHEL6下做的以及我的应用程序显然需要的东西;作为我努力进行编译的一部分,我尝试了部分选项,但这没有任何区别,它仍然被扼杀。

答案 1 :(得分:1)

当您包含与系统标题同名的标题(包括stdint.h)时,就会发生这种情况。

来自Pro*C manual

  

预编译器按以下顺序搜索目录:

     
      
  • 当前目录

  •   
  • 在SYS_INCLUDE预编译器选项中指定的系统目录

  •   
  • INCLUDE选项指定的目录,按照其输入顺序

  •   
  • 标准头文件的内置目录

  •   

例如,您可以为项目创建头文件db.h

如果您的系统中已安装Berkeley DB,则它将为系统提供自己的db.h

只要您的db.h与预处理的.pc文件位于同一文件夹中,并且您不必传递include=your_include_folder选项即可进行操作。

如果您确实为包含文件设置了单独的文件夹,则必须将include=../include选项传递给proc,并且Berkeley的db.h(而不是项目中的db.h文件)就位。

答案 2 :(得分:1)

对于我来说,我可以通过以下两种方法之一来解决此问题:

define=ORASYS_TYPES添加到${ORACLE_HOME}/precomp/admin/pcscfg.cfg

添加DEFINE=ORASYS_TYPES作为处理的选项。

oci.h包含<oratypes.h>

oratypes.h具有:

#ifndef ORASYS_TYPES
# include <sys/types.h>
# define ORASYS_TYPES
#endif