Skip to content

Commit

Permalink
migrate from conan 1 to conan 2 (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
copperlight authored Nov 20, 2024
1 parent 8b9d409 commit 9a52ec5
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 107 deletions.
51 changes: 5 additions & 46 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,16 @@ jobs:
build:
if: ${{ github.repository == 'Netflix/spectator-cpp' }}
runs-on: ubuntu-latest
env:
BUILD_DIR: "cmake-build"
BUILD_TYPE: "Debug"
CC: "gcc-11"
CXX: "g++-11"
LANG: "en_US.UTF-8"
steps:
- uses: actions/checkout@v4

- name: Conan+Cmake Cache
uses: actions/cache@v4
with:
path: |
~/.conan
~/work/spectator-cpp/spectator-cpp/cmake-build
key: ${{ runner.os }}-conan-cmake

- name: Install System Dependencies
run: |
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update && sudo apt-get install -y binutils-dev g++-11 libiberty-dev
echo "==== cmake ===="
cmake -version
echo "==== python ===="
python3 -V
echo "==== conan ===="
pip install -r requirements.txt
conan --version
if [[ ! -f ~/.conan/profiles/default ]]; then conan profile new default --detect; fi
conan profile update settings.compiler.libcxx=libstdc++11 default
- name: Install Project Dependencies
run: |
if [[ "$BUILD_TYPE" == "Debug" ]]; then
conan install . --build --install-folder $BUILD_DIR --profile ./sanitized
else
conan install . --build=missing --install-folder $BUILD_DIR
fi
- name: Build spectator-cpp
run: |
cd $BUILD_DIR
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
cmake --build .
echo "==== ldd ===="
ldd bin/spectatord_main || true
sudo apt-get update && sudo apt-get install -y binutils-dev g++-13 libiberty-dev
- name: Test spectator-cpp
- name: Build
run: |
cd $BUILD_DIR
GTEST_COLOR=1 ctest --verbose
./setup-venv.sh
source venv/bin/activate
./build.sh
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.DS_Store
.idea/
cmake-build-debug
CMakeUserPresets.json
cmake-build/
conan_provider.cmake
spectator/valid_chars.inc
venv/
28 changes: 21 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ project(spectator-cpp)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

add_compile_options(-fno-omit-frame-pointer "$<$<CONFIG:Debug>:-fsanitize=address>")
add_link_options(-fno-omit-frame-pointer "$<$<CONFIG:Debug>:-fsanitize=address>")
add_compile_options(-pedantic -Werror -Wall -Wno-missing-braces -fno-omit-frame-pointer "$<$<CONFIG:Debug>:-fsanitize=address>")

find_package(absl REQUIRED)
find_package(asio REQUIRED)
find_package(Backward REQUIRED)
find_package(fmt REQUIRED)
find_package(GTest REQUIRED)
find_package(spdlog REQUIRED)

include(CTest)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

#-- spectator_test test executable
file(GLOB spectator_test_source_files
Expand All @@ -19,7 +25,10 @@ file(GLOB spectator_test_source_files
"spectator/test_*.h"
)
add_executable(spectator_test ${spectator_test_source_files})
target_link_libraries(spectator_test spectator ${CONAN_LIBS})
target_link_libraries(spectator_test
spectator
gtest::gtest
)
add_test(
NAME spectator_test
COMMAND spectator_test
Expand All @@ -41,8 +50,13 @@ add_library(spectator
"spectator/stateless_meters.h"
"spectator/valid_chars.inc"
)
target_link_libraries(spectator ${CONAN_LIBS})
target_link_options(spectator PRIVATE "$<$<CONFIG:Release>:-static-libstdc++>")
target_link_libraries(spectator
abseil::abseil
asio::asio
Backward::Backward
fmt::fmt
spdlog::spdlog
)

#-- generator tools
add_executable(gen_valid_chars "tools/gen_valid_chars.cc")
Expand Down
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,24 @@ fills up, the `Publisher` will not send nay meters to the sidecar. Therefore, if
meters at a high rate, you should either keep the buffer very small, or do not configure a buffer size at all,
which will fall back to the "publish immediately" mode of operation.
## Local Development
## Local & IDE Configuration
```shell
# setup python venv and activate, to gain access to conan cli
./setup-venv.sh
source venv/bin/activate
# link clion default build directory to our build directory
ln -s cmake-build cmake-build-debug
./build.sh # [clean|clean --force|skiptest]
./build.sh # [clean|clean --confirm|skiptest]
```

* CLion > Preferences > Plugins > Marketplace > Conan > Install
* CLion > Preferences > Build, Execution, Deploy > Conan > Conan Executable: $PROJECT_HOME/venv/bin/conan
* Install the Conan plugin for CLion.
* CLion > Settings > Plugins > Marketplace > Conan > Install
* Configure the Conan plugin.
* The easiest way to configure CLion to work with Conan is to build the project first from the command line.
* This will establish the `$PROJECT_HOME/CMakeUserPresets.json` file, which will allow you to choose the custom
CMake configuration created by Conan when creating a new CMake project. Using this custom profile will ensure
that sources are properly indexed and explorable.
* Open the project. The wizard will show three CMake profiles.
* Disable the default Cmake `Debug` profile.
* Enable the CMake `conan-debug` profile.
* CLion > View > Tool Windows > Conan > (gear) > Conan Executable: `$PROJECT_HOME/venv/bin/conan`
46 changes: 28 additions & 18 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#!/usr/bin/env bash

set -e

# usage: ./build.sh [clean|clean --confirm|skiptest]

BUILD_DIR=cmake-build
# Choose: Debug, Release, RelWithDebInfo and MinSizeRel
# Choose: Debug, Release, RelWithDebInfo and MinSizeRel. Use Debug for asan checking locally.
BUILD_TYPE=Debug

BLUE="\033[0;34m"
Expand All @@ -11,43 +15,49 @@ if [[ "$1" == "clean" ]]; then
echo -e "${BLUE}==== clean ====${NC}"
rm -rf $BUILD_DIR
rm -f spectator/*.inc
if [[ "$2" == "--force" ]]; then
# remove all packages and binaries from the local cache, to allow swapping between Debug/Release builds
conan remove '*' --force
if [[ "$2" == "--confirm" ]]; then
# remove all packages from the conan cache, to allow swapping between Release/Debug builds
conan remove "*" --confirm
fi
fi

if [[ "$OSTYPE" == "linux-gnu"* ]]; then
export CC=gcc-11
export CXX=g++-11
export CC=gcc-13
export CXX=g++-13
fi

if [[ ! -d $BUILD_DIR ]]; then
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo -e "${BLUE}==== configure default profile ====${NC}"
conan profile new default --detect
conan profile update settings.compiler.libcxx=libstdc++11 default
fi
if [[ ! -f "$HOME/.conan2/profiles/default" ]]; then
echo -e "${BLUE}==== create default profile ====${NC}"
conan profile detect
fi

if [[ ! -d $BUILD_DIR ]]; then
echo -e "${BLUE}==== install required dependencies ====${NC}"
if [[ "$BUILD_TYPE" == "Debug" ]]; then
conan install . --build --install-folder $BUILD_DIR --profile ./sanitized
conan install . --output-folder=$BUILD_DIR --build="*" --settings=build_type=$BUILD_TYPE --profile=./sanitized
else
conan install . --build=missing --install-folder $BUILD_DIR
conan install . --output-folder=$BUILD_DIR --build=missing
fi
fi

pushd $BUILD_DIR || exit 1
pushd $BUILD_DIR

echo -e "${BLUE}==== configure conan environment to access tools ====${NC}"
source conanbuild.sh

if [[ $OSTYPE == "darwin"* ]]; then
export MallocNanoZone=0
fi

echo -e "${BLUE}==== generate build files ====${NC}"
cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE || exit 1
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE

echo -e "${BLUE}==== build ====${NC}"
cmake --build . || exit 1
cmake --build .

if [[ "$1" != "skiptest" ]]; then
echo -e "${BLUE}==== test ====${NC}"
GTEST_COLOR=1 ctest --verbose
fi

popd || exit 1
popd
16 changes: 8 additions & 8 deletions conanfile.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from conans import ConanFile
from conan import ConanFile


class SpectatorCppConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
requires = (
"abseil/20230125.3",
"asio/1.28.1",
"abseil/20240722.0",
"asio/1.32.0",
"backward-cpp/1.6",
"fmt/10.1.1",
"gtest/1.14.0",
"spdlog/1.12.0"
"fmt/11.0.2",
"gtest/1.15.0",
"spdlog/1.15.0",
)
generators = "cmake"
default_options = {}
tool_requires = ()
generators = "CMakeDeps", "CMakeToolchain"
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
conan==1.64.1
conan==2.9.2
41 changes: 32 additions & 9 deletions spectator/id.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,39 @@ struct equal_to<shared_ptr<spectator::Id>> {

} // namespace std

template <>
struct fmt::formatter<spectator::Id> {
constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
template <> struct fmt::formatter<spectator::Tags>: formatter<std::string_view> {
auto format(const spectator::Tags& tags, format_context& ctx) const -> format_context::iterator {
std::string s;
auto size = tags.size();

if (size > 0) {
// sort keys, to ensure stable output
std::vector<std::string> keys;
for (const auto& pair : tags) {
keys.push_back(pair.first);
}
std::sort(keys.begin(), keys.end());

s = "[";
for (const auto &key : keys) {
if (size > 1) {
s += key + "=" + tags.at(key) + ", ";
} else {
s += key + "=" + tags.at(key) + "]";
}
size -= 1;
}
} else {
s = "[]";
}

return fmt::formatter<std::string_view>::format(s, ctx);
}
};

// formatter for Ids
template <typename FormatContext>
auto format(const spectator::Id& id, FormatContext& context) {
return fmt::format_to(context.out(), "Id(name={}, tags={})", id.Name(),
id.GetTags());
template <> struct fmt::formatter<spectator::Id>: formatter<std::string_view> {
auto format(const spectator::Id& id, format_context& ctx) const -> format_context::iterator {
auto s = fmt::format("Id(name={}, tags={})", id.Name(), id.GetTags());
return fmt::formatter<std::string_view>::format(s, ctx);
}
};
17 changes: 13 additions & 4 deletions spectator/id_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,31 @@
#include <gtest/gtest.h>

namespace {

using spectator::Id;
using spectator::Tags;

TEST(Id, Create) {
Id id{"foo", Tags{}};
EXPECT_EQ(id.Name(), "foo");
EXPECT_EQ(id.GetTags().size(), 0);
EXPECT_EQ(fmt::format("{}", id), "Id(name=foo, tags=[])");

Id id_tags_single{"name", Tags{{"k", "v"}}};
EXPECT_EQ(id_tags_single.Name(), "name");
EXPECT_EQ(id_tags_single.GetTags().size(), 1);
EXPECT_EQ(fmt::format("{}", id_tags_single), "Id(name=name, tags=[k=v])");

Id id_tags_multiple{"name", Tags{{"k", "v"}, {"k1", "v1"}}};
EXPECT_EQ(id_tags_multiple.Name(), "name");
EXPECT_EQ(id_tags_multiple.GetTags().size(), 2);

Id id_tags{"name", Tags{{"k", "v"}, {"k1", "v1"}}};
EXPECT_EQ(id_tags.Name(), "name");
EXPECT_EQ(id_tags.GetTags().size(), 2);
EXPECT_EQ(fmt::format("{}", id_tags_multiple), "Id(name=name, tags=[k=v, k1=v1])");

std::shared_ptr<Id> id_of{Id::of("name", Tags{{"k", "v"}, {"k1", "v1"}})};
EXPECT_EQ(id_of->Name(), "name");
EXPECT_EQ(id_of->GetTags().size(), 2);
fmt::format("{}", id);
EXPECT_EQ(fmt::format("{}", *id_of), "Id(name=name, tags=[k=v, k1=v1])");
}

TEST(Id, Tags) {
Expand Down
11 changes: 5 additions & 6 deletions spectator/meter_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ enum class MeterType {
};
}

// Provide a formatter for MeterType
template <>
struct fmt::formatter<spectator::MeterType> : fmt::formatter<std::string_view> {
template <typename FormatContext>
auto format(const spectator::MeterType& meter_type, FormatContext& context) {
template <> struct fmt::formatter<spectator::MeterType>: formatter<std::string_view> {
auto format(spectator::MeterType meter_type, format_context& ctx) const -> format_context::iterator {
using namespace spectator;
std::string_view s = "unknown";

switch (meter_type) {
case MeterType::AgeGauge:
s = "age-gauge";
Expand Down Expand Up @@ -56,6 +54,7 @@ struct fmt::formatter<spectator::MeterType> : fmt::formatter<std::string_view> {
s = "timer";
break;
}
return fmt::formatter<std::string_view>::format(s, context);

return fmt::formatter<std::string_view>::format(s, ctx);
}
};
11 changes: 11 additions & 0 deletions spectator/meter_type_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "../spectator/meter_type.h"
#include <gtest/gtest.h>

namespace {

using spectator::MeterType;

TEST(MeterType, Format) {
EXPECT_EQ(fmt::format("{}", MeterType::Counter), "counter");
}
} // namespace
1 change: 1 addition & 0 deletions spectator/stateless_meters.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "id.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/time/time.h"

Expand Down

0 comments on commit 9a52ec5

Please sign in to comment.