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# Updates a tokenized string database in the source tree with artifacts from one 20# or more targets. Other database files may also be used. 21# 22# The database file must exist. A CSV or binary database can be created with the 23# pw/pw_tokenizer/database.py tool. An empty CSV database file can be also 24# created as a starting point. 25# 26# Args: 27# database: if updating a database, path to an existing database in the source 28# tree; optional if creating a database, but may provide an output 29# directory path to override the default of 30# "$target_gen_dir/$target_name.[csv/binary]" 31# create: if specified, create a database instead of updating one; 'create' 32# must be set to one of the supported database types: "csv" or "binary" 33# targets: GN targets (executables or libraries) from which to add tokens; 34# these targets are added to deps 35# optional_targets: GN targets from which to add tokens, if the output files 36# already exist; these targets are NOT added to 'deps' 37# optional_paths: Paths or globs to files in the output directory from which 38# to add tokens. For example, "$root_build_dir/**/*.elf" finds all ELF 39# files in the output directory; this does NOT add anything to 'deps': add 40# targets to 'deps' or 'targets' if they must be built first 41# input_databases: paths to other database files from which to add tokens 42# deps: GN targets to build prior to generating the database; artifacts from 43# these targets are NOT implicitly used for database generation 44# domain: if provided, extract strings from tokenization domains matching this 45# regular expression 46# 47template("pw_tokenizer_database") { 48 assert(defined(invoker.database) || defined(invoker.create), 49 "pw_tokenizer_database requires a 'database' variable, unless " + 50 "'create' is specified") 51 52 if (defined(invoker.create)) { 53 assert(invoker.create == "csv" || invoker.create == "binary", 54 "If provided, 'create' must be \"csv\" or \"binary\"") 55 _create = invoker.create 56 } else { 57 _create = "" 58 } 59 60 if (defined(invoker.database)) { 61 _database = invoker.database 62 } else { 63 _database = "$target_gen_dir/$target_name.${invoker.create}" 64 } 65 if (defined(invoker.targets)) { 66 _targets = invoker.targets 67 } else { 68 _targets = [] 69 } 70 71 if (defined(invoker.optional_targets)) { 72 _optional_targets = invoker.optional_targets 73 } else { 74 _optional_targets = [] 75 } 76 77 if (defined(invoker.input_databases)) { 78 _input_databases = invoker.input_databases 79 } else { 80 _input_databases = [] 81 } 82 83 if (defined(invoker.domain)) { 84 _domain = "#" + invoker.domain 85 } else { 86 _domain = "" 87 } 88 89 if (_targets == [] && _optional_targets == []) { 90 # If no targets were specified, the domain will not be used, which is OK. 91 not_needed([ "_domain" ]) 92 } 93 94 pw_python_action(target_name) { 95 script = "$dir_pw_tokenizer/py/pw_tokenizer/database.py" 96 97 inputs = _input_databases 98 99 if (_create == "") { 100 # Restrict parallelism for updating this database file to one thread. This 101 # makes it safe to update it from multiple toolchains. 102 pool = "$dir_pw_tokenizer/pool:database($default_toolchain)" 103 args = [ "add" ] 104 if (defined(invoker.commit)) { 105 args += [ 106 "--discard-temporary", 107 invoker.commit, 108 ] 109 } 110 inputs += [ _database ] 111 stamp = true 112 } else { 113 args = [ 114 "create", 115 "--force", 116 "--type", 117 _create, 118 ] 119 outputs = [ _database ] 120 } 121 122 args += [ 123 "--database", 124 rebase_path(_database, root_build_dir), 125 ] 126 args += rebase_path(_input_databases, root_build_dir) 127 128 foreach(target, _targets) { 129 args += [ "<TARGET_FILE($target)>$_domain" ] 130 } 131 132 # For optional targets, the build outputs may not exist, since they aren't 133 # added to deps. Use TARGET_FILE_IF_EXISTS to handle this. 134 foreach(target, _optional_targets) { 135 args += [ "<TARGET_FILE_IF_EXISTS($target)>$_domain" ] 136 } 137 138 if (defined(invoker.optional_paths)) { 139 _paths = rebase_path(invoker.optional_paths, root_build_dir) 140 assert(filter_include(_paths, [ "../*" ]) == [], 141 "Paths in 'optional_paths' must be in the out directory. Use " + 142 "'input_databases' for files in the source tree.") 143 args += _paths 144 } 145 146 deps = _targets 147 148 if (defined(invoker.deps)) { 149 deps += invoker.deps 150 } 151 } 152} 153