博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
make和makefile
阅读量:7305 次
发布时间:2019-06-30

本文共 4167 字,大约阅读时间需要 13 分钟。

hot3.png

  Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。而makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。makefile 文件是许多编译器--包括 Windows NT 下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改 makefile 文件而已。   在 UNIX 系统中,习惯使用 Makefile 作为 makefile 文件。如果要使用其他文件作为 makefile,则可利用类似下面的 make 命令选项指定 makefile 文件:

make命令
  $ make -f Makefile.debug
  例如,一个名为prog的程序由三个C源文件filea.c、fileb.c和filec.c以及库文件LS编译生成,这三个文件还分别包含自己的头文件a.h、b.h和c.h。通常情况下,C编译器将会输出三个目标文件filea.o、fileb.o和filec.o。假设filea.c和fileb.c都要声明用到一个名为defs的文件,但filec.c不用。即在filea.c和fileb.c里都有这样的声明:
   #include "defs"
   那么下面的文档就描述了这些文件之间的相互联系:
 ---------------------------------------------------------
   #It is a example for describing makefile
   prog : filea.o fileb.o filec.o
   cc filea.o fileb.o filec.o -LS -o prog
   filea.o : filea.c a.h defs
   cc -c filea.c
   fileb.o : fileb.c b.h defs
   cc -c fileb.c
   filec.o : filec.c c.h
   cc -c filec.c
 ----------------------------------------------------------
   这个描述文档就是一个简单的makefile文件。
   从上面的例子注意到,第一个字符为#的行为注释行。第一个非注释行指定prog由三个目标文件filea.o、fileb.o和filec.o链接生成。第三行描述了如何从prog所依赖的文件建立可执行文件。接下来的4、6行分别指定三个目标文件,以及它们所依赖的.c和.h文件以及defs文件。而5、7、9行则指定了如何从目标所依赖的文件建立目标。
  当filea.c或a.h文件在编译之后又被修改,则make工具可自动重新编译filea.o,如果在前后两次编译之间,filea.c和a.h均没有被修改,而且filea.o还存在的话,就没有必要重新编译。这种依赖关系在多源文件的程序编译中尤其重要。通过这种依赖关系的定义,make工具可避免许多不必要的编译工作。当然,利用Shell脚本也可以达到自动编译的效果,但是,Shell脚本将全部编译任何源文件,包括哪些不必要重新编译的源文件,而make工具则可根据目标上一次编译的时间和目标所依赖的源文件的更新时间而自动判断应当编译哪个源文件。   Makefile文件准备好之后,接着在Makefile文件所在的目录下敲入make这个命令就可以了,根据Makefile文件,以告诉make命令需要怎么样的去编译和链接目标程序。

Makefile的规则

  让我们先来粗略地看一看Makefile的规则。
   target ... : prerequisites ...
   command
   ...
   ...
   目标:依赖
   执行指令 ...
   target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label)。
   ① prerequisites就是,要生成那个target所需要的文件或是目标。
   ② command也就是make需要执行的命令。(任意的Shell命令)   这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行(command一定要以Tab键开始,否者编译器无法识别command),减少重复编译,提高了其软件工程管理效率。
 
 文件定义与命令
  Makefile文件作为一种描述文档一般需要包含以下内容:
   ◆ 宏定义
      ◆ 源文件之间的相互依赖关系
   ◆ 可执行的命令   Makefile中允许使用简单的宏指代源文件及其相关编译信息,在Linux中也称宏为变量。在引用宏时只需在变量前加$符号,但值得注意的是,如果变量名的长度超过一个字符,在引用时就必须加圆括号()。
 
 有效的宏引用:
  $(CFLAGS)
  $Z
  $(Z)
 其中最后两个引用是完全一致的。
需要注意的是一些宏的预定义变量,在Unix系统中,$*、$@、$?和$<四个特殊宏的值在执行命令的过程中会发生相应的变化,而在GNUmake中则定义了更多的预定义变量。关于预定义变量的详细内容,宏定义的使用可以使我们脱离那些冗长乏味的编译选项,为编写makefile文件带来很大的方便。

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

   # Define a macro for the object files
   OBJECTS= filea.o fileb.o filec.o
   # Define a macro for the library file
   LIBES= -LS
   # use macros rewrite makefile
   prog: $(OBJECTS)
   cc $(OBJECTS) $(LIBES) -o prog
   ……   
---------------------------------------------------------

  此时如果执行不带参数的make命令,将连接三个目标文件和库文件LS;但是如果在make命令后带有新的宏定义:

  make "LIBES= -LL -LS" #如何实现?
  则命令行后面的宏定义将覆盖makefile文件中的宏定义。若LL也是库文件,此时make命令将连接三个目标文件以及两个库文件LS和LL。
  在Unix系统中没有对常量NULL作出明确的定义,因此我们要定义NULL字符串时要使用下述宏定义:
  STRINGNAME= //这里有待考证
  makefile 中的变量(宏)
  GNU的make工具除提供有建立目标的基本功能之外,还有许多便于表达依赖性关系以及建立目标的命令的特色。其中之一就是变量或宏的定义能力。
如果你要以相同的编译选项同时编译十几个C源文件,而为每个目标的编译指定冗长的编译选项的话,将是非常乏味的。但利用简单的变量定义,可避免这种乏味的工作:
 # Define macros for name of compiler
  CC = gcc
  # Define a macr o for the CC flags
  CCFLAGS = -D_DEBUG -g -m486
  # A rule for building a object file
  test.o: test.c test.h
  $(CC) -c $(CCFLAGS) test.c
  在上面的例子中,CC 和 CCFLAGS 就是 make 的变量。GNUmake通常称之为变量,而其他UNIX的make工具称之为宏,实际是同一个东西。在makefile 中引用变量的值时,只需变量名之前添加 $ 符号,如上面的 $(CC) 和 $(CCFLAGS)。
  GNU make 有许多预定义的变量,这些变量具有特殊的含义,可在规则中使用。

预定义变量   含义

   $*    不包含扩展名的目标文件名称。
   $+    所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
   $<    第一个依赖文件的名称。
   $?    所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
   $@    目标的完整名称。
   $^    所有的依赖文件,以空格分开,不包含重复的依赖文件。
   $%    如果目标是归档成员,则该变量表示目标的归档成员名称。
                  例如,如果目标名称为(image.o),则$@为,而$%为image.o。
   AR    归档维护程序的名称,默认值为 ar。
   ARFLAGS   归档维护程序的选项。
   AS    汇编程序的名称,默认值为 as。
   ASFLAGS   汇编程序的选项。
   CC    C 编译器的名称,默认值为 cc。
   CFLAGS   C 编译器的选项。
   CPP    C 预编译器的名称,默认值为 $(CC) -E。
   CPPFLAGS  C 预编译的选项。
   CXX    C++ 编译器的名称,默认值为 g++。
   CXXFLAGS  C++ 编译器的选项。
   FC    FORTRAN 编译器的名称,默认值为 f77。
   FFLAGS   FORTRAN 编译器的选项。

Makefile以文件名:文件名的形式比较冒号右边的文件是不是较左边的文件有更新,如果有更新则执行下一行的程序代码。因此Makefile可以把文件关联起来

原文:

转载于:https://my.oschina.net/showcolors/blog/101103

你可能感兴趣的文章
tcpdump:理论、自动抓包及业务架构树的生成
查看>>
MySQL8.0新特性——不可见索引(Invisible Indexes)
查看>>
移动H5前端性能优化指南
查看>>
OWA简化登录设置OWA登录使用只输入用户名的方式
查看>>
部署exchange2010三合一:之四:安装exchange
查看>>
找工作之旅
查看>>
eclipse常用插件 转载
查看>>
web前端开发必读
查看>>
ucos在s3c2410上运行过程整体剖析-从main函数到UCOS初始化完毕
查看>>
Android源码下载及开发环境的搭建
查看>>
MySQL的多实例
查看>>
康哥教你如何有效管理重做日志文件
查看>>
关于c++调用rar程序压缩与解压的问题
查看>>
Spring Boot 使用 Junit
查看>>
SpringBoot 启动参数设置环境变量、JVM参数、tomcat远程调试
查看>>
JPA @Column 注解
查看>>
老毛桃U盘PE工具+veket linux配置
查看>>
APPLE G5 机箱改造“黑苹果”全攻略
查看>>
视图必须派生自 WebViewPage 或 WebViewPage
查看>>
cvsadmin
查看>>