1@setlocal
2@echo off
3
4rem This script is intended for building official releases of Python.
5rem To use it to build alternative releases, you should clone this file
6rem and modify the following three URIs.
7
8rem These two will ensure that your release can be installed
9rem alongside an official Python release, by modifying the GUIDs used
10rem for all components.
11rem
12rem The following substitutions will be applied to the release URI:
13rem     Variable        Description         Example
14rem     {arch}          architecture        amd64, win32
15rem Do not change the scheme to https. Otherwise, releases built with this
16rem script will not be upgradable to/from official releases of Python.
17set RELEASE_URI=http://www.python.org/{arch}
18
19rem This is the URL that will be used to download installation files.
20rem The files available from the default URL *will* conflict with your
21rem installer. Trust me, you don't want them, even if it seems like a
22rem good idea.
23rem
24rem The following substitutions will be applied to the download URL:
25rem     Variable        Description         Example
26rem     {version}       version number      3.5.0
27rem     {arch}          architecture        amd64, win32
28rem     {releasename}   release name        a1, b2, rc3 (or blank for final)
29rem     {msi}           MSI filename        core.msi
30set DOWNLOAD_URL=https://www.python.org/ftp/python/{version}/{arch}{releasename}/{msi}
31
32set D=%~dp0
33set PCBUILD=%D%..\..\PCbuild\
34if NOT DEFINED Py_OutDir set Py_OutDir=%PCBUILD%
35set EXTERNALS=%D%..\..\externals\windows-installer\
36
37set BUILDX86=
38set BUILDX64=
39set BUILDARM64=
40set TARGET=Rebuild
41set TESTTARGETDIR=
42set PGO=-m test -q --pgo
43set BUILDMSI=1
44set BUILDNUGET=1
45set BUILDZIP=1
46
47
48:CheckOpts
49if    "%1" EQU "-h" goto Help
50if    "%1" EQU "-c" (set CERTNAME=%~2) && shift && shift && goto CheckOpts
51if    "%1" EQU "--certificate" (set CERTNAME=%~2) && shift && shift && goto CheckOpts
52if    "%1" EQU "-o" (set OUTDIR=%~2) && shift && shift && goto CheckOpts
53if    "%1" EQU "--out" (set OUTDIR=%~2) && shift && shift && goto CheckOpts
54if    "%1" EQU "-D" (set SKIPDOC=1) && shift && goto CheckOpts
55if    "%1" EQU "--skip-doc" (set SKIPDOC=1) && shift && goto CheckOpts
56if    "%1" EQU "-B" (set SKIPBUILD=1) && shift && goto CheckOpts
57if    "%1" EQU "--skip-build" (set SKIPBUILD=1) && shift && goto CheckOpts
58if    "%1" EQU "--download" (set DOWNLOAD_URL=%~2) && shift && shift && goto CheckOpts
59if    "%1" EQU "--test" (set TESTTARGETDIR=%~2) && shift && shift && goto CheckOpts
60if    "%1" EQU "-b" (set TARGET=Build) && shift && goto CheckOpts
61if    "%1" EQU "--build" (set TARGET=Build) && shift && goto CheckOpts
62if /I "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts
63if /I "%1" EQU "-Win32" (set BUILDX86=1) && shift && goto CheckOpts
64if /I "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts
65if /I "%1" EQU "-arm64" (set BUILDARM64=1) && shift && goto CheckOpts
66if    "%1" EQU "--pgo" (set PGO=%~2) && shift && shift && goto CheckOpts
67if    "%1" EQU "--skip-pgo" (set PGO=) && shift && goto CheckOpts
68if    "%1" EQU "--skip-nuget" (set BUILDNUGET=) && shift && goto CheckOpts
69if    "%1" EQU "--skip-zip" (set BUILDZIP=) && shift && goto CheckOpts
70if    "%1" EQU "--skip-msi" (set BUILDMSI=) && shift && goto CheckOpts
71
72if "%1" NEQ "" echo Invalid option: "%1" && exit /B 1
73
74if not defined BUILDX86 if not defined BUILDX64 if not defined BUILDARM64 (set BUILDX86=1) && (set BUILDX64=1)
75
76if not exist "%GIT%" where git > "%TEMP%\git.loc" 2> nul && set /P GIT= < "%TEMP%\git.loc" & del "%TEMP%\git.loc"
77if not exist "%GIT%" echo Cannot find Git on PATH && exit /B 1
78
79call "%D%get_externals.bat"
80call "%PCBUILD%find_msbuild.bat" %MSBUILD%
81if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable & exit /b 2)
82
83:builddoc
84if "%SKIPBUILD%" EQU "1" goto skipdoc
85if "%SKIPDOC%" EQU "1" goto skipdoc
86
87call "%D%..\..\doc\make.bat" html
88if errorlevel 1 exit /B %ERRORLEVEL%
89:skipdoc
90
91if defined BUILDX86 (
92    call :build x86
93    if errorlevel 1 exit /B %ERRORLEVEL%
94)
95
96if defined BUILDX64 (
97    call :build x64 "%PGO%"
98    if errorlevel 1 exit /B %ERRORLEVEL%
99)
100
101if defined BUILDARM64 (
102    call :build ARM64
103    if errorlevel 1 exit /B %ERRORLEVEL%
104)
105
106if defined TESTTARGETDIR (
107    call "%D%testrelease.bat" -t "%TESTTARGETDIR%"
108    if errorlevel 1 exit /B %ERRORLEVEL%
109)
110
111exit /B 0
112
113:build
114@setlocal
115@echo off
116
117if "%1" EQU "x86" (
118    set PGO=
119    set BUILD=%Py_OutDir%win32\
120    set BUILD_PLAT=Win32
121    set OUTDIR_PLAT=win32
122    set OBJDIR_PLAT=x86
123) else if "%1" EQU "x64" (
124    set BUILD=%Py_OutDir%amd64\
125    set PGO=%~2
126    set BUILD_PLAT=x64
127    set OUTDIR_PLAT=amd64
128    set OBJDIR_PLAT=x64
129) else if "%1" EQU "ARM64" (
130    set BUILD=%Py_OutDir%amd64\
131    set PGO=%~2
132    set BUILD_PLAT=ARM64
133    set OUTDIR_PLAT=arm64
134    set OBJDIR_PLAT=arm64
135) else (
136    echo Unknown platform %1
137    exit /B 1
138)
139
140if exist "%BUILD%en-us" (
141    echo Deleting %BUILD%en-us
142    rmdir /q/s "%BUILD%en-us"
143    if errorlevel 1 exit /B %ERRORLEVEL%
144)
145
146if exist "%D%obj\Debug_%OBJDIR_PLAT%" (
147    echo Deleting "%D%obj\Debug_%OBJDIR_PLAT%"
148    rmdir /q/s "%D%obj\Debug_%OBJDIR_PLAT%"
149    if errorlevel 1 exit /B %ERRORLEVEL%
150)
151
152if exist "%D%obj\Release_%OBJDIR_PLAT%" (
153    echo Deleting "%D%obj\Release_%OBJDIR_PLAT%"
154    rmdir /q/s "%D%obj\Release_%OBJDIR_PLAT%"
155    if errorlevel 1 exit /B %ERRORLEVEL%
156)
157
158if not "%CERTNAME%" EQU "" (
159    set CERTOPTS="/p:SigningCertificate=%CERTNAME%"
160) else (
161    set CERTOPTS=
162)
163if not "%PGO%" EQU "" (
164    set PGOOPTS=--pgo-job "%PGO%"
165) else (
166    set PGOOPTS=
167)
168if not "%SKIPBUILD%" EQU "1" (
169    @echo call "%PCBUILD%build.bat" -e -p %BUILD_PLAT% -t %TARGET% %PGOOPTS% %CERTOPTS%
170    @call "%PCBUILD%build.bat" -e -p %BUILD_PLAT% -t %TARGET% %PGOOPTS% %CERTOPTS%
171    @if errorlevel 1 exit /B %ERRORLEVEL%
172    @rem build.bat turns echo back on, so we disable it again
173    @echo off
174
175    @echo call "%PCBUILD%build.bat" -d -e -p %BUILD_PLAT% -t %TARGET%
176    @call "%PCBUILD%build.bat" -d -e -p %BUILD_PLAT% -t %TARGET%
177    @if errorlevel 1 exit /B %ERRORLEVEL%
178    @rem build.bat turns echo back on, so we disable it again
179    @echo off
180)
181
182if "%OUTDIR_PLAT%" EQU "win32" (
183    %MSBUILD% "%D%launcher\launcher.wixproj" /p:Platform=x86 %CERTOPTS% /p:ReleaseUri=%RELEASE_URI%
184    if errorlevel 1 exit /B %ERRORLEVEL%
185) else if not exist "%Py_OutDir%win32\en-us\launcher.msi" (
186    %MSBUILD% "%D%launcher\launcher.wixproj" /p:Platform=x86 %CERTOPTS% /p:ReleaseUri=%RELEASE_URI%
187    if errorlevel 1 exit /B %ERRORLEVEL%
188)
189
190set BUILDOPTS=/p:Platform=%1 /p:BuildForRelease=true /p:DownloadUrl=%DOWNLOAD_URL% /p:DownloadUrlBase=%DOWNLOAD_URL_BASE% /p:ReleaseUri=%RELEASE_URI%
191if defined BUILDMSI (
192    %MSBUILD% "%D%bundle\releaselocal.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true
193    if errorlevel 1 exit /B %ERRORLEVEL%
194)
195
196if defined BUILDZIP (
197    if "%BUILD_PLAT%" EQU "ARM64" (
198        echo Skipping embeddable ZIP generation for ARM64 platform
199    ) else (
200        %MSBUILD% "%D%make_zip.proj" /t:Build %BUILDOPTS% %CERTOPTS% /p:OutputPath="%BUILD%en-us"
201        if errorlevel 1 exit /B %ERRORLEVEL%
202    )
203)
204
205if defined BUILDNUGET (
206    if "%BUILD_PLAT%" EQU "ARM64" (
207        echo Skipping Nuget package generation for ARM64 platform
208    ) else (
209        %MSBUILD% "%D%..\nuget\make_pkg.proj" /t:Build /p:Configuration=Release /p:Platform=%1 /p:OutputPath="%BUILD%en-us"
210        if errorlevel 1 exit /B %ERRORLEVEL%
211    )
212)
213
214if not "%OUTDIR%" EQU "" (
215    mkdir "%OUTDIR%\%OUTDIR_PLAT%"
216    mkdir "%OUTDIR%\%OUTDIR_PLAT%\binaries"
217    mkdir "%OUTDIR%\%OUTDIR_PLAT%\symbols"
218    robocopy "%BUILD%en-us" "%OUTDIR%\%OUTDIR_PLAT%" /XF "*.wixpdb"
219    robocopy "%BUILD%\" "%OUTDIR%\%OUTDIR_PLAT%\binaries" *.exe *.dll *.pyd /XF "_test*" /XF "*_d.*" /XF "_freeze*" /XF "tcl*" /XF "tk*" /XF "*_test.*"
220    robocopy "%BUILD%\" "%OUTDIR%\%OUTDIR_PLAT%\symbols" *.pdb              /XF "_test*" /XF "*_d.*" /XF "_freeze*" /XF "tcl*" /XF "tk*" /XF "*_test.*"
221)
222
223exit /B 0
224
225:Help
226echo buildrelease.bat [--out DIR] [-x86] [-x64] [-arm64] [--certificate CERTNAME] [--build] [--pgo COMMAND]
227echo                  [--skip-build] [--skip-doc] [--skip-nuget] [--skip-zip] [--skip-pgo]
228echo                  [--download DOWNLOAD URL] [--test TARGETDIR]
229echo                  [-h]
230echo.
231echo    --out (-o)          Specify an additional output directory for installers
232echo    -x86                Build x86 installers
233echo    -x64                Build x64 installers
234echo    -arm64              Build ARM64 installers
235echo    --build (-b)        Incrementally build Python rather than rebuilding
236echo    --skip-build (-B)   Do not build Python (just do the installers)
237echo    --skip-doc (-D)     Do not build documentation
238echo    --pgo               Specify PGO command for x64 installers
239echo    --skip-pgo          Build x64 installers without using PGO
240echo    --skip-msi          Do not build executable/MSI packages
241echo    --skip-nuget        Do not build Nuget packages
242echo    --skip-zip          Do not build embeddable package
243echo    --download          Specify the full download URL for MSIs
244echo    --test              Specify the test directory to run the installer tests
245echo    -h                  Display this help information
246echo.
247echo If no architecture is specified, all architectures will be built.
248echo If --test is not specified, the installer tests are not run.
249echo.
250echo For the --pgo option, any Python command line can be used, or 'default' to
251echo use the default task (-m test --pgo).
252echo.
253echo x86 and ARM64 builds will never use PGO. ARM64 builds will never generate
254echo embeddable or Nuget packages.
255echo.
256echo The following substitutions will be applied to the download URL:
257echo     Variable        Description         Example
258echo     {version}       version number      3.5.0
259echo     {arch}          architecture        amd64, win32
260echo     {releasename}   release name        a1, b2, rc3 (or blank for final)
261echo     {msi}           MSI filename        core.msi
262