Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bindings/cpp): expose all api returned by value #3001

Merged
merged 4 commits into from
Sep 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions .github/workflows/bindings_cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,23 @@ jobs:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get install libgtest-dev ninja-build
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp lib/*.a /usr/lib
sudo ln -s /usr/lib/libgtest.a /usr/local/lib/libgtest.a
sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a
sudo apt-get install libgtest-dev ninja-build libboost-all-dev valgrind doxygen

- name: Setup Rust toolchain
uses: ./.github/actions/setup

- name: Build Cpp binding
- name: Build Cpp binding && Run tests
working-directory: "bindings/cpp"
run: |
mkdir build
cd build
cmake -GNinja ..
ninja
./opendal_cpp_test

- name: Run tests
- name: Run tests with valgrind
working-directory: "bindings/cpp/build"
run: ./opendal_cpp_test
run: |
cmake -GNinja -DENABLE_ADDRESS_SANITIZER=OFF ..
ninja
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose ./opendal_cpp_test
10 changes: 2 additions & 8 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,14 @@ jobs:

- name: Install dependencies
run: |
sudo apt-get install doxygen graphviz ninja-build libgtest-dev
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp lib/*.a /usr/lib
sudo ln -s /usr/lib/libgtest.a /usr/local/lib/libgtest.a
sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a
sudo apt-get install doxygen graphviz ninja-build

- name: Build Cpp docs
working-directory: "bindings/cpp"
run: |
mkdir build
cd build
cmake -GNinja ..
cmake -GNinja -DDOCS_ONLY=ON ..
ninja docs

- name: Upload docs
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 30 additions & 25 deletions bindings/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,27 @@ if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()

option(ENABLE_ADDRESS_SANITIZER "Enable address sanitizer" ON)
option(DOCS_ONLY "Only build documentation" OFF)

# Documentation
set(PROJECT_DOCUMENT_SOURCE ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/README.md)
string(REPLACE ";" " " PROJECT_DOCUMENT_SOURCE "${PROJECT_DOCUMENT_SOURCE}")
file(DOWNLOAD https://cdn.jsdelivr.net/gh/jothepro/[email protected]/doxygen-awesome.min.css ${CMAKE_BINARY_DIR}/doxygen-awesome.css)
find_package(Doxygen REQUIRED)
set(DOXYGEN_IN ${CMAKE_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_BINARY_DIR}/Doxyfile.out)
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
add_custom_target(docs
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)

if (DOCS_ONLY)
return()
endif()

# cargo target dir must be absolute, otherwise some build target cannot find it
get_filename_component(CARGO_TARGET_DIR ${CMAKE_SOURCE_DIR}/../../target ABSOLUTE)
set(CARGO_MANIFEST ${CMAKE_SOURCE_DIR}/Cargo.toml)
Expand All @@ -42,9 +63,12 @@ add_custom_command(
COMMENT "Running cargo..."
)

find_package(Boost REQUIRED COMPONENTS date_time)

add_library(opendal_cpp STATIC ${CPP_SOURCE_FILE} ${RUST_BRIDGE_CPP})
target_include_directories(opendal_cpp PUBLIC ${CPP_INCLUDE_DIR})
target_link_libraries(opendal_cpp PUBLIC ${RUST_LIB} ${CMAKE_DL_LIBS})
target_include_directories(opendal_cpp PUBLIC ${CPP_INCLUDE_DIR} Boost::date_time)
target_link_libraries(opendal_cpp PUBLIC ${RUST_LIB})
target_link_libraries(opendal_cpp PRIVATE ${CMAKE_DL_LIBS} Boost::date_time)
set_target_properties(opendal_cpp
PROPERTIES ADDITIONAL_CLEAN_FILES ${CARGO_TARGET_DIR}
)
Expand All @@ -71,7 +95,9 @@ target_link_libraries(opendal_cpp_test ${GTEST_LDFLAGS} GTest::gtest_main openda
target_compile_options(opendal_cpp_test PRIVATE ${GTEST_CFLAGS})

# enable address sanitizers
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (ENABLE_ADDRESS_SANITIZER)
target_compile_options(opendal_cpp PRIVATE -fsanitize=leak,address,undefined -fno-omit-frame-pointer -fno-common -O1)
target_link_options(opendal_cpp PRIVATE -fsanitize=leak,address,undefined)
target_compile_options(opendal_cpp_test PRIVATE -fsanitize=leak,address,undefined -fno-omit-frame-pointer -fno-common -O1)
target_link_options(opendal_cpp_test PRIVATE -fsanitize=leak,address,undefined)
endif()
Expand All @@ -85,25 +111,4 @@ if(APPLE)
endif()

include(GoogleTest)
gtest_discover_tests(opendal_cpp_test)

# Documentation
set(PROJECT_DOCUMENT_SOURCE ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/README.md)
string(REPLACE ";" " " PROJECT_DOCUMENT_SOURCE "${PROJECT_DOCUMENT_SOURCE}")
file(DOWNLOAD https://cdn.jsdelivr.net/gh/jothepro/[email protected]/doxygen-awesome.min.css ${CMAKE_BINARY_DIR}/doxygen-awesome.css)
find_package(Doxygen)
if (DOXYGEN_FOUND)
set(DOXYGEN_IN ${CMAKE_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_BINARY_DIR}/Doxyfile.out)

configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
message("Doxygen build started")

add_custom_target(docs
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM )
else (DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
gtest_discover_tests(opendal_cpp_test)
18 changes: 10 additions & 8 deletions bindings/cpp/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ To build OpenDAL C++ binding, the following is all you need:

- **GTest(Google Test)**. It is used to run the tests. To see how to build, check [here](https://github.com/google/googletest).

- **Boost**. It is one dependency of this library. To see how to build, check [here](https://www.boost.org/doc/libs/1_76_0/more/getting_started/unix-variants.html).

- **Doxygen**. It is used to generate the documentation. To see how to build, check [here](https://www.doxygen.nl/manual/install.html).

- **Graphviz**. It is used to generate the documentation with graphs. To see how to build, check [here](https://graphviz.org/download/).
Expand All @@ -48,14 +50,11 @@ sudo apt install cmake ninja-build
# install clang-format
sudo apt install clang-format

# install and build GTest library under /usr/lib and softlink to /usr/local/lib
# install GTest library
sudo apt-get install libgtest-dev
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp lib/*.a /usr/lib
sudo ln -s /usr/lib/libgtest.a /usr/local/lib/libgtest.a
sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a

# install Boost library
sudo apt install libboost-all-dev

# install Doxygen and Graphviz
sudo apt install doxygen graphviz
Expand All @@ -76,6 +75,9 @@ brew install clang-format
# install GTest library
brew install googletest

# install Boost library
brew install boost

# install Doxygen and Graphviz
brew install doxygen graphviz
```
Expand All @@ -89,7 +91,7 @@ mkdir build
cd build

# Add -DCMAKE_EXPORT_COMPILE_COMMANDS=1 to generate compile_commands.json for clangd
cmake -DCMAKE_BUILD_TYPE=Debug -GNinja ..
cmake -GNinja ..

ninja
```
Expand Down
1 change: 1 addition & 0 deletions bindings/cpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ crate-type = ["staticlib"]
opendal.workspace = true
cxx = "1.0"
anyhow = "1.0"
chrono = "0.4"

[build-dependencies]
cxx-build = "1.0"
97 changes: 96 additions & 1 deletion bindings/cpp/include/opendal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma once
#include "lib.rs.h"

#include <boost/date_time/posix_time/posix_time.hpp>
#include <memory>
#include <optional>
#include <string>
Expand All @@ -28,11 +29,48 @@

namespace opendal {

/**
* @enum EntryMode
* @brief The mode of the entry
*/
enum EntryMode {
FILE = 1,
DIR = 2,
UNKNOWN = 0,
};

/**
* @struct Metadata
* @brief The metadata of a file or directory
*/
struct Metadata {
EntryMode type;
std::uint64_t content_length;
std::optional<std::string> cache_control;
std::optional<std::string> content_disposition;
std::optional<std::string> content_md5;
std::optional<std::string> content_type;
std::optional<std::string> etag;
std::optional<boost::posix_time::ptime> last_modified;

Metadata(ffi::Metadata &&);
};

/**
* @struct Entry
* @brief The entry of a file or directory
*/
struct Entry {
std::string path;

Entry(ffi::Entry &&);
};

/**
* @class Operator
* @brief Operator is the entry for all public APIs.
*/
class Operator : std::enable_shared_from_this<Operator> {
class Operator {
public:
Operator() = default;

Expand Down Expand Up @@ -63,6 +101,8 @@ class Operator : std::enable_shared_from_this<Operator> {

/**
* @brief Read data from the operator
* @note The operation will make unnecessary copy. So we recommend to use the
* `reader` method.
*
* @param path The path of the data
* @return The data read from the operator
Expand All @@ -77,6 +117,61 @@ class Operator : std::enable_shared_from_this<Operator> {
*/
void write(std::string_view path, const std::vector<uint8_t> &data);

/**
* @brief Check if the path exists
*
* @param path The path to check
* @return true if the path exists, false otherwise
*/
bool is_exist(std::string_view path);

/**
* @brief Create a directory
*
* @param path The path of the directory
*/
void create_dir(std::string_view path);

/**
* @brief Copy a file from src to dst.
*
* @param src The source path
* @param dst The destination path
*/
void copy(std::string_view src, std::string_view dst);

/**
* @brief Rename a file from src to dst.
*
* @param src The source path
* @param dst The destination path
*/
void rename(std::string_view src, std::string_view dst);

/**
* @brief Remove a file or directory
*
* @param path The path of the file or directory
*/
void remove(std::string_view path);

/**
* @brief Get the metadata of a file or directory
*
* @param path The path of the file or directory
* @return The metadata of the file or directory
*/
Metadata stat(std::string_view path);

/**
* @brief List the entries of a directory
* @note The returned entries are sorted by name.
*
* @param path The path of the directory
* @return The entries of the directory
*/
std::vector<Entry> list(std::string_view path);

private:
std::optional<rust::Box<opendal::ffi::Operator>> operator_;
};
Expand Down
Loading
Loading