[ 
https://issues.apache.org/jira/browse/THRIFT-5477?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17440675#comment-17440675
 ] 

Max commented on THRIFT-5477:
-----------------------------

Hi Csonkás Kristóf Gyula , I had to write a much, much more involved CMake 
helper for Thrift. It came out at about 1200 SLoC AFAIRC.

If you go down this road, be prepared for the following.

Thrift generator will output variable set of files, depending on whether the 
source IDL file has at least 1 service defined or not. Names of the output 
files will be variable, too (you got this).

Thrift generator's {{-r}} recursive flag makes bad friends with CMake. If you 
use {{include}} in your IDLs — don't use -r; parse out the include's, walk them 
recursively and map each IDL file to cmake custom target, setting proper 
dependencies between targets. Otherwise, you'll lose incremental rebuilds, in 
one of two ways:
 # the entire project will get recompiled on every `make`/`ninja` call (or what 
have you);
 # make won't pick up changes in .thrift and their dependees, forcing the user 
to nuke CMAKE_BUILD_DIR and recompile from scratch on every change to .thrift 
IDL files.

To do the parsing, I'd coded a ~150 SLoC Thrift AST parser in Python + 
arpeggio, it was easy. Then called it via execute_process() at CMake configure 
stage, using the output.

That same parser did me triple-duty: 1) parse inter-IDL includes 2) parse 
whether there's at least 1 service definition 3) extract Golang namespacing 
info. (The same thrift.cmake had supported codegen for C++, Python, Golang and 
PHP in my case.)

I highly recommend using the common cmake idiom of add_custom_command() wrapped 
in add_custom_target(). The former alone will give issues.

As another trick, I had great success with packaging the compiled .o files from 
Thrift codegen into static library targets (one .a glue library per IDL file) — 
that worked really smoothly with CMake's target dependency tracking.

Am very sorry to not provide the cmake module itself; it was developed 
commercially under a proprietary license and cannot be openly shared.

> Thrift does not generate a well-defined set of files
> ----------------------------------------------------
>
>                 Key: THRIFT-5477
>                 URL: https://issues.apache.org/jira/browse/THRIFT-5477
>             Project: Thrift
>          Issue Type: Bug
>          Components: C++ - Compiler
>    Affects Versions: 0.14.0, 0.15.0
>            Reporter: Csonkás Kristóf Gyula
>            Priority: Major
>
> While upgrading the Thrift version that we use, I noticed that starting with 
> version 0.14.0 Thrift does not generate a well-defined set of output files 
> for C++, which makes it difficult to build generic build system tooling 
> around it. I tracked the issue down to THRIFT-5168.
> Our current cmake helper function, where I prefixed the lines that were added 
> to workaround this issue with a {{{}+{}}}:
> {code:none}
> function(target_thrift_source _target)
>   set(_single_args
>     "THRIFT_FILE"
>     "BINARY_DIR"
>   )
>   set(_multi_args
>     "SERVICES;CXX_OPTIONS"
>   )
>   cmake_parse_arguments(tts "" "${_single_args}" "${_multi_args}" ${ARGN})
>   foreach(_required_arg THRIFT_FILE)
>     if(NOT tts_${_required_arg})
>       message(FATAL_ERROR "target_thrift_source called without 
> ${_required_arg}")
>     endif()
>   endforeach()
>   if(NOT tts_BINARY_DIR)
>     set(tts_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/thrift_generated")
>   endif()  get_filename_component(_thriftfile_abs_path "${tts_THRIFT_FILE}" 
> ABSOLUTE)
>   get_filename_component(_working_directory "${_thriftfile_abs_path}" 
> DIRECTORY)
>   get_filename_component(_thriftfile_name "${tts_THRIFT_FILE}" NAME_WE)  
> set(_output_files
>     "${tts_BINARY_DIR}/${_thriftfile_name}_types.h"
>     "${tts_BINARY_DIR}/${_thriftfile_name}_types.cpp"
>     "${tts_BINARY_DIR}/${_thriftfile_name}_constants.h"
>     "${tts_BINARY_DIR}/${_thriftfile_name}_constants.cpp"
>   )
>   foreach(_service IN LISTS tts_SERVICES)
>     list(APPEND _output_files
>       "${tts_BINARY_DIR}/${_service}.h"
>       "${tts_BINARY_DIR}/${_service}.cpp"
>     )
>   endforeach()  set(thrift_CXX_OPTIONS "moveable_types,no_skeleton")
>   foreach(_opt IN LISTS tts_CXX_OPTIONS)
>     string(APPEND thrift_CXX_OPTIONS ",${_opt}")
>   endforeach()
> +  set(_touch_commands)
> +  foreach(_file IN LISTS _output_files)
> +    list(APPEND _touch_commands COMMAND "${CMAKE_COMMAND}" -E touch 
> "${_file}")
> +  endforeach()
>   add_custom_command(
>     OUTPUT ${_output_files}
>     COMMAND "${CMAKE_COMMAND}" -E make_directory "${tts_BINARY_DIR}"
>     COMMAND Thrift::compiler -out "${tts_BINARY_DIR}"
>             --gen cpp:${thrift_CXX_OPTIONS}
>             "${_thriftfile_abs_path}"
> +    ${_touch_commands}
>     MAIN_DEPENDENCY "${_thriftfile_abs_path}"
>     DEPENDS "${_thriftfile_abs_path}"
>     WORKING_DIRECTORY "${_working_directory}"
>   )
>   target_include_directories("${_target}" PRIVATE "${tts_BINARY_DIR}")
>   target_sources("${_target}"
>     PRIVATE ${_output_files} ${tts_THRIFT_FILE}
>   )
> endfunction()
> {code}



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to