diff --git a/.github/workflows/conan-package.yml b/.github/workflows/conan-package.yml index cb0e672..3318641 100644 --- a/.github/workflows/conan-package.yml +++ b/.github/workflows/conan-package.yml @@ -77,5 +77,5 @@ jobs: - name: Export changed recipes run: | mkdir runner_scripts - wget https://raw.githubusercontent.com/Ultimaker/cura-workflows/CURA-10831/runner_scripts/upload_conan_recipes.py -O runner_scripts/upload_conan_recipes.py + wget https://raw.githubusercontent.com/Ultimaker/cura-workflows/main/runner_scripts/upload_conan_recipes.py -O runner_scripts/upload_conan_recipes.py python runner_scripts/upload_conan_recipes.py --user ultimaker --branch ${{ github.ref_name }} --remote cura ${{ env.GIT_DIFF_FILTERED }} diff --git a/recipes/cpython/all/conandata.yml b/recipes/cpython/all/conandata.yml index 8d7da3f..8378a1d 100644 --- a/recipes/cpython/all/conandata.yml +++ b/recipes/cpython/all/conandata.yml @@ -19,68 +19,38 @@ sources: sha256: "da3080e3b488f648a3d7a4560ddee895284c3380b11d6de75edb986526b9a814" patches: "3.10.4": - - 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.4-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.4-0005-disable-macos-tcltk.patch" - patch_file: "patches/3.x-0001-relocatable-python-config.patch" - base_path: "source_subfolder" "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" + - 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" + - 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" + - 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 a0d341f..6aadc48 100644 --- a/recipes/cpython/all/conanfile.py +++ b/recipes/cpython/all/conanfile.py @@ -1,21 +1,29 @@ -from conans import AutoToolsBuildEnvironment, ConanFile, MSBuild, tools -from conans.errors import ConanInvalidConfiguration -from io import StringIO import os import re import textwrap -required_conan_version = ">=1.33.0" +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration, ConanException +from conan.tools.apple import is_apple_os, fix_apple_shared_install_name +from conan.tools.env import VirtualRunEnv +from conan.tools.files import apply_conandata_patches, copy, export_conandata_patches, get, mkdir, 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 MSBuildDeps, MSBuildToolchain, MSBuild, is_msvc, is_msvc_static_runtime, msvc_runtime_flag, msvs_toolset +from conan.tools.scm import Version + +required_conan_version = ">=1.58.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/**" + + package_type = "library" settings = "os", "arch", "compiler", "build_type" options = { "shared": [True, False], @@ -64,44 +72,31 @@ class CPythonConan(ConanFile): "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) - - @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 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": + if is_msvc(self): del self.options.lto del self.options.docstrings del self.options.pymalloc @@ -116,223 +111,299 @@ def config_options(self): del self.options.with_bsddb del self.options.unicode - del self.settings.compiler.libcxx - del self.settings.compiler.cppstd + self.settings.compiler.rm_safe("libcxx") + self.settings.compiler.rm_safe("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": - # The msbuild generator only works with Visual Studio - self.generators.append("MSBuildDeps") + self.options.rm_safe("with_bsddb") + self.options.rm_safe("with_lzma") - 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 layout(self): + basic_layout(self, src_folder="src") - def source(self): - tools.get(**self.conan_data["sources"][self.version], - destination=self._source_subfolder, strip_root=True) + @property + def _use_vendored_libffi(self): + # cpython < 3.8 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 Version(self.version) < "3.8" and is_msvc(self) @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 self._use_vendored_libffi def requirements(self): - self.requires("zlib/1.2.11") + self.requires("zlib/[>=1.2.11 <2]") if self._supports_modules: - self.requires("openssl/1.1.1w") - 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) < "3.8": self.requires("mpdecimal/2.4.2") - elif tools.Version(self._version_number_only) < "3.10": + elif Version(self.version) < "3.10" or is_apple_os(self): + # FIXME: mpdecimal > 2.5.0 on MacOS causes the _decimal module to not be importable self.requires("mpdecimal/2.5.0") else: - self.requires("mpdecimal/2.5.0") # FIXME: no 2.5.1 to troubleshoot apple + self.requires("mpdecimal/2.5.1") if self.settings.os != "Windows": - if not tools.is_apple_os(self.settings.os): + if not is_apple_os(self): self.requires("util-linux-libuuid/2.39.2") - self.requires("libxcrypt/4.4.25") + # If crypt.h is detected, it is included in the public headers. + self.requires("libxcrypt/4.4.36", transitive_headers=True, transitive_libs=True) 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.44.2") 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.3") + # 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): - self.requires("xz_utils/5.2.5") + self.requires("xz_utils/5.4.5") + + def package_id(self): + del self.info.options.env_vars + + 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 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) >= "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") + + if self._supports_modules: + if Version(self.version) < "3.8.0": + if self.dependencies["mpdecimal"].ref.version >= 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 < 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 msvc_runtime_flag(self): + raise ConanInvalidConfiguration("libffi versions >= 3.3 cause 'read access violations' when using a debug runtime (MTd/MDd)") + + if is_apple_os(self) and self.settings.arch == "armv8" and Version(self.version) < "3.8.0": + raise ConanInvalidConfiguration("cpython 3.7 and older does not support Apple ARM CPUs") - 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 source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def _generate_autotools(self): + tc = AutotoolsToolchain(self, prefix=self.package_folder) 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", - "--with-system-ffi", "--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 not self._use_vendored_libffi: + tc.configure_args += ["--with-system-ffi"] 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: + 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(["-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") + + tc.generate() + + deps = AutotoolsDeps(self) + deps.generate() - build = None - if tools.cross_building(self) and not tools.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 + def generate(self): + VirtualRunEnv(self).generate(scope="build") + + if is_msvc(self): + # The msbuild generator only works with Visual Studio + deps = MSBuildDeps(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() 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) + setup_py = os.path.join(self.source_folder, "setup.py") + if self._is_py3 and Version(self.version) < "3.10": + replace_in_file(self, 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.aggregated_components() + replace_in_file(self, setup_py, + "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() + if self._is_py3: + replace_in_file(self, setup_py, + "openssl_includes = ", + f"openssl_includes = {openssl.includedirs + zlib.includedirs} #") + replace_in_file(self, setup_py, + "openssl_libdirs = ", + f"openssl_libdirs = {openssl.libdirs + zlib.libdirs} #") + replace_in_file(self, setup_py, + "openssl_libs = ", + f"openssl_libs = {openssl.libs + zlib.libs} #") + else: + replace_in_file(self, setup_py, "'/usr/local/ssl/include',", f"{(openssl.includedirs + zlib.includedirs)[1:-2]}") + replace_in_file(self, setup_py, "'/usr/contrib/ssl/include/'", "") + replace_in_file(self, setup_py, "lib_dirs = []", f"lib_dirs = {openssl.libdirs + zlib.libdirs}") + replace_in_file(self, setup_py, "libraries = ['ssl', 'crypto'],", f"libraries = {openssl.libs + zlib.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)") - - 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. - """ - 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")) + 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)") + + # 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'', + ) + + for project in ["python", "pythonw"]: + replace_in_file(self, os.path.join(self.source_folder, "PCbuild", f"{project}.vcxproj"), + '', + f'') @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: @@ -341,24 +412,20 @@ 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" + return ["pythoncore", "python", "pythonw"] @property def _msvc_discarded_projects(self): - discarded = {"python_uwp", "pythonw_uwp"} + discarded = { + "python_uwp", + "pythonw_uwp", + "_freeze_importlib", + "sqlite3", + "bdist_wininst", + } if not self.options.with_bz2: discarded.add("bz2") if not self.options.with_sqlite3: @@ -367,11 +434,21 @@ 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({ + "libeay", + "ssleay", + "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({ + "liblzma", + "openssl", + "xxlimited", + }) if not self.options.with_lzma: discarded.add("_lzma") return discarded @@ -382,7 +459,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,39 +469,33 @@ def _msvc_archs(self): def _msvc_build(self): msbuild = MSBuild(self) - msbuild_properties = { - "IncludeExternals": "true", - } + msbuild.platform = self._msvc_archs[str(self.settings.arch)] + projects = self._solution_projects - self.output.info("Building {} Visual Studio projects: {}".format(len(projects), projects)) + self.output.info(f"Building {len(projects)} Visual Studio 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) + sln = os.path.join(self.source_folder, "PCbuild", "pcbuild.sln") + if Version(self.version) > "3.8.0": + msbuild.build(sln, targets=projects) + else: + # In these versions, solution files do not pick up the toolset automatically. + # All of these versions are EOL, so a hacky solution is fine for now. + cmd = msbuild.command(sln, targets=projects) + self.run(f"{cmd} /p:PlatformToolset={msvs_toolset(self)}") 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() + 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.make() @property @@ -433,59 +504,58 @@ 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", "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", "--include-pip", "--include-venv", "--include-dev", - "--include-stable", ] if self.options.with_tkinter: 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): @@ -499,45 +569,67 @@ 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(version) > Version(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) + 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): - 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.install() - tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig")) - tools.rmdir(os.path.join(self.package_folder, "share")) + 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) + # FIXME: Autotools.install() always adds DESTDIR, we don't want this argument. + # Use .make() directly instead + autotools.make(target="altinstall") + 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")): @@ -551,23 +643,23 @@ def package(self): 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) - self._fix_install_name() + os.symlink(f"python{self._version_suffix}", self._cpython_symlink) + fix_apple_shared_install_name(self) @property def _cpython_symlink(self): @@ -578,14 +670,12 @@ def _cpython_symlink(self): @property def _cpython_interpreter_name(self): - if self.settings.compiler == "Visual Studio": - suffix = "" - else: - suffix = self._version_suffix - python = "python{}".format(suffix) - if self.settings.compiler == "Visual Studio": + python = "python" + if is_msvc(self): if self.settings.build_type == "Debug": python += "_d" + else: + python += self._version_suffix if self.settings.os == "Windows": python += ".exe" return python @@ -600,34 +690,23 @@ 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: 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) - - def _fix_install_name(self): - if tools.is_apple_os(self.settings.os) 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:] - 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)) + 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 package_info(self): # FIXME: conan components Python::Interpreter component, need a target type @@ -635,40 +714,53 @@ 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: - 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"].includedirs = [] 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"].includedirs = [] + 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"].includedirs = [] + 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: @@ -682,7 +774,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("util-linux-libuuid::util-linux-libuuid") self.cpp_info.components["_hidden"].requires.append("libxcrypt::libxcrypt") if self.options.with_bz2: @@ -699,34 +791,34 @@ def package_info(self): self.cpp_info.components["_hidden"].requires.append("xz_utils::xz_utils") if self.options.get_safe("with_tkinter"): self.cpp_info.components["_hidden"].requires.append("tk::tk") + self.cpp_info.components["_hidden"].includedirs = [] self.cpp_info.components["_hidden"].libdirs = [] 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): - 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)) + pythonhome = self.package_folder + 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: @@ -734,6 +826,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 96% 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 index 2c10104..c87be88 100644 --- a/recipes/cpython/all/patches/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/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 94% 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 index e9b1faf..9884e12 100644 --- a/recipes/cpython/all/patches/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 @@ - +