diff options
Diffstat (limited to 'Tools/msi')
-rw-r--r-- | Tools/msi/buildrelease.bat | 24 | ||||
-rw-r--r-- | Tools/msi/bundle/Default.thm | 7 | ||||
-rw-r--r-- | Tools/msi/bundle/Default.wxl | 3 | ||||
-rw-r--r-- | Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 155 | ||||
-rw-r--r-- | Tools/msi/bundle/bundle.ico | bin | 19790 -> 0 bytes | |||
-rw-r--r-- | Tools/msi/bundle/bundle.wxs | 2 | ||||
-rw-r--r-- | Tools/msi/common.wxs | 8 | ||||
-rw-r--r-- | Tools/msi/common_en-US.wxl_template | 1 | ||||
-rw-r--r-- | Tools/msi/exe/exe.wixproj | 1 | ||||
-rw-r--r-- | Tools/msi/exe/exe.wxs | 2 | ||||
-rw-r--r-- | Tools/msi/exe/exe_d.wixproj | 1 | ||||
-rw-r--r-- | Tools/msi/exe/exe_en-US.wxl_template | 1 | ||||
-rw-r--r-- | Tools/msi/exe/exe_files.wxs | 10 | ||||
-rw-r--r-- | Tools/msi/exe/exe_pdb.wixproj | 1 | ||||
-rw-r--r-- | Tools/msi/exe/exe_reg.wxs | 25 | ||||
-rw-r--r-- | Tools/msi/launcher/launcher.wixproj | 2 | ||||
-rw-r--r-- | Tools/msi/launcher/launcher.wxs | 16 | ||||
-rw-r--r-- | Tools/msi/launcher/launcher_en-US.wxl | 1 | ||||
-rw-r--r-- | Tools/msi/launcher/launcher_reg.wxs | 8 | ||||
-rw-r--r-- | Tools/msi/lib/lib_files.wxs | 6 | ||||
-rw-r--r-- | Tools/msi/make_zip.py | 54 | ||||
-rw-r--r-- | Tools/msi/msi.props | 9 |
22 files changed, 191 insertions, 146 deletions
diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat index e8da3ec..c672dd0 100644 --- a/Tools/msi/buildrelease.bat +++ b/Tools/msi/buildrelease.bat @@ -35,7 +35,7 @@ set BUILDX86= set BUILDX64=
set TARGET=Rebuild
set TESTTARGETDIR=
-set PGO=
+set PGO=default
:CheckOpts
@@ -55,6 +55,7 @@ if "%1" EQU "--build" (set TARGET=Build) && shift && goto CheckOpts if "%1" EQU "-x86" (set BUILDX86=1) && shift && goto CheckOpts
if "%1" EQU "-x64" (set BUILDX64=1) && shift && goto CheckOpts
if "%1" EQU "--pgo" (set PGO=%~2) && shift && shift && goto CheckOpts
+if "%1" EQU "--skip-pgo" (set PGO=) && shift && goto CheckOpts
if "%1" NEQ "" echo Invalid option: "%1" && exit /B 1
@@ -105,20 +106,15 @@ exit /B 0 if "%1" EQU "x86" (
call "%PCBUILD%env.bat" x86
+ set PGO=
set BUILD=%PCBUILD%win32\
set BUILD_PLAT=Win32
set OUTDIR_PLAT=win32
set OBJDIR_PLAT=x86
-) else if "%~2" NEQ "" (
- call "%PCBUILD%env.bat" amd64
- set PGO=%~2
- set BUILD=%PCBUILD%amd64-pgo\
- set BUILD_PLAT=x64
- set OUTDIR_PLAT=amd64
- set OBJDIR_PLAT=x64
) else (
call "%PCBUILD%env.bat" amd64
set BUILD=%PCBUILD%amd64\
+ set PGO=%~2
set BUILD_PLAT=x64
set OUTDIR_PLAT=amd64
set OBJDIR_PLAT=x64
@@ -174,12 +170,11 @@ if not "%SKIPBUILD%" EQU "1" ( @echo off
)
-set BUILDOPTS=/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%
+set BUILDOPTS=/p:Platform=%1 /p:BuildForRelease=true /p:DownloadUrl=%DOWNLOAD_URL% /p:DownloadUrlBase=%DOWNLOAD_URL_BASE% /p:ReleaseUri=%RELEASE_URI%
msbuild "%D%launcher\launcher.wixproj" /p:Platform=x86 %CERTOPTS% /p:ReleaseUri=%RELEASE_URI%
-msbuild "%D%bundle\releaselocal.wixproj" /t:Rebuild /p:Platform=%1 %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true
+msbuild "%D%bundle\releaselocal.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true
if errorlevel 1 exit /B
-msbuild "%D%bundle\releaseweb.wixproj" /t:Rebuild /p:Platform=%1 %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false
+msbuild "%D%bundle\releaseweb.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false
if errorlevel 1 exit /B
msbuild "%D%make_zip.proj" /t:Build %BUILDOPTS% %CERTOPTS%
@@ -196,7 +191,7 @@ exit /B 0 :Help
echo buildrelease.bat [--out DIR] [-x86] [-x64] [--certificate CERTNAME] [--build] [--skip-build]
-echo [--pgo COMMAND] [--skip-doc] [--download DOWNLOAD URL] [--test TARGETDIR]
+echo [--pgo COMMAND] [--skip-pgo] [--skip-doc] [--download DOWNLOAD URL] [--test TARGETDIR]
echo [-h]
echo.
echo --out (-o) Specify an additional output directory for installers
@@ -205,7 +200,8 @@ echo -x64 Build x64 installers echo --build (-b) Incrementally build Python rather than rebuilding
echo --skip-build (-B) Do not build Python (just do the installers)
echo --skip-doc (-D) Do not build documentation
-echo --pgo Build x64 installers using PGO
+echo --pgo Specify PGO command for x64 installers
+echo --skip-pgo Build x64 installers using PGO
echo --download Specify the full download URL for MSIs
echo --test Specify the test directory to run the installer tests
echo -h Display this help information
diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm index 4d9c97a..1c0bd08 100644 --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -116,10 +116,11 @@ <Text X="185" Y="11" Width="-11" Height="36" FontId="1" DisablePrefix="yes">#(loc.SuccessHeader)</Text> <Image X="0" Y="0" Width="178" Height="382" ImageFile="SideBar.png"/> - <Hypertext Name="SuccessText" X="205" Y="71" Width="-31" Height="100" FontId="3" DisablePrefix="yes"></Hypertext> + <Hypertext Name="SuccessText" X="205" Y="71" Width="-71" Height="150" FontId="3" DisablePrefix="yes"></Hypertext> - <Text Name="SuccessRestartText" X="205" Y="-100" Width="-11" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text> - <Button Name="LaunchButton" X="185" Y="-50" Width="-11" Height="59" TabStop="yes" FontId="3" HexStyle="0xF" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button> + <Button Name="SuccessMaxPathButton" X="185" Y="-70" Width="-11" Height="81" TabStop="yes" FontId="3" HexStyle="0xE" HideWhenDisabled="yes">#(loc.SuccessMaxPathButton)</Button> + + <Text Name="SuccessRestartText" X="205" Y="-40" Width="-11" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text> <Button Name="SuccessRestartButton" X="-101" Y="-11" Width="85" Height="27" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button> <Button Name="SuccessCancelButton" X="-11" Y="-11" Width="85" Height="27" TabStop="yes" FontId="0">#(loc.CloseButton)</Button> </Page> diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl index ed79246..43506d6 100644 --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -142,4 +142,7 @@ Please <a href="https://www.bing.com/search?q=how%20to%20install%20windows%20 <String Id="FailureWS2K3OrEarlier">Windows Server 2008 SP2 or later is required to install and use [WixBundleName]. Visit <a href="https://www.python.org/">python.org</a> to download Python 3.4.</String> + + <String Id="SuccessMaxPathButton">Disable path length limit</String> + <String Id="SuccessMaxPathButtonNote">Changes your machine configuration to allow programs, including Python, to bypass the 260 character "MAX_PATH" limitation.</String> </WixLocalization> diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp index 6a67ee2..e88981f 100644 --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -11,10 +11,6 @@ #include "pch.h" static const LPCWSTR PYBA_WINDOW_CLASS = L"PythonBA"; -static const LPCWSTR PYBA_VARIABLE_LAUNCH_TARGET_PATH = L"LaunchTarget"; -static const LPCWSTR PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID = L"LaunchTargetElevatedId"; -static const LPCWSTR PYBA_VARIABLE_LAUNCH_ARGUMENTS = L"LaunchArguments"; -static const LPCWSTR PYBA_VARIABLE_LAUNCH_HIDDEN = L"LaunchHidden"; static const DWORD PYBA_ACQUIRE_PERCENTAGE = 30; static const LPCWSTR PYBA_VARIABLE_BUNDLE_FILE_VERSION = L"WixBundleFileVersion"; @@ -129,11 +125,11 @@ enum CONTROL_ID { ID_PROGRESS_CANCEL_BUTTON, // Success page - ID_LAUNCH_BUTTON, ID_SUCCESS_TEXT, ID_SUCCESS_RESTART_TEXT, ID_SUCCESS_RESTART_BUTTON, ID_SUCCESS_CANCEL_BUTTON, + ID_SUCCESS_MAX_PATH_BUTTON, // Failure page ID_FAILURE_LOGFILE_LINK, @@ -188,11 +184,11 @@ static THEME_ASSIGN_CONTROL_ID CONTROL_ID_NAMES[] = { { ID_OVERALL_PROGRESS_TEXT, L"OverallProgressText" }, { ID_PROGRESS_CANCEL_BUTTON, L"ProgressCancelButton" }, - { ID_LAUNCH_BUTTON, L"LaunchButton" }, { ID_SUCCESS_TEXT, L"SuccessText" }, { ID_SUCCESS_RESTART_TEXT, L"SuccessRestartText" }, { ID_SUCCESS_RESTART_BUTTON, L"SuccessRestartButton" }, { ID_SUCCESS_CANCEL_BUTTON, L"SuccessCancelButton" }, + { ID_SUCCESS_MAX_PATH_BUTTON, L"SuccessMaxPathButton" }, { ID_FAILURE_LOGFILE_LINK, L"FailureLogFileLink" }, { ID_FAILURE_MESSAGE_TEXT, L"FailureMessageText" }, @@ -436,6 +432,11 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { case ID_UNINSTALL_BUTTON: OnPlan(BOOTSTRAPPER_ACTION_UNINSTALL); break; + + case ID_SUCCESS_MAX_PATH_BUTTON: + EnableMaxPathSupport(); + ThemeControlEnable(_theme, ID_SUCCESS_MAX_PATH_BUTTON, FALSE); + break; } LExit: @@ -533,9 +534,8 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { } void SuccessPage_Show() { - // on the "Success" page, check if the restart or launch button should be enabled. + // on the "Success" page, check if the restart button should be enabled. BOOL showRestartButton = FALSE; - BOOL launchTargetExists = FALSE; LOC_STRING *successText = nullptr; HRESULT hr = S_OK; @@ -543,8 +543,6 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { if (BOOTSTRAPPER_RESTART_PROMPT == _command.restart) { showRestartButton = TRUE; } - } else if (ThemeControlExists(_theme, ID_LAUNCH_BUTTON)) { - launchTargetExists = BalStringVariableExists(PYBA_VARIABLE_LAUNCH_TARGET_PATH); } switch (_plannedAction) { @@ -571,9 +569,41 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { } } - ThemeControlEnable(_theme, ID_LAUNCH_BUTTON, launchTargetExists && BOOTSTRAPPER_ACTION_UNINSTALL < _plannedAction); ThemeControlEnable(_theme, ID_SUCCESS_RESTART_TEXT, showRestartButton); ThemeControlEnable(_theme, ID_SUCCESS_RESTART_BUTTON, showRestartButton); + + if (_command.action != BOOTSTRAPPER_ACTION_INSTALL || + !IsWindowsVersionOrGreater(10, 0, 0)) { + ThemeControlEnable(_theme, ID_SUCCESS_MAX_PATH_BUTTON, FALSE); + } else { + DWORD dataType = 0, buffer = 0, bufferLen = sizeof(buffer); + HKEY hKey; + LRESULT res = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control\\FileSystem", + 0, + KEY_READ, + &hKey + ); + if (res == ERROR_SUCCESS) { + res = RegQueryValueExW(hKey, L"LongPathsEnabled", nullptr, &dataType, + (LPBYTE)&buffer, &bufferLen); + RegCloseKey(hKey); + } + else { + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Failed to open SYSTEM\\CurrentControlSet\\Control\\FileSystem: error code %d", res); + } + if (res == ERROR_SUCCESS && dataType == REG_DWORD && buffer == 0) { + ThemeControlElevates(_theme, ID_SUCCESS_MAX_PATH_BUTTON, TRUE); + } + else { + if (res == ERROR_SUCCESS) + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Failed to read LongPathsEnabled value: error code %d", res); + else + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Hiding MAX_PATH button because it is already enabled"); + ThemeControlEnable(_theme, ID_SUCCESS_MAX_PATH_BUTTON, FALSE); + } + } } void FailurePage_Show() { @@ -626,6 +656,34 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { ThemeControlEnable(_theme, ID_FAILURE_RESTART_BUTTON, showRestartButton); } + static void EnableMaxPathSupport() { + LPWSTR targetDir = nullptr, defaultDir = nullptr; + HRESULT hr = BalGetStringVariable(L"TargetDir", &targetDir); + if (FAILED(hr) || !targetDir || !targetDir[0]) { + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to get TargetDir"); + return; + } + + LPWSTR pythonw = nullptr; + StrAllocFormatted(&pythonw, L"%ls\\pythonw.exe", targetDir); + if (!pythonw || !pythonw[0]) { + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to construct pythonw.exe path"); + return; + } + + LPCWSTR arguments = L"-c \"import winreg; " + "winreg.SetValueEx(" + "winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, " + "r'SYSTEM\\CurrentControlSet\\Control\\FileSystem'), " + "'LongPathsEnabled', " + "None, " + "winreg.REG_DWORD, " + "1" + ")\""; + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Executing %ls %ls", pythonw, arguments); + HINSTANCE res = ShellExecuteW(0, L"runas", pythonw, arguments, NULL, SW_HIDE); + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "return code 0x%08x", res); + } public: // IBootstrapperApplication virtual STDMETHODIMP OnStartup() { @@ -1216,12 +1274,6 @@ public: // IBootstrapperApplication } virtual STDMETHODIMP_(void) OnLaunchApprovedExeComplete(__in HRESULT hrStatus, __in DWORD /*processId*/) { - if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hrStatus) { - //try with ShelExec next time - OnClickLaunchButton(); - } else { - ::PostMessageW(_hWnd, WM_CLOSE, 0, 0); - } } @@ -1867,10 +1919,6 @@ private: switch (LOWORD(wParam)) { // Customize commands // Success/failure commands - case ID_LAUNCH_BUTTON: - pBA->OnClickLaunchButton(); - return 0; - case ID_SUCCESS_RESTART_BUTTON: __fallthrough; case ID_FAILURE_RESTART_BUTTON: pBA->OnClickRestartButton(); @@ -2372,69 +2420,6 @@ private: } - // - // OnClickLaunchButton - launch the app from the success page. - // - void OnClickLaunchButton() { - HRESULT hr = S_OK; - LPWSTR sczUnformattedLaunchTarget = nullptr; - LPWSTR sczLaunchTarget = nullptr; - LPWSTR sczLaunchTargetElevatedId = nullptr; - LPWSTR sczUnformattedArguments = nullptr; - LPWSTR sczArguments = nullptr; - int nCmdShow = SW_SHOWNORMAL; - - hr = BalGetStringVariable(PYBA_VARIABLE_LAUNCH_TARGET_PATH, &sczUnformattedLaunchTarget); - BalExitOnFailure1(hr, "Failed to get launch target variable '%ls'.", PYBA_VARIABLE_LAUNCH_TARGET_PATH); - - hr = BalFormatString(sczUnformattedLaunchTarget, &sczLaunchTarget); - BalExitOnFailure1(hr, "Failed to format launch target variable: %ls", sczUnformattedLaunchTarget); - - if (BalStringVariableExists(PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID)) { - hr = BalGetStringVariable(PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID, &sczLaunchTargetElevatedId); - BalExitOnFailure1(hr, "Failed to get launch target elevated id '%ls'.", PYBA_VARIABLE_LAUNCH_TARGET_ELEVATED_ID); - } - - if (BalStringVariableExists(PYBA_VARIABLE_LAUNCH_ARGUMENTS)) { - hr = BalGetStringVariable(PYBA_VARIABLE_LAUNCH_ARGUMENTS, &sczUnformattedArguments); - BalExitOnFailure1(hr, "Failed to get launch arguments '%ls'.", PYBA_VARIABLE_LAUNCH_ARGUMENTS); - } - - if (BalStringVariableExists(PYBA_VARIABLE_LAUNCH_HIDDEN)) { - nCmdShow = SW_HIDE; - } - - if (sczLaunchTargetElevatedId && !_triedToLaunchElevated) { - _triedToLaunchElevated = TRUE; - hr = _engine->LaunchApprovedExe(_hWnd, sczLaunchTargetElevatedId, sczUnformattedArguments, 0); - if (FAILED(hr)) { - BalLogError(hr, "Failed to launch elevated target: %ls", sczLaunchTargetElevatedId); - - //try with ShelExec next time - OnClickLaunchButton(); - } - } else { - if (sczUnformattedArguments) { - hr = BalFormatString(sczUnformattedArguments, &sczArguments); - BalExitOnFailure1(hr, "Failed to format launch arguments variable: %ls", sczUnformattedArguments); - } - - hr = ShelExec(sczLaunchTarget, sczArguments, L"open", nullptr, nCmdShow, _hWnd, nullptr); - BalExitOnFailure1(hr, "Failed to launch target: %ls", sczLaunchTarget); - - ::PostMessageW(_hWnd, WM_CLOSE, 0, 0); - } - - LExit: - StrSecureZeroFreeString(sczArguments); - ReleaseStr(sczUnformattedArguments); - ReleaseStr(sczLaunchTargetElevatedId); - StrSecureZeroFreeString(sczLaunchTarget); - ReleaseStr(sczUnformattedLaunchTarget); - - return; - } - // // OnClickRestartButton - allows the restart and closes the app. @@ -3157,7 +3142,6 @@ public: _taskbarButtonCreatedMessage = UINT_MAX; _taskbarButtonOK = FALSE; _showingInternalUIThisPackage = FALSE; - _triedToLaunchElevated = FALSE; _suppressPaint = FALSE; @@ -3242,7 +3226,6 @@ private: UINT _taskbarButtonCreatedMessage; BOOL _taskbarButtonOK; BOOL _showingInternalUIThisPackage; - BOOL _triedToLaunchElevated; BOOL _suppressPaint; diff --git a/Tools/msi/bundle/bundle.ico b/Tools/msi/bundle/bundle.ico Binary files differdeleted file mode 100644 index 1ab629e..0000000 --- a/Tools/msi/bundle/bundle.ico +++ /dev/null diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs index 38307e0..c89e6ee 100644 --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -4,7 +4,7 @@ <Bundle Name="!(loc.FullProductName)" UpgradeCode="$(var.CoreUpgradeCode)" Version="$(var.Version)" - IconSourceFile="bundle.ico" + IconSourceFile="..\..\..\PC\icons\setup.ico" Manufacturer="!(loc.Manufacturer)" AboutUrl="http://www.python.org/" DisableModify="button" diff --git a/Tools/msi/common.wxs b/Tools/msi/common.wxs index 4efad65..1949e81 100644 --- a/Tools/msi/common.wxs +++ b/Tools/msi/common.wxs @@ -1,6 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Fragment> + <Property Id="ROOTREGISTRYKEY" Value="Software\Python\PythonCore" /> + </Fragment> + + <Fragment> <Property Id="REGISTRYKEY" Value="Software\Python\PythonCore\$(var.ShortVersion)$(var.PyArchExt)$(var.PyTestExt)" /> </Fragment> @@ -16,10 +20,12 @@ <Fragment> <Property Id="UpgradeTable" Value="1" /> + <?ifndef SuppressUpgradeTable ?> <Upgrade Id="$(var.UpgradeCode)"> <UpgradeVersion Property="DOWNGRADE" Minimum="$(var.Version)" IncludeMinimum="no" OnlyDetect="yes" /> <UpgradeVersion Property="UPGRADE" Minimum="$(var.UpgradeMinimumVersion)" IncludeMinimum="yes" Maximum="$(var.Version)" IncludeMaximum="no" /> </Upgrade> + <?endif ?> <?ifdef CoreUpgradeCode ?> <?if $(var.UpgradeCode)!=$(var.CoreUpgradeCode) ?> @@ -40,7 +46,7 @@ <Fragment> <!-- Include an icon for the Programs and Features dialog --> - <Icon Id="ARPIcon" SourceFile="!(bindpath.src)PC\pycon.ico" /> + <Icon Id="ARPIcon" SourceFile="!(bindpath.src)PC\icons\python.ico" /> <Property Id="ARPPRODUCTICON" Value="ARPIcon" /> <Property Id="ARPNOMODIFY" Value="1" /> <Property Id="DISABLEADVTSHORTCUTS" Value="1" /> diff --git a/Tools/msi/common_en-US.wxl_template b/Tools/msi/common_en-US.wxl_template index 8d03526..c95c271 100644 --- a/Tools/msi/common_en-US.wxl_template +++ b/Tools/msi/common_en-US.wxl_template @@ -14,4 +14,5 @@ <String Id="NoDowngrade">A newer version of !(loc.ProductName) is already installed.</String> <String Id="IncorrectCore">An incorrect version of a prerequisite package is installed. Please uninstall any other versions of !(loc.ProductName) and try installing this again.</String> <String Id="NoTargetDir">The TARGETDIR variable must be provided when invoking this installer.</String> + <String Id="ManufacturerSupportUrl">http://www.python.org/</String> </WixLocalization> diff --git a/Tools/msi/exe/exe.wixproj b/Tools/msi/exe/exe.wixproj index d26a603..24df0f5 100644 --- a/Tools/msi/exe/exe.wixproj +++ b/Tools/msi/exe/exe.wixproj @@ -14,6 +14,7 @@ <ItemGroup> <Compile Include="exe.wxs" /> <Compile Include="exe_files.wxs" /> + <Compile Include="exe_reg.wxs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="*.wxl" /> diff --git a/Tools/msi/exe/exe.wxs b/Tools/msi/exe/exe.wxs index 154cee5..03d43c6 100644 --- a/Tools/msi/exe/exe.wxs +++ b/Tools/msi/exe/exe.wxs @@ -9,6 +9,7 @@ <Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)"> <ComponentGroupRef Id="exe_python" Primary="yes" /> + <ComponentGroupRef Id="exe_reg" Primary="yes" /> <ComponentGroupRef Id="exe_txt" /> <ComponentGroupRef Id="exe_icons" /> <ComponentRef Id="OptionalFeature" /> @@ -24,7 +25,6 @@ WorkingDirectory="InstallDirectory" /> <RemoveFolder Id="Remove_MenuDir" Directory="MenuDir" On="uninstall" /> <RegistryKey Root="HKMU" Key="[REGISTRYKEY]"> - <RegistryValue Key="InstallPath\InstallGroup" Type="string" Value="!(loc.ProductName)" KeyPath="yes" /> <RegistryValue Key="InstalledFeatures" Name="Shortcuts" Type="string" Value="$(var.Version)" /> </RegistryKey> </Component> diff --git a/Tools/msi/exe/exe_d.wixproj b/Tools/msi/exe/exe_d.wixproj index 27545ca..cf085be 100644 --- a/Tools/msi/exe/exe_d.wixproj +++ b/Tools/msi/exe/exe_d.wixproj @@ -10,6 +10,7 @@ <ItemGroup> <Compile Include="exe_d.wxs" /> <Compile Include="exe_files.wxs" /> + <Compile Include="exe_reg.wxs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="*.wxl" /> diff --git a/Tools/msi/exe/exe_en-US.wxl_template b/Tools/msi/exe/exe_en-US.wxl_template index 577fbe5..1f9e290 100644 --- a/Tools/msi/exe/exe_en-US.wxl_template +++ b/Tools/msi/exe/exe_en-US.wxl_template @@ -4,4 +4,5 @@ <String Id="ShortDescriptor">executable</String> <String Id="ShortcutName">Python {{ShortVersion}} ({{Bitness}})</String> <String Id="ShortcutDescription">Launches the !(loc.ProductName) interpreter.</String> + <String Id="SupportUrl">http://www.python.org/</String> </WixLocalization> diff --git a/Tools/msi/exe/exe_files.wxs b/Tools/msi/exe/exe_files.wxs index 9e47b5d..0138587 100644 --- a/Tools/msi/exe/exe_files.wxs +++ b/Tools/msi/exe/exe_files.wxs @@ -28,6 +28,9 @@ </Component> <Component Id="pythonw.exe" Directory="InstallDirectory" Guid="$(var.PythonwExeComponentGuid)"> <File Name="pythonw.exe" KeyPath="yes" /> + <RegistryKey Root="HKMU" Key="[REGISTRYKEY]"> + <RegistryValue Key="InstallPath" Name="WindowedExecutablePath" Type="string" Value="[#pythonw.exe]" KeyPath="no" /> + </RegistryKey> </Component> <Component Id="vcruntime140.dll" Directory="InstallDirectory" Guid="*"> <File Name="vcruntime140.dll" Source="!(bindpath.redist)vcruntime140.dll" KeyPath="yes" /> @@ -66,10 +69,13 @@ <Fragment> <ComponentGroup Id="exe_icons"> <Component Id="py.ico" Directory="DLLs" Guid="*"> - <File Name="py.ico" Source="!(bindpath.src)PC\py.ico" KeyPath="yes" /> + <File Name="py.ico" Source="!(bindpath.src)PC\icons\py.ico" KeyPath="yes" /> </Component> <Component Id="pyc.ico" Directory="DLLs" Guid="*"> - <File Name="pyc.ico" Source="!(bindpath.src)PC\pyc.ico" KeyPath="yes" /> + <File Name="pyc.ico" Source="!(bindpath.src)PC\icons\pyc.ico" KeyPath="yes" /> + </Component> + <Component Id="pyd.ico" Directory="DLLs" Guid="*"> + <File Name="pyd.ico" Source="!(bindpath.src)PC\icons\pyd.ico" KeyPath="yes" /> </Component> </ComponentGroup> </Fragment> diff --git a/Tools/msi/exe/exe_pdb.wixproj b/Tools/msi/exe/exe_pdb.wixproj index 4f4c869..bf1213e 100644 --- a/Tools/msi/exe/exe_pdb.wixproj +++ b/Tools/msi/exe/exe_pdb.wixproj @@ -10,6 +10,7 @@ <ItemGroup> <Compile Include="exe_pdb.wxs" /> <Compile Include="exe_files.wxs" /> + <Compile Include="exe_reg.wxs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="*.wxl" /> diff --git a/Tools/msi/exe/exe_reg.wxs b/Tools/msi/exe/exe_reg.wxs new file mode 100644 index 0000000..4443c21 --- /dev/null +++ b/Tools/msi/exe/exe_reg.wxs @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> + <Fragment> + <PropertyRef Id="ROOTREGISTRYKEY" /> + <PropertyRef Id="REGISTRYKEY" /> + + <ComponentGroup Id="exe_reg"> + <Component Id="CommonPythonRegistration" Directory="InstallDirectory" Guid="$(var.CommonPythonRegComponentGuid)"> + <RegistryKey Root="HKMU" Key="[ROOTREGISTRYKEY]"> + <RegistryValue Name="DisplayName" Type="string" Value="!(loc.Manufacturer)" KeyPath="yes" /> + <RegistryValue Name="SupportUrl" Type="string" Value="!(loc.ManufacturerSupportUrl)" KeyPath="no" /> + </RegistryKey> + </Component> + <Component Id="PythonRegistration" Directory="InstallDirectory" Guid="$(var.PythonRegComponentGuid)"> + <RegistryKey Root="HKMU" Key="[REGISTRYKEY]"> + <RegistryValue Name="DisplayName" Type="string" Value="!(loc.ShortcutName)" KeyPath="yes" /> + <RegistryValue Name="SupportUrl" Type="string" Value="!(loc.SupportUrl)" KeyPath="no" /> + <RegistryValue Name="Version" Type="string" Value="$(var.LongVersion)" KeyPath="no" /> + <RegistryValue Name="SysVersion" Type="string" Value="$(var.ShortVersion)" KeyPath="no" /> + <RegistryValue Name="SysArchitecture" Type="string" Value="$(var.PlatformArchitecture)" KeyPath="no" /> + </RegistryKey> + </Component> + </ComponentGroup> + </Fragment> +</Wix> diff --git a/Tools/msi/launcher/launcher.wixproj b/Tools/msi/launcher/launcher.wixproj index 01a9dcb..8935ce8 100644 --- a/Tools/msi/launcher/launcher.wixproj +++ b/Tools/msi/launcher/launcher.wixproj @@ -5,7 +5,7 @@ <SchemaVersion>2.0</SchemaVersion> <OutputName>launcher</OutputName> <OutputType>Package</OutputType> - <DefineConstants>UpgradeCode=1B68A0EC-4DD3-5134-840E-73854B0863F1;$(DefineConstants)</DefineConstants> + <DefineConstants>UpgradeCode=1B68A0EC-4DD3-5134-840E-73854B0863F1;SuppressUpgradeTable=1;$(DefineConstants)</DefineConstants> <IgnoreCommonWxlTemplates>true</IgnoreCommonWxlTemplates> <SuppressICEs>ICE80</SuppressICEs> </PropertyGroup> diff --git a/Tools/msi/launcher/launcher.wxs b/Tools/msi/launcher/launcher.wxs index ebd875c..7de131a 100644 --- a/Tools/msi/launcher/launcher.wxs +++ b/Tools/msi/launcher/launcher.wxs @@ -5,7 +5,10 @@ <MediaTemplate EmbedCab="yes" CompressionLevel="high" /> <Property Id="Suppress_TARGETDIR_Check" Value="1" /> - <PropertyRef Id="ARPPRODUCTICON" /> + <Icon Id="ARPIcon" SourceFile="!(bindpath.src)PC\icons\launcher.ico" /> + <Property Id="ARPPRODUCTICON" Value="ARPIcon" /> + <Property Id="ARPNOMODIFY" Value="1" /> + <Property Id="DISABLEADVTSHORTCUTS" Value="1" /> <Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)"> <ComponentGroupRef Id="launcher_exe" Primary="yes" /> @@ -26,18 +29,21 @@ <Custom Before="SetLauncherInstallDirectoryLM" Action="SetLauncherInstallDirectoryCU">NOT Installed AND NOT ALLUSERS=1</Custom> <Custom Before="CostFinalize" Action="SetLauncherInstallDirectoryLM">NOT Installed AND ALLUSERS=1</Custom> - <RemoveExistingProducts After="InstallValidate">UPGRADE or REMOVE_350_LAUNCHER</RemoveExistingProducts> + <RemoveExistingProducts After="InstallValidate">UPGRADE or REMOVE_350_LAUNCHER or REMOVE_360A1_LAUNCHER</RemoveExistingProducts> </InstallExecuteSequence> + <!-- Upgrade all versions of the launcher --> + <Upgrade Id="$(var.UpgradeCode)"> + <UpgradeVersion Property="DOWNGRADE" Minimum="$(var.Version)" IncludeMinimum="no" OnlyDetect="yes" /> + <UpgradeVersion Property="UPGRADE" Minimum="0.0.0.0" IncludeMinimum="yes" Maximum="$(var.Version)" IncludeMaximum="no" /> + </Upgrade> <!-- Python 3.5.0 shipped with a different UpgradeCode --> <Upgrade Id="A71530B9-E89D-53DB-9C2D-C6D7551876D8"> <UpgradeVersion Minimum="0.0.0.0" Property="REMOVE_350_LAUNCHER" /> </Upgrade> <!-- Python 3.6.0a1 shipped with a different UpgradeCode --> <Upgrade Id="394750C0-7880-5A8F-999F-933965FBCFB4"> - <UpgradeVersion Maximum="$(var.Version)" Property="REMOVE_360A1_LAUNCHER" /> - <UpgradeVersion Minimum="$(var.Version)" Property="BLOCK_360A1_LAUNCHER" /> + <UpgradeVersion Minimum="0.0.0.0" Property="REMOVE_360A1_LAUNCHER" /> </Upgrade> - <Condition Message="!(loc.NoDowngrade)">Installed OR NOT BLOCK_360A1_LAUNCHER</Condition> </Product> </Wix> diff --git a/Tools/msi/launcher/launcher_en-US.wxl b/Tools/msi/launcher/launcher_en-US.wxl index e4c1aaa..a7e3827 100644 --- a/Tools/msi/launcher/launcher_en-US.wxl +++ b/Tools/msi/launcher/launcher_en-US.wxl @@ -11,6 +11,7 @@ <String Id="PythonFileDescription">Python File</String> <String Id="PythonNoConFileDescription">Python File (no console)</String> <String Id="PythonCompiledFileDescription">Compiled Python File</String> + <String Id="PythonExtensionDescription">Python Extension Module</String> <String Id="PythonArchiveFileDescription">Python Zip Application File</String> <String Id="PythonNoConArchiveFileDescription">Python Zip Application File (no console)</String> </WixLocalization> diff --git a/Tools/msi/launcher/launcher_reg.wxs b/Tools/msi/launcher/launcher_reg.wxs index 981961a..dace97e 100644 --- a/Tools/msi/launcher/launcher_reg.wxs +++ b/Tools/msi/launcher/launcher_reg.wxs @@ -27,14 +27,18 @@ </ProgId> <RegistryValue Root="HKCR" Key="Python.CompiledFile\shellex\DropHandler" Value="{BEA218D2-6950-497B-9434-61683EC065FE}" Type="string" /> - <ProgId Id="Python.ArchiveFile" Description="!(loc.PythonArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1"> + <ProgId Id="Python.Extension" Description="!(loc.PythonExtensionDescription)" Advertise="no" Icon="py.exe" IconIndex="3"> + <Extension Id="pyd" /> + </ProgId> + + <ProgId Id="Python.ArchiveFile" Description="!(loc.PythonArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="5"> <Extension Id="pyz" ContentType="application/x-zip-compressed"> <Verb Id="open" TargetFile="py.exe" Argument=""%L" %*" /> </Extension> </ProgId> <RegistryValue Root="HKCR" Key="Python.ArchiveFile\shellex\DropHandler" Value="{BEA218D2-6950-497B-9434-61683EC065FE}" Type="string" /> - <ProgId Id="Python.NoConArchiveFile" Description="!(loc.PythonNoConArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="1"> + <ProgId Id="Python.NoConArchiveFile" Description="!(loc.PythonNoConArchiveFileDescription)" Advertise="no" Icon="py.exe" IconIndex="5"> <Extension Id="pyzw" ContentType="application/x-zip-compressed"> <Verb Id="open" TargetFile="pyw.exe" Argument=""%L" %*" /> </Extension> diff --git a/Tools/msi/lib/lib_files.wxs b/Tools/msi/lib/lib_files.wxs index fa79a8d..804ab01 100644 --- a/Tools/msi/lib/lib_files.wxs +++ b/Tools/msi/lib/lib_files.wxs @@ -64,16 +64,10 @@ <RegistryValue Key="PythonPath" Type="string" Value="[Lib];[DLLs]" /> </RegistryKey> </Component> - <Component Id="Lib_site_packages_README" Directory="Lib_site_packages" Guid="*"> - <File Id="Lib_site_packages_README" Name="README.txt" Source="!(bindpath.src)Lib\site-packages\README" KeyPath="yes" /> - </Component> <Component Id="Lib2to3_pickle_remove" Directory="Lib_lib2to3" Guid="$(var.RemoveLib2to3PickleComponentGuid)"> <RemoveFile Id="Lib2to3_pickle_remove_files" Name="*.pickle" On="uninstall" /> <RemoveFolder Id="Lib2to3_pickle_remove_folder" On="uninstall" /> </Component> </ComponentGroup> - <DirectoryRef Id="Lib"> - <Directory Id="Lib_site_packages" Name="site-packages" /> - </DirectoryRef> </Fragment> </Wix> diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py index 0e8a4a6..ebb1766 100644 --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -46,6 +46,10 @@ EXCLUDE_FILE_FROM_LIBS = { 'python3stub', } +EXCLUDED_FILES = { + 'pyshellext', +} + def is_not_debug(p): if DEBUG_RE.search(p.name): return False @@ -53,7 +57,7 @@ def is_not_debug(p): if TKTCL_RE.search(p.name): return False - return p.stem.lower() not in DEBUG_FILES + return p.stem.lower() not in DEBUG_FILES and p.stem.lower() not in EXCLUDED_FILES def is_not_debug_or_python(p): return is_not_debug(p) and not PYTHON_DLL_RE.search(p.name) @@ -63,8 +67,6 @@ def include_in_lib(p): if p.is_dir(): if name in EXCLUDE_FROM_LIBRARY: return False - if name.startswith('plat-'): - return False if name == 'test' and p.parts[-2].lower() == 'lib': return False if name in {'test', 'tests'} and p.parts[-3].lower() == 'lib': @@ -89,25 +91,27 @@ def include_in_tools(p): return p.suffix.lower() in {'.py', '.pyw', '.txt'} +BASE_NAME = 'python{0.major}{0.minor}'.format(sys.version_info) + FULL_LAYOUT = [ - ('/', '$build', 'python.exe', is_not_debug), - ('/', '$build', 'pythonw.exe', is_not_debug), - ('/', '$build', 'python{0.major}.dll'.format(sys.version_info), is_not_debug), - ('/', '$build', 'python{0.major}{0.minor}.dll'.format(sys.version_info), is_not_debug), - ('DLLs/', '$build', '*.pyd', is_not_debug), - ('DLLs/', '$build', '*.dll', is_not_debug_or_python), + ('/', 'PCBuild/$arch', 'python.exe', is_not_debug), + ('/', 'PCBuild/$arch', 'pythonw.exe', is_not_debug), + ('/', 'PCBuild/$arch', 'python{}.dll'.format(sys.version_info.major), is_not_debug), + ('/', 'PCBuild/$arch', '{}.dll'.format(BASE_NAME), is_not_debug), + ('DLLs/', 'PCBuild/$arch', '*.pyd', is_not_debug), + ('DLLs/', 'PCBuild/$arch', '*.dll', is_not_debug_or_python), ('include/', 'include', '*.h', None), ('include/', 'PC', 'pyconfig.h', None), ('Lib/', 'Lib', '**/*', include_in_lib), - ('libs/', '$build', '*.lib', include_in_libs), + ('libs/', 'PCBuild/$arch', '*.lib', include_in_libs), ('Tools/', 'Tools', '**/*', include_in_tools), ] EMBED_LAYOUT = [ - ('/', '$build', 'python*.exe', is_not_debug), - ('/', '$build', '*.pyd', is_not_debug), - ('/', '$build', '*.dll', is_not_debug), - ('python{0.major}{0.minor}.zip'.format(sys.version_info), 'Lib', '**/*', include_in_lib), + ('/', 'PCBuild/$arch', 'python*.exe', is_not_debug), + ('/', 'PCBuild/$arch', '*.pyd', is_not_debug), + ('/', 'PCBuild/$arch', '*.dll', is_not_debug), + ('{}.zip'.format(BASE_NAME), 'Lib', '**/*', include_in_lib), ] if os.getenv('DOC_FILENAME'): @@ -168,18 +172,18 @@ def rglob(root, pattern, condition): def main(): parser = argparse.ArgumentParser() parser.add_argument('-s', '--source', metavar='dir', help='The directory containing the repository root', type=Path) - parser.add_argument('-o', '--out', metavar='file', help='The name of the output archive', type=Path, default=None) + parser.add_argument('-o', '--out', metavar='file', help='The name of the output self-extracting archive', type=Path, default=None) parser.add_argument('-t', '--temp', metavar='dir', help='A directory to temporarily extract files into', type=Path, default=None) parser.add_argument('-e', '--embed', help='Create an embedding layout', action='store_true', default=False) - parser.add_argument('-b', '--build', help='Specify the build directory', type=Path) + parser.add_argument('-a', '--arch', help='Specify the architecture to use (win32/amd64)', type=str, default="win32") ns = parser.parse_args() source = ns.source or (Path(__file__).resolve().parent.parent.parent) out = ns.out - build = ns.build + arch = ns.arch assert isinstance(source, Path) assert not out or isinstance(out, Path) - assert isinstance(build, Path) + assert isinstance(arch, str) if ns.temp: temp = ns.temp @@ -202,15 +206,17 @@ def main(): try: for t, s, p, c in layout: - if s == '$build': - s = build - else: - s = source / s + s = source / s.replace("$arch", arch) copied = copy_to_layout(temp / t.rstrip('/'), rglob(s, p, c)) print('Copied {} files'.format(copied)) - with open(str(temp / 'pyvenv.cfg'), 'w') as f: - print('applocal = true', file=f) + if ns.embed: + with open(str(temp / (BASE_NAME + '._pth')), 'w') as f: + print(BASE_NAME + '.zip', file=f) + print('.', file=f) + print('', file=f) + print('# Uncomment to run site.main() automatically', file=f) + print('#import site', file=f) if out: total = copy_to_layout(out, rglob(temp, '**/*', None)) diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props index 0cf7c77..745fc54 100644 --- a/Tools/msi/msi.props +++ b/Tools/msi/msi.props @@ -69,6 +69,8 @@ <PropertyGroup> <Bitness>32-bit</Bitness> <Bitness Condition="$(Platform) == 'x64'">64-bit</Bitness> + <PlatformArchitecture>32bit</PlatformArchitecture> + <PlatformArchitecture Condition="$(Platform) == 'x64'">64bit</PlatformArchitecture> <DefineConstants> $(DefineConstants); Version=$(InstallerVersion); @@ -79,6 +81,7 @@ UpgradeMinimumVersion=$(MajorVersionNumber).$(MinorVersionNumber).0.0; NextMajorVersionNumber=$(MajorVersionNumber).$([msbuild]::Add($(MinorVersionNumber), 1)).0.0; Bitness=$(Bitness); + PlatformArchitecture=$(PlatformArchitecture); PyDebugExt=$(PyDebugExt); PyArchExt=$(PyArchExt); PyTestExt=$(PyTestExt); @@ -155,6 +158,12 @@ <_Uuid Include="RemoveLib2to3PickleComponentGuid"> <Uri>lib2to3/pickles</Uri> </_Uuid> + <_Uuid Include="CommonPythonRegComponentGuid"> + <Uri>registry</Uri> + </_Uuid> + <_Uuid Include="PythonRegComponentGuid"> + <Uri>registry/$(OutputName)</Uri> + </_Uuid> </ItemGroup> <Target Name="_GenerateGuids" AfterTargets="PrepareForBuild" Condition="$(TargetName) != 'launcher'"> <PropertyGroup> |