aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2020-02-24 15:15:06 -0800
committerXavier Claessens <xclaesse@gmail.com>2020-03-04 14:07:27 -0500
commit1210a67f66df15a54fc7c65f7406bcd5391d15aa (patch)
tree9890464379ef921245c01bba0bcc5167b0e33b43
parenta46f0a620228f9acfbf2340d6d9a2d58229720aa (diff)
downloadmeson-1210a67f66df15a54fc7c65f7406bcd5391d15aa.zip
meson-1210a67f66df15a54fc7c65f7406bcd5391d15aa.tar.gz
meson-1210a67f66df15a54fc7c65f7406bcd5391d15aa.tar.bz2
mesonbuild: Add mcompile command
This is tested working with both msbuild and ninja/samu. Since our xcode support is pretty much broken I didn't bother. Fixes #6670
-rw-r--r--.github/workflows/lint_mypy.yml2
-rw-r--r--docs/markdown/snippets/meson_compile_command.md21
-rw-r--r--mesonbuild/mcompile.py123
-rw-r--r--mesonbuild/mesonmain.py4
-rwxr-xr-xrun_unittests.py15
5 files changed, 163 insertions, 2 deletions
diff --git a/.github/workflows/lint_mypy.yml b/.github/workflows/lint_mypy.yml
index 8f6d917..7c83714 100644
--- a/.github/workflows/lint_mypy.yml
+++ b/.github/workflows/lint_mypy.yml
@@ -30,4 +30,4 @@ jobs:
with:
python-version: '3.x'
- run: python -m pip install mypy
- - run: mypy --follow-imports=skip mesonbuild/interpreterbase.py mesonbuild/mtest.py mesonbuild/minit.py mesonbuild/mintro.py mesonbuild/mparser.py mesonbuild/msetup.py mesonbuild/ast mesonbuild/wrap tools/ mesonbuild/modules/fs.py mesonbuild/dependencies/boost.py mesonbuild/dependencies/mpi.py mesonbuild/dependencies/hdf5.py mesonbuild/compilers/mixins/intel.py mesonbuild/mlog.py
+ - run: mypy --follow-imports=skip mesonbuild/interpreterbase.py mesonbuild/mtest.py mesonbuild/minit.py mesonbuild/mintro.py mesonbuild/mparser.py mesonbuild/msetup.py mesonbuild/ast mesonbuild/wrap tools/ mesonbuild/modules/fs.py mesonbuild/dependencies/boost.py mesonbuild/dependencies/mpi.py mesonbuild/dependencies/hdf5.py mesonbuild/compilers/mixins/intel.py mesonbuild/mlog.py mesonbuild/mcompile.py
diff --git a/docs/markdown/snippets/meson_compile_command.md b/docs/markdown/snippets/meson_compile_command.md
new file mode 100644
index 0000000..e029ff8
--- /dev/null
+++ b/docs/markdown/snippets/meson_compile_command.md
@@ -0,0 +1,21 @@
+## Backend agnostic compile command
+
+A new `meson compile` command has been added to support backend agnostic
+compilation. It accepts two arguments, `-j` and `-l`, which are used if
+possible (`-l` does nothing with msbuild). A `-j` or `-l` value < 1 lets the
+backend decide how many threads to use. For msbuild this means `-m`, for
+ninja it means passing no arguments.
+
+```console
+meson builddir --backend vs
+meson compile -C builddir -j0 # this is the same as `msbuild builddir/my.sln -m`
+```
+
+```console
+meson builddir
+meson compile -C builddir -j3 # this is the same as `ninja -C builddir -j3`
+```
+
+Additionally `meson compile` provides a `--clean` switch to clean the project.
+
+A complete list of arguments is always documented via `meson compile --help`
diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py
new file mode 100644
index 0000000..372c853
--- /dev/null
+++ b/mesonbuild/mcompile.py
@@ -0,0 +1,123 @@
+# Copyright 2020 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.
+
+"""Entrypoint script for backend agnostic compile."""
+
+import os
+import pathlib
+import shutil
+import sys
+import typing as T
+
+from . import mlog
+from . import mesonlib
+from .mesonlib import MesonException
+
+if T.TYPE_CHECKING:
+ import argparse
+
+
+def add_arguments(parser: 'argparse.ArgumentParser') -> None:
+ """Add compile specific arguments."""
+ parser.add_argument(
+ '-j', '--jobs',
+ action='store',
+ default=0,
+ type=int,
+ help='The number of worker jobs to run (if supported). If the value is less than 1 the build program will guess.'
+ )
+ parser.add_argument(
+ '-l', '--load-average',
+ action='store',
+ default=0,
+ type=int,
+ help='The system load average to try to maintain (if supported)'
+ )
+ parser.add_argument(
+ '--clean',
+ action='store_true',
+ help='Clean the build directory.'
+ )
+ parser.add_argument(
+ '-C',
+ action='store',
+ dest='builddir',
+ type=pathlib.Path,
+ required=True,
+ default='.',
+ help='The directory containing build files to be built.'
+ )
+
+
+def run(options: 'argparse.Namespace') -> int:
+ bdir = options.builddir # type: pathlib.Path
+ if not bdir.exists():
+ raise MesonException('Path to builddir {} does not exist!'.format(str(bdir.resolve())))
+ if not bdir.is_dir():
+ raise MesonException('builddir path should be a directory.')
+
+ cmd = [] # type: T.List[str]
+ runner = None # type T.Optional[str]
+ slns = list(bdir.glob('*.sln'))
+
+ if (bdir / 'build.ninja').exists():
+ runner = os.environ.get('NINJA')
+ if not runner:
+ if shutil.which('ninja'):
+ runner = 'ninja'
+ elif shutil.which('samu'):
+ runner = 'samu'
+
+ if runner is None:
+ raise MesonException('Cannot find either ninja or samu.')
+
+ cmd = [runner, '-C', bdir.as_posix()]
+
+ # If the value is set to < 1 then don't set anything, which let's
+ # ninja/samu decide what to do.
+ if options.jobs > 0:
+ cmd.extend(['-j', str(options.jobs)])
+ if options.load_average > 0:
+ cmd.extend(['-l', str(options.load_average)])
+ if options.clean:
+ cmd.append('clean')
+
+ # TODO: with python 3.8 this could be `elif slns := bdir.glob('*.sln'):`
+ elif slns:
+ assert len(slns) == 1, 'More than one solution in a project?'
+
+ sln = slns[0]
+ cmd = ['msbuild', str(sln.resolve())]
+
+ # In msbuild `-m` with no number means "detect cpus", the default is `-m1`
+ if options.jobs > 0:
+ cmd.append('-m{}'.format(options.jobs))
+ else:
+ cmd.append('-m')
+
+ if options.load_average:
+ mlog.warning('Msbuild does not have a load-average switch, ignoring.')
+ if options.clean:
+ cmd.extend(['/t:Clean'])
+
+ # TODO: xcode?
+ else:
+ raise MesonException(
+ 'Could not find any runner or backend for directory {}'.format(bdir.resolve().as_posix()))
+
+ mlog.log('Found runner:', runner)
+
+ p, *_ = mesonlib.Popen_safe(cmd, stdout=sys.stdout.buffer, stderr=sys.stderr.buffer)
+
+ return p.returncode
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 6ec9682..b6b11df 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -22,7 +22,7 @@ import shutil
from . import mesonlib
from . import mlog
-from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata
+from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile
from .mesonlib import MesonException
from .environment import detect_msys2_arch
from .wrap import wraptool
@@ -62,6 +62,8 @@ class CommandLineParser:
help_msg='Print help of a subcommand')
self.add_command('rewrite', lambda parser: rewriter.add_arguments(parser, self.formatter), rewriter.run,
help_msg='Modify the project definition')
+ self.add_command('compile', mcompile.add_arguments, mcompile.run,
+ help_msg='Build the project')
# Hidden commands
self.add_command('runpython', self.add_runpython_arguments, self.run_runpython_command,
diff --git a/run_unittests.py b/run_unittests.py
index 3f5c87e..b9dcd41 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -4412,6 +4412,21 @@ recommended as it is not supported on some platforms''')
else:
self.assertEqual(expected_lines, out_lines)
+ def test_meson_compile(self):
+ """Test the meson compile command."""
+ prog = 'trivialprog'
+ if is_windows():
+ prog = '{}.exe'.format(prog)
+
+ testdir = os.path.join(self.common_test_dir, '1 trivial')
+ self.init(testdir)
+ self._run([*self.meson_command, 'compile', '-C', self.builddir])
+ # If compile worked then we should get a program
+ self.assertPathExists(os.path.join(self.builddir, prog))
+
+ self._run([*self.meson_command, 'compile', '-C', self.builddir, '--clean'])
+ self.assertPathDoesNotExist(os.path.join(self.builddir, prog))
+
class FailureTests(BasePlatformTests):
'''