mirror of
https://git.yoctoproject.org/meta-arm
synced 2026-07-16 03:47:19 +00:00
arm/lib: Specify the FVP environment variables explicitly
It is sometimes useful to be able to configure the behavior of FVPs using environment variables, e.g. for licensing or plugins. Add a new FVP option: FVP_ENV_PASSTHROUGH, which allows the Bitbake variables to be passed to the environment to be specified explicitly (in a similar way to BB_ENV_PASSTHROUGH). This ensures that: * FVPs launched via runfvp have a reproducable environment * FVPs launched via testimage (which run from an isolated Bitbake task) can receive environment variables Change the self-tests to use cwd instead of PATH to find the mock FVPs, as the PATH environment variable is no longer passed through. Issue-Id: SCM-4964 Signed-off-by: Peter Hoyes <Peter.Hoyes@arm.com> Change-Id: Idf6ac6d41fda4cd5f950bc383c2fc1fa1acdf4e3 Signed-off-by: Jon Mason <jon.mason@arm.com>
This commit is contained in:
@@ -116,6 +116,14 @@ Arbitrary extra arguments that are passed directly to the FVP. For example:
|
|||||||
FVP_EXTRA_ARGS = "--simlimit 60"
|
FVP_EXTRA_ARGS = "--simlimit 60"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `FVP_ENV_PASSTHROUGH`
|
||||||
|
|
||||||
|
The FVP is launched with an isolated set of environment variables. Add the name of a Bitbake variable to this list to pass it through to the FVP environment. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
FVP_ENV_PASSTHROUGH = "ARMLMD_LICENSE_FILE FM_TRACE_PLUGINS"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
[AEM]: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models
|
[AEM]: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models
|
||||||
[FVP]: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms
|
[FVP]: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ FVP_CONSOLE ?= ""
|
|||||||
FVP_CONSOLES[default] ?= "${FVP_CONSOLE}"
|
FVP_CONSOLES[default] ?= "${FVP_CONSOLE}"
|
||||||
# Arbitrary extra arguments
|
# Arbitrary extra arguments
|
||||||
FVP_EXTRA_ARGS ?= ""
|
FVP_EXTRA_ARGS ?= ""
|
||||||
|
# Bitbake variables to pass to the FVP environment
|
||||||
|
FVP_ENV_PASSTHROUGH ?= ""
|
||||||
|
|
||||||
EXTRA_IMAGEDEPENDS += "${FVP_PROVIDER}"
|
EXTRA_IMAGEDEPENDS += "${FVP_PROVIDER}"
|
||||||
|
|
||||||
@@ -66,6 +68,10 @@ python do_write_fvpboot_conf() {
|
|||||||
data["terminals"] = getFlags("FVP_TERMINALS")
|
data["terminals"] = getFlags("FVP_TERMINALS")
|
||||||
data["args"] = shlex.split(d.getVar("FVP_EXTRA_ARGS") or "")
|
data["args"] = shlex.split(d.getVar("FVP_EXTRA_ARGS") or "")
|
||||||
|
|
||||||
|
data["env"] = {}
|
||||||
|
for var in d.getVar("FVP_ENV_PASSTHROUGH").split():
|
||||||
|
data["env"][var] = d.getVar(var)
|
||||||
|
|
||||||
os.makedirs(os.path.dirname(conffile), exist_ok=True)
|
os.makedirs(os.path.dirname(conffile), exist_ok=True)
|
||||||
with open(conffile, "wt") as f:
|
with open(conffile, "wt") as f:
|
||||||
json.dump(data, f)
|
json.dump(data, f)
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ def load(config_file):
|
|||||||
sanitise("terminals", {})
|
sanitise("terminals", {})
|
||||||
sanitise("args", [])
|
sanitise("args", [])
|
||||||
sanitise("consoles", {})
|
sanitise("consoles", {})
|
||||||
|
sanitise("env", {})
|
||||||
|
|
||||||
if not config["exe"]:
|
if not config["exe"]:
|
||||||
raise ValueError("Required value FVP_EXE not set in machine configuration")
|
raise ValueError("Required value FVP_EXE not set in machine configuration")
|
||||||
|
|||||||
@@ -60,7 +60,10 @@ class FVPRunner:
|
|||||||
cli = cli_from_config(config, terminal_choice)
|
cli = cli_from_config(config, terminal_choice)
|
||||||
cli += extra_args
|
cli += extra_args
|
||||||
self._logger.debug(f"Constructed FVP call: {cli}")
|
self._logger.debug(f"Constructed FVP call: {cli}")
|
||||||
self._fvp_process = await asyncio.create_subprocess_exec(*cli, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
self._fvp_process = await asyncio.create_subprocess_exec(
|
||||||
|
*cli,
|
||||||
|
stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
||||||
|
env=config['env'])
|
||||||
|
|
||||||
def detect_terminals(line):
|
def detect_terminals(line):
|
||||||
m = re.match(r"^(\S+): Listening for serial connection on port (\d+)$", line)
|
m = re.match(r"^(\S+): Listening for serial connection on port (\d+)$", line)
|
||||||
|
|||||||
@@ -20,11 +20,10 @@ class RunFVPTests(OESelftestTestCase):
|
|||||||
on exit code 0 or fail the test, otherwise return the CompletedProcess
|
on exit code 0 or fail the test, otherwise return the CompletedProcess
|
||||||
instance.
|
instance.
|
||||||
"""
|
"""
|
||||||
# Put the test directory in PATH so that any mock FVPs are found first
|
|
||||||
newenv = {"PATH": str(testdir) + ":" + os.environ["PATH"]}
|
|
||||||
cli = [runfvp,] + list(args)
|
cli = [runfvp,] + list(args)
|
||||||
print(f"Calling {cli}")
|
print(f"Calling {cli}")
|
||||||
ret = subprocess.run(cli, env=newenv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
|
# Set cwd to testdir so that any mock FVPs are found
|
||||||
|
ret = subprocess.run(cli, cwd=testdir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
|
||||||
if should_succeed:
|
if should_succeed:
|
||||||
self.assertEqual(ret.returncode, 0, f"runfvp exit {ret.returncode}, output: {ret.stdout}")
|
self.assertEqual(ret.returncode, 0, f"runfvp exit {ret.returncode}, output: {ret.stdout}")
|
||||||
return ret.stdout
|
return ret.stdout
|
||||||
@@ -40,8 +39,6 @@ class RunFVPTests(OESelftestTestCase):
|
|||||||
self.run_fvp("--this-is-an-invalid-option", should_succeed=False)
|
self.run_fvp("--this-is-an-invalid-option", should_succeed=False)
|
||||||
|
|
||||||
def test_run_auto_tests(self):
|
def test_run_auto_tests(self):
|
||||||
newenv = {"PATH": str(testdir) + ":" + os.environ["PATH"]}
|
|
||||||
|
|
||||||
cases = list(testdir.glob("auto-*.json"))
|
cases = list(testdir.glob("auto-*.json"))
|
||||||
if not cases:
|
if not cases:
|
||||||
self.fail("No tests found")
|
self.fail("No tests found")
|
||||||
@@ -79,6 +76,7 @@ class ConfFileTests(OESelftestTestCase):
|
|||||||
self.assertTrue("terminals" in conf)
|
self.assertTrue("terminals" in conf)
|
||||||
self.assertTrue("args" in conf)
|
self.assertTrue("args" in conf)
|
||||||
self.assertTrue("consoles" in conf)
|
self.assertTrue("consoles" in conf)
|
||||||
|
self.assertTrue("env" in conf)
|
||||||
|
|
||||||
|
|
||||||
class RunnerTests(OESelftestTestCase):
|
class RunnerTests(OESelftestTestCase):
|
||||||
@@ -97,6 +95,7 @@ class RunnerTests(OESelftestTestCase):
|
|||||||
"applications": {'a1': 'file'},
|
"applications": {'a1': 'file'},
|
||||||
"terminals": {},
|
"terminals": {},
|
||||||
"args": ['--extra-arg'],
|
"args": ['--extra-arg'],
|
||||||
|
"env": {"FOO": "BAR"}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
m.assert_called_once_with('/usr/bin/FVP_Binary',
|
m.assert_called_once_with('/usr/bin/FVP_Binary',
|
||||||
@@ -106,4 +105,5 @@ class RunnerTests(OESelftestTestCase):
|
|||||||
'--extra-arg',
|
'--extra-arg',
|
||||||
stdin=unittest.mock.ANY,
|
stdin=unittest.mock.ANY,
|
||||||
stdout=unittest.mock.ANY,
|
stdout=unittest.mock.ANY,
|
||||||
stderr=unittest.mock.ANY)
|
stderr=unittest.mock.ANY,
|
||||||
|
env={"FOO":"BAR"})
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
|
"fvp-bindir": ".",
|
||||||
"exe": "auto-basic.sh"
|
"exe": "auto-basic.sh"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"fvp-bindir": ".",
|
||||||
"exe": "test-parameters.py",
|
"exe": "test-parameters.py",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"board.cow": "moo",
|
"board.cow": "moo",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"fvp-bindir": ".",
|
||||||
"exe": "test-parameters.py",
|
"exe": "test-parameters.py",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"board.cow": "moo"
|
"board.cow": "moo"
|
||||||
|
|||||||
Reference in New Issue
Block a user