跟我一起写Makefile(高清)

合集下载

Makefile写法

Makefile写法
• 如果你要以相同的编译选项同时编译十几个 C 源文件,而为每
个目标的编译指定冗长的编译选项的话,将是非常乏味的。但 利用简单的变量定义,可避免这种乏味的工作: # Define macros for name of compiler CC = gcc # Define a macr o for the CC flags CCFLAGS = -D_DEBUG -g
规则(rule)概念
• 跟Shell不同,在makefile里规则的前后顺序不太重要. • 实际的调用顺序取决目标之间的依赖关系. • 因此make 采用逆推的方式来判断和执行目标
makefile 基本结构
makefile 中一般包含如下内容 – 需要由 make 工具创建的项目,通常是目标文件和可执行文件。 通常使用“目标(target)”一词来表示要创建的项目。 – 要创建的目标依赖于哪些文件。 – 创建每个目标时需要运行的命令,每个命令之前必须有tab打头 – 通常都包含一些固定的伪目标,如all,install,clean用作缺省编译, 安装和清除文件
3 Sept. 2008 © Neusoft Confidential
make的调用
• 最常用的make调用形式.就是直接执行make – 它会自动查找当前目录下的名称为Makefile或makefile的文
件. – 象其它GNU工具一样,make有一些命令参数,以便应用在一些 特殊场所 • 如果makefile脚本名称不是缺省名称,则需要用-f参数来通知 make – make –f hello.mk – 表示执行名称叫hello.mk makefile脚本 • 如果需要make不去查找当前目录,而是查找另外一个目录下的 makefile,则使用-C 参数 – make -C /home/hxy – 表示去找查找 /home/hxy下的makefile

c语言makefile编写实例

c语言makefile编写实例

c语言makefile编写实例Makefile是用来管理程序编译的工具,可以方便地管理程序的编译过程。

使用Makefile可以大大简化程序的编译过程,提高程序的可维护性。

Makefile的语法比较简单,主要由目标、依赖和命令三部分组成。

下面我们以一个简单的C程序为例,来介绍如何使用Makefile进行编译。

假设我们有一个名为hello.c的程序,代码如下:```c#include <stdio.h>int main(){printf("Hello, world!\n");return 0;}```我们需要使用gcc编译器将其编译成可执行文件。

下面是一个简单的Makefile:```makefilehello: hello.cgcc -o hello hello.c```这个Makefile很简单,它定义了一个名为hello的目标,该目标依赖于hello.c文件,并使用gcc命令将其编译成可执行文件。

如果我们在终端中输入make命令,Makefile会自动执行编译过程:```$ makegcc -o hello hello.c```Makefile还可以定义多个目标,每个目标可以有多个依赖和多个命令。

下面是一个稍微复杂一些的Makefile:```makefileCC=gccCFLAGS=-Wall -gall: hello goodbyehello: hello.o$(CC) $(CFLAGS) -o hello hello.ogoodbye: goodbye.o$(CC) $(CFLAGS) -o goodbye goodbye.ohello.o: hello.c$(CC) $(CFLAGS) -c hello.cgoodbye.o: goodbye.c$(CC) $(CFLAGS) -c goodbye.cclean:rm -f *.o hello goodbye```这个Makefile定义了两个目标:all和clean。

一个简单的makefile文件编写

一个简单的makefile文件编写

⼀个简单的makefile⽂件编写下午闲来⽆聊,就打开很久没动过的linux系统想熟悉熟悉在linux上⾯编译代码,结果⼀个makefile⽂件搞到晚上才搞定,哈哈!先把代码简单贴上来,就写了⼀个冒泡排序:sort.h:#ifndef SORT_H#define SORT_H#include<stdio.h>#include<time.h>#include<stdlib.h>#define N 10#define swap(a,b) {a^=b;b^=a;a^=b;}#define ins(a,b,c) for( a = b ; a < c ; ++a)void bub_sort();#endifsort.c:#include"sort.h"void bub_sort(){int *in;int i , j;in = malloc(N*sizeof(int));srand((unsigned)time(NULL));ins(i,0,N){in[i] = rand()%100;}ins(i,0,N){printf("%d%s",in[i],i == N-1 ? "\n" : "->");}ins(i,0,N-1){ins(j,i,N){if(in[i] > in[j]){swap(in[i] , in[j]);}}}ins(i,0,N){printf("%d%s" , in[i] , i == N-1 ? "\n" : "->");}free(in);in = NULL;}main.c:#include"sort.h"int main(){bub_sort();return 0;}如果直接编译的话得⽤三条指令:gcc -c sort.c -o sort.ogcc -c main.c -o main.ogcc main.o sort.o -o main每⼀次编译的时候如果都得敲这三⾏代码就显得效率很低了,所以尝试着写⼀个makefile⽂件;编写makefile时有⼀定的规则:⽬标(target):需要的条件(dependencies)(注意冒号两边有空格) 命令(system command) (注意前⾯⽤tab键开头) 解释⼀下: 1 ⽬标可以是⼀个或多个,可以是Object File,也可以是执⾏⽂件,甚⾄可以是⼀个标签。

makefile 写法

makefile 写法

makefile 写法makefile是一种用于自动化构建的工具,它可以帮助开发者管理项目中的源代码、依赖关系以及构建过程。

本文将详细介绍makefile的基本语法和使用方法,以及如何根据项目需求编写一个高效的makefile。

在这篇文章中,我们将一步一步回答关于makefile写法的问题。

第一步:什么是makefile及其作用?Makefile是一种文本文件,其中包含一系列的规则,告诉make命令如何编译和链接代码。

它能够根据源代码文件的修改日期来判断哪些文件需要重新编译,从而提高代码的构建效率。

通过makefile,我们可以定义编译器的参数、编译顺序和目标文件等信息,使得项目的构建过程更加简化、自动化。

第二步:makefile的基本语法是什么?Makefile由一系列的规则组成,每个规则都包含目标文件、依赖文件和命令。

下面是一个简单的示例:makefiletarget: dependency1 dependency2command1command2其中,`target`是要生成的目标文件,`dependency1`和`dependency2`是`target`所依赖的文件,`command1`和`command2`是执行的命令。

第三步:如何编写一个最基本的makefile?首先,我们需要确定项目的目标文件和依赖关系。

比如,我们的项目中有两个源代码文件`main.c`和`utility.c`,它们都依赖于一个头文件`utility.h`。

我们的目标是生成一个可执行文件`main`。

makefile# 目标文件main: main.o utility.ogcc -o main main.o utility.o# 依赖关系main.o: main.c utility.hgcc -c main.cutility.o: utility.c utility.hgcc -c utility.c第四步:如何使用变量和函数来简化makefile的编写?在makefile中,我们可以使用变量和函数来简化代码的编写。

makefile的编写

makefile的编写

makefile的编写Makefile是一种文本文件,它描述了如何编译和链接源文件来构建程序。

它包含规则、变量和命令,用于指示编译器怎样工作。

Makefile通常用于编译大型项目,以确保能够快速构建和生成目标文件。

下面我们将分步骤阐述如何编写一个Makefile。

第一步:定义变量在编写Makefile时,我们首先需要定义变量。

变量可以用于存储文件名、目录名、选项、标志等信息。

在Makefile中,为了提高可读性和可维护性,最好把常量值都定义成变量。

变量的定义格式为:变量名=变量值。

例如:```CC = g++CFLAGS = -Wall -O2```上述代码中,CC变量定义为编译器g++,CFLAGS变量定义为编译选项-Wall -O2。

这样,我们在Makefile中就可以直接使用这些变量,而不用每次都输入完整的命令。

第二步:编写规则Makefile中的规则描述了如何生成目标文件。

一般来说,每一条规则包含两部分:目标(target)和依赖关系(dependencies)。

目标是指要生成的文件,依赖关系是指这个文件所依赖的其他文件。

规则的格式为:```target: dependenciescommands```例如:main: main.cpp func.cpp$(CC) $(CFLAGS) -o main main.cpp func.cpp```这条规则表示将main.cpp和func.cpp编译成可执行文件main。

当我们使用make命令时,Makefile会检查main.cpp和func.cpp是否有修改,如果有修改,则重新编译目标文件main。

第三步:定义伪目标伪目标(phony target)用于定义一些没有实际文件对应的操作,例如清理、安装等。

伪目标的语法格式为:```.PHONY: target```例如:```.PHONY: cleanclean:rm -f *.o main```这个规则定义了一个名为clean的伪目标,用于删除所有的目标文件和可执行文件。

手把手教你如何写Makefile

手把手教你如何写Makefile

手把手教你如何写Makefile陈皓 2005.04.01一、Makefile的规则在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。

target ... : prerequisites ...commandtarget也就是一个目标文件,可以是Object File,也可以是执行文件。

还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

prerequisites就是,要生成那个target所需要的文件或是目标。

command也就是make需要执行的命令。

(任意的Shell命令)这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites 中的文件,其生成规则定义在command中。

说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。

这就是Makefile的规则。

也就是Makefile中最核心的内容。

说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。

呵呵。

还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。

内容还多着呢。

:)二、一个示例正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。

edit : main.o kbd.o command.o display.o \insert.o search.o files.o utils.occ -o edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.omain.o : main.c defs.hcc -c main.ckbd.o : kbd.c defs.h command.hcc -c kbd.ccommand.o : command.c defs.h command.hcc -c command.cdisplay.o : display.c defs.h buffer.hcc -c display.cinsert.o : insert.c defs.h buffer.hcc -c insert.csearch.o : search.c defs.h buffer.hcc -c search.cfiles.o : files.c defs.h buffer.h command.hcc -c files.cutils.o : utils.c defs.hcc -c utils.cclean :rm edit main.o kbd.o command.o display.o \insert.o search.o files.o utils.o反斜杠(\)是换行符的意思。

makefile写法

makefile写法

makefile写法Makefile 是代码构建和自动化构建的重要工具,它可以帮助我们高效、准确地管理和构建程序。

在本文中,我将和大家分享几种常见的Makefile 写法,以及一些有用的技巧和注意事项。

1. Makefile 的基本结构Makefile 中包含了以下基本结构:```target: dependencies<tab> command```其中,target 表示目标文件或目标任务名称;dependencies 表示该目标文件或任务所依赖的文件或任务;command 表示需要执行的命令。

比如,下面是一个简单的 Makefile 例子:```all: testtest: main.o func.o<tab> gcc main.o func.o -o testmain.o: main.c<tab> gcc -c main.c -o main.ofunc.o: func.c func.h<tab> gcc -c func.c -o func.o```其中,目标文件 all 是 Makefile 的默认目标,执行 make 命令时会自动执行 all 目标中所列出的任务。

在本例中,all 的唯一任务是test。

test 任务需要依赖 main.o 和 func.o,如果这两个文件不被更新,则 test 任务不会被重新构建。

2. Makefile 的变量在 Makefile 中,我们可以定义变量来方便地管理代码中的重复部分。

变量可以在任何位置使用,使得代码更加清晰易读,同时也方便了维护。

变量的定义格式是:```变量名 = 值```例如:```CC = gccCFLAGS = -Wall -g```在 Makefile 内使用变量的格式是 $+变量名。

例如:```all: testtest: main.o func.o<tab> $(CC) main.o func.o -o test $(CFLAGS)main.o: main.c<tab> $(CC) -c main.c -o main.o $(CFLAGS)func.o: func.c func.h<tab> $(CC) -c func.c -o func.o $(CFLAGS)```在本例中,我们定义了两个变量,CC 和 CFLAGS。

简单的makefile模板

简单的makefile模板

简单的makefile模板makefile不是总⽤到,每次⽤到的时候总要重新找资料,有点⿇烦(怪⾃⼰基础知识不扎实,汗)。

留⼀个通⽤模板放这,⽅便以后使⽤CC = gccCXX = g++LINK = g++CFLAGS = -g -Wall -O2TARGET = mk0SRCS = $(wildcard *.cpp)SRCS += $(wildcard *.c)CXX_OBJS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))C_OBJS = $(patsubst %.c, %.o, $(wildcard *.c))all:$(TARGET)$(TARGET):$(CXX_OBJS) $(C_OBJS)$(LINK) $(CFLAGS) -o $@ $^%.o:%.cpp$(CXX) $(CFLAGS) -c -o $@ $<%.o:%.c$(CC) $(CFLAGS) -c -o $@ $<.PHONY:cleanclean:rm -rf *.o $(TARGET) $(CXX_OBJS) $(C_OBJS)因为项⽬特殊性,经常c与cpp都会⽤到,所以简单写个这样的makefile⽂件上⾯makefile有很⼤局限性,⽐如只能使⽤与所有源⽂件在⼀个⽬录场景。

下⾯展⽰可以多个⽬录下源⽂件,以及程序使⽤动态库的特殊场景CC = gccCXX = g++LINKC = gccLINKCXX = g++CFLAGS = -g -Wall -O2TOP_DIR := $(shell pwd)SRC_DIRS := $(shell find $(TOP_DIR) -maxdepth 1 -type d)TARGET := $(TOP_DIR)/bin/mk0INC_PATH = -I$(TOP_DIR)/include/LIB_PATH = -L$(TOP_DIR)/lib/EXT_LIB = -Wl,-rpath,$(TOP_DIR)/bin/ -lcsayCXX_SRCS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.cpp))CXX_OBJS = $(patsubst %.cpp, %.o, $(CXX_SRCS))C_SRCS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))C_OBJS = $(patsubst %.c, %.o, $(C_SRCS))all:$(TARGET)$(TARGET):$(CXX_OBJS) $(C_OBJS) $(shell if [ ! -d $(TOP_DIR)/bin ]; then mkdir $(TOP_DIR)/bin; fi)ifeq ($(CXX_SRCS),) $(LINKC) $(LIB_PATH) $(EXT_LIB) $(CFLAGS) -o $@ $^else $(LINKCXX) $(LIB_PATH) $(EXT_LIB) $(CFLAGS) -o $@ $^endif%.o:%.cpp $(CXX) $(INC_PATH) $(CFLAGS) -c -o $@ $<%.o:%.c $(CC) $(INC_PATH) $(CFLAGS) -c -o $@ $<.PHONY:cleanclean:rm -rf $(TARGET) $(CXX_OBJS) $(C_OBJS)如上所⽰,代码包括了三个⽬录:. func0 func1⽬录。

gccmakefile文件的编写精品PPT课件

gccmakefile文件的编写精品PPT课件
❖ 拷贝复制命令: (可视模式下) yy—拷贝一行到剪切板 p—粘贴剪切板的内容 在冒号命令方式下:yn,表示从当前光标处开始复制n行内容到 剪切板。将光标移到相应的位置,按p即可粘贴剪切板的内容。
常用的vim命令
❖ 编辑命令(可视模式下)
dd—删除整行命令 u—恢复前一次的删除动作
❖ 冒号命令方式命令 :q—退出命令 :w—存档 :wq—存档退出 :q!--放弃任何改动,强行退出
实例分析
❖ #The make for test. objects = main.o subr.o exec = prog all:$(objects) gcc –o $(exec) $(objects) main.o:test1.c gcc –c main.c subr.o:test2.c gcc –c subr.c clean: rm –r $(exec) $(objects)
vi的编辑状态
❖ 可视命令模式:一般当进入vi时,会首先进 入可视命令方式,这是Vi的启动默认模式。
❖ 冒号命令方式:所有命令都要以“:”开始, 所输入的字符系统均作命令来处理, 如输入 “:q”代表退出,“:w”表示存盘。
❖ 文本编辑模式:在可视命令模式下,输入”i” 即可进入编辑模式,进行编写、修改代码等 操作。
❖ $@ 扩展成当前规则的目的文件名, ❖ $< 扩展成依靠列表中的第 一个依靠文件 ❖ $^ 扩展成整个依靠的列表
gdb
❖ Linux 包含了一个叫gdb 的GNU 调试程序. gdb 是一个用来调试C 和C++ 程序的强力调 试器. 它使你能在程序运行时观察程序的内部 结构和内存的使用情况. Gdb 功能非常强大:
gcc规则
❖ gcc通过后缀来区别输入文件的类别,gcc所 遵循的部分约定规则如下:

makefile入门 PPT课件

makefile入门 PPT课件
则以<replacement>替换。 – $(wildcard PATTERN...) :保持通配符有效。 功能:在规则中,通配符会被自动展开。但在变量的定义和函数引 用时,通配符将失效。这种情况下如果需要通配符有效,就需要使 用函数“wildcard”。
makefile:编译使用的文件二 • :=和=的区别:
Q&A
谢谢!
隐式规则 • 看如下的一个编译规则: %.o : %.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ %.o(目标,target) : %.c(依赖, prerequisites ) 是表示把所有的[.c]文件都编译成[.o]文件; $< 是每次匹配到的那个依赖文件 $@ 是每次匹配到的那个目标文件
• 什么是makefile
• 分析一个简单的makefile
makefile的基本结构 helloworld的makefile
• Makefile中经常用到的知识 • 我们常用的makefile是如何组成的
• 什么是makefile • 分析一个简单的makefile
• Makefile中经常用到的知识
• 什么是makefile • 分析一个简单的makefile • Makefile中经常用到的知识
• 我们常用的makefile是如何组成的
m:通用库调用路径 makefile:编译使用的文件
m:通用库调用路径 • “-I” :定义了你自己的头文件的存储目录。 • “-L”:定义了你自己的库文件存放目录。 • Make中可以定义变量,直接赋值就可以了: ARPS_ROOT = /home/yedeng/arps • 引用变量使用$(APRS_ROOT),make会自动进行替 换。将$(APRS_ROOT)用“/home/yedeng/arps”来代 替。 实际看我们用的一个m:打开文件

Makefile编写及通用模板

Makefile编写及通用模板

Makefile 函数说明:wildcard 是扩展通配符函数,功能是展开成一列所有符合由其参数描述的文 件名,文件间以空格间隔。

objects= $(wildcard *.c) , 会产生一个所有以.c结尾的文件列表(本例结果为add.c sub.c div.c mul.c cal.c),然后存入变量objects里patsubst 是匹配替换函数, patsubst 函数需要3个参数,第一个是需要匹配的文件样式,第二个是匹配替换成什么文件,第三个是需要匹配的源文件。

objects : $(patsubst %.c,%.o,$(wildcard *.c))会被处理为objects :=add.o sub.o div.o mul.o cal.onotdir 是去除路径函数,只留下文件名,如:./src/mytest.c, 通过notdir之后得到mytest.c Makefile 变量说明:$@ 表示目标文件;一般是在规则中这么用:gcc $(object) -o $@$^ 表示所有依赖文件;用所有依赖文件链接成目的文件:gcc $^ ­o $@$< 表示第一个依赖文件;每个依赖文件生成一个目的文件:gcc ­o $@ ­c $<$? 表示比目标还要新的依赖文件列表 Makefile 赋值操作:= 是最基本的赋值:= 是覆盖之前的值?= 是如果没有被赋值过就赋予等号后面的值+= 是添加等号后面的值make会将整个makefile展开后,再决定变量的值。

也就是说,变量的值将会是整个makefile中最后被指定的值 Makefile 特殊符号:@表示不显示命令本身,而只显示它的结果,通常用在“规则”行中Makefile 规则:target... : prerequisites ...commandtarget 是一个目标文件,可以是执行文件prerequisites 是要生成那个target所需要的文件或是目标command 是make需要执行的命令(任意的Shell命令),一定要以一个Tab 键作为开头。

MakeFile简单编写

MakeFile简单编写

MakeFile简单编写Makefile编写:Makefile好处:⼀次编写,终⾝受益Makefile命名规则。

Makefilemakefile#使⽤时,在命令⾏上输⼊make回车即可#如果使⽤其他名称,在使⽤的时候需要加-f参数指定⽂件名例如:make -f 指定⽂件名Makefile三要素:1⽬标2依赖3规则命令45具体写法:6⽬标:依赖7 tab键规则命令makefile隐含规则:默认处理第⼀个⽬标函数:1 wildcard #可以进⾏⽂件匹配2 patsubst #内容替换Makefile的变量1 $@ 代表⽬标的变量值2 $^ 代表全部依赖的变量值3 $< 第⼀个依赖的变量值4 $? 第⼀个变化的依赖的变量值5 #注:这些只能在规则⾥出现⽰例:2 #get all .c files3 ScrFiles=$(wildcard *.c)4 #all .c files --> .o files5 ObjFiles=$(patsubst %.c,%.o,$(ScrFiles))6 app:$(ObjFiles)7gcc -o app -I ./include $(ObjFiles)89 %.o:%.c10gcc -c $< -I ./include =o $@11 #定义伪⽬标,防⽌有歧义,如果当前⽬录下有⽂件的名称和clean相同,则得到结果不理想12 .PHONY:clean13 clean:14 -@rm *.o #-表⽰当这条命令报错时仍然继续执⾏,@表⽰规则命令不打印到屏幕上15 @rm -f appmakefile ⾃动编译任意⽂件代码:srcFile=$(wildcard *c)TargetFile=$(patsubst %.c,%,$(srcFile))app:$(TargetFile)%:%.cgcc -o $@ $^。

如何写一个简单的Makefile

如何写一个简单的Makefile

如何写一个简单的Makefile当我们在提示符号之下下一个命令:$ make program就是说你要去”make”一个新版本—而且通常是最新版本—的程序. 如果这个程序是一个可执行文件,你所下的这个命令意思就是说你想要完成有所必须的编译(compiling)与连结(linking),然后得出一一个可执行文件. 你可以使用make来使这些程序自动化,不必不断输入为数可观的gcc(or cc)这些编译器指令.当我们讨论make的时候,我们把我们所要建造的程序(program)称做目标(target). 程序是由一个或一个以上的文件汇集在一起所建造出来的,这些文件的关系分为必要文件(prerequisites)与附属文件(dependents). 每一个构成程序的文件依序有他们自己的必要文件和附属文件.例如,你由连结建造了可执行文件. 一旦你的原始文件(source file)或头文件(head file)改变了,你就必须再连结新的可可执行文件之前重新编译目标文件(object file). 每一个原始文件都是一个目标文件的必要文件.Make的优点就是它对附属的隶属关系是非常敏感的,像是原始文件->目标文件,目标文件->可可执行文件. 你负责在描述文件(description file)中指定一些附属文件,这个描述文件的文件名通常为makefile 或是Makefile. 但是make也知道自己所在的执行环境,它也会自己决定许多它自己的附属文件. make会利用文件的文件名,这些文件最近修改的时间,和一些內建的规则,决定编译时要使用哪些文件与如何去建立它们. 在这样的技术背景之下,之前所做的那个简单的make指令会保证在隶属中所有建造目标时必须存在的部分都会被更新.描述文件(Description File)假设你写了一个程序,程序由以下部分所組成:*用C语言写的原始文件— main.c iodat.c dorun.c*用其它语言写的程序码—lo.s ,此文件被C写成的原始文件所调用*一組位于/usr/fred/lib/crtn.a 之中的函数库方法(library routine)如果你用手一一下指令建造这个程序,你会在提示符号下打入:$cc –c main.c$cc –c iodat.c$cc –c dorun.c$as –0 lo.o lo.s$cc –o program main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a当然你也可以在一行cc命令之內就做好编译,连结的工作(要下很长的一串指令),但是在实际的程序设计环境下这是很少发生的(因为指令实在是又长又复杂),因为以下原因: 首先,每一个原始文件都可能被不同的人所建立或测试. 第二,一个大程序会花掉好几小时的编译工作,所以程序设计师一般都会尽可能的使用已经存在的目标文件而不要再重新编译(可以节省时间).现在让我们来看看如何透过描述文件下指令給make. 我们建立了一个新的文件叫做makefile,这个文件和所有的原始码放在同一个目录之下. 为了方便起见,这个描述文件中的每一个指令和附属文件都明显的打出来,很多对make来说都是不需要的. 这个描述文件的內容如下:program : main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.acc –o program main.o iodat.o dorun.o lo.o /usr/fred/lib/ctrn.amain.o : main.ccc –c main.ciodat.o : iodat.ccc –c iodat.cdorun.o : dorun.ccc –c dorun.clo.o : lo.sas –0 lo.o lo.s在每一行左边的数字并不属于描述文件的一部份,只是为了待会解释方便这个描述文件中包含了五个项目(或说是入口点)(entry). 每一个项目由一个含有冒号(:)(叫做附属列[dependency line]或是规则列[rules line]),和一个或一个以上以tab(4个字元空白)开头的命令列(command line). 在附属行那个冒号左边的叫做目标(target);冒号左边的就是目标的必要文件. 受tab影响的(tab-indented)命令列,告诉make如何从他们的必须文件中建造出目标.从上面的描述文件来看,第1列说明了program这个目标依靠main.o,iodat.o,dorun.o,lo.o这些目标文件,还有依靠函数库/usr/fred/lib/crtn.a .第2列指定了从必要文件构造program这个目标文件所必须下的编译器指令.(这些文件都是目标文件与函数库,所以实际上并不用编译,只调用了连结器(linker)而已). 假设program这的目标文件不存在,你可以下这个指令:$make programmake会去执行第二行的命令. 如果其中一个目标文件不在该怎么办呢? 你能够把这个目标文件当作参数传給make(例如:没有main.o ,你可以下指令$make main.o ,就可以得到main.o 这个文件),但是几乎不必这样做.Make最重要的贡献就在于它有能力可以自己决定什么东西必须被建立(例如:在建立program时,如果少了main.o,则他会根据附属列所指定的內容,自己建立main.o这个文件).检查附属文件(Dependency Checking)当你要求make去建造program这个目标时,make会去参考前面所列出的那一个描述文件,但是,第二列的编译器指令并不会立刻就执行. make所做的动作应该如下: 首先,make先去检查目录下是否有program这个文件,如果有的话,make会去检查main.o , iodat.o , dorun.o , lo.o , 还有/usr/fred/lib/crtn.a 这些文件,看看这些文件有没有比program这个文件更新(更新的意思是说,这些文件比program这个文件建造的时间更晚). 这个动作非常容易,因为操作系统会储存每一个文件最近被修改的时间,你只要下一个指令ls –l就可以看到这个信息. 如果program的建造时间比它所有的必要文件的最近修改时间还要晚,make会决定不再重新建造program这个文件,然后不会发出任何指令就离开(跳回提示符号下). 但是在make下这个决定之前,它还会做一些检查: make会根据附属列所描述的必要文件,去检查每一个 .o文件的必要文件是否有更新的情况.例如,从第3列就可以看出main.o的建造必须依靠main.c. 因此,如果再main.o被建造之后,main.c才又被修改,则make就会去执行第4列的指令重新建造一个新的main.o. 只有在program的必要文件都被检查而且更新过(这必要文件的必要文件也要被检查且更新过. 例如:main.o是program的必要文件,main.c是main.o的必要文件). make 才会去执行第2列的指令建造program这个目标文件. 假设自从上一次建造program这个文件之后,iodat.c是唯一被更新过的文件,所以当我们再次执行$make program之后,make所发出的编译器指令实际上只有cc –c main.ccc –o program main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a这两行指令而已.make命令执行以后,会在标准输出上显示出它所发出的指令,因此当你使用make的时候,你可以从你的屏幕上看到它所发出的命令的顺序.总而言之,一个程序的建造包含了顺序正确的指令连接(chain). 一般而言,你只要要求make去建造连接中最后的那个文件即可. make会透过附属文件连接(你在描述文件中所指定的那些必要文件所构成的树状結构构成附属文件连接),自己回朔跟踪(traces back,也就是往树状結构的叶子方向)这个连接,然后找出哪些指令必须被执行. 最后,make会慢慢在连接中前进(moves forward,就是往数状結构的根部移动),执行每个建造目标所必须要有的指令直到目标建立完成(或被更新). 因为这种特性,make是一个使用后序方法(backward-chaining:在人工智能领域中,一种搜索问题答案的方法,它的搜索方向是由目标状态开始,然后向初始状态前进,最后再慢慢回来)这个技巧最有名的例子,这个技巧通常仅使用在像是Prolog语言这一类大家比较不熟悉的环境上.重建最小化(Minimizing Rebuilds)现在我们来讨论一个可以以各种不同版本形式存在的程序(通常是不同平台,或是不同操作系统,或是要分散(release)給不同层级使用者的版本),这是一个可以告诉你make如何节省你的时间,而且可以避免混淆的例子,比前的例子更复杂一点. 假设你写了一个可以绘出文件的程序,它可以在终端(文字模式)或是图形界面(例如:X window)之下执行. 涉及到计算和文件处理的部分在两个版本之中都相同,而且你把它们都存放在basic.c这个文件中. 处理文字模式下使用者输入的程序放在prompt.c之中,而处理图形界面上使用者输入的程序放在window.c之中.因此,这个程序可以以两种不同的版本被发行(release),当你想要建立这个程序时,你可以选择要建立你觉得最适合你现在工作环境的版本. 以文字模式下的版本来说,你可以由basic.c 与prompt.c这两个文件来产生plot_prompt这个可执行文件. 对图形界面的版本来说,你就可以使用basic.c与window.c这两个文件来产生叫做plot_win的可执行文件. 以下产生这两种版本所使用的自述文件:plot_prompt : basic.o prompt.occ –o plot_prompt basic.o prompt.oplot_win : basic.o window.occ –o plot_win basic.o window.obasic.o : basic.ccc –c basic.cprompt.o : prompt.ccc –c prompt.cwindow.0 : window.ccc –c window.c当你第一次建造其中一个可执行文件时,你必须编译basic.c这个文件. 但是只要你没有改变basic.c这个文件,也没有刪除掉basic.o的话,下一次你想要重新产生新的图形界面可执行文件时,就可以不必再重新编译basic.c. 如果你修改了prompt.c,然后重新建立plot_prompt的话,make会去检查修改时间,然后就明白只要重新编译prompt.c,然后再连结就可以了. 也就是说,如果你重新下$make plot_prompt这个指令,你会在屏幕上看到下面的結果:cc –c promptcc –o plot_prompt basic.o prompt.o这这些范例之中的描述文件,实际上可以被大量的简化. 因为make 有內建的规则和宏(macro)的定义可以用来处理在文件中一再重复出现的附属物(dependencies),例如”.o”文件的附属文件”.c”文件,他们都是前面的名称相同,只有副文件名不同而已. 我们会讨论这些make的特色. 在这里,我们只把附属(dependency)和更新(updating)的概念传达給你而已引用make(Invoking make)前面的几个小节的范例都有以下的假设:*工程文件(project file),也就是描述文件,和原始码放在同一个目录底下*描述文件的文件名叫做makefile或是Makefile*將你输入make指令时,工作目录就是这些文件放置的目录有了这些假设,你只要下一个$make target的指令,就可以建立在描述文件中的任何一个目标. 建造这个目标所必须要下的指令都会被显示在终端上,然后执行. 如果一些中间文件(intermediate file)已经存在或者已经被更新过,make会掠过建造这些中间文件的指令. make只会发出建造这个目标所必须执行的最少指令. 如果在上次建造这个目标后,没有任何必要文件被修改或是删除,make会发出一个信息‘target’ is up to date然后什么事情也不做.如果你想要建造在描述文件中没有指定,后置规则(suffix rule)中所讨论的內定规则所蕴涵的目标,例如:你下了一个指令建造一个不存在的目标$make nottarget则make会回应:‘nottarget’ is up to date或是make: Don’t know ho to ma ke nontarget. Stop.如果再目前的工作目录之下真的有nontarget这个文件存在,就会发出上面的第一个信息. 我们可以一次要make建立好几个目标. 这个命令的效果就跟连续的发出好几个make命令相同,例如:$make main.o target就相当于$make main.o$make target一样我们也可以只简单的打上$make没有附上任何的目标名称. 在此情況下,在描述文件中的第一个目标將会被建立(同时他的必要文件也会一起被建立)在命令列下发出make指令有许多的选择项(option,通常前面会加上”-“). 例如,你可以选择不要在终端上显示出make所发出的命令. 反过来说,你也可以要求显示出哪些命令会被执行,而实际上并没有执行它们.语法的基本规则(Basic Rules of Syntax)在你开始要尝试写自己的描述文件之前,你应该了解一些在make所使用的一些难懂的条件(requirement),这些条件如果单独从范例中来体会,是不够不清楚的.最重要的一条规则就是”每一个命令列的开头都要是一个tab字元(四个空格)”. 一个常常犯的错误就是在每个命令列的开头省略了tab字元. 就算在每个命令列中按空白键插入四个空白也不行,因为make无法辨別出这就是tab字元,而且非常不幸的,在这种情況下,就算出了错误,make也无法提供有用的信息.make是靠开头的那个tab字来辨认命令列,所以一定要注意不要在其他不是命令列的那一列之前加上tab字元. 如果你把tab当作第一个字元加在附属列,注解,或这甚至是一个空白列之前,你都会得到错误信息.Tab字元可以用在每一列的任何地方,只有在每一列的第一个字元才有上述的限制.如果你想要检查描述文件中的tab字元,你可以下指令$cat –v –t –e makefile在这里–v 与–t会使得描述文件中的每一个tab字元以^I 的方式显示出来,而–e 会使得每一列的最后以$ 的样子显示出来,所以你可以看出在每一列的結束之前有几个空白.你可以打很长一串指令,如果已经到了文字编辑器的右边界,你可以在到达右边界之前放入一个斜线(\)符号. 你必须确定在新的一列开始之前,会有一个斜线符号在哪里.斜线符号和新的一行之间不要有空白(don’t let any white space slip in between). 由斜线符号所连续的每一列都会被当作单独一列来语法分析(parsing).make会忽略描述文件中的空白行(blank line). 同样的,它也会忽略掉以# 符号开头,到每一列結尾之间的字元,所以# 符号用来当作每个注解的开头.命令列跟附属列不一定都要各自佔掉一列的空间,你可以写成plot_prompt : prompt.o ; cc –o plot_prompt prompt.o虽然之前有说过命令列的开头都要有一个tab字元,不过这里是唯一的例外.一个单独的目标也可以用多个附属列来表示. 当你为了要易于区分附属文件的的种类时,这是一个很实用的技巧,例如file.o : file.ccc –c file.c……file.o : global.h defs.h虽然实际上建造file.o的命令是第一个附属列的下面那一行,即使重新建造时,file.c并没有被修改,可是如果附属的.h文件被修改过的话,file.o仍然会被重新编译.如果你使用了多个附属列的技巧,只有其中一个附属列才能有能够伴随有指令列. 但是如果你在一个附属列中使用了两个冒号,则不在此限.在描述文件中可以有”没有附属文件的目标”(但是冒号还是要打上去,不能省略),这些文件通常不全是文件名. 例如,许多描述文件含有下面的目标,用来幫助程序设计师在一天辛苦的测试之后删除临时文件.clean :/bin/rm –f core *.o当我们下指令$make clean如果工作目录下没有clean这个文件,make就会去执行claen这个项目下的命令脚本(command script). 这是因为make把每一个不存在的目标当作是一个过时的目标在每个项目中的命令,就目前来说,应该要是單一一行的Bourne Shell指令.不要尝试去使用別名(aliases),环境变数(environment variables),或是像if或for这一类会有很多行的命令,同时要避免使用cd,现在你已经能够借由输入你习惯在终端前打的指令来建立你自己的描述文件了. 但是很快的,你会发现非常的乏味. 往后你可简化(simplify)与一般化(generalize)你属于你自己的描述文件的方法.。

编写简单的makefile文件

编写简单的makefile文件

MakeFile文件的编写Sunny.man1. make命令的运行过程在shell的提示符号下,若输入"make",则它会到目前的目录下找寻makefile这个文件。

然后依照makefile中所记录的步骤一步一步的来执行。

经常使用make all, make install, make clean等命令,而他们处理的目标都是一个makefile文件,那么all、install、clean参数是如何调用Makefile文件的运行呢?如果上面的命令如果能够正确运行的话,那么在makefile文件里一定有这样的几行,他们的以all、install、clean开始all: ××××××××××××××××××install: ×××××××××××××××××clean: ××××××××××××××××××××all,install,clean我们可以用其他的变量来代替,他们是编译时的一个参数,在makefile文件中作为一个标志存在,也就是我们所说的目标。

make all 命令,就告诉make我们将执行all所指定的目标。

举一个例子如下:#makefile beginall:@echo you have typed command make allclean:@echo you have typed command make cleaninstall:@echo you have typed command make $@#Makefile end注:all:、clean:、install:行要顶格些,而所有的@echo前要加tab键来跳格缩进.下面是运行结果[root@xxx test]#make allyou have typed command make all[root@xxx test]#make cleanyou have typed command make clean[root@xxx test]#make installyou have typed command make install2.简单makefile文件的编写2.1、makefile文件的一般组成2.1.1.注释:在makefile中,任何以"#"起始的文字都是注释,make在解释makefile的时候会忽略它们.2.1.2转接下行标志:在Makefile中,若一行不足以容纳该命令的时候.可在此行之后加一个反斜线(\)表示下一行为本行的延续,两行应视为一行处理2.1.3宏(macro)宏的格式为:=例如:CFLAGS = -O -systype bsd43其实make本身已有许多的default的macro,如果要查看这些macro 的话,可以用make -p的命令.宏主要是作为运行make时的一些环境变量的设置,比如制定编译器等。

makefile文件编写实例

makefile文件编写实例

makefile文件编写实例以下是一个简单的 makefile 文件示例,它创建了一个名为"example" 的可执行文件,并将其编译为其静态链接库:```all: exampleexample: example.otchmod 666 example.otg++ -o example example.o -static -lboost_static -lcudart example.o: example.cppt$(CXX) -o $@ -c $^ -fPIC -I/usr/include/cuda-I/usr/include/c++/4.8/cuda```这个 makefile 文件使用了两个目标:- `all` 目标:编译所有可执行文件和静态链接库。

- `example` 目标:编译名为 "example" 的可执行文件,并将其编译为其静态链接库。

在 `all` 目标中,我们使用 `chmod` 命令将 "example.o" 文件的访问权限设置为 "666",以便只有所有者可以读取和写入该文件。

然后,我们使用 `g++` 命令将 "example.o" 文件编译为可执行文件,同时将其链接为名为 "static" 的静态链接库。

最后,我们将"example.o" 文件链接到可执行文件中,同时为静态链接库分配一个名称为 "libboost_static.so" 和 "libcudart.so" 的链接器。

在 `example` 目标中,我们使用 `$(CXX)` 命令来编译"example.cpp" 文件,并将其链接为静态链接库。

我们还指定了要链接的静态库和 CUDA 库。

这个 makefile 文件假定您已经在 "usr/include/cuda" 和"usr/include/c++/4.8/cuda" 文件夹中放置了必要的 CUDA 库。

跟我一起写Makefile(Linux)

跟我一起写Makefile(Linux)

跟我⼀起写Makefile(Linux)
1、昨天在 Linux 下⽤ touch 指令新建了⼀个 hello.c 并且使⽤ vim 编辑器写了代码,使⽤ gcc 指令编译最后运⾏成功了。

具体⽅式如下:
在Linux 根⽬录/ 下 root ⽂件下新建⼀个 learngit ⽂件夹(mkdir 指令),使⽤touch 指令创建⽂件 hello.c,使⽤vim 打开并编写以下代码
#include <stdio.h>
void main()
{
printf("Hello World\n");
}
接着使⽤指令: gcc hello.c,会发现在 learngit ⽂件下⽣成了 a.out ⽂件
接着使⽤ ./a.out 会发现会输出"Hello World",这⾥查了⼀下./ 表⽰当前⽬录,../表⽰上⼀⽬录。

2017年2⽉23⽇16:43:14。

# 根据Makefile 的过程1。

应该第⼀步:在所在的hello.c ⽂件路径下,新建⼀个⽂件名字为 Makefile”或“makefile”的⽂件。

# 根据Makefile 的过程2、3。

应该第⼆步:⽤ vim 打开 Makefile⽂件,第⼀⾏写代码 edit : hello.o
注意在 Makefile中不能随便出现 table,因为table代表接下来的信息是命令,命令⾏会被识别成红⾊如下截图!(注意截图中红⾊字体前⾯有⼀个 table 长度为4)
2017年2⽉25⽇18:42:42。

Makefile文件编写

Makefile文件编写

SYNOPSYS VCS Makefile文件编写与研究这个Makefile是synopsys提供的模板,看上去非常好用,你只要按部就班提供实际项目的参数就可以了。

我们来看这个文件的头部说明:makefile 其实完全可以用csh或其他脚本来编写,只是VCS使用的linux内置的make命令定义了一个标准的仿真脚本,make命令是专门用来做项目的源文件管理和编译控制的命令。

这篇文章重点看synpsys的标准仿真脚本都做了哪些操作,然后使用其他脚本来实现。

这里主要是自己写的一点东西,有些地方是猜测的或者不准确。

#---------------------------------------------------------------------------------------------------------------------------# SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of# Synopsys, Inc., and is fully protected under copyright and trade secret# laws. You may not view, use, disclose, copy, or distribute this file or# any information contained herein except pursuant to a valid written# license from Synopsys.# SYNOPSYS公司的版权声明,没有权限不可使用#-----------------------------------------------------------------------------------------------------------------------------# Filename : $Id: Makefile,v 1.0 2006/07/18 23:59:59 vangundy Exp $# Created by : Synopsys Inc. 07/17/2006# $Author : vangundy $# Description : Demonstrates Verilog DUT and SVTB using VCS# makefile文件头#---------------------------------------------------------------------------------------------------------------------------# The Makefile works on two seperate flows. The DEBUG flow is intended to be used# During debugging of a testcase and/or the DUT. The REGRESSION flow is used# During regression runs and collects coverage data.#该makefile模版包括两部分流程,debug(查错)流程和regress(回归测试)流程,两个流程大致步骤都相同都是:Compile,SIM(urg,覆盖#率的分析和采集),debug时主要是跑一个pattern,并dump VPD文件,SIM的同时可以打开DVE视图界面,结束后观察波形,regress主要用#于采集覆盖率,一般要跑多个pattern,这时就无需dump VPD文件(节约时间),由于是debug后有进行的重复运行,所以叫regress(回归)。

makefile写法实例

makefile写法实例

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<stdio.h>void mytool1_print(char *print_str){printf("This is mytool1 print : %s ", print_str);}/*mytool1.h*/#ifndef _MYTOOL_1_H#define _MYTOOL_1_Hvoid mytool1_print(char *print_str);#endif/*mytool2.c*/#include"mytool2.h"#include<stdio.h>void mytool2_print(char *print_str){printf("This is mytool2 print : %s ", print_str);}/*mytool2.h*/#ifndef _MYTOOL_2_H#define _MYTOOL_2_Hvoid mytool2_print(char *print_str);#endif⾸先了解⼀下make和Makefile。

GNU make是⼀个⼯程管理器,它可以管理较多的⽂件。

我所使⽤的RedHat 9.0的make版本为GNU Make version 3.79.1。

makefile文件编写

makefile文件编写

Makefile文件编写详解——WangYiwei 利用makefile工具可以自动完成编译工作。

如果仅修改了几个源文件,则只重新编译这几个源文件,其他没有修改的不再去编译。

如果某个头文件被修改,则只重新编译包含这几个头文件的源文件。

因此可以简化开发工作。

格式:TARGET(目标) :DEPENDENCIES(依赖)COMMOND(命令)目标:程序要产生的文件,如可执行文件和目标文件。

目标也可以是要执行的动作,如clean也成为伪目标。

依赖:是用来产生目标输入文件列表,一个目标通常依赖于多个文件。

命令:是make执行的动作(命令是shell命令或是可在shell下执行的程序)。

注意:每个命令行的起始字符都是table字符$@ 规则目标文件名$< 规则第一个依赖文件名$^ 规则的所有文件列表例子:(1)生成一个可执行文件:说明:在01目录下有main.c sub.c sub.h add.c add.h Makefile,以下部分是Makefile的内容①简单的例子.PHONY: clean#显示地指出clean为伪目标,防止当前目录下存在clean文件,不能进行清理工作main: main.o add.o sub.ogcc main.o add.o sub.o -o mainmain.o: main.c add.h sub.hgcc -c main.c -o main.oadd.o: add.c add.hgcc -c add.c -o add.osub.o: sub.c sub.hgcc -c sub.c -o sub.oclean:@echo "remove file ..."rm main main.o add.o sub.o②利用自定义变量和自动化变量.PHONY: clean#显示的指出clean为伪目标,防止当前目录下存在clean文件,不能进行清理工作OBJECTS = main.o add.o sub.o#自定义变量main: $(OBJECTS)gcc -Wall -g $^ -o $@main.o: main.c add.h sub.hgcc -Wall -g -c $< -o $@add.o: add.c add.hgcc -Wall -g -c $< -o $@sub.o: sub.c sub.hgcc -Wall -g -c $< -o $@clean:@echo "remove file ..."#在命令前加@表示不显示命令rm -f main $(OBJECTS)(2)生成多个可执行文件说明:在02目录下有01test.c 02test.c 03test.c Makefile,以下部分是Makefile 的内容①默认规则.PHONY: all clean#显示的指出clean为伪目标,防止当前目录下存在clean文件,不能进行清理工作CC = gccCFLAGS = -Wall -gBIN = 01test 02test 03testall: $(BIN)clean:@echo "Begin remove ..."rm -f $(BIN)执行之后生成01test 02test 03test可执行文件,系统执行的是隐含推导规则,也可以自己编写推导规则。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

跟我一起写Makefile1.1概述什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE 都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。

这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML 的标识的含义。

特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。

因为,makefile关系到了整个工程的编译规则。

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

make是一个命令工具,是一个解释makefile 中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。

可见,makefile都成为了一种在工程方面的编译方法。

现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。

当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux8.0,make的版本是3.80。

必竟,这个make是应用最为广泛的,也是用得最多的。

而且其还是最遵循于IEEE1003.2-1992标准的(POSIX.2)。

在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。

这里所默认的编译器是UNIX 下的GCC和CC。

1.2关于程序的编译和链接在此,我想多说关于程序编译的一些规范和方法,一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是.obj文件,UNIX下是.o文件,即Object File,这个动作叫做编译(compile)。

然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。

编译时,编译器需要的是语法的正确,函数与变量的声明的正确。

对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。

一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。

链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。

链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是.lib文件,在UNIX 下,是Archive File,也就是.a文件。

总结一下,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。

在编译时,编译器只检测程序语法,和函数、变量是否被声明。

如果函数未被声明,编译器会给出一个警告,但可以生成Object File。

而在链接程序时,链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error),在VC下,这种错误一般是:Link2001错误,意思说是说,链接器未能找到函数的实现。

你需要指定函数的Object File.好,言归正传,GNU的make有许多的内容,闲言少叙,还是让我们开始吧。

1.3Makefile介绍make命令执行时,需要一个Makefile文件,以告诉make命令需要怎么样的去编译和链接程序。

首先,我们用一个示例来说明Makefile的书写规则。

以便给大家一个感兴认识。

这个示例来源于GNU的make使用手册,在这个示例中,我们的工程有8个C文件,和3个头文件,我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。

我们的规则是:1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。

2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。

3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。

只要我们的Makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。

1.3.1Makefile的规则在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。

target...:prerequisites...command......target也就是一个目标文件,可以是Object File,也可以是执行文件。

还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

prerequisites就是,要生成那个target所需要的文件或是目标。

command也就是make需要执行的命令。

(任意的Shell命令)这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。

说白一点就是说,prerequisites 中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。

这就是Makefile的规则。

也就是Makefile中最核心的内容。

说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。

呵呵。

还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。

内容还多着呢。

:)1.3.2一个示例正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。

edit:main.o kbd.o command.o display.o\insert.o search.o files.o utils.occ-o edit main.o kbd.o command.o display.o\insert.o search.o files.o utils.omain.o:main.c defs.hcc-c main.ckbd.o:kbd.c defs.h command.hcc-c kbd.ccommand.o:command.c defs.h command.hcc-c command.cdisplay.o:display.c defs.h buffer.hcc-c display.cinsert.o:insert.c defs.h buffer.hcc-c insert.csearch.o:search.c defs.h buffer.hcc-c search.cfiles.o:files.c defs.h buffer.h command.hcc-c files.cutils.o:utils.c defs.hcc-c utils.cclean:rm edit main.o kbd.o command.o display.o\insert.o search.o files.o utils.o反斜杠(\)是换行符的意思。

这样比较便于Makefile的易读。

我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make”就可以生成执行文件edit。

如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make clean”就可以了。

在这个makefile中,目标文件(target)包含:执行文件edit和中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些.c文件和.h文件。

每一个.o文件都有一组依赖文件,而这些.o文件又是执行文件edit的依赖文件。

依赖关系的实质上就是说明了目标文件是由哪些文件生成的,换言之,目标文件是哪些文件更新的。

在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。

记住,make并不管命令是怎么工作的,他只管执行所定义的命令。

make 会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。

这里要说明一点的是,clean不是一个文件,它只不过是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。

要执行其后的命令,就要在make命令后明显得指出这个lable的名字。

这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。

1.3.3make是如何工作的在默认的方式下,也就是我们只输入make命令。

那么,1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。

2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。

3、如果edit文件不存在,或是edit所依赖的后面的.o文件的文件修改时间要比edit 这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。

4、如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。

(这有点像一个堆栈的过程)5、当然,你的C文件和H文件是存在的啦,于是make会生成.o文件,然后再用.o文件生命make的终极任务,也就是执行文件edit了。

相关文档
最新文档