| #!/bin/bash |
| # Copyright 2025 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| |
| # This is a light wrapper script to seamlessly run the //:pw tool while |
| # forwarding arguments. This is written as a shell script for three reasons: |
| # |
| # 1. `./pw` is significantly shorter than `bazelisk run --config=foo //:pw`. |
| # 2. .bazelrc configs cannot express multiple portions of this wrapper: |
| # a. Startup flags in a --config are ignored. |
| # b. The double-dash separator cannot be correctly expressed in a --config. |
| # 3. There's no way to ask Bazel to be verbose on the first clean build, and |
| # as quiet as possible on subsequent runs. |
| |
| # Print a message that indicates the pw tool might take a few seconds to load. |
| if [ -t 1 ]; then |
| printf " ⏱ Initializing pw tool...\r" |
| fi |
| # Don't generate compile commands from this action. Note that since we're |
| # using bazelisk, `BAZEL_WRAPPER` is NOT respected. |
| export BAZELISK_SKIP_WRAPPER=1 |
| |
| if test -n "$BASH"; then |
| declare -r _PW_SCRIPT_DIR=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")") |
| elif test -n "$ZSH_NAME"; then |
| declare -r _PW_SCRIPT_DIR="${0:h:A}" |
| fi |
| declare -r _PW_WORKFLOWS_OUT_DIR="${_PW_SCRIPT_DIR}/out/workflows_launcher" |
| declare -r _PW_WORKFLOWS_BIN_PATH="${_PW_WORKFLOWS_OUT_DIR}/bazel-bin/pw.exe" |
| |
| # Check if the existing pw tool binary is stale. We consider it stale if the |
| # wrapper script, the root BUILD.bazel, or any of the python sources it depends |
| # on are newer. |
| # A marker file is used as the timestamp of the last bazelisk invocation. |
| # The mtime of this file is compared to the `//:pw` sources to determine whether |
| # Bazel should be re-run. |
| declare -i _PW_STALE=1 |
| declare -r _PW_FRESH_MARKER="${_PW_WORKFLOWS_OUT_DIR}/.pw_fresh" |
| |
| # If no marker file or build artifacts exist, bazelisk has not previously been |
| # run. Otherwise, fall back to checking sources. |
| if [ -f "$_PW_WORKFLOWS_BIN_PATH" ] && [ -f "$_PW_FRESH_MARKER" ]; then |
| if [ ! "$_PW_SCRIPT_DIR/pw" -nt "$_PW_FRESH_MARKER" ] && \ |
| [ ! "$_PW_SCRIPT_DIR/BUILD.bazel" -nt "$_PW_FRESH_MARKER" ]; then |
| |
| # As a rough proxy for the script's sources and dependencies, consider all |
| # Python, Bazel, and proto files within pw_build, pw_cli, and |
| # pw_config_loader. |
| declare _PW_STALE_SOURCES |
| _PW_STALE_SOURCES=$(find "$_PW_SCRIPT_DIR/pw_build/py" \ |
| "$_PW_SCRIPT_DIR/pw_cli/py" \ |
| "$_PW_SCRIPT_DIR/pw_config_loader/py" \ |
| -type f \( -name '*.py' -o -name '*.bazel' -o -name '*.proto' \) \ |
| -newer "$_PW_FRESH_MARKER" -print -quit 2>/dev/null) |
| |
| if [ -z "$_PW_STALE_SOURCES" ]; then |
| _PW_STALE=0 |
| fi |
| fi |
| fi |
| |
| if [ $_PW_STALE -eq 0 ]; then |
| # Bypass bazel entirely for speed if the tool is already built and fresh. |
| # We must manually inject the directory environment variables that `bazel run` |
| # normally provides. |
| export BUILD_WORKSPACE_DIRECTORY="${_PW_SCRIPT_DIR}" |
| export BUILD_WORKING_DIRECTORY="${PWD}" |
| exec "$_PW_WORKFLOWS_BIN_PATH" "$@" |
| else |
| # If the `pw` tool hasn't been built yet, don't silence output since it might |
| # take a long time. |
| if [ -f "$_PW_WORKFLOWS_BIN_PATH" ]; then |
| declare -r _PW_WORKFLOWS_QUIET=--quiet |
| else |
| declare -r _PW_WORKFLOWS_QUIET |
| fi |
| |
| # Note: ${_PW_WORKFLOWS_QUIET} below needs to remain unquoted. This |
| # removes it as an argument to bazelisk. Otherwise an empty string |
| # agument is passed in as the bazel command. |
| |
| bazelisk \ |
| ${_PW_WORKFLOWS_QUIET} \ |
| --output_base="${_PW_WORKFLOWS_OUT_DIR}" \ |
| run \ |
| --symlink_prefix="${_PW_WORKFLOWS_OUT_DIR}/bazel-" \ |
| --show_result=0 \ |
| //:pw -- "$@" |
| |
| _PW_EXIT=$? |
| if [ $_PW_EXIT -eq 0 ]; then |
| mkdir -p "$_PW_WORKFLOWS_OUT_DIR" |
| touch "$_PW_FRESH_MARKER" |
| fi |
| exit $_PW_EXIT |
| fi |