Building PostgreSQL in a Modern Way – With Meson

Enterprise PostgreSQL Solutions

Comments are off

Building PostgreSQL in a Modern Way – With Meson

1.0 Introduction

Starting in PostgreSQL 16, we will have an option to build PostgreSQL software using a modern build system, meson, in addition to the traditional ./configure and Makefile. I started practicing meson when I was working on a community patch a few weeks ago for PostgreSQL, where I have been told to update the meson.build file in addition to the usual Makefile. This also means that if you are working on community features, you will need to consider meson in your work. Today I will share my take on how to use meson to build PostgreSQL on Ubuntu 18.04 and I hope you will find it useful.

2.0 Meson vs Makefile

Makefile

  • widely used, mature and stable
  • Makefile syntax is complex and cumbersome to edit and maintain. It can become unmanageable for very large or complex projects

Meson

  • the syntax is concise, easy to understand and write
  • Provides a fast and efficient compilation process while maintaining ease of use and flexibility

3.0 Installation

We need to install meson and ninja to get started. The version is very important, using a version too old or too new may result in error during the build process. The versions below are confirmed to work (by me):

  • meson v0.57.2 (minimum meson version recommended by PostgreSQL), github download link
  • ninja v1.10.1, github downlad link

Once you have them downloaded, you need to add meson to your PATH environment variable and put ninja in /usr/bin/ninja so the build scripts can find them

I have also tried using meson v0.57.2 with newer version of ninja and encountered error during build, so I cannot guarantee the build will work with different version combinations.

4.0 The build

Meson build is available in PostgreSQL 16, which has not been released officially so we need to be on the master PG16 development branch to use this feature. You can clone official PostgreSQL source code here.

If you have previously run ./configure and build the PostgreSQL, you will need to undo that by:

$ make maintainer-clean

If you would like to start from scratch, do:

$ git clone https://github.com/postgres/postgres.git

Now, we are ready to do a meson build. We start by setting up our build folder (within postgres folder) where all the build outputs, logs, test outputs, configurations…etc will be stored.

We can also pass special build parameters during the setup stage. These build parameters are similar to the arguments passed to the classic ./configure script. For example:

$ cd postgres
$ meson setup build --prefix=$PWD/highgo -Dcassert=true '-DPG_TEST_EXTRA=kerberos ldap' -Dbuildtype=debug

the –prefix command configures the installation prefix just like ./configure. The rest of the optional build parameters are passed to meson via -D followed by the parameter name without space.

We can view a list of possible parameters and their descriptions using this command:

$ meson configure
WARNING: The source directory instead of the build directory was specified.
WARNING: Only the default values for the project are printed, and all command line parameters are ignored.

Core properties:
  Source dir /home/caryh/postgres

Main project options:

  Core options            Default Value        Possible Values                                               Description
  ------------            -------------        ---------------                                               -----------
  ...
  buildtype               debugoptimized       [plain, debug, debugoptimized, release, minsize, custom]      Build type to use
  ...
  cassert                 false                [true, false]                                                 Enable assertion checks (for debugging)
  ...
  PG_TEST_EXTRA                                                                                              Enable selected extra tests
  ...

  ... and many more

Since we run meson configure outside the build folder, it gives you a warning that it only prints default and possible values for your build. To see the current values, we need to re-run the same command in the build folder that we have created.

$ cd build
$ meson configure
Core properties:
  Source dir /home/caryh/postgres
  Build dir  /home/caryh/postgres/build

Main project options:

  Core options        Current Value                                    Possible Values                                               Description
  ------------        -------------                                    ---------------                                               -----------
  ...
  buildtype           debug                                            [plain, debug, debugoptimized, release, minsize, custom]      Build type to use
  ...
  cassert             true                                             [true, false]                                                 Enable assertion checks (for debugging)
  ...
  PG_TEST_EXTRA       kerberos ldap                                                                                                  Enable selected extra tests

  .... and many more

If you need to change any build parameter, you can also do so here inside build folder instead of running ./configure again like we would normally do before.

$ meson configure -Dcassert=false

When we have finalized the build parameter, we can start the build and install by running these commands in build folder:

$ ninja
$ sudo ninja install

and that is it!

5.0 Run the Test Suites

We know PostgreSQL source code repository is packed with a lot of test cases to ensure the software is working. We normally would run make check or make check-world to execute the test suite for core processes, extensions and front end tools separately. In meson, all can be run at once. Simply run the following command inside build folder:

$ meson test
  1/257 postgresql:setup / tmp_install                                                     OK                8.48s
  2/257 postgresql:setup / install_test_files                                              OK                0.06s
  3/257 postgresql:pg_upgrade / pg_upgrade/001_basic                                       OK                0.18s   8 subtests passed
  4/257 postgresql:recovery / recovery/002_archiving                                       OK                3.61s   8 subtests passed
  5/257 postgresql:recovery / recovery/003_recovery_targets                                OK                6.73s   9 subtests passed
  6/257 postgresql:recovery / recovery/004_timeline_switch                                 OK                6.99s   3 subtests passed
  7/257 postgresql:recovery / recovery/005_replay_delay                                    OK                7.58s   3 subtests passed
  8/257 postgresql:recovery / recovery/006_logical_decoding                                OK                4.78s   20 subtests passed
  9/257 postgresql:recovery / recovery/001_stream_rep                                      OK               10.34s   59 subtests passed
 10/257 postgresql:recovery / recovery/007_sync_rep                                        OK                6.20s   11 subtests passed
 11/257 postgresql:recovery / recovery/010_logical_decoding_timelines                      OK                4.59s   13 subtests passed
 12/257 postgresql:recovery / recovery/013_crash_restart                                   OK                3.55s   18 subtests passed
 13/257 postgresql:recovery / recovery/014_unlogged_reinit                                 OK                3.72s   23 subtests passed
 14/257 postgresql:recovery / recovery/012_subtransactions                                 OK                6.63s   12 subtests passed
 15/257 postgresql:recovery / recovery/009_twophase                                        OK               11.63s   24 subtests passed
 16/257 postgresql:recovery / recovery/016_min_consistency                                 OK                4.34s   1 subtests passed
 17/257 postgresql:recovery / recovery/015_promotion_pages                                 OK                4.74s   1 subtests passed
 18/257 postgresql:recovery / recovery/008_fsm_truncation                                  OK               14.55s   1 subtests passed
 19/257 postgresql:recovery / recovery/017_shm                                             OK                5.23s   4 subtests passed

...
 36/257 postgresql:kerberos / kerberos/001_auth                                            ERROR             0.21s   (exit status 255 or signal 127 SIGinvalid)
...
236/257 postgresql:ldap_password_func / ldap_password_func/001_mutated_bindpasswd          ERROR             0.19s   (exit status 255 or signal 127 SIGinvalid)
...
249/257 postgresql:ldap / ldap/001_auth                                                    ERROR             0.17s   (exit status 255 or signal 127 SIGinvalid)
250/257 postgresql:ldap / ldap/002_bindpasswd                                              ERROR             0.18s   (exit status 255 or signal 127 SIGinvalid)
...


Ok:                 251
Expected Fail:      0
Fail:               4
Unexpected Pass:    0
Skipped:            2
Timeout:            0

I have 4 test cases related to ldap and kerberos because I do not have these services set up, so failure is expected. I would like to emphasize more on these extra test cases that normally don’t get run in the traditional setup unless we specify them in $PG_TEST_EXTRA environment variable. In the traditional way, to run extra tests such as ldap and kerberos, we need to do this:

$ cd src/test/ldap
$ make check PG_TEST_EXTRA=ldap

or

$ cd src/test/kerberos
$ make check PG_TEST_EXTRA=kerberos

These are not run by default because they need separate services being setup or unsafe to run. With meson, if you need to run these extra tests, the following command will not work unless you have specifically defined -DPG_TEST_EXTRA during meson setup as one of the build options.

$ export PG_TEST_EXTRA="ldap kerberos"
$ meson test

===> will skip ldap and kerberos tests if you did not do '-DPG_TEST_EXTRA=kerberos ldap' during meson setup

6.0 Conclusion

Overall, Meson offers a modern, intuitive, and efficient approach to building software projects. While Makefile remains a widely used and powerful build system, Meson offers a more streamlined and user-friendly experience, particularly for modern development workflows.