GCC 4.8: Does -Og подразумевает -g?
Недавно была обновлена документация для GCC 4.8, которая теперь вводит новый переключатель оптимизации -Og
. Это
[..] обращается к необходимости быстрой компиляции и превосходному опыту отладки при обеспечении разумного уровня производительности во время выполнения. Общий опыт разработки должен быть лучше уровня оптимизации по умолчанию -O0.
Этот переключатель подразумевает -g
или мне нужно добавить его в мой CXXFLAGS
вручную?
Ответы
Ответ 1
Короткий ответ: Нет, вы все равно должны добавить -g
вручную.
Длинный ответ:
Я изо всех сил пытался найти жесткий ответ прямо из источника, поэтому решил сам проверить его, используя описанные здесь методы: Как проверить, была ли скомпилирована программа с помощью отладочных символов?
Я построил исполняемый файл с флагом -O3
и без -g
. Использование objdump --syms <file> | grep debug
ничего не дало, как ожидалось.
Затем я построил исполняемый файл с -g
и без каких-либо флагов оптимизации. Та же команда objdump
дала шесть результатов, таких как:
0000000000000000 l d .debug_info 0000000000000000 .debug_info
Наконец, я создал исполняемый файл с флагом -Og
и без -g
. Команда objdump
ничего не дала. Это означает, что в этом случае присутствуют символы отладки не.
Пока я не могу найти явную документацию непосредственно из GCC, Gentoo Wiki (как упоминалось ранее Марко Сканнадинари) подтверждает мое утверждение что -Og
не означает -g
.
Ответ 2
Взгляд в исходный код GCC 4.9.2 (gcc/opts.c) показал, что -Og
совпадает с -O1
, но с некоторыми отключенными флагами, что может привести к худшему опыту отладки:
/* in function default_options_optimization: */
case OPT_Og:
/* -Og selects optimization level 1. */
opts->x_optimize_size = 0;
opts->x_optimize = 1;
opts->x_optimize_fast = 0;
opts->x_optimize_debug = 1;
break;
Несколько шагов спустя функция maybe_default_option
вызывается с набором опций и флагом x_optimize_debug
. Параметры, отмеченные OPT_LEVELS_1_PLUS_NOT_DEBUG
, OPT_LEVELS_1_PLUS_SPEED_ONLY
и OPT_LEVELS_2_PLUS_SPEED_ONLY
, не будут включены, если используется -Og
.
Так вот откуда происходит утверждение "должно быть лучше, чем -O0". -Og
находится между -O0
и -O1
. Это не влияет на включение отладочной информации, которая была бы включена с помощью опций -g
. Вы, вероятно, также будете интересоваться различными опциями -g
:
- Опция
-ggdb
переопределяет -g
. То есть, если вы установите -ggdb
после -g
, параметр -g
будет эффективно проигнорирован.
- Опция
-g
равна -g2
, а опускание -g
совпадает с -g0
.
- Вариант
-g3
создает большую часть отладки, чем -g2
, а также -ggdb3
против -ggdb2
.
- Более высокие уровни оптимизации приводят к увеличению секций кода и отладки. (
-O0
< -O1
< -Og
< -O2
< -O3
).
-
strip --strip-debug
привел к тому же размеру объекта, который не зависит от уровней -g
. Это соответствовало ожиданию того, что только уровень -O
влияет на фактический код, где -g
определяет разделы отладки.
-
strip --keep-debug
приводит к объектам, в которых в качестве размера доминирует уровень -g
, за которым следуют уровни -O
. (поэтому -g0 -O3
меньше -g3 -O0
).
Примечание: здесь я не считаю время компилировать. Это, скорее всего, будет увеличиваться с более агрессивными уровнями оптимизации. Я ожидал бы, что уровни отладки будут лишь незначительно влиять на время (по сравнению с оптимизацией), поскольку это просто означает, что во время пропусков нужно отслеживать дополнительные детали.
Вот команда, которую я использовал для проверки фактического поведения (также сравните -ggdbX
вместо -gX
):
for g in -g0 -g2 -g3;do
for O in -O0 -O1 -O2 -O3 -Og; do
flags="$g $O";
gcc -fPIC -rdynamic -c -Wall -Wextra -Ilib ltunify.c -o obj/gL_"${flags// /_}_.o" $flags || break;
done;
done