{"id":15825,"date":"2017-05-10T12:01:04","date_gmt":"2017-05-10T19:01:04","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/?p=15825"},"modified":"2021-01-05T10:06:51","modified_gmt":"2021-01-05T10:06:51","slug":"linux-cross-platform-and-type-visualization","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/linux-cross-platform-and-type-visualization\/","title":{"rendered":"Linux C++ improvements for cross-platform code sharing and type visualization"},"content":{"rendered":"<p><a href=\"http:\/\/aka.ms\/vslinux\">In Visual Studio 2017 we introduced the Linux development with C++ workload<\/a>. This tutorial is going to walk through some of the improvements we have made in the 15.2 release using the classic spinning cube demo from <a href=\"http:\/\/lousodrome.net\/opengl\/\">Julien Guertault\u2019s OpenGL tutorial<\/a>. We have shown <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/linux-development-with-c-in-visual-studio\/\">how to use this OpenGL demo in our Linux workload<\/a> before. What we are showing here is how to use this as a single source base for both Windows and Linux using Shared Items in Visual Studio. From there we will show off some improvements we have made to debugger type visualization for Linux C++, for both natvis and Python pretty printing.<\/p>\n<h2>C++ cross-platform code sharing with shared items<\/h2>\n<p>Shared Items Projects were introduced in Visual Studio 2015 Update 1 to share cross platform C and C++ code between projects that targeted specific platforms. We introduced them by <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2015\/07\/30\/cross-platform-code-sharing-with-visual-c\/\">showing how Shared Items can be used for common code across Android, iOS and Universal Windows Platform<\/a>. We now also have support for Shared Items with our Linux C\/C++ projects.<\/p>\n<p>To try this out you will need to have at minimum Visual Studio 2017 15.2 installed with the Desktop C++ and Linux development with C++ workloads installed. For the Linux portion you will need a Linux machine that has the following libraries installed.<\/p>\n<pre>sudo apt-get install libgles1-mesa libgles1-mesa-dev freeglut3 freeglut3-dev<\/pre>\n<p>You will want to <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2016\/03\/30\/visual-c-for-linux-development\/#includes\">copy your include files locally to your Windows box for enabling IntelliSense<\/a> as well (after adding those libraries).<\/p>\n<p>To get started create a new solution and choose Shared Items Project under Visual C++ -&gt; General, name the Solution and Project CrossPlatCube. \u00a0Get the source for Spinning Cube from\u00a0<a href=\"http:\/\/lousodrome.net\/opengl\/\">Julien Guertault\u2019s OpenGL tutorial<\/a>. Extract it and add main.c to your project as main.cpp.\u00a0Now add a new project to your solution and choose Visual C++ -&gt; Empty Project and name it WindowsCube. Now right click on References and choose add reference. In the dialog choose Shared Projects and select CrossPlatCube. We\u2019re not going to add any source to this project, we\u2019re just using it to build the source in the Shared Items project. To do so <a href=\"http:\/\/www.transmissionzero.co.uk\/software\/freeglut-devel\/\">get the prebuilt OpenGL libraries from Martin Payne\u2019s site<\/a>. Extract these on your machine and in the project properties of the WindowsCube project add references to the include and library directories under VC++ Directories to enable IntelliSense. You will also need to provide the include directory location in the project properties under General -&gt; Additional Include Directories and the location of freeglut.lib under Linker -&gt; Additional Dependencies. You should now be able to build and run the WindowsCube project and see the spinning cube.<\/p>\n<p>Now add a new Empty Project (Linux) to the solution from Add -&gt; New Project -&gt; Visual C++ -&gt; Cross Platform -&gt; Linux and name it LinuxCube. Add a reference to the CrossPlatCube project as you did for the empty Windows project. Before moving on open main.cpp from the CrossPlatCube project if it is not currently open. Note under the file name tab there is a context menu, if you drop this down and select the WindowsCube project you will see that there are purple squiggles for many items because we have not added the include location for the Linux project yet. The purple indicates these are not syntax errors with the current platform project context, but are errors in another context the shared items code is used in. If you switch the context to the LinuxCube project the squiggles will be red indicating they are errors in this context.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/linuxsharing.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-15835\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/linuxsharing.png\" alt=\"linuxsharing\" width=\"651\" height=\"295\" \/><\/a><\/p>\n<p>Now open your Project Properties make sure under General you have the correct remote machine selected and add your local folder with your Linux include files under VC++ Directories -&gt; Include Directories. On the Debugging Property Page add export DISPLAY=:0.0 to the Pre-Launch command. Under the Linker Input Property Page add the library dependencies: m;GL;GLU;glut. Now right click the Linux project and set it as the startup project. You should now be able to build and run it on your Linux machine using the same code that you built your Windows app from.<\/p>\n<p>You\u2019ve already seen some basic IntelliSense, build and launch\/debug capabilities in the above example using Shared Items across platforms. Shared Items also give you platform specific Semantic colorization, Quick Info, Parameter Help and Member List results that are specific to that selected project\u2019s platform. That\u2019s not all though, browsing and refactoring support functionality like Go to\/Peek definition\/declaration, Find all References, Call Hierarchy and Class View are all also available for any platforms you project targets. You\u2019ll be able to easily navigate deeply into platform specific headers and back to your shared source.\u00a0 You can <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2015\/07\/30\/cross-platform-code-sharing-with-visual-c\/\">read more about these capabilities in this shared items post<\/a>.<\/p>\n<h2>Debugger types visualization improvements<\/h2>\n<p>Another area we have improved in Visual Studio 15.2 is debugger types visualizations for Linux C\/C++. This has been done using both Visual Studios natvis format that provides visualizations of C\/C++ types and supporting Python pretty printing in GDB. We\u2019ll talk about nativs first. To get something interesting to look at lets add some usage of libstdc++ types to the cube example.<\/p>\n<p>Add these includes and arrary to main.cpp in the CrossPlatCube project.<\/p>\n<pre>#include &lt;vector&gt;\r\n#include &lt;array&gt;\r\n\r\nstd::vector&lt;std::array&lt;GLfloat, 6&gt;&gt; vertices = {\r\n\u00a0\u00a0\u00a0 { 0, 0, 0, -1, -1, -1},\r\n\u00a0\u00a0\u00a0 { 0, 0, 1, -1, -1, 1},\r\n\u00a0\u00a0\u00a0 { 0, 1, 1, -1,\u00a0 1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 0, 1, 0, -1,\u00a0 1, -1 },\r\n\u00a0\u00a0\u00a0 { 1, 0, 0, 1, -1, -1 },\r\n\u00a0\u00a0\u00a0 { 1, 0, 1, 1, -1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 1, 1, 1,\u00a0 1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 1, 0, 1,\u00a0 1, -1 },\r\n\u00a0\u00a0\u00a0 { 0, 0, 0, -1, -1, -1 },\r\n\u00a0\u00a0\u00a0 { 0, 0, 1, -1, -1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 0, 1, 1, -1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 0, 0, 1, -1, -1 },\r\n\u00a0\u00a0\u00a0 { 0, 1, 0, -1,\u00a0 1, -1 },\r\n\u00a0\u00a0\u00a0 { 0, 1, 1, -1,\u00a0 1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 1, 1, 1,\u00a0 1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 1, 0, 1,\u00a0 1, -1 },\r\n\u00a0\u00a0\u00a0 { 0, 0, 0, -1, -1, -1 },\r\n\u00a0\u00a0\u00a0 { 0, 1, 0, -1,\u00a0 1, -1 },\r\n\u00a0\u00a0\u00a0 { 1, 1, 0, 1,\u00a0 1, -1 },\r\n\u00a0\u00a0\u00a0 { 1, 0, 0, 1, -1, -1 },\r\n\u00a0\u00a0\u00a0 { 0, 0, 1, -1, -1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 0, 1, 1, -1,\u00a0 1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 1, 1, 1,\u00a0 1,\u00a0 1 },\r\n\u00a0\u00a0\u00a0 { 1, 0, 1, 1, -1,\u00a0 1 },\r\n};<\/pre>\n<p>Now at what was line 45 where this comment is remove the calls to glCoror3f and glVertex3f and replace them with a for loop over the array as so.<\/p>\n<pre>\u00a0\u00a0\u00a0 \/* Every four calls to glVertex, a quad is drawn *\/\r\n\u00a0\u00a0\u00a0 for (auto vertex : vertices)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 glColor3f(vertex[0], vertex[1], vertex[2]);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 glVertex3f(vertex[3], vertex[4], vertex[5]);\r\n\u00a0\u00a0\u00a0 }<\/pre>\n<p>Set a break point in the for loop and run the application on Linux. If you are on Visual Studio 2017 15.1 or earlier if you were to expand the for range it would look something like this.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/typebefore.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-15845\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/typebefore.png\" alt=\"typebefore\" width=\"679\" height=\"353\" \/><\/a><\/p>\n<p>That\u2019s quite deep before you get to your data. In Visual Studio 2017 15.2 it now looks like this.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/typesnatvis.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-15855\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/typesnatvis.png\" alt=\"typesnatvis\" width=\"681\" height=\"350\" \/><\/a><\/p>\n<p>Much easier to get to your data and the actual type information you care about.<\/p>\n<p>We are providing a natvis visualizer for libstdc++ that will work with both the default gdbserver and gdb modes of Linux projects in Visual Studio 2017. <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2015\/09\/28\/debug-visualizers-in-visual-c-2015\/\">This post describes how to build your own visualizers using natvis here<\/a>, once created just add the file to your project root and it will be picked up and used. You can also still get to the raw view as opposed to the visualized view if you need it.<\/p>\n<p>We\u2019ve also added support for Python pretty printers using gdb mode. You can <a href=\"https:\/\/gcc.gnu.org\/onlinedocs\/libstdc++\/manual\/debug.html\">learn more about Python pretty printing from the GNU site<\/a>, but basically this is the way that visualizations for types are enabled in GDB. It was introduced in GDB 7.0 and printers have shipped with GCC since version 4.5 for libstdc++. If you are using something older you may need to take additional steps to enable them. Other libraries on Linux may or may not provide printers, but similarly to natvis you can write your own. Let\u2019s look at the same example as above.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/typespythonprinter.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-15865\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/typespythonprinter.png\" alt=\"typespythonprinter\" width=\"682\" height=\"350\" \/><\/a><\/p>\n<p>Here you can see what was the raw view is now neatly visualized using what came back from the built in Python pretty printer on Linux. Here I have expanded to the same element in the array as the above examples. At each expansion level you can see the Visualized View that shows the natvis visualization is present, unexpanded here.<\/p>\n<p>Python pretty printing is on by default. If you experience any performance problems with this (large arrays etc.) it can be deactivated under project properties -&gt; Debugging -&gt; Enable Python Pretty Printing).<\/p>\n<h2>Wrap up<\/h2>\n<p>We hope these improvements make our Linux C\/C++ support more useful to you. You can <a href=\"http:\/\/aka.ms\/vslinux\">find out more about our Linux C\/C++ support here<\/a>. <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2016\/03\/30\/visual-c-for-linux-development\/#reporting\">As always, we love to hear from you<\/a>, what doesn\u2019t work but also what does and how you are using it. We are continuing to make investments to improve our Linux C\/C++ story and can\u2019t wait to show you what we\u2019re working on now.<\/p>\n<p>&#8212; Marc Goodner, <a href=\"https:\/\/twitter.com\/robotdad\">@robotdad<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Visual Studio 2017 we introduced the Linux development with C++ workload. This tutorial is going to walk through some of the improvements we have made in the 15.2 release using the classic spinning cube demo from Julien Guertault\u2019s OpenGL tutorial. We have shown how to use this OpenGL demo in our Linux workload before. [&hellip;]<\/p>\n","protected":false},"author":677,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-15825","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>In Visual Studio 2017 we introduced the Linux development with C++ workload. This tutorial is going to walk through some of the improvements we have made in the 15.2 release using the classic spinning cube demo from Julien Guertault\u2019s OpenGL tutorial. We have shown how to use this OpenGL demo in our Linux workload before. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/15825","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/677"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=15825"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/15825\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=15825"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=15825"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=15825"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}