If the archive directory isn't set, display the error immediately
[0release.git] / compile.py
blob6d45afd2740046296c7a91bfa6a643be2e4aab0e
1 # Copyright (C) 2009, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 import tempfile, shutil, subprocess, os
5 import ConfigParser
6 from zeroinstall.injector import model
8 import support
10 COMPILE = 'http://0install.net/2006/interfaces/0compile.xml'
11 RELEASE = 'http://0install.net/2007/interfaces/0release.xml'
13 class Compiler:
14 def __init__(self, options, src_feed_name):
15 self.src_feed_name = src_feed_name
16 self.src_feed = support.load_feed(src_feed_name)
17 self.archive_dir_public_url = options.archive_dir_public_url
18 assert options.archive_dir_public_url
20 self.src_impl = support.get_singleton_impl(self.src_feed)
21 if self.src_impl.arch and self.src_impl.arch.endswith('-src'):
22 self.targets = ['host']
23 else:
24 self.targets = []
26 # We run the build in a sub-process. The idea is that the build may need to run
27 # on a different machine.
28 def build_binaries(self):
29 if not self.targets: return
31 print "Source package, so generating binaries..."
33 archive_file = support.get_archive_basename(self.src_impl)
35 for arch in self.targets:
36 if arch == 'host':
37 command = ['0launch', '--not-before', '0.8-post', RELEASE, '--build-slave']
38 else:
39 command = ['0release-build', arch]
41 binary_feed = 'binary-' + arch + '.xml'
42 if os.path.exists(binary_feed):
43 print "Feed %s already exists; not rebuilding" % binary_feed
44 else:
45 print "\nBuilding binary for %s architecture...\n" % arch
46 subprocess.check_call(command + [self.src_feed_name, archive_file, self.archive_dir_public_url, binary_feed + '.new'])
47 bin_feed = support.load_feed(binary_feed + '.new')
48 bin_impl = support.get_singleton_impl(bin_feed)
49 bin_archive_file = support.get_archive_basename(bin_impl)
50 bin_size = bin_impl.download_sources[0].size
52 assert os.path.exists(bin_archive_file), "Compiled binary '%s' not found!" % os.path.abspath(bin_archive_file)
53 assert os.path.getsize(bin_archive_file) == bin_size, "Compiled binary '%s' has wrong size!" % os.path.abspath(bin_archive_file)
55 os.rename(binary_feed + '.new', binary_feed)
57 def get_binary_feeds(self):
58 return ['binary-%s.xml' % arch for arch in self.targets]
60 # This is the actual build process, running on the build machine
61 def build_slave(src_feed, archive_file, archive_dir_public_url, target_feed):
62 feed = support.load_feed(src_feed)
64 archive_file = os.path.abspath(archive_file)
65 target_feed = os.path.abspath(target_feed)
67 impl, = feed.implementations.values()
69 tmpdir = tempfile.mkdtemp(prefix = '0release-')
70 try:
71 os.chdir(tmpdir)
72 depdir = os.path.join(tmpdir, 'dependencies')
73 os.mkdir(depdir)
75 support.unpack_tarball(archive_file)
76 os.rename(impl.download_sources[0].extract, os.path.join(depdir, impl.id))
78 config = ConfigParser.RawConfigParser()
79 config.add_section('compile')
80 config.set('compile', 'download-base-url', archive_dir_public_url)
81 config.set('compile', 'version-modifier', '')
82 config.set('compile', 'interface', src_feed)
83 config.set('compile', 'selections', '')
84 config.set('compile', 'metadir', '0install')
85 stream = open(os.path.join(tmpdir, '0compile.properties'), 'w')
86 try:
87 config.write(stream)
88 finally:
89 stream.close()
91 subprocess.check_call(['0launch', COMPILE, 'build'], cwd = tmpdir)
92 subprocess.check_call(['0launch', COMPILE, 'publish', '--target-feed', target_feed], cwd = tmpdir)
94 # TODO: run unit-tests
96 feed = support.load_feed(target_feed)
97 impl = support.get_singleton_impl(feed)
98 archive_file = support.get_archive_basename(impl)
100 shutil.move(archive_file, os.path.join(os.path.dirname(target_feed), archive_file))
101 except:
102 print "\nLeaving temporary directory %s for inspection...\n" % tmpdir
103 raise
104 else:
105 shutil.rmtree(tmpdir)