4.9 KiB
Compiling, debugging and testing efficiently
This document describes ways of compiling, debugging and testing efficiently for various use cases.
The intended audience are developers, who want to leverage newly added tricks to Monero via CMake
. The document will lower the entry point for these developers.
Before reading this document, please consult section "Build instructions" in the main README.md.
Some information from README.md will be repeated here, but the aim is to go beyond it.
Basic compilation
Monero can be compiled via the main Makefile
, using one of several targets listed there.
The targets are actually presets for CMake
calls with various options, plus make
commands for building or in some cases make test
for testing.
It is possible to extract these CMake
calls and modify them for your specific needs. For example, a minimal external cmake command to compile Monero, executed from within a newly created build directory could look like:
cmake -S "$DIR_SRC" -DCMAKE_BUILD_TYPE=Release && make
where the variable DIR_SRC
is expected to store the path to the Monero source code.
Use cases
Test Driven Development (TDD) - shared libraries for release builds
Building shared libraries spares a lot of disk space and linkage time. By default only the debug builds produce shared libraries. If you'd like to produce dynamic libraries for the release build for the same reasons as it's being done for the debug version, then you need to add the BUILD_SHARED_LIBS=ON
flag to the CMake
call, like the following:
cmake -S "$DIR_SRC" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON && make
A perfect use case for the above call is following the Test Driven Development (TDD) principles. In a nutshell, you'd first write a couple of tests, which describe the (new) requirements of the class/method that you're about to write or modify. The tests will typically compile for quite a long time, so ideally write them once. After you're done with the tests, the only thing left to do is to keep modifying the implementation for as long as the tests are failing. If the implementation is contained properly within a .cpp file, then the only time cost to be paid will be compiling the single source file and generating the implementation's shared library. The test itself will not have to be touched and will pick up the new version of the implementation (via the shared library) upon the next execution of the test.
Project generation for IDEs
CMake allows to generate project files for many IDEs. The list of supported project files can be obtained by writing in the console:
cmake -G
For instance, in order to generate Makefiles and project files for the Code::Blocks IDE, this part of the call would look like the following:
cmake -G "CodeBlocks - Unix Makefiles" (...)
The additional artifact of the above call is the monero.cbp
Code::Blocks project file in the build directory.
Debugging in Code::Blocks (CB)
First prepare the build directory for debugging using the following example command, assuming, that the path to the source dir is being held in the DIR_SRC variable, and using 2 cores:
cmake -S "$DIR_SRC" -G "CodeBlocks - Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON && make -j 2
After a successful build, open the monero.cbp
with CB. From the CB's menu bar select the target, that you want debug. Assuming these are unit tests:
Build -> Select target -> Select target -> unit_tests
In order to lower the turnaround times, we will run a specific portion of code of interest, without having to go through all the time costly initialization and execution of unrelated parts. For this we'll use GTest's capabilities of test filtering. From the build directory run the following command to learn all the registered tests:
tests/unit_tests/unit_tests --gtest_list_tests
For example, if you're only interested in logging, you'd find in the list the label logging.
and its subtests. To execute all the logging tests, you'd write in the console:
tests/unit_tests/unit_tests --gtest_filter="logging.*"
This parameter is what we need to transfer to CB, in order to reflect the same behaviour in the CB's debugger. From the main menu select:
Project -> Set program's arguments...
Then in the Program's arguments
textbox you'd write in this case:
--gtest_filter="logging.*"
Verify if the expected UTs are being properly executed with F9
or select:
Build -> Build and run
If everything looks fine, then after setting some breakpoints of your choice, the target is ready for debugging in CB via:
Debug -> Start/Continue
To be done (and merged):
Multihost parallel compilation
https://github.com/monero-project/monero/pull/7160
Faster core_tests with caching
https://github.com/monero-project/monero/pull/5821
Precompiled headers
https://github.com/monero-project/monero/pull/7216