Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a simple Windows command-line build script #6674

Merged
merged 1 commit into from
Jul 8, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 190 additions & 0 deletions build_win.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
@setlocal disableDelayedExpansion enableExtensions
@echo off
GOTO :MAIN
:HELP
@ECHO Performs initial build or rebuild of the app (build) and deps (build/deps).
@ECHO Default options are determined from build directories and system state.
@ECHO.
@ECHO Usage: build_win [-ARCH ^<arch^>] [-CONFIG ^<config^>] [-DESTDIR ^<directory^>]
@ECHO [-STEPS ^<all^|all-dirty^|app^|app-dirty^|deps^|deps-dirty^>]
@ECHO.
@ECHO -a -ARCH Target processor architecture
@ECHO Default: %PS_ARCH_HOST%
@ECHO -c -CONFIG MSVC project config
@ECHO Default: %PS_CONFIG_DEFAULT%
@ECHO -s -STEPS Performs only the specified build steps:
@ECHO all - clean and build deps and app
@ECHO all-dirty - build deps and app without cleaning
@ECHO app - build main project/application
@ECHO app-dirty - does not build main project/application
@ECHO deps - clean and build deps
@ECHO deps-dirty - build deps without cleaning
@ECHO Default: %PS_STEPS_DEFAULT%
@ECHO -d -DESTDIR Deps destination directory
@ECHO %PS_DESTDIR_DEFAULT_MSG%
@ECHO.
@ECHO Example usage:
@ECHO First build: build_win -d "c:\src\PrusaSlicer-deps"
@ECHO Deps change: build_win -s all
@ECHO App rebuild: build_win
GOTO :END

:MAIN
SET START_TIME=%TIME%
pushd %~dp0
REM Probe build directories and sytem state for reasonable default arguments
SET PS_CONFIG=RelWithDebInfo
SET PS_ARCH=%PROCESSOR_ARCHITECTURE%
CALL :TOLOWER PS_ARCH
SET DEPS_PATH_FILE=%~dp0deps\build\.DEPS_PATH.txt
SET PS_DESTDIR=
IF EXIST %DEPS_PATH_FILE% (
FOR /F "tokens=* USEBACKQ" %%I IN ("%DEPS_PATH_FILE%") DO SET PS_DESTDIR=%%I
IF EXIST build/ALL_BUILD.vcxproj (
SET PS_STEPS=app-dirty
) ELSE SET PS_STEPS=app
) ELSE SET PS_STEPS=all

REM Set up parameters used by help menu
SET PS_CONFIG_DEFAULT=%PS_CONFIG%
SET PS_ARCH_HOST=%PS_ARCH%
SET PS_STEPS_DEFAULT=%PS_STEPS%
IF "%PS_DESTDIR%" NEQ "" (
SET PS_DESTDIR_DEFAULT_MSG=Default: %PS_DESTDIR%
) ELSE (
SET PS_DESTDIR_DEFAULT_MSG=Argument required ^(no default available^)
)

REM Parse arguments
SET EXIT_STATUS=1
SET PARSER_STATE=
SET PARSER_FAIL=
FOR %%I in (%*) DO CALL :PARSE_OPTION "ARCH CONFIG DESTDIR STEPS" PARSER_STATE "%%~I"
IF "%PARSER_FAIL%%PARSER_STATE%" NEQ "" GOTO :HELP

REM Validate arguments
CALL :PARSE_OPTION_NAME "all all-dirty deps-dirty deps app-dirty app" PS_STEPS -%PS_STEPS%
IF "%PS_STEPS%" EQU "" GOTO :HELP
(echo %PS_STEPS%)| findstr /I /C:"dirty">nul && SET PS_STEPS_DIRTY=1
CALL :TOLOWER PS_STEPS
CALL :TOLOWER PS_ARCH
IF "%OPTION_NAME%" NEQ "" GOTO :HELP
IF "%PS_STEPS_DIRTY%%PS_DESTDIR%" EQU "" GOTO :HELP

REM Set up MSVC environment
SET EXIT_STATUS=2
@ECHO **********************************************************************
@ECHO ** Build Config: %PS_CONFIG%
@ECHO ** Target Arch: %PS_ARCH%
@ECHO ** Build Steps: %PS_STEPS%
@ECHO ** Using Microsoft Visual Studio installation found at:
SET VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
IF NOT EXIST %VSWHERE% SET VSWHERE="%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe"
FOR /F "tokens=* USEBACKQ" %%I IN (`%VSWHERE% -nologo -property installationPath`) DO SET MSVC_DIR=%%I
@ECHO ** %MSVC_DIR%
CALL "%MSVC_DIR%\Common7\Tools\vsdevcmd.bat" -arch=%PS_ARCH% -host_arch=%PS_ARCH_HOST% -app_platform=Desktop || GOTO :END
IF /I "%PS_STEPS:~0,3%" EQU "app" GOTO :BUILD_APP

REM Build deps
:BUILD_DEPS
SET EXIT_STATUS=3
IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY deps\build
cd deps\build || GOTO :END
IF "%PS_STEPS_DIRTY%" EQU "" cmake.exe .. -DDESTDIR="%PS_DESTDIR%" || GOTO :END
(echo %PS_DESTDIR%)> "%DEPS_PATH_FILE%"
msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% || GOTO :END
cd ..\..
IF /I "%PS_STEPS:~0,4%" EQU "deps" GOTO :PROLOGUE

REM Build app
:BUILD_APP
SET EXIT_STATUS=4
IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY build
cd build || GOTO :END
IF "%PS_STEPS_DIRTY%" EQU "" cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" || GOTO :END
msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% || GOTO :END

:PROLOGUE
SET EXIT_STATUS=%ERRORLEVEL%
:END
@ECHO Script started at %START_TIME% and completed at %TIME%.
popd
endlocal
exit /B %EXIT_STATUS%

GOTO :EOF
REM Functions and stubs start here.

:PARSE_OPTION
REM Argument parser called for each argument
REM %1 - Valid option list
REM %2 - Variable name for parser state; must be unset when parsing finished
REM %3 - Current argument value
REM PARSER_FAIL will be set on an error
REM Note: Must avoid delayed expansion since filenames may contain ! character
setlocal disableDelayedExpansion
CALL SET LAST_ARG=%%%2%%
IF "%LAST_ARG%" EQU "" (
CALL :PARSE_OPTION_NAME %1 %~2 %~3 1
SET ARG_TYPE=NAME
) ELSE (
SET PS_SET_COMMAND=^&SET PS_%LAST_ARG%=%~3
SET ARG_TYPE=LAST_ARG
SET %~2=
)
CALL SET LAST_ARG=%%%2%%
IF "%LAST_ARG%" EQU "" IF "%ARG_TYPE%" EQU "NAME" SET PARSER_FAIL=1
endlocal & (SET PARSER_FAIL=%PARSER_FAIL%) & (SET %~2=%LAST_ARG%) %PS_SET_COMMAND%
GOTO :EOF

:PARSE_OPTION_NAME
REM Parses an option name
REM %1 - Valid option list
REM %2 - Out variable name; unset on error
REM %3 - Current argument value
REM $4 - Boolean indicating single character switches are valid
REM Note: Delayed expansion safe because ! character is invalid in option name
setlocal enableDelayedExpansion
IF "%4" NEQ "" FOR %%I IN (%~1) DO (
SET SHORT_NAME=%%~I
SET SHORT_ARG_!SHORT_NAME:~0,1!=%%~I
)
SET OPTION_NAME=%~3
(echo %OPTION_NAME%)| findstr /R /C:"[-/]..*">nul || GOTO :PARSE_OPTION_NAME_FAIL
SET OPTION_NAME=%OPTION_NAME:~1%
IF "%4" NEQ "" (
IF "%OPTION_NAME%" EQU "%OPTION_NAME:~0,1%" (
IF "!SHORT_ARG_%OPTION_NAME:~0,1%!" NEQ "" SET OPTION_NAME=!SHORT_ARG_%OPTION_NAME:~0,1%!
)
)
(echo %OPTION_NAME%)| findstr /R /C:".[ ][ ]*.">nul && GOTO :PARSE_OPTION_NAME_FAIL
(echo %~1 )| findstr /I /C:" %OPTION_NAME% ">nul || GOTO :PARSE_OPTION_NAME_FAIL
endlocal & SET %~2=%OPTION_NAME%
GOTO :EOF
:PARSE_OPTION_NAME_FAIL
endlocal & SET %~2=
GOTO :EOF

:MAKE_OR_CLEAN_DIRECTORY
REM Create directory if it doesn't exist or clean it if it does
REM %1 - Directory path to clean or create
setlocal disableDelayedExpansion
IF NOT EXIST "%~1" (
ECHO Creating %~1
mkdir "%~1" && GOTO :EOF
)
ECHO Cleaning %~1 ...
for /F "usebackq delims=" %%I in (`dir /a /b "%~1"`) do (
(rmdir /s /q "%~1\%%I" 2>nul ) || del /q /f "%~1\%%I")
GOTO :EOF

:TOLOWER
REM Converts supplied environment variable to lowercase
REM %1 - Input/output variable name
REM Note: This is slow on very long strings, but is used only on very short ones
setlocal disableDelayedExpansion
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%%
CALL SET OUTPUT=%%%~1%%
endlocal & SET %~1=%OUTPUT%
GOTO :EOF