# Copyright (c) Facebook, Inc. and its affiliates. include(FBCMakeParseArgs) include(FBPythonBinary) # Generate a Python library from a thrift file function(add_fbthrift_py_library LIB_NAME THRIFT_FILE) # Parse the arguments set(one_value_args NAMESPACE THRIFT_INCLUDE_DIR) set(multi_value_args SERVICES DEPENDS OPTIONS) fb_cmake_parse_args( ARG "" "${one_value_args}" "${multi_value_args}" "${ARGN}" ) if(NOT DEFINED ARG_THRIFT_INCLUDE_DIR) set(ARG_THRIFT_INCLUDE_DIR "include/thrift-files") endif() get_filename_component(base ${THRIFT_FILE} NAME_WE) set(output_dir "${CMAKE_CURRENT_BINARY_DIR}/${THRIFT_FILE}-py") # Parse the namespace value if (NOT DEFINED ARG_NAMESPACE) set(ARG_NAMESPACE "${base}") endif() string(REPLACE "." "/" namespace_dir "${ARG_NAMESPACE}") set(py_output_dir "${output_dir}/gen-py/${namespace_dir}") list(APPEND generated_sources "${py_output_dir}/__init__.py" "${py_output_dir}/ttypes.py" "${py_output_dir}/constants.py" ) foreach(service IN LISTS ARG_SERVICES) list(APPEND generated_sources ${py_output_dir}/${service}.py ) endforeach() # Define a dummy interface library to help propagate the thrift include # directories between dependencies. add_library("${LIB_NAME}.thrift_includes" INTERFACE) target_include_directories( "${LIB_NAME}.thrift_includes" INTERFACE "$" "$" ) foreach(dep IN LISTS ARG_DEPENDS) target_link_libraries( "${LIB_NAME}.thrift_includes" INTERFACE "${dep}.thrift_includes" ) endforeach() # This generator expression gets the list of include directories required # for all of our dependencies. # It requires using COMMAND_EXPAND_LISTS in the add_custom_command() call # below. COMMAND_EXPAND_LISTS is only available in CMake 3.8+ # If we really had to support older versions of CMake we would probably need # to use a wrapper script around the thrift compiler that could take the # include list as a single argument and split it up before invoking the # thrift compiler. if (NOT POLICY CMP0067) message(FATAL_ERROR "add_fbthrift_py_library() requires CMake 3.8+") endif() set( thrift_include_options "-I;$,;-I;>" ) # Always force generation of "new-style" python classes for Python 2 list(APPEND ARG_OPTIONS "new_style") # CMake 3.12 is finally getting a list(JOIN) function, but until then # treating the list as a string and replacing the semicolons is good enough. string(REPLACE ";" "," GEN_ARG_STR "${ARG_OPTIONS}") # Emit the rule to run the thrift compiler add_custom_command( OUTPUT ${generated_sources} COMMAND_EXPAND_LISTS COMMAND "${CMAKE_COMMAND}" -E make_directory "${output_dir}" COMMAND "${FBTHRIFT_COMPILER}" --legacy-strict --gen "py:${GEN_ARG_STR}" "${thrift_include_options}" -o "${output_dir}" "${CMAKE_CURRENT_SOURCE_DIR}/${THRIFT_FILE}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" MAIN_DEPENDENCY "${THRIFT_FILE}" DEPENDS "${FBTHRIFT_COMPILER}" ) # We always want to pass the namespace as "" to this call: # thrift will already emit the files with the desired namespace prefix under # gen-py. We don't want add_fb_python_library() to prepend the namespace a # second time. add_fb_python_library( "${LIB_NAME}" BASE_DIR "${output_dir}/gen-py" NAMESPACE "" SOURCES ${generated_sources} DEPENDS ${ARG_DEPENDS} FBThrift::thrift_py ) endfunction()