Anonymous avatar Anonymous committed 7c2019f

Merged revisions 3088-3319,3321-3322,3324-3349,3351-3481,3483-3484,3486-3520,3522-3565,3567-3595,3597-3684,3686-3694,3696-3711,3713-3830,3832-3857,3859-3931,3933-3967,3969-3982,3984-3998,4000-4005,4007-4010,4012-4023 via svnmerge from
http://scons.tigris.org/svn/scons/branches/vs_revamp

................
r3089 | cournape | 2008-06-17 20:20:32 -0700 (Tue, 17 Jun 2008) | 3 lines

Initialized merge tracking via "svnmerge" with revisions "1-3088" from
http://scons.tigris.org/svn/scons/branches/core
................
r3090 | cournape | 2008-06-18 02:36:58 -0700 (Wed, 18 Jun 2008) | 1 line

Start working on MSVCCommon: we can find the product dir from registry and/or VS*COMTOOLS.
................
r3102 | cournape | 2008-06-24 01:22:38 -0700 (Tue, 24 Jun 2008) | 1 line

Get output from the bat file for vs.
................
r3103 | cournape | 2008-06-24 01:26:21 -0700 (Tue, 24 Jun 2008) | 1 line

Add function to parse vcbat output into env var.
................
r3104 | cournape | 2008-06-24 01:42:47 -0700 (Tue, 24 Jun 2008) | 1 line

Fix parsing output.
................
r3105 | cournape | 2008-06-24 02:06:56 -0700 (Tue, 24 Jun 2008) | 1 line

Set directly the variables to a list of path.
................
r3106 | cournape | 2008-06-24 02:28:43 -0700 (Tue, 24 Jun 2008) | 1 line

Add a function get_new to get only new paths which are added by the .bat file.
................
r3107 | cournape | 2008-06-24 02:45:28 -0700 (Tue, 24 Jun 2008) | 1 line

Better code for parse_output: do not swing with keys unnecessarily.
................
r3108 | cournape | 2008-06-24 02:56:06 -0700 (Tue, 24 Jun 2008) | 1 line

Put everything together in varbat_variables function.
................
r3109 | cournape | 2008-06-24 03:03:36 -0700 (Tue, 24 Jun 2008) | 1 line

More code cleaning for parse_output.
................
r3110 | cournape | 2008-06-24 03:07:25 -0700 (Tue, 24 Jun 2008) | 1 line

Handle empty path.
................
r3111 | cournape | 2008-06-24 03:23:41 -0700 (Tue, 24 Jun 2008) | 1 line

Add MSVCCommon to the manifest.
................
r3112 | cournape | 2008-06-24 03:24:16 -0700 (Tue, 24 Jun 2008) | 1 line

Plug the code to get env from reg/env to msvc tool.
................
r3319 | cournape | 2008-08-28 00:53:53 -0700 (Thu, 28 Aug 2008) | 188 lines

Merged revisions 3094,3115-3128,3181-3182,3194,3204,3206,3217-3218,3231,3237-3247,3249,3265 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core

................
r3094 | stevenknight | 2008-06-20 01:52:16 +0900 (Fri, 20 Jun 2008) | 3 lines

Change the User's Guide to use the new Variables object and its
associated function for controlling command-line build variables.
................
r3115 | stevenknight | 2008-06-25 22:46:36 +0900 (Wed, 25 Jun 2008) | 2 lines

Issue 2072: end indentation after generated Builder text.
................
r3116 | stevenknight | 2008-06-26 11:07:15 +0900 (Thu, 26 Jun 2008) | 2 lines

Reorganize the command-line arguments chapter.
................
r3117 | stevenknight | 2008-06-26 11:13:58 +0900 (Thu, 26 Jun 2008) | 2 lines

Editing pass for formatting in the Glob() sections.
................
r3118 | stevenknight | 2008-06-26 11:23:09 +0900 (Thu, 26 Jun 2008) | 3 lines

Wording changing: Preventing => Controlling, because the chapter
also talks about how to clean additional targets.
................
r3119 | stevenknight | 2008-06-26 11:50:41 +0900 (Thu, 26 Jun 2008) | 2 lines

Fix missing </literal> tags, minor wording fix.
................
r3120 | stevenknight | 2008-06-26 11:58:34 +0900 (Thu, 26 Jun 2008) | 2 lines

Add "the Default Function" to the appropriate subsection title.
................
r3121 | stevenknight | 2008-06-27 00:33:43 +0900 (Fri, 27 Jun 2008) | 2 lines

Issue 1988: Document the Variables.UnknownVariables() method.
................
r3122 | stevenknight | 2008-06-27 00:35:51 +0900 (Fri, 27 Jun 2008) | 3 lines

Remove comments listing some of the variables that have been
documented recently.
................
r3123 | stevenknight | 2008-06-27 04:42:53 +0900 (Fri, 27 Jun 2008) | 2 lines

Issue 2118: Fix incorrectly swapped man page text. (Alexey Zezukin)
................
r3124 | bdbaddog | 2008-06-27 13:23:46 +0900 (Fri, 27 Jun 2008) | 2 lines

Fix bug 2108 - duplicate text in description of interactive mode
................
r3125 | stevenknight | 2008-06-28 13:54:56 +0900 (Sat, 28 Jun 2008) | 3 lines

Issue 1993: Document the $*COMSTR variables, the Progress() function,
and create a common "Controlling Build Output" chapter.
................
r3126 | garyo | 2008-06-28 21:46:44 +0900 (Sat, 28 Jun 2008) | 1 line

Fix issue 2105; temporarily omit doc saying that SetOption can override user-created Options (until that is implemented).
................
r3127 | stevenknight | 2008-06-28 23:29:18 +0900 (Sat, 28 Jun 2008) | 2 lines

Issue 1747: Explicitly document use of Node lists as input to Depends().
................
r3128 | stevenknight | 2008-06-28 23:48:32 +0900 (Sat, 28 Jun 2008) | 6 lines

White space change: indent the construction environment sections
further to make way for combining this chapter with others to make
one big "Controlling Environments" chapter.
Also, get rid of some now-unnecessary doc from the old Cons classic
POD, that was taking up space here waiting to be documented.
................
r3181 | stevenknight | 2008-07-08 23:17:27 +0900 (Tue, 08 Jul 2008) | 4 lines

Reorganize the discussion of different environments into one chapter.
Document the SetDefault(), PrependUnique(), AppendUnique(),
PrependENVPath() and AppendENVPath() functions.
................
r3182 | stevenknight | 2008-07-09 00:47:55 +0900 (Wed, 09 Jul 2008) | 2 lines

Issue 1998: Docment the ARGLIST variable in the User's Guide.
................
r3194 | GregNoel | 2008-07-10 15:16:51 +0900 (Thu, 10 Jul 2008) | 1 line

remove unnecessary trailing spaces on lines
................
r3204 | stevenknight | 2008-07-12 00:29:18 +0900 (Sat, 12 Jul 2008) | 2 lines

Issue 1853: Remove referenc to SCons.Util.CLVar from a doc example.
................
r3206 | GregNoel | 2008-07-12 18:08:19 +0900 (Sat, 12 Jul 2008) | 1 line

Another go at describing VariantDir()
................
r3217 | stevenknight | 2008-07-16 22:52:44 +0900 (Wed, 16 Jul 2008) | 2 lines

Update the copyright year in the User's Guide.
................
r3218 | stevenknight | 2008-07-16 23:08:52 +0900 (Wed, 16 Jul 2008) | 3 lines

Issue 1881: Add man page text clarifying the behavior of
Add{Pre,Post}Action() when multiple targets are specified.
................
r3231 | stevenknight | 2008-07-22 17:58:11 +0900 (Tue, 22 Jul 2008) | 4 lines

Enhance MSVSProject() tests so they're runnable on any system, regardless
of whether Visual Studio is installed, or if it's even a Windows system
at all.
................
r3237 | GregNoel | 2008-07-26 16:07:49 +0900 (Sat, 26 Jul 2008) | 1 line

Issue 1983: Document ParseConfig, MergeFlags, and ParseFlags for the Users' Guide
................
r3238 | stevenknight | 2008-07-27 00:38:18 +0900 (Sun, 27 Jul 2008) | 3 lines

Follow-ons for building the User's Guide with Greg's recent additions
for MergeFlags() and ParseFlags().
................
r3239 | stevenknight | 2008-07-27 01:52:40 +0900 (Sun, 27 Jul 2008) | 3 lines

Re-arrange some sections talking about creating construction environments
and fetching/expanding variables.
................
r3240 | stevenknight | 2008-07-27 04:16:11 +0900 (Sun, 27 Jul 2008) | 2 lines

Stylistic editing of new {Merge,Parse}{Config,Flags} sections.
................
r3241 | GregNoel | 2008-07-27 04:42:42 +0900 (Sun, 27 Jul 2008) | 1 line

Issue 1987: Document SideEffect for Users' Guide (incomplete)
................
r3242 | stevenknight | 2008-07-27 05:27:56 +0900 (Sun, 27 Jul 2008) | 2 lines

Correct dumb XML mistakes in my last checkin.
................
r3243 | stevenknight | 2008-07-27 05:34:05 +0900 (Sun, 27 Jul 2008) | 2 lines

One-character typo. Gah.
................
r3244 | stevenknight | 2008-07-27 05:44:14 +0900 (Sun, 27 Jul 2008) | 2 lines

Issue 1977,1980: document the Exit() and Flatten() functions.
................
r3245 | stevenknight | 2008-07-28 02:24:12 +0900 (Mon, 28 Jul 2008) | 14 lines

Updates to the new SideEffect section (kudos to Greg).

While working on this, Greg discovered a bug (issue #2154) that prevents
a SideEffect() file from being used as input to another builder call; it
makes the builder target not get build when run in paralle (e.g. -j2)...
:-( So this patch comments out that section of Greg's section.

This also contains my usual editing pass. In this case I changed some
of the examples and added a bunch of text to try to help clarify some
things that seemed important. I also added a closing paragraph warning
that SideEffect() really shouldn't be used as an alternative to specifying
multiple target files in a Builder call when a command builds more than
one file that you care about.
................
r3246 | stevenknight | 2008-07-28 02:31:17 +0900 (Mon, 28 Jul 2008) | 2 lines

Proofreading edits of the MergeFlags() section. (Greg Noel)
................
r3247 | stevenknight | 2008-07-28 03:17:27 +0900 (Mon, 28 Jul 2008) | 2 lines

Issue 1976: document ensure{Python,SCons}Version() in the User's Guide.
................
r3249 | GregNoel | 2008-07-29 07:57:00 +0900 (Tue, 29 Jul 2008) | 1 line

Add svn-bisect script
................
r3265 | stevenknight | 2008-08-09 23:08:40 +0900 (Sat, 09 Aug 2008) | 14 lines

Merged revisions 3060-3264 via svnmerge from
http://scons.tigris.org/svn/scons/trunk

........
r3092 | stevenknight | 2008-06-19 06:35:38 -0700 (Thu, 19 Jun 2008) | 2 lines

Fix typo: caes => case(s).
........
r3093 | stevenknight | 2008-06-19 06:42:52 -0700 (Thu, 19 Jun 2008) | 3 lines

Another typo fix (cse => case) and clarification of why submitting a
test case is good.
........
................
................
r3321 | cournape | 2008-08-28 01:24:20 -0700 (Thu, 28 Aug 2008) | 1 line

Fix indenting issues.
................
r3324 | cournape | 2008-08-29 04:56:16 -0700 (Fri, 29 Aug 2008) | 2 lines

Fix eol to unix for msvc files.
................
r3398 | cournape | 2008-09-12 23:55:41 -0700 (Fri, 12 Sep 2008) | 2 lines

Add a function FindMSVSBatFile.
................
r3399 | cournape | 2008-09-12 23:56:03 -0700 (Fri, 12 Sep 2008) | 6 lines

Merge commit '5258bd36b856d1f042aa9ca8df419af96e1d7bf8' into work

Conflicts:

src/engine/SCons/Tool/MSVCCommon.py
................
r3400 | cournape | 2008-09-13 02:13:24 -0700 (Sat, 13 Sep 2008) | 1 line
................
r3403 | cournape | 2008-09-13 22:02:26 -0700 (Sat, 13 Sep 2008) | 1 line

Do not use None as default argument for FindMSVSBatFile, as it does not make sense.
................
r3404 | cournape | 2008-09-13 22:06:23 -0700 (Sat, 13 Sep 2008) | 1 line

Do not raise IOError in find_ functions, but return None.
................
r3405 | cournape | 2008-09-13 22:35:59 -0700 (Sat, 13 Sep 2008) | 1 line

Remove common paths between os.environ and var parsed by ParseBatFile.
................
r3406 | cournape | 2008-09-13 22:50:00 -0700 (Sat, 13 Sep 2008) | 1 line

Add MergeMSVSBatFile function.
................
r3407 | cournape | 2008-09-13 23:12:19 -0700 (Sat, 13 Sep 2008) | 2 lines

Remove trailing spaces.
................
r3408 | cournape | 2008-09-13 23:12:47 -0700 (Sat, 13 Sep 2008) | 2 lines

Remove printing debug statement.
................
r3409 | cournape | 2008-09-13 23:13:16 -0700 (Sat, 13 Sep 2008) | 2 lines

Improve documentation of public functions for MSVCCommon.py.
................
r3410 | cournape | 2008-09-13 23:23:09 -0700 (Sat, 13 Sep 2008) | 2 lines

Set a default version of use for MergeMSVSBatFile.
................
r3411 | cournape | 2008-09-13 23:23:31 -0700 (Sat, 13 Sep 2008) | 2 lines

Update examples.
................
r3412 | cournape | 2008-09-13 23:23:54 -0700 (Sat, 13 Sep 2008) | 2 lines

Look for several versions before giving up.
................
r3413 | cournape | 2008-09-13 23:24:17 -0700 (Sat, 13 Sep 2008) | 2 lines

Improve documentation for MergeMSVSBatFile.
................
r3483 | cournape | 2008-09-25 22:20:11 -0700 (Thu, 25 Sep 2008) | 1 line

Indent docstrings correctly.
................
r3486 | cournape | 2008-09-26 00:17:47 -0700 (Fri, 26 Sep 2008) | 1 line

Use PrependENVPath to merge MSVC variables.
................
r3487 | cournape | 2008-09-26 00:18:35 -0700 (Fri, 26 Sep 2008) | 1 line

Use new MSVC support instead of the old one by default.
................
r3488 | cournape | 2008-09-26 00:30:34 -0700 (Fri, 26 Sep 2008) | 1 line

Add a small note about new msvc support.
................
r3493 | stevenknight | 2008-09-27 08:02:30 -0700 (Sat, 27 Sep 2008) | 4 lines

Change our catching of implicit RegError and InternalError exceptions
when trying to do "MSVS stuff" into raising and catching a new explicit
MSVCError exception.
................
r3494 | stevenknight | 2008-09-27 08:16:30 -0700 (Sat, 27 Sep 2008) | 8 lines

Fix it so tests will work on Linux:
* Use full names of SCons.Util.* things so we don't die at import time
if they don't exist.
* Use the new SCons.Errors.MSVCError exception.
Also:
* Sort import statements.
* Add copyright and doc string.
................
r3495 | stevenknight | 2008-09-27 08:18:11 -0700 (Sat, 27 Sep 2008) | 2 lines

Python 1.5 portability: no "import ... as" and no list comprehensions.
................
r3496 | cournape | 2008-09-27 23:07:55 -0700 (Sat, 27 Sep 2008) | 2 lines

Fix pdir_from_reg for VS 2003 .net.
................
r3497 | cournape | 2008-09-28 00:01:12 -0700 (Sun, 28 Sep 2008) | 1 line

Add comments about discrepancies between various VS versions.
................
r3498 | cournape | 2008-09-28 00:02:38 -0700 (Sun, 28 Sep 2008) | 1 line

Fix pdir_from_env for VS 2003 .net.
................
r3499 | cournape | 2008-09-28 00:04:09 -0700 (Sun, 28 Sep 2008) | 1 line

Remove dead code.
................
r3500 | cournape | 2008-09-28 01:16:12 -0700 (Sun, 28 Sep 2008) | 1 line

Fix typo: exceptions are raised, not returned...
................
r3501 | cournape | 2008-09-28 01:16:45 -0700 (Sun, 28 Sep 2008) | 1 line

Add a small comment on vsvars32 vs vsvarsall.
................
r3502 | cournape | 2008-09-28 01:17:20 -0700 (Sun, 28 Sep 2008) | 1 line

Fix detect for msvc tool.
................
r3503 | cournape | 2008-09-28 03:42:22 -0700 (Sun, 28 Sep 2008) | 1 line

Add WoW6432 info.
................
r3504 | cournape | 2008-09-28 03:42:46 -0700 (Sun, 28 Sep 2008) | 1 line

Add a function is_win64, needed to detect 32 bits VS on 64 bits windows.
................
r3505 | cournape | 2008-09-28 04:08:20 -0700 (Sun, 28 Sep 2008) | 1 line

Use required version if set; look for a valid version otherwise.
................
r3506 | cournape | 2008-09-28 04:13:25 -0700 (Sun, 28 Sep 2008) | 1 line

Forgot to call with env gar.
................
r3507 | cournape | 2008-09-28 04:20:30 -0700 (Sun, 28 Sep 2008) | 1 line

Fix typo.
................
r3508 | cournape | 2008-09-28 04:24:30 -0700 (Sun, 28 Sep 2008) | 1 line

And another typo.
................
r3509 | cournape | 2008-09-28 04:27:15 -0700 (Sun, 28 Sep 2008) | 1 line

And another...
................
r3510 | cournape | 2008-09-28 04:35:02 -0700 (Sun, 28 Sep 2008) | 1 line

Add a FindDefaultMSVSBatFile function to use in msvc.
................
r3511 | cournape | 2008-09-28 04:35:27 -0700 (Sun, 28 Sep 2008) | 1 line

Use FindDefaultMSVSBatFile to detect msvc if no specific version was required.
................
r3512 | cournape | 2008-09-28 04:49:26 -0700 (Sun, 28 Sep 2008) | 1 line

Fix get_required_version.
................
r3513 | cournape | 2008-09-28 04:52:14 -0700 (Sun, 28 Sep 2008) | 1 line

Typo.
................
r3516 | cournape | 2008-09-29 05:54:51 -0700 (Mon, 29 Sep 2008) | 1 line

Add our own custom query_versions to detect available VS versions on the build machine.
................
r3517 | cournape | 2008-09-29 06:02:46 -0700 (Mon, 29 Sep 2008) | 1 line

Add a function to get default version of MS VS, but using new logic based on bat file instead of registry insanity.
................
r3518 | cournape | 2008-09-29 06:27:46 -0700 (Mon, 29 Sep 2008) | 1 line

Use query_version to get actual VS version to use; my previous attempt was totally bogus.
................
r3519 | cournape | 2008-09-29 07:03:58 -0700 (Mon, 29 Sep 2008) | 1 line

Update our fake test for debugging purpose.
................
r3522 | cournape | 2008-09-29 21:54:53 -0700 (Mon, 29 Sep 2008) | 1 line

Always succeed msvc.generate, even when no compiler is found.
................
r3532 | garyo | 2008-10-01 21:48:33 -0700 (Wed, 01 Oct 2008) | 1 line

vs_revamp: look for paths non-case-sensitively for e.g. VC9 Express.
................
r3553 | cournape | 2008-10-06 06:00:05 -0700 (Mon, 06 Oct 2008) | 2 lines

Rename default_version function.
................
r3554 | cournape | 2008-10-06 06:00:34 -0700 (Mon, 06 Oct 2008) | 2 lines

Put MSVCCommon import on top.
................
r3555 | cournape | 2008-10-06 06:00:56 -0700 (Mon, 06 Oct 2008) | 2 lines

Use new MSVS detection in mslink tool.
................
r3556 | cournape | 2008-10-06 06:01:24 -0700 (Mon, 06 Oct 2008) | 2 lines

Use detect_msvs function for every MS-tool detect method.
................
r3557 | cournape | 2008-10-06 06:01:52 -0700 (Mon, 06 Oct 2008) | 2 lines

Use single function to detect default msvs version.
................
r3558 | cournape | 2008-10-06 06:02:12 -0700 (Mon, 06 Oct 2008) | 2 lines

Use common function to detect msvs version for mslib tool.
................
r3559 | cournape | 2008-10-06 06:02:33 -0700 (Mon, 06 Oct 2008) | 2 lines

Use common msvc funcs in linkloc tool.
................
r3560 | cournape | 2008-10-06 06:02:53 -0700 (Mon, 06 Oct 2008) | 2 lines

Remove old code for msvc: not used anymore.
................
r3561 | cournape | 2008-10-06 06:03:13 -0700 (Mon, 06 Oct 2008) | 2 lines

Use merge_default_version in msvs tool.
................
r3562 | cournape | 2008-10-06 06:03:34 -0700 (Mon, 06 Oct 2008) | 2 lines

Remove more obsolete cruft.
................
r3563 | cournape | 2008-10-06 06:03:53 -0700 (Mon, 06 Oct 2008) | 2 lines

Use common msvs detection instead of cutom one in midl.py.
................
r3564 | cournape | 2008-10-06 06:04:13 -0700 (Mon, 06 Oct 2008) | 2 lines

Removed obsolete is_msvs_installed.
................
r3565 | cournape | 2008-10-06 06:04:32 -0700 (Mon, 06 Oct 2008) | 2 lines

Make sure we still use string in MSVS_VERSION, even if we use float internally everywhere otherwise.
................
r3567 | cournape | 2008-10-06 07:41:16 -0700 (Mon, 06 Oct 2008) | 1 line

Add env argument to MergeBatFile.
................
r3568 | cournape | 2008-10-06 07:43:07 -0700 (Mon, 06 Oct 2008) | 1 line

Add env argument to get_output to control environment executing the bat file.
................
r3573 | cournape | 2008-10-07 01:48:05 -0700 (Tue, 07 Oct 2008) | 1 line

Remove obsolete varbat_variables.
................
r3574 | cournape | 2008-10-07 01:48:33 -0700 (Tue, 07 Oct 2008) | 1 line

Define a DEFVERSIONSTR.
................
r3575 | cournape | 2008-10-07 01:48:57 -0700 (Tue, 07 Oct 2008) | 1 line

Set supported versions in a global variable.
................
r3576 | cournape | 2008-10-07 01:49:21 -0700 (Tue, 07 Oct 2008) | 1 line

Trailing spaces.
................
r3577 | cournape | 2008-10-07 01:49:43 -0700 (Tue, 07 Oct 2008) | 1 line

Add a function to normalize environments for some keys set.
................
r3578 | cournape | 2008-10-07 01:50:10 -0700 (Tue, 07 Oct 2008) | 1 line

Use normalized env when executing the .bat file.
................
r3579 | cournape | 2008-10-07 02:02:18 -0700 (Tue, 07 Oct 2008) | 1 line

Typo.
................
r3580 | cournape | 2008-10-07 02:13:26 -0700 (Tue, 07 Oct 2008) | 1 line

Fix wrong definition of version to env var dictionary.
................
r3581 | cournape | 2008-10-07 02:15:24 -0700 (Tue, 07 Oct 2008) | 1 line

Fix missed variable.
................
r3582 | cournape | 2008-10-07 02:28:35 -0700 (Tue, 07 Oct 2008) | 1 line

Use values and not keys of env.
................
r3583 | cournape | 2008-10-07 03:45:50 -0700 (Tue, 07 Oct 2008) | 1 line

Handle string encoding when reading env from .bat file.
................
r3584 | cournape | 2008-10-07 04:07:26 -0700 (Tue, 07 Oct 2008) | 1 line

Directly return the parsed variables, since we use a sanitize env now.
................
r3585 | cournape | 2008-10-07 04:33:34 -0700 (Tue, 07 Oct 2008) | 1 line

Add locations of MS sdk (from registry only).
................
r3586 | cournape | 2008-10-07 04:43:32 -0700 (Tue, 07 Oct 2008) | 1 line

Mention that MS SDK has only been investigated for 6.1.
................
r3587 | cournape | 2008-10-07 04:43:56 -0700 (Tue, 07 Oct 2008) | 1 line

Add function to get the MS SDK directory from registry.
................
r3588 | cournape | 2008-10-07 04:50:52 -0700 (Tue, 07 Oct 2008) | 1 line

Fix typo in variable.
................
r3589 | cournape | 2008-10-07 05:12:27 -0700 (Tue, 07 Oct 2008) | 1 line

Remove unused keep arg of get_output.
................
r3590 | cournape | 2008-10-07 05:12:49 -0700 (Tue, 07 Oct 2008) | 1 line

Fix typo in MS SDK reg key.
................
r3591 | cournape | 2008-10-07 05:30:50 -0700 (Tue, 07 Oct 2008) | 1 line

Fix parse_output for cases where keys do not have special treatment.
................
r3597 | cournape | 2008-10-08 01:18:17 -0700 (Wed, 08 Oct 2008) | 1 line

Add a function to parse outputstring into env dict.
................
r3602 | cournape | 2008-10-09 10:34:10 -0700 (Thu, 09 Oct 2008) | 1 line

Use version string for default version.
................
r3605 | cournape | 2008-10-10 06:36:45 -0700 (Fri, 10 Oct 2008) | 1 line

Start working on using def path if requested to avoid huge cost of executing the .bat files.
................
r3606 | cournape | 2008-10-10 06:47:43 -0700 (Fri, 10 Oct 2008) | 1 line

Rename global var to get windows sdk from registry.
................
r3607 | cournape | 2008-10-10 07:01:39 -0700 (Fri, 10 Oct 2008) | 1 line

Handle platform sdk in default env.
................
r3661 | cournape | 2008-10-11 03:47:55 -0700 (Sat, 11 Oct 2008) | 1 line

Move MSVCCommon module into a subpackage.
................
r3662 | cournape | 2008-10-11 04:06:15 -0700 (Sat, 11 Oct 2008) | 1 line

Start splitting MSVCCommon module in multiple files.
................
r3663 | cournape | 2008-10-11 04:09:30 -0700 (Sat, 11 Oct 2008) | 1 line

Put sdk-stuff in separate module.
................
r3664 | cournape | 2008-10-11 04:20:25 -0700 (Sat, 11 Oct 2008) | 1 line

Put defaults and environment parsing/bat execution in separate module.
................
r3665 | cournape | 2008-10-11 04:27:29 -0700 (Sat, 11 Oct 2008) | 1 line

Add a version module for version handling/detection.
................
r3666 | cournape | 2008-10-11 04:56:52 -0700 (Sat, 11 Oct 2008) | 1 line

Fix various broken imports related to refactoring of MSVCCommon.
................
r3667 | cournape | 2008-10-11 05:00:57 -0700 (Sat, 11 Oct 2008) | 1 line

Move msvc notes in our new module.
................
r3668 | cournape | 2008-10-11 06:12:34 -0700 (Sat, 11 Oct 2008) | 1 line

Add COMSPEC to default env['ENV'] + put system32 into the path.
................
r3669 | cournape | 2008-10-11 06:14:02 -0700 (Sat, 11 Oct 2008) | 1 line

Set up PATH correctly.
................
r3671 | cournape | 2008-10-11 06:17:07 -0700 (Sat, 11 Oct 2008) | 1 line

Fix various import issues left over by the refactorization.
................
r3674 | cournape | 2008-10-11 06:42:57 -0700 (Sat, 11 Oct 2008) | 1 line

SDK versions can have letters in them: cannot use float, have to use strings.
................
r3675 | cournape | 2008-10-11 06:55:28 -0700 (Sat, 11 Oct 2008) | 1 line

Update msvc notes.
................
r3680 | cournape | 2008-10-14 01:17:13 -0700 (Tue, 14 Oct 2008) | 1 line

Add some info I found out on sdk mess.
................
r3681 | cournape | 2008-10-14 02:15:07 -0700 (Tue, 14 Oct 2008) | 1 line

Add some more comments on how we get the SDK.
................
r3682 | cournape | 2008-10-14 03:05:08 -0700 (Tue, 14 Oct 2008) | 1 line

The SDK tool can find the 2003R2 SDK too.
................
r3686 | cournape | 2008-10-14 20:13:20 -0700 (Tue, 14 Oct 2008) | 1 line

Fix tab vs space.
................
r3687 | cournape | 2008-10-14 20:14:40 -0700 (Tue, 14 Oct 2008) | 2 lines

Add UUID for sdk 2003R1
.
................
r3688 | cournape | 2008-10-14 20:33:18 -0700 (Tue, 14 Oct 2008) | 1 line

Add comment on which version of the SDK the sdk module can find.
................
r3690 | cournape | 2008-10-15 01:14:12 -0700 (Wed, 15 Oct 2008) | 1 line

Update the msvc notes.
................
r3696 | cournape | 2008-10-16 23:23:14 -0700 (Thu, 16 Oct 2008) | 1 line

Change sanity check files for SDK 6.0A and 6.1.
................
r3697 | cournape | 2008-10-16 23:35:03 -0700 (Thu, 16 Oct 2008) | 1 line

Do not handle sdk in defaults.
................
r3698 | cournape | 2008-10-16 23:49:25 -0700 (Thu, 16 Oct 2008) | 1 line

Add docstring for exists method of ms tools.
................
r3699 | cournape | 2008-10-17 00:04:17 -0700 (Fri, 17 Oct 2008) | 1 line

Fix spave vs tab issue.
................
r3700 | cournape | 2008-10-17 00:26:50 -0700 (Fri, 17 Oct 2008) | 1 line

Add a TODO.
................
r3701 | cournape | 2008-10-17 00:58:27 -0700 (Fri, 17 Oct 2008) | 1 line

Find VC98 product dir from the registry.
................
r3702 | cournape | 2008-10-17 01:01:51 -0700 (Fri, 17 Oct 2008) | 1 line

Refactor find_v* functions: 3 different batname needed now that we support VC98.
................
r3703 | cournape | 2008-10-17 01:03:20 -0700 (Fri, 17 Oct 2008) | 1 line

Fix dos EOL.
................
r3704 | cournape | 2008-10-17 01:04:28 -0700 (Fri, 17 Oct 2008) | 1 line

More fixes dos EOL.
................
r3705 | cournape | 2008-10-17 01:08:59 -0700 (Fri, 17 Oct 2008) | 1 line

Fix typo in bat filename for VS 2005/2008.
................
r3706 | cournape | 2008-10-17 01:10:12 -0700 (Fri, 17 Oct 2008) | 1 line

VC98 now correctly detected in query_versions.
................
r3707 | cournape | 2008-10-17 01:58:49 -0700 (Fri, 17 Oct 2008) | 1 line

Fix some encoding issues when parsing the .bat file ouptut.
................
r3708 | cournape | 2008-10-17 02:35:25 -0700 (Fri, 17 Oct 2008) | 1 line

Remove unused/dead code.
................
r3713 | cournape | 2008-10-24 05:40:31 -0700 (Fri, 24 Oct 2008) | 1 line

Add a function to detect VCINSTALLDIR and VSINSTALLDIR.
................
r3714 | cournape | 2008-10-24 05:41:48 -0700 (Fri, 24 Oct 2008) | 1 line

'inline' trivial functions.
................
r3715 | cournape | 2008-10-24 05:45:40 -0700 (Fri, 24 Oct 2008) | 1 line

Fix bad function name in previous commit.
................
r3716 | cournape | 2008-10-24 05:50:34 -0700 (Fri, 24 Oct 2008) | 1 line

Rename find_msvs_path since several paths are returned.
................
r3717 | cournape | 2008-10-24 05:51:00 -0700 (Fri, 24 Oct 2008) | 1 line

Return correct variable in find_msvs_paths.
................
r3718 | cournape | 2008-10-24 05:51:42 -0700 (Fri, 24 Oct 2008) | 1 line

Fix VSINSTALLDIR.
................
r3719 | cournape | 2008-10-24 05:52:40 -0700 (Fri, 24 Oct 2008) | 1 line

Normalize paths returned by find_msvs_paths.
................
r3720 | cournape | 2008-10-25 04:06:14 -0700 (Sat, 25 Oct 2008) | 1 line

Adapt empty test case to new msvc support.
................
r3721 | cournape | 2008-10-25 04:10:53 -0700 (Sat, 25 Oct 2008) | 1 line

Handle os.environ overriding a bit better.
................
r3722 | cournape | 2008-10-25 04:29:22 -0700 (Sat, 25 Oct 2008) | 1 line

Add our get_msvs_install_dirs function to be compatible with old unit test suite.
................
r3723 | cournape | 2008-10-25 04:31:21 -0700 (Sat, 25 Oct 2008) | 1 line

Fix empty test case.
................
r3724 | cournape | 2008-10-25 05:16:32 -0700 (Sat, 25 Oct 2008) | 1 line

Start working on net frameworks detection.
................
r3725 | cournape | 2008-10-25 05:21:06 -0700 (Sat, 25 Oct 2008) | 1 line

Fix forgotten colon.
................
r3726 | cournape | 2008-10-25 05:25:57 -0700 (Sat, 25 Oct 2008) | 1 line

Add a function to query available .net frameworks.
................
r3727 | cournape | 2008-10-25 05:27:15 -0700 (Sat, 25 Oct 2008) | 1 line

Fix typo.
................
r3728 | cournape | 2008-10-25 05:28:03 -0700 (Sat, 25 Oct 2008) | 1 line

Forgot to improt string module.
................
r3729 | cournape | 2008-10-25 05:42:51 -0700 (Sat, 25 Oct 2008) | 1 line

Add a method to detect the MS SDK.
................
r3730 | cournape | 2008-10-25 05:54:16 -0700 (Sat, 25 Oct 2008) | 1 line

Simplify merge_default_version: do not use MSVS_USE_DEFAULT_PATHS anymore.
................
r3731 | cournape | 2008-10-25 06:10:36 -0700 (Sat, 25 Oct 2008) | 1 line

Add functions to add sdk depending on MS toolsuite.
................
r3732 | cournape | 2008-10-25 06:11:55 -0700 (Sat, 25 Oct 2008) | 1 line

Set up the SDK in merge_default_version.
................
r3733 | cournape | 2008-10-25 06:14:08 -0700 (Sat, 25 Oct 2008) | 1 line

Use float version, not string version for FindMSVSBatFile.
................
r3734 | cournape | 2008-10-25 06:14:59 -0700 (Sat, 25 Oct 2008) | 1 line

Forgot to pass scons env argument for psdk functions.
................
r3735 | cournape | 2008-10-25 06:17:11 -0700 (Sat, 25 Oct 2008) | 1 line

Pass correct versions tring.
................
r3736 | cournape | 2008-10-25 06:17:47 -0700 (Sat, 25 Oct 2008) | 1 line

Fix typo.
................
r3737 | cournape | 2008-10-25 07:55:25 -0700 (Sat, 25 Oct 2008) | 1 line

Add MSVCCommon module to MANIFEST.
................
r3738 | cournape | 2008-10-25 08:23:30 -0700 (Sat, 25 Oct 2008) | 1 line

Add MSVCCommon to distutils setup files.
................
r3739 | cournape | 2008-10-25 08:43:40 -0700 (Sat, 25 Oct 2008) | 1 line

Include 8 in the msvs versions to Set PSDK.
................
r3740 | cournape | 2008-10-25 08:47:09 -0700 (Sat, 25 Oct 2008) | 1 line

Set up PSDK in msvc tool only.
................
r3832 | stevenknight | 2008-12-12 08:10:24 -0800 (Fri, 12 Dec 2008) | 2 lines

Set svn:ignore on the Tool/MSVCCommon subdirectory.
................
r3833 | stevenknight | 2008-12-12 08:27:06 -0800 (Fri, 12 Dec 2008) | 4 lines

When appending to the PATH, use get_system_root() instead of assuming
SYSTEMROOT is in env['ENV']. Make using get_system_root() repeatedly
more acceptable by returning a cached value after the first call.
................
r3834 | stevenknight | 2008-12-12 10:17:01 -0800 (Fri, 12 Dec 2008) | 5 lines

Define WindowsError and other necessary things (HKEY_*, RegGetValue())
on non-Windows platforms, so we can run platform-independent vs_revamp
tests on non-Windows platforms without having to teach the rest of the
code that they might not be running on a Windows system.
................
r3835 | stevenknight | 2008-12-12 10:18:30 -0800 (Fri, 12 Dec 2008) | 2 lines

Add an AppendENVPath() method to our fake Environment class.
................
r3933 | stevenknight | 2009-01-30 05:54:00 -0800 (Fri, 30 Jan 2009) | 3 lines

Add copyright statements, __revision__ specifications and __doc__ string
place-holders.
................
r3934 | stevenknight | 2009-01-30 06:39:56 -0800 (Fri, 30 Jan 2009) | 2 lines

Python 1.5 portability.
................
r3935 | stevenknight | 2009-01-30 07:12:20 -0800 (Fri, 30 Jan 2009) | 3 lines

Add copyright and __revision__, fix import module for
{Find,Parse,Merge}BatFile() (from SCons.Tool.MSVCCommon.misc).
................
r3937 | stevenknight | 2009-01-31 07:40:31 -0800 (Sat, 31 Jan 2009) | 5 lines

Fix NameError on the msvs_parse_version() call in merge_default_version().
This (showed up in test\PharLap.py. The import should be moved to the
top eventually, but would currently cause a circular error with imports
that try to find merge_default_version() itself.
................
r3938 | stevenknight | 2009-01-31 07:51:16 -0800 (Sat, 31 Jan 2009) | 2 lines

Fix 80-char line wrap on imported variables.
................
r3939 | stevenknight | 2009-01-31 08:00:44 -0800 (Sat, 31 Jan 2009) | 10 lines

Fix the test\MSVS\vs-*-exec.py tests by restoring the old
get__{default,}_visual_studio*() and get_msvs_install_dirs()
functions to src/engine/SCons/Tool/msvs.py. The last one
is still used by the test infrastructure (specifically
QMTest\TestSConsMSVS.py) to get the path to the visual studio
executable (devenv.exe). We can clean this up by removing
these wrappers in favor of better interfaces directly from
MSVCCommon, but I want to get the tests working first and
then fine-tune the aesthetics.
................
r3964 | stevenknight | 2009-02-05 06:51:32 -0800 (Thu, 05 Feb 2009) | 15 lines

First stab at refactoring SDK detection:
* Add a separate 'mssdk' tool to provide a direct interface to applying
SDK information to a construction environment. (Currently used by 'msvc'.)
* Add support for $MSSDK_DIR and $MSSDK_VERSION variables to give the
user explicit control over how to specify where to find an SDK.
* Collect information about different possibly installed SDK versions (what
sanity check file to use, what HKEY to look up) from being scattered in
multiple lists to a common list of definitions, specified by concrete
WindowsSDK and PlatformSDK subclasses of an abstract SDKDefinition
base class.
* Cache results of trying to find SDKs so we only have to go out to the
registry and disk once, regardless of how many times we're asked.
* Cache lists of variables to be appended so we only have to look for
'mfc' and 'atl' subdirectories once.
................
r3965 | stevenknight | 2009-02-05 19:34:25 -0800 (Thu, 05 Feb 2009) | 2 lines

Fix name errors in my reworking of sdk searching.
................
r3966 | stevenknight | 2009-02-05 21:34:19 -0800 (Thu, 05 Feb 2009) | 5 lines

Fix get_output() to use the subprocess.Popen.std{out,err} attributes
directly instead subprocess.Popen.communicate(), which uses the
threading module and therefore won't work on Pythons not built with
thread support.
................
r3969 | stevenknight | 2009-02-06 08:38:57 -0800 (Fri, 06 Feb 2009) | 5 lines

Fix some test errors on cygwin:
* Generalize the expected error message(s) in Install.py
* Make sure M4 is attached to all the environments.
* Use the TestSCons.file_expr expression in PCHSTOP-errors.py
................
r3971 | stevenknight | 2009-02-06 10:00:59 -0800 (Fri, 06 Feb 2009) | 2 lines

Fix use of TestSCons.file_expr.
................
r3972 | stevenknight | 2009-02-06 10:09:57 -0800 (Fri, 06 Feb 2009) | 2 lines

Fixes for use of regular expressions with must_contain_all_lines().
................
r3974 | stevenknight | 2009-02-06 10:37:40 -0800 (Fri, 06 Feb 2009) | 2 lines

Update expected error string list for Cygwin.
................
r3975 | stevenknight | 2009-02-06 10:41:38 -0800 (Fri, 06 Feb 2009) | 2 lines

Relax the expected PCH speedup to 90% of the non-PCH compilation.
................
r3976 | stevenknight | 2009-02-06 10:48:08 -0800 (Fri, 06 Feb 2009) | 2 lines

Add skeleton of XML doc of new MSSDK_* variables.
................
r3984 | garyo | 2009-02-08 08:51:52 -0800 (Sun, 08 Feb 2009) | 11 lines

Fixes for some of the failing msvsTests.py tests on vs_revamp branch.

CODE FIXES:
* SCons/Util.py: removed extra trailing backslash from registry lookup.
* Started on a path to handling vs 8.0 express in msvs.py, version.py, and common.py, but need feedback here.

TEST FIXES:
* Added a MSVS 8.0 std version test, since that's what's on my home machine. I got the fake registry data by exporting my real registry subtree.
* I changed the expected values of many of the tests to conform to what the code actually returns. I think that's right, because it's using fake registry data anyway.
* Tests now monkey-patch os.path.isfile and os.path.isdir to return true, just like os.path.exists already was.
* Improved some test error reporting and added some debug logging.
................
r3985 | stevenknight | 2009-02-08 19:58:23 -0800 (Sun, 08 Feb 2009) | 2 lines

Re-fix use of file_expr, wiped out in last merge from trunk.
................
r3986 | stevenknight | 2009-02-09 10:27:15 -0800 (Mon, 09 Feb 2009) | 2 lines

Add emacs and vim editing settings to the bottom of vs_revamp *.py files.
................
r3993 | stevenknight | 2009-02-11 05:00:55 -0800 (Wed, 11 Feb 2009) | 3 lines

Separate error message for an SDK that's not supported, vs. one that's
supported but not installed.
................
r3994 | stevenknight | 2009-02-11 05:03:51 -0800 (Wed, 11 Feb 2009) | 2 lines

Minor code cleanup.
................
r3995 | stevenknight | 2009-02-11 05:04:40 -0800 (Wed, 11 Feb 2009) | 2 lines

Link reference to $MSVS_VERSION.
................
r4000 | stevenknight | 2009-02-12 18:51:30 -0800 (Thu, 12 Feb 2009) | 12 lines

First cut at collecting the different version-specific logic from
different modules and methods and putting it in a common MSVCCommon/vs.py
module. This also basically gets rid of the separation of "version" and
"flavor" or "suite" arguments in favor of just treating Express as
separate versions, and versions are now strings, not floats: "8.0"
and "8.0Exp". (It's not like there's so much commonality between the
Express and Pro versions that keeping things synchronized will be a burden.)

This is only part way through absorbing the current API into the new
scheme and getting rid of some now-unused functions, but should support
testing from various people while that work proceeds.
................
r4001 | stevenknight | 2009-02-12 20:40:14 -0800 (Thu, 12 Feb 2009) | 3 lines

Add comments with the official Microsoft names of the different releases.
(I can never remember the mapping of names to version numbers.)
................
r4002 | stevenknight | 2009-02-12 20:41:55 -0800 (Thu, 12 Feb 2009) | 2 lines

Fix some 80-char line wrap.
................
r4012 | stevenknight | 2009-02-19 06:24:58 -0800 (Thu, 19 Feb 2009) | 3 lines

Add a $MSVS_ARCH variable and support for 'amd64' in some of
the supported Visual Studio versions. (Roberto de Vecchi)
................
r4013 | stevenknight | 2009-02-19 06:36:55 -0800 (Thu, 19 Feb 2009) | 2 lines

Fetch the VisualStudio object using .get(), not .has_key().
................
r4014 | stevenknight | 2009-02-19 06:53:31 -0800 (Thu, 19 Feb 2009) | 2 lines

Start getting rid of unnecessary code. Cosmetic cleanups. Comments.
................
r4015 | stevenknight | 2009-02-19 06:59:06 -0800 (Thu, 19 Feb 2009) | 2 lines

Move query_versions() into MSVCCommon/vs.py. Fix variable names.
................
r4016 | stevenknight | 2009-02-19 07:27:01 -0800 (Thu, 19 Feb 2009) | 3 lines

Get rid of MSVCCommon/misc.py and MSVCCommon/version.py, now that
the necessary logic has been migrated to MSVCCommon/vs.py.
................
r4017 | stevenknight | 2009-02-19 08:40:20 -0800 (Thu, 19 Feb 2009) | 2 lines

Add trailing commas.
................
r4018 | stevenknight | 2009-02-19 09:55:33 -0800 (Thu, 19 Feb 2009) | 3 lines

Get rid of one-line wrappers in msvs.py in favor of direct testing
of functions in MSVCCommon/*.py.
................
r4019 | stevenknight | 2009-02-19 11:26:29 -0800 (Thu, 19 Feb 2009) | 3 lines

Use consistent spelling of SystemDrive and SystemRoot for those
environment variables.
................
r4020 | stevenknight | 2009-02-19 13:36:05 -0800 (Thu, 19 Feb 2009) | 12 lines

Get rid of msvs.get_msvs_install_dirs(), only used by the unit tests
in msvsTests.py.
Make get_vs_by_version() public.
Update msvsTests.py with a rudimentary test for detect_msvs(),
and get rid of the test for get_msvs_install_dirs().
Remove MSVCCommon\findloc.py and MSVCCommon\defaults.py, no longer needed.
Move contents of MSVCCommon\envhelpers.py to MSVCCommon\common.py to
try to collect things, and remove MSVCCommon\envhelpers.py.
Update QMTest\TestSConsMSVS.py to use the new vs infrastructure to find
the appropriate executable (devenv.com, etc.).
Update MANIFEST.in for the removed modules.
................
r4021 | stevenknight | 2009-02-19 13:48:49 -0800 (Thu, 19 Feb 2009) | 3 lines

Rename MSVCCommon to MSCommon so it's not tied too tightly to Visual C/C++
(leaving the door a little more open for other Visual products).
................
r4022 | stevenknight | 2009-02-19 13:54:55 -0800 (Thu, 19 Feb 2009) | 2 lines

Change additional MSVCCommon references.
................

Comments (0)

Files changed (33)

QMTest/TestSConsMSVS.py

         """Returns a full path to the executable (MSDEV or devenv)
         for the specified version of Visual Studio.
         """
-        common_msdev98_bin_msdev_com = ['Common', 'MSDev98', 'Bin', 'MSDEV.COM']
-        common7_ide_devenv_com       = ['Common7', 'IDE', 'devenv.com']
-        common7_ide_vcexpress_exe    = ['Common7', 'IDE', 'VCExpress.exe']
-        sub_paths = {
-            '6.0' : [
-                common_msdev98_bin_msdev_com,
-            ],
-            '7.0' : [
-                common7_ide_devenv_com,
-            ],
-            '7.1' : [
-                common7_ide_devenv_com,
-            ],
-            '8.0' : [
-                common7_ide_devenv_com,
-                common7_ide_vcexpress_exe,
-            ],
-        }
-        from SCons.Tool.msvs import get_msvs_install_dirs
-        vs_path = get_msvs_install_dirs(version)['VSINSTALLDIR']
-        for sp in sub_paths[version]:
-            p = apply(os.path.join, [vs_path] + sp)
-            if os.path.exists(p):
-                return p
-        return apply(os.path.join, [vs_path] + sub_paths[version][0])
+        from SCons.Tool.MSCommon import get_vs_by_version
+
+        msvs = get_vs_by_version(version)
+        if not msvs:
+            return None
+        return msvs.get_executable()
 
 # Local Variables:
 # tab-width:4
 mingw
 mslib
 mslink
+mssdk
 msvc
 msvs
 mwcc
 
     - Make suffix-matching for scanners case-insensitive on Windows.
 
+  From David Cournapeau:
+
+    - Change the way SCons finds versions of Visual C/C++ and Visual
+      Studio to find and use the Microsoft v*vars.bat files.
+
+  From Robert P. J. Day:
+
+    - User's Guide updates.
+
   From Dan Eaton:
 
     - Fix generation of Visual Studio 8 project files on x64 platforms.
     - Spell the Windows environment variables consistently "SystemDrive"
       and "SystemRoot" instead of "SYSTEMDRIVE" and "SYSTEMROOT".
 
-  From Robert P. J. Day:
-
-    - User's Guide updates.
-
 
 
 RELEASE 1.2.0.d20090113 - Tue, 13 Jan 2009 02:50:30 -0800

src/engine/MANIFEST-xml.in

 SCons/Tool/mingw.xml
 SCons/Tool/mslib.xml
 SCons/Tool/mslink.xml
+SCons/Tool/mssdk.xml
 SCons/Tool/msvc.xml
 SCons/Tool/msvs.xml
 SCons/Tool/mwcc.xml

src/engine/MANIFEST.in

 SCons/Tool/lex.py
 SCons/Tool/link.py
 SCons/Tool/linkloc.py
+SCons/Tool/MSCommon/__init__.py
+SCons/Tool/MSCommon/common.py
+SCons/Tool/MSCommon/netframework.py
+SCons/Tool/MSCommon/sdk.py
+SCons/Tool/MSCommon/vs.py
 SCons/Tool/m4.py
 SCons/Tool/masm.py
 SCons/Tool/midl.py
 SCons/Tool/mingw.py
 SCons/Tool/mslib.py
 SCons/Tool/mslink.py
+SCons/Tool/mssdk.py
 SCons/Tool/msvc.py
 SCons/Tool/msvs.py
 SCons/Tool/mwcc.py

src/engine/SCons/Errors.py

 class EnvironmentError(Exception):
     pass
 
+class MSVCError(IOError):
+    pass
+
 class ExplicitExit(Exception):
     def __init__(self, node=None, status=None, *args):
         self.node = node

src/engine/SCons/Platform/PlatformTests.py

 class Environment(UserDict.UserDict):
     def Detect(self, cmd):
         return cmd
+    def AppendENVPath(self, key, value):
+        pass
 
 class PlatformTestCase(unittest.TestCase):
     def test_Platform(self):

src/engine/SCons/Platform/win32.py

     return '"' + x + '"'
 
 # Get the windows system directory name
+_system_root = None
+
 def get_system_root():
+    global _system_root
+    if _system_root is not None:
+        return _system_root
+
     # A resonable default if we can't read the registry
-    try:
-        val = os.environ['SystemRoot']
-    except KeyError:
-        val = "C:/WINDOWS"
-        pass
+    val = os.environ.get('SystemRoot', "C:/WINDOWS")
 
-    # First see if we can look in the registry...
     if SCons.Util.can_read_reg:
         try:
             # Look for Windows NT system root
                 raise
             except:
                 pass
+    _system_root = val
     return val
 
 # Get the location of the program files directory
     # the env's PATH.  The problem with that is that it might not
     # contain an ENV and a PATH.
     if not cmd_interp:
-        systemroot = r'C:\Windows'
-        if os.environ.has_key('SystemRoot'):
-            systemroot = os.environ['SystemRoot']
+        systemroot = get_system_root()
         tmp_path = systemroot + os.pathsep + \
                    os.path.join(systemroot,'System32')
         tmp_pathext = '.com;.exe;.bat;.cmd'
         if v:
             env['ENV'][var] = v
 
+    if not env['ENV'].has_key('COMSPEC'):
+        v = os.environ.get("COMSPEC")
+        if v:
+            env['ENV']['COMSPEC'] = v
+
+    env.AppendENVPath('PATH', get_system_root() + '\System32')
+
     env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD'
     env['OBJPREFIX']      = ''
     env['OBJSUFFIX']      = '.obj'

src/engine/SCons/Tool/MSCommon/TODO

+Last Change: Fri Oct 17 04:00 PM 2008 J
+
+- Make sure VS 6 and VS 2003 .Net work (with their own SDK)
+- See whether current unit tests can be updated and need to be rewritten from
+  scratch

src/engine/SCons/Tool/MSCommon/__init__.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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+__doc__ = """
+Common functions for Microsoft Visual Studio and Visual C/C++.
+"""
+
+import copy
+import os
+import re
+import subprocess
+
+import SCons.Errors
+import SCons.Platform.win32
+import SCons.Util
+
+from SCons.Tool.MSCommon.vs import detect_msvs, \
+                                   get_default_version, \
+                                   get_vs_by_version, \
+                                   merge_default_version, \
+                                   query_versions
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

src/engine/SCons/Tool/MSCommon/common.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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+__doc__ = """
+Common helper functions for working with
+"""
+
+import copy
+import os
+import subprocess
+import re
+
+import SCons.Util
+
+# Uncomment to enable debug logging to your choice of file
+#import logging,os
+#os.unlink('c:/tmp/debug.log')
+#logging.basicConfig(filename='c:/tmp/debug.log', level=logging.DEBUG,)
+
+try:
+    from logging import debug
+except ImportError:
+    debug = lambda x : None
+
+#debug = lambda x : open('con', 'w').write(x + '\n')
+
+# TODO(sgk): unused
+def is_win64():
+    """Return true if running on windows 64 bits."""
+    # Unfortunately, python does not seem to have anything useful: neither
+    # sys.platform nor os.name gives something different on windows running on
+    # 32 bits or 64 bits. Note that we don't care about whether python itself
+    # is 32 or 64 bits here
+    value = "Software\Wow6432Node"
+    yo = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0]
+    if yo is None:
+        return 0
+    else:
+        return 1
+
+def read_reg(value):
+    return SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0]
+
+
+# Functions for fetching environment variable settings from batch files.
+
+def normalize_env(env, keys):
+    """Given a dictionary representing a shell environment, add the variables
+    from os.environ needed for the processing of .bat files; the keys are
+    controlled by the keys argument.
+
+    It also makes sure the environment values are correctly encoded.
+
+    Note: the environment is copied"""
+    normenv = {}
+    if env:
+        for k in env.keys():
+            normenv[k] = copy.deepcopy(env[k]).encode('mbcs')
+
+        for k in keys:
+            if os.environ.has_key(k):
+                normenv[k] = os.environ[k].encode('mbcs')
+
+    return normenv
+
+def get_output(vcbat, args = None, env = None):
+    """Parse the output of given bat file, with given args."""
+    if args:
+        debug("Calling '%s %s'" % (vcbat, args))
+        popen = subprocess.Popen('"%s" %s & set' % (vcbat, args),
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE,
+                                 env=env)
+    else:
+        debug("Calling '%s'" % vcbat)
+        popen = subprocess.Popen('"%s" & set' % vcbat,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE,
+                                 env=env)
+
+    # Use the .stdout and .stderr attributes directly because the
+    # .communicate() method uses the threading module on Windows
+    # and won't work under Pythons not built with threading.
+    stdout = popen.stdout.read()
+    if popen.wait() != 0:
+        raise IOError(popen.stderr.read().decode("mbcs"))
+
+    output = stdout.decode("mbcs")
+    return output
+
+def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")):
+    # dkeep is a dict associating key: path_list, where key is one item from
+    # keep, and pat_list the associated list of paths
+
+    # TODO(1.5):  replace with the following list comprehension:
+    #dkeep = dict([(i, []) for i in keep])
+    dkeep = dict(map(lambda i: (i, []), keep))
+
+    # rdk will  keep the regex to match the .bat file output line starts
+    rdk = {}
+    for i in keep:
+        rdk[i] = re.compile('%s=(.*)' % i, re.I)
+
+    def add_env(rmatch, key):
+        plist = rmatch.group(1).split(os.pathsep)
+        for p in plist:
+            # Do not add empty paths (when a var ends with ;)
+            if p:
+                p = p.encode('mbcs')
+                # XXX: For some reason, VC98 .bat file adds "" around the PATH
+                # values, and it screws up the environment later, so we strip
+                # it. 
+                p = p.strip('"')
+                dkeep[key].append(p)
+
+    for line in output.splitlines():
+        for k,v in rdk.items():
+            m = v.match(line)
+            if m:
+                add_env(m, k)
+
+    return dkeep
+
+# TODO(sgk): unused
+def output_to_dict(output):
+    """Given an output string, parse it to find env variables.
+
+    Return a dict where keys are variables names, and values their content"""
+    envlinem = re.compile(r'^([a-zA-z0-9]+)=([\S\s]*)$')
+    parsedenv = {}
+    for line in output.splitlines():
+        m = envlinem.match(line)
+        if m:
+            parsedenv[m.group(1)] = m.group(2)
+    return parsedenv
+
+# TODO(sgk): unused
+def get_new(l1, l2):
+    """Given two list l1 and l2, return the items in l2 which are not in l1.
+    Order is maintained."""
+
+    # We don't try to be smart: lists are small, and this is not the bottleneck
+    # is any case
+    new = []
+    for i in l2:
+        if i not in l1:
+            new.append(i)
+
+    return new
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

src/engine/SCons/Tool/MSCommon/msvc_changes.txt

+The Visual Studio support has been totally revamped. Instead of using registry
+magic, we use the .bat files available for each version of visual studio. This
+is simpler (does not depend on the version of the compiler), more reliable, and
+just plain better.
+
+Specification
+=============
+
+Tested versions
+---------------
+
+The following versions have been succesfully tested:
+  - VS 2008 (express), 32 bits
+  - VS 2005 (express), 32 bits
+  - VS 2003 (.Net, pro), 32 bits
+
+Detection
+---------
+
+All tools related to the ms toolchain are detected through the same method:
+  - detect the .bat configuration file (vsvarsall.bat/vsvars32.bat
+    depending on the version) from the registry
+  - if registry does not return anything useful, use the VS*COMNTOOLS env
+    variable.
+
+A version is detected only when the .bat file actually exists on the
+filesystem.  Once the .bat file is found, it is executed through a clean
+environment, and its output is parsed to get the variables
+PATH/LIB/LIBPATH/INCLUDE. Those variables are then added to env['ENV']
+
+By default, the most recent detected version is set, and can be queried in
+env['MSVS_VERSION'] *after* the tool initialization. The version can be forced
+by setting the MSVS_VERSION variable *before* initializing the tool.
+
+SDK
+---
+
+Separate SDKs are only supported for the following versions:
+        - Platform SDK 2003 R1 and R2
+        - Windows SDK. I tried the following versions: 6.0, 6.0A (SDK delivered
+          with VS 2008 express) and 6.1 (Windows SDK 2008).
+
+Previous SDKs are not available anymore on MS website, so I could not test
+them. I believe VS 6 has its own SDK included, as well as VS 2003 .Net. The SDK
+is set *after* the msvs tool.
+
+The version of the SDK can be controlled by the scons variable:
+
+    MSSDK_DIR:      If set, specifies the directory location of the
+                    SDK to be used.
+
+    MSSDK_VERSION:  If set, specifies the version of the SDK to be used.
+
+If neither of these is set, MSVS_VERSION is used to pick an appropriate
+default.
+
+Architecture
+------------
+
+env['MSVS_ARCH'] = 'x86'
+                   'amd64'
+
+If not set, the selection logic defaults to x86. Cross compiling has been
+disabled, filtering out values not included in version.SUPPORTED_ARCH.
+(No tests made with cross compiling.)
+
+Fundamental changes
+===================
+
+env["ENV"] has been expanded a bit on windows:
+  - add %SystemRoot%\system32 in the path for windows
+  - add COMSPEC (needed by the .bat file execution)
+
+Internals
+=========
+
+The code can be found in the MSVCCommon submodule:
+  - findloc: find the product dir from the registry or the shell environment
+        - versions: query the system for available versions of the VS suite on
+          the system
+        - misc: high level functions, *candidates* for the public API.
+        - sdk: specifics to the SDK detection.
+        - defaults: default values to use for the paths, to use instead of the
+          whole env parsing which can be quite slow, but less reliable. Still
+          experimental, may be removed
+  - envhelpers: functions to execute a VS .bat file, parse its output,
+    and get the variables with modified values.
+
+At this point, no function should be considered public, the exact API is not
+good yet.

src/engine/SCons/Tool/MSCommon/netframework.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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+__doc__ = """
+"""
+
+import os
+import re
+import string
+
+from common import read_reg, debug
+
+# Original value recorded by dcournapeau
+_FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\.NETFramework\InstallRoot'
+# On SGK's system
+_FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\Microsoft SDKs\.NETFramework\v2.0\InstallationFolder'
+
+def find_framework_root():
+    # XXX: find it from environment (FrameworkDir)
+    try:
+        froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT)
+        debug("Found framework install root in registry: %s" % froot)
+    except WindowsError, e:
+        debug("Could not read reg key %s" % _FRAMEWORKDIR_HKEY_ROOT)
+        return None
+
+    if not os.path.exists(froot):
+        debug("%s not found on fs" % froot)
+        return None
+
+    return froot
+
+def query_versions():
+    froot = find_framework_root()
+    if froot:
+        contents = os.listdir(froot)
+
+        l = re.compile('v[0-9]+.*')
+        versions = filter(lambda e, l=l: l.match(e), contents)
+
+        def versrt(a,b):
+            # since version numbers aren't really floats...
+            aa = a[1:]
+            bb = b[1:]
+            aal = string.split(aa, '.')
+            bbl = string.split(bb, '.')
+            # sequence comparison in python is lexicographical
+            # which is exactly what we want.
+            # Note we sort backwards so the highest version is first.
+            return cmp(bbl,aal)
+
+        versions.sort(versrt)
+    else:
+        versions = []
+
+    return versions
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

src/engine/SCons/Tool/MSCommon/sdk.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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+__doc__ = """Module to detect the Platform/Windows SDK
+
+PSDK 2003 R1 is the earliest version detected.
+"""
+
+import os
+
+import SCons.Errors
+from SCons.Tool.MSCommon.common import debug, read_reg
+import SCons.Util
+
+# SDK Checks. This is of course a mess as everything else on MS platforms. Here
+# is what we do to detect the SDK:
+#
+# For Windows SDK >= 6.0: just look into the registry entries:
+#   HKLM\Software\Microsoft\Microsoft SDKs\Windows
+# All the keys in there are the available versions.
+#
+# For Platform SDK before 6.0 (2003 server R1 and R2, etc...), there does not
+# seem to be any sane registry key, so the precise location is hardcoded.
+#
+# For versions below 2003R1, it seems the PSDK is included with Visual Studio?
+#
+# Also, per the following:
+#     http://benjamin.smedbergs.us/blog/tag/atl/
+# VC++ Professional comes with the SDK, VC++ Express does not.
+
+# Location of the SDK (checked for 6.1 only)
+_CURINSTALLED_SDK_HKEY_ROOT = \
+        r"Software\Microsoft\Microsoft SDKs\Windows\CurrentInstallFolder"
+
+
+class SDKDefinition:
+    """
+    An abstract base class for trying to find installed SDK directories.
+    """
+    def __init__(self, version, **kw):
+        self.version = version
+        self.__dict__.update(kw)
+
+    def find_install_dir(self):
+        """Try to find the MS SDK from the registry.
+
+        Return None if failed or the directory does not exist.
+        """
+        if not SCons.Util.can_read_reg:
+            debug('SCons cannot read registry')
+            return None
+
+        hkey = self.HKEY_FMT % self.hkey_data
+
+        try:
+            install_dir = read_reg(hkey)
+            debug('Found sdk dir in registry: %s' % install_dir)
+        except WindowsError, e:
+            debug('Did not find sdk dir key %s in registry' % hkey)
+            return None
+
+        if not os.path.exists(install_dir):
+            debug('%s is not found on the filesystem' % install_dir)
+            return None
+
+        ftc = os.path.join(install_dir, self.sanity_check_file)
+        if not os.path.exists(ftc):
+            debug("File %s used for sanity check not found" % ftc)
+            return None
+
+        return install_dir
+
+    def get_install_dir(self):
+        """Return the MSSSDK given the version string."""
+        try:
+            return self._install_dir
+        except AttributeError:
+            install_dir = self.find_install_dir()
+            self._install_dir = install_dir
+            return install_dir
+
+class WindowsSDK(SDKDefinition):
+    """
+    A subclass for trying to find installed Windows SDK directories.
+    """
+    HKEY_FMT = r'Software\Microsoft\Microsoft SDKs\Windows\v%s\InstallationFolder'
+    def __init__(self, *args, **kw):
+        apply(SDKDefinition.__init__, (self,)+args, kw)
+        self.hkey_data = self.version
+
+class PlatformSDK(SDKDefinition):
+    """
+    A subclass for trying to find installed Platform SDK directories.
+    """
+    HKEY_FMT = r'Software\Microsoft\MicrosoftSDK\InstalledSDKS\%s\Install Dir'
+    def __init__(self, *args, **kw):
+        apply(SDKDefinition.__init__, (self,)+args, kw)
+        self.hkey_data = self.uuid
+
+# The list of support SDKs which we know how to detect.
+#
+# The first SDK found in the list is the one used by default if there
+# are multiple SDKs installed.  Barring good reasons to the contrary,
+# this means we should list SDKs with from most recent to oldest.
+#
+# If you update this list, update the documentation in Tool/mssdk.xml.
+SupportedSDKList = [
+    WindowsSDK('6.1',
+                sanity_check_file=r'include\windows.h'),
+
+    WindowsSDK('6.0A',
+               sanity_check_file=r'include\windows.h'),
+
+    WindowsSDK('6.0',
+               sanity_check_file=r'bin\gacutil.exe'),
+
+    PlatformSDK('2003R2',
+                sanity_check_file=r'SetEnv.Cmd',
+                uuid="D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1"),
+
+    PlatformSDK('2003R1',
+                sanity_check_file=r'SetEnv.Cmd',
+                uuid="8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3"),
+]
+
+SupportedSDKMap = {}
+for sdk in SupportedSDKList:
+    SupportedSDKMap[sdk.version] = sdk
+
+
+# Finding installed SDKs isn't cheap, because it goes not only to the
+# registry but also to the disk to sanity-check that there is, in fact,
+# an SDK installed there and that the registry entry isn't just stale.
+# Find this information once, when requested, and cache it.
+
+InstalledSDKList = None
+InstalledSDKMap = None
+
+def get_installed_sdks():
+    global InstalledSDKList
+    global InstalledSDKMap
+    if InstalledSDKList is None:
+        InstalledSDKList = []
+        InstalledSDKMap = {}
+        for sdk in SupportedSDKList:
+            if sdk.get_install_dir():
+                InstalledSDKList.append(sdk)
+                InstalledSDKMap[sdk.version] = sdk
+    return InstalledSDKList
+
+
+# We may be asked to update multiple construction environments with
+# SDK information.  When doing this, we check on-disk for whether
+# the SDK has 'mfc' and 'atl' subdirectories.  Since going to disk
+# is expensive, cache results by directory.
+
+SDKEnvironmentUpdates = {}
+
+def set_sdk_by_directory(env, sdk_dir):
+    global SDKEnvironmentUpdates
+    try:
+        env_tuple_list = SDKEnvironmentUpdates[sdk_dir]
+    except KeyError:
+        env_tuple_list = []
+        SDKEnvironmentUpdates[sdk_dir] = env_tuple_list
+
+        include_path = os.path.join(sdk_dir, 'include')
+        mfc_path = os.path.join(include_path, 'mfc')
+        atl_path = os.path.join(include_path, 'atl')
+
+        if os.path.exists(mfc_path):
+            env_tuple_list.append(('INCLUDE', mfc_path))
+        if os.path.exists(atl_path):
+            env_tuple_list.append(('INCLUDE', atl_path))
+        env_tuple_list.append(('INCLUDE', include_path))
+
+        env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib')))
+        env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib')))
+        env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin')))
+
+    for variable, directory in env_tuple_list:
+        env.PrependENVPath(variable, directory)
+
+
+# TODO(sgk):  currently unused; remove?
+def get_cur_sdk_dir_from_reg():
+    """Try to find the platform sdk directory from the registry.
+
+    Return None if failed or the directory does not exist"""
+    if not SCons.Util.can_read_reg:
+        debug('SCons cannot read registry')
+        return None
+
+    try:
+        val = read_reg(_CURINSTALLED_SDK_HKEY_ROOT)
+        debug("Found current sdk dir in registry: %s" % val)
+    except WindowsError, e:
+        debug("Did not find current sdk in registry")
+        return None
+
+    if not os.path.exists(val):
+        debug("Current sdk dir %s not on fs" % val)
+        return None
+
+    return val
+
+
+def detect_sdk():
+    return (len(get_installed_sdks()) > 0)
+
+def set_sdk_by_version(env, mssdk):
+    if not SupportedSDKMap.has_key(mssdk):
+        msg = "SDK version %s is not supported" % repr(mssdk)
+        raise SCons.Errors.UserError, msg
+    get_installed_sdks()
+    sdk = InstalledSDKMap.get(mssdk)
+    if not sdk:
+        msg = "SDK version %s is not installed" % repr(mssdk)
+        raise SCons.Errors.UserError, msg
+    set_sdk_by_directory(env, sdk.get_install_dir())
+
+def set_default_sdk(env, msver):
+    """Set up the default Platform/Windows SDK."""
+    # For MSVS < 8, use integrated windows sdk by default
+    if msver >= 8:
+        sdks = get_installed_sdks()
+        if len(sdks) > 0:
+            set_sdk_by_directory(env, sdks[0].get_install_dir())
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

src/engine/SCons/Tool/MSCommon/vs.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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+__doc__ = """Module to detect Visual Studio and/or Visual C/C++
+"""
+
+import os
+
+import SCons.Errors
+import SCons.Util
+
+from SCons.Tool.MSCommon.common import debug, \
+                                       read_reg, \
+                                       normalize_env, \
+                                       get_output, \
+                                       parse_output
+
+class VisualStudio:
+    """
+    An abstract base class for trying to find installed versions of
+    Visual Studio.
+    """
+    def __init__(self, version, **kw):
+        self.version = version
+        self.__dict__.update(kw)
+        self._cache = {}
+
+    def batch_file_path(self):
+        pdir = self.get_vc_product_dir()
+        if not pdir:
+            return None
+        return os.path.join(pdir, self.batch_file)
+
+    def common_tools_path(self):
+        return os.environ.get(self.common_tools_var)
+
+    def vc_product_dir_path(self):
+        if not SCons.Util.can_read_reg:
+            debug('SCons can not read registry')
+            return None
+        key = self.hkey_root + '\\' + self.vc_product_dir_key
+        try:
+            comps = read_reg(key)
+        except WindowsError, e:
+            debug('Did not find product dir key %s in registry' % key)
+        else:
+            if self.batch_file_dir_reg_relpath:
+                comps = os.path.join(comps, self.batch_file_dir_reg_relpath)
+            if os.path.exists(comps):
+                return comps
+            debug('%s is not found on the file system' % comps)
+
+    #
+
+    def find_batch_file(self):
+        """Try to find the Visual Studio or Visual C/C++ batch file.
+
+        Return None if failed or the batch file does not exist.
+        """
+        pdir = self.get_vc_product_dir()
+        if not pdir:
+            debug('find_batch_file();  no pdir')
+            return None
+        batch_file = os.path.join(pdir, self.batch_file)
+        if not os.path.isfile(batch_file):
+            debug('%s file not on file system' % batch_file)
+            return None
+        return batch_file
+
+    def find_executable(self):
+        pdir = self.get_vc_product_dir()
+        if not pdir:
+            return None
+        executable = os.path.join(pdir, self.executable_path)
+        if not os.path.isfile(executable):
+            debug('%s file not on file system' % executable)
+            return None
+        return executable
+
+    def find_vc_product_dir(self):
+        if SCons.Util.can_read_reg:
+            key = self.hkey_root + '\\' + self.vc_product_dir_key
+            try:
+                comps = read_reg(key)
+            except WindowsError, e:
+                debug('Did not find product dir key %s in registry' % key)
+            else:
+                if self.batch_file_dir_reg_relpath:
+                    comps = os.path.join(comps, self.batch_file_dir_reg_relpath)
+                if os.path.exists(comps):
+                    return comps
+                debug('%s is not found on the file system' % comps)
+        else:
+            debug('SCons can not read registry')
+
+        d = os.environ.get(self.common_tools_var)
+        if d and os.path.isdir(d):
+            debug('%s found from %s' % (d, self.common_tools_var))
+            if self.batch_file_dir_env_relpath:
+                d = os.path.join(d, self.batch_file_dir_env_relpath)
+            return d
+        return None
+
+    #
+
+    def get_batch_file(self):
+        try:
+            return self._cache['batch_file']
+        except KeyError:
+            batch_file = self.find_batch_file()
+            self._cache['batch_file'] = batch_file
+            return batch_file
+
+    def get_executable(self):
+        try:
+            return self._cache['executable']
+        except KeyError:
+            executable = self.find_executable()
+            self._cache['executable'] = executable
+            return executable
+
+    def get_supported_arch(self):
+        try:
+            return self._cache['supported_arch']
+        except KeyError:
+            # RDEVE: for the time being use hardcoded lists
+            # supported_arch = self.find_supported_arch()
+            self._cache['supported_arch'] = self.supported_arch
+            return self.supported_arch
+
+    def get_vc_product_dir(self):
+        try:
+            return self._cache['vc_product_dir']
+        except KeyError:
+            vc_product_dir = self.find_vc_product_dir()
+            self._cache['vc_product_dir'] = vc_product_dir
+            return vc_product_dir
+
+    def reset(self):
+        self._cache = {}
+
+# The list of supported Visual Studio versions we know how to detect.
+#
+# How to look for .bat file ?
+#  - VS 2008 Express (x86):
+#     * from registry key productdir, gives the full path to vsvarsall.bat. In
+#     HKEY_LOCAL_MACHINE):
+#         Software\Microsoft\VCEpress\9.0\Setup\VC\productdir
+#     * from environmnent variable VS90COMNTOOLS: the path is then ..\..\VC
+#     relatively to the path given by the variable.
+#
+#  - VS 2008 Express (WoW6432: 32 bits on windows x64):
+#         Software\Wow6432Node\Microsoft\VCEpress\9.0\Setup\VC\productdir
+#
+#  - VS 2005 Express (x86):
+#     * from registry key productdir, gives the full path to vsvarsall.bat. In
+#     HKEY_LOCAL_MACHINE):
+#         Software\Microsoft\VCEpress\8.0\Setup\VC\productdir
+#     * from environmnent variable VS80COMNTOOLS: the path is then ..\..\VC
+#     relatively to the path given by the variable.
+#
+#  - VS 2005 Express (WoW6432: 32 bits on windows x64): does not seem to have a
+#  productdir ?
+#
+#  - VS 2003 .Net (pro edition ? x86):
+#     * from registry key productdir. The path is then ..\Common7\Tools\
+#     relatively to the key. The key is in HKEY_LOCAL_MACHINE):
+#         Software\Microsoft\VisualStudio\7.1\Setup\VC\productdir
+#     * from environmnent variable VS71COMNTOOLS: the path is the full path to
+#     vsvars32.bat
+#
+#  - VS 98 (VS 6):
+#     * from registry key productdir. The path is then Bin
+#     relatively to the key. The key is in HKEY_LOCAL_MACHINE):
+#         Software\Microsoft\VisualStudio\6.0\Setup\VC98\productdir
+#
+# The first version found in the list is the one used by default if
+# there are multiple versions installed.  Barring good reasons to
+# the contrary, this means we should list versions from most recent
+# to oldest.  Pro versions get listed before Express versions on the
+# assumption that, by default, you'd rather use the version you paid
+# good money for in preference to whatever Microsoft makes available
+# for free.
+#
+# If you update this list, update the documentation in Tool/msvs.xml.
+
+SupportedVSList = [
+    # Visual Studio 2010
+    # TODO: find the settings, perhaps from someone with a CTP copy?
+    #VisualStudio('TBD',
+    #             hkey_root=r'TBD',
+    #             common_tools_var='TBD',
+    #             batch_file='TBD',
+    #             vc_product_dir_key=r'TBD',
+    #             batch_file_dir_reg_relpath=None,
+    #             batch_file_dir_env_relpath=r'TBD',
+    #             executable_path=r'TBD',
+    #             default_dirname='TBD',
+    #),
+
+    # Visual Studio 2008
+    VisualStudio('9.0',
+                 hkey_root=r'Software\Microsoft\VisualStudio\9.0',
+                 common_tools_var='VS90COMNTOOLS',
+                 batch_file='vcvarsall.bat',
+                 vc_product_dir_key=r'Setup\VC\ProductDir',
+                 batch_file_dir_reg_relpath=None,
+                 batch_file_dir_env_relpath=r'..\..\VC',
+                 executable_path=r'..\Common7\IDE\devenv.com',
+                 default_dirname='Microsoft Visual Studio 9',
+                 supported_arch=['x86', 'amd64'],
+    ),
+
+    # Visual C++ 2008 Express Edition
+    VisualStudio('9.0Exp',
+                 hkey_root=r'Software\Microsoft\VisualStudio\9.0',
+                 common_tools_var='VS90COMNTOOLS',
+                 batch_file='vcvarsall.bat',
+                 vc_product_dir_key=r'Setup\VC\ProductDir',
+                 batch_file_dir_reg_relpath=None,
+                 batch_file_dir_env_relpath=r'..\..\VC',
+                 executable_path=r'..\Common7\IDE\VCExpress.exe',
+                 default_dirname='Microsoft Visual Studio 9',
+                 supported_arch=['x86'],
+    ),
+
+    # Visual Studio 2005
+    VisualStudio('8.0',
+                 hkey_root=r'Software\Microsoft\VisualStudio\8.0',
+                 common_tools_var='VS80COMNTOOLS',
+                 batch_file='vcvarsall.bat',
+                 vc_product_dir_key=r'Setup\VC\ProductDir',
+                 batch_file_dir_reg_relpath=None,
+                 batch_file_dir_env_relpath=r'..\..\VC',
+                 executable_path=r'..\Common7\IDE\devenv.com',
+                 default_dirname='Microsoft Visual Studio 8',
+                 supported_arch=['x86', 'amd64'],
+    ),
+
+    # Visual C++ 2005 Express Edition
+    VisualStudio('8.0Exp',
+                 hkey_root=r'Software\Microsoft\VCExpress\8.0',
+                 common_tools_var='VS80COMNTOOLS',
+                 batch_file='vcvarsall.bat',
+                 vc_product_dir_key=r'Setup\VC\ProductDir',
+                 batch_file_dir_reg_relpath=None,
+                 batch_file_dir_env_relpath=r'..\..\VC',
+                 executable_path=r'..\Common7\IDE\VCExpress.exe',
+                 default_dirname='Microsoft Visual Studio 8',
+                 supported_arch=['x86'],
+    ),
+
+    # Visual Studio .NET 2003
+    VisualStudio('7.1',
+                 hkey_root=r'Software\Microsoft\VisualStudio\7.1',
+                 common_tools_var='VS71COMNTOOLS',
+                 batch_file='vsvars32.bat',
+                 vc_product_dir_key=r'Setup\VC\ProductDir',
+                 batch_file_dir_reg_relpath=r'..\Common7\Tools',
+                 batch_file_dir_env_relpath=None,
+                 executable_path=r'..\Common7\IDE\devenv.com',
+                 default_dirname='Microsoft Visual Studio .NET',
+                 supported_arch=['x86'],
+    ),
+
+    # Visual Studio .NET
+    VisualStudio('7.0',
+                 hkey_root=r'Software\Microsoft\VisualStudio\7.0',
+                 common_tools_var='VS70COMNTOOLS',
+                 batch_file='vsvars32.bat',
+                 vc_product_dir_key=r'Setup\VC\ProductDir',
+                 batch_file_dir_reg_relpath=r'..\Common7\Tools',
+                 batch_file_dir_env_relpath=None,
+                 executable_path=r'..\Common7\IDE\devenv.com',
+                 default_dirname='Microsoft Visual Studio .NET',
+                 supported_arch=['x86'],
+    ),
+
+    # Visual Studio 6.0
+    VisualStudio('6.0',
+                 hkey_root=r'Software\Microsoft\VisualStudio\6.0',
+                 common_tools_var='VS60COMNTOOLS',
+                 batch_file='vcvars32.bat',
+                 vc_product_dir_key='Setup\Microsoft Visual C++\ProductDir',
+                 batch_file_dir_reg_relpath='Bin',
+                 batch_file_dir_env_relpath=None,
+                 executable_path=r'Common\MSDev98\Bin\MSDEV.COM',
+                 default_dirname='Microsoft Visual Studio',
+                 supported_arch=['x86'],
+    ),
+]
+
+SupportedVSMap = {}
+for vs in SupportedVSList:
+    SupportedVSMap[vs.version] = vs
+
+
+# Finding installed versions of Visual Studio isn't cheap, because it
+# goes not only to the registry but also to the disk to sanity-check
+# that there is, in fact, a Visual Studio directory there and that the
+# registry entry isn't just stale.  Find this information once, when
+# requested, and cache it.
+
+InstalledVSList = None
+InstalledVSMap = None
+
+def get_installed_visual_studios():
+    global InstalledVSList
+    global InstalledVSMap
+    if InstalledVSList is None:
+        InstalledVSList = []
+        InstalledVSMap = {}
+        for vs in SupportedVSList:
+            debug('trying to find %s' % vs.version)
+            if vs.get_batch_file():
+                debug('found %s' % vs.version)
+                InstalledVSList.append(vs)
+                InstalledVSMap[vs.version] = vs
+    return InstalledVSList
+
+def reset_installed_visual_studios():
+    global InstalledVSList
+    global InstalledVSMap
+    InstalledVSList = None
+    InstalledVSMap = None
+    for vs in SupportedVSList:
+        vs.reset()
+
+
+# We may be asked to update multiple construction environments with
+# SDK information.  When doing this, we check on-disk for whether
+# the SDK has 'mfc' and 'atl' subdirectories.  Since going to disk
+# is expensive, cache results by directory.
+
+#SDKEnvironmentUpdates = {}
+#
+#def set_sdk_by_directory(env, sdk_dir):
+#    global SDKEnvironmentUpdates
+#    try:
+#        env_tuple_list = SDKEnvironmentUpdates[sdk_dir]
+#    except KeyError:
+#        env_tuple_list = []
+#        SDKEnvironmentUpdates[sdk_dir] = env_tuple_list
+#
+#        include_path = os.path.join(sdk_dir, 'include')
+#        mfc_path = os.path.join(include_path, 'mfc')
+#        atl_path = os.path.join(include_path, 'atl')
+#
+#        if os.path.exists(mfc_path):
+#            env_tuple_list.append(('INCLUDE', mfc_path))
+#        if os.path.exists(atl_path):
+#            env_tuple_list.append(('INCLUDE', atl_path))
+#        env_tuple_list.append(('INCLUDE', include_path))
+#
+#        env_tuple_list.append(('LIB', os.path.join(sdk_dir, 'lib')))
+#        env_tuple_list.append(('LIBPATH', os.path.join(sdk_dir, 'lib')))
+#        env_tuple_list.append(('PATH', os.path.join(sdk_dir, 'bin')))
+#
+#    for variable, directory in env_tuple_list:
+#        env.PrependENVPath(variable, directory)
+
+def detect_msvs():
+    return (len(get_installed_visual_studios()) > 0)
+
+def get_vs_by_version(msvs):
+    if not SupportedVSMap.has_key(msvs):
+        msg = "Visual Studio version %s is not supported" % repr(msvs)
+        raise SCons.Errors.UserError, msg
+    get_installed_visual_studios()
+    vs = InstalledVSMap.get(msvs)
+    # Some check like this would let us provide a useful error message
+    # if they try to set a Visual Studio version that's not installed.
+    # However, we also want to be able to run tests (like the unit
+    # tests) on systems that don't, or won't ever, have it installed.
+    # It might be worth resurrecting this, with some configurable
+    # setting that the tests can use to bypass the check.
+    #if not vs:
+    #    msg = "Visual Studio version %s is not installed" % repr(msvs)
+    #    raise SCons.Errors.UserError, msg
+    return vs
+
+def get_default_version(env):
+    """Returns the default version string to use for MSVS.
+
+    If no version was requested by the user through the MSVS environment
+    variable, query all the available the visual studios through
+    query_versions, and take the highest one.
+
+    Return
+    ------
+    version: str
+        the default version.
+    """
+    if not env.has_key('MSVS') or not SCons.Util.is_Dict(env['MSVS']):
+        # TODO(1.5):
+        #versions = [vs.version for vs in get_installed_visual_studios()]
+        versions = map(lambda vs: vs.version, get_installed_visual_studios())
+        env['MSVS'] = {'VERSIONS' : versions}
+    else:
+        versions = env['MSVS'].get('VERSIONS', [])
+
+    if not env.has_key('MSVS_VERSION'):
+        if versions:
+            env['MSVS_VERSION'] = versions[0] #use highest version by default
+        else:
+            env['MSVS_VERSION'] = SupportedVSList[0].version
+
+    env['MSVS']['VERSION'] = env['MSVS_VERSION']
+
+    return env['MSVS_VERSION']
+
+def get_default_arch(env):
+    """Return the default arch to use for MSVS
+
+    if no version was requested by the user through the MSVS_ARCH environment
+    variable, select x86
+
+    Return
+    ------
+    arch: str
+    """
+    arch = env.get('MSVS_ARCH', 'x86')
+
+    msvs = InstalledVSMap.get(env['MSVS_VERSION'])
+
+    if not msvs:
+        arch = 'x86'
+    elif not arch in msvs.get_supported_arch():
+        fmt = "Visual Studio version %s does not support architecture %s"
+        raise SCons.Errors.UserError, fmt % (env['MSVS_VERSION'], arch)
+
+    return arch
+
+def merge_default_version(env):
+    version = get_default_version(env)
+    arch = get_default_arch(env)
+
+    msvs = get_vs_by_version(version)
+    if msvs is None:
+        return
+    batfilename = msvs.get_batch_file()
+
+    # XXX: I think this is broken. This will silently set a bogus tool instead
+    # of failing, but there is no other way with the current scons tool
+    # framework
+    if batfilename is not None:
+
+        vars = ('LIB', 'LIBPATH', 'PATH', 'INCLUDE')
+
+        msvs_list = get_installed_visual_studios()
+        # TODO(1.5):
+        #vscommonvarnames = [ vs.common_tools_var for vs in msvs_list ]
+        vscommonvarnames = map(lambda vs: vs.common_tools_var, msvs_list)
+        nenv = normalize_env(env['ENV'], vscommonvarnames + ['COMSPEC'])
+        output = get_output(batfilename, arch, env=nenv)
+        vars = parse_output(output, vars)
+
+        for k, v in vars.items():
+            env.PrependENVPath(k, v, delete_existing=1)
+
+def query_versions():
+    """Query the system to get available versions of VS. A version is
+    considered when a batfile is found."""
+    msvs_list = get_installed_visual_studios()
+    # TODO(1.5)
+    #versions = [ msvs.version for msvs in msvs_list ]
+    versions = map(lambda msvs:  msvs.version, msvs_list)
+    return versions
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

src/engine/SCons/Tool/linkloc.py

 import SCons.Tool
 import SCons.Util
 
-from SCons.Tool.msvc import get_msvc_paths
+from SCons.Tool.MSCommon import detect_msvs, merge_default_version
 from SCons.Tool.PharLapCommon import addPharLapPaths
 
 _re_linker_command = re.compile(r'(\s)@\s*([^\s]+)')
     env['LIBLINKPREFIX']='-lib '
     env['LIBLINKSUFFIX']='$LIBSUFFIX'
 
-    msvs_version = env.get('MSVS_VERSION')
-    include_path, lib_path, exe_path = get_msvc_paths(env, version = msvs_version)
-    env['ENV']['LIB'] = lib_path
-    env.PrependENVPath('PATH', exe_path)
+    # Set-up ms tools paths for default version
+    merge_default_version(env)
 
     addPharLapPaths(env)
 
 def exists(env):
-    return env.Detect('linkloc')
+    if detect_msvs():
+        return env.Detect('linkloc')
+    else:
+        return 0
 
 # Local Variables:
 # tab-width:4

src/engine/SCons/Tool/midl.py

 import SCons.Scanner.IDL
 import SCons.Util
 
+from MSCommon import detect_msvs
+
 def midl_emitter(target, source, env):
     """Produces a list of outputs from the MIDL compiler"""
     base, ext = SCons.Util.splitext(str(target[0]))
     env['BUILDERS']['TypeLibrary'] = midl_builder
 
 def exists(env):
-    if not env['PLATFORM'] in ('win32', 'cygwin'):
-        return 0
-
-    import SCons.Tool.msvs
-    if SCons.Tool.msvs.is_msvs_installed():
-        # there's at least one version of MSVS installed, which comes with midl:
-        return 1
-    else:
-        return env.Detect('midl')
+    return detect_msvs()
 
 # Local Variables:
 # tab-width:4

src/engine/SCons/Tool/mslib.py

 import SCons.Tool.msvc
 import SCons.Util
 
+from MSCommon import detect_msvs, merge_default_version
+
 def generate(env):
     """Add Builders and construction variables for lib to an Environment."""
     SCons.Tool.createStaticLibBuilder(env)
 
-    try:
-        version = SCons.Tool.msvs.get_default_visualstudio_version(env)
-
-        if env.has_key('MSVS_IGNORE_IDE_PATHS') and env['MSVS_IGNORE_IDE_PATHS']:
-            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(env,version)
-        else:
-            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,version)
-
-        # since other tools can set this, we just make sure that the
-        # relevant stuff from MSVS is in there somewhere.
-        env.PrependENVPath('PATH', exe_path)
-    except (SCons.Util.RegError, SCons.Errors.InternalError):
-        pass
+    # Set-up ms tools paths for default version
+    merge_default_version(env)
 
     env['AR']          = 'lib'
     env['ARFLAGS']     = SCons.Util.CLVar('/nologo')
     env['LIBSUFFIX']   = '.lib'
 
 def exists(env):
-    try:
-        v = SCons.Tool.msvs.get_visualstudio_versions()
-    except (SCons.Util.RegError, SCons.Errors.InternalError):
-        pass
-
-    if not v:
-        return env.Detect('lib')
-    else:
-        # there's at least one version of MSVS installed.
-        return 1
+    return detect_msvs()
 
 # Local Variables:
 # tab-width:4

src/engine/SCons/Tool/mslink.py

 import SCons.Tool.msvs
 import SCons.Util
 
+from MSCommon import merge_default_version, detect_msvs
+
 def pdbGenerator(env, target, source, for_signature):
     try:
         return ['/PDB:%s' % target[0].attributes.pdb, '/DEBUG']
     env['REGSVRFLAGS'] = '/s '
     env['REGSVRCOM'] = '$REGSVR $REGSVRFLAGS ${TARGET.windows}'
 
-    try:
-        version = SCons.Tool.msvs.get_default_visualstudio_version(env)
-
-        if env.has_key('MSVS_IGNORE_IDE_PATHS') and env['MSVS_IGNORE_IDE_PATHS']:
-            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_default_paths(env,version)
-        else:
-            include_path, lib_path, exe_path = SCons.Tool.msvc.get_msvc_paths(env,version)
-
-        # since other tools can set these, we just make sure that the
-        # relevant stuff from MSVS is in there somewhere.
-        env.PrependENVPath('INCLUDE', include_path)
-        env.PrependENVPath('LIB', lib_path)
-        env.PrependENVPath('PATH', exe_path)
-    except (SCons.Util.RegError, SCons.Errors.InternalError):
-        pass
+    # Set-up ms tools paths for default version
+    merge_default_version(env)
 
     # Loadable modules are on Windows the same as shared libraries, but they
     # are subject to different build parameters (LDMODULE* variables).
     env['LDMODULECOM'] = compositeLdmodAction
 
 def exists(env):
-    platform = env.get('PLATFORM', '')
-    if SCons.Tool.msvs.is_msvs_installed():
-        # there's at least one version of MSVS installed.
-        return 1
-    elif platform in ('win32', 'cygwin'):
-        # Only explicitly search for a 'link' executable on Windows
-        # systems.  Some other systems (e.g. Ubuntu Linux) have an
-        # executable named 'link' and we don't want that to make SCons
-        # think Visual Studio is installed.
-        return env.Detect('link')
-    return None
+    return detect_msvs()
 
 # Local Variables:
 # tab-width:4

src/engine/SCons/Tool/mssdk.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.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""engine.SCons.Tool.mssdk
+
+Tool-specific initialization for Microsoft SDKs, both Platform
+SDKs and Windows SDKs.
+
+There normally shouldn't be any need to import this module directly.
+It will usually be imported through the generic SCons.Tool.Tool()
+selection method.
+"""
+
+from SCons.Tool.MSCommon.sdk import detect_sdk, \
+                                    set_default_sdk, \
+                                    set_sdk_by_directory, \
+                                    set_sdk_by_version
+
+def generate(env):
+    """Add construction variables for an MS SDK to an Environment."""
+    if env.has_key('MSSDK_DIR'):
+        set_sdk_by_directory(env, env.subst('$MSSDK_DIR'))
+        return
+
+    if env.has_key('MSSDK_VERSION'):
+        set_sdk_by_version(env, env.subst('$MSSDK_VERSION'))
+        return
+
+    if env.has_key('MSVS_VERSION'):
+        set_default_sdk(env, env['MSVS_VERSION'])
+
+    #print "No MSVS_VERSION: this is likely to be a bug"
+    return
+
+def exists(env):
+    return detect_sdk()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:

src/engine/SCons/Tool/mssdk.xml

+<!--
+__COPYRIGHT__
+
+This file is processed by the bin/SConsDoc.py module.
+See its __doc__ string for a discussion of the format.
+-->
+<tool name="mssdk">
+<summary>
+Sets variables for Microsoft Platform SDK and/or Windows SDK.
+Note that unlike most other Tool modules,
+mssdk does not set construction variables,
+but sets the <emphasis>environment variables</emphasis>
+in the environment &SCons; uses to execute
+the Microsoft toolchain:
+<literal>%INCLUDE%</literal>,
+<literal>%LIB%</literal>,
+<literal>%LIBPATH%</literal> and
+<literal>%PATH%</literal>.
+</summary>
+<sets>
+</sets>
+<uses>
+MSSDK_DIR
+MSSDK_VERSION
+MSVS_VERSION
+</uses>
+</tool>
+
+<cvar name="MSSDK_DIR">
+<summary>
+The directory containing the Microsoft SDK
+(either Platform SDK or Windows SDK)
+to be used for compilation.
+</summary>
+</cvar>
+
+<cvar name="MSSDK_VERSION">
+<summary>
+The version string of the Microsoft SDK
+(either Platform SDK or Windows SDK)
+to be used for compilation.
+Supported versions include
+<literal>6.1</literal>,
+<literal>6.0A</literal>,
+<literal>6.0</literal>,
+<literal>2003R2</literal>
+and 
+<literal>2003R1</literal>.
+</summary>
+</cvar>

src/engine/SCons/Tool/msvc.py

 import os.path
 import re
 import string
+import sys
 
 import SCons.Action
 import SCons.Builder
 import SCons.Warnings
 import SCons.Scanner.RC
 
+from MSCommon import merge_default_version, detect_msvs
+
 CSuffixes = ['.c', '.C']
 CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
 
-def _parse_msvc7_overrides(version,platform):
-    """ Parse any overridden defaults for MSVS directory locations
-    in MSVS .NET. """
-
-    # First, we get the shell folder for this user:
-    if not SCons.Util.can_read_reg:
-        raise SCons.Errors.InternalError, "No Windows registry module was found"
-
-    comps = ""
-    try:
-        (comps, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
-                                            r'Software\Microsoft\Windows\CurrentVersion' +\
-                                            r'\Explorer\Shell Folders\Local AppData')
-    except SCons.Util.RegError:
-        raise SCons.Errors.InternalError, \
-              "The Local AppData directory was not found in the registry."
-
-    comps = comps + '\\Microsoft\\VisualStudio\\' + version + '\\VCComponents.dat'
-    dirs = {}
-
-    if os.path.exists(comps):
-        # now we parse the directories from this file, if it exists.
-        # We only look for entries after:
-        # [VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories],
-        # since this file could contain a number of things...
-        lines = None
-        try:
-            import codecs
-        except ImportError:
-            pass
-        else:
-            try:
-                f = codecs.open(comps, 'r', 'utf16')
-                encoder = codecs.getencoder('ascii')
-                lines = map(lambda l, e=encoder: e(l)[0], f.readlines())
-            except (LookupError, UnicodeError):
-                lines = codecs.open(comps, 'r', 'utf8').readlines()
-        if lines is None:
-            lines = open(comps, 'r').readlines()
-        if 'x86' == platform: platform = 'Win32'
-
-        found = 0
-        for line in lines:
-            line.strip()
-            if line.find(r'[VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories]'%platform) >= 0:
-                found = 1
-            elif line == '' or line[:1] == '[':
-                found = 0
-            elif found == 1:
-                kv = line.split('=', 1)
-                if len(kv) == 2:
-                    (key, val) = kv
-                key = key.replace(' Dirs','')
-                dirs[key.upper()] = val
-        f.close()
-    else:
-        # since the file didn't exist, we have only the defaults in
-        # the registry to work with.
-
-        if 'x86' == platform: platform = 'Win32'
-
-        try:
-            K = 'SOFTWARE\\Microsoft\\VisualStudio\\' + version
-            K = K + r'\VC\VC_OBJECTS_PLATFORM_INFO\%s\Directories'%platform
-            k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,K)
-            i = 0
-            while 1:
-                try:
-                    (key,val,t) = SCons.Util.RegEnumValue(k,i)
-                    key = key.replace(' Dirs','')
-                    dirs[key.upper()] = val
-                    i = i + 1
-                except SCons.Util.RegError:
-                    break
-        except SCons.Util.RegError:
-            # if we got here, then we didn't find the registry entries:
-            raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
-    return dirs
-
-def _parse_msvc8_overrides(version,platform,suite):
-    """ Parse any overridden defaults for MSVC directory locations
-    in MSVC 2005. """
-
-    # In VS8 the user can change the location of the settings file that
-    # contains the include, lib and binary paths. Try to get the location
-    # from registry
-    if not SCons.Util.can_read_reg:
-        raise SCons.Errors.InternalError, "No Windows registry module was found"
-
-    # XXX This code assumes anything that isn't EXPRESS uses the default
-    # registry key string.  Is this really true for all VS suites?
-    if suite == 'EXPRESS':
-        s = '\\VCExpress\\'
-    else:
-        s = '\\VisualStudio\\'
-
-    settings_path = ""
-    try:
-        (settings_path, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
-                                                    r'Software\Microsoft' + s + version +\
-                                                    r'\Profile\AutoSaveFile')
-        settings_path = settings_path.upper()
-    except SCons.Util.RegError:
-        raise SCons.Errors.InternalError, \
-              "The VS8 settings file location was not found in the registry."
-
-    # Look for potential environment variables in the settings path
-    if settings_path.find('%VSSPV_VISUALSTUDIO_DIR%') >= 0:
-        # First replace a special variable named %vsspv_visualstudio_dir%
-        # that is not found in the OSs environment variables...
-        try:
-            (value, t) = SCons.Util.RegGetValue(SCons.Util.HKEY_CURRENT_USER,
-                                                r'Software\Microsoft' + s + version +\
-                                                r'\VisualStudioLocation')
-            settings_path = settings_path.replace('%VSSPV_VISUALSTUDIO_DIR%', value)
-        except SCons.Util.RegError:
-            raise SCons.Errors.InternalError, "The VS8 settings file location was not found in the registry."
-
-    if settings_path.find('%') >= 0:
-        # Collect global environment variables
-        env_vars = {}
-
-        # Read all the global environment variables of the current user
-        k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_CURRENT_USER, r'Environment')
-        i = 0
-        while 1:
-            try:
-                (key,val,t) = SCons.Util.RegEnumValue(k,i)
-                env_vars[key.upper()] = val.upper()
-                i = i + 1
-            except SCons.Util.RegError:
-                break
-
-        # And some more variables that are not found in the registry
-        env_vars['USERPROFILE'] = os.getenv('USERPROFILE')
-        env_vars['SystemDrive'] = os.getenv('SystemDrive')
-
-        found_var = 1
-        while found_var:
-            found_var = 0
-            for env_var in env_vars:
-                if settings_path.find(r'%' + env_var + r'%') >= 0:
-                    settings_path = settings_path.replace(r'%' + env_var + r'%', env_vars[env_var])
-                    found_var = 1
-
-    dirs = {}
-
-    if os.path.exists(settings_path):
-        # now we parse the directories from this file, if it exists.
-        import xml.dom.minidom
-        doc = xml.dom.minidom.parse(settings_path)
-        user_settings = doc.getElementsByTagName('UserSettings')[0]
-        tool_options = user_settings.getElementsByTagName('ToolsOptions')[0]
-        tool_options_categories = tool_options.getElementsByTagName('ToolsOptionsCategory')
-        environment_var_map = {
-            'IncludeDirectories' : 'INCLUDE',
-            'LibraryDirectories' : 'LIBRARY',
-            'ExecutableDirectories' : 'PATH',
-        }
-        for category in tool_options_categories:
-            category_name = category.attributes.get('name')
-            if category_name is not None and category_name.value == 'Projects':
-                subcategories = category.getElementsByTagName('ToolsOptionsSubCategory')
-                for subcategory in subcategories:
-                    subcategory_name = subcategory.attributes.get('name')
-                    if subcategory_name is not None and subcategory_name.value == 'VCDirectories':
-                        properties = subcategory.getElementsByTagName('PropertyValue')
-                        for property in properties:
-                            property_name = property.attributes.get('name')
-                            if property_name is None:
-                                continue
-                            var_name = environment_var_map.get(property_name)
-                            if var_name:
-                                data = property.childNodes[0].data
-                                value_list = string.split(data, '|')
-                                if len(value_list) == 1:
-                                    dirs[var_name] = value_list[0]
-                                else:
-                                    while value_list:
-                                        dest, value = value_list[:2]
-                                        del value_list[:2]
-                                        # ToDo: Support for destinations
-                                        # other than Win32
-                                        if dest == 'Win32':
-                                            dirs[var_name] = value
-                                            break
-    else:
-        # There are no default directories in the registry for VS8 Express :(
-        raise SCons.Errors.InternalError, "Unable to find MSVC paths in the registry."
-    return dirs
-
-def _get_msvc7_path(path, version, platform):
-    """
-    Get Visual Studio directories from version 7 (MSVS .NET)
-    (it has a different registry structure than versions before it)
-    """
-    # first, look for a customization of the default values in the
-    # registry: These are sometimes stored in the Local Settings area
-    # for Visual Studio, in a file, so we have to parse it.
-    dirs = _parse_msvc7_overrides(version,platform)
-
-    if dirs.has_key(path):
-        p = dirs[path]
-    else:
-        raise SCons.Errors.InternalError, \
-              "Unable to retrieve the %s path from MS VC++."%path
-
-    # collect some useful information for later expansions...
-    paths = SCon