PostgreSQL开发 - 编译配置

PostgreSQL用的是autoconf和automake来管理编译的。

image

从这个图可以看到autoscan,automake,aclocal,autoconf,autoheader一共5个命令工具。

  1. autoscan, 目测没有用到, 直接手工修改configgure.in
  2. aclocal, 生成aclocal.m4
  3. autoheader, 生成src/config/pg_config.h.in
  4. automake, 生成Makefile.in
  5. autoconf, 生成configure
  6. configure生成config.hMakefile
  7. 最后使用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的编译目标

  1. all : 包含其他所有目标
  2. check
  3. install
  4. installdirs
  5. installcheck
  6. installcheck-parallel
  7. uninstall
  8. clean
  9. distclean
  10. maintainer-clean
  11. dist
  12. distcheck
  13. world
  14. check-world
  15. install-world
  16. 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 variable subdir to
# the relative path from the top to itself and top_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引入本文件之前,需要定义以下两个变量:

  1. subdir : 当前Makefile文件相对于根目录的相对路径
  2. top_builddir : 相对于当前Makefile文件的根路径

主要设置的变量

  1. 从PGXS读取PostgreSQL的信息bindir,datadir,sysconfdir,includedir等等。
  2. PostgreSQL的功能特性开关: with_*, enable_*, python_*等等。
  3. 编译器的变量: CC,GCC,LIBS等等
  4. 安装最终调用的shell是install-sh: install_sh = $(SHELL) $(top_srcdir)/config/install-sh -c
  5. 生成/更新一些头文件, 譬如:
    1. 更新配置状态: $(top_builddir)/config.status
    2. $(top_builddir)/src/include/pg_config.h
    3. $(top_builddir)/src/include/stamp-h
    4. $(top_builddir)/src/include/pg_config_ext.h
    5. $(top_builddir)/src/interfaces/ecpg/include/ecpg_config.h
  6. 定义recurse函数,用于递归处理子目录, 它有3个参数:
    1. $1: targets to make recursive (defaults to list of standard targets)
    2. $2: list of subdirs (defaults to SUBDIRS variable)
    3. $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)))
    
  7. Native language support: include $(top_srcdir)/src/nls-global.mk
  8. 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

参考文档:

  1. postgresql 编译源码时,在预编译configure中,添加配置选项
  2. 编写configure.ac
  3. configure.ac介绍

你可能感兴趣的:(PostgreSQL开发 - 编译配置)