/[thuban]/branches/WIP-pyshapelib-bramz/setup.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/setup.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (hide annotations)
Fri Aug 31 15:35:18 2001 UTC (23 years, 6 months ago) by bh
Original Path: trunk/thuban/setup.py
File MIME type: text/x-python
File size: 23016 byte(s)
numerous fixes and majopr additions for the windows installer with Inno Setup

1 bh 6 # Copyright (c) 2001 by Intevation GmbH
2     # Authors:
3     # Bernhard Herzog <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with Thuban for details.
7    
8     """Distutils setup script for Thuban."""
9    
10     __version__ = "$Revision$"
11    
12     # Configuration:
13     #
14     # depending on your platform you may have to configure some variables by
15     # hand below.
16     #
17    
18     import os
19 bh 15 from types import TupleType
20 bh 6 from distutils.core import setup, Extension, Command
21     from distutils.command.install import install
22     from distutils.command.build_py import build_py
23 bh 15 from distutils.file_util import write_file
24     from distutils.util import convert_path
25 bh 6
26     import distutils
27    
28     from string import split
29     import string
30    
31     if os.name == "posix":
32     ###################################################################
33     # Posix configuration. Adapt this if you're running some kind of
34     # Unix like system.
35    
36     # Directories where Proj4 is installed
37     proj4_prefix = "/usr/local/"
38     proj4_incdir = os.path.join(proj4_prefix, "include")
39     proj4_libdir = os.path.join(proj4_prefix, "lib")
40     proj4_lib = "proj"
41    
42    
43     # You shpuldn't have to modify anything below here
44     ###################################################################
45    
46     # The installation prefix (similar to autoconf's --prefix). This is
47     # only the default value, you can override it on the command line
48     # with the install command's --prefix option
49     prefix = "/usr/local/"
50    
51     # On POSIX-systems we run wxgtk-config to determine the C++-compiler
52     # flags
53     wx_config_script = "wxgtk-config"
54     # These lists will be filled automatically below
55     wx_defs = []
56     wx_incdirs = []
57     wx_libdirs = []
58     wx_libs = []
59    
60     elif os.name == "nt":
61     #################################################################
62     # Windows configuration.
63     #
64    
65     # Directories where Proj4 is installed
66     proj4_prefix = r"D:\cygwin\home\user\proj-4.4.3\src"
67     proj4_incdir = proj4_prefix
68     proj4_libdir = proj4_prefix
69     proj4_lib = "proj_i"
70    
71 bh 15 # Define include and lib directories for wxWindows and
72     wx_prefix = r"D:\wx230"
73     wx_inc = os.path.join(wx_prefix, "include")
74     wx_lib = os.path.join(wx_prefix, "lib")
75    
76 bh 6 #
77     # Unless you use a wxPython version other than 2.3.1, you probably
78     # shouldn't have to modify anything below here
79     ##################################################################
80    
81     # Installation prefix. Just install relative to current directory by
82     # default. This is only the default value, you can override it on
83     # the command line with the install command's --prefix option
84     prefix = r"install"
85    
86     # There doesn't seem to be an easy way to get at the wx compiler
87     # flags, so we define them here. These flags work for us with
88     # wxPython 2.3.1. They may have to be modified for other versions.
89    
90     # there's no config script.
91     wx_config_script = ""
92    
93     # the values of wx_defs and wx_libs. copied from the wxPython
94     # setup.py
95     wx_defs = [ ('WIN32', None), # Some of these are no longer
96     ('__WIN32__', None), # necessary. Anybody know which?
97     ('_WINDOWS', None),
98     ('__WINDOWS__', None),
99     ('WINVER', '0x0400'),
100     ('__WIN95__', None),
101     ('STRICT', None),
102    
103     ('__WXMSW__', None),
104     ('WXUSINGDLL', '1'),
105    
106     ('SWIG_GLOBAL', None),
107     ('HAVE_CONFIG_H', None),
108     ('WXP_USE_THREAD', '1'),
109     ]
110    
111     wx_incdirs = [wx_inc]
112     wx_libdirs = [wx_lib]
113     wx_libs = ["wx23_1h"]
114     wx_libs = wx_libs + ['kernel32', 'user32', 'gdi32', 'comdlg32',
115     'winspool', 'winmm', 'shell32', 'oldnames',
116     'comctl32', 'ctl3d32', 'odbc32', 'ole32', 'oleaut32',
117     'uuid', 'rpcrt4', 'advapi32', 'wsock32']
118     else:
119     raise RuntimeError("Unsupported platform " + os.name)
120    
121    
122     ######################################################################
123     #
124     # There's nothing beyond this point that has to be modified for a
125     # normal installation
126     #
127     ######################################################################
128    
129    
130     #
131     # Functions to determine wxWindows config on POSIX systems
132     #
133    
134     def run_script(cmdline):
135     """Run command and return its stdout or none in case of errors"""
136     pipe = os.popen(cmdline)
137     result = pipe.read()
138     if pipe.close() is not None:
139     print '"' + cmdline + '"', 'failed'
140     return None
141     return result
142    
143    
144     def run_wx_script(command):
145     # first, determine the C++ preprocessor flags
146     flags = run_script(command + ' --cxxflags ')
147     if flags is None:
148     return 0
149     for flag in split(flags):
150     start = flag[:2]
151     value = flag[2:]
152     if start == "-I":
153     wx_incdirs.append(value)
154     elif start == "-D":
155     wx_defs.append((value, None))
156    
157     # determine the library flags
158     flags = run_script(command + ' --libs')
159     if flags is None:
160     return 0
161     for flag in split(flags):
162     start = flag[:2]
163     value = flag[2:]
164     if start == "-L":
165     wx_libdirs.append(value)
166     elif start == "-l":
167     wx_libs.append(value)
168    
169     if wx_config_script:
170     # if there's a wx config script, run it to determine the configuration
171     run_wx_script(wx_config_script)
172    
173    
174    
175     #
176     # Define some extension and python modules
177     #
178     # The C-extension names are prefixed woth "Lib." so they get put into
179     # the Lib/ subdirectory. Lib/ is not really a package but distutils
180     # doesn't care
181    
182     # subdirectory containing the extensions
183     ext_dir = "extensions"
184    
185     # subdirectory with some shapelib files
186     shp_dir = ext_dir + "/shapelib"
187    
188     # lists to fill with the module descriptions
189     extensions = []
190     py_modules = []
191    
192    
193     #
194     # Thuban specific modules
195     #
196    
197     extensions.append(Extension("Lib.wxproj",
198     [ext_dir + "/thuban/wxproj.cpp",
199     shp_dir + "/shpopen.c"],
200     include_dirs = [shp_dir, proj4_incdir] +wx_incdirs,
201     define_macros = wx_defs,
202     library_dirs = [proj4_libdir] + wx_libdirs,
203     libraries = [proj4_lib] + wx_libs))
204    
205     #
206     # shapelib wrappers are also distributed with thuban
207     #
208    
209     extensions.append(Extension("Lib.shapelibc",
210     [ext_dir + "/pyshapelib/shapelib_wrap.c",
211     shp_dir + "/shpopen.c"],
212     include_dirs = [shp_dir]))
213     extensions.append(Extension("Lib.dbflibc",
214     [ext_dir + "/pyshapelib/dbflib_wrap.c",
215     shp_dir + "/dbfopen.c"],
216     include_dirs = [shp_dir]))
217     for name in ("shapelib", "dbflib"):
218     py_modules.append(ext_dir + "/pyshapelib/" + name)
219    
220     #
221     # PROJ4 bindings are also distributed with thuban
222     #
223     extensions.append(Extension("Lib.Projectionc",
224     [ext_dir + "/pyprojection/Projection_wrap.c"],
225     include_dirs = [proj4_incdir],
226     library_dirs = [proj4_libdir],
227     libraries = [proj4_lib]))
228     py_modules.append(ext_dir + "/pyprojection/Projection")
229    
230    
231     #
232     # Data files
233     #
234    
235     data_files = []
236    
237     # bitmaps
238 bh 15 dir = "Resources/Bitmaps"
239 bh 6 bitmaps = []
240     for file in os.listdir(os.path.join("Resources", "Bitmaps")):
241     if string.lower(file[-4:]) == ".xpm":
242 bh 15 bitmaps.append(dir + '/' + file)
243 bh 6 data_files.append((dir, bitmaps))
244    
245     #
246     # Command definitions
247     #
248     # So far distutils are only meant to distribute python extensions, not
249     # complete applications, so we have to redefine a few commands
250    
251    
252    
253     class InstallLocal(Command):
254    
255     """
256     A new install command to just link (or copy, on non-POSIX systems)
257     the extension modules to the top directory so that Thuban can be run
258     directly from the source dir.
259     """
260    
261     description =\
262     "Create some symlink so you can run thubanfrom the source directory"
263    
264     user_options = [
265     ('skip-build', None, "skip the build steps"),
266     ]
267    
268     def initialize_options (self):
269     self.extensions = None
270     self.build_dir = None
271     self.skip_build = None
272    
273     def finalize_options (self):
274     self.set_undefined_options("install",
275     ("build_lib", "build_dir"),
276     ('skip_build', 'skip_build'))
277     self.extensions = self.distribution.ext_modules
278    
279     def run(self):
280     # Make sure we have built everything we need first
281     self.build()
282    
283     # now do the work. Simply link or copy the Lib dir
284     libdir = os.path.join(self.build_dir, "Lib")
285     if os.name == "posix":
286     # on posix, just lilnk the Lib dir
287     self.link_dir(libdir, "Lib")
288     else:
289     self.copy_tree(libdir, "Lib")
290    
291     def link_dir(self, src, dest):
292     """Create a symbolic link dest pointing to src"""
293     if self.verbose:
294 bh 15 self.announce("symlinking %s -> %s" % (src, dest))
295 bh 6 if self.dry_run:
296     return
297    
298     if not (os.path.exists(dest) and os.path.samefile(src, dest)):
299     os.symlink(src, dest)
300    
301     def build (self):
302     if not self.skip_build:
303     if self.distribution.has_pure_modules():
304     self.run_command('build_py')
305     if self.distribution.has_ext_modules():
306     self.run_command('build_ext')
307    
308    
309    
310     class thuban_build_py(build_py):
311    
312     """
313 bh 8 A new build_py that can deal with both packages and modules in one
314     distribution.
315 bh 6 """
316    
317     def run(self):
318 bh 8 """The same the as the original in build_py revision 1.33 except
319 bh 6 that this allows both packages and modules to be in one
320     distribution
321     """
322     if not self.py_modules and not self.packages:
323     return
324    
325     # Now we're down to two cases: 'py_modules' only and 'packages' only.
326     if self.py_modules:
327     self.build_modules()
328     if self.packages:
329     self.build_packages()
330    
331     self.byte_compile(self.get_outputs(include_bytecode=0))
332    
333     def find_modules (self):
334     """Thuban specific version of build_py.find_modules. Unlike the
335     original version, we assume that the modules in self.py_modules
336     can contain directories and are all to be placed into the same
337     subdirectory, Lib, in the build directory. This is achieved by
338     returning the modules as a list (package, module, filename)
339     where package is 'Lib', module is the basename of the module name
340     and filename is the filename relative to the package root.
341     """
342     modules = []
343     for module in self.py_modules:
344     module_base = os.path.basename(module)
345     module_file = module + ".py"
346     if not self.check_module(module, module_file):
347     continue
348    
349     modules.append(("Lib", module_base, module_file))
350     return modules
351    
352 bh 15 def find_all_modules (self):
353     # same as find_all_modules of the original build_py command
354     # (rev. 1.33) but handle installations with both modules and
355     # packages. Needed here so tha the get_outputs works correctly
356     modules = []
357     if self.py_modules:
358     modules.extend(self.find_modules())
359     if self.packages:
360     for package in self.packages:
361     package_dir = self.get_package_dir(package)
362     m = self.find_package_modules(package, package_dir)
363     modules.extend(m)
364 bh 6
365 bh 15 return modules
366    
367    
368    
369 bh 6 class ThubanInstall(install):
370    
371 bh 8 """
372     Thuban specific install command.
373    
374     Extend the standard install command to symlink the installed script
375     to $prefix/bin/
376     """
377 bh 15
378     user_options = install.user_options[:]
379     user_options.extend([("do-symlink", None,
380     "Create a symlink to the script in <prefix>/bin."
381     "(default on posix systems and only relevant there)"),
382    
383     ("extra-files", None,
384     "List of filenames or (src, dest) pairs describing "
385     " extra files to install "
386     "(can only be set from witin setup.py"),
387     ])
388    
389     boolean_options = install.boolean_options[:]
390     boolean_options.append("do-symlink")
391    
392     def initialize_options(self):
393     self.do_symlink = None
394     self.extra_files = []
395     install.initialize_options(self)
396    
397     def finalize_options(self):
398     if self.do_symlink is None:
399     if os.name == "posix":
400     self.do_symlink = 1
401     else:
402     self.do_symlink = 0
403     install.finalize_options(self)
404    
405 bh 6 def run(self):
406     install.run(self)
407 bh 15 for item in self.extra_files:
408     if type(item) == TupleType:
409     src, dest = item
410     else:
411     src = dest = item
412     self.copy_file(convert_path(src),
413     os.path.join(self.root, convert_path(dest)))
414    
415     if os.name == "posix" and self.do_symlink:
416 bh 6 scriptfile = os.path.join(self.install_scripts, "thuban.py")
417     bindir = os.path.join(self.prefix, "bin")
418     binfile = os.path.join(bindir, "thuban")
419     self.mkpath(bindir)
420     self.copy_file(scriptfile, binfile, link="sym")
421    
422 bh 15 def get_outputs (self):
423     outputs = install.get_outputs(self)
424     for item in self.extra_files:
425     if type(item) == TupleType:
426     src, dest = item
427     else:
428     src = dest = item
429     outputs.append(os.path.join(self.root, convert_path(dest)))
430     return outputs
431 bh 6
432 bh 15 class bdist_inno(Command):
433    
434     """Command to create a windows installer with Inno Setup"""
435    
436     description = "Create a windows installer with Inno Setup"
437    
438     user_options = [
439     ('skip-build', None, "skip the build steps"),
440     ('bdist-dir=', None,
441     "temporary directory for creating the distribution"),
442     ('run-inno', None,
443     "Run inno-setup to create the installer. On by default on nt"),
444     ('iss-name', None,
445     "The name of the iss file to generate. "
446     "Shouldn't contain directories"),
447    
448     # Parameters for the Inno Setup script
449     ('copyright', None, "Copyright notice for the Inno Setup file"),
450     ('default-dir-name', None,
451     "Default installation directory. Defaults to '{pf}\\<name>'"),
452     ('default-group-name', None,
453     "Default program group name. Defaults to <name>'"),
454     ("license-file", None, "File containing the license."),
455     ("output-basename", None,
456     "Base filename for the Inno Setup output "
457     "(defaults to <name>-<version>-<issrevision>)."),
458     ("iss-revision", None,
459     "revision of the generated installer of the package version"),
460    
461     ("icons-entries", None,
462     "List if InnoIconItems "
463     "(this can only be set from inside the setup.py script)"),
464     ]
465    
466     boolean_options = ["do-symlink"]
467    
468     def initialize_options(self):
469     self.skip_build = 0
470     self.bdist_dir = None
471     self.run_inno = None
472     self.iss_name = None
473     self.copyright = ""
474     self.default_dir_name = None
475     self.default_group_name = None
476     self.license_file = None
477     self.output_basename = None
478     self.iss_revision = None
479     self.icons_entries = []
480    
481     def finalize_options(self):
482     self.set_undefined_options("install",
483     ('skip_build', 'skip_build'))
484     if self.bdist_dir is None:
485     bdist_base = self.get_finalized_command('bdist').bdist_base
486     self.bdist_dir = os.path.join(bdist_base, 'inno')
487    
488     if self.run_inno is None:
489     self.run_inno = os.name == "nt"
490    
491     name = self.distribution.get_name()
492     if self.iss_name is None:
493     self.iss_name = name + '.iss'
494    
495     if self.default_dir_name is None:
496     self.default_dir_name = "{pf}\\" + name
497     if self.default_group_name is None:
498     self.default_group_name = name
499    
500     if self.iss_revision is None:
501     self.iss_revision = 0
502     if self.output_basename is None:
503     self.output_basename = "%s-%s-%d" \
504     % (name, self.distribution.get_version(),
505     self.iss_revision)
506    
507     def run(self, install_options = None):
508     """Execute the command. install_options if given, should be a
509     directory of additional options to set in the install step"""
510     # Obviously have to build before we can install
511     if not self.skip_build:
512     self.run_command('build')
513    
514     # Install in a temporary directory
515     install = self.reinitialize_command('install')
516     install.root = self.bdist_dir
517     if install_options is not None:
518     for key, value in install_options.items():
519     setattr(install, key, value)
520     if os.name != 'nt':
521     # Must force install to use the 'nt' scheme;
522     install.select_scheme('nt')
523     # don't make a symlink because we're simulating windows, so
524     # that we can generate the iss-file even on Linux
525     install.do_symlink = 0
526    
527     self.announce("installing to %s" % self.bdist_dir)
528     install.ensure_finalized()
529     install.run()
530    
531     # Create the iss file
532     iss_file = os.path.join(self.bdist_dir, self.iss_name)
533     self.execute(write_file, (iss_file, self.generate_iss()),
534     "Create Inno Setup script file %s" % iss_file)
535    
536     # and invoke
537     if self.run_inno:
538     self.spawn(["iscc", iss_file])
539    
540     def generate_iss(self):
541     """Return the contents of the iss file as list of strings, one
542     string per line"""
543    
544     # first, turn the icons entries into a more usable form
545     icons = {}
546     for item in self.icons_entries:
547     icons[item.filename] = item
548    
549     iss = []
550    
551     name = self.distribution.get_name()
552     iss.extend(["[Setup]",
553     "AppName=" + name,
554     "AppVerName=" + name + " "+self.distribution.get_version(),
555     "DefaultDirName=" + self.default_dir_name,
556     "DefaultGroupName=" + self.default_group_name,
557     ])
558     if self.copyright:
559     iss.append("AppCopyright=" + self.copyright)
560     if self.license_file:
561     iss.append("LicenseFile=" + self.license_file)
562    
563     iss.append("OutputBasefilename=" + self.output_basename)
564    
565     iss.append("")
566     iss.append("[Files]")
567    
568     install = self.get_finalized_command("install")
569     install_scripts = self.get_finalized_command("install_scripts")
570     script_files = install_scripts.get_outputs()
571     prefixlen = len(self.bdist_dir) + len(os.sep)
572     for filename in install.get_outputs():
573     filename = filename[prefixlen:]
574     icon = icons.get(filename)
575     dirname = os.path.dirname(filename)
576     if os.name != "nt":
577     # change the separators to \ on non-windos systems
578     filename = string.join(string.split(filename, os.sep), "\\")
579     dirname = string.join(string.split(dirname, os.sep), "\\")
580     line = 'Source: "%s"' % filename
581     if icon is not None:
582     # install it as defined in the icon object
583     backslash = string.rfind(icon.install_name, "\\")
584     if backslash >= 0:
585     dirname = icon.install_name[:backslash]
586     basename = icon.install_name[backslash + 1:]
587     else:
588     dirname = ""
589     basename = icon.install_name
590     line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
591     basename)
592     else:
593     line = line + '; DestDir: "{app}\\%s"' % (dirname)
594     iss.append(line)
595    
596     iss.append("")
597     iss.append("[Icons]")
598     for icon in self.icons_entries:
599     line = 'Name: "{group}\\%s"; Filename: "%s";' \
600     % (icon.title, icon.install_name)
601     iss.append(line)
602    
603     return iss
604    
605    
606     class InnoIconItem:
607    
608     """Describe one item for he start menu for the Inno Setup installer"""
609    
610     def __init__(self, filename, title, install_name = None):
611     self.filename = filename
612     self.title = title
613     if install_name is not None:
614     self.install_name = install_name
615     else:
616     self.install_name = filename
617    
618    
619     class thuban_bdist_inno(bdist_inno):
620    
621     """Thuban specific Inno Setup stuff"""
622    
623     def run(self):
624     install_options = {
625     "prefix": ".",
626     "install_scripts": "$base",
627     "warn_dir": 0,
628     "extra_files": ["COPYING", "Lib/proj.dll"],
629     }
630     bdist_inno.run(self, install_options)
631    
632    
633     #
634     # Run the script
635     #
636    
637    
638 bh 6 long_description = """\
639     Thuban is a viewer for geographic data written in Python
640     """
641    
642 bh 15 setup(name = "Thuban",
643 bh 6 version = "0.0.3",
644     description = "Geographic data viewer",
645     long_description = long_description,
646     licence = "GPL",
647     author = "Intevation GmbH",
648     author_email = "[email protected]",
649     url = "ftp:intevation.de/",
650    
651     scripts = ["thuban.py"],
652     packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI"],
653     ext_modules = extensions,
654     py_modules = py_modules,
655     data_files = data_files,
656    
657     # defaults for the install command
658     options = {"install":
659     # prefix defaults to python's prefix normally
660     {"prefix": prefix,
661     # make sure both libs and scripts are installed in the
662     # same directory.
663     "install_lib": "$base/thuban",
664     "install_scripts": "$base/thuban",
665 bh 15 "install_data": "$base/thuban",
666 bh 6
667     # Don't print warning messages about the lib dir not
668     # being on Python's path. The libraries are Thuban
669     # specific and are installed just for Thuban. They'll
670     # be automatically on Python's path when Thuban is run
671     "warn_dir": 0,
672 bh 15 },
673     "bdist_inno":
674     {"icons_entries": [InnoIconItem(".\\thuban.py",
675     "Start Thuban",
676     "{app}\\thuban.pyw")],
677     "license_file": "COPYING",
678     }
679     },
680 bh 6 cmdclass = {"build_py": thuban_build_py,
681     "install_local": InstallLocal,
682 bh 15 "install": ThubanInstall,
683     "bdist_inno": thuban_bdist_inno
684     })
685 bh 6
686 bh 15

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26