[Distutils] wish list

Greg Ward gward@cnri.reston.va.us
Mon, 17 Jan 2000 16:09:40 -0500


On 13 January 2000, Paul F. Dubois said:
> Here's my wish list after some use of Distutils-0.1.2
> 
> 1. The object files should go in some subdirectory of build so that I
> can clean up by just blowing away that directory.

Agreed.  It's not done that way because I thought it would be cute to
compile a bunch of source files together (gcc -c foo.c bar.c baz.c
instead of 3 compiler invocations).  I remember the ability to do this
with Borland make under MS-DOS was a big win about 8 years ago, but it
has a couple of annoying side-effects: poor feedback (compiler sits
there churning for several minutes without uttering a peep) and
inability to control where the .o files go (without doing a chdir, which
I want to avoid).  (Actually, it can and does move them out of the
current directory when done.  This doesn't work too well if the user
kills the build, though.)

Oh, another thing: you've given a good reason for dropping the .o's in
'build/'.  But there's an almost equally good reason for *not* doing so:
'build/' is supposed to be trivially installable, and putting temporary
files there would break that.  Damn.

I guess a 'clean' command is the right way to do it.  It would need to
know where to find .o files (s/.c/.o/ on all the sources listed in
'ext_modules' should do the trick... well, OK, s/.[cC](pp|xx)?/.o/ to
handle C++ source files.  You get the idea.  And it could just blow away
'build/' with a single 'rmtree()' call.  One nice thing about having a
'clean' command is that you could tell it how clean you want to be,
e.g. only clean up .o files, only clean up the build directory, etc.

> 2. Sometimes I eliminate a .py file but there is a copy in build that still
> gets installed.  

Glib answer: that's why we need a 'clean' command!

Real answer: hmmm.  Does that mean we need to scan the build directory,
see if there's anything there that doesn't exist in the source
directory, and warn about it?  That's the only real solution I can think
of.

> 3. If you just type python setup.py the information you get back is not
> helpful, since you don't know what the commands are.  I think it should list
> all the legal commands.

That should be doable.  Guess it means I'd need to add a canonical list
of the standard commands -- I s'pose distutils/command/__init__.py would
be the way to do that.  I just realized something nice: the cmdclass
dictionary (which is how you supply custom command classes, whether
they're extended versions of standard commands or completely new
commands) will give the list of all non-standard commands available in
the current run.  Nice!

Minor problem: there needs to be a standard way for a command class to
advertise what it does, so that this mythical list of commands can
include a blurb about each one.  This should be doable with a class
attribute, but it adds one more little thing to the interface you must
follow to implement a command class.  This doesn't bother me especially.

Slightly bigger problem: many commands are clearly subordinate to each
other (eg. 'build_py' and 'build_ext' "belong to" 'build'), but this is
not formally noted anywhere.  Would the mythical list of commands be
helped if it could convey this information?  Here are some possible
formats for the command list to take.  First, no mention of the implicit
"hierarchy of commands":

  Available commands:
    build        - build all modules and extensions
    build_py     - build (ie. prepare for installation) all pure Python
                   modules
    build_ext    - build (compile and link) all C/C++ extension modules
    install      - install all modules and extensions
    install_py   - install all pure Python modules
    install_ext  - install all extension modules

Here's what it might look like if we leave it up to the command classes'
descriptive blurb to describe the run-time relationships between
commands in the text:

  Available commands:
    build        - build all modules and extensions (runs 'build_py' and
                   'build_ext')
    build_py     - build (ie. prepare for installation) all pure Python
                   modules
    build_ext    - build (compile and link) all C/C++ extension modules
    install      - install all modules and extensions (runs 'build',
                   'install_py', and 'install_ext')
    install_py   - install all pure Python modules
    install_ext  - install all extension modules

And here's what it might look like if the code "knows" about the
run-time command hierarchy:

  Available commands:
    build        - build all modules and extensions
      build_py   - build (ie. prepare for installation) all pure Python
                   modules
      build_ext  - build (compile and link) all C/C++ extension modules
    install      - install all modules and extensions
      install_py - install all pure Python modules
      install_ext- install all extension modules

Any preferences?

        Greg