pw_env_setup: Switch to using config JSON files
Change-Id: I7e209f8fe862e745db00d56c3f14046fd25ceb32
Bug: 327
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/34140
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Rob Mohr <mohrr@google.com>
diff --git a/bootstrap.bat b/bootstrap.bat
index 4ef0023..5c46a29 100644
--- a/bootstrap.bat
+++ b/bootstrap.bat
@@ -111,9 +111,7 @@
--pw-root "%PW_ROOT%" ^
--shell-file "%shell_file%" ^
--install-dir "%_PW_ACTUAL_ENVIRONMENT_ROOT%" ^
- --use-pigweed-defaults ^
- --virtualenv-gn-target "%PW_ROOT%#pw_env_setup:python.install" ^
- --virtualenv-gn-target "%PW_ROOT%#pw_env_setup:target_support_packages.install" ^
+ --config-file "%PW_ROOT%/pw_env_setup/config.json" ^
--project-root "%PW_PROJECT_ROOT%"
goto activate_shell
diff --git a/bootstrap.sh b/bootstrap.sh
index 06c427b..71006b9 100644
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -89,7 +89,7 @@
if [ "$(basename "$_BOOTSTRAP_PATH")" = "bootstrap.sh" ] || \
[ ! -f "$SETUP_SH" ] || \
[ ! -s "$SETUP_SH" ]; then
- pw_bootstrap --shell-file "$SETUP_SH" --install-dir "$_PW_ACTUAL_ENVIRONMENT_ROOT" --use-pigweed-defaults --json-file "$_PW_ACTUAL_ENVIRONMENT_ROOT/actions.json" --virtualenv-gn-out-dir "$PW_ROOT/out" --virtualenv-gn-target "$PW_ROOT#pw_env_setup:python.install" --virtualenv-gn-target "$PW_ROOT#pw_env_setup:target_support_packages.install"
+ pw_bootstrap --shell-file "$SETUP_SH" --install-dir "$_PW_ACTUAL_ENVIRONMENT_ROOT" --json-file "$_PW_ACTUAL_ENVIRONMENT_ROOT/actions.json" --config-file "$PW_ROOT/pw_env_setup/config.json"
pw_finalize bootstrap "$SETUP_SH"
else
pw_activate
diff --git a/pw_env_setup/compatibility.json b/pw_env_setup/compatibility.json
new file mode 100644
index 0000000..3c3cac7
--- /dev/null
+++ b/pw_env_setup/compatibility.json
@@ -0,0 +1,14 @@
+{
+ "cipd_package_files": [
+ "pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json",
+ "pw_env_setup/py/pw_env_setup/cipd_setup/luci.json"
+ "pw_env_setup/py/pw_env_setup/cipd_setup/compatibility.json"
+ ],
+ "virtualenv": {
+ "gn_root": ".",
+ "gn_targets": [
+ ":python.install",
+ ":target_support_packages.install"
+ ]
+ }
+}
diff --git a/pw_env_setup/config.json b/pw_env_setup/config.json
new file mode 100644
index 0000000..435be72
--- /dev/null
+++ b/pw_env_setup/config.json
@@ -0,0 +1,13 @@
+{
+ "cipd_package_files": [
+ "pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json",
+ "pw_env_setup/py/pw_env_setup/cipd_setup/luci.json"
+ ],
+ "virtualenv": {
+ "gn_root": ".",
+ "gn_targets": [
+ ":python.install",
+ ":target_support_packages.install"
+ ]
+ }
+}
diff --git a/pw_env_setup/docs.rst b/pw_env_setup/docs.rst
index 8c76c75..473f1b6 100644
--- a/pw_env_setup/docs.rst
+++ b/pw_env_setup/docs.rst
@@ -158,66 +158,45 @@
********************************************
Projects depending on Pigweed but using additional or different packages should
-copy the Pigweed `sample project`'s ``bootstrap.sh`` and update the call to
-``pw_bootstrap``. Search for "downstream" for other places that may require
-changes, like setting the ``PW_ROOT`` and ``PW_PROJECT_ROOT`` environment
-variables. Relevant arguments to ``pw_bootstrap`` are listed here.
+copy the Pigweed `sample project`'s ``bootstrap.sh`` and ``config.json`` and
+update the call to ``pw_bootstrap``. Search for "downstream" for other places
+that may require changes, like setting the ``PW_ROOT`` and ``PW_PROJECT_ROOT``
+environment variables. Explanations of parts of ``config.json`` are described
+here.
.. _sample project: https://pigweed.googlesource.com/pigweed/sample_project/+/master
-``--use-pigweed-defaults``
- Use Pigweed default values in addition to the other switches.
-
-``--cipd-package-file path/to/packages.json``
+``cipd_package_files``
CIPD package file. JSON file consisting of a list of dictionaries with "path"
and "tags" keys, where "tags" is a list of strings.
-``--virtualenv-requierements path/to/requirements.txt``
- Pip requirements file. Compiled with pip-compile.
+``virtualenv.gn_targets``
+ Target for installing Python packages. Downstream projects will need to
+ create targets to install their packages or only use Pigweed Python packages.
-``--virtualenv-gn-target path/to/directory#package-install-target``
- Target for installing Python packages, and the directory from which it must be
- run. Example for Pigweed: ``third_party/pigweed#:python.install`` (assuming
- Pigweed is included in the project at ``third_party/pigweed``). Downstream
- projects will need to create targets to install their packages and either
- choose a subset of Pigweed packages or use
- ``third_party/pigweed#:python.install`` to install all Pigweed packages.
+``virtualenv.gn_root``
+ The root directory of your GN build tree, relative to ``PW_PROJECT_ROOT``.
+ This is the directory your project's ``.gn`` file is located in. If you're
+ only installing Pigweed Python packages, use the location of the Pigweed
+ submodule.
-``--cargo-package-file path/to/packages.txt``
- Rust cargo packages to install. Lines with package name and version separated
- by a space. Has no effect without ``--enable-cargo``.
+An example of a config file is below.
-``--enable-cargo``
- Enable cargo package installation.
+.. code-block:: json
-An example of the changed env_setup.py line is below.
-
-.. code-block:: bash
-
- pw_bootstrap \
- --shell-file "$SETUP_SH" \
- --install-dir "$_PW_ACTUAL_ENVIRONMENT_ROOT" \
- --use-pigweed-defaults \
- --cipd-package-file "$PW_PROJECT_ROOT/path/to/cipd.json" \
- --virtualenv-gn-target "$PW_PROJECT_ROOT#:python.install"
-
-Projects wanting some of the Pigweed environment packages but not all of them
-should not use ``--use-pigweed-defaults`` and must manually add the references
-to Pigweed default packages through the other arguments. The arguments below
-are identical to using ``--use-pigweed-defaults``.
-
-.. code-block:: bash
-
- --cipd-package-file
- "$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json"
- --cipd-package-file
- "$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/luci.json"
- --virtualenv-requirements
- "$PW_ROOT/pw_env_setup/py/pw_env_setup/virtualenv_setup/requirements.txt"
- --virtualenv-gn-target
- "$PW_ROOT#:python.install"
- --cargo-package-file
- "$PW_ROOT/pw_env_setup/py/pw_env_setup/cargo_setup/packages.txt"
+ {
+ "cipd_package_files": [
+ "pigweed/pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json",
+ "pigweed/pw_env_setup/py/pw_env_setup/cipd_setup/luci.json"
+ "tools/packages.json"
+ ],
+ "virtualenv": {
+ "gn_root": ".",
+ "gn_targets": [
+ ":python.install",
+ ]
+ }
+ }
Environment Variables
*********************
diff --git a/pw_env_setup/py/pw_env_setup/env_setup.py b/pw_env_setup/py/pw_env_setup/env_setup.py
index a05663b..42470c8 100755
--- a/pw_env_setup/py/pw_env_setup/env_setup.py
+++ b/pw_env_setup/py/pw_env_setup/env_setup.py
@@ -166,6 +166,10 @@
return result
+class ConfigFileError(Exception):
+ pass
+
+
# TODO(mohrr) remove disable=useless-object-inheritance once in Python 3.
# pylint: disable=useless-object-inheritance
# pylint: disable=too-many-instance-attributes
@@ -176,7 +180,7 @@
use_pigweed_defaults, cipd_package_file, virtualenv_root,
virtualenv_requirements, virtualenv_gn_target,
virtualenv_gn_out_dir, cargo_package_file, enable_cargo,
- json_file, project_root):
+ json_file, project_root, config_file):
self._env = environment.Environment()
self._project_root = project_root
self._pw_root = pw_root
@@ -202,6 +206,9 @@
self._cargo_package_file = []
self._enable_cargo = enable_cargo
+ if config_file:
+ self._parse_config_file(config_file)
+
self._json_file = json_file
setup_root = os.path.join(pw_root, 'pw_env_setup', 'py',
@@ -238,6 +245,33 @@
self._env.add_replacement('_PW_ACTUAL_ENVIRONMENT_ROOT', install_dir)
self._env.add_replacement('PW_ROOT', pw_root)
+ def _parse_config_file(self, config_file):
+ config = json.load(config_file)
+
+ self._cipd_package_file.extend(
+ os.path.join(self._project_root, x)
+ for x in config.pop('cipd_package_files', ()))
+
+ virtualenv = config.pop('virtualenv', {})
+
+ if virtualenv.get('gn_root'):
+ root = os.path.join(self._project_root, virtualenv.pop('gn_root'))
+ else:
+ root = self._project_root
+
+ for target in virtualenv.pop('gn_targets', ()):
+ self._virtualenv_gn_targets.append(
+ virtualenv_setup.GnTarget('{}#{}'.format(root, target)))
+
+ if virtualenv:
+ raise ConfigFileError(
+ 'unrecognized option in {}: "virtualenv.{}"'.format(
+ config_file.name, next(iter(virtualenv))))
+
+ if config:
+ raise ConfigFileError('unrecognized option in {}: "{}"'.format(
+ config_file.name, next(iter(config))))
+
def _log(self, *args, **kwargs):
# Not using logging module because it's awkward to flush a log handler.
if self._quiet:
@@ -505,6 +539,12 @@
)
parser.add_argument(
+ '--config-file',
+ help='JSON file describing CIPD and virtualenv requirements.',
+ type=argparse.FileType('r'),
+ )
+
+ parser.add_argument(
'--use-pigweed-defaults',
help='Use Pigweed default values in addition to the given environment '
'variables.',
@@ -570,7 +610,7 @@
args = parser.parse_args(argv)
- one_required = (
+ others = (
'use_pigweed_defaults',
'cipd_package_file',
'virtualenv_requirements',
@@ -578,10 +618,17 @@
'cargo_package_file',
)
+ one_required = others + ('config_file', )
+
if not any(getattr(args, x) for x in one_required):
parser.error('At least one of ({}) is required'.format(', '.join(
'"--{}"'.format(x.replace('_', '-')) for x in one_required)))
+ if args.config_file and any(getattr(args, x) for x in others):
+ parser.error('Cannot combine --config-file with any of {}'.format(
+ ', '.join('"--{}"'.format(x.replace('_', '-'))
+ for x in one_required)))
+
return args
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
index 8e798ea..9a227c8 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
@@ -218,6 +218,7 @@
build_dir,
'--args=dir_pigweed="{}"'.format(pw_root),
)
+ print(gn_cmd, file=outs)
subprocess.check_call(gn_cmd,
cwd=os.path.join(project_root,
gn_target.directory),
@@ -234,6 +235,7 @@
with open(ninja_log_path, 'w') as outs:
ninja_cmd = ['ninja', '-C', build_dir]
ninja_cmd.append(gn_target.target)
+ print(ninja_cmd, file=outs)
subprocess.check_call(ninja_cmd, stdout=outs, stderr=outs)
except subprocess.CalledProcessError as err:
with open(ninja_log_path, 'r') as ins: