Visual Studio 2010 C++ Project Upgrade Guide

Visual Studio 2010 C++ Project Upgrade Guide

Rate This
  • Comments 26

Hi, my name is Li Shao. I am Software Design Engineer in Test on the C++ team. As has been mentioned in many of the blogs, for example, recent blog by Felix Huang, the blog by Andreea Issac and my earlier blog, one of the major improvements in this release is that the C++ build system is moving from the VCBuild based system to the MSBuild based build system. The C++ project system is also built on top of the MSBuild build system. There were a large amount of changes that went in to make this happen. Our goal is to make the upgrade process as smooth as possible from the end user point of view. There are some limitations, known issues or by design changes that you may run into during the upgrade process. The goal of this post is to give you some guidance and explain some of the issues that you may run into when upgrading to VS2010.

How to Upgrade?

VS2010 supports upgrading from VC6, VS2002, VS2003, VS2005 and VS2008.  As in previous versions of Visual Studio, upgrade can be done either through IDE conversion wizards or from the command line (Devenv /upgrade).

 Here are the recommendations for upgrading your applications:

1)      Set up the upgrade environment the same as your build environment

The upgrade process will try to load files and evaluate values during upgrade. If your projects use values that are not defined by the project files themselves, for example, values defined by environment variables, it is required that these environment variables are set up before doing the upgrade. Without these environment variables properly set up, you may get conversion warnings or errors caused by unevaluated values.

2)      Make sure you have the required platforms installed before doing upgrade

Converting a project on a machine without all the available platforms for the project will result in a conversion error. For example, if you try to convert a project with Itanium Platform on Visual Studio Professional SKU, which does not support the Itanium platform, you will see a conversion error like the following:

Failed to upgrade 'Debug|<Itanium>'. Please make sure you have the corresponding platform installed under '%vctargetspath%\platforms\Itanium'. Cannot load the project due to a corrupt project file. The following error has occurred during XML parsing:

File: D:\Sample\ConsoleApp\ConsoleApp.vcproj

Line: 28

Column: 5

Error Message:

System error: -2147154677.

The file 'D:\Sample\ConsoleApp\ConsoleApp.vcproj' has failed to load.

This is by design as the conversion needs to evaluate the properties in the missing platforms to do a successful conversion. You can verify which platforms are installed on your machine by looking in the following directories:  %ProgramFiles%\MSBuild\Microsoft.cpp\V4.0\Platforms (or %ProgramFiles(x86)%\MSBuild\Microsoft.cpp\V4.0\Platforms on x64 machine) for the Platforms installed on the machine.

3)      Use native Multi-Targeting to build against VS2008 toolset first if possible

In VS 2010, we added Native multi-targeting which allows you to build against the Visual Studio 2008 toolset from within the VS2010 IDE using the new MSBuild-based project system. You can take a look of this blog for the details about this feature. We recommend customers, especially customers with large codebases, take advantage of this feature by using VS2010 to build against VS2008 toolset first when upgrading. This can help isolate any project system/build system related issues from the tools issues that you may run into after upgrade. This will make the move to the VS2010 toolset much smoother.

Upon upgrade, the property sheet files (.vsprops) are converted to their new format (.props). Likewise, project files (.vcproj) are converted to their new format (.vcxproj). Note, the new project files are generated alongside the old project files. A new file type (.filter.vcxproj) is also generated during conversion. The filter files contain the information that is used to display folders in the solution explorer. This filter information was originally part of the project file. This change was necessary because MSBuild requests a rebuild whenever the project files changes. By storing filter information in a separate file, the filter can be changed without triggering a rebuild of the entire project.

      Note: Upgrade process will not convert the .user file. As a result, your debugging and deployment settings will not be preserved after conversion.

In VS2010, a new command line upgrade tool, VCUpgrade.exe is introduced. This command line tool is suitable for upgrading applications with only one project as it cannot take in solution file as input and parse solution information into project files. VCUpgrade.exe is located at: $(VSInstallDir)\common7\Tools directory. This tool will also be shipped in the next release of WinSDK so that the users can do command line upgrade of the project files shipped in WinSDK without Visual Studio IDE.

Warnings during upgrade

Here are some of the common warnings that you may run into during conversion:

1)      Linker output directory

One of the warnings you may see when upgrading you applications is MSB8012: $(TargetPath) and Linker’s OutputFile property value does not match:

- MSB8012: $(TargetExt) ('.dll') does not match the Linker's OutputFile property value 'C:\foo\Debug\MFCActiveX.ocx' ('.ocx') in project configuration 'Debug|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetExt) property value matches the value specified in %(Link.OutputFile).

- MSB8012: $(TargetPath) ('C:\foo\Debug\MFCActiveX.dll') does not match the Linker's OutputFile property value 'C:\foo\Debug\MFCActiveX.ocx' ('C:\foo\Debug\MFCActiveX.ocx') in project configuration 'Debug|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetPath) property value matches the value specified in %(Link.OutputFile).

Link.OutputFile is the value defined at Linker -> General -> Output File on the property page. By default, its value is $(OutDir)$(TargetName)$(TargetExt), which is the same as the value of $(TargetPath). When we convert an application from a previous version, however, there is not an easy way for conversion to parse Link.OutputFile to figure out what exactly the values are for $(TargetName) and $(TargetExt), as different customers may have formatted them in different ways. To work around that, we decided to preserve the value of Linker.OutputFile during conversion. After conversion, $(TargetName) will default to $(ProjectName). $(TargetExt) will default to the default extension for the application type: .dll for Dynamic Library, .lib for Static Library and .exe for Application. Link.OutputFile value will be preserved. Warning MSB8012 will be issued in the conversion log if Link.OutputFile and $(TargetPath) are not the same. You will get the same warnings when building the application.

$(OutDir), $(TargetName) and $(TargetExt) are exposed on the "General" property page, as "Output Directory", "Target Name", "Target Extension", respectively. You can manually change the values of these properties so that you no longer get the warning.

-If your project produces Import Library (Linker -> Advanced -> Import Library), you may need to change the Output folder of the Import Library as well after conversion if the Linker output directory is not the default output directory. Otherwise, the generated import lib maybe in a different directory than the linker output.

-Debugging.Command is set to default $(TargetPath) after conversion. You may need to make changes so that the right executable will be launched upon F5 (Debugging) or Ctrl + F5 (Start without debugging).

2)      Property sheet ordering

If you have property sheets in your application, you may come across the following warning during conversion:

- All user macros reported below for configuration 'Debug|Win32' are used before their definition, which can cause undesirable build results; this is not supported in this release. You can resolve this by changing the inclusion order of the consuming property sheets and making sure they come after the property sheets defining the user macros.

- MSB4211: C:\foo\PropertySheet\foo.props; The property "MyIncludePath" is being set to a value for the first time, but it was already consumed at "C:\foo\PropertySheet\bar.props".

The warning is due to the way that MSBuild evaluates its properties. MSBuild evaluates its properties in a sequential order. The properties defined in the inherited property sheets are evaluated as empty if they are used in the parent property sheets. VCBuild, however, does late evaluation, which enables the usage of the properties in the parent property sheets even if they are defined in the inherited property sheets. To work around the issue, please follow the warning message to change the inclusion order of the property sheets to ensure that properties are defined before they are used.

Behavior changes after upgrade

We strived to maintain a similar experience for our customers migrating to VS2010 in spite of the underlying build system change. On the other hand, we have made changes to improve some specific build experiences or accommodate MSBuild specific requirement. As a result, you may notice a few behavior changes once you migrate to VS2010.

1)      Solution Dependencies into Project to project reference

When a C++ application from a previous version of Visual Studio is converted to VS2010, project dependencies defined at the solution level are converted to project to project references. This change ensures that C++ project dependencies are captured in the project file. Below is how a Project to project reference looks in the project file:

<ItemGroup>

    <ProjectReference Include="..\Cpp\Cpp.vcxproj">

      <Project>{c58574bf-9dd8-4cf8-b5b6-6551f2f3eece}</Project>

      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

    </ProjectReference>

  </ItemGroup>

 There are several advantages of having dependency information in the project file. First, user can build a project without the solution and the dependent projects will be built automatically. Second, it sets up the customer for large trees, where they might not use solution files. In addition, many customers have several solution files, each with different subsets of the projects. This can save the customers from setting project dependencies for each of the solutions. Another important factor is that, build dependencies are more reliable when the dependencies are set through project to project reference, especially when building with multiple cores.  This has been the case with previous versions of Visual Studio as well.

-If you have a C# application that is dependent on a C++ application and this dependency is only expressed through solution dependency, the current conversion process won’t change the solution dependencies to the project to project references. You may run into build errors caused by incorrect build orders especially when building at the command line with MSBuild directly. To fix the issue, you will need to manually se up a proper project to project reference for C# and C++ applications.

-Use project to project reference instead of solution dependencies when setting up new build dependencies in VS2010 in general.

2)      Project to project reference property change

After conversion, CopyLocalDependencies and UseDependenciesInBuild properties are removed. “Use in Build” property is changed to “Reference Assembly Output” to better represent the functionality of the property.  Two more properties: “Link Library Dependencies” and “Use Library Dependency Inputs” are added for the referenced projects so that the referenced projects can control whether its output will be passed to the referencing projects. Below is the side by side image of VS2008 and VS2010 project to project reference properties.

-Setting “Reference Assembly Output” to “false” allows the project to be part of the project to project reference, so that the build dependency is set up, while its output is not passed to the CL of the referencing project. This property is used by managed application.

-Setting “Link Library Dependencies” to “false” allows the project to be part of the project to project reference, so that the build dependency is set up, while its output is not passed to the linker of the referencing project.

3)       VC++ Directories change

VC++ Directories are no longer supported in VS2010 through Tools->Options page. Instead, VS2010 introduces the user settings file (Microsoft.cpp.<Platform>.users.props) to control global settings including Global search path. These files are located at $(USERPROFILE)\appdata\local\microsoft\msbuild\v4.0 directory. Upon migration to VS2010, the custom settings of VC++ Directories from VS2005 or VS2008 are migrated to these user files. These global settings files are imported into all the converted and newly created projects.

 Here are the steps to change the settings file through UI:

·         Open up property manager by clicking on View.Property Manager.

·         Expand the project node and then the Configuration|Platform nodes, you will see "Microsoft.cpp.<Platform>.users" file for each Configuration|Platform. These are the files for the global settings, similar to the old tools/Options/VC++ Directories.

·         Multi-Select "Microsoft.cpp.<Platform>.users", right click and bring up the property page window

·         In the property page window, click on "VC++ Directories" (for example) in the left pane, add new paths for the directories such as "Include Directories". separated by semicolons

·         Make sure to save the settings before shutting down Visual Studio.

·         Re-launch Visual Studio and the new settings will be in effect.

-Note: If you would like to only change the settings for one project, you can right click on the project and bring up the property page. Change the settings for “VC++ Directories”, these settings will be persisted to the project file.

4)      Custom Build Rule Change

In VS2008, a custom build rule is defined by a .rules file. Conversion will convert these .rules files into three separate files: .targets, .xml and .props. You can find these files in the same directory as the rules file after conversion. Note that there is no UI available to add new custom build rules. You can take a look of this blog for more information about VS2010 custom build rule.

5)      Up to date check change

When you hit F5, you may run into the situation that Up to check dialog always coming up even after a fresh rebuild. You can refer to this blog to troubleshoot the problem. Most likely, the issue is caused by the fact that some files are listed as part of the project files but are missing on the disk. Because these files are part of the project files, the new up to date check mechanism will check for their existence. If the files are not on the disk, the up to date check will assume that a new build is needed. The fix is to remove the files from the project files if they are not on the disk.

One limitation we had for VS2010 is that Managed Incremental build is not supported. We are investigating how to bring back this feature in future release.

Known issues for conversion in VS2010

Here are some of the known issues for the conversion in VS2010:

1)      TargetFrameworkVersion

After conversion, managed C++ projects will target the 4.0 Framework by default.  The reason behind this design is that the VS2010 compiler cannot target Framework 2.0, 3.0 or 3.5. The VS2008 compiler must be used to target 2.0, 3.0 or 3.5. To make the converted C++ application build out of box, we decided to move the TargetFrameWorkVersion to 4.0 by default for C++ applications. The C++ applications can be retargeted to other frameworks (say 3.5 for example) by one of the following methods:

        Edit the vcxproj file and in the first property group define add the following:

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

 •   Open the VS2010 command line, set TargetFrameworkVersion=v3.5, and then start devenv.exe from the commandline. This will target all your C++ applications to v3.5 framework.

 •   Pass /p:TargetFrameworkVersion=v3.5 to MSBuild when building applications: MSBuild my.vcxproj /p:TargetFrameworkVersion=v3.5

Note that VS2008 has to be installed on the machine for the application to target 2.0, 3.0 or 3.5.

For C#/VB applications, conversion does not change the target Framework version if the targeted Framework is installed on the machine.  If the targeted Framework is not installed, you will have the choice of either downloading the required Framework or upgrading the target Framework to 4.0.      

-If you have mixed CSharp/VB/managed C++ projects in your solution, you may run into a situations where CSharp/VB applications and managed C++ applications are targeting a different framework version. You may get warning MSB3258 if the referenced project has a higher Framework version than the Framework version of referencing project:

The primary reference “foo, Version=x.x.xxx.xxxx, Culture=neutral, processorArchitecture=x86” has an indirect dependency on the .NET Framework assembly “mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089” which has a higher version “4.0.0.0” than exists in the current target framework. The version found in the current target framework redist list is “2.0.0.0”. By including the primary reference you may get compile and/or runtime errors.

-Or you may run into warnings such as C4691: type referenced was expected in the unreferenced assembly ‘file’, type defined in current translation unit used instead, if the Framework version of the referencing project is higher.

-You need to retarget all projects in your solution to the same framework version.

2)      Quotes used in makefile “Output” Property

If you have a make file project with quotes used in the “Output” property, the conversion will fail. The fix is to remove the quotes in the “Output” property before doing the conversion.

 <Tool

                                                                Name="VCNMakeTool"

                                                                BuildCommandLine="nmake /nologo &quot;OUT=$(OutDir)&quot; &quot;OBJ=$(IntDir)&quot;"

                                                                ReBuildCommandLine="nmake /a /nologo &quot;OUT=$(OutDir)&quot; &quot;OBJ=$(IntDir)&quot;"

                                                                CleanCommandLine="nmake /nologo &quot;OUT=$(OutDir)&quot; &quot;OBJ=$(IntDir)&quot; clean"

                                                                Output="&quot;$(OutDir)hlekernel.rom&quot; &quot;$(IntDir)hlekernel_gen.inl&quot; &quot;$(IntDir)hlekernel_gen.h&quot;"

                                                                PreprocessorDefinitions="WIN32;_DEBUG"

                                                                IncludeSearchPath=""

                                                                ForcedIncludes=""

                                                                AssemblySearchPath=""

                                                                ForcedUsingAssemblies=""

                                                                CompileAsManaged=""

3)      Backslash in $(IntDir) and $(OutDir)

$(IntDir) and $(OutDir) are exposed at “General -> Intermediate Directories” and “General -> Output Directories” on the property page, respectively. To unify the format for $(IntDir) and $(OutDir), conversion has intentionally appended “\” to their property values if they don’t have one when converting them. Trailing “/”s are removed if there are any.

This, however, may break the build scenarios if $(IntDir) or $(OutDir) are used in makefile or custom build, where Exec task is used.

In the makefile case, nmake tool cannot evaluate the values if they are ended with “\”. For example, with this command,

BuildCommandLine="nmake /nologo &quot;OUT=$(OutDir)&quot; &quot;OBJ=$(IntDir)&quot;"

 Because $(OutDir) and $(IntDir) has a trailing “\”, nmake tool cannot properly expand them and OUT and OBJ will be evaluated as empty as a result. To fix that, you need to remove the “\” for $(IntDir) and $(OutDir) at the property page.

 If $(OutDir) or $(IntDir) are passed to the custom build, including build event, custom build tool, custom build steps,  you may run into build failure due to the fact that “\” may be treated as an escape character by the tools. For example, if you have a prebuild event like the following:

 <PreBuildEvent>

  <Command>cl /c  /Fo"$(IntDir)" "$(ProjectDir)\win32.cpp"</Command>

</PreBuildEvent>

The command line will be: cl /c  /Fo"Debug\" "C:\foo\win32.cpp" instead of cl /c  /Fo"Debug\\" "C:\foo\win32.cpp"

To fix the issue, add an extra “\” in the value passed to /Fo (C/C++ -> Output Files -> Object File Name) so to compensate the escaping.

4)      Solution Explorer UI

The display of the folders and files in solution explorer is controlled by .vcxproj.filters file in VS2010. If you have folders with the same name but under different scopes, for example, “Native\Include” and “Include”, the second “Include” and the files under “Include” will not show up in solution explorer after conversion. To work around the issue, you can recreate the folder in the solution explorer and add the respective files into this folder.

5)       Read-only Project file or directories

You may run into issues when upgrading from a read-only directory or reconverting when the previously converted project files are read-only. Be sure to make the directory and files writable unless the files can be automatically checked out, as in the case of integrated source control system.

Related Community Posts

Here are the collections of community post/connect bugs that may help troubleshooting build issues once upgraded to VS2010:

·         Global Search Directories

·         About c++/cli dll in vs2k10 beta1

·         Project Dependencies option issue

·         Best Practices for custom build steps in VS2008 and VS2010?

·         Managed resources

·         How to sign C++/CLI assemblies in VS 2010?

·         error RC1106: invalid option: -ologo_RC

·         Custom build Rule conversion

·         VC++ Directories

·         CL crash when targeting v90

·         Semantics of PrecompiledHeaderOutputFile

·         Import Lib directory

·         Register ATL COM EXE in non-admin mode

·         Fail to clean or rebuild for nmake project

 

Li Shao

Project and Build Team

 

  • So I upgraded my MSVC 2008 project to 2010 RC...

    I always compile my code with /Wall /wd4820 /we4289 /wd4342 /wd4347 /wd4514 /we4545 /we4546 /we4547 /we4548 /we4549 /we4619 /we4623 /we4625 /we4626 /wd4710 /we4836 /we4905 /we4906 /we4928 /we4946

    After upgrade,  warning C4986: 'operator new[]': exception specification does not match previous declaration entered the game.

    The problem has been reported there: http://connect.microsoft.com/VisualStudio/feedback/details/506966/new-warning-4986-prevents-clean-compile-at-warning-level-4

    I know I just have to add /wd4986 to make the compiler happy again. Call me pedantic, but... *sigh*

  • Thank you for your feedback. As Stephen mentioned in the connect bug, we ensure our library compile cleanly under /W4 /analyze but we don't guarantee compile cleanly under /wall. Please let us know if you think this should be fixed for next release.

    Li Shao, Project and Build Team

  • We currently use VS2005 to target .NET Framework 2.0. Is it possible to move to VS2010 and still target the 2.0 framework? Or is it explicitly the VS2008 compiler which is required (and which we do not have)? Would the compiler from a VS2008 Express edition work?

  • Yes, you can create the custom PlatformToolset for VS2005 to target VS2005. I have an example of how to create PlatformToolset for VS2005 in earlier blog: http://blogs.msdn.com/vcblog/archive/2009/12/08/c-native-multi-targeting.aspx.

    Yes, compiler from VS2008 express edition works as well. The only limitation is that you cannot target x64/Itanium with Express, also, Express does not come with MFC/ATL headers.

    Li Shao, Project and Build Team

  • "Converting a project on a machine without all the available platforms for the project will result in a conversion error."

    Why?

    What if I don't need this part of project?

    I think, such case is subject of warning, but not error.

  • As Li mentioned in her blog, the convertor needs to evaluate the properties in the platform to be able to convert the project successfully. When the platform is missing, it cannot do this step and the conversion cannot complete, hence it fails with the error. We do not want data loss during conversion.

    If you don't need this part of project, you could just delete the missing Platform from the original project before performing the conversion.

    However, if you strongly feel that this should be a warning, please open a Connect bug.

    Renin John, VC++ Project and Build Team

  • When upgrading a project/solution from VS 2005 or earlier, you should check ALL the settings. Several upgrade bugs were fixed from VS 2008, but there are differences you may want to take advantage of.

    Also, for native code, if you had the Win98 linker optimization on, you'll need to clear it to prevent warnings.

  • Thanks for mentioning that, Joe.

    Yes, there are some changes in compiler default settings:

    VS2008: RuntimeLibrary = MultiTreaded (/MT)

         DebugInformationFormat = Disabled

    VS2010: RuntimeLibrary = MultiTreaded (/MD)

         DebugInformationFormat = ProgramDatabase (/Zi)

    The projects created by VS2002, VS2003 and VS2005, VS2008 have those options in the project files and should not see the defaults change (unless somebody deliberately removed the settings from the project). The projects created by VC6 might be affected as many of them don't have those settings in their project files by default. People will need to set these options in their project files (or any props files they import) to override the defaults.

    In addition, VS2010 sets /O2 (C/C++/Optimization/Optimization) as the default for release configuration for both newly created or converted projects.

    Li Shao, MSFT

  • As a result of the /Zi change, you may see some build performance degradation from VS2008 for applications originally created and migrated from VC6. On single proc build, this is due to the fact that .pdbs are generated.

    Li Shao, Project and Build Team

  • One bit of confusion are the number of items in the properties which are left blank. Not a huge problem except it's not always clear what the default is.

    (And I think the NOWIN98 setting was finally removed entirely.)

  • Li Shao, you wrote "Note that there is no UI available to add new custom build rules." Does that mean that it's not available yet, or that there won't be any UI to add new custom build rules in Visual Studio 2010?

  • Yes, there are some properties especially the properties with Boolean values are left blank. I agree this is not helpful in determining what the defaults are. You may want to open a connect bug. Your feedback can help us prioritize and get the issue fixed for next release.

    Li Shao, Project and Build Team

  • @Jake. No, there will be no UI to add new custom build rule for Visual Studio 2010. If you have old custom build rules, they will be converted to the new format and you can still use them.

    Li Shao, Porject and Build Team

  •  I've been using VS2010 RC now for a few weeks, and while I love the new language features for C++ , I'm still having some pretty major issues with the overall responsiveness of the IDE(and this is running on a very powerful i7 system).

    -toggling between files is often very slow, even switching between the same files repeatedly can cause multi second delays for no apparent reason.

    -the IDE can't seem to keep up with me as I type, it often falls beyond and does not display what I am typing until well after I typed it.

    -multi second delays are not uncommon when scrolling or clicking on different menu options.

    I have enabled precompiled headers to speed up intellisense as was suggested in one of the other posts(and placed many common files in it), but everything still seems slow and unresponsive.

  • Follow up to previous post--

    I noticed that VS2010 RC was using 1 gig of memory(had it running for around 8 hours), so I restarted it(only uses 210 megs once restarted).

    I can see the memory usage slowly ticking upward(actually not that slow)

    Anyway it is much more responsive after a restart, but if VS2010 RC can't even be run for 8 hours without falling apart I think it still needs a little work on the performance side :/

Page 1 of 2 (26 items) 12