backends: add a new "none" backend

It can only be used for projects that don't have any rules at all, i.e.
they are purely using Meson to:

- configure files
- run (script?) tests
- install files that exist by the end of the setup stage

This can be useful e.g. for Meson itself, a pure python project.
pull/10779/head
Eli Schwartz 3 years ago
parent 2a0b80eb67
commit a024d75e15
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 12
      docs/markdown/Builtin-options.md
  2. 4
      docs/markdown/snippets/none-backend.md
  3. 3
      mesonbuild/backend/backends.py
  4. 31
      mesonbuild/backend/nonebackend.py
  5. 2
      mesonbuild/coredata.py
  6. 2
      mesonbuild/interpreter/interpreter.py
  7. 14
      mesonbuild/minstall.py
  8. 8
      mesonbuild/mtest.py
  9. 4
      test cases/python/7 install path/meson.build
  10. 3
      test cases/python/7 install path/target/meson.build
  11. 1
      unittests/baseplatformtests.py
  12. 17
      unittests/platformagnostictests.py

@ -75,7 +75,7 @@ machine](#specifying-options-per-machine) section for details.
| Option | Default value | Description | Is per machine | Is per subproject |
| -------------------------------------- | ------------- | ----------- | -------------- | ----------------- |
| auto_features {enabled, disabled, auto} | auto | Override value of all 'auto' features | no | no |
| backend {ninja, vs,<br>vs2010, vs2012, vs2013, vs2015, vs2017, vs2019, vs2022, xcode} | ninja | Backend to use | no | no |
| backend {ninja, vs,<br>vs2010, vs2012, vs2013, vs2015, vs2017, vs2019, vs2022, xcode, none} | ninja | Backend to use | no | no |
| buildtype {plain, debug,<br>debugoptimized, release, minsize, custom} | debug | Build type to use | no | no |
| debug | true | Enable debug symbols and other information | no | no |
| default_library {shared, static, both} | shared | Default library type | no | yes |
@ -95,6 +95,16 @@ machine](#specifying-options-per-machine) section for details.
| wrap_mode {default, nofallback,<br>nodownload, forcefallback, nopromote} | default | Wrap mode to use | no | no |
| force_fallback_for | [] | Force fallback for those dependencies | no | no |
#### Details for `backend`
Several build file formats are supported as command runners to build the
configured project. Meson prefers ninja by default, but platform-specific
backends are also available for better IDE integration with native tooling:
Visual Studio for Windows, and xcode for macOS. It is also possible to
configure with no backend at all, which is an error if you have targets to
build, but for projects that need configuration + testing + installation allows
for a lighter automated build pipeline.
#### Details for `buildtype`
<a name="build-type-options"></a> For setting optimization levels and

@ -0,0 +1,4 @@
## New "none" backend
The `--backend=none` option has been added, to configure a project that has no
build rules, only install rules. This avoids depending on ninja.

@ -251,6 +251,9 @@ def get_backend_from_name(backend: str, build: T.Optional[build.Build] = None, i
elif backend == 'xcode':
from . import xcodebackend
return xcodebackend.XCodeBackend(build, interpreter)
elif backend == 'none':
from . import nonebackend
return nonebackend.NoneBackend(build, interpreter)
return None
# This class contains the basic functionality that is needed by all backends.

@ -0,0 +1,31 @@
# Copyright 2022 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
from .backends import Backend
from .. import mlog
from ..mesonlib import MesonBugException
class NoneBackend(Backend):
name = 'none'
def generate(self):
if self.build.get_targets():
raise MesonBugException('None backend cannot generate target rules, but should have failed earlier.')
mlog.log('Generating simple install-only backend')
self.serialize_tests()
self.create_install_data_files()

@ -61,7 +61,7 @@ if T.TYPE_CHECKING:
# But the corresponding Git tag needs to be '0.1.0rc1'
version = '1.0.99'
backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode']
backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode', 'none']
DEFAULT_YIELDING = False

@ -3090,6 +3090,8 @@ class Interpreter(InterpreterBase, HoldableObject):
"internal use. Please rename.")
def add_target(self, name: str, tobj: build.Target) -> None:
if self.backend.name == 'none':
raise InterpreterException('Install-only backend cannot generate target rules, try using `--backend=ninja`.')
if name == '':
raise InterpreterException('Target name must not be empty.')
if name.strip() == '':

@ -14,7 +14,6 @@
from __future__ import annotations
from glob import glob
from pathlib import Path
import argparse
import errno
import os
@ -25,8 +24,7 @@ import subprocess
import sys
import typing as T
from . import build
from . import environment
from . import build, coredata, environment
from .backend.backends import InstallData
from .mesonlib import MesonException, Popen_safe, RealPathAction, is_windows, setup_vsenv, pickle_load, is_osx
from .scripts import depfixer, destdir_join
@ -755,8 +753,11 @@ class Installer:
# file mode needs to be set last, after strip/depfixer editing
self.set_mode(outname, install_mode, d.install_umask)
def rebuild_all(wd: str) -> bool:
if not (Path(wd) / 'build.ninja').is_file():
def rebuild_all(wd: str, backend: str) -> bool:
if backend == 'none':
# nothing to build...
return True
if backend != 'ninja':
print('Only ninja backend is supported to rebuild the project before installation.')
return True
@ -816,7 +817,8 @@ def run(opts: 'ArgumentType') -> int:
if not opts.no_rebuild:
b = build.load(opts.wd)
setup_vsenv(b.need_vsenv)
if not rebuild_all(opts.wd):
backend = T.cast('str', b.environment.coredata.get_option(coredata.OptionKey('backend')))
if not rebuild_all(opts.wd, backend):
sys.exit(-1)
os.chdir(opts.wd)
with open(os.path.join(log_dir, 'install-log.txt'), 'w', encoding='utf-8') as lf:

@ -43,7 +43,7 @@ import xml.etree.ElementTree as et
from . import build
from . import environment
from . import mlog
from .coredata import major_versions_differ, MesonVersionMismatchException
from .coredata import MesonVersionMismatchException, OptionKey, major_versions_differ
from .coredata import version as coredata_version
from .mesonlib import (MesonException, OrderedSet, RealPathAction,
get_wine_shortpath, join_args, split_args, setup_vsenv)
@ -2099,7 +2099,11 @@ def run(options: argparse.Namespace) -> int:
setup_vsenv(b.need_vsenv)
if not options.no_rebuild:
if not (Path(options.wd) / 'build.ninja').is_file():
backend = b.environment.coredata.get_option(OptionKey('backend'))
if backend == 'none':
# nothing to build...
options.no_rebuild = True
elif backend != 'ninja':
print('Only ninja backend is supported to rebuild tests before running them.')
# Disable, no point in trying to build anything later
options.no_rebuild = True

@ -17,4 +17,8 @@ py_plat.install_sources('test.py', pure: true, subdir: 'kwrevert')
install_data('test.py', install_dir: py_plat.get_install_dir() / 'kw/data')
install_data('test.py', install_dir: py_plat.get_install_dir(pure: true) / 'kwrevert/data')
if get_option('backend') == 'none'
subdir('target')
endif
subdir('structured')

@ -0,0 +1,3 @@
testcase expect_error('Install-only backend cannot generate target rules, try using `--backend=ninja`.')
import('fs').copyfile('../test.py')
endtestcase

@ -70,6 +70,7 @@ class BasePlatformTests(TestCase):
self.uninstall_command = get_backend_commands(self.backend)
# Test directories
self.common_test_dir = os.path.join(src_root, 'test cases/common')
self.python_test_dir = os.path.join(src_root, 'test cases/python')
self.rust_test_dir = os.path.join(src_root, 'test cases/rust')
self.vala_test_dir = os.path.join(src_root, 'test cases/vala')
self.framework_test_dir = os.path.join(src_root, 'test cases/frameworks')

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
import tempfile
import subprocess
@ -121,3 +122,19 @@ class PlatformAgnosticTests(BasePlatformTests):
'''))
subprocess.check_call(self.wrap_command + ['update-db'], cwd=testdir)
self.init(testdir, workdir=testdir)
def test_none_backend(self):
testdir = os.path.join(self.python_test_dir, '7 install path')
self.init(testdir, extra_args=['--backend=none'], override_envvars={'NINJA': 'absolutely false command'})
self.assertPathDoesNotExist(os.path.join(self.builddir, 'build.ninja'))
self.run_tests(inprocess=True, override_envvars={})
out = self._run(self.meson_command + ['install', f'--destdir={self.installdir}'], workdir=self.builddir)
self.assertNotIn('Only ninja backend is supported to rebuild the project before installation.', out)
with open(os.path.join(testdir, 'test.json'), 'rb') as f:
dat = json.load(f)
for i in dat['installed']:
self.assertPathExists(os.path.join(self.installdir, i['file']))

Loading…
Cancel
Save