On 10/6/26 14:28, Joseph Myers wrote:
One limitation of the DejaGnu board file interface is the lack of
support for setting environment variables on a board. As a
consequence, various GCC tests that depend on environment variable
setting are either skipped for remote targets, or do not function
correctly in the remote target case, unless a hack is used in the
board file to copy relevant environment variables (set directly on the
build system in the current testsuite code) from the build system to
the target.
This feature has actually been on the TODO list for some time and is
planned as part of a larger refactoring of the remote target support in
a future release. The current aim is for 1.6.4 to mostly consolidate
bugfixes.
A sufficiently simple API can be carried into the future easily, (and
perhaps even be slipped into 1.6.4) but I am very reluctant to establish
more conventions on the board_info array, which appears to be intended
to be an internal variable in the framework, since we have accessor
procedures for it.
For an immediate workaround, do the affected targets have the env(1)
command? Using env(1) would have the advantage of backwards
compatibility with current and previous releases of DejaGnu.
Add support for the most common environment variable cases (as used in
the GCC testsuites) to the board file interface, and implement the
underlying support in ssh.exp as well as for the local testing case.
The basic operations provided are setenv and unsetenv, with a
convention for how remote boards store the current environment
variable settings in board_info($dest,env_$var). Since a common use
case is setting a variable only for a given test or group of tests,
and restoring the previous state afterwards, there are also saveenv
and restoreenv operations, and, building on top of those, pushenv and
popenv operations that maintain a stack of saved state for a given
environment variable and restore from that stack.
What prevents simply adding an env-override-list optional argument to
remote_exec? If the backend sets environment variables only for each
test rather than manipulating global state on the target, why should the
framework treat that state as global inside DejaGnu?
Merely adding an additional option would also be less work to document.
(The remote_* procedures are documented.) The intermediate optional
arguments for remote_exec are already documented as accepting an empty
string as a neutral value, and an empty list of environment overrides
would also naturally be neutral.
Why a group of related procedures and not a single remote_env command
with get/set/unset/push/pop subcommands?
These are either related and remote-protocol-specific or
target-specific, or the entire set could be condensed into a shared
implementation with a get-all operation for remote drivers to use.
Why a remote_env command at all? Why not simply propagate local
environment changes to a remote target? (This could be done by setting
traces on ::env or simply snapshotting the environment when runtest
starts and comparing.)
Further, as I read this, it seems that the intention is for testsuites
to specify short-lived target environment variable overrides. If we are
adding new API to a future DejaGnu release, the (also relatively new)
"testcase group" infrastructure is designed to frame this kind of
dynamic variable; there will eventually be infrastructure in the
framework to run each test script in its own group, for example.
(Perhaps "testcase group captures environment" to save the current
environment and mark it for restoration upon the end of the current
group? What else could "testcase group captures FOO" be useful for in
the future? Maybe Tcl global variables with group-extent values?
"testcase group captures variable NAME"?)
Some of the main limitations in this interface are as follows:
* There is no getenv interface; tests should generally only need to
set a controlled environment on the board rather than retrieve the
original uncontrolled state, except for the save/restore case (which
can hopefully be handled, as in ssh.exp, b only ever setting
variables in the context of an individual test being run, rather
than actually changing some kind of global state on the board).
* The unsetenv interface unsets a variable in the local state, but
restores it to its initial state (not necessarily unset) in the
remote case. Similarly, the pushenv interface only supports setting
a string value (with previous state saved) rather than setting
either "unset" or "initial" (with previous state saved).
* There is no handling for PATH-like variables, where appropriate
handling is prepending a new value (plus colon) rather than fully
replacing a previous value. This is not in practice an important
limitation for testing GCC, since the use of variables such as
LD_LIBRARY_PATH in the GCC testsuites is readily avoided in remote
testing, either by testing an installed compiler (with the required
shared libraries installed in the root filesystem) or by using a
board file that links with options such as -rpath. If it were
desired to handle such variables, however, I'd be inclined to prefer
a "prepend with colon" interface rather than building it on a getenv
interface.
A getenv interface solves not only PATH but also all other cases where
replacing a value is inappropriate by enabling testcase code to simply
examine the effects of previous code before making its own changes.
A major part of DejaGnu's purpose is to "paper over" irrelevant
differences between targets. Having unsetenv do significantly different
things with local and remote targets is a serious deficiency that I do
not want lurking in the framework for users to trip over.
This feature is desirable, but this interface as suggested is not
suitable for DejaGnu.
-- Jacob