Repository navigation
feat: mcpp run and mcpp test name a script's missing #! interpreter - #923
Open
NopeCharon wants to merge 1 commit into
Open
NopeCharon wants to merge 1 commit into
NopeCharon wants to merge 1 commit into
Conversation
…eter An artefact the run slot executes directly can be a script: emsdk's JavaScript launcher begins `#!/usr/bin/env node`. An emsdk payload installed before its recipe wrote `.mcpp-toolchain.json` names no runner, so the launcher runs through that line, and on a host without `node` on PATH the only output was `/usr/bin/env: 'node': No such file or directory`. mcpp had spawned `env` successfully, so none of its own launcher messages applied, and nothing named the cause or the remedy. mcpp.build.runner_lookup now reads a script's `#!` line as the kernel reads it (parse_script_interpreter, script_interpreter): the interpreter is the first word after `#!`, and through `env` the program is the first word that is neither `-S` nor a `NAME=value` assignment. A form it does not read with certainty (a relative interpreter, any other `env` option, `env` with no program) names no program, so the note never names the wrong one. Windows reads no `#!` line and is skipped. missing_interpreter_note says, when the interpreter is not an executable file or the program `env` would look up is on no directory of the artefact's PATH, which program is missing, that a toolchain payload names its runner in `.mcpp-toolchain.json` and one installed before its recipe wrote that file names none, and the remedy: `mcpp index update`, then `mcpp toolchain remove <spec>` and `mcpp toolchain install <spec>`. It names no toolchain, because which payload built a file is not a fact its first line holds. `mcpp run` prints the note before it executes an artefact with no runner and no execution host, against the PATH the artefact receives; the blank line before the program's output now follows the composed environment so the note stays above it. `mcpp test` prints it once per build, for the first test it executes directly. Neither prints it for `--print-launch`, and `mcpp test` not under `--message-format json`. Tests: five RunnerLookup cases cover the parse (direct, `env`, `env -S` with an assignment, CRLF), the forms that name no program, a missing `env` program and a missing interpreter path, and the cases that stay silent (a found interpreter, a binary, a missing file). docs/20 states the note in both languages in place of "mcpp does not yet explain it". Closes mcpp-community#621
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
An artefact the run slot executes directly can be a script: emsdk's JavaScript launcher begins
#!/usr/bin/env node. An emsdk payload installed before its recipe wrote.mcpp-toolchain.jsonnames no runner, so the launcher runs through that line, and on a host withoutnodeon PATH the only output was/usr/bin/env: 'node': No such file or directory. mcpp had startedenvsuccessfully, so none of its own launcher messages applied.mcpp.build.runner_lookupreads a script's#!line as the kernel reads it (parse_script_interpreter,script_interpreter). The interpreter is the first word after#!. Throughenv, the program is the first word that is neither-Snor aNAME=valueassignment. When the line can't be read with certainty (a relative interpreter, any otherenvoption,envwith no program), no program is named, so the note never names the wrong one. Windows reads no#!line and is skipped.missing_interpreter_noteapplies when the interpreter is not an executable file, or when the programenvwould look up is not on the artefact's PATH. It names the missing program and says that a toolchain payload names its runner in.mcpp-toolchain.json, and that one installed before its recipe wrote that file names none. It then gives the remedy that mcpp run: a script artefact whose interpreter is missing fails without naming the remedy #621 proposes:mcpp index update, thenmcpp toolchain remove <spec>andmcpp toolchain install <spec>. It names no toolchain, because a file's first line does not say which payload built it.mcpp runprints the note before it executes an artefact that has no runner and no execution host. It checks against the PATH the artefact receives (the composedchildEnv, else this invocation's). The blank line before the program's output now comes after the environment is composed, so the note stays above it.mcpp testprints the note once per build, for the first test it executes directly. Neither command prints it under--print-launch, andmcpp testdoes not print it under--message-format json.docs/20-toolchains.mdand its Chinese copy describe the note, replacing "which mcpp does not yet explain (mcpp run: a script artefact whose interpreter is missing fails without naming the remedy #621)".Closes #621.
Criteria
#!line is read as the kernel reads it.RunnerLookup/AShebangNamesItsInterpretercovers a direct interpreter with an argument,env nodewith a CRLF line end, andenv -S NAME=value node --flag.RunnerLookup/AnUncertainShebangNamesNoProgramcovers an ELF header, an empty#!, a relative interpreter,envwith no program,env -iandenv -u X.RunnerLookup/AScriptWhoseInterpreterIsMissingIsNoteduses anenvwhose program is on no directory of the PATH given, then puts the program on that PATH, and the note goes away.RunnerLookup/AMissingInterpreterPathIsNoteduses an absolute interpreter that does not exist.RunnerLookup/AProgramOrAFoundInterpreterIsNotNotedcovers a script whose interpreter exists, a binary and a missing file.tests/unit/test_runner_lookup.cpptogether outside the engine (Apple clang 21,-std=c++23 -Wall -Wextra, with a stand-in formcpplibs.mtest). All 16 RunnerLookup cases pass with no warnings. The engine build, the module form of these tests and the other hosts are left to CI. The wiring inexecute.cppmdid not run locally: it needs a built engine and a script artefact with no runner.check_docs_style.sh,check_docs_structure.sh,check_version_pins.shandcheck_workflow_assertions.pypass locally.Intersections
mcpp runreads the artefact's#!line before it executes it directlychoice.tmpl.empty() && host.prefix.empty(), the same condition the direct-exec branch already uses; no e2e sits there--print-launchdescribes the launch on standard output and starts nothing--print-launch; no test sits thererun_foregroundreplaces the image)run_foreground, and the separator still comes lastmcpp testnotes the first directly executed testTestBuild::interpreterNoted, skipped for--no-run, a host that cannot reach the tests and an invocation already not run#!program is namedRunnerLookup/AnUncertainShebangNamesNoProgramCompatibility
mcpp runandmcpp testprint one morenote:on standard error when a directly executed script's interpreter is missing. Otherwise their output, exit codes and the program's environment are unchanged. A program that starts sees the same streams it did before. No cache key or file format changes.Checks before merging
bash .github/tools/check_docs_style.sh,check_docs_structure.shandcheck_version_pins.shpass.python3 .github/tools/check_workflow_assertions.pypasses (a step asserts what its name says).git log origin/main..HEAD -i --grep='Co-Authored-By'prints nothing.compose one from the branch's commits. Suggested subject:
feat:mcpp runandmcpp testname a script's missing#!interpreter.