Skip to content

Commit 715c859

Browse files
author
Christopher Rowley
committed
change to just one new option (lib) with sensible discovery/defaults of libpath, exepath and bindir depending on if others are set
1 parent df51ae6 commit 715c859

3 files changed

Lines changed: 25 additions & 31 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
# Changelog
22

33
## Unreleased
4-
* JuliaCall: added `libpath` / `default_bindir` options
5-
(`PYTHON_JULIACALL_LIBPATH` / `PYTHON_JULIACALL_DEFAULT_BINDIR`) to supply
6-
libjulia's path and `Sys.BINDIR` directly, skipping the discovery subprocess
7-
at startup. Behaviour is unchanged unless both are set.
4+
* Added option `lib` to JuliaCall. Setting this will skip the discovery subprocess.
85

96
## 0.9.34 (2026-05-18)
107
* Bug fixes.

docs/src/juliacall.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ be configured in two ways:
142142
| `-X juliacall-heap-size-hint=<N>` | `PYTHON_JULIACALL_HEAP_SIZE_HINT=<N>` | Hint for initial heap size in bytes. |
143143
| `-X juliacall-exe=<file>` | `PYTHON_JULIACALL_EXE=<file>` | Path to Julia binary to use (overrides JuliaPkg). |
144144
| `-X juliacall-project=<dir>` | `PYTHON_JULIACALL_PROJECT=<dir>` | Path to the Julia project to use (overrides JuliaPkg). |
145-
| `-X juliacall-libpath=<file>` | `PYTHON_JULIACALL_LIBPATH=<file>` | Path to libjulia. If set together with `default-bindir`, skips the subprocess that discovers it. |
146-
| `-X juliacall-default-bindir=<dir>` | `PYTHON_JULIACALL_DEFAULT_BINDIR=<dir>` | Julia's `Sys.BINDIR`. If set together with `libpath`, skips the subprocess that discovers it. |
145+
| `-X juliacall-lib=<file>` | `PYTHON_JULIACALL_LIB=<file>` | Path to libjulia. Set to skip the relatively slow discovery process. |
147146
| `-X juliacall-trace-compile=<stderr\|name>` | `PYTHON_JULIACALL_TRACE_COMPILE=<stderr\|name>` | Print precompile statements. |
148147
| `-X juliacall-trace-compile-timing` | `PYTHON_JULIACALL_TRACE_COMPILE_TIMING=<yes\|no>` | Include timings with precompile statements. |
149148

pysrc/juliacall/__init__.py

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -179,48 +179,46 @@ def args_from_config(config):
179179
CONFIG['opt_handle_signals'] = choice('handle_signals', ['yes', 'no'])[0]
180180
CONFIG['opt_startup_file'] = choice('startup_file', ['yes', 'no'])[0]
181181
CONFIG['opt_heap_size_hint'] = option('heap_size_hint')[0]
182-
CONFIG['project'] = path_option('project', check_exists=True)[0]
183-
CONFIG['exepath'] = executable_option('exe')[0]
182+
CONFIG['project'] = project = path_option('project', check_exists=True)[0]
183+
CONFIG['libpath'] = libpath = path_option('lib', check_exists=True)[0]
184+
CONFIG['exepath'] = exepath = executable_option('exe')[0]
184185

185186
# Stop if we already initialised
186187
if CONFIG['inited']:
187188
return
188189

189-
have_exepath = CONFIG['exepath'] is not None
190-
have_project = CONFIG['project'] is not None
191-
if have_exepath and have_project:
190+
if (exepath is None) and (bindir is not None):
191+
# if bindir is set then set exepath={bindir}/julia
192+
CONFIG['exepath'] = exepath = os.path.join(bindir, 'julia.exe' if os.name == 'nt' else 'julia')
193+
if (exepath is not None) and (project is not None):
192194
pass
193-
elif (not have_exepath) and (not have_project):
195+
elif (exepath is None) and (project is None):
194196
# we don't import this at the top level because it is not required when
195197
# juliacall is loaded by PythonCall and won't be available, or if both
196198
# `exepath` and `project` are set by the user.
197199
import juliapkg
198200

199201
# Find the Julia executable and project
200-
CONFIG['exepath'] = juliapkg.executable()
201-
CONFIG['project'] = juliapkg.project()
202+
CONFIG['exepath'] = exepath = juliapkg.executable()
203+
CONFIG['project'] = project = juliapkg.project()
202204
else:
203205
raise Exception("Both PYTHON_JULIACALL_PROJECT and PYTHON_JULIACALL_EXE must be set together, not only one of them.")
206+
if (libpath is not None) and (exepath is None):
207+
raise Exception("PYTHON_JULIACALL_EXE is required if PYTHON_JULIACALL_LIB is set.")
204208

205-
exepath = CONFIG['exepath']
206-
project = CONFIG['project']
207-
208-
# Find the Julia library.
209-
#
210-
# This normally starts a short-lived Julia process just to print libjulia's
211-
# path and Sys.BINDIR. In deployment scenarios (e.g. a pre-built container
212-
# or system image) these are static and known ahead of time, so they may be
213-
# supplied directly via the `libpath` / `default_bindir` options to skip the
214-
# extra process. Behaviour is unchanged unless both are set.
215-
libpath = path_option('libpath', check_exists=True)[0]
216-
default_bindir = path_option('default_bindir', check_exists=True)[0]
217-
if libpath is None or default_bindir is None:
209+
# Find the Julia library, if not specified.
210+
if libpath is None:
218211
cmd = [exepath, '--project='+project, '--startup-file=no', '-O0', '--compile=min',
219212
'-e', 'import Libdl; print(abspath(Libdl.dlpath("libjulia")), "\\0", Sys.BINDIR)']
220-
libpath, default_bindir = subprocess.run(cmd, check=True, capture_output=True, encoding='utf8').stdout.split('\0')
213+
found_libpath, found_bindir = subprocess.run(cmd, check=True, capture_output=True, encoding='utf8').stdout.split('\0')
214+
if libpath is None:
215+
CONFIG['libpath'] = libpath = found_libpath
216+
if bindir is None:
217+
CONFIG['bindir'] = bindir = found_bindir
218+
if bindir is None:
219+
bindir = os.path.dirname(exepath)
221220
assert os.path.exists(libpath)
222-
assert os.path.exists(default_bindir)
223-
CONFIG['libpath'] = libpath
221+
assert os.path.exists(bindir)
224222

225223
# Add the Julia library directory to the PATH on Windows so Julia's system libraries can
226224
# be found. They are normally found because they are in the same directory as julia.exe,
@@ -251,7 +249,7 @@ def args_from_config(config):
251249
jl_init.argtypes = [c.c_char_p, c.c_char_p]
252250
jl_init.restype = None
253251
jl_init(
254-
(default_bindir if bindir is None else bindir).encode('utf8'),
252+
None if bindir is None else bindir.encode('utf8'),
255253
None if sysimg is None else sysimg.encode('utf8'),
256254
)
257255

0 commit comments

Comments
 (0)