NEDM/meson.build

398 lines
14 KiB
Meson

# Copyright 2020 - 2025, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
project(
'nedm',
'c',
version : '0.1.6',
license : 'MIT',
default_options : ['c_std=c23,c11', 'warning_level=3']
)
add_project_arguments(
[
'-DWLR_USE_UNSTABLE',
'-Werror=implicit-function-declaration',
'-Wundef',
],
language: 'c',
)
if get_option('buildtype').startswith('debug')
add_project_arguments(
[
'-DDEBUG',
],
language : 'c',
)
endif
cc = meson.get_compiler('c')
fuzz_compile_args = []
fuzz_link_args = []
if get_option('fuzz')
fuzzing_engine = meson.get_compiler('c').find_library('Fuzzer', required : false)
if fuzzing_engine.found()
fuzz_compile_args += '-fsanitize-coverage=trace-pc-guard,trace-cmp'
elif cc.has_argument('-fsanitize=fuzzer-no-link')
fuzz_compile_args += '-fsanitize=fuzzer-no-link'
fuzz_link_args += '-fsanitize=fuzzer-no-link'
else
error('Looks like neither libFuzzer nor -fsanitize=fuzzer-no-link is supported. Disable fuzzing using -Dfuzz=false to build without fuzzers.')
endif
endif
is_freebsd = host_machine.system().startswith('freebsd')
if is_freebsd
add_project_arguments(
[
'-Wno-format-extra-args',
'-Wno-gnu-zero-variadic-macro-arguments',
],
language: 'c'
)
endif
wlroots = dependency('wlroots-0.19')
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
wayland_server = dependency('wayland-server')
wayland_cursor = dependency('wayland-cursor')
wayland_client = dependency('wayland-client')
xkbcommon = dependency('xkbcommon')
cairo = dependency('cairo')
pango = dependency('pango')
pangocairo = dependency('pangocairo')
fontconfig = dependency('fontconfig')
libinput = dependency('libinput')
libevdev = dependency('libevdev')
libudev = dependency('libudev')
math = cc.find_library('m')
wl_protocol_dir = wayland_protos.get_variable(pkgconfig : 'pkgdatadir')
wayland_scanner = find_program('wayland-scanner')
wayland_scanner_server = generator(
wayland_scanner,
output: '@BASENAME@-protocol.h',
arguments: ['server-header', '@INPUT@', '@OUTPUT@'],
)
server_protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
['protocols', 'wlr-layer-shell-unstable-v1.xml'],
]
server_protos_headers = []
foreach p : server_protocols
xml = join_paths(p)
server_protos_headers += wayland_scanner_server.process(xml)
endforeach
server_protos = declare_dependency(
sources: server_protos_headers,
)
if get_option('xwayland')
wlroots_has_xwayland = cc.get_define('WLR_HAS_XWAYLAND', prefix: '#include <wlr/config.h>', dependencies: wlroots) == '1'
if not wlroots_has_xwayland
error('Cannot build Cagebreak with XWayland support: wlroots has been built without it')
else
have_xwayland = true
endif
else
have_xwayland = false
endif
fanalyzer_compile_flag=[]
if cc.has_argument('-fanalyzer')
have_fanalyze=true
fanalyzer_compile_flag=[ '-fanalyzer' ]
else
have_fanalyze=false
endif
if get_option('version_override') != ''
version = '@0@'.format(get_option('version_override'))
else
version = '@0@'.format(meson.project_version())
endif
conf_data = configuration_data()
conf_data.set10('NEDM_HAS_XWAYLAND', have_xwayland)
conf_data.set10('NEDM_HAS_FANALYZE', have_fanalyze)
conf_data.set_quoted('NEDM_VERSION', version)
nedm_main_file = [ 'nedm.c', ]
nedm_source_strings = [
'idle_inhibit_v1.c',
'input_manager.c',
'ipc_server.c',
'keybinding.c',
'layer_shell.c',
'workspace.c',
'output.c',
'parse.c',
'seat.c',
'util.c',
'view.c',
'wallpaper.c',
'xdg_shell.c',
'libinput.c',
'server.c',
'message.c',
'pango.c',
]
nedm_header_strings = [
'idle_inhibit_v1.h',
'ipc_server.h',
'keybinding.h',
'layer_shell.h',
'workspace.h',
'output.h',
'parse.h',
'seat.h',
'server.h',
'util.h',
'view.h',
'wallpaper.h',
'xdg_shell.h',
'pango.h',
'message.h',
]
if conf_data.get('NEDM_HAS_XWAYLAND', 0) == 1
nedm_source_strings += 'xwayland.c'
nedm_header_strings += 'xwayland.h'
endif
nedm_sources = [
configure_file(input: 'config.h.in',
output: 'config.h',
configuration: conf_data),
]
nedm_headers = []
foreach source : nedm_source_strings
nedm_sources += files(source)
endforeach
foreach header : nedm_header_strings
nedm_headers += files(header)
endforeach
# Dependencies marked with "true" are required to have
# the version specified below in order for the build
# to be reproducible.
nedm_dependencies_dict = {
'server_protos': [server_protos,true],
'wayland_server': [wayland_server,false],
'wayland_client': [wayland_client,true],
'wayland_cursor': [wayland_cursor,true],
'wlroots': [wlroots,true],
'xkbcommon': [xkbcommon,true],
'fontconfig': [fontconfig,true],
'libinput': [libinput,true],
'libevdev': [libevdev,true],
'libudev': [libudev,true],
'pango': [pango,true],
'cairo': [cairo,true],
'pangocairo': [pangocairo,true],
'math': [math,true],
}
reproducible_build_versions = {
'server_protos': '-1',
'wayland_server': '1.19.0',
'wayland_client': '1.23.1',
'wayland_cursor': '1.23.1',
'wlroots': '0.19.0',
'xkbcommon': '1.10.0',
'fontconfig': '2.17.1',
'libinput': '1.28.1',
'libevdev': '1.13.4',
'libudev': '257',
'pango': '1.56.4',
'cairo': '1.18.4',
'pangocairo': '1.56.4',
'math': '-1'
}
nedm_dependencies = []
foreach name, dep : nedm_dependencies_dict
nedm_dependencies += dep[0]
endforeach
foreach name, dep : nedm_dependencies_dict
if reproducible_build_versions[name] != '-1'
if dep[1] == false
if dep[0].version() < reproducible_build_versions[name]
warning('The installed version of "' + name + '" on your machine (' + dep[0].version() + ') is older than the one used to generate the binary specified in Hashes.md (' + reproducible_build_versions[name] + '). It is recommended to use an up-to-date version for compiling cagebreak.'
)
endif
elif reproducible_build_versions[name] != dep[0].version()
warning('The installed version of "' + name + '" on your machine (' + dep[0].version() + ') differs from the one used to generate the binary specified in Hashes.md (' + reproducible_build_versions[name] + '). Cagebreak does not guarantee a reproducible build for this configuration.'
)
break
endif
endif
endforeach
reproducible_build_compiler = 'gcc'
reproducible_build_compiler_version = '15.1.1'
if cc.get_id() != reproducible_build_compiler
warning('The compiler "' + cc.get_id() + '" differs from the one used to generate to binary specified in Hashes.md (' + reproducible_build_compiler + ').')
elif cc.version() != reproducible_build_compiler_version
warning('The version of ' + cc.get_id() + ' (' + cc.version() + ') differs from the one used to generate the binary specified in Hashes.md ' + reproducible_build_compiler_version + '.')
endif
executable(
meson.project_name(),
nedm_main_file + nedm_sources + nedm_headers,
dependencies: nedm_dependencies,
install: true,
link_args: fuzz_link_args+fanalyzer_compile_flag,
c_args: fuzz_compile_args,
)
install_data('examples/config', install_dir : '/etc/xdg/' + meson.project_name())
install_data('LICENSE', install_dir : '/usr/share/licenses/' + meson.project_name() + '/')
if get_option('man-pages')
scdoc = find_program('scdoc')
secssinceepoch = 1751745126
shcommand = 'export SOURCE_DATE_EPOCH=' + secssinceepoch.to_string() + ' ; @0@ < @INPUT@'.format(scdoc.full_path())
sh = find_program('sh')
mandir1 = join_paths(get_option('mandir'), 'man1')
mandir5 = join_paths(get_option('mandir'), 'man5')
mandir7 = join_paths(get_option('mandir'), 'man7')
cagebreak_man = custom_target('cagebreak_man',
output : 'cagebreak.1',
input : 'man/cagebreak.1.md',
capture : true,
command : [sh, '-c', shcommand],
install: true,
install_dir: mandir1
)
cagebreak_man = custom_target('cagebreak_config_man',
output : 'cagebreak-config.5',
input : 'man/cagebreak-config.5.md',
capture : true,
command : [sh, '-c', shcommand],
install: true,
install_dir: mandir5
)
cagebreak_man = custom_target('cagebreak_socket_man',
output : 'cagebreak-socket.7',
input : 'man/cagebreak-socket.7.md',
capture : true,
command : [sh, '-c', shcommand],
install: true,
install_dir: mandir7
)
endif
fuzz_sources = [
'fuzz/fuzz-parse.c',
'fuzz/fuzz-lib.c',
]
fuzz_headers = [
'parse.h',
'fuzz/fuzz-lib.h',
]
fuzz_override_lib = [ 'fuzz/execl_override.c' ]
if get_option('fuzz')
inc = include_directories(['.','build/'])
fuzz_dependencies = nedm_dependencies
if fuzzing_engine.found()
fuzz_dependencies += fuzzing_engine
else
link_args = [ '-fsanitize=fuzzer', ]
endif
override_lib = shared_library('execl_override',
[ fuzz_override_lib ],
dependencies: [ cairo,pango,pangocairo ],
install: false
)
executable(
'fuzz-parse',
fuzz_sources + fuzz_headers + nedm_headers + nedm_sources,
dependencies: fuzz_dependencies,
install: false,
include_directories: inc,
link_args: link_args + fuzz_link_args,
c_args: fuzz_compile_args,
link_with: override_lib,
)
endif
summary = [
'',
'NEDM @0@'.format(version),
'',
' xwayland: @0@'.format(have_xwayland),
''
]
message('\n'.join(summary))
# Commenting out missing scripts temporarily
# run_target('devel-install',
# command : ['scripts/install-development-environment'])
# run_target('fuzz',
# command : ['scripts/fuzz', get_option('corpus')])
# run_target('adjust-epoch',
# command : ['scripts/adjust-epoch'])
# run_target('git-tag',
# command : ['scripts/git-tag', get_option('gpg_id'), meson.project_version()])
# run_target('output-hashes',
# command : ['scripts/output-hashes', meson.project_version()])
# run_target('create-sigs',
# command : ['scripts/create-signatures', get_option('gpg_id')])
# run_target('set-ver',
# command : ['scripts/set-version', meson.project_version()])
# run_target('create-artefacts',
# command : ['scripts/create-release-artefacts', get_option('gpg_id'), meson.project_version()])
# Test Suite - commented out due to missing test scripts
# test('Build without warnings', find_program('test/build-w-o-warnings'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Example script header is consistent', find_program('test/script-header'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Script executability is consistent', find_program('test/script-header'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Man page consistency', find_program('test/man-pages'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Build without xwayland', find_program('test/build-w-o-xwayland'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Copyright and LICENSE', find_program('test/copyright-license'), args : [ nedm_main_file + nedm_source_strings + nedm_header_strings + fuzz_sources + fuzz_headers + fuzz_override_lib ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()), ''.join('MESONLICENSE=', meson.project_license())], suite: 'devel' )
# test('Formatting check (clang-format)', find_program('test/clang-format'), args : [ nedm_main_file + nedm_source_strings + nedm_header_strings + fuzz_sources + fuzz_headers + fuzz_override_lib ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Script linting (shellcheck)', find_program('test/shellcheck'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('GPG key validity', find_program('test/gpg-validity'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Illegal Strings', find_program('test/illegal-strings'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel')
# test('Static analysis (scan-build)', find_program('test/scan-build'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel-long')
# test('Arguments', find_program('test/arguments'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'basic')
# test('Environment Variables', find_program('test/environment-variables'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'basic')
# test('Semantic versioning', find_program('test/versions'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release')
# test('Signature validity', find_program('test/gpg-signatures'), suite: 'release')
# test('Hashes.md', find_program('test/hashes-md'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release')
# test('Non-auto tests', find_program('test/non-auto-tests'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release')
# test('Git tag', find_program('test/git-tag'), args : [ meson.project_version() ], suite: 'release')
# test('Release-artefacts', find_program('test/check-artefacts'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release')