| #!/bin/bash | |
| # Copyright 2013 The Flutter Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| ### Serves the out directory | |
| ## usage: | |
| ## --out <out_dir> Required. The out directory (ex: out/fuchsia_debug_x64). | |
| ## -p <port> Optional. The port for "pm serve" to listen on. Defaults to 8084. | |
| ## -d <device_name> Required for local workflows. The device_name to use for connecting. | |
| ## -r Optional. Serve to a remote target. | |
| ## --only-serve-runners Optional. Only serve the flutter and dart runners. | |
| #TODO: Take an out directory and use that to find the list of packages to publish | |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/vars.sh || exit $? | |
| # We need to use the fuchsia checkout still, make sure it is there | |
| ensure_fuchsia_dir | |
| out="" | |
| port="8084" | |
| component_framework_version=2 | |
| device_name="" | |
| remote=false | |
| only_serve_runners=false | |
| while (($#)); do | |
| case "$1" in | |
| --out) | |
| out="$2" | |
| shift | |
| ;; | |
| -c) | |
| component_framework_version="$2" | |
| # for `pm serve` `config.json` and if "2" (the default for this script) | |
| # use `pkgctl add` (which is not supported on older instances of fuchsia) | |
| # instead of `amberctl add_src`. | |
| shift | |
| ;; | |
| -p) | |
| port="$2" | |
| shift | |
| ;; | |
| -d) | |
| device_name="$2" | |
| shift | |
| ;; | |
| -r) | |
| remote=true | |
| ;; | |
| --only-serve-runners) | |
| only_serve_runners=true | |
| ;; | |
| *) | |
| echo 2>&1 "Unknown argument: \"${1}\" ignored" | |
| ;; | |
| esac | |
| shift | |
| done | |
| if [[ -z "${out}" ]]; then | |
| engine-error "Must specify an out directory, such as out/fuchsia_debug_x64" | |
| exit 1 | |
| fi | |
| if [[ ${component_framework_version} != [12] ]]; then | |
| engine-error "valid values for -c are 1 or 2" | |
| exit 1 | |
| fi | |
| fuchsia_build_dir="$(<"${FUCHSIA_DIR}/.fx-build-dir")" | |
| if [[ "${fuchsia_build_dir:0:1}" != "/" ]]; then | |
| fuchsia_build_dir="${FUCHSIA_DIR}/${fuchsia_build_dir}" | |
| fi | |
| # If remote, there is currently no equivalent check, but perhaps there could be? | |
| if [[ $remote != true ]]; then | |
| # Warn if the package server for the fuchsia packages is not running. Test | |
| # runners and any fuchsia package dependencies not included in the fuchsia | |
| # system image (via `--with-base` instead of `--with`) typically require | |
| # running `fx serve` (or equivalent commands), for the default `fuchsia.com` | |
| # (`devhost`) package URL domain. | |
| active_fuchsia_repo=$( | |
| ps -eo args \ | |
| | sed -nre \ | |
| "s#.*\bpm .*\bserve\b.* -repo ($FUCHSIA_DIR/out/.*)/amber-files.*#\1#p" | |
| ) | |
| if [[ "${active_fuchsia_repo}" == "" ]]; then | |
| engine-warning 'The default fuchsia package server may not be running.' | |
| echo 'If your test requires packages or test runners from fuchsia, those' | |
| echo 'packages will need to be bundled in the fuchsia system image (such as' | |
| echo 'via `fx set ... --with-base <package_target> ...). If your test' | |
| echo 'includes fuchsia package dependencies that need to be served, kill' | |
| echo 'this flutter "engine" package server first, run `fx serve` (in' | |
| echo 'another window or shell), and then re-run this `serve.sh` script.' | |
| echo '(The launch order is important.)' | |
| elif [[ "${active_fuchsia_repo}" != "${fuchsia_build_dir}" ]]; then | |
| engine-warning 'There default fuchsia package server may be' | |
| echo 'serving packages from the wrong build directory:' | |
| echo " ${active_fuchsia_repo}" | |
| echo 'which does not match your current build directory:' | |
| echo " ${fuchsia_build_dir}" | |
| echo 'It may be serving the wrong packages. If so, kill all package' | |
| echo 'servers, and restart them. Make sure you start the fuchsia package' | |
| echo 'server (for example, via `fx serve`) **before** starting this' | |
| echo '`serve.sh` script' | |
| fi | |
| fi | |
| # Start our package server | |
| # TODO: Need to ask for the out directory to find the package list | |
| # TODO: Generate the all_packages.list file | |
| cd "${FLUTTER_ENGINE_SRC_DIR}/${out}" || exit | |
| if ! [[ -d "${FLUTTER_ENGINE_SRC_DIR}/${out}/tuf" ]]; then | |
| # Create the repository to serve | |
| "${FLUTTER_ENGINE_FUCHSIA_SDK_DIR}/tools/pm" newrepo -vt \ | |
| -repo "${FLUTTER_ENGINE_SRC_DIR}/${out}/tuf" | |
| fi | |
| # Serve packages (run as a background process) | |
| "${FLUTTER_ENGINE_FUCHSIA_SDK_DIR}/tools/pm" serve -vt \ | |
| -repo "${FLUTTER_ENGINE_SRC_DIR}/${out}/tuf" \ | |
| -l ":${port}" \ | |
| -c "${component_framework_version}" \ | |
| -p "${FLUTTER_ENGINE_SRC_DIR}/flutter/tools/fuchsia/all_packages.list" \ | |
| & | |
| serve_pid=$! | |
| # Add debug symbols to the symbol index. | |
| "${FLUTTER_ENGINE_FUCHSIA_SDK_DIR}/tools/symbol-index" add \ | |
| "${FLUTTER_ENGINE_SRC_DIR}/${out}/.build-id" \ | |
| "${FLUTTER_ENGINE_SRC_DIR}/${out}" | |
| # Start our server and loop to check if our device is up give some slack time | |
| # to ensure that pm has started | |
| sleep 1 | |
| ffx="${FLUTTER_ENGINE_FUCHSIA_SDK_DIR}/tools/x64/ffx" | |
| serve_updates_target_addr="" | |
| resolve_local_target() { | |
| if [[ -z "${device_name}" ]]; then | |
| engine-error "Must specify a device name with -d if using a local workflow" | |
| exit 1 | |
| fi | |
| result=$("${ffx}" target list "${device_name}" --format a 2> /dev/null) | |
| if [[ $? == 0 ]]; then | |
| serve_updates_target_addr=$result | |
| fi | |
| } | |
| resolve_target() { | |
| if [[ $remote == true ]]; then | |
| serve_updates_target_addr="-p 8022 ::1" | |
| else | |
| resolve_local_target | |
| fi | |
| } | |
| clear_target_addr() { | |
| serve_updates_target_addr="" | |
| } | |
| kill_child_processes() { | |
| child_pids=$(jobs -p) | |
| if [[ -n "${child_pids}" ]]; then | |
| # Note: child_pids must be expanded to args here. | |
| kill ${child_pids} 2> /dev/null | |
| wait 2> /dev/null | |
| fi | |
| } | |
| trap kill_child_processes EXIT | |
| run_ssh_command() { | |
| # Enusre we have a target to ssh to | |
| if [[ -z $serve_updates_target_addr ]]; then | |
| return 1 | |
| fi | |
| ssh_config="${fuchsia_build_dir}/ssh-keys/ssh_config" | |
| if [[ ! -e $ssh_config ]]; then | |
| engine-error "No valid ssh_config at $ssh_config" | |
| fi | |
| if [[ $remote == true ]]; then | |
| ssh -F "${ssh_config}" -p 8022 ::1 "$@" | |
| else | |
| ssh -F "${ssh_config}" "$serve_updates_target_addr" "$@" | |
| fi | |
| } | |
| if [[ $remote != true && -z "${device_name}" ]]; then | |
| device_name="$(cat ${fuchsia_build_dir}.device)" | |
| fi | |
| echo -n "Connecting to " | |
| if $remote; then | |
| echo -n "remote device via ssh tunnel on port 8022..." | |
| else | |
| echo -n "device '${device_name}', port ${port}..." | |
| fi | |
| # State is used to prevent too much output | |
| state="discover" | |
| while true; do | |
| if ! kill -0 "${serve_pid}" 2> /dev/null; then | |
| echo "Server died, exiting" | |
| serve_pid= | |
| exit 1 | |
| fi | |
| if [[ "$state" == "discover" ]]; then | |
| # While we're still trying to connect to the device, clear the target | |
| # address state so we re-resolve. | |
| clear_target_addr | |
| resolve_target | |
| run_ssh_command exit 2>/dev/null | |
| ping_result=$? | |
| else | |
| run_ssh_command -O check > /dev/null 2>&1 | |
| ping_result=$? | |
| fi | |
| if [[ "$state" == "discover" && "$ping_result" == 0 ]]; then | |
| echo | |
| echo "Device up" | |
| state="config" | |
| fi | |
| if [[ "$state" == "config" ]]; then | |
| echo "Registering engine as update source" | |
| # Get our ssh host address | |
| addr=$(run_ssh_command 'echo $SSH_CONNECTION' | cut -d ' ' -f 1) | |
| if [[ $? -ne 0 || -z "${addr}" ]]; then | |
| engine-error "unable to determine host address as seen from the target. Is the target up?" | |
| exit 1 | |
| fi | |
| addr="$(echo "${addr}" | sed 's/%/%25/g')" | |
| if [[ "${addr}" =~ : ]]; then | |
| addr="[${addr}]" | |
| fi | |
| config_url="http://${addr}:${port}/config.json" | |
| if [[ ${component_framework_version} == 2 ]]; then | |
| run_ssh_command pkgctl repo add url \ | |
| -n "engine" \ | |
| "${config_url}" | |
| else | |
| run_ssh_command amberctl add_src \ | |
| -n "engine" \ | |
| -f "${config_url}" | |
| fi | |
| err=$? | |
| if [[ $err -ne 0 ]]; then | |
| engine-error "Failed to add update source" | |
| exit 1 | |
| fi | |
| if [[ $only_serve_runners == true ]]; then | |
| run_ssh_command "pkgctl rule replace json '$(cat <<EOF | |
| { | |
| "version": "1", | |
| "content": [ | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/flutter_jit_runner/", "path_prefix_replacement": "/flutter_jit_runner/" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/flutter_jit_runner", "path_prefix_replacement": "/flutter_jit_runner" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/flutter_aot_runner/", "path_prefix_replacement": "/flutter_aot_runner/" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/flutter_aot_runner", "path_prefix_replacement": "/flutter_aot_runner" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/dart_jit_runner/", "path_prefix_replacement": "/dart_jit_runner/" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/dart_jit_runner", "path_prefix_replacement": "/dart_jit_runner" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/dart_aot_runner/", "path_prefix_replacement": "/dart_aot_runner/" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "engine", | |
| "path_prefix_match": "/dart_aot_runner", "path_prefix_replacement": "/dart_aot_runner" | |
| }, | |
| { | |
| "host_match": "fuchsia.com", "host_replacement": "devhost", | |
| "path_prefix_match": "/", "path_prefix_replacement": "/" | |
| } | |
| ] | |
| } | |
| EOF | |
| )'" | |
| err=$? | |
| if [[ $err -ne 0 ]]; then | |
| engine-error "Failed to add runner rewrite rules" | |
| exit 1 | |
| fi | |
| fi | |
| state="ready" | |
| fi | |
| if [[ "$state" == "ready" ]]; then | |
| if [[ "$ping_result" != 0 ]]; then | |
| echo "Device lost" | |
| state="discover" | |
| else | |
| sleep 1 | |
| fi | |
| else | |
| sleep 1 | |
| echo -n "." | |
| fi | |
| done |