Почему важно, чтобы код C / C++ был компилируемым на разных компиляторах?

Я интересуют разные аспекты переносимости (как вы можете видеть при просмотре других моих вопросов), поэтому я много читал об этом. Довольно часто я читаю / слышу, что код должен быть написан таким образом, чтобы он был компилируемым на разных компиляторах.

без какого-либо реального жизненного опыта с gcc / g++, мне кажется, что он поддерживает все основные платформы, которые можно себе представить, поэтому код, который компилируется на g++, может работать практически на любой системе. Так зачем кому-то беспокоиться о том, чтобы его код запускался компилятор MS, компилятор Intel и другие?

Я тоже могу придумать некоторые причины. Как показывают FAQ, я попытаюсь опубликовать их в качестве ответа, а не включать их в свой собственный вопрос.

Edit: Заключение

вы меня полностью убедили, что есть несколько веских причин поддерживать несколько компиляторов. Есть так много причин, что было трудно выбрать ответ, чтобы быть принятым. Наиболее важные причины я:

  • участники гораздо чаще работают над моим проектом или просто используют его, если они могут использовать компилятор по своему выбору
  • быть компилируемым везде, быть годным к употреблению с будущими компиляторами и инструментами, и придерживаться стандартов принуждают Одина другого, поэтому хорошая идея

с другой стороны, я все еще верю, что есть другие вещи, которые более важны, и теперь я знаю, что иногда это не важно все.

и, наконец, не было ни одного ответа, который мог бы убедить меня не выбирать GCC в качестве первичный или по умолчанию компилятор для моего проекта.

13 ответов


для большинства языков я меньше забочусь о переносимости и больше о соответствии международным стандартам или принятым определениям языков, из которых, вероятно, следует переносимость свойств. Для C, однако, переносимость является полезной идеей, потому что очень трудно написать программу, которая "строго соответствует" стандарту. (Почему? Потому что комитеты по стандартам посчитали необходимым ввести некоторую существующую практику, в том числе предоставить компиляторам некоторую свободу, которая вам может не понравиться их.)

Так зачем пытаться соответствовать стандарту или сделать ваш код приемлемым для нескольких компиляторов, а не просто писать то, что GCC (или ваш другой любимый компилятор) принимает?

  • вероятно, в 2015 году gcc примет довольно другой язык, чем сегодня. Вы бы предпочли не переписывать свой старый код.

  • возможно, ваш код может быть портирован на очень маленькие устройства, где находится GNU toolchain не так хорошо поддерживается.

  • Если ваш код компилируется с любым компилятором ANSI C прямо из коробки без ошибок и без предупреждений, жизнь ваших пользователей будет проще, и ваше программное обеспечение может быть широко портировано и использовано.

  • возможно, кто-то изобретет отличный новый инструмент для анализа C-программ, рефакторинга C-программ, повышения производительности C-программ или поиска ошибок в C-программах. Мы не уверены, какая версия c этого инструмента будет работать или на каком компиляторе он может быть основан, но почти наверняка инструмент примет стандарт C.

из всех этих аргументов это аргумент инструмента, который я нахожу наиболее убедительным. Люди забывают, что есть другие вещи, которые можно сделать с исходным кодом, кроме как просто скомпилировать и запустить его. На другом языке, Haskell, инструменты для анализа и рефакторинга сильно отстали от компиляторов, но люди, которые придерживались стандарта Haskell 98, имеют доступ к много дополнительные инструменты. Аналогичная ситуация, вероятно, для C: если я собираюсь пойти на усилия по созданию инструмента, я собираюсь основывать его на стандарте со сроком службы 10 лет или около того, а не на версии gcc, которая может измениться до завершения моего инструмента.

тем не менее, многие люди могут позволить себе полностью игнорировать переносимость. Например, в 1995 году я пытался убедить Линуса Торвальдса скомпилировать Linux с помощью любого компилятора ANSI C, а не только gcc. Линус я подозреваю, что он пришел к выводу, что ни ему, ни его проекту это ничего не даст. И он был прав. Компиляция Linux только с gcc была большой потерей для исследователей компиляторов, но не потерей для Linux. "Аргумент инструмента" не годился для Linux, потому что Linux стал настолько дико популярным; люди, создающие анализ и инструменты поиска ошибок для программ C, были готовы работать с gcc, потому что работа на Linux позволила бы их работе иметь большое влияние. Так что если вы можете рассчитывать на проект становится диким успехом, как Linux или Mosaic / Netscape, вы можете позволить себе игнорировать стандарты: -)


некоторые причины с верхней части моей головы:

1), чтобы избежать блокировки с одним поставщиком компилятора (с открытым исходным кодом или нет).

2) компиляция кода с разными компиляторами, вероятно, обнаружит больше ошибок: предупреждения разные, и разные компиляторы поддерживают стандарт в разной степени.


хорошо быть компилируемым на MSVC, потому что у некоторых людей могут быть проекты, которые они строят в MSVC, в которые они хотят связать ваш код, без необходимости настраивать совершенно другую систему сборки.

хорошо быть компилируемым под компилятором Intel, потому что он часто компилирует более быстрый код.

хорошо быть компилируемым под лязгом, потому что он может дать лучшие сообщения об ошибках и обеспечить лучший опыт разработки, и это проще проект, чем GCC и так может получить дополнительные выгоды в будущем.

В общем, это хорошо, чтобы держать свои варианты открытыми, потому что нет ни одного компилятора, который соответствует всем требованиям. GCC-хороший компилятор и отлично подходит для большинства целей, но иногда вам нужно что-то еще.

и даже если вы обычно будете компилироваться только под GCC, убедитесь, что ваш код компилируется под другими компиляторами, также, вероятно, поможет найти проблемы, которые могут предотвратить код от работы с прошлыми и будущими версиями GCC, например, если есть что-то, что GCC менее строгое сейчас, но позже добавляет проверки, другой компилятор может перехватить заранее, помогая вам сохранить ваш код чище. Я нашел это полезным в обратном случае, когда GCC поймал больше потенциальных проблем с предупреждениями ,чем MSVC (MSVC-единственный компилятор, который нам нужен для поддержки, поскольку мы только грузили на Windows, но мы сделали частичный порт для Mac под GCC в наше свободное время), что позволило мне создать более чистый код, чем я бы сделал в противном случае.


переносимость. Если вы хотите, чтобы ваш код был доступен максимально возможному количеству людей, вы должны заставить его работать на самом широком диапазоне возможных компиляторов. Это такая же идея, как сделать веб-сайт работать в браузерах, отличных от IE.

некоторые из них политические. У компаний есть стандарты, у людей есть любимые инструменты и т. д. Говоря кому-то, что они должны использовать X, действительно отталкивает некоторых людей и делает его действительно недоступным для других.

Неманья поднимает хороший момент тоже, таргетинг на определенный компилятор блокирует вас на его использование. В мире с открытым исходным кодом это может быть не такой большой проблемой (хотя люди могут просто перестать развиваться на нем, и он становится устаревшим), но что, если компания, у которой вы покупаете его, прекращает продукт или выходит из бизнеса?


Если вы строите для разных платформ, вы в конечном итоге будете использовать разные компиляторы. Кроме того, компиляторы C++ всегда немного отстают от стандарта C++, что означает, что они обычно меняют свою приверженность к нему с течением времени. Если вы нацелите общий знаменатель на все основные компиляторы, стоимость обслуживания кода будет ниже.


Это очень распространено для приложений (особенно приложений с открытым исходным кодом), которые другие разработчики хотели бы использовать разные компиляторы. Некоторые предпочитают использовать Visual Studio с компилятором MS для целей разработки. Некоторые предпочитают использовать компилятор Intel для заявленных преимуществ производительности и тому подобное.


Итак, вот причины, которые я могу придумать

  • Если скорость является самой большой проблемой, и есть специальный, высоко оптимизированный компилятор для некоторых платформ
  • Если вы создаете библиотеку с интерфейсом C++ (классы и шаблоны, а не только функции). Из-за искажения имен и других вещей библиотека должна быть скомпилирована с тем же компилятором, что и клиентский код, и если клиент хочет использовать Visual C++, он должен иметь возможность скомпилировать lib с помощью это
  • Если вы хотите поддержать очень редкую платформу, которая не имеет поддержки gcc

(для меня эти причины не важны, так как я хочу создать библиотеку, которая использует C++ внутри, но имеет интерфейс C.)


обычно это причины, которые я нашел:

  • кросс-платформенный (windows, linux, mac)
  • разные разработчики делают разработку на разных ОС (хотя это не оптимально, это происходит - тестирование обычно происходит только на целевой платформе).
  • компилятор компании выходят из бизнеса - или остановить развитие на этом языке. Если вы знаете, что ваша программа компилируется / работает хорошо с помощью другого компилятора, вы покрыли свой ставка.

Я уверен, что есть и другие ответы, но это самые распространенные причины, с которыми я столкнулся до сих пор.


несколько проектов используют gcc / G++ как компилятор "изо дня в день" для нормального использования, но каждый раз будет проверять, чтобы их код соответствовал стандартам с компилятор Comeau C / C++. Их веб-сайт выглядит как кошмар, и компилятор не является бесплатным, но он известен как, возможно, самый совместимый со стандартами компилятор вокруг, и предупредит вас о том, что многие компиляторы будут молча принимать или явно разрешать как нестандартное расширение (да, я смотрю на вас, Г-Н I-don't-mind-and-actually-actively-support-your-efforts-to-do-pointer-arithmetic-on-void-pointers-GCC).

компиляция так часто с таким строгим компилятором, как Comeau (или, что еще лучше, компиляция с таким количеством компиляторов, как вы можете получить в свои руки), позволит вам узнать об ошибках, которые могут возникнуть при попытке скомпилировать ваш код, вещи, которые ваш компилятор позволяет вам делать, что он не должен, и потенциально вещи, которые другие компиляторы не позволяют вам делать, что вы должны. Пишу ANSI C или c++ должны быть важной целью для кода, который вы собираетесь использовать на нескольких платформах, и использование наиболее совместимого со стандартами компилятора-хороший способ сделать это.

(отказ от ответственности: у меня нет Comeau, и я не планирую его получать, и не могу его получить, потому что я на OS X. Я делаю C, а не C++, поэтому я могу на самом деле знать весь язык, и средний компилятор C намного ближе к стандарту C, чем средний компилятор C++ к стандарту C++, поэтому для меня это меньше проблем. Просто хотел поместить это сюда, потому что это начало выглядеть как реклама для Comeau. Его следует рассматривать скорее как рекламу для компиляции со многими различными компиляторами.)


Это один из тех вопросов "это зависит". Для открытого исходного кода хорошо быть переносимым на несколько компиляторов. В конце концов, люди в разных средах строят код, это своего рода точка.

но для закрытого источника, это гораздо менее важно. Вы никогда не хотите напрасно свяжите себя с определенным компилятором. Но в большинстве мест, где я работал, переносимость компилятора даже не вошла в топ-10 вещей, о которых мы заботились. Даже если вы никогда не используйте ничего, кроме standerd C/C++, переключение большой базы кода на новый компилятор-опасная вещь. Компиляторы имеют ошибки. Иногда ваш код будет иметь ошибки, которые являются доброкачественными на одном компиляторе, но внезапно проблема на другом.

Я помню один переход, где один компилятор думал, что этот код был очень хорошо:

for (int ii = 0; ii < n; ++ii) { /* some code */ }
for (int ii = 0; ii < y; ++ii) { /* some other code */ }

в то время как новый компилятор жаловался, что ii было объявлено дважды, поэтому нам пришлось пройти весь наш код и объявить переменные цикла до петля для переключения.

одно место, где я работал, было настолько осторожным с непреднамеренными побочными эффектами коммутаторов компилятора, что они проверяли конкретные компиляторы в каждом исходном дереве, и как только код будет отправлен, будет использовать только один компилятор для обновления этой базы кода - навсегда.

другое место будет опробовать новый компилятор в течение 6 месяцев до года, прежде чем они переключатся на него.


Я нахожу gcc медленным компилятором в windows (нечего сравнивать с linux). Поэтому я (иногда) хочу скомпилировать свой код под другими компиляторами, просто для более быстрых циклов разработки.


Я не думаю, что кто-то упоминал об этом до сих пор, но другая причина может быть доступ к определенным функциям платформы: У многих поставщиков операционных систем есть специальные версии GCC или даже их собственные домашние (или лицензированные и модифицированные) компиляторы. Поэтому, если вы хотите, чтобы ваш код хорошо работал на нескольких платформах, вам может потребоваться выбрать правильный компилятор на каждой платформе. Будь то встроенная система, MacOS, Windows и т. д.

кроме того, скорость может быть проблема (как скорость компиляции и скорость выполнения). Еще в дни PPC GCC выпускала печально известный медленный код на процессорах PowerPC, поэтому Apple поставила кучу инженеров на GCC, чтобы улучшить это (GCC был очень новым для Mac, и все другие платформы PowerPC были небольшими). Платформы, которые используются меньше, могут быть оптимизированы меньше в GCC, поэтому использование другого компилятора, написанного для этой платформы, может быть быстрее.

но в качестве окончательного резюме: хотя есть идеальное значение при компиляции на нескольких компиляторах, в практика, это в основном интересно для кросс-платформенного программного обеспечения (и программного обеспечения с открытым исходным кодом, потому что оно часто делается кросс-платформенным довольно быстро, и участникам легче, если они могут использовать свой компилятор по выбору вместо того, чтобы изучать новый). Если вам нужно грузить на одной платформе только,доставка и техническое обслуживание обычно гораздо важнее, чем инвестировать в создание нескольких компиляторов, если вы выпускаете только сборки, сделанные с одним из их. Тем не менее, вы захотите четко документировать любые отклонения от стандарта (например, GCC-isms), чтобы облегчить работу по переносу, если вам когда-либо придется это делать.


и компилятор Intel и llvm быстрее, чем gcc. Реальными причинами использования gcc являются

  • бесконечная аппаратная поддержка (ни на одном другом компиляторе вы не можете скомпилировать код lego mindstorm на своем старом DEC).

  • дешево

  • лучший оптимизатор spagety в бизнесе.