1:: Make sure the extensions are enabled 2@verify other 2>nul 3@setlocal EnableDelayedExpansion 4@if errorlevel 1 ( 5 call :print_usage "Failed to enable extensions" 6 exit /b 1 7) 8 9::Change the code page to unicode 10@chcp 65001 1>nul 2>nul 11@if errorlevel 1 ( 12 call :print_usage "Failed to change the code page to unicode" 13 exit /b 1 14) 15 16:: Set up some global variables 17@set project=civetweb 18@set "script_name=%~nx0" 19@set "script_folder=%~dp0" 20@set "script_folder=%script_folder:~0,-1%" 21@set "output_path=%script_folder%\output" 22@set "build_path=%output_path%\build" 23@set "install_path=%output_path%\install" 24@set build_shared=OFF 25@set build_type=Release 26@set dependency_path=%TEMP%\%project%-build-dependencies 27 28:: Check the command line parameters 29@set logging_level=1 30@set "options=%* " 31@if not "!options!"=="!options:/? =!" set usage="Convenience script to build %project% with CMake" 32@for %%a in (%options%) do @( 33 @set arg=%%~a 34 @set arg=!arg: =! 35 @set one=!arg:~0,1! 36 @set two=!arg:~0,2! 37 @if /i [!arg!] == [/q] set quiet=true 38 @if /i [!two!] == [/v] call :verbosity "!arg!" 39 @if /i [!arg!] == [/s] set build_shared=ON 40 @if /i [!arg!] == [/d] set build_type=Debug 41 @if /i not [!one!] == [/] ( 42 if not defined generator ( 43 set generator=!arg! 44 ) else ( 45 set usage="Too many generators: !method! !arg!" ^ 46 "There should only be one generator parameter" 47 ) 48 ) 49) 50@if defined quiet ( 51 set logging_level=0 52) 53@if not defined generator ( 54 set generator=MSVC 55) 56@if /i not [%generator%] == [MinGW] ( 57 if /i not [%generator%] == [MSVC] ( 58 call :print_usage "Invalid argument: %generator%" 59 exit /b 1 60 ) 61) 62 63:: Set up the logging 64@set log_folder=%output_path%\logs 65@call :iso8601 timestamp 66@set log_path=%log_folder%\%timestamp%.log 67@set log_keep=10 68 69:: Only keep a certain amount of logs 70@set /a "log_keep=log_keep-1" 71@if not exist %log_folder% @mkdir %log_folder% 72@for /f "skip=%log_keep%" %%f in ('dir /b /o-D /tc %log_folder%') do @( 73 call :log 4 "Removing old log file %log_folder%\%%f" 74 del %log_folder%\%%f 75) 76 77:: Set up some more global variables 78@call :architecture arch 79@call :windows_version win_ver win_ver_major win_ver_minor win_ver_rev 80@call :script_source script_source 81@if [%script_source%] == [explorer] ( 82 set /a "logging_level=logging_level+1" 83) 84 85:: Print the usage or start the script 86@set exit_code=0 87@if defined usage ( 88 call :print_usage %usage% 89) else ( 90 call :main 91 @if errorlevel 1 ( 92 @call :log 0 "Failed to build the %project% project" 93 @set exit_code=1 94 ) 95) 96 97:: Tell the user where the built files are 98@call :log 5 99@call :log 0 "The built files are available in %install_path%" 100 101:: Stop the script if the user double clicked 102@if [%script_source%] == [explorer] ( 103 pause 104) 105 106@exit /b %exit_code% 107@endlocal 108@goto :eof 109 110:: -------------------------- Functions start here ---------------------------- 111 112:main - Main function that performs the build 113@setlocal 114@call :log 6 115@call :log 2 "Welcome to the %project% build script" 116@call :log 6 "------------------------------------" 117@call :log 6 118@call :log 2 "This script builds the project using CMake" 119@call :log 6 120@call :log 2 "Generating %generator%..." 121@call :log 6 122@set methods=dependencies ^ 123 generate ^ 124 build ^ 125 install 126@for %%m in (%methods%) do @( 127 call :log 3 "Excuting the '%%m' method" 128 call :log 8 129 call :%%~m 130 if errorlevel 1 ( 131 call :log 0 "Failed to complete the '%%~m' dependency routine" 132 call :log 0 "View the log at %log_path%" 133 exit /b 1 134 ) 135) 136@call :log 6 "------------------------------------" 137@call :log 2 "Build complete" 138@call :log 6 139@endlocal 140@goto :eof 141 142:print_usage - Prints the usage of the script 143:: %* - message to print, each argument on it's own line 144@setlocal 145@for %%a in (%*) do @echo.%%~a 146@echo. 147@echo.build [/?][/v[v...]^|/q][MinGW^|MSVC] 148@echo. 149@echo. [MinGW^|(MSVC)] 150@echo. Builds the library with one of the compilers 151@echo. /s Builds shared libraries 152@echo. /d Builds a debug variant of the project 153@echo. /v Sets the output to be more verbose 154@echo. /v[v...] Extra verbosity, /vv, /vvv, etc 155@echo. /q Quiets the output 156@echo. /? Shows this usage message 157@echo. 158@endlocal 159@goto :eof 160 161:dependencies - Installs any prerequisites for the build 162@setlocal EnableDelayedExpansion 163@if errorlevel 1 ( 164 call :log 0 "Failed to enable extensions" 165 exit /b 1 166) 167@call :log 5 168@call :log 0 "Installing dependencies for %generator%" 169@if /i [%generator%] == [MinGW] ( 170 call :mingw compiler_path 171 @if errorlevel 1 ( 172 @call :log 5 173 @call :log 0 "Failed to find MinGW" 174 @exit /b 1 175 ) 176 set "PATH=!compiler_path!;%PATH%" 177 @call :find_in_path gcc_executable gcc.exe 178 @if errorlevel 1 ( 179 @call :log 5 180 @call :log 0 "Failed to find gcc.exe" 181 @exit /b 1 182 ) 183) 184@if [%reboot_required%] equ [1] call :reboot 185@endlocal & set "PATH=%PATH%" 186@goto :eof 187 188:generate - Uses CMake to generate the build files 189@setlocal EnableDelayedExpansion 190@if errorlevel 1 ( 191 call :log 0 "Failed to enable extensions" 192 exit /b 1 193) 194@call :log 5 195@call :log 0 "Generating CMake files for %generator%" 196@call :cmake cmake_executable 197@if errorlevel 1 ( 198 @call :log 5 199 @call :log 0 "Need CMake to create the build files" 200 @exit /b 1 201) 202@if /i [%generator%] == [MinGW] @( 203 @set "generator_var=-G "MinGW Makefiles^"" 204) 205@if /i [%generator%] == [MSVC] @( 206 rem We could figure out the correct MSVS generator here 207) 208@call :iso8601 iso8601 209@set output=%temp%\cmake-%iso8601%.log 210@if not exist %build_path% mkdir %build_path% 211@cd %build_path% 212@"%cmake_executable%" ^ 213 !generator_var! ^ 214 -DCMAKE_BUILD_TYPE=!build_type! ^ 215 -DBUILD_SHARED_LIBS=!build_shared! ^ 216 "%script_folder%" > "%output%" 217@if errorlevel 1 ( 218 @call :log 5 219 @call :log 0 "Failed to generate build files with CMake" 220 @call :log_append "%output%" 221 @cd %script_folder% 222 @exit /b 1 223) 224@cd %script_folder% 225@endlocal 226@goto :eof 227 228:build - Builds the library 229@setlocal EnableDelayedExpansion 230@if errorlevel 1 ( 231 call :log 0 "Failed to enable extensions" 232 exit /b 1 233) 234@call :log 5 235@call :log 0 "Building %project% with %generator%" 236@if /i [%generator%] == [MinGW] @( 237 @call :find_in_path mingw32_make_executable mingw32-make.exe 238 @if errorlevel 1 ( 239 @call :log 5 240 @call :log 0 "Failed to find mingw32-make" 241 @exit /b 1 242 ) 243 @set "build_command=^"!mingw32_make_executable!^" all test" 244) 245@if /i [%generator%] == [MSVC] @( 246 @call :msbuild msbuild_executable 247 @if errorlevel 1 ( 248 @call :log 5 249 @call :log 0 "Failed to find MSBuild" 250 @exit /b 1 251 ) 252 @set "build_command=^"!msbuild_executable!^" /m:4 /p:Configuration=%build_type% %project%.sln" 253) 254@if not defined build_command ( 255 @call :log 5 256 @call :log 0 "No build command for %generator%" 257 @exit /b 1 258) 259@cd %build_path% 260@call :iso8601 iso8601 261@set output=%temp%\build-%iso8601%.log 262@call :log 7 263@call :log 2 "Build command: %build_command:"=%" 264@%build_command% > "%output%" 265@if errorlevel 1 ( 266 @call :log_append "%output%" 267 @call :log 5 268 @call :log 0 "Failed to complete the build" 269 @exit /b 1 270) 271@call :log_append "%output%" 272@cd %script_folder% 273@endlocal 274@goto :eof 275 276:install - Installs the built files 277@setlocal 278@call :log 5 279@call :log 0 "Installing built files" 280@call :cmake cmake_executable 281@if errorlevel 1 ( 282 @call :log 5 283 @call :log 0 "Need CMake to install the built files" 284 @exit /b 1 285) 286@call :iso8601 iso8601 287@set output=%temp%\install-%iso8601%.log 288@"%cmake_executable%" ^ 289 "-DCMAKE_INSTALL_PREFIX=%install_path%" ^ 290 -P "%build_path%/cmake_install.cmake" ^ 291 > "%output%" 292@if errorlevel 1 ( 293 @call :log_append "%output%" 294 @call :log 5 295 @call :log 0 "Failed to install the files" 296 @exit /b 1 297) 298@call :log_append "%output%" 299@endlocal 300@goto :eof 301 302:script_source - Determines if the script was ran from the cli or explorer 303:: %1 - The return variable [cli|explorer] 304@verify other 2>nul 305@setlocal EnableDelayedExpansion 306@if errorlevel 1 ( 307 call :log 0 "Failed to enable extensions" 308 exit /b 1 309) 310@call :log 3 "Attempting to detect the script source" 311@echo "The invocation command was: '%cmdcmdline%'" >> %log_path% 312@for /f "tokens=1-3,*" %%a in ("%cmdcmdline%") do @( 313 set cmd=%%~a 314 set arg1=%%~b 315 set arg2=%%~c 316 set rest=%%~d 317) 318@set quote=" 319@if "!arg2:~0,1!" equ "!quote!" ( 320 if "!arg2:~-1!" neq "!quote!" ( 321 set "arg2=!arg2:~1!" 322 ) 323) 324@call :log 4 "cmd = %cmd%" 325@call :log 4 "arg1 = %arg1%" 326@call :log 4 "arg2 = %arg2%" 327@call :log 4 "rest = %rest%" 328@call :log 4 "src = %~f0" 329@if /i "%arg2%" == "call" ( 330 set script_source=cli 331) else ( 332 @if /i "%arg1%" == "/c" ( 333 set script_source=explorer 334 ) else ( 335 set script_source=cli 336 ) 337) 338@call :log 3 "The script was invoked from %script_source%" 339@endlocal & set "%~1=%script_source%" 340@goto :eof 341 342:architecture - Finds the system architecture 343:: %1 - The return variable [x86|x86_64] 344@setlocal 345@call :log 3 "Determining the processor architecture" 346@set "key=HKLM\System\CurrentControlSet\Control\Session Manager\Environment" 347@set "var=PROCESSOR_ARCHITECTURE" 348@for /f "skip=2 tokens=2,*" %%a in ('reg query "%key%" /v "%var%"') do @set "arch=%%b" 349@if "%arch%" == "AMD64" set arch=x86_64 350@call :log 4 "arch = %arch%" 351@endlocal & set "%~1=%arch%" 352@goto :eof 353 354:md5 - Gets the MD5 checksum for a file 355:: %1 - The hash 356:: %2 - The file path 357@setlocal 358@set var=%~1 359@set file_path=%~2 360@if [%var%] == [] exit /b 1 361@if "%file_path%" == "" exit /b 1 362@if not exist "%file_path%" exit /b 1 363@for /f "skip=3 tokens=1,*" %%a in ('powershell Get-FileHash -Algorithm MD5 "'%file_path%'"') do @set hash=%%b 364@if not defined hash ( 365 call :log 6 366 call :log 0 "Failed to get MD5 hash for %file_path%" 367 exit /b 1 368) 369@endlocal & set "%var%=%hash: =%" 370@goto :eof 371 372:windows_version - Checks the windows version 373:: %1 - The windows version 374:: %2 - The major version number return variable 375:: %3 - The minor version number return variable 376:: %4 - The revision version number return variable 377@setlocal 378@call :log 3 "Retrieving the Windows version" 379@for /f "tokens=2 delims=[]" %%x in ('ver') do @set win_ver=%%x 380@set win_ver=%win_ver:Version =% 381@set win_ver_major=%win_ver:~0,1% 382@set win_ver_minor=%win_ver:~2,1% 383@set win_ver_rev=%win_ver:~4% 384@call :log 4 "win_ver = %win_ver%" 385@endlocal & set "%~1=%win_ver%" ^ 386 & set "%~2=%win_ver_major%" ^ 387 & set "%~3=%win_ver_minor%" ^ 388 & set "%~4=%win_ver_rev%" 389@goto :eof 390 391:find_in_path - Finds a program of file in the PATH 392@setlocal 393@set var=%~1 394@set file=%~2 395@if [%var%] == [] exit /b 1 396@if [%file%] == [] exit /b 1 397@call :log 3 "Searching PATH for %file%" 398@for %%x in ("%file%") do @set "file_path=%%~f$PATH:x" 399@if not defined file_path exit /b 1 400@endlocal & set "%var%=%file_path%" 401@goto :eof 402 403:administrator_check - Checks for administrator priviledges 404@setlocal 405@call :log 2 "Checking for administrator priviledges" 406@set "key=HKLM\Software\VCA\Tool Chain\Admin Check" 407@reg add "%key%" /v Elevated /t REG_DWORD /d 1 /f > nul 2>&1 408@if errorlevel 1 exit /b 1 409@reg delete "%key%" /va /f > nul 2>&1 410@endlocal 411@goto :eof 412 413:log_append - Appends another file into the current logging file 414:: %1 - the file_path to the file to concatenate 415@setlocal 416@set "file_path=%~1" 417@if [%file_path%] == [] exit /b 1 418@call :log 3 "Appending to log: %file_path%" 419@call :iso8601 iso8601 420@set "temp_log=%temp%\append-%iso8601%.log" 421@call :log 4 "Using temp file %temp_log%" 422@type "%log_path%" "%file_path%" > "%temp_log%" 2>nul 423@move /y "%temp_log%" "%log_path%" 1>nul 424@del "%file_path%" 2>nul 425@del "%temp_log%" 2>nul 426@endlocal 427@goto :eof 428 429:iso8601 - Returns the current time in ISO8601 format 430:: %1 - the return variable 431:: %2 - format [extended|basic*] 432:: iso8601 - contains the resulting timestamp 433@setlocal 434@wmic Alias /? >NUL 2>&1 || @exit /b 1 435@set "var=%~1" 436@if "%var%" == "" @exit /b 1 437@set "format=%~2" 438@if "%format%" == "" set format=basic 439@for /F "skip=1 tokens=1-6" %%g IN ('wmic Path Win32_UTCTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') do @( 440 @if "%%~l"=="" goto :iso8601_done 441 @set "yyyy=%%l" 442 @set "mm=00%%j" 443 @set "dd=00%%g" 444 @set "hour=00%%h" 445 @set "minute=00%%i" 446 @set "seconds=00%%k" 447) 448:iso8601_done 449@set mm=%mm:~-2% 450@set dd=%dd:~-2% 451@set hour=%hour:~-2% 452@set minute=%minute:~-2% 453@set seconds=%seconds:~-2% 454@if /i [%format%] == [extended] ( 455 set iso8601=%yyyy%-%mm%-%dd%T%hour%:%minute%:%seconds%Z 456) else ( 457 if /i [%format%] == [basic] ( 458 set iso8601=%yyyy%%mm%%dd%T%hour%%minute%%seconds%Z 459 ) else ( 460 @exit /b 1 461 ) 462) 463@set iso8601=%iso8601: =0% 464@endlocal & set %var%=%iso8601% 465@goto :eof 466 467:verbosity - Processes the verbosity parameter '/v[v...] 468:: %1 - verbosity given on the command line 469:: logging_level - set to the number of v's 470@setlocal 471@set logging_level=0 472@set verbosity=%~1 473:verbosity_loop 474@set verbosity=%verbosity:~1% 475@if not [%verbosity%] == [] @( 476 set /a "logging_level=logging_level+1" 477 goto verbosity_loop 478) 479@endlocal & set logging_level=%logging_level% 480@goto :eof 481 482:log - Logs a message, depending on verbosity 483:: %1 - level 484:: [0-4] for CLI logging 485:: [5-9] for GUI logging 486:: %2 - message to print 487@setlocal 488@set "level=%~1" 489@set "msg=%~2" 490@if "%log_folder%" == "" ( 491 echo Logging was used to early in the script, log_folder isn't set yet 492 goto :eof 493) 494@if "%log_path%" == "" ( 495 echo Logging was used to early in the script, log_path isn't set yet 496 goto :eof 497) 498@if not exist "%log_folder%" mkdir "%log_folder%" 499@if not exist "%log_path%" echo. 1>nul 2>"%log_path%" 500@echo.%msg% >> "%log_path%" 501@if %level% geq 5 ( 502 @if [%script_source%] == [explorer] ( 503 set /a "level=level-5" 504 ) else ( 505 @goto :eof 506 ) 507) 508@if "%logging_level%" == "" ( 509 echo Logging was used to early in the script, logging_level isn't set yet 510 goto :eof 511) 512@if %logging_level% geq %level% echo.%msg% 1>&2 513@endlocal 514@goto :eof 515 516 517:start_browser - Opens the default browser to a URL 518:: %1 - the url to open 519@setlocal 520@set url=%~1 521@call :log 4 "Opening default browser: %url%" 522@start %url% 523@endlocal 524@goto :eof 525 526:find_cmake - Finds cmake on the command line or in the registry 527:: %1 - the cmake file path 528@setlocal 529@set var=%~1 530@if [%var%] == [] exit /b 1 531@call :log 6 532@call :log 6 "Finding CMake" 533@call :log 6 "--------------" 534@call :find_in_path cmake_executable cmake.exe 535@if not errorlevel 1 goto found_cmake 536@for /l %%i in (5,-1,0) do @( 537@for /l %%j in (9,-1,0) do @( 538@for /l %%k in (9,-1,0) do @( 539@for %%l in (HKCU HKLM) do @( 540@for %%m in (SOFTWARE SOFTWARE\Wow6432Node) do @( 541 @reg query "%%l\%%m\Kitware\CMake %%i.%%j.%%k" /ve > nul 2>nul 542 @if not errorlevel 1 ( 543 @for /f "skip=2 tokens=2,*" %%a in ('reg query "%%l\%%m\Kitware\CMake %%i.%%j.%%k" /ve') do @( 544 @if exist "%%b\bin\cmake.exe" ( 545 @set "cmake_executable=%%b\bin\cmake.exe" 546 goto found_cmake 547 ) 548 ) 549 ) 550))))) 551@call :log 5 552@call :log 0 "Failed to find cmake" 553@exit /b 1 554:found_cmake 555@endlocal & set "%var%=%cmake_executable%" 556@goto :eof 557 558:cmake - Finds cmake and installs it if necessary 559:: %1 - the cmake file path 560@setlocal 561@set var=%~1 562@if [%var%] == [] exit /b 1 563@call :log 6 564@call :log 6 "Checking for CMake" 565@call :log 6 "------------------" 566@call :find_cmake cmake_executable cmake.exe 567@if not errorlevel 1 goto got_cmake 568@set checksum=C00267A3D3D9619A7A2E8FA4F46D7698 569@set version=3.2.2 570@call :install_nsis cmake http://www.cmake.org/files/v%version:~0,3%/cmake-%version%-win32-x86.exe %checksum% 571@if errorlevel 1 ( 572 call :log 5 573 call :log 0 "Failed to install cmake" 574 @exit /b 1 575) 576@call :find_cmake cmake_executable cmake.exe 577@if not errorlevel 1 goto got_cmake 578@call :log 5 579@call :log 0 "Failed to check for cmake" 580@exit /b 1 581:got_cmake 582@endlocal & set "%var%=%cmake_executable%" 583@goto :eof 584 585:mingw - Finds MinGW, installing it if needed 586:: %1 - the compiler path that should be added to PATH 587@setlocal EnableDelayedExpansion 588@if errorlevel 1 ( 589 @call :log 5 590 @call :log 0 "Failed to enable extensions" 591 @exit /b 1 592) 593@set var=%~1 594@if [%var%] == [] exit /b 1 595@call :log 6 596@call :log 6 "Checking for MinGW" 597@call :log 6 "------------------" 598@call :find_in_path gcc_executable gcc.exe 599@if not errorlevel 1 ( 600 @for %%a in ("%gcc_executable%") do @set "compiler_path=%%~dpa" 601 goto got_mingw 602) 603@call :log 7 604@call :log 2 "Downloading MinGW" 605@if %logging_level% leq 1 set "logging=/q" 606@if %logging_level% gtr 1 set "logging=/v" 607@set output_path= 608@for /f %%a in ('call 609 "%script_folder%\mingw.cmd" 610 %logging% 611 /arch "%arch%" 612 "%dependency_path%"' 613) do @set "compiler_path=%%a\" 614@if not defined compiler_path ( 615 @call :log_append "%output%" 616 @call :log 5 617 @call :log 0 "Failed to download MinGW" 618 @exit /b 1 619) 620:got_mingw 621@call :log 5 622@call :log 0 "Found MinGW: %compiler_path%gcc.exe" 623@endlocal & set "%var%=%compiler_path%" 624@goto :eof 625 626:msbuild - Finds MSBuild 627:: %1 - the path to MSBuild executable 628@setlocal 629@set var=%~1 630@if [%var%] == [] exit /b 1 631@call :find_in_path msbuild_executable msbuild.exe 632@if not errorlevel 1 goto got_msbuild 633@for /l %%i in (20,-1,4) do @( 634@for /l %%j in (9,-1,0) do @( 635@for %%k in (HKCU HKLM) do @( 636@for %%l in (SOFTWARE SOFTWARE\Wow6432Node) do @( 637 @reg query "%%k\%%l\Microsoft\MSBuild\%%i.%%j" /v MSBuildOverrideTasksPath > nul 2>nul 638 @if not errorlevel 1 ( 639 @for /f "skip=2 tokens=2,*" %%a in ('reg query "%%k\%%l\Microsoft\MSBuild\%%i.%%j" /v MSBuildOverrideTasksPath') do @( 640 @if exist "%%bmsbuild.exe" ( 641 @set "msbuild_executable=%%bmsbuild.exe" 642 goto got_msbuild 643 ) 644 ) 645 ) 646)))) 647@call :log 5 648@call :log 0 "Failed to check for MSBuild" 649@exit /b 1 650:got_msbuild 651@endlocal & set "%var%=%msbuild_executable%" 652@goto :eof 653 654:download - Downloads a file from the internet 655:: %1 - the url of the file to download 656:: %2 - the file to download to 657:: %3 - the MD5 checksum of the file (optional) 658@setlocal EnableDelayedExpansion 659@if errorlevel 1 ( 660 call :print_usage "Failed to enable extensions" 661 exit /b 1 662) 663@set url=%~1 664@set file_path=%~2 665@set checksum=%~3 666@for %%a in (%file_path%) do @set dir_path=%%~dpa 667@for %%a in (%file_path%) do @set file_name=%%~nxa 668@if [%url%] == [] exit /b 1 669@if [%file_path%] == [] exit /b 1 670@if [%dir_path%] == [] exit /b 1 671@if [%file_name%] == [] exit /b 1 672@if not exist "%dir_path%" mkdir "%dir_path%" 673@call :log 1 "Downloading %url%" 674@call :iso8601 iso8601 675@set temp_path=%temp%\download-%iso8601%-%file_name% 676@call :log 3 "Using temp file %temp_path%" 677@powershell Invoke-WebRequest "%url%" -OutFile %temp_path% 678@if errorlevel 1 ( 679 call :log 0 "Failed to download %url%" 680 exit /b 1 681) 682@if [%checksum%] neq [] ( 683 @call :log 4 "Checking %checksum% against %temp_path%" 684 @call :md5 hash "%temp_path%" 685 if "!hash!" neq "%checksum%" ( 686 call :log 0 "Failed to match checksum: %temp_path%" 687 call :log 0 "Hash : !hash!" 688 call :log 0 "Checksum: %checksum%" 689 exit /b 1 690 ) else ( 691 call :log 3 "Checksum matched: %temp_path%" 692 call :log 3 "Hash : !hash!" 693 call :log 3 "Checksum: %checksum%" 694 ) 695) 696@call :log 4 "Renaming %temp_path% to %file_path%" 697@move /y "%temp_path%" "%file_path%" 1>nul 698@endlocal 699@goto :eof 700 701:install_msi - Installs a dependency from an Microsoft Installer package (.msi) 702:: %1 - [string] name of the project to install 703:: %2 - The location of the .msi, a url must start with 'http://' or file_path 704:: %3 - The checksum of the msi (optional) 705@setlocal 706@set name=%~1 707@set file_path=%~2 708@set checksum=%~3 709@set msi=%~nx2 710@set msi_path=%dependency_path%\%msi% 711@if [%name%] == [] exit /b 1 712@if [%file_path%] == [] exit /b 1 713@if [%msi%] == [] exit /b 1 714@if [%msi_path%] == [] exit /b 1 715@for %%x in (msiexec.exe) do @set "msiexec_path=%%~f$PATH:x" 716@if "msiexec_path" == "" ( 717 call :log 0 "Failed to find the Microsoft package installer (msiexec.exe)" 718 call :log 6 719 call :log 0 "Please install it from the Microsoft Download center" 720 call :log 6 721 choice /C YN /T 60 /D N /M "Would you like to go there now?" 722 if !errorlevel! equ 1 call :start_browser ^ 723 "http://search.microsoft.com/DownloadResults.aspx?q=Windows+Installer" 724 exit /b 1 725) 726@call :log 6 727@call :log 1 "Installing the '%name%' dependency" 728@call :log 6 "-------------------------------------" 729@call :administrator_check 730@if errorlevel 1 ( 731 call :log 0 "You must run %~nx0 in elevated mode to install '%name%'" 732 call :log 5 "Right-Click and select 'Run as Administrator' 733 call :log 0 "Install the dependency manually by running %file_path%" 734 @exit /b 740 735) 736@if [%file_path:~0,4%] == [http] ( 737 if not exist "%msi_path%" ( 738 call :download "%file_path%" "%msi_path%" %checksum% 739 if errorlevel 1 ( 740 call :log 0 "Failed to download the %name% dependency" 741 exit /b 1 742 ) 743 ) 744) else ( 745 call :log 2 "Copying MSI %file_path% to %msi_path%" 746 call :log 7 747 if not exist "%msi_path%" ( 748 xcopy /q /y /z "%file_path%" "%msi_path%" 1>nul 749 if errorlevel 1 ( 750 call :log 0 "Failed to copy the Microsoft Installer" 751 exit /b 1 752 ) 753 ) 754) 755@call :log 1 "Running the %msi%" 756@call :log 6 757@set msi_log=%temp%\msiexec-%timestamp%.log 758@call :log 3 "Logging to: %msi_log%" 759@msiexec /i "%msi_path%" /passive /log "%msi_log%" ALLUSERS=1 760@set msi_errorlevel=%errorlevel% 761@call :log_append "%msi_log%" 762@if %msi_errorlevel% equ 0 goto install_msi_success 763@if %msi_errorlevel% equ 3010 goto install_msi_success_reboot 764@if %msi_errorlevel% equ 1641 goto install_msi_success_reboot 765@if %msi_errorlevel% equ 3015 goto install_msi_in_progress_reboot 766@if %msi_errorlevel% equ 1615 goto install_msi_in_progress_reboot 767@call :log 0 "Microsoft Installer failed: %msi_errorlevel%" 768@call :log 0 "Install the dependency manually by running %msi_path%" 769@exit /b 1 770:install_msi_in_progress_reboot 771@call :log 0 "The installation requires a reboot to continue" 772@call :log 5 773@call :reboot 774@exit /b 1 775:install_msi_success_reboot 776@call :log 3 "The installation requires a reboot to be fully functional" 777@set reboot_required=1 778:install_msi_success 779@call :log 2 "Successfully installed %name%" 780@call :log 7 781@endlocal & set reboot_required=%reboot_required% 782@goto :eof 783 784:install_nsis - Installs a dependency from an Nullsoft Installer package (.exe) 785:: %1 - [string] name of the project to install 786:: %2 - The location of the .exe, a url must start with 'http://' or file_path 787:: %3 - The checksum of the exe (optional) 788@setlocal 789@set name=%~1 790@set file_path=%~2 791@set checksum=%~3 792@set exe=%~nx2 793@set exe_path=%dependency_path%\%exe% 794@if [%name%] == [] exit /b 1 795@if [%file_path%] == [] exit /b 1 796@if [%exe%] == [] exit /b 1 797@if [%exe_path%] == [] exit /b 1 798@call :log 6 799@call :log 1 "Installing the '%name%' dependency" 800@call :log 6 "-------------------------------------" 801@call :administrator_check 802@if errorlevel 1 ( 803 call :log 0 "You must run %~nx0 in elevated mode to install '%name%'" 804 call :log 5 "Right-Click and select 'Run as Administrator' 805 call :log 0 "Install the dependency manually by running %file_path%" 806 @exit /b 740 807) 808@if [%file_path:~0,4%] == [http] ( 809 if not exist "%exe_path%" ( 810 call :download "%file_path%" "%exe_path%" %checksum% 811 if errorlevel 1 ( 812 call :log 0 "Failed to download the %name% dependency" 813 exit /b 1 814 ) 815 ) 816) else ( 817 call :log 2 "Copying installer %file_path% to %exe_path%" 818 call :log 7 819 if not exist "%exe_path%" ( 820 xcopy /q /y /z "%file_path%" "%exe_path%" 1>nul 821 if errorlevel 1 ( 822 call :log 0 "Failed to copy the Nullsoft Installer" 823 exit /b 1 824 ) 825 ) 826) 827@call :log 1 "Running the %exe%" 828@call :log 6 829@"%exe_path%" /S 830@set nsis_errorlevel=%errorlevel% 831@if %nsis_errorlevel% equ 0 goto install_nsis_success 832@if %nsis_errorlevel% equ 3010 goto install_nsis_success_reboot 833@if %nsis_errorlevel% equ 1641 goto install_nsis_success_reboot 834@if %nsis_errorlevel% equ 3015 goto install_nsis_in_progress_reboot 835@if %nsis_errorlevel% equ 1615 goto install_nsis_in_progress_reboot 836@call :log 0 "Nullsoft Installer failed: %nsis_errorlevel%" 837@call :log 0 "Install the dependency manually by running %exe_path%" 838@exit /b 1 839:install_nsis_in_progress_reboot 840@call :log 0 "The installation requires a reboot to continue" 841@call :log 5 842@call :reboot 843@exit /b 1 844:install_nsis_success_reboot 845@call :log 3 "The installation requires a reboot to be fully functional" 846@set reboot_required=1 847:install_nsis_success 848@call :log 2 "Successfully installed %name%" 849@call :log 7 850@endlocal & set reboot_required=%reboot_required% 851@goto :eof 852 853:reboot - Asks the user if they would like to reboot then stops the script 854@setlocal 855@call :log 6 "-------------------------------------------" 856@choice /C YN /T 60 /D N /M "The %method% requires a reboot, reboot now?" 857@set ret=%errorlevel% 858@call :log 6 859@if %ret% equ 1 ( 860 @shutdown /r 861) else ( 862 @call :log 0 "You will need to reboot to complete the %method%" 863 @call :log 5 864) 865@endlocal 866@goto :eof 867