Skip to content

Commit

Permalink
cmake: Add install rules and option to use submodule dependencies
Browse files Browse the repository at this point in the history
Package ecosystems that know how to install CMake projects can now
package nanobind for distribution without using submodule'd
dependencies.

nanobind does not install any compiled library artifacts. Instead, all
necessary source files and supporting CMake files are installed to build
nanobind within another CMake project.

A CMake user can now adjust the CMake option `NB_USE_SUBMODULE_DEPS` to
choose whether nanobind will use and/or install the submodule'd external
dependencies. This is `ON` by default, allowing nanobind's CMake logic
to continue operating as it did previously.

Another CMake option was introduced, `NB_CREATE_INSTALL_RULES`, to allow
users to choose whether to enable or disable the installation rules.
Notably, if nanobind is added to a CMake project with
`add_subdirectory`, the installation rules are disabled, because
installing source files probably isn't the expected result of the parent
project(s). Install-rule generation still respects the standard CMake
`CMAKE_SKIP_INSTALL_RULES` variable.
  • Loading branch information
ekilmer committed Nov 7, 2023
1 parent 61ca0f9 commit ede589d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
49 changes: 48 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ else()
set(NB_MASTER_PROJECT OFF)
endif()

option(NB_CREATE_INSTALL_RULES "Create installation rules" ${NB_MASTER_PROJECT})
option(NB_USE_SUBMODULE_DEPS "Use submodule'd dependencies" ON)

option(NB_TEST "Compile nanobind tests?" ${NB_MASTER_PROJECT})
option(NB_TEST_STABLE_ABI "Test the stable ABI interface?" OFF)
option(NB_TEST_SHARED_BUILD "Build a shared nanobind library for the test suite?" OFF)
Expand All @@ -30,12 +33,56 @@ endif()
# Check whether all dependencies are present
# ---------------------------------------------------------------------------

if (NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ext/robin_map/include")
if (NB_USE_SUBMODULE_DEPS AND NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ext/robin_map/include")
message(FATAL_ERROR "The nanobind dependencies are missing! "
"You probably did not clone the project with --recursive. It is possible to recover "
"by invoking\n$ git submodule update --init --recursive")
endif()

# ---------------------------------------------------------------------------
# Installation rules
# ---------------------------------------------------------------------------

if(NB_CREATE_INSTALL_RULES AND NOT CMAKE_SKIP_INSTALL_RULES)
set(CMAKE_INSTALL_DATAROOTDIR "share"
CACHE PATH "Installation path for read-only architecture-independent data root")

# Normally these would be configurable by the user, but we can't allow that
# because the lookup paths are hard-coded in 'cmake/nanobind-config.cmake'
set(CMAKE_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_DATAROOTDIR}/nanobind/include")
set(NB_INSTALL_SRCDIR "${CMAKE_INSTALL_DATAROOTDIR}/nanobind/src")
set(NB_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATAROOTDIR}/nanobind/cmake")

install(
DIRECTORY include/
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

install(
DIRECTORY src/
DESTINATION "${NB_INSTALL_SRCDIR}"
PATTERN "*.py" EXCLUDE
)

if(NB_USE_SUBMODULE_DEPS)
install(
DIRECTORY ext/robin_map/include/
DESTINATION "${NB_INSTALL_SRCDIR}/ext/robin_map/include"
)
install(
FILES
"ext/robin_map/tsl-robin-map.natvis"
"ext/robin_map/CMakeLists.txt"
DESTINATION "${NB_INSTALL_SRCDIR}/ext/robin_map"
)
endif()

install(
DIRECTORY cmake/
DESTINATION "${NB_INSTALL_CMAKEDIR}"
)
endif()

# ---------------------------------------------------------------------------
# Compile with a few more compiler warnings turned on
# ---------------------------------------------------------------------------
Expand Down
16 changes: 14 additions & 2 deletions cmake/nanobind-config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,20 @@ function (nanobind_build_library TARGET_NAME)
target_compile_definitions(${TARGET_NAME} PRIVATE
$<${NB_OPT_SIZE}:NB_COMPACT_ASSERTIONS>)

target_include_directories(${TARGET_NAME} PRIVATE
${NB_DIR}/ext/robin_map/include)
# If nanobind was installed without submodule dependencies, then the
# dependencies directory won't exist and we need to find them.
# However, if the directory _does_ exist, then the user is free to choose
# whether nanobind uses them (based on `NB_USE_SUBMODULE_DEPS`), with a
# preference to choose them if `NB_USE_SUBMODULE_DEPS` is not defined
if (NOT IS_DIRECTORY ${NB_DIR}/ext/robin_map/include OR
(DEFINED NB_USE_SUBMODULE_DEPS AND NOT NB_USE_SUBMODULE_DEPS))
include(CMakeFindDependencyMacro)
find_dependency(tsl-robin-map)
target_link_libraries(${TARGET_NAME} PRIVATE tsl::robin_map)
else()
target_include_directories(${TARGET_NAME} PRIVATE
${NB_DIR}/ext/robin_map/include)
endif()

target_include_directories(${TARGET_NAME} PUBLIC
${Python_INCLUDE_DIRS}
Expand Down

0 comments on commit ede589d

Please sign in to comment.