06 December 2010

Fixing C++ projects that always rebuild

After upgrading to Visual Studio 2010, one of our C++ projects would always be built, even if none of its files changed. When setting MSBuild output verbosity to "Normal", the Build output window would show:

1>------ Build started: Project: SomeLib, Configuration: Release Win32 ------ 
1>InitializeBuildStatus: 
1>  Creating ".\Release\SomeLib.unsuccessfulbuild" because "AlwaysCreate" was specified. 
...
1>Build succeeded. 
1> 
1>Time Elapsed 00:00:00.47 
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== 

This occurred even though none of the files in that project had changed.

This forum thread and Connect issue describe the problem and state that it's usually caused by referencing a .h file in the project that doesn't exist on disk; the build system in VS2010 then assumes the project is out-of- date and builds it. The forum thread references a blog post about enabling C++ project system logging in order to diagnose the problem, but it didn't help me identify the missing file. Instead, I wrote the following script to parse the project file and check for missing files:

    // set this to your project
    string fileName = @"C:\Path\To\MyProject.vcxproj";

    XDocument project = XDocument.Load(fileName);
    XNamespace msbuild = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");

    int present = 0, missing = 0;
    string folder = Path.GetDirectoryName(fileName);
    foreach (XElement elem in project.Root.Elements(msbuild + "ItemGroup").Elements(msbuild + "ClInclude"))
    {
        string name = (string)elem.Attribute("Include");
        string itemPath = Path.Combine(folder, name);
        if (!File.Exists(itemPath))
        {
            Console.WriteLine(name);
            missing++;
        }
        else
        {
            present++;
        }
    }

    Console.WriteLine("{0} files present, {1} missing.", present, missing);

You could change "ClInclude" to "ClCompile" to look for missing C++ files (but this should already be a build error) or to "None" to find missing non-source files.

Posted by Bradley Grainger at December 06, 2010 03:53 PM