namespace :protoc do desc "Compile Protobuf and generate ruby code" task compile: :environment do compile remove_unnecessary_require end private def proto_path File.join(Rails.root, "proto") end def grpc_path File.join(Rails.root, "grpc") end def ruby_out File.join(grpc_path, "lib") end def grpc_out ruby_out end def grpc_ruby_plugin_path `which grpc_ruby_plugin`.chomp end def proto_files Dir.glob(File.join(Rails.root, "proto", "*.proto")) end def compile command = <<-EOS protoc -I #{proto_path} --ruby_out=#{ruby_out} --grpc_out=#{grpc_out} \ --plugin=protoc-gen-grpc=#{grpc_ruby_plugin_path} #{proto_files.join(" ")} EOS puts "Compile Protobuf..." puts command `#{command}` end def grpc_out_ruby_files Dir.glob(File.join(ruby_out, "**/*.rb")) end # FIXME: # - Load the definition of protobuf twice will result in an error # so we remove the require pb definition. # This is not a smart way, we need to fix it. def remove_unnecessary_require service_files = grpc_out_ruby_files.select do |v| name = File.basename(v) name.end_with?("_pb.rb") && name.include?("_services_") end service_files.each do |path| source = open(path) .read .split("\n") .reject { |line| line =~ /^require / && !line.include?("grpc") }.join("\n") open(path, "w") do |f| f.write source end end without_service_files = grpc_out_ruby_files.select do |v| name = File.basename(v) name.end_with?("_pb.rb") && !name.include?("_services_") end without_service_files.each do |path| source = open(path) .read .split("\n") .reject { |line| line =~ /^require / && !line.include?("google/protobuf") }.join("\n") open(path, "w") do |f| f.write source end end end end