LDC contributor's guide
This page is a work-in-progress collection of tips for LDC contributors and development guidelines.
Contents
Continuous Integration
The LDC project uses two different CI systems: Travis CI, which does Ubuntu x86 + OS X builds, and AppVeyor, which does Windows builds. Both test LDC's branches and test pull requests too. Have a look at the build scripts in .travis.yml (Ubuntu Linux and OSX) and appveyor.yml (Windows).
Any efforts to get regular builds+tests on other platforms would be very much appreciated (especially non-x86 platforms, like ARM, PowerPC, ...).
To run the test suite locally, use ctest (e.g. ctest -j3 --output-on-failure) in the CMake root directory. To work on a specific test case, you might want to look into the -R and --verbose options to ctest.
Style guidelines
Generally, use your good taste and try to use a style similar to the surrounding code. Many parts of the LLVM Coding Standards are directly applicable to LDC as well.
Formatting, etc.
- Use clang-format with the LLVM style for formatting.
- Use include guards consistently, in the format LDC_<dir>_<filename>, e.g. LDC_GEN_DVALUE_H.
- Includes are placed at the top of the file, sorted lexicographically and grouped in the following order:
- Main include corresponding to the .cpp file, if any.
- DMD and other LDC includes.
- LLVM/libconfig includes.
- System includes.
APIs and idioms
- Avoid making changes to the front end sources (ddmd and dmd2) as much as reasonably possible. If modifications are necessary, be sure to enclose the deviations from the upstream source #if IN_LLVM blocks, and keep the original source code around for easier comparison. Add a comment referring to the relevant issue on our tracker, or the upstream DMD commit in case of a straight backport. This makes it much easier to resolve any merge conflicts when folding in new frontend releases.
- Use llvm_unreachable("message") instead of assert(0 && "message") (from llvm/Support/ErrorHandling.h). Not only might it lead to slightly better codegen, it also prevents »variable might be used uninitialized« and similar compiler warnings.
Test suite
Tests are very important to prevent regressions. Upon fixing a bug, a test case should be added so that the bug stays fixed and doesn't come back by accident. Upon adding a new feature, extensive tests should be added that test all functionalities of that feature.
- Bug fixing often starts from a minimal test case, which is a good basis for the eventual test case that is added to the testsuite.
- Instead of creating tests after feature development, consider adding tests during feature development: it is a good way to solidify the feature implementation because often you will discover tricky cases that you didn't think of and that may steer the direction of development. The "lit-based" testsuite makes it easy to run individual tests (run python runlit.py -v [testname] in your build/tests/ directory) so there is no excuse! ;-)
LDC is tested by the "lit-based" testsuite and DMD's dmd-testsuite with LDC specific modifications and additions. The dmd-testsuite is put in the tests/d2/ directory. The "lit-based" testsuite is found in the subdirectories of tests/, excluding the d2 subfolder. The "lit-based" testsuite is the most powerful of the two.
Merging a new DMD release
Eventually, we will want to write up a checklist of what to consider when merging a new frontend release. Right now, just a few points to consider:
- Check if there were any new command line options added to DMD. if so, also handle them in LDMD.
Updating the dmd-testsuite repository
The dmd-testsuite repository is derived from the upstream DMD repository by the update-dmd-testsuite.sh script in the ldc-scripts repository. Just run it without arguments, and it should update the repository with the latest commits/tags (given that you have Git installed and an SSH key configured for github.com). The changes should apply to the remote repository in a fast-forward fashion, never force a push.
After this is done, when merging a new DMD frontend release, just merge the v2.<xyz> tag into the ldc branch, manually resolving any merge conflicts as necessary (most changes should definitely be upstreamed).
Releasing a new version of LDC
There is a separate page describing the LDC release process: How to release LDC.