8000 BUG: MSVCCompiler grows 'lib' & 'include' env strings exponentially. · numpy/numpy@78eba2f · GitHub
[go: up one dir, main page]

Skip to content

Commit 78eba2f

Browse files
committed
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.
1 parent 2c8a3ba commit 78eba2f

File tree

2 files changed

+97
-25
lines changed

2 files changed

+97
-25
lines changed

numpy/distutils/msvc9compiler.py

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,63 @@
11
from __future__ import division, absolute_import, print_function
22

33
import os
4-
import distutils.msvc9compiler
5-
from distutils.msvc9compiler import *
4+
from distutils.msvc9compiler import MSVCCompiler as _MSVCCompiler
65

76

8-
class MSVCCompiler(distutils.msvc9compiler.MSVCCompiler):
7+
def _merge(old, new):
8+
"""Concatenate two environment paths avoiding repeats.
9+
10+
Here `old` is the environment string before the base class initialize
11+
function is called and `new` is the string after the call. The new string
12+
will be a fixed string if it is not obtained from the current enviroment,
13+
or the same as the old string if obtained from the same enviroment. The aim
14+
here is not to append the new string if it is already contained in the old
15+
string so as to limit the growth of the environment string.
16+
17+
Parameters
18+
----------
19+
old : string
20+
Previous enviroment string.
21+
new : string
22+
New environment string.
23+
24+
Returns
25+
-------
26+
ret : string
27+
Updated environment string.
28+
29+
"""
30+
if new in old:
31+
return old
32+
if not old:
33+
return new
34+
35+
# Neither new nor old is empty. Give old priority.
36+
return ';'.join([old, new])
37+
38+
39+
class MSVCCompiler(_MSVCCompiler):
940
def __init__(self, verbose=0, dry_run=0, force=0):
10-
distutils.msvc9compiler.MSVCCompiler.__init__(self, verbose, dry_run, force)
41+
_MSVCCompiler.__init__(self, verbose, dry_run, force)
1142

1243
def initialize(self, plat_name=None):
44+
# The 'lib' and 'include' variables may be overwritten
45+
# by MSVCCompiler.initialize, so save them for later merge.
1346
environ_lib = os.getenv('lib')
1447
environ_include = os.getenv('include')
15-
distutils.msvc9compiler.MSVCCompiler.initialize(self, plat_name)
16-
if environ_lib is not None:
17-
os.environ['lib'] = environ_lib + os.environ['lib']
18-
if environ_include is not None:
19-
os.environ['include'] = environ_include + os.environ['include']
48+
_MSVCCompiler.initialize(self, plat_name)
49+
50+
# Merge current and previous values of 'lib' and 'include'
51+
os.environ['lib'] = _merge(environ_lib, os.environ['lib'])
52+
os.environ['include'] = _merge(environ_include, os.environ['include'])
53+
54+
# msvc9 building for 32 bits requires SSE2 to work around a
55+
# compiler bug.
56+
if platform_bits == 32:
57+
self.compile_options += ['/arch:SSE2']
58+
self.compile_options_debug += ['/arch:SSE2']
2059

2160
def manifest_setup_ldargs(self, output_filename, build_temp, ld_args):
2261
ld_args.append('/MANIFEST')
23-
distutils.msvc9compiler.MSVCCompiler.manifest_setup_ldargs(self,
24-
output_filename,
25-
build_temp, ld_args)
62+
_MSVCCompiler.manifest_setup_ldargs(self, output_filename,
63+
build_temp, ld_args)

numpy/distutils/msvccompiler.py

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,60 @@
11
from __future__ import division, absolute_import, print_function
22

33
import os
4-
import distutils.msvccompiler
5-
from distutils.msvccompiler import *
4+
from distutils.msvccompiler import MSVCCompiler as _MSVCCompiler
65

76
from .system_info import platform_bits
87

98

10-
class MSVCCompiler(distutils.msvccompiler.MSVCCompiler):
9+
def _merge(old, new):
10+
"""Concatenate two environment paths avoiding repeats.
11+
12+
Here `old` is the environment string before the base class initialize
13+
function is called and `new` is the string after the call. The new string
14+
will be a fixed string if it is not obtained from the current enviroment,
15+
or the same as the old string if obtained from the same enviroment. The aim
16+
here is not to append the new string if it is already contained in the old
17+
string so as to limit the growth of the environment string.
18+
19+
Parameters
20+
----------
21+
old : string
22+
Previous enviroment string.
23+
new : string
24+
New environment string.
25+
26+
Returns
27+
-------
28+
ret : string
29+
Updated environment string.
30+
31+
"""
32+
if new in old:
33+
return old
34+
if not old:
35+
return new
36+
37+
# Neither new nor old is empty. Give old priority.
38+
return ';'.join([old, new])
39+
40+
41+
class MSVCCompiler(_MSVCCompiler):
1142
def __init__(self, verbose=0, dry_run=0, force=0):
12-
distutils.msvccompiler.MSVCCompiler.__init__(self, verbose, dry_run, force)
43+
_MSVCCompiler.__init__(self, verbose, dry_run, force)
1344

1445
def initialize(self, plat_name=None):
15-
environ_lib = os.getenv('lib')
16-
environ_include = os.getenv('include')
17-
distutils.msvccompiler.MSVCCompiler.initialize(self, plat_name)
18-
if environ_lib is not None:
19-
os.environ['lib'] = environ_lib + os.environ['lib']
20-
if environ_include is not None:
21-
os.environ['include'] = environ_include + os.environ['include']
46+
# The 'lib' and 'include' variables may be overwritten
47+
# by MSVCCompiler.initialize, so save them for later merge.
48+
environ_lib = os.getenv('lib', '')
49+
environ_include = os.getenv('include', '')
50+
_MSVCCompiler.initialize(self, plat_name)
51+
52+
# Merge current and previous values of 'lib' and 'include'
53+
os.environ['lib'] = _merge(environ_lib, os.environ['lib'])
54+
os.environ['include'] = _merge(environ_include, os.environ['include'])
55+
56+
# msvc9 building for 32 bits requires SSE2 to work around a
57+
# compiler bug.
2258
if platform_bits == 32:
23-
# msvc9 building for 32 bits requires SSE2 to work around a
24-
# compiler bug.
2559
self.compile_options += ['/arch:SSE2']
2660
self.compile_options_debug += ['/arch:SSE2']

0 commit comments

Comments
 (0)
0