Skip to content

Contributing

Stéphane Letz edited this page Dec 23, 2024 · 13 revisions

Contribution guidelines

This document sets out the methods and practices for contributing to the Faust project.

How to contribute

Please use the "Pull Request" mechanism for proposing contributions to the code base.

Brief overview of this process

Fork your own copy of Faust to your repository and create a dedicated branch from the faust:master-dev branch for your developments. Make your changes. You can commit to your branch as many times as you like. Validate your changes (see below).

Formatting the code

Be sure to use the make format command in the Faust root folder to properly format the new code.

Creating the pull request

When you're ready to provide your changes "upstream," you can open a pull request to the faust:master-dev branch. NB: You will want to make sure you're proposing a merge to master-dev.

Review and merge

We will then review your submission. If you are asked to make changes, you can push these changes to your original branch and the pull request will be automatically updated. Once the changes have gone through our review process, we will merge your changes into our repository. You may then delete your dedicated branch.

Keeping the compilation deterministic

Until version 2.71.1, the Faust compiler was non-deterministic, meaning that for the same DSP program, the generated C++ code (or other backends) could vary slightly from one execution to another, even though the behavior (i.e., the calculation of the sequence of samples produced during execution) remained unchanged. This lack of determinism was caused by the use of pointers in the internal tree structures (used for the compiler’s different ASTs), comparisons on the pointers themselves, as well as the use of these pointers in STL data structures like map or set, which rely on a comparison operator for the keys.

Thanks to this contribution, which introduces a plugin for the Clang compiler to instrument the code during compilation, it is now possible to detect all uses of comparisons on specific categories of pointers (explicitly described in the plugin) and display a corresponding trace.

The next step is to assign a serial number (using the serial method on Tree) to each pointer allocation and use this number to implement a custom comparison, which will then be systematically applied wherever necessary. The CTreeComparator comparator has to be used in map or set containers when they use a Tree pointer as the key. Look at this commit.

The make debug target can be used to check all uses of Tree and be sure the use of Tree pointers keeps the correct property. The following kind of lines may have to be used:

export LLVM_DIR=/opt/local/libexec/llvm-19/lib/cmake/llvm

export Clang_DIR=/opt/local/libexec/llvm-19/lib/cmake/clang

This technique ensures the determinism of the compiler!

Additionally, a set of intermediate text traces during compilation allows for the verification of a large number of properties in a stable and therefore useful manner, and these traces are used to validate each significant evolution in the compilation chain. In faust/tests/impulse-tests, look at the following targets:

'test-box' : test box creation intermediate step

'test-signal' : test signal creation intermediate step

'test-type' : test signal typing intermediate step

'test-fir' : test FIR intermediate step

'test-cpp' : test C++ generation step

Clone this wiki locally