Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
dean0x7d committed Jun 13, 2024
1 parent 979e81e commit 2cb3466
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 50 deletions.
8 changes: 8 additions & 0 deletions core/embedded_python-core.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@ else()
endif()

find_package(Python ${self.pyversion} EXACT REQUIRED GLOBAL COMPONENTS Interpreter Development)

set(pth_file ".embedded_python-core.pth")
if(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(pth_file ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${pth_file})
endif()
file(GENERATE OUTPUT ${pth_file} CONTENT "${Python_ROOT_DIR}")

unset(pth_file)
29 changes: 8 additions & 21 deletions core/test_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import subprocess
import conan
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.cmake import CMake, cmake_layout


# noinspection PyUnresolvedReferences
class TestEmbeddedPythonCore(ConanFile):
name = "test_embedded_python"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps", "VirtualRunEnv"
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"
test_type = "explicit"

def layout(self):
Expand All @@ -19,18 +19,7 @@ def layout(self):
def requirements(self):
self.requires(self.tested_reference_str)

def generate(self):
build_type = self.settings.build_type.value
tc = CMakeToolchain(self)
tc.variables[f"CMAKE_RUNTIME_OUTPUT_DIRECTORY_{build_type.upper()}"] = "bin"
tc.generate()

def build(self):
sys.path.append(str(self._core_package_path))

import embedded_python_tools

embedded_python_tools.symlink_import(self, dst="bin/python")
cmake = CMake(self)
cmake.configure(
variables={
Expand All @@ -42,20 +31,18 @@ def build(self):
)
cmake.build()

@property
def _py_exe(self):
if self.settings.os == "Windows":
return pathlib.Path(self.build_folder, "bin/python/python.exe")
else:
return pathlib.Path(self.build_folder, "bin/python/bin/python3")

@property
def _core_package_path(self):
if conan.__version__.startswith("2"):
return pathlib.Path(self.dependencies["embedded_python-core"].package_folder)
else:
return pathlib.Path(self.deps_cpp_info["embedded_python-core"].rootpath)

@property
def _py_exe(self):
exe = "python.exe" if sys.platform == "win32" else "python3"
return self._core_package_path / "embedded_python" / exe

def _test_stdlib(self):
"""Ensure that Python runs and built the optional stdlib modules"""
self.run(f'{self._py_exe} -c "import sys; print(sys.version);"')
Expand All @@ -78,7 +65,7 @@ def _test_libpython_path(self):

def _test_embed(self):
"""Ensure that everything is available to compile and link to the embedded Python"""
self.run(pathlib.Path("bin", "test_package"), env="conanrun")
self.run(pathlib.Path(self.cpp.build.bindir, "test_package").absolute(), env="conanrun")

def _test_licenses(self):
"""Ensure that the license file is included"""
Expand Down
9 changes: 8 additions & 1 deletion core/test_package/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
#include <Python.h>
#include <iostream>
#include <fstream>
#include <filesystem>

int main(int argc, const char* argv[]) {
auto config = PyConfig{};
PyConfig_InitIsolatedConfig(&config);

const auto bin = std::filesystem::path(argv[0]).parent_path();
const auto python_home = (bin / "python").string();
auto pth_file = bin / ".embedded_python.pth";
if (!std::filesystem::exists(pth_file)) {
pth_file = bin / ".embedded_python-core.pth";
}
auto pth_stream = std::ifstream(pth_file);
const auto python_home = std::string(std::istreambuf_iterator<char>(pth_stream),
std::istreambuf_iterator<char>());
if (auto status = PyConfig_SetBytesString(&config, &config.home, python_home.c_str());
PyStatus_Exception(status)) {
PyConfig_Clear(&config);
Expand Down
14 changes: 11 additions & 3 deletions embedded_python.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@
# library. On top of that, `embedded_python.cmake` adds `EmbeddedPython_EXECUTABLE` which is aware
# of the full environment with `pip` packages. Note that we do no provide any include or lib dirs
# since those are already provided by `core`.

set(EmbeddedPython_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/embedded_python" CACHE STRING "" FORCE)
if(WIN32)
set(EmbeddedPython_EXECUTABLE "${CMAKE_CURRENT_LIST_DIR}/embedded_python/python.exe" CACHE STRING "" FORCE)
set(EmbeddedPython_EXECUTABLE "${EmbeddedPython_ROOT_DIR}/python.exe" CACHE STRING "" FORCE)
else()
set(EmbeddedPython_EXECUTABLE "${CMAKE_CURRENT_LIST_DIR}/embedded_python/python3" CACHE STRING "" FORCE)
set(EmbeddedPython_EXECUTABLE "${EmbeddedPython_ROOT_DIR}/python3" CACHE STRING "" FORCE)
endif()

set(pth_file ".embedded_python.pth")
if(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(pth_file ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${pth_file})
endif()
file(GENERATE OUTPUT ${pth_file} CONTENT "${EmbeddedPython_ROOT_DIR}")

unset(pth_file)
38 changes: 13 additions & 25 deletions test_package/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import subprocess
import conan
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.cmake import CMake, cmake_layout

project_root = pathlib.Path(__file__).parent

Expand All @@ -17,7 +17,7 @@ def _read_env(name):
class TestEmbeddedPython(ConanFile):
name = "test_embedded_python"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps", "VirtualRunEnv"
generators = "CMakeToolchain", "CMakeDeps", "VirtualRunEnv"
options = {"env": [None, "ANY"]}
default_options = {
"env": None,
Expand All @@ -38,6 +38,11 @@ def _package_path(self):
else:
return pathlib.Path(self.deps_cpp_info["embedded_python"].rootpath)

@property
def _py_exe(self):
exe = "python.exe" if sys.platform == "win32" else "python3"
return self._package_path / "embedded_python" / exe

def layout(self):
cmake_layout(self)

Expand All @@ -48,19 +53,7 @@ def configure(self):
if self.options.env:
self.options["embedded_python"].packages = _read_env(self.options.env)

def generate(self):
build_type = self.settings.build_type.value
tc = CMakeToolchain(self)
tc.variables[f"CMAKE_RUNTIME_OUTPUT_DIRECTORY_{build_type.upper()}"] = "bin"
tc.generate()

def build(self):
sys.path.append(str(self._package_path))

import embedded_python_tools

embedded_python_tools.symlink_import(self, dst="bin/python")

cmake = CMake(self)
cmake.configure(
variables={
Expand All @@ -75,22 +68,17 @@ def build(self):

def _test_env(self):
"""Ensure that Python runs and finds the installed environment"""
if self.settings.os == "Windows":
python_exe = str(pathlib.Path("./bin/python/python").resolve())
else:
python_exe = str(pathlib.Path("./bin/python/bin/python3").resolve())

self.run(f'{python_exe} -c "import sys; print(sys.version);"')

self.run(f'{self._py_exe} -c "import sys; print(sys.version);"')
name = str(self.options.env) if self.options.env else "baseline"
self.run(f"{python_exe} {project_root / name / 'test.py'}", env="conanrun")
self.run(f"{self._py_exe} {project_root / name / 'test.py'}", env="conanrun")

def _test_libpython_path(self):
if self.settings.os != "Macos":
return

python_exe = str(pathlib.Path("./bin/python/bin/python3").resolve())
p = subprocess.run(["otool", "-L", python_exe], check=True, text=True, capture_output=True)
p = subprocess.run(
["otool", "-L", self._py_exe], check=True, text=True, capture_output=True
)
lines = str(p.stdout).strip().split("\n")[1:]
libraries = [line.split()[0] for line in lines]
candidates = [lib for lib in libraries if "libpython" in lib]
Expand All @@ -101,7 +89,7 @@ def _test_libpython_path(self):

def _test_embed(self):
"""Ensure that everything is available to compile and link to the embedded Python"""
self.run(pathlib.Path("bin", "test_package"), env="conanrun")
self.run(pathlib.Path(self.cpp.build.bindir, "test_package").absolute(), env="conanrun")

def _test_licenses(self):
"""Ensure that the licenses have been gathered"""
Expand Down

0 comments on commit 2cb3466

Please sign in to comment.