#linker #g #compilation
#компоновщик #g #Сборник
Вопрос:
Я понимаю, что MINGW-g компилирует большие исполняемые файлы, потому что он статически связывает многие вещи. С другой стороны, MSVC динамически связывается с библиотеками DLL из пакета VCRedist, и именно поэтому он создает исполняемые файлы намного меньшего размера.
Однако возможно ли аналогичным образом скомпилировать с g в Windows? Не обязательно MINGW-g , но что-то, что я могу использовать с Qt Creator (я не добавил Qt в качестве тега, потому что это не имеет отношения к вопросу).
Ответ №1:
MinGW прекрасно способен динамически подключаться к среде выполнения msvcrt. Единственная проблема, от которой вы не избавляетесь таким образом, — это код запуска GCC / MinGW, который не очень большой.
Небольшая тестовая программа на C (простая программа iostream hello world, примечание: я получил те же результаты для простой версии C printf).
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!" << endl;
return 0;
}
Командные строки:
g main.cpp -MD -Os -s -o test.exe
cl /MD /Os main.cpp /link /out:test2.exe
Размеры исполняемых файлов:
GCC: 13 КБ
MSVC: 6 КБ
Хотя это двойное значение, весь необходимый код запуска объясняет большую разницу; для более крупных программ разница незначительна.
Комментарии:
1. Является ли переключатель -MD тем, который позволяет ему связываться со средой выполнения VC?
2. MinGW всегда ссылается на среду выполнения VC (the msvcrt.dll в C:WindowsSystem32 ).
-MD
просто делает то же самое, что и/MD
для MSVC. Я думаю, вы неправильно понимаете, что такое / делает MinGW: он создает собственные исполняемые файлы точно так же, как компиляторы Visual Studio, но с помощью набора инструментов GNU. Таким образом, существует небольшой фрагмент кода, не разделяемый между ними, но все это всегда скрыто от пользователя. Также C ABI немного отличается (и g ссылается на libstdc от GCC, а не на MS, в отличие от библиотеки C, которая одинакова в обоих случаях), но это примерно суммирует разницу.3. Вы пробовали удалять двоичные файлы?
4. Да, я это сделал. Кроме того, UPX (который тоже отключается). Моя проблема была конкретно с приложениями Qt, которые, как я видел, некоторые из предварительно скомпилированных примеров имели размер около ~ 100 КБ, но когда я их перекомпилировал, они были в 5-8 раз больше, а не с отладочной сборкой. К счастью, я только что узнал, что использование компилятора MS с Qt — это всего лишь вопрос использования Qt SDK версии MSVC.
5. @Tamas: что вполне возможно в вашем случае, так это то, что вы используете версию MinGW только со статической сборкой стандартной библиотеки C , что может объяснить дополнительное раздувание. Мой использует libstdc как dll. Но на самом деле, использовать MSVC с Qt совсем не сложно.
Ответ №2:
Чтобы провести справедливое сравнение между VC и MinGW с использованием статической компоновки, я бы предложил удалить переключатель компилятора / MD в синтаксисе командной строки выше. Это приведет к тому, что компилятор Visual C вместо этого будет статически связываться со статическими библиотеками, но все равно компилятор Visual C сгенерирует исполняемый файл гораздо меньшего размера, чем тот, который скомпилирован статически с помощью MinGW.
Поскольку компоновщик, используемый компилятором Visual C , имеет функцию, называемую связыванием на уровне функций, с помощью этого компоновщика связываются только необходимые библиотеки на основе функций, используемых в вашем коде. Любые не имеющие ссылок или неиспользуемые функции не будут связаны с конечным сгенерированным исполняемым файлом, что приведет к гораздо меньшему статически связанному двоичному файлу.
Возвращаясь к приведенному выше примеру с использованием компилятора Visual C , и на этот раз, используя статическое связывание, синтаксис командной строки будет следующим:
cl / Os main.cpp /ссылка /out:test2.exe
Здесь вы можете заметить, что я убрал переключатель /MD, чтобы компилятор использовал статическое связывание вместо динамического.
Теперь, чтобы создать гораздо меньший статически связанный исполняемый файл, я предлагаю синтаксис командной строки:
cl /Ox main.cpp /link /FILEALIGN:512 /OPT: REF /OPT: ICF /ИНКРЕМЕНТНЫЙ: НЕТ /out:test2.exe
Если вы проверите полученный двоичный файл, вы заметите, что он намного меньше, что опять же является статически связанным исполняемым файлом.
На самом деле я почерпнул эту идею из обсуждения на этом веб-сайте по адресу http://www.catch22.net/tuts/minexe
Большинство компиляторов Pascal, включая Delphi, также имеют ту же функцию компоновки, и она известна как интеллектуальная компоновка, но результирующие статически связанные исполняемые файлы намного меньше тех, которые создаются компилятором Visual C .
Компоновщик, используемый MinGW, очень тупой, он не подвержен раздуванию и, следовательно, он связывает множество статических библиотек, включая те, которые содержат функции или подпрограммы, которые вообще не используются в вашем исходном коде, что приводит к очень раздутым статически связанным двоичным файлам.
Я бы посоветовал удалить MinGW и вместо этого использовать компилятор Visual C . Даже разработчик MinGW, похоже, не заботится о сокращении объема кода с помощью статического связывания.
Комментарии:
1. Есть ли в MinGW встроенная замена компоновщику? Я бы хотел остаться с g , потому что большинство приложений, которые я разрабатываю, предназначены для кросс-компиляции в Linux и Windows. Если я использую g на обеих платформах, это относительно безболезненно.
2. В настоящее время я пытаюсь выполнить поиск в Google для замены, но прямо сейчас я еще не нашел подходящего ответа. Поскольку вы действительно хотите остаться с g без какого-либо раздувания кода, я советую вам использовать динамическую компоновку для этого компилятора и включить необходимые библиотеки DLL в ваше приложение, если вы хотите развернуть его на других машинах, чтобы избежать проблем с зависимостями, также известных как DLL-ад в среде Windows.
3. Если вы будете разрабатывать свое приложение в Linux, прилагаемый к нему компилятор gcc и g по умолчанию использует динамическое связывание, и, насколько я знаю, в большинстве дистрибутивов Linux есть все необходимые библиотеки времени выполнения для разрабатываемых вами приложений, поэтому, возможно, не нужно беспокоиться о том, какие библиотеки времени выполнения необходимо включить в ваше приложение, если вы хотите развернуть его на других машинах, использующих Linux.
4. Да, настройка по умолчанию в Qt Creator также динамически связывает сам Qt с приложением. Рекомендуемый метод развертывания — отправить библиотеки DLL в каталог приложения. Это работает, и все в порядке. Что меня не совсем устраивает, так это то, что основной размер exe-файла в gcc больше по сравнению с VC (хотя оба они динамически ссылаются на Qt).
5. Насколько велика разница в размере между тем, который скомпилирован с помощью VC , по сравнению с тем, который с MinGW использует динамическую сборку? Если он маленький, то нет необходимости утруждать себя этим.
Ответ №3:
Вы можете использовать cygwin (www.cygwin.com ). Они используют DLL времени выполнения, очень похожую на MSVCRT . Тогда ваша программа, конечно, зависит от среды выполнения cygwin (извините, это тавтология).