.IP ENV
A dictionary of environment variables
-to use when invoking commands.
+to use when invoking commands. When ENV is used in a command all list
+values will be joined using the path separator and any other non-string
+values will simply be coerced to a string.
Note that, by default,
.B scons
does
It also initializes all QT_*
construction variables listed below.
(Note that all paths are constructed
-with python's os.path.join() method, but listed here with the '/' seperator
+with python's os.path.join() method,
+but are listed here with the '/' separator
for easier reading.)
In addition, the construction environment
variables CPPPATH, LIBPATH, LIBS, PROGEMITTER, SHLIBEMITTER and LIBEMITTER
<!ENTITY Ant "<application>Ant</application>">
<!ENTITY Autoconf "<application>Autoconf</application>">
<!ENTITY Automake "<application>Automake</application>">
+<!ENTITY cc "<application>cc</application>">
<!ENTITY Cons "<application>Cons</application>">
+<!ENTITY csh "<application>csh</application>">
<!ENTITY gcc "<application>gcc</application>">
<!ENTITY Jam "<application>Jam</application>">
<!ENTITY Make "<application>Make</application>">
<!ENTITY COLORS "<varname>COLORS</varname>">
<!ENTITY CONFIG "<varname>CONFIG</varname>">
<!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>">
+<!ENTITY ENV "<varname>ENV</varname>">
<!ENTITY LIBDIRPREFIX "<varname>LIBDIRPREFIX</varname>">
<!ENTITY LIBDIRSUFFIX "<varname>LIBDIRSUFFIX</varname>">
<!ENTITY LIBLINKPREFIX "<varname>LIBLINKPREFIX</varname>">
-->
+<!ENTITY PATH "<varname>PATH</varname>">
<!ENTITY PYTHONPATH "<varname>PYTHONPATH</varname>">
<!ENTITY SCONSFLAGS "<varname>SCONSFLAGS</varname>">
--- /dev/null
+
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ When &SCons; builds a target file,
+ it does not execute the commands with
+ the same external environment
+ that you used to execute &SCons;.
+ Instead, it uses the dictionary
+ stored in the &ENV; construction variable
+ as the external environment
+ for executing commands.
+
+ </para>
+
+ <para>
+
+ The most important ramification of this behavior
+ is that the &PATH; environment variable,
+ which controls where the operating system
+ will look for commands and utilities,
+ is not the same as in the external environment
+ from which you called &SCons;.
+ This means that &SCons; will not, by default,
+ necessarily find all of the tools
+ that you can execute from the command line.
+
+ </para>
+
+ <para>
+
+ The default value of the &PATH; environment variable
+ on a POSIX system
+ is <literal>/usr/local/bin:/bin:/usr/bin</literal>.
+ The default value of the &PATH; environment variable
+ on a Win32 system comes from the Windows registry
+ value for the command interpreter.
+ If you want to execute any commands--compilers, linkers, etc.--that
+ are not in these default locations,
+ you need to set the &PATH; value
+ in the &ENV; dictionary
+ in your construction environment.
+
+ </para>
+
+ <para>
+
+ The simplest way to do this is to initialize explicitly
+ the value when you create the construction environment;
+ this is one way to do that:
+
+ </para>
+
+ <sconstruct>
+ path = ['/usr/local/bin', '/bin', '/usr/bin']
+ env = Environment(ENV = {'PATH' : path})
+ </sconstruct>
+
+ <!--
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Command('foo', [], '__ROOT__/usr/bin/printenv.py')
+ </file>
+ <file name="__ROOT__/usr/bin/printenv.py" chmod="0755">
+ #!/usr/bin/env python
+ import os
+ import sys
+ if len(sys.argv) > 1:
+ keys = sys.argv[1:]
+ else:
+ keys = os.environ.keys()
+ keys.sort()
+ for key in keys:
+ print " " + key + "=" + os.environ[key]
+ </file>
+ </scons_example>
+
+ <para>
+
+ </para>
+
+ <scons_output example="ex1">
+ <command>scons -Q</command>
+ </scons_output>
+
+ -->
+
+ <section>
+ <title>Propagating &PATH; From the External Environment</title>
+
+ <para>
+
+ You may want to propagate the external &PATH;
+ to the execution environment for commands.
+ You do this by initializing the &PATH;
+ variable with the &PATH; value from
+ the <literal>os.environ</literal>
+ dictionary,
+ which is Python's way of letting you
+ get at the external environment:
+
+ </para>
+
+ <sconstruct>
+ import os
+ env = Environment(ENV = {'PATH' : os.environ['PATH']})
+ </sconstruct>
+
+ <para>
+
+ Alternatively, you may find it easier
+ to just propagate the entire external
+ environment to the execution environment
+ for commands.
+ This is simpler to code than explicity
+ selecting the &PATH; value:
+
+ </para>
+
+ <sconstruct>
+ import os
+ env = Environment(ENV = os.environ)
+ </sconstruct>
+
+ <para>
+
+ Either of these will guarantee that
+ &SCons; will be able to execute
+ any command that you can execute from the command line.
+ The drawback is that the build can behave
+ differently if it's run by people with
+ different &PATH; values in their environment--for example,
+ both the <literal>/bin</literal> and
+ <literal>/usr/local/bin</literal> directories
+ have different &cc; commands,
+ then which one will be used to compile programs
+ will depend on which directory is listed
+ first in the user's &PATH; variable.
+
+ </para>
+
+ </section>
--- /dev/null
+
+<!--
+
+ Copyright (c) 2001, 2002, 2003 Steven Knight
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ When &SCons; builds a target file,
+ it does not execute the commands with
+ the same external environment
+ that you used to execute &SCons;.
+ Instead, it uses the dictionary
+ stored in the &ENV; construction variable
+ as the external environment
+ for executing commands.
+
+ </para>
+
+ <para>
+
+ The most important ramification of this behavior
+ is that the &PATH; environment variable,
+ which controls where the operating system
+ will look for commands and utilities,
+ is not the same as in the external environment
+ from which you called &SCons;.
+ This means that &SCons; will not, by default,
+ necessarily find all of the tools
+ that you can execute from the command line.
+
+ </para>
+
+ <para>
+
+ The default value of the &PATH; environment variable
+ on a POSIX system
+ is <literal>/usr/local/bin:/bin:/usr/bin</literal>.
+ The default value of the &PATH; environment variable
+ on a Win32 system comes from the Windows registry
+ value for the command interpreter.
+ If you want to execute any commands--compilers, linkers, etc.--that
+ are not in these default locations,
+ you need to set the &PATH; value
+ in the &ENV; dictionary
+ in your construction environment.
+
+ </para>
+
+ <para>
+
+ The simplest way to do this is to initialize explicitly
+ the value when you create the construction environment;
+ this is one way to do that:
+
+ </para>
+
+ <programlisting>
+ path = ['/usr/local/bin', '/bin', '/usr/bin']
+ env = Environment(ENV = {'PATH' : path})
+ </programlisting>
+
+ <!--
+
+ <scons_example name="ex1">
+ <file name="SConstruct" printme="1">
+ env = Environment()
+ env.Command('foo', [], '__ROOT__/usr/bin/printenv.py')
+ </file>
+ <file name="__ROOT__/usr/bin/printenv.py" chmod="0755">
+ #!/usr/bin/env python
+ import os
+ import sys
+ if len(sys.argv) > 1:
+ keys = sys.argv[1:]
+ else:
+ keys = os.environ.keys()
+ keys.sort()
+ for key in keys:
+ print " " + key + "=" + os.environ[key]
+ </file>
+ </scons_example>
+
+ <para>
+
+ </para>
+
+ <scons_output example="ex1">
+ <command>scons -Q</command>
+ </scons_output>
+
+ -->
+
+ <section>
+ <title>Propagating &PATH; From the External Environment</title>
+
+ <para>
+
+ You may want to propagate the external &PATH;
+ to the execution environment for commands.
+ You do this by initializing the &PATH;
+ variable with the &PATH; value from
+ the <literal>os.environ</literal>
+ dictionary,
+ which is Python's way of letting you
+ get at the external environment:
+
+ </para>
+
+ <programlisting>
+ import os
+ env = Environment(ENV = {'PATH' : os.environ['PATH']})
+ </programlisting>
+
+ <para>
+
+ Alternatively, you may find it easier
+ to just propagate the entire external
+ environment to the execution environment
+ for commands.
+ This is simpler to code than explicity
+ selecting the &PATH; value:
+
+ </para>
+
+ <programlisting>
+ import os
+ env = Environment(ENV = os.environ)
+ </programlisting>
+
+ <para>
+
+ Either of these will guarantee that
+ &SCons; will be able to execute
+ any command that you can execute from the command line.
+ The drawback is that the build can behave
+ differently if it's run by people with
+ different &PATH; values in their environment--for example,
+ both the <literal>/bin</literal> and
+ <literal>/usr/local/bin</literal> directories
+ have different &cc; commands,
+ then which one will be used to compile programs
+ will depend on which directory is listed
+ first in the user's &PATH; variable.
+
+ </para>
+
+ </section>
cons.sgml
copyright.sgml
depends.sgml
+ENV.sgml
environments.sgml
errors.sgml
example.sgml
the same command-line options every time
they run &SCons;.
For example, a user might find that it saves time
- to always specify a value of <literal>-j 2</literal>
+ to specify a value of <literal>-j 2</literal>
to run the builds in parallel.
+ To avoid having to type <literal>-j 2</literal> by hand
+ every time,
+ you can set the external environment variable
+ &SCONSFLAGS; to a string containing
+ command-line options that you want &SCons; to use.
+
+ </para>
+
+ <para>
+
+ If, for example,
+ and you're using a POSIX shell that's
+ compatible with the Bourne shell,
+ and you always want &SCons; to use the
+ <literal>-Q</literal> option,
+ you can set the &SCONSFLAGS;
+ environment as follows:
</para>
<para>
+ Users of &csh;-style shells on POSIX systems
+ can set the &SCONSFLAGS; environment as follows:
+
+ </para>
+
+ <literallayout>
+ $ setenv SCONSFLAGS "-Q"
+ </literallayout>
+
+ <para>
+
+ Windows users may typically want to set this
+ &SCONSFLAGS; in the appropriate tab of the
+ <literal>System Properties</literal> window.
+
</para>
</section>
the same command-line options every time
they run &SCons;.
For example, a user might find that it saves time
- to always specify a value of <literal>-j 2</literal>
+ to specify a value of <literal>-j 2</literal>
to run the builds in parallel.
+ To avoid having to type <literal>-j 2</literal> by hand
+ every time,
+ you can set the external environment variable
+ &SCONSFLAGS; to a string containing
+ command-line options that you want &SCons; to use.
+
+ </para>
+
+ <para>
+
+ If, for example,
+ and you're using a POSIX shell that's
+ compatible with the Bourne shell,
+ and you always want &SCons; to use the
+ <literal>-Q</literal> option,
+ you can set the &SCONSFLAGS;
+ environment as follows:
</para>
<para>
+ Users of &csh;-style shells on POSIX systems
+ can set the &SCONSFLAGS; environment as follows:
+
+ </para>
+
+ <literallayout>
+ $ setenv SCONSFLAGS "-Q"
+ </literallayout>
+
+ <para>
+
+ Windows users may typically want to set this
+ &SCONSFLAGS; in the appropriate tab of the
+ <literal>System Properties</literal> window.
+
</para>
</section>
Technically, a &consenv; is an object
that has a number of associated
&consvars;, each with a name and a value.
- (A &consenv; also has an attached
+ (A construction environment also has an attached
set of &Builder; methods,
about which we'll learn more later.)
<para>
A &consenv; is created by the &Environment; method.
- When you initialize a &consenv;,
+ When you initialize a construction environment
you can set the values of the
environment's &consvars;
to control how a program is built.
<para>
The real advantage of construction environments
- become apparent when you realize
- that you can create as many different construction
+ is that you can create as many different construction
environments as you need,
each tailored to a different way to build
some piece of software or other file.
<para>
- We can even use multiple &consenvs; to build
+ We can even use multiple construction environments to build
multiple versions of a single program.
If you do this by simply trying to use the
&Program; builder with both environments, though,
<para>
- Sometimes you want more than one &consenv;
+ Sometimes you want more than one construction environment
to share the same values for one or more variables.
Rather than always having to repeat all of the common
- variables when you create each &consenv;,
+ variables when you create each construction environment,
you can use the &Copy; method
- to create a copy of a &consenv;.
+ to create a copy of a construction environment.
</para>
<para>
- Like the &Environment; call that creates a &consenv;,
+ Like the &Environment; call that creates a construction environment,
the &Copy; method takes &consvar; assignments,
- which will override the values in the copied &consenv;.
+ which will override the values in the copied construction environment.
For example, suppose we want to use &gcc;
to create three versions of a program,
one optimized, one debug, and one with neither.
- We could do this by creating a "base" &consenv;
+ We could do this by creating a "base" construction environment
that sets &CC; to &gcc;,
and then creating two copies,
one which sets &CCFLAGS; for optimization
<para>
- A &consenv;, however,
+ A construction environment, however,
is actually a Python object with
associated methods, etc.
If you want to have direct access to only the
<para>
&SCons; provides various methods that
- support modifying existing values in a &consenv;.
+ support modifying existing values in a construction environment.
</para>
Technically, a &consenv; is an object
that has a number of associated
&consvars;, each with a name and a value.
- (A &consenv; also has an attached
+ (A construction environment also has an attached
set of &Builder; methods,
about which we'll learn more later.)
<para>
A &consenv; is created by the &Environment; method.
- When you initialize a &consenv;,
+ When you initialize a construction environment
you can set the values of the
environment's &consvars;
to control how a program is built.
<para>
The real advantage of construction environments
- become apparent when you realize
- that you can create as many different construction
+ is that you can create as many different construction
environments as you need,
each tailored to a different way to build
some piece of software or other file.
<para>
- We can even use multiple &consenvs; to build
+ We can even use multiple construction environments to build
multiple versions of a single program.
If you do this by simply trying to use the
&Program; builder with both environments, though,
<para>
- Sometimes you want more than one &consenv;
+ Sometimes you want more than one construction environment
to share the same values for one or more variables.
Rather than always having to repeat all of the common
- variables when you create each &consenv;,
+ variables when you create each construction environment,
you can use the &Copy; method
- to create a copy of a &consenv;.
+ to create a copy of a construction environment.
</para>
<para>
- Like the &Environment; call that creates a &consenv;,
+ Like the &Environment; call that creates a construction environment,
the &Copy; method takes &consvar; assignments,
- which will override the values in the copied &consenv;.
+ which will override the values in the copied construction environment.
For example, suppose we want to use &gcc;
to create three versions of a program,
one optimized, one debug, and one with neither.
- We could do this by creating a "base" &consenv;
+ We could do this by creating a "base" construction environment
that sets &CC; to &gcc;,
and then creating two copies,
one which sets &CCFLAGS; for optimization
<para>
- A &consenv;, however,
+ A construction environment, however,
is actually a Python object with
associated methods, etc.
If you want to have direct access to only the
<para>
&SCons; provides various methods that
- support modifying existing values in a &consenv;.
+ support modifying existing values in a construction environment.
</para>
<para>
- One of the more useful ways in which you can use multiple
- construction environments is to link programs
- with different sets of libraries.
+ It's often useful to organize large software projects
+ by collecting parts of the software into one or more libraries.
+ &SCons; makes it easy to create libraries
+ and to use them in the programs.
</para>
and by specifying the directory in which
the library will be found in the
&LIBPATH; construction variable:
- env = Environment(LIBS = 'foo', LIBPATH = '.')
</para>
<para>
- One of the more useful ways in which you can use multiple
- construction environments is to link programs
- with different sets of libraries.
+ It's often useful to organize large software projects
+ by collecting parts of the software into one or more libraries.
+ &SCons; makes it easy to create libraries
+ and to use them in the programs.
</para>
and by specifying the directory in which
the library will be found in the
&LIBPATH; construction variable:
- env = Environment(LIBS = 'foo', LIBPATH = '.')
</para>
<!ENTITY cons SYSTEM "cons.sgml">
<!ENTITY copyright SYSTEM "copyright.sgml">
<!ENTITY depends SYSTEM "depends.sgml">
+ <!ENTITY ENV_file SYSTEM "ENV.sgml">
<!ENTITY environments SYSTEM "environments.sgml">
<!ENTITY errors SYSTEM "errors.sgml">
<!ENTITY example SYSTEM "example.sgml">
&environments;
</chapter>
+ <chapter id="chap-ENV">
+ <title>Controlling the Environment Used to Execute Build Commands</title>
+ &ENV_file;
+ </chapter>
+
<chapter id="chap-command-line">
<title>Controlling a Build From the Command Line</title>
&command-line;
<!ENTITY cons SYSTEM "cons.sgml">
<!ENTITY copyright SYSTEM "copyright.sgml">
<!ENTITY depends SYSTEM "depends.sgml">
+ <!ENTITY ENV_file SYSTEM "ENV.sgml">
<!ENTITY environments SYSTEM "environments.sgml">
<!ENTITY errors SYSTEM "errors.sgml">
<!ENTITY example SYSTEM "example.sgml">
&environments;
</chapter>
+ <chapter id="chap-ENV">
+ <title>Controlling the Environment Used to Execute Build Commands</title>
+ &ENV_file;
+ </chapter>
+
<chapter id="chap-command-line">
<title>Controlling a Build From the Command Line</title>
&command-line;
- Accomodate the fact that Cygwin's os.path.normcase() lies about
the underlying system being case-sensitive.
+ From Charles Crain:
+
+ - If no version of MSVC is detected but the tool is specified,
+ use the MSVC 6.0 paths by default.
+
+ - Ignore any "6.1" version of MSVC found in the registry; this is a
+ phony version number (created by later service packs?) and would
+ throw off the logic if the user had any non-default paths configure.
+
+ - Correctly detect if the user has independently configured the MSVC
+ "include," "lib" or "path" in the registry and use the appropriate
+ values. Previously, SCons would only use the values if all three
+ were set in the registry.
+
From Steven Knight:
- Fix EnsureSConsVersion() so it checks against the SCons version,
- Add -H help text listing the legal --debug values.
+ - Don't choke if a construction variable is a non-string value.
+
RELEASE 0.94 - Fri, 07 Nov 2003 05:29:48 -0600
import SCons.Environment
default_ENV = SCons.Environment.Environment()['ENV']
ENV = default_ENV
+
+ # ensure that the ENV values are all strings:
+ for key, value in ENV.items():
+ if SCons.Util.is_List(value):
+ # If the value is a list, then we assume
+ # it is a path list, because that's a pretty
+ # common list like value to stick in an environment
+ # variable:
+ ENV[key] = string.join(map(str, value), os.pathsep)
+ elif not SCons.Util.is_String(value):
+ # If it isn't a string or a list, then
+ # we just coerce it to a string, which
+ # is proper way to handle Dir and File instances
+ # and will produce something reasonable for
+ # just about everything else:
+ ENV[key] = str(value)
+
# Escape the command line for the command
# interpreter we are using
map(lambda x, e=escape: x.escape(e), cmd_line)
lib_path = ''
include_path = ''
- if not version and not SCons.Util.can_read_reg:
- version = '6.0'
-
- try:
- if not version:
- version = SCons.Tool.msvs.get_visualstudio_versions()[0] #use highest version
+ if not version:
+ versions = SCons.Tool.msvs.get_visualstudio_versions()
+ if versions:
+ version = versions[0] #use highest version by default
+ else:
+ version = '6.0'
+ # Some of the configured directories only
+ # appear if the user changes them from the default.
+ # Therefore, we'll see if we can get the path to the MSDev
+ # base installation from the registry and deduce the default
+ # directories.
+ if float(version) >= 7.0:
+ defpaths = _get_msvc7_default_paths(version)
+ else:
+ defpaths = _get_msvc6_default_paths(version)
+
+ try:
include_path = get_msvc_path("include", version)
+ except (SCons.Util.RegError, SCons.Errors.InternalError):
+ include_path = defpaths[0]
+
+ try:
lib_path = get_msvc_path("lib", version)
- exe_path = get_msvc_path("path", version)
+ except (SCons.Util.RegError, SCons.Errors.InternalError):
+ lib_path = defpaths[1]
+ try:
+ exe_path = get_msvc_path("path", version)
except (SCons.Util.RegError, SCons.Errors.InternalError):
- # Could not get all the configured directories from the
- # registry. However, some of the configured directories only
- # appear if the user changes them from the default.
- # Therefore, we'll see if we can get the path to the MSDev
- # base installation from the registry and deduce the default
- # directories.
- if float(version) >= 7.0:
- return _get_msvc7_default_paths(version)
- else:
- return _get_msvc6_default_paths(version)
-
+ exe_path = defpaths[2]
+
return (include_path, lib_path, exe_path)
def get_msvc_default_paths(version = None):
if not L:
return []
+ # This is a hack to get around the fact that certain Visual Studio
+ # patches place a "6.1" version in the registry, which does not have
+ # any of the keys we need to find include paths, install directories,
+ # etc. Therefore we ignore it if it is there, since it throws all
+ # other logic off.
+ try:
+ L.remove("6.1")
+ except ValueError:
+ pass
+
L.sort()
L.reverse()
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import os
+import string
import sys
import TestSCons
test.fail_test(test.read('env1.out') != "build.py env1\ninput file\n")
test.fail_test(test.read('env2.out') != "build.py env2\ninput file\n")
+
+test.write('SConstruct', """
+env = Environment()
+foo = env.Command('foo', [], r'%s build.py $TARGET')
+env['ENV']['LIST'] = [foo, 'bar']
+env['ENV']['FOO'] = foo
+"""%python)
+
+test.write('build.py',
+r"""
+import os
+print 'LIST:', os.environ['LIST']
+print 'FOO:', os.environ['FOO']
+""")
+
+test.run()
+
+test.fail_test(string.find(test.stdout(), "LIST: foo%sbar"%os.pathsep) == -1)
+test.fail_test(string.find(test.stdout(), "FOO: foo") == -1)
+
test.pass_test()