How to write a Makefile

How to write the better Makefile for cpputest 最近给其他几个团队培训UT工具cpputest。自己没有写PPT,而是从网上找了一份比较不错的CppUTest课件,这份课件来自于一家叫Odd-e的敏捷咨询公司。 里面的内容比较基础,也很清晰,非常适合帮助初学者较快的入门。 由于我之前一直是在Windows下用VS使用这款UT工具,Linux下的实践仅仅限于在学习cpputest源码中的过程中,利用工具附带的example工程 阅读详情

How to write a Makefile

17:32:18


Introduction
Make is one of the original Unix tools for Software Engineering. By S.I. Feldman of AT&T Bell Labs circa 1975. But there are public domain versions (eg. GNU) and versions for other systems (eg. Vax/VMS).
Related tools are the language compilers (cc, f77, lex, yacc, etc.) and shell programming tools (eg. awk, sed, cp, rm, etc.). You need to know how to use these.

Important adjuncts are lint (source code checking for obvious errors) ctags (locate functions, etc. in source code) and mkdepend. These are nice, and good programmers use them.

Important, and related tools, are the software revision systems SCCS (Source Code Control System) and RCS (Revision Control System -- the recommended choice)

The idea is to automate and optimize the construction of programs/files -- ie. to leave enough foot prints so that others can follow.

Makefile Naming
make is going to look for a file called Makefile, if not found then a file called makefile. Use the first (so the name stands out in listings).
You can get away without any Makefile (but shouldn't)! Make has default rules it knows about.

Makefile Components
Comments
Comments are any text beginning with the pound (#) sign. A comment can start anywhere on a line and continue until the end of the line. For example:

# $Id: slides,v 1.2 1992/02/14 21:00:58 reggers Exp $

Macros
Make has a simple macro definition and substitution mechanism. Macros are defined in a Makefile as = pairs. For example:

MACROS=  -me
PSROFF=  groff -Tps
DITROFF= groff -Tdvi
CFLAGS= -O -systype bsd43

There are lots of default macros -- you should honor the existing naming conventions. To find out what rules/macros make is using type:
% make -p

NOTE: That your environment variables are exported into the make as macros. They will override the defaults.
You can set macros on the make command line:

% make "CFLAGS= -O" "LDFLAGS=-s" printenv
   cc -O printenv.c -s -o printenv

Targets
You make a particular target (eg. make all), in none specified then the first target found:

paper.dvi: $(SRCS)
       $(DITROFF) $(MACROS) $(SRCS) >paper.dvi

NOTE: The the line beginning with $(DITROFF) begins with TAB not spaces.
The target is made if any of the dependent files have changed. The dependent files in this case are represented by the $(SRCS) statement.

Continuation of Lines
Use a back slash (/). This is important for long macros and/or rules.


Conventional Macros
There are lots of default macros (type "make -p" to print out the defaults). Most are pretty obvious from the rules in which they are used:

AR = ar
GFLAGS =
GET = get
ASFLAGS =
MAS = mas
AS = as
FC = f77
CFLAGS =
CC = cc
LDFLAGS =
LD = ld
LFLAGS =
LEX = lex
YFLAGS =
YACC = yacc
LOADLIBS =
MAKE = make
MAKEARGS = 'SHELL=/bin/sh'
SHELL = /bin/sh
MAKEFLAGS = b

Special Macros
Before issuing any command in a target rule set there are certain special macros predefined.


$@ is the name of the file to be made.
$? is the names of the changed dependents.
So, for example, we could use a rule

printenv: printenv.c
        $(CC) $(CFLAGS) $? $(LDFLAGS) -o $@

alternatively:
printenv: printenv.c
        $(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@

There are two more special macros used in implicit rules. They are:

$< the name of the related file that caused the action.
$* the prefix shared by target and dependent files.

Makefile Target Rules
The general syntax of a Makefile Target Rule is

    target [target...] : [dependent ....]
    [ command ...]

Items in brackets are optional, ellipsis means one or more. Note the tab to preface each command is required.
The semantics is pretty simple. When you say "make target" make finds the target rule that applies and, if any of the dependents are newer than the target, make executes the com- mands one at a time (after macro substitution). If any dependents have to be made, that happens first (so you have a recursion).

A make will terminate if any command returns a failure sta- tus. That's why you see rules like:

clean:
        -rm *.o *~ core paper

Make ignores the returned status on command lines that begin with a dash. eg. who cares if there is no core file?
Make will echo the commands, after macro substition to show you what's happening as it happens. Sometimes you might want to turn that off. For example:

install:
        @echo You must be root to install

Example Target Rules
For example, to manage sources stored within RCS (sometimes you'll need to "check out" a source file):

SRCS=x.c y.c z.c

$(SRCS):
        co $@

To manage sources stored within SCCS (sometimes you'll need to "get" a source file):
$(SRCS):
        sccs get $@

Alternativley, to manage sources stored within SCCS or RCS let's generalize with a macro that we can set as required.
SRCS=x.c y.c z.c
# GET= sccs get
GET= co

$(SRCS):
        $(GET) $@

For example, to construct a library of object files
lib.a: x.o y.o z.o
        ar rvu lib.a x.o y.o z.o
        ranlib lib.a

Alternatively, to be a bit more fancy you could use:
OBJ=x.o y.o z.o
AR=ar

lib.a: $(OBJ)
        $(AR) rvu $@ $(OBJ)
        ranlib $@

Since AR is a default macro already assigned to "ar" you can get away without defining it (but shouldn't).
If you get used to using macros you'll be able to make a few rules that you can use over and over again.
For example, to construct a library in some other directory

INC=../misc
OTHERS=../misc/lib.a

$(OTHERS):
        cd $(INC); make lib.a

Beware:, the following will not work (but you'd think it should)
INC=../misc
OTHERS=../misc/lib.a

$(OTHERS):
        cd $(INC)
        make lib.a

Each command in the target rule is executed in a separate shell. This makes for some interesting constructs and long continuation lines.
To generate a tags file

SRCS=x.c y.c z.c
CTAGS=ctags -x >tags

tags:   $(SRCS)
        ${CTAGS} $(SRCS)

On large projects a tags file, that lists all functions and their invocations is a handy tool.
To generate a listing of likely bugs in your problems
lint:
        lint $(CFLAGS) $(SRCS)

Lint is a really good tool for finding those obvious bugs that slip into programs -- eg. type classes, bad argu- ment list, etc.

Some Basic Make Rule
People have come to expect certain targets in Makefiles. You should always browse first, but it's reasonable to expect that the targets all (or just make), install, and clean will be found.


make all -- should compile everything so that you can do local testing before installing things.
make install -- should install things in the right places. But watch out that things are installed in the right place for your system.
make clean -- should clean things up. Get rid of the executables, any temporary files, object files, etc.
You may encounter other common targets, some have been already mentioned (tags and lint).


An Example Makefile for printenv

# make the printenv command
#
OWNER=bin
GROUP=bin
CTAGS= ctags -x >tags
CFLAGS= -O
LDFLAGS= -s
CC=cc
GET=co
SRCS=printenv.c
OBJS=printenv.o
SHAR=shar
MANDIR=/usr/man/manl/printenv.l
BINDIR=/usr/local/bin
DEPEND= makedepend $(CFLAGS)
all:    printenv

# To get things out of the revision control system
$(SRCS):
        $(GET) $@
# To make an object from source
       $(CC) $(CFLAGS) -c $*.c

# To make an executable

printenv: $(OBJS)
        $(CC) $(LDFLAGS) -o $@ $(OBJS)

# To install things in the right place
install: printenv printenv.man
        $(INSTALL) -c -o $(OWNER) -g $(GROUP) -m 755 printenv $(BINDIR)
        $(INSTALL) -c -o $(OWNER) -g $(GROUP) -m 644 printenv.man $(MANDIR)

# where are functions/procedures?
tags: $(SRCS)
        $(CTAGS) $(SRCS)

# what have I done wrong?
lint: $(SRCS)
        lint $(CFLAGS) $(SRCS)

# what are the source dependencies
depend: $(SRCS)
        $(DEPEND) $(SRCS)

# to make a shar distribution
shar:   clean
        $(SHAR) README Makefile printenv.man $(SRCS) >shar

# clean out the dross
clean:
        -rm printenv *~ *.o *.bak core tags shar

# DO NOT DELETE THIS LINE -- make depend depends on it.
printenv.o: /usr/include/stdio.h

Makefile Implicit Rules
Consider the rule we used for printenv

printenv: printenv.c
        $(CC) $(CFLAGS) printenv.c $(LDFLAGS) -o printenv

We generalized a bit to get
printenv: printenv.c
        $(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@

The command is one that ought to work in all cases where we build an executable x out of the source code x.c This can be stated as an implicit rule:
.c:
        $(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@

This Implicit rule says how to make x out of x.c -- run cc on x.c and call the output x. The rule is implicit because no particular target is mentioned. It can be used in all cases.
Another common implicit rule is for the construction of .o (object) files out of .c (source files).

.o.c:
        $(CC) $(CFLAGS) -c $<

alternatively
.o.c:
        $(CC) $(CFLAGS) -c $*.c

Make Dependencies
It's pretty common to have source code that uses include files. For example:

% cat program.c

#include       
#include        "defs.h"
#include        "glob.h"
        etc....
main(argc,argv)
        etc...

The implicit rule only covers part of the source code depen- dency (it only knows that program.o depends on program.c). The usual method for handling this is to list the dependen- cies separately;
        etc...
        $(CC) $(CFLAGS) -c $*.c
        etc...
program.o: program.c defs.h glob.h

Usually an implicit rule and a separate list of dependencies is all you need. And it ought to be easy enough to figure out what the dependencies are.
However, there are a number of nice tools around that will automatically generate dependency lists for you. For example (trivial):

DEPEND= makedepend $(CFLAGS)
        etc...
# what are the source dependencies

depend: $(SRCS)
        $(DEPEND) $(SRCS)

        etc....
# DO NOT DELETE THIS LINE -- ....

printenv.o: /usr/include/stdio.h

These tools (mkdepend, mkmkf, etc.) are very common these days and aren't too difficult to use or understand. They're just shell scripts that run cpp (or cc -M, or etc.) to find out what all the include dependencies are. They then just tack the dependency list onto the end of the Makefile.

Based on Make and Makefiles by
Reg Quinton
Computing and Communications Services
The University of Western Ontario
London, Ontario N6A 5B7
Canada


--------------------------------------------------------------------------------
Press here to return to the General Unix Software Menu.

RK3588 buildroot 制作的系统增加 docker 支持 RK3588 使用buildroot制作的系统添加 docker 和 docker-compose 的功能 阅读详情

相关推荐

2080Ti双卡开启NVLink

本文介绍了如何在Ubuntu 22.04系统下给2080Ti双卡开启NVLink的方法。

flymyd的博客 2901

MakeFile Implicit Rules,A Gift for Me(强大的MAKEFILE)!!!

MakeFile Implicit Rules,A Gift for Me(强大的MAKEFILE)!!!  这几天在解决源代码编译时忽然遇到个问题,今天终于在网络上学习MAKEFILE资料后得到解决,在此与大家分享。  使用GCC开发的朋友是不是会常写MakeFile呀,一般来说COPY一个已经有的MakeFile,改一改加入自己的CFLAGS和OBJECTS就好了,其中有几行处

冷梦天空 业精于勤 【程序员的人生】 1175

LabVIEW事件结构避坑指南:为什么你的‘确定按钮’事件有时会失灵?

本文深入探讨了LabVIEW事件结构中'确定按钮'事件失灵的常见原因及解决方案。从事件队列机制到事件类型选择,详细分析了事件丢失的五大原因,包括事件处理耗时过长、事件类型选择不当等,并提供了优化登录界面案例的实用建议。掌握这些技巧可显著提升LabVIEW用户界面的响应可靠性。

weixin_42548888的博客 355

从头开始写项目Makefile(二):隐含规则自动推导

原文链接:添加链接描述 上一节的Makefile勉强可用,但还写的比较繁琐,不够简洁。对每一个.c源文件,都需要写一个生成其对应的.o目标文件的规则,如果有几百个或上千个源文件,都手动来写,还不是很麻烦,这也不够自动化啊。 这样,我们把生成.o目标文件的规则全部删除掉,就是这样一个Makefile文件: target_bin : main.o debug.o ipc.o timer.o tools.o —gcc -o target_bin main.o debug.o ipc.o timer.o tool

qq_43248127的博客 314

基于openEuler配置LAMP,部署WordPress

openEuler 基于OpenEular操作系统部署WordPress,必须包含以下内容: OpenEular的安装与基本配置。 基于SSH远程管理方式开展操作。 部署LAMP环境。 部署WordPress软件。 提供个人网站服务,并通过浏览器测试应用。 简要讲授相关知识与原理。 cd /etc/yum.repos.d 欧拉系统安装后,没有配置yum源,我们需要重新配置。 [root@localhost yum.repos.d]# ls -l 总用量 4 -rw-r--r--

Axiayouqiaomu的博客 6081

CAN开发笔记(TI开发者推荐笔记)

查阅了很多资料没有查阅到关于5728芯片CAN模块寄存器的介绍,希望通过本文能给做CAN驱动的后来者有一点参考意义,我也是刚接触CAN模块有些不足请各位多多指正。 由下图所示是CAN模块初始化流程图 首先要开始初始化,设置CAN位时间,然后配置message objects, 完成初始化。 1.开始初始化 首先要控制DCAN_CTL 寄存器,该寄存器是CAN模块的总控制器,很多配置通过...

weixin_44316996的博客 3563

Linux下C++的通用Makefile与解析

http://graybull.is-programmer.com/posts/37758.html 本文给出万能Makefile的具体实现,以及对其中的关键点进行解析。 号称万能Makefile,一统江湖。我对原版的Makefile做了些修改。首先揭开它的庐山真面目: #################################################### #

Hello World! 935

避开这些坑!晶圆封装中Wire Bonding(引线键合)的5种常见不良与实战调试心得

本文深入探讨晶圆封装中Wire Bonding(引线键合)的5种常见不良现象,包括Wire Offset、BSOB不良、球径/球厚异常、弧度不良和IMC问题。通过实际案例和参数优化方案,帮助工程师提升封装质量和可靠性,特别适用于半导体封装领域的专业人士。

weixin_33672109的博客 526

how to write a makefile

makefile中的注释是以#号开头一直到行尾的字符,当nmake工具处理到这些字符的时候,它会完全忽略#号及全部注释字符。   在引用宏时只需在变量前加$符号,但是要注意的是,如果变量名的长度超过一个字符,在引用时就必须加圆括号()   configure是一个可移植的shell脚本,它检查编译环境以决定哪些库可用,所用平台有什么特征,哪些库和头文件已经找到等等。基于这些信息,它修改编译

TestFamily的专栏 1327

Transformer 时间序列预测实战

Transformer 时间序列预测实战

机器学习深度学习业余选手 743

【5】GD32H7xx CAN发送及FIFO接收

GD32H7xx CAN收发调试记录,包含源码

madao1234的博客 1816

MakeFile _10.3 Variables Used by Implicit Rules

10.3 Variables Used by Implicit Rules(潜规则。哈哈)The commands in built-in implicit rules make liberal use of certain predefined variables. You can alter the values of these variables in the makefile, wi

Easiny 650

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

How to write a simple Makefile

ENVDIR = (SOME PLACE)/ws     # the project environmentinclude    $(ENVDIR)/tpmakeenv   # predefinition by the environment# directory for output filesOS_OBJDIR = (SOME PLACE)/lib# directory for source

quanben 715

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

How to write a Makefile for ARM board

<br />First Edition<br /> <br />#<br /> # Description:<br /> # Makefile for 2.6 device drivers<br /> #<br /><br /> # Comment/uncomment the following line to disable/enable debugging<br /> #DEBUG = y<br /><br /> # Add your debugging flag (or not) to C

脚印 705

如何写makefile

How to write a MakefileIntroductionMake is one of the original Unix tools for Software Engineering. By S.I. Feldman of AT&T Bell Labs circa 1975. But there are public domain versions (eg. GNU) a

hotsolaris的专栏 1027

How to write makefile

http://wiki.ubuntu.org.cn/%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile:%E4%B9%A6%E5%86%99%E8%A7%84%E5%88%99#.E8.87.AA.E5.8A.A8.E7.94.9F.E6.88.90.E4.BE.9D.E8.B5.96.E6.80.A7

ziliangxiao的专栏 1041

how to write makefile

出处:http://www.chinaunix.net/jh/23/408225.html关于程序的编译和链接首先要把源文件编译成中间代码文件,在windows下也就是.obj文件,UNIX下是.o文件,即Object File,这个动作叫做编译,然后再把大量的Object File合成执行文件,这个动作叫作链接。链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在

永恒之爱的专栏 842

how to write Makefile

Search this site   Software Engineering‎ > ‎ Make Tutorial: How-To Write A Makefile Many C and C++ projects rely on makefiles for thei

nilbooy的博客 1198

How to write Makefile for kernel modules

ifneq ($(KERNELRELEASE),) obj-m := mymodule.o mymodule-objs := file_one.o file_two.o

ziliangxiao的专栏 671
上一篇: Write debug output to console window
green2
博客等级 码龄25年 0粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值