Compare commits

..

47 Commits
green ... elroy

Author SHA1 Message Date
Marcin Juszkiewicz
a340e3c7dc libice-native: update to 1.0.4 2009-03-12 09:04:45 +01:00
Koen Kooi
bd417f959e package bbclass: add an 'allow_links' param to get symlinks packaged, usefull for splitting out libraries 2009-03-11 12:08:35 +01:00
Robert Schuster
947e8d5fd6 base.bbclass: Add subdir feature to SRC_URI entries (from OE) 2009-03-11 12:04:16 +01:00
Marcin Juszkiewicz
130ccf8b72 libice-native: added 1.0.3 2009-03-10 12:57:22 +01:00
Marcin Juszkiewicz
d0db241a0a libxt-native: added 1.0.5 2009-03-10 12:57:22 +01:00
Marcin Juszkiewicz
84d814b5e8 libsm-native: added 1.0.3 2009-03-10 12:57:22 +01:00
Marcin Juszkiewicz
f1a5c811b5 libxdmcp-native: fix PROVIDES to empty value (from trunk) 2009-03-10 12:57:21 +01:00
Marcin Juszkiewicz
f5b492949e libx11-native: fix PROVIDES to empty value (from trunk) 2009-03-10 12:57:21 +01:00
Marcin Juszkiewicz
dce1887d8b checksums.ini: merge with trunk 2009-02-26 16:32:49 +01:00
Marcin Juszkiewicz
deddd3a450 shared-mime-info: fixed dependencies for native version (from trunk) 2009-02-23 17:06:59 +01:00
Marcin Juszkiewicz
2a643be89d ldconfig-native: set $S to proper value 2009-02-23 11:32:32 +01:00
Marcin Juszkiewicz
2b91ffc371 bitbake.conf: update Poky Maintainer name to "Poky Team <poky@openedhand.com>" (from trunk) 2009-02-20 17:33:33 +01:00
Marcin Juszkiewicz
f29120d571 base.bbclass, bitbake.conf: add support for BP/BPN variables (backported from trunk)
commit 94c895aad5
Author: Richard Purdie <rpurdie@linux.intel.com>
Date:   Fri Jan 2 10:15:45 2009 +0000

bitbake.conf: Create BPN variable containing the pruned version of
PN with various suffixes removed and use this for S and FILESPATH.
This uses naming from OE but with improved code
2009-02-20 17:33:13 +01:00
Marcin Juszkiewicz
b5a58d32f0 bitbake.conf: add IMAGE_ROOTFS_SIZE (from OE) 2009-01-23 17:48:38 +00:00
Richard Purdie
7361e38803 exmap-console: Backport DEPENDS fix from trunk (from hrw) 2009-01-23 16:51:15 +00:00
Richard Purdie
2cf9a10026 bitbake.conf/image.bbclass: Backport the magic rootfs sizing code from trunk (from hrw) 2009-01-23 16:27:25 +00:00
Richard Purdie
ebe7499a5e libtool-native: Stage libltdl headers (backport from master) 2009-01-02 12:09:34 +00:00
Ross Burton
cd4c255c94 hicolor-icon-theme: add size/stock directories to hicolor for compatibility with OpenMoko 2008-12-23 15:19:28 +00:00
Ross Burton
e6fe4911cf hicolor-icon-theme: ship a custom index.theme which includes the Hildon icon sizes 2008-12-16 18:06:55 +00:00
Ross Burton
0111b3ac5f openmoko-icon-theme-standard2: add a compat package which symlinks the new icons into hicolor 2008-12-16 15:37:16 +00:00
Ross Burton
0e3639209f Bump matchbox-desktop srcrev
This version of Matchbox Desktop correctly recurses when loading desktop files,
so it handles Hildon-style application folders.
2008-12-04 15:28:13 +00:00
Ross Burton
fb265757b9 clutter: fix -examples package naming 2008-12-01 17:56:39 +00:00
Richard Purdie
893cc30c71 clutter-0.6: Bump PR
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5411 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-12-01 17:56:35 +00:00
Richard Purdie
e43ee1281d clutter-0.6: Bump PR
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5410 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-12-01 17:56:35 +00:00
Richard Purdie
7edfdb4961 clutter-cairo: Set S correctly
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5409 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-12-01 17:56:34 +00:00
Robert Bragg
bfb1d06d69 Some build fixes for clutter-cairo-0.6, and clutter-gtk_svn
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5394 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-12-01 17:56:34 +00:00
Robert Bragg
eea56a7f4d Merge Clutter packaging rewrite from master.
- This adds clutter-{gst,gtk,cairo}-0.8 recipes and clutter-{gst,gtk,cairo}-0.6 recipes.
- It removes the 0.4 recipes.
- It renames things so that the major.minor revision is now part of the package name.
  This lets us correctly specify SRCREVs for each branch, and allows parallell install.
- All the SRCREVs have been updated to the heads of their corresponding branches

git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5384 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-12-01 17:56:33 +00:00
Ross Burton
13ac7cba37 Add gst-plugin-pulse 2008-12-01 17:56:29 +00:00
Ross Burton
1a5ccf1dde Fix compile failures on Intrepid 2008-12-01 17:56:15 +00:00
Ross Burton
64c2e76123 Fix qemu build on 2.6.27
Linux 2.6.27 removed linux/dirent.h, which qemu was included. Change this to
include dirent.h.
2008-12-01 17:54:49 +00:00
Ross Burton
83b96f079c Add gnome-icon-theme
This is required by some of the OpenMoko packages.  No idea how it didn't get
into elroy...
2008-10-30 11:40:06 +00:00
Ross Burton
cb404c508d poky-image-openmoko.bb: remove matchbox-applet-startup-monitor
We don't ship matchbox-applet-startup-monitor, so remove it.
2008-10-23 15:08:02 +01:00
Ross Burton
b797b8034c poky-image-openmoko.bb: remove unused PR 2008-10-23 15:07:42 +01:00
Richard Purdie
d39962a9fa Merged revisions 5355 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5355 | josh | 2008-10-01 00:05:39 +0100 (Wed, 01 Oct 2008) | 2 lines
  
  Fix a typo in the COMPATIBLE_MACHINE list
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5377 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-10-02 08:49:56 +00:00
Richard Purdie
ac9664c930 Merged revisions 5310 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5310 | richard | 2008-09-29 17:15:07 +0100 (Mon, 29 Sep 2008) | 1 line
  
  omap-3430: Generate jffs2 images
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5312 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-29 16:54:34 +00:00
Richard Purdie
dcf7185bab Merged revisions 5309 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5309 | richard | 2008-09-29 17:06:49 +0100 (Mon, 29 Sep 2008) | 1 line
  
  linux-omap-3430ldp: Build jffs2 support in.
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5311 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-29 16:53:36 +00:00
Ross Burton
c40aba1b89 Merged revisions 5306 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5306 | ross | 2008-09-29 13:49:37 +0100 (Mon, 29 Sep 2008) | 1 line
  
  libnotify: move from meta-extras to meta-openmoko
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5307 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-29 12:50:33 +00:00
Ross Burton
c2d945ef1c Merged revisions 5294 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5294 | ross | 2008-09-26 13:54:49 +0100 (Fri, 26 Sep 2008) | 1 line
  
  poky-fixed-revisions.inc: bump matchbox-wm-2 for work area fixes
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5295 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 12:58:00 +00:00
Ross Burton
65dc3dd729 Merged revisions 5287 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5287 | ross | 2008-09-26 10:29:52 +0100 (Fri, 26 Sep 2008) | 1 line
  
  clutter.inc: use eglnative on 3430sdp
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5289 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 09:32:57 +00:00
Ross Burton
dbc3a1ecb3 Blocked revisions 5237-5277 via svnmerge
........
  r5237 | rob | 2008-09-23 11:38:54 +0100 (Tue, 23 Sep 2008) | 1 line
  
  glib-2.0: Add 2.18.1 (new stable release)
........
  r5238 | rob | 2008-09-23 12:21:52 +0100 (Tue, 23 Sep 2008) | 1 line
  
  glib-2.0: Update default revision to 2.18.1
........
  r5239 | rob | 2008-09-23 12:22:01 +0100 (Tue, 23 Sep 2008) | 1 line
  
  glib-2.0: Remove old bleeding version.
........
  r5240 | hrw | 2008-09-23 12:26:18 +0100 (Tue, 23 Sep 2008) | 1 line
  
  checksums.ini: added some entries
........
  r5241 | hrw | 2008-09-23 13:54:15 +0100 (Tue, 23 Sep 2008) | 1 line
  
  metacity: do not require gdk-pixbuf-csource
........
  r5242 | rob | 2008-09-23 15:18:17 +0100 (Tue, 23 Sep 2008) | 1 line
  
  iso-codes: Add iso-codes package
........
  r5243 | rob | 2008-09-23 15:23:46 +0100 (Tue, 23 Sep 2008) | 1 line
  
  intltool: Update to intltool 0.37.1
........
  r5244 | rob | 2008-09-23 15:29:10 +0100 (Tue, 23 Sep 2008) | 1 line
  
  iso-codes: Make PACKAGE_ARCH=all
........
  r5245 | hrw | 2008-09-23 17:32:24 +0100 (Tue, 23 Sep 2008) | 1 line
  
  mesa-dri: fix packaging so test apps will really land in own package
........
  r5246 | hrw | 2008-09-23 17:32:37 +0100 (Tue, 23 Sep 2008) | 1 line
  
  xf86-video-intel: mark as x86 only
........
  r5247 | hrw | 2008-09-23 17:42:03 +0100 (Tue, 23 Sep 2008) | 1 line
  
  mesa-xlib: added non-dri version of mesa
........
  r5248 | hrw | 2008-09-23 17:42:13 +0100 (Tue, 23 Sep 2008) | 1 line
  
  mesa-dri: make it non-default for targets other then EeePC 901
........
  r5249 | rob | 2008-09-23 17:57:48 +0100 (Tue, 23 Sep 2008) | 1 line
  
  libxklavier: add libxklavier 3.7 (XKB wrapper library)
........
  r5250 | rob | 2008-09-23 17:57:57 +0100 (Tue, 23 Sep 2008) | 3 lines
  
  gtk+: Add gtk+ 2.14.2
  
  (with rebased hardcoded_libtool.patch and new disable-gio-png-sniff-test.diff)
........
  r5251 | hrw | 2008-09-24 09:10:15 +0100 (Wed, 24 Sep 2008) | 1 line
  
  libtiff: set LICENSE
........
  r5252 | tf | 2008-09-24 09:56:27 +0100 (Wed, 24 Sep 2008) | 1 line
  
  added recipe for metacity-clutter
........
  r5253 | ross | 2008-09-24 14:29:51 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gtk-industrial-engine: remove ancient package
........
  r5254 | ross | 2008-09-24 14:46:17 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gtk-clearlooks-engine_0.6.2.bb: remove old version
........
  r5255 | ross | 2008-09-24 14:46:50 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gtk-engines: set PACKAGES_DYNAMIC
........
  r5256 | ross | 2008-09-24 14:49:08 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gtk-theme-darkilouche.bb: depend on gtk-engines so that clearlooks is built, and rdepend on the engine not the theme
........
  r5257 | hrw | 2008-09-24 15:10:25 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gdk-pixbuf-csource: added 2.12.7
........
  r5258 | hrw | 2008-09-24 15:10:41 +0100 (Wed, 24 Sep 2008) | 1 line
  
  metacity(-clutter): use gdk-pixbuf-csource-native
........
  r5259 | hrw | 2008-09-24 15:20:08 +0100 (Wed, 24 Sep 2008) | 1 line
  
  jpeg: added native version
........
  r5260 | hrw | 2008-09-24 15:39:17 +0100 (Wed, 24 Sep 2008) | 1 line
  
  matchbox-themes-gtk: fixed dependencies after clearlooks cleanup
........
  r5261 | ross | 2008-09-24 15:43:58 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gtk-engines-2.10.2: remove old release
........
  r5262 | ross | 2008-09-24 15:46:42 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gtk-engines_2.14.0.bb: add PACKAGES_DYNAMIC
........
  r5263 | ross | 2008-09-24 15:47:09 +0100 (Wed, 24 Sep 2008) | 1 line
  
  gtk-engines-2.12: remove
........
  r5264 | rob | 2008-09-24 19:55:15 +0100 (Wed, 24 Sep 2008) | 1 line
  
  qemu-sdk: Build i386 QEMU for inclusion in the sdk.
........
  r5265 | rob | 2008-09-24 21:15:19 +0100 (Wed, 24 Sep 2008) | 1 line
  
  libx11-trim: Add missing dep on xf86bigfontproto
........
  r5266 | josh | 2008-09-25 10:50:05 +0100 (Thu, 25 Sep 2008) | 3 lines
  
  Initial support for netbooks with a poky-image-netbook(-live) image target.
  This needs much love from folk with UI and WM skills.
........
  r5267 | josh | 2008-09-25 14:27:10 +0100 (Thu, 25 Sep 2008) | 2 lines
  
  Netbooks will use Sato too for now.
........
  r5268 | hrw | 2008-09-25 15:09:07 +0100 (Thu, 25 Sep 2008) | 1 line
  
  qemu targets: added IMAGE_ROOTFS_SIZE for ext3 filesystems
........
  r5269 | hrw | 2008-09-25 15:09:22 +0100 (Thu, 25 Sep 2008) | 7 lines
  
  image.bbclass: make ext2/ext3 images autoresize
  
  New variable IMAGE_EXTRA_SPACE contains amount of kilobytes which has
  to be added to size of IMAGE_ROOTFS. Resulting size is then passed to
  genext2fs util.
  
  As a result we do not have to specify size for ROOTFS_SIZE anymore.
........
  r5270 | sameo | 2008-09-25 15:41:56 +0100 (Thu, 25 Sep 2008) | 4 lines
  
  acpid: Initial poky commit
  
  Needed on x86 machines.
........
  r5271 | sameo | 2008-09-25 15:47:22 +0100 (Thu, 25 Sep 2008) | 5 lines
  
  pm-utils: Initial commit
  
  This is a set of scripts usually needed by the ACPI 
  sleep/hibernate hooks.
........
  r5272 | sameo | 2008-09-25 15:58:13 +0100 (Thu, 25 Sep 2008) | 4 lines
  
  eee-acpi-scripts: Initial commit
  
  eeePC specific ACPI hooks.
........
  r5273 | sameo | 2008-09-25 16:06:11 +0100 (Thu, 25 Sep 2008) | 4 lines
  
  eee901: Add acpi and eee-acpi-scripts
  
  We can now suspend/resume the eee901 through the Fn keys.
........
  r5274 | richard | 2008-09-25 16:10:47 +0100 (Thu, 25 Sep 2008) | 1 line
  
  xcb-proto: Fix -dev and -dbg dependencies
........
  r5275 | josh | 2008-09-25 17:38:36 +0100 (Thu, 25 Sep 2008) | 2 lines
  
  Update fixed revision for the latest, greatest, metacity-clutter.
........
  r5276 | sameo | 2008-09-25 18:02:04 +0100 (Thu, 25 Sep 2008) | 2 lines
  
  eee-acpi-scripts: SRCREV should be in the distro config files
........
  r5277 | richard | 2008-09-25 21:38:26 +0100 (Thu, 25 Sep 2008) | 1 line
  
  eee-acpi-scripts: Set PV correctly
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5288 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 09:30:10 +00:00
Ross Burton
0d09d7af3e Blocked revisions 5166-5168,5171-5176,5179-5180,5182,5184,5186,5188,5199-5202,5204-5234 via svnmerge
........
  r5166 | sameo | 2008-09-10 16:37:14 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  linux-moblin2: Add moblin2 kernel
........
  r5167 | sameo | 2008-09-10 16:43:46 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  eee901: Initial support
........
  r5168 | sameo | 2008-09-10 16:44:26 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  formfactor: Add eee901 config file
........
  r5171 | sameo | 2008-09-10 22:12:46 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  eee901: Add video kernel options, vesa for now.
........
  r5172 | sameo | 2008-09-10 22:19:19 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  bootimg: Adding a rootfs to the disk image
........
  r5173 | sameo | 2008-09-10 22:21:23 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  initrdscripts: Simple init files for initrd/initramfs images
........
  r5174 | sameo | 2008-09-10 22:24:24 +0100 (Wed, 10 Sep 2008) | 4 lines
  
  Added live USB poky images
  
  We support sato and minimal live USB image production.
........
  r5175 | richard | 2008-09-10 23:07:29 +0100 (Wed, 10 Sep 2008) | 1 line
  
  poky-image-live.inc: Only run the FSTYPES check when the task is run
........
  r5176 | sameo | 2008-09-10 23:21:00 +0100 (Wed, 10 Sep 2008) | 2 lines
  
  exmap-console: Bump to the latest SVN
........
  r5179 | richard | 2008-09-10 23:54:21 +0100 (Wed, 10 Sep 2008) | 1 line
  
  pokyABConfig.py: Add eee901 builds
........
  r5180 | sameo | 2008-09-11 09:59:00 +0100 (Thu, 11 Sep 2008) | 5 lines
  
  image-live: exclude from world builds
  
  We also remove a video kernel command line option, as this is platform 
  specific.
........
  r5182 | richard | 2008-09-11 15:37:35 +0100 (Thu, 11 Sep 2008) | 1 line
  
  local.conf.sample: Add comment about eee901
........
  r5184 | sameo | 2008-09-11 16:57:47 +0100 (Thu, 11 Sep 2008) | 2 lines
  
  rt2860: Support for the rt2860 RaLink 802.11n chipset
........
  r5186 | sameo | 2008-09-11 17:35:54 +0100 (Thu, 11 Sep 2008) | 2 lines
  
  eee901: Add wifi support
........
  r5188 | richard | 2008-09-11 21:13:05 +0100 (Thu, 11 Sep 2008) | 1 line
  
  rt2860: Set COMPATIBLE_MACHINE for now to avoid builds with elderly kernels
........
  r5199 | josh | 2008-09-18 19:01:51 +0100 (Thu, 18 Sep 2008) | 2 lines
  
  Make the eee use the correct DPI.
........
  r5200 | josh | 2008-09-18 19:02:38 +0100 (Thu, 18 Sep 2008) | 2 lines
  
  Native pacage for the OpenSuse build service client.
........
  r5201 | josh | 2008-09-18 19:03:20 +0100 (Thu, 18 Sep 2008) | 2 lines
  
  Fetch implementation for the OpenSuse build service.
........
  r5202 | richard | 2008-09-19 18:29:23 +0100 (Fri, 19 Sep 2008) | 1 line
  
  gcc: Add 4.3.2 recipes
........
  r5204 | richard | 2008-09-22 12:48:01 +0100 (Mon, 22 Sep 2008) | 1 line
  
  cdrtools-native: Don't look for headers in /usr/src/linux, that would be crazy
........
  r5205 | bob | 2008-09-22 14:33:19 +0100 (Mon, 22 Sep 2008) | 20 lines
  
  Adds recipes to support building X servers based on the xfree86 DDX instead
  of kdrive and building mesa. It's a big commit and it's still rather rough
  around the edges, but there is a desire to get this in early so people can
  review the work and help polish the changes.
  
  Some of the notable bits:
  • DRI support in mesa and the X server. (configured in machine conf via
    MACHINE_DRI_MODULES variable)
  • XCB backend for xlib
  • A fairly lite X server build with lots of legacy modules disabled.
  
  I'm sure there is plenty of other fairly low hanging fruit if we want to
  put more effort into reducing the size of the xserver build. Currently the
  server build comes in @ ~2.3MB vs a kdrive fbdev server build @ ~1MB. E.g
  xaa could be made conditional to save ~320K. Of course the kdrive server
  doesn't include glx stuff, which is a pretty big chunk.
  
  Also thanks to hrw, since I nabbed a some patches from him for this, and RP,
  for various bits of Poky style advice.
........
  r5206 | hrw | 2008-09-22 14:50:05 +0100 (Mon, 22 Sep 2008) | 1 line
  
  libxdmcp-native: do not provide xdmcp
........
  r5207 | hrw | 2008-09-22 14:50:15 +0100 (Mon, 22 Sep 2008) | 1 line
  
  libx11-native: do not provide virtual/libx11
........
  r5208 | ross | 2008-09-22 14:53:19 +0100 (Mon, 22 Sep 2008) | 1 line
  
  Move libsoup to its own directory
........
  r5209 | hrw | 2008-09-22 14:58:57 +0100 (Mon, 22 Sep 2008) | 1 line
  
  libxkbfile-native: needed by xkbcomp-native
........
  r5210 | hrw | 2008-09-22 14:59:11 +0100 (Mon, 22 Sep 2008) | 1 line
  
  xkbcomp: added 1.0.5 required by xkeyboard-config
........
  r5211 | hrw | 2008-09-22 14:59:21 +0100 (Mon, 22 Sep 2008) | 1 line
  
  xkeyboard-config: add keymaps for X11
........
  r5212 | hrw | 2008-09-22 14:59:31 +0100 (Mon, 22 Sep 2008) | 1 line
  
  xkeyboard-config: provide 'xorg' rules which are link to 'base' ones
........
  r5213 | hrw | 2008-09-22 15:03:19 +0100 (Mon, 22 Sep 2008) | 1 line
  
  xf86-video-intel: add missing dependencies
........
  r5214 | hrw | 2008-09-22 15:46:13 +0100 (Mon, 22 Sep 2008) | 1 line
  
  libx11-trim: fix location on keysymdef.h
........
  r5215 | tf | 2008-09-22 16:37:55 +0100 (Mon, 22 Sep 2008) | 1 line
  
  added missing dri2proto dependency
........
  r5216 | josh | 2008-09-22 17:43:39 +0100 (Mon, 22 Sep 2008) | 2 lines
  
  Basic recipe for Metacity. Needs some tweaking to strip out themes into separate packages and strip some unneeded binaries.
........
  r5217 | ross | 2008-09-22 17:47:42 +0100 (Mon, 22 Sep 2008) | 1 line
  
  gnome-icon-theme: add
........
  r5218 | ross | 2008-09-22 17:48:52 +0100 (Mon, 22 Sep 2008) | 1 line
  
  libsoup-2.4: add libsoup 2.4
........
  r5219 | bob | 2008-09-22 18:19:02 +0100 (Mon, 22 Sep 2008) | 2 lines
  
  Some fixes for the xorg.conf for xserver-xf86-dri-lite
........
  r5220 | rob | 2008-09-22 19:32:20 +0100 (Mon, 22 Sep 2008) | 1 line
  
  Update to gtk-engines 2.14
........
  r5221 | rob | 2008-09-22 19:32:31 +0100 (Mon, 22 Sep 2008) | 1 line
  
  Add the Darkilouche dark theme
........
  r5222 | sameo | 2008-09-22 19:48:09 +0100 (Mon, 22 Sep 2008) | 2 lines
  
  libgdbus: Adding libgdbus as connman needs it
........
  r5223 | sameo | 2008-09-22 19:54:37 +0100 (Mon, 22 Sep 2008) | 2 lines
  
  libgdbus: Add latest git as SRCREV
........
  r5224 | sameo | 2008-09-22 19:56:51 +0100 (Mon, 22 Sep 2008) | 2 lines
  
  resolvconf: Adding resolvconf as connman needs it
........
  r5225 | sameo | 2008-09-22 20:02:30 +0100 (Mon, 22 Sep 2008) | 5 lines
  
  connman: Initial poky commit
  
  We're adding both connman the daemon and connman-gnome which is a gnome 
  applet.
........
  r5226 | hrw | 2008-09-22 20:08:58 +0100 (Mon, 22 Sep 2008) | 1 line
  
  libx11-trim: added missing dependencies
........
  r5227 | hrw | 2008-09-22 20:09:23 +0100 (Mon, 22 Sep 2008) | 1 line
  
  libxrender: added missing dependencies
........
  r5228 | bob | 2008-09-23 00:28:49 +0100 (Tue, 23 Sep 2008) | 5 lines
  
  increments task-poky revision, which fixed a dependency problem for me and
  may help with similar problems others are seeing with the new X builds. (The
  problem seemed to be related to the XSERVER variable which is referred to in
  task-poky.bb)
........
  r5229 | bob | 2008-09-23 00:40:14 +0100 (Tue, 23 Sep 2008) | 3 lines
  
  Adds eee901 specific support into clutter.inc and adds a new virtual/libgl
  for clutter to depend on which all mesa build variants provide.
........
  r5230 | bob | 2008-09-23 03:00:56 +0100 (Tue, 23 Sep 2008) | 2 lines
  
  Ensures the themes get packaged with metacity
........
  r5231 | bob | 2008-09-23 03:01:11 +0100 (Tue, 23 Sep 2008) | 3 lines
  
  Bumps the mesa-dri revision to 7.2 and adds a mesa-xdemos package including
  e.g glxinfo
........
  r5232 | bob | 2008-09-23 04:21:06 +0100 (Tue, 23 Sep 2008) | 2 lines
  
  Makes metacity install as an alternative x-window-manager
........
  r5233 | josh | 2008-09-23 04:30:23 +0100 (Tue, 23 Sep 2008) | 3 lines
  
  Add a bzip2-full-native recipe and make the python-native recipe depend on it.
  Yum requires bzip2 support in Python so our native Python package needs something to provide it.
........
  r5234 | rob | 2008-09-23 10:02:49 +0100 (Tue, 23 Sep 2008) | 1 line
  
  gnome-icon-theme: add an RRECOMMENDS on librsvg-gtk
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5286 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 09:22:12 +00:00
Ross Burton
005f63f560 Merged revisions 5203,5235-5236,5278-5279 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5203 | richard | 2008-09-19 18:32:35 +0100 (Fri, 19 Sep 2008) | 1 line
  
  tune-xscale.inc: Compile cairo for armv4 to avoid alighment trap issues with double instruction
........
  r5235 | ross | 2008-09-23 10:54:16 +0100 (Tue, 23 Sep 2008) | 1 line
  
  poky-fixed-revisions.inc: bump matchbox-desktop srvrev to fix icon loading bug
........
  r5236 | ross | 2008-09-23 11:14:38 +0100 (Tue, 23 Sep 2008) | 1 line
  
  poky-fixed-revisions.inc: fix typo
........
  r5278 | ross | 2008-09-25 21:52:29 +0100 (Thu, 25 Sep 2008) | 1 line
  
  dialer: specify revision instead of using autorev
........
  r5279 | richard | 2008-09-25 22:03:38 +0100 (Thu, 25 Sep 2008) | 1 line
  
  xserver-kdrive: Feed xrandr calls to the framebuffer driver in case it can do better than software rotation
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5285 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 09:02:47 +00:00
Ross Burton
cd8b52418c Merged revisions 5189-5198 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5189 | richard | 2008-09-11 23:41:08 +0100 (Thu, 11 Sep 2008) | 1 line
  
  local.conf.sample: Make the parallel threads documentation more visible and update with a quadcore example
........
  r5190 | richard | 2008-09-12 00:02:51 +0100 (Fri, 12 Sep 2008) | 1 line
  
  handbook/quickstart: Improve documentation on the options available in local.conf
........
  r5191 | richard | 2008-09-12 00:11:45 +0100 (Fri, 12 Sep 2008) | 1 line
  
  handbook/faq.xml: Add a QA about proxy server setup
........
  r5192 | ross | 2008-09-12 16:43:10 +0100 (Fri, 12 Sep 2008) | 1 line
  
  ref-variables.xml: Add POKY_EXTRA_INSTALL
........
  r5193 | ross | 2008-09-16 10:00:50 +0100 (Tue, 16 Sep 2008) | 1 line
  
  poky-fixed-revisions.inc: bump matchbox-wm-2
........
  r5194 | ross | 2008-09-16 16:36:32 +0100 (Tue, 16 Sep 2008) | 1 line
  
  poky-fixed-revisions: bump libowl srvrev
........
  r5195 | ross | 2008-09-16 17:24:31 +0100 (Tue, 16 Sep 2008) | 1 line
  
  poky-fixed-revisions.inc: bump matchbox-desktop srvrev
........
  r5196 | richard | 2008-09-16 20:14:49 +0100 (Tue, 16 Sep 2008) | 1 line
  
  bitbake parse/__init_.py: Add missing update_mtime function fixing bitbake shell reparse failures
........
  r5197 | richard | 2008-09-16 21:09:03 +0100 (Tue, 16 Sep 2008) | 1 line
  
  ConfHandler.py: revert accidental commit
........
  r5198 | ross | 2008-09-18 10:35:14 +0100 (Thu, 18 Sep 2008) | 1 line
  
  poky-eabi.conf: add dialer to as-needed blacklist
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5284 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 08:58:28 +00:00
Ross Burton
75f3f9bb6d Merged revisions 5177-5178,5181,5183,5185,5187 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5177 | richard | 2008-09-10 23:29:43 +0100 (Wed, 10 Sep 2008) | 1 line
  
  package.bbclass: Adjust to handle split packages already being present in PACKAGES
........
  r5178 | richard | 2008-09-10 23:32:22 +0100 (Wed, 10 Sep 2008) | 1 line
  
  gst-plugins-good: Remove bogus RPROVIDES and add to PACKAGES instead now the package class can handle this
........
  r5181 | richard | 2008-09-11 12:00:49 +0100 (Thu, 11 Sep 2008) | 1 line
  
  poky-eabi.inc/poky-fixed-revisions.inc: Bump the matchbox-wm-2 revision and remove from the asneeded blacklist
........
  r5183 | richard | 2008-09-11 16:43:25 +0100 (Thu, 11 Sep 2008) | 1 line
  
  eds-dbus: Add missing DEPENDS on libglade
........
  r5185 | ross | 2008-09-11 17:07:38 +0100 (Thu, 11 Sep 2008) | 1 line
  
  eds-dbus: package the glade files into libedataserverui
........
  r5187 | ross | 2008-09-11 17:57:47 +0100 (Thu, 11 Sep 2008) | 1 line
  
  eds-dbus: add libedataserverui to PACKAGES, fixing the borked packaging
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5283 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 08:55:15 +00:00
Ross Burton
148459e611 Merged revisions 5169-5170 via svnmerge from
https://svn.o-hand.com/repos/poky/trunk

........
  r5169 | ross | 2008-09-10 17:17:54 +0100 (Wed, 10 Sep 2008) | 1 line
  
  gaku: clean up depends/recommends
........
  r5170 | richard | 2008-09-10 17:25:46 +0100 (Wed, 10 Sep 2008) | 20 lines
  
  bitbake hg fetcher: Add fix from Matt Hoosier
  
  The Mercurial fetcher right now will fail when used to incrementally
  fetch an update to a local clone of a repository already fetched at
  some prior revision. The culprit is the sequence:
  
   hg pull -r <rev>
   hg update -C <rev>
    
  A subtlety in the way that Mercurial stores its tags (in a normally
  version-controlled file called .hgtags) has the side-effect that a
  repository fetched at a tag "foo" will not actually contain a
  new-enough copy of the .hgtags file to be self-aware of the foo tag's
  existence.
    
  The solution is just to get all the changesets in the repository on
  incremental upgrades, so that the following "hg update" will be able
  to resolve the tag.
    
........


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5282 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 08:46:30 +00:00
Ross Burton
a96187d660 Initialized merge tracking via "svnmerge" with revisions "1-5165" from
https://svn.o-hand.com/repos/poky/trunk


git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5281 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 08:44:52 +00:00
Ross Burton
0935caeded Branch for Elroy
git-svn-id: https://svn.o-hand.com/repos/poky/branches/elroy@5280 311d38ba-8fff-0310-9ca6-ca027cbcb966
2008-09-26 08:39:10 +00:00
3135 changed files with 699466 additions and 2954873 deletions

35
.gitignore vendored
View File

@@ -1,35 +0,0 @@
*.pyc
*.pyo
build/conf/local.conf
build/conf/bblayers.conf
build/tmp/
pstage/
scripts/poky-git-proxy-socks
sources/
meta-darwin
meta-maemo
meta-prvt*
poky-autobuilder*
*.swp
*.orig
*.rej
*~
handbook/poky-doc-tools/Makefile
handbook/poky-doc-tools/Makefile.in
handbook/poky-doc-tools/aclocal.m4
handbook/poky-doc-tools/autom4te.cache/
handbook/poky-doc-tools/common/Makefile
handbook/poky-doc-tools/common/Makefile.in
handbook/poky-doc-tools/common/fop-config.xml
handbook/poky-doc-tools/config.log
handbook/poky-doc-tools/config.status
handbook/poky-doc-tools/configure
handbook/poky-doc-tools/install-sh
handbook/poky-doc-tools/missing
handbook/poky-doc-tools/poky-docbook-to-pdf
handbook/poky-handbook.html
handbook/poky-handbook.pdf
handbook/poky-handbook.tgz
handbook/bsp-guide.html
handbook/bsp-guide.pdf

View File

@@ -5,10 +5,7 @@ bitbake/COPYING (GPLv2)
meta/COPYING.MIT (MIT)
meta-extras/COPYING.MIT (MIT)
which cover the components in those subdirectories. This means all
metadata is MIT licensed unless otherwise stated. Source code included
in tree for individual recipes is under the LICENSE stated in the .bb
file for those software projects unless otherwise stated.
which cover the components in those subdirectories.
License information for any other files is either explicitly stated
or defaults to GPL version 2.

View File

@@ -2,7 +2,7 @@ Tim Ansell <mithro@mithis.net>
Phil Blundell <pb@handhelds.org>
Seb Frankengul <seb@frankengul.org>
Holger Freyther <zecke@handhelds.org>
Marcin Juszkiewicz <marcin@juszkiewicz.com.pl>
Marcin Juszkiewicz <hrw@hrw.one.pl>
Chris Larson <kergoth@handhelds.org>
Ulrich Luckas <luckas@musoft.de>
Mickey Lauer <mickey@Vanille.de>

View File

@@ -1,99 +1,5 @@
Changes in Bitbake 1.9.x:
- Add PE (Package Epoch) support from Philipp Zabel (pH5)
- Treat python functions the same as shell functions for logging
- Use TMPDIR/anonfunc as a __anonfunc temp directory (T)
- Catch truncated cache file errors
- Allow operations other than assignment on flag variables
- Add code to handle inter-task dependencies
- Fix cache errors when generation dotGraphs
- Make sure __inherit_cache is updated before calling include() (from Michael Krelin)
- Fix bug when target was in ASSUME_PROVIDED (#2236)
- Raise ParseError for filenames with multiple underscores instead of infinitely looping (#2062)
- Fix invalid regexp in BBMASK error handling (missing import) (#1124)
- Promote certain warnings from debug to note 2 level
- Update manual
- Correctly redirect stdin when forking
- If parsing errors are found, exit, too many users miss the errors
- Remove supriours PREFERRED_PROVIDER warnings
- svn fetcher: Add _buildsvncommand function
- Improve certain error messages
- Rewrite svn fetcher to make adding extra operations easier
as part of future SRCDATE="now" fixes
(requires new FETCHCMD_svn definition in bitbake.conf)
- Change SVNDIR layout to be more unique (fixes #2644 and #2624)
- Add ConfigParsed Event after configuration parsing is complete
- Add SRCREV support for svn fetcher
- data.emit_var() - only call getVar if we need the variable
- Stop generating the A variable (seems to be legacy code)
- Make sure intertask depends get processed correcting in recursive depends
- Add pn-PN to overrides when evaluating PREFERRED_VERSION
- Improve the progress indicator by skipping tasks that have
already run before starting the build rather than during it
- Add profiling option (-P)
- Add BB_SRCREV_POLICY variable (clear or cache) to control SRCREV cache
- Add SRCREV_FORMAT support
- Fix local fetcher's localpath return values
- Apply OVERRIDES before performing immediate expansions
- Allow the -b -e option combination to take regular expressions
- Fix handling of variables with expansion in the name using _append/_prepend
e.g. RRECOMMENDS_${PN}_append_xyz = "abc"
- Add plain message function to bb.msg
- Sort the list of providers before processing so dependency problems are
reproducible rather than effectively random
- Fix/improve bitbake -s output
- Add locking for fetchers so only one tries to fetch a given file at a given time
- Fix int(0)/None confusion in runqueue.py which causes random gaps in dependency chains
- Expand data in addtasks
- Print the list of missing DEPENDS,RDEPENDS for the "No buildable providers available for required...."
error message.
- Rework add_task to be more efficient (6% speedup, 7% number of function calls reduction)
- Sort digraph output to make builds more reproducible
- Split expandKeys into two for loops to benefit from the expand_cache (12% speedup)
- runqueue.py: Fix idepends handling to avoid dependency errors
- Clear the terminal TOSTOP flag if set (and warn the user)
- Fix regression from r653 and make SRCDATE/CVSDATE work for packages again
- Fix a bug in bb.decodeurl where http://some.where.com/somefile.tgz decoded to host="" (#1530)
- Warn about malformed PREFERRED_PROVIDERS (#1072)
- Add support for BB_NICE_LEVEL option (#1627)
- Psyco is used only on x86 as there is no support for other architectures.
- Sort initial providers list by default preference (#1145, #2024)
- Improve provider sorting so prefered versions have preference over latest versions (#768)
- Detect builds of tasks with overlapping providers and warn (will become a fatal error) (#1359)
- Add MULTI_PROVIDER_WHITELIST variable to allow known safe multiple providers to be listed
- Handle paths in svn fetcher module parameter
- Support the syntax "export VARIABLE"
- Add bzr fetcher
- Add support for cleaning directories before a task in the form:
do_taskname[cleandirs] = "dir"
- bzr fetcher tweaks from Robert Schuster (#2913)
- Add mercurial (hg) fetcher from Robert Schuster (#2913)
- Don't add duplicates to BBPATH
- Fix preferred_version return values (providers.py)
- Fix 'depends' flag splitting
- Fix unexport handling (#3135)
- Add bb.copyfile function similar to bb.movefile (and improve movefile error reporting)
- Allow multiple options for deptask flag
- Use git-fetch instead of git-pull removing any need for merges when
fetching (we don't care about the index). Fixes fetch errors.
- Add BB_GENERATE_MIRROR_TARBALLS option, set to 0 to make git fetches
faster at the expense of not creating mirror tarballs.
- SRCREV handling updates, improvements and fixes from Poky
- Add bb.utils.lockfile() and bb.utils.unlockfile() from Poky
- Add support for task selfstamp and lockfiles flags
- Disable task number acceleration since it can allow the tasks to run
out of sequence
- Improve runqueue code comments
- Add task scheduler abstraction and some example schedulers
- Improve circular dependency chain debugging code and user feedback
- Don't give a stacktrace for invalid tasks, have a user friendly message (#3431)
- Add support for "-e target" (#3432)
- Fix shell showdata command (#3259)
- Fix shell data updating problems (#1880)
- Properly raise errors for invalid source URI protocols
- Change the wget fetcher failure handling to avoid lockfile problems
- Add support for branches in git fetcher (Otavio Salvador, Michael Lauer)
- Make taskdata and runqueue errors more user friendly
- Add norecurse and fullpath options to cvs fetcher
Changes in BitBake 1.8.x:
- Fix -f (force) in conjunction with -b
- Fix exit code for build failures in --continue mode
- Fix git branch tags fetching
- Change parseConfigurationFile so it works on real data, not a copy
@@ -118,10 +24,8 @@ Changes in Bitbake 1.9.x:
how extensively stamps are looked at for validity
- When handling build target failures make sure idepends are checked and
failed where needed. Fixes --continue mode crashes.
- Fix -f (force) in conjunction with -b
- Fix problems with recrdeptask handling where some idepends weren't handled
correctly.
- Handle exit codes correctly (from pH5)
- Work around refs/HEAD issues with git over http (#3410)
- Add proxy support to the CVS fetcher (from Cyril Chemparathy)
- Improve runfetchcmd so errors are seen and various GIT variables are exported
@@ -137,47 +41,109 @@ Changes in Bitbake 1.9.x:
- Add PERSISTENT_DIR to store the PersistData in a persistent
directory != the cache dir.
- Add md5 and sha256 checksum generation functions to utils.py
- Correctly handle '-' characters in class names (#2958)
- Make sure expandKeys has been called on the data dictonary before running tasks
- Correctly add a task override in the form task-TASKNAME.
- Revert the '-' character fix in class names since it breaks things
- When a regexp fails to compile for PACKAGES_DYNAMIC, print a more useful error (#4444)
- Allow to checkout CVS by Date and Time. Just add HHmm to the SRCDATE.
- Move prunedir function to utils.py and add explode_dep_versions function
- Raise an exception if SRCREV == 'INVALID'
- Fix hg fetcher username/password handling and fix crash
- Fix PACKAGES_DYNAMIC handling of packages with '++' in the name
- Rename __depends to __base_depends after configuration parsing so we don't
recheck the validity of the config files time after time
- Add better environmental variable handling. By default it will now only pass certain
whitelisted variables into the data store. If BB_PRESERVE_ENV is set bitbake will use
all variable from the environment. If BB_ENV_WHITELIST is set, that whitelist will be
used instead of the internal bitbake one. Alternatively, BB_ENV_EXTRAWHITE can be used
to extend the internal whitelist.
- Perforce fetcher fix to use commandline options instead of being overriden by the environment
- bb.utils.prunedir can cope with symlinks to directoriees without exceptions
- use @rev when doing a svn checkout
- Add osc fetcher (from Joshua Lock in Poky)
- When SRCREV autorevisioning for a recipe is in use, don't cache the recipe
- Add tryaltconfigs option to control whether bitbake trys using alternative providers
to fulfil failed dependencies. It defaults to off, changing the default since this
behaviour confuses many users and isn't often useful.
- Improve lock file function error handling
- Add username handling to the git fetcher (Robert Bragg)
- Add support for HTTP_PROXY and HTTP_PROXY_IGNORE variables to the wget fetcher
- Export more variables to the fetcher commands to allow ssh checkouts and checkouts through
proxies to work better. (from Poky)
- Also allow user and pswd options in SRC_URIs globally (from Poky)
- Improve proxy handling when using mirrors (from Poky)
- Add bb.utils.prune_suffix function
- Fix hg checkouts of specific revisions (from Poky)
- Fix wget fetching of urls with parameters specified (from Poky)
- Add username handling to git fetcher (from Poky)
- Set HOME environmental variable when running fetcher commands (from Poky)
- Make sure allowed variables inherited from the environment are exported again (from Poky)
- When running a stage task in bbshell, run populate_staging, not the stage task (from Poky)
- Fix + character escaping from PACKAGES_DYNAMIC (thanks Otavio Salvador)
- Addition of BBCLASSEXTEND support for allowing one recipe to provide multiple targets (from Poky)
Changes in BitBake 1.8.10:
- Psyco is available only for x86 - do not use it on other architectures.
- Fix a bug in bb.decodeurl where http://some.where.com/somefile.tgz decoded to host="" (#1530)
- Warn about malformed PREFERRED_PROVIDERS (#1072)
- Add support for BB_NICE_LEVEL option (#1627)
- Sort initial providers list by default preference (#1145, #2024)
- Improve provider sorting so prefered versions have preference over latest versions (#768)
- Detect builds of tasks with overlapping providers and warn (will become a fatal error) (#1359)
- Add MULTI_PROVIDER_WHITELIST variable to allow known safe multiple providers to be listed
- Handle paths in svn fetcher module parameter
- Support the syntax "export VARIABLE"
- Add bzr fetcher
- Add support for cleaning directories before a task in the form:
do_taskname[cleandirs] = "dir"
- bzr fetcher tweaks from Robert Schuster (#2913)
- Add mercurial (hg) fetcher from Robert Schuster (#2913)
- Fix bogus preferred_version return values
- Fix 'depends' flag splitting
- Fix unexport handling (#3135)
- Add bb.copyfile function similar to bb.movefile (and improve movefile error reporting)
- Allow multiple options for deptask flag
- Use git-fetch instead of git-pull removing any need for merges when
fetching (we don't care about the index). Fixes fetch errors.
- Add BB_GENERATE_MIRROR_TARBALLS option, set to 0 to make git fetches
faster at the expense of not creating mirror tarballs.
- SRCREV handling updates, improvements and fixes from Poky
- Add bb.utils.lockfile() and bb.utils.unlockfile() from Poky
- Add support for task selfstamp and lockfiles flags
- Disable task number acceleration since it can allow the tasks to run
out of sequence
- Improve runqueue code comments
- Add task scheduler abstraction and some example schedulers
- Improve circular dependency chain debugging code and user feedback
- Don't give a stacktrace for invalid tasks, have a user friendly message (#3431)
- Add support for "-e target" (#3432)
- Fix shell showdata command (#3259)
- Fix shell data updating problems (#1880)
- Properly raise errors for invalid source URI protocols
- Change the wget fetcher failure handling to avoid lockfile problems
- Add git branch support
- Add support for branches in git fetcher (Otavio Salvador, Michael Lauer)
- Make taskdata and runqueue errors more user friendly
- Add norecurse and fullpath options to cvs fetcher
Changes in Bitbake 1.8.8:
- Rewrite svn fetcher to make adding extra operations easier
as part of future SRCDATE="now" fixes
(requires new FETCHCMD_svn definition in bitbake.conf)
- Change SVNDIR layout to be more unique (fixes #2644 and #2624)
- Import persistent data store from trunk
- Sync fetcher code with that in trunk, adding SRCREV support for svn
- Add ConfigParsed Event after configuration parsing is complete
- data.emit_var() - only call getVar if we need the variable
- Stop generating the A variable (seems to be legacy code)
- Make sure intertask depends get processed correcting in recursive depends
- Add pn-PN to overrides when evaluating PREFERRED_VERSION
- Improve the progress indicator by skipping tasks that have
already run before starting the build rather than during it
- Add profiling option (-P)
- Add BB_SRCREV_POLICY variable (clear or cache) to control SRCREV cache
- Add SRCREV_FORMAT support
- Fix local fetcher's localpath return values
- Apply OVERRIDES before performing immediate expansions
- Allow the -b -e option combination to take regular expressions
- Add plain message function to bb.msg
- Sort the list of providers before processing so dependency problems are
reproducible rather than effectively random
- Add locking for fetchers so only one tries to fetch a given file at a given time
- Fix int(0)/None confusion in runqueue.py which causes random gaps in dependency chains
- Fix handling of variables with expansion in the name using _append/_prepend
e.g. RRECOMMENDS_${PN}_append_xyz = "abc"
- Expand data in addtasks
- Print the list of missing DEPENDS,RDEPENDS for the "No buildable providers available for required...."
error message.
- Rework add_task to be more efficient (6% speedup, 7% number of function calls reduction)
- Sort digraph output to make builds more reproducible
- Split expandKeys into two for loops to benefit from the expand_cache (12% speedup)
- runqueue.py: Fix idepends handling to avoid dependency errors
- Clear the terminal TOSTOP flag if set (and warn the user)
- Fix regression from r653 and make SRCDATE/CVSDATE work for packages again
Changes in Bitbake 1.8.6:
- Correctly redirect stdin when forking
- If parsing errors are found, exit, too many users miss the errors
- Remove supriours PREFERRED_PROVIDER warnings
Changes in Bitbake 1.8.4:
- Make sure __inherit_cache is updated before calling include() (from Michael Krelin)
- Fix bug when target was in ASSUME_PROVIDED (#2236)
- Raise ParseError for filenames with multiple underscores instead of infinitely looping (#2062)
- Fix invalid regexp in BBMASK error handling (missing import) (#1124)
- Don't run build sanity checks on incomplete builds
- Promote certain warnings from debug to note 2 level
- Update manual
Changes in Bitbake 1.8.2:
- Catch truncated cache file errors
- Add PE (Package Epoch) support from Philipp Zabel (pH5)
- Add code to handle inter-task dependencies
- Allow operations other than assignment on flag variables
- Fix cache errors when generation dotGraphs
Changes in Bitbake 1.8.0:
- Release 1.7.x as a stable series

52
bitbake/MANIFEST Normal file
View File

@@ -0,0 +1,52 @@
AUTHORS
COPYING
ChangeLog
MANIFEST
setup.py
bin/bitdoc
bin/bbimage
bin/bitbake
lib/bb/__init__.py
lib/bb/build.py
lib/bb/cache.py
lib/bb/cooker.py
lib/bb/COW.py
lib/bb/data.py
lib/bb/data_smart.py
lib/bb/event.py
lib/bb/fetch/__init__.py
lib/bb/fetch/bzr.py
lib/bb/fetch/cvs.py
lib/bb/fetch/git.py
lib/bb/fetch/hg.py
lib/bb/fetch/local.py
lib/bb/fetch/perforce.py
lib/bb/fetch/ssh.py
lib/bb/fetch/svk.py
lib/bb/fetch/svn.py
lib/bb/fetch/wget.py
lib/bb/manifest.py
lib/bb/methodpool.py
lib/bb/msg.py
lib/bb/parse/__init__.py
lib/bb/parse/parse_py/__init__.py
lib/bb/parse/parse_py/BBHandler.py
lib/bb/parse/parse_py/ConfHandler.py
lib/bb/persist_data.py
lib/bb/providers.py
lib/bb/runqueue.py
lib/bb/shell.py
lib/bb/taskdata.py
lib/bb/utils.py
setup.py
doc/COPYING.GPL
doc/COPYING.MIT
doc/bitbake.1
doc/manual/html.css
doc/manual/Makefile
doc/manual/usermanual.xml
contrib/bbdev.sh
contrib/vim/syntax/bitbake.vim
contrib/vim/ftdetect/bitbake.vim
conf/bitbake.conf
classes/base.bbclass

View File

@@ -22,20 +22,12 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys, os, getopt, re, time, optparse, xmlrpclib
import sys, os, getopt, re, time, optparse
sys.path.insert(0,os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb
from bb import cooker
from bb import ui
from bb import server
from bb.server import none
#from bb.server import xmlrpc
__version__ = "1.9.0"
if sys.hexversion < 0x020500F0:
print "Sorry, python 2.5 or later is required for this version of bitbake"
sys.exit(1)
__version__ = "1.8.11"
#============================================================================#
# BBOptions
@@ -49,28 +41,11 @@ class BBConfiguration( object ):
setattr( self, key, val )
def print_exception(exc, value, tb):
"""
Print the exception to stderr, only showing the traceback if bitbake
debugging is enabled.
"""
if not bb.msg.debug_level['default']:
tb = None
sys.__excepthook__(exc, value, tb)
#============================================================================#
# main
#============================================================================#
def main():
return_value = 0
pythonver = sys.version_info
if pythonver[0] < 2 or (pythonver[0] == 2 and pythonver[1] < 5):
print "Sorry, bitbake needs python 2.5 or later."
sys.exit(1)
parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
usage = """%prog [options] [package ...]
@@ -85,9 +60,6 @@ Default BBFILES are the .bb files in the current directory.""" )
parser.add_option( "-k", "--continue", help = "continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same.",
action = "store_false", dest = "abort", default = True )
parser.add_option( "-a", "--tryaltconfigs", help = "continue with builds by trying to use alternative providers where possible.",
action = "store_true", dest = "tryaltconfigs", default = False )
parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
action = "store_true", dest = "force", default = False )
@@ -124,8 +96,8 @@ Default BBFILES are the .bb files in the current directory.""" )
parser.add_option( "-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax",
action = "store_true", dest = "dot_graph", default = False )
parser.add_option( "-I", "--ignore-deps", help = """Assume these dependencies don't exist and are already provided (equivalent to ASSUME_PROVIDED). Useful to make dependency graphs more appealing""",
action = "append", dest = "extra_assume_provided", default = [] )
parser.add_option( "-I", "--ignore-deps", help = """Stop processing at the given list of dependencies when generating dependency graphs. This can help to make the graph more appealing""",
action = "append", dest = "ignored_dot_deps", default = [] )
parser.add_option( "-l", "--log-domains", help = """Show debug logging for the specified logging domains""",
action = "append", dest = "debug_domains", default = [] )
@@ -133,65 +105,30 @@ Default BBFILES are the .bb files in the current directory.""" )
parser.add_option( "-P", "--profile", help = "profile the command and print a report",
action = "store_true", dest = "profile", default = False )
parser.add_option( "-u", "--ui", help = "userinterface to use",
action = "store", dest = "ui")
parser.add_option( "", "--revisions-changed", help = "Set the exit code depending on whether upstream floating revisions have changed or not",
action = "store_true", dest = "revisions_changed", default = False )
options, args = parser.parse_args(sys.argv)
configuration = BBConfiguration(options)
configuration.pkgs_to_build = []
configuration.pkgs_to_build.extend(args[1:])
#server = bb.server.xmlrpc
server = bb.server.none
cooker = bb.cooker.BBCooker(configuration)
# Save a logfile for cooker into the current working directory. When the
# server is daemonized this logfile will be truncated.
cooker_logfile = os.path.join (os.getcwd(), "cooker.log")
if configuration.profile:
try:
import cProfile as profile
except:
import profile
cooker = bb.cooker.BBCooker(configuration, server)
# Clear away any spurious environment variables. But don't wipe the
# environment totally. This is necessary to ensure the correct operation
# of the UIs (e.g. for DISPLAY, etc.)
bb.utils.clean_environment()
cooker.parseCommandLine()
serverinfo = server.BitbakeServerInfo(cooker.server)
server.BitBakeServerFork(serverinfo, cooker.serve, cooker_logfile)
del cooker
sys.excepthook = print_exception
# Setup a connection to the server (cooker)
serverConnection = server.BitBakeServerConnection(serverinfo)
# Launch the UI
if configuration.ui:
ui = configuration.ui
profile.runctx("cooker.cook()", globals(), locals(), "profile.log")
import pstats
p = pstats.Stats('profile.log')
p.sort_stats('time')
p.print_stats()
p.print_callers()
p.sort_stats('cumulative')
p.print_stats()
else:
ui = "knotty"
try:
# Dynamically load the UI based on the ui name. Although we
# suggest a fixed set this allows you to have flexibility in which
# ones are available.
exec "from bb.ui import " + ui
exec "return_value = " + ui + ".init(serverConnection.connection, serverConnection.events)"
except ImportError:
print "FATAL: Invalid user interface '%s' specified. " % ui
print "Valid interfaces are 'ncurses', 'depexp' or the default, 'knotty'."
except Exception, e:
print "FATAL: Unable to start to '%s' UI due to exception: %s." % (configuration.ui, e)
finally:
serverConnection.terminate()
return return_value
cooker.cook()
if __name__ == "__main__":
ret = main()
sys.exit(ret)
main()

View File

@@ -453,8 +453,6 @@ def main():
except bb.parse.ParseError:
bb.fatal( "Unable to parse %s" % config_file )
if isinstance(documentation, dict):
documentation = documentation[""]
# Assuming we've the file loaded now, we will initialize the 'tree'
doc = Documentation()

View File

@@ -16,17 +16,12 @@ endif
syn case match
" Catch incorrect syntax (only matches if nothing else does)
"
syn match bbUnmatched "."
syn include @python syntax/python.vim
if exists("b:current_syntax")
unlet b:current_syntax
endif
" Other
syn match bbComment "^#.*$" display contains=bbTodo
@@ -39,25 +34,21 @@ syn match bbArrayBrackets "[\[\]]" contained
" BitBake strings
syn match bbContinue "\\$"
syn region bbString matchgroup=bbQuote start=/"/ skip=/\\$/ excludenl end=/"/ contained keepend contains=bbTodo,bbContinue,bbVarInlinePy,bbVarDeref
syn region bbString matchgroup=bbQuote start=/'/ skip=/\\$/ excludenl end=/'/ contained keepend contains=bbTodo,bbContinue,bbVarInlinePy,bbVarDeref
syn region bbString matchgroup=bbQuote start=/"/ skip=/\\$/ excludenl end=/"/ contained keepend contains=bbTodo,bbContinue,bbVarDeref
syn region bbString matchgroup=bbQuote start=/'/ skip=/\\$/ excludenl end=/'/ contained keepend contains=bbTodo,bbContinue,bbVarDeref
" BitBake variable metadata
syn match bbVarBraces "[\${}]"
syn region bbVarDeref matchgroup=bbVarBraces start="${" end="}" contained
" syn region bbVarDeref start="${" end="}" contained
" syn region bbVarInlinePy start="${@" end="}" contained contains=@python
syn region bbVarInlinePy matchgroup=bbVarBraces start="${@" end="}" contained contains=@python
syn keyword bbExportFlag export contained nextgroup=bbIdentifier skipwhite
" syn match bbVarDeref "${[a-zA-Z0-9\-_\.]\+}" contained
syn match bbVarDef "^\(export\s*\)\?\([a-zA-Z0-9\-_\.]\+\(_[${}a-zA/-Z0-9\-_\.]\+\)\?\)\s*\(:=\|+=\|=+\|\.=\|=\.\|?=\|=\)\@=" contains=bbExportFlag,bbIdentifier,bbVarDeref nextgroup=bbVarEq
syn match bbVarDeref "${[a-zA-Z0-9\-_\.]\+}" contained
syn match bbVarDef "^\(export\s*\)\?\([a-zA-Z0-9\-_\.]\+\(_[${}a-zA-Z0-9\-_\.]\+\)\?\)\s*\(:=\|+=\|=+\|\.=\|=\.\|?=\|=\)\@=" contains=bbExportFlag,bbIdentifier,bbVarDeref nextgroup=bbVarEq
syn match bbIdentifier "[a-zA-Z0-9\-_\./]\+" display contained
syn match bbIdentifier "[a-zA-Z0-9\-_\.]\+" display contained
"syn keyword bbVarEq = display contained nextgroup=bbVarValue
syn match bbVarEq "\(:=\|+=\|=+\|\.=\|=\.\|?=\|=\)" contained nextgroup=bbVarValue
syn match bbVarValue ".*$" contained contains=bbString
syn match bbVarValue ".*$" contained contains=bbString,bbVarDeref
" BitBake variable metadata flags
syn match bbVarFlagDef "^\([a-zA-Z0-9\-_\.]\+\)\(\[[a-zA-Z0-9\-_\.]\+\]\)\@=" contains=bbIdentifier nextgroup=bbVarFlagFlag
@@ -70,6 +61,10 @@ syn match bbFunction "\h\w*" display contained
" BitBake python metadata
syn include @python syntax/python.vim
if exists("b:current_syntax")
unlet b:current_syntax
endif
syn keyword bbPythonFlag python contained nextgroup=bbFunction
syn match bbPythonFuncDef "^\(python\s\+\)\(\w\+\)\?\(\s*()\s*\)\({\)\@=" contains=bbPythonFlag,bbFunction,bbDelimiter nextgroup=bbPythonFuncRegion skipwhite
@@ -103,6 +98,7 @@ syn match bbStatementRest ".*$" contained contains=bbString,bbVarDeref
"
hi def link bbArrayBrackets Statement
hi def link bbUnmatched Error
hi def link bbVarDeref String
hi def link bbContinue Special
hi def link bbDef Statement
hi def link bbPythonFlag Type
@@ -120,8 +116,5 @@ hi def link bbIdentifier Identifier
hi def link bbVarEq Operator
hi def link bbQuote String
hi def link bbVarValue String
" hi def link bbVarInlinePy PreProc
hi def link bbVarDeref PreProc
hi def link bbVarBraces PreProc
let b:current_syntax = "bb"

View File

@@ -32,7 +32,7 @@ command.
\fBbitbake\fP is a program that executes the specified task (default is 'build')
for a given set of BitBake files.
.br
It expects that BBFILES is defined, which is a space separated list of files to
It expects that BBFILES is defined, which is a space seperated list of files to
be executed. BBFILES does support wildcards.
.br
Default BBFILES are the .bb files in the current directory.
@@ -54,9 +54,6 @@ continue as much as possible after an error. While the target that failed, and
those that depend on it, cannot be remade, the other dependencies of these
targets can be processed all the same.
.TP
.B \-a, \-\-tryaltconfigs
continue with builds by trying to use alternative providers where possible.
.TP
.B \-f, \-\-force
force run of specified cmd, regardless of stamp status
.TP
@@ -67,7 +64,7 @@ drop into the interactive mode also called the BitBake shell.
Specify task to execute. Note that this only executes the specified task for
the providee and the packages it depends on, i.e. 'compile' does not implicitly
call stage for the dependencies (IOW: use only if you know what you are doing).
Depending on the base.bbclass a listtasks task is defined and will show
Depending on the base.bbclass a listtaks tasks is defined and will show
available tasks.
.TP
.B \-rFILE, \-\-read=FILE
@@ -100,13 +97,12 @@ emit the dependency trees of the specified packages in the dot syntax
.B \-IIGNORED\_DOT\_DEPS, \-\-ignore-deps=IGNORED_DOT_DEPS
Stop processing at the given list of dependencies when generating dependency
graphs. This can help to make the graph more appealing
.TP
.B \-lDEBUG_DOMAINS, \-\-log-domains=DEBUG_DOMAINS
Show debug logging for the specified logging domains
.TP
.B \-P, \-\-profile
profile the command and print a report
.TP
.\"
.\" Next option is only in BitBake 1.7.x (trunk)
.\"
.\".TP
.\".B \-lDEBUG_DOMAINS, \-\-log-domains=DEBUG_DOMAINS
.\"Show debug logging for the specified logging domains
.SH AUTHORS
BitBake was written by

View File

@@ -88,17 +88,6 @@ share common metadata between many packages.</para></listitem>
<varname>B</varname> = "pre${A}post"</screen></para>
<para>This results in <varname>A</varname> containing <literal>aval</literal> and <varname>B</varname> containing <literal>preavalpost</literal>.</para>
</section>
<section>
<title>Setting a default value (?=)</title>
<para><screen><varname>A</varname> ?= "aval"</screen></para>
<para>If <varname>A</varname> is set before the above is called, it will retain it's previous value. If <varname>A</varname> is unset prior to the above call, <varname>A</varname> will be set to <literal>aval</literal>. Note that this assignment is immediate, so if there are multiple ?= assignments to a single variable, the first of those will be used.</para>
</section>
<section>
<title>Setting a default value (??=)</title>
<para><screen><varname>A</varname> ??= "somevalue"</screen></para>
<para><screen><varname>A</varname> ??= "someothervalue"</screen></para>
<para>If <varname>A</varname> is set before the above, it will retain that value. If <varname>A</varname> is unset prior to the above, <varname>A</varname> will be set to <literal>someothervalue</literal>. This is a lazy version of ??=, in that the assignment does not occur until the end of the parsing process, so that the last, rather than the first, ??= assignment to a given variable will be used.</para>
</section>
<section>
<title>Immediate variable expansion (:=)</title>
<para>:= results in a variable's contents being expanded immediately, rather than when the variable is actually used.</para>
@@ -130,7 +119,7 @@ will be introduced.</para>
</section>
<section>
<title>Conditional metadata set</title>
<para>OVERRIDES is a <quote>:</quote> separated variable containing each item you want to satisfy conditions. So, if you have a variable which is conditional on <quote>arm</quote>, and <quote>arm</quote> is in OVERRIDES, then the <quote>arm</quote> specific version of the variable is used rather than the non-conditional version. Example:</para>
<para>OVERRIDES is a <quote>:</quote> seperated variable containing each item you want to satisfy conditions. So, if you have a variable which is conditional on <quote>arm</quote>, and <quote>arm</quote> is in OVERRIDES, then the <quote>arm</quote> specific version of the variable is used rather than the non-conditional version. Example:</para>
<para><screen><varname>OVERRIDES</varname> = "architecture:os:machine"
<varname>TEST</varname> = "defaultvalue"
<varname>TEST_os</varname> = "osspecificvalue"
@@ -195,7 +184,7 @@ include</literal> directive.</para>
<section>
<title>Inheritance</title>
<para><emphasis>NOTE:</emphasis> This is only supported in .bb and .bbclass files.</para>
<para>The <literal>inherit</literal> directive is a means of specifying what classes of functionality your .bb requires. It is a rudimentary form of inheritance. For example, you can easily abstract out the tasks involved in building a package that uses autoconf and automake, and put that into a bbclass for your packages to make use of. A given bbclass is located by searching for classes/filename.oeclass in <envar>BBPATH</envar>, where filename is what you inherited.</para>
<para>The <literal>inherit</literal> directive is a means of specifying what classes of functionality your .bb requires. It is a rudamentary form of inheritence. For example, you can easily abstract out the tasks involved in building a package that uses autoconf and automake, and put that into a bbclass for your packages to make use of. A given bbclass is located by searching for classes/filename.oeclass in <envar>BBPATH</envar>, where filename is what you inherited.</para>
</section>
<section>
<title>Tasks</title>
@@ -228,18 +217,6 @@ This event handler gets called every time an event is triggered. A global variab
method one can get the name of the triggered event.</para><para>The above event handler prints the name
of the event and the content of the <varname>FILE</varname> variable.</para>
</section>
<section>
<title>Variants</title>
<para>Two Bitbake features exist to facilitate the creation of multiple buildable incarnations from a single recipe file.</para>
<para>The first is <varname>BBCLASSEXTEND</varname>. This variable is a space separated list of classes to utilize to "extend" the recipe for each variant. As an example, setting <screen>BBCLASSEXTEND = "native"</screen> results in a second incarnation of the current recipe being available. This second incarantion will have the "native" class inherited.</para>
<para>The second feature is <varname>BBVERSIONS</varname>. This variable allows a single recipe to be able to build multiple versions of a project from a single recipe file, and allows you to specify conditional metadata (using the <varname>OVERRIDES</varname> mechanism) for a single version, or an optionally named range of versions:</para>
<para><screen>BBVERSIONS = "1.0 2.0 git"
SRC_URI_git = "git://someurl/somepath.git"</screen></para>
<para><screen>BBVERSIONS = "1.0.[0-6]:1.0.0+ \
1.0.[7-9]:1.0.7+"
SRC_URI_append_1.0.7+ = "file://some_patch_which_the_new_versions_need.patch;patch=1"</screen></para>
<para>Note that the name of the range will default to the original version of the recipe, so given OE, a recipe file of foo_1.0.0+.bb will default the name of its versions to 1.0.0+. This is useful, as the range name is not only placed into overrides, it's also made available for the metadata to use in the form of the <varname>BPV</varname> variable, for use in file:// search paths (<varname>FILESPATH</varname>).</para>
</section>
</section>
<section>
<title>Dependency Handling</title>
@@ -281,18 +258,16 @@ SRC_URI_append_1.0.7+ = "file://some_patch_which_the_new_versions_need.patch;pat
<title>Parsing</title>
<section>
<title>Configuration Files</title>
<para>The first of the classifications of metadata in BitBake is configuration metadata. This metadata is global, and therefore affects <emphasis>all</emphasis> packages and tasks which are executed.</para>
<para>Bitbake will first search the current working directory for an optional "conf/bblayers.conf" configuration file. This file is expected to contain a BBLAYERS variable which is a space delimited list of 'layer' directories. For each directory in this list a "conf/layer.conf" file will be searched for and parsed with the LAYERDIR variable being set to the directory where the layer was found. The idea is these files will setup BBPATH and other variables correctly for a given build directory automatically for the user.</para>
<para>Bitbake will then expect to find 'conf/bitbake.conf' somewhere in the user specified <envar>BBPATH</envar>. That configuration file generally has include directives to pull in any other metadata (generally files specific to architecture, machine, <emphasis>local</emphasis> and so on.</para>
<para>The first of the classifications of metadata in BitBake is configuration metadata. This metadata is global, and therefore affects <emphasis>all</emphasis> packages and tasks which are executed. Currently, BitBake has hardcoded knowledge of a single configuration file. It expects to find 'conf/bitbake.conf' somewhere in the user specified <envar>BBPATH</envar>. That configuration file generally has include directives to pull in any other metadata (generally files specific to architecture, machine, <emphasis>local</emphasis> and so on.</para>
<para>Only variable definitions and include directives are allowed in .conf files.</para>
</section>
<section>
<title>Classes</title>
<para>BitBake classes are our rudimentary inheritance mechanism. As briefly mentioned in the metadata introduction, they're parsed when an <literal>inherit</literal> directive is encountered, and they are located in classes/ relative to the dirs in <envar>BBPATH</envar>.</para>
<para>BitBake classes are our rudamentary inheritence mechanism. As briefly mentioned in the metadata introduction, they're parsed when an <literal>inherit</literal> directive is encountered, and they are located in classes/ relative to the dirs in <envar>BBPATH</envar>.</para>
</section>
<section>
<title>.bb Files</title>
<para>A BitBake (.bb) file is a logical unit of tasks to be executed. Normally this is a package to be built. Inter-.bb dependencies are obeyed. The files themselves are located via the <varname>BBFILES</varname> variable, which is set to a space separated list of .bb files, and does handle wildcards.</para>
<para>A BitBake (.bb) file is a logical unit of tasks to be executed. Normally this is a package to be built. Inter-.bb dependencies are obeyed. The files themselves are located via the <varname>BBFILES</varname> variable, which is set to a space seperated list of .bb files, and does handle wildcards.</para>
</section>
</section>
</chapter>
@@ -377,7 +352,15 @@ will be tried first when fetching a file if that fails the actual file will be t
<chapter>
<title>The bitbake command</title>
<title>Commands</title>
<section>
<title>bbread</title>
<para>bbread is a command for displaying BitBake metadata. When run with no arguments, it has the core parse 'conf/bitbake.conf', as located in BBPATH, and displays that. If you supply a file on the commandline, such as a .bb, then it parses that afterwards, using the aforementioned configuration metadata.</para>
<para><emphasis>NOTE: the stand a lone bbread command was removed. Instead of bbread use bitbake -e.
</emphasis></para>
</section>
<section>
<title>bitbake</title>
<section>
<title>Introduction</title>
<para>bitbake is the primary command in the system. It facilitates executing tasks in a single .bb file, or executing a given task on a set of multiple .bb files, accounting for interdependencies amongst them.</para>
@@ -389,7 +372,7 @@ will be tried first when fetching a file if that fails the actual file will be t
usage: bitbake [options] [package ...]
Executes the specified task (default is 'build') for a given set of BitBake files.
It expects that BBFILES is defined, which is a space separated list of files to
It expects that BBFILES is defined, which is a space seperated list of files to
be executed. BBFILES does support wildcards.
Default BBFILES are the .bb files in the current directory.
@@ -411,7 +394,7 @@ options:
it depends on, i.e. 'compile' does not implicitly call
stage for the dependencies (IOW: use only if you know
what you are doing). Depending on the base.bbclass a
listtasks task is defined and will show available
listtasks tasks is defined and will show available
tasks
-r FILE, --read=FILE read the specified file before bitbake.conf
-v, --verbose output more chit-chat to the terminal
@@ -432,8 +415,6 @@ options:
the graph more appealing
-l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
Show debug logging for the specified logging domains
-P, --profile profile the command and print a report
</screen>
</para>
@@ -480,12 +461,12 @@ Two files will be written into the current working directory, <emphasis>depends.
</section>
<section>
<title>Metadata</title>
<para>As you may have seen in the usage information, or in the information about .bb files, the BBFILES variable is how the bitbake tool locates its files. This variable is a space separated list of files that are available, and supports wildcards.
<para>As you may have seen in the usage information, or in the information about .bb files, the BBFILES variable is how the bitbake tool locates its files. This variable is a space seperated list of files that are available, and supports wildcards.
<example>
<title>Setting BBFILES</title>
<programlisting><varname>BBFILES</varname> = "/path/to/bbfiles/*.bb"</programlisting>
</example></para>
<para>With regard to dependencies, it expects the .bb to define a <varname>DEPENDS</varname> variable, which contains a space separated list of <quote>package names</quote>, which themselves are the <varname>PN</varname> variable. The <varname>PN</varname> variable is, in general, by default, set to a component of the .bb filename.</para>
<para>With regard to dependencies, it expects the .bb to define a <varname>DEPENDS</varname> variable, which contains a space seperated list of <quote>package names</quote>, which themselves are the <varname>PN</varname> variable. The <varname>PN</varname> variable is, in general, by default, set to a component of the .bb filename.</para>
<example>
<title>Depending on another .bb</title>
<para>a.bb:
@@ -532,5 +513,6 @@ BBFILE_PRIORITY_upstream = "5"
BBFILE_PRIORITY_local = "10"</screen>
</example>
</section>
</section>
</chapter>
</book>

View File

@@ -23,8 +23,10 @@
# Assign a file to __warn__ to get warnings about slow operations.
#
from inspect import getmro
import copy
import types
import types, sets
types.ImmutableTypes = tuple([ \
types.BooleanType, \
types.ComplexType, \
@@ -33,7 +35,7 @@ types.ImmutableTypes = tuple([ \
types.LongType, \
types.NoneType, \
types.TupleType, \
frozenset] + \
sets.ImmutableSet] + \
list(types.StringTypes))
MUTABLE = "__mutable__"

File diff suppressed because it is too large Load Diff

View File

@@ -25,23 +25,12 @@
#
#Based on functions from the base bb module, Copyright 2003 Holger Schurig
from bb import data, event, mkdirhier, utils
import bb, os, sys
# When we execute a python function we'd like certain things
# in all namespaces, hence we add them to __builtins__
# If we do not do this and use the exec globals, they will
# not be available to subfunctions.
__builtins__['bb'] = bb
__builtins__['os'] = os
from bb import data, fetch, event, mkdirhier, utils
import bb, os
# events
class FuncFailed(Exception):
"""
Executed function failed
First parameter a message
Second paramter is a logfile (optional)
"""
"""Executed function failed"""
class EventException(Exception):
"""Exception which is associated with an Event."""
@@ -54,9 +43,7 @@ class TaskBase(event.Event):
def __init__(self, t, d ):
self._task = t
self._package = bb.data.getVar("PF", d, 1)
event.Event.__init__(self)
self._message = "package %s: task %s: %s" % (bb.data.getVar("PF", d, 1), t, bb.event.getName(self)[4:])
event.Event.__init__(self, d)
def getTask(self):
return self._task
@@ -74,10 +61,6 @@ class TaskSucceeded(TaskBase):
class TaskFailed(TaskBase):
"""Task execution failed"""
def __init__(self, msg, logfile, t, d ):
self.logfile = logfile
self.msg = msg
TaskBase.__init__(self, t, d)
class InvalidTask(TaskBase):
"""Invalid Task"""
@@ -114,114 +97,47 @@ def exec_func(func, d, dirs = None):
else:
adir = data.getVar('B', d, 1)
# Save current directory
try:
prevdir = os.getcwd()
except OSError:
prevdir = data.getVar('TOPDIR', d, True)
# Setup logfiles
t = data.getVar('T', d, 1)
if not t:
bb.msg.fatal(bb.msg.domain.Build, "T not set")
mkdirhier(t)
logfile = "%s/log.%s.%s" % (t, func, str(os.getpid()))
runfile = "%s/run.%s.%s" % (t, func, str(os.getpid()))
# Change to correct directory (if specified)
if adir and os.access(adir, os.F_OK):
os.chdir(adir)
# Handle logfiles
si = file('/dev/null', 'r')
try:
if bb.msg.debug_level['default'] > 0 or ispython:
so = os.popen("tee \"%s\"" % logfile, "w")
else:
so = file(logfile, 'w')
except OSError, e:
bb.msg.error(bb.msg.domain.Build, "opening log file: %s" % e)
pass
se = so
# Dup the existing fds so we dont lose them
osi = [os.dup(sys.stdin.fileno()), sys.stdin.fileno()]
oso = [os.dup(sys.stdout.fileno()), sys.stdout.fileno()]
ose = [os.dup(sys.stderr.fileno()), sys.stderr.fileno()]
# Replace those fds with our own
os.dup2(si.fileno(), osi[1])
os.dup2(so.fileno(), oso[1])
os.dup2(se.fileno(), ose[1])
locks = []
lockfiles = (data.expand(flags['lockfiles'], d) or "").split()
for lock in lockfiles:
locks.append(bb.utils.lockfile(lock))
try:
# Run the function
if ispython:
exec_func_python(func, d, runfile, logfile)
else:
exec_func_shell(func, d, runfile, logfile, flags)
if flags['python']:
exec_func_python(func, d)
else:
exec_func_shell(func, d, flags)
# Restore original directory
try:
os.chdir(prevdir)
except:
pass
for lock in locks:
bb.utils.unlockfile(lock)
finally:
if os.path.exists(prevdir):
os.chdir(prevdir)
# Unlock any lockfiles
for lock in locks:
bb.utils.unlockfile(lock)
# Restore the backup fds
os.dup2(osi[0], osi[1])
os.dup2(oso[0], oso[1])
os.dup2(ose[0], ose[1])
# Close our logs
si.close()
so.close()
se.close()
if os.path.exists(logfile) and os.path.getsize(logfile) == 0:
bb.msg.debug(2, bb.msg.domain.Build, "Zero size logfile %s, removing" % logfile)
os.remove(logfile)
# Close the backup fds
os.close(osi[0])
os.close(oso[0])
os.close(ose[0])
def exec_func_python(func, d, runfile, logfile):
def exec_func_python(func, d):
"""Execute a python BB 'function'"""
import re, os
bbfile = bb.data.getVar('FILE', d, 1)
tmp = "def " + func + "():\n%s" % data.getVar(func, d)
tmp += '\n' + func + '()'
f = open(runfile, "w")
f.write(tmp)
comp = utils.better_compile(tmp, func, bbfile)
prevdir = os.getcwd()
g = {} # globals
g['bb'] = bb
g['os'] = os
g['d'] = d
try:
utils.better_exec(comp, g, tmp, bbfile)
except:
(t,value,tb) = sys.exc_info()
utils.better_exec(comp, g, tmp, bbfile)
if os.path.exists(prevdir):
os.chdir(prevdir)
if t in [bb.parse.SkipPackage, bb.build.FuncFailed]:
raise
bb.msg.error(bb.msg.domain.Build, "Function %s failed" % func)
raise FuncFailed("function %s failed" % func, logfile)
def exec_func_shell(func, d, runfile, logfile, flags):
def exec_func_shell(func, d, flags):
"""Execute a shell BB 'function' Returns true if execution was successful.
For this, it creates a bash shell script in the tmp dectory, writes the local
@@ -231,13 +147,23 @@ def exec_func_shell(func, d, runfile, logfile, flags):
of the directories you need created prior to execution. The last
item in the list is where we will chdir/cd to.
"""
import sys
deps = flags['deps']
check = flags['check']
interact = flags['interactive']
if check in globals():
if globals()[check](func, deps):
return
global logfile
t = data.getVar('T', d, 1)
if not t:
return 0
mkdirhier(t)
logfile = "%s/log.%s.%s" % (t, func, str(os.getpid()))
runfile = "%s/run.%s.%s" % (t, func, str(os.getpid()))
f = open(runfile, "w")
f.write("#!/bin/sh -e\n")
if bb.msg.debug_level['default'] > 0: f.write("set -x\n")
@@ -249,21 +175,85 @@ def exec_func_shell(func, d, runfile, logfile, flags):
os.chmod(runfile, 0775)
if not func:
bb.msg.error(bb.msg.domain.Build, "Function not specified")
raise FuncFailed("Function not specified for exec_func_shell")
raise FuncFailed()
# open logs
si = file('/dev/null', 'r')
try:
if bb.msg.debug_level['default'] > 0:
so = os.popen("tee \"%s\"" % logfile, "w")
else:
so = file(logfile, 'w')
except OSError, e:
bb.msg.error(bb.msg.domain.Build, "opening log file: %s" % e)
pass
se = so
if not interact:
# dup the existing fds so we dont lose them
osi = [os.dup(sys.stdin.fileno()), sys.stdin.fileno()]
oso = [os.dup(sys.stdout.fileno()), sys.stdout.fileno()]
ose = [os.dup(sys.stderr.fileno()), sys.stderr.fileno()]
# replace those fds with our own
os.dup2(si.fileno(), osi[1])
os.dup2(so.fileno(), oso[1])
os.dup2(se.fileno(), ose[1])
# execute function
prevdir = os.getcwd()
if flags['fakeroot']:
maybe_fakeroot = "PATH=\"%s\" fakeroot " % bb.data.getVar("PATH", d, 1)
else:
maybe_fakeroot = ''
lang_environment = "LC_ALL=C "
ret = os.system('%s%ssh -e %s' % (lang_environment, maybe_fakeroot, runfile))
try:
os.chdir(prevdir)
except:
pass
if ret == 0:
if not interact:
# restore the backups
os.dup2(osi[0], osi[1])
os.dup2(oso[0], oso[1])
os.dup2(ose[0], ose[1])
# close our logs
si.close()
so.close()
se.close()
# close the backup fds
os.close(osi[0])
os.close(oso[0])
os.close(ose[0])
if ret==0:
if bb.msg.debug_level['default'] > 0:
os.remove(runfile)
# os.remove(logfile)
return
bb.msg.error(bb.msg.domain.Build, "Function %s failed" % func)
raise FuncFailed("function %s failed" % func, logfile)
else:
bb.msg.error(bb.msg.domain.Build, "function %s failed" % func)
if data.getVar("BBINCLUDELOGS", d):
bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile)
number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
if number_of_lines:
os.system('tail -n%s %s' % (number_of_lines, logfile))
else:
f = open(logfile, "r")
while True:
l = f.readline()
if l == '':
break
l = l.rstrip()
print '| %s' % l
f.close()
else:
bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile)
raise FuncFailed( logfile )
def exec_task(task, d):
@@ -284,20 +274,14 @@ def exec_task(task, d):
data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata)
data.update_data(localdata)
data.expandKeys(localdata)
event.fire(TaskStarted(task, localdata), localdata)
event.fire(TaskStarted(task, localdata))
exec_func(task, localdata)
event.fire(TaskSucceeded(task, localdata), localdata)
except FuncFailed, message:
# Try to extract the optional logfile
try:
(msg, logfile) = message
except:
logfile = None
msg = message
bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % message )
failedevent = TaskFailed(msg, logfile, task, d)
event.fire(failedevent, d)
raise EventException("Function failed in task: %s" % message, failedevent)
event.fire(TaskSucceeded(task, localdata))
except FuncFailed, reason:
bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % reason )
failedevent = TaskFailed(task, d)
event.fire(failedevent)
raise EventException("Function failed in task: %s" % reason, failedevent)
# make stamp, or cause event and raise exception
if not data.getVarFlag(task, 'nostamp', d) and not data.getVarFlag(task, 'selfstamp', d):

View File

@@ -31,6 +31,7 @@
import os, re
import bb.data
import bb.utils
from sets import Set
try:
import cPickle as pickle
@@ -38,7 +39,7 @@ except ImportError:
import pickle
bb.msg.note(1, bb.msg.domain.Cache, "Importing cPickle failed. Falling back to a very slow implementation.")
__cache_version__ = "131"
__cache_version__ = "129"
class Cache:
"""
@@ -58,16 +59,18 @@ class Cache:
if self.cachedir in [None, '']:
self.has_cache = False
bb.msg.note(1, bb.msg.domain.Cache, "Not using a cache. Set CACHE = <directory> to enable.")
return
else:
self.has_cache = True
self.cachefile = os.path.join(self.cachedir,"bb_cache.dat")
bb.msg.debug(1, bb.msg.domain.Cache, "Using cache in '%s'" % self.cachedir)
try:
os.stat( self.cachedir )
except OSError:
bb.mkdirhier( self.cachedir )
self.has_cache = True
self.cachefile = os.path.join(self.cachedir,"bb_cache.dat")
bb.msg.debug(1, bb.msg.domain.Cache, "Using cache in '%s'" % self.cachedir)
try:
os.stat( self.cachedir )
except OSError:
bb.mkdirhier( self.cachedir )
if not self.has_cache:
return
# If any of configuration.data's dependencies are newer than the
# cache there isn't even any point in loading it...
@@ -92,11 +95,7 @@ class Cache:
bb.msg.note(1, bb.msg.domain.Cache, "Invalid cache found, rebuilding...")
self.depends_cache = {}
else:
try:
os.stat( self.cachefile )
bb.msg.note(1, bb.msg.domain.Cache, "Out of date cache found, rebuilding...")
except OSError:
pass
bb.msg.note(1, bb.msg.domain.Cache, "Out of date cache found, rebuilding...")
def getVar(self, var, fn, exp = 0):
"""
@@ -124,67 +123,30 @@ class Cache:
self.depends_cache[fn][var] = result
return result
def setData(self, virtualfn, fn, data):
def setData(self, fn, data):
"""
Called to prime bb_cache ready to learn which variables to cache.
Will be followed by calls to self.getVar which aren't cached
but can be fulfilled from self.data.
"""
self.data_fn = virtualfn
self.data_fn = fn
self.data = data
# Make sure __depends makes the depends_cache
# If we're a virtual class we need to make sure all our depends are appended
# to the depends of fn.
depends = self.getVar("__depends", virtualfn, True) or []
if "__depends" not in self.depends_cache[fn] or not self.depends_cache[fn]["__depends"]:
self.depends_cache[fn]["__depends"] = depends
for dep in depends:
if dep not in self.depends_cache[fn]["__depends"]:
self.depends_cache[fn]["__depends"].append(dep)
self.getVar("__depends", fn, True)
self.depends_cache[fn]["CACHETIMESTAMP"] = bb.parse.cached_mtime(fn)
# Make sure the variants always make it into the cache too
self.getVar('__VARIANTS', virtualfn, True)
self.depends_cache[virtualfn]["CACHETIMESTAMP"] = bb.parse.cached_mtime(fn)
def virtualfn2realfn(self, virtualfn):
"""
Convert a virtual file name to a real one + the associated subclass keyword
"""
fn = virtualfn
cls = ""
if virtualfn.startswith('virtual:'):
cls = virtualfn.split(':', 2)[1]
fn = virtualfn.replace('virtual:' + cls + ':', '')
#bb.msg.debug(2, bb.msg.domain.Cache, "virtualfn2realfn %s to %s %s" % (virtualfn, fn, cls))
return (fn, cls)
def realfn2virtual(self, realfn, cls):
"""
Convert a real filename + the associated subclass keyword to a virtual filename
"""
if cls == "":
#bb.msg.debug(2, bb.msg.domain.Cache, "realfn2virtual %s and '%s' to %s" % (realfn, cls, realfn))
return realfn
#bb.msg.debug(2, bb.msg.domain.Cache, "realfn2virtual %s and %s to %s" % (realfn, cls, "virtual:" + cls + ":" + realfn))
return "virtual:" + cls + ":" + realfn
def loadDataFull(self, virtualfn, cfgData):
def loadDataFull(self, fn, cfgData):
"""
Return a complete set of data for fn.
To do this, we need to parse the file.
"""
(fn, cls) = self.virtualfn2realfn(virtualfn)
bb.msg.debug(1, bb.msg.domain.Cache, "Parsing %s (full)" % fn)
bb_data = self.load_bbfile(fn, cfgData)
return bb_data[cls]
bb_data, skipped = self.load_bbfile(fn, cfgData)
return bb_data
def loadData(self, fn, cfgData, cacheData):
def loadData(self, fn, cfgData):
"""
Load a subset of data for fn.
If the cached data is valid we do nothing,
@@ -192,39 +154,18 @@ class Cache:
to record the variables accessed.
Return the cache status and whether the file was skipped when parsed
"""
skipped = 0
virtuals = 0
if fn not in self.checked:
self.cacheValidUpdate(fn)
if self.cacheValid(fn):
multi = self.getVar('__VARIANTS', fn, True)
for cls in (multi or "").split() + [""]:
virtualfn = self.realfn2virtual(fn, cls)
if self.depends_cache[virtualfn]["__SKIPPED"]:
skipped += 1
bb.msg.debug(1, bb.msg.domain.Cache, "Skipping %s" % virtualfn)
continue
self.handle_data(virtualfn, cacheData)
virtuals += 1
return True, skipped, virtuals
if "SKIPPED" in self.depends_cache[fn]:
return True, True
return True, False
bb.msg.debug(1, bb.msg.domain.Cache, "Parsing %s" % fn)
bb_data = self.load_bbfile(fn, cfgData)
for data in bb_data:
virtualfn = self.realfn2virtual(fn, data)
self.setData(virtualfn, fn, bb_data[data])
if self.getVar("__SKIPPED", virtualfn, True):
skipped += 1
bb.msg.debug(1, bb.msg.domain.Cache, "Skipping %s" % virtualfn)
else:
self.handle_data(virtualfn, cacheData)
virtuals += 1
return False, skipped, virtuals
bb_data, skipped = self.load_bbfile(fn, cfgData)
self.setData(fn, bb_data)
return False, skipped
def cacheValid(self, fn):
"""
@@ -278,7 +219,7 @@ class Cache:
for f,old_mtime in depends:
fmtime = bb.parse.cached_mtime_noerror(f)
# Check if file still exists
if old_mtime != 0 and fmtime == 0:
if fmtime == 0:
self.remove(fn)
return False
@@ -291,14 +232,17 @@ class Cache:
if not fn in self.clean:
self.clean[fn] = ""
# Mark extended class data as clean too
multi = self.getVar('__VARIANTS', fn, True)
for cls in (multi or "").split():
virtualfn = self.realfn2virtual(fn, cls)
self.clean[virtualfn] = ""
return True
def skip(self, fn):
"""
Mark a fn as skipped
Called from the parser
"""
if not fn in self.depends_cache:
self.depends_cache[fn] = {}
self.depends_cache[fn]["SKIPPED"] = "1"
def remove(self, fn):
"""
Remove a fn from the cache
@@ -315,7 +259,6 @@ class Cache:
Save the cache
Called from the parser when complete (or exiting)
"""
import copy
if not self.has_cache:
return
@@ -328,17 +271,8 @@ class Cache:
version_data['CACHE_VER'] = __cache_version__
version_data['BITBAKE_VER'] = bb.__version__
cache_data = copy.copy(self.depends_cache)
for fn in self.depends_cache:
if '__BB_DONT_CACHE' in self.depends_cache[fn] and self.depends_cache[fn]['__BB_DONT_CACHE']:
bb.msg.debug(2, bb.msg.domain.Cache, "Not caching %s, marked as not cacheable" % fn)
del cache_data[fn]
elif 'PV' in self.depends_cache[fn] and 'SRCREVINACTION' in self.depends_cache[fn]['PV']:
bb.msg.error(bb.msg.domain.Cache, "Not caching %s as it had SRCREVINACTION in PV. Please report this bug" % fn)
del cache_data[fn]
p = pickle.Pickler(file(self.cachefile, "wb" ), -1 )
p.dump([cache_data, version_data])
p.dump([self.depends_cache, version_data])
def mtime(self, cachefile):
return bb.parse.cached_mtime_noerror(cachefile)
@@ -351,8 +285,6 @@ class Cache:
pn = self.getVar('PN', file_name, True)
pe = self.getVar('PE', file_name, True) or "0"
pv = self.getVar('PV', file_name, True)
if 'SRCREVINACTION' in pv:
bb.note("Found SRCREVINACTION in PV (%s) or %s. Please report this bug." % (pv, file_name))
pr = self.getVar('PR', file_name, True)
dp = int(self.getVar('DEFAULT_PREFERENCE', file_name, True) or "0")
depends = bb.utils.explode_deps(self.getVar("DEPENDS", file_name, True) or "")
@@ -441,9 +373,6 @@ class Cache:
if not self.getVar('BROKEN', file_name, True) and not self.getVar('EXCLUDE_FROM_WORLD', file_name, True):
cacheData.possible_world.append(file_name)
# Touch this to make sure its in the cache
self.getVar('__BB_DONT_CACHE', file_name, True)
self.getVar('__VARIANTS', file_name, True)
def load_bbfile( self, bbfile , config):
"""
@@ -464,7 +393,10 @@ class Cache:
try:
bb_data = parse.handle(bbfile, bb_data) # read .bb data
os.chdir(oldpath)
return bb_data
return bb_data, False
except bb.parse.SkipPackage:
os.chdir(oldpath)
return bb_data, True
except:
os.chdir(oldpath)
raise
@@ -528,6 +460,6 @@ class CacheData:
(set elsewhere)
"""
self.ignored_dependencies = []
self.world_target = set()
self.world_target = Set()
self.bbfile_priority = {}
self.bbfile_config_priorities = []

View File

@@ -1,273 +0,0 @@
"""
BitBake 'Command' module
Provide an interface to interact with the bitbake server through 'commands'
"""
# Copyright (C) 2006-2007 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
The bitbake server takes 'commands' from its UI/commandline.
Commands are either synchronous or asynchronous.
Async commands return data to the client in the form of events.
Sync commands must only return data through the function return value
and must not trigger events, directly or indirectly.
Commands are queued in a CommandQueue
"""
import bb.event
import bb.cooker
import bb.data
async_cmds = {}
sync_cmds = {}
class Command:
"""
A queue of asynchronous commands for bitbake
"""
def __init__(self, cooker):
self.cooker = cooker
self.cmds_sync = CommandsSync()
self.cmds_async = CommandsAsync()
# FIXME Add lock for this
self.currentAsyncCommand = None
for attr in CommandsSync.__dict__:
command = attr[:].lower()
method = getattr(CommandsSync, attr)
sync_cmds[command] = (method)
for attr in CommandsAsync.__dict__:
command = attr[:].lower()
method = getattr(CommandsAsync, attr)
async_cmds[command] = (method)
def runCommand(self, commandline):
try:
command = commandline.pop(0)
if command in CommandsSync.__dict__:
# Can run synchronous commands straight away
return getattr(CommandsSync, command)(self.cmds_sync, self, commandline)
if self.currentAsyncCommand is not None:
return "Busy (%s in progress)" % self.currentAsyncCommand[0]
if command not in CommandsAsync.__dict__:
return "No such command"
self.currentAsyncCommand = (command, commandline)
self.cooker.server.register_idle_function(self.cooker.runCommands, self.cooker)
return True
except:
import traceback
return traceback.format_exc()
def runAsyncCommand(self):
try:
if self.currentAsyncCommand is not None:
(command, options) = self.currentAsyncCommand
commandmethod = getattr(CommandsAsync, command)
needcache = getattr( commandmethod, "needcache" )
if needcache and self.cooker.cookerState != bb.cooker.cookerParsed:
self.cooker.updateCache()
return True
else:
commandmethod(self.cmds_async, self, options)
return False
else:
return False
except:
import traceback
self.finishAsyncCommand(traceback.format_exc())
return False
def finishAsyncCommand(self, error = None):
if error:
bb.event.fire(CookerCommandFailed(error), self.cooker.configuration.event_data)
else:
bb.event.fire(CookerCommandCompleted(), self.cooker.configuration.event_data)
self.currentAsyncCommand = None
class CommandsSync:
"""
A class of synchronous commands
These should run quickly so as not to hurt interactive performance.
These must not influence any running synchronous command.
"""
def stateShutdown(self, command, params):
"""
Trigger cooker 'shutdown' mode
"""
command.cooker.cookerAction = bb.cooker.cookerShutdown
def stateStop(self, command, params):
"""
Stop the cooker
"""
command.cooker.cookerAction = bb.cooker.cookerStop
def getCmdLineAction(self, command, params):
"""
Get any command parsed from the commandline
"""
return command.cooker.commandlineAction
def getVariable(self, command, params):
"""
Read the value of a variable from configuration.data
"""
varname = params[0]
expand = True
if len(params) > 1:
expand = params[1]
return bb.data.getVar(varname, command.cooker.configuration.data, expand)
def setVariable(self, command, params):
"""
Set the value of variable in configuration.data
"""
varname = params[0]
value = params[1]
bb.data.setVar(varname, value, command.cooker.configuration.data)
class CommandsAsync:
"""
A class of asynchronous commands
These functions communicate via generated events.
Any function that requires metadata parsing should be here.
"""
def buildFile(self, command, params):
"""
Build a single specified .bb file
"""
bfile = params[0]
task = params[1]
command.cooker.buildFile(bfile, task)
buildFile.needcache = False
def buildTargets(self, command, params):
"""
Build a set of targets
"""
pkgs_to_build = params[0]
task = params[1]
command.cooker.buildTargets(pkgs_to_build, task)
buildTargets.needcache = True
def generateDepTreeEvent(self, command, params):
"""
Generate an event containing the dependency information
"""
pkgs_to_build = params[0]
task = params[1]
command.cooker.generateDepTreeEvent(pkgs_to_build, task)
command.finishAsyncCommand()
generateDepTreeEvent.needcache = True
def generateDotGraph(self, command, params):
"""
Dump dependency information to disk as .dot files
"""
pkgs_to_build = params[0]
task = params[1]
command.cooker.generateDotGraphFiles(pkgs_to_build, task)
command.finishAsyncCommand()
generateDotGraph.needcache = True
def showVersions(self, command, params):
"""
Show the currently selected versions
"""
command.cooker.showVersions()
command.finishAsyncCommand()
showVersions.needcache = True
def showEnvironmentTarget(self, command, params):
"""
Print the environment of a target recipe
(needs the cache to work out which recipe to use)
"""
pkg = params[0]
command.cooker.showEnvironment(None, pkg)
command.finishAsyncCommand()
showEnvironmentTarget.needcache = True
def showEnvironment(self, command, params):
"""
Print the standard environment
or if specified the environment for a specified recipe
"""
bfile = params[0]
command.cooker.showEnvironment(bfile)
command.finishAsyncCommand()
showEnvironment.needcache = False
def parseFiles(self, command, params):
"""
Parse the .bb files
"""
command.cooker.updateCache()
command.finishAsyncCommand()
parseFiles.needcache = True
def compareRevisions(self, command, params):
"""
Parse the .bb files
"""
command.cooker.compareRevisions()
command.finishAsyncCommand()
compareRevisions.needcache = True
#
# Events
#
class CookerCommandCompleted(bb.event.Event):
"""
Cooker command completed
"""
def __init__(self):
bb.event.Event.__init__(self)
class CookerCommandFailed(bb.event.Event):
"""
Cooker command completed
"""
def __init__(self, error):
bb.event.Event.__init__(self)
self.error = error
class CookerCommandSetExitCode(bb.event.Event):
"""
Set the exit code for a cooker command
"""
def __init__(self, exitcode):
bb.event.Event.__init__(self)
self.exitcode = int(exitcode)

File diff suppressed because it is too large Load Diff

View File

@@ -1,191 +0,0 @@
"""
Python Deamonizing helper
Configurable daemon behaviors:
1.) The current working directory set to the "/" directory.
2.) The current file creation mode mask set to 0.
3.) Close all open files (1024).
4.) Redirect standard I/O streams to "/dev/null".
A failed call to fork() now raises an exception.
References:
1) Advanced Programming in the Unix Environment: W. Richard Stevens
2) Unix Programming Frequently Asked Questions:
http://www.erlenstar.demon.co.uk/unix/faq_toc.html
Modified to allow a function to be daemonized and return for
bitbake use by Richard Purdie
"""
__author__ = "Chad J. Schroeder"
__copyright__ = "Copyright (C) 2005 Chad J. Schroeder"
__version__ = "0.2"
# Standard Python modules.
import os # Miscellaneous OS interfaces.
import sys # System-specific parameters and functions.
# Default daemon parameters.
# File mode creation mask of the daemon.
# For BitBake's children, we do want to inherit the parent umask.
UMASK = None
# Default maximum for the number of available file descriptors.
MAXFD = 1024
# The standard I/O file descriptors are redirected to /dev/null by default.
if (hasattr(os, "devnull")):
REDIRECT_TO = os.devnull
else:
REDIRECT_TO = "/dev/null"
def createDaemon(function, logfile):
"""
Detach a process from the controlling terminal and run it in the
background as a daemon, returning control to the caller.
"""
try:
# Fork a child process so the parent can exit. This returns control to
# the command-line or shell. It also guarantees that the child will not
# be a process group leader, since the child receives a new process ID
# and inherits the parent's process group ID. This step is required
# to insure that the next call to os.setsid is successful.
pid = os.fork()
except OSError, e:
raise Exception, "%s [%d]" % (e.strerror, e.errno)
if (pid == 0): # The first child.
# To become the session leader of this new session and the process group
# leader of the new process group, we call os.setsid(). The process is
# also guaranteed not to have a controlling terminal.
os.setsid()
# Is ignoring SIGHUP necessary?
#
# It's often suggested that the SIGHUP signal should be ignored before
# the second fork to avoid premature termination of the process. The
# reason is that when the first child terminates, all processes, e.g.
# the second child, in the orphaned group will be sent a SIGHUP.
#
# "However, as part of the session management system, there are exactly
# two cases where SIGHUP is sent on the death of a process:
#
# 1) When the process that dies is the session leader of a session that
# is attached to a terminal device, SIGHUP is sent to all processes
# in the foreground process group of that terminal device.
# 2) When the death of a process causes a process group to become
# orphaned, and one or more processes in the orphaned group are
# stopped, then SIGHUP and SIGCONT are sent to all members of the
# orphaned group." [2]
#
# The first case can be ignored since the child is guaranteed not to have
# a controlling terminal. The second case isn't so easy to dismiss.
# The process group is orphaned when the first child terminates and
# POSIX.1 requires that every STOPPED process in an orphaned process
# group be sent a SIGHUP signal followed by a SIGCONT signal. Since the
# second child is not STOPPED though, we can safely forego ignoring the
# SIGHUP signal. In any case, there are no ill-effects if it is ignored.
#
# import signal # Set handlers for asynchronous events.
# signal.signal(signal.SIGHUP, signal.SIG_IGN)
try:
# Fork a second child and exit immediately to prevent zombies. This
# causes the second child process to be orphaned, making the init
# process responsible for its cleanup. And, since the first child is
# a session leader without a controlling terminal, it's possible for
# it to acquire one by opening a terminal in the future (System V-
# based systems). This second fork guarantees that the child is no
# longer a session leader, preventing the daemon from ever acquiring
# a controlling terminal.
pid = os.fork() # Fork a second child.
except OSError, e:
raise Exception, "%s [%d]" % (e.strerror, e.errno)
if (pid == 0): # The second child.
# We probably don't want the file mode creation mask inherited from
# the parent, so we give the child complete control over permissions.
if UMASK is not None:
os.umask(UMASK)
else:
# Parent (the first child) of the second child.
os._exit(0)
else:
# exit() or _exit()?
# _exit is like exit(), but it doesn't call any functions registered
# with atexit (and on_exit) or any registered signal handlers. It also
# closes any open file descriptors. Using exit() may cause all stdio
# streams to be flushed twice and any temporary files may be unexpectedly
# removed. It's therefore recommended that child branches of a fork()
# and the parent branch(es) of a daemon use _exit().
return
# Close all open file descriptors. This prevents the child from keeping
# open any file descriptors inherited from the parent. There is a variety
# of methods to accomplish this task. Three are listed below.
#
# Try the system configuration variable, SC_OPEN_MAX, to obtain the maximum
# number of open file descriptors to close. If it doesn't exists, use
# the default value (configurable).
#
# try:
# maxfd = os.sysconf("SC_OPEN_MAX")
# except (AttributeError, ValueError):
# maxfd = MAXFD
#
# OR
#
# if (os.sysconf_names.has_key("SC_OPEN_MAX")):
# maxfd = os.sysconf("SC_OPEN_MAX")
# else:
# maxfd = MAXFD
#
# OR
#
# Use the getrlimit method to retrieve the maximum file descriptor number
# that can be opened by this process. If there is not limit on the
# resource, use the default value.
#
import resource # Resource usage information.
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if (maxfd == resource.RLIM_INFINITY):
maxfd = MAXFD
# Iterate through and close all file descriptors.
# for fd in range(0, maxfd):
# try:
# os.close(fd)
# except OSError: # ERROR, fd wasn't open to begin with (ignored)
# pass
# Redirect the standard I/O file descriptors to the specified file. Since
# the daemon has no controlling terminal, most daemons redirect stdin,
# stdout, and stderr to /dev/null. This is done to prevent side-effects
# from reads and writes to the standard I/O file descriptors.
# This call to open is guaranteed to return the lowest file descriptor,
# which will be 0 (stdin), since it was closed above.
# os.open(REDIRECT_TO, os.O_RDWR) # standard input (0)
# Duplicate standard input to standard output and standard error.
# os.dup2(0, 1) # standard output (1)
# os.dup2(0, 2) # standard error (2)
si = file('/dev/null', 'r')
so = file(logfile, 'w')
se = so
# Replace those fds with our own
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
function()
os._exit(0)

View File

@@ -37,7 +37,7 @@ the speed is more critical here.
#
#Based on functions from the base bb module, Copyright 2003 Holger Schurig
import sys, os, re, types
import sys, os, re, time, types
if sys.argv[0][-5:] == "pydoc":
path = os.path.dirname(os.path.dirname(sys.argv[1]))
else:
@@ -47,9 +47,6 @@ sys.path.insert(0,path)
from bb import data_smart
import bb
class VarExpandError(Exception):
pass
_dict_type = data_smart.DataSmart
def init():
@@ -327,14 +324,21 @@ def expandData(alterdata, readdata = None):
if val != expanded:
setVar(key, expanded, alterdata)
import os
def inheritFromOS(d):
"""Inherit variables from the environment."""
# fakeroot needs to be able to set these
non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
for s in os.environ.keys():
try:
setVar(s, os.environ[s], d)
setVarFlag(s, "export", True, d)
except TypeError:
pass
if not s in non_inherit_vars:
try:
setVar(s, os.environ[s], d)
setVarFlag(s, 'matchesenv', '1', d)
except TypeError:
pass
import sys
def emit_var(var, o=sys.__stdout__, d = init(), all=False):
"""Emit a variable to be sourced by a shell."""
@@ -375,6 +379,9 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False):
o.write('unset %s\n' % varExpanded)
return 1
if getVarFlag(var, 'matchesenv', d):
return 0
val.rstrip()
if not val:
return 0
@@ -556,9 +563,7 @@ def inherits_class(klass, d):
def _test():
"""Start a doctest run on this module"""
import doctest
import bb
from bb import data
bb.msg.set_debug_level(0)
doctest.testmod(data)
if __name__ == "__main__":

View File

@@ -32,6 +32,7 @@ import copy, os, re, sys, time, types
import bb
from bb import utils, methodpool
from COW import COWDictBase
from sets import Set
from new import classobj
@@ -39,11 +40,6 @@ __setvar_keyword__ = ["_append","_prepend"]
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?')
__expand_var_regexp__ = re.compile(r"\${[^{}]+}")
__expand_python_regexp__ = re.compile(r"\${@.+?}")
_expand_globals = {
"os": os,
"bb": bb,
"time": time,
}
class DataSmart:
@@ -55,7 +51,6 @@ class DataSmart:
self._seen_overrides = seen
self.expand_cache = {}
self.expand_locals = {"d": self}
def expand(self,s, varname):
def var_sub(match):
@@ -72,7 +67,8 @@ class DataSmart:
def python_sub(match):
import bb
code = match.group()[3:-1]
s = eval(code, _expand_globals, self.expand_locals)
locals()['d'] = self
s = eval(code)
if type(s) == types.IntType: s = str(s)
return s
@@ -146,19 +142,22 @@ class DataSmart:
try:
self._special_values[keyword].add( base )
except:
self._special_values[keyword] = set()
self._special_values[keyword] = Set()
self._special_values[keyword].add( base )
return
if not var in self.dict:
self._makeShadowCopy(var)
if self.getVarFlag(var, 'matchesenv'):
self.delVarFlag(var, 'matchesenv')
self.setVarFlag(var, 'export', 1)
# more cookies for the cookie monster
if '_' in var:
override = var[var.rfind('_')+1:]
if not self._seen_overrides.has_key(override):
self._seen_overrides[override] = set()
self._seen_overrides[override] = Set()
self._seen_overrides[override].add( var )
# setting var
@@ -176,15 +175,14 @@ class DataSmart:
Rename the variable key to newkey
"""
val = self.getVar(key, 0)
if val is not None:
self.setVar(newkey, val)
if val is None:
return
self.setVar(newkey, val)
for i in ('_append', '_prepend'):
src = self.getVarFlag(key, i)
if src is None:
continue
dest = self.getVarFlag(newkey, i) or []
src = self.getVarFlag(key, i) or []
dest.extend(src)
self.setVarFlag(newkey, i, dest)
@@ -224,7 +222,7 @@ class DataSmart:
if not var in self.dict:
self._makeShadowCopy(var)
for i in flags:
for i in flags.keys():
if i == "content":
continue
self.dict[var][i] = flags[i]
@@ -234,7 +232,7 @@ class DataSmart:
flags = {}
if local_var:
for i in local_var:
for i in local_var.keys():
if i == "content":
continue
flags[i] = local_var[i]

View File

@@ -22,20 +22,23 @@ BitBake build tools.
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os, re, sys
import os, re
import bb.utils
import pickle
# This is the pid for which we should generate the event. This is set when
# the runqueue forks off.
worker_pid = 0
worker_pipe = None
class Event:
"""Base class for events"""
type = "Event"
def __init__(self):
self.pid = worker_pid
def __init__(self, d):
self._data = d
def getData(self):
return self._data
def setData(self, data):
self._data = data
data = property(getData, setData, None, "data property")
NotHandled = 0
Handled = 1
@@ -44,95 +47,75 @@ Registered = 10
AlreadyRegistered = 14
# Internal
_handlers = {}
_ui_handlers = {}
_ui_handler_seq = 0
_handlers = []
_handlers_dict = {}
def fire_class_handlers(event, d):
for handler in _handlers:
h = _handlers[handler]
event.data = d
def tmpHandler(event):
"""Default handler for code events"""
return NotHandled
def defaultTmpHandler():
tmp = "def tmpHandler(e):\n\t\"\"\"heh\"\"\"\n\treturn NotHandled"
comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event.defaultTmpHandler")
return comp
def fire(event):
"""Fire off an Event"""
for h in _handlers:
if type(h).__name__ == "code":
exec(h)
tmpHandler(event)
if tmpHandler(event) == Handled:
return Handled
else:
h(event)
del event.data
def fire_ui_handlers(event, d):
errors = []
for h in _ui_handlers:
#print "Sending event %s" % event
try:
# We use pickle here since it better handles object instances
# which xmlrpc's marshaller does not. Events *must* be serializable
# by pickle.
_ui_handlers[h].event.send((pickle.dumps(event)))
except:
errors.append(h)
for h in errors:
del _ui_handlers[h]
def fire(event, d):
"""Fire off an Event"""
# We can fire class handlers in the worker process context and this is
# desired so they get the task based datastore.
# UI handlers need to be fired in the server context so we defer this. They
# don't have a datastore so the datastore context isn't a problem.
fire_class_handlers(event, d)
if worker_pid != 0:
worker_fire(event, d)
else:
fire_ui_handlers(event, d)
def worker_fire(event, d):
data = "<event>" + pickle.dumps(event) + "</event>"
try:
if os.write(worker_pipe, data) != len (data):
print "Error sending event to server (short write)"
except OSError:
sys.exit(1)
def fire_from_worker(event, d):
if not event.startswith("<event>") or not event.endswith("</event>"):
print "Error, not an event"
return
event = pickle.loads(event[7:-8])
fire_ui_handlers(event, d)
if h(event) == Handled:
return Handled
return NotHandled
def register(name, handler):
"""Register an Event handler"""
# already registered
if name in _handlers:
if name in _handlers_dict:
return AlreadyRegistered
if handler is not None:
# handle string containing python code
# handle string containing python code
if type(handler).__name__ == "str":
tmp = "def tmpHandler(e):\n%s" % handler
comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event._registerCode")
_handlers[name] = comp
_registerCode(handler)
else:
_handlers[name] = handler
_handlers.append(handler)
_handlers_dict[name] = 1
return Registered
def _registerCode(handlerStr):
"""Register a 'code' Event.
Deprecated interface; call register instead.
Expects to be passed python code as a string, which will
be passed in turn to compile() and then exec(). Note that
the code will be within a function, so should have had
appropriate tabbing put in place."""
tmp = "def tmpHandler(e):\n%s" % handlerStr
comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event._registerCode")
# prevent duplicate registration
_handlers.append(comp)
def remove(name, handler):
"""Remove an Event handler"""
_handlers.pop(name)
def register_UIHhandler(handler):
bb.event._ui_handler_seq = bb.event._ui_handler_seq + 1
_ui_handlers[_ui_handler_seq] = handler
return _ui_handler_seq
_handlers_dict.pop(name)
if type(handler).__name__ == "str":
return _removeCode(handler)
else:
_handlers.remove(handler)
def unregister_UIHhandler(handlerNum):
if handlerNum in _ui_handlers:
del _ui_handlers[handlerNum]
return
def _removeCode(handlerStr):
"""Remove a 'code' Event handler
Deprecated interface; call remove instead."""
tmp = "def tmpHandler(e):\n%s" % handlerStr
comp = bb.utils.better_compile(tmp, "tmpHandler(e)", "bb.event._removeCode")
_handlers.remove(comp)
def getName(e):
"""Returns the name of a class or class instance"""
@@ -144,20 +127,13 @@ def getName(e):
class ConfigParsed(Event):
"""Configuration Parsing Complete"""
class RecipeParsed(Event):
""" Recipe Parsing Complete """
def __init__(self, fn):
self.fn = fn
Event.__init__(self)
class StampUpdate(Event):
"""Trigger for any adjustment of the stamp files to happen"""
def __init__(self, targets, stampfns):
def __init__(self, targets, stampfns, d):
self._targets = targets
self._stampfns = stampfns
Event.__init__(self)
Event.__init__(self, d)
def getStampPrefix(self):
return self._stampfns
@@ -168,13 +144,29 @@ class StampUpdate(Event):
stampPrefix = property(getStampPrefix)
targets = property(getTargets)
class PkgBase(Event):
"""Base class for package events"""
def __init__(self, t, d):
self._pkg = t
Event.__init__(self, d)
def getPkg(self):
return self._pkg
def setPkg(self, pkg):
self._pkg = pkg
pkg = property(getPkg, setPkg, None, "pkg property")
class BuildBase(Event):
"""Base class for bbmake run events"""
def __init__(self, n, p, failures = 0):
def __init__(self, n, p, c, failures = 0):
self._name = n
self._pkgs = p
Event.__init__(self)
Event.__init__(self, c)
self._failures = failures
def getPkgs(self):
@@ -206,7 +198,32 @@ class BuildBase(Event):
cfg = property(getCfg, setCfg, None, "cfg property")
class DepBase(PkgBase):
"""Base class for dependency events"""
def __init__(self, t, data, d):
self._dep = d
PkgBase.__init__(self, t, data)
def getDep(self):
return self._dep
def setDep(self, dep):
self._dep = dep
dep = property(getDep, setDep, None, "dep property")
class PkgStarted(PkgBase):
"""Package build started"""
class PkgFailed(PkgBase):
"""Package build failed"""
class PkgSucceeded(PkgBase):
"""Package build completed"""
class BuildStarted(BuildBase):
@@ -217,13 +234,18 @@ class BuildCompleted(BuildBase):
"""bbmake build run completed"""
class UnsatisfiedDep(DepBase):
"""Unsatisfied Dependency"""
class RecursiveDep(DepBase):
"""Recursive Dependency"""
class NoProvider(Event):
"""No Provider for an Event"""
def __init__(self, item, runtime=False):
Event.__init__(self)
def __init__(self, item, data,runtime=False):
Event.__init__(self, data)
self._item = item
self._runtime = runtime
@@ -236,8 +258,8 @@ class NoProvider(Event):
class MultipleProviders(Event):
"""Multiple Providers"""
def __init__(self, item, candidates, runtime = False):
Event.__init__(self)
def __init__(self, item, candidates, data, runtime = False):
Event.__init__(self, data)
self._item = item
self._candidates = candidates
self._is_runtime = runtime
@@ -259,29 +281,3 @@ class MultipleProviders(Event):
Get the possible Candidates for a PROVIDER.
"""
return self._candidates
class ParseProgress(Event):
"""
Parsing Progress Event
"""
def __init__(self, cached, parsed, skipped, masked, virtuals, errors, total):
Event.__init__(self)
self.cached = cached
self.parsed = parsed
self.skipped = skipped
self.virtuals = virtuals
self.masked = masked
self.errors = errors
self.sofar = cached + parsed
self.total = total
class DepTreeGenerated(Event):
"""
Event when a dependency tree has been generated
"""
def __init__(self, depgraph):
Event.__init__(self)
self._depgraph = depgraph

View File

@@ -24,13 +24,15 @@ BitBake build tools.
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os, re
import os, re, fcntl
import bb
from bb import data
from bb import persist_data
class MalformedUrl(Exception):
"""Exception raised when encountering an invalid url"""
try:
import cPickle as pickle
except ImportError:
import pickle
class FetchError(Exception):
"""Exception raised when a download fails"""
@@ -50,103 +52,6 @@ class MD5SumError(Exception):
class InvalidSRCREV(Exception):
"""Exception raised when an invalid SRCREV is encountered"""
def decodeurl(url):
"""Decodes an URL into the tokens (scheme, network location, path,
user, password, parameters).
>>> decodeurl("http://www.google.com/index.html")
('http', 'www.google.com', '/index.html', '', '', {})
>>> decodeurl("file://gas/COPYING")
('file', '', 'gas/COPYING', '', '', {})
CVS url with username, host and cvsroot. The cvs module to check out is in the
parameters:
>>> decodeurl("cvs://anoncvs@cvs.handhelds.org/cvs;module=familiar/dist/ipkg")
('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', '', {'module': 'familiar/dist/ipkg'})
Dito, but this time the username has a password part. And we also request a special tag
to check out.
>>> decodeurl("cvs://anoncvs:anonymous@cvs.handhelds.org/cvs;module=familiar/dist/ipkg;tag=V0-99-81")
('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', 'anonymous', {'tag': 'V0-99-81', 'module': 'familiar/dist/ipkg'})
"""
m = re.compile('(?P<type>[^:]*)://((?P<user>.+)@)?(?P<location>[^;]+)(;(?P<parm>.*))?').match(url)
if not m:
raise MalformedUrl(url)
type = m.group('type')
location = m.group('location')
if not location:
raise MalformedUrl(url)
user = m.group('user')
parm = m.group('parm')
locidx = location.find('/')
if locidx != -1 and type.lower() != 'file':
host = location[:locidx]
path = location[locidx:]
else:
host = ""
path = location
if user:
m = re.compile('(?P<user>[^:]+)(:?(?P<pswd>.*))').match(user)
if m:
user = m.group('user')
pswd = m.group('pswd')
else:
user = ''
pswd = ''
p = {}
if parm:
for s in parm.split(';'):
s1,s2 = s.split('=')
p[s1] = s2
return (type, host, path, user, pswd, p)
def encodeurl(decoded):
"""Encodes a URL from tokens (scheme, network location, path,
user, password, parameters).
>>> encodeurl(['http', 'www.google.com', '/index.html', '', '', {}])
'http://www.google.com/index.html'
CVS with username, host and cvsroot. The cvs module to check out is in the
parameters:
>>> encodeurl(['cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', '', {'module': 'familiar/dist/ipkg'}])
'cvs://anoncvs@cvs.handhelds.org/cvs;module=familiar/dist/ipkg'
Dito, but this time the username has a password part. And we also request a special tag
to check out.
>>> encodeurl(['cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', 'anonymous', {'tag': 'V0-99-81', 'module': 'familiar/dist/ipkg'}])
'cvs://anoncvs:anonymous@cvs.handhelds.org/cvs;tag=V0-99-81;module=familiar/dist/ipkg'
"""
(type, host, path, user, pswd, p) = decoded
if not type or not path:
bb.msg.fatal(bb.msg.domain.Fetcher, "invalid or missing parameters for url encoding")
url = '%s://' % type
if user:
url += "%s" % user
if pswd:
url += ":%s" % pswd
url += "@"
if host:
url += "%s" % host
url += "%s" % path
if p:
for parm in p:
url += ";%s=%s" % (parm, p[parm])
return url
def uri_replace(uri, uri_find, uri_replace, d):
# bb.msg.note(1, bb.msg.domain.Fetcher, "uri_replace: operating on %s" % uri)
if not uri or not uri_find or not uri_replace:
@@ -160,6 +65,7 @@ def uri_replace(uri, uri_find, uri_replace, d):
result_decoded[loc] = uri_decoded[loc]
import types
if type(i) == types.StringType:
import re
if (re.match(i, uri_decoded[loc])):
result_decoded[loc] = re.sub(i, uri_replace_decoded[loc], uri_decoded[loc])
if uri_find_decoded.index(i) == 2:
@@ -172,13 +78,12 @@ def uri_replace(uri, uri_find, uri_replace, d):
# bb.msg.note(1, bb.msg.domain.Fetcher, "uri_replace: no match")
return uri
# else:
# for j in i:
# for j in i.keys():
# FIXME: apply replacements against options
return bb.encodeurl(result_decoded)
methods = []
urldata_cache = {}
saved_headrevs = {}
def fetcher_init(d):
"""
@@ -192,42 +97,13 @@ def fetcher_init(d):
bb.msg.debug(1, bb.msg.domain.Fetcher, "Keeping SRCREV cache due to cache policy of: %s" % srcrev_policy)
elif srcrev_policy == "clear":
bb.msg.debug(1, bb.msg.domain.Fetcher, "Clearing SRCREV cache due to cache policy of: %s" % srcrev_policy)
try:
bb.fetch.saved_headrevs = pd.getKeyValues("BB_URI_HEADREVS")
except:
pass
pd.delDomain("BB_URI_HEADREVS")
else:
bb.msg.fatal(bb.msg.domain.Fetcher, "Invalid SRCREV cache policy of: %s" % srcrev_policy)
for m in methods:
if hasattr(m, "init"):
m.init(d)
# Make sure our domains exist
pd.addDomain("BB_URI_HEADREVS")
pd.addDomain("BB_URI_LOCALCOUNT")
def fetcher_compare_revisons(d):
"""
Compare the revisions in the persistant cache with current values and
return true/false on whether they've changed.
"""
pd = persist_data.PersistData(d)
data = pd.getKeyValues("BB_URI_HEADREVS")
data2 = bb.fetch.saved_headrevs
changed = False
for key in data:
if key not in data2 or data2[key] != data[key]:
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s changed" % key)
changed = True
return True
else:
bb.msg.debug(2, bb.msg.domain.Fetcher, "%s did not change" % key)
return False
# Function call order is usually:
# 1. init
# 2. go
@@ -252,16 +128,14 @@ def init(urls, d, setup = True):
urldata_cache[fn] = urldata
return urldata
def go(d, urls = None):
def go(d):
"""
Fetch all urls
init must have previously been called
"""
if not urls:
urls = d.getVar("SRC_URI", 1).split()
urldata = init(urls, d, True)
urldata = init([], d, True)
for u in urls:
for u in urldata:
ud = urldata[u]
m = ud.method
if ud.localfile:
@@ -285,23 +159,7 @@ def go(d, urls = None):
pass
bb.utils.unlockfile(lf)
continue
# First try fetching uri, u, from PREMIRRORS
mirrors = [ i.split() for i in (bb.data.getVar('PREMIRRORS', d, 1) or "").split('\n') if i ]
localpath = try_mirrors(d, u, mirrors)
if not localpath:
# Next try fetching from the original uri, u
try:
m.go(u, ud, d)
localpath = ud.localpath
except:
# Finally, try fetching uri, u, from MIRRORS
mirrors = [ i.split() for i in (bb.data.getVar('MIRRORS', d, 1) or "").split('\n') if i ]
localpath = try_mirrors (d, u, mirrors)
if localpath:
ud.localpath = localpath
m.go(u, ud, d)
if ud.localfile:
if not m.forcefetch(u, ud, d):
Fetch.write_md5sum(u, ud, d)
@@ -319,20 +177,9 @@ def checkstatus(d):
ud = urldata[u]
m = ud.method
bb.msg.note(1, bb.msg.domain.Fetcher, "Testing URL %s" % u)
# First try checking uri, u, from PREMIRRORS
mirrors = [ i.split() for i in (bb.data.getVar('PREMIRRORS', d, 1) or "").split('\n') if i ]
ret = try_mirrors(d, u, mirrors, True)
ret = m.checkstatus(u, ud, d)
if not ret:
# Next try checking from the original uri, u
try:
ret = m.checkstatus(u, ud, d)
except:
# Finally, try checking uri, u, from MIRRORS
mirrors = [ i.split() for i in (bb.data.getVar('MIRRORS', d, 1) or "").split('\n') if i ]
ret = try_mirrors (d, u, mirrors, True)
if not ret:
bb.msg.error(bb.msg.domain.Fetcher, "URL %s doesn't work" % u)
bb.msg.fatal(bb.msg.domain.Fetcher, "URL %s doesn't work" % u)
def localpaths(d):
"""
@@ -385,8 +232,6 @@ def get_srcrev(d):
bb.msg.error(bb.msg.domain.Fetcher, "SRCREV was used yet no valid SCM was found in SRC_URI")
raise ParameterError
bb.data.setVar('__BB_DONT_CACHE','1', d)
if len(scms) == 1:
return urldata[scms[0]].method.sortable_revision(scms[0], urldata[scms[0]], d)
@@ -427,7 +272,7 @@ def runfetchcmd(cmd, d, quiet = False):
# rather than host provided
# Also include some other variables.
# FIXME: Should really include all export varaiables?
exportvars = ['PATH', 'GIT_PROXY_COMMAND', 'GIT_PROXY_HOST', 'GIT_PROXY_PORT', 'GIT_CONFIG', 'http_proxy', 'ftp_proxy', 'SSH_AUTH_SOCK', 'SSH_AGENT_PID', 'HOME']
exportvars = ['PATH', 'GIT_PROXY_HOST', 'GIT_PROXY_PORT', 'GIT_PROXY_COMMAND']
for var in exportvars:
val = data.getVar(var, d, True)
@@ -459,48 +304,6 @@ def runfetchcmd(cmd, d, quiet = False):
return output
def try_mirrors(d, uri, mirrors, check = False):
"""
Try to use a mirrored version of the sources.
This method will be automatically called before the fetchers go.
d Is a bb.data instance
uri is the original uri we're trying to download
mirrors is the list of mirrors we're going to try
"""
fpath = os.path.join(data.getVar("DL_DIR", d, 1), os.path.basename(uri))
if not check and os.access(fpath, os.R_OK):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists, skipping checkout." % fpath)
return fpath
ld = d.createCopy()
for (find, replace) in mirrors:
newuri = uri_replace(uri, find, replace, ld)
if newuri != uri:
try:
ud = FetchData(newuri, ld)
except bb.fetch.NoMethodError:
bb.msg.debug(1, bb.msg.domain.Fetcher, "No method for %s" % uri)
continue
ud.setup_localpath(ld)
try:
if check:
ud.method.checkstatus(newuri, ud, ld)
else:
ud.method.go(newuri, ud, ld)
return ud.localpath
except (bb.fetch.MissingParameterError,
bb.fetch.FetchError,
bb.fetch.MD5SumError):
import sys
(type, value, traceback) = sys.exc_info()
bb.msg.debug(2, bb.msg.domain.Fetcher, "Mirror fetch failure: %s" % value)
continue
return None
class FetchData(object):
"""
A class which represents the fetcher state for a given URI.
@@ -510,10 +313,6 @@ class FetchData(object):
(self.type, self.host, self.path, self.user, self.pswd, self.parm) = bb.decodeurl(data.expand(url, d))
self.date = Fetch.getSRCDate(self, d)
self.url = url
if not self.user and "user" in self.parm:
self.user = self.parm["user"]
if not self.pswd and "pswd" in self.parm:
self.pswd = self.parm["pswd"]
self.setup = False
for m in methods:
if m.supports(url, self, d):
@@ -527,33 +326,14 @@ class FetchData(object):
# if user sets localpath for file, use it instead.
self.localpath = self.parm["localpath"]
else:
premirrors = bb.data.getVar('PREMIRRORS', d, True)
local = ""
if premirrors and self.url:
aurl = self.url.split(";")[0]
mirrors = [ i.split() for i in (premirrors or "").split('\n') if i ]
for (find, replace) in mirrors:
if replace.startswith("file://"):
path = aurl.split("://")[1]
path = path.split(";")[0]
local = replace.split("://")[1] + os.path.basename(path)
if local == aurl or not os.path.exists(local) or os.path.isdir(local):
local = ""
self.localpath = local
if not local:
try:
bb.fetch.srcrev_internal_call = True
self.localpath = self.method.localpath(self.url, self, d)
finally:
bb.fetch.srcrev_internal_call = False
# We have to clear data's internal caches since the cached value of SRCREV is now wrong.
# Horrible...
bb.data.delVar("ISHOULDNEVEREXIST", d)
# Note: These files should always be in DL_DIR whereas localpath may not be.
basepath = bb.data.expand("${DL_DIR}/%s" % os.path.basename(self.localpath), d)
self.md5 = basepath + '.md5'
self.lockfile = basepath + '.lock'
bb.fetch.srcrev_internal_call = True
self.localpath = self.method.localpath(self.url, self, d)
bb.fetch.srcrev_internal_call = False
# We have to clear data's internal caches since the cached value of SRCREV is now wrong.
# Horrible...
bb.data.delVar("ISHOULDNEVEREXIST", d)
self.md5 = self.localpath + '.md5'
self.lockfile = self.localpath + '.lock'
class Fetch(object):
@@ -658,22 +438,37 @@ class Fetch(object):
srcrev_internal_helper = staticmethod(srcrev_internal_helper)
def localcount_internal_helper(ud, d):
def try_mirror(d, tarfn):
"""
Return:
a) a locked localcount if specified
b) None otherwise
Try to use a mirrored version of the sources. We do this
to avoid massive loads on foreign cvs and svn servers.
This method will be used by the different fetcher
implementations.
d Is a bb.data instance
tarfn is the name of the tarball
"""
tarpath = os.path.join(data.getVar("DL_DIR", d, 1), tarfn)
if os.access(tarpath, os.R_OK):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists, skipping checkout." % tarfn)
return True
localcount= None
if 'name' in ud.parm:
pn = data.getVar("PN", d, 1)
localcount = data.getVar("LOCALCOUNT_" + ud.parm['name'], d, 1)
if not localcount:
localcount = data.getVar("LOCALCOUNT", d, 1)
return localcount
pn = data.getVar('PN', d, True)
src_tarball_stash = None
if pn:
src_tarball_stash = (data.getVar('SRC_TARBALL_STASH_%s' % pn, d, True) or data.getVar('CVS_TARBALL_STASH_%s' % pn, d, True) or data.getVar('SRC_TARBALL_STASH', d, True) or data.getVar('CVS_TARBALL_STASH', d, True) or "").split()
localcount_internal_helper = staticmethod(localcount_internal_helper)
for stash in src_tarball_stash:
fetchcmd = data.getVar("FETCHCOMMAND_mirror", d, True) or data.getVar("FETCHCOMMAND_wget", d, True)
uri = stash + tarfn
bb.msg.note(1, bb.msg.domain.Fetcher, "fetch " + uri)
fetchcmd = fetchcmd.replace("${URI}", uri)
ret = os.system(fetchcmd)
if ret == 0:
bb.msg.note(1, bb.msg.domain.Fetcher, "Fetched %s from tarball stash, skipping checkout" % tarfn)
return True
return False
try_mirror = staticmethod(try_mirror)
def verify_md5sum(ud, got_sum):
"""
@@ -707,7 +502,7 @@ class Fetch(object):
raise ParameterError
pd = persist_data.PersistData(d)
key = self.generate_revision_key(url, ud, d)
key = self._revision_key(url, ud, d)
rev = pd.getValue("BB_URI_HEADREVS", key)
if rev != None:
return str(rev)
@@ -724,28 +519,16 @@ class Fetch(object):
return self._sortable_revision(url, ud, d)
pd = persist_data.PersistData(d)
key = self.generate_revision_key(url, ud, d)
key = self._revision_key(url, ud, d)
latest_rev = self._build_revision(url, ud, d)
last_rev = pd.getValue("BB_URI_LOCALCOUNT", key + "_rev")
uselocalcount = bb.data.getVar("BB_LOCALCOUNT_OVERRIDE", d, True) or False
count = None
if uselocalcount:
count = Fetch.localcount_internal_helper(ud, d)
if count is None:
count = pd.getValue("BB_URI_LOCALCOUNT", key + "_count")
count = pd.getValue("BB_URI_LOCALCOUNT", key + "_count")
if last_rev == latest_rev:
return str(count + "+" + latest_rev)
buildindex_provided = hasattr(self, "_sortable_buildindex")
if buildindex_provided:
count = self._sortable_buildindex(url, ud, d, latest_rev)
if count is None:
count = "0"
elif uselocalcount or buildindex_provided:
count = str(count)
else:
count = str(int(count) + 1)
@@ -754,9 +537,6 @@ class Fetch(object):
return str(count + "+" + latest_rev)
def generate_revision_key(self, url, ud, d):
key = self._revision_key(url, ud, d)
return "%s-%s" % (key, bb.data.getVar("PN", d, True) or "")
import cvs
import git
@@ -768,8 +548,6 @@ import ssh
import perforce
import bzr
import hg
import osc
import repo
methods.append(local.Local())
methods.append(wget.Wget())
@@ -781,5 +559,3 @@ methods.append(ssh.SSH())
methods.append(perforce.Perforce())
methods.append(bzr.Bzr())
methods.append(hg.Hg())
methods.append(osc.Osc())
methods.append(repo.Repo())

View File

@@ -29,6 +29,7 @@ import bb
from bb import data
from bb.fetch import Fetch
from bb.fetch import FetchError
from bb.fetch import MissingParameterError
from bb.fetch import runfetchcmd
class Bzr(Fetch):
@@ -91,6 +92,11 @@ class Bzr(Fetch):
def go(self, loc, ud, d):
"""Fetch url"""
# try to use the tarball stash
if Fetch.try_mirror(d, ud.localfile):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists or was mirrored, skipping bzr checkout." % ud.localpath)
return
if os.access(os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir), '.bzr'), os.R_OK):
bzrcmd = self._buildbzrcommand(ud, d, "update")
bb.msg.debug(1, bb.msg.domain.Fetcher, "BZR Update %s" % loc)

View File

@@ -26,7 +26,7 @@ BitBake build tools.
#Based on functions from the base bb module, Copyright 2003 Holger Schurig
#
import os
import os, re
import bb
from bb import data
from bb.fetch import Fetch
@@ -41,7 +41,7 @@ class Cvs(Fetch):
"""
Check to see if a given url can be fetched with cvs.
"""
return ud.type in ['cvs']
return ud.type in ['cvs', 'pserver']
def localpath(self, url, ud, d):
if not "module" in ud.parm:
@@ -77,6 +77,11 @@ class Cvs(Fetch):
def go(self, loc, ud, d):
# try to use the tarball stash
if not self.forcefetch(loc, ud, d) and Fetch.try_mirror(d, ud.localfile):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists or was mirrored, skipping cvs checkout." % ud.localpath)
return
method = "pserver"
if "method" in ud.parm:
method = ud.parm["method"]
@@ -113,11 +118,7 @@ class Cvs(Fetch):
if 'norecurse' in ud.parm:
options.append("-l")
if ud.date:
# treat YYYYMMDDHHMM specially for CVS
if len(ud.date) == 12:
options.append("-D \"%s %s:%s UTC\"" % (ud.date[0:8], ud.date[8:10], ud.date[10:12]))
else:
options.append("-D \"%s UTC\"" % ud.date)
options.append("-D \"%s UTC\"" % ud.date)
if ud.tag:
options.append("-r %s" % ud.tag)

View File

@@ -20,20 +20,15 @@ BitBake 'Fetch' git implementation
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
import os, re
import bb
from bb import data
from bb.fetch import Fetch
from bb.fetch import FetchError
from bb.fetch import runfetchcmd
class Git(Fetch):
"""Class to fetch a module or modules from git repositories"""
def init(self, d):
#
# Only enable _sortable revision if the key is set
#
if bb.data.getVar("BB_GIT_CLONE_FOR_SRCREV", d, True):
self._sortable_buildindex = self._sortable_buildindex_disabled
def supports(self, url, ud, d):
"""
Check to see if a given url can be fetched with git.
@@ -42,125 +37,84 @@ class Git(Fetch):
def localpath(self, url, ud, d):
ud.proto = "rsync"
if 'protocol' in ud.parm:
ud.proto = ud.parm['protocol']
elif not ud.host:
ud.proto = 'file'
else:
ud.proto = "rsync"
ud.branch = ud.parm.get("branch", "master")
gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
ud.mirrortarball = 'git_%s.tar.gz' % (gitsrcname)
ud.clonedir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
tag = Fetch.srcrev_internal_helper(ud, d)
if tag is True:
ud.tag = self.latest_revision(url, ud, d)
elif tag:
ud.tag = tag
if not ud.tag or ud.tag == "master":
if not ud.tag:
ud.tag = self.latest_revision(url, ud, d)
subdir = ud.parm.get("subpath", "")
if subdir != "":
if subdir.endswith("/"):
subdir = subdir[:-1]
subdirpath = os.path.join(ud.path, subdir);
else:
subdirpath = ud.path;
if ud.tag == "master":
ud.tag = self.latest_revision(url, ud, d)
if 'fullclone' in ud.parm:
ud.localfile = ud.mirrortarball
else:
ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, subdirpath.replace('/', '.'), ud.tag), d)
ud.basecmd = data.getVar("FETCHCMD_git", d, True) or "git"
ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.tag), d)
return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
def go(self, loc, ud, d):
"""Fetch url"""
if ud.user:
username = ud.user + '@'
else:
username = ""
if Fetch.try_mirror(d, ud.localfile):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists (or was stashed). Skipping git checkout." % ud.localpath)
return
repofile = os.path.join(data.getVar("DL_DIR", d, 1), ud.mirrortarball)
gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
repofilename = 'git_%s.tar.gz' % (gitsrcname)
repofile = os.path.join(data.getVar("DL_DIR", d, 1), repofilename)
repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
coname = '%s' % (ud.tag)
codir = os.path.join(ud.clonedir, coname)
codir = os.path.join(repodir, coname)
if not os.path.exists(ud.clonedir):
try:
Fetch.try_mirrors(ud.mirrortarball)
bb.mkdirhier(ud.clonedir)
os.chdir(ud.clonedir)
if not os.path.exists(repodir):
if Fetch.try_mirror(d, repofilename):
bb.mkdirhier(repodir)
os.chdir(repodir)
runfetchcmd("tar -xzf %s" % (repofile), d)
except:
runfetchcmd("%s clone -n %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.clonedir), d)
else:
runfetchcmd("git clone -n %s://%s%s %s" % (ud.proto, ud.host, ud.path, repodir), d)
os.chdir(ud.clonedir)
os.chdir(repodir)
# Remove all but the .git directory
if not self._contains_ref(ud.tag, d):
runfetchcmd("rm * -Rf", d)
runfetchcmd("%s fetch %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.branch), d)
runfetchcmd("%s fetch --tags %s://%s%s%s" % (ud.basecmd, ud.proto, username, ud.host, ud.path), d)
runfetchcmd("%s prune-packed" % ud.basecmd, d)
runfetchcmd("%s pack-redundant --all | xargs -r rm" % ud.basecmd, d)
runfetchcmd("rm * -Rf", d)
runfetchcmd("git fetch %s://%s%s %s" % (ud.proto, ud.host, ud.path, ud.branch), d)
runfetchcmd("git fetch --tags %s://%s%s" % (ud.proto, ud.host, ud.path), d)
runfetchcmd("git prune-packed", d)
runfetchcmd("git pack-redundant --all | xargs -r rm", d)
os.chdir(ud.clonedir)
os.chdir(repodir)
mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True)
if mirror_tarballs != "0" or 'fullclone' in ud.parm:
if mirror_tarballs != "0":
bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git repository")
runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d)
if 'fullclone' in ud.parm:
return
if os.path.exists(codir):
bb.utils.prunedir(codir)
subdir = ud.parm.get("subpath", "")
if subdir != "":
if subdir.endswith("/"):
subdirbase = os.path.basename(subdir[:-1])
else:
subdirbase = os.path.basename(subdir)
else:
subdirbase = ""
if subdir != "":
readpathspec = ":%s" % (subdir)
codir = os.path.join(codir, "git")
coprefix = os.path.join(codir, subdirbase, "")
else:
readpathspec = ""
coprefix = os.path.join(codir, "git", "")
bb.mkdirhier(codir)
os.chdir(ud.clonedir)
runfetchcmd("%s read-tree %s%s" % (ud.basecmd, ud.tag, readpathspec), d)
runfetchcmd("%s checkout-index -q -f --prefix=%s -a" % (ud.basecmd, coprefix), d)
os.chdir(repodir)
runfetchcmd("git read-tree %s" % (ud.tag), d)
runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (os.path.join(codir, "git", "")), d)
os.chdir(codir)
bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git checkout")
runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d)
os.chdir(ud.clonedir)
os.chdir(repodir)
bb.utils.prunedir(codir)
def suppports_srcrev(self):
return True
def _contains_ref(self, tag, d):
basecmd = data.getVar("FETCHCMD_git", d, True) or "git"
output = runfetchcmd("%s log --pretty=oneline -n 1 %s -- 2> /dev/null | wc -l" % (basecmd, tag), d, quiet=True)
return output.split()[0] != "0"
def _revision_key(self, url, ud, d):
"""
Return a unique key for the url
@@ -171,47 +125,9 @@ class Git(Fetch):
"""
Compute the HEAD revision for the url
"""
if ud.user:
username = ud.user + '@'
else:
username = ""
basecmd = data.getVar("FETCHCMD_git", d, True) or "git"
cmd = "%s ls-remote %s://%s%s%s %s" % (basecmd, ud.proto, username, ud.host, ud.path, ud.branch)
output = runfetchcmd(cmd, d, True)
if not output:
raise bb.fetch.FetchError("Fetch command %s gave empty output\n" % (cmd))
output = runfetchcmd("git ls-remote %s://%s%s %s" % (ud.proto, ud.host, ud.path, ud.branch), d, True)
return output.split()[0]
def _build_revision(self, url, ud, d):
return ud.tag
def _sortable_buildindex_disabled(self, url, ud, d, rev):
"""
Return a suitable buildindex for the revision specified. This is done by counting revisions
using "git rev-list" which may or may not work in different circumstances.
"""
cwd = os.getcwd()
# Check if we have the rev already
if not os.path.exists(ud.clonedir):
print "no repo"
self.go(None, ud, d)
if not os.path.exists(ud.clonedir):
bb.msg.error(bb.msg.domain.Fetcher, "GIT repository for %s doesn't exist in %s, cannot get sortable buildnumber, using old value" % (url, ud.clonedir))
return None
os.chdir(ud.clonedir)
if not self._contains_ref(rev, d):
self.go(None, ud, d)
output = runfetchcmd("%s rev-list %s -- 2> /dev/null | wc -l" % (ud.basecmd, rev), d, quiet=True)
os.chdir(cwd)
buildindex = "%s" % output.split()[0]
bb.msg.debug(1, bb.msg.domain.Fetcher, "GIT repository for %s in %s is returning %s revisions in rev-list before %s" % (url, ud.clonedir, buildindex, rev))
return buildindex

View File

@@ -24,7 +24,7 @@ BitBake 'Fetch' implementation for mercurial DRCS (hg).
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os
import os, re
import sys
import bb
from bb import data
@@ -57,14 +57,6 @@ class Hg(Fetch):
if 'rev' in ud.parm:
ud.revision = ud.parm['rev']
else:
tag = Fetch.srcrev_internal_helper(ud, d)
if tag is True:
ud.revision = self.latest_revision(url, ud, d)
elif tag:
ud.revision = tag
else:
ud.revision = self.latest_revision(url, ud, d)
ud.localfile = data.expand('%s_%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision), d)
@@ -87,7 +79,7 @@ class Hg(Fetch):
host = "/"
ud.host = "localhost"
if not ud.user:
if ud.user == None:
hgroot = host + ud.path
else:
hgroot = ud.user + "@" + host + ud.path
@@ -116,6 +108,11 @@ class Hg(Fetch):
def go(self, loc, ud, d):
"""Fetch url"""
# try to use the tarball stash
if Fetch.try_mirror(d, ud.localfile):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists or was mirrored, skipping hg checkout." % ud.localpath)
return
bb.msg.debug(2, bb.msg.domain.Fetcher, "Fetch: checking for module directory '" + ud.moddir + "'")
if os.access(os.path.join(ud.moddir, '.hg'), os.R_OK):
@@ -126,6 +123,9 @@ class Hg(Fetch):
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % updatecmd)
runfetchcmd(updatecmd, d)
updatecmd = self._buildhgcommand(ud, d, "update")
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % updatecmd)
runfetchcmd(updatecmd, d)
else:
fetchcmd = self._buildhgcommand(ud, d, "fetch")
bb.msg.note(1, bb.msg.domain.Fetcher, "Fetch " + loc)
@@ -134,12 +134,6 @@ class Hg(Fetch):
os.chdir(ud.pkgdir)
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % fetchcmd)
runfetchcmd(fetchcmd, d)
# Even when we clone (fetch), we still need to update as hg's clone
# won't checkout the specified revision if its on a branch
updatecmd = self._buildhgcommand(ud, d, "update")
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % updatecmd)
runfetchcmd(updatecmd, d)
os.chdir(ud.pkgdir)
try:
@@ -151,23 +145,3 @@ class Hg(Fetch):
except OSError:
pass
raise t, v, tb
def suppports_srcrev(self):
return True
def _latest_revision(self, url, ud, d):
"""
Compute tip revision for the url
"""
output = runfetchcmd(self._buildhgcommand(ud, d, "info"), d)
return output.strip()
def _build_revision(self, url, ud, d):
return ud.revision
def _revision_key(self, url, ud, d):
"""
Return a unique key for the url
"""
return "hg:" + ud.moddir

View File

@@ -25,7 +25,7 @@ BitBake build tools.
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os
import os, re
import bb
from bb import data
from bb.fetch import Fetch
@@ -33,9 +33,9 @@ from bb.fetch import Fetch
class Local(Fetch):
def supports(self, url, urldata, d):
"""
Check to see if a given url represents a local fetch.
Check to see if a given url can be fetched with cvs.
"""
return urldata.type in ['file']
return urldata.type in ['file','patch']
def localpath(self, url, urldata, d):
"""

View File

@@ -1,150 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
Bitbake "Fetch" implementation for osc (Opensuse build service client).
Based on the svn "Fetch" implementation.
"""
import os
import sys
import bb
from bb import data
from bb.fetch import Fetch
from bb.fetch import FetchError
from bb.fetch import MissingParameterError
from bb.fetch import runfetchcmd
class Osc(Fetch):
"""Class to fetch a module or modules from Opensuse build server
repositories."""
def supports(self, url, ud, d):
"""
Check to see if a given url can be fetched with osc.
"""
return ud.type in ['osc']
def localpath(self, url, ud, d):
if not "module" in ud.parm:
raise MissingParameterError("osc method needs a 'module' parameter.")
ud.module = ud.parm["module"]
# Create paths to osc checkouts
relpath = ud.path
if relpath.startswith('/'):
# Remove leading slash as os.path.join can't cope
relpath = relpath[1:]
ud.pkgdir = os.path.join(data.expand('${OSCDIR}', d), ud.host)
ud.moddir = os.path.join(ud.pkgdir, relpath, ud.module)
if 'rev' in ud.parm:
ud.revision = ud.parm['rev']
else:
pv = data.getVar("PV", d, 0)
rev = Fetch.srcrev_internal_helper(ud, d)
if rev and rev != True:
ud.revision = rev
else:
ud.revision = ""
ud.localfile = data.expand('%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.path.replace('/', '.'), ud.revision), d)
return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
def _buildosccommand(self, ud, d, command):
"""
Build up an ocs commandline based on ud
command is "fetch", "update", "info"
"""
basecmd = data.expand('${FETCHCMD_osc}', d)
proto = "ocs"
if "proto" in ud.parm:
proto = ud.parm["proto"]
options = []
config = "-c %s" % self.generate_config(ud, d)
if ud.revision:
options.append("-r %s" % ud.revision)
coroot = ud.path
if coroot.startswith('/'):
# Remove leading slash as os.path.join can't cope
coroot= coroot[1:]
if command is "fetch":
osccmd = "%s %s co %s/%s %s" % (basecmd, config, coroot, ud.module, " ".join(options))
elif command is "update":
osccmd = "%s %s up %s" % (basecmd, config, " ".join(options))
else:
raise FetchError("Invalid osc command %s" % command)
return osccmd
def go(self, loc, ud, d):
"""
Fetch url
"""
bb.msg.debug(2, bb.msg.domain.Fetcher, "Fetch: checking for module directory '" + ud.moddir + "'")
if os.access(os.path.join(data.expand('${OSCDIR}', d), ud.path, ud.module), os.R_OK):
oscupdatecmd = self._buildosccommand(ud, d, "update")
bb.msg.note(1, bb.msg.domain.Fetcher, "Update "+ loc)
# update sources there
os.chdir(ud.moddir)
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % oscupdatecmd)
runfetchcmd(oscupdatecmd, d)
else:
oscfetchcmd = self._buildosccommand(ud, d, "fetch")
bb.msg.note(1, bb.msg.domain.Fetcher, "Fetch " + loc)
# check out sources there
bb.mkdirhier(ud.pkgdir)
os.chdir(ud.pkgdir)
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % oscfetchcmd)
runfetchcmd(oscfetchcmd, d)
os.chdir(os.path.join(ud.pkgdir + ud.path))
# tar them up to a defined filename
try:
runfetchcmd("tar -czf %s %s" % (ud.localpath, ud.module), d)
except:
t, v, tb = sys.exc_info()
try:
os.unlink(ud.localpath)
except OSError:
pass
raise t, v, tb
def supports_srcrev(self):
return False
def generate_config(self, ud, d):
"""
Generate a .oscrc to be used for this run.
"""
config_path = "%s/oscrc" % data.expand('${OSCDIR}', d)
if (os.path.exists(config_path)):
os.remove(config_path)
f = open(config_path, 'w')
f.write("[general]\n")
f.write("apisrv = %s\n" % ud.host)
f.write("scheme = http\n")
f.write("su-wrapper = su -c\n")
f.write("build-root = %s\n" % data.expand('${WORKDIR}', d))
f.write("urllist = http://moblin-obs.jf.intel.com:8888/build/%(project)s/%(repository)s/%(buildarch)s/:full/%(name)s.rpm\n")
f.write("extra-pkgs = gzip\n")
f.write("\n")
f.write("[%s]\n" % ud.host)
f.write("user = %s\n" % ud.parm["user"])
f.write("pass = %s\n" % ud.parm["pswd"])
f.close()
return config_path

View File

@@ -25,11 +25,12 @@ BitBake build tools.
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os
import os, re
import bb
from bb import data
from bb.fetch import Fetch
from bb.fetch import FetchError
from bb.fetch import MissingParameterError
class Perforce(Fetch):
def supports(self, url, ud, d):
@@ -66,15 +67,14 @@ class Perforce(Fetch):
doparse = staticmethod(doparse)
def getcset(d, depot,host,user,pswd,parm):
p4opt = ""
if "cset" in parm:
return parm["cset"];
if user:
p4opt += " -u %s" % (user)
data.setVar('P4USER', user, d)
if pswd:
p4opt += " -P %s" % (pswd)
data.setVar('P4PASSWD', pswd, d)
if host:
p4opt += " -p %s" % (host)
data.setVar('P4PORT', host, d)
p4date = data.getVar("P4DATE", d, 1)
if "revision" in parm:
@@ -85,8 +85,8 @@ class Perforce(Fetch):
depot += "@%s" % (p4date)
p4cmd = data.getVar('FETCHCOMMAND_p4', d, 1)
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s%s changes -m 1 %s" % (p4cmd, p4opt, depot))
p4file = os.popen("%s%s changes -m 1 %s" % (p4cmd, p4opt, depot))
bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s changes -m 1 %s" % (p4cmd, depot))
p4file = os.popen("%s changes -m 1 %s" % (p4cmd,depot))
cset = p4file.readline().strip()
bb.msg.debug(1, bb.msg.domain.Fetcher, "READ %s" % (cset))
if not cset:
@@ -124,6 +124,11 @@ class Perforce(Fetch):
Fetch urls
"""
# try to use the tarball stash
if Fetch.try_mirror(d, ud.localfile):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists or was mirrored, skipping perforce checkout." % ud.localpath)
return
(host,depot,user,pswd,parm) = Perforce.doparse(loc, d)
if depot.find('/...') != -1:
@@ -141,15 +146,14 @@ class Perforce(Fetch):
data.update_data(localdata)
# Get the p4 command
p4opt = ""
if user:
p4opt += " -u %s" % (user)
data.setVar('P4USER', user, localdata)
if pswd:
p4opt += " -P %s" % (pswd)
data.setVar('P4PASSWD', pswd, localdata)
if host:
p4opt += " -p %s" % (host)
data.setVar('P4PORT', host, localdata)
p4cmd = data.getVar('FETCHCOMMAND', localdata, 1)
@@ -171,8 +175,8 @@ class Perforce(Fetch):
os.chdir(tmpfile)
bb.msg.note(1, bb.msg.domain.Fetcher, "Fetch " + loc)
bb.msg.note(1, bb.msg.domain.Fetcher, "%s%s files %s" % (p4cmd, p4opt, depot))
p4file = os.popen("%s%s files %s" % (p4cmd, p4opt, depot))
bb.msg.note(1, bb.msg.domain.Fetcher, "%s files %s" % (p4cmd, depot))
p4file = os.popen("%s files %s" % (p4cmd, depot))
if not p4file:
bb.error("Fetch: unable to get the P4 files from %s" % (depot))
@@ -189,7 +193,7 @@ class Perforce(Fetch):
dest = list[0][len(path)+1:]
where = dest.find("#")
os.system("%s%s print -o %s/%s %s" % (p4cmd, p4opt, module,dest[:where],list[0]))
os.system("%s print -o %s/%s %s" % (p4cmd, module,dest[:where],list[0]))
count = count + 1
if count == 0:

View File

@@ -1,106 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake "Fetch" repo (git) implementation
"""
# Copyright (C) 2009 Tom Rini <trini@embeddedalley.com>
#
# Based on git.py which is:
#Copyright (C) 2005 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os, re
import bb
from bb import data
from bb.fetch import Fetch
from bb.fetch import FetchError
from bb.fetch import runfetchcmd
class Repo(Fetch):
"""Class to fetch a module or modules from repo (git) repositories"""
def supports(self, url, ud, d):
"""
Check to see if a given url can be fetched with repo.
"""
return ud.type in ["repo"]
def localpath(self, url, ud, d):
"""
We don"t care about the git rev of the manifests repository, but
we do care about the manifest to use. The default is "default".
We also care about the branch or tag to be used. The default is
"master".
"""
if "protocol" in ud.parm:
ud.proto = ud.parm["protocol"]
else:
ud.proto = "git"
if "branch" in ud.parm:
ud.branch = ud.parm["branch"]
else:
ud.branch = "master"
if "manifest" in ud.parm:
manifest = ud.parm["manifest"]
if manifest.endswith(".xml"):
ud.manifest = manifest
else:
ud.manifest = manifest + ".xml"
else:
ud.manifest = "default.xml"
ud.localfile = data.expand("repo_%s%s_%s_%s.tar.gz" % (ud.host, ud.path.replace("/", "."), ud.manifest, ud.branch), d)
return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
def go(self, loc, ud, d):
"""Fetch url"""
if os.access(os.path.join(data.getVar("DL_DIR", d, True), ud.localfile), os.R_OK):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists (or was stashed). Skipping repo init / sync." % ud.localpath)
return
gitsrcname = "%s%s" % (ud.host, ud.path.replace("/", "."))
repodir = data.getVar("REPODIR", d, True) or os.path.join(data.getVar("DL_DIR", d, True), "repo")
codir = os.path.join(repodir, gitsrcname, ud.manifest)
if ud.user:
username = ud.user + "@"
else:
username = ""
bb.mkdirhier(os.path.join(codir, "repo"))
os.chdir(os.path.join(codir, "repo"))
if not os.path.exists(os.path.join(codir, "repo", ".repo")):
runfetchcmd("repo init -m %s -b %s -u %s://%s%s%s" % (ud.manifest, ud.branch, ud.proto, username, ud.host, ud.path), d)
runfetchcmd("repo sync", d)
os.chdir(codir)
# Create a cache
runfetchcmd("tar --exclude=.repo --exclude=.git -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d)
def suppports_srcrev(self):
return False
def _build_revision(self, url, ud, d):
return ud.manifest
def _want_sortable_revision(self, url, ud, d):
return False

View File

@@ -37,9 +37,11 @@ IETF secsh internet draft:
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import re, os
import bb
from bb import data
from bb.fetch import Fetch
from bb.fetch import FetchError
from bb.fetch import MissingParameterError
__pattern__ = re.compile(r'''

View File

@@ -25,7 +25,7 @@ This implementation is for svk. It is based on the svn implementation
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os
import os, re
import bb
from bb import data
from bb.fetch import Fetch
@@ -36,7 +36,7 @@ class Svk(Fetch):
"""Class to fetch a module or modules from svk repositories"""
def supports(self, url, ud, d):
"""
Check to see if a given url can be fetched with svk.
Check to see if a given url can be fetched with cvs.
"""
return ud.type in ['svk']
@@ -62,12 +62,15 @@ class Svk(Fetch):
def go(self, loc, ud, d):
"""Fetch urls"""
if not self.forcefetch(loc, ud, d) and Fetch.try_mirror(d, ud.localfile):
return
svkroot = ud.host + ud.path
svkcmd = "svk co -r {%s} %s/%s" % (ud.date, svkroot, ud.module)
svkcmd = "svk co -r {%s} %s/%s" % (date, svkroot, ud.module)
if ud.revision:
svkcmd = "svk co -r %s %s/%s" % (ud.revision, svkroot, ud.module)
svkcmd = "svk co -r %s/%s" % (ud.revision, svkroot, ud.module)
# create temp directory
localdata = data.createCopy(d)

View File

@@ -23,7 +23,7 @@ BitBake 'Fetch' implementation for svn.
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os
import os, re
import sys
import bb
from bb import data
@@ -114,15 +114,13 @@ class Svn(Fetch):
if command is "info":
svncmd = "%s info %s %s://%s/%s/" % (basecmd, " ".join(options), proto, svnroot, ud.module)
else:
suffix = ""
if ud.revision:
options.append("-r %s" % ud.revision)
suffix = "@%s" % (ud.revision)
elif ud.date:
options.append("-r {%s}" % ud.date)
if command is "fetch":
svncmd = "%s co %s %s://%s/%s%s %s" % (basecmd, " ".join(options), proto, svnroot, ud.module, suffix, ud.module)
svncmd = "%s co %s %s://%s/%s %s" % (basecmd, " ".join(options), proto, svnroot, ud.module, ud.module)
elif command is "update":
svncmd = "%s update %s" % (basecmd, " ".join(options))
else:
@@ -136,6 +134,11 @@ class Svn(Fetch):
def go(self, loc, ud, d):
"""Fetch url"""
# try to use the tarball stash
if Fetch.try_mirror(d, ud.localfile):
bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists or was mirrored, skipping svn checkout." % ud.localpath)
return
bb.msg.debug(2, bb.msg.domain.Fetcher, "Fetch: checking for module directory '" + ud.moddir + "'")
if os.access(os.path.join(ud.moddir, '.svn'), os.R_OK):

View File

@@ -25,17 +25,18 @@ BitBake build tools.
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os
import os, re
import bb
from bb import data
from bb.fetch import Fetch
from bb.fetch import FetchError
from bb.fetch import uri_replace
class Wget(Fetch):
"""Class to fetch urls via 'wget'"""
def supports(self, url, ud, d):
"""
Check to see if a given url can be fetched with wget.
Check to see if a given url can be fetched with cvs.
"""
return ud.type in ['http','https','ftp']
@@ -59,34 +60,9 @@ class Wget(Fetch):
else:
fetchcmd = data.getVar("FETCHCOMMAND", d, 1)
uri = uri.split(";")[0]
uri_decoded = list(bb.decodeurl(uri))
uri_type = uri_decoded[0]
uri_host = uri_decoded[1]
bb.msg.note(1, bb.msg.domain.Fetcher, "fetch " + uri)
fetchcmd = fetchcmd.replace("${URI}", uri.split(";")[0])
fetchcmd = fetchcmd.replace("${URI}", uri)
fetchcmd = fetchcmd.replace("${FILE}", ud.basename)
httpproxy = None
ftpproxy = None
if uri_type == 'http':
httpproxy = data.getVar("HTTP_PROXY", d, True)
httpproxy_ignore = (data.getVar("HTTP_PROXY_IGNORE", d, True) or "").split()
for p in httpproxy_ignore:
if uri_host.endswith(p):
httpproxy = None
break
if uri_type == 'ftp':
ftpproxy = data.getVar("FTP_PROXY", d, True)
ftpproxy_ignore = (data.getVar("HTTP_PROXY_IGNORE", d, True) or "").split()
for p in ftpproxy_ignore:
if uri_host.endswith(p):
ftpproxy = None
break
if httpproxy:
fetchcmd = "http_proxy=" + httpproxy + " " + fetchcmd
if ftpproxy:
fetchcmd = "ftp_proxy=" + ftpproxy + " " + fetchcmd
bb.msg.debug(2, bb.msg.domain.Fetcher, "executing " + fetchcmd)
ret = os.system(fetchcmd)
if ret != 0:
@@ -94,7 +70,7 @@ class Wget(Fetch):
# Sanity check since wget can pretend it succeed when it didn't
# Also, this used to happen if sourceforge sent us to the mirror page
if not os.path.exists(ud.localpath) and not checkonly:
if not os.path.exists(ud.localpath):
bb.msg.debug(2, bb.msg.domain.Fetcher, "The fetch command for %s returned success but %s doesn't exist?..." % (uri, ud.localpath))
return False
@@ -104,9 +80,24 @@ class Wget(Fetch):
data.setVar('OVERRIDES', "wget:" + data.getVar('OVERRIDES', localdata), localdata)
data.update_data(localdata)
premirrors = [ i.split() for i in (data.getVar('PREMIRRORS', localdata, 1) or "").split('\n') if i ]
for (find, replace) in premirrors:
newuri = uri_replace(uri, find, replace, d)
if newuri != uri:
if fetch_uri(newuri, ud, localdata):
return True
if fetch_uri(uri, ud, localdata):
return True
# try mirrors
mirrors = [ i.split() for i in (data.getVar('MIRRORS', localdata, 1) or "").split('\n') if i ]
for (find, replace) in mirrors:
newuri = uri_replace(uri, find, replace, d)
if newuri != uri:
if fetch_uri(newuri, ud, localdata):
return True
raise FetchError(uri)

144
bitbake/lib/bb/manifest.py Normal file
View File

@@ -0,0 +1,144 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2003, 2004 Chris Larson
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os, sys
import bb, bb.data
def getfields(line):
fields = {}
fieldmap = ( "pkg", "src", "dest", "type", "mode", "uid", "gid", "major", "minor", "start", "inc", "count" )
for f in xrange(len(fieldmap)):
fields[fieldmap[f]] = None
if not line:
return None
splitline = line.split()
if not len(splitline):
return None
try:
for f in xrange(len(fieldmap)):
if splitline[f] == '-':
continue
fields[fieldmap[f]] = splitline[f]
except IndexError:
pass
return fields
def parse (mfile, d):
manifest = []
while 1:
line = mfile.readline()
if not line:
break
if line.startswith("#"):
continue
fields = getfields(line)
if not fields:
continue
manifest.append(fields)
return manifest
def emit (func, manifest, d):
#str = "%s () {\n" % func
str = ""
for line in manifest:
emittedline = emit_line(func, line, d)
if not emittedline:
continue
str += emittedline + "\n"
# str += "}\n"
return str
def mangle (func, line, d):
import copy
newline = copy.copy(line)
src = bb.data.expand(newline["src"], d)
if src:
if not os.path.isabs(src):
src = "${WORKDIR}/" + src
dest = newline["dest"]
if not dest:
return
if dest.startswith("/"):
dest = dest[1:]
if func is "do_install":
dest = "${D}/" + dest
elif func is "do_populate":
dest = "${WORKDIR}/install/" + newline["pkg"] + "/" + dest
elif func is "do_stage":
varmap = {}
varmap["${bindir}"] = "${STAGING_DIR}/${HOST_SYS}/bin"
varmap["${libdir}"] = "${STAGING_DIR}/${HOST_SYS}/lib"
varmap["${includedir}"] = "${STAGING_DIR}/${HOST_SYS}/include"
varmap["${datadir}"] = "${STAGING_DATADIR}"
matched = 0
for key in varmap.keys():
if dest.startswith(key):
dest = varmap[key] + "/" + dest[len(key):]
matched = 1
if not matched:
newline = None
return
else:
newline = None
return
newline["src"] = src
newline["dest"] = dest
return newline
def emit_line (func, line, d):
import copy
newline = copy.deepcopy(line)
newline = mangle(func, newline, d)
if not newline:
return None
str = ""
type = newline["type"]
mode = newline["mode"]
src = newline["src"]
dest = newline["dest"]
if type is "d":
str = "install -d "
if mode:
str += "-m %s " % mode
str += dest
elif type is "f":
if not src:
return None
if dest.endswith("/"):
str = "install -d "
str += dest + "\n"
str += "install "
else:
str = "install -D "
if mode:
str += "-m %s " % mode
str += src + " " + dest
del newline
return str

View File

@@ -22,8 +22,8 @@ Message handling infrastructure for bitbake
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys, bb
from bb import event
import sys, os, re, bb
from bb import utils, event
debug_level = {}
@@ -47,9 +47,9 @@ domain = bb.utils.Enum(
class MsgBase(bb.event.Event):
"""Base class for messages"""
def __init__(self, msg):
def __init__(self, msg, d ):
self._message = msg
event.Event.__init__(self)
event.Event.__init__(self, d)
class MsgDebug(MsgBase):
"""Debug Message"""
@@ -97,29 +97,33 @@ def set_debug_domains(domains):
#
def debug(level, domain, msg, fn = None):
bb.event.fire(MsgDebug(msg, None))
if not domain:
domain = 'default'
if debug_level[domain] >= level:
bb.event.fire(MsgDebug(msg), None)
print 'DEBUG: ' + msg
def note(level, domain, msg, fn = None):
bb.event.fire(MsgNote(msg, None))
if not domain:
domain = 'default'
if level == 1 or verbose or debug_level[domain] >= 1:
bb.event.fire(MsgNote(msg), None)
print 'NOTE: ' + msg
def warn(domain, msg, fn = None):
bb.event.fire(MsgWarn(msg), None)
bb.event.fire(MsgWarn(msg, None))
print 'WARNING: ' + msg
def error(domain, msg, fn = None):
bb.event.fire(MsgError(msg), None)
bb.event.fire(MsgError(msg, None))
print 'ERROR: ' + msg
def fatal(domain, msg, fn = None):
bb.event.fire(MsgFatal(msg), None)
print 'FATAL: ' + msg
bb.event.fire(MsgFatal(msg, None))
print 'ERROR: ' + msg
sys.exit(1)
def plain(msg, fn = None):
bb.event.fire(MsgPlain(msg), None)
bb.event.fire(MsgPlain(msg, None))
print msg

View File

@@ -80,34 +80,5 @@ def init(fn, data):
if h['supports'](fn):
return h['init'](data)
def resolve_file(fn, d):
if not os.path.isabs(fn):
fn = bb.which(bb.data.getVar("BBPATH", d, 1), fn)
if not fn:
raise IOError("file %s not found" % fn)
bb.msg.debug(2, bb.msg.domain.Parsing, "LOAD %s" % fn)
return fn
# Used by OpenEmbedded metadata
__pkgsplit_cache__={}
def vars_from_file(mypkg, d):
if not mypkg:
return (None, None, None)
if mypkg in __pkgsplit_cache__:
return __pkgsplit_cache__[mypkg]
myfile = os.path.splitext(os.path.basename(mypkg))
parts = myfile[0].split('_')
__pkgsplit_cache__[mypkg] = parts
if len(parts) > 3:
raise ParseError("Unable to generate default variables from the filename: %s (too many underscores)" % mypkg)
exp = 3 - len(parts)
tmplist = []
while exp != 0:
exp -= 1
tmplist.append(None)
parts.extend(tmplist)
return parts
from bb.parse.parse_py import __version__, ConfHandler, BBHandler
from parse_py import __version__, ConfHandler, BBHandler

View File

@@ -1,451 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
AbstractSyntaxTree classes for the Bitbake language
"""
# Copyright (C) 2003, 2004 Chris Larson
# Copyright (C) 2003, 2004 Phil Blundell
# Copyright (C) 2009 Holger Hans Peter Freyther
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import bb, re, string
from itertools import chain
__word__ = re.compile(r"\S+")
__parsed_methods__ = bb.methodpool.get_parsed_dict()
_bbversions_re = re.compile(r"\[(?P<from>[0-9]+)-(?P<to>[0-9]+)\]")
class StatementGroup(list):
def eval(self, data):
map(lambda x: x.eval(data), self)
class AstNode(object):
pass
class IncludeNode(AstNode):
def __init__(self, what_file, fn, lineno, force):
self.what_file = what_file
self.from_fn = fn
self.from_lineno = lineno
self.force = force
def eval(self, data):
"""
Include the file and evaluate the statements
"""
s = bb.data.expand(self.what_file, data)
bb.msg.debug(3, bb.msg.domain.Parsing, "CONF %s:%d: including %s" % (self.from_fn, self.from_lineno, s))
# TODO: Cache those includes... maybe not here though
if self.force:
bb.parse.ConfHandler.include(self.from_fn, s, data, "include required")
else:
bb.parse.ConfHandler.include(self.from_fn, s, data, False)
class ExportNode(AstNode):
def __init__(self, var):
self.var = var
def eval(self, data):
bb.data.setVarFlag(self.var, "export", 1, data)
class DataNode(AstNode):
"""
Various data related updates. For the sake of sanity
we have one class doing all this. This means that all
this need to be re-evaluated... we might be able to do
that faster with multiple classes.
"""
def __init__(self, groupd):
self.groupd = groupd
def getFunc(self, key, data):
if 'flag' in self.groupd and self.groupd['flag'] != None:
return bb.data.getVarFlag(key, self.groupd['flag'], data)
else:
return bb.data.getVar(key, data)
def eval(self, data):
groupd = self.groupd
key = groupd["var"]
if "exp" in groupd and groupd["exp"] != None:
bb.data.setVarFlag(key, "export", 1, data)
if "ques" in groupd and groupd["ques"] != None:
val = self.getFunc(key, data)
if val == None:
val = groupd["value"]
elif "colon" in groupd and groupd["colon"] != None:
e = data.createCopy()
bb.data.update_data(e)
val = bb.data.expand(groupd["value"], e)
elif "append" in groupd and groupd["append"] != None:
val = "%s %s" % ((self.getFunc(key, data) or ""), groupd["value"])
elif "prepend" in groupd and groupd["prepend"] != None:
val = "%s %s" % (groupd["value"], (self.getFunc(key, data) or ""))
elif "postdot" in groupd and groupd["postdot"] != None:
val = "%s%s" % ((self.getFunc(key, data) or ""), groupd["value"])
elif "predot" in groupd and groupd["predot"] != None:
val = "%s%s" % (groupd["value"], (self.getFunc(key, data) or ""))
else:
val = groupd["value"]
if 'flag' in groupd and groupd['flag'] != None:
bb.msg.debug(3, bb.msg.domain.Parsing, "setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
bb.data.setVarFlag(key, groupd['flag'], val, data)
elif groupd["lazyques"]:
assigned = bb.data.getVar("__lazy_assigned", data) or []
assigned.append(key)
bb.data.setVar("__lazy_assigned", assigned, data)
bb.data.setVarFlag(key, "defaultval", val, data)
else:
bb.data.setVar(key, val, data)
class MethodNode:
def __init__(self, func_name, body, lineno, fn):
self.func_name = func_name
self.body = body
self.fn = fn
self.lineno = lineno
def eval(self, data):
if self.func_name == "__anonymous":
funcname = ("__anon_%s_%s" % (self.lineno, self.fn.translate(string.maketrans('/.+-', '____'))))
if not funcname in bb.methodpool._parsed_fns:
text = "def %s(d):\n" % (funcname) + '\n'.join(self.body)
bb.methodpool.insert_method(funcname, text, self.fn)
anonfuncs = bb.data.getVar('__BBANONFUNCS', data) or []
anonfuncs.append(funcname)
bb.data.setVar('__BBANONFUNCS', anonfuncs, data)
else:
bb.data.setVarFlag(self.func_name, "func", 1, data)
bb.data.setVar(self.func_name, '\n'.join(self.body), data)
class PythonMethodNode(AstNode):
def __init__(self, root, body, fn):
self.root = root
self.body = body
self.fn = fn
def eval(self, data):
# Note we will add root to parsedmethods after having parse
# 'this' file. This means we will not parse methods from
# bb classes twice
if not self.root in __parsed_methods__:
text = '\n'.join(self.body)
bb.methodpool.insert_method(self.root, text, self.fn)
class MethodFlagsNode(AstNode):
def __init__(self, key, m):
self.key = key
self.m = m
def eval(self, data):
if bb.data.getVar(self.key, data):
# clean up old version of this piece of metadata, as its
# flags could cause problems
bb.data.setVarFlag(self.key, 'python', None, data)
bb.data.setVarFlag(self.key, 'fakeroot', None, data)
if self.m.group("py") is not None:
bb.data.setVarFlag(self.key, "python", "1", data)
else:
bb.data.delVarFlag(self.key, "python", data)
if self.m.group("fr") is not None:
bb.data.setVarFlag(self.key, "fakeroot", "1", data)
else:
bb.data.delVarFlag(self.key, "fakeroot", data)
class ExportFuncsNode(AstNode):
def __init__(self, fns, classes):
self.n = __word__.findall(fns)
self.classes = classes
def eval(self, data):
for f in self.n:
allvars = []
allvars.append(f)
allvars.append(self.classes[-1] + "_" + f)
vars = [[ allvars[0], allvars[1] ]]
if len(self.classes) > 1 and self.classes[-2] is not None:
allvars.append(self.classes[-2] + "_" + f)
vars = []
vars.append([allvars[2], allvars[1]])
vars.append([allvars[0], allvars[2]])
for (var, calledvar) in vars:
if bb.data.getVar(var, data) and not bb.data.getVarFlag(var, 'export_func', data):
continue
if bb.data.getVar(var, data):
bb.data.setVarFlag(var, 'python', None, data)
bb.data.setVarFlag(var, 'func', None, data)
for flag in [ "func", "python" ]:
if bb.data.getVarFlag(calledvar, flag, data):
bb.data.setVarFlag(var, flag, bb.data.getVarFlag(calledvar, flag, data), data)
for flag in [ "dirs" ]:
if bb.data.getVarFlag(var, flag, data):
bb.data.setVarFlag(calledvar, flag, bb.data.getVarFlag(var, flag, data), data)
if bb.data.getVarFlag(calledvar, "python", data):
bb.data.setVar(var, "\tbb.build.exec_func('" + calledvar + "', d)\n", data)
else:
bb.data.setVar(var, "\t" + calledvar + "\n", data)
bb.data.setVarFlag(var, 'export_func', '1', data)
class AddTaskNode(AstNode):
def __init__(self, func, before, after):
self.func = func
self.before = before
self.after = after
def eval(self, data):
var = self.func
if self.func[:3] != "do_":
var = "do_" + self.func
bb.data.setVarFlag(var, "task", 1, data)
bbtasks = bb.data.getVar('__BBTASKS', data) or []
if not var in bbtasks:
bbtasks.append(var)
bb.data.setVar('__BBTASKS', bbtasks, data)
existing = bb.data.getVarFlag(var, "deps", data) or []
if self.after is not None:
# set up deps for function
for entry in self.after.split():
if entry not in existing:
existing.append(entry)
bb.data.setVarFlag(var, "deps", existing, data)
if self.before is not None:
# set up things that depend on this func
for entry in self.before.split():
existing = bb.data.getVarFlag(entry, "deps", data) or []
if var not in existing:
bb.data.setVarFlag(entry, "deps", [var] + existing, data)
class BBHandlerNode(AstNode):
def __init__(self, fns):
self.hs = __word__.findall(fns)
def eval(self, data):
bbhands = bb.data.getVar('__BBHANDLERS', data) or []
for h in self.hs:
bbhands.append(h)
bb.data.setVarFlag(h, "handler", 1, data)
bb.data.setVar('__BBHANDLERS', bbhands, data)
class InheritNode(AstNode):
def __init__(self, files):
self.n = __word__.findall(files)
def eval(self, data):
bb.parse.BBHandler.inherit(self.n, data)
def handleInclude(statements, m, fn, lineno, force):
statements.append(IncludeNode(m.group(1), fn, lineno, force))
def handleExport(statements, m):
statements.append(ExportNode(m.group(1)))
def handleData(statements, groupd):
statements.append(DataNode(groupd))
def handleMethod(statements, func_name, lineno, fn, body):
statements.append(MethodNode(func_name, body, lineno, fn))
def handlePythonMethod(statements, root, body, fn):
statements.append(PythonMethodNode(root, body, fn))
def handleMethodFlags(statements, key, m):
statements.append(MethodFlagsNode(key, m))
def handleExportFuncs(statements, m, classes):
statements.append(ExportFuncsNode(m.group(1), classes))
def handleAddTask(statements, m):
func = m.group("func")
before = m.group("before")
after = m.group("after")
if func is None:
return
statements.append(AddTaskNode(func, before, after))
def handleBBHandlers(statements, m):
statements.append(BBHandlerNode(m.group(1)))
def handleInherit(statements, m):
files = m.group(1)
n = __word__.findall(files)
statements.append(InheritNode(m.group(1)))
def finalise(fn, d):
for lazykey in bb.data.getVar("__lazy_assigned", d) or ():
if bb.data.getVar(lazykey, d) is None:
val = bb.data.getVarFlag(lazykey, "defaultval", d)
bb.data.setVar(lazykey, val, d)
bb.data.expandKeys(d)
bb.data.update_data(d)
anonqueue = bb.data.getVar("__anonqueue", d, 1) or []
body = [x['content'] for x in anonqueue]
flag = { 'python' : 1, 'func' : 1 }
bb.data.setVar("__anonfunc", "\n".join(body), d)
bb.data.setVarFlags("__anonfunc", flag, d)
from bb import build
try:
t = bb.data.getVar('T', d)
bb.data.setVar('T', '${TMPDIR}/anonfunc/', d)
anonfuncs = bb.data.getVar('__BBANONFUNCS', d) or []
code = ""
for f in anonfuncs:
code = code + " %s(d)\n" % f
bb.data.setVar("__anonfunc", code, d)
build.exec_func("__anonfunc", d)
bb.data.delVar('T', d)
if t:
bb.data.setVar('T', t, d)
except Exception, e:
bb.msg.debug(1, bb.msg.domain.Parsing, "Exception when executing anonymous function: %s" % e)
raise
bb.data.delVar("__anonqueue", d)
bb.data.delVar("__anonfunc", d)
bb.data.update_data(d)
all_handlers = {}
for var in bb.data.getVar('__BBHANDLERS', d) or []:
# try to add the handler
handler = bb.data.getVar(var,d)
bb.event.register(var, handler)
tasklist = bb.data.getVar('__BBTASKS', d) or []
bb.build.add_tasks(tasklist, d)
bb.event.fire(bb.event.RecipeParsed(fn), d)
def _create_variants(datastores, names, function):
def create_variant(name, orig_d, arg = None):
new_d = bb.data.createCopy(orig_d)
function(arg or name, new_d)
datastores[name] = new_d
for variant, variant_d in datastores.items():
for name in names:
if not variant:
# Based on main recipe
create_variant(name, variant_d)
else:
create_variant("%s-%s" % (variant, name), variant_d, name)
def _expand_versions(versions):
def expand_one(version, start, end):
for i in xrange(start, end + 1):
ver = _bbversions_re.sub(str(i), version, 1)
yield ver
versions = iter(versions)
while True:
try:
version = versions.next()
except StopIteration:
break
range_ver = _bbversions_re.search(version)
if not range_ver:
yield version
else:
newversions = expand_one(version, int(range_ver.group("from")),
int(range_ver.group("to")))
versions = chain(newversions, versions)
def multi_finalize(fn, d):
safe_d = d
d = bb.data.createCopy(safe_d)
try:
finalise(fn, d)
except bb.parse.SkipPackage:
bb.data.setVar("__SKIPPED", True, d)
datastores = {"": safe_d}
versions = (d.getVar("BBVERSIONS", True) or "").split()
if versions:
pv = orig_pv = d.getVar("PV", True)
baseversions = {}
def verfunc(ver, d, pv_d = None):
if pv_d is None:
pv_d = d
overrides = d.getVar("OVERRIDES", True).split(":")
pv_d.setVar("PV", ver)
overrides.append(ver)
bpv = baseversions.get(ver) or orig_pv
pv_d.setVar("BPV", bpv)
overrides.append(bpv)
d.setVar("OVERRIDES", ":".join(overrides))
versions = list(_expand_versions(versions))
for pos, version in enumerate(list(versions)):
try:
pv, bpv = version.split(":", 2)
except ValueError:
pass
else:
versions[pos] = pv
baseversions[pv] = bpv
if pv in versions and not baseversions.get(pv):
versions.remove(pv)
else:
pv = versions.pop()
# This is necessary because our existing main datastore
# has already been finalized with the old PV, we need one
# that's been finalized with the new PV.
d = bb.data.createCopy(safe_d)
verfunc(pv, d, safe_d)
try:
finalise(fn, d)
except bb.parse.SkipPackage:
bb.data.setVar("__SKIPPED", True, d)
_create_variants(datastores, versions, verfunc)
extended = d.getVar("BBCLASSEXTEND", True) or ""
if extended:
pn = d.getVar("PN", True)
def extendfunc(name, d):
d.setVar("PN", "%s-%s" % (pn, name))
bb.parse.BBHandler.inherit([name], d)
safe_d.setVar("BBCLASSEXTEND", extended)
_create_variants(datastores, extended.split(), extendfunc)
for variant, variant_d in datastores.items():
if variant:
try:
finalise(fn, variant_d)
except bb.parse.SkipPackage:
bb.data.setVar("__SKIPPED", True, variant_d)
if len(datastores) > 1:
variants = filter(None, datastores.keys())
safe_d.setVar("__VARIANTS", " ".join(variants))
datastores[""] = d
return datastores

View File

@@ -25,15 +25,12 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import re, bb, os, sys, time, string
import re, bb, os, sys, time
import bb.fetch, bb.build, bb.utils
from bb import data, fetch
from bb import data, fetch, methodpool
from ConfHandler import include, init
from bb.parse import ParseError, resolve_file, ast
# For compatibility
from bb.parse import vars_from_file
from ConfHandler import include, localpath, obtain, init
from bb.parse import ParseError
__func_start_regexp__ = re.compile( r"(((?P<py>python)|(?P<fr>fakeroot))\s*)*(?P<func>[\w\.\-\+\{\}\$]+)?\s*\(\s*\)\s*{$" )
__inherit_regexp__ = re.compile( r"inherit\s+(.+)" )
@@ -42,7 +39,7 @@ __addtask_regexp__ = re.compile("addtask\s+(?P<func>\w+)\s*((before\s*(?P<
__addhandler_regexp__ = re.compile( r"addhandler\s+(.+)" )
__def_regexp__ = re.compile( r"def\s+(\w+).*:" )
__python_func_regexp__ = re.compile( r"(\s+.*)|(^$)" )
__word__ = re.compile(r"\S+")
__infunc__ = ""
__inpython__ = False
@@ -50,8 +47,6 @@ __body__ = []
__classname__ = ""
classes = [ None, ]
cached_statements = {}
# We need to indicate EOF to the feeder. This code is so messy that
# factoring it out to a close_parse_file method is out of question.
# We will use the IN_PYTHON_EOF as an indicator to just close the method
@@ -59,10 +54,11 @@ cached_statements = {}
# The two parts using it are tightly integrated anyway
IN_PYTHON_EOF = -9999999999999
__parsed_methods__ = methodpool.get_parsed_dict()
def supports(fn, d):
return fn[-3:] == ".bb" or fn[-8:] == ".bbclass" or fn[-4:] == ".inc"
localfn = localpath(fn, d)
return localfn[-3:] == ".bb" or localfn[-8:] == ".bbclass" or localfn[-4:] == ".inc"
def inherit(files, d):
__inherit_cache = data.getVar('__inherit_cache', d) or []
@@ -80,38 +76,13 @@ def inherit(files, d):
include(fn, file, d, "inherit")
__inherit_cache = data.getVar('__inherit_cache', d) or []
def get_statements(filename, absolsute_filename, base_name):
global cached_statements
try:
return cached_statements[absolsute_filename]
except KeyError:
file = open(absolsute_filename, 'r')
statements = ast.StatementGroup()
lineno = 0
while 1:
lineno = lineno + 1
s = file.readline()
if not s: break
s = s.rstrip()
feeder(lineno, s, filename, base_name, statements)
if __inpython__:
# add a blank line to close out any python definition
feeder(IN_PYTHON_EOF, "", filename, base_name, statements)
if filename.endswith(".bbclass") or filename.endswith(".inc"):
cached_statements[absolsute_filename] = statements
return statements
def handle(fn, d, include):
def handle(fn, d, include = 0):
global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __residue__
__body__ = []
__infunc__ = ""
__classname__ = ""
__residue__ = []
if include == 0:
bb.msg.debug(2, bb.msg.domain.Parsing, "BB " + fn + ": handle(data)")
else:
@@ -134,41 +105,106 @@ def handle(fn, d, include):
else:
oldfile = None
abs_fn = resolve_file(fn, d)
fn = obtain(fn, d)
bbpath = (data.getVar('BBPATH', d, 1) or '').split(':')
if not os.path.isabs(fn):
f = None
for p in bbpath:
j = os.path.join(p, fn)
if os.access(j, os.R_OK):
abs_fn = j
f = open(j, 'r')
break
if f is None:
raise IOError("file not found")
else:
f = open(fn,'r')
abs_fn = fn
if ext != ".bbclass":
dname = os.path.dirname(abs_fn)
if bbpath[0] != dname:
bbpath.insert(0, dname)
data.setVar('BBPATH', ":".join(bbpath), d)
if include:
bb.parse.mark_dependency(d, abs_fn)
# actual loading
statements = get_statements(fn, abs_fn, base_name)
# DONE WITH PARSING... time to evaluate
if ext != ".bbclass":
data.setVar('FILE', fn, d)
statements.eval(d)
lineno = 0
while 1:
lineno = lineno + 1
s = f.readline()
if not s: break
s = s.rstrip()
feeder(lineno, s, fn, base_name, d)
if __inpython__:
# add a blank line to close out any python definition
feeder(IN_PYTHON_EOF, "", fn, base_name, d)
if ext == ".bbclass":
classes.remove(__classname__)
else:
if include == 0:
return ast.multi_finalize(fn, d)
data.expandKeys(d)
data.update_data(d)
anonqueue = data.getVar("__anonqueue", d, 1) or []
body = [x['content'] for x in anonqueue]
flag = { 'python' : 1, 'func' : 1 }
data.setVar("__anonfunc", "\n".join(body), d)
data.setVarFlags("__anonfunc", flag, d)
from bb import build
try:
t = data.getVar('T', d)
data.setVar('T', '${TMPDIR}/', d)
build.exec_func("__anonfunc", d)
data.delVar('T', d)
if t:
data.setVar('T', t, d)
except Exception, e:
bb.msg.debug(1, bb.msg.domain.Parsing, "Exception when executing anonymous function: %s" % e)
raise
data.delVar("__anonqueue", d)
data.delVar("__anonfunc", d)
set_additional_vars(fn, d, include)
data.update_data(d)
all_handlers = {}
for var in data.getVar('__BBHANDLERS', d) or []:
# try to add the handler
handler = data.getVar(var,d)
bb.event.register(var, handler)
tasklist = data.getVar('__BBTASKS', d) or []
bb.build.add_tasks(tasklist, d)
bbpath.pop(0)
if oldfile:
bb.data.setVar("FILE", oldfile, d)
# we have parsed the bb class now
if ext == ".bbclass" or ext == ".inc":
bb.methodpool.get_parsed_dict()[base_name] = 1
__parsed_methods__[base_name] = 1
return d
def feeder(lineno, s, fn, root, statements):
def feeder(lineno, s, fn, root, d):
global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__,__infunc__, __body__, classes, bb, __residue__
if __infunc__:
if s == '}':
__body__.append('')
ast.handleMethod(statements, __infunc__, lineno, fn, __body__)
data.setVar(__infunc__, '\n'.join(__body__), d)
data.setVarFlag(__infunc__, "func", 1, d)
if __infunc__ == "__anonymous":
anonqueue = bb.data.getVar("__anonqueue", d) or []
anonitem = {}
anonitem["content"] = bb.data.getVar("__anonymous", d)
anonitem["flags"] = bb.data.getVarFlags("__anonymous", d)
anonqueue.append(anonitem)
bb.data.setVar("__anonqueue", anonqueue, d)
bb.data.delVarFlags("__anonymous", d)
bb.data.delVar("__anonymous", d)
__infunc__ = ""
__body__ = []
else:
@@ -181,7 +217,19 @@ def feeder(lineno, s, fn, root, statements):
__body__.append(s)
return
else:
ast.handlePythonMethod(statements, root, __body__, fn)
# Note we will add root to parsedmethods after having parse
# 'this' file. This means we will not parse methods from
# bb classes twice
if not root in __parsed_methods__:
text = '\n'.join(__body__)
methodpool.insert_method( root, text, fn )
funcs = data.getVar('__functions__', d) or {}
if not funcs.has_key( root ):
funcs[root] = text
else:
funcs[root] = "%s\n%s" % (funcs[root], text)
data.setVar('__functions__', funcs, d)
__body__ = []
__inpython__ = False
@@ -202,7 +250,20 @@ def feeder(lineno, s, fn, root, statements):
m = __func_start_regexp__.match(s)
if m:
__infunc__ = m.group("func") or "__anonymous"
ast.handleMethodFlags(statements, __infunc__, m)
key = __infunc__
if data.getVar(key, d):
# clean up old version of this piece of metadata, as its
# flags could cause problems
data.setVarFlag(key, 'python', None, d)
data.setVarFlag(key, 'fakeroot', None, d)
if m.group("py") is not None:
data.setVarFlag(key, "python", "1", d)
else:
data.delVarFlag(key, "python", d)
if m.group("fr") is not None:
data.setVarFlag(key, "fakeroot", "1", d)
else:
data.delVarFlag(key, "fakeroot", d)
return
m = __def_regexp__.match(s)
@@ -213,26 +274,141 @@ def feeder(lineno, s, fn, root, statements):
m = __export_func_regexp__.match(s)
if m:
ast.handleExportFuncs(statements, m, classes)
fns = m.group(1)
n = __word__.findall(fns)
for f in n:
allvars = []
allvars.append(f)
allvars.append(classes[-1] + "_" + f)
vars = [[ allvars[0], allvars[1] ]]
if len(classes) > 1 and classes[-2] is not None:
allvars.append(classes[-2] + "_" + f)
vars = []
vars.append([allvars[2], allvars[1]])
vars.append([allvars[0], allvars[2]])
for (var, calledvar) in vars:
if data.getVar(var, d) and not data.getVarFlag(var, 'export_func', d):
continue
if data.getVar(var, d):
data.setVarFlag(var, 'python', None, d)
data.setVarFlag(var, 'func', None, d)
for flag in [ "func", "python" ]:
if data.getVarFlag(calledvar, flag, d):
data.setVarFlag(var, flag, data.getVarFlag(calledvar, flag, d), d)
for flag in [ "dirs" ]:
if data.getVarFlag(var, flag, d):
data.setVarFlag(calledvar, flag, data.getVarFlag(var, flag, d), d)
if data.getVarFlag(calledvar, "python", d):
data.setVar(var, "\tbb.build.exec_func('" + calledvar + "', d)\n", d)
else:
data.setVar(var, "\t" + calledvar + "\n", d)
data.setVarFlag(var, 'export_func', '1', d)
return
m = __addtask_regexp__.match(s)
if m:
ast.handleAddTask(statements, m)
func = m.group("func")
before = m.group("before")
after = m.group("after")
if func is None:
return
var = "do_" + func
data.setVarFlag(var, "task", 1, d)
bbtasks = data.getVar('__BBTASKS', d) or []
if not var in bbtasks:
bbtasks.append(var)
data.setVar('__BBTASKS', bbtasks, d)
existing = data.getVarFlag(var, "deps", d) or []
if after is not None:
# set up deps for function
for entry in after.split():
if entry not in existing:
existing.append(entry)
data.setVarFlag(var, "deps", existing, d)
if before is not None:
# set up things that depend on this func
for entry in before.split():
existing = data.getVarFlag(entry, "deps", d) or []
if var not in existing:
data.setVarFlag(entry, "deps", [var] + existing, d)
return
m = __addhandler_regexp__.match(s)
if m:
ast.handleBBHandlers(statements, m)
fns = m.group(1)
hs = __word__.findall(fns)
bbhands = data.getVar('__BBHANDLERS', d) or []
for h in hs:
bbhands.append(h)
data.setVarFlag(h, "handler", 1, d)
data.setVar('__BBHANDLERS', bbhands, d)
return
m = __inherit_regexp__.match(s)
if m:
ast.handleInherit(statements, m)
files = m.group(1)
n = __word__.findall(files)
inherit(n, d)
return
from bb.parse import ConfHandler
return ConfHandler.feeder(lineno, s, fn, statements)
return ConfHandler.feeder(lineno, s, fn, d)
__pkgsplit_cache__={}
def vars_from_file(mypkg, d):
if not mypkg:
return (None, None, None)
if mypkg in __pkgsplit_cache__:
return __pkgsplit_cache__[mypkg]
myfile = os.path.splitext(os.path.basename(mypkg))
parts = myfile[0].split('_')
__pkgsplit_cache__[mypkg] = parts
if len(parts) > 3:
raise ParseError("Unable to generate default variables from the filename: %s (too many underscores)" % mypkg)
exp = 3 - len(parts)
tmplist = []
while exp != 0:
exp -= 1
tmplist.append(None)
parts.extend(tmplist)
return parts
def set_additional_vars(file, d, include):
"""Deduce rest of variables, e.g. ${A} out of ${SRC_URI}"""
return
# Nothing seems to use this variable
#bb.msg.debug(2, bb.msg.domain.Parsing, "BB %s: set_additional_vars" % file)
#src_uri = data.getVar('SRC_URI', d, 1)
#if not src_uri:
# return
#a = (data.getVar('A', d, 1) or '').split()
#from bb import fetch
#try:
# ud = fetch.init(src_uri.split(), d)
# a += fetch.localpaths(d, ud)
#except fetch.NoMethodError:
# pass
#except bb.MalformedUrl,e:
# raise ParseError("Unable to generate local paths for SRC_URI due to malformed uri: %s" % e)
#del fetch
#data.setVar('A', " ".join(a), d)
# Add us to the handlers list
from bb.parse import handlers

View File

@@ -25,25 +25,70 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import re, bb.data, os, sys
from bb.parse import ParseError, resolve_file, ast
from bb.parse import ParseError
#__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}]+)\s*(?P<colon>:)?(?P<ques>\?)?=\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}/]+)(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?\s*((?P<colon>:=)|(?P<lazyques>\?\?=)|(?P<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}/]+)(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?\s*((?P<colon>:=)|(?P<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
__include_regexp__ = re.compile( r"include\s+(.+)" )
__require_regexp__ = re.compile( r"require\s+(.+)" )
__export_regexp__ = re.compile( r"export\s+(.+)" )
def init(data):
topdir = bb.data.getVar('TOPDIR', data)
if not topdir:
topdir = os.getcwd()
bb.data.setVar('TOPDIR', topdir, data)
if not bb.data.getVar('TOPDIR', data):
bb.data.setVar('TOPDIR', os.getcwd(), data)
if not bb.data.getVar('BBPATH', data):
bb.fatal("The BBPATH environment variable must be set")
bb.data.setVar('BBPATH', os.path.join(sys.prefix, 'share', 'bitbake'), data)
def supports(fn, d):
return fn[-5:] == ".conf"
return localpath(fn, d)[-5:] == ".conf"
def localpath(fn, d):
if os.path.exists(fn):
return fn
if "://" not in fn:
return fn
localfn = None
try:
localfn = bb.fetch.localpath(fn, d, False)
except bb.MalformedUrl:
pass
if not localfn:
return fn
return localfn
def obtain(fn, data):
import sys, bb
fn = bb.data.expand(fn, data)
localfn = bb.data.expand(localpath(fn, data), data)
if localfn != fn:
dldir = bb.data.getVar('DL_DIR', data, 1)
if not dldir:
bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: DL_DIR not defined")
return localfn
bb.mkdirhier(dldir)
try:
bb.fetch.init([fn], data)
except bb.fetch.NoMethodError:
(type, value, traceback) = sys.exc_info()
bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: no method: %s" % value)
return localfn
try:
bb.fetch.go(data)
except bb.fetch.MissingParameterError:
(type, value, traceback) = sys.exc_info()
bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: missing parameters: %s" % value)
return localfn
except bb.fetch.FetchError:
(type, value, traceback) = sys.exc_info()
bb.msg.debug(1, bb.msg.domain.Parsing, "obtain: failed: %s" % value)
return localfn
return localfn
def include(oldfn, fn, data, error_out):
"""
@@ -57,13 +102,6 @@ def include(oldfn, fn, data, error_out):
fn = bb.data.expand(fn, data)
oldfn = bb.data.expand(oldfn, data)
if not os.path.isabs(fn):
dname = os.path.dirname(oldfn)
bbpath = "%s:%s" % (dname, bb.data.getVar("BBPATH", data, 1))
abs_fn = bb.which(bbpath, fn)
if abs_fn:
fn = abs_fn
from bb.parse import handle
try:
ret = handle(fn, data, True)
@@ -72,22 +110,42 @@ def include(oldfn, fn, data, error_out):
raise ParseError("Could not %(error_out)s file %(fn)s" % vars() )
bb.msg.debug(2, bb.msg.domain.Parsing, "CONF file '%s' not found" % fn)
def handle(fn, data, include):
def handle(fn, data, include = 0):
if include:
inc_string = "including"
else:
inc_string = "reading"
init(data)
if include == 0:
bb.data.inheritFromOS(data)
oldfile = None
else:
oldfile = bb.data.getVar('FILE', data)
abs_fn = resolve_file(fn, data)
f = open(abs_fn, 'r')
fn = obtain(fn, data)
if not os.path.isabs(fn):
f = None
bbpath = bb.data.getVar("BBPATH", data, 1) or []
for p in bbpath.split(":"):
currname = os.path.join(p, fn)
if os.access(currname, os.R_OK):
f = open(currname, 'r')
abs_fn = currname
bb.msg.debug(2, bb.msg.domain.Parsing, "CONF %s %s" % (inc_string, currname))
break
if f is None:
raise IOError("file '%s' not found" % fn)
else:
f = open(fn,'r')
bb.msg.debug(1, bb.msg.domain.Parsing, "CONF %s %s" % (inc_string,fn))
abs_fn = fn
if include:
bb.parse.mark_dependency(data, abs_fn)
statements = ast.StatementGroup()
lineno = 0
bb.data.setVar('FILE', fn, data)
while 1:
lineno = lineno + 1
s = f.readline()
@@ -100,36 +158,66 @@ def handle(fn, data, include):
s2 = f.readline()[:-1].strip()
lineno = lineno + 1
s = s[:-1] + s2
feeder(lineno, s, fn, statements)
feeder(lineno, s, fn, data)
# DONE WITH PARSING... time to evaluate
bb.data.setVar('FILE', fn, data)
statements.eval(data)
if oldfile:
bb.data.setVar('FILE', oldfile, data)
return data
def feeder(lineno, s, fn, statements):
def feeder(lineno, s, fn, data):
def getFunc(groupd, key, data):
if 'flag' in groupd and groupd['flag'] != None:
return bb.data.getVarFlag(key, groupd['flag'], data)
else:
return bb.data.getVar(key, data)
m = __config_regexp__.match(s)
if m:
groupd = m.groupdict()
ast.handleData(statements, groupd)
key = groupd["var"]
if "exp" in groupd and groupd["exp"] != None:
bb.data.setVarFlag(key, "export", 1, data)
if "ques" in groupd and groupd["ques"] != None:
val = getFunc(groupd, key, data)
if val == None:
val = groupd["value"]
elif "colon" in groupd and groupd["colon"] != None:
e = data.createCopy()
bb.data.update_data(e)
val = bb.data.expand(groupd["value"], e)
elif "append" in groupd and groupd["append"] != None:
val = "%s %s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
elif "prepend" in groupd and groupd["prepend"] != None:
val = "%s %s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
elif "postdot" in groupd and groupd["postdot"] != None:
val = "%s%s" % ((getFunc(groupd, key, data) or ""), groupd["value"])
elif "predot" in groupd and groupd["predot"] != None:
val = "%s%s" % (groupd["value"], (getFunc(groupd, key, data) or ""))
else:
val = groupd["value"]
if 'flag' in groupd and groupd['flag'] != None:
bb.msg.debug(3, bb.msg.domain.Parsing, "setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
bb.data.setVarFlag(key, groupd['flag'], val, data)
else:
bb.data.setVar(key, val, data)
return
m = __include_regexp__.match(s)
if m:
ast.handleInclude(statements, m, fn, lineno, False)
s = bb.data.expand(m.group(1), data)
bb.msg.debug(3, bb.msg.domain.Parsing, "CONF %s:%d: including %s" % (fn, lineno, s))
include(fn, s, data, False)
return
m = __require_regexp__.match(s)
if m:
ast.handleInclude(statements, m, fn, lineno, True)
s = bb.data.expand(m.group(1), data)
include(fn, s, data, "include required")
return
m = __export_regexp__.match(s)
if m:
ast.handleExport(statements, m)
bb.data.setVarFlag(m.group(1), "export", 1, data)
return
raise ParseError("%s:%d: unparsed line: '%s'" % (fn, lineno, s));

View File

@@ -69,17 +69,6 @@ class PersistData:
"""
self.connection.execute("DROP TABLE IF EXISTS %s;" % domain)
def getKeyValues(self, domain):
"""
Return a list of key + value pairs for a domain
"""
ret = {}
data = self.connection.execute("SELECT key, value from %s;" % domain)
for row in data:
ret[str(row[0])] = str(row[1])
return ret
def getValue(self, domain, key):
"""
Return the value of a key for a domain

View File

@@ -21,7 +21,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import re
import os, re
from bb import data, utils
import bb
@@ -50,27 +50,19 @@ def sortPriorities(pn, dataCache, pkg_pn = None):
if preference not in priorities[priority]:
priorities[priority][preference] = []
priorities[priority][preference].append(f)
pri_list = priorities.keys()
pri_list.sort(lambda a, b: a - b)
tmp_pn = []
for pri in sorted(priorities, lambda a, b: a - b):
for pri in pri_list:
pref_list = priorities[pri].keys()
pref_list.sort(lambda a, b: b - a)
tmp_pref = []
for pref in sorted(priorities[pri], lambda a, b: b - a):
for pref in pref_list:
tmp_pref.extend(priorities[pri][pref])
tmp_pn = [tmp_pref] + tmp_pn
return tmp_pn
def preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r):
"""
Check if the version pe,pv,pr is the preferred one.
If there is preferred version defined and ends with '%', then pv has to start with that version after removing the '%'
"""
if (pr == preferred_r or preferred_r == None):
if (pe == preferred_e or preferred_e == None):
if preferred_v == pv:
return True
if preferred_v != None and preferred_v.endswith('%') and pv.startswith(preferred_v[:len(preferred_v)-1]):
return True
return False
def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
"""
@@ -104,7 +96,7 @@ def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
for file_set in pkg_pn:
for f in file_set:
pe,pv,pr = dataCache.pkg_pepvpr[f]
if preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r):
if preferred_v == pv and (preferred_r == pr or preferred_r == None) and (preferred_e == pe or preferred_e == None):
preferred_file = f
preferred_ver = (pe, pv, pr)
break
@@ -192,14 +184,14 @@ def _filterProviders(providers, item, cfgData, dataCache):
bb.msg.debug(1, bb.msg.domain.Provider, "providers for %s are: %s" % (item, pkg_pn.keys()))
# First add PREFERRED_VERSIONS
for pn in pkg_pn:
for pn in pkg_pn.keys():
sortpkg_pn[pn] = sortPriorities(pn, dataCache, pkg_pn)
preferred_versions[pn] = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item)
if preferred_versions[pn][1]:
eligible.append(preferred_versions[pn][1])
# Now add latest verisons
for pn in sortpkg_pn:
for pn in pkg_pn.keys():
if pn in preferred_versions and preferred_versions[pn][1]:
continue
preferred_versions[pn] = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[pn][0])
@@ -268,10 +260,9 @@ def filterProvidersRunTime(providers, item, cfgData, dataCache):
pn = dataCache.pkg_fn[p]
provides = dataCache.pn_provides[pn]
for provide in provides:
bb.msg.note(2, bb.msg.domain.Provider, "checking PREFERRED_PROVIDER_%s" % (provide))
prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % provide, cfgData, 1)
if prefervar == pn:
var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar)
var = "PREFERRED_PROVIDERS_%s = %s" % (provide, prefervar)
bb.msg.note(2, bb.msg.domain.Provider, "selecting %s to satisfy runtime %s due to %s" % (pn, item, var))
preferred_vars.append(var)
eligible.remove(p)
@@ -282,14 +273,12 @@ def filterProvidersRunTime(providers, item, cfgData, dataCache):
numberPreferred = len(preferred)
if numberPreferred > 1:
bb.msg.error(bb.msg.domain.Provider, "Conflicting PREFERRED_PROVIDER entries were found which resulted in an attempt to select multiple providers (%s) for runtime dependecy %s\nThe entries resulting in this conflict were: %s" % (preferred, item, preferred_vars))
bb.msg.error(bb.msg.domain.Provider, "Conflicting PREFERRED_PROVIDERS entries were found which resulted in an attempt to select multiple providers (%s) for runtime dependecy %s\nThe entries resulting in this conflict were: %s" % (preferred, item, preferred_vars))
bb.msg.debug(1, bb.msg.domain.Provider, "sorted providers for %s are: %s" % (item, eligible))
return eligible, numberPreferred
regexp_cache = {}
def getRuntimeProviders(dataCache, rdepend):
"""
Return any providers of runtime dependency
@@ -308,15 +297,11 @@ def getRuntimeProviders(dataCache, rdepend):
# Only search dynamic packages if we can't find anything in other variables
for pattern in dataCache.packages_dynamic:
pattern = pattern.replace('+', "\+")
if pattern in regexp_cache:
regexp = regexp_cache[pattern]
else:
try:
regexp = re.compile(pattern)
except:
bb.msg.error(bb.msg.domain.Provider, "Error parsing re expression: %s" % pattern)
raise
regexp_cache[pattern] = regexp
try:
regexp = re.compile(pattern)
except:
bb.msg.error(bb.msg.domain.Provider, "Error parsing re expression: %s" % pattern)
raise
if regexp.match(rdepend):
rproviders += dataCache.packages_dynamic[pattern]

View File

@@ -23,10 +23,10 @@ Handles preparation and execution of a queue of tasks
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from bb import msg, data, event, mkdirhier, utils
from sets import Set
import bb, os, sys
import signal
import stat
import fcntl
class TaskFailure(Exception):
"""Exception raised when a task in a runqueue fails"""
@@ -38,38 +38,20 @@ class RunQueueStats:
"""
Holds statistics on the tasks handled by the associated runQueue
"""
def __init__(self, total):
def __init__(self):
self.completed = 0
self.skipped = 0
self.failed = 0
self.active = 0
self.total = total
def taskFailed(self):
self.active = self.active - 1
self.failed = self.failed + 1
def taskCompleted(self, number = 1):
self.active = self.active - number
self.completed = self.completed + number
def taskSkipped(self, number = 1):
self.active = self.active + number
self.skipped = self.skipped + number
def taskActive(self):
self.active = self.active + 1
# These values indicate the next step due to be run in the
# runQueue state machine
runQueuePrepare = 2
runQueueRunInit = 3
runQueueRunning = 4
runQueueFailed = 6
runQueueCleanUp = 7
runQueueComplete = 8
runQueueChildProcess = 9
class RunQueueScheduler:
"""
Control the order tasks are scheduled in.
@@ -161,9 +143,9 @@ class RunQueue:
self.cooker = cooker
self.dataCache = dataCache
self.taskData = taskData
self.cfgData = cfgData
self.targets = targets
self.cfgdata = cfgData
self.number_tasks = int(bb.data.getVar("BB_NUMBER_THREADS", cfgData, 1) or 1)
self.multi_provider_whitelist = (bb.data.getVar("MULTI_PROVIDER_WHITELIST", cfgData, 1) or "").split()
self.scheduler = bb.data.getVar("BB_SCHEDULER", cfgData, 1) or "speed"
@@ -171,20 +153,11 @@ class RunQueue:
self.stampwhitelist = bb.data.getVar("BB_STAMP_WHITELIST", cfgData, 1) or ""
def reset_runqueue(self):
self.runq_fnid = []
self.runq_task = []
self.runq_depends = []
self.runq_revdeps = []
self.state = runQueuePrepare
def runq_depends_names(self, ids):
import re
ret = []
for id in self.runq_depends[ids]:
nam = os.path.basename(self.get_user_idstring(id))
nam = re.sub("_[^,]*,", ",", nam)
ret.extend([nam])
return ret
def get_user_idstring(self, task):
fn = self.taskData.fn_index[self.runq_fnid[task]]
@@ -256,7 +229,7 @@ class RunQueue:
valid_chains.append(new_chain)
msgs.append("Dependency loop #%d found:\n" % len(valid_chains))
for dep in new_chain:
msgs.append(" Task %s (%s) (dependent Tasks %s)\n" % (dep, self.get_user_idstring(dep), self.runq_depends_names(dep)))
msgs.append(" Task %s (%s) (depends: %s)\n" % (dep, self.get_user_idstring(dep), self.runq_depends[dep]))
msgs.append("\n")
if len(valid_chains) > 10:
msgs.append("Aborted dependency loops search after 10 matches.\n")
@@ -349,10 +322,9 @@ class RunQueue:
to optimise the execution order.
"""
depends = []
runq_build = []
recursive_tdepends = {}
runq_recrdepends = []
tdepends_fnid = {}
taskData = self.taskData
@@ -364,51 +336,20 @@ class RunQueue:
# Step A - Work out a list of tasks to run
#
# Taskdata gives us a list of possible providers for every build and run
# target ordered by priority. It also gives information on each of those
# providers.
# Taskdata gives us a list of possible providers for a every target
# ordered by priority (build_targets, run_targets). It also gives
# information on each of those providers.
#
# To create the actual list of tasks to execute we fix the list of
# providers and then resolve the dependencies into task IDs. This
# process is repeated for each type of dependency (tdepends, deptask,
# rdeptast, recrdeptask, idepends).
def add_build_dependencies(depids, tasknames, depends):
for depid in depids:
# Won't be in build_targets if ASSUME_PROVIDED
if depid not in taskData.build_targets:
continue
depdata = taskData.build_targets[depid][0]
if depdata is None:
continue
dep = taskData.fn_index[depdata]
for taskname in tasknames:
taskid = taskData.gettask_id(dep, taskname, False)
if taskid is not None:
depends.append(taskid)
def add_runtime_dependencies(depids, tasknames, depends):
for depid in depids:
if depid not in taskData.run_targets:
continue
depdata = taskData.run_targets[depid][0]
if depdata is None:
continue
dep = taskData.fn_index[depdata]
for taskname in tasknames:
taskid = taskData.gettask_id(dep, taskname, False)
if taskid is not None:
depends.append(taskid)
for task in range(len(taskData.tasks_name)):
depends = []
recrdepends = []
fnid = taskData.tasks_fnid[task]
fn = taskData.fn_index[fnid]
task_deps = self.dataCache.task_deps[fn]
bb.msg.debug(2, bb.msg.domain.RunQueue, "Processing %s:%s" %(fn, taskData.tasks_name[task]))
if fnid not in taskData.failed_fnids:
# Resolve task internal dependencies
@@ -422,7 +363,14 @@ class RunQueue:
# (makes sure sometask runs after someothertask of all DEPENDS)
if 'deptask' in task_deps and taskData.tasks_name[task] in task_deps['deptask']:
tasknames = task_deps['deptask'][taskData.tasks_name[task]].split()
add_build_dependencies(taskData.depids[fnid], tasknames, depends)
for depid in taskData.depids[fnid]:
# Won't be in build_targets if ASSUME_PROVIDED
if depid in taskData.build_targets:
depdata = taskData.build_targets[depid][0]
if depdata is not None:
dep = taskData.fn_index[depdata]
for taskname in tasknames:
depends.append(taskData.gettask_id(dep, taskname))
# Resolve 'rdeptask' dependencies
#
@@ -430,14 +378,17 @@ class RunQueue:
# (makes sure sometask runs after someothertask of all RDEPENDS)
if 'rdeptask' in task_deps and taskData.tasks_name[task] in task_deps['rdeptask']:
taskname = task_deps['rdeptask'][taskData.tasks_name[task]]
add_runtime_dependencies(taskData.rdepids[fnid], [taskname], depends)
for depid in taskData.rdepids[fnid]:
if depid in taskData.run_targets:
depdata = taskData.run_targets[depid][0]
if depdata is not None:
dep = taskData.fn_index[depdata]
depends.append(taskData.gettask_id(dep, taskname))
# Resolve inter-task dependencies
#
# e.g. do_sometask[depends] = "targetname:do_someothertask"
# (makes sure sometask runs after targetname's someothertask)
if fnid not in tdepends_fnid:
tdepends_fnid[fnid] = set()
idepends = taskData.tasks_idepends[task]
for (depid, idependtask) in idepends:
if depid in taskData.build_targets:
@@ -445,22 +396,122 @@ class RunQueue:
depdata = taskData.build_targets[depid][0]
if depdata is not None:
dep = taskData.fn_index[depdata]
taskid = taskData.gettask_id(dep, idependtask)
depends.append(taskid)
if depdata != fnid:
tdepends_fnid[fnid].add(taskid)
depends.append(taskData.gettask_id(dep, idependtask))
# Create a list of recursive dependent tasks (from tdepends) and cache
def get_recursive_tdepends(task):
if not task:
return []
if task in recursive_tdepends:
return recursive_tdepends[task]
# Resolve recursive 'recrdeptask' dependencies (A)
fnid = taskData.tasks_fnid[task]
taskids = taskData.gettask_ids(fnid)
rectdepends = taskids
nextdeps = taskids
while len(nextdeps) != 0:
newdeps = []
for nextdep in nextdeps:
for tdepend in taskData.tasks_tdepends[nextdep]:
if tdepend not in rectdepends:
rectdepends.append(tdepend)
newdeps.append(tdepend)
nextdeps = newdeps
recursive_tdepends[task] = rectdepends
return rectdepends
# Using the list of tdepends for this task create a list of
# the recursive idepends we have
def get_recursive_idepends(task):
if not task:
return []
rectdepends = get_recursive_tdepends(task)
recidepends = []
for tdepend in rectdepends:
for idepend in taskData.tasks_idepends[tdepend]:
recidepends.append(idepend)
return recidepends
def add_recursive_build(depid, depfnid):
"""
Add build depends of depid to depends
(if we've not see it before)
(calls itself recursively)
"""
if str(depid) in dep_seen:
return
dep_seen.append(depid)
if depid in taskData.build_targets:
depdata = taskData.build_targets[depid][0]
if depdata is not None:
dep = taskData.fn_index[depdata]
# Need to avoid creating new tasks here
taskid = taskData.gettask_id(dep, taskname, False)
if taskid is not None:
depends.append(taskid)
fnid = taskData.tasks_fnid[taskid]
#print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid])
else:
fnid = taskData.getfn_id(dep)
for nextdepid in taskData.depids[fnid]:
if nextdepid not in dep_seen:
add_recursive_build(nextdepid, fnid)
for nextdepid in taskData.rdepids[fnid]:
if nextdepid not in rdep_seen:
add_recursive_run(nextdepid, fnid)
for (idependid, idependtask) in get_recursive_idepends(taskid):
if idependid not in dep_seen:
add_recursive_build(idependid, fnid)
def add_recursive_run(rdepid, depfnid):
"""
Add runtime depends of rdepid to depends
(if we've not see it before)
(calls itself recursively)
"""
if str(rdepid) in rdep_seen:
return
rdep_seen.append(rdepid)
if rdepid in taskData.run_targets:
depdata = taskData.run_targets[rdepid][0]
if depdata is not None:
dep = taskData.fn_index[depdata]
# Need to avoid creating new tasks here
taskid = taskData.gettask_id(dep, taskname, False)
if taskid is not None:
depends.append(taskid)
fnid = taskData.tasks_fnid[taskid]
#print "Added %s (%s) due to %s" % (taskid, taskData.fn_index[fnid], taskData.fn_index[depfnid])
else:
fnid = taskData.getfn_id(dep)
for nextdepid in taskData.depids[fnid]:
if nextdepid not in dep_seen:
add_recursive_build(nextdepid, fnid)
for nextdepid in taskData.rdepids[fnid]:
if nextdepid not in rdep_seen:
add_recursive_run(nextdepid, fnid)
for (idependid, idependtask) in get_recursive_idepends(taskid):
if idependid not in dep_seen:
add_recursive_build(idependid, fnid)
# Resolve recursive 'recrdeptask' dependencies
#
# e.g. do_sometask[recrdeptask] = "do_someothertask"
# (makes sure sometask runs after someothertask of all DEPENDS, RDEPENDS and intertask dependencies, recursively)
# We cover the recursive part of the dependencies below
if 'recrdeptask' in task_deps and taskData.tasks_name[task] in task_deps['recrdeptask']:
for taskname in task_deps['recrdeptask'][taskData.tasks_name[task]].split():
recrdepends.append(taskname)
add_build_dependencies(taskData.depids[fnid], [taskname], depends)
add_runtime_dependencies(taskData.rdepids[fnid], [taskname], depends)
dep_seen = []
rdep_seen = []
idep_seen = []
for depid in taskData.depids[fnid]:
add_recursive_build(depid, fnid)
for rdepid in taskData.rdepids[fnid]:
add_recursive_run(rdepid, fnid)
deptaskid = taskData.gettask_id(fn, taskname, False)
for (idependid, idependtask) in get_recursive_idepends(deptaskid):
add_recursive_build(idependid, fnid)
# Rmove all self references
if task in depends:
@@ -471,54 +522,13 @@ class RunQueue:
newdep.append(dep)
depends = newdep
self.runq_fnid.append(taskData.tasks_fnid[task])
self.runq_task.append(taskData.tasks_name[task])
self.runq_depends.append(set(depends))
self.runq_revdeps.append(set())
self.runq_depends.append(Set(depends))
self.runq_revdeps.append(Set())
runq_build.append(0)
runq_recrdepends.append(recrdepends)
#
# Build a list of recursive cumulative dependencies for each fnid
# We do this by fnid, since if A depends on some task in B
# we're interested in later tasks B's fnid might have but B itself
# doesn't depend on
#
# Algorithm is O(tasks) + O(tasks)*O(fnids)
#
reccumdepends = {}
for task in range(len(self.runq_fnid)):
fnid = self.runq_fnid[task]
if fnid not in reccumdepends:
if fnid in tdepends_fnid:
reccumdepends[fnid] = tdepends_fnid[fnid]
else:
reccumdepends[fnid] = set()
reccumdepends[fnid].update(self.runq_depends[task])
for task in range(len(self.runq_fnid)):
taskfnid = self.runq_fnid[task]
for fnid in reccumdepends:
if task in reccumdepends[fnid]:
reccumdepends[fnid].add(task)
if taskfnid in reccumdepends:
reccumdepends[fnid].update(reccumdepends[taskfnid])
# Resolve recursive 'recrdeptask' dependencies (B)
#
# e.g. do_sometask[recrdeptask] = "do_someothertask"
# (makes sure sometask runs after someothertask of all DEPENDS, RDEPENDS and intertask dependencies, recursively)
for task in range(len(self.runq_fnid)):
if len(runq_recrdepends[task]) > 0:
taskfnid = self.runq_fnid[task]
for dep in reccumdepends[taskfnid]:
# Ignore self references
if dep == task:
continue
for taskname in runq_recrdepends[task]:
if taskData.tasks_name[dep] == taskname:
self.runq_depends[task].add(dep)
# Step B - Mark all active tasks
#
@@ -598,7 +608,7 @@ class RunQueue:
if len(self.runq_fnid) == 0:
if not taskData.abort:
bb.msg.fatal(bb.msg.domain.RunQueue, "All buildable tasks have been run but the build is incomplete (--continue mode). Errors for the tasks that failed will have been printed above.")
else:
else:
bb.msg.fatal(bb.msg.domain.RunQueue, "No active tasks and not in --continue mode?! Please report this bug.")
bb.msg.note(2, bb.msg.domain.RunQueue, "Pruned %s inactive tasks, %s left" % (delcount, len(self.runq_fnid)))
@@ -612,7 +622,7 @@ class RunQueue:
if maps[origdep] == -1:
bb.msg.fatal(bb.msg.domain.RunQueue, "Invalid mapping - Should never happen!")
newdeps.append(maps[origdep])
self.runq_depends[listid] = set(newdeps)
self.runq_depends[listid] = Set(newdeps)
bb.msg.note(2, bb.msg.domain.RunQueue, "Assign Weightings")
@@ -635,6 +645,7 @@ class RunQueue:
bb.msg.note(2, bb.msg.domain.RunQueue, "Compute totals (have %s endpoint(s))" % len(endpoints))
# Calculate task weights
# Check of higher length circular dependencies
self.runq_weight = self.calculate_task_weights(endpoints)
@@ -681,8 +692,6 @@ class RunQueue:
#self.dump_data(taskData)
self.state = runQueueRunInit
def check_stamps(self):
unchecked = {}
current = []
@@ -796,7 +805,7 @@ class RunQueue:
return False
# If its a 'nostamp' task, it's not current
taskdep = self.dataCache.task_deps[fn]
if 'nostamp' in taskdep and taskname in taskdep['nostamp']:
if 'nostamp' in taskdep and task in taskdep['nostamp']:
bb.msg.debug(2, bb.msg.domain.RunQueue, "%s.%s is nostamp\n" % (fn, taskname))
return False
@@ -826,51 +835,39 @@ class RunQueue:
(if the abort on failure configuration option isn't set)
"""
if self.state is runQueuePrepare:
self.prepare_runqueue()
if self.state is runQueueRunInit:
bb.msg.note(1, bb.msg.domain.RunQueue, "Executing runqueue")
self.execute_runqueue_initVars()
if self.state is runQueueRunning:
self.execute_runqueue_internal()
if self.state is runQueueCleanUp:
self.finish_runqueue()
if self.state is runQueueFailed:
if not self.taskData.tryaltconfigs:
raise bb.runqueue.TaskFailure(self.failed_fnids)
for fnid in self.failed_fnids:
failures = 0
while 1:
failed_fnids = []
try:
self.execute_runqueue_internal()
finally:
if self.master_process:
failed_fnids = self.finish_runqueue()
if len(failed_fnids) == 0:
return failures
if self.taskData.abort:
raise bb.runqueue.TaskFailure(failed_fnids)
for fnid in failed_fnids:
#print "Failure: %s %s %s" % (fnid, self.taskData.fn_index[fnid], self.runq_task[fnid])
self.taskData.fail_fnid(fnid)
failures = failures + 1
self.reset_runqueue()
if self.state is runQueueComplete:
# All done
bb.msg.note(1, bb.msg.domain.RunQueue, "Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed." % (self.stats.completed, self.stats.skipped, self.stats.failed))
return False
if self.state is runQueueChildProcess:
print "Child process"
return False
# Loop
return True
self.prepare_runqueue()
def execute_runqueue_initVars(self):
self.stats = RunQueueStats(len(self.runq_fnid))
self.stats = RunQueueStats()
self.active_builds = 0
self.runq_buildable = []
self.runq_running = []
self.runq_complete = []
self.build_pids = {}
self.build_pipes = {}
self.failed_fnids = []
self.master_process = True
# Mark initial buildable tasks
for task in range(self.stats.total):
for task in range(len(self.runq_fnid)):
self.runq_running.append(0)
self.runq_complete.append(0)
if len(self.runq_depends[task]) == 0:
@@ -878,10 +875,6 @@ class RunQueue:
else:
self.runq_buildable.append(0)
self.state = runQueueRunning
event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp), self.cfgData)
def task_complete(self, task):
"""
Mark a task as completed
@@ -904,32 +897,26 @@ class RunQueue:
taskname = self.runq_task[revdep]
bb.msg.debug(1, bb.msg.domain.RunQueue, "Marking task %s (%s, %s) as buildable" % (revdep, fn, taskname))
def task_fail(self, task, exitcode):
"""
Called when a task has failed
Updates the state engine with the failure
"""
bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed with %s" % (task, self.get_user_idstring(task), exitcode))
self.stats.taskFailed()
fnid = self.runq_fnid[task]
self.failed_fnids.append(fnid)
bb.event.fire(runQueueTaskFailed(task, self.stats, self), self.cfgData)
if self.taskData.abort:
self.state = runQueueCleanUp
def execute_runqueue_internal(self):
"""
Run the tasks in a queue prepared by prepare_runqueue
"""
if self.stats.total == 0:
bb.msg.note(1, bb.msg.domain.RunQueue, "Executing runqueue")
self.execute_runqueue_initVars()
if len(self.runq_fnid) == 0:
# nothing to do
self.state = runQueueCleanUp
return []
def sigint_handler(signum, frame):
raise KeyboardInterrupt
event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp, self.cfgdata))
while True:
task = None
if self.stats.active < self.number_tasks:
task = self.sched.next()
task = self.sched.next()
if task is not None:
fn = self.taskData.fn_index[self.runq_fnid[task]]
@@ -937,154 +924,105 @@ class RunQueue:
if self.check_stamp_task(task):
bb.msg.debug(2, bb.msg.domain.RunQueue, "Stamp current task %s (%s)" % (task, self.get_user_idstring(task)))
self.runq_running[task] = 1
self.runq_buildable[task] = 1
self.task_complete(task)
self.stats.taskCompleted()
self.stats.taskSkipped()
continue
bb.msg.note(1, bb.msg.domain.RunQueue, "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.active_builds + 1, len(self.runq_fnid), task, self.get_user_idstring(task)))
sys.stdout.flush()
sys.stderr.flush()
try:
pipein, pipeout = os.pipe()
try:
pid = os.fork()
except OSError, e:
bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror))
if pid == 0:
os.close(pipein)
# Save out the PID so that the event can include it the
# events
bb.event.worker_pid = os.getpid()
bb.event.worker_pipe = pipeout
self.state = runQueueChildProcess
# Bypass master process' handling
self.master_process = False
# Stop Ctrl+C being sent to children
# signal.signal(signal.SIGINT, signal.SIG_IGN)
# Make the child the process group leader
os.setpgid(0, 0)
# No stdin
newsi = os.open('/dev/null', os.O_RDWR)
os.dup2(newsi, sys.stdin.fileno())
# Stdout to a logfile
#logout = data.expand("${TMPDIR}/log/stdout.%s" % os.getpid(), self.cfgData, True)
#mkdirhier(os.path.dirname(logout))
#newso = open(logout, 'w')
#os.dup2(newso.fileno(), sys.stdout.fileno())
#os.dup2(newso.fileno(), sys.stderr.fileno())
bb.event.fire(runQueueTaskStarted(task, self.stats, self), self.cfgData)
bb.msg.note(1, bb.msg.domain.RunQueue,
"Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.stats.active + 1,
self.stats.total,
task,
self.get_user_idstring(task)))
self.cooker.configuration.cmd = taskname[3:]
bb.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", self, self.cooker.configuration.data)
bb.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY2", fn, self.cooker.configuration.data)
try:
self.cooker.tryBuild(fn, taskname[3:])
self.cooker.tryBuild(fn)
except bb.build.EventException:
bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
os._exit(1)
sys.exit(1)
except:
bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
os._exit(1)
os._exit(0)
raise
sys.exit(0)
self.build_pids[pid] = task
self.build_pipes[pid] = runQueuePipe(pipein, pipeout, self.cfgData)
self.runq_running[task] = 1
self.stats.taskActive()
if self.stats.active < self.number_tasks:
self.active_builds = self.active_builds + 1
if self.active_builds < self.number_tasks:
continue
for pipe in self.build_pipes:
self.build_pipes[pipe].read()
if self.stats.active > 0:
result = os.waitpid(-1, os.WNOHANG)
if result[0] is 0 and result[1] is 0:
return
if self.active_builds > 0:
result = os.waitpid(-1, 0)
self.active_builds = self.active_builds - 1
task = self.build_pids[result[0]]
del self.build_pids[result[0]]
self.build_pipes[result[0]].close()
del self.build_pipes[result[0]]
if result[1] != 0:
self.task_fail(task, result[1])
return
del self.build_pids[result[0]]
bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task)))
self.failed_fnids.append(self.runq_fnid[task])
self.stats.taskFailed()
break
self.task_complete(task)
self.stats.taskCompleted()
bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData)
del self.build_pids[result[0]]
continue
if len(self.failed_fnids) != 0:
self.state = runQueueFailed
return
# Sanity Checks
for task in range(self.stats.total):
if self.runq_buildable[task] == 0:
bb.msg.error(bb.msg.domain.RunQueue, "Task %s never buildable!" % task)
if self.runq_running[task] == 0:
bb.msg.error(bb.msg.domain.RunQueue, "Task %s never ran!" % task)
if self.runq_complete[task] == 0:
bb.msg.error(bb.msg.domain.RunQueue, "Task %s never completed!" % task)
self.state = runQueueComplete
return
def finish_runqueue_now(self):
bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGINT to remaining %s tasks" % self.stats.active)
for k, v in self.build_pids.iteritems():
try:
os.kill(-k, signal.SIGINT)
except:
pass
for pipe in self.build_pipes:
self.build_pipes[pipe].read()
def finish_runqueue(self, now = False):
self.state = runQueueCleanUp
for pipe in self.build_pipes:
self.build_pipes[pipe].read()
if now:
self.finish_runqueue_now()
def finish_runqueue(self):
try:
while self.stats.active > 0:
bb.event.fire(runQueueExitWait(self.stats.active), self.cfgData)
#bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.stats.active)
#tasknum = 1
#for k, v in self.build_pids.iteritems():
# bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (pid %s)" % (tasknum, self.get_user_idstring(v), k))
# tasknum = tasknum + 1
result = os.waitpid(-1, os.WNOHANG)
if result[0] is 0 and result[1] is 0:
return
while self.active_builds > 0:
bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.active_builds)
tasknum = 1
for k, v in self.build_pids.iteritems():
bb.msg.note(1, bb.msg.domain.RunQueue, "%s: %s (%s)" % (tasknum, self.get_user_idstring(v), k))
tasknum = tasknum + 1
result = os.waitpid(-1, 0)
task = self.build_pids[result[0]]
del self.build_pids[result[0]]
self.build_pipes[result[0]].close()
del self.build_pipes[result[0]]
if result[1] != 0:
self.task_fail(task, result[1])
else:
self.stats.taskCompleted()
bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData)
except:
self.finish_runqueue_now()
bb.msg.error(bb.msg.domain.RunQueue, "Task %s (%s) failed" % (task, self.get_user_idstring(task)))
self.failed_fnids.append(self.runq_fnid[task])
self.stats.taskFailed()
del self.build_pids[result[0]]
self.active_builds = self.active_builds - 1
bb.msg.note(1, bb.msg.domain.RunQueue, "Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed." % (self.stats.completed, self.stats.skipped, self.stats.failed))
return self.failed_fnids
except KeyboardInterrupt:
bb.msg.note(1, bb.msg.domain.RunQueue, "Sending SIGINT to remaining %s tasks" % self.active_builds)
for k, v in self.build_pids.iteritems():
try:
os.kill(-k, signal.SIGINT)
except:
pass
raise
if len(self.failed_fnids) != 0:
self.state = runQueueFailed
return
# Sanity Checks
for task in range(len(self.runq_fnid)):
if self.runq_buildable[task] == 0:
bb.msg.error(bb.msg.domain.RunQueue, "Task %s never buildable!" % task)
if self.runq_running[task] == 0:
bb.msg.error(bb.msg.domain.RunQueue, "Task %s never ran!" % task)
if self.runq_complete[task] == 0:
bb.msg.error(bb.msg.domain.RunQueue, "Task %s never completed!" % task)
self.state = runQueueComplete
return
bb.msg.note(1, bb.msg.domain.RunQueue, "Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed." % (self.stats.completed, self.stats.skipped, self.stats.failed))
return self.failed_fnids
def dump_data(self, taskQueue):
"""
Dump some debug information on the internal data structures
"""
bb.msg.debug(3, bb.msg.domain.RunQueue, "run_tasks:")
for task in range(len(self.runq_task)):
for task in range(len(self.runq_fnid)):
bb.msg.debug(3, bb.msg.domain.RunQueue, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task,
taskQueue.fn_index[self.runq_fnid[task]],
self.runq_task[task],
@@ -1093,7 +1031,7 @@ class RunQueue:
self.runq_revdeps[task]))
bb.msg.debug(3, bb.msg.domain.RunQueue, "sorted_tasks:")
for task1 in range(len(self.runq_task)):
for task1 in range(len(self.runq_fnid)):
if task1 in self.prio_map:
task = self.prio_map[task1]
bb.msg.debug(3, bb.msg.domain.RunQueue, " (%s)%s - %s: %s Deps %s RevDeps %s" % (task,
@@ -1104,96 +1042,11 @@ class RunQueue:
self.runq_revdeps[task]))
class TaskFailure(Exception):
"""
Exception raised when a task in a runqueue fails
"""
def __init__(self, x):
self.args = x
class runQueueExitWait(bb.event.Event):
"""
Event when waiting for task processes to exit
"""
def __init__(self, remain):
self.remain = remain
self.message = "Waiting for %s active tasks to finish" % remain
bb.event.Event.__init__(self)
class runQueueEvent(bb.event.Event):
"""
Base runQueue event class
"""
def __init__(self, task, stats, rq):
self.taskid = task
self.taskstring = rq.get_user_idstring(task)
self.stats = stats
bb.event.Event.__init__(self)
class runQueueTaskStarted(runQueueEvent):
"""
Event notifing a task was started
"""
def __init__(self, task, stats, rq):
runQueueEvent.__init__(self, task, stats, rq)
self.message = "Running task %s (%d of %d) (%s)" % (task, stats.completed + stats.active + 1, self.stats.total, self.taskstring)
class runQueueTaskFailed(runQueueEvent):
"""
Event notifing a task failed
"""
def __init__(self, task, stats, rq):
runQueueEvent.__init__(self, task, stats, rq)
self.message = "Task %s failed (%s)" % (task, self.taskstring)
class runQueueTaskCompleted(runQueueEvent):
"""
Event notifing a task completed
"""
def __init__(self, task, stats, rq):
runQueueEvent.__init__(self, task, stats, rq)
self.message = "Task %s completed (%s)" % (task, self.taskstring)
def check_stamp_fn(fn, taskname, d):
rq = bb.data.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", d)
fn = bb.data.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY2", d)
fnid = rq.taskData.getfn_id(fn)
taskid = rq.get_task_id(fnid, taskname)
if taskid is not None:
return rq.check_stamp_task(taskid)
return None
class runQueuePipe():
"""
Abstraction for a pipe between a worker thread and the server
"""
def __init__(self, pipein, pipeout, d):
self.fd = pipein
os.close(pipeout)
fcntl.fcntl(self.fd, fcntl.F_SETFL, fcntl.fcntl(self.fd, fcntl.F_GETFL) | os.O_NONBLOCK)
self.queue = ""
self.d = d
def read(self):
start = len(self.queue)
try:
self.queue = self.queue + os.read(self.fd, 1024)
except OSError:
pass
end = len(self.queue)
index = self.queue.find("</event>")
while index != -1:
bb.event.fire_from_worker(self.queue[:index+8], self.d)
self.queue = self.queue[index+8:]
index = self.queue.find("</event>")
return (end > start)
def close(self):
while self.read():
continue
if len(self.queue) > 0:
print "Warning, worker left partial message"
os.close(self.fd)

View File

@@ -1,181 +0,0 @@
#
# BitBake 'dummy' Passthrough Server
#
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
This module implements an xmlrpc server for BitBake.
Use this by deriving a class from BitBakeXMLRPCServer and then adding
methods which you want to "export" via XMLRPC. If the methods have the
prefix xmlrpc_, then registering those function will happen automatically,
if not, you need to call register_function.
Use register_idle_function() to add a function which the xmlrpc server
calls from within server_forever when no requests are pending. Make sure
that those functions are non-blocking or else you will introduce latency
in the server's main loop.
"""
import time
import bb
from bb.ui import uievent
import xmlrpclib
import pickle
DEBUG = False
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import inspect, select
class BitBakeServerCommands():
def __init__(self, server, cooker):
self.cooker = cooker
self.server = server
def runCommand(self, command):
"""
Run a cooker command on the server
"""
#print "Running Command %s" % command
return self.cooker.command.runCommand(command)
def terminateServer(self):
"""
Trigger the server to quit
"""
self.server.server_exit()
#print "Server (cooker) exitting"
return
def ping(self):
"""
Dummy method which can be used to check the server is still alive
"""
return True
eventQueue = []
class BBUIEventQueue:
class event:
def __init__(self, parent):
self.parent = parent
@staticmethod
def send(event):
bb.server.none.eventQueue.append(pickle.loads(event))
@staticmethod
def quit():
return
def __init__(self, BBServer):
self.eventQueue = bb.server.none.eventQueue
self.BBServer = BBServer
self.EventHandle = bb.event.register_UIHhandler(self)
def getEvent(self):
if len(self.eventQueue) == 0:
return None
return self.eventQueue.pop(0)
def waitEvent(self, delay):
event = self.getEvent()
if event:
return event
self.BBServer.idle_commands(delay)
return self.getEvent()
def queue_event(self, event):
self.eventQueue.append(event)
def system_quit( self ):
bb.event.unregister_UIHhandler(self.EventHandle)
class BitBakeServer():
# remove this when you're done with debugging
# allow_reuse_address = True
def __init__(self, cooker):
self._idlefuns = {}
self.commands = BitBakeServerCommands(self, cooker)
def register_idle_function(self, function, data):
"""Register a function to be called while the server is idle"""
assert callable(function)
self._idlefuns[function] = data
def idle_commands(self, delay):
#print "Idle queue length %s" % len(self._idlefuns)
#print "Idle timeout, running idle functions"
#if len(self._idlefuns) == 0:
nextsleep = delay
for function, data in self._idlefuns.items():
try:
retval = function(self, data, False)
#print "Idle function returned %s" % (retval)
if retval is False:
del self._idlefuns[function]
elif retval is True:
nextsleep = None
elif nextsleep is None:
continue
elif retval < nextsleep:
nextsleep = retval
except SystemExit:
raise
except:
import traceback
traceback.print_exc()
pass
if nextsleep is not None:
#print "Sleeping for %s (%s)" % (nextsleep, delay)
time.sleep(nextsleep)
def server_exit(self):
# Tell idle functions we're exiting
for function, data in self._idlefuns.items():
try:
retval = function(self, data, True)
except:
pass
class BitbakeServerInfo():
def __init__(self, server):
self.server = server
self.commands = server.commands
class BitBakeServerFork():
def __init__(self, serverinfo, command, logfile):
serverinfo.forkCommand = command
serverinfo.logfile = logfile
class BitBakeServerConnection():
def __init__(self, serverinfo):
self.server = serverinfo.server
self.connection = serverinfo.commands
self.events = bb.server.none.BBUIEventQueue(self.server)
def terminate(self):
try:
self.events.system_quit()
except:
pass
try:
self.connection.terminateServer()
except:
pass

View File

@@ -1,187 +0,0 @@
#
# BitBake XMLRPC Server
#
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
This module implements an xmlrpc server for BitBake.
Use this by deriving a class from BitBakeXMLRPCServer and then adding
methods which you want to "export" via XMLRPC. If the methods have the
prefix xmlrpc_, then registering those function will happen automatically,
if not, you need to call register_function.
Use register_idle_function() to add a function which the xmlrpc server
calls from within server_forever when no requests are pending. Make sure
that those functions are non-blocking or else you will introduce latency
in the server's main loop.
"""
import bb
import xmlrpclib, sys
from bb import daemonize
from bb.ui import uievent
DEBUG = False
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import inspect, select
if sys.hexversion < 0x020600F0:
print "Sorry, python 2.6 or later is required for bitbake's XMLRPC mode"
sys.exit(1)
class BitBakeServerCommands():
def __init__(self, server, cooker):
self.cooker = cooker
self.server = server
def registerEventHandler(self, host, port):
"""
Register a remote UI Event Handler
"""
s = xmlrpclib.Server("http://%s:%d" % (host, port), allow_none=True)
return bb.event.register_UIHhandler(s)
def unregisterEventHandler(self, handlerNum):
"""
Unregister a remote UI Event Handler
"""
return bb.event.unregister_UIHhandler(handlerNum)
def runCommand(self, command):
"""
Run a cooker command on the server
"""
return self.cooker.command.runCommand(command)
def terminateServer(self):
"""
Trigger the server to quit
"""
self.server.quit = True
print "Server (cooker) exitting"
return
def ping(self):
"""
Dummy method which can be used to check the server is still alive
"""
return True
class BitBakeServer(SimpleXMLRPCServer):
# remove this when you're done with debugging
# allow_reuse_address = True
def __init__(self, cooker, interface = ("localhost", 0)):
"""
Constructor
"""
SimpleXMLRPCServer.__init__(self, interface,
requestHandler=SimpleXMLRPCRequestHandler,
logRequests=False, allow_none=True)
self._idlefuns = {}
self.host, self.port = self.socket.getsockname()
#self.register_introspection_functions()
commands = BitBakeServerCommands(self, cooker)
self.autoregister_all_functions(commands, "")
def autoregister_all_functions(self, context, prefix):
"""
Convenience method for registering all functions in the scope
of this class that start with a common prefix
"""
methodlist = inspect.getmembers(context, inspect.ismethod)
for name, method in methodlist:
if name.startswith(prefix):
self.register_function(method, name[len(prefix):])
def register_idle_function(self, function, data):
"""Register a function to be called while the server is idle"""
assert callable(function)
self._idlefuns[function] = data
def serve_forever(self):
"""
Serve Requests. Overloaded to honor a quit command
"""
self.quit = False
self.timeout = 0 # Run Idle calls for our first callback
while not self.quit:
#print "Idle queue length %s" % len(self._idlefuns)
self.handle_request()
#print "Idle timeout, running idle functions"
nextsleep = None
for function, data in self._idlefuns.items():
try:
retval = function(self, data, False)
if retval is False:
del self._idlefuns[function]
elif retval is True:
nextsleep = 0
elif nextsleep is 0:
continue
elif nextsleep is None:
nextsleep = retval
elif retval < nextsleep:
nextsleep = retval
except SystemExit:
raise
except:
import traceback
traceback.print_exc()
pass
if nextsleep is None and len(self._idlefuns) > 0:
nextsleep = 0
self.timeout = nextsleep
# Tell idle functions we're exiting
for function, data in self._idlefuns.items():
try:
retval = function(self, data, True)
except:
pass
self.server_close()
return
class BitbakeServerInfo():
def __init__(self, server):
self.host = server.host
self.port = server.port
class BitBakeServerFork():
def __init__(self, serverinfo, command, logfile):
daemonize.createDaemon(command, logfile)
class BitBakeServerConnection():
def __init__(self, serverinfo):
self.connection = xmlrpclib.Server("http://%s:%s" % (serverinfo.host, serverinfo.port), allow_none=True)
self.events = uievent.BBUIEventQueue(self.connection)
def terminate(self):
# Don't wait for server indefinitely
import socket
socket.setdefaulttimeout(2)
try:
self.events.system_quit()
except:
pass
try:
self.connection.terminateServer()
except:
pass

View File

@@ -147,10 +147,13 @@ class BitBakeShellCommands:
global last_exception
globexpr = params[0]
self._checkParsed()
names = globfilter( cooker.status.pkg_pn, globexpr )
names = globfilter( cooker.status.pkg_pn.keys(), globexpr )
if len( names ) == 0: names = [ globexpr ]
print "SHELL: Building %s" % ' '.join( names )
oldcmd = cooker.configuration.cmd
cooker.configuration.cmd = cmd
td = taskdata.TaskData(cooker.configuration.abort)
localdata = data.createCopy(cooker.configuration.data)
data.update_data(localdata)
@@ -165,7 +168,7 @@ class BitBakeShellCommands:
if len(providers) == 0:
raise Providers.NoProvider
tasks.append([name, "do_%s" % cmd])
tasks.append([name, "do_%s" % cooker.configuration.cmd])
td.add_unresolved(localdata, cooker.status)
@@ -186,6 +189,7 @@ class BitBakeShellCommands:
print "ERROR: Couldn't build '%s'" % names
last_exception = e
cooker.configuration.cmd = oldcmd
build.usage = "<providee>"
@@ -204,11 +208,6 @@ class BitBakeShellCommands:
self.build( params, "configure" )
configure.usage = "<providee>"
def install( self, params ):
"""Execute 'install' on a providee"""
self.build( params, "install" )
install.usage = "<providee>"
def edit( self, params ):
"""Call $EDITOR on a providee"""
name = params[0]
@@ -241,14 +240,18 @@ class BitBakeShellCommands:
bf = completeFilePath( name )
print "SHELL: Calling '%s' on '%s'" % ( cmd, bf )
oldcmd = cooker.configuration.cmd
cooker.configuration.cmd = cmd
try:
cooker.buildFile(bf, cmd)
cooker.buildFile(bf)
except parse.ParseError:
print "ERROR: Unable to open or parse '%s'" % bf
except build.EventException, e:
print "ERROR: Couldn't build '%s'" % name
last_exception = e
cooker.configuration.cmd = oldcmd
fileBuild.usage = "<bbfile>"
def fileClean( self, params ):
@@ -273,7 +276,7 @@ class BitBakeShellCommands:
print "SHELL: Parsing '%s'" % bbfile
parse.update_mtime( bbfile )
cooker.bb_cache.cacheValidUpdate(bbfile)
fromCache = cooker.bb_cache.loadData(bbfile, cooker.configuration.data, cooker.status)
fromCache = cooker.bb_cache.loadData(bbfile, cooker.configuration.data)
cooker.bb_cache.sync()
if False: #fromCache:
print "SHELL: File has not been updated, not reparsing"
@@ -294,7 +297,9 @@ class BitBakeShellCommands:
def help( self, params ):
"""Show a comprehensive list of commands and their purpose"""
print "="*30, "Available Commands", "="*30
for cmd in sorted(cmds):
allcmds = cmds.keys()
allcmds.sort()
for cmd in allcmds:
function,numparams,usage,helptext = cmds[cmd]
print "| %s | %s" % (usage.ljust(30), helptext)
print "="*78
@@ -320,10 +325,10 @@ class BitBakeShellCommands:
what, globexpr = params
if what == "files":
self._checkParsed()
for key in globfilter( cooker.status.pkg_fn, globexpr ): print key
for key in globfilter( cooker.status.pkg_fn.keys(), globexpr ): print key
elif what == "providers":
self._checkParsed()
for key in globfilter( cooker.status.pkg_pn, globexpr ): print key
for key in globfilter( cooker.status.pkg_pn.keys(), globexpr ): print key
else:
print "Usage: match %s" % self.print_.usage
match.usage = "<files|providers> <glob>"
@@ -471,10 +476,10 @@ SRC_URI = ""
what = params[0]
if what == "files":
self._checkParsed()
for key in cooker.status.pkg_fn: print key
for key in cooker.status.pkg_fn.keys(): print key
elif what == "providers":
self._checkParsed()
for key in cooker.status.providers: print key
for key in cooker.status.providers.keys(): print key
else:
print "Usage: print %s" % self.print_.usage
print_.usage = "<files|providers>"
@@ -488,7 +493,7 @@ SRC_URI = ""
interpreter.interact( "SHELL: Expert Mode - BitBake Python %s\nType 'help' for more information, press CTRL-D to switch back to BBSHELL." % sys.version )
def showdata( self, params ):
"""Execute 'showdata' on a providee"""
"""Show the parsed metadata for a given providee"""
cooker.showEnvironment(None, params)
showdata.usage = "<providee>"
@@ -513,7 +518,7 @@ SRC_URI = ""
def stage( self, params ):
"""Execute 'stage' on a providee"""
self.build( params, "populate_staging" )
self.build( params, "stage" )
stage.usage = "<providee>"
def status( self, params ):
@@ -569,7 +574,7 @@ def completeFilePath( bbfile ):
"""Get the complete bbfile path"""
if not cooker.status: return bbfile
if not cooker.status.pkg_fn: return bbfile
for key in cooker.status.pkg_fn:
for key in cooker.status.pkg_fn.keys():
if key.endswith( bbfile ):
return key
return bbfile
@@ -613,7 +618,7 @@ def completer( text, state ):
allmatches = cooker.configuration.data.keys()
elif u == "<bbfile>":
if cooker.status.pkg_fn is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
else: allmatches = [ x.split("/")[-1] for x in cooker.status.pkg_fn ]
else: allmatches = [ x.split("/")[-1] for x in cooker.status.pkg_fn.keys() ]
elif u == "<providee>":
if cooker.status.pkg_fn is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
else: allmatches = cooker.status.providers.iterkeys()

View File

@@ -23,26 +23,14 @@ Task data collection and handling
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import bb
def re_match_strings(target, strings):
"""
Whether or not the string 'target' matches
any one string of the strings which can be regular expression string
"""
import re
for name in strings:
if (name==target or
re.search(name,target)!=None):
return True
return False
from bb import data, event, mkdirhier, utils
import bb, os
class TaskData:
"""
BitBake Task Data implementation
"""
def __init__(self, abort = True, tryaltconfigs = False):
def __init__(self, abort = True):
self.build_names_index = []
self.run_names_index = []
self.fn_index = []
@@ -69,7 +57,6 @@ class TaskData:
self.failed_fnids = []
self.abort = abort
self.tryaltconfigs = tryaltconfigs
def getbuild_id(self, name):
"""
@@ -173,8 +160,6 @@ class TaskData:
ids = []
for dep in task_deps['depends'][task].split():
if dep:
if ":" not in dep:
bb.msg.fatal(bb.msg.domain.TaskData, "Error, dependency %s does not contain ':' character\n. Task 'depends' should be specified in the form 'packagename:task'" % (dep, fn))
ids.append(((self.getbuild_id(dep.split(":")[0])), dep.split(":")[1]))
self.tasks_idepends[taskid].extend(ids)
@@ -276,7 +261,7 @@ class TaskData:
"""
unresolved = []
for target in self.build_names_index:
if re_match_strings(target, dataCache.ignored_dependencies):
if target in dataCache.ignored_dependencies:
continue
if self.build_names_index.index(target) in self.failed_deps:
continue
@@ -291,7 +276,7 @@ class TaskData:
"""
unresolved = []
for target in self.run_names_index:
if re_match_strings(target, dataCache.ignored_dependencies):
if target in dataCache.ignored_dependencies:
continue
if self.run_names_index.index(target) in self.failed_rdeps:
continue
@@ -354,10 +339,7 @@ class TaskData:
self.add_provider_internal(cfgData, dataCache, item)
except bb.providers.NoProvider:
if self.abort:
if self.get_rdependees_str(item):
bb.msg.error(bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (item, self.get_dependees_str(item)))
else:
bb.msg.error(bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (item))
bb.msg.error(bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (item, self.get_dependees_str(item)))
raise
targetid = self.getbuild_id(item)
self.remove_buildtarget(targetid)
@@ -371,15 +353,12 @@ class TaskData:
added internally during dependency resolution
"""
if re_match_strings(item, dataCache.ignored_dependencies):
if item in dataCache.ignored_dependencies:
return
if not item in dataCache.providers:
if self.get_rdependees_str(item):
bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (item, self.get_dependees_str(item)))
else:
bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (item))
bb.event.fire(bb.event.NoProvider(item), cfgData)
bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (item, self.get_dependees_str(item)))
bb.event.fire(bb.event.NoProvider(item, cfgData))
raise bb.providers.NoProvider(item)
if self.have_build_target(item):
@@ -388,11 +367,15 @@ class TaskData:
all_p = dataCache.providers[item]
eligible, foundUnique = bb.providers.filterProviders(all_p, item, cfgData, dataCache)
eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids]
for p in eligible:
fnid = self.getfn_id(p)
if fnid in self.failed_fnids:
eligible.remove(p)
if not eligible:
bb.msg.note(2, bb.msg.domain.Provider, "No buildable provider PROVIDES '%s' but '%s' DEPENDS on or otherwise requires it. Enable debugging and see earlier logs to find unbuildable providers." % (item, self.get_dependees_str(item)))
bb.event.fire(bb.event.NoProvider(item), cfgData)
bb.event.fire(bb.event.NoProvider(item, cfgData))
raise bb.providers.NoProvider(item)
if len(eligible) > 1 and foundUnique == False:
@@ -402,7 +385,7 @@ class TaskData:
providers_list.append(dataCache.pkg_fn[fn])
bb.msg.note(1, bb.msg.domain.Provider, "multiple providers are available for %s (%s);" % (item, ", ".join(providers_list)))
bb.msg.note(1, bb.msg.domain.Provider, "consider defining PREFERRED_PROVIDER_%s" % item)
bb.event.fire(bb.event.MultipleProviders(item, providers_list), cfgData)
bb.event.fire(bb.event.MultipleProviders(item, providers_list, cfgData))
self.consider_msgs_cache.append(item)
for fn in eligible:
@@ -422,7 +405,7 @@ class TaskData:
(takes item names from RDEPENDS/PACKAGES namespace)
"""
if re_match_strings(item, dataCache.ignored_dependencies):
if item in dataCache.ignored_dependencies:
return
if self.have_runtime_target(item):
@@ -432,15 +415,19 @@ class TaskData:
if not all_p:
bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables" % (self.get_rdependees_str(item), item))
bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData)
bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True))
raise bb.providers.NoRProvider(item)
eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache)
eligible = [p for p in eligible if not self.getfn_id(p) in self.failed_fnids]
for p in eligible:
fnid = self.getfn_id(p)
if fnid in self.failed_fnids:
eligible.remove(p)
if not eligible:
bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables of any buildable targets.\nEnable debugging and see earlier logs to find unbuildable targets." % (self.get_rdependees_str(item), item))
bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData)
bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True))
raise bb.providers.NoRProvider(item)
if len(eligible) > 1 and numberPreferred == 0:
@@ -450,7 +437,7 @@ class TaskData:
providers_list.append(dataCache.pkg_fn[fn])
bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (%s);" % (item, ", ".join(providers_list)))
bb.msg.note(2, bb.msg.domain.Provider, "consider defining a PREFERRED_PROVIDER entry to match runtime %s" % item)
bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData)
bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True))
self.consider_msgs_cache.append(item)
if numberPreferred > 1:
@@ -460,7 +447,7 @@ class TaskData:
providers_list.append(dataCache.pkg_fn[fn])
bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (top %s entries preferred) (%s);" % (item, numberPreferred, ", ".join(providers_list)))
bb.msg.note(2, bb.msg.domain.Provider, "consider defining only one PREFERRED_PROVIDER entry to match runtime %s" % item)
bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData)
bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True))
self.consider_msgs_cache.append(item)
# run through the list until we find one that we can build
@@ -548,10 +535,7 @@ class TaskData:
except bb.providers.NoProvider:
targetid = self.getbuild_id(target)
if self.abort and targetid in self.external_targets:
if self.get_rdependees_str(target):
bb.msg.error(bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (target, self.get_dependees_str(target)))
else:
bb.msg.error(bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (target))
bb.msg.error(bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (target, self.get_dependees_str(target)))
raise
self.remove_buildtarget(targetid)
for target in self.get_unresolved_run_targets(dataCache):
@@ -560,7 +544,7 @@ class TaskData:
added = added + 1
except bb.providers.NoRProvider:
self.remove_runtarget(self.getrun_id(target))
bb.msg.debug(1, bb.msg.domain.TaskData, "Resolved " + str(added) + " extra dependencies")
bb.msg.debug(1, bb.msg.domain.TaskData, "Resolved " + str(added) + " extra dependecies")
if added == 0:
break
# self.dump_data()

View File

@@ -1,18 +0,0 @@
#
# BitBake UI Implementation
#
# Copyright (C) 2006-2007 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

View File

@@ -1,18 +0,0 @@
#
# BitBake UI Implementation
#
# Copyright (C) 2006-2007 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

View File

@@ -1,457 +0,0 @@
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2008 Intel Corporation
#
# Authored by Rob Bradford <rob@linux.intel.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import gtk
import gobject
import threading
import os
import datetime
import time
class BuildConfiguration:
""" Represents a potential *or* historic *or* concrete build. It
encompasses all the things that we need to tell bitbake to do to make it
build what we want it to build.
It also stored the metadata URL and the set of possible machines (and the
distros / images / uris for these. Apart from the metdata URL these are
not serialised to file (since they may be transient). In some ways this
functionality might be shifted to the loader class."""
def __init__ (self):
self.metadata_url = None
# Tuple of (distros, image, urls)
self.machine_options = {}
self.machine = None
self.distro = None
self.image = None
self.urls = []
self.extra_urls = []
self.extra_pkgs = []
def get_machines_model (self):
model = gtk.ListStore (gobject.TYPE_STRING)
for machine in self.machine_options.keys():
model.append ([machine])
return model
def get_distro_and_images_models (self, machine):
distro_model = gtk.ListStore (gobject.TYPE_STRING)
for distro in self.machine_options[machine][0]:
distro_model.append ([distro])
image_model = gtk.ListStore (gobject.TYPE_STRING)
for image in self.machine_options[machine][1]:
image_model.append ([image])
return (distro_model, image_model)
def get_repos (self):
self.urls = self.machine_options[self.machine][2]
return self.urls
# It might be a lot lot better if we stored these in like, bitbake conf
# file format.
@staticmethod
def load_from_file (filename):
f = open (filename, "r")
conf = BuildConfiguration()
for line in f.readlines():
data = line.split (";")[1]
if (line.startswith ("metadata-url;")):
conf.metadata_url = data.strip()
continue
if (line.startswith ("url;")):
conf.urls += [data.strip()]
continue
if (line.startswith ("extra-url;")):
conf.extra_urls += [data.strip()]
continue
if (line.startswith ("machine;")):
conf.machine = data.strip()
continue
if (line.startswith ("distribution;")):
conf.distro = data.strip()
continue
if (line.startswith ("image;")):
conf.image = data.strip()
continue
f.close ()
return conf
# Serialise to a file. This is part of the build process and we use this
# to be able to repeat a given build (using the same set of parameters)
# but also so that we can include the details of the image / machine /
# distro in the build manager tree view.
def write_to_file (self, filename):
f = open (filename, "w")
lines = []
if (self.metadata_url):
lines += ["metadata-url;%s\n" % (self.metadata_url)]
for url in self.urls:
lines += ["url;%s\n" % (url)]
for url in self.extra_urls:
lines += ["extra-url;%s\n" % (url)]
if (self.machine):
lines += ["machine;%s\n" % (self.machine)]
if (self.distro):
lines += ["distribution;%s\n" % (self.distro)]
if (self.image):
lines += ["image;%s\n" % (self.image)]
f.writelines (lines)
f.close ()
class BuildResult(gobject.GObject):
""" Represents an historic build. Perhaps not successful. But it includes
things such as the files that are in the directory (the output from the
build) as well as a deserialised BuildConfiguration file that is stored in
".conf" in the directory for the build.
This is GObject so that it can be included in the TreeStore."""
(STATE_COMPLETE, STATE_FAILED, STATE_ONGOING) = \
(0, 1, 2)
def __init__ (self, parent, identifier):
gobject.GObject.__init__ (self)
self.date = None
self.files = []
self.status = None
self.identifier = identifier
self.path = os.path.join (parent, identifier)
# Extract the date, since the directory name is of the
# format build-<year><month><day>-<ordinal> we can easily
# pull it out.
# TODO: Better to stat a file?
(_ , date, revision) = identifier.split ("-")
print date
year = int (date[0:4])
month = int (date[4:6])
day = int (date[6:8])
self.date = datetime.date (year, month, day)
self.conf = None
# By default builds are STATE_FAILED unless we find a "complete" file
# in which case they are STATE_COMPLETE
self.state = BuildResult.STATE_FAILED
for file in os.listdir (self.path):
if (file.startswith (".conf")):
conffile = os.path.join (self.path, file)
self.conf = BuildConfiguration.load_from_file (conffile)
elif (file.startswith ("complete")):
self.state = BuildResult.STATE_COMPLETE
else:
self.add_file (file)
def add_file (self, file):
# Just add the file for now. Don't care about the type.
self.files += [(file, None)]
class BuildManagerModel (gtk.TreeStore):
""" Model for the BuildManagerTreeView. This derives from gtk.TreeStore
but it abstracts nicely what the columns mean and the setup of the columns
in the model. """
(COL_IDENT, COL_DESC, COL_MACHINE, COL_DISTRO, COL_BUILD_RESULT, COL_DATE, COL_STATE) = \
(0, 1, 2, 3, 4, 5, 6)
def __init__ (self):
gtk.TreeStore.__init__ (self,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_OBJECT,
gobject.TYPE_INT64,
gobject.TYPE_INT)
class BuildManager (gobject.GObject):
""" This class manages the historic builds that have been found in the
"results" directory but is also used for starting a new build."""
__gsignals__ = {
'population-finished' : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
'populate-error' : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
())
}
def update_build_result (self, result, iter):
# Convert the date into something we can sort by.
date = long (time.mktime (result.date.timetuple()))
# Add a top level entry for the build
self.model.set (iter,
BuildManagerModel.COL_IDENT, result.identifier,
BuildManagerModel.COL_DESC, result.conf.image,
BuildManagerModel.COL_MACHINE, result.conf.machine,
BuildManagerModel.COL_DISTRO, result.conf.distro,
BuildManagerModel.COL_BUILD_RESULT, result,
BuildManagerModel.COL_DATE, date,
BuildManagerModel.COL_STATE, result.state)
# And then we use the files in the directory as the children for the
# top level iter.
for file in result.files:
self.model.append (iter, (None, file[0], None, None, None, date, -1))
# This function is called as an idle by the BuildManagerPopulaterThread
def add_build_result (self, result):
gtk.gdk.threads_enter()
self.known_builds += [result]
self.update_build_result (result, self.model.append (None))
gtk.gdk.threads_leave()
def notify_build_finished (self):
# This is a bit of a hack. If we have a running build running then we
# will have a row in the model in STATE_ONGOING. Find it and make it
# as if it was a proper historic build (well, it is completed now....)
# We need to use the iters here rather than the Python iterator
# interface to the model since we need to pass it into
# update_build_result
iter = self.model.get_iter_first()
while (iter):
(ident, state) = self.model.get(iter,
BuildManagerModel.COL_IDENT,
BuildManagerModel.COL_STATE)
if state == BuildResult.STATE_ONGOING:
result = BuildResult (self.results_directory, ident)
self.update_build_result (result, iter)
iter = self.model.iter_next(iter)
def notify_build_succeeded (self):
# Write the "complete" file so that when we create the BuildResult
# object we put into the model
complete_file_path = os.path.join (self.cur_build_directory, "complete")
f = file (complete_file_path, "w")
f.close()
self.notify_build_finished()
def notify_build_failed (self):
# Without a "complete" file then this will mark the build as failed:
self.notify_build_finished()
# This function is called as an idle
def emit_population_finished_signal (self):
gtk.gdk.threads_enter()
self.emit ("population-finished")
gtk.gdk.threads_leave()
class BuildManagerPopulaterThread (threading.Thread):
def __init__ (self, manager, directory):
threading.Thread.__init__ (self)
self.manager = manager
self.directory = directory
def run (self):
# For each of the "build-<...>" directories ..
if os.path.exists (self.directory):
for directory in os.listdir (self.directory):
if not directory.startswith ("build-"):
continue
build_result = BuildResult (self.directory, directory)
self.manager.add_build_result (build_result)
gobject.idle_add (BuildManager.emit_population_finished_signal,
self.manager)
def __init__ (self, server, results_directory):
gobject.GObject.__init__ (self)
# The builds that we've found from walking the result directory
self.known_builds = []
# Save out the bitbake server, we need this for issuing commands to
# the cooker:
self.server = server
# The TreeStore that we use
self.model = BuildManagerModel ()
# The results directory is where we create (and look for) the
# build-<xyz>-<n> directories. We need to populate ourselves from
# directory
self.results_directory = results_directory
self.populate_from_directory (self.results_directory)
def populate_from_directory (self, directory):
thread = BuildManager.BuildManagerPopulaterThread (self, directory)
thread.start()
# Come up with the name for the next build ident by combining "build-"
# with the date formatted as yyyymmdd and then an ordinal. We do this by
# an optimistic algorithm incrementing the ordinal if we find that it
# already exists.
def get_next_build_ident (self):
today = datetime.date.today ()
datestr = str (today.year) + str (today.month) + str (today.day)
revision = 0
test_name = "build-%s-%d" % (datestr, revision)
test_path = os.path.join (self.results_directory, test_name)
while (os.path.exists (test_path)):
revision += 1
test_name = "build-%s-%d" % (datestr, revision)
test_path = os.path.join (self.results_directory, test_name)
return test_name
# Take a BuildConfiguration and then try and build it based on the
# parameters of that configuration. S
def do_build (self, conf):
server = self.server
# Work out the build directory. Note we actually create the
# directories here since we need to write the ".conf" file. Otherwise
# we could have relied on bitbake's builder thread to actually make
# the directories as it proceeds with the build.
ident = self.get_next_build_ident ()
build_directory = os.path.join (self.results_directory,
ident)
self.cur_build_directory = build_directory
os.makedirs (build_directory)
conffile = os.path.join (build_directory, ".conf")
conf.write_to_file (conffile)
# Add a row to the model representing this ongoing build. It's kinda a
# fake entry. If this build completes or fails then this gets updated
# with the real stuff like the historic builds
date = long (time.time())
self.model.append (None, (ident, conf.image, conf.machine, conf.distro,
None, date, BuildResult.STATE_ONGOING))
try:
server.runCommand(["setVariable", "BUILD_IMAGES_FROM_FEEDS", 1])
server.runCommand(["setVariable", "MACHINE", conf.machine])
server.runCommand(["setVariable", "DISTRO", conf.distro])
server.runCommand(["setVariable", "PACKAGE_CLASSES", "package_ipk"])
server.runCommand(["setVariable", "BBFILES", \
"""${OEROOT}/meta/packages/*/*.bb ${OEROOT}/meta-moblin/packages/*/*.bb"""])
server.runCommand(["setVariable", "TMPDIR", "${OEROOT}/build/tmp"])
server.runCommand(["setVariable", "IPK_FEED_URIS", \
" ".join(conf.get_repos())])
server.runCommand(["setVariable", "DEPLOY_DIR_IMAGE",
build_directory])
server.runCommand(["buildTargets", [conf.image], "rootfs"])
except Exception, e:
print e
class BuildManagerTreeView (gtk.TreeView):
""" The tree view for the build manager. This shows the historic builds
and so forth. """
# We use this function to control what goes in the cell since we store
# the date in the model as seconds since the epoch (for sorting) and so we
# need to make it human readable.
def date_format_custom_cell_data_func (self, col, cell, model, iter):
date = model.get (iter, BuildManagerModel.COL_DATE)[0]
datestr = time.strftime("%A %d %B %Y", time.localtime(date))
cell.set_property ("text", datestr)
# This format function controls what goes in the cell. We use this to map
# the integer state to a string and also to colourise the text
def state_format_custom_cell_data_fun (self, col, cell, model, iter):
state = model.get (iter, BuildManagerModel.COL_STATE)[0]
if (state == BuildResult.STATE_ONGOING):
cell.set_property ("text", "Active")
cell.set_property ("foreground", "#000000")
elif (state == BuildResult.STATE_FAILED):
cell.set_property ("text", "Failed")
cell.set_property ("foreground", "#ff0000")
elif (state == BuildResult.STATE_COMPLETE):
cell.set_property ("text", "Complete")
cell.set_property ("foreground", "#00ff00")
else:
cell.set_property ("text", "")
def __init__ (self):
gtk.TreeView.__init__(self)
# Misc descriptiony thing
renderer = gtk.CellRendererText ()
col = gtk.TreeViewColumn (None, renderer,
text=BuildManagerModel.COL_DESC)
self.append_column (col)
# Machine
renderer = gtk.CellRendererText ()
col = gtk.TreeViewColumn ("Machine", renderer,
text=BuildManagerModel.COL_MACHINE)
self.append_column (col)
# distro
renderer = gtk.CellRendererText ()
col = gtk.TreeViewColumn ("Distribution", renderer,
text=BuildManagerModel.COL_DISTRO)
self.append_column (col)
# date (using a custom function for formatting the cell contents it
# takes epoch -> human readable string)
renderer = gtk.CellRendererText ()
col = gtk.TreeViewColumn ("Date", renderer,
text=BuildManagerModel.COL_DATE)
self.append_column (col)
col.set_cell_data_func (renderer,
self.date_format_custom_cell_data_func)
# For status.
renderer = gtk.CellRendererText ()
col = gtk.TreeViewColumn ("Status", renderer,
text = BuildManagerModel.COL_STATE)
self.append_column (col)
col.set_cell_data_func (renderer,
self.state_format_custom_cell_data_fun)

View File

@@ -1,606 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Mon Nov 10 12:24:12 2008 -->
<glade-interface>
<widget class="GtkDialog" id="build_dialog">
<property name="title" translatable="yes">Start a build</property>
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkTable" id="build_table">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="n_rows">7</property>
<property name="n_columns">3</property>
<property name="column_spacing">5</property>
<property name="row_spacing">6</property>
<child>
<widget class="GtkAlignment" id="status_alignment">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkHBox" id="status_hbox">
<property name="spacing">6</property>
<child>
<widget class="GtkImage" id="status_image">
<property name="visible">True</property>
<property name="no_show_all">True</property>
<property name="xalign">0</property>
<property name="stock">gtk-dialog-error</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="status_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">If you see this text something is wrong...</property>
<property name="use_markup">True</property>
<property name="use_underline">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Build configuration&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="image_combo">
<property name="visible">True</property>
<property name="sensitive">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="image_label">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Image:</property>
</widget>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="distribution_combo">
<property name="visible">True</property>
<property name="sensitive">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="distribution_label">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Distribution:</property>
</widget>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkComboBox" id="machine_combo">
<property name="visible">True</property>
<property name="sensitive">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="machine_label">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Machine:</property>
</widget>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="refresh_button">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-refresh</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="location_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width_chars">32</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Location:</property>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Repository&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="right_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkDialog" id="dialog2">
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="n_rows">7</property>
<property name="n_columns">3</property>
<property name="column_spacing">6</property>
<property name="row_spacing">6</property>
<child>
<widget class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Repositories&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="right_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment4">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<widget class="GtkTreeView" id="treeview1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_clickable">True</property>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Additional packages&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="right_attach">3</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment6">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="xscale">0</property>
<child>
<widget class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Location: </property>
</widget>
</child>
</widget>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment7">
<property name="visible">True</property>
<property name="xalign">1</property>
<property name="xscale">0</property>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="spacing">5</property>
<child>
<widget class="GtkButton" id="button7">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-remove</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="button6">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-edit</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button5">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-add</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment5">
<property name="visible">True</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Search:</property>
</widget>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entry2">
<property name="visible">True</property>
<property name="can_focus">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkAlignment" id="alignment8">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="left_padding">12</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<widget class="GtkTreeView" id="treeview2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_clickable">True</property>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="right_attach">3</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="button4">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">gtk-close</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
<widget class="GtkWindow" id="main_window">
<child>
<widget class="GtkVBox" id="main_window_vbox">
<property name="visible">True</property>
<child>
<widget class="GtkToolbar" id="main_toolbar">
<property name="visible">True</property>
<child>
<widget class="GtkToolButton" id="main_toolbutton_build">
<property name="visible">True</property>
<property name="label" translatable="yes">Build</property>
<property name="stock_id">gtk-execute</property>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkVPaned" id="vpaned1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkScrolledWindow" id="results_scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="resize">False</property>
<property name="shrink">True</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="progress_scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@@ -1,180 +0,0 @@
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2008 Intel Corporation
#
# Authored by Rob Bradford <rob@linux.intel.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import gtk
import gobject
class RunningBuildModel (gtk.TreeStore):
(COL_TYPE, COL_PACKAGE, COL_TASK, COL_MESSAGE, COL_ICON, COL_ACTIVE) = (0, 1, 2, 3, 4, 5)
def __init__ (self):
gtk.TreeStore.__init__ (self,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_BOOLEAN)
class RunningBuild (gobject.GObject):
__gsignals__ = {
'build-succeeded' : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
'build-failed' : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
())
}
pids_to_task = {}
tasks_to_iter = {}
def __init__ (self):
gobject.GObject.__init__ (self)
self.model = RunningBuildModel()
def handle_event (self, event):
# Handle an event from the event queue, this may result in updating
# the model and thus the UI. Or it may be to tell us that the build
# has finished successfully (or not, as the case may be.)
parent = None
pid = 0
package = None
task = None
# If we have a pid attached to this message/event try and get the
# (package, task) pair for it. If we get that then get the parent iter
# for the message.
if hasattr(event, 'pid'):
pid = event.pid
if self.pids_to_task.has_key(pid):
(package, task) = self.pids_to_task[pid]
parent = self.tasks_to_iter[(package, task)]
if isinstance(event, bb.msg.Msg):
# Set a pretty icon for the message based on it's type.
if isinstance(event, bb.msg.MsgWarn):
icon = "dialog-warning"
elif isinstance(event, bb.msg.MsgErr):
icon = "dialog-error"
else:
icon = None
# Ignore the "Running task i of n .." messages
if (event._message.startswith ("Running task")):
return
# Add the message to the tree either at the top level if parent is
# None otherwise as a descendent of a task.
self.model.append (parent,
(event.__name__.split()[-1], # e.g. MsgWarn, MsgError
package,
task,
event._message,
icon,
False))
elif isinstance(event, bb.build.TaskStarted):
(package, task) = (event._package, event._task)
# Save out this PID.
self.pids_to_task[pid] = (package,task)
# Check if we already have this package in our model. If so then
# that can be the parent for the task. Otherwise we create a new
# top level for the package.
if (self.tasks_to_iter.has_key ((package, None))):
parent = self.tasks_to_iter[(package, None)]
else:
parent = self.model.append (None, (None,
package,
None,
"Package: %s" % (package),
None,
False))
self.tasks_to_iter[(package, None)] = parent
# Because this parent package now has an active child mark it as
# such.
self.model.set(parent, self.model.COL_ICON, "gtk-execute")
# Add an entry in the model for this task
i = self.model.append (parent, (None,
package,
task,
"Task: %s" % (task),
None,
False))
# Save out the iter so that we can find it when we have a message
# that we need to attach to a task.
self.tasks_to_iter[(package, task)] = i
# Mark this task as active.
self.model.set(i, self.model.COL_ICON, "gtk-execute")
elif isinstance(event, bb.build.Task):
if isinstance(event, bb.build.TaskFailed):
# Mark the task as failed
i = self.tasks_to_iter[(package, task)]
self.model.set(i, self.model.COL_ICON, "dialog-error")
# Mark the parent package as failed
i = self.tasks_to_iter[(package, None)]
self.model.set(i, self.model.COL_ICON, "dialog-error")
else:
# Mark the task as inactive
i = self.tasks_to_iter[(package, task)]
self.model.set(i, self.model.COL_ICON, None)
# Mark the parent package as inactive
i = self.tasks_to_iter[(package, None)]
self.model.set(i, self.model.COL_ICON, None)
# Clear the iters and the pids since when the task goes away the
# pid will no longer be used for messages
del self.tasks_to_iter[(package, task)]
del self.pids_to_task[pid]
elif isinstance(event, bb.event.BuildCompleted):
failures = int (event._failures)
# Emit the appropriate signal depending on the number of failures
if (failures > 1):
self.emit ("build-failed")
else:
self.emit ("build-succeeded")
class RunningBuildTreeView (gtk.TreeView):
def __init__ (self):
gtk.TreeView.__init__ (self)
# The icon that indicates whether we're building or failed.
renderer = gtk.CellRendererPixbuf ()
col = gtk.TreeViewColumn ("Status", renderer)
col.add_attribute (renderer, "icon-name", 4)
self.append_column (col)
# The message of the build.
renderer = gtk.CellRendererText ()
col = gtk.TreeViewColumn ("Message", renderer, text=3)
self.append_column (col)

View File

@@ -1,272 +0,0 @@
#
# BitBake Graphical GTK based Dependency Explorer
#
# Copyright (C) 2007 Ross Burton
# Copyright (C) 2007 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import gobject
import gtk
import threading
import xmlrpclib
# Package Model
(COL_PKG_NAME) = (0)
# Dependency Model
(TYPE_DEP, TYPE_RDEP) = (0, 1)
(COL_DEP_TYPE, COL_DEP_PARENT, COL_DEP_PACKAGE) = (0, 1, 2)
class PackageDepView(gtk.TreeView):
def __init__(self, model, dep_type, label):
gtk.TreeView.__init__(self)
self.current = None
self.dep_type = dep_type
self.filter_model = model.filter_new()
self.filter_model.set_visible_func(self._filter)
self.set_model(self.filter_model)
#self.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
self.append_column(gtk.TreeViewColumn(label, gtk.CellRendererText(), text=COL_DEP_PACKAGE))
def _filter(self, model, iter):
(this_type, package) = model.get(iter, COL_DEP_TYPE, COL_DEP_PARENT)
if this_type != self.dep_type: return False
return package == self.current
def set_current_package(self, package):
self.current = package
self.filter_model.refilter()
class PackageReverseDepView(gtk.TreeView):
def __init__(self, model, label):
gtk.TreeView.__init__(self)
self.current = None
self.filter_model = model.filter_new()
self.filter_model.set_visible_func(self._filter)
self.set_model(self.filter_model)
self.append_column(gtk.TreeViewColumn(label, gtk.CellRendererText(), text=COL_DEP_PARENT))
def _filter(self, model, iter):
package = model.get_value(iter, COL_DEP_PACKAGE)
return package == self.current
def set_current_package(self, package):
self.current = package
self.filter_model.refilter()
class DepExplorer(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.set_title("Dependency Explorer")
self.set_default_size(500, 500)
self.connect("delete-event", gtk.main_quit)
# Create the data models
self.pkg_model = gtk.ListStore(gobject.TYPE_STRING)
self.depends_model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING)
pane = gtk.HPaned()
pane.set_position(250)
self.add(pane)
# The master list of packages
scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_IN)
self.pkg_treeview = gtk.TreeView(self.pkg_model)
self.pkg_treeview.get_selection().connect("changed", self.on_cursor_changed)
self.pkg_treeview.append_column(gtk.TreeViewColumn("Package", gtk.CellRendererText(), text=COL_PKG_NAME))
pane.add1(scrolled)
scrolled.add(self.pkg_treeview)
box = gtk.VBox(homogeneous=True, spacing=4)
# Runtime Depends
scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_IN)
self.rdep_treeview = PackageDepView(self.depends_model, TYPE_RDEP, "Runtime Depends")
self.rdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
scrolled.add(self.rdep_treeview)
box.add(scrolled)
# Build Depends
scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_IN)
self.dep_treeview = PackageDepView(self.depends_model, TYPE_DEP, "Build Depends")
self.dep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
scrolled.add(self.dep_treeview)
box.add(scrolled)
pane.add2(box)
# Reverse Depends
scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_IN)
self.revdep_treeview = PackageReverseDepView(self.depends_model, "Reverse Depends")
self.revdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PARENT)
scrolled.add(self.revdep_treeview)
box.add(scrolled)
pane.add2(box)
self.show_all()
def on_package_activated(self, treeview, path, column, data_col):
model = treeview.get_model()
package = model.get_value(model.get_iter(path), data_col)
pkg_path = []
def finder(model, path, iter, needle):
package = model.get_value(iter, COL_PKG_NAME)
if package == needle:
pkg_path.append(path)
return True
else:
return False
self.pkg_model.foreach(finder, package)
if pkg_path:
self.pkg_treeview.get_selection().select_path(pkg_path[0])
self.pkg_treeview.scroll_to_cell(pkg_path[0])
def on_cursor_changed(self, selection):
(model, it) = selection.get_selected()
if iter is None:
current_package = None
else:
current_package = model.get_value(it, COL_PKG_NAME)
self.rdep_treeview.set_current_package(current_package)
self.dep_treeview.set_current_package(current_package)
self.revdep_treeview.set_current_package(current_package)
def parse(depgraph, pkg_model, depends_model):
for package in depgraph["pn"]:
pkg_model.set(pkg_model.append(), COL_PKG_NAME, package)
for package in depgraph["depends"]:
for depend in depgraph["depends"][package]:
depends_model.set (depends_model.append(),
COL_DEP_TYPE, TYPE_DEP,
COL_DEP_PARENT, package,
COL_DEP_PACKAGE, depend)
for package in depgraph["rdepends-pn"]:
for rdepend in depgraph["rdepends-pn"][package]:
depends_model.set (depends_model.append(),
COL_DEP_TYPE, TYPE_RDEP,
COL_DEP_PARENT, package,
COL_DEP_PACKAGE, rdepend)
class ProgressBar(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.set_title("Parsing .bb files, please wait...")
self.set_default_size(500, 0)
self.connect("delete-event", gtk.main_quit)
self.progress = gtk.ProgressBar()
self.add(self.progress)
self.show_all()
class gtkthread(threading.Thread):
quit = threading.Event()
def __init__(self, shutdown):
threading.Thread.__init__(self)
self.setDaemon(True)
self.shutdown = shutdown
def run(self):
gobject.threads_init()
gtk.gdk.threads_init()
gtk.main()
gtkthread.quit.set()
def init(server, eventHandler):
try:
cmdline = server.runCommand(["getCmdLineAction"])
if not cmdline or cmdline[0] != "generateDotGraph":
print "This UI is only compatible with the -g option"
return
ret = server.runCommand(["generateDepTreeEvent", cmdline[1], cmdline[2]])
if ret != True:
print "Couldn't run command! %s" % ret
return
except xmlrpclib.Fault, x:
print "XMLRPC Fault getting commandline:\n %s" % x
return
shutdown = 0
gtkgui = gtkthread(shutdown)
gtkgui.start()
gtk.gdk.threads_enter()
pbar = ProgressBar()
dep = DepExplorer()
gtk.gdk.threads_leave()
while True:
try:
event = eventHandler.waitEvent(0.25)
if gtkthread.quit.isSet():
break
if event is None:
continue
if isinstance(event, bb.event.ParseProgress):
x = event.sofar
y = event.total
if x == y:
print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors."
% ( event.cached, event.parsed, event.skipped, event.masked, event.errors))
pbar.hide()
gtk.gdk.threads_enter()
pbar.progress.set_fraction(float(x)/float(y))
pbar.progress.set_text("%d/%d (%2d %%)" % (x, y, x*100/y))
gtk.gdk.threads_leave()
continue
if isinstance(event, bb.event.DepTreeGenerated):
gtk.gdk.threads_enter()
parse(event._depgraph, dep.pkg_model, dep.depends_model)
gtk.gdk.threads_leave()
if isinstance(event, bb.command.CookerCommandCompleted):
continue
if isinstance(event, bb.command.CookerCommandFailed):
print "Command execution failed: %s" % event.error
break
if isinstance(event, bb.cooker.CookerExit):
break
continue
except KeyboardInterrupt:
if shutdown == 2:
print "\nThird Keyboard Interrupt, exit.\n"
break
if shutdown == 1:
print "\nSecond Keyboard Interrupt, stopping...\n"
server.runCommand(["stateStop"])
if shutdown == 0:
print "\nKeyboard Interrupt, closing down...\n"
server.runCommand(["stateShutdown"])
shutdown = shutdown + 1
pass

View File

@@ -1,77 +0,0 @@
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2008 Intel Corporation
#
# Authored by Rob Bradford <rob@linux.intel.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import gobject
import gtk
import xmlrpclib
from bb.ui.crumbs.runningbuild import RunningBuildTreeView, RunningBuild
def event_handle_idle_func (eventHandler, build):
# Consume as many messages as we can in the time available to us
event = eventHandler.getEvent()
while event:
build.handle_event (event)
event = eventHandler.getEvent()
return True
class MainWindow (gtk.Window):
def __init__ (self):
gtk.Window.__init__ (self, gtk.WINDOW_TOPLEVEL)
# Setup tree view and the scrolled window
scrolled_window = gtk.ScrolledWindow ()
self.add (scrolled_window)
self.cur_build_tv = RunningBuildTreeView()
scrolled_window.add (self.cur_build_tv)
def init (server, eventHandler):
gobject.threads_init()
gtk.gdk.threads_init()
window = MainWindow ()
window.show_all ()
# Create the object for the current build
running_build = RunningBuild ()
window.cur_build_tv.set_model (running_build.model)
try:
cmdline = server.runCommand(["getCmdLineAction"])
print cmdline
if not cmdline:
return 1
ret = server.runCommand(cmdline)
if ret != True:
print "Couldn't get default commandline! %s" % ret
return 1
except xmlrpclib.Fault, x:
print "XMLRPC Fault getting commandline:\n %s" % x
return 1
# Use a timeout function for probing the event queue to find out if we
# have a message waiting for us.
gobject.timeout_add (200,
event_handle_idle_func,
eventHandler,
running_build)
gtk.main()

View File

@@ -1,182 +0,0 @@
#
# BitBake (No)TTY UI Implementation
#
# Handling output to TTYs or files (no TTY)
#
# Copyright (C) 2006-2007 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
import sys
import itertools
import xmlrpclib
from bb import ui
from bb.ui import uihelper
parsespin = itertools.cycle( r'|/-\\' )
def init(server, eventHandler):
# Get values of variables which control our output
includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"])
loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
helper = uihelper.BBUIHelper()
try:
cmdline = server.runCommand(["getCmdLineAction"])
#print cmdline
if not cmdline:
return 1
ret = server.runCommand(cmdline)
if ret != True:
print "Couldn't get default commandline! %s" % ret
return 1
except xmlrpclib.Fault, x:
print "XMLRPC Fault getting commandline:\n %s" % x
return 1
shutdown = 0
return_value = 0
while True:
try:
event = eventHandler.waitEvent(0.25)
if event is None:
continue
#print event
helper.eventHandler(event)
if isinstance(event, bb.runqueue.runQueueExitWait):
if not shutdown:
shutdown = 1
if shutdown and helper.needUpdate:
activetasks, failedtasks = helper.getTasks()
if activetasks:
print "Waiting for %s active tasks to finish:" % len(activetasks)
tasknum = 1
for task in activetasks:
print "%s: %s (pid %s)" % (tasknum, activetasks[task]["title"], task)
tasknum = tasknum + 1
if isinstance(event, bb.msg.MsgPlain):
print event._message
continue
if isinstance(event, bb.msg.MsgDebug):
print 'DEBUG: ' + event._message
continue
if isinstance(event, bb.msg.MsgNote):
print 'NOTE: ' + event._message
continue
if isinstance(event, bb.msg.MsgWarn):
print 'WARNING: ' + event._message
continue
if isinstance(event, bb.msg.MsgError):
return_value = 1
print 'ERROR: ' + event._message
continue
if isinstance(event, bb.msg.MsgFatal):
return_value = 1
print 'FATAL: ' + event._message
break
if isinstance(event, bb.build.TaskFailed):
return_value = 1
logfile = event.logfile
if logfile:
print "ERROR: Logfile of failure stored in: %s" % logfile
if 1 or includelogs:
print "Log data follows:"
f = open(logfile, "r")
lines = []
while True:
l = f.readline()
if l == '':
break
l = l.rstrip()
if loglines:
lines.append(' | %s' % l)
if len(lines) > int(loglines):
lines.pop(0)
else:
print '| %s' % l
f.close()
if lines:
for line in lines:
print line
if isinstance(event, bb.build.TaskBase):
print "NOTE: %s" % event._message
continue
if isinstance(event, bb.event.ParseProgress):
x = event.sofar
y = event.total
if os.isatty(sys.stdout.fileno()):
sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
sys.stdout.flush()
else:
if x == 1:
sys.stdout.write("Parsing .bb files, please wait...")
sys.stdout.flush()
if x == y:
sys.stdout.write("done.")
sys.stdout.flush()
if x == y:
print("\nParsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
% ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors))
continue
if isinstance(event, bb.command.CookerCommandCompleted):
break
if isinstance(event, bb.command.CookerCommandSetExitCode):
return_value = event.exitcode
continue
if isinstance(event, bb.command.CookerCommandFailed):
return_value = 1
print "Command execution failed: %s" % event.error
break
if isinstance(event, bb.cooker.CookerExit):
break
# ignore
if isinstance(event, bb.event.BuildStarted):
continue
if isinstance(event, bb.event.BuildCompleted):
continue
if isinstance(event, bb.event.MultipleProviders):
continue
if isinstance(event, bb.runqueue.runQueueEvent):
continue
if isinstance(event, bb.runqueue.runQueueExitWait):
continue
if isinstance(event, bb.event.StampUpdate):
continue
if isinstance(event, bb.event.ConfigParsed):
continue
if isinstance(event, bb.event.RecipeParsed):
continue
print "Unknown Event: %s" % event
except KeyboardInterrupt:
if shutdown == 2:
print "\nThird Keyboard Interrupt, exit.\n"
break
if shutdown == 1:
print "\nSecond Keyboard Interrupt, stopping...\n"
server.runCommand(["stateStop"])
if shutdown == 0:
print "\nKeyboard Interrupt, closing down...\n"
server.runCommand(["stateShutdown"])
shutdown = shutdown + 1
pass
return return_value

View File

@@ -1,335 +0,0 @@
#
# BitBake Curses UI Implementation
#
# Implements an ncurses frontend for the BitBake utility.
#
# Copyright (C) 2006 Michael 'Mickey' Lauer
# Copyright (C) 2006-2007 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
We have the following windows:
1.) Main Window: Shows what we are ultimately building and how far we are. Includes status bar
2.) Thread Activity Window: Shows one status line for every concurrent bitbake thread.
3.) Command Line Window: Contains an interactive command line where you can interact w/ Bitbake.
Basic window layout is like that:
|---------------------------------------------------------|
| <Main Window> | <Thread Activity Window> |
| | 0: foo do_compile complete|
| Building Gtk+-2.6.10 | 1: bar do_patch complete |
| Status: 60% | ... |
| | ... |
| | ... |
|---------------------------------------------------------|
|<Command Line Window> |
|>>> which virtual/kernel |
|openzaurus-kernel |
|>>> _ |
|---------------------------------------------------------|
"""
import os, sys, curses, itertools, time
import bb
import xmlrpclib
from bb import ui
from bb.ui import uihelper
parsespin = itertools.cycle( r'|/-\\' )
X = 0
Y = 1
WIDTH = 2
HEIGHT = 3
MAXSTATUSLENGTH = 32
class NCursesUI:
"""
NCurses UI Class
"""
class Window:
"""Base Window Class"""
def __init__( self, x, y, width, height, fg=curses.COLOR_BLACK, bg=curses.COLOR_WHITE ):
self.win = curses.newwin( height, width, y, x )
self.dimensions = ( x, y, width, height )
"""
if curses.has_colors():
color = 1
curses.init_pair( color, fg, bg )
self.win.bkgdset( ord(' '), curses.color_pair(color) )
else:
self.win.bkgdset( ord(' '), curses.A_BOLD )
"""
self.erase()
self.setScrolling()
self.win.noutrefresh()
def erase( self ):
self.win.erase()
def setScrolling( self, b = True ):
self.win.scrollok( b )
self.win.idlok( b )
def setBoxed( self ):
self.boxed = True
self.win.box()
self.win.noutrefresh()
def setText( self, x, y, text, *args ):
self.win.addstr( y, x, text, *args )
self.win.noutrefresh()
def appendText( self, text, *args ):
self.win.addstr( text, *args )
self.win.noutrefresh()
def drawHline( self, y ):
self.win.hline( y, 0, curses.ACS_HLINE, self.dimensions[WIDTH] )
self.win.noutrefresh()
class DecoratedWindow( Window ):
"""Base class for windows with a box and a title bar"""
def __init__( self, title, x, y, width, height, fg=curses.COLOR_BLACK, bg=curses.COLOR_WHITE ):
NCursesUI.Window.__init__( self, x+1, y+3, width-2, height-4, fg, bg )
self.decoration = NCursesUI.Window( x, y, width, height, fg, bg )
self.decoration.setBoxed()
self.decoration.win.hline( 2, 1, curses.ACS_HLINE, width-2 )
self.setTitle( title )
def setTitle( self, title ):
self.decoration.setText( 1, 1, title.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD )
#-------------------------------------------------------------------------#
# class TitleWindow( Window ):
#-------------------------------------------------------------------------#
# """Title Window"""
# def __init__( self, x, y, width, height ):
# NCursesUI.Window.__init__( self, x, y, width, height )
# version = bb.__version__
# title = "BitBake %s" % version
# credit = "(C) 2003-2007 Team BitBake"
# #self.win.hline( 2, 1, curses.ACS_HLINE, width-2 )
# self.win.border()
# self.setText( 1, 1, title.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD )
# self.setText( 1, 2, credit.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD )
#-------------------------------------------------------------------------#
class ThreadActivityWindow( DecoratedWindow ):
#-------------------------------------------------------------------------#
"""Thread Activity Window"""
def __init__( self, x, y, width, height ):
NCursesUI.DecoratedWindow.__init__( self, "Thread Activity", x, y, width, height )
def setStatus( self, thread, text ):
line = "%02d: %s" % ( thread, text )
width = self.dimensions[WIDTH]
if ( len(line) > width ):
line = line[:width-3] + "..."
else:
line = line.ljust( width )
self.setText( 0, thread, line )
#-------------------------------------------------------------------------#
class MainWindow( DecoratedWindow ):
#-------------------------------------------------------------------------#
"""Main Window"""
def __init__( self, x, y, width, height ):
self.StatusPosition = width - MAXSTATUSLENGTH
NCursesUI.DecoratedWindow.__init__( self, None, x, y, width, height )
curses.nl()
def setTitle( self, title ):
title = "BitBake %s" % bb.__version__
self.decoration.setText( 2, 1, title, curses.A_BOLD )
self.decoration.setText( self.StatusPosition - 8, 1, "Status:", curses.A_BOLD )
def setStatus(self, status):
while len(status) < MAXSTATUSLENGTH:
status = status + " "
self.decoration.setText( self.StatusPosition, 1, status, curses.A_BOLD )
#-------------------------------------------------------------------------#
class ShellOutputWindow( DecoratedWindow ):
#-------------------------------------------------------------------------#
"""Interactive Command Line Output"""
def __init__( self, x, y, width, height ):
NCursesUI.DecoratedWindow.__init__( self, "Command Line Window", x, y, width, height )
#-------------------------------------------------------------------------#
class ShellInputWindow( Window ):
#-------------------------------------------------------------------------#
"""Interactive Command Line Input"""
def __init__( self, x, y, width, height ):
NCursesUI.Window.__init__( self, x, y, width, height )
# put that to the top again from curses.textpad import Textbox
# self.textbox = Textbox( self.win )
# t = threading.Thread()
# t.run = self.textbox.edit
# t.start()
#-------------------------------------------------------------------------#
def main(self, stdscr, server, eventHandler):
#-------------------------------------------------------------------------#
height, width = stdscr.getmaxyx()
# for now split it like that:
# MAIN_y + THREAD_y = 2/3 screen at the top
# MAIN_x = 2/3 left, THREAD_y = 1/3 right
# CLI_y = 1/3 of screen at the bottom
# CLI_x = full
main_left = 0
main_top = 0
main_height = ( height / 3 * 2 )
main_width = ( width / 3 ) * 2
clo_left = main_left
clo_top = main_top + main_height
clo_height = height - main_height - main_top - 1
clo_width = width
cli_left = main_left
cli_top = clo_top + clo_height
cli_height = 1
cli_width = width
thread_left = main_left + main_width
thread_top = main_top
thread_height = main_height
thread_width = width - main_width
#tw = self.TitleWindow( 0, 0, width, main_top )
mw = self.MainWindow( main_left, main_top, main_width, main_height )
taw = self.ThreadActivityWindow( thread_left, thread_top, thread_width, thread_height )
clo = self.ShellOutputWindow( clo_left, clo_top, clo_width, clo_height )
cli = self.ShellInputWindow( cli_left, cli_top, cli_width, cli_height )
cli.setText( 0, 0, "BB>" )
mw.setStatus("Idle")
helper = uihelper.BBUIHelper()
shutdown = 0
try:
cmdline = server.runCommand(["getCmdLineAction"])
if not cmdline:
return
ret = server.runCommand(cmdline)
if ret != True:
print "Couldn't get default commandlind! %s" % ret
return
except xmlrpclib.Fault, x:
print "XMLRPC Fault getting commandline:\n %s" % x
return
exitflag = False
while not exitflag:
try:
event = eventHandler.waitEvent(0.25)
if not event:
continue
helper.eventHandler(event)
#mw.appendText("%s\n" % event[0])
if isinstance(event, bb.build.Task):
mw.appendText("NOTE: %s\n" % event._message)
if isinstance(event, bb.msg.MsgDebug):
mw.appendText('DEBUG: ' + event._message + '\n')
if isinstance(event, bb.msg.MsgNote):
mw.appendText('NOTE: ' + event._message + '\n')
if isinstance(event, bb.msg.MsgWarn):
mw.appendText('WARNING: ' + event._message + '\n')
if isinstance(event, bb.msg.MsgError):
mw.appendText('ERROR: ' + event._message + '\n')
if isinstance(event, bb.msg.MsgFatal):
mw.appendText('FATAL: ' + event._message + '\n')
if isinstance(event, bb.event.ParseProgress):
x = event.sofar
y = event.total
if x == y:
mw.setStatus("Idle")
mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked."
% ( event.cached, event.parsed, event.skipped, event.masked ))
else:
mw.setStatus("Parsing: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
# if isinstance(event, bb.build.TaskFailed):
# if event.logfile:
# if data.getVar("BBINCLUDELOGS", d):
# bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile)
# number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
# if number_of_lines:
# os.system('tail -n%s %s' % (number_of_lines, logfile))
# else:
# f = open(logfile, "r")
# while True:
# l = f.readline()
# if l == '':
# break
# l = l.rstrip()
# print '| %s' % l
# f.close()
# else:
# bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile)
if isinstance(event, bb.command.CookerCommandCompleted):
exitflag = True
if isinstance(event, bb.command.CookerCommandFailed):
mw.appendText("Command execution failed: %s" % event.error)
time.sleep(2)
exitflag = True
if isinstance(event, bb.cooker.CookerExit):
exitflag = True
if helper.needUpdate:
activetasks, failedtasks = helper.getTasks()
taw.erase()
taw.setText(0, 0, "")
if activetasks:
taw.appendText("Active Tasks:\n")
for task in activetasks:
taw.appendText(task)
if failedtasks:
taw.appendText("Failed Tasks:\n")
for task in failedtasks:
taw.appendText(task)
curses.doupdate()
except KeyboardInterrupt:
if shutdown == 2:
mw.appendText("Third Keyboard Interrupt, exit.\n")
exitflag = True
if shutdown == 1:
mw.appendText("Second Keyboard Interrupt, stopping...\n")
server.runCommand(["stateStop"])
if shutdown == 0:
mw.appendText("Keyboard Interrupt, closing down...\n")
server.runCommand(["stateShutdown"])
shutdown = shutdown + 1
pass
def init(server, eventHandler):
if not os.isatty(sys.stdout.fileno()):
print "FATAL: Unable to run 'ncurses' UI without a TTY."
return
ui = NCursesUI()
try:
curses.wrapper(ui.main, server, eventHandler)
except:
import traceback
traceback.print_exc()

View File

@@ -1,425 +0,0 @@
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2008 Intel Corporation
#
# Authored by Rob Bradford <rob@linux.intel.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import gtk
import gobject
import gtk.glade
import threading
import urllib2
import os
from bb.ui.crumbs.buildmanager import BuildManager, BuildConfiguration
from bb.ui.crumbs.buildmanager import BuildManagerTreeView
from bb.ui.crumbs.runningbuild import RunningBuild, RunningBuildTreeView
# The metadata loader is used by the BuildSetupDialog to download the
# available options to populate the dialog
class MetaDataLoader(gobject.GObject):
""" This class provides the mechanism for loading the metadata (the
fetching and parsing) from a given URL. The metadata encompasses details
on what machines are available. The distribution and images available for
the machine and the the uris to use for building the given machine."""
__gsignals__ = {
'success' : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
()),
'error' : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_STRING,))
}
# We use these little helper functions to ensure that we take the gdk lock
# when emitting the signal. These functions are called as idles (so that
# they happen in the gtk / main thread's main loop.
def emit_error_signal (self, remark):
gtk.gdk.threads_enter()
self.emit ("error", remark)
gtk.gdk.threads_leave()
def emit_success_signal (self):
gtk.gdk.threads_enter()
self.emit ("success")
gtk.gdk.threads_leave()
def __init__ (self):
gobject.GObject.__init__ (self)
class LoaderThread(threading.Thread):
""" This class provides an asynchronous loader for the metadata (by
using threads and signals). This is useful since the metadata may be
at a remote URL."""
class LoaderImportException (Exception):
pass
def __init__(self, loader, url):
threading.Thread.__init__ (self)
self.url = url
self.loader = loader
def run (self):
result = {}
try:
f = urllib2.urlopen (self.url)
# Parse the metadata format. The format is....
# <machine>;<default distro>|<distro>...;<default image>|<image>...;<type##url>|...
for line in f.readlines():
components = line.split(";")
if (len (components) < 4):
raise MetaDataLoader.LoaderThread.LoaderImportException
machine = components[0]
distros = components[1].split("|")
images = components[2].split("|")
urls = components[3].split("|")
result[machine] = (distros, images, urls)
# Create an object representing this *potential*
# configuration. It can become concrete if the machine, distro
# and image are all chosen in the UI
configuration = BuildConfiguration()
configuration.metadata_url = self.url
configuration.machine_options = result
self.loader.configuration = configuration
# Emit that we've actually got a configuration
gobject.idle_add (MetaDataLoader.emit_success_signal,
self.loader)
except MetaDataLoader.LoaderThread.LoaderImportException, e:
gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader,
"Repository metadata corrupt")
except Exception, e:
gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader,
"Unable to download repository metadata")
print e
def try_fetch_from_url (self, url):
# Try and download the metadata. Firing a signal if successful
thread = MetaDataLoader.LoaderThread(self, url)
thread.start()
class BuildSetupDialog (gtk.Dialog):
RESPONSE_BUILD = 1
# A little helper method that just sets the states on the widgets based on
# whether we've got good metadata or not.
def set_configurable (self, configurable):
if (self.configurable == configurable):
return
self.configurable = configurable
for widget in self.conf_widgets:
widget.set_sensitive (configurable)
if not configurable:
self.machine_combo.set_active (-1)
self.distribution_combo.set_active (-1)
self.image_combo.set_active (-1)
# GTK widget callbacks
def refresh_button_clicked (self, button):
# Refresh button clicked.
url = self.location_entry.get_chars (0, -1)
self.loader.try_fetch_from_url(url)
def repository_entry_editable_changed (self, entry):
if (len (entry.get_chars (0, -1)) > 0):
self.refresh_button.set_sensitive (True)
else:
self.refresh_button.set_sensitive (False)
self.clear_status_message()
# If we were previously configurable we are no longer since the
# location entry has been changed
self.set_configurable (False)
def machine_combo_changed (self, combobox):
active_iter = combobox.get_active_iter()
if not active_iter:
return
model = combobox.get_model()
if model:
chosen_machine = model.get (active_iter, 0)[0]
(distros_model, images_model) = \
self.loader.configuration.get_distro_and_images_models (chosen_machine)
self.distribution_combo.set_model (distros_model)
self.image_combo.set_model (images_model)
# Callbacks from the loader
def loader_success_cb (self, loader):
self.status_image.set_from_icon_name ("info",
gtk.ICON_SIZE_BUTTON)
self.status_image.show()
self.status_label.set_label ("Repository metadata successfully downloaded")
# Set the models on the combo boxes based on the models generated from
# the configuration that the loader has created
# We just need to set the machine here, that then determines the
# distro and image options. Cunning huh? :-)
self.configuration = self.loader.configuration
model = self.configuration.get_machines_model ()
self.machine_combo.set_model (model)
self.set_configurable (True)
def loader_error_cb (self, loader, message):
self.status_image.set_from_icon_name ("error",
gtk.ICON_SIZE_BUTTON)
self.status_image.show()
self.status_label.set_text ("Error downloading repository metadata")
for widget in self.conf_widgets:
widget.set_sensitive (False)
def clear_status_message (self):
self.status_image.hide()
self.status_label.set_label (
"""<i>Enter the repository location and press _Refresh</i>""")
def __init__ (self):
gtk.Dialog.__init__ (self)
# Cancel
self.add_button (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
# Build
button = gtk.Button ("_Build", None, True)
image = gtk.Image ()
image.set_from_stock (gtk.STOCK_EXECUTE,gtk.ICON_SIZE_BUTTON)
button.set_image (image)
self.add_action_widget (button, BuildSetupDialog.RESPONSE_BUILD)
button.show_all ()
# Pull in *just* the table from the Glade XML data.
gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade",
root = "build_table")
table = gxml.get_widget ("build_table")
self.vbox.pack_start (table, True, False, 0)
# Grab all the widgets that we need to turn on/off when we refresh...
self.conf_widgets = []
self.conf_widgets += [gxml.get_widget ("machine_label")]
self.conf_widgets += [gxml.get_widget ("distribution_label")]
self.conf_widgets += [gxml.get_widget ("image_label")]
self.conf_widgets += [gxml.get_widget ("machine_combo")]
self.conf_widgets += [gxml.get_widget ("distribution_combo")]
self.conf_widgets += [gxml.get_widget ("image_combo")]
# Grab the status widgets
self.status_image = gxml.get_widget ("status_image")
self.status_label = gxml.get_widget ("status_label")
# Grab the refresh button and connect to the clicked signal
self.refresh_button = gxml.get_widget ("refresh_button")
self.refresh_button.connect ("clicked", self.refresh_button_clicked)
# Grab the location entry and connect to editable::changed
self.location_entry = gxml.get_widget ("location_entry")
self.location_entry.connect ("changed",
self.repository_entry_editable_changed)
# Grab the machine combo and hook onto the changed signal. This then
# allows us to populate the distro and image combos
self.machine_combo = gxml.get_widget ("machine_combo")
self.machine_combo.connect ("changed", self.machine_combo_changed)
# Setup the combo
cell = gtk.CellRendererText()
self.machine_combo.pack_start(cell, True)
self.machine_combo.add_attribute(cell, 'text', 0)
# Grab the distro and image combos. We need these to populate with
# models once the machine is chosen
self.distribution_combo = gxml.get_widget ("distribution_combo")
cell = gtk.CellRendererText()
self.distribution_combo.pack_start(cell, True)
self.distribution_combo.add_attribute(cell, 'text', 0)
self.image_combo = gxml.get_widget ("image_combo")
cell = gtk.CellRendererText()
self.image_combo.pack_start(cell, True)
self.image_combo.add_attribute(cell, 'text', 0)
# Put the default descriptive text in the status box
self.clear_status_message()
# Mark as non-configurable, this is just greys out the widgets the
# user can't yet use
self.configurable = False
self.set_configurable(False)
# Show the table
table.show_all ()
# The loader and some signals connected to it to update the status
# area
self.loader = MetaDataLoader()
self.loader.connect ("success", self.loader_success_cb)
self.loader.connect ("error", self.loader_error_cb)
def update_configuration (self):
""" A poorly named function but it updates the internal configuration
from the widgets. This can make that configuration concrete and can
thus be used for building """
# Extract the chosen machine from the combo
model = self.machine_combo.get_model()
active_iter = self.machine_combo.get_active_iter()
if (active_iter):
self.configuration.machine = model.get(active_iter, 0)[0]
# Extract the chosen distro from the combo
model = self.distribution_combo.get_model()
active_iter = self.distribution_combo.get_active_iter()
if (active_iter):
self.configuration.distro = model.get(active_iter, 0)[0]
# Extract the chosen image from the combo
model = self.image_combo.get_model()
active_iter = self.image_combo.get_active_iter()
if (active_iter):
self.configuration.image = model.get(active_iter, 0)[0]
# This function operates to pull events out from the event queue and then push
# them into the RunningBuild (which then drives the RunningBuild which then
# pushes through and updates the progress tree view.)
#
# TODO: Should be a method on the RunningBuild class
def event_handle_timeout (eventHandler, build):
# Consume as many messages as we can ...
event = eventHandler.getEvent()
while event:
build.handle_event (event)
event = eventHandler.getEvent()
return True
class MainWindow (gtk.Window):
# Callback that gets fired when the user hits a button in the
# BuildSetupDialog.
def build_dialog_box_response_cb (self, dialog, response_id):
conf = None
if (response_id == BuildSetupDialog.RESPONSE_BUILD):
dialog.update_configuration()
print dialog.configuration.machine, dialog.configuration.distro, \
dialog.configuration.image
conf = dialog.configuration
dialog.destroy()
if conf:
self.manager.do_build (conf)
def build_button_clicked_cb (self, button):
dialog = BuildSetupDialog ()
# For some unknown reason Dialog.run causes nice little deadlocks ... :-(
dialog.connect ("response", self.build_dialog_box_response_cb)
dialog.show()
def __init__ (self):
gtk.Window.__init__ (self)
# Pull in *just* the main vbox from the Glade XML data and then pack
# that inside the window
gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade",
root = "main_window_vbox")
vbox = gxml.get_widget ("main_window_vbox")
self.add (vbox)
# Create the tree views for the build manager view and the progress view
self.build_manager_view = BuildManagerTreeView()
self.running_build_view = RunningBuildTreeView()
# Grab the scrolled windows that we put the tree views into
self.results_scrolledwindow = gxml.get_widget ("results_scrolledwindow")
self.progress_scrolledwindow = gxml.get_widget ("progress_scrolledwindow")
# Put the tree views inside ...
self.results_scrolledwindow.add (self.build_manager_view)
self.progress_scrolledwindow.add (self.running_build_view)
# Hook up the build button...
self.build_button = gxml.get_widget ("main_toolbutton_build")
self.build_button.connect ("clicked", self.build_button_clicked_cb)
# I'm not very happy about the current ownership of the RunningBuild. I have
# my suspicions that this object should be held by the BuildManager since we
# care about the signals in the manager
def running_build_succeeded_cb (running_build, manager):
# Notify the manager that a build has succeeded. This is necessary as part
# of the 'hack' that we use for making the row in the model / view
# representing the ongoing build change into a row representing the
# completed build. Since we know only one build can be running a time then
# we can handle this.
# FIXME: Refactor all this so that the RunningBuild is owned by the
# BuildManager. It can then hook onto the signals directly and drive
# interesting things it cares about.
manager.notify_build_succeeded ()
print "build succeeded"
def running_build_failed_cb (running_build, manager):
# As above
print "build failed"
manager.notify_build_failed ()
def init (server, eventHandler):
# Initialise threading...
gobject.threads_init()
gtk.gdk.threads_init()
main_window = MainWindow ()
main_window.show_all ()
# Set up the build manager stuff in general
builds_dir = os.path.join (os.getcwd(), "results")
manager = BuildManager (server, builds_dir)
main_window.build_manager_view.set_model (manager.model)
# Do the running build setup
running_build = RunningBuild ()
main_window.running_build_view.set_model (running_build.model)
running_build.connect ("build-succeeded", running_build_succeeded_cb,
manager)
running_build.connect ("build-failed", running_build_failed_cb, manager)
# We need to save the manager into the MainWindow so that the toolbar
# button can use it.
# FIXME: Refactor ?
main_window.manager = manager
# Use a timeout function for probing the event queue to find out if we
# have a message waiting for us.
gobject.timeout_add (200,
event_handle_timeout,
eventHandler,
running_build)
gtk.main()

View File

@@ -1,125 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2007 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Use this class to fork off a thread to recieve event callbacks from the bitbake
server and queue them for the UI to process. This process must be used to avoid
client/server deadlocks.
"""
import socket, threading, pickle
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
class BBUIEventQueue:
def __init__(self, BBServer):
self.eventQueue = []
self.eventQueueLock = threading.Lock()
self.eventQueueNotify = threading.Event()
self.BBServer = BBServer
self.t = threading.Thread()
self.t.setDaemon(True)
self.t.run = self.startCallbackHandler
self.t.start()
def getEvent(self):
self.eventQueueLock.acquire()
if len(self.eventQueue) == 0:
self.eventQueueLock.release()
return None
item = self.eventQueue.pop(0)
if len(self.eventQueue) == 0:
self.eventQueueNotify.clear()
self.eventQueueLock.release()
return item
def waitEvent(self, delay):
self.eventQueueNotify.wait(delay)
return self.getEvent()
def queue_event(self, event):
self.eventQueueLock.acquire()
self.eventQueue.append(pickle.loads(event))
self.eventQueueNotify.set()
self.eventQueueLock.release()
def startCallbackHandler(self):
server = UIXMLRPCServer()
self.host, self.port = server.socket.getsockname()
server.register_function( self.system_quit, "event.quit" )
server.register_function( self.queue_event, "event.send" )
server.socket.settimeout(1)
self.EventHandle = self.BBServer.registerEventHandler(self.host, self.port)
self.server = server
while not server.quit:
server.handle_request()
server.server_close()
def system_quit( self ):
"""
Shut down the callback thread
"""
try:
self.BBServer.unregisterEventHandler(self.EventHandle)
except:
pass
self.server.quit = True
class UIXMLRPCServer (SimpleXMLRPCServer):
def __init__( self, interface = ("localhost", 0) ):
self.quit = False
SimpleXMLRPCServer.__init__( self,
interface,
requestHandler=SimpleXMLRPCRequestHandler,
logRequests=False, allow_none=True)
def get_request(self):
while not self.quit:
try:
sock, addr = self.socket.accept()
sock.settimeout(1)
return (sock, addr)
except socket.timeout:
pass
return (None,None)
def close_request(self, request):
if request is None:
return
SimpleXMLRPCServer.close_request(self, request)
def process_request(self, request, client_address):
if request is None:
return
SimpleXMLRPCServer.process_request(self, request, client_address)

View File

@@ -1,50 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2007 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
class BBUIHelper:
def __init__(self):
self.needUpdate = False
self.running_tasks = {}
self.failed_tasks = []
def eventHandler(self, event):
if isinstance(event, bb.build.TaskStarted):
self.running_tasks[event.pid] = { 'title' : "%s %s" % (event._package, event._task) }
self.needUpdate = True
if isinstance(event, bb.build.TaskSucceeded):
del self.running_tasks[event.pid]
self.needUpdate = True
if isinstance(event, bb.build.TaskFailed):
del self.running_tasks[event.pid]
self.failed_tasks.append( { 'title' : "%s %s" % (event._package, event._task)})
self.needUpdate = True
# Add runqueue event handling
#if isinstance(event, bb.runqueue.runQueueTaskCompleted):
# a = 1
#if isinstance(event, bb.runqueue.runQueueTaskStarted):
# a = 1
#if isinstance(event, bb.runqueue.runQueueTaskFailed):
# a = 1
#if isinstance(event, bb.runqueue.runQueueExitWait):
# a = 1
def getTasks(self):
self.needUpdate = False
return (self.running_tasks, self.failed_tasks)

View File

@@ -19,35 +19,32 @@ BitBake Utility Functions
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
separators = ".-"
digits = "0123456789"
ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
import re, fcntl, os, types, bb, string, stat, shutil
from commands import getstatusoutput
import re, fcntl, os
def explode_version(s):
r = []
alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
numeric_regexp = re.compile('^(\d+)(.*)$')
while (s != ''):
if s[0] in string.digits:
if s[0] in digits:
m = numeric_regexp.match(s)
r.append(int(m.group(1)))
s = m.group(2)
continue
if s[0] in string.letters:
if s[0] in ascii_letters:
m = alpha_regexp.match(s)
r.append(m.group(1))
s = m.group(2)
continue
r.append(s[0])
s = s[1:]
return r
def vercmp_part(a, b):
va = explode_version(a)
vb = explode_version(b)
sa = False
sb = False
while True:
if va == []:
ca = None
@@ -59,16 +56,6 @@ def vercmp_part(a, b):
cb = vb.pop(0)
if ca == None and cb == None:
return 0
if type(ca) is types.StringType:
sa = ca in separators
if type(cb) is types.StringType:
sb = cb in separators
if sa and not sb:
return -1
if not sa and sb:
return 1
if ca > cb:
return 1
if ca < cb:
@@ -164,8 +151,8 @@ def better_compile(text, file, realfile):
# split the text into lines again
body = text.split('\n')
bb.msg.error(bb.msg.domain.Util, "Error in compiling python function in: ", realfile)
bb.msg.error(bb.msg.domain.Util, "The lines leading to this error were:")
bb.msg.error(bb.msg.domain.Util, "Error in compiling: ", realfile)
bb.msg.error(bb.msg.domain.Util, "The lines resulting into this error were:")
bb.msg.error(bb.msg.domain.Util, "\t%d:%s:'%s'" % (e.lineno, e.__class__.__name__, body[e.lineno-1]))
_print_trace(body, e.lineno)
@@ -189,7 +176,7 @@ def better_exec(code, context, text, realfile):
raise
# print the Header of the Error Message
bb.msg.error(bb.msg.domain.Util, "Error in executing python function in: %s" % realfile)
bb.msg.error(bb.msg.domain.Util, "Error in executing: ", realfile)
bb.msg.error(bb.msg.domain.Util, "Exception:%s Message:%s" % (t,value) )
# let us find the line number now
@@ -248,12 +235,6 @@ def lockfile(name):
Use the file fn as a lock file, return when the lock has been acquired.
Returns a variable to pass to unlockfile().
"""
path = os.path.dirname(name)
if not os.path.isdir(path):
import bb, sys
bb.msg.error(bb.msg.domain.Util, "Error, lockfile path does not exist!: %s" % path)
sys.exit(1)
while True:
# If we leave the lockfiles lying around there is no problem
# but we should clean up after ourselves. This gives potential
@@ -265,18 +246,15 @@ def lockfile(name):
# This implementation is unfair since the last person to request the
# lock is the most likely to win it.
try:
lf = open(name, "a+")
fcntl.flock(lf.fileno(), fcntl.LOCK_EX)
statinfo = os.fstat(lf.fileno())
if os.path.exists(lf.name):
statinfo2 = os.stat(lf.name)
if statinfo.st_ino == statinfo2.st_ino:
return lf
# File no longer exists or changed, retry
lf.close
except Exception, e:
continue
lf = open(name, "a+")
fcntl.flock(lf.fileno(), fcntl.LOCK_EX)
statinfo = os.fstat(lf.fileno())
if os.path.exists(lf.name):
statinfo2 = os.stat(lf.name)
if statinfo.st_ino == statinfo2.st_ino:
return lf
# File no longer exists or changed, retry
lf.close
def unlockfile(lf):
"""
@@ -318,92 +296,6 @@ def sha256_file(filename):
s.update(line)
return s.hexdigest()
def preserved_envvars_list():
return [
'BBPATH',
'BB_PRESERVE_ENV',
'BB_ENV_WHITELIST',
'BB_ENV_EXTRAWHITE',
'COLORTERM',
'DBUS_SESSION_BUS_ADDRESS',
'DESKTOP_SESSION',
'DESKTOP_STARTUP_ID',
'DISPLAY',
'GNOME_KEYRING_PID',
'GNOME_KEYRING_SOCKET',
'GPG_AGENT_INFO',
'GTK_RC_FILES',
'HOME',
'LANG',
'LOGNAME',
'PATH',
'PWD',
'SESSION_MANAGER',
'SHELL',
'SSH_AUTH_SOCK',
'TERM',
'USER',
'USERNAME',
'_',
'XAUTHORITY',
'XDG_DATA_DIRS',
'XDG_SESSION_COOKIE',
]
def filter_environment(good_vars):
"""
Create a pristine environment for bitbake. This will remove variables that
are not known and may influence the build in a negative way.
"""
import bb
removed_vars = []
for key in os.environ.keys():
if key in good_vars:
continue
removed_vars.append(key)
os.unsetenv(key)
del os.environ[key]
if len(removed_vars):
bb.debug(1, "Removed the following variables from the environment:", ",".join(removed_vars))
return removed_vars
def clean_environment():
"""
Clean up any spurious environment variables. This will remove any
variables the user hasn't chose to preserve.
"""
if 'BB_PRESERVE_ENV' not in os.environ:
if 'BB_ENV_WHITELIST' in os.environ:
good_vars = os.environ['BB_ENV_WHITELIST'].split()
else:
good_vars = preserved_envvars_list()
if 'BB_ENV_EXTRAWHITE' in os.environ:
good_vars.extend(os.environ['BB_ENV_EXTRAWHITE'].split())
filter_environment(good_vars)
def empty_environment():
"""
Remove all variables from the environment.
"""
for s in os.environ.keys():
os.unsetenv(s)
del os.environ[s]
def build_environment(d):
"""
Build an environment from all exported variables.
"""
import bb
for var in bb.data.keys(d):
export = bb.data.getVarFlag(var, "export", d)
if export:
os.environ[var] = bb.data.getVar(var, d, True) or ""
def prunedir(topdir):
# Delete everything reachable from the directory named in 'topdir'.
# CAUTION: This is dangerous!
@@ -411,206 +303,5 @@ def prunedir(topdir):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
if os.path.islink(os.path.join(root, name)):
os.remove(os.path.join(root, name))
else:
os.rmdir(os.path.join(root, name))
os.rmdir(os.path.join(root, name))
os.rmdir(topdir)
#
# Could also use return re.compile("(%s)" % "|".join(map(re.escape, suffixes))).sub(lambda mo: "", var)
# but thats possibly insane and suffixes is probably going to be small
#
def prune_suffix(var, suffixes, d):
# See if var ends with any of the suffixes listed and
# remove it if found
for suffix in suffixes:
if var.endswith(suffix):
return var.replace(suffix, "")
return var
def mkdirhier(dir):
"""Create a directory like 'mkdir -p', but does not complain if
directory already exists like os.makedirs
"""
bb.debug(3, "mkdirhier(%s)" % dir)
try:
os.makedirs(dir)
bb.debug(2, "created " + dir)
except OSError, e:
if e.errno != 17: raise e
import stat
def movefile(src,dest,newmtime=None,sstat=None):
"""Moves a file from src to dest, preserving all permissions and
attributes; mtime will be preserved even when moving across
filesystems. Returns true on success and false on failure. Move is
atomic.
"""
#print "movefile("+src+","+dest+","+str(newmtime)+","+str(sstat)+")"
try:
if not sstat:
sstat=os.lstat(src)
except Exception, e:
print "movefile: Stating source file failed...", e
return None
destexists=1
try:
dstat=os.lstat(dest)
except:
dstat=os.lstat(os.path.dirname(dest))
destexists=0
if destexists:
if stat.S_ISLNK(dstat[stat.ST_MODE]):
try:
os.unlink(dest)
destexists=0
except Exception, e:
pass
if stat.S_ISLNK(sstat[stat.ST_MODE]):
try:
target=os.readlink(src)
if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
os.unlink(dest)
os.symlink(target,dest)
#os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
os.unlink(src)
return os.lstat(dest)
except Exception, e:
print "movefile: failed to properly create symlink:", dest, "->", target, e
return None
renamefailed=1
if sstat[stat.ST_DEV]==dstat[stat.ST_DEV]:
try:
ret=os.rename(src,dest)
renamefailed=0
except Exception, e:
import errno
if e[0]!=errno.EXDEV:
# Some random error.
print "movefile: Failed to move", src, "to", dest, e
return None
# Invalid cross-device-link 'bind' mounted or actually Cross-Device
if renamefailed:
didcopy=0
if stat.S_ISREG(sstat[stat.ST_MODE]):
try: # For safety copy then move it over.
shutil.copyfile(src,dest+"#new")
os.rename(dest+"#new",dest)
didcopy=1
except Exception, e:
print 'movefile: copy', src, '->', dest, 'failed.', e
return None
else:
#we don't yet handle special, so we need to fall back to /bin/mv
a=getstatusoutput("/bin/mv -f "+"'"+src+"' '"+dest+"'")
if a[0]!=0:
print "movefile: Failed to move special file:" + src + "' to '" + dest + "'", a
return None # failure
try:
if didcopy:
os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
os.unlink(src)
except Exception, e:
print "movefile: Failed to chown/chmod/unlink", dest, e
return None
if newmtime:
os.utime(dest,(newmtime,newmtime))
else:
os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
newmtime=sstat[stat.ST_MTIME]
return newmtime
def copyfile(src,dest,newmtime=None,sstat=None):
"""
Copies a file from src to dest, preserving all permissions and
attributes; mtime will be preserved even when moving across
filesystems. Returns true on success and false on failure.
"""
#print "copyfile("+src+","+dest+","+str(newmtime)+","+str(sstat)+")"
try:
if not sstat:
sstat=os.lstat(src)
except Exception, e:
print "copyfile: Stating source file failed...", e
return False
destexists=1
try:
dstat=os.lstat(dest)
except:
dstat=os.lstat(os.path.dirname(dest))
destexists=0
if destexists:
if stat.S_ISLNK(dstat[stat.ST_MODE]):
try:
os.unlink(dest)
destexists=0
except Exception, e:
pass
if stat.S_ISLNK(sstat[stat.ST_MODE]):
try:
target=os.readlink(src)
if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
os.unlink(dest)
os.symlink(target,dest)
#os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
return os.lstat(dest)
except Exception, e:
print "copyfile: failed to properly create symlink:", dest, "->", target, e
return False
if stat.S_ISREG(sstat[stat.ST_MODE]):
try: # For safety copy then move it over.
shutil.copyfile(src,dest+"#new")
os.rename(dest+"#new",dest)
except Exception, e:
print 'copyfile: copy', src, '->', dest, 'failed.', e
return False
else:
#we don't yet handle special, so we need to fall back to /bin/mv
a=getstatusoutput("/bin/cp -f "+"'"+src+"' '"+dest+"'")
if a[0]!=0:
print "copyfile: Failed to copy special file:" + src + "' to '" + dest + "'", a
return False # failure
try:
os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
except Exception, e:
print "copyfile: Failed to chown/chmod/unlink", dest, e
return False
if newmtime:
os.utime(dest,(newmtime,newmtime))
else:
os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
newmtime=sstat[stat.ST_MTIME]
return newmtime
def which(path, item, direction = 0):
"""
Locate a file in a PATH
"""
paths = (path or "").split(':')
if direction != 0:
paths.reverse()
for p in paths:
next = os.path.join(p, item)
if os.path.exists(next):
return next
return ""

View File

@@ -1,9 +0,0 @@
# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
LCONF_VERSION = "1"
BBFILES ?= ""
BBLAYERS = " \
${OEROOT}/meta \
${OEROOT}/meta-moblin \
"

View File

@@ -1,10 +1,6 @@
# CONF_VERSION is increased each time build/conf/ changes incompatibly
CONF_VERSION = "1"
# Where to cache the files Poky downloads
DL_DIR ?= "${OEROOT}/sources"
# Where to cache Poky's built staging output
PSTAGE_DIR ?= "${OEROOT}/pstage"
BBFILES = "${OEROOT}/meta/packages/*/*.bb"
# Uncomment and set to allow bitbake to execute multiple tasks at once.
# For a quadcore, BB_NUMBER_THREADS = "4", PARALLEL_MAKE = "-j 4" would
@@ -14,11 +10,10 @@ PSTAGE_DIR ?= "${OEROOT}/pstage"
# PARALLEL_MAKE = "-j 4"
# The machine to target
MACHINE ?= "qemux86"
MACHINE ?= "qemuarm"
# Other supported machines
#MACHINE ?= "qemuarm"
#MACHINE ?= "netbook"
#MACHINE ?= "qemux86"
#MACHINE ?= "c7x0"
#MACHINE ?= "akita"
#MACHINE ?= "spitz"
@@ -41,20 +36,17 @@ DISTRO ?= "poky"
# Poky has various extra metadata collections (openmoko, extras).
# To enable these, uncomment all (or some of) the following lines:
# BBFILES = "\
# ${OEROOT}/meta/packages/*/*.bb \
# ${OEROOT}/meta-extras/packages/*/*.bb \
# ${OEROOT}/meta-openmoko/packages/*/*.bb \
# ${OEROOT}/meta-moblin/packages/*/*.bb \
# ${OEROOT}/meta/packages/*/*.bb
# ${OEROOT}/meta-extras/packages/*/*.bb
# ${OEROOT}/meta-openmoko/packages/*/*.bb
# "
# BBFILE_COLLECTIONS = "normal extras openmoko moblin"
# BBFILE_COLLECTIONS = "normal extras openmoko"
# BBFILE_PATTERN_normal = "^${OEROOT}/meta/"
# BBFILE_PATTERN_extras = "^${OEROOT}/meta-extras/"
# BBFILE_PATTERN_openmoko = "^${OEROOT}/meta-openmoko/"
# BBFILE_PATTERN_moblin = "^${OEROOT}/meta-moblin/"
# BBFILE_PRIORITY_normal = "5"
# BBFILE_PRIORITY_extras = "5"
# BBFILE_PRIORITY_openmoko = "5"
# BBFILE_PRIORITY_moblin = "5"
BBMASK = ""
@@ -134,6 +126,11 @@ TMPDIR = "${OEROOT}/build/tmp"
# Uncomment this if you want BitBake to emit the log if a build fails.
BBINCLUDELOGS = "yes"
# Specifies a location to search for pre-generated tarballs when fetching
# a cvs:// or svn:// URI. Uncomment this, if you do not want to pull directly
# from CVS or Subversion
SRC_TARBALL_STASH = "http://pokylinux.org/sources/"
# Set this if you wish to make pkgconfig libraries from your system available
# for native builds. Combined with extra ASSUME_PROVIDEDs this can allow
# native builds of applications like oprofileui-native (unsupported feature).
@@ -141,13 +138,3 @@ BBINCLUDELOGS = "yes"
#ASSUME_PROVIDED += "gtk+-native libglade-native"
ENABLE_BINARY_LOCALE_GENERATION = "1"
# The architecture to build SDK items for, by setting this you can build SDK
# packages for architectures other than the host i.e. building i586 packages
# on an x86_64 host.
# Supported values are i586 and x86_64
#SDKMACHINE="i586"
# Poky can try and fetch packaged-staging packages from a http, https or ftp
# mirror. Set this variable to the root of a pstage directory on a server.
#PSTAGE_MIRROR ?= "http://someserver.tld/share/pstage"

View File

@@ -2,39 +2,15 @@
# local.conf covers user settings, site.conf covers site specific information
# such as proxy server addresses and optionally any shared download location
#
# SITE_CONF_VERSION is increased each time build/conf/site.conf
# changes incompatibly
SCONF_VERSION = "1"
# Uncomment to cause CVS to use the proxy host specified
#CVS_PROXY_HOST = "proxy.example.com"
#CVS_PROXY_PORT = "81"
# For svn, you need to create ~/.subversion/servers containing:
#[global]
#http-proxy-host = proxy.example.com
#http-proxy-port = 81
#
# Uncomment to cause git to use the proxy host specificed
# although this only works for http
# Uncomment to cause git to use the proxy host specificed
#GIT_PROXY_HOST = "proxy.example.com"
#GIT_PROXY_PORT = "81"
#export GIT_PROXY_COMMAND = "${OEROOT}/scripts/poky-git-proxy-command"
# GIT_PROXY_IGNORE_* lines define hosts which do not require a proxy to access
#GIT_CORE_CONFIG = "Yes"
#GIT_PROXY_IGNORE_1 = "host.server.com"
#GIT_PROXY_IGNORE_2 = "another.server.com"
# If SOCKS is available run the following command to comple a simple transport
# gcc scripts/poky-git-proxy-socks.c -o poky-git-proxy-socks
# and then share that binary somewhere in PATH, then use the following settings
#GIT_PROXY_HOST = "proxy.example.com"
#GIT_PROXY_PORT = "81"
#export GIT_PROXY_COMMAND = "${OEROOT}/scripts/poky-git-proxy-socks-command"
# Uncomment this to use a shared download directory
#DL_DIR = "/some/shared/download/directory/"
#DL_DIR = "/some/shared/download/directory/"

View File

@@ -1,27 +1,20 @@
all: html pdf tarball
all: html pdf
pdf:
./poky-doc-tools/poky-docbook-to-pdf poky-handbook.xml
./poky-doc-tools/poky-docbook-to-pdf bsp-guide.xml
poky-docbook-to-pdf poky-handbook.xml
# -- old way --
# dblatex poky-handbook.xml
XSLTOPTS = --stringparam html.stylesheet style.css \
--stringparam chapter.autolabel 1 \
--stringparam appendix.autolabel 1 \
--stringparam section.autolabel 1 \
--xinclude
##
# These URI should be rewritten by your distribution's xml catalog to
# match your localy installed XSL stylesheets.
XSL_BASE_URI = http://docbook.sourceforge.net/release/xsl/current
XSL_XHTML_URI = $(XSL_BASE_URI)/xhtml/docbook.xsl
html:
# See http://www.sagehill.net/docbookxsl/HtmlOutput.html
xsltproc $(XSLTOPTS) -o poky-handbook.html $(XSL_XHTML_URI) poky-handbook.xml
xsltproc $(XSLTOPTS) -o bsp-guide.html $(XSL_XHTML_URI) bsp-guide.xml
xsltproc --stringparam html.stylesheet style.css \
--stringparam chapter.autolabel 1 \
--stringparam appendix.autolabel 1 \
--stringparam section.autolabel 1 \
-o poky-handbook.html \
--xinclude /usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl \
poky-handbook.xml
# -- old way --
# xmlto xhtml-nochunks poky-handbook.xml
@@ -30,9 +23,3 @@ tarball: html
validate:
xmllint --postvalid --xinclude --noout poky-handbook.xml
OUTPUTS = poky-handbook.tgz poky-handbook.html poky-handbook.pdf bsp-guide.pdf
SOURCES = *.png *.xml *.css *.svg
publish:
scp -r $(OUTPUTS) $(SOURCES) o-hand.com:/srv/www/pokylinux.org/doc/

View File

@@ -1,61 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<book id='poky-handbook' lang='en'
xmlns:xi="http://www.w3.org/2003/XInclude"
xmlns="http://docbook.org/ns/docbook"
>
<bookinfo>
<mediaobject>
<imageobject>
<imagedata fileref='common/poky-handbook.png'
format='SVG'
align='center' scalefit='1' width='100%'/>
</imageobject>
</mediaobject>
<title>Board Support Package (BSP) Developers Guide</title>
<authorgroup>
<author>
<firstname>Richard</firstname> <surname>Purdie</surname>
<affiliation>
<orgname>Intel Corporation</orgname>
</affiliation>
<email>richard@linux.intel.com</email>
</author>
</authorgroup>
<revhistory>
<revision>
<revnumber>0.4</revnumber>
<date>26 May 2010</date>
<revremark>Alpha Draft</revremark>
</revision>
</revhistory>
<copyright>
<year>2010</year>
<holder>Intel Corporation</holder>
</copyright>
<legalnotice>
<para>
Permission is granted to copy, distribute and/or modify this document under
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-nc-sa/2.0/uk/">Creative Commons Attribution-Non-Commercial-Share Alike 2.0 UK: England &amp; Wales</ulink> as published by Creative Commons.
</para>
</legalnotice>
</bookinfo>
<xi:include href="bsp.xml"/>
<index id='index'>
<title>Index</title>
</index>
</book>
<!--
vim: expandtab tw=80 ts=4
-->

View File

@@ -1,287 +0,0 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<chapter id='bsp'>
<title>Board Support Packages (BSP) - Developers Guide</title>
<para>
A Board Support Package (BSP) is a collection of information which together
defines how to support a particular hardware device, set of devices or
hardware platform. It will include information about the hardware features
present on the device, kernel configuration information along with any
additional hardware drivers required and also any additional software
components required in addition to a generic Linux software stack for both
essential and optional platform features.
</para>
<para>
The intend of this document is to define a structure for these components
so that BSPs follow a commonly understood layout allowing them to be
provided in a common way that everyone understands. It also allows end
users to become familiar with one common format and encourages standardisation
of software support of hardware.
</para>
<para>
The proposed format does have elements that are specific to the Poky and
OpenEmbedded build systems. It is intended that this information can be
used by other systems besides Poky/OpenEmbedded and that it will be simple
to extract information and convert to other formats if required. The format
descriped can be directly accepted as a layer by Poky using its standard
layers mechanism but its important to recognise that the BSP captures all
the hardware specific details in one place in a standard format which is
useful for any person wishing to use the hardware platform regardless of
the build system in use.
</para>
<para>
The BSP specification does not include a build system or other tooling,
it is concerned with the hardware specific components only. At the end
distribution point the BSP may be shipped combined with a build system
and other tools but it is important to maintain the distinction that these
are separate components which may just be combined in certain end products.
</para>
<section id='bsp-filelayout'>
<title>Example Filesystem Layout</title>
<para>
The BSP consists of a file structure inside a base directory, meta-bsp in this example where "bsp" is a placeholder for the machine or platform name. Examples of some files that it could contain are:
</para>
<para>
<programlisting>
meta-bsp/
meta-bsp/binary/zImage
meta-bsp/binary/poky-image-minimal.directdisk
meta-bsp/conf/layer.conf
meta-bsp/conf/machine/*.conf
meta-bsp/conf/machine/include/tune-*.inc
meta-bsp/packages/bootloader/bootloader_0.1.bb
meta-bsp/packages/linux/linux-bsp-2.6.50/*.patch
meta-bsp/packages/linux/linux-bsp-2.6.50/defconfig-bsp
meta-bsp/packages/linux/linux-bsp_2.6.50.bb
meta-bsp/packages/modem/modem-driver_0.1.bb
meta-bsp/packages/modem/modem-daemon_0.1.bb
meta-bsp/packages/image-creator/image-creator-native_0.1.bb
meta-bsp/prebuilds/
</programlisting>
</para>
<para>
The following sections detail what these files and directories could contain.
</para>
</section>
<section id='bsp-filelayout-binary'>
<title>Prebuilt User Binaries (meta-bsp/binary/*)</title>
<para>
This optional area cotains useful prebuilt kernels and userspace filesystem
images appropriate to the target system. Users could use these to get a system
running and quickly get started on development tasks. The exact types of binaries
present will be highly hardware dependent but a README file should be present
explaining how to use them with the target hardware. If prebuilt binaries are
present, source code to meet licensing requirements must also be provided in
some form.
</para>
</section>
<section id='bsp-filelayout-layer'>
<title>Layer Configuration (meta-bsp/conf/layer.conf)</title>
<para>
This file identifies the structure as a Poky layer. This file identifies the
contents of the layer and how contains information about how Poky should use
it. In general it will most likely be a standard boilerplate file consisting of:
</para>
<para>
<programlisting>
# We have a conf directory, add to BBPATH
BBPATH := "${BBPATH}${LAYERDIR}"
# We have a packages directory, add to BBFILES
BBFILES := "${BBFILES} ${LAYERDIR}/packages/*/*.bb"
BBFILE_COLLECTIONS += "meta-bsp"
BBFILE_PATTERN_meta-bsp := "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-bsp = "5"
</programlisting>
</para>
<para>
which simply makes bitbake aware of the packages and conf directories.
</para>
<para>
This file is required for recognition of the BSP by Poky.
</para>
</section>
<section id='bsp-filelayout-machine'>
<title>Hardware Configuration Options (meta-bsp/conf/machine/*.conf)</title>
<para>
The machine files bind together all the information contained elsewhere
in the BSP into a format that Poky/OpenEmbedded can understand it in. If
the BSP supports multiple machines, multiple machine configuration files
can be present. These filenames correspond to the values users set the
MACHINE variable to.
</para>
<para>
These files would define things like which kernel package to use
(PREFERRED_PROVIDER of virtual/kernel), which hardware drivers to
include in different types of images, any special software components
that are needed, any bootloader information and also any special image
format requirements.
</para>
<para>
At least one machine file is required for a Poky BSP layer but more than one may be present.
</para>
</section>
<section id='bsp-filelayout-tune'>
<title>Hardware Optimisation Options (meta-bsp/conf/machine/include/tune-*.inc)</title>
<para>
These are shared hardware "tuning" definitions and are commonly used to
pass specific optimisation flags to the compiler. An example is
tune-atom.inc:
</para>
<para>
<programlisting>
BASE_PACKAGE_ARCH = "core2"
TARGET_CC_ARCH = "-m32 -march=core2 -msse3 -mtune=generic -mfpmath=sse"
</programlisting>
</para>
<para>
which defines a new package architecture called "core2" and uses the
optimisation flags specified which are carefully chosen to give best
performance on atom cpus.
</para>
<para>
The tune file would be included by the machine definition and can be
contained in the BSP or reference one from the standard core set of
files included with Poky itself.
</para>
<para>
These files are optional for a Poky BSP layer.
</para>
</section>
<section id='bsp-filelayout-kernel'>
<title>Linux Kernel Configuration (meta-bsp/packages/linux/*)</title>
<para>
These files make up the definition of a kernel to use with this
hardware. In this case its a complete self contained kernel with its own
configuration and patches but kernels can be shared between many
machines as well. Taking some specific example files:
</para>
<para>
<programlisting>
meta-bsp/packages/linux/linux-bsp_2.6.50.bb
</programlisting>
</para>
<para>
which is the core kernel recipe which firstly details where to get the kernel
source from. All standard source code locations are supported so this could
be a release tarball, some git repository or source included in
the directory within the BSP itself. It then contains information about which
patches to apply and how to configure and build it. It can reuse the main
Poky kernel build class meaning the definitions here can remain very simple.
</para>
<para>
<programlisting>
linux-bsp-2.6.50/*.patch
</programlisting>
</para>
<para>
which are patches which may be applied against the base kernel, wherever
that may have been obtained from.
</para>
<para>
<programlisting>
meta-bsp/packages/linux/linux-bsp-2.6.50/defconfig-bsp
</programlisting>
</para>
<para>
which is the configuration information to use to configure the kernel.
</para>
<para>
Examples of kernel recipes are available in Poky itself. These files are
optional since a kernel from Poky itself could be selected although it
would be unusual not to have a kernel configuration.
</para>
</section>
<section id='bsp-filelayout-packages'>
<title>Other Software (meta-bsp/packages/*)</title>
<para>
This area includes other pieces of software which the hardware may need for best
operation. These are just examples of the kind of things that may be
encountered. The are standard .bb file recipes in the usual Poky format
so for examples, see standard Poky recipes. The source can be included directly,
referred to in source control systems or release tarballs of external software projects.
</para>
<para>
<programlisting>
meta-bsp/packages/bootloader/bootloader_0.1.bb
</programlisting>
</para>
<para>
Some kind of bootloader recipe which may be used to generate a new
bootloader binary. Sometimes these are included in the final image
format and needed to reflash hardware.
</para>
<para>
<programlisting>
meta-bsp/packages/modem/modem-driver_0.1.bb
meta-bsp/packages/modem/modem-daemon_0.1.bb
</programlisting>
</para>
<para>
These are examples of a hardware driver and also a hardware daemon which
may need to be included in images to make the hardware useful. "modem"
is one example but there may be other components needed like firmware.
</para>
<para>
<programlisting>
meta-bsp/packages/image-creator/image-creator-native_0.1.bb
</programlisting>
</para>
<para>
Sometimes the device will need an image in a very specific format for
its update mechanism to accept and reflash with it. Recipes to build the
tools needed to do this can be included with the BSP.
</para>
<para>
These files only need be provided if the platform requires them.
</para>
</section>
<section id='bsp-filelayout-prebuilds'>
<title>Prebuild Data (meta-bsp/prebuilds/*)</title>
<para>
The location can contains a precompiled representation of the source code
contained elsewhere in the BSP layer. It can be processed and used by
Poky to provide much faster build times assuming a compatible configuration is used.
</para>
<para>
These files are optional.
</para>
</section>
</chapter>

30
handbook/contactus.xml Normal file
View File

@@ -0,0 +1,30 @@
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<appendix id='contact'>
<title>OpenedHand Contact Information</title>
<literallayout>
OpenedHand Ltd
Unit R, Homesdale Business Center
216-218 Homesdale Rd
Bromley, BR1 2QZ
England
+44 (0) 208 819 6559
info@openedhand.com</literallayout>
<!-- Fop messes this up so we do like above
<address>
OpenedHand Ltd
Unit R, Homesdale Business Center
<street>216-218 Homesdale Rd</street>
<city>Bromley</city>, <postcode>BR1 2QZ</postcode>
<country>England</country>
<phone> +44 (0) 208 819 6559</phone>
<email>info@openedhand.com</email>
</address>
-->
</appendix>
<!--
vim: expandtab tw=80 ts=4
-->

View File

@@ -59,16 +59,13 @@
</screenshot>
-->
<para>
To use the plugin, a toolchain and SDK built by Poky is required along with Anjuta it's development
headers and the Anjuta plugin. The Poky Anjuta plugin is available to download as a tarball at the
<ulink url='http://labs.o-hand.com/sources/anjuta-plugin-sdk/'>OpenedHand labs</ulink> page or
directly from the Poky Git repository located at git://git.pokylinux.org/anjuta-poky; a web interface
to the repository can be accessed at <ulink url='http://git.pokylinux.org/cgit.cgi/anjuta-poky/'/>.
</para>
<para>
See the README file contained in the project for more information on dependencies and building
the plugin. It's recommended you enable the experimental gdb integration by passing configure the
--enable-gdb-integration switch.
To use the plugin, a toolchain and SDK built by Poky is required along with Anjuta and the Anjuta
plugin. The Poky Anjuta plugin is available from the OpenedHand SVN repository located at
http://svn.o-hand.com/repos/anjuta-poky/trunk/anjuta-plugin-sdk/; a web interface
to the repository can be accessed at <ulink url='http://svn.o-hand.com/view/anjuta-poky/'/>.
See the README file contained in the project for more information
about the dependencies and how to get them along with details of
the prebuilt packages.
</para>
<section id="platdev-appdev-external-anjuta-setup">
@@ -499,7 +496,7 @@ $ bitbake matchbox-desktop -c devshell
the gdb-cross package so for example you would run:
<programlisting>bitbake gdb-cross</programlisting>
Once built, the cross gdb binary can be found at
<programlisting>tmp/sysroots/&lt;host-arch&lt;/usr/bin/&lt;target-abi&gt;-gdb </programlisting>
<programlisting>tmp/cross/bin/&lt;target-abi&gt;-gdb </programlisting>
</para>
</section>
@@ -535,17 +532,17 @@ $ bitbake matchbox-desktop -c devshell
Firstly you want to install the <emphasis>foo</emphasis> package to tmp/rootfs
by doing:
</para>
<programlisting>tmp/sysroots/i686-linux/usr/bin/opkg-cl -f \
<programlisting>tmp/staging/i686-linux/usr/bin/opkg-cl -f \
tmp/work/&lt;target-abi&gt;/poky-image-sato-1.0-r0/temp/opkg.conf -o \
tmp/rootfs/ update</programlisting>
<para>
then,
</para>
<programlisting>tmp/sysroots/i686-linux/usr/bin/opkg-cl -f \
<programlisting>tmp/staging/i686-linux/usr/bin/opkg-cl -f \
tmp/work/&lt;target-abi&gt;/poky-image-sato-1.0-r0/temp/opkg.conf \
-o tmp/rootfs install foo
tmp/sysroots/i686-linux/usr/bin/opkg-cl -f \
tmp/staging/i686-linux/usr/bin/opkg-cl -f \
tmp/work/&lt;target-abi&gt;/poky-image-sato-1.0-r0/temp/opkg.conf \
-o tmp/rootfs install foo-dbg</programlisting>
<para>

View File

@@ -26,15 +26,7 @@
</para>
<para>
Before writing a recipe from scratch it is often useful to check
someone else hasn't written one already. OpenEmbedded is a good place
to look as it has a wider scope and hence a wider range of packages.
Poky aims to be compatible with OpenEmbedded so most recipes should
just work in Poky.
</para>
<para>
For new packages, the simplest way to add a recipe is to base it on a similar
The simplest way to add a new package is to base it on a similar
pre-existing recipe. There are some examples below of how to add
standard types of packages:
</para>
@@ -56,7 +48,6 @@
DESCRIPTION = "Simple helloworld application"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://COPYING;md5=ae764cfda68da96df20af9fbf9fe49bd"
SRC_URI = "file://helloworld.c"
@@ -100,7 +91,6 @@ do_install() {
DESCRIPTION = "GNU Helloworld application"
SECTION = "examples"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=ae764cfda68da96df20af9fbf9fe49bd"
SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.bz2"
@@ -141,7 +131,6 @@ SECTION = "base"
DEPENDS = "zlib"
HOMEPAGE = "http://www.linux-mtd.infradead.org/"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=ae764cfda68da96df20af9fbf9fe49bd"
SRC_URI = "ftp://ftp.infradead.org/pub/mtd-utils/mtd-utils-${PV}.tar.gz"
@@ -177,8 +166,8 @@ require xorg-lib-common.inc
DESCRIPTION = "X11 Pixmap library"
LICENSE = "X-BSD"
LIC_FILES_CHKSUM = "file://COPYING;md5=ae764cfda68da96df20af9fbf9fe49bd"
DEPENDS += "libxext"
PE = "1"
XORG_PN = "libXpm"
@@ -227,7 +216,7 @@ pkg_postinst_PACKAGENAME () {
<para>
Sometimes it is necessary that the execution of a post-installation
script is delayed until the first boot, because the script
needs to be executed on the device itself. To delay script execution
needs to be executed the device itself. To delay script execution
until boot time, the post-installation function should have the
following structure:
</para>
@@ -280,7 +269,7 @@ inherit poky-image
<para>
By creating a custom image, a developer has total control
over the contents of the image. It is important to use
over the contents of the image. It is important use
the correct names of packages in the <glossterm><link
linkend='var-IMAGE_INSTALL'>IMAGE_INSTALL</link></glossterm> variable.
The names must be in
@@ -307,11 +296,11 @@ IMAGE_INSTALL += "strace"
<title>Customising Images through custom tasks</title>
<para>
For complex custom images, the best approach is to create a custom
task package which is then used to build the image (or images). A good
For for complex custom images, the best approach is to create a custom
task package which is them used to build the image (or images). A good
example of a tasks package is <filename>meta/packages/tasks/task-poky.bb
</filename>. The <glossterm><link linkend='var-PACKAGES'>PACKAGES</link></glossterm>
variable lists the task packages to build (along with the complementary
variable lists the task packages to build (along with the complimentary
-dbg and -dev packages). For each package added,
<glossterm><link linkend='var-PACKAGES'>RDEPENDS</link></glossterm> and
<glossterm><link linkend='var-PACKAGES'>RRECOMMENDS</link></glossterm>
@@ -518,101 +507,57 @@ bitbake poky-image-sato
</para>
<para>
Poky supports the idea of <link
linkend='usingpoky-changes-layers'>"layers"</link> which when used
linkend='usingpoky-changes-collections'>"collections"</link> which when used
properly can massively ease future upgrades and allow segregation
between the Poky core and a given developer's changes. Some other advice on
managing changes to Poky is also given in the following section.
</para>
<section id="usingpoky-changes-layers">
<title>Bitbake Layers</title>
<section id="usingpoky-changes-collections">
<title>Bitbake Collections</title>
<para>
<para>
Often, people want to extend Poky either through adding packages
or overriding files contained within Poky to add their own
functionality. Bitbake has a powerful mechanism called
layers which provides a way to handle this extension in a fully
supported and non-invasive fashion.
</para>
<para>
The Poky tree includes two additional layers which demonstrate
this functionality, meta-moblin and meta-extras.
The meta-extras repostory is not enabled by default but enabling
it is as easy as adding the layers path to the BBLAYERS variable in
your bblayers.conf, this is how all layers are enabled in Poky builds:
</para>
<para>
<literallayout class='monospaced'>LCONF_VERSION = "1"
BBFILES ?= ""
BBLAYERS = " \
${OEROOT}/meta \
${OEROOT}/meta-moblin \
${OEROOT}/meta-extras \
"
</literallayout>
</para>
<para>
Bitbake parses the conf/layer.conf of each of the layers in BBLAYERS
to add the layers packages, classes and configuration to Poky.
To create your own layer, independent of the main Poky repository,
you need only create a directory with a conf/layer.conf file and
add the directory to your bblayers.conf.
</para>
<para>
The meta-extras layer.conf demonstrates the required syntax:
<literallayout class='monospaced'># We have a conf and classes directory, add to BBPATH
BBPATH := "${BBPATH}${LAYERDIR}"
# We have a packages directory, add to BBFILES
BBFILES := "${BBFILES} ${LAYERDIR}/packages/*/*.bb"
BBFILE_COLLECTIONS += "extras"
BBFILE_PATTERN_extras := "^${LAYERDIR}/"
BBFILE_PRIORITY_extras = "5"
require conf/distro/include/poky-extras-src-revisions.inc
</literallayout>
</para>
<para>
As can be seen, the layers recipes are added to BBFILES. The
BBFILE_COLLECTIONS variable is then appended to with the
layer name. The BBFILE_PATTERN variable is immediately expanded
with a regular expression used to match files from BBFILES into
a particular layer, in this case by using the base pathname.
The BBFILE_PRIORITY variable then assigns different
priorities to the files in different layers. This is useful
in situations where the same package might appear in multiple
layers and allows you to choose which layer should 'win'.
Note the use of LAYERDIR with the immediate expansion operator.
LAYERDIR expands to the directory of the current layer and
requires use of the immediate expansion operator so that Bitbake
does not lazily expand the variable when it's parsing a
different directory.
collections which provide a way to handle this which is fully
supported and actively encouraged within Poky.
</para>
<para>
Extra bbclasses and configuration are added to the BBPATH
environment variable. In this case, the first file with the
matching name found in BBPATH is the one that is used, just
like the PATH variable for binaries. It is therefore recommended
that you use unique bbclass and configuration file names in your
custom layer.
In the standard tree, meta-extras is an example of how you can
do this. As standard the data in meta-extras is not used on a
Poky build but local.conf.sample shows how to enable it:
</para>
<para>
The recommended approach for custom layers is to store them in a
git repository of the format meta-prvt-XXXX and have this repository
cloned alongside the other meta directories in the Poky tree.
This way you can keep your Poky tree and it's configuration entirely
inside OEROOT.
<literallayout class='monospaced'>
BBFILES := "${OEROOT}/meta/packages/*/*.bb ${OEROOT}/meta-extras/packages/*/*.bb"
BBFILE_COLLECTIONS = "normal extras"
BBFILE_PATTERN_normal = "^${OEROOT}/meta/"
BBFILE_PATTERN_extras = "^${OEROOT}/meta-extras/"
BBFILE_PRIORITY_normal = "5"
BBFILE_PRIORITY_extras = "5"</literallayout>
</para>
<para>
As can be seen, the extra recipes are added to BBFILES. The
BBFILE_COLLECTIONS variable is then set to contain a list of
collection names. The BBFILE_PATTERN variables are regular
expressions used to match files from BBFILES into a particular
collection in this case by using the base pathname.
The BBFILE_PRIORITY variable then assigns the different
priorities to the files in different collections. This is useful
in situations where the same package might appear in both
repositories and allows you to choose which collection should
'win'.
</para>
<para>
This works well for recipes. For bbclasses and configuration
files, you can use the BBPATH environment variable. In this
case, the first file with the matching name found in BBPATH is
the one that is used, just like the PATH variable for binaries.
</para>
</section>
<section id='usingpoky-changes-commits'>
<title>Committing Changes</title>
@@ -620,8 +565,8 @@ require conf/distro/include/poky-extras-src-revisions.inc
Modifications to Poky are often managed under some kind of source
revision control system. The policy for committing to such systems
is important as some simple policy can significantly improve
usability. The tips below are based on the policy followed for the
Poky core.
usability. The tips below are based on the policy that OpenedHand
uses for commits to Poky.
</para>
<para>
@@ -678,69 +623,6 @@ require conf/distro/include/poky-extras-src-revisions.inc
upgradable packages in all cases.
</para>
</section>
<section id='usingpoky-changes-collaborate'>
<title>Using Poky in a Team Environment</title>
<para>
It may not be immediately clear how Poky can work in a team environment,
or scale to a large team of developers. The specifics of any situation
will determine the best solution and poky offers immense flexibility in
that aspect but there are some practises that experience has shown to work
well.
</para>
<para>
The core component of any development effort with Poky is often an
automated build testing framework and image generation process. This
can be used to check that the metadata is buildable, highlight when
commits break the builds and provide up to date images allowing people
to test the end result and use them as a base platform for further
development. Experience shows that buildbot is a good fit for this role
and that it works well to configure it to make two types of build -
incremental builds and 'from scratch'/full builds. The incremental builds
can be tied to a commit hook which triggers them each time a commit is
made to the metadata and are a useful acid test of whether a given commit
breaks the build in some serious way. They catch lots of simple errors
and whilst they won't catch 100% of failures, the tests are fast so
developers can get feedback on their changes quickly. The full builds
are builds that build everything from the ground up and test everything.
They usually happen at preset times such as at night when the machine
load isn't high from the incremental builds.
</para>
<para>
Most teams have pieces of software undergoing active development. It is of
significant benefit to put these under control of a source control system
compatible with Poky such as git or svn. The autobuilder can then be set to
pull the latest revisions of these packages so the latest commits get tested
by the builds allowing any issues to be highlighted quickly. Poky easily
supports configurations where there is both a stable known good revision
and a floating revision to test. Poky can also only take changes from specific
source control branches giving another way it can be used to track/test only
specified changes.
</para>
<para>
Perhaps the hardest part of setting this up is the policy that surrounds
the different source control systems, be them software projects or the Poky
metadata itself. The circumstances will be different in each case but this is
one of Poky's advantages - the system itself doesn't force any particular policy
unlike a lot of build systems, allowing the best policy to be chosen for the
circumstances.
</para>
</section>
<section id='usingpoky-changes-updatingimages'>
<title>Updating Existing Images</title>
<para>
Often, rather than reflashing a new image you might wish to install updated
packages into an existing running system. This can be done by sharing the <filename class="directory">tmp/deploy/ipk/</filename> directory through a web server and then on the device, changing <filename>/etc/opkg/base-feeds.conf</filename> to point at this server, for example by adding:
</para>
<literallayout class='monospaced'>
src/gz all http://www.mysite.com/somedir/deploy/ipk/all
src/gz armv7a http://www.mysite.com/somedir/deploy/ipk/armv7a
src/gz beagleboard http://www.mysite.com/somedir/deploy/ipk/beagleboard</literallayout>
</section>
</section>
<section id='usingpoky-modifing-packages'>
@@ -827,7 +709,7 @@ quilt refresh
Poky metadata and added into <glossterm><link
linkend='var-SRC_URI'>SRC_URI</link></glossterm> of a recipe:
<programlisting>
SRC_URI += "file://NAME-OF-PATCH.patch"
SRC_URI += "file://NAME-OF-PATCH.patch;patch=1"
</programlisting>
This also requires a bump of <glossterm><link
@@ -836,112 +718,9 @@ SRC_URI += "file://NAME-OF-PATCH.patch"
</section>
</section>
<section id='usingpoky-configuring-LIC_FILES_CHKSUM'>
<title>Configuring the LIC_FILES_CHKSUM variable</title>
<para>
The changes in the license text inside source code files is tracked
using the LIC_FILES_CHKSUM metadata variable.
</para>
</section>
<section id='usingpoky-specifying-LIC_FILES_CHKSUM'>
<title>Specifying the LIC_FILES_CHKSUM variable </title>
<programlisting>
LIC_FILES_CHKSUM = "file://COPYING; md5=xxxx \
file://licfile1.txt; beginline=5; endline=29;md5=yyyy \
file://licfile2.txt; endline=50;md5=zzzz \
..."
</programlisting>
</section>
<section id='usingpoky-LIC_FILES_CHKSUM-explanation-of-syntax'>
<title>Explanation of syntax</title>
<para>
This parameter lists all the important files containing the text
of licenses for the
source code. It is also possible to specify on which line the license text
starts and on which line it ends within that file using the "beginline" and
"endline" parameters. If the "beginline" parameter is not specified then license
text begins from the 1st line is assumed. Similarly if "endline" parameter is
not specified then the license text ends at the last line in the file is
assumed. So if a file contains only licensing information, then there is no need
to specify "beginline" and "endline" parameters.
</para>
<para>
The "md5" parameter stores the md5 checksum of the license text. So if
the license text changes in any way from a file, then it's md5 sum will differ and will not
match with the previously stored md5 checksum. This mismatch will trigger build
failure, notifying developer about the license text md5 mismatch, and allowing
the developer to review the license text changes. Also note that if md5 checksum
is not matched while building, the correct md5 checksum is printed in the build
log.
</para>
<para>
There is no limit on how many files can be specified on this parameter. But generally every
project would need specifying of just one or two files for license tracking.
Many projects would have a "COPYING" file which will store all the
license information for all the source code files. If the "COPYING" file
is valid then tracking only that file would be enough.
</para>
<tip>
<para>
1. If you specify empty or invalid "md5" parameter; then while building
the package, bitbake will give md5 not matched error, and also show the correct
"md5" parameter value in the build log
</para>
<para>
2. If the whole file contains only license text, then there is no need to
specify "beginline" and "endline" parameters.
</para>
</tip>
</section>
</section>
<section id='usingpoky-configuring-DISTRO_PN_ALIAS'>
<title>Configuring the DISTRO_PN_ALIAS variable</title>
<para>
Sometimes the names of the same packages are different in different
linux distributions; and that can becomes an issue for the distro_check
task to check if the given recipe package exists in other linux distros.
This issue is avoided by defining per distro recipe name alias:
DISTRO_PN_ALIAS
</para>
<section id='usingpoky-specifying-DISTRO_PN_ALIAS'>
<title>Specifying the DISTRO_PN_ALIAS variable </title>
<programlisting>
DISTRO_PN_ALIAS = "distro1=package_name_alias1; distro2=package_name_alias2 \
distro3=package_name_alias3; \
..."
</programlisting>
<para>
Look at the meta/packages/xorg-app/xset_1.0.4.bb recipe file for an example.
</para>
<tip>
<para>
The current code can check if the src package for a recipe exists in the latest
releases of these distributions automatically.
</para>
<programlisting>
Fedora, OpenSuSE, Debian, Ubuntu, Mandriva
</programlisting>
<para>
For example, this command will generate a report, listing which linux distros include the
sources for each of the poky recipe.
</para>
<programlisting>
bitbake world -f -c distro_check
</programlisting>
<para>
The results will be stored in the build/tmp/log/distro_check-${DATETIME}.results file.
</para>
</tip>
</section>
</section>
</chapter>
<!--
vim: expandtab tw=80 ts=4
-->

View File

@@ -135,18 +135,6 @@
</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>
I see the error 'chmod: XXXXX new permissions are r-xrwxrwx, not r-xr-xr-x'. What's wrong?
</para>
</question>
<answer>
<para>
You're probably running the build on an NTFS filesystem. Use a sane one like ext2/3/4 instead!
</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>
@@ -254,58 +242,8 @@
</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>
I'm using Ubuntu Intrepid and am seeing build failures. Whats wrong?
</para>
</question>
<answer>
<para>
In Intrepid, Ubuntu turned on by default normally optional compile-time security features
and warnings. There are more details at <ulink
url='https://wiki.ubuntu.com/CompilerFlags'>https://wiki.ubuntu.com/CompilerFlags</ulink>.
You can work around this problem by disabling those options by adding " -Wno-format-security -U_FORTIFY_SOURCE"
to the BUILD_CPPFLAGS variable in conf/bitbake.conf.
</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>
Whats the difference between foo and foo-native?
</para>
</question>
<answer>
<para>
The *-native targets are designed to run on the system the buil is running on. These are usually tools that are needed to assist the build in some way such as quilt-native which is used to apply patches. The non-native version is the one that would run on the target device.
</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>
I'm seeing random build failures. Help?!
</para>
</question>
<answer>
<para>
If the same build is failing in totally different and random ways the most likely explaination is that either the hardware you're running it on has some problem or if you are running it under virtualisation, the virtualisation probably has bugs. Poky processes a massive amount of data causing lots of network, disk and cpu activity and is senstive to even single bit failure in any of these areas. Totally random failures have always been traced back to hardware or virtualisation issues.
</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>
What do we need to ship for licence complience?
</para>
</question>
<answer>
<para>
This is a difficult question and you need to consult your lawyer for the answer for your specific case. Its worth bearing in mind that for GPL complience there needs to be enough information shipped to allow someone else to rebuild the same end result as you are shipping. This means sharing the source code, any patches applied to it but also any configuration information about how that package was configured and built.
</para>
</answer>
</qandaentry>
</qandaset>
</appendix>
<!--

View File

@@ -58,7 +58,7 @@
<screenshot>
<mediaobject>
<imageobject>
<imagedata fileref="screenshots/ss-sato.png" format="PNG" align='center' scalefit='1' width="100%" contentdepth="100%"/>
<imagedata fileref="screenshots/ss-sato.png" format="PNG"/>
</imageobject>
<caption>
<para>The Sato Desktop - A screenshot from a machine running a Poky built image</para>
@@ -69,7 +69,7 @@
<para>
Poky has a growing open source community and is also backed up by commercial organisations including <ulink url="http://www.intel.com/">Intel Corporation</ulink>.
Poky has a growing open source community backed up by commercial support provided by the principle developer and maintainer of Poky, <ulink url="http://o-hand.com/">OpenedHand Ltd</ulink>.
</para>
</section>
@@ -117,7 +117,7 @@
<para>build-essential</para>
</listitem>
<listitem>
<para>python (version 2.6 or later)</para>
<para>python</para>
</listitem>
<listitem>
<para>diffstat</para>
@@ -153,8 +153,8 @@
<ulink url='http://debian.o-hand.com'/>
for instructions on doing this) and then run <command>
"apt-get install qemu poky-depends poky-scripts"</command> which will
automatically install all these dependencies. Virtualisation images with
Poky and all dependencies can also easily be built if required.
automatically install all these dependencies. OpenedHand can also provide
VMware images with Poky and all dependencies pre-installed if required.
</para>
<para>
@@ -172,17 +172,17 @@
<para>
If you want to try Poky, you can do so in a few commands. The example below
checks out the Poky source code, sets up a build environment, builds an
image and then runs that image under the QEMU emulator in x86 system emulation mode:
image and then runs that image under the QEMU emulator in ARM system emulation mode:
</para>
<para>
<literallayout class='monospaced'>
$ wget http://pokylinux.org/releases/poky-green-3.3.tar.bz2
$ tar xjvf poky-green-3.3.tar.bz2
$ cd green-3.3/
$ wget http://pokylinux.org/releases/pinky-3.1.tar.gz
$ tar zxvf pinky-3.1.tar.gz
$ cd pinky-3.1/
$ source poky-init-build-env
$ bitbake poky-image-sato
$ runqemu qemux86
$ runqemu qemuarm
</literallayout>
</para>
@@ -289,7 +289,7 @@ $ poky-qemu &lt;kernel&gt; &lt;image&gt;
We make nightly builds of Poky for testing purposes and to make the
latest developments available. The output from these builds is available
at <ulink url='http://pokylinux.org/autobuild/'/>
where the numbers increase for each subsequent build and can be used to reference it.
where the numbers represent the svn revision the builds were made from.
</para>
<para>
@@ -308,13 +308,13 @@ $ poky-qemu &lt;kernel&gt; &lt;image&gt;
<title>Development Checkouts</title>
<para>
Poky is available from our GIT repository located at
git://git.pokylinux.org/poky.git; a web interface to the repository
can be accessed at <ulink url='http://git.pokylinux.org/'/>.
Poky is available from our SVN repository located at
http://svn.o-hand.com/repos/poky/trunk; a web interface to the repository
can be accessed at <ulink url='http://svn.o-hand.com/view/poky/'/>.
</para>
<para>
The 'master' is where the deveopment work takes place and you should use this if you're
'trunk' is where the deveopment work takes place and you should use this if you're
after to work with the latest cutting edge developments. It is possible trunk
can suffer temporary periods of instability while new features are developed and
if this is undesireable we recommend using one of the release branches.

View File

@@ -7,13 +7,7 @@ bin_SCRIPTS = poky-docbook-to-pdf
edit = sed \
-e 's,@datadir\@,$(pkgdatadir),g' \
-e 's,@prefix\@,$(prefix),g' \
-e 's,@version\@,@VERSION@,g'
##
# These URI should be rewritten by your distribution's xml catalog to
# match your localy installed XSL stylesheets.
XSL_BASE_URI="http://docbook.sourceforge.net/release/xsl/current"
XSL_TEMPLATE_URI = $(XSL_BASE_URI)/template/titlepage.xsl
-e 's,@version\@,@VERSION@,g'
poky-docbook-to-pdf: poky-docbook-to-pdf.in
rm -f poky-docbook-to-pdf

View File

@@ -1,7 +1,7 @@
poky-doc-tools
==============
Simple tools to wrap fop to create Poky branded PDF's from docbook sources.
Simple tools to wrap fop to create oh branded PDF's from docbook sources.
(based on OH doc tools)
Dependencies
@@ -9,10 +9,15 @@ Dependencies
Sun Java, make sure the java in your path is the *sun* java.
xlstproc, nwalsh style sheets, fop
xlstproc, nwalsh style sheets.
FOP, installed - see http://www.sagehill.net/docbookxsl/InstallingAnFO.html.
Updated to work with (fop > 0.95)
Also a 'fop' binary, eg I have;
% cat ~/bin/fop
#!/bin/sh
java org.apache.fop.apps.Fop "$@"

View File

@@ -1,3 +1,3 @@
#! /bin/sh
autoreconf -v --install || exit 1
./configure "$@"
./configure --enable-maintainer-mode --enable-debug "$@"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,58 +1,33 @@
<fop version="1.0">
<configuration>
<entry>
<!--
Set the baseDir so common/openedhand.svg references in plans still
work ok. Note, relative file references to current dir should still work.
-->
<key>baseDir</key>
<value>@datadir@</value>
</entry>
<fonts>
<font metrics-file="@datadir@/common/VeraMono.xml"
kerning="yes"
embed-file="@datadir@/common/VeraMono.ttf">
<font-triplet name="veramono" style="normal" weight="normal"/>
</font>
<!-- Strict user configuration -->
<strict-configuration>true</strict-configuration>
<font metrics-file="@datadir@/common/VeraMoBd.xml"
kerning="yes"
embed-file="@datadir@/common/VeraMoBd.ttf">
<font-triplet name="veramono" style="normal" weight="bold"/>
</font>
<!-- Strict FO validation -->
<strict-validation>true</strict-validation>
<!--
Set the baseDir so common/openedhand.svg references in plans still
work ok. Note, relative file references to current dir should still work.
-->
<base>@datadir@</base>
<font-base>@datadir@/common</font-base>
<!-- Source resolution in dpi (dots/pixels per inch) for determining the
size of pixels in SVG and bitmap images, default: 72dpi -->
<!-- <source-resolution>72</source-resolution> -->
<!-- Target resolution in dpi (dots/pixels per inch) for specifying the
target resolution for generated bitmaps, default: 72dpi -->
<!-- <target-resolution>72</target-resolution> -->
<!-- default page-height and page-width, in case
value is specified as auto -->
<default-page-settings height="11in" width="8.26in"/>
<!-- <use-cache>false</use-cache> -->
<renderers>
<renderer mime="application/pdf">
<fonts>
<font metrics-file="VeraMono.xml"
kerning="yes"
embed-url="VeraMono.ttf">
<font-triplet name="veramono" style="normal" weight="normal"/>
</font>
<font metrics-file="VeraMoBd.xml"
kerning="yes"
embed-url="VeraMoBd.ttf">
<font-triplet name="veramono" style="normal" weight="bold"/>
</font>
<font metrics-file="Vera.xml"
kerning="yes"
embed-url="Vera.ttf">
<font-triplet name="verasans" style="normal" weight="normal"/>
<font-triplet name="verasans" style="normal" weight="bold"/>
<font-triplet name="verasans" style="italic" weight="normal"/>
<font-triplet name="verasans" style="italic" weight="bold"/>
</font>
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>
<font metrics-file="@datadir@/common/Vera.xml"
kerning="yes"
embed-file="@datadir@/common/Vera.ttf">
<font-triplet name="verasans" style="normal" weight="normal"/>
<font-triplet name="verasans" style="normal" weight="bold"/>
<font-triplet name="verasans" style="italic" weight="normal"/>
<font-triplet name="verasans" style="italic" weight="bold"/>
</font>
</fonts>
</configuration>

View File

@@ -1,7 +1,7 @@
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl" />
<xsl:import href="file:///usr/share/xml/docbook/stylesheet/nwalsh/fo/docbook.xsl"/>
<!-- check project-plan.sh for how this is generated, needed to tweak
the cover page
@@ -54,7 +54,7 @@
<!-- general settings -->
<xsl:param name="fop1.extensions" select="1"></xsl:param>
<xsl:param name="fop.extensions" select="1"></xsl:param>
<xsl:param name="paper.type" select="'A4'"></xsl:param>
<xsl:param name="section.autolabel" select="1"></xsl:param>
<xsl:param name="body.font.family" select="'verasans'"></xsl:param>

View File

@@ -18,14 +18,9 @@ BASENAME=`basename $1 .xml` || exit 1
FO="$BASENAME.fo"
PDF="$BASENAME.pdf"
##
# These URI should be rewritten by your distribution's xml catalog to
# match your localy installed XSL stylesheets.
XSL_BASE_URI="http://docbook.sourceforge.net/release/xsl/current"
xsltproc -o /tmp/titlepage.xsl \
--xinclude \
$XSL_BASE_URI/template/titlepage.xsl \
/usr/share/xml/docbook/stylesheet/nwalsh/template/titlepage.xsl \
@datadir@/common/titlepage.templates.xml || exit 1
xsltproc --xinclude \

View File

@@ -11,7 +11,7 @@
<imageobject>
<imagedata fileref='common/poky-handbook.png'
format='SVG'
align='center' scalefit='1' width='100%'/>
align='center'/>
</imageobject>
</mediaobject>
@@ -22,37 +22,47 @@
<author>
<firstname>Richard</firstname> <surname>Purdie</surname>
<affiliation>
<orgname>Intel Corporation</orgname>
<orgname>OpenedHand Ltd</orgname>
</affiliation>
<email>richard@linux.intel.com</email>
<email>richard@openedhand.com</email>
</author>
<author>
<firstname>Tomas</firstname> <surname>Frydrych</surname>
<affiliation>
<orgname>Intel Corporation</orgname>
<orgname>OpenedHand Ltd</orgname>
</affiliation>
<email>tf@openedhand.com</email>
</author>
<author>
<firstname>Marcin</firstname> <surname>Juszkiewicz</surname>
<affiliation>
<orgname>OpenedHand Ltd</orgname>
</affiliation>
<email>hrw@openedhand.com</email>
</author>
<author>
<firstname>Dodji</firstname> <surname>Seketeli</surname>
<affiliation>
<orgname>OpenedHand Ltd</orgname>
</affiliation>
<email>dodji@openedhand.com</email>
</author>
</authorgroup>
<revhistory>
<revision>
<revnumber>3.3.1</revnumber>
<date>8 July 2010</date>
<revremark>Poky Green Documentation</revremark>
<revnumber>3.1</revnumber>
<date>15 February 2008</date>
<revremark>Poky 3.1 (Pinky) Documentation Release</revremark>
</revision>
</revhistory>
<copyright>
<year>2007-2010</year>
<holder>Intel Corporation</holder>
<year>2007</year>
<year>2008</year>
<holder>OpenedHand Limited</holder>
</copyright>
<legalnotice>
@@ -70,8 +80,6 @@
<xi:include href="extendpoky.xml"/>
<xi:include href="bsp.xml"/>
<xi:include href="development.xml"/>
<xi:include href="ref-structure.xml"/>
@@ -92,6 +100,8 @@
<xi:include href="resources.xml"/>
<xi:include href="contactus.xml"/>
<index id='index'>
<title>Index</title>
</index>

View File

@@ -81,10 +81,9 @@
default this specifies the <filename class="directory">meta/packages/
</filename> directory within Poky, but other directories such as
<filename class="directory">meta-extras/</filename> can be included
too. Adding extra content to
<glossterm><link linkend='var-BBFILES'>BBFILES</link></glossterm> is best
acheived through the use of Bitbake
<link linkend='usingpoky-changes-layers'>"layers"</link>.
too. If multiple directories are specified a system referred to as
<link linkend='usingpoky-changes-collections'>"collections"</link> is used to
determine which files have priority.
</para>
<para>

View File

@@ -179,8 +179,8 @@ autotools_stage_all
<para>
During staging Bitbake installs such scripts into the <filename
class="directory">sysroots/</filename> directory. It also changes all
paths to point into the <filename class="directory">sysroots/</filename>
class="directory">staging/</filename> directory. It also changes all
paths to point into the <filename class="directory">staging/</filename>
directory so all builds which use the script will use the correct
directories for the cross compiling layout.
</para>
@@ -206,7 +206,7 @@ autotools_stage_all
<para>
During staging Bitbake installs pkg-config data into the <filename
class="directory">sysroots/</filename> directory. By making use of
class="directory">staging/</filename> directory. By making use of
sysroot functionality within pkgconfig this class no longer has to
manipulate the files.
</para>
@@ -266,20 +266,19 @@ autotools_stage_all
<title>Python extensions - <filename>distutils.bbclass</filename></title>
<para>
Recipes for Python extensions are simple - they usually only
require pointing to the source archive and inheriting the proper
bbclasses.
Building is split into two methods depending on the build method
used by the module authors.
Recipes for Python extensions are simple - usually needs only
pointing to source archive and inheriting of proper bbclass.
Building is split into two methods dependly on method used by
module authors.
</para>
<para>
Extensions which use autotools based build system require use
Extensions which use autotools based build system require using
of autotools and distutils-base bbclasses in their recipes.
</para>
<para>
Extensions which use distutils build system require use
Extensions which use distutils build system require using
of <filename>distutils.bbclass</filename> in their recipes.
</para>
@@ -301,12 +300,12 @@ autotools_stage_all
<title>Packaging - <filename>package*.bbclass</filename></title>
<para>
The packaging classes add support for generating packages from a builds
output. The core generic functionality is in
<filename>package.bbclass</filename>, code specific to particular package
types is contained in various sub classes such as
<filename>package_deb.bbclass</filename> and <filename>package_ipk.bbclass</filename>.
Most users will
The packaging classes add support for generating packages from the output
from builds. The core generic functionality is in
<filename>package.bbclass</filename>, code specific to particular package
types is contained in various sub classes such as
<filename>package_deb.bbclass</filename> and <filename>package_ipk.bbclass</filename>.
Most users will
want one or more of these classes and this is controlled by the <glossterm>
<link linkend='var-PACKAGE_CLASSES'>PACKAGE_CLASSES</link></glossterm>
variable. The first class listed in this variable will be used for image
@@ -320,15 +319,15 @@ autotools_stage_all
<title>Building kernels - <filename>kernel.bbclass</filename></title>
<para>
This class handles building of Linux kernels and the class contains code to know how to build both 2.4 and 2.6 kernel trees. All needed headers are
This class handle building of Linux kernels and the class contains code to know how to build both 2.4 and 2.6 kernel trees. All needed headers are
staged into <glossterm><link
linkend='var-STAGING_KERNEL_DIR'>STAGING_KERNEL_DIR</link></glossterm>
directory to allow building of out-of-tree modules using <filename>module.bbclass</filename>.
</para>
<para>
The means that each kerel module built is packaged separately and inter-module dependencies are
The means that each kerel module built is packaged separately and inter-modules dependencies are
created by parsing the <command>modinfo</command> output. If all modules are
required then installing the "kernel-modules" package will install all
required then installing "kernel-modules" package will install all
packages with modules and various other kernel packages such as "kernel-vmlinux" are also generated.
</para>
@@ -378,7 +377,7 @@ autotools_stage_all
packages generated by Poky. There are an ever increasing range of checks
this makes, checking for common problems which break builds/packages/images,
see the bbclass file for more information. Its usually up to distribution
policy to include this class (Poky does).
policy to include this class (Poky doesn't at the time of writing but plans
to soon).
</para>
</section>

View File

@@ -166,6 +166,15 @@
</para>
</section>
<section id='structure-build-tmp-cross'>
<title><filename class="directory">build/tmp/cross/</filename></title>
<para>
The cross compiler when generated is placed into this directory and those
beneath it.
</para>
</section>
<section id='structure-build-tmp-deploy'>
<title><filename class="directory">build/tmp/deploy/</filename></title>
@@ -207,11 +216,11 @@
</para>
</section>
<section id='structure-build-tmp-sysroots'>
<title><filename class="directory">build/tmp/sysroots/</filename></title>
<section id='structure-build-tmp-staging'>
<title><filename class="directory">build/tmp/staging/</filename></title>
<para>
Any package needing to share output with other packages does so within sysroots.
Any package needing to share output with other packages does so within staging.
This means it contains any shared header files and any shared libraries amongst
other data. It is subdivided by architecture so multiple builds can run within
the one build directory.

View File

@@ -84,13 +84,6 @@
</glossdef>
</glossentry>
<glossentry id='var-BPN'><glossterm>BPN</glossterm>
<glossdef>
<para>Bare name of package with any suffixes like -cross -native
removed. </para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id='var-glossary-c'><title>C</title>
@@ -223,19 +216,6 @@
</glossdef>
</glossentry>
<glossentry id='var-DISTRO_PN_ALIAS'><glossterm>DISTRO_PN_ALIAS</glossterm>
<glossdef>
<para>Alias names of the recipe in various Linux distributions. </para>
<para>See the "meta/package/xorg-app/xset_1.0.4.bb" file for an example</para>
<para>More information in
<link
linkend='usingpoky-configuring-DISTRO_PN_ALIAS'>
Configuring the DISTRO_PN_ALIAS variable section
</link>
</para>
</glossdef>
</glossentry>
<glossentry id='var-DISTRO_VERSION'><glossterm>DISTRO_VERSION</glossterm>
<glossdef>
<para>Version of distribution</para>
@@ -410,37 +390,11 @@
<glossdiv id='var-glossary-l'><title>L</title>
<glossentry id='var-LAYERDIR'><glossterm>LAYERDIR</glossterm>
<glossdef>
<para>When used inside a layer.conf gives the path of the
current layer. This variable requires immediate expansion
(see the Bitbake manual) as lazy expansion can result in
the expansion happening in the wrong directory and therefore
giving the wrong value.</para>
</glossdef>
</glossentry>
<glossentry id='var-LICENSE'><glossterm>LICENSE</glossterm>
<glossdef>
<para>List of package source licenses.</para>
</glossdef>
</glossentry>
<glossentry id='var-LIC_FILES_CHKSUM'><glossterm>LIC_FILES_CHKSUM</glossterm>
<glossdef>
<para>Checksums of the license text in the recipe source code.
</para>
<para>This variables tracks changes in license text of the source
code files. If the license text is changed it triggers the build
failure. Which gives developer an oppurtunity to review any
license changes</para>
<para> This is an optional variable now. And the plan is to make
it a required variable in the future </para>
<para>See the "meta/package/zlib/zlib_${PV}.bb" file for an example</para>
<para>More information in <link
linkend='usingpoky-configuring-LIC_FILES_CHKSUM'>
Configuring the LIC_FILES_CHKSUM variable section</link></para>
</glossdef>
</glossentry>
</glossdiv>
@@ -561,7 +515,7 @@
<glossentry id='var-PE'><glossterm>PE</glossterm>
<glossdef>
<para>
Epoch of the package. The default value is "0". The field is used
Epoch of the package. The default value is "1". The field is used
to make upgrades possible when the versioning scheme changes in
some backwards incompatible way.
</para>
@@ -632,7 +586,7 @@
output packages there would usually be an override attached
to this variable like RDEPENDS_${PN}-dev. Names in this field
should be as they are in <link linkend='var-PACKAGES'>PACKAGES
</link> namespace before any renaming of the output package
</link> namespave before any renaming of the output package
by classes like debian.bbclass.
</para>
</glossdef>

View File

@@ -127,9 +127,6 @@
<listitem>
<para><glossterm><link linkend='var-LICENSE'>LICENSE</link></glossterm></para>
</listitem>
<listitem>
<para><glossterm><link linkend='var-LIC_FILES_CHKSUM'>LIC_FILES_CHKSUM</link></glossterm></para>
</listitem>
<listitem>
<para><glossterm><link linkend='var-SECTION'>SECTION</link></glossterm></para>
</listitem>
@@ -187,10 +184,6 @@
<title>Recipe Variables - Extra Build Information</title>
<itemizedlist>
<listitem>
<para><glossterm><link
linkend='var-DISTRO_PN_ALIAS'>DISTRO_PN_ALIAS</link></glossterm></para>
</listitem>
<listitem>
<para><glossterm><link linkend='var-EXTRA_OECONF'>EXTRA_OECONF</link></glossterm></para>
</listitem>

View File

@@ -58,13 +58,8 @@ poky+subscribe &lt;at&gt; openedhand &lt;dot&gt; com
</para></listitem>
<listitem><para>
<ulink url='http://www.openedhand.com/'>OpenedHand</ulink> - The
original company behind Poky.
company behind Poky.
</para></listitem>
<listitem><para>
<ulink url='http://www.intel.com/'>Intel Corporation</ulink> - The
company who acquired OpenedHand in 2008.
</para></listitem>
<listitem><para>
<ulink url='http://www.openembedded.org/'>OpenEmbedded</ulink>
- The upstream generic embedded distribution Poky derives
@@ -91,51 +86,6 @@ poky+subscribe &lt;at&gt; openedhand &lt;dot&gt; com
</itemizedlist>
</section>
<section id='resources-contributions'>
<title>Contributions</title>
<para>
Contributions to Poky are very welcome. Patches should be sent to the Poky mailing list along with a Signed-off-by: line in the same style as the Linux kernel. Adding this line signifies the developer has agreed to the Developer's Certificate of Origin 1.1:
</para>
<programlisting>
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
</programlisting>
<para>
A Poky contributions tree (poky-contrib) exists for people to stage
contributions in, for regular contributors. If people desire such
access, please ask on the mailing list. Usually access will be given
to anyone with a proven track record of good patches.
</para>
</section>
</appendix>
<!--
vim: expandtab tw=80 ts=4

View File

@@ -64,8 +64,8 @@ h1 {
}
h2.subtitle {
margin: 0.10em 0em 3.0em 0em;
padding: 0em 0em 0em 0em;
margin: 0.10em 0 3.0em 0;
padding: 0 0 0 0;
font-size: 1.8em;
padding-left: 20%;
font-weight: normal;
@@ -83,7 +83,7 @@ h3.subtitle {
margin: 0em 0em 1em 0em;
padding: 0em 0em 0em 0em;
font-size: 142.14%;
text-align: right;
text-align : right;
}
h3 {
@@ -117,7 +117,7 @@ h6 {
.authorgroup {
background-color: transparent;
background-repeat: no-repeat;
padding-top: 256px;
padding-top: 256;
background-image: url("poky-beaver.png");
background-position: right top;
float: right;
@@ -129,8 +129,8 @@ h6 {
}
h3.author {
margin: 0em 0me 0em 0em;
padding: 0em 0em 0em 0em;
margin: 0 0 0 0;
padding: 0 0 0 0;
font-weight: normal;
font-size: 100%;
clear: both;
@@ -141,7 +141,7 @@ h3.author {
}
.titlepage hr {
width: 0em;
width: 0;
clear: both;
}
@@ -161,9 +161,9 @@ h3.author {
.list-of-tables p,
.list-of-figures p,
.list-of-examples p {
padding: 0em 0em 0em 0em;
padding: 0 0 0 0;
padding: 0em 0em 0.3em;
margin: 1.5em 0em 0em 0em;
margin: 1.5em 0 0 0;
}
.toc p b,
@@ -178,18 +178,18 @@ h3.author {
.list-of-tables dl,
.list-of-figures dl,
.list-of-examples dl {
margin: 0em 0em 0.5em 0em;
padding: 0em 0em 0em 0em;
margin: 0 0 0.5em 0;
padding: 0 0 0 0;
}
.toc dt {
margin: 0em 0em 0em 0em;
padding: 0em 0em 0em 0em;
margin: 0 0 0 0;
padding: 0 0 0 0;
}
.toc dd {
margin: 0em 0em 0em 2.6em;
padding: 0em 0em 0em 0em;
padding: 0 0 0 0;
}
div.glossary dl,
@@ -222,8 +222,8 @@ div.variablelist dl {
div.calloutlist table td {
padding: 0em 0em 0em 0em;
margin: 0em 0em 0em 0em;
padding: 0 0 0 0;
margin: 0 0 0 0;
}
div.calloutlist table td p {
@@ -236,12 +236,12 @@ div p.copyright {
}
div.legalnotice p.legalnotice-title {
margin-bottom: 0em;
margin-bottom: 0;
}
p {
line-height: 1.5em;
margin-top: 0em;
margin-top: 0;
}
@@ -264,11 +264,11 @@ img {
}
ul {
padding: 0em 0em 0em 1.5em;
padding: 0 0 0 1.5em;
}
ul li {
padding: 0em 0em 0em 0em;
padding: 0 0 0 0;
}
ul li p {
@@ -292,8 +292,8 @@ td {
}
p a[id] {
margin: 0px;
padding: 0px;
margin: 0;
padding: 0;
display: inline;
background-image: none;
}
@@ -304,7 +304,7 @@ a {
}
pre {
overflow: auto;
overflow : auto;
}
a:hover {
@@ -331,8 +331,8 @@ div.informaltable p.title b,
div.figure p.title b,
div.example p.title b,
div.table p.title b{
padding-top: 0em;
margin-top: 0em;
padding-top: 0;
margin-top: 0;
font-size: 100%;
font-weight: normal;
}
@@ -398,7 +398,7 @@ span.application {
.caution table th,
.note table th {
padding: 0.8em 0.0em 0.0em 0.0em;
margin : 0em 0em 0em 0em;
margin : 0 0 0 0;
}
.tip p,
@@ -418,7 +418,7 @@ span.application {
b.keycap,
.keycap {
padding: 0.09em 0.3em;
margin: 0em;
margin: 0;
}
.itemizedlist li {
@@ -433,8 +433,8 @@ b.keycap,
div.navheader, div.heading{
position: absolute;
left: 0em;
top: 0em;
left: 0;
top: 0;
width: 100%;
background-color: #cdf;
width: 100%;
@@ -461,16 +461,16 @@ div.navheader table th {
}
div.navheader table {
border-left: 0em;
border-right: 0em;
border-top: 0em;
border-left: 0;
border-right: 0;
border-top: 0;
width: 100%;
}
div.navfooter table {
border-left: 0em;
border-right: 0em;
border-bottom: 0em;
border-left: 0;
border-right: 0;
border-bottom: 0;
width: 100%;
}
@@ -506,13 +506,13 @@ div.navfooter hr {
.qandaset tr.question td p {
margin: 0em 0em 1em 0em;
padding: 0em 0em 0em 0em;
margin: 0 0 1em 0;
padding: 0 0 0 0;
}
.qandaset tr.answer td p {
margin: 0em 0em 1em 0em;
padding: 0em 0em 0em 0em;
margin: 0 0 1em 0;
padding: 0 0 0 0;
}
.answer td {
padding-bottom: 1.5em;
@@ -572,7 +572,7 @@ div.informalfigure,
div.informaltable,
div.informalexample,
div.example {
border: 1px solid;
border : 1px solid;
}
@@ -581,14 +581,14 @@ div.example {
.warning,
.caution,
.note {
border: 1px solid;
border : 1px solid;
}
.tip table th,
.warning table th,
.caution table th,
.note table th {
border-bottom: 1px solid;
border-bottom : 1px solid;
}
.question td {
@@ -640,7 +640,7 @@ h5,
h6,
h7,
h8 {
background-color: transparent;
background-color : transparent;
}
hr {
@@ -649,7 +649,7 @@ hr {
.tip, .warning, .caution, .note {
border-color: #aaa;
border-color : #aaa;
}
@@ -784,7 +784,7 @@ h1.title {
background-color: transparent;
background-image: url("poky-handbook.png");
background-repeat: no-repeat;
height: 256px;
height: 256;
text-indent: -9000px;
overflow:hidden;
}
@@ -793,7 +793,7 @@ h2.subtitle {
background-color: transparent;
text-indent: -9000px;
overflow:hidden;
width: 0px;
width: 0;
display: none;
}
@@ -864,7 +864,7 @@ body {
/ ****************************************/
/*
div.navfooter, div.footing{
-moz-opacity: 0.8em;
-moz-opacity: 0.8;
}
div.figure,
@@ -896,11 +896,11 @@ hr {
}
table {
border: 0em;
border: 0;
}
.photo {
float: right;
float:right;
margin-left: 1.5em;
margin-bottom: 1.5em;
margin-top: 0em;
@@ -911,7 +911,7 @@ table {
}
.seperator {
padding-top: 2em;
clear: both;
clear :both;
}
#validators {
@@ -939,8 +939,8 @@ table {
.tip h3,
.note h3 {
padding: 0em;
margin: 0em;
padding: 0;
margin: 0;
font-size: 2em;
font-weight: bold;
color: #fff;
@@ -950,4 +950,4 @@ table {
.note a {
color: #fff;
text-decoration: underline;
}
}

View File

@@ -27,7 +27,7 @@
and configuration data for machines, policy decisions, etc., which acts as
a glue and binds everything together. Bitbake knows how to combine multiple
data sources together, each data source being referred to as a <link
linkend='usingpoky-changes-layers'>'layer'</link>.
linkend='usingpoky-changes-collections'>'collection'</link>.
</para>
<para>
@@ -75,7 +75,7 @@
</para>
<para>
'package' can also be used to describe recipes but since the same
'package' can also used to describe recipes but since the same
word is used for the packaged output from Poky (i.e. .ipk or .deb
files), this document will avoid it.
</para>
@@ -114,7 +114,7 @@
<title>Running a Build</title>
<para>
First the Poky build environment needs to be set up using the following command:
First the Poky build environment needs to be setup using the following command:
</para>
<para>
<literallayout class='monospaced'>
@@ -122,7 +122,7 @@ $ source poky-init-build-env
</literallayout>
</para>
<para>
Once the Poky build environment is set up, a target can now be built using:
Once the Poky build environment is setup, a target can now be built using:
</para>
<para>
<literallayout class='monospaced'>
@@ -204,11 +204,11 @@ route add default gw 192.168.7.200 tap0
<para>
The second is to configure name resolution which is configured in the
<filename>/etc/resolv.conf</filename> file. The simplest solution is
to copy its content from the host machine.
to copy it's content from the host machine.
</para>
<para>
USB connections to devices can be set up and automated in a similar way.
USB connections to devices can be setup and automated in a similar way.
First add the following to
<filename>/etc/network/interfaces</filename>:
</para>
@@ -246,7 +246,7 @@ route add default gw 192.168.0.202 usb0
debugging practises such as comparing to the last
known working version and examining the changes, reapplying the
changes in steps to identify the one causing the problem etc. are
valid for Poky just like any other system. It's impossible to detail
valid for Poky just like any other system. Its impossible to detail
every possible potential failure here but there are some general
tips to aid debugging:
</para>
@@ -293,7 +293,7 @@ route add default gw 192.168.0.202 usb0
<para>
which would build matchbox-desktop, then recompile it. The
final command reruns all tasks after the compile (basically
the packaging tasks) since bitbake will notice that the
the packaging tasks) since bitbake will notice the the
compile has been rerun and hence the other tasks also need
to run again.
</para>

View File

@@ -1,6 +0,0 @@
SRCREV_pn-evince ??= "2437"
SRCDATE_maemo-mapper-nohildon ??= "20061114"
SRCREV_pn-libxosd ??= "627"
SRCREV_pn-matchbox-applet-light ??= "1548"
SRCREV_pn-matchbox-common ??= "1561"

View File

@@ -1,11 +0,0 @@
# We have a conf and classes directory, add to BBPATH
BBPATH := "${BBPATH}${LAYERDIR}"
# We have a packages directory, add to BBFILES
BBFILES := "${BBFILES} ${LAYERDIR}/packages/*/*.bb"
BBFILE_COLLECTIONS += "extras"
BBFILE_PATTERN_extras := "^${LAYERDIR}/"
BBFILE_PRIORITY_extras = "5"
require conf/distro/include/poky-extras-src-revisions.inc

View File

@@ -5,3 +5,7 @@ PR = "r1"
SRC_URI = "http://www.balabit.com/downloads/files/eventlog/0.2/${P}.tar.gz"
inherit autotools pkgconfig
do_stage () {
autotools_stage_all
}

View File

@@ -1,7 +1,7 @@
DESCRIPTION = "GPS Controlling Daemon"
LICENSE = "GPL"
SECTION = "x11"
DEPENDS = "glib-2.0 dbus bluez4 dbus-glib"
DEPENDS = "glib-2.0 dbus bluez-libs dbus-glib"
inherit autotools pkgconfig

View File

@@ -6,3 +6,9 @@ S = "${WORKDIR}/${PN}-${PV}"
inherit autotools binconfig
do_stage() {
install -d ${STAGING_INCDIR}/libol
install -m 0755 ${S}/src/.libs/libol.so.0.0.0 ${STAGING_LIBDIR}/
ln -fs ${STAGING_LIBDIR}/libol.so.0.0.0 ${STAGING_LIBDIR}/libol.so.0
install ${S}/src/*.h ${STAGING_INCDIR}/libol/
}

View File

@@ -13,6 +13,10 @@ S = "${WORKDIR}/current"
inherit autotools binconfig
do_stage() {
autotools_stage_all
}
PACKAGES =+ "${PN}-examples-dbg ${PN}-examples"
FILES_${PN}-examples = "${bindir}/osd_cat"
FILES_${PN}-examples-dbg += "${bindir}/.debug/"

View File

@@ -16,3 +16,8 @@ EXTRA_OECONF = " --enable-xpdf-headers \
#check for TARGET_FPU=soft and inform configure of the result so it can disable some floating points
require poppler-fpu.inc
EXTRA_OECONF += "${@get_poppler_fpu_setting(bb, d)}"
do_stage() {
autotools_stage_all
}

View File

@@ -1,29 +0,0 @@
Index: redland-1.0.8/raptor/configure.ac
===================================================================
--- redland-1.0.8.orig/raptor/configure.ac 2008-12-16 17:26:58.000000000 +0000
+++ redland-1.0.8/raptor/configure.ac 2008-12-16 17:27:41.000000000 +0000
@@ -279,23 +279,7 @@
if test $ac_cv_func_vsnprintf = yes; then
AC_MSG_CHECKING(vsnprintf has C99 compatible return value)
- AC_TRY_RUN([#include <stdarg.h>
-int is_c99(char *s, ...) {
- char buffer[32];
- va_list args;
- int r;
- va_start(args, s);
- r = vsnprintf(buffer, 5, s, args);
- va_end(args);
-
- return (r == 7);
-}
-
-int main(int argc, char* argv) {
- return is_c99("1234567");
-}], AC_MSG_RESULT(no),
- AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [vsnprint has C99 compatible return value])
- AC_MSG_RESULT(yes))
+ AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [vsnprint has C99 compatible return value])
fi
need_libm=no

Some files were not shown because too many files have changed in this diff Show More