xref: /aosp_15_r20/external/pigweed/pw_build/zip.gni (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1# Copyright 2020 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
15import("//build_overrides/pigweed.gni")
16
17import("$dir_pw_build/python_action.gni")
18
19# Takes a set of input sources and zips them up to a .zip output.
20#
21# Users can either pass in specific input files or entire directories.
22# This target type also supports renaming files as well as specifing
23# desired zip destination directories for each input source.
24#
25# Args:
26#   deps: Dependencies for this target.
27#
28#   inputs: List of input files following the custom input formatting
29#      convention. See below for syntax.
30#
31#   dirs: List of directories to be completely zipped up following the same
32#     input formatting convention. See below for syntax.
33#
34#   output: Filename of artifact .zip file produced by script's execution.
35#
36# Each input follows the following convention:
37#   /source_path > /zip_destination/
38#
39# All directories are expected to be end with a '/'. Inputs must always specify
40# both a source and a destination. Destinations are expected to have a leading
41# '/' which stands for the root of the archive.
42#
43# Example:
44#   Let's say we have the following structure for a //source/ directory:
45#
46#     source/
47#     ├── file1.txt
48#     ├── file2.txt
49#     ├── file3.txt
50#     └── some_dir/
51#         ├── file4.txt
52#         └── some_other_dir/
53#             └── file5.txt
54#
55#   And we create the following build target:
56#
57#     import("$dir_pw_build/zip.gni")
58#
59#     pw_zip("target_name") {
60#       inputs = [
61#         "//source/file1.txt > /",             # Copied to the zip root dir.
62#         "//source/file2.txt > /renamed.txt",  # File renamed.
63#         "//source/file3.txt > /bar/",         # File moved to the /bar/ dir.
64#       ]
65#
66#       dirs = [
67#         "//source/some_dir/ > /bar/some_dir/",  # Whole /some_dir/ contents
68#                                                 # copied as /bar/some_dir/.
69#       ]
70#
71#       # Note on output: if the specific output directory isn't defined
72#       # (such as output = "zoo.zip") then the .zip will output to the
73#       # same directory as the BUILD.gn file that called the target.
74#       output = "//$target_out_dir/foo.zip",  # Where the foo.zip will end up
75#     }
76#
77#   This will result in a .zip file called foo.zip stored in //$target_out_dir
78#   with the following structure:
79#
80#     foo.zip
81#     ├── bar/
82#     │   ├── file3.txt
83#     │   └── some_dir/
84#     │       ├── file4.txt
85#     │       └── some_other_dir/
86#     │           └── file5.txt
87#     ├── file1.txt
88#     └── renamed.txt
89#
90template("pw_zip") {
91  _delimiter = ">"
92  pw_python_action(target_name) {
93    forward_variables_from(invoker,
94                           [
95                             "deps",
96                             "public_deps",
97                           ])
98    script = "$dir_pw_build/py/pw_build/zip.py"
99
100    args = [ "--out_filename" ]
101    args += [ rebase_path(invoker.output, root_build_dir) ]
102
103    inputs = []
104    args += [ "--input_list" ]
105    if (defined(invoker.inputs)) {
106      foreach(input, invoker.inputs) {
107        # Adding spaces around our delimiter is great for readability,
108        # but not great for the string split: remove the spacing.
109        input = string_replace(input, " $_delimiter", _delimiter)
110        input = string_replace(input, "$_delimiter ", _delimiter)
111
112        input_list = []
113        input_list = string_split(input, _delimiter)
114        inputs += [ input_list[0] ]
115        input_list[0] = rebase_path(input_list[0], root_build_dir)
116
117        # Pass rebased and delimited path to script.
118        args += [ string_join(_delimiter, input_list) ]
119      }
120    }
121
122    if (defined(invoker.dirs)) {
123      foreach(dir, invoker.dirs) {
124        # Adding spaces around our delimiter is great for readability,
125        # but not great for the string split: remove the spacing.
126        dir = string_replace(dir, " $_delimiter", _delimiter)
127        dir = string_replace(dir, "$_delimiter ", _delimiter)
128
129        args += [ rebase_path(dir, root_build_dir) ]
130      }
131    }
132
133    outputs = [ invoker.output ]
134  }
135}
136