Welcome to MSDN Blogs Sign in | Join | Help

VS Project Blog Moving

We aren’t going away -- we’re just moving to a better home. To give you even more news, articles, and walkthroughs on Visual Studio, the VS Project Team blog is moving to become part of The Visual Studio Blog.  As part of The Visual Studio Blog, we’ll be joining the rest of the Visual Studio Platform Team in blogging not only about Visual Studio Project, but other topics such as the core IDE and UI, the editor, extensibility, MSBuild, and more. 

So please make sure to update your RSS readers to our new home. 

See you all at the new blog location – http://blogs.msdn.com/visualstudio!

Posted by Brian Tyler | 0 Comments

Minify your EmbeddedResource .js and .css files in your MSBuild project

If you write a C# or VB.NET class library that contains ASP.NET controls that also have .js or .css files embedded in your assembly, you probably want to minify those files for optimal download size in production, but keep the files readable for coding and debugging.  What if you could add a single <Import> to your class library’s project file that would automatically minify these files in Release builds, while leaving them untouched in debug builds?

Well, I wrote a .targets file and associated MSBuild task that uses Dean Edwards’ excellent Packer algorithm to make .js files really small.  Just import the .targets file right after your last <Import> and you’re done.

You can get it here:

http://teamcity.dotnetopenauth.net:82/project.html?projectId=project3

Just click "Artifacts" then "Download all (.zip)" in the upper-right corner.

Or the source for it if you're interested:

http://github.com/AArnott/JavascriptCssPackerTargets

Just click the "download" button to get it as a zip file.

Please take this as a tip and not an endorsement.  This is not a Microsoft product—it’s just an open source project that I wanted to point out to you for you to evaluate whether it’s appropriate for your project.  As far as the license goes, this MSBuild task uses code from Dean Edwards that is under the LGPL license, so the whole MSBuild task .dll ships under the LGPL license.  While I don’t interpret that to mean that your shipping project must be under any particular license, you should consult your own attorneys and not take my word for it.

Microsoft Development Tools Ecosystem Summit

If there is one thing Microsoft is really good at, it is creating really long names for things :)

But the name aside, I just wanted to add my call to what is likely to be several blog posts about this upcoming event starting on October 19th. VS 2010 has had a major focus on extensibility and making it easier for others to extend and enhance experiences in the tool. If you are involved in such activities, we'd love to meet you in person and help you get started on 2010. You can find more information about the event here.

This fall, Microsoft is hosting a developer conference at the Microsoft Conference Center in Redmond, Washington to teach developers how to extend Visual Studio. Visual Studio is an open, extensible platform that can be customized for everything from individual productivity tools to enterprise-wide development needs. The Visual Studio Shell enables developers to leverage a world class IDE to build specialized tools for any number of vertical industries, and can even be custom-branded with your own splash screen and app icon. The conference is open to all developers on October 19th and 20th to learn how to extend Visual Studio 2010. October 21st through October 23rd is a private event for VSIP program members under NDA to receive exclusive business and technical content.

Posted by Brian Tyler | 5 Comments

We're Still Here!

Sorry for our absence in the last couple of weeks - we've had some internal deadlines to hit and so everyone on the team has been really swamped. However, things are calming down again so I hope to have some new posts up soon. Feel free to post up requests for any topics you'd like to see.

 Thanks for reading!

Posted by Brian Tyler | 7 Comments

Enable C++ project system logging

The new Visual C++ project system in Visual Studio 2010 leverages the .NET System.Diagnostics trace logging feature to help users investigate why certain operations have failed or just to better understand what is happening behind the scenes. 

Here are some features that VC++ logs lots of messages about so you can diagnose any bad behavior:

  1. Design-time build failures, such as project, COM, or assembly references that won’t resolve
  2. Project filters
  3. IDE build up-to-date check

In order to avoid negatively impacting performance in the common case where you don’t care to review the trace logs, we only emit the trace messages when a user “opts in” to logging these messages.  To enable logging in the Visual C++ project system you just have to add a snippet to a .config file:

  1. Since it can be difficult to recover from a damaged devenv.exe.config file, consider copying the file to devenv.exe.config.original before modifying it so you have a backup copy you can revert to if things go awry.
  2. Open a text editor with admin privileges.
  3. Open your %PROGRAMFILES%\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe.config file.  Note this will be in %ProgramFiles(x86)% on 64-bit Windows.
  4. Add this snippet to your devenv.exe.config file just below the <configSections /> block:
    <system.diagnostics>
      <switches>
        <add name="CPS" value="4" />
      </switches>
    </system.diagnostics>
    
  5. Save the text file.

You can find out more about setting traceswitch verbosity levels on MSDN.  Why the name “CPS” for our trace switch?  Just an implementation detail for this release.

Now that we’ve enabled logging of VC++ messages, we need a way to view them.  You have a few options here.  You can pick any ONE of the following:

  1. Configure the System.Diagnostics trace to be logged to a text file.
  2. DebugView is a free Sysinternals tool that displays all log messages on screen and doesn’t require any installation.
  3. Attach a debugger to the devenv.exe process (perhaps another instance of devenv.exe) and watch the Debug pane of the Output window (Debug –> Windows –> Output).

Regardless of how you view the resulting log messages, you may find that they are quite verbose.  Many services in Visual Studio 2010 log messages and many of these are “on by default” (VC++ logging is off by default, which is why we modified the .config file).  Try a keyword search to scan for the messages that you’re interested in and then scan through the surrounding messages to find the ones that can help identify whatever you’re investigating.

Here’s a sample picture of DebugView showing the relevant log message explaining why a special project type doesn’t get standard up-to-date check behavior in the IDE:

image

Posted by andarno | 3 Comments
Filed under: ,

VC++ Directories

The goal of this post is to quickly explain what VC++ Directories are, what happened to them in VS 2010 and why the change was made.

Life in VS 2008

To start with, let’s take a look at the VS 2008 feature of VC++ Directories. If you were to go to the Tools->Options menu, you would see the following under the Project and Solutions settings

These are the IDE equivalents to the command line environment variables of PATH, INCLUDE, etc. However, these values only apply within the IDE or vcbuild.exe – they don’t apply when executing cl.exe, for example, directly from the command line. Additionally, as you can see from the Platform dropdown at the top of the dialog, you can customize these settings for each platform.

The implementation for these settings is to store the values in the VCComponents.dat file stored in %LOCALAPPDATA%\Microsoft\VisualStudio\9.0. Looking at the file, you’ll notice two things. First, it is in the LocalAppData directory, which means the settings are per-user, per-machine. The second thing you’ll notice is that the file is in an INI format, not the XML of a .vcproj file. This shows that the importing of the .dat file is some custom code of vcbuild.exe and the IDE.

Changes in VS 2010

The first thing you’ll notice in VS 2010 when working with VC++ Directories is that they appear to have disappeared. When you go to the Tools->Options window and look in Project and Solutions, you’ll see the window looks very similar to the screenshot above – only VC++ Directories is gone. However, if you bring up a VC++ project in the IDE and open the project properties window (right-click on the project node and select Properties), you will notice a Rule called VC++ Directories (Rules are the tree of selections on the left pane of the property page window) and that the values you see are the same defaults that you would get from VS 2008. Additionally, you can edit these properties in the same way as any other project property (including using the macro editor as shown – something not possible in VS 2008).

Of course, any edits you make right here are applied directly to the project you are working on – and directly to the project file itself. This means that the edits are NOT per-user, per-machine as they were in VS 2008. However, that option still exists in the form of a property sheet (If you don’t know about property sheets or how they work in VS 2010, I recommend reading my previous post about them here).

If you open up the Property Manager view to see the property sheets associated with your project, you’ll see that one of the property sheets is named Microsoft.Cpp.Win32.User. This property sheet is actually stored in LocalAppData, just as VCComponents.dat file was, in the directory %LocalAppData%\Microsoft\VisualStudio\10.0. Using the property editor on the property sheet (just right-click on this property sheet node and select Properties…), you can see that you are able to make edits directly to this file. Since all projects, by default, import this property sheet, you are effectively editing the VC++ directories in the same way you were able to do before.

Additionally, you can also delete the reference to this per-user, per-machine property sheet and create your own set of property sheets that set these values. Deleting the reference to this property sheet makes your project operate independently of any per-user, per-machine settings – and important step when trying to ensure correct behavior in a SCC (source code control) environment.

Why the Changes?

A reasonable question would be to ask why these changes were done. There are several reasons.

  1. VS 2008 VC++ Directories were applied to all projects loaded on that machine and could not be stopped.
    This is probably the biggest reason for the change. We’ve had many customers complain that they had different projects with very different setups. As you are probably well aware, the order that directories are listed for things like PATH and INCLUDE can have dramatic effects on the results of builds and being unable to customize these values easily on per-project (or groups of projects) basis required many unfortunate hacks by our customers.
  2. VS 2008 VC++ Directories were per-user, per-machine and made SCC enlistments fragile.
    Imagine that you want to be able to check in your entire project system – not just the source files and project files, but the entire build system as well. If you could do that, then you could go up to any machine with only the SCC system installed, check out the project system and build. However, if your build was dependent on settings that were per-machine, as in the case of VCComponents.dat, that was impossible. Instead, by deleting the reference to the per-user property sheet, a VS 2010-based build system can be made fully enlistment-based – a key feature we wanted to provide in VS 2010.
  3. VC 2008 VC++ Directories were inconsistent with the rest of the build technology.
    This is a minor, but satisfying, improvement. The VCComponents.dat was an INI based file that was hard-wired into the vcbuild engine, whereas the property sheet is a standard MSBuild file that uses the build-in rules of any MSBuild import – learning the one MSBuild language is all that is required. As a side benefit, the editing experience of the VC++ directories is also made consistent by moving the editor into the property editor.

A Note About Import/Export Settings

As part of moving the VC++ Directories out of the Tools->Options and into property sheets, I should also note that this means they are no longer considered part of VC++ Settings in Visual Studio. The settings are meant for IDE specific configuration settings, and VC++ Directories are now built-in directly to the build process and are found via standard property sheet mechanisms. Therefore there is no longer any need to have these participate in import/export – they are put into a single property sheet file (by default) that can be shared between different versions of VS – and work the same both inside and outside of the IDE.

The one exception to this is migration – if you migrate your settings from VS2008, the VC++ directories from the earlier version will be migrated up and into the per-user property sheet file for you.

For SDK Authors

As a closing remark for those of you out there that would edit the VC++ Directories as part of your SDK installation. That scenario is still supported – either via the VCProjectEngine APIs or by directly editing the new property sheet (see the MSBuild APIs for simply editing access). However, I would also urge you to think anew about what it means to install your SDK.

The VC++ Directories approach does provide a way to install your SDK into the user’s build system, but it has a few major drawbacks.

  1. You can’t uninstall – at least not easily – given the other changes that the user may have done since the install.
  2. You are automatically applied to all projects, whether they want to use your SDK or not.
  3. In VS 2010, you are no longer necessarily applied to all projects because the per-user property sheet link may have been removed.

Instead, think about how you can provide the options for customers to enable you in their projects. For example, if you provide your own property sheets than can be added into the customers projects on demand, then the user has control over their environment – and you can also be checked into the SCC enlistment, enabling the enlistment scenario described earlier.

The downside of this approach, of course, is that the SDK isn’t immediately available after installation. This is an opt-in model. But using the tool extensibility, controlled by switches, you can also create a system that is an opt-out as well. Basically, the new directories design combined with the new extensibility model provides a lot of flexibility. We’d love to work with all the SDK providers to try to come up with some best practices and patterns – so drop us a line!

Posted by Brian Tyler | 31 Comments

Inherited Properties and Property Sheets

In my last post, I talked at length about the various types of MSBuild elements – items, properties, imports, etc. One of the things that I said I would get around to in a later post was to explain what I meant by “inherited properties”, where they came from and how you can create your own. Well, I’m slow but I’m finally getting around to it!

What you are going to learn is how to take advantage of one of the most powerful – but lesser known – features of VC++ Projects: Property Sheets. And if that isn’t enough for you – you’ll also learn the foundations needed to understand my next post…What happened to VC Directories?!?!!?

The above image is straight out of a new Win32 Console application project property window. Notice how some of the property values (Debug Information Format and Warning Level) are bolded while others are not? What this means is that the values that are bold in value are defined in the .vcxproj (or associated .user file), while the other values are inherited from another file. How does that work? As I said in my previous post, an MSBuild file can import other files – just like a #include for a header file. In this case, if you open your .vcxproj file, you’ll see an import for Microsoft.Cpp.default.props and Microsoft.Cpp.props. Pretty much all of your inherited property values in a new VC++ project comes from these files – or their imports.

What this allows Microsoft to do is define the defaults in a set of files that all projects import – and therefore not have to replicate them in everyone’s project file. The trick is, you can do the exact same thing – it’s called Property Sheets.

A property sheet is simply an MSBuild file that you import into your project that defines some property values. But because it is a separate file, it can be shared among multiple projects, allowing you to centralize some settings and perform a central edit operation. Examples of where this is useful are

  • Setting build conventions for teams, such as warning levels, use of exceptions and optimization settings.
  • Setting system information, such as the include and library paths for an SDK you might consume.
  • Feature settings, such as the various properties to set when using Unicode or Ansi strings.

The system is open, so you can use it for pretty much whatever takes your fancy.

Of course, to make it really useful, we need to allow you to work with them inside the IDE. To see property sheets in action, bring up the Property Manager window. This may already be in your windows next to the solution explorer – or you can bring it up from the View->(Other Windows)->Property Manager (whether it is in Other Windows or not depends on what profile you selected when you first started Visual Studio).

What you’ll notice is that it is somewhat like the solution explorer – it lists out all of the VC++ projects in the solution. However, rather than source files, it shows property sheet “sources”, grouped by their configurations. In this case, you can see that there are four existing property sheets by default for a new Win32 console application project. For each of them, you can right-click and bring up the property window just as you did for the project earlier. Now, however, it shows the settings that are known about by the property sheet you have selected (Microsoft.Cpp.Win32.user is shown below).

Some things to notice about this window

  1. The Configuration and Platform selections are grayed out.
    This is because you select them automatically when you click on the property sheet in the Property Manager window. (Yes, I know this is inconsistent and a bit strange, but it’s the way it’s been since property sheets arrived – so until we do a larger UI overhaul, consider it a lovely quirk).
  2. Some properties are still not bolded.
    Editing a property sheet is like editing a project – it can have it’s own property sheets that are providing defaults.
  3. There are a lot more rules (left column of C/C++, Linker, etc).
    This is because in a project view, we only show rules that apply to the project as it is…if you have no .rc files, then we don’t show the Resources rule. Property Sheets, however, can be applied to multiple projects and therefore we don’t filter out any known rule.

Now, you may notice that if you selected one of the property sheets that has an icon that looks like a computer with a sheet in front of it, that everything was read-only. That is because these are System Property Sheets. Simply, a system property sheet is one that is provided by the build system automatically (part of the Microsoft.cpp.props for example) and therefore is not meant to be edited. That doesn’t mean you can’t override their values in a property sheet or project file – only that you can’t edit the system property sheet itself. It is displayed only so that you can see what those sheets contribute.

Okay, so let’s create our own property sheet to get the feel for it. First thing to do is to select a context in the property manager window – if you pick a project, the property sheet is applied to all config/platform settings. If you pick a specific config/platform, then obviously it would only apply for that one. Anyway – go ahead and right-click and select “Add New Project Property Sheet'” and follow the wizard. The only real thing to note here is that you have to say where the file should be located. Remember, the value of a property sheet is that it can be shared between multiple projects so a common directory near the top of your solution source is probably a good idea.

You should now have 5 property sheets – 3 system property sheets and two user property sheets. You might be wondering whether or not the order of them in the list has any importance (if not, go ahead and do it now, we’ll wait….Hey, did you know it rains a lot in Seattle? How about those Seahawks, eh?).

Ah, your back! Great – I can now cease your wondering by me saying that yes, indeed, the order matters. What the order is telling you is that the property sheet at the bottom is applied first, then the next and the next, so on up the list. This means that your newest property sheet will be applied last – just before the project itself is evaluated. If you want to change that ordering, just right-click on the property sheet and select either “Move Earlier in Evaluation” or “Move Later in Evaluation”.

An important note: Notice how “Move Earlier in Evaluation” is grayed out above? That is because not only are system property sheets read-only, they also are read-only when it comes to ordering.

Now here is another trick – try right clicking on a property sheet and selecting “Add New Project Property Sheet” (as also visible above). The result is a child property sheet. Again, you have control over the evaluation ordering, just remember that move earlier/later on children obviously only affect the group of children sheets. Similar to the main list, children are evaluated from the bottom up – and all the children of a parent are evaluated just before the parent itself is evaluated.

Just two more things to say about property sheets at this point.

  1. Notice how the right-click context menu above has a “Save” option? Yes – I’m afraid that property sheets are not owned by a project and therefore saving a project does not save property sheets – so they have their own save command. All I can say is (a) it was that way in VS 2008 and that (b) addressing some of the UI hiccups is high on my own priority list for the next release…back me up on this one!
  2. Microsoft.Cpp.Win32.user is a special – but optional – property sheet. This guy lives in your LocalAppData directory and is automatically part of any new or upgraded project. Therefore anything set in this property sheet, by default, applies to ALL projects. We’ll get more into him in a following post on “What the heck happened to the Tools->Options VC Directories?”

To complete the circle, set a property value in your new property sheet and then go back to the project properties window and you should see your value showing up – and not-bolded – proving the inheritance.

So there you have it, Property Sheets in a nut-shell. I’ll be honest with you – these aren’t the easiest things to understand when you first come across them – make sure to play around with them a bit to get a feel and post up any questions you have. Once you get the hang of them, you’ll wonder how you ever did anything without them.

Up next (from me anyway) – The prodigal VC Directories returns.

Posted by Brian Tyler | 5 Comments

Insights into the VC++ Project System (Channel 9 Video)

Bogdan Mihalcea is a developer on the VC++ build and project system team and he's been working on the new project and build system for VC++. He has some great insight to share about the architecture and the advantages that VC++ developers can leverage from the new MSBuild based project system. Tune into http://channel9.msdn.com/posts/Charles/Bogdan-Mihalcea-The-New-VC-ProjectBuild-system-MSBuild-for-C/ to learn more!
Posted by Brian Tyler | 1 Comments

Platform extensibility - Part 2

In my previous blog post on platform extensibility, I introduced you to the data-driven nature of the property pages UI. I explained how a collection of xml files drives the UI but stopped short of describing the contents of these files. I'll continue from where I stopped in that post and describe the format of one such xml file so that you have enough information to confidently author your own. The contents of this post will also come in handy when I discuss Build Customizations in my upcoming post.

To recall, every top level node under Configuration Properties in the property pages UI (such as C/C++, Linker, etc) is called a Rule. Each Rule generally has multiple Category nodes under it and each Category node houses a bunch of properties, frequently displayed as a property grid on the right pane in the UI.  Underlying every Rule, there is an xml file from which the UI sources its data and some rendering information. This xml file represents a UI-independent data model for a Rule and its properties, although as we will see a few very common UI terms do make their way into this file.

I'll use the %ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\cl.xml file to realize my goal for this post. You may want to open it in notepad or, to get the nice color formatting, in VS. The first thing to know about this xml file is that it is in the XAML format. At this stage, XAML is just a convenient xml format to express information and has no other significance. The property page UI is built using WinForms and not WPF, hence we do not utilize the XAML-driven WPF architecture although that is the direction we would like to head in the future.

If you stripped cl.xml of all data, you will end up with the following skeleton:

<?xml version="1.0" encoding="utf-8"?>

<Rule>

 

  <Rule.DataSource />

 

  <Rule.Categories>

    <Category />

        ...

  </Rule.Categories>

 

  <BoolProperty />

  <EnumProperty />

  <IntProperty />

  <StringProperty />

  <StringListProperty />

        ...

       

</Rule>

 

In other words, a property page xml generally contains a Rule declaration which in turn includes the declarations for a bunch of categories, a data source and most importantly a collection of properties of various types. The snippet above shows the five possible types a property can have. In what follows, we will explain each of these major elements while showing some of the metadata that can be attached to them.

1.       Rule:  Rule is generally the lone root node in the xml file. A Rule can have many attributes defined on it. The following snippet from cl.xml shows many of them.

<Rule Name="CL" PageTemplate="tool" SwitchPrefix="/" Order="10"

          xmlns="http://schemas.microsoft.com/build/2009/properties"

          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

          xmlns:sys="clr-namespace:System;assembly=mscorlib">

  <Rule.DisplayName>

    <sys:String>C/C++</sys:String>

  </Rule.DisplayName>

 

I'll briefly describe the attributes you see above:

a.       Name: The Name attribute is an id for the Rule. It needs to be unique among all the property page xml files for a project.

b.      PageTemplate: The value of this attribute is used by the UI to choose from a collection of UI templates. The "tool" template renders the properties in a standard grid format. Other in-built values for this attribute are "debugger" and "generic".  See the Debugging node and General node, respectively, to see the UI format resulting from specifying these values. The UI for "debugger" page template uses a drop-down box to switch between the properties of different debuggers whereas the "generic" template displays different property categories all in one page as opposed to having multiple category sub-nodes under the Rule node. This attribute is just a suggestion to the UI; the xml file is designed to be UI independent. So, a different UI could use this attribute for different purposes.

c.       SwitchPrefix: This is the prefix used in the command line for the switches. A value of "/" would result in switches that look like /ZI, /nologo, /W3, etc.

d.      Order: This is a suggestion to a prospective UI client on the relative location of this Rule compared to all other Rules in the system.

e.      The namespaces: This is a standard XAML element. You can see three namespaces listed. These correspond to the namespaces for the XAML deserialization classes, XAML schema and system namespace, respectively.

f.        DisplayName: This is the name that is shown on the property page UI for the Rule node. This value is localized. We created DisplayName as a child element of Rule rather than as an attribute (like Name or SwitchPrefix) because of internal localization tool requirements. From XAML's perspective, both are equivalent. So, you can just make it an attribute to reduce clutter or leave it as it is.

g.       DataSource: This is a very important property that tells the project system the location from which the property value should read from and written to, and its grouping (explained below).  For cl.xml, we have

       <DataSource Persistence="ProjectFile" ItemType="ClCompile" Label="" HasConfigurationCondition="true" />

 

Persistence="ProjectFile"  tells the project system that all properties for the Rule should be written to the project file or the property sheet file (depending on which node was used to spawn the property pages). The other possible value is "UserFile" which will write the value to the .user file.

ItemType="ClCompile" says that the properties will be stored as ItemDefinition metadata or item metadata (the latter only if the property pages were spawned from a file node in solution explorer) of this item type. If this field is not set, then the property is written as a common property in a PropertyGroup.

Label="" indicates that when the properties are written as ItemDefinition metadata, the label of the parent ItemDefinitionGroup will be empty (every MSBuild element can have a Label). In VS 2010 we use labeled groups to delineate the VC++ project file. I'll go over the ordered layout design of the .vcxproj file in a later post.  Getting back to the Label attribute, note that the groups housing most Rule properties do not have a label (or in other words, they have the empty string as the label).

HasConfigurationCondition="true" tells the project system to affix a configuration condition to the value so that it takes effect only for the current project configuration (the condition could be affixed to the parent group or the value itself). E.g. open the property pages off the project node and set the value of the property Treat Warnings As Error under Configuration Properties > C/C++ > General to Yes. The following value is written to the project file. Notice the configuration condition attached to the parent ItemDefinitionGroup.

<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

  <ClCompile>

    <TreatWarningAsError>true</TreatWarningAsError>

  </ClCompile>

</ItemDefinitionGroup>

 

If this value were set in the property pages spawned off a file, say stdafx.cpp, then we would have the property written under the stdafx.cpp item in the project file as shown below. Notice how the configuration condition is directly attached to the metadata itself.

<ItemGroup>

     <ClCompile Include="stdafx.cpp">

       <TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</TreatWarningAsError>

     </ClCompile>

   </ItemGroup>

 

Another attribute of DataSource not listed above is PersistedName. If you wish to represent a property in the project file using a different name, this attribute will hold that different name. By default this attribute is set to the property's Name since most properties are likely to be stored as themselves in the project files.

I'll end the description of the DataSource attribute by mentioning that an individual property can override its parent Rule's DataSource to point to a different data source. In that case,  the location for that particular property's value will be different from other properties in the Rule.

There are other attributes of a Rule such as Description,  SupportsFileBatching, etc that are not shown here. The full set of attributes applicable to a Rule or on any other element can be obtained by browsing the msdn documentation for these types (currently, the descriptions included in these pages are sparse, but they should be accrue over time). Alternately, they can be gleaned by examining the public properties on the types in the Microsoft.Build.Framework.XamlTypes namespace living in the Microsoft.Build.Framework .dll assembly (you can use ildasm.exe for this purpose if you wish).

DisplayName, PageTemplate, Order are few UI related properties that are present in this otherwise UI-independent data model. That is fine since these are not tied to a particular UI technology. Further, these are almost certain to be used by any UI that is used to display the property pages.

DisplayName and Description are two properties that are present on almost all elements in the xml file. And these are the only two properties that are localized (localization of these strings will be explained in a later post).

2.       Category: A Rule can have multiple Categories. The order in which the categories are listed in the xml file is a suggestion to the UI to display the categories in the same order. E.g. the order of the categories under the C/C++ node as seen in the UI - General, Optimization, Preprocessor, ...  - is the same as that in cl.xml. A sample category looks like this:

<Category Name="Optimization">

      <Category.DisplayName>

        <sys:String>Optimization</sys:String>

      </Category.DisplayName>

    </Category>

 

The above snippet shows the Name and DisplayName attributes that have been described before. Once again, there are other attributes a Category can have that are not used above. You can know about them by reading the documentation or by examining the assemblies using ildasm.exe.

3.       Properties: This is the meat of the xml file and contains the list of all properties in this Rule. Each property can be one of five possible types shown in the XAML skeleton above. Of course, you could have only a few of those types in your file. A property has a number of attributes that allow it to be described richly. I'll explain only the StringProperty here. The rest are very similar.

<StringProperty Subtype="file" Name="ObjectFileName" Category="Output Files" Switch="Fo">

     <StringProperty.DisplayName>

       <sys:String>Object File Name</sys:String>

     </StringProperty.DisplayName>

     <StringProperty.Description>

       <sys:String>Specifies a name to override the default object file name; can be file or directory name.(/Fo[name])</sys:String>

     </StringProperty.Description>

   </StringProperty>

 

Most of the attributes in the snippet have been described before. The new ones are Subtype, Category and Switch.

a.       Subtype: Subtype is an attribute available only for StringProperty and StringListProperty; the rest of the attributes described below are applicable to any type of property. Subtype gives contextual information on this property. E.g. the value of "file" indicates that not only is this property a string, but it also represents a file path. Such contextual information can be and is used to enhance the editing experience by providing a windows explorer as the property's editor that allows the user to choose the file visually rather than type its path (which is still possible).

b.      Category: This declares the category under which this property falls. Try to find this property under the Output Files category in the UI.

c.       Switch: When a Rule represents a tool - such as the compiler tool in this case - most properties of the Rule are passed as switches to the tool executable during build time. The value of this attribute indicates the switch literal to be used. The property above specifies that its switch should be Fo. Combined with the SwitchPrefix attribute on the parent Rule, this property is passed to the executable as  /Fo"Debug\" (visible in the command line for C/C++ in the property page UI).

 

I would like to mention a few other attributes for a property that are not illustrated here. These are:

d.      Visible: If for some reason, you don't want your property to show up in the property pages (but probably still available during build time), set this attribute to false.

e.       ReadOnly: If you want to provide a read-only view of this property's value in the property pages, set this attribute to true.

f.        IncludeInCommandLine: Some properties may not need to be passed to a tool during build time. Setting this attribute to false will prevent it from being passed.

 

I hope the above description of the format of a property page XAML file has given you enough details to help you write one of your own.

Platform Extensibility - Part 1

Have you ever wanted to write a custom tool (like a custom parser or a compiler) and add it to the VC++ project system? Until now, we had three disparate ways of doing it, viz. Build Events, Custom Build Step and Custom Build Rule. These three methods were introduced in different releases of VS in the past in attempts to provide such customization.  As if that were not enough, the tools shipped by Microsoft are integrated into the system in a completely different way - by hard coding them in! In VS 2010, we have come up with a new way of adding tools to the system that is the way every tool will be added, including Microsoft shipped tools.

 

In this blog post, I'll give an overview of some aspects of this new approach of integrating tools into the system. In particular, I'll concentrate on the way the tool properties get exposed in the property page UI.

 

In VS 2010, we have a completely data-driven approach to the property page UI. Nothing is hard-coded or known innately to the system. The properties that are listed by the UI as well as some aspects of how they are rendered are based off of a richly described XML file. Let me explain this in a top-down manner. First, let us open the property pages for a project (right click on the project node in the solution explorer and choose Properties).  The UI is shown below.

 

Property page UI 

 

 Each node under Configuration Properties represent a tool or some other artifact. E.g. the C/C++ node represents the compiler tool and properties related to it, the Linker node represents the linker tool. Similarly, the Debugging node houses properties related to the debuggers. We will call each such top level node under Configuration Properties as a Rule. A Rule, in many cases, represents a tool like the compiler, but in some cases (such as debugger/code analysis) does not. We use the term Rule as an abstract term for something that has properties, executes and may produce some output.

 

Going back to the UI, we see that each Rule has a bunch of properties organized into categories. Each sub node under a Rule represents a category. E.g. the Optimization node under C/C++ houses all the optimization related properties of the compiler tool. The properties and their values themselves are rendered in a grid format on the right pane.

 

Where does the system get the list of these properties from? The answer is an information-rich XML file whose location is made available to the project. Use your Windows explorer to go %ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0 (see snapshot below). There you will find the cl.xml file. Its location is listed in Microsoft.CppBuild.targets  which is imported into the project file indirectly through a long list of target file imports starting with Microsoft.Cpp.targets (found at the end of your .vcxproj file).

 

Windows explorer in $(VCTargetsPath) 

 

Open the file cl.xml in notepad or any XML editor (see snapshot below). While you may not understand everything in it, you must be able to see in this file the contours of what the UI has displayed under the C/C++ node. You will see a root node called Rule that has the same list of properties defined under it as is displayed in the UI. The rule and every property has metadata describing it further.

 

First few lines of cl.xml 

 

Go ahead and play with this file. In fact, this XML file is loaded at run-time, so you can even make some modifications and re-start VS and see your changes (be sure to make a backup copy of the XML file if you do plan to do that). E.g. copy an existing property and change its name to Foo or something like that. See if you can find it in the property page UI after restarting VS.

 

There is one XML file corresponding to every node under Configuration Properties in the property pages UI. You can add (remove) Rules in the UI by including (removing) locations to corresponding XML files in the project (using a special item type of PropertyPageSchema; see how Microsoft.CppBuild.targets includes cl.xml).

 

Note that the XML file describes only the schema of the properties - their types, display names, some aspects of how they are rendered (such as standard grid vs. a different format) and other such metadata. The actual values themselves are written to and read from the project file or other files that the project imports. The XML file only mentions the file in which the property values must be stored.

 

It should be clear why this data driven approach equalizes the field for 3rd party tools. The system doesn't care who authors the XML file - it could be Microsoft or someone else - it just gleans information from it and displays it.

 

In future blog posts, I'll delve deeper into the XML file contents. I'll also describe how you can integrate your tool in the build process (what I described above allows only design time integration).

MSBuild Syntax and the IDE

Changing over to MSBuild as the project file format and build engine has some subtle changes. I just want to give a quick tour of the main concepts and terms so you'll be better able to work with the system - and better able to understand the new features we'll be describing over the next few weeks.

If you'd like to read this along with your project file, you can open it inside VS - just right-click on the project node in the solution explorer and select "Unload Project". Then right-click it again and select "Edit <my project>".

Definitions

Property: A simple name-value pairing that is global in scope to the project.

    <CharacterSet>Unicode</CharacterSet>

 

Property Group: Simple XML notation to group together properties.

  <PropertyGroup ...>

    <ConfigurationType>Application</ConfigurationType>

    <WholeProgramOptimization>true</WholeProgramOptimization>

    <CharacterSet>Unicode</CharacterSet>

  </PropertyGroup>

 

Okay - I'm cheating a bit here...a Property Group element can also have some attributes:

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

 

Condition is basically an IF statement - if the property values Configuration and Platform are equal to Release and Win32, then this property group is active. Think of it like a #define. Label is just a search marker we use to help us find the right locations in a project file - we'll get into that in a later post. Note that just about every MSBuild element can have conditions. I'll tend to delete them from this post to keep the XML simple.

Also note that property groups don’t impact the properties – except in the case of conditions – whether a property is in one property group or another is really about human readability.

Item: An entry of some sort of item - files are the most common. Items have two key attributes: ItemType and Include (think name & value). In this example, we have a ClCompile Item that points to the relative path of the file. The ItemType is how we distinguish a file consumed by CL.exe versus RC.exe. We don't rely on file extensions - it's all down to the ItemType.

    <ClCompile Include="ConsoleApp.cpp" />

 

ItemGroup: Similar to PropertyGroup. Also can have conditions and labels, but you won't often see them in a VS generated project for source files.

  <ItemGroup>

    <ClCompile Include="ConsoleApp.cpp" />

    <ClCompile Include="stdafx.cpp" />

  </ItemGroup>

 

Similar to PropertyGroups, ItemGroups are for your convience – which group an item belongs to doesn’t really matter. You can even mix different ItemTypes in the same group if you want.

One very important difference between Items and Properties – when you specify the same property name later in the project file, its value becomes the new value.

  <PropertyGroup ...>

    <WholeProgramOptimization>true</WholeProgramOptimization>

    <WholeProgramOptimization>false</WholeProgramOptimization>

  </PropertyGroup>

 

Thus optimization is now false. However, Items are cumulative. Thus

  <ItemGroup>

    <ClCompile Include="ConsoleApp.cpp" />

    <ClCompile Include="stdafx.cpp" />

  </ItemGroup>

 

Means you have two items. Even if the Include values are the same, you still have two items.

Item Metadata: Think of these as properties that apply to a specific Item.

    <ClCompile Include="stdafx.cpp">

      <PrecompiledHeader>Create</PrecompiledHeader>

    </ClCompile>

 

ItemDefinition: Consider these the templates for Item Metadata. You can specify an ItemDefinition - such as for ClCompile.PrecompiledHeader - that automatically applies to all items of that type, unless they override it locally.

  <ItemDefinitionGroup>

    <ClCompile>

      <WarningLevel>Level3</WarningLevel>

    </ClCompile>

  </ItemDefinitionGroup>

 

Now all ClCompile items, such as the stdafx.cpp in the previous example, have WarningLevel set to 3.

Imports: Just like #includes - they bring in other MSBuild files. The extensions of these files are more for humans (like .h) - the Import doesn't care.

  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

 

Now, just because we don’t care about their extensions doesn’t mean we don’t have a convention. You’ll find .props are files that contain property values and are imported at the top of the file. At the bottom of the project file you’ll find .targets imports. We aren’t really getting into this aspect in this post – but consider targets and tasks as the verbs of your build system. This is where things like Build, Rebuild, and Clean would be defined.

Evaluation Order

Okay, now that we have these concepts, let's talk about one of the big changes from VCBuild to MSBuild - evaluation order. MSBuild is what we call a linear evaluation model - this means that you start at the top of the file and work your way down.

If I have the following (where $() is used to refer to a property):

  <PropertyGroup ...>

    <A>1</A>

    <B>$(A)</B>

    <A>2</A>

  </PropertyGroup>

 

The final result of B is 1 for MSBuild - you just follow the logic like a program. However, VCBuild is a late evaluation model, which results in B being equal to 2 - VCBuild keeps the string values until the very end in a large table and then evaluates everything.

This might sound like not much of a deal, but it has caused numerous issues for us as we ported from VCBuild to MSBuild - and if you are porting your projects to Dev10 - it might become an issue for you as well. We try to fix it up where we can, but watch for it in your conversion warning messages.

Referencing Elements

Okay - whew - finally at the part I wanted to talk about: How to work with these bits in the IDE. The way to access project properties is the same as in VS2008 - just right click on the project or file you are interested in and select Properties.

Property Page

Notice how the highlighted properties above are using MSBuild property values (the $ is the indication of an MSBuild property) in their own definitions. This is pretty straight-forward. To help you out, however, we can display what properties are available to you when setting another property. For example, if you want to set Output Directory, you can select the drown-down arrow, select edit and then press the Macros button.

Macro Editor

We calculate what all the macro values are at the point Output Directory would be evaluated so you don't have to worry about it. The same also applies to ItemMetadata.

Item Definition Usage

Notice here how the project is pre-pending some values to itself - and notice how the % symbol is used instead of $. This shows that you are working with ItemDefinitions - and if you bring up the macro editor window again, you'll be able to pick from not just properties, but also any ItemDefinition metadata defined for your ItemType (in this case, ClCompile).

Inheritence

Lastly - see the checkbox at the top of the screenshot. As I said above, PreprocessorDefinitions inherits from values defined before it as is evident from the MSBuild syntax displayed. But you don't need to do that yourself (although you are free to). We provide a checkbox to turn on or off the automatic appending of the inherited value.

Summary

So that is some basic behind-the-scenes on what is going on with your project and its properties. Notice we haven't talked about where these inherited values are coming from - that will come in a future post about property sheets and a walk-through of the MSBuild import structure we use for VC++ projects.

Posted by Brian Tyler | 2 Comments

Hello and Welcome

Hi! My name is Brian Tyler and I'm the technical lead for the VS Project Team here at Microsoft. Our areas of responsibility are those surrounding projects and solutions in Visual Studio - specifically the C++, C# and VB project systems - but we're involved in other code bases in those areas as well. We are also - obviously - very related to Build and are actually part of the same team that handles MSBuild. Hey guys!

We're just starting off on the team blog and we're excited about all the things to talk about. For starters, we're going to focus on the new things coming your way in VS 2010. Specifically we'll be starting with our major effort in this release: the conversion of the VC++ project system from VCBuild to MSBuild. All this work wasn't just accomplished by us and MSBuild, but also included several folks a few floors down from us in VC++ land. Hey you other guys!

This conversion is not just a matter of project file format or build engine - it was a fairly serious rewrite of many parts of the VC++ project system. A primary goal in this move to MSBuild was to give a much more flexible project and build system to our C++ customers - and I hope you'll take advantage of it during the beta and give us your thoughts. These include

  • A highly customizable build process thanks to MSBuild.
  • An extensible tool system that lets you add your own toolsets to the UI - using the same technology we used for CL, LINK, etc.
  • A high-performance incremental build based on a file-system tracking tool - this ensures the incremental knowledge is exact (and available for your tools as well).
  • An extensible platform system allowing anyone to define and add their own custom platforms - again using the same technology we used to add Win32 and x64.
  • Native multi-targeting - you can now upgrade to the VS 2010 experience while still using the VS 2008 toolsets (compilers, linkers, libraries and headers).
  • Enlistment-based toolsets - you can now check in your toolsets and platforms into source code control to provide versioning control for all developers, build machines, etc.

And that's just what is new in VC++ projects for VS 2010....like I said, we've got a lot to talk about. So expect to see posting as regularly as we can manage while we dive into the details of these topics - and rattle our cage if we fall behind. Also make sure to post a comment or send us an email for other topics you'd like to see covered.

Posted by Brian Tyler | 2 Comments
 
Page view tracker