blob: 594dc961a644a74691946a8a626c3f2dac6c787a [file] [log] [blame]
Alexei Frolovb3f7fda2020-03-18 14:59:20 -07001.. default-domain:: cpp
2
3.. highlight:: sh
4
5.. _chapter-module-guide:
6
7-------------------
8What's in a module?
9-------------------
10The Pigweed module structure is designed to keep as much code as possible for a
11particular slice of functionality in one place. That means including the code
12from multiple languages, as well as all the related documentation and tests.
13
14Additionally, the structure is designed to limit the number of places a file
15could go, so that when reading callsites it is obvious where a header is from.
16That is where the duplicated ``<module>`` occurrences in file paths comes from.
17
18Example module structure
19------------------------
20.. code-block:: python
21
22 pw_foo/...
23
24 docs.rst # If there is just 1 docs file, call it docs.rst
25 README.md # All modules must have a short README for gittiles
26
27 BUILD.gn # GN build required
28 BUILD # Bazel build required
29
30 # C++ public headers; the repeated module name is required
31 public/pw_foo/foo.h
32 public/pw_foo/baz.h
33
34 # Exposed public headers go under internal/
35 public/pw_foo/internal/bar.h
36 public/pw_foo/internal/qux.h
37
38 # Public override headers must go in 'public_overrides'
39 public_overrides/gtest/gtest.h
40 public_overrides/string.h
41
42 # Private headers go into <module>_*/...
43 pw_foo_internal/zap.h
44 pw_foo_private/zip.h
45 pw_foo_secret/alxx.h
46
47 # C++ implementations go in the root
48 foo_impl.cc
49 foo.cc
50 baz.cc
51 bar.cc
52 zap.cc
53 zip.cc
54 alxx.cc
55
56 # C++ tests also go in the root
57 foo_test.cc
58 bar_test.cc
59 zip_test.cc
60
61 # Python files go into 'py/<module>/...'
62 py/setup.py # All Python must be a Python module with setup.py
63 py/foo_test.py # Tests go in py/ but outside of the Python module
64 py/bar_test.py
65 py/pw_foo/__init__.py
66 py/pw_foo/__main__.py
67 py/pw_foo/bar.py
68
69 # Go files go into 'go/...'
70 go/...
71
72 # Examples go in examples/, mixing different languages
73 examples/demo.py
74 examples/demo.cc
75 examples/demo.go
76 examples/BUILD.gn
77 examples/BUILD
78
79 # Size reports go under size_report/
80 size_report/BUILD.gn
81 size_report/base.cc
82 size_report/use_case_a.cc
83 size_report/use_case_b.cc
84
85 # Protobuf definition files go into <module>_protos/...
86 pw_foo_protos/foo.proto
87 pw_foo_protos/internal/zap.proto
88
89 # Other directories are fine, but should be private.
90 data/...
91 graphics/...
92 collection_of_tests/...
93 code_relating_to_subfeature/...
94
95Module name
96~~~~~~~~~~~
97Pigweed upstream modules are always named with a prefix ``pw_`` to enforce
98namespacing. Projects using Pigweed that wish to make their own modules can use
99whatever name they like, but we suggest picking a short prefix to namespace
100your product (e.g. for an Internet of Toast project, perhaps the prefix could
101be ``it_``).
102
103C++ file and directory locations
104~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105
106C++ public headers
107^^^^^^^^^^^^^^^^^^
108Located ``{pw_module_dir}/public/<module>``. These are headers that must be
109exposed due to C++ limitations (i.e. are included from the public interface,
110but are not intended for public use).
111
112**Public headers** should take the form:
113
114``{pw_module_dir}/public/<module>/*.h``
115
116**Exposed private headers** should take the form:
117
118``{pw_module_dir}/public/<module>/internal/*.h``
119
120Examples:
121
122.. code-block::
123
124 pw_foo/...
125 public/pw_foo/foo.h
126 public/pw_foo/a_header.h
127 public/pw_foo/baz.h
128
129For headers that must be exposed due to C++ limitations (i.e. are included from
130the public interface, but are not intended for use), place the headers in a
131``internal`` subfolder under the public headers directory; as
132``{pw_module_dir}/public/<module>/internal/*.h``. For example:
133
134.. code-block::
135
136 pw_foo/...
137 public/pw_foo/internal/secret.h
138 public/pw_foo/internal/business.h
139
140.. note::
141
142 These headers must not override headers from other modules. For
143 that, there is the ``public_overrides/`` directory.
144
145Public override headers
146^^^^^^^^^^^^^^^^^^^^^^^
147Located ``{pw_module_dir}/public_overrides/<module>``. In general, the Pigweed
148philosophy is to avoid having "things hiding under rocks", and having header
149files with the same name that can override each other is considered a rock
150where surprising things can hide. Additionally, a design goal of the Pigweed
151module structure is to make it so there is ideally exactly one obvious place
152to find a header based on an ``#include``.
153
154However, in some cases header overrides are necessary to enable flexibly
155combining modules. To make this as explicit as possible, headers which override
156other headers must go in
157
158``{pw_module_dir}/public_overrides/...```
159
160For example, the ``pw_unit_test`` module provides a header override for
161``gtest/gtest.h``. The structure of the module is (omitting some files):
162
163.. code-block::
164
165 pw_unit_test/...
166
167 public_overrides/gtest
168 public_overrides/gtest/gtest.h
169
170 public/pw_unit_test
171 public/pw_unit_test/framework.h
172 public/pw_unit_test/simple_printing_event_handler.h
173 public/pw_unit_test/event_handler.h
174
175Note that the overrides are in a separate directory ``public_overrides``.
176
177C++ implementation files
178^^^^^^^^^^^^^^^^^^^^^^^^
179Located ``{pw_module_dir}/``. C++ implementation files go at the top level of
180the module. Implementation files must always use "" style includes.
181
182Example:
183
184.. code-block::
185
186 pw_unit_test/...
187 main.cc
188 framework.cc
189 test.gni
190 BUILD.gn
191 README.md
192
193Documentation
194~~~~~~~~~~~~~
195Documentation should go in the root module folder, typically in the
196``docs.rst`` file. There must be a docgen entry for the documentation in the
197``BUILD.gn`` file with the target name ``docs``; so the full target for the
198docs would be ``<module>:docs``.
199
200.. code-block::
201
202 pw_example_module/...
203
204 docs.rst
205
206For modules with more involved documentation, create a separate directory
207called ``docs/`` under the module root, and put the ``.rst`` files and other
208related files (like images and diagrams) there.
209
210.. code-block::
211
212 pw_example_module/...
213
214 docs/docs.rst
215 docs/bar.rst
216 docs/foo.rst
217 docs/image/screenshot.png
218 docs/image/diagram.svg
219
220Steps to create a new module for a Pigweed project
221--------------------------------------------------
222These instructions are for creating a new module for contribution to the
223Pigweed project. See below for an `example`__ of what the new module folder
224might look like.
225
226__ `Example module structure`_
227
2281. Create module folder following `Module name`_ guidelines
2292. Add `C++ public headers`_ files in
230 ``{pw_module_dir}/public/{pw_module_name}/``
2313. Add `C++ implementation files`_ files in ``{pw_module_dir}/``
2324. Add module documentation
233
234 - Add ``{pw_module_dir}/README.md`` that has a module summary
235 - Add ``{pw_module_dir}/docs.rst`` that contains the main module
236 documentation
237
2385. Add build support inside of new module
239
240 - Add GN with ``{pw_module_dir}/BUILD.gn``
241 - Add Bazel with ``{pw_module_dir}/BUILD``
242 - Add CMake with ``{pw_module_dir}/CMakeLists.txt``
243
2446. Add folder alias for new module variable in ``/modules.gni``
245
246 - dir_pw_new = "$dir_pigweed/pw_new"
247
2487. Add new module to main GN build
249
250 - in ``/BUILD.gn`` to ``group("pw_modules")`` using folder alias variable
251 - General modules and backends of facades go in ``pw_modules``, facades go
252 in ``pw_facades``
253
2548. Add test target for new module in ``/BUILD.gn`` to
255 ``pw_test_group("pw_module_tests")``
2569. Add new module to CMake build
257
258 - In ``/CMakeLists.txt`` add ``add_subdirectory(pw_new)``
259
26010. Add the new module to docs module
261
262 - Add in ``docs/BUILD.gn`` to ``pw_doc_gen("docs")``
263
26411. Run :ref:`chapter-module-module-check`
265
266 - ``$ pw module-check {pw_module_dir}``
267