Dienstag, 30. Juni 2020

[C++] gRPC - No, Thank you.

How about some network-programming?
Trying some of the new and hot stuff.
Yes?

As library gRPC (C++) sounded nice. And instead of its main serialization library Protocol Buffer (C++) FlatBuffers (with gRPC & C++) seemed promising because of its benchmarks

On Debian there are currently the following versions available:
  • libflatbuffers-dev and flatbuffers-compiler 1.11
  • libgrpc++-dev and protobuf-compiler-grpc 1.16, 1.26, 1.30
  • libprotobuf-dev and protobuf-compiler 3.6, 3.11, 3.12
First I wanted to try an asynchronous gRPC server with FlatBuffers, like in the example
From the schema you create via flatc the files for the languages you want to use, C++ and gRPC in my case. But I don't want to do that by hand. CMake should be able to handle it?
Yes! If you look inside the source of FlatBuffers, you'll find fitting things, especially "flatbuffers_generate_headers" from "BuildFlatBuffers.cmake". But this is not part of Debian. There is just FlatbuffersConfig.cmake.
Solution one: Copy the files into the project and include them.
Or write an add_custom_command for executing flatc.

And then if break:
error: using typedef-name ‘grpc::CompletionQueue’ after ‘class’
error: 'grpc::ClientContext' has not been declared
After a while I found the answer:
i would suggest you to use grpc 16.1.1 which is last working version that is compatible with flatc grpc generated code
In some gRPC-code of them you'll also find, that they stick to version 1.15.1…

Okay. So downgrading packages. And the files can be generated. Good.

I continued to write the server. The asynchronous one is not directly with a sample on the FlatBuffers site, so it's a little harder to convert. At some point the server runs, port is open.
How to test?
Let's try a quick little python bit. Should be simple, right?
Creating a pipenv.
Installing grpcio...
Crash.
What?
error: ambiguating new declaration of ‘long int gettid()’
Issue is closed. Solution would be: Upgrade. But I can't do it because of the downgrade from above. Nice…

How about not using FlatBuffers? Then I could use newer versions again.
So, let's try with the synchronous server. It looks simple.
Coding… coding… coding… Compiler is happy.

For converting the Protocol Buffers via protoc there is a funtion in CMake called protobuf_generate_cpp. But it just generates the protobuf part, and not the protobuf-grpc one.
I wrote a custom function to get this working for both:

FUNCTION(GRPC_PROTO_GEN OUTDIR OUTFILES SCHEMAS)
    SET(SCHEMA_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/schema-generated")
    SET(${OUTDIR} ${SCHEMA_BUILD_DIR} PARENT_SCOPE)
   FILE(MAKE_DIRECTORY ${SCHEMA_BUILD_DIR})
    FIND_PROGRAM(GRPC_CPP_PLUGIN NAMES grpc_cpp_plugin)
    # MESSAGE("FOUND ${GRPC_CPP_PLUGIN}")
    SET(OUT_GENERATED)

    FOREACH(SCHEMA ${SCHEMAS})
        get_filename_component(file_dir ${SCHEMA} DIRECTORY)
        get_filename_component(file_name ${SCHEMA} NAME_WLE)
        # SET(file_dir_generated "${CMAKE_CURRENT_BINARY_DIR}/${file_dir}-generated")
        get_filename_component(full_file ${SCHEMA} ABSOLUTE)
        get_filename_component(full_path ${file_dir} ABSOLUTE)
        SET(proto_out_cc "${SCHEMA_BUILD_DIR}/${file_name}.pb.cc")
        SET(proto_out_h "${SCHEMA_BUILD_DIR}/${file_name}.pb.h")
        ADD_CUSTOM_COMMAND(
            OUTPUT ${proto_out_cc} ${proto_out_h}
            COMMAND protobuf::protoc
            ARGS --proto_path ${full_path} --cpp_out ${SCHEMA_BUILD_DIR} ${full_file}
            DEPENDS ${full_file} protobuf::protoc
            COMMENT "ProtoCPPCompiling ${SCHEMA}"
            VERBATIM
        )
        # MESSAGE("ProtoCompiled ${proto_out_cc}")
        # MESSAGE("ProtoCompiled ${proto_out_h}")

        LIST(APPEND OUT_GENERATED ${proto_out_cc} ${proto_out_h})

        SET(grpc_out_cc "${SCHEMA_BUILD_DIR}/${file_name}.grpc.pb.cc")
        SET(grpc_out_h "${SCHEMA_BUILD_DIR}/${file_name}.grpc.pb.h")

        ADD_CUSTOM_COMMAND(
            OUTPUT ${grpc_out_cc} ${grpc_out_h}
            COMMAND protobuf::protoc
            ARGS --proto_path ${full_path} --plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN} --grpc_out ${SCHEMA_BUILD_DIR} ${full_file}
            DEPENDS ${full_file} protobuf::protoc ${GRPC_CPP_PLUGIN}
            COMMENT "ProtoGRPCCompiling ${SCHEMA}"
            VERBATIM
        )
        # MESSAGE("ProtoCompiled ${grpc_out_cc}")
        # MESSAGE("ProtoCompiled ${grpc_out_h}")

        LIST(APPEND OUT_GENERATED ${grpc_out_cc} ${grpc_out_h})
    ENDFOREACH()

    SET(${OUTFILES} ${OUT_GENERATED} PARENT_SCOPE)

ENDFUNCTION()

SET(PROTO_SCHEMAS schema/chatmessage.proto)
GRPC_PROTO_GEN(PROTO_GENERATED_DIR PROTO_GENERATED ${PROTO_SCHEMAS})
And then, the code looked good, I tried running it. But it got stuck, it seemed. At the BuildAndStart Funtion. But it did not start. No port was open.
Was it my mistake?
I step by step converted my code to the sample code.
And it did not change. Still not working.
Of course, the solution would be: Update.

Go for version 1.30 from experimental. Okay. Let's try…
Nope. You won't get it installed because it depends on packages, that are non-existent.

I heard that Conan might be a good package-manager for C++.
How about getting new packages from there?

They don't even have it.

Thanks, I just wanted to do a little bit of fun coding.
But noooooooooooooooooo, wasting days fighting with some libraries.

Keine Kommentare:

Kommentar veröffentlichen

[Review/Critic] UDock X - 13,3" LapDock

The UDock X - 13.3" LapDock is a combination of touch display, keyboard, touch-pad and battery. It can be used as an extension of vari...