]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/distutils/emxccompiler.py
AppPkg/Applications/Python: Add Python 2.7.2 sources since the release of Python...
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / distutils / emxccompiler.py
CommitLineData
4710c53d 1"""distutils.emxccompiler\r
2\r
3Provides the EMXCCompiler class, a subclass of UnixCCompiler that\r
4handles the EMX port of the GNU C compiler to OS/2.\r
5"""\r
6\r
7# issues:\r
8#\r
9# * OS/2 insists that DLLs can have names no longer than 8 characters\r
10# We put export_symbols in a def-file, as though the DLL can have\r
11# an arbitrary length name, but truncate the output filename.\r
12#\r
13# * only use OMF objects and use LINK386 as the linker (-Zomf)\r
14#\r
15# * always build for multithreading (-Zmt) as the accompanying OS/2 port\r
16# of Python is only distributed with threads enabled.\r
17#\r
18# tested configurations:\r
19#\r
20# * EMX gcc 2.81/EMX 0.9d fix03\r
21\r
22__revision__ = "$Id$"\r
23\r
24import os,sys,copy\r
25from distutils.ccompiler import gen_preprocess_options, gen_lib_options\r
26from distutils.unixccompiler import UnixCCompiler\r
27from distutils.file_util import write_file\r
28from distutils.errors import DistutilsExecError, CompileError, UnknownFileError\r
29from distutils import log\r
30\r
31class EMXCCompiler (UnixCCompiler):\r
32\r
33 compiler_type = 'emx'\r
34 obj_extension = ".obj"\r
35 static_lib_extension = ".lib"\r
36 shared_lib_extension = ".dll"\r
37 static_lib_format = "%s%s"\r
38 shared_lib_format = "%s%s"\r
39 res_extension = ".res" # compiled resource file\r
40 exe_extension = ".exe"\r
41\r
42 def __init__ (self,\r
43 verbose=0,\r
44 dry_run=0,\r
45 force=0):\r
46\r
47 UnixCCompiler.__init__ (self, verbose, dry_run, force)\r
48\r
49 (status, details) = check_config_h()\r
50 self.debug_print("Python's GCC status: %s (details: %s)" %\r
51 (status, details))\r
52 if status is not CONFIG_H_OK:\r
53 self.warn(\r
54 "Python's pyconfig.h doesn't seem to support your compiler. " +\r
55 ("Reason: %s." % details) +\r
56 "Compiling may fail because of undefined preprocessor macros.")\r
57\r
58 (self.gcc_version, self.ld_version) = \\r
59 get_versions()\r
60 self.debug_print(self.compiler_type + ": gcc %s, ld %s\n" %\r
61 (self.gcc_version,\r
62 self.ld_version) )\r
63\r
64 # Hard-code GCC because that's what this is all about.\r
65 # XXX optimization, warnings etc. should be customizable.\r
66 self.set_executables(compiler='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',\r
67 compiler_so='gcc -Zomf -Zmt -O3 -fomit-frame-pointer -mprobe -Wall',\r
68 linker_exe='gcc -Zomf -Zmt -Zcrtdll',\r
69 linker_so='gcc -Zomf -Zmt -Zcrtdll -Zdll')\r
70\r
71 # want the gcc library statically linked (so that we don't have\r
72 # to distribute a version dependent on the compiler we have)\r
73 self.dll_libraries=["gcc"]\r
74\r
75 # __init__ ()\r
76\r
77 def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):\r
78 if ext == '.rc':\r
79 # gcc requires '.rc' compiled to binary ('.res') files !!!\r
80 try:\r
81 self.spawn(["rc", "-r", src])\r
82 except DistutilsExecError, msg:\r
83 raise CompileError, msg\r
84 else: # for other files use the C-compiler\r
85 try:\r
86 self.spawn(self.compiler_so + cc_args + [src, '-o', obj] +\r
87 extra_postargs)\r
88 except DistutilsExecError, msg:\r
89 raise CompileError, msg\r
90\r
91 def link (self,\r
92 target_desc,\r
93 objects,\r
94 output_filename,\r
95 output_dir=None,\r
96 libraries=None,\r
97 library_dirs=None,\r
98 runtime_library_dirs=None,\r
99 export_symbols=None,\r
100 debug=0,\r
101 extra_preargs=None,\r
102 extra_postargs=None,\r
103 build_temp=None,\r
104 target_lang=None):\r
105\r
106 # use separate copies, so we can modify the lists\r
107 extra_preargs = copy.copy(extra_preargs or [])\r
108 libraries = copy.copy(libraries or [])\r
109 objects = copy.copy(objects or [])\r
110\r
111 # Additional libraries\r
112 libraries.extend(self.dll_libraries)\r
113\r
114 # handle export symbols by creating a def-file\r
115 # with executables this only works with gcc/ld as linker\r
116 if ((export_symbols is not None) and\r
117 (target_desc != self.EXECUTABLE)):\r
118 # (The linker doesn't do anything if output is up-to-date.\r
119 # So it would probably better to check if we really need this,\r
120 # but for this we had to insert some unchanged parts of\r
121 # UnixCCompiler, and this is not what we want.)\r
122\r
123 # we want to put some files in the same directory as the\r
124 # object files are, build_temp doesn't help much\r
125 # where are the object files\r
126 temp_dir = os.path.dirname(objects[0])\r
127 # name of dll to give the helper files the same base name\r
128 (dll_name, dll_extension) = os.path.splitext(\r
129 os.path.basename(output_filename))\r
130\r
131 # generate the filenames for these files\r
132 def_file = os.path.join(temp_dir, dll_name + ".def")\r
133\r
134 # Generate .def file\r
135 contents = [\r
136 "LIBRARY %s INITINSTANCE TERMINSTANCE" % \\r
137 os.path.splitext(os.path.basename(output_filename))[0],\r
138 "DATA MULTIPLE NONSHARED",\r
139 "EXPORTS"]\r
140 for sym in export_symbols:\r
141 contents.append(' "%s"' % sym)\r
142 self.execute(write_file, (def_file, contents),\r
143 "writing %s" % def_file)\r
144\r
145 # next add options for def-file and to creating import libraries\r
146 # for gcc/ld the def-file is specified as any other object files\r
147 objects.append(def_file)\r
148\r
149 #end: if ((export_symbols is not None) and\r
150 # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):\r
151\r
152 # who wants symbols and a many times larger output file\r
153 # should explicitly switch the debug mode on\r
154 # otherwise we let dllwrap/ld strip the output file\r
155 # (On my machine: 10KB < stripped_file < ??100KB\r
156 # unstripped_file = stripped_file + XXX KB\r
157 # ( XXX=254 for a typical python extension))\r
158 if not debug:\r
159 extra_preargs.append("-s")\r
160\r
161 UnixCCompiler.link(self,\r
162 target_desc,\r
163 objects,\r
164 output_filename,\r
165 output_dir,\r
166 libraries,\r
167 library_dirs,\r
168 runtime_library_dirs,\r
169 None, # export_symbols, we do this in our def-file\r
170 debug,\r
171 extra_preargs,\r
172 extra_postargs,\r
173 build_temp,\r
174 target_lang)\r
175\r
176 # link ()\r
177\r
178 # -- Miscellaneous methods -----------------------------------------\r
179\r
180 # override the object_filenames method from CCompiler to\r
181 # support rc and res-files\r
182 def object_filenames (self,\r
183 source_filenames,\r
184 strip_dir=0,\r
185 output_dir=''):\r
186 if output_dir is None: output_dir = ''\r
187 obj_names = []\r
188 for src_name in source_filenames:\r
189 # use normcase to make sure '.rc' is really '.rc' and not '.RC'\r
190 (base, ext) = os.path.splitext (os.path.normcase(src_name))\r
191 if ext not in (self.src_extensions + ['.rc']):\r
192 raise UnknownFileError, \\r
193 "unknown file type '%s' (from '%s')" % \\r
194 (ext, src_name)\r
195 if strip_dir:\r
196 base = os.path.basename (base)\r
197 if ext == '.rc':\r
198 # these need to be compiled to object files\r
199 obj_names.append (os.path.join (output_dir,\r
200 base + self.res_extension))\r
201 else:\r
202 obj_names.append (os.path.join (output_dir,\r
203 base + self.obj_extension))\r
204 return obj_names\r
205\r
206 # object_filenames ()\r
207\r
208 # override the find_library_file method from UnixCCompiler\r
209 # to deal with file naming/searching differences\r
210 def find_library_file(self, dirs, lib, debug=0):\r
211 shortlib = '%s.lib' % lib\r
212 longlib = 'lib%s.lib' % lib # this form very rare\r
213\r
214 # get EMX's default library directory search path\r
215 try:\r
216 emx_dirs = os.environ['LIBRARY_PATH'].split(';')\r
217 except KeyError:\r
218 emx_dirs = []\r
219\r
220 for dir in dirs + emx_dirs:\r
221 shortlibp = os.path.join(dir, shortlib)\r
222 longlibp = os.path.join(dir, longlib)\r
223 if os.path.exists(shortlibp):\r
224 return shortlibp\r
225 elif os.path.exists(longlibp):\r
226 return longlibp\r
227\r
228 # Oops, didn't find it in *any* of 'dirs'\r
229 return None\r
230\r
231# class EMXCCompiler\r
232\r
233\r
234# Because these compilers aren't configured in Python's pyconfig.h file by\r
235# default, we should at least warn the user if he is using a unmodified\r
236# version.\r
237\r
238CONFIG_H_OK = "ok"\r
239CONFIG_H_NOTOK = "not ok"\r
240CONFIG_H_UNCERTAIN = "uncertain"\r
241\r
242def check_config_h():\r
243\r
244 """Check if the current Python installation (specifically, pyconfig.h)\r
245 appears amenable to building extensions with GCC. Returns a tuple\r
246 (status, details), where 'status' is one of the following constants:\r
247 CONFIG_H_OK\r
248 all is well, go ahead and compile\r
249 CONFIG_H_NOTOK\r
250 doesn't look good\r
251 CONFIG_H_UNCERTAIN\r
252 not sure -- unable to read pyconfig.h\r
253 'details' is a human-readable string explaining the situation.\r
254\r
255 Note there are two ways to conclude "OK": either 'sys.version' contains\r
256 the string "GCC" (implying that this Python was built with GCC), or the\r
257 installed "pyconfig.h" contains the string "__GNUC__".\r
258 """\r
259\r
260 # XXX since this function also checks sys.version, it's not strictly a\r
261 # "pyconfig.h" check -- should probably be renamed...\r
262\r
263 from distutils import sysconfig\r
264 import string\r
265 # if sys.version contains GCC then python was compiled with\r
266 # GCC, and the pyconfig.h file should be OK\r
267 if string.find(sys.version,"GCC") >= 0:\r
268 return (CONFIG_H_OK, "sys.version mentions 'GCC'")\r
269\r
270 fn = sysconfig.get_config_h_filename()\r
271 try:\r
272 # It would probably better to read single lines to search.\r
273 # But we do this only once, and it is fast enough\r
274 f = open(fn)\r
275 try:\r
276 s = f.read()\r
277 finally:\r
278 f.close()\r
279\r
280 except IOError, exc:\r
281 # if we can't read this file, we cannot say it is wrong\r
282 # the compiler will complain later about this file as missing\r
283 return (CONFIG_H_UNCERTAIN,\r
284 "couldn't read '%s': %s" % (fn, exc.strerror))\r
285\r
286 else:\r
287 # "pyconfig.h" contains an "#ifdef __GNUC__" or something similar\r
288 if string.find(s,"__GNUC__") >= 0:\r
289 return (CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn)\r
290 else:\r
291 return (CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn)\r
292\r
293\r
294def get_versions():\r
295 """ Try to find out the versions of gcc and ld.\r
296 If not possible it returns None for it.\r
297 """\r
298 from distutils.version import StrictVersion\r
299 from distutils.spawn import find_executable\r
300 import re\r
301\r
302 gcc_exe = find_executable('gcc')\r
303 if gcc_exe:\r
304 out = os.popen(gcc_exe + ' -dumpversion','r')\r
305 try:\r
306 out_string = out.read()\r
307 finally:\r
308 out.close()\r
309 result = re.search('(\d+\.\d+\.\d+)',out_string)\r
310 if result:\r
311 gcc_version = StrictVersion(result.group(1))\r
312 else:\r
313 gcc_version = None\r
314 else:\r
315 gcc_version = None\r
316 # EMX ld has no way of reporting version number, and we use GCC\r
317 # anyway - so we can link OMF DLLs\r
318 ld_version = None\r
319 return (gcc_version, ld_version)\r