2026-07-24 12:35:04 +08:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
|
cat <<'EOF'
|
|
|
|
|
Usage: script/build_msquic.sh [options]
|
|
|
|
|
|
|
|
|
|
Build the pinned MsQuic source into:
|
|
|
|
|
dependency/<arch>/third_party/msquic/v<version>
|
|
|
|
|
|
|
|
|
|
Options:
|
|
|
|
|
--arch x86|arm Dependency architecture (default: native host)
|
|
|
|
|
--version VERSION Supported pinned version without leading v (default: 2.5.9)
|
|
|
|
|
--jobs N Parallel build jobs (default: nproc)
|
|
|
|
|
--clean Recreate the MsQuic build and staging directories
|
|
|
|
|
-h, --help Show this help
|
|
|
|
|
|
|
|
|
|
Environment:
|
|
|
|
|
CMVR_CMAKE Absolute CMake executable override
|
|
|
|
|
CMVR_MSQUIC_TOOLCHAIN_FILE CMake toolchain file for cross-compilation
|
|
|
|
|
CC, CXX Native compiler overrides
|
|
|
|
|
|
|
|
|
|
The first run needs network access to clone the official MsQuic tag and its
|
|
|
|
|
QuicTLS submodule. No sudo or system MsQuic installation is used.
|
|
|
|
|
EOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
|
|
|
repo_root="$(cd -- "${script_dir}/.." && pwd -P)"
|
|
|
|
|
version="2.5.9"
|
|
|
|
|
arch=""
|
|
|
|
|
jobs=""
|
|
|
|
|
clean_build=false
|
|
|
|
|
|
|
|
|
|
while (($# > 0)); do
|
|
|
|
|
case "$1" in
|
|
|
|
|
--arch)
|
|
|
|
|
[[ $# -ge 2 ]] || { echo "missing value for --arch" >&2; exit 2; }
|
|
|
|
|
arch="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--version)
|
|
|
|
|
[[ $# -ge 2 ]] || { echo "missing value for --version" >&2; exit 2; }
|
|
|
|
|
version="${2#v}"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--jobs)
|
|
|
|
|
[[ $# -ge 2 ]] || { echo "missing value for --jobs" >&2; exit 2; }
|
|
|
|
|
jobs="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--clean)
|
|
|
|
|
clean_build=true
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
-h|--help)
|
|
|
|
|
usage
|
|
|
|
|
exit 0
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "unknown option: $1" >&2
|
|
|
|
|
usage >&2
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
host_machine="$(uname -m)"
|
|
|
|
|
case "${host_machine}" in
|
|
|
|
|
x86_64|amd64)
|
|
|
|
|
native_arch="x86"
|
|
|
|
|
;;
|
|
|
|
|
aarch64|arm64|armv8*)
|
|
|
|
|
native_arch="arm"
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "unsupported host architecture: ${host_machine}" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
arch="${arch:-${native_arch}}"
|
|
|
|
|
if [[ "${arch}" != "x86" && "${arch}" != "arm" ]]; then
|
|
|
|
|
echo "--arch must be x86 or arm" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
|
|
|
echo "--version must use the form MAJOR.MINOR.PATCH" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
case "${version}" in
|
|
|
|
|
2.5.9)
|
|
|
|
|
expected_source_commit="87b53085d76bd7920d490a6f226c9999b6614d14"
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "unsupported MsQuic version: ${version}" >&2
|
|
|
|
|
echo "add its reviewed tag and commit to script/build_msquic.sh first" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
if [[ -z "${jobs}" ]]; then
|
|
|
|
|
jobs="$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN || echo 2)"
|
|
|
|
|
fi
|
|
|
|
|
if [[ ! "${jobs}" =~ ^[1-9][0-9]*$ ]]; then
|
|
|
|
|
echo "--jobs must be a positive integer" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
toolchain_args=()
|
|
|
|
|
if [[ "${arch}" != "${native_arch}" ]]; then
|
|
|
|
|
if [[ -z "${CMVR_MSQUIC_TOOLCHAIN_FILE:-}" ]]; then
|
|
|
|
|
echo "cross-building ${arch} on ${host_machine} requires" >&2
|
|
|
|
|
echo "CMVR_MSQUIC_TOOLCHAIN_FILE=/absolute/path/to/toolchain.cmake" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
if [[ ! -f "${CMVR_MSQUIC_TOOLCHAIN_FILE}" ]]; then
|
|
|
|
|
echo "toolchain file does not exist: ${CMVR_MSQUIC_TOOLCHAIN_FILE}" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
toolchain_file="$(realpath "${CMVR_MSQUIC_TOOLCHAIN_FILE}")"
|
|
|
|
|
toolchain_args+=("-DCMAKE_TOOLCHAIN_FILE=${toolchain_file}")
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
tag="v${version}"
|
|
|
|
|
source_dir="${repo_root}/build/third_party/msquic-src/${tag}"
|
|
|
|
|
build_dir="${repo_root}/build/third_party/msquic-build/${arch}-${tag}"
|
|
|
|
|
stage_dir="${repo_root}/build/third_party/msquic-stage/${arch}-${tag}"
|
|
|
|
|
stage_prefix="${stage_dir}/prefix"
|
|
|
|
|
install_root="${repo_root}/dependency/${arch}/third_party/msquic/${tag}"
|
|
|
|
|
backup_root="${install_root}.previous"
|
|
|
|
|
|
|
|
|
|
for guarded_path in \
|
|
|
|
|
"${source_dir}" "${build_dir}" "${stage_dir}" \
|
|
|
|
|
"${install_root}" "${backup_root}"; do
|
|
|
|
|
case "${guarded_path}" in
|
|
|
|
|
"${repo_root}"/build/third_party/*|\
|
|
|
|
|
"${repo_root}"/dependency/"${arch}"/third_party/msquic/"${tag}"|\
|
|
|
|
|
"${repo_root}"/dependency/"${arch}"/third_party/msquic/"${tag}".previous)
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "refusing unsafe path: ${guarded_path}" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
if [[ -n "${CMVR_CMAKE:-}" ]]; then
|
|
|
|
|
cmake_bin="$(realpath "${CMVR_CMAKE}")"
|
|
|
|
|
else
|
|
|
|
|
bundled_cmake="${repo_root}/dependency/${arch}/third_party/cmake/v3.30.3/cmake-3.30.3-linux-$(
|
|
|
|
|
[[ "${arch}" == "x86" ]] && echo x86_64 || echo aarch64
|
|
|
|
|
)/bin/cmake"
|
|
|
|
|
if [[ "${arch}" == "${native_arch}" && -x "${bundled_cmake}" ]]; then
|
|
|
|
|
cmake_bin="${bundled_cmake}"
|
|
|
|
|
else
|
|
|
|
|
cmake_bin="$(command -v cmake)"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
[[ -x "${cmake_bin}" ]] || {
|
|
|
|
|
echo "CMake executable is unavailable: ${cmake_bin}" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
git_bin="/usr/bin/git"
|
|
|
|
|
[[ -x "${git_bin}" ]] || git_bin="$(command -v git)"
|
|
|
|
|
[[ -x "${git_bin}" ]] || { echo "git is required" >&2; exit 2; }
|
|
|
|
|
|
|
|
|
|
clean_path="$(dirname "${cmake_bin}"):/usr/local/bin:/usr/bin:/bin"
|
|
|
|
|
export PATH="${clean_path}"
|
|
|
|
|
unset CONDA_PREFIX CONDA_DEFAULT_ENV CMAKE_PREFIX_PATH PKG_CONFIG_PATH \
|
|
|
|
|
OPENSSL_ROOT_DIR OPENSSL_DIR LD_LIBRARY_PATH LIBRARY_PATH CPATH \
|
|
|
|
|
C_INCLUDE_PATH CPLUS_INCLUDE_PATH CFLAGS CXXFLAGS CPPFLAGS LDFLAGS \
|
|
|
|
|
PERL5LIB PERL5OPT
|
|
|
|
|
|
|
|
|
|
if [[ "${arch}" == "${native_arch}" ]]; then
|
|
|
|
|
export CC="${CC:-/usr/bin/cc}"
|
|
|
|
|
export CXX="${CXX:-/usr/bin/c++}"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
mkdir -p "$(dirname "${source_dir}")" "$(dirname "${install_root}")"
|
|
|
|
|
if [[ ! -d "${source_dir}/.git" ]]; then
|
|
|
|
|
"${git_bin}" clone \
|
|
|
|
|
--branch "${tag}" \
|
|
|
|
|
--depth 1 \
|
|
|
|
|
https://github.com/microsoft/msquic.git \
|
|
|
|
|
"${source_dir}"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
source_commit="$("${git_bin}" -C "${source_dir}" rev-parse HEAD)"
|
|
|
|
|
tag_commit="$("${git_bin}" -C "${source_dir}" rev-list -n 1 "${tag}")"
|
|
|
|
|
if [[ "${source_commit}" != "${tag_commit}" ]]; then
|
|
|
|
|
echo "${source_dir} is not checked out at ${tag}" >&2
|
|
|
|
|
echo "remove that cache directory and rerun the script" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
if [[ "${source_commit}" != "${expected_source_commit}" ]]; then
|
|
|
|
|
echo "${tag} resolved to an unexpected source commit" >&2
|
|
|
|
|
echo "expected: ${expected_source_commit}" >&2
|
|
|
|
|
echo "actual: ${source_commit}" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
unexpected_initialized_submodules="$(
|
|
|
|
|
"${git_bin}" -C "${source_dir}" submodule status |
|
|
|
|
|
awk '$2 != "submodules/quictls" && substr($1, 1, 1) != "-" {
|
|
|
|
|
print $2 " (" $1 ")"
|
|
|
|
|
}'
|
|
|
|
|
)"
|
|
|
|
|
if [[ -n "${unexpected_initialized_submodules}" ]]; then
|
|
|
|
|
echo "MsQuic source cache contains initialized non-QuicTLS submodules:" >&2
|
|
|
|
|
echo "${unexpected_initialized_submodules}" >&2
|
|
|
|
|
echo "deinitialize those submodules or use a clean source cache before building" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
"${git_bin}" -C "${source_dir}" submodule sync -- submodules/quictls
|
|
|
|
|
"${git_bin}" -C "${source_dir}" submodule update \
|
|
|
|
|
--init --depth 1 -- submodules/quictls
|
|
|
|
|
|
|
|
|
|
source_changes="$("${git_bin}" -C "${source_dir}" status \
|
|
|
|
|
--porcelain --untracked-files=all --ignore-submodules=all)"
|
|
|
|
|
if [[ -n "${source_changes}" ]]; then
|
|
|
|
|
echo "MsQuic source cache contains local changes:" >&2
|
|
|
|
|
echo "${source_changes}" >&2
|
|
|
|
|
echo "use a clean source cache before building" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
quictls_dir="${source_dir}/submodules/quictls"
|
|
|
|
|
expected_quictls_commit="$("${git_bin}" -C "${source_dir}" \
|
|
|
|
|
rev-parse HEAD:submodules/quictls)"
|
|
|
|
|
actual_quictls_commit="$("${git_bin}" -C "${quictls_dir}" rev-parse HEAD)"
|
|
|
|
|
quictls_changes="$("${git_bin}" -C "${quictls_dir}" status \
|
|
|
|
|
--porcelain --untracked-files=all)"
|
|
|
|
|
if [[ "${actual_quictls_commit}" != "${expected_quictls_commit}" ||
|
|
|
|
|
-n "${quictls_changes}" ]]; then
|
|
|
|
|
echo "QuicTLS source cache is not at the clean pinned commit" >&2
|
|
|
|
|
echo "expected: ${expected_quictls_commit}" >&2
|
|
|
|
|
echo "actual: ${actual_quictls_commit}" >&2
|
|
|
|
|
[[ -z "${quictls_changes}" ]] || echo "${quictls_changes}" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ "${clean_build}" == true ]]; then
|
|
|
|
|
"${cmake_bin}" -E remove_directory "${build_dir}"
|
|
|
|
|
fi
|
|
|
|
|
"${cmake_bin}" -E remove_directory "${stage_dir}"
|
|
|
|
|
"${cmake_bin}" -E make_directory "${build_dir}" "${stage_prefix}"
|
|
|
|
|
|
|
|
|
|
toolchain_fingerprint="native"
|
|
|
|
|
if [[ ${#toolchain_args[@]} -ne 0 ]]; then
|
|
|
|
|
toolchain_fingerprint="$(
|
|
|
|
|
sha256sum "${toolchain_file}" | awk '{print $1}'
|
|
|
|
|
)"
|
|
|
|
|
fi
|
|
|
|
|
build_recipe_version="5"
|
|
|
|
|
build_fingerprint="$(
|
|
|
|
|
printf '%s' \
|
|
|
|
|
"${source_commit}|${build_recipe_version}|${arch}|" \
|
|
|
|
|
"${CC:-toolchain}|${CXX:-toolchain}|" \
|
|
|
|
|
"${toolchain_fingerprint}|${cmake_bin}"
|
|
|
|
|
)"
|
|
|
|
|
fingerprint_file="${build_dir}/cmvr-msquic-build.fingerprint"
|
|
|
|
|
if [[ -f "${build_dir}/CMakeCache.txt" ]]; then
|
|
|
|
|
if [[ ! -f "${fingerprint_file}" ]]; then
|
|
|
|
|
echo "existing MsQuic build cache predates compiler fingerprinting" >&2
|
|
|
|
|
echo "rerun with --clean" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
existing_fingerprint="$(<"${fingerprint_file}")"
|
|
|
|
|
if [[ "${existing_fingerprint}" != "${build_fingerprint}" ]]; then
|
|
|
|
|
echo "MsQuic compiler/toolchain fingerprint changed" >&2
|
|
|
|
|
echo "rerun with --clean" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
printf '%s\n' "${build_fingerprint}" >"${fingerprint_file}"
|
|
|
|
|
|
|
|
|
|
prefix_map_flags="\
|
|
|
|
|
-ffile-prefix-map=${repo_root}=. -fmacro-prefix-map=${repo_root}=."
|
|
|
|
|
"${cmake_bin}" \
|
|
|
|
|
-S "${source_dir}" \
|
|
|
|
|
-B "${build_dir}" \
|
|
|
|
|
-G "Unix Makefiles" \
|
|
|
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
|
|
|
"-DCMAKE_INSTALL_PREFIX=${stage_prefix}" \
|
|
|
|
|
"-DCMAKE_MODULE_PATH=${repo_root}/cmake/msquic" \
|
|
|
|
|
"-DCMVR_MSQUIC_PROCESSOR_COUNT=${jobs}" \
|
|
|
|
|
"-DCMAKE_C_FLAGS=${prefix_map_flags}" \
|
|
|
|
|
"-DCMAKE_CXX_FLAGS=${prefix_map_flags}" \
|
|
|
|
|
-DQUIC_BUILD_SHARED=ON \
|
|
|
|
|
-DQUIC_BUILD_TEST=OFF \
|
|
|
|
|
-DQUIC_BUILD_TOOLS=OFF \
|
|
|
|
|
-DQUIC_BUILD_PERF=OFF \
|
|
|
|
|
-DQUIC_ENABLE_LOGGING=OFF \
|
|
|
|
|
-DQUIC_TLS_LIB=quictls \
|
|
|
|
|
-DQUIC_USE_SYSTEM_LIBCRYPTO=OFF \
|
|
|
|
|
-DNUMA:STRING=FALSE \
|
|
|
|
|
"${toolchain_args[@]}"
|
|
|
|
|
|
|
|
|
|
# QuicTLS derives MODULESDIR from its temporary --prefix and compiles that
|
|
|
|
|
# absolute path into libcrypto. Dynamic providers are disabled above
|
|
|
|
|
# (no-shared, no-legacy and no-fips), so keep the unused fallback path stable
|
|
|
|
|
# instead of leaking the build workspace into the shipped MsQuic runtime.
|
|
|
|
|
openssl_makefile_target="_deps/opensslquic-build/submodules/quictls/Makefile"
|
|
|
|
|
openssl_build_rules="_deps/opensslquic-build/CMakeFiles/OpenSSL_Target.dir/build.make"
|
|
|
|
|
make_bin="$(command -v make)"
|
|
|
|
|
[[ -x "${make_bin}" ]] || {
|
|
|
|
|
echo "GNU Make is required to configure the bundled QuicTLS source" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
}
|
|
|
|
|
"${make_bin}" -C "${build_dir}" -f "${openssl_build_rules}" \
|
|
|
|
|
"${openssl_makefile_target}"
|
|
|
|
|
openssl_makefile="${build_dir}/${openssl_makefile_target}"
|
|
|
|
|
test -f "${openssl_makefile}"
|
|
|
|
|
if ! grep -Fx 'MODULESDIR=/usr/lib/ssl/ossl-modules' \
|
|
|
|
|
"${openssl_makefile}" >/dev/null; then
|
|
|
|
|
sed -i -E \
|
|
|
|
|
's|^MODULESDIR=.*$|MODULESDIR=/usr/lib/ssl/ossl-modules|' \
|
|
|
|
|
"${openssl_makefile}"
|
|
|
|
|
fi
|
|
|
|
|
grep -Fx 'MODULESDIR=/usr/lib/ssl/ossl-modules' \
|
|
|
|
|
"${openssl_makefile}" >/dev/null
|
|
|
|
|
|
|
|
|
|
"${cmake_bin}" --build "${build_dir}" --parallel "${jobs}"
|
|
|
|
|
"${cmake_bin}" --install "${build_dir}"
|
|
|
|
|
|
|
|
|
|
# Keep only the public Linux API and shared runtime that cmvr-es consumes.
|
|
|
|
|
find "${stage_prefix}/include" -maxdepth 1 -type f \
|
|
|
|
|
! -name msquic.h \
|
|
|
|
|
! -name msquic_posix.h \
|
|
|
|
|
! -name quic_sal_stub.h \
|
|
|
|
|
-delete
|
|
|
|
|
"${cmake_bin}" -E rm -f "${stage_prefix}/lib/libmsquic_platform.a"
|
|
|
|
|
"${cmake_bin}" -E remove_directory "${stage_prefix}/share"
|
|
|
|
|
"${cmake_bin}" -E make_directory "${stage_prefix}/share/licenses/msquic"
|
|
|
|
|
"${cmake_bin}" -E copy "${source_dir}/LICENSE" \
|
|
|
|
|
"${stage_prefix}/share/licenses/msquic/LICENSE"
|
|
|
|
|
"${cmake_bin}" -E copy "${source_dir}/THIRD-PARTY-NOTICES" \
|
|
|
|
|
"${stage_prefix}/share/licenses/msquic/THIRD-PARTY-NOTICES"
|
|
|
|
|
|
|
|
|
|
cat >"${stage_prefix}/BUILD-INFO.txt" <<EOF
|
|
|
|
|
msquic_version=${version}
|
|
|
|
|
source_tag=${tag}
|
|
|
|
|
source_commit=${source_commit}
|
|
|
|
|
dependency_arch=${arch}
|
|
|
|
|
tls_backend=quictls-static
|
|
|
|
|
dynamic_tls_providers=false
|
|
|
|
|
system_libcrypto=false
|
|
|
|
|
numa=false
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
test -f "${stage_prefix}/include/msquic.h"
|
|
|
|
|
test -f "${stage_prefix}/include/msquic_posix.h"
|
|
|
|
|
test -f "${stage_prefix}/include/quic_sal_stub.h"
|
|
|
|
|
test -f "${stage_prefix}/lib/libmsquic.so.${version}"
|
|
|
|
|
test -L "${stage_prefix}/lib/libmsquic.so"
|
|
|
|
|
|
|
|
|
|
if command -v readelf >/dev/null 2>&1; then
|
|
|
|
|
if readelf -d "${stage_prefix}/lib/libmsquic.so.${version}" |
|
|
|
|
|
grep -E 'NEEDED.*lib(ssl|crypto|numa)' >/dev/null; then
|
|
|
|
|
echo "MsQuic unexpectedly depends on system TLS or NUMA libraries" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
if grep -R -F --exclude='libmsquic.so*' \
|
|
|
|
|
"${repo_root}" "${stage_prefix}" >/dev/null 2>&1; then
|
|
|
|
|
echo "staged MsQuic metadata contains a non-relocatable workspace path" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
if command -v strings >/dev/null 2>&1 &&
|
|
|
|
|
strings "${stage_prefix}/lib/libmsquic.so.${version}" |
|
|
|
|
|
grep -F "${repo_root}" >/dev/null; then
|
|
|
|
|
echo "staged MsQuic runtime contains a non-relocatable workspace path" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
swap_in_progress=false
|
|
|
|
|
restore_install_on_exit() {
|
|
|
|
|
if [[ "${swap_in_progress}" != true ]]; then
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
if [[ -e "${install_root}" ]]; then
|
|
|
|
|
"${cmake_bin}" -E remove_directory "${backup_root}" || true
|
|
|
|
|
elif [[ -e "${backup_root}" ]]; then
|
|
|
|
|
mv "${backup_root}" "${install_root}" || true
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
trap restore_install_on_exit EXIT
|
|
|
|
|
|
|
|
|
|
if [[ -e "${backup_root}" ]]; then
|
|
|
|
|
if [[ ! -e "${install_root}" ]]; then
|
|
|
|
|
mv "${backup_root}" "${install_root}"
|
|
|
|
|
else
|
|
|
|
|
echo "stale MsQuic backup requires manual inspection:" >&2
|
|
|
|
|
echo " ${backup_root}" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
if [[ -e "${install_root}" ]]; then
|
|
|
|
|
swap_in_progress=true
|
|
|
|
|
mv "${install_root}" "${backup_root}"
|
|
|
|
|
fi
|
|
|
|
|
mv "${stage_prefix}" "${install_root}"
|
|
|
|
|
swap_in_progress=false
|
|
|
|
|
"${cmake_bin}" -E remove_directory "${backup_root}"
|
|
|
|
|
trap - EXIT
|
|
|
|
|
|
|
|
|
|
echo "MsQuic ${tag} installed to:"
|
|
|
|
|
echo " ${install_root}"
|
2026-07-27 17:47:30 +08:00
|
|
|
echo "MsQuic is enabled through its request.txt dependency entry."
|