Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— |
programming:kernel_module_26 [2013/12/16 13:57] (aktuell) idefix angelegt |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | |||
+ | ====== | ||
+ | ===== With Normal Makefile | ||
+ | The hello world program. With normal Makefile, the Makefile: | ||
+ | < | ||
+ | ARCH := i386 | ||
+ | CROSS_COMPILE : | ||
+ | # | ||
+ | INSTALL := install -c | ||
+ | |||
+ | INSTALL_DATA : | ||
+ | KERNELVERSION : | ||
+ | # KERNELVERSION : | ||
+ | EXTRA_CFLAGS := -g -I/ | ||
+ | |||
+ | KDIR := / | ||
+ | PWD := $(shell pwd) | ||
+ | |||
+ | obj-m := hello_world.o | ||
+ | |||
+ | all: | ||
+ | $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) | ||
+ | # gcc -o scope scope.c | ||
+ | clean: | ||
+ | rm -f *.o *.ko *.mod.o *.mod.c .*.{cmd, | ||
+ | rm -rf config.status config.log autom4te*.cache .tmp_versions | ||
+ | </ | ||
+ | |||
+ | The hello_world.c: | ||
+ | < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | MODULE_LICENSE(" | ||
+ | |||
+ | |||
+ | int init_module(void) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | void cleanup_module(void) | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== With Automake and Autoconf | ||
+ | |||
+ | create the directory structure: | ||
+ | < | ||
+ | mkdir test | ||
+ | cd test | ||
+ | mkdir src | ||
+ | mkdir m4 | ||
+ | touch NEWS | ||
+ | touch README | ||
+ | touch AUTHORS | ||
+ | touch ChangeLog | ||
+ | </ | ||
+ | |||
+ | Now we create the Makefile.am: | ||
+ | < | ||
+ | ACLOCAL_AMFLAGS = -I m4 | ||
+ | |||
+ | SUBDIRS = src | ||
+ | EXTRA_DIST = autogen.sh | ||
+ | </ | ||
+ | * ACLOCAL_AMFLAGS says aclocal where to look for additional m4 macros | ||
+ | * SUBDIRS are processed | ||
+ | * EXTRA_DIST says to include the autogen.sh in our distribution tar | ||
+ | |||
+ | Now we create a m4 script to get the kernel-source named m4/ | ||
+ | < | ||
+ | dnl check for kernel source | ||
+ | |||
+ | AC_DEFUN([AC_PATH_KERNEL_SOURCE_SEARCH], | ||
+ | [ | ||
+ | kerneldir=missing | ||
+ | kernelext=ko | ||
+ | no_kernel=yes | ||
+ | |||
+ | if test `uname` != " | ||
+ | kerneldir=" | ||
+ | else | ||
+ | for dir in / | ||
+ | if test -d $dir; then | ||
+ | kerneldir=`dirname $dir/ | ||
+ | no_kernel=no | ||
+ | fi; | ||
+ | done | ||
+ | fi | ||
+ | |||
+ | if test x${no_kernel} != xyes; then | ||
+ | if test -f ${kerneldir}/ | ||
+ | if test " | ||
+ | ac_pkss_makefile=`mktemp / | ||
+ | else | ||
+ | ac_pkss_makefile=/ | ||
+ | fi | ||
+ | cat ${kerneldir}/ | ||
+ | echo " | ||
+ | echo " echo \$(CC)" | ||
+ | |||
+ | kernelcc=`make -s -C ${kerneldir} -f ${ac_pkss_makefile} lirc_tell_me_what_cc_is` | ||
+ | |||
+ | echo " | ||
+ | echo " echo \$(VERSION)" | ||
+ | echo " | ||
+ | echo " echo \$(PATCHLEVEL)" | ||
+ | version=`make -s -C ${kerneldir} -f ${ac_pkss_makefile} lirc_tell_me_what_version_is` | ||
+ | patchlevel=`make -s -C ${kerneldir} -f ${ac_pkss_makefile} lirc_tell_me_what_patchlevel_is` | ||
+ | if test ${version} -eq 2; then | ||
+ | if test ${patchlevel} -lt 5; then | ||
+ | kernelext=o | ||
+ | fi | ||
+ | fi | ||
+ | rm -f ${ac_pkss_makefile} | ||
+ | else | ||
+ | kerneldir=" | ||
+ | no_kernel=yes | ||
+ | fi | ||
+ | fi | ||
+ | ac_cv_have_kernel=" | ||
+ | kerneldir=\" | ||
+ | kernelext=\" | ||
+ | kernelcc=\" | ||
+ | ] | ||
+ | ) | ||
+ | |||
+ | AC_DEFUN([AC_PATH_KERNEL_SOURCE], | ||
+ | [ | ||
+ | AC_CHECK_PROG(ac_pkss_mktemp, | ||
+ | AC_PROVIDE([AC_PATH_KERNEL_SOURCE]) | ||
+ | AC_MSG_CHECKING(for Linux kernel sources) | ||
+ | |||
+ | AC_ARG_WITH(kerneldir, | ||
+ | [ --with-kerneldir=DIR | ||
+ | |||
+ | ac_kerneldir=${withval} | ||
+ | AC_PATH_KERNEL_SOURCE_SEARCH, | ||
+ | |||
+ | ac_kerneldir="" | ||
+ | AC_CACHE_VAL(ac_cv_have_kernel, | ||
+ | ) | ||
+ | | ||
+ | eval " | ||
+ | |||
+ | AC_SUBST(kerneldir) | ||
+ | AC_SUBST(kernelcc) | ||
+ | AC_SUBST(kernelext) | ||
+ | AC_MSG_RESULT(${kerneldir}) | ||
+ | ] | ||
+ | ) | ||
+ | </ | ||
+ | |||
+ | Create now the file configure.ac: | ||
+ | < | ||
+ | dnl Proccess this file with autoconf to produce a configure script. | ||
+ | AC_INIT(hello_world, | ||
+ | AC_PREREQ(2.5) | ||
+ | AC_CONFIG_SRCDIR(src/ | ||
+ | AC_CONFIG_AUX_DIR(config) | ||
+ | |||
+ | AM_INIT_AUTOMAKE(1.8) | ||
+ | |||
+ | dnl Checks for programms | ||
+ | AC_PROG_CC | ||
+ | |||
+ | AC_PATH_KERNEL_SOURCE | ||
+ | |||
+ | default_moduledir=/ | ||
+ | AC_ARG_WITH(moduledir, | ||
+ | [ --with-moduledir=DIR | ||
+ | moduledir=${withval}, | ||
+ | moduledir=${default_moduledir}) | ||
+ | |||
+ | AC_SUBST(moduledir) | ||
+ | |||
+ | AC_OUTPUT(Makefile src/ | ||
+ | </ | ||
+ | * AC_INIT init the file with project name, version and email address | ||
+ | * AC_CONFIG_AUX_DIR says autoconf to store tmp file in the dir config to keep the main dir clean | ||
+ | * AC_CONFIG_SRCDIR where is the program to compile | ||
+ | * AM_INIT_AUTOMAKE directive to generate the Makefile | ||
+ | * AC_PROC_CC check for gcc | ||
+ | * AC_OUTPUT generate the following files from the *.in or *.am files | ||
+ | |||
+ | Now generate the src/ | ||
+ | < | ||
+ | EXTRA_DIST = Makefile.kernel Makefile.common | ||
+ | EXTRA_PROGRAMS = automake_dummy | ||
+ | automake_dummy_SOURCES = hello_world.c | ||
+ | |||
+ | module_DATA = hello_world.o | ||
+ | |||
+ | include ./ | ||
+ | </ | ||
+ | * " | ||
+ | * LIBRARIES for static libraries (.a) | ||
+ | * LTLIBRARIES for Libtool-based shared libraries (.la) | ||
+ | * HEADERS | ||
+ | * ... | ||
+ | |||
+ | * The prefix " | ||
+ | * bin_ - for programs, e.g., / | ||
+ | * lib_ - where libraries are placed, e.g., / | ||
+ | * include_ - where header files are placed, e.g., / | ||
+ | * pkginclude_ - e.g., / | ||
+ | * noinst_ - files that will not be copied anywhere by make install | ||
+ | * ... | ||
+ | |||
+ | < | ||
+ | Note: The user can specify the locations of these directories when running the configure script. For more info, run configure --help.</ | ||
+ | |||
+ | * " | ||
+ | * CFLAGS, CPPFLAGS, CXXFLAGS - extra arguments passed to the compiler/ | ||
+ | * LIBADD - extra objects for a library | ||
+ | * LDADD - extra objects for a program | ||
+ | * LDFLAGS - extra arguments passed to the linker | ||
+ | * ... | ||
+ | |||
+ | Create the Makefile.common: | ||
+ | < | ||
+ | KERNEL_LOCATION=@kerneldir@ | ||
+ | KBUILD_VERBOSE = 1 | ||
+ | |||
+ | ARCH := i386 | ||
+ | CROSS_COMPILE : | ||
+ | # | ||
+ | |||
+ | # | ||
+ | # KERNELVERSION : | ||
+ | HELLO_WORLD_EXTRA_CFLAGS = -g -I/ | ||
+ | |||
+ | PWD := $(shell pwd) | ||
+ | |||
+ | |||
+ | export HELLO_WORLD_EXTRA_CFLAGS module_DATA | ||
+ | |||
+ | $(module_DATA): | ||
+ | mv Makefile Makefile.automake | ||
+ | cp Makefile.kernel Makefile | ||
+ | $(MAKE) -C $(KERNEL_LOCATION) SUBDIRS=$(PWD) modules \ | ||
+ | KBUILD_VERBOSE=$(KBUILD_VERBOSE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) | ||
+ | mv Makefile.automake Makefile | ||
+ | |||
+ | CLEANFILES = $(module_DATA) .$(module_DATA).{cmd, | ||
+ | $(module_DATA: | ||
+ | Modules.symvers *~ | ||
+ | |||
+ | clean: | ||
+ | -test -z " | ||
+ | rm -rf .tmp_versions | ||
+ | </ | ||
+ | |||
+ | Create Makefile.kernel: | ||
+ | < | ||
+ | EXTRA_CFLAGS += $(HELLO_WORLD_EXTRA_CFLAGS) | ||
+ | |||
+ | obj-m=$(module_DATA) | ||
+ | MI_OBJS = $(module_DATA) | ||
+ | |||
+ | all clean: | ||
+ | $(warning **************************************************) | ||
+ | $(warning *** Makefile trick not undone, trying to recover *) | ||
+ | $(warning **************************************************) | ||
+ | mv Makefile.automake Makefile | ||
+ | $(MAKE) $@ | ||
+ | |||
+ | # The following is needed for 2.5 kernels and also let's the makefile work | ||
+ | # when things get screwed. | ||
+ | ifneq (, | ||
+ | include $(KERNEL_LOCATION)/ | ||
+ | endif | ||
+ | </ | ||