Visual Studio debug visualizers (.natvis files) typically require knowledge of non-public members and of implementation details of classes. Also, and because of this, there is no guarantee that the implementation of those visualizers remains valid from one version of Qt to another. This is a serious limitation of the current debug visualization support provided with the Qt VS Tools extension.
To fix this limitation in such a way that visualizers (1) only use public members of Qt classes, and (2) are valid for any version of Qt, the following solution is proposed:
- .natvis files will be generated at build-time, using information in Qt headers and in application object files.
- Generated .natvis files will then be added to the application PDB file using the /NATVIS option of the linker, and will thus be available in debugging sessions.
- The visualizer for a Qt type will only reference accessors of that type, i.e. public, const, non-void, nullary member functions.
- For example:
- QString QDir::path() const ← ok, can be used in .natvis.
- void QDir::refresh() const ← NOK, returns void.
- bool QDir::removeRecursively() ← NOK, must be const.
- QString QDir::filePath(const QString &) const ← NOK, must have zero arguments.
- A few exceptions to this rule might be needed, e.g. for accessing items in a collection type.
- The tool ctags will be used to extract information from Qt headers.
- The tool dumpbin will be used to extract symbol data from .obj files.
The following recipe can be used to generate .natvis support for an application that uses Qt types:
- (dumpbin) Run dumpbin on the application .obj files. → [sym-data]
- (ctags) Run ctags on the Qt public headers. → [ctags-data]
- (xref) Cross-reference types in [ctags-data] with symbols in [sym-data] to obtain the set of Qt types used by the application. → [types]
- (lookup) For each type in [types], lookup in [ctags-data] the available public accessors. → [accs]
- (gen) For each accessor in [accs], generate the corresponding .natvis spec, as well as any supporting C++ code. → [natvis] + [code]
- (compile) Compile [code]. → [obj]
- (link) Add [natvis] and [obj] to the linker inputs. → [bin]
This recipe can be implemented using MSBuild targets. The resulting implementation can then be added to the set of targets in Qt/MSBuild.
A proof of concept can be found at: https://codereview.qt-project.org/c/qt-labs/vstools/+/378809