概述:
通過Makefile傳遞宏參數(shù)進行挑揀編譯,是編程中常用的技術。
Windows我不會,也不想會。這里只談 Linux/GNU系統(tǒng)。
在Linux平臺下,編程大體分為兩種,內核態(tài)編程和用戶空間編程。對于內核態(tài)編程,對于大多數(shù)人而言,
都是采用內核模塊的方式,將自己的代碼加入到內核之中。用戶空間的編程就多種多樣了。
但是無論是在那種context下編程,我們使用的基本上都是GNU的工具:Make,Gcc,LD等。而且無論代碼要在那種context運行,都需要經(jīng)過預處理,編譯,連接,代碼優(yōu)化等過程。在這個過程之中,這里討論的只適用于預處理階段,也就是說選擇性的進行編譯。
由于在內核態(tài),通過kernel module的方式進行編譯的時候,程序員主要是借助于Linux kernel KBuild編譯系統(tǒng);然而,在用戶空間編程的時候,所有的工作都需要我們自己來作,所以兩者之間存在不同。
一. 用戶空間
因為實際上進行預處理的只是Gcc工具,而make工具只是一個解決依賴關系的工具。所以問題就簡化成如何通過make向gcc傳遞參數(shù)。
通過簡單的例子來說明:
hello.c
#include <stdio.h>
void main(void) {
#ifdef DEBUG
printf("you ask for debug!\n");
#endif
printf("we must say goodbye\n");
return;
}
Makefile:
ifeq ($(DEBUG),y)
CFLAGS := $(CFLAGS) -DDEBUG
endif
hello: hello.c
$(CC) $(CFLAGS) $< -o $@
執(zhí)行過程:
[ville@localhost test]$ ls
hello.c Makefile
[ville@localhost test]$ make
cc hello.c -o hello
[ville@localhost test]$ ./hello
we must say goodbye
[ville@localhost test]$ rm hello
[ville@localhost test]$ ls
hello.c Makefile
[ville@localhost test]$ make DEBUG:=y
cc -DDEBUG hello.c -o hello
[ville@localhost test]$ ./hello
you ask for debug!
we must say goodbye
[ville@localhost test]$
通過以上的簡單例子說明如何通過宏開關進行條件編譯。
二. 在內核空間的module形式
KBuild是Linux Kernel的編譯系統(tǒng),但是最終實際執(zhí)行編譯連接的還是GNU GCC LD。雖然我們是程序員,但是在KBuild的問題上,我們已經(jīng)成為了軟件的使用者。對于用戶而言,我們應當更多關注功能,會使用是最終目的,當然如果有時間學習一下KBuild也是十分有意義的!
有問題,看文檔!Linux Kernel一向以文檔不全不規(guī)范而聞名世界,但是這個KBuild的文檔還是有的,
linuxXXXXX/Documentation/kbuild 目錄下:
00-INDEX
kbuild.txt
kconfig-language.txt
kconfig.txt
makefiles.txt
modules.txt
有空還是要看看的!?。?br> 在makefile.txt 第284行,---3.7 Complilation Flags一節(jié)中有說明。
以前都是使用EXTRA_XFLAGS,現(xiàn)在還是支持,但是建議使用xxflags-y這些內置變量了。
ccflags-y:$(CC)的編譯選項添加這里,宏開關也在這里添加
asflags-y:as匯編器使用的
ldflags-y :ld鏈接器使用的
還是用一個例子來演示:
ville.c :
/**
* Author : ville lee
* Create Time : 2010/07/31
* Description : This module implements a virtual file system.
* Aimming at learning the theory of Linux VFS.
*
* Change Log :
* version author Date Log
*
*
*
* */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
/**
* init function of the module
*
* */
static int __init
ville_init(void)
{
#ifdef DEBUG
/* we give the debug message like: module name : function name : debug message */
printk(KERN_ALERT "ville :ville_init: you ask for debug!\n");
#endif
printk(KERN_ALERT "ville :ville_init: ville module init!\n");
return 0;
}
static void __exit
ville_exit(void)
{
#ifdef DEBUG
/* we give the debug message like: module name : function name : debug message */
printk(KERN_ALERT "ville :ville_exit: you ask for debug!\n");
#endif
printk(KERN_ALERT "ville :ville_exit: ville module exit!\n");
return;
}
module_init(ville_init);
module_exit(ville_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ville lee");
Makefile:
## if module is built in the kernel module
## system. Give the work to kbuild.
# provide the default value to module name and ccflags-y
ifeq ($(MODULE),)
MODULE := ville
endif
ifeq ($(DEBUG),y)
ccflags-y += -DDEBUG
endif
ifneq ($(KERNELRELEASE),)
obj-m := $(MODULE).o
else
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
.PHONY:clean
clean:
echo "cleaning ...."
rm modules.order Module.symvers \
$(MODULE).ko $(MODULE).mod.c \
$(MODULE).mod.o $(MODULE).o
echo "clean up"
操作:
[ville@localhost source]$ ls
Makefile ville.c ville.h
[ville@localhost source]$ make
make -C /lib/modules/2.6.35.13-91.fc14.i686.PAE/build M=/home/ville/Programming/VFS/villefs/source modules
make[1]: Entering directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'
CC [M] /home/ville/Programming/VFS/villefs/source/ville.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/ville/Programming/VFS/villefs/source/ville.mod.o
LD [M] /home/ville/Programming/VFS/villefs/source/ville.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'
[ville@localhost source]$ su
Password:
[root@localhost source]# insmod ville.ko
[root@localhost source]# tail /var/log/messages
Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
[root@localhost source]# rmmod ville
[root@localhost source]# tail /var/log/messages
Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
Aug 1 21:55:06 localhost kernel: [ 694.160046] ville :ville_exit: ville module exit!
[root@localhost source]# exit
exit
[ville@localhost source]$ ls
Makefile modules.order Module.symvers ville.c ville.h ville.ko ville.mod.c ville.mod.o ville.o
[ville@localhost source]$ make clean
echo "cleaning ...."
cleaning ....
rm modules.order Module.symvers \
ville.ko ville.mod.c \
ville.mod.o ville.o
echo "clean up"
clean up
[ville@localhost source]$ make DEBUG:=y
make -C /lib/modules/2.6.35.13-91.fc14.i686.PAE/build M=/home/ville/Programming/VFS/villefs/source modules
make[1]: Entering directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'
CC [M] /home/ville/Programming/VFS/villefs/source/ville.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/ville/Programming/VFS/villefs/source/ville.mod.o
LD [M] /home/ville/Programming/VFS/villefs/source/ville.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.35.13-91.fc14.i686.PAE'
[ville@localhost source]$ ls
Makefile modules.order Module.symvers ville.c ville.h ville.ko ville.mod.c ville.mod.o ville.o
[ville@localhost source]$ su
Password:
[root@localhost source]# insmod ville.ko
[root@localhost source]# tail /var/log/messages
Aug 1 21:44:24 localhost rtkit-daemon[1721]: Successfully made thread 1838 of process 1836 (/usr/bin/pulseaudio) owned by '500' RT at priority 5.
Aug 1 21:44:24 localhost rtkit-daemon[1721]: Successfully made thread 1839 of process 1836 (/usr/bin/pulseaudio) owned by '500' RT at priority 5.
Aug 1 21:44:24 localhost pulseaudio[1836]: bluetooth-util.c: Error from ListAdapters reply: org.freedesktop.DBus.Error.Spawn.ChildExited
Aug 1 21:44:26 localhost rtkit-daemon[1721]: Successfully made thread 1870 of process 1870 (/usr/bin/pulseaudio) owned by '500' high priority at nice level -11.
Aug 1 21:44:26 localhost pulseaudio[1870]: pid.c: Daemon already running.
Aug 1 21:44:41 localhost dbus: [system] Rejected send message, 2 matched rules; type="method_call", sender=":1.56" (uid=500 pid=1855 comm="nautilus) interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply=0 destination=":1.18" (uid=0 pid=1588 comm="/usr/sbin/console-kit-daemon))
Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
Aug 1 21:55:06 localhost kernel: [ 694.160046] ville :ville_exit: ville module exit!
Aug 1 21:56:17 localhost kernel: [ 764.867120] ville :ville_init: you ask for debug!
Aug 1 21:56:17 localhost kernel: [ 764.867127] ville :ville_init: ville module init!
[root@localhost source]# rmmod ville
[root@localhost source]# tail /var/log/messages
Aug 1 21:44:24 localhost pulseaudio[1836]: bluetooth-util.c: Error from ListAdapters reply: org.freedesktop.DBus.Error.Spawn.ChildExited
Aug 1 21:44:26 localhost rtkit-daemon[1721]: Successfully made thread 1870 of process 1870 (/usr/bin/pulseaudio) owned by '500' high priority at nice level -11.
Aug 1 21:44:26 localhost pulseaudio[1870]: pid.c: Daemon already running.
Aug 1 21:44:41 localhost dbus: [system] Rejected send message, 2 matched rules; type="method_call", sender=":1.56" (uid=500 pid=1855 comm="nautilus) interface="org.freedesktop.DBus.Properties" member="GetAll" error name="(unset)" requested_reply=0 destination=":1.18" (uid=0 pid=1588 comm="/usr/sbin/console-kit-daemon))
Aug 1 21:52:20 localhost kernel: [ 527.943854] ville :ville_init: ville module init!
Aug 1 21:55:06 localhost kernel: [ 694.160046] ville :ville_exit: ville module exit!
Aug 1 21:56:17 localhost kernel: [ 764.867120] ville :ville_init: you ask for debug!
Aug 1 21:56:17 localhost kernel: [ 764.867127] ville :ville_init: ville module init!
Aug 1 21:56:44 localhost kernel: [ 792.003641] ville :ville_exit: you ask for debug!
Aug 1 21:56:44 localhost kernel: [ 792.003648] ville :ville_exit: ville module exit!
總結:
通過這兩個例子,就了解了如何在用戶空間和內核態(tài)模塊中使用開關宏來進行條件編譯。
ville
文章出處:飛諾網(wǎng)(www.diybl.com):http://www.diybl.com/course/6_system/linux/Linuxjs/20110802/557787.html