[Distutils] Supporting Borland's compiler

Greg Ward gward@python.net
Sat, 20 May 2000 08:48:06 -0400


Hi all --

this is a followup to Lyle and Thomas' exchange earlier in the week;
sorry for the delay.

1. First topic: list of symbols to export.

[Lyle]
> Since only the compiler class knows for sure how to specify the .DEF file
> name (or alternatively the exported symbols list) it seems that we should
> pass this information directly to the compiler through the
> link_shared_object() function's argument list, instead of cooking up those
> arguments in the build_ext command. I'd propose adding an additional
> argument to the function's signature (its default could be None and could be
> ignored by non-Windows compilers).

Yep, I've been thinking this was needed for a while.  Here's a proposed
new signature for the 'link_shared_lib()' method:

    def link_shared_lib (self,
                         objects,
                         output_libname,
                         output_dir=None,
                         libraries=None,
                         library_dirs=None,
                         runtime_library_dirs=None,
                         exported_symbols=None,
                         debug=0,
                         extra_preargs=None,
                         extra_postargs=None):

'exported_symbols' would be a list of strings; it's up to the compiler
class to translate that into command-line options, a file (in the
appropriate format for that compiler) listing the names, or whatever.
For MSVCCompiler, we would add "/EXPORT:" options to the command line,
one for each string in 'exported_symbols'.  For BorlandCCompiler (or
whatever Lyle's calling it -- I suppose I should have veto power on the
name, but I still can't make up my mind), the class would have to
generate a .def file (in Borland style with underscores added/removed as
appropriate) and pass that in just the right place on the compiler
command-line.

'link_shared_object()', of course, would be adjusted similarly (since
'link_shared_lib()' is just a wrapper around 'link_shared_object()' on
both Unix and Windows.)

2. Variation on first topic: allowing sneaky symbol aliasing

[Lyle]
> The terminally clever developer who wants the (private)
> name of his module initialization function to be something else would be
> required to provide a .DEF file which exports that function as "init" +
> module, though -- there's obviously no way for distutils to guess that.

[Thomas echoes my sentiments]
> Is this possible? I think when you 'import extension' python looks
> for extension.dll or extension.pyd, then tries to locate and call
> 'void initextension (void)' and will fail if this is not found.

More importantly, is this *desirable* or *useful*?  This doesn't sound
like a useful thing to support; in fact, it sounds like a downright
*bad* idea to let developers name their module initializer anything
other than "init" + extension_name.  (Assuming that it even works -- if
the symbols exported from a DLL really can be aliased in the way that
Lyle's "initmodule = _initmodule" example implies, then that demolishes
Thomas' argument... but it doesn't make this kind of trickery a good
idea!)

3. Second topic: temporary files

[Lyle]
> Changing the subject, it might also be appropriate to pass down the
> temporary files directory for the current extension's build, unless this
> kind of code:
>             
>         build_ext = self.find_peer ('build_ext')
>       build_temp = build_ext.build_temp
> 
> is considered safe. If this doesn't violate encapsulation (for the compiler
> object to know that the build_ext object has an attribute named
> "build_temp") then I'll just do this and sleep soundly ;)

If you're talking about putting this code in one (or more) of the
CCompiler classes, then Thomas was right: I don't like this.
Furthermore, it won't work -- 'find_peer()' is a method of Command, and
CCompiler is independent of that class hierarchy.

I think the right thing to do is add a 'temp_dir' attribute to
CCompiler.  (I see no reason to allow overriding this in every method.)
Currently this would not gain much, just the ability to move a bit of
the MSVC-specific code out of build_ext.py (specifically, the stuff that
generates the /IMPLIB: option).  But if it's necessary to support
Borland's compiler cleanly, I'm willing to do it.

Here are proposed semantics for 'temp_dir':
  * files that are obviously compiler/linker turds (like the stuff
    Lyle is talking about, and the MSVC turds that Thomas took care
    of several months ago by generating that /IMPLIB: option)
    would unconditionally go in 'temp_dir'
  * intermediate products, specifically object files, would go
    under 'temp_dir' unless you pass 'output_dir' to 'compile()'
  * 'temp_dir' would really be the root of a temporary tree,
    to avoid possible name collisions.  Eg. if you compile
    "src/foo/a.c" and "src/bar/a.c", you'd get "<temp_dir>/src/foo/a.o"
    and "<temp_dir>/src/bar/a.o"
  * in the distutils context (ie. the "build_ext" command), temp_dir
    would be build/temp.<plat> -- ie. build_ext would do something like
       self.compiler.temp_dir = self.build_temp
    and that's the only use it would have for 'self.build_temp'
  * the compiler classes would be responsible for making sure any
    output directories (temp_dir or otherwise) exist before
    writing to them
  * the compiler classes are *not* responsible for cleaning up the
    temp dir -- that way, we can reuse .o files across builds.
    In the Distutils context, the user is responsible for cleaning
    via the "clean" command

Sound reasonable?

        Greg
-- 
Greg Ward - Unix geek                                   gward@python.net
http://starship.python.net/~gward/
"Passionate hatred can give meaning and purpose to an empty life."
    -- Eric Hoffer