pw_build: Optionally generate setup.py & nest protos
- Support the generated_setup argument for pw_python_package. This
mirrors the package to the out directory and generates a setup.py
for it there.
- Allow pw_proto_library targets to add their protos to an existing
Python package rather than generating a protos-only package.
- Only reinstall --editable packages when setup.py changes rather than
when any file changes.
Requires: pigweed-internal:10840
Change-Id: I35ed555c2667e60d844468eb614ce0a6f76c3d32
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/36504
Commit-Queue: Wyatt Hepler <hepler@google.com>
Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-by: Joe Ethier <jethier@google.com>
Reviewed-by: Alexei Frolov <frolv@google.com>
diff --git a/pw_protobuf_compiler/proto.gni b/pw_protobuf_compiler/proto.gni
index 27c608f..c877b28 100644
--- a/pw_protobuf_compiler/proto.gni
+++ b/pw_protobuf_compiler/proto.gni
@@ -49,7 +49,6 @@
rebase_path(get_target_outputs(":${invoker.base_target}._includes"))
pw_python_action("$target_name._gen") {
- forward_variables_from(invoker, [ "metadata" ])
script =
"$dir_pw_protobuf_compiler/py/pw_protobuf_compiler/generate_protos.py"
@@ -89,6 +88,15 @@
} else {
stamp = true
}
+
+ if (defined(invoker.metadata)) {
+ metadata = invoker.metadata
+ } else {
+ metadata = {
+ protoc_outputs = rebase_path(outputs)
+ root = [ rebase_path(_out_dir) ]
+ }
+ }
}
}
@@ -252,42 +260,49 @@
# the generated files. This is internal and should not be used outside of this
# file. Use pw_proto_library instead.
template("_pw_python_proto_library") {
- _target = target_name
-
_pw_invoke_protoc(target_name) {
- forward_variables_from(invoker, "*", _forwarded_vars)
+ forward_variables_from(invoker, "*", _forwarded_vars + [ "python_package" ])
language = "python"
python_deps = [ "$dir_pw_protobuf_compiler:protobuf_requirements" ]
}
- _setup_py = "${invoker.base_out_dir}/python/setup.py"
+ if (defined(invoker.python_package) && invoker.python_package != "") {
+ # If nested in a Python package, write the package's name to a file so
+ # pw_python_package can check that the dependencies are correct.
+ write_file("${invoker.base_out_dir}/python_package.txt",
+ get_label_info(invoker.python_package, "label_no_toolchain"))
- # Create the setup and init files for the Python package.
- action(target_name + "._package_gen") {
- script = "$dir_pw_protobuf_compiler/py/pw_protobuf_compiler/generate_python_package.py"
- args = [
- "--setup",
- rebase_path(_setup_py),
- "--package",
- invoker._package_dir,
- ] + rebase_path(invoker.outputs, "${invoker.base_out_dir}/python")
-
- if (invoker.module_as_package != "") {
- args += [ "--module-as-package" ]
+ # If anyone attempts to depend on this Python package, print an error.
+ pw_error(target_name) {
+ _pkg = get_label_info(invoker.python_package, "label_no_toolchain")
+ message_lines = [
+ "This proto Python package is embedded in the $_pkg Python package.",
+ "It cannot be used directly; instead, depend on $_pkg.",
+ ]
}
+ foreach(subtarget, pw_python_package_subtargets) {
+ group("$target_name.$subtarget") {
+ deps = [ ":${invoker.target_name}" ]
+ }
+ }
+ } else {
+ write_file("${invoker.base_out_dir}/python_package.txt", "")
- public_deps = [ ":$_target._gen($default_toolchain)" ]
- outputs = [ _setup_py ]
- }
+ # Create a Python package with the generated source files.
+ pw_python_package(target_name) {
+ forward_variables_from(invoker, _forwarded_vars)
+ generate_setup = {
+ name = invoker._package_dir
+ version = "0.0.1" # TODO(hepler): Need to be able to set this verison.
+ }
+ sources = invoker.outputs
+ strip_prefix = "${invoker.base_out_dir}/python"
+ python_deps = invoker.deps
+ other_deps = [ ":$target_name._gen($default_toolchain)" ]
+ lint = false
- # Create a Python package with the generated source files.
- pw_python_package(target_name) {
- forward_variables_from(invoker, _forwarded_vars)
- setup = [ _setup_py ]
- sources = invoker.outputs
- python_deps = invoker.deps
- other_deps = [ ":$_target._package_gen($default_toolchain)" ]
- _pw_generated = true
+ _pw_module_as_package = invoker.module_as_package != ""
+ }
}
}
@@ -309,6 +324,7 @@
# compiled with protoc as "nested/foo.proto".
# strip_prefix: Remove this prefix from the source protos. All source and
# input files must be nested under this path.
+# python_package: Label of Python package in which to nest the proto modules.
#
template("pw_proto_library") {
assert(defined(invoker.sources) && invoker.sources != [],
@@ -348,8 +364,9 @@
# This is the output directory for all files related to this proto library.
# Sources are mirrored to "$base_out_dir/sources" and protoc puts outputs in
# "$base_out_dir/$language" by default.
- base_out_dir = get_label_info(":$target_name($default_toolchain)",
- "target_gen_dir") + "/$target_name"
+ base_out_dir =
+ get_label_info(":$target_name($default_toolchain)", "target_gen_dir") +
+ "/$target_name.proto_library"
compile_dir = "$base_out_dir/sources"
@@ -422,7 +439,7 @@
deps = process_file_template(_deps, "{{source}}._includes")
data_keys = [ "protoc_includes" ]
- outputs = [ "$target_gen_dir/${_common.base_target}/includes.txt" ]
+ outputs = [ "${_common.base_out_dir}/includes.txt" ]
# Indicate this library's base directory for its dependents.
metadata = {
@@ -537,6 +554,7 @@
_pw_python_proto_library("$target_name.python") {
forward_variables_from(_common, "*")
+ forward_variables_from(invoker, [ "python_package" ])
module_as_package = _module_as_package
deps = []