summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2016-08-22 18:00:24 -0600
committerCharles Harris <charlesr.harris@gmail.com>2016-08-24 10:43:29 -0600
commitc7602711ac86d862a44470e534d96487e5d52536 (patch)
tree5c1a1bb0732a62fc94f31eba1f7bb472dcb99169
parent276423aa7f4f7d39189ee5ccf7b167ad2c9c25a7 (diff)
downloadnumpy-c7602711ac86d862a44470e534d96487e5d52536.tar.gz
BUG: MSVCCompiler grows 'lib' & 'include' env strings exponentially.
Each time an MSVCCompiler was instantiated the old values of os.environ['lib'] and os.environ['include'] were concatenated to the new values set by initializing the distutils.msvc{,9}compiler.MSVCCompiler base class. Consequently when the the old and new values of those variables were the same, they doubled in size with each instantiation, leading to quickly hitting the 32,768 character limit.
-rw-r--r--numpy/distutils/msvc9compiler.py62
-rw-r--r--numpy/distutils/msvccompiler.py60
2 files changed, 97 insertions, 25 deletions
diff --git a/numpy/distutils/msvc9compiler.py b/numpy/distutils/msvc9compiler.py
index c53f45531..58af9042f 100644
--- a/numpy/distutils/msvc9compiler.py
+++ b/numpy/distutils/msvc9compiler.py
@@ -1,25 +1,63 @@
from __future__ import division, absolute_import, print_function
import os
-import distutils.msvc9compiler
-from distutils.msvc9compiler import *
+from distutils.msvc9compiler import MSVCCompiler as _MSVCCompiler
-class MSVCCompiler(distutils.msvc9compiler.MSVCCompiler):
+def _merge(old, new):
+ """Concatenate two environment paths avoiding repeats.
+
+ Here `old` is the environment string before the base class initialize
+ function is called and `new` is the string after the call. The new string
+ will be a fixed string if it is not obtained from the current enviroment,
+ or the same as the old string if obtained from the same enviroment. The aim
+ here is not to append the new string if it is already contained in the old
+ string so as to limit the growth of the environment string.
+
+ Parameters
+ ----------
+ old : string
+ Previous enviroment string.
+ new : string
+ New environment string.
+
+ Returns
+ -------
+ ret : string
+ Updated environment string.
+
+ """
+ if new in old:
+ return old
+ if not old:
+ return new
+
+ # Neither new nor old is empty. Give old priority.
+ return ';'.join([old, new])
+
+
+class MSVCCompiler(_MSVCCompiler):
def __init__(self, verbose=0, dry_run=0, force=0):
- distutils.msvc9compiler.MSVCCompiler.__init__(self, verbose, dry_run, force)
+ _MSVCCompiler.__init__(self, verbose, dry_run, force)
def initialize(self, plat_name=None):
+ # The 'lib' and 'include' variables may be overwritten
+ # by MSVCCompiler.initialize, so save them for later merge.
environ_lib = os.getenv('lib')
environ_include = os.getenv('include')
- distutils.msvc9compiler.MSVCCompiler.initialize(self, plat_name)
- if environ_lib is not None:
- os.environ['lib'] = environ_lib + os.environ['lib']
- if environ_include is not None:
- os.environ['include'] = environ_include + os.environ['include']
+ _MSVCCompiler.initialize(self, plat_name)
+
+ # Merge current and previous values of 'lib' and 'include'
+ os.environ['lib'] = _merge(environ_lib, os.environ['lib'])
+ os.environ['include'] = _merge(environ_include, os.environ['include'])
+
+ # msvc9 building for 32 bits requires SSE2 to work around a
+ # compiler bug.
+ if platform_bits == 32:
+ self.compile_options += ['/arch:SSE2']
+ self.compile_options_debug += ['/arch:SSE2']
def manifest_setup_ldargs(self, output_filename, build_temp, ld_args):
ld_args.append('/MANIFEST')
- distutils.msvc9compiler.MSVCCompiler.manifest_setup_ldargs(self,
- output_filename,
- build_temp, ld_args)
+ _MSVCCompiler.manifest_setup_ldargs(self, output_filename,
+ build_temp, ld_args)
diff --git a/numpy/distutils/msvccompiler.py b/numpy/distutils/msvccompiler.py
index 78a386d5d..575013a11 100644
--- a/numpy/distutils/msvccompiler.py
+++ b/numpy/distutils/msvccompiler.py
@@ -1,26 +1,60 @@
from __future__ import division, absolute_import, print_function
import os
-import distutils.msvccompiler
-from distutils.msvccompiler import *
+from distutils.msvccompiler import MSVCCompiler as _MSVCCompiler
from .system_info import platform_bits
-class MSVCCompiler(distutils.msvccompiler.MSVCCompiler):
+def _merge(old, new):
+ """Concatenate two environment paths avoiding repeats.
+
+ Here `old` is the environment string before the base class initialize
+ function is called and `new` is the string after the call. The new string
+ will be a fixed string if it is not obtained from the current enviroment,
+ or the same as the old string if obtained from the same enviroment. The aim
+ here is not to append the new string if it is already contained in the old
+ string so as to limit the growth of the environment string.
+
+ Parameters
+ ----------
+ old : string
+ Previous enviroment string.
+ new : string
+ New environment string.
+
+ Returns
+ -------
+ ret : string
+ Updated environment string.
+
+ """
+ if new in old:
+ return old
+ if not old:
+ return new
+
+ # Neither new nor old is empty. Give old priority.
+ return ';'.join([old, new])
+
+
+class MSVCCompiler(_MSVCCompiler):
def __init__(self, verbose=0, dry_run=0, force=0):
- distutils.msvccompiler.MSVCCompiler.__init__(self, verbose, dry_run, force)
+ _MSVCCompiler.__init__(self, verbose, dry_run, force)
def initialize(self, plat_name=None):
- environ_lib = os.getenv('lib')
- environ_include = os.getenv('include')
- distutils.msvccompiler.MSVCCompiler.initialize(self, plat_name)
- if environ_lib is not None:
- os.environ['lib'] = environ_lib + os.environ['lib']
- if environ_include is not None:
- os.environ['include'] = environ_include + os.environ['include']
+ # The 'lib' and 'include' variables may be overwritten
+ # by MSVCCompiler.initialize, so save them for later merge.
+ environ_lib = os.getenv('lib', '')
+ environ_include = os.getenv('include', '')
+ _MSVCCompiler.initialize(self, plat_name)
+
+ # Merge current and previous values of 'lib' and 'include'
+ os.environ['lib'] = _merge(environ_lib, os.environ['lib'])
+ os.environ['include'] = _merge(environ_include, os.environ['include'])
+
+ # msvc9 building for 32 bits requires SSE2 to work around a
+ # compiler bug.
if platform_bits == 32:
- # msvc9 building for 32 bits requires SSE2 to work around a
- # compiler bug.
self.compile_options += ['/arch:SSE2']
self.compile_options_debug += ['/arch:SSE2']