From sales@lookelu.com Sat Jul 1 14:20:49 2000 From: sales@lookelu.com (The Western Web) Date: Sat, 1 Jul 2000 13:20:49 Subject: [Distutils] The Western Web has just finished our new classified ad section. Please check it out and make sure that your classified ad has been moved. We are in the process of moving ads at this time, but would appreciate your help to insure that if your ad has been moved. If it hasn't been moved or you would like to place a new ad feel free to do so. We have added new sections in the classifieds, hay/feed/shavings, livestock, camelids, cattle, deer and elk, poultry, rabbits, sheep, livestock equipment, swine, donkeys, dogs and mules. We are currently receiving 100 new ads a day, and over 20,000 unique hits a day. Message-ID: <20000701201950.D8EED1CD8D@dinsdale.python.org> The Western Web has just finished our new classified ad section. Please check it out and make sure that your classified ad has been moved. We are in the process of moving ads at this time, but would appreciate your help to insure that if your ad has been moved. If it hasn't been moved or you would like to place a new ad feel free to do so. We have added new sections in the classifieds, hay/feed/shavings, livestock, camelids, cattle, deer and elk, poultry, rabbits, sheep, livestock equipment, swine, donkeys, dogs and mules. We are currently receiving 100 new ads a day, and over 20,000 unique hits a day. http://www.thewesternweb.com The new classified section is automated now and your ads will be posted immediatly. You can also add Multi-Media files (photos, sound and video) on line. This is a free service to you so use it at your will. http://www.westernwebclassified.com We have also finished the Western Web Search Engine, which is solely optimized for the western way of life. Please stop by the search engine add your site. http://www.lookelu.com Our message board is also now up and running so please use it . http://www.westernmessageboard.com/cgi-bin/Ultimate.cgi We are sorry for any inconvenience. Thank you, http://www.thewesternweb.com This ad is being sent in compliance with Senate bill 1618, Title 3, section 301. http://www.senate.gov/ ~murkowski/commercialemail/S771index.html Here is a more detailed version of the legal notice above: This message is sent in compliance of the new e-mail bill: SECTION 301. Per Section 301, Paragraph (a)(2)(C) of S. 1618, http://www.senate.gov/~murkowski/commercialemail/S771index.html Further transmissions to you by the sender of this email may be stopped at no cost to you by sending a reply to this email address with the word "remove" in the subject line. From gward@python.net Tue Jul 4 15:14:10 2000 From: gward@python.net (Greg Ward) Date: Tue, 4 Jul 2000 10:14:10 -0400 Subject: [Distutils] Can it be? no paper-bag-over-head bugs? Message-ID: <20000704101410.A1900@beelzebub> What's this? No bug reports for 0.9 except for the delay between the announcement and the availability of downloadable files? Oh yeah, and the regex problem with the latest SRE code... but that's not my fault, honest. ;-) Guess everyone must have slept all weekend, 'cause I found at least one itty-bitty teeny-tiny bug while putting together the release. More on that later. Greg -- Greg Ward - just another Python hacker gward@python.net http://starship.python.net/~gward/ A man wrapped up in himself makes a very small package. From gward@python.net Tue Jul 4 15:16:13 2000 From: gward@python.net (Greg Ward) Date: Tue, 4 Jul 2000 10:16:13 -0400 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler In-Reply-To: <395CB802.7CE487C@gmx.de>; from R.Liebscher@gmx.de on Fri, Jun 30, 2000 at 05:08:50PM +0200 References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> Message-ID: <20000704101613.A1881@beelzebub> On 30 June 2000, Rene Liebscher said: > But if you compile it with MSVC or use the downloaded binary > version, then you have this special PC config.h file. And in > this file you need a special section for GNU C. (probably > using #ifdef __GNUC__ somewhere.) > > So I will change my code, if it finds GCC in sys.version, then > it doesn't need to check the config.h file. This is all to avoid the "Python's config.h doesn't seem to support your compiler." warning, right? Or is there something more to it? Have a patch yet, BTW? Greg -- Greg Ward - programmer-at-big gward@python.net http://starship.python.net/~gward/ "I want to be *different*, just like everyone ELSE!" From calvin@cs.uni-sb.de Wed Jul 5 18:20:45 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Wed, 5 Jul 2000 19:20:45 +0200 (CEST) Subject: [Distutils] Python zlib in Debian Message-ID: Hi, I remember the question if zlib is always included in Python installations? Well its not in Debian until you install the python-zlib package. So you have to include this package to the requirements for Debian Linux. Bastian From gward@python.net Thu Jul 6 04:36:15 2000 From: gward@python.net (Greg Ward) Date: Wed, 5 Jul 2000 23:36:15 -0400 Subject: [Distutils] Python zlib in Debian In-Reply-To: ; from calvin@cs.uni-sb.de on Wed, Jul 05, 2000 at 07:20:45PM +0200 References: Message-ID: <20000705233615.A4334@beelzebub> On 05 July 2000, Bastian Kleineidam said: > I remember the question if zlib is always included in Python > installations? Well its not in Debian until you install the python-zlib > package. So you have to include this package to the requirements for > Debian Linux. But zlib is really only needed on Windows, where we create ZIP files from scratch (ie. using zipfile.py and zlib -- not through spawning an external zip utility). On Unix, we generally rely on external utilities (zip, gzip, tar, ...) for that sort of thing. However, having python-zlib installed shouldn't hurt! ;-) Greg -- Greg Ward - geek-at-large gward@python.net http://starship.python.net/~gward/ God is real, unless declared integer. From gward@python.net Tue Jul 4 15:30:29 2000 From: gward@python.net (Greg Ward) Date: Tue, 4 Jul 2000 10:30:29 -0400 Subject: [Distutils] Two thoughts on bdist_rpm Message-ID: <20000704103029.A1918@beelzebub> Well, my first real experience with bdist_rpm was last Thursday, putting together the Distutils 0.9 RPM. I also built RPMs for NumPy and mxDateTime just to see if it would work (it did, mostly). Some comments: * is it really necessary to run "build" twice? This takes quite a while with NumPy (with two source files > 600k) on a 100 MHz Pentium, and I don't think it's necessary -- you *should* just be able to ask the "build" command what its outputs would have been with 'get_outputs()' * the .spec file is always generated with "python setup.py ..." commands, even if I ran "/usr/local/bin/python1.6 setup.py ..." to generate the RPM. Thus, if I use a non-standard Python to create the .spec file, it still uses the standard /usr/bin/python, and I end up with an RPM that goes in /usr/lib/python1.5/site-pacakges. I'm not saying that an RPM that installs to /usr/local/lib/python1.6/site-packages is necessarily a good thing to be distributing, but if I use that python to make the RPM... * should we put the output RPMs (source and "binary" -- not really a binary for pure-Python distributions, but you-know-what-I-mean) in a more convenient place? If I didn't know the system intimately, it would not have occurred to me to look for the built RPM in build/bdist.linux2/rpm/RPMS/noarch. ;-) I'm thinking that a common directory for distribution bureaucracy is a good idea, and we already have a start: putting .spec files in "dist" if bdist_rpm is *only* generating the .spec file. So here's a short list of what could go in "dist" right now: - .spec file - RPMs - Win32 exes - source distributions (tarball, zip file) - dumb built distributions (tarball, zip file) Currently, all of these things wind up wherever they feel (mostly in the distribution root, but also a few other places). This just seems like a really good idea to me, so unless anyone howls I'm going to go ahead and implement it. In future, there could be a "debian" subdirectory of "dist", and maybe a directory of FreeBSD "port" info (if that's how it works -- not really clear on that). A Wise script could also go there, if you need to generate a full-blow Windows installer instead of Thomas' minimalist self-extracting ZIP file. Comments? Greg -- Greg Ward - Linux geek gward@python.net http://starship.python.net/~gward/ I'm a nuclear submarine under the polar ice cap and I need a Kleenex! From R.Liebscher@gmx.de Thu Jul 6 11:57:00 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Thu, 06 Jul 2000 12:57:00 +0200 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> <20000704101613.A1881@beelzebub> Message-ID: <396465FC.3FD96CAD@gmx.de> This is a multi-part message in MIME format. --------------C2F9671324B463815CAE57DD Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Greg Ward wrote: > > On 30 June 2000, Rene Liebscher said: > > But if you compile it with MSVC or use the downloaded binary > > version, then you have this special PC config.h file. And in > > this file you need a special section for GNU C. (probably > > using #ifdef __GNUC__ somewhere.) > > > > So I will change my code, if it finds GCC in sys.version, then > > it doesn't need to check the config.h file. > > This is all to avoid the "Python's config.h doesn't seem to support your > compiler." warning, right? Or is there something more to it? Yes, on a GCC compiled python you would get this warning. > Have a patch yet, BTW? And here is the patch. (It removes also the msvc_hack from build_ext.) It fixes my compiler class to avoid this warning on a GCC compiled python and it removes all the python specific stuff (except the above). It inserts this in build_ext (specifying the export symbol init{module} if no export symbols given and link the library python??) This means also I had to adapt the msvc compiler class and the Extension class (It should be possible to specify None as export symbols, this would mean standard python module with one export symbol, specifying a list would mean export what is in the list.) The def-file will go through the export_symbols parameter. (as string or if given export_symbols as list) I didn't changed bcppcompiler.py because I can't test it. kind regards Rene Liebscher --------------C2F9671324B463815CAE57DD Content-Type: text/plain; charset=iso-8859-1; name="mscv_hack.patch" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="mscv_hack.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build_ext.py dp/distutils/command/build_ext.py --- distutils.orig/distutils/command/build_ext.py Fri Jun 30 17:18:01 2000 +++ dp/distutils/command/build_ext.py Wed Jul 5 11:27:48 2000 @@ -420,16 +420,40 @@ objects.extend (ext.extra_objects) extra_args = ext.extra_link_args or [] - # Bunch of fixing-up we have to do for Microsoft's linker. - if self.compiler.compiler_type == 'msvc': - self.msvc_prelink_hack(sources, ext, extra_args) + # For all platforms and compiler doesn't export all symbols + # by default, we have to specify the module's init function + # if the use doesn't provide any export information. + # All other platforms and compilers should ignore such + # export information. + if ext.export_symbol_file == None and ext.export_symbols == None: + # if no exports are specified we can't build a working + # python module. + # so let us export the module's init function + export_symbols = ["init" + string.split(ext.name,'.')[-1]] + else: + # export_symbols will be a list, a string or None if + # neither export_symbols nor export_symbol_file was set. + export_symbols = ext.export_symbols or ext.export_symbol_file + + # The python library is always needed on + # Windows we need the python version without the dot, eg. '15' + # MSVC doesn't really need this, because the pragma in config.h + if sys.platform == "win32": + pythonlib = ("python%d%d" % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + libraries = ext.libraries + [pythonlib] + else: + libraries = ext.libraries self.compiler.link_shared_object ( objects, ext_filename, - libraries=ext.libraries, + libraries=libraries, library_dirs=ext.library_dirs, runtime_library_dirs=ext.runtime_library_dirs, extra_postargs=extra_args, + export_symbols=export_symbols, debug=self.debug, build_temp=self.build_temp) @@ -511,44 +535,6 @@ # find_swig () - - # -- Hooks 'n hacks ------------------------------------------------ - - def msvc_prelink_hack (self, sources, ext, extra_args): - - # XXX this is a kludge! Knowledge of specific compilers or - # platforms really doesn't belong here; in an ideal world, the - # CCompiler interface would provide access to everything in a - # compiler/linker system needs to build Python extensions, and - # we would just do everything nicely and cleanly through that - # interface. However, this is a not an ideal world and the - # CCompiler interface doesn't handle absolutely everything. - # Thus, kludges like this slip in occasionally. (This is no - # excuse for committing more platform- and compiler-specific - # kludges; they are to be avoided if possible!) - - def_file = ext.export_symbol_file - - if def_file is not None: - extra_args.append ('/DEF:' + def_file) - else: - modname = string.split (ext.name, '.')[-1] - extra_args.append('/export:init%s' % modname) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - implib_file = os.path.join ( - self.implib_dir, - self.get_ext_libname (ext.name)) - extra_args.append ('/IMPLIB:' + implib_file) - self.mkpath (os.path.dirname (implib_file)) - - # msvc_prelink_hack () - - # -- Name generators ----------------------------------------------- # (extension names, filenames, whatever) diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/cygwinccompiler.py dp/distutils/cygwinccompiler.py --- distutils.orig/distutils/cygwinccompiler.py Fri Jun 30 17:17:55 2000 +++ dp/distutils/cygwinccompiler.py Wed Jul 5 12:29:57 2000 @@ -6,11 +6,34 @@ cygwin in no-cygwin mode). """ +# problems: +# +# * if you use a msvc compiled python version (1.5.2) +# 1. you have to insert a __GNUC__ section in its config.h +# 2. you have to generate a import library for its dll +# - create a def-file for python??.dll +# - create a import library using +# dlltool --dllname python15.dll --def python15.def \ +# --output-lib libpython15.a +# +# see also http://starship.python.net/crew/kernr/mingw32 +# +# * cygwin gcc 2.91 works (after patching some include files) +# * mingw32 gcc 2.95.2 works (it doesn't support gcc -shared) +# * cygwin gcc 2.95.2 doesn't work now +# - its dllwrap doesn't work at my machine +# - target had to be changed to something like i686-cygwin32 +# - mingw32-mode is specified by -mno-cygwin +# - using gcc -shared instead dllwrap didn't work because some problems with +# the import library, maybe it needs some additional parameters + + # created 2000/05/05, Rene Liebscher __revision__ = "$Id: cygwinccompiler.py,v 1.2 2000/06/29 22:57:55 gward Exp $" import os,sys,string +from types import * from distutils import sysconfig from distutils.unixccompiler import UnixCCompiler @@ -20,13 +43,25 @@ def check_config_h(): """Checks if the GCC compiler is mentioned in config.h. If it is not, - compiling probably doesn't work, so print a warning to stderr. + compiling probably doesn't work. """ - - # XXX the result of the check should be returned! + # return values + # 2: OK, python was compiled with GCC + # 1: OK, python's config.h mentions __GCC__ + # 0: uncertain, because we couldn't check it + # -1: probably not OK, because we didn't found it in config.h + # You could check check_config_h()>0 => OK from distutils import sysconfig import string,sys + # if sys.version contains GCC then python was compiled with + # GCC, and the config.h file should be OK + try: + string.index(sys.version,"GCC") + return 2 + except ValueError: + pass # go to the next test + try: # It would probably better to read single lines to search. # But we do this only once, and it is fast enough @@ -35,19 +70,15 @@ f.close() try: # is somewhere a #ifdef __GNUC__ or something similar - string.index(s,"__GNUC__") + string.index(s,"__GNUC__") + return 1 except ValueError: - sys.stderr.write ("warning: "+ - "Python's config.h doesn't seem to support your compiler.\n") + return -1 except IOError: # if we can't read this file, we cannot say it is wrong # the compiler will complain later about this file as missing pass - - -# This is called when the module is imported, so we make this check only once -# XXX why not make it only when the compiler is needed? -check_config_h() + return 0 class CygwinCCompiler (UnixCCompiler): @@ -59,8 +90,13 @@ dry_run=0, force=0): + UnixCCompiler.__init__ (self, verbose, dry_run, force) + if check_config_h()<=0: + self.warn( + "Python's config.h doesn't seem to support your compiler.") + # Hard-code GCC because that's what this is all about. # XXX optimization, warnings etc. should be customizable. self.set_executables(compiler='gcc -O -Wall', @@ -96,53 +132,55 @@ if libraries == None: libraries = [] - # Additional libraries: the python library is always needed on - # Windows we need the python version without the dot, eg. '15' - - pythonlib = ("python%d%d" % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - libraries.append(pythonlib) - libraries.extend(self.dll_libraries) - - # name of extension - - # XXX WRONG WRONG WRONG - # this is NOT the place to make guesses about Python namespaces; - # that MUST be done in build_ext.py + # Additional libraries + # libraries.extend(...) would affect the list we got as parameter + # and this can come from anywhere + libraries = libraries + self.dll_libraries + + # we want to put some files in the same directory as the + # object files are, build_temp doesn´t help much + # name of dll if not debug: - ext_name = os.path.basename(output_filename)[:-len(".pyd")] + dll_name = os.path.basename(output_filename)[:-len(".pyd")] else: - ext_name = os.path.basename(output_filename)[:-len("_d.pyd")] + dll_name = os.path.basename(output_filename)[:-len("_d.pyd")] - def_file = os.path.join(build_temp, ext_name + ".def") - #exp_file = os.path.join(build_temp, ext_name + ".exp") - #lib_file = os.path.join(build_temp, 'lib' + ext_name + ".a") + # where are the object files + temp_dir=os.path.dirname(objects[0]) + + # generate the filenames for these files + def_file = None # this will be done later, if necessary + exp_file = os.path.join(temp_dir, dll_name + ".exp") + lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a") - # Make .def file - # (It would probably better to check if we really need this, - # but for this we had to insert some unchanged parts of - # UnixCCompiler, and this is not what we want.) - f = open(def_file,"w") - f.write("EXPORTS\n") # intro - if export_symbols == None: - # export a function "init" + ext_name - f.write("init" + ext_name + "\n") + # check what we got in export_symbols + if export_symbols != None and type(export_symbols) == StringType: + def_file = export_symbol_file else: - # if there are more symbols to export write them into f - for sym in export_symbols: - f.write(sym+"\n") - f.close() - + # Make .def file + # (It would probably better to check if we really need this, + # but for this we had to insert some unchanged parts of + # UnixCCompiler, and this is not what we want.) + if type(export_symbols) == ListType : + def_file = os.path.join(temp_dir, dll_name + ".def") + f = open(def_file,"w") + f.write("EXPORTS\n") # intro + for sym in export_symbols: + f.write(sym+"\n") + f.close() + + if extra_preargs == None: extra_preargs = [] extra_preargs = extra_preargs + [ #"--verbose", - #"--output-exp",exp_file, - #"--output-lib",lib_file, - "--def",def_file + "--output-exp",exp_file, + "--output-lib",lib_file, ] + if def_file: + extra_preargs.extend(["--def",def_file]) # who wants symbols and a many times larger output file # should explicitely switch the debug mode on diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/extension.py dp/distutils/extension.py --- distutils.orig/distutils/extension.py Mon Jun 26 09:34:35 2000 +++ dp/distutils/extension.py Tue Jul 4 17:00:00 2000 @@ -111,7 +111,7 @@ self.extra_objects = extra_objects or [] self.extra_compile_args = extra_compile_args or [] self.extra_link_args = extra_link_args or [] - self.export_symbols = export_symbols or [] + self.export_symbols = export_symbols self.export_symbol_file = export_symbol_file # class Extension diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/msvccompiler.py dp/distutils/msvccompiler.py --- distutils.orig/distutils/msvccompiler.py Mon Jul 3 12:33:44 2000 +++ dp/distutils/msvccompiler.py Tue Jul 4 18:06:50 2000 @@ -374,11 +374,25 @@ ldflags = self.ldflags_shared export_opts = [] - for sym in (export_symbols or []): - export_opts.append("/EXPORT:" + sym) + if export_symbols != None and type(export_symbols) == StringType: + export_opts.append('/DEF:' + export_symbols) + else: + for sym in (export_symbols or []): + export_opts.append("/EXPORT:" + sym) ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + dll_name, dll_ext = os.path.splitext(os.path.basename(output_filename)) + implib_file = os.path.join ( + os.path.dirname(objects[0]), + self.static_lib_format % (dll_name, self.static_lib_extension)) + ld_args.append ('/IMPLIB:' + implib_file) if extra_preargs: ld_args[:0] = extra_preargs --------------C2F9671324B463815CAE57DD-- From dubois@users.sourceforge.net Thu Jul 6 14:59:17 2000 From: dubois@users.sourceforge.net (Paul F. Dubois) Date: Thu, 6 Jul 2000 06:59:17 -0700 Subject: [Distutils] New setup.py in numpy CVS In-Reply-To: <20000704103029.A1918@beelzebub> Message-ID: I checked in a new version of setup.py for Numerical that corresponds to Distutils-0.9. This is a modification of the setup_numpy.py that Greg has in Distutils. This version REQUIRES the new Distutils. If you install Distutils into 1.6a2, remember (which I didn't at first) to go delete the distutils directory in the Python library directory. If you don't you will get a message while running setup informing you that your Distutils must be updated. This CVS version also separates out LAPACK/BLAS so that using the "lite" version of the libraries supplied with numpy is now optional. A small attempt is made to find the library or the user can edit setup.py to set the locations if that fails. I have not tested this on Windows and I would bet it needs help; we probably won't cut a new Numerical release until this is resolved and Python 2.0 is out so that the needed version of Distutils is standard. Suggestions for improvements would be most welcome. Paul From dubois1@llnl.gov Thu Jul 6 18:01:41 2000 From: dubois1@llnl.gov (Paul F. Dubois) Date: Thu, 6 Jul 2000 10:01:41 -0700 Subject: [Distutils] Re distutils and numpy In-Reply-To: <14681.25131.166235.152210@anthem.concentric.net> References: <20000627205843.A1607@beelzebub> <14681.25131.166235.152210@anthem.concentric.net> Message-ID: <00070610043200.02062@almanac> I have made even more changes to Numeric this morning, separating off FFT= and MA as separate packages and adding the package RNG. I found an error in the previous setup.py; it was installing headers in include/python1.6/Numerical instead of Numeric. This apparently gets fixe= d if=20 you change the name of the package (which I otherwise thought didn't do anything.) From gward@python.net Sat Jul 8 00:13:44 2000 From: gward@python.net (Greg Ward) Date: Fri, 7 Jul 2000 19:13:44 -0400 Subject: [Distutils] Re: Re distutils and numpy In-Reply-To: <00070610043200.02062@almanac>; from dubois1@llnl.gov on Thu, Jul 06, 2000 at 10:01:41AM -0700 References: <20000627205843.A1607@beelzebub> <14681.25131.166235.152210@anthem.concentric.net> <00070610043200.02062@almanac> Message-ID: <20000707191344.A1249@beelzebub> On 06 July 2000, Paul F. Dubois said: > I found an error in the previous setup.py; it was installing headers > in include/python1.6/Numerical instead of Numeric. This apparently > gets fixed if you change the name of the package (which I otherwise > thought didn't do anything.) That's a feature. If Joe Blow releases an extension that requires the headers from NumPy, he should just have to specify, "I require the headers for " and have Distutils take care of the -I paths for him. (It doesn't do this currently, but it could and should!) Don't tell me I'm the only one who's confused about whether it's "NumPy", "Numerical Python", or "Numeric Python", and whether the above blank should be filled in with "Numeric" or "Numerical". BTW, the distribution name is also used, obviously, to create source and built distributions. So naming the header file directory after it is not without precedent. (It does have the subtle side-effect that distribution names should be valid as part of the filename in C #include statements. I have no idea what restrictions that imposes... but it's probably just common sense to stick to [a-zA-Z0-9_-] in distribution names and filenames.) Greg -- Greg Ward - Unix geek gward@python.net http://starship.python.net/~gward/ "Question authority!" "Oh yeah? Says who?" From gward@python.net Sun Jul 9 02:20:19 2000 From: gward@python.net (Greg Ward) Date: Sat, 8 Jul 2000 21:20:19 -0400 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler In-Reply-To: <396465FC.3FD96CAD@gmx.de>; from R.Liebscher@gmx.de on Thu, Jul 06, 2000 at 12:57:00PM +0200 References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> <20000704101613.A1881@beelzebub> <396465FC.3FD96CAD@gmx.de> Message-ID: <20000708212019.A4248@beelzebub> On 06 July 2000, Rene Liebscher said: > It fixes my compiler class to avoid this warning on a GCC > compiled python and it removes all the python specific stuff > (except the above). OK, good. > It inserts this in build_ext (specifying the export symbol > init{module} if no export symbols given and link the library python??) > This means also I had to adapt the msvc compiler class and the Extension > class (It should be possible to specify None as export symbols, > this would mean standard python module with one export symbol, > specifying a list would mean export what is in the list.) Agreed on changed semantics of 'export_symbols'. One reservation: I don't see how putting the "implib" file in the temp dir is taken care of. I agree that it's better to do it in msvccompiler.py using the 'build_temp' parameter to the 'link_*()' methods, but I don't see that being done in your patch. Am I missing something or did you forget that? > I didn't changed bcppcompiler.py because I can't test it. OK. Lyle, are you out there and following this? I can try to hack up bcppcompiler.py to agree with msvccompiler.py and cygwincompiler.py, but I can't test it either. > The def-file will go through the export_symbols parameter. > (as string or if given export_symbols as list) Uh no, that's wrong: that's what 'export_symbol_file' is for. Wait, maybe it's my fault for not supporting 'export_symbol_file' in the CCompiler interface. Oops. I vote we drop 'export_symbol_file' from Extension -- ie. require that the symbols to export be listed in a Python list in your setup script, rather than in an external file -- and see if anyone howls. Detailed comments on the patch... > --- distutils.orig/distutils/command/build_ext.py Fri Jun 30 17:18:01 2000 > +++ dp/distutils/command/build_ext.py Wed Jul 5 11:27:48 2000 > @@ -420,16 +420,40 @@ > objects.extend (ext.extra_objects) > extra_args = ext.extra_link_args or [] > > - # Bunch of fixing-up we have to do for Microsoft's linker. > - if self.compiler.compiler_type == 'msvc': > - self.msvc_prelink_hack(sources, ext, extra_args) > + # For all platforms and compiler doesn't export all symbols > + # by default, we have to specify the module's init function > + # if the use doesn't provide any export information. > + # All other platforms and compilers should ignore such > + # export information. [...] Aiee! Too much code in one place. Please factor this out into two new methods: I'd suggest * get_export_symbols(ext) -> [string] determine the list of symbols to export from the .so/.pyd * get_libraries(ext) -> [string] determine the list of libraries to link with when generating the .so/.pyd > - > - # -- Hooks 'n hacks ------------------------------------------------ > - > - def msvc_prelink_hack (self, sources, ext, extra_args): > - [...] > - implib_file = os.path.join ( > - self.implib_dir, > - self.get_ext_libname (ext.name)) > - extra_args.append ('/IMPLIB:' + implib_file) > - self.mkpath (os.path.dirname (implib_file)) Again, I'm not convinced we can get rid of those yet. Convince me. ;-) > --- distutils.orig/distutils/cygwinccompiler.py Fri Jun 30 17:17:55 2000 > +++ dp/distutils/cygwinccompiler.py Wed Jul 5 12:29:57 2000 > @@ -6,11 +6,34 @@ > cygwin in no-cygwin mode). > """ > > +# problems: > +# > +# * if you use a msvc compiled python version (1.5.2) > +# 1. you have to insert a __GNUC__ section in its config.h > +# 2. you have to generate a import library for its dll > +# - create a def-file for python??.dll > +# - create a import library using > +# dlltool --dllname python15.dll --def python15.def \ > +# --output-lib libpython15.a Ouch! So the Cygwin support is definitely not ready for prime time with 1.5.2. My understanding is that #1 has been fixed in the current Python 2.0 CVS code. What about #2? Should we try to convince Guido to include libpython20.a the 2.0 distribution to save Cygwin/Mingw32 users the bother of generating it? Or maybe "build_ext" can grow a little bit of compiler-sensitivity for Cygwin/Mingw32 and run the above command to generate libpython20.a the first time the user tries to build an extension with Cygwin/Mingw32. Come to think of it, this solves the problem nicely for 1.5.2. And hey, we could even do the same thing for config.h, but that's rather more dangerous -- modifying an existing file rather than generating a new one. Worth considering, though. > +# * cygwin gcc 2.91 works (after patching some include files) > +# * mingw32 gcc 2.95.2 works (it doesn't support gcc -shared) > +# * cygwin gcc 2.95.2 doesn't work now > +# - its dllwrap doesn't work at my machine > +# - target had to be changed to something like i686-cygwin32 > +# - mingw32-mode is specified by -mno-cygwin > +# - using gcc -shared instead dllwrap didn't work because some problems with > +# the import library, maybe it needs some additional parameters AAUUGGHH!!! (What more can I say?) > def check_config_h(): > """Checks if the GCC compiler is mentioned in config.h. If it is not, > - compiling probably doesn't work, so print a warning to stderr. > + compiling probably doesn't work. > """ > - > - # XXX the result of the check should be returned! > + # return values > + # 2: OK, python was compiled with GCC > + # 1: OK, python's config.h mentions __GCC__ > + # 0: uncertain, because we couldn't check it > + # -1: probably not OK, because we didn't found it in config.h > + # You could check check_config_h()>0 => OK Ick. Magic numbers bad. Strings good. Intelligent exception objects (often) better. Think about it. > + # if sys.version contains GCC then python was compiled with > + # GCC, and the config.h file should be OK > + try: > + string.index(sys.version,"GCC") > + return 2 > + except ValueError: > + pass # go to the next test > + I don't like relying on exception-handling like this: I think I'm superstitious about the cost of invoking an unnecessary exception. Please recode using string.find(). > + > UnixCCompiler.__init__ (self, verbose, dry_run, force) > > + if check_config_h()<=0: > + self.warn( > + "Python's config.h doesn't seem to support your compiler.") Should this warning add something like, "expect compilation to die horribly"? > + # name of dll > if not debug: > - ext_name = os.path.basename(output_filename)[:-len(".pyd")] > + dll_name = os.path.basename(output_filename)[:-len(".pyd")] > else: > - ext_name = os.path.basename(output_filename)[:-len("_d.pyd")] > + dll_name = os.path.basename(output_filename)[:-len("_d.pyd")] More Python-specific stuff. Note that all this is already done for you in build_ext.py: see 'get_ext_filename()'. As long as it's being called appropriately, the compiler class doesn't need to figure out what the name of the file it's going to create. > + # where are the object files > + temp_dir=os.path.dirname(objects[0]) What about the 'build_temp' parameter? > + if export_symbols != None and type(export_symbols) == StringType: > + def_file = export_symbol_file Minor quibble: I use "is" for comparing to None and type objects. I know it makes no difference, but that's the Distutils Coding Standard. So there. ;-) This concern will go away if we stop supporting 'export_symbol_file', but 'export_symbols' should always be a list. I hate the "if it's a string, it's a filename, if it's a list, it's a list of symbols" distinction. Makes the code tricky to follow. > + # Make .def file > + # (It would probably better to check if we really need this, > + # but for this we had to insert some unchanged parts of > + # UnixCCompiler, and this is not what we want.) > + if type(export_symbols) == ListType : > + def_file = os.path.join(temp_dir, dll_name + ".def") > + f = open(def_file,"w") > + f.write("EXPORTS\n") # intro > + for sym in export_symbols: > + f.write(sym+"\n") > + f.close() Is it necessary to make a .def file if there are multiple export symbols? Or can they go on the command line? (I think I'd rather put them on the command-line: more explicit, and one less temp file to worry about.) > - self.export_symbols = export_symbols or [] > + self.export_symbols = export_symbols I understand the reason for this change, but we need to make sure there isn't code out there that relies on export_symbols always being a list (ie. never None). > --- distutils.orig/distutils/msvccompiler.py Mon Jul 3 12:33:44 2000 > +++ dp/distutils/msvccompiler.py Tue Jul 4 18:06:50 2000 > @@ -374,11 +374,25 @@ [...] > + if export_symbols != None and type(export_symbols) == StringType: > + export_opts.append('/DEF:' + export_symbols) "is" again, and again I express distaste for this sort of type-sensitivity. > + # The MSVC linker generates .lib and .exp files, which cannot be > + # suppressed by any linker switches. The .lib files may even be > + # needed! Make sure they are generated in the temporary build > + # directory. Since they have different names for debug and release > + # builds, they can go into the same directory. > + dll_name, dll_ext = os.path.splitext(os.path.basename(output_filename)) > + implib_file = os.path.join ( > + os.path.dirname(objects[0]), > + self.static_lib_format % (dll_name, self.static_lib_extension)) > + ld_args.append ('/IMPLIB:' + implib_file) Ahh, is this the code that's supposed to replace the last stanza of 'msvc_prelink_hack()'? If so, why isn't it putting the "implib" file in 'build_temp'? ...oh of course, it goes there anyways, because that's where object files go. This just respects the convention of preserving the source tree structure under build_temp. I take it all back; I think this is right. Can you regenerate your patch to take the above comments into account and resubmit it? Thanks a bunch! Greg -- Greg Ward - just another Python hacker gward@python.net http://starship.python.net/~gward/ All of life is a blur of Republicans and meat! From gward@python.net Sun Jul 9 02:23:33 2000 From: gward@python.net (Greg Ward) Date: Sat, 8 Jul 2000 21:23:33 -0400 Subject: [Distutils] New setup.py in numpy CVS In-Reply-To: ; from dubois1@llnl.gov on Thu, Jul 06, 2000 at 06:59:17AM -0700 References: <20000704103029.A1918@beelzebub> Message-ID: <20000708212333.B4248@beelzebub> On 06 July 2000, Paul F. Dubois said: > This version REQUIRES the new Distutils. If you install Distutils into > 1.6a2, remember (which I didn't at first) to go delete the distutils > directory in the Python library directory. If you don't you will get a > message while running setup informing you that your Distutils must be > updated. The "Official Recommendation" is just to rename that directory away: that way you'll have (eg.) lib/python1.6/distutils-orig and lib/python1.6/site-packages/distutils, and the site-packages version will take precedence without having clobbered the standard library too badly. See the Distutils README.txt. The alternative was support in the Distutils for replacing/upgrading bits of the standard library; Guido was, shall we say, non-receptive to that idea. Oh well. > This CVS version also separates out LAPACK/BLAS so that using the "lite" > version of the libraries supplied with numpy is now optional. A small > attempt is made to find the library or the user can edit setup.py to set the > locations if that fails. Oh good, does that mean it'll take less than 20 minutes to compile NumPy on my pokey old 100 MHz Pentium? ;-) Greg -- Greg Ward - Unix bigot gward@python.net http://starship.python.net/~gward/ Software patents SUCK -- boycott amazon.com! From jonathan.gilligan@vanderbilt.edu Tue Jul 11 16:27:34 2000 From: jonathan.gilligan@vanderbilt.edu (Jonathan M. Gilligan) Date: Tue, 11 Jul 2000 10:27:34 -0500 Subject: [Distutils] Current versions not on CVS (distutils and NumPy) Message-ID: <4.3.2.7.2.20000711101829.055a71a0@g.mail.vanderbilt.edu> I tried updating my distutils and numpy from their CVS sites last night, to try building and found the following problems. Distutils from :pserver:distutilscvs@cvs.python.org:/projects/cvsroot has a most recent tag of Distutils-0_8_2. Where can I get CVS access to Distutils 0.9, or is this a tar-only distribution. On a related note, the cvs of Numerical Python from SourceForge has a most recent tag of V15_2. If I get the most recent (untagged) version, of NumPy, there is not lapack_lite_library directory, so "setup.py install" fails. Does this mean that Numerical Python 15.3 has not yet been checked into the CVS repository? It's a bit confusing when the CVS repositories are not up to date with the most recent releases. Could someone clarify for me, please. Jonathan Gilligan From vanandel@ucar.edu Tue Jul 11 17:38:23 2000 From: vanandel@ucar.edu (Joe Van Andel) Date: Tue, 11 Jul 2000 10:38:23 -0600 Subject: [Distutils] BUG: distutils 0.9 bdist_rpm - missing subdirectory Message-ID: <396B4D7F.12A20384@atd.ucar.edu> Using distutils 0.9 (downloaded 7/10/00 from python.org), on Redhat 6.1, I'm trying to build an RPM. distutils fails to write /nexrad/6/code/rdss/spol/perp/build/bdist.linux2/rpm/RPMS/i386/Perp-0.5-1.i386.rpm because the i386 subdirectory of RPMS /nexrad/6/code/rdss/spol/perp/build/bdist.linux2/rpm/RPMS/i386 does not exist. If I manually create 'RPMS/i386', the binary RPM gets built fine. Aside from this glitch - this is great progress, since I've never learned how to build RPMS before, and now distutils has done it for me. Very nice! (Thanks, Harry Henry Gebel!) -- Joe VanAndel National Center for Atmospheric Research http://www.atd.ucar.edu/~vanandel/ Internet: vanandel@ucar.edu From hgebel@inet.net Wed Jul 12 00:22:48 2000 From: hgebel@inet.net (Harry Henry Gebel) Date: Tue, 11 Jul 2000 19:22:48 -0400 Subject: [Distutils] BUG: distutils 0.9 bdist_rpm - missing subdirectory In-Reply-To: <396B4D7F.12A20384@atd.ucar.edu>; from vanandel@atd.ucar.edu on Tue, Jul 11, 2000 at 10:38:23AM -0600 References: <396B4D7F.12A20384@atd.ucar.edu> Message-ID: <20000711192247.A770@inet.net> On Tue, Jul 11, 2000 at 10:38:23AM -0600, Joe Van Andel wrote: > If I manually create 'RPMS/i386', the binary RPM gets built fine. I believe that either (RPM) 3.03 or 3.04 started creating directories if they were not already there. There are a number of changes I want to make to bdist_rpm to handle this and some other situations, but I am working two jobs right now so I do not know when I will be able to get to it. We are interviewing a marketing guy this week, if he's as good as he says he is maybe soon I will be able to go back to just the business and will have some more time. -- Harry Henry Gebel, Senior Developer, Landon House SBS ICQ# 76308382 West Dover Hundred, Delaware From gward@python.net Wed Jul 12 02:01:43 2000 From: gward@python.net (Greg Ward) Date: Tue, 11 Jul 2000 21:01:43 -0400 Subject: [Distutils] Off the net for a week or so Message-ID: <20000711210143.A1101@beelzebub> Hi all -- I'll be off the 'net from this Thursday (13 July) until the following Sunday (23 July). So don't be expecting a lot of progress in bug-fixing, feature-adding, documentation-writing, or testing of the Distutils. Looks like 0.9 has been pretty stable though -- only one bug report so far! ;-) Happy hacking -- Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ And now for something completely different. From taylor@rhino.llnl.gov Wed Jul 12 05:51:40 2000 From: taylor@rhino.llnl.gov (Lee Taylor) Date: Tue, 11 Jul 2000 21:51:40 -0700 (PDT) Subject: [Distutils] Absolute path library names Message-ID: I'm using Distutils-0.9 on Linux with a setup file similar to setup (... Extension('name', libraries=['pgs', 'ppc', '/usr/X11R6/lib/X11') ) And I'm getting the traceback File "distutils/core.py", line 112, in setup File "distutils/dist.py", line 776, in run_commands File "distutils/dist.py", line 797, in run_command File "distutils/command/build.py", line 117, in run File "/home/taylor/local-linux/lib/python1.5/cmd.py", line 310, in run_command File "distutils/dist.py", line 797, in run_command File "/home/taylor/python/Distutils-0.9/distutils/command/build_ext.py", line 224, in run self.build_extensions () File "/home/taylor/python/Distutils-0.9/distutils/command/build_ext.py", line 435, in build_extensions build_temp=self.build_temp) File "/home/taylor/python/Distutils-0.9/distutils/unixccompiler.py", line 239, in link_shared_object libraries) File "/home/taylor/python/Distutils-0.9/distutils/ccompiler.py", line 959, in gen_lib_options lib_file = compiler.find_library_file ([lib_dir], lib_name) File "/home/taylor/python/Distutils-0.9/distutils/unixccompiler.py", line 324, in find_library_file shared = os.path.join (dir, self.shared_library_filename (lib)) AttributeError: shared_library_filename grepping thru the source I only find references to shared_library_filename in unixccompiler.py in the method find_library_file which is only called when a path component for a library is supplied. Lee Taylor From Brad Chapman Wed Jul 12 13:37:36 2000 From: Brad Chapman (Brad Chapman) Date: Wed, 12 Jul 2000 08:37:36 -0400 Subject: [Distutils] Absolute path library names Message-ID: <200007121237.IAA112342@archa11.cc.uga.edu> Lee Taylor wrote: > I'm using Distutils-0.9 on Linux with a setup file similar to > > setup (... > Extension('name', > libraries=['pgs', 'ppc', '/usr/X11R6/lib/X11') > ) > > And I'm getting the traceback [...snip...] I'm not exactly sure if I know what you are trying to do, but hopefully the following might help... The 'libraries' key is only for listing libraries that will be linked in (ie. -lpgs -lppc, from your example) and the 'library_dirs' key is for listing library directories that will be looked in for the libraries to link (ie. -L/usr/X11R6/lib/X11). So, I believe your setup.py should look like: setup (.... ext_modules = [('name', {'sources' : [ your c sources ], 'libraries': ['pgs', 'ppc'], 'library_dirs' : ['/usr/X11R6/lib/X11'] }) ] ) Hope this helps. Brad From calvin@cs.uni-sb.de Wed Jul 12 14:19:49 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Wed, 12 Jul 2000 15:19:49 +0200 (CEST) Subject: [Distutils] Absolute path library names In-Reply-To: <200007121237.IAA112342@archa11.cc.uga.edu> Message-ID: The error ist that shared_library_filename is nowhere defined. As I can guess from the source this function should look like: def shared_library_filename(lib): return 'lib'+lib+'.so' For a workaround use this: ... 'libraries': ['pgs','ppc','X11'], 'library_dirs': ['/usr/X11R6/lib'] .. because you want -L/usr/X11R6/lib -lX11. Bastian Kleineidam From R.Liebscher@gmx.de Wed Jul 12 14:24:49 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Wed, 12 Jul 2000 15:24:49 +0200 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> <20000704101613.A1881@beelzebub> <396465FC.3FD96CAD@gmx.de> <20000708212019.A4248@beelzebub> Message-ID: <396C71A1.198D8C2C@gmx.de> This is a multi-part message in MIME format. --------------61EACC115ECA50FFAE966E69 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Greg Ward wrote: > > On 06 July 2000, Rene Liebscher said: > > I didn't changed bcppcompiler.py because I can't test it. > > OK. Lyle, are you out there and following this? I can try to hack up > bcppcompiler.py to agree with msvccompiler.py and cygwincompiler.py, but > I can't test it either. But I can test it now. I found the problem Lyle had in it. (He forgot to close the file in which he wrote the export symbols, and the compiler didn't want use an open file.) I also added some comments and a extension concerning libraries. It now looks first if there is a library called bcpp_{libname}.lib before it tries {libname}.lib. So you can have both, the default msvc libraries and special libraries for Borland C++. (They are not compatible.) This is useful if you have installed your Python in a network and user use different compilers. (Or for someone like me, who has now six different compilers on one machine to test distutils compiler classes.) > I vote we drop 'export_symbol_file' from > Extension -- ie. require that the symbols to export be listed in a > Python list in your setup script, rather than in an external file -- and > see if anyone howls. It is your decision, export_symbol_file is now no longer used anywhere, but it still exists as parameter to Extension. > Detailed comments on the patch... > > --- distutils.orig/distutils/cygwinccompiler.py Fri Jun 30 17:17:55 2000 > > +++ dp/distutils/cygwinccompiler.py Wed Jul 5 12:29:57 2000 > > @@ -6,11 +6,34 @@ > > cygwin in no-cygwin mode). > > """ > > > > +# problems: > > +# > > +# * if you use a msvc compiled python version (1.5.2) > > +# 1. you have to insert a __GNUC__ section in its config.h > > +# 2. you have to generate a import library for its dll > > +# - create a def-file for python??.dll > > +# - create a import library using > > +# dlltool --dllname python15.dll --def python15.def \ > > +# --output-lib libpython15.a > > Ouch! So the Cygwin support is definitely not ready for prime time with > 1.5.2. My understanding is that #1 has been fixed in the current Python > 2.0 CVS code. Not yet, but there is a patch in SourceForges open patches list. > What about #2? Should we try to convince Guido to > include libpython20.a the 2.0 distribution to save Cygwin/Mingw32 users > the bother of generating it? > > Or maybe "build_ext" can grow a little bit of compiler-sensitivity for > Cygwin/Mingw32 and run the above command to generate libpython20.a the > first time the user tries to build an extension with Cygwin/Mingw32. > Come to think of it, this solves the problem nicely for 1.5.2. And hey, > we could even do the same thing for config.h, but that's rather more > dangerous -- modifying an existing file rather than generating a new > one. Worth considering, though. I think he should add a def-file for python20.dll in the distribution. Every serious compiler can build from this an import library. (Many can also use the dll to build it, but most fail because Python exports not only functions, it also exports data.) (Borland can also translate MSVC import libraries into its own format.) We could also add a tools directory or something similar. In this directory we could put some python programs which generate an import library for a given def-file, library or dll. They could called ????_def2lib.py, ????_lib2lib.py and ????_dll2lib.py, where ???? stands for the compiler (bcpp,...). This would help users to use other dlls or libraries they want to use for extension. This would also the place to put a replacement for the python 1.5.2 config.h file. I think the python 2.0 config.h should work fine, after changing references from 2.0 to 1.5 (#pragma comment(lib,"python20.lib") > > > +# * cygwin gcc 2.91 works (after patching some include files) > > +# * mingw32 gcc 2.95.2 works (it doesn't support gcc -shared) > > +# * cygwin gcc 2.95.2 doesn't work now > > +# - its dllwrap doesn't work at my machine > > +# - target had to be changed to something like i686-cygwin32 > > +# - mingw32-mode is specified by -mno-cygwin > > +# - using gcc -shared instead dllwrap didn't work because some problems with > > +# the import library, maybe it needs some additional parameters > > AAUUGGHH!!! (What more can I say?) gcc 2.91 is no problem for us. People should use a newer compiler. But the differences betweeen these two gcc 2.9.5 are a problem, mingw32 doesn't support gcc -shared yet, and cygwin's dllwrap seems to have a bug (It fails to reallocate 1.7 GByte of Memory.) Cygwin's gcc -shared wants other symbols than dlltool creates in the import library. Is there someone out there who has already successful created a extension module with the new cygwin version? If yes, please send me the commandlines you used for this. > > - # XXX the result of the check should be returned! > > + # return values > > + # 2: OK, python was compiled with GCC > > + # 1: OK, python's config.h mentions __GCC__ > > + # 0: uncertain, because we couldn't check it > > + # -1: probably not OK, because we didn't found it in config.h > > + # You could check check_config_h()>0 => OK > > Ick. Magic numbers bad. Strings good. Intelligent exception objects > (often) better. Think about it. Not magic numbers, more a kind of level, higher number mean a greater probability that compiling will successful. > Is it necessary to make a .def file if there are multiple export > symbols? Or can they go on the command line? (I think I'd rather put > them on the command-line: more explicit, and one less temp file to worry > about.) > Normally gcc exports all symbols if you don't specify any exports related options. But you can't rely on it, I also found some extensions build without exports. This why we have to specify them. There is an exclude-symbols option, but I never found a export-symbols or include-symbols or something similar. It seems we have to build this def-file. > > - self.export_symbols = export_symbols or [] > > + self.export_symbols = export_symbols > > I understand the reason for this change, but we need to make sure there > isn't code out there that relies on export_symbols always being a list > (ie. never None). It was never used by build_ext and in the compiler interface it has a default value of None. So it is unlikely someone will even take notice of it. And now something new. Is anyone out there using the LCC-Win32 compiler? (http://www.cs.virginia.edu/~lcc-win32/) It is a small C compiler, but it comes with a IDE (gcc and free BCC55 don't) and it is able to build python extensions. I have a compiler class for it, which is already able to build extensions. So if anyone is interested or maybe want it to complete, I will post it to the mailing list. kind regards Rene Liebscher --------------61EACC115ECA50FFAE966E69 Content-Type: text/plain; charset=iso-8859-1; name="msvc_hack2.patch" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="msvc_hack2.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/bcppcompiler.py distutils.patched/distutils/bcppcompiler.py --- distutils.orig/distutils/bcppcompiler.py Wed Jun 28 03:20:35 2000 +++ distutils.patched/distutils/bcppcompiler.py Wed Jul 12 14:33:34 2000 @@ -11,17 +11,6 @@ # someone should sit down and factor out the common code as # WindowsCCompiler! --GPW -# XXX Lyle reports that this doesn't quite work yet: -# """...but this is what I've got so far. The compile step works fine but -# when it runs the link step I get an "out of memory" failure. Since -# spawn() echoes the command it's trying to spawn, I can type the link line -# verbatim at the DOS prompt and it links the Windows DLL correctly -- so -# the syntax is correct. There's just some weird interaction going on when -# it tries to "spawn" the link process from within the setup.py script. I'm -# not really sure how to debug this one right off-hand; obviously there's -# nothing wrong with the "spawn()" function since it's working properly for -# the compile stage.""" - __revision__ = "$Id: bcppcompiler.py,v 1.1 2000/06/28 01:20:35 gward Exp $" @@ -123,6 +112,9 @@ elif ext in self._cpp_extensions: input_opt = "-P" + src = os.path.normpath(src) + obj = os.path.normpath(obj) + output_opt = "-o" + obj self.mkpath (os.path.dirname (obj)) @@ -230,24 +222,55 @@ else: ldflags = self.ldflags_shared + # Borland C++ has problems with '/' in paths + objects = map(os.path.normpath,objects) + startup_obj = 'c0d32' - libraries.append ('mypylib') + # either exchange python15.lib in the python libs directory against + # a Borland-like one, or create one with name bcpp_python15.lib + # there and remove the pragmas from config.h + #libraries.append ('mypylib') libraries.append ('import32') libraries.append ('cw32mt') # Create a temporary exports file for use by the linker head, tail = os.path.split (output_filename) modname, ext = os.path.splitext (tail) - def_file = os.path.join (build_temp, '%s.def' % modname) + temp_dir = os.path.dirname(objects[0]) # preserve tree structure + def_file = os.path.join (temp_dir, '%s.def' % modname) f = open (def_file, 'w') f.write ('EXPORTS\n') for sym in (export_symbols or []): f.write (' %s=_%s\n' % (sym, sym)) - - ld_args = ldflags + [startup_obj] + objects + \ - [',%s,,' % output_filename] + \ - libraries + [',' + def_file] + f.close() + + # start building command line + # flags and options + ld_args = list(ldflags) # don't use a reference, use a separate copy + for l in library_dirs: + ld_args.append("/L%s" % os.path.normpath(l)) + # objects list + ld_args.extend([startup_obj]) + ld_args.extend(objects) + # name of dll file + ld_args.extend([',',output_filename]) + # no map file + ld_args.extend([',']) + # start libraries + ld_args.extend([',']) + for lib in libraries: + # see if we find it and if there is a bcpp specific lib (bcpp_xxx.lib) + l = self.find_library_file(library_dirs,lib,debug) + if l == None: + ld_args.append(lib) + # probably an bcpp internal library + # self.warn('library %s not found.' % lib) + else: + # full name which prefers bcpp_xxx.lib over xxx.lib + ld_args.append(l) + # def file for export symbols + ld_args.extend([',',def_file]) if extra_preargs: ld_args[:0] = extra_preargs @@ -325,15 +348,28 @@ def runtime_library_dir_option (self, dir): raise DistutilsPlatformError, \ - "don't know how to set runtime library search path for MSVC++" + "don't know how to set runtime library search path for Borland C++" def library_option (self, lib): return self.library_filename (lib) - def find_library_file (self, dirs, lib): - + def find_library_file (self, dirs, lib, debug=0): + # find library file + # bcpp_xxx.lib is better than xxx.lib + # and xxx_d.lib is better than xxx.lib if debug is set for dir in dirs: + if debug: + libfile = os.path.join (dir, self.library_filename ("bcpp_" + lib + "_d")) + if os.path.exists (libfile): + return libfile + libfile = os.path.join (dir, self.library_filename ("bcpp_" + lib)) + if os.path.exists (libfile): + return libfile + if debug: + libfile = os.path.join (dir, self.library_filename (lib + '_d')) + if os.path.exists (libfile): + return libfile libfile = os.path.join (dir, self.library_filename (lib)) if os.path.exists (libfile): return libfile diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build_ext.py distutils.patched/distutils/command/build_ext.py --- distutils.orig/distutils/command/build_ext.py Fri Jul 7 22:41:21 2000 +++ distutils.patched/distutils/command/build_ext.py Wed Jul 12 13:57:48 2000 @@ -283,6 +283,9 @@ # Medium-easy stuff: same syntax/semantics, different names. ext.runtime_library_dirs = build_info.get('rpath') ext.export_symbol_file = build_info.get('def_file') + if ext.export_symbol_file is not None: + self.warn("export_symbol_file is no longer supported, " + "comments and questions to ") # Non-trivial stuff: 'macros' split into 'define_macros' # and 'undef_macros'. @@ -420,16 +423,14 @@ objects.extend (ext.extra_objects) extra_args = ext.extra_link_args or [] - # Bunch of fixing-up we have to do for Microsoft's linker. - if self.compiler.compiler_type == 'msvc': - self.msvc_prelink_hack(sources, ext, extra_args) self.compiler.link_shared_object ( objects, ext_filename, - libraries=ext.libraries, + libraries=self.get_libraries(ext), library_dirs=ext.library_dirs, runtime_library_dirs=ext.runtime_library_dirs, extra_postargs=extra_args, + export_symbols=self.get_export_symbols(ext), debug=self.debug, build_temp=self.build_temp) @@ -511,44 +512,6 @@ # find_swig () - - # -- Hooks 'n hacks ------------------------------------------------ - - def msvc_prelink_hack (self, sources, ext, extra_args): - - # XXX this is a kludge! Knowledge of specific compilers or - # platforms really doesn't belong here; in an ideal world, the - # CCompiler interface would provide access to everything in a - # compiler/linker system needs to build Python extensions, and - # we would just do everything nicely and cleanly through that - # interface. However, this is a not an ideal world and the - # CCompiler interface doesn't handle absolutely everything. - # Thus, kludges like this slip in occasionally. (This is no - # excuse for committing more platform- and compiler-specific - # kludges; they are to be avoided if possible!) - - def_file = ext.export_symbol_file - - if def_file is not None: - extra_args.append ('/DEF:' + def_file) - else: - modname = string.split (ext.name, '.')[-1] - extra_args.append('/export:init%s' % modname) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - implib_file = os.path.join ( - self.implib_dir, - self.get_ext_libname (ext.name)) - extra_args.append ('/IMPLIB:' + implib_file) - self.mkpath (os.path.dirname (implib_file)) - - # msvc_prelink_hack () - - # -- Name generators ----------------------------------------------- # (extension names, filenames, whatever) @@ -578,5 +541,33 @@ if os.name == 'nt' and self.debug: return apply (os.path.join, ext_path) + '_d.lib' return apply (os.path.join, ext_path) + '.lib' + + + def get_export_symbols (self, ext): + # For all platforms and compiler doesn't export all symbols + # by default, we have to specify the module's init function + # if the user doesn't provide any export information. + # All other platforms and compilers should ignore such + # export information. + if ext.export_symbols is None: + # if no exports are specified we can't build a working + # python module. + # so let us export the module's init function + return ["init" + string.split(ext.name,'.')[-1]] + else: + return ext.export_symbols + + def get_libraries (self, ext): + # The python library is always needed on Windows. + # We need the python version without the dot, eg. '15' + # MSVC doesn't really need this, because the pragma in config.h + if sys.platform == "win32": + pythonlib = ("python%d%d" % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] + else: + return ext.libraries # class build_ext diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/cygwinccompiler.py distutils.patched/distutils/cygwinccompiler.py --- distutils.orig/distutils/cygwinccompiler.py Fri Jun 30 00:57:55 2000 +++ distutils.patched/distutils/cygwinccompiler.py Wed Jul 12 14:17:57 2000 @@ -10,6 +10,29 @@ __revision__ = "$Id: cygwinccompiler.py,v 1.2 2000/06/29 22:57:55 gward Exp $" +# problems: +# +# * if you use a msvc compiled python version (1.5.2) +# 1. you have to insert a __GNUC__ section in its config.h +# 2. you have to generate a import library for its dll +# - create a def-file for python??.dll +# - create a import library using +# dlltool --dllname python15.dll --def python15.def \ +# --output-lib libpython15.a +# +# see also http://starship.python.net/crew/kernr/mingw32 +# +# * cygwin gcc 2.91 works (after patching some include files) +# * mingw32 gcc 2.95.2 works (it doesn't support gcc -shared) +# * cygwin gcc 2.95.2 doesn't work now +# - its dllwrap doesn't work at my machine +# - using gcc -shared instead dllwrap didn't work because some problems with +# the import library, maybe it needs some additional parameters. +# It tries to import _imp__XXX but dlltool creates an import library +# with __imp__XXX symbols. + + + import os,sys,string from distutils import sysconfig from distutils.unixccompiler import UnixCCompiler @@ -20,34 +43,41 @@ def check_config_h(): """Checks if the GCC compiler is mentioned in config.h. If it is not, - compiling probably doesn't work, so print a warning to stderr. + compiling probably doesn't work. """ - - # XXX the result of the check should be returned! + # return values + # 2: OK, python was compiled with GCC + # 1: OK, python's config.h mentions __GCC__ + # 0: uncertain, because we couldn't check it + # -1: probably not OK, because we didn't found it in config.h + # You could check check_config_h()>0 => OK from distutils import sysconfig import string,sys + # if sys.version contains GCC then python was compiled with + # GCC, and the config.h file should be OK + if -1 == string.find(sys.version,"GCC"): + pass # go to the next test + else: + return 2 + try: # It would probably better to read single lines to search. # But we do this only once, and it is fast enough f=open(sysconfig.get_config_h_filename()) s=f.read() f.close() - try: - # is somewhere a #ifdef __GNUC__ or something similar - string.index(s,"__GNUC__") - except ValueError: - sys.stderr.write ("warning: "+ - "Python's config.h doesn't seem to support your compiler.\n") + + # is somewhere a #ifdef __GNUC__ or something similar + if -1 == string.find(s,"__GNUC__"): + return -1 + else: + return 1 except IOError: # if we can't read this file, we cannot say it is wrong # the compiler will complain later about this file as missing pass - - -# This is called when the module is imported, so we make this check only once -# XXX why not make it only when the compiler is needed? -check_config_h() + return 0 class CygwinCCompiler (UnixCCompiler): @@ -59,14 +89,20 @@ dry_run=0, force=0): + UnixCCompiler.__init__ (self, verbose, dry_run, force) + if check_config_h()<=0: + self.warn( + "Python's config.h doesn't seem to support your compiler. " + "Compiling may fail because of undefined preprocessor macros.") + # Hard-code GCC because that's what this is all about. # XXX optimization, warnings etc. should be customizable. self.set_executables(compiler='gcc -O -Wall', - compiler_so='gcc -O -Wall', + compiler_so='gcc -O -Wall -mcygwin', linker_exe='gcc', - linker_so='dllwrap --target=i386-cygwin32') + linker_so='dllwrap -mcygwin') # cygwin and mingw32 need different sets of libraries self.dll_libraries=[ @@ -96,53 +132,49 @@ if libraries == None: libraries = [] - # Additional libraries: the python library is always needed on - # Windows we need the python version without the dot, eg. '15' - - pythonlib = ("python%d%d" % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - libraries.append(pythonlib) - libraries.extend(self.dll_libraries) - - # name of extension + # Additional libraries + # libraries.extend(...) would affect the list we got as parameter + # and this can come from anywhere + libraries = libraries + self.dll_libraries + + # we want to put some files in the same directory as the + # object files are, build_temp doesn´t help much - # XXX WRONG WRONG WRONG - # this is NOT the place to make guesses about Python namespaces; - # that MUST be done in build_ext.py + # name of dll to give the helper files (def, lib, exp) the same name + dll_name,dll_extension = os.path.splitext(os.path.basename(output_filename)) - if not debug: - ext_name = os.path.basename(output_filename)[:-len(".pyd")] - else: - ext_name = os.path.basename(output_filename)[:-len("_d.pyd")] + # where are the object files + temp_dir = os.path.dirname(objects[0]) - def_file = os.path.join(build_temp, ext_name + ".def") - #exp_file = os.path.join(build_temp, ext_name + ".exp") - #lib_file = os.path.join(build_temp, 'lib' + ext_name + ".a") + # generate the filenames for these files + def_file = None # this will be done later, if necessary + exp_file = os.path.join(temp_dir, dll_name + ".exp") + lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a") - # Make .def file - # (It would probably better to check if we really need this, - # but for this we had to insert some unchanged parts of - # UnixCCompiler, and this is not what we want.) - f = open(def_file,"w") - f.write("EXPORTS\n") # intro - if export_symbols == None: - # export a function "init" + ext_name - f.write("init" + ext_name + "\n") - else: - # if there are more symbols to export write them into f + # check what we got in export_symbols + if export_symbols is not None: + # Make .def file + # (It would probably better to check if we really need this, + # but for this we had to insert some unchanged parts of + # UnixCCompiler, and this is not what we want.) + def_file = os.path.join(temp_dir, dll_name + ".def") + f = open(def_file,"w") + f.write("EXPORTS\n") # intro for sym in export_symbols: f.write(sym+"\n") - f.close() - - if extra_preargs == None: + f.close() + + + if extra_preargs is None: extra_preargs = [] extra_preargs = extra_preargs + [ #"--verbose", #"--output-exp",exp_file, #"--output-lib",lib_file, - "--def",def_file ] + if def_file: + extra_preargs.extend(["--def",def_file]) # who wants symbols and a many times larger output file # should explicitely switch the debug mode on @@ -150,7 +182,7 @@ # (On my machine unstripped_file = stripped_file + 254KB # 10KB < stripped_file < ??100KB ) if not debug: - extra_preargs = extra_preargs + ["-s"] + extra_preargs.append("-s") UnixCCompiler.link_shared_object(self, objects, @@ -185,15 +217,13 @@ self.set_executables(compiler='gcc -mno-cygwin -O -Wall', compiler_so='gcc -mno-cygwin -O -Wall', linker_exe='gcc -mno-cygwin', - linker_so='dllwrap' - + ' --target=i386-mingw32' - + ' --entry _DllMain@12') - # mingw32 doesn't really need 'target' and cygwin too (it seems, - # it is enough to specify a different entry point) + linker_so='dllwrap -mno-cygwin -mthreads') + #+ ' --entry _DllMain@12') + # mingw32-mode on cygwin needs to specify a different entry point # no additional libraries need # (only msvcrt, which is already added by CygwinCCompiler) - # __init__ () - + # __init__ () + # class Mingw32CCompiler diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/extension.py distutils.patched/distutils/extension.py --- distutils.orig/distutils/extension.py Sat Jun 24 02:18:24 2000 +++ distutils.patched/distutils/extension.py Wed Jul 12 14:01:03 2000 @@ -111,7 +111,7 @@ self.extra_objects = extra_objects or [] self.extra_compile_args = extra_compile_args or [] self.extra_link_args = extra_link_args or [] - self.export_symbols = export_symbols or [] + self.export_symbols = export_symbols self.export_symbol_file = export_symbol_file # class Extension diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/msvccompiler.py distutils.patched/distutils/msvccompiler.py --- distutils.orig/distutils/msvccompiler.py Fri Jun 30 21:37:59 2000 +++ distutils.patched/distutils/msvccompiler.py Wed Jul 12 14:01:03 2000 @@ -380,6 +380,17 @@ ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + dll_name, dll_ext = os.path.splitext(os.path.basename(output_filename)) + implib_file = os.path.join ( + os.path.dirname(objects[0]), + self.static_lib_format % (dll_name, self.static_lib_extension)) + ld_args.append ('/IMPLIB:' + implib_file) + if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: --------------61EACC115ECA50FFAE966E69-- From R.Liebscher@gmx.de Wed Jul 12 14:37:34 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Wed, 12 Jul 2000 15:37:34 +0200 Subject: [Distutils] Absolute path library names References: Message-ID: <396C749E.7FF25EE0@gmx.de> Bastian Kleineidam wrote: > > The error ist that shared_library_filename is nowhere defined. As I > can guess from the source this function should look like: > > def shared_library_filename(lib): > return 'lib'+lib+'.so' It is not a missing function, it is only a wrong piece of code. It should look like this: --------------------------------------------------------------------------------- diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/unixccompiler.py distutils.patched/distutils/unixccompiler.py --- distutils.orig/distutils/unixccompiler.py Wed Jun 28 03:29:09 2000 +++ distutils.patched/distutils/unixccompiler.py Wed Jul 12 15:29:21 2000 @@ -320,7 +320,7 @@ def find_library_file (self, dirs, lib): for dir in dirs: - shared = os.path.join (dir, self.shared_library_filename (lib)) + shared = os.path.join (dir, self.library_filename (lib,'shared')) static = os.path.join (dir, self.library_filename (lib)) # We're second-guessing the linker here, with not much hard ---------------------------------------------------------------------------------- library_filename comes from ccompiler.py, its second parameter is by default 'static'. > For a workaround use this: > ... > 'libraries': ['pgs','ppc','X11'], > 'library_dirs': ['/usr/X11R6/lib'] > .. > because you want -L/usr/X11R6/lib -lX11. Rene Liebscher From taylor@rhino.llnl.gov Wed Jul 12 20:20:04 2000 From: taylor@rhino.llnl.gov (Lee Taylor) Date: Wed, 12 Jul 2000 12:20:04 -0700 (PDT) Subject: [Distutils] Absolute path library names In-Reply-To: <396C749E.7FF25EE0@gmx.de> Message-ID: This patch did exactly what I wanted. Thanks. Lee Taylor On Wed, 12 Jul 2000, Rene Liebscher wrote: > It is not a missing function, it is only a wrong piece of code. > It should look like this: > --------------------------------------------------------------------------------- > diff -BurN --minimal --exclude=*.pyc > distutils.orig/distutils/unixccompiler.py > distutils.patched/distutils/unixccompiler.py > --- distutils.orig/distutils/unixccompiler.py Wed Jun 28 03:29:09 2000 > +++ distutils.patched/distutils/unixccompiler.py Wed Jul 12 > 15:29:21 2000 > @@ -320,7 +320,7 @@ > def find_library_file (self, dirs, lib): > > for dir in dirs: > - shared = os.path.join (dir, self.shared_library_filename > (lib)) > + shared = os.path.join (dir, self.library_filename > (lib,'shared')) > static = os.path.join (dir, self.library_filename (lib)) > > # We're second-guessing the linker here, with not much hard > ---------------------------------------------------------------------------------- > library_filename comes from ccompiler.py, its second parameter is by > default 'static'. From fred@scd.ucar.edu Wed Jul 12 23:39:07 2000 From: fred@scd.ucar.edu (fred) Date: Wed, 12 Jul 2000 16:39:07 -0600 (MDT) Subject: [Distutils] installation Message-ID: <200007122239.QAA06573@niwot.scd.ucar.edu> I am trying to install numpy and am first installing distutils. I am running SunOS 5.7 on a sparc Ultra-4. I installed Python after downloading it from python.org. When I try to install distutils, it reports that it cannot find the /lib/python1.5/config and indeed there is no such directory in the python distribution that I can see. Fred Clare fred@ucar.edu From calvin@cs.uni-sb.de Fri Jul 14 13:03:18 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Fri, 14 Jul 2000 14:03:18 +0200 (CEST) Subject: [Distutils] Catched a typo In-Reply-To: <200007122239.QAA06573@niwot.scd.ucar.edu> Message-ID: Patch follows. Bastian Kleineidam diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build_ext.py distutils/distutils/command/build_ext.py --- distutils.orig/distutils/command/build_ext.py Thu Jul 13 01:15:27 2000 +++ distutils/distutils/command/build_ext.py Fri Jul 14 14:02:38 2000 @@ -309,7 +309,7 @@ def get_source_files (self): - self.check_extension_list() + self.check_extensions_list(self.extensions) filenames = [] # Wouldn't it be neat if we knew the names of header files too... From akuchlin@mems-exchange.org Fri Jul 14 14:36:02 2000 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Fri, 14 Jul 2000 09:36:02 -0400 Subject: [Distutils] Catched a typo In-Reply-To: ; from calvin@cs.uni-sb.de on Fri, Jul 14, 2000 at 02:03:18PM +0200 References: <200007122239.QAA06573@niwot.scd.ucar.edu> Message-ID: <20000714093602.A28819@kronos.cnri.reston.va.us> On Fri, Jul 14, 2000 at 02:03:18PM +0200, Bastian Kleineidam wrote: >Patch follows. Applied; Greg's away on vacation, but your fix looks correct to me. --amk From calvin@cs.uni-sb.de Fri Jul 14 14:56:41 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Fri, 14 Jul 2000 15:56:41 +0200 (CEST) Subject: [Distutils] sdist.py::findall chokes on broken links In-Reply-To: <20000714093602.A28819@kronos.cnri.reston.va.us> Message-ID: Hello, the findall function in sdist.py gives an error when a broken link is found. The responsible function call is os.stat(). I replaced the stat() calls with os.path.{isfile,islink,isdir}. This is somewhat more robust. The new findall is now a member function of the sdist class so I can use self.announce to warn about broken links. Here is the patch: diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/sdist.py distutils/distutils/command/sdist.py --- distutils.orig/distutils/command/sdist.py Thu Jul 13 01:15:28 2000 +++ distutils/distutils/command/sdist.py Fri Jul 14 15:47:05 2000 @@ -324,7 +324,7 @@ containing a Unix-style glob pattern). If 'pattern' is None, find all files under 'dir'. Return the list of found filenames. """ - allfiles = findall (dir) + allfiles = self.findall (dir) if pattern is None: return allfiles @@ -376,7 +376,7 @@ rstrip_ws=1, collapse_ws=1) - all_files = findall () + all_files = self.findall () while 1: @@ -695,43 +695,42 @@ """ return self.archive_files -# class sdist - + def findall(self, dir = os.curdir): + """Find all files under 'dir' and return the list of full filenames + (relative to 'dir'). + """ + list = [] + stack = [dir] + pop = stack.pop + push = stack.append -# ---------------------------------------------------------------------- -# Utility functions + while stack: + dir = pop() + names = os.listdir (dir) -def findall (dir = os.curdir): - """Find all files under 'dir' and return the list of full filenames - (relative to 'dir'). - """ - from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK + for name in names: + if dir != os.curdir: # avoid the dreaded "./" syndrome + fullname = os.path.join (dir, name) + else: + fullname = name - list = [] - stack = [dir] - pop = stack.pop - push = stack.append + # note: isfile follows symlinks + if os.path.isfile(fullname): + list.append (fullname) + elif os.path.islink(fullname): + self.announce("warning: link %s is broken" % fullname) + elif os.path.isdir(fullname): + push (fullname) - while stack: - dir = pop() - names = os.listdir (dir) + return list - for name in names: - if dir != os.curdir: # avoid the dreaded "./" syndrome - fullname = os.path.join (dir, name) - else: - fullname = name + # findall - # Avoid excess stat calls -- just one will do, thank you! - stat = os.stat(fullname) - mode = stat[ST_MODE] - if S_ISREG(mode): - list.append (fullname) - elif S_ISDIR(mode) and not S_ISLNK(mode): - push (fullname) +# class sdist - return list +# ---------------------------------------------------------------------- +# Utility functions def glob_to_re (pattern): """Translate a shell-like glob pattern to a regular expression; return From akuchlin@mems-exchange.org Fri Jul 14 16:31:51 2000 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Fri, 14 Jul 2000 11:31:51 -0400 Subject: [Distutils] sdist.py::findall chokes on broken links In-Reply-To: ; from calvin@cs.uni-sb.de on Fri, Jul 14, 2000 at 03:56:41PM +0200 References: <20000714093602.A28819@kronos.cnri.reston.va.us> Message-ID: <20000714113151.G28819@kronos.cnri.reston.va.us> On Fri, Jul 14, 2000 at 03:56:41PM +0200, Bastian Kleineidam wrote: >I replaced the stat() calls with os.path.{isfile,islink,isdir}. This is >somewhat more robust. The new findall is now a member function of the >sdist class so I can use self.announce to warn about broken links. The reorganization, though minor, is enough to make me shy about checking it in without Greg's approval. I'd encourage you to go to the SourceForge patch manager for Python (http://sourceforge.net/patch/?group_id=5470) and check it in, so it doesn't get lost. --amk From R.Liebscher@gmx.de Sun Jul 23 00:54:53 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Sun, 23 Jul 2000 01:54:53 +0200 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> <20000704101613.A1881@beelzebub> <396465FC.3FD96CAD@gmx.de> <20000708212019.A4248@beelzebub> <396C71A1.198D8C2C@gmx.de> Message-ID: <397A344D.E3837BD6@gmx.de> This is a multi-part message in MIME format. --------------7EEEE0777720915A60C3A738 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Rene Liebscher wrote: > > Greg Ward wrote: > > > > On 06 July 2000, Rene Liebscher said: > > > +# * cygwin gcc 2.91 works (after patching some include files) > > > +# * mingw32 gcc 2.95.2 works (it doesn't support gcc -shared) > > > +# * cygwin gcc 2.95.2 doesn't work now > > > +# - its dllwrap doesn't work at my machine > > > +# - target had to be changed to something like i686-cygwin32 > > > +# - mingw32-mode is specified by -mno-cygwin > > > +# - using gcc -shared instead dllwrap didn't work because some problems with > > > +# the import library, maybe it needs some additional parameters > > > > AAUUGGHH!!! (What more can I say?) > gcc 2.91 is no problem for us. People should use a newer compiler. > But the differences betweeen these two gcc 2.9.5 are a problem, > mingw32 doesn't support gcc -shared yet, and cygwin's dllwrap > seems to have a bug (It fails to reallocate 1.7 GByte of Memory.) > Cygwin's gcc -shared wants other symbols than dlltool creates > in the import library. > Is there someone out there who has already successful created a > extension module with the new cygwin version? If yes, please send me > the commandlines you used for this. In the latest cygwin binutils 2.10.90 is a bug in dllwrap. This new version of my patch tries now to find out the version numbers of gcc, ld and dllwrap, so we can inform the user if he is using a broken version of one of these programs. (I also found many tabs in distutils which were introduced by by my help-option patch. This patch replaces these tabs with spaces.) kind regards Rene Liebscher --------------7EEEE0777720915A60C3A738 Content-Type: text/plain; charset=us-ascii; name="msvc_hack3.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="msvc_hack3.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/bcppcompiler.py distutils.patched/distutils/bcppcompiler.py --- distutils.orig/distutils/bcppcompiler.py Wed Jun 28 03:20:35 2000 +++ distutils.patched/distutils/bcppcompiler.py Tue Jul 18 11:20:23 2000 @@ -11,17 +11,6 @@ # someone should sit down and factor out the common code as # WindowsCCompiler! --GPW -# XXX Lyle reports that this doesn't quite work yet: -# """...but this is what I've got so far. The compile step works fine but -# when it runs the link step I get an "out of memory" failure. Since -# spawn() echoes the command it's trying to spawn, I can type the link line -# verbatim at the DOS prompt and it links the Windows DLL correctly -- so -# the syntax is correct. There's just some weird interaction going on when -# it tries to "spawn" the link process from within the setup.py script. I'm -# not really sure how to debug this one right off-hand; obviously there's -# nothing wrong with the "spawn()" function since it's working properly for -# the compile stage.""" - __revision__ = "$Id: bcppcompiler.py,v 1.1 2000/06/28 01:20:35 gward Exp $" @@ -123,6 +112,9 @@ elif ext in self._cpp_extensions: input_opt = "-P" + src = os.path.normpath(src) + obj = os.path.normpath(obj) + output_opt = "-o" + obj self.mkpath (os.path.dirname (obj)) @@ -230,24 +222,56 @@ else: ldflags = self.ldflags_shared + # Borland C++ has problems with '/' in paths + objects = map(os.path.normpath,objects) + startup_obj = 'c0d32' - libraries.append ('mypylib') + # either exchange python15.lib in the python libs directory against + # a Borland-like one, or create one with name bcpp_python15.lib + # there and remove the pragmas from config.h + #libraries.append ('mypylib') libraries.append ('import32') libraries.append ('cw32mt') # Create a temporary exports file for use by the linker head, tail = os.path.split (output_filename) modname, ext = os.path.splitext (tail) - def_file = os.path.join (build_temp, '%s.def' % modname) + temp_dir = os.path.dirname(objects[0]) # preserve tree structure + def_file = os.path.join (temp_dir, '%s.def' % modname) f = open (def_file, 'w') f.write ('EXPORTS\n') for sym in (export_symbols or []): f.write (' %s=_%s\n' % (sym, sym)) + f.close() - ld_args = ldflags + [startup_obj] + objects + \ - [',%s,,' % output_filename] + \ - libraries + [',' + def_file] + # start building command line + # flags and options + ld_args = list(ldflags) # don't use a reference, use a separate copy + for l in library_dirs: + ld_args.append("/L%s" % os.path.normpath(l)) + # objects list + ld_args.extend([startup_obj]) + ld_args.extend(objects) + # name of dll file + ld_args.extend([',',output_filename]) + # no map file + ld_args.extend([',']) + # start libraries + ld_args.extend([',']) + for lib in libraries: + # see if we find it and if there is a bcpp specific lib + # (bcpp_xxx.lib) + l = self.find_library_file(library_dirs,lib,debug) + if l == None: + ld_args.append(lib) + # probably an bcpp internal library + # self.warn('library %s not found.' % lib) + else: + # full name which prefers bcpp_xxx.lib over xxx.lib + ld_args.append(l) + # def file for export symbols + ld_args.extend([',',def_file]) if extra_preargs: ld_args[:0] = extra_preargs @@ -325,15 +349,28 @@ def runtime_library_dir_option (self, dir): raise DistutilsPlatformError, \ - "don't know how to set runtime library search path for MSVC++" + "don't know how to set runtime library search path for Borland C++" def library_option (self, lib): return self.library_filename (lib) - def find_library_file (self, dirs, lib): - + def find_library_file (self, dirs, lib, debug=0): + # find library file + # bcpp_xxx.lib is better than xxx.lib + # and xxx_d.lib is better than xxx.lib if debug is set for dir in dirs: + if debug: + libfile = os.path.join (dir, self.library_filename ("bcpp_" + lib + "_d")) + if os.path.exists (libfile): + return libfile + libfile = os.path.join (dir, self.library_filename ("bcpp_" + lib)) + if os.path.exists (libfile): + return libfile + if debug: + libfile = os.path.join (dir, self.library_filename (lib + '_d')) + if os.path.exists (libfile): + return libfile libfile = os.path.join (dir, self.library_filename (lib)) if os.path.exists (libfile): return libfile diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/bdist.py distutils.patched/distutils/command/bdist.py --- distutils.orig/distutils/command/bdist.py Wed Jul 5 05:07:18 2000 +++ distutils.patched/distutils/command/bdist.py Tue Jul 18 11:20:23 2000 @@ -42,7 +42,7 @@ help_options = [ ('help-formats', None, "lists available distribution formats", show_formats), - ] + ] # The following commands do not take a format option from bdist no_format_option = ('bdist_rpm',) diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build.py distutils.patched/distutils/command/build.py --- distutils.orig/distutils/command/build.py Sat Jun 24 03:23:37 2000 +++ distutils.patched/distutils/command/build.py Tue Jul 18 11:20:23 2000 @@ -45,7 +45,7 @@ help_options = [ ('help-compiler', None, "list available compilers", show_compilers), - ] + ] def initialize_options (self): self.build_base = 'build' diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build_clib.py distutils.patched/distutils/command/build_clib.py --- distutils.orig/distutils/command/build_clib.py Sun Jun 25 04:10:58 2000 +++ distutils.patched/distutils/command/build_clib.py Tue Jul 18 11:20:23 2000 @@ -51,7 +51,7 @@ help_options = [ ('help-compiler', None, "list available compilers", show_compilers), - ] + ] def initialize_options (self): self.build_clib = None diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build_ext.py distutils.patched/distutils/command/build_ext.py --- distutils.orig/distutils/command/build_ext.py Sun Jul 16 16:10:00 2000 +++ distutils.patched/distutils/command/build_ext.py Tue Jul 18 11:20:23 2000 @@ -84,7 +84,7 @@ help_options = [ ('help-compiler', None, "list available compilers", show_compilers), - ] + ] def initialize_options (self): self.extensions = None @@ -283,6 +283,9 @@ # Medium-easy stuff: same syntax/semantics, different names. ext.runtime_library_dirs = build_info.get('rpath') ext.export_symbol_file = build_info.get('def_file') + if ext.export_symbol_file is not None: + self.warn("export_symbol_file is no longer supported, " + "comments and questions to ") # Non-trivial stuff: 'macros' split into 'define_macros' # and 'undef_macros'. @@ -420,16 +423,14 @@ objects.extend (ext.extra_objects) extra_args = ext.extra_link_args or [] - # Bunch of fixing-up we have to do for Microsoft's linker. - if self.compiler.compiler_type == 'msvc': - self.msvc_prelink_hack(sources, ext, extra_args) self.compiler.link_shared_object ( objects, ext_filename, - libraries=ext.libraries, + libraries=self.get_libraries(ext), library_dirs=ext.library_dirs, runtime_library_dirs=ext.runtime_library_dirs, extra_postargs=extra_args, + export_symbols=self.get_export_symbols(ext), debug=self.debug, build_temp=self.build_temp) @@ -511,44 +512,6 @@ # find_swig () - - # -- Hooks 'n hacks ------------------------------------------------ - - def msvc_prelink_hack (self, sources, ext, extra_args): - - # XXX this is a kludge! Knowledge of specific compilers or - # platforms really doesn't belong here; in an ideal world, the - # CCompiler interface would provide access to everything in a - # compiler/linker system needs to build Python extensions, and - # we would just do everything nicely and cleanly through that - # interface. However, this is a not an ideal world and the - # CCompiler interface doesn't handle absolutely everything. - # Thus, kludges like this slip in occasionally. (This is no - # excuse for committing more platform- and compiler-specific - # kludges; they are to be avoided if possible!) - - def_file = ext.export_symbol_file - - if def_file is not None: - extra_args.append ('/DEF:' + def_file) - else: - modname = string.split (ext.name, '.')[-1] - extra_args.append('/export:init%s' % modname) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - implib_file = os.path.join ( - self.implib_dir, - self.get_ext_libname (ext.name)) - extra_args.append ('/IMPLIB:' + implib_file) - self.mkpath (os.path.dirname (implib_file)) - - # msvc_prelink_hack () - - # -- Name generators ----------------------------------------------- # (extension names, filenames, whatever) @@ -578,5 +541,33 @@ if os.name == 'nt' and self.debug: return apply (os.path.join, ext_path) + '_d.lib' return apply (os.path.join, ext_path) + '.lib' + + + def get_export_symbols (self, ext): + # For all platforms and compiler doesn't export all symbols + # by default, we have to specify the module's init function + # if the user doesn't provide any export information. + # All other platforms and compilers should ignore such + # export information. + if ext.export_symbols is None: + # if no exports are specified we can't build a working + # python module. + # so let us export the module's init function + return ["init" + string.split(ext.name,'.')[-1]] + else: + return ext.export_symbols + + def get_libraries (self, ext): + # The python library is always needed on Windows. + # We need the python version without the dot, eg. '15' + # MSVC doesn't really need this, because the pragma in config.h + if sys.platform == "win32": + pythonlib = ("python%d%d" % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] + else: + return ext.libraries # class build_ext diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/install_data.py distutils.patched/distutils/command/install_data.py --- distutils.orig/distutils/command/install_data.py Sat Jun 24 19:36:24 2000 +++ distutils.patched/distutils/command/install_data.py Tue Jul 18 11:20:23 2000 @@ -32,9 +32,9 @@ def finalize_options (self): self.set_undefined_options('install', - ('install_data', 'install_dir'), - ('root', 'root'), - ) + ('install_data', 'install_dir'), + ('root', 'root'), + ) def run (self): self.mkpath(self.install_dir) diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/install_lib.py distutils.patched/distutils/command/install_lib.py --- distutils.orig/distutils/command/install_lib.py Sat May 27 19:27:23 2000 +++ distutils.patched/distutils/command/install_lib.py Tue Jul 18 11:20:23 2000 @@ -74,7 +74,7 @@ out_fn = f + (__debug__ and "c" or "o") compile_msg = "byte-compiling %s to %s" % \ (f, os.path.basename (out_fn)) - skip_msg = "byte-compilation of %s skipped" % f + skip_msg = "skipping byte-compilation of %s" % f self.make_file (f, out_fn, compile, (f,), compile_msg, skip_msg) # run () diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/sdist.py distutils.patched/distutils/command/sdist.py --- distutils.orig/distutils/command/sdist.py Wed Jul 5 05:06:46 2000 +++ distutils.patched/distutils/command/sdist.py Tue Jul 18 11:20:23 2000 @@ -73,7 +73,7 @@ help_options = [ ('help-formats', None, "list available distribution formats", show_formats), - ] + ] negative_opt = {'no-defaults': 'use-defaults', 'no-prune': 'prune' } diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/cygwinccompiler.py distutils.patched/distutils/cygwinccompiler.py --- distutils.orig/distutils/cygwinccompiler.py Fri Jun 30 00:57:55 2000 +++ distutils.patched/distutils/cygwinccompiler.py Tue Jul 18 11:20:23 2000 @@ -6,53 +6,45 @@ cygwin in no-cygwin mode). """ +# problems: +# +# * if you use a msvc compiled python version (1.5.2) +# 1. you have to insert a __GNUC__ section in its config.h +# 2. you have to generate a import library for its dll +# - create a def-file for python??.dll +# - create a import library using +# dlltool --dllname python15.dll --def python15.def \ +# --output-lib libpython15.a +# +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# +# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works +# (after patching python's config.h and for C++ some other include files) +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works +# (ld doesn't support -shared, so we use dllwrap) +# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 doesn't work +# - its dllwrap doesn't work, there is a bug in binutils 2.10.90 +# see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html +# - using gcc -shared instead dllwrap didn't work because some problems +# with the import library, maybe it needs some additional parameters? +# ( "undefined reference to '_imp__PyErr_SetString'", +# dlltool builds import libraries with '__imp__PyErr_SetString' +# and '___imp_PyErr_SetString' ) + # created 2000/05/05, Rene Liebscher __revision__ = "$Id: cygwinccompiler.py,v 1.2 2000/06/29 22:57:55 gward Exp $" -import os,sys,string -from distutils import sysconfig +import os,sys from distutils.unixccompiler import UnixCCompiler -# Because these compilers aren't configured in Python's config.h file by -# default we should at least warn the user if he is using a unmodified -# version. - -def check_config_h(): - """Checks if the GCC compiler is mentioned in config.h. If it is not, - compiling probably doesn't work, so print a warning to stderr. - """ - - # XXX the result of the check should be returned! - - from distutils import sysconfig - import string,sys - try: - # It would probably better to read single lines to search. - # But we do this only once, and it is fast enough - f=open(sysconfig.get_config_h_filename()) - s=f.read() - f.close() - try: - # is somewhere a #ifdef __GNUC__ or something similar - string.index(s,"__GNUC__") - except ValueError: - sys.stderr.write ("warning: "+ - "Python's config.h doesn't seem to support your compiler.\n") - except IOError: - # if we can't read this file, we cannot say it is wrong - # the compiler will complain later about this file as missing - pass - - -# This is called when the module is imported, so we make this check only once -# XXX why not make it only when the compiler is needed? -check_config_h() - - class CygwinCCompiler (UnixCCompiler): compiler_type = 'cygwin' + gcc_version = None + dllwrap_version = None + ld_version = None def __init__ (self, verbose=0, @@ -61,22 +53,41 @@ UnixCCompiler.__init__ (self, verbose, dry_run, force) + if check_config_h()<=0: + self.warn( + "Python's config.h doesn't seem to support your compiler. " + "Compiling may fail because of undefined preprocessor macros.") + + self.gcc_version, self.ld_version, self.dllwrap_version = get_versions() + sys.stderr.write(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" % + (self.gcc_version, + self.ld_version, + self.dllwrap_version) ) + + # ld_version >= "2.10.90" should also be able to use + # gcc -shared instead of dllwrap + # Older dllwraps had own version numbers, newer ones use the + # same as the rest of binutils ( also ld ) + if self.dllwrap_version == "2.10.90": + # only warn, the user could have a patched version + self.warn("dllwrap 2.10.90 is buggy please use another version.") + # Hard-code GCC because that's what this is all about. # XXX optimization, warnings etc. should be customizable. - self.set_executables(compiler='gcc -O -Wall', - compiler_so='gcc -O -Wall', - linker_exe='gcc', - linker_so='dllwrap --target=i386-cygwin32') + self.set_executables(compiler='gcc -mcygwin -O -Wall', + compiler_so='gcc -mcygwin -mdll -O -Wall', + linker_exe='gcc -mcygwin', + linker_so='dllwrap -mcygwin -mdll') # cygwin and mingw32 need different sets of libraries - self.dll_libraries=[ - # cygwin shouldn't need msvcrt, - # but without the dll's will crash - # ( gcc version 2.91.57 ) - # perhaps something about initialization - # mingw32 needs it in all cases - "msvcrt" - ] + if self.gcc_version == "2.91.57": + # cygwin shouldn't need msvcrt, but without the dlls will crash + # ( gcc version 2.91.57 ) perhaps something about initialization + self.dll_libraries=["msvcrt"] + self.warn( + "You should think over switching to a newer version of gcc") + else: + self.dll_libraries=[] # __init__ () @@ -96,53 +107,49 @@ if libraries == None: libraries = [] - # Additional libraries: the python library is always needed on - # Windows we need the python version without the dot, eg. '15' - - pythonlib = ("python%d%d" % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - libraries.append(pythonlib) - libraries.extend(self.dll_libraries) - - # name of extension + # Additional libraries + # libraries.extend(...) would affect the list we got as parameter + # and this can come from anywhere + libraries = libraries + self.dll_libraries + + # we want to put some files in the same directory as the + # object files are, build_temp doesn't help much - # XXX WRONG WRONG WRONG - # this is NOT the place to make guesses about Python namespaces; - # that MUST be done in build_ext.py + # name of dll to give the helper files (def, lib, exp) the same name + dll_name,dll_extension = os.path.splitext(os.path.basename(output_filename)) - if not debug: - ext_name = os.path.basename(output_filename)[:-len(".pyd")] - else: - ext_name = os.path.basename(output_filename)[:-len("_d.pyd")] + # where are the object files + temp_dir = os.path.dirname(objects[0]) - def_file = os.path.join(build_temp, ext_name + ".def") - #exp_file = os.path.join(build_temp, ext_name + ".exp") - #lib_file = os.path.join(build_temp, 'lib' + ext_name + ".a") + # generate the filenames for these files + def_file = None # this will be done later, if necessary + exp_file = os.path.join(temp_dir, dll_name + ".exp") + lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a") - # Make .def file - # (It would probably better to check if we really need this, - # but for this we had to insert some unchanged parts of - # UnixCCompiler, and this is not what we want.) - f = open(def_file,"w") - f.write("EXPORTS\n") # intro - if export_symbols == None: - # export a function "init" + ext_name - f.write("init" + ext_name + "\n") - else: - # if there are more symbols to export write them into f + # check what we got in export_symbols + if export_symbols is not None: + # Make .def file + # (It would probably better to check if we really need this, + # but for this we had to insert some unchanged parts of + # UnixCCompiler, and this is not what we want.) + def_file = os.path.join(temp_dir, dll_name + ".def") + f = open(def_file,"w") + f.write("EXPORTS\n") # intro for sym in export_symbols: f.write(sym+"\n") - f.close() - - if extra_preargs == None: + f.close() + + + if extra_preargs is None: extra_preargs = [] extra_preargs = extra_preargs + [ #"--verbose", #"--output-exp",exp_file, #"--output-lib",lib_file, - "--def",def_file ] + if def_file: + extra_preargs.extend(["--def",def_file]) # who wants symbols and a many times larger output file # should explicitely switch the debug mode on @@ -150,7 +157,7 @@ # (On my machine unstripped_file = stripped_file + 254KB # 10KB < stripped_file < ??100KB ) if not debug: - extra_preargs = extra_preargs + ["-s"] + extra_preargs.append("-s") UnixCCompiler.link_shared_object(self, objects, @@ -181,19 +188,112 @@ force=0): CygwinCCompiler.__init__ (self, verbose, dry_run, force) - + + # a real mingw32 doesn't need to specify a different entry point + # but cygwin 2.91.57 in no-cygwin-mode needs it + if self.gcc_version <= "2.91.57": + entry_point = ' --entry _DllMain@12' + else: + entry_point = '' self.set_executables(compiler='gcc -mno-cygwin -O -Wall', - compiler_so='gcc -mno-cygwin -O -Wall', + compiler_so='gcc -mno-cygwin -mdll -O -Wall', linker_exe='gcc -mno-cygwin', - linker_so='dllwrap' - + ' --target=i386-mingw32' - + ' --entry _DllMain@12') - # mingw32 doesn't really need 'target' and cygwin too (it seems, - # it is enough to specify a different entry point) - - # no additional libraries need - # (only msvcrt, which is already added by CygwinCCompiler) - + linker_so='dllwrap -mno-cygwin -mdll' + + entry_point) + # Maybe we should also append -mthreads, but then the finished + # dlls need another dll (mingwm10.dll see Mingw32 docs) + # (-mthreads: Support thread-safe exception handling on `Mingw32') + + # no additional libraries needed + self.dll_libraries=[] + # __init__ () - + # class Mingw32CCompiler + +# Because these compilers aren't configured in Python's config.h file by +# default, we should at least warn the user if he is using a unmodified +# version. + +def check_config_h(): + """Checks if the GCC compiler is mentioned in config.h. If it is not, + compiling probably doesn't work. + """ + # return values + # 2: OK, python was compiled with GCC + # 1: OK, python's config.h mentions __GCC__ + # 0: uncertain, because we couldn't check it + # -1: probably not OK, because we didn't found it in config.h + # You could check check_config_h()>0 => OK + + from distutils import sysconfig + import string,sys + # if sys.version contains GCC then python was compiled with + # GCC, and the config.h file should be OK + if -1 == string.find(sys.version,"GCC"): + pass # go to the next test + else: + return 2 + + try: + # It would probably better to read single lines to search. + # But we do this only once, and it is fast enough + f=open(sysconfig.get_config_h_filename()) + s=f.read() + f.close() + + # is somewhere a #ifdef __GNUC__ or something similar + if -1 == string.find(s,"__GNUC__"): + return -1 + else: + return 1 + except IOError: + # if we can't read this file, we cannot say it is wrong + # the compiler will complain later about this file as missing + pass + return 0 + +def get_versions(): + from distutils.version import StrictVersion + from distutils.spawn import find_executable + import re + + gcc_exe = find_executable('gcc') + if gcc_exe: + out = os.popen(gcc_exe + ' -dumpversion','r') + out_string = out.read() + out.close() + result = re.search('(\d+\.\d+\.\d+)',out_string) + if result: + gcc_version = StrictVersion(result.group(1)) + else: + gcc_version = None + else: + gcc_version = None + ld_exe = find_executable('ld') + if ld_exe: + out = os.popen(ld_exe + ' -v','r') + out_string = out.read() + out.close() + result = re.search('(\d+\.\d+\.\d+)',out_string) + if result: + ld_version = StrictVersion(result.group(1)) + else: + ld_version = None + else: + ld_version = None + dllwrap_exe = find_executable('dllwrap') + if dllwrap_exe: + out = os.popen(dllwrap_exe + ' --version','r') + out_string = out.read() + out.close() + result = re.search(' (\d+\.\d+\.\d+)',out_string) + if result: + dllwrap_version = StrictVersion(result.group(1)) + else: + dllwrap_version = None + else: + dllwrap_version = None + return (gcc_version, ld_version, dllwrap_version) + + diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/dist.py distutils.patched/distutils/dist.py --- distutils.orig/distutils/dist.py Fri Jul 7 22:45:21 2000 +++ distutils.patched/distutils/dist.py Tue Jul 18 11:20:23 2000 @@ -278,7 +278,7 @@ user_filename = ".pydistutils.cfg" else: user_filename = "pydistutils.cfg" - + # And look for the user config file if os.environ.has_key('HOME'): user_file = os.path.join(os.environ.get('HOME'), user_filename) @@ -437,8 +437,8 @@ negative_opt = copy (negative_opt) negative_opt.update (cmd_class.negative_opt) - # Check for help_options in command class. They have a different - # format (tuple of four) so we need to preprocess them here. + # Check for help_options in command class. They have a different + # format (tuple of four) so we need to preprocess them here. if (hasattr(cmd_class, 'help_options') and type (cmd_class.help_options) is ListType): help_options = fix_help_options(cmd_class.help_options) @@ -463,7 +463,7 @@ for (help_option, short, desc, func) in cmd_class.help_options: if hasattr(opts, parser.get_attr_name(help_option)): help_option_found=1 - #print "showing help for option %s of command %s" % \ + #print "showing help for option %s of command %s" % \ # (help_option[0],cmd_class) if callable(func): @@ -539,7 +539,7 @@ return # _show_help () - + def handle_display_options (self, option_order): """If there were any non-global "display-only" options diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/extension.py distutils.patched/distutils/extension.py --- distutils.orig/distutils/extension.py Sat Jun 24 02:18:24 2000 +++ distutils.patched/distutils/extension.py Tue Jul 18 11:20:23 2000 @@ -111,7 +111,7 @@ self.extra_objects = extra_objects or [] self.extra_compile_args = extra_compile_args or [] self.extra_link_args = extra_link_args or [] - self.export_symbols = export_symbols or [] + self.export_symbols = export_symbols self.export_symbol_file = export_symbol_file # class Extension diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/msvccompiler.py distutils.patched/distutils/msvccompiler.py --- distutils.orig/distutils/msvccompiler.py Fri Jun 30 21:37:59 2000 +++ distutils.patched/distutils/msvccompiler.py Tue Jul 18 11:20:23 2000 @@ -379,6 +380,17 @@ ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + dll_name, dll_ext = os.path.splitext(os.path.basename(output_filename)) + implib_file = os.path.join ( + os.path.dirname(objects[0]), + self.static_lib_format % (dll_name, self.static_lib_extension)) + ld_args.append ('/IMPLIB:' + implib_file) if extra_preargs: ld_args[:0] = extra_preargs diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/spawn.py distutils.patched/distutils/spawn.py --- distutils.orig/distutils/spawn.py Sun Mar 26 23:47:00 2000 +++ distutils.patched/distutils/spawn.py Tue Jul 18 11:20:23 2000 @@ -1,7 +1,9 @@ """distutils.spawn Provides the 'spawn()' function, a front-end to various platform- -specific functions for launching another program in a sub-process.""" +specific functions for launching another program in a sub-process. +Also provides the 'find_executable()' to search the path for a given +executable name. """ # created 1999/07/24, Greg Ward @@ -65,17 +67,8 @@ executable = cmd[0] cmd = _nt_quote_args (cmd) if search_path: - paths = string.split( os.environ['PATH'], os.pathsep) - base,ext = os.path.splitext(executable) - if (ext != '.exe'): - executable = executable + '.exe' - if not os.path.isfile(executable): - paths.reverse() # go over the paths and keep the last one - for p in paths: - f = os.path.join( p, executable ) - if os.path.isfile ( f ): - # the file exists, we have a shot at spawn working - executable = f + # either we find one or it stays the same + executable = find_executable(executable) or executable if verbose: print string.join ([executable] + cmd[1:], ' ') if not dry_run: @@ -91,7 +84,6 @@ raise DistutilsExecError, \ "command '%s' failed with exit status %d" % (cmd[0], rc) - def _spawn_posix (cmd, search_path=1, @@ -147,3 +139,24 @@ "unknown error executing '%s': termination status %d" % \ (cmd[0], status) # _spawn_posix () + + +def find_executable(executable): + """ Tries to find executable in the directories listed in PATH. + Returns the complete filename or None if not found. """ + + paths = string.split( os.environ['PATH'], os.pathsep) + base,ext = os.path.splitext(executable) + if (sys.platform == 'win32') and (ext != '.exe'): + executable = executable + '.exe' + if not os.path.isfile(executable): + for p in paths: + f = os.path.join( p, executable ) + if os.path.isfile ( f ): + # the file exists, we have a shot at spawn working + return f + return None + else: + return executable + +# find_executable() diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/sysconfig.py distutils.patched/distutils/sysconfig.py --- distutils.orig/distutils/sysconfig.py Tue Jun 27 03:59:43 2000 +++ distutils.patched/distutils/sysconfig.py Tue Jul 18 11:20:24 2000 @@ -267,24 +267,8 @@ g['INCLUDEPY'] = get_python_inc(plat_specific=0) g['SO'] = '.pyd' - g['exec_prefix'] = EXEC_PREFIX - - # These are needed for the CygwinCCompiler and Mingw32CCompiler - # classes, which are just UnixCCompiler classes that happen to work on - # Windows. UnixCCompiler expects to find these values in sysconfig, so - # here they are. The fact that other Windows compilers don't need - # these values is pure luck (hmmm). - - # XXX I think these are now unnecessary... - - g['CC'] = "cc" # not gcc? - g['RANLIB'] = "ranlib" - g['AR'] = "ar" - g['OPT'] = "-O2" - g['SO'] = ".pyd" - g['LDSHARED'] = "ld" - g['CCSHARED'] = "" g['EXE'] = ".exe" + g['exec_prefix'] = EXEC_PREFIX def _init_mac(): --------------7EEEE0777720915A60C3A738-- From R.Liebscher@gmx.de Sun Jul 23 02:18:06 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Sun, 23 Jul 2000 03:18:06 +0200 Subject: [Distutils] Extract template processing from sdist.py Message-ID: <397A47CE.812A3636@gmx.de> This is a multi-part message in MIME format. --------------661895B6616B78ECA85C1F65 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Relating to Greg's answer to a similar topic, > (26 Jun 2000) ... Even in a really complex case, where the > manifest machinery would be useful, I think it would be better > just to expose it as one of the "utility classes" that Distutils > makes available to authors of setup scripts, ... here is now a patch which extracts this template machinery from sdist.py and puts it in new file template.py The sdist command uses then the Template class which is provided by this new file. It also possible for authors of setup scripts to use it. > What's wrong with glob.glob()? It only works in one directory, Template() uses also the subdirectories of the given directory. If you have a non-flat directory structure, you had to use glob.glob() in a recursive way to select your files. kind regards Rene Liebscher --------------661895B6616B78ECA85C1F65 Content-Type: text/plain; charset=us-ascii; name="template.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="template.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/sdist.py d.p2/distutils/command/sdist.py --- distutils.orig/distutils/command/sdist.py Wed Jul 5 05:06:46 2000 +++ d.p2/distutils/command/sdist.py Tue Jul 18 12:33:29 2000 @@ -6,16 +6,16 @@ __revision__ = "$Id: sdist.py,v 1.37 2000/07/05 03:06:46 gward Exp $" -import sys, os, string, re -import fnmatch +import sys, os, string from types import * from glob import glob from distutils.core import Command from distutils.util import \ - convert_path, create_tree, remove_tree, newer, write_file, \ + create_tree, remove_tree, newer, write_file, \ check_archive_formats from distutils.text_file import TextFile from distutils.errors import DistutilsExecError, DistutilsOptionError +from distutils.template import Template def show_formats (): @@ -319,45 +319,6 @@ # add_defaults () - def search_dir (self, dir, pattern=None): - """Recursively find files under 'dir' matching 'pattern' (a string - containing a Unix-style glob pattern). If 'pattern' is None, find - all files under 'dir'. Return the list of found filenames. - """ - allfiles = findall (dir) - if pattern is None: - return allfiles - - pattern_re = translate_pattern (pattern) - files = [] - for file in allfiles: - if pattern_re.match (os.path.basename (file)): - files.append (file) - - return files - - # search_dir () - - - def recursive_exclude_pattern (self, dir, pattern=None): - """Remove filenames from 'self.files' that are under 'dir' and - whose basenames match 'pattern'. - """ - self.debug_print("recursive_exclude_pattern: dir=%s, pattern=%s" % - (dir, pattern)) - if pattern is None: - pattern_re = None - else: - pattern_re = translate_pattern (pattern) - - for i in range (len (self.files)-1, -1, -1): - (cur_dir, cur_base) = os.path.split (self.files[i]) - if (cur_dir == dir and - (pattern_re is None or pattern_re.match (cur_base))): - self.debug_print("removing %s" % self.files[i]) - del self.files[i] - - def read_template (self): """Read and parse the manifest template file named by 'self.template' (usually "MANIFEST.in"). Process all file @@ -376,7 +337,10 @@ rstrip_ws=1, collapse_ws=1) - all_files = findall () + # if we give Template() a list, it modifies this list + files_template = Template(files=self.files, + warn=self.warn, + debug_print=self.debug_print) while 1: @@ -384,142 +348,7 @@ if line is None: # end of file break - words = string.split (line) - action = words[0] - - # First, check that the right number of words are present - # for the given action (which is the first word) - if action in ('include','exclude', - 'global-include','global-exclude'): - if len (words) < 2: - template.warn \ - ("invalid manifest template line: " + - "'%s' expects ..." % - action) - continue - - pattern_list = map(convert_path, words[1:]) - - elif action in ('recursive-include','recursive-exclude'): - if len (words) < 3: - template.warn \ - ("invalid manifest template line: " + - "'%s' expects ..." % - action) - continue - - dir = convert_path(words[1]) - pattern_list = map (convert_path, words[2:]) - - elif action in ('graft','prune'): - if len (words) != 2: - template.warn \ - ("invalid manifest template line: " + - "'%s' expects a single " % - action) - continue - - dir_pattern = convert_path (words[1]) - - else: - template.warn ("invalid manifest template line: " + - "unknown action '%s'" % action) - continue - - # OK, now we know that the action is valid and we have the - # right number of words on the line for that action -- so we - # can proceed with minimal error-checking. Also, we have - # defined either (pattern), (dir and pattern), or - # (dir_pattern) -- so we don't have to spend any time - # digging stuff up out of 'words'. - - if action == 'include': - self.debug_print("include " + string.join(pattern_list)) - for pattern in pattern_list: - files = self.select_pattern (all_files, pattern, anchor=1) - if not files: - template.warn ("no files found matching '%s'" % - pattern) - else: - self.files.extend (files) - - elif action == 'exclude': - self.debug_print("exclude " + string.join(pattern_list)) - for pattern in pattern_list: - num = self.exclude_pattern (self.files, pattern, anchor=1) - if num == 0: - template.warn ( - "no previously-included files found matching '%s'"% - pattern) - - elif action == 'global-include': - self.debug_print("global-include " + string.join(pattern_list)) - for pattern in pattern_list: - files = self.select_pattern (all_files, pattern, anchor=0) - if not files: - template.warn (("no files found matching '%s' " + - "anywhere in distribution") % - pattern) - else: - self.files.extend (files) - - elif action == 'global-exclude': - self.debug_print("global-exclude " + string.join(pattern_list)) - for pattern in pattern_list: - num = self.exclude_pattern (self.files, pattern, anchor=0) - if num == 0: - template.warn \ - (("no previously-included files matching '%s' " + - "found anywhere in distribution") % - pattern) - - elif action == 'recursive-include': - self.debug_print("recursive-include %s %s" % - (dir, string.join(pattern_list))) - for pattern in pattern_list: - files = self.select_pattern ( - all_files, pattern, prefix=dir) - if not files: - template.warn (("no files found matching '%s' " + - "under directory '%s'") % - (pattern, dir)) - else: - self.files.extend (files) - - elif action == 'recursive-exclude': - self.debug_print("recursive-exclude %s %s" % - (dir, string.join(pattern_list))) - for pattern in pattern_list: - num = self.exclude_pattern( - self.files, pattern, prefix=dir) - if num == 0: - template.warn \ - (("no previously-included files matching '%s' " + - "found under directory '%s'") % - (pattern, dir)) - - elif action == 'graft': - self.debug_print("graft " + dir_pattern) - files = self.select_pattern( - all_files, None, prefix=dir_pattern) - if not files: - template.warn ("no directories found matching '%s'" % - dir_pattern) - else: - self.files.extend (files) - - elif action == 'prune': - self.debug_print("prune " + dir_pattern) - num = self.exclude_pattern( - self.files, None, prefix=dir_pattern) - if num == 0: - template.warn \ - (("no previously-included directories found " + - "matching '%s'") % - dir_pattern) - else: - raise RuntimeError, \ - "this cannot happen: invalid action '%s'" % action + files_template.process_line(line) # while loop over lines of template file @@ -536,65 +365,14 @@ """ build = self.get_finalized_command('build') base_dir = self.distribution.get_fullname() - self.exclude_pattern (self.files, None, prefix=build.build_base) - self.exclude_pattern (self.files, None, prefix=base_dir) - self.exclude_pattern (self.files, r'/(RCS|CVS)/.*', is_regex=1) - - - def select_pattern (self, files, pattern, - anchor=1, prefix=None, is_regex=0): - """Select strings (presumably filenames) from 'files' that match - 'pattern', a Unix-style wildcard (glob) pattern. Patterns are not - quite the same as implemented by the 'fnmatch' module: '*' and '?' - match non-special characters, where "special" is platform-dependent: - slash on Unix, colon, slash, and backslash on DOS/Windows, and colon on - Mac OS. - - If 'anchor' is true (the default), then the pattern match is more - stringent: "*.py" will match "foo.py" but not "foo/bar.py". If - 'anchor' is false, both of these will match. - - If 'prefix' is supplied, then only filenames starting with 'prefix' - (itself a pattern) and ending with 'pattern', with anything in between - them, will match. 'anchor' is ignored in this case. - - If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and - 'pattern' is assumed to be either a string containing a regex or a - regex object -- no translation is done, the regex is just compiled - and used as-is. - - Return the list of matching strings, possibly empty. - """ - matches = [] - pattern_re = translate_pattern (pattern, anchor, prefix, is_regex) - self.debug_print("select_pattern: applying regex r'%s'" % - pattern_re.pattern) - for name in files: - if pattern_re.search (name): - matches.append (name) - self.debug_print(" adding " + name) - - return matches - - # select_pattern () - - - def exclude_pattern (self, files, pattern, - anchor=1, prefix=None, is_regex=0): - """Remove strings (presumably filenames) from 'files' that match - 'pattern'. Other parameters are the same as for - 'select_pattern()', above. The list 'files' is modified in place. - """ - pattern_re = translate_pattern (pattern, anchor, prefix, is_regex) - self.debug_print("exclude_pattern: applying regex r'%s'" % - pattern_re.pattern) - for i in range (len(files)-1, -1, -1): - if pattern_re.search (files[i]): - self.debug_print(" removing " + files[i]) - del files[i] - - # exclude_pattern () + # if we give Template() a list, it modifies this list + files_template = Template(files=self.files, + warn=self.warn, + debug_print=self.debug_print) + files_template.exclude_pattern (None, prefix=build.build_base) + files_template.exclude_pattern (None, prefix=base_dir) + files_template.exclude_pattern (r'/(RCS|CVS)/.*', is_regex=1) def write_manifest (self): @@ -696,88 +474,3 @@ return self.archive_files # class sdist - - -# ---------------------------------------------------------------------- -# Utility functions - -def findall (dir = os.curdir): - """Find all files under 'dir' and return the list of full filenames - (relative to 'dir'). - """ - from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK - - list = [] - stack = [dir] - pop = stack.pop - push = stack.append - - while stack: - dir = pop() - names = os.listdir (dir) - - for name in names: - if dir != os.curdir: # avoid the dreaded "./" syndrome - fullname = os.path.join (dir, name) - else: - fullname = name - - # Avoid excess stat calls -- just one will do, thank you! - stat = os.stat(fullname) - mode = stat[ST_MODE] - if S_ISREG(mode): - list.append (fullname) - elif S_ISDIR(mode) and not S_ISLNK(mode): - push (fullname) - - return list - - -def glob_to_re (pattern): - """Translate a shell-like glob pattern to a regular expression; return - a string containing the regex. Differs from 'fnmatch.translate()' in - that '*' does not match "special characters" (which are - platform-specific). - """ - pattern_re = fnmatch.translate (pattern) - - # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which - # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, - # and by extension they shouldn't match such "special characters" under - # any OS. So change all non-escaped dots in the RE to match any - # character except the special characters. - # XXX currently the "special characters" are just slash -- i.e. this is - # Unix-only. - pattern_re = re.sub (r'(^|[^\\])\.', r'\1[^/]', pattern_re) - return pattern_re - -# glob_to_re () - - -def translate_pattern (pattern, anchor=1, prefix=None, is_regex=0): - """Translate a shell-like wildcard pattern to a compiled regular - expression. Return the compiled regex. If 'is_regex' true, - then 'pattern' is directly compiled to a regex (if it's a string) - or just returned as-is (assumes it's a regex object). - """ - if is_regex: - if type(pattern) is StringType: - return re.compile(pattern) - else: - return pattern - - if pattern: - pattern_re = glob_to_re (pattern) - else: - pattern_re = '' - - if prefix is not None: - prefix_re = (glob_to_re (prefix))[0:-1] # ditch trailing $ - pattern_re = "^" + os.path.join (prefix_re, ".*" + pattern_re) - else: # no prefix -- respect anchor flag - if anchor: - pattern_re = "^" + pattern_re - - return re.compile (pattern_re) - -# translate_pattern () diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/template.py d.p2/distutils/template.py --- distutils.orig/distutils/template.py Thu Jan 1 01:00:00 1970 +++ d.p2/distutils/template.py Tue Jul 18 12:40:11 2000 @@ -0,0 +1,359 @@ +"""distutils.template + Provides a template class which implements a file selecting + mechanism as used in MANIFEST.in +""" + +# created 2000/07/17, Rene Liebscher +# most parts taken from commands/sdist.py + +__revision__ = "$Id: template.py $" + +import sys, os, string, re +import fnmatch +from types import * +from glob import glob +from distutils.util import convert_path + +class Template: + + files = None # reference to files list to mainpulate + allfiles = None # list of all files, if None will be filled + # at first use from directory self.dir + dir = None # directory from which files will be taken + # to fill self.allfiles if it was not set otherwise + + # next both functions (callable objects) can be set by the user + # warn: warning function + # debug_print: debug function + + def __init__(self, + files=[], + dir=os.curdir, + allfiles=None, + warn=None, + debug_print=None): + # use standard warning and debug functions, if no other given + if warn is None: warn = self.__warn + if debug_print is None: debug_print = self.__debug_print + self.warn = warn + self.debug_print = debug_print + self.files = files + self.dir = dir + self.allfiles = allfiles + # if None, it will be filled, when used for first time + + + # standard warning and debug functions, if no other given + def __warn (self, msg): + sys.stderr.write ("warning: template: %s\n" % msg) + + def __debug_print (self, msg): + """Print 'msg' to stdout if the global DEBUG (taken from the + DISTUTILS_DEBUG environment variable) flag is true. + """ + from distutils.core import DEBUG + if DEBUG: + print msg + + + def process_line(self, line): + + words = string.split (line) + action = words[0] + + # First, check that the right number of words are present + # for the given action (which is the first word) + if action in ('include','exclude', + 'global-include','global-exclude'): + if len (words) < 2: + self.warn \ + ("invalid template line: " + + "'%s' expects ..." % + action) + return + + pattern_list = map(convert_path, words[1:]) + + elif action in ('recursive-include','recursive-exclude'): + if len (words) < 3: + self.warn \ + ("invalid template line: " + + "'%s' expects ..." % + action) + return + + dir = convert_path(words[1]) + pattern_list = map (convert_path, words[2:]) + + elif action in ('graft','prune'): + if len (words) != 2: + self.warn \ + ("invalid template line: " + + "'%s' expects a single " % + action) + return + + dir_pattern = convert_path (words[1]) + + else: + self.warn ("invalid template line: " + + "unknown action '%s'" % action) + return + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. Also, we have + # defined either (pattern), (dir and pattern), or + # (dir_pattern) -- so we don't have to spend any time + # digging stuff up out of 'words'. + + if action == 'include': + self.debug_print("include " + string.join(pattern_list)) + for pattern in pattern_list: + if not self.select_pattern (pattern, anchor=1): + self.warn ("no files found matching '%s'" % + pattern) + + elif action == 'exclude': + self.debug_print("exclude " + string.join(pattern_list)) + for pattern in pattern_list: + if not self.exclude_pattern (pattern, anchor=1): + self.warn ( + "no previously-included files found matching '%s'"% + pattern) + + elif action == 'global-include': + self.debug_print("global-include " + string.join(pattern_list)) + for pattern in pattern_list: + if not self.select_pattern (pattern, anchor=0): + self.warn (("no files found matching '%s' " + + "anywhere in distribution") % + pattern) + + elif action == 'global-exclude': + self.debug_print("global-exclude " + string.join(pattern_list)) + for pattern in pattern_list: + if not self.exclude_pattern (pattern, anchor=0): + self.warn \ + (("no previously-included files matching '%s' " + + "found anywhere in distribution") % + pattern) + + elif action == 'recursive-include': + self.debug_print("recursive-include %s %s" % + (dir, string.join(pattern_list))) + for pattern in pattern_list: + if not self.select_pattern (pattern, prefix=dir): + self.warn (("no files found matching '%s' " + + "under directory '%s'") % + (pattern, dir)) + + elif action == 'recursive-exclude': + self.debug_print("recursive-exclude %s %s" % + (dir, string.join(pattern_list))) + for pattern in pattern_list: + if not self.exclude_pattern(pattern, prefix=dir): + self.warn \ + (("no previously-included files matching '%s' " + + "found under directory '%s'") % + (pattern, dir)) + + elif action == 'graft': + self.debug_print("graft " + dir_pattern) + if not self.select_pattern(None, prefix=dir_pattern): + self.warn ("no directories found matching '%s'" % + dir_pattern) + + elif action == 'prune': + self.debug_print("prune " + dir_pattern) + if not self.exclude_pattern(None, prefix=dir_pattern): + self.warn \ + (("no previously-included directories found " + + "matching '%s'") % + dir_pattern) + else: + raise RuntimeError, \ + "this cannot happen: invalid action '%s'" % action + + # process_line () + + + + + def select_pattern (self, pattern, + anchor=1, prefix=None, is_regex=0): + """Select strings (presumably filenames) from 'files' that match + 'pattern', a Unix-style wildcard (glob) pattern. Patterns are not + quite the same as implemented by the 'fnmatch' module: '*' and '?' + match non-special characters, where "special" is platform-dependent: + slash on Unix, colon, slash, and backslash on DOS/Windows, and colon on + Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return 1 if files are found. + """ + files_found = 0 + pattern_re = translate_pattern (pattern, anchor, prefix, is_regex) + self.debug_print("select_pattern: applying regex r'%s'" % + pattern_re.pattern) + + # delayed loading of allfiles list + if self.allfiles is None: self.allfiles = findall (self.dir) + + for name in self.allfiles: + if pattern_re.search (name): + self.debug_print(" adding " + name) + self.files.append (name) + files_found = 1 + + return files_found + + # select_pattern () + + + def exclude_pattern (self, pattern, + anchor=1, prefix=None, is_regex=0): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. Other parameters are the same as for + 'select_pattern()', above. + The list 'self.files' is modified in place. + Return 1 if files are found. + """ + files_found = 0 + pattern_re = translate_pattern (pattern, anchor, prefix, is_regex) + self.debug_print("exclude_pattern: applying regex r'%s'" % + pattern_re.pattern) + for i in range (len(self.files)-1, -1, -1): + if pattern_re.search (self.files[i]): + self.debug_print(" removing " + self.files[i]) + del self.files[i] + files_found = 1 + + return files_found + + # exclude_pattern () + + + def recursive_exclude_pattern (self, dir, pattern=None): + """Remove filenames from 'self.files' that are under 'dir' and + whose basenames match 'pattern'. + Return 1 if files are found. + """ + files_found = 0 + self.debug_print("recursive_exclude_pattern: dir=%s, pattern=%s" % + (dir, pattern)) + if pattern is None: + pattern_re = None + else: + pattern_re = translate_pattern (pattern) + + for i in range (len (self.files)-1, -1, -1): + (cur_dir, cur_base) = os.path.split (self.files[i]) + if (cur_dir == dir and + (pattern_re is None or pattern_re.match (cur_base))): + self.debug_print("removing %s" % self.files[i]) + del self.files[i] + files_found = 1 + + return files_found + +# class Template + + +# ---------------------------------------------------------------------- +# Utility functions + +def findall (dir = os.curdir): + """Find all files under 'dir' and return the list of full filenames + (relative to 'dir'). + """ + from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK + + list = [] + stack = [dir] + pop = stack.pop + push = stack.append + + while stack: + dir = pop() + names = os.listdir (dir) + + for name in names: + if dir != os.curdir: # avoid the dreaded "./" syndrome + fullname = os.path.join (dir, name) + else: + fullname = name + + # Avoid excess stat calls -- just one will do, thank you! + stat = os.stat(fullname) + mode = stat[ST_MODE] + if S_ISREG(mode): + list.append (fullname) + elif S_ISDIR(mode) and not S_ISLNK(mode): + push (fullname) + + return list + + +def glob_to_re (pattern): + """Translate a shell-like glob pattern to a regular expression; return + a string containing the regex. Differs from 'fnmatch.translate()' in + that '*' does not match "special characters" (which are + platform-specific). + """ + pattern_re = fnmatch.translate (pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters. + # XXX currently the "special characters" are just slash -- i.e. this is + # Unix-only. + pattern_re = re.sub (r'(^|[^\\])\.', r'\1[^/]', pattern_re) + return pattern_re + +# glob_to_re () + + +def translate_pattern (pattern, anchor=1, prefix=None, is_regex=0): + """Translate a shell-like wildcard pattern to a compiled regular + expression. Return the compiled regex. If 'is_regex' true, + then 'pattern' is directly compiled to a regex (if it's a string) + or just returned as-is (assumes it's a regex object). + """ + if is_regex: + if type(pattern) is StringType: + return re.compile(pattern) + else: + return pattern + + if pattern: + pattern_re = glob_to_re (pattern) + else: + pattern_re = '' + + if prefix is not None: + prefix_re = (glob_to_re (prefix))[0:-1] # ditch trailing $ + pattern_re = "^" + os.path.join (prefix_re, ".*" + pattern_re) + else: # no prefix -- respect anchor flag + if anchor: + pattern_re = "^" + pattern_re + + return re.compile (pattern_re) + +# translate_pattern () --------------661895B6616B78ECA85C1F65-- From gward@python.net Sun Jul 23 03:10:57 2000 From: gward@python.net (Greg Ward) Date: Sat, 22 Jul 2000 22:10:57 -0400 Subject: [Distutils] Re: distutils, tutorials and documentation In-Reply-To: ; from igorr@ifi.uio.no on Thu, Jul 20, 2000 at 02:33:36PM +0200 References: Message-ID: <20000722221057.D1135@beelzebub> On 20 July 2000, Igor V. Rafienko said: > [I'm not sure whether this should have gone to the distutils mailing list] Yeah, probably. I'll cc the list -- nothing private here, except my embarassment about state of the Distutils docs. > I was wondering whether the missing documentation > (for instance > , > or an entire chapter 8 and 9 for that matter) > was a result of my unwillingness to dig deeper on > or an implementation > feature of the documentation? ;) There's nothing there yet because I haven't written it yet. You haven't missed anything. > Seriously, I've got a somewhat particular mix of python, C, and SQL code > that is supposed to be luser-friendly to install. After snooping a little > bit around, it looked like distutils was the right way to go. However, I'm > unable to find any detailed documentation on writing install scripts with > distutils, short of looking at the source code. Since you've written most > of the documentation I could find, I thought that maybe you could give a > couple of hints as to where I should look. See examples/sample3/setup.py in the Distutils 0.9 distribution for a slightly silly example of writing custom commands. For a real-world example, Numerical Python used to require a custom command to install C headers, but not any more -- you can see the old setup script in the Numerical 15.2 release. After you've taken a look at those examples, *please* flood the list with questions. ;-) This will 1) prod me into writing the docs, and 2) give me some idea of what needs the most documenting. Thanks -- Greg -- Greg Ward - maladjusted computer geek gward@python.net http://starship.python.net/~gward/ I once decorated my apartment entirely in ten foot salad forks!! From gward@python.net Thu Jul 27 02:11:47 2000 From: gward@python.net (Greg Ward) Date: Wed, 26 Jul 2000 21:11:47 -0400 Subject: [Distutils] Absolute path library names In-Reply-To: <396C749E.7FF25EE0@gmx.de>; from R.Liebscher@gmx.de on Wed, Jul 12, 2000 at 03:37:34PM +0200 References: <396C749E.7FF25EE0@gmx.de> Message-ID: <20000726211147.B1506@beelzebub> On 12 July 2000, Rene Liebscher said: > It is not a missing function, it is only a wrong piece of code. > It should look like this: > --- distutils.orig/distutils/unixccompiler.py Wed Jun 28 03:29:09 2000 > +++ distutils.patched/distutils/unixccompiler.py Wed Jul 12 > 15:29:21 2000 > @@ -320,7 +320,7 @@ > def find_library_file (self, dirs, lib): > > for dir in dirs: > - shared = os.path.join (dir, self.shared_library_filename > (lib)) > + shared = os.path.join (dir, self.library_filename > (lib,'shared')) > static = os.path.join (dir, self.library_filename (lib)) That's only half of it -- you forgot to grep for the other place where I made this mistake! ;-) (Hint: same file, different place.) ...there, I've fixed 'em both. Will checkin shortly. Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ War is Peace; Freedom is Slavery; Ignorance is Knowledge From gward@python.net Thu Jul 27 02:06:40 2000 From: gward@python.net (Greg Ward) Date: Wed, 26 Jul 2000 21:06:40 -0400 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler In-Reply-To: <397A344D.E3837BD6@gmx.de>; from R.Liebscher@gmx.de on Sun, Jul 23, 2000 at 01:54:53AM +0200 References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> <20000704101613.A1881@beelzebub> <396465FC.3FD96CAD@gmx.de> <20000708212019.A4248@beelzebub> <396C71A1.198D8C2C@gmx.de> <397A344D.E3837BD6@gmx.de> Message-ID: <20000726210640.A1506@beelzebub> On 23 July 2000, Rene Liebscher said: > In the latest cygwin binutils 2.10.90 is a bug in dllwrap. > This new version of my patch tries now to find out the version > numbers of gcc, ld and dllwrap, so we can inform the user > if he is using a broken version of one of these programs. Ugh. I guess version-checking is slightly better than crashing, but I hate that it's necessary. *grumble* > (I also found many tabs in distutils which were introduced by > by my help-option patch. This patch replaces these tabs with > spaces.) This patch is getting too big for me to digest, and there are too many unrelated changes. Could you drop the tab fix (I'll do it myself -- been meaning to for a while now), and submit your fix to bcppcompiler.py separately from the other patches? *Then* I'll be able to comment sensibly on it. Thanks -- Greg -- Greg Ward - Linux geek gward@python.net http://starship.python.net/~gward/ An elephant: a mouse built to government specifications. From gward@python.net Thu Jul 27 02:16:39 2000 From: gward@python.net (Greg Ward) Date: Wed, 26 Jul 2000 21:16:39 -0400 Subject: [Distutils] installation In-Reply-To: <200007122239.QAA06573@niwot.scd.ucar.edu>; from fred@scd.ucar.edu on Wed, Jul 12, 2000 at 04:39:07PM -0600 References: <200007122239.QAA06573@niwot.scd.ucar.edu> Message-ID: <20000726211639.C1506@beelzebub> On 12 July 2000, fred said: > I am trying to install numpy and am first installing > distutils. I am running SunOS 5.7 on a sparc Ultra-4. > I installed Python after downloading it from python.org. > When I try to install distutils, it reports that it > cannot find the /lib/python1.5/config and > indeed there is no such directory in the python distribution > that I can see. Sorry for the delay -- I've been away on holiday, and then I took a few more days holiday from Distutils hacking (or reading the sig, or applying patches, or any of that stuff). Anyways -- has this problem been resolved? Bastian posted a patch in reply, but I wasn't clear if the patch was in any way related to your problem -- it just looked like a silly little typo fix. So are you still unable to install the Distutils? If the lib/python1.5/config directory doesn't exist, the Distutils are useless. Greg -- Greg Ward - Unix nerd gward@python.net http://starship.python.net/~gward/ Animals can be driven crazy by placing too many in too small a pen. Homo sapiens is the only animal that voluntarily does this to himself. From gward@python.net Thu Jul 27 02:51:29 2000 From: gward@python.net (Greg Ward) Date: Wed, 26 Jul 2000 21:51:29 -0400 Subject: [Distutils] sdist.py::findall chokes on broken links In-Reply-To: ; from calvin@cs.uni-sb.de on Fri, Jul 14, 2000 at 03:56:41PM +0200 References: <20000714093602.A28819@kronos.cnri.reston.va.us> Message-ID: <20000726215129.D1506@beelzebub> On 14 July 2000, Bastian Kleineidam said: > the findall function in sdist.py gives an error when a broken link is > found. The responsible function call is os.stat(). > > I replaced the stat() calls with os.path.{isfile,islink,isdir}. This is > somewhat more robust. The new findall is now a member function of the > sdist class so I can use self.announce to warn about broken links. I've looked into this a bit and decided it's a feature. (Ie., it'd be too hard to fix it properly.) It boils down to this: the 'findall()' routine in sdist.py isn't the only place that pokes about the filesystem looking for stuff; to do this right, we would have to detect dangling links in all such places. (The only other place I can think of offhand is in built_py.py, where we turn the packages listed in the 'packages' list into a list of filenames.) Or we could have a single function or class whose job it is to walk the filesystem looking for stuff: that's probably the right way, and the filesystem-searching code in sdist.py is general enough that it wouldn't take much to extract it and make it into something useful across the whole of the Distutils. But, on reflection, I'm not going to bother. In an ideal world, we'd warn about dangling links and then skip them. In a bad world, we'd include dangling links in tarballs. Blowing up when we hit dangling links isn't the best, but it isn't the worst either. Greg PS. what an appropriate fortune for this post... -- Greg Ward - maladjusted nerd gward@python.net http://starship.python.net/~gward/ Save energy: be apathetic. From calvin@cs.uni-sb.de Thu Jul 27 11:51:15 2000 From: calvin@cs.uni-sb.de (Bastian Kleineidam) Date: Thu, 27 Jul 2000 12:51:15 +0200 (CEST) Subject: [Distutils] sdist.py::findall chokes on broken links In-Reply-To: <20000726215129.D1506@beelzebub> Message-ID: Hello, if the Distutils bail out on broken links we will run into problems with Debian packages. I am calling the dh_undocumented script which generates the link debian/tmp/usr/share/man/man1/linkchecker.1.gz -> ../man7/undocumented.7.gz which is broken only temporarily, but not after installing the generated .deb package. Well, I will have to make symlinks with absolute pathnames.. Bastian From R.Liebscher@gmx.de Thu Jul 27 11:54:45 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Thu, 27 Jul 2000 12:54:45 +0200 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> <20000704101613.A1881@beelzebub> <396465FC.3FD96CAD@gmx.de> <20000708212019.A4248@beelzebub> <396C71A1.198D8C2C@gmx.de> <397A344D.E3837BD6@gmx.de> <20000726210640.A1506@beelzebub> Message-ID: <398014F5.728445EE@gmx.de> Greg Ward wrote: > > On 23 July 2000, Rene Liebscher said: > > In the latest cygwin binutils 2.10.90 is a bug in dllwrap. > > This new version of my patch tries now to find out the version > > numbers of gcc, ld and dllwrap, so we can inform the user > > if he is using a broken version of one of these programs. > > Ugh. I guess version-checking is slightly better than crashing, but I > hate that it's necessary. *grumble* There is no other way (except to have a own compiler class for every version.) In the latest version of cygwinccompiler.py all cygwin/mingw compilers I could test are now working. > ....., and submit your fix to bcppcompiler.py > separately from the other patches? *Then* I'll be able to comment > sensibly on it. > OK, here are now three patches: * msvc.patch: changes msvccompiler.py and build_ext.py (You need its changes in build_ext.py to get the other two compilers work properly after applying their patches.) * bcpp.patch: changes bcppcompiler.py * cygwin.patch: the latest version of cygwinccompiler.py, some changes in spawn.py (I moved a port of spawn_nt() in a separate function find_executable(), I use this in my compiler class) and it removes from sysconfig.py g['CC'] = "cc" and this other stuff which UnixCCompiler needed in its old version. And some cosmetic changes: Almost all messages start with a verb, but this one in install_lib.py starts with a noun. ####################### --- distutils.orig/distutils/command/install_lib.py +++ distutils.patched/distutils/command/install_lib.py @@ -74,7 +74,7 @@ out_fn = f + (__debug__ and "c" or "o") compile_msg = "byte-compiling %s to %s" % \ (f, os.path.basename (out_fn)) - skip_msg = "byte-compilation of %s skipped" % f + skip_msg = "skipping byte-compilation of %s" % f self.make_file (f, out_fn, compile, (f,), compile_msg, skip_msg) # run () ####################### Kind regards Rene Liebscher From R.Liebscher@gmx.de Thu Jul 27 11:57:15 2000 From: R.Liebscher@gmx.de (Rene Liebscher) Date: Thu, 27 Jul 2000 12:57:15 +0200 Subject: [Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler References: <395B7BA6.F65C24FA@gmx.de> <000401bfe1ed$0d778a60$2937ba8c@nhv> <20000629191650.D682@beelzebub> <395CB802.7CE487C@gmx.de> <20000704101613.A1881@beelzebub> <396465FC.3FD96CAD@gmx.de> <20000708212019.A4248@beelzebub> <396C71A1.198D8C2C@gmx.de> <397A344D.E3837BD6@gmx.de> <20000726210640.A1506@beelzebub> <398014F5.728445EE@gmx.de> Message-ID: <3980158B.32AC4D3C@gmx.de> This is a multi-part message in MIME format. --------------09D84941F7DE6AE76370E7A8 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Oops, I forgot to attach the patches. Here they are. Kind regards Rene Liebscher --------------09D84941F7DE6AE76370E7A8 Content-Type: text/plain; charset=us-ascii; name="msvc.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="msvc.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/command/build_ext.py d.px/distutils/command/build_ext.py --- distutils.orig/distutils/command/build_ext.py Thu Jul 27 09:52:46 2000 +++ d.px/distutils/command/build_ext.py Thu Jul 27 12:31:44 2000 @@ -84,7 +84,7 @@ help_options = [ ('help-compiler', None, "list available compilers", show_compilers), - ] + ] def initialize_options (self): self.extensions = None @@ -283,6 +283,9 @@ # Medium-easy stuff: same syntax/semantics, different names. ext.runtime_library_dirs = build_info.get('rpath') ext.export_symbol_file = build_info.get('def_file') + if ext.export_symbol_file is not None: + self.warn("export_symbol_file is no longer supported, " + "comments and questions to ") # Non-trivial stuff: 'macros' split into 'define_macros' # and 'undef_macros'. @@ -420,16 +423,14 @@ objects.extend (ext.extra_objects) extra_args = ext.extra_link_args or [] - # Bunch of fixing-up we have to do for Microsoft's linker. - if self.compiler.compiler_type == 'msvc': - self.msvc_prelink_hack(sources, ext, extra_args) self.compiler.link_shared_object ( objects, ext_filename, - libraries=ext.libraries, + libraries=self.get_libraries(ext), library_dirs=ext.library_dirs, runtime_library_dirs=ext.runtime_library_dirs, extra_postargs=extra_args, + export_symbols=self.get_export_symbols(ext), debug=self.debug, build_temp=self.build_temp) @@ -511,44 +512,6 @@ # find_swig () - - # -- Hooks 'n hacks ------------------------------------------------ - - def msvc_prelink_hack (self, sources, ext, extra_args): - - # XXX this is a kludge! Knowledge of specific compilers or - # platforms really doesn't belong here; in an ideal world, the - # CCompiler interface would provide access to everything in a - # compiler/linker system needs to build Python extensions, and - # we would just do everything nicely and cleanly through that - # interface. However, this is a not an ideal world and the - # CCompiler interface doesn't handle absolutely everything. - # Thus, kludges like this slip in occasionally. (This is no - # excuse for committing more platform- and compiler-specific - # kludges; they are to be avoided if possible!) - - def_file = ext.export_symbol_file - - if def_file is not None: - extra_args.append ('/DEF:' + def_file) - else: - modname = string.split (ext.name, '.')[-1] - extra_args.append('/export:init%s' % modname) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - implib_file = os.path.join ( - self.implib_dir, - self.get_ext_libname (ext.name)) - extra_args.append ('/IMPLIB:' + implib_file) - self.mkpath (os.path.dirname (implib_file)) - - # msvc_prelink_hack () - - # -- Name generators ----------------------------------------------- # (extension names, filenames, whatever) @@ -578,5 +541,33 @@ if os.name == 'nt' and self.debug: return apply (os.path.join, ext_path) + '_d.lib' return apply (os.path.join, ext_path) + '.lib' + + + def get_export_symbols (self, ext): + # For all platforms and compiler doesn't export all symbols + # by default, we have to specify the module's init function + # if the user doesn't provide any export information. + # All other platforms and compilers should ignore such + # export information. + if ext.export_symbols is None: + # if no exports are specified we can't build a working + # python module. + # so let us export the module's init function + return ["init" + string.split(ext.name,'.')[-1]] + else: + return ext.export_symbols + + def get_libraries (self, ext): + # The python library is always needed on Windows. + # We need the python version without the dot, eg. '15' + # MSVC doesn't really need this, because the pragma in config.h + if sys.platform == "win32": + pythonlib = ("python%d%d" % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] + else: + return ext.libraries # class build_ext diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/extension.py d.px/distutils/extension.py --- distutils.orig/distutils/extension.py Sat Jun 24 02:18:24 2000 +++ d.px/distutils/extension.py Thu Jul 27 12:31:44 2000 @@ -111,7 +111,7 @@ self.extra_objects = extra_objects or [] self.extra_compile_args = extra_compile_args or [] self.extra_link_args = extra_link_args or [] - self.export_symbols = export_symbols or [] + self.export_symbols = export_symbols self.export_symbol_file = export_symbol_file # class Extension diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/msvccompiler.py d.px/distutils/msvccompiler.py --- distutils.orig/distutils/msvccompiler.py Fri Jun 30 21:37:59 2000 +++ d.px/distutils/msvccompiler.py Thu Jul 27 12:31:44 2000 @@ -380,6 +380,17 @@ ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + dll_name, dll_ext = os.path.splitext(os.path.basename(output_filename)) + implib_file = os.path.join ( + os.path.dirname(objects[0]), + self.static_lib_format % (dll_name, self.static_lib_extension)) + ld_args.append ('/IMPLIB:' + implib_file) + if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: --------------09D84941F7DE6AE76370E7A8 Content-Type: text/plain; charset=us-ascii; name="bcpp.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="bcpp.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/bcppcompiler.py d.px/distutils/bcppcompiler.py --- distutils.orig/distutils/bcppcompiler.py Wed Jun 28 03:20:35 2000 +++ d.px/distutils/bcppcompiler.py Thu Jul 27 12:35:21 2000 @@ -11,17 +11,6 @@ # someone should sit down and factor out the common code as # WindowsCCompiler! --GPW -# XXX Lyle reports that this doesn't quite work yet: -# """...but this is what I've got so far. The compile step works fine but -# when it runs the link step I get an "out of memory" failure. Since -# spawn() echoes the command it's trying to spawn, I can type the link line -# verbatim at the DOS prompt and it links the Windows DLL correctly -- so -# the syntax is correct. There's just some weird interaction going on when -# it tries to "spawn" the link process from within the setup.py script. I'm -# not really sure how to debug this one right off-hand; obviously there's -# nothing wrong with the "spawn()" function since it's working properly for -# the compile stage.""" - __revision__ = "$Id: bcppcompiler.py,v 1.1 2000/06/28 01:20:35 gward Exp $" @@ -123,6 +112,9 @@ elif ext in self._cpp_extensions: input_opt = "-P" + src = os.path.normpath(src) + obj = os.path.normpath(obj) + output_opt = "-o" + obj self.mkpath (os.path.dirname (obj)) @@ -230,24 +222,56 @@ else: ldflags = self.ldflags_shared + # Borland C++ has problems with '/' in paths + objects = map(os.path.normpath,objects) + startup_obj = 'c0d32' - libraries.append ('mypylib') + # either exchange python15.lib in the python libs directory against + # a Borland-like one, or create one with name bcpp_python15.lib + # there and remove the pragmas from config.h + #libraries.append ('mypylib') libraries.append ('import32') libraries.append ('cw32mt') # Create a temporary exports file for use by the linker head, tail = os.path.split (output_filename) modname, ext = os.path.splitext (tail) - def_file = os.path.join (build_temp, '%s.def' % modname) + temp_dir = os.path.dirname(objects[0]) # preserve tree structure + def_file = os.path.join (temp_dir, '%s.def' % modname) f = open (def_file, 'w') f.write ('EXPORTS\n') for sym in (export_symbols or []): f.write (' %s=_%s\n' % (sym, sym)) + f.close() - ld_args = ldflags + [startup_obj] + objects + \ - [',%s,,' % output_filename] + \ - libraries + [',' + def_file] + # start building command line + # flags and options + ld_args = list(ldflags) # don't use a reference, use a separate copy + for l in library_dirs: + ld_args.append("/L%s" % os.path.normpath(l)) + # objects list + ld_args.extend([startup_obj]) + ld_args.extend(objects) + # name of dll file + ld_args.extend([',',output_filename]) + # no map file + ld_args.extend([',']) + # start libraries + ld_args.extend([',']) + for lib in libraries: + # see if we find it and if there is a bcpp specific lib + # (bcpp_xxx.lib) + l = self.find_library_file(library_dirs,lib,debug) + if l == None: + ld_args.append(lib) + # probably an bcpp internal library + # self.warn('library %s not found.' % lib) + else: + # full name which prefers bcpp_xxx.lib over xxx.lib + ld_args.append(l) + # def file for export symbols + ld_args.extend([',',def_file]) if extra_preargs: ld_args[:0] = extra_preargs @@ -325,15 +349,28 @@ def runtime_library_dir_option (self, dir): raise DistutilsPlatformError, \ - "don't know how to set runtime library search path for MSVC++" + "don't know how to set runtime library search path for Borland C++" def library_option (self, lib): return self.library_filename (lib) - def find_library_file (self, dirs, lib): - + def find_library_file (self, dirs, lib, debug=0): + # find library file + # bcpp_xxx.lib is better than xxx.lib + # and xxx_d.lib is better than xxx.lib if debug is set for dir in dirs: + if debug: + libfile = os.path.join (dir, self.library_filename ("bcpp_" + lib + "_d")) + if os.path.exists (libfile): + return libfile + libfile = os.path.join (dir, self.library_filename ("bcpp_" + lib)) + if os.path.exists (libfile): + return libfile + if debug: + libfile = os.path.join (dir, self.library_filename (lib + '_d')) + if os.path.exists (libfile): + return libfile libfile = os.path.join (dir, self.library_filename (lib)) if os.path.exists (libfile): return libfile --------------09D84941F7DE6AE76370E7A8 Content-Type: text/plain; charset=us-ascii; name="cygwin.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="cygwin.patch" diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/cygwinccompiler.py d.px/distutils/cygwinccompiler.py --- distutils.orig/distutils/cygwinccompiler.py Thu Jul 27 09:52:42 2000 +++ d.px/distutils/cygwinccompiler.py Thu Jul 27 12:19:55 2000 @@ -6,53 +6,53 @@ cygwin in no-cygwin mode). """ +# problems: +# +# * if you use a msvc compiled python version (1.5.2) +# 1. you have to insert a __GNUC__ section in its config.h +# 2. you have to generate a import library for its dll +# - create a def-file for python??.dll +# - create a import library using +# dlltool --dllname python15.dll --def python15.def \ +# --output-lib libpython15.a +# +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# +# * We use put export_symbols in a def-file, and don't use +# --export-all-symbols because it doesn't worked reliable in some +# tested configurations. And because other windows compilers also +# need their symbols specified this no serious problem. +# +# tested configurations: +# +# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works +# (after patching python's config.h and for C++ some other include files) +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works +# (ld doesn't support -shared, so we use dllwrap) +# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now +# - its dllwrap doesn't work, there is a bug in binutils 2.10.90 +# see also ..... +# - using gcc -mdll instead dllwrap doesn't work without -static because +# it tries to link against dlls instead their import libraries. (If +# it finds the dll first.) +# By specifying -static we force ld to link against the import libraries, +# this is windows standard and there are normally not the necessary symbols +# in the dlls. + # created 2000/05/05, Rene Liebscher __revision__ = "$Id: cygwinccompiler.py,v 1.3 2000/07/27 02:13:19 gward Exp $" -import os,sys,string -from distutils import sysconfig +import os,sys from distutils.unixccompiler import UnixCCompiler -# Because these compilers aren't configured in Python's config.h file by -# default we should at least warn the user if he is using a unmodified -# version. - -def check_config_h(): - """Checks if the GCC compiler is mentioned in config.h. If it is not, - compiling probably doesn't work, so print a warning to stderr. - """ - - # XXX the result of the check should be returned! - - from distutils import sysconfig - import string,sys - try: - # It would probably better to read single lines to search. - # But we do this only once, and it is fast enough - f=open(sysconfig.get_config_h_filename()) - s=f.read() - f.close() - try: - # is somewhere a #ifdef __GNUC__ or something similar - string.index(s,"__GNUC__") - except ValueError: - sys.stderr.write ("warning: "+ - "Python's config.h doesn't seem to support your compiler.\n") - except IOError: - # if we can't read this file, we cannot say it is wrong - # the compiler will complain later about this file as missing - pass - - -# This is called when the module is imported, so we make this check only once -# XXX why not make it only when the compiler is needed? -check_config_h() - - class CygwinCCompiler (UnixCCompiler): compiler_type = 'cygwin' + gcc_version = None + dllwrap_version = None + ld_version = None def __init__ (self, verbose=0, @@ -61,22 +61,43 @@ UnixCCompiler.__init__ (self, verbose, dry_run, force) + if check_config_h()<=0: + self.warn( + "Python's config.h doesn't seem to support your compiler. " + "Compiling may fail because of undefined preprocessor macros.") + + self.gcc_version, self.ld_version, self.dllwrap_version = get_versions() + sys.stderr.write(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" % + (self.gcc_version, + self.ld_version, + self.dllwrap_version) ) + + # ld_version >= "2.10.90" should also be able to use + # gcc -mdll instead of dllwrap + # Older dllwraps had own version numbers, newer ones use the + # same as the rest of binutils ( also ld ) + # dllwrap 2.10.90 is buggy + if self.ld_version >= "2.10.90": + self.linker = "gcc" + else: + self.linker = "dllwrap" + # Hard-code GCC because that's what this is all about. # XXX optimization, warnings etc. should be customizable. - self.set_executables(compiler='gcc -O -Wall', - compiler_so='gcc -O -Wall', - linker_exe='gcc', - linker_so='dllwrap --target=i386-cygwin32') + self.set_executables(compiler='gcc -mcygwin -O -Wall', + compiler_so='gcc -mcygwin -mdll -O -Wall', + linker_exe='gcc -mcygwin', + linker_so=('%s -mcygwin -mdll -static' % self.linker)) # cygwin and mingw32 need different sets of libraries - self.dll_libraries=[ - # cygwin shouldn't need msvcrt, - # but without the dll's will crash - # ( gcc version 2.91.57 ) - # perhaps something about initialization - # mingw32 needs it in all cases - "msvcrt" - ] + if self.gcc_version == "2.91.57": + # cygwin shouldn't need msvcrt, but without the dlls will crash + # ( gcc version 2.91.57 ) perhaps something about initialization + self.dll_libraries=["msvcrt"] + self.warn( + "You should think over switching to a newer version of gcc") + else: + self.dll_libraries=[] # __init__ () @@ -93,64 +114,65 @@ extra_postargs=None, build_temp=None): - if libraries == None: - libraries = [] + # use seperate copies, so can modify the lists + extra_preargs = list(extra_preargs or []) + libraries = list(libraries or []) - # Additional libraries: the python library is always needed on - # Windows we need the python version without the dot, eg. '15' - - pythonlib = ("python%d%d" % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - libraries.append(pythonlib) + # Additional libraries libraries.extend(self.dll_libraries) + + # we want to put some files in the same directory as the + # object files are, build_temp doesn't help much - # name of extension + # where are the object files + temp_dir = os.path.dirname(objects[0]) - # XXX WRONG WRONG WRONG - # this is NOT the place to make guesses about Python namespaces; - # that MUST be done in build_ext.py + # name of dll to give the helper files (def, lib, exp) the same name + dll_name,dll_extension = os.path.splitext(os.path.basename(output_filename)) - if not debug: - ext_name = os.path.basename(output_filename)[:-len(".pyd")] - else: - ext_name = os.path.basename(output_filename)[:-len("_d.pyd")] + # generate the filenames for these files + def_file = None # this will be done later, if necessary + exp_file = os.path.join(temp_dir, dll_name + ".exp") + lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a") - def_file = os.path.join(build_temp, ext_name + ".def") - #exp_file = os.path.join(build_temp, ext_name + ".exp") - #lib_file = os.path.join(build_temp, 'lib' + ext_name + ".a") - - # Make .def file - # (It would probably better to check if we really need this, - # but for this we had to insert some unchanged parts of - # UnixCCompiler, and this is not what we want.) - f = open(def_file,"w") - f.write("EXPORTS\n") # intro - if export_symbols == None: - # export a function "init" + ext_name - f.write("init" + ext_name + "\n") + #extra_preargs.append("--verbose") + if self.linker == "dllwrap": + extra_preargs.extend([#"--output-exp",exp_file, + "--output-lib",lib_file, + ]) else: - # if there are more symbols to export write them into f + # doesn't work: bfd_close build\...\libfoo.a: Invalid operation + extra_preargs.extend([#"-Wl,--out-implib,%s" % lib_file, + ]) + + # check what we got in export_symbols + if export_symbols is not None: + # Make .def file + # (It would probably better to check if we really need this, + # but for this we had to insert some unchanged parts of + # UnixCCompiler, and this is not what we want.) + def_file = os.path.join(temp_dir, dll_name + ".def") + f = open(def_file,"w") + f.write("LIBRARY %s\n" % os.path.basename(output_filename)) + f.write("EXPORTS\n") # intro for sym in export_symbols: f.write(sym+"\n") - f.close() - - if extra_preargs == None: - extra_preargs = [] - - extra_preargs = extra_preargs + [ - #"--verbose", - #"--output-exp",exp_file, - #"--output-lib",lib_file, - "--def",def_file - ] - + f.close() + + if def_file: + if self.linker == "dllwrap": + # for dllwrap we have to use a special option + extra_preargs.append("--def") + # for gcc/ld it is specified as any other object file + extra_preargs.append(def_file) + # who wants symbols and a many times larger output file # should explicitly switch the debug mode on - # otherwise we let dllwrap strip the output file + # otherwise we let dllwrap/ld strip the output file # (On my machine unstripped_file = stripped_file + 254KB # 10KB < stripped_file < ??100KB ) if not debug: - extra_preargs = extra_preargs + ["-s"] + extra_preargs.append("-s") UnixCCompiler.link_shared_object(self, objects, @@ -159,7 +181,7 @@ libraries, library_dirs, runtime_library_dirs, - None, # export_symbols, we do this with our def-file + None, # export_symbols, we do this in our def-file debug, extra_preargs, extra_postargs, @@ -181,19 +203,115 @@ force=0): CygwinCCompiler.__init__ (self, verbose, dry_run, force) + + # a real mingw32 doesn't need to specify a different entry point + # but cygwin 2.91.57 in no-cygwin-mode needs it + if self.gcc_version <= "2.91.57": + entry_point = '--entry _DllMain@12' + else: + entry_point = '' self.set_executables(compiler='gcc -mno-cygwin -O -Wall', - compiler_so='gcc -mno-cygwin -O -Wall', + compiler_so='gcc -mno-cygwin -mdll -O -Wall', linker_exe='gcc -mno-cygwin', - linker_so='dllwrap' - + ' --target=i386-mingw32' - + ' --entry _DllMain@12') - # mingw32 doesn't really need 'target' and cygwin too (it seems, - # it is enough to specify a different entry point) - - # no additional libraries need - # (only msvcrt, which is already added by CygwinCCompiler) - + linker_so='%s -mno-cygwin -mdll -static %s' + % (self.linker, entry_point)) + # Maybe we should also append -mthreads, but then the finished + # dlls need another dll (mingwm10.dll see Mingw32 docs) + # (-mthreads: Support thread-safe exception handling on `Mingw32') + + # no additional libraries needed + self.dll_libraries=[] + # __init__ () - + # class Mingw32CCompiler + +# Because these compilers aren't configured in Python's config.h file by +# default, we should at least warn the user if he is using a unmodified +# version. + +def check_config_h(): + """Checks if the GCC compiler is mentioned in config.h. If it is not, + compiling probably doesn't work. + """ + # return values + # 2: OK, python was compiled with GCC + # 1: OK, python's config.h mentions __GCC__ + # 0: uncertain, because we couldn't check it + # -1: probably not OK, because we didn't found it in config.h + # You could check check_config_h()>0 => OK + + from distutils import sysconfig + import string,sys + # if sys.version contains GCC then python was compiled with + # GCC, and the config.h file should be OK + if -1 == string.find(sys.version,"GCC"): + pass # go to the next test + else: + return 2 + + try: + # It would probably better to read single lines to search. + # But we do this only once, and it is fast enough + f=open(sysconfig.get_config_h_filename()) + s=f.read() + f.close() + + # is somewhere a #ifdef __GNUC__ or something similar + if -1 == string.find(s,"__GNUC__"): + return -1 + else: + return 1 + except IOError: + # if we can't read this file, we cannot say it is wrong + # the compiler will complain later about this file as missing + pass + return 0 + +def get_versions(): + """ Try to find out the versions of gcc, ld and dllwrap. + If not possible it returns None for it. + """ + from distutils.version import StrictVersion + from distutils.spawn import find_executable + import re + + gcc_exe = find_executable('gcc') + if gcc_exe: + out = os.popen(gcc_exe + ' -dumpversion','r') + out_string = out.read() + out.close() + result = re.search('(\d+\.\d+\.\d+)',out_string) + if result: + gcc_version = StrictVersion(result.group(1)) + else: + gcc_version = None + else: + gcc_version = None + ld_exe = find_executable('ld') + if ld_exe: + out = os.popen(ld_exe + ' -v','r') + out_string = out.read() + out.close() + result = re.search('(\d+\.\d+\.\d+)',out_string) + if result: + ld_version = StrictVersion(result.group(1)) + else: + ld_version = None + else: + ld_version = None + dllwrap_exe = find_executable('dllwrap') + if dllwrap_exe: + out = os.popen(dllwrap_exe + ' --version','r') + out_string = out.read() + out.close() + result = re.search(' (\d+\.\d+\.\d+)',out_string) + if result: + dllwrap_version = StrictVersion(result.group(1)) + else: + dllwrap_version = None + else: + dllwrap_version = None + return (gcc_version, ld_version, dllwrap_version) + diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/spawn.py d.px/distutils/spawn.py --- distutils.orig/distutils/spawn.py Sun Mar 26 23:47:00 2000 +++ d.px/distutils/spawn.py Thu Jul 27 12:29:03 2000 @@ -1,7 +1,9 @@ """distutils.spawn Provides the 'spawn()' function, a front-end to various platform- -specific functions for launching another program in a sub-process.""" +specific functions for launching another program in a sub-process. +Also provides the 'find_executable()' to search the path for a given +executable name. """ # created 1999/07/24, Greg Ward @@ -65,17 +67,8 @@ executable = cmd[0] cmd = _nt_quote_args (cmd) if search_path: - paths = string.split( os.environ['PATH'], os.pathsep) - base,ext = os.path.splitext(executable) - if (ext != '.exe'): - executable = executable + '.exe' - if not os.path.isfile(executable): - paths.reverse() # go over the paths and keep the last one - for p in paths: - f = os.path.join( p, executable ) - if os.path.isfile ( f ): - # the file exists, we have a shot at spawn working - executable = f + # either we find one or it stays the same + executable = find_executable(executable) or executable if verbose: print string.join ([executable] + cmd[1:], ' ') if not dry_run: @@ -91,7 +84,6 @@ raise DistutilsExecError, \ "command '%s' failed with exit status %d" % (cmd[0], rc) - def _spawn_posix (cmd, search_path=1, @@ -147,3 +139,24 @@ "unknown error executing '%s': termination status %d" % \ (cmd[0], status) # _spawn_posix () + + +def find_executable(executable): + """ Tries to find executable in the directories listed in PATH. + Returns the complete filename or None if not found. """ + + paths = string.split( os.environ['PATH'], os.pathsep) + base,ext = os.path.splitext(executable) + if (sys.platform == 'win32') and (ext != '.exe'): + executable = executable + '.exe' + if not os.path.isfile(executable): + for p in paths: + f = os.path.join( p, executable ) + if os.path.isfile ( f ): + # the file exists, we have a shot at spawn working + return f + return None + else: + return executable + +# find_executable() diff -BurN --minimal --exclude=*.pyc distutils.orig/distutils/sysconfig.py d.px/distutils/sysconfig.py --- distutils.orig/distutils/sysconfig.py Tue Jun 27 03:59:43 2000 +++ d.px/distutils/sysconfig.py Thu Jul 27 12:29:03 2000 @@ -267,24 +267,8 @@ g['INCLUDEPY'] = get_python_inc(plat_specific=0) g['SO'] = '.pyd' - g['exec_prefix'] = EXEC_PREFIX - - # These are needed for the CygwinCCompiler and Mingw32CCompiler - # classes, which are just UnixCCompiler classes that happen to work on - # Windows. UnixCCompiler expects to find these values in sysconfig, so - # here they are. The fact that other Windows compilers don't need - # these values is pure luck (hmmm). - - # XXX I think these are now unnecessary... - - g['CC'] = "cc" # not gcc? - g['RANLIB'] = "ranlib" - g['AR'] = "ar" - g['OPT'] = "-O2" - g['SO'] = ".pyd" - g['LDSHARED'] = "ld" - g['CCSHARED'] = "" g['EXE'] = ".exe" + g['exec_prefix'] = EXEC_PREFIX def _init_mac(): --------------09D84941F7DE6AE76370E7A8-- From gward@python.net Sun Jul 30 02:57:20 2000 From: gward@python.net (Greg Ward) Date: Sat, 29 Jul 2000 21:57:20 -0400 Subject: [Distutils] New code snapshot Message-ID: <20000729215720.A1465@beelzebub> Hi all -- I've just put together a new code snapshot. This fixes all the little bugs that have dribbled in over the last week or so, and also adds Rene Liebscher's refactoring of the file-list-generation code from sdist.py to a new class in a new module (FileList, in filelist.py -- renamed from Template in Rene's patch). Please give it a whirl -- this code will most likely become Distutils 0.9.1 to get the bug fixes out there fairly quickly (ie. without adding Rene's latest changes to various Windows compiler classes -- that can wait for 0.9.2). Oh yeah, it's at http://starship.python.net/~gward/python/distutils.html Greg -- Greg Ward - programmer-at-big gward@python.net http://starship.python.net/~gward/ What happens if you touch these two wires tog-- From webmaster@lookelu.com Sun Jul 30 09:36:21 2000 From: webmaster@lookelu.com (The Western Web) Date: Sun, 30 Jul 2000 08:36:21 Subject: [Distutils] The Western Web Newsletter Message-ID: <20000730153421.692471CDEB@dinsdale.python.org> THE WESTERN WEB WEEKLY NEWS LETTER Week of July 24, 2000 Serving Over 75000 Recipients With your assistance "The Western Web" continues to improve and your input is helpful.Our goal is to make "The Western Web" THE one place stop for all your Horse, Livestock and Western Life Style needs. If You have added your site to our search engine, please make sure everything is correct. If you haven't noticed we have upgraded the look and capabilities of The Western Web search engine. You can now type in your search word and find all related site links. Don't forget to add your Web Site to our search engine too. http://www.searchthewesternweb.com This week you might take a look at our "Events Calendar" in our Classified Ad section. You can post your upcoming events in subcategories such as: Events, Shows, Cuttings, Team Roping, Gymkhana, Clinics, Trail, Auctions, Rodeos, Reining, Barrel Racing, Team Penning and Performance & Halter. We also have a subcategory for "Other" to place any event not categorized. These ads are free and you can add pictures, video and audio. A note to our subscribers who have posted ads, with you User Name and Password you can update your events. http://www.westernwebclassified.com/cgi-bin/classifieds/classifieds.cgi At last, an online service available with the horse lover in mind, The Sale Barn.Com (www.thesalebarn.com). The Sale Barn offers an online auction specifically for horse-related items, whether you are buying or selling. The Sale Barn auctions off 100s of items daily with many items in the Hot Items Listing starting at $1.00! Usually there are from 150 to 200 items starting at only $1.00. From saddles, bridles, bits, spurs and unique gift items. Register now to qualify for our weekly drawing. The current prize is a 34 x 36 Wool Blend Show Blanket with wear leathers and silver conchos valued at $99.95! This item is featured on our Home Page at www.thesalebarn.com. Registration is free on our secure site with no credit card necessary. The Sale Barn is amongst the top 10 visited horse sites on the Internet with over 10,000 hits a day. A perfect opportunity to turn unneeded horse related items in to cash. The Sale Barn is the ebay of the horse world with categories directed to specific items such as saddles, headstalls, bits, spurs, ropes, gift items, horse trailers, etc. http://www.thesalebarn.com We appreciate you patronizing our sponsors. You to can have your web site on our front page along with Banks Power, Roo-hyde Saddlery, GMC, Bootbarn.com,Truckloads.net, Zig Zigler, Comforce, The Gaited Horse, Cowboy Tack, Painted Acres Ranch,The ShawnOshine,Tom Balding Bits & Spurs, Centenary of Federation and Stoxrus.com. You can find our reasonable rates at: http://www.thewesternweb.com/Advertising/Advertising.htm While at The Western Web site take a look at our message board: http://www.westernmessageboard.com/cgi-bin/Ultimate.cgi We can Design & Host your web site. Check out our low domain name registration prices at: http://www.thewesternweb.com/Web_Design/Domain_Name_Registration.htm For you convenience, there are links to these sites and more, from The Western Web Home Page. http://www.thewesternweb.com/ If you receive this message in error or want us to remove you from our newsletter e-mail list, please reply to this email address with the word "Remove" in the subject line. Thank You, http://www.thewesternweb.com