blob: 7286bf1f3f9ec40d45692251a0b7df9d8336f5f9 [file] [log] [blame]
Greg Warda4efe652000-05-25 01:20:15 +00001"""distutils.command.build_scripts
2
3Implements the Distutils 'build_scripts' command."""
4
5# created 2000/05/23, Bastian Kleineidam
6
7__revision__ = "$Id$"
8
Greg Ward80fa55e2000-05-25 02:03:56 +00009import sys, os, re
Michael W. Hudsonfb173cd2001-12-10 16:15:44 +000010from distutils import sysconfig
Greg Warda4efe652000-05-25 01:20:15 +000011from distutils.core import Command
Greg Ward80fa55e2000-05-25 02:03:56 +000012from distutils.dep_util import newer
Just van Rossum8d8e7a32001-07-29 21:39:18 +000013from distutils.util import convert_path
Greg Warda4efe652000-05-25 01:20:15 +000014
Greg Ward7cf7e7e2001-07-25 20:20:11 +000015# check if Python is called on the first line with this expression
Andrew M. Kuchling3ecc1ce2001-12-06 21:29:28 +000016first_line_re = re.compile(r'^#!.*python(\s+.*)?$')
Greg Warda4efe652000-05-25 01:20:15 +000017
18class build_scripts (Command):
19
Greg Ward80fa55e2000-05-25 02:03:56 +000020 description = "\"build\" scripts (copy and fixup #! line)"
Greg Warda4efe652000-05-25 01:20:15 +000021
22 user_options = [
23 ('build-dir=', 'd', "directory to \"build\" (copy) to"),
24 ('force', 'f', "forcibly build everything (ignore file timestamps"),
25 ]
26
Greg Ward99b032e2000-09-25 01:41:15 +000027 boolean_options = ['force']
28
Greg Warda4efe652000-05-25 01:20:15 +000029
30 def initialize_options (self):
31 self.build_dir = None
32 self.scripts = None
33 self.force = None
34 self.outfiles = None
35
36 def finalize_options (self):
Greg Wardcb1f4c42000-09-30 18:27:54 +000037 self.set_undefined_options('build',
38 ('build_scripts', 'build_dir'),
39 ('force', 'force'))
Greg Warda4efe652000-05-25 01:20:15 +000040 self.scripts = self.distribution.scripts
41
42
43 def run (self):
44 if not self.scripts:
45 return
Greg Ward80fa55e2000-05-25 02:03:56 +000046 self.copy_scripts()
47
Fred Drake53a79062001-03-02 07:28:03 +000048
Greg Ward80fa55e2000-05-25 02:03:56 +000049 def copy_scripts (self):
50 """Copy each script listed in 'self.scripts'; if it's marked as a
51 Python script in the Unix way (first line matches 'first_line_re',
52 ie. starts with "\#!" and contains "python"), then adjust the first
Greg Ward612eb9f2000-07-27 02:13:20 +000053 line to refer to the current Python interpreter as we copy.
Greg Ward80fa55e2000-05-25 02:03:56 +000054 """
Greg Warda4efe652000-05-25 01:20:15 +000055 self.mkpath(self.build_dir)
Greg Ward80fa55e2000-05-25 02:03:56 +000056 for script in self.scripts:
57 adjust = 0
Just van Rossum8d8e7a32001-07-29 21:39:18 +000058 script = convert_path(script)
Greg Wardfe55e862000-05-25 20:05:52 +000059 outfile = os.path.join(self.build_dir, os.path.basename(script))
Greg Ward80fa55e2000-05-25 02:03:56 +000060
61 if not self.force and not newer(script, outfile):
Fred Drake53a79062001-03-02 07:28:03 +000062 self.announce("not copying %s (up-to-date)" % script)
Greg Ward80fa55e2000-05-25 02:03:56 +000063 continue
64
65 # Always open the file, but ignore failures in dry-run mode --
66 # that way, we'll get accurate feedback if we can read the
67 # script.
68 try:
69 f = open(script, "r")
70 except IOError:
71 if not self.dry_run:
72 raise
73 f = None
74 else:
75 first_line = f.readline()
76 if not first_line:
77 self.warn("%s is an empty file (skipping)" % script)
Greg Warda4efe652000-05-25 01:20:15 +000078 continue
Greg Ward80fa55e2000-05-25 02:03:56 +000079
80 match = first_line_re.match(first_line)
81 if match:
82 adjust = 1
83 post_interp = match.group(1)
84
85 if adjust:
86 self.announce("copying and adjusting %s -> %s" %
87 (script, self.build_dir))
88 if not self.dry_run:
89 outf = open(outfile, "w")
Michael W. Hudsonfb173cd2001-12-10 16:15:44 +000090 if not sysconfig.python_build:
91 outf.write("#!%s%s\n" %
92 (os.path.normpath(sys.executable),
93 post_interp))
94 else:
95 outf.write("#!%s%s" %
96 (os.path.join(
97 sysconfig.get_config_var("BINDIR"),
98 "python" + sysconfig.get_config_var("EXE")),
99 post_interp))
Greg Ward80fa55e2000-05-25 02:03:56 +0000100 outf.writelines(f.readlines())
101 outf.close()
102 if f:
103 f.close()
104 else:
105 f.close()
106 self.copy_file(script, outfile)
107
108 # copy_scripts ()
109
110# class build_scripts