Ensure that the ENV values are all strings. (Anthony Roach)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 18 Nov 2003 07:10:57 +0000 (07:10 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 18 Nov 2003 07:10:57 +0000 (07:10 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@848 fdb21ef1-2011-0410-befe-b5e4ea1792b1

18 files changed:
doc/man/scons.1
doc/scons.mod
doc/user/ENV.in [new file with mode: 0644]
doc/user/ENV.sgml [new file with mode: 0644]
doc/user/MANIFEST
doc/user/command-line.in
doc/user/command-line.sgml
doc/user/environments.in
doc/user/environments.sgml
doc/user/libraries.in
doc/user/libraries.sgml
doc/user/main.in
doc/user/main.sgml
src/CHANGES.txt
src/engine/SCons/Action.py
src/engine/SCons/Tool/msvc.py
src/engine/SCons/Tool/msvs.py
test/ENV.py

index cdf785a80a3ab618a0207359a0d209117ccdf260..67b1b9e166d562a6c3956809f28a8bc1484d1898 100644 (file)
@@ -4107,7 +4107,9 @@ General options passed to the TeX DVI file to PostScript converter.
 
 .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
@@ -4744,7 +4746,8 @@ The qt tool tries to take this from os.environ.
 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
index 443be6726286c40c9da3f4d2ff0d26ca4353d16f..c4d0e8ec1b71325a526ccbab00ff7ac74cc81d95 100644 (file)
@@ -18,7 +18,9 @@
 <!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>">
 
diff --git a/doc/user/ENV.in b/doc/user/ENV.in
new file mode 100644 (file)
index 0000000..3fc3a29
--- /dev/null
@@ -0,0 +1,168 @@
+
+<!--
+
+  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>
diff --git a/doc/user/ENV.sgml b/doc/user/ENV.sgml
new file mode 100644 (file)
index 0000000..d3078f1
--- /dev/null
@@ -0,0 +1,168 @@
+
+<!--
+
+  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>
index 337c8e01a0a5067c55cb11157cc0546fd79456ae..c9af4a4a76784288808adb38942e5602f0581c30 100644 (file)
@@ -10,6 +10,7 @@ cons.pl
 cons.sgml
 copyright.sgml
 depends.sgml
+ENV.sgml
 environments.sgml
 errors.sgml
 example.sgml
index 9367c0912f2ef42b05cee17d6421bcbb7b93e2d5..6f523a891820059b1dfe05cedac73e6f383a16ac 100644 (file)
     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>
index f6f219ce0a5ee42ad0f0cf62e238a8e4f4daf3e6..cf15b93284e9e11eb11be50da807963df4dd55ae 100644 (file)
     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>
index 2083d4fcb799f2e0cb4a0c30bd6d62d43ad09477..7e68b5ed4ffc9124d45d07720bd49012621f2fc6 100644 (file)
@@ -402,7 +402,7 @@ environment undisturbed.
    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.)
 
@@ -411,7 +411,7 @@ environment undisturbed.
  <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.
@@ -453,8 +453,7 @@ environment undisturbed.
    <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.
@@ -488,7 +487,7 @@ environment undisturbed.
 
    <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,
@@ -587,24 +586,24 @@ environment undisturbed.
 
    <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
@@ -675,7 +674,7 @@ environment undisturbed.
 
    <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
@@ -723,7 +722,7 @@ environment undisturbed.
    <para>
 
    &SCons; provides various methods that
-   support modifying existing values in a &consenv;.
+   support modifying existing values in a construction environment.
 
    </para>
 
index 2be8614e52e7e46aab2e22f130ec4126c2bd9de0..2b4fb5dda160bde1b1138bea1ecd33145daf6eda 100644 (file)
@@ -402,7 +402,7 @@ environment undisturbed.
    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.)
 
@@ -411,7 +411,7 @@ environment undisturbed.
  <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.
@@ -450,8 +450,7 @@ environment undisturbed.
    <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.
@@ -481,7 +480,7 @@ environment undisturbed.
 
    <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,
@@ -577,24 +576,24 @@ environment undisturbed.
 
    <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
@@ -666,7 +665,7 @@ environment undisturbed.
 
    <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
@@ -720,7 +719,7 @@ environment undisturbed.
    <para>
 
    &SCons; provides various methods that
-   support modifying existing values in a &consenv;.
+   support modifying existing values in a construction environment.
 
    </para>
 
index a69bbeeb7f96c9efa33bd031c55336fd3dbff2e8..a31b2b4fa9ab0a8b96f0f65516704f76cd470872 100644 (file)
 
   <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>
 
index 118a5608568b8f0e9cea10893aa5023fb652b76c..fedeb7f059135c2be1fa5ef9cd9f07bf2937d09a 100644 (file)
 
   <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>
 
index 4aa4d9c9200f3163e29879283563fe88d5ecaf28..1a017d338b5e866c513ab3fcea39c980392e3920 100644 (file)
@@ -43,6 +43,7 @@
     <!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;
index 4aa4d9c9200f3163e29879283563fe88d5ecaf28..1a017d338b5e866c513ab3fcea39c980392e3920 100644 (file)
@@ -43,6 +43,7 @@
     <!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;
index a36b2abb565724b541e7f6741bf8c71d148c7c90..a6965c626b4abbdcfb8ad5c8ad5803fb1169a956 100644 (file)
@@ -20,6 +20,20 @@ RELEASE 0.95 - XXX
   - 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,
@@ -46,6 +60,8 @@ RELEASE 0.95 - XXX
 
   - 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
index 93580cc14a1c1c030173558839620b8671931456..17915324eac4a2806c172bbb97595c09e5422a02 100644 (file)
@@ -237,6 +237,23 @@ class CommandAction(ActionBase):
                             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)
index 2a067b955b2a22f06e2928ae4a050d57875bc123..f7ec5e473b84d7c7dbafbafdf6f064a81f32d297 100644 (file)
@@ -261,29 +261,38 @@ def get_msvc_paths(version=None):
     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):
index 949793a0a38453a6e0390ac93bb7120948ab3d2f..ee860e3def73ed1d4749fd22a3f86694ab66f24a 100644 (file)
@@ -787,6 +787,16 @@ def get_visualstudio_versions():
     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()
 
index 31ad970b883e66a4a4426d7d3f87cb7b4f19ef94..98d04f99f29abe06c8c22dc086aa96a0b54d08c8 100644 (file)
@@ -24,6 +24,8 @@
 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+import os
+import string
 import sys
 import TestSCons
 
@@ -60,4 +62,24 @@ test.run(arguments = '.')
 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()