summaryrefslogtreecommitdiffstats
path: root/Lib/distutils/cygwinccompiler.py
blob: cc2ed5db667c9cfbd2be174530ae4ac7be37dafa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
"""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$"

import os,sys,string,tempfile
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 used this unmodified version. 
def check_if_config_h_is_gcc_ready():
        """ 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:
                        string.index(s,"__GNUC__") # is somewhere a #ifdef __GNUC__ or something similar
                except:
                        sys.stderr.write ("warning: Python's config.h doesn't seem to support your compiler.\n")
        except: # unspecific error => ignore
                pass


# This is called when the module is imported, so we make this check only once
check_if_config_h_is_gcc_ready()


# 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
	self.cc='gcc'
	self.ld_shared='dllwrap'
	self.ldflags_shared=[]

        # some variables to manage the differences between cygwin and mingw32
        self.dllwrap_options=["--target=i386-cygwin32"]
        # specification of entry point is not necessary
        
        self.dll_additional_libraries=[
               # cygwin shouldn't need msvcrt, but without the dll's will crash
               # perhaps something about initialization (Python uses it, too)
               # 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):
        
        if libraries==None:
                libraries=[]
        
        python_library=["python"+str(sys.hexversion>>24)+str((sys.hexversion>>16)&0xff)]
        libraries=libraries+python_library+self.dll_additional_libraries
        
        # if you don't need the def-file afterwards, it is
        # better to use for it tempfile.mktemp() as its name
        # (unix-style compilers don't like backslashes in filenames)
        win_dll_def_file=string.replace(tempfile.mktemp(),"\\","/")
        #win_dll_def_file=output_filename[:-len(self.shared_lib_extension)]+".def"
        #win_dll_exp_file=output_filename[:-len(self.shared_lib_extension)]+".exp"
        #win_dll_lib_file=output_filename[:-len(self.shared_lib_extension)]+".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 I want.) 
        f=open(win_dll_def_file,"w")
        f.write("EXPORTS\n") # intro
        # always export a function "init"+module_name
        if not debug:
                f.write("init"+os.path.basename(output_filename)[:-len(self.shared_lib_extension)]+"\n")
        else: # in debug mode outfile_name is something like XXXXX_d.pyd
                f.write("init"+os.path.basename(output_filename)[:-(len(self.shared_lib_extension)+2)]+"\n")
        # if there are more symbols to export
        # insert code here to write them in f
        if export_symbols!=None: 
            for sym in export_symbols:
                f.write(sym+"\n")                
        f.close()
        
        if extra_preargs==None:
                extra_preargs=[]
        
        extra_preargs=extra_preargs+[
                        #"--verbose",
                        #"--output-exp",win_dll_exp_file,
                        #"--output-lib",win_dll_lib_file,
                        "--def",win_dll_def_file
                        ]+ self.dllwrap_options
        
        # who wants symbols and a many times greater output file
        # should explicitely switch the debug mode on 
        # otherwise we let dllwrap strip the outputfile
        # (On my machine unstripped_file=stripped_file+254KB
        #   10KB < stripped_file < ??100KB ) 
        if not debug: 
                extra_preargs=extra_preargs+["-s"] 
	
	try:        
    	    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)
        finally: 
    	    # we don't need the def-file anymore
    	    os.remove(win_dll_def_file) 
        
    # 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.ccflags = self.ccflags + ["-mno-cygwin"]
        self.dllwrap_options=[
                                # mingw32 doesn't really need 'target' 
                                # and cygwin too (it seems, it is enough
                                # to specify a different entry point)                
                                #"--target=i386-mingw32",
                                "--entry","_DllMain@12"
                                ]
        # no additional libraries need 
        # (only msvcrt, which is already added by CygwinCCompiler)

    # __init__ ()
                
# class Mingw32CCompiler