Copy `.pdb` files to `Editable Installations` and `Wheel`s for easier debugging on windows
Copy .pdb files to Editable Installations and Wheels for easier debugging on windows
Hi team, first of all, thank you for developing this awesome tool.
Is your feature request related to a problem? Please describe
I have a project that uses the Mixed Rust/Python layout. After running maturin dev, the project layout looks like this:
my-project
├── Cargo.toml
├── my_project
│ ├── __init__.py
│ ├── bar.py
│ └── lib_name.cp310-win_amd64.pyd
├── README.md
└── src
└── lib.rs
I then started debugging, but was surprised to find that I couldn’t set breakpoints and saw <unknown> entries in the Rust panic backtrace:
49: 0x7ffecfdaef5c - CallWindowProcW
50: 0x7ffecfdae684 - DispatchMessageW
51: 0x7ffe587e6ccf - PyInit__lib_name
52: 0x7ffe586207db - <unknown>
53: 0x7ffe58620e5b - <unknown>
54: 0x7ffe585d2ae1 - <unknown>
55: 0x7ffe58565089 - <unknown>
56: 0x7ffe583b0600 - <unknown>
57: 0x7ffe583b0e2c - <unknown>
58: 0x7ffe583b7a63 - <unknown>
59: 0x7ffe586abb29 - PyInit__lib_name
I realized this was likely due to the lib_name.cp310-win_amd64.pyd/.dll not finding the corresponding .pdb file.
Specifically, cargo build produces both lib_name.dll and lib_name.pdb in the same directory (target\debug\), so there is no problem. However, both maturin dev and maturin build only copy the lib_name.dll to another directory without copying the lib_name.pdb, causing the above issue.
Describe the solution you'd like
Running $env:RUSTFLAGS="--print=link-args"; cargo build, I observed that rustc emits the linker flags /DEBUG and /PDBALTPATH:%_PDB%.
This means that as long as lib_name.cp310-win_amd64.pyd and lib_name.pdb are in the same directory, the debug information should load correctly.
After I manually copied target\debug\lib_name.pdb to my_project\lib_name.pdb, the issue was resolved.
Describe your feature request
I am not an expert in debugging, so if my approach is incorrect or there’s a better solution, please correct me!
I would like maturin to automatically copy the .pdb files to the editable installation directory (my_project\) and also include them in the wheel.
Since developers may not always generate .pdb files, or might modify the /PDBALTPATH:%_PDB% flag, I suggest adding a --pdb[=relative_path] option to maturin.
- When the
--pdboption is specified,maturinshould copy the.pdbfile (with the same name aslib_name.dll) tomy_project\lib_name.pdband include it in the wheel. - When
--pdb="foo\bar.pdb"is specified,maturinshould copy the.pdbfile tomy_project\foo\bar.pdband place it in the corresponding location in the wheel.- This is typically used with
/PDBALTPATH:<relative_path>
- This is typically used with
This would only affect Windows, as debugging information on Linux and macOS can be included within the library file.
Describe alternatives you've considered
Manually copying the .pdb files.
Rejection 1
The debugger only loads .pdb files that exactly match the .pdb files created when an app was built (that is, the original .pdb files or copies). This exact duplication is necessary because the layout of apps can change even if the code itself has not changed.
This means manually copying .pdb files every time maturin dev is re-run, which is not ideal.
Rejection 2
Even if developers manually copy the .pdb files, they cannot include them in the wheel.
Additional context
For local development, the debugging experience without .pdb files is very poor, as I am unable to set breakpoints.
If you're curious, Polars has a clever method for setting breakpoints when debugging Python/Rust code.
For wheel users, not having .pdb files means that Rust panic backtraces will only show <unknown> entries, making it harder to report issues to developers. You can see an example here.
See also #267, since the default is packed for both Windows and macOS, I don't think this is only specific to Windows, so a --pdb option isn't the right name.
I'm going to ask the same question as in #267 again:
Do you know any Python C/C++ extension that includes debug symbol files as a reference?
See also #267, since the default is
packedfor both Windows and macOS, I don't think this is only specific to Windows, so a--pdboption isn't the right name.
I don’t have experience developing on macOS, so please correct me if I’m wrong.
For macOS, I think this issue can be alleviated by setting RUSTFLAGS="-Csplit-debuginfo=off", which embeds debug information into the .dylib.
But for MSVC, only packed is supported, so copying the .pdb file seems to be the only solution we have.
If maturin chooses to support packed for macOS, what about packed for Linux? And what about unpacked? I’m not against this approach, but I think the need is more urgent for Windows, as there’s no workaround.
Do you know any Python C/C++ extension that includes debug symbol files as a reference?
meson-python seems to copy .pdb files into the wheel in debug mode. Here’s their code.
According to their documentation, they seem to have strong support for development debugging.
IDEs and other tools will then be able to show correct file locations and line numbers during debugging.
See also mesonbuild/meson#10639
File 'pandas\_libs\window\indexers.cp38-win_amd64.pdb' not found, skipping
This suggests that pandas includes .pdb files in development mode, but does not include them when publishing to pypi.
Personally, I like to include debug information even in release builds. I agree with this perspective.
but I think the need is more urgent for Windows, as there’s no workaround.
The workaround is copy the .pdb file manually, right? It's not ergonomic but should work.
I'm in favor of adding the support, but it should be considered for all major supported platforms. --pdb just isn't right, we need a better name. BTW, pdb is also the name of a popular Python debugger, so it'll be confusing.
As always, pull requests are welcome!
The workaround is copy the
.pdbfile manually, right? It's not ergonomic but should work.
But it's really painful😫.
--pdbjust isn't right, we need a better name. BTW,pdbis also the name of a popular Python debugger, so it'll be confusing.
You're right, I realized this while searching for related issues on GitHub. pdb was just a name I came up with casually, I agree that we need a better name.
As always, pull requests are welcome!
Thanks! I might give it a try this weekend if I have time, but I don’t have a macOS to test on.
Thanks for the workaround! I never would have figured that out on my own.
It would be nice to just copy them next to the .pyd file IMO.
This is exactly what PR #2220 does, but that PR still has some finishing work to be done. Unfortunately, I have almost no time to push it.
So per my understanding the workaround described here only applies to the project that directly uses maturin but not for projects that has such project as a dependency, right?
Through GitHub cross-references, I guess you're referring to cryptography.
You can clone and build it locally, which will allow you to obtain the .pdb files. But it seems you've already resolved it yourself 😁.