Skip to content

Commit 1c7b600

Browse files
authored
Production and Debug builds section added to FAQ (#453)
* Production and Debug builds section added to FAQ * Update to Production/Debug release section
1 parent 447f996 commit 1c7b600

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

user-guide/modules/ROOT/pages/faq.adoc

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This section contains answers to the common questions that new developers to Boo
2525
* <<Metaprogramming>>
2626
* <<Modular Boost>>
2727
* <<Other Languages>>
28+
* <<Production and Debug Builds>>
2829
* <<Releases>>
2930
* <<Safe C++>>
3031
* <<Smart Pointers>>
@@ -1020,6 +1021,170 @@ Future technological shifts, such as advances in quantum computing or entirely n
10201021
+
10211022
Python is often the top recommendation due to its versatility, simplicity, and wide application in growing fields like artificial intelligence (AI), machine learning (ML), rapid prototyping, and data science. And boost:python[] is there to help you integrate with the Boost libraries. Rust is another strong contender, especially if you are interested in systems programming and are looking for reliability and security. If you see the future as more cloud computing, then Go makes a strong case for itself. And let's not forget that so much computing is now web based, so JavaScript deserves a mention here too. All of these languages offer valuable resources that complement pass:[C++] and prepare you for an uncertain future.
10221023

1024+
== Production and Debug Builds
1025+
1026+
. *What is the value of using `BOOST_ASSERT` or `BOOST_STATIC_ASSERT` over the Standard Library assert macros?*
1027+
+
1028+
There are a few advantages of using the Boost asserts, available in `<boost/assert.hpp>`, including that `BOOST_ASSERT` is fully customizable using `BOOST_ENABLE_ASSERT_HANDLER`, which can be used to log extra data or stack traces, and there is better integration with boost:test[]. `BOOST_STATIC_ASSERT` is best utilized when using older pass:[C++] standards (pre-pass:[C++17]), or you are using deeply templated code. You might also prefer the Boost macros if you are engaging the features of other Boost libraries and are looking for consistent tooling. For a fuller discussion, refer to xref:boost-macros.adoc[].
1029+
1030+
. *For maximum performance, is it good practice to remove, or comment out, the `BOOST_ASSERT`s for the final production code, or do they simply not get compiled into anything so there is no performance cost for leaving them as is?*
1031+
+
1032+
By default, `BOOST_ASSERT` macros are completely removed from the compiled binary when `NDEBUG` is defined, just like the standard assert macro. If `NDEBUG` is not defined a `BOOST_ASSERT(x)` will expand, usually to an `assertion_failed()` if the assert condition fails. If NDEBUG is defined it expands to `((void)0)` so nothing is generated. Boost does provide the `BOOST_DISABLE_ASSERTS` macro, which has the same effect on Boost asserts as `NDEBUG` - but will leave other asserts alone.
1033+
1034+
. *What is usually considered to be best practices in handling assertions that fire with a production build?*
1035+
+
1036+
Instead of throwing an exception when an assert fails, it is often the best practice to log the failure. For example, here is a custom assert handler using the features of boost:log[] to record the event:
1037+
+
1038+
[source,cpp]
1039+
----
1040+
#include <boost/assert.hpp>
1041+
#include <boost/log/trivial.hpp>
1042+
#include <boost/log/utility/setup/file.hpp>
1043+
#include <boost/log/utility/setup/console.hpp>
1044+
#include <boost/log/utility/setup/common_attributes.hpp>
1045+
#include <boost/log/expressions.hpp>
1046+
#include <sstream>
1047+
#include <cstdlib>
1048+
1049+
namespace logging = boost::log;
1050+
1051+
// Configure Boost.Log (call once at startup)
1052+
void init_logging() {
1053+
logging::add_common_attributes();
1054+
1055+
// Console output
1056+
logging::add_console_log(
1057+
std::clog,
1058+
logging::keywords::format = "[%TimeStamp%] [%Severity%] %Message%"
1059+
);
1060+
1061+
// File output
1062+
logging::add_file_log(
1063+
logging::keywords::file_name = "assert_failures_%N.log",
1064+
logging::keywords::rotation_size = 10 * 1024 * 1024, // 10 MB
1065+
logging::keywords::format = "[%TimeStamp%] [%Severity%] %Message%"
1066+
);
1067+
}
1068+
1069+
// Custom handler for BOOST_ASSERT
1070+
namespace boost {
1071+
void assertion_failed(char const* expr, char const* function, char const* file, long line) {
1072+
std::ostringstream oss;
1073+
oss << "BOOST_ASSERT failed!\n"
1074+
<< " Expression: " << expr << "\n"
1075+
<< " Function: " << function << "\n"
1076+
<< " File: " << file << "\n"
1077+
<< " Line: " << line;
1078+
1079+
BOOST_LOG_TRIVIAL(error) << oss.str();
1080+
1081+
std::abort(); // Optional: comment out if soft fail is desired
1082+
}
1083+
}
1084+
1085+
----
1086+
+
1087+
An example use of this handler would be:
1088+
+
1089+
[source,cpp]
1090+
----
1091+
#include <boost/assert.hpp>
1092+
#include <iostream>
1093+
1094+
// Declare logging initializer
1095+
void init_logging();
1096+
1097+
void test_logic(int value) {
1098+
BOOST_ASSERT(value >= 0);
1099+
std::cout << "Value is: " << value << std::endl;
1100+
}
1101+
1102+
int main() {
1103+
init_logging();
1104+
1105+
std::cout << "Testing BOOST_ASSERT with value = 42..." << std::endl;
1106+
test_logic(42);
1107+
1108+
std::cout << "Testing BOOST_ASSERT with value = -1..." << std::endl;
1109+
test_logic(-1); // Logs to file and console, then aborts
1110+
1111+
return 0;
1112+
}
1113+
1114+
----
1115+
1116+
. *What should I be aware of when moving from a Debug to a Production release?*
1117+
+
1118+
Use this checklist to ensure your application correctly integrates Boost libraries across **Debug** and **Release** configurations.
1119+
+
1120+
- *Linking and Compatibility*
1121+
- [ ] Link with the correct Boost library variant (`-gd` for Debug, none for Release).
1122+
- [ ] Ensure runtime settings (Debug CRT or Release CRT) match Boost binaries.
1123+
- [ ] Avoid mixing Debug-built Boost libraries with Release-built applications.
1124+
- *Macro Definitions and Configuration*
1125+
- [ ] Define `BOOST_DEBUG` in Debug builds to enable extra runtime checks (if applicable).
1126+
- [ ] Define `BOOST_DISABLE_ASSERTS` in Release builds to remove `BOOST_ASSERT` checks.
1127+
- [ ] Optionally define `BOOST_ENABLE_ASSERT_HANDLER` to install custom assertion handlers.
1128+
- [ ] Review conditional macros like `BOOST_NO_EXCEPTIONS`, `BOOST_NO_RTTI`, etc.
1129+
- *Assertions and Diagnostics*
1130+
- [ ] Use `BOOST_ASSERT` for critical development-time checks.
1131+
- [ ] Consider diagnostic logging using `BOOST_LOG_TRIVIAL`.
1132+
- [ ] Ensure failing assertions are tested and logged in Debug builds.
1133+
- *Debugging and Tooling*
1134+
- [ ] Run AddressSanitizer, Valgrind, or Visual Leak Detector in Debug builds. Refer to xref:contributor-guide:ROOT:testing/sanitizers.adoc[Contributor Guide: Sanitizers].
1135+
- [ ] Confirm boost:pool[], boost:container[], and alloc-heavy libraries don't leak memory.
1136+
- [ ] Validate boost:thread[], boost:asio[], and boost:fiber[] components using thread sanitizers.
1137+
- *Performance Awareness*
1138+
- [ ] Avoid benchmarking with Debug builds — optimization is disabled.
1139+
- [ ] Use Release builds to test compile times for boost:mp11[], boost:spirit[], and any heavy use of templates.
1140+
- [ ] Validate any `BOOST_FORCEINLINE` or `BOOST_NOINLINE` effects in both builds.
1141+
- *Unit Testing*
1142+
- [ ] Run the full suite of unit tests in both Debug and Release.
1143+
- [ ] Ensure no logic is only covered by Debug-only paths or assertions.
1144+
- [ ] Use boost:test[] to validate results across optimization levels.
1145+
1146+
. *Typically, how should I set up a CMake file to handle Debug and Release builds?*
1147+
+
1148+
Here's an example of how to set up your `CMakeLists.txt` to handle `BOOST_ASSERT` correctly by toggling behavior based on the build type (Debug or Release). The example includes linking with some sample libraries (boost:log[], boost:system[] and boost:thread[]):
1149+
+
1150+
[source,cmake]
1151+
----
1152+
cmake_minimum_required(VERSION 3.10)
1153+
project(MyBoostApp)
1154+
1155+
# Set your C++ standard
1156+
set(CMAKE_CXX_STANDARD 17)
1157+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1158+
1159+
# Enable debug symbols for Debug mode
1160+
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
1161+
1162+
# Link Boost (adjust components as needed)
1163+
find_package(Boost REQUIRED COMPONENTS log log_setup system thread)
1164+
1165+
target_link_libraries(MyBoostApp PRIVATE
1166+
Boost::log
1167+
Boost::log_setup
1168+
Boost::system
1169+
Boost::thread
1170+
)
1171+
1172+
add_executable(MyBoostApp main.cpp)
1173+
1174+
target_include_directories(MyBoostApp PRIVATE ${Boost_INCLUDE_DIRS})
1175+
target_link_libraries(MyBoostApp PRIVATE ${Boost_LIBRARIES})
1176+
1177+
# Enable BOOST_ASSERT in Debug, disable in Release
1178+
target_compile_definitions(MyBoostApp PRIVATE
1179+
$<$<CONFIG:Debug>:BOOST_ENABLE_ASSERT_HANDLER>
1180+
$<$<CONFIG:Release>:NDEBUG>
1181+
)
1182+
1183+
# Optional: You can define a custom assert handler in debug builds
1184+
# by linking a file like the assert handler shown above that defines `boost::assertion_failed`
1185+
1186+
----
1187+
10231188
== Releases
10241189

10251190
. *How do I download the latest libraries?*

0 commit comments

Comments
 (0)