If you are checking out the libsemigroups git repo, then the following steps
are required to build the documentation:
- Install doxygen (using homebrew or apt-get)
- Check out the doxygen-awesome-css/ submodule of
libsemigroupsusing:
git submodule update --init --recursive- Type
make doc
| Object | Convention |
| class | NamedLikeThis |
| struct | NamedLikeThis |
| function | named_like_this |
| enum class | namedlikethis |
| enum class member | named_like_this |
| stateful type alias | named_like_this_type |
| stateless type alias | LikeThis |
| iterator | iterator or const_iterator |
| global variable | NAMED_LIKE_THIS |
Try to ensure that any new functionality added to libsemigroups satisfies
the strong exception guarantee, and if not that this is documented.
Some more conventions:
If a function does not check its arguments (including
*thisfor member functions), then it must have the suffix_no_checksif there is any possibility that the function will fail. This indicates that anything may happen if the function is called on a non-valid object or for non-valid arguments.In the python bindings
libsemigroups_pybind11it should not be possible to construct or modify an object so that it is invalid. For example, it shouldn't be possible to create an invalidBipartitionor to modify a validBipartitionso that it is invalid. So, it is safe to call theBipartition::rank_no_checksmember function as if it was theBipartition::rankfunction. Hence in the python bindings we bind a functions calledBipartition.rankto the C++ functionBipartition::rank_no_checks.All class helper functions (i.e. those free functions taking a class as an argument, and using public member functions of that class) should be in a helper namespace with the same name as the class (but in lower case). I.e.
bipartition::one, orptransf::one. Exceptions are:- operators such as
operator*etc. This is because these are more or less difficult to use if they are in a nested namespace. - functions that are (or should be) implemented for all of the public facing
classes in
libsemigroups, such as, for exampleto_human_readable_repr
- operators such as
Functions that construct an object must be of one of three types; constructors,
makefunctions, ortofunctions:- A constructor should be used to construct an object without checking its arguments.
- A
makefunction should be a free function template in the libsemigroups namespace that is used to construct an object from non-libsemigroups objects such as containers, integers and strings. It should check its arguments. - A
tofunction should a free function template in the libsemigroups namespace that is used to convert from onelibsemigroupstype to another. A typical signature might look something liketo<ToddCoxeter>(Presentation<word_type> p). It should check its arguments.
The documentation for each function may contain the following section indicators in the following order:
\tparam\param\return\exceptionsor\throws\complexity\note\warning\sa
This can be checked by running
etc/check_doc_order.py.
To run lldb:
./configure --enable-debug && make test_all
libtool --mode=execute lldb test_alltest_all is the name of the check program produced by make check.
Similarly to run valgrind you have to do:
./configure --enable-debug --disable-hpcombi && make test_all
libtool --mode=execute valgrind --leak-check=full ./test_all [quick] 2>&1 | tee --append valgrind.txtAny new tests should be tagged with one of the following:
| Tag | Runtime |
| quick | < 200ms |
| standard | < 3s |
| extreme | > 3s |
They should be declared using
LIBSEMIGROUPS_TEST_CASE(classname, number, message, tags)"tags" should include "[FilePrefix]" where "FilePrefix" would be "cong-pair" in the file "tests/cong-pair.test.cc", if the file prefix is the same as "classname", then it should not be included. Tags are case insensitive.
A *bugfix release* is one of the form x.y.z -> x.y.z+1, and
a *non-bugfix release* is one of the form x.y.z -> x+1.y.z or
x.y+1.z.
The following tools may be useful for developers of libsemigroups. Their use
is explained in the following sections, and all of them cen be installed in a
conda/mamba environment by running
source etc/make-dev-environment.shThis script requires a conda-flavoured package manager. A good choice is
mamba, and instructions on how to install it can be found on the
mamba installation page.
The codebase of libsemigroups is formatted using using version 15 of
clang-format,
and adherence to this standard is checked as part of all pull requests.
To install this locally on a Debian-like system with root access, you may be able to run:
apt install clang-format-15In some cases, it may be desirable to disable automatic formatting; for example, if you want to use two lines to construct a vector that represents a 2x2 matrix, even though it would fit on one line. Automatic formatting can be disabled using the comment
// clang-format offand then, importantly, re-enabled using the comment
// clang-format onThis should be done sparingly and with good reason.
As well as checking formatting, the codebase of libsemigroups is linted
using cpplint as part of every pull
request. Instructions on how to install locally can be found on their
installation page.
Certain lines can be spared from the linter in the following way
void some_offending_line_of_code(); // NOLINT(category)
// NOLINTNEXTLINE(category)
class SomeOtherOffendingLineOfCode;
// NOLINTBEGIN(category)
auto some_offending_thing({
"that", "spans",
"several", "lines"
});
// NOLINTENDwhere category is the type of linter error to ignore. The names of these
categories can be found in the
source code,
but it is probably easier to try linting, and then quote the error that is spat
out.
As with clang-format, disabling the linter should be done sparingly and with
good reason.
As part of every pull request, the codebase of libsemigroups is checked for
spelling mistakes using
codespell. Instructions on how
to install this locally can be found on their installation page.
Sometimes, false positives may get thrown, especially when writing maths or
names. Therefore, codespell can be disabled using
// codespell:begin-ignoreand then re-enabled using
// codespell:end-ignoreIf the issue is more widespread than a few lines of code, then the offending
word(s) can be added to the ignore-words-list of the .codespellrc file.