[Distutils] How can I create prebuilt distributions?

Thomas Heller theller@python.net
Fri Feb 14 03:08:00 2003


Jack Jansen <Jack.Jansen@oratrix.com> writes:

> I remember that this was discussed some time ago, but at that time I
> wasn't interested, and now I can't find it back in the archives. Can
> someone help me out?
> 
> 
> I want to create binary packages (i.e. packages that are usable if the
> end-user doesn't have a development environment). For now I'm happy
> with something that works on Unix (MacOSX to be specific).
> 
> 
> I had always thought that bdist did this, but it turns out that it
> does something completely different: it creates a tar file with all
> pathnames already hard-coded. This isn't good enough, as it doesn't
> allow the end user to select install location, etc.
> 
> 
> What I want as output is a tarfile with inside it basically a tree
> that has seen "setup.py build", but with some extra glue so it doesn't
> try to build again. If I simply tar the tree after the build this
> doesn't work: on the destination machine it still tries to build
> things, probably due to differences in modification times or
> something. This won't work if the end user doesn't have a c compiler,
> of course.
> 

IIRC, I've first seen Pete Shinners doing this, so maybe you want to
ask him also.

I've also thought about this some time, and experimented a little bit.
Here is a technique which seems to work (on Windows, with Python2.2.2).

Overrider the sdist command in your setup script by a class which doesn't
remove the build tree from the file list (I think this may be a buglet:
If the build tree is specified in the MANIFEST.in file, it should NOT
be removed later):

  from distutils.command import sdist

  class my_sdist(sdist.sdist):
      def prune_file_list (self):
          """Prune off branches that might slip into the file list as created
          by 'read_template()', but really don't belong there:
            * the build tree (typically "build")
            * the release tree itself (only an issue if we ran "sdist"
              previously with --keep-temp, or it aborted)
            * any RCS or CVS directories
          """
          build = self.get_finalized_command('build')
          base_dir = self.distribution.get_fullname()

  ## Commented out, because we want the build tree to be included
  ##        self.filelist.exclude_pattern(None, prefix=build.build_base)
          self.filelist.exclude_pattern(None, prefix=base_dir)
          self.filelist.exclude_pattern(r'/(RCS|CVS)/.*', is_regex=1)

and later:

  setup(...
        cmdclass = {'sdist': my_sdist},
        ...)    


Then, in your MANIFEST.in file, insert something like this:

  recursive-include build *.obj *.pyd

Finally, first run 'python setup.py build', and then 'python setup.py sdist'.
This creates a zip-file (default on Windows), which can be unpacked somewhere,
and, since the timestamps are ok, be 'built' without a C compiler (as long
as you don't change the sources).

I haven't tried it, but it should also be possible to include prebuild
binaries for several Pythin versions.

> 
> Also, I wouldn't mind losing all the source code to trim down the
> archive size.

Also a task for either the MANIFEST.in file, or your custom sdist class.

Thomas