blob: 56808b3ab4363376bf92ee0c118ecd749805746b [file] [log] [blame]
Keir Mierlec34f71f2019-12-06 12:44:47 -08001.. _chapter-module:
2
3.. default-domain:: cpp
4
5.. highlight:: sh
6
7---------
8pw_module
9---------
10
11The ``pw_module`` module is the "meta-module" for Pigweed, containing
12documentation for Pigweed's module structure as well as tools to detect when
13modules are in or out of conformance to the module style.
14
15The Pigweed module structure
16----------------------------
17
18The Pigweed module structure is designed to keep as much code as possible for a
19particular slice of functionality in one place. That means including the code
20from multiple languages, as well as all the related documentation and tests.
21
Alexei Frolov44d54732020-01-10 14:45:43 -080022Additionally, the structure is designed to limit the number of places a file
Keir Mierlec34f71f2019-12-06 12:44:47 -080023could go, so that when reading callsites it is obvious where a header is from.
Alexei Frolov44d54732020-01-10 14:45:43 -080024That is where the duplicated ``<module>`` occurrences in file paths comes from.
Keir Mierlec34f71f2019-12-06 12:44:47 -080025
David Rogers582c1902020-01-16 18:17:09 -080026Steps to create a new module Pigweed project
27--------------------------------------------
28
29These instructions are for creating a new module for contribution to the
30Pigweed project. See below for an `example`__ of what the new module folder
31might look like.
32
33__ `Example module structure`_
34
351. Create module folder following `Module name`_ guidelines
362. Add `C++ public headers`_ files in
37 ``{pw_module_dir}/public/{pw_module_name}/``
383. Add `C++ implementation files`_ files in ``{pw_module_dir}/``
394. Add module documentation
40
41 - Add ``{pw_module_dir}/README.md`` that has a module summary
42 - Add ``{pw_module_dir}/docs.rst`` that contains the main module
43 documentation
44
455. Add build support inside of new module
46
47 - Add GN with ``{pw_module_dir}/BUILD.gn``
48 - Add Bazel with ``{pw_module_dir}/BUILD``
49 - Add CMake with ``{pw_module_dir}/CMakeLists.txt``
50
516. Add folder alias for new module variable in ``/modules.gni``
52
53 - dir_pw_new = "$dir_pigweed/pw_new"
54
557. Add new module to main GN build
56
57 - in ``/BUILD.gn`` to ``group("pw_modules")`` using folder alias variable
58 - General modules and backends of facades go in ``pw_modules``, facades go
59 in ``pw_facades``
60
618. Add test target for new module in ``/BUILD.gn`` to
62 ``pw_test_group("pw_module_tests")``
639. Add new module to CMake build
64
65 - In ``/CMakeLists.txt`` add ``add_subdirectory(pw_new)``
66
6710. Add the new module to docs module
68
69 - Add in ``docs/BUILD.gn`` to ``pw_doc_gen("docs")``
70
7111. Run `module check`__
72
73 - ``$ pw module-check {pw_module_dir}``
74
75__ `Command: pw module-check`_
76
77Example module structure
78------------------------
Keir Mierlec34f71f2019-12-06 12:44:47 -080079
80.. code-block:: python
81
82 pw_foo/...
83
84 docs.rst # If there is just 1 docs file, call it docs.rst
85 README.md # All modules must have a short README for gittiles
86
87 BUILD.gn # GN build required
88 BUILD # Bazel build required
89
David Rogers582c1902020-01-16 18:17:09 -080090 # C++ public headers; the repeated module name is required
Keir Mierlec34f71f2019-12-06 12:44:47 -080091 public/pw_foo/foo.h
92 public/pw_foo/baz.h
93
94 # Exposed public headers go under internal/
95 public/pw_foo/internal/bar.h
96 public/pw_foo/internal/qux.h
97
98 # Public override headers must go in 'public_overrides'
99 public_overrides/gtest/gtest.h
100 public_overrides/string.h
101
102 # Private headers go into <module>_*/...
103 pw_foo_internal/zap.h
104 pw_foo_private/zip.h
105 pw_foo_secret/alxx.h
106
107 # C++ implementations go in the root
108 foo_impl.cc
109 foo.cc
110 baz.cc
111 bar.cc
112 zap.cc
113 zip.cc
114 alxx.cc
115
116 # C++ tests also go in the root
117 foo_test.cc
118 bar_test.cc
119 zip_test.cc
120
121 # Python files go into 'py/<module>/...'
122 py/setup.py # All Python must be a Python module with setup.py
123 py/foo_test.py # Tests go in py/ but outside of the Python module
124 py/bar_test.py
125 py/pw_foo/__init__.py
126 py/pw_foo/__main__.py
127 py/pw_foo/bar.py
128
129 # Go files go into 'go/...'
130 go/...
131
132 # Examples go in examples/, mixing different languages
133 examples/demo.py
134 examples/demo.cc
135 examples/demo.go
136 examples/BUILD.gn
137 examples/BUILD
138
139 # Size reports go under size_report/
140 size_report/BUILD.gn
141 size_report/base.cc
142 size_report/use_case_a.cc
143 size_report/use_case_b.cc
144
Alexei Frolov942adf02019-12-11 17:07:28 -0800145 # Protobuf definition files go into <module>_protos/...
146 pw_foo_protos/foo.proto
147 pw_foo_protos/internal/zap.proto
148
Keir Mierlec34f71f2019-12-06 12:44:47 -0800149 # Other directories are fine, but should be private.
150 data/...
151 graphics/...
152 collection_of_tests/...
153 code_relating_to_subfeature/...
154
155Module name
156-----------
157Pigweed upstream modules are always named with a prefix ``pw_`` to enforce
158namespacing. Projects using Pigweed that wish to make their own modules can use
Alexei Frolov44d54732020-01-10 14:45:43 -0800159whatever name they like, but we suggest picking a short prefix to namespace
Keir Mierlec34f71f2019-12-06 12:44:47 -0800160your product (e.g. for an Internet of Toast project, perhaps the prefix could
Alexei Frolov44d54732020-01-10 14:45:43 -0800161be ``it_``).
Keir Mierlec34f71f2019-12-06 12:44:47 -0800162
163C++ file and directory locations
164~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165
David Rogers582c1902020-01-16 18:17:09 -0800166C++ public headers
167^^^^^^^^^^^^^^^^^^
168Located ``{pw_module_dir}/public/<module>``. These are headers that must be
169exposed due to C++ limitations (i.e. are included from the public interface,
170but are not intended for public use).
Keir Mierlec34f71f2019-12-06 12:44:47 -0800171
172**Public headers** should take the form:
173
David Rogers582c1902020-01-16 18:17:09 -0800174``{pw_module_dir}/public/<module>/*.h``
Keir Mierlec34f71f2019-12-06 12:44:47 -0800175
176**Exposed private headers** should take the form:
177
David Rogers582c1902020-01-16 18:17:09 -0800178``{pw_module_dir}/public/<module>/internal/*.h``
Keir Mierlec34f71f2019-12-06 12:44:47 -0800179
180Examples:
181
182.. code-block::
183
184 pw_foo/...
185 public/pw_foo/foo.h
186 public/pw_foo/a_header.h
187 public/pw_foo/baz.h
188
189For headers that must be exposed due to C++ limitations (i.e. are included from
190the public interface, but are not intended for use), place the headers in a
191``internal`` subfolder under the public headers directory; as
David Rogers582c1902020-01-16 18:17:09 -0800192``{pw_module_dir}/public/<module>/internal/*.h``. For example:
Keir Mierlec34f71f2019-12-06 12:44:47 -0800193
194.. code-block::
195
196 pw_foo/...
197 public/pw_foo/internal/secret.h
198 public/pw_foo/internal/business.h
199
200.. note::
201
202 These headers must not override headers from other modules. For
203 that, there is the ``public_overrides/`` directory.
204
David Rogers582c1902020-01-16 18:17:09 -0800205Public override headers
206^^^^^^^^^^^^^^^^^^^^^^^
207Located ``{pw_module_dir}/public_overrides/<module>``. In general, the Pigweed
208philosophy is to avoid having "things hiding under rocks", and having header
209files with the same name that can override each other is considered a rock
210where surprising things can hide. Additionally, a design goal of the Pigweed
211module structure is to make it so there is ideally exactly one obvious place
212to find a header based on an ``#include``.
Keir Mierlec34f71f2019-12-06 12:44:47 -0800213
214However, in some cases header overrides are necessary to enable flexibly
215combining modules. To make this as explicit as possible, headers which override
216other headers must go in
217
David Rogers582c1902020-01-16 18:17:09 -0800218``{pw_module_dir}/public_overrides/...```
Keir Mierlec34f71f2019-12-06 12:44:47 -0800219
220For example, the ``pw_unit_test`` module provides a header override for
221``gtest/gtest.h``. The structure of the module is (omitting some files):
222
223.. code-block::
224
225 pw_unit_test/...
226
227 public_overrides/gtest
228 public_overrides/gtest/gtest.h
229
230 public/pw_unit_test
231 public/pw_unit_test/framework.h
232 public/pw_unit_test/simple_printing_event_handler.h
233 public/pw_unit_test/event_handler.h
234
235Note that the overrides are in a separate directory ``public_overrides``.
236
David Rogers582c1902020-01-16 18:17:09 -0800237C++ implementation files
238^^^^^^^^^^^^^^^^^^^^^^^^
239Located ``{pw_module_dir}/``. C++ implementation files go at the top level of
240the module. Implementation files must always use "" style includes.
Keir Mierlec34f71f2019-12-06 12:44:47 -0800241
242Example:
243
244.. code-block::
245
246 pw_unit_test/...
247 main.cc
248 framework.cc
249 test.gni
250 BUILD.gn
251 README.md
252
253Documentation
254~~~~~~~~~~~~~
255Documentation should go in the root module folder, typically in the
256``docs.rst`` file. There must be a docgen entry for the documentation in the
257``BUILD.gn`` file with the target name ``docs``; so the full target for the
258docs would be ``<module>:docs``.
259
260.. code-block::
261
262 pw_example_module/...
263
264 docs.rst
265
266For modules with more involved documentation, create a separate directory
267called ``docs/`` under the module root, and put the ``.rst`` files and other
268related files (like images and diagrams) there.
269
270.. code-block::
271
272 pw_example_module/...
273
274 docs/docs.rst
275 docs/bar.rst
276 docs/foo.rst
277 docs/image/screenshot.png
278 docs/image/diagram.svg
279
280Command: ``pw module-check``
281----------------------------
282
283The ``pw module-check`` command exists to ensure that your module conforms to
284the Pigweed module norms.
285
286For example, at time of writing ``pw module-check pw_module`` is not passing
287its own lint:
288
289.. code-block:: none
290
291 $ pw module-check pw_module
292
293 ▒█████▄ █▓ ▄███▒ ▒█ ▒█ ░▓████▒ ░▓████▒ ▒▓████▄
294 ▒█░ █░ ░█▒ ██▒ ▀█▒ ▒█░ █ ▒█ ▒█ ▀ ▒█ ▀ ▒█ ▀█▌
295 ▒█▄▄▄█░ ░█▒ █▓░ ▄▄░ ▒█░ █ ▒█ ▒███ ▒███ ░█ █▌
296 ▒█▀ ░█░ ▓█ █▓ ░█░ █ ▒█ ▒█ ▄ ▒█ ▄ ░█ ▄█▌
297 ▒█ ░█░ ░▓███▀ ▒█▓▀▓█░ ░▓████▒ ░▓████▒ ▒▓████▀
298
299 20191205 17:05:19 INF Checking module: pw_module
300 20191205 17:05:19 ERR PWCK005: Missing ReST documentation; need at least e.g. "docs.rst"
301 20191205 17:05:19 ERR FAIL: Found errors when checking module pw_module
302
303