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