Build with "RelWithDebInfo" flag is much bigger than "Debug"

I have a large project with three main dependencies: drogon, swredis and hiredis. All three dependencies are shared libraries.
Project itself contains multiple static libs (tools, models, schemas, services, etc.) linking together with cmake

I want to connect Sentry and it needs debug symbols for it to work. This is where the weird stuff starts:

  1. When building cmake .. -DCMAKE_BUILD_TYPE:STRING=Release , the final size is 27.8 MB
  2. When building cmake .. -DCMAKE_BUILD_TYPE:STRING=Debug (without optimizations), the size is 313.4 MB
  3. When building cmake .. -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo the size is 484.2 megabytes

I don’t understand how this is possible? Why is the size of RelWithDebInfo larger than simple Debug? I guess I made a mistake somewhere in CMakeLists.txt itself and it somehow adds all dependencies to debug symbols? Or is this normal? Searching forums didn’t give me any results, everyone says that such a situation is impossible (but here it is).

I would like to keep the size of the application as small as possible to save space on Sentry.

Here is my main CMakeLists.txt

cmake_minimum_required(VERSION 3.20)  # Ensure CMake version supports CMP0079
set(CMAKE_POLICY_DEFAULT_CMP0079 NEW) # Prefer shared libraries over static
project(app CXX)

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

include(CheckIncludeFileCXX)

check_include_file_cxx(any HAS_ANY)
check_include_file_cxx(string_view HAS_STRING_VIEW)
check_include_file_cxx(coroutine HAS_COROUTINE)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_STATIC_LIBRARY_PREFIX "")

###########################################################################
find_package(Drogon CONFIG REQUIRED SHARED)
link_libraries(Drogon::Drogon)

find_package(Sentry REQUIRED SHARED)

add_executable(${PROJECT_NAME} main.cc)

###########################################################################

add_subdirectory(libs)
add_subdirectory(models)
add_subdirectory(src)

target_link_libraries(${PROJECT_NAME}
    PRIVATE
    models
    schemas
    services
    states
    tools
    sentry
)

My CMakeLists.txt for tools (contains hiredis and swredis):

add_library(tools)

target_sources(tools
    PRIVATE
    ... (all cpp files)
)

######################################
find_path(HIREDIS_HEADER hiredis)
include_directories(${HIREDIS_HEADER})
find_library(HIREDIS_LIB hiredis SHARED)

find_path(REDIS_PLUS_PLUS_HEADER sw)
include_directories(${REDIS_PLUS_PLUS_HEADER})
find_library(REDIS_PLUS_PLUS_LIB redis++ SHARED)

find_package(OpenSSL REQUIRED)

target_link_libraries(tools
    PUBLIC
    ${HIREDIS_LIB}
    ${REDIS_PLUS_PLUS_LIB}
    OpenSSL::Crypto
    OpenSSL::SSL
    PRIVATE
    models
    sha256
    base64
)

target_include_directories(tools
    PUBLIC
    ${CMAKE_CURRENT_LIST_DIR}/../../include
    PRIVATE
    ${PROJECT_SOURCE_DIR}/libs
    ${CMAKE_CURRENT_LIST_DIR}/../../include/tools
    ${CMAKE_CURRENT_LIST_DIR}/../../include/tools/parsers
    ${CMAKE_CURRENT_LIST_DIR}/private
)

I would be very happy if you could help me. I am not an expert in CMake and it is difficult for me to understand some features of the work.
The ideal situation is that I can take all dependencies separately (since they do not change) and update only app . I still can’t figure out whether debug symbols for dynamic libraries (drogon, redis) are added to app or not.

This is typical of any non-trivial code when shipping debug information in an optimized build.

Imagine a simple function:

int add(int a, int b) {
  return a + b;
}

In an unoptimized build, this remains a traditional function, with a short snippet of debug information documenting its metadata. All calls to this function are performed as usual, and all resolve to the same short snippet of debug metadata.

In an optimized build this function will almost certainly be inlined, perhaps many tens or hundreds or thousands of times. At ever inlining site, the debug information must be replicated. It is this replication of debug information due to inlining, loop unrolling, and other optimization techniques which leads to inflation of the overall size of “optimized” debug metadata.

Thank you very much for explanation