2011-04-19 9 views
5

मैं निर्देशिका संरचना के साथ लिनक्स कर्नेल बिल्ड सिस्टम (Kbuild, कर्नेल ≥2.6.28) का सामना कर रहा हूं और एक बड़ी परियोजना के लिए सिस्टम का निर्माण कर रहा हूं। चाहिएएक अलग ऑब्जेक्ट निर्देशिका में एक आउट-ऑफ-पेड़ लिनक्स कर्नेल मॉड्यूल का निर्माण

checkout/src/common/*.c   source files (common to Linux and other platforms) 
checkout/src/linux-driver/*.c  source files (for the Linux kernel driver) 
checkout/build/linux/Kbuild  Kbuild 
tmp/linux-2.6.xx/     where the Linux kernel is unpacked and configured 
output/linux-arm-debug/   where object files must end up 

निर्माण प्रक्रिया checkout के तहत कुछ भी संशोधित नहीं होना चाहिए, और मॉड्यूल का निर्माण: हमारी परियोजना एक बाहर के पेड़ लिनक्स कर्नेल मॉड्यूल शामिल है, और हमारी निर्देशिका संरचना इस तरह दिखता है (सरलीकृत, स्पष्ट रूप से) tmp/linux-2.6.xx के तहत कुछ भी संशोधित नहीं करें। सभी आउटपुट फाइलों को output/linux-arm-debug (या जो भी आर्किटेक्चर और डीबग संस्करण का निर्माण समय पर चुना गया था) के तहत समाप्त होना चाहिए।

मैं kbuild/modules.txt पढ़ा है, और मेरे Kbuild फ़ाइल लिखना शुरू किया:

MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG) 
obj-m += $(MOD_OUTPUT_DIR)/foo_mod.o 
$(MOD_OUTPUT_DIR)/our_module-objs := $(MOD_OUTPUT_DIR)/foo_common.o $(MOD_OUTPUT_DIR)/foo_linux.o 

यह जहां Kbuild जीवन से एक अलग निर्देशिका में वस्तु फ़ाइलों को संग्रहीत करने संभालती है। अब मैं foo_common.o को …/checkout/src/common/foo_common.c और foo_linux.o से …/checkout/src/linux-driver/foo_linux.c से संकलित करने की आवश्यकता कैसे निर्दिष्ट कर सकता हूं?

उत्तर

0

जबकि आपने अभी तक जो भी प्रयास नहीं किया है (या क्या आपको पहले से कोई समाधान मिला है) का उल्लेख नहीं किया है, ऐसा लगता है कि आपको बस modules.txt फ़ाइल को थोड़ा आगे जारी रखने की आवश्यकता है - अनुभाग 4.3:

--- 4.3 Several Subdirectories 

kbuild can handle files that are spread over several directories. 
Consider the following example: 

. 
|__ src 
| |__ complex_main.c 
| |__ hal 
| |__ hardwareif.c 
| |__ include 
|  |__ hardwareif.h 
|__ include 
    |__ complex.h 

To build the module complex.ko, we then need the following 
kbuild file: 

    --> filename: Kbuild 
    obj-m := complex.o 
    complex-y := src/complex_main.o 
    complex-y += src/hal/hardwareif.o 

    ccflags-y := -I$(src)/include 
    ccflags-y += -I$(src)/src/hal/include 

As you can see, kbuild knows how to handle object files located 
in other directories. The trick is to specify the directory 
relative to the kbuild file's location. That being said, this 
is NOT recommended practice. 

For the header files, kbuild must be explicitly told where to 
look. When kbuild executes, the current directory is always the 
root of the kernel tree (the argument to "-C") and therefore an 
absolute path is needed. $(src) provides the absolute path by 
pointing to the directory where the currently executing kbuild 
file is located. 
+3

मैं वह हिस्सा पढ़ा है, और मैं यह कैसे मेरी मदद करने के लिए के रूप में एक नुकसान में हूँ। उस उदाहरण में, 'complex_main.c' और' complex_main.o' एक ही निर्देशिका में हैं।मेरे निर्माण पेड़ में, स्रोत और निर्माण उत्पाद पूरी तरह से अलग हैं। – Gilles

1

मेरे असुरूप लेकिन प्रभावी समाधान उत्पादन पेड़ में स्रोत फ़ाइलों की प्रतिलिपि बनाना है।

FOO_SOURCES_DIR = $(src)/../../../checkout/src 
FOO_MOD_OUTPUT_DIR = ../../../output/linux-$(ARCH)-$(DEBUG) 

# Specify the object files 
obj-m += $(FOO_MOD_OUTPUT_DIR)/foo_mod.o 
FOO_MODULE_OBJS := $(FOO_MOD_OUTPUT_DIR)/foo_common.o $(FOO_MOD_OUTPUT_DIR)/foo_linux.o 
$(FOO_MOD_OUTPUT_DIR)/foo_mod-objs := $(FOO_MODULE_OBJS) 

# Where to find the sources 
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_common.c: $(FOO_SOURCES_DIR)/common/foo_common.c 
$(src)/$(FOO_MOD_OUTPUT_DIR)/foo_linux.c: $(FOO_SOURCES_DIR)/linux-driver/foo_linux.c 

# Rules to copy the sources 
FOO_COPIED_SOURCES = $(patsubst %.o,$(src)/%.c,$(FOO_MODULE_OBJS)) 
$(FOO_COPIED_SOURCES): 
     $(Q)mkdir -p $(@D) 
     cp -f $< [email protected] 
clean-files += $(FOO_COPIED_SOURCES) 
clean-dirs += $(FOO_MOD_OUTPUT_DIR) 
+0

कॉपी करें? कम से कम प्रतीकात्मक लिंक _once_ बनाओ और फिर इसे छोड़ दें! – Shahbaz

+1

@ शाहबाज प्रतीकात्मक लिंक हमेशा पेड़ों के निर्माण में काम नहीं करते हैं। उन्हें संग्रहकर्ताओं में सिम्लिंक के रूप में शामिल किया जाता है। मुझे कुछ बिंदु (उह) पर सांबा निर्यात पर भी काम करना पड़ा। लिनक्स कर्नेल बिल्ड पेड़ में कुछ हद तक स्रोत फ़ाइलों की प्रतिलिपि बनाना मूंगफली है। – Gilles

0

थोड़ा देर से, लेकिन ऐसा लगता O= flag की तरह तुम क्या जरूरत है।

+0

यह सही दिखता है। मुझे आश्चर्य होगा अगर मैंने कोशिश नहीं की थी, लेकिन यह थोड़ी देर हो चुकी है और मैं अन्य परियोजनाओं पर चली गई हूं, इसलिए मैं ईमानदारी से सुनिश्चित नहीं हो सकता। आपके सुझाव के लिए धन्यवाद, मैं इसे आजमाने का मौका ढूंढने की कोशिश करूंगा। – Gilles

+3

मेरे लिए काम नहीं कर रहा है - ऐसा लगता है कि 'ओ =' और 'KBUILD_OUTPUT' दोनों को उस बिंदु पर लागू करने की आवश्यकता है जहां आप कर्नेल स्वयं बनाते हैं, न केवल बाहरी मॉड्यूल। जो मैं देखता हूं वह स्रोत पेड़ के भीतर जेनरेट की गई फ़ाइलों को ढूंढने में त्रुटियों है - उदाहरण के लिए 'linux/version.h' - यह उन्हें ओ = स्थान में ढूंढ रहा है। – Greg

0

आप पर्यावरण परिवर्तनीय KBUILD_OUTPUT सेट कर सकते हैं। यह O= विकल्प के समान कार्य करता है; हालांकि, चूंकि यह एक पर्यावरण परिवर्तनीय है, इसलिए यह कई मेकफ़ाइलों को फैला सकता है जहां O= पारित नहीं किया जा सकता है या बाहर की निर्देशिका मॉड्यूल को बनाने की आवश्यकता है। मुझे कंपैट-वायरलेस मॉड्यूल का एक सेट बनाने की कोशिश करने के साथ यही समस्या थी और मुझे वास्तविक कर्नेल छवि निर्माण के लिए O= का उपयोग करने की आवश्यकता थी।

3

मुझे एक ही समस्या थी। मैंने निम्नानुसार linux_2_6_34/scripts/Makefile.build संशोधित किया।

ifdef SRCDIR 
src := $(SRCDIR) 
else 
src := $(obj) 
endif 

SRCDIR निर्देशिका स्रोत है।

मॉड्यूल संकलन करने के लिए, चलाने

make -c $(KDIR) M=$(Your_output_dir) SRCDIR=$(your source directory)` 
+0

तो बंद करें - सी-फाइल संकलित, लेकिन यह '.ko' (संस्करण 3.14.0) – Greg

+0

उत्पन्न करने के लिए अंतिम चरण लेने से इनकार करता है क्षमा करें - pebcak - मेरे Kbuild में एक बग था - यह चाल है - के साथ साबित करें कि यह किस निर्देशिका के बारे में थोड़ा उलझन में आता है और एक चरण में दोनों निर्देशिकाओं में Kbuild फ़ाइल होने की आवश्यकता होती है। यह – Greg

+0

पर जाने के लिए भुगतान करने के लिए एक छोटी सी कीमत है, यह काम करने लगता है लेकिन किसी कारण से मुझे काम करने के लिए आउटपुट निर्देशिका में खाली मेकफ़ाइल होना चाहिए (लिनक्स-4.1.6) –

2

यहाँ एक Makefile जो स्रोत पेड़ से बाहर करता है कर्नेल-वृक्ष मॉड्यूल (@ मार्क की टिप्पणी से रूपांतरित) से बाहर के लिए बनाता है ...

KDIR ?= /lib/modules/$(shell uname -r)/build 
BUILD_DIR ?= $(PWD)/build 
BUILD_DIR_MAKEFILE ?= $(PWD)/build/Makefile 

default: $(BUILD_DIR_MAKEFILE) 
    make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) modules 

$(BUILD_DIR): 
    mkdir -p "[email protected]" 

$(BUILD_DIR_MAKEFILE): $(BUILD_DIR) 
    touch "[email protected]" 

clean: 
    make -C $(KDIR) M=$(BUILD_DIR) src=$(PWD) clean 

ध्यान दें: आप अभी भी एक Kbuild फ़ाइल की आवश्यकता है ...

obj-m += my_driver.o 
+0

मुझे समझ में नहीं आया कि हमें अभी भी एक Kbuild फ़ाइल 'obj-m + = my_driver.o' –

+0

क्यों चाहिए, यह वरीयता का मामला है। यदि आप चाहते हैं कि आप इस लाइन को मेकफ़ाइल में जोड़ सकें। इसे Kbuild फ़ाइल में रखकर मेकफ़ाइल को 'ifneq ($ (KERNELRELEASE),) को हटाकर मेकफ़ाइल में इस कथन की सुरक्षा के लिए उपयोग किया जाता है। देखें: http://www.makelinux.net/ldd3/chp-2-sect-4.shtml –

+0

यह मेरी आवश्यकता के बहुत करीब है, लेकिन दुख की बात यह है कि यह मानता है कि 'मेकफ़ाइल' मॉड्यूल 'src' में है निर्देशिका, जो मेरे लिए मामला नहीं है (इसे ऑटोकॉन्फ़ द्वारा बनाया जा रहा है, इसलिए 'Makefile.in' स्रोत में है और बिल्ड/एम डीआईआर में' मेकफ़ाइल 'है, और इसी तरह केबिल्ड फाइलों के लिए)। – Miral

संबंधित मुद्दे