diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..fe699e0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,10 @@ +BasedOnStyle: Google +IndentWidth: 4 +AccessModifierOffset: -4 +ColumnLimit: 100 +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +DerivePointerAlignment: true +KeepEmptyLinesAtTheStartOfBlocks: true +SortIncludes: false diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..1f59684 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,41 @@ +--- +Checks: '-*,cppcoreguidelines-avoid-goto,cppcoreguidelines-pro-type-const-cast, google-readability-casting, modernize-replace-random-shuffle, readability-braces-around-statements, readability-container-size-empty, readability-redundant-control-flow, readability-redundant-string-init, modernize-use-nullptr, readability-identifier-naming, google-build-using-namespace' +HeaderFilterRegex: '\.h$' +WarningsAsErrors: '*' +CheckOptions: + - key: readability-identifier-naming.NamespaceCase + value: lower_case + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.TypedefCase + value: CamelCase + - key: readability-identifier-naming.TypedefIgnoredRegexp + value: (allocator_type|size_type|key_type|value_type|mapped_type|difference_type|pointer|const_pointer|reference|const_reference|iterator_category|const_iterator|iterator|reverse_iterator|const_reverse_iterator|key_compare) + - key: readability-identifier-naming.TypeAliasCase + value: CamelCase + - key: readability-identifier-naming.PrivateMemberSuffix + value: '_' + - key: readability-identifier-naming.StructCase + value: CamelCase + - key: readability-identifier-naming.FunctionCase + value: CamelCase + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.PrivateMemberCase + value: lower_case + - key: readability-identifier-naming.ParameterCase + value: lower_case + - key: readability-identifier-naming.GlobalConstantPrefix + value: k + - key: readability-identifier-naming.GlobalConstantCase + value: CamelCase + - key: readability-identifier-naming.StaticConstantPrefix + value: k + - key: readability-identifier-naming.StaticConstantCase + value: CamelCase + - key: readability-identifier-naming.ConstexprVariableCase + value: CamelCase + - key: readability-identifier-naming.ConstexprVariablePrefix + value: k + - key: google-runtime-int.TypeSuffix + value: _t diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..25cb436 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,104 @@ +name: CI + +on: + push: + branches: ["main"] + pull_request: + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + asan: + name: Tests (ASAN+UBSAN) + runs-on: ubuntu-24.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install tools + run: | + sudo apt-get update + sudo apt-get install -y ninja-build cmake clang + + - name: Configure (Debug, ASAN+UBSAN) + run: | + cmake -S . -B build-asan -G Ninja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCOLUMNAR_BUILD_TESTS=ON \ + -DCOLUMNAR_BUILD_BENCHMARKS=OFF \ + -DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" \ + -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" + + - name: Build + run: cmake --build build-asan + + - name: Run tests + run: ctest --test-dir build-asan --output-on-failure + + + tsan: + name: Tests (TSAN) + runs-on: ubuntu-24.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install tools + run: | + sudo apt-get update + sudo apt-get install -y ninja-build cmake clang + + - name: Configure (Debug, TSAN) + run: | + cmake -S . -B build-tsan -G Ninja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCOLUMNAR_BUILD_TESTS=ON \ + -DCOLUMNAR_BUILD_BENCHMARKS=OFF \ + -DCMAKE_C_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" \ + -DCMAKE_CXX_FLAGS="-fsanitize=thread -fno-omit-frame-pointer" + + - name: Build + run: cmake --build build-tsan + + - name: Run tests + env: + TSAN_OPTIONS: "halt_on_error=1" + run: ctest --test-dir build-tsan --output-on-failure + + + release-bench: + name: Benchmark (Release) + runs-on: ubuntu-24.04 + needs: [asan, tsan] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install tools + run: | + sudo apt-get update + sudo apt-get install -y ninja-build cmake g++ + + - name: Configure (Release) + run: | + cmake -S . -B build-release -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCOLUMNAR_BUILD_TESTS=OFF \ + -DCOLUMNAR_BUILD_BENCHMARKS=ON + + - name: Build + run: cmake --build build-release + + - name: Run all benchmarks + run: | + chmod +x tools/run_benchmarks.sh + tools/run_benchmarks.sh build-release diff --git a/.gitignore b/.gitignore index d4fb281..8e20cef 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,7 @@ # debug information files *.dwo + +build/ +.vscode/ +.cache/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..978defb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.20) +project(columnar_engine LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +option(COLUMNAR_BUILD_TESTS "Build tests" ON) +option(COLUMNAR_BUILD_BENCHMARKS "Build benchmarks" ON) + +include(cmake/deps.cmake) + +add_library(columnar_lib + src/add.cpp +) + +target_include_directories(columnar_lib PUBLIC include) + +target_compile_options(columnar_lib PRIVATE -Wall -Wextra -Wpedantic) + +add_subdirectory(apps/converter) + +if(COLUMNAR_BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() + +if(COLUMNAR_BUILD_BENCHMARKS) + add_subdirectory(benchmarks) +endif() diff --git a/apps/converter/CMakeLists.txt b/apps/converter/CMakeLists.txt new file mode 100644 index 0000000..ad9781a --- /dev/null +++ b/apps/converter/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable(converter + main.cpp +) + +target_link_libraries(converter + PRIVATE + columnar_lib + absl::flags + absl::flags_parse +) diff --git a/apps/converter/main.cpp b/apps/converter/main.cpp new file mode 100644 index 0000000..09b7f9f --- /dev/null +++ b/apps/converter/main.cpp @@ -0,0 +1,17 @@ +#include +#include + +#include + +#include "columnar/add.h" + +ABSL_FLAG(int, x, 1, "x"); +ABSL_FLAG(int, y, 2, "y"); + +int main(int argc, char** argv) { + absl::ParseCommandLine(argc, argv); + int x = absl::GetFlag(FLAGS_x); + int y = absl::GetFlag(FLAGS_y); + std::cout << "Add(" << x << ", " << y << ") = " << columnar::Add(x, y) << "\n"; + return 0; +} diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt new file mode 100644 index 0000000..e0c05a3 --- /dev/null +++ b/benchmarks/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(columnar_bench + bench_bruh.cpp +) + +target_link_libraries(columnar_bench + PRIVATE + columnar_lib + benchmark::benchmark_main +) diff --git a/benchmarks/bench_bruh.cpp b/benchmarks/bench_bruh.cpp new file mode 100644 index 0000000..a6440b7 --- /dev/null +++ b/benchmarks/bench_bruh.cpp @@ -0,0 +1,12 @@ +#include +#include "columnar/add.h" + +static void BenchmarkAdd(benchmark::State& state) { + int x = 1; + int y = 2; + for (auto _ : state) { + benchmark::DoNotOptimize(columnar::Add(x, y)); + } +} + +BENCHMARK(BenchmarkAdd); diff --git a/cmake/deps.cmake b/cmake/deps.cmake new file mode 100644 index 0000000..853e617 --- /dev/null +++ b/cmake/deps.cmake @@ -0,0 +1,22 @@ +include(FetchContent) + +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.zip +) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +FetchContent_Declare( + benchmark + URL https://github.com/google/benchmark/archive/refs/tags/v1.9.1.zip +) +set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) +set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(benchmark) + +FetchContent_Declare( + absl + URL https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.2.zip +) +FetchContent_MakeAvailable(absl) \ No newline at end of file diff --git a/include/columnar/add.h b/include/columnar/add.h new file mode 100644 index 0000000..411598f --- /dev/null +++ b/include/columnar/add.h @@ -0,0 +1,5 @@ +#pragma once + +namespace columnar { +int Add(int a, int b); +} // namespace columnar diff --git a/src/add.cpp b/src/add.cpp new file mode 100644 index 0000000..8540034 --- /dev/null +++ b/src/add.cpp @@ -0,0 +1,7 @@ +#include "columnar/add.h" + +namespace columnar { +int Add(int a, int b) { + return a + b; +} +} // namespace columnar \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..fd7d94d --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(columnar_tests + test_bruh.cpp +) + +target_link_libraries(columnar_tests + PRIVATE + columnar_lib + GTest::gtest_main +) + +include(GoogleTest) +gtest_discover_tests(columnar_tests) diff --git a/tests/test_bruh.cpp b/tests/test_bruh.cpp new file mode 100644 index 0000000..a18cad5 --- /dev/null +++ b/tests/test_bruh.cpp @@ -0,0 +1,6 @@ +#include +#include "columnar/add.h" + +TEST(Bruh, AddWorks) { + EXPECT_EQ(columnar::Add(1, 2), 3); +} \ No newline at end of file diff --git a/tools/run_benchmarks.sh b/tools/run_benchmarks.sh new file mode 100755 index 0000000..3a8d1f9 --- /dev/null +++ b/tools/run_benchmarks.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -euo pipefail + +BUILD_DIR="${1:-build-release}" +BENCH_DIR="${BUILD_DIR}/benchmarks" + +MIN_TIME="${BENCH_MIN_TIME:-0.1}" +REPS="${BENCH_REPS:-1}" + +if [[ ! -d "$BENCH_DIR" ]]; then + echo "[bench] No benchmarks dir: $BENCH_DIR" + echo "[bench] Nothing to run." + exit 0 +fi + +echo "[bench] Looking for benchmark executables in: $BENCH_DIR" + +mapfile -d '' BENCHES < <(find "$BENCH_DIR" -maxdepth 1 -type f -executable -print0) + +if [[ "${#BENCHES[@]}" -eq 0 ]]; then + echo "[bench] No benchmark executables found." + exit 0 +fi + +for b in "${BENCHES[@]}"; do + echo "==================================================" + echo "[bench] Running: $b" + "$b" --benchmark_min_time="$MIN_TIME" --benchmark_repetitions="$REPS" +done + +echo "==================================================" +echo "[bench] Done."