From cb0b78a070ea3b704416e74f64046178ae0dff3e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 7 Dec 2018 12:57:43 +0100 Subject: [PATCH] Revert "bpo-34977: Add Windows App Store package (GH-10245)" (GH-11019) This reverts commit 468a15aaf9206448a744fc5eab3fc21f51966aad. --- .azure-pipelines/windows-appx-test.yml | 65 -- .gitattributes | 1 - Doc/make.bat | 2 - Lib/test/test_pathlib.py | 2 +- Lib/test/test_venv.py | 1 - Lib/venv/__init__.py | 49 +- .../2018-10-30-13-39-17.bpo-34977.0l7_QV.rst | 1 - PC/classicAppCompat.can.xml | 1 - PC/classicAppCompat.cat | Bin 10984 -> 0 bytes PC/classicAppCompat.sccd | 28 - PC/getpathp.c | 8 +- PC/icons/pythonwx150.png | Bin 8187 -> 0 bytes PC/icons/pythonwx44.png | Bin 2232 -> 0 bytes PC/icons/pythonx150.png | Bin 8271 -> 0 bytes PC/icons/pythonx44.png | Bin 2178 -> 0 bytes PC/icons/pythonx50.png | Bin 2190 -> 0 bytes PC/launcher.c | 223 +------ PC/layout/__init__.py | 0 PC/layout/__main__.py | 14 - PC/layout/main.py | 612 ------------------ PC/layout/support/__init__.py | 0 PC/layout/support/appxmanifest.py | 487 -------------- PC/layout/support/catalog.py | 44 -- PC/layout/support/constants.py | 28 - .../distutils.command.bdist_wininst.py | 25 - PC/layout/support/filesets.py | 100 --- PC/layout/support/logging.py | 93 --- PC/layout/support/options.py | 122 ---- PC/layout/support/pip.py | 79 --- PC/layout/support/props.py | 110 ---- PC/pylauncher.rc | 6 - PC/python_uwp.cpp | 226 ------- PC/store_info.txt | 146 ----- PCbuild/_tkinter.vcxproj | 6 - PCbuild/find_msbuild.bat | 10 - PCbuild/pcbuild.proj | 3 - PCbuild/pcbuild.sln | 72 --- PCbuild/python.props | 3 +- PCbuild/python_uwp.vcxproj | 86 --- PCbuild/pythoncore.vcxproj | 15 - PCbuild/pythonw_uwp.vcxproj | 86 --- PCbuild/venvlauncher.vcxproj | 85 --- PCbuild/venvwlauncher.vcxproj | 85 --- Tools/msi/buildrelease.bat | 13 +- Tools/msi/make_appx.ps1 | 71 -- Tools/msi/make_cat.ps1 | 34 - Tools/msi/make_zip.proj | 9 +- Tools/msi/make_zip.py | 250 +++++++ Tools/msi/sdktools.psm1 | 43 -- Tools/msi/sign_build.ps1 | 34 - Tools/nuget/make_pkg.proj | 38 +- .../support => Tools/nuget}/python.props | 0 52 files changed, 331 insertions(+), 3085 deletions(-) delete mode 100644 .azure-pipelines/windows-appx-test.yml delete mode 100644 Misc/NEWS.d/next/Windows/2018-10-30-13-39-17.bpo-34977.0l7_QV.rst delete mode 100644 PC/classicAppCompat.can.xml delete mode 100644 PC/classicAppCompat.cat delete mode 100644 PC/classicAppCompat.sccd delete mode 100644 PC/icons/pythonwx150.png delete mode 100644 PC/icons/pythonwx44.png delete mode 100644 PC/icons/pythonx150.png delete mode 100644 PC/icons/pythonx44.png delete mode 100644 PC/icons/pythonx50.png delete mode 100644 PC/layout/__init__.py delete mode 100644 PC/layout/__main__.py delete mode 100644 PC/layout/main.py delete mode 100644 PC/layout/support/__init__.py delete mode 100644 PC/layout/support/appxmanifest.py delete mode 100644 PC/layout/support/catalog.py delete mode 100644 PC/layout/support/constants.py delete mode 100644 PC/layout/support/distutils.command.bdist_wininst.py delete mode 100644 PC/layout/support/filesets.py delete mode 100644 PC/layout/support/logging.py delete mode 100644 PC/layout/support/options.py delete mode 100644 PC/layout/support/pip.py delete mode 100644 PC/layout/support/props.py delete mode 100644 PC/python_uwp.cpp delete mode 100644 PC/store_info.txt delete mode 100644 PCbuild/python_uwp.vcxproj delete mode 100644 PCbuild/pythonw_uwp.vcxproj delete mode 100644 PCbuild/venvlauncher.vcxproj delete mode 100644 PCbuild/venvwlauncher.vcxproj delete mode 100644 Tools/msi/make_appx.ps1 delete mode 100644 Tools/msi/make_cat.ps1 create mode 100644 Tools/msi/make_zip.py delete mode 100644 Tools/msi/sdktools.psm1 delete mode 100644 Tools/msi/sign_build.ps1 rename {PC/layout/support => Tools/nuget}/python.props (100%) diff --git a/.azure-pipelines/windows-appx-test.yml b/.azure-pipelines/windows-appx-test.yml deleted file mode 100644 index 9840c0a1221..00000000000 --- a/.azure-pipelines/windows-appx-test.yml +++ /dev/null @@ -1,65 +0,0 @@ -jobs: -- job: Prebuild - displayName: Pre-build checks - - pool: - vmImage: ubuntu-16.04 - - steps: - - template: ./prebuild-checks.yml - - -- job: Windows_Appx_Tests - displayName: Windows Appx Tests - dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) - - pool: - vmImage: vs2017-win2016 - - strategy: - matrix: - win64: - arch: amd64 - buildOpt: '-p x64' - testRunTitle: '$(Build.SourceBranchName)-win64-appx' - testRunPlatform: win64 - maxParallel: 2 - - steps: - - checkout: self - clean: true - fetchDepth: 5 - - - powershell: | - # Relocate build outputs outside of source directory to make cleaning faster - Write-Host '##vso[task.setvariable variable=Py_IntDir]$(Build.BinariesDirectory)\obj' - # UNDONE: Do not build to a different directory because of broken tests - Write-Host '##vso[task.setvariable variable=Py_OutDir]$(Build.SourcesDirectory)\PCbuild' - Write-Host '##vso[task.setvariable variable=EXTERNAL_DIR]$(Build.BinariesDirectory)\externals' - displayName: Update build locations - - - script: PCbuild\build.bat -e $(buildOpt) - displayName: 'Build CPython' - - - script: python.bat PC\layout -vv -s "$(Build.SourcesDirectory)" -b "$(Py_OutDir)\$(arch)" -t "$(Py_IntDir)\layout-tmp-$(arch)" --copy "$(Py_IntDir)\layout-$(arch)" --precompile --preset-appx --include-tests - displayName: 'Create APPX layout' - - - script: .\python.exe -m test.pythoninfo - workingDirectory: $(Py_IntDir)\layout-$(arch) - displayName: 'Display build info' - - - script: .\python.exe -m test -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 --junit-xml="$(Build.BinariesDirectory)\test-results.xml" --tempdir "$(Py_IntDir)\tmp-$(arch)" - workingDirectory: $(Py_IntDir)\layout-$(arch) - displayName: 'Tests' - env: - PREFIX: $(Py_IntDir)\layout-$(arch) - - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - inputs: - testResultsFiles: '$(Build.BinariesDirectory)\test-results.xml' - mergeTestResults: true - testRunTitle: $(testRunTitle) - platform: $(testRunPlatform) - condition: succeededOrFailed() diff --git a/.gitattributes b/.gitattributes index 16237bb2b3a..4a487c3c2a1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -19,7 +19,6 @@ # Specific binary files Lib/test/sndhdrdata/sndhdr.* binary -PC/classicAppCompat.* binary # Text files that should not be subject to eol conversion Lib/test/cjkencodings/* -text diff --git a/Doc/make.bat b/Doc/make.bat index a8b32375810..d28dae78e86 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -117,12 +117,10 @@ if not exist "%BUILDDIR%" mkdir "%BUILDDIR%" if exist ..\Misc\NEWS ( echo.Copying Misc\NEWS to build\NEWS - if not exist build mkdir build copy ..\Misc\NEWS build\NEWS > nul ) else if exist ..\Misc\NEWS.D ( if defined BLURB ( echo.Merging Misc/NEWS with %BLURB% - if not exist build mkdir build %BLURB% merge -f build\NEWS ) else ( echo.No Misc/NEWS file and Blurb is not available. diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index d3fd4bd9e6b..876eecccfd5 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1521,7 +1521,7 @@ class _BasePathTest(object): # resolves to 'dirB/..' first before resolving to parent of dirB. self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False) # Now create absolute symlinks - d = support._longpath(tempfile.mkdtemp(suffix='-dirD', dir=os.getcwd())) + d = support._longpath(tempfile.mkdtemp(suffix='-dirD')) self.addCleanup(support.rmtree, d) os.symlink(os.path.join(d), join('dirA', 'linkX')) os.symlink(join('dirB'), os.path.join(d, 'linkY')) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 22a3b78852f..461fe7afd21 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -243,7 +243,6 @@ class BasicTest(BaseTest): self.assertIn('include-system-site-packages = %s\n' % s, data) @unittest.skipUnless(can_symlink(), 'Needs symlinks') - @unittest.skipIf(os.name == 'nt', 'Symlinks are never used on Windows') def test_symlinking(self): """ Test symlinking works as expected diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 5438b0d4e50..043420897e4 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -64,11 +64,10 @@ class EnvBuilder: self.system_site_packages = False self.create_configuration(context) self.setup_python(context) - if not self.upgrade: - self.setup_scripts(context) if self.with_pip: self._setup_pip(context) if not self.upgrade: + self.setup_scripts(context) self.post_setup(context) if true_system_site_packages: # We had set it to False before, now @@ -159,6 +158,14 @@ class EnvBuilder: f.write('include-system-site-packages = %s\n' % incl) f.write('version = %d.%d.%d\n' % sys.version_info[:3]) + if os.name == 'nt': + def include_binary(self, f): + if f.endswith(('.pyd', '.dll')): + result = True + else: + result = f.startswith('python') and f.endswith('.exe') + return result + def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): """ Try symlinking a file, and if that fails, fall back to copying. @@ -188,9 +195,9 @@ class EnvBuilder: binpath = context.bin_path path = context.env_exe copier = self.symlink_or_copy + copier(context.executable, path) dirname = context.python_dir if os.name != 'nt': - copier(context.executable, path) if not os.path.islink(path): os.chmod(path, 0o755) for suffix in ('python', 'python3'): @@ -202,22 +209,26 @@ class EnvBuilder: if not os.path.islink(path): os.chmod(path, 0o755) else: - # For normal cases, the venvlauncher will be copied from - # our scripts folder. For builds, we need to copy it - # manually. + # See bpo-34011. When using a proper install, we should only need to + # copy the top-level of DLLs. + include = self.include_binary + files = [f for f in os.listdir(dirname) if include(f)] + for f in files: + src = os.path.join(dirname, f) + dst = os.path.join(binpath, f) + if dst != context.env_exe: # already done, above + copier(src, dst) + + # When creating from a build directory, we continue to copy all files. if sysconfig.is_python_build(True): - suffix = '.exe' - if context.python_exe.lower().endswith('_d.exe'): - suffix = '_d.exe' - - src = os.path.join(dirname, "venvlauncher" + suffix) - dst = os.path.join(binpath, context.python_exe) - copier(src, dst) - - src = os.path.join(dirname, "venvwlauncher" + suffix) - dst = os.path.join(binpath, "pythonw" + suffix) - copier(src, dst) - + subdir = 'DLLs' + dirname = os.path.join(dirname, subdir) + if os.path.isdir(dirname): + files = [f for f in os.listdir(dirname) if include(f)] + for f in files: + src = os.path.join(dirname, f) + dst = os.path.join(binpath, f) + copier(src, dst) # copy init.tcl over for root, dirs, files in os.walk(context.python_dir): if 'init.tcl' in files: @@ -315,7 +326,7 @@ class EnvBuilder: dstfile = os.path.join(dstdir, f) with open(srcfile, 'rb') as f: data = f.read() - if not srcfile.endswith(('.exe', '.pdb')): + if not srcfile.endswith('.exe'): try: data = data.decode('utf-8') data = self.replace_variables(data, context) diff --git a/Misc/NEWS.d/next/Windows/2018-10-30-13-39-17.bpo-34977.0l7_QV.rst b/Misc/NEWS.d/next/Windows/2018-10-30-13-39-17.bpo-34977.0l7_QV.rst deleted file mode 100644 index 8e1a4ba8488..00000000000 --- a/Misc/NEWS.d/next/Windows/2018-10-30-13-39-17.bpo-34977.0l7_QV.rst +++ /dev/null @@ -1 +0,0 @@ -Adds support for building a Windows App Store package diff --git a/PC/classicAppCompat.can.xml b/PC/classicAppCompat.can.xml deleted file mode 100644 index f00475c8da3..00000000000 --- a/PC/classicAppCompat.can.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/PC/classicAppCompat.cat b/PC/classicAppCompat.cat deleted file mode 100644 index 3d213596accffa255e1443126228f7ab1bb2899c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10984 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 M - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 diff --git a/PC/getpathp.c b/PC/getpathp.c index 76d3a081b36..35c31bf29bd 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -536,16 +536,10 @@ static _PyInitError get_program_full_path(const _PyCoreConfig *core_config, PyCalculatePath *calculate, _PyPathConfig *config) { - const wchar_t *pyvenv_launcher; wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); - /* The launcher may need to force the executable path to a - * different environment, so override it here. */ - pyvenv_launcher = _wgetenv(L"__PYVENV_LAUNCHER__"); - if (pyvenv_launcher && pyvenv_launcher[0]) { - wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher); - } else if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { + if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { /* GetModuleFileName should never fail when passed NULL */ return _Py_INIT_ERR("Cannot determine program path"); } diff --git a/PC/icons/pythonwx150.png b/PC/icons/pythonwx150.png deleted file mode 100644 index 4c3eb316739c7989cabaad145e278b17741afe92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8187 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 xGE;KqWvT diff --git a/PC/icons/pythonwx44.png b/PC/icons/pythonwx44.png deleted file mode 100644 index e3b32a871f90a747f46d0732b5bdd0cfddebb448..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2232 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 Ef?z!-4*&oF diff --git a/PC/icons/pythonx50.png b/PC/icons/pythonx50.png deleted file mode 100644 index 7cc3aecd0242b9670e3633faeb10201140793f83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2190 zcmV;92yyp`P)N2bZe?^J zG%hhNG!sB*!~g&Y3`s;mRA@u(n0ru^*BQp0PCAox(wVl?=}iCYKk0NPooO3yHN=3o zAdo0gqGFTQAhgw0yo4AV1Oyh4 z+tcTq?<}(HGU9q+|KOc@X8Gj%&iDTIec$IC95)tY@g!nH?q$m4YMK;dGbmP^ZX$(nkRt4iBG z0s{k0{{H@$K7G1NYw_a69U@niwtb9&JYkK2xSGa5Tul!Q;y&LU6JjQeNRzirwt3m( z)B}Tfyyk%^>!*xJZaO!cmpx96&B&vYudgqnqN0$Mm4(8>LR3~(qN=KDK;pWns0i8F z+1RsZ4}5%l9Ii8}Akop$=;-J`XLm31D$Pj!rV0nMZX!}&fUPNc*qw152R<*v$uG;0 zU(tZxzJ8d^W`u-<*sV2cAmQQR5OMPBD$L(^5wmw^!876uyt3mQW^Vf&Gs5+l_ODOj zu{jMdZ%o0|4X5C@`wVWF8qnR{4V_MBv)+Rb`&L=jZ1<$fJ^oUHT%-jyR8t zhB|qjRaoNyA{lN9;?M6SV$zzUSaUc_-X9PUFtFaJg6v2yfalIkct>PnW&D@$+{Ts) z%OC{jLO^UF#CwEz*9!45Cay}rszc}H^DYCjJ?#c&Z9j{dTR&qZ#BdWr4Yw8I#dnh= z#AF3AAvhkv2Q%gKPaGsTI9Toj_4W1W?d_FGh_H0^pxJU4&Fw;6Hae13q(Ovy!nq*C zY7OFr6>(Vk;W@Q}7Q)52cK@YIml}EbGnKk+3Ql-A1hAX~)si+lMpxHCUc- z6?67v-`8f{-qRdPgE)pstB*>E@hgttPs?MmBIYc=g)6}AcQn<}9*7jEX$9Nk)kvS4VIFx{xB_Ossve{%Cn-vZ< zaTOs}9>EI=!Um*n4e)(1A#^~^KY{OpfR+pa(nI}9A!y<3jD&@S$^Kn;B99OkGzdDB z81A7E(xHUS+BuYf;9LxX5Lz4i1<-zx5Gx6>oB;m-s+R({mhhTYVGtxhA!y+&NOE#A zx;YzSCT8zCFKyPwp+;b{8bq9&i@_j?*#$uJC#=FUtqRovg!mg!^(Ij1&-Q8)Acqx# z7S4j?=jWrmzLgN1i=hyMY*rg?$2Kb*YAA&N&J=Wa(VS}8Qq_S3c$)x!1x$Y-#6qCL z59lZmL!YM*v~U*0WHQMUt>;ebaDS#8D#M{e`Glup(e6*Na927O>`a5-jugz_b_(;h zCQB_Mz=4db=T1UWEvv9twUVkr*=sFtbhiKvo9!W_t*X6YxPg{cm`8}Ygm{$@ zUWAwh7}KLQJD((6zcmYn@aGS~v?58X77=cBEcY4rObzi8%(g04;O?V$cpPtMGUGfvy-d z(6W_86<#3(lQ((*#Z!6z2Kios1Ste9oCWdr_C{M<8;Wk3Sq*!eP0T4K$T3v~2Rror z2D)T60aPm)+zIg#<;E&s6A)e0FBF0n0)*;ax^!vBgG#U0%cE`_PqNlCl=UE(m_rw8 z`Plh^mQ`RY8CV4YAXFP+t;Qjh{=FbXWKd90f-}c?h8GfK^HuCo;2t(5_bCwztDORxI=s?nggX@cf;%VyF>eY`Y_^zk; zlIN)Bh2-1K{HC26=n(lh*O{Z%`W-)is$TVELuS&*RvF1aSFq)pd2}~%mc%UF19@I8 zH+sP&x?pDik7S@*zmkdLZnXwd&9-B3jo+%}MlYB|0ouP-RTyT6w%Tgl0g*Oa@w5ig zlp-L6#Xh5!8@*r>>=Q;K2j0;RZFpHr+A0J8&03BA9sv@smKxn4!jG5?zhZ`k$CdAB zw>LS|)`7Nx;I)Z1-Eu+R&U4gtemMT$lFfKR&CLaIFxDF-dc)d0k_(d(`^+d Q0000007*qoM6N<$g6^^h%K!iX diff --git a/PC/launcher.c b/PC/launcher.c index 4c620dab7c0..2c2da76f614 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -28,7 +28,7 @@ #define RC_NO_PYTHON 103 #define RC_NO_MEMORY 104 /* - * SCRIPT_WRAPPER is used to choose one of the variants of an executable built + * SCRIPT_WRAPPER is used to choose between two variants of an executable built * from this source file. If not defined, the PEP 397 Python launcher is built; * if defined, a script launcher of the type used by setuptools is built, which * looks for a script name related to the executable name and runs that script @@ -40,15 +40,6 @@ #if defined(SCRIPT_WRAPPER) #define RC_NO_SCRIPT 105 #endif -/* - * VENV_REDIRECT is used to choose the variant that looks for an adjacent or - * one-level-higher pyvenv.cfg, and uses its "home" property to locate and - * launch the original python.exe. - */ -#if defined(VENV_REDIRECT) -#define RC_NO_VENV_CFG 106 -#define RC_BAD_VENV_CFG 107 -#endif /* Just for now - static definition */ @@ -106,7 +97,7 @@ error(int rc, wchar_t * format, ... ) #if !defined(_WINDOWS) fwprintf(stderr, L"%ls\n", message); #else - MessageBoxW(NULL, message, L"Python Launcher is sorry to say ...", + MessageBox(NULL, message, TEXT("Python Launcher is sorry to say ..."), MB_OK); #endif exit(rc); @@ -140,17 +131,6 @@ static wchar_t * get_env(wchar_t * key) return buf; } -#if defined(_DEBUG) -#if defined(_WINDOWS) - -#define PYTHON_EXECUTABLE L"pythonw_d.exe" - -#else - -#define PYTHON_EXECUTABLE L"python_d.exe" - -#endif -#else #if defined(_WINDOWS) #define PYTHON_EXECUTABLE L"pythonw.exe" @@ -159,7 +139,6 @@ static wchar_t * get_env(wchar_t * key) #define PYTHON_EXECUTABLE L"python.exe" -#endif #endif #define MAX_VERSION_SIZE 4 @@ -1478,87 +1457,6 @@ show_python_list(wchar_t ** argv) return FALSE; /* If this has been called we cannot continue */ } -#if defined(VENV_REDIRECT) - -static int -find_home_value(const char *buffer, const char **start, DWORD *length) -{ - for (const char *s = strstr(buffer, "home"); s; s = strstr(s + 1, "\nhome")) { - if (*s == '\n') { - ++s; - } - for (int i = 4; i > 0 && *s; --i, ++s); - - while (*s && iswspace(*s)) { - ++s; - } - if (*s != L'=') { - continue; - } - - do { - ++s; - } while (*s && iswspace(*s)); - - *start = s; - char *nl = strchr(s, '\n'); - if (nl) { - *length = (DWORD)((ptrdiff_t)nl - (ptrdiff_t)s); - } else { - *length = (DWORD)strlen(s); - } - return 1; - } - return 0; -} -#endif - -static wchar_t * -wcsdup_pad(const wchar_t *s, int padding, int *newlen) -{ - size_t len = wcslen(s); - len += 1 + padding; - wchar_t *r = (wchar_t *)malloc(len * sizeof(wchar_t)); - if (!r) { - return NULL; - } - if (wcscpy_s(r, len, s)) { - free(r); - return NULL; - } - *newlen = len < MAXINT ? (int)len : MAXINT; - return r; -} - -static wchar_t * -get_process_name() -{ - DWORD bufferLen = MAX_PATH; - DWORD len = bufferLen; - wchar_t *r = NULL; - - while (!r) { - r = (wchar_t *)malloc(bufferLen * sizeof(wchar_t)); - if (!r) { - error(RC_NO_MEMORY, L"out of memory"); - return NULL; - } - len = GetModuleFileNameW(NULL, r, bufferLen); - if (len == 0) { - free(r); - error(0, L"Failed to get module name"); - return NULL; - } else if (len == bufferLen && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - free(r); - r = NULL; - bufferLen *= 2; - } - } - - return r; -} - static int process(int argc, wchar_t ** argv) { @@ -1566,27 +1464,21 @@ process(int argc, wchar_t ** argv) wchar_t * command; wchar_t * executable; wchar_t * p; - wchar_t * argv0; int rc = 0; + size_t plen; INSTALLED_PYTHON * ip; BOOL valid; DWORD size, attrs; + HRESULT hr; wchar_t message[MSGSIZE]; void * version_data; VS_FIXEDFILEINFO * file_info; UINT block_size; -#if defined(VENV_REDIRECT) - wchar_t * venv_cfg_path; + int index; +#if defined(SCRIPT_WRAPPER) int newlen; -#elif defined(SCRIPT_WRAPPER) wchar_t * newcommand; wchar_t * av[2]; - int newlen; - HRESULT hr; - int index; -#else - HRESULT hr; - int index; #endif setvbuf(stderr, (char *)NULL, _IONBF, 0); @@ -1604,7 +1496,6 @@ process(int argc, wchar_t ** argv) #else debug(L"launcher executable: Console\n"); #endif -#if !defined(VENV_REDIRECT) /* Get the local appdata folder (non-roaming) */ hr = SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appdata_ini_path); @@ -1613,7 +1504,9 @@ process(int argc, wchar_t ** argv) appdata_ini_path[0] = L'\0'; } else { - wcsncat_s(appdata_ini_path, MAX_PATH, L"\\py.ini", _TRUNCATE); + plen = wcslen(appdata_ini_path); + p = &appdata_ini_path[plen]; + wcsncpy_s(p, MAX_PATH - plen, L"\\py.ini", _TRUNCATE); attrs = GetFileAttributesW(appdata_ini_path); if (attrs == INVALID_FILE_ATTRIBUTES) { debug(L"File '%ls' non-existent\n", appdata_ini_path); @@ -1622,9 +1515,8 @@ process(int argc, wchar_t ** argv) debug(L"Using local configuration file '%ls'\n", appdata_ini_path); } } -#endif - argv0 = get_process_name(); - size = GetFileVersionInfoSizeW(argv0, &size); + plen = GetModuleFileNameW(NULL, launcher_ini_path, MAX_PATH); + size = GetFileVersionInfoSizeW(launcher_ini_path, &size); if (size == 0) { winerror(GetLastError(), message, MSGSIZE); debug(L"GetFileVersionInfoSize failed: %ls\n", message); @@ -1632,7 +1524,7 @@ process(int argc, wchar_t ** argv) else { version_data = malloc(size); if (version_data) { - valid = GetFileVersionInfoW(argv0, 0, size, + valid = GetFileVersionInfoW(launcher_ini_path, 0, size, version_data); if (!valid) debug(L"GetFileVersionInfo failed: %X\n", GetLastError()); @@ -1649,51 +1541,15 @@ process(int argc, wchar_t ** argv) free(version_data); } } - -#if defined(VENV_REDIRECT) - /* Allocate some extra space for new filenames */ - venv_cfg_path = wcsdup_pad(argv0, 32, &newlen); - if (!venv_cfg_path) { - error(RC_NO_MEMORY, L"Failed to copy module name"); - } - p = wcsrchr(venv_cfg_path, L'\\'); - - if (p == NULL) { - error(RC_NO_VENV_CFG, L"No pyvenv.cfg file"); - } - p[0] = L'\0'; - wcscat_s(venv_cfg_path, newlen, L"\\pyvenv.cfg"); - attrs = GetFileAttributesW(venv_cfg_path); - if (attrs == INVALID_FILE_ATTRIBUTES) { - debug(L"File '%ls' non-existent\n", venv_cfg_path); - p[0] = '\0'; - p = wcsrchr(venv_cfg_path, L'\\'); - if (p != NULL) { - p[0] = '\0'; - wcscat_s(venv_cfg_path, newlen, L"\\pyvenv.cfg"); - attrs = GetFileAttributesW(venv_cfg_path); - if (attrs == INVALID_FILE_ATTRIBUTES) { - debug(L"File '%ls' non-existent\n", venv_cfg_path); - error(RC_NO_VENV_CFG, L"No pyvenv.cfg file"); - } - } - } - debug(L"Using venv configuration file '%ls'\n", venv_cfg_path); -#else - /* Allocate some extra space for new filenames */ - if (wcscpy_s(launcher_ini_path, MAX_PATH, argv0)) { - error(RC_NO_MEMORY, L"Failed to copy module name"); - } p = wcsrchr(launcher_ini_path, L'\\'); - if (p == NULL) { debug(L"GetModuleFileNameW returned value has no backslash: %ls\n", launcher_ini_path); launcher_ini_path[0] = L'\0'; } else { - p[0] = L'\0'; - wcscat_s(launcher_ini_path, MAX_PATH, L"\\py.ini"); + wcsncpy_s(p, MAX_PATH - (p - launcher_ini_path), L"\\py.ini", + _TRUNCATE); attrs = GetFileAttributesW(launcher_ini_path); if (attrs == INVALID_FILE_ATTRIBUTES) { debug(L"File '%ls' non-existent\n", launcher_ini_path); @@ -1702,7 +1558,6 @@ process(int argc, wchar_t ** argv) debug(L"Using global configuration file '%ls'\n", launcher_ini_path); } } -#endif command = skip_me(GetCommandLineW()); debug(L"Called with command line: %ls\n", command); @@ -1738,55 +1593,6 @@ process(int argc, wchar_t ** argv) command = newcommand; valid = FALSE; } -#elif defined(VENV_REDIRECT) - { - FILE *f; - char buffer[4096]; /* 4KB should be enough for anybody */ - char *start; - DWORD len, cch, cch_actual; - size_t cb; - if (_wfopen_s(&f, venv_cfg_path, L"r")) { - error(RC_BAD_VENV_CFG, L"Cannot read '%ls'", venv_cfg_path); - } - cb = fread_s(buffer, sizeof(buffer), sizeof(buffer[0]), - sizeof(buffer) / sizeof(buffer[0]), f); - fclose(f); - - if (!find_home_value(buffer, &start, &len)) { - error(RC_BAD_VENV_CFG, L"Cannot find home in '%ls'", - venv_cfg_path); - } - - cch = MultiByteToWideChar(CP_UTF8, 0, start, len, NULL, 0); - if (!cch) { - error(0, L"Cannot determine memory for home path"); - } - cch += (DWORD)wcslen(PYTHON_EXECUTABLE) + 1 + 1; /* include sep and null */ - executable = (wchar_t *)malloc(cch * sizeof(wchar_t)); - if (executable == NULL) { - error(RC_NO_MEMORY, L"A memory allocation failed"); - } - cch_actual = MultiByteToWideChar(CP_UTF8, 0, start, len, executable, cch); - if (!cch_actual) { - error(RC_BAD_VENV_CFG, L"Cannot decode home path in '%ls'", - venv_cfg_path); - } - if (executable[cch_actual - 1] != L'\\') { - executable[cch_actual++] = L'\\'; - executable[cch_actual] = L'\0'; - } - if (wcscat_s(executable, cch, PYTHON_EXECUTABLE)) { - error(RC_BAD_VENV_CFG, L"Cannot create executable path from '%ls'", - venv_cfg_path); - } - if (GetFileAttributesW(executable) == INVALID_FILE_ATTRIBUTES) { - error(RC_NO_PYTHON, L"No Python at '%ls'", executable); - } - if (!SetEnvironmentVariableW(L"__PYVENV_LAUNCHER__", argv0)) { - error(0, L"Failed to set launcher environment"); - } - valid = 1; - } #else if (argc <= 1) { valid = FALSE; @@ -1794,6 +1600,7 @@ process(int argc, wchar_t ** argv) } else { p = argv[1]; + plen = wcslen(p); if ((argc == 2) && // list version args (!wcsncmp(p, L"-0", wcslen(L"-0")) || !wcsncmp(p, L"--list", wcslen(L"--list")))) diff --git a/PC/layout/__init__.py b/PC/layout/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/PC/layout/__main__.py b/PC/layout/__main__.py deleted file mode 100644 index f7aa1e6d261..00000000000 --- a/PC/layout/__main__.py +++ /dev/null @@ -1,14 +0,0 @@ -import sys - -try: - import layout -except ImportError: - # Failed to import our package, which likely means we were started directly - # Add the additional search path needed to locate our module. - from pathlib import Path - - sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) - -from layout.main import main - -sys.exit(int(main() or 0)) diff --git a/PC/layout/main.py b/PC/layout/main.py deleted file mode 100644 index 82d0536ca92..00000000000 --- a/PC/layout/main.py +++ /dev/null @@ -1,612 +0,0 @@ -""" -Generates a layout of Python for Windows from a build. - -See python make_layout.py --help for usage. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - -import argparse -import functools -import os -import re -import shutil -import subprocess -import sys -import tempfile -import zipfile - -from pathlib import Path - -if __name__ == "__main__": - # Started directly, so enable relative imports - __path__ = [str(Path(__file__).resolve().parent)] - -from .support.appxmanifest import * -from .support.catalog import * -from .support.constants import * -from .support.filesets import * -from .support.logging import * -from .support.options import * -from .support.pip import * -from .support.props import * - -BDIST_WININST_FILES_ONLY = FileNameSet("wininst-*", "bdist_wininst.py") -BDIST_WININST_STUB = "PC/layout/support/distutils.command.bdist_wininst.py" - -TEST_PYDS_ONLY = FileStemSet("xxlimited", "_ctypes_test", "_test*") -TEST_DIRS_ONLY = FileNameSet("test", "tests") - -IDLE_DIRS_ONLY = FileNameSet("idlelib") - -TCLTK_PYDS_ONLY = FileStemSet("tcl*", "tk*", "_tkinter") -TCLTK_DIRS_ONLY = FileNameSet("tkinter", "turtledemo") -TCLTK_FILES_ONLY = FileNameSet("turtle.py") - -VENV_DIRS_ONLY = FileNameSet("venv", "ensurepip") - -EXCLUDE_FROM_PYDS = FileStemSet("python*", "pyshellext") -EXCLUDE_FROM_LIB = FileNameSet("*.pyc", "__pycache__", "*.pickle") -EXCLUDE_FROM_PACKAGED_LIB = FileNameSet("readme.txt") -EXCLUDE_FROM_COMPILE = FileNameSet("badsyntax_*", "bad_*") -EXCLUDE_FROM_CATALOG = FileSuffixSet(".exe", ".pyd", ".dll") - -REQUIRED_DLLS = FileStemSet("libcrypto*", "libssl*") - -LIB2TO3_GRAMMAR_FILES = FileNameSet("Grammar.txt", "PatternGrammar.txt") - -PY_FILES = FileSuffixSet(".py") -PYC_FILES = FileSuffixSet(".pyc") -CAT_FILES = FileSuffixSet(".cat") -CDF_FILES = FileSuffixSet(".cdf") - -DATA_DIRS = FileNameSet("data") - -TOOLS_DIRS = FileNameSet("scripts", "i18n", "pynche", "demo", "parser") -TOOLS_FILES = FileSuffixSet(".py", ".pyw", ".txt") - - -def get_lib_layout(ns): - def _c(f): - if f in EXCLUDE_FROM_LIB: - return False - if f.is_dir(): - if f in TEST_DIRS_ONLY: - return ns.include_tests - if f in TCLTK_DIRS_ONLY: - return ns.include_tcltk - if f in IDLE_DIRS_ONLY: - return ns.include_idle - if f in VENV_DIRS_ONLY: - return ns.include_venv - else: - if f in TCLTK_FILES_ONLY: - return ns.include_tcltk - if f in BDIST_WININST_FILES_ONLY: - return ns.include_bdist_wininst - return True - - for dest, src in rglob(ns.source / "Lib", "**/*", _c): - yield dest, src - - if not ns.include_bdist_wininst: - src = ns.source / BDIST_WININST_STUB - yield Path("distutils/command/bdist_wininst.py"), src - - -def get_tcltk_lib(ns): - if not ns.include_tcltk: - return - - tcl_lib = os.getenv("TCL_LIBRARY") - if not tcl_lib or not os.path.isdir(tcl_lib): - try: - with open(ns.build / "TCL_LIBRARY.env", "r", encoding="utf-8-sig") as f: - tcl_lib = f.read().strip() - except FileNotFoundError: - pass - if not tcl_lib or not os.path.isdir(tcl_lib): - warn("Failed to find TCL_LIBRARY") - return - - for dest, src in rglob(Path(tcl_lib).parent, "**/*"): - yield "tcl/{}".format(dest), src - - -def get_layout(ns): - def in_build(f, dest="", new_name=None): - n, _, x = f.rpartition(".") - n = new_name or n - src = ns.build / f - if ns.debug and src not in REQUIRED_DLLS: - if not src.stem.endswith("_d"): - src = src.parent / (src.stem + "_d" + src.suffix) - if not n.endswith("_d"): - n += "_d" - f = n + "." + x - yield dest + n + "." + x, src - if ns.include_symbols: - pdb = src.with_suffix(".pdb") - if pdb.is_file(): - yield dest + n + ".pdb", pdb - if ns.include_dev: - lib = src.with_suffix(".lib") - if lib.is_file(): - yield "libs/" + n + ".lib", lib - - yield from in_build("python_uwp.exe", new_name="python") - yield from in_build("pythonw_uwp.exe", new_name="pythonw") - - yield from in_build(PYTHON_DLL_NAME) - - if ns.include_launchers: - if ns.include_pip: - yield from in_build("python_uwp.exe", new_name="pip") - if ns.include_idle: - yield from in_build("pythonw_uwp.exe", new_name="idle") - - if ns.include_stable: - yield from in_build(PYTHON_STABLE_DLL_NAME) - - for dest, src in rglob(ns.build, "vcruntime*.dll"): - yield dest, src - - for dest, src in rglob(ns.build, ("*.pyd", "*.dll")): - if src.stem.endswith("_d") != bool(ns.debug) and src not in REQUIRED_DLLS: - continue - if src in EXCLUDE_FROM_PYDS: - continue - if src in TEST_PYDS_ONLY and not ns.include_tests: - continue - if src in TCLTK_PYDS_ONLY and not ns.include_tcltk: - continue - - yield from in_build(src.name, dest="" if ns.flat_dlls else "DLLs/") - - if ns.zip_lib: - zip_name = PYTHON_ZIP_NAME - yield zip_name, ns.temp / zip_name - else: - for dest, src in get_lib_layout(ns): - yield "Lib/{}".format(dest), src - - if ns.include_venv: - yield from in_build("venvlauncher.exe", "Lib/venv/scripts/nt/", "python") - yield from in_build("venvwlauncher.exe", "Lib/venv/scripts/nt/", "pythonw") - - if ns.include_tools: - - def _c(d): - if d.is_dir(): - return d in TOOLS_DIRS - return d in TOOLS_FILES - - for dest, src in rglob(ns.source / "Tools", "**/*", _c): - yield "Tools/{}".format(dest), src - - if ns.include_underpth: - yield PYTHON_PTH_NAME, ns.temp / PYTHON_PTH_NAME - - if ns.include_dev: - - def _c(d): - if d.is_dir(): - return d.name != "internal" - return True - - for dest, src in rglob(ns.source / "Include", "**/*.h", _c): - yield "include/{}".format(dest), src - src = ns.source / "PC" / "pyconfig.h" - yield "include/pyconfig.h", src - - for dest, src in get_tcltk_lib(ns): - yield dest, src - - if ns.include_pip: - pip_dir = get_pip_dir(ns) - if not pip_dir.is_dir(): - log_warning("Failed to find {} - pip will not be included", pip_dir) - else: - pkg_root = "packages/{}" if ns.zip_lib else "Lib/site-packages/{}" - for dest, src in rglob(pip_dir, "**/*"): - if src in EXCLUDE_FROM_LIB or src in EXCLUDE_FROM_PACKAGED_LIB: - continue - yield pkg_root.format(dest), src - - if ns.include_chm: - for dest, src in rglob(ns.doc_build / "htmlhelp", PYTHON_CHM_NAME): - yield "Doc/{}".format(dest), src - - if ns.include_html_doc: - for dest, src in rglob(ns.doc_build / "html", "**/*"): - yield "Doc/html/{}".format(dest), src - - if ns.include_props: - for dest, src in get_props_layout(ns): - yield dest, src - - for dest, src in get_appx_layout(ns): - yield dest, src - - if ns.include_cat: - if ns.flat_dlls: - yield ns.include_cat.name, ns.include_cat - else: - yield "DLLs/{}".format(ns.include_cat.name), ns.include_cat - - -def _compile_one_py(src, dest, name, optimize): - import py_compile - - if dest is not None: - dest = str(dest) - - try: - return Path( - py_compile.compile( - str(src), - dest, - str(name), - doraise=True, - optimize=optimize, - invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH, - ) - ) - except py_compile.PyCompileError: - log_warning("Failed to compile {}", src) - return None - - -def _py_temp_compile(src, ns, dest_dir=None): - if not ns.precompile or src not in PY_FILES or src.parent in DATA_DIRS: - return None - - dest = (dest_dir or ns.temp) / (src.stem + ".py") - return _compile_one_py(src, dest.with_suffix(".pyc"), dest, optimize=2) - - -def _write_to_zip(zf, dest, src, ns): - pyc = _py_temp_compile(src, ns) - if pyc: - try: - zf.write(str(pyc), dest.with_suffix(".pyc")) - finally: - try: - pyc.unlink() - except: - log_exception("Failed to delete {}", pyc) - return - - if src in LIB2TO3_GRAMMAR_FILES: - from lib2to3.pgen2.driver import load_grammar - - tmp = ns.temp / src.name - try: - shutil.copy(src, tmp) - load_grammar(str(tmp)) - for f in ns.temp.glob(src.stem + "*.pickle"): - zf.write(str(f), str(dest.parent / f.name)) - try: - f.unlink() - except: - log_exception("Failed to delete {}", f) - except: - log_exception("Failed to compile {}", src) - finally: - try: - tmp.unlink() - except: - log_exception("Failed to delete {}", tmp) - - zf.write(str(src), str(dest)) - - -def generate_source_files(ns): - if ns.zip_lib: - zip_name = PYTHON_ZIP_NAME - zip_path = ns.temp / zip_name - if zip_path.is_file(): - zip_path.unlink() - elif zip_path.is_dir(): - log_error( - "Cannot create zip file because a directory exists by the same name" - ) - return - log_info("Generating {} in {}", zip_name, ns.temp) - ns.temp.mkdir(parents=True, exist_ok=True) - with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf: - for dest, src in get_lib_layout(ns): - _write_to_zip(zf, dest, src, ns) - - if ns.include_underpth: - log_info("Generating {} in {}", PYTHON_PTH_NAME, ns.temp) - ns.temp.mkdir(parents=True, exist_ok=True) - with open(ns.temp / PYTHON_PTH_NAME, "w", encoding="utf-8") as f: - if ns.zip_lib: - print(PYTHON_ZIP_NAME, file=f) - if ns.include_pip: - print("packages", file=f) - else: - print("Lib", file=f) - print("Lib/site-packages", file=f) - if not ns.flat_dlls: - print("DLLs", file=f) - print(".", file=f) - print(file=f) - print("# Uncomment to run site.main() automatically", file=f) - print("#import site", file=f) - - if ns.include_appxmanifest: - log_info("Generating AppxManifest.xml in {}", ns.temp) - ns.temp.mkdir(parents=True, exist_ok=True) - - with open(ns.temp / "AppxManifest.xml", "wb") as f: - f.write(get_appxmanifest(ns)) - - with open(ns.temp / "_resources.xml", "wb") as f: - f.write(get_resources_xml(ns)) - - if ns.include_pip: - pip_dir = get_pip_dir(ns) - if not (pip_dir / "pip").is_dir(): - log_info("Extracting pip to {}", pip_dir) - pip_dir.mkdir(parents=True, exist_ok=True) - extract_pip_files(ns) - - if ns.include_props: - log_info("Generating {} in {}", PYTHON_PROPS_NAME, ns.temp) - ns.temp.mkdir(parents=True, exist_ok=True) - with open(ns.temp / PYTHON_PROPS_NAME, "wb") as f: - f.write(get_props(ns)) - - -def _create_zip_file(ns): - if not ns.zip: - return None - - if ns.zip.is_file(): - try: - ns.zip.unlink() - except OSError: - log_exception("Unable to remove {}", ns.zip) - sys.exit(8) - elif ns.zip.is_dir(): - log_error("Cannot create ZIP file because {} is a directory", ns.zip) - sys.exit(8) - - ns.zip.parent.mkdir(parents=True, exist_ok=True) - return zipfile.ZipFile(ns.zip, "w", zipfile.ZIP_DEFLATED) - - -def copy_files(files, ns): - if ns.copy: - ns.copy.mkdir(parents=True, exist_ok=True) - - try: - total = len(files) - except TypeError: - total = None - count = 0 - - zip_file = _create_zip_file(ns) - try: - need_compile = [] - in_catalog = [] - - for dest, src in files: - count += 1 - if count % 10 == 0: - if total: - log_info("Processed {:>4} of {} files", count, total) - else: - log_info("Processed {} files", count) - log_debug("Processing {!s}", src) - - if ( - ns.precompile - and src in PY_FILES - and src not in EXCLUDE_FROM_COMPILE - and src.parent not in DATA_DIRS - and os.path.normcase(str(dest)).startswith(os.path.normcase("Lib")) - ): - if ns.copy: - need_compile.append((dest, ns.copy / dest)) - else: - (ns.temp / "Lib" / dest).parent.mkdir(parents=True, exist_ok=True) - shutil.copy2(src, ns.temp / "Lib" / dest) - need_compile.append((dest, ns.temp / "Lib" / dest)) - - if src not in EXCLUDE_FROM_CATALOG: - in_catalog.append((src.name, src)) - - if ns.copy: - log_debug("Copy {} -> {}", src, ns.copy / dest) - (ns.copy / dest).parent.mkdir(parents=True, exist_ok=True) - try: - shutil.copy2(src, ns.copy / dest) - except shutil.SameFileError: - pass - - if ns.zip: - log_debug("Zip {} into {}", src, ns.zip) - zip_file.write(src, str(dest)) - - if need_compile: - for dest, src in need_compile: - compiled = [ - _compile_one_py(src, None, dest, optimize=0), - _compile_one_py(src, None, dest, optimize=1), - _compile_one_py(src, None, dest, optimize=2), - ] - for c in compiled: - if not c: - continue - cdest = Path(dest).parent / Path(c).relative_to(src.parent) - if ns.zip: - log_debug("Zip {} into {}", c, ns.zip) - zip_file.write(c, str(cdest)) - in_catalog.append((cdest.name, cdest)) - - if ns.catalog: - # Just write out the CDF now. Compilation and signing is - # an extra step - log_info("Generating {}", ns.catalog) - ns.catalog.parent.mkdir(parents=True, exist_ok=True) - write_catalog(ns.catalog, in_catalog) - - finally: - if zip_file: - zip_file.close() - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument("-v", help="Increase verbosity", action="count") - parser.add_argument( - "-s", - "--source", - metavar="dir", - help="The directory containing the repository root", - type=Path, - default=None, - ) - parser.add_argument( - "-b", "--build", metavar="dir", help="Specify the build directory", type=Path - ) - parser.add_argument( - "--doc-build", - metavar="dir", - help="Specify the docs build directory", - type=Path, - default=None, - ) - parser.add_argument( - "--copy", - metavar="directory", - help="The name of the directory to copy an extracted layout to", - type=Path, - default=None, - ) - parser.add_argument( - "--zip", - metavar="file", - help="The ZIP file to write all files to", - type=Path, - default=None, - ) - parser.add_argument( - "--catalog", - metavar="file", - help="The CDF file to write catalog entries to", - type=Path, - default=None, - ) - parser.add_argument( - "--log", - metavar="file", - help="Write all operations to the specified file", - type=Path, - default=None, - ) - parser.add_argument( - "-t", - "--temp", - metavar="file", - help="A temporary working directory", - type=Path, - default=None, - ) - parser.add_argument( - "-d", "--debug", help="Include debug build", action="store_true" - ) - parser.add_argument( - "-p", - "--precompile", - help="Include .pyc files instead of .py", - action="store_true", - ) - parser.add_argument( - "-z", "--zip-lib", help="Include library in a ZIP file", action="store_true" - ) - parser.add_argument( - "--flat-dlls", help="Does not create a DLLs directory", action="store_true" - ) - parser.add_argument( - "-a", - "--include-all", - help="Include all optional components", - action="store_true", - ) - parser.add_argument( - "--include-cat", - metavar="file", - help="Specify the catalog file to include", - type=Path, - default=None, - ) - for opt, help in get_argparse_options(): - parser.add_argument(opt, help=help, action="store_true") - - ns = parser.parse_args() - update_presets(ns) - - ns.source = ns.source or (Path(__file__).resolve().parent.parent.parent) - ns.build = ns.build or Path(sys.executable).parent - ns.temp = ns.temp or Path(tempfile.mkdtemp()) - ns.doc_build = ns.doc_build or (ns.source / "Doc" / "build") - if not ns.source.is_absolute(): - ns.source = (Path.cwd() / ns.source).resolve() - if not ns.build.is_absolute(): - ns.build = (Path.cwd() / ns.build).resolve() - if not ns.temp.is_absolute(): - ns.temp = (Path.cwd() / ns.temp).resolve() - if not ns.doc_build.is_absolute(): - ns.doc_build = (Path.cwd() / ns.doc_build).resolve() - if ns.include_cat and not ns.include_cat.is_absolute(): - ns.include_cat = (Path.cwd() / ns.include_cat).resolve() - - if ns.copy and not ns.copy.is_absolute(): - ns.copy = (Path.cwd() / ns.copy).resolve() - if ns.zip and not ns.zip.is_absolute(): - ns.zip = (Path.cwd() / ns.zip).resolve() - if ns.catalog and not ns.catalog.is_absolute(): - ns.catalog = (Path.cwd() / ns.catalog).resolve() - - configure_logger(ns) - - log_info( - """OPTIONS -Source: {ns.source} -Build: {ns.build} -Temp: {ns.temp} - -Copy to: {ns.copy} -Zip to: {ns.zip} -Catalog: {ns.catalog}""", - ns=ns, - ) - - if ns.include_idle and not ns.include_tcltk: - log_warning("Assuming --include-tcltk to support --include-idle") - ns.include_tcltk = True - - try: - generate_source_files(ns) - files = list(get_layout(ns)) - copy_files(files, ns) - except KeyboardInterrupt: - log_info("Interrupted by Ctrl+C") - return 3 - except SystemExit: - raise - except: - log_exception("Unhandled error") - - if error_was_logged(): - log_error("Errors occurred.") - return 1 - - -if __name__ == "__main__": - sys.exit(int(main() or 0)) diff --git a/PC/layout/support/__init__.py b/PC/layout/support/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/PC/layout/support/appxmanifest.py b/PC/layout/support/appxmanifest.py deleted file mode 100644 index c5dda70c7ef..00000000000 --- a/PC/layout/support/appxmanifest.py +++ /dev/null @@ -1,487 +0,0 @@ -""" -File generation for APPX/MSIX manifests. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - - -import collections -import ctypes -import io -import os -import sys - -from pathlib import Path, PureWindowsPath -from xml.etree import ElementTree as ET - -from .constants import * - -__all__ = [] - - -def public(f): - __all__.append(f.__name__) - return f - - -APPX_DATA = dict( - Name="PythonSoftwareFoundation.Python.{}".format(VER_DOT), - Version="{}.{}.{}.0".format(VER_MAJOR, VER_MINOR, VER_FIELD3), - Publisher=os.getenv( - "APPX_DATA_PUBLISHER", "CN=4975D53F-AA7E-49A5-8B49-EA4FDC1BB66B" - ), - DisplayName="Python {}".format(VER_DOT), - Description="The Python {} runtime and console.".format(VER_DOT), - ProcessorArchitecture="x64" if IS_X64 else "x86", -) - -PYTHON_VE_DATA = dict( - DisplayName="Python {}".format(VER_DOT), - Description="Python interactive console", - Square150x150Logo="_resources/pythonx150.png", - Square44x44Logo="_resources/pythonx44.png", - BackgroundColor="transparent", -) - -PYTHONW_VE_DATA = dict( - DisplayName="Python {} (Windowed)".format(VER_DOT), - Description="Python windowed app launcher", - Square150x150Logo="_resources/pythonwx150.png", - Square44x44Logo="_resources/pythonwx44.png", - BackgroundColor="transparent", - AppListEntry="none", -) - -PIP_VE_DATA = dict( - DisplayName="pip (Python {})".format(VER_DOT), - Description="pip package manager for Python {}".format(VER_DOT), - Square150x150Logo="_resources/pythonx150.png", - Square44x44Logo="_resources/pythonx44.png", - BackgroundColor="transparent", - AppListEntry="none", -) - -IDLE_VE_DATA = dict( - DisplayName="IDLE (Python {})".format(VER_DOT), - Description="IDLE editor for Python {}".format(VER_DOT), - Square150x150Logo="_resources/pythonwx150.png", - Square44x44Logo="_resources/pythonwx44.png", - BackgroundColor="transparent", -) - -APPXMANIFEST_NS = { - "": "http://schemas.microsoft.com/appx/manifest/foundation/windows10", - "m": "http://schemas.microsoft.com/appx/manifest/foundation/windows10", - "uap": "http://schemas.microsoft.com/appx/manifest/uap/windows10", - "rescap": "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities", - "rescap4": "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities/4", - "desktop4": "http://schemas.microsoft.com/appx/manifest/desktop/windows10/4", - "desktop6": "http://schemas.microsoft.com/appx/manifest/desktop/windows10/6", - "uap3": "http://schemas.microsoft.com/appx/manifest/uap/windows10/3", - "uap4": "http://schemas.microsoft.com/appx/manifest/uap/windows10/4", - "uap5": "http://schemas.microsoft.com/appx/manifest/uap/windows10/5", -} - -APPXMANIFEST_TEMPLATE = """ - - - - - Python Software Foundation - - _resources/pythonx50.png - - - - - - - - - - - - - - -""" - - -RESOURCES_XML_TEMPLATE = r""" - - - - - - - - - - - - - - - - - - - - - - - - - - - -""" - - -SCCD_FILENAME = "PC/classicAppCompat.sccd" - -REGISTRY = { - "HKCU\\Software\\Python\\PythonCore": { - VER_DOT: { - "DisplayName": APPX_DATA["DisplayName"], - "SupportUrl": "https://www.python.org/", - "SysArchitecture": "64bit" if IS_X64 else "32bit", - "SysVersion": VER_DOT, - "Version": "{}.{}.{}".format(VER_MAJOR, VER_MINOR, VER_MICRO), - "InstallPath": { - # I have no idea why the trailing spaces are needed, but they seem to be needed. - "": "[{AppVPackageRoot}][ ]", - "ExecutablePath": "[{AppVPackageRoot}]python.exe[ ]", - "WindowedExecutablePath": "[{AppVPackageRoot}]pythonw.exe[ ]", - }, - "Help": { - "Main Python Documentation": { - "_condition": lambda ns: ns.include_chm, - "": "[{{AppVPackageRoot}}]Doc\\{}[ ]".format( - PYTHON_CHM_NAME - ), - }, - "Local Python Documentation": { - "_condition": lambda ns: ns.include_html_doc, - "": "[{AppVPackageRoot}]Doc\\html\\index.html[ ]", - }, - "Online Python Documentation": { - "": "https://docs.python.org/{}".format(VER_DOT) - }, - }, - "Idle": { - "_condition": lambda ns: ns.include_idle, - "": "[{AppVPackageRoot}]Lib\\idlelib\\idle.pyw[ ]", - }, - } - } -} - - -def get_packagefamilyname(name, publisher_id): - class PACKAGE_ID(ctypes.Structure): - _fields_ = [ - ("reserved", ctypes.c_uint32), - ("processorArchitecture", ctypes.c_uint32), - ("version", ctypes.c_uint64), - ("name", ctypes.c_wchar_p), - ("publisher", ctypes.c_wchar_p), - ("resourceId", ctypes.c_wchar_p), - ("publisherId", ctypes.c_wchar_p), - ] - _pack_ = 4 - - pid = PACKAGE_ID(0, 0, 0, name, publisher_id, None, None) - result = ctypes.create_unicode_buffer(256) - result_len = ctypes.c_uint32(256) - r = ctypes.windll.kernel32.PackageFamilyNameFromId( - pid, ctypes.byref(result_len), result - ) - if r: - raise OSError(r, "failed to get package family name") - return result.value[: result_len.value] - - -def _fixup_sccd(ns, sccd, new_hash=None): - if not new_hash: - return sccd - - NS = dict(s="http://schemas.microsoft.com/appx/2016/sccd") - with open(sccd, "rb") as f: - xml = ET.parse(f) - - pfn = get_packagefamilyname(APPX_DATA["Name"], APPX_DATA["Publisher"]) - - ae = xml.find("s:AuthorizedEntities", NS) - ae.clear() - - e = ET.SubElement(ae, ET.QName(NS["s"], "AuthorizedEntity")) - e.set("AppPackageFamilyName", pfn) - e.set("CertificateSignatureHash", new_hash) - - for e in xml.findall("s:Catalog", NS): - e.text = "FFFF" - - sccd = ns.temp / sccd.name - sccd.parent.mkdir(parents=True, exist_ok=True) - with open(sccd, "wb") as f: - xml.write(f, encoding="utf-8") - - return sccd - - -@public -def get_appx_layout(ns): - if not ns.include_appxmanifest: - return - - yield "AppxManifest.xml", ns.temp / "AppxManifest.xml" - yield "_resources.xml", ns.temp / "_resources.xml" - icons = ns.source / "PC" / "icons" - yield "_resources/pythonx44.png", icons / "pythonx44.png" - yield "_resources/pythonx44$targetsize-44_altform-unplated.png", icons / "pythonx44.png" - yield "_resources/pythonx50.png", icons / "pythonx50.png" - yield "_resources/pythonx50$targetsize-50_altform-unplated.png", icons / "pythonx50.png" - yield "_resources/pythonx150.png", icons / "pythonx150.png" - yield "_resources/pythonx150$targetsize-150_altform-unplated.png", icons / "pythonx150.png" - yield "_resources/pythonwx44.png", icons / "pythonwx44.png" - yield "_resources/pythonwx44$targetsize-44_altform-unplated.png", icons / "pythonwx44.png" - yield "_resources/pythonwx150.png", icons / "pythonwx150.png" - yield "_resources/pythonwx150$targetsize-150_altform-unplated.png", icons / "pythonwx150.png" - sccd = ns.source / SCCD_FILENAME - if sccd.is_file(): - # This should only be set for side-loading purposes. - sccd = _fixup_sccd(ns, sccd, os.getenv("APPX_DATA_SHA256")) - yield sccd.name, sccd - - -def find_or_add(xml, element, attr=None, always_add=False): - if always_add: - e = None - else: - q = element - if attr: - q += "[@{}='{}']".format(*attr) - e = xml.find(q, APPXMANIFEST_NS) - if e is None: - prefix, _, name = element.partition(":") - name = ET.QName(APPXMANIFEST_NS[prefix or ""], name) - e = ET.SubElement(xml, name) - if attr: - e.set(*attr) - return e - - -def _get_app(xml, appid): - if appid: - app = xml.find( - "m:Applications/m:Application[@Id='{}']".format(appid), APPXMANIFEST_NS - ) - if app is None: - raise LookupError(appid) - else: - app = xml - return app - - -def add_visual(xml, appid, data): - app = _get_app(xml, appid) - e = find_or_add(app, "uap:VisualElements") - for i in data.items(): - e.set(*i) - return e - - -def add_alias(xml, appid, alias, subsystem="windows"): - app = _get_app(xml, appid) - e = find_or_add(app, "m:Extensions") - e = find_or_add(e, "uap5:Extension", ("Category", "windows.appExecutionAlias")) - e = find_or_add(e, "uap5:AppExecutionAlias") - e.set(ET.QName(APPXMANIFEST_NS["desktop4"], "Subsystem"), subsystem) - e = find_or_add(e, "uap5:ExecutionAlias", ("Alias", alias)) - - -def add_file_type(xml, appid, name, suffix, parameters='"%1"'): - app = _get_app(xml, appid) - e = find_or_add(app, "m:Extensions") - e = find_or_add(e, "uap3:Extension", ("Category", "windows.fileTypeAssociation")) - e = find_or_add(e, "uap3:FileTypeAssociation", ("Name", name)) - e.set("Parameters", parameters) - e = find_or_add(e, "uap:SupportedFileTypes") - if isinstance(suffix, str): - suffix = [suffix] - for s in suffix: - ET.SubElement(e, ET.QName(APPXMANIFEST_NS["uap"], "FileType")).text = s - - -def add_application( - ns, xml, appid, executable, aliases, visual_element, subsystem, file_types -): - node = xml.find("m:Applications", APPXMANIFEST_NS) - suffix = "_d.exe" if ns.debug else ".exe" - app = ET.SubElement( - node, - ET.QName(APPXMANIFEST_NS[""], "Application"), - { - "Id": appid, - "Executable": executable + suffix, - "EntryPoint": "Windows.FullTrustApplication", - ET.QName(APPXMANIFEST_NS["desktop4"], "SupportsMultipleInstances"): "true", - }, - ) - if visual_element: - add_visual(app, None, visual_element) - for alias in aliases: - add_alias(app, None, alias + suffix, subsystem) - if file_types: - add_file_type(app, None, *file_types) - return app - - -def _get_registry_entries(ns, root="", d=None): - r = root if root else PureWindowsPath("") - if d is None: - d = REGISTRY - for key, value in d.items(): - if key == "_condition": - continue - elif isinstance(value, dict): - cond = value.get("_condition") - if cond and not cond(ns): - continue - fullkey = r - for part in PureWindowsPath(key).parts: - fullkey /= part - if len(fullkey.parts) > 1: - yield str(fullkey), None, None - yield from _get_registry_entries(ns, fullkey, value) - elif len(r.parts) > 1: - yield str(r), key, value - - -def add_registry_entries(ns, xml): - e = find_or_add(xml, "m:Extensions") - e = find_or_add(e, "rescap4:Extension") - e.set("Category", "windows.classicAppCompatKeys") - e.set("EntryPoint", "Windows.FullTrustApplication") - e = ET.SubElement(e, ET.QName(APPXMANIFEST_NS["rescap4"], "ClassicAppCompatKeys")) - for name, valuename, value in _get_registry_entries(ns): - k = ET.SubElement( - e, ET.QName(APPXMANIFEST_NS["rescap4"], "ClassicAppCompatKey") - ) - k.set("Name", name) - if value: - k.set("ValueName", valuename) - k.set("Value", value) - k.set("ValueType", "REG_SZ") - - -def disable_registry_virtualization(xml): - e = find_or_add(xml, "m:Properties") - e = find_or_add(e, "desktop6:RegistryWriteVirtualization") - e.text = "disabled" - e = find_or_add(xml, "m:Capabilities") - e = find_or_add(e, "rescap:Capability", ("Name", "unvirtualizedResources")) - - -@public -def get_appxmanifest(ns): - for k, v in APPXMANIFEST_NS.items(): - ET.register_namespace(k, v) - ET.register_namespace("", APPXMANIFEST_NS["m"]) - - xml = ET.parse(io.StringIO(APPXMANIFEST_TEMPLATE)) - NS = APPXMANIFEST_NS - QN = ET.QName - - node = xml.find("m:Identity", NS) - for k in node.keys(): - value = APPX_DATA.get(k) - if value: - node.set(k, value) - - for node in xml.find("m:Properties", NS): - value = APPX_DATA.get(node.tag.rpartition("}")[2]) - if value: - node.text = value - - winver = sys.getwindowsversion()[:3] - if winver < (10, 0, 17763): - winver = 10, 0, 17763 - find_or_add(xml, "m:Dependencies/m:TargetDeviceFamily").set( - "MaxVersionTested", "{}.{}.{}.0".format(*winver) - ) - - if winver > (10, 0, 17763): - disable_registry_virtualization(xml) - - app = add_application( - ns, - xml, - "Python", - "python", - ["python", "python{}".format(VER_MAJOR), "python{}".format(VER_DOT)], - PYTHON_VE_DATA, - "console", - ("python.file", [".py"]), - ) - - add_application( - ns, - xml, - "PythonW", - "pythonw", - ["pythonw", "pythonw{}".format(VER_MAJOR), "pythonw{}".format(VER_DOT)], - PYTHONW_VE_DATA, - "windows", - ("python.windowedfile", [".pyw"]), - ) - - if ns.include_pip and ns.include_launchers: - add_application( - ns, - xml, - "Pip", - "pip", - ["pip", "pip{}".format(VER_MAJOR), "pip{}".format(VER_DOT)], - PIP_VE_DATA, - "console", - ("python.wheel", [".whl"], 'install "%1"'), - ) - - if ns.include_idle and ns.include_launchers: - add_application( - ns, - xml, - "Idle", - "idle", - ["idle", "idle{}".format(VER_MAJOR), "idle{}".format(VER_DOT)], - IDLE_VE_DATA, - "windows", - None, - ) - - if (ns.source / SCCD_FILENAME).is_file(): - add_registry_entries(ns, xml) - node = xml.find("m:Capabilities", NS) - node = ET.SubElement(node, QN(NS["uap4"], "CustomCapability")) - node.set("Name", "Microsoft.classicAppCompat_8wekyb3d8bbwe") - - buffer = io.BytesIO() - xml.write(buffer, encoding="utf-8", xml_declaration=True) - return buffer.getbuffer() - - -@public -def get_resources_xml(ns): - return RESOURCES_XML_TEMPLATE.encode("utf-8") diff --git a/PC/layout/support/catalog.py b/PC/layout/support/catalog.py deleted file mode 100644 index 43121187ed1..00000000000 --- a/PC/layout/support/catalog.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -File generation for catalog signing non-binary contents. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - - -import sys - -__all__ = ["PYTHON_CAT_NAME", "PYTHON_CDF_NAME"] - - -def public(f): - __all__.append(f.__name__) - return f - - -PYTHON_CAT_NAME = "python.cat" -PYTHON_CDF_NAME = "python.cdf" - - -CATALOG_TEMPLATE = r"""[CatalogHeader] -Name={target.stem}.cat -ResultDir={target.parent} -PublicVersion=1 -CatalogVersion=2 -HashAlgorithms=SHA256 -PageHashes=false -EncodingType= - -[CatalogFiles] -""" - - -def can_sign(file): - return file.is_file() and file.stat().st_size - - -@public -def write_catalog(target, files): - with target.open("w", encoding="utf-8") as cat: - cat.write(CATALOG_TEMPLATE.format(target=target)) - cat.writelines("{}={}\n".format(n, f) for n, f in files if can_sign(f)) diff --git a/PC/layout/support/constants.py b/PC/layout/support/constants.py deleted file mode 100644 index 88ea410b340..00000000000 --- a/PC/layout/support/constants.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -Constants for generating the layout. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - -import struct -import sys - -VER_MAJOR, VER_MINOR, VER_MICRO, VER_FIELD4 = struct.pack(">i", sys.hexversion) -VER_FIELD3 = VER_MICRO << 8 | VER_FIELD4 -VER_NAME = {"alpha": "a", "beta": "b", "rc": "rc"}.get( - sys.version_info.releaselevel, "" -) -VER_SERIAL = sys.version_info.serial if VER_NAME else "" -VER_DOT = "{}.{}".format(VER_MAJOR, VER_MINOR) - -PYTHON_DLL_NAME = "python{}{}.dll".format(VER_MAJOR, VER_MINOR) -PYTHON_STABLE_DLL_NAME = "python{}.dll".format(VER_MAJOR) -PYTHON_ZIP_NAME = "python{}{}.zip".format(VER_MAJOR, VER_MINOR) -PYTHON_PTH_NAME = "python{}{}._pth".format(VER_MAJOR, VER_MINOR) - -PYTHON_CHM_NAME = "python{}{}{}{}{}.chm".format( - VER_MAJOR, VER_MINOR, VER_MICRO, VER_NAME, VER_SERIAL -) - -IS_X64 = sys.maxsize > 2 ** 32 diff --git a/PC/layout/support/distutils.command.bdist_wininst.py b/PC/layout/support/distutils.command.bdist_wininst.py deleted file mode 100644 index 6e9b49fe42d..00000000000 --- a/PC/layout/support/distutils.command.bdist_wininst.py +++ /dev/null @@ -1,25 +0,0 @@ -"""distutils.command.bdist_wininst - -Suppress the 'bdist_wininst' command, while still allowing -setuptools to import it without breaking.""" - -from distutils.core import Command -from distutils.errors import DistutilsPlatformError - - -class bdist_wininst(Command): - description = "create an executable installer for MS Windows" - - # Marker for tests that we have the unsupported bdist_wininst - _unsupported = True - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - raise DistutilsPlatformError( - "bdist_wininst is not supported in this Python distribution" - ) diff --git a/PC/layout/support/filesets.py b/PC/layout/support/filesets.py deleted file mode 100644 index 47f727c0578..00000000000 --- a/PC/layout/support/filesets.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -File sets and globbing helper for make_layout. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - -import os - - -class FileStemSet: - def __init__(self, *patterns): - self._names = set() - self._prefixes = [] - self._suffixes = [] - for p in map(os.path.normcase, patterns): - if p.endswith("*"): - self._prefixes.append(p[:-1]) - elif p.startswith("*"): - self._suffixes.append(p[1:]) - else: - self._names.add(p) - - def _make_name(self, f): - return os.path.normcase(f.stem) - - def __contains__(self, f): - bn = self._make_name(f) - return ( - bn in self._names - or any(map(bn.startswith, self._prefixes)) - or any(map(bn.endswith, self._suffixes)) - ) - - -class FileNameSet(FileStemSet): - def _make_name(self, f): - return os.path.normcase(f.name) - - -class FileSuffixSet: - def __init__(self, *patterns): - self._names = set() - self._prefixes = [] - self._suffixes = [] - for p in map(os.path.normcase, patterns): - if p.startswith("*."): - self._names.add(p[1:]) - elif p.startswith("*"): - self._suffixes.append(p[1:]) - elif p.endswith("*"): - self._prefixes.append(p[:-1]) - elif p.startswith("."): - self._names.add(p) - else: - self._names.add("." + p) - - def _make_name(self, f): - return os.path.normcase(f.suffix) - - def __contains__(self, f): - bn = self._make_name(f) - return ( - bn in self._names - or any(map(bn.startswith, self._prefixes)) - or any(map(bn.endswith, self._suffixes)) - ) - - -def _rglob(root, pattern, condition): - dirs = [root] - recurse = pattern[:3] in {"**/", "**\\"} - if recurse: - pattern = pattern[3:] - - while dirs: - d = dirs.pop(0) - if recurse: - dirs.extend( - filter( - condition, (type(root)(f2) for f2 in os.scandir(d) if f2.is_dir()) - ) - ) - yield from ( - (f.relative_to(root), f) - for f in d.glob(pattern) - if f.is_file() and condition(f) - ) - - -def _return_true(f): - return True - - -def rglob(root, patterns, condition=None): - if isinstance(patterns, tuple): - for p in patterns: - yield from _rglob(root, p, condition or _return_true) - else: - yield from _rglob(root, patterns, condition or _return_true) diff --git a/PC/layout/support/logging.py b/PC/layout/support/logging.py deleted file mode 100644 index 30869b949a1..00000000000 --- a/PC/layout/support/logging.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -Logging support for make_layout. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - -import logging -import sys - -__all__ = [] - -LOG = None -HAS_ERROR = False - - -def public(f): - __all__.append(f.__name__) - return f - - -@public -def configure_logger(ns): - global LOG - if LOG: - return - - LOG = logging.getLogger("make_layout") - LOG.level = logging.DEBUG - - if ns.v: - s_level = max(logging.ERROR - ns.v * 10, logging.DEBUG) - f_level = max(logging.WARNING - ns.v * 10, logging.DEBUG) - else: - s_level = logging.ERROR - f_level = logging.INFO - - handler = logging.StreamHandler(sys.stdout) - handler.setFormatter(logging.Formatter("{levelname:8s} {message}", style="{")) - handler.setLevel(s_level) - LOG.addHandler(handler) - - if ns.log: - handler = logging.FileHandler(ns.log, encoding="utf-8", delay=True) - handler.setFormatter( - logging.Formatter("[{asctime}]{levelname:8s}: {message}", style="{") - ) - handler.setLevel(f_level) - LOG.addHandler(handler) - - -class BraceMessage: - def __init__(self, fmt, *args, **kwargs): - self.fmt = fmt - self.args = args - self.kwargs = kwargs - - def __str__(self): - return self.fmt.format(*self.args, **self.kwargs) - - -@public -def log_debug(msg, *args, **kwargs): - return LOG.debug(BraceMessage(msg, *args, **kwargs)) - - -@public -def log_info(msg, *args, **kwargs): - return LOG.info(BraceMessage(msg, *args, **kwargs)) - - -@public -def log_warning(msg, *args, **kwargs): - return LOG.warning(BraceMessage(msg, *args, **kwargs)) - - -@public -def log_error(msg, *args, **kwargs): - global HAS_ERROR - HAS_ERROR = True - return LOG.error(BraceMessage(msg, *args, **kwargs)) - - -@public -def log_exception(msg, *args, **kwargs): - global HAS_ERROR - HAS_ERROR = True - return LOG.exception(BraceMessage(msg, *args, **kwargs)) - - -@public -def error_was_logged(): - return HAS_ERROR diff --git a/PC/layout/support/options.py b/PC/layout/support/options.py deleted file mode 100644 index 76d9e34e1f4..00000000000 --- a/PC/layout/support/options.py +++ /dev/null @@ -1,122 +0,0 @@ -""" -List of optional components. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - - -__all__ = [] - - -def public(f): - __all__.append(f.__name__) - return f - - -OPTIONS = { - "stable": {"help": "stable ABI stub"}, - "pip": {"help": "pip"}, - "distutils": {"help": "distutils"}, - "tcltk": {"help": "Tcl, Tk and tkinter"}, - "idle": {"help": "Idle"}, - "tests": {"help": "test suite"}, - "tools": {"help": "tools"}, - "venv": {"help": "venv"}, - "dev": {"help": "headers and libs"}, - "symbols": {"help": "symbols"}, - "bdist-wininst": {"help": "bdist_wininst support"}, - "underpth": {"help": "a python._pth file", "not-in-all": True}, - "launchers": {"help": "specific launchers"}, - "appxmanifest": {"help": "an appxmanifest"}, - "props": {"help": "a python.props file"}, - "chm": {"help": "the CHM documentation"}, - "html-doc": {"help": "the HTML documentation"}, -} - - -PRESETS = { - "appx": { - "help": "APPX package", - "options": [ - "stable", - "pip", - "distutils", - "tcltk", - "idle", - "venv", - "dev", - "launchers", - "appxmanifest", - # XXX: Disabled for now "precompile", - ], - }, - "nuget": { - "help": "nuget package", - "options": ["stable", "pip", "distutils", "dev", "props"], - }, - "default": { - "help": "development kit package", - "options": [ - "stable", - "pip", - "distutils", - "tcltk", - "idle", - "tests", - "tools", - "venv", - "dev", - "symbols", - "bdist-wininst", - "chm", - ], - }, - "embed": { - "help": "embeddable package", - "options": ["stable", "zip-lib", "flat-dlls", "underpth", "precompile"], - }, -} - - -@public -def get_argparse_options(): - for opt, info in OPTIONS.items(): - help = "When specified, includes {}".format(info["help"]) - if info.get("not-in-all"): - help = "{}. Not affected by --include-all".format(help) - - yield "--include-{}".format(opt), help - - for opt, info in PRESETS.items(): - help = "When specified, includes default options for {}".format(info["help"]) - yield "--preset-{}".format(opt), help - - -def ns_get(ns, key, default=False): - return getattr(ns, key.replace("-", "_"), default) - - -def ns_set(ns, key, value=True): - k1 = key.replace("-", "_") - k2 = "include_{}".format(k1) - if hasattr(ns, k2): - setattr(ns, k2, value) - elif hasattr(ns, k1): - setattr(ns, k1, value) - else: - raise AttributeError("no argument named '{}'".format(k1)) - - -@public -def update_presets(ns): - for preset, info in PRESETS.items(): - if ns_get(ns, "preset-{}".format(preset)): - for opt in info["options"]: - ns_set(ns, opt) - - if ns.include_all: - for opt in OPTIONS: - if OPTIONS[opt].get("not-in-all"): - continue - ns_set(ns, opt) diff --git a/PC/layout/support/pip.py b/PC/layout/support/pip.py deleted file mode 100644 index 369a923ce13..00000000000 --- a/PC/layout/support/pip.py +++ /dev/null @@ -1,79 +0,0 @@ -""" -Extraction and file list generation for pip. -""" - -__author__ = "Steve Dower " -__version__ = "3.8" - - -import os -import shutil -import subprocess -import sys - -__all__ = [] - - -def public(f): - __all__.append(f.__name__) - return f - - -@public -def get_pip_dir(ns): - if ns.copy: - if ns.zip_lib: - return ns.copy / "packages" - return ns.copy / "Lib" / "site-packages" - else: - return ns.temp / "packages" - - -@public -def extract_pip_files(ns): - dest = get_pip_dir(ns) - dest.mkdir(parents=True, exist_ok=True) - - src = ns.source / "Lib" / "ensurepip" / "_bundled" - - ns.temp.mkdir(parents=True, exist_ok=True) - wheels = [shutil.copy(whl, ns.temp) for whl in src.glob("*.whl")] - search_path = os.pathsep.join(wheels) - if os.environ.get("PYTHONPATH"): - search_path += ";" + os.environ["PYTHONPATH"] - - env = os.environ.copy() - env["PYTHONPATH"] = search_path - - output = subprocess.check_output( - [ - sys.executable, - "-m", - "pip", - "--no-color", - "install", - "pip", - "setuptools", - "--upgrade", - "--target", - str(dest), - "--no-index", - "--no-cache-dir", - "-f", - str(src), - "--only-binary", - ":all:", - ], - env=env, - ) - - try: - shutil.rmtree(dest / "bin") - except OSError: - pass - - for file in wheels: - try: - os.remove(file) - except OSError: - pass diff --git a/PC/layout/support/props.py b/PC/layout/support/props.py deleted file mode 100644 index 3a047d21505..00000000000 --- a/PC/layout/support/props.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -Provides .props file. -""" - -import os - -from .constants import * - -__all__ = ["PYTHON_PROPS_NAME"] - - -def public(f): - __all__.append(f.__name__) - return f - - -PYTHON_PROPS_NAME = "python.props" - -PROPS_DATA = { - "PYTHON_TAG": VER_DOT, - "PYTHON_VERSION": os.getenv("PYTHON_NUSPEC_VERSION"), - "PYTHON_PLATFORM": os.getenv("PYTHON_PROPS_PLATFORM"), - "PYTHON_TARGET": "", -} - -if not PROPS_DATA["PYTHON_VERSION"]: - if VER_NAME: - PROPS_DATA["PYTHON_VERSION"] = "{}.{}-{}{}".format( - VER_DOT, VER_MICRO, VER_NAME, VER_SERIAL - ) - else: - PROPS_DATA["PYTHON_VERSION"] = "{}.{}".format(VER_DOT, VER_MICRO) - -if not PROPS_DATA["PYTHON_PLATFORM"]: - PROPS_DATA["PYTHON_PLATFORM"] = "x64" if IS_X64 else "Win32" - -PROPS_DATA["PYTHON_TARGET"] = "_GetPythonRuntimeFilesDependsOn{}{}_{}".format( - VER_MAJOR, VER_MINOR, PROPS_DATA["PYTHON_PLATFORM"] -) - -PROPS_TEMPLATE = r""" - - - $([msbuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), "python_d.exe") - $([msbuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), "python.exe") - $(PythonHome)\include - $(PythonHome)\libs - {PYTHON_TAG} - {PYTHON_VERSION} - - true - false - false - false - - {PYTHON_TARGET};$(GetPythonRuntimeFilesDependsOn) - - - - - $(PythonInclude);%(AdditionalIncludeDirectories) - MultiThreadedDLL - - - $(PythonLibs);%(AdditionalLibraryDirectories) - - - - - - - - <_PythonRuntimeExe Include="$(PythonHome)\python*.dll" /> - <_PythonRuntimeExe Include="$(PythonHome)\python*.exe" Condition="$(IncludePythonExe) == 'true'" /> - <_PythonRuntimeExe> - %(Filename)%(Extension) - - <_PythonRuntimeDlls Include="$(PythonHome)\DLLs\*.pyd" /> - <_PythonRuntimeDlls Include="$(PythonHome)\DLLs\*.dll" /> - <_PythonRuntimeDlls> - DLLs\%(Filename)%(Extension) - - <_PythonRuntimeLib Include="$(PythonHome)\Lib\**\*" Exclude="$(PythonHome)\Lib\**\*.pyc;$(PythonHome)\Lib\site-packages\**\*" /> - <_PythonRuntimeLib Remove="$(PythonHome)\Lib\distutils\**\*" Condition="$(IncludeDistutils) != 'true'" /> - <_PythonRuntimeLib Remove="$(PythonHome)\Lib\lib2to3\**\*" Condition="$(IncludeLib2To3) != 'true'" /> - <_PythonRuntimeLib Remove="$(PythonHome)\Lib\ensurepip\**\*" Condition="$(IncludeVEnv) != 'true'" /> - <_PythonRuntimeLib Remove="$(PythonHome)\Lib\venv\**\*" Condition="$(IncludeVEnv) != 'true'" /> - <_PythonRuntimeLib> - Lib\%(RecursiveDir)%(Filename)%(Extension) - - - - - - - -""" - - -@public -def get_props_layout(ns): - if ns.include_all or ns.include_props: - yield "python.props", ns.temp / "python.props" - - -@public -def get_props(ns): - # TODO: Filter contents of props file according to included/excluded items - props = PROPS_TEMPLATE.format_map(PROPS_DATA) - return props.encode("utf-8") diff --git a/PC/pylauncher.rc b/PC/pylauncher.rc index 92987af7138..3da3445f5fc 100644 --- a/PC/pylauncher.rc +++ b/PC/pylauncher.rc @@ -7,11 +7,6 @@ #include 1 RT_MANIFEST "python.manifest" -#if defined(PY_ICON) -1 ICON DISCARDABLE "icons\python.ico" -#elif defined(PYW_ICON) -1 ICON DISCARDABLE "icons\pythonw.ico" -#else 1 ICON DISCARDABLE "icons\launcher.ico" 2 ICON DISCARDABLE "icons\py.ico" 3 ICON DISCARDABLE "icons\pyc.ico" @@ -19,7 +14,6 @@ 5 ICON DISCARDABLE "icons\python.ico" 6 ICON DISCARDABLE "icons\pythonw.ico" 7 ICON DISCARDABLE "icons\setup.ico" -#endif ///////////////////////////////////////////////////////////////////////////// // diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp deleted file mode 100644 index 1658d05994b..00000000000 --- a/PC/python_uwp.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* Main program when embedded in a UWP application on Windows */ - -#include "Python.h" -#include - -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include - -#ifdef PYTHONW -#ifdef _DEBUG -const wchar_t *PROGNAME = L"pythonw_d.exe"; -#else -const wchar_t *PROGNAME = L"pythonw.exe"; -#endif -#else -#ifdef _DEBUG -const wchar_t *PROGNAME = L"python_d.exe"; -#else -const wchar_t *PROGNAME = L"python.exe"; -#endif -#endif - -static void -set_user_base() -{ - wchar_t envBuffer[2048]; - try { - const auto appData = winrt::Windows::Storage::ApplicationData::Current(); - if (appData) { - const auto localCache = appData.LocalCacheFolder(); - if (localCache) { - auto path = localCache.Path(); - if (!path.empty() && - !wcscpy_s(envBuffer, path.c_str()) && - !wcscat_s(envBuffer, L"\\local-packages") - ) { - _wputenv_s(L"PYTHONUSERBASE", envBuffer); - } - } - } - } catch (...) { - } -} - -static const wchar_t * -get_argv0(const wchar_t *argv0) -{ - winrt::hstring installPath; - const wchar_t *launcherPath; - wchar_t *buffer; - size_t len; - - launcherPath = _wgetenv(L"__PYVENV_LAUNCHER__"); - if (launcherPath && launcherPath[0]) { - len = wcslen(launcherPath) + 1; - buffer = (wchar_t *)malloc(sizeof(wchar_t) * len); - if (!buffer) { - Py_FatalError("out of memory"); - return NULL; - } - if (wcscpy_s(buffer, len, launcherPath)) { - Py_FatalError("failed to copy to buffer"); - return NULL; - } - return buffer; - } - - try { - const auto package = winrt::Windows::ApplicationModel::Package::Current(); - if (package) { - const auto install = package.InstalledLocation(); - if (install) { - installPath = install.Path(); - } - } - } - catch (...) { - } - - if (!installPath.empty()) { - len = installPath.size() + wcslen(PROGNAME) + 2; - } else { - len = wcslen(argv0) + wcslen(PROGNAME) + 1; - } - - buffer = (wchar_t *)malloc(sizeof(wchar_t) * len); - if (!buffer) { - Py_FatalError("out of memory"); - return NULL; - } - - if (!installPath.empty()) { - if (wcscpy_s(buffer, len, installPath.c_str())) { - Py_FatalError("failed to copy to buffer"); - return NULL; - } - if (wcscat_s(buffer, len, L"\\")) { - Py_FatalError("failed to concatenate backslash"); - return NULL; - } - } else { - if (wcscpy_s(buffer, len, argv0)) { - Py_FatalError("failed to copy argv[0]"); - return NULL; - } - - wchar_t *name = wcsrchr(buffer, L'\\'); - if (name) { - name[1] = L'\0'; - } else { - buffer[0] = L'\0'; - } - } - - if (wcscat_s(buffer, len, PROGNAME)) { - Py_FatalError("failed to concatenate program name"); - return NULL; - } - - return buffer; -} - -static wchar_t * -get_process_name() -{ - DWORD bufferLen = MAX_PATH; - DWORD len = bufferLen; - wchar_t *r = NULL; - - while (!r) { - r = (wchar_t *)malloc(bufferLen * sizeof(wchar_t)); - if (!r) { - Py_FatalError("out of memory"); - return NULL; - } - len = GetModuleFileNameW(NULL, r, bufferLen); - if (len == 0) { - free((void *)r); - return NULL; - } else if (len == bufferLen && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - free(r); - r = NULL; - bufferLen *= 2; - } - } - - return r; -} - -int -wmain(int argc, wchar_t **argv) -{ - const wchar_t **new_argv; - int new_argc; - const wchar_t *exeName; - - new_argc = argc; - new_argv = (const wchar_t**)malloc(sizeof(wchar_t *) * (argc + 2)); - if (new_argv == NULL) { - Py_FatalError("out of memory"); - return -1; - } - - exeName = get_process_name(); - - new_argv[0] = get_argv0(exeName ? exeName : argv[0]); - for (int i = 1; i < argc; ++i) { - new_argv[i] = argv[i]; - } - - set_user_base(); - - if (exeName) { - const wchar_t *p = wcsrchr(exeName, L'\\'); - if (p) { - const wchar_t *moduleName = NULL; - if (*p++ == L'\\') { - if (wcsnicmp(p, L"pip", 3) == 0) { - moduleName = L"pip"; - _wputenv_s(L"PIP_USER", L"true"); - } - else if (wcsnicmp(p, L"idle", 4) == 0) { - moduleName = L"idlelib"; - } - } - - if (moduleName) { - new_argc += 2; - for (int i = argc; i >= 1; --i) { - new_argv[i + 2] = new_argv[i]; - } - new_argv[1] = L"-m"; - new_argv[2] = moduleName; - } - } - } - - /* Override program_full_path from here so that - sys.executable is set correctly. */ - _Py_SetProgramFullPath(new_argv[0]); - - int result = Py_Main(new_argc, (wchar_t **)new_argv); - - free((void *)exeName); - free((void *)new_argv); - - return result; -} - -#ifdef PYTHONW - -int WINAPI wWinMain( - HINSTANCE hInstance, /* handle to current instance */ - HINSTANCE hPrevInstance, /* handle to previous instance */ - LPWSTR lpCmdLine, /* pointer to command line */ - int nCmdShow /* show state of window */ -) -{ - return wmain(__argc, __wargv); -} - -#endif diff --git a/PC/store_info.txt b/PC/store_info.txt deleted file mode 100644 index ed40a918e2e..00000000000 --- a/PC/store_info.txt +++ /dev/null @@ -1,146 +0,0 @@ -# Overview - -NOTE: This file requires more content. - -Since Python 3.8.2, releases have been made through the Microsoft Store -to allow easy installation on Windows 10.0.17763.0 and later. - -# Building - -To build the store package, the PC/layout script should be used. -Execute the directory with the build of Python to package, and pass -"-h" for full command-line options. - -To sideload test builds, you will need a local certificate. -Instructions are available at -https://docs.microsoft.com/windows/uwp/packaging/create-certificate-package-signing. - -After exporting your certificate, you will need the subject name and -SHA256 hash. The `certutil -dump ` command will display this -information. - -To build for sideloading, use these commands in PowerShell: - -``` -$env:APPX_DATA_PUBLISHER= -$env:APPX_DATA_SHA256= -$env:SigningCertificateFile= - -python PC/layout --copy --include-appxmanifest -Tools/msi/make_appx.ps1 python.msix -sign - -Add-AppxPackage python.msix -``` - -(Note that only the last command requires PowerShell, and the others -can be used from Command Prompt. You can also double-click to install -the final package.) - -To build for publishing to the Store, use these commands: - -``` -$env:APPX_DATA_PUBLISHER = $null -$env:APPX_DATA_SHA256 = $null - -python PC/layout --copy --preset-appxmanifest --precompile -Tools/msi/make_appx.ps1 python.msix -``` - -Note that this package cannot be installed locally. It may only be -added to a submission for the store. - - -# Submission Metadata - -This file contains the text that we use to fill out the store listing -for the Microsoft Store. It needs to be entered manually when creating -a new submission via the dashboard at -https://partner.microsoft.com/dashboard. - -We keep it here for convenience and to allow it to be updated via pull -requests. - -## Title - -Python 3.8 - -## Short Title - -Python - -## Description - -Python is an easy to learn, powerful programming language. It has efficient high-level data structures and a simple but effective approach to object-oriented programming. Python’s elegant syntax and dynamic typing, together with its interpreted nature, make it an ideal language for scripting and rapid application development in many areas on most platforms. - -The Python interpreter and the extensive standard library are freely available in source or binary form for all major platforms from the Python Web site, https://www.python.org/, and may be freely distributed. The same site also contains distributions of and pointers to many free third party Python modules, programs and tools, and additional documentation. - -The Python interpreter is easily extended with new functions and data types implemented in C or C++ (or other languages callable from C). Python is also suitable as an extension language for customizable applications. - -## ShortDescription - -The Python 3.8 interpreter and runtime. - -## Copyright Trademark Information - -(c) Python Software Foundation - -## Additional License Terms - -Visit https://docs.python.org/3.8/license.html for latest license terms. - -PSF LICENSE AGREEMENT FOR PYTHON 3.8 - -1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and - the Individual or Organization ("Licensee") accessing and otherwise using Python - 3.8 software in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby - grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, - analyze, test, perform and/or display publicly, prepare derivative works, - distribute, and otherwise use Python 3.8 alone or in any derivative - version, provided, however, that PSF's License Agreement and PSF's notice of - copyright, i.e., "Copyright © 2001-2018 Python Software Foundation; All Rights - Reserved" are retained in Python 3.8 alone or in any derivative version - prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on or - incorporates Python 3.8 or any part thereof, and wants to make the - derivative work available to others as provided herein, then Licensee hereby - agrees to include in any such work a brief summary of the changes made to Python - 3.8. - -4. PSF is making Python 3.8 available to Licensee on an "AS IS" basis. - PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF - EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR - WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE - USE OF PYTHON 3.8 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.8 - FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF - MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.8, OR ANY DERIVATIVE - THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material breach of - its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any relationship - of agency, partnership, or joint venture between PSF and Licensee. This License - Agreement does not grant permission to use PSF trademarks or trade name in a - trademark sense to endorse or promote products or services of Licensee, or any - third party. - -8. By copying, installing or otherwise using Python 3.8, Licensee agrees - to be bound by the terms and conditions of this License Agreement. - -## Features - -* Easy to install Python runtime -* Supported by core CPython team -* Find Python, Pip and Idle on PATH - -## Search Terms - -* Python -* Scripting -* Interpreter - diff --git a/PCbuild/_tkinter.vcxproj b/PCbuild/_tkinter.vcxproj index bd61c0d4f68..95e3cd50eca 100644 --- a/PCbuild/_tkinter.vcxproj +++ b/PCbuild/_tkinter.vcxproj @@ -95,10 +95,4 @@ - - - - - - \ No newline at end of file diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index a2810f09c45..57512a01927 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -29,16 +29,6 @@ @where msbuild > "%TEMP%\msbuild.loc" 2> nul && set /P MSBUILD= < "%TEMP%\msbuild.loc" & del "%TEMP%\msbuild.loc" @if exist "%MSBUILD%" set MSBUILD="%MSBUILD%" & (set _Py_MSBuild_Source=PATH) & goto :found -@rem VS 2017 and later provide vswhere.exe, which can be used -@if not exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" goto :skip_vswhere -@set _Py_MSBuild_Root= -@for /F "tokens=*" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -latest') DO @(set _Py_MSBuild_Root=%%i\MSBuild) -@if not defined _Py_MSBuild_Root goto :skip_vswhere -@for %%j in (Current 15.0) DO @if exist "%_Py_MSBuild_Root%\%%j\Bin\msbuild.exe" (set MSBUILD="%_Py_MSBuild_Root%\%%j\Bin\msbuild.exe") -@set _Py_MSBuild_Root= -@if defined MSBUILD @if exist %MSBUILD% (set _Py_MSBuild_Source=Visual Studio installation) & goto :found -:skip_vswhere - @rem VS 2017 sets exactly one install as the "main" install, so we may find MSBuild in there. @reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v 15.0 /reg:32 >nul 2>nul @if NOT ERRORLEVEL 1 @for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v 15.0 /reg:32') DO @( diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj index 6bf1667e39f..9e103e12103 100644 --- a/PCbuild/pcbuild.proj +++ b/PCbuild/pcbuild.proj @@ -52,8 +52,6 @@ - - @@ -72,7 +70,6 @@ - diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln index c212d9f8f32..59b3861ed40 100644 --- a/PCbuild/pcbuild.sln +++ b/PCbuild/pcbuild.sln @@ -93,14 +93,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_queue", "_queue.vcxproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblzma", "liblzma.vcxproj", "{12728250-16EC-4DC6-94D7-E21DD88947F8}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python_uwp", "python_uwp.vcxproj", "{9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "venvlauncher", "venvlauncher.vcxproj", "{494BAC80-A60C-43A9-99E7-ACB691CE2C4D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "venvwlauncher", "venvwlauncher.vcxproj", "{FDB84CBB-2FB6-47C8-A2D6-091E0833239D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythonw_uwp", "pythonw_uwp.vcxproj", "{AB603547-1E2A-45B3-9E09-B04596006393}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -701,70 +693,6 @@ Global {12728250-16EC-4DC6-94D7-E21DD88947F8}.Release|Win32.Build.0 = Release|Win32 {12728250-16EC-4DC6-94D7-E21DD88947F8}.Release|x64.ActiveCfg = Release|x64 {12728250-16EC-4DC6-94D7-E21DD88947F8}.Release|x64.Build.0 = Release|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Debug|Win32.ActiveCfg = Debug|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Debug|Win32.Build.0 = Debug|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Debug|x64.ActiveCfg = Debug|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Debug|x64.Build.0 = Debug|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGInstrument|x64.Build.0 = PGInstrument|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.PGUpdate|x64.Build.0 = PGUpdate|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Release|Win32.ActiveCfg = Release|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Release|Win32.Build.0 = Release|Win32 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Release|x64.ActiveCfg = Release|x64 - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF}.Release|x64.Build.0 = Release|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Debug|Win32.ActiveCfg = Debug|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Debug|Win32.Build.0 = Debug|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Debug|x64.ActiveCfg = Debug|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Debug|x64.Build.0 = Debug|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGInstrument|x64.Build.0 = PGInstrument|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.PGUpdate|x64.Build.0 = PGUpdate|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Release|Win32.ActiveCfg = Release|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Release|Win32.Build.0 = Release|Win32 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Release|x64.ActiveCfg = Release|x64 - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D}.Release|x64.Build.0 = Release|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Debug|Win32.ActiveCfg = Debug|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Debug|Win32.Build.0 = Debug|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Debug|x64.ActiveCfg = Debug|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Debug|x64.Build.0 = Debug|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGInstrument|x64.Build.0 = PGInstrument|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.PGUpdate|x64.Build.0 = PGUpdate|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Release|Win32.ActiveCfg = Release|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Release|Win32.Build.0 = Release|Win32 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Release|x64.ActiveCfg = Release|x64 - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D}.Release|x64.Build.0 = Release|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.Debug|Win32.ActiveCfg = Debug|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.Debug|Win32.Build.0 = Debug|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.Debug|x64.ActiveCfg = Debug|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.Debug|x64.Build.0 = Debug|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGInstrument|Win32.ActiveCfg = PGInstrument|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGInstrument|Win32.Build.0 = PGInstrument|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGInstrument|x64.ActiveCfg = PGInstrument|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGInstrument|x64.Build.0 = PGInstrument|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGUpdate|Win32.ActiveCfg = PGUpdate|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGUpdate|Win32.Build.0 = PGUpdate|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGUpdate|x64.ActiveCfg = PGUpdate|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.PGUpdate|x64.Build.0 = PGUpdate|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.Release|Win32.ActiveCfg = Release|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.Release|Win32.Build.0 = Release|Win32 - {AB603547-1E2A-45B3-9E09-B04596006393}.Release|x64.ActiveCfg = Release|x64 - {AB603547-1E2A-45B3-9E09-B04596006393}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PCbuild/python.props b/PCbuild/python.props index 6dbb503b324..09f11d3bba8 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -77,8 +77,7 @@ --> <_RegistryVersion>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion) <_RegistryVersion Condition="$(_RegistryVersion) == ''">$(Registry:HKEY_LOCAL_MACHINE\WOW6432Node\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0@ProductVersion) - 10.0.17763.0 - 10.0.17134.0 + 10.0.17134.0 10.0.16299.0 10.0.15063.0 10.0.14393.0 diff --git a/PCbuild/python_uwp.vcxproj b/PCbuild/python_uwp.vcxproj deleted file mode 100644 index af187dd4df3..00000000000 --- a/PCbuild/python_uwp.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - PGInstrument - Win32 - - - PGInstrument - x64 - - - PGUpdate - Win32 - - - PGUpdate - x64 - - - Release - Win32 - - - Release - x64 - - - - {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF} - - - - - Application - false - Unicode - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - - - - %(PreprocessorDefinitions) - /EHsc /std:c++17 %(AdditionalOptions) - - - windowsapp.lib;%(AdditionalDependencies) - Console - - - - - - - - - - - - - - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - - - - - - diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 78ec9a16efa..4ae2d692eee 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -479,19 +479,4 @@ - - - $(VCInstallDir)\Redist\MSVC\$(VCToolsRedistVersion)\ - $(VCRedistDir)x86\ - $(VCRedistDir)$(Platform)\ - - - - - - - - - - diff --git a/PCbuild/pythonw_uwp.vcxproj b/PCbuild/pythonw_uwp.vcxproj deleted file mode 100644 index 79e105877fb..00000000000 --- a/PCbuild/pythonw_uwp.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - PGInstrument - Win32 - - - PGInstrument - x64 - - - PGUpdate - Win32 - - - PGUpdate - x64 - - - Release - Win32 - - - Release - x64 - - - - {AB603547-1E2A-45B3-9E09-B04596006393} - - - - - Application - false - Unicode - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - - - - PYTHONW;%(PreprocessorDefinitions) - /EHsc /std:c++17 %(AdditionalOptions) - - - windowsapp.lib;%(AdditionalDependencies) - Windows - - - - - - - - - - - - - - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - - - - - - diff --git a/PCbuild/venvlauncher.vcxproj b/PCbuild/venvlauncher.vcxproj deleted file mode 100644 index 295b3630473..00000000000 --- a/PCbuild/venvlauncher.vcxproj +++ /dev/null @@ -1,85 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - PGInstrument - Win32 - - - PGInstrument - x64 - - - PGUpdate - Win32 - - - PGUpdate - x64 - - - Release - Win32 - - - Release - x64 - - - - {494BAC80-A60C-43A9-99E7-ACB691CE2C4D} - venvlauncher - venvlauncher - false - - - - - Application - MultiByte - - - - - - ClCompile - - - - - - - - - _CONSOLE;VENV_REDIRECT;%(PreprocessorDefinitions) - MultiThreaded - - - PY_ICON;%(PreprocessorDefinitions) - - - version.lib;%(AdditionalDependencies) - Console - - - - - - - - - - - - - - - diff --git a/PCbuild/venvwlauncher.vcxproj b/PCbuild/venvwlauncher.vcxproj deleted file mode 100644 index e7ba25da41e..00000000000 --- a/PCbuild/venvwlauncher.vcxproj +++ /dev/null @@ -1,85 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - PGInstrument - Win32 - - - PGInstrument - x64 - - - PGUpdate - Win32 - - - PGUpdate - x64 - - - Release - Win32 - - - Release - x64 - - - - {FDB84CBB-2FB6-47C8-A2D6-091E0833239D} - venvwlauncher - venvwlauncher - false - - - - - Application - MultiByte - - - - - - ClCompile - - - - - - - - - _WINDOWS;VENV_REDIRECT;%(PreprocessorDefinitions) - MultiThreaded - - - PYW_ICON;%(PreprocessorDefinitions) - - - version.lib;%(AdditionalDependencies) - Windows - - - - - - - - - - - - - - - diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat index 45e189b537f..4178981195e 100644 --- a/Tools/msi/buildrelease.bat +++ b/Tools/msi/buildrelease.bat @@ -37,7 +37,6 @@ set BUILDX64= set TARGET=Rebuild set TESTTARGETDIR= set PGO=-m test -q --pgo -set BUILDMSI=1 set BUILDNUGET=1 set BUILDZIP=1 @@ -62,7 +61,6 @@ if "%1" EQU "--pgo" (set PGO=%~2) && shift && shift && goto CheckOpts if "%1" EQU "--skip-pgo" (set PGO=) && shift && goto CheckOpts if "%1" EQU "--skip-nuget" (set BUILDNUGET=) && shift && goto CheckOpts if "%1" EQU "--skip-zip" (set BUILDZIP=) && shift && goto CheckOpts -if "%1" EQU "--skip-msi" (set BUILDMSI=) && shift && goto CheckOpts if "%1" NEQ "" echo Invalid option: "%1" && exit /B 1 @@ -176,12 +174,10 @@ if "%OUTDIR_PLAT%" EQU "win32" ( ) set BUILDOPTS=/p:Platform=%1 /p:BuildForRelease=true /p:DownloadUrl=%DOWNLOAD_URL% /p:DownloadUrlBase=%DOWNLOAD_URL_BASE% /p:ReleaseUri=%RELEASE_URI% -if defined BUILDMSI ( - %MSBUILD% "%D%bundle\releaselocal.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true - if errorlevel 1 exit /B - %MSBUILD% "%D%bundle\releaseweb.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false - if errorlevel 1 exit /B -) +%MSBUILD% "%D%bundle\releaselocal.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=true +if errorlevel 1 exit /B +%MSBUILD% "%D%bundle\releaseweb.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false +if errorlevel 1 exit /B if defined BUILDZIP ( %MSBUILD% "%D%make_zip.proj" /t:Build %BUILDOPTS% %CERTOPTS% /p:OutputPath="%BUILD%en-us" @@ -218,7 +214,6 @@ echo --skip-build (-B) Do not build Python (just do the installers) echo --skip-doc (-D) Do not build documentation echo --pgo Specify PGO command for x64 installers echo --skip-pgo Build x64 installers without using PGO -echo --skip-msi Do not build executable/MSI packages echo --skip-nuget Do not build Nuget packages echo --skip-zip Do not build embeddable package echo --download Specify the full download URL for MSIs diff --git a/Tools/msi/make_appx.ps1 b/Tools/msi/make_appx.ps1 deleted file mode 100644 index b3f190e07db..00000000000 --- a/Tools/msi/make_appx.ps1 +++ /dev/null @@ -1,71 +0,0 @@ -<# -.Synopsis - Compiles and signs an APPX package -.Description - Given the file listing, ensures all the contents are signed - and builds and signs the final package. -.Parameter mapfile - The location on disk of the text mapping file. -.Parameter msix - The path and name to store the APPX/MSIX. -.Parameter sign - When set, signs the APPX/MSIX. Packages to be published to - the store should not be signed. -.Parameter description - Description to embed in the signature (optional). -.Parameter certname - The name of the certificate to sign with (optional). -.Parameter certsha1 - The SHA1 hash of the certificate to sign with (optional). -#> -param( - [Parameter(Mandatory=$true)][string]$layout, - [Parameter(Mandatory=$true)][string]$msix, - [switch]$sign, - [string]$description, - [string]$certname, - [string]$certsha1, - [string]$certfile -) - -$tools = $script:MyInvocation.MyCommand.Path | Split-Path -parent; -Import-Module $tools\sdktools.psm1 -WarningAction SilentlyContinue -Force - -Set-Alias makeappx (Find-Tool "makeappx.exe") -Scope Script -Set-Alias makepri (Find-Tool "makepri.exe") -Scope Script - -$msixdir = Split-Path $msix -Parent -if ($msixdir) { - $msixdir = (mkdir -Force $msixdir).FullName -} else { - $msixdir = Get-Location -} -$msix = Join-Path $msixdir (Split-Path $msix -Leaf) - -pushd $layout -try { - if (Test-Path resources.pri) { - del resources.pri - } - $name = ([xml](gc AppxManifest.xml)).Package.Identity.Name - makepri new /pr . /mn AppxManifest.xml /in $name /cf _resources.xml /of _resources.pri /mf appx /o - if (-not $? -or -not (Test-Path _resources.map.txt)) { - throw "makepri step failed" - } - $lines = gc _resources.map.txt - $lines | ?{ -not ($_ -match '"_resources[\w\.]+?"') } | Out-File _resources.map.txt -Encoding utf8 - makeappx pack /f _resources.map.txt /m AppxManifest.xml /o /p $msix - if (-not $?) { - throw "makeappx step failed" - } -} finally { - popd -} - -if ($sign) { - Sign-File -certname $certname -certsha1 $certsha1 -certfile $certfile -description $description -files $msix - - if (-not $?) { - throw "Package signing failed" - } -} diff --git a/Tools/msi/make_cat.ps1 b/Tools/msi/make_cat.ps1 deleted file mode 100644 index 70741439869..00000000000 --- a/Tools/msi/make_cat.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -<# -.Synopsis - Compiles and signs a catalog file. -.Description - Given the CDF definition file, builds and signs a catalog. -.Parameter catalog - The path to the catalog definition file to compile and - sign. It is assumed that the .cat file will be the same - name with a new extension. -.Parameter description - The description to add to the signature (optional). -.Parameter certname - The name of the certificate to sign with (optional). -.Parameter certsha1 - The SHA1 hash of the certificate to sign with (optional). -#> -param( - [Parameter(Mandatory=$true)][string]$catalog, - [string]$description, - [string]$certname, - [string]$certsha1, - [string]$certfile -) - -$tools = $script:MyInvocation.MyCommand.Path | Split-Path -parent; -Import-Module $tools\sdktools.psm1 -WarningAction SilentlyContinue -Force - -Set-Alias MakeCat (Find-Tool "makecat.exe") -Scope Script - -MakeCat $catalog -if (-not $?) { - throw "Catalog compilation failed" -} -Sign-File -certname $certname -certsha1 $certsha1 -certfile $certfile -description $description -files @($catalog -replace 'cdf$', 'cat') diff --git a/Tools/msi/make_zip.proj b/Tools/msi/make_zip.proj index 125a434e51f..21411173421 100644 --- a/Tools/msi/make_zip.proj +++ b/Tools/msi/make_zip.proj @@ -15,12 +15,11 @@ .zip $(OutputPath)\$(TargetName)$(TargetExt) rmdir /q/s "$(IntermediateOutputPath)\zip_$(ArchName)" - "$(PythonExe)" "$(PySourcePath)PC\layout" - $(Arguments) -b "$(BuildPath.TrimEnd(`\`))" -s "$(PySourcePath.TrimEnd(`\`))" - $(Arguments) -t "$(IntermediateOutputPath)\zip_$(ArchName)" - $(Arguments) --zip "$(TargetPath)" - $(Arguments) --precompile --zip-lib --include-underpth --include-stable --flat-dlls + "$(PythonExe)" "$(MSBuildThisFileDirectory)\make_zip.py" + $(Arguments) -e -o "$(TargetPath)" -t "$(IntermediateOutputPath)\zip_$(ArchName)" -b "$(BuildPath.TrimEnd(`\`))" + set DOC_FILENAME=python$(PythonVersion).chm $(Environment)%0D%0Aset PYTHONPATH=$(PySourcePath)Lib + $(Environment)%0D%0Aset VCREDIST_PATH=$(CRTRedist)\$(Platform) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py new file mode 100644 index 00000000000..58f3b15ef85 --- /dev/null +++ b/Tools/msi/make_zip.py @@ -0,0 +1,250 @@ +import argparse +import py_compile +import re +import sys +import shutil +import stat +import os +import tempfile + +from itertools import chain +from pathlib import Path +from zipfile import ZipFile, ZIP_DEFLATED + + +TKTCL_RE = re.compile(r'^(_?tk|tcl).+\.(pyd|dll)', re.IGNORECASE) +DEBUG_RE = re.compile(r'_d\.(pyd|dll|exe|pdb|lib)$', re.IGNORECASE) +PYTHON_DLL_RE = re.compile(r'python\d\d?\.dll$', re.IGNORECASE) + +DEBUG_FILES = { + '_ctypes_test', + '_testbuffer', + '_testcapi', + '_testconsole', + '_testimportmultiple', + '_testmultiphase', + 'xxlimited', + 'python3_dstub', +} + +EXCLUDE_FROM_LIBRARY = { + '__pycache__', + 'idlelib', + 'pydoc_data', + 'site-packages', + 'tkinter', + 'turtledemo', +} + +EXCLUDE_FROM_EMBEDDABLE_LIBRARY = { + 'ensurepip', + 'venv', +} + +EXCLUDE_FILE_FROM_LIBRARY = { + 'bdist_wininst.py', +} + +EXCLUDE_FILE_FROM_LIBS = { + 'liblzma', + 'python3stub', +} + +EXCLUDED_FILES = { + 'pyshellext', +} + +def is_not_debug(p): + if DEBUG_RE.search(p.name): + return False + + if TKTCL_RE.search(p.name): + return False + + 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) + +def include_in_lib(p): + name = p.name.lower() + if p.is_dir(): + if name in EXCLUDE_FROM_LIBRARY: + return False + if name == 'test' and p.parts[-2].lower() == 'lib': + return False + if name in {'test', 'tests'} and p.parts[-3].lower() == 'lib': + return False + return True + + if name in EXCLUDE_FILE_FROM_LIBRARY: + return False + + suffix = p.suffix.lower() + return suffix not in {'.pyc', '.pyo', '.exe'} + +def include_in_embeddable_lib(p): + if p.is_dir() and p.name.lower() in EXCLUDE_FROM_EMBEDDABLE_LIBRARY: + return False + + return include_in_lib(p) + +def include_in_libs(p): + if not is_not_debug(p): + return False + + return p.stem.lower() not in EXCLUDE_FILE_FROM_LIBS + +def include_in_tools(p): + if p.is_dir() and p.name.lower() in {'scripts', 'i18n', 'pynche', 'demo', 'parser'}: + return True + + 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{}.dll'.format(sys.version_info.major), is_not_debug), + ('/', '$build', '{}.dll'.format(BASE_NAME), is_not_debug), + ('DLLs/', '$build', '*.pyd', is_not_debug), + ('DLLs/', '$build', '*.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), + ('Tools/', 'Tools', '**/*', include_in_tools), +] + +EMBED_LAYOUT = [ + ('/', '$build', 'python*.exe', is_not_debug), + ('/', '$build', '*.pyd', is_not_debug), + ('/', '$build', '*.dll', is_not_debug), + ('{}.zip'.format(BASE_NAME), 'Lib', '**/*', include_in_embeddable_lib), +] + +if os.getenv('DOC_FILENAME'): + FULL_LAYOUT.append(('Doc/', 'Doc/build/htmlhelp', os.getenv('DOC_FILENAME'), None)) +if os.getenv('VCREDIST_PATH'): + FULL_LAYOUT.append(('/', os.getenv('VCREDIST_PATH'), 'vcruntime*.dll', None)) + EMBED_LAYOUT.append(('/', os.getenv('VCREDIST_PATH'), 'vcruntime*.dll', None)) + +def copy_to_layout(target, rel_sources): + count = 0 + + if target.suffix.lower() == '.zip': + if target.exists(): + target.unlink() + + with ZipFile(str(target), 'w', ZIP_DEFLATED) as f: + with tempfile.TemporaryDirectory() as tmpdir: + for s, rel in rel_sources: + if rel.suffix.lower() == '.py': + pyc = Path(tmpdir) / rel.with_suffix('.pyc').name + try: + py_compile.compile(str(s), str(pyc), str(rel), doraise=True, optimize=2) + except py_compile.PyCompileError: + f.write(str(s), str(rel)) + else: + f.write(str(pyc), str(rel.with_suffix('.pyc'))) + else: + f.write(str(s), str(rel)) + count += 1 + + else: + for s, rel in rel_sources: + dest = target / rel + try: + dest.parent.mkdir(parents=True) + except FileExistsError: + pass + if dest.is_file(): + dest.chmod(stat.S_IWRITE) + shutil.copy(str(s), str(dest)) + if dest.is_file(): + dest.chmod(stat.S_IWRITE) + count += 1 + + return count + +def rglob(root, pattern, condition): + dirs = [root] + recurse = pattern[:3] in {'**/', '**\\'} + while dirs: + d = dirs.pop(0) + for f in d.glob(pattern[3:] if recurse else pattern): + if recurse and f.is_dir() and (not condition or condition(f)): + dirs.append(f) + elif f.is_file() and (not condition or condition(f)): + yield f, f.relative_to(root) + +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('-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, default=None) + ns = parser.parse_args() + + source = ns.source or (Path(__file__).resolve().parent.parent.parent) + out = ns.out + build = ns.build or Path(sys.exec_prefix) + assert isinstance(source, Path) + assert not out or isinstance(out, Path) + assert isinstance(build, Path) + + if ns.temp: + temp = ns.temp + delete_temp = False + else: + temp = Path(tempfile.mkdtemp()) + delete_temp = True + + if out: + try: + out.parent.mkdir(parents=True) + except FileExistsError: + pass + try: + temp.mkdir(parents=True) + except FileExistsError: + pass + + layout = EMBED_LAYOUT if ns.embed else FULL_LAYOUT + + try: + for t, s, p, c in layout: + if s == '$build': + fs = build + else: + fs = source / s + files = rglob(fs, p, c) + extra_files = [] + if s == 'Lib' and p == '**/*': + extra_files.append(( + source / 'tools' / 'msi' / 'distutils.command.bdist_wininst.py', + Path('distutils') / 'command' / 'bdist_wininst.py' + )) + copied = copy_to_layout(temp / t.rstrip('/'), chain(files, extra_files)) + print('Copied {} files'.format(copied)) + + 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)) + print('Wrote {} files to {}'.format(total, out)) + finally: + if delete_temp: + shutil.rmtree(temp, True) + + +if __name__ == "__main__": + sys.exit(int(main() or 0)) diff --git a/Tools/msi/sdktools.psm1 b/Tools/msi/sdktools.psm1 deleted file mode 100644 index 81a74d3679d..00000000000 --- a/Tools/msi/sdktools.psm1 +++ /dev/null @@ -1,43 +0,0 @@ -function Find-Tool { - param([string]$toolname) - - $kitroot = (gp 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots\').KitsRoot10 - $tool = (gci -r "$kitroot\Bin\*\x64\$toolname" | sort FullName -Desc | select -First 1) - if (-not $tool) { - throw "$toolname is not available" - } - Write-Host "Found $toolname at $($tool.FullName)" - return $tool.FullName -} - -Set-Alias SignTool (Find-Tool "signtool.exe") -Scope Script - -function Sign-File { - param([string]$certname, [string]$certsha1, [string]$certfile, [string]$description, [string[]]$files) - - if (-not $description) { - $description = $env:SigningDescription; - if (-not $description) { - $description = "Python"; - } - } - if (-not $certname) { - $certname = $env:SigningCertificate; - } - if (-not $certfile) { - $certfile = $env:SigningCertificateFile; - } - - foreach ($a in $files) { - if ($certsha1) { - SignTool sign /sha1 $certsha1 /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a - } elseif ($certname) { - SignTool sign /n $certname /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a - } elseif ($certfile) { - SignTool sign /f $certfile /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a - } else { - SignTool sign /a /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a - } - } -} - diff --git a/Tools/msi/sign_build.ps1 b/Tools/msi/sign_build.ps1 deleted file mode 100644 index 6668eb33a2d..00000000000 --- a/Tools/msi/sign_build.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -<# -.Synopsis - Recursively signs the contents of a directory. -.Description - Given the file patterns, code signs the contents. -.Parameter root - The root directory to sign. -.Parameter patterns - The file patterns to sign -.Parameter description - The description to add to the signature (optional). -.Parameter certname - The name of the certificate to sign with (optional). -.Parameter certsha1 - The SHA1 hash of the certificate to sign with (optional). -#> -param( - [Parameter(Mandatory=$true)][string]$root, - [string[]]$patterns=@("*.exe", "*.dll", "*.pyd"), - [string]$description, - [string]$certname, - [string]$certsha1, - [string]$certfile -) - -$tools = $script:MyInvocation.MyCommand.Path | Split-Path -parent; -Import-Module $tools\sdktools.psm1 -WarningAction SilentlyContinue -Force - -pushd $root -try { - Sign-File -certname $certname -certsha1 $certsha1 -certfile $certfile -description $description -files (gci -r $patterns) -} finally { - popd -} \ No newline at end of file diff --git a/Tools/nuget/make_pkg.proj b/Tools/nuget/make_pkg.proj index e093a6d0bd7..9843bc97ccd 100644 --- a/Tools/nuget/make_pkg.proj +++ b/Tools/nuget/make_pkg.proj @@ -20,28 +20,25 @@ false $(OutputName).$(NuspecVersion) .nupkg - $(IntermediateOutputPath)\nuget_$(ArchName)\ + $(IntermediateOutputPath)\nuget_$(ArchName) - rmdir /q/s "$(IntermediateOutputPath.TrimEnd(`\`))" + rmdir /q/s "$(IntermediateOutputPath)" - "$(PythonExe)" "$(PySourcePath)PC\layout" - $(PythonArguments) -b "$(BuildPath.TrimEnd(`\`))" -s "$(PySourcePath.TrimEnd(`\`))" - $(PythonArguments) -t "$(IntermediateOutputPath)obj" - $(PythonArguments) --copy "$(IntermediateOutputPath)pkg" - $(PythonArguments) --include-dev --include-tools --include-pip --include-stable --include-launcher --include-props + "$(PythonExe)" "$(MSBuildThisFileDirectory)\..\msi\make_zip.py" + $(PythonArguments) -t "$(IntermediateOutputPath)" -b "$(BuildPath.TrimEnd(`\`))" - "$(IntermediateOutputPath)pkg\pip.exe" -B -m pip install -U $(Packages) + "$(IntermediateOutputPath)\python.exe" -B -c "import sys; sys.path.append(r'$(PySourcePath)\Lib'); import ensurepip; ensurepip._main()" + "$(IntermediateOutputPath)\python.exe" -B -m pip install -U $(Packages) - "$(Nuget)" pack "$(MSBuildThisFileDirectory)\$(OutputName).nuspec" -BasePath "$(IntermediateOutputPath)pkg" + "$(Nuget)" pack "$(MSBuildThisFileDirectory)\$(OutputName).nuspec" -BasePath "$(IntermediateOutputPath)" "$(Nuget)" pack "$(MSBuildThisFileDirectory)\$(OutputName).symbols.nuspec" -BasePath "$(BuildPath.TrimEnd(`\`))" $(NugetArguments) -OutputDirectory "$(OutputPath.Trim(`\`))" $(NugetArguments) -Version "$(NuspecVersion)" $(NugetArguments) -NoPackageAnalysis -NonInteractive + set DOC_FILENAME=python$(PythonVersion).chm $(Environment)%0D%0Aset PYTHONPATH=$(PySourcePath)Lib - $(Environment)%0D%0Aset PYTHON_NUSPEC_VERSION=$(NuspecVersion) - $(Environment)%0D%0Aset PYTHON_PROPS_PLATFORM=$(Platform) - $(Environment)%0D%0Aset PYTHON_PROPS_PLATFORM=Win32 + $(Environment)%0D%0Aset VCREDIST_PATH=$(CRTRedist)\$(Platform) $(Environment)%0D%0Amkdir "$(OutputPath.Trim(`\`))" >nul 2>nul @@ -51,7 +48,22 @@ - + + + + + + <_PropsContents>$([System.IO.File]::ReadAllText('python.props')) + <_PropsContents>$(_PropsContents.Replace('$$PYTHON_TAG$$', '$(MajorVersionNumber).$(MinorVersionNumber)')) + <_PropsContents>$(_PropsContents.Replace('$$PYTHON_VERSION$$', '$(NuspecVersion)')) + <_PropsContents Condition="$(Platform) == 'x86'">$(_PropsContents.Replace('$$PYTHON_PLATFORM$$', 'Win32')) + <_PropsContents Condition="$(Platform) != 'x86'">$(_PropsContents.Replace('$$PYTHON_PLATFORM$$', '$(Platform)')) + <_PropsContents>$(_PropsContents.Replace('$$PYTHON_TARGET$$', '_GetPythonRuntimeFilesDependsOn$(MajorVersionNumber)$(MinorVersionNumber)_$(Platform)')) + <_ExistingContents Condition="Exists('$(IntermediateOutputPath)\python.props')">$([System.IO.File]::ReadAllText('$(IntermediateOutputPath)\python.props')) + + diff --git a/PC/layout/support/python.props b/Tools/nuget/python.props similarity index 100% rename from PC/layout/support/python.props rename to Tools/nuget/python.props