
All the required public API is annotated with SYMEXPORT, so we can just
add the meson notation, to hide all the symbols by default.
Thus we no longer spill all the internal API into the global namespace.
This is effectively a regression from the autotools build, which used
hidden and internal for DARWIN and others respectively.
The use of hidden is considered sufficient, considering:
- internal was introduced with commit 920b0d20
("Update usage of gcc
__attribute__ flags"), referencing the GCC manual and potential
optimisations, although
- the details about the optimisations or respective benefits are close
to non-existent,
- the code/data size of the binaries is identical across hidden and
internal. While the latter produces slightly larger overall binaries.
- Internal is not widely supported - missing on Darwin, the CMake build
system lacks a wrapper (unlike for hidden)
- Internal is not widely used in projects.
Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Signed-off-by: Allan McRae <allan@archlinux.org>
463 lines
15 KiB
Meson
463 lines
15 KiB
Meson
project('pacman',
|
|
'c',
|
|
version : '5.2.1',
|
|
license : 'GPLv2+',
|
|
default_options : [
|
|
'c_std=gnu99',
|
|
'prefix=/usr',
|
|
'sysconfdir=/etc',
|
|
'localstatedir=/var',
|
|
],
|
|
meson_version : '>= 0.51')
|
|
|
|
libalpm_version = '12.0.1'
|
|
|
|
cc = meson.get_compiler('c')
|
|
|
|
# commandline options
|
|
PREFIX = get_option('prefix')
|
|
DATAROOTDIR = join_paths(PREFIX, get_option('datarootdir'))
|
|
SYSCONFDIR = join_paths(PREFIX, get_option('sysconfdir'))
|
|
LOCALSTATEDIR = join_paths(PREFIX, get_option('localstatedir'))
|
|
LOCALEDIR = join_paths(PREFIX, get_option('localedir'))
|
|
ROOTDIR = get_option('root-dir')
|
|
BINDIR = join_paths(PREFIX, get_option('bindir'))
|
|
MANDIR = join_paths(PREFIX, get_option('mandir'))
|
|
BUILDSCRIPT = get_option('buildscript')
|
|
LIBMAKEPKGDIR = join_paths(PREFIX, DATAROOTDIR, 'makepkg')
|
|
PKGDATADIR = join_paths(PREFIX, DATAROOTDIR, meson.project_name())
|
|
|
|
PYTHON = import('python').find_installation('python3')
|
|
SED = find_program('sed')
|
|
DU = find_program('du')
|
|
LDCONFIG = get_option('ldconfig')
|
|
MESON_MAKE_SYMLINK = join_paths(meson.source_root(), 'build-aux/meson-make-symlink.sh')
|
|
|
|
BASH = find_program('bash4', 'bash')
|
|
if BASH.found()
|
|
bash_version = run_command(BASH, '-c', 'IFS=.; echo "${BASH_VERSINFO[*]:0:3}"').stdout()
|
|
|
|
have_bash = bash_version.version_compare('>= 4.4.0')
|
|
endif
|
|
if not have_bash
|
|
error('bash >= 4.4.0 is required for pacman scripts.')
|
|
endif
|
|
|
|
bashcompletion = dependency('bash-completion', required : false)
|
|
if bashcompletion.found()
|
|
BASHCOMPDIR = bashcompletion.get_pkgconfig_variable('completionsdir')
|
|
else
|
|
BASHCOMPDIR = join_paths(DATAROOTDIR, 'bash-completion/completions')
|
|
endif
|
|
|
|
if get_option('use-git-version')
|
|
PACKAGE_VERSION = run_command(
|
|
find_program('git'),
|
|
'describe',
|
|
'--abbrev=4',
|
|
'--dirty').stdout().strip().strip('v')
|
|
else
|
|
PACKAGE_VERSION = meson.project_version()
|
|
endif
|
|
|
|
conf = configuration_data()
|
|
conf.set('_GNU_SOURCE', true)
|
|
conf.set_quoted('PACKAGE', meson.project_name())
|
|
conf.set_quoted('PACKAGE_VERSION', PACKAGE_VERSION)
|
|
conf.set_quoted('LOCALEDIR', LOCALEDIR)
|
|
conf.set_quoted('SCRIPTLET_SHELL', get_option('scriptlet-shell'))
|
|
conf.set_quoted('LDCONFIG', LDCONFIG)
|
|
conf.set_quoted('LIB_VERSION', libalpm_version)
|
|
conf.set_quoted('SYSHOOKDIR', join_paths(DATAROOTDIR, 'libalpm/hooks/'))
|
|
conf.set_quoted('CONFFILE', join_paths(SYSCONFDIR, 'pacman.conf'))
|
|
conf.set_quoted('DBPATH', join_paths(LOCALSTATEDIR, 'lib/pacman/'))
|
|
conf.set_quoted('GPGDIR', join_paths(SYSCONFDIR, 'pacman.d/gnupg/'))
|
|
conf.set_quoted('LOGFILE', join_paths(LOCALSTATEDIR, 'log/pacman.log'))
|
|
conf.set_quoted('CACHEDIR', join_paths(LOCALSTATEDIR, 'cache/pacman/pkg/'))
|
|
conf.set_quoted('HOOKDIR', join_paths(SYSCONFDIR, 'pacman.d/hooks/'))
|
|
conf.set_quoted('ROOTDIR', ROOTDIR)
|
|
|
|
libintl = dependency('', required: false)
|
|
if get_option('i18n')
|
|
if not cc.has_function('ngettext')
|
|
libintl = cc.find_library('intl', required : false, static: get_option('buildstatic'))
|
|
if not libintl.found()
|
|
error('ngettext not found but NLS support requested')
|
|
endif
|
|
endif
|
|
conf.set('ENABLE_NLS', 1)
|
|
endif
|
|
|
|
# dependencies
|
|
libarchive = dependency('libarchive',
|
|
version : '>=3.0.0',
|
|
static : get_option('buildstatic'))
|
|
|
|
libcurl = dependency('libcurl',
|
|
version : '>=7.55.0',
|
|
required : get_option('curl'),
|
|
static : get_option('buildstatic'))
|
|
conf.set('HAVE_LIBCURL', libcurl.found())
|
|
|
|
needed_gpgme_version = '>=1.3.0'
|
|
gpgme = dependency('gpgme',
|
|
version : needed_gpgme_version,
|
|
required : get_option('gpgme'),
|
|
static : get_option('buildstatic'),
|
|
not_found_message : 'gpgme @0@ is needed for GPG signature support'.format(needed_gpgme_version))
|
|
conf.set('HAVE_LIBGPGME', gpgme.found())
|
|
|
|
want_crypto = get_option('crypto')
|
|
if want_crypto == 'openssl'
|
|
libcrypto = dependency('libcrypto', static : get_option('buildstatic'),
|
|
not_found_message : 'openssl support requested but not found')
|
|
crypto_provider = libcrypto
|
|
conf.set10('HAVE_LIBSSL', true)
|
|
elif want_crypto == 'nettle'
|
|
libnettle = dependency('nettle', static : get_option('buildstatic'),
|
|
not_found_message : 'nettle support requested but not found')
|
|
crypto_provider = libnettle
|
|
conf.set10('HAVE_LIBNETTLE', true)
|
|
else
|
|
error('unhandled crypto value @0@'.format(want_crypto))
|
|
endif
|
|
|
|
foreach header : [
|
|
'mntent.h',
|
|
'sys/mnttab.h',
|
|
'sys/mount.h',
|
|
'sys/param.h',
|
|
'sys/statvfs.h',
|
|
'sys/types.h',
|
|
'sys/ucred.h',
|
|
'termios.h',
|
|
]
|
|
if cc.has_header(header)
|
|
conf.set('HAVE_' + header.underscorify().to_upper(), true)
|
|
endif
|
|
endforeach
|
|
|
|
foreach sym : [
|
|
'getmntent',
|
|
'getmntinfo',
|
|
'strndup',
|
|
'strnlen',
|
|
'strsep',
|
|
'swprintf',
|
|
'tcflush',
|
|
]
|
|
have = cc.has_function(sym, args : '-D_GNU_SOURCE')
|
|
conf.set10('HAVE_' + sym.to_upper(), have)
|
|
endforeach
|
|
|
|
foreach member : [
|
|
['struct stat', 'st_blksize', '''#include <sys/stat.h>'''],
|
|
['struct statvfs', 'f_flag', '''#include <sys/statvfs.h>'''],
|
|
['struct statfs', 'f_flags', '''#include <sys/param.h>
|
|
#include <sys/mount.h>'''],
|
|
]
|
|
have = cc.has_member(member[0], member[1], prefix : member[2])
|
|
conf.set('HAVE_' + '_'.join([member[0], member[1]]).underscorify().to_upper(), have)
|
|
endforeach
|
|
|
|
foreach type : [
|
|
# type # program prefix # fallback
|
|
['mode_t', '''#include <sys/types.h>''', 'unsigned int'],
|
|
['uid_t', '''#include <sys/types.h>''', 'unsigned int'],
|
|
['off_t', '''#include <sys/types.h>''', 'signed int'],
|
|
['pid_t', '''#include <sys/types.h>''', 'signed int'],
|
|
['size_t', '''#include <sys/types.h>''', 'unsigned int'],
|
|
['ssize_t', '''#include <sys/types.h>''', 'signed int'],
|
|
['int64_t', '''#include <stdint.h>''', 'signed long int'],
|
|
]
|
|
if not cc.has_type(type[0], prefix: type[1])
|
|
conf.set(type[0], type[2])
|
|
endif
|
|
endforeach
|
|
|
|
if conf.has('HAVE_STRUCT_STATVFS_F_FLAG')
|
|
conf.set('FSSTATSTYPE', 'struct statvfs')
|
|
elif conf.has('HAVE_STRUCT_STATFS_F_FLAGS')
|
|
conf.set('FSSTATSTYPE', 'struct statfs')
|
|
endif
|
|
|
|
if get_option('debug')
|
|
extra_cflags = [
|
|
'-Wcast-align',
|
|
'-Wclobbered',
|
|
'-Wempty-body',
|
|
'-Wfloat-equal',
|
|
'-Wformat-nonliteral',
|
|
'-Wformat-security',
|
|
'-Wignored-qualifiers',
|
|
'-Wimplicit-fallthrough',
|
|
'-Winit-self',
|
|
'-Wlogical-op',
|
|
'-Wmissing-declarations',
|
|
'-Wmissing-field-initializers',
|
|
'-Wmissing-parameter-type',
|
|
'-Wmissing-prototypes',
|
|
'-Wold-style-declaration',
|
|
'-Woverride-init',
|
|
'-Wpointer-arith',
|
|
'-Wredundant-decls',
|
|
'-Wshadow',
|
|
'-Wsign-compare',
|
|
'-Wstrict-aliasing',
|
|
'-Wstrict-overflow=5',
|
|
'-Wstrict-prototypes',
|
|
'-Wtype-limits',
|
|
'-Wuninitialized',
|
|
'-Wunused-but-set-parameter',
|
|
'-Wunused-parameter',
|
|
'-Wwrite-strings',
|
|
]
|
|
add_project_arguments(cc.get_supported_arguments(extra_cflags), language : 'c')
|
|
|
|
conf.set('PACMAN_DEBUG', 1)
|
|
endif
|
|
|
|
config_h = configure_file(
|
|
output : 'config.h',
|
|
configuration : conf)
|
|
add_project_arguments('-include', 'config.h', language : 'c')
|
|
|
|
filecmd = 'file'
|
|
inodecmd = 'stat -c \'%i %n\''
|
|
strip_binaries = '--strip-all'
|
|
strip_shared = '--strip-unneeded'
|
|
strip_static = '--strip-debug'
|
|
|
|
file_seccomp = get_option('file-seccomp')
|
|
# meson-git has find_program('file', required: false, version: '>=5.38')
|
|
filever = run_command('sh', '-c', 'file --version | sed -n "s/^file-\(.*\)/\\1/p"').stdout()
|
|
if file_seccomp.enabled() or ( file_seccomp.auto() and filever.version_compare('>= 5.38') )
|
|
filecmd = 'file -S'
|
|
endif
|
|
|
|
os = host_machine.system()
|
|
if os.startswith('darwin')
|
|
inodecmd = '/usr/bin/stat -f \'%i %N\''
|
|
strip_binaries = ''
|
|
strip_shared = '-s'
|
|
strip_static = '-s'
|
|
elif os.contains('bsd') or os == 'dragonfly'
|
|
inodecmd = 'stat -f \'%i %N\''
|
|
endif
|
|
|
|
chost = run_command(cc, '-dumpmachine').stdout().strip()
|
|
carch = chost.split('-')[0]
|
|
|
|
# annoyingly, we have to maintain two sets of configuration_data which is
|
|
# largely identical, but which distinguishes between quoting needs.
|
|
substs = configuration_data()
|
|
substs.set('SED', SED.path())
|
|
substs.set('CARCH', carch)
|
|
substs.set('CHOST', chost)
|
|
substs.set('PKGEXT', get_option('pkg-ext'))
|
|
substs.set('SRCEXT', get_option('src-ext'))
|
|
substs.set('ROOTDIR', ROOTDIR)
|
|
substs.set('LOCALEDIR', LOCALEDIR)
|
|
substs.set('sysconfdir', SYSCONFDIR)
|
|
substs.set('localstatedir', LOCALSTATEDIR)
|
|
substs.set('PKGDATADIR', PKGDATADIR)
|
|
substs.set('PREFIX', PREFIX)
|
|
substs.set('BASH', BASH.path())
|
|
substs.set('PACKAGE_VERSION', PACKAGE_VERSION)
|
|
substs.set('PACKAGE_NAME', meson.project_name())
|
|
substs.set('BUILDSCRIPT', BUILDSCRIPT)
|
|
substs.set('TEMPLATE_DIR', get_option('makepkg-template-dir'))
|
|
substs.set('DEBUGSUFFIX', get_option('debug-suffix'))
|
|
substs.set('INODECMD', inodecmd)
|
|
substs.set('FILECMD', filecmd)
|
|
substs.set('LIBMAKEPKGDIR', LIBMAKEPKGDIR)
|
|
substs.set('STRIP_BINARIES', strip_binaries)
|
|
substs.set('STRIP_SHARED', strip_shared)
|
|
substs.set('STRIP_STATIC', strip_static)
|
|
|
|
subdir('lib/libalpm')
|
|
subdir('src/common')
|
|
subdir('src/pacman')
|
|
subdir('src/util')
|
|
subdir('scripts')
|
|
|
|
# Internationalization
|
|
if get_option('i18n')
|
|
i18n = import('i18n')
|
|
subdir('lib/libalpm/po')
|
|
subdir('src/pacman/po')
|
|
subdir('scripts/po')
|
|
endif
|
|
|
|
want_doc = get_option('doc')
|
|
ASCIIDOC = find_program('asciidoc', required : want_doc)
|
|
A2X = find_program('a2x', required : want_doc)
|
|
build_doc = A2X.found() and not want_doc.disabled()
|
|
if build_doc
|
|
subdir('doc')
|
|
endif
|
|
|
|
includes = include_directories('src/common', 'lib/libalpm')
|
|
|
|
libcommon = static_library(
|
|
'common',
|
|
libcommon_sources,
|
|
include_directories : includes,
|
|
gnu_symbol_visibility : 'hidden',
|
|
install : false)
|
|
|
|
alpm_deps = [crypto_provider, libarchive, libcurl, libintl, gpgme]
|
|
|
|
libalpm_a = static_library(
|
|
'alpm_objlib',
|
|
libalpm_sources,
|
|
# https://github.com/mesonbuild/meson/issues/3937
|
|
objects : libcommon.extract_all_objects(),
|
|
include_directories : includes,
|
|
gnu_symbol_visibility : 'hidden',
|
|
dependencies : alpm_deps)
|
|
|
|
libalpm = library(
|
|
'alpm',
|
|
version : libalpm_version,
|
|
objects: libalpm_a.extract_all_objects(recursive: true),
|
|
dependencies : alpm_deps,
|
|
install : true)
|
|
|
|
install_headers(
|
|
'lib/libalpm/alpm.h',
|
|
'lib/libalpm/alpm_list.h')
|
|
|
|
pkgconfig = import('pkgconfig')
|
|
pkgconfig.generate(
|
|
libalpm,
|
|
name : 'libalpm',
|
|
description : 'Arch Linux package management library',
|
|
version : libalpm_version,
|
|
url : 'http://www.archlinux.org/pacman/')
|
|
|
|
pacman_bin = executable(
|
|
'pacman',
|
|
pacman_sources,
|
|
include_directories : includes,
|
|
link_with : [libalpm, libcommon],
|
|
dependencies : [libarchive],
|
|
install : true,
|
|
)
|
|
|
|
executable(
|
|
'pacman-conf',
|
|
pacman_conf_sources,
|
|
include_directories : includes,
|
|
link_with : [libalpm, libcommon],
|
|
dependencies : [libarchive],
|
|
install : true,
|
|
)
|
|
|
|
executable(
|
|
'testpkg',
|
|
testpkg_sources,
|
|
include_directories : includes,
|
|
link_with : [libalpm],
|
|
dependencies : [libarchive],
|
|
install : true,
|
|
)
|
|
|
|
executable(
|
|
'vercmp',
|
|
vercmp_sources,
|
|
include_directories : includes,
|
|
link_with : [libalpm_a],
|
|
install : true,
|
|
)
|
|
|
|
foreach wrapper : script_wrappers
|
|
cdata = configuration_data()
|
|
cdata.set_quoted('BASH', BASH.path())
|
|
cdata.set_quoted('BUILDDIR', wrapper[2])
|
|
cdata.set_quoted('REAL_PROGPATH', wrapper[1].full_path())
|
|
|
|
# Create a wrapper script that bootstraps the real script within the build
|
|
# directory. Use configure_file instead of a custom_target to ensure that
|
|
# permissions on the input script wrapper are preserved.
|
|
configure_file(
|
|
input : join_paths(meson.source_root(), 'build-aux', 'script-wrapper.sh.in'),
|
|
output : wrapper[0],
|
|
configuration : cdata)
|
|
endforeach
|
|
|
|
configure_file(
|
|
input : 'etc/makepkg.conf.in',
|
|
output : 'makepkg.conf',
|
|
configuration : substs,
|
|
install_dir : SYSCONFDIR)
|
|
|
|
configure_file(
|
|
input : 'etc/pacman.conf.in',
|
|
output : 'pacman.conf',
|
|
configuration : substs,
|
|
install_dir : SYSCONFDIR)
|
|
|
|
install_data(
|
|
'proto/PKGBUILD-split.proto',
|
|
'proto/PKGBUILD-vcs.proto',
|
|
'proto/PKGBUILD.proto',
|
|
'proto/proto.install',
|
|
install_dir : join_paths(DATAROOTDIR, 'pacman'))
|
|
|
|
foreach path : [
|
|
join_paths(LOCALSTATEDIR, 'lib/pacman/'),
|
|
join_paths(LOCALSTATEDIR, 'cache/pacman/pkg/'),
|
|
join_paths(DATAROOTDIR, 'makepkg-template/'),
|
|
join_paths(DATAROOTDIR, 'libalpm/hooks/'),
|
|
]
|
|
meson.add_install_script('sh', '-c', 'mkdir -p "$DESTDIR/@0@"'.format(path))
|
|
endforeach
|
|
|
|
TEST_ENV = environment()
|
|
TEST_ENV.set('PMTEST_SCRIPTLIB_DIR', join_paths(meson.source_root(), 'scripts/library/'))
|
|
TEST_ENV.set('PMTEST_LIBMAKEPKG_DIR', join_paths(meson.build_root(), 'scripts/libmakepkg/'))
|
|
TEST_ENV.set('PMTEST_UTIL_DIR', meson.build_root() + '/')
|
|
TEST_ENV.set('PMTEST_SCRIPT_DIR', join_paths(meson.build_root(), 'scripts/'))
|
|
|
|
subdir('test/pacman')
|
|
subdir('test/scripts')
|
|
subdir('test/util')
|
|
|
|
message('\n '.join([
|
|
'@0@ @1@'.format(meson.project_name(), meson.project_version()),
|
|
'Build information:',
|
|
' prefix : @0@'.format(PREFIX),
|
|
' sysconfdir : @0@'.format(SYSCONFDIR),
|
|
' conf file : @0@'.format(join_paths(SYSCONFDIR, 'pacman.conf')),
|
|
' localstatedir : @0@'.format(LOCALSTATEDIR),
|
|
' database dir : @0@'.format(join_paths(LOCALSTATEDIR, 'lib/pacman/')),
|
|
' cache dir : @0@'.format(join_paths(LOCALSTATEDIR, 'cache/pacman/pkg/')),
|
|
' compiler : @0@ @1@'.format(cc.get_id(), cc.version()),
|
|
'',
|
|
' Architecture : @0@'.format(carch),
|
|
' Host Type : @0@'.format(chost),
|
|
' File inode command : @0@'.format(inodecmd),
|
|
' File seccomp command : @0@'.format(filecmd),
|
|
' libalpm version : @0@'.format(libalpm_version),
|
|
' pacman version : @0@'.format(PACKAGE_VERSION),
|
|
'',
|
|
'Directory and file information:',
|
|
' root working directory : @0@'.format(ROOTDIR),
|
|
' package extension : @0@'.format(get_option('pkg-ext')),
|
|
' source pkg extension : @0@'.format(get_option('src-ext')),
|
|
' build script name : @0@'.format(BUILDSCRIPT),
|
|
' template directory : @0@'.format(get_option('makepkg-template-dir')),
|
|
'',
|
|
'Compilation options:',
|
|
' i18n support : @0@'.format(get_option('i18n')),
|
|
' Build docs : @0@'.format(build_doc),
|
|
' debug build : @0@'.format(get_option('buildtype') == 'debug'),
|
|
' Use libcurl : @0@'.format(conf.get('HAVE_LIBCURL')),
|
|
' Use GPGME : @0@'.format(conf.get('HAVE_LIBGPGME')),
|
|
' Use OpenSSL : @0@'.format(conf.has('HAVE_LIBSSL') and
|
|
conf.get('HAVE_LIBSSL') == 1),
|
|
' Use nettle : @0@'.format(conf.has('HAVE_LIBNETTLE') and
|
|
conf.get('HAVE_LIBNETTLE') == 1),
|
|
'',
|
|
]))
|