### Automate Example Application Builds in CMake Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt This function simplifies the creation of example executables and provides optional logic to deploy them as VSCode extensions by copying binaries and configuration files to the user's extensions directory. ```cmake function(build_example target) add_executable(${target} "${CMAKE_CURRENT_SOURCE_DIR}/examples/${target}.cpp") cppdap_set_target_options(${target}) target_link_libraries(${target} PRIVATE cppdap) # Optional VSCode extension deployment logic follows endfunction(build_example) ``` -------------------------------- ### Implement a minimal DAP server in C++ Source: https://context7.com/google/cppdap/llms.txt This example demonstrates how to create a DAP server using cppdap that handles core protocol requests like Initialize, Launch, and StackTrace. It utilizes a session-based architecture to manage client connections and event dispatching. ```cpp #include "dap/io.h" #include "dap/network.h" #include "dap/protocol.h" #include "dap/session.h" #include #include #include class SimpleDebugAdapter { public: void run(int port) { auto server = dap::net::Server::create(); server->start(port, [this](const std::shared_ptr& socket) { handleConnection(socket); }, [](const char* err) { fprintf(stderr, "Server error: %s\n", err); }); printf("Debug adapter listening on port %d\n", port); while (running_) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } server->stop(); } private: void handleConnection(const std::shared_ptr& socket) { auto session = dap::Session::create(); session->setOnInvalidData(dap::kClose); session->registerHandler([this](const dap::InitializeRequest& req) { printf("Initialize from: %s\n", req.clientName.value("unknown").c_str()); dap::InitializeResponse resp; resp.supportsConfigurationDoneRequest = true; return resp; }); session->registerSentHandler( [session](const dap::ResponseOrError&) { session->send(dap::InitializedEvent{}); }); session->bind(socket, []() {}); } std::atomic running_{true}; }; int main() { SimpleDebugAdapter adapter; adapter.run(4711); return 0; } ``` -------------------------------- ### Manage File-based and Pipe I/O Source: https://context7.com/google/cppdap/llms.txt Provides examples for handling standard I/O, logging communication to files using spies, and creating in-memory pipes for testing or IPC. It also demonstrates printf-style formatting for writers. ```cpp #include "dap/io.h" #include "dap/protocol.h" #include "dap/session.h" void fileBasedSession() { auto in = dap::file(stdin, false); auto out = dap::file(stdout, false); auto session = dap::Session::create(); session->bind(in, out); } void fileLogging() { auto logFile = dap::file("/tmp/dap-debug.log"); auto session = dap::Session::create(); auto in = dap::spy(dap::file(stdin, false), logFile, "\n-> "); auto out = dap::spy(dap::file(stdout, false), logFile, "\n<- "); session->bind(in, out); } void inMemoryPipe() { auto pipe1 = dap::pipe(); auto pipe2 = dap::pipe(); auto serverSession = dap::Session::create(); auto clientSession = dap::Session::create(); serverSession->bind( dap::ReaderWriter::create(pipe1, pipe2), []() { printf("Server: connection closed\n"); } ); clientSession->bind( dap::ReaderWriter::create(pipe2, pipe1), []() { printf("Client: connection closed\n"); } ); } void writeFormatted(std::shared_ptr writer) { dap::writef(writer, "Debug message: value=%d, name=%s\n", 42, "test"); } ``` -------------------------------- ### Build cppdap with CMake Source: https://github.com/google/cppdap/blob/main/README.md Commands to generate build files and compile the cppdap library on Unix-like systems. It supports optional flags for building tests and examples. ```bash cd mkdir build cd build cmake .. make ``` -------------------------------- ### Implement Asynchronous Operations with cppdap Source: https://context7.com/google/cppdap/llms.txt Demonstrates the usage of dap::promise and dap::future for asynchronous task management. Includes examples of setting values from worker threads, blocking waits, handling timeouts, and waiting until specific deadlines. ```cpp #include "dap/future.h" #include #include void asyncOperations() { dap::promise promise; dap::future future = promise.get_future(); if (future.valid()) { printf("Future is valid\n"); } std::thread worker([promise]() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); promise.set_value(42); }); future.wait(); int result = future.get(); printf("Result: %d\n", result); worker.join(); } void asyncWithTimeout() { dap::promise promise; auto future = promise.get_future(); std::thread worker([promise]() { std::this_thread::sleep_for(std::chrono::seconds(2)); promise.set_value("delayed result"); }); auto status = future.wait_for(std::chrono::milliseconds(500)); if (status == dap::future_status::timeout) { printf("Operation timed out, still waiting...\n"); future.wait(); } printf("Got result: %s\n", future.get().c_str()); worker.join(); } void asyncUntilDeadline() { dap::promise promise; auto future = promise.get_future(); auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(5); std::thread worker([promise]() { std::this_thread::sleep_for(std::chrono::seconds(1)); promise.set_value(true); }); auto status = future.wait_until(deadline); if (status == dap::future_status::ready) { printf("Operation completed: %s\n", future.get() ? "success" : "failure"); } worker.join(); } ``` -------------------------------- ### Send C++ DAP Events from Server Source: https://context7.com/google/cppdap/llms.txt Provides examples of sending various Debug Adapter Protocol events from the server to the client using `session->send()`. This includes notifications for stopped events, output messages, thread lifecycle changes, and capability updates. Requires 'dap/protocol.h' and 'dap/session.h'. ```cpp #include "dap/protocol.h" #include "dap/session.h" class DebugAdapter { dap::Session* session; dap::integer threadId = 1; public: void notifyBreakpointHit(int breakpointId, int line) { dap::StoppedEvent event; event.reason = "breakpoint"; event.threadId = threadId; event.allThreadsStopped = true; event.hitBreakpointIds = {breakpointId}; event.description = "Paused on breakpoint"; session->send(event); } void notifyStepCompleted() { dap::StoppedEvent event; event.reason = "step"; event.threadId = threadId; event.allThreadsStopped = false; session->send(event); } void notifyThreadStarted(int newThreadId) { dap::ThreadEvent event; event.reason = "started"; event.threadId = newThreadId; session->send(event); } void sendOutput(const std::string& text, const std::string& category = "stdout") { dap::OutputEvent event; event.output = text; event.category = category; // "console", "stdout", "stderr", "telemetry" session->send(event); } void notifyCapabilitiesChanged() { dap::CapabilitiesEvent event; event.capabilities.supportsStepBack = true; event.capabilities.supportsRestartRequest = true; session->send(event); } }; ``` -------------------------------- ### Define and install library target Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt Registers the cppdap library target and configures its installation path and export settings. It uses CMakePackageConfigHelpers to generate configuration files for downstream consumption. ```cmake add_library(cppdap ${CPPDAP_LIST}) set_target_properties(cppdap PROPERTIES POSITION_INDEPENDENT_CODE 1) cppdap_set_target_options(cppdap) install(TARGETS cppdap EXPORT cppdap-targets ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) ``` -------------------------------- ### Initialize Git Submodules Source: https://github.com/google/cppdap/blob/main/README.md Fetches the required third-party dependencies for cppdap, specifically nlohmann/json and googletest, using git submodules. ```bash cd git submodule update --init ``` -------------------------------- ### Initialize and Bind a DAP Session in C++ Source: https://context7.com/google/cppdap/llms.txt Demonstrates the creation of a dap::Session, registering error handlers, and binding the session to standard I/O streams for message processing. ```cpp #include "dap/io.h" #include "dap/protocol.h" #include "dap/session.h" int main() { // Create a new DAP session auto session = dap::Session::create(); // Register error handler for protocol errors session->onError([](const char* msg) { fprintf(stderr, "Session error: %s\n", msg); }); // Bind session to stdin/stdout for communication std::shared_ptr in = dap::file(stdin, false); std::shared_ptr out = dap::file(stdout, false); // Start processing messages with an optional close handler session->bind(in, out, []() { printf("Connection closed\n"); }); // Session is now running and processing messages // Block until terminated... return 0; } ``` -------------------------------- ### Send C++ DAP Requests from Client Source: https://context7.com/google/cppdap/llms.txt Illustrates how to send various Debug Adapter Protocol requests from the client to the remote endpoint using `session->send()`. It covers sending initialize, launch, and set breakpoints requests, and demonstrates how to handle responses using futures and timeouts. Requires 'dap/protocol.h', 'dap/session.h', and ''. ```cpp #include "dap/protocol.h" #include "dap/session.h" #include void sendRequests(dap::Session* session) { // Send initialize request and wait for response dap::InitializeRequest initReq; initReq.adapterID = "my-debugger"; initReq.clientID = "my-client"; initReq.linesStartAt1 = true; initReq.columnsStartAt1 = true; initReq.supportsRunInTerminalRequest = true; auto initFuture = session->send(initReq); auto initResponse = initFuture.get(); // Blocks until response if (initResponse.error) { fprintf(stderr, "Initialize failed: %s\n", initResponse.error.message.c_str()); return; } printf("Adapter supports breakpoints: %s\n", initResponse.response.supportsBreakpointLocationsRequest.value(false) ? "yes" : "no"); // Send launch request dap::LaunchRequest launchReq; launchReq.noDebug = false; session->send(launchReq); // Set breakpoints dap::SetBreakpointsRequest bpReq; bpReq.source.path = "/path/to/source.cpp"; dap::SourceBreakpoint bp; bp.line = 42; bp.condition = "x > 10"; bpReq.breakpoints = {bp}; auto bpFuture = session->send(bpReq); // Use wait_for for timeout handling if (bpFuture.wait_for(std::chrono::seconds(5)) == dap::future_status::timeout) { fprintf(stderr, "Timeout waiting for breakpoint response\n"); return; } auto bpResponse = bpFuture.get(); for (const auto& breakpoint : bpResponse.response.breakpoints) { printf("Breakpoint at line %lld: verified=%s\n", breakpoint.line.value(0), breakpoint.verified ? "true" : "false"); } } ``` -------------------------------- ### Implement TCP Network Server for DAP Source: https://context7.com/google/cppdap/llms.txt Shows how to create a TCP server using the dap::net::Server class to accept and manage DAP client connections. Each connection is bound to a unique session with custom request handlers. ```cpp #include "dap/io.h" #include "dap/network.h" #include "dap/protocol.h" #include "dap/session.h" #include int main() { constexpr int kPort = 4711; std::atomic running{true}; auto server = dap::net::Server::create(); // Handle incoming connections auto onConnect = [&](const std::shared_ptr& socket) { printf("Client connected\n"); auto session = dap::Session::create(); // Close connection on invalid protocol data (security) session->setOnInvalidData(dap::kClose); // Bind session to the network socket session->bind(socket, [&]() { printf("Client disconnected\n"); }); // Register handlers session->registerHandler([](const dap::InitializeRequest&) { dap::InitializeResponse response; response.supportsConfigurationDoneRequest = true; return response; }); session->registerHandler([&](const dap::DisconnectRequest& req) { if (req.terminateDebuggee.value(false)) { running = false; } return dap::DisconnectResponse{}; }); // Keep session alive while socket is open while (socket->isOpen() && running) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }; auto onError = [](const char* msg) { fprintf(stderr, "Server error: %s\n", msg); }; // Start server on localhost if (!server->start(kPort, onConnect, onError)) { fprintf(stderr, "Failed to start server on port %d\n", kPort); return 1; } printf("DAP server listening on port %d\n", kPort); // Run until shutdown while (running) { std::this_thread::sleep_for(std::chrono::seconds(1)); } server->stop(); return 0; } ``` -------------------------------- ### Connect to a DAP server over TCP Source: https://context7.com/google/cppdap/llms.txt Demonstrates how to establish a TCP connection to a DAP server, bind a session, register event handlers, and send protocol requests. It requires the dap/network.h and dap/session.h headers. ```cpp #include "dap/io.h" #include "dap/network.h" #include "dap/protocol.h" #include "dap/session.h" int main() { constexpr int kPort = 4711; constexpr uint32_t kTimeoutMs = 5000; auto socket = dap::net::connect("localhost", kPort, kTimeoutMs); if (!socket) { fprintf(stderr, "Failed to connect to server\n"); return 1; } printf("Connected to server\n"); auto session = dap::Session::create(); session->bind(socket); session->registerHandler([](const dap::StoppedEvent& event) { printf("Debuggee stopped: %s\n", event.reason.c_str()); }); session->registerHandler([](const dap::OutputEvent& event) { printf("[output] %s", event.output.c_str()); }); dap::InitializeRequest initReq; initReq.adapterID = "example-adapter"; initReq.clientID = "example-client"; auto initFuture = session->send(initReq); auto initResp = initFuture.get(); if (initResp.error) { fprintf(stderr, "Initialize failed: %s\n", initResp.error.message.c_str()); return 1; } printf("Server capabilities received\n"); session->send(dap::ConfigurationDoneRequest{}); dap::ContinueRequest contReq; contReq.threadId = 1; auto contFuture = session->send(contReq); contFuture.get(); dap::DisconnectRequest discReq; discReq.terminateDebuggee = false; session->send(discReq); printf("Disconnected\n"); return 0; } ``` -------------------------------- ### CMake Configuration for C++ Debug Adapter with cppdap Source: https://context7.com/google/cppdap/llms.txt This CMakeLists.txt file sets up a C++ project to build a debug adapter using the cppdap library. It defines the project, locates and includes the cppdap subdirectory, specifies the executable source files, links the cppdap library, and enforces a minimum C++ standard. ```cmake cmake_minimum_required(VERSION 3.22) project(MyDebugAdapter) # Set path to cppdap set(CPPDAP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/cppdap) # Optional: Configure JSON library path # set(CPPDAP_JSON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/json) # Optional: Use system-installed JSON library # set(CPPDAP_USE_EXTERNAL_NLOHMANN_JSON_PACKAGE ON) # set(CPPDAP_USE_EXTERNAL_RAPIDJSON_PACKAGE ON) # set(CPPDAP_USE_EXTERNAL_JSONCPP_PACKAGE ON) # Add cppdap add_subdirectory(${CPPDAP_DIR}) # Your executable add_executable(my_debug_adapter src/main.cpp src/debugger.cpp ) # Link against cppdap target_link_libraries(my_debug_adapter cppdap) # C++11 minimum required target_compile_features(my_debug_adapter PRIVATE cxx_std_11) ``` -------------------------------- ### DAP C++ Error Handling and Session Management Source: https://context7.com/google/cppdap/llms.txt Demonstrates setting up session-level error handlers for protocol parsing errors and configuring invalid data handling behavior. It also shows how to register handlers for specific requests that return errors using dap::ResponseOrError and how to send requests and handle potential errors in the responses. ```cpp #include "dap/protocol.h" #include "dap/session.h" void setupErrorHandling(dap::Session* session) { // Handle session-level errors (protocol parsing, etc.) session->onError([](const char* msg) { fprintf(stderr, "Protocol error: %s\n", msg); // Could trigger cleanup/shutdown here }); // Configure behavior on invalid data // kIgnore - continue processing (default) // kClose - close the session on invalid data session->setOnInvalidData(dap::kClose); // Recommended for network sessions // Handler returning errors for invalid requests session->registerHandler( [](const dap::StackTraceRequest& request) -> dap::ResponseOrError { // Validate thread ID if (request.threadId < 1 || request.threadId > 100) { return dap::Error("Invalid thread ID: %d", int(request.threadId)); } // Validate frame count if (request.levels.value(0) > 1000) { return dap::Error("Too many frames requested"); } // Return successful response dap::StackTraceResponse response; dap::StackFrame frame; frame.id = 1; frame.name = "main"; frame.line = 10; frame.column = 1; response.stackFrames.push_back(frame); response.totalFrames = 1; return response; }); } void handleClientResponses(dap::Session* session) { // Send request and handle potential errors dap::StackTraceRequest req; req.threadId = 1; req.levels = 20; auto future = session->send(req); auto result = future.get(); // Check for error if (result.error) { fprintf(stderr, "StackTrace request failed: %s\n", result.error.message.c_str()); return; } // Access successful response printf("Got %zu stack frames\n", result.response.stackFrames.size()); for (const auto& frame : result.response.stackFrames) { printf(" %s at line %lld\n", frame.name.c_str(), frame.line); } } ``` -------------------------------- ### DAP C++ Working with Optional Values Source: https://context7.com/google/cppdap/llms.txt Illustrates how to use `dap::optional` for fields that may or may not be present in DAP protocol messages. It covers setting optional fields, checking for their existence, accessing their values with defaults, and conditional access. ```cpp #include "dap/optional.h" #include "dap/protocol.h" void workingWithOptionals() { dap::StackFrame frame; frame.id = 1; frame.name = "main"; frame.line = 42; frame.column = 1; // Set optional fields frame.endLine = 50; frame.endColumn = 10; frame.presentationHint = "normal"; // Check if optional has value if (frame.source.has_value()) { printf("Source: %s\n", frame.source->path.value("unknown").c_str()); } // Use value() with default int endLine = frame.endLine.value(frame.line); printf("End line: %d\n", endLine); // Conditional access with operator bool if (frame.moduleId) { // moduleId is a variant printf("Has module ID\n"); } // Working with response optionals dap::SetBreakpointsResponse response; dap::Breakpoint bp; bp.verified = true; bp.line = 42; bp.message = "Breakpoint set successfully"; // Optional message // bp.id is optional - leave unset if not needed response.breakpoints.push_back(bp); // Reading optional from request dap::ContinueRequest req; req.threadId = 1; req.singleThread = true; // Optional, defaults to false if unset bool singleThread = req.singleThread.value(false); } ``` -------------------------------- ### Register Request Handlers in C++ Source: https://context7.com/google/cppdap/llms.txt Shows how to register handlers for DAP requests, including returning standard responses, handling errors via ResponseOrError, and performing asynchronous callbacks. ```cpp #include "dap/protocol.h" #include "dap/session.h" void setupHandlers(dap::Session* session, int sourceReferenceId) { // Simple handler returning a response session->registerHandler([](const dap::InitializeRequest&) { dap::InitializeResponse response; response.supportsConfigurationDoneRequest = true; response.supportsBreakpointLocationsRequest = true; response.supportsFunctionBreakpoints = true; return response; }); // Handler that may return an error using ResponseOrError session->registerHandler( [sourceReferenceId](const dap::SourceRequest& request) -> dap::ResponseOrError { if (request.sourceReference != sourceReferenceId) { return dap::Error("Unknown source reference '%d'", int(request.sourceReference)); } dap::SourceResponse response; response.content = "// Source code content here"; response.mimeType = "text/plain"; return response; }); // Handler with asynchronous callback for delayed responses session->registerHandler( [](const dap::EvaluateRequest& request, std::function callback) { // Can respond later from another thread dap::EvaluateResponse response; response.result = "evaluated: " + request.expression; response.variablesReference = 0; callback(response); }); } ``` -------------------------------- ### Define Conditional CMake Options and Variables Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt Helper functions used to define build options and directory paths only if they have not been previously set. This allows for flexible configuration overrides by the user or parent projects. ```cmake function (option_if_not_defined name description default) if(NOT DEFINED ${name}) option(${name} ${description} ${default}) endif() endfunction() function (set_if_not_defined name value) if(NOT DEFINED ${name}) set(${name} ${value} PARENT_SCOPE) endif() endfunction() ``` -------------------------------- ### Define OS-Specific Libraries and Extensions Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt Sets the required system libraries and executable file extensions based on the host operating system detected by CMake. ```cmake if(CMAKE_SYSTEM_NAME MATCHES "Windows") set(CPPDAP_OS_LIBS WS2_32) set(CPPDAP_OS_EXE_EXT ".exe") elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") set(CPPDAP_OS_LIBS pthread) set(CPPDAP_OS_EXE_EXT "") elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") set(CPPDAP_OS_LIBS) set(CPPDAP_OS_EXE_EXT "") endif() ``` -------------------------------- ### Configure Project Build Options Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt Sets various build-time toggles for the cppdap library, including compiler warnings, sanitizers (ASAN, MSAN, TSAN), and external dependency management strategies. ```cmake option_if_not_defined(CPPDAP_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF) option_if_not_defined(CPPDAP_BUILD_TESTS "Build tests" OFF) option_if_not_defined(CPPDAP_ASAN "Build dap with address sanitizer" OFF) option_if_not_defined(CPPDAP_USE_EXTERNAL_NLOHMANN_JSON_PACKAGE "Use nlohmann_json with find_package() instead of building internal submodule" OFF) ``` -------------------------------- ### Configure Unit Testing with GoogleTest in CMake Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt This snippet configures the unit testing environment for cppdap. It handles the inclusion of GoogleTest, either via an external package or a local subdirectory, and sets up the test executable with appropriate compiler flags. ```cmake if(CPPDAP_BUILD_TESTS) enable_testing() set(DAP_TEST_LIST ${CPPDAP_SRC_DIR}/any_test.cpp ...) if(CPPDAP_USE_EXTERNAL_GTEST_PACKAGE) find_package(GTest REQUIRED) else() add_subdirectory(${CPPDAP_GOOGLETEST_DIR}) target_compile_options(gtest PRIVATE -w) endif() add_executable(cppdap-unittests ${DAP_TEST_LIST}) add_test(NAME cppdap-unittests COMMAND cppdap-unittests) endif() ``` -------------------------------- ### Register C++ Event Handlers with DAP Session Source: https://context7.com/google/cppdap/llms.txt Demonstrates how to register event handlers for various Debug Adapter Protocol events using the dap::Session. This includes handling stopped events, output messages, thread lifecycle changes, and breakpoint state updates. It requires the 'dap/protocol.h' and 'dap/session.h' headers. ```cpp #include "dap/protocol.h" #include "dap/session.h" void setupEventHandlers(dap::Session* session) { // Handle stopped events (breakpoint hit, stepping completed, etc.) session->registerHandler([](const dap::StoppedEvent& event) { printf("Debuggee stopped: reason=%s, threadId=%lld\n", event.reason.c_str(), event.threadId.value(0)); if (event.allThreadsStopped.value(false)) { printf("All threads are now stopped\n"); } }); // Handle output from the debuggee session->registerHandler([](const dap::OutputEvent& event) { const char* category = event.category.value("console").c_str(); printf("[%s] %s", category, event.output.c_str()); }); // Handle thread lifecycle events session->registerHandler([](const dap::ThreadEvent& event) { printf("Thread %lld %s\n", event.threadId, event.reason.c_str()); // \"started\" or \"exited\" }); // Handle breakpoint state changes session->registerHandler([](const dap::BreakpointEvent& event) { printf("Breakpoint %d %s: verified=%s\n", event.breakpoint.id.value(-1), event.reason.c_str(), event.breakpoint.verified ? "true" : "false"); }); } ``` -------------------------------- ### Configure Third-Party Dependency Paths Source: https://github.com/google/cppdap/blob/main/README.md Allows overriding default paths for third-party dependencies like JSON libraries and googletest before including the cppdap subdirectory. ```cmake set(CPPDAP_THIRD_PARTY_DIR ) set(CPPDAP_JSON_DIR ) set(CPPDAP_GOOGLETEST_DIR ) add_subdirectory(${CPPDAP_DIR}) ``` -------------------------------- ### Configure Fuzzing with Clang Sanitizers in CMake Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt This snippet sets up a fuzzer executable for the project, requiring the Clang compiler. It dynamically applies Address, Memory, or Thread sanitizers based on CMake variables. ```cmake if(CPPDAP_BUILD_FUZZER) if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") message(FATAL_ERROR "CPPDAP_BUILD_FUZZER can currently only be used with the clang toolchain") endif() add_executable(cppdap-fuzzer ${DAP_FUZZER_LIST}) if(CPPDAP_ASAN) target_compile_options(cppdap-fuzzer PUBLIC "-fsanitize=fuzzer,address") endif() endif() ``` -------------------------------- ### Integrate cppdap into CMake Projects Source: https://github.com/google/cppdap/blob/main/README.md Instructions for linking the cppdap library into a custom CMake project using add_subdirectory and target_link_libraries. ```cmake set(CPPDAP_DIR ) add_subdirectory(${CPPDAP_DIR}) target_link_libraries( cppdap) ``` -------------------------------- ### Configure JSON library dependencies in CMake Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt This function dynamically links the appropriate JSON library based on user-defined CMake options. It supports nlohmann_json, rapidjson, and JsonCpp, or falls back to a local include directory. ```cmake function(cppdap_set_json_links target) if (CPPDAP_USE_EXTERNAL_NLOHMANN_JSON_PACKAGE) target_link_libraries(${target} PRIVATE "$") elseif(CPPDAP_USE_EXTERNAL_RAPIDJSON_PACKAGE) target_link_libraries(${target} PRIVATE rapidjson) elseif(CPPDAP_USE_EXTERNAL_JSONCPP_PACKAGE) target_link_libraries(${target} PRIVATE JsonCpp::JsonCpp) else() target_include_directories(${target} PRIVATE "${CPPDAP_JSON_DIR}/include/") endif() endfunction(cppdap_set_json_links) ``` -------------------------------- ### Set target compiler options and sanitizers Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt Configures compiler warnings, sanitizers (ASan, MSan, TSan), and include directories for a given target. It ensures consistent build settings across different compilers like MSVC and GCC/Clang. ```cmake function(cppdap_set_target_options target) if(MSVC) target_compile_options(${target} PRIVATE "-W4") else() target_compile_options(${target} PRIVATE "-Wall") endif() if(CPPDAP_ASAN) target_compile_options(${target} PUBLIC "-fsanitize=address") target_link_options(${target} PUBLIC "-fsanitize=address") endif() target_include_directories(${target} PUBLIC "$") cppdap_set_json_links(${target}) endfunction(cppdap_set_target_options) ``` -------------------------------- ### Register Sent Handlers in C++ DAP Source: https://context7.com/google/cppdap/llms.txt Demonstrates how to use registerSentHandler to execute logic after specific DAP responses are sent. This is useful for triggering follow-up events or logging response outcomes. ```cpp #include "dap/protocol.h" #include "dap/session.h" void setupSentHandlers(dap::Session* session) { // Send InitializedEvent after InitializeResponse is sent session->registerSentHandler( [session](const dap::ResponseOrError& response) { if (!response.error) { // Only send initialized event if initialize succeeded session->send(dap::InitializedEvent()); } }); // Handle after ConfigurationDone response is sent session->registerSentHandler( [session](const dap::ResponseOrError&) { // Start the debuggee after configuration is complete dap::StoppedEvent event; event.reason = "entry"; event.threadId = 1; event.allThreadsStopped = true; session->send(event); }); // Log all launch responses session->registerSentHandler( [](const dap::ResponseOrError& response) { if (response.error) { printf("Launch failed: %s\n", response.error.message.c_str()); } else { printf("Launch response sent successfully\n"); } }); } ``` -------------------------------- ### Configure JSON Library Dependencies in CMake Source: https://github.com/google/cppdap/blob/main/CMakeLists.txt This logic checks for external JSON library flags and validates that no more than one is selected. It attempts to locate the library via find_package or by inspecting the directory structure if not explicitly provided. ```cmake if(CPPDAP_USE_EXTERNAL_NLOHMANN_JSON_PACKAGE) list(APPEND CPPDAP_EXTERNAL_JSON_PACKAGES "CPPDAP_USE_EXTERNAL_NLOHMANN_JSON_PACKAGE") endif() if(CPPDAP_USE_EXTERNAL_RAPIDJSON_PACKAGE) list(APPEND CPPDAP_EXTERNAL_JSON_PACKAGES "CPPDAP_USE_EXTERNAL_RAPIDJSON_PACKAGE") endif() if(CPPDAP_USE_EXTERNAL_JSONCPP_PACKAGE) list(APPEND CPPDAP_EXTERNAL_JSON_PACKAGES "CPPDAP_USE_EXTERNAL_JSONCPP_PACKAGE") endif() list(LENGTH CPPDAP_EXTERNAL_JSON_PACKAGES CPPDAP_EXTERNAL_JSON_PACKAGES_COUNT) if(CPPDAP_EXTERNAL_JSON_PACKAGES_COUNT GREATER 1) message(FATAL_ERROR "At most one of CPPDAP_USE_EXTERNAL_NLOHMANN_JSON_PACKAGE, CPPDAP_USE_EXTERNAL_RAPIDJSON_PACKAGE, and CPPDAP_USE_EXTERNAL_JSONCPP_PACKAGE can be set.") elseif(CPPDAP_USE_EXTERNAL_NLOHMANN_JSON_PACKAGE) find_package(nlohmann_json CONFIG REQUIRED) set(CPPDAP_JSON_LIBRARY "nlohmann") endif() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.