11import os
22import pathlib
3- from conans import ConanFile , tools
3+ from conan import ConanFile
4+ from conan .tools .files import get , replace_in_file , download , rmdir , copy
5+ from conan .tools .scm import Version
6+
7+ required_conan_version = ">=1.56.0"
48
59
610# noinspection PyUnresolvedReferences
711class EmbeddedPython (ConanFile ):
812 name = "embedded_python"
9- version = "1.4.5 " # of the Conan package, `options.version` is the Python version
13+ version = "1.5.0 " # of the Conan package, `options.version` is the Python version
1014 license = "PSFL"
1115 description = "Embedded distribution of Python"
1216 topics = "embedded" , "python"
@@ -50,23 +54,26 @@ def build_requirements(self):
5054 if self .settings .os == "Windows" :
5155 return
5256
53- self .build_requires ("sqlite3/3.35.5" )
54- self .build_requires ("bzip2/1.0.8" )
55- self .build_requires ("xz_utils/5.2.5" )
56- self .build_requires ("mpdecimal/2.4.2" )
57- self .build_requires ("zlib/1.2.11" )
57+ self .tool_requires ("sqlite3/3.35.5" )
58+ self .tool_requires ("bzip2/1.0.8" )
59+ self .tool_requires ("xz_utils/5.2.5" )
60+ self .tool_requires ("zlib/1.2.11" )
5861 if self .settings .os == "Linux" :
59- self .build_requires ("libffi/3.4.2" )
60- self .build_requires ("libuuid/1.0.3" )
62+ self .tool_requires ("libffi/3.4.2" )
63+ self .tool_requires ("libuuid/1.0.3" )
64+ if Version (self .pyversion ) < "3.8" :
65+ self .tool_requires ("mpdecimal/2.4.2" )
66+ else :
67+ self .tool_requires ("mpdecimal/2.5.0" )
6168
6269 # The pre-conan-center-index version of `openssl` was capitalized as `OpenSSL`.
6370 # Both versions can't live in the same Conan cache so we need this compatibility
6471 # option to pick the available version. The cache case-sensitivity issue should
6572 # be solved in Conan 2.0, but we need this for now.
6673 if self .options .openssl_variant == "lowercase" :
67- self .build_requires ("openssl/1.1.1k" )
74+ self .tool_requires ("openssl/1.1.1k" )
6875 else :
69- self .build_requires ("OpenSSL/1.1.1f" )
76+ self .tool_requires ("OpenSSL/1.1.1f" )
7077
7178 @property
7279 def pyversion (self ):
@@ -129,7 +136,7 @@ def _gather_licenses(self, bootstrap):
129136 )
130137
131138 def build (self ):
132- tools . replace_in_file ("embedded_python.cmake" , "${self.pyversion}" , str (self .pyversion ))
139+ replace_in_file (self , "embedded_python.cmake" , "${self.pyversion}" , str (self .pyversion ))
133140
134141 prefix = pathlib .Path (self .build_folder ) / "embedded_python"
135142 if self .settings .os == "Windows" :
@@ -155,18 +162,18 @@ def build(self):
155162 )
156163
157164 def package (self ):
158- self . copy ( "embedded_python/*" , keep_path = True )
159- self . copy ( "embedded_python_tools.py " )
160- self . copy ("embedded_python.cmake" )
161- self . copy ("embedded_python/LICENSE.txt" , dst = "licenses" , keep_path = False )
162- self . copy ("package_licenses.txt" , dst = "licenses" )
165+ src = self . build_folder
166+ license_folder = pathlib . Path ( self . package_folder , "licenses " )
167+ copy (self , "embedded_python*" , src , self . package_folder )
168+ copy (self , "embedded_python/LICENSE.txt" , src , license_folder , keep_path = False )
169+ copy (self , "package_licenses.txt" , src , license_folder , keep_path = False )
163170
164171 def package_info (self ):
165172 self .env_info .PYTHONPATH .append (self .package_folder )
173+ self .cpp_info .set_property ("cmake_build_modules" , ["embedded_python.cmake" ])
166174 self .cpp_info .build_modules = ["embedded_python.cmake" ]
167- self .user_info .pyversion = self .pyversion
168-
169175 prefix = pathlib .Path (self .package_folder ) / "embedded_python"
176+ self .cpp_info .includedirs = [str (prefix / "include" )]
170177 if self .settings .os == "Windows" :
171178 self .cpp_info .bindirs = [str (prefix )]
172179 else :
@@ -181,15 +188,15 @@ def __init__(self, conanfile, prefix_dir):
181188 def _get_binaries (self , dest_dir ):
182189 """Get the binaries from the special embeddable Python package"""
183190 url = "https://www.python.org/ftp/python/{0}/python-{0}-embed-amd64.zip"
184- tools . get (url .format (self .conanfile .pyversion ), destination = dest_dir )
191+ get (self . conanfile , url .format (self .conanfile .pyversion ), destination = dest_dir )
185192
186193 def _get_headers_and_lib (self , dest_dir ):
187194 """We also need headers and the `python3.lib` file to link against"""
188195 url = f"https://www.python.org/ftp/python/{ self .conanfile .pyversion } /amd64/dev.msi"
189- tools . download (url , filename = "tmp\\ dev.msi" )
196+ download (self . conanfile , url , filename = "tmp\\ dev.msi" )
190197 build_folder = self .conanfile .build_folder
191198 self .conanfile .run (f"msiexec.exe /a { build_folder } \\ tmp\\ dev.msi targetdir={ dest_dir } " )
192- tools . rmdir ("tmp" )
199+ rmdir (self . conanfile , "tmp" )
193200
194201 def build_embedded (self ):
195202 self ._get_binaries (self .prefix_dir )
@@ -198,7 +205,7 @@ def build_embedded(self):
198205 def enable_site_packages (self ):
199206 """Enable site-packages, i.e. additional non-system packages"""
200207 dst = self .prefix_dir / f"python{ self .conanfile .pyver } ._pth"
201- tools . replace_in_file (dst , "#import site" , "import site" )
208+ replace_in_file (self . conanfile , dst , "#import site" , "import site" )
202209
203210 def build_bootstrap (self ):
204211 """Set up a special embedded Python environment for bootstrapping
@@ -217,7 +224,7 @@ def build_bootstrap(self):
217224
218225 # We need pip to install packages
219226 python_exe = build_folder / "bootstrap/python.exe"
220- tools . download ("https://bootstrap.pypa.io/get-pip.py" , filename = "get-pip.py" )
227+ download (self . conanfile , "https://bootstrap.pypa.io/get-pip.py" , filename = "get-pip.py" )
221228 self .conanfile .run (f"{ python_exe } get-pip.py" )
222229
223230 specs = [
@@ -237,15 +244,15 @@ def __init__(self, conanfile, prefix_dir):
237244
238245 def _get_source (self ):
239246 url = f"https://github.com/python/cpython/archive/v{ self .conanfile .pyversion } .tar.gz"
240- tools .get (url )
241- os .rename (f"cpython-{ self .conanfile .pyversion } " , "src" )
247+ get (self .conanfile , url , strip_root = True )
242248
243249 # Patch a build issue with clang 13: https://bugs.python.org/issue45405. We simply apply
244250 # the patch for all clang versions since the flag never did anything on clang/apple-clang anyway.
245251 compiler = self .conanfile .settings .compiler
246- if "clang" in str (compiler ) and tools .Version (self .conanfile .pyversion ) < "3.9.8" :
247- tools .replace_in_file (
248- "src/configure" ,
252+ if "clang" in str (compiler ) and Version (self .conanfile .pyversion ) < "3.9.8" :
253+ replace_in_file (
254+ self .conanfile ,
255+ "configure" ,
249256 "MULTIARCH=$($CC --print-multiarch 2>/dev/null)" ,
250257 "MULTIARCH=''" ,
251258 strict = False ,
@@ -260,32 +267,33 @@ def _openssl_path(self):
260267 return self .conanfile .deps_cpp_info [pck ].rootpath
261268
262269 def _build (self , dest_dir ):
263- from conans import AutoToolsBuildEnvironment
270+ from conan .tools .gnu import AutotoolsToolchain , Autotools
271+
272+ tc = AutotoolsToolchain (self .conanfile , prefix = dest_dir )
273+ tc .configure_args .extend (["--enable-shared" , f"--with-openssl={ self ._openssl_path } " ])
274+ tc .make_args .append ("-j8" )
264275
265- autotools = AutoToolsBuildEnvironment (self .conanfile )
266- env_vars = autotools .vars
276+ # We need to do this manually because `AutotoolsDeps` doesn't add `tools_requires` deps
277+ for dep in self .conanfile .deps_cpp_info .deps :
278+ info = self .conanfile .deps_cpp_info [dep ]
279+ tc .extra_cflags .extend ([f"-I{ x } " for x in info .include_paths ])
280+ tc .extra_ldflags .extend ([f"-L{ x } " for x in info .lib_paths ])
267281
268282 # On Linux, we need to set RPATH so that `root/bin/python3` can correctly find the `.so`
269283 # file in `root/lib` no matter where `root` is. We need it to be portable. We explicitly
270284 # set `--disable-new-dtags` to use RPATH instead of RUNPATH. RUNPATH can be overridden by
271285 # the LD_LIBRARY_PATH env variable which is not at all what we want for this self-contained
272286 # package. Unlike RUNPATH, RPATH takes precedence over LD_LIBRARY_PATH.
273287 if self .conanfile .settings .os == "Linux" :
274- env_vars ["LDFLAGS" ] += " -Wl,-rpath,'$$ORIGIN/../lib' -Wl,--disable-new-dtags"
275-
276- config_args = " " .join (
277- [
278- "--enable-shared" ,
279- f"--prefix={ dest_dir } " ,
280- f"--with-openssl={ self ._openssl_path } " ,
281- ]
282- )
288+ tc .extra_ldflags .extend (["-Wl,-rpath,'$$ORIGIN/../lib'" , "-Wl,--disable-new-dtags" ])
289+
290+ tc .generate ()
283291
284- tools . mkdir ( "./build" )
285- with tools . chdir ( "./build" ), tools . environment_append ( env_vars ):
286- self . conanfile . run ( f"../src/ configure { config_args } " )
287- self . conanfile . run ( " make -j8" )
288- self . conanfile . run ( "make install -j8" )
292+ with tc . environment (). vars ( self . conanfile ). apply ():
293+ autotools = Autotools ( self . conanfile )
294+ autotools . configure ( )
295+ autotools . make ( )
296+ autotools . install ( args = [ "DESTDIR=''" ]) # already handled by `prefix=dest_dir`
289297
290298 ver = "." .join (self .conanfile .pyversion .split ("." )[:2 ])
291299 exe = str (dest_dir / f"bin/python{ ver } " )
0 commit comments