• Harshit Chopra's avatar
    Adds support for proto2 syntax for Ruby gem. · d0535cc0
    Harshit Chopra authored
    This change only adds basic proto2 support without advanced features
    like extensions, custom options, maps, etc.
    
    The protoc binary now generates ruby code for proto2 syntax.
    However, for now, it is restricted to proto2 files without advanced features
    like extensions, in which case it still errors out.
    
    This change also modifies the DSL to add proto messages to the DescriptorPool.
    There is a new DSL Builder#add_file to create a new FileDescriptor. With this,
    the generated ruby DSL looks something like:
    
    Google::Protobuf::DescriptorPool.generated_pool.build do
      add_file "test.proto" do
        add_message "foo" do
          optional :val, :int32, 1
        end
      end
    end
    d0535cc0
Rakefile 4.53 KB
require "rubygems"
require "rubygems/package_task"
require "rake/extensiontask" unless RUBY_PLATFORM == "java"
require "rake/testtask"

spec = Gem::Specification.load("google-protobuf.gemspec")

well_known_protos = %w[
  google/protobuf/any.proto
  google/protobuf/api.proto
  google/protobuf/duration.proto
  google/protobuf/empty.proto
  google/protobuf/field_mask.proto
  google/protobuf/source_context.proto
  google/protobuf/struct.proto
  google/protobuf/timestamp.proto
  google/protobuf/type.proto
  google/protobuf/wrappers.proto
]

# These are omitted for now because we don't support proto2.
proto2_protos = %w[
  google/protobuf/descriptor.proto
  google/protobuf/compiler/plugin.proto
]

genproto_output = []

# We won't have access to .. from within docker, but the proto files
# will be there, thanks to the :genproto rule dependency for gem:native.
unless ENV['IN_DOCKER'] == 'true'
  well_known_protos.each do |proto_file|
    input_file = "../src/" + proto_file
    output_file = "lib/" + proto_file.sub(/\.proto$/, "_pb.rb")
    genproto_output << output_file
    file output_file => input_file do |file_task|
      sh "../src/protoc -I../src --ruby_out=lib #{input_file}"
    end
  end
end

if RUBY_PLATFORM == "java"
  if `which mvn` == ''
    raise ArgumentError, "maven needs to be installed"
  end
  task :clean do
    system("mvn --batch-mode clean")
  end

  task :compile do
    system("mvn --batch-mode package")
  end
else
  Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
    unless RUBY_PLATFORM =~ /darwin/
      # TODO: also set "no_native to true" for mac if possible. As is,
      # "no_native" can only be set if the RUBY_PLATFORM doing
      # cross-compilation is contained in the "ext.cross_platform" array.
      ext.no_native = true
    end
    ext.ext_dir = "ext/google/protobuf_c"
    ext.lib_dir = "lib/google"
    ext.cross_compile = true
    ext.cross_platform = [
      'x86-mingw32', 'x64-mingw32',
      'x86_64-linux', 'x86-linux',
      'universal-darwin'
    ]
  end

  task 'gem:windows' do
    require 'rake_compiler_dock'
    RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0"
  end

  if RUBY_PLATFORM =~ /darwin/
    task 'gem:native' do
      system "rake genproto"
      system "rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0"
    end
  else
    task 'gem:native' => [:genproto, 'gem:windows']
  end
end


# Proto for tests.
genproto_output << "tests/generated_code.rb"
genproto_output << "tests/generated_code_proto2.rb"
genproto_output << "tests/test_import.rb"
genproto_output << "tests/test_import_proto2.rb"
genproto_output << "tests/test_ruby_package.rb"
genproto_output << "tests/test_ruby_package_proto2.rb"
genproto_output << "tests/basic_test.rb"
genproto_output << "tests/basic_test_proto2.rb"
file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/generated_code.proto"
end

file "tests/generated_code_proto2.rb" => "tests/generated_code_proto2.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/generated_code_proto2.proto"
end

file "tests/test_import.rb" => "tests/test_import.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/test_import.proto"
end

file "tests/test_import_proto2.rb" => "tests/test_import_proto2.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/test_import_proto2.proto"
end

file "tests/test_ruby_package.rb" => "tests/test_ruby_package.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/test_ruby_package.proto"
end

file "tests/test_ruby_package_proto2.rb" => "tests/test_ruby_package_proto2.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/test_ruby_package_proto2.proto"
end

file "tests/basic_test.rb" => "tests/basic_test.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/basic_test.proto"
end

file "tests/basic_test_proto2.rb" => "tests/basic_test_proto2.proto" do |file_task|
  sh "../src/protoc --ruby_out=. tests/basic_test_proto2.proto"
end

task :genproto => genproto_output

task :clean do
  sh "rm -f #{genproto_output.join(' ')}"
end

Gem::PackageTask.new(spec) do |pkg|
end

Rake::TestTask.new(:test => :build) do |t|
  t.test_files = FileList["tests/*.rb"].exclude("tests/gc_test.rb", "tests/common_tests.rb")
end

# gc_test needs to be split out to ensure the generated file hasn't been
# imported by other tests.
Rake::TestTask.new(:gc_test => :build) do |t|
  t.test_files = FileList["tests/gc_test.rb"]
end

task :build => [:clean, :compile, :genproto]
task :default => [:build]

# vim:sw=2:et