1# Copyright 2022 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"""Serializes an Environment into a JSON file.""" 15 16from __future__ import print_function 17 18import ntpath 19import os 20import posixpath 21import re 22 23# Disable super() warnings since this file must be Python 2 compatible. 24# pylint: disable=super-with-arguments 25 26 27class GNIVisitor(object): # pylint: disable=useless-object-inheritance 28 """Serializes portions of an Environment into a gni file. 29 30 Example gni file: 31 32 declare_args() { 33 pw_env_setup_CIPD_ARM = "//<ENVIRONMENT_DIR>/cipd/packages/arm" 34 pw_env_setup_CIPD_BAZEL = "//<ENVIRONMENT_DIR>/cipd/packages/bazel" 35 pw_env_setup_CIPD_DEFAULT = "//<ENVIRONMENT_DIR>/cipd/packages/default" 36 pw_env_setup_CIPD_LUCI = "//<ENVIRONMENT_DIR>/cipd/packages/luci" 37 pw_env_setup_CIPD_PIGWEED = "//<ENVIRONMENT_DIR>/cipd/packages/pigweed" 38 pw_env_setup_CIPD_PYTHON = "//<ENVIRONMENT_DIR>/cipd/packages/python" 39 pw_env_setup_VIRTUAL_ENV = "//<ENVIRONMENT_DIR>/pigweed-venv" 40 } 41 """ 42 43 def __init__(self, project_root, gni_file, *args, **kwargs): 44 super(GNIVisitor, self).__init__(*args, **kwargs) 45 self._project_root = project_root 46 self._gni_file = gni_file 47 self._variables = {} # Dict of variables to set. 48 49 def _gn_variables(self, env): 50 self._variables.clear() 51 env.accept(self) 52 variables = dict(self._variables) 53 self._variables.clear() 54 return variables 55 56 def serialize(self, env, outs): 57 """Write a gni file based on the given environment. 58 59 Args: 60 env (environment.Environment): Environment variables to use. 61 outs (file): GNI file to write. 62 """ 63 64 print( 65 """ 66# This file is automatically generated by Pigweed's environment setup. Do not 67# edit it manually or check it in. 68 69# Relative paths are interpreted with respect to this file, which helps 70# determine the correct path even if the source root changes. 71 """.strip(), 72 file=outs, 73 ) 74 75 print('declare_args() {', file=outs) 76 for name, value in sorted(self._gn_variables(env).items()): 77 print(' {} = {}'.format(name, value), file=outs) 78 print('}', file=outs) 79 80 def _abspath_to_gn_path(self, path): 81 gn_dir = os.path.join( 82 self._project_root, os.path.dirname(self._gni_file) 83 ) 84 # Use relative paths within the project root: 85 if path.startswith(self._project_root + os.sep): 86 gn_path = os.path.relpath(path, start=gn_dir) 87 else: 88 gn_path = path 89 if os.name == 'nt': 90 # GN paths are posix-style, so convert to posix. This 91 # find-and-replace is a little crude, but python 2.7 doesn't support 92 # pathlib. 93 gn_path = gn_path.replace(ntpath.sep, posixpath.sep) 94 return 'get_path_info("{}", "abspath")'.format(gn_path) 95 96 def visit_set(self, set): # pylint: disable=redefined-builtin 97 match = re.search(r'PW_(.*)_CIPD_INSTALL_DIR', set.name) 98 name = None 99 100 if match: 101 name = 'pw_env_setup_CIPD_{}'.format(match.group(1)) 102 if set.name == 'VIRTUAL_ENV': 103 name = 'pw_env_setup_VIRTUAL_ENV' 104 if set.name == 'PW_PACKAGE_ROOT': 105 name = 'pw_env_setup_PACKAGE_ROOT' 106 107 if name: 108 self._variables[name] = self._abspath_to_gn_path(set.value) 109 110 def visit_clear(self, clear): 111 pass 112 113 def visit_remove(self, remove): 114 pass 115 116 def visit_prepend(self, prepend): 117 pass 118 119 def visit_append(self, append): 120 pass 121 122 def visit_echo(self, echo): 123 pass 124 125 def visit_comment(self, comment): 126 pass 127 128 def visit_command(self, command): 129 pass 130 131 def visit_doctor(self, doctor): 132 pass 133 134 def visit_blank_line(self, blank_line): 135 pass 136 137 def visit_function(self, function): 138 pass 139 140 def visit_hash(self, hash): # pylint: disable=redefined-builtin 141 pass 142