[Distutils] Re: CygwinCCompiler, msvc hack, BCPPCompiler

Rene Liebscher R.Liebscher@gmx.de
Thu, 29 Jun 2000 18:39:02 +0200


This is a multi-part message in MIME format.
--------------CEAF3E0844BC03C09B03A5C1
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

---- CygwinCCompiler ------------

OK, it should now be better to read. I also included your other changes
(set_executables, build_temp.)

----- msvc hack -----------

I also had a look at this msvc hack in build_ext. I think it is now
possible
to get rid of it. It does several things which could be done in an other 
way or shouldn't be done at all.

First, it tries to find a def-file in the source directory if 
none is given. I think one should specify this explicitely, who
knows if it is really the right file and moreover it overwrites
any export_symbols given to Extension().

Then it uses the module_name to create an export directive 
for the procedure 'init{modulename}'. It is possible to extract
this name from the output filename (see (bcpp|cygwin)compiler.py )
I think this export parameter should be only used if neither a def
file nor a list of symbols is given. (Then you could use your compiler
classes also for non python dll's by specifying [] as export_symbols
list.) 

And finally it uses the build_temp path for it implib directive.
We have now this new extra parameter to link_shared_library, so
this is also not a problem.   


When I looked at the code of build_ext I found you are not using 
export_symbols as parameter to link_shared_object. Also you are not 
using any of this export_* values from the Extension class.
This should be changed. But there is one point which is not clear.
There is no parameter at link_shared_object for export_symbols_file.
Either we add this or we change the semantics of the existing
export_symbols a bit.

* export_symbols == None : no export symbols given => add init{module}
* type(export_symbols) == ListType : export all symbols from this list
* type(export_symbols) == StringType : take this as a filename of a def
file

------ bcppcompiler -------------

Which version of Borland C you need to use it?
I tried BC5. It doesn't have a linker named ilink32 (?)
and it doesn't accept some of your parameters
/q for bcc32 and  /Gn /q for the linker (tlink32).
Also it is using mypylib, which probably the 
stub library for python15.dll . Is this library
somewhere to download or how can I create it?

My BC version doesn't include files if they are
in the source directory
( src/foo.c includes "foo.h" which is really src/foo.h )
so I had to specify this as an include_dir (-Isrc).
If all versions of BC do the same, the directories
of the source files should append to include_dir
in the bcppcompiler class.



Kind regards

Rene Liebscher
--------------CEAF3E0844BC03C09B03A5C1
Content-Type: text/plain; charset=us-ascii; name="cygwinccompiler.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="cygwinccompiler.py"

"""distutils.cygwinccompiler

Contains the CygwinCCompiler class, a subclass of UnixCCompiler that handles
the Gnu Win32 C compiler.
It also contains the Mingw32CCompiler class which handles the mingw32 compiler
(same as cygwin in no-cygwin mode.)

"""

# created 2000/05/05, Rene Liebscher

__revision__ = "$Id: cygwinccompiler.py,v 1.1 2000/06/21 03:33:03 gward Exp $"

import os,sys,string
from distutils import sysconfig
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 """ 
    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
check_config_h()


# XXX Things not currently handled:
#   * see UnixCCompiler

class CygwinCCompiler (UnixCCompiler):

    compiler_type = 'cygwin'
   
    def __init__ (self,
                  verbose=0,
                  dry_run=0,
                  force=0):

        UnixCCompiler.__init__ (self, verbose, dry_run, force)

        # our compiler uses other names
        # dllwrap: specification of entry point is not necessary
        self.set_executables(compiler='gcc -O -Wall',
                             compiler_so='gcc -O -Wall',
                             linker_exe='gcc',
                             linker_so='dllwrap --target=i386-cygwin32')

        # 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"
                            ]
        
    # __init__ ()

    def link_shared_object (self,
                            objects,
                            output_filename,
                            output_dir=None,
                            libraries=None,
                            library_dirs=None,
                            runtime_library_dirs=None,
                            export_symbols=None,
                            debug=0,
                            extra_preargs=None,
                            extra_postargs=None,
                            build_temp=None):
        
        if libraries == None:
            libraries = []
        
        # additional libraries
        # the python library is always needed on Windows
        # we need the python version without the dot, eg. '15' 
        libraries = libraries + [
           "python%d%d" % ( sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)
                                ] + self.dll_libraries

        # name of extension
        if not debug:
            ext_name = os.path.basename(output_filename)[:-len(".pyd")]
        else:
            ext_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")
        
        # 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
            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
                        ]
        
        # who wants symbols and a many times larger output file
        # should explicitely switch the debug mode on 
        # otherwise we let dllwrap strip the output file
        # (On my machine unstripped_file = stripped_file + 254KB
        #   10KB < stripped_file < ??100KB ) 
        if not debug: 
            extra_preargs = extra_preargs + ["-s"] 
        
        UnixCCompiler.link_shared_object(self,
                            objects,
                            output_filename,
                            output_dir,
                            libraries,
                            library_dirs,
                            runtime_library_dirs,
                            None, # export_symbols, we do this with our def-file
                            debug,
                            extra_preargs,
                            extra_postargs,
                            build_temp)
        
    # link_shared_object ()

# class CygwinCCompiler

# the same as cygwin plus some additional parameters
class Mingw32CCompiler (CygwinCCompiler):

    compiler_type = 'mingw32'

    def __init__ (self,
                  verbose=0,
                  dry_run=0,
                  force=0):

        CygwinCCompiler.__init__ (self, verbose, dry_run, force)

        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)                

        # no additional libraries need 
        # (only msvcrt, which is already added by CygwinCCompiler)

    # __init__ ()
                
# class Mingw32CCompiler

--------------CEAF3E0844BC03C09B03A5C1--