1@echo off
2goto Run
3:Usage
4echo.%~nx0 [flags and arguments] [quoted MSBuild options]
5echo.
6echo.Build CPython from the command line.  Requires the appropriate
7echo.version(s) of Microsoft Visual Studio to be installed (see readme.txt).
8echo.
9echo.After the flags recognized by this script, up to 9 arguments to be passed
10echo.directly to MSBuild may be passed.  If the argument contains an '=', the
11echo.entire argument must be quoted (e.g. `%~nx0 "/p:PlatformToolset=v100"`).
12echo.Alternatively you can put extra flags for MSBuild in a file named
13echo.`msbuild.rsp` in the `PCbuild` directory, one flag per line. This file
14echo.will be picked automatically by MSBuild. Flags put in this file does not
15echo.need to be quoted. You can still use environment variables inside the
16echo.response file.
17echo.
18echo.Available flags:
19echo.  -h  Display this help message
20echo.  -V  Display version information for the current build
21echo.  -r  Target Rebuild instead of Build
22echo.  -d  Set the configuration to Debug
23echo.  -E  Don't fetch or build external libraries.  Extension modules that
24echo.      depend on external libraries will not attempt to build if this flag
25echo.      is present; -e is also accepted to explicitly enable fetching and
26echo.      building externals.
27echo.  -m  Enable parallel build (enabled by default)
28echo.  -M  Disable parallel build
29echo.  -v  Increased output messages
30echo.  -vv Verbose output messages
31echo.  -q  Quiet output messages (errors and warnings only)
32echo.  -k  Attempt to kill any running Pythons before building (usually done
33echo.      automatically by the pythoncore project)
34echo.  --pgo          Build with Profile-Guided Optimization.  This flag
35echo.                 overrides -c and -d
36echo.  --test-marker  Enable the test marker within the build.
37echo.  --regen        Regenerate all opcodes, grammar and tokens
38echo.
39echo.Available flags to avoid building certain modules.
40echo.These flags have no effect if '-e' is not given:
41echo.  --no-ctypes   Do not attempt to build _ctypes
42echo.  --no-ssl      Do not attempt to build _ssl
43echo.  --no-tkinter  Do not attempt to build Tkinter
44echo.
45echo.Available arguments:
46echo.  -c Release ^| Debug ^| PGInstrument ^| PGUpdate
47echo.     Set the configuration (default: Release)
48echo.  -p x64 ^| Win32 ^| ARM ^| ARM64
49echo.     Set the platform (default: x64)
50echo.  -t Build ^| Rebuild ^| Clean ^| CleanAll
51echo.     Set the target manually
52echo.  --pgo-job  The job to use for PGO training; implies --pgo
53echo.             (default: "-m test --pgo")
54exit /b 127
55
56:Run
57setlocal
58set platf=x64
59set conf=Release
60set target=Build
61set dir=%~dp0
62set parallel=/m
63set verbose=/nologo /v:m /clp:summary
64set kill=
65set do_pgo=
66set pgo_job=-m test --pgo
67
68:CheckOpts
69if "%~1"=="-h" goto Usage
70if "%~1"=="-c" (set conf=%2) & shift & shift & goto CheckOpts
71if "%~1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts
72if "%~1"=="-r" (set target=Rebuild) & shift & goto CheckOpts
73if "%~1"=="-t" (set target=%2) & shift & shift & goto CheckOpts
74if "%~1"=="-d" (set conf=Debug) & shift & goto CheckOpts
75if "%~1"=="-m" (set parallel=/m) & shift & goto CheckOpts
76if "%~1"=="-M" (set parallel=) & shift & goto CheckOpts
77if "%~1"=="-v" (set verbose=/v:n) & shift & goto CheckOpts
78if "%~1"=="-vv" (set verbose=/v:d /ds) & shift & goto CheckOpts
79if "%~1"=="-q" (set verbose=/v:q /nologo /clp:summary) & shift & goto CheckOpts
80if "%~1"=="-k" (set kill=true) & shift & goto CheckOpts
81if "%~1"=="--pgo" (set do_pgo=true) & shift & goto CheckOpts
82if "%~1"=="--pgo-job" (set do_pgo=true) & (set pgo_job=%~2) & shift & shift & goto CheckOpts
83if "%~1"=="--test-marker" (set UseTestMarker=true) & shift & goto CheckOpts
84if "%~1"=="-V" shift & goto Version
85if "%~1"=="--regen" (set Regen=true) & shift & goto CheckOpts
86rem These use the actual property names used by MSBuild.  We could just let
87rem them in through the environment, but we specify them on the command line
88rem anyway for visibility so set defaults after this
89if "%~1"=="-e" (set IncludeExternals=true) & shift & goto CheckOpts
90if "%~1"=="-E" (set IncludeExternals=false) & shift & goto CheckOpts
91if "%~1"=="--no-ctypes" (set IncludeCTypes=false) & shift & goto CheckOpts
92if "%~1"=="--no-ssl" (set IncludeSSL=false) & shift & goto CheckOpts
93if "%~1"=="--no-tkinter" (set IncludeTkinter=false) & shift & goto CheckOpts
94
95if "%IncludeExternals%"=="" set IncludeExternals=true
96if "%IncludeCTypes%"=="" set IncludeCTypes=true
97if "%IncludeSSL%"=="" set IncludeSSL=true
98if "%IncludeTkinter%"=="" set IncludeTkinter=true
99
100if "%IncludeExternals%"=="true" call "%dir%get_externals.bat"
101
102if "%do_pgo%" EQU "true" if "%platf%" EQU "x64" (
103    if "%PROCESSOR_ARCHITEW6432%" NEQ "AMD64" if "%PROCESSOR_ARCHITECTURE%" NEQ "AMD64" (
104        echo.ERROR: Cannot cross-compile with PGO
105        echo.       32bit operating system detected. Ensure your PROCESSOR_ARCHITECTURE
106        echo.       and PROCESSOR_ARCHITEW6432 environment variables are correct.
107        exit /b 1
108    )
109)
110
111if not exist "%GIT%" where git > "%TEMP%\git.loc" 2> nul && set /P GIT= < "%TEMP%\git.loc" & del "%TEMP%\git.loc"
112if exist "%GIT%" set GITProperty=/p:GIT="%GIT%"
113if not exist "%GIT%" echo Cannot find Git on PATH & set GITProperty=
114
115rem Setup the environment
116call "%dir%find_msbuild.bat" %MSBUILD%
117if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable & exit /b 2)
118
119if "%kill%"=="true" call :Kill
120if ERRORLEVEL 1 exit /B 3
121
122if "%do_pgo%"=="true" (
123    set conf=PGInstrument
124    call :Build %1 %2 %3 %4 %5 %6 %7 %8 %9
125)
126rem %VARS% are evaluated eagerly, which would lose the ERRORLEVEL
127rem value if we didn't split it out here.
128if "%do_pgo%"=="true" if ERRORLEVEL 1 exit /B %ERRORLEVEL%
129if "%do_pgo%"=="true" (
130    del /s "%dir%\*.pgc"
131    del /s "%dir%\..\Lib\*.pyc"
132    echo on
133    call "%dir%\..\python.bat" %pgo_job%
134    @echo off
135    call :Kill
136    set conf=PGUpdate
137    set target=Build
138)
139goto :Build
140
141:Kill
142echo on
143%MSBUILD% "%dir%\pythoncore.vcxproj" /t:KillPython %verbose%^
144 /p:Configuration=%conf% /p:Platform=%platf%^
145 /p:KillPython=true
146
147@echo off
148exit /B %ERRORLEVEL%
149
150:Build
151rem Call on MSBuild to do the work, echo the command.
152rem Passing %1-9 is not the preferred option, but argument parsing in
153rem batch is, shall we say, "lackluster"
154echo on
155%MSBUILD% "%dir%pcbuild.proj" /t:%target% %parallel% %verbose%^
156 /p:Configuration=%conf% /p:Platform=%platf%^
157 /p:IncludeExternals=%IncludeExternals%^
158 /p:IncludeCTypes=%IncludeCTypes%^
159 /p:IncludeSSL=%IncludeSSL% /p:IncludeTkinter=%IncludeTkinter%^
160 /p:UseTestMarker=%UseTestMarker% %GITProperty%^
161 %1 %2 %3 %4 %5 %6 %7 %8 %9
162
163@if not ERRORLEVEL 1 @if "%Regen%"=="true" (
164    %MSBUILD% "%dir%regen.vcxproj" /t:%target% %parallel% %verbose%^
165     /p:IncludeExternals=%IncludeExternals%^
166     /p:Configuration=%conf% /p:Platform=%platf%^
167     /p:UseTestMarker=%UseTestMarker% %GITProperty%^
168     %1 %2 %3 %4 %5 %6 %7 %8 %9
169)
170
171@echo off
172exit /b %ERRORLEVEL%
173
174:Version
175rem Display the current build version information
176call "%dir%find_msbuild.bat" %MSBUILD%
177if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable & exit /b 2)
178%MSBUILD% "%dir%pythoncore.vcxproj" /t:ShowVersionInfo /v:m /nologo %1 %2 %3 %4 %5 %6 %7 %8 %9
179if ERRORLEVEL 1 exit /b 3