| # 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. |
| template("pw_python_wheels") { |
| _outer_name = target_name |
| _wheel_paths_path = "${target_gen_dir}/${target_name}_wheel_paths.txt" |
| |
| _deps = [] |
| if (defined(invoker.deps)) { |
| _deps = invoker.deps |
| } |
| |
| _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 + [ ":${_outer_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("${target_out_dir}/python_wheels", 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 |
| } |
| |
| pw_python_wheels("${target_name}.wheels") { |
| packages = invoker.packages |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "public_deps", |
| ]) |
| } |
| |
| pw_zip("${target_name}") { |
| forward_variables_from(invoker, [ "public_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}/python_wheels/ > /${target_name}/python_wheels/" ] |
| |
| output = _zip_path |
| |
| 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" ] |
| } |
| } |
| } |