Makefile/扩展

Makefile 文件描述了整个工程的编译、链接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后产生想要得可执行文件。

makefile带来的好处是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。而且在 Makefile 中可以使用系统 shell 所提供的任何命令来完成想要的工作。make是一个命令工具,是一个解释makefile中指令的命令工具。当我们输入make命令的时候,make命令会在当前目录下找寻名字是Makefile的文件。

准备知识

编译:高级语言-->机器指令。编译时,编译器检查高级语言的语法、函数与变量的声明是否正确。只有所有的语法正确、相关变量定义正确编译器就可以编译出中间目标文件。通常,一个高级语言的源文件都可对应一个目标文件。目标文件在Linux 中默认后缀为“.o”(如“foo.c”的目标文件为“foo.o”)

链接:.o 文件库文件链接成为可被操作系统执行的可执行程序(Linux 环境下,可执行文件的格式为“ELF”格式)。链接器不检查函数所在的源文件,只检查所有.o 文件中的定义的符号。将.o 文件中使用的函数和其它.o 或者库文件中的相关符号进行合并,对所有文件中的符号进行重新安排(重定位),并链接系统相关文件(程序启动文件等)最终生成可执行程序。链接过程使用 GNU 的“ld”工具。

静态库:又称为文档文件(Archive File)。它是多个.o 文件的集合。Linux 中静态库文件的后缀为“.a”。静态库中的各个成员(.o 文件)没有特殊的存在格式,仅仅是一个.o 文件的集合。使用“ar”工具维护和管理静态库。

共享库:也是多个.o 文件的集合,但是这些.o 文件时有编译器按照一种特殊的方式生成(Linux 中,共享库文件格式通常为“ELF”格式。共享库已经具备了可执行条件)。模块中各个成员的地址(变量引用和函数调用)都是相对地址。使用此共享库的程序在运行时,共享库被动态加载到内存并和主程序在内存中进行连接。多个可执行程序可共享库文件的代码段(多个程序可以共享的使用库中的某一个模块,共享代码,不共享数据)。另外共享库的成员对象可被执行(由 libdl.so 提供支持)

GNU make

在 shell 下执行“make”。make 会自动根据修改情况完成源文件的对应.o 文件的更新、库文件的更新、最终的可执行程序的更新。make 通过比较对应文件(规则的目标和依赖)的最后修改时间,来决定哪些文件需要更新、那些文件不需要更新。对需要更新的文件 make 就执行数据库中所记录的相应命令(在 make 读取 Makefile 以后会建立一个编译过程的描述数据库。此数据库中记录了所有各个文件之间的相互关系,以及它们的关系描述)来重建它,对于不需要重建的文件 make 什么也不做。而且可以通过make的命令行选项来指定需要重新编译的文件。

当使用 make 工具进行编译时,工程中以下几种文件在执行 make 时将会被编译(重新编译):

1. 所有的源文件没有被编译过,则对各个 C 源文件进行编译并进行链接,生成最后的可执行程序;

2. 每一个在上次执行 make 之后修改过的 C 源代码文件在本次执行 make 时将会被重新编译;

3. 头文件在上一次执行 make 之后被修改。则所有包含此头文件的 C 源文件在本次执行 make 时将会被重新编译。

一、makefile文件格式

目标:指的是生成的目标文件名称,可以意取;

依赖:生成目标所需要的文件列表;通常一个目标依赖于一个或者多个文件

    命令:通过执行命令对依赖项操作生成目标(命令前必须加 Tab,四个空格将会报错 )。一个目标可以没有依赖而只有动作(指定的命令)。比如 Makefile 中的目标“clean”,此目标没有依赖,只有命令。它所定义的命令用来删除 make 过程产生的中间文件(进行清理工作)。

假设当前文件夹中有hello.cMakefile两个文件,当我们在终端输入make指令的时候,就会自动编译出hello.o,hello.S,hello.i及目标可执行文件hello

当不想要这些不相关的文件,想对这些文件做一些操作,我们把这样的操作叫做伪目标,标志位.PHONY:

.PHONY:这是固定格式,不能变的,但是下面的clean是自己取的名字,你随便取什么名字都可以,但是clean比较直观。

二、变量

1、内置环境变量

这里的变量其实就是一个类似宏的概念,它是替换的意思,本质上就是一个字符串,字符串如果表示一个列表的话,每一个元素以空格隔开。在makefile执行的时候,会被扩展到对应的位置。

与命令相关的变量(就是这些变量可以当作命令使用):

AR       函数库打包程序。默认命令是“ar”。

AS       汇编语言编译程序。默认命令是“as”。

CC       C语言编译程序。默认命令是“cc”。

CXX     C++语言编译程序。默认命令是“g++”。

CPP     C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。

GET     从SCCS文件中扩展文件的程序。默认命令是“get”。

RM      删除文件命令。默认命令是“rm –f”。

关于命令参数可以使用的变量:

ARFLAGS     函数库打包程序AR命令的参数。默认值是“rv”。

ASFLAGS      汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。

CFLAGS        C语言编译器参数。-g  -O0

CXXFLAGS    C++语言编译器参数。

COFLAGS     RCS命令参数。

CPPFLAGS    C预处理器参数。( C 和 Fortran 编译器也会用到)。

FFLAGS     Fortran语言编译器参数。

GFLAGS     SCCS “get”程序参数。

LDFLAGS   链接器参数。(如:“ld”)

LFLAGS      Lex文法分析器参数。

PFLAGS      Pascal语言编译器参数。

RFLAGS      Ratfor 程序的Fortran 编译器参数。

YFLAGS      Yacc文法分析器参数。

2.自动化变量

3、普通变量

“objects”、“OBJECTS”、“objs”、“OBJS”、“obj”或者“OBJ”:

所有的.o 文件的列表的替代,在使用到这些文件列表的地方,使用$(objects)来代替。

4.命名包变量:多行定义一个命令块

5.变量的赋值:

=     看完了所有变量,然后根据变量的最终的值,来进行赋值

6.变量的引用

(1)通过$()

(2)通过$$var

因为在makefile中 $ 的意思是引用,如果想要在命令执行的时候就打印出 $ ,那么就需要$$,就像C语言中的 \ \ 输出 \ 一样

$(var:%.c=%.o)   将var中的所有元素,如果是以 .c结尾的,则换成 .o形式,返回转换后的结果

打印变量:

①通过warning:$(warning 提示性语句  $(变量名))

②通过error:$(error 提示性语句  $(变量名))

三、语句

ifeq( a ,  b ) - else - endif   或  ifeq  'a'   'b'  - else - endif 

ifneq( a ,  b ) - else - endif

ifdef(a) - else - endif

ifndef(a)- else - endif

在格式上,这四个关键字书写的时候前面不能有【tab】键,要顶格书写,如果有【tab】的话,会被make解析成shell命令来执行。

四、函数

这里说的都是makefile内置函数,可以直接调用执行的。

函数调用格式如下:

$( <function> <arguments> )         或者是        ${<function> <arguments>}

function 是函数名,arguments 是函数的参数,参数之间要用逗号分隔开。而参数和函数名之间使用空格分开。调用函数的时候要使用字符“$”,后面可以跟小括号也可以使用花括号。

1.字符串处理函数

字符串替代函数:函数功能是查找 text 中的单词是否符合模式 pattern,如果匹配的话,则用 replacement 替换。返回值为替换后的新字符串。

$(patsubst<pattern>,<replacement>,<text>)

例:   $(subst <from>,<to>,<text>)

函数说明:函数的功能是把字符串中的 form 替换成 to,返回值为替换后的新字符串。

对于上面这俩函数,可以看到都有substitute string,即替代字符串,不同的是,有一个加了pattern ,也就是上一个函数可以使用通配符匹配,比较高端。

去空格函数:函数的功能是去掉字符串的开头和结尾的字符串,并且将其中的多个连续的空格合并成为一个空格。返回值为去掉空格后的字符串。

$(strip<string>)

查找字符串函数:函数的功能是查找 in 中的 find ,如果我们查找的目标字符串存在。返回值为目标字符串,如果不存在就返回空。

$(findstring<find>,<in>)

过滤函数:函数的功能是过滤出 text 中符合模式 pattern 的字符串,可以有多个 pattern (用空格隔开)。返回值为滤到的字符串。

$(filter<pattern>,<text>)

反过滤函数:函数的功能是功能和 filter 函数正好相反,但是用法相同。去除符合模式 pattern 的字符串,保留符合的字符串。返回值是保留的字符串。

$(filter-out <pattern>,<text>)

排序函数:函数的功能是将 <list> 中的单词按首字母排序(升序)。返回值为排列后的字符串。【注:sort会去除重复的字符串】

$(sort <list>)

去单词函数:函数的功能是取出函数 <text> 中的第n个单词。返回值为我们取出的第 n 个单词

$(word <n>,<text>)

2.文件名操作函数

取目录函数:函数的功能是从文件名序列 names 中取出目录部分,如果 names 中没有 “/” ,取出的值为 “./” 。返回值为目录部分,指的是最后一个反斜杠之前的部分。如果没有反斜杠将返回“./”。

$(dir <names>)

取文件函数:函数的功能是从文件名序列 names 中取出非目录的部分。非目录的部分是最后一个反斜杠之后的部分。返回值为文件非目录的部分。

$(notdir<names>)

取后缀名函数:函数的功能是从文件名序列中 names 中取出各个文件的后缀名。返回值为文件名序列 names 中的后缀序列,如果文件没有后缀名,则返回空字符串。

$(suffix<names>)

取前缀函数:函数的功能是从文件名序列 names 中取出各个文件名的前缀部分。返回值为被取出来的文件的前缀名,如果文件没有前缀名则返回空的字符串。

$(basename<names>)

添加后缀名函数:函数的功能是把后缀 suffix 加到 names 中的每个单词后面。返回值为添加上后缀的文件名序列

$(addsuffix<suffix>,<names>)

添加前缀名函数:函数的功能是把前缀 prefix 加到 names 中的每个单词的前面。返回值为添加上前缀的文件名序列。

$(addprefix <prefix>,<names>)

链接函数:函数功能是把 list2 中的单词对应的拼接到 list1 的后面。如果 list1 的单词要比 list2的多,那么,list1 中多出来的单词将保持原样,如果 list1 中的单词要比 list2 中的单词少,那么 list2 中多出来的单词将保持原样。返回值为拼接好的字符串。

$(join <list1>,<list2>)

获取匹配模式文件名函数:函数的功能是列出当前目录下所有符合模式的 PATTERN 格式的文件名。返回值为空格分隔并且存在当前目录下的所有符合模式 PATTERN 的文件名。

$(wildcard PATTERN)

真正的makefile其实很少涉及到具体的名字啥的,一般都是从wildcard入手,获取当前目录下的文件,然后再用其他的文件名操作函数,可以看到,上面的8个函数,说是文件名操作函数,其实就是本质上处理字符串而已,只有wildcard函数是真正的去当前目录下去获取当前目录下符合pattern的文件名。

3.其他常用函数

foreach函数:把参数<list>中的单词逐一取出放到参数 <var> 所指定的变量中,然后再执行<text>所包含的表达式。每一次 <text> 会返回一个字符串,循环过程中,<text> 所返回的每个字符串会以空格分割,最后当整个循环结束的时候,<text> 所返回的每个字符串所组成的整个字符串(以空格分隔)将会是 foreach 函数的返回值。所以<var>最好是一个变量名,<list> 可以是一个表达式,而<text>中一般会只用 <var>这个参数来一次枚举<list>中的单词。【注意:这里的var是一个局部变量,函数结束之后,var变量会消失】

$(foreach <var>,<list>,<text>)

if函数:if 函数可以包含else部分,或者是不包含,即if函数的参数可以是两个,也可以是三个。

$(if <condition>,<then-part>)或(if<condition>,<then-part>,<else-part>)

call函数:call 函数是唯一 一个可以调用参数化表达式的函数。我们可以用来写一个非常复杂的表达式,这个表达式中,我们可以定义很多的参数,然后你可以用 call 函数来向这个表达式传递参数。当 make 执行这个函数的时候,expression参数中的变量$(1)、$(2)、$(3)等,会被参数parm1,parm2,parm3依次取代。而expression的返回值就是 call 函数的返回值。

$(call <expression>,<parm1>,<parm2>,<parm3>,...)

origin函数:origin 函数不像其他的函数,它并不操作变量的值,它只是告诉你这个变量是哪里来的。【注意: variable 是变量的名字,不应该是引用,所以最好不要在 variable 中使用“$”字符。origin 函数会员其返回值来告诉你这个变量的“出生情况”。】

$(origin <variable>)

shell函数:shell函数把执行操作系统命令后的输出作为函数返回。

$(shell <command>)

注意: 这个函数会新生成一个Shell程序来执行命令,所以你要注意其运行性能,如果你的Makefile中有一些比较复杂的规则,并大量使用了这个函数,那么对于你的系统性能是有害的。特别是Makefile的隐晦的规则可能会让你的shell函数执行的次数比你想像的多得多。

五、通配符   *   %

*是去系统中匹配,%是仅在makefile中匹配的:

凡是要到系统中去匹配的,就得用 * ;%通配符仅限在makefile文件中用来匹配规则而已,也就是%匹配的东西(可以看成字符串)在makefile(可以看成普通文档)中是可以找到的,而 * 匹配的东西,就需要跳出makefile去系统中匹配对应的文件之类的东西。

1.在shell命令中可以使用*,因为shell命令是连接系统的,shell中使用*,就是匹配系统中的文件

2.在依赖的时候可以使用*,如:

因为,test,作为target,需要找它的依赖,这个找依赖的过程,makefile是做不到的,makefile只能说去决定如何编译依赖,找依赖,需要到系统中去找,所以需要用*。

3.如果依赖存在,那么在makefile中决定如何编译依赖,就可以使用%通配符

这时候,我们已经人为规定了test需要这两个依赖,但是这两个依赖,如何编译,需要在makefile中进行寻找,所以就需要%通配符,来匹配下面的规则。

4.在wildcard中使用*,因为wildcard需要连接系统,获取当前目录下的文件名字,所以需要使用shell中的通配符*

六、源文件搜索路径

源文件搜索路径,是我们在编译的时候,如果工程量巨大,源文件不都在当前目录下,存放于其他目录下,那么VPATH或者vpath就派上了用场,用来指定找寻不在当前目录下的源文件的目录

VPATH 和 vpath 的区别:VPATH 是变量,更具体的说是环境变量,Makefile 中的一种特殊变量,使用时需要指定文件的路径;vpath 是关键字,按照模式搜索,也可以说成是选择搜索。搜索的时候不仅需要加上文件的路径,还需要加上相应限制的条件。

通俗点说,就是VPATH是一个不具有筛选条件的指定路径方法,如果缺失了一个文件,makefile会去VPATH中的所有目录中挨个寻找对比,效率低。而vpath带了模式搜索,可以选择性的指定哪种类型的文件去哪个目录下寻找,比较方便

注意:无论定义了多少路径,make 执行的时候会先搜索当前路径下的文件,当前目录下没有我们要找的文件,才去 VPATH 的路径中去寻找。如果当前目录下有我们要使用的文件,那么 make 就会使用我们当前目录下的文件。

七、包含makefile文件include

include就相当于C语言中的#include,当make读取到当前makefile中的include关键字的时候,会暂停读取当前的makefile,进而转去读取include中包含的makefile文件,读取包含的makefile文件之后,再回来继续读取当前的makefile文件。

注意:“include” 关键字所在的行首可以包含一个或者是多个的空格(读取的时候空格会被自动的忽略),但是不能使用 Tab 开始,否则会把 “include” 当作式命令来处理。包含的多个文件之间要使用空格分隔开。使用 “include” 包含进来的 Makefile 文件中,如果存在函数或者是变量的引用,它们会在包含的 Makefile 中展开。

说白了,就是原封不动的将被包含的makefile文件展开在当前makefile文件中包含被包含文件的位置。

八、调用其他makefile

当生成target目标对象时,会执行$(MAKE) -C $(SUBDIR)这条命令,进入目录SUBDIR,该目录下有一个Makefile,并执行。其中,$(MAKE) 指make预定义的变量,一般指的就是make,无需修改,可通过make -p查看make所有的预定义的变量。当然,也可直接指明为make,即make -C $(SUBDIR)。其中-C表示改变当前目录,make的命令选项可通过make -h查看。(make维护了一个变量CURDIR,代表make的工作目录,当使用-C选项修改工作目录的时候,此变量会被重新赋值)

注意: 当Makefile内嵌shell脚本时,Makefile中每一行的shell脚本需要一个shell进程来执行,不同行之间变量值不能传递。所以,Makefile中的shell不管多长也要写在一行。因此,多行的shell需要在Makefile使用反斜杠“\”连接为一行。此时,shell脚本中的一条语句后需要添加分号分隔。

注意: Makefile中对一些简单变量的引用,可以不使用”()”和”{}”来标记变量名,而直接使用$x的格式来实现,此种用法仅限于变量名为单字符的情况。另外自动化变量也使用这种格式。对于一般多字符变量的引用必须使用括号,否则make将把变量名的首字母作为作为变量而不是整个字符串($PATH在Makefile中实际上是$(P)ATH)。

1.变量传递

makefile中的变量传递,当makefile嵌套执行的时候,可以使用:

将指定变量传递给下层makefile,如果不需要传了,可以使用:

九、伪目标

所谓的伪目标可以这样来理解,它并不会创建目标文件,只是想去执行这个目标下面的命令。伪目标的存在可以帮助我们找到命令并执行。

先来看下面指令:

其实这么写是不对的,第一是影响效率,第二是有些情况下,shell命令不会被执行。

规则中 rm 命令不是创建target目标 clean 的命令,而是执行删除任务,删除当前目录下的所有的 .o 结尾和文件名为 ftp的文件。当工作目录下不存在以 clean 为名字的文件时,在 shell 中输入 make clean 命令,命令 rm 总会被执行 ,这也是我们期望的结果。

如果当前目录下存在文件名为 clean 的文件时情况就会不一样了,当我们在 shell 中执行命令 make clean,由于这个规则没有依赖文件,所以目标被认为是最新的而不去执行规则所定义的命令,因此命令 rm 将不会被执行。

将一个目标声明称伪目标的方法是将它作为特殊的目标.PHONY的依赖:

这样 clean 就被声明成一个伪目标,无论当前目录下是否存在 clean 这个文件,当我们执行 make clean 后 rm 都会被执行。而且当一个目标被声明为伪目标之后,make 在执行此规则时不会去试图去查找隐含的关系去创建它。这样同样提高了 make 的执行效率,同时也不用担心目标和文件名重名而使我们的编译失败。

十、隐含规则

隐含规则简要理解就是:正常的规则是三要素一个都不能少,就是目标、依赖、命令一个都少不了,如果少了,就不能正确运行,但是由于隐含规则的存在,可以自动补全,自动利用隐含规则推导,补充上缺失的部分。

注:隐含条件只能省略中间目标文件重建的命令和规则,但是最终目标的命令和规则不能省略。

可以联想到,如果没有显式指出命令的话,会推导命令,但是命令就真的凭空产生吗?不是的,还记得说变量的时候,第一个就说的是默认得隐含变量,这些推到出来的就会用这些默认变量来生成命令。

这里我们没有写生成main.o和common.o的规则,但是照样可以正常编译链接,然后运行。这就是隐含规则的作用。

隐含规则的具体的工作流程:make 执行过程中遇到没有提供显式规则的中间目标文件,则根据其后缀 .o 找到隐含规则,隐含规则提供了此中间目标的基本依赖关系。确定中间目标的依赖文件和重建中间目标需要使用的命令行。隐含规则所提供的依赖文件只是一个基本的依赖关系(在C语言中,通常他们之间的对应关系是:test.o 对应的是 test.c 文件)。如果需要增加其他的自定义的文件作为依赖,则需要 在Makefile 中使用没有命令行的规则给出。

十一、其他技巧

1.不输出回显指令:@

2.定义string类型为空:先定义一个空变量,然后后面采用“#”注释符来表示变量定义的终止,这样,我们可以定义出其值是一个空格的变量。

注释符”#“才是一个变量定义的结束。如果注释符之前有空格的话,那些空格也会算到所定义的变量之中。


扩展 SQL


一、扩展的构建基础设施

PGXS构建基础设施:简单的扩展模块能够在一个已经安装的服务器上简单地编译。PGXS主要是为了包括 C 代码的扩展而设计,不过它也能用于纯 SQL 的扩展。注意PGXS并不想成为一种用于构建任何与PostgreSQL交互的软件的通用构建系统框架。它只是简单地把简单服务器扩展模块的公共构建规则自动化。对于更复杂的包,你可能需要编写你自己的构建系统。

要把PGXS基础设施用于扩展,必须编写一个简单的 makefile。在这个 makefile 中,你需要设置一些变量并且把它们包括在全局的PGXS makefile 中。

最后三行应该总是相同的。在这个文件的前面部分,你要对变量赋值或者增加自定义的make规则。

设置这三个变量之一来指定要构建什么:

1.MODULES:要从源文件构建的具有相同词干的共享库对象的列表(不要在这个列表中包括库后缀)

2.MODULE_big:一个要从多个源文件中构建的共享库(在OBJS中列出对象文件)

3.PROGRAM:一个要构建的可执行程序(在OBJS中列出对象文件)

还可以设置以下变量:

EXTENSION:扩展名称;你必须为每一个名称提供一个extension.control文件,它将被安装到prefix/share/extension中

MODULEDIR:subdirectory of prefix/share的子目录,DATA 和 DOCS 文件会被安装到其中(如果没有设置,设置了EXTENSION时默认为extension,没有设置EXTENSION时默认为contrib)

DATA:要安装到prefix/share/$MODULEDIR中的随机文件

DATA_built:要安装到prefix/share/$MODULEDIR中的随机文件,它们需要先被构建

DATA_TSEARCH:要安装到prefix/share/tsearch_data中的随机文件

DOCS:要安装到prefix/doc/$MODULEDIR中的随机文件

HEADERS:要(构建并且)安装在prefix/include/server/$MODULEDIR/$MODULE_big下面的文件

HEADERS_built:和DATA_built不同,HEADERS_built中的文件不会被clean目标移除,如果想要移除它们,把它们也加入到EXTRA_CLEAN或者增加自己的规则来做这件事。

HEADERS_$MODULE:要安装(如果指定了构建则在构建之后安装)在prefix/include/server/$MODULEDIR/$MODULE之下的文件,这里$MODULE必须是一个在MODULES or MODULE_big中用到的模块名。

HEADERS_built_$MODULE:和DATA_built不同,HEADERS_built_$MODULE中的文件不会被clean目标移除,如果想要移除它们,把它们也加入到EXTRA_CLEAN或者增加自己的规则来做这件事。可以为同一个模块同时使用这两个变量或者两者的任意组合,除非你在MODULES列表中有两个模块名称仅有前缀built_上的区别,因为那样会导致歧义。在那种情况下(还好不太可能),应该仅使用HEADERS_built_$MODULE变量。

SCRIPTS:要安装到prefix/bin中的脚本文件(非二进制)

SCRIPTS_built:要安装到prefix/bin中的脚本文件(非二进制),它们需要先被构建

REGRESS:回归测试案例(不带后缀)的列表,见下文

REGRESS_OPTS:要传递给pg_regress的附加开关

ISOLATION:隔离测试用例列表,请参阅下文了解更多详细信息。

ISOLATION_OPTS:要传递给pg_isolation_regress的附加开关

TAP_TESTS:是否需要运行 TAP 测试的开关定义,请参阅下文

NO_INSTALLCHECK:不定义installcheck目标,如果测试要求特殊的配置就会很有用,或者不使用pg_regress

EXTRA_CLEAN:要在make clean中移除的额外文件

PG_CPPFLAGS:将被加到CPPFLAGS前面

PG_CFLAGS:将被加到CFLAGS后面

PG_CXXFLAGS:将被加到CXXFLAGS后面

PG_LDFLAGS:将被加到LDFLAGS前面

PG_LIBS:将被加到PROGRAM链接行

SHLIB_LINK:将被加到MODULE_big链接行

PG_CONFIG:要在其中构建的PostgreSQL安装的pg_config程序的路径(通常只用在你的PATH中的第一个pg_config)

把这个 makefile 作为Makefile放在保存你扩展的目录中。然后你可以执行make进行编译,并且接着make install来安装你的模块。默认情况下,该模块会为在你的PATH中找到的第一个pg_config程序所对应的PostgreSQL安装编译和安装。你可以通过在 makefile 中或者make命令行中设置PG_CONFIG指向另一个pg_config程序来使用一个不同的安装。

如果你想保持编译目录独立,你也可以在你的扩展所属的源代码树之外的目录中运行 make。 这个过程也被称为一个 VPATH 编译。下面是做法:

mkdir build_dir

cd build_dir

make -f /path/to/extension/source/tree/Makefile

make -f /path/to/extension/source/tree/Makefile install

此外,你可以以对核心代码所作的方式一样为 VPATH 设置一个目录。一种方式是使用核心脚本 config/prep_buildtree。一旦这样做,你可以这样设置 make变量VPATH:

make VPATH=/path/to/extension/source/tree

make VPATH=/path/to/extension/source/tree install

这个过程可以在很多种目录布局下工作。

列举在REGRESS变量中的脚本会被用来对你的扩展进行回归测试,回归测试可以在做完make install之后用make installcheck调用。要让这能够工作,你必须已经有一个运行着的PostgreSQL服务器。列举在REGRESS中的脚本文件必须在你扩展目录的名为sql/的子目录中出现。这些文件必须带有扩展.sql,但扩展不能被包括在 makefile 的REGRESS列表中。对每一个测试还应该在名为expected/的子目录中有一个包含预期输出的文件,它具有和脚本文件相同的词干并带有扩展.out。make installcheck会用psql执行每一个测试脚本,并且将得到结果输出与相应的预期输出比较。任何区别都将以diff -c格式写入到文件regression.diffs中。注意尝试运行一个不带预期文件的测试将被报告为“故障”,因此确保你拥有所有的预期文件。

ISOLATION变量中列出的脚本用于测试强调与模块并发会话的行为,可以在make install之后通过make installcheck 调用。 要实现这个工作,你必须有一个正在运行的PostgreSQL服务器。 ISOLATION中列出的脚本文件必须显示在扩展名目录中名为 specs/的子目录中。 这些文件必须具备扩展名.spec,并且不得包含在 makefile 中的ISOLATION列表中。 对于每个测试,在名为expected/的子目录中还应该有一个包含预期输出的文件,并且具有相同的词干和扩展名 .out。 make installcheck执行每个测试脚本,并将结果输出与匹配的预期文件进行比较。 任何差异都将以diff -c的格式写入到output_iso/regression.diffs文件中。 请注意,尝试运行缺少其预期文件的测试将会报告“trouble”,因此请确保你具有全部的预期文件。

TAP_TESTS 启用TAP测试. 每个运行中的数据都存在于名为 tmp_check/的子目录中。

无法给orafce打断点



ifeq($(strip $(foreach v,clean check,$(findstring $(v),$(MAKECMDGOALS)))),)

不等于make clean|check的进入判断

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 一.编译&链接 1.编译: 1)每个源文件都对应于一个中间目标文件(O文件或是OBJ文件); 2)编译器只检测程序...
    Brlat阅读 628评论 0 0
  • 隐含规则 在我们使用Makefile时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的...
    Stan_Z阅读 393评论 0 0
  • 序 什么是Makefile?如果你是熟练运用各大集成开发环境的程序猿可能对这个不是太了解,因为Makefile的工...
    云华兄阅读 2,916评论 0 4
  • Makefile学习笔记 学习Makefile的资料 《跟我一起写makefile》 《GUN make manu...
    crazybaoli阅读 2,950评论 0 4
  • 一.makefile格式 1.makefile 文件一般命名 为makefile 即可,放在目录下面,直接调出 t...
    浩林Leon阅读 7,728评论 0 2