1
1
import os
2
2
import 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"
4
8
5
9
6
10
# noinspection PyUnresolvedReferences
7
11
class EmbeddedPython (ConanFile ):
8
12
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
10
14
license = "PSFL"
11
15
description = "Embedded distribution of Python"
12
16
topics = "embedded" , "python"
@@ -50,23 +54,26 @@ def build_requirements(self):
50
54
if self .settings .os == "Windows" :
51
55
return
52
56
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" )
58
61
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" )
61
68
62
69
# The pre-conan-center-index version of `openssl` was capitalized as `OpenSSL`.
63
70
# Both versions can't live in the same Conan cache so we need this compatibility
64
71
# option to pick the available version. The cache case-sensitivity issue should
65
72
# be solved in Conan 2.0, but we need this for now.
66
73
if self .options .openssl_variant == "lowercase" :
67
- self .build_requires ("openssl/1.1.1k" )
74
+ self .tool_requires ("openssl/1.1.1k" )
68
75
else :
69
- self .build_requires ("OpenSSL/1.1.1f" )
76
+ self .tool_requires ("OpenSSL/1.1.1f" )
70
77
71
78
@property
72
79
def pyversion (self ):
@@ -129,7 +136,7 @@ def _gather_licenses(self, bootstrap):
129
136
)
130
137
131
138
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 ))
133
140
134
141
prefix = pathlib .Path (self .build_folder ) / "embedded_python"
135
142
if self .settings .os == "Windows" :
@@ -155,18 +162,18 @@ def build(self):
155
162
)
156
163
157
164
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 )
163
170
164
171
def package_info (self ):
165
172
self .env_info .PYTHONPATH .append (self .package_folder )
173
+ self .cpp_info .set_property ("cmake_build_modules" , ["embedded_python.cmake" ])
166
174
self .cpp_info .build_modules = ["embedded_python.cmake" ]
167
- self .user_info .pyversion = self .pyversion
168
-
169
175
prefix = pathlib .Path (self .package_folder ) / "embedded_python"
176
+ self .cpp_info .includedirs = [str (prefix / "include" )]
170
177
if self .settings .os == "Windows" :
171
178
self .cpp_info .bindirs = [str (prefix )]
172
179
else :
@@ -181,15 +188,15 @@ def __init__(self, conanfile, prefix_dir):
181
188
def _get_binaries (self , dest_dir ):
182
189
"""Get the binaries from the special embeddable Python package"""
183
190
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 )
185
192
186
193
def _get_headers_and_lib (self , dest_dir ):
187
194
"""We also need headers and the `python3.lib` file to link against"""
188
195
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" )
190
197
build_folder = self .conanfile .build_folder
191
198
self .conanfile .run (f"msiexec.exe /a { build_folder } \\ tmp\\ dev.msi targetdir={ dest_dir } " )
192
- tools . rmdir ("tmp" )
199
+ rmdir (self . conanfile , "tmp" )
193
200
194
201
def build_embedded (self ):
195
202
self ._get_binaries (self .prefix_dir )
@@ -198,7 +205,7 @@ def build_embedded(self):
198
205
def enable_site_packages (self ):
199
206
"""Enable site-packages, i.e. additional non-system packages"""
200
207
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" )
202
209
203
210
def build_bootstrap (self ):
204
211
"""Set up a special embedded Python environment for bootstrapping
@@ -217,7 +224,7 @@ def build_bootstrap(self):
217
224
218
225
# We need pip to install packages
219
226
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" )
221
228
self .conanfile .run (f"{ python_exe } get-pip.py" )
222
229
223
230
specs = [
@@ -237,15 +244,15 @@ def __init__(self, conanfile, prefix_dir):
237
244
238
245
def _get_source (self ):
239
246
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 )
242
248
243
249
# Patch a build issue with clang 13: https://bugs.python.org/issue45405. We simply apply
244
250
# the patch for all clang versions since the flag never did anything on clang/apple-clang anyway.
245
251
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" ,
249
256
"MULTIARCH=$($CC --print-multiarch 2>/dev/null)" ,
250
257
"MULTIARCH=''" ,
251
258
strict = False ,
@@ -260,32 +267,33 @@ def _openssl_path(self):
260
267
return self .conanfile .deps_cpp_info [pck ].rootpath
261
268
262
269
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" )
264
275
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 ])
267
281
268
282
# On Linux, we need to set RPATH so that `root/bin/python3` can correctly find the `.so`
269
283
# file in `root/lib` no matter where `root` is. We need it to be portable. We explicitly
270
284
# set `--disable-new-dtags` to use RPATH instead of RUNPATH. RUNPATH can be overridden by
271
285
# the LD_LIBRARY_PATH env variable which is not at all what we want for this self-contained
272
286
# package. Unlike RUNPATH, RPATH takes precedence over LD_LIBRARY_PATH.
273
287
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 ()
283
291
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`
289
297
290
298
ver = "." .join (self .conanfile .pyversion .split ("." )[:2 ])
291
299
exe = str (dest_dir / f"bin/python{ ver } " )
0 commit comments