build_win.bat 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. @setlocal disableDelayedExpansion enableExtensions
  2. @IF "%PS_ECHO_ON%" NEQ "" (echo on) ELSE (echo off)
  3. @GOTO :MAIN
  4. :HELP
  5. @ECHO Performs initial build or rebuild of the app (build) and deps (build/deps).
  6. @ECHO Default options are determined from build directories and system state.
  7. @ECHO.
  8. @ECHO Usage: build_win [-ARCH ^<arch^>] [-CONFIG ^<config^>] [-DESTDIR ^<directory^>]
  9. @ECHO [-STEPS ^<all^|all-dirty^|app^|app-dirty^|deps^|deps-dirty^>]
  10. @ECHO.
  11. @ECHO -a -ARCH Target processor architecture
  12. @ECHO Default: %PS_ARCH_HOST%
  13. @ECHO -c -CONFIG MSVC project config
  14. @ECHO Default: %PS_CONFIG_DEFAULT%
  15. @ECHO -s -STEPS Performs only the specified build steps:
  16. @ECHO all - clean and build deps and app
  17. @ECHO all-dirty - build deps and app without cleaning
  18. @ECHO app - build main project/application
  19. @ECHO app-dirty - does not build main project/application
  20. @ECHO deps - clean and build deps
  21. @ECHO deps-dirty - build deps without cleaning
  22. @ECHO Default: %PS_STEPS_DEFAULT%
  23. @ECHO -d -DESTDIR Deps destination directory (ignored on dirty builds)
  24. @ECHO %PS_DESTDIR_DEFAULT_MSG%
  25. @ECHO.
  26. @ECHO Example usage:
  27. @ECHO First build: build_win -d "c:\src\PrusaSlicer-deps"
  28. @ECHO Deps change: build_win -s all
  29. @ECHO App rebuild: build_win
  30. @ECHO.
  31. GOTO :END
  32. :MAIN
  33. SET START_TIME=%TIME%
  34. SET PS_START_DIR=%CD%
  35. pushd %~dp0
  36. REM Probe build directories and sytem state for reasonable default arguments
  37. SET PS_CONFIG=RelWithDebInfo
  38. SET PS_ARCH=%PROCESSOR_ARCHITECTURE%
  39. CALL :TOLOWER PS_ARCH
  40. SET PS_DEPS_PATH_FILE=%~dp0deps\build\.DEPS_PATH.txt
  41. SET PS_DESTDIR=
  42. IF EXIST %PS_DEPS_PATH_FILE% (
  43. FOR /F "tokens=* USEBACKQ" %%I IN ("%PS_DEPS_PATH_FILE%") DO SET PS_DESTDIR=%%I
  44. IF EXIST build/ALL_BUILD.vcxproj (
  45. SET PS_STEPS=app-dirty
  46. ) ELSE SET PS_STEPS=app
  47. ) ELSE SET PS_STEPS=all
  48. SET PS_DESTDIR_CACHED=%PS_DESTDIR%
  49. REM Set up parameters used by help menu
  50. SET PS_CONFIG_DEFAULT=%PS_CONFIG%
  51. SET PS_ARCH_HOST=%PS_ARCH%
  52. SET PS_STEPS_DEFAULT=%PS_STEPS%
  53. IF "%PS_DESTDIR%" NEQ "" (
  54. SET PS_DESTDIR_DEFAULT_MSG=Default: %PS_DESTDIR%
  55. ) ELSE (
  56. SET PS_DESTDIR_DEFAULT_MSG=Argument required ^(no default available^)
  57. )
  58. REM Parse arguments
  59. SET EXIT_STATUS=1
  60. SET PARSER_STATE=
  61. SET PARSER_FAIL=
  62. FOR %%I in (%*) DO CALL :PARSE_OPTION "ARCH CONFIG DESTDIR STEPS" PARSER_STATE "%%~I"
  63. IF "%PARSER_FAIL%" NEQ "" (
  64. @ECHO ERROR: Invalid switch: %PARSER_FAIL% 1>&2
  65. GOTO :HELP
  66. )ELSE IF "%PARSER_STATE%" NEQ "" (
  67. @ECHO ERROR: Missing parameter for: %PARSER_STATE% 1>&2
  68. GOTO :HELP
  69. )
  70. REM Validate arguments
  71. SET PS_STEPS_SAVED=%PS_STEPS%
  72. CALL :PARSE_OPTION_NAME "all all-dirty deps-dirty deps app-dirty app" PS_STEPS -%PS_STEPS%
  73. IF "%PS_STEPS%" EQU "" (
  74. @ECHO ERROR: Invalid parameter: steps=%PS_STEPS_SAVED% 1>&2
  75. GOTO :HELP
  76. ) ELSE SET PS_STEPS_SAVED=
  77. (echo %PS_STEPS%)| findstr /I /C:"dirty">nul && SET PS_STEPS_DIRTY=1
  78. CALL :TOLOWER PS_STEPS
  79. CALL :TOLOWER PS_ARCH
  80. CALL :CANONICALIZE_PATH PS_DESTDIR "%PS_START_DIR%"
  81. IF "%PS_DESTDIR%" EQU "" (
  82. IF "%PS_STEPS_DIRTY%" EQU "" (
  83. @ECHO ERROR: Parameter required: destdir 1>&2
  84. GOTO :HELP
  85. )
  86. ) ELSE IF "%PS_DESTDIR%" NEQ "%PS_DESTDIR_CACHED%" (
  87. IF "%PS_STEPS_DIRTY%" NEQ "" (
  88. @ECHO WARNING: Parameter ignored: destdir
  89. ) ELSE (echo "all deps")| findstr /I /C:"%PS_STEPS%">nul || (
  90. @ECHO WARNING: Conflict with cached parameter: 1>&2
  91. @ECHO WARNING: -destdir=%PS_DESTDIR% 1>&2
  92. @ECHO WARNING: cached=%PS_DESTDIR_CACHED% 1>&2
  93. )
  94. )
  95. SET PS_DESTDIR_DEFAULT_MSG=
  96. REM Set up MSVC environment
  97. SET EXIT_STATUS=2
  98. @ECHO **********************************************************************
  99. @ECHO ** Build Config: %PS_CONFIG%
  100. @ECHO ** Target Arch: %PS_ARCH%
  101. @ECHO ** Build Steps: %PS_STEPS%
  102. @ECHO ** Deps path: %PS_DESTDIR%
  103. @ECHO ** Using Microsoft Visual Studio installation found at:
  104. SET VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
  105. IF NOT EXIST %VSWHERE% SET VSWHERE="%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe"
  106. FOR /F "tokens=* USEBACKQ" %%I IN (`%VSWHERE% -nologo -property installationPath`) DO SET MSVC_DIR=%%I
  107. @ECHO ** %MSVC_DIR%
  108. CALL "%MSVC_DIR%\Common7\Tools\vsdevcmd.bat" -arch=%PS_ARCH% -host_arch=%PS_ARCH_HOST% -app_platform=Desktop
  109. IF "%ERRORLEVEL%" NEQ "0" GOTO :END
  110. IF "%PS_DRY_RUN_ONLY%" NEQ "" (
  111. @ECHO Script terminated early because PS_DRY_RUN_ONLY is set. 1>&2
  112. GOTO :END
  113. )
  114. IF /I "%PS_STEPS:~0,3%" EQU "app" GOTO :BUILD_APP
  115. REM Build deps
  116. :BUILD_DEPS
  117. SET EXIT_STATUS=3
  118. IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY deps\build
  119. cd deps\build || GOTO :END
  120. IF "%PS_STEPS_DIRTY%" EQU "" cmake.exe .. -DDESTDIR="%PS_DESTDIR%" || GOTO :END
  121. (echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE%"
  122. msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% || GOTO :END
  123. cd ..\..
  124. IF /I "%PS_STEPS:~0,4%" EQU "deps" GOTO :PROLOGUE
  125. REM Build app
  126. :BUILD_APP
  127. SET EXIT_STATUS=4
  128. IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY build
  129. cd build || GOTO :END
  130. IF "%PS_STEPS_DIRTY%" EQU "" cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" || GOTO :END
  131. msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% || GOTO :END
  132. :PROLOGUE
  133. SET EXIT_STATUS=%ERRORLEVEL%
  134. :END
  135. @IF "%PS_ECHO_ON%%PS_DRY_RUN_ONLY%" NEQ "" (
  136. @ECHO Script Parameters:
  137. @SET PS_
  138. )
  139. @ECHO Script started at %START_TIME% and completed at %TIME%.
  140. popd
  141. exit /B %EXIT_STATUS%
  142. GOTO :EOF
  143. REM Functions and stubs start here.
  144. :PARSE_OPTION
  145. @REM Argument parser called for each argument
  146. @REM %1 - Valid option list
  147. @REM %2 - Variable name for parser state; must be unset when parsing finished
  148. @REM %3 - Current argument value
  149. @REM PARSER_FAIL will be set on an error
  150. @REM Note: Must avoid delayed expansion since filenames may contain ! character
  151. setlocal disableDelayedExpansion
  152. IF "%PARSER_FAIL%" NEQ "" GOTO :EOF
  153. CALL SET LAST_ARG=%%%2%%
  154. IF "%LAST_ARG%" EQU "" (
  155. CALL :PARSE_OPTION_NAME %1 %~2 %~3 1
  156. SET ARG_TYPE=NAME
  157. ) ELSE (
  158. SET PS_SET_COMMAND=SET PS_%LAST_ARG%=%~3
  159. SET ARG_TYPE=LAST_ARG
  160. SET %~2=
  161. )
  162. CALL SET LAST_ARG=%%%2%%
  163. IF "%LAST_ARG%%ARG_TYPE%" EQU "NAME" SET PARSER_FAIL=%~3
  164. (
  165. endlocal
  166. SET PARSER_FAIL=%PARSER_FAIL%
  167. SET %~2=%LAST_ARG%
  168. %PS_SET_COMMAND%
  169. )
  170. GOTO :EOF
  171. :PARSE_OPTION_NAME
  172. @REM Parses an option name
  173. @REM %1 - Valid option list
  174. @REM %2 - Out variable name; unset on error
  175. @REM %3 - Current argument value
  176. @REM $4 - Boolean indicating single character switches are valid
  177. @REM Note: Delayed expansion safe because ! character is invalid in option name
  178. setlocal enableDelayedExpansion
  179. IF "%4" NEQ "" FOR %%I IN (%~1) DO @(
  180. SET SHORT_NAME=%%~I
  181. SET SHORT_ARG_!SHORT_NAME:~0,1!=%%~I
  182. )
  183. @SET OPTION_NAME=%~3
  184. @(echo %OPTION_NAME%)| findstr /R /C:"[-/]..*">nul || GOTO :PARSE_OPTION_NAME_FAIL
  185. @SET OPTION_NAME=%OPTION_NAME:~1%
  186. IF "%4" NEQ "" (
  187. IF "%OPTION_NAME%" EQU "%OPTION_NAME:~0,1%" (
  188. IF "!SHORT_ARG_%OPTION_NAME:~0,1%!" NEQ "" SET OPTION_NAME=!SHORT_ARG_%OPTION_NAME:~0,1%!
  189. )
  190. )
  191. @(echo %OPTION_NAME%)| findstr /R /C:".[ ][ ]*.">nul && GOTO :PARSE_OPTION_NAME_FAIL
  192. @(echo %~1 )| findstr /I /C:" %OPTION_NAME% ">nul || GOTO :PARSE_OPTION_NAME_FAIL
  193. endlocal & SET %~2=%OPTION_NAME%
  194. GOTO :EOF
  195. :PARSE_OPTION_NAME_FAIL
  196. endlocal & SET %~2=
  197. GOTO :EOF
  198. :MAKE_OR_CLEAN_DIRECTORY
  199. @REM Create directory if it doesn't exist or clean it if it does
  200. @REM %1 - Directory path to clean or create
  201. setlocal disableDelayedExpansion
  202. IF NOT EXIST "%~1" (
  203. ECHO Creating %~1
  204. mkdir "%~1" && GOTO :EOF
  205. )
  206. ECHO Cleaning %~1 ...
  207. for /F "usebackq delims=" %%I in (`dir /a /b "%~1"`) do (
  208. (rmdir /s /q "%~1\%%I" 2>nul ) || del /q /f "%~1\%%I")
  209. GOTO :EOF
  210. :TOLOWER
  211. @REM Converts supplied environment variable to lowercase
  212. @REM %1 - Input/output variable name
  213. @REM Note: This is slow on very long strings, but is used only on very short ones
  214. setlocal disableDelayedExpansion
  215. @FOR %%b IN (a b c d e f g h i j k l m n o p q r s t u v w x y z) DO @CALL set %~1=%%%1:%%b=%%b%%
  216. @CALL SET OUTPUT=%%%~1%%
  217. endlocal & SET %~1=%OUTPUT%
  218. GOTO :EOF
  219. :CANONICALIZE_PATH
  220. @REM Canonicalizes the path in the supplied variable
  221. @REM %1 - Input/output variable containing path to canonicalize
  222. @REM %2 - Optional base directory
  223. setlocal
  224. CALL :CANONICALIZE_PATH_INNER %1 %%%~1%% %2
  225. endlocal & SET %~1=%OUTPUT%
  226. GOTO :EOF
  227. :CANONICALIZE_PATH_INNER
  228. if "%~3" NEQ "" (pushd %~3 || GOTO :EOF)
  229. SET OUTPUT=%~f2
  230. if "%~3" NEQ "" popd %~3
  231. GOTO :EOF