New stable version. Many internal cleanups/fixups/C++20-modernization, but also a number of new features: mu: - better handling of html parts - fall back to most recent 'Received' for 'Date:'-less messages - record the time-zone offset mu4e: - improved mime-handling - improved HTML view (generate HTML view for pure text as well) - hide "clickables" until requested (but see mu4e-view-always-show-url-indicators) scm: - performance improvements - new methods for querying system configuration" and querying database fields, and getting timezone information (for 'date' and 'changed') See NEWS.org for further details.
425 lines
14 KiB
Meson
425 lines
14 KiB
Meson
## Copyright (C) 2022-2026 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
|
##
|
|
## This program is free software; you can redistribute it and/or modify
|
|
## it under the terms of the GNU General Public License as published by
|
|
## the Free Software Foundation; either version 3 of the License, or
|
|
## (at your option) any later version.
|
|
##
|
|
## This program is distributed in the hope that it will be useful,
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
## GNU General Public License for more details.
|
|
##
|
|
## You should have received a copy of the GNU General Public License
|
|
## along with this program; if not, write to the Free Software Foundation,
|
|
## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
################################################################################
|
|
# project setup
|
|
project('mu', ['c', 'cpp'],
|
|
version: '1.14.3',
|
|
meson_version: '>= 1.3.2',
|
|
license: 'GPL-3.0-or-later',
|
|
default_options : {
|
|
'buildtype': 'debugoptimized',
|
|
'warning_level': '3',
|
|
'c_std': 'c11',
|
|
'cpp_std': 'c++20'})
|
|
|
|
fs = import('fs')
|
|
|
|
# hard-code the datxe here (for reproducibility); we derive the dates used in
|
|
# e.g. documentation from this.
|
|
mu_date='2026-08-09'
|
|
|
|
# installation paths
|
|
prefixdir = get_option('prefix')
|
|
bindir = prefixdir / get_option('bindir')
|
|
datadir = prefixdir / get_option('datadir')
|
|
mandir = prefixdir / get_option('mandir')
|
|
infodir = prefixdir / get_option('infodir')
|
|
|
|
svgicondir = datadir / 'icons' / 'hicolor' / 'scalable' / 'apps'
|
|
muiconpath = svgicondir / 'mu-icon.svg'
|
|
|
|
# allow for configuring lispdir, as with autotools.
|
|
if get_option('lispdir') == ''
|
|
mu4e_lispdir= datadir / 'emacs' / 'site-lisp' / 'mu4e'
|
|
else
|
|
mu4e_lispdir= get_option('lispdir') / 'mu4e'
|
|
endif
|
|
|
|
################################################################################
|
|
# compilers / flags
|
|
#
|
|
|
|
# compilers
|
|
cc = meson.get_compiler('c')
|
|
cxx= meson.get_compiler('cpp')
|
|
|
|
extra_flags = [
|
|
'-Wno-unused-parameter',
|
|
'-Wno-cast-function-type',
|
|
'-Wformat-security',
|
|
'-Wformat=2',
|
|
'-Wstack-protector',
|
|
'-fstack-protector-strong',
|
|
'-Wno-switch-enum',
|
|
# assuming these are false alarm... (in fmt, with gcc13):
|
|
'-Wno-array-bounds',
|
|
'-Wno-stringop-overflow',
|
|
# c++23, in tabulate.hpp (3rd-party)
|
|
'-Wno-deprecated-literal-operator'
|
|
]
|
|
|
|
if (cxx.get_id() == 'clang')
|
|
extra_flags += [
|
|
'-Wc11-extensions',
|
|
'-Wno-keyword-macro',
|
|
'-Wno-deprecated-volatile',
|
|
'-Wno-unknown-warning-option',
|
|
'-Wno-#warnings']
|
|
endif
|
|
|
|
extra_cpp_flags= [
|
|
'-Wno-volatile'
|
|
]
|
|
|
|
if get_option('buildtype') == 'debug'
|
|
extra_flags += [
|
|
'-D_GLIBCXX_ASSERTIONS',
|
|
'-ggdb',
|
|
'-g3']
|
|
endif
|
|
|
|
# extra arguments, if available
|
|
add_project_arguments(cxx.get_supported_arguments(extra_flags + extra_cpp_flags),
|
|
language: 'cpp')
|
|
|
|
# some clang don't have charconv, but we need it.
|
|
# https://github.com/djcb/mu/issues/2347
|
|
cxx.check_header('charconv', required:true)
|
|
|
|
build_aux = meson.project_source_root() / 'build-aux'
|
|
################################################################################
|
|
# derived date values (based on 'mu-date'); used in docs
|
|
# we can't use the 'date' because MacOS 'date' is incompatible with GNU's.
|
|
pdate=find_program(build_aux / 'date.py')
|
|
env = environment()
|
|
env.set('LANG', 'C')
|
|
mu_day_month_year = run_command(pdate, mu_date, '%d %B %Y',
|
|
check:true, capture:true,
|
|
env: env).stdout().strip()
|
|
mu_month_year = run_command(pdate, mu_date, '%B %Y',
|
|
check:true, capture:true,
|
|
env: env).stdout().strip()
|
|
mu_year = run_command(pdate, mu_date, '%Y',
|
|
check:true, capture:true, env: env).stdout().strip()
|
|
|
|
################################################################################
|
|
# config.h setup
|
|
#
|
|
config_h_data=configuration_data()
|
|
config_h_data.set('MU_STORE_SCHEMA_VERSION', 500)
|
|
config_h_data.set_quoted('PACKAGE_VERSION', meson.project_version())
|
|
config_h_data.set_quoted('PACKAGE_STRING', meson.project_name() + ' ' +
|
|
meson.project_version())
|
|
config_h_data.set_quoted('VERSION', meson.project_version())
|
|
config_h_data.set_quoted('PACKAGE_NAME', meson.project_name())
|
|
|
|
add_project_arguments(['-DHAVE_CONFIG_H'], language: ['c', 'cpp'])
|
|
config_h_dep=declare_dependency(
|
|
include_directories: include_directories(['.']))
|
|
|
|
#
|
|
# d_type, d_ino are not available universally, so let's check
|
|
# (we use them for optimizations in mu-scanner
|
|
#
|
|
if cxx.has_member('struct dirent', 'd_ino', prefix : '#include<dirent.h>')
|
|
config_h_data.set('HAVE_DIRENT_D_INO', 1)
|
|
endif
|
|
|
|
if cxx.has_member('struct dirent', 'd_type', prefix : '#include<dirent.h>')
|
|
config_h_data.set('HAVE_DIRENT_D_TYPE', 1)
|
|
endif
|
|
|
|
|
|
functions=[
|
|
'setsid'
|
|
]
|
|
foreach f : functions
|
|
if cc.has_function(f)
|
|
define = 'HAVE_' + f.underscorify().to_upper()
|
|
config_h_data.set(define, 1)
|
|
endif
|
|
endforeach
|
|
|
|
if cc.has_function('wordexp')
|
|
config_h_data.set('HAVE_WORDEXP_H',1)
|
|
else
|
|
message('no wordexp, no command-line option expansion')
|
|
endif
|
|
|
|
pthread_setname_np_code = '''
|
|
#include <pthread.h>
|
|
int main() { return pthread_setname_np(pthread_self(), "test"); }
|
|
'''
|
|
pthread_setname_np_check = cxx.compiles(
|
|
pthread_setname_np_code,
|
|
name: 'pthread_setname_np check',
|
|
args: '-D_GNU_SOURCE'
|
|
)
|
|
if pthread_setname_np_check
|
|
config_h_data.set('HAVE_PTHREAD_SETNAME_NP', 1)
|
|
endif
|
|
|
|
if get_option('tests').allowed()
|
|
# only needed for tests
|
|
cp=find_program('cp')
|
|
ln=find_program('ln')
|
|
rm=find_program('rm')
|
|
|
|
config_h_data.set_quoted('CP_PROGRAM', cp.full_path())
|
|
config_h_data.set_quoted('RM_PROGRAM', rm.full_path())
|
|
config_h_data.set_quoted('LN_PROGRAM', ln.full_path())
|
|
|
|
testmaildir= meson.project_source_root() / 'testdata'
|
|
config_h_data.set_quoted('MU_TESTDATADIR', testmaildir)
|
|
config_h_data.set_quoted('MU_TESTMAILDIR', testmaildir / 'testdir')
|
|
config_h_data.set_quoted('MU_TESTMAILDIR2', testmaildir / 'testdir2')
|
|
config_h_data.set_quoted('MU_TESTMAILDIR4', testmaildir / 'testdir4')
|
|
config_h_data.set_quoted('MU_TESTMAILDIR_CJK', testmaildir / 'cjk')
|
|
endif
|
|
|
|
|
|
################################################################################
|
|
# hard dependencies
|
|
#
|
|
# glib & friends
|
|
glib_dep = dependency('glib-2.0', version: '>= 2.80')
|
|
gobject_dep = dependency('gobject-2.0', version: '>= 2.80')
|
|
gio_dep = dependency('gio-2.0', version: '>= 2.80')
|
|
gio_unix_dep = dependency('gio-unix-2.0', version: '>= 2.80')
|
|
|
|
# gmime
|
|
gmime_dep = dependency('gmime-3.0', version: '>= 3.2.13')
|
|
# 3.2.13 version has g_mime_object_write_content_to_stream
|
|
|
|
thread_dep = dependency('threads')
|
|
|
|
# we need Xapian 1.4.22 or higher
|
|
xapian_dep = dependency('xapian-core', version:'>= 1.4.22', required:true)
|
|
xapver = xapian_dep.version()
|
|
if xapver.version_compare('>= 1.4.23')
|
|
message('xapian ' + xapver + ' supports ngrams')
|
|
config_h_data.set('HAVE_XAPIAN_FLAG_NGRAMS', 1)
|
|
endif
|
|
|
|
#
|
|
# soft dependencies
|
|
#
|
|
|
|
# use system's fmt if found, otherwise fall back to embedded version
|
|
# we can probably get away with a lower version, but want to have (roughly)
|
|
# the same in embedded / system.
|
|
fmt_dep = dependency('fmt', version: '>=11.1', required:false)
|
|
if not fmt_dep.found() or get_option('use-embedded-fmt')
|
|
message('using embedded fmt')
|
|
fmt_dep = declare_dependency(
|
|
include_directories : include_directories('thirdparty/fmt'),
|
|
compile_args: '-DFMT_HEADER_ONLY')
|
|
endif
|
|
|
|
# use system's CLI11 if found, otherwise fall back to embedded version. we can
|
|
# probably get away with a lower version, but want to have (roughly) the same in
|
|
# embedded / system.
|
|
cli11_dep = dependency('CLI11', version: '>=2.4', required:false)
|
|
if not cli11_dep.found() or get_option('use-embedded-cli11')
|
|
message('using embedded CLI11')
|
|
cli11_dep = declare_dependency(
|
|
compile_args: '-DUSE_EMBEDDED_CLI11',
|
|
include_directories : include_directories('thirdparty/cli11'))
|
|
endif
|
|
|
|
#
|
|
# logging
|
|
#
|
|
# if we're on a linux machine, perhaps there's systemd/journald.
|
|
# otherwise, we don't bother.
|
|
if host_machine.system() == 'linux'
|
|
config_h_data.set('MAYBE_USE_JOURNAL', 1)
|
|
endif
|
|
if cc.has_function('g_log_writer_syslog',dependencies: glib_dep)
|
|
config_h_data.set('MAYBE_USE_SYSLOG', 1)
|
|
endif
|
|
|
|
#
|
|
# use Compact Language Detector2 if we can find it
|
|
#
|
|
cld2_dep = cxx.find_library('cld2', required: get_option('cld2'))
|
|
if get_option('cld2').allowed() and cld2_dep.found()
|
|
config_h_data.set('HAVE_CLD2', 1)
|
|
else
|
|
message('CLD2 not found or disabled; no support for language detection')
|
|
config_h_data.set('HAVE_CLD2', 0)
|
|
endif
|
|
|
|
#
|
|
# guile
|
|
#
|
|
guile_required=get_option('guile').enabled() or get_option('scm').enabled()
|
|
guile_dep = dependency('guile-3.0', required: guile_required)
|
|
|
|
# allow for a custom guile-extension-dir (for old-style guile-support)
|
|
if guile_dep.found() and get_option('guile').allowed()
|
|
custom_guile_xd=get_option('guile-extension-dir')
|
|
if custom_guile_xd == ''
|
|
guile_extension_dir = guile_dep.get_variable(pkgconfig: 'extensiondir')
|
|
else
|
|
guile_extension_dir = custom_guile_xd
|
|
endif
|
|
config_h_data.set_quoted('MU_GUILE_EXTENSION_DIR', guile_extension_dir)
|
|
message('Using guile-extension-dir: ' + guile_extension_dir)
|
|
endif
|
|
|
|
makeinfo=find_program(['makeinfo'], required:false)
|
|
if not makeinfo.found()
|
|
message('makeinfo (texinfo) not found; not building info documentation')
|
|
else
|
|
install_info=find_program(['install-info'], required:false)
|
|
if not install_info.found()
|
|
message('install-info not found')
|
|
else
|
|
install_info_script=build_aux / 'meson-install-info.sh'
|
|
endif
|
|
endif
|
|
|
|
# readline. annoyingly, macos has an incompatible libedit claiming to be
|
|
# readline. this is only a dev/debug convenience for the mu4e repl.
|
|
if get_option('readline').enabled()
|
|
readline_dep = dependency('readline', version:'>= 8.0')
|
|
config_h_data.set('HAVE_LIBREADLINE', 1)
|
|
config_h_data.set('HAVE_READLINE_READLINE_H', 1)
|
|
config_h_data.set('HAVE_READLINE_HISTORY', 1)
|
|
config_h_data.set('HAVE_READLINE_HISTORY_H', 1)
|
|
else
|
|
readline_dep=declare_dependency() # dummy
|
|
endif
|
|
|
|
################################################################################
|
|
# write out version.texi (for texinfo builds in mu4e, guile)
|
|
version_texi_data=configuration_data()
|
|
version_texi_data.set('VERSION', meson.project_version())
|
|
version_texi_data.set('EDITION', meson.project_version())
|
|
|
|
# derived date values
|
|
version_texi_data.set('UPDATED', mu_day_month_year)
|
|
version_texi_data.set('UPDATEDMONTH', mu_month_year)
|
|
version_texi_data.set('UPDATEDYEAR', mu_year)
|
|
|
|
configure_file(input: build_aux / 'version.texi.in',
|
|
output: 'version.texi',
|
|
configuration: version_texi_data)
|
|
# build-time copy; texinfo targets must declare 'depends: fdl_texi'
|
|
fdl_texi = fs.copyfile(build_aux / 'fdl.texi')
|
|
|
|
################################################################################
|
|
# install some data files
|
|
install_data('NEWS.org', 'IDEAS.org',
|
|
install_dir : datadir / 'doc' / 'mu')
|
|
|
|
################################################################################
|
|
# subdirs
|
|
subdir('assets')
|
|
subdir('lib')
|
|
|
|
# dummy-dep.
|
|
mu_scm_dep = declare_dependency()
|
|
|
|
# this must happen _after_ subdir('lib')
|
|
if guile_dep.found()
|
|
|
|
# modern guile support
|
|
if get_option('scm').allowed()
|
|
config_h_data.set('BUILD_SCM', 1)
|
|
subdir('scm')
|
|
else
|
|
config_h_data.set('BUILD_SCM', 0)
|
|
endif
|
|
|
|
# old-style guile-support (deprecated)
|
|
if get_option('guile').allowed()
|
|
message('old-style guile support is deprecated')
|
|
config_h_data.set('BUILD_GUILE', 1)
|
|
config_h_data.set_quoted('GUILE_BINARY',
|
|
guile_dep.get_variable(pkgconfig: 'guile'))
|
|
subdir('guile')
|
|
endif
|
|
else
|
|
config_h_data.set('BUILD_SCM', 0)
|
|
endif
|
|
|
|
subdir('mu')
|
|
|
|
# emacs -- needed for mu4e compilation
|
|
emacs_name=get_option('emacs')
|
|
emacs_min_version='28.1'
|
|
emacs=find_program([emacs_name], version: '>=' + emacs_min_version, required:false)
|
|
if emacs.found()
|
|
subdir('man')
|
|
subdir('mu4e')
|
|
else
|
|
message('emacs not found; not pre-compiling mu4e / generating man-pages')
|
|
endif
|
|
|
|
config_h_data.set_quoted('MU_PROGRAM', mu.full_path())
|
|
################################################################################
|
|
|
|
################################################################################
|
|
# write-out config.h
|
|
configure_file(output : 'config.h', configuration : config_h_data)
|
|
|
|
if gmime_dep.version() == '3.2.13'
|
|
warning('gmime version 3.2.13 detected, which has a decoding bug')
|
|
warning('See: https://github.com/jstedfast/gmime/issues/133')
|
|
endif
|
|
|
|
################################################################################
|
|
# summary
|
|
summary({'prefix' : prefixdir,
|
|
'buildtype' : get_option('buildtype'),
|
|
'c compiler' : cc.get_id() + ' ' + cc.version(),
|
|
'c++ compiler' : cxx.get_id() + ' ' + cxx.version()},
|
|
section: 'Build')
|
|
|
|
summary({'glib' : glib_dep.version(),
|
|
'gmime' : gmime_dep.version(),
|
|
'xapian' : xapian_dep.version(),
|
|
'fmt' : fmt_dep.type_name() == 'internal' ? 'embedded' : fmt_dep.version(),
|
|
'CLI11' : cli11_dep.type_name() == 'internal' ? 'embedded' : cli11_dep.version(),
|
|
'guile' : guile_dep.found() ? guile_dep.version() : 'not found'},
|
|
section: 'Dependencies')
|
|
|
|
summary({'language detection (cld2)' : get_option('cld2').allowed() and cld2_dep.found(),
|
|
'scm scripting' : guile_dep.found() and get_option('scm').allowed(),
|
|
'guile (old-style, deprecated)': guile_dep.found() and get_option('guile').allowed(),
|
|
'readline' : get_option('readline').enabled(),
|
|
'tests' : get_option('tests').allowed(),
|
|
'info docs (makeinfo)' : makeinfo.found(),
|
|
'mu4e, man-pages (emacs)' : emacs.found()},
|
|
section: 'Features', bool_yn: true)
|
|
|
|
if emacs.found()
|
|
summary({'emacs version': emacs.version(),
|
|
'mu4e lispdir' : mu4e_lispdir},
|
|
section: 'Mu4e')
|
|
endif
|
|
|
|
summary({'bash' : get_option('bash-completion').allowed(),
|
|
'zsh' : get_option('zsh-completion').allowed()},
|
|
section: 'Completion', bool_yn: true)
|
|
|
|
# Local Variables:
|
|
# indent-tabs-mode: nil
|
|
# End:
|