Commit 57fb4c7c by pybind11_abseil authors Committed by Copybara-Service

Add CMake support

PiperOrigin-RevId: 557226797
parent 41f3de4d
......@@ -10,20 +10,31 @@ on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
PIP_BREAK_SYSTEM_PACKAGES: 1
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
unix:
strategy:
matrix:
runs-on: [ubuntu-latest]
build_tool: [bazel, cmake]
runs-on: ubuntu-latest
name: "${{matrix.runs-on}} ${{matrix.build_tool}}"
runs-on: ${{matrix.runs-on}}
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Show env
run: env
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- uses: actions/checkout@v3
# Runs a single command using the runners shell
- name: Install Bazel
- name: Install bazel
if: matrix.build_tool == 'bazel'
# Install Bazel, see https://docs.bazel.build/versions/master/install-ubuntu.html#step-1-install-required-packages
run: |
sudo apt install curl gnupg
......@@ -32,11 +43,28 @@ jobs:
echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
sudo apt update && sudo apt install bazel -y
- name: Show bazel version
if: matrix.build_tool == 'bazel'
run: bazel --version
- name: Update cmake
if: matrix.build_tool == 'cmake'
uses: jwlawson/actions-setup-cmake@v1.14
- name: Show cmake version
if: matrix.build_tool == 'cmake'
run: cmake --version
- name: Show platform info
run: python -m platform
- name: Install virtualenv
run: |
sudo apt-get install python3-pip -y
sudo pip3 install virtualenv
# Runs a set of commands using the runners shell
- name: Run tests
run: bash ./scripts/build_and_run_tests.sh
- name: Show nproc
run: echo nproc=$(nproc)
- name: Build and run tests
run: bash ./scripts/build_and_run_tests_${{matrix.build_tool}}.sh -j $(nproc)
\ No newline at end of file
build
tmp_build
cmake_minimum_required(VERSION 3.11)
project(pybind11_abseil LANGUAGES CXX)
include(FetchContent)
include(CTest)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
endif(NOT DEFINED CMAKE_CXX_STANDARD)
set(ABSL_PROPAGATE_CXX_STD ON)
set(BUILD_TESTING OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)
find_package(PythonLibs REQUIRED)
FetchContent_Declare(
abseil-cpp
URL https://github.com/abseil/abseil-cpp/archive/refs/tags/20211102.0.tar.gz
URL_HASH
SHA256=dcf71b9cba8dc0ca9940c4b316a0c796be8fab42b070bb6b7cab62b48f0e66c4)
FetchContent_Declare(
pybind11
URL https://github.com/pybind/pybind11/archive/refs/heads/master.tar.gz)
FetchContent_MakeAvailable(abseil-cpp pybind11)
set(TOP_LEVEL_DIR ${CMAKE_CURRENT_LIST_DIR})
include_directories(${TOP_LEVEL_DIR} ${PYTHON_INCLUDE_DIR}
${pybind11_INCLUDE_DIRS})
add_subdirectory(pybind11_abseil)
......@@ -19,6 +19,10 @@ in the .cc file with your bindings:
## Installation
pybind11_abseil can be built with Bazel or CMake. Instructions for both are below.
### Bazel
You will need to depend on `pybind11`, `pybind11_bazel`(see
[doc](https://github.com/pybind/pybind11_bazel#installation), and on
`pybind11_abseil`, e.g.
......@@ -54,6 +58,23 @@ Then, in your BUILD file:
load("@pybind11_bazel//:build_defs.bzl", "pybind_extension")
```
### CMake
In your project, add a FetchContent for pybind11_abseil. This will also fetch the
appropriate versions of Abseil and pybind11 which your project can use
(eliminating the need for submoduling Abseil or using find_package).
Add the following to your CMakeLists.txt:
```
include(FetchContent)
FetchContent_Declare {
pybind11_abseil
GIT_REPOSITORY https://github.com/pybind/pybind11_abseil.git
GIT_TAG master
}
FetchContent_MakeAvailable(pybind11 abseil-cpp pybind11_abseil)
```
## absl::Duration
`absl::Duration` objects are converted to/ from python datetime.timedelta objects.
......
add_subdirectory(cpp_capsule_tools)
# absl_casters ============================================================
add_library(absl_casters INTERFACE)
add_library(pybind11_abseil::absl_casters ALIAS absl_casters)
target_include_directories(absl_casters
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(
absl_casters
INTERFACE absl::cleanup
absl::btree
absl::flat_hash_map
absl::flat_hash_set
absl::node_hash_map
absl::node_hash_set
absl::strings
absl::time
absl::optional
absl::span)
# ok_status_singleton_lib ======================================================
add_library(ok_status_singleton_lib STATIC ok_status_singleton_lib.cc)
add_library(pybind11_abseil::ok_status_singleton_lib ALIAS
ok_status_singleton_lib)
target_include_directories(ok_status_singleton_lib
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(ok_status_singleton_lib PUBLIC absl::status)
# ok_status_singleton_pyinit_google3 ===========================================
add_library(ok_status_singleton_pyinit_google3 STATIC
ok_status_singleton_pyinit_google3.cc)
target_link_libraries(ok_status_singleton_pyinit_google3
PUBLIC ok_status_singleton_lib)
# ok_status_singleton =======================================================
add_library(ok_status_singleton SHARED ok_status_singleton_py_extension_stub.cc)
add_library(pybind11_abseil::ok_status_singleton ALIAS ok_status_singleton)
target_include_directories(ok_status_singleton
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
set_target_properties(ok_status_singleton PROPERTIES PREFIX "")
target_link_libraries(ok_status_singleton
PUBLIC ok_status_singleton_pyinit_google3)
# no_throw_status ==============================================================
add_library(no_throw_status INTERFACE)
add_library(pybind11_abseil::no_throw_status ALIAS no_throw_status)
target_include_directories(no_throw_status
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
# status_not_ok_exception ======================================================
add_library(status_not_ok_exception INTERFACE)
add_library(pybind11_abseil::status_not_ok_exception ALIAS
status_not_ok_exception)
target_include_directories(status_not_ok_exception
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(status_not_ok_exception INTERFACE absl::status)
# check_status_module_imported =================================================
add_library(check_status_module_imported INTERFACE)
target_link_libraries(check_status_module_imported INTERFACE absl::status)
# status_caster ================================================================
add_library(status_caster INTERFACE)
add_library(pybind11_abseil::status_caster ALIAS status_caster)
target_include_directories(status_caster
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(
status_caster
INTERFACE check_status_module_imported
no_throw_status
ok_status_singleton_lib
status_not_ok_exception
raw_ptr_from_capsule
absl::status
absl::statusor)
# statusor_caster ==============================================================
add_library(statusor_caster INTERFACE)
add_library(pybind11_abseil::statusor_caster ALIAS statusor_caster)
target_include_directories(statusor_caster
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(
statusor_caster INTERFACE check_status_module_imported no_throw_status
status_caster absl::status absl::statusor)
# init_from_tag ================================================================
add_library(init_from_tag INTERFACE)
add_library(pybind11_abseil::init_from_tag ALIAS init_from_tag)
target_include_directories(init_from_tag
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
# utils_pybind11_absl ==========================================================
add_library(utils_pybind11_absl STATIC utils_pybind11_absl.cc)
target_link_libraries(utils_pybind11_absl PUBLIC absl::strings)
# register_status_bindings =====================================================
add_library(register_status_bindings STATIC register_status_bindings.cc)
target_link_libraries(
register_status_bindings
PUBLIC absl_casters
init_from_tag
no_throw_status
ok_status_singleton_lib
status_caster
status_not_ok_exception
utils_pybind11_absl
raw_ptr_from_capsule
absl::status
absl::statusor
absl::strings)
# status_pyinit_google3 ========================================================
add_library(status_pyinit_google3 STATIC status_pyinit_google3.cc)
target_link_libraries(status_pyinit_google3 PUBLIC register_status_bindings)
# status ====================================================================
add_library(status SHARED status_py_extension_stub.cc)
add_library(pybind11_abseil::status ALIAS status)
target_include_directories(status INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
set_target_properties(status PROPERTIES PREFIX "")
target_link_libraries(status PUBLIC status_pyinit_google3 absl::status)
# import_status_module =========================================================
add_library(import_status_module STATIC import_status_module.cc)
add_library(pybind11_abseil::import_status_module ALIAS import_status_module)
target_include_directories(import_status_module
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(import_status_module PUBLIC status)
# status_casters ===============================================================
add_library(status_casters INTERFACE)
add_library(pybind11_abseil::status_casters ALIAS status_casters)
target_include_directories(status_casters
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(status_casters INTERFACE import_status_module
status_caster statusor_caster)
add_subdirectory(tests)
\ No newline at end of file
# void_ptr_from_capsule ========================================================
add_library(void_ptr_from_capsule STATIC void_ptr_from_capsule.cc)
add_library(pybind11_abseil::cpp_capsule_tools::void_ptr_from_capsule ALIAS
void_ptr_from_capsule)
target_include_directories(void_ptr_from_capsule
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(void_ptr_from_capsule PUBLIC absl::status absl::statusor
absl::strings)
# raw_ptr_from_capsule =========================================================
add_library(raw_ptr_from_capsule INTERFACE)
add_library(pybind11_abseil::cpp_capsule_tools::raw_ptr_from_capsule ALIAS
raw_ptr_from_capsule)
target_include_directories(raw_ptr_from_capsule
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(
raw_ptr_from_capsule INTERFACE void_ptr_from_capsule absl::statusor
# python_headers does not need to be linked
)
# make_shared_ptr_capsule ======================================================
add_library(make_shared_ptr_capsule INTERFACE)
add_library(pybind11_abseil::cpp_capsule_tools::make_shared_ptr_capsule ALIAS
make_shared_ptr_capsule)
target_include_directories(make_shared_ptr_capsule
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
# shared_ptr_from_capsule ======================================================
add_library(shared_ptr_from_capsule INTERFACE)
add_library(pybind11_abseil::cpp_capsule_tools::shared_ptr_from_capsule ALIAS
shared_ptr_from_capsule)
target_include_directories(shared_ptr_from_capsule
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
target_link_libraries(
shared_ptr_from_capsule INTERFACE void_ptr_from_capsule absl::statusor
# python_headers does not need to be linked
)
\ No newline at end of file
# cpp_capsule_tools_testing ====================================================
pybind11_add_module(cpp_capsule_tools_testing SHARED
cpp_capsule_tools_testing.cc)
target_link_libraries(
cpp_capsule_tools_testing PUBLIC make_shared_ptr_capsule raw_ptr_from_capsule
shared_ptr_from_capsule absl::statusor)
# cpp_capsule_tools_testing_test ===============================================
add_test(
NAME cpp_capsule_tools_testing_test
COMMAND
${CMAKE_COMMAND} -E env PYTHONPATH=$PYTHONPATH:${CMAKE_BINARY_DIR}
${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/cpp_capsule_tools_testing_test.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# absl_example =================================================================
pybind11_add_module(absl_example SHARED absl_example.cc)
target_link_libraries(
absl_example
PRIVATE absl_casters
absl::btree
absl::flat_hash_set
absl::strings
absl::time
absl::optional
absl::span)
# absl_test ====================================================================
add_test(
NAME absl_test
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=$PYTHONPATH:${CMAKE_BINARY_DIR}
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/absl_test.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# ok_status_singleton_test =====================================================
add_test(
NAME ok_status_singleton_test
COMMAND
${CMAKE_COMMAND} -E env PYTHONPATH=$PYTHONPATH:${CMAKE_BINARY_DIR}
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/ok_status_singleton_test.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# missing_import ===============================================================
pybind11_add_module(missing_import SHARED missing_import.cc)
target_compile_options(missing_import PUBLIC -UNDEBUG)
target_link_libraries(missing_import PRIVATE status_casters absl::status
absl::statusor)
# missing_import_test ==========================================================
add_test(
NAME missing_import_test
COMMAND
${CMAKE_COMMAND} -E env PYTHONPATH=$PYTHONPATH:${CMAKE_BINARY_DIR}
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/missing_import_test.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# status_test ==================================================================
add_test(
NAME status_test
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=$PYTHONPATH:${CMAKE_BINARY_DIR}
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/status_test.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# status_example ===============================================================
pybind11_add_module(status_example SHARED status_example.cc)
target_link_libraries(status_example PRIVATE status_casters absl::status
absl::statusor)
# status_example_test ==========================================================
add_test(
NAME status_example_test
COMMAND
${CMAKE_COMMAND} -E env PYTHONPATH=$PYTHONPATH:${CMAKE_BINARY_DIR}
${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/status_example_test.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
\ No newline at end of file
......@@ -3,6 +3,8 @@
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
import sys
from absl.testing import absltest
from pybind11_abseil import ok_status_singleton
......@@ -12,8 +14,11 @@ class OkStatusSingletonTest(absltest.TestCase):
def test_singleton(self):
cap = ok_status_singleton.OkStatusSingleton()
self.assertStartsWith(repr(cap), '<capsule object "::absl::Status" at 0x')
if 'pybind11_abseil.status' in sys.modules: # OSS
expected_repr_cap = '<pybind11_abseil.status.Status object at 0x'
else:
expected_repr_cap = '<capsule object "::absl::Status" at 0x'
self.assertStartsWith(repr(cap), expected_repr_cap)
if __name__ == '__main__':
absltest.main()
......@@ -80,5 +80,7 @@ export PYTHON_LIB_PATH=`python3 -c "import sysconfig; print(sysconfig.get_path('
echo "Using PYTHON_BIN_PATH: $PYTHON_BIN_PATH"
echo "Using PYTHON_LIB_PATH: $PYTHON_LIB_PATH"
BAZEL_CXXOPTS="-std=c++14" bazel test ... --test_output=errors
BAZEL_CXXOPTS="-std=c++17" bazel test ... --test_output=errors
BAZEL_CXXOPTS="-std=c++14" bazel test ... --test_output=errors "$@"
BAZEL_CXXOPTS="-std=c++17" bazel test ... --test_output=errors "$@"
#!/bin/bash
# The following scripts:
# - creates a virtualenv
# - installs the pip package dependencies
# - builds and runs tests
set -e # exit when any command fails
# set -x # Prints all executed command
MYDIR="$(dirname "$(realpath "$0")")"
CMAKE=$(which cmake || true)
if [[ -z $CMAKE || ! -x $CMAKE ]]
then
echo -e -n '\e[1m\e[93m'
echo -n 'CMake not found (cmake is needed to '
echo -n 'compile & test). '
echo -e 'Exiting...\e[0m'
exit 1
fi
VIRTUAL_ENV_BINARY=$(which virtualenv || true)
if [[ -z $VIRTUAL_ENV_BINARY || ! -x $VIRTUAL_ENV_BINARY ]]
then
echo -e -n '\e[1m\e[93m'
echo -n 'virtualenv command not found '
echo -n '(try `python3 -m pip install virtualenv`, possibly as root). '
echo -e 'Exiting...\e[0m'
exit 1
fi
is_in_virtual_env="false"
# if we are in a virtual_env, we will not create a new one inside.
if [[ "$VIRTUAL_ENV" != "" ]]
then
echo -e "\e[1m\e[93mVirtualenv already detected. We do not create a new one.\e[0m"
is_in_virtual_env="true"
fi
echo -e "\e[33mRunning ${0} from $PWD\e[0m"
PYBIN=$(which python3 || true)
if [[ -z $PYBIN || ! -x $PYBIN ]]
then
echo -e '\e[1m\e[93mpython3 not found! Skip build and test.\e[0m'
exit 1
fi
PYVERSION=$($PYBIN -c 'import sys; print(".".join(map(str, sys.version_info[:3])))')
VENV_DIR="./venv"
if [[ $is_in_virtual_env == "false" ]]; then
if ! [ -d "$VENV_DIR" ]; then
echo "Installing..."
echo -e "\e[33mInstalling a virtualenv to $VENV_DIR. The setup is long the first time, please wait.\e[0m"
virtualenv -p $PYBIN $VENV_DIR
else
echo -e "\e[33mReusing virtualenv from $VENV_DIR.\e[0m"
fi
source $VENV_DIR/bin/activate
fi
# We only exit the virtualenv if we created one.
function cleanup {
if [[ $is_in_virtual_env == "true" ]]; then
echo "Exiting virtualenv"
deactivate
fi
}
trap cleanup EXIT
echo -e "\e[33mInstalling the requirements (use --noinstall to skip).\e[0m"
pip3 install --upgrade -r ./requirements.txt
echo "Building and testing in $PWD using 'python' (version $PYVERSION)."
export PYTHON_BIN_PATH=`which python3`
export PYTHON_LIB_PATH=`python3 -c "import sysconfig; print(sysconfig.get_path('include'))"`
echo "Using PYTHON_BIN_PATH: $PYTHON_BIN_PATH"
echo "Using PYTHON_LIB_PATH: $PYTHON_LIB_PATH"
if [ -e tmp_build ]; then
rm -r tmp_build
fi
mkdir tmp_build
cd tmp_build
# C++14
cmake ../ -DCMAKE_CXX_STANDARD=14 -DCMAKE_VERBOSE_MAKEFILE=ON
make "$@"
ctest --output-on-failure
rm -r ./*
# C++17
cmake ../ -DCMAKE_CXX_STANDARD=17 -DCMAKE_VERBOSE_MAKEFILE=ON
make "$@"
ctest --output-on-failure
cd ../
rm -r tmp_build
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment