·ChinaUnix首页 ·论坛 ·博客 
Linux首页 | Linux新闻 | Linux文档 | Linux论坛 | Linux下载 | Linux博客 | Linux搜索
新手入门 | 安装启动 | 管理员指南 | 开发手册 | 桌面应用 | 程序开发 | 数据库 | 网络技术| CentOS | Fedora | MySQL | Apache | Ubuntu | Gentoo| OSCON08
  Linux时代 >> 技术文档 >> 程序开发
 
Linux下的makefile
来源: ChinaUnix博客  日期: 2008.03.15 12:27 (共有条评论) 我要评论
 
linux下的makefile与前面接触的Qualcomm的基本是差不多的,但是在一些地方还是有写出入。

首先,我们要搭建我们的交叉编译环境,这个其实很简单,就是个tar的过程。将我们需要用到的arm-linux-gcc的一些东西放在/usr/local/arm/3.*.*/bin下面,然后在环境变量的配置里面设置一下
export PATH=/usr/local/arm/3.*.*/bin:usr/bin:/usr/sbin:/opt/332/bin/:$PATH
linux下面的/usr/local应该类似于windows下面的program files。在下面我们可以安装自己所需要的软件。

交叉编译环境搭建好以后,我们就要进行makefile的修改了,现在的项目里面有一个缺点便是没有一个总的makefile来编译下面所有的模块,对每一个模块都要自己动手去cd到模块的目录下面运行make,这样做显然是浪费了很多时间,因此我们需要建立一个总的makefile来保证在工程所在的目录下运行make,可以编译工程里面所有的模块。

在我所接触的makefile里面,主要有下面几种:
1.应用的makefile
2..a的makefile
3..so的makefile

应用的makefile主要是针对小应用的,其主要格式如下:

TARGET=app
指定我们的目标
SOURCES=$(wildcard *.c)
wildcard是一个很有用的函数,在这一步我们实现了将当前目录下面所有的.c文件以列表的形式放在了变量SOURCES里面,在此过程中遇到过一个问题,就是.c文件不在当前的目录下,而是在当前目录的子目录下面,这个时候我们的makefile应该怎样编写呢?其实也很简单,我们只需要定义一个.c文件所在的目录的变量就可以了,假如.c文件所在的目录是当前目录下面的src,我们只需按照如下的方法便可以实现:
SRC=src
SOURCES+=$(wildcard $(SRC)/*.c)
我们将src下面的.c也追加到了需要编译的.c文件里面来了。在下面还需对应修改生成.o文件的目录,这样编译的时候才不会报错,否则编译器会提示no such dir or file.

在这个过程中,还曾碰到过一个问题,i.e.,在当前的目录下一共有10个.c文件,而我需要用到其中的8个,有2个d*.c是我不需要的,这个时候使用wildcard还可以么?我曾这样尝试过:

SOURCES=$(wildcard *.c)
SRCOBJS=$(patsubst %.c,%.o, $(SOURCES))
OBJS1:=$(addprefix $(PRJ_NAME)/,$(SRCOBJS))
OBJS2=$(PRJ_NAME)/device.o $(PRJ_NAME)/devproc.o
OBJS1:=$(filter-out $(OBJS2),$(OBJS1)

此时我们便把d开头的两个.c文件从OBJS1中剔除了。
其中的filter-out函数需要注意几点,其第一个参数OBJS2,这个参数里面必须是字符串,不能包含某些特殊的字符,开始的时候我就犯过这么一个错误,我将PRJ_NAME定义成了./project,在匹配的过程中,filter-out是匹配的就是./project/device.o ./project/devproc.o,由于当前目录中实际保存的目录应该是/project/device.o /project/devproc.o,这样filter-out便无法找到./project这个目录,因此也就无法完成剔除的工作了。
另外要注意的是filter和filter-out的区别

函数名称:反过滤函数—filter-out。
函数功能:和“filter”函数事项的功能相反。过滤掉字串“TEXT”中所有符合模式“PATTERN”的单词,保留所有不符合此模式的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。
返回值:空格分割的“TEXT”字串中所有不符合模式“PATTERN”的字串。
函数说明:“filter-out”函数也可以用来去除一个变量中的某些字符串,(实现和“filter”函数相反)。
示例:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter-out $(mains),$(objects))
实现了去除变量“objects”中“mains”定义的字串(文件名)功能。它的返回值为“foo.o bar.o”。


函数名称:过滤函数—filter。
函数功能:和“filter-out”函数事项的功能相反。过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。
返回值:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。
函数说明:“filter”函数也可以用来筛选一个变量中的某些字符串.
示例:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter $(mains),$(objects))
实现了筛选出变量“objects”中“mains”定义的字串(文件名)功能。它的返回值为“main1.o main2.o”。


还有一点需要注意的是上面makefile里面的OBJS1:=$(filter-out $(OBJS2),$(OBJS1),在OBJS1后面我们多加了一个:,而且与上面的OBJS1:保持一致,这又是为什么呢?我们可以看到,在给OBJS1赋值的过程中,我们又引用了OBJS1本身,这样有可能进入一个无限循环的过程中,如果没有:,编译器便会提示Recursive variable `OBJS1' references itself (eventually)你变量又引用了自身,导致编译不通过,所以我们需要使用:=,这样会避免陷入一个无限的循环展开的过程中。
SRCOBJS=$(patsubst %.c,%.o, $(SOURCES))//将所有的.c转换成为.o
OBJS=$(addprefix $(PRJ_NAME)/,$(SRCOBJS))//将.o生成到指定的目录下
DSTDIR=$(SYS_BIN)/$(TARGET)//定义目标文件生成的目录,这里我们区分SYS_BIN和APP_BIN
INCLUDES=-I. -I$(MGUI_RUN_INC) -I$(PRJ_RUN_INC)
这个需要拿出来说一下,那就是include文件的顺序问题,在一个完整的项目当中,我们可能无需去追究他们之间的顺序问题,因为每个.h文件里面都会有ifndef _a_h #define _a_h来保证我们的头文件不会重复包含,那我们这里说的是什么问题呢?在有的项目中,当前目录下的.h文件里面的定义可能与公共目录中.h的定义不同,我们现在需要包含的是当前目录下还是公共目录下的.h文件呢,因为二者不同,就有可能造成编译时出现错误,一般都是变量未定义的错误。所以这个时候我们需要关注INCLUDES中的头文件的包含顺序。
LDFLAGS=-L$(MGUI_LIB) -L$(PRJ_LIB)\
-lmguios\
-lmguiq\
-lmguiclient\
-lmguigdi\
-lmguigfx\
-lmguiwidget\
-lmguicfg\
-lfont\
-lfreetype
//这个下面主要是一些连接的flag,我们所需要用的一些库函数,都是从这些连接库里面来找的。
%.o:%.c
$(CC) -c $(INCLUDES) $(CFLAGS) $
//运行arm-linux-gcc -c -I -Cflags 编译

.PHONY:all install cross clean mkdirprj
all:mkdirprj $(SRCOBJS)
$(CC) -o $(PRJ_NAME)/$(TARGET) $(OBJS) $(LDFLAGS)
$(STRIP) $(PRJ_NAME)/$(TARGET)
mkdirprj:
@if [ ! -d $(PRJ_NAME) ]; then \
  mkdir $(PRJ_NAME); \
fi
//这里需要注意一点,就是我们需要编译的.c文件不在当前的目录下的时候,这个地方也要随之发生改变,我们需要创建一个.o文件所在目录,这个目录要对应.c文件的目录。
install:all
cp $(PRJ_NAME)/$(TARGET) $(DSTDIR)
cross:all
sz $(PRJ_NAME)/$(TARGET)
clean:
-rm -fr $(PRJ_NAME)



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/62407/showart_496960.html
  发表评论 查看评论(共有条评论) 我要提问
 
 


最新资讯更多>> 
· 番茄花园事件给我们的反思
· 红帽收购Qumranet加强虚拟化领..
· Debian 下一个稳定版的代号被确..
· 发行版发布:Mandriva Linux 2..
· Sun VirtualBox v2.0 发布
· Ubuntu Linux用户突破800万
· Mandriva Linux 2009 RC 1 发布
· 构建Linux版本的谷歌Chrome浏览器
· 发行版发布:Scientific Linux..
· BSD发行版:DragonFly BSD 2.1..
论坛热点更多>> 
· 奔腾老机器16M内存,还能用什..
· 【经典】我是一条内存
· 刚接到通知
· 建议!
· 下班我们部门KTV有美女陪 o(..
· 中秋都有什么打算啊
· 誰懂裝修啊,來幫幫忙
· UNIX环境高级编程这本书怎么样?
· 真实的战争~~~~来晚的已经没..
· 《深入理解Linux网络内幕》原..
文档更新更多>> 
· 用YUM升级CentOS系统中PHP和MySQL
· [转]Red Hat Linux 安全设置指南
· 使用Emacs作为文件管理器
· linux内核的移植与遭遇问题的解决
· KStar 校园网锐捷认证GUI版
· 给eclipse安装CDT插件开发C/C++工程
· ubuntu 8.10 安装 Lotus Symphony
· fsck命令
· RHEL5的kickstart中的%packages部..
· linux 线程实现机制分析
 
关于我们 | 联系方式 | 广告合作 | 诚聘英才 | 网站地图 | 友情链接 | 免费注册

Copyright © 2001-2008 ChinaUnix.net All Rights Reserved

感谢所有关心和支持过ChinaUnix的朋友们