kubo / ruby-oci8

Ruby-oci8 - Oracle interface for ruby
Other
169 stars 75 forks source link

Error on Alpine linux (Was: Conflicting types for 'OCIEnvCreate') #179

Closed callebstrom closed 5 years ago

callebstrom commented 6 years ago

Hi!

I'm having issues building the native gem on Alpine 3.6 using Ruby 2.4.0 with the 12.2.0.1.0 of Oracle Instant Client (basic, sql plus and sdk).

I'm getting the following error:

Building native extensions.  This could take a while...
ERROR:  Error installing ruby-oci8:
    ERROR: Failed to build gem native extension.

    current directory: /usr/lib/ruby/gems/2.4.0/gems/ruby-oci8-2.2.5/ext/oci8
/usr/bin/ruby -r ./siteconf20171213-6-txz4q2.rb extconf.rb
checking for load library path... 
  LD_LIBRARY_PATH... 
    checking /opt/oracle/instantclient_12_2... yes
  /opt/oracle/instantclient_12_2/libclntsh.so.12.1 looks like an instant client.
checking for cc... ok
checking for gcc... yes
checking for LP64... yes
checking for sys/types.h... yes
checking for ruby header... ok
checking for OCIEnvCreate() in oci.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/usr/bin/$(RUBY_BASE_NAME)
    --with-instant-client
    --without-instant-client
/usr/lib/ruby/gems/2.4.0/gems/ruby-oci8-2.2.5/ext/oci8/oraconf.rb:1125:in `initialize': RuntimeError (RuntimeError)
    from /usr/lib/ruby/gems/2.4.0/gems/ruby-oci8-2.2.5/ext/oci8/oraconf.rb:267:in `new'
    from /usr/lib/ruby/gems/2.4.0/gems/ruby-oci8-2.2.5/ext/oci8/oraconf.rb:267:in `get'
    from extconf.rb:22:in `<main>'
---------------------------------------------------
Error Message:
  Could not compile with Oracle instant client.
  You may need to set a environment variable:
      LD_LIBRARY_PATH=/opt/oracle/instantclient_12_2
      export LD_LIBRARY_PATH

Backtrace:
  /usr/lib/ruby/gems/2.4.0/gems/ruby-oci8-2.2.5/ext/oci8/oraconf.rb:1125:in `initialize'
  /usr/lib/ruby/gems/2.4.0/gems/ruby-oci8-2.2.5/ext/oci8/oraconf.rb:267:in `new'
  /usr/lib/ruby/gems/2.4.0/gems/ruby-oci8-2.2.5/ext/oci8/oraconf.rb:267:in `get'
  extconf.rb:22:in `<main>'

This output seems to be indicating that OCIEnvCreate is not defined in oci.h however, when checking the mkmf.log this seems to be what's causing the issue:


collect2: error: ld returned 1 exit status
checked program was:
/* begin */
 1: #include "ruby.h"
 2: 
 3: #include <oci.h>
 4: 
 5: /*top*/
 6: extern int t(void);
 7: int main(int argc, char **argv)
 8: {
 9:   if (argc > 1000000) {
10:     printf("%p", &t);
11:   }
12: 
13:   return 0;
14: }
15: int t(void) { void ((*volatile p)()); p = (void ((*)()))OCIEnvCreate; return !p; }
/* end */

"gcc -o conftest -I/usr/include/ruby-2.4.0/x86_64-linux-musl -I/usr/include/ruby-2.4.0/ruby/backward -I/usr/include/ruby-2.4.0 -I. -Os -fomit-frame-pointer -fno-omit-frame-pointer -fno-strict-aliasing   -Os -fomit-frame-pointer -fno-omit-frame-pointer -fno-strict-aliasing -fPIC -I/opt/oracle/instantclient_12_2/sdk/include conftest.c  -L. -L/usr/lib -L. -Wl,--as-needed -fstack-protector -rdynamic -Wl,-export-dynamic     -L/usr/lib  -L/opt/oracle/instantclient_12_2 -Wl,-rpath,/opt/oracle/instantclient_12_2 -lclntsh -lruby  -L/usr/lib  -L/opt/oracle/instantclient_12_2 -Wl,-rpath,/opt/oracle/instantclient_12_2 -lclntsh -lpthread -lgmp -ldl -lcrypt -lm   -lc"
conftest.c:15:13: error: conflicting types for 'OCIEnvCreate'
 extern void OCIEnvCreate();
             ^~~~~~~~~~~~
In file included from /opt/oracle/instantclient_12_2/sdk/include/oci.h:3456:0,
                 from conftest.c:3:
/opt/oracle/instantclient_12_2/sdk/include/ociap.h:7223:9: note: previous declaration of 'OCIEnvCreate' was here
 sword   OCIEnvCreate (OCIEnv **envp, ub4 mode, void  *ctxp,
         ^~~~~~~~~~~~
checked program was:
/* begin */
 1: #include "ruby.h"
 2: 
 3: #include <oci.h>
 4: 
 5: /*top*/
 6: extern int t(void);
 7: int main(int argc, char **argv)
 8: {
 9:   if (argc > 1000000) {
10:     printf("%p", &t);
11:   }
12: 
13:   return 0;
14: }
15: extern void OCIEnvCreate();
16: int t(void) { OCIEnvCreate(); return 0; }
/* end */

It seems like as the definition is missing, the return type is set to int and therefore mismatches the actual implementation that is linked at runtime.

Am I barking up the wrong tree here? Have you encountered this behaviour before?

Appreciate any input on this as I've been struggling with this for over a day now, thanks!

Best regards, Calle

kubo commented 6 years ago

( I changed the title.)

Edited: I recommend that you use other linux distribution.

I have not heard that Oracle database interfaces for ruby, node-js, python, php and any other scripting languages run on alpine.

Alpine linux is based on musl libc. On the other hand Oracle client library depends on glibc. If all the following things succeed fortunately, you are the first person to run ruby-oci8 on alpine.

  1. Make sqlplus run on alpine. Glibc package is definitely required. I don't know whether it runs. I have not tried it.
  2. Install C compiler which can make glibc applications. I don't know whether such compiler is available on alpine.
  3. Compile ruby as a glibc application.
  4. Install ruby-oci8 by using above C compiler and ruby.

If the step 1 passes and others fail, compile ruby and ruby-oci8 on a glibc-based linux distribution and copy them to alpine.

callebstrom commented 6 years ago

@kubo Thanks for the quick reply. I just realized there was a similar issue submitted, sorry about that.

In my case though I actually had an Alpine container with glibc installed (running parallell to musl libc). Now that you mention it I suspect the issue is that ruby isn't actually compiled using glibc (I only tried compiling ruby-oci8).

I will try your suggested steps, thanks!

For future reference; thanks to @frol there is a great Alpine container with glibc (https://hub.docker.com/r/frolvlad/alpine-glibc/).