OZI-Project/OZI

View on GitHub
meson.build

Summary

Maintainability
Test Coverage
# meson.build
# Part of the OZI Project, under the Apache License v2.0 with LLVM Exceptions.
# See LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
project(
    'OZI',
    version: run_command(
        'python3',  # scm_version_snip
        [
            '-c',
            '''from setuptools_scm import get_version
from packaging.version import Version
v = get_version(normalize=False)
print(v)
''',
        ],
        check: true,
    ).stdout().strip(),
    default_options: ['warning_level=3'],
    license: 'Apache-2.0 WITH LLVM-exception',
    license_files: 'LICENSE.txt',
    meson_version: '>=1.1.0',
)
env = environment()
fs = import('fs')
pymod = import('python')
pyproject_config = configuration_data()

# prescript arrays
no_version = get_option('no-version')
unhashable = get_option('unhashable')
should_fail = get_option('should-fail')
module_only = get_option('module-only')
dist_suite = get_option('dist-suite')
docs_suite = get_option('docs-suite')
lint_suite = get_option('lint-suite')
test_suite = get_option('test-suite')
dist_exclude_suites = get_option('dist-exclude-suites')
docs_exclude_suites = get_option('docs-exclude-suites')
lint_exclude_suites = get_option('lint-exclude-suites')
test_exclude_suites = get_option('test-exclude-suites')
# descript arrays
namespace = get_option('namespace')
plugin_only = get_option('plugin-only')
python_dependencies = get_option('python-dependencies')
# features
dev = get_option('dev')
docs_source = get_option('docs-source')
test_source = get_option('test-source')
# templates
python_readlines = 'f=open("@0@","r");print(*f.readlines(),sep="",end="");f.close();'

build_root = meson.global_build_root()
scripts = 'ozi' / 'scripts'
project_name = meson.project_name()
python = pymod.find_installation(
    'python3',
    modules: python_dependencies,
    required: true,
    disabler: true,
)
pyproject_config.set(
    'PYTHON_VERSION_DIST',
    'py' + ''.join(python.language_version().split('.')),
)
pyproject_config.set('VCS_TAG', '@VCS_TAG@')
root_files = [
    'README',
    'CHANGELOG.md',
    'LICENSE.txt',
    'pyproject.toml',
    '.gitignore',
]
configure_file(
    input: root_files[3],
    output: root_files[3],
    configuration: pyproject_config,
)
meson_setuptools_scm = run_command(
    python,
    ['-c', python_readlines.format(scripts / 'meson_setuptools_scm.py')],
    check: true,
).stdout()
meson_dist_setuptools_scm = run_command(
    python,
    ['-c', python_readlines.format(scripts / 'meson_dist_setuptools_scm.py')],
    check: true,
).stdout()
core_metadata = run_command(
    python,
    ['-c', python_readlines.format(scripts / 'core_metadata_template.py')],
    check: true,
).stdout()
metadata_version = run_command(
    python,
    ['-c', python_readlines.format(scripts / 'version_metadata_template.py')],
    check: true,
).stdout()
# snippets
scm_version_snip = run_command(
    python,
    ['-c', python_readlines.format(scripts / 'scm_version_snip.py')],
    check: true,
).stdout()
to_distribution = run_command(
    python,
    ['-c', python_readlines.format(scripts / 'to_distribution_template.py')],
    check: true,
).stdout()
install_dependencies = run_command(
    python,
    [
        '-c',
        python_readlines.format(
            scripts / 'meson_postconf_install_dependencies.py',
        ),
    ],
    check: true,
).stdout()
replace_ruff_target_version = run_command(
    python,
    ['-c', python_readlines.format(scripts / 'replace_ruff_target_version.py')],
    check: true,
).stdout()
run_command(python, ['-c', replace_ruff_target_version], check: true)
install_cmd = find_program(
    get_option('install-requirements-command')[0],
    required: false,
    disabler: true,
)
if install_cmd.found()
    pip = get_option('install-requirements-command')
else
    pip = find_program('pip', required: true).full_path()
endif
pipx = find_program('pipx', required: true, disabler: true)
compile_cmd = find_program(
    get_option('compile-requirements-command')[0],
    required: false,
    disabler: true,
)
if compile_cmd.found()
    pip_compile = get_option('compile-requirements-command')
else
    pip_compile = find_program('pip-compile', required: true).full_path()
endif
if not meson.is_subproject()
    deps = run_command(python, '-c', install_dependencies, check: true).stdout().strip().split(
        '$$',
    )
    if deps.length() > 1
        meson.add_postconf_script(pip, 'install', deps)
    endif
endif
docs_source = 'docs'
test_source = 'tests'
no_check = {'check': false, 'env': env}
install = ['install']
build_commands = {'dev': []}
test_app_args = {}
configure_file(command: [python, '-c', meson_setuptools_scm], output: 'PKG-INFO')
meson.add_dist_script(pip, 'install', 'tomli>=2.0.0')
meson.add_dist_script(python, '-c', meson_dist_setuptools_scm)
vcs_tag(input: 'pyproject.toml', output: 'pyproject.orig.toml')
message('backed up pyproject.toml as pyproject.orig.toml')
foreach source : root_files
    if source not in ['.gitignore', 'pyproject.toml', 'README', 'CHANGELOG.md']
        fs.copyfile(source)
    elif source == 'README'
        fs.copyfile(source, 'README.rst')
    endif
endforeach
if get_option('ozi-blastpipe').enabled()
# BEGIN BOOTSTRAP SCRIPT
    subproject('blastpipe')
# END BOOTSTRAP SCRIPT
endif
root_children = ['ozi', 'tests']
foreach child : root_children
    subdir(child)
endforeach
if false
    executable('root_files', root_files)
    executable('source_files', source_files)
    executable('source_children', source_children)
    executable('test_files', test_files)
    executable('test_children', test_children)
endif

# BEGIN checkpoint-suite-install
modules = []
foreach name : namespace
    command_names = get_option(name + '-suite')
    summary(
        name,
        get_option(name),
        section: ' '.join('$', 'meson setup --reconfigure -D[option]'),
    )
    suite = get_option(name)
    suite.enable_auto_if(dev.enabled())
    set_variable(name, suite)
    foreach command : command_names
        if suite.enabled() and command in module_only
            modules += [command.underscorify()]  # we should collapse repeated `_`
        endif
        if command == 'python-semantic-release'
            command = 'semantic_release'
        endif
        flag = disabler()
        if ((get_option('dev').enabled() or suite.enabled())
and command not in plugin_only
)
            if command not in module_only and get_option('tox-env-dir') != ''
                message('install', command, 'with pipx')
                run_command(
                    pipx,
                    [
                        'runpip',
                        'meson',
                        '--python',
                        python,
                        'install',
                        get_option('install-args-' + command),
                        '-r',
                        meson.project_build_root() / 'ozi' / name / command / 'requirements.txt',
                    ],
                    check: true,
                )
            else
                message('install', command, 'with', ' '.join(pip))
                run_command(
                    pip,
                    [
                        'install',
                        get_option('install-args-' + command),
                        '-r',
                        meson.project_build_root() / 'ozi' / name / command / 'requirements.txt',
                    ],
                    check: true,
                )
            endif
            if not flag.found() and command not in module_only
                flag = find_program(
                    command,
                    required: false,
                    disabler: true,
                    dirs: [get_option('tox-env-dir') / 'bin'],
                )
            elif command in module_only
                command = command.replace('-', '_')
                flag = command
            endif
        endif
        if command not in plugin_only
            set_variable(command.replace('-', '_'), flag)
        endif
        set_variable(name + '_kwargs', {'suite': name, 'env': env})
    endforeach
endforeach
pymod.find_installation(
    'python3',
    modules: modules,
    required: false,
    disabler: true,
)
# END checkpoint-suite-install

# BEGIN checkpoint-suite-version-check
done = []
foreach name : namespace
    foreach suite : get_option(name + '-exclude-suites')
        foreach app : get_option(suite + '-suite')
            if app in ['python-semantic-release']
                app = 'semantic_release'
            endif
            if app in done
                continue
            endif
            header = ['$', 'meson', 'test', '--suite=@0@'.format(suite)]
            feature = get_variable(suite)
            if feature.enabled()
                if app not in plugin_only + module_only
                    if app not in no_version
                        summary(
                            {app: get_variable(app.replace('-', '_')).version()},
                            section: ' '.join(header),
                        )
                    endif
                    packaged_version = run_command(
                        python,
                        ['-c', metadata_version.format(app)],
                        kwargs: no_check,
                    ).stdout().strip()
                    fallback_version = run_command(
                        pip,
                        ['show', app],
                        kwargs: no_check,
                    ).stdout().split(
                        '\n',
                    )
                    if fallback_version.length() > 2
                        fallback_version = fallback_version[1].split(':')[1].strip()
                    else
                        fallback_version = 'unknown (see Python packages)'
                    endif
                    if app in no_version
                        if packaged_version == ''
                            version = fallback_version
                        else
                            version = packaged_version
                        endif
                        if app not in done
                            summary({app: version}, section: ' '.join(header))
                        endif
                    endif
                else
                    packaged_version = run_command(
                        python,
                        ['-c', metadata_version.format(app)],
                        kwargs: no_check,
                    ).stdout().strip()
                    if app in module_only
                        fallback_version = run_command(
                            pip,
                            [
                                'show',
                                run_command(
                                    python,
                                    ['-c', to_distribution.format(app)],
                                    kwargs: no_check,
                                ).stdout(),
                            ],
                            kwargs: no_check,
                        ).stdout().split(
                            '\n',
                        )
                    else
                        fallback_version = run_command(
                            pip,
                            ['show', app],
                            kwargs: no_check,
                        ).stdout().split(
                            '\n',
                        )
                    endif
                    if fallback_version.length() > 2
                        fallback_version = fallback_version[1].split(':')[1].strip()
                    else
                        fallback_version = 'unknown (see Python packages)'
                    endif
                    if app in no_version
                        summary(
                            {app: fallback_version},
                            section: ' '.join(header),
                        )
                    else
                        summary(
                            {app: packaged_version},
                            section: ' '.join(header),
                        )
                    endif
                endif
            endif
            done += app
        endforeach
    endforeach
endforeach
# END checkpoint-suite-version-check

# BEGIN checkpoint-suite-invocation
add_test_setup('dev', is_default: not meson.is_subproject(), env: env)
env.append('TESTS_BUILDDIR', build_root)
no_check = {'check': false, 'env': env}
opt_cov_eq_project_name = '--cov=' + project_name
build_commands = {'dev': []}
foreach name : namespace
    add_test_setup(
        name,
        exclude_suites: get_option(name + '-exclude-suites'),
        timeout_multiplier: get_option(name + '-timeout-multiplier'),
    )
    set_variable(name + '_kwargs', {'suite': name, 'env': env})
    command_names = get_option(name + '-suite')
    foreach command : command_names
        if command == 'python-semantic-release'
            command = 'semantic_release'
        endif
        if command not in plugin_only
            _args = get_option('args-' + command)
        else
            _args = []
        endif
        command_args = []
        test_app_args = {}
        foreach arg : _args
            if (arg.startswith('@')
and (arg.endswith('@')
or arg.endswith('@/')
or arg.endswith('@/test')
)
)
                arg = arg.strip('@')
                if is_variable(arg)
                    arg = get_variable(arg)
                elif arg.endswith('@/')
                    arg = get_variable(arg.replace('@/', '')) + '/'
                elif arg.endswith('@/test')
                    arg = get_variable(arg.replace('@/test', '')) + '/tests'
                else
                    warning(arg + ' unknown')
                endif
            endif
            command_args += arg
        endforeach
        if command in ['pytest'] and not meson.is_subproject()
            test_paths = []
            foreach file : test_files
                test_paths += ['tests' / file]
            endforeach
            command_args = test_paths + command_args
        endif
        if command not in plugin_only
            foreach app, args : {command: command_args}
                if app in module_only
                    args = ['-m', app.replace('-', '_'), args]
                endif
                args = {
                    'args': args,
                    'env': env,
                    'priority': get_option(name + '-priority'),
                    'suite': name,
                }
                if app in should_fail
                    args += {'should_fail': true}
                endif
                feature = get_variable(name)
                if feature.enabled() and app not in module_only
                    test_app = get_variable(app.replace('-', '_'))
                else
                    test_app = disabler()
                endif
                if test_app.found() and app not in module_only
                    test(app, test_app, kwargs: args)
                elif app in ['bandit']
                    args += {'workdir': meson.global_source_root()}
                    test(app, python, kwargs: args)
                else
                    test(app, python, kwargs: args)
                endif
            endforeach
        endif
    endforeach
endforeach
# END checkpoint-suite-invocation

display_dirs = ['bindir', 'datadir', 'libdir', 'localedir', 'prefix']
foreach dir : display_dirs
    summary(
        {dir: get_option(dir)},
        section: '$ meson install -C @0@'.format(build_root),
    )
endforeach
summary('install_dir', python.get_install_dir(), section: 'Python')
summary('install_env', get_option('python.install_env'), section: 'Python')
summary('path', python.full_path(), section: 'Python')
summary('version', python.language_version(), section: 'Python')

foreach name : namespace
    if get_option(name).enabled() or dev.enabled()
        installed_packages = []
        foreach line : run_command(pip, 'freeze', check: true).stdout().split(
            '\n',
        )
            if line == ''
                continue
            endif
            if not line.contains('@')
                package = line.split('==')
            else
                package = line.split('@')
            endif
            if (package[0] not in get_option('test-suite')
and package[0] not in get_option('lint-suite')
and package[0] not in get_option('dist-suite')
)
                installed_packages += package[0]
                summary(
                    package[0],
                    package[1].strip(),
                    section: 'Python packages',
                )
            endif
        endforeach

        # Prior to Python 3.12 these would not be included in pip freeze
        # See: https://github.com/pypa/pip/pull/12032
        foreach legacy_package : ['wheel', 'setuptools', 'distribute']
            if legacy_package not in installed_packages
                legacy_package_version = run_command(
                    python,
                    ['-c', metadata_version.format(legacy_package)],
                    kwargs: no_check,
                ).stdout().strip()
                if legacy_package_version != ''
                    summary(
                        legacy_package,
                        legacy_package_version,
                        section: 'Python packages',
                    )
                endif
            endif
        endforeach
        pip_version = run_command(pip, '-V', check: true).stdout().split()
        summary(pip_version[0], pip_version[1], section: 'Python packages')
        break  ### avoids repeating for each namespace making the above run once for *any*
    endif
endforeach