gliderlabs / docker-alpine

Alpine Linux Docker image. Win at minimalism!
http://gliderlabs.viewdocs.io/docker-alpine
BSD 2-Clause "Simplified" License
5.7k stars 528 forks source link

Cannot build native extensions for unf_ext gem #261

Closed cjbottaro closed 7 years ago

cjbottaro commented 7 years ago

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```
ncopa commented 7 years ago

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:

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.

ncopa commented 7 years ago

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.

cjbottaro commented 7 years ago

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.

ncopa commented 7 years ago

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.

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
cjbottaro commented 7 years ago

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

hpedrorodrigues commented 5 years ago

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
jspaleta commented 5 years ago

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

jspaleta commented 5 years ago

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