diff options
author | Dave Reisner <dreisner@archlinux.org> | 2018-07-07 16:29:48 +0200 |
---|---|---|
committer | Dave Reisner <dreisner@archlinux.org> | 2018-11-02 08:16:34 +0100 |
commit | 51db84750ece4de58923d4ce43cb0638ef150f5f (patch) | |
tree | 6aec4d1ed84ca324d61359f2d8408ff078f3bb28 /meson.build | |
parent | dab45f0808951afc2e3146211a1c6d7ebb8bd06d (diff) | |
download | pacman-51db84750ece4de58923d4ce43cb0638ef150f5f.tar.gz pacman-51db84750ece4de58923d4ce43cb0638ef150f5f.tar.xz |
Add meson.build files to build with meson
Provide both build systems in parallel for now, to ensure that we work
out all the differences between the two. Some time from now, we'll give
up on autotools.
Meson tends to be faster and probably easier to read/maintain. On my
machine, the full meson configure+build+install takes a little under
half as long as a similar autotools-based invocation.
Building with meson is a two step process. First, configure the build:
meson build
Then, compile the project:
ninja -C build
There's some mild differences in functionality between meson and
autotools. specifically:
1) No singular update-po target. meson only generates individual
update-po targets for each textdomain (of which we have 3). To make
this easier, there's a build-aux/update-po script which finds all
update-po targets and runs them.
2) No 'make dist' equivalent. Just run 'git archive' to generate a
suitable tarball for distribution.
Diffstat (limited to 'meson.build')
-rw-r--r-- | meson.build | 487 |
1 files changed, 487 insertions, 0 deletions
diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..95895300 --- /dev/null +++ b/meson.build @@ -0,0 +1,487 @@ +project('pacman', + 'c', + version : '5.1.0', + license : 'GPLv2+', + default_options : [ + 'c_std=gnu99', + 'prefix=/usr', + 'sysconfdir=/etc', + 'localstatedir=/var', + ], + meson_version : '>= 0.47') + +libalpm_version = '11.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') +M4 = find_program('m4') +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', meson.project_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) + +if get_option('i18n') + if not cc.has_function('ngettext') + error('ngettext not found but NLS support requested') + 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()) + +want_gpgme = get_option('gpgme') +gpgme_config = find_program('gpgme-config', required : want_gpgme) +if not want_gpgme.disabled() and gpgme_config.found() + gpgme_version = run_command(gpgme_config, '--version').stdout().strip() + + needed_gpgme_version = '>=1.3.0' + have = gpgme_version.version_compare(needed_gpgme_version) + if want_gpgme.enabled() and not have + error('gpgme @0@ is needed for GPG signature support'.format(needed_gpgme_version)) + endif + + gpgme_libs = [ + cc.find_library('gpgme', required : have, + dirs : [get_option('gpgme-libdir')]), + cc.find_library('gpg-error', required : have, + dirs : [get_option('gpgme-libdir')]), + cc.find_library('assuan', required : have, + dirs : [get_option('gpgme-libdir')]), + ] + + conf.set('HAVE_LIBGPGME', have) +else + gpgme_libs = [] + conf.set('HAVE_LIBGPGME', false) +endif + +want_crypto = get_option('crypto') +if want_crypto == 'openssl' + libcrypto = dependency('libcrypto', static : get_option('buildstatic')) + if not libcrypto.found() + error('openssl support requested but not found') + endif + crypto_provider = libcrypto + conf.set10('HAVE_LIBSSL', true) +elif want_crypto == 'nettle' + libnettle = dependency('nettle', static : get_option('buildstatic')) + if not libnettle.found() + error('nettle support requested but not found') + endif + 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 : [ + 'dup2', + 'fork', + 'getcwd', + 'getmntent', + 'getmntinfo', + 'gettimeofday', + 'memmove', + 'memset', + 'mkdir', + 'realpath', + 'regcomp', + 'rmdir', + 'setenv', + 'setlocale', + 'strcasecmp', + 'strchr', + 'strcspn', + 'strdup', + 'strerror', + 'strndup', + 'strnlen', + 'strnlen', + 'strrchr', + 'strsep', + 'strsep', + 'strstr', + 'strtol', + 'swprintf', + 'tcflush', + 'tcflush', + 'uname', + 'wcwidth', + ] + 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 + +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('buildtype') == 'debug' + extra_cflags = [ + '-Wcast-align', + '-Wclobbered', + '-Wempty-body', + '-Wfloat-equal', + '-Wformat-nonliteral', + '-Wformat-security', + '-Wignored-qualifiers', + '-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') + +default_duflags = ' -sk --apparent-size' +default_sedinplaceflags = ' --follow-symlinks -i' +inodecmd = 'stat -c \'%i %n\'' +ownercmd = 'stat -c \'%u:%g\'' +modecmd = 'stat -c \'%a\'' +strip_binaries = '--strip-all' +strip_shared = '--strip-unneeded' +strip_static = '--strip-debug' + +os = host_machine.system() +if os.startswith('darwin') + inodecmd = '/usr/bin/stat -f \'%i %n\'' + ownercmd = '/usr/bin/stat -f \'%u:%g\'' + modecmd = '/usr/bin/stat -f \'%lp\'' + default_sedinplaceflags = ' -i \'\'' + default_duflags = ' -sk' + strip_binaries = '' + strip_shared = '-s' + strip_static = '-s' +elif os.contains('bsd') or os == 'dragonfly' + inodecmd = 'stat -f \'%i %n\'' + ownercmd = 'stat -f \'%u:%g\'' + modecmd = 'stat -f \'%lp\'' + default_sedinplaceflags = ' -i \'\'' + default_duflags = ' -sk' +endif + +duflags = get_option('duflags') +if duflags == 'autodetect' + duflags = default_duflags +endif + +sedinplaceflags = get_option('sedinplaceflags') +if sedinplaceflags == 'auto' + sedinplaceflags = default_sedinplaceflags +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('M4', M4.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('OWNERCMD', ownercmd) +substs.set('MODECMD', modecmd) +substs.set('SEDINPLACEFLAGS', sedinplaceflags) +substs.set('SEDPATH', SED.path()) +substs.set('DUFLAGS', duflags) +substs.set('DUPATH', DU.path()) +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) + +libalpm = library( + 'alpm', + libalpm_sources, + version : libalpm_version, + include_directories : includes, + dependencies : [crypto_provider, libarchive, libcurl] + gpgme_libs, + link_with : [libcommon], + install : true) + +install_headers( + 'lib/libalpm/alpm.h', + 'lib/libalpm/alpm_list.h') + +# TODO: libs.private seem quite wrong here +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], + install : true, +) + +executable( + 'cleanupdelta', + cleanupdelta_sources, + include_directories : includes, + link_with : [libalpm], + install : true, +) + +executable( + 'testpkg', + testpkg_sources, + include_directories : includes, + link_with : [libalpm], + install : true, +) + +executable( + 'vercmp', + vercmp_sources, + include_directories : includes, + link_with : [libalpm], + install : true, +) + +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')) + +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 owner command : @0@'.format(ownercmd), + ' File mode command : @0@'.format(modecmd), + ' Directory size command : @0@ @1@'.format(DU.path(), duflags), + ' In-place sed command : @0@ @1@'.format(SED.path(), sedinplaceflags), + ' 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), + '', +])) |