Skip to content

Commit e9d65cb

Browse files
committed
fix: workaround for avro-cpp fmt formatter on Windows
conda-forge's avro-cpp defines fmt::formatter with non-const format() method, but fmt v11+ requires const. Create a centralized AvroIncludes.h wrapper that: 1. Temporarily sets FMT_VERSION to 80000 (below 90000 threshold) to prevent avro from defining its broken formatters 2. Includes all avro headers 3. Restores FMT_VERSION and defines const-correct formatters for both avro::Name and avro::Type This can be removed once conda-forge updates avro-cpp. Signed-off-by: Krzysztof Milde <Krzysztof.Milde@Point72.com>
1 parent e0d5cd9 commit e9d65cb

4 files changed

Lines changed: 66 additions & 44 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#ifndef _IN_CSP_ADAPTERS_UTILS_AVROINCLUDES_H
2+
#define _IN_CSP_ADAPTERS_UTILS_AVROINCLUDES_H
3+
4+
// =============================================================================
5+
// Workaround for avro-cpp fmt::formatter incompatibility on Windows
6+
// =============================================================================
7+
// conda-forge's avro-cpp (as of early 2025) has outdated fmt::formatter
8+
// specializations with non-const format() methods, but fmt v11+ requires const.
9+
//
10+
// The avro formatters are guarded by:
11+
// #if FMT_VERSION >= 90000
12+
//
13+
// We temporarily set FMT_VERSION below this threshold to prevent avro from
14+
// defining its broken formatters, then restore it and define const-correct
15+
// versions.
16+
//
17+
// This workaround can be removed once conda-forge updates avro-cpp.
18+
// =============================================================================
19+
20+
#include <fmt/format.h>
21+
22+
#ifdef _MSC_VER
23+
#pragma push_macro("FMT_VERSION")
24+
#undef FMT_VERSION
25+
#define FMT_VERSION 80000
26+
#endif
27+
28+
// Include all avro headers that may be needed
29+
#include <avro/Compiler.hh>
30+
#include <avro/Decoder.hh>
31+
#include <avro/Encoder.hh>
32+
#include <avro/Generic.hh>
33+
#include <avro/GenericDatum.hh>
34+
#include <avro/Node.hh>
35+
#include <avro/Schema.hh>
36+
#include <avro/Stream.hh>
37+
#include <avro/ValidSchema.hh>
38+
39+
#ifdef _MSC_VER
40+
#undef FMT_VERSION
41+
#pragma pop_macro("FMT_VERSION")
42+
43+
// Define const-correct fmt::formatter specializations for avro types
44+
// These mirror the definitions in avro's headers but with the required const
45+
46+
template<>
47+
struct fmt::formatter<avro::Name> : fmt::formatter<std::string> {
48+
auto format(const avro::Name &n, fmt::format_context &ctx) const {
49+
return fmt::format_to(ctx.out(), "{}", n.fullname());
50+
}
51+
};
52+
53+
template<>
54+
struct fmt::formatter<avro::Type> : fmt::formatter<std::string> {
55+
auto format(avro::Type t, fmt::format_context &ctx) const {
56+
return fmt::format_to(ctx.out(), "{}", avro::toString(t));
57+
}
58+
};
59+
60+
#endif // _MSC_VER
61+
62+
#endif // _IN_CSP_ADAPTERS_UTILS_AVROINCLUDES_H

cpp/csp/adapters/utils/AvroMessageStructConverter.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,9 @@
11
#include <csp/adapters/utils/AvroMessageStructConverter.h>
22
#include <csp/engine/PartialSwitchCspType.h>
3-
#include <avro/Compiler.hh>
4-
#include <avro/GenericDatum.hh>
5-
#include <avro/Stream.hh>
6-
#include <avro/Node.hh>
3+
74
#include <type_traits>
85
#include <iostream>
96

10-
// Implement the corrected fmt::formatter<avro::Name> for Windows
11-
#ifdef _MSC_VER
12-
template<typename FormatContext>
13-
auto fmt::formatter<avro::Name, char>::format(const avro::Name &n, FormatContext &ctx) const -> decltype(ctx.out()) {
14-
return fmt::format_to(ctx.out(), "{}", n.fullname());
15-
}
16-
#endif
17-
187
namespace csp::adapters::utils
198
{
209

cpp/csp/adapters/utils/AvroMessageStructConverter.h

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,10 @@
22
#define _IN_CSP_ADAPTERS_UTILS_AVROMESSAGESTRUCTCONVERTER_H
33

44
#include <csp/adapters/utils/MessageStructConverter.h>
5+
#include <csp/adapters/utils/AvroIncludes.h>
56
#include <csp/core/Hash.h>
67
#include <csp/engine/Dictionary.h>
78

8-
// Workaround for avro-cpp from conda-forge on Windows
9-
// conda-forge's avro-cpp has outdated fmt::formatter<avro::Name> without const
10-
// We define the correct const version first, then disable the redefinition error
11-
#ifdef _MSC_VER
12-
#include <fmt/format.h>
13-
// Forward declare avro::Name
14-
namespace avro { class Name; }
15-
// Define correct const-correct formatter before avro headers include the broken one
16-
namespace fmt {
17-
template<>
18-
struct formatter<avro::Name, char> : formatter<std::string, char> {
19-
template<typename FormatContext>
20-
auto format(const avro::Name &n, FormatContext &ctx) const -> decltype(ctx.out());
21-
};
22-
}
23-
// Disable C2766 error (redefinition) - our version will be used
24-
#pragma warning(push)
25-
#pragma warning(disable: 2766)
26-
#endif
27-
28-
#include <avro/Decoder.hh>
29-
#include <avro/Generic.hh>
30-
#include <avro/Schema.hh>
31-
#include <avro/ValidSchema.hh>
32-
33-
#ifdef _MSC_VER
34-
#pragma warning(pop)
35-
#endif
369
#include <list>
3710
#include <string>
3811
#include <unordered_map>

cpp/csp/adapters/utils/AvroMessageWriter.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
#define _IN_CSP_ADAPTERS_UTILS_AVROMESSAGEWRITER_H
33

44
#include <csp/adapters/utils/MessageWriter.h>
5+
#include <csp/adapters/utils/AvroIncludes.h>
56
#include <csp/engine/CspEnum.h>
67
#include <csp/engine/Dictionary.h>
78
#include <csp/engine/PartialSwitchCspType.h>
8-
#include <avro/Compiler.hh>
9-
#include <avro/Encoder.hh>
10-
#include <avro/Generic.hh>
11-
#include <avro/Stream.hh>
9+
1210
#include <cstring>
1311
#include <sstream>
1412

0 commit comments

Comments
 (0)