Skip to content

Commit

Permalink
Refactoring of Build framework (#2)
Browse files Browse the repository at this point in the history
* Updating `conanfile` to use Conan v2

* Updated the build configuration to make the project compile/build again.

* Build now succeeds

* Updated the `$COMMON_UTILS/build` script too (massenz/common_utils`).

* Fixed unit tests build

* Fixed failing tests

* Added `Bucket::operator==` and `Bucket::operator<` to fix a potential bug in the View class.
  • Loading branch information
massenz authored Dec 14, 2024
1 parent 2d46851 commit 6e28d94
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 260 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ bin/test
.la

cmake-build-debug
logs/
60 changes: 34 additions & 26 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
# This file (c) 2016-2020 AlertAvert.com. All rights reserved.
# This file (c) 2016-2024 AlertAvert.com. All rights reserved.

cmake_minimum_required(VERSION 3.23)
project(distlib)
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC")

# Conan Packaging support
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")

##
# Include common cmake utilities.
# See: https://bitbucket.org/marco/common-utils
# See: https://github.com/massenz/common-utils
#
include(${COMMON_UTILS_DIR}/commons.cmake OPTIONAL RESULT_VARIABLE COMMONS_FILE)
message(STATUS "Using Common Utilities: ${COMMONS_FILE}")

##
# Installation directory; this is both used to access
Expand All @@ -23,6 +21,7 @@ include(${COMMON_UTILS_DIR}/commons.cmake OPTIONAL RESULT_VARIABLE COMMONS_FILE)
if(NOT DEFINED INSTALL_DIR)
if(DEFINED ENV{INSTALL_DIR})
set(INSTALL_DIR $ENV{INSTALL_DIR})
message(STATUS "INSTALL_DIR set to: ${INSTALL_DIR}")
else()
message(FATAL_ERROR
"INSTALL_DIR should be defined as an environment variable, or via -D notation")
Expand All @@ -33,7 +32,7 @@ endif()
# Release version management
#
set(RELEASE_MAJOR 0)
set(RELEASE_MINOR 18)
set(RELEASE_MINOR 20)
set(RELEASE_PATCH 0)

set(RELEASE "${RELEASE_MAJOR}.${RELEASE_MINOR}.${RELEASE_PATCH}")
Expand All @@ -51,11 +50,12 @@ message(STATUS "Building Release: ${RELEASE_STRING} (${CMAKE_BUILD_TYPE})")
# Both the value of CMAKE_BUILD_TYPE and the `build_type` setting
# in `~/.conan/profiles/default` need to match.
#
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(GLOG glogd)
else()
set(GLOG glog)
endif()
# TODO: review to confirm whether this is still necessary with Conan V2
#if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
# set(GLOG glogd)
#else()
# set(GLOG glog)
#endif()

set(SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
Expand All @@ -75,10 +75,10 @@ include_directories(
${INSTALL_DIR}/include
)

link_directories(
${INSTALL_DIR}/lib
${PROJECT_BINARY_DIR}/lib
)
#link_directories(
# ${INSTALL_DIR}/lib
# ${PROJECT_BINARY_DIR}/lib
#)

set(UTILS_SOURCES
${SOURCE_DIR}/utils/misc.cpp
Expand All @@ -91,9 +91,16 @@ set(SOURCES
${SOURCE_DIR}/View.cpp
)

set(UTILS_LIBS
crypto
${GLOG}
# Add Conan build folder to CMAKE_PREFIX_PATH for dependency resolution
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")

find_package(cryptopp REQUIRED)
find_package(glog)
find_package(OpenSSL REQUIRED)
set(LIBS
cryptopp::cryptopp
glog::glog
openssl::openssl
pthread
)

Expand All @@ -106,7 +113,7 @@ add_library(distutils SHARED
${SOURCES}
${UTILS_SOURCES}
)
target_link_libraries(distutils ${UTILS_LIBS})
target_link_libraries(distutils ${LIBS})


##
Expand All @@ -126,20 +133,21 @@ add_subdirectory(${TESTS_DIR})

set(EXAMPLES_DIR ${SOURCE_DIR}/examples)

# Examples will use the latest build for the shared libraries
message(STATUS "Libraries will be linked from
${CMAKE_BINARY_DIR} and ${INSTALL_DIR}/lib")
link_directories(
${CMAKE_BINARY_DIR}/lib
${CMAKE_BINARY_DIR}
${INSTALL_DIR}/lib
)

##
# Merkle Tree Demo
#
add_executable(merkle_demo ${EXAMPLES_DIR}/merkle_demo.cpp)
target_link_libraries(merkle_demo distutils ${UTILS_LIBS})
target_link_libraries(merkle_demo distutils ${LIBS})

##
# KeyValue Store Demo
#
add_executable(keystore_demo ${EXAMPLES_DIR}/keystore_example.cpp)
target_link_libraries(keystore_demo distutils ${UTILS_LIBS})
target_link_libraries(keystore_demo distutils ${LIBS})
9 changes: 9 additions & 0 deletions CMakeLists.txt.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.15)
project(MyProject)

# Find the glog package installed by Conan
find_package(glog REQUIRED)

# Set up the target and link glog
add_executable(use-glog src/examples/use_glog.cpp)
target_link_libraries(use-glog PRIVATE glog::glog)
3 changes: 2 additions & 1 deletion CMakeUserPresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"conan": {}
},
"include": [
"build/CMakePresets.json"
"build/Release/generators/CMakePresets.json",
"build/Debug/generators/CMakePresets.json"
]
}
33 changes: 27 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,42 @@ A detailed description of the library's features follows the [Install & build](#

## Build & testing

The sequence of commands to build the project:

```shell
conan install . -s build_type=Debug --build=missing
cmake --preset conan-debug -DCOMMON_UTILS=$COMMON_UTILS
cmake --build --preset conan-debug -DCOMMON_UTILS_DIR=$COMMON_UTILS
```
The build targets are currently just `distutils` lib and the `merkle_demo` and
`keystore_demo` examples, in the `build/Debug` directory:

```shell
./build/Debug/merkle_demo "this is the string to hash"
```

For the `Release` build, use the `conan-release` preset and `Release` build type.
See [#Common utilities](#common-utilities) for a simpler way.

### Common utilities

The build/test scripts in this repository take advantage of shared common utility functions in [this common utils repository](https://bitbucket.org/marco/common-utils): clone it
somewhere, and make `$COMMON_UTILS_DIR` point to it:
The build/test scripts in this repository take advantage of shared common utility functions in
[the Common Utils repository](https://bitbucket.org/marco/common-utils): follow the instructions there to install the utilities and
set the `COMMON_UTILS` environment variable to point to the directory where you installed them.

That is done as part of the installation process anyway:

```shell
git clone [email protected]:marco/common-utils.git
export COMMON_UTILS_DIR="$(pwd)/common-utils"
export COMMON_UTILS=/path/to/common-utils
export VERSION=...
curl -s -L https://cdn.githubraw.com/massenz/common-utils/$VERSION/install.sh | zsh -s
```

To build/test the project, link to the scripts there:

```shell
ln -s ${COMMON_UTILS_DIR}/build.sh build && \
ln -s ${COMMON_UTILS_DIR}/test.sh test
ln -s ${COMMON_UTILS_DIR}/build.sh bin/build && \
ln -s ${COMMON_UTILS_DIR}/test.sh bin/test
```

### Build & Install libdistutils.so
Expand Down
13 changes: 8 additions & 5 deletions conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ glog/0.4.0
gtest/1.15.0
openssl/3.3.2
#protobuf/5.27.0
zeromq/4.3.5
#cppzmq/4.10.0

[options]
glog/*:with_gflags=False
gtest/*:shared=False
protobuf/*:shared=True
#protobuf/*:shared=True

[imports]
#
Expand All @@ -24,10 +24,13 @@ protobuf/*:shared=True
# This is useful for the `install` step to move them to $INSTALL_DIR
# if defined.
#
lib, *.dylib* -> ./lib
lib, *.so* -> ./lib
include, * -> ./include
#lib, *.dylib* -> ./lib
#lib, *.so* -> ./lib
#include, * -> ./include

[generators]
CMakeDeps
CMakeToolchain

[layout]
cmake_layout
19 changes: 0 additions & 19 deletions env.sh

This file was deleted.

41 changes: 30 additions & 11 deletions include/Bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#pragma once


#include <memory>
#include <string>
#include <utility>
Expand All @@ -14,6 +13,14 @@
#include "json.hpp"

using json = nlohmann::json;
class Bucket;

/**
* Utility function to stream a string representation of a bucket.
*
* @return the passed in stream, to which the bucket has been streamed to.
*/
std::ostream& operator<<(std::ostream& out, const Bucket &bucket);

/**
* A "bucket" abstracts the concept of a hashed partition, using consistent hashing.
Expand Down Expand Up @@ -79,15 +86,15 @@ class Bucket {
*
* @return the set of {@link partitions()} points that define this bucket
*/
std::vector<float> partition_points() const {
[[nodiscard]] std::vector<float> partition_points() const {
return hash_points_;
}

float partition_point(int i) const {
[[nodiscard]] float partition_point(int i) const {
if (i < 0 || i >= partitions()) {
std::ostringstream msg;
msg << "Out of bound: requesting partition point #" << i << ", when only "
<< partitions() << " are available ('" << name_ << "')";
msg << "Requesting partition point #" << i << ", when only "
<< partitions() << " are available in " << *this;
throw std::out_of_range(msg.str());
}
return hash_points_[i];
Expand All @@ -103,17 +110,29 @@ class Bucket {
*
* @param x a point in the [0, 1] interval.
* @return a pair of {index, point} values that determine which partition point is
* the immediately greater than `x`.
* the one immediately greater than `x`.
*/
std::pair<int, float> partition_point(float x) const;
[[nodiscard]] std::pair<int, float> partition_point(float x) const;

int partitions() const { return hash_points_.size(); }
[[nodiscard]] int partitions() const { return hash_points_.size(); }
};



/**
* Utility function to stream a string representation of a bucket.
* Equality operator for `Bucket` objects.
* Uses the name and partition points to determine equality.
*
* @return the passed in stream, to which the bucket has been streamed to.
* This method actully uses the ordering operator to compare the two buckets, using
* the usual approach that (a == b) iff !(a < b) && !(b < a).
*/
std::ostream& operator<<(std::ostream& out, const Bucket &bucket);
bool operator==(const Bucket &lhs, const Bucket &rhs);

/**
* Ordering operator for `Bucket` objects.
* Uses the name and partition points to define a total order on the Buckets.
*
* To compare partition points (which are floats), we use a tolerance of 1e-6.
* TODO: this should actually be a configurable (static) attribute of the class.
*/
bool operator<(const Bucket &lhs, const Bucket &rhs);
24 changes: 11 additions & 13 deletions include/ConsistentHash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,15 @@ float consistent_hash(const std::string &msg);
*
* See Item 40 of Effective STL.
*/
template <int Tolerance = 5>
class FloatLessWithTolerance :
public std::binary_function<float, float, bool> {

double epsilon_;
public:
FloatLessWithTolerance() {
epsilon_ = pow(10, -Tolerance);
}

bool operator()( const float &left, const float &right ) const {
return (std::abs(left - right) > epsilon_) && (left < right);
}
template<int Tolerance = 5>
class FloatLessWithTolerance {
public:
explicit FloatLessWithTolerance(double eps = pow(10, -Tolerance)) : epsilon_(eps) { }

bool operator()(const float &left, const float &right) const {
return (std::abs(left - right) > epsilon_) && (left < right);
}

private:
double epsilon_;
};
Loading

0 comments on commit 6e28d94

Please sign in to comment.