diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 39c1e65..b02653e 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,9 +1,11 @@ name: pre-commit on: + workflow_dispatch: pull_request: push: - branches: [main] + branches: + - main jobs: pre-commit: diff --git a/.github/workflows/ubuntu-build.yml b/.github/workflows/ubuntu-build.yml new file mode 100644 index 0000000..349f070 --- /dev/null +++ b/.github/workflows/ubuntu-build.yml @@ -0,0 +1,48 @@ +name: ubuntu-build + +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + +concurrency: + group: ci-${{github.workflow}}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-22.04 + name: ubuntu-build + steps: + - name: Show env + run: env + + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Build Dependencies + shell: bash + run: | + sudo apt update && sudo apt install --no-install-recommends -y \ + cmake \ + make + + - name: Show Python version and platform info + run: | + python --version + python -m platform + + - name: Show CMake version + run: cmake --version + + - name: CMake Configure + shell: bash + run: | + cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE=ON + + - name: CMake Build + shell: bash + run: | + cmake --build build -j$(nproc) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e936f66 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,138 @@ +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) + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# ============================================================================ +# Options + +option(BUILD_TESTS "Build tests." OFF) + +# ============================================================================ +# Find Python + +find_package(Python COMPONENTS Interpreter Development) + +# ============================================================================ +# Build dependencies + +set(_absl_repository "https://github.com/abseil/abseil-cpp.git") +set(_absl_version 20220623.1) +set(_absl_tag 20220623.1) + +set(_protobuf_repository "https://github.com/protocolbuffers/protobuf.git") +set(_protobuf_version 21.5) +set(_protobuf_tag v21.5) + +set(_pybind11_repository "https://github.com/pybind/pybind11.git") +set(_pybind11_version 2.10) +set(_pybind11_tag v2.10.1) + +add_subdirectory(cmake/dependencies dependencies) + +# ============================================================================ +# 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..439cd64 --- /dev/null +++ b/cmake/dependencies/CMakeLists.txt @@ -0,0 +1,64 @@ +include(FetchContent) + +# ============================================================================ +# Declare all dependencies first + +find_package(absl ${_absl_version} EXACT QUIET) +if(NOT absl_FOUND) + set(ABSL_PROPAGATE_CXX_STD ON) + FetchContent_Declare( + absl + GIT_REPOSITORY ${_absl_repository} + GIT_TAG ${_absl_tag}) +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 +find_package(Protobuf ${_protobuf_version} EXACT QUIET) +if(NOT Protobuf_FOUND) + set(protobuf_BUILD_TESTS + OFF + CACHE INTERNAL "") + FetchContent_Declare( + Protobuf + GIT_REPOSITORY ${_protobuf_repository} + GIT_TAG ${_protobuf_tag} + GIT_SUBMODULES "") +endif() + +find_package(pybind11 ${_pybind11_version} EXACT QUIET) +if(NOT pybind11_FOUND) + set(PYBIND11_TEST OFF) + FetchContent_Declare( + pybind11 + GIT_REPOSITORY ${_pybind11_repository} + GIT_TAG ${_pybind11_tag}) +endif() + +# ============================================================================ +# Make dependencies avaialble + +if(NOT absl_FOUND) + 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(NOT Protobuf_FOUND) + 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(NOT pybind11_FOUND) + message(CHECK_START "Fetching pybind11") + list(APPEND CMAKE_MESSAGE_INDENT " ") + FetchContent_MakeAvailable(pybind11) + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(CHECK_PASS "fetched") +endif()