Skip to content
Open
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
6 changes: 5 additions & 1 deletion cmake/nanobind-config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ endfunction()
# ---------------------------------------------------------------------------

function (nanobind_add_stub name)
cmake_parse_arguments(PARSE_ARGV 1 ARG "VERBOSE;INCLUDE_PRIVATE;EXCLUDE_DOCSTRINGS;EXCLUDE_VALUES;INSTALL_TIME;RECURSIVE;EXCLUDE_FROM_ALL" "MODULE;COMPONENT;PATTERN_FILE;OUTPUT_PATH" "PYTHON_PATH;DEPENDS;MARKER_FILE;OUTPUT")
cmake_parse_arguments(PARSE_ARGV 1 ARG "VERBOSE;INCLUDE_PRIVATE;EXCLUDE_DOCSTRINGS;EXCLUDE_VALUES;INSTALL_TIME;RECURSIVE;EXCLUDE_FROM_ALL" "MODULE;COMPONENT;PATTERN_FILE;OUTPUT_PATH" "PYTHON_PATH;LIB_PATH;DEPENDS;MARKER_FILE;OUTPUT")

if (EXISTS ${NB_DIR}/src/stubgen.py)
set(NB_STUBGEN "${NB_DIR}/src/stubgen.py")
Expand Down Expand Up @@ -626,6 +626,10 @@ function (nanobind_add_stub name)
list(APPEND NB_STUBGEN_ARGS -i "${PYTHON_PATH}")
endforeach()

foreach (LIB_PATH IN LISTS ARG_LIB_PATH)
list(APPEND NB_STUBGEN_ARGS -L "${LIB_PATH}")
endforeach()

if (ARG_PATTERN_FILE)
list(APPEND NB_STUBGEN_ARGS -p "${ARG_PATTERN_FILE}")
endif()
Expand Down
12 changes: 12 additions & 0 deletions docs/api_cmake.rst
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,18 @@ Nanobind's CMake tooling includes a convenience command to interface with the
generation. Otherwise, generator expressions should not be used.
Optional.

* - ``LIB_PATH``
- List of search paths that should be considered when searching for
shared libraries. This can be useful when the Python module being
imported depends on shared libraries that are not in the default
search path. On Windows, these directories are added to the DLL search
path using ``os.add_dll_directory()``. On Linux, the paths are
prepended to the ``LD_LIBRARY_PATH`` environment variable (on macOS,
to ``DYLD_LIBRARY_PATH``). The paths are relative to
``CMAKE_CURRENT_BINARY_DIR`` for build-time stub generation and
relative to ``CMAKE_INSTALL_PREFIX`` for install-time stub
generation. Optional.

* - ``DEPENDS``
- Any targets listed here will be marked as a dependencies. This should
generally be used to list the target names of one or more prior
Expand Down
7 changes: 5 additions & 2 deletions docs/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,9 @@ The program has the following command line options:

.. code-block:: text

usage: python -m nanobind.stubgen [-h] [-o FILE] [-O PATH] [-i PATH] [-m MODULE]
[-r] [-M FILE] [-P] [-D] [--exclude-values] [-q]
usage: python -m nanobind.stubgen [-h] [-o FILE] [-O PATH] [-i PATH]
[-L PATH] [-m MODULE] [-r] [-M FILE] [-P]
[-D] [--exclude-values] [-q]

Generate stubs for nanobind-based extensions.

Expand All @@ -550,6 +551,8 @@ The program has the following command line options:
-O PATH, --output-dir PATH write generated stubs to the specified directory
-i PATH, --import PATH add the directory to the Python import path (can
specify multiple times)
-L PATH, --lib-path PATH add directory to shared library search path (can
specify multiple times)
-m MODULE, --module MODULE generate a stub for the specified module (can
specify multiple times)
-r, --recursive recursively process submodules
Expand Down
21 changes: 21 additions & 0 deletions src/stubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 +1285,16 @@ def parse_options(args: List[str]) -> argparse.Namespace:
help="add the directory to the Python import path (can specify multiple times)",
)

parser.add_argument(
"-L",
"--lib-path",
action="append",
metavar="PATH",
dest="lib_paths",
default=[],
help="add directory to shared library search path (can specify multiple times)"
)

parser.add_argument(
"-m",
"--module",
Expand Down Expand Up @@ -1426,6 +1436,7 @@ def add_pattern(query: str, lines: List[str]):

def main(args: Optional[List[str]] = None) -> None:
import sys
import os

# Ensure that the current directory is on the path
if "" not in sys.path and "." not in sys.path:
Expand All @@ -1446,6 +1457,16 @@ def main(args: Optional[List[str]] = None) -> None:
for i in opt.imports:
sys.path.insert(0, i)

if os.name == 'nt':
for lib_path in opt.lib_paths:
os.add_dll_directory(lib_path)
else:
lib_env = "DYLD_LIBRARY_PATH" if sys.platform == "darwin" else "LD_LIBRARY_PATH"
old_value = os.environ.get(lib_env, "")
paths_str = ":".join(opt.lib_paths)
if paths_str:
os.environ[lib_env] = f"{paths_str}:{old_value}" if old_value else paths_str

for i, mod in enumerate(opt.modules):
if not opt.quiet:
if i > 0:
Expand Down
17 changes: 17 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,27 @@ target_compile_definitions(inter_module PRIVATE -DSHARED_BUILD)
target_compile_features(inter_module PRIVATE cxx_std_17)
target_include_directories(inter_module PRIVATE ${NB_DIR}/include)

# Output inter_module to a separate lib subdirectory to test LIB_PATH functionality
set_target_properties(inter_module PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib
)

nanobind_add_module(test_inter_module_1_ext NB_DOMAIN mydomain test_inter_module_1.cpp ${NB_EXTRA_ARGS})
nanobind_add_module(test_inter_module_2_ext NB_DOMAIN mydomain test_inter_module_2.cpp ${NB_EXTRA_ARGS})
target_link_libraries(test_inter_module_1_ext PRIVATE inter_module)
target_link_libraries(test_inter_module_2_ext PRIVATE inter_module)

# Generate stub for inter_module_1 to test LIB_PATH functionality
nanobind_add_stub(
inter_module_1_ext_stub
MODULE test_inter_module_1_ext
OUTPUT ${PYI_PREFIX}test_inter_module_1_ext.pyi
PYTHON_PATH $<TARGET_FILE_DIR:test_inter_module_1_ext>
LIB_PATH $<TARGET_FILE_DIR:inter_module>
DEPENDS test_inter_module_1_ext inter_module
)

set(TEST_FILES
common.py
conftest.py
Expand Down Expand Up @@ -177,6 +193,7 @@ set(TEST_FILES
# Stub reference files
test_classes_ext.pyi.ref
test_functions_ext.pyi.ref
test_inter_module_1_ext.pyi.ref
test_make_iterator_ext.pyi.ref
test_ndarray_ext.pyi.ref
test_jax_ext.pyi.ref
Expand Down
3 changes: 3 additions & 0 deletions tests/test_inter_module_1_ext.pyi.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


def create_shared() -> "Shared": ...
Loading