Moves Windows installer externals onto SVN and updates the build process to grab them automatically.

This commit is contained in:
Steve Dower 2015-10-23 09:51:16 -07:00
commit fe3e7a006e
8 changed files with 100 additions and 70 deletions

View File

@ -62,10 +62,14 @@ the initial download size by separating them into their own MSIs.
Building the Installer
======================
Before building the installer, download extra build dependencies using
Tools\msi\get_externals.bat. (Note that this is in addition to the
similarly named file in PCBuild.)
For testing, the installer should be built with the Tools/msi/build.bat
script:
build.bat [-x86] [-x64] [--doc]
build.bat [-x86] [-x64] [--doc] [--test-marker] [--pack]
This script will build the required configurations of Python and
generate an installer layout in PCBuild/(win32|amd64)/en-us.
@ -80,8 +84,13 @@ available, it will simply be excluded from the installer. Ensure
also set %HTMLHELP% to the Html Help Compiler (hhc.exe), or put HHC on
your PATH or in externals/.
If WiX is not found on your system, it will be automatically downloaded
and extracted to the externals/ directory.
Specify --test-marker to build an installer that works side-by-side with
an official Python release. All registry keys and install locations will
include an extra marker to avoid overwriting files. This marker is
currently an 'x' prefix, but may change at any time.
Specify --pack to build an installer that does not require all MSIs to
be available alongside. This takes longer, but is easier to share.
For an official release, the installer should be built with the
@ -175,6 +184,38 @@ The following properties may be passed when building these projects.
When true, rebuilds all of the MSIs making up the layout. Defaults to
true.
Uploading the Installer
=======================
For official releases, the uploadrelease.bat script should be used.
You will require PuTTY so that plink.exe and pscp.exe can be used, and your
SSH key can be activated in pageant.exe. PuTTY should be either on your path
or in %ProgramFiles(x86)%\PuTTY.
To include signatures for each uploaded file, you will need gpg2.exe on your
path or have run get_externals.bat. You may also need to "gpg2.exe --import"
your key before running the upload script.
uploadrelease.bat --host <host> --user <username> [--dry-run] [--no-gpg]
The host is the URL to the server. This can be provided by the Release
Manager. You should be able to SSH to this address.
The username is your own username, which you have permission to SSH into
the server containing downloads.
Use --dry-run to display the generated upload commands without executing
them. Signatures for each file will be generated but not uploaded unless
--no-gpg is also passed.
Use --no-gpg to suppress signature generation and upload.
The default target directory (which appears in uploadrelease.proj) is
correct for official Python releases, but may be overridden with
--target <path> for other purposes. This path should generally not include
any version specifier, as that will be added automatically.
Modifying the Installer
=======================
@ -298,9 +339,9 @@ based on whether the install is for all users of the machine or just for
the user performing the installation.
The default installation location when installing for all users is
"%ProgramFiles%\Python 3.X" for the 64-bit interpreter and
"%ProgramFiles(x86)%\Python 3.X" for the 32-bit interpreter. (Note that
the latter path is equivalent to "%ProgramFiles%\Python 3.X" when
"%ProgramFiles%\Python3X" for the 64-bit interpreter and
"%ProgramFiles(x86)%\Python3X-32" for the 32-bit interpreter. (Note that
the latter path is equivalent to "%ProgramFiles%\Python3X-32" when
running a 32-bit version of Windows.) This location requires
administrative privileges to install or later modify the installation.
@ -311,6 +352,8 @@ interpreter. Only the current user can access this location. This
provides a suitable level of protection against malicious modification
of Python's files.
(Default installation locations are set in Tools\msi\bundle\bundle.wxs.)
Within this install directory is the following approximate layout:
.\python[w].exe The core executable files
@ -487,6 +530,6 @@ Removing Python will clean up all the files and registry keys that were
created by the installer, as well as __pycache__ folders that are
explicitly handled by the installer. Python packages installed later
using a tool like pip will not be removed. Some components may be
installed by other installers (such as the MSVCRT) and these will not be
removed if another product has a dependency on them.
installed by other installers and these will not be removed if another
product has a dependency on them.

View File

@ -19,6 +19,8 @@ if "%~1" EQU "--pack" (set BUILDPACK=1) && shift && goto CheckOpts
if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1)
call "%D%get_externals.bat"
call "%PCBUILD%env.bat" x86
if defined BUILDX86 (
@ -48,12 +50,10 @@ if defined BUILDPACK (
)
if defined BUILDX86 (
"%PCBUILD%win32\python.exe" "%D%get_wix.py"
msbuild %BUILD_CMD%
if errorlevel 1 goto :eof
)
if defined BUILDX64 (
"%PCBUILD%amd64\python.exe" "%D%get_wix.py"
msbuild /p:Platform=x64 %BUILD_CMD%
if errorlevel 1 goto :eof
)

View File

@ -29,6 +29,7 @@ set DOWNLOAD_URL=https://www.python.org/ftp/python/{version}/{arch}{releasename}
set D=%~dp0
set PCBUILD=%D%..\..\PCBuild\
set EXTERNALS=%D%..\..\externals\windows-installer\
set BUILDX86=
set BUILDX64=
@ -59,12 +60,15 @@ if "%1" NEQ "" echo Invalid option: "%1" && exit /B 1
if not defined BUILDX86 if not defined BUILDX64 (set BUILDX86=1) && (set BUILDX64=1)
call "%D%get_externals.bat"
:builddoc
if "%SKIPBUILD%" EQU "1" goto skipdoc
if "%SKIPDOC%" EQU "1" goto skipdoc
if not defined PYTHON where py -q || echo Cannot find py on path and PYTHON is not set. && exit /B 1
if not defined SPHINXBUILD where sphinx-build -q || echo Cannot find sphinx-build on path and SPHINXBUILD is not set. && exit /B 1
call "%D%..\..\doc\make.bat" htmlhelp
if errorlevel 1 goto :eof
:skipdoc
@ -73,7 +77,7 @@ where hg /q || echo Cannot find Mercurial on PATH && exit /B 1
where dlltool /q && goto skipdlltoolsearch
set _DLLTOOL_PATH=
where /R "%D%..\..\externals" dlltool > "%TEMP%\dlltool.loc" 2> nul && set /P _DLLTOOL_PATH= < "%TEMP%\dlltool.loc" & del "%TEMP%\dlltool.loc"
where /R "%EXTERNALS%\" dlltool > "%TEMP%\dlltool.loc" 2> nul && set /P _DLLTOOL_PATH= < "%TEMP%\dlltool.loc" & del "%TEMP%\dlltool.loc"
if not exist "%_DLLTOOL_PATH%" echo Cannot find binutils on PATH or in external && exit /B 1
for %%f in (%_DLLTOOL_PATH%) do set PATH=%PATH%;%%~dpf
set _DLLTOOL_PATH=
@ -170,8 +174,6 @@ if not "%SKIPBUILD%" EQU "1" (
@echo off
)
"%BUILD%python.exe" "%D%get_wix.py"
set BUILDOPTS=/p:Platform=%1 /p:BuildForRelease=true /p:DownloadUrl=%DOWNLOAD_URL% /p:DownloadUrlBase=%DOWNLOAD_URL_BASE% /p:ReleaseUri=%RELEASE_URI%
if "%PGO%" NEQ "" set BUILDOPTS=%BUILDOPTS% /p:PGOBuildPath=%BUILD%
msbuild "%D%bundle\releaselocal.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true

View File

@ -0,0 +1,27 @@
@echo off
setlocal
rem Simple script to fetch source for external tools
where /Q svn
if ERRORLEVEL 1 (
echo.svn.exe must be on your PATH to get external tools.
echo.Try TortoiseSVN (http://tortoisesvn.net/^) and be sure to check the
echo.command line tools option.
popd
exit /b 1
)
if not exist "%~dp0..\..\externals" mkdir "%~dp0..\..\externals"
pushd "%~dp0..\..\externals"
if "%SVNROOT%"=="" set SVNROOT=http://svn.python.org/projects/external/
if not exist "windows-installer\.svn" (
echo.Checking out installer dependencies to %CD%\windows-installer
svn co %SVNROOT%windows-installer
) else (
echo.Updating installer dependencies in %CD%\windows-installer
svn up windows-installer
)
popd

View File

@ -1,49 +0,0 @@
'''
Downloads and extracts WiX to a local directory
'''
__author__ = 'Steve Dower <steve.dower@microsoft.com>'
import io
import os
import sys
from pathlib import Path
from subprocess import Popen
from zipfile import ZipFile
EXTERNALS_DIR = None
for p in (Path.cwd() / __file__).parents:
if any(p.glob("PCBuild/*.vcxproj")):
EXTERNALS_DIR = p / "externals"
break
if not EXTERNALS_DIR:
print("Cannot find project root")
sys.exit(1)
WIX_BINARIES_ZIP = 'http://wixtoolset.org/downloads/v3.10.0.1823/wix310-binaries.zip'
TARGET_BIN_ZIP = EXTERNALS_DIR / "wix.zip"
TARGET_BIN_DIR = EXTERNALS_DIR / "wix"
POWERSHELL_COMMAND = "[IO.File]::WriteAllBytes('{}', (Invoke-WebRequest {} -UseBasicParsing).Content)"
if __name__ == '__main__':
if TARGET_BIN_DIR.exists() and any(TARGET_BIN_DIR.glob("*")):
print('WiX is already installed')
sys.exit(0)
try:
TARGET_BIN_DIR.mkdir()
except FileExistsError:
pass
print('Downloading WiX to', TARGET_BIN_ZIP)
p = Popen(["powershell.exe", "-Command", POWERSHELL_COMMAND.format(TARGET_BIN_ZIP, WIX_BINARIES_ZIP)])
p.wait()
print('Extracting WiX to', TARGET_BIN_DIR)
with ZipFile(str(TARGET_BIN_ZIP)) as z:
z.extractall(str(TARGET_BIN_DIR))
TARGET_BIN_ZIP.unlink()
print('Extracted WiX')

View File

@ -53,7 +53,7 @@
<OutputPath Condition="!HasTrailingSlash($(OutputPath))">$(OutputPath)\</OutputPath>
<OutDir>$(OutputPath)</OutDir>
<ReuseCabinetCache>true</ReuseCabinetCache>
<CRTRedist Condition="'$(CRTRedist)' == ''">$(ExternalsDir)\redist</CRTRedist>
<CRTRedist Condition="'$(CRTRedist)' == ''">$(ExternalsDir)\windows-installer\redist</CRTRedist>
<CRTRedist Condition="!Exists($(CRTRedist))"></CRTRedist>
<DocFilename>python$(MajorVersionNumber)$(MinorVersionNumber)$(MicroVersionNumber)$(ReleaseLevelName).chm</DocFilename>

View File

@ -8,6 +8,7 @@ set HOST=
set USER=
set TARGET=
set DRYRUN=false
set NOGPG=
:CheckOpts
if "%1" EQU "-h" goto Help
@ -18,6 +19,7 @@ if "%1" EQU "--user" (set USER=%~2) && shift && shift && goto CheckOpts
if "%1" EQU "-t" (set TARGET=%~2) && shift && shift && goto CheckOpts
if "%1" EQU "--target" (set TARGET=%~2) && shift && shift && goto CheckOpts
if "%1" EQU "--dry-run" (set DRYRUN=true) && shift && goto CheckOpts
if "%1" EQU "--no-gpg" (set NOGPG=true) && shift && goto CheckOpts
if not defined PLINK where plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc"
if not defined PLINK where /R "%ProgramFiles(x86)%\PuTTY" plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc"
@ -31,10 +33,15 @@ if not defined PSCP where /R "%ProgramFiles(x86)%" pscp > "%TEMP%\pscp.loc" 2> n
if not defined PSCP echo Cannot locate pscp.exe & exit /B 1
echo Found pscp.exe at %PSCP%
if not defined GPG where gpg2 > "%TEMP%\gpg.loc" 2> nul && set /P GPG= < "%TEMP%\gpg.loc" & del "%TEMP%\gpg.loc"
if not defined GPG where /R "%PCBUILD%..\externals" gpg2 > "%TEMP%\gpg.loc" 2> nul && set /P GPG= < "%TEMP%\gpg.loc" & del "%TEMP%\gpg.loc"
if not defined GPG echo Cannot locate gpg2.exe. Signatures will not be uploaded & pause
echo Found gpg2.exe at %GPG%
if defined NOGPG (
set GPG=
echo Skipping GPG signature generation because of --no-gpg
) else (
if not defined GPG where gpg2 > "%TEMP%\gpg.loc" 2> nul && set /P GPG= < "%TEMP%\gpg.loc" & del "%TEMP%\gpg.loc"
if not defined GPG where /R "%PCBUILD%..\externals\windows-installer" gpg2 > "%TEMP%\gpg.loc" 2> nul && set /P GPG= < "%TEMP%\gpg.loc" & del "%TEMP%\gpg.loc"
if not defined GPG echo Cannot locate gpg2.exe. Signatures will not be uploaded & pause
echo Found gpg2.exe at %GPG%
)
call "%PCBUILD%env.bat" > nul 2> nul
pushd "%D%"

View File

@ -4,9 +4,9 @@
<PropertyGroup>
<WixInstallPath Condition="'$(WixInstallPath)' == '' and Exists('$(MSBuildThisFileDirectory)\Wix')">$(MSBuildThisFileDirectory)\Wix\</WixInstallPath>
<WixInstallPath Condition="'$(WixInstallPath)' == '' and Exists('$(ExternalsDir)\Wix')">$(ExternalsDir)\Wix\</WixInstallPath>
<WixInstallPath Condition="'$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Installer XML\3.9@InstallRoot)</WixInstallPath>
<WixInstallPath Condition="'$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows Installer XML\3.9@InstallRoot)</WixInstallPath>
<WixInstallPath Condition="'$(WixInstallPath)' == '' and Exists('$(ExternalsDir)\windows-installer\wix')">$(ExternalsDir)\windows-installer\wix\</WixInstallPath>
<WixInstallPath Condition="'$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Installer XML\3.10@InstallRoot)</WixInstallPath>
<WixInstallPath Condition="'$(WixInstallPath)' == ''">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows Installer XML\3.10@InstallRoot)</WixInstallPath>
<WixTargetsPath>$(WixInstallPath)\Wix.targets</WixTargetsPath>
</PropertyGroup>
</Project>