编写一个真正可以用的makefile,遇到的问题及特殊符号含义汇总

最近发现网上很多关于Makefile的文章都过于基础,事实上太笨拙的写法在工程中是不可能用到的,因为你的makefile一般会面对几十个.c .h,会有诸多的动态库需要加载。这里做一个汇总和总结,也是对我自己遇到的问题有个简单记录,方便将来自己复习。

一 特殊符号,极大简化Makefile代码。

$? 代表依赖文件列表中被改变过的所有文件。

$^ 代表所有通过目录搜索得到的依赖文件的完整路径名(目录 + 一般文件名)列表。

$@ 代表规则的目标。

$< 代表规则中通过目录搜索得到的依赖文件列表的第一个依赖文件。

$% 仅当目标是函数库文件中,表示规则中的目标成员名。

1.AR        

归档维护程序的名称,默认值为 ar

2.ARFLAGS   

归档维护程序的选项。
3.AS        

汇编程序的名称,默认值为 as
4.ASFLAGS   

汇编程序的选项。
5.CC        

C编译器的名称,默认值为 cc
6.CCFLAGS   

C编译器的选项。
7.CPP       

C预编译器的名称,默认值为 $(CC) -E
8.CPPFLAGS  

C预编译的选项。

9.-c -o -O

-c是指到编译那一步为止,也就是生成.o

-o是指生成指定名称的可执行文件。

-O是优化,后面可以加数字指定优化等级。

下面贴一段我的makefile:


SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
CC=gcc
LDFLAGS=-L/usr/local/lib -lintlc -lsvml -limf enc_sub.so
CFLAGS =-I/home/knight/Desktop/DolbySDK/Code/system_code/cli_frontend/include/


encoder: $(OBJS)
       $(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c
        $(CC) -c $^ $(CFLAGS)   

clean:
        rm *.o
可以看到里面有 .c .h的编译,动态库的调用。

SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)</span>
这里两句是指先获取所有的.c,再把所有的.c编译成.o,当然这里不是真的编译,相当于指定一种编译规则。

 
CC=gcc
指定编译器
 
LDFLAGS=-L/usr/local/lib -lintlc -lsvml -limf enc_sub.so
这里引用动态库,ldflags指的是在哪个目录搜索动态库,后面接一个大写的L,小写的l是指在指定目录下搜索那些库,看我的调用顺序,因为这几个库是有依赖关系的,具体可以用ldd命令查看某个库的依赖。被其他库所依赖的放前面,前三个库全名是libintlc.so等等,搜索的时候自动去除开头的lib 和 结尾的 .so ,包括 .so.5,这都是自动匹配的。最后一个库为什么不加-l,而且加上了.so呢,因为我这个库的名字就叫enc_sub.so,不需要掐头去尾的搜索,不加-l,直接写全名就好。
 
CFLAGS =-I/home/knight/Desktop/DolbySDK/Code/system_code/cli_frontend/include/
这里是你所需要的头文件的路径。
 
encoder: $(OBJS)
encoder是最后要生成的可执行文件。$(OBJS)OBJS是开头定义的变量,指代所有生成的.o,其实makefile就是shell脚本,这里属于脚本语法。
 
$(CC) -o $@ $^ $(LDFLAGS)

这句我们对应每个空格来说:

用gcc编译器 生成 encoder 依赖于objs这个变量里的所有.o 并且调用XX库文件

<span style="font-family: Arial, Helvetica, sans-serif;">%.o: %.c</span>
规则很简单,要生成.o,依赖.c
 
$(CC) -c $^ $(CFLAGS) 
用gcc编译器 生成.o 依赖于所有的.c 引用那些头文件
 

为什么我有一行调用ldflags,有一行调用cflags呢?这就是编译的四个阶段不同导致的。.c->.o->encoder。

这里提两个可能遇见的问题,因为其他的我记不清了=。=:

1.如果你再安装一个软件,./configure时加上如上动态库引用时报错了,说让你用什么交叉编译。那很可能使你把库名字写错了,或者引用格式没写对。

2.如果make的时候出现错误:undefined reference to 'xxxxx'

那你不是库文件没引用成功,就是头文件没引用成功,好好看看你写的对不对。这里贴一段引用网上一段解释,觉得解释的相当到位。

为什么会出现undefined reference to 'xxxxx'错误?
首先这是链接错误,不是编译错误,也就是说如果只有这个错误,说明你的程序源码本身没有问题,是你用编译器编译时参数用得不对,你没有指定链接程序要用到得库,比如你的程序里用到了一些数学函数,那么你就要在编译参数里指定程序要链接数学库,方法是在编译命令行里加入-lm
4、-l参数和-L参数
-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了
好了现在我们知道怎么得到库名,当我们自已要用到一个第三方提供的库名字libtest.so,那么我们只要把libtest.so拷贝到/usr/lib里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里的函数,我们还需要与libtest.so配套的头文件)
放在/lib和/usr/lib和/usr/local/lib里的库直接用-l参数就能链接了,但如果库文件没放在这三个目录里,而是放在其他目录里,这时我们只用-l参数的话,链接还是会出错,出错信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是链接程序ld在那3个目录里找不到libxxx.so,这时另外一个参数-L就派上用场了,比如常用的X11的库,它在/usr/X11R6/lib目录下,我们编译时就要用-L/usr/X11R6/lib -lX11参数,-L参数跟着的是库文件所在的目录名。再比如我们把libtest.so放在/aaa/bbb/ccc目录下,那链接参数就是-L/aaa/bbb/ccc -ltest
另外,大部分libxxxx.so只是一个链接,以RH9为例,比如libm.so它链接到/lib/libm.s
o.x,/lib/libm.so.6又链接到/lib/libm-2.3.2.so。

欢迎批评指正探讨。

GNU libiconv-1.15和libintl-0.19.8.1,VS2015工程和 Makefile 命令行编译文件 CSDN-tags: libiconv1.15 libintl 0.19.8.1 VS2015 Makefile 声明: 代码为本人良心制作,虽然花费了一定的时间和精力,但不保证完全没有错误。如果您下载并使用了本代码,将其包含在您发布的应用,给您带来了经济上,心理上,生活上的损失,本人不负有责任。 所有代码都基于官网进行修改,iconv的代码来源于libiconv-1.15的lib目录,intl的代码来源于gettext-runtime的intl目录。 intl需要iconv的支持,如果想单独编译不需要iconv的intl, 请自行修改intl目录下的config.h文件, /* Define if you have the iconv() function and it works. */ #define HAVE_ICONV 1 /* Define to 1 if you have the header file. */ #define HAVE_ICONV_H 1 为: /* Define if you have the iconv() function and it works. */ /* #undef HAVE_ICONV */ /* Define to 1 if you have the header file. */ /* #undef HAVE_ICONV_H */ 并修改VS工程预处理器定义,删掉/DDEPENDS_ON_LIBICONV=1 VS的工程为VS2015的工程文件,使用VC140工具集,如果没有2015,也可以用Makefile.mak文件来编译。 nmake /f Makefile.mak [DLL] [DEBUG] 指定 DLL=1 编译dll版本,默认是lib版本,libiconv.lib , libintl.lib。 指定 DEBUG=1 编译debug版本,默认是release版本。 同理,如果intl不需要iconv,请修改上面的配置文件选项,并, 删掉Makefile.mak/DDEPENDS_ON_LIBICONV=1 配置文件的制作,参考了以下几处,修改的大概原则是,能定义的全定义了,就这样: https://github.com/kahrl/gettext-msvc 这个地址提供了libiconv和libintl的VS工程和配置文件。 https://github.com/winlibs 为编译PHP而修改的libiconv和libintl源码,libiconv是最新1.15版本,gettext不是。 附带的Cygwin目录的工具 libiconv官方的制作文档,用cygwin配合VC,生成的配置文件。 一大堆的宏和函数搞得我头晕脑涨。所以配置文件如果有错误,也在所难免,所有修改的文件,如config.h,iconv.h,libintl.h都附带了原始文件。 如: 配置文件 原始文件 DLL原始文件 LIB原始文件 config.h config.h.in iconv.h iconv.h.build.in iconv.h.in localcharset.h localcharset.h.build.in localcharset.h.in libgnuintl.h libgnuintl.in.h 欢迎同学们下载测试。有问题可以给我发邮件travel981cn@139.com
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值