PostgreSQL用的是autoconf和automake来管理编译的。
从这个图可以看到autoscan
,automake
,aclocal
,autoconf
,autoheader
一共5个命令工具。
- autoscan, 目测没有用到, 直接手工修改
configgure.in
- aclocal, 生成
aclocal.m4
- autoheader, 生成
src/config/pg_config.h.in
- automake, 生成
Makefile.in
- autoconf, 生成
configure
-
configure
生成config.h
和Makefile
- 最后使用make命令读取
Makefile
执行编译和安装等操作
m4
http://www.gnu.org/software/m4/m4.html
M4是一个Unix宏处理器, 用于将输入赋值到模板中并展开成输出. 可以使用简单的运算和字符串操作, 主要用于编译前的预处理. 主要是因为autoconf而使用. M4存在于各种类Unix系统中, 并且已经被POSIX(Portable Operating System Interface)标准化 .
m4中的m
应该就是macro
。
在PostgreSQL源码里的config
目录下有一堆m4文件。
aclocal
aclocal是一个perl脚本程序,它的定义是:aclocal - create aclocal.m4 by scanning configure.ac(configure.in)。
autoconf需要GNU m4宏处理器来处理aclocal.m4,以生成configure脚本。
autoconf
https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/autoconf.html
Autoconf 是一个可扩展的M4宏集合, 用于产生shell脚本来自动配置软件源码. 这些脚本可以自动适配多种类Unix的操作系统. 需要与automake, libtool合用产生可移植的软件.
configure.in
旧的项目是configure.in
, 现在新的项目都是configure.ac
了。
一般是基于 autoscan
生成的configure.scan
修改而来或者纯手工编写。
PostgreSQL的configure.in
文件说明:
dnl Process this file with autoconf to produce a configure script.
dnl configure.in
dnl
dnl Developers, please strive to achieve this order:
dnl
dnl 0. Initialization and options processing
dnl 1. Programs
dnl 2. Libraries
dnl 3. Header files
dnl 4. Types
dnl 5. Structures
dnl 6. Compiler characteristics
dnl 7. Functions, global variables
dnl 8. System services
dnl
dnl Read the Autoconf manual for details.
dnl
常用预定义宏:
基础设置
AC_INIT(PACKAGE, VERSION, BUG_REPORT_EMAIL)
AC_PREREQ(VERSION) # 最小支持的autoconf版本号
AC_CONFIG_SRCDIR(FILE) # safe check 确保configure的确是在正确的目录中被执行的
AC_CONFIG_AUX_DIR(DIR) # 辅助目录地址,存放install-sh和depcomp等辅助工具文件,若不指定会在当前目录直接创建辅助工具文件
src/template
是--with-template=
的值对应的配置模板, 一类操作系统是一个单独的文件, 如果这里没有对应系统的模板, 就用--with-template
来指定一个接近的。
Makefile
PostgreSQL使用GNUMakefile
进行编译, 但是在根目录有一个Makefile
, 这个文件的说明如下:
# The PostgreSQL make files exploit features of GNU make that other
# makes do not have. Because it is a common mistake for users to try
# to build Postgres with a different make, we have this make file
# that, as a service, will look for a GNU make and invoke it, or show
# an error message if none could be found.
就是说, 手工写这个Makefile是为了防止用户搞错, 用了其他的make来编译。
其他的make会执行Makefile
, 而这个Makefile
会重新调用GNU make
。
GNU make会先找到GNUMakefile
从而绕过这个Makefile
文件。
PostgreSQL的编译目标
- all : 包含其他所有目标
- check
- install
- installdirs
- installcheck
- installcheck-parallel
- uninstall
- clean
- distclean
- maintainer-clean
- dist
- distcheck
- world
- check-world
- install-world
- installcheck-world
GNUMakefile.in
这个文件可以用automake
生成, 也可以手工写。PostgreSQL里的这个文件看着像是手工写的。
src/Makefile.global.in
GNUMakefile.in
文件的第一步就是引入这个文件, 用于设置全局的变量。
其他文件夹下的所有Makefile
第一件事也是引入这个文件。
#------------------------------------------------------------------------------
# All PostgreSQL makefiles include this file and use the variables it sets,
# which in turn are put here by the configure script. There is no need for
# users to edit this file -- if it turns out to be necessary then that's a
# bug.
#
# A makefile that includes this file needs to set the variablesubdir
to
# the relative path from the top to itself andtop_builddir
to the relative
# path from itself to the top before including this file. (The "top" is the
# parent directory of the directory this file is in.)
#------------------------------------------------------------------------------
其他Makefile引入本文件之前,需要定义以下两个变量:
- subdir : 当前Makefile文件相对于根目录的相对路径
- top_builddir : 相对于当前Makefile文件的根路径
主要设置的变量
- 从PGXS读取PostgreSQL的信息
bindir
,datadir
,sysconfdir
,includedir
等等。 - PostgreSQL的功能特性开关:
with_*
,enable_*
,python_*
等等。 - 编译器的变量:
CC
,GCC
,LIBS
等等 - 安装最终调用的shell是
install-sh
:install_sh = $(SHELL) $(top_srcdir)/config/install-sh -c
- 生成/更新一些头文件, 譬如:
- 更新配置状态:
$(top_builddir)/config.status
$(top_builddir)/src/include/pg_config.h
$(top_builddir)/src/include/stamp-h
$(top_builddir)/src/include/pg_config_ext.h
$(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h
- 更新配置状态:
- 定义
recurse
函数,用于递归处理子目录, 它有3个参数:- $1: targets to make recursive (defaults to list of standard targets)
- $2: list of subdirs (defaults to SUBDIRS variable)
- $3: target to run in subdir (defaults to current element of $1)
函数体:
foreach target, $(if $1,$1,$(standard_targets)), foreach subdir, $(if $2,$2,$(SUBDIRS)), eval $(call _create_recursive_target,$(target),$(subdir), $(if $3,$3,$(target)))
- Native language support:
include $(top_srcdir)/src/nls-global.mk
- LLVM support
PostgreSQL的Makefile分布
基本上, 每个子目录都有一个Makefile的, 然后编译的时候, 通过./configure
读取GNUMakefile.in
生成GNUMakefile
, 然后make
读取GNUMakefile
通过递归的方式依次调用各个子目录里的这些Makefile逐个目录编译, 最终完成整个编译。
src/
backend/
access/Makefile
brin/Makefile
common/Makefile
gin/Makefile
gist/Makefile
hash/Makefile
heap/Makefile
index/Makefile --------------> 这个是索引访问方法的API
nbtree/Makefile
rmgrdesc/Makefile --------------> the rmgr descriptor routines
nbtree/Makefile
spgist/Makefile
table/Makefile --------------> 这个是表访问方法的API
tablesample/Makefile
transam/Makefile
bootstrap/Makefile --------------> routines to support running postgres in 'bootstrap' mode
catalog/Makefile
system_views.sql
information_schema.sql
Catalog.pm
sql_features.txt : sql特性支持情况
sql_feature_packages.txt : sql特性支持情况
genbki.pl : Perl script that generates postgres.bki. The BKI files are used to initialize the postgres template database.
commands/Makefile
foreign/Makefile --------------> support for foreign-data wrappers, servers and user mappings.
jit/Makefile
llvm/Makefile --------------> the LLVM JIT provider, building it into a shared library.
lib/Makefile
libpq/Makefile --------------> libpq subsystem (backend half of libpq interface)
main/Makefile
nodes/Makefile
optimizer/Makefile
geqo/Makefile --------------> the genetic query optimizer module
path/Makefile
plan/Makefile
prep/Makefile
util/Makefile
parser/Makefile
partitioning/Makefile
po/*.po --------------> simplified 某种语言 translation file for PostgreSQL server
port/Makefile --------------> 有一些.s文件,是汇编?
postmaster/Makefile
regex/Makefile
replication/Makefile
libpqwalreceiver/Makefile ---->是一个动态库, receive WAL during streaming replication
logical/Makefile
pgoutput/Makefile ---->是一个动态库, standard logical replication output plugin
rewrite/Makefile
snowball/Makefile
statistics/Makefile
storage/Makefile
buffer/Makefile
file/Makefile
freespace/Makefile
ipc/Makefile
large_object/Makefile
lmgr/Makefile
page/Makefile
smgr/Makefile
sync/Makefile
tcop/Makefile ----> 这个是什么代码??
tsearch/Makefile ----> 还有一些字典文件在这里边
utils/Makefile
adt/Makefile ----> dt应该是data type, 但是a代表什么?
cache/Makefile
error/Makefile
fmgr/Makefile
hash/Makefile
init/Makefile
mb/Makefile
misc/Makefile
mmgr/Makefile
resowner/Makefile
sort/Makefile
time/Makefile
bin/ ----------> client programs, 这下面的是一堆客户端工具命令
makefiles/
pgxs.mk -----> contrib目录下的插件需要引用它
port/Makefile
template/
test/ -------> 这个目录存放了各种各样的测试代码
timezone/
tutorial/
这些文件的结构都非常相似。
Makefile知识
call函数
call函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以用call函数来向这个表达式传递参数。其语法是:
$(call 表达式, 参数1, 参数2,...)
当make执行这个函数时,参数中的变量,如$(1),$(2),$(3)
等,会被参数,,依次取代。而返回值就是call函数的返回值。例如:
reverse = $(1) $(2)
foo = $(call reverse,a,b)
那么,foo的值就是“a b”。当然,参数的次序是可以自定义的,不一定是顺序的,如:
reverse = $(2) $(1)
foo = $(call reverse,a,b)
此时的foo的值就是“b a”。
TAS
src/backend/port/Makefile
port是对各种底层架构的适配, 其中出现了TAS, 这里科普下它是什么:
PostgreSQL中使用spinlock来对资源进行加锁。TAS lock是最简单的spinlock。当然spinlock可以用信号量来实现。但是据PostgreSQL的早期报告显示,内核提供的信号量将大大降低性能。所以学习TAS lock对我们提高软件性能是大有帮助的。
TAS就是Test And Set。它要做的就是跟一个变量进行Test。如果条件满足对其Set另外一个值,如果条件不满足,就继续等待。但是所有这些都是原子操作。
Windows提供了一个API:InterlockedCompareExchange。PostgreSQL的Windows版本就是利用它来实现TAS的。
https://blog.csdn.net/gp_community/article/details/109719815
https://www.iteye.com/blog/aoogoo-591059
参考文档:
- postgresql 编译源码时,在预编译configure中,添加配置选项
- 编写configure.ac
- configure.ac介绍