Skip to content

Commit

Permalink
nanobind: update, convert to header-only package
Browse files Browse the repository at this point in the history
  • Loading branch information
valgur committed Mar 21, 2024
1 parent fca85a7 commit c187a4e
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 95 deletions.
6 changes: 3 additions & 3 deletions recipes/nanobind/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sources:
"1.6.1":
url: "https://github.com/wjakob/nanobind/archive/refs/tags/v1.6.1.tar.gz"
sha256: "6acf2cfef781b8b7d82a8c298c1bfe7ccb4dd0de06626b69ed1c99a71a93e78d"
"1.9.2":
url: "https://github.com/wjakob/nanobind/archive/refs/tags/v1.9.2.tar.gz"
sha256: "149a3da40b0a988513d8cf5e71db3037373823505a3c92f87b988c92d7e0ab34"
95 changes: 16 additions & 79 deletions recipes/nanobind/all/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.build import check_min_cppstd
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout, CMakeDeps
from conan.tools.files import get, copy, rm, replace_in_file, save, rename
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.files import get, copy, rm, rename
from conan.tools.scm import Version

required_conan_version = ">=1.53.0"
Expand All @@ -16,21 +16,17 @@ class PackageConan(ConanFile):
license = "BSD-3-Clause"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/wjakob/nanobind"
topics = ("python", "bindings", "pybind11")
topics = ("python", "bindings", "pybind11", "header-only")

package_type = "library"
package_type = "header-library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"stable_abi": [True, False],
"domain": [None, "ANY"],
}
default_options = {
"shared": False,
"fPIC": True,
"stable_abi": False, # TODO: enable after CPython 3.12 is available
"domain": None,
}

@property
Expand Down Expand Up @@ -60,7 +56,6 @@ def layout(self):

def requirements(self):
self.requires("tsl-robin-map/1.2.2")
self.requires("cpython/3.10.0")

def validate(self):
if self.settings.compiler.cppstd:
Expand All @@ -71,91 +66,33 @@ def validate(self):
f"{self.ref} requires C++{self._min_cppstd}, which your compiler does not support."
)

if self.options.stable_abi and Version(self.dependencies["cpython"].ref.version) < "3.12":
raise ConanInvalidConfiguration(
f"CPython 3.12+ is required for stable ABI support."
)

def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)

def generate(self):
tc = CMakeToolchain(self)
tc.cache_variables["NB_TEST"] = False
tc.variables["NB_TEST"] = False
tc.variables["NB_USE_SUBMODULE_DEPS"] = False
tc.generate()
deps = CMakeDeps(self)
deps.generate()

@property
def _libname(self):
libname = "nanobind"
if not self.options.shared:
libname += "-static"
if self.options.stable_abi:
libname += "-abi3"
if self.options.domain and self.options.shared:
libname += f"-{self.options.domain}"
return libname

def build(self):
self._patch_sources()
cmake = CMake(self)
cmake.configure()
cmake.build(target=self._libname)

def _patch_sources(self):
cmakelists = os.path.join(self.source_folder, "CMakeLists.txt")
nb_config = os.path.join(self.source_folder, "cmake", "nanobind-config.cmake")
# tsl-robin-map has been unvendored, skip a check for its presence
replace_in_file(self, cmakelists, "if (NOT IS_DIRECTORY", "if (FALSE AND NOT IS_DIRECTORY")
# Force building of nanobind lib
save(self, cmakelists, f"\nnanobind_build_library({self._libname})", append=True)
# Link against tsl-robin-map and install the lib and headers
replace_in_file(self, nb_config,
"target_include_directories(${TARGET_NAME} PRIVATE\n ${NB_DIR}/ext/robin_map/include)\n",
(
"find_package(tsl-robin-map REQUIRED CONFIG)\n"
"target_link_libraries(${TARGET_NAME} PRIVATE tsl::robin_map)\n"
"include(GNUInstallDirs)\n"
"install(TARGETS ${TARGET_NAME})\n"
"install(DIRECTORY ${NB_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})\n"
),
)
# No need to build the lib inside nanobind_add_module() call
replace_in_file(self, nb_config, "nanobind_build_library(${libname})\n", "")
# Link against previously built nanobind and Python
# FIXME: the CPython include dirs should be added by Conan automatically
replace_in_file(self, nb_config,
"target_link_libraries(${name} PRIVATE ${libname})\n",
(
"target_link_libraries(${name} PRIVATE nanobind::nanobind)\n"
"target_include_directories(${name} PUBLIC ${Python_INCLUDE_DIRS})\n"
),
)
# Propagate options to nanobind_add_module()
replace_in_file(self, nb_config, "add_library(${name}",
(
f"set(ARG_NB_SHARED {str(self.options.shared).upper()})\n"
f"set(ARG_NB_STATIC {str(not self.options.shared).upper()})\n"
f"set(ARG_STABLE_ABI {str(self.options.stable_abi).upper()})\n"
+ (f"set(ARG_NB_DOMAIN {self.options.domain})\n" if self.options.domain else "")
+ "add_library(${name}"
),
)
cmake.build()

@property
def _cmake_rel_dir(self):
return os.path.join("share", "nanobind", "cmake")

def package(self):
copy(self, "LICENSE", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses"))
cmake = CMake(self)
cmake.install()
copy(self, "nanobind-config.cmake",
src=os.path.join(self.source_folder, "cmake"),
dst=os.path.join(self.package_folder, "lib", "cmake"))
rename(self,
os.path.join(self.package_folder, "lib", "cmake", "nanobind-config.cmake"),
os.path.join(self.package_folder, "lib", "cmake", "nanobind-conan-config.cmake"))
os.path.join(self.package_folder, self._cmake_rel_dir, "nanobind-config.cmake"),
os.path.join(self.package_folder, self._cmake_rel_dir, "nanobind-conan-config.cmake"))
rm(self, "*.pdb", self.package_folder, recursive=True)

def package_info(self):
self.cpp_info.libs = [self._libname]
self.cpp_info.builddirs = [os.path.join(self.package_folder, "lib", "cmake")]
self.cpp_info.set_property("cmake_build_modules", [os.path.join("lib", "cmake", "nanobind-conan-config.cmake")])
self.cpp_info.builddirs = [self._cmake_rel_dir]
self.cpp_info.set_property("cmake_build_modules", [os.path.join(self._cmake_rel_dir, "nanobind-conan-config.cmake")])
15 changes: 3 additions & 12 deletions recipes/nanobind/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import importlib
import sys

from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout, CMake
Expand All @@ -13,6 +10,7 @@ class TestPackageConan(ConanFile):

def requirements(self):
self.requires(self.tested_reference_str)
self.requires("cpython/3.10.0", run=True)

def layout(self):
cmake_layout(self)
Expand All @@ -22,14 +20,7 @@ def build(self):
cmake.configure()
cmake.build()

def _test_nanobind_module(self):
sys.path.append(self.build_folder)
# Cannot use 'import test_package' due to pylint
test_package = importlib.import_module("test_package")
assert test_package.add(2, 3) == 5
self.output.info("test_package.add(2, 3) ran successfully")
sys.path.pop()

def test(self):
if can_run(self):
self._test_nanobind_module()
self.run('python -c "import test_package; print(test_package.add(2, 3))"',
env="conanrun", cwd=self.cpp.build.bindir)
2 changes: 1 addition & 1 deletion recipes/nanobind/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
versions:
"1.6.1":
"1.9.2":
folder: all

0 comments on commit c187a4e

Please sign in to comment.