| |
| 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
|
| 发表评论
查看评论(共有条评论)
我要提问
|
| |
|
|
|