Hi again --
[cc'd to Paul Dubois: you said you weren't following the distutils sig
anymore, but this directly concerns NumPy and I'd like to get your
input!]
here's that sample setup.py for NumPy. See below for discussion (and
questions!).
------------------------------------------------------------------------
#!/usr/bin/env python
# Setup script example for building the Numeric extension to Python.
# This does sucessfully compile all the .dlls. Nothing happens
# with the .py files currently.
# Move this file to the Numerical directory of the LLNL numpy
# distribution and run as:
# python numpysetup.py --verbose build_ext
#
# created 1999/08 Perry Stoll
__rcsid__ = "$Id: numpysetup.py,v 1.1 1999/09/12 20:42:48 gward Exp $"
from distutils.core import setup
setup (name = "numerical",
version = "0.01",
description = "Numerical Extension to Python",
url = "http://www.python.org/sigs/matrix-sig/",
ext_modules = [ ( '_numpy', { 'sources' : [ 'Src/_numpymodule.c',
'Src/arrayobject.c',
'Src/ufuncobject.c'
],
'include_dirs' : ['./Include'],
'def_file' : 'Src/numpy.def' }
),
( 'multiarray', { 'sources' : ['Src/multiarraymodule.c'],
'include_dirs' : ['./Include'],
'def_file': 'Src/multiarray.def'
}
),
( 'umath', { 'sources': ['Src/umathmodule.c'],
'include_dirs' : ['./Include'],
'def_file' : 'Src/umath.def' }
),
( 'fftpack', { 'sources': ['Src/fftpackmodule.c', 'Src/fftpack.c'],
'include_dirs' : ['./Include'],
'def_file' : 'Src/fftpack.def' }
),
( 'lapack_lite', { 'sources' : [ 'Src/lapack_litemodule.c',
'Src/dlapack_lite.c',
'Src/zlapack_lite.c',
'Src/blas_lite.c',
'Src/f2c_lite.c'
],
'include_dirs' : ['./Include'],
'def_file' : 'Src/lapack_lite.def' }
),
( 'ranlib', { 'sources': ['Src/ranlibmodule.c',
'Src/ranlib.c',
'Src/com.c',
'Src/linpack.c',
],
'include_dirs' : ['./Include'],
'def_file' : 'Src/ranlib.def' }
),
]
)
------------------------------------------------------------------------
First, what d'you think? Too clunky and verbose? Too much information
for each extension? I kind of think so, but I'm not sure how to reduce
it elegantly. Right now, the internal data structures needed to compile
a module are pretty obviously exposed: is this a good thing? Or should
there be some more compact form for setup.py that will be expanded later
into the full glory we see above?
I've already made one small step towards reducing the amount of cruft by
factoring 'include_dirs' out and supplying it directly as a parameter to
'setup()'. (But that needs code not in the CVS archive yet, so I've
left the sample setup.py the same for now.)
The next thing I'd like to do is get that damn "def_file" out of there.
To support it in MSVCCompiler, there's already an ugly hack that
unnecessarily affects both the UnixCCompiler and CCompiler classes, and
I want to get rid of that. (I refer to passing the 'build_info'
dictionary into the compiler classes, if you're familiar with the code
-- that dictionary is part of the Distutils extension-building system,
and should not propagate into the more general compiler classes.)
But I don't want to give these weird "def file" things standing on the
order of source files, object files, libraries, etc., because they seem
to me to be a bizarre artifact of one particular compiler, rather than
something present in a wide range of C/C++ compilers.
Based on the NumPy model, it seems like there's a not-too-kludgy way to
handle this problem. Namely:
if building extension "foo":
if file "foo.def" found in same directory as "foo.c"
add "/def:foo.def" to MSVC command line
this will of course require some platform-specific code in the build_ext
command class, but I figured that was coming eventually, so why put it
off? ;-)
To make this hack work with NumPy, one change would be necessary: rename
Src/numpy.def to Src/_numpy.def to match Src/_numpy.c, which implements
the _numpy module. Would this be too much to ask of NumPy? (Paul?)
What about other module distributions that support MSVC++ and thus ship
with "def" files? Could they be made to accomodate this scheme?
Thanks for your feedback --
Greg
--
Greg Ward - software developer gward(a)cnri.reston.va.us
Corporation for National Research Initiatives
1895 Preston White Drive voice: +1-703-620-8990
Reston, Virginia, USA 20191-5434 fax: +1-703-620-0913
Hi all --
at long last, I found the time to hack in the ability to compile
extension modules to the Distutils. Mainly, this meant adding a
'build_ext' command which uses a CCompiler instance for all its dirty
work. I also had to add a few methods to CCompiler (and, of course,
UnixCCompiler) to make this work.
And I added a new module, 'spawn', which takes care of running
sub-programs more efficiently and robustly (no shell involved) than
os.system. That's needed, obviously, so we can run the compiler!
If you're in the mood for grubbing over raw source code, then get the
latest from CVS or download a current snapshot. See
http://www.python.org/sigs/distutils-sig/implementation.html
for a link to the code snapshot.
I'm still waiting for more subclasses of CCompiler to appear. At the
very least, we're going to need MSVCCompiler to build extensions on
Windows. Any takers? Also, someone who knows the Mac, and how to run
compilers programmatically there, will have to figure out how to write a
Mac-specific concrete CCompiler subclass.
The spawn module also needs a bit of work to be portable. I suspect
that _win32_spawn() (the intended analog to my _posix_spawn()) will be
easy to implement, if it even needs to go in a separate function at all.
It looks from the Python Library documentation for 1.5.2 that the
os.spawnv() function is all we need, but it's a bit hard to figure out
just what's needed. Windows wizards, please take a look at the
'spawn()' function and see if you can make it work on Windows.
As for actually compiling extensions: well, if you can figure out the
build_ext command, go ahead and give it a whirl. It's a bit cryptic
right now, since there's no documentation and no example setup.py. (I
have a working example at home, but it's not available online.) If you
feel up to it, though, see if you can read the code and figure out
what's going on. I'm just hoping *I'll* be able to figure out what's
going on when I get back from the O'Reilly conference next week... ;-)
Enjoy --
Greg
--
Greg Ward - software developer gward(a)cnri.reston.va.us
Corporation for National Research Initiatives
1895 Preston White Drive voice: +1-703-620-8990
Reston, Virginia, USA 20191-5434 fax: +1-703-620-0913
Hi all --
at long last, I have fixed two problems that a couple people noticed a
while ago:
* I folded in Amos Latteier's NT patches almost verbatim -- just
changed an `os.path.sep == "/"' to `os.name == "posix"' and added
some comments bitching about the inadequacy of the current library
installation model (I think this is Python's fault, but for now
Distutils is slavishly aping the situation in Python 1.5.x)
* I fixed the problem whereby running "setup.py install" without
doing anything else caused a crash (because 'build' hadn't yet
been run). Now, the 'install' command automatically runs 'build'
before doing anything; to make this bearable, I added a 'have_run'
dictionary to the Distribution class to keep track of which commands
have been run. So now not only are command classes singletons,
but their 'run' method can only be invoked once -- both restrictions
enforced by Distribution.
The code is checked into CVS, or you can download a snapshot at
http://www.python.org/sigs/distutils-sig/distutils-19990607.tar.gz
Hope someone (Amos?) can try the new version under NT. Any takers for
Mac OS?
BTW, all parties involved in the Great "Where Do We Install Stuff?"
Debate should take a good, hard look at the 'set_final_options()' method
of the Install class in distutils/install.py; this is where all the
policy decisions about where to install files are made. Currently it
apes the Python 1.5 situation as closely as I could figure it out.
Obviously, this is subject to change -- I just don't know to *what* it
will change!
Greg
--
Greg Ward - software developer gward(a)cnri.reston.va.us
Corporation for National Research Initiatives
1895 Preston White Drive voice: +1-703-620-8990
Reston, Virginia, USA 20191-5434 fax: +1-703-620-0913
Hi all,
I've been aware that the distutils sig has been simmerring away, but
until recently it has not been directly relevant to what I do.
I like the look of the proposed api, but have one question. Will this
support an installed system that has multiple versions of the same
package installed simultaneously? If not, then this would seem to be a
significant limitation, especially when dependencies between packages
are considered.
Assuming it does, then how will this be achieved? I am presently
managing this with a messy arrangement of symlinks. A package is
installed with its version number in it's name, and a separate
directory is created for an application with links from the
unversioned package name to the versioned one. Then I just set the
pythonpath to this directory.
A sample of what the directory looks like is shown below.
I'm sure there is a better solution that this, and I'm not sure that
this would work under windows anyway (does windows have symlinks?).
So, has this SIG considered such versioning issues yet?
Cheers,
Tim
--------------------------------------------------------------
Tim Docker timd(a)macquarie.com.au
Quantative Applications Division
Macquarie Bank
--------------------------------------------------------------
qad16:qad $ ls -l lib/python/
total 110
drwxr-xr-x 2 mts mts 512 Nov 11 11:23 1.1
-r--r----- 1 root mts 45172 Sep 1 1998 cdrmodule_0_7_1.so
drwxr-xr-x 2 mts mts 512 Sep 1 1998 chart_1_1
drwxr-xr-x 3 mts mts 512 Sep 1 1998 Fnorb_0_7_1
dr-xr-x--- 3 mts mts 512 Nov 11 11:21 Fnorb_0_8
drwxr-xr-x 3 mts mts 1536 Mar 3 12:45 mts_1_1
dr-xr-x--- 7 mts mts 512 Nov 11 11:22 OpenGL_1_5_1
dr-xr-x--- 2 mts mts 1024 Nov 11 11:23 PIL_0_3
drwxr-xr-x 3 mts mts 512 Sep 1 1998 Pmw_0_7
dr-xr-x--- 2 mts mts 512 Nov 11 11:21 v3d_1_1
qad16:qad $ ls -l lib/python/1.1
total 30
lrwxrwxrwx 1 root other 29 Apr 10 10:43 _glumodule.so -> ../OpenGL_1_5_1/_glumodule.so
lrwxrwxrwx 1 root other 30 Apr 10 10:43 _glutmodule.so -> ../OpenGL_1_5_1/_glutmodule.so
lrwxrwxrwx 1 root other 22 Apr 10 10:43 _imaging.so -> ../PIL_0_3/_imaging.so
lrwxrwxrwx 1 root other 36 Apr 10 10:43 _opengl_nummodule.so -> ../OpenGL_1_5_1/_opengl_nummodule.so
lrwxrwxrwx 1 root other 27 Apr 10 10:43 _tkinter.so -> ../OpenGL_1_5_1/_tkinter.so
lrwxrwxrwx 1 mts mts 21 Apr 10 10:43 cdrmodule.so -> ../cdrmodule_0_7_1.so
lrwxrwxrwx 1 mts mts 12 Apr 10 10:43 chart -> ../chart_1_1
lrwxrwxrwx 1 root other 12 Apr 10 10:43 Fnorb -> ../Fnorb_0_8
lrwxrwxrwx 1 mts mts 12 Apr 10 10:43 mts -> ../mts_1_1
lrwxrwxrwx 1 root other 15 Apr 10 10:43 OpenGL -> ../OpenGL_1_5_1
lrwxrwxrwx 1 root other 33 Apr 10 10:43 opengltrmodule.so -> ../OpenGL_1_5_1/opengltrmodule.so
lrwxrwxrwx 1 root other 33 Apr 10 10:43 openglutil_num.so -> ../OpenGL_1_5_1/openglutil_num.so
lrwxrwxrwx 1 root other 10 Apr 10 10:43 PIL -> ../PIL_0_3
lrwxrwxrwx 1 mts mts 10 Apr 10 10:43 Pmw -> ../Pmw_0_7
lrwxrwxrwx 1 root other 10 Apr 10 10:43 v3d -> ../v3d_1_1
I apologize of this is documented somewhere. If it
is, I haven't found it. I've done lots of python
modules, but not any packages, so if I'm just
package ignorant feel free to slap me.....
It all started in the early Zope days when I loaded
Zope only to discover that all my scripts using
Marc Lemburg's mxDateTime bombed because Zope's
DateTime produced a namespace collision. The solution
then was to move Zope, since I didn't 'need' it at
the time.
Now I do. So, I contacted Marc who, of course, knew
about the collision and has already started looking
at packaging all his stuff under an umbrella "mx"
package. When I asked about Distutils, he hadn't
really looked at it so I volunteered to see what
it would take.
Since Distutils includes a sample mxDateTime setup.py,
it seemed fairly easy. I hacked it up to push it down
a level (see attempt below). No problem except, of
course, that it doesn't import because there's no
mx.__init__.py. Ok, so I add an mx.__init__.py with
__all__ defined and appropriate imports. Everything's
happy and Distutils does fine.
Now, I add in mx.TextTools and things get murkier.
How does mx.__init__.py determine what __all__
should be and what to import? How do I tell
Distutils about the other packages? I tried a
single all-purpose Distutils setup.py that searches
the mx package directory and adds in the sub-packages
that it finds. So far so good. Now, what about
mx.__init__.py?
Should it:
1) Search it's package directory at runtime to
determine what __all__ should be and what
subpackages to import? If it does that, then
mx.__init__.py will exist in all possible
mx packages. Distutils probably won't care and
will happily copy the lastest __init__.py into
place (since they "should" all be the same,
that's not a problem). BUT -- what if I make
packages with --bdist-WHATEVER. Package manager
WHATEVER is going to not be pleased with
multiple packages that all provide mx.__init__.py.
Some type of package forcing is going to have
to occur for all except the first subpackage
installed.
- OR -
2) Be created dynamically at "install" time. The
all-purpose setup.py can scan when Distutils
runs and programatically create an __init__.py
at installation time that meets the needs of
the currently installed subpacakges. BUT --
that doesn't help when I used --bdist-WHATEVER
again, because the resulting package is going
to be installed on a system that probably does
not have the same set of subpackages installed.
I'll have to provide a postinstall script to
WHATEVER to create __init__.py on the install
host. Do-able, but now I'm manually tacking
stuff on to the package that --bdist-WHATEVER
can't (unless I missed it) handle. And,
mx.__init__.py is not registered to the package
somewhat defeating the purpose.
It looks like --bdist-WHATEVER needs information about
pre- and post-installation processing. This would have
to be included in setup.py somewhere. But what should
it be? Package managers (that support pre/post install)
expect shell scripts. It would be really nice if --bdist
took a python function and wrapped it for us in a shell
wrapper, e.g.
#!/bin/sh
python -i <<EOF
def postinstall():
...
postinstall
EOF
So, am I missing something or are these issues real?
FWIW, I've included the directory scanning setup.py
below. If you try it, it "almost" works for mxDateTime,
mxTextTools, and mxNewBuiltins. There's still some
issues with mx sub-modules that I'm ignorant of, but
they're not related to this discussion.
Mark
mwa(a)gate.net
############## mx.DateTime setup.py ################
#!/usr/bin/env python
import os
""" setup.py for Marc-Andr� Lemburg's mx Extension modules
Will scan the 'mx' directory for Marc's packages
(just DateTime, TextTools, and NewBuiltins so far....)
and provide the Distutils infor for all found packages.
."""
# created 1999/09/19, Greg Ward
# pushed to mx package by Mark Alexander
__revision__ = "$Id: mxdatetime_setup.py,v 1.4 2000/03/02 01:49:46 gward Exp $"
from distutils.core import setup
DateTimePackages=['mx.DateTime', 'mx.DateTime.Examples', 'mx.DateTime.mxDateTime']
DateTimeExtensions=[('mx.DateTime.mxDateTime.mxDateTime',
{ 'sources': ['mx/DateTime/mxDateTime/mxDateTime.c'],
'include_dirs': ['mxDateTime'],
'macros': [('HAVE_STRFTIME', None),
('HAVE_STRPTIME', None),
('HAVE_TIMEGM', None)], }
)]
TextToolsPackages=['mx.TextTools','mx.TextTools','mx.TextTools.Constants','mx.TextTools.Examples']
TextToolsExtensions=[('mx.TextTools.mxTextTools.mxTextTools',
{ 'sources': ['mx/TextTools/mxTextTools/mxTextTools.c'],
'include_dirs': ['mxTextTools'],
'macros': [('HAVE_STRFTIME', None),
('HAVE_STRPTIME', None),
('HAVE_TIMEGM', None)], }
)]
NewBuiltinsPackages=['mx.NewBuiltins','mx.NewBuiltins.Examples','mx.NewBuiltins.mxTools']
NewBuiltinsExtensions=[('mx.NewBuiltins.mxTools.mxTools',
{ 'sources': ['mx/NewBuiltins/mxTools/mxTools.c'],
'include_dirs': ['NewBuiltins'],
'macros': [('HAVE_STRFTIME', None),
('HAVE_STRPTIME', None),
('HAVE_TIMEGM', None)], }
),
('mx.NewBuiltins.mxTools.xmap',
{ 'sources': ['mx/NewBuiltins/mxTools/xmap.c'],
'include_dirs': ['NewBuiltins'],
'macros': [('HAVE_STRFTIME', None),
('HAVE_STRPTIME', None),
('HAVE_TIMEGM', None)], }
)]
mxPackages=['mx']
mxExtensions=[]
if os.path.isdir('mx/DateTime'):
mxPackages=mxPackages+DateTimePackages
mxExtensions=mxExtensions+DateTimeExtensions
if os.path.isdir('mx/TextTools'):
mxPackages=mxPackages+TextToolsPackages
mxExtensions=mxExtensions+TextToolsExtensions
if os.path.isdir('mx/NewBuiltins'):
mxPackages=mxPackages+NewBuiltinsPackages
mxExtensions=mxExtensions+NewBuiltinsExtensions
setup (name = "mxDateTime",
version = "1.3.0",
description = "",
author = "Marc-Andr� Lemburg",
author_email = "mal(a)lemburg.com",
url = "http://starship.python.net/~lemburg/mxDateTime.html",
packages = mxPackages,
# XXX user might have to edit the macro definitions here: yuck!
# Probably do need to support 'Setup' file or something similar.
ext_modules = mxExtensions,
)
The bdist command in the CVS version is broken under windows.
Two problems:
1. It seems the needed directories are not created:
.
.
.
self.bdist_dir = build\bdist.win32\dumb
self.format = zip
changing into 'build\bdist.win32\dumb'
error: build\bdist.win32\dumb: No such file or directory
2. This error occurrs only after hacking around the second problem:
change_root(), which is not implemented for nt.
Having said this, I cannot really understand the purpose of change_root.
Finally I tried distutils under Linux, and it seems that
change_root converts relative into (nearly) absolute pathnames:
usr/lib/python1.5/site-packages/distutils/...
This MAY make sense under unix, where python is always(?) installed
in the same path, but not under windows!
Thomas Heller
Hi all (especially to the two [?] of you working on support for
additional C/C++ compilers) --
I'm contemplating a major simplification in the CCompiler API that
should make life easier for anyone writing or maintaining one of the
CCompiler classes, but will raise a lot of dust for a few days.
Specifically: currently, each of the compile/link/whatever methods takes
a bunch of arguments that enhance instance attributes. For example,
every CCompiler instance carries around attributes 'include_dirs',
'libraries', and 'library_dirs'; plus, the 'compile()' method takes an
'include_dirs' parameter, and the 'link_*()' methods all take
'libraries' and 'library_dirs' parameters.
These are all combined by convenience functions provided by the
CCompiler superclass, so the code overhead to supporting this rather
complex interface isn't *too* great. However, I'm getting tired of the
*conceptual* overhead: you're forever worrying about "instance attribute
'include_dirs' vs. method argument 'include_dirs'", and so forth.
So I'd like to ditch all the extra method parameters and rely on
instance attributes as much as possible. That moves CCompiler a little
closer to representing a "compiler/linker session", which is meaningless
in Unixworld but very much relevant in Macland. (Or so I gather from my
spies in that strange and distant country. I'm not clear on the
situation in Windowsia, given the constant turmoil in that troubled
realm.) I think this is a good thing.
The main drawback is that it would make the "build_ext" command a bit
more complex. Currently, it sets the instance attributes for
compilation properties that apply to all extensions, and passes method
arguments for things that vary by extension. (Currently, only
'include_dirs' can do both.) It would have to take care of combining
the "global" and "per-extension" properties when it starts to build each
extension. This is not, IMHO, a big deal.
If nothing else, it would make the signatures and docstrings for the
common CCompiler methods a *lot* shorter. Opinions?
Greg
--
Greg Ward - just another /P(erl|ython)/ hacker gward(a)python.net
http://starship.python.net/~gward/
Screw up your courage! You've screwed up everything else.
I'm currently working at the Cygwin-Compiler class on Win32,
there I found a problem with "bdist".
When I have build all extensions with my compiler class and then
try to use "bdist", the msvc compiler class starts and
fails (I don't have it on my machine.)
I think there are two problems.
First the system seems to check the filedates
with the objectfile-extensions of the standard compiler
( msvc ".obj" , cygwin ".o" ). So it doesn't find my
object files, and tries to recreate them, but uses a
wrong compiler. I think it should be
possible to configure the compiler also for "bdist".
(If this is already possible? Please explain how.)
Also I think "bdist" does a "build" if there aren't
already the right files. In this case "bdist" should
accept *all* parameters which "build" accepts.
The second problem. Why "bdist" doesn't check only the
source files against the finished extension modules?
Currently it seems to check the source files against
the compiled object files.
Then there is something else concerning the compiler
option.
If the user uses help he get the information that he
can use the compiler option, but how can he know
which compilers(classes) are available. There should be
a possibility to get a list. (In ccompiler.py we have
such list, we only had print it.)
kind regards
Rene Liebscher
Greg Ward wrote:
[snip]
> I have yet to hear howls of my revulsion at my loopy idea of sticking
> this:
> import sys; sys.path.insert(0, application-python-path)
>
> into scripts that are installed as part of a "Python application" (ie.
> a module distribution whose main interface is a script or scripts, and
> that gets its own directory rather than dangling off Python's library
> directory). Could it be that people actually think this is a *good*
> idea? ;-)
[snip]
Problem is, the alternatives are equally bad.
Ok, playing Devil's advocate: one issue is that if the user (or sysadmin)
chooses to move the application directory tree, everything will stop
working. Since this also causes problems for uninstall (and probably many
other things), the best solution for this problem is *don't do this*.
One thing to consider is that the python interpreter automatically prepends
the path of the script into sys.path. Therefore, if you install your
scripts into the root of your application install directory, you don't need
do do any path-mangling.
=============================================================================
michaelMuller = mmuller(a)enduden.com | http://www.cloud9.net/~proteus
-----------------------------------------------------------------------------
In this book it is spoken of the Sephiroth, and the Paths, of Spirits and
Conjurations; of Gods, Spheres, Planes and many other things which may or
may not exist. It is immaterial whether they exist or not. By doing
certain things certain results follow. - Aleister Crowley
=============================================================================