| #!/bin/bash |
| # Copyright 2022 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=Build |
| ### Attempt to build a few known SDK-based OOT repos based on a core SDK |
| ### produced from the local Fuchsia tree |
| ## |
| ## This command attempts to build some known SDK-based OOT repos with an SDK |
| ## produced with the local Fuchsia tree and build configuration. |
| ## |
| ## Usage: fx validate-sdk [--local-bazel-rules] [--keep-tmp] [[REPO/CLNUM/PATCHSET] ...] |
| ## |
| ## It first runs the equivalent of 'fx build sdk:core sdk:driver' |
| ## |
| ## Then for each SDK-based repo from the list: |
| ## sdk-samples/getting-started |
| ## sdk-samples/drivers |
| ## sdk-samples/fortune-teller |
| ## it will clone the corresponding repo and attempt to build it with |
| ## the local SDK produced by 'fx build sdk:core sdk:driver' |
| ## |
| ## Given that some of these repos, like getting-started and drivers, only |
| ## update their SDK every few weeks, there will likely be a WIP roller CL |
| ## that you may want to patch before attempting to build. |
| ## If you want to patch a CL from these repos before validating the SDK, |
| ## you can use the [REPO/CL/PATCHSET] syntax: |
| ## |
| ## |
| ## --local-bazel-rules Use the version of the sdk-integration repo in |
| ## the local Fuchsia tree (//third_party/sdk-integration) |
| ## instead of the version checked-in on the samples. |
| ## With this option, the in-tree sdk-integration will replace both |
| ## the checked-in and patched-in sdk-integration. |
| ## |
| ## --keep-tmp Do not delete the temporary directories used to fetch and |
| ## build the samples when they fail to build. This is useful |
| ## to debug and iterate on fixes without having to download the samples again. |
| ## If the build succeeds, the temp dirs will be deleted |
| ## regardless of this flag. |
| ## |
| ## Examples: |
| ## fx validate-sdk |
| ## fx validate-sdk --local-bazel-rules |
| ## fx validate-sdk drivers/715716/9 getting-started/691515/11 |
| ## fx validate-sdk --keep-tmp |
| |
| source "${FUCHSIA_DIR}/tools/devshell/lib/style.sh" || exit $? |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../lib/vars.sh || exit $? |
| |
| set -e -o pipefail |
| |
| fx-config-read |
| |
| # keep both in sync, as associatie arrays are not well supported in the |
| # version of Bash that ships with MacOS |
| declare -a REPO_NAMES=( "drivers" "getting-started" "fortune-teller" ) |
| declare -a REPOS=( |
| "https://fuchsia.googlesource.com/sdk-samples/drivers" |
| "https://fuchsia.googlesource.com/sdk-samples/getting-started" |
| "https://fuchsia.googlesource.com/sdk-samples/fortune-teller" |
| ) |
| |
| readonly REPOS REPO_NAMES |
| |
| function create_sdk { |
| fx-command-run build sdk:core sdk:driver |
| } |
| |
| |
| function is_valid_repo_name { |
| for r in "${REPO_NAMES[@]}"; do |
| if [[ "$r" == "$k" ]]; then |
| return 0 |
| fi |
| done |
| return 1 |
| } |
| |
| function validate_patches { |
| while [[ $# -gt 0 ]]; do |
| if [[ "$1" =~ ^([a-z-]+)\/([0-9]+)\/([0-9]+)$ ]]; then |
| k="${BASH_REMATCH[1]}" |
| cl="${BASH_REMATCH[2]}" |
| ps="${BASH_REMATCH[3]}" |
| if ! is_valid_repo_name "$k"; then |
| fx-error "Invalid repo name '$k' in patch spec. Must be one of ${REPO_NAMES[@]}" |
| exit 1 |
| fi |
| else |
| fx-error "Invalid patch spec, must be REPO_NAME/CL_NUM/PATCHSET: $1" |
| exit 1 |
| fi |
| shift |
| done |
| } |
| |
| function get_patches { |
| local repo_key="$1" |
| shift |
| local patches=() |
| while [[ $# -gt 0 ]]; do |
| if [[ "$1" =~ ^${repo_key}\/([0-9]+)\/([0-9]+)$ ]]; then |
| cl="${BASH_REMATCH[1]}" |
| ps="${BASH_REMATCH[2]}" |
| patches+=( "${cl}" "${ps}" ) |
| fi |
| shift |
| done |
| echo "${patches[@]}" |
| } |
| |
| function clone { |
| local git_url="$1" |
| local tmp_dir="$2" |
| |
| git clone "$git_url" "$tmp_dir" |
| git -C "$tmp_dir" submodule update --recursive --init |
| } |
| |
| function replace_sdk_integration { |
| local tmp_dir="$1" |
| local sample_bazel_rules="${tmp_dir}/third_party/sdk-integration" |
| local local_bazel_rules="${FUCHSIA_DIR}/third_party/sdk-integration" |
| if [[ ! -d "$sample_bazel_rules" ]]; then |
| fx-error "Unexpected error: cannot find Bazel rules in $sample_bazel_rules" |
| exit 1 |
| fi |
| if [[ ! -d "$local_bazel_rules" ]]; then |
| fx-error "Unexpected error: cannot find local Bazel rules in $local_bazel_rules" |
| exit 1 |
| fi |
| rm -Rf "${sample_bazel_rules}" |
| mkdir -p "${sample_bazel_rules}" |
| # copy contents instead of the entire directory to avoid copying the .git |
| # directory, as it is large and useless in this context |
| cp -R "${local_bazel_rules}"/* "${sample_bazel_rules}" |
| } |
| |
| function patch { |
| local git_url="$1" |
| local tmp_dir="$2" |
| local cl_num="$3" |
| local cl_patchset="$4" |
| |
| local cl_tail="${cl_num:(-2)}" |
| git -C "$tmp_dir" fetch "$git_url" \ |
| "refs/changes/${cl_tail}/${cl_num}/${cl_patchset}" |
| git -C "$tmp_dir" checkout FETCH_HEAD --recurse-submodules |
| } |
| |
| function build_sample { |
| local repo_key="$1" |
| local tmp_dir="$2" |
| |
| local build_dir="$FUCHSIA_BUILD_DIR" |
| |
| cd "$tmp_dir" |
| scripts/bootstrap.sh |
| LOCAL_FUCHSIA_PLATFORM_BUILD="$FUCHSIA_BUILD_DIR" tools/bazel build --config=fuchsia_${FUCHSIA_ARCH} src:samples_repository |
| } |
| |
| function show_instructions { |
| local repo_key="$1" |
| local tmp_dir="$2" |
| if [[ -d "${tmp_dir}" ]]; then |
| echo >&2 |
| fx-warn "Keeping temp directory for $repo_key. Use the instructions below to build it:" |
| echo >&2 "fx build sdk:core sdk:driver" |
| echo >&2 "cd $tmp_dir" |
| echo >&2 "LOCAL_FUCHSIA_PLATFORM_BUILD=\"$FUCHSIA_BUILD_DIR\" tools/bazel build --config=fuchsia_${FUCHSIA_ARCH} src:samples_repository" |
| fi |
| } |
| |
| function cleanup { |
| local tmp_dir="$1" |
| if [[ -d "${tmp_dir}" ]]; then |
| rm -Rf "${tmp_dir}" |
| fi |
| } |
| |
| function main { |
| use_sdk_intree=0 |
| keep=0 |
| patches=() |
| while [[ $# -gt 0 ]]; do |
| if [[ "$1" =~ ^-- ]]; then |
| if [[ "$1" == "--local-bazel-rules" ]]; then |
| use_sdk_intree=1 |
| elif [[ "$1" == "--keep-tmp" ]]; then |
| keep=1 |
| else |
| fx-error "Invalid syntax" |
| fx-command-help |
| exit 1 |
| fi |
| else |
| patches+=( "$1" ) |
| fi |
| shift |
| done |
| |
| validate_patches "${patches[@]}" |
| |
| fx-info "*** Creating the SDK..." |
| create_sdk |
| |
| local i=0 |
| for repo_key in "${REPO_NAMES[@]}"; do |
| local repo_url="${REPOS[$i]}" |
| i=$((i+1)) |
| local message="*** Building $repo_key with local SDK, target arch $FUCHSIA_ARCH " |
| if [[ $use_sdk_intree -eq 1 ]]; then |
| message+="and in-tree sdk-integration " |
| fi |
| fx-info "$message..." |
| |
| local tmp_dir="$(mktemp -d)" |
| if [[ $keep -eq 0 ]]; then |
| trap "cleanup ${tmp_dir}" EXIT |
| else |
| trap "show_instructions \"$repo_key\" \"$tmp_dir\"" EXIT |
| fi |
| |
| clone "$repo_url" "$tmp_dir" |
| |
| local repo_patches=( $(get_patches "$repo_key" "${patches[@]}" ) ) |
| for (( pi=0; pi<${#repo_patches[@]}; pi+=2 )); do |
| patch "$repo_url" "$tmp_dir" "${repo_patches[$pi]}" "${repo_patches[$pi+1]}" |
| done |
| |
| if [[ $use_sdk_intree -eq 1 ]]; then |
| replace_sdk_integration "$tmp_dir" |
| fi |
| |
| build_sample "$repo_key" "$tmp_dir" |
| |
| trap - EXIT |
| cleanup ${tmp_dir} |
| done |
| } |
| |
| main "$@" |