blob: fb917101b16a497f4ecc3ebf5b9c243d34e810bf [file] [log] [blame]
#!/bin/bash
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#### CATEGORY=Run, Inspect and Debug
### run a host tool produced by the build
## usage: fx host-tool [--no-build] TOOLNAME [TOOL_ARGS...]
##
## This looks for a tool named TOOLNAME in tool_paths.json and executes it
## with the provided TOOL_ARGS.
## --no-build does not attempt to build the tool if it does not exist
## --check-firewall print a warning if the tool isn't included in firewall
## rules. This is a no-op outside of macOS.
## --print print the tool path instead of executing it. TOOL_ARGS
## is ignored, but check-firewall and build behaves the
## same.
##
## If the tool is not known to the build system, for example if it is not in
## the GN build graph, a proper message will be printed and the script fails.
## This script is specially useful for other scripts, via fx-command-run,
## although it can also be used directly by final users.
##
## The tool will be built if host-tool is being run interactively,
## otherwise an error will be produced if the tool is missing.
set -e
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/vars.sh || exit $?
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/host_symbolizer.sh || exit $?
fx-config-read
build=true
print_only=false
check_firewall=false
function is_macos {
[[ "$(uname -s)" == "Darwin" ]]
}
function firewall_cmd_macos {
local fw
if type -P "socketfilterfw"; then
fw="socketfilterfw"
else
fw="/usr/libexec/ApplicationFirewall/socketfilterfw"
fi
"$fw" "$@"
}
function check_firewall_func {
if is_macos; then
if firewall_cmd_macos --getglobalstate | grep "disabled" > /dev/null; then
return 0
fi
if ! firewall_cmd_macos --getappblocked "$1" | grep "permitted" > /dev/null; then
fx-warn "Firewall rules are not configured, you may need to run \"fx setup-macos\""
return 0
fi
fi
}
while [[ $1 == --* ]]; do
if [[ $1 == '--no-build' ]]; then
build=false
shift
elif [[ $1 == '--print' ]]; then
print_only=true
shift
elif [[ $1 == '--check-firewall' ]]; then
check_firewall=true
shift
else
fx-error "Unrecognized option: $1"
fx-command-help
exit 1
fi
done
if [[ $# -eq 0 || $1 == -* ]]; then
fx-error "Invalid syntax"
fx-command-help
exit 1
fi
toolname="$1"
shift
# list-build-artifacts fails with a reasonable error message if tool is unknown
toolpath="$(fx-command-run list-build-artifacts --name "${toolname}" --expect-one tools)"
if [[ ! -f "${FUCHSIA_BUILD_DIR}/${toolpath}" ]]; then
# If the desire is to build, then it's important for the build to
# have stdout and stderr to print to. There are two possible
# conditions, one is that host-tool is being run with stdout going to
# a terminal, the other is that stdout is being captured, for example
# if the user is running `fx set-device`. In the latter case it is
# desirable to attach the build to the controlling terminal, if there
# is one. In the case where there is not, fall back to printing an
# error, as if --no-build was passed. If stderr is also redirected,
# then the build is cundontiionally skipped.
if ! fx-is-stderr-tty; then
build=false
fi
if ! $build; then
fx-error "Tool \"${toolname}\" is required by this command and has not been built."
fx-error "Please build it first: fx build ${toolpath}"
exit 2
fi
{
echo "Building required tool \"${toolpath}\"..."
fx-command-run build "${toolpath}" || exit $?
} 1>&2
fi
# Print a warning if the firewall doesn't allow this tool from running.
if $check_firewall; then
check_firewall_func "${FUCHSIA_BUILD_DIR}/${toolpath}"
fi
if $print_only; then
echo "${FUCHSIA_BUILD_DIR}/${toolpath}"
else
exec "${FUCHSIA_BUILD_DIR}/${toolpath}" "$@"
fi