makefile的和gcc参数

来源:互联网 发布:黄金时时彩缩水软件 编辑:程序博客网 时间:2024/04/30 15:28

makefile的和gcc参数

今天建个程序工程,需求了解一下makefile的和gcc参数。

首先看一下我使用了makefile

$cat ../rule.mk
#rule.mk

version= $(shell cat $(base_dir)/VERSION | perl -pechomp)

cpp= xlC
cppflag = -g -q64 -D_VERSION="\"$(version)\""

#makefile

base_dir= ../
include $(base_dir)/rule.mk

srcs= $(wildcard *.cpp)
#objs = $(patsubst %.ppc,%.o,$(psrcs)) $(patsubst %.cpp,%.o,$(srcs))
objs = $(patsubst %.cpp,%.o,$(srcs))

inc= `sl-config --cflags`
libmm = `sl-config --libs64`

inc+= -I../include
libs += $(libmm)

.SUFFIXES:.o .cpp

%.o:%.cpp
@$(cpp) $(cppflag) $(inc) -o $@ -c $<

module= bdpp

all:$(module)

$(module):$(objs)
@$(cpp) $(cppflag) $(inc) -bhalt:5 -o $(module) $^  $(libs)
@echo done.

clean:
@rm -f $(objs)
rm $(module)
@echo clean done.
tag:
ctags -R --language-force=C++ --exclude=.svn --exclude=html --exclude=tags

----------------------------

下面简单说明一下:

cppflag= -g -q64 -D_VERSION="\"$(version)\"" 这名可以在编译器里加入参数,D_VERSION可以在程序中使用,并打印程序的版本号。

srcs= $(wildcard *.cpp) wildcard 是求得一个人集合。这里取得当前目录所有.cpp文件名。

objs= $(patsubst %.cpp,%.o,$(srcs))

$(patsubst<pattern>,<replacement>,<text>)
名称:模式字符串替换函数——patsubst
功能:查找<text>中的单词(单词以空格“Tab”回车”“换行分隔)是否符
合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通
配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacem
ent>中的这个“%”将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,
“\%”来表示真实含义的“%”字符)
返回:函数返回被替换过后的字符串。
示例:
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”

objs= $(patsubst %.cpp,%.o,$(srcs))   这名的是根据.cpp文件名得到对应的.o文件

 

.SUFFIXES:.o .cpp  定义前缀。

%.o:%.cpp
@$(cpp) $(cppflag) $(inc) -o $@ -c $<

这句目标是所有%.o.  依赖于.cpp文件。

$@表于目标。即%.o文件。

请看一下预定义说明(来自网络):

预定义变量 含义
$* 不包含扩展名的目标文件名称。
$+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$< 第一个依赖文件的名称。
$? 所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
$@ 目标的完整名称。
$^ 所有的依赖文件,以空格分开,不包含重复的依赖文件。
$% 如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称

 

我这里说明一下,$<$^对都依赖文件来说的。$<是第一个文件(只是文件名),而$^是一个集合,且加路径的文件名。

@$(cpp)$(cppflag) $(inc) -o $@ -c $< 这样,这名就很容易理解,就是根据点cpp文件生成.o中间文件。

下面这个也很好理解,

$(module):$(objs)
@$(cpp) $(cppflag) $(inc) -bhalt:5 -o $(module) $^  $(libs)

最生终可以执行的程序。

 

 

到这个有必要说明一下,生成一个程序文件的几个步骤:

1.预处理,生成.i的文件[预处理器cpp]
2.
编译:将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs]
3.
汇编:有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
4.
链接:连接目标代码,生成可执行程序[链接器ld]

 

 

这里注意下几个参数:如

Gcc–o test.o  -c test.c

这里生成test.o 这是一个中间文件,不是可以执行的文件。中间是有一定组织结构的文件。如果把很多 .o文件打包成一个.a文件。Ar libxxx  xxx.o yyy.o …. 

参数-o 这个是指定输出文件名,而-c是决定出生中间文件。

我们知道,生成执行文件有4个步骤的,加上-c参数,只是做了第3步就停止,并输出目标文件。

-c只激活预处理,编译,和汇编)

类似的,

1步的停下的参数是gcc –E   预处理。

2步的停下的参数是gcc –S   输出汇编代码。

 

Gcc –o test  test.c  这条语句是生成名为test的可行文件。

说明已经执行到第4步。

其他效果相当于

gcc–o test.o –c test.c

gcc–o test test.o

 

makefile中要注意 –L –I 参数的一些用法:

我们知道,调使用一个不在同一个文件的函数有两种方法,

直接在文件里include xxx/ddd/yyy.h”

另外一种是只include “yyy.h”这个头文件,然后用I参数指定路径。

inc=I/xxx/ddd

Gcc-$(inc) –o test.o -c test.c

从前面的知识可以知道,这只是进行到编译的第3步,生成中间文件。这一步调整外面的接口函数,只需要头文件即可。

真正查找一个函数的实现在链接阶段。

这个大多数情况是用库的形式发布,如libxxx.so libxxx.a文件。

需要在生成执行文件的时候使用这些.so .a文件。

makefile语句:

@$(cpp)$(cppflag) $(inc)  -o $(module) $^  $(libs)

其中 $(libs) 就是链接一个库(其实就是很多o.中间文件打包而成)。

链接一个库有两种方式:

一种是在编译命令最后直接加上库路径/库名称。例如你的库在绝对目录/lib/libtest.a下面
你就可以这样来编译
$(CC) $(CFLAGS) $^ -o $@ /lib/libtest.a

另外一种方法是,你可以用-L制定库的路径,用-l指定库的名称
例如库的名称为libtest.a 那么就用-ltest

-L/xxx/yyy/zzz/-ltest 

就是libtest.a libtest.so  因为库的命名是有规则的。

lib开头,以.a.so结尾。

如果没有-L 参数指明数据的话,只编译器里会的/lib/usr/lib/usr/local/lib两个目录。

如果你的库没有放在上面两个目录的话,就会找不到函数,链接报错。

 

这里顺便说一下,-lm -L/xxx/yyy/zzz/-ltest m是一个数学函数的库. 名字为libm.a

若你想使用一些数学函数就要加上这个库。

 

另外L 参数要注意的是:

$(CC)$(CFLAGS) $(OBJS) -o $@ $(libs) –static

$(libs)要放在$@目标的后面,否则有可能找不到库。

 

最后,说明一些动态库和静态库的知识:

生成静态库:

Gcc–c liba.c

Gcc–c libb.c

Ar–cru –o libmylib.a liba.o libb.o

使用:gcc –o test test.c –l mylib –L.

-l指明要加载的库。 -L是搜索路径。

 

生成动态库:

Gcc–c liba.c –fPIC

Gcc–c libb.c –fPIC

Gcc–shared -0 libmylib.so liba.o libb.o

使用

Gcc–o test test.c –l mylib –L

用-l 查找时,会优先链接动态库。

如果有libmylib.a  libmylib.so两个库。会优先链接libmylib.so

Linux加载动态库的默认环境变量:LD_LIBRARY_PATH

可以设置环境变量:export LD_LIBRARY_PATH=xxx

 

 

 

 

 

原创粉丝点击