diff --git a/package-appimage.sh b/package-appimage.sh index 994e9dc8..6c3ae311 100755 --- a/package-appimage.sh +++ b/package-appimage.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail # Install deps diff --git a/package-debian.sh b/package-debian.sh index c174a80c..58d97482 100755 --- a/package-debian.sh +++ b/package-debian.sh @@ -1,21 +1,36 @@ -#!/bin/bash +#!/usr/bin/env bash +set -euo pipefail -Arch="$1" -OutputPath="$2" -Version="$3" +# Root directory = the script's location +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" +source ./utils.sh -FileName="v2rayN-${Arch}.zip" -wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName" -7z x $FileName -cp -rf v2rayN-${Arch}/* $OutputPath +Arch="linux-64" +OutputPath="$(mktemp -d)" +Version="$1" + +PROJ="./v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj" +dotnet clean "${PROJ}" -c Release +sudo rm -rf "$(dirname "$PROJ")/bin/Release/net8.0" +dotnet publish "${PROJ}" -c Release -r "linux-x64" --self-contained -o "$OutputPath" +PROJ="./v2rayN/AmazTool/AmazTool.csproj" +dotnet clean "${PROJ}" -c Release +sudo rm -rf "$(dirname "$PROJ")/bin/Release/net8.0" +dotnet publish "${PROJ}" -c Release -r "linux-x64" --self-contained -p:PublishTrimmed=true -o "$OutputPath" + +export RID_DIR="linux-x64" +download_xray "$OutputPath/bin/xray" +download_singbox "$OutputPath/bin/sing_box" +download_geo_assets "$OutputPath" PackagePath="v2rayN-Package-${Arch}" mkdir -p "${PackagePath}/DEBIAN" mkdir -p "${PackagePath}/opt" -cp -rf $OutputPath "${PackagePath}/opt/v2rayN" +cp -rf "$OutputPath" "${PackagePath}/opt/v2rayN" echo "When this file exists, app will not store configs under this folder" >"${PackagePath}/opt/v2rayN/NotStoreConfigHere.txt" -if [ $Arch = "linux-64" ]; then +if [ "$Arch" = "linux-64" ]; then Arch2="amd64" else Arch2="arm64" @@ -24,11 +39,14 @@ echo $Arch2 # basic cat >"${PackagePath}/DEBIAN/control" <<-EOF -Package: v2rayN +Package: v2rayn-unofficial Version: $Version +Maintainer: Vlyaii Architecture: $Arch2 -Maintainer: https://github.com/2dust/v2rayN +Replaces: v2rayN, v2rayn Depends: desktop-file-utils, xdg-utils +Breaks: v2rayN, v2rayn +Conflicts: v2rayN, v2rayn Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others EOF @@ -65,5 +83,6 @@ sudo chmod 755 "${PackagePath}/opt/v2rayN/v2rayN" 2>/dev/null || true sudo chmod 755 "${PackagePath}/opt/v2rayN/AmazTool" 2>/dev/null || true # build deb package -sudo dpkg-deb -Zxz --build $PackagePath +sudo dpkg-deb -Zzstd --build "$PackagePath" sudo mv "${PackagePath}.deb" "v2rayN-${Arch}.deb" +sudo rm -rf "$OutputPath" diff --git a/package-linux.sh b/package-linux.sh new file mode 100755 index 00000000..cab4299d --- /dev/null +++ b/package-linux.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Usage: ./package-linux.sh + +OutputArch="linux-64" +OutputPath="$(mktemp -d)" +Version="$1" + +dotnet publish ./v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r "linux-x64" --self-contained -o "$OutputPath" +dotnet publish ./v2rayN/AmazTool/AmazTool.csproj -c Release -r "linux-x64" --self-contained -p:PublishTrimmed=true -o "$OutputPath" + +./package-debian.sh "$OutputArch" "$OutputPath" "$Version" + +rm -rf "$OutputPath" diff --git a/package-osx.sh b/package-osx.sh index aaee58b5..5bf1cb95 100755 --- a/package-osx.sh +++ b/package-osx.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash Arch="$1" OutputPath="$2" diff --git a/package-release-zip.sh b/package-release-zip.sh index 60804e69..f44f5589 100755 --- a/package-release-zip.sh +++ b/package-release-zip.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash Arch="$1" OutputPath="$2" @@ -12,4 +12,4 @@ ZipPath64="./$OutputArch" mkdir $ZipPath64 cp -rf $OutputPath "$ZipPath64/$OutputArch" -7z a -tZip $FileName "$ZipPath64/$OutputArch" -mx1 \ No newline at end of file +7z a -tZip $FileName "$ZipPath64/$OutputArch" -mx1 diff --git a/package-rhel.sh b/package-rhel.sh index 0eeca661..2729caa9 100755 --- a/package-rhel.sh +++ b/package-rhel.sh @@ -1,16 +1,16 @@ #!/usr/bin/env bash set -euo pipefail -# == Require Red Hat Enterprise Linux/FedoraLinux/RockyLinux/AlmaLinux/CentOS OR Ubuntu/Debian == +# == Require Red Hat Enterprise Linux/FedoraLinux/RockyLinux/AlmaLinux/CentOS OR Ubuntu == if [[ -r /etc/os-release ]]; then - . /etc/os-release + source /etc/os-release case "$ID" in - rhel | rocky | almalinux | fedora | centos | ubuntu | debian) + rhel | rocky | almalinux | fedora | centos | ubuntu) echo "[OK] Detected supported system: $NAME $VERSION_ID" ;; *) echo "[ERROR] Unsupported system: $NAME ($ID)." - echo "This script only supports Red Hat Enterprise Linux/RockyLinux/AlmaLinux/CentOS or Ubuntu/Debian." + echo "This script only supports Red Hat Enterprise Linux/RockyLinux/AlmaLinux/CentOS or Ubuntu." exit 1 ;; esac @@ -22,10 +22,7 @@ fi # ===== Config & Parse arguments ========================================================= VERSION_ARG="${1:-}" # Pass version number like 7.13.8, or leave empty WITH_CORE="both" # Default: bundle both xray+sing-box -AUTOSTART=0 # 1 = enable system-wide autostart (/etc/xdg/autostart) -FORCE_NETCORE=0 # --netcore => skip archive bundle, use separate downloads ARCH_OVERRIDE="" # --arch x64|arm64|all (optional compile target) -BUILD_FROM="" # --buildfrom 1|2|3 to select channel non-interactively # If the first argument starts with --, do not treat it as a version number if [[ "${VERSION_ARG:-}" == --* ]]; then @@ -41,10 +38,6 @@ while [[ $# -gt 0 ]]; do WITH_CORE="${2:-both}" shift 2 ;; - --autostart) - AUTOSTART=1 - shift - ;; --xray-ver) XRAY_VER="${2:-}" shift 2 @@ -53,16 +46,12 @@ while [[ $# -gt 0 ]]; do SING_VER="${2:-}" shift 2 ;; - --netcore) - FORCE_NETCORE=1 - shift - ;; --arch) ARCH_OVERRIDE="${2:-}" shift 2 ;; - --buildfrom) - BUILD_FROM="${2:-}" + --release) + RPM_RELEASE="${2:-}" shift 2 ;; *) @@ -72,19 +61,17 @@ while [[ $# -gt 0 ]]; do esac done -# Conflict: version number AND --buildfrom cannot be used together -if [[ -n "${VERSION_ARG:-}" && -n "${BUILD_FROM:-}" ]]; then - echo "[ERROR] You cannot specify both an explicit version and --buildfrom at the same time." - echo " Provide either a version (e.g. 7.14.0) OR --buildfrom 1|2|3." +if [[ -z "${RPM_RELEASE:-}" ]]; then + echo "--release is required" exit 1 fi # ===== Environment check + Dependencies ======================================== host_arch="$(uname -m)" -[[ "$host_arch" == "aarch64" || "$host_arch" == "x86_64" ]] || { +if ! [[ "$host_arch" == "aarch64" || "$host_arch" == "x86_64" ]]; then echo "Only supports aarch64 / x86_64" exit 1 -} +fi install_ok=0 case "$ID" in @@ -127,33 +114,6 @@ ubuntu) fi install_ok=1 ;; -# ------------------------------ Debian (KEEP, with local dotnet install) ------------ -debian) - sudo apt-get update - # Base tools + rpm (provides rpmbuild on Debian) + objdump/strip - sudo apt-get -y install curl unzip tar rsync rpm binutils || true - # rpmbuild presence check - if ! command -v rpmbuild >/dev/null 2>&1; then - echo "[ERROR] 'rpmbuild' not found after installing 'rpm'." - echo " Please ensure 'rpm' is available from Debian repos." - exit 1 - fi - # Try apt for dotnet; fallback to official installer into $HOME/.dotnet - if ! command -v dotnet >/dev/null 2>&1; then - echo "[INFO] 'dotnet' not found. Installing .NET 8 SDK locally to \$HOME/.dotnet ..." - tmp="$(mktemp -d)" - trap '[[ -n "${tmp:-}" ]] && rm -rf "$tmp"' RETURN - curl -fsSL https://dot.net/v1/dotnet-install.sh -o "$tmp/dotnet-install.sh" - bash "$tmp/dotnet-install.sh" --channel 8.0 --install-dir "$HOME/.dotnet" - export PATH="$HOME/.dotnet:$HOME/.dotnet/tools:$PATH" - export DOTNET_ROOT="$HOME/.dotnet" - if ! command -v dotnet >/dev/null 2>&1; then - echo "[ERROR] dotnet installation failed." - exit 1 - fi - fi - install_ok=1 - ;; esac if [[ "$install_ok" -ne 1 ]]; then @@ -167,6 +127,8 @@ command -v curl >/dev/null SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" +source ./utils.sh + # Git submodules (best effort) if [[ -f .gitmodules ]]; then git submodule sync --recursive || true @@ -183,384 +145,7 @@ fi exit 1 } -# ===== Resolve GUI version & auto checkout ============================================ -VERSION="" - -choose_channel() { - # If --buildfrom provided, map it directly and skip interaction. - if [[ -n "${BUILD_FROM:-}" ]]; then - case "$BUILD_FROM" in - 1) - echo "latest" - return 0 - ;; - 2) - echo "prerelease" - return 0 - ;; - 3) - echo "keep" - return 0 - ;; - *) - echo "[ERROR] Invalid --buildfrom value: ${BUILD_FROM}. Use 1|2|3." >&2 - exit 1 - ;; - esac - fi - - # Print menu to stderr and read from /dev/tty so stdout only carries the token. - local ch="latest" sel="" - if [[ -t 0 ]]; then - echo "[?] Choose v2rayN release channel:" >&2 - echo " 1) Latest (stable) [default]" >&2 - echo " 2) Pre-release (preview)" >&2 - echo " 3) Keep current (do nothing)" >&2 - printf "Enter 1, 2 or 3 [default 1]: " >&2 - if read -r sel /dev/null 2>&1; then - tag="$(printf '%s' "$json" | - jq -r '[.[] | select(.prerelease==true)][0].tag_name' 2>/dev/null | - sed 's/^v//')" || true - fi - - # 2) Fallback to sed/grep only - if [[ -z "${tag:-}" || "${tag:-}" == "null" ]]; then - tag="$(printf '%s' "$json" | - tr '\n' ' ' | - sed 's/},[[:space:]]*{/\n/g' | - grep -m1 -E '"prerelease"[[:space:]]*:[[:space:]]*true' | - grep -Eo '"tag_name"[[:space:]]*:[[:space:]]*"v?[^"]+"' | - head -n1 | - sed -E 's/.*"tag_name"[[:space:]]*:[[:space:]]*"v?([^"]+)".*/\1/')" || true - fi - - [[ -n "${tag:-}" && "${tag:-}" != "null" ]] || return 1 - printf '%s\n' "$tag" -} - -git_try_checkout() { - # Try a series of refs and checkout when found. - local want="$1" ref="" - if git rev-parse --git-dir >/dev/null 2>&1; then - git fetch --tags --force --prune --depth=1 || true - if git rev-parse "refs/tags/v${want}" >/dev/null 2>&1; then - ref="v${want}" - elif git rev-parse "refs/tags/${want}" >/dev/null 2>&1; then - ref="${want}" - elif git rev-parse --verify "${want}" >/dev/null 2>&1; then - ref="${want}" - fi - if [[ -n "$ref" ]]; then - echo "[OK] Found ref '${ref}', checking out..." - git checkout -f "${ref}" - if [[ -f .gitmodules ]]; then - git submodule sync --recursive || true - git submodule update --init --recursive || true - fi - return 0 - fi - fi - return 1 -} - -if git rev-parse --git-dir >/dev/null 2>&1; then - if [[ -n "${VERSION_ARG:-}" ]]; then - echo "[*] Trying to switch v2rayN repo to version: ${VERSION_ARG}" - if git_try_checkout "${VERSION_ARG#v}"; then - VERSION="${VERSION_ARG#v}" - else - echo "[WARN] Tag '${VERSION_ARG}' not found." - ch="$(choose_channel)" - if [[ "$ch" == "keep" ]]; then - echo "[*] Keep current repository state (no checkout)." - if git describe --tags --abbrev=0 >/dev/null 2>&1; then - VERSION="$(git describe --tags --abbrev=0)" - else - VERSION="0.0.0+git" - fi - VERSION="${VERSION#v}" - else - echo "[*] Resolving ${ch} tag from GitHub releases..." - tag="" - if [[ "$ch" == "prerelease" ]]; then - tag="$(get_latest_tag_prerelease || true)" - if [[ -z "$tag" ]]; then - echo "[WARN] Failed to resolve prerelease tag, falling back to latest." - tag="$(get_latest_tag_latest || true)" - fi - else - tag="$(get_latest_tag_latest || true)" - fi - [[ -n "$tag" ]] || { - echo "[ERROR] Failed to resolve latest tag for channel '${ch}'." - exit 1 - } - echo "[*] Latest tag for '${ch}': ${tag}" - git_try_checkout "$tag" || { - echo "[ERROR] Failed to checkout '${tag}'." - exit 1 - } - VERSION="${tag#v}" - fi - fi - else - ch="$(choose_channel)" - if [[ "$ch" == "keep" ]]; then - echo "[*] Keep current repository state (no checkout)." - if git describe --tags --abbrev=0 >/dev/null 2>&1; then - VERSION="$(git describe --tags --abbrev=0)" - else - VERSION="0.0.0+git" - fi - VERSION="${VERSION#v}" - else - echo "[*] Resolving ${ch} tag from GitHub releases..." - tag="" - if [[ "$ch" == "prerelease" ]]; then - tag="$(get_latest_tag_prerelease || true)" - if [[ -z "$tag" ]]; then - echo "[WARN] Failed to resolve prerelease tag, falling back to latest." - tag="$(get_latest_tag_latest || true)" - fi - else - tag="$(get_latest_tag_latest || true)" - fi - [[ -n "$tag" ]] || { - echo "[ERROR] Failed to resolve latest tag for channel '${ch}'." - exit 1 - } - echo "[*] Latest tag for '${ch}': ${tag}" - git_try_checkout "$tag" || { - echo "[ERROR] Failed to checkout '${tag}'." - exit 1 - } - VERSION="${tag#v}" - fi - fi -else - echo "[WARN] Current directory is not a git repo; cannot checkout version. Proceeding on current tree." - VERSION="${VERSION_ARG:-}" - if [[ -z "$VERSION" ]]; then - if git describe --tags --abbrev=0 >/dev/null 2>&1; then - VERSION="$(git describe --tags --abbrev=0)" - else - VERSION="0.0.0+git" - fi - fi - VERSION="${VERSION#v}" -fi -echo "[*] GUI version resolved as: ${VERSION}" - -# ===== Helpers for core/rules download (use RID_DIR for arch sync) ===================== -download_xray() { - # Download Xray core and install to outdir/xray - local outdir="$1" ver="${XRAY_VER:-}" url tmp zipname="xray.zip" - mkdir -p "$outdir" - if [[ -n "${XRAY_VER:-}" ]]; then ver="${XRAY_VER}"; fi - if [[ -z "$ver" ]]; then - ver="$(curl -fsSL https://api.github.com/repos/XTLS/Xray-core/releases/latest | - grep -Eo '"tag_name":\s*"v[^"]+"' | sed -E 's/.*"v([^"]+)".*/\1/' | head -n1)" || true - fi - [[ -n "$ver" ]] || { - echo "[xray] Failed to get version" - return 1 - } - if [[ "$RID_DIR" == "linux-arm64" ]]; then - url="https://github.com/XTLS/Xray-core/releases/download/v${ver}/Xray-linux-arm64-v8a.zip" - else - url="https://github.com/XTLS/Xray-core/releases/download/v${ver}/Xray-linux-64.zip" - fi - echo "[+] Download xray: $url" - tmp="$(mktemp -d)" - trap '[[ -n "${tmp:-}" ]] && rm -rf "$tmp"' RETURN - curl -fL "$url" -o "$tmp/$zipname" - unzip -q "$tmp/$zipname" -d "$tmp" - install -Dm755 "$tmp/xray" "$outdir/xray" -} - -download_singbox() { - # Download sing-box core and install to outdir/sing-box - local outdir="$1" ver="${SING_VER:-}" url tmp tarname="singbox.tar.gz" bin - mkdir -p "$outdir" - if [[ -n "${SING_VER:-}" ]]; then ver="${SING_VER}"; fi - if [[ -z "$ver" ]]; then - ver="$(curl -fsSL https://api.github.com/repos/SagerNet/sing-box/releases/latest | - grep -Eo '"tag_name":\s*"v[^"]+"' | sed -E 's/.*"v([^"]+)".*/\1/' | head -n1)" || true - fi - [[ -n "$ver" ]] || { - echo "[sing-box] Failed to get version" - return 1 - } - if [[ "$RID_DIR" == "linux-arm64" ]]; then - url="https://github.com/SagerNet/sing-box/releases/download/v${ver}/sing-box-${ver}-linux-arm64.tar.gz" - else - url="https://github.com/SagerNet/sing-box/releases/download/v${ver}/sing-box-${ver}-linux-amd64.tar.gz" - fi - echo "[+] Download sing-box: $url" - tmp="$(mktemp -d)" - trap '[[ -n "${tmp:-}" ]] && rm -rf "$tmp"' RETURN - curl -fL "$url" -o "$tmp/$tarname" - tar -C "$tmp" -xzf "$tmp/$tarname" - bin="$(find "$tmp" -type f -name 'sing-box' | head -n1 || true)" - [[ -n "$bin" ]] || { - echo "[!] sing-box unpack failed" - return 1 - } - install -Dm755 "$bin" "$outdir/sing-box" -} - -# ---- NEW: download_mihomo (REQUIRED in --netcore mode) ---- -download_mihomo() { - # Download mihomo into outroot/bin/mihomo/mihomo - local outroot="$1" - local url="" - if [[ "$RID_DIR" == "linux-arm64" ]]; then - url="https://raw.githubusercontent.com/2dust/v2rayN-core-bin/refs/heads/master/v2rayN-linux-arm64/bin/mihomo/mihomo" - else - url="https://raw.githubusercontent.com/2dust/v2rayN-core-bin/refs/heads/master/v2rayN-linux-64/bin/mihomo/mihomo" - fi - echo "[+] Download mihomo: $url" - mkdir -p "$outroot/bin/mihomo" - curl -fL "$url" -o "$outroot/bin/mihomo/mihomo" - chmod +x "$outroot/bin/mihomo/mihomo" || true -} - -# Move geo files to a unified path: outroot/bin -unify_geo_layout() { - local outroot="$1" - mkdir -p "$outroot/bin" - local names=( - "geosite.dat" - "geoip.dat" - "geoip-only-cn-private.dat" - "Country.mmdb" - "geoip.metadb" - ) - for n in "${names[@]}"; do - # If file exists under bin/xray/, move it up to bin/ - if [[ -f "$outroot/bin/xray/$n" ]]; then - mv -f "$outroot/bin/xray/$n" "$outroot/bin/$n" - fi - # If file already in bin/, leave it as-is - if [[ -f "$outroot/bin/$n" ]]; then - : - fi - done -} - -# Download geo/rule assets; then unify to bin/ -download_geo_assets() { - local outroot="$1" - local bin_dir="$outroot/bin" - local srss_dir="$bin_dir/srss" - mkdir -p "$bin_dir" "$srss_dir" - - echo "[+] Download Xray Geo to ${bin_dir}" - curl -fsSL -o "$bin_dir/geosite.dat" \ - "https://github.com/Loyalsoldier/V2ray-rules-dat/releases/latest/download/geosite.dat" - curl -fsSL -o "$bin_dir/geoip.dat" \ - "https://github.com/Loyalsoldier/V2ray-rules-dat/releases/latest/download/geoip.dat" - curl -fsSL -o "$bin_dir/geoip-only-cn-private.dat" \ - "https://raw.githubusercontent.com/Loyalsoldier/geoip/release/geoip-only-cn-private.dat" - curl -fsSL -o "$bin_dir/Country.mmdb" \ - "https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb" - - echo "[+] Download sing-box rule DB & rule-sets" - curl -fsSL -o "$bin_dir/geoip.metadb" \ - "https://github.com/MetaCubeX/meta-rules-dat/releases/latest/download/geoip.metadb" || true - - for f in \ - geoip-private.srs geoip-cn.srs geoip-facebook.srs geoip-fastly.srs \ - geoip-google.srs geoip-netflix.srs geoip-telegram.srs geoip-twitter.srs; do - curl -fsSL -o "$srss_dir/$f" \ - "https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geoip/$f" || true - done - for f in \ - geosite-cn.srs geosite-gfw.srs geosite-greatfire.srs \ - geosite-geolocation-cn.srs geosite-category-ads-all.srs geosite-private.srs; do - curl -fsSL -o "$srss_dir/$f" \ - "https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geosite/$f" || true - done - - # Unify to bin/ - unify_geo_layout "$outroot" -} - -# Prefer the prebuilt v2rayN core bundle; then unify geo layout -download_v2rayn_bundle() { - local outroot="$1" - local url="" - if [[ "$RID_DIR" == "linux-arm64" ]]; then - url="https://raw.githubusercontent.com/2dust/v2rayN-core-bin/refs/heads/master/v2rayN-linux-arm64.zip" - else - url="https://raw.githubusercontent.com/2dust/v2rayN-core-bin/refs/heads/master/v2rayN-linux-64.zip" - fi - echo "[+] Try v2rayN bundle archive: $url" - local tmp zipname - tmp="$(mktemp -d)" - zipname="$tmp/v2rayn.zip" - curl -fL "$url" -o "$zipname" || { - echo "[!] Bundle download failed" - return 1 - } - unzip -q "$zipname" -d "$tmp" || { - echo "[!] Bundle unzip failed" - return 1 - } - - if [[ -d "$tmp/bin" ]]; then - mkdir -p "$outroot/bin" - rsync -a "$tmp/bin/" "$outroot/bin/" - else - rsync -a "$tmp/" "$outroot/" - fi - - rm -f "$outroot/v2rayn.zip" 2>/dev/null || true - # keep mihomo - # find "$outroot" -type d -name "mihomo" -prune -exec rm -rf {} + 2>/dev/null || true - - local nested_dir - nested_dir="$(find "$outroot" -maxdepth 1 -type d -name 'v2rayN-linux-*' | head -n1 || true)" - if [[ -n "${nested_dir:-}" && -d "$nested_dir/bin" ]]; then - mkdir -p "$outroot/bin" - rsync -a "$nested_dir/bin/" "$outroot/bin/" - rm -rf "$nested_dir" - fi - - # Unify to bin/ - unify_geo_layout "$outroot" - - echo "[+] Bundle extracted to $outroot" -} +VERSION="$VERSION_ARG" # ===== Build results collection for --arch all ======================================== BUILT_RPMS=() # Will collect absolute paths of built RPMs @@ -597,6 +182,7 @@ build_for_arch() { dotnet restore "$PROJECT" dotnet publish "$PROJECT" \ -c Release -r "$rid" \ + --sc \ -p:PublishSingleFile=false \ -p:SelfContained=true \ -p:IncludeNativeLibrariesForSelfExtract=true @@ -645,31 +231,13 @@ build_for_arch() { mkdir -p "$WORKDIR/$PKGROOT/bin/xray" "$WORKDIR/$PKGROOT/bin/sing_box" # Bundle / cores per-arch - if [[ "$FORCE_NETCORE" -eq 0 ]]; then - if download_v2rayn_bundle "$WORKDIR/$PKGROOT"; then - echo "[*] Using v2rayN bundle archive." - else - echo "[*] Bundle failed, fallback to separate core + rules." - if [[ "$WITH_CORE" == "xray" || "$WITH_CORE" == "both" ]]; then - download_xray "$WORKDIR/$PKGROOT/bin/xray" || echo "[!] xray download failed (skipped)" - fi - if [[ "$WITH_CORE" == "sing-box" || "$WITH_CORE" == "both" ]]; then - download_singbox "$WORKDIR/$PKGROOT/bin/sing_box" || echo "[!] sing-box download failed (skipped)" - fi - download_geo_assets "$WORKDIR/$PKGROOT" || echo "[!] Geo rules download failed (skipped)" - fi - else - echo "[*] --netcore specified: use separate core + rules." - if [[ "$WITH_CORE" == "xray" || "$WITH_CORE" == "both" ]]; then - download_xray "$WORKDIR/$PKGROOT/bin/xray" || echo "[!] xray download failed (skipped)" - fi - if [[ "$WITH_CORE" == "sing-box" || "$WITH_CORE" == "both" ]]; then - download_singbox "$WORKDIR/$PKGROOT/bin/sing_box" || echo "[!] sing-box download failed (skipped)" - fi - download_geo_assets "$WORKDIR/$PKGROOT" || echo "[!] Geo rules download failed (skipped)" - # ---- REQUIRED: always fetch mihomo in netcore mode, per-arch ---- - download_mihomo "$WORKDIR/$PKGROOT" || echo "[!] mihomo download failed (skipped)" + if [[ "$WITH_CORE" == "xray" || "$WITH_CORE" == "both" ]]; then + download_xray "$WORKDIR/$PKGROOT/bin/xray" || echo "[!] xray download failed (skipped)" fi + if [[ "$WITH_CORE" == "sing-box" || "$WITH_CORE" == "both" ]]; then + download_singbox "$WORKDIR/$PKGROOT/bin/sing_box" || echo "[!] sing-box download failed (skipped)" + fi + download_geo_assets "$WORKDIR/$PKGROOT" || echo "[!] Geo rules download failed (skipped)" # Tarball mkdir -p "$SOURCEDIR" @@ -685,12 +253,12 @@ build_for_arch() { # Ignore outdated LTTng dependencies incorrectly reported by the .NET runtime (to avoid installation failures) %global __requires_exclude ^liblttng-ust\.so\..*$ -Name: v2rayN +Name: v2rayn-unofficial Version: __VERSION__ -Release: 1%{?dist} +Release: __RELEASE__ Summary: v2rayN (Avalonia) GUI client for Linux (x86_64/aarch64) License: GPL-3.0-only -URL: https://github.com/2dust/v2rayN +URL: https://git.vlyaii.ru/voronin9032/v2rayN BugURL: https://github.com/2dust/v2rayN/issues ExclusiveArch: aarch64 x86_64 Source0: __PKGROOT__.tar.gz @@ -699,6 +267,9 @@ Source0: __PKGROOT__.tar.gz Requires: libX11, libXrandr, libXcursor, libXi, libXext, libxcb, libXrender, libXfixes, libXinerama, libxkbcommon Requires: fontconfig, freetype, cairo, pango, mesa-libEGL, mesa-libGL, xdg-utils +Conflicts: v2rayN +Obsoletes: v2rayN + %description v2rayN Linux for Red Hat Enterprise Linux Support vless / vmess / Trojan / http / socks / Anytls / Hysteria2 / Shadowsocks / tuic / WireGuard @@ -771,41 +342,9 @@ fi %{_datadir}/icons/hicolor/256x256/apps/v2rayn.png SPEC - # Autostart injection (inside %install) and %files entry - if [[ "$AUTOSTART" -eq 1 ]]; then - awk ' - BEGIN{ins=0} - /^%post$/ && !ins { - print "# --- Autostart (.desktop) ---" - print "install -dm0755 %{buildroot}/etc/xdg/autostart" - print "cat > %{buildroot}/etc/xdg/autostart/v2rayn.desktop << '\''EOF'\''" - print "[Desktop Entry]" - print "Type=Application" - print "Name=v2rayN (Autostart)" - print "Exec=v2rayn" - print "X-GNOME-Autostart-enabled=true" - print "NoDisplay=false" - print "EOF" - ins=1 - } - {print} - ' "$SPECFILE" >"${SPECFILE}.tmp" && mv "${SPECFILE}.tmp" "$SPECFILE" - - awk ' - BEGIN{infiles=0; done=0} - /^%files$/ {infiles=1} - infiles && done==0 && $0 ~ /%{_datadir}\/icons\/hicolor\/256x256\/apps\/v2rayn\.png/ { - print - print "%config(noreplace) /etc/xdg/autostart/v2rayn.desktop" - done=1 - next - } - {print} - ' "$SPECFILE" >"${SPECFILE}.tmp" && mv "${SPECFILE}.tmp" "$SPECFILE" - fi - # Replace placeholders sed -i "s/__VERSION__/${VERSION}/g" "$SPECFILE" + sed -i "s/__RELEASE__/${RPM_RELEASE}/g" "$SPECFILE" sed -i "s/__PKGROOT__/${PKGROOT}/g" "$SPECFILE" # ----- Select proper 'strip' per target arch on Ubuntu only (cross-binutils) ----- @@ -840,7 +379,7 @@ SPEC echo "Build done for $short. RPM at:" local f - for f in "${TOPDIR}/RPMS/${archdir}/v2rayN-${VERSION}-1"*.rpm; do + for f in "${TOPDIR}/RPMS/${archdir}/v2rayN-${VERSION}-${RPM_RELEASE}"*.rpm; do [[ -e "$f" ]] || continue echo " $f" BUILT_RPMS+=("$f") diff --git a/utils.sh b/utils.sh new file mode 100644 index 00000000..8cc0183c --- /dev/null +++ b/utils.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash + +download_xray() { + # Download Xray core and install to outdir/xray + local outdir="$1" ver="${XRAY_VER:-}" url tmp zipname="xray.zip" + mkdir -p "$outdir" + if [[ -n "${XRAY_VER:-}" ]]; then ver="${XRAY_VER}"; fi + if [[ -z "$ver" ]]; then + echo "Downloading latest xray" + ver="$(curl -fsSL https://api.github.com/repos/XTLS/Xray-core/releases/latest | + grep -Eo '"tag_name":\s*"v[^"]+"' | sed -E 's/.*"v([^"]+)".*/\1/' | head -n1)" || true + fi + if [[ -z "$ver" ]]; then + echo "[xray] Failed to get version" + return 1 + fi + if [[ "$RID_DIR" == "linux-arm64" ]]; then + url="https://github.com/XTLS/Xray-core/releases/download/v${ver}/Xray-linux-arm64-v8a.zip" + else + url="https://github.com/XTLS/Xray-core/releases/download/v${ver}/Xray-linux-64.zip" + fi + echo "[+] Download xray: $url" + tmp="$(mktemp -d)" + trap '[[ -n "${tmp:-}" ]] && rm -rf "$tmp"' RETURN + curl -fL "$url" -o "$tmp/$zipname" + unzip -q "$tmp/$zipname" -d "$tmp" + install -Dm755 "$tmp/xray" "$outdir/xray" +} + +download_singbox() { + # Download sing-box core and install to outdir/sing-box + local outdir="$1" ver="${SING_VER:-}" url tmp tarname="singbox.tar.gz" bin + mkdir -p "$outdir" + if [[ -n "${SING_VER:-}" ]]; then ver="${SING_VER}"; fi + if [[ -z "$ver" ]]; then + echo "Downloading latest sing-box" + ver="$(curl -fsSL https://api.github.com/repos/SagerNet/sing-box/releases/latest | + grep -Eo '"tag_name":\s*"v[^"]+"' | sed -E 's/.*"v([^"]+)".*/\1/' | head -n1)" || true + fi + if [[ -z "$ver" ]]; then + echo "[sing-box] Failed to get version" + return 1 + fi + if [[ "$RID_DIR" == "linux-arm64" ]]; then + url="https://github.com/SagerNet/sing-box/releases/download/v${ver}/sing-box-${ver}-linux-arm64.tar.gz" + else + url="https://github.com/SagerNet/sing-box/releases/download/v${ver}/sing-box-${ver}-linux-amd64.tar.gz" + fi + echo "[+] Download sing-box: $url" + tmp="$(mktemp -d)" + trap '[[ -n "${tmp:-}" ]] && rm -rf "$tmp"' RETURN + curl -fL "$url" -o "$tmp/$tarname" + tar -C "$tmp" -xzf "$tmp/$tarname" + bin="$(find "$tmp" -type f -name 'sing-box' | head -n1 || true)" + [[ -n "$bin" ]] || { + echo "[!] sing-box unpack failed" + return 1 + } + install -Dm755 "$bin" "$outdir/sing-box" +} + +# Move geo files to a unified path: outroot/bin +unify_geo_layout() { + local outroot="$1" + mkdir -p "$outroot/bin" + local names=( + "geosite.dat" + "geoip.dat" + "geoip-only-cn-private.dat" + "Country.mmdb" + "geoip.metadb" + ) + for n in "${names[@]}"; do + # If file exists under bin/xray/, move it up to bin/ + if [[ -f "$outroot/bin/xray/$n" ]]; then + mv -f "$outroot/bin/xray/$n" "$outroot/bin/$n" + fi + # If file already in bin/, leave it as-is + if [[ -f "$outroot/bin/$n" ]]; then + : + fi + done +} + +# Download geo/rule assets; then unify to bin/ +download_geo_assets() { + local outroot="$1" + local bin_dir="$outroot/bin" + local srss_dir="$bin_dir/srss" + mkdir -p "$bin_dir" "$srss_dir" + echo "[+] Download Xray Geo to ${bin_dir}" + curl -fsSL -o "$bin_dir/geosite.dat" \ + "https://github.com/Loyalsoldier/V2ray-rules-dat/releases/latest/download/geosite.dat" + curl -fsSL -o "$bin_dir/geoip.dat" \ + "https://github.com/Loyalsoldier/V2ray-rules-dat/releases/latest/download/geoip.dat" + curl -fsSL -o "$bin_dir/geoip-only-cn-private.dat" \ + "https://raw.githubusercontent.com/Loyalsoldier/geoip/release/geoip-only-cn-private.dat" + curl -fsSL -o "$bin_dir/Country.mmdb" \ + "https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb" + + echo "[+] Download sing-box rule DB & rule-sets" + curl -fsSL -o "$bin_dir/geoip.metadb" \ + "https://github.com/MetaCubeX/meta-rules-dat/releases/latest/download/geoip.metadb" || true + + for f in \ + geoip-private.srs geoip-cn.srs geoip-facebook.srs geoip-fastly.srs \ + geoip-google.srs geoip-netflix.srs geoip-telegram.srs geoip-twitter.srs; do + curl -fsSL -o "$srss_dir/$f" \ + "https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geoip/$f" || true + done + for f in \ + geosite-cn.srs geosite-gfw.srs geosite-greatfire.srs \ + geosite-geolocation-cn.srs geosite-category-ads-all.srs geosite-private.srs; do + curl -fsSL -o "$srss_dir/$f" \ + "https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geosite/$f" || true + done + + # Unify to bin/ + unify_geo_layout "$outroot" +}