views:

65

answers:

2

For a simple project of mine, a release build in Visual Studio produces an assembly of size 18,944 bytes. But if I build the same solution from the command line with MSBuild, I get an assembly of size 28,672 bytes. That's a difference of 9,728 bytes.

I am invoking MSBuild with:

msbuild /p:Configuration=Release /t:Rebuild MySolution.sln

In ILDasm, I saw only minor differences in metadata. Dumping and comparing the tree view shows no differences. Dumping and comparing headers yielded a clue:

Visual Studio Output                             MSBuild Output
// Size of init.data:              0x00000800    // Size of init.data:              0x00002000
// Size of headers:                0x00000200    // Size of headers:                0x00001000
// File alignment:                 0x00000200    // File alignment:                 0x00001000

The difference in init data size is 0x1800, or 6,144 bytes. The difference in header size is 0xE00, or 3,584 bytes. The sum of these two differences is 9,728 bytes, which accounts for the discrepancy. The difference in file alignment is 3,584 bytes.

Further down I see:

Visual Studio Output                                    MSBuild Output
// File size            : 18944                         // File size            : 28672
// PE header size       : 512 (496 used)    ( 2.70%)    // PE header size       : 4096 (496 used)    (14.29%)
// Data                 : 2048              (10.81%)    // Data                 : 8192              (28.57%)

So obviously this all comes down to file alignments. But why do file alignments differ when building from the command line? In the advanced settings inside Visual Studio, I see that the file alignment is indeed set to 512:

alt text

This property is manifested in the project file in a PropertyGroup:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    ...
    <FileAlignment>512</FileAlignment>
</PropertyGroup>

But notice the combination of $Configuration and $Platform? On a hunch, I tried this from the command line:

msbuild /p:Configuration=Release /p:Platform="Any CPU" /t:Rebuild MySolution.sln

And then the output matched (in size) perfectly!

This is the only property group for a release configuration, so it is obviously being used by MSBuild regardless of whether the platform is specified. To prove this, I changed the OutputPath in this property group and then built with MSBuild at the command line. Sure enough, it picked up the new output directory.

I tried changing the alignment of 512 to 1024 and then built at the command line. It used it!

Why is it necessary to explicitly specify the platform in order for MSBuild to pick up a file alignment of 512 bytes?

+2  A: 

Why is it necessary to explicitly specify the platform

Because the default is probably Debug|AnyCPU. Check the first <PropertyGroup> in the project file, it should contain something close to:

<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>

which sets the default build if Configuration or Platform is not set on the command line. This first group might also be setting a default file alignment.

Richard
As per my question, I *am* specifying a Release build and it *is* using all the properties in the correct property group apart from the file aligment.
Kent Boogaart
Richard
@Richard: I've re-read my question and I think it's sufficiently clear. You even quoted me as saying "specify the platform" - not "specify the configuration and platform", so I'm not sure where the confusion stems from.
Kent Boogaart
@Kent: If you do not specify the platform then it will and if the default is not `AnyCPU` (as in the file I quoted) then the conditional property group you quoted will not apply. "Ifs" needed because without seeing more of your project file one cannot tell.
Richard
@Richard: if you go back and read my question *in full*, you'll see that all your points thus far have been addressed. The property group *is* being applied - just not the file alignment when it's set to 256.
Kent Boogaart
@Kent: I'm only giving you *free* help. Reduce your MSBuild file to the shortest that shows the problem (removing everything you can) with command lines that show and don't show the problem: then I may give it another look.
Richard
@Richard: I hope no offence was taken, because certainly none was intended. I wasn't able to repro this in a simple fashion, which is why I posted everything I knew in my question. I've posted my own "answer" which goes some way to explaining what happened. Thanks for your help all the same (+1).
Kent Boogaart
@Kent: np. Also could this be down to setting the file alignment for only certain configuration/platform combinations?
Richard
@Richard: I thought the same, but wasn't able to repro when I tried. That said, when I create a new project in 2010 it adds the `FileAlignment` property to a generic property group, whereas my faulty project file had it in the Release|Any CPU group. I think what may have happened is the upgrade left it out completely and VS defaults to 256 whereas MSBuild defaults to 8192. Then when I edited the settings in VS it decided to add it to the Release|Any CPU group because it wasn't present in the generic group. Might test that theory tomorrow if I get a chance.
Kent Boogaart
@Kent: That would explain things. From time to time I find a little manual editing of the project file (unload the project to get the option to directly open the `x.zzproj` file) can be easier, especially to make a 100% consistent change across multiple configurations. Or a change the IDE doesn't directly allow (`x.sn` file for multiple projects referenced in solution folder).
Richard
A: 

Looking through the history of my project file, I noticed that there was no FileAlignment property until I explicitly set it in Visual Studio (which I did whilst concocting my question). The project file had been upgraded from VS2008 to VS2010 (and I think VS2005 to VS2008 before that) so I'm assuming something got broken along the way.

So, for now at least, I'm putting this down to a combination of broken upgrades and me confusing myself whilst writing the question. I still can't quite explain the behavior I was seeing (as per my post) but things seem to have righted themselves since the FileAlignment was explicitly added.

Kent Boogaart