Re: [Distutils] WinNT and distutils

Greg Stein <gstein@lyra.org> writes:
Yup, you're right.
In short: no, you cannot parse them. You must have access to the Win32 registry functions.
Presumably Microsoft change the binary format every six months for fun, too...
There has been discussion about putting them into Python 1.6.
That would strike me as quite a good idea. It's hard to see how distutils can function *really* well on Windows without them. Cheers, Michael

On 28 Jan 2000, Michael Hudson wrote:
Heh. Guess Microsoft isn't the only advocate of FUD.
I definitely agree. However, Greg Ward has this requirement in his head: distutils must work on Python 1.5. Therefore, you may have some problems here. Go fight him about it, though. I'll stay on the sidelines :-) Cheers, -g -- Greg Stein, http://www.lyra.org/

Greg Stein writes:
However, Greg Ward has this requirement in his head: distutils must work on Python 1.5. Therefore, you may have some problems here.
As Guido pointed out at IPC8, distutils is most valuable if it doesn't need to be included with the packages that use it and doesn't need to be installed separately. So it's really not "there" until 1.6 anyway. Drop support for 1.5.2 and we're in good shape. Got that, Greg (Ward)? ;) -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> Corporation for National Research Initiatives

On 28 January 2000, Fred L. Drake, Jr. said:
Yeah, I've been (slowly, quietly) moving towards that position anyways. Using all sorts of 1.6 features would make it a bit hard to develop, test, and debug the Distutils -- I guess at some point I'll have to break down and start running the CVS version of Python instead of the standard Red Hat RPM. ;-) What 1.6 features are really, absolutely necessary, though? So far I see only one: * registry access on Windows Others? Oh yeah, will the registry-access code that Robin Becker posted work under 1.5.2 with Mark's extensions installed as well as under 1.6 with built-in registry support? Greg

On Fri, 28 Jan 2000, Greg Ward wrote:
Some people have suggested that distutils does some of its install work via the new import stuff. I'm not sure what that entails (I don't understand why distutils would need the custom importing/packaging that imputil provides). Also, I don't have feedback from Guido yet on what needs to happen to imputil before its incorporation into 1.6. So I'd count this as a "thought" rather than a requirement.
It won't work until 1.6 because we don't have the 1.6 design yet :-) But, there is no reason it shouldn't (with some creative try/except around some imports). Note that win32api isn't going into 1.6 -- either a new module from scratch, or a small extraction of win32api. In any case, it certainly won't (can't) be called win32api. Cheers, -g -- Greg Stein, http://www.lyra.org/

On 28 January 2000, Greg Stein said:
I agree with you: I don't understand why distutils would want to depend on imputils. It seems desirable for distutils to be able to generate archives (or whatever) that can only be imported from using imputils, but I don't see a need to take it farther than that. One can speculate about a world where Python module distributions are distributed as archives with a __run__.py (JPython convention brought to my attention by Barry) that is the setup script. But I think Python itself would have to grok the archive and its __run__.py, and anyways that all seems rather far out at this point.
Ahh, OK, I wasn't really clear on that. I had a vague idea that some sort of registry access would be in 1.6, I gather that Mark's win32api provides registry access, and thus I assumed that something called win32api would be in 1.6. So much for blithe assumptions. So it seems to me as if something like the following will be needed: try: import win32api, win32con get MSVC++ registry keys from it except ImportError: do the same thing with whatever the official Python 1.6 registry access mechanism is except ImportError: just assume cl.exe is on the path if we got the MSVC++ registry keys: use Robin Becker's code to figure out where cl.exe is supposed to be Ugh. This is starting to look like writing an autoconf script. At least it's not in Bourne shell... >shudder<... I guess for now I should stick with the code Robin provided, since there is no "official Python 1.6 registry access mechanism" yet. Greg

In article <20000131093428.A17133@cnri.reston.va.us>, Greg Ward <gward@cnri.reston.va.us> writes ....
... it seems that not all of the directories obtained from the keys are actually rock solid eg they are part of the devstudio customisables. I'm fairly sure that you could add all of the Path dirs to the path set Include=all the directories in Include Dirs (; sep) set Lib=all in the lib dirs (; sep) and then cl.exe etc are supposed to work. I guess that other explicit includes and libs get looked at first so there shouldn't be any harm in adding the extras. -- Robin Becker

On 31 January 2000, Robin Becker said:
??? I don't follow. Are `Include' and `Lib' environment variables that you want me to set? If you could just supply a new patch to msvccompiler.py, I think we'd save a lot of bouncing back and forth. Thanks -- Greg

In article <20000201090005.C17402@cnri.reston.va.us>, Greg Ward <gward@cnri.reston.va.us> writes
OK this patch works for me with none of the vcvars things set. I tried building Numeric and it works modulo complaints about missing arrayfns.def I don't have that so the dll hasn't got an entry point. *** msvccompiler.py.org Mon Jan 17 21:57:18 2000 --- msvccompiler.py Tue Feb 01 16:11:20 2000 *************** *** 10,19 **** --- 10,104 ---- import os import sys + import string from distutils.errors import * from distutils.ccompiler import \ CCompiler, gen_preprocess_options, gen_lib_options + def _devstudio_versions(): + "Get a list of devstudio versions" + try: + import win32api + import win32con + except ImportError: + return None + + K = 'Software\\Microsoft\\Devstudio' + L = [] + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + p = win32api.RegEnumKey(k,i) + if p[0] in '123456789' and p not in L: + L.append(p) + except win32api.error: + break + i = i + 1 + except win32api.error: + pass + L.sort() + return L + + def _msvc_get_paths(path, vNum='6.0', platform='x86'): + "Get a devstudio path (include, lib or path)" + try: + import win32api + import win32con + except ImportError: + return None + + L = [] + if path=='lib': path= 'Library' + path = string.upper(path + ' Dirs') + K = 'Software\\Microsoft\\Devstudio\\%s\\Build System\\Components\\Platforms\\Win32 (%s)\\Directories' \ + % (vNum,platform) + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + (p,v,t) = win32api.RegEnumValue(k,i) + if string.upper(p)==path: + V = string.split(v,';') + for v in V: + if v=='' or v in L: continue + L.append(v) + break + i = i + 1 + except win32api.error: + break + except win32api.error: + pass + return L + + def _find_exe(exe): + for v in _devstudio_versions(): + for p in _msvc_get_paths('bin',v): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + + #didn't find it; try existing path + try: + for p in string.split(os.environ['Path'],';'): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + except: + pass + return exe #last desperate hope + + def _find_SET(n): + for v in _devstudio_versions(): + p=_msvc_get_paths(n,v) + if p!=[]: return p + return [] + + def _do_SET(n): + p=_find_SET(n) + if p!=[]: os.environ[n]=string.join(p,';') class MSVCCompiler (CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, *************** *** 34,41 **** self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! self.cc = "cl.exe" ! self.link = "link.exe" self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] --- 119,135 ---- self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! self.cc = _find_exe("cl.exe") ! self.link = _find_exe("link.exe") ! _do_SET('lib') ! _do_SET('include') ! path=_find_SET('path') ! try: ! for p in string.split(os.environ['path'],';'): ! path.append(p) ! except KeyError: ! pass ! os.environ['path'] = string.join(path,';') self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] -- Robin Becker

Robin, there are some small typos in your patch, and a more severe problem.
-------------------------------------------------------- The more severe problem is the following: The background is that in my PC I have registry entries for version 5.0 and 6.0, although VC5.0 is no longer installed. Note that I had 5.0 installed in different directories than 6.0! It seems the setup program did not remove the 5.0 entries. Now, what happens in your code is the following:
Now the self.spawn() call launches cl.exe, this displays a Box that some dll is not found, because this is not in the (invalid) path. Conclusion: - Your code may mix up different versions of compiler, linker and path, lib, and include directories. The code should first determine a version which is actually installed, and then set up everything, sticking to this version. - _devstudio_versions() returns version numbers in ascending order, so lower version numbers are preferred over higher version numbers. Should be the other way (although I'm not sure if it is possible to have different versions of VC installed at the same time). Do you want to fix this, or should I prepare another patch? Regards, Thomas Heller

In article <035401bf6da9$25e68c30$4500a8c0@thomasnotebook>, Thomas Heller <thomas.heller@ion-tof.com> writes
try this patch Thomas and see if it's ok with your registry. I put in a DistutilsPlatformError if it can't find any devstudio at all. *** msvccompiler.py.org Mon Jan 17 21:57:18 2000 --- msvccompiler.py Wed Feb 02 20:40:40 2000 *************** *** 10,19 **** --- 10,101 ---- import os import sys + import string from distutils.errors import * from distutils.ccompiler import \ CCompiler, gen_preprocess_options, gen_lib_options + def _devstudio_versions(): + "Get a list of devstudio versions" + try: + import win32api + import win32con + except ImportError: + return [] + + K = 'Software\\Microsoft\\Devstudio' + L = [] + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + p = win32api.RegEnumKey(k,i) + if p[0] in '123456789' and p not in L: + L.append(p) + except win32api.error: + break + i = i + 1 + except win32api.error: + pass + L.sort() + L.reverse() + return L + + def _msvc_get_paths(path, vNum='6.0', platform='x86'): + "Get a devstudio path (include, lib or path)" + try: + import win32api + import win32con + except ImportError: + return [] + + L = [] + if path=='lib': path= 'Library' + path = string.upper(path + ' Dirs') + K = 'Software\\Microsoft\\Devstudio\\%s\\Build System\\Components\\Platforms\\Win32 (%s)\\Directories' \ + % (vNum,platform) + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + (p,v,t) = win32api.RegEnumValue(k,i) + if string.upper(p)==path: + V = string.split(v,';') + for v in V: + if v=='' or v in L: continue + L.append(v) + break + i = i + 1 + except win32api.error: + break + except win32api.error: + pass + return L + + def _find_exe(exe,vNum): + for p in _msvc_get_paths('bin',vNum): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + + #didn't find it; try existing path + try: + for p in string.split(os.environ['Path'],';'): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + except: + pass + return exe #last desperate hope + + def _find_SET(n,vNum): + return _msvc_get_paths(n,vNum) + + def _do_SET(n,vNum): + p=_find_SET(n,vNum) + if p!=[]: os.environ[n]=string.join(p,';') class MSVCCompiler (CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, *************** *** 34,41 **** self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! self.cc = "cl.exe" ! self.link = "link.exe" self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] --- 116,136 ---- self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! vNum = _devstudio_versions() ! if vNum==[]: ! raise DistutilsPlatformError, "Can't seem to find devstudio in the registry" ! vNum = vNum[0] #highest version ! self.cc = _find_exe("cl.exe",vNum) ! self.link = _find_exe("link.exe",vNum) ! _do_SET('lib',vNum) ! _do_SET('include',vNum) ! path=_find_SET('path',vNum) ! try: ! for p in string.split(os.environ['path'],';'): ! path.append(p) ! except KeyError: ! pass ! os.environ['path'] = string.join(path,';') self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] -- Robin Becker

Robin, I have extended your patch a little. If it works for you, we should submit it to Greg. The attached file (I have not mastered diff on NT yet) does the following: 1. Try to find cl.exe and link.exe in the path. If this succeeds, it assumes everything is set up and starts the build. User in control! 2. Then it reads the versions from the registry, starting with the highest one until it finds cl and link. For debugging, it also prints the version number it uses. 3. If this also fails, DistutilError is raised. Thomas

In article <030701bf6e58$c4c670e0$4500a8c0@thomasnotebook>, Thomas Heller <thomas.heller@ion-tof.com> writes
I've no problem with your version except that it may fail even though the path is set up. If cl.exe & link.exe are on the path and properly installed then they should findable via the registry. Even so Lib & Include may not be set up and the compile will fail. Searching the registry first won't fail provided it finds the best version and the Lib/Include dirs haven't been hacked to death inside devstudio. Both search orders will fail under particular circumstances. Perhaps it should try both in the manner of autoconf by attempting a trial compile. I'm not serious really. I feel my original search has more chance of success if things are 'properly' installed. -- Robin Becker

In article <02de01bf6da1$93dba1b0$4500a8c0@thomasnotebook>, Thomas Heller <thomas.heller@ion-tof.com> writes Agreed about the typos. I had some idea of checking for non-availability using None. It's simpler to return []. As for the other at the bottom of _devstudio_versions try L.reverse() after the L.sort(). I meant to do that originally, but failed. Then the versions should return the versions in latest first order. It's a bit of a pain to have multiple versions. Probably we should get a version just once and pass to the other lookups as required. if multiple versions are available there's always a choice to be made. Probably we should write a warning message into the output and use the latest throughout. Is there an obvious version flag setup.py?
-- Robin Becker

Where do you get the impression that 1.6 will have Windows registry access built in? I didn't even know that was on the wish list. (If it is, maybe someone can mail me code?) --Guido van Rossum (home page: http://www.python.org/~guido/)

On Fri, 28 Jan 2000, Guido van Rossum wrote:
It will appear in time, or it won't. :-) [ with the caveat of not knowing when "in time" is :-) ] Thomas Heller has offered to write such an extension. Cheers, -g -- Greg Stein, http://www.lyra.org/

Greg Ward writes:
If that's the only dependency we need, that's all that we need. I don't think we need to introduce dependencies artificially. If it works with 1.5.2 on Unix & 1.6 on Windows, I'd be quite happy. With the proposed timeline for 1.6, that seems quite acceptable.
This I don't know. ;) -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> Corporation for National Research Initiatives

On 28 January 2000, Fred L. Drake, Jr. said:
Don't forget, Distutils seems to work fine on Windows as long as cl.exe is in your PATH. I agree that it would be better to be more ironclad (ie. get the VC++ bin directory from the registry if possible), but for now it seems to be muddling along (modulo stupid bugs in my code). Greg

On 28 Jan 2000, Michael Hudson wrote:
Heh. Guess Microsoft isn't the only advocate of FUD.
I definitely agree. However, Greg Ward has this requirement in his head: distutils must work on Python 1.5. Therefore, you may have some problems here. Go fight him about it, though. I'll stay on the sidelines :-) Cheers, -g -- Greg Stein, http://www.lyra.org/

Greg Stein writes:
However, Greg Ward has this requirement in his head: distutils must work on Python 1.5. Therefore, you may have some problems here.
As Guido pointed out at IPC8, distutils is most valuable if it doesn't need to be included with the packages that use it and doesn't need to be installed separately. So it's really not "there" until 1.6 anyway. Drop support for 1.5.2 and we're in good shape. Got that, Greg (Ward)? ;) -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> Corporation for National Research Initiatives

On 28 January 2000, Fred L. Drake, Jr. said:
Yeah, I've been (slowly, quietly) moving towards that position anyways. Using all sorts of 1.6 features would make it a bit hard to develop, test, and debug the Distutils -- I guess at some point I'll have to break down and start running the CVS version of Python instead of the standard Red Hat RPM. ;-) What 1.6 features are really, absolutely necessary, though? So far I see only one: * registry access on Windows Others? Oh yeah, will the registry-access code that Robin Becker posted work under 1.5.2 with Mark's extensions installed as well as under 1.6 with built-in registry support? Greg

On Fri, 28 Jan 2000, Greg Ward wrote:
Some people have suggested that distutils does some of its install work via the new import stuff. I'm not sure what that entails (I don't understand why distutils would need the custom importing/packaging that imputil provides). Also, I don't have feedback from Guido yet on what needs to happen to imputil before its incorporation into 1.6. So I'd count this as a "thought" rather than a requirement.
It won't work until 1.6 because we don't have the 1.6 design yet :-) But, there is no reason it shouldn't (with some creative try/except around some imports). Note that win32api isn't going into 1.6 -- either a new module from scratch, or a small extraction of win32api. In any case, it certainly won't (can't) be called win32api. Cheers, -g -- Greg Stein, http://www.lyra.org/

On 28 January 2000, Greg Stein said:
I agree with you: I don't understand why distutils would want to depend on imputils. It seems desirable for distutils to be able to generate archives (or whatever) that can only be imported from using imputils, but I don't see a need to take it farther than that. One can speculate about a world where Python module distributions are distributed as archives with a __run__.py (JPython convention brought to my attention by Barry) that is the setup script. But I think Python itself would have to grok the archive and its __run__.py, and anyways that all seems rather far out at this point.
Ahh, OK, I wasn't really clear on that. I had a vague idea that some sort of registry access would be in 1.6, I gather that Mark's win32api provides registry access, and thus I assumed that something called win32api would be in 1.6. So much for blithe assumptions. So it seems to me as if something like the following will be needed: try: import win32api, win32con get MSVC++ registry keys from it except ImportError: do the same thing with whatever the official Python 1.6 registry access mechanism is except ImportError: just assume cl.exe is on the path if we got the MSVC++ registry keys: use Robin Becker's code to figure out where cl.exe is supposed to be Ugh. This is starting to look like writing an autoconf script. At least it's not in Bourne shell... >shudder<... I guess for now I should stick with the code Robin provided, since there is no "official Python 1.6 registry access mechanism" yet. Greg

In article <20000131093428.A17133@cnri.reston.va.us>, Greg Ward <gward@cnri.reston.va.us> writes ....
... it seems that not all of the directories obtained from the keys are actually rock solid eg they are part of the devstudio customisables. I'm fairly sure that you could add all of the Path dirs to the path set Include=all the directories in Include Dirs (; sep) set Lib=all in the lib dirs (; sep) and then cl.exe etc are supposed to work. I guess that other explicit includes and libs get looked at first so there shouldn't be any harm in adding the extras. -- Robin Becker

On 31 January 2000, Robin Becker said:
??? I don't follow. Are `Include' and `Lib' environment variables that you want me to set? If you could just supply a new patch to msvccompiler.py, I think we'd save a lot of bouncing back and forth. Thanks -- Greg

In article <20000201090005.C17402@cnri.reston.va.us>, Greg Ward <gward@cnri.reston.va.us> writes
OK this patch works for me with none of the vcvars things set. I tried building Numeric and it works modulo complaints about missing arrayfns.def I don't have that so the dll hasn't got an entry point. *** msvccompiler.py.org Mon Jan 17 21:57:18 2000 --- msvccompiler.py Tue Feb 01 16:11:20 2000 *************** *** 10,19 **** --- 10,104 ---- import os import sys + import string from distutils.errors import * from distutils.ccompiler import \ CCompiler, gen_preprocess_options, gen_lib_options + def _devstudio_versions(): + "Get a list of devstudio versions" + try: + import win32api + import win32con + except ImportError: + return None + + K = 'Software\\Microsoft\\Devstudio' + L = [] + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + p = win32api.RegEnumKey(k,i) + if p[0] in '123456789' and p not in L: + L.append(p) + except win32api.error: + break + i = i + 1 + except win32api.error: + pass + L.sort() + return L + + def _msvc_get_paths(path, vNum='6.0', platform='x86'): + "Get a devstudio path (include, lib or path)" + try: + import win32api + import win32con + except ImportError: + return None + + L = [] + if path=='lib': path= 'Library' + path = string.upper(path + ' Dirs') + K = 'Software\\Microsoft\\Devstudio\\%s\\Build System\\Components\\Platforms\\Win32 (%s)\\Directories' \ + % (vNum,platform) + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + (p,v,t) = win32api.RegEnumValue(k,i) + if string.upper(p)==path: + V = string.split(v,';') + for v in V: + if v=='' or v in L: continue + L.append(v) + break + i = i + 1 + except win32api.error: + break + except win32api.error: + pass + return L + + def _find_exe(exe): + for v in _devstudio_versions(): + for p in _msvc_get_paths('bin',v): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + + #didn't find it; try existing path + try: + for p in string.split(os.environ['Path'],';'): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + except: + pass + return exe #last desperate hope + + def _find_SET(n): + for v in _devstudio_versions(): + p=_msvc_get_paths(n,v) + if p!=[]: return p + return [] + + def _do_SET(n): + p=_find_SET(n) + if p!=[]: os.environ[n]=string.join(p,';') class MSVCCompiler (CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, *************** *** 34,41 **** self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! self.cc = "cl.exe" ! self.link = "link.exe" self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] --- 119,135 ---- self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! self.cc = _find_exe("cl.exe") ! self.link = _find_exe("link.exe") ! _do_SET('lib') ! _do_SET('include') ! path=_find_SET('path') ! try: ! for p in string.split(os.environ['path'],';'): ! path.append(p) ! except KeyError: ! pass ! os.environ['path'] = string.join(path,';') self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] -- Robin Becker

Robin, there are some small typos in your patch, and a more severe problem.
-------------------------------------------------------- The more severe problem is the following: The background is that in my PC I have registry entries for version 5.0 and 6.0, although VC5.0 is no longer installed. Note that I had 5.0 installed in different directories than 6.0! It seems the setup program did not remove the 5.0 entries. Now, what happens in your code is the following:
Now the self.spawn() call launches cl.exe, this displays a Box that some dll is not found, because this is not in the (invalid) path. Conclusion: - Your code may mix up different versions of compiler, linker and path, lib, and include directories. The code should first determine a version which is actually installed, and then set up everything, sticking to this version. - _devstudio_versions() returns version numbers in ascending order, so lower version numbers are preferred over higher version numbers. Should be the other way (although I'm not sure if it is possible to have different versions of VC installed at the same time). Do you want to fix this, or should I prepare another patch? Regards, Thomas Heller

In article <035401bf6da9$25e68c30$4500a8c0@thomasnotebook>, Thomas Heller <thomas.heller@ion-tof.com> writes
try this patch Thomas and see if it's ok with your registry. I put in a DistutilsPlatformError if it can't find any devstudio at all. *** msvccompiler.py.org Mon Jan 17 21:57:18 2000 --- msvccompiler.py Wed Feb 02 20:40:40 2000 *************** *** 10,19 **** --- 10,101 ---- import os import sys + import string from distutils.errors import * from distutils.ccompiler import \ CCompiler, gen_preprocess_options, gen_lib_options + def _devstudio_versions(): + "Get a list of devstudio versions" + try: + import win32api + import win32con + except ImportError: + return [] + + K = 'Software\\Microsoft\\Devstudio' + L = [] + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + p = win32api.RegEnumKey(k,i) + if p[0] in '123456789' and p not in L: + L.append(p) + except win32api.error: + break + i = i + 1 + except win32api.error: + pass + L.sort() + L.reverse() + return L + + def _msvc_get_paths(path, vNum='6.0', platform='x86'): + "Get a devstudio path (include, lib or path)" + try: + import win32api + import win32con + except ImportError: + return [] + + L = [] + if path=='lib': path= 'Library' + path = string.upper(path + ' Dirs') + K = 'Software\\Microsoft\\Devstudio\\%s\\Build System\\Components\\Platforms\\Win32 (%s)\\Directories' \ + % (vNum,platform) + for base in (win32con.HKEY_CLASSES_ROOT,win32con.HKEY_LOCAL_MACHINE,win32con.HKEY_CURRENT_USER,win32con.HKEY_USERS): + try: + k = win32api.RegOpenKeyEx(base,K) + i = 0 + while 1: + try: + (p,v,t) = win32api.RegEnumValue(k,i) + if string.upper(p)==path: + V = string.split(v,';') + for v in V: + if v=='' or v in L: continue + L.append(v) + break + i = i + 1 + except win32api.error: + break + except win32api.error: + pass + return L + + def _find_exe(exe,vNum): + for p in _msvc_get_paths('bin',vNum): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + + #didn't find it; try existing path + try: + for p in string.split(os.environ['Path'],';'): + fn=os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): return fn + except: + pass + return exe #last desperate hope + + def _find_SET(n,vNum): + return _msvc_get_paths(n,vNum) + + def _do_SET(n,vNum): + p=_find_SET(n,vNum) + if p!=[]: os.environ[n]=string.join(p,';') class MSVCCompiler (CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, *************** *** 34,41 **** self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! self.cc = "cl.exe" ! self.link = "link.exe" self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] --- 116,136 ---- self.add_library ( "python" + sys.version[0] + sys.version[2] ) self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) ) ! vNum = _devstudio_versions() ! if vNum==[]: ! raise DistutilsPlatformError, "Can't seem to find devstudio in the registry" ! vNum = vNum[0] #highest version ! self.cc = _find_exe("cl.exe",vNum) ! self.link = _find_exe("link.exe",vNum) ! _do_SET('lib',vNum) ! _do_SET('include',vNum) ! path=_find_SET('path',vNum) ! try: ! for p in string.split(os.environ['path'],';'): ! path.append(p) ! except KeyError: ! pass ! os.environ['path'] = string.join(path,';') self.preprocess_options = None self.compile_options = [ '/nologo', '/Ox', '/MD' ] -- Robin Becker

Robin, I have extended your patch a little. If it works for you, we should submit it to Greg. The attached file (I have not mastered diff on NT yet) does the following: 1. Try to find cl.exe and link.exe in the path. If this succeeds, it assumes everything is set up and starts the build. User in control! 2. Then it reads the versions from the registry, starting with the highest one until it finds cl and link. For debugging, it also prints the version number it uses. 3. If this also fails, DistutilError is raised. Thomas

In article <030701bf6e58$c4c670e0$4500a8c0@thomasnotebook>, Thomas Heller <thomas.heller@ion-tof.com> writes
I've no problem with your version except that it may fail even though the path is set up. If cl.exe & link.exe are on the path and properly installed then they should findable via the registry. Even so Lib & Include may not be set up and the compile will fail. Searching the registry first won't fail provided it finds the best version and the Lib/Include dirs haven't been hacked to death inside devstudio. Both search orders will fail under particular circumstances. Perhaps it should try both in the manner of autoconf by attempting a trial compile. I'm not serious really. I feel my original search has more chance of success if things are 'properly' installed. -- Robin Becker

In article <02de01bf6da1$93dba1b0$4500a8c0@thomasnotebook>, Thomas Heller <thomas.heller@ion-tof.com> writes Agreed about the typos. I had some idea of checking for non-availability using None. It's simpler to return []. As for the other at the bottom of _devstudio_versions try L.reverse() after the L.sort(). I meant to do that originally, but failed. Then the versions should return the versions in latest first order. It's a bit of a pain to have multiple versions. Probably we should get a version just once and pass to the other lookups as required. if multiple versions are available there's always a choice to be made. Probably we should write a warning message into the output and use the latest throughout. Is there an obvious version flag setup.py?
-- Robin Becker

Where do you get the impression that 1.6 will have Windows registry access built in? I didn't even know that was on the wish list. (If it is, maybe someone can mail me code?) --Guido van Rossum (home page: http://www.python.org/~guido/)

On Fri, 28 Jan 2000, Guido van Rossum wrote:
It will appear in time, or it won't. :-) [ with the caveat of not knowing when "in time" is :-) ] Thomas Heller has offered to write such an extension. Cheers, -g -- Greg Stein, http://www.lyra.org/

Greg Ward writes:
If that's the only dependency we need, that's all that we need. I don't think we need to introduce dependencies artificially. If it works with 1.5.2 on Unix & 1.6 on Windows, I'd be quite happy. With the proposed timeline for 1.6, that seems quite acceptable.
This I don't know. ;) -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> Corporation for National Research Initiatives

On 28 January 2000, Fred L. Drake, Jr. said:
Don't forget, Distutils seems to work fine on Windows as long as cl.exe is in your PATH. I agree that it would be better to be more ironclad (ie. get the VC++ bin directory from the registry if possible), but for now it seems to be muddling along (modulo stupid bugs in my code). Greg
participants (7)
-
Fred L. Drake, Jr.
-
Greg Stein
-
Greg Ward
-
Guido van Rossum
-
Michael Hudson
-
Robin Becker
-
Thomas Heller