From b6804bf49c68ca84c22f9f0c4d18732f15461847 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Tue, 16 Feb 2021 11:14:38 -0500 Subject: [PATCH] Substitute @CURRENT_SOURCE_DIR@ in run_target() and custom_target() run_target() does some variable substitutions since 0.57.0. This is a new behavior, and undocumented, caused by sharing more code with custom_target(). More consistency is better, so document it now. custom_target() was doing variable substitution in the past, because it shared some code with generator(), but that was undocumented. Some refactoring in 0.57.0 caused it to not replace @CURRENT_SOURCE_DIR@, @SOURCE_DIR@, and @BUILD_DIR@ anymore. This patch adds back @CURRENT_SOURCE_DIR@ and document it. It does not add back @SOURCE_DIR@ because it is duplicate with @SOURCE_ROOT@ that has a better name. Also do not add back @BUILD_DIR@ which is duplicate of @PRIVATE_DIR@, and not @BUILD_ROOT@ surprisingly, adding to the confusion. --- docs/markdown/Reference-manual.md | 17 ++++++++++++++++ mesonbuild/backend/backends.py | 2 ++ run_unittests.py | 1 + test cases/common/52 run target/check-env.py | 16 ++++++++++++++- test cases/common/52 run target/meson.build | 21 ++++++++++++++++++-- 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 46ea1c00542a..3693e57db103 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -402,6 +402,13 @@ the following special string substitutions: - `@PLAINNAME@`: the input filename, without a path - `@BASENAME@`: the input filename, with extension removed - `@PRIVATE_DIR@` *(since 0.50.1)*: path to a directory where the custom target must store all its intermediate files. +- `@SOURCE_ROOT@`: the path to the root of the source tree. Depending on the backend, + this may be an absolute or a relative to current workdir path. +- `@BUILD_ROOT@`: the path to the root of the build tree. Depending on the backend, + this may be an absolute or a relative to current workdir path. +- `@CURRENT_SOURCE_DIR@`: this is the directory where the currently + processed meson.build is located in. Depending on the backend, + this may be an absolute or a relative to current workdir path. *(since 0.47.0)* The `depfile` keyword argument also accepts the `@BASENAME@` and `@PLAINNAME@` substitutions. @@ -1522,6 +1529,16 @@ and subdirectory the target was defined in, respectively. or an [`environment()` object](#environment-object) which allows more sophisticated environment juggling. +*Since 0.57.0* The template strings passed to `command` keyword arguments accept +the following special substitutions: +- `@SOURCE_ROOT@`: the path to the root of the source tree. Depending on the backend, + this may be an absolute or a relative to current workdir path. +- `@BUILD_ROOT@`: the path to the root of the build tree. Depending on the backend, + this may be an absolute or a relative to current workdir path. +- `@CURRENT_SOURCE_DIR@` *Since 0.57.1*: this is the directory where the currently + processed meson.build is located in. Depending on the backend, + this may be an absolute or a relative to current workdir path. + ### set_variable() ``` meson diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 2dbf1ec57a4a..ecd506789d4f 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -1153,6 +1153,8 @@ def eval_custom_target_command(self, target, absolute_outputs=False): i = i.replace('@SOURCE_ROOT@', source_root) if '@BUILD_ROOT@' in i: i = i.replace('@BUILD_ROOT@', build_root) + if '@CURRENT_SOURCE_DIR@' in i: + i = i.replace('@CURRENT_SOURCE_DIR@', os.path.join(source_root, target.subdir)) if '@DEPFILE@' in i: if target.depfile is None: msg = 'Custom target {!r} has @DEPFILE@ but no depfile ' \ diff --git a/run_unittests.py b/run_unittests.py index 3aa1cb31f58e..73be9b7ae21e 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -2382,6 +2382,7 @@ def test_run_target_files_path(self): self.init(testdir) self.run_target('check_exists') self.run_target('check-env') + self.run_target('dummy.stamp') def test_install_introspection(self): ''' diff --git a/test cases/common/52 run target/check-env.py b/test cases/common/52 run target/check-env.py index 8df3e28c7bc9..cf3eb7c08dd8 100644 --- a/test cases/common/52 run target/check-env.py +++ b/test cases/common/52 run target/check-env.py @@ -1,9 +1,23 @@ #!/usr/bin/env python3 -import os +import os, sys +from pathlib import Path assert 'MESON_SOURCE_ROOT' in os.environ assert 'MESON_BUILD_ROOT' in os.environ assert 'MESON_SUBDIR' in os.environ assert 'MESONINTROSPECT' in os.environ assert 'MY_ENV' in os.environ + +# Environment has absolute paths and argv has relative paths when using ninja +# backend and absolute paths when using vs backend. What matters is once +# resolved they point to same location. +env_source_root = Path(os.environ['MESON_SOURCE_ROOT']).resolve() +env_build_root = Path(os.environ['MESON_BUILD_ROOT']).resolve() +env_current_source_dir = Path(env_source_root, os.environ['MESON_SUBDIR']).resolve() +argv_paths = [Path(i).resolve() for i in sys.argv[1:]] +source_root, build_root, current_source_dir = argv_paths + +assert source_root == env_source_root +assert build_root == env_build_root +assert current_source_dir == env_current_source_dir diff --git a/test cases/common/52 run target/meson.build b/test cases/common/52 run target/meson.build index d1964e89f409..9b62f165c3ee 100644 --- a/test cases/common/52 run target/meson.build +++ b/test cases/common/52 run target/meson.build @@ -81,8 +81,25 @@ run_target('ctags', run_target('clang-format', command : converter) -# Check we can pass env to the program +# Check we can pass env to the program. Also check some string substitutions +# that were added in 0.57.0 but not documented. This is documented behaviour +# since 0.57.1. run_target('check-env', - command: [find_program('check-env.py')], + command: [find_program('check-env.py'), '@SOURCE_ROOT@', '@BUILD_ROOT@', + '@CURRENT_SOURCE_DIR@'], env: {'MY_ENV': '1'}, ) + +# Check some string substitutions that has always been done but never documented. +# Some projects have been relying on this implementation detail. This is +# documented behaviour since 0.57.1. +custom_target('dummy.stamp', + command: [find_program('check-env.py'), '@SOURCE_ROOT@', '@BUILD_ROOT@', + '@CURRENT_SOURCE_DIR@'], + env: {'MESON_SOURCE_ROOT': meson.source_root(), + 'MESON_BUILD_ROOT': meson.build_root(), + 'MESON_SUBDIR': meson.current_source_dir(), + 'MESONINTROSPECT': 'fake value', + 'MY_ENV': '1'}, + output: 'dummy.stamp', +)