From a3c8eb5f9d2b982d24fe7ed8f82ead35383862c1 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 21 Jun 2023 00:21:22 +0200 Subject: [PATCH 001/102] wip --- recipes/cpython/all/conanfile.py | 228 +++++++++++++++---------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 4fa1d1da6334e..26c60df37af1c 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -1,11 +1,18 @@ -from conans import AutoToolsBuildEnvironment, ConanFile, MSBuild, tools -from conans.errors import ConanInvalidConfiguration +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.microsoft import MSBuild, is_msvc, MSBuildDeps, MSBuildToolchain +from conan.tools.scm import Version +from conan.tools.apple import is_apple_os +from conan.tools.files import rmdir, copy, replace_in_file, rename, mkdir, get + +from conans import AutoToolsBuildEnvironment, tools + from io import StringIO import os import re import textwrap -required_conan_version = ">=1.33.0" +required_conan_version = ">=1.58.0" class CPythonConan(ConanFile): @@ -70,38 +77,28 @@ class CPythonConan(ConanFile): def _source_subfolder(self): return "source_subfolder" - @property - def _version_number_only(self): - return re.match(r"^([0-9.]+)", self.version).group(1) - - @property - def _version_tuple(self): - return tuple(self._version_number_only.split(".")) - @property def _supports_modules(self): - return self.settings.compiler != "Visual Studio" or self.options.shared + return not is_msvc(self) or self.options.shared @property def _version_suffix(self): - if self.settings.compiler == "Visual Studio": - joiner = "" - else: - joiner = "." - return joiner.join(self._version_tuple[:2]) + v = Version(self.version) + joiner = "" if is_msvc(self) else "." + return f"{v.major}{joiner}{v.minor}" @property def _is_py3(self): - return tools.Version(self._version_number_only).major == "3" + return Version(self.version).major == "3" @property def _is_py2(self): - return tools.Version(self._version_number_only).major == "2" + return Version(self.version).major == "2" def config_options(self): if self.settings.os == "Windows": del self.options.fPIC - if self.settings.compiler == "Visual Studio": + if is_msvc(self): del self.options.lto del self.options.docstrings del self.options.pymalloc @@ -123,21 +120,27 @@ def configure(self): if self.options.shared: del self.options.fPIC if not self._supports_modules: - del self.options.with_bz2 - del self.options.with_sqlite3 - del self.options.with_tkinter + del self.options.with_bz2 + del self.options.with_sqlite3 + del self.options.with_tkinter - del self.options.with_bsddb - del self.options.with_lzma - if self.settings.compiler == "Visual Studio": + del self.options.with_bsddb + del self.options.with_lzma + + def generate(self): + if is_msvc(self): # The msbuild generator only works with Visual Studio - self.generators.append("MSBuildDeps") + deps = MSBuildDeps(self) + deps.generate() + # The toolchain.props is not injected yet, but it also generates VCVars + toolchain = MSBuildToolchain(self) + toolchain.generate() def validate(self): if self.options.shared: - if self.settings.compiler == "Visual Studio" and "MT" in self.settings.compiler.runtime: + if is_msvc(self) and "MT" in self.settings.compiler.runtime: raise ConanInvalidConfiguration("cpython does not support MT(d) runtime when building a shared cpython library") - if self.settings.compiler == "Visual Studio": + if is_msvc(self): if self.options.optimizations: raise ConanInvalidConfiguration("This recipe does not support optimized MSVC cpython builds (yet)") # FIXME: should probably throw when cross building @@ -147,30 +150,39 @@ def validate(self): # 3. build the MSVC PGUpdate build_type if self.settings.build_type == "Debug" and "d" not in self.settings.compiler.runtime: raise ConanInvalidConfiguration("Building debug cpython requires a debug runtime (Debug cpython requires _CrtReportMode symbol, which only debug runtimes define)") - if self._is_py2: - if self.settings.compiler.version >= tools.Version("14"): - self.output.warn("Visual Studio versions 14 and higher were never officially supported by the CPython developers") if str(self.settings.arch) not in self._msvc_archs: raise ConanInvalidConfiguration("Visual Studio does not support this architecture") - - if not self.options.shared and tools.Version(self._version_number_only) >= "3.10": + if not self.options.shared and Version(self.version) >= "3.10": raise ConanInvalidConfiguration("Static msvc build disabled (>=3.10) due to \"AttributeError: module 'sys' has no attribute 'winver'\"") if self.options.get_safe("with_curses", False) and not self.options["ncurses"].with_widec: raise ConanInvalidConfiguration("cpython requires ncurses with wide character support") + if self._supports_modules: + if Version(self.version) < "3.8.0": + if self.dependencies["mpdecimal"].ref.version >= "2.5.0": + raise ConanInvalidConfiguration("cpython versions lesser then 3.8.0 require a mpdecimal lesser then 2.5.0") + elif Version(self.version) >= "3.9.0": + if self.dependencies["mpdecimal"].ref.version < "2.5.0": + raise ConanInvalidConfiguration("cpython 3.9.0 (and newer) requires (at least) mpdecimal 2.5.0") + + if self._with_libffi: + if self.dependencies["libffi"].ref.version >= "3.3" and is_msvc(self) and "d" in str(self.settings.compiler.runtime): + raise ConanInvalidConfiguration("libffi versions >= 3.3 cause 'read access violations' when using a debug runtime (MTd/MDd)") + + def package_id(self): del self.info.options.env_vars def source(self): - tools.get(**self.conan_data["sources"][self.version], - destination=self._source_subfolder, strip_root=True) + get(self, **self.conan_data["sources"][self.version], + destination=self._source_subfolder, strip_root=True) @property def _with_libffi(self): # cpython 3.7.x on MSVC uses an ancient libffi 2.00-beta (which is not available at cci, and is API/ABI incompatible with current 3.2+) return self._supports_modules \ - and (self.settings.compiler != "Visual Studio" or tools.Version(self._version_number_only) >= "3.8") + and (not is_msvc(self) or Version(self.version) >= "3.8") def requirements(self): self.requires("zlib/1.2.11") @@ -179,14 +191,14 @@ def requirements(self): self.requires("expat/2.4.1") if self._with_libffi: self.requires("libffi/3.2.1") - if tools.Version(self._version_number_only) < "3.8": + if Version(self.version) < "3.8": self.requires("mpdecimal/2.4.2") - elif tools.Version(self._version_number_only) < "3.10": + elif Version(self.version) < "3.10": self.requires("mpdecimal/2.5.0") else: self.requires("mpdecimal/2.5.0") # FIXME: no 2.5.1 to troubleshoot apple if self.settings.os != "Windows": - if not tools.is_apple_os(self.settings.os): + if not is_apple_os(self): self.requires("libuuid/1.0.3") self.requires("libxcrypt/4.4.25") if self.options.get_safe("with_bz2"): @@ -265,10 +277,10 @@ def _configure_autotools(self): def _patch_sources(self): for patch in self.conan_data.get("patches",{}).get(self.version, []): tools.patch(**patch) - if self._is_py3 and tools.Version(self._version_number_only) < "3.10": - tools.replace_in_file(os.path.join(self._source_subfolder, "setup.py"), + if self._is_py3 and Version(self.version) < "3.10": + replace_in_file(self, os.path.join(self._source_subfolder, "setup.py"), ":libmpdec.so.2", "mpdec") - if self.settings.compiler == "Visual Studio": + if is_msvc(self): runtime_library = { "MT": "MultiThreaded", "MTd": "MultiThreadedDebug", @@ -276,38 +288,38 @@ def _patch_sources(self): "MDd": "MultiThreadedDebugDLL", }[str(self.settings.compiler.runtime)] self.output.info("Patching runtime") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pyproject.props"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "pyproject.props"), "MultiThreadedDLL", runtime_library) - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pyproject.props"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "pyproject.props"), "MultiThreadedDebugDLL", runtime_library) # Remove vendored packages - tools.rmdir(os.path.join(self._source_subfolder, "Modules", "_decimal", "libmpdec")) - tools.rmdir(os.path.join(self._source_subfolder, "Modules", "expat")) + rmdir(self, os.path.join(self._source_subfolder, "Modules", "_decimal", "libmpdec")) + rmdir(self, os.path.join(self._source_subfolder, "Modules", "expat")) if self.options.get_safe("with_curses", False): # FIXME: this will link to ALL libraries of ncurses. Only need to link to ncurses(w) (+ eventually tinfo) - tools.replace_in_file(os.path.join(self._source_subfolder, "setup.py"), + replace_in_file(self, os.path.join(self._source_subfolder, "setup.py"), "curses_libs = ", "curses_libs = {} #".format(repr(self.deps_cpp_info["ncurses"].libs + self.deps_cpp_info["ncurses"].system_libs))) # Enable static MSVC cpython if not self.options.shared: - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), "","Py_NO_BUILD_SHARED;") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), "Py_ENABLE_SHARED", "Py_NO_ENABLE_SHARED") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), "DynamicLibrary", "StaticLibrary") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "python.vcxproj"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "python.vcxproj"), "", "shlwapi.lib;ws2_32.lib;pathcch.lib;version.lib;%(AdditionalDependencies)") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "python.vcxproj"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "python.vcxproj"), "", "Py_NO_ENABLE_SHARED;") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythonw.vcxproj"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "pythonw.vcxproj"), "", "shlwapi.lib;ws2_32.lib;pathcch.lib;version.lib;%(AdditionalDependencies)") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythonw.vcxproj"), + replace_in_file(self, os.path.join(self._source_subfolder, "PCbuild", "pythonw.vcxproj"), "", "Py_NO_ENABLE_SHARED;%(PreprocessorDefinitions)") def _upgrade_single_project_file(self, project_file): @@ -317,15 +329,15 @@ def _upgrade_single_project_file(self, project_file): This is needed for static cpython or for disabled optional dependencies (e.g. tkinter=False) Restore it afterwards because it is needed to build some targets. """ - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln"), + rename(self, os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln"), os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln.bak")) - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj"), + rename(self, os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj"), os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj.bak")) with tools.vcvars(self.settings): self.run("devenv \"{}\" /upgrade".format(project_file), run_environment=True) - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln.bak"), + rename(self, os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln.bak"), os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln")) - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj.bak"), + rename(self, os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj.bak"), os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj")) @property @@ -382,7 +394,7 @@ def _msvc_archs(self): "x86": "Win32", "x86_64": "x64", } - if tools.Version(self._version_number_only) >= "3.8": + if Version(self.version) >= "3.8": archs.update({ "armv7": "ARM", "armv8_32": "ARM", @@ -392,36 +404,24 @@ def _msvc_archs(self): def _msvc_build(self): msbuild = MSBuild(self) + msbuild.platform = self._msvc_archs[str(self.settings.arch)] + # TODO msbuild_properties = { "IncludeExternals": "true", } + projects = self._solution_projects self.output.info("Building {} Visual Studio projects: {}".format(len(projects), projects)) - with tools.no_op(): - for project_i, project in enumerate(projects, 1): - self.output.info("[{}/{}] Building project '{}'...".format(project_i, len(projects), project)) - project_file = os.path.join(self._source_subfolder, "PCbuild", project + ".vcxproj") - self._upgrade_single_project_file(project_file) - msbuild.build(project_file, upgrade_project=False, build_type="Debug" if self.settings.build_type == "Debug" else "Release", - platforms=self._msvc_archs, properties=msbuild_properties) + for project_i, project in enumerate(projects, 1): + self.output.info("[{}/{}] Building project '{}'...".format(project_i, len(projects), project)) + project_file = os.path.join(self._source_subfolder, "PCbuild", project + ".vcxproj") + self._upgrade_single_project_file(project_file) + msbuild.build(project_file) def build(self): - # FIXME: these checks belong in validate, but the versions of dependencies are not available there yet - if self._supports_modules: - if tools.Version(self._version_number_only) < "3.8.0": - if tools.Version(self.deps_cpp_info["mpdecimal"].version) >= "2.5.0": - raise ConanInvalidConfiguration("cpython versions lesser then 3.8.0 require a mpdecimal lesser then 2.5.0") - elif tools.Version(self._version_number_only) >= "3.9.0": - if tools.Version(self.deps_cpp_info["mpdecimal"].version) < "2.5.0": - raise ConanInvalidConfiguration("cpython 3.9.0 (and newer) requires (at least) mpdecimal 2.5.0") - - if self._with_libffi: - if tools.Version(self.deps_cpp_info["libffi"].version) >= "3.3" and self.settings.compiler == "Visual Studio" and "d" in str(self.settings.compiler.runtime): - raise ConanInvalidConfiguration("libffi versions >= 3.3 cause 'read access violations' when using a debug runtime (MTd/MDd)") - self._patch_sources() - if self.settings.compiler == "Visual Studio": + if is_msvc(self): self._msvc_build() else: autotools = self._configure_autotools() @@ -433,7 +433,7 @@ def _msvc_artifacts_path(self): "x86_64": "amd64", "x86": "win32", } - if tools.Version(self._version_number_only) >= "3.8": + if Version(self.version) >= "3.8": build_subdir_lut.update({ "armv7": "arm32", "armv8_32": "arm32", @@ -446,22 +446,22 @@ def _msvc_install_subprefix(self): return "bin" def _copy_essential_dlls(self): - if self.settings.compiler == "Visual Studio": + if is_msvc(self): # Until MSVC builds support cross building, copy dll's of essential (shared) dependencies to python binary location. # These dll's are required when running the layout tool using the newly built python executable. dest_path = os.path.join(self.build_folder, self._msvc_artifacts_path) if self._with_libffi: for bin_path in self.deps_cpp_info["libffi"].bin_paths: - self.copy("*.dll", src=bin_path, dst=dest_path) + copy(self, "*.dll", src=bin_path, dst=dest_path) for bin_path in self.deps_cpp_info["expat"].bin_paths: - self.copy("*.dll", src=bin_path, dst=dest_path) + copy(self, "*.dll", src=bin_path, dst=dest_path) for bin_path in self.deps_cpp_info["zlib"].bin_paths: - self.copy("*.dll", src=bin_path, dst=dest_path) + copy(self, "*.dll", src=bin_path, dst=dest_path) def _msvc_package_layout(self): self._copy_essential_dlls() install_prefix = os.path.join(self.package_folder, self._msvc_install_subprefix) - tools.mkdir(install_prefix) + mkdir(self, install_prefix) build_path = self._msvc_artifacts_path infix = "_d" if self.settings.build_type == "Debug" else "" # FIXME: if cross building, use a build python executable here @@ -484,7 +484,7 @@ def _msvc_package_layout(self): python_args = " ".join("\"{}\"".format(a) for a in layout_args) self.run("{} {}".format(python_built, python_args), run_environment=True) - tools.rmdir(os.path.join(self.package_folder, "bin", "tcl")) + rmdir(self, os.path.join(self.package_folder, "bin", "tcl")) for file in os.listdir(install_prefix): if re.match("vcruntime.*", file): @@ -498,14 +498,14 @@ def _msvc_package_layout(self): def _msvc_package_copy(self): build_path = self._msvc_artifacts_path infix = "_d" if self.settings.build_type == "Debug" else "" - self.copy("*.exe", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) - self.copy("*.dll", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) - self.copy("*.pyd", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "DLLs")) - self.copy("python{}{}.lib".format(self._version_suffix, infix), src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "libs")) - self.copy("*", src=os.path.join(self._source_subfolder, "Include"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) - self.copy("pyconfig.h", src=os.path.join(self._source_subfolder, "PC"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) - self.copy("*.py", src=os.path.join(self._source_subfolder, "lib"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib")) - tools.rmdir(os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib", "test")) + copy(self, "*.exe", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) + copy(self, "*.dll", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) + copy(self, "*.pyd", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "DLLs")) + copy(self, "python{}{}.lib".format(self._version_suffix, infix), src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "libs")) + copy(self, "*", src=os.path.join(self._source_subfolder, "Include"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) + copy(self, "pyconfig.h", src=os.path.join(self._source_subfolder, "PC"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) + copy(self, "*.py", src=os.path.join(self._source_subfolder, "lib"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib")) + rmdir(self, os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib", "test")) packages = {} get_name_version = lambda fn: fn.split(".", 2)[:2] @@ -515,7 +515,7 @@ def _msvc_package_copy(self): add = True if name in packages: pname, pversion = get_name_version(packages[name]) - add = tools.Version(version) > tools.Version(pversion) + add = Version(version) > Version(pversion) if add: packages[name] = fn for fname in packages.values(): @@ -525,8 +525,8 @@ def _msvc_package_copy(self): run_environment=True) def package(self): - self.copy("LICENSE", src=self._source_subfolder, dst="licenses") - if self.settings.compiler == "Visual Studio": + copy(self, "LICENSE", src=self._source_subfolder, dst="licenses") + if is_msvc(self): if self._is_py2 or not self.options.shared: self._msvc_package_copy() else: @@ -535,8 +535,8 @@ def package(self): else: autotools = self._configure_autotools() autotools.install() - tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig")) - tools.rmdir(os.path.join(self.package_folder, "share")) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + rmdir(self, os.path.join(self.package_folder, "share")) # Rewrite shebangs of python scripts for filename in os.listdir(os.path.join(self.package_folder, "bin")): @@ -577,12 +577,12 @@ def _cpython_symlink(self): @property def _cpython_interpreter_name(self): - if self.settings.compiler == "Visual Studio": + if is_msvc(self): suffix = "" else: suffix = self._version_suffix python = "python{}".format(suffix) - if self.settings.compiler == "Visual Studio": + if is_msvc(self): if self.settings.build_type == "Debug": python += "_d" if self.settings.os == "Windows": @@ -599,14 +599,14 @@ def _abi_suffix(self): if self._is_py3: if self.settings.build_type == "Debug": res += "d" - if tools.Version(self._version_number_only) < "3.8": + if Version(self.version) < "3.8": if self.options.get_safe("pymalloc", False): res += "m" return res @property def _lib_name(self): - if self.settings.compiler == "Visual Studio": + if is_msvc(self): if self.settings.build_type == "Debug": lib_ext = "_d" else: @@ -616,7 +616,7 @@ def _lib_name(self): return "python{}{}".format(self._version_suffix, lib_ext) def _fix_install_name(self): - if tools.is_apple_os(self.settings.os) and self.options.shared: + if is_apple_os(self) and self.options.shared: buffer = StringIO() python = os.path.join(self.package_folder, "bin", "python") self.run('otool -L "%s"' % python, output=buffer) @@ -634,9 +634,9 @@ def package_info(self): # self.cpp_info.names["cmake_find_package_multi"] = "Python" # FIXME: conan components need to generate multiple .pc files (python2, python-27) - py_version = tools.Version(self._version_number_only) + py_version = Version(self.version) # python component: "Build a C extension for Python" - if self.settings.compiler == "Visual Studio": + if is_msvc(self): self.cpp_info.components["python"].includedirs = [os.path.join(self._msvc_install_subprefix, "include")] libdir = os.path.join(self._msvc_install_subprefix, "libs") else: @@ -681,7 +681,7 @@ def package_info(self): if self._with_libffi: self.cpp_info.components["_hidden"].requires.append("libffi::libffi") if self.settings.os != "Windows": - if not tools.is_apple_os(self.settings.os): + if not is_apple_os(self): self.cpp_info.components["_hidden"].requires.append("libuuid::libuuid") self.cpp_info.components["_hidden"].requires.append("libxcrypt::libxcrypt") if self.options.with_bz2: @@ -711,19 +711,19 @@ def package_info(self): self.output.info("Setting PYTHON environment variable: {}".format(python)) self.env_info.PYTHON = python - if self.settings.compiler == "Visual Studio": + if is_msvc(self): pythonhome = os.path.join(self.package_folder, "bin") - elif tools.is_apple_os(self.settings.os): + elif is_apple_os(self): pythonhome = self.package_folder else: - version = tools.Version(self._version_number_only) + version = Version(self.version) pythonhome = os.path.join(self.package_folder, "lib", "python{}.{}".format(version.major, version.minor)) self.user_info.pythonhome = pythonhome - pythonhome_required = self.settings.compiler == "Visual Studio" or tools.is_apple_os(self.settings.os) + pythonhome_required = is_msvc(self) or is_apple_os(self) self.user_info.module_requires_pythonhome = pythonhome_required - if self.settings.compiler == "Visual Studio": + if is_msvc(self): if self.options.env_vars: self.output.info("Setting PYTHONHOME environment variable: {}".format(pythonhome)) self.env_info.PYTHONHOME = pythonhome From 342f926d6dc1be94a7a8ebedced900cfa502cd47 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Wed, 4 Oct 2023 20:16:36 +0300 Subject: [PATCH 002/102] cpython: migrate to Conan v2 --- recipes/cpython/all/conandata.yml | 101 ++- recipes/cpython/all/conanfile.py | 623 ++++++++++-------- .../patches/{ => 2.7}/2.7.18-0001-msvc.patch | 0 .../2.7.18-0002-add-support-msvc-14.patch | 0 .../2.7.18-0003-msvc-fix-static.patch | 0 .../2.7.18-0004-disable-macos-tcltk.patch | 0 .../patches/{ => 3.10}/3.10.0-0001-msvc.patch | 0 .../{ => 3.10}/3.10.0-0003-_ctypes-ffi.patch | 0 ...0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch | 0 .../3.10.0-0005-disable-macos-tcltk.patch | 0 .../patches/{ => 3.7}/3.7.9-0001-msvc.patch | 0 ...9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch | 0 .../3.7.9-0003-disable-macos-tcltk.patch | 0 .../patches/{ => 3.8}/3.8.12-0001-msvc.patch | 0 .../{ => 3.8}/3.8.12-0002-_ctypes-ffi.patch | 0 ...2-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch | 0 .../3.8.12-0004-disable-macos-tcltk.patch | 0 .../patches/{ => 3.9}/3.9.7-0001-msvc.patch | 0 .../{ => 3.9}/3.9.7-0002-_msi-vcxproj.patch | 0 .../{ => 3.9}/3.9.7-0003-_ctypes-ffi.patch | 0 ...7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch | 0 .../3.9.7-0005-disable-macos-tcltk.patch | 0 .../cpython/all/test_package/CMakeLists.txt | 7 +- recipes/cpython/all/test_package/conanfile.py | 266 +++++--- .../cpython/all/test_package/test_package.py | 33 +- .../all/test_v1_package/CMakeLists.txt | 8 + .../cpython/all/test_v1_package/conanfile.py | 192 ++++++ recipes/cpython/config.yml | 8 +- 28 files changed, 819 insertions(+), 419 deletions(-) rename recipes/cpython/all/patches/{ => 2.7}/2.7.18-0001-msvc.patch (100%) rename recipes/cpython/all/patches/{ => 2.7}/2.7.18-0002-add-support-msvc-14.patch (100%) rename recipes/cpython/all/patches/{ => 2.7}/2.7.18-0003-msvc-fix-static.patch (100%) rename recipes/cpython/all/patches/{ => 2.7}/2.7.18-0004-disable-macos-tcltk.patch (100%) rename recipes/cpython/all/patches/{ => 3.10}/3.10.0-0001-msvc.patch (100%) rename recipes/cpython/all/patches/{ => 3.10}/3.10.0-0003-_ctypes-ffi.patch (100%) rename recipes/cpython/all/patches/{ => 3.10}/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch (100%) rename recipes/cpython/all/patches/{ => 3.10}/3.10.0-0005-disable-macos-tcltk.patch (100%) rename recipes/cpython/all/patches/{ => 3.7}/3.7.9-0001-msvc.patch (100%) rename recipes/cpython/all/patches/{ => 3.7}/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch (100%) rename recipes/cpython/all/patches/{ => 3.7}/3.7.9-0003-disable-macos-tcltk.patch (100%) rename recipes/cpython/all/patches/{ => 3.8}/3.8.12-0001-msvc.patch (100%) rename recipes/cpython/all/patches/{ => 3.8}/3.8.12-0002-_ctypes-ffi.patch (100%) rename recipes/cpython/all/patches/{ => 3.8}/3.8.12-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch (100%) rename recipes/cpython/all/patches/{ => 3.8}/3.8.12-0004-disable-macos-tcltk.patch (100%) rename recipes/cpython/all/patches/{ => 3.9}/3.9.7-0001-msvc.patch (100%) rename recipes/cpython/all/patches/{ => 3.9}/3.9.7-0002-_msi-vcxproj.patch (100%) rename recipes/cpython/all/patches/{ => 3.9}/3.9.7-0003-_ctypes-ffi.patch (100%) rename recipes/cpython/all/patches/{ => 3.9}/3.9.7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch (100%) rename recipes/cpython/all/patches/{ => 3.9}/3.9.7-0005-disable-macos-tcltk.patch (100%) create mode 100644 recipes/cpython/all/test_v1_package/CMakeLists.txt create mode 100644 recipes/cpython/all/test_v1_package/conanfile.py diff --git a/recipes/cpython/all/conandata.yml b/recipes/cpython/all/conandata.yml index f9fd51067c8b3..0deb2c8f60363 100644 --- a/recipes/cpython/all/conandata.yml +++ b/recipes/cpython/all/conandata.yml @@ -1,72 +1,57 @@ sources: +# "3.10.13": +# url: "https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz" +# sha256: "698ec55234c1363bd813b460ed53b0f108877c7a133d48bde9a50a1eb57b7e65" "3.10.0": url: "https://www.python.org/ftp/python/3.10.0/Python-3.10.0.tgz" sha256: "c4e0cbad57c90690cb813fb4663ef670b4d0f587d8171e2c42bd4c9245bd2758" - "3.9.7": - url: "https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tgz" - sha256: "a838d3f9360d157040142b715db34f0218e535333696a5569dc6f854604eb9d1" - "3.8.12": - url: "https://www.python.org/ftp/python/3.8.12/Python-3.8.12.tgz" - sha256: "316aa33f3b7707d041e73f246efedb297a70898c4b91f127f66dc8d80c596f1a" - "3.7.12": - url: "https://www.python.org/ftp/python/3.7.12/Python-3.7.12.tgz" - sha256: "33b4daaf831be19219659466d12645f87ecec6eb21d4d9f9711018a7b66cce46" +# "3.9.18": +# url: "https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz" +# sha256: "504ce8cfd59addc04c22f590377c6be454ae7406cb1ebf6f5a350149225a9354" +# "3.8.18": +# url: "https://www.python.org/ftp/python/3.8.18/Python-3.8.18.tgz" +# sha256: "7c5df68bab1be81a52dea0cc2e2705ea00553b67107a301188383d7b57320b16" + "3.7.17": + url: "https://www.python.org/ftp/python/3.7.17/Python-3.7.17.tgz" + sha256: "fd50161bc2a04f4c22a0971ff0f3856d98b4bf294f89740a9f06b520aae63b49" "2.7.18": url: "https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tgz" sha256: "da3080e3b488f648a3d7a4560ddee895284c3380b11d6de75edb986526b9a814" patches: + "3.10.13": + - patch_file: "patches/3.10/3.10.0-0001-msvc.patch" + - patch_file: "patches/3.9/3.9.7-0002-_msi-vcxproj.patch" + - patch_file: "patches/3.10/3.10.0-0003-_ctypes-ffi.patch" + - patch_file: "patches/3.10/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch" + - patch_file: "patches/3.10/3.10.0-0005-disable-macos-tcltk.patch" + - patch_file: "patches/3.x-0001-relocatable-python-config.patch" "3.10.0": - - patch_file: "patches/3.10.0-0001-msvc.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.9.7-0002-_msi-vcxproj.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.10.0-0003-_ctypes-ffi.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.10.0-0005-disable-macos-tcltk.patch" - base_path: "source_subfolder" + - patch_file: "patches/3.10/3.10.0-0001-msvc.patch" + - patch_file: "patches/3.9/3.9.7-0002-_msi-vcxproj.patch" + - patch_file: "patches/3.10/3.10.0-0003-_ctypes-ffi.patch" + - patch_file: "patches/3.10/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch" + - patch_file: "patches/3.10/3.10.0-0005-disable-macos-tcltk.patch" - patch_file: "patches/3.x-0001-relocatable-python-config.patch" - base_path: "source_subfolder" - "3.9.7": - - patch_file: "patches/3.9.7-0001-msvc.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.9.7-0002-_msi-vcxproj.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.9.7-0003-_ctypes-ffi.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.9.7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.9.7-0005-disable-macos-tcltk.patch" - base_path: "source_subfolder" + "3.9.18": + - patch_file: "patches/3.9/3.9.7-0001-msvc.patch" + - patch_file: "patches/3.9/3.9.7-0002-_msi-vcxproj.patch" + - patch_file: "patches/3.9/3.9.7-0003-_ctypes-ffi.patch" + - patch_file: "patches/3.9/3.9.7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch" + - patch_file: "patches/3.9/3.9.7-0005-disable-macos-tcltk.patch" - patch_file: "patches/3.x-0001-relocatable-python-config.patch" - base_path: "source_subfolder" - "3.8.12": - - patch_file: "patches/3.8.12-0001-msvc.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.8.12-0002-_ctypes-ffi.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.8.12-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.8.12-0004-disable-macos-tcltk.patch" - base_path: "source_subfolder" + "3.8.18": + - patch_file: "patches/3.8/3.8.12-0001-msvc.patch" + - patch_file: "patches/3.8/3.8.12-0002-_ctypes-ffi.patch" + - patch_file: "patches/3.8/3.8.12-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch" + - patch_file: "patches/3.8/3.8.12-0004-disable-macos-tcltk.patch" - patch_file: "patches/3.x-0001-relocatable-python-config.patch" - base_path: "source_subfolder" - "3.7.12": - - patch_file: "patches/3.7.9-0001-msvc.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch" - base_path: "source_subfolder" - - patch_file: "patches/3.7.9-0003-disable-macos-tcltk.patch" - base_path: "source_subfolder" + "3.7.17": + - patch_file: "patches/3.7/3.7.9-0001-msvc.patch" + - patch_file: "patches/3.7/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch" + - patch_file: "patches/3.7/3.7.9-0003-disable-macos-tcltk.patch" - patch_file: "patches/3.x-0001-relocatable-python-config.patch" - base_path: "source_subfolder" "2.7.18": - - patch_file: "patches/2.7.18-0001-msvc.patch" - base_path: "source_subfolder" - - patch_file: "patches/2.7.18-0002-add-support-msvc-14.patch" - base_path: "source_subfolder" - - patch_file: "patches/2.7.18-0003-msvc-fix-static.patch" - base_path: "source_subfolder" - - patch_file: "patches/2.7.18-0004-disable-macos-tcltk.patch" - base_path: "source_subfolder" + - patch_file: "patches/2.7/2.7.18-0001-msvc.patch" + - patch_file: "patches/2.7/2.7.18-0002-add-support-msvc-14.patch" + - patch_file: "patches/2.7/2.7.18-0003-msvc-fix-static.patch" + - patch_file: "patches/2.7/2.7.18-0004-disable-macos-tcltk.patch" diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 4fa1d1da6334e..4ee436c262480 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -1,21 +1,30 @@ -from conans import AutoToolsBuildEnvironment, ConanFile, MSBuild, tools -from conans.errors import ConanInvalidConfiguration -from io import StringIO import os import re import textwrap +from io import StringIO + +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.apple import is_apple_os +from conan.tools.build import cross_building +from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, mkdir, rename, replace_in_file, rm, rmdir, unzip +from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps +from conan.tools.layout import basic_layout +from conan.tools.microsoft import MSBuild, is_msvc, is_msvc_static_runtime, msvc_runtime_flag +from conan.tools.scm import Version -required_conan_version = ">=1.33.0" +required_conan_version = ">=1.47.0" class CPythonConan(ConanFile): name = "cpython" + description = "Python is a programming language that lets you work quickly and integrate systems more effectively." + license = "Python-2.0" url = "https://github.com/conan-io/conan-center-index" homepage = "https://www.python.org" - description = "Python is a programming language that lets you work quickly and integrate systems more effectively." - topics = ("python", "cpython", "language", "script") - license = ("Python-2.0",) - exports_sources = "patches/**" + topics = ("python", "language", "script") + + package_type = "application" settings = "os", "arch", "compiler", "build_type" options = { "shared": [True, False], @@ -30,13 +39,11 @@ class CPythonConan(ConanFile): "with_sqlite3": [True, False], "with_tkinter": [True, False], "with_curses": [True, False], - # Python 2 options "unicode": ["ucs2", "ucs4"], "with_bsddb": [True, False], # Python 3 options "with_lzma": [True, False], - # options that don't change package id "env_vars": [True, False], # set environment variables } @@ -53,23 +60,15 @@ class CPythonConan(ConanFile): "with_sqlite3": True, "with_tkinter": True, "with_curses": True, - # Python 2 options "unicode": "ucs2", "with_bsddb": False, # True, # FIXME: libdb package missing (#5309/#5392) # Python 3 options "with_lzma": True, - # options that don't change package id "env_vars": True, } - _autotools = None - - @property - def _source_subfolder(self): - return "source_subfolder" - @property def _version_number_only(self): return re.match(r"^([0-9.]+)", self.version).group(1) @@ -80,11 +79,11 @@ def _version_tuple(self): @property def _supports_modules(self): - return self.settings.compiler != "Visual Studio" or self.options.shared + return not is_msvc(self) or self.options.shared @property def _version_suffix(self): - if self.settings.compiler == "Visual Studio": + if is_msvc(self): joiner = "" else: joiner = "." @@ -92,129 +91,143 @@ def _version_suffix(self): @property def _is_py3(self): - return tools.Version(self._version_number_only).major == "3" + return Version(self._version_number_only).major == "3" @property def _is_py2(self): - return tools.Version(self._version_number_only).major == "2" + return Version(self._version_number_only).major == "2" + + def export_sources(self): + export_conandata_patches(self) def config_options(self): if self.settings.os == "Windows": del self.options.fPIC - if self.settings.compiler == "Visual Studio": - del self.options.lto - del self.options.docstrings - del self.options.pymalloc - del self.options.with_curses - del self.options.with_gdbm - del self.options.with_nis + if is_msvc(self): + self.options.rm_safe("lto") + self.options.rm_safe("docstrings") + self.options.rm_safe("pymalloc") + self.options.rm_safe("with_curses") + self.options.rm_safe("with_gdbm") + self.options.rm_safe("with_nis") if self._is_py2: # Python 2.xx does not support following options - del self.options.with_lzma + self.options.rm_safe("with_lzma") elif self._is_py3: # Python 3.xx does not support following options - del self.options.with_bsddb - del self.options.unicode + self.options.rm_safe("with_bsddb") + self.options.rm_safe("unicode") - del self.settings.compiler.libcxx - del self.settings.compiler.cppstd + self.settings.rm_safe("compiler.libcxx") + self.settings.rm_safe("compiler.cppstd") def configure(self): if self.options.shared: - del self.options.fPIC + self.options.rm_safe("fPIC") if not self._supports_modules: - del self.options.with_bz2 - del self.options.with_sqlite3 - del self.options.with_tkinter + self.options.rm_safe("with_bz2") + self.options.rm_safe("with_sqlite3") + self.options.rm_safe("with_tkinter") - del self.options.with_bsddb - del self.options.with_lzma - if self.settings.compiler == "Visual Studio": + self.options.rm_safe("with_bsddb") + self.options.rm_safe("with_lzma") + if is_msvc(self): # The msbuild generator only works with Visual Studio self.generators.append("MSBuildDeps") - def validate(self): - if self.options.shared: - if self.settings.compiler == "Visual Studio" and "MT" in self.settings.compiler.runtime: - raise ConanInvalidConfiguration("cpython does not support MT(d) runtime when building a shared cpython library") - if self.settings.compiler == "Visual Studio": - if self.options.optimizations: - raise ConanInvalidConfiguration("This recipe does not support optimized MSVC cpython builds (yet)") - # FIXME: should probably throw when cross building - # FIXME: optimizations for Visual Studio, before building the final `build_type`: - # 1. build the MSVC PGInstrument build_type, - # 2. run the instrumented binaries, (PGInstrument should have created a `python.bat` file in the PCbuild folder) - # 3. build the MSVC PGUpdate build_type - if self.settings.build_type == "Debug" and "d" not in self.settings.compiler.runtime: - raise ConanInvalidConfiguration("Building debug cpython requires a debug runtime (Debug cpython requires _CrtReportMode symbol, which only debug runtimes define)") - if self._is_py2: - if self.settings.compiler.version >= tools.Version("14"): - self.output.warn("Visual Studio versions 14 and higher were never officially supported by the CPython developers") - if str(self.settings.arch) not in self._msvc_archs: - raise ConanInvalidConfiguration("Visual Studio does not support this architecture") - - if not self.options.shared and tools.Version(self._version_number_only) >= "3.10": - raise ConanInvalidConfiguration("Static msvc build disabled (>=3.10) due to \"AttributeError: module 'sys' has no attribute 'winver'\"") - - if self.options.get_safe("with_curses", False) and not self.options["ncurses"].with_widec: - raise ConanInvalidConfiguration("cpython requires ncurses with wide character support") - - def package_id(self): - del self.info.options.env_vars - - def source(self): - tools.get(**self.conan_data["sources"][self.version], - destination=self._source_subfolder, strip_root=True) + def layout(self): + basic_layout(self, src_folder="src") @property def _with_libffi(self): # cpython 3.7.x on MSVC uses an ancient libffi 2.00-beta (which is not available at cci, and is API/ABI incompatible with current 3.2+) - return self._supports_modules \ - and (self.settings.compiler != "Visual Studio" or tools.Version(self._version_number_only) >= "3.8") + return self._supports_modules and (not is_msvc(self) or Version(self._version_number_only) >= "3.8") def requirements(self): - self.requires("zlib/1.2.11") + self.requires("zlib/[>=1.2.11 <2]", force=True) if self._supports_modules: - self.requires("openssl/1.1.1l") - self.requires("expat/2.4.1") + self.requires("openssl/[>=1.1 <4]") + self.requires("expat/2.5.0") if self._with_libffi: - self.requires("libffi/3.2.1") - if tools.Version(self._version_number_only) < "3.8": + self.requires("libffi/3.4.4") + if Version(self._version_number_only) < "3.8": self.requires("mpdecimal/2.4.2") - elif tools.Version(self._version_number_only) < "3.10": + elif Version(self._version_number_only) < "3.10": self.requires("mpdecimal/2.5.0") else: self.requires("mpdecimal/2.5.0") # FIXME: no 2.5.1 to troubleshoot apple if self.settings.os != "Windows": - if not tools.is_apple_os(self.settings.os): - self.requires("libuuid/1.0.3") - self.requires("libxcrypt/4.4.25") + if not is_apple_os(self): + self.requires("util-linux-libuuid/2.39") + self.requires("libxcrypt/4.4.35") if self.options.get_safe("with_bz2"): self.requires("bzip2/1.0.8") if self.options.get_safe("with_gdbm", False): - self.requires("gdbm/1.19") + self.requires("gdbm/1.23") if self.options.get_safe("with_nis", False): # TODO: Add nis when available. raise ConanInvalidConfiguration("nis is not available on CCI (yet)") if self.options.get_safe("with_sqlite3"): - self.requires("sqlite3/3.36.0") + self.requires("sqlite3/3.43.1") if self.options.get_safe("with_tkinter"): self.requires("tk/8.6.10") if self.options.get_safe("with_curses", False): - self.requires("ncurses/6.2") + self.requires("ncurses/6.4") if self.options.get_safe("with_bsddb", False): self.requires("libdb/5.3.28") if self.options.get_safe("with_lzma", False): - self.requires("xz_utils/5.2.5") + self.requires("xz_utils/5.4.4") - def _configure_autotools(self): - if self._autotools: - return self._autotools - self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows) - self._autotools.libs = [] + def package_id(self): + del self.info.settings.compiler + del self.info.settings.build_type + + def validate(self): + if self.options.shared: + if is_msvc_static_runtime(self): + raise ConanInvalidConfiguration( + "cpython does not support MT(d) runtime when building a shared cpython library" + ) + if is_msvc(self): + if self.options.optimizations: + raise ConanInvalidConfiguration( + "This recipe does not support optimized MSVC cpython builds (yet)" + ) + # FIXME: should probably throw when cross building + # FIXME: optimizations for Visual Studio, before building the final `build_type`: + # 1. build the MSVC PGInstrument build_type, + # 2. run the instrumented binaries, (PGInstrument should have created a `python.bat` file in the PCbuild folder) + # 3. build the MSVC PGUpdate build_type + if self.settings.build_type == "Debug" and "d" not in msvc_runtime_flag(self): + raise ConanInvalidConfiguration( + "Building debug cpython requires a debug runtime (Debug cpython requires _CrtReportMode" + " symbol, which only debug runtimes define)" + ) + if self._is_py2: + if self.settings.compiler.version >= Version(self, "14"): + self.output.warning( + "Visual Studio versions 14 and higher were never officially supported by the CPython" + " developers" + ) + if str(self.settings.arch) not in self._msvc_archs: + raise ConanInvalidConfiguration("Visual Studio does not support this architecture") + + if not self.options.shared and Version(self._version_number_only) >= "3.10": + raise ConanInvalidConfiguration( + "Static msvc build disabled (>=3.10) due to \"AttributeError: module 'sys' has no" + " attribute 'winver'\"" + ) + + if self.options.get_safe("with_curses", False) and not self.dependencies["ncurses"].options.with_widec: + raise ConanInvalidConfiguration("cpython requires ncurses with wide character support") + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def _generate_autotools(self): + tc = AutotoolsToolchain(self) yes_no = lambda v: "yes" if v else "no" - conf_args = [ - "--enable-shared={}".format(yes_no(self.options.shared)), + tc.configure_args += [ "--with-doc-strings={}".format(yes_no(self.options.docstrings)), "--with-pymalloc={}".format(yes_no(self.options.pymalloc)), "--with-system-expat", @@ -224,91 +237,105 @@ def _configure_autotools(self): "--with-pydebug={}".format(yes_no(self.settings.build_type == "Debug")), ] if self._is_py2: - conf_args.extend([ - "--enable-unicode={}".format(yes_no(self.options.unicode)), - ]) + tc.configure_args += ["--enable-unicode={}".format(yes_no(self.options.unicode))] if self._is_py3: - conf_args.extend([ + tc.configure_args += [ "--with-system-libmpdec", - "--with-openssl={}".format(self.deps_cpp_info["openssl"].rootpath), - "--enable-loadable-sqlite-extensions={}".format(yes_no(not self.options["sqlite3"].omit_load_extension)), - ]) - if self.settings.compiler == "intel": - conf_args.extend(["--with-icc"]) - if tools.get_env("CC") or self.settings.compiler != "gcc": - conf_args.append("--without-gcc") + "--with-openssl={}".format(self.dependencies["openssl"].package_folder), + "--enable-loadable-sqlite-extensions={}".format( + yes_no(not self.dependencies["sqlite3"].options.omit_load_extension) + ), + ] + if self.settings.compiler == "intel-cc": + tc.configure_args.append("--with-icc") + if os.environ.get("CC") or self.settings.compiler != "gcc": + tc.configure_args.append("--without-gcc") if self.options.with_tkinter: tcltk_includes = [] tcltk_libs = [] # FIXME: collect using some conan util (https://github.com/conan-io/conan/issues/7656) for dep in ("tcl", "tk", "zlib"): - tcltk_includes += ["-I{}".format(d) for d in self.deps_cpp_info[dep].include_paths] - tcltk_libs += ["-l{}".format(lib) for lib in self.deps_cpp_info[dep].libs] - if self.settings.os == "Linux" and not self.options["tk"].shared: + tcltk_includes += [f"-I{d}" for d in self.dependencies[dep].cpp_info.includedirs] + tcltk_libs += [f"-L{lib}" for lib in self.dependencies[dep].cpp_info.libdirs] + tcltk_libs += [f"-l{lib}" for lib in self.dependencies[dep].cpp_info.libs] + if self.settings.os in ["Linux", "FreeBSD"] and not self.dependencies["tk"].options.shared: # FIXME: use info from xorg.components (x11, xscrnsaver) - tcltk_libs.extend(["-l{}".format(lib) for lib in ("X11", "Xss")]) - conf_args.extend([ + tcltk_libs.extend([f"-l{lib}" for lib in ("X11", "Xss")]) + tc.configure_args += [ "--with-tcltk-includes={}".format(" ".join(tcltk_includes)), "--with-tcltk-libs={}".format(" ".join(tcltk_libs)), - ]) + ] if self.settings.os in ("Linux", "FreeBSD"): # Building _testembed fails due to missing pthread/rt symbols - self._autotools.link_flags.append("-lpthread") + tc.ldflags.append("-lpthread") build = None - if tools.cross_building(self) and not tools.cross_building(self, skip_x64_x86=True): + if cross_building(self) and not cross_building(self, skip_x64_x86=True): # Building from x86_64 to x86 is not a "real" cross build, so set build == host - build = tools.get_gnu_triplet(str(self.settings.os), str(self.settings.arch), str(self.settings.compiler)) - self._autotools.configure(args=conf_args, configure_dir=self._source_subfolder, build=build) - return self._autotools + build = get_gnu_triplet( + self, str(self.settings.os), str(self.settings.arch), str(self.settings.compiler) + ) + tc.generate() + + deps = AutotoolsDeps(self) + deps.generate() + + def generate(self): + self._generate_autotools() def _patch_sources(self): - for patch in self.conan_data.get("patches",{}).get(self.version, []): - tools.patch(**patch) - if self._is_py3 and tools.Version(self._version_number_only) < "3.10": - tools.replace_in_file(os.path.join(self._source_subfolder, "setup.py"), - ":libmpdec.so.2", "mpdec") - if self.settings.compiler == "Visual Studio": + apply_conandata_patches(self) + if self._is_py3 and Version(self._version_number_only) < "3.10": + replace_in_file(self, os.path.join(self.source_folder, "setup.py"), ":libmpdec.so.2", "mpdec") + if is_msvc(self): runtime_library = { "MT": "MultiThreaded", "MTd": "MultiThreadedDebug", "MD": "MultiThreadedDLL", "MDd": "MultiThreadedDebugDLL", - }[str(self.settings.compiler.runtime)] + }[msvc_runtime_flag(self)] self.output.info("Patching runtime") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pyproject.props"), - "MultiThreadedDLL", runtime_library) - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pyproject.props"), - "MultiThreadedDebugDLL", runtime_library) + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pyproject.props"), + "MultiThreadedDLL", runtime_library) + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pyproject.props"), + "MultiThreadedDebugDLL", runtime_library) # Remove vendored packages - tools.rmdir(os.path.join(self._source_subfolder, "Modules", "_decimal", "libmpdec")) - tools.rmdir(os.path.join(self._source_subfolder, "Modules", "expat")) + rmdir(self, os.path.join(self.source_folder, "Modules", "_decimal", "libmpdec")) + rmdir(self, os.path.join(self.source_folder, "Modules", "expat")) if self.options.get_safe("with_curses", False): # FIXME: this will link to ALL libraries of ncurses. Only need to link to ncurses(w) (+ eventually tinfo) - tools.replace_in_file(os.path.join(self._source_subfolder, "setup.py"), - "curses_libs = ", - "curses_libs = {} #".format(repr(self.deps_cpp_info["ncurses"].libs + self.deps_cpp_info["ncurses"].system_libs))) + ncurses_info = self.dependencies["ncurses"].cpp_info + replace_in_file(self, os.path.join(self.source_folder, "setup.py"), + "curses_libs = ", + "curses_libs = {} #".format(repr(ncurses_info.libs + ncurses_info.system_libs))) # Enable static MSVC cpython if not self.options.shared: - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), - "","Py_NO_BUILD_SHARED;") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), - "Py_ENABLE_SHARED", "Py_NO_ENABLE_SHARED") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythoncore.vcxproj"), - "DynamicLibrary", "StaticLibrary") - - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "python.vcxproj"), - "", "shlwapi.lib;ws2_32.lib;pathcch.lib;version.lib;%(AdditionalDependencies)") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "python.vcxproj"), - "", "Py_NO_ENABLE_SHARED;") - - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythonw.vcxproj"), - "", "shlwapi.lib;ws2_32.lib;pathcch.lib;version.lib;%(AdditionalDependencies)") - tools.replace_in_file(os.path.join(self._source_subfolder, "PCbuild", "pythonw.vcxproj"), - "", "Py_NO_ENABLE_SHARED;%(PreprocessorDefinitions)") + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pythoncore.vcxproj"), + "", + "Py_NO_BUILD_SHARED;") + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pythoncore.vcxproj"), + "Py_ENABLE_SHARED", + "Py_NO_ENABLE_SHARED") + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pythoncore.vcxproj"), + "DynamicLibrary", + "StaticLibrary") + + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "python.vcxproj"), + "", + "shlwapi.lib;ws2_32.lib;pathcch.lib;version.lib;%(AdditionalDependencies)") + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "python.vcxproj"), + "", + "Py_NO_ENABLE_SHARED;") + + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pythonw.vcxproj"), + "", + "shlwapi.lib;ws2_32.lib;pathcch.lib;version.lib;%(AdditionalDependencies)") + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pythonw.vcxproj"), + "", + "Py_NO_ENABLE_SHARED;%(PreprocessorDefinitions)") def _upgrade_single_project_file(self, project_file): """ @@ -317,22 +344,21 @@ def _upgrade_single_project_file(self, project_file): This is needed for static cpython or for disabled optional dependencies (e.g. tkinter=False) Restore it afterwards because it is needed to build some targets. """ - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln"), - os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln.bak")) - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj"), - os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj.bak")) - with tools.vcvars(self.settings): - self.run("devenv \"{}\" /upgrade".format(project_file), run_environment=True) - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln.bak"), - os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln")) - tools.rename(os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj.bak"), - os.path.join(self._source_subfolder, "PCbuild", "pcbuild.proj")) + rename(self,os.path.join(self.source_folder, "PCbuild", "pcbuild.sln"), + os.path.join(self.source_folder, "PCbuild", "pcbuild.sln.bak")) + rename(self, os.path.join(self.source_folder, "PCbuild", "pcbuild.proj"), + os.path.join(self.source_folder, "PCbuild", "pcbuild.proj.bak")) + self.run(f'devenv "{project_file}" /upgrade') + rename(self, os.path.join(self.source_folder, "PCbuild", "pcbuild.sln.bak"), + os.path.join(self.source_folder, "PCbuild", "pcbuild.sln")) + rename(self, os.path.join(self.source_folder, "PCbuild", "pcbuild.proj.bak"), + os.path.join(self.source_folder, "PCbuild", "pcbuild.proj")) @property def _solution_projects(self): if self.options.shared: - solution_path = os.path.join(self._source_subfolder, "PCbuild", "pcbuild.sln") - projects = set(m.group(1) for m in re.finditer("\"([^\"]+)\\.vcxproj\"", open(solution_path).read())) + solution_path = os.path.join(self.source_folder, "PCbuild", "pcbuild.sln") + projects = set(m.group(1) for m in re.finditer('"([^"]+)\\.vcxproj"', open(solution_path).read())) def project_build(name): if os.path.basename(name) in self._msvc_discarded_projects: @@ -343,8 +369,8 @@ def project_build(name): def sort_importance(key): importance = ( - "pythoncore", # The python library MUST be built first. All modules and executables depend on it - "python", # Build the python executable next (for convenience, when debugging) + "pythoncore", # The python library MUST be built first. All modules and executables depend on it + "python", # Build the python executable next (for convenience, when debugging) ) try: return importance.index(key) @@ -358,7 +384,10 @@ def sort_importance(key): @property def _msvc_discarded_projects(self): - discarded = {"python_uwp", "pythonw_uwp"} + discarded = { + "python_uwp", + "pythonw_uwp", + } if not self.options.with_bz2: discarded.add("bz2") if not self.options.with_sqlite3: @@ -367,11 +396,25 @@ def _msvc_discarded_projects(self): discarded.add("_tkinter") if self._is_py2: # Python 2 Visual Studio projects NOT to build - discarded = discarded.union({"bdist_wininst", "libeay", "ssleay", "sqlite3", "tcl", "tk", "tix"}) + discarded = discarded.union({ + "bdist_wininst", + "libeay", + "ssleay", + "sqlite3", + "tcl", + "tk", + "tix", + }) if not self.options.with_bsddb: discarded.add("_bsddb") elif self._is_py3: - discarded = discarded.union({"bdist_wininst", "liblzma", "openssl", "sqlite3", "xxlimited"}) + discarded = discarded.union({ + "bdist_wininst", + "liblzma", + "openssl", + "sqlite3", + "xxlimited", + }) if not self.options.with_lzma: discarded.add("_lzma") return discarded @@ -382,7 +425,7 @@ def _msvc_archs(self): "x86": "Win32", "x86_64": "x64", } - if tools.Version(self._version_number_only) >= "3.8": + if Version(self._version_number_only) >= "3.8": archs.update({ "armv7": "ARM", "armv8_32": "ARM", @@ -396,35 +439,48 @@ def _msvc_build(self): "IncludeExternals": "true", } projects = self._solution_projects - self.output.info("Building {} Visual Studio projects: {}".format(len(projects), projects)) - - with tools.no_op(): - for project_i, project in enumerate(projects, 1): - self.output.info("[{}/{}] Building project '{}'...".format(project_i, len(projects), project)) - project_file = os.path.join(self._source_subfolder, "PCbuild", project + ".vcxproj") - self._upgrade_single_project_file(project_file) - msbuild.build(project_file, upgrade_project=False, build_type="Debug" if self.settings.build_type == "Debug" else "Release", - platforms=self._msvc_archs, properties=msbuild_properties) + self.output.info(f"Building {len(projects)} Visual Studio projects: {projects}") + + for project_i, project in enumerate(projects, 1): + self.output.info(f"[{project_i}/{len(projects)}] Building project '{project}'...") + project_file = os.path.join(self.source_folder, "PCbuild", project + ".vcxproj") + self._upgrade_single_project_file(project_file) + msbuild.build( + project_file, + upgrade_project=False, + build_type="Debug" if self.settings.build_type == "Debug" else "Release", + platforms=self._msvc_archs, + properties=msbuild_properties, + ) def build(self): # FIXME: these checks belong in validate, but the versions of dependencies are not available there yet if self._supports_modules: - if tools.Version(self._version_number_only) < "3.8.0": - if tools.Version(self.deps_cpp_info["mpdecimal"].version) >= "2.5.0": - raise ConanInvalidConfiguration("cpython versions lesser then 3.8.0 require a mpdecimal lesser then 2.5.0") - elif tools.Version(self._version_number_only) >= "3.9.0": - if tools.Version(self.deps_cpp_info["mpdecimal"].version) < "2.5.0": - raise ConanInvalidConfiguration("cpython 3.9.0 (and newer) requires (at least) mpdecimal 2.5.0") + if Version(self._version_number_only) < "3.8.0": + if Version(self.dependencies["mpdecimal"].ref.version) >= "2.5.0": + raise ConanInvalidConfiguration( + "cpython versions lesser then 3.8.0 require a mpdecimal lesser then 2.5.0" + ) + elif Version(self._version_number_only) >= "3.9.0": + if Version(self.dependencies["mpdecimal"].ref.version) < "2.5.0": + raise ConanInvalidConfiguration( + "cpython 3.9.0 (and newer) requires (at least) mpdecimal 2.5.0" + ) if self._with_libffi: - if tools.Version(self.deps_cpp_info["libffi"].version) >= "3.3" and self.settings.compiler == "Visual Studio" and "d" in str(self.settings.compiler.runtime): - raise ConanInvalidConfiguration("libffi versions >= 3.3 cause 'read access violations' when using a debug runtime (MTd/MDd)") + if Version(self.dependencies["libffi"].ref.version) >= "3.3": + if is_msvc(self) and "d" in msvc_runtime_flag(self): + raise ConanInvalidConfiguration( + "libffi versions >= 3.3 cause 'read access violations' when using a debug runtime" + " (MTd/MDd)" + ) self._patch_sources() - if self.settings.compiler == "Visual Studio": + if is_msvc(self): self._msvc_build() else: - autotools = self._configure_autotools() + autotools = Autotools(self) + autotools.configure() autotools.make() @property @@ -433,43 +489,43 @@ def _msvc_artifacts_path(self): "x86_64": "amd64", "x86": "win32", } - if tools.Version(self._version_number_only) >= "3.8": + if Version(self._version_number_only) >= "3.8": build_subdir_lut.update({ "armv7": "arm32", "armv8_32": "arm32", "armv8": "arm64", }) - return os.path.join(self._source_subfolder, "PCbuild", build_subdir_lut[str(self.settings.arch)]) + return os.path.join(self.source_folder, "PCbuild", build_subdir_lut[str(self.settings.arch)]) @property def _msvc_install_subprefix(self): return "bin" def _copy_essential_dlls(self): - if self.settings.compiler == "Visual Studio": + if is_msvc(self): # Until MSVC builds support cross building, copy dll's of essential (shared) dependencies to python binary location. # These dll's are required when running the layout tool using the newly built python executable. dest_path = os.path.join(self.build_folder, self._msvc_artifacts_path) if self._with_libffi: - for bin_path in self.deps_cpp_info["libffi"].bin_paths: - self.copy("*.dll", src=bin_path, dst=dest_path) - for bin_path in self.deps_cpp_info["expat"].bin_paths: - self.copy("*.dll", src=bin_path, dst=dest_path) - for bin_path in self.deps_cpp_info["zlib"].bin_paths: - self.copy("*.dll", src=bin_path, dst=dest_path) + for bin_path in self.dependencies["libffi"].cpp_info.bindirs: + copy(self, "*.dll", src=bin_path, dst=dest_path) + for bin_path in self.dependencies["expat"].cpp_info.bindirs: + copy(self, "*.dll", src=bin_path, dst=dest_path) + for bin_path in self.dependencies["zlib"].cpp_info.bindirs: + copy(self, "*.dll", src=bin_path, dst=dest_path) def _msvc_package_layout(self): self._copy_essential_dlls() install_prefix = os.path.join(self.package_folder, self._msvc_install_subprefix) - tools.mkdir(install_prefix) + mkdir(self, install_prefix) build_path = self._msvc_artifacts_path infix = "_d" if self.settings.build_type == "Debug" else "" # FIXME: if cross building, use a build python executable here - python_built = os.path.join(build_path, "python{}.exe".format(infix)) + python_built = os.path.join(build_path, f"python{infix}.exe") layout_args = [ - os.path.join(self._source_subfolder, "PC", "layout", "main.py"), + os.path.join(self.source_folder, "PC", "layout", "main.py"), "-v", - "-s", self._source_subfolder, + "-s", self.source_folder, "-b", build_path, "--copy", install_prefix, "-p", @@ -481,10 +537,10 @@ def _msvc_package_layout(self): layout_args.append("--include-tcltk") if self.settings.build_type == "Debug": layout_args.append("-d") - python_args = " ".join("\"{}\"".format(a) for a in layout_args) - self.run("{} {}".format(python_built, python_args), run_environment=True) + python_args = " ".join(f'"{a}"' for a in layout_args) + self.run(f"{python_built} {python_args}") - tools.rmdir(os.path.join(self.package_folder, "bin", "tcl")) + rmdir(self, os.path.join(self.package_folder, "bin", "tcl")) for file in os.listdir(install_prefix): if re.match("vcruntime.*", file): @@ -498,45 +554,64 @@ def _msvc_package_layout(self): def _msvc_package_copy(self): build_path = self._msvc_artifacts_path infix = "_d" if self.settings.build_type == "Debug" else "" - self.copy("*.exe", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) - self.copy("*.dll", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) - self.copy("*.pyd", src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "DLLs")) - self.copy("python{}{}.lib".format(self._version_suffix, infix), src=build_path, dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "libs")) - self.copy("*", src=os.path.join(self._source_subfolder, "Include"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) - self.copy("pyconfig.h", src=os.path.join(self._source_subfolder, "PC"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) - self.copy("*.py", src=os.path.join(self._source_subfolder, "lib"), dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib")) - tools.rmdir(os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib", "test")) + copy(self, "*.exe", + src=build_path, + dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) + copy(self, "*.dll", + src=build_path, + dst=os.path.join(self.package_folder, self._msvc_install_subprefix)) + copy(self, "*.pyd", + src=build_path, + dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "DLLs")) + copy(self, f"python{self._version_suffix}{infix}.lib", + src=build_path, + dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "libs")) + copy(self, "*", + src=os.path.join(self.source_folder, "Include"), + dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) + copy(self, "pyconfig.h", + src=os.path.join(self.source_folder, "PC"), + dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "include")) + copy(self, "*.py", + src=os.path.join(self.source_folder, "lib"), + dst=os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib")) + rmdir(self, os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib", "test")) packages = {} get_name_version = lambda fn: fn.split(".", 2)[:2] - whldir = os.path.join(self._source_subfolder, "Lib", "ensurepip", "_bundled") + whldir = os.path.join(self.source_folder, "Lib", "ensurepip", "_bundled") for fn in filter(lambda n: n.endswith(".whl"), os.listdir(whldir)): name, version = get_name_version(fn) add = True if name in packages: pname, pversion = get_name_version(packages[name]) - add = tools.Version(version) > tools.Version(pversion) + add = Version(self, version) > Version(self, pversion) if add: packages[name] = fn for fname in packages.values(): - tools.unzip(filename=os.path.join(whldir, fname), destination=os.path.join(self.package_folder, "bin", "Lib", "site-packages")) + unzip(self, filename=os.path.join(whldir, fname), + destination=os.path.join(self.package_folder, "bin", "Lib", "site-packages")) - self.run("{} -c \"import compileall; compileall.compile_dir('{}')\"".format(os.path.join(build_path, self._cpython_interpreter_name), os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib").replace("\\", "/")), - run_environment=True) + self.run( + "{} -c \"import compileall; compileall.compile_dir('{}')\"".format( + os.path.join(build_path, self._cpython_interpreter_name), + os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib").replace("\\", "/"), + ) + ) def package(self): - self.copy("LICENSE", src=self._source_subfolder, dst="licenses") - if self.settings.compiler == "Visual Studio": + copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) + if is_msvc(self): if self._is_py2 or not self.options.shared: self._msvc_package_copy() else: self._msvc_package_layout() - tools.remove_files_by_mask(os.path.join(self.package_folder, "bin"), "vcruntime*") + rm(self, "vcruntime*", os.path.join(self.package_folder, "bin"), recursive=True) else: - autotools = self._configure_autotools() + autotools = Autotools(self) autotools.install() - tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig")) - tools.rmdir(os.path.join(self.package_folder, "share")) + rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) + rmdir(self, os.path.join(self.package_folder, "share")) # Rewrite shebangs of python scripts for filename in os.listdir(os.path.join(self.package_folder, "bin")): @@ -547,25 +622,29 @@ def package(self): continue with open(filepath, "rb") as fn: firstline = fn.readline(1024) - if not(firstline.startswith(b"#!") and b"/python" in firstline and b"/bin/sh" not in firstline): + if not ( + firstline.startswith(b"#!") + and b"/python" in firstline + and b"/bin/sh" not in firstline + ): continue text = fn.read() - self.output.info("Rewriting shebang of {}".format(filename)) + self.output.info(f"Rewriting shebang of {filename}") with open(filepath, "wb") as fn: - fn.write(textwrap.dedent("""\ + fn.write(textwrap.dedent(f"""\ #!/bin/sh ''':' __file__="$0" while [ -L "$__file__" ]; do __file__="$(dirname "$__file__")/$(readlink "$__file__")" done - exec "$(dirname "$__file__")/python{}" "$0" "$@" + exec "$(dirname "$__file__")/python{self._version_suffix}" "$0" "$@" ''' - """.format(self._version_suffix)).encode()) + """).encode()) fn.write(text) if not os.path.exists(self._cpython_symlink): - os.symlink("python{}".format(self._version_suffix), self._cpython_symlink) + os.symlink(f"python{self._version_suffix}", self._cpython_symlink) self._fix_install_name() @property @@ -577,12 +656,12 @@ def _cpython_symlink(self): @property def _cpython_interpreter_name(self): - if self.settings.compiler == "Visual Studio": + if is_msvc(self): suffix = "" else: suffix = self._version_suffix - python = "python{}".format(suffix) - if self.settings.compiler == "Visual Studio": + python = f"python{suffix}" + if is_msvc(self): if self.settings.build_type == "Debug": python += "_d" if self.settings.os == "Windows": @@ -599,34 +678,36 @@ def _abi_suffix(self): if self._is_py3: if self.settings.build_type == "Debug": res += "d" - if tools.Version(self._version_number_only) < "3.8": + if Version(self._version_number_only) < "3.8": if self.options.get_safe("pymalloc", False): res += "m" return res @property def _lib_name(self): - if self.settings.compiler == "Visual Studio": + if is_msvc(self): if self.settings.build_type == "Debug": lib_ext = "_d" else: lib_ext = "" else: - lib_ext = self._abi_suffix + (".dll.a" if self.options.shared and self.settings.os == "Windows" else "") - return "python{}{}".format(self._version_suffix, lib_ext) + lib_ext = self._abi_suffix + ( + ".dll.a" if self.options.shared and self.settings.os == "Windows" else "" + ) + return f"python{self._version_suffix}{lib_ext}" def _fix_install_name(self): - if tools.is_apple_os(self.settings.os) and self.options.shared: + if is_apple_os(self) and self.options.shared: buffer = StringIO() python = os.path.join(self.package_folder, "bin", "python") - self.run('otool -L "%s"' % python, output=buffer) - lines = buffer.getvalue().strip().split('\n')[1:] + self.run(f'otool -L "{python}"', buffer) + lines = buffer.getvalue().strip().split("\n")[1:] for line in lines: library = line.split()[0] if library.startswith(self.package_folder): new = library.replace(self.package_folder, "@executable_path/..") - self.output.info("patching {}, replace {} with {}".format(python, library, new)) - self.run("install_name_tool -change {} {} {}".format(library, new, python)) + self.output.info(f"patching {python}, replace {library} with {new}") + self.run(f"install_name_tool -change {library} {new} {python}") def package_info(self): # FIXME: conan components Python::Interpreter component, need a target type @@ -634,40 +715,57 @@ def package_info(self): # self.cpp_info.names["cmake_find_package_multi"] = "Python" # FIXME: conan components need to generate multiple .pc files (python2, python-27) - py_version = tools.Version(self._version_number_only) + self.cpp_info.frameworkdirs = [] + self.cpp_info.libdirs = [] + self.cpp_info.resdirs = [] + self.cpp_info.includedirs = [] + + py_version = Version(self._version_number_only) # python component: "Build a C extension for Python" - if self.settings.compiler == "Visual Studio": - self.cpp_info.components["python"].includedirs = [os.path.join(self._msvc_install_subprefix, "include")] + if is_msvc(self): + self.cpp_info.components["python"].includedirs = [ + os.path.join(self._msvc_install_subprefix, "include") + ] libdir = os.path.join(self._msvc_install_subprefix, "libs") else: - self.cpp_info.components["python"].includedirs.append(os.path.join("include", "python{}{}".format(self._version_suffix, self._abi_suffix))) + self.cpp_info.components["python"].includedirs.append( + os.path.join("include", f"python{self._version_suffix}{self._abi_suffix}") + ) libdir = "lib" if self.options.shared: self.cpp_info.components["python"].defines.append("Py_ENABLE_SHARED") else: self.cpp_info.components["python"].defines.append("Py_NO_ENABLE_SHARED") - if self.settings.os == "Linux": + if self.settings.os in ["Linux", "FreeBSD"]: self.cpp_info.components["python"].system_libs.extend(["dl", "m", "pthread", "util"]) elif self.settings.os == "Windows": - self.cpp_info.components["python"].system_libs.extend(["pathcch", "shlwapi", "version", "ws2_32"]) + self.cpp_info.components["python"].system_libs.extend( + ["pathcch", "shlwapi", "version", "ws2_32"] + ) self.cpp_info.components["python"].requires = ["zlib::zlib"] if self.settings.os != "Windows": self.cpp_info.components["python"].requires.append("libxcrypt::libxcrypt") - self.cpp_info.components["python"].names["pkg_config"] = "python-{}.{}".format(py_version.major, py_version.minor) + self.cpp_info.components["python"].set_property( + "pkg_config_name", f"python-{py_version.major}.{py_version.minor}" + ) self.cpp_info.components["python"].libdirs = [] - self.cpp_info.components["_python_copy"].names["pkg_config"] = "python{}".format(py_version.major) + self.cpp_info.components["_python_copy"].set_property("pkg_config_name", f"python{py_version.major}") self.cpp_info.components["_python_copy"].requires = ["python"] self.cpp_info.components["_python_copy"].libdirs = [] # embed component: "Embed Python into an application" self.cpp_info.components["embed"].libs = [self._lib_name] self.cpp_info.components["embed"].libdirs = [libdir] - self.cpp_info.components["embed"].names["pkg_config"] = "python-{}.{}-embed".format(py_version.major, py_version.minor) + self.cpp_info.components["embed"].set_property( + "pkg_config_name", f"python-{py_version.major}.{py_version.minor}-embed" + ) self.cpp_info.components["embed"].requires = ["python"] self.cpp_info.components["_embed_copy"].requires = ["embed"] - self.cpp_info.components["_embed_copy"].names["pkg_config"] = ["python{}-embed".format(py_version.major)] + self.cpp_info.components["_embed_copy"].set_property( + "pkg_config_name", f"python{py_version.major}-embed" + ) self.cpp_info.components["_embed_copy"].libdirs = [] if self._supports_modules: @@ -681,7 +779,7 @@ def package_info(self): if self._with_libffi: self.cpp_info.components["_hidden"].requires.append("libffi::libffi") if self.settings.os != "Windows": - if not tools.is_apple_os(self.settings.os): + if not is_apple_os(self): self.cpp_info.components["_hidden"].requires.append("libuuid::libuuid") self.cpp_info.components["_hidden"].requires.append("libxcrypt::libxcrypt") if self.options.with_bz2: @@ -702,30 +800,34 @@ def package_info(self): if self.options.env_vars: bindir = os.path.join(self.package_folder, "bin") - self.output.info("Appending PATH environment variable: {}".format(bindir)) + self.output.info(f"Appending PATH environment variable: {bindir}") self.env_info.PATH.append(bindir) python = self._cpython_interpreter_path + self.conf_info.define("user.cpython:python", python) self.user_info.python = python if self.options.env_vars: - self.output.info("Setting PYTHON environment variable: {}".format(python)) self.env_info.PYTHON = python - if self.settings.compiler == "Visual Studio": + if is_msvc(self): pythonhome = os.path.join(self.package_folder, "bin") - elif tools.is_apple_os(self.settings.os): + elif is_apple_os(self): pythonhome = self.package_folder else: - version = tools.Version(self._version_number_only) - pythonhome = os.path.join(self.package_folder, "lib", "python{}.{}".format(version.major, version.minor)) + version = Version(self._version_number_only) + pythonhome = os.path.join( + self.package_folder, "lib", f"python{version.major}.{version.minor}" + ) + self.conf_info.define("user.cpython:pythonhome", pythonhome) self.user_info.pythonhome = pythonhome - pythonhome_required = self.settings.compiler == "Visual Studio" or tools.is_apple_os(self.settings.os) + pythonhome_required = is_msvc(self) or is_apple_os(self) + self.conf_info.define("user.cpython:module_requires_pythonhome", pythonhome_required) self.user_info.module_requires_pythonhome = pythonhome_required - if self.settings.compiler == "Visual Studio": + if is_msvc(self): if self.options.env_vars: - self.output.info("Setting PYTHONHOME environment variable: {}".format(pythonhome)) + self.output.info(f"Setting PYTHONHOME environment variable: {pythonhome}") self.env_info.PYTHONHOME = pythonhome if self._is_py2: @@ -733,6 +835,7 @@ def package_info(self): else: python_root = self.package_folder if self.options.env_vars: - self.output.info("Setting PYTHON_ROOT environment variable: {}".format(python_root)) + self.output.info(f"Setting PYTHON_ROOT environment variable: {python_root}") self.env_info.PYTHON_ROOT = python_root + self.conf_info.define("user.cpython:python_root", python_root) self.user_info.python_root = python_root diff --git a/recipes/cpython/all/patches/2.7.18-0001-msvc.patch b/recipes/cpython/all/patches/2.7/2.7.18-0001-msvc.patch similarity index 100% rename from recipes/cpython/all/patches/2.7.18-0001-msvc.patch rename to recipes/cpython/all/patches/2.7/2.7.18-0001-msvc.patch diff --git a/recipes/cpython/all/patches/2.7.18-0002-add-support-msvc-14.patch b/recipes/cpython/all/patches/2.7/2.7.18-0002-add-support-msvc-14.patch similarity index 100% rename from recipes/cpython/all/patches/2.7.18-0002-add-support-msvc-14.patch rename to recipes/cpython/all/patches/2.7/2.7.18-0002-add-support-msvc-14.patch diff --git a/recipes/cpython/all/patches/2.7.18-0003-msvc-fix-static.patch b/recipes/cpython/all/patches/2.7/2.7.18-0003-msvc-fix-static.patch similarity index 100% rename from recipes/cpython/all/patches/2.7.18-0003-msvc-fix-static.patch rename to recipes/cpython/all/patches/2.7/2.7.18-0003-msvc-fix-static.patch diff --git a/recipes/cpython/all/patches/2.7.18-0004-disable-macos-tcltk.patch b/recipes/cpython/all/patches/2.7/2.7.18-0004-disable-macos-tcltk.patch similarity index 100% rename from recipes/cpython/all/patches/2.7.18-0004-disable-macos-tcltk.patch rename to recipes/cpython/all/patches/2.7/2.7.18-0004-disable-macos-tcltk.patch diff --git a/recipes/cpython/all/patches/3.10.0-0001-msvc.patch b/recipes/cpython/all/patches/3.10/3.10.0-0001-msvc.patch similarity index 100% rename from recipes/cpython/all/patches/3.10.0-0001-msvc.patch rename to recipes/cpython/all/patches/3.10/3.10.0-0001-msvc.patch diff --git a/recipes/cpython/all/patches/3.10.0-0003-_ctypes-ffi.patch b/recipes/cpython/all/patches/3.10/3.10.0-0003-_ctypes-ffi.patch similarity index 100% rename from recipes/cpython/all/patches/3.10.0-0003-_ctypes-ffi.patch rename to recipes/cpython/all/patches/3.10/3.10.0-0003-_ctypes-ffi.patch diff --git a/recipes/cpython/all/patches/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch b/recipes/cpython/all/patches/3.10/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch similarity index 100% rename from recipes/cpython/all/patches/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch rename to recipes/cpython/all/patches/3.10/3.10.0-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch diff --git a/recipes/cpython/all/patches/3.10.0-0005-disable-macos-tcltk.patch b/recipes/cpython/all/patches/3.10/3.10.0-0005-disable-macos-tcltk.patch similarity index 100% rename from recipes/cpython/all/patches/3.10.0-0005-disable-macos-tcltk.patch rename to recipes/cpython/all/patches/3.10/3.10.0-0005-disable-macos-tcltk.patch diff --git a/recipes/cpython/all/patches/3.7.9-0001-msvc.patch b/recipes/cpython/all/patches/3.7/3.7.9-0001-msvc.patch similarity index 100% rename from recipes/cpython/all/patches/3.7.9-0001-msvc.patch rename to recipes/cpython/all/patches/3.7/3.7.9-0001-msvc.patch diff --git a/recipes/cpython/all/patches/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch b/recipes/cpython/all/patches/3.7/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch similarity index 100% rename from recipes/cpython/all/patches/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch rename to recipes/cpython/all/patches/3.7/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch diff --git a/recipes/cpython/all/patches/3.7.9-0003-disable-macos-tcltk.patch b/recipes/cpython/all/patches/3.7/3.7.9-0003-disable-macos-tcltk.patch similarity index 100% rename from recipes/cpython/all/patches/3.7.9-0003-disable-macos-tcltk.patch rename to recipes/cpython/all/patches/3.7/3.7.9-0003-disable-macos-tcltk.patch diff --git a/recipes/cpython/all/patches/3.8.12-0001-msvc.patch b/recipes/cpython/all/patches/3.8/3.8.12-0001-msvc.patch similarity index 100% rename from recipes/cpython/all/patches/3.8.12-0001-msvc.patch rename to recipes/cpython/all/patches/3.8/3.8.12-0001-msvc.patch diff --git a/recipes/cpython/all/patches/3.8.12-0002-_ctypes-ffi.patch b/recipes/cpython/all/patches/3.8/3.8.12-0002-_ctypes-ffi.patch similarity index 100% rename from recipes/cpython/all/patches/3.8.12-0002-_ctypes-ffi.patch rename to recipes/cpython/all/patches/3.8/3.8.12-0002-_ctypes-ffi.patch diff --git a/recipes/cpython/all/patches/3.8.12-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch b/recipes/cpython/all/patches/3.8/3.8.12-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch similarity index 100% rename from recipes/cpython/all/patches/3.8.12-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch rename to recipes/cpython/all/patches/3.8/3.8.12-0003-setup.py-pass-CFLAGS-CPPFLAGS.patch diff --git a/recipes/cpython/all/patches/3.8.12-0004-disable-macos-tcltk.patch b/recipes/cpython/all/patches/3.8/3.8.12-0004-disable-macos-tcltk.patch similarity index 100% rename from recipes/cpython/all/patches/3.8.12-0004-disable-macos-tcltk.patch rename to recipes/cpython/all/patches/3.8/3.8.12-0004-disable-macos-tcltk.patch diff --git a/recipes/cpython/all/patches/3.9.7-0001-msvc.patch b/recipes/cpython/all/patches/3.9/3.9.7-0001-msvc.patch similarity index 100% rename from recipes/cpython/all/patches/3.9.7-0001-msvc.patch rename to recipes/cpython/all/patches/3.9/3.9.7-0001-msvc.patch diff --git a/recipes/cpython/all/patches/3.9.7-0002-_msi-vcxproj.patch b/recipes/cpython/all/patches/3.9/3.9.7-0002-_msi-vcxproj.patch similarity index 100% rename from recipes/cpython/all/patches/3.9.7-0002-_msi-vcxproj.patch rename to recipes/cpython/all/patches/3.9/3.9.7-0002-_msi-vcxproj.patch diff --git a/recipes/cpython/all/patches/3.9.7-0003-_ctypes-ffi.patch b/recipes/cpython/all/patches/3.9/3.9.7-0003-_ctypes-ffi.patch similarity index 100% rename from recipes/cpython/all/patches/3.9.7-0003-_ctypes-ffi.patch rename to recipes/cpython/all/patches/3.9/3.9.7-0003-_ctypes-ffi.patch diff --git a/recipes/cpython/all/patches/3.9.7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch b/recipes/cpython/all/patches/3.9/3.9.7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch similarity index 100% rename from recipes/cpython/all/patches/3.9.7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch rename to recipes/cpython/all/patches/3.9/3.9.7-0004-setup.py-pass-CFLAGS-CPPFLAGS.patch diff --git a/recipes/cpython/all/patches/3.9.7-0005-disable-macos-tcltk.patch b/recipes/cpython/all/patches/3.9/3.9.7-0005-disable-macos-tcltk.patch similarity index 100% rename from recipes/cpython/all/patches/3.9.7-0005-disable-macos-tcltk.patch rename to recipes/cpython/all/patches/3.9/3.9.7-0005-disable-macos-tcltk.patch diff --git a/recipes/cpython/all/test_package/CMakeLists.txt b/recipes/cpython/all/test_package/CMakeLists.txt index 525329324757f..502bf95860bce 100644 --- a/recipes/cpython/all/test_package/CMakeLists.txt +++ b/recipes/cpython/all/test_package/CMakeLists.txt @@ -1,8 +1,7 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.15) project(test_package C) -include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") -conan_basic_setup() +find_package(cpython REQUIRED CONFIG) set(CACHE PY_VERSION_MAJOR "" CACHE STRING "MAJOR version of python") set(CACHE PY_VERSION_MAJOR_MINOR "" CACHE STRING "MAJOR.MINOR version of python") @@ -97,4 +96,4 @@ if(BUILD_MODULE) endif() add_executable(${PROJECT_NAME} "py${PY_VERSION_MAJOR}/test_package.c") -target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS}) +target_link_libraries(${PROJECT_NAME} PRIVATE cpython::cpython) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 8abc18e4492c5..e990896305c6b 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -1,5 +1,83 @@ -from conans import AutoToolsBuildEnvironment, ConanFile, CMake, tools, RunEnvironment -from conans.errors import ConanException +# TODO: verify the Conan v2 migration + +import os +from contextlib import nullcontext + +from conan import ConanFile, conan_version +from conan.errors import ConanInvalidConfiguration, ConanException +from conan.tools.android import android_abi +from conan.tools.apple import ( + XCRun, + fix_apple_shared_install_name, + is_apple_os, + to_apple_arch, +) +from conan.tools.build import ( + build_jobs, + can_run, + check_min_cppstd, + cross_building, + default_cppstd, + stdcpp_library, + valid_min_cppstd, +) +from conan.tools.cmake import ( + CMake, + CMakeDeps, + CMakeToolchain, + cmake_layout, +) +from conan.tools.env import ( + Environment, + VirtualBuildEnv, + VirtualRunEnv, +) +from conan.tools.files import ( + apply_conandata_patches, + chdir, + collect_libs, + copy, + download, + export_conandata_patches, + get, + load, + mkdir, + patch, + patches, + rename, + replace_in_file, + rm, + rmdir, + save, + symlinks, + unzip, +) +from conan.tools.gnu import ( + Autotools, + AutotoolsDeps, + AutotoolsToolchain, + PkgConfig, + PkgConfigDeps, +) +from conan.tools.layout import basic_layout +from conan.tools.meson import MesonToolchain, Meson +from conan.tools.microsoft import ( + MSBuild, + MSBuildDeps, + MSBuildToolchain, + NMakeDeps, + NMakeToolchain, + VCVars, + check_min_vs, + is_msvc, + is_msvc_static_runtime, + msvc_runtime_flag, + unix_path, + unix_path_package_info_legacy, + vs_layout, +) +from conan.tools.scm import Version +from conan.tools.system import package_manager from io import StringIO import os import re @@ -19,9 +97,7 @@ def __init__(self, debug, pymalloc, unicode): @property def suffix(self): return "{}{}{}".format( - "d" if self.debug else "", - "m" if self.pymalloc else "", - "u" if self.unicode else "", + "d" if self.debug else "", "m" if self.pymalloc else "", "u" if self.unicode else "" ) @property @@ -31,105 +107,119 @@ def cmake_arg(self): class TestPackageConan(ConanFile): settings = "os", "compiler", "build_type", "arch" - generators = "cmake" @property def _py_version(self): - return re.match(r"^([0-9.]+)", self.deps_cpp_info["cpython"].version).group(1) + return re.match(r"^([0-9.]+)", self.dependencies["cpython"].ref.version).group(1) @property def _pymalloc(self): - return bool("pymalloc" in self.options["cpython"] and self.options["cpython"].pymalloc) + return bool(self.dependencies["cpython"].options.get_safe("pymalloc", False)) @property def _cmake_abi(self): - if self._py_version < tools.Version("3.8"): + if self._py_version < Version(self, "3.8"): return CmakePython3Abi( - debug=self.settings.build_type == "Debug", - pymalloc=self._pymalloc, - unicode=False, + debug=self.settings.build_type == "Debug", pymalloc=self._pymalloc, unicode=False ) else: - return CmakePython3Abi( - debug=self.settings.build_type == "Debug", - pymalloc=False, - unicode=False, - ) + return CmakePython3Abi(debug=self.settings.build_type == "Debug", pymalloc=False, unicode=False) @property def _cmake_try_FindPythonX(self): - if self.settings.compiler == "Visual Studio" and self.settings.build_type == "Debug": + if is_msvc(self) and self.settings.build_type == "Debug": return False return True @property def _supports_modules(self): - return self.settings.compiler != "Visual Studio" or self.options["cpython"].shared + return not is_msvc(self) or self.dependencies["cpython"].options.shared - def build(self): - if not tools.cross_building(self, skip_x64_x86=True): - command = "{} --version".format(self.deps_user_info["cpython"].python) - buffer = StringIO() - self.run(command, output=buffer, ignore_errors=True, run_environment=True) - self.output.info("output: %s" % buffer.getvalue()) - self.run(command, run_environment=True) + def generate(self): + tc = CMakeToolchain(self) + py_major = Version(self.dependencies["cpython"]).major + tc.variables["BUILD_MODULE"] = self._supports_modules + tc.variables["PY_VERSION_MAJOR"] = py_major + tc.variables["PY_VERSION_MAJOR_MINOR"] = ".".join(self._py_version.split(".")[:2]) + tc.variables["PY_FULL_VERSION"] = self.dependencies["cpython"].ref.version + tc.variables["PY_VERSION"] = self._py_version + tc.variables["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix + tc.variables["PYTHON_EXECUTABLE"] = self.conf_info.get("user.cpython:python") + tc.variables["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX + tc.variables[f"Python{py_major}_EXECUTABLE"] = self.conf_info.get("user.cpython:python") + tc.variables[f"Python{py_major}_ROOT_DIR"] = self.dependencies["cpython"].package_folder + tc.variables[f"Python{py_major}_USE_STATIC_LIBS"] = not self.dependencies["cpython"].options.shared + tc.variables[f"Python{py_major}_FIND_FRAMEWORK"] = "NEVER" + tc.variables[f"Python{py_major}_FIND_REGISTRY"] = "NEVER" + tc.variables[f"Python{py_major}_FIND_IMPLEMENTATIONS"] = "CPython" + tc.variables[f"Python{py_major}_FIND_STRATEGY"] = "LOCATION" - cmake = CMake(self) - py_major = self.deps_cpp_info["cpython"].version.split(".")[0] - cmake.definitions["BUILD_MODULE"] = self._supports_modules - cmake.definitions["PY_VERSION_MAJOR"] = py_major - cmake.definitions["PY_VERSION_MAJOR_MINOR"] = ".".join(self._py_version.split(".")[:2]) - cmake.definitions["PY_FULL_VERSION"] = self.deps_cpp_info["cpython"].version - cmake.definitions["PY_VERSION"] = self._py_version - cmake.definitions["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix - cmake.definitions["PYTHON_EXECUTABLE"] = self.deps_user_info["cpython"].python - cmake.definitions["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX - cmake.definitions["Python{}_EXECUTABLE".format(py_major)] = self.deps_user_info["cpython"].python - cmake.definitions["Python{}_ROOT_DIR".format(py_major)] = self.deps_cpp_info["cpython"].rootpath - cmake.definitions["Python{}_USE_STATIC_LIBS".format(py_major)] = not self.options["cpython"].shared - cmake.definitions["Python{}_FIND_FRAMEWORK".format(py_major)] = "NEVER" - cmake.definitions["Python{}_FIND_REGISTRY".format(py_major)] = "NEVER" - cmake.definitions["Python{}_FIND_IMPLEMENTATIONS".format(py_major)] = "CPython" - cmake.definitions["Python{}_FIND_STRATEGY".format(py_major)] = "LOCATION" - - if self.settings.compiler != "Visual Studio": - if tools.Version(self._py_version) < tools.Version("3.8"): - cmake.definitions["Python{}_FIND_ABI".format(py_major)] = self._cmake_abi.cmake_arg - - with tools.environment_append(RunEnvironment(self).vars): - cmake.configure() - cmake.build() + if not is_msvc(self): + if Version(self._py_version) < Version(self, "3.8"): + tc.variables["Python{}_FIND_ABI".format(py_major)] = self._cmake_abi.cmake_arg - if not tools.cross_building(self, skip_x64_x86=True): + if not cross_building(self, skip_x64_x86=True): if self._supports_modules: - with tools.vcvars(self.settings) if self.settings.compiler == "Visual Studio" else tools.no_op(): - modsrcfolder = "py2" if tools.Version(self.deps_cpp_info["cpython"].version).major < "3" else "py3" - tools.mkdir(os.path.join(self.build_folder, modsrcfolder)) + with vcvars(self.settings) if is_msvc(self) else nullcontext(): + modsrcfolder = ( + "py2" if Version(self.dependencies["cpython"].ref.version).major < "3" else "py3" + ) + mkdir(self, os.path.join(self.build_folder, modsrcfolder)) for fn in os.listdir(os.path.join(self.source_folder, modsrcfolder)): - shutil.copy(os.path.join(self.source_folder, modsrcfolder, fn), os.path.join(self.build_folder, modsrcfolder, fn)) - shutil.copy(os.path.join(self.source_folder, "setup.py"), os.path.join(self.build_folder, "setup.py")) + shutil.copy( + os.path.join(self.source_folder, modsrcfolder, fn), + os.path.join(self.build_folder, modsrcfolder, fn), + ) + shutil.copy( + os.path.join(self.source_folder, "setup.py"), + os.path.join(self.build_folder, "setup.py"), + ) env = { "DISTUTILS_USE_SDK": "1", - "MSSdk": "1" + "MSSdk": "1", } env.update(**AutoToolsBuildEnvironment(self).vars) - with tools.environment_append(env): + with environment_append(self, env): setup_args = [ "{}/setup.py".format(self.source_folder), # "conan", # "--install-folder", self.build_folder, "build", - "--build-base", self.build_folder, - "--build-platlib", os.path.join(self.build_folder, "lib_setuptools"), + "--build-base", + self.build_folder, + "--build-platlib", + os.path.join(self.build_folder, "lib_setuptools"), ] if self.settings.build_type == "Debug": setup_args.append("--debug") - self.run("{} {}".format(self.deps_user_info["cpython"].python, " ".join("\"{}\"".format(a) for a in setup_args)), run_environment=True) + self.run( + "{} {}".format( + self.conf_info.get("user.cpython:python"), + " ".join('"{}"'.format(a) for a in setup_args), + ), + ) + + def build(self): + if not cross_building(self, skip_x64_x86=True): + python_executable = self.conf_info.get("user.cpython:python") + command = f"{python_executable} --version" + buffer = StringIO() + self.run(command, stdout=buffer, ignore_errors=True) + self.output.info(f"output: {buffer.getvalue()}") + self.run(command) + + cmake = CMake(self) + cmake.configure() + cmake.build() def _test_module(self, module, should_work): try: - self.run("{} {}/test_package.py -b {} -t {} ".format( - self.deps_user_info["cpython"].python, self.source_folder, self.build_folder, module), run_environment=True) + self.run( + "{} {}/test_package.py -b {} -t {} ".format( + self.conf_info.get("user.cpython:python"), self.source_folder, self.build_folder, module + ), + run_environment=True, + ) works = True except ConanException as e: works = False @@ -138,27 +228,38 @@ def _test_module(self, module, should_work): self.output.info("Result of test was expected.") else: if works: - raise ConanException("Module '{}' works, but should not have worked".format(module)) + raise ConanException(f"Module '{module}' works, but should not have worked") else: - self.output.warn("Module '{}' does not work, but should have worked".format(module)) + self.output.warning(f"Module '{module}' does not work, but should have worked") raise exception def _cpython_option(self, name): try: - return getattr(self.options["cpython"], name, False) + return self.dependencies["cpython"].options.get_safe(name, False) except ConanException: return False def test(self): - if not tools.cross_building(self, skip_x64_x86=True): - self.run("{} -c \"print('hello world')\"".format(self.deps_user_info["cpython"].python), run_environment=True) + if not cross_building(self, skip_x64_x86=True): + self.run( + "{} -c \"print('hello world')\"".format(self.conf_info.get("user.cpython:python")), + ) buffer = StringIO() - self.run("{} -c \"import sys; print('.'.join(str(s) for s in sys.version_info[:3]))\"".format(self.deps_user_info["cpython"].python), run_environment=True, output=buffer) + self.run( + "{} -c \"import sys; print('.'.join(str(s) for s in sys.version_info[:3]))\"".format( + self.conf_info.get("user.cpython:python") + ), + stdout=buffer, + ) self.output.info(buffer.getvalue()) version_detected = buffer.getvalue().splitlines()[-1].strip() if self._py_version != version_detected: - raise ConanException("python reported wrong version. Expected {exp}. Got {res}.".format(exp=self._py_version, res=version_detected)) + raise ConanException( + "python reported wrong version. Expected {exp}. Got {res}.".format( + exp=self._py_version, res=version_detected + ) + ) if self._supports_modules: self._test_module("gdbm", self._cpython_option("with_gdbm")) @@ -166,27 +267,36 @@ def test(self): self._test_module("bsddb", self._cpython_option("with_bsddb")) self._test_module("lzma", self._cpython_option("with_lzma")) self._test_module("tkinter", self._cpython_option("with_tkinter")) - with tools.environment_append({"TERM": "ansi"}): - self._test_module("curses", self._cpython_option("with_curses")) + os.environ["TERM"] = "ansi" + self._test_module("curses", self._cpython_option("with_curses")) self._test_module("expat", True) self._test_module("sqlite3", True) self._test_module("decimal", True) self._test_module("ctypes", True) - if tools.is_apple_os(self.settings.os) and not self.options["cpython"].shared: - self.output.info("Not testing the module, because these seem not to work on apple when cpython is built as a static library") + if is_apple_os(self) and not self.dependencies["cpython"].options.shared: + self.output.info( + "Not testing the module, because these seem not to work on apple when cpython is built as" + " a static library" + ) # FIXME: find out why cpython on apple does not allow to use modules linked against a static python else: if self._supports_modules: - with tools.environment_append({"PYTHONPATH": [os.path.join(self.build_folder, "lib")]}): + with environment_append(self, {"PYTHONPATH": [os.path.join(self.build_folder, "lib")]}): self.output.info("Testing module (spam) using cmake built module") self._test_module("spam", True) - with tools.environment_append({"PYTHONPATH": [os.path.join(self.build_folder, "lib_setuptools")]}): + with environment_append( + self, {"PYTHONPATH": [os.path.join(self.build_folder, "lib_setuptools")]} + ): self.output.info("Testing module (spam) using setup.py built module") self._test_module("spam", True) # MSVC builds need PYTHONHOME set. - with tools.environment_append({"PYTHONHOME": self.deps_user_info["cpython"].pythonhome}) if self.deps_user_info["cpython"].module_requires_pythonhome == "True" else tools.no_op(): + with ( + environment_append(self, {"PYTHONHOME": self.conf_info.get("user.cpython:pythonhome")}) + if self.conf_info.get("user.cpython:module_requires_pythonhome") == "True" + else nullcontext() + ): self.run(os.path.join("bin", "test_package"), run_environment=True) diff --git a/recipes/cpython/all/test_package/test_package.py b/recipes/cpython/all/test_package/test_package.py index f77d2837c6376..aad4eb9c6cc9a 100644 --- a/recipes/cpython/all/test_package/test_package.py +++ b/recipes/cpython/all/test_package/test_package.py @@ -14,12 +14,13 @@ def add_test(fn): global ALL_TESTS - name = fn.__name__[fn.__name__.find("_")+1:] + name = fn.__name__[fn.__name__.find("_") + 1 :] def inner_fn(): print("testing {}".format(name)) sys.stdout.flush() fn() + ALL_TESTS[name] = inner_fn return fn @@ -30,13 +31,13 @@ def test_expat(): # 3 handler functions def start_element(name, attrs): - print('Start element:', name, attrs) + print("Start element:", name, attrs) def end_element(name): - print('End element:', name) + print("End element:", name) def char_data(data): - print('Character data:', repr(data)) + print("Character data:", repr(data)) p = xml.parsers.expat.ParserCreate() @@ -44,7 +45,8 @@ def char_data(data): p.EndElementHandler = end_element p.CharacterDataHandler = char_data - p.Parse(""" + p.Parse( + """ Text goes here More text """, 1) @@ -85,10 +87,8 @@ def test_spam(): if "This is an example spam doc." not in spam.__doc__: raise Exception("spam.__doc__ does not contain the expected text") - cmd = { - "Windows": "dir", - }.get(platform.system(), "ls") - print("About to run spam.system(\"{}\")".format(cmd)) + cmd = {"Windows": "dir"}.get(platform.system(), "ls") + print('About to run spam.system("{}")'.format(cmd)) sys.stdout.flush() spam.system(cmd) @@ -133,6 +133,7 @@ def test_lzma(): @add_test def test_sqlite3(): import sqlite3 + conn = sqlite3.connect("sqlite3.db") c = conn.cursor() @@ -141,16 +142,16 @@ def test_sqlite3(): c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)") conn.commit() - t = ('RHAT',) - c.execute('SELECT * FROM stocks WHERE symbol=?', t) + t = ("RHAT",) + c.execute("SELECT * FROM stocks WHERE symbol=?", t) # Larger example that inserts many records at a time purchases = [ - ('2006-03-28', 'BUY', 'IBM', 1000, 45.00), - ('2006-04-05', 'BUY', 'MSFT', 1000, 72.00), - ('2006-04-06', 'SELL', 'IBM', 500, 53.00), + ("2006-03-28", "BUY", "IBM", 1000, 45.00), + ("2006-04-05", "BUY", "MSFT", 1000, 72.00), + ("2006-04-06", "SELL", "IBM", 500, 53.00), ] - c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases) + c.executemany("INSERT INTO stocks VALUES (?,?,?,?,?)", purchases) conn.commit() conn.close() conn = sqlite3.connect("sqlite3.db") @@ -165,7 +166,7 @@ def test_sqlite3(): @add_test def test_decimal(): - if sys.version_info >= (3, ): + if sys.version_info >= (3,): # Check whether the _decimal package was built successfully import _decimal as decimal else: diff --git a/recipes/cpython/all/test_v1_package/CMakeLists.txt b/recipes/cpython/all/test_v1_package/CMakeLists.txt new file mode 100644 index 0000000000000..91630d79f4abb --- /dev/null +++ b/recipes/cpython/all/test_v1_package/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.15) +project(test_package) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup(TARGETS) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/ + ${CMAKE_CURRENT_BINARY_DIR}/test_package/) diff --git a/recipes/cpython/all/test_v1_package/conanfile.py b/recipes/cpython/all/test_v1_package/conanfile.py new file mode 100644 index 0000000000000..e3dae899ab9ec --- /dev/null +++ b/recipes/cpython/all/test_v1_package/conanfile.py @@ -0,0 +1,192 @@ +from conans import AutoToolsBuildEnvironment, ConanFile, CMake, tools, RunEnvironment +from conans.errors import ConanException +from io import StringIO +import os +import re +import shutil + + +class CmakePython3Abi(object): + def __init__(self, debug, pymalloc, unicode): + self.debug, self.pymalloc, self.unicode = debug, pymalloc, unicode + + _cmake_lut = { + None: "ANY", + True: "ON", + False: "OFF", + } + + @property + def suffix(self): + return "{}{}{}".format( + "d" if self.debug else "", + "m" if self.pymalloc else "", + "u" if self.unicode else "", + ) + + @property + def cmake_arg(self): + return ";".join(self._cmake_lut[a] for a in (self.debug, self.pymalloc, self.unicode)) + + +class TestPackageConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake", "cmake_find_package_multi" + + @property + def _py_version(self): + return re.match(r"^([0-9.]+)", self.deps_cpp_info["cpython"].version).group(1) + + @property + def _pymalloc(self): + return bool("pymalloc" in self.options["cpython"] and self.options["cpython"].pymalloc) + + @property + def _cmake_abi(self): + if self._py_version < tools.Version("3.8"): + return CmakePython3Abi( + debug=self.settings.build_type == "Debug", + pymalloc=self._pymalloc, + unicode=False, + ) + else: + return CmakePython3Abi( + debug=self.settings.build_type == "Debug", + pymalloc=False, + unicode=False, + ) + + @property + def _cmake_try_FindPythonX(self): + if self.settings.compiler == "Visual Studio" and self.settings.build_type == "Debug": + return False + return True + + @property + def _supports_modules(self): + return self.settings.compiler != "Visual Studio" or self.options["cpython"].shared + + def build(self): + if not tools.cross_building(self, skip_x64_x86=True): + command = "{} --version".format(self.deps_user_info["cpython"].python) + buffer = StringIO() + self.run(command, output=buffer, ignore_errors=True, run_environment=True) + self.output.info("output: %s" % buffer.getvalue()) + self.run(command, run_environment=True) + + cmake = CMake(self) + py_major = self.deps_cpp_info["cpython"].version.split(".")[0] + cmake.definitions["BUILD_MODULE"] = self._supports_modules + cmake.definitions["PY_VERSION_MAJOR"] = py_major + cmake.definitions["PY_VERSION_MAJOR_MINOR"] = ".".join(self._py_version.split(".")[:2]) + cmake.definitions["PY_FULL_VERSION"] = self.deps_cpp_info["cpython"].version + cmake.definitions["PY_VERSION"] = self._py_version + cmake.definitions["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix + cmake.definitions["PYTHON_EXECUTABLE"] = self.deps_user_info["cpython"].python + cmake.definitions["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX + cmake.definitions["Python{}_EXECUTABLE".format(py_major)] = self.deps_user_info["cpython"].python + cmake.definitions["Python{}_ROOT_DIR".format(py_major)] = self.deps_cpp_info["cpython"].rootpath + cmake.definitions["Python{}_USE_STATIC_LIBS".format(py_major)] = not self.options["cpython"].shared + cmake.definitions["Python{}_FIND_FRAMEWORK".format(py_major)] = "NEVER" + cmake.definitions["Python{}_FIND_REGISTRY".format(py_major)] = "NEVER" + cmake.definitions["Python{}_FIND_IMPLEMENTATIONS".format(py_major)] = "CPython" + cmake.definitions["Python{}_FIND_STRATEGY".format(py_major)] = "LOCATION" + + if self.settings.compiler != "Visual Studio": + if tools.Version(self._py_version) < tools.Version("3.8"): + cmake.definitions["Python{}_FIND_ABI".format(py_major)] = self._cmake_abi.cmake_arg + + with tools.environment_append(RunEnvironment(self).vars): + cmake.configure() + cmake.build() + + if not tools.cross_building(self, skip_x64_x86=True): + if self._supports_modules: + with tools.vcvars(self.settings) if self.settings.compiler == "Visual Studio" else tools.no_op(): + modsrcfolder = "py2" if tools.Version(self.deps_cpp_info["cpython"].version).major < "3" else "py3" + tools.mkdir(os.path.join(self.build_folder, modsrcfolder)) + for fn in os.listdir(os.path.join(self.source_folder, modsrcfolder)): + shutil.copy(os.path.join(self.source_folder, modsrcfolder, fn), os.path.join(self.build_folder, modsrcfolder, fn)) + shutil.copy(os.path.join(self.source_folder, "setup.py"), os.path.join(self.build_folder, "setup.py")) + env = { + "DISTUTILS_USE_SDK": "1", + "MSSdk": "1" + } + env.update(**AutoToolsBuildEnvironment(self).vars) + with tools.environment_append(env): + setup_args = [ + "{}/setup.py".format(self.source_folder), + # "conan", + # "--install-folder", self.build_folder, + "build", + "--build-base", self.build_folder, + "--build-platlib", os.path.join(self.build_folder, "lib_setuptools"), + ] + if self.settings.build_type == "Debug": + setup_args.append("--debug") + self.run("{} {}".format(self.deps_user_info["cpython"].python, " ".join("\"{}\"".format(a) for a in setup_args)), run_environment=True) + + def _test_module(self, module, should_work): + try: + self.run("{} {}/test_package.py -b {} -t {} ".format( + self.deps_user_info["cpython"].python, self.source_folder, self.build_folder, module), run_environment=True) + works = True + except ConanException as e: + works = False + exception = e + if should_work == works: + self.output.info("Result of test was expected.") + else: + if works: + raise ConanException("Module '{}' works, but should not have worked".format(module)) + else: + self.output.warn("Module '{}' does not work, but should have worked".format(module)) + raise exception + + def _cpython_option(self, name): + try: + return getattr(self.options["cpython"], name, False) + except ConanException: + return False + + def test(self): + if not tools.cross_building(self, skip_x64_x86=True): + self.run("{} -c \"print('hello world')\"".format(self.deps_user_info["cpython"].python), run_environment=True) + + buffer = StringIO() + self.run("{} -c \"import sys; print('.'.join(str(s) for s in sys.version_info[:3]))\"".format(self.deps_user_info["cpython"].python), run_environment=True, output=buffer) + self.output.info(buffer.getvalue()) + version_detected = buffer.getvalue().splitlines()[-1].strip() + if self._py_version != version_detected: + raise ConanException("python reported wrong version. Expected {exp}. Got {res}.".format(exp=self._py_version, res=version_detected)) + + if self._supports_modules: + self._test_module("gdbm", self._cpython_option("with_gdbm")) + self._test_module("bz2", self._cpython_option("with_bz2")) + self._test_module("bsddb", self._cpython_option("with_bsddb")) + self._test_module("lzma", self._cpython_option("with_lzma")) + self._test_module("tkinter", self._cpython_option("with_tkinter")) + with tools.environment_append({"TERM": "ansi"}): + self._test_module("curses", self._cpython_option("with_curses")) + + self._test_module("expat", True) + self._test_module("sqlite3", True) + self._test_module("decimal", True) + self._test_module("ctypes", True) + + if tools.is_apple_os(self) and not self.options["cpython"].shared: + self.output.info("Not testing the module, because these seem not to work on apple when cpython is built as a static library") + # FIXME: find out why cpython on apple does not allow to use modules linked against a static python + else: + if self._supports_modules: + with tools.environment_append({"PYTHONPATH": [os.path.join(self.build_folder, "lib")]}): + self.output.info("Testing module (spam) using cmake built module") + self._test_module("spam", True) + + with tools.environment_append({"PYTHONPATH": [os.path.join(self.build_folder, "lib_setuptools")]}): + self.output.info("Testing module (spam) using setup.py built module") + self._test_module("spam", True) + + # MSVC builds need PYTHONHOME set. + with tools.environment_append({"PYTHONHOME": self.deps_user_info["cpython"].pythonhome}) if self.deps_user_info["cpython"].module_requires_pythonhome == "True" else tools.no_op(): + self.run(os.path.join("bin", "test_package"), run_environment=True) diff --git a/recipes/cpython/config.yml b/recipes/cpython/config.yml index e3abf3ec8acb2..9c1e3f1bc1142 100644 --- a/recipes/cpython/config.yml +++ b/recipes/cpython/config.yml @@ -1,11 +1,13 @@ versions: + "3.10.13": + folder: "all" "3.10.0": folder: "all" - "3.9.7": + "3.9.18": folder: "all" - "3.8.12": + "3.8.18": folder: "all" - "3.7.12": + "3.7.17": folder: "all" "2.7.18": folder: "all" From 8c8671ae4c23d6db4c8bc1591b104e95dcbffeee Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Thu, 5 Oct 2023 13:43:54 +0300 Subject: [PATCH 003/102] cpython: fix autotools install step --- recipes/cpython/all/conanfile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index f2db3c394d737..81a7c63d8bee1 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -262,6 +262,8 @@ def _generate_autotools(self): # Building _testembed fails due to missing pthread/rt symbols tc.ldflags.append("-lpthread") + tc.make_args += ["DESTDIR=", "prefix=", "exec_prefix="] + build = None if cross_building(self) and not cross_building(self, skip_x64_x86=True): # Building from x86_64 to x86 is not a "real" cross build, so set build == host From c1c9f2e1fad5ab01a1f7eff8c0f739f24f80a4f1 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Thu, 5 Oct 2023 13:44:50 +0300 Subject: [PATCH 004/102] cpython: fix libuuid requirement --- recipes/cpython/all/conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 81a7c63d8bee1..b32b096193549 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -747,7 +747,7 @@ def package_info(self): self.cpp_info.components["_hidden"].requires.append("libffi::libffi") if self.settings.os != "Windows": if not is_apple_os(self): - self.cpp_info.components["_hidden"].requires.append("libuuid::libuuid") + self.cpp_info.components["_hidden"].requires.append("util-linux-libuuid::util-linux-libuuid") self.cpp_info.components["_hidden"].requires.append("libxcrypt::libxcrypt") if self.options.with_bz2: self.cpp_info.components["_hidden"].requires.append("bzip2::bzip2") From 960811e97a8911486c4d22c480ebcd093297e118 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Thu, 5 Oct 2023 14:33:35 +0300 Subject: [PATCH 005/102] cpython: update test_package --- .../cpython/all/test_package/CMakeLists.txt | 10 +- recipes/cpython/all/test_package/conanfile.py | 281 ++++++------------ recipes/cpython/all/test_package/setup.py | 7 +- 3 files changed, 103 insertions(+), 195 deletions(-) diff --git a/recipes/cpython/all/test_package/CMakeLists.txt b/recipes/cpython/all/test_package/CMakeLists.txt index 502bf95860bce..844120fd54e0c 100644 --- a/recipes/cpython/all/test_package/CMakeLists.txt +++ b/recipes/cpython/all/test_package/CMakeLists.txt @@ -3,10 +3,10 @@ project(test_package C) find_package(cpython REQUIRED CONFIG) -set(CACHE PY_VERSION_MAJOR "" CACHE STRING "MAJOR version of python") -set(CACHE PY_VERSION_MAJOR_MINOR "" CACHE STRING "MAJOR.MINOR version of python") -set(CACHE PY_VERSION "" CACHE STRING "Required version of python") -set(CACHE PY_VERSION_SUFFIX "" CACHE STRING "Suffix of python") +set(PY_VERSION_MAJOR "" CACHE STRING "MAJOR version of python") +set(PY_VERSION_MAJOR_MINOR "" CACHE STRING "MAJOR.MINOR version of python") +set(PY_VERSION "" CACHE STRING "Required version of python") +set(PY_VERSION_SUFFIX "" CACHE STRING "Suffix of python") set(Python_ADDITIONAL_VERSIONS ${PY_VERSION}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR_MINOR}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR}${PY_VERSION_SUFFIX} ${PY_VERSION} ${PY_VERSION_MAJOR_MINOR} ${PY_VERSION_MAJOR}) message("Using Python_ADDITIONAL_VERSIONS: ${Python_ADDITIONAL_VERSIONS}") @@ -72,7 +72,7 @@ if(BUILD_MODULE) endif() option(USE_FINDPYTHON_X "Use new-style FindPythonX module") - if(USE_FINDPYTHON_X AND NOT (CMAKE_VERSION VERSION_LESS "3.16")) + if(USE_FINDPYTHON_X AND NOT CMAKE_VERSION VERSION_LESS "3.16") # Require CMake 3.16 because this version introduces Python${PY_VERSION_MAJOR}_FIND_ABI find_package(Python${PY_VERSION_MAJOR} REQUIRED COMPONENTS Interpreter Development) message("Python${PY_VERSION_MAJOR}_EXECUTABLE: ${Python${PY_VERSION_MAJOR}_EXECUTABLE}") diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index e990896305c6b..675aed8ec29b2 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -1,87 +1,16 @@ -# TODO: verify the Conan v2 migration - -import os -from contextlib import nullcontext - -from conan import ConanFile, conan_version -from conan.errors import ConanInvalidConfiguration, ConanException -from conan.tools.android import android_abi -from conan.tools.apple import ( - XCRun, - fix_apple_shared_install_name, - is_apple_os, - to_apple_arch, -) -from conan.tools.build import ( - build_jobs, - can_run, - check_min_cppstd, - cross_building, - default_cppstd, - stdcpp_library, - valid_min_cppstd, -) -from conan.tools.cmake import ( - CMake, - CMakeDeps, - CMakeToolchain, - cmake_layout, -) -from conan.tools.env import ( - Environment, - VirtualBuildEnv, - VirtualRunEnv, -) -from conan.tools.files import ( - apply_conandata_patches, - chdir, - collect_libs, - copy, - download, - export_conandata_patches, - get, - load, - mkdir, - patch, - patches, - rename, - replace_in_file, - rm, - rmdir, - save, - symlinks, - unzip, -) -from conan.tools.gnu import ( - Autotools, - AutotoolsDeps, - AutotoolsToolchain, - PkgConfig, - PkgConfigDeps, -) -from conan.tools.layout import basic_layout -from conan.tools.meson import MesonToolchain, Meson -from conan.tools.microsoft import ( - MSBuild, - MSBuildDeps, - MSBuildToolchain, - NMakeDeps, - NMakeToolchain, - VCVars, - check_min_vs, - is_msvc, - is_msvc_static_runtime, - msvc_runtime_flag, - unix_path, - unix_path_package_info_legacy, - vs_layout, -) -from conan.tools.scm import Version -from conan.tools.system import package_manager -from io import StringIO import os import re import shutil +from io import StringIO + +from conan import ConanFile +from conan.errors import ConanException +from conan.tools.apple import is_apple_os +from conan.tools.build import cross_building +from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout +from conan.tools.files import mkdir +from conan.tools.microsoft import is_msvc +from conan.tools.scm import Version class CmakePython3Abi(object): @@ -96,9 +25,14 @@ def __init__(self, debug, pymalloc, unicode): @property def suffix(self): - return "{}{}{}".format( - "d" if self.debug else "", "m" if self.pymalloc else "", "u" if self.unicode else "" - ) + suffix = "" + if self.debug: + suffix += "d" + if self.pymalloc: + suffix += "m" + if self.unicode: + suffix += "u" + return suffix @property def cmake_arg(self): @@ -106,11 +40,23 @@ def cmake_arg(self): class TestPackageConan(ConanFile): - settings = "os", "compiler", "build_type", "arch" + settings = "os", "arch", "compiler", "build_type" + generators = "CMakeDeps", "VirtualRunEnv" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + @property + def _python(self): + return self.dependencies["cpython"].conf_info.get("user.cpython:python", check_type=str) @property def _py_version(self): - return re.match(r"^([0-9.]+)", self.dependencies["cpython"].ref.version).group(1) + return re.match(r"^[0-9.]+", str(self.dependencies["cpython"].ref.version)).group(0) @property def _pymalloc(self): @@ -118,18 +64,14 @@ def _pymalloc(self): @property def _cmake_abi(self): - if self._py_version < Version(self, "3.8"): - return CmakePython3Abi( - debug=self.settings.build_type == "Debug", pymalloc=self._pymalloc, unicode=False - ) + if Version(self.dependencies["cpython"].ref.version) < "3.8": + return CmakePython3Abi(debug=self.settings.build_type == "Debug", pymalloc=self._pymalloc, unicode=False) else: return CmakePython3Abi(debug=self.settings.build_type == "Debug", pymalloc=False, unicode=False) @property def _cmake_try_FindPythonX(self): - if is_msvc(self) and self.settings.build_type == "Debug": - return False - return True + return not is_msvc(self) or self.settings.build_type != "Debug" @property def _supports_modules(self): @@ -137,72 +79,59 @@ def _supports_modules(self): def generate(self): tc = CMakeToolchain(self) - py_major = Version(self.dependencies["cpython"]).major - tc.variables["BUILD_MODULE"] = self._supports_modules - tc.variables["PY_VERSION_MAJOR"] = py_major - tc.variables["PY_VERSION_MAJOR_MINOR"] = ".".join(self._py_version.split(".")[:2]) - tc.variables["PY_FULL_VERSION"] = self.dependencies["cpython"].ref.version - tc.variables["PY_VERSION"] = self._py_version - tc.variables["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix - tc.variables["PYTHON_EXECUTABLE"] = self.conf_info.get("user.cpython:python") - tc.variables["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX - tc.variables[f"Python{py_major}_EXECUTABLE"] = self.conf_info.get("user.cpython:python") - tc.variables[f"Python{py_major}_ROOT_DIR"] = self.dependencies["cpython"].package_folder - tc.variables[f"Python{py_major}_USE_STATIC_LIBS"] = not self.dependencies["cpython"].options.shared - tc.variables[f"Python{py_major}_FIND_FRAMEWORK"] = "NEVER" - tc.variables[f"Python{py_major}_FIND_REGISTRY"] = "NEVER" - tc.variables[f"Python{py_major}_FIND_IMPLEMENTATIONS"] = "CPython" - tc.variables[f"Python{py_major}_FIND_STRATEGY"] = "LOCATION" - - if not is_msvc(self): - if Version(self._py_version) < Version(self, "3.8"): - tc.variables["Python{}_FIND_ABI".format(py_major)] = self._cmake_abi.cmake_arg + version = Version(self.dependencies["cpython"].ref.version) + py_major = str(version.major) + tc.cache_variables["BUILD_MODULE"] = self._supports_modules + tc.cache_variables["PY_VERSION_MAJOR"] = py_major + tc.cache_variables["PY_VERSION_MAJOR_MINOR"] = f"{version.major}.{version.minor}" + tc.cache_variables["PY_FULL_VERSION"] = str(version) + tc.cache_variables["PY_VERSION"] = self._py_version + tc.cache_variables["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix + tc.cache_variables["PYTHON_EXECUTABLE"] = self._python + tc.cache_variables["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX + tc.cache_variables[f"Python{py_major}_EXECUTABLE"] = self._python + tc.cache_variables[f"Python{py_major}_ROOT_DIR"] = self.dependencies["cpython"].package_folder + tc.cache_variables[f"Python{py_major}_USE_STATIC_LIBS"] = not self.dependencies["cpython"].options.shared + tc.cache_variables[f"Python{py_major}_FIND_FRAMEWORK"] = "NEVER" + tc.cache_variables[f"Python{py_major}_FIND_REGISTRY"] = "NEVER" + tc.cache_variables[f"Python{py_major}_FIND_IMPLEMENTATIONS"] = "CPython" + tc.cache_variables[f"Python{py_major}_FIND_STRATEGY"] = "LOCATION" + if not is_msvc(self) and self._py_version < "3.8": + tc.cache_variables[f"Python{py_major}_FIND_ABI"] = self._cmake_abi.cmake_arg + tc.generate() if not cross_building(self, skip_x64_x86=True): if self._supports_modules: - with vcvars(self.settings) if is_msvc(self) else nullcontext(): - modsrcfolder = ( - "py2" if Version(self.dependencies["cpython"].ref.version).major < "3" else "py3" - ) - mkdir(self, os.path.join(self.build_folder, modsrcfolder)) - for fn in os.listdir(os.path.join(self.source_folder, modsrcfolder)): - shutil.copy( - os.path.join(self.source_folder, modsrcfolder, fn), - os.path.join(self.build_folder, modsrcfolder, fn), - ) + modsrcfolder = "py2" if version.major == 2 else "py3" + mkdir(self, os.path.join(self.build_folder, modsrcfolder)) + for fn in os.listdir(os.path.join(self.source_folder, modsrcfolder)): shutil.copy( - os.path.join(self.source_folder, "setup.py"), - os.path.join(self.build_folder, "setup.py"), + os.path.join(self.source_folder, modsrcfolder, fn), + os.path.join(self.build_folder, modsrcfolder, fn), ) - env = { - "DISTUTILS_USE_SDK": "1", - "MSSdk": "1", - } - env.update(**AutoToolsBuildEnvironment(self).vars) - with environment_append(self, env): - setup_args = [ - "{}/setup.py".format(self.source_folder), - # "conan", - # "--install-folder", self.build_folder, - "build", - "--build-base", - self.build_folder, - "--build-platlib", - os.path.join(self.build_folder, "lib_setuptools"), - ] - if self.settings.build_type == "Debug": - setup_args.append("--debug") - self.run( - "{} {}".format( - self.conf_info.get("user.cpython:python"), - " ".join('"{}"'.format(a) for a in setup_args), - ), - ) + shutil.copy( + os.path.join(self.source_folder, "setup.py"), + os.path.join(self.build_folder, "setup.py"), + ) + os.environ["DISTUTILS_USE_SDK"] = "1" + os.environ["MSSdk"] = "1" + setup_args = [ + f"{self.source_folder}/setup.py", + # "conan", + # "--install-folder", self.build_folder, + "build", + "--build-base", self.build_folder, + "--build-platlib", os.path.join(self.build_folder, "lib_setuptools"), + ] + if self.settings.build_type == "Debug": + setup_args.append("--debug") + python = self.dependencies["cpython"].conf_info.get("user.cpython:python", check_type=str) + args = " ".join(f'"{a}"' for a in setup_args) + self.run(f"{python} {args}") def build(self): if not cross_building(self, skip_x64_x86=True): - python_executable = self.conf_info.get("user.cpython:python") - command = f"{python_executable} --version" + command = f"{self._python} --version" buffer = StringIO() self.run(command, stdout=buffer, ignore_errors=True) self.output.info(f"output: {buffer.getvalue()}") @@ -214,12 +143,7 @@ def build(self): def _test_module(self, module, should_work): try: - self.run( - "{} {}/test_package.py -b {} -t {} ".format( - self.conf_info.get("user.cpython:python"), self.source_folder, self.build_folder, module - ), - run_environment=True, - ) + self.run(f"{self._python} {self.source_folder}/test_package.py -b {self.build_folder} -t {module}") works = True except ConanException as e: works = False @@ -234,31 +158,19 @@ def _test_module(self, module, should_work): raise exception def _cpython_option(self, name): - try: - return self.dependencies["cpython"].options.get_safe(name, False) - except ConanException: - return False + return self.dependencies["cpython"].options.get_safe(name, False) def test(self): if not cross_building(self, skip_x64_x86=True): - self.run( - "{} -c \"print('hello world')\"".format(self.conf_info.get("user.cpython:python")), - ) + self.run(f"{self._python} -c \"print('hello world')\"") buffer = StringIO() - self.run( - "{} -c \"import sys; print('.'.join(str(s) for s in sys.version_info[:3]))\"".format( - self.conf_info.get("user.cpython:python") - ), - stdout=buffer, - ) + self.run(f"{self._python} -c \"import sys; print('.'.join(str(s) for s in sys.version_info[:3]))\"", buffer) self.output.info(buffer.getvalue()) version_detected = buffer.getvalue().splitlines()[-1].strip() if self._py_version != version_detected: raise ConanException( - "python reported wrong version. Expected {exp}. Got {res}.".format( - exp=self._py_version, res=version_detected - ) + f"python reported wrong version. Expected {self._py_version}. Got {version_detected}." ) if self._supports_modules: @@ -283,20 +195,15 @@ def test(self): # FIXME: find out why cpython on apple does not allow to use modules linked against a static python else: if self._supports_modules: - with environment_append(self, {"PYTHONPATH": [os.path.join(self.build_folder, "lib")]}): - self.output.info("Testing module (spam) using cmake built module") - self._test_module("spam", True) + os.environ["PYTHONPATH"] = os.path.join(self.build_folder, "lib") + self.output.info("Testing module (spam) using cmake built module") + self._test_module("spam", True) - with environment_append( - self, {"PYTHONPATH": [os.path.join(self.build_folder, "lib_setuptools")]} - ): - self.output.info("Testing module (spam) using setup.py built module") - self._test_module("spam", True) + os.environ["PYTHONPATH"] = os.path.join(self.build_folder, "lib_setuptools") + self.output.info("Testing module (spam) using setup.py built module") + self._test_module("spam", True) # MSVC builds need PYTHONHOME set. - with ( - environment_append(self, {"PYTHONHOME": self.conf_info.get("user.cpython:pythonhome")}) - if self.conf_info.get("user.cpython:module_requires_pythonhome") == "True" - else nullcontext() - ): - self.run(os.path.join("bin", "test_package"), run_environment=True) + if self.dependencies["cpython"].conf_info.get("user.cpython:module_requires_pythonhome", check_type=bool): + os.environ["PYTHONHOME"] = self.dependencies["cpython"].conf_info.get("user.cpython:pythonhome", check_type=str) + self.run(os.path.join(self.cpp.build.bindir, "test_package"), env="conanrun") diff --git a/recipes/cpython/all/test_package/setup.py b/recipes/cpython/all/test_package/setup.py index cd1754cef8131..70f6e8f6961db 100644 --- a/recipes/cpython/all/test_package/setup.py +++ b/recipes/cpython/all/test_package/setup.py @@ -8,8 +8,8 @@ if os.path.isdir(directory): os.add_dll_directory(directory) -PY2 = (2, 0) <= sys.version_info < (3, 0) -PY3 = (3, 0) <= sys.version_info < (4, 0) +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 if PY2: subdir = "py2" @@ -20,12 +20,13 @@ else: raise Exception +script_dir = os.path.dirname(os.path.realpath(__file__)) setup( name="test_package", version="1.0", use_2to3=True, ext_modules=[ - Extension("spam", [os.path.join(subdir, "test_module.c")]), + Extension("spam", [os.path.join(script_dir, subdir, "test_module.c")]), ], ) From 522d5d94621698534f86691c8ec44c2c28e8b2d6 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Thu, 5 Oct 2023 14:54:05 +0300 Subject: [PATCH 006/102] cpython: temporarily disable FindPythonX tests --- recipes/cpython/all/test_package/conanfile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 675aed8ec29b2..1a8fbafcdd72f 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -71,7 +71,9 @@ def _cmake_abi(self): @property def _cmake_try_FindPythonX(self): - return not is_msvc(self) or self.settings.build_type != "Debug" + # FIXME: re-enable + # return not is_msvc(self) or self.settings.build_type != "Debug" + return False @property def _supports_modules(self): From 9c83e18c116b770df8104eb5e9861c9c73425fcc Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Fri, 6 Oct 2023 11:38:31 +0300 Subject: [PATCH 007/102] cpython: package_type should be "library" --- recipes/cpython/all/conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index b32b096193549..c76a7adfd3e46 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -24,7 +24,7 @@ class CPythonConan(ConanFile): homepage = "https://www.python.org" topics = ("python", "cpython", "language", "script") - package_type = "application" + package_type = "library" settings = "os", "arch", "compiler", "build_type" options = { "shared": [True, False], From 6c496e68782eca1d6ecd9b5da957685f64cbc297 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Fri, 6 Oct 2023 11:39:10 +0300 Subject: [PATCH 008/102] cpython: tidy --- recipes/cpython/all/test_package/conanfile.py | 19 ++++++++---------- .../cpython/all/test_package/test_package.py | 20 ++++++++++--------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 1a8fbafcdd72f..892e32ccdbb6b 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -146,18 +146,15 @@ def build(self): def _test_module(self, module, should_work): try: self.run(f"{self._python} {self.source_folder}/test_package.py -b {self.build_folder} -t {module}") - works = True - except ConanException as e: - works = False - exception = e - if should_work == works: - self.output.info("Result of test was expected.") - else: - if works: - raise ConanException(f"Module '{module}' works, but should not have worked") - else: + except ConanException: + if should_work: self.output.warning(f"Module '{module}' does not work, but should have worked") - raise exception + raise + self.output.info("Module failed as expected") + return + if not should_work: + raise ConanException(f"Module '{module}' works, but should not have worked") + self.output.info("Module worked as expected") def _cpython_option(self, name): return self.dependencies["cpython"].options.get_safe(name, False) diff --git a/recipes/cpython/all/test_package/test_package.py b/recipes/cpython/all/test_package/test_package.py index aad4eb9c6cc9a..da3ebc3887585 100644 --- a/recipes/cpython/all/test_package/test_package.py +++ b/recipes/cpython/all/test_package/test_package.py @@ -17,7 +17,7 @@ def add_test(fn): name = fn.__name__[fn.__name__.find("_") + 1 :] def inner_fn(): - print("testing {}".format(name)) + print(f"testing {name}") sys.stdout.flush() fn() @@ -49,7 +49,9 @@ def char_data(data): """ Text goes here More text - """, 1) + """, + 1, + ) @add_test @@ -88,7 +90,7 @@ def test_spam(): raise Exception("spam.__doc__ does not contain the expected text") cmd = {"Windows": "dir"}.get(platform.system(), "ls") - print('About to run spam.system("{}")'.format(cmd)) + print(f'About to run spam.system("{cmd}")') sys.stdout.flush() spam.system(cmd) @@ -116,9 +118,9 @@ def test_bsddb(): if len(db) != 2: raise Exception("Wrong length") if db["key1"] != "value1": - raise Exception("value1 incorrect {}".format(db["key1"])) + raise Exception(f"value1 incorrect {db['key1']}") if db["key2"] != "value2": - raise Exception("value2 incorrect {}".format(db["key2"])) + raise Exception(f"value2 incorrect {db['key2']}") @add_test @@ -181,7 +183,7 @@ def test_decimal(): def test_curses(): import _curses - print("Using _curses version {}".format(_curses.version)) + print(f"Using _curses version {_curses.version}") @add_test @@ -189,15 +191,15 @@ def test_ctypes(): import _ctypes errno = _ctypes.get_errno() - print("errno={}".format(errno)) + print(f"errno={errno}") @add_test def test_tkinter(): import _tkinter - print("tcl version: {}".format(_tkinter.TCL_VERSION)) - print("tk version: {}".format(_tkinter.TK_VERSION)) + print(f"tcl version: {_tkinter.TCL_VERSION}") + print(f"tk version: {_tkinter.TK_VERSION}") def main(): From 35fac91f55633cb2e1e2016c4031db5fc0f02ae4 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Fri, 6 Oct 2023 11:39:49 +0300 Subject: [PATCH 009/102] cpython: ncurses is required transitively --- recipes/cpython/all/conanfile.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index c76a7adfd3e46..4acfadcb56981 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -163,7 +163,9 @@ def requirements(self): if self.options.get_safe("with_tkinter"): self.requires("tk/8.6.10") if self.options.get_safe("with_curses", False): - self.requires("ncurses/6.4") + # Used in a public header + # https://github.com/python/cpython/blob/v3.10.13/Include/py_curses.h#L34 + self.requires("ncurses/6.4", transitive_headers=True, transitive_libs=True) if self.options.get_safe("with_bsddb", False): self.requires("libdb/5.3.28") if self.options.get_safe("with_lzma", False): From ec99e2eb4996b2e87808e43cb628d0a013adc02e Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Fri, 6 Oct 2023 12:02:58 +0300 Subject: [PATCH 010/102] cpython: fix shared test --- recipes/cpython/all/test_package/conanfile.py | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 892e32ccdbb6b..574726e055174 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -8,6 +8,7 @@ from conan.tools.apple import is_apple_os from conan.tools.build import cross_building from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout +from conan.tools.env import VirtualRunEnv from conan.tools.files import mkdir from conan.tools.microsoft import is_msvc from conan.tools.scm import Version @@ -41,7 +42,7 @@ def cmake_arg(self): class TestPackageConan(ConanFile): settings = "os", "arch", "compiler", "build_type" - generators = "CMakeDeps", "VirtualRunEnv" + generators = "CMakeDeps" test_type = "explicit" def requirements(self): @@ -55,16 +56,20 @@ def _python(self): return self.dependencies["cpython"].conf_info.get("user.cpython:python", check_type=str) @property - def _py_version(self): + def _clean_py_version(self): return re.match(r"^[0-9.]+", str(self.dependencies["cpython"].ref.version)).group(0) + @property + def _py_version(self): + return Version(self.dependencies["cpython"].ref.version) + @property def _pymalloc(self): return bool(self.dependencies["cpython"].options.get_safe("pymalloc", False)) @property def _cmake_abi(self): - if Version(self.dependencies["cpython"].ref.version) < "3.8": + if self._py_version < "3.8": return CmakePython3Abi(debug=self.settings.build_type == "Debug", pymalloc=self._pymalloc, unicode=False) else: return CmakePython3Abi(debug=self.settings.build_type == "Debug", pymalloc=False, unicode=False) @@ -81,13 +86,13 @@ def _supports_modules(self): def generate(self): tc = CMakeToolchain(self) - version = Version(self.dependencies["cpython"].ref.version) + version = self._py_version py_major = str(version.major) tc.cache_variables["BUILD_MODULE"] = self._supports_modules tc.cache_variables["PY_VERSION_MAJOR"] = py_major tc.cache_variables["PY_VERSION_MAJOR_MINOR"] = f"{version.major}.{version.minor}" tc.cache_variables["PY_FULL_VERSION"] = str(version) - tc.cache_variables["PY_VERSION"] = self._py_version + tc.cache_variables["PY_VERSION"] = self._clean_py_version tc.cache_variables["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix tc.cache_variables["PYTHON_EXECUTABLE"] = self._python tc.cache_variables["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX @@ -98,13 +103,28 @@ def generate(self): tc.cache_variables[f"Python{py_major}_FIND_REGISTRY"] = "NEVER" tc.cache_variables[f"Python{py_major}_FIND_IMPLEMENTATIONS"] = "CPython" tc.cache_variables[f"Python{py_major}_FIND_STRATEGY"] = "LOCATION" - if not is_msvc(self) and self._py_version < "3.8": + if not is_msvc(self) and self._clean_py_version < "3.8": tc.cache_variables[f"Python{py_major}_FIND_ABI"] = self._cmake_abi.cmake_arg tc.generate() + VirtualRunEnv(self).generate(scope="run") + VirtualRunEnv(self).generate(scope="build") + + def build(self): + if not cross_building(self, skip_x64_x86=True): + command = f"{self._python} --version" + buffer = StringIO() + self.run(command, stdout=buffer, ignore_errors=True) + self.output.info(f"output: {buffer.getvalue()}") + self.run(command) + + cmake = CMake(self) + cmake.configure() + cmake.build() + if not cross_building(self, skip_x64_x86=True): if self._supports_modules: - modsrcfolder = "py2" if version.major == 2 else "py3" + modsrcfolder = "py2" if self._py_version.major == 2 else "py3" mkdir(self, os.path.join(self.build_folder, modsrcfolder)) for fn in os.listdir(os.path.join(self.source_folder, modsrcfolder)): shutil.copy( @@ -127,21 +147,8 @@ def generate(self): ] if self.settings.build_type == "Debug": setup_args.append("--debug") - python = self.dependencies["cpython"].conf_info.get("user.cpython:python", check_type=str) args = " ".join(f'"{a}"' for a in setup_args) - self.run(f"{python} {args}") - - def build(self): - if not cross_building(self, skip_x64_x86=True): - command = f"{self._python} --version" - buffer = StringIO() - self.run(command, stdout=buffer, ignore_errors=True) - self.output.info(f"output: {buffer.getvalue()}") - self.run(command) - - cmake = CMake(self) - cmake.configure() - cmake.build() + self.run(f"{self._python} {args}") def _test_module(self, module, should_work): try: @@ -167,9 +174,9 @@ def test(self): self.run(f"{self._python} -c \"import sys; print('.'.join(str(s) for s in sys.version_info[:3]))\"", buffer) self.output.info(buffer.getvalue()) version_detected = buffer.getvalue().splitlines()[-1].strip() - if self._py_version != version_detected: + if self._clean_py_version != version_detected: raise ConanException( - f"python reported wrong version. Expected {self._py_version}. Got {version_detected}." + f"python reported wrong version. Expected {self._clean_py_version}. Got {version_detected}." ) if self._supports_modules: From 220c4722b47f3f45a1aae4066a5a82e7af755ece Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Mon, 13 Nov 2023 09:08:05 +0200 Subject: [PATCH 011/102] cpython: use cpp_info.aggregated_components() for deps --- recipes/cpython/all/conanfile.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 4acfadcb56981..7e227b9fe2051 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -250,9 +250,10 @@ def _generate_autotools(self): tcltk_libs = [] # FIXME: collect using some conan util (https://github.com/conan-io/conan/issues/7656) for dep in ("tcl", "tk", "zlib"): - tcltk_includes += [f"-I{d}" for d in self.dependencies[dep].cpp_info.includedirs] - tcltk_libs += [f"-L{lib}" for lib in self.dependencies[dep].cpp_info.libdirs] - tcltk_libs += [f"-l{lib}" for lib in self.dependencies[dep].cpp_info.libs] + cpp_info = self.dependencies[dep].cpp_info.aggregated_components() + tcltk_includes += [f"-I{d}" for d in cpp_info.includedirs] + tcltk_libs += [f"-L{lib}" for lib in cpp_info.libdirs] + tcltk_libs += [f"-l{lib}" for lib in cpp_info.libs] if self.settings.os in ["Linux", "FreeBSD"] and not self.dependencies["tk"].options.shared: # FIXME: use info from xorg.components (x11, xscrnsaver) tcltk_libs.extend([f"-l{lib}" for lib in ("X11", "Xss")]) @@ -312,7 +313,7 @@ def _patch_sources(self): if self.options.get_safe("with_curses", False): # FIXME: this will link to ALL libraries of ncurses. Only need to link to ncurses(w) (+ eventually tinfo) - ncurses_info = self.dependencies["ncurses"].cpp_info + ncurses_info = self.dependencies["ncurses"].cpp_info.aggregated_components() replace_in_file(self, os.path.join(self.source_folder, "setup.py"), "curses_libs = ", "curses_libs = {} #".format(repr(ncurses_info.libs + ncurses_info.system_libs))) From 2e54e117b054c802c2bf925187f566e744b0e288 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Mon, 13 Nov 2023 09:21:31 +0200 Subject: [PATCH 012/102] cpython: bsddb has been remove in Python 3 --- recipes/cpython/all/conanfile.py | 9 +++------ recipes/cpython/all/test_package/conanfile.py | 3 ++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 7e227b9fe2051..296d2c97354b8 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -575,12 +575,9 @@ def _msvc_package_copy(self): unzip(self, filename=os.path.join(whldir, fname), destination=os.path.join(self.package_folder, "bin", "Lib", "site-packages")) - self.run( - "{} -c \"import compileall; compileall.compile_dir('{}')\"".format( - os.path.join(build_path, self._cpython_interpreter_name), - os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib").replace("\\", "/"), - ) - ) + interpreter_path = os.path.join(build_path, self._cpython_interpreter_name) + lib_dir_path = os.path.join(self.package_folder, self._msvc_install_subprefix, "Lib").replace("\\", "/") + self.run(f"{interpreter_path} -c \"import compileall; compileall.compile_dir('{lib_dir_path}')\"") def package(self): copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 574726e055174..fb247da886640 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -182,7 +182,8 @@ def test(self): if self._supports_modules: self._test_module("gdbm", self._cpython_option("with_gdbm")) self._test_module("bz2", self._cpython_option("with_bz2")) - self._test_module("bsddb", self._cpython_option("with_bsddb")) + if self._py_version.major < 3: + self._test_module("bsddb", self._cpython_option("with_bsddb")) self._test_module("lzma", self._cpython_option("with_lzma")) self._test_module("tkinter", self._cpython_option("with_tkinter")) os.environ["TERM"] = "ansi" From 51a3e1133018307db352bb694b8c60ac599a6d02 Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Mon, 13 Nov 2023 10:02:40 +0200 Subject: [PATCH 013/102] cpython: fix openssl support --- recipes/cpython/all/conanfile.py | 13 +++++++++++++ recipes/cpython/all/test_package/conanfile.py | 1 + recipes/cpython/all/test_package/test_package.py | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 296d2c97354b8..b05db11d574ae 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -318,6 +318,19 @@ def _patch_sources(self): "curses_libs = ", "curses_libs = {} #".format(repr(ncurses_info.libs + ncurses_info.system_libs))) + if self._supports_modules: + openssl = self.dependencies["openssl"].cpp_info.aggregated_components() + zlib = self.dependencies["zlib"].cpp_info.aggregated_components() + replace_in_file(self, os.path.join(self.source_folder, "setup.py"), + "openssl_includes = ", + f"openssl_includes = {openssl.includedirs + zlib.includedirs} #") + replace_in_file(self, os.path.join(self.source_folder, "setup.py"), + "openssl_libdirs = ", + f"openssl_libdirs = {openssl.libdirs + zlib.libdirs} #") + replace_in_file(self, os.path.join(self.source_folder, "setup.py"), + "openssl_libs = ", + f"openssl_libs = {openssl.libs + zlib.libs} #") + # Enable static MSVC cpython if not self.options.shared: replace_in_file(self, os.path.join(self.source_folder, "PCbuild", "pythoncore.vcxproj"), diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index fb247da886640..f48857c4fb12e 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -193,6 +193,7 @@ def test(self): self._test_module("sqlite3", True) self._test_module("decimal", True) self._test_module("ctypes", True) + self._test_module("ssl", True) if is_apple_os(self) and not self.dependencies["cpython"].options.shared: self.output.info( diff --git a/recipes/cpython/all/test_package/test_package.py b/recipes/cpython/all/test_package/test_package.py index da3ebc3887585..870e11b340eb1 100644 --- a/recipes/cpython/all/test_package/test_package.py +++ b/recipes/cpython/all/test_package/test_package.py @@ -202,6 +202,14 @@ def test_tkinter(): print(f"tk version: {_tkinter.TK_VERSION}") +@add_test +def test_ssl(): + import ssl + + default_context = ssl.create_default_context() + print(f"default_context.options={default_context.options}") + + def main(): parser = argparse.ArgumentParser() parser.add_argument("-b", dest="build_folder", help="build_folder", required=True) From 3cc7f612fca5d89dca926e0db2928743f59098d9 Mon Sep 17 00:00:00 2001 From: Ahajha Date: Wed, 22 Nov 2023 23:54:49 -0500 Subject: [PATCH 014/102] Fix package layout --- recipes/cpython/all/conanfile.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index b05db11d574ae..cb87e287168ab 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -221,6 +221,17 @@ def source(self): def _generate_autotools(self): tc = AutotoolsToolchain(self) + # TODO it's possible not all of these are needed + tc.update_configure_args({ + "--prefix": f"{self.package_folder}", + "--bindir": "${prefix}/bin", + "--sbindir": "${prefix}/bin", + "--libexecdir": "${prefix}/bin", + "--libdir": "${prefix}/lib", + "--includedir": "${prefix}/include", + "--oldincludedir": "${prefix}/include", + "--datarootdir": "${prefix}/share", + }) yes_no = lambda v: "yes" if v else "no" tc.configure_args += [ "--with-doc-strings={}".format(yes_no(self.options.docstrings)), @@ -230,6 +241,7 @@ def _generate_autotools(self): "--enable-optimizations={}".format(yes_no(self.options.optimizations)), "--with-lto={}".format(yes_no(self.options.lto)), "--with-pydebug={}".format(yes_no(self.settings.build_type == "Debug")), + "--disable-test-modules", ] if self._is_py2: tc.configure_args += ["--enable-unicode={}".format(yes_no(self.options.unicode))] From 1840f62327067a206cd4a10f3976d2797fda1f5c Mon Sep 17 00:00:00 2001 From: Ahajha Date: Fri, 24 Nov 2023 22:52:15 -0500 Subject: [PATCH 015/102] Fix new generators in test package --- recipes/cpython/all/test_package/CMakeLists.txt | 2 +- recipes/cpython/all/test_package/conanfile.py | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/recipes/cpython/all/test_package/CMakeLists.txt b/recipes/cpython/all/test_package/CMakeLists.txt index 844120fd54e0c..974fec1ae3a51 100644 --- a/recipes/cpython/all/test_package/CMakeLists.txt +++ b/recipes/cpython/all/test_package/CMakeLists.txt @@ -96,4 +96,4 @@ if(BUILD_MODULE) endif() add_executable(${PROJECT_NAME} "py${PY_VERSION_MAJOR}/test_package.c") -target_link_libraries(${PROJECT_NAME} PRIVATE cpython::cpython) +target_link_libraries(${PROJECT_NAME} PRIVATE cpython::embed) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index f48857c4fb12e..ed73e8e6e64b0 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -8,7 +8,6 @@ from conan.tools.apple import is_apple_os from conan.tools.build import cross_building from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout -from conan.tools.env import VirtualRunEnv from conan.tools.files import mkdir from conan.tools.microsoft import is_msvc from conan.tools.scm import Version @@ -42,7 +41,7 @@ def cmake_arg(self): class TestPackageConan(ConanFile): settings = "os", "arch", "compiler", "build_type" - generators = "CMakeDeps" + generators = "CMakeDeps", "VirtualRunEnv", "VCVars" # TODO test MSVC, is VCVars necessary? test_type = "explicit" def requirements(self): @@ -76,9 +75,7 @@ def _cmake_abi(self): @property def _cmake_try_FindPythonX(self): - # FIXME: re-enable - # return not is_msvc(self) or self.settings.build_type != "Debug" - return False + return not is_msvc(self) or self.settings.build_type != "Debug" @property def _supports_modules(self): @@ -103,7 +100,7 @@ def generate(self): tc.cache_variables[f"Python{py_major}_FIND_REGISTRY"] = "NEVER" tc.cache_variables[f"Python{py_major}_FIND_IMPLEMENTATIONS"] = "CPython" tc.cache_variables[f"Python{py_major}_FIND_STRATEGY"] = "LOCATION" - if not is_msvc(self) and self._clean_py_version < "3.8": + if not is_msvc(self) and self._py_version < "3.8": tc.cache_variables[f"Python{py_major}_FIND_ABI"] = self._cmake_abi.cmake_arg tc.generate() @@ -190,7 +187,7 @@ def test(self): self._test_module("curses", self._cpython_option("with_curses")) self._test_module("expat", True) - self._test_module("sqlite3", True) + self._test_module("sqlite3", self._cpython_option("with_sqlite3")) self._test_module("decimal", True) self._test_module("ctypes", True) self._test_module("ssl", True) @@ -203,7 +200,7 @@ def test(self): # FIXME: find out why cpython on apple does not allow to use modules linked against a static python else: if self._supports_modules: - os.environ["PYTHONPATH"] = os.path.join(self.build_folder, "lib") + os.environ["PYTHONPATH"] = self.build_folder self.output.info("Testing module (spam) using cmake built module") self._test_module("spam", True) @@ -214,4 +211,5 @@ def test(self): # MSVC builds need PYTHONHOME set. if self.dependencies["cpython"].conf_info.get("user.cpython:module_requires_pythonhome", check_type=bool): os.environ["PYTHONHOME"] = self.dependencies["cpython"].conf_info.get("user.cpython:pythonhome", check_type=str) - self.run(os.path.join(self.cpp.build.bindir, "test_package"), env="conanrun") + bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package") + self.run(bin_path, run_environment=True) From d0bcea794e1a62f6c3cb3f9b6c165cfadffc4a2c Mon Sep 17 00:00:00 2001 From: Ahajha Date: Fri, 24 Nov 2023 23:01:38 -0500 Subject: [PATCH 016/102] Misc fixes --- recipes/cpython/all/test_package/conanfile.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index ed73e8e6e64b0..7d3922cfaeea3 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -41,7 +41,7 @@ def cmake_arg(self): class TestPackageConan(ConanFile): settings = "os", "arch", "compiler", "build_type" - generators = "CMakeDeps", "VirtualRunEnv", "VCVars" # TODO test MSVC, is VCVars necessary? + generators = "CMakeDeps", "VirtualRunEnv" test_type = "explicit" def requirements(self): @@ -56,7 +56,7 @@ def _python(self): @property def _clean_py_version(self): - return re.match(r"^[0-9.]+", str(self.dependencies["cpython"].ref.version)).group(0) + return str(self._py_version) @property def _py_version(self): @@ -104,8 +104,6 @@ def generate(self): tc.cache_variables[f"Python{py_major}_FIND_ABI"] = self._cmake_abi.cmake_arg tc.generate() - VirtualRunEnv(self).generate(scope="run") - VirtualRunEnv(self).generate(scope="build") def build(self): if not cross_building(self, skip_x64_x86=True): @@ -212,4 +210,4 @@ def test(self): if self.dependencies["cpython"].conf_info.get("user.cpython:module_requires_pythonhome", check_type=bool): os.environ["PYTHONHOME"] = self.dependencies["cpython"].conf_info.get("user.cpython:pythonhome", check_type=str) bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package") - self.run(bin_path, run_environment=True) + self.run(bin_path) From f0797ef8619d5830a56e92560cb2acb46f7f2b59 Mon Sep 17 00:00:00 2001 From: Ahajha Date: Fri, 24 Nov 2023 23:03:03 -0500 Subject: [PATCH 017/102] Remove redundant test --- recipes/cpython/all/test_package/conanfile.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 7d3922cfaeea3..0c4914ada7cb3 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -106,13 +106,6 @@ def generate(self): def build(self): - if not cross_building(self, skip_x64_x86=True): - command = f"{self._python} --version" - buffer = StringIO() - self.run(command, stdout=buffer, ignore_errors=True) - self.output.info(f"output: {buffer.getvalue()}") - self.run(command) - cmake = CMake(self) cmake.configure() cmake.build() From c7663345b0bb06fd0617149b0a002cefe9d11a8e Mon Sep 17 00:00:00 2001 From: Ahajha Date: Fri, 24 Nov 2023 23:03:18 -0500 Subject: [PATCH 018/102] Add FIXMEs --- recipes/cpython/all/test_package/conanfile.py | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 0c4914ada7cb3..d7c961cd3e0eb 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -52,6 +52,8 @@ def layout(self): @property def _python(self): + #return self.deps_user_info["cpython"].python + # FIXME return self.dependencies["cpython"].conf_info.get("user.cpython:python", check_type=str) @property @@ -60,10 +62,14 @@ def _clean_py_version(self): @property def _py_version(self): + #return Version(self.deps_cpp_info["cpython"].version) + # FIXME return Version(self.dependencies["cpython"].ref.version) @property def _pymalloc(self): + #return bool("pymalloc" in self.options["cpython"] and self.options["cpython"].pymalloc) + # FIXME return bool(self.dependencies["cpython"].options.get_safe("pymalloc", False)) @property @@ -152,10 +158,22 @@ def _test_module(self, module, should_work): self.output.info("Module worked as expected") def _cpython_option(self, name): + #try: + # return getattr(self.options["cpython"], name, False) + #except ConanException: + # return False + # FIXME return self.dependencies["cpython"].options.get_safe(name, False) def test(self): if not cross_building(self, skip_x64_x86=True): + # FIXME + #command = f"{self._python} --version" + #buffer = StringIO() + #self.run(command, stdout=buffer, ignore_errors=True) + #self.output.info(f"output: {buffer.getvalue()}") + #self.run(command) + self.run(f"{self._python} -c \"print('hello world')\"") buffer = StringIO() @@ -181,7 +199,7 @@ def test(self): self._test_module("sqlite3", self._cpython_option("with_sqlite3")) self._test_module("decimal", True) self._test_module("ctypes", True) - self._test_module("ssl", True) + #self._test_module("ssl", True) # FIXME if is_apple_os(self) and not self.dependencies["cpython"].options.shared: self.output.info( @@ -200,7 +218,10 @@ def test(self): self._test_module("spam", True) # MSVC builds need PYTHONHOME set. + # FIXME if self.dependencies["cpython"].conf_info.get("user.cpython:module_requires_pythonhome", check_type=bool): os.environ["PYTHONHOME"] = self.dependencies["cpython"].conf_info.get("user.cpython:pythonhome", check_type=str) + #if self.deps_user_info["cpython"].module_requires_pythonhome == "True": + # os.environ["PYTHONHOME"] = self.deps_user_info["cpython"].pythonhome bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package") self.run(bin_path) From 6a1ebd91f4fa3a9252900cc8efd0448036646a15 Mon Sep 17 00:00:00 2001 From: Ahajha Date: Sat, 25 Nov 2023 15:59:06 -0500 Subject: [PATCH 019/102] Fix running test package multiple times in a row --- recipes/cpython/all/test_package/test_package.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/recipes/cpython/all/test_package/test_package.py b/recipes/cpython/all/test_package/test_package.py index 870e11b340eb1..5944ed43ad7af 100644 --- a/recipes/cpython/all/test_package/test_package.py +++ b/recipes/cpython/all/test_package/test_package.py @@ -164,6 +164,8 @@ def test_sqlite3(): raise Exception("Need 4 stocks") print(data) conn.close() + # Remove the file so subsequent tests don't fail + os.remove("sqlite3.db") @add_test From 15393323efd9132fa6f6ec7e4b0293c82b6a2be6 Mon Sep 17 00:00:00 2001 From: Ahajha Date: Sat, 25 Nov 2023 16:01:58 -0500 Subject: [PATCH 020/102] Handle conan 1/2 differences in test_package --- recipes/cpython/all/test_package/conanfile.py | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index d7c961cd3e0eb..121dd77c9c450 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -1,9 +1,8 @@ import os -import re import shutil from io import StringIO -from conan import ConanFile +from conan import ConanFile, __version__ as conan_version from conan.errors import ConanException from conan.tools.apple import is_apple_os from conan.tools.build import cross_building @@ -12,6 +11,7 @@ from conan.tools.microsoft import is_msvc from conan.tools.scm import Version +conan2 = conan_version >= Version("2.0.0") class CmakePython3Abi(object): def __init__(self, debug, pymalloc, unicode): @@ -52,9 +52,10 @@ def layout(self): @property def _python(self): - #return self.deps_user_info["cpython"].python - # FIXME - return self.dependencies["cpython"].conf_info.get("user.cpython:python", check_type=str) + if conan2: + return self.dependencies["cpython"].conf_info.get("user.cpython:python", check_type=str) + else: + return self.deps_user_info["cpython"].python @property def _clean_py_version(self): @@ -62,15 +63,17 @@ def _clean_py_version(self): @property def _py_version(self): - #return Version(self.deps_cpp_info["cpython"].version) - # FIXME - return Version(self.dependencies["cpython"].ref.version) + if conan2: + return Version(self.dependencies["cpython"].ref.version) + else: + return Version(self.deps_cpp_info["cpython"].version) @property def _pymalloc(self): - #return bool("pymalloc" in self.options["cpython"] and self.options["cpython"].pymalloc) - # FIXME - return bool(self.dependencies["cpython"].options.get_safe("pymalloc", False)) + if conan2: + return bool(self.dependencies["cpython"].options.get_safe("pymalloc", False)) + else: + return bool("pymalloc" in self.options["cpython"] and self.options["cpython"].pymalloc) @property def _cmake_abi(self): @@ -158,21 +161,17 @@ def _test_module(self, module, should_work): self.output.info("Module worked as expected") def _cpython_option(self, name): - #try: - # return getattr(self.options["cpython"], name, False) - #except ConanException: - # return False - # FIXME - return self.dependencies["cpython"].options.get_safe(name, False) + if conan2: + return self.dependencies["cpython"].options.get_safe(name, False) + else: + try: + return getattr(self.options["cpython"], name, False) + except ConanException: + return False def test(self): if not cross_building(self, skip_x64_x86=True): - # FIXME - #command = f"{self._python} --version" - #buffer = StringIO() - #self.run(command, stdout=buffer, ignore_errors=True) - #self.output.info(f"output: {buffer.getvalue()}") - #self.run(command) + self.run(f"{self._python} --version") self.run(f"{self._python} -c \"print('hello world')\"") @@ -219,9 +218,11 @@ def test(self): # MSVC builds need PYTHONHOME set. # FIXME - if self.dependencies["cpython"].conf_info.get("user.cpython:module_requires_pythonhome", check_type=bool): - os.environ["PYTHONHOME"] = self.dependencies["cpython"].conf_info.get("user.cpython:pythonhome", check_type=str) - #if self.deps_user_info["cpython"].module_requires_pythonhome == "True": - # os.environ["PYTHONHOME"] = self.deps_user_info["cpython"].pythonhome + if conan2: + if self.dependencies["cpython"].conf_info.get("user.cpython:module_requires_pythonhome", check_type=bool): + os.environ["PYTHONHOME"] = self.dependencies["cpython"].conf_info.get("user.cpython:pythonhome", check_type=str) + else: + if self.deps_user_info["cpython"].module_requires_pythonhome == "True": + os.environ["PYTHONHOME"] = self.deps_user_info["cpython"].pythonhome bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package") self.run(bin_path) From 1c2d2d15f67ae237298347def984c7c495506e6a Mon Sep 17 00:00:00 2001 From: Alex Trotta Date: Sun, 26 Nov 2023 10:41:35 -0500 Subject: [PATCH 021/102] Fix MSBuild --- recipes/cpython/all/conanfile.py | 66 +++++++++---------- .../all/patches/2.7/2.7.18-0001-msvc.patch | 16 ++--- .../all/patches/3.10/3.10.0-0001-msvc.patch | 22 +++---- .../all/patches/3.7/3.7.9-0001-msvc.patch | 20 +++--- .../all/patches/3.8/3.8.12-0001-msvc.patch | 22 +++---- .../all/patches/3.9/3.9.7-0001-msvc.patch | 22 +++---- recipes/cpython/all/test_package/conanfile.py | 5 +- 7 files changed, 85 insertions(+), 88 deletions(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index cb87e287168ab..fed697ff335c8 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -298,6 +298,7 @@ def generate(self): deps.generate() # The toolchain.props is not injected yet, but it also generates VCVars toolchain = MSBuildToolchain(self) + toolchain.properties["IncludeExternals"] = "true" toolchain.generate() else: self._generate_autotools() @@ -369,22 +370,31 @@ def _patch_sources(self): "", "Py_NO_ENABLE_SHARED;%(PreprocessorDefinitions)") - def _upgrade_single_project_file(self, project_file): - """ - `devenv /upgrade ` will upgrade *ALL* projects referenced by the project. - By temporarily moving the solution project, only one project is upgraded - This is needed for static cpython or for disabled optional dependencies (e.g. tkinter=False) - Restore it afterwards because it is needed to build some targets. - """ - rename(self,os.path.join(self.source_folder, "PCbuild", "pcbuild.sln"), - os.path.join(self.source_folder, "PCbuild", "pcbuild.sln.bak")) - rename(self, os.path.join(self.source_folder, "PCbuild", "pcbuild.proj"), - os.path.join(self.source_folder, "PCbuild", "pcbuild.proj.bak")) - self.run(f'devenv "{project_file}" /upgrade') - rename(self, os.path.join(self.source_folder, "PCbuild", "pcbuild.sln.bak"), - os.path.join(self.source_folder, "PCbuild", "pcbuild.sln")) - rename(self, os.path.join(self.source_folder, "PCbuild", "pcbuild.proj.bak"), - os.path.join(self.source_folder, "PCbuild", "pcbuild.proj")) + # Don't import projects that we aren't pulling + deps = [ + # Option suffix, base file name, conan props suffix + ("sqlite3", "_sqlite3", "sqlite3"), + ("tkinter", "_tkinter", "tk"), + ("bz2", "_bz2", "bzip2"), + ("lzma", "_lzma", "xz_utils"), + ] + for opt, fname, propname in deps: + full_file = os.path.join(self.source_folder, "PCbuild", f"{fname}.vcxproj") + if not self.options.get_safe(f"with_{opt}", default=True): + replace_in_file(self, full_file, f'', "") + + # Fix props path for dependencies we are pulling + PCBuild = os.path.join(self.source_folder, "PCbuild") + for filename in os.listdir(PCBuild): + if filename.endswith(".vcxproj"): + replace_in_file(self, os.path.join(PCBuild, filename), "CONAN_REPLACE_HERE", self.generators_folder, strict=False) + + conantoolchain_props = os.path.join(self.generators_folder, MSBuildToolchain.filename) + replace_in_file( + self, os.path.join(self.source_folder, "PCbuild", "pythoncore.vcxproj"), + '', + f'', + ) @property def _solution_projects(self): @@ -399,17 +409,7 @@ def project_build(name): return False return True - def sort_importance(key): - importance = ( - "pythoncore", # The python library MUST be built first. All modules and executables depend on it - "python", # Build the python executable next (for convenience, when debugging) - ) - try: - return importance.index(key) - except ValueError: - return len(importance) - - projects = sorted((p for p in projects if project_build(p)), key=sort_importance) + projects = list(filter(project_build, projects)) return projects else: return "pythoncore", "python", "pythonw" @@ -468,19 +468,12 @@ def _msvc_archs(self): def _msvc_build(self): msbuild = MSBuild(self) msbuild.platform = self._msvc_archs[str(self.settings.arch)] - # TODO - msbuild_properties = { - "IncludeExternals": "true", - } projects = self._solution_projects self.output.info(f"Building {len(projects)} Visual Studio projects: {projects}") - for project_i, project in enumerate(projects, 1): - self.output.info(f"[{project_i}/{len(projects)}] Building project '{project}'...") - project_file = os.path.join(self.source_folder, "PCbuild", project + ".vcxproj") - self._upgrade_single_project_file(project_file) - msbuild.build(project_file) + msbuild.build(os.path.join(self.source_folder, "PCbuild", "pcbuild.sln"), + targets=projects) def build(self): self._patch_sources() @@ -749,6 +742,7 @@ def package_info(self): # embed component: "Embed Python into an application" self.cpp_info.components["embed"].libs = [self._lib_name] self.cpp_info.components["embed"].libdirs = [libdir] + self.cpp_info.components["embed"].includedirs = [] self.cpp_info.components["embed"].set_property( "pkg_config_name", f"python-{py_version.major}.{py_version.minor}-embed" ) diff --git a/recipes/cpython/all/patches/2.7/2.7.18-0001-msvc.patch b/recipes/cpython/all/patches/2.7/2.7.18-0001-msvc.patch index 2c101049df531..c87be88c09016 100644 --- a/recipes/cpython/all/patches/2.7/2.7.18-0001-msvc.patch +++ b/recipes/cpython/all/patches/2.7/2.7.18-0001-msvc.patch @@ -5,7 +5,7 @@ - -+ ++ .pyd @@ -34,7 +34,7 @@ NotSet - -+ ++ .pyd @@ -71,7 +71,7 @@ NotSet - -+ ++ .pyd @@ -95,7 +95,7 @@ NotSet - -+ ++ .pyd @@ -132,7 +132,7 @@ - -+ ++ .pyd @@ -159,7 +159,7 @@ NotSet - -+ ++ .pyd @@ -206,7 +206,7 @@ NotSet - -+ ++ .pyd @@ -243,7 +243,7 @@ NotSet - -+ ++ .pyd diff --git a/recipes/cpython/all/patches/3.10/3.10.0-0001-msvc.patch b/recipes/cpython/all/patches/3.10/3.10.0-0001-msvc.patch index e9b1faf061f3b..9884e12e53f1e 100644 --- a/recipes/cpython/all/patches/3.10/3.10.0-0001-msvc.patch +++ b/recipes/cpython/all/patches/3.10/3.10.0-0001-msvc.patch @@ -26,7 +26,7 @@ Win32Proj - -+ ++ DynamicLibrary @@ -59,7 +59,7 @@ Win32Proj - -+ ++ DynamicLibrary @@ -88,7 +88,7 @@ Win32Proj - -+ ++ DynamicLibrary @@ -146,7 +146,7 @@ Win32Proj - -+ ++ DynamicLibrary @@ -180,7 +180,7 @@ +++ PCbuild/_sqlite3.vcxproj @@ -74,1 +74,1 @@ - -+ ++ @@ -129,4 +129,4 @@ - + - - - ---- PCbuild/_hashlib.vcxproj -+++ PCbuild/_hashlib.vcxproj -@@ -45,7 +45,7 @@ - DynamicLibrary - NotSet - -- -+ - - .pyd - -@@ -64,7 +64,7 @@ - $(opensslIncludeDir);%(AdditionalIncludeDirectories) - - -- ws2_32.lib;$(OutDir)libeay$(PyDebugExt).lib;$(OutDir)ssleay$(PyDebugExt).lib;%(AdditionalDependencies) -+ ws2_32.lib;%(AdditionalDependencies) - - - -@@ -75,14 +75,14 @@ - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - -- -+ - - - ---- PCbuild/_sqlite3.vcxproj -+++ PCbuild/_sqlite3.vcxproj -@@ -45,7 +45,7 @@ - DynamicLibrary - NotSet - -- -+ - - .pyd - -@@ -96,10 +96,10 @@ - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - -- -+ - - - ---- PCbuild/_ssl.vcxproj -+++ PCbuild/_ssl.vcxproj -@@ -45,7 +45,7 @@ - DynamicLibrary - NotSet - -- -+ - - .pyd - -@@ -64,7 +64,7 @@ - $(opensslIncludeDir);%(AdditionalIncludeDirectories) - - -- ws2_32.lib;crypt32.lib;$(OutDir)libeay$(PyDebugExt).lib;$(OutDir)ssleay$(PyDebugExt).lib;%(AdditionalDependencies) -+ ws2_32.lib;crypt32.lib;%(AdditionalDependencies) - - - -@@ -75,14 +75,14 @@ - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - -- -+ - - {86937f53-c189-40ef-8ce8-8759d8e7d480} - false ---- PCbuild/bz2.vcxproj -+++ PCbuild/bz2.vcxproj -@@ -47,7 +47,7 @@ - NotSet - - -- -+ - - .pyd - -@@ -72,13 +72,13 @@ - - - -- -+ - - - ---- PCbuild/_elementtree.vcxproj -+++ PCbuild/_elementtree.vcxproj -@@ -45,7 +45,7 @@ - DynamicLibrary - NotSet - -- -+ - - .pyd - -@@ -61,15 +61,15 @@ - - - -- ..\Modules\expat;%(AdditionalIncludeDirectories) -- _CRT_SECURE_NO_WARNINGS;USE_PYEXPAT_CAPI;XML_STATIC;%(PreprocessorDefinitions) -+ %(AdditionalIncludeDirectories) -+ _CRT_SECURE_NO_WARNINGS;USE_PYEXPAT_CAPI;%(PreprocessorDefinitions) - - - 0x1D100000 - - - -- -+ - - - -- -+ - - - ---- PCbuild/pyexpat.vcxproj -+++ PCbuild/pyexpat.vcxproj -@@ -45,7 +45,7 @@ - DynamicLibrary - NotSet - -- -+ - - .pyd - -@@ -58,19 +58,19 @@ - - - -- $(PySourcePath)Modules\expat;%(AdditionalIncludeDirectories) -- _CRT_SECURE_NO_WARNINGS;PYEXPAT_EXPORTS;XML_STATIC;%(PreprocessorDefinitions) -+ %(AdditionalIncludeDirectories) -+ _CRT_SECURE_NO_WARNINGS;PYEXPAT_EXPORTS;%(PreprocessorDefinitions) - - - -- -- -+ - - - -- -+ - - - ---- PCbuild/_tkinter.vcxproj -+++ PCbuild/_tkinter.vcxproj -@@ -45,7 +45,7 @@ - DynamicLibrary - NotSet - -- -+ - - .pyd - -@@ -61,11 +61,11 @@ - - - -- $(tcltkDir)include;%(AdditionalIncludeDirectories) -+ %(AdditionalIncludeDirectories) - WITH_APPINIT;%(PreprocessorDefinitions) - - -- $(tcltkLib);%(AdditionalDependencies) -+ %(AdditionalDependencies) - - - -@@ -77,12 +77,12 @@ - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - -- -+ - - - diff --git a/recipes/cpython/all/patches/2.7/2.7.18-0002-add-support-msvc-14.patch b/recipes/cpython/all/patches/2.7/2.7.18-0002-add-support-msvc-14.patch deleted file mode 100644 index 6034410d3d265..0000000000000 --- a/recipes/cpython/all/patches/2.7/2.7.18-0002-add-support-msvc-14.patch +++ /dev/null @@ -1,59 +0,0 @@ -Patches from https://bugs.python.org/issue30742 - ---- Modules/posixmodule.c -+++ Modules/posixmodule.c -@@ -563,7 +563,10 @@ typedef struct { - char osfile; - } my_ioinfo; - -+#if _MSC_VER < 1900 // MSVS2013 and lower (https://bugs.python.org/issue30742) - extern __declspec(dllimport) char * __pioinfo[]; -+#endif -+ - #define IOINFO_L2E 5 - #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) - #define IOINFO_ARRAYS 64 -@@ -575,6 +578,7 @@ extern __declspec(dllimport) char * __pioinfo[]; - int - _PyVerify_fd(int fd) - { -+#if _MSC_VER < 1900 // MSVS2013 and lower (https://bugs.python.org/issue30742) - const int i1 = fd >> IOINFO_L2E; - const int i2 = fd & ((1 << IOINFO_L2E) - 1); - -@@ -607,6 +611,13 @@ _PyVerify_fd(int fd) - fail: - errno = EBADF; - return 0; -+#else -+ //a call to _get_osfhandle with invalid fd sets errno to EBADF -+ if (_get_osfhandle(fd) == INVALID_HANDLE_VALUE) -+ return 0; -+ else -+ return 1; -+#endif - } - - /* the special case of checking dup2. The target fd must be in a sensible range */ ---- Modules/timemodule.c -+++ Modules/timemodule.c -@@ -803,7 +803,18 @@ inittimezone(PyObject *m) { - - And I'm lazy and hate C so nyer. - */ --#if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__) -+#if defined(HAVE_TZNAME) && (_MSC_VER >= 1900) //MSVS2015+ (https://bugs.python.org/issue30742) -+ tzset(); -+ PyModule_AddIntConstant(m, "timezone", _timezone); -+#ifdef HAVE_ALTZONE -+ PyModule_AddIntConstant(m, "altzone", altzone); -+#else -+ PyModule_AddIntConstant(m, "altzone", _timezone - 3600); -+#endif -+ PyModule_AddIntConstant(m, "daylight", _daylight); -+ PyModule_AddObject(m, "tzname", -+ Py_BuildValue("(zz)", _tzname[0], _tzname[1])); -+#elif defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__) - tzset(); - #ifdef PYOS_OS2 - PyModule_AddIntConstant(m, "timezone", _timezone); diff --git a/recipes/cpython/all/patches/2.7/2.7.18-0003-msvc-fix-static.patch b/recipes/cpython/all/patches/2.7/2.7.18-0003-msvc-fix-static.patch deleted file mode 100644 index 9eb079402733d..0000000000000 --- a/recipes/cpython/all/patches/2.7/2.7.18-0003-msvc-fix-static.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- PC/dl_nt.c -+++ PC/dl_nt.c -@@ -107,5 +107,7 @@ - } - return TRUE; - } -- -+#else -+ULONG_PTR _Py_ActivateActCtx() { return 0; } -+void _Py_DeactivateActCtx(ULONG_PTR cookie) {} - #endif /* Py_ENABLE_SHARED */ diff --git a/recipes/cpython/all/patches/2.7/2.7.18-0004-disable-macos-tcltk.patch b/recipes/cpython/all/patches/2.7/2.7.18-0004-disable-macos-tcltk.patch deleted file mode 100644 index 5c61acd74bd5c..0000000000000 --- a/recipes/cpython/all/patches/2.7/2.7.18-0004-disable-macos-tcltk.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- setup.py -+++ setup.py -@@ -1928,9 +1928,9 @@ - # Rather than complicate the code below, detecting and building - # AquaTk is a separate method. Only one Tkinter will be built on - # Darwin - either AquaTk, if it is found, or X11 based Tk. -- if (host_platform == 'darwin' and -- self.detect_tkinter_darwin(inc_dirs, lib_dirs)): -- return -+ #if (host_platform == 'darwin' and -+ # self.detect_tkinter_darwin(inc_dirs, lib_dirs)): -+ # return - - # Assume we haven't found any of the libraries or include files - # The versions with dots are used on Unix, and the versions without diff --git a/recipes/cpython/all/patches/3.7/3.7.9-0001-msvc.patch b/recipes/cpython/all/patches/3.7/3.7.9-0001-msvc.patch deleted file mode 100644 index 85e95cbae6d01..0000000000000 --- a/recipes/cpython/all/patches/3.7/3.7.9-0001-msvc.patch +++ /dev/null @@ -1,416 +0,0 @@ ---- PCbuild/pcbuild.sln -+++ PCbuild/pcbuild.sln -@@ -58,2 +58,0 @@ --Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqlite3", "sqlite3.vcxproj", "{A1A295E5-463C-437F-81CA-1F32367685DA}" --EndProject ---- PCbuild/python.vcxproj -+++ PCbuild/python.vcxproj -@@ -85,1 +85,1 @@ -- -+ ---- PCbuild/_freeze_importlib.vcxproj -+++ PCbuild/_freeze_importlib.vcxproj -@@ -110,1 +110,1 @@ -- -+ --> ---- PCbuild/_bz2.vcxproj -+++ PCbuild/_bz2.vcxproj -@@ -39,7 +39,7 @@ - bz2 - Win32Proj - -- -+ - - - DynamicLibrary -@@ -69,17 +69,17 @@ - - - -- -+ - - -- -- -+ - - - ---- PCbuild/_decimal.vcxproj -+++ PCbuild/_decimal.vcxproj -@@ -39,7 +39,7 @@ - _decimal - Win32Proj - -- -+ - - - DynamicLibrary -@@ -64,11 +64,11 @@ - _CRT_SECURE_NO_WARNINGS;MASM;%(PreprocessorDefinitions) - CONFIG_32;PPRO;%(PreprocessorDefinitions) - CONFIG_64;%(PreprocessorDefinitions) -- ..\Modules\_decimal;..\Modules\_decimal\libmpdec;%(AdditionalIncludeDirectories) -+ ..\Modules\_decimal;%(AdditionalIncludeDirectories) - - - -- -+ - - - -- -+ - - -- -+ - - - ---- PCbuild/_elementtree.vcxproj -+++ PCbuild/_elementtree.vcxproj -@@ -39,7 +39,7 @@ - _elementtree - Win32Proj - -- -+ - - - DynamicLibrary -@@ -65,8 +65,8 @@ -- _CRT_SECURE_NO_WARNINGS;USE_PYEXPAT_CAPI;XML_STATIC;%(PreprocessorDefinitions) -+ _CRT_SECURE_NO_WARNINGS;USE_PYEXPAT_CAPI;%(PreprocessorDefinitions) - - - -- -+ - - - -- -+ - - - ---- PCbuild/_lzma.vcxproj -+++ PCbuild/_lzma.vcxproj -@@ -39,7 +39,7 @@ - lzma - Win32Proj - -- -+ - - - DynamicLibrary -@@ -62,10 +62,10 @@ - - - $(lzmaDir)src/liblzma/api;%(AdditionalIncludeDirectories) -- WIN32;_FILE_OFFSET_BITS=64;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;LZMA_API_STATIC;%(PreprocessorDefinitions) -+ $(ConanPreprocessorDefinitions);WIN32;_FILE_OFFSET_BITS=64;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;LZMA_API_STATIC;%(PreprocessorDefinitions) - - -- $(OutDir)liblzma$(PyDebugExt).lib;%(AdditionalDependencies) -+ %(AdditionalDependencies) - - - -@@ -79,10 +79,10 @@ - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - -- -+ - - - ---- PCbuild/_sqlite3.vcxproj -+++ PCbuild/_sqlite3.vcxproj -@@ -39,7 +39,7 @@ - _sqlite3 - Win32Proj - -- -+ - - - DynamicLibrary -@@ -95,10 +95,10 @@ - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} - false - -- -+ - - - ---- PCbuild/openssl.vcxproj -+++ PCbuild/openssl.vcxproj -@@ -74,6 +74,6 @@ nmake - - - -- -+ - - - ---- PCbuild/pyexpat.vcxproj -+++ PCbuild/pyexpat.vcxproj -@@ -39,7 +39,7 @@ - {D06B6426-4762-44CC-8BAD-D79052507F2F} - pyexpat - -- -+ - - - DynamicLibrary -@@ -58,19 +58,19 @@ - - - -- $(PySourcePath)Modules\expat;%(AdditionalIncludeDirectories) -- _CRT_SECURE_NO_WARNINGS;PYEXPAT_EXPORTS;HAVE_EXPAT_H;XML_STATIC;%(PreprocessorDefinitions) -+ %(AdditionalIncludeDirectories) -+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - -- -- -+ - - - -- -+ - - - ---- PCbuild/pythoncore.vcxproj -+++ PCbuild/pythoncore.vcxproj -@@ -38,7 +38,7 @@ - {CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26} - pythoncore - -- -+ - - - DynamicLibrary -@@ -215,7 +215,7 @@ - - - -- -+ - - - -@@ -409,7 +409,7 @@ - - - -- -+ - - - ---- PCbuild/_hashlib.vcxproj -+++ PCbuild/_hashlib.vcxproj -@@ -39,7 +39,7 @@ - _hashlib - Win32Proj - -- -+ - - - DynamicLibrary -@@ -54,7 +54,7 @@ - - - -- -+ - - - ---- PCbuild/_ssl.vcxproj -+++ PCbuild/_ssl.vcxproj -@@ -39,7 +39,7 @@ - _ssl - Win32Proj - -- -+ - - - DynamicLibrary -@@ -54,7 +54,7 @@ - - - -- -+ - - - -@@ -67,9 +67,9 @@ - - - -- -+ - - - ---- PCbuild/_tkinter.vcxproj -+++ PCbuild/_tkinter.vcxproj -@@ -45,7 +45,7 @@ - DynamicLibrary - NotSet - -- -+ - - .pyd - -@@ -61,12 +61,12 @@ - - - -- $(tcltkDir)include;%(AdditionalIncludeDirectories) -+ %(AdditionalIncludeDirectories) - WITH_APPINIT;%(PreprocessorDefinitions) -- Py_TCLTK_DIR="$(tcltkDir.TrimEnd('\').Replace('\', '\\'))";%(PreprocessorDefinitions) -+ - - -- $(tcltkLib);%(AdditionalDependencies) -+ %(AdditionalDependencies) - - - -@@ -76,10 +76,10 @@ - - - -- -+ - - - {cf7ac3d1-e2df-41d2-bea6-1e2556cdea26} ---- PCbuild/pcbuild.sln -+++ PCbuild/pcbuild.sln -@@ -9,9 +9,6 @@ - EndProjectSection - EndProject - Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python", "python.vcxproj", "{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}" -- ProjectSection(ProjectDependencies) = postProject -- {0E9791DB-593A-465F-98BC-681011311618} = {0E9791DB-593A-465F-98BC-681011311618} -- EndProjectSection - EndProject - Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pythoncore", "pythoncore.vcxproj", "{CF7AC3D1-E2DF-41D2-BEA6-1E2556CDEA26}" - EndProject diff --git a/recipes/cpython/all/patches/3.7/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch b/recipes/cpython/all/patches/3.7/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch deleted file mode 100644 index 92e44c8ea6ee5..0000000000000 --- a/recipes/cpython/all/patches/3.7/3.7.9-0002-setup.py-pass-CFLAGS-CPPFLAGS.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- Makefile.pre.in -+++ Makefile.pre.in -@@ -618,10 +618,10 @@ - *\ -s*|s*) quiet="-q";; \ - *) quiet="";; \ - esac; \ -- echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ -+ echo "$(RUNSHARED) CC='$(CC) $(CONFIGURE_CFLAGS) $(CONFIGURE_CPPFLAGS)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ - $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ -- $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ -+ $(RUNSHARED) CC='$(CC) $(CONFIGURE_CFLAGS) $(CONFIGURE_CPPFLAGS)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ - $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build - diff --git a/recipes/cpython/all/patches/3.7/3.7.9-0003-disable-macos-tcltk.patch b/recipes/cpython/all/patches/3.7/3.7.9-0003-disable-macos-tcltk.patch deleted file mode 100644 index f5ffba2f61232..0000000000000 --- a/recipes/cpython/all/patches/3.7/3.7.9-0003-disable-macos-tcltk.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- setup.py -+++ setup.py -@@ -1829,9 +1829,9 @@ - # Rather than complicate the code below, detecting and building - # AquaTk is a separate method. Only one Tkinter will be built on - # Darwin - either AquaTk, if it is found, or X11 based Tk. -- if (host_platform == 'darwin' and -- self.detect_tkinter_darwin(inc_dirs, lib_dirs)): -- return -+ #if (host_platform == 'darwin' and -+ # self.detect_tkinter_darwin(inc_dirs, lib_dirs)): -+ # return - - # Assume we haven't found any of the libraries or include files - # The versions with dots are used on Unix, and the versions without diff --git a/recipes/cpython/all/test_package/CMakeLists.txt b/recipes/cpython/all/test_package/CMakeLists.txt index a3bfafd1c82db..0d333d99af1e3 100644 --- a/recipes/cpython/all/test_package/CMakeLists.txt +++ b/recipes/cpython/all/test_package/CMakeLists.txt @@ -9,12 +9,11 @@ find_package(cpython REQUIRED CONFIG) # but otherwise not at build time (in consumer packages). link_libraries(cpython::python) -set(PY_VERSION_MAJOR "" CACHE STRING "MAJOR version of python") set(PY_VERSION_MAJOR_MINOR "" CACHE STRING "MAJOR.MINOR version of python") set(PY_VERSION "" CACHE STRING "Required version of python") set(PY_VERSION_SUFFIX "" CACHE STRING "Suffix of python") -set(Python_ADDITIONAL_VERSIONS ${PY_VERSION}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR_MINOR}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR}${PY_VERSION_SUFFIX} ${PY_VERSION} ${PY_VERSION_MAJOR_MINOR} ${PY_VERSION_MAJOR}) +set(Python_ADDITIONAL_VERSIONS ${PY_VERSION}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR_MINOR}${PY_VERSION_SUFFIX} 3${PY_VERSION_SUFFIX} ${PY_VERSION} ${PY_VERSION_MAJOR_MINOR} 3) message("Using Python_ADDITIONAL_VERSIONS: ${Python_ADDITIONAL_VERSIONS}") find_package(PythonInterp REQUIRED) @@ -27,7 +26,6 @@ endif() message(STATUS "FindPythonInterp:") message(STATUS "PYTHON_VERSION_STRING: ${PYTHON_VERSION_STRING}") -message(STATUS "PYTHON_VERSION_MAJOR: ${PYTHON_VERSION_MAJOR}") message(STATUS "PYTHON_VERSION_MINOR: ${PYTHON_VERSION_MINOR}") message(STATUS "PYTHON_VERSION_PATCH: ${PYTHON_VERSION_PATCH}") message(STATUS "=============================================") @@ -59,7 +57,7 @@ endif() option(BUILD_MODULE "Build python module") if(BUILD_MODULE) - add_library(spam MODULE "py${PY_VERSION_MAJOR}/test_module.c") + add_library(spam MODULE "test_module.c") target_include_directories(spam PRIVATE ${PYTHON_INCLUDE_DIRS} @@ -77,27 +75,21 @@ if(BUILD_MODULE) option(USE_FINDPYTHON_X "Use new-style FindPythonX module") if(USE_FINDPYTHON_X AND NOT CMAKE_VERSION VERSION_LESS "3.16") - # Require CMake 3.16 because this version introduces Python${PY_VERSION_MAJOR}_FIND_ABI - find_package(Python${PY_VERSION_MAJOR} REQUIRED COMPONENTS Interpreter Development) - message("Python${PY_VERSION_MAJOR}_EXECUTABLE: ${Python${PY_VERSION_MAJOR}_EXECUTABLE}") - message("Python${PY_VERSION_MAJOR}_INTERPRETER_ID: ${Python${PY_VERSION_MAJOR}_INTERPRETER_ID}") - message("Python${PY_VERSION_MAJOR}_VERSION: ${Python${PY_VERSION_MAJOR}_VERSION}") - message("Python${PY_VERSION_MAJOR}_INCLUDE_DIRS: ${Python${PY_VERSION_MAJOR}_INCLUDE_DIRS}") - message("Python${PY_VERSION_MAJOR}_LIBRARIES: ${Python${PY_VERSION_MAJOR}_LIBRARIES}") - if(NOT Python${PY_VERSION_MAJOR}_VERSION STREQUAL "${PY_VERSION}") + # Require CMake 3.16 because this version introduces Python3_FIND_ABI + find_package(Python3 REQUIRED COMPONENTS Interpreter Development) + message("Python3_EXECUTABLE: ${Python3_EXECUTABLE}") + message("Python3_INTERPRETER_ID: ${Python3_INTERPRETER_ID}") + message("Python3_VERSION: ${Python3_VERSION}") + message("Python3_INCLUDE_DIRS: ${Python3_INCLUDE_DIRS}") + message("Python3_LIBRARIES: ${Python3_LIBRARIES}") + if(NOT Python3_VERSION STREQUAL "${PY_VERSION}") message("Python_ADDITIONAL_VERSIONS does not match PY_VERSION") message(FATAL_ERROR "CMake detected wrong cpython version") endif() - if(PY_VERSION_MAJOR STREQUAL "2") - python2_add_library(spam2 "py${PY_VERSION_MAJOR}/test_module.c") - elseif(PY_VERSION_MAJOR STREQUAL "3") - python3_add_library(spam2 "py${PY_VERSION_MAJOR}/test_module.c") - else() - message(FATAL_ERROR "Unknown PY_VERSION_MAJOR") - endif() + python3_add_library(spam2 "test_module.c") endif() endif() -add_executable(${PROJECT_NAME} "py${PY_VERSION_MAJOR}/test_package.c") +add_executable(${PROJECT_NAME} "test_package.c") target_link_libraries(${PROJECT_NAME} PRIVATE cpython::embed) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index aa34c73bd1cd9..4f4970f36f428 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -13,32 +13,6 @@ conan2 = conan_version.major >= 2 -class CmakePython3Abi(object): - def __init__(self, debug, pymalloc, unicode): - self.debug, self.pymalloc, self.unicode = debug, pymalloc, unicode - - _cmake_lut = { - None: "ANY", - True: "ON", - False: "OFF", - } - - @property - def suffix(self): - suffix = "" - if self.debug: - suffix += "d" - if self.pymalloc: - suffix += "m" - if self.unicode: - suffix += "u" - return suffix - - @property - def cmake_arg(self): - return ";".join(self._cmake_lut[a] for a in (self.debug, self.pymalloc, self.unicode)) - - class TestPackageConan(ConanFile): settings = "os", "arch", "compiler", "build_type" test_type = "explicit" @@ -79,11 +53,6 @@ def _py_version(self): else: return Version(self.deps_cpp_info["cpython"].version) - @property - def _cmake_abi(self): - pymalloc = self._cpython_option("pymalloc") if self._py_version < "3.8" else False - return CmakePython3Abi(debug=self.settings.build_type == "Debug", pymalloc=bool(pymalloc), unicode=False) - @property def _cmake_try_FindPythonX(self): return not is_msvc(self) or self.settings.build_type != "Debug" @@ -97,10 +66,9 @@ def generate(self): version = self._py_version py_major = str(version.major) tc.cache_variables["BUILD_MODULE"] = self._supports_modules - tc.cache_variables["PY_VERSION_MAJOR"] = py_major tc.cache_variables["PY_VERSION_MAJOR_MINOR"] = f"{version.major}.{version.minor}" tc.cache_variables["PY_VERSION"] = str(self._py_version) - tc.cache_variables["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix + tc.cache_variables["PY_VERSION_SUFFIX"] = "d" if self.settings.build_type == "Debug" else "" tc.cache_variables["PYTHON_EXECUTABLE"] = self._python tc.cache_variables["USE_FINDPYTHON_X"] = self._cmake_try_FindPythonX tc.cache_variables[f"Python{py_major}_EXECUTABLE"] = self._python @@ -110,8 +78,6 @@ def generate(self): tc.cache_variables[f"Python{py_major}_FIND_REGISTRY"] = "NEVER" tc.cache_variables[f"Python{py_major}_FIND_IMPLEMENTATIONS"] = "CPython" tc.cache_variables[f"Python{py_major}_FIND_STRATEGY"] = "LOCATION" - if not is_msvc(self) and self._py_version < "3.8": - tc.cache_variables[f"Python{py_major}_FIND_ABI"] = self._cmake_abi.cmake_arg tc.generate() deps = CMakeDeps(self) @@ -186,25 +152,19 @@ def test(self): if self._supports_modules: self._test_module("gdbm", self._cpython_option("with_gdbm")) self._test_module("bz2", self._cpython_option("with_bz2")) - if self._py_version.major < 3: - self._test_module("bsddb", self._cpython_option("with_bsddb")) self._test_module("lzma", self._cpython_option("with_lzma")) self._test_module("tkinter", self._cpython_option("with_tkinter")) os.environ["TERM"] = "ansi" self._test_module("curses", self._cpython_option("with_curses")) - self._test_module("expat", True) self._test_module("sqlite3", self._cpython_option("with_sqlite3")) self._test_module("decimal", True) self._test_module("ctypes", True) - skip_ssl_test = is_msvc(self) and self._py_version < "3.8" and self._cpython_option("shared") - if not skip_ssl_test: - # Unsure cause of failure in this oddly specific combo, but these versions are EOL so not concerned with fixing. - env = Environment() - if self.settings.os != "Windows": - env.define_path("OPENSSL_CONF", os.path.join(os.sep, "dev", "null")) - with env.vars(self).apply(): - self._test_module("ssl", True) + env = Environment() + if self.settings.os != "Windows": + env.define_path("OPENSSL_CONF", os.path.join(os.sep, "dev", "null")) + with env.vars(self).apply(): + self._test_module("ssl", True) if is_apple_os(self) and not self._cpython_option("shared"): self.output.info( diff --git a/recipes/cpython/all/test_package/py2/test_module.c b/recipes/cpython/all/test_package/py2/test_module.c deleted file mode 100644 index 9c5af39ab391b..0000000000000 --- a/recipes/cpython/all/test_package/py2/test_module.c +++ /dev/null @@ -1,42 +0,0 @@ -#include - -#include - -static PyObject *SpamError; - -static PyObject * -spam_system(PyObject *self, PyObject *args) -{ - const char *command; - int sts; - - if (!PyArg_ParseTuple(args, "s", &command)) - return NULL; - sts = system(command); - if (sts < 0) { - PyErr_SetString(SpamError, "System command failed"); - return NULL; - } - return PyLong_FromLong(sts); -} - -const char spam_doc[] = "This is an example spam doc."; - -static PyMethodDef SpamMethods[] = { - {"system", spam_system, METH_VARARGS, "Execute a shell command."}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - -PyMODINIT_FUNC -initspam(void) -{ - PyObject *m; - - m = Py_InitModule("spam", SpamMethods); - if (m == NULL) - return; - PyModule_AddStringConstant(m, "__doc__", spam_doc); - SpamError = PyErr_NewException("spam.error", NULL, NULL); - Py_INCREF(SpamError); - PyModule_AddObject(m, "error", SpamError); -} diff --git a/recipes/cpython/all/test_package/py2/test_package.c b/recipes/cpython/all/test_package/py2/test_package.c deleted file mode 100644 index 5e5d839b5a6a1..0000000000000 --- a/recipes/cpython/all/test_package/py2/test_package.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -int -main(int argc, char *argv[]) -{ - Py_SetProgramName(argv[0]); /* optional but recommended */ - Py_Initialize(); - PyRun_SimpleString("from time import time,ctime\n" - "print 'Today is',ctime(time())\n"); - Py_Finalize(); - return 0; -} diff --git a/recipes/cpython/all/test_package/setup.py b/recipes/cpython/all/test_package/setup.py index 70f6e8f6961db..2cf4febef6264 100644 --- a/recipes/cpython/all/test_package/setup.py +++ b/recipes/cpython/all/test_package/setup.py @@ -1,5 +1,4 @@ import os -import sys # Hack to work around Python 3.8+ secure dll loading: # see https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew @@ -8,25 +7,14 @@ if os.path.isdir(directory): os.add_dll_directory(directory) -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY2: - subdir = "py2" - from distutils.core import setup, Extension -elif PY3: - subdir = "py3" - from setuptools import setup, Extension -else: - raise Exception +from setuptools import setup, Extension script_dir = os.path.dirname(os.path.realpath(__file__)) setup( name="test_package", version="1.0", - use_2to3=True, ext_modules=[ - Extension("spam", [os.path.join(script_dir, subdir, "test_module.c")]), + Extension("spam", [os.path.join(script_dir, "test_module.c")]), ], ) diff --git a/recipes/cpython/all/test_package/py3/test_module.c b/recipes/cpython/all/test_package/test_module.c similarity index 100% rename from recipes/cpython/all/test_package/py3/test_module.c rename to recipes/cpython/all/test_package/test_module.c diff --git a/recipes/cpython/all/test_package/py3/test_package.c b/recipes/cpython/all/test_package/test_package.c similarity index 100% rename from recipes/cpython/all/test_package/py3/test_package.c rename to recipes/cpython/all/test_package/test_package.c diff --git a/recipes/cpython/all/test_package/test_package.py b/recipes/cpython/all/test_package/test_package.py index b682818b06128..bed43fac74c62 100644 --- a/recipes/cpython/all/test_package/test_package.py +++ b/recipes/cpython/all/test_package/test_package.py @@ -56,10 +56,7 @@ def char_data(data): @add_test def test_gdbm(): - if sys.version_info < (3, 0): - import gdbm - else: - import dbm.gnu as gdbm + import dbm.gnu as gdbm dbfile = "gdbm.db" @@ -105,24 +102,6 @@ def test_bz2(): raise Exception("bz2.compress returned no data") -@add_test -def test_bsddb(): - import bsddb - - db = bsddb.btopen("bsddb.db", "c") - db["key1"] = "value1" - db["key2"] = "value2" - db.close() - - db = bsddb.btopen("bsddb.db", "r") - if len(db) != 2: - raise Exception("Wrong length") - if db["key1"] != "value1": - raise Exception("value1 incorrect {}".format(db["key1"])) - if db["key2"] != "value2": - raise Exception("value2 incorrect {}".format(db["key2"])) - - @add_test def test_lzma(): import lzma @@ -170,11 +149,9 @@ def test_sqlite3(): @add_test def test_decimal(): - if sys.version_info >= (3,): - # Check whether the _decimal package was built successfully - import _decimal as decimal - else: - import decimal + # Check whether the _decimal package was built successfully + import _decimal as decimal + decimal.getcontext().prec = 6 print("1/7 =", decimal.Decimal(1) / decimal.Decimal(7)) decimal.getcontext().prec = 40 diff --git a/recipes/cpython/all/test_v1_package/CMakeLists.txt b/recipes/cpython/all/test_v1_package/CMakeLists.txt index 715d734264d9f..6014dcdd6efcb 100644 --- a/recipes/cpython/all/test_v1_package/CMakeLists.txt +++ b/recipes/cpython/all/test_v1_package/CMakeLists.txt @@ -9,7 +9,7 @@ set(CACHE PY_VERSION_MAJOR_MINOR "" CACHE STRING "MAJOR.MINOR version of python" set(CACHE PY_VERSION "" CACHE STRING "Required version of python") set(CACHE PY_VERSION_SUFFIX "" CACHE STRING "Suffix of python") -set(Python_ADDITIONAL_VERSIONS ${PY_VERSION}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR_MINOR}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR}${PY_VERSION_SUFFIX} ${PY_VERSION} ${PY_VERSION_MAJOR_MINOR} ${PY_VERSION_MAJOR}) +set(Python_ADDITIONAL_VERSIONS ${PY_VERSION}${PY_VERSION_SUFFIX} ${PY_VERSION_MAJOR_MINOR}${PY_VERSION_SUFFIX} 3${PY_VERSION_SUFFIX} ${PY_VERSION} ${PY_VERSION_MAJOR_MINOR} 3) message("Using Python_ADDITIONAL_VERSIONS: ${Python_ADDITIONAL_VERSIONS}") find_package(PythonInterp REQUIRED) @@ -53,7 +53,7 @@ endif() option(BUILD_MODULE "Build python module") -set(SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../test_package/py${PY_VERSION_MAJOR}") +set(SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../test_package") if(BUILD_MODULE) add_library(spam MODULE "${SOURCE_DIR}/test_module.c") @@ -76,25 +76,19 @@ if(BUILD_MODULE) option(USE_FINDPYTHON_X "Use new-style FindPythonX module") if(USE_FINDPYTHON_X AND NOT (CMAKE_VERSION VERSION_LESS "3.16")) - # Require CMake 3.16 because this version introduces Python${PY_VERSION_MAJOR}_FIND_ABI - find_package(Python${PY_VERSION_MAJOR} REQUIRED COMPONENTS Interpreter Development) - message("Python${PY_VERSION_MAJOR}_EXECUTABLE: ${Python${PY_VERSION_MAJOR}_EXECUTABLE}") - message("Python${PY_VERSION_MAJOR}_INTERPRETER_ID: ${Python${PY_VERSION_MAJOR}_INTERPRETER_ID}") - message("Python${PY_VERSION_MAJOR}_VERSION: ${Python${PY_VERSION_MAJOR}_VERSION}") - message("Python${PY_VERSION_MAJOR}_INCLUDE_DIRS: ${Python${PY_VERSION_MAJOR}_INCLUDE_DIRS}") - message("Python${PY_VERSION_MAJOR}_LIBRARIES: ${Python${PY_VERSION_MAJOR}_LIBRARIES}") - if(NOT Python${PY_VERSION_MAJOR}_VERSION STREQUAL "${PY_VERSION}") + # Require CMake 3.16 because this version introduces Python3_FIND_ABI + find_package(Python3 REQUIRED COMPONENTS Interpreter Development) + message("Python3_EXECUTABLE: ${Python3_EXECUTABLE}") + message("Python3_INTERPRETER_ID: ${Python3_INTERPRETER_ID}") + message("Python3_VERSION: ${Python3_VERSION}") + message("Python3_INCLUDE_DIRS: ${Python3_INCLUDE_DIRS}") + message("Python3_LIBRARIES: ${Python3_LIBRARIES}") + if(NOT Python3_VERSION STREQUAL "${PY_VERSION}") message("Python_ADDITIONAL_VERSIONS does not match PY_VERSION") message(FATAL_ERROR "CMake detected wrong cpython version") endif() - if(PY_VERSION_MAJOR STREQUAL "2") - python2_add_library(spam2 "${SOURCE_DIR}/test_module.c") - elseif(PY_VERSION_MAJOR STREQUAL "3") - python3_add_library(spam2 "${SOURCE_DIR}/test_module.c") - else() - message(FATAL_ERROR "Unknown PY_VERSION_MAJOR") - endif() + python3_add_library(spam2 "${SOURCE_DIR}/test_module.c") endif() endif() diff --git a/recipes/cpython/all/test_v1_package/conanfile.py b/recipes/cpython/all/test_v1_package/conanfile.py index 43cd3d0cbca5a..2d304994b1768 100644 --- a/recipes/cpython/all/test_v1_package/conanfile.py +++ b/recipes/cpython/all/test_v1_package/conanfile.py @@ -5,30 +5,6 @@ import os import re - -class CmakePython3Abi(object): - def __init__(self, debug, pymalloc, unicode): - self.debug, self.pymalloc, self.unicode = debug, pymalloc, unicode - - _cmake_lut = { - None: "ANY", - True: "ON", - False: "OFF", - } - - @property - def suffix(self): - return "{}{}{}".format( - "d" if self.debug else "", - "m" if self.pymalloc else "", - "u" if self.unicode else "", - ) - - @property - def cmake_arg(self): - return ";".join(self._cmake_lut[a] for a in (self.debug, self.pymalloc, self.unicode)) - - class TestPackageConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "cmake" @@ -37,25 +13,6 @@ class TestPackageConan(ConanFile): def _py_version(self): return re.match(r"^([0-9.]+)", self.deps_cpp_info["cpython"].version).group(1) - @property - def _pymalloc(self): - return bool("pymalloc" in self.options["cpython"] and self.options["cpython"].pymalloc) - - @property - def _cmake_abi(self): - if self._py_version < tools.Version("3.8"): - return CmakePython3Abi( - debug=self.settings.build_type == "Debug", - pymalloc=self._pymalloc, - unicode=False, - ) - else: - return CmakePython3Abi( - debug=self.settings.build_type == "Debug", - pymalloc=False, - unicode=False, - ) - @property def _cmake_try_FindPythonX(self): if self.settings.compiler == "Visual Studio" and self.settings.build_type == "Debug": @@ -89,11 +46,10 @@ def build(self): cmake = CMake(self) py_major = self.deps_cpp_info["cpython"].version.split(".")[0] cmake.definitions["BUILD_MODULE"] = self._supports_modules - cmake.definitions["PY_VERSION_MAJOR"] = py_major cmake.definitions["PY_VERSION_MAJOR_MINOR"] = ".".join(self._py_version.split(".")[:2]) cmake.definitions["PY_FULL_VERSION"] = self.deps_cpp_info["cpython"].version cmake.definitions["PY_VERSION"] = self._py_version - cmake.definitions["PY_VERSION_SUFFIX"] = self._cmake_abi.suffix + cmake.definitions["PY_VERSION_SUFFIX"] = "d" if self.settings.build_type == "Debug" else "" cmake.definitions["PYTHON_EXECUTABLE"] = self.deps_user_info["cpython"].python cmake.definitions["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX cmake.definitions["Python{}_EXECUTABLE".format(py_major)] = self.deps_user_info["cpython"].python @@ -104,10 +60,6 @@ def build(self): cmake.definitions["Python{}_FIND_IMPLEMENTATIONS".format(py_major)] = "CPython" cmake.definitions["Python{}_FIND_STRATEGY".format(py_major)] = "LOCATION" - if self.settings.compiler != "Visual Studio": - if tools.Version(self._py_version) < tools.Version("3.8"): - cmake.definitions["Python{}_FIND_ABI".format(py_major)] = self._cmake_abi.cmake_arg - with tools.environment_append(RunEnvironment(self).vars): cmake.configure() cmake.build() @@ -174,7 +126,6 @@ def test(self): if self._supports_modules: self._test_module("gdbm", self._cpython_option("with_gdbm")) self._test_module("bz2", self._cpython_option("with_bz2")) - self._test_module("bsddb", self._cpython_option("with_bsddb")) self._test_module("lzma", self._cpython_option("with_lzma")) self._test_module("tkinter", self._cpython_option("with_tkinter")) with tools.environment_append({"TERM": "ansi"}): diff --git a/recipes/cpython/config.yml b/recipes/cpython/config.yml index e3abf3ec8acb2..cce5cc26948d6 100644 --- a/recipes/cpython/config.yml +++ b/recipes/cpython/config.yml @@ -5,7 +5,3 @@ versions: folder: "all" "3.8.12": folder: "all" - "3.7.12": - folder: "all" - "2.7.18": - folder: "all" From ab8ca5fdb8530903b6198a6f4777dc5d002d7f14 Mon Sep 17 00:00:00 2001 From: Alex Trotta Date: Mon, 18 Mar 2024 16:25:18 -0400 Subject: [PATCH 098/102] Remove calculated Python major version --- recipes/cpython/all/test_package/conanfile.py | 15 +++++++-------- .../cpython/all/test_v1_package/conanfile.py | 17 ++++++++--------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/recipes/cpython/all/test_package/conanfile.py b/recipes/cpython/all/test_package/conanfile.py index 4f4970f36f428..bca7c7fcfd3b7 100644 --- a/recipes/cpython/all/test_package/conanfile.py +++ b/recipes/cpython/all/test_package/conanfile.py @@ -64,20 +64,19 @@ def _supports_modules(self): def generate(self): tc = CMakeToolchain(self) version = self._py_version - py_major = str(version.major) tc.cache_variables["BUILD_MODULE"] = self._supports_modules tc.cache_variables["PY_VERSION_MAJOR_MINOR"] = f"{version.major}.{version.minor}" tc.cache_variables["PY_VERSION"] = str(self._py_version) tc.cache_variables["PY_VERSION_SUFFIX"] = "d" if self.settings.build_type == "Debug" else "" tc.cache_variables["PYTHON_EXECUTABLE"] = self._python tc.cache_variables["USE_FINDPYTHON_X"] = self._cmake_try_FindPythonX - tc.cache_variables[f"Python{py_major}_EXECUTABLE"] = self._python - tc.cache_variables[f"Python{py_major}_ROOT_DIR"] = self.dependencies["cpython"].package_folder - tc.cache_variables[f"Python{py_major}_USE_STATIC_LIBS"] = not self.dependencies["cpython"].options.shared - tc.cache_variables[f"Python{py_major}_FIND_FRAMEWORK"] = "NEVER" - tc.cache_variables[f"Python{py_major}_FIND_REGISTRY"] = "NEVER" - tc.cache_variables[f"Python{py_major}_FIND_IMPLEMENTATIONS"] = "CPython" - tc.cache_variables[f"Python{py_major}_FIND_STRATEGY"] = "LOCATION" + tc.cache_variables["Python3_EXECUTABLE"] = self._python + tc.cache_variables["Python3_ROOT_DIR"] = self.dependencies["cpython"].package_folder + tc.cache_variables["Python3_USE_STATIC_LIBS"] = not self.dependencies["cpython"].options.shared + tc.cache_variables["Python3_FIND_FRAMEWORK"] = "NEVER" + tc.cache_variables["Python3_FIND_REGISTRY"] = "NEVER" + tc.cache_variables["Python3_FIND_IMPLEMENTATIONS"] = "CPython" + tc.cache_variables["Python3_FIND_STRATEGY"] = "LOCATION" tc.generate() deps = CMakeDeps(self) diff --git a/recipes/cpython/all/test_v1_package/conanfile.py b/recipes/cpython/all/test_v1_package/conanfile.py index 2d304994b1768..b79e5742735f3 100644 --- a/recipes/cpython/all/test_v1_package/conanfile.py +++ b/recipes/cpython/all/test_v1_package/conanfile.py @@ -44,21 +44,20 @@ def build(self): self.run(command, run_environment=True) cmake = CMake(self) - py_major = self.deps_cpp_info["cpython"].version.split(".")[0] cmake.definitions["BUILD_MODULE"] = self._supports_modules cmake.definitions["PY_VERSION_MAJOR_MINOR"] = ".".join(self._py_version.split(".")[:2]) cmake.definitions["PY_FULL_VERSION"] = self.deps_cpp_info["cpython"].version cmake.definitions["PY_VERSION"] = self._py_version cmake.definitions["PY_VERSION_SUFFIX"] = "d" if self.settings.build_type == "Debug" else "" cmake.definitions["PYTHON_EXECUTABLE"] = self.deps_user_info["cpython"].python - cmake.definitions["USE_FINDPYTHON_X".format(py_major)] = self._cmake_try_FindPythonX - cmake.definitions["Python{}_EXECUTABLE".format(py_major)] = self.deps_user_info["cpython"].python - cmake.definitions["Python{}_ROOT_DIR".format(py_major)] = self.deps_cpp_info["cpython"].rootpath - cmake.definitions["Python{}_USE_STATIC_LIBS".format(py_major)] = not self.options["cpython"].shared - cmake.definitions["Python{}_FIND_FRAMEWORK".format(py_major)] = "NEVER" - cmake.definitions["Python{}_FIND_REGISTRY".format(py_major)] = "NEVER" - cmake.definitions["Python{}_FIND_IMPLEMENTATIONS".format(py_major)] = "CPython" - cmake.definitions["Python{}_FIND_STRATEGY".format(py_major)] = "LOCATION" + cmake.definitions["USE_FINDPYTHON_X"] = self._cmake_try_FindPythonX + cmake.definitions["Python3_EXECUTABLE"] = self.deps_user_info["cpython"].python + cmake.definitions["Python3_ROOT_DIR"] = self.deps_cpp_info["cpython"].rootpath + cmake.definitions["Python3_USE_STATIC_LIBS"] = not self.options["cpython"].shared + cmake.definitions["Python3_FIND_FRAMEWORK"] = "NEVER" + cmake.definitions["Python3_FIND_REGISTRY"] = "NEVER" + cmake.definitions["Python3_FIND_IMPLEMENTATIONS"] = "CPython" + cmake.definitions["Python3_FIND_STRATEGY"] = "LOCATION" with tools.environment_append(RunEnvironment(self).vars): cmake.configure() From 9466a2bb034203a1dc9c2cd121373a9d71e530d6 Mon Sep 17 00:00:00 2001 From: Ahajha <44127594+Ahajha@users.noreply.github.com> Date: Tue, 19 Mar 2024 20:54:57 -0400 Subject: [PATCH 099/102] Use autotools.install() directly Co-authored-by: Uilian Ries --- recipes/cpython/all/conanfile.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index db04b12fd03ec..489e1bea7e154 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -536,9 +536,7 @@ def package(self): self.output.info(f"{os.path.join(self.package_folder, 'lib')} exists, but it shouldn't.") rm(self, "lib", self.package_folder) autotools = Autotools(self) - # FIXME: Autotools.install() always adds DESTDIR, we don't want this argument. - # Use .make() directly instead - autotools.make(target="altinstall") + autotools.install(args=["DESTDIR="]) rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) rmdir(self, os.path.join(self.package_folder, "share")) From bc6d2321ac815689b91556586f76fec37791902b Mon Sep 17 00:00:00 2001 From: Ahajha Date: Tue, 19 Mar 2024 20:58:34 -0400 Subject: [PATCH 100/102] Remove outdated configure flags and some hacks --- recipes/cpython/all/conanfile.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 489e1bea7e154..539dfd7754e75 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -198,10 +198,6 @@ def _generate_autotools(self): tc.configure_args.append("--enable-loadable-sqlite-extensions={}".format( yes_no(not self.dependencies["sqlite3"].options.omit_load_extension) )) - if self.settings.compiler == "intel-cc": - tc.configure_args.append("--with-icc") - if os.environ.get("CC") or self.settings.compiler != "gcc": - tc.configure_args.append("--without-gcc") if self.options.with_tkinter: tcltk_includes = [] tcltk_libs = [] @@ -408,13 +404,7 @@ def build(self): self._msvc_build() else: autotools = Autotools(self) - # For debugging configure errors - try: - autotools.configure() - except ConanException: - with open(os.path.join(self.build_folder, "config.log"), 'r') as f: - self.output.info(f.read()) - raise + autotools.configure() autotools.make() @property @@ -531,10 +521,6 @@ def package(self): self._msvc_package_copy() rm(self, "vcruntime*", os.path.join(self.package_folder, "bin"), recursive=True) else: - if (os.path.isfile(os.path.join(self.package_folder, "lib"))): - # FIXME not sure where this file comes from - self.output.info(f"{os.path.join(self.package_folder, 'lib')} exists, but it shouldn't.") - rm(self, "lib", self.package_folder) autotools = Autotools(self) autotools.install(args=["DESTDIR="]) rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig")) From 3988348009e39e3deefefd32fca95577d9a26ae0 Mon Sep 17 00:00:00 2001 From: Ahajha Date: Tue, 19 Mar 2024 21:33:42 -0400 Subject: [PATCH 101/102] Add 2.0 versions of env variables --- recipes/cpython/all/conanfile.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 539dfd7754e75..41e66adf154be 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -679,6 +679,10 @@ def package_info(self): if self.options.env_vars: bindir = os.path.join(self.package_folder, "bin") + self.runenv_info.append_path("PATH", bindir) + self.buildenv_info.append_path("PATH", bindir) + + # TODO remove once Conan 1.x is no longer supported self.output.info(f"Appending PATH environment variable: {bindir}") self.env_info.PATH.append(bindir) @@ -686,6 +690,11 @@ def package_info(self): self.conf_info.define("user.cpython:python", python) self.user_info.python = python if self.options.env_vars: + self.runenv_info.append_path("PYTHON", python) + self.buildenv_info.append_path("PYTHON", python) + + # TODO remove once Conan 1.x is no longer supported + self.output.info(f"Appending PYTHON environment variable: {python}") self.env_info.PYTHON = python if is_msvc(self): @@ -701,11 +710,19 @@ def package_info(self): if is_msvc(self): if self.options.env_vars: + self.runenv_info.append_path("PYTHONHOME", pythonhome) + self.buildenv_info.append_path("PYTHONHOME", pythonhome) + + # TODO remove once Conan 1.x is no longer supported self.output.info(f"Setting PYTHONHOME environment variable: {pythonhome}") self.env_info.PYTHONHOME = pythonhome python_root = self.package_folder if self.options.env_vars: + self.runenv_info.append_path("PYTHON_ROOT", python_root) + self.buildenv_info.append_path("PYTHON_ROOT", python_root) + + # TODO remove once Conan 1.x is no longer supported self.output.info(f"Setting PYTHON_ROOT environment variable: {python_root}") self.env_info.PYTHON_ROOT = python_root self.conf_info.define("user.cpython:python_root", python_root) From c5fa0c5e567a1dd8e032f82376b95c057a40d1bb Mon Sep 17 00:00:00 2001 From: Alex Trotta Date: Wed, 20 Mar 2024 01:12:20 -0400 Subject: [PATCH 102/102] Remove PYTHONHOME from env info for now --- recipes/cpython/all/conanfile.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/recipes/cpython/all/conanfile.py b/recipes/cpython/all/conanfile.py index 41e66adf154be..160fe6920a426 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -710,8 +710,14 @@ def package_info(self): if is_msvc(self): if self.options.env_vars: - self.runenv_info.append_path("PYTHONHOME", pythonhome) - self.buildenv_info.append_path("PYTHONHOME", pythonhome) + # FIXME: On Windows, defining this breaks the packaged Python executable, but fixes + # separately built executables with an embedded interpreter trying to run standard Python + # modules. However, NOT defining this reverses the situation, normal Python executables + #work, but embedded interpreters break. + # The docs at https://python.readthedocs.io/en/latest/using/cmdline.html#envvar-PYTHONHOME + # seem to not be accurate to Windows (https://discuss.python.org/t/the-document-on-pythonhome-might-be-wrong/19614/5) + #self.runenv_info.append_path("PYTHONHOME", pythonhome) + #self.buildenv_info.append_path("PYTHONHOME", pythonhome) # TODO remove once Conan 1.x is no longer supported self.output.info(f"Setting PYTHONHOME environment variable: {pythonhome}")