1 .. _module-pw_env_setup:
6 A classic problem in the embedded space is reducing the time from git clone
7 to having a binary executing on a device. The issue is that an entire suite
8 of tools is needed for non-trivial production embedded projects. For example:
10 - A C++ compiler for your target device, and also for your host
11 - A build system or three; for example, GN, Ninja, CMake, Bazel
12 - A code formatting program like clang-format
13 - A debugger like OpenOCD to flash and debug your embedded device
14 - A known Python version with known modules installed for scripting
15 - A Go compiler for the Go-based command line tools
19 In the server space, container solutions like Docker or Podman solve this;
20 however, in our experience container solutions are a mixed bag for embedded
21 systems development where one frequently needs access to native system
22 resources like USB devices, or must operate on Windows.
24 ``pw_env_setup`` is our compromise solution for this problem that works on Mac,
25 Windows, and Linux. It leverages the Chrome packaging system `CIPD`_ to
26 bootstrap a Python installation, which in turn inflates a virtual
27 environment. The tooling is installed into your workspace, and makes no
28 changes to your system. This tooling is designed to be reused by any
31 .. _CIPD: https://github.com/luci/luci-go/tree/master/cipd
33 Users interact with ``pw_env_setup`` with two commands: ``. bootstrap.sh`` and
34 ``. activate.sh``. The bootstrap command always pulls down the current versions
35 of CIPD packages and sets up the Python virtual environment. The activate
36 command reinitializes a previously configured environment, and if none is found,
40 On Windows the scripts used to set up the environment are ``bootstrap.bat``
41 and ``activate.bat``. For simplicity they will be referred to with the ``.sh``
42 endings unless the distinction is relevant.
45 At this time ``pw_env_setup`` works for us, but isn’t well tested. We don’t
46 suggest relying on it just yet. However, we are interested in experience
47 reports; if you give it a try, please `send us a note`_ about your
50 .. _send us a note: pigweed@googlegroups.com
52 ==================================
53 Using pw_env_setup in your project
54 ==================================
56 Downstream Projects Using Pigweed's Packages
57 ********************************************
59 Projects using Pigweed can leverage ``pw_env_setup`` to install Pigweed's
60 dependencies or their own dependencies. Projects that only want to use Pigweed's
61 dependencies without modifying them can just source Pigweed's ``bootstrap.sh``
62 and ``activate.sh`` scripts.
64 An example of what your project's `bootstrap.sh` could look like is below. This
65 assumes `bootstrap.sh` is at the top level of your repository.
69 # Do not include a "#!" line, this must be sourced and not executed.
71 # This assumes the user is sourcing this file from it's parent directory. See
72 # below for a more flexible way to handle this.
73 PROJ_SETUP_SCRIPT_PATH="$(pwd)/bootstrap.sh"
75 export PW_PROJECT_ROOT="$(_python_abspath "$(dirname "$PROJ_SETUP_SCRIPT_PATH")")"
77 # You may wish to check if the user is attempting to execute this script
78 # instead of sourcing it. See below for an example of how to handle that
81 # Source Pigweed's bootstrap utility script.
82 # Using '.' instead of 'source' for POSIX compatibility. Since users don't use
83 # dash directly, using 'source' in most documentation so users don't get
84 # confused and try to `./bootstrap.sh`.
85 . "$PW_PROJECT_ROOT/third_party/pigweed/pw_env_setup/util.sh"
87 pw_check_root "$PW_ROOT"
88 _PW_ACTUAL_ENVIRONMENT_ROOT="$(pw_get_env_root)"
89 export _PW_ACTUAL_ENVIRONMENT_ROOT
90 SETUP_SH="$_PW_ACTUAL_ENVIRONMENT_ROOT/activate.sh"
91 pw_bootstrap --args... # See below for details about args.
92 pw_finalize bootstrap "$SETUP_SH"
97 You may wish to allow sourcing `bootstrap.sh` from a different directory. In
98 that case you'll need the following at the top of `bootstrap.sh`.
103 python -c "import os.path; print(os.path.abspath('$@'))"
106 # Use this code from Pigweed's bootstrap to find the path to this script when
107 # sourced. This should work with common shells. PW_CHECKOUT_ROOT is only used in
108 # presubmit tests with strange setups, and can be omitted if you're not using
109 # Pigweed's automated testing infrastructure.
110 if test -n "$PW_CHECKOUT_ROOT"; then
111 PROJ_SETUP_SCRIPT_PATH="$(_python_abspath "$PW_CHECKOUT_ROOT/bootstrap.sh")"
112 unset PW_CHECKOUT_ROOT
114 elif test -n "$BASH"; then
115 PROJ_SETUP_SCRIPT_PATH="$(_python_abspath "$BASH_SOURCE")"
117 elif test -n "$ZSH_NAME"; then
118 PROJ_SETUP_SCRIPT_PATH="$(_python_abspath "${(%):-%N}")"
120 elif test ${0##*/} = dash; then
121 PROJ_SETUP_SCRIPT_PATH="$(_python_abspath \
122 "$(lsof -p $$ -Fn0 | tail -1 | sed 's#^[^/]*##;')")"
123 # If everything else fails, try $0. It could work.
125 PROJ_SETUP_SCRIPT_PATH="$(_python_abspath "$0")"
128 You may also wish to check if the user is attempting to execute `bootstrap.sh`
129 instead of sourcing it. Executing `bootstrap.sh` would download everything
130 required for the environment, but cannot modify the environment of the parent
131 process. To check for this add the following.
135 # Check if this file is being executed or sourced.
137 # If not running in Pigweed's automated testing infrastructure the
138 # SWARMING_BOT_ID check is unnecessary.
139 if [ -n "$SWARMING_BOT_ID" ]; then
140 # If set we're running on swarming and don't need this check.
142 elif [ -n "$ZSH_EVAL_CONTEXT" ]; then
143 case $ZSH_EVAL_CONTEXT in *:file) _pw_sourced=1;; esac
144 elif [ -n "$KSH_VERSION" ]; then
145 [ "$(cd $(dirname -- $0) && pwd -P)/$(basename -- $0)" != \
146 "$(cd $(dirname -- ${.sh.file}) && pwd -P)/$(basename -- ${.sh.file})" ] \
148 elif [ -n "$BASH_VERSION" ]; then
149 (return 0 2>/dev/null) && _pw_sourced=1
150 else # All other shells: examine $0 for known shell binary filenames
151 # Detects `sh` and `dash`; add additional shell filenames as needed.
152 case ${0##*/} in sh|dash) _pw_sourced=1;; esac
155 _pw_eval_sourced "$_pw_sourced"
157 Downstream Projects Using Different Packages
158 ********************************************
160 Projects depending on Pigweed but using additional or different packages should
161 copy the Pigweed `sample project`'s ``bootstrap.sh`` and update the call to
162 ``pw_bootstrap``. Search for "downstream" for other places that may require
163 changes, like setting the ``PW_ROOT`` and ``PW_PROJECT_ROOT`` environment
164 variables. Relevant arguments to ``pw_bootstrap`` are listed here.
166 .. _sample project: https://pigweed.googlesource.com/pigweed/sample_project/+/master
168 ``--use-pigweed-defaults``
169 Use Pigweed default values in addition to the other switches.
171 ``--cipd-package-file path/to/packages.json``
172 CIPD package file. JSON file consisting of a list of dictionaries with "path"
173 and "tags" keys, where "tags" is a list of strings.
175 ``--virtualenv-requierements path/to/requirements.txt``
176 Pip requirements file. Compiled with pip-compile.
178 ``--virtualenv-gn-target path/to/directory#package-install-target``
179 Target for installing Python packages, and the directory from which it must be
180 run. Example for Pigweed: ``third_party/pigweed#:python.install`` (assuming
181 Pigweed is included in the project at ``third_party/pigweed``). Downstream
182 projects will need to create targets to install their packages and either
183 choose a subset of Pigweed packages or use
184 ``third_party/pigweed#:python.install`` to install all Pigweed packages.
186 ``--cargo-package-file path/to/packages.txt``
187 Rust cargo packages to install. Lines with package name and version separated
188 by a space. Has no effect without ``--enable-cargo``.
191 Enable cargo package installation.
193 An example of the changed env_setup.py line is below.
198 --shell-file "$SETUP_SH" \
199 --install-dir "$_PW_ACTUAL_ENVIRONMENT_ROOT" \
200 --use-pigweed-defaults \
201 --cipd-package-file "$PW_PROJECT_ROOT/path/to/cipd.json" \
202 --virtualenv-gn-target "$PW_PROJECT_ROOT#:python.install"
204 Projects wanting some of the Pigweed environment packages but not all of them
205 should not use ``--use-pigweed-defaults`` and must manually add the references
206 to Pigweed default packages through the other arguments. The arguments below
207 are identical to using ``--use-pigweed-defaults``.
212 "$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json"
214 "$PW_ROOT/pw_env_setup/py/pw_env_setup/cipd_setup/luci.json"
215 --virtualenv-requirements
216 "$PW_ROOT/pw_env_setup/py/pw_env_setup/virtualenv_setup/requirements.txt"
217 --virtualenv-gn-target
218 "$PW_ROOT#:python.install"
220 "$PW_ROOT/pw_env_setup/py/pw_env_setup/cargo_setup/packages.txt"
222 Environment Variables
223 *********************
224 The following environment variables affect env setup behavior. Most users will
225 never need to set these.
228 Location of CIPD cache dir. Defaults to ``$HOME/.cipd-cache-dir``.
230 ``PW_ACTIVATE_SKIP_CHECKS``
231 If set, skip running ``pw doctor`` at end of bootstrap/activate. Intended to
232 be used by automated tools but not interactively.
234 ``PW_BOOTSTRAP_PYTHON``
235 Python executable to be used, for example "python2" or "python3". Defaults to
238 ``PW_ENVIRONMENT_ROOT``
239 Location to which packages are installed. Defaults to ``.environment`` folder
240 within the checkout root.
242 ``PW_ENVSETUP_DISABLE_SPINNER``
243 Disable the spinner during env setup. Intended to be used when the output is
244 being redirected to a log.
246 ``PW_ENVSETUP_QUIET``
247 Disables all non-error output.
252 The environment is set up by installing CIPD and Python packages in
253 ``PW_ENVIRONMENT_ROOT`` or ``<checkout>/.environment``, and saving modifications
254 to environment variables in setup scripts in those directories. To support
255 multiple operating systems this is done in an operating system-agnostic manner
256 and then written into operating system-specific files to be sourced now and in
257 the future when running ``activate.sh`` instead of ``bootstrap.sh``. In the
258 future these could be extended to C shell and PowerShell. A logical mapping of
259 high-level commands to system-specific initialization files is shown below.
261 .. image:: doc_resources/pw_env_setup_output.png
262 :alt: Mapping of high-level commands to system-specific commands.