1Documenting public Functions and Macros
2=======================================
3
4In the last few years, the OpenSSL project has strived to improve the quality
5and coverage of the API documentation. A while ago, this goal has been
6turned into an official [documentation-policy]. This policy is actively
7enforced by the `make doc-nits` target resp. `check-docs` GitHub action.
8
9[documentation-policy]: https://www.openssl.org/policies/technical/documentation-policy.html
10
11If you add a new public function or macro to a header file without documenting
12it, it will give you an error message like this:
13
14```text
15include/openssl/bio.h: macro BIO_set_dgram_origin(3) undocumented
16include/openssl/bio.h: macro BIO_get_dgram_origin(3) undocumented
17include/openssl/bio.h: macro BIO_set_dgram_dest(3) undocumented
18include/openssl/bio.h: macro BIO_get_dgram_dest(3) undocumented
19```
20
21and you'll want to document this.
22
23So, create a new `.pod` file named `doc/man3/FUNCTION.pod`.
24
25If you are asked to document several related functions in that file,
26you can create a single pod file in which you document them together.
27In this case, use the name of the first function as the file name,
28like for the above example:
29
30```text
31doc/man3/BIO_set_dgram_origin.pod
32```
33
34If you do use an unrelated name (like `BIO_dgram.pod`) then you'll get
35a warning about that.
36
37Next, you need to add your new file to the `doc/build.info` file.
38This command does it automatically for you:
39
40```console
41$ make generate_doc_buildinfo
42```
43
44this will update `doc/build.info`.
45You should git add the result as `generate_doc_buildinfo` is not run on every build.
46
47With these two changes, running `make doc-nits` locally should
48now agree with you that you have documented all your new defines,
49but it might then complain:
50
51```text
52BIO_get_dgram_dest(3) is supposedly internal
53(maybe missing from other.syms) but is documented as public
54```
55
56If it is the case that your interface is meant to be public, then you need
57to edit the file `util/other.syms` to add the names of your `#define`
58functions.
59This file gets sorted alphabetically prior to each major release,
60but new additions should be placed at the end of the file.
61
62Example
63-------
64
65For demonstration purposes, two new public symbols have been added
66by "implementing" a public function `BIO_set_dgram_foo()`
67and a public function-like macro `BIO_set_dgram_bar()`:
68
69```diff
70diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c
71index 82d382cf4e..30382f0abe 100644
72--- a/crypto/bio/bss_dgram.c
73+++ b/crypto/bio/bss_dgram.c
74@@ -192,6 +192,13 @@ BIO *BIO_new_dgram(int fd, int close_flag)
75     return ret;
76 }
77
78+
79+int BIO_set_dgram_foo(BIO* b, int foo)
80+{
81+    return foo;
82+}
83+
84+
85 static int dgram_new(BIO *bi)
86 {
87     bio_dgram_data *data = OPENSSL_zalloc(sizeof(*data));
88diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in
89index c70185db34..4ddea2f96b 100644
90--- a/include/openssl/bio.h.in
91+++ b/include/openssl/bio.h.in
92@@ -485,6 +485,9 @@ struct bio_dgram_sctp_prinfo {
93 #define BIO_set_dgram_dest(b, addr)   BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, addr)
94 #define BIO_get_dgram_dest(b, addr)   BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, addr)
95
96+int BIO_set_dgram_foo(BIO* b, int foo);
97+#define BIO_set_dgram_bar(b, bar) BIO_ctrl(b, BIO_CTRL_DGRAM_SET_ADDR, 0, bar)
98+
99 /*
100  * name is cast to lose const, but might be better to route through a
101  * function so we can do it safely
102```
103
104If you run `make doc-nits`, you might be surprised that it only
105complains about the undocumented macro, not the function:
106
107```console
108$ make doc-nits
109
110/usr/bin/perl ./util/find-doc-nits -c -n -l -e
111include/openssl/bio.h: macro BIO_set_dgram_bar(3) undocumented
112# 1 macros undocumented (count is approximate)
113make: *** [Makefile:3833: doc-nits] Error 1
114```
115
116The explanation for this is that one important step is still missing,
117it needs to be done first: you need to run
118
119```console
120$ make update
121```
122
123which triggers a scan of the public headers for new API functions.
124
125All new functions will be added to either `util/libcrypto.num`
126or `util/libssl.num`.
127Those files store the information about the symbols which need
128to be exported from the shared library resp. DLL.
129Among other stuff, they contain the ordinal numbers for the
130[module definition file] of the Windows DLL, which is the
131reason for the `.num` extension.
132
133[module definition file]: https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files
134
135After running `make update`, you can use `git diff` to check the outcome:
136
137```diff
138diff --git a/util/libcrypto.num b/util/libcrypto.num
139index 394f454732..fc3c67313a 100644
140--- a/util/libcrypto.num
141+++ b/util/libcrypto.num
142@@ -5437,3 +5437,4 @@ BN_signed_bn2native                     ? 3_1_0   EXIST::FUNCTION:
143 ASYNC_set_mem_functions                 ?  3_1_0   EXIST::FUNCTION:
144 ASYNC_get_mem_functions                 ?  3_1_0   EXIST::FUNCTION:
145 BIO_ADDR_dup                            ?  3_1_0   EXIST::FUNCTION:SOCK
146+BIO_set_dgram_foo                       ?  3_1_0   EXIST::FUNCTION:
147```
148
149The changes need to be committed, ideally as a separate commit:
150
151```console
152$ git commit -a -m "make update"
153```
154
155which has the advantage that it can easily be discarded when it
156becomes necessary to rerun `make update`.
157
158Finally, we reached the point where `make doc-nits` complains about
159both symbols:
160
161```console
162$ make doc-nits
163/usr/bin/perl ./util/find-doc-nits -c -n -l -e
164crypto: function BIO_set_dgram_foo(3) undocumented
165# 1 libcrypto names are not documented
166include/openssl/bio.h: macro BIO_set_dgram_bar(3) undocumented
167# 1 macros undocumented (count is approximate)
168make: *** [Makefile:3833: doc-nits] Error 1
169```
170
171Additionally, public symbols added should contain an entry in the HISTORY
172section of their documentation explaining the exact OpenSSL version in which
173they have appeared for the first time. The option -i for "find-doc-nits"
174can be utilized to check for this. A completely new documentation file
175should also contain a HISTORY section with wording along this line, e.g.
176"These functions have been added in OpenSSL version xxx.".
177
178Summary
179-------
180
181The bottom line is that only the way how the public symbols
182are recorded is different between functions and macros,
183the rest of the documentation procedure is analogous.
184