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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show 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 # 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 from types import TupleType
20 from distutils.core import setup, Extension, Command
21 from distutils.command.install import install
22 from distutils.command.build_py import build_py
23 from distutils.file_util import write_file
24 from distutils.util import convert_path
25
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 # 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 #
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 dir = "Resources/Bitmaps"
239 bitmaps = []
240 for file in os.listdir(os.path.join("Resources", "Bitmaps")):
241 if string.lower(file[-4:]) == ".xpm":
242 bitmaps.append(dir + '/' + file)
243 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 self.announce("symlinking %s -> %s" % (src, dest))
295 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 A new build_py that can deal with both packages and modules in one
314 distribution.
315 """
316
317 def run(self):
318 """The same the as the original in build_py revision 1.33 except
319 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 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
365 return modules
366
367
368
369 class ThubanInstall(install):
370
371 """
372 Thuban specific install command.
373
374 Extend the standard install command to symlink the installed script
375 to $prefix/bin/
376 """
377
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 def run(self):
406 install.run(self)
407 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 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 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
432 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 long_description = """\
639 Thuban is a viewer for geographic data written in Python
640 """
641
642 setup(name = "Thuban",
643 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 "install_data": "$base/thuban",
666
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 },
673 "bdist_inno":
674 {"icons_entries": [InnoIconItem(".\\thuban.py",
675 "Start Thuban",
676 "{app}\\thuban.pyw")],
677 "license_file": "COPYING",
678 }
679 },
680 cmdclass = {"build_py": thuban_build_py,
681 "install_local": InstallLocal,
682 "install": ThubanInstall,
683 "bdist_inno": thuban_bdist_inno
684 })
685
686

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26