Подтвердить что ты не робот

Компиляция модуля ядра и KBUILD_NOPEDANTIC

Я заметил, что недавние ядра (начиная с 2.16.24?) не нравятся, если во внешнем модуле Kbuild изменен CFLAGS. Если параметр CFLAGS изменен, вы получите следующую ошибку в системе Linux Kbuild:

scripts/Makefile.build:46: *** CFLAGS was changed in "/some/path". Fix it to use EXTRA_CFLAGS.  Stop.

От здесь:

Внешние модули имеют в нескольких случаях модифицированную опцию gcc     путем изменения CFLAGS. Это никогда не было документировано и     была плохая практика.

Дополнительный email из LKML.

Почему это плохая идея? Что рационально?

4b9b3361

Ответ 1

Прежде всего, стоит упомянуть, что EXTRA_CFLAGS устарел некоторое время назад и заменяется на ccflags-y. Вы можете прочитать о намерении ccflags-y в Documentation/kbuild/makefiles.txt, раздел 3.7.

В принципе, эта переменная позволяет добавлять настройки к множеству флагов компиляции C, в пределах объема файла, где он назначен. Вы не должны изменять глобальные флаги, потому что это может иметь глобальное влияние вне вашего собственного make файла, что считается плохой практикой. Проверка, которую вы указали, проверяет, действительно ли глобальные флаги не изменялись включенными make файлами.

Интересно проверить, как ccflags-y, ранее известный как EXTRA_CFLAGS, в конечном итоге используется в процессе сборки. Отслеживание некоторых релевантных точек (но не всех, поскольку это остается как упражнение для читателя;-)) показывает следующее:

EXTRA_CFLAGS все еще можно использовать, согласно scripts/Makefile.lib

1 # Backward compatibility
2 asflags-y  += $(EXTRA_AFLAGS)
3 ccflags-y  += $(EXTRA_CFLAGS)

В том же файле показано, как ccflags-y заканчивается флагами компиляции C (а также показывает, что у вас есть другая переменная в вашем распоряжении, называемая CFLAGS_<filename>.o):

104 orig_c_flags   = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
105                  $(ccflags-y) $(CFLAGS_$(basetarget).o)
106 _c_flags       = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
...
133 __c_flags       = $(_c_flags)
...
147 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
148                  $(__c_flags) $(modkern_cflags)                           \
149                  -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)

Затем в scripts/Makefile.build определено правило компиляции:

234 cmd_cc_o_c = $(CC) $(c_flags) -c -o [email protected] $<

Обратите внимание, что это все рекурсивно расширенные переменные, используя =, а не :=, что означает, что ваше собственное значение ccflags-y вставляется в флага C, когда вы определяете его в своем собственном make файле.

Наконец, о KBUILD_NOPEDANTIC, о котором вы упоминаете в заголовке, но не в актуальном вопросе. Этот тест для измененного значения CFLAGS можно отключить, указав KBUILD_NOPEDANTIC любое значение - см. scripts/Makefile.build

47 ifeq ($(KBUILD_NOPEDANTIC),)
48         ifneq ("$(save-cflags)","$(CFLAGS)")
49                 $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y)
50         endif
51 endif

Файлы, указанные в этом ответе, были получены сегодня.

Теперь... не будучи экспертом в этой области и глядя дальше в make файлы после написания всей этой истории, есть вещь, которую я тоже не понимаю. Мне кажется, что CFLAGS не используется в системе сборки (неявно или явно), но KBUILD_CFLAGS is. Поэтому я задаюсь вопросом, действительно ли эта проверка изменений в CFLAGS должна быть проверкой изменений в KBUILD_CFLAGS.

Ответ 2

Linux makefiles build CFLAGS таким образом, который подходит для ядра.
Переопределение CFLAGS означает, что вы добавляете некоторые флаги и можете удалить некоторые флаги. Некоторые из удаленных флагов могут быть важны для правильной компиляции.