pacman/meson.build
Eli Schwartz 3bd88821bb build: add libintl dependency to meson and the .pc file
In order to use gettext on systems where it is not part of libc, the
correct linker flags are needed in libalpm.pc (for static compilation).
This has never been the case.

The new meson build system currently only checks for ngettext in libc,
but does not fall back to searching for the existence of -lintl; add it
to the libalpm dependencies.

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Allan McRae <allan@archlinux.org>
2020-06-11 10:47:14 +10:00

461 lines
14 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.32.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,
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,
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],
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),
'',
]))