openssl/doc/HOWTO/documenting-functions-and-macros.md
Michael Richardson c3637cafd3 doc: add HOWTO document about Documenting public Functions and Macros
Co-authored-by: Matthias St. Pierre <matthias.st.pierre@ncp-e.com>
Co-authored-by: Tomáš Mráz <tm@t8m.info>
Co-authored-by: Lin2Jing4 <35728132+Lin2Jing4@users.noreply.github.com>
Co-authored-by: Richard Levitte <levitte@openssl.org>

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17926)
2023-03-29 12:18:07 +02:00

5.7 KiB

Documenting public Functions and Macros

In the last few years, the OpenSSL project has strived to improve the quality and coverage of the API documentation. A while ago, this goal has been turned into an official documentation-policy. This policy is actively enforced by the make doc-nits target resp. check-docs GitHub action.

If you add a new public function or macro to a header file without documenting it, it will give you an error message like this:

include/openssl/bio.h: macro BIO_set_dgram_origin(3) undocumented
include/openssl/bio.h: macro BIO_get_dgram_origin(3) undocumented
include/openssl/bio.h: macro BIO_set_dgram_dest(3) undocumented
include/openssl/bio.h: macro BIO_get_dgram_dest(3) undocumented

and you'll want to document this.

So, create a new .pod file named doc/man3/FUNCTION.pod.

If you are asked to document several related functions in that file, you can create a single pod file in which you document them together. In this case, use the name of the first function as the file name, like for the above example:

doc/man3/BIO_set_dgram_origin.pod

If you do use an unrelated name (like BIO_dgram.pod) then you'll get a warning about that.

Next, you need to add your new file to the doc/build.info file. This command does it automatically for you:

$ make generate_doc_buildinfo

this will update doc/build.info. You should git add the result as generate_doc_buildinfo is not run on every build.

With these two changes, running make doc-nits locally should now agree with you that you have documented all your new defines, but it might then complain:

BIO_get_dgram_dest(3) is supposedly internal
(maybe missing from other.syms) but is documented as public

If it is the case that your interface is meant to be public, then you need to edit the file util/other.syms to add the names of your #define functions. This file gets sorted alphabetically prior to each major release, but new additions should be placed at the end of the file.

Example

For demonstration purposes, two new public symbols have been added by "implementing" a public function BIO_set_dgram_foo() and a public function-like macro BIO_set_dgram_bar():

diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c
index 82d382cf4e..30382f0abe 100644
--- a/crypto/bio/bss_dgram.c
+++ b/crypto/bio/bss_dgram.c
@@ -192,6 +192,13 @@ BIO *BIO_new_dgram(int fd, int close_flag)
     return ret;
 }

+
+int BIO_set_dgram_foo(BIO* b, int foo)
+{
+    return foo;
+}
+
+
 static int dgram_new(BIO *bi)
 {
     bio_dgram_data *data = OPENSSL_zalloc(sizeof(*data));
diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in
index c70185db34..4ddea2f96b 100644
--- a/include/openssl/bio.h.in
+++ b/include/openssl/bio.h.in
@@ -485,6 +485,9 @@ struct bio_dgram_sctp_prinfo {
 #define BIO_set_dgram_dest(b, addr)   BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, addr)
 #define BIO_get_dgram_dest(b, addr)   BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, addr)

+int BIO_set_dgram_foo(BIO* b, int foo);
+#define BIO_set_dgram_bar(b, bar) BIO_ctrl(b, BIO_CTRL_DGRAM_SET_ADDR, 0, bar)
+
 /*
  * name is cast to lose const, but might be better to route through a
  * function so we can do it safely

If you run make doc-nits, you might be surprised that it only complains about the undocumented macro, not the function:

$ make doc-nits

/usr/bin/perl ./util/find-doc-nits -c -n -l -e
include/openssl/bio.h: macro BIO_set_dgram_bar(3) undocumented
# 1 macros undocumented (count is approximate)
make: *** [Makefile:3833: doc-nits] Error 1

The explanation for this is that one important step is still missing, it needs to be done first: you need to run

$ make update

which triggers a scan of the public headers for new API functions.

All new functions will be added to either util/libcrypto.num or util/libssl.num. Those files store the information about the symbols which need to be exported from the shared library resp. DLL. Among other stuff, they contain the ordinal numbers for the module definition file of the Windows DLL, which is the reason for the .num extension.

After running make update, you can use git diff to check the outcome:

diff --git a/util/libcrypto.num b/util/libcrypto.num
index 394f454732..fc3c67313a 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5437,3 +5437,4 @@ BN_signed_bn2native                     ? 3_1_0   EXIST::FUNCTION:
 ASYNC_set_mem_functions                 ?  3_1_0   EXIST::FUNCTION:
 ASYNC_get_mem_functions                 ?  3_1_0   EXIST::FUNCTION:
 BIO_ADDR_dup                            ?  3_1_0   EXIST::FUNCTION:SOCK
+BIO_set_dgram_foo                       ?  3_1_0   EXIST::FUNCTION:

The changes need to be committed, ideally as a separate commit:

$ git commit -a -m "make update"

which has the advantage that it can easily be discarded when it becomes necessary to rerun make update.

Finally, we reached the point where make doc-nits complains about both symbols:

$ make doc-nits
/usr/bin/perl ./util/find-doc-nits -c -n -l -e
crypto: function BIO_set_dgram_foo(3) undocumented
# 1 libcrypto names are not documented
include/openssl/bio.h: macro BIO_set_dgram_bar(3) undocumented
# 1 macros undocumented (count is approximate)
make: *** [Makefile:3833: doc-nits] Error 1

Summary

The bottom line is that only the way how the public symbols are recorded is different between functions and macros, the rest of the documentation procedure is analogous.