• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _module-pw_log_string:
2
3=============
4pw_log_string
5=============
6.. pigweed-module::
7   :name: pw_log_string
8
9``pw_log_string`` is a partial backend for ``pw_log``. This backend fowards the
10``PW_LOG_*`` macros to the ``pw_log_string:handler`` facade which is backed by
11a C API. ``pw_log_string:handler`` does not implement the full C API, leaving
12projects to provide their own implementation of
13``pw_log_string_HandleMessageVaList``. See ``pw_log_basic`` for a similar
14``pw_log`` backend that also provides an implementation.
15
16As this module passes the log message, file name, and module name as a string to
17the handler function, it's relatively expensive and not well suited for
18space-constrained devices. This module is oriented towards usage on a host
19(e.g. a simulated device).
20
21Note that ``pw_log_string:handler`` may be used even when it's not used
22as the backend for ``pw_log`` via ``pw_log_string``. For example it can be
23useful to mix tokenized and string based logging in case you have a C ABI where
24tokenization can not be used on the other side.
25
26.. _module-pw_log_string-get-started-gn:
27
28----------------
29Get started (GN)
30----------------
31This section outlines how to implement a ``pw_log_string`` backend in a
32GN-based project.
33
34.. note::
35   The example code was written for a :ref:`host <target-host>` target running
36   on Linux.
37
38Invoke a logging macro
39======================
40Call one of the :ref:`pw_log macros <module-pw_log-macros>` in your project
41code:
42
43.. code-block:: cpp
44   :emphasize-lines: 9
45
46   /* //src/app.cc */
47
48   #include <unistd.h>
49
50   #include "pw_log/log.h"
51
52   int main() {
53       while (true) {
54           PW_LOG_INFO("Hello, world!");
55           sleep(5);
56       }
57       return 0;
58   }
59
60Implement the logging function
61==============================
62Implement :cpp:func:`pw_log_string_HandleMessageVaList()` in C. Macros like
63:cpp:func:`PW_LOG()` hand off the actual logging implementation to this
64function.
65
66The function signature of your implementation must match the one specified by
67Pigweed.
68
69The example code below just logs most of the available information to
70``stdout``:
71
72.. code-block:: c
73
74   /* //src/pw_log_string_backend.c */
75
76   #include <stdio.h>
77   #include <stdarg.h>
78
79   void pw_log_string_HandleMessageVaList(int level,
80                                          unsigned int flags,
81                                          const char* module_name,
82                                          const char* file_name,
83                                          int line_number,
84                                          const char* message,
85                                          va_list args) {
86       printf("Entering custom pw_log_string backend...\n");
87       printf("%d\n", level);
88       printf("%u\n", flags);
89       printf("%s\n", module_name);
90       printf("%s\n", file_name);
91       printf("%d\n", line_number);
92       printf("%s\n", message);
93       if (args) { /* Do something with your args here... */ }
94       printf("Exiting custom pw_log_string backend...\n\n");
95   }
96
97What exactly ``pw_log_string_HandleMessageVaList()`` should do is entirely up to
98the implementation. The log handler in ``pw_log_basic`` is one example, but it's
99also possible to encode as protobuf and send over a TCP port, write to a file,
100or even blink an LED to log as morse code.
101
102Create source sets
103==================
104.. _source set: https://gn.googlesource.com/gn/+/main/docs/reference.md#c_language-source_sets
105
106Use ``pw_source_set`` to create a `source set`_ for your logging
107implementation. Do not use GN's built-in ``source_set`` feature.
108
109.. code-block:: python
110
111   # //src/BUILD.gn
112
113   ...
114
115   pw_source_set("pw_log_string_backend") {
116       sources = [ "pw_log_string_backend.c" ]
117   }
118
119   pw_source_set("pw_log_string_backend.impl") {
120       sources = []
121   }
122
123   ...
124
125.. _//pw_log/BUILD.gn: https://cs.opensource.google/pigweed/pigweed/+/main:pw_log/BUILD.gn
126
127The empty ``pw_log_string_backend.impl`` source set prevents circular
128dependencies. See the comment for ``group("impl")`` in `//pw_log/BUILD.gn`_
129for more context.
130
131Configure backends
132==================
133Update your target toolchain configuration file:
134
135* Set ``pw_log_BACKEND`` to ``dir_pw_log_string``
136* Point ``pw_log_string_HANDLER_BACKEND`` to your source set that implements
137  :cpp:func:`pw_log_string_HandleMessageVaList()`
138* Update :ref:`pw_build_LINK_DEPS <module-pw_build-link-deps>` to include
139  ``"$dir_pw_log:impl"`` and ``"$dir_pw_log_string:handler:impl"``
140
141.. code-block:: python
142   :emphasize-lines: 11,12,14,15
143
144   # //targets/my_target/target_toolchains.gni
145
146   ...
147
148   my_target = {
149     ...
150     my_toolchain = {
151       name = "my_toolchain"
152       defaults = {
153         ...
154         pw_log_BACKEND = dir_pw_log_string
155         pw_log_string_HANDLER_BACKEND = "//src:pw_log_string_backend"
156         pw_build_LINK_DEPS = [
157           "$dir_pw_log:impl",
158           "$dir_pw_log_string:handler.impl",
159           ...
160         ]
161         ...
162       }
163     }
164   }
165
166   ...
167
168
169(Optional) Implement message handler
170====================================
171Optionally provide your own implementation of ``PW_LOG_STRING_HANDLE_MESSAGE``
172which invokes ``pw_log_string_HANDLER_BACKEND`` with your selected arguments.
173
174``assert`` wrapper
175==================
176A wrapper for ``assert`` is provided that redirects calls to the ``pw_log_string``
177handler. This can be used to replace all usage of ``assert`` in a Newlib binary
178at link time.
179
180-------------
181API reference
182-------------
183.. doxygenfunction:: pw_log_string_HandleMessageVaList(int level, unsigned int flags, const char* module_name, const char* file_name, int line_number, const char* message, va_list args)
184