Please read the GTIRB Code of Conduct.
-
Text files may not have trailing whitespace.
-
Text files must end with a trailing newline.
-
All tests should be able to run and pass. This can be checked by running
make check
on your build directory after runningcmake
. -
All CMake files shall be formatted with cmake-format. A
.cmake-format
file is provided in the root directory for the project, and a pass through this tool is included as part of ourpre-commit
configuration (see below for details). -
The GTIRB version saved in
version.txt
in the base of the GTIRB repository is like semantic versioning but offset by one (because we're still early enough as a project to have many backwards in-compatible changes and we don't want to be at version 50.x in 5 years). So with a version ofX.Y.Z
the firstX
is incremented very rarely and only for major updates, the secondY
is incremented for every backwards incompatible change, and the thirdZ
is incremented when new features are added. -
We also track a Protobuf version number in
version.txt
(asVERSION_PROTOBUF
). This number is incremented whenever our protobuf files (underproto/
in the GTIRB repository) are changed in any way that affects the serialized protobuf -- even if the change could potentially be backwards compatible because of the way protobuf gracefully handles unknown new fields. -
We ask that all contributors complete our Contributor License Agreement (CLA), which can be found at GrammaTech-CLA-GTIRB.pdf, and email the completed form to
CLA@GrammaTech.com
. Under this agreement contributors retain the copyright to their work but grants GrammaTech unlimited license to the work.
In general, code must follow a unified format. To make compliance with
this format easier, we recommend the use of
pre-commit
with the provided
configuration file, .pre-commit-config.yaml
, to manage formatting.
To use pre-commit
:
- If
pre-commit
is not already installed on your system, install it now withpip
.pip3 install pre-commit
- If
clang-format
is not already installed on your system, install it now. - Install the formatters as a pre-commit hook. In the gtirb root directory:
If you prefer to run
pre-commit install
pre-commit
manually instead, run this before all commits:pre-commit run
-
All code shall be formatted with clang-format. A
.clang-format
is provided in the root directory for the project, and a pass through this tool is included as part of ourpre-commit
configuration. -
Code should generally follow the C++ Core Guidelines recommendations.
-
Code should generally allow for thread safety.
- No static variables.
- No globals
- Free functions should not maintain state.
- Use caution when using iterators to guard against invalidation.
-
Maintain const-correctness.
-
Use UpperCamelCase for type names.
-
Use UpperCamelCase for enum members.
-
Use UpperCamelCase for variable and class members.
-
Use lowerCamelCase for function and method names.
-
Avoid
using namespace std
-
Use
auto
when the deduced type is explicitly spelled out in the initialization or if the deduced type is an abstract type alias. Always explicitly specify type qualifiers, pointers, and references. E.g.,const auto *Ptr = dynamic_cast<const Foo *>(SomePtr); auto Val = static_cast<unsigned>(SomeValue); for (auto Iter = SomeContainer.begin(), End = SomeContainer.end(); Iter != End; ++Iter) {}
-
Use
auto
to make code more readable, but preferauto &
orauto *
to avoid unexpected copies. -
#include
as little as possible to reduce compile times. Use forward declarations of classes when possible to avoid including their definitions. -
Do not introduce variables to the code that would require a client to dllimport them. Export.hpp does not setup dllimport declarations for clients. For example, do not add static function-local variables in inline functions in header files.
Some tips to keep in mind to not needlessly regress build performance when working with GTIRB:
- Do not include a protobuf header from within a .hpp file unless you need the enum values from protobuf. A forward declare + include in the .cpp file is sufficient and cuts out 100s of transitive headers to parse.
- CFG.hpp and ByteInterval.hpp are the most expensive headers you can possibly include. Avoid including these whenever humanly possible (getting rid of 2 includes of CFG.hpp cut out ~2500 transitive header includes).
- Boost headers are extremely heavy to parse, try to push as much of their inclusions down into a .cpp file as possible. For instance, including boost's endian header requires ~200 transitive headers by itself. Things like the boost containers are considerably more expensive. This is what contributes to ByteInterval and CFG being so expensive to include. Be wary when adding includes to boost headers or adding new boost dependencies.
- Do not blindly trust the output from tools like include what you use; they sometimes do silly things like include a header file when a forward declare is sufficient. When adding an include to a .hpp file, try hard to avoid adding the include.
- All code you care about should be tested.
- Any code you don't care about should be removed.
- C++ code should be tested on Linux using GCC and Clang, and on Windows using Visual Studio.
- Code testing is done via Google Test.
- Test names are prefixed with the type of test they are (
Unit_
,System_
,Integration_
). - No unit test should take more than 0.5 seconds.
Most of the build issues on Windows arise from having to define the location of many dependencies.
- When using a batch file to call
cmake
, make sure to quote all paths and escape all backshlases in paths. i.e.-DCMAKE_PREFIX_PATH="c:\\Program Files\\capstone"
and do not leave a trailing backslash on paths. - Use
-Dprotobuf_DEBUG=ON
for protobuf related build issues in general. '../src/gtirb/proto/protobuf::protoc', needed by 'src/gtirb/proto/AuxData.pb.h', missing and no known rule to make it
- due to missing or unusable protoc protobuf compiler. You may need to define
-Dprotobuf_EXECUTABLE="<path to protoc.exe>"
, or check that the CMAKE_PREFIX_PATH has a path to the protobuf dir (resulting fromninja install
after building).
- due to missing or unusable protoc protobuf compiler. You may need to define
CMAKE_PREFIX_PATH
is not additive. If you set it again, it will silently overwrite prior settings. Add to the one definition, separtaing with semi-colons.
-
Code must be PEP8 compliant. To check for PEP8 compliance, flake8 is recommended, and included as part of our
pre-commit
configuration. -
All code must be formatted with Black (set to line lengths of 79, for PEP8 compliance). A pass through this tool is included as part of our
pre-commit
configuration.- Please note that
black
only works on Python version 3.6 and newer. This is newer than what is available on some OSes by default (for example, Ubuntu 16), so you may have to install Python 3.6 or newer to runblack
. If installing Python 3.6+ on your system is not possible, there exists an online interface to Black you can manually enter files into.
- Please note that
-
The Python API should be made to run on all version of Python 3.
-
Use
UpperCamelCase
for type names,UPPER_CASE
for constant names, andsnake_case
for other identifier names.
- All code you care about should be tested.
- Any code you don't care about should be removed.
- Code testing is done via the built-in
unittest
framework. - No unit test should take more than 0.5 seconds.
The GTIRB documentation consists of complete documentation for all components of the GTIRB API, along with examples and other usage information.
At minimum, you will need CMake and Doxygen. To build the documentation:
-
Create and change to a temporary build directory. We will refer to this directory as
build
.> mkdir build > cd build
-
Build the documentation.
build> cmake <PATH_TO_GTIRB> [<api_options>] build> cmake --build . --target doc
-
Open the documentation home page
build/doc/html/index.html
in your browser.
The <api_options>
are as follows
-
-DGTIRB_CXX_API=OFF
: do not generate C++ API documentation.If this option is not specified,
cmake
will attempt to generate C++ API documentation, failing (along with the documentation build as a whole) if Doxygen is not available. -
-DGTIRB_CL_API=OFF
: do not generate Common Lisp API documentation.If this option is not specified,
cmake
will attempt to generate Common Lisp API documentation if and only if it can locate a SBCL/Quicklisp installation, failing if simpler-documentation-template (SDT) is not available. -
-DGTIRB_PY_API=OFF
: do not generate Python API documentation.If this option is not specified,
cmake
will attempt to generate Python API documentation if and only if it can locate a Python installation, failing if Sphinx, sphinx-autodoc-typehints, or the Python API dependencies are not available.
To add a new markdown document to the documentation:
-
Create the new document as a child of
/doc
.- File names start with
gtirb
. - File extension is
.md
. - Use github markdown syntax.
- Wrap your markdown documents at 80 columns.
- File names start with
-
Edit
/doc/general/Doxyfile.in
to add the basename of your new markdown document to theINPUT
rule setting. -
Edit
/doc/general/CMakeLists.txt
to add your new markdown document toMDFILES_IN
. Ordering is not important. -
Integrate your new markdown document into the documentation, either by linking to it from an existing page or by updating
/doc/general/DoxygenLayout.xml
to add an entry to the More Information tab. -
Build the documentation and check that your new page is present and rendered correctly.
- If it is not rendered correctly, you may need to add a new
preprocessing step to
doc/general/preprocmd.py
to rewrite the corresponding github-style markdown into something Doxygen can handle correctly.
- If it is not rendered correctly, you may need to add a new
preprocessing step to
- File names start with
gtirb
. - The color palette is
black
,lightblue
,cornflowerblue
, andcoral
. - Render
.dot
files to the same file name with a.png
extension.- Example:
dot -Tpng gtirbScope.dot > gtirbScope.png
- Example:
- Use the
arial
font.
For the Python API, Sphinx and related plugins are required. To install these via pip, run:
pip3 install sphinx sphinx-autodoc-typehints
You will also need all the dependencies of the GTIRB Python API itself. If you haven't already installed the Python API (and don't want to do so now) you can install just its dependencies as follows.
cd <PATH_TO_GTIRB>/build/python
python3 setup.py egg_info
pip3 install -r gtirb.egg-info/requires.txt
For the Common Lisp API, simpler-documentation-template (SDT)
is required. This package should automatically be downloaded via the build process;
see cl/README.md
for details on how to prepare the Common Lisp API.