diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c9062f7..2fc26719 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,3 +64,28 @@ jobs: run: > cd build; python -m pytest + + nvcc: + runs-on: ubuntu-latest + container: nvidia/cuda:12.2.0-devel-ubuntu22.04 + name: "Python 3 / NVCC (CUDA 12.2)" + + steps: + - name: Install dependencies + run: apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y cmake git python3-dev python3-pytest python3-numpy python3-pip libeigen3-dev && python3 -m pip install typing_extensions + + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Configure + run: > + cmake -S . -B build -DNB_TEST_CUDA=ON + + - name: Build C++ + run: cmake --build build -j 2 + + - name: Run tests + run: > + cd build; + python3 -m pytest diff --git a/CMakeLists.txt b/CMakeLists.txt index ba81d017..9ec06780 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ option(NB_USE_SUBMODULE_DEPS "Use the nanobind dependencies shipped as a git s 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) +option(NB_TEST_CUDA "Force the use of the CUDA/NVCC compiler for testing purposes" OFF) if (NOT MSVC) option(NB_TEST_SANITZE "Build tests with address and undefined behavior sanitizers?" OFF) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 62f2bdb8..a40d34cf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,27 +21,45 @@ if (UNIX AND (CMAKE_SIZEOF_VOID_P EQUAL 4) AND (CMAKE_SYSTEM_PROCESSOR STREQUAL add_compile_options(-mfpmath=sse -msse2) endif() +# Enforce the use of the CUDA NVCC compiler if requested +if (NB_TEST_CUDA) + enable_language(CUDA) + set(CMAKE_CUDA_STANDARD 17) + set(CMAKE_CUDA_STANDARD_REQUIRED ON) +endif() + if (NB_TEST_SANITIZE) add_compile_options(-fsanitize=address,undefined) add_link_options(-fsanitize=address,undefined) endif() +set(TEST_NAMES + functions + classes + holders + stl + stl_bind_map + stl_bind_vector + chrono + enum + eval + ndarray + exception + make_iterator + typing + issue + intrusive +) + +foreach (NAME ${TEST_NAMES}) + nanobind_add_module(test_${NAME}_ext test_${NAME}.cpp ${NB_EXTRA_ARGS}) + + if (NB_TEST_CUDA) + set_property(SOURCE test_${NAME}.cpp PROPERTY LANGUAGE CUDA) + endif() +endforeach() -nanobind_add_module(test_functions_ext test_functions.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_classes_ext test_classes.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_holders_ext test_holders.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_stl_ext test_stl.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_bind_map_ext test_stl_bind_map.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_bind_vector_ext test_stl_bind_vector.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_chrono_ext test_chrono.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_enum_ext test_enum.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_eval_ext test_eval.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_ndarray_ext test_ndarray.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_intrusive_ext test_intrusive.cpp test_intrusive_impl.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_exception_ext test_exception.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_make_iterator_ext test_make_iterator.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_typing_ext test_typing.cpp ${NB_EXTRA_ARGS}) -nanobind_add_module(test_issue_ext test_issue.cpp ${NB_EXTRA_ARGS}) +target_sources(test_intrusive_ext PRIVATE test_intrusive_impl.cpp) foreach (NAME functions classes ndarray stl enum typing make_iterator) if (NAME STREQUAL typing) diff --git a/tests/test_stl_bind_map.cpp b/tests/test_stl_bind_map.cpp index 7afcb0bc..47769cb2 100644 --- a/tests/test_stl_bind_map.cpp +++ b/tests/test_stl_bind_map.cpp @@ -41,7 +41,7 @@ NestMap *times_hundred(int n) { return m; } -NB_MODULE(test_bind_map_ext, m) { +NB_MODULE(test_stl_bind_map_ext, m) { // test_map_string_double nb::bind_map>(m, "MapStringDouble"); nb::bind_map>(m, "UnorderedMapStringDouble"); diff --git a/tests/test_stl_bind_map.py b/tests/test_stl_bind_map.py index 8ded3f27..0aea77ec 100644 --- a/tests/test_stl_bind_map.py +++ b/tests/test_stl_bind_map.py @@ -2,7 +2,7 @@ import sys import platform -import test_bind_map_ext as t +import test_stl_bind_map_ext as t def test_map_string_double(capfd): @@ -35,12 +35,12 @@ def test_map_string_double(capfd): assert len(mm2) == 1 mm2.clear() assert len(mm2) == 0 - assert repr(mm) == "test_bind_map_ext.MapStringDouble({'a': 1.0, 'b': 2.5})" + assert repr(mm) == "test_stl_bind_map_ext.MapStringDouble({'a': 1.0, 'b': 2.5})" with pytest.raises(TypeError): mm2.update({"a" : "b"}) captured = capfd.readouterr().err.strip() - ref = "nanobind: implicit conversion from type 'dict' to type 'test_bind_map_ext.MapStringDouble' failed!" + ref = "nanobind: implicit conversion from type 'dict' to type 'test_stl_bind_map_ext.MapStringDouble' failed!" # Work around Pytest-related flakiness (https://github.com/pytest-dev/pytest/issues/10843) if platform.system() == 'Windows': @@ -102,7 +102,7 @@ def test_map_string_double(capfd): assert t.MapStringDouble.__init__.__doc__ == \ """__init__(self) -> None -__init__(self, arg: test_bind_map_ext.MapStringDouble) -> None +__init__(self, arg: test_stl_bind_map_ext.MapStringDouble) -> None __init__(self, arg: %s[str, float], /) -> None Overloaded function. @@ -111,7 +111,7 @@ def test_map_string_double(capfd): Default constructor -2. ``__init__(self, arg: test_bind_map_ext.MapStringDouble) -> None`` +2. ``__init__(self, arg: test_stl_bind_map_ext.MapStringDouble) -> None`` Copy constructor diff --git a/tests/test_stl_bind_vector.cpp b/tests/test_stl_bind_vector.cpp index 055542d1..b16bb0dc 100644 --- a/tests/test_stl_bind_vector.cpp +++ b/tests/test_stl_bind_vector.cpp @@ -3,7 +3,7 @@ namespace nb = nanobind; -NB_MODULE(test_bind_vector_ext, m) { +NB_MODULE(test_stl_bind_vector_ext, m) { nb::bind_vector>(m, "VectorInt"); nb::bind_vector>(m, "VectorBool"); diff --git a/tests/test_stl_bind_vector.py b/tests/test_stl_bind_vector.py index 35d74c94..8cd2d918 100644 --- a/tests/test_stl_bind_vector.py +++ b/tests/test_stl_bind_vector.py @@ -1,7 +1,7 @@ import pytest import platform -import test_bind_vector_ext as t +import test_stl_bind_vector_ext as t def test01_vector_int(capfd): v_int = t.VectorInt([0, 0]) @@ -11,7 +11,7 @@ def test01_vector_int(capfd): # test construction from a generator v_int1 = t.VectorInt(x for x in range(5)) assert t.VectorInt(v_int1) == t.VectorInt([0, 1, 2, 3, 4]) - assert repr(v_int1) == "test_bind_vector_ext.VectorInt([0, 1, 2, 3, 4])" + assert repr(v_int1) == "test_stl_bind_vector_ext.VectorInt([0, 1, 2, 3, 4])" v_int2 = t.VectorInt([0, 0]) assert v_int == v_int2 @@ -47,7 +47,7 @@ def test01_vector_int(capfd): v_int2.extend([8, "a"]) captured = capfd.readouterr().err.strip() - ref = "nanobind: implicit conversion from type 'list' to type 'test_bind_vector_ext.VectorInt' failed!" + ref = "nanobind: implicit conversion from type 'list' to type 'test_stl_bind_vector_ext.VectorInt' failed!" # Work around Pytest-related flakiness (https://github.com/pytest-dev/pytest/issues/10843) if platform.system() == 'Windows':