blob: 89ec692a962d3972b0274dfad7d40ce90d6f0647 [file] [log] [blame]
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -07001.. _docs-module-structure:
Alexei Frolovb3f7fda2020-03-18 14:59:20 -07002
Keir Mierle086ef1c2020-03-19 02:03:51 -07003----------------
4Module Structure
5----------------
Alexei Frolovb3f7fda2020-03-18 14:59:20 -07006The Pigweed module structure is designed to keep as much code as possible for a
7particular slice of functionality in one place. That means including the code
8from multiple languages, as well as all the related documentation and tests.
9
10Additionally, the structure is designed to limit the number of places a file
11could go, so that when reading callsites it is obvious where a header is from.
12That is where the duplicated ``<module>`` occurrences in file paths comes from.
13
14Example module structure
15------------------------
16.. code-block:: python
17
18 pw_foo/...
19
20 docs.rst # If there is just 1 docs file, call it docs.rst
21 README.md # All modules must have a short README for gittiles
22
23 BUILD.gn # GN build required
24 BUILD # Bazel build required
25
26 # C++ public headers; the repeated module name is required
27 public/pw_foo/foo.h
28 public/pw_foo/baz.h
29
30 # Exposed public headers go under internal/
31 public/pw_foo/internal/bar.h
32 public/pw_foo/internal/qux.h
33
34 # Public override headers must go in 'public_overrides'
35 public_overrides/gtest/gtest.h
36 public_overrides/string.h
37
38 # Private headers go into <module>_*/...
39 pw_foo_internal/zap.h
40 pw_foo_private/zip.h
41 pw_foo_secret/alxx.h
42
43 # C++ implementations go in the root
44 foo_impl.cc
45 foo.cc
46 baz.cc
47 bar.cc
48 zap.cc
49 zip.cc
50 alxx.cc
51
52 # C++ tests also go in the root
53 foo_test.cc
54 bar_test.cc
55 zip_test.cc
56
57 # Python files go into 'py/<module>/...'
58 py/setup.py # All Python must be a Python module with setup.py
59 py/foo_test.py # Tests go in py/ but outside of the Python module
60 py/bar_test.py
61 py/pw_foo/__init__.py
62 py/pw_foo/__main__.py
63 py/pw_foo/bar.py
64
65 # Go files go into 'go/...'
66 go/...
67
68 # Examples go in examples/, mixing different languages
69 examples/demo.py
70 examples/demo.cc
71 examples/demo.go
72 examples/BUILD.gn
73 examples/BUILD
74
75 # Size reports go under size_report/
76 size_report/BUILD.gn
77 size_report/base.cc
78 size_report/use_case_a.cc
79 size_report/use_case_b.cc
80
81 # Protobuf definition files go into <module>_protos/...
82 pw_foo_protos/foo.proto
83 pw_foo_protos/internal/zap.proto
84
85 # Other directories are fine, but should be private.
86 data/...
87 graphics/...
88 collection_of_tests/...
89 code_relating_to_subfeature/...
90
91Module name
Ewout van Bekkume072fab2020-07-17 16:34:00 -070092-----------
Alexei Frolovb3f7fda2020-03-18 14:59:20 -070093Pigweed upstream modules are always named with a prefix ``pw_`` to enforce
94namespacing. Projects using Pigweed that wish to make their own modules can use
95whatever name they like, but we suggest picking a short prefix to namespace
96your product (e.g. for an Internet of Toast project, perhaps the prefix could
97be ``it_``).
98
Keir Mierle16f86f42020-08-09 01:01:20 -070099C++ module structure
100--------------------
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700101
102C++ public headers
Ewout van Bekkume072fab2020-07-17 16:34:00 -0700103~~~~~~~~~~~~~~~~~~
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700104Located ``{pw_module_dir}/public/<module>``. These are headers that must be
105exposed due to C++ limitations (i.e. are included from the public interface,
106but are not intended for public use).
107
108**Public headers** should take the form:
109
110``{pw_module_dir}/public/<module>/*.h``
111
112**Exposed private headers** should take the form:
113
114``{pw_module_dir}/public/<module>/internal/*.h``
115
116Examples:
117
118.. code-block::
119
120 pw_foo/...
121 public/pw_foo/foo.h
122 public/pw_foo/a_header.h
123 public/pw_foo/baz.h
124
125For headers that must be exposed due to C++ limitations (i.e. are included from
126the public interface, but are not intended for use), place the headers in a
127``internal`` subfolder under the public headers directory; as
128``{pw_module_dir}/public/<module>/internal/*.h``. For example:
129
130.. code-block::
131
132 pw_foo/...
133 public/pw_foo/internal/secret.h
134 public/pw_foo/internal/business.h
135
136.. note::
137
138 These headers must not override headers from other modules. For
139 that, there is the ``public_overrides/`` directory.
140
Keir Mierle16f86f42020-08-09 01:01:20 -0700141C++ public override headers
142~~~~~~~~~~~~~~~~~~~~~~~~~~~
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700143Located ``{pw_module_dir}/public_overrides/<module>``. In general, the Pigweed
144philosophy is to avoid having "things hiding under rocks", and having header
145files with the same name that can override each other is considered a rock
146where surprising things can hide. Additionally, a design goal of the Pigweed
147module structure is to make it so there is ideally exactly one obvious place
148to find a header based on an ``#include``.
149
150However, in some cases header overrides are necessary to enable flexibly
151combining modules. To make this as explicit as possible, headers which override
152other headers must go in
153
154``{pw_module_dir}/public_overrides/...```
155
156For example, the ``pw_unit_test`` module provides a header override for
157``gtest/gtest.h``. The structure of the module is (omitting some files):
158
159.. code-block::
160
161 pw_unit_test/...
162
163 public_overrides/gtest
164 public_overrides/gtest/gtest.h
165
166 public/pw_unit_test
167 public/pw_unit_test/framework.h
168 public/pw_unit_test/simple_printing_event_handler.h
169 public/pw_unit_test/event_handler.h
170
171Note that the overrides are in a separate directory ``public_overrides``.
172
173C++ implementation files
Ewout van Bekkume072fab2020-07-17 16:34:00 -0700174~~~~~~~~~~~~~~~~~~~~~~~~
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700175Located ``{pw_module_dir}/``. C++ implementation files go at the top level of
176the module. Implementation files must always use "" style includes.
177
178Example:
179
180.. code-block::
181
182 pw_unit_test/...
183 main.cc
184 framework.cc
185 test.gni
186 BUILD.gn
187 README.md
188
189Documentation
Keir Mierle16f86f42020-08-09 01:01:20 -0700190-------------
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700191Documentation should go in the root module folder, typically in the
192``docs.rst`` file. There must be a docgen entry for the documentation in the
193``BUILD.gn`` file with the target name ``docs``; so the full target for the
194docs would be ``<module>:docs``.
195
196.. code-block::
197
198 pw_example_module/...
199
200 docs.rst
201
202For modules with more involved documentation, create a separate directory
203called ``docs/`` under the module root, and put the ``.rst`` files and other
204related files (like images and diagrams) there.
205
206.. code-block::
207
208 pw_example_module/...
209
210 docs/docs.rst
211 docs/bar.rst
212 docs/foo.rst
213 docs/image/screenshot.png
214 docs/image/diagram.svg
215
Keir Mierle16f86f42020-08-09 01:01:20 -0700216Creating a new Pigweed module
217-----------------------------
218To create a new Pigweed module, follow the below steps.
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700219
Keir Mierle16f86f42020-08-09 01:01:20 -0700220.. tip::
221
222 Connect with the Pigweed community (by `mailing the Pigweed list
223 <https://groups.google.com/forum/#!forum/pigweed>`_ or `raising your idea
224 in the Pigweed chat <https://discord.gg/M9NSeTA>`_) to discuss your module
225 idea before getting too far into the implementation. This can prevent
226 accidentally duplicating work, or avoiding writing code that won't get
227 accepted.
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700228
2291. Create module folder following `Module name`_ guidelines
2302. Add `C++ public headers`_ files in
231 ``{pw_module_dir}/public/{pw_module_name}/``
2323. Add `C++ implementation files`_ files in ``{pw_module_dir}/``
2334. Add module documentation
234
235 - Add ``{pw_module_dir}/README.md`` that has a module summary
236 - Add ``{pw_module_dir}/docs.rst`` that contains the main module
237 documentation
238
2395. Add build support inside of new module
240
241 - Add GN with ``{pw_module_dir}/BUILD.gn``
242 - Add Bazel with ``{pw_module_dir}/BUILD``
243 - Add CMake with ``{pw_module_dir}/CMakeLists.txt``
244
2456. Add folder alias for new module variable in ``/modules.gni``
246
247 - dir_pw_new = "$dir_pigweed/pw_new"
248
2497. Add new module to main GN build
250
251 - in ``/BUILD.gn`` to ``group("pw_modules")`` using folder alias variable
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700252
2538. Add test target for new module in ``/BUILD.gn`` to
254 ``pw_test_group("pw_module_tests")``
2559. Add new module to CMake build
256
257 - In ``/CMakeLists.txt`` add ``add_subdirectory(pw_new)``
258
25910. Add the new module to docs module
260
261 - Add in ``docs/BUILD.gn`` to ``pw_doc_gen("docs")``
262
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -070026311. Run :ref:`module-pw_module-module-check`
Alexei Frolovb3f7fda2020-03-18 14:59:20 -0700264
265 - ``$ pw module-check {pw_module_dir}``
266
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -070026712. Contribute your module to upstream Pigweed (optional but encouraged!)