kubo / ruby-oci8

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

Compile error on Alpine Linux #129

Closed gacha closed 8 years ago

gacha commented 8 years ago

Hi, Im trying to compile ruby-oci8 on a alpine linux with ruby 2.2.1. I have unzipped these files:

instantclient-basic-linux.x64-12.1.0.2.0.zip
instantclient-sdk-linux.x64-12.1.0.2.0.zip
instantclient-sqlplus-linux.x64-12.1.0.2.0.zip

into /opt/oracle and have set LD_LIBRARY_PATH to /opt/oracle/instantclient_12_1.

Output:

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

    current directory: /usr/local/bundle/gems/ruby-oci8-2.2.1/ext/oci8
/usr/local/bin/ruby -r ./siteconf20160422-77-1tov4gz.rb extconf.rb
checking for load library path...
  LD_LIBRARY_PATH...
    checking /opt/oracle/instantclient_12_1... yes
  /opt/oracle/instantclient_12_1/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/local/bin/$(RUBY_BASE_NAME)
        --with-instant-client
        --without-instant-client
/usr/local/bundle/gems/ruby-oci8-2.2.1/ext/oci8/oraconf.rb:1168:in `initialize': RuntimeError (RuntimeError)
        from /usr/local/bundle/gems/ruby-oci8-2.2.1/ext/oci8/oraconf.rb:318:in `new'
        from /usr/local/bundle/gems/ruby-oci8-2.2.1/ext/oci8/oraconf.rb:318: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_1
      export LD_LIBRARY_PATH

Backtrace:
  /usr/local/bundle/gems/ruby-oci8-2.2.1/ext/oci8/oraconf.rb:1168:in `initialize'
  /usr/local/bundle/gems/ruby-oci8-2.2.1/ext/oci8/oraconf.rb:318:in `new'
  /usr/local/bundle/gems/ruby-oci8-2.2.1/ext/oci8/oraconf.rb:318:in `get'
  extconf.rb:22:in `<main>'

Last lines of mkmf.log:

/opt/oracle/instantclient_12_1/libclntsh.so: undefined reference to `bindresvport@GLIBC_2.2.5'
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 0; }
/* end */

"gcc -o conftest -I/usr/local/include/ruby-2.2.0/x86_64-linux -I/usr/local/include/ruby-2.2.0/ruby/backward -I/usr/local/include/ruby-2.2.0 -I.     -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -Wdeprecated-declarations -Wno-packed-bitfield-compat -I/opt/oracle/instantclient_12_1/sdk/include conftest.c  -L. -L/usr/local/lib -Wl,-R/usr/local/lib -L. -fstack-protector -rdynamic -Wl,-export-dynamic     -L/usr/local/lib  -L/opt/oracle/instantclient_12_1 -Wl,-rpath,/opt/oracle/instantclient_12_1 -lclntsh -Wl,-R/usr/local/lib -L/usr/local/lib -lruby-static  -L/usr/local/lib  -L/opt/oracle/instantclient_12_1 -Wl,-rpath,/opt/oracle/instantclient_12_1 -lclntsh -lpthread -ldl -lcrypt -lm   -lc"
conftest.c: In function 't':
conftest.c:15:15: error: too few arguments to function 'OCIEnvCreate'
 int t(void) { OCIEnvCreate(); return 0; }
               ^
In file included from /opt/oracle/instantclient_12_1/sdk/include/oci.h:3488:0,
                 from conftest.c:3:
/opt/oracle/instantclient_12_1/sdk/include/ociap.h:7134:9: note: declared 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: int t(void) { OCIEnvCreate(); return 0; }
/* end */

--------------------

Env:

bash-4.3# env
HOSTNAME=326cc83346be
GEM_HOME=/usr/local/bundle
TERM=xterm
LD_LIBRARY_PATH=/opt/oracle/instantclient_12_1
BUNDLE_SILENCE_ROOT_WARNING=1
BUNDLE_APP_CONFIG=/usr/local/bundle
PATH=/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUBY_DOWNLOAD_SHA256=b6eff568b48e0fda76e5a36333175df049b204e91217aa32a65153cc0cdcb761
PWD=/myapp
RUBY_MAJOR=2.2
RUBYGEMS_VERSION=2.6.3
BUNDLE_BIN=/usr/local/bundle/bin
SHLVL=1
HOME=/root
BUNDLE_PATH=/usr/local/bundle
RUBY_VERSION=2.2.4
BUNDLER_VERSION=1.11.2
_=/usr/bin/env

And yes the link to libclntsh.so is correct:

bash-4.3# ls -la /opt/oracle/instantclient_12_1/
total 193348
drwxrwxr-x    3 root     root          4096 Apr 22 13:54 .
drwxr-xr-x    4 root     root          4096 Apr 22 13:54 ..
-rw-rw-r--    1 root     root           440 Jul  7  2014 BASIC_README
-rw-rw-r--    1 root     root           444 Jul  7  2014 SQLPLUS_README
-rwxrwxr-x    1 root     root         29404 Jul  7  2014 adrci
-rwxrwxr-x    1 root     root         43944 Jul  7  2014 genezi
-r-xr-xr-x    1 root     root           342 Jul  7  2014 glogin.sql
lrwxrwxrwx    1 root     root            17 Apr 22 13:54 libclntsh.so -> libclntsh.so.12.1
-rwxrwxr-x    1 root     root      58793741 Jul  7  2014 libclntsh.so.12.1
-rwxrwxr-x    1 root     root       6990875 Jul  7  2014 libclntshcore.so.12.1
-r-xr-xr-x    1 root     root       1768370 Jul  7  2014 libipc1.so
-r-xr-xr-x    1 root     root        544150 Jul  7  2014 libmql1.so
-r-xr-xr-x    1 root     root       6213011 Jul  7  2014 libnnz12.so
-rwxrwxr-x    1 root     root       2576030 Jul  7  2014 libocci.so.12.1
-rwxrwxr-x    1 root     root     109549133 Jul  7  2014 libociei.so
-r-xr-xr-x    1 root     root        156353 Jul  7  2014 libocijdbc12.so
-r-xr-xr-x    1 root     root        337137 Jul  7  2014 libons.so
-rwxrwxr-x    1 root     root        118491 Jul  7  2014 liboramysql12.so
-r-xr-xr-x    1 root     root       1546540 Jul  7  2014 libsqlplus.so
-r-xr-xr-x    1 root     root       1564082 Jul  7  2014 libsqlplusic.so
-r--r--r--    1 root     root       3692096 Jul  7  2014 ojdbc6.jar
-r--r--r--    1 root     root       3698857 Jul  7  2014 ojdbc7.jar
drwxrwxr-x    5 root     root          4096 Jul  7  2014 sdk
-r-xr-xr-x    1 root     root          9581 Jul  7  2014 sqlplus
-rwxrwxr-x    1 root     root        227410 Jul  7  2014 uidrvci
-rw-rw-r--    1 root     root         71202 Jul  7  2014 xstreams.jar
kubo commented 8 years ago

Could you run sqlplus on the alpine linux? If it works, could you run sqlplus after setting export LD_BIND_NOW=1?

/opt/oracle/instantclient_12_1/libclntsh.so: undefined reference to `bindresvport@GLIBC_2.2.5'

libclntsh.so refers bindresvport, which exists in glibc (GNU C Library) 2.2.5 or upper. However it doesn't exist in your system. IMO, musl libc used by the alpine linux doesn't implement bindresvport.

kubo commented 8 years ago

@gacha I changed the title.

Linux distributions usually use glibc as a C library. Oracle instant client was build for such distributions. However Alpine Linux uses musl libc in place of glibc to make the distribution size small.

In this musl libc FAQ

At present, some glibc-linked shared libraries can be loaded with musl, ...

Oracle instant libraries isn't included in such libraries because of lack of a function. If you want to use ruby-oci8 on Apline Linux, you need to request musl libc developers to implement the missing function (and others if necessary) and then request Alpine Linux to include fixed musl libc.

In this musl libc FAQ

... but all but the simplest glibc-linked applications will fail if musl is dropped-in in place of /lib/ld-linux.so.2.

sqlplus fails because musl is dropped-in in place of /lib/ld-linux.so.2 on Alpine Linux.

kubo commented 8 years ago

I tried to compile ruby-oci8 by myself and looked at full mkmf.log. IMO, it is impossible to use Oracle client library on Alpine Linux as long as Alpine Linux lacks the glibc dynamic loader by design.

gacha commented 8 years ago

Hi, thanks for investigating, now I tried with the docker default ruby image - debian, now it get's by the OCIEnvCreate() but fails in another place:

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    /usr/local/bin/ruby -r ./siteconf20160425-11-1poeet9.rb extconf.rb
checking for load library path...
  LD_LIBRARY_PATH...
    checking /opt/oracle/instantclient_12_1... yes
  /opt/oracle/instantclient_12_1/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... yes
checking for OCI_MAJOR_VERSION in oci.h... *** 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/local/bin/$(RUBY_BASE_NAME)
        --with-instant-client
        --without-instant-client
/usr/local/lib/ruby/2.2.0/mkmf.rb:704:in `Integer': can't convert nil into Integer (TypeError)
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:704:in `block in try_constant'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:408:in `popen'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:408:in `block in xpopen'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:321:in `open'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:401:in `xpopen'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:703:in `try_constant'
        from extconf.rb:34:in `block in <main>'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:917:in `block in checking_for'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:351:in `block (2 levels) in postpone'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:321:in `open'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:351:in `block in postpone'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:321:in `open'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:347:in `postpone'
        from /usr/local/lib/ruby/2.2.0/mkmf.rb:916:in `checking_for'
        from extconf.rb:33:in `<main>'

extconf failed, exit code 1

Gem files will remain installed in /usr/local/bundle/gems/ruby-oci8-2.2.2 for inspection.
Results logged to /usr/local/bundle/extensions/x86_64-linux/2.2.0-static/ruby-oci8-2.2.2/gem_make.out
Installing sass 3.4.22
Installing libv8 3.16.14.13
An error occurred while installing ruby-oci8 (2.2.2), and Bundler cannot
continue.
Make sure that `gem install ruby-oci8 -v '2.2.2'` succeeds before bundling.

Here is my Dockerfile:

FROM ruby:2.2.0
RUN apt-get update -qq && apt-get install -y build-essential wget unzip

RUN mkdir -p /opt/oracle
ADD *.zip /opt/oracle/
RUN cd /opt/oracle && unzip -q \*.zip
RUN cd /opt/oracle/instantclient_12_1 && ln -s libclntsh.so.12.1 libclntsh.so
ENV LD_LIBRARY_PATH /opt/oracle/instantclient_12_1

RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
# ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install --jobs=4
ADD . /myapp
kubo commented 8 years ago

Could you put mkmf.log to https://gist.github.com/?

gacha commented 8 years ago

Here you go https://gist.github.com/gacha/ad70623939bb94cfb441f70353af4538

kubo commented 8 years ago

./conftest: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory

You need to install libaio.so.1.

apt-get install libaio1
gacha commented 8 years ago

Thanks, it works, should spot that by myself.