CMake has been getting increasingly popular over the past years due to its simplicity and integration with the modern IDEs. The recently added CMake Server mode made it even more usable, allowing it to share the precise project structure with different IDEs, but if you wanted to actively edit a large project, you would still inevitably have to edit the CMakeLists.txt files manually, making it less intuitive than working with regular Visual Studio projects.
So we decided to bridge this gap and designed a new VisualGDB CMake Project subsystem that lets Visual Studio open Linux CMake projects and treat them just like the normal Visual C++ projects.
Displaying Project Contents
CMake already supports reporting the detailed project structure (including targets and the associated source files) to the IDEs via the CMake server protocol. The information is sufficient to see all of the project’s targets, tell their types and the related source files. Visual Studio itself can use this information to help IntelliSense find header files included from your sources, but this only works for Windows projects and does not show the relations between different targets or specific sources used by each target. To get the maximum usability, our CMake project subsystem presents the CMake project contents in Solution Explorer using the same hierarchical view as the normal Visual C++ projects do (while normal Visual C++ projects require a separate project per target, a singile VisualGDB CMake project will automatically show all the targets from all related CMake files):
This makes it possible to define advanced settings for each target (e.g. where and when to deploy it or which command-line arguments to use when debugging it):This also allowed us to automatically determine the exact list of libraries that are required by the currently debugged target, so VisualGDB can automatically deploy them and set variables like LD_LIBRARY_PATH and solib-search-path to make debugging work out-of-the-box.
So how do we get to not editing the CMakeLists.txt files manually when adding or removing sources or targets? CMake doesn’t normally let you do that, but if you look closer into its sources you can actually see that it internally tracks where each target is defined:
/** Get a backtrace from the creation of the target. */
cmListFileBacktrace const& GetBacktrace() const;
Even better, CMake actually remembers the locations of all statements like target_link_libraries() that affect each target and lets its components query them:
cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
cmBacktraceRange GetCompileOptionsBacktraces() const;
cmBacktraceRange GetCompileFeaturesBacktraces() const;
cmBacktraceRange GetCompileDefinitionsBacktraces() const;
So we made a very small modification to the CMake sources (see the commit in our CMake fork on Github) that lets CMake report where exactly is each target defined and list all statements like target_link_libraries() that affected the target.
This information was just enough for VisualGDB to automatically edit the add_executable() or add_library() statement each time you add, remove or rename a source file:We made it as non-intrusive as possible, so it actually detects your formatting style like the maximum amount of source items per line and follows it when editing CMakeLists.txt:
It will also recognize the cases where the sources (or source subdirectories) are defined via variables and will use the same variables when adding new source files:
To make creation of new targets easier, we have added an option to create them from GUI as well. VisualGDB will automatically add the necessary statements (and create/reference new CMakeLists.txt files if you are creating targets in new subdirectories):
Renaming and deleting of targets and source files will also work completely automatically.
Editing Target Properties
Another common scenario is editing target properties (e.g. adding new include directories or preprocessor macros). To make this easier, we connected the regular Visual Studio property pages with the underlying CMake statements. E.g. you can select one or more targets, open Properties and set Additional Include Directories for them:
VisualGDB will then ask CMake for the location of all target_include_directories statements related to the selected targets and will edit them or create new ones if none were found:
This works in both directions: if you manually add or edit similar statements in CMakeLists.txt files, VisualGDB will still recognize them, display their contents in VS property pages and let you edit them.
Editing Linux Projects via SSH
As the new CMake project subsystem works independently from the regular Visual C++ projects and all file and IntelliSense operations are under VisualGDB’s control, the sources don’t have to be physically located on the Windows machine anymore. So we added a special mode that lets you create (or import) CMake projects directly on the Linux machine without setting up any shared folders:Visual Studio will recognize the special vgdb-ssh://… URLs and let VisualGDB handle them, while the rest of the Visual Studio will treat those files as if they were located on the Windows machine. To avoid downloading the same files over and over, VisualGDB caches them locally and periodically determines if any of them are outdated by running the “ls” command in the background. This results in great performance and extremely accurate IntelliSense – it will understand Linux paths and will always use the latest versions of the headers:
Importing Existing Projects
Because the project structure used by VisualGDB is accurately reported by CMake and does not rely on any specific layout of the CMakeLists.txt files, the new CMake Project Subsystem supports opening huge 3rd-party projects as long as they are based on CMake. VisualGDB will locate and display the targets, sources and settings the same way as for projects created from scratch:
When combined with the direct SSH file access, this lets you quickly open any CMake-based project on your Linux machine from Visual Studio and immediately begin developing it as if it was a normal Windows project. We have also added a special diagnostics console that shows the internal status of the cache and calculates the exact time spent on fetching files and listing directories on the Linux machine to make timing analysis easier: