diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0e22d48 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,196 @@ +cmake_minimum_required(VERSION 3.18) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +project(pybind11_protobuf ) + +if(MSVC) + set(CMAKE_CXX_STANDARD 20) +else() + set(CMAKE_CXX_STANDARD 17) +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + + +#============================================================================ +# Warnings + +message(WARNING "CI testing for pybind11_protobuf cmake is currently MISSING! (https://github.com/pybind/pybind11_protobuf/issues/104)") + +#============================================================================ +# Options + +option(BUILD_absl "Build the abseil-cpp dependency Library" ON) +message(STATUS "Build abseil-cpp: ${BUILD_absl}") + +option(BUILD_protobuf "Build the Protobuf dependency Library" ON) +message(STATUS "Build protobuf: ${BUILD_protobuf}") + +option(BUILD_pybind11 "Build the pybind11 dependency Library" ON) +message(STATUS "Python: Build pybind11: ${BUILD_pybind11}") + +#============================================================================ +# Find Python + +find_package(Python COMPONENTS Interpreter Development) + +#============================================================================ +# Build dependencies + +add_subdirectory(cmake/dependencies dependencies) + +include(deps) + +include(CMakeFindDependencyMacro) +include(FindProtobuf) +if (NOT protobuf_FOUND AND NOT PROTOBUF_FOUND AND NOT TARGET protobuf::libprotobuf) + if (BUILD_protobuf) + find_dependency(protobuf CONFIG REQUIRED) + endif() +endif() + +#============================================================================ +# Debug messages for find_package + +# message("pybind11_FOUND: ${pybind11_FOUND}") +# message("pybind11_VERSION: ${pybind11_VERSION}") +# message("pybind11_VERSION_TYPE: ${pybind11_VERSION_TYPE}") +# message("pybind11_INCLUDE_DIRS: ${pybind11_INCLUDE_DIRS}") +# message("pybind11_INCLUDE_DIR: ${pybind11_INCLUDE_DIR}") +# message("pybind11_DEFINITIONS: ${pybind11_DEFINITIONS}") +# message("pybind11_LIBRARIES: ${pybind11_LIBRARIES}") + +# message("Python_FOUND: ${Python_FOUND}") +# message("Python_VERSION: ${Python_VERSION}") +# message("Python_INCLUDE_DIRS: ${Python_INCLUDE_DIRS}") +# message("Python_LIBRARIES: ${Python_LIBRARIES}") + +# message("protobuf_FOUND: ${protobuf_FOUND}") +# message("protobuf_VERSION: ${protobuf_VERSION}") +# message("protobuf_INCLUDE_DIRS: ${protobuf_INCLUDE_DIRS}") +# message("protobuf_SOURCE_DIR: ${protobuf_SOURCE_DIR}") +# message("protobuf_LIBRARIES: ${protobuf_LIBRARIES}") + +#============================================================================ +# pybind11_proto_utils pybind11 extension module +pybind11_add_module(pybind11_proto_utils MODULE + pybind11_protobuf/proto_utils.cc + pybind11_protobuf/proto_utils.h +) + +target_link_libraries(pybind11_proto_utils + PRIVATE + absl::strings + protobuf::libprotobuf + ${Python_LIBRARIES} +) + +target_include_directories(pybind11_proto_utils + PRIVATE + ${PROJECT_SOURCE_DIR} + ${protobuf_INCLUDE_DIRS} + ${protobuf_SOURCE_DIR} + ${pybind11_INCLUDE_DIRS} +) + +#============================================================================ +# pybind11_native_proto_caster shared library +add_library(pybind11_native_proto_caster SHARED + # bazel: pybind_library: native_proto_caster + pybind11_protobuf/native_proto_caster.h + + # bazel: pybind_library: enum_type_caster + pybind11_protobuf/enum_type_caster.h + + # bazel: pybind_library: proto_cast_util + pybind11_protobuf/proto_cast_util.cc + pybind11_protobuf/proto_cast_util.h + pybind11_protobuf/proto_caster_impl.h + + # bazel: cc_library::check_unknown_fields + pybind11_protobuf/check_unknown_fields.cc + pybind11_protobuf/check_unknown_fields.h +) + +target_link_libraries(pybind11_native_proto_caster + absl::flat_hash_map + absl::flat_hash_set + absl::hash + absl::strings + absl::optional + protobuf::libprotobuf + pybind11::pybind11 + ${Python_LIBRARIES} +) + +target_include_directories(pybind11_native_proto_caster + PRIVATE + ${PROJECT_SOURCE_DIR} + ${protobuf_INCLUDE_DIRS} + ${protobuf_SOURCE_DIR} + ${pybind11_INCLUDE_DIRS} +) + +#============================================================================ +# pybind11_wrapped_proto_caster shared library +add_library(pybind11_wrapped_proto_caster SHARED + # bazel: pybind_library: wrapped_proto_caster + pybind11_protobuf/wrapped_proto_caster.h + + # bazel: pybind_library: proto_cast_util + pybind11_protobuf/proto_cast_util.cc + pybind11_protobuf/proto_cast_util.h + pybind11_protobuf/proto_caster_impl.h + + # bazel: cc_library: check_unknown_fields + pybind11_protobuf/check_unknown_fields.cc + pybind11_protobuf/check_unknown_fields.h +) + +target_link_libraries(pybind11_wrapped_proto_caster + absl::flat_hash_map + absl::flat_hash_set + absl::hash + absl::strings + absl::optional + protobuf::libprotobuf + pybind11::pybind11 + ${Python_LIBRARIES} +) + +target_include_directories(pybind11_wrapped_proto_caster + PRIVATE + ${PROJECT_SOURCE_DIR} + ${protobuf_INCLUDE_DIRS} + ${protobuf_SOURCE_DIR} + ${pybind11_INCLUDE_DIRS} +) + +# TODO set defines +# PYBIND11_PROTOBUF_ENABLE_PYPROTO_API +# see: bazel: pybind_library: proto_cast_util + +# bazel equivs. checklist +# +# bazel: pybind_library: enum_type_caster +# - enum_type_caster.h +# +# bazel: pybind_library: native_proto_caster +# - native_proto_caster.h +# +# check_unknown_fields +# enum_type_caster +# proto_cast_util +# +# bazel: pybind_library: proto_cast_util +# - proto_cast_util.cc +# - proto_cast_util.h +# - proto_caster_impl.h +# +# check_unknown_fields +# +# bazel: pybind_library: wrapped_proto_caster +# - wrapped_proto_caster.h +# +# proto_cast_util +# diff --git a/cmake/dependencies/CMakeLists.txt b/cmake/dependencies/CMakeLists.txt new file mode 100644 index 0000000..8b172aa --- /dev/null +++ b/cmake/dependencies/CMakeLists.txt @@ -0,0 +1,62 @@ +include(FetchContent) + +#============================================================================ +# Declare all dependencies first + +if(BUILD_absl) + FetchContent_Declare( + absl + GIT_REPOSITORY "https://github.com/abseil/abseil-cpp.git" + GIT_TAG "20220623.1" + ) +endif() + +# https://stackoverflow.com/questions/63309544/cmake-protobuf-external-to-application-code +# https://cmake.org/cmake/help/latest/policy/CMP0077.html +# https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7565/diffs +if(BUILD_protobuf) + set(protobuf_BUILD_TESTS OFF CACHE INTERNAL "") + FetchContent_Declare( + protobuf + GIT_REPOSITORY "https://github.com/protocolbuffers/protobuf.git" + GIT_TAG "v21.5" + GIT_SUBMODULES "" + ) +endif() + +if(BUILD_pybind11) + set(PYBIND11_TEST OFF) + FetchContent_Declare( + pybind11 + GIT_REPOSITORY "https://github.com/pybind/pybind11.git" + GIT_TAG "v2.10.1" + ) +endif() + +#============================================================================ +# Make dependencies avaialble + +if(BUILD_absl) + message(CHECK_START "Fetching Abseil-cpp") + list(APPEND CMAKE_MESSAGE_INDENT " ") + FetchContent_MakeAvailable(absl) + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(CHECK_PASS "fetched") +endif() + +if(BUILD_protobuf) + message(CHECK_START "Fetching protobuf") + list(APPEND CMAKE_MESSAGE_INDENT " ") + FetchContent_MakeAvailable(protobuf) + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(CHECK_PASS "fetched") +endif() + +if(BUILD_pybind11) + message(CHECK_START "Fetching pybind11") + list(APPEND CMAKE_MESSAGE_INDENT " ") + FetchContent_MakeAvailable(pybind11) + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(CHECK_PASS "fetched") +endif() + diff --git a/cmake/deps.cmake b/cmake/deps.cmake new file mode 100644 index 0000000..1de23be --- /dev/null +++ b/cmake/deps.cmake @@ -0,0 +1,12 @@ +if(NOT BUILD_absl) + find_package(absl REQUIRED) +endif() + +if(NOT BUILD_protobuf) + find_package(protobuf REQUIRED) +endif() + +if(NOT BUILD_pybind11) + find_package(pybind11 REQUIRED) +endif() + diff --git a/pybind11_protobuf/tests/CMakeLists.txt b/pybind11_protobuf/tests/CMakeLists.txt new file mode 100644 index 0000000..8a0222b --- /dev/null +++ b/pybind11_protobuf/tests/CMakeLists.txt @@ -0,0 +1,36 @@ +#============================================================================ +# tests +#============================================================================ + +#============================================================================ +# generate protobuf bindings + +set(Protobuf_IMPORT_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/../../..;${Protobuf_IMPORT_DIRS}" +) + +protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS + # extension.proto + test.proto +) + +protobuf_generate_python(PROTO_PYS + # extension.proto + test.proto +) + +#============================================================================ +# adding a custom target forces CMake to generate the bindings + +add_custom_target(pybind11_test_proto_cpp ALL DEPENDS ${PROTO_SRCS} ${PROTO_HDRS}) +add_custom_target(pybind11_test_proto_python ALL DEPENDS ${PROTO_PYS}) + +#============================================================================ +# generate protobuf library + +add_library(pybind11_test_proto ${PROTO_SRCS} ${PROTO_HDR}) + +target_include_directories(pybind11_test_proto + PUBLIC + ${Protobuf_INCLUDE_DIR} +)