Docker-alpine: Cannot build native extensions for unf_ext gem

Created on 7 Mar 2017  路  8Comments  路  Source: gliderlabs/docker-alpine

Hello. I'm not sure where to ask for help on this, but I can't a lot of Ruby gems with native extensions. unf_ext is just one example, but I think they all error with similar messages.

# gem install unf_ext --no-ri --no-rdoc
Fetching: unf_ext-0.0.7.2.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing unf_ext:
    ERROR: Failed to build gem native extension.

    current directory: /opt/rubies/ruby-2.3.3/lib/ruby/gems/2.3.0/gems/unf_ext-0.0.7.2/ext/unf_ext
/opt/rubies/ruby-2.3.3/bin/ruby -r ./siteconf20170307-8-129b0u7.rb extconf.rb
checking for main() in -lstdc++... yes
creating Makefile

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /opt/rubies/ruby-2.3.3/lib/ruby/gems/2.3.0/extensions/x86_64-linux/2.3.0-static/unf_ext-0.0.7.2/mkmf.log

current directory: /opt/rubies/ruby-2.3.3/lib/ruby/gems/2.3.0/gems/unf_ext-0.0.7.2/ext/unf_ext
make "DESTDIR=" clean

current directory: /opt/rubies/ruby-2.3.3/lib/ruby/gems/2.3.0/gems/unf_ext-0.0.7.2/ext/unf_ext
make "DESTDIR="
compiling unf.cc
cc1plus: warning: command line option '-Wdeclaration-after-statement' is valid for C/ObjC but not for C++
cc1plus: warning: command line option '-Wimplicit-function-declaration' is valid for C/ObjC but not for C++
In file included from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/defines.h:68:0,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/ruby.h:36,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby.h:33,
                 from unf.cc:3:
/opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/missing.h:166:29: error: 'int isinf(double)' conflicts with a previous declaration
 RUBY_EXTERN int isinf(double);
                             ^
In file included from /usr/include/c++/6.2.1/math.h:36:0,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/missing.h:23,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/defines.h:68,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/ruby.h:36,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby.h:33,
                 from unf.cc:3:
/usr/include/c++/6.2.1/cmath:618:3: note: previous declaration 'constexpr bool std::isinf(double)'
   isinf(double __x)
   ^~~~~
In file included from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/defines.h:68:0,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/ruby.h:36,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby.h:33,
                 from unf.cc:3:
/opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/missing.h:173:29: error: 'int isnan(double)' conflicts with a previous declaration
 RUBY_EXTERN int isnan(double);
                             ^
In file included from /usr/include/c++/6.2.1/math.h:36:0,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/missing.h:23,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/defines.h:68,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby/ruby.h:36,
                 from /opt/rubies/ruby-2.3.3/include/ruby-2.3.0/ruby.h:33,
                 from unf.cc:3:
/usr/include/c++/6.2.1/cmath:643:3: note: previous declaration 'constexpr bool std::isnan(double)'
   isnan(double __x)
   ^~~~~
make: *** [Makefile:207: unf.o] Error 1

make failed, exit code 2

Gem files will remain installed in /opt/rubies/ruby-2.3.3/lib/ruby/gems/2.3.0/gems/unf_ext-0.0.7.2 for inspection.
Results logged to /opt/rubies/ruby-2.3.3/lib/ruby/gems/2.3.0/extensions/x86_64-linux/2.3.0-static/unf_ext-0.0.7.2/gem_make.out

And here's my Dockerfile:

```
FROM alpine:3.5

RUN apk --no-cache add build-base
RUN apk --no-cache add git
RUN apk --no-cache add openssh-client
RUN apk --no-cache add libressl libressl-dev
RUN apk --no-cache add bash
RUN apk --no-cache add readline-dev
RUN apk --no-cache add zlib-dev
RUN apk --no-cache add linux-headers

ADD ruby-install-0.6.1.tar.gz /
RUN cd ruby-install-0.6.1 && make install
RUN rm -rf ruby-install-0.6.1
RUN ruby-install ruby 2.3.3 -- --disable-install-rdoc
ENV PATH /opt/rubies/ruby-2.3.3/bin:$PATH```

Most helpful comment

I get this error when I try to reproduce:
Step 10/14 : ADD ruby-install-0.6.1.tar.gz / lstat ruby-install-0.6.1.tar.gz: no such file or directory

However, when I use the ruby package from alpine it works:
````Dockerfile
FROM alpine:3.5

RUN apk add --no-cache build-base ruby ruby-dev
RUN gem install unf_ext --no-ri --no-rdoc
````

The ruby version is ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-linux-musl]

So my guess is that there are some bug in ruby-install-0.6.1.tar.gz. You should report it to who ever made that tarball.

All 8 comments

I get this error when I try to reproduce:
Step 10/14 : ADD ruby-install-0.6.1.tar.gz / lstat ruby-install-0.6.1.tar.gz: no such file or directory

However, when I use the ruby package from alpine it works:
````Dockerfile
FROM alpine:3.5

RUN apk add --no-cache build-base ruby ruby-dev
RUN gem install unf_ext --no-ri --no-rdoc
````

The ruby version is ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-linux-musl]

So my guess is that there are some bug in ruby-install-0.6.1.tar.gz. You should report it to who ever made that tarball.

You could also try install those dependencies before building ruby:
gmp-dev zlib-dev libressl-dev gdbm-dev db-dev readline-dev libffi-dev coreutils yaml-dev linux-headers autoconf

Those are the ones we use for the ruby package on alpine.

Hello. Here is my revised Dockerfile. It should run from your computer now (it downloads ruby source from ruby-lang.org). Still fails, even after adding those packages.

FROM alpine:3.5

RUN apk --no-cache add build-base
RUN apk --no-cache add git
RUN apk --no-cache add openssh-client
RUN apk --no-cache add libressl libressl-dev
RUN apk --no-cache add bash
RUN apk --no-cache add readline-dev
RUN apk --no-cache add zlib-dev
RUN apk --no-cache add linux-headers
RUN apk --no-cache add libffi-dev
RUN apk --no-cache add gmp-dev
RUN apk --no-cache add gmp-dev zlib-dev libressl-dev gdbm-dev db-dev readline-dev libffi-dev coreutils yaml-dev linux-headers autoconf

ADD https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz /
RUN tar xzf ruby-2.3.3.tar.gz

WORKDIR /ruby-2.3.3
RUN ./configure --disable-install-doc
RUN make
RUN make install

RUN gem install unf_ext --no-ri --no-rdoc

ENTRYPOINT /bin/bash

Thank you for the help.

This is an upstream bug. The configure script does not detect isnan/isinf as macros.

You should report this upstream to ruby.

The workaround is to set ac_cv_func_isnan=yes and ac_cv_func_isinf=yes when running configure.

````Dockerfile
FROM alpine:3.5

RUN apk --no-cache add build-base
RUN apk --no-cache add git
RUN apk --no-cache add openssh-client
RUN apk --no-cache add libressl libressl-dev
RUN apk --no-cache add bash
RUN apk --no-cache add readline-dev
RUN apk --no-cache add zlib-dev
RUN apk --no-cache add linux-headers
RUN apk --no-cache add libffi-dev
RUN apk --no-cache add gmp-dev
RUN apk --no-cache add gmp-dev zlib-dev libressl-dev gdbm-dev db-dev readline-dev libffi-dev coreutils yaml-dev linux-headers autoconf

ADD https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz /
RUN tar xzf ruby-2.3.3.tar.gz

WORKDIR /ruby-2.3.3

the configure script does not detect isnan/isinf as macros

RUN ac_cv_func_isnan=yes ac_cv_func_isinf=yes \
./configure --disable-install-doc
RUN make
RUN make install

RUN gem install unf_ext --no-ri --no-rdoc

ENTRYPOINT /bin/bash
````

Thank you very much for your time helping me with this.

Based on @ncopa's response and on docker-alpine-rbenv.

This solved on Alpine 3.8:

FROM alpine:3.8

RUN apk add --update bash \
                     git \
                     build-base \
                     linux-headers \
                     readline-dev \
                     openssl-dev \
                     zlib-dev \
                     gmp-dev \
                     imagemagick-dev \
                     libffi-dev \
                     libffi-dev \
                     yaml-dev \
      && rm -rf /var/cache/apk/*

ENV RBENV_ROOT '/usr/local/rbenv'
ENV PATH ${RBENV_ROOT}/shims:${RBENV_ROOT}/bin:${PATH}
ENV RUBY_VERSION '2.3.3'
ENV CONFIGURE_OPTS '--disable-install-doc'

RUN git clone --depth 1 git://github.com/sstephenson/rbenv.git ${RBENV_ROOT} \
      &&  git clone --depth 1 https://github.com/sstephenson/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build \
      &&  git clone --depth 1 git://github.com/jf/rbenv-gemset.git ${RBENV_ROOT}/plugins/rbenv-gemset \
      && ${RBENV_ROOT}/plugins/ruby-build/install.sh

RUN echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh 

RUN ac_cv_func_isnan=yes ac_cv_func_isinf=yes \
      rbenv install ${RUBY_VERSION} \
      && rbenv global ${RUBY_VERSION}

RUN gem install bundler
RUN gem install unf_ext

ENTRYPOINT /bin/bash

Not sure how to fix this with ruby-install... it doesn't offer a configure step.. just a make install...

Found a sufficient set of changes. Might not be optimal, but allows me to build the sensu-plugins-http asset from inside the alpine container.
Snippet:

RUN apk add linux-headers build-base zlib-dev openssl-dev wget sudo bash bash-doc bash-completion
RUN wget -O ruby-install-0.7.0.tar.gz https://github.com/postmodern/ruby-install/archive/v0.7.0.tar.gz && \
  tar -xzvf ruby-install-0.7.0.tar.gz && \
  cd ruby-install-0.7.0/ 
RUN cd ruby-install-0.7.0/ && ac_cv_func_isnan=yes ac_cv_func_isinf=yes make install 
RUN  ac_cv_func_isnan=yes ac_cv_func_isinf=yes ruby-install ruby ${RUBY_VERSION} -- --enable-load-relative --disable-install-doc && \
  PATH=$PATH:/opt/rubies/ruby-${RUBY_VERSION}/bin/ && gem install --no-ri --no-rdoc ffi
Was this page helpful?
0 / 5 - 0 ratings