如何在Bazel中为Thrift生成Python绑定
我正在尝试使用Bazel为Thrift服务定义生成Python绑定。据我所知,没有任何现有的如何在Bazel中为Thrift生成Python绑定,python,code-generation,thrift,bazel,Python,Code Generation,Thrift,Bazel,我正在尝试使用Bazel为Thrift服务定义生成Python绑定。据我所知,没有任何现有的.bzl可以这样做,所以我在这里有点孤立无援。我以前写过.bzl规则,但在本例中遇到的情况不同 一般的问题是,在构建开始之前,我不知道thrift命令中输出文件的名称,这意味着我无法生成设置了srcs属性的py_库规则,因为我没有文件的名称。我尝试了以下示例,即通过生成.zip文件提前知道输出文件,但是py_库规则只允许将.py文件作为src,因此这不起作用 我能想到的唯一一件事是使用存储库规则生成代码和
.bzl
可以这样做,所以我在这里有点孤立无援。我以前写过.bzl
规则,但在本例中遇到的情况不同
一般的问题是,在构建开始之前,我不知道thrift
命令中输出文件的名称,这意味着我无法生成设置了srcs
属性的py_库
规则,因为我没有文件的名称。我尝试了以下示例,即通过生成.zip
文件提前知道输出文件,但是py_库
规则只允许将.py
文件作为src,因此这不起作用
我能想到的唯一一件事是使用
存储库规则生成代码和构建文件,但我试图完成的工作似乎不是很长,应该得到支持。以前有人尝试过这样做
在此讨论:
代码如下:
我会从那里开始
编辑:
我从那里开始。我没有达到我希望的程度。Bazel正在扩展以支持由一个输入生成多个输出,但它目前还不太容易做到这一点,根据:
groups.google.com/forum/#!主题/bazel讨论/3WQhHm194yU
无论如何,我尝试过C++节俭绑定,它们有相同的问题。Java示例通过使用源jar作为构建源来解决这个问题,这对我们来说是行不通的。为了让它工作,我输入了我关心的源文件列表,这些文件将由thrift generator创建。然后,我将这些文件报告为将在impl中生成的输出。这似乎奏效了。这有点令人讨厌,因为在构建之前,您必须知道要查找哪些文件,但它确实有效。也可以让一个小程序读取thift文件并确定它将生成的输出文件。那会更好,但我没有时间。另外,当前的方法很好,因为它明确定义了要生成的文件,这使得像我这样的新手更容易理解构建文件
首先通过一些代码,也许我会清理它并将其作为补丁提交(也许不是):
以前有人尝试过这个
在此讨论:
代码如下:
我会从那里开始
编辑:
我从那里开始。我没有达到我希望的程度。Bazel正在扩展以支持由一个输入生成多个输出,但它目前还不太容易做到这一点,根据:
groups.google.com/forum/#!主题/bazel讨论/3WQhHm194yU
无论如何,我尝试过C++节俭绑定,它们有相同的问题。Java示例通过使用源jar作为构建源来解决这个问题,这对我们来说是行不通的。为了让它工作,我输入了我关心的源文件列表,这些文件将由thrift generator创建。然后,我将这些文件报告为将在impl中生成的输出。这似乎奏效了。这有点令人讨厌,因为在构建之前,您必须知道要查找哪些文件,但它确实有效。也可以让一个小程序读取thift文件并确定它将生成的输出文件。那会更好,但我没有时间。另外,当前的方法很好,因为它明确定义了要生成的文件,这使得像我这样的新手更容易理解构建文件
首先通过一些代码,也许我会清理它并将其作为补丁提交(也许不是):
是的,我曾考虑过明确说明应该生成的文件。这太恶心了,所以我没有走这条路,尽管事实上我知道这是可行的。我也曾想过使用存储库规则,但这似乎令人担忧。最后,我考虑为生成的文件生成一个.zip
,并构建一个存根.py
,该存根解压包含源代码的.zip
。我相信它会起作用,但这似乎是一个黑客行为。是的,我曾考虑过明确说明应该生成的文件。这太恶心了,所以我没有走这条路,尽管事实上我知道这是可行的。我也曾想过使用存储库规则,但这似乎令人担忧。最后,我考虑为生成的文件生成一个.zip
,并构建一个存根.py
,该存根解压包含源代码的.zip
。我相信它会起作用,但再一次,这似乎是一个黑客。嘿,布莱恩,我也陷入了类似的境地。我问了一些类似的问题,你能分享一下你的最终方法吗?嘿,布莱恩,我也陷入了类似的境地。我问了一些类似的问题,你能分享一下你的最终方法吗?
###########
# CPP gen
###########
# Create Generated cpp source files from thrift idl files.
#
def _gen_thrift_cc_src_impl(ctx):
out = ctx.outputs.outs
if not out:
# empty set
# nothing to do, no inputs to build
return DefaultInfo(files=depset(out))
# Used dir(out[0]) to see what
# we had available in the object.
# dirname attribute tells us the directory
# we should be putting stuff in, works nicely.
# ctx.genfile_dir is not the output directory
# when called as an external repository
target_genfiles_root = out[0].dirname
thrift_includes_root = "/".join(
[ target_genfiles_root, "thrift_includes"])
gen_cpp_dir = "/".join([target_genfiles_root,"." ])
commands = []
commands.append(_mkdir_command_string(target_genfiles_root))
commands.append(_mkdir_command_string(thrift_includes_root))
thrift_lib_archive_files = ctx.attr.thrift_library._transitive_archive_files
for f in thrift_lib_archive_files:
commands.append(
_tar_extract_command_string(f.path, thrift_includes_root))
commands.append(_mkdir_command_string(gen_cpp_dir))
thrift_lib_srcs = ctx.attr.thrift_library.srcs
for src in thrift_lib_srcs:
commands.append(_thrift_cc_compile_command_string(
thrift_includes_root, gen_cpp_dir, src))
inputs = (
list(thrift_lib_archive_files) + thrift_lib_srcs )
ctx.action(
inputs = inputs,
outputs = out,
progress_message = "Generating CPP sources from thift archive %s" % target_genfiles_root,
command = " && ".join(commands),
)
return DefaultInfo(files=depset(out))
thrift_cc_gen_src= rule(
_gen_thrift_cc_src_impl,
attrs = {
"thrift_library": attr.label(
mandatory=True, providers=['srcs', '_transitive_archive_files']),
"outs" : attr.output_list(mandatory=True, non_empty=True),
},output_to_genfiles = True,
)
# wraps cc_library to generate a library from one or more .thrift files
# provided as a thrift_library bundle.
#
# Generates all src and hdr files needed, but you must specify the expected
# files. This is a bug in bazel: https://groups.google.com/forum/#!topic/bazel-discuss/3WQhHm194yU
#
# Instead of src and hdrs, requires: cpp_srcs and cpp_hdrs. These are required.
#
# Takes:
# name: The library name, like cc_library
#
# thrift_library: The library of source .thrift files from which our
# code will be built from.
#
# cpp_srcs: The expected source that will be generated and built. Passed to
# cc_library as src.
#
# cpp_hdrs: The expected header files that will be generated. Passed to
# cc_library as hdrs.
#
# Rest of options are documented in native.cc_library
#
def thrift_cc_library(name, thrift_library,
cpp_srcs=[],cpp_hdrs=[],
build_skeletons=False,
deps=[], alwayslink=0, copts=[],
defines=[], include_prefix=None,
includes=[], linkopts=[],
linkstatic=0, nocopts=None,
strip_include_prefix=None,
textual_hdrs=[],
visibility=None):
# from our thrift_library tarball source bundle,
# create a generated cpp source directory.
outs = []
for src in cpp_srcs:
outs.append("//:"+src)
for hdr in cpp_hdrs:
outs.append("//:"+hdr)
thrift_cc_gen_src(
name = name + 'cc_gen_src',
thrift_library = thrift_library,
outs = outs,
)
# Then make the library for the given name.
native.cc_library(
name = name,
deps = deps,
srcs = cpp_srcs,
hdrs = cpp_hdrs,
alwayslink = alwayslink,
copts = copts,
defines=defines,
include_prefix=include_prefix,
includes=includes,
linkopts=linkopts,
linkstatic=linkstatic,
nocopts=nocopts,
strip_include_prefix=strip_include_prefix,
textual_hdrs=textual_hdrs,
visibility=visibility,
)