440 lines
14 KiB
Batchfile
440 lines
14 KiB
Batchfile
@echo off
|
|
rem ===========================================================================
|
|
rem SG_Algorithm 编译脚本
|
|
rem
|
|
rem 功能:
|
|
rem 1) 交互选择要编译的库, 使用 MSBuild Rebuild (先清理再编译),
|
|
rem 按库显示完成百分比进度, Debug 和 Release 都编译 (默认 x64)
|
|
rem 2) 使用 WSL + CMake 编译 arm(aarch64) 库, 构建目录 armbuild,
|
|
rem 每次都先 make clean 再编译
|
|
rem
|
|
rem 用法:
|
|
rem build.bat 交互选择库, Rebuild Debug + Release, 并编译 ARM
|
|
rem build.bat /all 编译全部库
|
|
rem build.bat /config:debug 只编译 Debug (debug / release / both)
|
|
rem build.bat /no-arm 跳过 ARM 编译
|
|
rem build.bat /arm-config:Debug ARM 配置 (默认 Release)
|
|
rem build.bat /opencv:480 ARM 使用 OpenCV 4.8.0 (默认 320)
|
|
rem build.bat /platform:x86 Windows 平台 (默认 x64)
|
|
rem build.bat /j:8 ARM make 并行任务数 (默认 CPU 核心数)
|
|
rem build.bat /dry-run 只打印命令, 不实际编译
|
|
rem build.bat /no-pause 结束后不暂停
|
|
rem
|
|
rem 输出:
|
|
rem Windows : build\{platform}\{config}\ (e.g. build\x64\Debug)
|
|
rem ARM : build\aarch64\
|
|
rem ===========================================================================
|
|
|
|
rem 注意: 本文件保存为 ANSI(GBK/cp936) 编码, 与中文 Windows 控制台代码页一致,
|
|
rem 请勿另存为 UTF-8, 否则 cmd 解析中文时会乱码。
|
|
setlocal EnableExtensions EnableDelayedExpansion
|
|
|
|
set "ROOT=%~dp0"
|
|
if "%ROOT:~-1%"=="\" set "ROOT=%ROOT:~0,-1%"
|
|
set "SLN=%ROOT%\SG_Algorithm.sln"
|
|
set "ARMBUILD=%ROOT%\armbuild"
|
|
set "LOGDIR=%ROOT%\build\logs"
|
|
|
|
rem ---------------------------- 默认参数 -----------------------------------
|
|
set "PLATFORM=x64"
|
|
set "CONFIGS=Debug Release"
|
|
set "DO_ARM=1"
|
|
set "ARM_CONFIG=Release"
|
|
set "OPENCV_VERSION=320"
|
|
set "JOBS="
|
|
set "NOPAUSE=0"
|
|
set "DRYRUN=0"
|
|
set "BUILD_ALL=0"
|
|
set "FAILED="
|
|
set "FAIL_COUNT=0"
|
|
set "OK_COUNT=0"
|
|
set "STEP=0"
|
|
|
|
rem ---------------------------- 参数解析 -----------------------------------
|
|
:parse_args
|
|
if "%~1"=="" goto args_done
|
|
set "ARG=%~1"
|
|
if /i "%ARG%"=="/all" ( set "BUILD_ALL=1" & shift & goto parse_args )
|
|
if /i "%ARG%"=="/no-arm" ( set "DO_ARM=0" & shift & goto parse_args )
|
|
if /i "%ARG%"=="/no-pause" ( set "NOPAUSE=1" & shift & goto parse_args )
|
|
if /i "%ARG%"=="/dry-run" ( set "DRYRUN=1" & shift & goto parse_args )
|
|
if /i "%ARG%"=="/help" goto help
|
|
if /i "%ARG%"=="/?" goto help
|
|
if /i "%ARG%"=="-h" goto help
|
|
if /i "!ARG:~0,10!"=="/platform:" ( set "PLATFORM=!ARG:~10!" & shift & goto parse_args )
|
|
if /i "!ARG:~0,12!"=="/arm-config:" ( set "ARM_CONFIG=!ARG:~12!" & shift & goto parse_args )
|
|
if /i "!ARG:~0,8!"=="/opencv:" ( set "OPENCV_VERSION=!ARG:~8!" & shift & goto parse_args )
|
|
if /i "!ARG:~0,8!"=="/config:" ( call :set_configs "!ARG:~8!" & shift & goto parse_args )
|
|
if /i "!ARG:~0,3!"=="/j:" ( set "JOBS=!ARG:~3!" & shift & goto parse_args )
|
|
echo [错误] 未知参数: %ARG%
|
|
echo 使用 build.bat /help 查看帮助。
|
|
set "EXIT_CODE=1"
|
|
goto end
|
|
|
|
:args_done
|
|
if /i not "%PLATFORM%"=="x64" if /i not "%PLATFORM%"=="x86" (
|
|
echo [错误] 不支持的平台: %PLATFORM% ^(仅支持 x64 / x86^)
|
|
set "EXIT_CODE=1"
|
|
goto end
|
|
)
|
|
if /i "%ARM_CONFIG%"=="debug" set "ARM_CONFIG=Debug"
|
|
if /i "%ARM_CONFIG%"=="release" set "ARM_CONFIG=Release"
|
|
if /i not "%ARM_CONFIG%"=="Debug" if /i not "%ARM_CONFIG%"=="Release" (
|
|
echo [错误] 不支持的 ARM 配置: %ARM_CONFIG% ^(仅支持 Debug / Release^)
|
|
set "EXIT_CODE=1"
|
|
goto end
|
|
)
|
|
|
|
if not exist "%SLN%" (
|
|
echo [错误] 找不到解决方案: %SLN%
|
|
set "EXIT_CODE=1"
|
|
goto end
|
|
)
|
|
|
|
rem ---------------------------- 查找 MSBuild --------------------------------
|
|
rem 优先使用装有 v142 工具集的 VS 安装 (本解决方案中部分工程仍使用 v142)
|
|
set "MSBUILD="
|
|
set "MSBUILD_V142="
|
|
set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
|
|
if exist "%VSWHERE%" (
|
|
for /f "delims=" %%i in ('call "%VSWHERE%" -products * -property installationPath') do (
|
|
if exist "%%i\MSBuild\Current\Bin\MSBuild.exe" (
|
|
if not defined MSBUILD set "MSBUILD=%%i\MSBuild\Current\Bin\MSBuild.exe"
|
|
for /d %%d in ("%%i\VC\Tools\MSVC\14.29*") do (
|
|
set "MSBUILD_V142=%%i\MSBuild\Current\Bin\MSBuild.exe"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
if defined MSBUILD_V142 set "MSBUILD=%MSBUILD_V142%"
|
|
if not defined MSBUILD (
|
|
for %%p in (MSBuild.exe) do if not "%%~$PATH:p"=="" set "MSBUILD=%%~$PATH:p"
|
|
)
|
|
if not defined MSBUILD (
|
|
echo [错误] 未找到 MSBuild.exe, 请安装 Visual Studio 2019/2022 生成工具。
|
|
set "EXIT_CODE=1"
|
|
goto end
|
|
)
|
|
|
|
rem ---------------------------- 枚举库工程 ----------------------------------
|
|
rem 只列出非 *_test 的库工程, 且工程文件必须存在
|
|
set "LIB_COUNT=0"
|
|
for /f "usebackq tokens=2,3 delims==, " %%A in (`findstr /b /c:"Project(" "%SLN%"`) do (
|
|
set "PNAME=%%~A"
|
|
set "PPATH=%%~B"
|
|
if not "!PPATH:_test\=!"=="!PPATH!" set "PNAME="
|
|
if /i "!PNAME:~-5!"=="_test" set "PNAME="
|
|
if "!PPATH:~-8!"==".vcxproj" if defined PNAME if exist "%ROOT%\!PPATH!" (
|
|
set /a LIB_COUNT+=1
|
|
set "LIB[!LIB_COUNT!]=!PNAME!"
|
|
set "LIBPATH[!LIB_COUNT!]=!PPATH!"
|
|
)
|
|
)
|
|
if %LIB_COUNT%==0 (
|
|
echo [错误] 在解决方案中未找到可编译的库工程。
|
|
set "EXIT_CODE=1"
|
|
goto end
|
|
)
|
|
|
|
if "%BUILD_ALL%"=="1" goto pick_all
|
|
|
|
rem ---------------------------- 交互选择 -----------------------------------
|
|
:menu
|
|
echo.
|
|
echo ============================================================
|
|
echo SG_Algorithm 编译 (Rebuild)
|
|
echo 解决方案 : SG_Algorithm.sln
|
|
echo 平台 : %PLATFORM%
|
|
echo 配置 : %CONFIGS%
|
|
echo ARM 编译 : %DO_ARM% ^(%ARM_CONFIG%^)
|
|
echo ============================================================
|
|
for /l %%i in (1,1,%LIB_COUNT%) do (
|
|
set "IDX= %%i"
|
|
if %%i GEQ 10 set "IDX= %%i"
|
|
echo !IDX!. !LIB[%%i]!
|
|
)
|
|
echo.
|
|
echo A. 全部
|
|
echo Q. 退出
|
|
echo.
|
|
set "SEL="
|
|
set /p "SEL=请输入编号 (多选: 1 3 5 / 1-4 / all): "
|
|
if not defined SEL (
|
|
set /a EMPTY_COUNT+=1
|
|
if !EMPTY_COUNT! GEQ 3 (
|
|
echo 未输入选择, 退出。
|
|
set "EXIT_CODE=1"
|
|
goto end
|
|
)
|
|
goto menu
|
|
)
|
|
set "SEL=%SEL:,= %"
|
|
set "SEL=%SEL:;= %"
|
|
if /i "%SEL: =%"=="q" goto cancel
|
|
if /i "%SEL: =%"=="quit" goto cancel
|
|
if /i "%SEL: =%"=="all" goto pick_all
|
|
if /i "%SEL: =%"=="a" goto pick_all
|
|
if "%SEL: =%"=="*" goto pick_all
|
|
rem 只允许 数字 / 空格 / 减号, 避免特殊字符进入命令行
|
|
for /f "delims=0123456789- " %%x in ("%SEL%") do (
|
|
echo [警告] 输入包含无效内容: %%x
|
|
goto menu
|
|
)
|
|
if "%SEL: =%"=="" goto menu
|
|
for %%t in (!SEL!) do call :select_token "%%t"
|
|
if not defined PICKED (
|
|
echo [警告] 没有选中任何有效的库, 请重新输入。
|
|
goto menu
|
|
)
|
|
goto selection_done
|
|
|
|
:pick_all
|
|
set "PICKED=1"
|
|
for /l %%i in (1,1,%LIB_COUNT%) do set "PICK[%%i]=1"
|
|
|
|
:selection_done
|
|
rem 自动附加 baseAlgorithm (工程之间没有 ProjectReference, 靠链接 .lib 依赖)
|
|
set "HAS_BASE=0"
|
|
set "NEED_BASE=0"
|
|
for /l %%i in (1,1,%LIB_COUNT%) do (
|
|
if defined PICK[%%i] (
|
|
if /i "!LIB[%%i]!"=="baseAlgorithm" (
|
|
set "HAS_BASE=1"
|
|
) else (
|
|
findstr /i /c:"baseAlgorithm.lib" "%ROOT%\!LIBPATH[%%i]!" >nul && set "NEED_BASE=1"
|
|
)
|
|
)
|
|
)
|
|
if "%NEED_BASE%"=="1" if "%HAS_BASE%"=="0" (
|
|
for /l %%i in (1,1,%LIB_COUNT%) do (
|
|
if /i "!LIB[%%i]!"=="baseAlgorithm" (
|
|
set "PICK[%%i]=1"
|
|
echo [提示] 自动附加依赖库 baseAlgorithm
|
|
)
|
|
)
|
|
)
|
|
|
|
rem ---------------------------- Windows 编译 (Rebuild) ----------------------
|
|
if not exist "%LOGDIR%" mkdir "%LOGDIR%"
|
|
|
|
set "SEL_COUNT=0"
|
|
for /l %%i in (1,1,%LIB_COUNT%) do if defined PICK[%%i] set /a SEL_COUNT+=1
|
|
set "CFG_COUNT=0"
|
|
for %%c in (%CONFIGS%) do set /a CFG_COUNT+=1
|
|
set /a JOB_TOTAL=SEL_COUNT*CFG_COUNT
|
|
|
|
echo.
|
|
echo ============================================================
|
|
echo MSBuild Rebuild ^(%PLATFORM%^) 共 !JOB_TOTAL! 个任务
|
|
echo ============================================================
|
|
|
|
rem 先重建 baseAlgorithm, 其它库都链接它
|
|
for %%c in (%CONFIGS%) do (
|
|
for /l %%i in (1,1,%LIB_COUNT%) do (
|
|
if /i "!LIB[%%i]!"=="baseAlgorithm" if defined PICK[%%i] call :rebuild_one "!LIB[%%i]!" "%ROOT%\!LIBPATH[%%i]!" "%%c"
|
|
)
|
|
for /l %%i in (1,1,%LIB_COUNT%) do (
|
|
if /i not "!LIB[%%i]!"=="baseAlgorithm" if defined PICK[%%i] call :rebuild_one "!LIB[%%i]!" "%ROOT%\!LIBPATH[%%i]!" "%%c"
|
|
)
|
|
)
|
|
echo [100%%] 全部任务完成
|
|
|
|
rem ---------------------------- ARM 编译 ------------------------------------
|
|
if "%DO_ARM%"=="1" (
|
|
call :build_arm
|
|
) else (
|
|
echo.
|
|
echo [跳过] ARM 编译 ^(/no-arm^)
|
|
)
|
|
|
|
rem ---------------------------- 汇总 ----------------------------------------
|
|
echo.
|
|
echo ============================================================
|
|
echo 编译结果
|
|
echo ============================================================
|
|
echo Windows 输出 : %ROOT%\build\%PLATFORM%\ (%CONFIGS%)
|
|
if "%DO_ARM%"=="1" echo ARM 输出 : %ROOT%\build\aarch64
|
|
echo 成功任务 : %OK_COUNT%
|
|
if %FAIL_COUNT% GTR 0 (
|
|
echo 失败任务 : %FAIL_COUNT%
|
|
echo -^> %FAILED%
|
|
echo 详细日志 : %LOGDIR%
|
|
set "EXIT_CODE=1"
|
|
) else (
|
|
echo 失败任务 : 0
|
|
set "EXIT_CODE=0"
|
|
)
|
|
goto end
|
|
|
|
:cancel
|
|
echo.
|
|
echo 已取消。
|
|
set "EXIT_CODE=0"
|
|
goto end
|
|
|
|
:help
|
|
echo.
|
|
echo SG_Algorithm 编译脚本 (全部为 Rebuild: 先清理再编译)
|
|
echo.
|
|
echo build.bat 交互选择库, Rebuild Debug + Release, 并编译 ARM
|
|
echo build.bat /all 编译全部库
|
|
echo build.bat /config:debug 只编译 Debug ^(debug / release / both^)
|
|
echo build.bat /no-arm 跳过 ARM 编译
|
|
echo build.bat /arm-config:Debug ARM 配置 ^(默认 Release^)
|
|
echo build.bat /opencv:480 ARM 使用 OpenCV 4.8.0 ^(默认 320^)
|
|
echo build.bat /platform:x86 Windows 平台 ^(默认 x64^)
|
|
echo build.bat /j:8 ARM make 并行任务数 ^(默认 CPU 核心数^)
|
|
echo build.bat /dry-run 只打印命令, 不实际编译
|
|
echo build.bat /no-pause 结束后不暂停
|
|
echo.
|
|
echo 输出:
|
|
echo Windows : build\^<平台^>\^<配置^>\
|
|
echo ARM : build\aarch64 ^(CMake 构建目录 armbuild, 需要 WSL^)
|
|
echo.
|
|
set "EXIT_CODE=0"
|
|
goto end
|
|
|
|
rem ===========================================================================
|
|
rem 子过程
|
|
rem ===========================================================================
|
|
|
|
rem ---- 解析 /config: 参数 ----
|
|
:set_configs
|
|
set "CFG=%~1"
|
|
if /i "%CFG%"=="both" ( set "CONFIGS=Debug Release" & goto :eof )
|
|
if /i "%CFG%"=="all" ( set "CONFIGS=Debug Release" & goto :eof )
|
|
if /i "%CFG%"=="debug" ( set "CONFIGS=Debug" & goto :eof )
|
|
if /i "%CFG%"=="release" ( set "CONFIGS=Release" & goto :eof )
|
|
set "CONFIGS=%CFG:,= %"
|
|
goto :eof
|
|
|
|
rem ---- 解析交互输入中的单个记号 ----
|
|
:select_token
|
|
set "TOK=%~1"
|
|
if not defined TOK goto :eof
|
|
if /i "%TOK%"=="all" ( set "PICKED=1" & for /l %%i in (1,1,%LIB_COUNT%) do set "PICK[%%i]=1" & goto :eof )
|
|
if /i "%TOK%"=="a" ( set "PICKED=1" & for /l %%i in (1,1,%LIB_COUNT%) do set "PICK[%%i]=1" & goto :eof )
|
|
set "SINGLE=%TOK:-=%"
|
|
if "%SINGLE%"=="%TOK%" (
|
|
call :select_range %TOK% %TOK%
|
|
) else (
|
|
for /f "tokens=1,2 delims=-" %%a in ("%TOK%") do call :select_range %%a %%b
|
|
)
|
|
goto :eof
|
|
|
|
rem ---- 选中一个编号区间 ----
|
|
:select_range
|
|
set "FROM=%~1"
|
|
set "TO=%~2"
|
|
if not defined FROM goto :eof
|
|
if not defined TO goto :eof
|
|
if %FROM% LSS 1 goto :bad_range
|
|
if %TO% GTR %LIB_COUNT% goto :bad_range
|
|
if %FROM% GTR %TO% goto :bad_range
|
|
for /l %%i in (%FROM%,1,%TO%) do (
|
|
set "PICK[%%i]=1"
|
|
set "PICKED=1"
|
|
)
|
|
goto :eof
|
|
:bad_range
|
|
echo [警告] 编号超出范围 (1-%LIB_COUNT%): %FROM%-%TO%
|
|
goto :eof
|
|
|
|
rem ---- Rebuild 单个库, 显示完成百分比进度 ----
|
|
:rebuild_one
|
|
set "LIB=%~1"
|
|
set "PROJ=%~2"
|
|
set "CFG=%~3"
|
|
set "LOG=%LOGDIR%\%~1_%~3.log"
|
|
set /a STEP+=1
|
|
set /a DONE=STEP-1
|
|
set /a PCT=DONE*100/JOB_TOTAL
|
|
set "PCTXT= !PCT!"
|
|
if !PCT! GEQ 10 set "PCTXT= !PCT!"
|
|
if !PCT! GEQ 100 set "PCTXT=!PCT!"
|
|
echo [!PCTXT!%%] (!STEP!/!JOB_TOTAL!) Rebuild !LIB! [%CFG% ^| %PLATFORM%]
|
|
if "%DRYRUN%"=="1" (
|
|
echo [dry-run] "%MSBUILD%" "%PROJ%" /t:Rebuild /p:Configuration=%CFG% /p:Platform=%PLATFORM%
|
|
set /a OK_COUNT+=1
|
|
goto :eof
|
|
)
|
|
"%MSBUILD%" "%PROJ%" /t:Rebuild /p:Configuration=%CFG% /p:Platform=%PLATFORM% "/p:SolutionDir=%ROOT%\\" /m /nologo /v:m > "!LOG!" 2>&1
|
|
if errorlevel 1 (
|
|
echo [失败] -^> !LOG!
|
|
findstr /i /c:" error " /c:"error C" /c:"error LNK" /c:"error MSB" "!LOG!"
|
|
set "FAILED=!FAILED! !LIB![%CFG%]"
|
|
set /a FAIL_COUNT+=1
|
|
) else (
|
|
echo [成功]
|
|
set /a OK_COUNT+=1
|
|
)
|
|
goto :eof
|
|
|
|
rem ---- 编译 ARM 库 (WSL + CMake, 目录 armbuild, 先 make clean) ----
|
|
:build_arm
|
|
echo.
|
|
echo ============================================================
|
|
echo ARM (aarch64) Rebuild ^| 构建目录: armbuild
|
|
echo ============================================================
|
|
where wsl.exe >nul 2>nul
|
|
if errorlevel 1 (
|
|
echo [错误] 未找到 wsl.exe, 无法编译 ARM 库。可加 /no-arm 跳过。
|
|
set "FAILED=!FAILED! ARM[wsl]"
|
|
set /a FAIL_COUNT+=1
|
|
goto :eof
|
|
)
|
|
if not exist "%ARMBUILD%" mkdir "%ARMBUILD%"
|
|
set "WSL_ARM="
|
|
for /f "usebackq delims=" %%i in (`wsl wslpath -a -u "%ARMBUILD%"`) do set "WSL_ARM=%%i"
|
|
if not defined WSL_ARM (
|
|
echo [错误] 无法转换为 WSL 路径: %ARMBUILD%
|
|
set "FAILED=!FAILED! ARM[path]"
|
|
set /a FAIL_COUNT+=1
|
|
goto :eof
|
|
)
|
|
|
|
set "NPROC=%NUMBER_OF_PROCESSORS%"
|
|
if not defined NPROC set "NPROC=4"
|
|
set "MAKE_OPTS=-j%NPROC%"
|
|
if defined JOBS set "MAKE_OPTS=-j%JOBS%"
|
|
|
|
if "%DRYRUN%"=="1" (
|
|
echo [dry-run] cd '%WSL_ARM%' ^&^& cmake -DCMAKE_BUILD_TYPE=%ARM_CONFIG% -DOPENCV_VERSION=%OPENCV_VERSION% .. ^&^& make clean ^&^& make %MAKE_OPTS%
|
|
set /a OK_COUNT+=1
|
|
goto :eof
|
|
)
|
|
|
|
wsl -e bash -lc "command -v cmake >/dev/null 2>&1 || { echo '[错误] WSL 中未找到 cmake'; exit 2; }"
|
|
if errorlevel 1 (
|
|
echo [错误] WSL 中未找到 cmake。
|
|
set "FAILED=!FAILED! ARM[cmake]"
|
|
set /a FAIL_COUNT+=1
|
|
goto :eof
|
|
)
|
|
wsl -e bash -lc "command -v aarch64-linux-gnu-g++ >/dev/null 2>&1 || { echo '[错误] WSL 中未找到 aarch64-linux-gnu-g++'; exit 3; }"
|
|
if errorlevel 1 (
|
|
echo [错误] WSL 中未找到 aarch64-linux-gnu-g++ 交叉编译器。
|
|
set "FAILED=!FAILED! ARM[gcc]"
|
|
set /a FAIL_COUNT+=1
|
|
goto :eof
|
|
)
|
|
|
|
wsl -e bash -lc "cd '%WSL_ARM%' && cmake -DCMAKE_BUILD_TYPE=%ARM_CONFIG% -DOPENCV_VERSION=%OPENCV_VERSION% .. && make clean && make %MAKE_OPTS%"
|
|
if errorlevel 1 (
|
|
echo [失败] ARM Rebuild ^(%ARM_CONFIG%^)
|
|
set "FAILED=!FAILED! ARM[%ARM_CONFIG%]"
|
|
set /a FAIL_COUNT+=1
|
|
) else (
|
|
echo [成功] ARM Rebuild ^(%ARM_CONFIG%^) -^> %ROOT%\build\aarch64
|
|
set /a OK_COUNT+=1
|
|
)
|
|
goto :eof
|
|
|
|
rem ===========================================================================
|
|
:end
|
|
if %NOPAUSE%==0 (
|
|
echo.
|
|
pause
|
|
)
|
|
endlocal & exit /b %EXIT_CODE%
|