diff --git a/.github/actions/do-build/action.yml b/.github/actions/do-build/action.yml new file mode 100644 index 0000000..2e7bb52 --- /dev/null +++ b/.github/actions/do-build/action.yml @@ -0,0 +1,35 @@ +name: "Build AnyBlob" +description: "Build AnyBlob using either clang or gcc" +inputs: + clang-toolchain: + required: false + description: "Build with clang and use libcxx as the standard library" + default: false + +runs: + using: "composite" + steps: + # CMake configuration option 1 - GCC toolchain + - name: Configure CMake + if: ${{ inputs.clang-toolchain == 'false' }} + run: | + cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + shell: bash + + # CMake configuration option 2 - Clang toolchain + - name: Configure CMake + if: ${{ inputs.clang-toolchain == 'true' }} + # Explicitly use clang-15. The runner comes with clang-13, 14, and 15. + # However, only clang-15 and up support `-Wno-unqualified-std-cast-call`. + run: | + sudo apt install libc++-15-dev libc++abi-15-dev + cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ + -DCMAKE_C_COMPILER=clang-15 \ + -DCMAKE_CXX_COMPILER=clang++-15 \ + -DANYBLOB_LIBCXX_COMPAT=1 + shell: bash + + # Build library and test binaries + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + shell: bash diff --git a/.github/actions/install-deps/action.yml b/.github/actions/install-deps/action.yml new file mode 100644 index 0000000..148c98c --- /dev/null +++ b/.github/actions/install-deps/action.yml @@ -0,0 +1,11 @@ +name: "Install Dependencies" +description: "Installs dynamic libraries required by AnyBlob" + +runs: + using: "composite" + steps: + # Install dependencies + - name: Install dependencies + run: sudo apt update && sudo apt install liburing-dev openssl libssl-dev libjemalloc-dev lld + shell: bash + diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 367a474..914c104 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -12,11 +12,19 @@ on: env: BUILD_TYPE: Debug + # False ASAN positives for alloc_dealloc_mismatch when running with clang + # https://github.com/llvm/llvm-project/issues/59432 + ASAN_OPTIONS: alloc_dealloc_mismatch=0 jobs: integration-test: + name: Integration Tests (Clang ${{ matrix.clang-toolchain }}) # Run on ubuntu runs-on: ubuntu-latest + # Use both the GCC and Clang Toolchain + strategy: + matrix: + clang-toolchain: [true, false] # Define the steps steps: @@ -39,17 +47,15 @@ jobs: with: submodules: true - # Install dependencies - - name: Install dependencies - run: sudo apt update && sudo apt install liburing-dev openssl libssl-dev libjemalloc-dev lld + # Use action to install dependencies + - name: Install Dependencies + uses: ./.github/actions/install-deps - # CMake configuration - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - - # Build library and integration tester - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + # Use action to build + - name: Build AnyBlob + uses: ./.github/actions/do-build + with: + clang-toolchain: ${{ matrix.clang-toolchain }} # Run the integration test - name: Integration Test diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index a3e64df..390500d 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -12,11 +12,19 @@ on: env: BUILD_TYPE: Debug + # False ASAN positives for alloc_dealloc_mismatch when running with clang + # https://github.com/llvm/llvm-project/issues/59432 + ASAN_OPTIONS: alloc_dealloc_mismatch=0 jobs: - uint-test: + unit-test: + name: Unit Tests (Clang ${{ matrix.clang-toolchain }}) # Run on ubuntu runs-on: ubuntu-latest + # Use both the GCC and Clang Toolchain + strategy: + matrix: + clang-toolchain: [true, false] # Define the steps steps: @@ -25,19 +33,17 @@ jobs: with: submodules: true - # Install dependencies - - name: Install dependencies - run: sudo apt update && sudo apt install liburing-dev openssl libssl-dev libjemalloc-dev lld + # Use action to install dependencies + - name: Install Dependencies + uses: ./.github/actions/install-deps - # CMake configuration - - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - - # Build library and tester - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + # Use action to build + - name: Build AnyBlob + uses: ./.github/actions/do-build + with: + clang-toolchain: ${{ matrix.clang-toolchain }} - # Run the unit test + # Run the unit tests - name: Unit Test working-directory: ${{github.workspace}}/build run: ./tester diff --git a/CMakeLists.txt b/CMakeLists.txt index d3ac432..a3a1e0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,16 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo" "Coverage") endif() +option(ANYBLOB_LIBCXX_COMPAT "Build AnyBlob in a way that's compatible with libcxx." OFF) +if (ANYBLOB_LIBCXX_COMPAT) + message("Building AnyBlob with libcxx") + # Update compiler flags to use libcxx as standard library. + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -stdlib=libc++") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -stdlib=libc++") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -stdlib=libc++") + set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -stdlib=libc++") +endif() + # --------------------------------------------------------------------------- # Coverage Environment # --------------------------------------------------------------------------- @@ -113,6 +123,9 @@ include("${PROJECT_SOURCE_DIR}/test/integration/local.cmake") add_library(AnyBlob STATIC ${SRC_CPP} ${INCLUDE_HPP}) target_link_libraries(AnyBlob PUBLIC OpenSSL::SSL Threads::Threads ${LIBURING_LIBRARY} jemalloc) target_include_directories(AnyBlob PUBLIC ${PROJECT_SOURCE_DIR}/include) +if (ANYBLOB_LIBCXX_COMPAT) + target_compile_definitions(AnyBlob PRIVATE ANYBLOB_LIBCXX_COMPAT) +endif() # --------------------------------------------------------------------------- # Unit tests diff --git a/README.md b/README.md index 59bc0a0..7fe4e0f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ AnyBlob relies on some third-party libraries: - openssl - jemalloc -For Ubuntu the following command install the third-party libraries: +For Ubuntu 22.04+ the following command installs the third-party libraries: ``` sudo apt update && sudo apt install liburing-dev openssl libssl-dev libjemalloc-dev lld g++ cmake ``` diff --git a/include/cloud/provider.hpp b/include/cloud/provider.hpp index a0f3cd2..e03eb52 100644 --- a/include/cloud/provider.hpp +++ b/include/cloud/provider.hpp @@ -1,6 +1,8 @@ #pragma once #include #include +#include +#include //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library // Dominik Durner, 2021 diff --git a/include/network/io_uring_socket.hpp b/include/network/io_uring_socket.hpp index e5389a4..a5243f8 100644 --- a/include/network/io_uring_socket.hpp +++ b/include/network/io_uring_socket.hpp @@ -1,5 +1,5 @@ #pragma once -#include "network/throughput_resolver.hpp" +#include "network/resolver.hpp" #include #include #include diff --git a/include/network/tasked_send_receiver.hpp b/include/network/tasked_send_receiver.hpp index 024f493..7bcae88 100644 --- a/include/network/tasked_send_receiver.hpp +++ b/include/network/tasked_send_receiver.hpp @@ -1,8 +1,8 @@ #pragma once +#include "network/config.hpp" #include "network/io_uring_socket.hpp" #include "network/message_task.hpp" #include "network/tls_context.hpp" -#include "network/config.hpp" #include "utils/ring_buffer.hpp" #include #include @@ -10,6 +10,7 @@ #include #include #include +#include #include //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library diff --git a/include/network/throughput_resolver.hpp b/include/network/throughput_resolver.hpp index b043d00..4476d0e 100644 --- a/include/network/throughput_resolver.hpp +++ b/include/network/throughput_resolver.hpp @@ -1,4 +1,8 @@ #pragma once +// The `ThroughputResolver` depends on gnu stdlib associative containers that are +// not supported by libcxx. We remove the throughput resolver in its entirety when +// building with libcxx. +#ifndef ANYBLOB_LIBCXX_COMPAT #include "network/resolver.hpp" #include #include @@ -55,3 +59,4 @@ class ThroughputResolver : public network::Resolver { }; // namespace network //--------------------------------------------------------------------------- }; // namespace anyblob +#endif // ANYBLOB_LIBCXX_COMPAT diff --git a/src/cloud/aws.cpp b/src/cloud/aws.cpp index df0ac48..d4799e4 100644 --- a/src/cloud/aws.cpp +++ b/src/cloud/aws.cpp @@ -8,6 +8,7 @@ #include #include #include +#include //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library // Dominik Durner, 2021 diff --git a/src/cloud/azure.cpp b/src/cloud/azure.cpp index 171a344..5f667bd 100644 --- a/src/cloud/azure.cpp +++ b/src/cloud/azure.cpp @@ -3,7 +3,7 @@ #include "network/http_helper.hpp" #include "network/original_message.hpp" #include "network/tasked_send_receiver.hpp" -#include "network/throughput_resolver.hpp" +#include "network/resolver.hpp" #include "utils/data_vector.hpp" #include #include diff --git a/src/cloud/gcp.cpp b/src/cloud/gcp.cpp index 384339f..94d8a0c 100644 --- a/src/cloud/gcp.cpp +++ b/src/cloud/gcp.cpp @@ -3,7 +3,7 @@ #include "network/http_helper.hpp" #include "network/original_message.hpp" #include "network/tasked_send_receiver.hpp" -#include "network/throughput_resolver.hpp" +#include "network/resolver.hpp" #include "utils/data_vector.hpp" #include #include diff --git a/src/network/http_helper.cpp b/src/network/http_helper.cpp index d588401..11c0038 100644 --- a/src/network/http_helper.cpp +++ b/src/network/http_helper.cpp @@ -3,6 +3,7 @@ #include #include #include +#include //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library // Dominik Durner, 2021 diff --git a/src/network/io_uring_socket.cpp b/src/network/io_uring_socket.cpp index a80e099..b3b93aa 100644 --- a/src/network/io_uring_socket.cpp +++ b/src/network/io_uring_socket.cpp @@ -11,6 +11,9 @@ #include #include #include +#ifndef ANYBLOB_LIBCXX_COMPAT +#include "network/throughput_resolver.hpp" +#endif //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library // Dominik Durner, 2021 @@ -43,7 +46,14 @@ IOUringSocket::IOUringSocket(uint32_t entries, int32_t /*flags*/) : _resolverCac if (_eventId < 0) throw runtime_error("Event FD creation error!"); io_uring_register_eventfd(&_uring, _eventId); +#ifndef ANYBLOB_LIBCXX_COMPAT + // By default, use the ThroughputResolver. _resolverCache.emplace("", make_unique(entries)); +#else + // If we build in libcxx compatability mode, we need to use the default resolver. + // The ThroughputResolver currently does not build with libcxx. + _resolverCache.emplace("", make_unique(entries)); +#endif } //--------------------------------------------------------------------------- int32_t IOUringSocket::connect(string hostname, uint32_t port, TCPSettings& tcpSettings, int retryLimit) diff --git a/src/network/throughput_resolver.cpp b/src/network/throughput_resolver.cpp index 881c914..70bcf8c 100644 --- a/src/network/throughput_resolver.cpp +++ b/src/network/throughput_resolver.cpp @@ -1,3 +1,4 @@ +#ifndef ANYBLOB_LIBCXX_COMPAT #include "network/throughput_resolver.hpp" #include #include @@ -106,3 +107,4 @@ void ThroughputResolver::stopSocket(int fd, uint64_t bytes) }; // namespace network //--------------------------------------------------------------------------- }; // namespace anyblob +#endif // ANYBLOB_LIBCXX_COMPAT diff --git a/src/network/tls_connection.cpp b/src/network/tls_connection.cpp index 0128938..a38b6f2 100644 --- a/src/network/tls_connection.cpp +++ b/src/network/tls_connection.cpp @@ -5,6 +5,7 @@ #include #include #include +#include //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library // Dominik Durner, 2023 diff --git a/test/unit/network/io_uring_socket_test.cpp b/test/unit/network/io_uring_socket_test.cpp index 1f8e64c..051922c 100644 --- a/test/unit/network/io_uring_socket_test.cpp +++ b/test/unit/network/io_uring_socket_test.cpp @@ -1,5 +1,6 @@ -#include "network/io_uring_socket.hpp" #include "catch2/single_include/catch2/catch.hpp" +#include "cloud/aws_resolver.hpp" +#include "network/io_uring_socket.hpp" #include "perfevent/PerfEvent.hpp" //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library diff --git a/test/unit/network/resolver_test.cpp b/test/unit/network/resolver_test.cpp index 3ef9dad..0ecabfd 100644 --- a/test/unit/network/resolver_test.cpp +++ b/test/unit/network/resolver_test.cpp @@ -1,6 +1,5 @@ #include "network/resolver.hpp" #include "catch2/single_include/catch2/catch.hpp" -#include "network/throughput_resolver.hpp" //--------------------------------------------------------------------------- // AnyBlob - Universal Cloud Object Storage Library // Dominik Durner, 2022