package*.bbclass: Switch to separate tasks for each packing type (from poky)
[vuplus_openembedded] / classes / package_deb.bbclass
1 #
2 # Copyright 2006-2007 OpenedHand Ltd.
3 #
4
5 inherit package
6
7 BOOTSTRAP_EXTRA_RDEPENDS += "dpkg"
8 DISTRO_EXTRA_RDEPENDS += "dpkg"
9 IMAGE_PKGTYPE ?= "deb"
10
11 python package_deb_fn () {
12     from bb import data
13     bb.data.setVar('PKGFN', bb.data.getVar('PKG',d), d)
14 }
15
16 addtask package_deb_install
17 python do_package_deb_install () {
18     import os, sys
19     pkg = bb.data.getVar('PKG', d, 1)
20     pkgfn = bb.data.getVar('PKGFN', d, 1)
21     rootfs = bb.data.getVar('IMAGE_ROOTFS', d, 1)
22     debdir = bb.data.getVar('DEPLOY_DIR_DEB', d, 1)
23     stagingdir = bb.data.getVar('STAGING_DIR', d, 1)
24     stagingbindir = bb.data.getVar('STAGING_BINDIR_NATIVE', d, 1)
25     tmpdir = bb.data.getVar('TMPDIR', d, 1)
26
27     if None in (pkg,pkgfn,rootfs):
28         raise bb.build.FuncFailed("missing variables (one or more of PKG, PKGFN, IMAGE_ROOTFS)")
29     try:
30         if not os.exists(rootfs):
31             os.makedirs(rootfs)
32         os.chdir(rootfs)
33     except OSError:
34         raise bb.build.FuncFailed(str(sys.exc_value))
35
36     # update packages file
37     (exitstatus, output) = commands.getstatusoutput('dpkg-scanpackages %s > %s/Packages' % (debdir, debdir))
38     if (exitstatus != 0 ):
39         raise bb.build.FuncFailed(output)
40
41     f = open(os.path.join(tmpdir, "stamps", "do_packages"), "w")
42     f.close()
43
44     # NOTE: this env stuff is racy at best, we need something more capable
45     # than 'commands' for command execution, which includes manipulating the
46     # env of the fork+execve'd processs
47
48     # Set up environment
49     apt_config = os.getenv('APT_CONFIG')
50     os.putenv('APT_CONFIG', os.path.join(stagingdir, 'etc', 'apt', 'apt.conf'))
51     path = os.getenv('PATH')
52     os.putenv('PATH', '%s:%s' % (stagingbindir, os.getenv('PATH')))
53
54     # install package
55     commands.getstatusoutput('apt-get update')
56     commands.getstatusoutput('apt-get install -y %s' % pkgfn)
57
58     # revert environment
59     os.putenv('APT_CONFIG', apt_config)
60     os.putenv('PATH', path)
61 }
62
63 python do_package_deb () {
64     import sys, re, fcntl, copy
65
66     workdir = bb.data.getVar('WORKDIR', d, 1)
67     if not workdir:
68         bb.error("WORKDIR not defined, unable to package")
69         return
70
71     import os # path manipulations
72     outdir = bb.data.getVar('DEPLOY_DIR_DEB', d, 1)
73     if not outdir:
74         bb.error("DEPLOY_DIR_DEB not defined, unable to package")
75         return
76
77     dvar = bb.data.getVar('D', d, 1)
78     if not dvar:
79         bb.error("D not defined, unable to package")
80         return
81     bb.mkdirhier(dvar)
82
83     packages = bb.data.getVar('PACKAGES', d, 1)
84     if not packages:
85         bb.debug(1, "PACKAGES not defined, nothing to package")
86         return
87
88     tmpdir = bb.data.getVar('TMPDIR', d, 1)
89     # Invalidate the packages file
90     if os.access(os.path.join(tmpdir, "stamps", "do_packages"),os.R_OK):
91         os.unlink(os.path.join(tmpdir, "stamps", "do_packages"))
92
93     if packages == []:
94         bb.debug(1, "No packages; nothing to do")
95         return
96
97     def lockfile(name):
98         lf = open(name, "a+")
99         fcntl.flock(lf.fileno(), fcntl.LOCK_EX)
100         return lf
101
102     def unlockfile(lf):
103         fcntl.flock(lf.fileno(), fcntl.LOCK_UN)
104         lf.close
105
106     for pkg in packages.split():
107         localdata = bb.data.createCopy(d)
108         root = "%s/install/%s" % (workdir, pkg)
109
110         lf = lockfile(root + ".lock")
111
112         bb.data.setVar('ROOT', '', localdata)
113         bb.data.setVar('ROOT_%s' % pkg, root, localdata)
114         pkgname = bb.data.getVar('PKG_%s' % pkg, localdata, 1)
115         if not pkgname:
116             pkgname = pkg
117         bb.data.setVar('PKG', pkgname, localdata)
118
119         overrides = bb.data.getVar('OVERRIDES', localdata)
120         if not overrides:
121             raise bb.build.FuncFailed('OVERRIDES not defined')
122         overrides = bb.data.expand(overrides, localdata)
123         bb.data.setVar('OVERRIDES', overrides + ':' + pkg, localdata)
124
125         bb.data.update_data(localdata)
126         basedir = os.path.join(os.path.dirname(root))
127
128         pkgoutdir = os.path.join(outdir, bb.data.getVar('PACKAGE_ARCH', localdata, 1))
129         bb.mkdirhier(pkgoutdir)
130
131         os.chdir(root)
132         from glob import glob
133         g = glob('*')
134         try:
135             del g[g.index('DEBIAN')]
136             del g[g.index('./DEBIAN')]
137         except ValueError:
138             pass
139         if not g and bb.data.getVar('ALLOW_EMPTY', localdata) != "1":
140             from bb import note
141             note("Not creating empty archive for %s-%s-%s" % (pkg, bb.data.getVar('PV', localdata, 1), bb.data.getVar('PR', localdata, 1)))
142             unlockfile(lf)
143             continue
144         controldir = os.path.join(root, 'DEBIAN')
145         bb.mkdirhier(controldir)
146         os.chmod(controldir, 0755)
147         try:
148             ctrlfile = file(os.path.join(controldir, 'control'), 'wb')
149             # import codecs
150             # ctrlfile = codecs.open("someFile", "w", "utf-8")
151         except OSError:
152             raise bb.build.FuncFailed("unable to open control file for writing.")
153
154         fields = []
155         pe = bb.data.getVar('PE', d, 1)
156         if pe and int(pe) > 0:
157             fields.append(["Version: %s:%s-%s\n", ['PE', 'PV', 'PR']])
158         else:
159             fields.append(["Version: %s-%s\n", ['PV', 'PR']])
160         fields.append(["Description: %s\n", ['DESCRIPTION']])
161         fields.append(["Section: %s\n", ['SECTION']])
162         fields.append(["Priority: %s\n", ['PRIORITY']])
163         fields.append(["Maintainer: %s\n", ['MAINTAINER']])
164         fields.append(["Architecture: %s\n", ['TARGET_ARCH']])
165         fields.append(["OE: %s\n", ['PN']])
166         fields.append(["Homepage: %s\n", ['HOMEPAGE']])
167
168 #        Package, Version, Maintainer, Description - mandatory
169 #        Section, Priority, Essential, Architecture, Source, Depends, Pre-Depends, Recommends, Suggests, Conflicts, Replaces, Provides - Optional
170
171
172         def pullData(l, d):
173             l2 = []
174             for i in l:
175                 data = bb.data.getVar(i, d, 1)
176                 if data is None:
177                     raise KeyError(f)
178                 if i == 'TARGET_ARCH' and bb.data.getVar('PACKAGE_ARCH', d, 1) == 'all':
179                     data = 'all'
180                 l2.append(data)
181             return l2
182
183         ctrlfile.write("Package: %s\n" % pkgname)
184         # check for required fields
185         try:
186             for (c, fs) in fields:
187                 ctrlfile.write(unicode(c % tuple(pullData(fs, localdata))))
188         except KeyError:
189             (type, value, traceback) = sys.exc_info()
190             ctrlfile.close()
191             raise bb.build.FuncFailed("Missing field for deb generation: %s" % value)
192         # more fields
193
194         bb.build.exec_func("mapping_rename_hook", localdata)
195
196         rdepends = explode_deps(unicode(bb.data.getVar("RDEPENDS", localdata, 1) or ""))
197         rdepends = [dep for dep in rdepends if not '*' in dep]
198         rrecommends = explode_deps(unicode(bb.data.getVar("RRECOMMENDS", localdata, 1) or ""))
199         rrecommends = [rec for rec in rrecommends if not '*' in rec]
200         rsuggests = (unicode(bb.data.getVar("RSUGGESTS", localdata, 1) or "")).split()
201         rprovides = (unicode(bb.data.getVar("RPROVIDES", localdata, 1) or "")).split()
202         rreplaces = (unicode(bb.data.getVar("RREPLACES", localdata, 1) or "")).split()
203         rconflicts = (unicode(bb.data.getVar("RCONFLICTS", localdata, 1) or "")).split()
204         if rdepends:
205             ctrlfile.write(u"Depends: %s\n" % ", ".join(rdepends))
206         if rsuggests:
207             ctrlfile.write(u"Suggests: %s\n" % ", ".join(rsuggests))
208         if rrecommends:
209             ctrlfile.write(u"Recommends: %s\n" % ", ".join(rrecommends))
210         if rprovides:
211             ctrlfile.write(u"Provides: %s\n" % ", ".join(rprovides))
212         if rreplaces:
213             ctrlfile.write(u"Replaces: %s\n" % ", ".join(rreplaces))
214         if rconflicts:
215             ctrlfile.write(u"Conflicts: %s\n" % ", ".join(rconflicts))
216         ctrlfile.close()
217
218         for script in ["preinst", "postinst", "prerm", "postrm"]:
219             scriptvar = bb.data.getVar('pkg_%s' % script, localdata, 1)
220             if not scriptvar:
221                 continue
222             try:
223                 scriptfile = file(os.path.join(controldir, script), 'w')
224             except OSError:
225                 raise bb.build.FuncFailed("unable to open %s script file for writing." % script)
226             scriptfile.write("#!/bin/sh\n")
227             scriptfile.write(scriptvar)
228             scriptfile.close()
229             os.chmod(os.path.join(controldir, script), 0755)
230
231         conffiles_str = bb.data.getVar("CONFFILES", localdata, 1)
232         if conffiles_str:
233             try:
234                 conffiles = file(os.path.join(controldir, 'conffiles'), 'w')
235             except OSError:
236                 raise bb.build.FuncFailed("unable to open conffiles for writing.")
237             for f in conffiles_str.split():
238                 conffiles.write('%s\n' % f)
239             conffiles.close()
240
241         os.chdir(basedir)
242         ret = os.system("PATH=\"%s\" fakeroot dpkg-deb -b %s %s" % (bb.data.getVar("PATH", localdata, 1), root, pkgoutdir))
243         if ret != 0:
244             raise bb.build.FuncFailed("dpkg-deb execution failed")
245
246         for script in ["preinst", "postinst", "prerm", "postrm", "control" ]:
247             scriptfile = os.path.join(controldir, script)
248             try:
249                 os.remove(scriptfile)
250             except OSError:
251                 pass
252         try:
253             os.rmdir(controldir)
254         except OSError:
255             pass
256
257         unlockfile(lf)
258 }
259
260 python () {
261     import bb
262     if bb.data.getVar('PACKAGES', d, True) != '':
263         bb.data.setVarFlag('do_package_write_deb', 'depends', 'dpkg-native:do_populate_staging fakeroot-native:do_populate_staging', d)
264 }
265
266 python do_package_write_deb () {
267         bb.build.exec_func("read_subpackage_metadata", d)
268         bb.build.exec_func("do_package_deb", d)
269 }
270 do_package_write_deb[dirs] = "${D}"
271 addtask package_write_deb before do_package_write after do_package
272