Merged revisions 62954-62959,62961,62963-62967,62969-62970,62972-62973,62975-62976,62978-62982,62984,62987-62996 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r62954 | martin.v.loewis | 2008-05-09 16:11:37 -0400 (Fri, 09 May 2008) | 1 line

  Port to VS 2008. Drop W9x support.
........
  r62957 | benjamin.peterson | 2008-05-09 17:30:26 -0400 (Fri, 09 May 2008) | 2 lines

  In stdtypes.rst, move methods under class directives where applicable
........
  r62958 | brett.cannon | 2008-05-09 17:30:36 -0400 (Fri, 09 May 2008) | 2 lines

  Add a todo list to the module deletion command.
........
  r62963 | brett.cannon | 2008-05-09 18:52:28 -0400 (Fri, 09 May 2008) | 2 lines

  Add support for extension modules in 3.0 deprection command.
........
  r62967 | brett.cannon | 2008-05-09 22:25:00 -0400 (Fri, 09 May 2008) | 2 lines

  Fix some errors in the deprecation warnings for new and user.
........
  r62975 | brett.cannon | 2008-05-09 22:54:52 -0400 (Fri, 09 May 2008) | 3 lines

  Suppress deprecations for packages as well when using
  test.test_support.import_module().
........
  r62976 | brett.cannon | 2008-05-09 22:57:03 -0400 (Fri, 09 May 2008) | 2 lines

  Also ignore package deprecations.
........
  r62982 | benjamin.peterson | 2008-05-09 23:08:17 -0400 (Fri, 09 May 2008) | 2 lines

  Add the examples in the json module docstring as a doctest
........
  r62992 | martin.v.loewis | 2008-05-10 09:24:09 -0400 (Sat, 10 May 2008) | 2 lines

  Explicitly refer to current hhp file (2.6a3)
........
  r62993 | skip.montanaro | 2008-05-10 10:48:49 -0400 (Sat, 10 May 2008) | 2 lines

  Note the PyPI-edness of bsddb185 for people who might still need it.
........
  r62994 | andrew.kuchling | 2008-05-10 13:36:24 -0400 (Sat, 10 May 2008) | 1 line

  Docstring typo
........
  r62995 | andrew.kuchling | 2008-05-10 13:37:05 -0400 (Sat, 10 May 2008) | 1 line

  Document the 'line' argument
........
  r62996 | andrew.kuchling | 2008-05-10 13:48:45 -0400 (Sat, 10 May 2008) | 1 line

  #1625509: describe behaviour of import lock
........
This commit is contained in:
Alexandre Vassalotti 2008-05-15 22:51:26 +00:00
parent 6461e10158
commit a79e33e039
12 changed files with 223 additions and 204 deletions

View File

@ -112,10 +112,16 @@ This module provides an interface to the mechanisms used to implement the
.. function:: acquire_lock()
Acquires the interpreter's import lock for the current thread. This lock should
Acquire the interpreter's import lock for the current thread. This lock should
be used by import hooks to ensure thread-safety when importing modules. On
platforms without threads, this function does nothing.
Once a thread has acquired the import lock, the same thread may acquire it
again without blocking; the thread must release it once for each time it has
acquired it.
On platforms without threads, this function does nothing.
.. function:: release_lock()

View File

@ -1458,159 +1458,160 @@ The constructors for both classes work the same:
sets, the inner sets must be :class:`frozenset` objects. If *iterable* is
not specified, a new empty set is returned.
Instances of :class:`set` and :class:`frozenset` provide the following
operations:
Instances of :class:`set` and :class:`frozenset` provide the following
operations:
.. describe:: len(s)
.. describe:: len(s)
Return the cardinality of set *s*.
Return the cardinality of set *s*.
.. describe:: x in s
.. describe:: x in s
Test *x* for membership in *s*.
Test *x* for membership in *s*.
.. describe:: x not in s
.. describe:: x not in s
Test *x* for non-membership in *s*.
Test *x* for non-membership in *s*.
.. method:: set.isdisjoint(other)
.. method:: isdisjoint(other)
Return True if the set has no elements in common with *other*.
Sets are disjoint if and only if their interesection is the empty set.
Return True if the set has no elements in common with *other*. Sets are
disjoint if and only if their interesection is the empty set.
.. method:: set.issubset(other)
set <= other
.. method:: issubset(other)
set <= other
Test whether every element in the set is in *other*.
Test whether every element in the set is in *other*.
.. method:: set < other
.. method:: set < other
Test whether the set is a true subset of *other*, that is,
``set <= other and set != other``.
Test whether the set is a true subset of *other*, that is,
``set <= other and set != other``.
.. method:: set.issuperset(other)
set >= other
.. method:: issuperset(other)
set >= other
Test whether every element in *other* is in the set.
Test whether every element in *other* is in the set.
.. method:: set > other
.. method:: set > other
Test whether the set is a true superset of *other*, that is,
``set >= other and set != other``.
Test whether the set is a true superset of *other*, that is, ``set >=
other and set != other``.
.. method:: set.union(other)
set | other
.. method:: union(other)
set | other
Return a new set with elements from both sets.
Return a new set with elements from both sets.
.. method:: set.intersection(other)
set & other
.. method:: intersection(other)
set & other
Return a new set with elements common to both sets.
Return a new set with elements common to both sets.
.. method:: set.difference(other)
set - other
.. method:: difference(other)
set - other
Return a new set with elements in the set that are not in *other*.
Return a new set with elements in the set that are not in *other*.
.. method:: set.symmetric_difference(other)
set ^ other
.. method:: symmetric_difference(other)
set ^ other
Return a new set with elements in either the set or *other* but not both.
Return a new set with elements in either the set or *other* but not both.
.. method:: set.copy()
.. method:: copy()
Return a new set with a shallow copy of *s*.
Return a new set with a shallow copy of *s*.
Note, the non-operator versions of :meth:`union`, :meth:`intersection`,
:meth:`difference`, and :meth:`symmetric_difference`, :meth:`issubset`, and
:meth:`issuperset` methods will accept any iterable as an argument. In
contrast, their operator based counterparts require their arguments to be sets.
This precludes error-prone constructions like ``set('abc') & 'cbs'`` in favor of
the more readable ``set('abc').intersection('cbs')``.
Note, the non-operator versions of :meth:`union`, :meth:`intersection`,
:meth:`difference`, and :meth:`symmetric_difference`, :meth:`issubset`, and
:meth:`issuperset` methods will accept any iterable as an argument. In
contrast, their operator based counterparts require their arguments to be
sets. This precludes error-prone constructions like ``set('abc') & 'cbs'``
in favor of the more readable ``set('abc').intersection('cbs')``.
Both :class:`set` and :class:`frozenset` support set to set comparisons. Two
sets are equal if and only if every element of each set is contained in the
other (each is a subset of the other). A set is less than another set if and
only if the first set is a proper subset of the second set (is a subset, but is
not equal). A set is greater than another set if and only if the first set is a
proper superset of the second set (is a superset, but is not equal).
Both :class:`set` and :class:`frozenset` support set to set comparisons. Two
sets are equal if and only if every element of each set is contained in the
other (each is a subset of the other). A set is less than another set if and
only if the first set is a proper subset of the second set (is a subset, but
is not equal). A set is greater than another set if and only if the first set
is a proper superset of the second set (is a superset, but is not equal).
Instances of :class:`set` are compared to instances of :class:`frozenset` based
on their members. For example, ``set('abc') == frozenset('abc')`` returns
``True`` and so does ``set('abc') in set([frozenset('abc')])``.
Instances of :class:`set` are compared to instances of :class:`frozenset`
based on their members. For example, ``set('abc') == frozenset('abc')``
returns ``True`` and so does ``set('abc') in set([frozenset('abc')])``.
The subset and equality comparisons do not generalize to a complete ordering
function. For example, any two disjoint sets are not equal and are not subsets
of each other, so *all* of the following return ``False``: ``a<b``, ``a==b``,
or ``a>b``. Accordingly, sets do not implement the :meth:`__cmp__` method.
The subset and equality comparisons do not generalize to a complete ordering
function. For example, any two disjoint sets are not equal and are not
subsets of each other, so *all* of the following return ``False``: ``a<b``,
``a==b``, or ``a>b``. Accordingly, sets do not implement the :meth:`__cmp__`
method.
Since sets only define partial ordering (subset relationships), the output of
the :meth:`list.sort` method is undefined for lists of sets.
Since sets only define partial ordering (subset relationships), the output of
the :meth:`list.sort` method is undefined for lists of sets.
Set elements, like dictionary keys, must be :term:`hashable`.
Set elements, like dictionary keys, must be :term:`hashable`.
Binary operations that mix :class:`set` instances with :class:`frozenset` return
the type of the first operand. For example: ``frozenset('ab') | set('bc')``
returns an instance of :class:`frozenset`.
Binary operations that mix :class:`set` instances with :class:`frozenset`
return the type of the first operand. For example: ``frozenset('ab') |
set('bc')`` returns an instance of :class:`frozenset`.
The following table lists operations available for :class:`set` that do not
apply to immutable instances of :class:`frozenset`:
The following table lists operations available for :class:`set` that do not
apply to immutable instances of :class:`frozenset`:
.. method:: set.update(other)
set |= other
.. method:: update(other)
set |= other
Update the set, adding elements from *other*.
Update the set, adding elements from *other*.
.. method:: set.intersection_update(other)
set &= other
.. method:: intersection_update(other)
set &= other
Update the set, keeping only elements found in it and *other*.
Update the set, keeping only elements found in it and *other*.
.. method:: set.difference_update(other)
set -= other
.. method:: difference_update(other)
set -= other
Update the set, removing elements found in *other*.
Update the set, removing elements found in *other*.
.. method:: set.symmetric_difference_update(other)
set ^= other
.. method:: symmetric_difference_update(other)
set ^= other
Update the set, keeping only elements found in either set, but not in both.
Update the set, keeping only elements found in either set, but not in both.
.. method:: set.add(elem)
.. method:: add(elem)
Add element *elem* to the set.
Add element *elem* to the set.
.. method:: set.remove(elem)
.. method:: remove(elem)
Remove element *elem* from the set. Raises :exc:`KeyError` if *elem* is not
contained in the set.
Remove element *elem* from the set. Raises :exc:`KeyError` if *elem* is
not contained in the set.
.. method:: set.discard(elem)
.. method:: discard(elem)
Remove element *elem* from the set if it is present.
Remove element *elem* from the set if it is present.
.. method:: set.pop()
.. method:: pop()
Remove and return an arbitrary element from the set. Raises :exc:`KeyError`
if the set is empty.
Remove and return an arbitrary element from the set. Raises
:exc:`KeyError` if the set is empty.
.. method:: set.clear()
.. method:: clear()
Remove all elements from the set.
Remove all elements from the set.
Note, the non-operator versions of the :meth:`update`,
:meth:`intersection_update`, :meth:`difference_update`, and
:meth:`symmetric_difference_update` methods will accept any iterable as an
argument.
Note, the non-operator versions of the :meth:`update`,
:meth:`intersection_update`, :meth:`difference_update`, and
:meth:`symmetric_difference_update` methods will accept any iterable as an
argument.
Note, the *elem* argument to the :meth:`__contains__`, :meth:`remove`, and
:meth:`discard` methods may be a set. To support searching for an equivalent
frozenset, the *elem* set is temporarily mutated during the search and then
restored. During the search, the *elem* set should not be read or mutated
since it does not have a meaningful value.
Note, the *elem* argument to the :meth:`__contains__`, :meth:`remove`, and
:meth:`discard` methods may be a set. To support searching for an equivalent
frozenset, the *elem* set is temporarily mutated during the search and then
restored. During the search, the *elem* set should not be read or mutated
since it does not have a meaningful value.
.. _typesmapping:
@ -1674,108 +1675,109 @@ pairs within braces, for example: ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098:
others work with any valid keys.
These are the operations that dictionaries support (and therefore, custom mapping
types should support too):
These are the operations that dictionaries support (and therefore, custom
mapping types should support too):
.. describe:: len(d)
.. describe:: len(d)
Return the number of items in the dictionary *d*.
Return the number of items in the dictionary *d*.
.. describe:: d[key]
.. describe:: d[key]
Return the item of *d* with key *key*. Raises a :exc:`KeyError` if *key* is
not in the map.
If a subclass of dict defines a method :meth:`__missing__`, if the key *key*
is not present, the ``d[key]`` operation calls that method with the key *key*
as argument. The ``d[key]`` operation then returns or raises whatever is
returned or raised by the ``__missing__(key)`` call if the key is not
present. No other operations or methods invoke :meth:`__missing__`. If
:meth:`__missing__` is not defined, :exc:`KeyError` is raised.
:meth:`__missing__` must be a method; it cannot be an instance variable. For
an example, see :class:`collections.defaultdict`.
Return the item of *d* with key *key*. Raises a :exc:`KeyError` if *key* is
not in the map.
If a subclass of dict defines a method :meth:`__missing__`, if the key *key*
is not present, the ``d[key]`` operation calls that method with the key *key*
as argument. The ``d[key]`` operation then returns or raises whatever is
returned or raised by the ``__missing__(key)`` call if the key is not
present. No other operations or methods invoke :meth:`__missing__`. If
:meth:`__missing__` is not defined, :exc:`KeyError` is raised.
:meth:`__missing__` must be a method; it cannot be an instance variable. For
an example, see :class:`collections.defaultdict`.
.. describe:: d[key] = value
.. describe:: d[key] = value
Set ``d[key]`` to *value*.
Set ``d[key]`` to *value*.
.. describe:: del d[key]
.. describe:: del d[key]
Remove ``d[key]`` from *d*. Raises a :exc:`KeyError` if *key* is not in the
map.
Remove ``d[key]`` from *d*. Raises a :exc:`KeyError` if *key* is not in the
map.
.. describe:: key in d
.. describe:: key in d
Return ``True`` if *d* has a key *key*, else ``False``.
Return ``True`` if *d* has a key *key*, else ``False``.
.. describe:: key not in d
.. describe:: key not in d
Equivalent to ``not key in d``.
Equivalent to ``not key in d``.
.. method:: dict.clear()
.. method:: clear()
Remove all items from the dictionary.
Remove all items from the dictionary.
.. method:: dict.copy()
.. method:: copy()
Return a shallow copy of the dictionary.
Return a shallow copy of the dictionary.
.. method:: dict.fromkeys(seq[, value])
.. method:: fromkeys(seq[, value])
Create a new dictionary with keys from *seq* and values set to *value*.
Create a new dictionary with keys from *seq* and values set to *value*.
:func:`fromkeys` is a class method that returns a new dictionary. *value*
defaults to ``None``.
:meth:`fromkeys` is a class method that returns a new dictionary. *value*
defaults to ``None``.
.. method:: dict.get(key[, default])
.. method:: get(key[, default])
Return the value for *key* if *key* is in the dictionary, else *default*. If
*default* is not given, it defaults to ``None``, so that this method never
raises a :exc:`KeyError`.
Return the value for *key* if *key* is in the dictionary, else *default*.
If *default* is not given, it defaults to ``None``, so that this method
never raises a :exc:`KeyError`.
.. method:: dict.items()
.. method:: items()
Return a new view of the dictionary's items (``(key, value)`` pairs). See
below for documentation of view objects.
Return a new view of the dictionary's items (``(key, value)`` pairs). See
below for documentation of view objects.
.. method:: dict.keys()
.. method:: keys()
Return a new view of the dictionary's keys. See below for documentation of
view objects.
Return a new view of the dictionary's keys. See below for documentation of
view objects.
.. method:: dict.pop(key[, default])
.. method:: pop(key[, default])
If *key* is in the dictionary, remove it and return its value, else return
*default*. If *default* is not given and *key* is not in the dictionary, a
:exc:`KeyError` is raised.
If *key* is in the dictionary, remove it and return its value, else return
*default*. If *default* is not given and *key* is not in the dictionary,
a :exc:`KeyError` is raised.
.. method:: dict.popitem()
.. method:: popitem()
Remove and return an arbitrary ``(key, value)`` pair from the dictionary.
Remove and return an arbitrary ``(key, value)`` pair from the dictionary.
:func:`popitem` is useful to destructively iterate over a dictionary, as
often used in set algorithms. If the dictionary is empty, calling
:func:`popitem` raises a :exc:`KeyError`.
:meth:`popitem` is useful to destructively iterate over a dictionary, as
often used in set algorithms. If the dictionary is empty, calling
:meth:`popitem` raises a :exc:`KeyError`.
.. method:: dict.setdefault(key[, default])
.. method:: setdefault(key[, default])
If *key* is in the dictionary, return its value. If not, insert *key* with
a value of *default* and return *default*. *default* defaults to ``None``.
If *key* is in the dictionary, return its value. If not, insert *key*
with a value of *default* and return *default*. *default* defaults to
``None``.
.. method:: dict.update([other])
.. method:: update([other])
Update the dictionary with the key/value pairs from *other*, overwriting
existing keys. Return ``None``.
Update the dictionary with the key/value pairs from *other*, overwriting
existing keys. Return ``None``.
:func:`update` accepts either another dictionary object or an iterable of
key/value pairs (as a tuple or other iterable of length two). If keyword
arguments are specified, the dictionary is then is updated with those
key/value pairs: ``d.update(red=1, blue=2)``.
:meth:`update` accepts either another dictionary object or an iterable of
key/value pairs (as a tuple or other iterable of length two). If keyword
arguments are specified, the dictionary is then is updated with those
key/value pairs: ``d.update(red=1, blue=2)``.
.. method:: dict.values()
.. method:: values()
Return a new view of the dictionary's values. See below for documentation of
view objects.
Return a new view of the dictionary's values. See below for documentation of
view objects.
Dictionary view objects

View File

@ -209,12 +209,17 @@ Available Functions
resulting string to *file*, which defaults to ``sys.stderr``. You may replace
this function with an alternative implementation by assigning to
``warnings.showwarning``.
*line* is a line of source code to be included in the warning
message; if *line* is not supplied, :func:`showwarning` will
try to read the line specified by *filename* and *lineno*.
.. function:: formatwarning(message, category, filename, lineno[, line])
Format a warning the standard way. This returns a string which may contain
embedded newlines and ends in a newline.
embedded newlines and ends in a newline. *line* is
a line of source code to be included in the warning message; if *line* is not supplied,
:func:`formatwarning` will try to read the line specified by *filename* and *lineno*.
.. function:: filterwarnings(action[, message[, category[, module[, lineno[, append]]]]])

View File

@ -184,7 +184,7 @@ def addsitedir(sitedir, known_paths=None):
def check_enableusersite():
"""Check if user site directory is safe for inclusion
The functions tests for the command line flag (including environment var),
The function tests for the command line flag (including environment var),
process uid/gid equal to effective uid/gid.
None: Disabled for security reasons

View File

@ -9,7 +9,8 @@ class AllTest(unittest.TestCase):
def check_all(self, modname):
names = {}
with catch_warning():
warnings.filterwarnings("ignore", ".* module", DeprecationWarning)
warnings.filterwarnings("ignore", ".* (module|package)",
DeprecationWarning)
try:
exec("import %s" % modname, names)
except ImportError:

View File

@ -11,6 +11,7 @@ import test.test_support
def test_main():
test.test_support.run_unittest(json.tests.test_suite())
test.test_support.run_doctest(json)
if __name__ == "__main__":

View File

@ -42,7 +42,8 @@ def import_module(name, deprecated=False):
available."""
with catch_warning(record=False):
if deprecated:
warnings.filterwarnings("ignore", ".+ module", DeprecationWarning)
warnings.filterwarnings("ignore", ".+ (module|package)",
DeprecationWarning)
try:
module = __import__(name, level=0)
except ImportError:

View File

@ -6,24 +6,50 @@
<string>nop</string>
<key>command</key>
<string>#!/usr/bin/python
"""Generate code to warn about a module's removal in Python 3.0.
template = """from warnings import warnpy3k
XXX Not supported:
- Module's in a package do not have their full name generated.
- Package's __init__ module; should detect and use the package's name instead.
"""
py_template = """from warnings import warnpy3k
warnpy3k("the ${1:%s} module has been removed in Python 3.0", stacklevel=2)
del warnpy3k
$0"""
del warnpy3k$0"""
c_template = """
if (PyErr_WarnPy3k("the ${1:%s} module has been removed in "
"Python 3.0", 2) &lt; 0)
return;$0"""
import imp
import os
file_name = os.path.split(os.environ['TM_FILEPATH'])[1]
for suffix in (tuple_[0] for tuple_ in imp.get_suffixes()):
if not file_name.endswith(suffix):
py_suffixes = reversed(sorted((suffix[0] for suffix in imp.get_suffixes() if suffix[2] == imp.PY_SOURCE), key=len))
c_suffixes = reversed(sorted((os.path.splitext(suffix[0])[0] + '.c'
for suffix in imp.get_suffixes() if suffix[2] == imp.C_EXTENSION), key=len))
pairings = ((py_suffixes, py_template), (c_suffixes, c_template))
def create_template(suffixes, template):
for suffix in suffixes:
if not file_name.endswith(suffix):
continue
module_name = file_name[:-len(suffix)]
return template % module_name
else:
return None
for template in (create_template(*pair) for pair in pairings):
if not template:
continue
module_name = file_name[:-len(suffix)]
print (template % module_name),
print template,
break
else:
print (template % "XXX"),</string>
print 'XXX Could not generate code.'</string>
<key>input</key>
<string>none</string>
<key>name</key>

View File

@ -22,10 +22,12 @@
<string>Python-Dev</string>
<key>ordering</key>
<array>
<string>9519C22B-6AB8-41A1-94F6-079E0B45C147</string>
<string>B545BB1B-A8E1-426C-B50A-426E78B96D38</string>
<string>6EF151E5-7149-4F82-8796-0CC40FE589FA</string>
<string>FD25A8DC-22DC-4ED4-B222-B943C8A9117D</string>
<string>BF336FFF-E14D-4BF1-A156-71CF768AC034</string>
<string>EDBB037F-AAE3-4512-863F-D9AA82C9E51E</string>
</array>
<key>uuid</key>
<string>A932ECD1-D43A-4F57-B7FB-A1CEC3B65D20</string>

View File

@ -9,7 +9,7 @@ vcbuild /useenv PCbuild\pcbuild.sln "Release|Win32"
@rem build the documentation
bash.exe -c 'cd Doc;make PYTHON=python2.5 update htmlhelp'
"%ProgramFiles%\HTML Help Workshop\hhc.exe" Doc\build\htmlhelp\pydoc.hhp
"%ProgramFiles%\HTML Help Workshop\hhc.exe" Doc\build\htmlhelp\python30a5.hhp
@rem buold the MSI file
cd PC

View File

@ -1,8 +1,6 @@
#include "windows.h"
#include "msiquery.h"
int isWinNT;
/* Print a debug message to the installer log file.
* To see the debug messages, install with
* msiexec /i pythonxy.msi /l*v python.log
@ -30,21 +28,14 @@ UINT __declspec(dllexport) __stdcall CheckDir(MSIHANDLE hInstall)
DWORD size = PSIZE;
DWORD attributes;
isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
if (isWinNT)
result = MsiGetPropertyW(hInstall, L"TARGETDIR", wpath, &size);
else
result = MsiGetPropertyA(hInstall, "TARGETDIR", path, &size);
result = MsiGetPropertyW(hInstall, L"TARGETDIR", wpath, &size);
if (result != ERROR_SUCCESS)
return result;
wpath[size] = L'\0';
path[size] = L'\0';
if (isWinNT)
attributes = GetFileAttributesW(wpath);
else
attributes = GetFileAttributesA(path);
attributes = GetFileAttributesW(wpath);
if (attributes == INVALID_FILE_ATTRIBUTES ||
!(attributes & FILE_ATTRIBUTE_DIRECTORY))
{

View File

@ -1,25 +1,9 @@
!IF "$(CPU)" == ""
# VS environment
# /OPT: REF and ICF are added by VS.NET by default
# NOWIN98 saves 7k of executable size, at the expense of some
# slowdown on Win98
msisupport.dll: msisupport.obj
link.exe /OUT:msisupport.dll /INCREMENTAL:NO /NOLOGO /DLL /MACHINE:X86 /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /OPT:NOWIN98 msisupport.obj msi.lib kernel32.lib
link.exe /OUT:msisupport.dll /INCREMENTAL:NO /NOLOGO /DLL /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF msisupport.obj msi.lib kernel32.lib
# We request a static CRT, so that there will be no CRT dependencies
# for the target system. We cannot do without a CRT, since it provides
# the DLL entry point.
msisupport.obj: msisupport.c
cl /O2 /D WIN32 /D NDEBUG /D _WINDOWS /MT /W3 /c msisupport.c
!ELSE
# SDK environment: assume all options are already correct
msisupport.dll: msisupport.obj
link.exe /OUT:msisupport.dll /INCREMENTAL:NO /NOLOGO /DLL msisupport.obj msi.lib kernel32.lib
msisupport.obj: msisupport.c
cl /O2 /D WIN32 /D NDEBUG /D _WINDOWS /MD /W3 /GS- /c msisupport.c
!ENDIF