258 lines
8.7 KiB
Plaintext
258 lines
8.7 KiB
Plaintext
# Copyright 2021 The Pigweed Authors
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
# use this file except in compliance with the License. You may obtain a copy of
|
|
# the License at
|
|
#
|
|
# https://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations under
|
|
# the License.
|
|
|
|
import("//build_overrides/pigweed.gni")
|
|
|
|
import("$dir_pw_build/python.gni")
|
|
import("$dir_pw_build/python_action.gni")
|
|
import("$dir_pw_build/zip.gni")
|
|
|
|
# Builds a directory containing a collection of Python wheels.
|
|
#
|
|
# Given one or more pw_python_package targets, this target will build their
|
|
# .wheel sub-targets along with the .wheel sub-targets of all dependencies,
|
|
# direct and indirect, as understood by GN. The resulting .whl files will be
|
|
# collected into a single directory called 'python_wheels'.
|
|
#
|
|
# Args:
|
|
# packages: A list of pw_python_package targets whose wheels should be
|
|
# included; their dependencies will be pulled in as wheels also.
|
|
# directory: output directory for the wheels; defaults to
|
|
# $target_out_dir/$target_name
|
|
# deps: additional dependencies
|
|
#
|
|
template("pw_python_wheels") {
|
|
_wheel_paths_path = "${target_gen_dir}/${target_name}_wheel_paths.txt"
|
|
|
|
_deps = []
|
|
if (defined(invoker.deps)) {
|
|
_deps = invoker.deps
|
|
}
|
|
|
|
if (defined(invoker.directory)) {
|
|
_directory = invoker.directory
|
|
} else {
|
|
_directory = "$target_out_dir/$target_name"
|
|
}
|
|
|
|
_packages = []
|
|
foreach(_pkg, invoker.packages) {
|
|
_pkg_name = get_label_info(_pkg, "label_no_toolchain")
|
|
_pkg_toolchain = get_label_info(_pkg, "toolchain")
|
|
_packages += [ "${_pkg_name}.wheel(${_pkg_toolchain})" ]
|
|
}
|
|
|
|
# Build a list of relative paths containing all the wheels we depend on.
|
|
generated_file("${target_name}._wheel_paths") {
|
|
data_keys = [ "pw_python_package_wheels" ]
|
|
rebase = root_build_dir
|
|
deps = _packages
|
|
outputs = [ _wheel_paths_path ]
|
|
}
|
|
|
|
pw_python_action(target_name) {
|
|
forward_variables_from(invoker, [ "public_deps" ])
|
|
deps = _deps + [ ":$target_name._wheel_paths" ]
|
|
module = "pw_build.collect_wheels"
|
|
|
|
args = [
|
|
"--prefix",
|
|
rebase_path(root_build_dir, root_build_dir),
|
|
"--suffix",
|
|
rebase_path(_wheel_paths_path, root_build_dir),
|
|
"--out_dir",
|
|
rebase_path(_directory, root_build_dir),
|
|
]
|
|
|
|
stamp = true
|
|
}
|
|
}
|
|
|
|
# Builds a .zip containing Python wheels and setup scripts.
|
|
#
|
|
# The resulting .zip archive will contain a directory with Python wheels for
|
|
# all pw_python_package targets listed in 'packages', plus wheels for any
|
|
# pw_python_package targets those packages depend on, directly or indirectly,
|
|
# as understood by GN.
|
|
#
|
|
# In addition to Python wheels, the resulting .zip will also contain simple
|
|
# setup scripts for Linux, MacOS, and Windows that take care of creating a
|
|
# Python venv and installing all the included wheels into it, and a README.md
|
|
# file with setup and usage instructions.
|
|
#
|
|
# Args:
|
|
# packages: A list of pw_python_package targets whose wheels should be
|
|
# included; their dependencies will be pulled in as wheels also.
|
|
# inputs: An optional list of extra files to include in the generated .zip,
|
|
# formatted the same was as the 'inputs' argument to pw_zip targets.
|
|
# dirs: An optional list of directories to include in the generated .zip,
|
|
# formatted the same way as the 'dirs' argument to pw_zip targets.
|
|
template("pw_python_zip_with_setup") {
|
|
_outer_name = target_name
|
|
_zip_path = "${target_out_dir}/${target_name}.zip"
|
|
|
|
_inputs = []
|
|
if (defined(invoker.inputs)) {
|
|
_inputs = invoker.inputs
|
|
}
|
|
_dirs = []
|
|
if (defined(invoker.dirs)) {
|
|
_dirs = invoker.dirs
|
|
}
|
|
_public_deps = []
|
|
if (defined(invoker.public_deps)) {
|
|
_public_deps = invoker.public_deps
|
|
}
|
|
|
|
pw_python_wheels("$target_name.wheels") {
|
|
packages = invoker.packages
|
|
forward_variables_from(invoker, [ "deps" ])
|
|
}
|
|
|
|
pw_zip(target_name) {
|
|
forward_variables_from(invoker, [ "deps" ])
|
|
inputs = _inputs + [
|
|
"$dir_pw_build/python_dist/setup.bat > /${target_name}/",
|
|
"$dir_pw_build/python_dist/setup.sh > /${target_name}/",
|
|
]
|
|
|
|
dirs = _dirs + [ "$target_out_dir/$target_name.wheels/ > /$target_name/python_wheels/" ]
|
|
|
|
output = _zip_path
|
|
|
|
# TODO(pwbug/634): Remove the plumbing-through of invoker's public_deps.
|
|
public_deps = _public_deps + [ ":${_outer_name}.wheels" ]
|
|
}
|
|
}
|
|
|
|
# Generates a directory of Python packages from source files suitable for
|
|
# deployment outside of the project developer environment.
|
|
#
|
|
# The resulting directory contains only files mentioned in each package's
|
|
# setup.cfg file. This is useful for bundling multiple Python packages up
|
|
# into a single package for distribution to other locations like
|
|
# http://pypi.org.
|
|
#
|
|
# Args:
|
|
# packages: A list of pw_python_package targets to be installed into the build
|
|
# directory. Their dependencies will be pulled in as wheels also.
|
|
#
|
|
# include_tests: If true, copy Python package tests to a `tests` subdir.
|
|
#
|
|
# extra_files: A list of extra files that should be included in the output. The
|
|
# format of each item in this list follows this convention:
|
|
# //some/nested/source_file > nested/destination_file
|
|
template("pw_create_python_source_tree") {
|
|
_output_dir = "${target_out_dir}/${target_name}/"
|
|
_metadata_json_file_list =
|
|
"${target_gen_dir}/${target_name}_metadata_path_list.txt"
|
|
|
|
# If generating a setup.cfg file a common base file must be provided.
|
|
if (defined(invoker.generate_setup_cfg)) {
|
|
generate_setup_cfg = invoker.generate_setup_cfg
|
|
assert(defined(generate_setup_cfg.common_config_file),
|
|
"'common_config_file' is required in generate_setup_cfg")
|
|
}
|
|
|
|
_extra_file_inputs = []
|
|
_extra_file_args = []
|
|
|
|
# Convert extra_file strings to input, outputs and create_python_tree.py args.
|
|
if (defined(invoker.extra_files)) {
|
|
_delimiter = ">"
|
|
_extra_file_outputs = []
|
|
foreach(input, invoker.extra_files) {
|
|
# Remove spaces before and after the delimiter
|
|
input = string_replace(input, " $_delimiter", _delimiter)
|
|
input = string_replace(input, "$_delimiter ", _delimiter)
|
|
|
|
input_list = []
|
|
input_list = string_split(input, _delimiter)
|
|
|
|
# Save the input file
|
|
_extra_file_inputs += [ input_list[0] ]
|
|
|
|
# Save the output file
|
|
_this_output = _output_dir + "/" + input_list[1]
|
|
_extra_file_outputs += [ _this_output ]
|
|
|
|
# Compose an arg for passing to create_python_tree.py with properly
|
|
# rebased paths.
|
|
_extra_file_args +=
|
|
[ string_join(" $_delimiter ",
|
|
[
|
|
rebase_path(input_list[0], root_build_dir),
|
|
rebase_path(_this_output, root_build_dir),
|
|
]) ]
|
|
}
|
|
}
|
|
|
|
_include_tests = defined(invoker.include_tests) && invoker.include_tests
|
|
|
|
# Build a list of relative paths containing all the python
|
|
# package_metadata.json files we depend on.
|
|
generated_file("${target_name}._metadata_path_list.txt") {
|
|
data_keys = [ "pw_python_package_metadata_json" ]
|
|
rebase = root_build_dir
|
|
deps = invoker.packages
|
|
outputs = [ _metadata_json_file_list ]
|
|
}
|
|
|
|
# Run the python action on the metadata_path_list.txt file
|
|
pw_python_action(target_name) {
|
|
deps =
|
|
invoker.packages + [ ":${invoker.target_name}._metadata_path_list.txt" ]
|
|
script = "$dir_pw_build/py/pw_build/create_python_tree.py"
|
|
inputs = _extra_file_inputs
|
|
|
|
args = [
|
|
"--tree-destination-dir",
|
|
rebase_path(_output_dir, root_build_dir),
|
|
"--input-list-files",
|
|
rebase_path(_metadata_json_file_list, root_build_dir),
|
|
]
|
|
|
|
# Add required setup.cfg args if we are generating a merged config.
|
|
if (defined(generate_setup_cfg)) {
|
|
if (defined(generate_setup_cfg.common_config_file)) {
|
|
args += [
|
|
"--setupcfg-common-file",
|
|
rebase_path(generate_setup_cfg.common_config_file, root_build_dir),
|
|
]
|
|
}
|
|
if (defined(generate_setup_cfg.append_git_sha_to_version)) {
|
|
args += [ "--setupcfg-version-append-git-sha" ]
|
|
}
|
|
if (defined(generate_setup_cfg.append_date_to_version)) {
|
|
args += [ "--setupcfg-version-append-date" ]
|
|
}
|
|
}
|
|
|
|
if (_extra_file_args == []) {
|
|
# No known output files - stamp instead.
|
|
stamp = true
|
|
} else {
|
|
args += [ "--extra-files" ]
|
|
args += _extra_file_args
|
|
|
|
# Include extra_files as outputs
|
|
outputs = _extra_file_outputs
|
|
}
|
|
|
|
if (_include_tests) {
|
|
args += [ "--include-tests" ]
|
|
}
|
|
}
|
|
}
|