From f7e7a5d09e5e1e0a0a468aa424f77b7a3101e4b2 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Fri, 26 Sep 2025 17:33:26 +0200 Subject: [PATCH] Logging: Add argument to list all available categories New `--log-list-categories` command line argument to list all available logging categories. This improves documentation of logging, allowing users to understand what logging categories are available for use. It is also useful for developers to understand what logging categories already exist before making a change. Implemented using static initializers to register all logrefs on startup. Ref #141754 Pull Request: https://projects.blender.org/blender/blender/pulls/146456 --- intern/clog/CLG_log.h | 12 ++++++++ intern/clog/clog.cc | 53 +++++++++++++++++++++++++++------- source/creator/creator_args.cc | 16 ++++++++++ 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/intern/clog/CLG_log.h b/intern/clog/CLG_log.h index e580f121892..181984c75bd 100644 --- a/intern/clog/CLG_log.h +++ b/intern/clog/CLG_log.h @@ -76,6 +76,8 @@ struct CLG_LogType { }; struct CLG_LogRef { + CLG_LogRef(const char *identifier); + const char *identifier; CLG_LogType *type; struct CLG_LogRef *next; @@ -114,6 +116,10 @@ void CLG_level_set(CLG_Level level); void CLG_logref_init(CLG_LogRef *clg_ref); +void CLG_logref_register(CLG_LogRef *clg_ref); +void CLG_logref_list_all(void (*callback)(const char *identifier, void *user_data), + void *user_data); + int CLG_color_support_get(CLG_LogRef *clg_ref); /* When true, quiet any NOCHECK logs that would otherwise be printed regardless of log filters @@ -123,6 +129,12 @@ int CLG_color_support_get(CLG_LogRef *clg_ref); void CLG_quiet_set(bool quiet); bool CLG_quiet_get(); +inline CLG_LogRef::CLG_LogRef(const char *identifier) + : identifier(identifier), type(nullptr), next(nullptr) +{ + CLG_logref_register(this); +} + /** Declare outside function, declare as extern in header. */ #define CLG_LOGREF_DECLARE_GLOBAL(var, id) \ static CLG_LogRef _static_##var = {id}; \ diff --git a/intern/clog/clog.cc b/intern/clog/clog.cc index a4328f8340f..fe0583270e0 100644 --- a/intern/clog/clog.cc +++ b/intern/clog/clog.cc @@ -14,6 +14,7 @@ #include #include +#include /* Disable for small single threaded programs * to avoid having to link with pthreads. */ @@ -78,8 +79,6 @@ struct CLG_IDFilter { struct CLogContext { /** Single linked list of types. */ CLG_LogType *types; - /** Single linked list of references. */ - CLG_LogRef *refs; #ifdef WITH_CLOG_PTHREADS pthread_mutex_t types_lock; #endif @@ -113,6 +112,20 @@ struct CLogContext { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Global LogRef Single Linked List + * \{ */ + +static CLG_LogRef **clg_all_refs_p() +{ + /* Inside a function for correct static initialization order, otherwise + * all_refs might get null initialized only after logrefs are registered.*/ + static CLG_LogRef *all_refs = nullptr; + return &all_refs; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Mini Buffer Functionality * @@ -827,10 +840,8 @@ static void CLG_ctx_free(CLogContext *ctx) MEM_freeN(item); } - while (ctx->refs != nullptr) { - CLG_LogRef *item = ctx->refs; - ctx->refs = item->next; - item->type = nullptr; + for (CLG_LogRef *ref = *clg_all_refs_p(); ref; ref = ref->next) { + ref->type = nullptr; } for (uint i = 0; i < 2; i++) { @@ -944,6 +955,32 @@ bool CLG_quiet_get() * Use to avoid look-ups each time. * \{ */ +void CLG_logref_register(CLG_LogRef *clg_ref) +{ + /* Add to global list of refs, both for setting the type to null on CLG_exit() + * and so CLG_logref_list_all can be used to print all categories. */ + static std::mutex mutex; + std::scoped_lock lock(mutex); + CLG_LogRef **all_refs = clg_all_refs_p(); + clg_ref->next = *all_refs; + *all_refs = clg_ref; +} + +void CLG_logref_list_all(void (*callback)(const char *identifier, void *user_data), + void *user_data) +{ + /* Generate sorted list of unique identifiers. */ + auto cmp = [](const char *a, const char *b) { return std::strcmp(a, b) < 0; }; + std::set identifiers(cmp); + for (CLG_LogRef *ref = *clg_all_refs_p(); ref; ref = ref->next) { + identifiers.insert(ref->identifier); + } + + for (const char *identifier : identifiers) { + callback(identifier, user_data); + } +} + void CLG_logref_init(CLG_LogRef *clg_ref) { #ifdef WITH_CLOG_PTHREADS @@ -951,10 +988,6 @@ void CLG_logref_init(CLG_LogRef *clg_ref) pthread_mutex_lock(&g_ctx->types_lock); #endif if (clg_ref->type == nullptr) { - /* Add to the refs list so we can nullptr the pointers to 'type' when CLG_exit() is called. */ - clg_ref->next = g_ctx->refs; - g_ctx->refs = clg_ref; - CLG_LogType *clg_ty = clg_ctx_type_find_by_name(g_ctx, clg_ref->identifier); if (clg_ty == nullptr) { clg_ty = clg_ctx_type_register(g_ctx, clg_ref->identifier); diff --git a/source/creator/creator_args.cc b/source/creator/creator_args.cc index 844c85db4c5..a2eab2aba42 100644 --- a/source/creator/creator_args.cc +++ b/source/creator/creator_args.cc @@ -732,6 +732,7 @@ static void print_help(bArgs *ba, bool all) BLI_args_print_arg_doc(ba, "--log-show-source"); BLI_args_print_arg_doc(ba, "--log-show-backtrace"); BLI_args_print_arg_doc(ba, "--log-file"); + BLI_args_print_arg_doc(ba, "--log-list-categories"); PRINT("\n"); PRINT("Debug Options:\n"); @@ -1312,6 +1313,19 @@ static int arg_handle_log_set(int argc, const char **argv, void * /*data*/) return 0; } +static const char arg_handle_list_clog_cats_doc[] = + "\n" + "\tList all available logging categories for --log, and exit.\n"; + +static int arg_handle_list_clog_cats(int /*argc*/, const char ** /*argv*/, void * /*data*/) +{ + auto print_identifier = [](const char *identifier, void *) { printf("%s\n", identifier); }; + CLG_logref_list_all(print_identifier, nullptr); + BKE_blender_atexit(); + exit(EXIT_SUCCESS); + return 0; +} + static const char arg_handle_debug_mode_set_doc[] = "\n" "\tTurn debugging on.\n" @@ -2866,10 +2880,12 @@ void main_args_setup(bContext *C, bArgs *ba, bool all) * Also and commands that exit after usage. */ BLI_args_pass_set(ba, ARG_PASS_SETTINGS); BLI_args_add(ba, "-h", "--help", CB(arg_handle_print_help), ba); + /* MS-Windows only. */ BLI_args_add(ba, "/?", nullptr, CB_EX(arg_handle_print_help, win32), ba); BLI_args_add(ba, "-v", "--version", CB(arg_handle_print_version), nullptr); + BLI_args_add(ba, nullptr, "--log-list-categories", CB(arg_handle_list_clog_cats), nullptr); BLI_args_add(ba, "-y", "--enable-autoexec", CB_EX(arg_handle_python_set, enable), (void *)true); BLI_args_add(