1*6777b538SAndroid Build Coastguard Worker# Copyright 2018 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker# Creates a group() that lists Python sources as |data|. 6*6777b538SAndroid Build Coastguard Worker# Having such targets serves two purposes: 7*6777b538SAndroid Build Coastguard Worker# 1) Causes files to be included in runtime_deps, so that they are uploaded to 8*6777b538SAndroid Build Coastguard Worker# swarming when running tests remotely. 9*6777b538SAndroid Build Coastguard Worker# 2) Causes "gn analyze" to know about all Python inputs so that tests will be 10*6777b538SAndroid Build Coastguard Worker# re-run when relevant Python files change. 11*6777b538SAndroid Build Coastguard Worker# 12*6777b538SAndroid Build Coastguard Worker# All non-trivial Python scripts should use a "pydeps" file to track their 13*6777b538SAndroid Build Coastguard Worker# sources. To create a .pydep file for a target in //example: 14*6777b538SAndroid Build Coastguard Worker# 15*6777b538SAndroid Build Coastguard Worker# build/print_python_deps.py \ 16*6777b538SAndroid Build Coastguard Worker# --root example \ 17*6777b538SAndroid Build Coastguard Worker# --output example/$target_name.pydeps \ 18*6777b538SAndroid Build Coastguard Worker# path/to/your/script.py 19*6777b538SAndroid Build Coastguard Worker# 20*6777b538SAndroid Build Coastguard Worker# Keep the .pydep file up-to-date by adding to //PRESUBMIT.py under one of: 21*6777b538SAndroid Build Coastguard Worker# _ANDROID_SPECIFIC_PYDEPS_FILES, _GENERIC_PYDEPS_FILES 22*6777b538SAndroid Build Coastguard Worker# 23*6777b538SAndroid Build Coastguard Worker# Variables 24*6777b538SAndroid Build Coastguard Worker# pydeps_file: Path to .pydeps file to read sources from (optional). 25*6777b538SAndroid Build Coastguard Worker# data: Additional files to include in data. E.g. non-.py files needed by the 26*6777b538SAndroid Build Coastguard Worker# library, or .py files that are conditionally / lazily imported. 27*6777b538SAndroid Build Coastguard Worker# 28*6777b538SAndroid Build Coastguard Worker# Example 29*6777b538SAndroid Build Coastguard Worker# python_library("my_library_py") { 30*6777b538SAndroid Build Coastguard Worker# pydeps_file = "my_library.pydeps" 31*6777b538SAndroid Build Coastguard Worker# data = [ "foo.dat" ] 32*6777b538SAndroid Build Coastguard Worker# } 33*6777b538SAndroid Build Coastguard Workertemplate("python_library") { 34*6777b538SAndroid Build Coastguard Worker group(target_name) { 35*6777b538SAndroid Build Coastguard Worker forward_variables_from(invoker, 36*6777b538SAndroid Build Coastguard Worker [ 37*6777b538SAndroid Build Coastguard Worker "data_deps", 38*6777b538SAndroid Build Coastguard Worker "deps", 39*6777b538SAndroid Build Coastguard Worker "testonly", 40*6777b538SAndroid Build Coastguard Worker "visibility", 41*6777b538SAndroid Build Coastguard Worker ]) 42*6777b538SAndroid Build Coastguard Worker 43*6777b538SAndroid Build Coastguard Worker if (defined(invoker.pydeps_file)) { 44*6777b538SAndroid Build Coastguard Worker # Read and filter out comments. 45*6777b538SAndroid Build Coastguard Worker _pydeps_lines = read_file(invoker.pydeps_file, "list lines") 46*6777b538SAndroid Build Coastguard Worker _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ]) 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker # Dependencies are listed relative to the pydeps file directory, but data 49*6777b538SAndroid Build Coastguard Worker # parameter expects paths that are relative to the current BUILD.gn 50*6777b538SAndroid Build Coastguard Worker _script_dir = get_path_info(invoker.pydeps_file, "dir") 51*6777b538SAndroid Build Coastguard Worker _rebased_pydeps_entries = rebase_path(_pydeps_entries, ".", _script_dir) 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker # Even though the .pydep file is not used at runtime, it must be added 54*6777b538SAndroid Build Coastguard Worker # so that "gn analyze" will mark the target as changed when .py files 55*6777b538SAndroid Build Coastguard Worker # are removed but none are added or modified. 56*6777b538SAndroid Build Coastguard Worker data = _rebased_pydeps_entries + [ invoker.pydeps_file ] 57*6777b538SAndroid Build Coastguard Worker } else { 58*6777b538SAndroid Build Coastguard Worker data = [] 59*6777b538SAndroid Build Coastguard Worker } 60*6777b538SAndroid Build Coastguard Worker if (defined(invoker.data)) { 61*6777b538SAndroid Build Coastguard Worker data += invoker.data 62*6777b538SAndroid Build Coastguard Worker } 63*6777b538SAndroid Build Coastguard Worker } 64*6777b538SAndroid Build Coastguard Worker} 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Worker# A template used for actions that execute a Python script, which has an 67*6777b538SAndroid Build Coastguard Worker# associated .pydeps file. In other words: 68*6777b538SAndroid Build Coastguard Worker# 69*6777b538SAndroid Build Coastguard Worker# - This is very similar to just an action(), except that |script| must point 70*6777b538SAndroid Build Coastguard Worker# to a Python script (e.g. "//build/.../foo.py") that has a corresponding 71*6777b538SAndroid Build Coastguard Worker# .pydeps file in the source tree (e.g. "//build/.../foo.pydeps"). 72*6777b538SAndroid Build Coastguard Worker# 73*6777b538SAndroid Build Coastguard Worker# - The .pydeps file contains a list of python dependencies (imports really) 74*6777b538SAndroid Build Coastguard Worker# and is generated _manually_ by using a command like: 75*6777b538SAndroid Build Coastguard Worker# 76*6777b538SAndroid Build Coastguard Worker# build/print_python_deps.py --inplace build/android/gyp/foo.py 77*6777b538SAndroid Build Coastguard Worker# 78*6777b538SAndroid Build Coastguard Worker# Example 79*6777b538SAndroid Build Coastguard Worker# action_with_pydeps("create_foo") { 80*6777b538SAndroid Build Coastguard Worker# script = "myscript.py" 81*6777b538SAndroid Build Coastguard Worker# args = [...] 82*6777b538SAndroid Build Coastguard Worker# } 83*6777b538SAndroid Build Coastguard Workertemplate("action_with_pydeps") { 84*6777b538SAndroid Build Coastguard Worker action(target_name) { 85*6777b538SAndroid Build Coastguard Worker # Ensure that testonly and visibility are forwarded 86*6777b538SAndroid Build Coastguard Worker # explicitly, since this performs recursive scope lookups, which is 87*6777b538SAndroid Build Coastguard Worker # required to ensure their definition from scopes above the caller are 88*6777b538SAndroid Build Coastguard Worker # properly handled. All other variables are forwarded with "*", which 89*6777b538SAndroid Build Coastguard Worker # doesn't perform recursive lookups at all. See https://crbug.com/862232 90*6777b538SAndroid Build Coastguard Worker forward_variables_from(invoker, 91*6777b538SAndroid Build Coastguard Worker [ 92*6777b538SAndroid Build Coastguard Worker "testonly", 93*6777b538SAndroid Build Coastguard Worker "visibility", 94*6777b538SAndroid Build Coastguard Worker ]) 95*6777b538SAndroid Build Coastguard Worker forward_variables_from(invoker, 96*6777b538SAndroid Build Coastguard Worker "*", 97*6777b538SAndroid Build Coastguard Worker [ 98*6777b538SAndroid Build Coastguard Worker "testonly", 99*6777b538SAndroid Build Coastguard Worker "visibility", 100*6777b538SAndroid Build Coastguard Worker ]) 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Worker # Read and filter out comments. 103*6777b538SAndroid Build Coastguard Worker # Happens every time the template is instantiated, but benchmarking shows no 104*6777b538SAndroid Build Coastguard Worker # perceivable impact on overall 'gn gen' speed. 105*6777b538SAndroid Build Coastguard Worker _pydeps_file = invoker.script + "deps" 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker _pydeps_lines = 108*6777b538SAndroid Build Coastguard Worker read_file(_pydeps_file, "list lines") # https://crbug.com/1102058 109*6777b538SAndroid Build Coastguard Worker _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ]) 110*6777b538SAndroid Build Coastguard Worker 111*6777b538SAndroid Build Coastguard Worker if (!defined(inputs)) { 112*6777b538SAndroid Build Coastguard Worker inputs = [] 113*6777b538SAndroid Build Coastguard Worker } 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker # Dependencies are listed relative to the script directory, but inputs 116*6777b538SAndroid Build Coastguard Worker # expects paths that are relative to the current BUILD.gn 117*6777b538SAndroid Build Coastguard Worker _script_dir = get_path_info(_pydeps_file, "dir") 118*6777b538SAndroid Build Coastguard Worker inputs += rebase_path(_pydeps_entries, ".", _script_dir) 119*6777b538SAndroid Build Coastguard Worker } 120*6777b538SAndroid Build Coastguard Worker} 121*6777b538SAndroid Build Coastguard Worker 122*6777b538SAndroid Build Coastguard Workertemplate("action_foreach_with_pydeps") { 123*6777b538SAndroid Build Coastguard Worker action_foreach(target_name) { 124*6777b538SAndroid Build Coastguard Worker # Ensure that testonly and visibility are forwarded 125*6777b538SAndroid Build Coastguard Worker # explicitly, since this performs recursive scope lookups, which is 126*6777b538SAndroid Build Coastguard Worker # required to ensure their definition from scopes above the caller are 127*6777b538SAndroid Build Coastguard Worker # properly handled. All other variables are forwarded with "*", which 128*6777b538SAndroid Build Coastguard Worker # doesn't perform recursive lookups at all. See https://crbug.com/862232 129*6777b538SAndroid Build Coastguard Worker forward_variables_from(invoker, 130*6777b538SAndroid Build Coastguard Worker [ 131*6777b538SAndroid Build Coastguard Worker "testonly", 132*6777b538SAndroid Build Coastguard Worker "visibility", 133*6777b538SAndroid Build Coastguard Worker ]) 134*6777b538SAndroid Build Coastguard Worker forward_variables_from(invoker, 135*6777b538SAndroid Build Coastguard Worker "*", 136*6777b538SAndroid Build Coastguard Worker [ 137*6777b538SAndroid Build Coastguard Worker "testonly", 138*6777b538SAndroid Build Coastguard Worker "visibility", 139*6777b538SAndroid Build Coastguard Worker ]) 140*6777b538SAndroid Build Coastguard Worker 141*6777b538SAndroid Build Coastguard Worker # Read and filter out comments. 142*6777b538SAndroid Build Coastguard Worker # Happens every time the template is instantiated, but benchmarking shows no 143*6777b538SAndroid Build Coastguard Worker # perceivable impact on overall 'gn gen' speed. 144*6777b538SAndroid Build Coastguard Worker if (defined(invoker.deps_file)) { 145*6777b538SAndroid Build Coastguard Worker _pydeps_file = invoker.deps_file 146*6777b538SAndroid Build Coastguard Worker } else { 147*6777b538SAndroid Build Coastguard Worker _pydeps_file = invoker.script + "deps" 148*6777b538SAndroid Build Coastguard Worker } 149*6777b538SAndroid Build Coastguard Worker _pydeps_lines = read_file(_pydeps_file, "list lines") 150*6777b538SAndroid Build Coastguard Worker _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ]) 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker if (!defined(inputs)) { 153*6777b538SAndroid Build Coastguard Worker inputs = [] 154*6777b538SAndroid Build Coastguard Worker } 155*6777b538SAndroid Build Coastguard Worker 156*6777b538SAndroid Build Coastguard Worker # Dependencies are listed relative to the script directory, but inputs 157*6777b538SAndroid Build Coastguard Worker # expects paths that are relative to the current BUILD.gn 158*6777b538SAndroid Build Coastguard Worker _script_dir = get_path_info(script, "dir") 159*6777b538SAndroid Build Coastguard Worker inputs += rebase_path(_pydeps_entries, ".", _script_dir) 160*6777b538SAndroid Build Coastguard Worker } 161*6777b538SAndroid Build Coastguard Worker} 162