diff --git a/CHANGELOG.md b/CHANGELOG.md index 50ec8a86..b8e6aa0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Added `juliacall.TypeValue.__numpy_dtype__` attribute to allow converting Julia types to the corresponding NumPy dtype, like `numpy.dtype(jl.Int)`. * JuliaCall now launches Julia with 1 thread by default. +* Added options `trace_compile` and `trace_compile_timing` to JuliaCall. * Bug fixes. ## 0.9.31 (2025-12-17) diff --git a/docs/src/juliacall.md b/docs/src/juliacall.md index 26182add..c49e150f 100644 --- a/docs/src/juliacall.md +++ b/docs/src/juliacall.md @@ -142,6 +142,8 @@ be configured in two ways: | `-X juliacall-heap-size-hint=` | `PYTHON_JULIACALL_HEAP_SIZE_HINT=` | Hint for initial heap size in bytes. | | `-X juliacall-exe=` | `PYTHON_JULIACALL_EXE=` | Path to Julia binary to use (overrides JuliaPkg). | | `-X juliacall-project=` | `PYTHON_JULIACALL_PROJECT=` | Path to the Julia project to use (overrides JuliaPkg). | +| `-X juliacall-trace-compile=` | `PYTHON_JULIACALL_TRACE_COMPILE=` | Print precompile statements. | +| `-X juliacall-trace-compile-timing` | `PYTHON_JULIACALL_TRACE_COMPILE_TIMING=` | Include timings with precompile statements. | ## [Multi-threading](@id py-multi-threading) diff --git a/pysrc/juliacall/__init__.py b/pysrc/juliacall/__init__.py index 729a2ae8..62fa5a51 100644 --- a/pysrc/juliacall/__init__.py +++ b/pysrc/juliacall/__init__.py @@ -64,7 +64,7 @@ def init(): "For updates, see https://github.com/pytorch/pytorch/issues/78829." ) - def option(name, default=None, xkey=None, envkey=None): + def option(name, default=None, xkey=None, envkey=None, allowflag=False): """Get an option. Options can be set as command line arguments '-X juliacall-{name}={value}' or as @@ -73,6 +73,10 @@ def option(name, default=None, xkey=None, envkey=None): k = xkey or 'juliacall-'+name.lower().replace('_', '-') v = sys._xoptions.get(k) if v is not None: + if v is True: + if not allowflag: + raise ValueError(f'-X{k}: expecting an argument') + return True, f'-X{k}' return v, f'-X{k}={v}' k = envkey or 'PYTHON_JULIACALL_'+name.upper() v = os.getenv(k) @@ -80,6 +84,17 @@ def option(name, default=None, xkey=None, envkey=None): return v, f'{k}={v}' return default, f'={default}' + def flag(name, default=None, **kw): + v, s = option(name, allowflag=True, **kw) + if v is None: + return default, s + elif v is True or v == 'yes': + return True, s + elif v == 'no': + return False, s + else: + raise ValueError(f'{s}: expecting yes or no') + def choice(name, choices, default=None, **kw): v, s = option(name, **kw) if v is None: @@ -128,7 +143,11 @@ def args_from_config(config): val = 'no' else: continue - argv.append('--' + opt[4:].replace('_', '-') + '=' + val) + arg = '--' + opt[4:].replace('_', '-') + if val is True: + argv.append(arg) + elif val is not None: + argv.append(f"{arg}={val}") argv = [s.encode("utf-8") for s in argv] argc = len(argv) @@ -145,6 +164,8 @@ def args_from_config(config): CONFIG['opt_home'] = bindir = path_option('home', check_exists=True, envkey='PYTHON_JULIACALL_BINDIR')[0] CONFIG['opt_check_bounds'] = choice('check_bounds', ['yes', 'no', 'auto'])[0] CONFIG['opt_compile'] = choice('compile', ['yes', 'no', 'all', 'min'])[0] + CONFIG["opt_trace_compile"] = option('trace_compile')[0] + CONFIG["opt_trace_compile_timing"] = flag('trace_compile_timing')[0] CONFIG['opt_compiled_modules'] = choice('compiled_modules', ['yes', 'no'])[0] CONFIG['opt_depwarn'] = choice('depwarn', ['yes', 'no', 'error'])[0] CONFIG['opt_inline'] = choice('inline', ['yes', 'no'])[0]