Allowing for creation of pre-compiled gems, using rack-compiler-dock.

pull/4936/head
Nicolas "Pixel" Noble 9 years ago
parent b8e2f9c02a
commit cb287a11df
  1. 2
      .gitignore
  2. 23
      Rakefile
  3. 21
      grpc.gemspec
  4. 7
      src/ruby/lib/grpc.rb
  5. 21
      templates/grpc.gemspec.template
  6. 109
      third_party/rake-compiler-dock/Dockerfile
  7. 22
      third_party/rake-compiler-dock/LICENSE.txt
  8. 1
      third_party/rake-compiler-dock/README.md
  9. 14
      third_party/rake-compiler-dock/build/patches/rake-compiler-0.9.5/without-exts.diff
  10. 2
      third_party/rake-compiler-dock/build/patches/ruby-1.8.7-p374/nop.patch
  11. 13
      third_party/rake-compiler-dock/build/patches/ruby-1.9.3/no_sendfile.patch
  12. 2
      third_party/rake-compiler-dock/build/patches/ruby-1.9.3/nop.patch
  13. 12
      third_party/rake-compiler-dock/build/patches/ruby-2.3.0/no_sendfile.patch
  14. 12
      third_party/rake-compiler-dock/build/runas
  15. 43
      third_party/rake-compiler-dock/build/sigfw.c
  16. 30
      third_party/rake-compiler-dock/build/strip_wrapper
  17. 1
      third_party/rake-compiler-dock/build/sudoers

2
.gitignore vendored

@ -56,7 +56,7 @@ out
.ycm_extra_conf.py
# XCode
build/
^build/
*.pbxuser
!default.pbxuser
*.mode1v3

@ -10,11 +10,18 @@ RuboCop::RakeTask.new(:rubocop) do |task|
task.patterns = ['src/ruby/{lib,spec}/**/*.rb']
end
spec = Gem::Specification.load('grpc.gemspec')
Gem::PackageTask.new(spec) do |pkg|
end
# Add the extension compiler task
Rake::ExtensionTask.new 'grpc' do |ext|
Rake::ExtensionTask.new('grpc', spec) do |ext|
ext.source_pattern = '**/*.{c,h}'
ext.ext_dir = File.join('src', 'ruby', 'ext', 'grpc')
ext.lib_dir = File.join('src', 'ruby', 'lib', 'grpc')
ext.cross_compile = true
ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
end
# Define the test suites
@ -51,6 +58,20 @@ namespace :suite do
end
end
desc 'Build the gem file under rake_compiler_dock'
task 'gem:windows' do
require 'digest'
require 'rake_compiler_dock'
version = Digest::SHA1.file('third_party/rake-compiler-dock/Dockerfile').hexdigest
image_name = 'grpc/rake-compiler-dock:' + version
cmd = "docker build -t #{image_name} third_party/rake-compiler-dock"
puts cmd
system cmd
exit 1 unless $? == 0
ENV['RAKE_COMPILER_DOCK_IMAGE'] = image_name
RakeCompilerDock.sh "bundle && rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.6:2.0.0"
end
# Define dependencies between the suites.
task 'suite:wrapper' => [:compile, :rubocop]
task 'suite:idiomatic' => 'suite:wrapper'

@ -16,7 +16,7 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 2.0.0'
s.requirements << 'libgrpc ~> 0.11.0 needs to be installed'
s.files = %w( Rakefile Makefile )
s.files = %w( Makefile )
s.files += %w( etc/roots.pem )
s.files += Dir.glob('src/ruby/bin/**/*')
s.files += Dir.glob('src/ruby/ext/**/*')
@ -33,16 +33,17 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'rake-compiler', '~> 0.9'
s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0'
s.add_development_dependency 'signet', '~>0.7.0'
s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'rake-compiler', '~> 0.9'
s.add_development_dependency 'rake-compiler-dock', '~> 0.5'
s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0'
s.add_development_dependency 'signet', '~> 0.7.0'
s.extensions = %w(src/ruby/ext/grpc/extconf.rb)

@ -32,8 +32,13 @@ unless ENV['GRPC_DEFAULT_SSL_ROOTS_FILE_PATH']
ENV['GRPC_DEFAULT_SSL_ROOTS_FILE_PATH'] = ssl_roots_path
end
begin
require "grpc/#{RUBY_VERSION.sub(/\.\d$/, '')}/grpc"
rescue LoadError
require 'grpc/grpc'
end
require 'grpc/errors'
require 'grpc/grpc'
require 'grpc/logconfig'
require 'grpc/notifier'
require 'grpc/version'

@ -18,7 +18,7 @@
s.required_ruby_version = '>= 2.0.0'
s.requirements << 'libgrpc ~> 0.11.0 needs to be installed'
s.files = %w( Rakefile Makefile )
s.files = %w( Makefile )
s.files += %w( etc/roots.pem )
s.files += Dir.glob('src/ruby/bin/**/*')
s.files += Dir.glob('src/ruby/ext/**/*')
@ -35,16 +35,17 @@
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'rake-compiler', '~> 0.9'
s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0'
s.add_development_dependency 'signet', '~>0.7.0'
s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'rake-compiler', '~> 0.9'
s.add_development_dependency 'rake-compiler-dock', '~> 0.5'
s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0'
s.add_development_dependency 'signet', '~> 0.7.0'
s.extensions = %w(src/ruby/ext/grpc/extconf.rb)

@ -0,0 +1,109 @@
FROM ubuntu:14.04
RUN apt-get -y update && \
apt-get install -y curl git-core mingw-w64 xz-utils build-essential wget unzip
RUN mkdir -p /opt/mingw && \
curl -SL http://downloads.sourceforge.net/mingw-w64/i686-w64-mingw32-gcc-4.7.2-release-linux64_rubenvb.tar.xz | \
tar -xJC /opt/mingw && \
echo "export PATH=\$PATH:/opt/mingw/mingw32/bin" >> /etc/rubybashrc
RUN mkdir -p /opt/mingw && \
curl -SL http://downloads.sourceforge.net/mingw-w64/x86_64-w64-mingw32-gcc-4.7.2-release-linux64_rubenvb.tar.xz | \
tar -xJC /opt/mingw && \
echo "export PATH=\$PATH:/opt/mingw/mingw64/bin" >> /etc/rubybashrc
# Add "rvm" as system group, to avoid conflicts with host GIDs typically starting with 1000
RUN groupadd -r rvm && useradd -r -g rvm -G sudo -p "" --create-home rvm && \
echo "source /etc/profile.d/rvm.sh" >> /etc/rubybashrc
USER rvm
# install rvm, RVM 1.26.0+ has signed releases, source rvm for usage outside of package scripts
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3 && \
(curl -L http://get.rvm.io | sudo bash -s stable) && \
bash -c " \
source /etc/rubybashrc && \
rvmsudo rvm cleanup all "
# Import patch files for ruby and gems
COPY build/patches /home/rvm/patches/
ENV BASH_ENV /etc/rubybashrc
# install rubies and fix permissions on
RUN bash -c " \
export CFLAGS='-s -O3 -fno-fast-math -fPIC' && \
for v in 2.3.0 ; do \
rvm install \$v --patch \$(echo ~/patches/ruby-\$v/* | tr ' ' ','); \
done && \
rvm cleanup all && \
find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
# Install rake-compiler and typical gems in all Rubies
# do not generate documentation for gems
RUN echo "gem: --no-ri --no-rdoc" >> ~/.gemrc && \
bash -c " \
rvm all do gem install bundler rake-compiler hoe mini_portile rubygems-tasks json && \
rvm 2.3.0 do gem install mini_portile2 && \
find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
# Install rake-compiler's cross rubies in global dir instead of /root
RUN sudo mkdir -p /usr/local/rake-compiler && \
sudo chown rvm.rvm /usr/local/rake-compiler && \
ln -s /usr/local/rake-compiler ~/.rake-compiler
# Patch rake-compiler to avoid build of ruby extensions
RUN cd /usr/local/rvm/gems/ruby-2.3.0/gems/rake-compiler-0.9.5 && patch -p1 < /home/rvm/patches/rake-compiler-0.9.5/without-exts.diff ; \
true
RUN bash -c "rvm use 2.3.0 --default && \
export MAKE=\"make -j`nproc`\" CFLAGS='-s -O1 -fno-omit-frame-pointer -fno-fast-math' && \
rake-compiler cross-ruby VERSION=2.3.0 HOST=i686-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.3.0 HOST=x86_64-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.2.2 HOST=i686-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.2.2 HOST=x86_64-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.1.6 HOST=i686-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.1.6 HOST=x86_64-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.0.0-p645 HOST=i686-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.0.0-p645 HOST=x86_64-w64-mingw32 && \
rm -rf ~/.rake-compiler/builds ~/.rake-compiler/sources && \
find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
RUN bash -c " \
rvm alias create 2.3 2.3.0 "
USER root
# Fix paths in rake-compiler/config.yml and add rvm and mingw-tools to the global bashrc
RUN sed -i -- "s:/root/.rake-compiler:/usr/local/rake-compiler:g" /usr/local/rake-compiler/config.yml && \
echo "source /etc/profile.d/rvm.sh" >> /etc/bash.bashrc && \
echo "export PATH=\$PATH:/opt/mingw/mingw32/bin" >> /etc/bash.bashrc && \
echo "export PATH=\$PATH:/opt/mingw/mingw64/bin" >> /etc/bash.bashrc
# Install wrappers for strip commands as a workaround for "Protocol error" in boot2docker.
COPY build/strip_wrapper /root/
RUN mv /opt/mingw/mingw32/bin/i686-w64-mingw32-strip /opt/mingw/mingw32/bin/i686-w64-mingw32-strip.bin && \
mv /opt/mingw/mingw64/bin/x86_64-w64-mingw32-strip /opt/mingw/mingw64/bin/x86_64-w64-mingw32-strip.bin && \
mv /usr/bin/i686-w64-mingw32-strip /usr/bin/i686-w64-mingw32-strip.bin && \
mv /usr/bin/x86_64-w64-mingw32-strip /usr/bin/x86_64-w64-mingw32-strip.bin && \
ln /root/strip_wrapper /opt/mingw/mingw32/bin/i686-w64-mingw32-strip && \
ln /root/strip_wrapper /opt/mingw/mingw64/bin/x86_64-w64-mingw32-strip && \
ln /root/strip_wrapper /usr/bin/i686-w64-mingw32-strip && \
ln /root/strip_wrapper /usr/bin/x86_64-w64-mingw32-strip
RUN find / -name rbconfig.rb | while read f ; do sed -i 's/0x0501/0x0600/' $f ; done
RUN find / -name win32.h | while read f ; do sed -i 's/gettimeofday/rb_gettimeofday/' $f ; done
RUN sed -i 's/defined.__MINGW64__.$/1/' /usr/local/rake-compiler/ruby/i686-w64-mingw32/ruby-2.0.0-p645/include/ruby-2.0.0/ruby/win32.h
# Install SIGINT forwarder
COPY build/sigfw.c /root/
RUN gcc $HOME/sigfw.c -o /usr/local/bin/sigfw
# Install user mapper
COPY build/runas /usr/local/bin/
# Install sudoers configuration
COPY build/sudoers /etc/sudoers.d/rake-compiler-dock
ENV RUBY_CC_VERSION 2.3.0:2.2.2:2.1.6:2.0.0
CMD bash

@ -0,0 +1,22 @@
Copyright (c) 2015 Lars Kanis
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -0,0 +1 @@
This is a modified Dockerfile taken from [rake-compiler-dock](https://github.com/rake-compiler/rake-compiler-dock) for the purpose of building gRPC's ruby gem.

@ -0,0 +1,14 @@
diff --git a/tasks/bin/cross-ruby.rake b/tasks/bin/cross-ruby.rake
index 6acc816..6aa2a49 100644
--- a/tasks/bin/cross-ruby.rake
+++ b/tasks/bin/cross-ruby.rake
@@ -135,8 +135,7 @@ file "#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/Makefile" => ["#{USER
"--build=#{RUBY_BUILD}",
'--enable-shared',
'--disable-install-doc',
- '--without-tk',
- '--without-tcl'
+ '--with-ext='
]
# Force Winsock2 for Ruby 1.8, 1.9 defaults to it

@ -0,0 +1,2 @@
diff --git a/configure b/configure
index 55157af..6630eba 100755

@ -0,0 +1,13 @@
diff --git a/configure b/configure
index 898730c..cfe6253 100755
--- a/configure
+++ b/configure
@@ -14695,7 +14695,7 @@ for ac_func in fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot ge
setsid telldir seekdir fchmod cosh sinh tanh log2 round\
setuid setgid daemon select_large_fdset setenv unsetenv\
mktime timegm gmtime_r clock_gettime gettimeofday poll ppoll\
- pread sendfile shutdown sigaltstack dl_iterate_phdr
+ pread shutdown sigaltstack dl_iterate_phdr
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

@ -0,0 +1,2 @@
diff --git a/configure b/configure
index 55157af..6630eba 100755

@ -0,0 +1,12 @@
diff --git a/configure b/configure
index ebe3d8c..a336b73 100755
--- a/configure
+++ b/configure
@@ -18943,7 +18943,6 @@ do :
ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile"
if test "x$ac_cv_func_sendfile" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_SENDFILE 1
_ACEOF
fi

@ -0,0 +1,12 @@
#!/bin/bash
groupadd -g "$GID" "$GROUP"
mkdir -p /tmp/home
useradd -g "$GID" -u "$UID" -G rvm,sudo -p "" -b /tmp/home -m "$USER"
HOME=$(bash <<< "echo ~$USER")
ln -s /usr/local/rake-compiler "$HOME"/.rake-compiler
sudo -u "$USER" --set-home \
BASH_ENV=/etc/rubybashrc \
-- "$@"

@ -0,0 +1,43 @@
/*
* This program handles SIGINT and forwards it to another process.
* It is intended to be run as PID 1.
*
* Docker starts processes with "docker run" as PID 1.
* On Linux, the default signal handler for PID 1 ignores any signals.
* Therefore Ctrl-C aka SIGINT is ignored per default.
*/
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
int pid = 0;
void
handle_sigint (int signum)
{
if(pid)
kill(pid, SIGINT);
}
int main(int argc, char *argv[]){
struct sigaction new_action;
int status = -1;
/* Set up the structure to specify the new action. */
new_action.sa_handler = handle_sigint;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGINT, &new_action, (void*)0);
pid = fork();
if(pid){
wait(&status);
return WEXITSTATUS(status);
}else{
status = execvp(argv[1], &argv[1]);
perror("exec");
return status;
}
}

@ -0,0 +1,30 @@
#!/usr/bin/env ruby
# Strip file on local folder instead of a Virtualbox shared folder
# to work around this bug: https://www.virtualbox.org/ticket/8463
require 'tempfile'
require 'fileutils'
strip = "#{File.basename($0)}.bin"
files = ARGV.reject{|f| f=~/^-/ }.map do |arg|
tmp = Tempfile.new 'strip'
tmp.close
FileUtils.cp arg, tmp.path
[tmp, arg]
end
options = ARGV.select{|f| f=~/^-/ } + files.map{|t,o| t.path }
unless system( strip, *options )
exit 127
end
code = $?.exitstatus
files.each do |tmp, orig|
FileUtils.rm orig
FileUtils.cp tmp.path, orig
end
exit code

@ -0,0 +1 @@
Defaults env_keep += "http_proxy https_proxy ftp_proxy RCD_HOST_RUBY_PLATFORM RCD_HOST_RUBY_VERSION RCD_IMAGE RUBY_CC_VERSION"
Loading…
Cancel
Save