Skip to content

Commit 65faa70

Browse files
hellozeedean0x7d
andcommitted
conan: Migrate to conan v2 tools
Co-authored-by: Dean Moldovan <[email protected]>
1 parent 8f79a19 commit 65faa70

File tree

6 files changed

+77
-73
lines changed

6 files changed

+77
-73
lines changed

.github/workflows/test_package.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
echo CXX=/usr/bin/clang++ >> $GITHUB_ENV
2525
- name: Install Conan
2626
run: |
27-
python -m pip install conan==1.53
27+
python -m pip install conan==1.59
2828
conan config set general.revisions_enabled=True
2929
conan profile new default --detect
3030
conan profile update settings.compiler.cppstd=17 default

changelog.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Changelog
22

3-
## v1.4.6 | In progress
3+
## v1.5.0 | 2023-02-28
44

55
- Fixed symlink re-creation, in case already existing symlink was invalid
6+
- Updated to conan v2 methods
67

78
## v1.4.5 | 2022-07-15
89

conanfile.py

+54-46
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import os
22
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"
48

59

610
# noinspection PyUnresolvedReferences
711
class 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}")

embedded_python_tools.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import shutil
33
import pathlib
4+
from conan.tools.files import copy
45

56

67
def _symlink_compat(conanfile, src, dst):
@@ -52,7 +53,7 @@ def imports(self):
5253
_symlink_compat(conanfile, src, dst)
5354

5455
bin = pathlib.Path(bin).absolute()
55-
conanfile.copy("python*.dll", dst=bin, src="embedded_python", keep_path=False)
56-
conanfile.copy("libpython*.so*", dst=bin, src="embedded_python/lib", keep_path=False)
57-
conanfile.copy("libpython*.dylib", dst=bin, src="embedded_python/lib", keep_path=False)
58-
conanfile.copy("python*.zip", dst=bin, src="embedded_python", keep_path=False)
56+
copy(conanfile, "python*.dll", src, bin, keep_path=False)
57+
copy(conanfile, "libpython*.so*", src / "lib", bin, keep_path=False)
58+
copy(conanfile, "libpython*.dylib", src / "lib", bin, keep_path=False)
59+
copy(conanfile, "python*.zip", src, bin, keep_path=False)

test_package/CMakeLists.txt

+2-13
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
cmake_minimum_required(VERSION 3.18)
22
project(test_package)
33

4-
# `cmake` generator
5-
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
6-
conan_basic_setup(KEEP_RPATHS)
7-
8-
if(NOT Python_VERSION VERSION_EQUAL CONAN_USER_EMBEDDED_PYTHON_pyversion)
9-
message(FATAL_ERROR "`cmake` failed to find the correct Python version")
10-
endif()
11-
12-
# `cmake_find_package` generator
13-
unset(Python_ROOT_DIR)
14-
unset(Python_VERSION)
154
find_package(embedded_python)
165

17-
if(NOT Python_VERSION VERSION_EQUAL CONAN_USER_EMBEDDED_PYTHON_pyversion)
18-
message(FATAL_ERROR "`cmake_find_package` failed to find the correct Python version")
6+
if(NOT Python_EXECUTABLE MATCHES "embedded_python")
7+
message(FATAL_ERROR "`cmake` failed to find the correct Python")
198
endif()
209

2110
add_executable(test_package src/main.cpp)

test_package/conanfile.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pathlib
22
import sys
3-
from conans import ConanFile, CMake
3+
from conan import ConanFile
4+
from conan.tools.cmake import CMake, CMakeToolchain
45

56
project_root = pathlib.Path(__file__).parent
67

@@ -14,7 +15,7 @@ def _read_env(name):
1415
class TestEmbeddedPython(ConanFile):
1516
name = "test_embedded_python"
1617
settings = "os", "compiler", "build_type", "arch"
17-
generators = "cmake", "cmake_find_package"
18+
generators = "CMakeDeps"
1819
options = {"env": "ANY"}
1920
default_options = {
2021
"env": None,
@@ -25,13 +26,17 @@ def configure(self):
2526
if self.options.env:
2627
self.options["embedded_python"].packages = _read_env(self.options.env)
2728

28-
def imports(self):
29+
def generate(self):
30+
build_type = self.settings.build_type.value
31+
tc = CMakeToolchain(self)
32+
tc.variables[f"CMAKE_RUNTIME_OUTPUT_DIRECTORY_{build_type.upper()}"] = "bin"
33+
tc.generate()
34+
35+
def build(self):
2936
import embedded_python_tools
3037

3138
embedded_python_tools.symlink_import(self, dst="bin/python")
32-
self.copy("licenses/*", dst="licenses", folder=True, ignore_case=True, keep_path=False)
3339

34-
def build(self):
3540
cmake = CMake(self)
3641
cmake.configure()
3742
cmake.build()
@@ -43,18 +48,18 @@ def _test_env(self):
4348
else:
4449
python_exe = str(pathlib.Path("./bin/python/bin/python3").resolve())
4550

46-
self.run([python_exe, "-c", "import sys; print(sys.version);"])
51+
self.run(f'{python_exe} -c "import sys; print(sys.version);"')
4752

4853
name = str(self.options.env) if self.options.env else "baseline"
49-
self.run([python_exe, str(project_root / f"{name}/test.py")], run_environment=True)
54+
self.run(f"{python_exe} {project_root / name / 'test.py'}", run_environment=True)
5055

5156
def _test_embed(self):
5257
"""Ensure that everything is available to compile and link to the embedded Python"""
5358
self.run(pathlib.Path("bin", "test_package"), run_environment=True)
5459

5560
def _test_licenses(self):
5661
"""Ensure that the licenses have been gathered"""
57-
license_dir = pathlib.Path("./licenses/embedded_python")
62+
license_dir = pathlib.Path(self.deps_cpp_info["embedded_python"].rootpath, "licenses")
5863
license_files = [license_dir / "LICENSE.txt"]
5964
if self.options.env:
6065
license_files += [license_dir / "package_licenses.txt"]

0 commit comments

Comments
 (0)