Skip to content

Commit

Permalink
Merge pull request #1941 from matthewdcong/pip_openvdb
Browse files Browse the repository at this point in the history
Add support for pip install
  • Loading branch information
danrbailey authored Oct 30, 2024
2 parents 2f84be5 + 18ad210 commit 58c8d3a
Show file tree
Hide file tree
Showing 17 changed files with 136 additions and 47 deletions.
26 changes: 25 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,30 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

# Add cmake modules to installation command

if(SKBUILD)
set(OPENVDB_INSTALL_BINDIR openvdb/${CMAKE_INSTALL_BINDIR})
set(OPENVDB_INSTALL_LIBDIR openvdb/${CMAKE_INSTALL_LIBDIR})
set(OPENVDB_INSTALL_INCLUDEDIR openvdb/${CMAKE_INSTALL_INCLUDEDIR})

if(OPENVDB_BUILD_NANOVDB)
set(NANOVDB_INSTALL_BINDIR nanovdb/${CMAKE_INSTALL_BINDIR})
set(NANOVDB_INSTALL_LIBDIR nanovdb/${CMAKE_INSTALL_LIBDIR})
set(NANOVDB_INSTALL_INCLUDEDIR nanovdb/${CMAKE_INSTALL_INCLUDEDIR})
set(NANOVDB_INSTALL_DOCDIR nanovdb/${CMAKE_INSTALL_DOCDIR})
endif()
else()
set(OPENVDB_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
set(OPENVDB_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
set(OPENVDB_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})

if(OPENVDB_BUILD_NANOVDB)
set(NANOVDB_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
set(NANOVDB_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
set(NANOVDB_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
set(NANOVDB_INSTALL_DOCDIR ${CMAKE_INSTALL_DOCDIR})
endif()
endif()

if(OPENVDB_INSTALL_CMAKE_MODULES)
set(OPENVDB_CMAKE_MODULES
cmake/FindBlosc.cmake
Expand All @@ -298,7 +322,7 @@ if(OPENVDB_INSTALL_CMAKE_MODULES)
cmake/OpenVDBMayaSetup.cmake
cmake/OpenVDBUtils.cmake
)
install(FILES ${OPENVDB_CMAKE_MODULES} DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/OpenVDB)
install(FILES ${OPENVDB_CMAKE_MODULES} DESTINATION ${OPENVDB_INSTALL_LIBDIR}/cmake/OpenVDB)
endif()

# Configure component dependencies by loading the Houdini/Maya setup
Expand Down
14 changes: 7 additions & 7 deletions nanovdb/nanovdb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -322,16 +322,16 @@ if(TARGET Threads::Threads)
target_link_libraries(nanovdb INTERFACE Threads::Threads)
endif()

set(NANOVDB_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/nanovdb)
set(NANOVDB_INSTALL_CUDA_DIR ${NANOVDB_INSTALL_INCLUDE_DIR}/cuda)
set(NANOVDB_INSTALL_IO_DIR ${NANOVDB_INSTALL_INCLUDE_DIR}/io)
set(NANOVDB_INSTALL_MATH_DIR ${NANOVDB_INSTALL_INCLUDE_DIR}/math)
set(NANOVDB_INSTALL_TOOLS_DIR ${NANOVDB_INSTALL_INCLUDE_DIR}/tools)
set(NANOVDB_INSTALL_ROOT_DIR ${NANOVDB_INSTALL_INCLUDEDIR}/nanovdb)
set(NANOVDB_INSTALL_CUDA_DIR ${NANOVDB_INSTALL_ROOT_DIR}/cuda)
set(NANOVDB_INSTALL_IO_DIR ${NANOVDB_INSTALL_ROOT_DIR}/io)
set(NANOVDB_INSTALL_MATH_DIR ${NANOVDB_INSTALL_ROOT_DIR}/math)
set(NANOVDB_INSTALL_TOOLS_DIR ${NANOVDB_INSTALL_ROOT_DIR}/tools)
set(NANOVDB_INSTALL_TOOLS_CUDA_DIR ${NANOVDB_INSTALL_TOOLS_DIR}/cuda)
set(NANOVDB_INSTALL_UTIL_DIR ${NANOVDB_INSTALL_INCLUDE_DIR}/util)
set(NANOVDB_INSTALL_UTIL_DIR ${NANOVDB_INSTALL_ROOT_DIR}/util)
set(NANOVDB_INSTALL_UTIL_CUDA_DIR ${NANOVDB_INSTALL_UTIL_DIR}/cuda)

install(FILES ${NANOVDB_INCLUDE_FILES} DESTINATION ${NANOVDB_INSTALL_INCLUDE_DIR})
install(FILES ${NANOVDB_INCLUDE_FILES} DESTINATION ${NANOVDB_INSTALL_ROOT_DIR})
install(FILES ${NANOVDB_INCLUDE_CUDA_FILES} DESTINATION ${NANOVDB_INSTALL_CUDA_DIR})
install(FILES ${NANOVDB_INCLUDE_IO_FILES} DESTINATION ${NANOVDB_INSTALL_IO_DIR})
install(FILES ${NANOVDB_INCLUDE_MATH_FILES} DESTINATION ${NANOVDB_INSTALL_MATH_DIR})
Expand Down
6 changes: 3 additions & 3 deletions nanovdb/nanovdb/cmd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ if(NOT NANOVDB_USE_OPENVDB)
else()
add_executable(nanovdb_convert convert/nanovdb_convert.cc)
target_link_libraries(nanovdb_convert PRIVATE nanovdb)
install(TARGETS nanovdb_convert RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS nanovdb_convert RUNTIME DESTINATION ${NANOVDB_INSTALL_BINDIR})
endif()

# -----------------------------------------------------------------------------
# nanovdb_print
add_executable(nanovdb_print print/nanovdb_print.cc)
target_link_libraries(nanovdb_print PRIVATE nanovdb)
install(TARGETS nanovdb_print RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS nanovdb_print RUNTIME DESTINATION ${NANOVDB_INSTALL_BINDIR})

# -----------------------------------------------------------------------------
# nanovdb_validate
add_executable(nanovdb_validate validate/nanovdb_validate.cc)
target_link_libraries(nanovdb_validate PRIVATE nanovdb)
install(TARGETS nanovdb_validate RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS nanovdb_validate RUNTIME DESTINATION ${NANOVDB_INSTALL_BINDIR})
2 changes: 1 addition & 1 deletion nanovdb/nanovdb/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function(NANOVDB_EXAMPLE)
target_include_directories(${EXAMPLE_NAME} PUBLIC ex_util)
target_link_libraries(${EXAMPLE_NAME} PRIVATE nanovdb)

install(TARGETS ${EXAMPLE_NAME} DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples)
install(TARGETS ${EXAMPLE_NAME} DESTINATION ${NANOVDB_INSTALL_DOCDIR}/examples)
endfunction()

# -----------------------------------------------------------------------
Expand Down
8 changes: 7 additions & 1 deletion nanovdb/nanovdb/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ target_include_directories(nanovdb_python PRIVATE ${CUDA_INCLUDE_DIRECTORY})
target_link_libraries(nanovdb_python PRIVATE nanovdb ${CUDA_LIBRARIES} ${NANOVDB_BLOSC} ${NANOVDB_ZLIB} ${NANOVDB_OPENVDB} ${NANOVDB_TBB})
target_compile_definitions(nanovdb_python PRIVATE ${NANOVDB_USE_CUDA_FLAG} ${NANOVDB_USE_BLOSC_FLAG} ${NANOVDB_USE_ZLIB_FLAG} ${NANOVDB_USE_OPENVDB_FLAG} ${NANOVDB_USE_TBB_FLAG})
set_target_properties(nanovdb_python PROPERTIES OUTPUT_NAME "nanovdb")
install(TARGETS nanovdb_python DESTINATION ${VDB_PYTHON_INSTALL_DIRECTORY})
if(SKBUILD)
set_target_properties(nanovdb_python PROPERTIES INSTALL_RPATH "$ORIGIN/../../openvdb/lib")
install(TARGETS nanovdb_python DESTINATION ${NANOVDB_INSTALL_LIBDIR})
install(FILES __init__.py DESTINATION nanovdb)
else()
install(TARGETS nanovdb_python DESTINATION ${VDB_PYTHON_INSTALL_DIRECTORY})
endif()
# pytest
if(NANOVDB_BUILD_PYTHON_UNITTESTS)
Expand Down
7 changes: 7 additions & 0 deletions nanovdb/nanovdb/python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import sys
if sys.platform == "win32":
import os
openvdb_dll_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, 'openvdb', 'lib')
os.add_dll_directory(directory)

from .lib.nanovdb import *
32 changes: 16 additions & 16 deletions openvdb/openvdb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -720,27 +720,27 @@ endif()

if(OPENVDB_CORE_STATIC)
install(TARGETS openvdb_static
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR}
LIBRARY DESTINATION ${OPENVDB_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${OPENVDB_INSTALL_LIBDIR}
)
endif()

if(OPENVDB_CORE_SHARED)
install(TARGETS openvdb_shared
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR}
LIBRARY DESTINATION ${OPENVDB_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${OPENVDB_INSTALL_LIBDIR}
)
endif()

install(FILES ${OPENVDB_LIBRARY_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/openvdb/version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb)
install(FILES ${OPENVDB_LIBRARY_IO_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/io)
install(FILES ${OPENVDB_LIBRARY_MATH_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/math)
install(FILES ${OPENVDB_LIBRARY_POINTS_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/points)
install(FILES ${OPENVDB_LIBRARY_POINTS_IMPL_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/points/impl)
install(FILES ${OPENVDB_LIBRARY_TOOLS_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/tools)
install(FILES ${OPENVDB_LIBRARY_TREE_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/tree)
install(FILES ${OPENVDB_LIBRARY_UTIL_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/util)
install(FILES ${OPENVDB_LIBRARY_THREAD_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb/thread)
install(FILES ${OPENVDB_LIBRARY_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/openvdb/version.h DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb)
install(FILES ${OPENVDB_LIBRARY_IO_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/io)
install(FILES ${OPENVDB_LIBRARY_MATH_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/math)
install(FILES ${OPENVDB_LIBRARY_POINTS_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/points)
install(FILES ${OPENVDB_LIBRARY_POINTS_IMPL_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/points/impl)
install(FILES ${OPENVDB_LIBRARY_TOOLS_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/tools)
install(FILES ${OPENVDB_LIBRARY_TREE_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/tree)
install(FILES ${OPENVDB_LIBRARY_UTIL_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/util)
install(FILES ${OPENVDB_LIBRARY_THREAD_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb/thread)
9 changes: 7 additions & 2 deletions openvdb/openvdb/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,13 @@ if(USE_AX)
target_compile_definitions(openvdb_python PUBLIC "-DPY_OPENVDB_USE_AX")
endif()
set_target_properties(openvdb_python PROPERTIES OUTPUT_NAME "openvdb")
install(TARGETS openvdb_python DESTINATION ${VDB_PYTHON_INSTALL_DIRECTORY})
if(SKBUILD)
set_target_properties(openvdb_python PROPERTIES INSTALL_RPATH "$ORIGIN")
install(TARGETS openvdb_python DESTINATION ${OPENVDB_INSTALL_LIBDIR})
install(FILES __init__.py DESTINATION openvdb)
else()
install(TARGETS openvdb_python DESTINATION ${VDB_PYTHON_INSTALL_DIRECTORY})
endif()
# pytest
if(OPENVDB_BUILD_PYTHON_UNITTESTS)
Expand Down
1 change: 1 addition & 0 deletions openvdb/openvdb/python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .lib.openvdb import *
20 changes: 10 additions & 10 deletions openvdb_ax/openvdb_ax/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -354,23 +354,23 @@ if(OPENVDB_AX_SHARED)
endif()
endif()

install(FILES ax.h Exceptions.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb_ax/)
install(FILES ${OPENVDB_AX_AST_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb_ax/ast)
install(FILES ${OPENVDB_AX_CODEGEN_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb_ax/codegen)
install(FILES ${OPENVDB_AX_COMPILER_INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/openvdb_ax/compiler)
install(FILES ax.h Exceptions.h DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb_ax/)
install(FILES ${OPENVDB_AX_AST_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb_ax/ast)
install(FILES ${OPENVDB_AX_CODEGEN_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb_ax/codegen)
install(FILES ${OPENVDB_AX_COMPILER_INCLUDE_FILES} DESTINATION ${OPENVDB_INSTALL_INCLUDEDIR}/openvdb_ax/compiler)

if(OPENVDB_AX_STATIC)
install(TARGETS openvdb_ax_static
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR}
LIBRARY DESTINATION ${OPENVDB_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${OPENVDB_INSTALL_LIBDIR}
)
endif()

if(OPENVDB_AX_SHARED)
install(TARGETS openvdb_ax_shared
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR}
LIBRARY DESTINATION ${OPENVDB_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${OPENVDB_INSTALL_LIBDIR}
)
endif()
2 changes: 1 addition & 1 deletion openvdb_cmd/vdb_ax/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ set(SOURCE_FILES main.cc)
add_executable(vdb_ax ${SOURCE_FILES})
target_link_libraries(vdb_ax ${OPENVDB_BINARIES_DEPENDENT_LIBS})

install(TARGETS vdb_ax RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS vdb_ax RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR})
2 changes: 1 addition & 1 deletion openvdb_cmd/vdb_lod/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ set(SOURCE_FILES main.cc)
add_executable(vdb_lod ${SOURCE_FILES})
target_link_libraries(vdb_lod ${OPENVDB_BINARIES_DEPENDENT_LIBS})

install(TARGETS vdb_lod RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS vdb_lod RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR})
2 changes: 1 addition & 1 deletion openvdb_cmd/vdb_print/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ set(SOURCE_FILES main.cc)
add_executable(vdb_print ${SOURCE_FILES})
target_link_libraries(vdb_print ${OPENVDB_BINARIES_DEPENDENT_LIBS})

install(TARGETS vdb_print RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS vdb_print RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR})
2 changes: 1 addition & 1 deletion openvdb_cmd/vdb_render/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ target_link_libraries(vdb_render
$<TARGET_NAME_IF_EXISTS:PNG::PNG>
)

install(TARGETS vdb_render RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS vdb_render RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR})
2 changes: 1 addition & 1 deletion openvdb_cmd/vdb_tool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ target_include_directories(vdb_tool_common INTERFACE "${Boost_INCLUDE_DIRS}" "${
add_executable(vdb_tool src/main.cpp)
target_include_directories(vdb_tool PRIVATE vdb_tool_common)
target_link_libraries(vdb_tool PRIVATE vdb_tool_common)
install(TARGETS vdb_tool RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS vdb_tool RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR})


# unit test
Expand Down
2 changes: 1 addition & 1 deletion openvdb_cmd/vdb_view/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ endif()

target_compile_definitions(vdb_view PRIVATE -DGL_GLEXT_PROTOTYPES=1)

install(TARGETS vdb_view RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS vdb_view RUNTIME DESTINATION ${OPENVDB_INSTALL_BINDIR})
46 changes: 46 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[build-system]
requires = ["scikit_build_core", "nanobind"]
build-backend = "scikit_build_core.build"

[project]
name = "openvdb"
version = "11.0.1"
description= "Python bindings for OpenVDB: sparse volume data structure and tools."
dependencies = [
"numpy",
]
authors = [
{ name = "OpenVDB Developer Team", email = "[email protected]" },
]
requires-python = ">=3.8"
classifiers = [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]

[project.urls]
homepage = "https://www.openvdb.org/"
documentation = "https://www.openvdb.org/documentation"
forum = "https://github.com/AcademySoftwareFoundation/openvdb/discussions"
repository = "https://github.com/AcademySoftwareFoundation/openvdb"
slack = "https://slack.aswf.io/"

[tool.scikit-build]
wheel.packages = []

[tool.scikit-build.cmake.define]
OPENVDB_CORE_STATIC="OFF"
USE_EXPLICIT_INSTANTIATION="OFF"
DISABLE_DEPENDENCY_VERSION_CHECKS="ON"
OPENVDB_USE_DELAYED_LOADING="OFF"
OPENVDB_BUILD_PYTHON_MODULE="ON"
USE_NUMPY="ON"

USE_NANOVDB="ON"
NANOVDB_USE_CUDA="ON"
NANOVDB_BUILD_PYTHON_MODULE="ON"
NANOVDB_USE_OPENVDB="ON"

0 comments on commit 58c8d3a

Please sign in to comment.