Commit | Line | Data |
---|---|---|
c638d827 CR |
1 | # |
2 | # Copyright (C) 2009 Stefan Seefeld | |
3 | # All rights reserved. | |
4 | # For license terms see the file COPYING.txt. | |
5 | # | |
6 | from distutils.command.build_scripts import build_scripts as base | |
7 | import sys, os, string | |
8 | ||
9 | class build_scripts(base): | |
10 | """ Overload the build_scripts command and create the scripts | |
11 | from scratch, depending on the target platform. | |
12 | ||
13 | You have to define the name of your package in an inherited | |
14 | class (due to the delayed instantiation of command classes | |
15 | in distutils, this cannot be passed to __init__). | |
16 | ||
17 | The scripts are created in an uniform scheme: they start the | |
18 | run() function in the module | |
19 | ||
20 | <packagename>.scripts.<mangled_scriptname> | |
21 | ||
22 | The mangling of script names replaces '-' and '/' characters | |
23 | with '-' and '.', so that they are valid module paths. | |
24 | ||
25 | If the target platform is win32, create .bat files instead of | |
26 | *nix shell scripts. Target platform is set to "win32" if main | |
27 | command is 'bdist_wininst' or if the command is 'bdist' and | |
28 | it has the list of formats (from command line or config file) | |
29 | and the first item on that list is wininst. Otherwise | |
30 | target platform is set to current (build) platform. | |
31 | """ | |
32 | package_name = 'roundup' | |
33 | ||
34 | def initialize_options(self): | |
35 | base.initialize_options(self) | |
36 | self.script_preamble = None | |
37 | self.target_platform = None | |
38 | self.python_executable = None | |
39 | ||
40 | def finalize_options(self): | |
41 | base.finalize_options(self) | |
42 | cmdopt=self.distribution.command_options | |
43 | ||
44 | # find the target platform | |
45 | if self.target_platform: | |
46 | # TODO? allow explicit setting from command line | |
47 | target = self.target_platform | |
48 | if cmdopt.has_key("bdist_wininst"): | |
49 | target = "win32" | |
50 | elif cmdopt.get("bdist", {}).has_key("formats"): | |
51 | formats = cmdopt["bdist"]["formats"][1].split(",") | |
52 | if formats[0] == "wininst": | |
53 | target = "win32" | |
54 | else: | |
55 | target = sys.platform | |
56 | if len(formats) > 1: | |
57 | self.warn( | |
58 | "Scripts are built for %s only (requested formats: %s)" | |
59 | % (target, ",".join(formats))) | |
60 | else: | |
61 | # default to current platform | |
62 | target = sys.platform | |
63 | self.target_platfom = target | |
64 | ||
65 | # for native builds, use current python executable path; | |
66 | # for cross-platform builds, use default executable name | |
67 | if self.python_executable: | |
68 | # TODO? allow command-line option | |
69 | pass | |
70 | if target == sys.platform: | |
71 | self.python_executable = os.path.normpath(sys.executable) | |
72 | else: | |
73 | self.python_executable = "python" | |
74 | ||
75 | # for windows builds, add ".bat" extension | |
76 | if target == "win32": | |
77 | # *nix-like scripts may be useful also on win32 (cygwin) | |
78 | # to build both script versions, use: | |
79 | #self.scripts = list(self.scripts) + [script + ".bat" | |
80 | # for script in self.scripts] | |
81 | self.scripts = [script + ".bat" for script in self.scripts] | |
82 | ||
83 | # tweak python path for installations outside main python library | |
84 | if cmdopt.get("install", {}).has_key("prefix"): | |
85 | prefix = os.path.expanduser(cmdopt['install']['prefix'][1]) | |
86 | version = '%d.%d'%sys.version_info[:2] | |
87 | self.script_preamble = """ | |
88 | import sys | |
89 | sys.path.insert(1, "%s/lib/python%s/site-packages") | |
90 | """%(prefix, version) | |
91 | else: | |
92 | self.script_preamble = '' | |
93 | ||
94 | def copy_scripts(self): | |
95 | """ Create each script listed in 'self.scripts' | |
96 | """ | |
97 | ||
98 | to_module = string.maketrans('-/', '_.') | |
99 | ||
100 | self.mkpath(self.build_dir) | |
101 | for script in self.scripts: | |
102 | outfile = os.path.join(self.build_dir, os.path.basename(script)) | |
103 | ||
104 | #if not self.force and not newer(script, outfile): | |
105 | # self.announce("not copying %s (up-to-date)" % script) | |
106 | # continue | |
107 | ||
108 | if self.dry_run: | |
109 | self.announce("would create %s" % outfile) | |
110 | continue | |
111 | ||
112 | module = os.path.splitext(os.path.basename(script))[0] | |
113 | module = string.translate(module, to_module) | |
114 | script_vars = { | |
115 | 'python': self.python_executable, | |
116 | 'package': self.package_name, | |
117 | 'module': module, | |
118 | 'prefix': self.script_preamble, | |
119 | } | |
120 | ||
121 | self.announce("creating %s" % outfile) | |
122 | file = open(outfile, 'w') | |
123 | ||
124 | try: | |
125 | # could just check self.target_platform, | |
126 | # but looking at the script extension | |
127 | # makes it possible to build both *nix-like | |
128 | # and windows-like scripts on win32. | |
129 | # may be useful for cygwin. | |
130 | if os.path.splitext(outfile)[1] == ".bat": | |
131 | file.write('@echo off\n' | |
132 | 'if NOT "%%_4ver%%" == "" "%(python)s" -c "from %(package)s.scripts.%(module)s import run; run()" %%$\n' | |
133 | 'if "%%_4ver%%" == "" "%(python)s" -c "from %(package)s.scripts.%(module)s import run; run()" %%*\n' | |
134 | % script_vars) | |
135 | else: | |
136 | file.write('#! %(python)s\n%(prefix)s' | |
137 | 'from %(package)s.scripts.%(module)s import run\n' | |
138 | 'run()\n' | |
139 | % script_vars) | |
140 | finally: | |
141 | file.close() | |
142 | os.chmod(outfile, 0755) |