Подстановка переменных в Makefile, очевидно, не выполнена, хотя: = используется в объявлении - PullRequest
4 голосов
/ 05 января 2012

У меня есть основной модуль ядра, с которым связываются другие модули ядра. Я структурировал модули так (концептуально):

main module/
           |
            \drivers/
                    |
                    |\driver1
                    |\driver2
                     \driver3

Поскольку это модули ядра, мне нужно скомпилировать их следующим образом:

make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules

Однако, поскольку Makefile драйверов может быть вызван из предыдущих каталогов, мне нужно сделать $(shell pwd) перед вызовом другого make (linux make). Итак, Makefile теперь выглядит так:

CURRENT_DIR := $(shell pwd)

.PHONY: all
all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) modules

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

EXTRA_CFLAGS += -I../..

и сразу понял, почему это не работает (относительный путь будет к / lib / module / ... не к текущему каталогу). Поэтому я изменил его на:

MAIN_MODULE_HOME := $(CURRENT_DIR)/../..
EXTRA_CFLAGS += -I$(MAIN_MODULE_HOME)

Как ни странно, это не работает! Если я напишу

EXTRA_CFLAGS += -Ipath/I/get/from/pwd/../..

вручную, компилируется! Может кто-нибудь объяснить, что я делаю не так? Перед вызовом make я echo ed $(CURRENT_DIR) и $(MAIN_MODULE_HOME) и переменные имеют смысл.

Я знаю, что EXTRA_CFLAGS оценивается не сразу, но, поскольку CURRENT_DIR и MAIN_MODULE_HOME объявлены с :=, я не понимаю, как все портится.

(Если кто-то может лучше сформулировать заголовок вопроса, пожалуйста, сделайте!)

Ответы [ 2 ]

7 голосов
/ 05 января 2012

Вы должны передать EXTRA_CFLAGS, чтобы сделать так:

$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(CURRENT_DIR) \
           EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules

Обновление:

Содержимое driver1 / Makefile читается дважды: сначала - когда вы запускаете make в каталоге driver1второе - по системе Kbuild.

Во-первых, CURRENT_DIR := $(shell pwd) оценивается как /home/users/.../main module/drivers/driver1.Во-вторых, Kbuild оценивает CURRENT_DIR := $(shell pwd) что-то вроде /usr/src/linux-headers-2.6.32-33-generic/

Эта ситуация описана в LDD3, ch2, p24

Хитрость заключается в том, чтобы написать ваш make-файл следующим образом:

# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
    obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD  := $(shell pwd)
default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
#endif
0 голосов
/ 05 января 2012

Скорее всего, из-за рекурсивного аромата EXTRA_CFLAGS, который фактически расширяется в подкомпании, у которого нет доступа к MAIN_MODULE_HOME, указанному в нем.

Сначала попробуйтеexport MAIN_MODULE_HOME:

export MAIN_MODULE_HOME

Я бы также попытался сгладить EXTRA_CFLAGS перед его использованием (однако я не уверен, является ли это хорошей практикой для Kbuild):

EXTRA_CFLAGS := $(EXTRA_CFLAGS)
...