2011-04-19 17 views
5

私はLinuxカーネルビルドシステム(Kbuild、カーネル≧2.6.28)と、より大きなプロジェクトのディレクトリ構造とビルドシステムに直面しています。私たちのプロジェクトでは、外の木のLinuxカーネルモジュールが含まれている、と私たちのディレクトリ構造は、(明らかに簡略化され、)次のようになります。独立したオブジェクトディレクトリにツリー外のLinuxカーネルモジュールを構築する

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.cfoo_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

@Shahbazシンボリックリンクはビルドツリーでは常に機能しません。彼らはアーカイブにシンボリックリンクとして含まれる傾向があります。私はある時点でSambaの輸出に取り組まなければならなかった(ugh)。 Linuxカーネルビルドツリーのソースファイルのほんの一部をピーナッツにコピーします。 – Gilles

0

少し遅くなりましたが、O= flagが必要です。

+0

それは正しく見えます。私はそれを試していなかった場合私は驚くだろうが、それはしばらくしていると私は他のプロジェクトに移動したので、私は正直に確信することはできません。あなたの提案をありがとう、私はそれを試してみる機会を見つけようとします。 – Gilles

+3

私のために働いていない - 'O ='と 'KBUILD_OUTPUT'は、外部モジュールだけでなく、カーネル自体をビルドする時点で両方を適用する必要があるようです。私が見ているのは、ソースツリー内で生成されたファイルを見つけるエラーです。例えば、 'linux/version.h'はO =の場所でそれらを探しています。 – Greg

0

環境変数KBUILD_OUTPUTを設定できます。これはO=オプションに似ています。ただし、環境変数であるため、O=を渡すことができない、またはディレクトリ外モジュールを構築する必要がある複数のメイクファイルにまたがることがあります。私はこれと同じ問題をcompat-wirelessモジュールのセットを作成しようとしていたので、実際のカーネルイメージビルドには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

だから、c-ファイルはコンパイルされましたが、 '.ko'(バージョン3.14.0)を生成する最後のステップを拒否します – Greg

+0

申し訳ありません - pebcak - 私のKbuildにバグがありました。ただし、どちらのディレクトリで、どちらかの段階でKbuildファイルを両方のディレクトリに置く必要があるかどうか不安です。それは行くために支払う小さな値です – Greg

+0

これはうまくいくようですが何らかの理由でこれが動作するために出力ディレクトリに空のMakefileが必要です(linux-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

これは単なる問題です。必要ならば、この行をMakefileに追加することができます。これをKbuildファイルに置くと、Makefile内のこの文をガードするために使用される 'ifneq($(KERNELRELEASE)、)'テストを削除してMakefileを単純化します。 See:http://www.makelinux.net/ldd3/chp-2-sect-4.shtml –

+0

これは私が必要とするものにとても近いですが、悲しいことに、 'Makefile'モジュールが' src'にあると仮定しています私の場合はそうではありません(autoconfによって構築されているので、 'Makefile.in'はソースにあり、' Makefile'はbuild/Mdirにあり、同様にKbuildファイルにもあります)。 – Miral