This repository is a git submodule providing standard-ish support code for applications that use libcwd.
It provides the following features,
- defines all libcwd debug macros as empty (with the exception of LibcwDoutFatal) when not compiling with debug support.
- defines the extra helper macros:
- CWDEBUG_ONLY(...)
- COMMA_CWDEBUG_ONLY(...)
- DEBUG_ONLY(...)
- COMMA_DEBUG_ONLY(...)
- ASSERT(expr)
- and when compiled with debugging, the macros,
- NAMESPACE_DEBUG
- NAMESPACE_DEBUG_START
- NAMESPACE_DEBUG_END
- NAMESPACE_CHANNELS
- DEBUGCHANNELS
- NAMESPACE_DEBUG_CHANNELS_START
- NAMESPACE_DEBUG_CHANNELS_END
- DoutEntering
- Declares initialization functions for libcwd to be called from the top of main and the start of threads.
- Defines a global mutex to be used for std::cout (if you want output to std::cout not to interfer with debug output).
- Defines a class tracked::Tracked<&name> that can be used to track proper use of move/copy constructors and assignment operators.
- Provides a function to turn an address into a string with filename and line number.
- Provides code for benchmarking (declared in cwds/benchmark.h).
- Support for plotting graphs (using gnuplot).
- Defines exception safe struct for indenting debug output (Indent) and making temporarily making allocation invisible (InvisibleAllocations).
- Provides a function to print simple variables from a signal handler (cwds/signal_safe_printf.h).
- Defines a streambuf class that can be used to turn background color of all debug output green.
- Defines ostream serializers for many types to pretty-print them easily to a debug stream, like
- timeval
- boost::shared_ptr<T>
- boost::weak_ptr<T>
- std::pair<T1, T2>
- std::map<T1, T2, T3>
To clone a project example-project that uses cwds simply run:
git clone --recursive <URL-to-project>/example-project.git cd example-project ./autogen.sh
The --recursive is optional because ./autogen.sh will fix it when you forgot it.
To add this submodule to a project, that project should already be set up to use cwm4.
Then simply execute the following in the root of that project:
git submodule add https://github.com/CarloWood/cwds.git
This should clone cwds into the subdirectory cwds, or if you already cloned it there, it should add it.
Typically you should use gitache to install libcwd itself. In that case, set the GITACHE_ROOT environment variable as described in the documentation of gitache and add the following to the root CMakeLists.txt file of your project:
... [cmake_minimum_required, project and CMAKE_CXX_STANDARD] # Begin of gitache configuration. set(GITACHE_PACKAGES libcwd_r) include(cwm4/cmake/StableGitache) # End of gitache configuration. # This project uses aicxx modules. include(cwm4/cmake/AICxxProject) include(AICxxSubmodules) ...
And add ${AICXX_OBJECTS_LIST} to every target that uses cwds (aka, debugging). For example,
add_executable(sum_first_n_primes sum_first_n_primes.cxx) target_link_libraries(sum_first_n_primes PRIVATE ${AICXX_OBJECTS_LIST})
To use gitache for libcwd you also have to create the file <project_root>/
cmake/gitache-configs/libcwd_r.cmake
with normally the following content (see gitache for more information):
gitache_config( GIT_REPOSITORY "https://github.com/CarloWood/libcwd.git" GIT_TAG "master" CMAKE_ARGS "-DEnableLibcwdAlloc:BOOL=OFF -DEnableLibcwdLocation:BOOL=ON" )
As described in the documentation of libcwd, each (C++) source file must begin with #include "sys.h" and use #include "debug.h" when containing any debug code. This submodule provides those header files, but there is some room for tuning the namespace used for the debugging specific code of the application.
The following namespaces are relevant:
namespace example { namespace debug { namespace channels { namespace dc {
Where namespace example is optional, in fact, anything inside namespace debug can be put anywhere, we're just using example::debug as the example right now.
Also the name of namespace channels can be changed, although that is only necessary in special cases when writing a library that wishes to reuse the name of an existing debug channel. You'll know when you need that, until then I suggest you'll just leave it at channels.
By default (which is ok for any application, but not for libraries) the debug namespace is just debug::, thus no namespace example. This is the case when directly including the debug.h provided by this submodule. Hence, a library should provide yet another debug.h file and make sure that is first in the include path. Other submodules, which don't know if such a debug.h is provided should therefore use the following order of include paths: first the top build directory, then the top source directory and last the cwds directory in the top source directory.
So that library projects (or applications) can put a debug.h in their top source directory that contains something like
#pragma once // These three defines are only necessary if you want the 'example' namespace. // The default is just 'debug'. #define NAMESPACE_DEBUG example::debug #define NAMESPACE_DEBUG_START namespace example { namespace debug { #define NAMESPACE_DEBUG_END } } #include "cwds/debug.h" #ifdef CWDEBUG NAMESPACE_DEBUG_CHANNELS_START extern channel_ct my_channel; extern channel_ct ... NAMESPACE_DEBUG_CHANNELS_END #endif
or if they don't, that then cwds/debug.h will be included directly. The top build directory include is needed to find any generated header files, most notably sys.h.
Debug channels that are only used in a single compilation unit can be defined by just adding
#include "sys.h" #include "debug.h" [...] #ifdef CWDEBUG NAMESPACE_DEBUG_CHANNELS_START channel_ct my_channel; NAMESPACE_DEBUG_CHANNELS_END #endif
of the respective source file, of course.
In order to initialize libcwd properly, the following has to be added to the top of main:
int main() { Debug(NAMESPACE_DEBUG::init());
The first three lines are actually something from ai-utils, just shown here to show the typical order.
Threads on the other hand need to begin with the following code:
Debug(NAMESPACE_DEBUG::init_thread());
Finally, run
./autogen.sh
to let cwm4 do its magic, and commit all the changes.
There is a tutorial video on youtube that shows how to set up a project with cwds and libcwd here.