diff options
author | Eli Schwartz <eschwartz@archlinux.org> | 2021-08-21 23:27:29 -0400 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2021-08-22 12:49:11 +0300 |
commit | 5a7b8d86d0c455680096d47cb87f0de08c0954ac (patch) | |
tree | e3a18b74e1044206014650f4657a80bb7d40579e | |
parent | db04a3f5f212209d9c9656735480d5ec6589794f (diff) | |
download | meson-5a7b8d86d0c455680096d47cb87f0de08c0954ac.zip meson-5a7b8d86d0c455680096d47cb87f0de08c0954ac.tar.gz meson-5a7b8d86d0c455680096d47cb87f0de08c0954ac.tar.bz2 |
use a more informative error message for invoking meson in a subdir
Explicitly mention that the project definition is invalid, and clarify
that project is `project()` -- a function.
Also try to walk the directory tree upward, and if there are parent
meson.build files, just say this isn't the project root, and "maybe you
meant to run meson there instead?"
This won't catch calls to subdir('foo/bar') but we can't be perfect,
only better than before and catch the *majority* of such cases, and
hopefully it's a lot more clear if meson protests that the project is
"invalid, there is no project() function", where the user should look
for a potential solution.
Fixes #3426
-rw-r--r-- | mesonbuild/interpreterbase/interpreterbase.py | 16 | ||||
-rw-r--r-- | test cases/failing/1 project not first/test.json | 2 |
2 files changed, 15 insertions, 3 deletions
diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index f0668e4..4930bee 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -45,7 +45,7 @@ from .disabler import Disabler, is_disabled from .helpers import check_stringlist, default_resolve_key, flatten, resolve_second_level_holders from ._unholder import _unholder -import os, copy, re +import os, copy, re, pathlib import typing as T if T.TYPE_CHECKING: @@ -123,7 +123,19 @@ class InterpreterBase: raise InvalidCode('No statements in code.') first = self.ast.lines[0] if not isinstance(first, mparser.FunctionNode) or first.func_name != 'project': - raise InvalidCode('First statement must be a call to project') + p = pathlib.Path(self.source_root).resolve() + found = p + for parent in p.parents: + if (parent / 'meson.build').is_file(): + found = parent + else: + break + + error = 'first statement must be a call to project()' + if found != p: + raise InvalidCode(f'Not the project root: {error}\n\nDid you mean to run meson from the directory: "{found}"?') + else: + raise InvalidCode(f'Invalid source tree: {error}') def run(self) -> None: # Evaluate everything after the first line, which is project() because diff --git a/test cases/failing/1 project not first/test.json b/test cases/failing/1 project not first/test.json index 70f3c41..27bae02 100644 --- a/test cases/failing/1 project not first/test.json +++ b/test cases/failing/1 project not first/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "ERROR: First statement must be a call to project" + "line": "ERROR: Invalid source tree: first statement must be a call to project()" } ] } |