Для моего простого проекта сборка выпуска в Visual Studio производит сборку размером 18 944 байта. Но если я собираю то же решение из командной строки с MSBuild, я получаю сборку размером 28 672 байта. Это разница в 9 728 байт.
Я вызываю MSBuild с:
msbuild /p:Configuration=Release /t:Rebuild MySolution.sln
В ILDasm я видел только незначительные различия в метаданных. Сброс и сравнение дерева не показывает различий. Сброс и сравнение заголовков дали подсказку:
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
Разница в размере данных инициализации составляет 0x1800 или 6,144 байта. Разница в размере заголовка составляет 0xE00 или 3584 байта. Сумма этих двух различий составляет 9 728 байт, что объясняет расхождение. Разница в выравнивании файла составляет 3584 байта.
Дальше я вижу:
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%)
Так что, очевидно, все это сводится к выравниванию файлов. Но почему выравнивания файлов отличаются при сборке из командной строки? В расширенных настройках Visual Studio я вижу, что выравнивание файлов действительно установлено на 512:

Это свойство проявляется в файле проекта в PropertyGroup
:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
<FileAlignment>512</FileAlignment>
</PropertyGroup>
Но обратите внимание на комбинацию $Configuration
и $Platform
? По догадке я попробовал это из командной строки:
msbuild /p:Configuration=Release /p:Platform="Any CPU" /t:Rebuild MySolution.sln
А потом вывод соответствует (по размеру) отлично!
Это единственная группа свойств для конфигурации выпуска, поэтому она, очевидно, используется MSBuild независимо от того, указана ли платформа. Чтобы доказать это, я изменил OutputPath
в этой группе свойств, а затем собрал MSBuild в командной строке. Конечно же, он поднял новый каталог вывода.
Я попытался изменить выравнивание от 512 до 1024, а затем встроил его в командную строку. Он использовал это!
Почему необходимо явно указывать платформу, чтобы MSBuild мог подобрать выравнивание файла в 512 байт?