blob: dc3ba2110d7dca76ce33fd32c055a2e545dab1b8 [file] [edit]
#!/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