wireguard源码分析(五)

这段批处理脚本用于在 Windows 系统上构建 WireGuard 应用程序。脚本自动化了依赖项的下载、资源文件的生成、代码的编译以及可执行文件的签名等过程。以下是对脚本各个部分的详细分析:

1. 初始设置

关闭命令回显
@echo off
  • 作用:关闭命令行回显,使脚本运行时不会显示每条执行的命令,仅显示输出信息。
版权信息
rem SPDX-License-Identifier: MIT
rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
  • 作用:使用 rem 命令添加注释,声明脚本的许可证类型和版权信息。
启用延迟变量扩展
setlocal enabledelayedexpansion
  • 作用:启用延迟变量扩展,允许在同一代码块内动态修改和访问变量值。这对于在循环或条件语句中处理变量非常有用。
设置环境变量
set BUILDDIR=%~dp0
set PATH=%BUILDDIR%.deps\llvm-mingw\bin;%BUILDDIR%.deps\go\bin;%BUILDDIR%.deps;%PATH%
set PATHEXT=.exe
cd /d %BUILDDIR% || exit /b 1
  • set BUILDDIR=%~dp0
    • 作用:将 BUILDDIR 设置为脚本所在目录的路径。
  • set PATH=...
    • 作用:将 .deps\llvm-mingw\bin.deps\go\bin.deps 目录添加到系统的 PATH 环境变量中,确保脚本能够找到所需的可执行文件和工具链。
  • set PATHEXT=.exe
    • 作用:设置可执行文件的扩展名为 .exe,确保命令行能够正确识别和执行这些文件。
  • cd /d %BUILDDIR% || exit /b 1
    • 作用:切换到 BUILDDIR 目录。如果切换失败,则脚本退出并返回错误代码 1

2. 检查和安装依赖项

检查是否已准备好依赖项
if exist .deps\prepared goto :render
  • 作用:检查 .deps\prepared 文件是否存在。如果存在,跳转到 :render 标签,跳过依赖项的下载和准备过程。
安装依赖项 (:installdeps)
:installdeps
    rmdir /s /q .deps 2> NUL
    mkdir .deps || goto :error
    cd .deps || goto :error
    ...
    copy /y NUL prepared > NUL || goto :error
    cd .. || goto :error
  • 作用
    • rmdir /s /q .deps 2> NUL:删除 .deps 目录及其所有内容,如果删除失败(例如目录不存在),则忽略错误。
    • mkdir .deps || goto :error:创建 .deps 目录。如果创建失败,跳转到 :error 标签处理错误。
    • cd .deps || goto :error:进入 .deps 目录。如果失败,跳转到 :error
    • 下载并验证依赖项:通过调用 :download 子程序下载和验证所需的依赖文件(Go、LLVM MinGW、ImageMagick、GNU Make、WireGuard 工具和 WireGuard-nt)。
    • copy /y NUL prepared > NUL || goto :error:创建一个空的 prepared 文件,标志依赖项已准备好。如果失败,跳转到 :error
    • cd .. || goto :error:返回上级目录,如果失败,跳转到 :error
下载子程序 (:download)
:download
    echo [+] Downloading %1
    curl -#fLo %1 %2 || exit /b 1
    echo [+] Verifying %1
    for /f %%a in ('CertUtil -hashfile %1 SHA256 ^| findstr /r "^[0-9a-f]*$"') do if not "%%a"=="%~3" exit /b 1
    echo [+] Extracting %1
    tar -xf %1 %~4 || exit /b 1
    echo [+] Cleaning up %1
    del %1 || exit /b 1
    goto :eof
  • 作用
    • 下载文件:使用 curl 从指定 URL 下载文件并保存为 %1(第一个参数)。
    • 验证 SHA256 校验和:使用 CertUtil 计算下载文件的 SHA256 哈希值,并与预期值 %~3 比较。如果不匹配,则退出并返回错误。
    • 解压文件:使用 tar 解压缩下载的文件,根据 %~4 指定的参数(例如解压特定目录或文件)。
    • 清理下载的压缩包:删除下载的压缩文件。
    • 跳转到文件末尾:结束子程序,返回调用点。

3. 渲染图标 (:render)

:render
    echo [+] Rendering icons
    for %%a in ("ui\icon\*.svg") do convert -background none "%%~fa" -define icon:auto-resize="256,192,128,96,64,48,40,32,24,20,16" -compress zip "%%~dpna.ico" || goto :error
  • 作用
    • 输出信息:显示正在渲染图标的消息。
    • 循环处理 SVG 图标:遍历 ui\icon\ 目录下的所有 .svg 文件,使用 convert(ImageMagick 工具)将每个 SVG 文件转换为多分辨率的 .ico 图标文件。
    • 错误处理:如果转换失败,跳转到 :error 标签。

4. 构建 WireGuard (:build)

:build
    for /f "tokens=3" %%a in ('findstr /r "Number.*=.*[0-9.]*" .\version\version.go') do set WIREGUARD_VERSION=%%a
    set WIREGUARD_VERSION=%WIREGUARD_VERSION:"=%
    for /f "tokens=1-4" %%a in ("%WIREGUARD_VERSION:.= % 0 0 0") do set WIREGUARD_VERSION_ARRAY=%%a,%%b,%%c,%%d
    set GOOS=windows
    set GOARM=7
    set GOPATH=%BUILDDIR%.deps\gopath
    set GOROOT=%BUILDDIR%.deps\go
    if "%GoGenerate%"=="yes" (
        echo [+] Regenerating files
        go generate ./... || exit /b 1
    )
    call :build_plat x86 i686 386 || goto :error
    call :build_plat amd64 x86_64 amd64 || goto :error
    call :build_plat arm64 aarch64 arm64 || goto :error
  • 作用
    • 提取版本号
      • 使用 findstrversion/version.go 文件中提取版本号,并存储在 WIREGUARD_VERSION 变量中。
      • 移除版本号中的引号。
      • 将版本号拆分为数组格式,存储在 WIREGUARD_VERSION_ARRAY 变量中,用于资源文件的版本信息。
    • 设置 Go 环境变量
      • set GOOS=windows:设置目标操作系统为 Windows。
      • set GOARM=7:设置 ARM 架构的目标版本(ARMv7)。
      • set GOPATHset GOROOT:设置 Go 的工作区和根目录,指向 .deps\gopath.deps\go
    • 生成代码
      • 如果环境变量 GoGenerate 设置为 yes,则运行 go generate 命令生成必要的代码。如果失败,退出脚本。
    • 构建不同架构的可执行文件
      • 调用 :build_plat 子程序三次,分别为 x86(386 架构)、amd64(amd64 架构)和 arm64(arm64 架构)构建 WireGuard。
构建平台子程序 (:build_plat)
:build_plat
    set GOARCH=%~3
    mkdir %1 >NUL 2>&1
    echo [+] Assembling resources %1
    %~2-w64-mingw32-windres -I ".deps\wireguard-nt\bin\%~1" -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
    echo [+] Building program %1
    go build -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v -o "%~1\wireguard.exe" || exit /b 1
    if not exist "%~1\wg.exe" (
        echo [+] Building command line tools %1
        del .deps\src\*.exe .deps\src\*.o .deps\src\wincompat\*.o .deps\src\wincompat\*.lib 2> NUL
        set LDFLAGS=-s
        make --no-print-directory -C .deps\src PLATFORM=windows CC=%~2-w64-mingw32-gcc WINDRES=%~2-w64-mingw32-windres V=1 RUNSTATEDIR= SYSTEMDUNITDIR= -j%NUMBER_OF_PROCESSORS% || exit /b 1
        move /Y .deps\src\wg.exe "%~1\wg.exe" > NUL || exit /b 1
    )
    goto :eof
  • 参数解释
    • %1:平台名称(如 x86amd64arm64)。
    • %2:对应的 MinGW 前缀(如 i686x86_64aarch64)。
    • %3:Go 架构标识(如 386amd64arm64)。
  • 作用
    • 设置架构
      • set GOARCH=%~3:设置 Go 的目标架构。
    • 创建平台目录
      • mkdir %1 >NUL 2>&1:创建对应平台的目录(如 x86amd64arm64),如果目录已存在,则忽略错误。
    • 组装资源文件
      • 使用 windres 工具(MinGW 的资源编译器)将 resources.rc 资源文件编译为 .syso 文件,嵌入版本信息。
      • 参数
        • -I ".deps\wireguard-nt\bin\%~1":指定资源文件包含路径。
        • -DWIREGUARD_VERSION_ARRAY=...-DWIREGUARD_VERSION_STR=...:定义资源文件中的版本信息宏。
        • -i resources.rc:输入的资源文件。
        • -o "resources_%~3.syso":输出的 .syso 资源文件。
        • -O coff -c 65001:指定输出格式为 COFF,并设置编码为 UTF-8。
    • 构建 WireGuard 可执行文件
      • 使用 go build 命令编译 WireGuard 程序,设置相应的编译标志:
        • -tags load_wgnt_from_rsrc:启用特定的编译标签。
        • -ldflags="-H windowsgui -s -w":链接器标志,生成 GUI 应用程序且删除调试信息以减小可执行文件大小。
        • -trimpath:去除编译时路径信息。
        • -buildvcs=false:不嵌入版本控制系统信息。
        • -v:显示详细的编译信息。
        • -o "%~1\wireguard.exe":指定输出的可执行文件路径。
      • 如果编译失败,退出脚本并返回错误代码。
    • 构建命令行工具 wg.exe
      • 检查 wg.exe 是否存在
        • if not exist "%~1\wg.exe" (:如果在目标平台目录中不存在 wg.exe,则需要构建命令行工具。
      • 删除旧的可执行文件和对象文件
        • del .deps\src\*.exe .deps\src\*.o .deps\src\wincompat\*.o .deps\src\wincompat\*.lib 2> NUL:删除旧的可执行文件和对象文件,忽略错误。
      • 设置链接器标志
        • set LDFLAGS=-s:设置链接器标志,去除符号表以减小可执行文件大小。
      • 运行 make 构建 wg.exe
        • make --no-print-directory -C .deps\src PLATFORM=windows CC=%~2-w64-mingw32-gcc WINDRES=%~2-w64-mingw32-windres V=1 RUNSTATEDIR= SYSTEMDUNITDIR= -j%NUMBER_OF_PROCESSORS% || exit /b 1
          • --no-print-directory:不打印目录信息。
          • -C .deps\src:切换到 .deps\src 目录执行 make
          • PLATFORM=windows:指定目标平台为 Windows。
          • CC=...WINDRES=...:指定使用的编译器和资源编译器。
          • V=1:启用详细输出。
          • -j%NUMBER_OF_PROCESSORS%:并行构建,使用与处理器数量相同的线程数。
        • 如果 make 构建失败,退出脚本并返回错误代码。
      • 移动生成的 wg.exe 到目标平台目录
        • move /Y .deps\src\wg.exe "%~1\wg.exe" > NUL || exit /b 1:将生成的 wg.exe 移动到目标平台目录,忽略输出。如果移动失败,退出脚本并返回错误代码。
    • 结束子程序
      • goto :eof:结束当前子程序,返回调用点。

5. 签名可执行文件 (:sign)

:sign
    if exist .\sign.bat call .\sign.bat
    if "%SigningCertificate%"=="" goto :success
    if "%TimestampServer%"=="" goto :success
    echo [+] Signing
    signtool sign /sha1 "%SigningCertificate%" /fd sha256 /tr "%TimestampServer%" /td sha256 /d WireGuard x86\wireguard.exe x86\wg.exe amd64\wireguard.exe amd64\wg.exe arm64\wireguard.exe arm64\wg.exe || goto :error
  • 作用
    • 调用自定义签名脚本
      • if exist .\sign.bat call .\sign.bat:如果存在 sign.bat 文件,则调用执行该脚本。这允许用户自定义签名过程。
    • 检查签名证书和时间戳服务器
      • if "%SigningCertificate%"=="" goto :success:如果未设置 SigningCertificate 环境变量,跳过签名步骤。
      • if "%TimestampServer%"=="" goto :success:如果未设置 TimestampServer 环境变量,跳过签名步骤。
    • 执行签名
      • signtool sign ...:使用 signtool 工具对生成的可执行文件进行签名。
        • /sha1 "%SigningCertificate%":指定签名证书的 SHA1 哈希值。
        • /fd sha256:使用 SHA256 哈希算法进行签名。
        • /tr "%TimestampServer%"/td sha256:指定时间戳服务器,并使用 SHA256 进行时间戳哈希。
        • /d WireGuard:为签名指定描述信息。
        • x86\wireguard.exe x86\wg.exe amd64\wireguard.exe amd64\wg.exe arm64\wireguard.exe arm64\wg.exe:要签名的目标可执行文件。
      • 如果签名失败,跳转到 :error 标签。

6. 成功结束 (:success)

:success
    echo [+] Success. Launch wireguard.exe.
    exit /b 0
  • 作用
    • 输出成功信息:显示构建成功的消息。
    • 退出脚本:以成功状态码 0 退出脚本。

7. 错误处理 (:error)

:error
    echo [-] Failed with error #%errorlevel%.
    cmd /c exit %errorlevel%
  • 作用
    • 输出错误信息:显示构建失败的消息及错误代码。
    • 退出脚本:使用当前错误级别退出脚本,传递错误状态给调用环境。

8. 关键子程序总结

:download 子程序
  • 功能:下载指定的文件、验证其 SHA256 校验和、解压缩并清理下载的压缩包。
  • 参数
    • %1:目标文件名。
    • %2:下载 URL。
    • %3:预期的 SHA256 校验和。
    • %4:解压缩参数(如要解压的特定文件或目录)。
:build_plat 子程序
  • 功能:为指定的平台架构编译 WireGuard 可执行文件。
  • 参数
    • %1:平台名称(如 x86amd64arm64)。
    • %2:MinGW 前缀(如 i686x86_64aarch64)。
    • %3:Go 架构标识(如 386amd64arm64)。

9. 总结

这段批处理脚本通过以下步骤自动化了 WireGuard 在 Windows 上的构建过程:

  1. 初始化环境:设置必要的环境变量,确保脚本在正确的目录下运行,并能找到所需的工具链。
  2. 依赖项管理:检查是否已经准备好依赖项,如果没有,则下载、验证和解压所需的依赖包,包括 Go、LLVM MinGW、ImageMagick、GNU Make 等。
  3. 资源生成:将 SVG 图标转换为多分辨率的 ICO 图标文件,确保应用程序具有适当的图标资源。
  4. 代码编译:提取版本信息,设置 Go 环境变量,并为不同的架构(x86、amd64、arm64)编译 WireGuard 可执行文件及其命令行工具。
  5. 签名可执行文件:如果提供了签名证书和时间戳服务器,使用 signtool 对生成的可执行文件进行数字签名,确保其完整性和来源的可信度。
  6. 错误处理:在任何步骤失败时,脚本都会输出相应的错误信息并退出,确保构建过程的可靠性。
  7. 成功提示:构建完成后,输出成功消息,指示用户可以启动生成的 wireguard.exe

通过这种自动化的构建流程,开发者能够高效地在 Windows 平台上生成不同架构的 WireGuard 版本,确保构建过程的一致性和可重复性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值