当前位置: 技术问答>linux和unix
makefile编写遇到问题
来源: 互联网 发布时间:2015-04-30
本文导语: CCC = /usr/local/bin/g++ SRC = ../src/*.cc OBJ = $(SRC: ../src/.cc = ../lib/.o) LIBS = -lsocket -lnsl INCDIR = -I../include -I$(ORACLE_HOME)/rdbms/demo -I$(ORACLE_HOME)/rdbms/public CFLAGS = -g SLIBS = -L${ORACLE_HOME}/lib/ -L${ORACLE_HOME}/rdbms/lib/ -lc...
CCC = /usr/local/bin/g++
SRC = ../src/*.cc
OBJ = $(SRC: ../src/.cc = ../lib/.o)
LIBS = -lsocket -lnsl
INCDIR = -I../include -I$(ORACLE_HOME)/rdbms/demo
-I$(ORACLE_HOME)/rdbms/public
CFLAGS = -g
SLIBS = -L${ORACLE_HOME}/lib/ -L${ORACLE_HOME}/rdbms/lib/ -lclntsh
clean:
rm -f ../lib/*.o *.o
../src/.cc: ../lib/.o
$(CCC) -c ../src/*.cc $(INCDIR) $(CFLAGS)
以上这段makefile总是有错,我如何该也不行,目的是将src目录所有.cc文件编译后将.o文件放入lib目录内。应如何该清高手指路!
SRC = ../src/*.cc
OBJ = $(SRC: ../src/.cc = ../lib/.o)
LIBS = -lsocket -lnsl
INCDIR = -I../include -I$(ORACLE_HOME)/rdbms/demo
-I$(ORACLE_HOME)/rdbms/public
CFLAGS = -g
SLIBS = -L${ORACLE_HOME}/lib/ -L${ORACLE_HOME}/rdbms/lib/ -lclntsh
clean:
rm -f ../lib/*.o *.o
../src/.cc: ../lib/.o
$(CCC) -c ../src/*.cc $(INCDIR) $(CFLAGS)
以上这段makefile总是有错,我如何该也不行,目的是将src目录所有.cc文件编译后将.o文件放入lib目录内。应如何该清高手指路!
|
Make通常用来维护程式,使可执行档的内容保持和原始程式的一致性,因其依循唯
有变动才需重新编译连结的方式,由各档之间的「依存关系」自动去编译连结,如
此可省下了宝贵的时间和系统资源。在Linux中最普遍的例子应是核心(kernel)的
重 编,当读者把gcc等程式和核心原始程式安装完後(Slackware中为D套件,SLS中
为C和 S套件),便可依实际情况去更新或置换核心的内容。核心是由许多不同的部
份所组成 ,如行程的管理、档案系统的支援、周边配备的驱动程式、网路通讯的
协定等,当组 成的部分有所更新或是不需要时,就需要重编核心,以便产生符合
真实环境的核心程 式,使得PC能得到最佳的利用。如没有SCSI卡的PC便不需要
SCSI的驱动程式,而且可 依光碟和音效卡的种类更换不同的驱动程式。如此繁琐
的过程,在make的帮助下,可 以作得又快又好,只需透过一连串的选择,其馀就
完全交给make去负责,真是省事又 方便。和核心编译有关的细节我们稍後再共同
研讨。make的最初目的是帮助程式设计 师作为编译连结时的管理,因此我们先来
看看make的用法。
使用时机和环境
当程式写作或是更新後,编连的步骤便是使用make的最好时机。在Linux中,
启 动make只消打make便可,make会先去找同目录下的Makefile或是makefile,若
找不到 便出现make的参数使用方法。makefile是一个文书档,可用vi或是jed编辑
,它可说 是make的script,make就完全依此档的内容来动作。在这个档中,记录
了档案的产生 方法、相关性质和一些变数等。在这个档中,凡是以#为开头者,整
行都视为注解, 和shell的script file是相同的。makefile中约略可分成变数区
和指令区两部分, 纵贯档案的有依存、字尾等规则,共同构成makefile的语法。
Makefile中的变数
在makefile中可将一字串设定给一变数,需要时可如shell的script file展
开 ,因此也可称为巨集(marco),变数设定的方式为:
变数名称=设定值
除了某些特殊符号外(如#、:、;、=、空白、定位字元、新列字元),其馀都可
作 为设定值的内容。一般来说,最好使用英数字,以避免发生不可预料的错误,
以下是 一些合法的设定
SOURCE = test1.c test2.c test3.c
OBJ = main.o
当要取用(展开)变数时,只需用()将变数括起来,前头加上$符号即可,如
$(OBJ) 这个变数,当make执行至此时,将视为main.o。
依存关系
make的主要工作方式,是依「依存关系」(dependency)来工作的,而所谓的
依存关系,就是指两或多个档案间彼此的关系,譬如我们写了一个test.c程式,当
我们 编译如下时:
$ gcc -O -o test test.c
便会产生test.o这个目的档,因此test.o便是依於test.c,当test.c改变时,
test.o也需重新编译,才能保持程式的最新版本;若test.o是由test1.c和
test2.c 所组成的,那test.o同时依存於test1.c及test2.c,依存关系便是相关档
案的先後关系,和档案的「生成」方式,如C语言的原始档.c需cc或gcc作编译後才
能生成目标档 .o,而且make功能强大,在依存规则中并不限定只能作和编译有关
的动作。
接下来就是将依存规则写入makefile中了,依存规则的格式如下:
目标档;依存档;命令
「目标档」就是「依存档」照「命令」的方式造出的档案,如上例便可写成:
test:test.c;gcc -O -o test test.c
或是可将「命令」写在下一行,但是需有定位字元作为前导,因此可写成:
test:test.c
gcc -O -o test test.c
通常以此方式撰写,认为是较好的方式;若「目标档」或「依存档」中有两个
以 上的档案,各档案名称间以空白隔开便可,如下:
test:test1.c test2.c
gcc -O -o test test1.c test.c
如此定下规则,那天若是test1.c或test2.c有修改时(日期会比test.o还新)
, make便会重新编译,若是test.o为最晚者,那就没有执行命令的必要了。
接下来我们先看范例一:
范例一:
01 #
02 # Makefile for cshow
03 # By Ivor Chen
04 # 08/31/1994
05 #
06
07 CC = gcc
08 OPTIMIZE = -fomit-frame-pointer -O2 -s
09 CFLAGS = $(DEFINES) $(OPTIMIZE)
10 LFLAGS = -N
11
12 PROGS = cshow
13 PROGS_O = cshow.o
14 LIBS = -lvgagl -lvga
15
16 all: progs
17
18 progs: $(PROGS)
19
20 objs: $(PROGS_O)
21
22 .c.o:
23 $(CC) $(CFLAGS) -c -o $*.o $>.depend
45
46 include .depend
范例一是笔者的cshow程式的makefile,其中01至05行以#开头作为注解用;
07至 14行是设定变数,其中07-10所设定的是有关编译器及其命令,11至14行则设
定被编 译的档案名称及额外需被连结的程式库名称;第16行便是一个依存规则,
若是我们在 命令列下只打make,那make便会去寻找makefile中的第一个规则来工
作,在此这便是 第一个规则,但这个规则比较特殊:一、本规则并无「命令」,
二、本规则中的all 并不是档名,而且其後的progs是下一条规则(第18行)的「目
标档」,这样一来,当 我们一去make all时,由於all是由progs所构成,因此会
跳到第18行去,而第18行 的$(PROGS)是cshow,为做本make最终产生的档案,为一
可执行档,第20行的cshow.o 便是最终的目的档,那cshow和cshow.o又是如何产生
的?这和第22、25、28行有关, 这几行是利用下一节的「字尾规则」,稍後再论
。
范例一中第32和35行是makefile中另外常见的规则,其目的不是「产生」目的
档 ,而是去「删除」某些档案,35行的动作包含在32之中,35行的目的是删除可
执行档 (rm -f $(PROGS));而32行会先执行35行的动作,再去删除*.o和*~的档
;若是我 们更新了一大群source的部份时,最好要make clean,否则仍会发生.
o和其source 间版本不同的错误。
字尾规则
通常我们会以特定的字尾来表示不同档案的种类,如.c 便是代表c语言的原始
档 , 而.o 通常代表此档经特定的编译程式所产生的目的档,由於在同一系统中
同一语 言原始档的编译程式皆相同,我们便可为这些原始档定出一定的编译方式
,这便是字 尾规则(Suffix rule)的用意所在,字尾规则通常是在於定义
Makefile的内建依存 规则;字尾规则的语法如下:
.字尾一.字尾二:
命令
其中的意义是字尾一的档案经「命令」的作用後产生字尾二的档案,如范例一
中 的第22和23行:
22 .c.o:
23 $(CC) $(CFLAGS) -c -o $*.o $
有变动才需重新编译连结的方式,由各档之间的「依存关系」自动去编译连结,如
此可省下了宝贵的时间和系统资源。在Linux中最普遍的例子应是核心(kernel)的
重 编,当读者把gcc等程式和核心原始程式安装完後(Slackware中为D套件,SLS中
为C和 S套件),便可依实际情况去更新或置换核心的内容。核心是由许多不同的部
份所组成 ,如行程的管理、档案系统的支援、周边配备的驱动程式、网路通讯的
协定等,当组 成的部分有所更新或是不需要时,就需要重编核心,以便产生符合
真实环境的核心程 式,使得PC能得到最佳的利用。如没有SCSI卡的PC便不需要
SCSI的驱动程式,而且可 依光碟和音效卡的种类更换不同的驱动程式。如此繁琐
的过程,在make的帮助下,可 以作得又快又好,只需透过一连串的选择,其馀就
完全交给make去负责,真是省事又 方便。和核心编译有关的细节我们稍後再共同
研讨。make的最初目的是帮助程式设计 师作为编译连结时的管理,因此我们先来
看看make的用法。
使用时机和环境
当程式写作或是更新後,编连的步骤便是使用make的最好时机。在Linux中,
启 动make只消打make便可,make会先去找同目录下的Makefile或是makefile,若
找不到 便出现make的参数使用方法。makefile是一个文书档,可用vi或是jed编辑
,它可说 是make的script,make就完全依此档的内容来动作。在这个档中,记录
了档案的产生 方法、相关性质和一些变数等。在这个档中,凡是以#为开头者,整
行都视为注解, 和shell的script file是相同的。makefile中约略可分成变数区
和指令区两部分, 纵贯档案的有依存、字尾等规则,共同构成makefile的语法。
Makefile中的变数
在makefile中可将一字串设定给一变数,需要时可如shell的script file展
开 ,因此也可称为巨集(marco),变数设定的方式为:
变数名称=设定值
除了某些特殊符号外(如#、:、;、=、空白、定位字元、新列字元),其馀都可
作 为设定值的内容。一般来说,最好使用英数字,以避免发生不可预料的错误,
以下是 一些合法的设定
SOURCE = test1.c test2.c test3.c
OBJ = main.o
当要取用(展开)变数时,只需用()将变数括起来,前头加上$符号即可,如
$(OBJ) 这个变数,当make执行至此时,将视为main.o。
依存关系
make的主要工作方式,是依「依存关系」(dependency)来工作的,而所谓的
依存关系,就是指两或多个档案间彼此的关系,譬如我们写了一个test.c程式,当
我们 编译如下时:
$ gcc -O -o test test.c
便会产生test.o这个目的档,因此test.o便是依於test.c,当test.c改变时,
test.o也需重新编译,才能保持程式的最新版本;若test.o是由test1.c和
test2.c 所组成的,那test.o同时依存於test1.c及test2.c,依存关系便是相关档
案的先後关系,和档案的「生成」方式,如C语言的原始档.c需cc或gcc作编译後才
能生成目标档 .o,而且make功能强大,在依存规则中并不限定只能作和编译有关
的动作。
接下来就是将依存规则写入makefile中了,依存规则的格式如下:
目标档;依存档;命令
「目标档」就是「依存档」照「命令」的方式造出的档案,如上例便可写成:
test:test.c;gcc -O -o test test.c
或是可将「命令」写在下一行,但是需有定位字元作为前导,因此可写成:
test:test.c
gcc -O -o test test.c
通常以此方式撰写,认为是较好的方式;若「目标档」或「依存档」中有两个
以 上的档案,各档案名称间以空白隔开便可,如下:
test:test1.c test2.c
gcc -O -o test test1.c test.c
如此定下规则,那天若是test1.c或test2.c有修改时(日期会比test.o还新)
, make便会重新编译,若是test.o为最晚者,那就没有执行命令的必要了。
接下来我们先看范例一:
范例一:
01 #
02 # Makefile for cshow
03 # By Ivor Chen
04 # 08/31/1994
05 #
06
07 CC = gcc
08 OPTIMIZE = -fomit-frame-pointer -O2 -s
09 CFLAGS = $(DEFINES) $(OPTIMIZE)
10 LFLAGS = -N
11
12 PROGS = cshow
13 PROGS_O = cshow.o
14 LIBS = -lvgagl -lvga
15
16 all: progs
17
18 progs: $(PROGS)
19
20 objs: $(PROGS_O)
21
22 .c.o:
23 $(CC) $(CFLAGS) -c -o $*.o $>.depend
45
46 include .depend
范例一是笔者的cshow程式的makefile,其中01至05行以#开头作为注解用;
07至 14行是设定变数,其中07-10所设定的是有关编译器及其命令,11至14行则设
定被编 译的档案名称及额外需被连结的程式库名称;第16行便是一个依存规则,
若是我们在 命令列下只打make,那make便会去寻找makefile中的第一个规则来工
作,在此这便是 第一个规则,但这个规则比较特殊:一、本规则并无「命令」,
二、本规则中的all 并不是档名,而且其後的progs是下一条规则(第18行)的「目
标档」,这样一来,当 我们一去make all时,由於all是由progs所构成,因此会
跳到第18行去,而第18行 的$(PROGS)是cshow,为做本make最终产生的档案,为一
可执行档,第20行的cshow.o 便是最终的目的档,那cshow和cshow.o又是如何产生
的?这和第22、25、28行有关, 这几行是利用下一节的「字尾规则」,稍後再论
。
范例一中第32和35行是makefile中另外常见的规则,其目的不是「产生」目的
档 ,而是去「删除」某些档案,35行的动作包含在32之中,35行的目的是删除可
执行档 (rm -f $(PROGS));而32行会先执行35行的动作,再去删除*.o和*~的档
;若是我 们更新了一大群source的部份时,最好要make clean,否则仍会发生.
o和其source 间版本不同的错误。
字尾规则
通常我们会以特定的字尾来表示不同档案的种类,如.c 便是代表c语言的原始
档 , 而.o 通常代表此档经特定的编译程式所产生的目的档,由於在同一系统中
同一语 言原始档的编译程式皆相同,我们便可为这些原始档定出一定的编译方式
,这便是字 尾规则(Suffix rule)的用意所在,字尾规则通常是在於定义
Makefile的内建依存 规则;字尾规则的语法如下:
.字尾一.字尾二:
命令
其中的意义是字尾一的档案经「命令」的作用後产生字尾二的档案,如范例一
中 的第22和23行:
22 .c.o:
23 $(CC) $(CFLAGS) -c -o $*.o $