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.
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.
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.
diff --git a/lib/remote.exp b/lib/remote.exp
index 4110575..30fa797 100644
--- a/lib/remote.exp
+++ b/lib/remote.exp
@@ -1446,4 +1446,108 @@ proc remote_swap_conn { host } {
return "pass"
}
+# Set an environment variable; return 0 if supported, 1 if not.
+# Remote boards supporting environment variable setting should store
+# the value in env_$var in board_info.
+
+proc remote_setenv { dest var value } {
+ return [call_remote "" setenv $dest $var $value]
+}
+
+proc standard_setenv { dest var value } {
+ if { ![isremote $dest] } {
+ global env
+ set env($var) $value
+ return 0
+ } else {
+ return 1
+ }
+}
+
+# Clear an environment variable (if local), or restore to its initial
+# value (if any) (if not local).
+
+proc remote_unsetenv { dest var } {
+ return [call_remote "" unsetenv $dest $var]
+}
+
+proc standard_unsetenv { dest var } {
+ if { ![isremote $dest] } {
+ global env
+ unset env($var)
+ } else {
+ global board_info
+ unset board_info($dest,env_$var)
+ }
+}
+
+# Return the current state of an environment variable (list of 0 and
+# "" or 1 and value), or restore it from such a state.
+
+proc remote_saveenv { dest var } {
+ return [call_remote "" saveenv $dest $var]
+}
+
+proc standard_saveenv { dest var } {
+ if { ![isremote $dest] } {
+ global env
+ if { [info exists env($var)] } {
+ return [list 1 $env($var)]
+ } else {
+ return [list 0 ""]
+ }
+ } else {
+ global board_info
+ if { [info exists board_info($dest,env_$var)] } {
+ return [list 1 $board_info($dest,env_$var)]
+ } else {
+ return [list 0 ""]
+ }
+ }
+}
+
+proc remote_restoreenv { dest var saved } {
+ set was_set [lindex $saved 0]
+ set value [lindex $saved 1]
+ if { $was_set == 1 } {
+ return [remote_setenv $dest $var $value]
+ } else {
+ return [remote_unsetenv $dest $var]
+ }
+}
+
+# Push the current state of an environment variable in saved_env_$var
+# in board_info and set a new value, or restore a previously saved
+# value; remote_pushenv returns the same value as remote_setenv. If
+# setting fails, a value is still stored on the stack; this is so that
+# callers using this function on a best-efforts basis, that wish to
+# continue execution even if setting environment variables is not
+# supported by this board, can call remote_popenv later without
+# needing to record whether remote_pushenv succeeded or failed.
+
+proc remote_pushenv { dest var value } {
+ set saved [remote_saveenv $dest $var]
+ set res [remote_setenv $dest $var $value]
+ if {[board_info $dest exists name]} {
+ set dest [board_info $dest name]
+ }
+ global board_info
+ if { ![info exists board_info($dest,saved_env_$var)] } {
+ set board_info($dest,saved_env_$var) ""
+ }
+ set board_info($dest,saved_env_$var) [list $saved
$board_info($dest,saved_env_$var)]
+ return $res
+}
+
+proc remote_popenv { dest var } {
+ if {[board_info $dest exists name]} {
+ set dest [board_info $dest name]
+ }
+ global board_info
+ set old_stack $board_info($dest,saved_env_$var)
+ set saved [lindex $old_stack 0]
+ set board_info($dest,saved_env_$var) [lindex $old_stack 1]
+ return [remote_restoreenv $dest $var $saved]
+}
+
set sum_program "testcsum"
diff --git a/lib/ssh.exp b/lib/ssh.exp
index 4514707..bb4150a 100644
--- a/lib/ssh.exp
+++ b/lib/ssh.exp
@@ -115,6 +115,12 @@ proc ssh_upload {desthost srcfile destfile} {
}
}
+proc ssh_setenv { dest var value } {
+ global board_info
+ set board_info($dest,env_$var) $value
+ return 0
+}
+
# Execute CMD on BOARDNAME.
#
proc ssh_exec { boardname program pargs inp outp } {
@@ -168,7 +174,14 @@ proc ssh_exec { boardname program pargs inp outp } {
set inp "/dev/null"
}
- set ret [local_exec "$SSH $ssh_useropts $ssh_user$hostname sh -c '$program
$pargs 2>&1 ; echo XYZ\\\${?}ZYX'" $inp $outp $timeout]
+ global board_info
+ set target_env ""
+ foreach {key val} [array get board_info $boardname,env_*] {
+ set var [string replace $key 0 [expr [string length $boardname,env_] -
1]]
+ append target_env "export $var=\"$val\"; "
+ }
+
+ set ret [local_exec "$SSH $ssh_useropts $ssh_user$hostname sh -c
'$target_env$program $pargs 2>&1 ; echo XYZ\\\${?}ZYX'" $inp $outp $timeout]
set status [lindex $ret 0]
set output [lindex $ret 1]
--
Joseph S. Myers
[email protected]