merge of '45ed15a71cd24c4894d885800ddeb8de3cdcc32c'
[vuplus_openembedded] / classes / package.bbclass
1 #
2 # General packaging help functions
3 #
4
5 PKGDEST = "${WORKDIR}/install"
6
7 def legitimize_package_name(s):
8         """
9         Make sure package names are legitimate strings
10         """
11         import re
12
13         def fixutf(m):
14                 cp = m.group(1)
15                 if cp:
16                         return ('\u%s' % cp).decode('unicode_escape').encode('utf-8')
17
18         # Handle unicode codepoints encoded as <U0123>, as in glibc locale files.
19         s = re.sub('<U([0-9A-Fa-f]{1,4})>', fixutf, s)
20
21         # Remaining package name validity fixes
22         return s.lower().replace('_', '-').replace('@', '+').replace(',', '+').replace('/', '-')
23
24 def do_split_packages(d, root, file_regex, output_pattern, description, postinst=None, recursive=False, hook=None, extra_depends=None, aux_files_pattern=None, postrm=None, allow_dirs=False, prepend=False, match_path=False, aux_files_pattern_verbatim=None):
25         """
26         Used in .bb files to split up dynamically generated subpackages of a 
27         given package, usually plugins or modules.
28         """
29         import os, os.path, bb
30
31         dvar = bb.data.getVar('D', d, 1)
32         if not dvar:
33                 bb.error("D not defined")
34                 return
35
36         packages = bb.data.getVar('PACKAGES', d, 1).split()
37
38         if postinst:
39                 postinst = '#!/bin/sh\n' + postinst + '\n'
40         if postrm:
41                 postrm = '#!/bin/sh\n' + postrm + '\n'
42         if not recursive:
43                 objs = os.listdir(dvar + root)
44         else:
45                 objs = []
46                 for walkroot, dirs, files in os.walk(dvar + root):
47                         for file in files:
48                                 relpath = os.path.join(walkroot, file).replace(dvar + root + '/', '', 1)
49                                 if relpath:
50                                         objs.append(relpath)
51
52         if extra_depends == None:
53                 # This is *really* broken
54                 mainpkg = packages[0]
55                 # At least try and patch it up I guess...
56                 if mainpkg.find('-dbg'):
57                         mainpkg = mainpkg.replace('-dbg', '')
58                 if mainpkg.find('-dev'):
59                         mainpkg = mainpkg.replace('-dev', '')
60                 extra_depends = mainpkg
61
62         for o in objs:
63                 import re, stat
64                 if match_path:
65                         m = re.match(file_regex, o)
66                 else:
67                         m = re.match(file_regex, os.path.basename(o))
68                 
69                 if not m:
70                         continue
71                 f = os.path.join(dvar + root, o)
72                 mode = os.lstat(f).st_mode
73                 if not (stat.S_ISREG(mode) or (allow_dirs and stat.S_ISDIR(mode))):
74                         continue
75                 on = legitimize_package_name(m.group(1))
76                 pkg = output_pattern % on
77                 if not pkg in packages:
78                         if prepend:
79                                 packages = [pkg] + packages
80                         else:
81                                 packages.append(pkg)
82                         the_files = [os.path.join(root, o)]
83                         if aux_files_pattern:
84                                 if type(aux_files_pattern) is list:
85                                         for fp in aux_files_pattern:
86                                                 the_files.append(fp % on)       
87                                 else:
88                                         the_files.append(aux_files_pattern % on)
89                         if aux_files_pattern_verbatim:
90                                 if type(aux_files_pattern_verbatim) is list:
91                                         for fp in aux_files_pattern_verbatim:
92                                                 the_files.append(fp % m.group(1))       
93                                 else:
94                                         the_files.append(aux_files_pattern_verbatim % m.group(1))
95                         bb.data.setVar('FILES_' + pkg, " ".join(the_files), d)
96                         if extra_depends != '':
97                                 the_depends = bb.data.getVar('RDEPENDS_' + pkg, d, 1)
98                                 if the_depends:
99                                         the_depends = '%s %s' % (the_depends, extra_depends)
100                                 else:
101                                         the_depends = extra_depends
102                                 bb.data.setVar('RDEPENDS_' + pkg, the_depends, d)
103                         bb.data.setVar('DESCRIPTION_' + pkg, description % on, d)
104                         if postinst:
105                                 bb.data.setVar('pkg_postinst_' + pkg, postinst, d)
106                         if postrm:
107                                 bb.data.setVar('pkg_postrm_' + pkg, postrm, d)
108                 else:
109                         oldfiles = bb.data.getVar('FILES_' + pkg, d, 1)
110                         if not oldfiles:
111                                 bb.fatal("Package '%s' exists but has no files" % pkg)
112                         bb.data.setVar('FILES_' + pkg, oldfiles + " " + os.path.join(root, o), d)
113                 if callable(hook):
114                         hook(f, pkg, file_regex, output_pattern, m.group(1))
115
116         bb.data.setVar('PACKAGES', ' '.join(packages), d)
117
118 PACKAGE_DEPENDS += "file-native"
119
120 python () {
121     import bb
122     if bb.data.getVar('PACKAGES', d, True) != '':
123         deps = bb.data.getVarFlag('do_package', 'depends', d) or ""
124         for dep in (bb.data.getVar('PACKAGE_DEPENDS', d, True) or "").split():
125             deps += " %s:do_populate_staging" % dep
126         bb.data.setVarFlag('do_package', 'depends', deps, d)
127
128         deps = (bb.data.getVarFlag('do_package', 'deptask', d) or "").split()
129         # shlibs requires any DEPENDS to have already packaged for the *.list files
130         deps.append("do_package")
131         bb.data.setVarFlag('do_package', 'deptask', " ".join(deps), d)
132 }
133
134 def runstrip(file, d):
135     # Function to strip a single file, called from populate_packages below
136     # A working 'file' (one which works on the target architecture)
137     # is necessary for this stuff to work, hence the addition to do_package[depends]
138
139     import bb, os, commands, stat
140
141     pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, 1)
142
143     ret, result = commands.getstatusoutput("%sfile '%s'" % (pathprefix, file))
144
145     if ret:
146         bb.error("runstrip: 'file %s' failed (forced strip)" % file)
147
148     if "not stripped" not in result:
149         bb.debug(1, "runstrip: skip %s" % file)
150         return 0
151
152     # If the file is in a .debug directory it was already stripped,
153     # don't do it again...
154     if os.path.dirname(file).endswith(".debug"):
155         bb.note("Already run strip")
156         return 0
157
158     strip = bb.data.getVar("STRIP", d, 1)
159     objcopy = bb.data.getVar("OBJCOPY", d, 1)
160
161     newmode = None
162     if not os.access(file, os.W_OK):
163         origmode = os.stat(file)[stat.ST_MODE]
164         newmode = origmode | stat.S_IWRITE
165         os.chmod(file, newmode)
166
167     extraflags = ""
168     if ".so" in file and "shared" in result:
169         extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded"
170     elif "shared" in result or "executable" in result:
171         extraflags = "--remove-section=.comment --remove-section=.note"
172
173     bb.mkdirhier(os.path.join(os.path.dirname(file), ".debug"))
174     debugfile=os.path.join(os.path.dirname(file), ".debug", os.path.basename(file))
175
176     stripcmd = "'%s' %s '%s'" % (strip, extraflags, file)
177     bb.debug(1, "runstrip: %s" % stripcmd)
178
179     os.system("%s'%s' --only-keep-debug '%s' '%s'" % (pathprefix, objcopy, file, debugfile))
180     ret = os.system("%s%s" % (pathprefix, stripcmd))
181     os.system("%s'%s' --add-gnu-debuglink='%s' '%s'" % (pathprefix, objcopy, debugfile, file))
182
183     if newmode:
184         os.chmod(file, origmode)
185
186     if ret:
187         bb.error("runstrip: '%s' strip command failed" % stripcmd)
188
189     return 1
190
191 #
192 # Package data handling routines
193 #
194
195 def get_package_mapping (pkg, d):
196         import bb, os
197
198         data = read_subpkgdata(pkg, d)
199         key = "PKG_%s" % pkg
200
201         if key in data:
202                 return data[key]
203
204         return pkg
205
206 def runtime_mapping_rename (varname, d):
207         import bb, os
208
209         #bb.note("%s before: %s" % (varname, bb.data.getVar(varname, d, 1)))    
210
211         new_depends = []
212         for depend in explode_deps(bb.data.getVar(varname, d, 1) or ""):
213                 # Have to be careful with any version component of the depend
214                 split_depend = depend.split(' (')
215                 new_depend = get_package_mapping(split_depend[0].strip(), d)
216                 if len(split_depend) > 1:
217                         new_depends.append("%s (%s" % (new_depend, split_depend[1]))
218                 else:
219                         new_depends.append(new_depend)
220
221         bb.data.setVar(varname, " ".join(new_depends) or None, d)
222
223         #bb.note("%s after: %s" % (varname, bb.data.getVar(varname, d, 1)))
224
225 #
226 # Package functions suitable for inclusion in PACKAGEFUNCS
227 #
228
229 python package_do_split_locales() {
230         import os
231
232         if (bb.data.getVar('PACKAGE_NO_LOCALE', d, 1) == '1'):
233                 bb.debug(1, "package requested not splitting locales")
234                 return
235
236         packages = (bb.data.getVar('PACKAGES', d, 1) or "").split()
237
238         datadir = bb.data.getVar('datadir', d, 1)
239         if not datadir:
240                 bb.note("datadir not defined")
241                 return
242
243         dvar = bb.data.getVar('D', d, 1)
244         if not dvar:
245                 bb.error("D not defined")
246                 return
247
248         pn = bb.data.getVar('PN', d, 1)
249         if not pn:
250                 bb.error("PN not defined")
251                 return
252
253         if pn + '-locale' in packages:
254                 packages.remove(pn + '-locale')
255
256         localedir = os.path.join(dvar + datadir, 'locale')
257
258         if not os.path.isdir(localedir):
259                 bb.debug(1, "No locale files in this package")
260                 return
261
262         locales = os.listdir(localedir)
263
264         # This is *really* broken
265         mainpkg = packages[0]
266         # At least try and patch it up I guess...
267         if mainpkg.find('-dbg'):
268                 mainpkg = mainpkg.replace('-dbg', '')
269         if mainpkg.find('-dev'):
270                 mainpkg = mainpkg.replace('-dev', '')
271
272         for l in locales:
273                 ln = legitimize_package_name(l)
274                 pkg = pn + '-locale-' + ln
275                 packages.append(pkg)
276                 bb.data.setVar('FILES_' + pkg, os.path.join(datadir, 'locale', l), d)
277                 bb.data.setVar('RDEPENDS_' + pkg, '%s virtual-locale-%s' % (mainpkg, ln), d)
278                 bb.data.setVar('RPROVIDES_' + pkg, '%s-locale %s-translation' % (pn, ln), d)
279                 bb.data.setVar('DESCRIPTION_' + pkg, '%s translation for %s' % (l, pn), d)
280
281         bb.data.setVar('PACKAGES', ' '.join(packages), d)
282
283         # Disabled by RP 18/06/07
284         # Wildcards aren't supported in debian
285         # They break with ipkg since glibc-locale* will mean that 
286         # glibc-localedata-translit* won't install as a dependency
287         # for some other package which breaks meta-toolchain
288         # Probably breaks since virtual-locale- isn't provided anywhere
289         #rdep = (bb.data.getVar('RDEPENDS_%s' % mainpkg, d, 1) or bb.data.getVar('RDEPENDS', d, 1) or "").split()
290         #rdep.append('%s-locale*' % pn)
291         #bb.data.setVar('RDEPENDS_%s' % mainpkg, ' '.join(rdep), d)
292 }
293
294 python populate_packages () {
295         import glob, stat, errno, re
296
297         workdir = bb.data.getVar('WORKDIR', d, 1)
298         if not workdir:
299                 bb.error("WORKDIR not defined, unable to package")
300                 return
301
302         import os # path manipulations
303         outdir = bb.data.getVar('DEPLOY_DIR', d, 1)
304         if not outdir:
305                 bb.error("DEPLOY_DIR not defined, unable to package")
306                 return
307         bb.mkdirhier(outdir)
308
309         dvar = bb.data.getVar('D', d, 1)
310         if not dvar:
311                 bb.error("D not defined, unable to package")
312                 return
313         bb.mkdirhier(dvar)
314
315         packages = bb.data.getVar('PACKAGES', d, 1)
316
317         pn = bb.data.getVar('PN', d, 1)
318         if not pn:
319                 bb.error("PN not defined")
320                 return
321
322         os.chdir(dvar)
323
324         def isexec(path):
325                 try:
326                         s = os.stat(path)
327                 except (os.error, AttributeError):
328                         return 0
329                 return (s[stat.ST_MODE] & stat.S_IEXEC)
330
331         # Sanity check PACKAGES for duplicates - should be moved to 
332         # sanity.bbclass once we have the infrastucture
333         package_list = []
334         for pkg in packages.split():
335                 if pkg in package_list:
336                         bb.error("-------------------")
337                         bb.error("%s is listed in PACKAGES multiple times, this leads to packaging errors." % pkg)
338                         bb.error("Please fix the metadata/report this as bug to OE bugtracker.")
339                         bb.error("-------------------")
340                 else:
341                         package_list.append(pkg)
342
343         if (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, 1) != '1'):
344                 for root, dirs, files in os.walk(dvar):
345                         for f in files:
346                                 file = os.path.join(root, f)
347                                 if not os.path.islink(file) and not os.path.isdir(file) and isexec(file):
348                                         runstrip(file, d)
349
350         pkgdest = bb.data.getVar('PKGDEST', d, 1)
351         os.system('rm -rf %s' % pkgdest)
352
353         seen = []
354
355         for pkg in package_list:
356                 localdata = bb.data.createCopy(d)
357                 root = os.path.join(pkgdest, pkg)
358                 bb.mkdirhier(root)
359
360                 bb.data.setVar('PKG', pkg, localdata)
361                 overrides = bb.data.getVar('OVERRIDES', localdata, 1)
362                 if not overrides:
363                         raise bb.build.FuncFailed('OVERRIDES not defined')
364                 bb.data.setVar('OVERRIDES', overrides + ':' + pkg, localdata)
365                 bb.data.update_data(localdata)
366
367                 filesvar = bb.data.getVar('FILES', localdata, 1) or ""
368                 files = filesvar.split()
369                 for file in files:
370                         if os.path.isabs(file):
371                                 file = '.' + file
372                         if not os.path.islink(file):
373                                 if os.path.isdir(file):
374                                         newfiles =  [ os.path.join(file,x) for x in os.listdir(file) ]
375                                         if newfiles:
376                                                 files += newfiles
377                                                 continue
378                         globbed = glob.glob(file)
379                         if globbed:
380                                 if [ file ] != globbed:
381                                         files += globbed
382                                         continue
383                         if (not os.path.islink(file)) and (not os.path.exists(file)):
384                                 continue
385                         if file in seen:
386                                 continue
387                         seen.append(file)
388                         if os.path.isdir(file) and not os.path.islink(file):
389                                 bb.mkdirhier(os.path.join(root,file))
390                                 os.chmod(os.path.join(root,file), os.stat(file).st_mode)
391                                 continue
392                         fpath = os.path.join(root,file)
393                         dpath = os.path.dirname(fpath)
394                         bb.mkdirhier(dpath)
395                         ret = bb.copyfile(file, fpath)
396                         if ret is False or ret == 0:
397                                 raise bb.build.FuncFailed("File population failed")
398                 del localdata
399         os.chdir(workdir)
400
401         unshipped = []
402         for root, dirs, files in os.walk(dvar):
403                 for f in files:
404                         path = os.path.join(root[len(dvar):], f)
405                         if ('.' + path) not in seen:
406                                 unshipped.append(path)
407
408         if unshipped != []:
409                 bb.note("the following files were installed but not shipped in any package:")
410                 for f in unshipped:
411                         bb.note("  " + f)
412
413         bb.build.exec_func("package_name_hook", d)
414
415         for pkg in package_list:
416                 pkgname = bb.data.getVar('PKG_%s' % pkg, d, 1)
417                 if pkgname is None:
418                         bb.data.setVar('PKG_%s' % pkg, pkg, d)
419
420         dangling_links = {}
421         pkg_files = {}
422         for pkg in package_list:
423                 dangling_links[pkg] = []
424                 pkg_files[pkg] = []
425                 inst_root = os.path.join(pkgdest, pkg)
426                 for root, dirs, files in os.walk(inst_root):
427                         for f in files:
428                                 path = os.path.join(root, f)
429                                 rpath = path[len(inst_root):]
430                                 pkg_files[pkg].append(rpath)
431                                 try:
432                                         s = os.stat(path)
433                                 except OSError, (err, strerror):
434                                         if err != errno.ENOENT:
435                                                 raise
436                                         target = os.readlink(path)
437                                         if target[0] != '/':
438                                                 target = os.path.join(root[len(inst_root):], target)
439                                         dangling_links[pkg].append(os.path.normpath(target))
440
441         for pkg in package_list:
442                 rdepends = explode_deps(bb.data.getVar('RDEPENDS_' + pkg, d, 1) or bb.data.getVar('RDEPENDS', d, 1) or "")
443                 for l in dangling_links[pkg]:
444                         found = False
445                         bb.debug(1, "%s contains dangling link %s" % (pkg, l))
446                         for p in package_list:
447                                 for f in pkg_files[p]:
448                                         if f == l:
449                                                 found = True
450                                                 bb.debug(1, "target found in %s" % p)
451                                                 if p == pkg:
452                                                         break
453                                                 if not p in rdepends:
454                                                         rdepends.append(p)
455                                                 break
456                         if found == False:
457                                 bb.note("%s contains dangling symlink to %s" % (pkg, l))
458                 bb.data.setVar('RDEPENDS_' + pkg, " " + " ".join(rdepends), d)
459 }
460 populate_packages[dirs] = "${D}"
461
462 python emit_pkgdata() {
463         from glob import glob
464
465         def write_if_exists(f, pkg, var):
466                 def encode(str):
467                         import codecs
468                         c = codecs.getencoder("string_escape")
469                         return c(str)[0]
470
471                 val = bb.data.getVar('%s_%s' % (var, pkg), d, 1)
472                 if val:
473                         f.write('%s_%s: %s\n' % (var, pkg, encode(val)))
474
475         packages = bb.data.getVar('PACKAGES', d, 1)
476
477         data_file = bb.data.expand("${PKGDATA_DIR}/${PN}", d)
478         f = open(data_file, 'w')
479         f.write("PACKAGES: %s\n" % packages)
480         f.close()
481
482         workdir = bb.data.getVar('WORKDIR', d, 1)
483
484         for pkg in packages.split():
485                 subdata_file = bb.data.expand("${PKGDATA_DIR}/runtime/%s" % pkg, d)
486                 sf = open(subdata_file, 'w')
487                 write_if_exists(sf, pkg, 'DESCRIPTION')
488                 write_if_exists(sf, pkg, 'RDEPENDS')
489                 write_if_exists(sf, pkg, 'RPROVIDES')
490                 write_if_exists(sf, pkg, 'RRECOMMENDS')
491                 write_if_exists(sf, pkg, 'RSUGGESTS')
492                 write_if_exists(sf, pkg, 'RPROVIDES')
493                 write_if_exists(sf, pkg, 'RREPLACES')
494                 write_if_exists(sf, pkg, 'RCONFLICTS')
495                 write_if_exists(sf, pkg, 'PKG')
496                 write_if_exists(sf, pkg, 'ALLOW_EMPTY')
497                 write_if_exists(sf, pkg, 'FILES')
498                 write_if_exists(sf, pkg, 'pkg_postinst')
499                 write_if_exists(sf, pkg, 'pkg_postrm')
500                 write_if_exists(sf, pkg, 'pkg_preinst')
501                 write_if_exists(sf, pkg, 'pkg_prerm')
502                 sf.close()
503
504                 allow_empty = bb.data.getVar('ALLOW_EMPTY_%s' % pkg, d, 1)
505                 if not allow_empty:
506                         allow_empty = bb.data.getVar('ALLOW_EMPTY', d, 1)
507                 root = "%s/install/%s" % (workdir, pkg)
508                 os.chdir(root)
509                 g = glob('*')
510                 if g or allow_empty == "1":
511                         packagedfile = bb.data.expand('${PKGDATA_DIR}/runtime/%s.packaged' % pkg, d)
512                         file(packagedfile, 'w').close()
513 }
514 emit_pkgdata[dirs] = "${PKGDATA_DIR}/runtime"
515
516 ldconfig_postinst_fragment() {
517 if [ x"$D" = "x" ]; then
518         [ -x /sbin/ldconfig ] && /sbin/ldconfig
519 fi
520 }
521
522 SHLIBSDIR = "${STAGING_DIR}/${HOST_SYS}/shlibs"
523
524 python package_do_shlibs() {
525         import os, re, os.path
526
527         exclude_shlibs = bb.data.getVar('EXCLUDE_FROM_SHLIBS', d, 0)
528         if exclude_shlibs:
529                 bb.note("not generating shlibs")
530                 return
531                 
532         lib_re = re.compile("^lib.*\.so")
533         libdir_re = re.compile(".*/lib$")
534
535         packages = bb.data.getVar('PACKAGES', d, 1)
536
537         workdir = bb.data.getVar('WORKDIR', d, 1)
538         if not workdir:
539                 bb.error("WORKDIR not defined")
540                 return
541
542         ver = bb.data.getVar('PV', d, 1)
543         if not ver:
544                 bb.error("PV not defined")
545                 return
546
547         pkgdest = bb.data.getVar('PKGDEST', d, 1)
548
549         shlibs_dir = bb.data.getVar('SHLIBSDIR', d, 1)
550         bb.mkdirhier(shlibs_dir)
551
552         needed = {}
553         private_libs = bb.data.getVar('PRIVATE_LIBS', d, 1)
554         for pkg in packages.split():
555                 needs_ldconfig = False
556                 bb.debug(2, "calculating shlib provides for %s" % pkg)
557
558                 needed[pkg] = []
559                 sonames = list()
560                 top = os.path.join(pkgdest, pkg)
561                 for root, dirs, files in os.walk(top):
562                         for file in files:
563                                 soname = None
564                                 path = os.path.join(root, file)
565                                 if os.access(path, os.X_OK) or lib_re.match(file):
566                                         cmd = bb.data.getVar('OBJDUMP', d, 1) + " -p " + path + " 2>/dev/null"
567                                         cmd = "PATH=\"%s\" %s" % (bb.data.getVar('PATH', d, 1), cmd)
568                                         fd = os.popen(cmd)
569                                         lines = fd.readlines()
570                                         fd.close()
571                                         for l in lines:
572                                                 m = re.match("\s+NEEDED\s+([^\s]*)", l)
573                                                 if m:
574                                                         needed[pkg].append(m.group(1))
575                                                 m = re.match("\s+SONAME\s+([^\s]*)", l)
576                                                 if m and not m.group(1) in sonames:
577                                                         # if library is private (only used by package) then do not build shlib for it
578                                                         if not private_libs or -1 == private_libs.find(m.group(1)):
579                                                                 sonames.append(m.group(1))
580                                                 if m and libdir_re.match(root):
581                                                         needs_ldconfig = True
582                 shlibs_file = os.path.join(shlibs_dir, pkg + ".list")
583                 if os.path.exists(shlibs_file):
584                         os.remove(shlibs_file)
585                 shver_file = os.path.join(shlibs_dir, pkg + ".ver")
586                 if os.path.exists(shver_file):
587                         os.remove(shver_file)
588                 if len(sonames):
589                         fd = open(shlibs_file, 'w')
590                         for s in sonames:
591                                 fd.write(s + '\n')
592                         fd.close()
593                         fd = open(shver_file, 'w')
594                         fd.write(ver + '\n')
595                         fd.close()
596                 if needs_ldconfig:
597                         bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
598                         postinst = bb.data.getVar('pkg_postinst_%s' % pkg, d, 1) or bb.data.getVar('pkg_postinst', d, 1)
599                         if not postinst:
600                                 postinst = '#!/bin/sh\n'
601                         postinst += bb.data.getVar('ldconfig_postinst_fragment', d, 1)
602                         bb.data.setVar('pkg_postinst_%s' % pkg, postinst, d)
603
604         shlib_provider = {}
605         list_re = re.compile('^(.*)\.list$')
606         for dir in [shlibs_dir]: 
607                 if not os.path.exists(dir):
608                         continue
609                 for file in os.listdir(dir):
610                         m = list_re.match(file)
611                         if m:
612                                 dep_pkg = m.group(1)
613                                 fd = open(os.path.join(dir, file))
614                                 lines = fd.readlines()
615                                 fd.close()
616                                 ver_file = os.path.join(dir, dep_pkg + '.ver')
617                                 lib_ver = None
618                                 if os.path.exists(ver_file):
619                                         fd = open(ver_file)
620                                         lib_ver = fd.readline().rstrip()
621                                         fd.close()
622                                 for l in lines:
623                                         shlib_provider[l.rstrip()] = (dep_pkg, lib_ver)
624
625         assumed_libs = bb.data.getVar('ASSUME_SHLIBS', d, 1)
626         if assumed_libs:
627             for e in assumed_libs.split():
628                 l, dep_pkg = e.split(":")
629                 lib_ver = None
630                 dep_pkg = dep_pkg.rsplit("_", 1)
631                 if len(dep_pkg) == 2:
632                     lib_ver = dep_pkg[1]
633                 dep_pkg = dep_pkg[0]
634                 shlib_provider[l] = (dep_pkg, lib_ver)
635
636         for pkg in packages.split():
637                 bb.debug(2, "calculating shlib requirements for %s" % pkg)
638
639                 deps = list()
640                 for n in needed[pkg]:
641                         if n in shlib_provider.keys():
642                                 (dep_pkg, ver_needed) = shlib_provider[n]
643
644                                 if dep_pkg == pkg:
645                                         continue
646
647                                 if ver_needed:
648                                         dep = "%s (>= %s)" % (dep_pkg, ver_needed)
649                                 else:
650                                         dep = dep_pkg
651                                 if not dep in deps:
652                                         deps.append(dep)
653                         else:
654                                 bb.note("Couldn't find shared library provider for %s" % n)
655
656                 deps_file = os.path.join(pkgdest, pkg + ".shlibdeps")
657                 if os.path.exists(deps_file):
658                         os.remove(deps_file)
659                 if len(deps):
660                         fd = open(deps_file, 'w')
661                         for dep in deps:
662                                 fd.write(dep + '\n')
663                         fd.close()
664 }
665
666 python package_do_pkgconfig () {
667         import re, os
668
669         packages = bb.data.getVar('PACKAGES', d, 1)
670
671         workdir = bb.data.getVar('WORKDIR', d, 1)
672         if not workdir:
673                 bb.error("WORKDIR not defined")
674                 return
675
676         pkgdest = bb.data.getVar('PKGDEST', d, 1)
677
678         shlibs_dir = bb.data.getVar('SHLIBSDIR', d, 1)
679         bb.mkdirhier(shlibs_dir)
680
681         pc_re = re.compile('(.*)\.pc$')
682         var_re = re.compile('(.*)=(.*)')
683         field_re = re.compile('(.*): (.*)')
684
685         pkgconfig_provided = {}
686         pkgconfig_needed = {}
687         for pkg in packages.split():
688                 pkgconfig_provided[pkg] = []
689                 pkgconfig_needed[pkg] = []
690                 top = os.path.join(pkgdest, pkg)
691                 for root, dirs, files in os.walk(top):
692                         for file in files:
693                                 m = pc_re.match(file)
694                                 if m:
695                                         pd = bb.data.init()
696                                         name = m.group(1)
697                                         pkgconfig_provided[pkg].append(name)
698                                         path = os.path.join(root, file)
699                                         if not os.access(path, os.R_OK):
700                                                 continue
701                                         f = open(path, 'r')
702                                         lines = f.readlines()
703                                         f.close()
704                                         for l in lines:
705                                                 m = var_re.match(l)
706                                                 if m:
707                                                         name = m.group(1)
708                                                         val = m.group(2)
709                                                         bb.data.setVar(name, bb.data.expand(val, pd), pd)
710                                                         continue
711                                                 m = field_re.match(l)
712                                                 if m:
713                                                         hdr = m.group(1)
714                                                         exp = bb.data.expand(m.group(2), pd)
715                                                         if hdr == 'Requires':
716                                                                 pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
717
718         for pkg in packages.split():
719                 pkgs_file = os.path.join(shlibs_dir, pkg + ".pclist")
720                 if os.path.exists(pkgs_file):
721                         os.remove(pkgs_file)
722                 if pkgconfig_provided[pkg] != []:
723                         f = open(pkgs_file, 'w')
724                         for p in pkgconfig_provided[pkg]:
725                                 f.write('%s\n' % p)
726                         f.close()
727
728         for dir in [shlibs_dir]:
729                 if not os.path.exists(dir):
730                         continue
731                 for file in os.listdir(dir):
732                         m = re.match('^(.*)\.pclist$', file)
733                         if m:
734                                 pkg = m.group(1)
735                                 fd = open(os.path.join(dir, file))
736                                 lines = fd.readlines()
737                                 fd.close()
738                                 pkgconfig_provided[pkg] = []
739                                 for l in lines:
740                                         pkgconfig_provided[pkg].append(l.rstrip())
741
742         for pkg in packages.split():
743                 deps = []
744                 for n in pkgconfig_needed[pkg]:
745                         found = False
746                         for k in pkgconfig_provided.keys():
747                                 if n in pkgconfig_provided[k]:
748                                         if k != pkg and not (k in deps):
749                                                 deps.append(k)
750                                         found = True
751                         if found == False:
752                                 bb.note("couldn't find pkgconfig module '%s' in any package" % n)
753                 deps_file = os.path.join(pkgdest, pkg + ".pcdeps")
754                 if os.path.exists(deps_file):
755                         os.remove(deps_file)
756                 if len(deps):
757                         fd = open(deps_file, 'w')
758                         for dep in deps:
759                                 fd.write(dep + '\n')
760                         fd.close()
761 }
762
763 python read_shlibdeps () {
764         packages = bb.data.getVar('PACKAGES', d, 1).split()
765         for pkg in packages:
766                 rdepends = explode_deps(bb.data.getVar('RDEPENDS_' + pkg, d, 0) or bb.data.getVar('RDEPENDS', d, 0) or "")
767                 for extension in ".shlibdeps", ".pcdeps", ".clilibdeps":
768                         depsfile = bb.data.expand("${PKGDEST}/" + pkg + extension, d)
769                         if os.access(depsfile, os.R_OK):
770                                 fd = file(depsfile)
771                                 lines = fd.readlines()
772                                 fd.close()
773                                 for l in lines:
774                                         rdepends.append(l.rstrip())
775                 bb.data.setVar('RDEPENDS_' + pkg, " " + " ".join(rdepends), d)
776 }
777
778 python package_depchains() {
779         """
780         For a given set of prefix and postfix modifiers, make those packages
781         RRECOMMENDS on the corresponding packages for its RDEPENDS.
782
783         Example:  If package A depends upon package B, and A's .bb emits an
784         A-dev package, this would make A-dev Recommends: B-dev.
785
786         If only one of a given suffix is specified, it will take the RRECOMMENDS
787         based on the RDEPENDS of *all* other packages. If more than one of a given 
788         suffix is specified, its will only use the RDEPENDS of the single parent 
789         package.
790         """
791
792         packages  = bb.data.getVar('PACKAGES', d, 1)
793         postfixes = (bb.data.getVar('DEPCHAIN_POST', d, 1) or '').split()
794         prefixes  = (bb.data.getVar('DEPCHAIN_PRE', d, 1) or '').split()
795
796         def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d):
797
798                 #bb.note('depends for %s is %s' % (base, depends))
799                 rreclist = explode_deps(bb.data.getVar('RRECOMMENDS_' + pkg, d, 1) or bb.data.getVar('RRECOMMENDS', d, 1) or "")
800
801                 for depend in depends:
802                         if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'):
803                                 #bb.note("Skipping %s" % depend)
804                                 continue
805                         if depend.endswith('-dev'):
806                                 depend = depend.replace('-dev', '')
807                         if depend.endswith('-dbg'):
808                                 depend = depend.replace('-dbg', '')
809                         pkgname = getname(depend, suffix)
810                         #bb.note("Adding %s for %s" % (pkgname, depend))
811                         if not pkgname in rreclist:
812                                 rreclist.append(pkgname)
813
814                 #bb.note('setting: RRECOMMENDS_%s=%s' % (pkg, ' '.join(rreclist)))
815                 bb.data.setVar('RRECOMMENDS_%s' % pkg, ' '.join(rreclist), d)
816
817         def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d):
818
819                 #bb.note('rdepends for %s is %s' % (base, rdepends))
820                 rreclist = explode_deps(bb.data.getVar('RRECOMMENDS_' + pkg, d, 1) or bb.data.getVar('RRECOMMENDS', d, 1) or "")
821
822                 for depend in rdepends:
823                         if depend.endswith('-dev'):
824                                 depend = depend.replace('-dev', '')
825                         if depend.endswith('-dbg'):
826                                 depend = depend.replace('-dbg', '')
827                         pkgname = getname(depend, suffix)
828                         if not pkgname in rreclist:
829                                 rreclist.append(pkgname)
830
831                 #bb.note('setting: RRECOMMENDS_%s=%s' % (pkg, ' '.join(rreclist)))
832                 bb.data.setVar('RRECOMMENDS_%s' % pkg, ' '.join(rreclist), d)
833
834         def add_dep(list, dep):
835                 dep = dep.split(' (')[0].strip()
836                 if dep not in list:
837                         list.append(dep)
838
839         depends = []
840         for dep in explode_deps(bb.data.getVar('DEPENDS', d, 1) or ""):
841                 add_dep(depends, dep)
842
843         rdepends = []
844         for dep in explode_deps(bb.data.getVar('RDEPENDS', d, 1) or ""):
845                 add_dep(rdepends, dep)
846
847         for pkg in packages.split():
848                 for dep in explode_deps(bb.data.getVar('RDEPENDS_' + pkg, d, 1) or ""):
849                         add_dep(rdepends, dep)
850
851         #bb.note('rdepends is %s' % rdepends)
852
853         def post_getname(name, suffix):
854                 return '%s%s' % (name, suffix)
855         def pre_getname(name, suffix):
856                 return '%s%s' % (suffix, name)
857
858         pkgs = {}
859         for pkg in packages.split():
860                 for postfix in postfixes:
861                         if pkg.endswith(postfix):
862                                 if not postfix in pkgs:
863                                         pkgs[postfix] = {}
864                                 pkgs[postfix][pkg] = (pkg[:-len(postfix)], post_getname)
865
866                 for prefix in prefixes:
867                         if pkg.startswith(prefix):
868                                 if not prefix in pkgs:
869                                         pkgs[prefix] = {}
870                                 pkgs[prefix][pkg] = (pkg[:-len(prefix)], pre_getname)
871
872         for suffix in pkgs:
873                 for pkg in pkgs[suffix]:
874                         (base, func) = pkgs[suffix][pkg]
875                         if suffix == "-dev":
876                                 pkg_adddeprrecs(pkg, base, suffix, func, depends, d)
877                         if len(pkgs[suffix]) == 1:
878                                 pkg_addrrecs(pkg, base, suffix, func, rdepends, d)
879                         else:
880                                 rdeps = []
881                                 for dep in explode_deps(bb.data.getVar('RDEPENDS_' + base, d, 1) or bb.data.getVar('RDEPENDS', d, 1) or ""):
882                                         add_dep(rdeps, dep)
883                                 pkg_addrrecs(pkg, base, suffix, func, rdeps, d)
884 }
885
886
887 PACKAGEFUNCS ?= "package_do_split_locales \
888                 populate_packages \
889                 package_do_shlibs \
890                 package_do_pkgconfig \
891                 read_shlibdeps \
892                 package_depchains \
893                 emit_pkgdata"
894
895 python package_do_package () {
896         packages = (bb.data.getVar('PACKAGES', d, 1) or "").split()
897         if len(packages) < 1:
898                 bb.debug(1, "No packages to build, skipping do_package")
899                 return
900
901         for f in (bb.data.getVar('PACKAGEFUNCS', d, 1) or '').split():
902                 bb.build.exec_func(f, d)
903 }
904 do_package[dirs] = "${D}"
905 addtask package before do_build after do_install
906
907 # Dummy task to mark when all packaging is complete
908 do_package_write () {
909         :
910 }
911 addtask package_write before do_build after do_package
912
913 EXPORT_FUNCTIONS do_package do_package_write
914
915 #
916 # Helper functions for the package writing classes
917 #
918
919 python package_mapping_rename_hook () {
920         """
921         Rewrite variables to account for package renaming in things
922         like debian.bbclass or manual PKG variable name changes
923         """
924         runtime_mapping_rename("RDEPENDS", d)
925         runtime_mapping_rename("RRECOMMENDS", d)
926         runtime_mapping_rename("RSUGGESTS", d)
927         runtime_mapping_rename("RPROVIDES", d)
928         runtime_mapping_rename("RREPLACES", d)
929         runtime_mapping_rename("RCONFLICTS", d)
930 }
931
932 EXPORT_FUNCTIONS mapping_rename_hook