smanders / externpro

build external projects with cmake
MIT License
13 stars 12 forks source link

Add CMake for generating javascript protobuf definitions using protoc #324

Open grahamaj opened 3 years ago

grahamaj commented 3 years ago

CMake has a couple of functions to generate protobuf definitions: protobuf_generate_cpp and protobuf_generate_python (See the documentation). Protoc actually supports serveral more languages including javascript. (See the documentation)

protobuf_generate_cpp and protobuf_generate_python both use an undocumented function protobuf_generate. This function almost supports javascript generation, but there are a couple of problems. It doesn't allow you to set additional options for the javascript independent of the output directory (See here and here ) The two most notable options are:

  1. --import_stye: allows you to specify the module syntax for the generated code. The default is closure which is incompatible with nodejs
  2. binary: this allows you to include parsers for the binary representation. Without this, the generated code is almost useless. Below is a working function that could be included in externpro to facilitate generation of javascript definitions. It is losely based on the cmake protobuf_generate function:
    function(PROTOBUF_GENERATE_JS SRCS)
    if(NOT ARGN)
    message(SEND_ERROR "Error: PROTOBUF_GENERATE_JS() called without any proto files")
    return()
    endif()
    set(generated_srcs)
    foreach(proto_src ${ARGN})
    get_filename_component(abs_file ${proto_src} ABSOLUTE)
    get_filename_component(abs_dir ${abs_file} DIRECTORY)
    get_filename_component(basename ${proto_src} NAME_WE)
    set(generated_src ${abs_dir}${basename}_pb.js)
    list(APPEND generated_srcs ${generated_src})
    add_custom_command(
      OUTPUT ${generated_src}
      COMMAND xpro::protoc
      ARGS --proto_path=${abs_dir} --js_out=import_style=commonjs_strict,binary:${abs_dir} ${abs_file}
      DEPENDS ${abs_file} xpro::protoc
      COMMENT "Running js protobuf compiler on ${proto_src}"
      VERBATIM)
    endforeach()
    set(${SRCS} ${generated_srcs} PARENT_SCOPE)
    endfunction()
grahamaj commented 3 years ago

One more thing, The protoc generated javascript requires a dependency on a library: https://www.npmjs.com/package/google-protobuf