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:
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?