Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions source/loaders/py_loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,34 @@ endif()
# Configuration
#

set(PY_LOADER_CONFIG_TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/data/py_loader.json.in")

set(PYTHON_HOME "")
set(Python3_LIBRARY_SEARCH_PATHS "")

if(PROJECT_OS_FAMILY STREQUAL win32)
# Prefer the interpreter directory as Python home for development builds.
set(PYTHON_HOME_DEVELOPMENT "${Python3_ROOT_DIR}")

# On installed layouts we place Python runtime artifacts under INSTALL_LIB.
set(PYTHON_HOME_INSTALL "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB}")

set(Python3_LIBRARY_SEARCH_PATHS_DEVELOPMENT
"${Python3_ROOT_DIR};${Python3_ROOT_DIR}/DLLs;${Python3_ROOT_DIR}/libs")
set(Python3_LIBRARY_SEARCH_PATHS_INSTALL
"${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB};${CMAKE_INSTALL_PREFIX}/${INSTALL_BIN}")
endif()

# Development
loader_configuration_begin(py_loader)
loader_configuration_begin(py_loader "${PY_LOADER_CONFIG_TEMPLATE}")
set(PYTHON_HOME "${PYTHON_HOME_DEVELOPMENT}")
loader_configuration_paths("${Python3_LIBRARY_SEARCH_PATHS_DEVELOPMENT}")
loader_configuration_deps(python "${Python3_LIBRARY_DEVELOPMENT}")
loader_configuartion_end_development()

# Install
loader_configuration_begin(py_loader)
loader_configuration_begin(py_loader "${PY_LOADER_CONFIG_TEMPLATE}")
set(PYTHON_HOME "${PYTHON_HOME_INSTALL}")
loader_configuration_paths("${Python3_LIBRARY_SEARCH_PATHS_INSTALL}")
loader_configuration_deps(python "${Python3_LIBRARY_INSTALL}")
loader_configuartion_end_install()
7 changes: 7 additions & 0 deletions source/loaders/py_loader/data/py_loader.json.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python_home": "@PYTHON_HOME@",
"search_paths": [ @LOADER_SEARCH_PATHS@ ],
"dependencies": {
@LOADER_DEPENDENCIES@
}
}
48 changes: 47 additions & 1 deletion source/loaders/py_loader/source/py_loader_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,45 @@ static int py_loader_impl_finalize(loader_impl_py py_impl, const int host);

static PyObject *py_loader_impl_load_from_memory_compile(loader_impl_py py_impl, const loader_name name, const char *buffer);

#if defined(WIN32) || defined(_WIN32)
static int py_loader_impl_initialize_python_home(configuration config)
{
value python_home_value;
const char *python_home;
const char *python_home_env = getenv("PYTHONHOME");

/* Respect user-provided PYTHONHOME when present. */
if (python_home_env != NULL && python_home_env[0] != '\0')
{
return 0;
}

python_home_value = configuration_value_type(config, "python_home", TYPE_STRING);

if (python_home_value == NULL)
{
return 0;
}

python_home = value_to_string(python_home_value);

if (python_home == NULL || python_home[0] == '\0')
{
return 0;
}

if (_putenv_s("PYTHONHOME", python_home) != 0)
{
log_write("metacall", LOG_LEVEL_ERROR, "Python loader failed to set PYTHONHOME to: %s", python_home);
return 1;
}

log_write("metacall", LOG_LEVEL_DEBUG, "Python loader configured PYTHONHOME to: %s", python_home);

return 0;
}
#endif

/* Implements: if __name__ == "__main__": */
static int py_loader_impl_run_main = 1;
static char *py_loader_impl_main_module = NULL;
Expand Down Expand Up @@ -2454,6 +2493,13 @@ loader_impl_data py_loader_impl_initialize(loader_impl impl, configuration confi

if (host == 0)
{
#if defined(WIN32) || defined(_WIN32)
if (py_loader_impl_initialize_python_home(config) != 0)
{
goto error_init_py;
}
#endif

Py_InitializeEx(0);

if (Py_IsInitialized() == 0)
Expand Down Expand Up @@ -3725,7 +3771,7 @@ static int py_loader_impl_validate_object(loader_impl impl, PyObject *obj, objec
log_write("metacall", LOG_LEVEL_DEBUG, "Discover object member %s, type %s",
PyUnicode_AsUTF8(dict_key),
type_id_name(py_loader_impl_capi_to_value_type(dict_val)));

}
}

Expand Down
39 changes: 38 additions & 1 deletion source/ports/rs_port/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,44 @@ use crate::{
bindings::{metacall_destroy, metacall_initialize, metacall_is_initialized},
types::MetaCallInitError,
};
use std::ptr;
use std::{env, ptr};

pub struct MetaCallDestroy(unsafe extern "C" fn());

#[cfg(target_os = "windows")]
fn ensure_python_home() {
use std::path::Path;

if env::var_os("PYTHONHOME").is_some() {
return;
}

let Some(configured_home) = option_env!("METACALL_PYTHONHOME") else {
return;
};

if configured_home.is_empty() {
return;
}

let configured_home_path = Path::new(configured_home);
let runtime_python_from_config = configured_home_path.join("runtimes").join("python");
let runtime_python_from_parent = configured_home_path
.parent()
.map(|p| p.join("runtimes").join("python"));

let selected_home = if runtime_python_from_config.is_dir() {
runtime_python_from_config.as_os_str()
} else if let Some(runtime_python) = runtime_python_from_parent.as_ref().filter(|p| p.is_dir())
{
runtime_python.as_os_str()
} else {
configured_home_path.as_os_str()
};

env::set_var("PYTHONHOME", selected_home);
}

impl Drop for MetaCallDestroy {
fn drop(&mut self) {
unsafe { self.0() }
Expand All @@ -22,6 +56,9 @@ impl Drop for MetaCallDestroy {
///
/// ```
pub fn initialize() -> Result<MetaCallDestroy, MetaCallInitError> {
#[cfg(target_os = "windows")]
ensure_python_home();

let code = unsafe { metacall_initialize() };

if code != 0 {
Expand Down
8 changes: 8 additions & 0 deletions source/ports/rs_port/sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,14 @@ pub fn build() {
define_library_search_path(ENV_VAR, SEPARATOR, &lib_path.search)
);

#[cfg(target_os = "windows")]
{
println!(
"cargo:rustc-env=METACALL_PYTHONHOME={}",
lib_path.search.display()
);
}

println!(
"cargo:warning=Library {} found in: {} with runtime search path: {}",
lib_path.library,
Expand Down
Loading