Remove absolute paths from build command lines The GN convention is to specify paths in command lines relative to the build directory. Unfortunately and contrary to pigweed's expectations this is not what rebase_path(path) does; that outputs an absolute path. Absolute paths are not desirable in most circumstances as they contain sources of nondeterminism such as the developer's home directory. Using them can for example reduce hit rate in build caches. Replace rebase_path(path) with rebase_path(path, root_build_dir) which is the correct idiom and matches GN's builtin behavior (e.g. for sources, include_dirs, etc). This also removes the --directory argument to python_action(). Changing the directory during the build while using relative paths is likely to result in confusion and should be discouraged. There's a couple more things to do on top of this for identical binaries between build directories / machines / developers: - pass options to avoid embedding the working directory - pass options to use relative paths for the vendored clang & libc++ See [1]-[2] for how to do that. [1] https://source.chromium.org/chromium/chromium/src/+/main:build/config/compiler/BUILD.gn;l=1170-1239;drc=ab531c265c533cba1c2f6d8240cc0bf7679f605a [2] https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILD.gn;l=145-216;drc=f6d705f0937c778d5d5f807a4580113612b02f5a Change-Id: I17708102c03d6488d68c8571b6e9343191fd47de Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/47461 Reviewed-by: Wyatt Hepler <hepler@google.com> Commit-Queue: Michael Spang <spang@google.com>
diff --git a/docs/module_structure.rst b/docs/module_structure.rst index dc2e4b0..e22bf4e 100644 --- a/docs/module_structure.rst +++ b/docs/module_structure.rst
@@ -320,7 +320,7 @@ config("set_options_in_header_file") { cflags = [ "-include", - rebase_path("my_config_overrides.h"), + rebase_path("my_config_overrides.h", root_build_dir), ] }
diff --git a/pw_arduino_build/arduino.gni b/pw_arduino_build/arduino.gni index 0d1704c..f35836d 100644 --- a/pw_arduino_build/arduino.gni +++ b/pw_arduino_build/arduino.gni
@@ -46,7 +46,8 @@ _required_args_message) _arduino_selected_core_path = - rebase_path("$pw_arduino_build_CORE_PATH/$pw_arduino_build_CORE_NAME") + rebase_path("$pw_arduino_build_CORE_PATH/$pw_arduino_build_CORE_NAME", + root_build_dir) arduino_builder_script = get_path_info("py/pw_arduino_build/__main__.py", "abspath") @@ -60,7 +61,8 @@ pw_arduino_build_PACKAGE_NAME + " list-boards") _compiler_path_override = - rebase_path(getenv("_PW_ACTUAL_ENVIRONMENT_ROOT") + "/cipd/pigweed/bin") + rebase_path(getenv("_PW_ACTUAL_ENVIRONMENT_ROOT") + "/cipd/pigweed/bin", + root_build_dir) arduino_core_library_path = "$_arduino_selected_core_path/hardware/" + "$pw_arduino_build_PACKAGE_NAME/libraries" @@ -75,13 +77,13 @@ # Save config files to "out/arduino_debug/gen/arduino_builder_config.json" "--config-file", - rebase_path(root_gen_dir) + "/arduino_builder_config.json", + rebase_path(root_gen_dir, root_build_dir) + "/arduino_builder_config.json", "--save-config", ] arduino_board_args = [ "--build-path", - rebase_path(root_build_dir), + ".", "--board", pw_arduino_build_BOARD, ]
diff --git a/pw_bloat/bloat.gni b/pw_bloat/bloat.gni index bb22417..6d79cfb 100644 --- a/pw_bloat/bloat.gni +++ b/pw_bloat/bloat.gni
@@ -116,9 +116,10 @@ # Allow each binary to override the global bloaty config. if (defined(binary.bloaty_config)) { - _bloaty_configs += [ rebase_path(binary.bloaty_config) ] + _bloaty_configs += [ rebase_path(binary.bloaty_config, root_build_dir) ] } else { - _bloaty_configs += [ rebase_path(pw_bloat_BLOATY_CONFIG) ] + _bloaty_configs += + [ rebase_path(pw_bloat_BLOATY_CONFIG, root_build_dir) ] } _binary_path += ";" + "<TARGET_FILE($_binary_base)>" @@ -131,7 +132,7 @@ "--bloaty-config", string_join(";", _bloaty_configs), "--out-dir", - rebase_path(target_gen_dir), + rebase_path(target_gen_dir, root_build_dir), "--target", target_name, "--title", @@ -165,7 +166,7 @@ } script = "$dir_pw_bloat/py/pw_bloat/no_bloaty.py" python_deps = [ "$dir_pw_bloat/py" ] - args = [ rebase_path(_doc_rst_output) ] + args = [ rebase_path(_doc_rst_output, root_build_dir) ] outputs = [ _doc_rst_output ] } @@ -250,7 +251,8 @@ _linker_script_target_name = "${_prefix}_linker_script" config(_linker_script_target_name) { if (defined(_toolchain.linker_script)) { - ldflags = [ "-T" + rebase_path(_toolchain.linker_script) ] + ldflags = + [ "-T" + rebase_path(_toolchain.linker_script, root_build_dir) ] inputs = [ _toolchain.linker_script ] } else { ldflags = [] @@ -327,7 +329,7 @@ } script = "$dir_pw_bloat/py/pw_bloat/no_toolchains.py" python_deps = [ "$dir_pw_bloat/py" ] - args = [ rebase_path(_doc_rst_output) ] + args = [ rebase_path(_doc_rst_output, root_build_dir) ] outputs = [ _doc_rst_output ] } }
diff --git a/pw_build/docs.rst b/pw_build/docs.rst index db3725d..7bf075b 100644 --- a/pw_build/docs.rst +++ b/pw_build/docs.rst
@@ -162,8 +162,6 @@ specifying ``outputs``. If ``stamp`` is true, a generic output file is used. If ``stamp`` is a file path, that file is used as a stamp file. Like any output file, ``stamp`` must be in the build directory. Defaults to false. -* ``directory``: Optional path. Change to this directory before executing the - command. Paths in arguments may need to be adjusted. * ``environment``: Optional list of strings. Environment variables to set, passed as NAME=VALUE strings. @@ -208,7 +206,7 @@ ``TARGET_FILE`` only resolves GN target labels to their outputs. To resolve paths generally, use the standard GN approach of applying the - ``rebase_path(path)`` function. With default arguments, ``rebase_path`` + ``rebase_path(path, root_build_dir)`` function. This function converts the provided GN path or list of paths to be relative to the build directory, from which all build commands and scripts are executed. @@ -266,7 +264,7 @@ script = "py/postprocess_binary.py" args = [ "--database", - rebase_path("my/database.csv"), + rebase_path("my/database.csv", root_build_dir), "--binary=<TARGET_FILE(//firmware/images:main)>", ] stamp = true
diff --git a/pw_build/error.gni b/pw_build/error.gni index a7c0e69..653b4a9 100644 --- a/pw_build/error.gni +++ b/pw_build/error.gni
@@ -41,9 +41,9 @@ "--message", _message, "--root", - rebase_path("//"), + rebase_path("//", root_build_dir), "--out", - rebase_path(root_build_dir), + ".", ] # This output file is never created.
diff --git a/pw_build/exec.gni b/pw_build/exec.gni index d2b4e69..fc6a5f9 100644 --- a/pw_build/exec.gni +++ b/pw_build/exec.gni
@@ -72,14 +72,14 @@ if (defined(invoker.env_file)) { _script_args += [ "--env-file", - rebase_path(invoker.env_file), + rebase_path(invoker.env_file, root_build_dir), ] } if (defined(invoker.args_file)) { _script_args += [ "--args-file", - rebase_path(invoker.args_file), + rebase_path(invoker.args_file, root_build_dir), ] if (defined(invoker.skip_empty_args) && invoker.skip_empty_args) {
diff --git a/pw_build/go.gni b/pw_build/go.gni index 49230f2..eadb93b 100644 --- a/pw_build/go.gni +++ b/pw_build/go.gni
@@ -149,7 +149,7 @@ args = [ "build", "-o", - rebase_path(target_out_dir), + rebase_path(target_out_dir, root_build_dir), invoker.package, ] deps = [
diff --git a/pw_build/host_tool.gni b/pw_build/host_tool.gni index cac3f23..b5a1ffc 100644 --- a/pw_build/host_tool.gni +++ b/pw_build/host_tool.gni
@@ -34,9 +34,9 @@ "--src", "<TARGET_FILE(${invoker.tool})>", "--dst", - rebase_path("$root_out_dir/host_tools"), + rebase_path("$root_out_dir/host_tools", root_build_dir), "--out-root", - rebase_path(root_out_dir), + rebase_path(root_out_dir, root_build_dir), ] if (defined(invoker.name) && invoker.name != "") {
diff --git a/pw_build/linker_script.gni b/pw_build/linker_script.gni index 7ba64ac..0cf681b 100644 --- a/pw_build/linker_script.gni +++ b/pw_build/linker_script.gni
@@ -73,7 +73,7 @@ # Treat the following file as a C file. "-x", "c", - rebase_path(invoker.linker_script), + rebase_path(invoker.linker_script, root_build_dir), ] # Include any explicitly listed c flags. @@ -91,7 +91,7 @@ # Set output file. args += [ "-o", - rebase_path(_final_linker_script), + rebase_path(_final_linker_script, root_build_dir), ] outputs = [ _final_linker_script ] } @@ -103,7 +103,7 @@ if (!defined(invoker.ldflags)) { ldflags = [] } - ldflags += [ "-T" + rebase_path(_final_linker_script) ] + ldflags += [ "-T" + rebase_path(_final_linker_script, root_build_dir) ] } # The target that adds the linker script config to this library and everything
diff --git a/pw_build/mirror_tree.gni b/pw_build/mirror_tree.gni index 5e78de8..6091738 100644 --- a/pw_build/mirror_tree.gni +++ b/pw_build/mirror_tree.gni
@@ -47,9 +47,9 @@ _args = [ "--source-root", - rebase_path(_root), + rebase_path(_root, root_build_dir), "--directory", - rebase_path(invoker.directory), + rebase_path(invoker.directory, root_build_dir), ] _deps = [] @@ -75,7 +75,8 @@ _deps += [ ":$target_name._path_list" ] _args += [ "--path-file" ] + - rebase_path(get_target_outputs(":$target_name._path_list")) + rebase_path(get_target_outputs(":$target_name._path_list"), + root_build_dir) } pw_python_action(target_name) { @@ -85,7 +86,7 @@ outputs = [] if (defined(invoker.sources)) { - args += rebase_path(invoker.sources) + args += rebase_path(invoker.sources, root_build_dir) foreach(path, rebase_path(invoker.sources, _root)) { outputs += [ "${invoker.directory}/$path" ]
diff --git a/pw_build/py/pw_build/generate_python_package.py b/pw_build/py/pw_build/generate_python_package.py index e70ce71..2ce4d62 100644 --- a/pw_build/py/pw_build/generate_python_package.py +++ b/pw_build/py/pw_build/generate_python_package.py
@@ -105,7 +105,8 @@ # Add all non-source files to package data. for file in (f for f in files if f.suffix != '.py'): - pkg = root / file.parent + pkg = file.parent + package_name = pkg.relative_to(root).as_posix().replace('/', '.') pkg_data[package_name].add(file.name)
diff --git a/pw_build/py/pw_build/python_runner.py b/pw_build/py/pw_build/python_runner.py index 15ce00e..5c38717 100755 --- a/pw_build/py/pw_build/python_runner.py +++ b/pw_build/py/pw_build/python_runner.py
@@ -41,20 +41,17 @@ type=Path, required=True, help=('Path to the root of the GN tree; ' - 'value of rebase_path("//")')) + 'value of rebase_path("//", root_build_dir)')) parser.add_argument('--current-path', type=Path, required=True, - help='Value of rebase_path(".")') + help='Value of rebase_path(".", root_build_dir)') parser.add_argument('--default-toolchain', required=True, help='Value of default_toolchain') parser.add_argument('--current-toolchain', required=True, help='Value of current_toolchain') - parser.add_argument('--directory', - type=Path, - help='Execute the command from this directory') parser.add_argument('--module', help='Run this module instead of a script') parser.add_argument('--env', action='append', @@ -164,7 +161,7 @@ _MAIN_ARTIFACTS = '', '.elf', '.a', '.so', '.dylib', '.exe', '.lib', '.dll' -def _get_artifact(build_dir: Path, entries: List[str]) -> _Artifact: +def _get_artifact(entries: List[str]) -> _Artifact: """Attempts to resolve which artifact to use if there are multiple. Selects artifacts based on extension. This will not work if a toolchain @@ -173,19 +170,19 @@ assert entries, "There should be at least one entry here!" if len(entries) == 1: - return _Artifact(build_dir / entries[0], {}) + return _Artifact(Path(entries[0]), {}) filtered = [p for p in entries if Path(p).suffix in _MAIN_ARTIFACTS] if len(filtered) == 1: - return _Artifact(build_dir / filtered[0], {}) + return _Artifact(Path(filtered[0]), {}) raise ExpressionError( f'Expected 1, but found {len(filtered)} artifacts, after filtering for ' f'extensions {", ".join(repr(e) for e in _MAIN_ARTIFACTS)}: {entries}') -def _parse_build_artifacts(build_dir: Path, fd) -> Iterator[_Artifact]: +def _parse_build_artifacts(fd) -> Iterator[_Artifact]: """Partially parses the build statements in a Ninja file.""" lines = iter(fd) @@ -212,7 +209,7 @@ else: match = _GN_NINJA_BUILD_STATEMENT.match(line) if match: - artifact = _get_artifact(build_dir, match.group(1).split()) + artifact = _get_artifact(match.group(1).split()) line = next_line() @@ -220,7 +217,7 @@ yield artifact -def _search_target_ninja(ninja_file: Path, paths: GnPaths, +def _search_target_ninja(ninja_file: Path, target: Label) -> Tuple[Optional[Path], List[Path]]: """Parses the main output file and object files from <target>.ninja.""" @@ -230,16 +227,16 @@ _LOG.debug('Parsing target Ninja file %s for %s', ninja_file, target) with ninja_file.open() as fd: - for path, variables in _parse_build_artifacts(paths.build, fd): + for path, variables in _parse_build_artifacts(fd): # Older GN used .stamp files when there is no build artifact. if path.suffix == '.stamp': continue if variables: assert not artifact, f'Multiple artifacts for {target}!' - artifact = path + artifact = Path(path) else: - objects.append(path) + objects.append(Path(path)) return artifact, objects @@ -271,7 +268,7 @@ if line.startswith(statement): output_files = line[len(statement):].strip().split() if len(output_files) == 1: - return paths.build / output_files[0] + return Path(output_files[0]) break @@ -283,7 +280,7 @@ target: Label) -> Tuple[bool, Optional[Path], List[Path]]: ninja_file = target.out_dir / f'{target.name}.ninja' if ninja_file.exists(): - return (True, *_search_target_ninja(ninja_file, paths, target)) + return (True, *_search_target_ninja(ninja_file, target)) ninja_file = paths.build / target.toolchain_name() / 'toolchain.ninja' if ninja_file.exists(): @@ -366,7 +363,7 @@ if target.artifact is None: raise ExpressionError(f'Target {target} has no output file!') - if Path(target.artifact).exists(): + if paths.build.joinpath(target.artifact).exists(): yield _ArgAction.APPEND, str(target.artifact) return @@ -441,7 +438,6 @@ def main( gn_root: Path, current_path: Path, - directory: Optional[Path], original_cmd: List[str], default_toolchain: str, current_toolchain: str, @@ -470,7 +466,7 @@ if module is not None: command += ['-m', module] - run_args: dict = dict(cwd=directory) + run_args: dict = dict() if env is not None: environment = os.environ.copy()
diff --git a/pw_build/py/python_runner_test.py b/pw_build/py/python_runner_test.py index 1ea69b0..f9e188c 100755 --- a/pw_build/py/python_runner_test.py +++ b/pw_build/py/python_runner_test.py
@@ -194,6 +194,8 @@ self._tempdir, self._outdir, self._paths = _create_ninja_files( NINJA_SOURCE_SET) + self._rel_outdir = self._outdir.relative_to(self._paths.build) + def tearDown(self): self._tempdir.cleanup() @@ -207,22 +209,22 @@ self.assertTrue(target.generated) self.assertEqual( set(target.object_files), { - self._outdir / 'fake_source_set.file_a.cc.o', - self._outdir / 'fake_source_set.file_b.c.o', + self._rel_outdir / 'fake_source_set.file_a.cc.o', + self._rel_outdir / 'fake_source_set.file_b.c.o', }) def test_executable_object_files(self): target = TargetInfo(self._paths, '//fake_module:fake_test') self.assertEqual( set(target.object_files), { - self._outdir / 'fake_test.fake_test.cc.o', - self._outdir / 'fake_test.fake_test_c.c.o', + self._rel_outdir / 'fake_test.fake_test.cc.o', + self._rel_outdir / 'fake_test.fake_test_c.c.o', }) def test_executable_artifact(self): target = TargetInfo(self._paths, '//fake_module:fake_test') self.assertEqual(target.artifact, - self._outdir / 'test' / 'fake_test.elf') + self._rel_outdir / 'test' / 'fake_test.elf') def test_non_existent_target(self): target = TargetInfo(self._paths, @@ -243,6 +245,8 @@ self._tempdir, self._outdir, self._paths = _create_ninja_files( NINJA_SOURCE_SET_STAMP) + self._rel_outdir = self._outdir.relative_to(self._paths.build) + class ExpandExpressionsTest(unittest.TestCase): """Tests expansion of expressions like <TARGET_FILE(//foo)>.""" @@ -260,7 +264,7 @@ path.touch() else: assert not path.exists() - return str(path) + return str(path.relative_to(self._paths.build)) def test_empty(self): self.assertEqual(list(expand_expressions(self._paths, '')), ['']) @@ -389,6 +393,8 @@ self._tempdir, self._outdir, self._paths = _create_ninja_files( NINJA_SOURCE_SET_STAMP) + self._rel_outdir = self._outdir.relative_to(self._paths.build) + if __name__ == '__main__': unittest.main()
diff --git a/pw_build/python.gni b/pw_build/python.gni index b7bf71a..217a7f8 100644 --- a/pw_build/python.gni +++ b/pw_build/python.gni
@@ -64,17 +64,17 @@ ] if (defined(invoker.mypy_ini)) { - args += [ "--config-file=" + rebase_path(invoker.mypy_ini) ] + args += + [ "--config-file=" + rebase_path(invoker.mypy_ini, root_build_dir) ] inputs = [ invoker.mypy_ini ] } - args += rebase_path(invoker.sources) + args += rebase_path(invoker.sources, root_build_dir) # Use this environment variable to force mypy to colorize output. # See https://github.com/python/mypy/issues/7771 environment = [ "MYPY_FORCE_COLOR=1" ] - directory = invoker.directory stamp = true deps = invoker.deps @@ -92,13 +92,13 @@ pw_python_action_foreach(target_name) { module = "pylint" args = [ - rebase_path(".") + "/{{source_target_relative}}", + rebase_path(".", root_build_dir) + "/{{source_target_relative}}", "--jobs=1", "--output-format=colorized", ] if (defined(invoker.pylintrc)) { - args += [ "--rcfile=" + rebase_path(invoker.pylintrc) ] + args += [ "--rcfile=" + rebase_path(invoker.pylintrc, root_build_dir) ] inputs = [ invoker.pylintrc ] } @@ -108,7 +108,6 @@ } sources = invoker.sources - directory = invoker.directory stamp = "$target_gen_dir/{{source_target_relative}}.pylint.passed" @@ -151,10 +150,10 @@ # generate_setup is required in place of setup if proto_library is used. # static_analysis: List of static analysis tools to run; "*" (default) runs # all tools. The supported tools are "mypy" and "pylint". -# pylintrc: Optional path to a pylintrc configuration file to use. If not -# provided, Pylint's default rcfile search is used. Pylint is executed -# from the package's setup directory, so pylintrc files in that directory -# will take precedence over others. +# pylintrc: Path to a pylintrc configuration file to use. If not +# provided, Pylint's default rcfile search is used. As this may +# use the the local user's configuration file, it is highly +# recommended to pass this option to specify the rcfile explicitly. # mypy_ini: Optional path to a mypy configuration file to use. If not # provided, mypy's default configuration file search is used. mypy is # executed from the package's setup directory, so mypy.ini files in that @@ -346,10 +345,10 @@ "--label", get_label_info(":$target_name", "label_no_toolchain"), "--generated-root", - rebase_path(_setup_dir), + rebase_path(_setup_dir, root_build_dir), "--setup-json", - rebase_path("$_setup_dir/setup.json"), - ] + rebase_path(_sources) + rebase_path("$_setup_dir/setup.json", root_build_dir), + ] + rebase_path(_sources, root_build_dir) # Pass in the .json information files for the imported proto libraries. foreach(proto, _import_protos) { @@ -359,7 +358,7 @@ get_label_info(_label, "name") + ".json" args += [ "--proto-library", - rebase_path(_file), + rebase_path(_file, root_build_dir), ] } @@ -406,7 +405,7 @@ args += [ "--editable" ] } - args += [ rebase_path(_setup_dir) ] + args += [ rebase_path(_setup_dir, root_build_dir) ] stamp = true @@ -431,12 +430,13 @@ module = "build" - args = [ - rebase_path(_setup_dir), - "--wheel", - "--no-isolation", - "--outdir", - ] + rebase_path(metadata.pw_python_package_wheels) + args = + [ + rebase_path(_setup_dir, root_build_dir), + "--wheel", + "--no-isolation", + "--outdir", + ] + rebase_path(metadata.pw_python_package_wheels, root_build_dir) deps = [ ":${invoker.target_name}" ] foreach(dep, _python_deps) { @@ -509,12 +509,6 @@ deps = _test_install_deps python_deps = _python_deps - if (defined(_setup_dir)) { - directory = rebase_path(_setup_dir) - } else { - directory = rebase_path(".") - } - _optional_variables = [ "mypy_ini", "pylintrc", @@ -729,7 +723,7 @@ foreach(_requirements_file, inputs) { args += [ "--requirement", - rebase_path(_requirements_file), + rebase_path(_requirements_file, root_build_dir), ] }
diff --git a/pw_build/python_action.gni b/pw_build/python_action.gni index fe31801..6ef48a4 100644 --- a/pw_build/python_action.gni +++ b/pw_build/python_action.gni
@@ -32,10 +32,6 @@ # creating their own placeholder file. If true, a generic file # is used. If false or not set, no file is touched. # -# directory The directory from which to execute the Python script. Paths -# in args may need to be adjusted to be relative to this -# directory. -# # environment Environment variables to set, passed as a list of NAME=VALUE # strings. # @@ -60,23 +56,16 @@ # GN root directory relative to the build directory (in which the runner # script is invoked). "--gn-root", - rebase_path("//"), + rebase_path("//", root_build_dir), # Current directory, used to resolve relative paths. "--current-path", - rebase_path("."), + rebase_path(".", root_build_dir), "--default-toolchain=$default_toolchain", "--current-toolchain=$current_toolchain", ] - if (defined(invoker.directory)) { - _script_args += [ - "--directory", - rebase_path(invoker.directory), - ] - } - if (defined(invoker.environment)) { foreach(variable, invoker.environment) { _script_args += [ "--env=$variable" ] @@ -112,7 +101,7 @@ _outputs += [ _stamp_file ] _script_args += [ "--touch", - rebase_path(_stamp_file), + rebase_path(_stamp_file, root_build_dir), ] } @@ -134,7 +123,7 @@ _script_args += [ "--" ] if (defined(invoker.script)) { - _script_args += [ rebase_path(invoker.script) ] + _script_args += [ rebase_path(invoker.script, root_build_dir) ] } if (defined(invoker.args)) {
diff --git a/pw_build/python_dist.gni b/pw_build/python_dist.gni index db41d1e..9514b94 100644 --- a/pw_build/python_dist.gni +++ b/pw_build/python_dist.gni
@@ -58,11 +58,11 @@ args = [ "--prefix", - rebase_path(root_build_dir), + rebase_path(root_build_dir, root_build_dir), "--suffix", - rebase_path(_wheel_paths_path), + rebase_path(_wheel_paths_path, root_build_dir), "--out_dir", - rebase_path("${target_out_dir}/python_wheels"), + rebase_path("${target_out_dir}/python_wheels", root_build_dir), ] stamp = true
diff --git a/pw_build/zip.gni b/pw_build/zip.gni index 653b0cd..60b3aa0 100644 --- a/pw_build/zip.gni +++ b/pw_build/zip.gni
@@ -94,7 +94,7 @@ script = "$dir_pw_build/py/pw_build/zip.py" args = [ "--out_filename" ] - args += [ rebase_path(invoker.output) ] + args += [ rebase_path(invoker.output, root_build_dir) ] inputs = [] args += [ "--input_list" ] @@ -107,8 +107,8 @@ input_list = [] input_list = string_split(input, _delimiter) - input_list[0] = rebase_path(input_list[0]) inputs += [ input_list[0] ] + input_list[0] = rebase_path(input_list[0], root_build_dir) # Pass rebased and delimited path to script. args += [ string_join(_delimiter, input_list) ] @@ -122,7 +122,7 @@ dir = string_replace(dir, " $_delimiter", _delimiter) dir = string_replace(dir, "$_delimiter ", _delimiter) - args += [ rebase_path(dir) ] + args += [ rebase_path(dir, root_build_dir) ] } }
diff --git a/pw_docgen/docs.gni b/pw_docgen/docs.gni index 50bf8d6..5759946 100644 --- a/pw_docgen/docs.gni +++ b/pw_docgen/docs.gni
@@ -97,18 +97,19 @@ "--gn-gen-root", rebase_path(root_gen_dir, root_build_dir) + "/", "--sphinx-build-dir", - rebase_path("$target_gen_dir/pw_docgen_tree"), + rebase_path("$target_gen_dir/pw_docgen_tree", root_build_dir), "--conf", - rebase_path(invoker.conf), + rebase_path(invoker.conf, root_build_dir), "--out-dir", - rebase_path(invoker.output_directory), + rebase_path(invoker.output_directory, root_build_dir), "--metadata", ] # Metadata JSON file path. - _script_args += rebase_path(get_target_outputs(":$_metadata_file_target")) + _script_args += + rebase_path(get_target_outputs(":$_metadata_file_target"), root_build_dir) - _script_args += rebase_path(invoker.sources) + _script_args += rebase_path(invoker.sources, root_build_dir) if (pw_docgen_BUILD_DOCS) { pw_python_action(target_name) {
diff --git a/pw_hdlc/BUILD.gn b/pw_hdlc/BUILD.gn index 41e5e4b..7ee98c1 100644 --- a/pw_hdlc/BUILD.gn +++ b/pw_hdlc/BUILD.gn
@@ -125,7 +125,7 @@ pw_python_action("generate_decoder_test") { outputs = [ "$target_gen_dir/generated_decoder_test.cc" ] script = "py/decode_test.py" - args = [ "--generate-cc-test" ] + rebase_path(outputs) + args = [ "--generate-cc-test" ] + rebase_path(outputs, root_build_dir) python_deps = [ "$dir_pw_build/py", "py",
diff --git a/pw_polyfill/BUILD.gn b/pw_polyfill/BUILD.gn index b173e06..6292b2d 100644 --- a/pw_polyfill/BUILD.gn +++ b/pw_polyfill/BUILD.gn
@@ -40,7 +40,7 @@ # without requiring a #include. This allows the use of newer C++ language # features in older C++ versions without an explicit include. "-include", - rebase_path("language_features.h"), + rebase_path("language_features.h", root_build_dir), ] visibility = [ ":*" ] }
diff --git a/pw_protobuf_compiler/proto.gni b/pw_protobuf_compiler/proto.gni index 241c666..cc0cb27 100644 --- a/pw_protobuf_compiler/proto.gni +++ b/pw_protobuf_compiler/proto.gni
@@ -49,7 +49,8 @@ } _includes = - rebase_path(get_target_outputs(":${invoker.base_target}._includes")) + rebase_path(get_target_outputs(":${invoker.base_target}._includes"), + root_build_dir) pw_python_action("$target_name._gen") { script = @@ -79,15 +80,16 @@ "--include-file", _includes[0], "--compile-dir", - rebase_path(invoker.compile_dir), + rebase_path(invoker.compile_dir, root_build_dir), "--out-dir", - rebase_path(_out_dir), + rebase_path(_out_dir, root_build_dir), "--sources", - ] + rebase_path(invoker.sources) + ] + rebase_path(invoker.sources, root_build_dir) if (defined(invoker.plugin)) { inputs = [ invoker.plugin ] - args += [ "--plugin-path=" + rebase_path(invoker.plugin) ] + args += + [ "--plugin-path=" + rebase_path(invoker.plugin, root_build_dir) ] } if (defined(invoker.outputs)) { @@ -104,8 +106,9 @@ # Output a .json file with information about this proto library. _proto_info = { label = get_label_info(":${invoker.target_name}", "label_no_toolchain") - protoc_outputs = rebase_path(get_target_outputs(":$target_name._gen")) - root = rebase_path(_out_dir) + protoc_outputs = + rebase_path(get_target_outputs(":$target_name._gen"), root_build_dir) + root = rebase_path(_out_dir, root_build_dir) package = invoker.package nested_in_python_package = "" @@ -118,7 +121,8 @@ foreach(dep, invoker.deps) { dependencies += rebase_path([ get_label_info(dep, "target_gen_dir") + "/" + - get_label_info(dep, "name") + ".json" ]) + get_label_info(dep, "name") + ".json" ], + root_build_dir) } } write_file("$target_gen_dir/$target_name.json", _proto_info, "json") @@ -494,7 +498,7 @@ # Indicate this library's base directory for its dependents. metadata = { - protoc_includes = [ rebase_path(_common.compile_dir) ] + protoc_includes = [ rebase_path(_common.compile_dir, root_build_dir) ] } }
diff --git a/pw_rpc/BUILD.gn b/pw_rpc/BUILD.gn index 9f4a95f..bc82b77 100644 --- a/pw_rpc/BUILD.gn +++ b/pw_rpc/BUILD.gn
@@ -232,7 +232,7 @@ outputs = [ "$target_gen_dir/generated_ids_test.cc" ] script = "py/tests/ids_test.py" - args = [ "--generate-cc-test" ] + rebase_path(outputs) + args = [ "--generate-cc-test" ] + rebase_path(outputs, root_build_dir) python_deps = [ "$dir_pw_build/py", "py",
diff --git a/pw_tokenizer/BUILD.gn b/pw_tokenizer/BUILD.gn index 520beb2..2500f00 100644 --- a/pw_tokenizer/BUILD.gn +++ b/pw_tokenizer/BUILD.gn
@@ -44,7 +44,7 @@ if (current_os == "") { ldflags = [ "-T", - rebase_path("pw_tokenizer_linker_sections.ld"), + rebase_path("pw_tokenizer_linker_sections.ld", root_build_dir), ] } else if (current_os == "linux" && !pw_toolchain_OSS_FUZZ_ENABLED) { # When building for Linux, the linker provides a default linker script. @@ -53,10 +53,11 @@ # default linker script instead of overriding it. ldflags = [ "-T", - rebase_path("add_tokenizer_sections_to_default_script.ld"), - "-L", - rebase_path("."), + rebase_path("add_tokenizer_sections_to_default_script.ld", + root_build_dir), ] + lib_dirs = [ "." ] + inputs += [ "add_tokenizer_sections_to_default_script.ld" ] } visibility = [ ":*" ]
diff --git a/pw_tokenizer/database.gni b/pw_tokenizer/database.gni index 81d6832..2508470 100644 --- a/pw_tokenizer/database.gni +++ b/pw_tokenizer/database.gni
@@ -119,9 +119,9 @@ args += [ "--database", - rebase_path(_database), + rebase_path(_database, root_build_dir), ] - args += rebase_path(_input_databases) + args += rebase_path(_input_databases, root_build_dir) foreach(target, _targets) { args += [ "<TARGET_FILE($target)>$_domain" ] @@ -134,9 +134,8 @@ } if (defined(invoker.optional_paths)) { - _paths = rebase_path(invoker.optional_paths) - _out_dir = rebase_path(root_build_dir) - assert(filter_include(_paths, [ "$_out_dir/*" ]) == _paths, + _paths = rebase_path(invoker.optional_paths, root_build_dir) + assert(filter_include(_paths, [ "../*" ]) == [], "Paths in 'optional_paths' must be in the out directory. Use " + "'input_databases' for files in the source tree.") args += _paths
diff --git a/pw_toolchain/arm_clang/clang_config.gni b/pw_toolchain/arm_clang/clang_config.gni index 2c71a2f..de212b9 100644 --- a/pw_toolchain/arm_clang/clang_config.gni +++ b/pw_toolchain/arm_clang/clang_config.gni
@@ -12,7 +12,8 @@ # License for the specific language governing permissions and limitations under # the License. -_script_path = rebase_path("../py/pw_toolchain/clang_arm_toolchain.py") +_script_path = + get_path_info("../py/pw_toolchain/clang_arm_toolchain.py", "abspath") # This template generates a config that can be used to target ARM cores using # a clang compiler.
diff --git a/pw_toolchain/default/BUILD.gn b/pw_toolchain/default/BUILD.gn index e961c97..e8ad524 100644 --- a/pw_toolchain/default/BUILD.gn +++ b/pw_toolchain/default/BUILD.gn
@@ -24,5 +24,6 @@ # If the user tries to build a target with the default toolchain, run a script # printing out the error. command = "python " + - rebase_path("$dir_pw_toolchain/py/pw_toolchain/bad_toolchain.py") + rebase_path("$dir_pw_toolchain/py/pw_toolchain/bad_toolchain.py", + root_build_dir) }
diff --git a/pw_toolchain/non_c_toolchain.gni b/pw_toolchain/non_c_toolchain.gni index 04e7013..53f7bdd 100644 --- a/pw_toolchain/non_c_toolchain.gni +++ b/pw_toolchain/non_c_toolchain.gni
@@ -41,14 +41,15 @@ _command = string_join(" ", [ "python", - rebase_path("$dir_pw_build/py/pw_build/error.py"), + rebase_path("$dir_pw_build/py/pw_build/error.py", + root_build_dir), "--message \"$_message\"", "--target", _label, "--root", - rebase_path("//"), + rebase_path("//", root_build_dir), "--out", - rebase_path(root_build_dir), + ".", ]) if (defined(invoker.command)) {
diff --git a/pw_toolchain/py/pw_toolchain/clang_arm_toolchain.py b/pw_toolchain/py/pw_toolchain/clang_arm_toolchain.py index 7494727..5c0cf61 100644 --- a/pw_toolchain/py/pw_toolchain/clang_arm_toolchain.py +++ b/pw_toolchain/py/pw_toolchain/clang_arm_toolchain.py
@@ -32,6 +32,7 @@ import argparse import sys +import os import subprocess from pathlib import Path @@ -88,8 +89,10 @@ def get_compiler_info(cflags: List[str]) -> Dict[str, str]: compiler_info: Dict[str, str] = {} - compiler_info['gcc_libs_dir'] = str(get_gcc_lib_dir(cflags)) - compiler_info['sysroot'] = _compiler_info_command('-print-sysroot', cflags) + compiler_info['gcc_libs_dir'] = os.path.relpath( + str(get_gcc_lib_dir(cflags)), ".") + compiler_info['sysroot'] = os.path.relpath( + _compiler_info_command('-print-sysroot', cflags), ".") compiler_info['version'] = _compiler_info_command('-dumpversion', cflags) compiler_info['multi_dir'] = _compiler_info_command( '-print-multi-directory', cflags)
diff --git a/pw_toolchain/universal_tools.gni b/pw_toolchain/universal_tools.gni index 820276d..eafc0e8 100644 --- a/pw_toolchain/universal_tools.gni +++ b/pw_toolchain/universal_tools.gni
@@ -19,8 +19,8 @@ cp_command = "cp -af {{source}} {{output}}" # Use python script in absence of cp command. - copy_tool_path = - rebase_path(dir_pw_toolchain) + "/py/pw_toolchain/copy_with_metadata.py" + copy_tool_path = rebase_path(dir_pw_toolchain, root_build_dir) + + "/py/pw_toolchain/copy_with_metadata.py" fallback_command = "python $copy_tool_path {{source}} {{output}}" command = "cmd /c \"($cp_command > NUL 2>&1) || ($fallback_command)\""
diff --git a/pw_unit_test/py/pw_unit_test/test_runner.py b/pw_unit_test/py/pw_unit_test/test_runner.py index 0d395ae..52e69b6 100644 --- a/pw_unit_test/py/pw_unit_test/test_runner.py +++ b/pw_unit_test/py/pw_unit_test/test_runner.py
@@ -23,6 +23,7 @@ import subprocess import sys +from pathlib import Path from typing import Dict, Iterable, List, Optional, Sequence, Set, Tuple import pw_cli.log @@ -136,7 +137,13 @@ test_counter = f'Test {idx:{len(total)}}/{total}' _LOG.info('%s: [ RUN] %s', test_counter, test.name) - command = [self._executable, test.file_path, *self._args] + + # Convert POSIX to native directory seperators as GN produces '/' + # but the Windows test runner needs '\\'. + command = [ + str(Path(self._executable)), + str(Path(test.file_path)), *self._args + ] if self._executable.endswith('.py'): command.insert(0, sys.executable)
diff --git a/pw_unit_test/test.gni b/pw_unit_test/test.gni index 02d9e26..fc112cf 100644 --- a/pw_unit_test/test.gni +++ b/pw_unit_test/test.gni
@@ -185,7 +185,7 @@ python_deps = [ "$dir_pw_cli/py" ] args = [ "--runner", - rebase_path(pw_unit_test_AUTOMATIC_RUNNER), + rebase_path(pw_unit_test_AUTOMATIC_RUNNER, root_build_dir), "--test", "<TARGET_FILE(:$_test_to_run)>", ]
diff --git a/targets/arduino/BUILD.gn b/targets/arduino/BUILD.gn index 7217dff..0032273 100644 --- a/targets/arduino/BUILD.gn +++ b/targets/arduino/BUILD.gn
@@ -32,7 +32,7 @@ if (current_toolchain != default_toolchain) { config("arduino_build") { # Debug: Print out arduinobuilder.py args - # print(string_join(" ", [rebase_path(arduino_builder_script)] + arduino_show_command_args)) + # print(string_join(" ", [rebase_path(arduino_builder_script, root_build_dir)] + arduino_show_command_args)) # Run prebuilds # TODO(tonymd) This only needs to be run once but it's happening multiple times.
diff --git a/targets/arduino/target_docs.rst b/targets/arduino/target_docs.rst index a6f6b0b..379da1b 100644 --- a/targets/arduino/target_docs.rst +++ b/targets/arduino/target_docs.rst
@@ -217,7 +217,7 @@ _library_args = [ "--library-path", - rebase_path(arduino_core_library_path), + rebase_path(arduino_core_library_path, root_build_dir), "--library-names", "Time", "Wire",
diff --git a/third_party/nanopb/BUILD.gn b/third_party/nanopb/BUILD.gn index 35620ac..c718d9f 100644 --- a/third_party/nanopb/BUILD.gn +++ b/third_party/nanopb/BUILD.gn
@@ -54,7 +54,7 @@ sources = [ "generate_nanopb_proto.py" ] pylintrc = "$dir_pigweed/.pylintrc" action = { - args = [ rebase_path(dir_pw_third_party_nanopb) ] + args = [ rebase_path(dir_pw_third_party_nanopb, root_build_dir) ] stamp = true } }