深入Linux(四): Makefile知识点

Makefile

目录

备忘

  • Makefile官方教程(英文)
  • 一个makefile教程网址
  • 一步编译链接 gcc -o hello hello.c 或者 gcc hello.c -o hello . (理解了getopts就明白为什么可以这么写)。 这里的一步编译链接等价于后续的-c -o两个步骤,即gcc -c hello.cgcc -o hello hello.o(或者写成 gcc hello.o -o hello也可以), 推荐使用高亮的一步编译或两步编译命令
我们用gcc编译程序时,可能会用到“-I”(大写i),“-L”(大写l),“-l”(小写l)等参数,下面做个记录:例:
gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld

上面这句表示在编译hello.c时:

-I /home/hello/include表示将/home/hello/include目录作为第一个寻找头文件的目录,寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include

-L /home/hello/lib表示将/home/hello/lib目录作为第一个寻找库文件的目录,寻找的顺序是:/home/hello/lib-->/lib-->/usr/lib-->/usr/local/lib

-lworld表示在上面的lib的路径中寻找libworld.so动态库文件或libworld.a静态库文件(如果两者都有,则链接器会优先链接动态库, 如果gcc编译选项中加入了“-static”表只寻找libworld.a静态库文件)
  • makefile例子 见mk_example.mk

Makefile基础

  • 语法格式如下:
TARGETS : PREREQUISITES
【TAB】 COMMAND
         ...     # 在执行TRAGETS后面的COMMAND之前必须提前构建依赖项PREREQUISITES

Makefile中的命令

  • 必须要以[Tab]键开始,如上一条例子中的 cc -c kbd. c 就必须以Tab键开头
  • 如果make执行的命令前面加了@字符,则不显示命令本身而只显示它的结果
  • 通常make执行的命令如果出错(该命令的退出状态非0)就立刻终止,不再执行后续命令,但如果命令前面加了-号,即使这条命令出错,make也会继续执行后续命令
  • 在 Makefile 中书写在同一行中的多个命令属于一个完整的 shell 命令行,书写在独立行的一条命令是一个独立的 shell 命令行。因此:在一个规则的命令中,命令行“ cd”改变目录不会对其后的命令的执行产生影响。就是说其后的命令执行的工作目录不会是之前使用“cd”进入的那个目录。如果要实现这个目的, 就不能把“cd”和其后的命令放在两行来书写。而应该把这两条命令写在一行上,用分号分隔。这样它们才是一个完整的 shell 命令行
  • make的命令行选项
    • -k: 它的作用是让make命令在发现错误时仍然继续执行, 而不是在检测到第一个错误时就停下来。 你可以利用这个选项在一次操作中发现所有未编译成功的源文件。
    • -n: 它的作用是让make命令输出将要执行的操作步骤, 而不真正执行这些操作。
    • -f : 它的作用是告诉make命令将哪个文件作为makefile文件
    • 其它命令行选项详见gnu_make第九章

make 的执行过程

  1. 依次读取变量“ MAKEFILES”定义的 makefile 文件列表
  2. 读取工作目录下的 makefile 文件(根据命名的查找顺序“ GNUmakefile”, “ makefile”,“ Makefile”,首先找到哪个就读取哪个) 可以通过 -f 来指定哪3. 个文件作为makefile文件
  3. 依次读取工作目录 makefile 文件中使用指示符“ include”包含的文件
  4. 查找重建所有已读取的 makefile 文件的规则(如果存在一个目标是当前读取的某一个makefile 文件,则执行此规则重建此 makefile 文件,完成以后从第一步 开始重新执行)
  5. 初始化变量值并展开那些需要立即展开的变量和函数并根据预设条件确定执行分支
  6. 根据“终极目标”以及其他目标的依赖关系建立依赖关系链表
  7. 执行除“终极目标”以外的所有的目标的规则(规则中如果依赖文件中任一个文件的时间戳比目标文件新,则使用规则所定义的命令重建目标文件)
  8. 执行“终极目标”所在的规则

多目标

  • 一个规则中可以有多个目标,规则所定义的命令对所有的目标有效。一个具有多目标的规则相当于多个规则。规则的命令对不同的目标的执行效果不同,因为在规则的命令中可能使用了自动环变量“ $@”。多目标规则意味着所有的目标具有相同的依赖文件
  • a b : c d 等价于 a : c d 和 b : c d
bigoutput littleoutput : text.g
    generate text.g -$(subst output,,$@) > $@
#等价于:
bigoutput : text.g
    generate text.g -big > bigoutput
littleoutput : text.g
    generate text.g -little > littleoutput

静态规则

  • 静态规则是为了生成依赖文件的,静态模式规则的基本语法:
TARGETS ...: TARGET-PATTERN: PREREQ-PATTERNS ...
        COMMANDS       “ TAGET-PATTERN”和“ PREREQ-PATTERNS”说明了如何为每一个符合 TARGET-PATTERN的目标文件(目标“ foo.o”符合模式“ %.o”,
其“茎”为“ foo”。而目标“ foo.c”和“ foo.out”就不符合此目标模式)生成依赖文件。从目标模式( TAGET-PATTERN)的目标名字中抽取一部分字符串(称为“茎”)。
使用“茎”替代依赖模式( PREREQ-PATTERNS)中的相应部分来产生对应目标的依赖文件

在这里插入图片描述

等价于

在这里插入图片描述

  • files = foo.elc bar.o lose.o $(filter %.o,$(files))的结果为“ bar.o lose.o”,“ filter”函数过滤不符合“ %.o”模式的文件名而返回所有符合此模式的文件列表

模式规则

#模式规则语法为
%.o : %.c 
    COMMAND...  #文件名中的模式字符“ %”可以匹配任何非空字符串
# 这个模式规则指定了如何由文件“ N.c”来创建文件“ N.o”,文件“ N.c”应该是已存在的或者可被创建的
  • 模式规则在Makefile中的顺序需要注意,当一个目标文件同时符合多个目标模式时, make将会把第一个目标匹配的模式规则作为重建它的规则
  • 同样一个模式规则可以存在多个目标。多目标的模式规则和普通多目标规则有些不同,普通多目标规则的处理是将每一个目标作为一个独立的规则来处理,所以多个目标就就对应多个独立的规则(这些规则各自有自己的命令行,各个规则的命令行可能相同)。但对于多目标模式规则来说,所有规则的目标共同拥有依赖文件和规则的命令行,当文件符合多个目标模式中的任何一个时,规则定义的命令就有可能将会执行;因为多个目标共同拥有规则的命令行,因此一次命令执行之后,规则不会再去检查是否需要重建符合其它模式的目标。看一个例子:
    #sample Makefile
    Objects = foo.o bar.o
    CFLAGS := -Wall
    %x : CFLAGS += -g
    %.o : CFLAGS += -O2
    %.o %.x : %.c
        $(CC) $(CFLAGS) $< -o $@ 
    #当在命令行中执行“ make foo.o foo.x”时,会看到只有一个文件“ foo.o”被创了,
    #同时make会提示“ foo.x”文件是最新的(其实“ foo.x”并没有被创建)。此过程明
    #了多目标的模式规则在make处理时是被作为一个整体来处理的。这是多目标模式规则
    #和多目标的普通规则的区别之处
    

后缀规则

  • 后缀规则在目前版本 GNU make中已经被模式规则替代.c.a: ... 等价于它相当于模式规则: (%.o): %.c ...

隐含规则

  • 只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是makefile再也不用写得这么复杂。

自动产生依赖

  • 在新版本的 make 中,推荐的方式是为每一个源文件产生一个描述其依赖关系的makefile 文件。对于一个源文件NAME.c,对应的这个 makefile 文件为“NAME.dNAME.d中描述了文件NAME.o所要依赖的所有头文件。采用这种方式,只有源文件在修改之后才会重新使用命令生成新的依赖关系描述文件NAME.o。我们可以使用如下的模式规则来自动生成每一个.c 文件对应的.d 文件:
    %.d: %.c
            $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
            sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
            rm -f $@.$$$$
    # 自动生成每一个`.c` 文件对应的`.d `文件.   一般使用模式规则自动生成依赖关系时,后面还会加上如下语句 `include $(sources:.c=.d)`, .d文件和其它的makefile文件一样, make在执行时读取并试图重建它们。其实这些.d文件也是一些可被make解析的makefile文件。需要注意的是include指示符的书写顺序,因为在这些.d文件中已经存在规则。当一个Makefile使用指示符include这些.d文件时,应该注意它应该出现在终极目标之后,以免.d文件中的规则被是Makefile的终极规则
    
  • 自动生成依赖关系清单
    • gcc -MM 例:gcc -MM main.c 2.c输出为main.o : main.c a.h 2.o : 2.c a.h
    • -M参数会把一些标准库的头文件也包含进来。-MM参数会忽略#include造成的依赖关系,不会显示标准库的头文件

清空目标文件的规则

  • 每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。这是一种“修养”一般的风格都是: clean: rm main $(objects) ,更为稳健的做法是:
    .PHONY : clean
    clean :
           -rm main $(objects)
    # .PHONY:clean (可以指定其它目标为伪目标“”)意思表示clean是一个“伪目标(无论在当前目录下是否存在“ clean”这个文件。我们输入“ make clean”之后。“ rm”命令都会被执行) ”。
    # 当然,clean的规则不要放在文件的开头,不然,这就会变成make的默认目标。不成文的规矩是——“clean从来都是放在文件的最后
    

Make的递归执行

  • 变量MAKE : 在使用 make 的递归调用时,在 Makefile 规则的命令行中应该使用变量“ MAKE”来代替直接使用“ make” , 这样当使用 make 的命令行选项“ -t”来更新目标的时间戳或者“ -n”选项打印命令时,这些选项将会被赋值给变量“ MAKEFLAGS” 被传递到下一级的 make 程序中。在下一级子目录中执行的 make,这些选项会被附加作为 make 的命令行参数来执行,和在此目录下使用“ make -t”或者“ make -n”有相同的效果。而如果使用make则在下一级目录中不会执行命令行参数,从而不能递归的执行相同的参数,详见gnu_make手册
  • export(变量传递) : 上层 make 过程要将所执行的 Makefile 中的变量传递 给子 make 过程,需要明确地指出。在 GNU make 中,实现此功能的指示符是“ export”。 当一个变量使用“ export”进行声明后,变量和它的值将被加入到当前工作的环境变量 中,以后在 make 执行的所有规则的命令都可以使用这个变量。而当没有使用指示符 “ export”对任何变量进行声明的情况下,上层 make 只将那些已经初始化的环境变量 (在执行 make 之前已经存在的环境变量)和使用命令行指定的变量(如命令“ make CFLAGS +=-g”或者“ make –e CFLAGS +=-g”)传递给子 make 程序

包含其它makefile

  • include: include FILENAMES... FILENAMES 是 shell 所支持的文件名(可以使用通配符)指示符“ include”和文件名之间、多个文件之间使用空格或者[Tab]键隔开make命令开始时,会把找寻include所指出的其它Makefile,并把其内容安置在当前的位置。就好像C/C++的#include指令一样。如果文件都没有指定绝对路径或是相对路径的话,make会在当前目录下首先寻找,如果当前目录下没有找到,那么,make还会在下面的几个目录下找:
    • 1.如果make执行时,有“-I”或“–include-dir”参数,那么make就会在这个参数所指定的目录下去寻找。
    • 2.如果目录/include(“ /usr/gnu/include”、“ /usr/local/include”和 “ /usr/include”)存在的话,make也会去找。如果最终没找到,make会出现一条致命信息。如果你想让make不理那些无法读取的文件,而继续执行,你可以在include前加一个减号“-”。如:-include其表示,无论include过程中出现什么错误,都不要报错继续执行。
  • 变量MAKEFILES: 如果在当前环境定义了一个“MAKEFILES”环境变量, make执行时首先将此变量的值作为需要读入的Makefile文件,多个文件之间使用空格分开.
  • 推荐的做法是:在需要包含其它 makefile 文件时使用指示符“ include”来实现

目录搜寻

  • 一般搜索(变量VPATH)
    • “VPATH” 变量所指定的是 Makefile 中所有文件的搜索路径,包括了规则的依赖文件和目标文件
    • 定义变量“ VPATH”时,使用空格或者冒号( :)将多个需要搜索的目录分开。 make搜索目录的顺序是按照变量“ VPATH”定义中的目录顺序进行的(当前目录永远是第一搜索目录)。例如对变量的定义如下:VPATH = src:../headers这样我们就为所有规则的依赖指定了两个搜索目录, src”和 ../headers
  • 选择性搜索(关键字vpath)
    • 通过“ VPATH”变量指定的路径在 Makefile 中对所有文件(包括目标文件)有效。当需要为不类型的文件指定不同的搜索目录时,需要使用vpath
    • vpath %.h ../headers 其含义是: Makefile 中出现的.h 文件;如果不能在当前目录下找到,则到目录“ …/headers”下寻找。注意:这里指定的路径仅限于在 Makefile 文件内容中出现的.h文件。 并不能指定源文件中包含的头文件所在的路径(在.c 源文件中所包含的头文件路径需要使用 gcc 的“ -I”选项来指定) - 通过变量“ VPATH”、或者关键字“ vpath”指定的搜索目录,对于隐含规则同样有效
  • 目录搜寻机制:make 在解析 Makefile 文件执行规则时对文件路径保存或废弃所依据的算法如下:
  1. 首先,如果规则的目标文件在 Makefile 文件所在的目录(工作目录)下不存在,那么就执行目录搜寻。
  2. 如果目录搜寻成功,在指定的目录下存在此规则的目标。那么搜索到的完整的路径名就被作为临时的目标文件被保存。
  3. 对于规则中的所有依赖文件使用相同的方法处理。
  4. 完成第三步的依赖处理后, make 程序就可以决定规则的目标是否需要重建,两种情况时后续处理如下:
  • a) 规则的目标不需要重建:当规则的目标不需要被重建时,已经存在的目标文件所在的目录不会被改变。不会在当前工作目录下重建目标文件。
  • b) 规则的目标需要重建:当规则的目标需要重建时,规则的目标文件会在工作目录下被重建,而不是在目录搜寻时所得到的目录。旧的目标文件仍在之前的目录中保存,但只有当前工作目录下的目标文件是最新的。(使用GPATH可以使得最新的目标文件仍旧在原先的目录中重建,但如果不存在目标文件,则会在工作目录下建立一个目标文件,具体用法见gnu_make手册 4.5.3节)
  • 库文件和搜索目录:Makefile 中程序链接的静态库、共享库同样也可以通过搜索目录得到,具体见gnu_make手册4.5.6节

变量

  • 一般在我们书写 Makefile 时,各部分变量引用的格式我们建议如下:
    1. make 变量( Makefile 中定义的或者是 make 的环境变量)的引用使用$(VAR)格式,无论VAR是单字符变量名还是多字符变量名。
    2. 出现在规则命令行中 shell 变量(一般为执行命令过程中的临时变量,它不属于Makefile 变量,而是一个 shell 变量)引用使用 shell 的“ $tmp”格式。
    3. 对出现在命令行中的 make 变量我们同样使用“ $(CMDVAR)”格式来引用
  • := 当前的变量不能使用后面的变量,只能使用前面已定义好了的变量,在使用“ :=”定义变量时,变量值中对其他量或者函数的引用在定义变量时被展开(对变量进行替换)。所以变量被定义后就是一个实际需要的文本串,其中不再包含任何变量的引用
    “=”
    make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
        x = foo
        y = $(x) bar
        x = xyz
    在上例中,y的值将会是 xyz bar ,而不是 foo bar 。
    
    “:=”
    “:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
        x := foo
        y := $(x) bar
        x := xyz
    在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。
    
  • ?= 先看示例:FOO ?= bar其含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语将什么也不做
  • += 追加,如果被追加值的变量之前没有定义,那么,“ +=”会自动变成“ =”
  • 定义变量的另外一种方式是使用“ define”指示符。它定义一个包含多行字符串的变量,例:
    define two-lines
    echo foo
    echo $(bar)
    endef   其相当于:two-lines = echo foo; echo $(bar) 大家应该对这个命令的执行比较熟悉。
    它把变量“two-lines”的值作为一个完整 的shell命令行来处理(是使用分号“ ;”分开的在同一行中的两个命令而不是作 为两个命令行来处理),保证了变量完整
    
  • override指示符: 对于一个在 Makefile 中使用常规方式(使用“ =”、 “ :=”或者“ define”)定义的变量,我们可以在执行 make 时通过命令行方式重新指定这个变量的值,命令行指定的值将替代出现在Makefile 中此变量的值。如果不希望命令行指定的变量值替代在 Makefile 中的变量定义,那么我们需要在Makefile 中使用指示符“ override”来对这个变量进行声明,变量在定义时使用了“ override”,则后续对它值进行追加时,也需要使用带有“ override”指示符的追加方式(即override VARIABLE += MORE TEXT )。否则对此变量值的追加不会生效
  • 变量的替换使用:格式为$(VAR:A=B)(或者${VAR:A=B}),意思是,替换变量“VAR”中所有“ A”字符结尾的字为“ B”结尾的字。“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“ A”字符不进行替换。例如: foo := a.o c.o bar := $(foo:.o=.c) 则bar的值为a.c c.c
  • prog:CFLAGS = -g 就是目标指定变量,使用目标定变量定义时,此变量被定义在某个具体目标和由它所引发的规则的目标上。而模式指定变量定义是将一个变量值指定到所有符合此模式的目标上(例%.o : CFLAGS += -O 它指定了所有.o 文件的编译选项包含“ -O”选项,不改变对其它类型文件的编译选项 ),详见gnu_make手册6.10、6.11节
  • 一些变量如CCCPPFLAG的含义见gnu_make10.3节
  • 注意事项
    • dir := /foo/bar # xxxx注释 变量“ dir”的值是/foo/bar (后面有 4 个空格),这可能并不是想要实现的。如果一个文件以它作为路径来表示$(dir)/file,那么大错特错了。为此,在书写Makefile时。推荐将注释书写在独立的行或者多行,防止出现上边例子中的意外情况,而且将注释书写在独立的行也使得Makefile清晰,便于阅读。对于特殊的定义,比如定义包含一个或者多个空格空格的变量时进行详细地说明和注释。
    • $对于Makefile文件有特殊含义,在命令行部分引用变量时写作$$ ,这里命令行指的是terminal中的命令行
常用$变量
  • $@ 当前目标文件的名字,在多目标模式规则中,它代表的是哪个触发规则被执行的目标文件名
  • $^ 所有的依赖文件
  • $< 第一个依赖文件
  • $? 当前目标所依赖的文件列表中比当前目标文件还要新的文件
  • $* 不包括后缀名的当前依赖文件的名字
  • 上述变量详细定义和更多自动化变量见gnu_make手册10.5.3节

条件判断

  • 条件语句可以根据一个变量的值来控制 make 执行或者忽略 Makefile 的特定部分。 条件语句可以是两个不同变量、或者变量和常量值的比较

在这里插入图片描述

  • ifeq ifneq ifdef ifndef 都可以有else语句,都需要加上endif , 然后是条件判断语句开头没有TAB

make的函数

  • GNU make 函数的调用格式类似于变量的引用,以$开始表示一个引用。语法格式如下:$(FUNCTION ARGUMENTS) 或者${FUNCTION ARGUMENTS} 推荐在变量引用和函数引用中统一使用圆括号 $(subst FROM,TO,TEXT) 把字串“TEXT”中的“FROM”字符替换为“TO”示例:$(subst ee,EE,feet on the street)替换“ feet on the street”中的“ ee”为“ EE”,结果得到字符串“ fEEt on the strEEt”其它函数功能查gnu_make手册
  • 用户自定义函数通过call来调用 $(call VARIABLE,PARAM,PARAM,...) 示例 1: reverse = $(2) $(1) foo = $(call reverse,a,b) 变量“foo”的值为“ba”
  • make的控制函数: $(error TEXT…)$(warning TEXT…)

多目录makefile编写

  • 方法1:文件进行分类,分为头文件、源文件、目标文件、可执行文件。也就是说通常将文件按照文件类型放在不同的目录当中,这个时候的Makefile需要统一管理这些文件,将生产的目标文件放在目标目录下,可执行文件放到可执行目录下。示例(来自网上http://www.cnblogs.com/Anker/p/3242207.html):`见Makefile1.mk` (注释:这种方法对于源文件中依赖的头文件统一通过在编译是指定“-I目录” 的方法来解决)
  • 方法2:将子目录下的文件编译成库文件(.a)放在专门的静态库目录下,然后主程序中Makefile需要依赖子目录的文件时,直接-L指定静态库目录。示例(来自http://www.latelee.org/programming-under-linux/multi-makefile-for-app.html) 见lib-test-latelee.org.tar.bz2 (Makefile中缺少-L)
  • 实用的方法1http://www.latelee.org/using-gnu-linux/multi-dir-makefile.html):`见Makefile_templet.zip` 这个博客也可参考http://www.cnblogs.com/coderkian/p/3479564.html
  • 方法三
    • 参考文件5012-DT的Makefile.zip
  • 本人归纳
    • makefile主要是针对源文件而非头文件来写,源文件所需头文件放到依赖文件中,然后源文件生成对应的.o
    • 由于链接需要,最后的目标需要所有的.c文件对应的.o文件
    • 一般项目的makefile包含两个,一个是Rules.make, 用来确定平台和相应的参数,还有一个Makefile来决定如何编译文件来获得目标

更新静态库

  • 静态库文件也称为“文档文件”,它是一些.o 文件的集合。在 Linux( Unix)中使

    用工具“ ar”对它进行维护管理。它所包含的成员( member)是若干.o 文件。

  • 静态库文件需要使用“ar”来创建和维护。当给静态库增建一个成员时(加入一个.o文件到静态库中),“ar”可直接 将需要增加的.o文件简单的追加到静态库的末尾。之后还更新库的有效符号表。这需要“ranlib”来对静态库的符号索引表进行更新。ranlib相当于ar -s, 也可用来后者来代替

  • 示例

    $(LIB):$(OBJS)
        $(AR) r $@ $(OBJS)
        $(RANLIB) $@
    

Makefile书写约定和常见错误

  • 见gnu_make手册十四、十五章

Makefile伪目标

  • .PHONY 详见gnu_make手册4.6节

常见变量参数的含义

  • CFLAGS : 执行“ CC”编译器的命令行参数(编译.c源文件的选项)。示例= -g -Os -Wall -fsigned-char -Wno-unused
  • CXXFLAGS : 执行“ g++”编译器的命令行参数(编译.cc源文件的选项)。示例= -g -Os -Wall -fsigned-char -Wno-unused
  • CC : C编译器的名称, 示例arm-hisiv100nptl-linux-gcc
  • CXX : C++编译器的名称, 示例arm-hisiv100nptl-linux-g++
  • CPP : C预编译器的名称,默认值$(CC) -E
  • CPPFLAGS : 执行C预处理器“ cc -E”的命令行参数( C 和 Fortran 编译器会用到), 预处理是C语言程序从源代码变成可执行程序的第一步,主要是C语言编译器对各种预处理命令进行处理,包括头文件的包含、宏定义的扩展、条件编译的选择等。makefile中,CPPFLAGS经常用来指定库文件路径,例 CPPFLAGS += -Inet/ipc/protocolLib/util/include
  • LDFLAGS:gcc 等编译器会用到的一些优化参数,也可以在里面指定库文件的位置。用法:LDFLAGS=-L/usr/lib LDFLAGS += -lpthread
  • LD 链接器的名字,缺省值是ld
  • AR 函数库打包程序,可创建静态库.a文档。默认是“ ar”。示例
    $(LIB):$(OBJS)
        $(AR) r $@ $(OBJS)
        $(RANLIB) $@
    
  • RM, 删除命令的名字,缺省值是rm -f
  • 更多命名约定,参见GNU_Make手册10.3.2
  • GNU的ar,ranlib和nm
  • 动态库和静态库
    • .a文件为静态库文件,它是.o文件的集合 ; .so为动态库文件
    • 静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译
    • 动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值