fix typo
[moonshot.git] / builder
1 #!/usr/bin/python
2
3 '''A script to buildMoonshot  potentially using a schroot for install testing.
4 '''
5
6 from contextlib import contextmanager
7 import os, subprocess, exceptions
8 import re
9 import sys
10 from optparse import OptionParser
11 from shutil import copy
12
13
14
15 # These variables can be overridden by options. If packages is not
16 # set, then it is read from the source_packages file
17 packages = []  # Set of packages to build
18 prefix = "/usr/local/moonshot"
19 root_command = "fakeroot"
20
21 schroot_command = ""
22
23 class CommandError(exceptions.StandardError):
24     pass
25
26 class Schroot(object):
27     '''Represents a schroot used for building moonshot.'''
28
29     def __init__(self, name):
30         '''Initialize a new schroot option from the named
31         schroot. Unless the named schroot starts with session:, then a
32         new session schroot is created.'''
33         if not name.startswith('session:'):
34             self.name = command_output(('schroot', '-b',
35                                         '-c', name))
36             self.end_session = True
37         else:
38             self.name = name
39             self.end_session = False
40
41     def __del__(self):
42         if self.end_session:
43             try:
44                 run_cmd(('schroot', '-e', '-c', self.name))
45             except CommandError: pass
46
47 @contextmanager
48 def current_directory(dir):
49     "Change the current directory as a context manager; when the context exits, return."
50     cwd = os.getcwd()
51     os.chdir(dir)
52     yield
53     os.chdir(cwd)
54
55
56 def run_cmd(args, **kwords):
57     rcode =  subprocess.call( args, **kwords)
58     if rcode <> 0:
59         raise CommandError(args)
60
61 def command_output(args) :
62     p = subprocess.Popen(args, stdout=subprocess.PIPE)
63     output = p.communicate()
64     output = output[0]
65     if p.returncode != 0:
66         raise CommandError(args)
67     return output.strip()
68
69 def build(package):
70     with current_directory(package):
71         try: os.makedirs( "m4")
72         except OSError: pass
73         run_cmd(('autoreconf', '-i', '-f'))
74         configure_command = [
75                                       './configure'] + configure_opts
76         if len(schroot_command) > 0:
77             configure_command = schroot_command.split(' ') \
78                 + configure_command
79         print ' '.join(configure_command)
80         sys.stdout.flush()
81         run_cmd(configure_command, shell=False)
82         if dist:
83             try: os.mkdir('doc/api')
84             except: pass
85             #Currently freeradius's make dist is broken
86             if not package == "freeradius-server":
87                 run_cmd(root_command +' make dist-gzip', shell=True)
88                 run_cmd('cp *.tar.gz ' +dist_dir, shell=True)
89         run_cmd(schroot_command + ' make -j3', shell=True)
90
91 def make_install(package):
92     with current_directory(package):
93         install_command = root_command + " make install"
94         print install_command
95         sys.stdout.flush()
96         run_cmd(install_command, shell=True)
97         
98
99 def read_packages():
100     '''Read in the packages file from source_packages
101     '''
102     try: pf = file("source_packages")
103     except IOError:
104         print "Error: source_packages file not found"
105         exit(1)
106     def is_comment(line):
107         if re.match("^\\s*#", line): return False
108         if "#" in line: raise ValueError(
109             "Source package line contains a comment but not at beginning")
110         return True
111     return map(lambda(x): x.rstrip(),
112         filter(is_comment, pf.readlines()))
113
114
115 # main program
116 opt = OptionParser()
117 opt.add_option('--prefix',
118                dest="prefix", default=prefix,
119                help="Set the prefix under which packages are built and"
120                + "installed")
121 opt.add_option('-c', '--configure-opt', dest="configure_opts",
122                action="append",
123                help="Specify an option to pass to configure")
124 opt.add_option('-r', '--root-cmd', dest="root_command",
125                default=root_command,
126                help="Specify command to gain root for make install")
127 opt.add_option('-s', '--schroot',
128                dest="schroot",
129                help="Specify name of schroot to use for build;"
130                "implicitly sets root_command")
131 opt.add_option( '--dist', action='store_true',
132                 default=False, dest='dist',
133                 help = 'make dist-gzip in addition to the build'
134                 )
135 opt.add_option('--tar-file',
136                dest='tar_file',
137                help = 'Tar up resulting distributions in given tar file',
138                default = None)
139 opt.usage = "%prog [options] [packages]"
140 (options, packages) = opt.parse_args()
141 prefix = options.prefix
142 root_command = options.root_command
143 dist = options.dist
144 configure_opts = ['--prefix', prefix,
145                   "LDFLAGS=-Wl,-L"+prefix+"/lib -Wl,-rpath="+prefix+"/lib",
146                   'CPPFLAGS=-I '+prefix+'/include',
147                   '--with-system-libtool', '--with-system-libltdl',
148                   '--enable-tls', '--with-gssapi='+prefix,
149                   "--with-xmltooling="+prefix, 
150                   ]
151 if options.configure_opts is not None: 
152     configure_opts.extend(options.configure_opts)
153 tar_file = options.tar_file
154 if tar_file is not None: dist = True
155
156 our_schroot = None
157 if options.schroot is not None:
158     our_schroot = Schroot(options.schroot)
159     schroot_command_base = "schroot -r -c " + our_schroot.name
160     root_command = schroot_command_base + " -u root --"
161     schroot_command = schroot_command_base + ' --'
162
163 all_packages = read_packages()
164 if len(packages) == 0: packages = all_packages
165
166 os.umask(022)
167 if dist:
168     try:
169         os.mkdir('distributions')
170     except: pass
171     dist_dir = os.path.join(os.getcwd(), 'distributions')
172
173 try:
174     for p in all_packages:
175         if p in packages: build(p)
176         if packages[-1] == p : break
177         make_install(p)
178     if tar_file is not None:
179         with current_directory(dist_dir):
180             run_cmd(['tar', '-cf', tar_file,
181                      '.'])
182 except CommandError as c:
183     print "Error:" + str(c.args)
184     our_schroot = None
185     exit(1)
186 finally: del our_schroot