sapling/build/fbcode_builder/CMake/FBThriftPyLibrary.cmake
Adam Simpkins e286e4c888 fix the thrift CMake rules to add dependencies on the thrift compiler
Summary:
Update the thrift C++ and Python CMake rules to indicate that the output also
depends on the thrift compiler itself.

Previously the C++ rule indicated that the output depended on the thrift
template files, which caught most cases when the thrift compiler was updated,
but wasn't fully correct.  The thrift templates were also removed and baked
into the thrift compiler binary in D16356056.

Reviewed By: yfeldblum, chadaustin

Differential Revision: D17401217

fbshipit-source-id: ae5cde7a7e5e07a74406a1b6f4469124187bc12f
2019-09-16 21:10:01 -07:00

112 lines
3.6 KiB
CMake

# 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
"$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>"
"$<INSTALL_INTERFACE:${ARG_THRIFT_INCLUDE_DIR}>"
)
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;$<JOIN:$<TARGET_PROPERTY:${LIB_NAME}.thrift_includes,INTERFACE_INCLUDE_DIRECTORIES>,;-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}"
--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()