Programming Languages on Power

 View Only

Grpc.Tools package for C# on Power

By Janani Janakiraman posted Thu May 04, 2023 02:43 PM

  

If you're in the world of software development, then you're probably familiar with the challenges of building fast and scalable APIs. Fortunately, gRPC is an open-source Remote Procedure Call (RPC) framework that can help you overcome these obstacles!

In this blog post, we'll take a closer look at how to build the Grpc.Tools package for C# on IBM Linux on Power. This package offers Protocol Buffers/gRPC codegen build integration for C# applications, making it an excellent tool to add to your development arsenal.

We'll walk you through the process of verifying the port of the Grpc.Tools package on Power, using a sample gRPC application written in C#. By the end of this post, you'll have a better understanding of how to leverage this package to create efficient APIs.

Let's dive in!

Introduction

In the world of APIs, gRPC is becoming increasingly popular for its speed, scalability, and ease of use. One of the key factors behind its success is its use of Protocol Buffers, or Protobuf, as its Interface Definition Language (IDL) and serialization toolset. Protocol Buffers is a well-known serialization/deserialization protocol developed by Google.

One of the standout features of gRPC is its native code generation for client/server applications. By using Protobuf, you can easily define your services and generate client libraries for your API.

So how does Protocol Buffers work in practice? Check out the following diagram to see how you can use it to work with your data.

Protocol Buffers Workflow diagram
Figure 1: Protocol Buffers Workflow Diagram. Source: https://protobuf.dev/overview/

The Grpc.Tools package contains the Protocol Buffers compiler and gRPC plugin, which you can use to generate C# code from .proto files that define your messages.

The Grpc.Tools package generates C# code for Protocol Buffer messages and gRPC service stubs, with the following characteristics:

  • The code is generated as-needed each time the project is built.
  • The generated code is not added to the project or checked into source control.
  • The generated code is build artifact that is usually contained in the obj directory.

Grpc.Tools is used only at build-time so it does not have any runtime components

Prerequisites

A Power virtual machine (VM) with Red Hat Enterprise Linux (RHEL) 8.7 or 9.1 and .NET 7 installed. Refer to Accelerate your open source development with access to IBM Power resources for more information about access to Power hardware.

.NET 7 is available as the RPM, dotnet-sdk-7.0 in the app stream repositories for RHEL 8.7 and 9.1. These repositories are enabled by default on RHEL 8 and 9 systems.

Install .NET on the Power VM

Install .NET 7 on the Power VM by entering the following command into the terminal:

sudo yum install dotnet-sdk-7.0

Build Grpc.Tools package

Perform the following steps to build Grpc.Tools on Power:

  1. Clone the gRPC code
  2. Add support for ppc64le architecture in Grpc.Tools projects.
  3. Change TargetFrameworks to net7.0.
  4. Build protoc compiler and grpc_scharp_plugin through bazel.
  5. Build Grpc.Tools projects.
  6. Create a Grpc.Tools nuget package by running build_nuget.sh script which is available in grpc/src/csharp directory.

After you've completed these steps, you'll have successfully built Grpc.Tools and created a nuget package for it.

To simplify the build process, we have created a folder named ‘grpc-tool’ with some scripts that can be downloaded. This folder includes two files:

  • grpc_v1.50.0.patch

    This patch file contains all the necessary changes made to the Grpc.Tools code in order to build and create a nuget package of Grpc.Tools for Power.

  • grpc.tools_ubi_8.5.sh

    This script file which is used to install required dependencies, clone the grpc code, apply the patch, build the Grpc.Tools, create the nuget package of Grpc.Tools for Power, and run the test suites of Grpc.Tools to ensure that the build is correct.

Examine the grpc_v1.50.0.patch file

The grpc_v1.50.0.patch file contains the necessary changes required to port gRPC.Tools to Power. Let's go through the changes one by one:

  • The TargetFrameworks have been changed from net45, netcoreapp3.1, and netstandard1.3 to net7.0.
  • The Ppc64le value has been added to the enum CpuArchitecture, and its corresponding method has been added to the Grpc.Tools project files.
  • In the grpc/src/csharp/build_nuget.sh file, some modifications have been made to build the protoc compiler and grpc_csharp_plugin using Bazel.

Let us walk you through the build process using these scripts.

  1. Run grpc.tools_ubi_8.5.sh script by using the following command.

    grpc.tools_ubi_8.5.sh

    You should see the output displayed as follows.

    Cloning into 'grpc'...
    remote: Enumerating objects: 687344, done.
    . . . 
    Note: switching to 'v1.50.0'.
    . . . 
    Submodule 'third_party/abseil-cpp' (https://github.com/abseil/abseil-cpp.git) registered for path 'third_party/abseil-cpp'
    Submodule 'third_party/benchmark' (https://github.com/google/benchmark) registered for path 'third_party/benchmark'
    . . . 
    Cloning into '/home/grpc/third_party/abseil-cpp'...
    . . . 
    Submodule path 'third_party/abseil-cpp': checked out '273292d1cfc0a94a65082ee350509af1d113344d'
    . . . 
    Cloning into '/home/grpc/third_party/protoc-gen-validate'...
    remote: Enumerating objects: 10576, done.
    . . . 
    ../grpc_v1.50.0.patch:21: trailing whitespace.
    warning: 1 line adds whitespace errors.
    Extracting Bazel installation...
    Starting local Bazel server and connecting to it...
    . . . 
    MSBuild version 17.4.1+2eac9157a for .NET
      Determining projects to restore...
      Restored /home/grpc/src/csharp/Grpc.Tools/Grpc.Tools.csproj (in 6.55 sec).
      Restored /home/grpc/src/csharp/Grpc.Tools.Tests/Grpc.Tools.Tests.csproj (in 6.62 sec).
      Grpc.Tools -> /home/grpc/src/csharp/Grpc.Tools/bin/Release/net7.0/Protobuf.MSBuild.dll
      Grpc.Tools.Tests -> /home/grpc/src/csharp/Grpc.Tools.Tests/bin/Release/net7.0/Grpc.Tools.Tests.dll
    
    Build succeeded.
        0 Warning(s)
        0 Error(s)
    
    Time Elapsed 00:00:46.18
    ++ dirname ./build_nuget.sh
    + cd .
    + mkdir -p ../../artifacts
    + mkdir -p protoc_plugins
    + ./nuget_helpers/expand_dev_version.sh
    . . . 
    MSBuild version 17.4.1+2eac9157a for .NET
      Determining projects to restore...
      Restored /home/grpc/src/csharp/Grpc.Tools/Grpc.Tools.csproj (in 1.9 sec).
      Grpc.Tools -> /home/grpc/src/csharp/Grpc.Tools/bin/Release/net7.0/Protobuf.MSBuild.dll
      Successfully created package '/home/grpc/artifacts/Grpc.Tools.2.50.0.nupkg'.
    + cd ../../artifacts
    + zip csharp_nugets_windows_dotnetcli.zip Grpc.Tools.2.50.0.nupkg
      adding: Grpc.Tools.2.50.0.nupkg (deflated 1%)
    Testing grpc with v1.50.0
    NUnitLite 3.10.1 (.NET Standard 2.0)
    Copyright (c) 2018 Charlie Poole, Rob Prouse
    
    Runtime Environment
       OS Version: Linux 5.4.0-125-generic #141-Ubuntu SMP Wed Aug 10 13:41:48 UTC 2022
      CLR Version: 7.0.4
    
    Test Files
        /home/grpc/src/csharp/Grpc.Tools.Tests/bin/Debug/net7.0/Grpc.Tools.Tests.dll
    
    Run Settings
        Number of Test Workers: 8
        Work Directory: /home/grpc/src/csharp/Grpc.Tools.Tests
        Internal Trace: Off
    
    Test Run Summary
      Overall result: Passed
      Test Count: 117, Passed: 117, Failed: 0, Warnings: 0, Inconclusive: 0, Skipped: 0
      Start time: 2023-04-12 11:19:52Z
        End time: 2023-04-12 11:19:53Z
        Duration: 1.334 seconds
    
    Results (nunit3) saved as /home/grpc/src/csharp/Grpc.Tools.Tests/TestResult.xml
    
  2. Examine the /grpc/artifacts/ directory to ensure that the Grpc.Tools nuget package is created.

    [artifacts]# ls
    Grpc.Tools.2.50.0.nupkg  csharp_nugets_windows_dotnetcli.zip
    

Verify the Grpc.Tools nuget package by running Greeter example code

Now let’s try to build and run Greeter example code (provided by Grpc.Tools) using the locally built Grpc.Tools nuget package.

  1. Point the Greeter example to the locally built Grpc.Tools.nupkg

    • Create a Nuget.config file inside Greeter directory.

    • Add a key named “local-grpc-tools” to give the path of local nuget package.

    • Provide the name of the build artifacts directory where the Grpc.Tools.nupkg is generated.

    • Add the directory that corresponds to your build.

    Use the following code to perform these activities:

    # vim Nuget.config 
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <packageSources>
        <clear />
        <add key="local-grpc-tools" value="<grpc_src_rootdir>/grpc/artifacts" />
      <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
      </packageSources>
    </configuration>
    
  2. Change the versions of Grpc.Tools, Grpc.Net.Client and Grpc.AspNetCore PackageReferences

    To use the newly created Grpc.Tools v2.50.0 nuget package, we need to update the version number to 2.50.0 in the Greeter/Client/Client.csproj and Greeter/Server/Server.csproj files.

    vim Client.csproj 
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net7.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <Protobuf Include="..\Proto\greet.proto" GrpcServices="Client" Link="Protos\greet.proto" />
    
        <PackageReference Include="Google.Protobuf" Version="3.21.6" />
        <PackageReference Include="Grpc.Net.Client" Version="2.50.0" />
        <PackageReference Include="Grpc.Tools" Version="2.50.0"  />
      </ItemGroup>
    </Project>
    # vim Server.csproj
    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
      </PropertyGroup>
    
      <ItemGroup>
        <Protobuf Include="..\Proto\greet.proto" GrpcServices="Server" Link="Protos\greet.proto" />
    
        <PackageReference Include="Grpc.AspNetCore" Version="2.50.0" />
        <PackageReference Include="Grpc.Tools" Version="2.50.0"  />
      </ItemGroup>
    
    </Project>
    
  3. Set default port to run Greeter example code locally.

    Change the default port to 80 and use ‘http’ instead of ‘https’ in the following files.
    # vi Server/Properties/launchSettings.json
    {
      "profiles": {
        "Server": {
          "commandName": "Project",
          "launchBrowser": false,
          "applicationUrl": "http://localhost:80",
          "environmentVariables": {
            "ASPNETCORE_ENVIRONMENT": "Development"
          }
        }
      }
    }
    # vi Client/Program.cs
    using Greet;
    using Grpc.Net.Client;
    using System;
    using var channel = GrpcChannel.ForAddress("http://localhost:80");
    var client = new Greeter.GreeterClient(channel);
    
    var reply = await client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });
    Console.WriteLine("Greeting: " + reply.Message);
    
    Console.WriteLine("Shutting down");
    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
    # vi Server/Program.cs
    using Server;
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddGrpc();
    
    var app = builder.Build();
    app.MapGrpcService<GreeterService>();
    
    app.Run("http://localhost:80");

    Refer to gRPC HelloWorldGreeter does not work on Fedora 35 for known issues.

  4. Build Greeter example code using the ‘dotnet build Greeter.sln’ command:

    # cd Greeter
    # dotnet build Greeter.sln
    MSBuild version 17.4.1+fedecea9d for .NET
      Determining projects to restore...
      Restored /root/amit/Greeter/Server/Server.csproj (in 576 ms).
      Restored /root/amit/Greeter/Client/Client.csproj (in 576 ms).
      Client -> /root/amit/Greeter/Client/bin/Debug/net7.0/Client.dll
      Server -> /root/amit/Greeter/Server/bin/Debug/net7.0/Server.dll
    
    Build succeeded.
        0 Warning(s)
        0 Error(s)
    
    Time Elapsed 00:00:12.47
  5. Run the Greeter example code by running the following commands over two different terminals to start the server and client environments.

    • To start the Server, open the terminal and run following commands.

      # cd Greeter/Server/bin/Debug/net7.0
      # ./Server
      info: Microsoft.Hosting.Lifetime[14]
            Now listening on: http://localhost:80
      info: Microsoft.Hosting.Lifetime[0]
            Application started. Press Ctrl+C to shut down.
      info: Microsoft.Hosting.Lifetime[0]
            Hosting environment: Production
      info: Microsoft.Hosting.Lifetime[0]
            Content root path: /root/amit/Greeter/Server/bin/Debug/net7.0
      
    • To start the Client, open another terminal and run the following commands.

      # cd Greeter/Client/bin/Debug/net7.0
      # ./Client
      Greeting: Hello GreeterClient
      Shutting down
      Press any key to exit...
      
  6. Check the console messages of Server to see if it receives the “Hello” message from client.

    # ./Server
    info: Microsoft.Hosting.Lifetime[14]
          Now listening on: http://localhost:80
    info: Microsoft.Hosting.Lifetime[0]
          Application started. Press Ctrl+C to shut down.
    info: Microsoft.Hosting.Lifetime[0]
          Hosting environment: Production
    info: Microsoft.Hosting.Lifetime[0]
          Content root path: /root/amit/Greeter/Server/bin/Debug/net7.0
    info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
          Request starting HTTP/2 POST http://localhost/greet.Greeter/SayHello application/grpc -
    info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
          Executing endpoint 'gRPC - /greet.Greeter/SayHello'
    info: Server.GreeterService[0]
          Sending hello to GreeterClient
    info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
          Executed endpoint 'gRPC - /greet.Greeter/SayHello'
    info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
          Request finished HTTP/2 POST http://localhost/greet.Greeter/SayHello application/grpc - - 200 - application/grpc 216.0101ms
    

The console messages confirm the successful execution of the Greeter example code, which was built using the locally installed Grpc.Tools nuget package on Power.

Conclusion

Overall, building Grpc.Tools for Power provides an opportunity for Power developers to take advantage of the powerful features offered by gRPC and Protocol Buffers. By using the Grpc.Tools package to generate C# code from .proto files, developers can easily create high-performance, scalable services that communicate over the network with minimal overhead. Through the step-by-step instructions provided in this blog, we have seen how to successfully build and install Grpc.Tools on Power, as well as how to verify its functionality by running the Greeter example code. By following these steps, Power developers can begin to incorporate the latest technologies into their projects, creating modern, efficient software that meets the demands of today's users.

References

Additional author

Thank you to Amit Sirohi for co-authoring this blog.

Permalink