diff --git a/xo-pywebutil/.github/workflows/main.yml b/xo-pywebutil/.github/workflows/main.yml new file mode 100644 index 00000000..0b2676ed --- /dev/null +++ b/xo-pywebutil/.github/workflows/main.yml @@ -0,0 +1,177 @@ +name: build xo-pywebutil + dependencies + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # You can convert this to a matrix build if you need cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - name: checkout source + uses: actions/checkout@v3 + + - name: Install catch2 + # install catch2. see [[https://stackoverflow.com/questions/57982945/how-to-apt-get-install-in-a-github-actions-workflow]] + run: sudo apt-get install -y catch2 + + - name: Install pybind11-dev + run: sudo apt-get install -y pybind11-dev + + # ---------------------------------------------------------------- + + - name: Clone xo-cmake + uses: actions/checkout@v3 + with: + repository: Rconybea/xo-cmake + path: repo/xo-cmake + + - name: Configure xo-cmake + run: cmake -B ${{github.workspace}}/build_xo-cmake -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local repo/xo-cmake + + - name: Build xo-cmake (trivial) + run: cmake --build ${{github.workspace}}/build_xo-cmake --config ${{env.BUILD_TYPE}} + + - name: Install xo-cmake + run: cmake --install ${{github.workspace}}/build_xo-cmake + + # ---------------------------------------------------------------- + + - name: Clone indentlog + uses: actions/checkout@v3 + with: + repository: Rconybea/indentlog + path: repo/indentlog + + - name: Configure indentlog + # configure cmake for indentlog in dedicated build directory. + run: cmake -B ${{github.workspace}}/build_indentlog -DCMAKE_MODULE_PATH=${{github.workspace}}/local/share/cmake -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local repo/indentlog + + - name: Build indentlog + run: cmake --build ${{github.workspace}}/build_indentlog --config ${{env.BUILD_TYPE}} + + - name: Install indentlog + # install into ${{github.workspace}}/local + run: cmake --install ${{github.workspace}}/build_indentlog + +# # ---------------------------------------------------------------- +# +# - name: Clone subsys +# uses: actions/checkout@v3 +# with: +# repository: Rconybea/subsys +# path: repo/subsys +# +# - name: Configure subsys +# # configure cmake for subsys in dedicated build directory. +# run: cmake -B ${{github.workspace}}/build_subsys -DCMAKE_MODULE_PATH=${{github.workspace}}/local/share/cmake -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local repo/subsys +# +# - name: Build subsys +# run: cmake --build ${{github.workspace}}/build_subsys --config ${{env.BUILD_TYPE}} +# +# - name: Install subsys +# # install into ${{github.workspace}}/local +# run: cmake --install ${{github.workspace}}/build_subsys + + # ---------------------------------------------------------------- + + - name: Clone refcnt + uses: actions/checkout@v3 + with: + repository: Rconybea/refcnt + path: repo/refcnt + + - name: Configure refcnt + # configure cmake for refcnt in dedicated build directory. + run: cmake -B ${{github.workspace}}/build_refcnt -DCMAKE_MODULE_PATH=${{github.workspace}}/local/share/cmake -DCMAKE_PREFIX_PATH=${{github.workspace}}/local -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local repo/refcnt + + - name: Build refcnt + run: cmake --build ${{github.workspace}}/build_refcnt --config ${{env.BUILD_TYPE}} + + - name: Install refcnt + # install into ${{github.workspace}}/local + run: cmake --install ${{github.workspace}}/build_refcnt + + # ---------------------------------------------------------------- + + - name: Clone callback + uses: actions/checkout@v3 + with: + repository: Rconybea/xo-callback + path: repo/callback + + - name: Configure callback + # configure cmake for callback in dedicated build directory. + run: cmake -B ${{github.workspace}}/build_callback -DCMAKE_MODULE_PATH=${{github.workspace}}/local/share/cmake -DCMAKE_PREFIX_PATH=${{github.workspace}}/local -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local repo/callback + + - name: Build callback + run: cmake --build ${{github.workspace}}/build_callback --config ${{env.BUILD_TYPE}} + + - name: Install callback + # install into ${{github.workspace}}/local + run: cmake --install ${{github.workspace}}/build_callback + + # ---------------------------------------------------------------- + + - name: Clone webutil + uses: actions/checkout@v3 + with: + repository: Rconybea/xo-webutil + path: repo/webutil + + - name: Configure webutil + # configure cmake for webutil in dedicated build directory. + run: cmake -B ${{github.workspace}}/build_webutil -DCMAKE_MODULE_PATH=${{github.workspace}}/local/share/cmake -DCMAKE_PREFIX_PATH=${{github.workspace}}/local -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local repo/webutil + + - name: Build webutil + run: cmake --build ${{github.workspace}}/build_webutil --config ${{env.BUILD_TYPE}} + + - name: Install webutil + # install into ${{github.workspace}}/local + run: cmake --install ${{github.workspace}}/build_webutil + + # ---------------------------------------------------------------- + + - name: Clone pyutil + uses: actions/checkout@v3 + with: + repository: Rconybea/xo-pyutil + path: repo/pyutil + + - name: Configure pyutil + # configure cmake for pyutil in dedicated build directory. + run: cmake -B ${{github.workspace}}/build_pyutil -DCMAKE_MODULE_PATH=${{github.workspace}}/local/share/cmake -DCMAKE_PREFIX_PATH=${{github.workspace}}/local -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local repo/pyutil + + - name: Build pyutil + run: cmake --build ${{github.workspace}}/build_pyutil --config ${{env.BUILD_TYPE}} + + - name: Install pyutil + # install into ${{github.workspace}}/local + run: cmake --install ${{github.workspace}}/build_pyutil + + # ---------------------------------------------------------------- + + - name: Configure self (pywebutil) + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build_pywebutil -DCMAKE_MODULE_PATH=${{github.workspace}}/local/share/cmake -DCMAKE_PREFIX_PATH=${{github.workspace}}/local -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/local -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build self (pywebutil) + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build_pywebutil --config ${{env.BUILD_TYPE}} + + - name: Test self (pywebutil) + working-directory: ${{github.workspace}}/build_pywebutil + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest -C ${{env.BUILD_TYPE}} diff --git a/xo-pywebutil/.gitignore b/xo-pywebutil/.gitignore new file mode 100644 index 00000000..53a9c92f --- /dev/null +++ b/xo-pywebutil/.gitignore @@ -0,0 +1,6 @@ +# lsp keeps state here +.cache +# typical build directory +.build* +# lsp: symlink to file in build directory (established manually) +compile_commands.json diff --git a/xo-pywebutil/CMakeLists.txt b/xo-pywebutil/CMakeLists.txt new file mode 100644 index 00000000..9851b8cd --- /dev/null +++ b/xo-pywebutil/CMakeLists.txt @@ -0,0 +1,26 @@ +# xo-pywebutil/CMakeLists.txt + +cmake_minimum_required(VERSION 3.10) + +project(xo_pywebutil VERSION 0.1) + +include(GNUInstallDirs) +include(cmake/xo-bootstrap-macros.cmake) + +xo_cxx_toplevel_options3() + +# ---------------------------------------------------------------- +# c++ settings (usually temporary) + +set(PROJECT_CXX_FLAGS "") +add_definitions(${PROJECT_CXX_FLAGS}) + +# ---------------------------------------------------------------- +# sources + +add_subdirectory(src/pywebutil) + +# ---------------------------------------------------------------- +# provide find_package() support + +xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) diff --git a/xo-pywebutil/EXAMPLES b/xo-pywebutil/EXAMPLES new file mode 100644 index 00000000..a495d316 --- /dev/null +++ b/xo-pywebutil/EXAMPLES @@ -0,0 +1,9 @@ +Creating this pybind11 library to hold low-dependency wrappers +used for interaction between {websock/, pywebsock/} and other subsystems. + +1. This library needs to be a (runtime) dependency of pyxxx libraries that + use reactor::EventStore, for example pyprocess/, to supply wrappers + for EndpointDescr and Alist. + +2. If we chose to put this code in pywebsock/, then pywebsock + libwebsocket + would become runtime dependencies of libraries like pyprocess/. diff --git a/xo-pywebutil/README.md b/xo-pywebutil/README.md new file mode 100644 index 00000000..52d702da --- /dev/null +++ b/xo-pywebutil/README.md @@ -0,0 +1,70 @@ +# python bindings for c++ webutil library (xo-webutil) + +## Getting Started + +### build + install dependencies + +- [github/Rconybea/xo-pyutil](https://github.com/Rconybea/xo-pyutil) +- [github/Rconybea/xo-webutil](https://github.com/Rconybea/xo-webutil) + +### build + install + +``` +$ cd xo-pywebutil +$ mkdir build +$ cd build +$ INSTALL_PREFIX=/usr/local # or wherever you prefer, e.g. ~/local +$ cmake \ + -DCMAKE_MODULE_PATH=${INSTALL_PREFIX}/share/cmake \ + -DCMAKE_PREFIX_PATH=${INSTALL_PREFIX} \ + -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} .. +$ make +$ make install +``` +(also see .github/workflows/main.yml) + +## Examples + +Assumes `xo-pywebutil` installed to `~/local2/lib` +``` +$ PYTHONPATH=~/local2/lib:$PYTHONPATH python +>>> import xo_pywebutil +>>> dir(xo_pywebutil) +['EndpointDescr', 'StreamEndpointDescr', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__'] +>>> from xo_pywebutil import * +``` + +## Development + +### build for unit test coverage +``` +$ cd xo-pywebutil +$ mkdir build-ccov +$ cd build-ccov +$ cmake \ + -DCMAKE_MODULE_PATH=${INSTALL_PREFIX}/share/cmake \ + -DCMAKE_PREFIX_PATH=${INSTALL_PREFIX} \ + -DCODE_COVERAGE=ON \ + -DCMAKE_BUILD_TYPE=Debug .. +``` + +### LSP (language server) support + +LSP looks for compile commands in the root of the source tree; +while Cmake creates them in the root of its build directory. + +``` +$ cd xo-pywebutil +$ ln -s build/compile_commands.json # supply compile commands to LSP +``` + +### display cmake variables + +- `-L` list variables +- `-A` include 'advanced' variables +- `-H` include help text + +``` +$ cd xo-pywebutil/build +$ cmake -LAH +``` diff --git a/xo-pywebutil/cmake/xo-bootstrap-macros.cmake b/xo-pywebutil/cmake/xo-bootstrap-macros.cmake new file mode 100644 index 00000000..aba31169 --- /dev/null +++ b/xo-pywebutil/cmake/xo-bootstrap-macros.cmake @@ -0,0 +1,35 @@ +# ---------------------------------------------------------------- +# for example: +# $ PREFIX=/usr/local # for example +# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build +# +# will get +# CMAKE_MODULE_PATH +# from xo-cmake-config --cmake-module-path +# +# and expect .cmake macros in +# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake +# ---------------------------------------------------------------- + +find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED) + +if ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND") + message(FATAL "could not find xo-cmake-config executable") +endif() + +message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}") + +if (NOT XO_SUBMODULE_BUILD) + if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix)) + # default to typical install location for xo-project-macros + execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH) + message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}") + endif() +endif() + +# needs to have been installed somewhere on CMAKE_MODULE_PATH, +# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX) +# +include(xo_macros/xo_cxx) + +xo_cxx_bootstrap_message() diff --git a/xo-pywebutil/cmake/xo_pywebutilConfig.cmake.in b/xo-pywebutil/cmake/xo_pywebutilConfig.cmake.in new file mode 100644 index 00000000..18eaf04d --- /dev/null +++ b/xo-pywebutil/cmake/xo_pywebutilConfig.cmake.in @@ -0,0 +1,6 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) +find_dependency(xo_pyutil) +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") +check_required_components("@PROJECT_NAME@") diff --git a/xo-pywebutil/include/README.md b/xo-pywebutil/include/README.md new file mode 100644 index 00000000..3df846f2 --- /dev/null +++ b/xo-pywebutil/include/README.md @@ -0,0 +1 @@ +placeholder for future pywebutil #include files diff --git a/xo-pywebutil/src/pywebutil/CMakeLists.txt b/xo-pywebutil/src/pywebutil/CMakeLists.txt new file mode 100644 index 00000000..cc68d6e1 --- /dev/null +++ b/xo-pywebutil/src/pywebutil/CMakeLists.txt @@ -0,0 +1,8 @@ +# xo-pywebutil/src/pywebutil/CMakeLists.txt + +set(SELF_LIB xo_pywebutil) +set(SELF_SRCS pywebutil.cpp) + +xo_pybind11_library(${SELF_LIB} ${PROJECT_NAME}Targets ${SELF_SRCS}) +xo_pybind11_dependency(${SELF_LIB} webutil) +xo_pybind11_dependency(${SELF_LIB} xo_pyutil) diff --git a/xo-pywebutil/src/pywebutil/pywebutil.cpp b/xo-pywebutil/src/pywebutil/pywebutil.cpp new file mode 100644 index 00000000..8618eba9 --- /dev/null +++ b/xo-pywebutil/src/pywebutil/pywebutil.cpp @@ -0,0 +1,33 @@ +/* @file pywebutil.cpp */ + +#include "pywebutil.hpp" +#include "xo/webutil/HttpEndpointDescr.hpp" +#include "xo/webutil/StreamEndpointDescr.hpp" +#include "xo/pyutil/pyutil.hpp" +#include + +namespace xo { + //using xo::web::Alist; + using xo::web::HttpEndpointDescr; + //using xo::time::utc_nanos; + namespace py = pybind11; + + namespace web { + PYBIND11_MODULE(PYWEBUTIL_MODULE_NAME(), m) { + //PYxxx_IMPORT_MODULE(); + + /* module docstring */ + m.doc() = "pybind11 plugin for xo.web_util"; + + py::class_(m, "EndpointDescr") + .def_property_readonly("uri_pattern", &HttpEndpointDescr::uri_pattern) + .def("__repr__", &HttpEndpointDescr::display_string); + + py::class_(m, "StreamEndpointDescr") + .def_property_readonly("uri_pattern", &StreamEndpointDescr::uri_pattern) + .def("__repr__", &StreamEndpointDescr::display_string); + } /*web*/ + } /*namespace web*/ +} /*namespace xo*/ + +/* end pywebutil.cpp */ diff --git a/xo-pywebutil/src/pywebutil/pywebutil.hpp.in b/xo-pywebutil/src/pywebutil/pywebutil.hpp.in new file mode 100644 index 00000000..086701c1 --- /dev/null +++ b/xo-pywebutil/src/pywebutil/pywebutil.hpp.in @@ -0,0 +1,25 @@ +/* @file pywebutil.hpp + * + * automatically generated from src/pywebutil/pywebutil.hpp.in + * see src/pywebutil/CMakeLists.txt + */ + +/* python requires module name = library name + * example: + * PYBIND11_MODULE(PYWEBUTIL_MODULE_NAME(), m) { ... } + */ +#define PYWEBUTIL_MODULE_NAME() @SELF_LIB@ + +/* example: + * py::module_::import(PYWEBUTIL_MODULE_NAME_STR) + */ +#define PYWEBUTIL_MODULE_NAME_STR "@SELF_LIB@" + +/* example: + * PYWEBUTIL_IMPORT_MODULE() + * replaces + * py::module_::import("pywebutil") + */ +#define PYWEBUTIL_IMPORT_MODULE() py::module_::import("@SELF_LIB@") + +/* end pywebutil.hpp */