Commits

smallbulb committed fde2a96 Draft Merge

Merged changes from original scons

Comments (0)

Files changed (45)

 
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
+#
+# After updating this file, run bin/update-release-info.py <MODE>.
+# 
+
 # The version tuple that will be used for the release.  The fields are
 # (major, minor, micro, type, patchlevel).  The release level is one of
 # 'alpha', 'beta', 'candidate', or 'final'.  If the release type is not
 # 'final', the patchlevel is set to the release date.  This value is
 # manatory and must be present in this file.
-version_tuple = (2, 1, 0, 'alpha', 0)
+version_tuple = (2, 2, 0, 'final', 0)
 
 # Python versions prior to unsupported_python_version cause a fatal error
 # when that version is used.  Python versions prior to deprecate_python_version
         commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY sdist --formats=%s" %  \
                             ','.join(distutils_formats))
 
-    commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_wininst")
+    commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_wininst --plat-name win32 --user-access-control auto")
 
     env.Command(distutils_targets, build_src_files, commands)
 

bin/update-release-info.py

 
 if mode == 'develop' and version_tuple[3] != 'alpha':
     version_tuple ==  version_tuple[:3] + ('alpha', 0)
-if version_tuple[3] != 'final':
+if len(version_tuple) > 3 and version_tuple[3] != 'final':
     if mode == 'develop':
         version_tuple = version_tuple[:4] + ('yyyymmdd',)
     else:
         yyyy,mm,dd,_,_,_ = release_date
         version_tuple = version_tuple[:4] + ((yyyy*100 + mm)*100 + dd,)
 version_string = '.'.join(map(str, version_tuple))
-version_type = version_tuple[3]
+if len(version_tuple) > 3:
+    version_type = version_tuple[3]
+else:
+    version_type = 'final'
 if DEBUG: print 'version string', version_string
 
 if version_type not in ['alpha', 'beta', 'candidate', 'final']:

bin/upload-release-files.sh

+#!/bin/sh
+
+if [ $# -lt 2 ]; then
+	echo Usage: $0 VERSION SF_USERNAME
+	exit 1
+fi
+
+VERSION=$1; shift
+SF_USER=$1; shift
+
+RSYNC='rsync'
+RSYNCOPTS='-v -e ssh'
+SF_MACHINE='frs.sourceforge.net'
+SF_TOPDIR='/home/frs/project/scons'
+
+# the build products are here:
+cd build/dist
+cp -f ../../src/CHANGES.txt ../../src/RELEASE.txt ../../src/Announce.txt .
+
+set -x
+
+# Upload main scons release files:
+$RSYNC $RSYNCOPTS \
+  scons-$VERSION-1.noarch.rpm \
+  scons-$VERSION-1.src.rpm \
+  scons-$VERSION-setup.exe \
+  scons-$VERSION.tar.gz \
+  scons-$VERSION.zip \
+  Announce.txt CHANGES.txt RELEASE.txt \
+  $SF_USER@$SF_MACHINE:$SF_TOPDIR/scons/$VERSION/
+
+# Local packages:
+$RSYNC $RSYNCOPTS \
+  scons-local-$VERSION.tar.gz \
+  scons-local-$VERSION.zip \
+  Announce.txt CHANGES.txt RELEASE.txt \
+  $SF_USER@$SF_MACHINE:$SF_TOPDIR/scons-local/$VERSION/
+
+# Source packages:
+$RSYNC $RSYNCOPTS \
+  scons-src-$VERSION.tar.gz \
+  scons-src-$VERSION.zip \
+  Announce.txt CHANGES.txt RELEASE.txt \
+  $SF_USER@$SF_MACHINE:$SF_TOPDIR/scons-src/$VERSION/
+
+
+#
+# scons.org stuff:
+# 
+# Doc: copy the doc tgz over; we'll unpack later
+$RSYNC $RSYNCOPTS \
+  scons-doc-$VERSION.tar.gz \
+  scons@scons.org:public_html/production/doc/$VERSION/
+# Copy the changelog
+$RSYNC $RSYNCOPTS \
+  CHANGES.txt \
+  scons@scons.org:public_html/production/
+# Note that Announce.txt gets copied over to RELEASE.txt.
+# This should be fixed at some point.
+$RSYNC $RSYNCOPTS \
+  Announce.txt \
+  scons@scons.org:public_html/production/RELEASE.txt
+# Unpack the doc and repoint doc symlinks:
+ssh scons@scons.org "
+  cd public_html/production/doc
+  cd $VERSION
+  tar xvf scons-doc-$VERSION.tar.gz
+  cd ..
+  rm latest; ln -s $VERSION latest
+  rm production; ln -s $VERSION production
+"
+echo '*****'
+echo '***** Now manually update index.php, includes/versions.php and news-raw.xhtml on scons.org.'
+echo '*****'

doc/user/MANIFEST

 factories.xml
 file-removal.xml
 functions.xml
+gettext.xml
 hierarchy.xml
 install.xml
 java.xml

doc/user/gettext.in

+<!--
+
+  __COPYRIGHT__
+
+  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>
+  The &t-link-gettext; toolset supports internationalization and localization
+  of SCons-based projects. Builders provided by &t-link-gettext; automatize
+  generation and updates of translation files. You can manage translations and
+  translation templates similarly to how it's done with autotools.
+  </para>
+
+  <section>
+  <title>Prerequisites</title>
+  <para>
+    To follow examples provided in this chapter set up your operating system to
+    support two or more languages. In following examples we use locales
+    <literal>en_US</literal>, <literal>de_DE</literal>, and
+    <literal>pl_PL</literal>.
+  </para>
+
+  <para>
+    Ensure, that you have <ulink
+    url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext
+    utilities</ulink> installed on your system.
+  </para>
+
+  <para>
+    To edit translation files you may wish to install <ulink
+    url="http://www.poedit.net/">poedit</ulink> editor.
+  </para>
+  </section>
+
+  <section>
+  <title>Simple project</title>
+    <para>
+    Let's start with a very simple project, the "Hello world" program 
+    for example
+    <scons_example name="ex1">
+    <file name="hello.c" printme="1">
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    int main(int argc, char* argv[])
+    {
+      printf("Hello world\n");
+      return 0;
+    }
+    </file>
+    </scons_example>
+
+    Prepare a <filename>SConstruct</filename> to compile the program
+    as usual.
+    <scons_example name="ex2">
+    <file name="SConstruct" printme="1">
+    # SConstruct
+    env = Environment()
+    hello = Program(["hello.c"])
+    </file>
+    </scons_example>
+    </para>
+
+    <para>
+    Now we'll convert the project to a multi-lingual one. If you don't
+    already have <ulink
+    url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext
+    utilities</ulink> installed, install them from your preffered
+    package repository, or download from <ulink
+    url="http://ftp.gnu.org/gnu/gettext/">
+    http://ftp.gnu.org/gnu/gettext/</ulink>. For the purpose of this example,
+    you should have following three locales installed on your system:
+    <literal>en_US</literal>, <literal>de_DE</literal> and
+    <literal>pl_PL</literal>. On debian, for example, you may enable certain
+    locales through <command>dpkg-reconfigure locales</command>.
+    </para>
+
+    <para>
+    First prepare the <filename>hello.c</filename> program for
+    internationalization. Change the previous code so it reads as follows:
+    <scons_example name="ex3">
+    <file name="hello.c" printme="1">
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    #include &lt;libintl.h&gt;
+    #include &lt;locale.h&gt;
+    int main(int argc, char* argv[])
+    {
+      bindtextdomain("hello", "locale");
+      setlocale(LC_ALL, "");
+      textdomain("hello");
+      printf(gettext("Hello world\n"));
+      return 0;
+    }
+    </file>
+    </scons_example>
+    Detailed recipes for such conversion can
+    be found at <ulink
+    url="http://www.gnu.org/software/gettext/manual/gettext.html#Sources">
+    http://www.gnu.org/software/gettext/manual/gettext.html#Sources</ulink>.
+    The <function>gettext("...")</function> has two purposes.
+    First, it marks messages for the <command>xgettext(1)</command> program, which
+    we will use to extract from the sources the messages for localization.
+    Second, it calls the <literal>gettext</literal> library internals to
+    translate the message at runtime.
+    </para>
+
+    <para> 
+    Now we shall instruct SCons how to generate and maintain translation files.
+    For that, use the &b-link-Translate; builder and &b-link-MOFiles; builder.
+    The first one takes source files, extracts internationalized
+    messages from them, creates so-called <literal>POT</literal> file
+    (translation template), and then creates <literal>PO</literal> translation
+    files, one for each requested language. Later, during the development
+    lifecycle, the builder keeps all these files up-to date. The
+    &b-link-MOFiles; builder compiles the <literal>PO</literal> files to binary
+    form. Then install the <literal>MO</literal> files under directory
+    called <filename>locale</filename>.
+    </para>
+
+    <para>  The completed 
+    <filename>SConstruct</filename> is as follows:
+    <scons_example name="ex4">
+    <file name="SConstruct" printme="1">
+    # SConstruct
+    env = Environment( tools = ['default', 'gettext'] )
+    hello = env.Program(["hello.c"])
+    env['XGETTEXTFLAGS'] = [
+      '--package-name=%s' % 'hello',
+      '--package-version=%s' % '1.0',
+    ]
+    po = env.Translate(["pl","en", "de"], ["hello.c"], POAUTOINIT = 1)
+    mo = env.MOFiles(po)
+    InstallAs(["locale/en/LC_MESSAGES/hello.mo"], ["en.mo"])
+    InstallAs(["locale/pl/LC_MESSAGES/hello.mo"], ["pl.mo"])
+    InstallAs(["locale/de/LC_MESSAGES/hello.mo"], ["de.mo"])
+    </file>
+    </scons_example>
+    </para>
+    <para>
+    Generate the translation files with <command>scons po-update</command>.
+    You should see the output from SCons simillar to this:
+    <screen>
+    user@host:$ scons po-update
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    Entering '/home/ptomulik/projects/tmp'
+    xgettext --package-name=hello --package-version=1.0 -o - hello.c
+    Leaving '/home/ptomulik/projects/tmp'
+    Writting 'messages.pot' (new file)
+    msginit --no-translator -l pl -i messages.pot -o pl.po
+    Created pl.po.
+    msginit --no-translator -l en -i messages.pot -o en.po
+    Created en.po.
+    msginit --no-translator -l de -i messages.pot -o de.po
+    Created de.po.
+    scons: done building targets.
+    </screen>
+    </para>
+
+    <para>
+    If everything is right, you should see following new files.
+    <screen>
+    user@host:$ ls *.po*
+    de.po  en.po  messages.pot  pl.po
+    </screen>
+    </para>
+
+    <para>
+    Open <filename>en.po</filename> in <command>poedit</command> and provide
+    the English translation to message <literal>"Hello world\n"</literal>. Do the
+    same for <filename>de.po</filename> (deutsch) and
+    <filename>pl.po</filename> (polish). Let the translations be, for example:
+    <itemizedlist>
+      <listitem><para>
+        <literal>en: "Welcome to beautiful world!\n"</literal>
+      </para></listitem>
+      <listitem><para>
+        <literal>de: "Hallo Welt!\n"</literal>
+      </para></listitem>
+      <listitem><para>
+        <literal>pl: "Witaj swiecie!\n"</literal>
+      </para></listitem>
+    </itemizedlist>
+    </para>
+    <para>
+    Now compile the project by executing <command>scons</command>. The
+    output should be similar to this:
+    <screen>
+    user@host:$ scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    msgfmt -c -o de.mo de.po
+    msgfmt -c -o en.mo en.po
+    gcc -o hello.o -c hello.c
+    gcc -o hello hello.o
+    Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo"
+    Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo"
+    msgfmt -c -o pl.mo pl.po
+    Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+    scons: done building targets.
+    </screen>
+    SCons automatically compiled the <literal>PO</literal> files to binary format
+    <literal>MO</literal>, and the <literal>InstallAs</literal> lines installed
+    these files under <filename>locale</filename> folder.
+    </para>
+    <para>
+    Your program should be now ready. You may try it as follows (linux):
+    <screen>
+    user@host:$ LANG=en_US.UTF-8 ./hello
+    Welcome to beautiful world
+    </screen>
+    <screen>
+    user@host:$ LANG=de_DE.UTF-8 ./hello
+    Hallo Welt
+    </screen>
+    <screen>
+    user@host:$ LANG=pl_PL.UTF-8 ./hello
+    Witaj swiecie
+    </screen>
+    </para>
+    <para>
+    To demonstrate the further life of translation files, let's change Polish
+    translation (<command>poedit pl.po</command>) to <literal>"Witaj drogi
+    swiecie\n"</literal>. Run <command>scons</command> to see how scons
+    reacts to this
+    <screen>
+    user@host:$scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    msgfmt -c -o pl.mo pl.po
+    Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+    scons: done building targets.
+    </screen>
+    </para>
+    <para>
+    Now, open <filename>hello.c</filename> and add another one
+    <literal>printf</literal> line with new message.
+    <scons_example name="ex5">
+    <file name="hello.c" printme="1">
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    #include &lt;libintl.h&gt;
+    #include &lt;locale.h&gt;
+    int main(int argc, char* argv[])
+    {
+      bindtextdomain("hello", "locale");
+      setlocale(LC_ALL, "");
+      textdomain("hello");
+      printf(gettext("Hello world\n"));
+      printf(gettext("and good bye\n"));
+      return 0;
+    }
+    </file>
+    </scons_example>
+    </para>
+    <para>
+    Compile project with <command>scons</command>. This time, the
+    <command>msgmerge(1)</command> program is used by SCons to update
+    <literal>PO</literal> file. The output from compilation is like:
+    <screen>
+    user@host:$scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    Entering '/home/ptomulik/projects/tmp'
+    xgettext --package-name=hello --package-version=1.0 -o - hello.c
+    Leaving '/home/ptomulik/projects/tmp'
+    Writting 'messages.pot' (messages in file were outdated)
+    msgmerge --update de.po messages.pot
+    ... done.
+    msgfmt -c -o de.mo de.po
+    msgmerge --update en.po messages.pot
+    ... done.
+    msgfmt -c -o en.mo en.po
+    gcc -o hello.o -c hello.c
+    gcc -o hello hello.o
+    Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo"
+    Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo"
+    msgmerge --update pl.po messages.pot
+    ... done.
+    msgfmt -c -o pl.mo pl.po
+    Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+    scons: done building targets.
+    </screen>
+    </para>
+    <para>
+    The next example demonstrates what happens if we change the source code
+    in such way that the internationalized messages do not change. The answer
+    is that none of translation files (<literal>POT</literal>,
+    <literal>PO</literal>) are touched (i.e. no content changes, no
+    creation/modification time changed and so on). Let's append another
+    line to the program (after the last printf), so its code becomes:
+    <scons_example name="ex6">
+    <file name="hello.c" printme="1">
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    #include &lt;libintl.h&gt;
+    #include &lt;locale.h&gt;
+    int main(int argc, char* argv[])
+    {
+      bindtextdomain("hello", "locale");
+      setlocale(LC_ALL, "");
+      textdomain("hello");
+      printf(gettext("Hello world\n"));
+      printf(gettext("and good bye\n"));
+      printf("----------------\n");
+      return a;
+    }
+    </file>
+    </scons_example>
+    Compile the project. You'll see on your screen
+    <screen>
+    user@host:$scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    Entering '/home/ptomulik/projects/tmp'
+    xgettext --package-name=hello --package-version=1.0 -o - hello.c
+    Leaving '/home/ptomulik/projects/tmp'
+    Not writting 'messages.pot' (messages in file found to be up-to-date)
+    gcc -o hello.o -c hello.c
+    gcc -o hello hello.o
+    scons: done building targets.
+    </screen>
+    As you see, the internationalized messages ditn't change, so the
+    <literal>POT</literal> and the rest of translation files have not
+    even been touched.
+    </para>
+  </section>

doc/user/gettext.xml

+<!--
+
+  __COPYRIGHT__
+
+  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>
+  The &t-link-gettext; toolset supports internationalization and localization
+  of SCons-based projects. Builders provided by &t-link-gettext; automatize
+  generation and updates of translation files. You can manage translations and
+  translation templates similarly to how it's done with autotools.
+  </para>
+
+  <section>
+  <title>Prerequisites</title>
+  <para>
+    To follow examples provided in this chapter set up your operating system to
+    support two or more languages. In following examples we use locales
+    <literal>en_US</literal>, <literal>de_DE</literal>, and
+    <literal>pl_PL</literal>.
+  </para>
+
+  <para>
+    Ensure, that you have <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext
+    utilities</ulink> installed on your system.
+  </para>
+
+  <para>
+    To edit translation files you may wish to install <ulink url="http://www.poedit.net/">poedit</ulink> editor.
+  </para>
+  </section>
+
+  <section>
+  <title>Simple project</title>
+    <para>
+    Let's start with a very simple project, the "Hello world" program 
+    for example
+    <programlisting>
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    int main(int argc, char* argv[])
+    {
+      printf("Hello world\n");
+      return 0;
+    }
+    </programlisting>
+
+    Prepare a <filename>SConstruct</filename> to compile the program
+    as usual.
+    <programlisting>
+    # SConstruct
+    env = Environment()
+    hello = Program(["hello.c"])
+    </programlisting>
+    </para>
+
+    <para>
+    Now we'll convert the project to a multi-lingual one. If you don't
+    already have <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html">GNU gettext
+    utilities</ulink> installed, install them from your preffered
+    package repository, or download from <ulink url="http://ftp.gnu.org/gnu/gettext/">
+    http://ftp.gnu.org/gnu/gettext/</ulink>. For the purpose of this example,
+    you should have following three locales installed on your system:
+    <literal>en_US</literal>, <literal>de_DE</literal> and
+    <literal>pl_PL</literal>. On debian, for example, you may enable certain
+    locales through <command>dpkg-reconfigure locales</command>.
+    </para>
+
+    <para>
+    First prepare the <filename>hello.c</filename> program for
+    internationalization. Change the previous code so it reads as follows:
+    <programlisting>
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    #include &lt;libintl.h&gt;
+    #include &lt;locale.h&gt;
+    int main(int argc, char* argv[])
+    {
+      bindtextdomain("hello", "locale");
+      setlocale(LC_ALL, "");
+      textdomain("hello");
+      printf(gettext("Hello world\n"));
+      return 0;
+    }
+    </programlisting>
+    Detailed recipes for such conversion can
+    be found at <ulink url="http://www.gnu.org/software/gettext/manual/gettext.html#Sources">
+    http://www.gnu.org/software/gettext/manual/gettext.html#Sources</ulink>.
+    The <function>gettext("...")</function> has two purposes.
+    First, it marks messages for the <command>xgettext(1)</command> program, which
+    we will use to extract from the sources the messages for localization.
+    Second, it calls the <literal>gettext</literal> library internals to
+    translate the message at runtime.
+    </para>
+
+    <para> 
+    Now we shall instruct SCons how to generate and maintain translation files.
+    For that, use the &b-link-Translate; builder and &b-link-MOFiles; builder.
+    The first one takes source files, extracts internationalized
+    messages from them, creates so-called <literal>POT</literal> file
+    (translation template), and then creates <literal>PO</literal> translation
+    files, one for each requested language. Later, during the development
+    lifecycle, the builder keeps all these files up-to date. The
+    &b-link-MOFiles; builder compiles the <literal>PO</literal> files to binary
+    form. Then install the <literal>MO</literal> files under directory
+    called <filename>locale</filename>.
+    </para>
+
+    <para>  The completed 
+    <filename>SConstruct</filename> is as follows:
+    <programlisting>
+    # SConstruct
+    env = Environment( tools = ['default', 'gettext'] )
+    hello = env.Program(["hello.c"])
+    env['XGETTEXTFLAGS'] = [
+      '--package-name=%s' % 'hello',
+      '--package-version=%s' % '1.0',
+    ]
+    po = env.Translate(["pl","en", "de"], ["hello.c"], POAUTOINIT = 1)
+    mo = env.MOFiles(po)
+    InstallAs(["locale/en/LC_MESSAGES/hello.mo"], ["en.mo"])
+    InstallAs(["locale/pl/LC_MESSAGES/hello.mo"], ["pl.mo"])
+    InstallAs(["locale/de/LC_MESSAGES/hello.mo"], ["de.mo"])
+    </programlisting>
+    </para>
+    <para>
+    Generate the translation files with <command>scons po-update</command>.
+    You should see the output from SCons simillar to this:
+    <screen>
+    user@host:$ scons po-update
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    Entering '/home/ptomulik/projects/tmp'
+    xgettext --package-name=hello --package-version=1.0 -o - hello.c
+    Leaving '/home/ptomulik/projects/tmp'
+    Writting 'messages.pot' (new file)
+    msginit --no-translator -l pl -i messages.pot -o pl.po
+    Created pl.po.
+    msginit --no-translator -l en -i messages.pot -o en.po
+    Created en.po.
+    msginit --no-translator -l de -i messages.pot -o de.po
+    Created de.po.
+    scons: done building targets.
+    </screen>
+    </para>
+
+    <para>
+    If everything is right, you should see following new files.
+    <screen>
+    user@host:$ ls *.po*
+    de.po  en.po  messages.pot  pl.po
+    </screen>
+    </para>
+
+    <para>
+    Open <filename>en.po</filename> in <command>poedit</command> and provide
+    the English translation to message <literal>"Hello world\n"</literal>. Do the
+    same for <filename>de.po</filename> (deutsch) and
+    <filename>pl.po</filename> (polish). Let the translations be, for example:
+    <itemizedlist>
+      <listitem><para>
+        <literal>en: "Welcome to beautiful world!\n"</literal>
+      </para></listitem>
+      <listitem><para>
+        <literal>de: "Hallo Welt!\n"</literal>
+      </para></listitem>
+      <listitem><para>
+        <literal>pl: "Witaj swiecie!\n"</literal>
+      </para></listitem>
+    </itemizedlist>
+    </para>
+    <para>
+    Now compile the project by executing <command>scons</command>. The
+    output should be similar to this:
+    <screen>
+    user@host:$ scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    msgfmt -c -o de.mo de.po
+    msgfmt -c -o en.mo en.po
+    gcc -o hello.o -c hello.c
+    gcc -o hello hello.o
+    Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo"
+    Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo"
+    msgfmt -c -o pl.mo pl.po
+    Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+    scons: done building targets.
+    </screen>
+    SCons automatically compiled the <literal>PO</literal> files to binary format
+    <literal>MO</literal>, and the <literal>InstallAs</literal> lines installed
+    these files under <filename>locale</filename> folder.
+    </para>
+    <para>
+    Your program should be now ready. You may try it as follows (linux):
+    <screen>
+    user@host:$ LANG=en_US.UTF-8 ./hello
+    Welcome to beautiful world
+    </screen>
+    <screen>
+    user@host:$ LANG=de_DE.UTF-8 ./hello
+    Hallo Welt
+    </screen>
+    <screen>
+    user@host:$ LANG=pl_PL.UTF-8 ./hello
+    Witaj swiecie
+    </screen>
+    </para>
+    <para>
+    To demonstrate the further life of translation files, let's change Polish
+    translation (<command>poedit pl.po</command>) to <literal>"Witaj drogi
+    swiecie\n"</literal>. Run <command>scons</command> to see how scons
+    reacts to this
+    <screen>
+    user@host:$scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    msgfmt -c -o pl.mo pl.po
+    Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+    scons: done building targets.
+    </screen>
+    </para>
+    <para>
+    Now, open <filename>hello.c</filename> and add another one
+    <literal>printf</literal> line with new message.
+    <programlisting>
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    #include &lt;libintl.h&gt;
+    #include &lt;locale.h&gt;
+    int main(int argc, char* argv[])
+    {
+      bindtextdomain("hello", "locale");
+      setlocale(LC_ALL, "");
+      textdomain("hello");
+      printf(gettext("Hello world\n"));
+      printf(gettext("and good bye\n"));
+      return 0;
+    }
+    </programlisting>
+    </para>
+    <para>
+    Compile project with <command>scons</command>. This time, the
+    <command>msgmerge(1)</command> program is used by SCons to update
+    <literal>PO</literal> file. The output from compilation is like:
+    <screen>
+    user@host:$scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    Entering '/home/ptomulik/projects/tmp'
+    xgettext --package-name=hello --package-version=1.0 -o - hello.c
+    Leaving '/home/ptomulik/projects/tmp'
+    Writting 'messages.pot' (messages in file were outdated)
+    msgmerge --update de.po messages.pot
+    ... done.
+    msgfmt -c -o de.mo de.po
+    msgmerge --update en.po messages.pot
+    ... done.
+    msgfmt -c -o en.mo en.po
+    gcc -o hello.o -c hello.c
+    gcc -o hello hello.o
+    Install file: "de.mo" as "locale/de/LC_MESSAGES/hello.mo"
+    Install file: "en.mo" as "locale/en/LC_MESSAGES/hello.mo"
+    msgmerge --update pl.po messages.pot
+    ... done.
+    msgfmt -c -o pl.mo pl.po
+    Install file: "pl.mo" as "locale/pl/LC_MESSAGES/hello.mo"
+    scons: done building targets.
+    </screen>
+    </para>
+    <para>
+    The next example demonstrates what happens if we change the source code
+    in such way that the internationalized messages do not change. The answer
+    is that none of translation files (<literal>POT</literal>,
+    <literal>PO</literal>) are touched (i.e. no content changes, no
+    creation/modification time changed and so on). Let's append another
+    line to the program (after the last printf), so its code becomes:
+    <programlisting>
+    /* hello.c */
+    #include &lt;stdio.h&gt;
+    #include &lt;libintl.h&gt;
+    #include &lt;locale.h&gt;
+    int main(int argc, char* argv[])
+    {
+      bindtextdomain("hello", "locale");
+      setlocale(LC_ALL, "");
+      textdomain("hello");
+      printf(gettext("Hello world\n"));
+      printf(gettext("and good bye\n"));
+      printf("----------------\n");
+      return a;
+    }
+    </programlisting>
+    Compile the project. You'll see on your screen
+    <screen>
+    user@host:$scons
+    scons: Reading SConscript files ...
+    scons: done reading SConscript files.
+    scons: Building targets ...
+    Entering '/home/ptomulik/projects/tmp'
+    xgettext --package-name=hello --package-version=1.0 -o - hello.c
+    Leaving '/home/ptomulik/projects/tmp'
+    Not writting 'messages.pot' (messages in file found to be up-to-date)
+    gcc -o hello.o -c hello.c
+    gcc -o hello hello.o
+    scons: done building targets.
+    </screen>
+    As you see, the internationalized messages ditn't change, so the
+    <literal>POT</literal> and the rest of translation files have not
+    even been touched.
+    </para>
+  </section>
     <!ENTITY factories SYSTEM "factories.xml">
     <!ENTITY file-removal SYSTEM "file-removal.xml">
     <!ENTITY functions SYSTEM "functions.xml">
+    <!ENTITY gettext SYSTEM "gettext.xml">
     <!ENTITY hierarchy SYSTEM "hierarchy.xml">
     <!ENTITY java SYSTEM "java.xml">
     <!ENTITY install SYSTEM "install.xml">
     &variants;
   </chapter>
 
+  <chapter id="chap-gettext">
+    <title>Internationalization and localization with gettext</title>
+    &gettext;
+  </chapter>
+
   <!--
 
   <chapter id="chap-builders-built-in">

doc/user/main.xml

     <!ENTITY factories SYSTEM "factories.xml">
     <!ENTITY file-removal SYSTEM "file-removal.xml">
     <!ENTITY functions SYSTEM "functions.xml">
+    <!ENTITY gettext SYSTEM "gettext.xml">
     <!ENTITY hierarchy SYSTEM "hierarchy.xml">
     <!ENTITY java SYSTEM "java.xml">
     <!ENTITY install SYSTEM "install.xml">
     &variants;
   </chapter>
 
+  <chapter id="chap-gettext">
+    <title>Internationalization and localization with gettext</title>
+    &gettext;
+  </chapter>
+
   <!--
 
   <chapter id="chap-builders-built-in">

doc/user/troubleshoot.xml

                          '.SPP',
                          '.sx'],
         'CXX': '$CC',
-        'CXXCOM': '$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM',
+        'CXXCOM': '${TEMPFILE("$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM")}',
         'CXXFILESUFFIX': '.cc',
         'CXXFLAGS': ['$(', '/TP', '$)'],
         'DSUFFIXES': ['.d'],
         'SHCCFLAGS': ['$CCFLAGS'],
         'SHCFLAGS': ['$CFLAGS'],
         'SHCXX': '$CXX',
-        'SHCXXCOM': '$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM',
+        'SHCXXCOM': '${TEMPFILE("$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM")}',
         'SHCXXFLAGS': ['$CXXFLAGS'],
         'SHELL': None,
         'SHLIBPREFIX': '',
 the scons-users mailing list.
 
 
-RELEASE 2.1.0 - Mon, 09 Sep 2011 20:54:57 -0700
+RELEASE 2.2.0 - Mon, 09 Sep 2011 20:54:57 -0700
 
-  Please consult the RELEASE.txt file for a summary changes since the last
+  Please consult the RELEASE.txt file for a summary of changes since the last
   release and consult the CHANGES.txt file for complete a list of changes
   since last release.  This announcement highlights only the important
   changes.
 
-  IMPORTANT:  In 1.3.0 and 2.0.0, explicit dependencies (configured via
-  the Depends() call) are ignored for any nodes that do not have builders.
-  This known issue[1] will typically only happen if you explicitly
-  configure a builder call to create multiple output files, some of which
-  are "hidden" from SCons by not being listed in the targets list, and then
-  use Depends() to establish an explicit dependency on a "hidden" file.
 
-  [1] See http://scons.tigris.org/issues/show_bug.cgi?id=2647 for details.
+  Please note the following important changes since release 2.1.0:
+
+    --  New gettext toolset for internationalization
+
+    --  Support for Visual Studio 11
+
+    --  Support for Intel C/C++ compiler v12 on Linux and Mac
+
+    --  LaTeX support for multibib, biblatex and biber
 
   Please note the following important changes since release 2.0.0:
 
+    --  Support for Windows manifest generation
+
+    --  SCons now searches sitewide dirs for site_scons
+
     --  Support for Latex bibunits package has been added along with 
-        support for tex files generated by other builders.
+        support for tex files generated by other builders
 
 
   Please note the following important changes since release 1.3.0:
 
 RELEASE 2.X.X - 
 
+  From dubcanada on Bitbucket:
+    - Fix 32-bit Visual Express C++ on 64-bit Windows (generate 32-bit code)
+
+  From Paweł Tomulik:
+    - Added gettext toolset
+    - Fixed FindSourceFiles to find final sources (leaf nodes).
+
+  From Greg Ward:
+    - Allow Node objects in Java path (#2825)
+
+  From Joshua Hughes:
+    - Make Windows not redefine builtin file as un-inheritable (#2857)
+    - Fix WINDOWS_INSERT_DEF on MinGW (Windows) (#2856)
+
   From smallbub on Bitbucket:
     - Fix LINKCOMSTR, SHLINKCOMSTR, and LDMODULECOMSTR on Windows (#2833).
 
     - Fix cloning of builders when cloning environment (#2821).
 
   From Gary Oberbrunner:
+    - Support Intel C v12 compiler on Linux and Mac (not yet Windows)
     - Show valid Visual Studio architectures in error message
        when user passes invalid arch.
 
-  A new SCons checkpoint release, 2.1.0.alpha.yyyymmdd, is now available
+  A new SCons release, 2.1.0.alpha.yyyymmdd, is now available
   on the SCons download page:
 
           http://www.scons.org/download.php
 
-  XXX The primary purpose of this release ... XXX
+  This release adds several new features and fixes many issues.
 
-  A SCons "checkpoint release" is intended to provide early access to
-  new features so they can be tested in the field before being released
-  for adoption by other software distributions.
-
-  Note that a checkpoint release is developed using the same test-driven
-  development methodology as all SCons releases.  Existing SCons
-  functionality should all work as it does in previous releases (except
-  for any changes identified in the release notes) and early adopters
-  should be able to use a checkpoint release safely for production work
-  with existing SConscript files.  If not, it represents not only a bug
-  in SCons but also a hole in the regression test suite, and we want to
-  hear about it.
-
-  New features may be more lightly tested than in past releases,
-  especially as concerns their interaction with all of the other
-  functionality in SCons.  We are especially interested in hearing bug
-  reports about new functionality.
-
-  We do not recommend that downstream distributions (Debian, Fedora,
-  etc.) package a checkpoint release, mainly to avoid confusing the
-  "public" release numbering with the long checkpoint release names.
-
-  Here is a summary of the changes since 2.0:
+  Here is a summary of the changes since 2.1:
 
   NEW FUNCTIONALITY
 
-    - SCons now supports Microsoft Visual Studio 11.
-
-    - SCons can now automatically embed manifests in Windows executables
-      and DLLs, by setting WINDOWS_EMBED_MANIFEST in the environment.
-
-    - SCons now searches for site_scons dirs in several system-wide
-      and per-user locations, in addition to the SConstruct top dir.
-      This should enable much easier use of third-party (non-core)
-      Tools.
-
-    - List new features (presumably why a checkpoint is being released)
+    - New gettext toolset for internationalization
+    - Support for Visual Studio 11 (both using it and generating solution files)
+    - Support for Intel C/C++ compiler v12 on Linux and Mac
+    - LaTeX support for multibib, biblatex and biber
 
   DEPRECATED FUNCTIONALITY
 
-    - List anything that's been deprecated since the last release
+    - None
 
   CHANGED/ENHANCED EXISTING FUNCTIONALITY
 
-    - scons --version now prints the path to the SCons package in use
-
-    - List modifications to existing features, where the previous behavior
-      wouldn't actually be considered a bug
-
-    - Add initial support for VS/VC 2010
+    - 32-bit Visual Express C++ on 64-bit Windows now generates 32-bit code instead of giving errors
 
   FIXES
 
-    - Fixed occasional crashes with -jN on Windows.
-    - Windows resource compiler (RC) scanner now handles DOS line endings
-    - Visual Studio project generation now works when CPPPATH contains Dir nodes
-    - Visual Studio projects are regenerated when CPPPATH or CPPDEFINES change
-      NOTE: this will cause all MSVS projects to be regenerated with this version.
-    - Passing MSVC_BATCH=False works now (treated same as 0)
-    - Long compile lines no longer break MSVC_BATCH mode
-    - RPATH is now in LINKCOM rather than LINKFLAGS, so resetting
-      LINKFLAGS doesn't kill RPATH
-    - Precompiled headers on Windows no longer break when used with
-      variant dirs containing spaces.
-    - Delete can now delete symlinks to directories and broken symlinks
-    - CPPDEFINES containing dictionaries now work better.
-    - A problem with using implicit-cache and removing dependencies on
-      disk is corrected.
-    - A problem with FS Entries which are dirs and have builders
-      is corrected.
-    - A problem with Install() of a dir when the dest dir exists
-      is corrected.
-    - Windows subprocess output should now be more reliable.
-    - The users guide and man page have various fixes.
-    - Appending to default $*FLAGS in a copied environment
-      now works properly.
-    - LaTeX scanner is improved for broken lines or embedded spaces.
-    - Windows UNC paths (\\SERVER\SHARE\dir) now work much better.
-
-    - List fixes of outright bugs
+    - Fixed FindSourceFiles to find final sources (leaf nodes).
+    - Make Windows not redefine builtin file as un-inheritable (#2857)
+    - Fix WINDOWS_INSERT_DEF on MinGW (Windows) (#2856)
+    - Fix LINKCOMSTR, SHLINKCOMSTR, and LDMODULECOMSTR on Windows (#2833).
+    - Make -s (silent mode) be silent about entering subdirs (#2976).
+    - Fix cloning of builders when cloning environment (#2821).
+    - Fixed the Taskmaster, curing spurious build failures in
+      multi-threaded runs (#2720).
+    - Fixed scons-doc.py to properly convert main XML files (#2812).
 
 
   IMPROVEMENTS
 
-    - ParseFlags now supports -std=c++0x and related CXXFLAGS
-    - ParseFlags now supports -dylib_file from pkgconfig
-    - New debugging options to print unlink/relinking of variant files
-      (--debug=duplicate) and preparation of targets (--debug=prepare).
-    - SCons can now generate MSVS 9.0 and 10.0 Projects and Solutions.
-    - MSVS Solution generation is improved.
-    - Fortran 03 is supported (preliminary)
-    - .sx files are now treated as assembly sources.
-    - site_scons/site_init.py is now treated as a proper module
-      with __doc__, __file__ and __name__.
-    - TeX command strings now work on Windows when the new dir is
-      on a different drive letter.
-    - DMD version 2 is supported (using the phobos2 library)
-    - New --debug=prepare option shows each target as it's prepared
-      for building; can help when you don't know why a target isn't
-      being built.
-
-    - List improvements that wouldn't be visible to the user in the
-      documentation:  performance improvements (describe the circumstances
-      under which they would be observed), or major code cleanups
+    - Improved documentation of command-line variables (#2809).
+    - Show valid Visual Studio architectures in error message
+       when user passes invalid arch.
+    - Allow Node objects in Java path (#2825)
 
   PACKAGING
 
-    - List changes in the way SCons is packaged and/or released
-
-  DOCUMENTATION
-
-    - List any significant changes to the documentation (not individual
-      typo fixes, even if they're mentioned in src/CHANGES.txt to give
-      the contributor credit)
+    - No changes
 
   DEVELOPMENT
 
-    - List visible changes in the way SCons is developed
+    - No changes
 
-  Thanks to
+Thanks to:
   Dirk Baechle,
-  Vincent Beffara,
-  Grzegorz Bizoń,
+  Vincent Beffar,
   Jean-François Colson,
   Bauke Conijn,
   Bill Deegan,
   Ken Deeter,
+  dubcanada on Bitbucket,
   Luca Falavigna,
   Alexander Goomenyuk,
   Justin Gullingsrud,
+  Joshua Hughes,
+  Alexey Klimkin,
   Steven Knight,
   Arve Knudsen,
   Jean-Baptiste Lab,
   Rob Managan,
+  Mortoray,
   Gary Oberbrunner,
+  Alexey Petruchik,
   Evgeny Podjachev,
+  smallbub on Bitbucket,
   Sohail Somani,
   Anatoly Techtonik,
+  Paweł Tomulik,
+  Greg Ward,
   Allen Weeks,
   Russel Winder,
   Joe Zuntz

src/engine/MANIFEST-xml.in

 SCons/Tool/tlib.xml
 SCons/Tool/yacc.xml
 SCons/Tool/zip.xml
+SCons/Tool/gettext.xml
+SCons/Tool/msgfmt.xml
+SCons/Tool/msginit.xml
+SCons/Tool/msgmerge.xml
+SCons/Tool/xgettext.xml

src/engine/MANIFEST.in

 SCons/Variables/PackageVariable.py
 SCons/Variables/PathVariable.py
 SCons/Warnings.py
+SCons/Tool/GettextCommon.py
+SCons/Tool/gettext.py
+SCons/Tool/msgfmt.py
+SCons/Tool/msginit.py
+SCons/Tool/msgmerge.py
+SCons/Tool/xgettext.py

src/engine/SCons/Environment.py

                     sources.append(s)
         build_source(node.all_children())
 
-    # THIS CODE APPEARS TO HAVE NO EFFECT
-    #    # get the final srcnode for all nodes, this means stripping any
-    #    # attached build node by calling the srcnode function
-    #    for file in sources:
-    #        srcnode = file.srcnode()
-    #        while srcnode != file.srcnode():
-    #            srcnode = file.srcnode()
-
+        def final_source(node):
+            while (node != node.srcnode()):
+              node = node.srcnode()
+            return node
+        sources = map( final_source, sources );
         # remove duplicates
         return list(set(sources))
 

src/engine/SCons/Platform/win32.py

 
     _builtin_file = builtins.file
     _builtin_open = builtins.open
-    
-    def _scons_file(*args, **kw):
-        fp = _builtin_file(*args, **kw)
-        win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
-                                      win32con.HANDLE_FLAG_INHERIT,
-                                      0)
-        return fp
+
+    class _scons_file(_builtin_file):
+        def __init__(self, *args, **kw):
+            _builtin_file.__init__(self, *args, **kw)
+            win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()),
+                win32con.HANDLE_FLAG_INHERIT, 0)
 
     def _scons_open(*args, **kw):
         fp = _builtin_open(*args, **kw)

src/engine/SCons/Tool/GettextCommon.py

+"""SCons.Tool.GettextCommon module
+
+Used by several tools of `gettext` toolset.
+"""
+
+# __COPYRIGHT__
+# 
+# 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.
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Warnings
+import re
+
+#############################################################################
+class XgettextToolWarning(SCons.Warnings.Warning): pass
+class XgettextNotFound(XgettextToolWarning): pass
+class MsginitToolWarning(SCons.Warnings.Warning): pass
+class MsginitNotFound(MsginitToolWarning): pass
+class MsgmergeToolWarning(SCons.Warnings.Warning): pass
+class MsgmergeNotFound(MsgmergeToolWarning): pass
+class MsgfmtToolWarning(SCons.Warnings.Warning): pass
+class MsgfmtNotFound(MsgfmtToolWarning): pass
+#############################################################################
+SCons.Warnings.enableWarningClass(XgettextToolWarning)
+SCons.Warnings.enableWarningClass(XgettextNotFound)
+SCons.Warnings.enableWarningClass(MsginitToolWarning)
+SCons.Warnings.enableWarningClass(MsginitNotFound)
+SCons.Warnings.enableWarningClass(MsgmergeToolWarning)
+SCons.Warnings.enableWarningClass(MsgmergeNotFound)
+SCons.Warnings.enableWarningClass(MsgfmtToolWarning)
+SCons.Warnings.enableWarningClass(MsgfmtNotFound)
+#############################################################################
+
+#############################################################################
+class _POTargetFactory(object):
+  """ A factory of `PO` target files.
+  
+  Factory defaults differ from these of `SCons.Node.FS.FS`.  We set `precious`
+  (this is required by builders and actions gettext) and `noclean` flags by
+  default for all produced nodes.
+  """
+  def __init__( self, env, nodefault = True, alias = None, precious = True
+              , noclean = True ):
+    """ Object constructor.
+
+    **Arguments**
+
+        - *env* (`SCons.Environment.Environment`)
+        - *nodefault* (`boolean`) - if `True`, produced nodes will be ignored
+          from default target `'.'`
+        - *alias* (`string`) - if provided, produced nodes will be automatically
+          added to this alias, and alias will be set as `AlwaysBuild`
+        - *precious* (`boolean`) - if `True`, the produced nodes will be set as
+          `Precious`.
+        - *noclen* (`boolean`) - if `True`, the produced nodes will be excluded
+          from `Clean`.
+    """
+    self.env = env
+    self.alias = alias
+    self.precious = precious
+    self.noclean = noclean
+    self.nodefault = nodefault
+
+  def _create_node(self, name, factory, directory = None, create = 1):
+    """ Create node, and set it up to factory settings. """
+    import SCons.Util
+    node = factory(name, directory, create)
+    node.set_noclean(self.noclean)
+    node.set_precious(self.precious)
+    if self.nodefault:
+      self.env.Ignore('.', node)
+    if self.alias:
+      self.env.AlwaysBuild(self.env.Alias(self.alias, node))
+    return node
+
+  def Entry(self, name, directory = None, create = 1):
+    """ Create `SCons.Node.FS.Entry` """
+    return self._create_node(name, self.env.fs.Entry, directory, create)
+
+  def File(self, name, directory = None, create = 1):
+    """ Create `SCons.Node.FS.File` """
+    return self._create_node(name, self.env.fs.File, directory, create)
+#############################################################################
+
+#############################################################################
+_re_comment = re.compile(r'(#[^\n\r]+)$', re.M)
+_re_lang = re.compile(r'([a-zA-Z0-9_]+)', re.M)
+#############################################################################
+def _read_linguas_from_files(env, linguas_files = None):
+  """ Parse `LINGUAS` file and return list of extracted languages """
+  import SCons.Util
+  import SCons.Environment
+  global _re_comment
+  global _re_lang
+  if not SCons.Util.is_List(linguas_files) \
+  and not SCons.Util.is_String(linguas_files) \
+  and not isinstance(linguas_files, SCons.Node.FS.Base) \
+  and linguas_files:
+    # If, linguas_files==True or such, then read 'LINGUAS' file.
+    linguas_files = [ 'LINGUAS' ]
+  if linguas_files is None:
+    return []  
+  fnodes = env.arg2nodes(linguas_files)
+  linguas = []
+  for fnode in fnodes:
+    contents =  _re_comment.sub("", fnode.get_text_contents())
+    ls = [ l for l in _re_lang.findall(contents) if l ]
+    linguas.extend(ls)
+  return linguas 
+#############################################################################
+
+#############################################################################
+from SCons.Builder import BuilderBase
+#############################################################################
+class _POFileBuilder(BuilderBase):
+  """ `PO` file builder.
+
+  This is multi-target single-source builder. In typical situation the source
+  is single `POT` file, e.g. `messages.pot`, and there are multiple `PO`
+  targets to be updated from this `POT`. We must run
+  `SCons.Builder.BuilderBase._execute()` separatelly for each target to track
+  dependencies separatelly for each target file.
+  
+  **NOTE**: if we call `SCons.Builder.BuilderBase._execute(.., target, ...)`
+  with target being list of all targets, all targets would be rebuilt each time
+  one of the targets from this list is missing. This would happen, for example,
+  when new language `ll` enters `LINGUAS_FILE` (at this moment there is no
+  `ll.po` file yet). To avoid this, we override
+  `SCons.Builder.BuilerBase._execute()` and call it separatelly for each
+  target. Here we also append to the target list the languages read from
+  `LINGUAS_FILE`.
+  """
+  #
+  #* The argument for overriding _execute(): We must use environment with
+  #  builder overrides applied (see BuilderBase.__init__(). Here it comes for
+  #  free.
+  #* The argument against using 'emitter': The emitter is called too late
+  #  by BuilderBase._execute(). If user calls, for example:
+  #  
+  #    env.POUpdate(LINGUAS_FILE = 'LINGUAS')
+  #
+  #  the builder throws error, because it is called with target=None,
+  #  source=None and is trying to "generate" sources or target list first.
+  #  If user calls
+  #
+  #    env.POUpdate(['foo', 'baz'], LINGUAS_FILE = 'LINGUAS')
+  #
+  #  the env.BuilderWrapper() calls our builder with target=None,
+  #  source=['foo', 'baz']. The BuilderBase._execute() then splits execution
+  #  and execute iterativelly (recursion) self._execute(None, source[i]). 
+  #  After that it calls emitter (which is quite too late). The emitter is
+  #  also called in each iteration, what makes things yet worse.
+  def __init__(self, env, **kw):
+    if not 'suffix' in kw:
+       kw['suffix'] = '$POSUFFIX'
+    if not 'src_suffix' in kw:
+       kw['src_suffix'] = '$POTSUFFIX'
+    if not 'src_builder' in kw:
+       kw['src_builder'] = '_POTUpdateBuilder'
+    if not 'single_source' in kw:
+       kw['single_source'] = True
+    alias = None
+    if 'target_alias' in kw:
+       alias = kw['target_alias']
+       del kw['target_alias']
+    if not 'target_factory' in kw:
+       kw['target_factory'] = _POTargetFactory(env, alias=alias).File
+    BuilderBase.__init__(self, **kw)
+
+  def _execute(self, env, target, source, *args, **kw):
+    """ Execute builder's actions.
+    
+    Here we append to `target` the languages read from `$LINGUAS_FILE` and 
+    apply `SCons.Builder.BuilderBase._execute()` separatelly to each target.
+    The arguments and return value are same as for
+    `SCons.Builder.BuilderBase._execute()`. 
+    """
+    import SCons.Util
+    import SCons.Node
+    linguas_files = None
+    if env.has_key('LINGUAS_FILE') and env['LINGUAS_FILE']:
+      linguas_files = env['LINGUAS_FILE']
+      # This prevents endless recursion loop (we'll be invoked once for 
+      # each target appended here, we must not extend the list again).
+      env['LINGUAS_FILE'] = None
+      linguas = _read_linguas_from_files(env,linguas_files)
+      if SCons.Util.is_List(target):
+        target.extend(linguas)
+      elif target is not None:
+        target = [target] + linguas
+      else:
+        target = linguas
+    if not target:
+      # Let the SCons.BuilderBase to handle this patologic situation
+      return BuilderBase._execute( self, env, target, source, *args, **kw)
+    # The rest is ours
+    if not SCons.Util.is_List(target):
+      target = [ target ]
+    result = []
+    for tgt in target:
+      r = BuilderBase._execute( self, env, [tgt], source, *args, **kw)
+      result.extend(r)
+    if linguas_files is not None:
+      env['LINGUAS_FILE'] = linguas_files
+    return SCons.Node.NodeList(result)
+#############################################################################
+
+import SCons.Environment
+#############################################################################
+def _translate(env, target=[], source=SCons.Environment._null, *args, **kw):
+  """ Function for `Translate()` pseudo-builder """
+  pot = env.POTUpdate(None, source, *args, **kw)
+  po = env.POUpdate(target, pot, *args, **kw)
+  return po
+#############################################################################
+
+#############################################################################
+class RPaths(object):
+  """ Callable object, which returns pathnames relative to SCons current
+  working directory.
+
+  It seems like `SCons.Node.FS.Base.get_path()` returns absolute paths
+  for nodes that are outside of current working directory (`env.fs.getcwd()`).
+  Here, we often have `SConscript`, `POT` and `PO` files within `po/`
+  directory and source files (e.g. `*.c`) outside of it. When generating `POT`
+  template file, references to source files are written to `POT` template, so
+  a translator may later quickly jump to appropriate source file and line from
+  its `PO` editor (e.g. `poedit`).  Relative paths in  `PO` file are usually
+  interpreted by `PO` editor as paths relative to the place, where `PO` file
+  lives. The absolute paths would make resultant `POT` file nonportable, as
+  the references would be correct only on the machine, where `POT` file was
+  recently re-created. For such reason, we need a function, which always
+  returns relative paths. This is the purpose of `RPaths` callable object.
+
+  The `__call__` method returns paths relative to current woking directory, but
+  we assume, that *xgettext(1)* is run from the directory, where target file is
+  going to be created.
+
+  Note, that this may not work for files distributed over several hosts or
+  across different drives on windows. We assume here, that single local
+  filesystem holds both source files and target `POT` templates.
+
+  Intended use of `RPaths` - in `xgettext.py`::
+
+    def generate(env):
+        from GettextCommon import RPaths
+        ...
+        sources = '$( ${_concat( "", SOURCES, "", __env__, XgettextRPaths, TARGET, SOURCES)} $)'
+        env.Append(
+          ...
+          XGETTEXTCOM = 'XGETTEXT ... ' + sources,
+          ...
+          XgettextRPaths = RPaths(env)
+        )
+  """
+  # NOTE: This callable object returns pathnames of dirs/files relative to
+  # current working directory. The pathname remains relative also for entries
+  # that are outside of current working directory (node, that
+  # SCons.Node.FS.File and siblings return absolute path in such case). For
+  # simplicity we compute path relative to current working directory, this
+  # seems be enough for our purposes (don't need TARGET variable and
+  # SCons.Defaults.Variable_Caller stuff).
+  
+  def __init__(self, env):
+    """ Initialize `RPaths` callable object.
+
+      **Arguments**:
+
+        - *env* - a `SCons.Environment.Environment` object, defines *current
+          working dir*.
+    """
+    self.env = env
+
+  # FIXME: I'm not sure, how it should be implemented (what the *args are in
+  # general, what is **kw).
+  def __call__(self, nodes, *args, **kw):
+    """ Return nodes' paths (strings) relative to current working directory. 
+    
+      **Arguments**:
+
+        - *nodes* ([`SCons.Node.FS.Base`]) - list of nodes.
+        - *args* -  currently unused.
+        - *kw* - currently unused.
+
+      **Returns**:
+
+       - Tuple of strings, which represent paths relative to current working
+         directory (for given environment).
+    """
+    # os.path.relpath is available only on python >= 2.6. We use our own
+    # implementation. It's taken from BareNecessities package:
+    #   http://jimmyg.org/work/code/barenecessities/index.html
+    from posixpath import curdir
+    def relpath(path, start=curdir):
+        import posixpath
+        """Return a relative version of a path"""
+        if not path:
+           raise ValueError("no path specified")
+        start_list = posixpath.abspath(start).split(posixpath.sep)
+        path_list = posixpath.abspath(path).split(posixpath.sep)
+        # Work out how much of the filepath is shared by start and path.
+        i = len(posixpath.commonprefix([start_list, path_list]))
+        rel_list = [posixpath.pardir] * (len(start_list)-i) + path_list[i:]
+        if not rel_list:
+           return posixpath.curdir
+        return posixpath.join(*rel_list)
+    import os 
+    import SCons.Node.FS
+    rpaths = ()
+    cwd =  self.env.fs.getcwd().get_abspath()
+    for node in nodes:
+      rpath = None
+      if isinstance(node, SCons.Node.FS.Base):
+        rpath = relpath(node.get_abspath(), cwd)
+      # FIXME: Other types possible here?
+      if rpath is not None:
+        rpaths += (rpath,)
+    return rpaths
+#############################################################################
+   
+#############################################################################
+def _init_po_files(target, source, env):
+  """ Action function for `POInit` builder. """
+  nop = lambda target, source, env : 0
+  if env.has_key('POAUTOINIT'):
+    autoinit = env['POAUTOINIT']
+  else:
+    autoinit = False
+  # Well, if everything outside works well, this loop should do single
+  # iteration. Otherwise we are rebuilding all the targets even, if just
+  # one has changed (but is this out fault?).
+  for tgt in target:
+    if not tgt.exists():
+      if autoinit:
+        action = SCons.Action.Action('$MSGINITCOM', '$MSGINITCOMSTR')
+      else:
+        msg = 'File ' + repr(str(tgt)) + ' does not exist. ' \
+            + 'If you are a translator, you can create it through: \n' \
+            + '$MSGINITCOM'
+        action = SCons.Action.Action(nop, msg)
+      status = action([tgt], source, env)
+      if status: return status
+  return 0
+#############################################################################
+
+#############################################################################
+def _detect_xgettext(env):
+  """ Detects *xgettext(1)* binary """
+  if env.has_key('XGETTEXT'):
+    return env['XGETTEXT']
+  xgettext = env.Detect('xgettext');
+  if xgettext:
+    return xgettext
+  raise SCons.Errors.StopError(XgettextNotFound,"Could not detect xgettext")
+  return None
+#############################################################################
+def _xgettext_exists(env):
+  return _detect_xgettext(env)
+#############################################################################
+
+#############################################################################
+def _detect_msginit(env):
+  """ Detects *msginit(1)* program. """
+  if env.has_key('MSGINIT'):
+    return env['MSGINIT']
+  msginit = env.Detect('msginit');
+  if msginit:
+    return msginit
+  raise SCons.Errors.StopError(MsginitNotFound, "Could not detect msginit")
+  return None
+#############################################################################
+def _msginit_exists(env):
+  return  _detect_msginit(env)
+#############################################################################
+
+#############################################################################
+def _detect_msgmerge(env):
+  """ Detects *msgmerge(1)* program. """
+  if env.has_key('MSGMERGE'):
+    return env['MSGMERGE']
+  msgmerge = env.Detect('msgmerge');
+  if msgmerge:
+    return msgmerge
+  raise SCons.Errors.StopError(MsgmergeNotFound, "Could not detect msgmerge")
+  return None
+#############################################################################
+def _msgmerge_exists(env):
+  return  _detect_msgmerge(env)
+#############################################################################
+
+#############################################################################
+def _detect_msgfmt(env):
+  """ Detects *msgmfmt(1)* program. """
+  if env.has_key('MSGFMT'):
+    return env['MSGFMT']
+  msgfmt = env.Detect('msgfmt');
+  if msgfmt:
+    return msgfmt
+  raise SCons.Errors.StopError(MsgfmtNotFound, "Could not detect msgfmt")
+  return None
+#############################################################################
+def _msgfmt_exists(env):
+  return _detect_msgfmt(env)
+#############################################################################
+
+#############################################################################
+def tool_list(platform, env):
+  """ List tools that shall be generated by top-level `gettext` tool """
+  return [ 'xgettext', 'msginit', 'msgmerge', 'msgfmt' ]
+#############################################################################
+

src/engine/SCons/Tool/MSCommon/vc.py

     # The TARGET_ARCH is amd64 then also try 32 bits if there are no viable
     # 64 bit tools installed
     try_target_archs = [target_platform]
-    if not req_target_platform and target_platform=='amd64':
+    if not req_target_platform and target_platform in ('amd64','x86_64'):
         try_target_archs.append('x86')
 
     d = None

src/engine/SCons/Tool/gettext.py

+"""gettext tool
+"""
+
+
+# __COPYRIGHT__
+# 
+# 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.
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+#############################################################################
+def generate(env,**kw):
+  import SCons.Tool
+  from SCons.Tool.GettextCommon \
+    import  _translate, tool_list
+  for t in tool_list(env['PLATFORM'], env):
+    env.Tool(t)
+  env.AddMethod(_translate, 'Translate')
+#############################################################################
+
+#############################################################################
+def exists(env):
+  from SCons.Tool.GettextCommon \
+  import _xgettext_exists, _msginit_exists, \
+         _msgmerge_exists, _msgfmt_exists
+  return _xgettext_exists(env) and _msginit_exists(env) \
+     and _msgmerge_exists(env) and _msgfmt_exists(env)
+#############################################################################

src/engine/SCons/Tool/gettext.xml

+<!--
+__COPYRIGHT__
+
+This file is processed by the bin/SConsDoc.py module.
+See its __doc__ string for a discussion of the format.
+-->
+<tool name="gettext">
+<summary>
+This is actually a toolset, which supports internationalization and
+localization of sofware being constructed with SCons. The toolset loads
+following tools:
+
+<itemizedlist mark='opencircle'>
+  <listitem><para>
+    &t-link-xgettext; - to extract internationalized messages from source code to 
+    <literal>POT</literal> file(s),
+  </para></listitem>
+  <listitem><para>
+    &t-link-msginit; - may be optionally used to initialize <literal>PO</literal>
+    files,
+  </para></listitem>
+  <listitem><para>
+    &t-link-msgmerge; - to update <literal>PO</literal> files, that already contain
+    translated messages,</para></listitem>
+  <listitem><para>
+    &t-link-msgfmt; - to compile textual <literal>PO</literal> file to binary
+    installable <literal>MO</literal> file.
+  </para></listitem>
+</itemizedlist>
+
+When you enable &t-gettext;, it internally loads all abovementioned tools,
+so you're encouraged to see their individual documentation.
+
+Each of the above tools provides its own builder(s) which may be used to
+perform particular activities related to software internationalization. You
+may be however interested in <emphasis>top-level</emphasis> builder
+&b-Translate; described few paragraphs later.
+
+To use &t-gettext; tools add <literal>'gettext'</literal> tool to your
+environment:
+<example>
+  env = Environment( tools = ['default', 'gettext'] )
+</example>
+</summary>
+<sets>
+</sets>
+<uses>
+<!-- PLATFORM -->
+</uses>
+</tool>
+
+<builder name="Translate">
+<summary>
+This pseudo-builder belongs to &t-link-gettext; toolset. The builder extracts
+internationalized messages from source files, updates <literal>POT</literal>
+template (if necessary) and then updates <literal>PO</literal> translations (if
+necessary). If &cv-link-POAUTOINIT; is set, missing <literal>PO</literal> files
+will be automatically created (i.e. without translator person intervention).
+The variables &cv-link-LINGUAS_FILE; and &cv-link-POTDOMAIN; are taken into
+acount too. All other construction variables used by &b-link-POTUpdate;, and
+&b-link-POUpdate; work here too.
+
+<emphasis>Example 1</emphasis>.
+The simplest way is to specify input files and output languages inline in
+a SCons script when invoking &b-Translate;
+<example>
+# SConscript in 'po/' directory
+env = Environment( tools = ["default", "gettext"] )
+env['POAUTOINIT'] = 1
+env.Translate(['en','pl'], ['../a.cpp','../b.cpp']) 
+</example>
+
+<emphasis>Example 2</emphasis>.
+If you wish, you may also stick to conventional style known from
+<productname>autotools</productname>, i.e. using
+<filename>POTFILES.in</filename> and <filename>LINGUAS</filename> files
+<example>
+# LINGUAS
+en pl 
+#end
+</example>
+
+<example>
+# POTFILES.in
+a.cpp
+b.cpp
+# end
+</example>
+
+<example>
+# SConscript
+env = Environment( tools = ["default", "gettext"] )
+env['POAUTOINIT'] = 1
+env['XGETTEXTPATH'] = ['../']
+env.Translate(LINGUAS_FILE = 1, XGETTEXTFROM = 'POTFILES.in') 
+</example>
+
+The last approach is perhaps the recommended one. It allows easily split
+internationalization/localization onto separate SCons scripts, where a script
+in source tree is responsible for translations (from sources to
+<literal>PO</literal> files) and script(s) under variant directories are
+responsible for compilation of <literal>PO</literal> to <literal>MO</literal>
+files to and for installation of <literal>MO</literal> files. The "gluing
+factor" synchronizing these two scripts is then the content of
+<filename>LINGUAS</filename> file.  Note, that the updated
+<literal>POT</literal> and <literal>PO</literal> files are usually going to be
+committed back to the repository, so they must be updated within the source
+directory (and not in variant directories). Additionaly, the file listing of
+<filename>po/</filename> directory contains <filename>LINGUAS</filename> file,
+so the source tree looks familiar to translators, and they may work with the
+project in their usual way.
+
+<emphasis>Example 3</emphasis>.
+Let's prepare a development tree as below
+<example>
+ project/
+  + SConstruct
+  + build/        
+  + src/
+      + po/
+          + SConscript
+          + SConscript.i18n
+          + POTFILES.in
+          + LINGUAS
+</example>
+with <filename>build</filename> being variant directory. Write the top-level
+<filename>SConstruct</filename> script as follows
+<example>
+  # SConstruct
+  env = Environment( tools = ["default", "gettext"] )
+  VariantDir('build', 'src', duplicate = 0)
+  env['POAUTOINIT'] = 1
+  SConscript('src/po/SConscript.i18n', exports = 'env')
+  SConscript('build/po/SConscript', exports = 'env')
+</example>
+the <filename>src/po/SConscript.i18n</filename> as
+<example>
+  # src/po/SConscript.i18n
+  Import('env')
+  env.Translate(LINGUAS_FILE=1, XGETTEXTFROM='POTFILES.in', XGETTEXTPATH=['../'])
+</example>
+and the <filename>src/po/SConscript</filename>
+<example>
+  # src/po/SConscript
+  Import('env')
+  env.MOFiles(LINGUAS_FILE = 1)
+</example>
+Such setup produces <literal>POT</literal> and <literal>PO</literal> files
+under source tree in <filename>src/po/</filename> and binary
+<literal>MO</literal> files under variant tree in
+<filename>build/po/</filename>. This way the <literal>POT</literal> and
+<literal>PO</literal> files are separated from other output files, which must
+not be committed back to source repositories (e.g. <literal>MO</literal>
+files).
+
+<note><para>In above example, the <literal>PO</literal> files are not updated,
+nor created automatically when you issue <command>scons '.'</command> command.
+The files must be updated (created) by hand via <command>scons
+po-update</command> and then <literal>MO</literal> files can be compiled by
+running <command>scons '.'</command>.</para></note>
+
+</summary>
+</builder>
+
+<cvar name="POTDOMAIN">
+<summary>
+The &cv-POTDOMAIN; defines default domain, used to generate
+<literal>POT</literal> filename as <filename>&cv-POTDOMAIN;.pot</filename> when
+no <literal>POT</literal> file name is provided by the user. This applies to
+&b-link-POTUpdate;, &b-link-POInit; and &b-link-POUpdate; builders (and
+builders, that use them, e.g. &b-Translate;). Normally (if &cv-POTDOMAIN; is
+not defined), the builders use <filename>messages.pot</filename> as default
+<literal>POT</literal> file name.
+</summary>
+</cvar>
+
+<cvar name="POAUTOINIT">
+<summary>
+The &cv-POAUTOINIT; variable, if set to <literal>True</literal> (on non-zero
+numeric value), let the &t-link-msginit; tool to automatically initialize
+<emphasis>missing</emphasis> <literal>PO</literal> files with
+<command>msginit(1)</command>.  This applies to both,
+&b-link-POInit; and &b-link-POUpdate; builders (and others that use any of
+them).
+</summary>
+</cvar>
+
+<cvar name="LINGUAS_FILE">
+<summary>
+The &cv-LINGUAS_FILE; defines file(s) containing list of additional linguas
+to be processed by &b-link-POInit;, &b-link-POUpdate; or &b-link-MOFiles;
+builders. It also affects &b-link-Translate; builder. If the variable contains
+a string, it defines name of the list file. The &cv-LINGUAS_FILE; may be a
+list of file names as well. If &cv-LINGUAS_FILE; is set to
+<literal>True</literal> (or non-zero numeric value), the list will be read from
+default file named
+<filename>LINGUAS</filename>.
+
+</summary>
+</cvar>

src/engine/SCons/Tool/intelc.py

     Always returns an old-style float like 80 or 90 for compatibility with Windows.
     Shades of Y2K!"""
     # Check for version number like 9.1.026: return 91.026
+    # XXX needs to be updated for 2011+ versions (like 2011.11.344 which is compiler v12.1.5)
     m = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)', vstr)
     if m:
         vmaj,vmin,build = m.groups()
         except EnvironmentError:
             # no more subkeys
             pass
-    elif is_linux:
+    elif is_linux or is_mac:
         for d in glob.glob('/opt/intel_cc_*'):
             # Typical dir here is /opt/intel_cc_80.
             m = re.search(r'cc_(.*)$', d)
             m = re.search(r'([0-9][0-9.]*)$', d)
             if m:
                 versions.append(m.group(1))
-    elif is_mac:
-        for d in glob.glob('/opt/intel/cc*/*'):
-            # Typical dir here is /opt/intel/cc/9.0 for IA32,
-            # /opt/intel/cce/9.0 for EMT64 (AMD64)
+        for d in glob.glob('/opt/intel/composerxe-*'):
+            # Typical dir here is /opt/intel/composerxe-2011.4.184
             m = re.search(r'([0-9][0-9.]*)$', d)
             if m:
                 versions.append(m.group(1))
+        for d in glob.glob('/opt/intel/composer_xe_*'):
+            # Typical dir here is /opt/intel/composer_xe_2011_sp1.11.344
+            # The _sp1 is useless, the installers are named 2011.9.x, 2011.10.x, 2011.11.x
+            m = re.search(r'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d)
+            if m:
+                versions.append("%s.%s"%(m.group(1), m.group(2)))
     def keyfunc(str):
         """Given a dot-separated version string, return a tuple of ints representing it."""
         return [int(x) for x in str.split('.')]
                     top = d
                     break
             return top
-        top = find_in_2010style_dir(version) or find_in_2008style_dir(version)
-        print "INTELC: top=",top
+        def find_in_2011style_dir(version):
+            # The 2011 (compiler v12) dirs are inconsistent, so just redo the search from
+            # get_all_compiler_versions and look for a match (search the newest form first)
+            top=None
+            for d in glob.glob('/opt/intel/composer_xe_*'):
+                # Typical dir here is /opt/intel/composer_xe_2011_sp1.11.344
+                # The _sp1 is useless, the installers are named 2011.9.x, 2011.10.x, 2011.11.x
+                m = re.search(r'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d)
+                if m:
+                    cur_ver = "%s.%s"%(m.group(1), m.group(2))
+                    if cur_ver == version and \
+                        (os.path.exists(os.path.join(d, "bin", "ia32", "icc")) or
+                        os.path.exists(os.path.join(d, "bin", "intel64", "icc"))):
+                        top = d
+                        break
+            if not top:
+                for d in glob.glob('/opt/intel/composerxe-*'):
+                    # Typical dir here is /opt/intel/composerxe-2011.4.184
+                    m = re.search(r'([0-9][0-9.]*)$', d)
+                    if m and m.group(1) == verison and \
+                        (os.path.exists(os.path.join(d, "bin", "ia32", "icc")) or
+                        os.path.exists(os.path.join(d, "bin", "intel64", "icc"))):
+                            top = d
+                            break
+            return top
+        top = find_in_2011style_dir(version) or find_in_2010style_dir(version) or find_in_2008style_dir(version)
+        # print "INTELC: top=",top
         if not top:
             raise MissingDirError("Can't find version %s Intel compiler in %s (abi='%s')"%(version,top, abi))
     return top

src/engine/SCons/Tool/javac.py

         if path and not SCons.Util.is_List(path):
             path = [path]
         if self.default:
-            path = path + [ env[self.default] ]
+            default = env[self.default]
+            if default:
+                if not SCons.Util.is_List(default):
+                    default = [default]
+                path = path + default
         if path:
-            return [self.opt, os.pathsep.join(path)]
-            #return self.opt + " " + os.pathsep.join(path)
+            return [self.opt, os.pathsep.join(map(str, path))]
         else:
             return []
-            #return ""
 
 def Java(env, target, source, *args, **kw):
     """

src/engine/SCons/Tool/javacTests.py

+#
+# __COPYRIGHT__
+#
+# 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.
+#
+
+import os
+import unittest
+
+import SCons.Tool.javac
+
+class DummyNode(object):
+    def __init__(self, val):
+        self.val = val
+
+    def __str__(self):
+        return str(self.val)
+
+class pathoptTestCase(unittest.TestCase):