Skip to content

Commit 14c3db2

Browse files
committed
Define EmbeddedPython_EXECUTABLE CMake variable
Previously, there was no way to access the Python executable that was aware of the full environment with `pip` packages. See the comment in `embedde_python.cmake` for more details about the core/full split.
1 parent b4d5d5f commit 14c3db2

7 files changed

+41
-10
lines changed

changelog.md

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

3-
## v1.8.0 | In development
3+
## v1.8.0 | 2023-07-12
44

55
- Added support for building with `openssl` v3 for Python 3.10 and newer.
66
- `openssl` v3.0.8 is now the default for Python >= 3.10 and `openssl` v1.1.1u is the default for Python 3.9.
77
- The `openssl_variant` is now obsolete. The flag is still there for backwards compatibility but it no longer does anything.
8+
- The `EmbeddedPython_EXECUTABLE` CMake variable is now defined and points to the executable that's aware of the full embedded Python environment with `pip` packages. `Python_EXECUTABLE` points to the `core` executable that's only aware of the standard library. This split ensures that we compile and link against `core` in order to avoid rebuilding the world when only the Python environment packages change but the version/headers/libs stay the same.
89

910
## v1.7.0 | 2023-06-22
1011

conanfile.py

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class EmbeddedPython(ConanFile):
3535
"openssl_variant": "lowercase",
3636
}
3737
short_paths = True # some of the pip packages go over the 260 char path limit on Windows
38+
exports_sources = "embedded_python.cmake"
3839

3940
def requirements(self):
4041
self.requires(f"embedded_python-core/1.2.0@{self.user}/{self.channel}")
@@ -172,6 +173,7 @@ def build(self):
172173
self._build_bootstrap()
173174

174175
def package(self):
176+
files.copy(self, "embedded_python.cmake", src=self.build_folder, dst=self.package_folder)
175177
files.copy(self, "embedded_python*", src=self.core_pkg, dst=self.package_folder)
176178
prefix = pathlib.Path(self.package_folder, "embedded_python")
177179
if self.settings.os == "Windows":

core/conanfile.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class EmbeddedPythonCore(ConanFile):
2626
default_options = {
2727
"zip_stdlib": "stored",
2828
}
29-
exports_sources = "embedded_python_tools.py", "embedded_python.cmake"
29+
exports_sources = "embedded_python_tools.py", "embedded_python-core.cmake"
3030

3131
def validate(self):
3232
minimum_python = "3.9.8"
@@ -87,7 +87,7 @@ def int_pyversion(self):
8787

8888
def generate(self):
8989
files.replace_in_file(
90-
self, "embedded_python.cmake", "${self.pyversion}", str(self.pyversion)
90+
self, "embedded_python-core.cmake", "${self.pyversion}", str(self.pyversion)
9191
)
9292
if self.settings.os == "Windows":
9393
return
@@ -236,7 +236,7 @@ def is_landmark(filepath):
236236
def package(self):
237237
src = self.build_folder
238238
dst = pathlib.Path(self.package_folder, "embedded_python")
239-
files.copy(self, "embedded_python.cmake", src, dst=self.package_folder)
239+
files.copy(self, "embedded_python-core.cmake", src, dst=self.package_folder)
240240
files.copy(self, "embedded_python_tools.py", src, dst=self.package_folder)
241241
license_folder = pathlib.Path(self.package_folder, "licenses")
242242

@@ -278,8 +278,8 @@ def package(self):
278278

279279
def package_info(self):
280280
self.env_info.PYTHONPATH.append(self.package_folder)
281-
self.cpp_info.set_property("cmake_build_modules", ["embedded_python.cmake"])
282-
self.cpp_info.build_modules = ["embedded_python.cmake"]
281+
self.cpp_info.set_property("cmake_build_modules", ["embedded_python-core.cmake"])
282+
self.cpp_info.build_modules = ["embedded_python-core.cmake"]
283283
prefix = pathlib.Path(self.package_folder) / "embedded_python"
284284
self.cpp_info.includedirs = [str(prefix / "include")]
285285
if self.settings.os == "Windows":

core/embedded_python.cmake core/embedded_python-core.cmake

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ set(Python_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/embedded_python")
33

44
if(WIN32) # Extra hint to speed up the find (not needed for correctness)
55
set(Python_EXECUTABLE "${Python_ROOT_DIR}/python.exe")
6+
else()
7+
set(Python_EXECUTABLE "${Python_ROOT_DIR}/bin/python3")
68
endif()
79

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

core/test_package/CMakeLists.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ project(test_package)
33

44
find_package(embedded_python-core)
55

6-
if(NOT Python_EXECUTABLE MATCHES "embedded_python")
7-
message(FATAL_ERROR "`cmake` failed to find the correct Python")
6+
message(STATUS "Python_EXECUTABLE: ${Python_EXECUTABLE}")
7+
if(NOT Python_EXECUTABLE MATCHES "embedded_python-core")
8+
message(FATAL_ERROR "CMake failed to find the correct Python")
89
endif()
910

1011
add_executable(test_package src/main.cpp)

embedded_python.cmake

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# There is one important thing we want to achieve with the `embedded_python`/`embedded_python-core`
2+
# split: we want to avoid recompiling the world when only the Python environment packages change
3+
# but the version/headers/libs stay the same. To do that we must ensure that everything is built
4+
# against `embedded_python-core` while the full `embedded_python` is provided for runtime.
5+
#
6+
# `embedded_python-core.cmake` calls `find_package(Python Interpreter Development)` which provides
7+
# `Python_EXECUTABLE` plus the includes, libs, and other variables needed to build against Python.
8+
# This means that `Python_EXECUTABLE` points to an executable that's only aware of the standard
9+
# library. On top of that, `embedded_python.cmake` adds `EmbeddedPython_EXECUTABLE` which is aware
10+
# of the full environment with `pip` packages. Note that we do no provide any include or lib dirs
11+
# since those are already provided by `core`.
12+
13+
if(WIN32)
14+
set(EmbeddedPython_EXECUTABLE "${CMAKE_CURRENT_LIST_DIR}/embedded_python/python.exe")
15+
else()
16+
set(EmbeddedPython_EXECUTABLE "${CMAKE_CURRENT_LIST_DIR}/embedded_python/bin/python3")
17+
endif()

test_package/CMakeLists.txt

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@ project(test_package)
33

44
find_package(embedded_python)
55

6-
if(NOT Python_EXECUTABLE MATCHES "embedded_python")
7-
message(FATAL_ERROR "`cmake` failed to find the correct Python")
6+
message(STATUS "Python_EXECUTABLE: ${Python_EXECUTABLE}")
7+
if(NOT Python_EXECUTABLE MATCHES "embedded_python-core")
8+
message(FATAL_ERROR "CMake failed to find the correct Python")
9+
endif()
10+
message(STATUS "EmbeddedPython_EXECUTABLE: ${EmbeddedPython_EXECUTABLE}")
11+
if(EmbeddedPython_EXECUTABLE MATCHES "embedded_python-core")
12+
message(FATAL_ERROR "CMake found the `-core` package instead of the full environment")
13+
endif()
14+
if(NOT EmbeddedPython_EXECUTABLE MATCHES "embedded_python")
15+
message(FATAL_ERROR "CMake failed to find the correct Python")
816
endif()
917

1018
add_executable(test_package ../core/test_package/src/main.cpp)

0 commit comments

Comments
 (0)