понедельник, 15 сентября 2008 г.

Компиляцию варнингом не испорть...

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

Я очень люблю предупреждения компилятора. :) В своих проектах я всегда выставляю -Wall -Wextra -Weffc++. Последний тоже весьма полезен, поскольку позволяет писать на C++ в соответствии с рекоммендациями Скота Майерса, что позволяет избежать лишних побочных эффектов.

Но вот некоторые, не будем показывать пальцем, хотя это boost, не используют эту опцию. В результате чего вы выходе имею горы предумреждений и никакой возможности их устранить. Можно конечно патчить boost, или даже слать патчи разработчикам, но мне некогда этим заниматься. Но и отключать любимые варнинги тоже не хочется. Должен быть путь управлять этим на уровне кода.

Вот в MSVC испокон веков существует #pragma warning, которая легко и непринужденно позволяет делать все это. Но в gcc все обстоит не столь радужно.

Вероятно, в gcc-2.96 появилась #pragma GCC system_header. Которая должна отключить генерацию последующего кода, при условии, что используется она в теле файла инклюда. Но мне почему-то не удалось заставить ее работать. Может быть ей требуется исключительно #include <>, В то время как локальные инклюды #include "" не прокатывают? не знаю.

Вычитал, что есть #pragma GCC diagnostic, правда появилась эта прагма только в gcc-4.2. Она позволяет выбирать реакцию на предупреждения от игнорирования до ошибки.

#pragma GCC diagnostic ignored "-Weffc++"
#include <boost/...>
#pragma GCC diagnostic warning "-Weffc++"

Это дело работает, но основной gcc в моей Gentoo на данный момент 4.1.2, Хотелось бы заставить компилиться без ошибок и на нем. Как же юзается этот system_header???

11 коммент.:

Анонимный комментирует...

Если не принципиально, какой версией gcc собирать свой софт, мне кажеться, проще gcc:4.2 из слота юзать для этих целей.

Андрей Валяев комментирует...

Это верно, можно использовать gcc-4.2 повсеместно, но мне кажется это некрасивым по отношению к остальной системе, которая всетаки живет под флагом x86. :)

К тому же чисто теоретический интерес. Должен же работать system_header! :)

Анонимный комментирует...

Про теоретический интерес - согласен :)

А про всю систему - я имел ввиду собирать именно свой софт можно под 4.2 (gcc-config-ом переключаться просто по мере необходимости). Система со своими приложения пусть себе существует как и раньше.

PS.
С jre вообще здорово в Gentoo сделали, мало того, что через eselect можно java-vm выбирать, так ещё и есть настройка для system & user отдельная! Вот такого для gcc мне кажется нехватает.

Андрей Валяев комментирует...

Но меня лично ломает постоянно переключать :) буду забывать и компилить все разными компиляторами.

Мало того, что для qemu итак стоит gcc:3.4. :)

Анонимный комментирует...

Можно конечно патчить boost, или даже слать патчи разработчикам, но мне некогда этим заниматься.
Ты что, это же Open Source 8-|, если видишь где-то баг, поправь его и опубликуй патч.

Вот в MSVC испокон веков существует #pragma warning, которая легко и непринужденно позволяет делать все это.
#pragma warning была практически везде. Даже в BorlandC 3 была некоторая аналогия через #pragma option... Синтаксис часто разный (например, WatcomC - #pragma warning NNN N), но это не большая проблема.

Вероятно, в gcc-2.96 появилась #pragma GCC system_header. ... Но мне почему-то не удалось заставить ее работать.
:-D Не вижу здесь иронии про ложку дегтя.

Млин, ну почему GCC вот .... такой? Банально неудобно под него писать. Почему бы не добавить __declspec (или _export/_import, как в BorlandC, если не любишь мсофтное), или #pragma warning, __asm общеиспольуемый?

Андрей Валяев комментирует...

2coff: Млин, ну почему GCC вот .... такой? Банально неудобно под него писать. Почему бы не добавить __declspec (или _export/_import, как в BorlandC, если не любишь мсофтное), или #pragma warning, __asm общеиспольуемый?

Чем же интересно __declspec отличется от __attribute__? И asm как asm...

Вообще применение в проекте асма должно иметь очень и очень веские причины... Да и с прагмами лучше не злоупотреблять, а то вдруг компилятор придется менять... Это все специфики.

Анонимный комментирует...

__declspec используется MSVC, BorlandC, WatcomC, ... Причем одинаково для всех компиляторов. __attribute__ - только GCC, и по-разному для объявления и определения... сам же писал.

И asm как asm...
Да не asm как asm, а совершенно не совместимая ни с чем конструкция.
Разработчики GCC прут одними им известным путем, не смотря вокруг.
Выдержка из WatcomC help:
[i]The asm directive (e.g., asm( "mov r0,1" ); ) is a non-portable construct. The Open Watcom C++ compiler treats all asm directives like comments.[/i]
В то же время про __asm:
There is an alternative to Open Watcom's auxiliary pragma method for creating in-line assembly code. You can use one of the _asm or __asm keywords to imbed assembly code into the generated code. The following is a revised example of the cursor positioning example introduced above.

Вообще применение в проекте асма должно иметь очень и очень веские причины.
Когда будешь писать кодек (я модифицировал Theora), тогда поймешь, как asm может быть полезен.

Это все специфики.
Некие "специфики" давно уже стандарт де факто... и постепенно переходят в де юре.

Андрей Валяев комментирует...

2coff: насчет того что более распространено: MSVC, Watcom, Borland с одной стороны или gcc с другой - это еще поспорить можно.. :)

как ассемблер вообще может быть portable? если только с компилятора на компилятор, да и то это ИМХО нужно гораздо меньше чем переход на одном компиляторе с платфрмы на платформу.

Когда решаешь одну конкретную задачу на одной платформе - зачастую и не нужно знать портируемо оно или нет.

А вот когда встает задача перенести с Watcom на gcc или с IA32 на ARM. Вот тогда и возникают проблемы, которые никакими стандартами на asm не решить.

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

Хорошо написанный c/c++ код не сильно проиграет асму.

Анонимный комментирует...

Смотри, ты иногда вынужден иногда вставлять __asm в код... Например, Theora с Си кодеком тормозная штука, приходится использовать asm.

А потом появляется необходимость потестить, как проект собирается на других компиляторах, под другую ось. К примеру, компилишь под Win32 на MSVC, под Linux на GCC. И как быть, вставлять бесконечные #ifdef?

asm - это не только системное программирование... я бы сказал - далеко не только.

С другой стороны, понятно, что написать аналог GAS, использующий Intel синтаксис, - это затраченное время.

Есть вариант - MMX/SSE интринсики, но они есть далеко не на всех компиляторах. И интринсики на GCC наверняка будут несовместимы с ICC/MSVC :-D.

Вот тогда и возникают проблемы, которые никакими стандартами на asm не решить.
Да я и не говорю, что это одна проблема. Можно еще взять __attribute__(( )). Да много чего еще есть, это да.

С/С++ не справляются там, где используется сложный кодер/декодер (битовые операции, сдвиги и shuffle), который, будучи переписан на регистры, дает некий прирост.

Андрей Валяев комментирует...

2coff: gas поддерживает intel синтакс... как-то там -msyntax=intel, точно не помню.

инстринсики в gcc естественно не совместимы с msvc... да и использование всяких MMX/SSE сродни использованию ассемблера. Непереносимо.

Что касается битовых операций, не думаю что ты на ассемблере много выиграешь. Можно сравнить. Тут все упирается в качество оптимизации компилятора. Причем то, что сегодня тормозит, завтра может полететь без переписывания на ассемблер. :)

И уж если пишешь на ассемблере - то для каждой платформы нужно писать свою версию.

Анонимный комментирует...

Хорошая новость про GAS, я посмотрю.

инстринсики в gcc естественно не совместимы с msvc
Я имею в виду MMX/SSE* интринсики. И основной тут не MSVC, а Intel C/C++ компилятор.

Что касается битовых операций, не думаю что ты на ассемблере много выиграешь.
Банальный пример - конвертация BGRA в RGBA. На SSE - одна инструкция на 4 пиксела, плюс загрузка/сохранение (причем с предварительным использованием PREFETCH для последовательности пикселов). На С/С++ один-то пиксел конвертнуть не удасться нормально. Сравнить действительно можно, но все понятно и так, я думаю. И компилятор тут не поможет, ибо тут язык виновен.

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

Неперносимость на уровне платформ - это нормально. К этому все готовы. А разница между компиляторами на одной платформе раздражает.

Понятно, что все это решаемо, можно использовать макросы, написать нечто вроде IDL и т.п. Да.