# An update on C++-ification of logging APIs

**URL:** <https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77>\
**Category:** Developers\
**Created:** [September 1, 2025, 11:49pm UTC](https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77 "2025-09-01T23:49:57Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rocallahan](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/rocallahan/32/22_2.png) [@rocallahan](https://yosyshq.discourse.group/u/rocallahan)\
**Post date:** [September 1, 2025, 11:49pm UTC](https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77/1 "2025-09-01T23:49:57Z")

</div>

Until recently the Yosys `stringf()` and logging APIs used C-style variadic functions. That means C++ objects like `std::string` and `std::string_view` can’t be passed directly, so the code is littered with `.c_str()` calls… and fear of associated lifetime issues has led to temporary space leaks like `log_id_cache`.

[`std::string_view` is not used much in Yosys currently, but it’s nice because unlike `const char*`, it lets you print not-null-terminated substrings without any copying.]

It would be good to fix this so C++ standard string types and also Yosys types such as `RTLIL::IdString` are passed directly. This allows removing a lot of `.c_str()` calls to declutter the code.

There was some discussion about the way forward, [here](https://github.com/YosysHQ/yosys/pull/5211#issuecomment-3052197601). There’s some interest in adopting `std::format` or `{fmt}`. However, that requires converting all format strings from `%`-style syntax to `{}`-style syntax. Instead, I proposed using C++ variadic templates to implement `%`-style formatting. I implemented that and my [PR](https://github.com/YosysHQ/yosys/pull/5221) for `stringf()` was actually merged, so today you can pass `std::string` and `std::string_view` to `stringf()`.

I have two followup PRs waiting for review. [One](https://github.com/YosysHQ/yosys/pull/5304) adds support for `IdString` to `stringf()` and mass-removes `.c_str()` calls from `stringf()` parameters. The [other](https://github.com/YosysHQ/yosys/pull/5243) updates the logging APIs to use the same formatting machinery as `stringf()` uses, thus immediately making `std::string`, `std::string_view` and `IdString` usable as `log()` parameters directly. (Of course `std::string` and `IdString` are passed by reference.)

Once these PRs are merged, we can look at fixing `log_id` and `log_signal` to avoid use of `log_str()` and the `log_id_cache` by returning `std::string` or `std::string_view`.

Even if the desired end goal is to use `std::format` or `{fmt}`, I think these PRs are a good incremental step forward.

---

<div class="post-metadata">

**Author:** ![jix](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/jix/32/23_2.png) [@jix](https://yosyshq.discourse.group/u/jix)\
**Post date:** [September 4, 2025, 12:13pm UTC](https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77/2 "2025-09-04T12:13:07Z")

</div>

I’m looking forward to this and agree that making incremental improvements is the way forward, even if we ultimately want to migrate to `std::format` or `{fmt}`.

As I mentioned during the dev JF, I’m particularly excited by the possibility to add formatters for RTLIL types and other custom types. Since, as you noted, some of the types commonly logged have multiple commonly used log representations (e.g. `log_id` stripping a `\` prefix vs `.c_str()` that doesn’t), that does raise the question of how to handle that. IMO if the goal is to migrate to another formatting library it would make sense to choose a way that’s as forwards compatible as possible, although off the top of my head I have no idea what that should look like. Discussing this aspect might also be a bit premature, it certainly shouldn’t get in the way of getting the base functionality reviewed and merged, I just wanted to make sure my thoughts on this were written down somewhere.

---

<div class="post-metadata">

**Author:** ![rocallahan](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/rocallahan/32/22_2.png) [@rocallahan](https://yosyshq.discourse.group/u/rocallahan)\
**Post date:** [September 4, 2025, 8:33pm UTC](https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77/3 "2025-09-04T20:33:00Z")

</div>

One option would be to just retain `log_id()` as the syntax for stripping prefixes from `IdString`. I would change it to return `std::string_vew`, but that’s a minor change. Returning `std::string_view` is not any safer than return `const char*`, but at one point I hand-audited all `log_id()` calls and didn’t find any lifetime issues. That’s not surprising — even if you call `log_id()` on a temporary `IdString`, the temporary won’t be destroyed until the end of the enclosing statement, so in parameters to`log()` calls the temporary will live long enough.

Alternatively, we could have dedicated format-string syntax to select alternate forms. A natural choice for printf-style formatting would be `%#s` to strip prefixes from `IdString`. `{fmt}` and `std::format` also support formatting syntax extension, with different syntax of course.

Of course we could support both `log_id()` and dedicated format-string syntax.

---

<div class="post-metadata">

**Author:** ![jix](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/jix/32/23_2.png) [@jix](https://yosyshq.discourse.group/u/jix)\
**Post date:** [September 9, 2025, 6:11pm UTC](https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77/4 "2025-09-09T18:11:37Z")

</div>

For anyone following along here, both PRs ([#5304](https://github.com/YosysHQ/yosys/pull/5304), [#5243](https://github.com/YosysHQ/yosys/pull/5243)) got merged.

---

<div class="post-metadata">

**Author:** ![micko](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/micko/32/53_2.png) [@micko](https://yosyshq.discourse.group/u/micko)\
**Post date:** [June 9, 2026, 12:58pm UTC](https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77/5 "2026-06-09T12:58:40Z")

</div>

@rocallahan Since in last release we moved to C++20 we can maybe move forward with more log changes.

FYI id2cstr and log\_id are not used any more in our code, but they could be used in plugins, so in case of gradual cleanup we should still have these API calls available.

Do you think converting internal change to io.h to use fmt with printf style formatting is good first thing to do in this case ? Or do you see any other cleanups we could do to make transition easier ?

---

<div class="post-metadata">

**Author:** ![rocallahan](https://yyz2.discourse-cdn.com/free1/user_avatar/yosyshq.discourse.group/rocallahan/32/22_2.png) [@rocallahan](https://yosyshq.discourse.group/u/rocallahan)\
**Post date:** [June 9, 2026, 5:56pm UTC](https://yosyshq.discourse.group/t/an-update-on-c-ification-of-logging-apis/77/6 "2026-06-09T17:56:49Z")

</div>

> Do you think converting internal change to io.h to use fmt with printf style formatting is good first thing to do in this case ? Or do you see any other cleanups we could do to make transition easier ?

Personally I don’t think migrating to `std::format` or `fmt` style formatting is worth the churn. But that’s not a technical judgement. If you / the project want to do it, I guess you can just go ahead … I can’t think of any other cleanups that would smooth that path.
