Обсуждение: meson: Allow disabling static libraries

Поиск
Список
Период
Сортировка

meson: Allow disabling static libraries

От
Peter Eisentraut
Дата:
This patch allows disabling the build of static libraries using the 
standard meson option -Ddefault_library=shared (defaults to "both"). 
This option would work out of the box if you use the library() function 
to build libraries, but we use shared_library() and static_library() 
separately, for reasons that are explained in 
src/interfaces/libpq/meson.build.  So now with this, the option works 
again as expected from the end user's perspective.

This approach was suggested by Tristan Partin over in the AIX thread[0], 
but I figured this could be a generally usable feature, as some 
distributions don't want to build static libraries.

For illustration and continuous testing, I disabled static libraries in 
the CI SanityCheck task.

The internal use static libraries like libpgcommon.a are still built in 
any case, but if you disable static libraries, they are not installed.

The opposite case of disabling shared libraries doesn't work at the 
moment.  I think that is much less useful, but if someone wanted to, 
they could implement it in this same framework.


[0]: 

https://www.postgresql.org/message-id/SJ4PPFB817783261597674B9814FE523944DB8EA%40SJ4PPFB81778326.namprd15.prod.outlook.com

Вложения

Re: meson: Allow disabling static libraries

От
"Tristan Partin"
Дата:
On Tue Jan 20, 2026 at 1:04 AM CST, Peter Eisentraut wrote:
> This patch allows disabling the build of static libraries using the
> standard meson option -Ddefault_library=shared (defaults to "both").
> This option would work out of the box if you use the library() function
> to build libraries, but we use shared_library() and static_library()
> separately, for reasons that are explained in
> src/interfaces/libpq/meson.build.  So now with this, the option works
> again as expected from the end user's perspective.
>
> This approach was suggested by Tristan Partin over in the AIX thread[0],
> but I figured this could be a generally usable feature, as some
> distributions don't want to build static libraries.
>
> For illustration and continuous testing, I disabled static libraries in
> the CI SanityCheck task.

Maybe a better test would be to install the build tree into a DESTDIR,
and then do a `find $DESTDIR -type f -name '*.a'` and confirm that no
static libraries were installed.

Otherwise, the patch looks good.

--
Tristan Partin
Databricks (https://databricks.com)



Re: meson: Allow disabling static libraries

От
Andres Freund
Дата:
Hi,

On 2026-01-20 08:03:58 +0100, Peter Eisentraut wrote:
> This patch allows disabling the build of static libraries using the standard
> meson option -Ddefault_library=shared (defaults to "both"). This option
> would work out of the box if you use the library() function to build
> libraries, but we use shared_library() and static_library() separately, for
> reasons that are explained in src/interfaces/libpq/meson.build.  So now with
> this, the option works again as expected from the end user's perspective.
> 
> This approach was suggested by Tristan Partin over in the AIX thread[0], but
> I figured this could be a generally usable feature, as some distributions
> don't want to build static libraries.

Makes sense to me.


> For illustration and continuous testing, I disabled static libraries in the
> CI SanityCheck task.

Hm. I guess that makes sense.


> The opposite case of disabling shared libraries doesn't work at the moment.
> I think that is much less useful, but if someone wanted to, they could
> implement it in this same framework.

I suspect there are some folks interested in that, although I don't find that
a particularly interesting thing to do personally.  It'd certainly a bit weird
to document, since it fundamentally won't work for the server...


>  ###############################################################
> @@ -3499,18 +3513,20 @@ endif
>  installed_targets = [
>    backend_targets,
>    bin_targets,
> -  libpq_st,
>    pl_targets,
>    contrib_targets,
>    nls_mo_targets,
>    ecpg_targets,
>  ]
> +if dep_static_lib.found()
> +  installed_targets += [libpq_st]
> +endif

Wonder if we ought to define installed_targets = [] earlier and allow
different meson.build files to add themselves, instead of putting knowledge
like this into a central spot.

Separately, perhaps it'd be mildly nicer to have a boolean for static libs
instead of using .found() everywhere.


Greetings,

Andres Freund



Re: meson: Allow disabling static libraries

От
Peter Eisentraut
Дата:
On 20.01.26 18:03, Andres Freund wrote:
>>   ###############################################################
>> @@ -3499,18 +3513,20 @@ endif
>>   installed_targets = [
>>     backend_targets,
>>     bin_targets,
>> -  libpq_st,
>>     pl_targets,
>>     contrib_targets,
>>     nls_mo_targets,
>>     ecpg_targets,
>>   ]
>> +if dep_static_lib.found()
>> +  installed_targets += [libpq_st]
>> +endif
> 
> Wonder if we ought to define installed_targets = [] earlier and allow
> different meson.build files to add themselves, instead of putting knowledge
> like this into a central spot.

Right.  See attached patch 0001.  This introduces a variable 
libpq_targets and populates it in the subdirectories.  This moves the 
knowledge away from the top-level meson.build.

> Separately, perhaps it'd be mildly nicer to have a boolean for static libs
> instead of using .found() everywhere.

Yeah, after playing with this a bit more, I'm not sure sure this 
disabler trick is really that good.  The idea would have been that you 
just need to add the disabler to the dependencies and everything else 
will magically work.  But the reason that you need stuff like

+if dep_static_lib.found()
+  installed_targets += [libpq_st]
+endif

is that the disabler sneaks up into other variables and dependencies and 
has weird effects.  For example, if you remove "if" around this and 
similar lines, then "meson test" breaks in highly confusing ways 
(probably because tmp_install depends on installed_targets).

So I think, since we have to have these conditionals, we might as well 
put them around the whole static_library() call.  And then we can use a 
straightforward Boolean variable, like you suggest.  See attached patch 
0003 (which is on top of 0002, so it would make more sense to view the 
diff 0001..0003).

This is also more robust because you get explicit errors for example if 
you use libpq_st or libpq_so when they are disabled, instead of 
sometimes silently doing nothing.


Вложения

Re: meson: Allow disabling static libraries

От
Tom Lane
Дата:
Peter Eisentraut <peter@eisentraut.org> writes:
> On 20.01.26 18:03, Andres Freund wrote:
>> Separately, perhaps it'd be mildly nicer to have a boolean for static libs
>> instead of using .found() everywhere.

> Yeah, after playing with this a bit more, I'm not sure sure this 
> disabler trick is really that good.  The idea would have been that you 
> just need to add the disabler to the dependencies and everything else 
> will magically work.  But the reason that you need stuff like
> +if dep_static_lib.found()
> +  installed_targets += [libpq_st]
> +endif
> is that the disabler sneaks up into other variables and dependencies and 
> has weird effects.  For example, if you remove "if" around this and 
> similar lines, then "meson test" breaks in highly confusing ways 
> (probably because tmp_install depends on installed_targets).

That seems like an excellent reason to stay away from disabler()
and use your "variant 2".  I reviewed/tested this and noted a couple
of other problems:

1. This doesn't work for AIX, because there we'll need to force
build_static_lib to false and yet we'll still want (by default anyway)
to install libpgcommon.a and friends.  In the attached I dealt with
that by breaking build_static_lib into two variables, build_static_lib
and install_internal_static_lib.

2. As written, this resulted in installing libpgcommon_srv.a and
libpgport_srv.a, whereas historically we've only installed the
frontend and shlib variants of those libraries.  I do not see a
reason to change that behavior.  I fixed it in the attached with

+        'install': install_internal_static_lib and name != '_srv',

but perhaps there's a nicer way?

I think the attached v3 is about ready to go, with perhaps two
loose ends for you to deal with:

* Do we need to document this in the SGML docs?

* Given that -Ddefault_library=static doesn't actually work and
I doubt we have any interest in ever making it work, perhaps
it would be nicer to throw an explicit 'not supported' error.
As this stands, if you try it you get
src/interfaces/libpq/meson.build:89:0: ERROR: Unknown variable "libpq_so".
which looks more like a bug than an intentionally-unsupported option.

            regards, tom lane

From ab973a6061b3c6b6b42905f5bac9da905123bd2d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 18 Feb 2026 13:22:37 -0500
Subject: [PATCH v3] meson: allow disabling building/installation of static
 libraries.

We now support the common meson option -Ddefault_library, with
values 'both' (the default), 'shared' (install only shared libraries),
and 'static' (install only static libraries).  The 'static' choice
doesn't actually work, since psql and other programs insist on linking
to the shared version of libpq, but it's there pro-forma.  It could be
built out if we really wanted, but since we have never supported the
equivalent in the autoconf build system, I think we don't want it.

With an eye to re-supporting AIX, the internal implementation
distinguishes whether to install libpgport.a and other static-only
libraries from whether to build/install the static variant of
libraries that we can build both ways.  This detail isn't exposed
as a meson option, though it could be if there's demand.

Author: Peter Eisentraut <peter@eisentraut.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/e8aa97db-872b-4087-b073-f296baae948d@eisentraut.org
---
 .cirrus.tasks.yml                          |  1 +
 meson.build                                | 38 +++++++++++++++++-----
 src/common/meson.build                     |  1 +
 src/fe_utils/meson.build                   |  4 ++-
 src/interfaces/ecpg/compatlib/meson.build  |  4 +++
 src/interfaces/ecpg/ecpglib/meson.build    |  4 +++
 src/interfaces/ecpg/pgtypeslib/meson.build |  8 +++--
 src/interfaces/libpq-oauth/meson.build     |  6 ++++
 src/interfaces/libpq/meson.build           |  6 ++++
 src/port/meson.build                       |  1 +
 10 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index 2a821593ce5..4841a204248 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -133,6 +133,7 @@ task:
       meson setup \
         --buildtype=debug \
         --auto-features=disabled \
+        -Ddefault_library=shared \
         -Dtap_tests=enabled \
         build
     EOF
diff --git a/meson.build b/meson.build
index f6d5842d852..9ce34e3ce37 100644
--- a/meson.build
+++ b/meson.build
@@ -20,6 +20,7 @@ project('postgresql',
     'warning_level=1', #-Wall equivalent
     'b_pch=false',
     'buildtype=debugoptimized', # -O2 + debug
+    'default_library=both',
     # For compatibility with the autoconf build, set a default prefix. This
     # works even on windows, where it's a drive-relative path (i.e. when on
     # d:/somepath it'll install to d:/usr/local/pgsql)
@@ -50,6 +51,31 @@ not_found_dep = dependency('', required: false)
 thread_dep = dependency('threads')
 auto_features = get_option('auto_features')

+# Declare variables to disable static or shared libraries.  This
+# makes the 'default_library' option work even though we don't use the
+# library() function but instead shared_library() and static_library()
+# separately.
+#
+# build_shared_lib/build_static_lib control building/installing the two
+# versions of libraries that we can build both versions of (e.g., libpq).
+# There are also libraries that we only build a static version of (e.g.,
+# libpgport).  These are always built, since we need them while building,
+# but they are installed only if install_internal_static_lib is true.
+#
+# Note: at present, -Ddefault_library=static doesn't actually work, because
+# psql and other programs insist on linking to the shared version of libpq.
+# This could be fixed if there was interest, but so far there is not.
+default_library_opt = get_option('default_library')
+build_shared_lib = true
+build_static_lib = true
+install_internal_static_lib = true
+if default_library_opt == 'shared'
+  build_static_lib = false
+  install_internal_static_lib = false
+elif default_library_opt == 'static'
+  build_shared_lib = false
+endif
+


 ###############################################################
@@ -3104,6 +3130,7 @@ add_project_link_arguments(ldflags, language: ['c', 'cpp'])
 # list of targets for various alias targets
 backend_targets = []
 bin_targets = []
+libpq_targets = []
 pl_targets = []
 contrib_targets = []
 testprep_targets = []
@@ -3530,20 +3557,13 @@ endif
 installed_targets = [
   backend_targets,
   bin_targets,
-  libpq_st,
+  libpq_targets,
   pl_targets,
   contrib_targets,
   nls_mo_targets,
   ecpg_targets,
 ]

-if oauth_flow_supported
-  installed_targets += [
-    libpq_oauth_so,
-    libpq_oauth_st,
-  ]
-endif
-
 # all targets that require building code
 all_built = [
   installed_targets,
@@ -3880,7 +3900,7 @@ add_test_setup('running',
 ###############################################################

 alias_target('backend', backend_targets)
-alias_target('bin', bin_targets + [libpq_st])
+alias_target('bin', bin_targets + libpq_targets)
 alias_target('pl', pl_targets)
 alias_target('contrib', contrib_targets)
 alias_target('testprep', testprep_targets)
diff --git a/src/common/meson.build b/src/common/meson.build
index b757618a9c9..4f9b8b8263d 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -192,6 +192,7 @@ foreach name, opts : pgcommon_variants
           opts.get('include_directories', []),
         ],
         'dependencies': opts['dependencies'] + [ssl],
+        'install': install_internal_static_lib and name != '_srv',
       }
     )
   pgcommon += {name: lib}
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
index a2420ea2d5c..86befca192e 100644
--- a/src/fe_utils/meson.build
+++ b/src/fe_utils/meson.build
@@ -35,5 +35,7 @@ fe_utils = static_library('libpgfeutils',
   include_directories: [postgres_inc, libpq_inc],
   c_args: host_system == 'windows' ? ['-DFD_SETSIZE=1024'] : [],
   dependencies: frontend_common_code,
-  kwargs: default_lib_args,
+  kwargs: default_lib_args + {
+            'install': install_internal_static_lib,
+          },
 )
diff --git a/src/interfaces/ecpg/compatlib/meson.build b/src/interfaces/ecpg/compatlib/meson.build
index 6cb1be73407..d578faefe1c 100644
--- a/src/interfaces/ecpg/compatlib/meson.build
+++ b/src/interfaces/ecpg/compatlib/meson.build
@@ -16,6 +16,7 @@ if host_system == 'windows'
 endif

 # see src/interfaces/libpq/meson.build
+if build_static_lib
 ecpg_compat_st = static_library('libecpg_compat',
   ecpg_compat_sources,
   include_directories: ecpg_compat_inc,
@@ -25,7 +26,9 @@ ecpg_compat_st = static_library('libecpg_compat',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_compat_st
+endif

+if build_shared_lib
 ecpg_compat_so = shared_library('libecpg_compat',
   ecpg_compat_sources + ecpg_compat_so_sources,
   include_directories: ecpg_compat_inc,
@@ -40,6 +43,7 @@ ecpg_compat_so = shared_library('libecpg_compat',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_compat_so
+endif

 pkgconfig.generate(
   name: 'libecpg_compat',
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index 889bd9efd65..81e92151945 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -25,6 +25,7 @@ if host_system == 'windows'
 endif

 # see src/interfaces/libpq/meson.build
+if build_static_lib
 ecpglib_st = static_library('libecpg',
   ecpglib_sources,
   include_directories: ecpglib_inc,
@@ -35,7 +36,9 @@ ecpglib_st = static_library('libecpg',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpglib_st
+endif

+if build_shared_lib
 ecpglib_so = shared_library('libecpg',
   ecpglib_sources + ecpglib_so_sources,
   include_directories: ecpglib_inc,
@@ -51,6 +54,7 @@ ecpglib_so = shared_library('libecpg',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpglib_so
+endif

 pkgconfig.generate(
   name: 'libecpg',
diff --git a/src/interfaces/ecpg/pgtypeslib/meson.build b/src/interfaces/ecpg/pgtypeslib/meson.build
index 6b78f529e53..241fa95e559 100644
--- a/src/interfaces/ecpg/pgtypeslib/meson.build
+++ b/src/interfaces/ecpg/pgtypeslib/meson.build
@@ -21,22 +21,25 @@ if host_system == 'windows'
 endif

 # see src/interfaces/libpq/meson.build
+if build_static_lib
 ecpg_pgtypes_st = static_library('libpgtypes',
   ecpg_pgtypes_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: frontend_stlib_code,
+  dependencies: [frontend_stlib_code],
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_pgtypes_st
+endif

+if build_shared_lib
 ecpg_pgtypes_so = shared_library('libpgtypes',
   ecpg_pgtypes_sources + ecpg_pgtypes_so_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: frontend_shlib_code,
+  dependencies: [frontend_shlib_code],
   version: '3.' + pg_version_major.to_string(),
   soversion: host_system != 'windows' ? '3' : '',
   darwin_versions: ['3', '3.' + pg_version_major.to_string()],
@@ -45,6 +48,7 @@ ecpg_pgtypes_so = shared_library('libpgtypes',
   kwargs: default_lib_args,
 )
 ecpg_targets += ecpg_pgtypes_so
+endif

 pkgconfig.generate(
   name: 'libpgtypes',
diff --git a/src/interfaces/libpq-oauth/meson.build b/src/interfaces/libpq-oauth/meson.build
index d8a0c04095a..27aca2bc324 100644
--- a/src/interfaces/libpq-oauth/meson.build
+++ b/src/interfaces/libpq-oauth/meson.build
@@ -21,6 +21,7 @@ export_file = custom_target('libpq-oauth.exports',
 # port needs to be in include path due to pthread-win32.h
 libpq_oauth_inc = include_directories('.', '../libpq', '../../port')

+if build_static_lib
 libpq_oauth_st = static_library('libpq-oauth',
   libpq_oauth_sources,
   include_directories: [libpq_oauth_inc, postgres_inc],
@@ -32,11 +33,14 @@ libpq_oauth_st = static_library('libpq-oauth',
   ],
   kwargs: default_lib_args,
 )
+libpq_targets += libpq_oauth_st
+endif

 # This is an internal module; we don't want an SONAME and therefore do not set
 # SO_MAJOR_VERSION.
 libpq_oauth_name = 'libpq-oauth-@0@'.format(pg_version_major)

+if build_shared_lib
 libpq_oauth_so = shared_module(libpq_oauth_name,
   libpq_oauth_sources + libpq_oauth_so_sources,
   include_directories: [libpq_oauth_inc, postgres_inc],
@@ -47,6 +51,8 @@ libpq_oauth_so = shared_module(libpq_oauth_name,
   link_args: export_fmt.format(export_file.full_path()),
   kwargs: default_lib_args,
 )
+libpq_targets += libpq_oauth_so
+endif

 libpq_oauth_test_deps = []

diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index c5ecd9c3a87..2b95098187e 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -57,6 +57,7 @@ libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
 # We could try to avoid building the source files twice, but it probably adds
 # more complexity than its worth (reusing object files requires also linking
 # to the library on windows or breaks precompiled headers).
+if build_static_lib
 libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
@@ -65,7 +66,10 @@ libpq_st = static_library('libpq',
   dependencies: [frontend_stlib_code, libpq_deps],
   kwargs: default_lib_args,
 )
+libpq_targets += libpq_st
+endif

+if build_shared_lib
 libpq_so = shared_library('libpq',
   libpq_sources + libpq_so_sources,
   include_directories: [libpq_inc, postgres_inc],
@@ -79,6 +83,8 @@ libpq_so = shared_library('libpq',
   link_args: export_fmt.format(export_file.full_path()),
   kwargs: default_lib_args,
 )
+libpq_targets += libpq_so
+endif

 libpq = declare_dependency(
   link_with: [libpq_so],
diff --git a/src/port/meson.build b/src/port/meson.build
index d7d4e705b89..52f9b3da631 100644
--- a/src/port/meson.build
+++ b/src/port/meson.build
@@ -192,6 +192,7 @@ foreach name, opts : pgport_variants
       c_pch: pch_c_h,
       kwargs: opts + {
         'dependencies': opts['dependencies'] + [ssl],
+        'install': install_internal_static_lib and name != '_srv',
       }
     )
   pgport += {name: lib}
--
2.43.7


Re: meson: Allow disabling static libraries

От
Peter Eisentraut
Дата:
On 18.02.26 19:39, Tom Lane wrote:
> I think the attached v3 is about ready to go, with perhaps two
> loose ends for you to deal with:
> 
> * Do we need to document this in the SGML docs?
> 
> * Given that -Ddefault_library=static doesn't actually work and
> I doubt we have any interest in ever making it work, perhaps
> it would be nicer to throw an explicit 'not supported' error.
> As this stands, if you try it you get
> src/interfaces/libpq/meson.build:89:0: ERROR: Unknown variable "libpq_so".
> which looks more like a bug than an intentionally-unsupported option.

Committed with documentation addition and an explicit error for the 
not-supported case.




Re: meson: Allow disabling static libraries

От
Tom Lane
Дата:
Peter Eisentraut <peter@eisentraut.org> writes:
> Committed with documentation addition and an explicit error for the 
> not-supported case.

Thanks!  Barring objections, I'll get on with pushing the AIX patches.

            regards, tom lane