Skip to content

Enable defining custom namespace for spdlog#3611

Open
hel-ableton wants to merge 5 commits into
gabime:v2.xfrom
hel-ableton:hel-ns-macros-pr-v2.x
Open

Enable defining custom namespace for spdlog#3611
hel-ableton wants to merge 5 commits into
gabime:v2.xfrom
hel-ableton:hel-ns-macros-pr-v2.x

Conversation

@hel-ableton
Copy link
Copy Markdown

Enable defining custom namespace for spdlog

When spdlog is used by multiple components in the same process,
each bundling their own copy, the linker or dynamic loader may resolve
all spdlog:: symbols to whichever definition it finds first. This is an ODR
(One Definition Rule) violation and can cause subtle misbehavior:
loggers silently share state across components, or the program crashes
when internal data structures disagree on their layout.

The SPDLOG_NAMESPACE macro lets a consumer place their copy of
spdlog in a dedicated namespace, making its symbols distinct from any
other copy in the process and avoiding ODR conflicts entirely.

For more sophisticated use cases, SPDLOG_NAMESPACE_BEGIN and
SPDLOG_NAMESPACE_END can be overridden directly. One example is
defining the namespace as inline, which keeps existing source code that
refers to spdlog::logger or spdlog::info(…) compiling without
changes, while the mangled symbol names still include the namespace
and remain ABI-distinct from other copies.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a configurable namespace mechanism for spdlog (via SPDLOG_NAMESPACE, SPDLOG_NAMESPACE_BEGIN, SPDLOG_NAMESPACE_END) to help consumers avoid ODR/linker collisions when multiple spdlog copies are present in the same process, and updates many headers to use these namespace macros.

Changes:

  • Adds namespace customization macros in include/spdlog/common.h.
  • Replaces namespace spdlog { ... } blocks across many public headers with SPDLOG_NAMESPACE_BEGIN/END.
  • Adjusts one C++17 nested-namespace usage (namespace spdlog::details) to a C++11-compatible form using the new macros.

Reviewed changes

Copilot reviewed 51 out of 51 changed files in this pull request and generated 20 comments.

Show a summary per file
File Description
include/spdlog/common.h Defines namespace customization macros and wraps common declarations in SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/spdlog.h Wraps API functions in SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/source_loc.h Switches source_loc namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/stopwatch.h Switches stopwatch namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/bin_to_hex.h Switches hex-dump utilities namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/pattern_formatter.h Switches pattern_formatter namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/logger.h Switches logger namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/fwd.h Switches forward declarations namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/formatter.h Switches formatter namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/filename_t.h Switches filename_t namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/file_event_handlers.h Switches file event handlers namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/async_log_msg.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/circular_q.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/err_helper.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/file_helper.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/fmt_helper.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/log_msg.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/mpmc_blocking_q.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/null_mutex.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/os.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/tcp_client_unix.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/tcp_client_windows.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/udp_client_unix.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/details/udp_client_windows.h Switches details namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/ansicolor_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/android_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/async_sink.h Switches sinks/details forward-decl namespaces to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/base_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/basic_file_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/callback_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/daily_file_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/dist_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/dup_filter_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/hourly_file_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/kafka_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/mongo_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/msvc_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/null_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/ostream_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/qt_sinks.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/ringbuffer_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/rotating_file_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/stdout_color_sinks.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/stdout_sinks.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/syslog_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/systemd_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/tcp_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/udp_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/win_eventlog_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
include/spdlog/sinks/wincolor_sink.h Switches sinks namespace to SPDLOG_NAMESPACE_BEGIN/END.
Comments suppressed due to low confidence (4)

include/spdlog/common.h:60

  • Inside SPDLOG_NAMESPACE_BEGIN this header still hard-codes spdlog:: in declarations (e.g. to_string_view(spdlog::level), level_from_str), which will fail to compile when SPDLOG_NAMESPACE is set to a non-spdlog namespace. Prefer unqualified level (since you’re already inside the namespace) or qualify via the configurable namespace macro consistently.
SPDLOG_NAMESPACE_BEGIN

class formatter;

namespace sinks {
class sink;
}

include/spdlog/bin_to_hex.h:93

  • After switching to SPDLOG_NAMESPACE_BEGIN/END, this header’s fmt::formatter specialization and helper functions still hard-code spdlog::details::dump_info and spdlog::fmt_lib::format_to. When SPDLOG_NAMESPACE is customized, those names won’t resolve. Use the active namespace macro (or another consistent qualifier) for these references.
SPDLOG_NAMESPACE_END

template <typename T>
struct fmt::formatter<spdlog::details::dump_info<T>, char> {
    char delimiter = ' ';

include/spdlog/details/fmt_helper.h:18

  • Within SPDLOG_NAMESPACE_BEGIN, append_string_view still takes a spdlog::string_view_t. With a custom namespace, spdlog::string_view_t won’t exist. Use string_view_t (unqualified) or qualify via the configurable namespace.
SPDLOG_NAMESPACE_BEGIN
namespace details {
namespace fmt_helper {

inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest) {
    const auto *buf_ptr = view.data();
    dest.append(buf_ptr, buf_ptr + view.size());

include/spdlog/details/os.h:18

  • details/os.h is inside SPDLOG_NAMESPACE_BEGIN, but now() is declared as returning spdlog::log_clock::time_point. That hard-codes the original namespace and will fail with SPDLOG_NAMESPACE customization. Use log_clock::time_point (unqualified) or qualify via the configurable namespace consistently.
SPDLOG_NAMESPACE_BEGIN
namespace details {
namespace os {

SPDLOG_API spdlog::log_clock::time_point now() noexcept;

SPDLOG_API std::tm localtime(const std::time_t &time_tt) noexcept;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +7 to 9
SPDLOG_NAMESPACE_BEGIN // source location
struct source_loc {
constexpr source_loc() = default;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed by 1d52715

Comment thread include/spdlog/fwd.h
Comment on lines 4 to 7
#pragma once

namespace spdlog {
SPDLOG_NAMESPACE_BEGIN
class logger;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See 1d52715

Comment on lines 14 to +18
#endif

namespace spdlog {
SPDLOG_NAMESPACE_BEGIN
using filename_t = std::filesystem::path;
} // namespace spdlog
SPDLOG_NAMESPACE_END
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See 1d52715

Comment on lines 5 to 9
#include "./filename_t.h"

namespace spdlog {
SPDLOG_NAMESPACE_BEGIN
struct file_event_handlers {
file_event_handlers()
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See 1d52715

Comment thread include/spdlog/spdlog.h
inline void critical(std::string_view msg) { log(level::critical, msg); }

} // namespace spdlog
SPDLOG_NAMESPACE_END
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by 4072679

Comment on lines 47 to +48
} // namespace sinks
} // namespace spdlog
SPDLOG_NAMESPACE_END
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 85 to +86
} // namespace sinks
} // namespace spdlog
SPDLOG_NAMESPACE_END
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 58 to +59
} // namespace sinks
} // namespace spdlog
SPDLOG_NAMESPACE_END
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// clang-format on

namespace spdlog {
SPDLOG_NAMESPACE_BEGIN
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// qt_sink class
//
namespace spdlog {
SPDLOG_NAMESPACE_BEGIN
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gabime
Copy link
Copy Markdown
Owner

gabime commented May 26, 2026

SPDLOG_NAMESPACE_BEGIN is enough. no need for the SPDLOG_NAMESPACE.
Also see the copilot findings. seems more involved than appears. I am not sure it worth it .

Move namespace macros to a dedicated namespace.h header and include it
in headers that don't pull in common.h, making each self-contained.
Inside SPDLOG_NAMESPACE_BEGIN blocks, names are already in scope
unqualified. The explicit spdlog:: prefix was harmless with the default
namespace but would silently break with any customization.
Fix logging macros in spdlog.h to use SPDLOG_NS__ instead of hardcoded
spdlog::, so they resolve correctly when SPDLOG_NAMESPACE_BEGIN is
customized.
@hel-ableton
Copy link
Copy Markdown
Author

Thank you for the review!

SPDLOG_NAMESPACE_BEGIN is enough. no need for the SPDLOG_NAMESPACE

See here for a suggestion to handle SPDLOG_NAMESPACE more like an implementation detail.

Also see the copilot findings.

I'm sorry for the oversight! ca6be4e fixes the namespaces which fell besides the customization. I'm afraid you would have to make it a rule not to introduce new redundant namespace qualifiers in headers. 😬

With the v2.x-based changes, I'm tapping in the dark a bit, as I can't easily use v2.x in our project. I've applied the necessary changes from this review to #3610 too, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants