当前位置:文档之家› linux2.6内核Makefile详解

linux2.6内核Makefile详解

linux2.6内核Makefile详解
linux2.6内核Makefile详解

=== 1 概述

=== 2 角色分工

=== 3 内核编译文档

--- 3.1 目标定义

--- 3.2 内嵌对象 - obj-y --- 3.3 可加载模块 - obj-m --- 3.4 导出符号

--- 3.5 库文档 - lib-y

--- 3.6 目录递归

--- 3.7 编译标记

--- 3.8 命令依赖

--- 3.9 依赖关系

--- 3.10 特别规则

=== 4 辅助程式

--- 4.1 简单辅助程式

--- 4.2 组合辅助程式

--- 4.3 定义共享库

--- 4.4 C++语言使用方法

--- 4.5 辅助程式编译控制选项

--- 4.6 何时建立辅助程式

--- 4.7 使用hostprogs-$(CONFIG_FOO) === 5 编译清除机制

=== 6 体系Makefile文档

--- 6.1 变量配置

--- 6.2 增加预配置项

--- 6.3 目录表

--- 6.4 引导映像

--- 6.5 编译非内核目标

--- 6.6 编译引导映像命令

--- 6.7 定制编译命令

--- 6.8 预处理连接脚本

--- 6.9 $(CC)支持功能

=== 7 Kbuild变量

=== 8 Makefile语言

=== 9 Credits

=== 10 TODO

=== 1 概述

Makefile包括五部分:

Makefile 顶层Makefile文档

.config 内核配置文档

arch/$(ARCH)/Makefile 机器体系Makefile文档

scripts/Makefile.* 任何内核Makefiles共用规则

kbuild Makefiles 其他makefile文档

通过内核配置操作产生.config文档,顶层Makefile文档读取该文档的配置。顶层Makefile文档负责产生两个主要的程式:vmlinux (内核image)和模块。顶层Makefile文档根据内核配置,通过递归编译内核代码树子目录建立这两个文档。顶层Makefile文档文本一个名为

arch/$(ARCH)/Makefile的机器体系makefile文档。机器体系Makefile文档为顶层makefile

文档提供和机器相关的信息。每一个子目录有一个makefile文档,子目录makefile文档根据上级目录makefile文档命令启动编译。这些makefile使用.config文档配置数据构建各种文档列表,并使用这些文档列表编译内嵌或模块目标文档。scripts/Makefile.*包含了任何的定义和规则,和makefile文档一起编译出内核程式。

=== 2 角色分工

人们和内核makefile存在四种不同的关系:

*用户* 用户使用"make menuconfig"或"make"命令编译内核。他们通常不读或编辑内核makefile 文档或其他源文档。

*普通研发者* 普通研发者维护设备驱动程式、文档系统和网络协议代码,他们维护相关子系统的makefile文档,因此他们需要内核makefile文档整体性的一般知识和关于kbuild公共接口的周详知识。

*体系研发者* 体系研发者关注一个整体的体系架构,比如sparc或ia64。体系研发者既需要掌控关于体系的makefile文档,也要熟悉内核makefile文档。

*内核研发者* 内核研发者关注内核编译系统本身。他们需要清楚内核makefile文档的任何方面。

本文档的读者对象是普通研发者和系统研发者。

=== 3 内核编译文档

内核中大多数makefile文档是使用kbuild基础架构的makefile文档。本章介绍kbuild的makefile中的语法。

3.1节“目标定义”是个快速导引,后面各章有周详介绍和实例。

--- 3.1 目标定义

目标定义是makefile文档的主要部分(核心)。这些目标定义行定义了如何编译文档,特别的兼容选项和递归子目录。

最简单的makefile文档只包含一行:

Example: obj-y += foo.o

这行告诉kbuild在该目录下名为foo.o的目标文档(object),foo.o通过编译foo.c或foo.S而得到。

假如foo.o编译成一个模块,则使用obj-m变量,因此常见写法如下:

Example: obj-$(CONFIG_FOO) += foo.o

$(CONFIG_FOO)能够代表y(built-in对象)或m(module对象)。

假如CONFIG_FOO不是y或m,那么这个文档不会被编译和链接。

--- 3.2 内嵌对象 - obj-y

makefile文档将为编译vmlinux的目标文档放在$(obj-y)列表中,这些列表依赖于内核配置。

Kbuild编译任何的$(obj-y)文档,然后调用"$(LD) -r"合并这些文档到一个built-in.o 文档中。built-in.o经过父makefile文档链接到vmlinux。$(obj-y)中的文档顺序很重要。列表中文档允许重复,文档第一次出现将被链接到built-in.o,后续出现该文档将被忽略。

链接顺序之所以重要是因为一些函数在内核引导时将按照他们出现的顺序被调用,如函数(module_init() / __initcall)。所以要牢记改变链接顺序意味着也要改变SCSI控制器的检测顺序和重数磁盘。

例如: #drivers/isdn/i4l/Makefile

# 内核ISDN子系统和设备驱动程式Makefile

# 每个配置项是个文档列表

obj-$(CONFIG_ISDN) += isdn.o

obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

--- 3.3 可加载模块 - obj-m

$(obj-m)表示对象文档(object files)编译成可加载的内核模块。

一个模块能够通过一个源文档或几个源文档编译而成。makefile只需简单地他们加到

$(obj-m)。

例如:#drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o

注意:在这个例子中$(CONFIG_ISDN_PPP_BSDCOMP)含义是'm'。

假如内核模块通过几个源文档编译而成,使用以上同样的方法。

Kbuild需要知道通过哪些文档编译模块,因此需要配置一个$(-objs)变量。

例如:#drivers/isdn/i4l/Makefile

obj-$(CONFIG_ISDN) += isdn.o

isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o

在这个例子中,模块名isdn.o. Kbuild首先编译$(isdn-objs)中的object文档,然后运行"$(LD) -r"将列表中文档生成isdn.o.

Kbuild使用后缀-objs、-y识别对象文档。这种方法允许makefile使用CONFIG_符号值确定一个object文档是否是另外一个object的组成部分。

例如: #fs/ext2/Makefile

obj-$(CONFIG_EXT2_FS) += ext2.o

ext2-y := balloc.o bitmap.o

ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

在这个例子中,假如$(CONFIG_EXT2_FS_XATTR)表示'y',则ext2.o只有xattr.o组成部分。 注意: 当然,当您将对象文档编译到内核时,以上语法同样有效。因此,假如

CONFIG_EXT2_FS=y,Kbuild将先编译ext2.o文档,然后链接到built-in.o。

--- 3.4 导出符号目标

在makefile文档中没有特别导出符号的标记。

--- 3.5 库文档 - lib-y

obj-*中的object文档用于模块或built-in.o编译。object文档也可能编译到库文档中--lib.a。

任何罗列在lib-y中的object文档都将编译到该目录下的一个单一的库文档中。

包含在0bj-y中的object文档假如也列举在lib-y中将不会包含到库文档中,因为他们不能被访问。但lib-m中的object文档将被编译进lib.a库文档。

注意在相同的makefile中能够列举文档到buit-in内核中也能够作为库文档的一个组成部分。因此在同一个目录下既能够有built-in.o也能够有lib.a文档。

例如:#arch/i386/lib/Makefile

lib-y := checksum.o delay.o

这样将基于checksum.o、delay.o创建一个lib.a文档。

对于内核编译来说,lib.a文档被包含在libs-y中。将“6.3 目录表”。

lib-y通常被限制使用在lib/和arch/*/lib目录中。

--- 3.6 目录递归

makefile文档负责编译当前目录下的目标文档,子目录中的文档由子目录中的makefile

文档负责编译。编译系统将使用obj-y和obj-m自动递归编译各个子目录中文档。

假如ext2是个子目录,fs目录下的makefile将使用以下赋值语句是编译系统编译ext2

子目录。

例如: #fs/Makefile

obj-$(CONFIG_EXT2_FS) += ext2/

假如CONFIG_EXT2_FS配置成'y(built-in)或'm'(modular),则对应的obj-变量也要配置,内核编译系统将进入ext2目录编译文档。

内核编译系统只使用这些信息来决定是否需要编译这个目录,子目录中makefile文档规定那些文档编译为模块那些是内核内嵌对象。

当指定目录名时使用CONFIG_变量是一种良好的做法。假如CONFIG_选项不为'y'或'm',内核编译系统就会跳过这个目录。

--- 3.7 编译标记

EXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGS, EXTRA_ARFLAGS

任何的EXTRA_变量只能使用在定义该变量后的makefile文档中。EXTRA_变量被makefile文档任何的执行命令语句所使用。

$(EXTRA_CFLAGS)是使用$(CC)编译C文档的选项。

例如: # drivers/sound/emu10k1/Makefile

EXTRA_CFLAGS += -I$(obj)

ifdef

DEBUG EXTRA_CFLAGS += -DEMU10K1_DEBUG

endif

定义这个变量是必须的,因为顶层makefile定义了$(CFLAGS)变量并使用该变量编译整个代码树。

$(EXTRA_AFLAGS)是每个目录编译汇编语言源文档的选项。

例如: #arch/x86_64/kernel/Makefile

EXTRA_AFLAGS := -traditional

$(EXTRA_LDFLAGS)和$(EXTRA_ARFLAGS)用于每个目录的$(LD)和$(AR)选项。

例如: #arch/m68k/fpsp040/Makefile

EXTRA_LDFLAGS := -x

CFLAGS_$@, AFLAGS_$@

CFLAGS_$@和AFLAGS_$@只使用到当前makefile文档的命令中。

$(CFLAGS_$@)定义了使用$(CC)的每个文档的选项。$@部分代表该文档。

例如: # drivers/scsi/Makefile

CFLAGS_aha152x.o = -DAHA152X_STAT -DAUTOCONF

CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ \

-DGDTH_STATISTICS CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM

这三行定义了aha152x.o、gdth.o和seagate.o文档的编译选项。

$(AFLAGS_$@)使用在汇编语言代码文档中,具备同上相同的含义。

例如: # arch/arm/kernel/Makefile

AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional

AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional

--- 3.9 依赖关系

内核编译记录如下依赖关系:

1) 任何的前提文档(both *.c and *.h)

2) CONFIG_ 选项影响到的任何文档

3) 编译目标文档使用的命令行

因此,假如改变$(CC)的一个选项,任何相关的文档都要重新编译。

--- 3.10 特别规则

特别规则使用在内核编译需要规则定义而没有相应定义的时候。典型的例子如编译时头文档的产生规则。其他例子有体系makefile编译引导映像的特别规则。特别规则写法同普通的Make 规则。

Kbuild(应该是编译程式)在makefile所在的目录不能被执行,因此任何的特别规则需要提供前提文档和目标文档的相对路径。

定义特别规则时将使用到两个变量:

$(src): $(src)是对于makefile文档目录的相对路径,当使用代码树中的文档时使用该变量$(src)。

$(obj): $(obj)是目标文档目录的相对路径。生成文档使用$(obj)变量。

例如: #drivers/scsi/Makefile

$(obj)/53c8xx_d.h: $(src)/53c7,8xx.scr $(src)/script_asm.pl

$(CPP) -DCHIP=810 - -objs)包含了任何的用于链接最终可执行程式的对象。

例如: #scripts/lxdialog/Makefile

hostprogs-y := lxdialog

lxdialog-objs := checklist.o lxdialog.o

扩展名.o文档都编译自对应的.c文档。在上面的例子中checklist.c编译成checklist.o,lxdialog.c编译为lxdialog.o。最后两个.o文档链接成可执行文档lxdialog。

注意:语法-y不能用于定义主机程式。

--- 4.3 定义共享库

扩展名为.so的对象是共享库文档,并且是位置无关的object文档。内核编译系统提供共享库使用支持,但使用方法有限制。在下面例子中libkconfig.so库文档被链接到可执行文档conf中。

例如: #scripts/kconfig/Makefile

hostprogs-y := conf

conf-objs := conf.o libkconfig.so

libkconfig-objs := expr.o type.o

共享库文档需要对应的-objs定义, 在上面例子中库libkconfig由两个对象组成:expr.o 和type.o。expr.o和type.o将被编译为位置无关代码并被链接如libkconfig.so。共享库不支持C++语言。

--- 4.4 C++语言使用方法

内核编译系统提供了对C++主机程式的支持以用于内核配置,但不主张其他方面使用这种方法。

例如: #scripts/kconfig/Makefile

hostprogs-y := qconf

qconf-cxxobjs := qconf.o

在上面例子中可执行文档由C++文档https://www.doczj.com/doc/6511013549.html,组成 - 通过$(qconf-cxxobjs)标识。

假如qconf由.c和.cc文档混合组成,附加行表示这种情况。

例如: #scripts/kconfig/Makefile

hostprogs-y := qconf

qconf-cxxobjs := qconf.o

qconf-objs := check.o

--- 4.5 辅助程式编译控制选项

当编译主机程式时仍然能够使用$(HOSTCFLAGS)配置编译选项传递给$(HOSTCC)。这些选项将影响任何使用变量HOST_EXTRACFLAG的makefile创建的主机程式。

例如: #scripts/lxdialog/Makefile

HOST_EXTRACFLAGS += -I/usr/include/ncurses

为单个文档配置选项使用下面方式:

例如: #arch/ppc64/boot/Makefile

HOSTCFLAGS_piggyback.o := -DKERNELBASE=$(KERNELBASE)

也能够使用附加链接选项:

例如: #scripts/kconfig/Makefile

HOSTLOADLIBES_qconf := -L$(QTDIR)/lib

当链接qconf时将使用外部选项"-L$(QTDIR)/lib"。

--- 4.6 何时建立辅助程式

只有当需要时内核编译系统才会编译主机程式。有两种方式:

(1) 在特别规则中作为隐式的前提需求

例如: #drivers/pci/Makefile

hostprogs-y := gen-devlist

$(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist

( cd $(obj); ./gen-devlist ) 产生 .config文档

2) 保存内核版本到include/linux/version.h文档中

3) 符号链接include/asm to include/asm-$(ARCH)

4) 更新任何目标对象的其他前提文档

- 附加前提文档定义在arch/$(ARCH)/Makefile文档中

5) 递归进入init-* core* drivers-* net-* libs-*中的任何子目录和编译任何的目标对象 - 上面变量值都引用到arch/$(ARCH)/Makefile文档。

6) 链接任何的object文档生成vmlinux文档,vmlinux文档放在代码树根目录下。

最开始链接的几个object文档列举在arch/$(ARCH)/Makefile文档的head-y变量中。 7) 最后体系makefile文档定义编译后期处理规则和建立最终的引导映像bootimage。

- 包括创建引导记录

- 准备initrd映像和相关处理

--- 6.1 变量配置

LDFLAGS $(LD)一般选项

选项使用于链接器的任何调用中。通常定义emulation就能够了。

例如: #arch/s390/Makefile

LDFLAGS := -m elf_s390

注意: EXTRA_LDFLAGS和LDFLAGS_$@能够进一步订制使用选项,将第7章。

LDFLAGS_MODULE $(LD)链接模块的选项

LDFLAGS_MODULE通常配置$(LD)链接模块的.ko选项。

默认为"-r"即可重定位输出文档。

LDFLAGS_vmlinux $(LD)链接vmlinux选项

LDFLAGS_vmlinux定义链接最终vmlinux时链接器的选项。

LDFLAGS_vmlinux支持使用LDFLAGS_$@。

例如: #arch/i386/Makefile

LDFLAGS_vmlinux := -e stext

OBJCOPYFLAGS objcopy选项

当使用$(call if_changed,objcopy)转化a .o文档时,OBJCOPYFLAGS中的选项将被使用。 $(call if_changed,objcopy)经常被用作为vmlinux产生原始的二进制文档。

例如: #arch/s390/Makefile

OBJCOPYFLAGS := -O binary

#arch/s390/boot/Makefile

$(obj)/image: vmlinux FORCE $(call if_changed,objcopy)

在上面例子中$(obj)/image是vmlinux的二进制版本文档。$(call if_changed,xxx)

的使用方法见后。

AFLAGS $(AS)汇编选项

默认值见顶层Makefile文档

针对每个体系需要另外添加和修改他。

例如: #arch/sparc64/Makefile

AFLAGS += -m64 -mcpu=ultrasparc

CFLAGS $(CC)编译器选项

默认值见顶层Makefile文档

针对每个体系需要另外添加和修改他。

通常CFLAGS变量值取决于内核配置。

例如: #arch/i386/Makefile

cflags-$(CONFIG_M386) += -march=i386

CFLAGS += $(cflags-y)

许多体系Makefiles文档动态启动市场目标机器上的C编译器检测支持的选项:

#arch/i386/Makefile

...

cflags-$(CONFIG_MPENTIUMII) += $(call cc-option,\

-march=pentium2,-march=i686) ...

# Disable unit-at-a-time mode ...

CFLAGS += $(call cc-option,-fno-unit-at-a-time)

...

第一个例子当config选项是'y'时将被选中。

CFLAGS_KERNEL $(CC)编译built-in对象的选项

$(CFLAGS_KERNEL)包含外部C编译器选项编译本地内核代码。

CFLAGS_MODULE $(CC)编译模块选项

$(CFLAGS_MODULE)包含外部C编译器选项编译可加载内核代码。

--- 6.2 增加预配置项

prepare: 这个规则用于列举开始进入子目录编译前需要的前提文档。通常是些包含汇编常量的头文档。

例如:

#arch/s390/Makefile

prepare: include/asm-$(ARCH)/offsets.h

在这个例子中include/asm-$(ARCH)/offsets.h将在进入子目录前编译。

详见XXX-TODO文档描述了kbuild如何产生offset头文档。

--- 6.3 目录表

体系makefile文档和顶层makefile文档一起定义了如何建立vmlinux文档的变量。注意没有体系相关的模块对象定义部分:任何的模块对象都是体系无关的。

head-y, init-y, core-y, libs-y, drivers-y, net-y

$(head-y) 列举首先链接到vmlinux的对象文档。

$(libs-y) 列举了能够找到lib.a文档的目录。

其余的变量列举了能够找到内嵌对象文档的目录。

$(init-y) 列举的对象位于$(head-y)对象之后。

然后是如下位置秩序:

$(core-y), $(libs-y), $(drivers-y) 和 $(net-y)。

顶层makefile定义了任何同用目录,arch/$(ARCH)/Makefile文档只需增加体系相关的目录。

例如: #arch/sparc64/Makefile

core-y += arch/sparc64/kernel/

libs-y += arch/sparc64/prom/ arch/sparc64/lib/

drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/

--- 6.4 引导映像

体系makefile文档定义了编译vmlinux文档的目标对象,将他们压缩和封装成引导代码,并复制到合适的位置。这包括各种安装命令。如何定义实际的目标对象无法为任何的体系结构提

供标准化的方法。

附加处理过程常位于arch/$(ARCH)/下的boot/目录。

内核编译系统无法在boot/目录下提供一种便捷的方法创建目标系统文档。因此

arch/$(ARCH)/Makefile要调用make命令在boot/目录下建立目标系统文档。建议使用的方法是在arch/$(ARCH)/Makefile中配置调用,并且使用完整路径引用arch/$(ARCH)/boot/Makefile。 例如: #arch/i386/Makefile

boot := arch/i386/boot

bzImage: vmlinux

$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

建议使用"$(Q)$(MAKE) $(build)="方式在子目录中调用make命令。

没有定义体系目标系统文档的规则,但执行"make help"命令要列出任何目标系统文档,因此必须定义$(archhelp)变量。

例如: #arch/i386/Makefile

define

archhelp echo '* bzImage - Image (arch/$(ARCH)/boot/bzImage)'

endef

当执行不带参数的make命令时,将首先编译第一个目标对象。在顶层makefile中第一个目标对象是all:。

一个体系结构需要定义一个默认的可引导映像。

"make help"命令的默认目标是以*开头的对象。

增加新的前提文档给all目标能够配置不同于vmlinux的默认目标对象。

例如: #arch/i386/Makefile

all: bzImage

当执行不带参数的"make"命令时,bzImage文档将被编译。

--- 6.5 编译非内核目标

extra-y

extra-y定义了在当前目录下创建没有在obj-*定义的附加的目标文档。

在extra-y中列举目标是处于两个目的:

1) 是内核编译系统在命令行中检查变动情况

- 当使用$(call if_changed,xxx)时

2) 内核编译系统知道执行"make clean"命令时删除哪些文档

例如: #arch/i386/kernel/Makefile

extra-y := head.o init_task.o

上面例子extra-y中的对象文档将被编译但不会练接到built-in.o中。

--- 6.6 编译引导映像命令

Kbuild提供了一些编译引导映像有用的宏。

if_changed

if_changed是后面命令使用的基础。

用法:

target: source(s)

FORCE $(call if_changed,ld/objcopy/gzip)

当这条规则被使用时他将检查哪些文档需要更新,或命令行被改变。后面这种情况将迫使重新编译编译选项被改变的执行文档。使用if_changed的目标对象必须列举在$(targets)中,否则命令行检查将失败,目标一直会编译。

赋值给$(targets)的对象没有$(obj)/前缀。

if_changed也能够和定制命令配合使用,见6.7"kbuild定制命令"。

注意: 一个常见错误是忘记了FORCE前导词。

ld

链接目标。常使用LDFLAGS_$@作为ld的选项。

objcopy

复制二进制文档。常用于arch/$(ARCH)/Makefile中和使用OBJCOPYFLAGS作为选项。 也能够用OBJCOPYFLAGS_$@配置附加选项。

gzip

压缩目标文档。使用最大压缩算法压缩目标文档。

例如: #arch/i386/boot/Makefile

LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary

LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext

targets += setup setup.o bootsect bootsect.o

$(obj)/setup $(obj)/bootsect: %: %.o FORCE

$(call if_changed,ld)

在上面例子中有两个可能的目标对象,分别需要不同的链接选项。使用LDFLAGS_$@语法为每个目标对象配置不同的链接选项。

$(targets)包含任何的目标对象,因此内核编译系统知道任何的目标对象并且将:

1) 检查命令行的改变情况

2) 执行make clean命令时删除目标对象

": %: %.o"是简写方法,减写setup.o和bootsect.o文档。

注意: 常犯错误是忘记"target :="语句,导致没有明显的原因目标文档被重新编译。

--- 6.7 定制编译命令

当执行带KBUILD_VERBOSE=0参数的编译命令时命令的简短信息会被显示。要让定制命令具备这种功能需要配置两个变量:

quiet_cmd_ - 将被显示的内容

cmd_ - 被执行的命令

例如: #

quiet_cmd_image = BUILD $@

cmd_image = $(obj)/tools/build $(BUILDFLAGS) \

$(obj)/vmlinux.bin > $@

targets += bzImage

$(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE

$(call if_changed,image)

@echo 'Kernel: $@ is ready'

执行"make KBUILD_VERBOSE=0"命令编译$(obj)/bzImage目标时将显示:

BUILD arch/i386/boot/bzImage

--- 6.8 预处理连接脚本

当编译vmlinux映像时将使用arch/$(ARCH)/kernel/vmlinux.lds链接脚本。

相同目录下的vmlinux.lds.S文档是这个脚本的预处理的变体。内核编译系统知晓.lds文档并使用规则*lds.S -> *lds。

例如: #arch/i386/kernel/Makefile

always := vmlinux.lds

#Makefile

export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)

$(always)赋值语句告诉编译系统编译目标是vmlinux.lds。$(CPPFLAGS_vmlinux.lds)赋值语句告诉编译系统编译vmlinux.lds目标的编译选项。

编译*.lds时将使用到下面这些变量:

CPPFLAGS : 定义在顶层Makefile

EXTRA_CPPFLAGS : 能够配置在编译的makefile文档中

CPPFLAGS_$(@F) : 目标编译选项。注意要使用文档全名。

--- 6.9 $(CC)支持功能

内核可能会用不同版本的$(CC)进行编译,每个版本有不同的性能和选项,内核编译系统提供基本的支持用于验证$(CC)选项。$(CC)通常是gcc编译器,但其他编译器也是能够。

cc-option cc-option 用于检测$(CC)是否支持给定的选项,假如不支持就使用第二个可选项。 例如: #arch/i386/Makefile

cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)

在上面例子中假如$(CC)支持-march=pentium-mmx则cflags-y等于该值,否则等于

-march-i586。假如没有第二个可选项且第一项不支持则cflags-y没有被赋值。

cc-option-yn cc-option-yn用于检测gcc是否支持给定的选项,支持返回'y'否则'n'。

例如: #arch/ppc/Makefile

biarch := $(call cc-option-yn, -m32)

aflags-$(biarch) += -a32

cflags-$(biarch) += -m32

在上面例子中假如$(CC)支持-m32选项则$(biarch)配置为y。当$(biarch)等于y时,变量

Linux内核修改与编译图文教程

Linux 内核修改与编译图文教程 1

1、实验目的 针对Ubuntu10.04中,通过下载新的内核版本,并且修改新版本内核中的系统调用看,然后,在其系统中编译,加载新内核。 2、任务概述 2.1 下载新内核 https://www.doczj.com/doc/6511013549.html,/ 2.2 修改新内核系统调用 添加新的系统调用函数,用来判断输入数据的奇偶性。 2.3 进行新内核编译 通过修改新版内核后,进行加载编译。最后通过编写测试程序进行测试 3、实验步骤 3.1 准备工作 查看系统先前内核版本: (终端下)使用命令:uname -r 2

3.2 下载最新内核 我这里使用的内核版本是 3.3 解压新版内核 将新版内核复制到“/usr/src”目录下 在终端下用命令:cd /usr/src进入到该文件目录 解压内核:linux-2.6.36.tar.bz2,在终端进入cd /usr/src目录输入一下命令: bzip2 -d linux-2.6.36.tar.bz2 tar -xvf linux-2.6.36.tar 文件将解压到/usr/src/linux目录中 3

使用命令: ln -s linux-2.6.36 linux 在终端下输入一下命令: sudo apt-get install build-essential kernel-package libncurses5-dev fakeroot sudo aptitude install libqt3-headers libqt3-mt-dev libqt3-compat-headers libqt3-mt 4

LAMMPS手册-中文版讲解之欧阳家百创编

LAMMPS手册-中文解析 一、 欧阳家百(2021.03.07) 二、简介 本部分大至介绍了LAMMPS的一些功能和缺陷。 1.什么是LAMMPS? LAMMPS是一个经典的分子动力学代码,他可以模拟液体中的粒子,固体和汽体的系综。他可以采用不同的力场和边界条件来模拟全原子,聚合物,生物,金属,粒状和粗料化体系。LAMMPS可以计算的体系小至几个粒子,大到上百万甚至是上亿个粒子。 LAMMPS可以在单个处理器的台式机和笔记本本上运行且有较高的计算效率,但是它是专门为并行计算机设计的。他可以在任何一个按装了C++编译器和MPI的平台上运算,这其中当然包括分布式和共享式并行机和Beowulf型的集群机。 LAMMPS是一可以修改和扩展的计算程序,比如,可以加上一些新的力场,原子模型,边界条件和诊断功能等。 通常意义上来讲,LAMMPS是根据不同的边界条件和初始条件对通过短程和长程力相互作用的分子,原子和宏观粒子集合对它们的牛顿运动方程进行积分。高效率计算的LAMMPS通过采用相邻清单来跟踪他们邻近的粒子。这些清单是根据粒子间的短程互拆力的大小进行优化过的,目的是防止局部粒子密度过高。在

并行机上,LAMMPS采用的是空间分解技术来分配模拟的区域,把整个模拟空间分成较小的三维小空间,其中每一个小空间可以分配在一个处理器上。各个处理器之间相互通信并且存储每一个小空间边界上的”ghost”原子的信息。LAMMPS(并行情况)在模拟3维矩行盒子并且具有近均一密度的体系时效率最高。 2.LAMMPS的功能 总体功能: 可以串行和并行计算 分布式MPI策略 模拟空间的分解并行机制 开源 高移植性C++语言编写 MPI和单处理器串行FFT的可选性(自定义) 可以方便的为之扩展上新特征和功能 只需一个输入脚本就可运行 有定义和使用变量和方程完备语法规则 在运行过程中循环的控制都有严格的规则 只要一个输入脚本试就可以同时实现一个或多个模拟任务 粒子和模拟的类型: (atom style命令) 原子 粗粒化粒子 全原子聚合物,有机分子,蛋白质,DNA

linux驱动的Makefile分析

第6行,判断KERNELRELEASE是否为空,该变量是描述内核版本的字符串。只有执行make命令的当前目录为内核源代码目录时,该变量才不为空字符。 第7、8行定义了KERNELDIR和PWD变量。KERNELDIR是内核路径变量,PWD是由执行pwd命令得到的当前模块路径。 第11行make的语法是”Make –C 内核路径M=模块路径modules”,该语法会执行内核模块的编译 第13行是将模块安装到对应的路径中,当在命令执行make modules_install时,执行该命令,其他时候不执行 第24行,意思是将hello.o编译成hello.ko模块。如果要编译其他模块时,只要将hello.o中的hello改成模块的文件名就可以了 Makefile的执行过程: 执行make命令后,将进入Makefile文件。此时KERNELRELEASE变量为空,此时是第一次进入Makefile文件。当执行完变量赋值代码后,会根据make参数执行不同的逻辑。 如下: make modules_install 命令,将执行13、15行将模块安装到操作系统中。 make clean命令,会删除目录中的所有临时文件。 make命令,会执行10、11行编译模块。首先$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 中的-C $(KERNELDIR)选项,会使编译器进入内核源码目录/home/zzc/linux-2.6.31,读取Makefile文件,从中得到一些信息,例如变量KERNELRELEASE将在这里赋值。当内核源码目录中的Makefile文件读取完成后,编译器会根据选项M=$(PWD)第二次进入模块所在的目录,并再一次执行Makefie文件。当第二次执行Makefile文件时,变量KERNELRELEASE

如何自行编译一个Linux内核的详细资料概述

如何自行编译一个Linux内核的详细资料概述 曾经有一段时间,升级Linux 内核让很多用户打心里有所畏惧。在那个时候,升级内核包含了很多步骤,也需要很多时间。现在,内核的安装可以轻易地通过像 apt 这样的包管理器来处理。通过添加特定的仓库,你能很轻易地安装实验版本的或者指定版本的内核(比如针对音频产品的实时内核)。 考虑一下,既然升级内核如此容易,为什么你不愿意自行编译一个呢?这里列举一些可能的原因: 你想要简单了解编译内核的过程 你需要启用或者禁用内核中特定的选项,因为它们没有出现在标准选项里 你想要启用标准内核中可能没有添加的硬件支持 你使用的发行版需要你编译内核 你是一个学生,而编译内核是你的任务 不管出于什么原因,懂得如何编译内核是非常有用的,而且可以被视作一个通行权。当我第一次编译一个新的Linux 内核(那是很久以前了),然后尝试从它启动,我从中(系统马上就崩溃了,然后不断地尝试和失败)感受到一种特定的兴奋。 既然这样,让我们来实验一下编译内核的过程。我将使用Ubuntu 16.04 Server 来进行演示。在运行了一次常规的 sudo apt upgrade 之后,当前安装的内核版本是 4.4.0-121。我想要升级内核版本到 4.17,让我们小心地开始吧。 有一个警告:强烈建议你在虚拟机里实验这个过程。基于虚拟机,你总能创建一个快照,然后轻松地从任何问题中回退出来。不要在产品机器上使用这种方式升级内核,除非你知道你在做什么。 下载内核 我们要做的第一件事是下载内核源码。在 Kernel 找到你要下载的所需内核的URL。找到URL 之后,使用如下命令(我以 4.17 RC2 内核为例)来下载源码文件: wget https://git.kernel/torvalds/t/linux-4.17-rc2.tar.gz

手动建立makefile简单实例解析

手动建立makefile简单实例解析 假设我们有一个程序由5个文件组成,源代码如下:/*main.c*/ #include "mytool1.h" #include "mytool2.h" int main() { mytool1_print("hello mytool1!"); mytool2_print("hello mytool2!"); return 0; } /*mytool1.c*/ #include "mytool1.h" #include void mytool1_print(char *print_str) { printf("This is mytool1 print : %s ",print_str); } /*mytool1.h*/ #ifndef _MYTOOL_1_H #define _MYTOOL_1_H void mytool1_print(char *print_str); #endif /*mytool2.c*/ #include "mytool2.h" #include void mytool2_print(char *print_str) { printf("This is mytool2 print : %s ",print_str); }

/*mytool2.h*/ #ifndef _MYTOOL_2_H #define _MYTOOL_2_H void mytool2_print(char *print_str); #endif 首先了解一下make和Makefile。GNU make是一个工程管理器,它可以管理较多的文件。我所使用的RedHat 9.0的make版本为GNU Make version 3.79.1。使用make的最大好处就是实现了“自动化编译”。如果有一个上百个文件的代码构成的项目,其中一个或者几个文件进行了修改,make就能够自动识别更新了的文件代码,不需要输入冗长的命令行就可以完成最后的编译工作。make执行时,自动寻找Makefile(makefile)文件,然后执行编译工作。所以我们需要编写Makefile文件,这样可以提高实际项目的工作效率。 在一个Makefile中通常包含下面内容: 1、需要由make工具创建的目标体(target),通常是目标文件或可执行文件。 2、要创建的目标体所依赖的文件(dependency_file)。 3、创建每个目标体时需要运行的命令(command)。 格式如下: target:dependency_files command target:规则的目标。通常是程序中间或者最后需要生成的文件名,可以是.o文件、也可以是最后的可执行程序的文件名。另外,目标也可以是一个make执行的动作的名称,如目标“clean”,这样的目标称为“伪目标”。 dependency_files:规则的依赖。生成规则目标所需要的文件名列表。通常一个目标依赖于一个或者多个文件。 command:规则的命令行。是make程序所有执行的动作(任意的shell命令或者可在shell下执行的程序)。一个规则可以有多个命令行,每一条命令占一行。注意:每一个命令行必须以[Tab]字符开始,[Tab]字符告诉make此行是一个命令行。make按照命令完成相应的动作。这也是书写Makefile中容易产生,而且比较隐蔽的错误。命令就是在任何一个目标的依赖文件发生变化后重建目标的动作描述。一个目标可以没有依赖而只有动作(指定的命令)。比如Makefile中的目标“clean”,此目标没有依赖,只有命令。它所指定的命令用来删除make过程产生的中间文件(清理工作)。 在Makefile中“规则”就是描述在什么情况下、如何重建规则的目标文件,通常规则

嵌入式Linux系统内核的配置、编译和烧写

实验二 嵌入式Linux系统内核的配置、编译和烧写 1.实验目的 1)掌握交叉编译的基本概念; 2)掌握配置和编译嵌入式Linux操作系统内核的方法; 3)掌握嵌入式系统的基本架构。 2.实验环境 1)装有Windows系统的计算机; 2)计算机上装有Linux虚拟机软件; 3)嵌入式系统实验箱及相关软硬件(各种线缆、交叉编译工具链等等)。 3.预备知识 1)嵌入式Linux内核的配置和裁剪方法; 2)交叉编译的基本概念及编译嵌入式Linux内核的方法; 3)嵌入式系统的基本架构。 4.实验内容和步骤 4.1 内核的配置和编译——配置内核的MMC支持 1)由于建立交叉编译器的过程很复杂,且涉及汇编等复杂的指令,在这里 我们提供一个制作好的编译器。建立好交叉编译器之后,我们需要完成 内核的编译,首先我们要有一个完整的Linux内核源文件包,目前流行 的源代码版本有Linux 2.4和Linux 2.6内核,我们使用的是Linux 2.6内核; 2)实验步骤: [1]以root用户登录Linux虚拟机,建立一个自己的工作路径(如用命令 “mkdir ‐p /home/user/build”建立工作路径,以下均采用工作路径 /home/user/build),然后将“cross‐3.3.2.tar.bz2、dma‐linux‐2.6.9.tar.gz、 dma‐rootfs.tar.gz”拷贝到工作路径中(利用Windows与虚拟机Linux 之间的共享目录作为中转),并进入工作目录; [2]解压cross‐3.3.2.tar.bz2到当前路径:“tar ‐jxvf cross‐3.3.2.tar.bz2”; [3]解压完成后,把刚刚解压后在当前路径下生成的“3.3.2”文件夹移 动到“/usr/local/arm/”路径下,如果在“/usr/local/”目录下没有“arm” 文件夹,用户创建即可; [4]解压“dma‐linux‐2.6.9.tar.gz”到当前路径下:

Makefile下编写Helloworld的例子

什么是makefile?或许很多Windows的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得 要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专 业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile, 从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中, makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复 杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。 makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make 命令,整个工程完全自动编译,极大的提高了软件 开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如: Delphi的make,VisualC++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 更新版本 hello.c程序 #include int main(){printf("Hello,World!\n");

return 0;}=== makefile开始=== Helloworld: hello.o gcc hello.o–o Helloworld Hello.o: hello.c hello.h gcc–MM hello.c gcc–c hello.c–o hello.o .PHONY: clean Clean: rm–rf*.o hellworld === makefile结束===

LINUX编程 Makefile中的变量详解应用

第六章:Makefile中的变量 -------------------------------------------------------------------------------- 在Makefile中,变量就是一个名字(像是C语言中的宏),代表一个文本字符串(变量的值)。在Makefile的目标、依赖、命令中引用一个变量的地方,变量会被它的值所取代(与C语言中宏引用的方式相同,因此其他版本的make也把变量称之为“宏”)。在Makefile中变量的特征有以下几点: 1. Makefile中变量和函数的展开(除规则的命令行以外),是在make读取makefile文件时进行的,这里的变量包括了使用“=”定义和使用指示符“define”定义的。 2. 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、搜索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。 3. 变量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。需要注意的是,尽管在GNU make中没有对变量的命名有其它的限制,但定义一个包含除字母、数字和下划线以外的变量的做法也是不可取的,因为除字母、数字和下划线以外的其它字符可能会在以后的make版本中被赋予特殊含义,并且这样命名的变量对于一些shell来说不能作为环境变量使用。 4. 变量名是大小写敏感的。变量“foo”、“Foo”和“FOO”指的是三个不同的变量。Makefile 传统做法是变量名是全采用大写的方式。推荐的做法是在对于内部定义定义的一般变量(例如:目标文件列表objects)使用小写方式,而对于一些参数列表(例如:编译选项CFLAGS)采用大写方式,这并不是要求的。但需要强调一点:对于一个工程,所有Makefile中的变量命名应保持一种风格,否则会显得你是一个蹩脚的程序员(就像代码的变量命名风格一样)。 5. 另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为自动化变量。像“$<”、“$@”、“$?”、“$*”等。 6.1 变量的引用 当我们定义了一个变量之后,就可以在Makefile的很多地方使用这个变量。变量的引用方式是:使用“$(VARIABLE_NAME)”或者“${ VARIABLE_NAME }”来引用一个变量的定义。例如:“$(foo) ”或者“${foo}”就是取变量“foo”的值。美元符号“$”在Makefile中有特殊的含义,所有在命令或者文件名中使用“$”时需要用两个美元符号“$$”来表示。对一个变量的引用可以在Makefile的任何上下文中,目标、依赖、命令、绝大多数指示符和新变量的赋值中。这里有一个例子,其中变量保存了所有.o文件的列表: objects = program.o foo.o utils.o program : $(objects) cc -o program $(objects)

MakeFile

MAKE 的使用 当编译单个文件时,使用GCC已经绰绰有余,但对于有几十个甚至上百个源文件的大工程来讲,单纯用GCC命令进行编译肯定就不行了,那样编译一次太麻烦,这就要求有一种自动化的方法,于是在Linux系统中Make工具就诞生了。 1、什么是Make makefile shell 什么是Make,可以将Make理解为一种脚本,这种脚本主要是用于多文件编译,在传统的命令行式编译方式中,如果修改了工程中的某一个头文件,有时候不需要重新编译整个工程,而只需要编译与这个头文件相关联的源文件即可,但如何以手动的方式从一个大工程里将这些文件找出,并手动编译,是件很麻烦的事情。 为了解决这一问题,设计了Make,make程序可以维护具有相互依赖性的源文件,当某些文件发生改变时,它能自动识别出,并只对相应文件进行自动编译。 虽然make工具有很多智能识别机制,但它无法自动了解他所面对的工程源文件的组成以及依赖规则,这些都需要开发人员编写makefile脚本,告诉make工具。MakeFile编写好以后,就可以在每次修改源文件之后,执行make命令就好了。Makefile make 什么又是makefile了,很多windows的程序开发人员都不知道这个东西,因为那些Windows的IDE都为你做了这些工作,但我觉得要作为一个好的和专业的程序员,makefile还是要懂得,这就好像在有这么多的HTML的编辑器,但如果你想成为一个专业人士,就必须了解HTML的标识的含义。特别在Linux下的软件编译,你就必须自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成某个大型大工程的能力。 2、makefile的组成 一个完整的makefile文件通常由五个部分组成: ◆显示规则 显示规则是指主动编写描述规则,用于指示在何种状态下更新哪些目标文件,即编写makefile时需要明确指出各目标文件所依赖的源文件的集合,以及编 译本目标文件所需的命令。 ◆隐含规则 指用make中默认的编译方式进行编译,即make工具可以根据目标文件的类型自动推导出的规则(由于我们的make有自动推导的功能,所以隐晦的规则可以 让我们比较粗糙地简略书写Makefile ,这是由make所支持的) abc.o abc.c cc -o abc.o -c abc.c ◆变量定义 为提升语句的灵活性,在make脚本中可以使用变量,来代表一个字符串,一组编译命令或一组文件名。(在makefile 中我们要定义一系列的变量,变量一般都是字符串,这个有点类似于C语言中的宏,当makefile 被执行时,其中的变量都会被扩展到相应的引用位置上) ◆makefile指示符 指示符告诉make工具,当程序在读取makefile文件时要执行的动作。 (文件指示包括三部分,一个是在一个makefile中引用另外一个makefile,就像C语言中的include一样,另一个是指根据某些情况制定MakeFile中的有效部分,就像C 语言中的预编译#if一样,还有就是定义一个多行的命令,)

linux、内核源码、内核编译与配置、内核模块开发、内核启动流程

linux、内核源码、内核编译与配置、内核模块开发、内核启动流程(转) linux是如何组成的? 答:linux是由用户空间和内核空间组成的 为什么要划分用户空间和内核空间? 答:有关CPU体系结构,各处理器可以有多种模式,而LInux这样的划分是考虑到系统的 安全性,比如X86可以有4种模式RING0~RING3 RING0特权模式给LINUX内核空间RING3给用户空间 linux内核是如何组成的? 答:linux内核由SCI(System Call Interface)系统调用接口、PM(Process Management)进程管理、MM(Memory Management)内存管理、Arch、 VFS(Virtual File Systerm)虚拟文件系统、NS(Network Stack)网络协议栈、DD(Device Drivers)设备驱动 linux 内核源代码 linux内核源代码是如何组成或目录结构? 答:arc目录存放一些与CPU体系结构相关的代码其中第个CPU子目录以分解boot,mm,kerner等子目录 block目录部分块设备驱动代码 crypto目录加密、压缩、CRC校验算法 documentation 内核文档 drivers 设备驱动 fs 存放各种文件系统的实现代码 include 内核所需要的头文件。与平台无关的头文件入在include/linux子目录下,与平台相关的头文件则放在相应的子目录中 init 内核初始化代码 ipc 进程间通信的实现代码 kernel Linux大多数关键的核心功能者是在这个目录实现(程序调度,进程控制,模块化) lib 库文件代码 mm 与平台无关的内存管理,与平台相关的放在相应的arch/CPU目录net 各种网络协议的实现代码,注意而不是驱动 samples 内核编程的范例 scripts 配置内核的脚本 security SElinux的模块 sound 音频设备的驱动程序 usr cpip命令实现程序 virt 内核虚拟机 内核配置与编译 一、清除 make clean 删除编译文件但保留配置文件

make_Makefile 结构分析

Makefile结构分析 -----uClinux (2.6.x内核)系统映像过程 刘江欧阳昭暐吕熙隆 1、源代码文件及目录构成 解压缩uClinux-dist-20070130.tar.gz压缩文件,在uClinux-dist原始子目录下主要有:config、Bin、linux-2.4.x、linux-2.6.x 、lib、tools、Include、user和vendors,以及文件Makefile。另外,在编译后生成子目录images和romfs,以及文件autoconfig.h、config.in和两个隐含文件:.config和.depend。 config子目录包含文件及下一级子目录,如 config.in、configure.help、Fixconfig、Makefile、 Mkconfig、Setconfig所有这些文件及子目录 Scripts均与系统配置有关; linux-2.6.x子目录是嵌入式操作系统 uClinux-2.6.x的核心目录,包括下一级子目录 arch、include、init、drivers、fs、ipc、kernel、 lib、Mm、scripts和关键文件Makefile、 rules.make,编译后还要生成新文件romfs.o、linux 和system.map;lib子目录为嵌入式操作系统提供 压缩和改进了的函数库支持;tools子目录包含 romfs-inst.sh文件,通过调用此文件,可以把目录 或文件加入到romfs子目录中;user子目录包含各 种驱动程序文件目录,根据用户的配置情况,不同的 驱动程序会被编译进最后形成的操作系统中; vendors子目录包括与特定硬件平台相关的分类目录 组。目录结构如图1所示。 Makefile的详细介绍情况在 uClinux-dist\linux-2.6.x\Documentation\kbuil d中,如图2所示。图1、目录结构即Linux 内核中的 Makefile 以及与 Makefile 直接相关的文件有:

linux内核编译和生成makefile文件实验报告

操作系统实验报告 姓名:学号: 一、实验题目 1.编译linux内核 2.使用autoconf和automake工具为project工程自动生成Makefile,并测试 3.在内核中添加一个模块 二、实验目的 1.了解一些命令提示符,也里了解一些linux系统的操作。 2.练习使用autoconf和automake工具自动生成Makefile,使同学们了解Makefile的生成原理,熟悉linux编程开发环境 三、实验要求 1使用静态库编译链接swap.c,同时使用动态库编译链接myadd.c。可运行程序生成在src/main目录下。 2要求独立完成,按时提交 四、设计思路和流程图(如:包括主要数据结构及其说明、测试数据的设计及测试结果分析) 1.Makefile的流程图: 2.内核的编译基本操作 1.在ubuntu环境下获取内核源码 2.解压内核源码用命令符:tar xvf linux- 3.18.12.tar.xz 3.配置内核特性:make allnoconfig 4.编译内核:make 5.安装内核:make install

6.测试:cat/boot/grub/grub.conf 7.重启系统:sudo reboot,看是否成功的安装上了内核 8.详情及结构见附录 3.生成makefile文件: 1.用老师给的projec里的main.c函数。 2.需要使用automake和autoconf两个工具,所以用命令符:sudo apt-get install autoconf 进行安装。 3.进入主函数所在目录执行命令:autoscan,这时会在目录下生成两个文件 autoscan.log和configure.scan,将configure.Scan改名为configure.ac,同时用gedit打开,打开后文件修改后的如下: # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) AC_CONFIG_SRCDIR([main.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE(main,1.0) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_OUTPUT(Makefile) 4.新建Makefile文件,如下: AUTOMAKE_OPTIONS=foreign bin_PROGRAMS=main first_SOURCES=main.c 5.运行命令aclocal 命令成功之后,在目录下会产生aclocal.m4和autom4te.cache两个文件。 6.运行命令autoheader 命令成功之后,会在目录下产生config.h.in这个新文件。 7.运行命令autoconf 命令成功之后,会在目录下产生configure这个新文件。 8.运行命令automake --add-missing输出结果为: Configure.ac:11:installing./compile’ Configure.ac:8:installing ‘.install-sh’ Configure.ac:8:installing ‘./missing’ Makefile.am:installing ‘./decomp’ 9. 命令成功之后,会在目录下产生depcomp,install-sh和missing这三个新文件和执行下一步的Makefile.in文件。 10.运行命令./configure就可以自动生成Makefile。 4.添加内核模块

通用Makefile模板及实例

1 通用Makefile——1 实现的功能: ?make——编译和连接程序 ?make objs——编译程序,生成目标文件 ?make clean——清除编译产生的目标文件(*.o)和依赖文件(*.d) ?make cleanall——清除目标文件(*.o)、依赖文件(*.d)和可执行文件(*.exe)?make rebuild——重新编译连接程序,相当于make clean && make Usage: Makefile源代码 # Gneric C/C++ Makefile #################################################### PROGRAM := SRCDIRS := SRCEXTS := CPPFLAGS := CFLAGS := CFLAGS += CXXFLAGS := CXXFLAGS += LDFLAGS := LDFLAGS += SHELL = /bin/sh SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) OBJS = $(foreach x,$(SRCEXTS),\ $(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES)))) DEPS = $(patsubst %.o,%.d,$(OBJS)) .PHONY: all objs clean cleanall rebuild all : $(PROGRAM) %.d : %.c @$(CC) -MM -MD $(CFLAGS) {1}lt; %.d : %.C @$(CC) -MM -MD $(CXXFLAGS) {1}lt; objs : $(OBJS) %.o : %.c $(CC) -c $(CPPFLAGS) $(CFLAGS) {1}lt; %.o : %.cpp $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) {1}lt; $(PROGRAM) : $(OBJS) ifeq ($(strip $(SRCEXTS)),.c) $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)

跟我一起写Makefile(可以注释版)

跟我一起写 Makefile 作者:陈皓 整理:祝冬华

第一部分、概述 (6) 第二部分、关于程序的编译和链接 (6) 第三部分、Makefile 介绍 (7) 一、Makefile的规则 (7) 二、一个示例 (8) 三、make是如何工作的 (9) 四、makefile中使用变量 (10) 五、让make自动推导 (11) 六、另类风格的makefile (12) 七、清空目标文件的规则 (13) 第四部分、Makefile 总述 (13) 一、Makefile里有什么? (13) 1、显式规则。 (14) 2、隐晦规则。 (14) 3、变量的定义。 (14) 4、文件指示。 (14) 5、注释。 (14) 二、Makefile的文件名 (15) 三、引用其它的Makefile (15) 四、环境变量 MAKEFILES (16) 五、make的工作方式 (16) 第五部分、书写规则 (17) 一、规则举例 (17) 二、规则的语法 (17) 三、在规则中使用通配符 (18) 四、文件搜寻 (19) 五、伪目标 (20) 六、多目标 (22) 七、静态模式 (22) 八、自动生成依赖性 (24) 第六部分书写命令 (25) 一、显示命令 (26) 二、命令执行 (26) 三、命令出错 (27) 四、嵌套执行make (28) 五、定义命令包 (30) 第七部分使用变量 (30) 一、变量的基础 (31) 二、变量中的变量 (32) 三、变量高级用法 (34) 四、追加变量值 (37) 五、override 指示符 (37) 六、多行变量 (38)

八、目标变量 (39) 九、模式变量 (40) 第八部分使用条件判断 (40) 一、示例 (40) 二、语法 (42) 第九部分使用函数 (43) 一、函数的调用语法 (44) 二、字符串处理函数 (44) 1、subst (44) 2、patsubst (45) 3、strip (45) 4、findstring (46) 5、filter (46) 6、filter-out (46) 7、sort (47) 8、word (47) 9、wordlist (47) 10、words (47) 11、firstword (48) 12、字符串函数实例 (48) 三、文件名操作函数 (48) 1、dir (48) 2、notdir (48) 3、suffix (49) 4、basename (49) 5、addsuffix (49) 6、addprefix (49) 7、join (50) 四、foreach 函数 (50) 五、if 函数 (50) 六、call函数 (51) 七、origin函数 (51) “undefined” (52) “default” (52) “file” (52) “command line” (52) “override” (52) “automatic” (52) 八、shell函数 (53) 九、控制make的函数 (53) 1、error (53) 2、warning (54) 第十部分 make 的运行 (54)

Makefile 语法分析

Makefile 语法分析第一部分 VERSION = 2 # 给变量VERSION赋值 PATCHLEVEL = 6 # 给变量PATCHLEVEL赋值 SUBLEVEL = 22 # 给变量SUBLEVEL赋值 EXTRAVERSION = .6 # 给变量EXTRAVERSION赋值 NAME = Holy Dancing Manatees, Batman! # 给变量NAME赋值 # *DOCUMENTATION* # To see a list of typical targets execute "make help" # More info can be located in ./README # Comments in this file are targeted only to the developer, do not # expect to learn how to build the kernel reading this file. # Do not: # o use make's built-in rules and variables # (this increases performance and avoid hard-to-debug behavour); # o print "Entering directory ..."; MAKEFLAGS += -rR --no-print-directory # 操作符“+=”的作用是给变量(“+=”前面的MAKEFLAGS)追加值。 # 如果变量(“+=”前面的MAKEFLAGS)之前没有定义过,那么,“+=”会自动变成“=”; # 如果前面有变量(“+=”前面的MAKEFLAGS)定义,那么“+=”会继承于前次操作的赋值符;# 如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符 # 在执行make时的命令行选项参数被通过变量“MAKEFLAGS”传递给子目录下的make程序。# 对于这个变量除非使用指示符“unexport”对它们进行声明,它们在整个make的执行过程中始终被自动的传递给所有的子make。 # 还有个特殊变量SHELL与MAKEFLAGS一样,默认情况(没有用“unexport”声明)下在整个make的执行过程中被自动的传递给所有的子make。 # # -rR --no-print-directory # -r disable the built-in impilict rules. # -R disable the built-in variable setttings. # --no-print-directory。 # We are using a recursive build, so we need to do a little thinking # to get the ordering right. # # Most importantly: sub-Makefiles should only ever modify files in # their own directory. If in some directory we have a dependency on # a file in another dir (which doesn't happen often, but it's often # unavoidable when linking the built-in.o targets which finally # turn into vmlinux), we will call a sub make in that other dir, and

makefile 中 $@ $^ % 使用

makefile 中$@ $^ %< 使用 https://www.doczj.com/doc/6511013549.html,/kesaihao862/article/details/7332528 这篇文章介绍在LINUX下进行C语言编程所需要的基础知识。在这篇文章当中,我们将会学到以下内容:源程序编译Makefile的编写程序库的链接程序的调试头文件和系统求助1.源程序的编译在Linux下面,如果要编译一个C语言源程序,我们要使用GNU的gcc编译器。下面我们以一个实例来说明如何使用gcc编译器。假设我们有下面一个非常简单的源程序(hello.c):int main(int argc,char **argv){printf("Hello Linux\n");}要编译这个程序,我们只要在命令行下执行:gcc -o hello hello.cgcc 编译器就会为我们生成一个hello的可执行文件。执行./hello就可以看到程序的输出结果了。命令行中gcc表示我们是用gcc来编译我们的源程序,-o 选项表示我们要求编译器给我们输出的可执行文件名为hello 而hello.c是我们的源程序文件。gcc编译器有许多选项,一般来说我们只要知道其中的几个就够了。-o 选项我们已经知道了,表示我们要求输出的可执行文件名。-c选项表示我们只要求编译器输出目标代码,而不必要输出可执行文件。-g选项表示我们要求编译器在编译的时候提供我们以后对程序进行调试的信息。知道了这三个选项,我

们就可以编译我们自己所写的简单的源程序了,如果你想要知道更多的选项,可以查看gcc的帮助文档,那里有着许多对其它选项的详细说明。2.Makefile的编写假设我们有下面这样的一个程序,源代码如下:/* main.c */#include "mytool1.h"#include "mytool2.h" int main(int argc,char **argv){mytool1_print("hello");mytool2_print("hello");}/* mytool1.h */ #ifndef _MYTOOL_1_H#define _MYTOOL_1_Hvoid mytool1_print(char *print_str);#endif/* mytool1.c */#include "mytool1.h"void mytool1_print(char *print_str){printf("This is mytool1 print %s\n",print_str);}/* mytool2.h */#ifndef _MYTOOL_2_H#define _MYTOOL_2_Hvoid mytool2_print(char *print_str);#endif/* mytool2.c */#include "mytool2.h"void mytool2_print(char *print_str){printf("This is mytool2 print %s\n",print_str);}当然由于这个程序是很短的我们可以这样来编译gcc -c main.cgcc -c mytool1.cgcc -c mytool2.cgcc -o main main.o mytool1.o mytool2.o这样的话我们也可以产生main程序,而且也不时很麻烦。但是如果我们考虑一下如果有一天我们修改了其中的一个文件(比如说mytool1.c)那么我们难道还要重新输入上面的命令?也许你会说,这个很容易解决啊,我写一个SHELL脚本,让她帮我去完成不就可以了。是的对于这个程序来说,是可

相关主题
文本预览
相关文档 最新文档