xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/distutils/bcppcompiler.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""distutils.bcppcompiler
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerContains BorlandCCompiler, an implementation of the abstract CCompiler class
4*cda5da8dSAndroid Build Coastguard Workerfor the Borland C++ compiler.
5*cda5da8dSAndroid Build Coastguard Worker"""
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard Worker# This implementation by Lyle Johnson, based on the original msvccompiler.py
8*cda5da8dSAndroid Build Coastguard Worker# module and using the directions originally published by Gordon Williams.
9*cda5da8dSAndroid Build Coastguard Worker
10*cda5da8dSAndroid Build Coastguard Worker# XXX looks like there's a LOT of overlap between these two classes:
11*cda5da8dSAndroid Build Coastguard Worker# someone should sit down and factor out the common code as
12*cda5da8dSAndroid Build Coastguard Worker# WindowsCCompiler!  --GPW
13*cda5da8dSAndroid Build Coastguard Worker
14*cda5da8dSAndroid Build Coastguard Worker
15*cda5da8dSAndroid Build Coastguard Workerimport os
16*cda5da8dSAndroid Build Coastguard Workerfrom distutils.errors import \
17*cda5da8dSAndroid Build Coastguard Worker     DistutilsExecError, \
18*cda5da8dSAndroid Build Coastguard Worker     CompileError, LibError, LinkError, UnknownFileError
19*cda5da8dSAndroid Build Coastguard Workerfrom distutils.ccompiler import \
20*cda5da8dSAndroid Build Coastguard Worker     CCompiler, gen_preprocess_options
21*cda5da8dSAndroid Build Coastguard Workerfrom distutils.file_util import write_file
22*cda5da8dSAndroid Build Coastguard Workerfrom distutils.dep_util import newer
23*cda5da8dSAndroid Build Coastguard Workerfrom distutils import log
24*cda5da8dSAndroid Build Coastguard Worker
25*cda5da8dSAndroid Build Coastguard Workerclass BCPPCompiler(CCompiler) :
26*cda5da8dSAndroid Build Coastguard Worker    """Concrete class that implements an interface to the Borland C/C++
27*cda5da8dSAndroid Build Coastguard Worker    compiler, as defined by the CCompiler abstract class.
28*cda5da8dSAndroid Build Coastguard Worker    """
29*cda5da8dSAndroid Build Coastguard Worker
30*cda5da8dSAndroid Build Coastguard Worker    compiler_type = 'bcpp'
31*cda5da8dSAndroid Build Coastguard Worker
32*cda5da8dSAndroid Build Coastguard Worker    # Just set this so CCompiler's constructor doesn't barf.  We currently
33*cda5da8dSAndroid Build Coastguard Worker    # don't use the 'set_executables()' bureaucracy provided by CCompiler,
34*cda5da8dSAndroid Build Coastguard Worker    # as it really isn't necessary for this sort of single-compiler class.
35*cda5da8dSAndroid Build Coastguard Worker    # Would be nice to have a consistent interface with UnixCCompiler,
36*cda5da8dSAndroid Build Coastguard Worker    # though, so it's worth thinking about.
37*cda5da8dSAndroid Build Coastguard Worker    executables = {}
38*cda5da8dSAndroid Build Coastguard Worker
39*cda5da8dSAndroid Build Coastguard Worker    # Private class data (need to distinguish C from C++ source for compiler)
40*cda5da8dSAndroid Build Coastguard Worker    _c_extensions = ['.c']
41*cda5da8dSAndroid Build Coastguard Worker    _cpp_extensions = ['.cc', '.cpp', '.cxx']
42*cda5da8dSAndroid Build Coastguard Worker
43*cda5da8dSAndroid Build Coastguard Worker    # Needed for the filename generation methods provided by the
44*cda5da8dSAndroid Build Coastguard Worker    # base class, CCompiler.
45*cda5da8dSAndroid Build Coastguard Worker    src_extensions = _c_extensions + _cpp_extensions
46*cda5da8dSAndroid Build Coastguard Worker    obj_extension = '.obj'
47*cda5da8dSAndroid Build Coastguard Worker    static_lib_extension = '.lib'
48*cda5da8dSAndroid Build Coastguard Worker    shared_lib_extension = '.dll'
49*cda5da8dSAndroid Build Coastguard Worker    static_lib_format = shared_lib_format = '%s%s'
50*cda5da8dSAndroid Build Coastguard Worker    exe_extension = '.exe'
51*cda5da8dSAndroid Build Coastguard Worker
52*cda5da8dSAndroid Build Coastguard Worker
53*cda5da8dSAndroid Build Coastguard Worker    def __init__ (self,
54*cda5da8dSAndroid Build Coastguard Worker                  verbose=0,
55*cda5da8dSAndroid Build Coastguard Worker                  dry_run=0,
56*cda5da8dSAndroid Build Coastguard Worker                  force=0):
57*cda5da8dSAndroid Build Coastguard Worker
58*cda5da8dSAndroid Build Coastguard Worker        CCompiler.__init__ (self, verbose, dry_run, force)
59*cda5da8dSAndroid Build Coastguard Worker
60*cda5da8dSAndroid Build Coastguard Worker        # These executables are assumed to all be in the path.
61*cda5da8dSAndroid Build Coastguard Worker        # Borland doesn't seem to use any special registry settings to
62*cda5da8dSAndroid Build Coastguard Worker        # indicate their installation locations.
63*cda5da8dSAndroid Build Coastguard Worker
64*cda5da8dSAndroid Build Coastguard Worker        self.cc = "bcc32.exe"
65*cda5da8dSAndroid Build Coastguard Worker        self.linker = "ilink32.exe"
66*cda5da8dSAndroid Build Coastguard Worker        self.lib = "tlib.exe"
67*cda5da8dSAndroid Build Coastguard Worker
68*cda5da8dSAndroid Build Coastguard Worker        self.preprocess_options = None
69*cda5da8dSAndroid Build Coastguard Worker        self.compile_options = ['/tWM', '/O2', '/q', '/g0']
70*cda5da8dSAndroid Build Coastguard Worker        self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
71*cda5da8dSAndroid Build Coastguard Worker
72*cda5da8dSAndroid Build Coastguard Worker        self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
73*cda5da8dSAndroid Build Coastguard Worker        self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
74*cda5da8dSAndroid Build Coastguard Worker        self.ldflags_static = []
75*cda5da8dSAndroid Build Coastguard Worker        self.ldflags_exe = ['/Gn', '/q', '/x']
76*cda5da8dSAndroid Build Coastguard Worker        self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r']
77*cda5da8dSAndroid Build Coastguard Worker
78*cda5da8dSAndroid Build Coastguard Worker
79*cda5da8dSAndroid Build Coastguard Worker    # -- Worker methods ------------------------------------------------
80*cda5da8dSAndroid Build Coastguard Worker
81*cda5da8dSAndroid Build Coastguard Worker    def compile(self, sources,
82*cda5da8dSAndroid Build Coastguard Worker                output_dir=None, macros=None, include_dirs=None, debug=0,
83*cda5da8dSAndroid Build Coastguard Worker                extra_preargs=None, extra_postargs=None, depends=None):
84*cda5da8dSAndroid Build Coastguard Worker
85*cda5da8dSAndroid Build Coastguard Worker        macros, objects, extra_postargs, pp_opts, build = \
86*cda5da8dSAndroid Build Coastguard Worker                self._setup_compile(output_dir, macros, include_dirs, sources,
87*cda5da8dSAndroid Build Coastguard Worker                                    depends, extra_postargs)
88*cda5da8dSAndroid Build Coastguard Worker        compile_opts = extra_preargs or []
89*cda5da8dSAndroid Build Coastguard Worker        compile_opts.append ('-c')
90*cda5da8dSAndroid Build Coastguard Worker        if debug:
91*cda5da8dSAndroid Build Coastguard Worker            compile_opts.extend (self.compile_options_debug)
92*cda5da8dSAndroid Build Coastguard Worker        else:
93*cda5da8dSAndroid Build Coastguard Worker            compile_opts.extend (self.compile_options)
94*cda5da8dSAndroid Build Coastguard Worker
95*cda5da8dSAndroid Build Coastguard Worker        for obj in objects:
96*cda5da8dSAndroid Build Coastguard Worker            try:
97*cda5da8dSAndroid Build Coastguard Worker                src, ext = build[obj]
98*cda5da8dSAndroid Build Coastguard Worker            except KeyError:
99*cda5da8dSAndroid Build Coastguard Worker                continue
100*cda5da8dSAndroid Build Coastguard Worker            # XXX why do the normpath here?
101*cda5da8dSAndroid Build Coastguard Worker            src = os.path.normpath(src)
102*cda5da8dSAndroid Build Coastguard Worker            obj = os.path.normpath(obj)
103*cda5da8dSAndroid Build Coastguard Worker            # XXX _setup_compile() did a mkpath() too but before the normpath.
104*cda5da8dSAndroid Build Coastguard Worker            # Is it possible to skip the normpath?
105*cda5da8dSAndroid Build Coastguard Worker            self.mkpath(os.path.dirname(obj))
106*cda5da8dSAndroid Build Coastguard Worker
107*cda5da8dSAndroid Build Coastguard Worker            if ext == '.res':
108*cda5da8dSAndroid Build Coastguard Worker                # This is already a binary file -- skip it.
109*cda5da8dSAndroid Build Coastguard Worker                continue # the 'for' loop
110*cda5da8dSAndroid Build Coastguard Worker            if ext == '.rc':
111*cda5da8dSAndroid Build Coastguard Worker                # This needs to be compiled to a .res file -- do it now.
112*cda5da8dSAndroid Build Coastguard Worker                try:
113*cda5da8dSAndroid Build Coastguard Worker                    self.spawn (["brcc32", "-fo", obj, src])
114*cda5da8dSAndroid Build Coastguard Worker                except DistutilsExecError as msg:
115*cda5da8dSAndroid Build Coastguard Worker                    raise CompileError(msg)
116*cda5da8dSAndroid Build Coastguard Worker                continue # the 'for' loop
117*cda5da8dSAndroid Build Coastguard Worker
118*cda5da8dSAndroid Build Coastguard Worker            # The next two are both for the real compiler.
119*cda5da8dSAndroid Build Coastguard Worker            if ext in self._c_extensions:
120*cda5da8dSAndroid Build Coastguard Worker                input_opt = ""
121*cda5da8dSAndroid Build Coastguard Worker            elif ext in self._cpp_extensions:
122*cda5da8dSAndroid Build Coastguard Worker                input_opt = "-P"
123*cda5da8dSAndroid Build Coastguard Worker            else:
124*cda5da8dSAndroid Build Coastguard Worker                # Unknown file type -- no extra options.  The compiler
125*cda5da8dSAndroid Build Coastguard Worker                # will probably fail, but let it just in case this is a
126*cda5da8dSAndroid Build Coastguard Worker                # file the compiler recognizes even if we don't.
127*cda5da8dSAndroid Build Coastguard Worker                input_opt = ""
128*cda5da8dSAndroid Build Coastguard Worker
129*cda5da8dSAndroid Build Coastguard Worker            output_opt = "-o" + obj
130*cda5da8dSAndroid Build Coastguard Worker
131*cda5da8dSAndroid Build Coastguard Worker            # Compiler command line syntax is: "bcc32 [options] file(s)".
132*cda5da8dSAndroid Build Coastguard Worker            # Note that the source file names must appear at the end of
133*cda5da8dSAndroid Build Coastguard Worker            # the command line.
134*cda5da8dSAndroid Build Coastguard Worker            try:
135*cda5da8dSAndroid Build Coastguard Worker                self.spawn ([self.cc] + compile_opts + pp_opts +
136*cda5da8dSAndroid Build Coastguard Worker                            [input_opt, output_opt] +
137*cda5da8dSAndroid Build Coastguard Worker                            extra_postargs + [src])
138*cda5da8dSAndroid Build Coastguard Worker            except DistutilsExecError as msg:
139*cda5da8dSAndroid Build Coastguard Worker                raise CompileError(msg)
140*cda5da8dSAndroid Build Coastguard Worker
141*cda5da8dSAndroid Build Coastguard Worker        return objects
142*cda5da8dSAndroid Build Coastguard Worker
143*cda5da8dSAndroid Build Coastguard Worker    # compile ()
144*cda5da8dSAndroid Build Coastguard Worker
145*cda5da8dSAndroid Build Coastguard Worker
146*cda5da8dSAndroid Build Coastguard Worker    def create_static_lib (self,
147*cda5da8dSAndroid Build Coastguard Worker                           objects,
148*cda5da8dSAndroid Build Coastguard Worker                           output_libname,
149*cda5da8dSAndroid Build Coastguard Worker                           output_dir=None,
150*cda5da8dSAndroid Build Coastguard Worker                           debug=0,
151*cda5da8dSAndroid Build Coastguard Worker                           target_lang=None):
152*cda5da8dSAndroid Build Coastguard Worker
153*cda5da8dSAndroid Build Coastguard Worker        (objects, output_dir) = self._fix_object_args (objects, output_dir)
154*cda5da8dSAndroid Build Coastguard Worker        output_filename = \
155*cda5da8dSAndroid Build Coastguard Worker            self.library_filename (output_libname, output_dir=output_dir)
156*cda5da8dSAndroid Build Coastguard Worker
157*cda5da8dSAndroid Build Coastguard Worker        if self._need_link (objects, output_filename):
158*cda5da8dSAndroid Build Coastguard Worker            lib_args = [output_filename, '/u'] + objects
159*cda5da8dSAndroid Build Coastguard Worker            if debug:
160*cda5da8dSAndroid Build Coastguard Worker                pass                    # XXX what goes here?
161*cda5da8dSAndroid Build Coastguard Worker            try:
162*cda5da8dSAndroid Build Coastguard Worker                self.spawn ([self.lib] + lib_args)
163*cda5da8dSAndroid Build Coastguard Worker            except DistutilsExecError as msg:
164*cda5da8dSAndroid Build Coastguard Worker                raise LibError(msg)
165*cda5da8dSAndroid Build Coastguard Worker        else:
166*cda5da8dSAndroid Build Coastguard Worker            log.debug("skipping %s (up-to-date)", output_filename)
167*cda5da8dSAndroid Build Coastguard Worker
168*cda5da8dSAndroid Build Coastguard Worker    # create_static_lib ()
169*cda5da8dSAndroid Build Coastguard Worker
170*cda5da8dSAndroid Build Coastguard Worker
171*cda5da8dSAndroid Build Coastguard Worker    def link (self,
172*cda5da8dSAndroid Build Coastguard Worker              target_desc,
173*cda5da8dSAndroid Build Coastguard Worker              objects,
174*cda5da8dSAndroid Build Coastguard Worker              output_filename,
175*cda5da8dSAndroid Build Coastguard Worker              output_dir=None,
176*cda5da8dSAndroid Build Coastguard Worker              libraries=None,
177*cda5da8dSAndroid Build Coastguard Worker              library_dirs=None,
178*cda5da8dSAndroid Build Coastguard Worker              runtime_library_dirs=None,
179*cda5da8dSAndroid Build Coastguard Worker              export_symbols=None,
180*cda5da8dSAndroid Build Coastguard Worker              debug=0,
181*cda5da8dSAndroid Build Coastguard Worker              extra_preargs=None,
182*cda5da8dSAndroid Build Coastguard Worker              extra_postargs=None,
183*cda5da8dSAndroid Build Coastguard Worker              build_temp=None,
184*cda5da8dSAndroid Build Coastguard Worker              target_lang=None):
185*cda5da8dSAndroid Build Coastguard Worker
186*cda5da8dSAndroid Build Coastguard Worker        # XXX this ignores 'build_temp'!  should follow the lead of
187*cda5da8dSAndroid Build Coastguard Worker        # msvccompiler.py
188*cda5da8dSAndroid Build Coastguard Worker
189*cda5da8dSAndroid Build Coastguard Worker        (objects, output_dir) = self._fix_object_args (objects, output_dir)
190*cda5da8dSAndroid Build Coastguard Worker        (libraries, library_dirs, runtime_library_dirs) = \
191*cda5da8dSAndroid Build Coastguard Worker            self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
192*cda5da8dSAndroid Build Coastguard Worker
193*cda5da8dSAndroid Build Coastguard Worker        if runtime_library_dirs:
194*cda5da8dSAndroid Build Coastguard Worker            log.warn("I don't know what to do with 'runtime_library_dirs': %s",
195*cda5da8dSAndroid Build Coastguard Worker                     str(runtime_library_dirs))
196*cda5da8dSAndroid Build Coastguard Worker
197*cda5da8dSAndroid Build Coastguard Worker        if output_dir is not None:
198*cda5da8dSAndroid Build Coastguard Worker            output_filename = os.path.join (output_dir, output_filename)
199*cda5da8dSAndroid Build Coastguard Worker
200*cda5da8dSAndroid Build Coastguard Worker        if self._need_link (objects, output_filename):
201*cda5da8dSAndroid Build Coastguard Worker
202*cda5da8dSAndroid Build Coastguard Worker            # Figure out linker args based on type of target.
203*cda5da8dSAndroid Build Coastguard Worker            if target_desc == CCompiler.EXECUTABLE:
204*cda5da8dSAndroid Build Coastguard Worker                startup_obj = 'c0w32'
205*cda5da8dSAndroid Build Coastguard Worker                if debug:
206*cda5da8dSAndroid Build Coastguard Worker                    ld_args = self.ldflags_exe_debug[:]
207*cda5da8dSAndroid Build Coastguard Worker                else:
208*cda5da8dSAndroid Build Coastguard Worker                    ld_args = self.ldflags_exe[:]
209*cda5da8dSAndroid Build Coastguard Worker            else:
210*cda5da8dSAndroid Build Coastguard Worker                startup_obj = 'c0d32'
211*cda5da8dSAndroid Build Coastguard Worker                if debug:
212*cda5da8dSAndroid Build Coastguard Worker                    ld_args = self.ldflags_shared_debug[:]
213*cda5da8dSAndroid Build Coastguard Worker                else:
214*cda5da8dSAndroid Build Coastguard Worker                    ld_args = self.ldflags_shared[:]
215*cda5da8dSAndroid Build Coastguard Worker
216*cda5da8dSAndroid Build Coastguard Worker
217*cda5da8dSAndroid Build Coastguard Worker            # Create a temporary exports file for use by the linker
218*cda5da8dSAndroid Build Coastguard Worker            if export_symbols is None:
219*cda5da8dSAndroid Build Coastguard Worker                def_file = ''
220*cda5da8dSAndroid Build Coastguard Worker            else:
221*cda5da8dSAndroid Build Coastguard Worker                head, tail = os.path.split (output_filename)
222*cda5da8dSAndroid Build Coastguard Worker                modname, ext = os.path.splitext (tail)
223*cda5da8dSAndroid Build Coastguard Worker                temp_dir = os.path.dirname(objects[0]) # preserve tree structure
224*cda5da8dSAndroid Build Coastguard Worker                def_file = os.path.join (temp_dir, '%s.def' % modname)
225*cda5da8dSAndroid Build Coastguard Worker                contents = ['EXPORTS']
226*cda5da8dSAndroid Build Coastguard Worker                for sym in (export_symbols or []):
227*cda5da8dSAndroid Build Coastguard Worker                    contents.append('  %s=_%s' % (sym, sym))
228*cda5da8dSAndroid Build Coastguard Worker                self.execute(write_file, (def_file, contents),
229*cda5da8dSAndroid Build Coastguard Worker                             "writing %s" % def_file)
230*cda5da8dSAndroid Build Coastguard Worker
231*cda5da8dSAndroid Build Coastguard Worker            # Borland C++ has problems with '/' in paths
232*cda5da8dSAndroid Build Coastguard Worker            objects2 = map(os.path.normpath, objects)
233*cda5da8dSAndroid Build Coastguard Worker            # split objects in .obj and .res files
234*cda5da8dSAndroid Build Coastguard Worker            # Borland C++ needs them at different positions in the command line
235*cda5da8dSAndroid Build Coastguard Worker            objects = [startup_obj]
236*cda5da8dSAndroid Build Coastguard Worker            resources = []
237*cda5da8dSAndroid Build Coastguard Worker            for file in objects2:
238*cda5da8dSAndroid Build Coastguard Worker                (base, ext) = os.path.splitext(os.path.normcase(file))
239*cda5da8dSAndroid Build Coastguard Worker                if ext == '.res':
240*cda5da8dSAndroid Build Coastguard Worker                    resources.append(file)
241*cda5da8dSAndroid Build Coastguard Worker                else:
242*cda5da8dSAndroid Build Coastguard Worker                    objects.append(file)
243*cda5da8dSAndroid Build Coastguard Worker
244*cda5da8dSAndroid Build Coastguard Worker
245*cda5da8dSAndroid Build Coastguard Worker            for l in library_dirs:
246*cda5da8dSAndroid Build Coastguard Worker                ld_args.append("/L%s" % os.path.normpath(l))
247*cda5da8dSAndroid Build Coastguard Worker            ld_args.append("/L.") # we sometimes use relative paths
248*cda5da8dSAndroid Build Coastguard Worker
249*cda5da8dSAndroid Build Coastguard Worker            # list of object files
250*cda5da8dSAndroid Build Coastguard Worker            ld_args.extend(objects)
251*cda5da8dSAndroid Build Coastguard Worker
252*cda5da8dSAndroid Build Coastguard Worker            # XXX the command-line syntax for Borland C++ is a bit wonky;
253*cda5da8dSAndroid Build Coastguard Worker            # certain filenames are jammed together in one big string, but
254*cda5da8dSAndroid Build Coastguard Worker            # comma-delimited.  This doesn't mesh too well with the
255*cda5da8dSAndroid Build Coastguard Worker            # Unix-centric attitude (with a DOS/Windows quoting hack) of
256*cda5da8dSAndroid Build Coastguard Worker            # 'spawn()', so constructing the argument list is a bit
257*cda5da8dSAndroid Build Coastguard Worker            # awkward.  Note that doing the obvious thing and jamming all
258*cda5da8dSAndroid Build Coastguard Worker            # the filenames and commas into one argument would be wrong,
259*cda5da8dSAndroid Build Coastguard Worker            # because 'spawn()' would quote any filenames with spaces in
260*cda5da8dSAndroid Build Coastguard Worker            # them.  Arghghh!.  Apparently it works fine as coded...
261*cda5da8dSAndroid Build Coastguard Worker
262*cda5da8dSAndroid Build Coastguard Worker            # name of dll/exe file
263*cda5da8dSAndroid Build Coastguard Worker            ld_args.extend([',',output_filename])
264*cda5da8dSAndroid Build Coastguard Worker            # no map file and start libraries
265*cda5da8dSAndroid Build Coastguard Worker            ld_args.append(',,')
266*cda5da8dSAndroid Build Coastguard Worker
267*cda5da8dSAndroid Build Coastguard Worker            for lib in libraries:
268*cda5da8dSAndroid Build Coastguard Worker                # see if we find it and if there is a bcpp specific lib
269*cda5da8dSAndroid Build Coastguard Worker                # (xxx_bcpp.lib)
270*cda5da8dSAndroid Build Coastguard Worker                libfile = self.find_library_file(library_dirs, lib, debug)
271*cda5da8dSAndroid Build Coastguard Worker                if libfile is None:
272*cda5da8dSAndroid Build Coastguard Worker                    ld_args.append(lib)
273*cda5da8dSAndroid Build Coastguard Worker                    # probably a BCPP internal library -- don't warn
274*cda5da8dSAndroid Build Coastguard Worker                else:
275*cda5da8dSAndroid Build Coastguard Worker                    # full name which prefers bcpp_xxx.lib over xxx.lib
276*cda5da8dSAndroid Build Coastguard Worker                    ld_args.append(libfile)
277*cda5da8dSAndroid Build Coastguard Worker
278*cda5da8dSAndroid Build Coastguard Worker            # some default libraries
279*cda5da8dSAndroid Build Coastguard Worker            ld_args.append ('import32')
280*cda5da8dSAndroid Build Coastguard Worker            ld_args.append ('cw32mt')
281*cda5da8dSAndroid Build Coastguard Worker
282*cda5da8dSAndroid Build Coastguard Worker            # def file for export symbols
283*cda5da8dSAndroid Build Coastguard Worker            ld_args.extend([',',def_file])
284*cda5da8dSAndroid Build Coastguard Worker            # add resource files
285*cda5da8dSAndroid Build Coastguard Worker            ld_args.append(',')
286*cda5da8dSAndroid Build Coastguard Worker            ld_args.extend(resources)
287*cda5da8dSAndroid Build Coastguard Worker
288*cda5da8dSAndroid Build Coastguard Worker
289*cda5da8dSAndroid Build Coastguard Worker            if extra_preargs:
290*cda5da8dSAndroid Build Coastguard Worker                ld_args[:0] = extra_preargs
291*cda5da8dSAndroid Build Coastguard Worker            if extra_postargs:
292*cda5da8dSAndroid Build Coastguard Worker                ld_args.extend(extra_postargs)
293*cda5da8dSAndroid Build Coastguard Worker
294*cda5da8dSAndroid Build Coastguard Worker            self.mkpath (os.path.dirname (output_filename))
295*cda5da8dSAndroid Build Coastguard Worker            try:
296*cda5da8dSAndroid Build Coastguard Worker                self.spawn ([self.linker] + ld_args)
297*cda5da8dSAndroid Build Coastguard Worker            except DistutilsExecError as msg:
298*cda5da8dSAndroid Build Coastguard Worker                raise LinkError(msg)
299*cda5da8dSAndroid Build Coastguard Worker
300*cda5da8dSAndroid Build Coastguard Worker        else:
301*cda5da8dSAndroid Build Coastguard Worker            log.debug("skipping %s (up-to-date)", output_filename)
302*cda5da8dSAndroid Build Coastguard Worker
303*cda5da8dSAndroid Build Coastguard Worker    # link ()
304*cda5da8dSAndroid Build Coastguard Worker
305*cda5da8dSAndroid Build Coastguard Worker    # -- Miscellaneous methods -----------------------------------------
306*cda5da8dSAndroid Build Coastguard Worker
307*cda5da8dSAndroid Build Coastguard Worker
308*cda5da8dSAndroid Build Coastguard Worker    def find_library_file (self, dirs, lib, debug=0):
309*cda5da8dSAndroid Build Coastguard Worker        # List of effective library names to try, in order of preference:
310*cda5da8dSAndroid Build Coastguard Worker        # xxx_bcpp.lib is better than xxx.lib
311*cda5da8dSAndroid Build Coastguard Worker        # and xxx_d.lib is better than xxx.lib if debug is set
312*cda5da8dSAndroid Build Coastguard Worker        #
313*cda5da8dSAndroid Build Coastguard Worker        # The "_bcpp" suffix is to handle a Python installation for people
314*cda5da8dSAndroid Build Coastguard Worker        # with multiple compilers (primarily Distutils hackers, I suspect
315*cda5da8dSAndroid Build Coastguard Worker        # ;-).  The idea is they'd have one static library for each
316*cda5da8dSAndroid Build Coastguard Worker        # compiler they care about, since (almost?) every Windows compiler
317*cda5da8dSAndroid Build Coastguard Worker        # seems to have a different format for static libraries.
318*cda5da8dSAndroid Build Coastguard Worker        if debug:
319*cda5da8dSAndroid Build Coastguard Worker            dlib = (lib + "_d")
320*cda5da8dSAndroid Build Coastguard Worker            try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
321*cda5da8dSAndroid Build Coastguard Worker        else:
322*cda5da8dSAndroid Build Coastguard Worker            try_names = (lib + "_bcpp", lib)
323*cda5da8dSAndroid Build Coastguard Worker
324*cda5da8dSAndroid Build Coastguard Worker        for dir in dirs:
325*cda5da8dSAndroid Build Coastguard Worker            for name in try_names:
326*cda5da8dSAndroid Build Coastguard Worker                libfile = os.path.join(dir, self.library_filename(name))
327*cda5da8dSAndroid Build Coastguard Worker                if os.path.exists(libfile):
328*cda5da8dSAndroid Build Coastguard Worker                    return libfile
329*cda5da8dSAndroid Build Coastguard Worker        else:
330*cda5da8dSAndroid Build Coastguard Worker            # Oops, didn't find it in *any* of 'dirs'
331*cda5da8dSAndroid Build Coastguard Worker            return None
332*cda5da8dSAndroid Build Coastguard Worker
333*cda5da8dSAndroid Build Coastguard Worker    # overwrite the one from CCompiler to support rc and res-files
334*cda5da8dSAndroid Build Coastguard Worker    def object_filenames (self,
335*cda5da8dSAndroid Build Coastguard Worker                          source_filenames,
336*cda5da8dSAndroid Build Coastguard Worker                          strip_dir=0,
337*cda5da8dSAndroid Build Coastguard Worker                          output_dir=''):
338*cda5da8dSAndroid Build Coastguard Worker        if output_dir is None: output_dir = ''
339*cda5da8dSAndroid Build Coastguard Worker        obj_names = []
340*cda5da8dSAndroid Build Coastguard Worker        for src_name in source_filenames:
341*cda5da8dSAndroid Build Coastguard Worker            # use normcase to make sure '.rc' is really '.rc' and not '.RC'
342*cda5da8dSAndroid Build Coastguard Worker            (base, ext) = os.path.splitext (os.path.normcase(src_name))
343*cda5da8dSAndroid Build Coastguard Worker            if ext not in (self.src_extensions + ['.rc','.res']):
344*cda5da8dSAndroid Build Coastguard Worker                raise UnknownFileError("unknown file type '%s' (from '%s')" % \
345*cda5da8dSAndroid Build Coastguard Worker                      (ext, src_name))
346*cda5da8dSAndroid Build Coastguard Worker            if strip_dir:
347*cda5da8dSAndroid Build Coastguard Worker                base = os.path.basename (base)
348*cda5da8dSAndroid Build Coastguard Worker            if ext == '.res':
349*cda5da8dSAndroid Build Coastguard Worker                # these can go unchanged
350*cda5da8dSAndroid Build Coastguard Worker                obj_names.append (os.path.join (output_dir, base + ext))
351*cda5da8dSAndroid Build Coastguard Worker            elif ext == '.rc':
352*cda5da8dSAndroid Build Coastguard Worker                # these need to be compiled to .res-files
353*cda5da8dSAndroid Build Coastguard Worker                obj_names.append (os.path.join (output_dir, base + '.res'))
354*cda5da8dSAndroid Build Coastguard Worker            else:
355*cda5da8dSAndroid Build Coastguard Worker                obj_names.append (os.path.join (output_dir,
356*cda5da8dSAndroid Build Coastguard Worker                                            base + self.obj_extension))
357*cda5da8dSAndroid Build Coastguard Worker        return obj_names
358*cda5da8dSAndroid Build Coastguard Worker
359*cda5da8dSAndroid Build Coastguard Worker    # object_filenames ()
360*cda5da8dSAndroid Build Coastguard Worker
361*cda5da8dSAndroid Build Coastguard Worker    def preprocess (self,
362*cda5da8dSAndroid Build Coastguard Worker                    source,
363*cda5da8dSAndroid Build Coastguard Worker                    output_file=None,
364*cda5da8dSAndroid Build Coastguard Worker                    macros=None,
365*cda5da8dSAndroid Build Coastguard Worker                    include_dirs=None,
366*cda5da8dSAndroid Build Coastguard Worker                    extra_preargs=None,
367*cda5da8dSAndroid Build Coastguard Worker                    extra_postargs=None):
368*cda5da8dSAndroid Build Coastguard Worker
369*cda5da8dSAndroid Build Coastguard Worker        (_, macros, include_dirs) = \
370*cda5da8dSAndroid Build Coastguard Worker            self._fix_compile_args(None, macros, include_dirs)
371*cda5da8dSAndroid Build Coastguard Worker        pp_opts = gen_preprocess_options(macros, include_dirs)
372*cda5da8dSAndroid Build Coastguard Worker        pp_args = ['cpp32.exe'] + pp_opts
373*cda5da8dSAndroid Build Coastguard Worker        if output_file is not None:
374*cda5da8dSAndroid Build Coastguard Worker            pp_args.append('-o' + output_file)
375*cda5da8dSAndroid Build Coastguard Worker        if extra_preargs:
376*cda5da8dSAndroid Build Coastguard Worker            pp_args[:0] = extra_preargs
377*cda5da8dSAndroid Build Coastguard Worker        if extra_postargs:
378*cda5da8dSAndroid Build Coastguard Worker            pp_args.extend(extra_postargs)
379*cda5da8dSAndroid Build Coastguard Worker        pp_args.append(source)
380*cda5da8dSAndroid Build Coastguard Worker
381*cda5da8dSAndroid Build Coastguard Worker        # We need to preprocess: either we're being forced to, or the
382*cda5da8dSAndroid Build Coastguard Worker        # source file is newer than the target (or the target doesn't
383*cda5da8dSAndroid Build Coastguard Worker        # exist).
384*cda5da8dSAndroid Build Coastguard Worker        if self.force or output_file is None or newer(source, output_file):
385*cda5da8dSAndroid Build Coastguard Worker            if output_file:
386*cda5da8dSAndroid Build Coastguard Worker                self.mkpath(os.path.dirname(output_file))
387*cda5da8dSAndroid Build Coastguard Worker            try:
388*cda5da8dSAndroid Build Coastguard Worker                self.spawn(pp_args)
389*cda5da8dSAndroid Build Coastguard Worker            except DistutilsExecError as msg:
390*cda5da8dSAndroid Build Coastguard Worker                print(msg)
391*cda5da8dSAndroid Build Coastguard Worker                raise CompileError(msg)
392*cda5da8dSAndroid Build Coastguard Worker
393*cda5da8dSAndroid Build Coastguard Worker    # preprocess()
394