Some breakpoints work while others don’t when compiling in debug mode with VS C++

Godot Version

4.3 windows

Question

Hello everyone,

UPDATE: testing it in some other project looks like i can’t put any custom method in the process method . whats going on here ?

I’m facing a strange issue while compiling a GDExtension in debug mode using Visual Studio C++. Some breakpoints work as expected, while others don’t.

I’ve tried recompiling multiple times and verified that the output is in debug mode, but no matter what I do, only some breakpoints are hit while others are not.
this is what the non working breakpoint massage say

it is compiled many time , can’t be the code is not updated to the output dll
this is the scons im using to compile:

#!/usr/bin/env python
import os
import sys

# Extract the required values
my_project_name = "adventure_rpg"
my_project_dir_name = "game"  # 'game' replaces the old 'demo'
my_godot_cpp_name = r"C:\dev\my\godot\cpp_new\godot-cpp\godot-cpp\SConstruct"
my_project_src_dir = r"C:\dev\my\godot\cpp_new\adventure_rpg\src"

def normalize_path(val, env):
    return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val)

def validate_parent_dir(key, val, env):
    if not os.path.isdir(normalize_path(os.path.dirname(val), env)):
        raise UserError("'%s' is not a directory: %s" % (key, os.path.dirname(val)))

libname = my_project_name
projectdir = my_project_dir_name
godot_cpp_path_SConstruct = my_godot_cpp_name
this_project_src = my_project_src_dir
print(this_project_src)

localEnv = Environment(tools=["default"], PLATFORM="")

# Explicitly set the PLATFORM variable based on the running OS.
if sys.platform.startswith("win"):
    localEnv["PLATFORM"] = "win32"
else:
    localEnv["PLATFORM"] = sys.platform

if 'MSVC' in localEnv['TOOLS']:
    localEnv.Append(CCFLAGS=['/std:c++17'])
    # Custom messages for MSVC compile and link commands.
    localEnv['CCCOMSTR']    = 'Compiling (MSVC): $SOURCE'
    localEnv['SHLINKCOMSTR'] = 'Linking (MSVC): $TARGET'
else:
    localEnv.Append(CCFLAGS=['-std=c++17'])

localEnv["compiledb"] = False

customs = ["custom.py"]
customs = [os.path.abspath(path) for path in customs]

opts = Variables(customs, ARGUMENTS)
opts.Add(
    BoolVariable(
        key="compiledb",
        help="Generate compilation DB (`compile_commands.json`) for external tools",
        default=localEnv.get("compiledb", False),
    )
)
opts.Add(
    PathVariable(
        key="compiledb_file",
        help="Path to a custom `compile_commands.json` file",
        default=localEnv.get("compiledb_file", "compile_commands.json"),
        validator=validate_parent_dir,
    )
)
opts.Update(localEnv)

Help(opts.GenerateHelpText(localEnv))

env = localEnv.Clone()

# Force SCons to print the full command line for every compile/link action.
env["PRINT_CMD_LINE_FUNC"] = lambda cmd, target, source, env: print(" ".join(cmd))

env.Tool("compilation_db")
compilation_db = env.CompilationDatabase(
    normalize_path(localEnv["compiledb_file"], localEnv)
)
env.Alias("compiledb", compilation_db)

env = SConscript(godot_cpp_path_SConstruct, {"env": env, "customs": customs})

def find_directories(directory):
    directories = ["src/"]
    for root, dirs, files in os.walk(directory):
        directories.extend(["src/" + os.path.relpath(os.path.join(root, d), directory).replace("\\", "/") + "/" for d in dirs])
    return directories

source_dirs = find_directories(this_project_src)
env.Append(CPPPATH=source_dirs)
print("Source directories detected:", source_dirs)

# Define object directory
obj_dir = "obj/"
if not os.path.exists(obj_dir):
    os.makedirs(obj_dir)

print("Source directories detected:", source_dirs)  # Debug detected directories

sources = []
for d in source_dirs:
    cpp_files = Glob(d + "*.cpp")
    print(f"Found {len(cpp_files)} files in {d}: {[str(f) for f in cpp_files]}")
    sources.extend(cpp_files)

print("Final list of source files:", [str(f) for f in sources])

# (Optional) Collect all source files again if required by the build process.
sources = []
for d in source_dirs:
    sources.extend(Glob(d + "*.cpp"))

# Create object files in obj_dir
objects = []
for source in sources:
    obj_file = os.path.join(obj_dir, os.path.splitext(os.path.basename(str(source)))[0] + ".obj")
    objects.append(env.Object(target=obj_file, source=source))

# Define the output library file exactly as in your original configuration.
file = "{}{}{}".format(libname, env["suffix"], env["SHLIBSUFFIX"])
libraryfile = "bin/{}/{}".format(env["platform"], file)

# Link objects into a shared library.
library = env.SharedLibrary(
    target=libraryfile,
    source=objects
)

copy = env.InstallAs("{}/bin/{}/lib{}".format(projectdir, env["platform"], file), library)

default_args = [library, copy]
if localEnv.get("compiledb", False):
    default_args += [compilation_db]
Default(*default_args)

Has anyone encountered this issue before? Any suggestions on how to fix it?

Thanks in advance!

I believe breakpoints can not be used on declarations, definitions, export annotations etc. They only work for executable lines of code.

no , the problem is in the scons command line im invoking ,
i only need to invoke : scons dev_build=yes

1 Like

As the VS message says, this is most often caused by compiler optimizations. And as Pauldrewett points out, this traditionally means breakpoints on variable declarations won’t trigger for example, but it’s not a general rule, it just depends on how are optimizations done by the compiler. Basically, if the code is optimized so well that this line is not represented by any machine instructions, the breakpoint cannot be hit.
dev_build=yes disables optimizations (sets compiler flag -O0, see Introduction to the buildsystem — Godot Engine (stable) documentation in English ), which is why your breakpoints start to work. Alternatively, if you don’t want to work with unoptimized code but you need to make sure your breakpoint gets hit, use the directive #pragma optimize(“”, off) and on (see optimize pragma | Microsoft Learn), this way you can mark just a part of your code (like one method you want to debug) and later, once you found and fixed the issue, remove it again. Or of course, you can just temporarily change the optimization compiler flag to -Od and then back to what usually is -O2 and then switch it back. You wil find the compiler flags somewhere in your project settings.